From 345d210cb4d63e0b028b12a77b6ffe4b253ace90 Mon Sep 17 00:00:00 2001 From: Sam Mosleh Date: Sun, 1 Feb 2026 18:55:52 +0400 Subject: [PATCH 1/2] fix: multiple statements from the same column --- internal/plan/rewrite.go | 11 ++++- .../add_default_not_null/diff.sql | 2 + .../create_table/add_default_not_null/new.sql | 4 ++ .../create_table/add_default_not_null/old.sql | 4 ++ .../add_default_not_null/plan.json | 44 +++++++++++++++++++ .../add_default_not_null/plan.sql | 9 ++++ .../add_default_not_null/plan.txt | 21 +++++++++ 7 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 testdata/diff/create_table/add_default_not_null/diff.sql create mode 100644 testdata/diff/create_table/add_default_not_null/new.sql create mode 100644 testdata/diff/create_table/add_default_not_null/old.sql create mode 100644 testdata/diff/create_table/add_default_not_null/plan.json create mode 100644 testdata/diff/create_table/add_default_not_null/plan.sql create mode 100644 testdata/diff/create_table/add_default_not_null/plan.txt 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..96395895 --- /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" + } + ] + } + ] +} \ No newline at end of file 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(); From 00d3f2b717fb7f2c430373c974a3b0fcdf38f522 Mon Sep 17 00:00:00 2001 From: Sam Mosleh Date: Sun, 1 Feb 2026 19:00:28 +0400 Subject: [PATCH 2/2] Fix EOL --- testdata/diff/create_table/add_default_not_null/plan.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testdata/diff/create_table/add_default_not_null/plan.json b/testdata/diff/create_table/add_default_not_null/plan.json index 96395895..6adb2a30 100644 --- a/testdata/diff/create_table/add_default_not_null/plan.json +++ b/testdata/diff/create_table/add_default_not_null/plan.json @@ -41,4 +41,4 @@ ] } ] -} \ No newline at end of file +}