diff --git a/db/helpers.go b/db/helpers.go index c52c3c4..ceac960 100644 --- a/db/helpers.go +++ b/db/helpers.go @@ -274,8 +274,8 @@ func ColumnExists(ctx context.Context, dbConn *sqlx.DB, tableName string, column err := getLog(ctx, dbConn, &count, ` SELECT COUNT(1) FROM information_schema.columns -WHERE table_name = $1 AND column_name = $2 -`, tableName, strings.ToLower(columnName)) +WHERE table_schema = 'public' AND table_name = $1 AND LOWER(column_name) = LOWER($2) +`, tableName, columnName) if err != nil { return false, err } @@ -3149,7 +3149,7 @@ INSERT INTO %s ( ) SELECT "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", MAX("ResourcePool") AS "ResourcePool", "Datacenter", "Cluster", "Folder", @@ -3201,7 +3201,8 @@ CROSS JOIN totals GROUP BY "InventoryId", "Name", "Vcenter", "VmId", "EventKey", "CloudId", "Datacenter", "Cluster", "Folder", - "IsTemplate", "SrmPlaceholder", "VmUuid"; + "IsTemplate", "SrmPlaceholder", "VmUuid", + totals.total_samples; `, unionQuery, tableName) 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 { 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. if hasIsPresent, err := ColumnExists(ctx, dbConn, tableName, "IsPresent"); err == nil && hasIsPresent { diff --git a/internal/tasks/monthlyAggregate.go b/internal/tasks/monthlyAggregate.go index 18825cf..d2fa490 100644 --- a/internal/tasks/monthlyAggregate.go +++ b/internal/tasks/monthlyAggregate.go @@ -679,11 +679,15 @@ func (c *CronTask) insertMonthlyAggregates(ctx context.Context, summaryTable str "PoolTinPct", "PoolBronzePct", "PoolSilverPct", "PoolGoldPct", "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)) for i := range columns { 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) tx, err := dbConn.BeginTxx(ctx, nil)