From 28e747b73668f64162f80de08fcc95f905007306 Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Sat, 11 Jul 2026 01:14:37 +0000 Subject: [PATCH] test: add generated-column fixtures and fix AT_SetExpression/AT_DropExpression deparsing - Add __fixtures__/kitchen-sink/misc/generated-columns.sql covering CREATE, ADD, SET, DROP, and DROP IF EXISTS for generated columns - Fix AT_SetExpression to emit SET EXPRESSION AS (expr) - Fix AT_DropExpression to emit DROP EXPRESSION IF EXISTS when missing_ok is true - Regenerate generated.json and kitchen-sink test file --- __fixtures__/generated/generated.json | 8 ++++ .../kitchen-sink/misc/generated-columns.sql | 41 +++++++++++++++++++ .../misc-generated-columns.test.ts | 16 ++++++++ packages/deparser/src/deparser.ts | 6 ++- 4 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 __fixtures__/kitchen-sink/misc/generated-columns.sql create mode 100644 packages/deparser/__tests__/kitchen-sink/misc-generated-columns.test.ts diff --git a/__fixtures__/generated/generated.json b/__fixtures__/generated/generated.json index 12905d11..654ea697 100644 --- a/__fixtures__/generated/generated.json +++ b/__fixtures__/generated/generated.json @@ -21372,6 +21372,14 @@ "misc/indexes-11.sql": "DROP INDEX CONCURRENTLY IF EXISTS my_index CASCADE", "misc/indexes-12.sql": "CREATE UNIQUE INDEX new_unique_idx ON new_example(a, b) INCLUDE (c)", "misc/indexes-13.sql": "CREATE INDEX CONCURRENTLY idx_with_operator ON boom.merkle_tree USING GIN ( name gin_trgm_ops ( param1 = 32, param2 = true) )", + "misc/generated-columns-1.sql": "CREATE TABLE generated_misc_test (\n a INT,\n b INT,\n c INT GENERATED ALWAYS AS (a + b) STORED\n)", + "misc/generated-columns-2.sql": "CREATE TABLE generated_func_test (\n name TEXT,\n name_upper TEXT GENERATED ALWAYS AS (upper(name)) STORED\n)", + "misc/generated-columns-3.sql": "CREATE TABLE generated_numeric_test (\n quantity INT,\n unit_price NUMERIC(10, 2),\n total_price NUMERIC(10, 2) GENERATED ALWAYS AS (quantity * unit_price) STORED NOT NULL UNIQUE\n)", + "misc/generated-columns-4.sql": "CREATE TABLE generated_case_test (\n flag BOOLEAN,\n result INT GENERATED ALWAYS AS (CASE WHEN flag THEN 1 ELSE 0 END) STORED\n)", + "misc/generated-columns-5.sql": "ALTER TABLE generated_misc_test\nADD COLUMN d INT GENERATED ALWAYS AS (a + b + c) STORED", + "misc/generated-columns-6.sql": "ALTER TABLE generated_misc_test\nALTER COLUMN c SET EXPRESSION AS (a - b)", + "misc/generated-columns-7.sql": "ALTER TABLE generated_misc_test\nALTER COLUMN c DROP EXPRESSION", + "misc/generated-columns-8.sql": "ALTER TABLE generated_misc_test\nALTER COLUMN c DROP EXPRESSION IF EXISTS", "misc/extract-1.sql": "SELECT EXTRACT(EPOCH FROM now())", "misc/extract-2.sql": "SELECT EXTRACT(EPOCH FROM DATE '1970-01-01')", "misc/extract-3.sql": "SELECT EXTRACT(EPOCH FROM TIMESTAMP '1970-01-01')", diff --git a/__fixtures__/kitchen-sink/misc/generated-columns.sql b/__fixtures__/kitchen-sink/misc/generated-columns.sql new file mode 100644 index 00000000..1a941467 --- /dev/null +++ b/__fixtures__/kitchen-sink/misc/generated-columns.sql @@ -0,0 +1,41 @@ +-- 1. CREATE TABLE with a generated column (arithmetic expression) +CREATE TABLE generated_misc_test ( + a INT, + b INT, + c INT GENERATED ALWAYS AS (a + b) STORED +); + +-- 2. Generated column with a function call +CREATE TABLE generated_func_test ( + name TEXT, + name_upper TEXT GENERATED ALWAYS AS (upper(name)) STORED +); + +-- 3. Generated column with type modifier and NOT NULL/UNIQUE +CREATE TABLE generated_numeric_test ( + quantity INT, + unit_price NUMERIC(10, 2), + total_price NUMERIC(10, 2) GENERATED ALWAYS AS (quantity * unit_price) STORED NOT NULL UNIQUE +); + +-- 4. Generated column with a CASE expression +CREATE TABLE generated_case_test ( + flag BOOLEAN, + result INT GENERATED ALWAYS AS (CASE WHEN flag THEN 1 ELSE 0 END) STORED +); + +-- 5. ALTER TABLE ADD COLUMN generated +ALTER TABLE generated_misc_test +ADD COLUMN d INT GENERATED ALWAYS AS (a + b + c) STORED; + +-- 6. ALTER TABLE SET EXPRESSION (new expression for an existing generated column) +ALTER TABLE generated_misc_test +ALTER COLUMN c SET EXPRESSION AS (a - b); + +-- 7. ALTER TABLE DROP EXPRESSION +ALTER TABLE generated_misc_test +ALTER COLUMN c DROP EXPRESSION; + +-- 8. ALTER TABLE DROP EXPRESSION IF EXISTS +ALTER TABLE generated_misc_test +ALTER COLUMN c DROP EXPRESSION IF EXISTS; diff --git a/packages/deparser/__tests__/kitchen-sink/misc-generated-columns.test.ts b/packages/deparser/__tests__/kitchen-sink/misc-generated-columns.test.ts new file mode 100644 index 00000000..a97e6370 --- /dev/null +++ b/packages/deparser/__tests__/kitchen-sink/misc-generated-columns.test.ts @@ -0,0 +1,16 @@ + +import { FixtureTestUtils } from '../../test-utils'; +const fixtures = new FixtureTestUtils(); + +it('misc-generated-columns', async () => { + await fixtures.runFixtureTests([ + "misc/generated-columns-1.sql", + "misc/generated-columns-2.sql", + "misc/generated-columns-3.sql", + "misc/generated-columns-4.sql", + "misc/generated-columns-5.sql", + "misc/generated-columns-6.sql", + "misc/generated-columns-7.sql", + "misc/generated-columns-8.sql" +]); +}); diff --git a/packages/deparser/src/deparser.ts b/packages/deparser/src/deparser.ts index e073b976..ff34e10e 100644 --- a/packages/deparser/src/deparser.ts +++ b/packages/deparser/src/deparser.ts @@ -5339,7 +5339,8 @@ export class Deparser implements DeparserVisitor { } output.push('SET EXPRESSION'); if (node.def) { - output.push(this.visit(node.def, context)); + output.push('AS'); + output.push(context.parens(this.visit(node.def, context))); } break; case 'AT_DropExpression': @@ -5348,6 +5349,9 @@ export class Deparser implements DeparserVisitor { output.push(QuoteUtils.quoteIdentifier(node.name)); } output.push('DROP EXPRESSION'); + if (node.missing_ok) { + output.push('IF EXISTS'); + } break; case 'AT_CheckNotNull': output.push('ALTER COLUMN');