Smail/server/db/migration/index.go
smail b365c2535f
Some checks are pending
Security Checks / security (push) Waiting to run
实现用户邮箱绑定和登录标识解析
2026-08-30 23:33:38 +08:00

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
}