From 4b9e0094d5683bd2d94186c4027f5aefec8206e8 Mon Sep 17 00:00:00 2001 From: Tianzhou Date: Mon, 23 Feb 2026 06:27:33 -0800 Subject: [PATCH] fix: quote camelCase column names in online NOT NULL rewrite DDL (#313) Co-Authored-By: Claude Opus 4.6 --- internal/plan/rewrite.go | 6 ++- .../diff.sql | 1 + .../new.sql | 5 +++ .../old.sql | 5 +++ .../plan.json | 38 +++++++++++++++++++ .../plan.sql | 7 ++++ .../plan.txt | 19 ++++++++++ 7 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 testdata/diff/online/issue_313_camelcase_column_not_null/diff.sql create mode 100644 testdata/diff/online/issue_313_camelcase_column_not_null/new.sql create mode 100644 testdata/diff/online/issue_313_camelcase_column_not_null/old.sql create mode 100644 testdata/diff/online/issue_313_camelcase_column_not_null/plan.json create mode 100644 testdata/diff/online/issue_313_camelcase_column_not_null/plan.sql create mode 100644 testdata/diff/online/issue_313_camelcase_column_not_null/plan.txt diff --git a/internal/plan/rewrite.go b/internal/plan/rewrite.go index 4cbbfbbd..28b47277 100644 --- a/internal/plan/rewrite.go +++ b/internal/plan/rewrite.go @@ -298,9 +298,11 @@ func generateColumnNotNullRewrite(_ *diff.ColumnDiff, path string) []RewriteStep tableName := getTableNameWithSchema(schema, table) constraintName := fmt.Sprintf("%s_not_null", column) + quotedColumn := ir.QuoteIdentifier(column) + // Step 1: Add CHECK constraint with NOT VALID addConstraintSQL := fmt.Sprintf("ALTER TABLE %s ADD CONSTRAINT %s CHECK (%s IS NOT NULL) NOT VALID;", - tableName, ir.QuoteIdentifier(constraintName), column) + tableName, ir.QuoteIdentifier(constraintName), quotedColumn) // Step 2: Validate the constraint validateConstraintSQL := fmt.Sprintf("ALTER TABLE %s VALIDATE CONSTRAINT %s;", @@ -308,7 +310,7 @@ func generateColumnNotNullRewrite(_ *diff.ColumnDiff, path string) []RewriteStep // Step 3: Set column to NOT NULL setNotNullSQL := fmt.Sprintf("ALTER TABLE %s ALTER COLUMN %s SET NOT NULL;", - tableName, column) + tableName, quotedColumn) // Step 4: Drop CHECK constraint dropConstraintSQL := fmt.Sprintf("ALTER TABLE %s DROP CONSTRAINT %s;", diff --git a/testdata/diff/online/issue_313_camelcase_column_not_null/diff.sql b/testdata/diff/online/issue_313_camelcase_column_not_null/diff.sql new file mode 100644 index 00000000..e2cf23d7 --- /dev/null +++ b/testdata/diff/online/issue_313_camelcase_column_not_null/diff.sql @@ -0,0 +1 @@ +ALTER TABLE "Planning" ALTER COLUMN "offersValidUntil" SET NOT NULL; diff --git a/testdata/diff/online/issue_313_camelcase_column_not_null/new.sql b/testdata/diff/online/issue_313_camelcase_column_not_null/new.sql new file mode 100644 index 00000000..9711a540 --- /dev/null +++ b/testdata/diff/online/issue_313_camelcase_column_not_null/new.sql @@ -0,0 +1,5 @@ +CREATE TABLE public."Planning" ( + id integer NOT NULL, + "offersValidUntil" timestamp with time zone NOT NULL, + CONSTRAINT "Planning_pkey" PRIMARY KEY (id) +); diff --git a/testdata/diff/online/issue_313_camelcase_column_not_null/old.sql b/testdata/diff/online/issue_313_camelcase_column_not_null/old.sql new file mode 100644 index 00000000..180e20e5 --- /dev/null +++ b/testdata/diff/online/issue_313_camelcase_column_not_null/old.sql @@ -0,0 +1,5 @@ +CREATE TABLE public."Planning" ( + id integer NOT NULL, + "offersValidUntil" timestamp with time zone, + CONSTRAINT "Planning_pkey" PRIMARY KEY (id) +); diff --git a/testdata/diff/online/issue_313_camelcase_column_not_null/plan.json b/testdata/diff/online/issue_313_camelcase_column_not_null/plan.json new file mode 100644 index 00000000..9e8953cc --- /dev/null +++ b/testdata/diff/online/issue_313_camelcase_column_not_null/plan.json @@ -0,0 +1,38 @@ +{ + "version": "1.0.0", + "pgschema_version": "1.7.2", + "created_at": "1970-01-01T00:00:00Z", + "source_fingerprint": { + "hash": "59ecc7fdab924e513eb6acdc93543167379bf64b4c6b5e1fe1d8e98fa48fdb9f" + }, + "groups": [ + { + "steps": [ + { + "sql": "ALTER TABLE \"Planning\" ADD CONSTRAINT \"offersValidUntil_not_null\" CHECK (\"offersValidUntil\" IS NOT NULL) NOT VALID;", + "type": "table.column", + "operation": "alter", + "path": "public.Planning.offersValidUntil" + }, + { + "sql": "ALTER TABLE \"Planning\" VALIDATE CONSTRAINT \"offersValidUntil_not_null\";", + "type": "table.column", + "operation": "alter", + "path": "public.Planning.offersValidUntil" + }, + { + "sql": "ALTER TABLE \"Planning\" ALTER COLUMN \"offersValidUntil\" SET NOT NULL;", + "type": "table.column", + "operation": "alter", + "path": "public.Planning.offersValidUntil" + }, + { + "sql": "ALTER TABLE \"Planning\" DROP CONSTRAINT \"offersValidUntil_not_null\";", + "type": "table.column", + "operation": "alter", + "path": "public.Planning.offersValidUntil" + } + ] + } + ] +} diff --git a/testdata/diff/online/issue_313_camelcase_column_not_null/plan.sql b/testdata/diff/online/issue_313_camelcase_column_not_null/plan.sql new file mode 100644 index 00000000..098ff225 --- /dev/null +++ b/testdata/diff/online/issue_313_camelcase_column_not_null/plan.sql @@ -0,0 +1,7 @@ +ALTER TABLE "Planning" ADD CONSTRAINT "offersValidUntil_not_null" CHECK ("offersValidUntil" IS NOT NULL) NOT VALID; + +ALTER TABLE "Planning" VALIDATE CONSTRAINT "offersValidUntil_not_null"; + +ALTER TABLE "Planning" ALTER COLUMN "offersValidUntil" SET NOT NULL; + +ALTER TABLE "Planning" DROP CONSTRAINT "offersValidUntil_not_null"; diff --git a/testdata/diff/online/issue_313_camelcase_column_not_null/plan.txt b/testdata/diff/online/issue_313_camelcase_column_not_null/plan.txt new file mode 100644 index 00000000..f3dd2b78 --- /dev/null +++ b/testdata/diff/online/issue_313_camelcase_column_not_null/plan.txt @@ -0,0 +1,19 @@ +Plan: 1 to modify. + +Summary by type: + tables: 1 to modify + +Tables: + ~ Planning + ~ offersValidUntil (column) + +DDL to be executed: +-------------------------------------------------- + +ALTER TABLE "Planning" ADD CONSTRAINT "offersValidUntil_not_null" CHECK ("offersValidUntil" IS NOT NULL) NOT VALID; + +ALTER TABLE "Planning" VALIDATE CONSTRAINT "offersValidUntil_not_null"; + +ALTER TABLE "Planning" ALTER COLUMN "offersValidUntil" SET NOT NULL; + +ALTER TABLE "Planning" DROP CONSTRAINT "offersValidUntil_not_null";