feat: Enhance PostgreSQL type handling and migration scripts
- Introduced equivalent base types and variants for PostgreSQL types to normalize type comparisons. - Added functions for normalizing SQL types and retrieving equivalent type variants. - Updated migration writer to handle type alterations with checks for existing types. - Implemented logic to create necessary extensions (e.g., pg_trgm) based on schema requirements. - Enhanced tests to cover new functionality for type normalization and migration handling. - Improved handling of GIN indexes to use appropriate operator classes based on column types.
This commit is contained in:
@@ -258,6 +258,11 @@ func runMerge(cmd *cobra.Command, args []string) error {
|
||||
fmt.Fprintf(os.Stderr, " ✓ Merge complete\n\n")
|
||||
fmt.Fprintf(os.Stderr, "%s\n", merge.GetMergeSummary(result))
|
||||
|
||||
if strings.EqualFold(mergeOutputType, "pgsql") && len(result.TypeConflicts) > 0 {
|
||||
return fmt.Errorf("merge detected conflicting existing column types and cannot safely continue with pgsql output\n%s",
|
||||
merge.GetColumnTypeConflictSummary(result, 10))
|
||||
}
|
||||
|
||||
// Step 4: Write output
|
||||
fmt.Fprintf(os.Stderr, "\n[4/4] Writing output...\n")
|
||||
fmt.Fprintf(os.Stderr, " Format: %s\n", mergeOutputType)
|
||||
|
||||
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -160,3 +161,38 @@ func TestRunMerge_FromListMissingSourceType(t *testing.T) {
|
||||
t.Error("expected error when neither --source-path nor --from-list is provided")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunMerge_PgsqlOutputRejectsColumnTypeConflict(t *testing.T) {
|
||||
saved := saveMergeState()
|
||||
defer restoreMergeState(saved)
|
||||
|
||||
dir := t.TempDir()
|
||||
targetFile := filepath.Join(dir, "target.json")
|
||||
sourceFile := filepath.Join(dir, "source.json")
|
||||
writeTestJSONWithSingleColumnType(t, targetFile, "users", "integer")
|
||||
writeTestJSONWithSingleColumnType(t, sourceFile, "users", "uuid")
|
||||
|
||||
mergeTargetType = "json"
|
||||
mergeTargetPath = targetFile
|
||||
mergeTargetConn = ""
|
||||
mergeSourceType = "json"
|
||||
mergeSourcePath = sourceFile
|
||||
mergeSourceConn = ""
|
||||
mergeFromList = nil
|
||||
mergeOutputType = "pgsql"
|
||||
mergeOutputPath = ""
|
||||
mergeOutputConn = "postgres://relspec:secret@localhost/testdb"
|
||||
mergeSkipTables = ""
|
||||
mergeReportPath = ""
|
||||
|
||||
err := runMerge(nil, nil)
|
||||
if err == nil {
|
||||
t.Fatal("expected pgsql output merge to fail on column type conflict")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "column type conflicts detected") {
|
||||
t.Fatalf("expected conflict summary in error, got: %v", err)
|
||||
}
|
||||
if !strings.Contains(err.Error(), "public.users.id") {
|
||||
t.Fatalf("expected conflicting column path in error, got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +71,40 @@ func writeTestJSON(t *testing.T, path string, tableNames []string) {
|
||||
}
|
||||
}
|
||||
|
||||
func writeTestJSONWithSingleColumnType(t *testing.T, path, tableName, columnType string) {
|
||||
t.Helper()
|
||||
|
||||
db := minimalDatabase{
|
||||
Name: "test_db",
|
||||
Schemas: []minimalSchema{{
|
||||
Name: "public",
|
||||
Tables: []minimalTable{{
|
||||
Name: tableName,
|
||||
Schema: "public",
|
||||
Columns: map[string]minimalColumn{
|
||||
"id": {
|
||||
Name: "id",
|
||||
Table: tableName,
|
||||
Schema: "public",
|
||||
Type: columnType,
|
||||
NotNull: true,
|
||||
IsPrimaryKey: true,
|
||||
AutoIncrement: true,
|
||||
},
|
||||
},
|
||||
}},
|
||||
}},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(db)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to marshal test JSON: %v", err)
|
||||
}
|
||||
if err := os.WriteFile(path, data, 0644); err != nil {
|
||||
t.Fatalf("failed to write test file %s: %v", path, err)
|
||||
}
|
||||
}
|
||||
|
||||
// convertState captures and restores all convert global vars.
|
||||
type convertState struct {
|
||||
sourceType string
|
||||
|
||||
Reference in New Issue
Block a user