From e7b777890e6fb7cac92cdb67e68e59502cd728c8 Mon Sep 17 00:00:00 2001 From: sagit <36596628+Sagit-chu@users.noreply.github.com> Date: Wed, 18 Feb 2026 18:44:37 +0800 Subject: [PATCH] fix(backend): rename legacy postgres unique constraints before AutoMigrate (#138) Old schema.sql created tables with inline UNIQUE column constraints, which PostgreSQL auto-names as __key. GORM expects uni_
_ (its NamingStrategy convention). On upgrade, AutoMigrate issued DROP CONSTRAINT uni_... against a name that did not exist, crashing startup with SQLSTATE 42704. Add preparePostgresLegacySchema() that runs before autoMigrateAll and renames all five mismatched constraints: - vite_config_name_key -> uni_vite_config_name - peer_share_token_key -> uni_peer_share_token - peer_share_runtime_reservation_id_key -> uni_peer_share_runtime_reservation_id - peer_share_runtime_resource_key_key -> uni_peer_share_runtime_resource_key - federation_tunnel_binding_resource_key_key -> uni_federation_tunnel_binding_resource_key The function is idempotent: it checks information_schema before each rename so re-runs on already-migrated databases are no-ops. Co-authored-by: Antigravity --- go-backend/internal/store/repo/repository.go | 48 ++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/go-backend/internal/store/repo/repository.go b/go-backend/internal/store/repo/repository.go index 2c6672c..bbdf042 100644 --- a/go-backend/internal/store/repo/repository.go +++ b/go-backend/internal/store/repo/repository.go @@ -127,6 +127,11 @@ func OpenPostgres(dsn string) (*Repository, error) { return nil, err } + if err := preparePostgresLegacySchema(db); err != nil { + _ = sqlDB.Close() + return nil, fmt.Errorf("prepare postgres legacy schema: %w", err) + } + if err := autoMigrateAll(db); err != nil { _ = sqlDB.Close() return nil, fmt.Errorf("auto migrate: %w", err) @@ -205,6 +210,49 @@ func autoMigrateAll(db *gorm.DB) error { return nil } +// preparePostgresLegacySchema renames unique constraints that were created by +// the old schema.sql (which used inline UNIQUE column syntax) to the names +// expected by GORM's NamingStrategy ("uni_
_"). Without this, +// GORM's AutoMigrate emits "DROP CONSTRAINT uni_..." against constraints that +// don't exist under that name, crashing startup on upgraded PostgreSQL installs. +func preparePostgresLegacySchema(db *gorm.DB) error { + if db == nil || db.Dialector.Name() != "postgres" { + return nil + } + + type rename struct{ table, oldName, newName string } + renames := []rename{ + {"vite_config", "vite_config_name_key", "uni_vite_config_name"}, + {"peer_share", "peer_share_token_key", "uni_peer_share_token"}, + {"peer_share_runtime", "peer_share_runtime_reservation_id_key", "uni_peer_share_runtime_reservation_id"}, + {"peer_share_runtime", "peer_share_runtime_resource_key_key", "uni_peer_share_runtime_resource_key"}, + {"federation_tunnel_binding", "federation_tunnel_binding_resource_key_key", "uni_federation_tunnel_binding_resource_key"}, + } + + for _, r := range renames { + var count int64 + if err := db.Raw( + `SELECT COUNT(*) FROM information_schema.table_constraints + WHERE constraint_schema = current_schema() + AND table_name = ? + AND constraint_name = ? + AND constraint_type = 'UNIQUE'`, + r.table, r.oldName, + ).Scan(&count).Error; err != nil { + return fmt.Errorf("check constraint %s.%s: %w", r.table, r.oldName, err) + } + if count == 0 { + continue + } + if err := db.Exec( + fmt.Sprintf(`ALTER TABLE %q RENAME CONSTRAINT %q TO %q`, r.table, r.oldName, r.newName), + ).Error; err != nil { + return fmt.Errorf("rename constraint %s.%s→%s: %w", r.table, r.oldName, r.newName, err) + } + } + return nil +} + func prepareSQLiteLegacyColumns(db *gorm.DB) error { if db == nil || db.Dialector.Name() != "sqlite" { return nil