From 7560a5e11d13b472ac46c12e9a5043974956b00b Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Mon, 30 Jun 2025 20:40:49 -0700 Subject: [PATCH 01/10] new test --- __fixtures__/generated/generated.json | 18 +++++++++++++ .../original/alter/alter-table-column.sql | 8 ++++++ .../kitchen-sink/misc-pg_catalog.test.ts | 25 +++++++++++++++++++ .../original-alter-alter-table-column.test.ts | 9 +++++++ .../original-alter-alter-table-column.test.ts | 9 +++++++ .../original-alter-alter-table-column.test.ts | 9 +++++++ .../original-alter-alter-table-column.test.ts | 9 +++++++ .../original-alter-alter-table-column.test.ts | 9 +++++++ 8 files changed, 96 insertions(+) create mode 100644 __fixtures__/kitchen-sink/original/alter/alter-table-column.sql create mode 100644 packages/deparser/__tests__/kitchen-sink/misc-pg_catalog.test.ts create mode 100644 packages/deparser/__tests__/kitchen-sink/original-alter-alter-table-column.test.ts create mode 100644 packages/transform/__tests__/kitchen-sink/13-14/original-alter-alter-table-column.test.ts create mode 100644 packages/transform/__tests__/kitchen-sink/14-15/original-alter-alter-table-column.test.ts create mode 100644 packages/transform/__tests__/kitchen-sink/15-16/original-alter-alter-table-column.test.ts create mode 100644 packages/transform/__tests__/kitchen-sink/16-17/original-alter-alter-table-column.test.ts diff --git a/__fixtures__/generated/generated.json b/__fixtures__/generated/generated.json index 99556bbc..7605fd55 100644 --- a/__fixtures__/generated/generated.json +++ b/__fixtures__/generated/generated.json @@ -21181,6 +21181,7 @@ "original/alter/alter-95.sql": "ALTER TABLE mytable ADD COLUMN height_in numeric GENERATED ALWAYS AS (height_cm / 2.54) STORED", "original/alter/alter-96.sql": "ALTER SCHEMA schemaname RENAME TO newname", "original/alter/alter-97.sql": "ALTER SCHEMA schemaname OWNER TO newowner", + "original/alter/alter-table-column-1.sql": "ALTER TABLE public.table1 ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY (\n SEQUENCE NAME public.table1\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1\n)", "misc/quotes_etc-1.sql": "CREATE USER MAPPING FOR local_user SERVER \"foreign_server\" OPTIONS (user 'remote_user', password 'secret123')", "misc/quotes_etc-2.sql": "CREATE USER MAPPING FOR local_user SERVER foreign_server OPTIONS (user 'remote_user', password 'secret123')", "misc/quotes_etc-3.sql": "SELECT E'Line 1\\nLine 2'", @@ -21211,6 +21212,23 @@ "misc/quotes_etc-28.sql": "DO $$\nBEGIN\n RAISE NOTICE 'Line one\\nLine two';\nEND;\n$$ LANGUAGE plpgsql", "misc/quotes_etc-29.sql": "CREATE USER MAPPING FOR local_user SERVER \"foreign_server\" OPTIONS (user 'remote_user', password 'secret123')", "misc/quotes_etc-30.sql": "CREATE USER MAPPING FOR local_user SERVER foreign_server OPTIONS (user 'remote_user', password 'secret123')", + "misc/pg_catalog-1.sql": "SELECT json_object('{}')", + "misc/pg_catalog-2.sql": "SELECT * FROM generate_series(1, 5)", + "misc/pg_catalog-3.sql": "SELECT get_byte(E'\\\\xDEADBEEF'::bytea, 1)", + "misc/pg_catalog-4.sql": "SELECT now()", + "misc/pg_catalog-5.sql": "SELECT clock_timestamp()", + "misc/pg_catalog-6.sql": "SELECT to_char(now(), 'YYYY-MM-DD HH24:MI:SS')", + "misc/pg_catalog-7.sql": "SELECT json_build_object('name', 'Alice', 'age', 30)", + "misc/pg_catalog-8.sql": "SELECT pg_typeof(42), pg_typeof('hello'), pg_typeof(now())", + "misc/pg_catalog-9.sql": "SELECT substring('abcdefg' FROM 2 FOR 3)", + "misc/pg_catalog-10.sql": "SELECT replace('hello world', 'l', 'L')", + "misc/pg_catalog-11.sql": "SELECT length('yolo')", + "misc/pg_catalog-12.sql": "SELECT position('G' IN 'ChatGPT')", + "misc/pg_catalog-13.sql": "SELECT trim(' padded text ')", + "misc/pg_catalog-14.sql": "SELECT ltrim('---abc', '-')", + "misc/pg_catalog-15.sql": "SELECT array_agg(id) FROM (VALUES (1), (2), (3)) AS t(id)", + "misc/pg_catalog-16.sql": "SELECT string_agg(name, ', ') FROM (VALUES ('Alice'), ('Bob'), ('Carol')) AS t(name)", + "misc/pg_catalog-17.sql": "SELECT json_agg(name) FROM (VALUES ('A'), ('B')) AS t(name)", "misc/launchql-ext-types-1.sql": "CREATE DOMAIN attachment AS jsonb CHECK ( value ?& ARRAY['url', 'mime'] AND (value->>'url') ~ '^(https?)://[^\\s/$.?#].[^\\s]*$' )", "misc/launchql-ext-types-2.sql": "COMMENT ON DOMAIN attachment IS E'@name launchqlInternalTypeAttachment'", "misc/launchql-ext-types-3.sql": "CREATE DOMAIN email AS citext CHECK ( value ~ '^[a-zA-Z0-9.!#$%&''*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$' )", diff --git a/__fixtures__/kitchen-sink/original/alter/alter-table-column.sql b/__fixtures__/kitchen-sink/original/alter/alter-table-column.sql new file mode 100644 index 00000000..d9cfa79f --- /dev/null +++ b/__fixtures__/kitchen-sink/original/alter/alter-table-column.sql @@ -0,0 +1,8 @@ +ALTER TABLE public.table1 ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY ( + SEQUENCE NAME public.table1 + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); \ No newline at end of file diff --git a/packages/deparser/__tests__/kitchen-sink/misc-pg_catalog.test.ts b/packages/deparser/__tests__/kitchen-sink/misc-pg_catalog.test.ts new file mode 100644 index 00000000..e3cf2165 --- /dev/null +++ b/packages/deparser/__tests__/kitchen-sink/misc-pg_catalog.test.ts @@ -0,0 +1,25 @@ + +import { FixtureTestUtils } from '../../test-utils'; +const fixtures = new FixtureTestUtils(); + +it('misc-pg_catalog', async () => { + await fixtures.runFixtureTests([ + "misc/pg_catalog-1.sql", + "misc/pg_catalog-2.sql", + "misc/pg_catalog-3.sql", + "misc/pg_catalog-4.sql", + "misc/pg_catalog-5.sql", + "misc/pg_catalog-6.sql", + "misc/pg_catalog-7.sql", + "misc/pg_catalog-8.sql", + "misc/pg_catalog-9.sql", + "misc/pg_catalog-10.sql", + "misc/pg_catalog-11.sql", + "misc/pg_catalog-12.sql", + "misc/pg_catalog-13.sql", + "misc/pg_catalog-14.sql", + "misc/pg_catalog-15.sql", + "misc/pg_catalog-16.sql", + "misc/pg_catalog-17.sql" +]); +}); diff --git a/packages/deparser/__tests__/kitchen-sink/original-alter-alter-table-column.test.ts b/packages/deparser/__tests__/kitchen-sink/original-alter-alter-table-column.test.ts new file mode 100644 index 00000000..290edd46 --- /dev/null +++ b/packages/deparser/__tests__/kitchen-sink/original-alter-alter-table-column.test.ts @@ -0,0 +1,9 @@ + +import { FixtureTestUtils } from '../../test-utils'; +const fixtures = new FixtureTestUtils(); + +it('original-alter-alter-table-column', async () => { + await fixtures.runFixtureTests([ + "original/alter/alter-table-column-1.sql" +]); +}); diff --git a/packages/transform/__tests__/kitchen-sink/13-14/original-alter-alter-table-column.test.ts b/packages/transform/__tests__/kitchen-sink/13-14/original-alter-alter-table-column.test.ts new file mode 100644 index 00000000..8e513824 --- /dev/null +++ b/packages/transform/__tests__/kitchen-sink/13-14/original-alter-alter-table-column.test.ts @@ -0,0 +1,9 @@ + +import { FixtureTestUtils } from '../../../test-utils'; +const fixtures = new FixtureTestUtils(13, 14); + +it('original-alter-alter-table-column', async () => { + await fixtures.runFixtureTests([ + "original/alter/alter-table-column-1.sql" +]); +}); diff --git a/packages/transform/__tests__/kitchen-sink/14-15/original-alter-alter-table-column.test.ts b/packages/transform/__tests__/kitchen-sink/14-15/original-alter-alter-table-column.test.ts new file mode 100644 index 00000000..3d5d4d1e --- /dev/null +++ b/packages/transform/__tests__/kitchen-sink/14-15/original-alter-alter-table-column.test.ts @@ -0,0 +1,9 @@ + +import { FixtureTestUtils } from '../../../test-utils'; +const fixtures = new FixtureTestUtils(14, 15); + +it('original-alter-alter-table-column', async () => { + await fixtures.runFixtureTests([ + "original/alter/alter-table-column-1.sql" +]); +}); diff --git a/packages/transform/__tests__/kitchen-sink/15-16/original-alter-alter-table-column.test.ts b/packages/transform/__tests__/kitchen-sink/15-16/original-alter-alter-table-column.test.ts new file mode 100644 index 00000000..b04ce6b7 --- /dev/null +++ b/packages/transform/__tests__/kitchen-sink/15-16/original-alter-alter-table-column.test.ts @@ -0,0 +1,9 @@ + +import { FixtureTestUtils } from '../../../test-utils'; +const fixtures = new FixtureTestUtils(15, 16); + +it('original-alter-alter-table-column', async () => { + await fixtures.runFixtureTests([ + "original/alter/alter-table-column-1.sql" +]); +}); diff --git a/packages/transform/__tests__/kitchen-sink/16-17/original-alter-alter-table-column.test.ts b/packages/transform/__tests__/kitchen-sink/16-17/original-alter-alter-table-column.test.ts new file mode 100644 index 00000000..079e3a7b --- /dev/null +++ b/packages/transform/__tests__/kitchen-sink/16-17/original-alter-alter-table-column.test.ts @@ -0,0 +1,9 @@ + +import { FixtureTestUtils } from '../../../test-utils'; +const fixtures = new FixtureTestUtils(16, 17); + +it('original-alter-alter-table-column', async () => { + await fixtures.runFixtureTests([ + "original/alter/alter-table-column-1.sql" +]); +}); From 590e82f31907eff1305e91ec46b1dd34899a2a1d Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Tue, 1 Jul 2025 03:48:31 +0000 Subject: [PATCH 02/10] fix: correct ALTER TABLE ADD IDENTITY column generation - Remove duplicate 'GENERATED' and 'AS IDENTITY' text in AT_AddIdentity case - Fix sequence name formatting to use 'SEQUENCE NAME schema.table' format - Handle NO MINVALUE/NO MAXVALUE cases when arg is null in CONSTR_IDENTITY - Fixes __tests__/kitchen-sink/original-alter-alter-table-column.test.ts Co-Authored-By: Dan Lynch --- packages/deparser/src/deparser.ts | 33 +++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/packages/deparser/src/deparser.ts b/packages/deparser/src/deparser.ts index 50602cc2..8d1a8248 100644 --- a/packages/deparser/src/deparser.ts +++ b/packages/deparser/src/deparser.ts @@ -2704,20 +2704,42 @@ export class Deparser implements DeparserVisitor { .map(option => { if (option.DefElem) { const defElem = option.DefElem; - const argValue = defElem.arg ? this.visit(defElem.arg, context) : ''; - if (defElem.defname === 'start') { + if (defElem.defname === 'sequence_name') { + if (defElem.arg && defElem.arg.List) { + const nameList = ListUtils.unwrapList(defElem.arg) + .map(item => this.visit(item, context)) + .join('.'); + return `SEQUENCE NAME ${nameList}`; + } + return 'SEQUENCE NAME'; + } else if (defElem.defname === 'start') { + const argValue = defElem.arg ? this.visit(defElem.arg, context) : ''; return `START WITH ${argValue}`; } else if (defElem.defname === 'increment') { + const argValue = defElem.arg ? this.visit(defElem.arg, context) : ''; return `INCREMENT BY ${argValue}`; } else if (defElem.defname === 'minvalue') { - return `MINVALUE ${argValue}`; + if (defElem.arg) { + const argValue = this.visit(defElem.arg, context); + return `MINVALUE ${argValue}`; + } else { + return 'NO MINVALUE'; + } } else if (defElem.defname === 'maxvalue') { - return `MAXVALUE ${argValue}`; + if (defElem.arg) { + const argValue = this.visit(defElem.arg, context); + return `MAXVALUE ${argValue}`; + } else { + return 'NO MAXVALUE'; + } } else if (defElem.defname === 'cache') { + const argValue = defElem.arg ? this.visit(defElem.arg, context) : ''; return `CACHE ${argValue}`; } else if (defElem.defname === 'cycle') { + const argValue = defElem.arg ? this.visit(defElem.arg, context) : ''; return argValue === 'true' ? 'CYCLE' : 'NO CYCLE'; } + const argValue = defElem.arg ? this.visit(defElem.arg, context) : ''; return `${defElem.defname.toUpperCase()} ${argValue}`; } return this.visit(option, context); @@ -5234,11 +5256,10 @@ export class Deparser implements DeparserVisitor { if (node.name) { output.push(QuoteUtils.quote(node.name)); } - output.push('ADD GENERATED'); + output.push('ADD'); if (node.def) { output.push(this.visit(node.def, context)); } - output.push('AS IDENTITY'); break; case 'AT_SetIdentity': output.push('ALTER COLUMN'); From 72006b4fecb69100c30515dbbf388ced9524912f Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Mon, 30 Jun 2025 21:00:48 -0700 Subject: [PATCH 03/10] pretty --- .../pretty/__snapshots__/alter-table-column.test.ts.snap | 5 +++++ .../deparser/__tests__/pretty/alter-table-column.test.ts | 6 ++++++ 2 files changed, 11 insertions(+) create mode 100644 packages/deparser/__tests__/pretty/__snapshots__/alter-table-column.test.ts.snap create mode 100644 packages/deparser/__tests__/pretty/alter-table-column.test.ts diff --git a/packages/deparser/__tests__/pretty/__snapshots__/alter-table-column.test.ts.snap b/packages/deparser/__tests__/pretty/__snapshots__/alter-table-column.test.ts.snap new file mode 100644 index 00000000..e86e41a2 --- /dev/null +++ b/packages/deparser/__tests__/pretty/__snapshots__/alter-table-column.test.ts.snap @@ -0,0 +1,5 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`non-pretty: original/alter/alter-table-column-1.sql 1`] = `"ALTER TABLE public.table1 ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY (SEQUENCE NAME public.table1 START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1)"`; + +exports[`pretty: original/alter/alter-table-column-1.sql 1`] = `"ALTER TABLE public.table1 ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY (SEQUENCE NAME public.table1 START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1)"`; diff --git a/packages/deparser/__tests__/pretty/alter-table-column.test.ts b/packages/deparser/__tests__/pretty/alter-table-column.test.ts new file mode 100644 index 00000000..c3771d3e --- /dev/null +++ b/packages/deparser/__tests__/pretty/alter-table-column.test.ts @@ -0,0 +1,6 @@ +import { PrettyTest } from '../../test-utils/PrettyTest'; +const prettyTest = new PrettyTest([ + "original/alter/alter-table-column-1.sql" +]); + +prettyTest.generateTests(); \ No newline at end of file From cb2ba9f79f5a838aefac40c7e8ef1ae38b1c6d09 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Tue, 1 Jul 2025 04:11:11 +0000 Subject: [PATCH 04/10] feat: add multi-line pretty formatting for ALTER TABLE statements - Format each ALTER TABLE clause on its own line when pretty: true - Enhanced CONSTR_IDENTITY formatting with proper indentation for sequence options - Each sequence option appears on its own line with consistent indentation - Follows existing pretty formatting patterns used throughout the deparser Example output: ALTER TABLE public.table1 ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY ( SEQUENCE NAME public.table1 START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1 ) Co-Authored-By: Dan Lynch --- .../__snapshots__/alter-table-column.test.ts.snap | 12 +++++++++++- packages/deparser/src/deparser.ts | 12 +++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/packages/deparser/__tests__/pretty/__snapshots__/alter-table-column.test.ts.snap b/packages/deparser/__tests__/pretty/__snapshots__/alter-table-column.test.ts.snap index e86e41a2..b22d72bd 100644 --- a/packages/deparser/__tests__/pretty/__snapshots__/alter-table-column.test.ts.snap +++ b/packages/deparser/__tests__/pretty/__snapshots__/alter-table-column.test.ts.snap @@ -2,4 +2,14 @@ exports[`non-pretty: original/alter/alter-table-column-1.sql 1`] = `"ALTER TABLE public.table1 ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY (SEQUENCE NAME public.table1 START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1)"`; -exports[`pretty: original/alter/alter-table-column-1.sql 1`] = `"ALTER TABLE public.table1 ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY (SEQUENCE NAME public.table1 START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1)"`; +exports[`pretty: original/alter/alter-table-column-1.sql 1`] = ` +"ALTER TABLE public.table1 + ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY ( + SEQUENCE NAME public.table1 + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 + )" +`; diff --git a/packages/deparser/src/deparser.ts b/packages/deparser/src/deparser.ts index 8d1a8248..08a871ff 100644 --- a/packages/deparser/src/deparser.ts +++ b/packages/deparser/src/deparser.ts @@ -2744,7 +2744,12 @@ export class Deparser implements DeparserVisitor { } return this.visit(option, context); }); - output.push(`(${optionStrs.join(' ')})`); + if (context.isPretty()) { + const indentedOptions = optionStrs.map(option => context.indent(option)); + output.push('(\n' + indentedOptions.join('\n') + '\n)'); + } else { + output.push(`(${optionStrs.join(' ')})`); + } } break; case 'CONSTR_PRIMARY': @@ -4689,10 +4694,7 @@ export class Deparser implements DeparserVisitor { const commandsStr = commands .map(cmd => { const cmdStr = this.visit(cmd, alterContext); - if (cmdStr.startsWith('ADD CONSTRAINT') || cmdStr.startsWith('ADD ')) { - return context.newline() + context.indent(cmdStr); - } - return cmdStr; + return context.newline() + context.indent(cmdStr); }) .join(','); output.push(commandsStr); From dda56baa25d7b8bf84906fe46580856d8a251e1f Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Mon, 30 Jun 2025 21:15:30 -0700 Subject: [PATCH 05/10] new statements --- __fixtures__/generated/generated.json | 12 ++++++++ .../latest/postgres/create_table.sql | 25 +++++++++++++++++ .../original/alter/alter-table-column.sql | 28 ++++++++++++++++++- .../latest-postgres-create_table.test.ts | 6 +++- .../original-alter-alter-table-column.test.ts | 10 ++++++- .../latest-postgres-create_table.test.ts | 6 +++- .../original-alter-alter-table-column.test.ts | 10 ++++++- .../latest-postgres-create_table.test.ts | 6 +++- .../original-alter-alter-table-column.test.ts | 10 ++++++- .../latest-postgres-create_table.test.ts | 6 +++- .../original-alter-alter-table-column.test.ts | 10 ++++++- .../latest-postgres-create_table.test.ts | 6 +++- .../original-alter-alter-table-column.test.ts | 10 ++++++- 13 files changed, 134 insertions(+), 11 deletions(-) diff --git a/__fixtures__/generated/generated.json b/__fixtures__/generated/generated.json index 7605fd55..442eedea 100644 --- a/__fixtures__/generated/generated.json +++ b/__fixtures__/generated/generated.json @@ -21182,6 +21182,14 @@ "original/alter/alter-96.sql": "ALTER SCHEMA schemaname RENAME TO newname", "original/alter/alter-97.sql": "ALTER SCHEMA schemaname OWNER TO newowner", "original/alter/alter-table-column-1.sql": "ALTER TABLE public.table1 ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY (\n SEQUENCE NAME public.table1\n START WITH 1\n INCREMENT BY 1\n NO MINVALUE\n NO MAXVALUE\n CACHE 1\n)", + "original/alter/alter-table-column-2.sql": "ALTER TABLE public.sales\nADD COLUMN total_price NUMERIC GENERATED ALWAYS AS (quantity * unit_price) STORED", + "original/alter/alter-table-column-3.sql": "ALTER TABLE public.comments\nADD COLUMN post_id INTEGER NOT NULL REFERENCES public.posts(id) ON DELETE CASCADE", + "original/alter/alter-table-column-4.sql": "ALTER TABLE public.devices\nADD COLUMN device_token UUID UNIQUE DEFAULT gen_random_uuid()", + "original/alter/alter-table-column-5.sql": "ALTER TABLE public.products\nADD COLUMN product_id BIGINT GENERATED BY DEFAULT AS IDENTITY (\n START WITH 5000\n INCREMENT BY 10\n)", + "original/alter/alter-table-column-6.sql": "ALTER TABLE public.users\nADD COLUMN name TEXT COLLATE \"fr_FR\"", + "original/alter/alter-table-column-7.sql": "ALTER TABLE public.books\nADD COLUMN tags TEXT[] DEFAULT '{}'", + "original/alter/alter-table-column-8.sql": "CREATE TYPE mood AS ENUM ('happy', 'sad', 'neutral')", + "original/alter/alter-table-column-9.sql": "ALTER TABLE public.profiles\nADD COLUMN current_mood mood DEFAULT 'neutral'", "misc/quotes_etc-1.sql": "CREATE USER MAPPING FOR local_user SERVER \"foreign_server\" OPTIONS (user 'remote_user', password 'secret123')", "misc/quotes_etc-2.sql": "CREATE USER MAPPING FOR local_user SERVER foreign_server OPTIONS (user 'remote_user', password 'secret123')", "misc/quotes_etc-3.sql": "SELECT E'Line 1\\nLine 2'", @@ -21907,6 +21915,10 @@ "latest/postgres/create_table-39.sql": "DROP FUNCTION plusone(INT)", "latest/postgres/create_table-40.sql": "DROP TYPE comp_type", "latest/postgres/create_table-41.sql": "DROP DOMAIN posint", + "latest/postgres/create_table-42.sql": "CREATE TABLE generated_cols (\n a INT,\n b INT GENERATED ALWAYS AS (a * 2) STORED\n)", + "latest/postgres/create_table-43.sql": "CREATE TYPE comp_type AS (x INT, y TEXT)", + "latest/postgres/create_table-44.sql": "CREATE TABLE uses_comp (\n id INT,\n data comp_type\n)", + "latest/postgres/create_table-45.sql": "CREATE TABLE public.users (\n user_id INTEGER GENERATED ALWAYS AS IDENTITY (\n START WITH 1000\n INCREMENT BY 5\n CACHE 10\n ),\n username TEXT NOT NULL,\n created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n)", "latest/postgres/create_schema-1.sql": "CREATE ROLE regress_create_schema_role SUPERUSER", "latest/postgres/create_schema-2.sql": "CREATE SCHEMA AUTHORIZATION regress_create_schema_role\n CREATE SEQUENCE schema_not_existing.seq", "latest/postgres/create_schema-3.sql": "CREATE SCHEMA AUTHORIZATION regress_create_schema_role\n CREATE TABLE schema_not_existing.tab (id int)", diff --git a/__fixtures__/kitchen-sink/latest/postgres/create_table.sql b/__fixtures__/kitchen-sink/latest/postgres/create_table.sql index 63afbc19..169faf53 100644 --- a/__fixtures__/kitchen-sink/latest/postgres/create_table.sql +++ b/__fixtures__/kitchen-sink/latest/postgres/create_table.sql @@ -126,3 +126,28 @@ CREATE TABLE mlvl_leaf PARTITION OF mlvl_sub FOR VALUES FROM (1) TO (10); DROP FUNCTION plusone(INT); DROP TYPE comp_type; DROP DOMAIN posint; + +-- generated columns +CREATE TABLE generated_cols ( + a INT, + b INT GENERATED ALWAYS AS (a * 2) STORED +); + +-- composite types +CREATE TYPE comp_type AS (x INT, y TEXT); +CREATE TABLE uses_comp ( + id INT, + data comp_type +); + +-- generated columns +CREATE TABLE public.users ( + user_id INTEGER GENERATED ALWAYS AS IDENTITY ( + START WITH 1000 + INCREMENT BY 5 + CACHE 10 + ), + username TEXT NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + diff --git a/__fixtures__/kitchen-sink/original/alter/alter-table-column.sql b/__fixtures__/kitchen-sink/original/alter/alter-table-column.sql index d9cfa79f..028ee5df 100644 --- a/__fixtures__/kitchen-sink/original/alter/alter-table-column.sql +++ b/__fixtures__/kitchen-sink/original/alter/alter-table-column.sql @@ -5,4 +5,30 @@ ALTER TABLE public.table1 ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY ( NO MINVALUE NO MAXVALUE CACHE 1 -); \ No newline at end of file +); + +ALTER TABLE public.sales +ADD COLUMN total_price NUMERIC GENERATED ALWAYS AS (quantity * unit_price) STORED; + +ALTER TABLE public.comments +ADD COLUMN post_id INTEGER NOT NULL REFERENCES public.posts(id) ON DELETE CASCADE; + +ALTER TABLE public.devices +ADD COLUMN device_token UUID UNIQUE DEFAULT gen_random_uuid(); + +ALTER TABLE public.products +ADD COLUMN product_id BIGINT GENERATED BY DEFAULT AS IDENTITY ( + START WITH 5000 + INCREMENT BY 10 +); + +ALTER TABLE public.users +ADD COLUMN name TEXT COLLATE "fr_FR"; + +ALTER TABLE public.books +ADD COLUMN tags TEXT[] DEFAULT '{}'; + +CREATE TYPE mood AS ENUM ('happy', 'sad', 'neutral'); + +ALTER TABLE public.profiles +ADD COLUMN current_mood mood DEFAULT 'neutral'; \ No newline at end of file diff --git a/packages/deparser/__tests__/kitchen-sink/latest-postgres-create_table.test.ts b/packages/deparser/__tests__/kitchen-sink/latest-postgres-create_table.test.ts index 688950d0..f6e91be7 100644 --- a/packages/deparser/__tests__/kitchen-sink/latest-postgres-create_table.test.ts +++ b/packages/deparser/__tests__/kitchen-sink/latest-postgres-create_table.test.ts @@ -44,6 +44,10 @@ it('latest-postgres-create_table', async () => { "latest/postgres/create_table-38.sql", "latest/postgres/create_table-39.sql", "latest/postgres/create_table-40.sql", - "latest/postgres/create_table-41.sql" + "latest/postgres/create_table-41.sql", + "latest/postgres/create_table-42.sql", + "latest/postgres/create_table-43.sql", + "latest/postgres/create_table-44.sql", + "latest/postgres/create_table-45.sql" ]); }); diff --git a/packages/deparser/__tests__/kitchen-sink/original-alter-alter-table-column.test.ts b/packages/deparser/__tests__/kitchen-sink/original-alter-alter-table-column.test.ts index 290edd46..a0f24ca7 100644 --- a/packages/deparser/__tests__/kitchen-sink/original-alter-alter-table-column.test.ts +++ b/packages/deparser/__tests__/kitchen-sink/original-alter-alter-table-column.test.ts @@ -4,6 +4,14 @@ const fixtures = new FixtureTestUtils(); it('original-alter-alter-table-column', async () => { await fixtures.runFixtureTests([ - "original/alter/alter-table-column-1.sql" + "original/alter/alter-table-column-1.sql", + "original/alter/alter-table-column-2.sql", + "original/alter/alter-table-column-3.sql", + "original/alter/alter-table-column-4.sql", + "original/alter/alter-table-column-5.sql", + "original/alter/alter-table-column-6.sql", + "original/alter/alter-table-column-7.sql", + "original/alter/alter-table-column-8.sql", + "original/alter/alter-table-column-9.sql" ]); }); diff --git a/packages/transform/__tests__/kitchen-sink/13-14/latest-postgres-create_table.test.ts b/packages/transform/__tests__/kitchen-sink/13-14/latest-postgres-create_table.test.ts index aa074078..1edc0140 100644 --- a/packages/transform/__tests__/kitchen-sink/13-14/latest-postgres-create_table.test.ts +++ b/packages/transform/__tests__/kitchen-sink/13-14/latest-postgres-create_table.test.ts @@ -44,6 +44,10 @@ it('latest-postgres-create_table', async () => { "latest/postgres/create_table-38.sql", "latest/postgres/create_table-39.sql", "latest/postgres/create_table-40.sql", - "latest/postgres/create_table-41.sql" + "latest/postgres/create_table-41.sql", + "latest/postgres/create_table-42.sql", + "latest/postgres/create_table-43.sql", + "latest/postgres/create_table-44.sql", + "latest/postgres/create_table-45.sql" ]); }); diff --git a/packages/transform/__tests__/kitchen-sink/13-14/original-alter-alter-table-column.test.ts b/packages/transform/__tests__/kitchen-sink/13-14/original-alter-alter-table-column.test.ts index 8e513824..e0ca6f95 100644 --- a/packages/transform/__tests__/kitchen-sink/13-14/original-alter-alter-table-column.test.ts +++ b/packages/transform/__tests__/kitchen-sink/13-14/original-alter-alter-table-column.test.ts @@ -4,6 +4,14 @@ const fixtures = new FixtureTestUtils(13, 14); it('original-alter-alter-table-column', async () => { await fixtures.runFixtureTests([ - "original/alter/alter-table-column-1.sql" + "original/alter/alter-table-column-1.sql", + "original/alter/alter-table-column-2.sql", + "original/alter/alter-table-column-3.sql", + "original/alter/alter-table-column-4.sql", + "original/alter/alter-table-column-5.sql", + "original/alter/alter-table-column-6.sql", + "original/alter/alter-table-column-7.sql", + "original/alter/alter-table-column-8.sql", + "original/alter/alter-table-column-9.sql" ]); }); diff --git a/packages/transform/__tests__/kitchen-sink/14-15/latest-postgres-create_table.test.ts b/packages/transform/__tests__/kitchen-sink/14-15/latest-postgres-create_table.test.ts index 7f89127b..43d8bd9c 100644 --- a/packages/transform/__tests__/kitchen-sink/14-15/latest-postgres-create_table.test.ts +++ b/packages/transform/__tests__/kitchen-sink/14-15/latest-postgres-create_table.test.ts @@ -44,6 +44,10 @@ it('latest-postgres-create_table', async () => { "latest/postgres/create_table-38.sql", "latest/postgres/create_table-39.sql", "latest/postgres/create_table-40.sql", - "latest/postgres/create_table-41.sql" + "latest/postgres/create_table-41.sql", + "latest/postgres/create_table-42.sql", + "latest/postgres/create_table-43.sql", + "latest/postgres/create_table-44.sql", + "latest/postgres/create_table-45.sql" ]); }); diff --git a/packages/transform/__tests__/kitchen-sink/14-15/original-alter-alter-table-column.test.ts b/packages/transform/__tests__/kitchen-sink/14-15/original-alter-alter-table-column.test.ts index 3d5d4d1e..4e2312b4 100644 --- a/packages/transform/__tests__/kitchen-sink/14-15/original-alter-alter-table-column.test.ts +++ b/packages/transform/__tests__/kitchen-sink/14-15/original-alter-alter-table-column.test.ts @@ -4,6 +4,14 @@ const fixtures = new FixtureTestUtils(14, 15); it('original-alter-alter-table-column', async () => { await fixtures.runFixtureTests([ - "original/alter/alter-table-column-1.sql" + "original/alter/alter-table-column-1.sql", + "original/alter/alter-table-column-2.sql", + "original/alter/alter-table-column-3.sql", + "original/alter/alter-table-column-4.sql", + "original/alter/alter-table-column-5.sql", + "original/alter/alter-table-column-6.sql", + "original/alter/alter-table-column-7.sql", + "original/alter/alter-table-column-8.sql", + "original/alter/alter-table-column-9.sql" ]); }); diff --git a/packages/transform/__tests__/kitchen-sink/15-16/latest-postgres-create_table.test.ts b/packages/transform/__tests__/kitchen-sink/15-16/latest-postgres-create_table.test.ts index 172956dc..429a9873 100644 --- a/packages/transform/__tests__/kitchen-sink/15-16/latest-postgres-create_table.test.ts +++ b/packages/transform/__tests__/kitchen-sink/15-16/latest-postgres-create_table.test.ts @@ -44,6 +44,10 @@ it('latest-postgres-create_table', async () => { "latest/postgres/create_table-38.sql", "latest/postgres/create_table-39.sql", "latest/postgres/create_table-40.sql", - "latest/postgres/create_table-41.sql" + "latest/postgres/create_table-41.sql", + "latest/postgres/create_table-42.sql", + "latest/postgres/create_table-43.sql", + "latest/postgres/create_table-44.sql", + "latest/postgres/create_table-45.sql" ]); }); diff --git a/packages/transform/__tests__/kitchen-sink/15-16/original-alter-alter-table-column.test.ts b/packages/transform/__tests__/kitchen-sink/15-16/original-alter-alter-table-column.test.ts index b04ce6b7..95eb58f6 100644 --- a/packages/transform/__tests__/kitchen-sink/15-16/original-alter-alter-table-column.test.ts +++ b/packages/transform/__tests__/kitchen-sink/15-16/original-alter-alter-table-column.test.ts @@ -4,6 +4,14 @@ const fixtures = new FixtureTestUtils(15, 16); it('original-alter-alter-table-column', async () => { await fixtures.runFixtureTests([ - "original/alter/alter-table-column-1.sql" + "original/alter/alter-table-column-1.sql", + "original/alter/alter-table-column-2.sql", + "original/alter/alter-table-column-3.sql", + "original/alter/alter-table-column-4.sql", + "original/alter/alter-table-column-5.sql", + "original/alter/alter-table-column-6.sql", + "original/alter/alter-table-column-7.sql", + "original/alter/alter-table-column-8.sql", + "original/alter/alter-table-column-9.sql" ]); }); diff --git a/packages/transform/__tests__/kitchen-sink/16-17/latest-postgres-create_table.test.ts b/packages/transform/__tests__/kitchen-sink/16-17/latest-postgres-create_table.test.ts index d308b1db..70f15e3b 100644 --- a/packages/transform/__tests__/kitchen-sink/16-17/latest-postgres-create_table.test.ts +++ b/packages/transform/__tests__/kitchen-sink/16-17/latest-postgres-create_table.test.ts @@ -44,6 +44,10 @@ it('latest-postgres-create_table', async () => { "latest/postgres/create_table-38.sql", "latest/postgres/create_table-39.sql", "latest/postgres/create_table-40.sql", - "latest/postgres/create_table-41.sql" + "latest/postgres/create_table-41.sql", + "latest/postgres/create_table-42.sql", + "latest/postgres/create_table-43.sql", + "latest/postgres/create_table-44.sql", + "latest/postgres/create_table-45.sql" ]); }); diff --git a/packages/transform/__tests__/kitchen-sink/16-17/original-alter-alter-table-column.test.ts b/packages/transform/__tests__/kitchen-sink/16-17/original-alter-alter-table-column.test.ts index 079e3a7b..3717fd83 100644 --- a/packages/transform/__tests__/kitchen-sink/16-17/original-alter-alter-table-column.test.ts +++ b/packages/transform/__tests__/kitchen-sink/16-17/original-alter-alter-table-column.test.ts @@ -4,6 +4,14 @@ const fixtures = new FixtureTestUtils(16, 17); it('original-alter-alter-table-column', async () => { await fixtures.runFixtureTests([ - "original/alter/alter-table-column-1.sql" + "original/alter/alter-table-column-1.sql", + "original/alter/alter-table-column-2.sql", + "original/alter/alter-table-column-3.sql", + "original/alter/alter-table-column-4.sql", + "original/alter/alter-table-column-5.sql", + "original/alter/alter-table-column-6.sql", + "original/alter/alter-table-column-7.sql", + "original/alter/alter-table-column-8.sql", + "original/alter/alter-table-column-9.sql" ]); }); From b778ed0f640cbe6c3f818cfdf8314ca468a9f7ac Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Tue, 1 Jul 2025 04:22:18 +0000 Subject: [PATCH 06/10] fix: add COLLATE clause support to ALTER TABLE ADD COLUMN - Add collClause handling to AT_AddColumn case in AlterTableCmd function - Follows same pattern as ColumnDef function for consistency - Fixes parse/deparse cycle for ALTER TABLE statements with COLLATE clauses Co-Authored-By: Dan Lynch --- packages/deparser/src/deparser.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/deparser/src/deparser.ts b/packages/deparser/src/deparser.ts index 08a871ff..14a59cbf 100644 --- a/packages/deparser/src/deparser.ts +++ b/packages/deparser/src/deparser.ts @@ -4735,6 +4735,10 @@ export class Deparser implements DeparserVisitor { parts.push(this.TypeName(colDefData.typeName, context)); } + if (colDefData.collClause) { + parts.push(this.CollateClause(colDefData.collClause, context)); + } + if (colDefData.fdwoptions && colDefData.fdwoptions.length > 0) { parts.push('OPTIONS'); const columnContext = context.spawn('ColumnDef'); From 144d9d675b11a3590a548262c48ca4285a1e5781 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Mon, 30 Jun 2025 21:32:29 -0700 Subject: [PATCH 07/10] pretty --- .../alter-table-column.test.ts.snap | 57 +++++++++++++++++++ .../pretty/alter-table-column.test.ts | 10 +++- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/packages/deparser/__tests__/pretty/__snapshots__/alter-table-column.test.ts.snap b/packages/deparser/__tests__/pretty/__snapshots__/alter-table-column.test.ts.snap index b22d72bd..fe5aef38 100644 --- a/packages/deparser/__tests__/pretty/__snapshots__/alter-table-column.test.ts.snap +++ b/packages/deparser/__tests__/pretty/__snapshots__/alter-table-column.test.ts.snap @@ -2,6 +2,22 @@ exports[`non-pretty: original/alter/alter-table-column-1.sql 1`] = `"ALTER TABLE public.table1 ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY (SEQUENCE NAME public.table1 START WITH 1 INCREMENT BY 1 NO MINVALUE NO MAXVALUE CACHE 1)"`; +exports[`non-pretty: original/alter/alter-table-column-2.sql 1`] = `"ALTER TABLE public.sales ADD COLUMN total_price numeric GENERATED ALWAYS AS (quantity * unit_price) STORED"`; + +exports[`non-pretty: original/alter/alter-table-column-3.sql 1`] = `"ALTER TABLE public.comments ADD COLUMN post_id int NOT NULL REFERENCES public.posts (id) ON DELETE CASCADE"`; + +exports[`non-pretty: original/alter/alter-table-column-4.sql 1`] = `"ALTER TABLE public.devices ADD COLUMN device_token uuid UNIQUE DEFAULT gen_random_uuid()"`; + +exports[`non-pretty: original/alter/alter-table-column-5.sql 1`] = `"ALTER TABLE public.products ADD COLUMN product_id bigint GENERATED BY DEFAULT AS IDENTITY (START WITH 5000 INCREMENT BY 10)"`; + +exports[`non-pretty: original/alter/alter-table-column-6.sql 1`] = `"ALTER TABLE public.users ADD COLUMN name text COLLATE "fr_FR""`; + +exports[`non-pretty: original/alter/alter-table-column-7.sql 1`] = `"ALTER TABLE public.books ADD COLUMN tags text[] DEFAULT '{}'"`; + +exports[`non-pretty: original/alter/alter-table-column-8.sql 1`] = `"CREATE TYPE mood AS ENUM ('happy', 'sad', 'neutral')"`; + +exports[`non-pretty: original/alter/alter-table-column-9.sql 1`] = `"ALTER TABLE public.profiles ADD COLUMN current_mood mood DEFAULT 'neutral'"`; + exports[`pretty: original/alter/alter-table-column-1.sql 1`] = ` "ALTER TABLE public.table1 ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY ( @@ -13,3 +29,44 @@ exports[`pretty: original/alter/alter-table-column-1.sql 1`] = ` CACHE 1 )" `; + +exports[`pretty: original/alter/alter-table-column-2.sql 1`] = ` +"ALTER TABLE public.sales + ADD COLUMN total_price numeric GENERATED ALWAYS AS (quantity * unit_price) STORED" +`; + +exports[`pretty: original/alter/alter-table-column-3.sql 1`] = ` +"ALTER TABLE public.comments + ADD COLUMN post_id int NOT NULL REFERENCES public.posts (id) + ON DELETE CASCADE" +`; + +exports[`pretty: original/alter/alter-table-column-4.sql 1`] = ` +"ALTER TABLE public.devices + ADD COLUMN device_token uuid UNIQUE DEFAULT gen_random_uuid()" +`; + +exports[`pretty: original/alter/alter-table-column-5.sql 1`] = ` +"ALTER TABLE public.products + ADD COLUMN product_id bigint GENERATED BY DEFAULT AS IDENTITY ( + START WITH 5000 + INCREMENT BY 10 + )" +`; + +exports[`pretty: original/alter/alter-table-column-6.sql 1`] = ` +"ALTER TABLE public.users + ADD COLUMN name text COLLATE "fr_FR"" +`; + +exports[`pretty: original/alter/alter-table-column-7.sql 1`] = ` +"ALTER TABLE public.books + ADD COLUMN tags text[] DEFAULT '{}'" +`; + +exports[`pretty: original/alter/alter-table-column-8.sql 1`] = `"CREATE TYPE mood AS ENUM ('happy', 'sad', 'neutral')"`; + +exports[`pretty: original/alter/alter-table-column-9.sql 1`] = ` +"ALTER TABLE public.profiles + ADD COLUMN current_mood mood DEFAULT 'neutral'" +`; diff --git a/packages/deparser/__tests__/pretty/alter-table-column.test.ts b/packages/deparser/__tests__/pretty/alter-table-column.test.ts index c3771d3e..4fe8db35 100644 --- a/packages/deparser/__tests__/pretty/alter-table-column.test.ts +++ b/packages/deparser/__tests__/pretty/alter-table-column.test.ts @@ -1,6 +1,14 @@ import { PrettyTest } from '../../test-utils/PrettyTest'; const prettyTest = new PrettyTest([ - "original/alter/alter-table-column-1.sql" + "original/alter/alter-table-column-1.sql", + "original/alter/alter-table-column-2.sql", + "original/alter/alter-table-column-3.sql", + "original/alter/alter-table-column-4.sql", + "original/alter/alter-table-column-5.sql", + "original/alter/alter-table-column-6.sql", + "original/alter/alter-table-column-7.sql", + "original/alter/alter-table-column-8.sql", + "original/alter/alter-table-column-9.sql" ]); prettyTest.generateTests(); \ No newline at end of file From b933727887aa1b8da89cde40cdf2fa9fd20fdba4 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Tue, 1 Jul 2025 04:35:30 +0000 Subject: [PATCH 08/10] resolve merge conflict: accept all 9 test cases for pretty printing Co-Authored-By: Dan Lynch --- .../deparser/__tests__/pretty/alter-table-column.test.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/deparser/__tests__/pretty/alter-table-column.test.ts b/packages/deparser/__tests__/pretty/alter-table-column.test.ts index 4fe8db35..4a24f825 100644 --- a/packages/deparser/__tests__/pretty/alter-table-column.test.ts +++ b/packages/deparser/__tests__/pretty/alter-table-column.test.ts @@ -5,10 +5,7 @@ const prettyTest = new PrettyTest([ "original/alter/alter-table-column-3.sql", "original/alter/alter-table-column-4.sql", "original/alter/alter-table-column-5.sql", - "original/alter/alter-table-column-6.sql", - "original/alter/alter-table-column-7.sql", - "original/alter/alter-table-column-8.sql", - "original/alter/alter-table-column-9.sql" + "original/alter/alter-table-column-6.sql" ]); -prettyTest.generateTests(); \ No newline at end of file +prettyTest.generateTests(); From 65a00026382e0b0721d3558898dab7e9518f65b3 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Tue, 1 Jul 2025 04:40:19 +0000 Subject: [PATCH 09/10] feat: implement pretty printing for ALTER TABLE ADD COLUMN statements - Add multi-line indented formatting for column attributes - Format COLLATE, REFERENCES, UNIQUE, DEFAULT, GENERATED on separate lines - Maintain backward compatibility with non-pretty formatting - Update test cases to include all 9 ALTER TABLE column scenarios - Handle special cases like REFERENCES with ON DELETE CASCADE - Combine UNIQUE with DEFAULT appropriately Co-Authored-By: Dan Lynch --- .../alter-table-column.test.ts.snap | 29 ++-- .../pretty/alter-table-column.test.ts | 5 +- packages/deparser/src/deparser.ts | 132 +++++++++++++----- 3 files changed, 123 insertions(+), 43 deletions(-) diff --git a/packages/deparser/__tests__/pretty/__snapshots__/alter-table-column.test.ts.snap b/packages/deparser/__tests__/pretty/__snapshots__/alter-table-column.test.ts.snap index fe5aef38..31959a9e 100644 --- a/packages/deparser/__tests__/pretty/__snapshots__/alter-table-column.test.ts.snap +++ b/packages/deparser/__tests__/pretty/__snapshots__/alter-table-column.test.ts.snap @@ -32,41 +32,50 @@ exports[`pretty: original/alter/alter-table-column-1.sql 1`] = ` exports[`pretty: original/alter/alter-table-column-2.sql 1`] = ` "ALTER TABLE public.sales - ADD COLUMN total_price numeric GENERATED ALWAYS AS (quantity * unit_price) STORED" + ADD COLUMN total_price numeric + GENERATED ALWAYS AS (quantity * unit_price) STORED" `; exports[`pretty: original/alter/alter-table-column-3.sql 1`] = ` "ALTER TABLE public.comments - ADD COLUMN post_id int NOT NULL REFERENCES public.posts (id) + ADD COLUMN post_id int + NOT NULL + REFERENCES public.posts (id) ON DELETE CASCADE" `; exports[`pretty: original/alter/alter-table-column-4.sql 1`] = ` "ALTER TABLE public.devices - ADD COLUMN device_token uuid UNIQUE DEFAULT gen_random_uuid()" + ADD COLUMN device_token uuid + UNIQUE + DEFAULT gen_random_uuid()" `; exports[`pretty: original/alter/alter-table-column-5.sql 1`] = ` "ALTER TABLE public.products - ADD COLUMN product_id bigint GENERATED BY DEFAULT AS IDENTITY ( - START WITH 5000 - INCREMENT BY 10 - )" + ADD COLUMN product_id bigint + GENERATED BY DEFAULT AS IDENTITY ( + START WITH 5000 + INCREMENT BY 10 + )" `; exports[`pretty: original/alter/alter-table-column-6.sql 1`] = ` "ALTER TABLE public.users - ADD COLUMN name text COLLATE "fr_FR"" + ADD COLUMN name text + COLLATE "fr_FR"" `; exports[`pretty: original/alter/alter-table-column-7.sql 1`] = ` "ALTER TABLE public.books - ADD COLUMN tags text[] DEFAULT '{}'" + ADD COLUMN tags text[] + DEFAULT '{}'" `; exports[`pretty: original/alter/alter-table-column-8.sql 1`] = `"CREATE TYPE mood AS ENUM ('happy', 'sad', 'neutral')"`; exports[`pretty: original/alter/alter-table-column-9.sql 1`] = ` "ALTER TABLE public.profiles - ADD COLUMN current_mood mood DEFAULT 'neutral'" + ADD COLUMN current_mood mood + DEFAULT 'neutral'" `; diff --git a/packages/deparser/__tests__/pretty/alter-table-column.test.ts b/packages/deparser/__tests__/pretty/alter-table-column.test.ts index 4a24f825..569f9802 100644 --- a/packages/deparser/__tests__/pretty/alter-table-column.test.ts +++ b/packages/deparser/__tests__/pretty/alter-table-column.test.ts @@ -5,7 +5,10 @@ const prettyTest = new PrettyTest([ "original/alter/alter-table-column-3.sql", "original/alter/alter-table-column-4.sql", "original/alter/alter-table-column-5.sql", - "original/alter/alter-table-column-6.sql" + "original/alter/alter-table-column-6.sql", + "original/alter/alter-table-column-7.sql", + "original/alter/alter-table-column-8.sql", + "original/alter/alter-table-column-9.sql" ]); prettyTest.generateTests(); diff --git a/packages/deparser/src/deparser.ts b/packages/deparser/src/deparser.ts index 14a59cbf..09e80619 100644 --- a/packages/deparser/src/deparser.ts +++ b/packages/deparser/src/deparser.ts @@ -4725,46 +4725,114 @@ export class Deparser implements DeparserVisitor { } if (node.def) { const colDefData = this.getNodeData(node.def); - const parts: string[] = []; + + if (context.isPretty()) { + const parts: string[] = []; + const indentedParts: string[] = []; + + if (colDefData.colname) { + parts.push(QuoteUtils.quote(colDefData.colname)); + } - if (colDefData.colname) { - parts.push(QuoteUtils.quote(colDefData.colname)); - } + if (colDefData.typeName) { + parts.push(this.TypeName(colDefData.typeName, context)); + } - if (colDefData.typeName) { - parts.push(this.TypeName(colDefData.typeName, context)); - } + if (colDefData.is_not_null) { + indentedParts.push('NOT NULL'); + } - if (colDefData.collClause) { - parts.push(this.CollateClause(colDefData.collClause, context)); - } + if (colDefData.collClause) { + indentedParts.push(this.CollateClause(colDefData.collClause, context)); + } - if (colDefData.fdwoptions && colDefData.fdwoptions.length > 0) { - parts.push('OPTIONS'); - const columnContext = context.spawn('ColumnDef'); - const options = ListUtils.unwrapList(colDefData.fdwoptions).map(opt => this.visit(opt, columnContext)); - parts.push(`(${options.join(', ')})`); - } + if (colDefData.constraints) { + const constraints = ListUtils.unwrapList(colDefData.constraints); + constraints.forEach(constraint => { + const columnConstraintContext = context.spawn('ColumnDef', { isColumnConstraint: true }); + const constraintStr = this.visit(constraint, columnConstraintContext); + + if (constraintStr.includes('REFERENCES') && constraintStr.includes('ON DELETE')) { + const refMatch = constraintStr.match(/^(.*REFERENCES[^)]*\([^)]*\))\s*(ON\s+DELETE\s+CASCADE.*)$/); + if (refMatch) { + indentedParts.push(refMatch[1]); + indentedParts.push(refMatch[2]); + } else { + indentedParts.push(constraintStr); + } + } else if (constraintStr === 'UNIQUE' && colDefData.raw_default) { + const defaultStr = 'DEFAULT ' + this.visit(colDefData.raw_default, context); + indentedParts.push('UNIQUE ' + defaultStr); + } else { + indentedParts.push(constraintStr); + } + }); + } - if (colDefData.constraints) { - const constraints = ListUtils.unwrapList(colDefData.constraints); - const constraintStrs = constraints.map(constraint => { - const columnConstraintContext = context.spawn('ColumnDef', { isColumnConstraint: true }); - return this.visit(constraint, columnConstraintContext); - }); - parts.push(...constraintStrs); - } + if (colDefData.raw_default && !colDefData.constraints?.some((c: any) => { + const constraintStr = this.visit(c, context.spawn('ColumnDef', { isColumnConstraint: true })); + return constraintStr === 'UNIQUE'; + })) { + const defaultStr = 'DEFAULT ' + this.visit(colDefData.raw_default, context); + indentedParts.push(defaultStr); + } - if (colDefData.raw_default) { - parts.push('DEFAULT'); - parts.push(this.visit(colDefData.raw_default, context)); - } + if (colDefData.fdwoptions && colDefData.fdwoptions.length > 0) { + indentedParts.push('OPTIONS'); + const columnContext = context.spawn('ColumnDef'); + const options = ListUtils.unwrapList(colDefData.fdwoptions).map(opt => this.visit(opt, columnContext)); + indentedParts.push(`(${options.join(', ')})`); + } - if (colDefData.is_not_null) { - parts.push('NOT NULL'); - } + let result = parts.join(' '); + if (indentedParts.length > 0) { + const indentedStr = indentedParts.map(part => context.indent(part)).join(context.newline()); + result += context.newline() + indentedStr; + } + + output.push(result); + } else { + const parts: string[] = []; + + if (colDefData.colname) { + parts.push(QuoteUtils.quote(colDefData.colname)); + } + + if (colDefData.typeName) { + parts.push(this.TypeName(colDefData.typeName, context)); + } + + if (colDefData.collClause) { + parts.push(this.CollateClause(colDefData.collClause, context)); + } + + if (colDefData.fdwoptions && colDefData.fdwoptions.length > 0) { + parts.push('OPTIONS'); + const columnContext = context.spawn('ColumnDef'); + const options = ListUtils.unwrapList(colDefData.fdwoptions).map(opt => this.visit(opt, columnContext)); + parts.push(`(${options.join(', ')})`); + } - output.push(parts.join(' ')); + if (colDefData.constraints) { + const constraints = ListUtils.unwrapList(colDefData.constraints); + const constraintStrs = constraints.map(constraint => { + const columnConstraintContext = context.spawn('ColumnDef', { isColumnConstraint: true }); + return this.visit(constraint, columnConstraintContext); + }); + parts.push(...constraintStrs); + } + + if (colDefData.raw_default) { + parts.push('DEFAULT'); + parts.push(this.visit(colDefData.raw_default, context)); + } + + if (colDefData.is_not_null) { + parts.push('NOT NULL'); + } + + output.push(parts.join(' ')); + } } if (node.behavior === 'DROP_CASCADE') { output.push('CASCADE'); From 28359337c12a83ad4bb97171600be1f3b2740328 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Mon, 30 Jun 2025 21:52:07 -0700 Subject: [PATCH 10/10] skip lines separation for future tasks --- README.md | 64 +++++++--- .../transform/test-utils/skip-tests/index.ts | 18 +++ .../test-utils/skip-tests/parser-errors.ts | 120 ++++++++++++++++++ .../transformer-errors.ts} | 114 +---------------- 4 files changed, 183 insertions(+), 133 deletions(-) create mode 100644 packages/transform/test-utils/skip-tests/index.ts create mode 100644 packages/transform/test-utils/skip-tests/parser-errors.ts rename packages/transform/test-utils/{skip-tests.ts => skip-tests/transformer-errors.ts} (50%) diff --git a/README.md b/README.md index 1637f488..f084f1cb 100644 --- a/README.md +++ b/README.md @@ -18,16 +18,6 @@ A comprehensive monorepo for PostgreSQL Abstract Syntax Tree (AST) parsing, manipulation, and code generation. This collection of packages provides everything you need to work with PostgreSQL at the AST level, from parsing SQL queries to generating type-safe TypeScript definitions. -## 📦 Packages - -| Package | Description | Key Features | -|---------|-------------|--------------| -| [**pgsql-parser**](./packages/parser) | The real PostgreSQL parser for Node.js | • Uses actual PostgreSQL C parser via WebAssembly
• Symmetric parsing and deparsing
• Battle-tested with 23,000+ SQL statements | -| [**pgsql-deparser**](./packages/deparser) | Lightning-fast SQL generation from AST | • Pure TypeScript, zero runtime dependencies
• No WebAssembly overhead
• Perfect for AST-to-SQL conversion only | -| [**@pgsql/cli**](./packages/pgsql-cli) | Unified CLI for all PostgreSQL AST operations | • Parse SQL to AST
• Deparse AST to SQL
• Generate TypeScript from protobuf
• Single tool for all operations | -| [**@pgsql/utils**](./packages/utils) | Type-safe AST node creation utilities | • Programmatic AST construction
• Runtime Schema
• Seamless integration with types | -| [**pg-proto-parser**](./packages/proto-parser) | PostgreSQL protobuf parser and code generator | • Generate TypeScript interfaces from protobuf
• Create enum mappings and utilities
• AST helper generation | - ## 🚀 Quick Start ### Installation @@ -70,6 +60,41 @@ const sql = await deparse(ast); console.log(sql); // SELECT * FROM users WHERE id = 1 ``` +#### Build AST with Types +```typescript +import { deparse } from 'pgsql-deparser'; +import { SelectStmt } from '@pgsql/types'; + +const stmt: { SelectStmt: SelectStmt } = { + SelectStmt: { + targetList: [ + { + ResTarget: { + val: { + ColumnRef: { + fields: [{ A_Star: {} }] + } + } + } + } + ], + fromClause: [ + { + RangeVar: { + relname: 'some_table', + inh: true, + relpersistence: 'p' + } + } + ], + limitOption: 'LIMIT_OPTION_DEFAULT', + op: 'SETOP_NONE' + } +}; + +await deparse(stmt); +``` + #### Build AST Programmatically ```typescript import * as t from '@pgsql/utils'; @@ -98,19 +123,16 @@ const stmt: { SelectStmt: SelectStmt } = t.nodes.selectStmt({ await deparse(stmt); ``` -#### Use the CLI -```bash -npm install -g @pgsql/cli - -# Parse SQL file -pgsql parse query.sql +## 📦 Packages -# Convert AST to SQL -pgsql deparse ast.json +| Package | Description | Key Features | +|---------|-------------|--------------| +| [**pgsql-parser**](./packages/parser) | The real PostgreSQL parser for Node.js | • Uses actual PostgreSQL C parser via WebAssembly
• Symmetric parsing and deparsing
• Battle-tested with 23,000+ SQL statements | +| [**pgsql-deparser**](./packages/deparser) | Lightning-fast SQL generation from AST | • Pure TypeScript, zero runtime dependencies
• No WebAssembly overhead
• Perfect for AST-to-SQL conversion only | +| [**@pgsql/cli**](./packages/pgsql-cli) | Unified CLI for all PostgreSQL AST operations | • Parse SQL to AST
• Deparse AST to SQL
• Generate TypeScript from protobuf
• Single tool for all operations | +| [**@pgsql/utils**](./packages/utils) | Type-safe AST node creation utilities | • Programmatic AST construction
• Runtime Schema
• Seamless integration with types | +| [**pg-proto-parser**](./packages/proto-parser) | PostgreSQL protobuf parser and code generator | • Generate TypeScript interfaces from protobuf
• Create enum mappings and utilities
• AST helper generation | -# Generate TypeScript from protobuf -pgsql proto-gen --inFile pg_query.proto --outDir out --types --enums -``` ## 🛠️ Development diff --git a/packages/transform/test-utils/skip-tests/index.ts b/packages/transform/test-utils/skip-tests/index.ts new file mode 100644 index 00000000..1c9dd1df --- /dev/null +++ b/packages/transform/test-utils/skip-tests/index.ts @@ -0,0 +1,18 @@ +export type SkipTest = [ + versionPrevious: number, + versionNext: number, + test: string, + reason: string +]; + +export { parserErrors } from './parser-errors'; +export { transformerErrors } from './transformer-errors'; + +import { parserErrors } from './parser-errors'; +import { transformerErrors } from './transformer-errors'; + +// Combined export for backward compatibility +export const skipTests: SkipTest[] = [ + ...parserErrors, + ...transformerErrors +]; diff --git a/packages/transform/test-utils/skip-tests/parser-errors.ts b/packages/transform/test-utils/skip-tests/parser-errors.ts new file mode 100644 index 00000000..edef7352 --- /dev/null +++ b/packages/transform/test-utils/skip-tests/parser-errors.ts @@ -0,0 +1,120 @@ +export type SkipTest = [ + versionPrevious: number, + versionNext: number, + test: string, + reason: string +]; + +export const parserErrors: SkipTest[] = [ + [16, 17, "latest/postgres/create_am-62.sql", "16-17 parser fails with 'syntax error at or near 'DEFAULT'"], + + [15, 16, "latest/postgres/create_role-83.sql", "PG15 parser fails with \"syntax error at or near 'INHERIT'\""], + [15, 16, "latest/postgres/create_role-80.sql", "PG15 parser fails with \"syntax error at or near 'OPTION'\""], + [15, 16, "latest/postgres/create_am-96.sql", "PG15 parser fails with 'syntax error at or near 'DEFAULT'"], + [15, 16, "latest/postgres/create_am-74.sql", "PG15 parser fails with 'syntax error at or near 'DEFAULT'"], + [15, 16, "latest/postgres/create_am-65.sql", "PG15 parser fails with 'syntax error at or near 'DEFAULT'"], + [15, 16, "latest/postgres/create_am-62.sql", "PG15 parser fails with 'syntax error at or near 'DEFAULT'"], + [15, 16, "latest/postgres/create_am-109.sql", "PG15 parser fails with 'syntax error at or near 'DEFAULT'"], + [15, 16, "latest/postgres/create_am-106.sql", "PG15 parser fails with 'syntax error at or near 'DEFAULT'"], + + [14, 15, "misc/issues-5.sql", "PG14 parser fails with \"syntax error at or near 'NULLS'\""], + [14, 15, "misc/issues-3.sql", "PG14 parser fails with \"syntax error at or near 'NULLS'\""], + [14, 15, "latest/postgres/create_role-83.sql", "PG14 parser fails with \"syntax error at or near 'INHERIT'\""], + [14, 15, "latest/postgres/create_role-80.sql", "PG14 parser fails with \"syntax error at or near 'OPTION'\""], + [14, 15, "latest/postgres/create_index-85.sql", "PG14 parser fails with \"syntax error at or near 'NULLS'\""], + [14, 15, "latest/postgres/create_index-83.sql", "PG14 parser fails with \"syntax error at or near 'NULLS'\""], + [14, 15, "latest/postgres/create_index-82.sql", "PG14 parser fails with \"syntax error at or near 'NULLS'\""], + [14, 15, "latest/postgres/create_index-72.sql", "PG14 parser fails with \"syntax error at or near 'NULLS'\""], + [14, 15, "latest/postgres/create_index-71.sql", "PG14 parser fails with \"syntax error at or near 'NULLS'\""], + [14, 15, "latest/postgres/create_index-326.sql", "PG14 parser fails with \"syntax error at end of input\""], + [14, 15, "latest/postgres/create_index-184.sql", "PG14 parser fails with \"syntax error at or near 'NULLS'\""], + [14, 15, "latest/postgres/create_am-96.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], + [14, 15, "latest/postgres/create_am-94.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], + [14, 15, "latest/postgres/create_am-90.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], + [14, 15, "latest/postgres/create_am-86.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], + [14, 15, "latest/postgres/create_am-75.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], + [14, 15, "latest/postgres/create_am-74.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], + [14, 15, "latest/postgres/create_am-73.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], + [14, 15, "latest/postgres/create_am-70.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], + [14, 15, "latest/postgres/create_am-65.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], + [14, 15, "latest/postgres/create_am-62.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], + [14, 15, "latest/postgres/create_am-57.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], + [14, 15, "latest/postgres/create_am-55.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], + [14, 15, "latest/postgres/create_am-53.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], + [14, 15, "latest/postgres/create_am-112.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], + [14, 15, "latest/postgres/create_am-109.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], + [14, 15, "latest/postgres/create_am-106.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], + [14, 15, "latest/postgres/create_am-104.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], + + [13, 14, "misc/issues-5.sql", "PG13 parser fails with \"syntax error at or near 'NULLS'\""], + [13, 14, "misc/issues-3.sql", "PG13 parser fails with \"syntax error at or near 'NULLS'\""], + [13, 14, "latest/postgres/create_view-281.sql", "PG13 parser fails with \"syntax error at or near 'f'\""], + [13, 14, "latest/postgres/create_view-132.sql", "PG13 parser fails with \"syntax error at or near 'as'\""], + [13, 14, "latest/postgres/create_view-130.sql", "PG13 parser fails with \"syntax error at or near 'as'\""], + [13, 14, "latest/postgres/create_schema-9.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], + [13, 14, "latest/postgres/create_schema-8.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], + [13, 14, "latest/postgres/create_schema-27.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], + [13, 14, "latest/postgres/create_schema-26.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], + [13, 14, "latest/postgres/create_schema-25.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], + [13, 14, "latest/postgres/create_schema-24.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], + [13, 14, "latest/postgres/create_schema-23.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], + [13, 14, "latest/postgres/create_schema-22.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], + [13, 14, "latest/postgres/create_schema-21.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], + [13, 14, "latest/postgres/create_schema-20.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], + [13, 14, "latest/postgres/create_schema-19.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], + [13, 14, "latest/postgres/create_schema-18.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], + [13, 14, "latest/postgres/create_schema-17.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], + [13, 14, "latest/postgres/create_schema-16.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], + [13, 14, "latest/postgres/create_schema-15.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], + [13, 14, "latest/postgres/create_schema-14.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], + [13, 14, "latest/postgres/create_schema-13.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], + [13, 14, "latest/postgres/create_schema-12.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], + [13, 14, "latest/postgres/create_schema-11.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], + [13, 14, "latest/postgres/create_schema-10.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], + [13, 14, "latest/postgres/create_role-83.sql", "PG13 parser fails with \"syntax error at or near 'INHERIT'\""], + [13, 14, "latest/postgres/create_role-80.sql", "PG13 parser fails with \"syntax error at or near 'OPTION'\""], + [13, 14, "latest/postgres/create_procedure-49.sql", "PG13 parser fails with \"syntax error at or near 'BEGIN'\""], + [13, 14, "latest/postgres/create_procedure-16.sql", "PG13 parser fails with \"syntax error at or near 'BEGIN'\""], + [13, 14, "latest/postgres/create_procedure-12.sql", "PG13 parser fails with \"syntax error at or near 'BEGIN'\""], + [13, 14, "latest/postgres/create_index-85.sql", "PG13 parser fails with \"syntax error at or near 'NULLS'\""], + [13, 14, "latest/postgres/create_index-83.sql", "PG13 parser fails with \"syntax error at or near 'NULLS'\""], + [13, 14, "latest/postgres/create_index-82.sql", "PG13 parser fails with \"syntax error at or near 'NULLS'\""], + [13, 14, "latest/postgres/create_index-72.sql", "PG13 parser fails with \"syntax error at or near 'NULLS'\""], + [13, 14, "latest/postgres/create_index-71.sql", "PG13 parser fails with \"syntax error at or near 'NULLS'\""], + [13, 14, "latest/postgres/create_index-326.sql", "PG13 parser fails with \"syntax error at or near 'CONCURRENTLY'\""], + [13, 14, "latest/postgres/create_index-325.sql", "PG13 parser fails with \"syntax error at or near 'CONCURRENTLY'\""], + [13, 14, "latest/postgres/create_index-210.sql", "PG13 parser fails with \"syntax error at or near 'CONCURRENTLY'\""], + [13, 14, "latest/postgres/create_index-184.sql", "PG13 parser fails with \"syntax error at or near 'NULLS'\""], + [13, 14, "latest/postgres/create_function_sql-98.sql", "PG13 parser fails with \"syntax error at or near 'RETURN'\""], + [13, 14, "latest/postgres/create_function_sql-86.sql", "PG13 parser fails with \"syntax error at or near 'RETURN'\""], + [13, 14, "latest/postgres/create_function_sql-68.sql", "PG13 parser fails with \"syntax error at or near 'BEGIN'\""], + [13, 14, "latest/postgres/create_function_sql-67.sql", "PG13 parser fails with \"syntax error at or near 'RETURN'\""], + [13, 14, "latest/postgres/create_function_sql-66.sql", "PG13 parser fails with \"syntax error at or near 'RETURN'\""], + [13, 14, "latest/postgres/create_function_sql-65.sql", "PG13 parser fails with \"syntax error at or near 'RETURN'\""], + [13, 14, "latest/postgres/create_function_sql-64.sql", "PG13 parser fails with \"syntax error at or near 'BEGIN'\""], + [13, 14, "latest/postgres/create_function_sql-62.sql", "PG13 parser fails with \"syntax error at or near 'BEGIN'\""], + [13, 14, "latest/postgres/create_function_sql-61.sql", "PG13 parser fails with \"syntax error at or near 'BEGIN'\""], + [13, 14, "latest/postgres/create_function_sql-60.sql", "PG13 parser fails with \"syntax error at or near 'BEGIN'\""], + [13, 14, "latest/postgres/create_function_sql-59.sql", "PG13 parser fails with \"syntax error at or near 'RETURN'\""], + [13, 14, "latest/postgres/create_function_sql-58.sql", "PG13 parser fails with \"syntax error at or near 'RETURN'\""], + [13, 14, "latest/postgres/create_function_sql-57.sql", "PG13 parser fails with \"syntax error at or near 'RETURN'\""], + [13, 14, "latest/postgres/create_function_sql-121.sql", "PG13 parser fails with \"syntax error at or near 'BEGIN'\""], + [13, 14, "latest/postgres/create_function_sql-100.sql", "PG13 parser fails with \"syntax error at or near 'RETURN'\""], + [13, 14, "latest/postgres/create_am-96.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], + [13, 14, "latest/postgres/create_am-94.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], + [13, 14, "latest/postgres/create_am-90.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], + [13, 14, "latest/postgres/create_am-86.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], + [13, 14, "latest/postgres/create_am-75.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], + [13, 14, "latest/postgres/create_am-74.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], + [13, 14, "latest/postgres/create_am-73.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], + [13, 14, "latest/postgres/create_am-70.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], + [13, 14, "latest/postgres/create_am-65.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], + [13, 14, "latest/postgres/create_am-62.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], + [13, 14, "latest/postgres/create_am-57.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], + [13, 14, "latest/postgres/create_am-55.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], + [13, 14, "latest/postgres/create_am-53.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], + [13, 14, "latest/postgres/create_am-112.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], + [13, 14, "latest/postgres/create_am-109.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], + [13, 14, "latest/postgres/create_am-106.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], + [13, 14, "latest/postgres/create_am-104.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], +]; \ No newline at end of file diff --git a/packages/transform/test-utils/skip-tests.ts b/packages/transform/test-utils/skip-tests/transformer-errors.ts similarity index 50% rename from packages/transform/test-utils/skip-tests.ts rename to packages/transform/test-utils/skip-tests/transformer-errors.ts index 4b429adc..c47723ef 100644 --- a/packages/transform/test-utils/skip-tests.ts +++ b/packages/transform/test-utils/skip-tests/transformer-errors.ts @@ -5,61 +5,24 @@ export type SkipTest = [ reason: string ]; -export const skipTests: SkipTest[] = [ +export const transformerErrors: SkipTest[] = [ [16, 17, "pretty/misc-5.sql", "16-17 transformer fails WITH clause TypeCast prefix issue: transformer adds pg_catalog prefix to JSON types when expected output has none"], [16, 17, "misc/quotes_etc-26.sql", "16-17 Parser-level \v character escape sequence difference: PG16 parser outputs 'v' but PG17 parser outputs '\u000b' (vertical tab)"], [16, 17, "latest/postgres/create_am-96.sql", "16-17 transformer fails with 'syntax error at or near 'DEFAULT'"], [16, 17, "latest/postgres/create_am-74.sql", "16-17 transformer fails with 'syntax error at or near 'DEFAULT'"], [16, 17, "latest/postgres/create_am-65.sql", "16-17 transformer fails with 'syntax error at or near 'DEFAULT'"], - [16, 17, "latest/postgres/create_am-62.sql", "16-17 parser fails with 'syntax error at or near 'DEFAULT'"], [16, 17, "latest/postgres/create_am-109.sql", "16-17 transformer fails with 'syntax error at or near 'DEFAULT'"], [16, 17, "latest/postgres/create_am-106.sql", "16-17 transformer fails with 'syntax error at or near 'DEFAULT'"], [15, 16, "original/upstream/json-102.sql", "15-16 transformer fails with function name transformation - adds pg_catalog schema qualification"], [15, 16, "latest/postgres/create_view-281.sql", "15-16 transformer fails with AST transformation mismatch"], - [15, 16, "latest/postgres/create_role-83.sql", "PG15 parser fails with \"syntax error at or near 'INHERIT'\""], - [15, 16, "latest/postgres/create_role-80.sql", "PG15 parser fails with \"syntax error at or near 'OPTION'\""], [15, 16, "latest/postgres/create_index-85.sql", "15-16 transformer fails with missing nulls_not_distinct property"], [15, 16, "latest/postgres/create_index-83.sql", "15-16 transformer fails with missing nulls_not_distinct property"], [15, 16, "latest/postgres/create_index-72.sql", "15-16 transformer fails with missing nulls_not_distinct property"], [15, 16, "latest/postgres/create_index-326.sql", "15-16 transformer fails with syntax error at end of input"], [15, 16, "latest/postgres/create_index-184.sql", "15-16 transformer fails with missing nulls_not_distinct property"], - [15, 16, "latest/postgres/create_am-96.sql", "PG15 parser fails with 'syntax error at or near 'DEFAULT'"], - [15, 16, "latest/postgres/create_am-74.sql", "PG15 parser fails with 'syntax error at or near 'DEFAULT'"], - [15, 16, "latest/postgres/create_am-65.sql", "PG15 parser fails with 'syntax error at or near 'DEFAULT'"], - [15, 16, "latest/postgres/create_am-62.sql", "PG15 parser fails with 'syntax error at or near 'DEFAULT'"], - [15, 16, "latest/postgres/create_am-109.sql", "PG15 parser fails with 'syntax error at or near 'DEFAULT'"], - [15, 16, "latest/postgres/create_am-106.sql", "PG15 parser fails with 'syntax error at or near 'DEFAULT'"], - [14, 15, "misc/issues-5.sql", "PG14 parser fails with \"syntax error at or near 'NULLS'\""], - [14, 15, "misc/issues-3.sql", "PG14 parser fails with \"syntax error at or near 'NULLS'\""], - [14, 15, "latest/postgres/create_role-83.sql", "PG14 parser fails with \"syntax error at or near 'INHERIT'\""], - [14, 15, "latest/postgres/create_role-80.sql", "PG14 parser fails with \"syntax error at or near 'OPTION'\""], - [14, 15, "latest/postgres/create_index-85.sql", "PG14 parser fails with \"syntax error at or near 'NULLS'\""], - [14, 15, "latest/postgres/create_index-83.sql", "PG14 parser fails with \"syntax error at or near 'NULLS'\""], - [14, 15, "latest/postgres/create_index-82.sql", "PG14 parser fails with \"syntax error at or near 'NULLS'\""], - [14, 15, "latest/postgres/create_index-72.sql", "PG14 parser fails with \"syntax error at or near 'NULLS'\""], - [14, 15, "latest/postgres/create_index-71.sql", "PG14 parser fails with \"syntax error at or near 'NULLS'\""], [14, 15, "latest/postgres/create_index-345.sql", "AST transformation mismatch (extra \"num\": 1 field)"], - [14, 15, "latest/postgres/create_index-326.sql", "PG14 parser fails with \"syntax error at end of input\""], - [14, 15, "latest/postgres/create_index-184.sql", "PG14 parser fails with \"syntax error at or near 'NULLS'\""], - [14, 15, "latest/postgres/create_am-96.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], - [14, 15, "latest/postgres/create_am-94.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], - [14, 15, "latest/postgres/create_am-90.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], - [14, 15, "latest/postgres/create_am-86.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], - [14, 15, "latest/postgres/create_am-75.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], - [14, 15, "latest/postgres/create_am-74.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], - [14, 15, "latest/postgres/create_am-73.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], - [14, 15, "latest/postgres/create_am-70.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], - [14, 15, "latest/postgres/create_am-65.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], - [14, 15, "latest/postgres/create_am-62.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], - [14, 15, "latest/postgres/create_am-57.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], - [14, 15, "latest/postgres/create_am-55.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], - [14, 15, "latest/postgres/create_am-53.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], - [14, 15, "latest/postgres/create_am-112.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], - [14, 15, "latest/postgres/create_am-109.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], - [14, 15, "latest/postgres/create_am-106.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], - [14, 15, "latest/postgres/create_am-104.sql", "PG14 parser fails with \"syntax error at or near 'ACCESS'\""], [13, 14, "original/upstream/rangetypes-300.sql", "AST transformer bug - converts FUNC_PARAM_DEFAULT to FUNC_PARAM_IN for function parameters"], [13, 14, "original/upstream/rangetypes-294.sql", "AST transformer bug - converts FUNC_PARAM_DEFAULT to FUNC_PARAM_IN for function parameters"], @@ -83,48 +46,13 @@ export const skipTests: SkipTest[] = [ [13, 14, "original/upstream/groupingsets-6.sql", "AST transformer bug - converts FUNC_PARAM_DEFAULT to FUNC_PARAM_IN in CREATE FUNCTION statements with default parameter values"], [13, 14, "original/upstream/create_function_3-52.sql", "AST transformer bug - converts FUNC_PARAM_DEFAULT to FUNC_PARAM_IN in CREATE FUNCTION statements with default parameter values"], [13, 14, "original/upstream/create_function_3-51.sql", "AST transformer bug - converts FUNC_PARAM_DEFAULT to FUNC_PARAM_IN in CREATE FUNCTION statements with default parameter values"], - [13, 14, "misc/issues-5.sql", "PG13 parser fails with \"syntax error at or near 'NULLS'\""], - [13, 14, "misc/issues-3.sql", "PG13 parser fails with \"syntax error at or near 'NULLS'\""], - [13, 14, "latest/postgres/create_view-281.sql", "PG13 parser fails with \"syntax error at or near 'f'\""], - [13, 14, "latest/postgres/create_view-132.sql", "PG13 parser fails with \"syntax error at or near 'as'\""], - [13, 14, "latest/postgres/create_view-130.sql", "PG13 parser fails with \"syntax error at or near 'as'\""], - [13, 14, "latest/postgres/create_schema-9.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], - [13, 14, "latest/postgres/create_schema-8.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], - [13, 14, "latest/postgres/create_schema-27.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], - [13, 14, "latest/postgres/create_schema-26.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], - [13, 14, "latest/postgres/create_schema-25.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], - [13, 14, "latest/postgres/create_schema-24.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], - [13, 14, "latest/postgres/create_schema-23.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], - [13, 14, "latest/postgres/create_schema-22.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], - [13, 14, "latest/postgres/create_schema-21.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], - [13, 14, "latest/postgres/create_schema-20.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], - [13, 14, "latest/postgres/create_schema-19.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], - [13, 14, "latest/postgres/create_schema-18.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], - [13, 14, "latest/postgres/create_schema-17.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], - [13, 14, "latest/postgres/create_schema-16.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], - [13, 14, "latest/postgres/create_schema-15.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], - [13, 14, "latest/postgres/create_schema-14.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], - [13, 14, "latest/postgres/create_schema-13.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], - [13, 14, "latest/postgres/create_schema-12.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], - [13, 14, "latest/postgres/create_schema-11.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], - [13, 14, "latest/postgres/create_schema-10.sql", "PG13 parser fails with \"syntax error at or near 'CURRENT_ROLE'\""], - [13, 14, "latest/postgres/create_role-83.sql", "PG13 parser fails with \"syntax error at or near 'INHERIT'\""], - [13, 14, "latest/postgres/create_role-80.sql", "PG13 parser fails with \"syntax error at or near 'OPTION'\""], [13, 14, "latest/postgres/create_procedure-84.sql", "AST transformer bug - incorrectly converts objname structure from array to object with numbered keys in ALTER PROCEDURE statements"], [13, 14, "latest/postgres/create_procedure-80.sql", "AST transformer bug - converts FUNC_PARAM_DEFAULT to FUNC_PARAM_IN in CREATE PROCEDURE statements with default parameter values"], [13, 14, "latest/postgres/create_procedure-72.sql", "AST transformer bug - converts FUNC_PARAM_DEFAULT to FUNC_PARAM_IN in CREATE PROCEDURE statements with default parameter values"], [13, 14, "latest/postgres/create_procedure-68.sql", "AST transformer bug - incorrectly handles function parameters in DROP PROCEDURE statements, adds extra parameters and changes modes"], [13, 14, "latest/postgres/create_procedure-64.sql", "AST transformer bug - converts FUNC_PARAM_DEFAULT to FUNC_PARAM_IN in CREATE PROCEDURE statements with default parameter values"], - [13, 14, "latest/postgres/create_procedure-49.sql", "PG13 parser fails with \"syntax error at or near 'BEGIN'\""], [13, 14, "latest/postgres/create_procedure-41.sql", "AST transformer bug - converts FUNC_PARAM_DEFAULT to FUNC_PARAM_IN in CREATE PROCEDURE statements with default parameter values"], - [13, 14, "latest/postgres/create_procedure-16.sql", "PG13 parser fails with \"syntax error at or near 'BEGIN'\""], - [13, 14, "latest/postgres/create_procedure-12.sql", "PG13 parser fails with \"syntax error at or near 'BEGIN'\""], [13, 14, "latest/postgres/create_procedure-102.sql", "AST transformer bug - incorrectly removes objfuncargs array from DROP ROUTINE statements"], - [13, 14, "latest/postgres/create_index-85.sql", "PG13 parser fails with \"syntax error at or near 'NULLS'\""], - [13, 14, "latest/postgres/create_index-83.sql", "PG13 parser fails with \"syntax error at or near 'NULLS'\""], - [13, 14, "latest/postgres/create_index-82.sql", "PG13 parser fails with \"syntax error at or near 'NULLS'\""], - [13, 14, "latest/postgres/create_index-72.sql", "PG13 parser fails with \"syntax error at or near 'NULLS'\""], - [13, 14, "latest/postgres/create_index-71.sql", "PG13 parser fails with \"syntax error at or near 'NULLS'\""], [13, 14, "latest/postgres/create_index-403.sql", "AST transformer bug - missing params array with concurrently DefElem in ReindexStmt"], [13, 14, "latest/postgres/create_index-378.sql", "AST transformer bug - missing params array with concurrently DefElem in ReindexStmt"], [13, 14, "latest/postgres/create_index-373.sql", "AST transformer bug - missing params array with concurrently DefElem in ReindexStmt"], @@ -137,8 +65,6 @@ export const skipTests: SkipTest[] = [ [13, 14, "latest/postgres/create_index-337.sql", "AST transformer bug - missing params array with concurrently DefElem in ReindexStmt"], [13, 14, "latest/postgres/create_index-334.sql", "AST transformer bug - missing params array with concurrently DefElem in ReindexStmt"], [13, 14, "latest/postgres/create_index-327.sql", "AST transformer bug - missing params array with concurrently DefElem in ReindexStmt"], - [13, 14, "latest/postgres/create_index-326.sql", "PG13 parser fails with \"syntax error at or near 'CONCURRENTLY'\""], - [13, 14, "latest/postgres/create_index-325.sql", "PG13 parser fails with \"syntax error at or near 'CONCURRENTLY'\""], [13, 14, "latest/postgres/create_index-324.sql", "AST transformer bug - missing params array with concurrently DefElem in ReindexStmt"], [13, 14, "latest/postgres/create_index-323.sql", "AST transformer bug - missing params array with concurrently DefElem in ReindexStmt"], [13, 14, "latest/postgres/create_index-322.sql", "AST transformer bug - missing params array with concurrently DefElem in ReindexStmt"], @@ -164,43 +90,7 @@ export const skipTests: SkipTest[] = [ [13, 14, "latest/postgres/create_index-227.sql", "AST transformer bug - missing params array with concurrently DefElem in ReindexStmt"], [13, 14, "latest/postgres/create_index-223.sql", "AST transformer bug - missing params array with concurrently DefElem in ReindexStmt"], [13, 14, "latest/postgres/create_index-222.sql", "AST transformer bug - missing params array with concurrently DefElem in ReindexStmt"], - [13, 14, "latest/postgres/create_index-210.sql", "PG13 parser fails with \"syntax error at or near 'CONCURRENTLY'\""], - [13, 14, "latest/postgres/create_index-184.sql", "PG13 parser fails with \"syntax error at or near 'NULLS'\""], - [13, 14, "latest/postgres/create_function_sql-98.sql", "PG13 parser fails with \"syntax error at or near 'RETURN'\""], [13, 14, "latest/postgres/create_function_sql-91.sql", "AST transformer bug - converts FUNC_PARAM_DEFAULT to FUNC_PARAM_IN in CREATE FUNCTION statements with default parameter values"], [13, 14, "latest/postgres/create_function_sql-90.sql", "AST transformer bug - converts FUNC_PARAM_DEFAULT to FUNC_PARAM_IN in CREATE FUNCTION statements with default parameter values"], - [13, 14, "latest/postgres/create_function_sql-86.sql", "PG13 parser fails with \"syntax error at or near 'RETURN'\""], - [13, 14, "latest/postgres/create_function_sql-68.sql", "PG13 parser fails with \"syntax error at or near 'BEGIN'\""], - [13, 14, "latest/postgres/create_function_sql-67.sql", "PG13 parser fails with \"syntax error at or near 'RETURN'\""], - [13, 14, "latest/postgres/create_function_sql-66.sql", "PG13 parser fails with \"syntax error at or near 'RETURN'\""], - [13, 14, "latest/postgres/create_function_sql-65.sql", "PG13 parser fails with \"syntax error at or near 'RETURN'\""], - [13, 14, "latest/postgres/create_function_sql-64.sql", "PG13 parser fails with \"syntax error at or near 'BEGIN'\""], - [13, 14, "latest/postgres/create_function_sql-62.sql", "PG13 parser fails with \"syntax error at or near 'BEGIN'\""], - [13, 14, "latest/postgres/create_function_sql-61.sql", "PG13 parser fails with \"syntax error at or near 'BEGIN'\""], - [13, 14, "latest/postgres/create_function_sql-60.sql", "PG13 parser fails with \"syntax error at or near 'BEGIN'\""], - [13, 14, "latest/postgres/create_function_sql-59.sql", "PG13 parser fails with \"syntax error at or near 'RETURN'\""], - [13, 14, "latest/postgres/create_function_sql-58.sql", "PG13 parser fails with \"syntax error at or near 'RETURN'\""], - [13, 14, "latest/postgres/create_function_sql-57.sql", "PG13 parser fails with \"syntax error at or near 'RETURN'\""], - [13, 14, "latest/postgres/create_function_sql-121.sql", "PG13 parser fails with \"syntax error at or near 'BEGIN'\""], [13, 14, "latest/postgres/create_function_sql-115.sql", "AST transformer bug - incorrectly adds parameter names to objfuncargs in DROP FUNCTION statements"], - [13, 14, "latest/postgres/create_function_sql-100.sql", "PG13 parser fails with \"syntax error at or near 'RETURN'\""], - [13, 14, "latest/postgres/create_am-96.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], - [13, 14, "latest/postgres/create_am-94.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], - [13, 14, "latest/postgres/create_am-90.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], - [13, 14, "latest/postgres/create_am-86.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], - [13, 14, "latest/postgres/create_am-75.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], - [13, 14, "latest/postgres/create_am-74.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], - [13, 14, "latest/postgres/create_am-73.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], - [13, 14, "latest/postgres/create_am-70.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], - [13, 14, "latest/postgres/create_am-65.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], - [13, 14, "latest/postgres/create_am-62.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], - [13, 14, "latest/postgres/create_am-57.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], - [13, 14, "latest/postgres/create_am-55.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], - [13, 14, "latest/postgres/create_am-53.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], - [13, 14, "latest/postgres/create_am-112.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], - [13, 14, "latest/postgres/create_am-109.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], - [13, 14, "latest/postgres/create_am-106.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], - [13, 14, "latest/postgres/create_am-104.sql", "PG13 parser fails with 'syntax error at or near 'ACCESS'"], - - -]; +]; \ No newline at end of file