Fix SQL insert statement to properly quote column names in monthly aggregates
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2026-02-18 11:19:44 +11:00
parent e4d73ee294
commit 9419103709
2 changed files with 48 additions and 5 deletions

View File

@@ -274,8 +274,8 @@ func ColumnExists(ctx context.Context, dbConn *sqlx.DB, tableName string, column
err := getLog(ctx, dbConn, &count, ` err := getLog(ctx, dbConn, &count, `
SELECT COUNT(1) SELECT COUNT(1)
FROM information_schema.columns FROM information_schema.columns
WHERE table_name = $1 AND column_name = $2 WHERE table_schema = 'public' AND table_name = $1 AND LOWER(column_name) = LOWER($2)
`, tableName, strings.ToLower(columnName)) `, tableName, columnName)
if err != nil { if err != nil {
return false, err return false, err
} }
@@ -3149,7 +3149,7 @@ INSERT INTO %s (
) )
SELECT SELECT
"InventoryId", "Name", "Vcenter", "VmId", "EventKey", "CloudId", "InventoryId", "Name", "Vcenter", "VmId", "EventKey", "CloudId",
COALESCE(NULLIF("CreationTime", 0), MIN(NULLIF("CreationTime", 0)), 0) AS "CreationTime", COALESCE(MIN(NULLIF("CreationTime", 0)), 0) AS "CreationTime",
NULLIF(MAX(NULLIF("DeletionTime", 0)), 0) AS "DeletionTime", NULLIF(MAX(NULLIF("DeletionTime", 0)), 0) AS "DeletionTime",
MAX("ResourcePool") AS "ResourcePool", MAX("ResourcePool") AS "ResourcePool",
"Datacenter", "Cluster", "Folder", "Datacenter", "Cluster", "Folder",
@@ -3201,7 +3201,8 @@ CROSS JOIN totals
GROUP BY GROUP BY
"InventoryId", "Name", "Vcenter", "VmId", "EventKey", "CloudId", "InventoryId", "Name", "Vcenter", "VmId", "EventKey", "CloudId",
"Datacenter", "Cluster", "Folder", "Datacenter", "Cluster", "Folder",
"IsTemplate", "SrmPlaceholder", "VmUuid"; "IsTemplate", "SrmPlaceholder", "VmUuid",
totals.total_samples;
`, unionQuery, tableName) `, unionQuery, tableName)
return insert, nil return insert, nil
} }
@@ -3294,6 +3295,44 @@ func EnsureSummaryTable(ctx context.Context, dbConn *sqlx.DB, tableName string)
if _, err := execLog(ctx, dbConn, ddl); err != nil { if _, err := execLog(ctx, dbConn, ddl); err != nil {
return err return err
} }
requiredColumns := []ColumnDef{
{Name: "InventoryId", Type: "BIGINT"},
{Name: "Name", Type: "TEXT"},
{Name: "Vcenter", Type: "TEXT"},
{Name: "VmId", Type: "TEXT"},
{Name: "EventKey", Type: "TEXT"},
{Name: "CloudId", Type: "TEXT"},
{Name: "CreationTime", Type: "BIGINT"},
{Name: "DeletionTime", Type: "BIGINT"},
{Name: "ResourcePool", Type: "TEXT"},
{Name: "Datacenter", Type: "TEXT"},
{Name: "Cluster", Type: "TEXT"},
{Name: "Folder", Type: "TEXT"},
{Name: "ProvisionedDisk", Type: "REAL"},
{Name: "VcpuCount", Type: "BIGINT"},
{Name: "RamGB", Type: "BIGINT"},
{Name: "IsTemplate", Type: "TEXT"},
{Name: "PoweredOn", Type: "TEXT"},
{Name: "SrmPlaceholder", Type: "TEXT"},
{Name: "VmUuid", Type: "TEXT"},
{Name: "SamplesPresent", Type: "BIGINT"},
{Name: "AvgVcpuCount", Type: "REAL"},
{Name: "AvgRamGB", Type: "REAL"},
{Name: "AvgProvisionedDisk", Type: "REAL"},
{Name: "AvgIsPresent", Type: "REAL"},
{Name: "PoolTinPct", Type: "REAL"},
{Name: "PoolBronzePct", Type: "REAL"},
{Name: "PoolSilverPct", Type: "REAL"},
{Name: "PoolGoldPct", Type: "REAL"},
{Name: "SnapshotTime", Type: "BIGINT"},
{Name: "Tin", Type: "REAL"},
{Name: "Bronze", Type: "REAL"},
{Name: "Silver", Type: "REAL"},
{Name: "Gold", Type: "REAL"},
}
if err := EnsureColumns(ctx, dbConn, tableName, requiredColumns); err != nil {
return err
}
// Best-effort: drop legacy IsPresent column if it exists. // Best-effort: drop legacy IsPresent column if it exists.
if hasIsPresent, err := ColumnExists(ctx, dbConn, tableName, "IsPresent"); err == nil && hasIsPresent { if hasIsPresent, err := ColumnExists(ctx, dbConn, tableName, "IsPresent"); err == nil && hasIsPresent {

View File

@@ -679,11 +679,15 @@ func (c *CronTask) insertMonthlyAggregates(ctx context.Context, summaryTable str
"PoolTinPct", "PoolBronzePct", "PoolSilverPct", "PoolGoldPct", "PoolTinPct", "PoolBronzePct", "PoolSilverPct", "PoolGoldPct",
"Tin", "Bronze", "Silver", "Gold", "Tin", "Bronze", "Silver", "Gold",
} }
quotedColumns := make([]string, len(columns))
for i, col := range columns {
quotedColumns[i] = fmt.Sprintf(`"%s"`, col)
}
placeholders := make([]string, len(columns)) placeholders := make([]string, len(columns))
for i := range columns { for i := range columns {
placeholders[i] = "?" placeholders[i] = "?"
} }
stmtText := fmt.Sprintf(`INSERT INTO %s (%s) VALUES (%s)`, summaryTable, strings.Join(columns, ","), strings.Join(placeholders, ",")) stmtText := fmt.Sprintf(`INSERT INTO %s (%s) VALUES (%s)`, summaryTable, strings.Join(quotedColumns, ","), strings.Join(placeholders, ","))
stmtText = dbConn.Rebind(stmtText) stmtText = dbConn.Rebind(stmtText)
tx, err := dbConn.BeginTxx(ctx, nil) tx, err := dbConn.BeginTxx(ctx, nil)