diff --git a/internal/plan/rewrite.go b/internal/plan/rewrite.go index a32185ae..8498261e 100644 --- a/internal/plan/rewrite.go +++ b/internal/plan/rewrite.go @@ -78,9 +78,16 @@ func generateRewrite(d diff.Diff, newlyCreatedTables map[string]bool, newlyCreat case diff.DiffTypeTableColumn: if d.Operation == diff.DiffOperationAlter { if columnDiff, ok := d.Source.(*diff.ColumnDiff); ok { - // Check if this is a NOT NULL addition + // Check if this is a NOT NULL addition AND this specific statement is for SET NOT NULL + // Multiple statements can be generated from the same ColumnDiff (e.g., SET NOT NULL + SET DEFAULT), + // so we must only rewrite the statement that actually contains SET NOT NULL if columnDiff.Old.IsNullable && !columnDiff.New.IsNullable { - return generateColumnNotNullRewrite(columnDiff, d.Path) + // Verify this diff's SQL actually contains SET NOT NULL + for _, stmt := range d.Statements { + if strings.Contains(stmt.SQL, "SET NOT NULL") { + return generateColumnNotNullRewrite(columnDiff, d.Path) + } + } } } } diff --git a/testdata/diff/create_table/add_default_not_null/diff.sql b/testdata/diff/create_table/add_default_not_null/diff.sql new file mode 100644 index 00000000..a65a81ff --- /dev/null +++ b/testdata/diff/create_table/add_default_not_null/diff.sql @@ -0,0 +1,2 @@ +ALTER TABLE people ALTER COLUMN created_at SET NOT NULL; +ALTER TABLE people ALTER COLUMN created_at SET DEFAULT now(); diff --git a/testdata/diff/create_table/add_default_not_null/new.sql b/testdata/diff/create_table/add_default_not_null/new.sql new file mode 100644 index 00000000..43b2b578 --- /dev/null +++ b/testdata/diff/create_table/add_default_not_null/new.sql @@ -0,0 +1,4 @@ +CREATE TABLE public.people ( + id bigint PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + created_at timestamp with time zone DEFAULT NOW() NOT NULL +); diff --git a/testdata/diff/create_table/add_default_not_null/old.sql b/testdata/diff/create_table/add_default_not_null/old.sql new file mode 100644 index 00000000..448f508a --- /dev/null +++ b/testdata/diff/create_table/add_default_not_null/old.sql @@ -0,0 +1,4 @@ +CREATE TABLE public.people ( + id bigint PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + created_at timestamp with time zone +); diff --git a/testdata/diff/create_table/add_default_not_null/plan.json b/testdata/diff/create_table/add_default_not_null/plan.json new file mode 100644 index 00000000..6adb2a30 --- /dev/null +++ b/testdata/diff/create_table/add_default_not_null/plan.json @@ -0,0 +1,44 @@ +{ + "version": "1.0.0", + "pgschema_version": "1.6.2", + "created_at": "1970-01-01T00:00:00Z", + "source_fingerprint": { + "hash": "a5614a0f5b8d53ba131811b4a89cd3eddb434b6bd0398b7ec180199c8fba880d" + }, + "groups": [ + { + "steps": [ + { + "sql": "ALTER TABLE people ADD CONSTRAINT created_at_not_null CHECK (created_at IS NOT NULL) NOT VALID;", + "type": "table.column", + "operation": "alter", + "path": "public.people.created_at" + }, + { + "sql": "ALTER TABLE people VALIDATE CONSTRAINT created_at_not_null;", + "type": "table.column", + "operation": "alter", + "path": "public.people.created_at" + }, + { + "sql": "ALTER TABLE people ALTER COLUMN created_at SET NOT NULL;", + "type": "table.column", + "operation": "alter", + "path": "public.people.created_at" + }, + { + "sql": "ALTER TABLE people DROP CONSTRAINT created_at_not_null;", + "type": "table.column", + "operation": "alter", + "path": "public.people.created_at" + }, + { + "sql": "ALTER TABLE people ALTER COLUMN created_at SET DEFAULT now();", + "type": "table.column", + "operation": "alter", + "path": "public.people.created_at" + } + ] + } + ] +} diff --git a/testdata/diff/create_table/add_default_not_null/plan.sql b/testdata/diff/create_table/add_default_not_null/plan.sql new file mode 100644 index 00000000..fb84c6e2 --- /dev/null +++ b/testdata/diff/create_table/add_default_not_null/plan.sql @@ -0,0 +1,9 @@ +ALTER TABLE people ADD CONSTRAINT created_at_not_null CHECK (created_at IS NOT NULL) NOT VALID; + +ALTER TABLE people VALIDATE CONSTRAINT created_at_not_null; + +ALTER TABLE people ALTER COLUMN created_at SET NOT NULL; + +ALTER TABLE people DROP CONSTRAINT created_at_not_null; + +ALTER TABLE people ALTER COLUMN created_at SET DEFAULT now(); diff --git a/testdata/diff/create_table/add_default_not_null/plan.txt b/testdata/diff/create_table/add_default_not_null/plan.txt new file mode 100644 index 00000000..0eaaeecc --- /dev/null +++ b/testdata/diff/create_table/add_default_not_null/plan.txt @@ -0,0 +1,21 @@ +Plan: 1 to modify. + +Summary by type: + tables: 1 to modify + +Tables: + ~ people + ~ created_at (column) + +DDL to be executed: +-------------------------------------------------- + +ALTER TABLE people ADD CONSTRAINT created_at_not_null CHECK (created_at IS NOT NULL) NOT VALID; + +ALTER TABLE people VALIDATE CONSTRAINT created_at_not_null; + +ALTER TABLE people ALTER COLUMN created_at SET NOT NULL; + +ALTER TABLE people DROP CONSTRAINT created_at_not_null; + +ALTER TABLE people ALTER COLUMN created_at SET DEFAULT now();