Files
descrybe/apps/api/cmd/migrator/mysqlmeta.go
T

77 lines
1.8 KiB
Go
Raw Normal View History

package main
import (
"context"
"database/sql"
"fmt"
"strings"
)
// mysqlCol returns a quoted column name if present, otherwise a SQL literal/expression fallback.
func mysqlCol(ctx context.Context, db *sql.DB, table, column, fallbackExpr string) string {
if mysqlColumnExists(ctx, db, table, column) {
q, err := quoteMySQLIdent(column)
if err != nil {
return fallbackExpr
}
return q
}
return fallbackExpr
}
// mysqlCoalesce returns COALESCE(column, fallback) when column exists, else fallback alone.
func mysqlCoalesce(ctx context.Context, db *sql.DB, table, column, fallbackExpr string) string {
if mysqlColumnExists(ctx, db, table, column) {
q, err := quoteMySQLIdent(column)
if err != nil {
return fallbackExpr
}
return fmt.Sprintf("COALESCE(%s, %s)", q, fallbackExpr)
}
return fallbackExpr
}
// mysqlSelectList builds "SELECT a, b, ..." from expressions (already resolved).
func mysqlSelectList(exprs ...string) string {
return "SELECT " + strings.Join(exprs, ", ")
}
// scanIntish scans MySQL INT/DECIMAL/string numeric values into an int.
func scanIntish(v any) int {
switch x := v.(type) {
case int64:
return int(x)
case int32:
return int(x)
case float64:
return int(x)
case []byte:
var n float64
if _, err := fmt.Sscanf(string(x), "%f", &n); err == nil {
return int(n)
}
case string:
var n float64
if _, err := fmt.Sscanf(x, "%f", &n); err == nil {
return int(n)
}
}
return 0
}
// queryFirstOK tries queries in order until one succeeds (for column-shape fallbacks).
func queryFirstOK(ctx context.Context, db *sql.DB, queries ...string) (*sql.Rows, error) {
var last error
for _, q := range queries {
rows, err := db.QueryContext(ctx, q)
if err == nil {
return rows, nil
}
last = err
}
if last == nil {
return nil, fmt.Errorf("no queries provided")
}
return nil, last
}