From 73e79c5904c5fc0ab96fdb21ffcfb79e19262fff Mon Sep 17 00:00:00 2001 From: Dan Lynch Date: Sun, 22 Jun 2025 22:37:15 -0700 Subject: [PATCH] parens for complex stmts --- __fixtures__/generated/generated.json | 1 + __fixtures__/kitchen-sink/misc/issues.sql | 5 ++- .../kitchen-sink/misc-issues.test.ts | 3 +- packages/deparser/src/deparser.ts | 36 +++++++++++++++---- 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/__fixtures__/generated/generated.json b/__fixtures__/generated/generated.json index b8a01c00..fa80b858 100644 --- a/__fixtures__/generated/generated.json +++ b/__fixtures__/generated/generated.json @@ -21097,6 +21097,7 @@ "misc/issues-11.sql": "COMMENT ON COLUMN \"foo\".\"whatever\" IS $$\nSomething blah, this data may have chars like '\\n' and '\\r' in it.\n$$", "misc/issues-12.sql": "SELECT * from foo.bar.baz", "misc/issues-13.sql": "CREATE AGGREGATE json_agg_strict(anyelement)(\n SFUNC = json_agg_strict_sfunc,\n STYPE = jsonb,\n FINALFUNC = json_agg_strict_finalfunc,\n INITCOND = '[]'\n)", + "misc/issues-14.sql": "SELECT (1 IS NOT NULL) IS DISTINCT FROM (2 IS NOT NULL)", "misc/inflection-1.sql": "CREATE SCHEMA inflection", "misc/inflection-2.sql": "GRANT USAGE ON SCHEMA inflection TO PUBLIC", "misc/inflection-3.sql": "ALTER DEFAULT PRIVILEGES IN SCHEMA inflection \n GRANT EXECUTE ON FUNCTIONS TO PUBLIC", diff --git a/__fixtures__/kitchen-sink/misc/issues.sql b/__fixtures__/kitchen-sink/misc/issues.sql index f85de085..dd8e2820 100644 --- a/__fixtures__/kitchen-sink/misc/issues.sql +++ b/__fixtures__/kitchen-sink/misc/issues.sql @@ -64,4 +64,7 @@ CREATE AGGREGATE json_agg_strict(anyelement)( STYPE = jsonb, FINALFUNC = json_agg_strict_finalfunc, INITCOND = '[]' -); \ No newline at end of file +); + +-- https://github.com/launchql/pgsql-parser/issues/62 +SELECT (1 IS NOT NULL) IS DISTINCT FROM (2 IS NOT NULL); \ No newline at end of file diff --git a/packages/deparser/__tests__/kitchen-sink/misc-issues.test.ts b/packages/deparser/__tests__/kitchen-sink/misc-issues.test.ts index 01ac29c3..662c9f68 100644 --- a/packages/deparser/__tests__/kitchen-sink/misc-issues.test.ts +++ b/packages/deparser/__tests__/kitchen-sink/misc-issues.test.ts @@ -16,6 +16,7 @@ it('misc-issues', async () => { "misc/issues-10.sql", "misc/issues-11.sql", "misc/issues-12.sql", - "misc/issues-13.sql" + "misc/issues-13.sql", + "misc/issues-14.sql" ]); }); diff --git a/packages/deparser/src/deparser.ts b/packages/deparser/src/deparser.ts index eaa883fb..fa7807c3 100644 --- a/packages/deparser/src/deparser.ts +++ b/packages/deparser/src/deparser.ts @@ -438,18 +438,42 @@ export class Deparser implements DeparserVisitor { 'ALL', this.formatter.parens(this.visit(rexpr, context)) ]); - case 'AEXPR_DISTINCT': + case 'AEXPR_DISTINCT': { + let leftExpr = this.visit(lexpr, context); + let rightExpr = this.visit(rexpr, context); + + // Add parentheses for complex expressions + if (lexpr && this.isComplexExpression(lexpr)) { + leftExpr = this.formatter.parens(leftExpr); + } + if (rexpr && this.isComplexExpression(rexpr)) { + rightExpr = this.formatter.parens(rightExpr); + } + return this.formatter.format([ - this.visit(lexpr, context), + leftExpr, 'IS DISTINCT FROM', - this.visit(rexpr, context) + rightExpr ]); - case 'AEXPR_NOT_DISTINCT': + } + case 'AEXPR_NOT_DISTINCT': { + let leftExpr = this.visit(lexpr, context); + let rightExpr = this.visit(rexpr, context); + + // Add parentheses for complex expressions + if (lexpr && this.isComplexExpression(lexpr)) { + leftExpr = this.formatter.parens(leftExpr); + } + if (rexpr && this.isComplexExpression(rexpr)) { + rightExpr = this.formatter.parens(rightExpr); + } + return this.formatter.format([ - this.visit(lexpr, context), + leftExpr, 'IS NOT DISTINCT FROM', - this.visit(rexpr, context) + rightExpr ]); + } case 'AEXPR_NULLIF': return this.formatter.format([ 'NULLIF',