Skip to content

Commit 68b1381

Browse files
authored
Merge pull request #286 from constructive-io/devin/1773537015-exclude-where-clause
fix(deparser): fix EXCLUDE WHERE, TypeName quoting, VALUES formatting; fix CI + pg-proto-parser
2 parents c764e21 + 452c69a commit 68b1381

13 files changed

Lines changed: 2757 additions & 5620 deletions

File tree

.github/workflows/run-tests.yaml

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,28 @@
11
name: Parser tests
22
on:
33
push:
4+
branches: [main]
45
pull_request:
56
workflow_dispatch:
67

8+
concurrency:
9+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
10+
cancel-in-progress: true
11+
712
jobs:
813
parser-tests:
914
runs-on: ubuntu-latest
1015
strategy:
16+
fail-fast: false
1117
matrix:
1218
package:
13-
- deparser
14-
- parser
19+
- pgsql-deparser
20+
- pgsql-parser
1521
- plpgsql-deparser
1622
- plpgsql-parser
17-
- pgsql-cli
18-
- proto-parser
19-
- transform
20-
- traverse
21-
- utils
23+
- pg-proto-parser
24+
- '@pgsql/quotes'
25+
- '@pgsql/transform'
2226
steps:
2327
- name: checkout
2428
uses: actions/checkout@v3

__fixtures__/generated/generated.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21330,6 +21330,7 @@
2133021330
"misc/issues-15.sql": "select \"A\" from \"table_name\"",
2133121331
"misc/issues-16.sql": "select \"AA\" from \"table_name\"",
2133221332
"misc/issues-17.sql": "SELECT CAST(t.date AT TIME ZONE $$America/New_York$$ AS text)::date FROM tbl t",
21333+
"misc/issues-18.sql": "CREATE TABLE test_exclude_where (\n id uuid PRIMARY KEY,\n database_id uuid NOT NULL,\n status text NOT NULL DEFAULT 'pending',\n EXCLUDE USING btree (database_id WITH =)\n WHERE (status = 'pending')\n)",
2133321334
"misc/inflection-1.sql": "CREATE SCHEMA inflection",
2133421335
"misc/inflection-2.sql": "GRANT USAGE ON SCHEMA inflection TO PUBLIC",
2133521336
"misc/inflection-3.sql": "ALTER DEFAULT PRIVILEGES IN SCHEMA inflection \n GRANT EXECUTE ON FUNCTIONS TO PUBLIC",

__fixtures__/kitchen-sink/misc/issues.sql

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,15 @@ select "A" from "table_name";
7474
select "AA" from "table_name";
7575

7676
-- https://github.com/constructive-io/pgsql-parser/issues/217
77-
SELECT CAST(t.date AT TIME ZONE $$America/New_York$$ AS text)::date FROM tbl t;
77+
SELECT CAST(t.date AT TIME ZONE $$America/New_York$$ AS text)::date FROM tbl t;
78+
79+
-- https://github.com/constructive-io/pgsql-parser/issues/287
80+
-- EXCLUDE constraint with WHERE clause (partial exclusion constraint)
81+
-- The deparser drops the WHERE clause from EXCLUDE USING ... WHERE (...)
82+
CREATE TABLE test_exclude_where (
83+
id uuid PRIMARY KEY,
84+
database_id uuid NOT NULL,
85+
status text NOT NULL DEFAULT 'pending',
86+
EXCLUDE USING btree (database_id WITH =)
87+
WHERE (status = 'pending')
88+
);

packages/deparser/__tests__/kitchen-sink/misc-issues.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ it('misc-issues', async () => {
2020
"misc/issues-14.sql",
2121
"misc/issues-15.sql",
2222
"misc/issues-16.sql",
23-
"misc/issues-17.sql"
23+
"misc/issues-17.sql",
24+
"misc/issues-18.sql"
2425
]);
2526
});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
import { FixtureTestUtils } from '../../test-utils';
3+
const fixtures = new FixtureTestUtils();
4+
5+
it('original-tables-foreign_table', async () => {
6+
await fixtures.runFixtureTests([
7+
"original/tables/foreign_table-1.sql"
8+
]);
9+
});
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
import { FixtureTestUtils } from '../../test-utils';
3+
const fixtures = new FixtureTestUtils();
4+
5+
it('pretty-formatting', async () => {
6+
await fixtures.runFixtureTests([
7+
"pretty/formatting-1.sql",
8+
"pretty/formatting-2.sql",
9+
"pretty/formatting-3.sql",
10+
"pretty/formatting-4.sql",
11+
"pretty/formatting-5.sql",
12+
"pretty/formatting-6.sql",
13+
"pretty/formatting-7.sql",
14+
"pretty/formatting-8.sql",
15+
"pretty/formatting-9.sql"
16+
]);
17+
});
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
2+
import { FixtureTestUtils } from '../../test-utils';
3+
const fixtures = new FixtureTestUtils();
4+
5+
it('pretty-quoting', async () => {
6+
await fixtures.runFixtureTests([
7+
"pretty/quoting-1.sql",
8+
"pretty/quoting-2.sql",
9+
"pretty/quoting-3.sql",
10+
"pretty/quoting-4.sql",
11+
"pretty/quoting-5.sql",
12+
"pretty/quoting-6.sql",
13+
"pretty/quoting-7.sql",
14+
"pretty/quoting-8.sql",
15+
"pretty/quoting-9.sql",
16+
"pretty/quoting-10.sql",
17+
"pretty/quoting-11.sql",
18+
"pretty/quoting-12.sql",
19+
"pretty/quoting-13.sql",
20+
"pretty/quoting-14.sql",
21+
"pretty/quoting-15.sql",
22+
"pretty/quoting-16.sql"
23+
]);
24+
});

