Some checks are pending
Security Checks / security (push) Waiting to run
统一 frontend、backend、test、test-log 和 out 目录,更新构建、部署及测试入口;纳入配置管理兼容与首次安全引导修复;排除本机配置、密钥和测试产物。
60 lines
1.9 KiB
Go
60 lines
1.9 KiB
Go
package migration
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
func ensureIndex(ctx context.Context, exec executor, dialect Dialect, table, index string, unique bool, columns []string) error {
|
|
exists, err := indexExists(ctx, exec, dialect, table, index)
|
|
if err != nil {
|
|
return fmt.Errorf("check index %s: %w", index, err)
|
|
}
|
|
if exists {
|
|
return nil
|
|
}
|
|
quotedTable, quotedIndex, err := quotedIdentifiers(dialect, table, index)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
quotedColumns := make([]string, 0, len(columns))
|
|
for _, column := range columns {
|
|
_, quotedColumn, err := quotedIdentifiers(dialect, table, column)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
quotedColumns = append(quotedColumns, quotedColumn)
|
|
}
|
|
indexType := "INDEX"
|
|
if unique {
|
|
indexType = "UNIQUE INDEX"
|
|
}
|
|
statement := fmt.Sprintf("CREATE %s %s ON %s (%s)", indexType, quotedIndex, quotedTable, strings.Join(quotedColumns, ", "))
|
|
if _, err := exec.ExecContext(ctx, statement); err != nil {
|
|
return fmt.Errorf("create index %s: %w", index, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func indexExists(ctx context.Context, exec executor, dialect Dialect, table, index string) (bool, error) {
|
|
var count int
|
|
switch dialect {
|
|
case DialectSQLite:
|
|
if err := exec.QueryRowContext(ctx, `SELECT COUNT(*) FROM pragma_index_list(?) WHERE name = ?`, table, index).Scan(&count); err != nil {
|
|
return false, err
|
|
}
|
|
case DialectMySQL:
|
|
if err := exec.QueryRowContext(ctx, "SELECT COUNT(*) FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = ? AND index_name = ?", table, index).Scan(&count); err != nil {
|
|
return false, err
|
|
}
|
|
case DialectPostgres:
|
|
if err := exec.QueryRowContext(ctx, "SELECT COUNT(*) FROM pg_indexes WHERE schemaname = current_schema() AND tablename = $1 AND indexname = $2", table, index).Scan(&count); err != nil {
|
|
return false, err
|
|
}
|
|
default:
|
|
return false, fmt.Errorf("unsupported index dialect %q", dialect)
|
|
}
|
|
return count > 0, nil
|
|
}
|