packages/deparser/src/deparser.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -563,9 +563,7 @@ export class Deparser implements DeparserVisitor {
563563
output.push('VALUES');
564564
const lists = ListUtils.unwrapList(node.valuesLists).map(list => {
565565
const values = ListUtils.unwrapList(list).map(val => this.visit(val as Node, context));
566-
// Put each value on its own line for pretty printing
567-
const indentedValues = values.map(val => context.indent(val));
568-
return '(\n' + indentedValues.join(',\n') + '\n)';
566+
return context.parens(values.join(', '));
569567
});
570568
const indentedTuples = lists.map(tuple => {
571569
if (this.containsMultilineStringLiteral(tuple)) {
@@ -1892,7 +1890,7 @@ export class Deparser implements DeparserVisitor {
18921890
return output.join(' ');
18931891
}
18941892

1895-
let result = mods(typeName, args);
1893+
let result = mods(QuoteUtils.quoteIdentifierTypeName(typeName), args);
18961894

18971895
if (node.arrayBounds && node.arrayBounds.length > 0) {
18981896
result += formatArrayBounds(node.arrayBounds);
@@ -3067,6 +3065,10 @@ export class Deparser implements DeparserVisitor {
30673065
});
30683066
output.push(`(${exclusionElements.join(', ')})`);
30693067
}
3068+
if (node.where_clause) {
3069+
output.push('WHERE');
3070+
output.push(context.parens(this.visit(node.where_clause as any, context)));
3071+
}
30703072
break;
30713073
}
30723074

@@ -11445,3 +11447,4 @@ export class Deparser implements DeparserVisitor {
1144511447
return stringLiteralRegex.test(content);
1144611448
}
1144711449
}
11450+

packages/plpgsql-deparser/__tests__/__snapshots__/hydrate-demo.test.ts.snap

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -140,23 +140,7 @@ BEGIN
140140
note,
141141
updated_at
142142
) VALUES
143-
(
144-
p_org_id,
145-
p_user_id,
146-
p_from_ts,
147-
p_to_ts,
148-
p_currency,
149-
v_orders_scanned,
150-
v_gross,
151-
v_discount,
152-
v_tax,
153-
v_net,
154-
v_avg,
155-
v_top_sku,
156-
v_top_sku_qty,
157-
p_note,
158-
now()
159-
) ON CONFLICT (org_id, user_id, period_from, period_to, currency) DO UPDATE SET
143+
(p_org_id, p_user_id, p_from_ts, p_to_ts, p_currency, v_orders_scanned, v_gross, v_discount, v_tax, v_net, v_avg, v_top_sku, v_top_sku_qty, p_note, now()) ON CONFLICT (org_id, user_id, period_from, period_to, currency) DO UPDATE SET
160144
orders_scanned = excluded.orders_scanned,
161145
gross_total = excluded.gross_total,
162146
discount_total = excluded.discount_total,

packages/plpgsql-deparser/__tests__/__snapshots__/schema-rename-mapped.test.ts.snap

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -209,13 +209,7 @@ CREATE FUNCTION myapp_v2.audit_changes() RETURNS trigger LANGUAGE plpgsql AS $$B
209209
new_data,
210210
changed_at
211211
) VALUES
212-
(
213-
tg_table_name,
214-
tg_op,
215-
to_json(old),
216-
to_json(new),
217-
now()
218-
);
212+
(tg_table_name, tg_op, to_json(old), to_json(new), now());
219213
IF tg_op = 'DELETE' THEN
220214
RETURN old;
221215
END IF;
@@ -232,11 +226,7 @@ CREATE FUNCTION myapp_v2.update_user_status(
232226
status,
233227
changed_at
234228
) VALUES
235-
(
236-
p_user_id,
237-
p_status,
238-
now()
239-
);
229+
(p_user_id, p_status, now());
240230
RETURN;
241231
END$$;
242232
@@ -323,10 +313,7 @@ BEGIN
323313
user_id,
324314
created_at
325315
) VALUES
326-
(
327-
new.id,
328-
now()
329-
);
316+
(new.id, now());
330317
ELSE
331318
UPDATE myapp_v2.profiles SET updated_at = now() WHERE user_id = new.id;
332319
END IF;
@@ -412,10 +399,7 @@ BEGIN
412399
item_id,
413400
processed_at
414401
) VALUES
415-
(
416-
item.id,
417-
now()
418-
);
402+
(item.id, now());
419403
UPDATE myapp_v2.batch_items SET status = 'processed' WHERE id = item.id;
420404
END LOOP;
421405
UPDATE myapp_v2.batches SET status = 'completed',completed_at = now() WHERE id = p_batch_id;

0 commit comments

Comments
 (0)