pgsql-deparser 16.0.0 → 17.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +45 -88
  2. package/deparser.d.ts +297 -0
  3. package/{deparser/deparser.js → deparser.js} +110 -435
  4. package/esm/{deparser/deparser.js → deparser.js} +110 -435
  5. package/esm/index.js +3 -15
  6. package/esm/utils/index.js +90 -0
  7. package/esm/{deparser/utils → utils}/list-utils.js +0 -4
  8. package/esm/{deparser/utils → utils}/quote-utils.js +0 -34
  9. package/esm/utils/sql-formatter.js +23 -0
  10. package/esm/{deparser/visitors → visitors}/base.js +0 -4
  11. package/index.d.ts +3 -9
  12. package/index.js +4 -16
  13. package/package.json +27 -14
  14. package/utils/index.d.ts +4 -0
  15. package/utils/index.js +97 -0
  16. package/{deparser/utils → utils}/list-utils.d.ts +0 -4
  17. package/{deparser/utils → utils}/list-utils.js +0 -4
  18. package/utils/quote-utils.d.ts +5 -0
  19. package/{deparser/utils → utils}/quote-utils.js +0 -34
  20. package/{deparser/utils → utils}/sql-formatter.d.ts +1 -7
  21. package/{deparser/utils → utils}/sql-formatter.js +2 -15
  22. package/{deparser/visitors → visitors}/base.d.ts +5 -8
  23. package/{deparser/visitors → visitors}/base.js +0 -4
  24. package/deparser/deparser.d.ts +0 -301
  25. package/deparser/index.d.ts +0 -9
  26. package/deparser/index.js +0 -17
  27. package/deparser/utils/quote-utils.d.ts +0 -24
  28. package/esm/deparser/index.js +0 -13
  29. package/esm/deparser/utils/sql-formatter.js +0 -36
  30. package/esm/v16-to-v17-direct.js +0 -44
  31. package/esm/v16-to-v17.js +0 -1488
  32. package/v16-to-v17-direct.d.ts +0 -21
  33. package/v16-to-v17-direct.js +0 -48
  34. package/v16-to-v17.d.ts +0 -638
  35. package/v16-to-v17.js +0 -1492
@@ -1,7 +1,3 @@
1
- /**
2
- * Auto-generated file with types stripped for better tree-shaking
3
- * DO NOT EDIT - Generated by strip-deparser-types.ts
4
- */
5
1
  import { SqlFormatter } from './utils/sql-formatter';
6
2
  import { QuoteUtils } from './utils/quote-utils';
7
3
  import { ListUtils } from './utils/list-utils';
@@ -52,7 +48,7 @@ export class Deparser {
52
48
  tree;
53
49
  options;
54
50
  constructor(tree, opts = {}) {
55
- this.formatter = new SqlFormatter(opts.newline, opts.tab, opts.pretty);
51
+ this.formatter = new SqlFormatter(opts.newline, opts.tab);
56
52
  // Set default options
57
53
  this.options = {
58
54
  functionDelimiter: '$$',
@@ -185,25 +181,23 @@ export class Deparser {
185
181
  }
186
182
  if (!node.op || node.op === 'SETOP_NONE') {
187
183
  if (node.valuesLists == null) {
188
- if (!this.formatter.isPretty() || !node.targetList) {
189
- output.push('SELECT');
190
- }
184
+ output.push('SELECT');
191
185
  }
192
186
  }
193
187
  else {
194
188
  const leftStmt = this.SelectStmt(node.larg, context);
195
189
  const rightStmt = this.SelectStmt(node.rarg, context);
196
190
  // Add parentheses if the operand is a set operation OR has ORDER BY/LIMIT clauses OR has WITH clause
197
- const leftNeedsParens = node.larg && (((node.larg).op && (node.larg).op !== 'SETOP_NONE') ||
198
- (node.larg).sortClause ||
199
- (node.larg).limitCount ||
200
- (node.larg).limitOffset ||
201
- (node.larg).withClause);
202
- const rightNeedsParens = node.rarg && (((node.rarg).op && (node.rarg).op !== 'SETOP_NONE') ||
203
- (node.rarg).sortClause ||
204
- (node.rarg).limitCount ||
205
- (node.rarg).limitOffset ||
206
- (node.rarg).withClause);
191
+ const leftNeedsParens = node.larg && ((node.larg.op && node.larg.op !== 'SETOP_NONE') ||
192
+ node.larg.sortClause ||
193
+ node.larg.limitCount ||
194
+ node.larg.limitOffset ||
195
+ node.larg.withClause);
196
+ const rightNeedsParens = node.rarg && ((node.rarg.op && node.rarg.op !== 'SETOP_NONE') ||
197
+ node.rarg.sortClause ||
198
+ node.rarg.limitCount ||
199
+ node.rarg.limitOffset ||
200
+ node.rarg.withClause);
207
201
  if (leftNeedsParens) {
208
202
  output.push(this.formatter.parens(leftStmt));
209
203
  }
@@ -233,82 +227,41 @@ export class Deparser {
233
227
  output.push(rightStmt);
234
228
  }
235
229
  }
236
- // Handle DISTINCT clause - in pretty mode, we'll include it in the SELECT clause
237
- let distinctPart = '';
238
230
  if (node.distinctClause) {
239
231
  const distinctClause = ListUtils.unwrapList(node.distinctClause);
240
232
  if (distinctClause.length > 0 && Object.keys(distinctClause[0]).length > 0) {
233
+ output.push('DISTINCT ON');
241
234
  const clause = distinctClause
242
235
  .map(e => this.visit(e, { ...context, select: true }))
243
236
  .join(', ');
244
- distinctPart = ' DISTINCT ON ' + this.formatter.parens(clause);
237
+ output.push(this.formatter.parens(clause));
245
238
  }
246
239
  else {
247
- distinctPart = ' DISTINCT';
248
- }
249
- if (!this.formatter.isPretty()) {
250
- if (distinctClause.length > 0 && Object.keys(distinctClause[0]).length > 0) {
251
- output.push('DISTINCT ON');
252
- const clause = distinctClause
253
- .map(e => this.visit(e, { ...context, select: true }))
254
- .join(', ');
255
- output.push(this.formatter.parens(clause));
256
- }
257
- else {
258
- output.push('DISTINCT');
259
- }
240
+ output.push('DISTINCT');
260
241
  }
261
242
  }
262
243
  if (node.targetList) {
263
244
  const targetList = ListUtils.unwrapList(node.targetList);
264
- if (this.formatter.isPretty()) {
265
- const targetStrings = targetList
266
- .map(e => {
267
- const targetStr = this.visit(e, { ...context, select: true });
268
- if (this.containsMultilineStringLiteral(targetStr)) {
269
- return targetStr;
270
- }
271
- return this.formatter.indent(targetStr);
272
- });
273
- const formattedTargets = targetStrings.join(',' + this.formatter.newline());
274
- output.push('SELECT' + distinctPart);
275
- output.push(formattedTargets);
276
- }
277
- else {
278
- const targets = targetList
279
- .map(e => this.visit(e, { ...context, select: true }))
280
- .join(', ');
281
- output.push(targets);
282
- }
245
+ const targets = targetList
246
+ .map(e => this.visit(e, { ...context, select: true }))
247
+ .join(', ');
248
+ output.push(targets);
283
249
  }
284
250
  if (node.intoClause) {
285
251
  output.push('INTO');
286
252
  output.push(this.IntoClause(node.intoClause, context));
287
253
  }
288
254
  if (node.fromClause) {
255
+ output.push('FROM');
289
256
  const fromList = ListUtils.unwrapList(node.fromClause);
290
257
  const fromItems = fromList
291
258
  .map(e => this.deparse(e, { ...context, from: true }))
292
259
  .join(', ');
293
- output.push('FROM ' + fromItems.trim());
260
+ output.push(fromItems);
294
261
  }
295
262
  if (node.whereClause) {
296
- if (this.formatter.isPretty()) {
297
- output.push('WHERE');
298
- const whereExpr = this.visit(node.whereClause, context);
299
- const lines = whereExpr.split(this.formatter.newline());
300
- const indentedLines = lines.map((line, index) => {
301
- if (index === 0) {
302
- return this.formatter.indent(line);
303
- }
304
- return line;
305
- });
306
- output.push(indentedLines.join(this.formatter.newline()));
307
- }
308
- else {
309
- output.push('WHERE');
310
- output.push(this.visit(node.whereClause, context));
311
- }
263
+ output.push('WHERE');
264
+ output.push(this.visit(node.whereClause, context));
312
265
  }
313
266
  if (node.valuesLists) {
314
267
  output.push('VALUES');
@@ -319,43 +272,16 @@ export class Deparser {
319
272
  output.push(lists.join(', '));
320
273
  }
321
274
  if (node.groupClause) {
275
+ output.push('GROUP BY');
322
276
  const groupList = ListUtils.unwrapList(node.groupClause);
323
- if (this.formatter.isPretty()) {
324
- const groupItems = groupList
325
- .map(e => {
326
- const groupStr = this.visit(e, { ...context, group: true });
327
- if (this.containsMultilineStringLiteral(groupStr)) {
328
- return groupStr;
329
- }
330
- return this.formatter.indent(groupStr);
331
- })
332
- .join(',' + this.formatter.newline());
333
- output.push('GROUP BY');
334
- output.push(groupItems);
335
- }
336
- else {
337
- output.push('GROUP BY');
338
- const groupItems = groupList
339
- .map(e => this.visit(e, { ...context, group: true }))
340
- .join(', ');
341
- output.push(groupItems);
342
- }
277
+ const groupItems = groupList
278
+ .map(e => this.visit(e, { ...context, group: true }))
279
+ .join(', ');
280
+ output.push(groupItems);
343
281
  }
344
282
  if (node.havingClause) {
345
- if (this.formatter.isPretty()) {
346
- output.push('HAVING');
347
- const havingStr = this.visit(node.havingClause, context);
348
- if (this.containsMultilineStringLiteral(havingStr)) {
349
- output.push(havingStr);
350
- }
351
- else {
352
- output.push(this.formatter.indent(havingStr));
353
- }
354
- }
355
- else {
356
- output.push('HAVING');
357
- output.push(this.visit(node.havingClause, context));
358
- }
283
+ output.push('HAVING');
284
+ output.push(this.visit(node.havingClause, context));
359
285
  }
360
286
  if (node.windowClause) {
361
287
  output.push('WINDOW');
@@ -366,33 +292,20 @@ export class Deparser {
366
292
  output.push(windowClauses);
367
293
  }
368
294
  if (node.sortClause) {
295
+ output.push('ORDER BY');
369
296
  const sortList = ListUtils.unwrapList(node.sortClause);
370
- if (this.formatter.isPretty()) {
371
- const sortItems = sortList
372
- .map(e => {
373
- const sortStr = this.visit(e, { ...context, sort: true });
374
- if (this.containsMultilineStringLiteral(sortStr)) {
375
- return sortStr;
376
- }
377
- return this.formatter.indent(sortStr);
378
- })
379
- .join(',' + this.formatter.newline());
380
- output.push('ORDER BY');
381
- output.push(sortItems);
382
- }
383
- else {
384
- output.push('ORDER BY');
385
- const sortItems = sortList
386
- .map(e => this.visit(e, { ...context, sort: true }))
387
- .join(', ');
388
- output.push(sortItems);
389
- }
297
+ const sortItems = sortList
298
+ .map(e => this.visit(e, { ...context, sort: true }))
299
+ .join(', ');
300
+ output.push(sortItems);
390
301
  }
391
302
  if (node.limitCount) {
392
- output.push('LIMIT ' + this.visit(node.limitCount, context));
303
+ output.push('LIMIT');
304
+ output.push(this.visit(node.limitCount, context));
393
305
  }
394
306
  if (node.limitOffset) {
395
- output.push('OFFSET ' + this.visit(node.limitOffset, context));
307
+ output.push('OFFSET');
308
+ output.push(this.visit(node.limitOffset, context));
396
309
  }
397
310
  if (node.lockingClause) {
398
311
  const lockingList = ListUtils.unwrapList(node.lockingClause);
@@ -401,10 +314,6 @@ export class Deparser {
401
314
  .join(' ');
402
315
  output.push(lockingClauses);
403
316
  }
404
- if (this.formatter.isPretty()) {
405
- const filteredOutput = output.filter(item => item.trim() !== '');
406
- return filteredOutput.join(this.formatter.newline());
407
- }
408
317
  return output.join(' ');
409
318
  }
410
319
  A_Expr(node, context) {
@@ -469,38 +378,18 @@ export class Deparser {
469
378
  'ALL',
470
379
  this.formatter.parens(this.visit(rexpr, context))
471
380
  ]);
472
- case 'AEXPR_DISTINCT': {
473
- let leftExpr = this.visit(lexpr, context);
474
- let rightExpr = this.visit(rexpr, context);
475
- // Add parentheses for complex expressions
476
- if (lexpr && this.isComplexExpression(lexpr)) {
477
- leftExpr = this.formatter.parens(leftExpr);
478
- }
479
- if (rexpr && this.isComplexExpression(rexpr)) {
480
- rightExpr = this.formatter.parens(rightExpr);
481
- }
381
+ case 'AEXPR_DISTINCT':
482
382
  return this.formatter.format([
483
- leftExpr,
383
+ this.visit(lexpr, context),
484
384
  'IS DISTINCT FROM',
485
- rightExpr
385
+ this.visit(rexpr, context)
486
386
  ]);
487
- }
488
- case 'AEXPR_NOT_DISTINCT': {
489
- let leftExpr = this.visit(lexpr, context);
490
- let rightExpr = this.visit(rexpr, context);
491
- // Add parentheses for complex expressions
492
- if (lexpr && this.isComplexExpression(lexpr)) {
493
- leftExpr = this.formatter.parens(leftExpr);
494
- }
495
- if (rexpr && this.isComplexExpression(rexpr)) {
496
- rightExpr = this.formatter.parens(rightExpr);
497
- }
387
+ case 'AEXPR_NOT_DISTINCT':
498
388
  return this.formatter.format([
499
- leftExpr,
389
+ this.visit(lexpr, context),
500
390
  'IS NOT DISTINCT FROM',
501
- rightExpr
391
+ this.visit(rexpr, context)
502
392
  ]);
503
- }
504
393
  case 'AEXPR_NULLIF':
505
394
  return this.formatter.format([
506
395
  'NULLIF',
@@ -894,24 +783,9 @@ export class Deparser {
894
783
  if (node.recursive) {
895
784
  output.push('RECURSIVE');
896
785
  }
897
- if (node.ctes && node.ctes.length > 0) {
898
- const ctes = ListUtils.unwrapList(node.ctes);
899
- if (this.formatter.isPretty()) {
900
- const cteStrings = ctes.map((cte, index) => {
901
- const cteStr = this.visit(cte, context);
902
- const prefix = index === 0 ? this.formatter.newline() : ',' + this.formatter.newline();
903
- if (this.containsMultilineStringLiteral(cteStr)) {
904
- return prefix + cteStr;
905
- }
906
- return prefix + this.formatter.indent(cteStr);
907
- });
908
- output.push(cteStrings.join(''));
909
- }
910
- else {
911
- const cteStrings = ctes.map(cte => this.visit(cte, context));
912
- output.push(cteStrings.join(', '));
913
- }
914
- }
786
+ const ctes = ListUtils.unwrapList(node.ctes);
787
+ const cteStrs = ctes.map(cte => this.visit(cte, context));
788
+ output.push(cteStrs.join(', '));
915
789
  return output.join(' ');
916
790
  }
917
791
  ResTarget(node, context) {
@@ -990,28 +864,13 @@ export class Deparser {
990
864
  formatStr = '(%s)';
991
865
  }
992
866
  const boolContext = { ...context, bool: true };
993
- // explanation of our syntax/fix below:
994
- // return formatStr.replace('%s', andArgs); // ❌ Interprets $ as special syntax
995
- // return formatStr.replace('%s', () => andArgs); // ✅ Function callback prevents interpretation
996
867
  switch (boolop) {
997
868
  case 'AND_EXPR':
998
- if (this.formatter.isPretty() && args.length > 1) {
999
- const andArgs = args.map(arg => this.visit(arg, boolContext)).join(this.formatter.newline() + ' AND ');
1000
- return formatStr.replace('%s', () => andArgs);
1001
- }
1002
- else {
1003
- const andArgs = args.map(arg => this.visit(arg, boolContext)).join(' AND ');
1004
- return formatStr.replace('%s', () => andArgs);
1005
- }
869
+ const andArgs = args.map(arg => this.visit(arg, boolContext)).join(' AND ');
870
+ return formatStr.replace('%s', andArgs);
1006
871
  case 'OR_EXPR':
1007
- if (this.formatter.isPretty() && args.length > 1) {
1008
- const orArgs = args.map(arg => this.visit(arg, boolContext)).join(this.formatter.newline() + ' OR ');
1009
- return formatStr.replace('%s', () => orArgs);
1010
- }
1011
- else {
1012
- const orArgs = args.map(arg => this.visit(arg, boolContext)).join(' OR ');
1013
- return formatStr.replace('%s', () => orArgs);
1014
- }
872
+ const orArgs = args.map(arg => this.visit(arg, boolContext)).join(' OR ');
873
+ return formatStr.replace('%s', orArgs);
1015
874
  case 'NOT_EXPR':
1016
875
  return `NOT (${this.visit(args[0], context)})`;
1017
876
  default:
@@ -1213,13 +1072,7 @@ export class Deparser {
1213
1072
  windowParts.push(frameClause);
1214
1073
  }
1215
1074
  if (windowParts.length > 0) {
1216
- if (this.formatter.isPretty() && windowParts.length > 1) {
1217
- const formattedParts = windowParts.map(part => this.formatter.indent(part));
1218
- result += ` OVER (${this.formatter.newline()}${formattedParts.join(this.formatter.newline())}${this.formatter.newline()})`;
1219
- }
1220
- else {
1221
- result += ` OVER (${windowParts.join(' ')})`;
1222
- }
1075
+ result += ` OVER (${windowParts.join(' ')})`;
1223
1076
  }
1224
1077
  else {
1225
1078
  result += ` OVER ()`;
@@ -1276,23 +1129,23 @@ export class Deparser {
1276
1129
  else if (nodeAny.sval !== undefined) {
1277
1130
  if (typeof nodeAny.sval === 'object' && nodeAny.sval !== null) {
1278
1131
  if (nodeAny.sval.sval !== undefined) {
1279
- return QuoteUtils.formatEString(nodeAny.sval.sval);
1132
+ return QuoteUtils.escape(nodeAny.sval.sval);
1280
1133
  }
1281
1134
  else if (nodeAny.sval.String && nodeAny.sval.String.sval !== undefined) {
1282
- return QuoteUtils.formatEString(nodeAny.sval.String.sval);
1135
+ return QuoteUtils.escape(nodeAny.sval.String.sval);
1283
1136
  }
1284
1137
  else if (Object.keys(nodeAny.sval).length === 0) {
1285
1138
  return "''";
1286
1139
  }
1287
1140
  else {
1288
- return QuoteUtils.formatEString(nodeAny.sval.toString());
1141
+ return QuoteUtils.escape(nodeAny.sval.toString());
1289
1142
  }
1290
1143
  }
1291
1144
  else if (nodeAny.sval === null) {
1292
1145
  return 'NULL';
1293
1146
  }
1294
1147
  else {
1295
- return QuoteUtils.formatEString(nodeAny.sval);
1148
+ return QuoteUtils.escape(nodeAny.sval);
1296
1149
  }
1297
1150
  }
1298
1151
  else if (nodeAny.boolval !== undefined) {
@@ -1600,14 +1453,7 @@ export class Deparser {
1600
1453
  output.push('ONLY');
1601
1454
  }
1602
1455
  let tableName = '';
1603
- if (node.catalogname) {
1604
- tableName = QuoteUtils.quote(node.catalogname);
1605
- if (node.schemaname) {
1606
- tableName += '.' + QuoteUtils.quote(node.schemaname);
1607
- }
1608
- tableName += '.' + QuoteUtils.quote(node.relname);
1609
- }
1610
- else if (node.schemaname) {
1456
+ if (node.schemaname) {
1611
1457
  tableName = QuoteUtils.quote(node.schemaname) + '.' + QuoteUtils.quote(node.relname);
1612
1458
  }
1613
1459
  else {
@@ -1843,39 +1689,15 @@ export class Deparser {
1843
1689
  output.push(this.visit(node.arg, context));
1844
1690
  }
1845
1691
  const args = ListUtils.unwrapList(node.args);
1846
- if (this.formatter.isPretty() && args.length > 0) {
1847
- for (const arg of args) {
1848
- const whenClause = this.visit(arg, context);
1849
- if (this.containsMultilineStringLiteral(whenClause)) {
1850
- output.push(this.formatter.newline() + whenClause);
1851
- }
1852
- else {
1853
- output.push(this.formatter.newline() + this.formatter.indent(whenClause));
1854
- }
1855
- }
1856
- if (node.defresult) {
1857
- const elseResult = this.visit(node.defresult, context);
1858
- if (this.containsMultilineStringLiteral(elseResult)) {
1859
- output.push(this.formatter.newline() + 'ELSE ' + elseResult);
1860
- }
1861
- else {
1862
- output.push(this.formatter.newline() + this.formatter.indent('ELSE ' + elseResult));
1863
- }
1864
- }
1865
- output.push(this.formatter.newline() + 'END');
1866
- return output.join(' ');
1692
+ for (const arg of args) {
1693
+ output.push(this.visit(arg, context));
1867
1694
  }
1868
- else {
1869
- for (const arg of args) {
1870
- output.push(this.visit(arg, context));
1871
- }
1872
- if (node.defresult) {
1873
- output.push('ELSE');
1874
- output.push(this.visit(node.defresult, context));
1875
- }
1876
- output.push('END');
1877
- return output.join(' ');
1695
+ if (node.defresult) {
1696
+ output.push('ELSE');
1697
+ output.push(this.visit(node.defresult, context));
1878
1698
  }
1699
+ output.push('END');
1700
+ return output.join(' ');
1879
1701
  }
1880
1702
  CoalesceExpr(node, context) {
1881
1703
  const args = ListUtils.unwrapList(node.args);
@@ -2010,7 +1832,7 @@ export class Deparser {
2010
1832
  }
2011
1833
  String(node, context) {
2012
1834
  if (context.isStringLiteral || context.isEnumValue) {
2013
- return QuoteUtils.formatEString(node.sval || '');
1835
+ return `'${node.sval || ''}'`;
2014
1836
  }
2015
1837
  const value = node.sval || '';
2016
1838
  if (context.parentNodeTypes.includes('DefElem') ||
@@ -2088,13 +1910,7 @@ export class Deparser {
2088
1910
  const elementStrs = elements.map(el => {
2089
1911
  return this.deparse(el, context);
2090
1912
  });
2091
- if (this.formatter.isPretty()) {
2092
- const formattedElements = elementStrs.map(el => this.formatter.indent(el)).join(',' + this.formatter.newline());
2093
- output.push('(' + this.formatter.newline() + formattedElements + this.formatter.newline() + ')');
2094
- }
2095
- else {
2096
- output.push(this.formatter.parens(elementStrs.join(', ')));
2097
- }
1913
+ output.push(this.formatter.parens(elementStrs.join(', ')));
2098
1914
  }
2099
1915
  else if (!node.partbound) {
2100
1916
  output.push(this.formatter.parens(''));
@@ -2333,9 +2149,6 @@ export class Deparser {
2333
2149
  break;
2334
2150
  case 'CONSTR_UNIQUE':
2335
2151
  output.push('UNIQUE');
2336
- if (node.nulls_not_distinct) {
2337
- output.push('NULLS NOT DISTINCT');
2338
- }
2339
2152
  if (node.keys && node.keys.length > 0) {
2340
2153
  const keyList = ListUtils.unwrapList(node.keys)
2341
2154
  .map(key => this.visit(key, context))
@@ -2379,52 +2192,38 @@ export class Deparser {
2379
2192
  }
2380
2193
  }
2381
2194
  if (node.fk_upd_action && node.fk_upd_action !== 'a') {
2382
- let updateClause = 'ON UPDATE ';
2195
+ output.push('ON UPDATE');
2383
2196
  switch (node.fk_upd_action) {
2384
2197
  case 'r':
2385
- updateClause += 'RESTRICT';
2198
+ output.push('RESTRICT');
2386
2199
  break;
2387
2200
  case 'c':
2388
- updateClause += 'CASCADE';
2201
+ output.push('CASCADE');
2389
2202
  break;
2390
2203
  case 'n':
2391
- updateClause += 'SET NULL';
2204
+ output.push('SET NULL');
2392
2205
  break;
2393
2206
  case 'd':
2394
- updateClause += 'SET DEFAULT';
2207
+ output.push('SET DEFAULT');
2395
2208
  break;
2396
2209
  }
2397
- if (this.formatter.isPretty()) {
2398
- output.push('\n' + this.formatter.indent(updateClause));
2399
- }
2400
- else {
2401
- output.push('ON UPDATE');
2402
- output.push(updateClause.replace('ON UPDATE ', ''));
2403
- }
2404
2210
  }
2405
2211
  if (node.fk_del_action && node.fk_del_action !== 'a') {
2406
- let deleteClause = 'ON DELETE ';
2212
+ output.push('ON DELETE');
2407
2213
  switch (node.fk_del_action) {
2408
2214
  case 'r':
2409
- deleteClause += 'RESTRICT';
2215
+ output.push('RESTRICT');
2410
2216
  break;
2411
2217
  case 'c':
2412
- deleteClause += 'CASCADE';
2218
+ output.push('CASCADE');
2413
2219
  break;
2414
2220
  case 'n':
2415
- deleteClause += 'SET NULL';
2221
+ output.push('SET NULL');
2416
2222
  break;
2417
2223
  case 'd':
2418
- deleteClause += 'SET DEFAULT';
2224
+ output.push('SET DEFAULT');
2419
2225
  break;
2420
2226
  }
2421
- if (this.formatter.isPretty()) {
2422
- output.push('\n' + this.formatter.indent(deleteClause));
2423
- }
2424
- else {
2425
- output.push('ON DELETE');
2426
- output.push(deleteClause.replace('ON DELETE ', ''));
2427
- }
2428
2227
  }
2429
2228
  // Handle NOT VALID for foreign key constraints - only for table constraints, not domain constraints
2430
2229
  if (node.skip_validation && !context.isDomainConstraint) {
@@ -2482,48 +2281,17 @@ export class Deparser {
2482
2281
  // Handle deferrable constraints for all constraint types that support it
2483
2282
  if (node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_FOREIGN') {
2484
2283
  if (node.deferrable) {
2485
- if (this.formatter.isPretty() && node.contype === 'CONSTR_FOREIGN') {
2486
- output.push('\n' + this.formatter.indent('DEFERRABLE'));
2487
- if (node.initdeferred === true) {
2488
- output.push('\n' + this.formatter.indent('INITIALLY DEFERRED'));
2489
- }
2490
- else if (node.initdeferred === false) {
2491
- output.push('\n' + this.formatter.indent('INITIALLY IMMEDIATE'));
2492
- }
2284
+ output.push('DEFERRABLE');
2285
+ if (node.initdeferred === true) {
2286
+ output.push('INITIALLY DEFERRED');
2493
2287
  }
2494
- else {
2495
- output.push('DEFERRABLE');
2496
- if (node.initdeferred === true) {
2497
- output.push('INITIALLY DEFERRED');
2498
- }
2499
- else if (node.initdeferred === false) {
2500
- output.push('INITIALLY IMMEDIATE');
2501
- }
2288
+ else if (node.initdeferred === false) {
2289
+ output.push('INITIALLY IMMEDIATE');
2502
2290
  }
2503
2291
  }
2504
2292
  else if (node.deferrable === false) {
2505
- if (this.formatter.isPretty() && node.contype === 'CONSTR_FOREIGN') {
2506
- output.push('\n' + this.formatter.indent('NOT DEFERRABLE'));
2507
- }
2508
- else {
2509
- output.push('NOT DEFERRABLE');
2510
- }
2511
- }
2512
- }
2513
- if (this.formatter.isPretty() && node.contype === 'CONSTR_FOREIGN') {
2514
- let result = '';
2515
- for (let i = 0; i < output.length; i++) {
2516
- if (output[i].startsWith('\n')) {
2517
- result += output[i];
2518
- }
2519
- else {
2520
- if (i > 0 && !output[i - 1].startsWith('\n')) {
2521
- result += ' ';
2522
- }
2523
- result += output[i];
2524
- }
2293
+ output.push('NOT DEFERRABLE');
2525
2294
  }
2526
- return result;
2527
2295
  }
2528
2296
  return output.join(' ');
2529
2297
  }
@@ -3247,9 +3015,11 @@ export class Deparser {
3247
3015
  }
3248
3016
  switch (node.jointype) {
3249
3017
  case 'JOIN_INNER':
3018
+ // Handle NATURAL JOIN first - it has isNatural=true (NATURAL already added above)
3250
3019
  if (node.isNatural) {
3251
3020
  joinStr += 'JOIN';
3252
3021
  }
3022
+ // Handle CROSS JOIN case - when there's no quals, no usingClause, and not natural
3253
3023
  else if (!node.quals && (!node.usingClause || node.usingClause.length === 0)) {
3254
3024
  joinStr += 'CROSS JOIN';
3255
3025
  }
@@ -3269,63 +3039,26 @@ export class Deparser {
3269
3039
  default:
3270
3040
  joinStr += 'JOIN';
3271
3041
  }
3042
+ output.push(joinStr);
3272
3043
  if (node.rarg) {
3273
3044
  let rargStr = this.visit(node.rarg, context);
3274
3045
  if (node.rarg && 'JoinExpr' in node.rarg && !node.rarg.JoinExpr.alias) {
3275
3046
  rargStr = `(${rargStr})`;
3276
3047
  }
3277
- if (this.formatter.isPretty()) {
3278
- output.push(this.formatter.newline() + joinStr + ' ' + rargStr);
3279
- }
3280
- else {
3281
- output.push(joinStr + ' ' + rargStr);
3282
- }
3283
- }
3284
- else {
3285
- if (this.formatter.isPretty()) {
3286
- output.push(this.formatter.newline() + joinStr);
3287
- }
3288
- else {
3289
- output.push(joinStr);
3290
- }
3048
+ output.push(rargStr);
3291
3049
  }
3292
3050
  if (node.usingClause && node.usingClause.length > 0) {
3051
+ output.push('USING');
3293
3052
  const usingList = ListUtils.unwrapList(node.usingClause);
3294
3053
  const columnNames = usingList.map(col => this.visit(col, context));
3295
- if (this.formatter.isPretty()) {
3296
- output.push(` USING (${columnNames.join(', ')})`);
3297
- }
3298
- else {
3299
- output.push(`USING (${columnNames.join(', ')})`);
3300
- }
3054
+ output.push(`(${columnNames.join(', ')})`);
3301
3055
  }
3302
3056
  else if (node.quals) {
3303
- const qualsStr = this.visit(node.quals, context);
3304
- if (this.formatter.isPretty()) {
3305
- // For complex JOIN conditions, format with proper indentation
3306
- if (qualsStr.includes('AND') || qualsStr.includes('OR') || qualsStr.length > 50) {
3307
- if (this.containsMultilineStringLiteral(qualsStr)) {
3308
- output.push(` ON ${qualsStr}`);
3309
- }
3310
- else {
3311
- output.push(` ON${this.formatter.newline()}${this.formatter.indent(qualsStr)}`);
3312
- }
3313
- }
3314
- else {
3315
- output.push(` ON ${qualsStr}`);
3316
- }
3317
- }
3318
- else {
3319
- output.push(`ON ${qualsStr}`);
3320
- }
3321
- }
3322
- let result;
3323
- if (this.formatter.isPretty()) {
3324
- result = output.join('');
3325
- }
3326
- else {
3327
- result = output.join(' ');
3057
+ output.push('ON');
3058
+ output.push(this.visit(node.quals, context));
3328
3059
  }
3060
+ let result = output.join(' ');
3061
+ // Handle join_using_alias first (for USING clause aliases like "AS x")
3329
3062
  if (node.join_using_alias && node.join_using_alias.aliasname) {
3330
3063
  let aliasStr = node.join_using_alias.aliasname;
3331
3064
  if (node.join_using_alias.colnames && node.join_using_alias.colnames.length > 0) {
@@ -3335,6 +3068,7 @@ export class Deparser {
3335
3068
  }
3336
3069
  result += ` AS ${aliasStr}`;
3337
3070
  }
3071
+ // Handle regular alias (for outer table aliases like "y")
3338
3072
  if (node.alias && node.alias.aliasname) {
3339
3073
  let aliasStr = node.alias.aliasname;
3340
3074
  if (node.alias.colnames && node.alias.colnames.length > 0) {
@@ -5317,18 +5051,6 @@ export class Deparser {
5317
5051
  : argValue;
5318
5052
  return `${node.defname} = ${quotedValue}`;
5319
5053
  }
5320
- // Handle CopyStmt WITH clause options - uppercase format without quotes
5321
- if (context.parentNodeTypes.includes('CopyStmt')) {
5322
- if (node.defname === 'format' && node.arg && this.getNodeType(node.arg) === 'String') {
5323
- const stringData = this.getNodeData(node.arg);
5324
- return `FORMAT ${stringData.sval.toUpperCase()}`;
5325
- }
5326
- // Handle other COPY options with uppercase defname
5327
- if (node.arg) {
5328
- return `${node.defname.toUpperCase()} ${argValue}`;
5329
- }
5330
- return node.defname.toUpperCase();
5331
- }
5332
5054
  // Handle CREATE OPERATOR and CREATE TYPE context
5333
5055
  if (context.parentNodeTypes.includes('DefineStmt')) {
5334
5056
  const preservedName = this.preserveOperatorDefElemCase(node.defname);
@@ -6019,7 +5741,8 @@ export class Deparser {
6019
5741
  output.push('NULL');
6020
5742
  }
6021
5743
  else if (node.comment) {
6022
- output.push(QuoteUtils.formatEString(node.comment));
5744
+ const escapedComment = node.comment.replace(/'/g, "''");
5745
+ output.push(`'${escapedComment}'`);
6023
5746
  }
6024
5747
  return output.join(' ');
6025
5748
  }
@@ -6053,82 +5776,38 @@ export class Deparser {
6053
5776
  return output.join(' ');
6054
5777
  }
6055
5778
  CreatePolicyStmt(node, context) {
6056
- const output = [];
6057
- const initialParts = ['CREATE', 'POLICY'];
5779
+ const output = ['CREATE', 'POLICY'];
6058
5780
  if (node.policy_name) {
6059
- initialParts.push(`"${node.policy_name}"`);
5781
+ output.push(`"${node.policy_name}"`);
6060
5782
  }
6061
- output.push(initialParts.join(' '));
6062
- // Add ON clause on new line in pretty mode
5783
+ output.push('ON');
6063
5784
  if (node.table) {
6064
- if (this.formatter.isPretty()) {
6065
- output.push(this.formatter.newline() + this.formatter.indent(`ON ${this.RangeVar(node.table, context)}`));
6066
- }
6067
- else {
6068
- output.push('ON');
6069
- output.push(this.RangeVar(node.table, context));
6070
- }
5785
+ output.push(this.RangeVar(node.table, context));
6071
5786
  }
6072
5787
  // Handle AS RESTRICTIVE/PERMISSIVE clause
6073
5788
  if (node.permissive === undefined) {
6074
- if (this.formatter.isPretty()) {
6075
- output.push(this.formatter.newline() + this.formatter.indent('AS RESTRICTIVE'));
6076
- }
6077
- else {
6078
- output.push('AS', 'RESTRICTIVE');
6079
- }
5789
+ output.push('AS', 'RESTRICTIVE');
6080
5790
  }
6081
5791
  else if (node.permissive === true) {
6082
- if (this.formatter.isPretty()) {
6083
- output.push(this.formatter.newline() + this.formatter.indent('AS PERMISSIVE'));
6084
- }
6085
- else {
6086
- output.push('AS', 'PERMISSIVE');
6087
- }
5792
+ output.push('AS', 'PERMISSIVE');
6088
5793
  }
6089
5794
  if (node.cmd_name) {
6090
- if (this.formatter.isPretty()) {
6091
- output.push(this.formatter.newline() + this.formatter.indent(`FOR ${node.cmd_name.toUpperCase()}`));
6092
- }
6093
- else {
6094
- output.push('FOR', node.cmd_name.toUpperCase());
6095
- }
5795
+ output.push('FOR', node.cmd_name.toUpperCase());
6096
5796
  }
6097
5797
  if (node.roles && node.roles.length > 0) {
5798
+ output.push('TO');
6098
5799
  const roles = ListUtils.unwrapList(node.roles).map(role => this.visit(role, context));
6099
- if (this.formatter.isPretty()) {
6100
- output.push(this.formatter.newline() + this.formatter.indent(`TO ${roles.join(', ')}`));
6101
- }
6102
- else {
6103
- output.push('TO');
6104
- output.push(roles.join(', '));
6105
- }
5800
+ output.push(roles.join(', '));
6106
5801
  }
6107
5802
  if (node.qual) {
6108
- if (this.formatter.isPretty()) {
6109
- const qualExpr = this.visit(node.qual, context);
6110
- output.push(this.formatter.newline() + this.formatter.indent('USING ('));
6111
- output.push(this.formatter.newline() + this.formatter.indent(this.formatter.indent(qualExpr)));
6112
- output.push(this.formatter.newline() + this.formatter.indent(')'));
6113
- }
6114
- else {
6115
- output.push('USING');
6116
- output.push(`(${this.visit(node.qual, context)})`);
6117
- }
5803
+ output.push('USING');
5804
+ output.push(`(${this.visit(node.qual, context)})`);
6118
5805
  }
6119
5806
  if (node.with_check) {
6120
- if (this.formatter.isPretty()) {
6121
- const checkExpr = this.visit(node.with_check, context);
6122
- output.push(this.formatter.newline() + this.formatter.indent('WITH CHECK ('));
6123
- output.push(this.formatter.newline() + this.formatter.indent(this.formatter.indent(checkExpr)));
6124
- output.push(this.formatter.newline() + this.formatter.indent(')'));
6125
- }
6126
- else {
6127
- output.push('WITH CHECK');
6128
- output.push(`(${this.visit(node.with_check, context)})`);
6129
- }
5807
+ output.push('WITH CHECK');
5808
+ output.push(`(${this.visit(node.with_check, context)})`);
6130
5809
  }
6131
- return this.formatter.isPretty() ? output.join('') : output.join(' ');
5810
+ return output.join(' ');
6132
5811
  }
6133
5812
  AlterPolicyStmt(node, context) {
6134
5813
  const output = ['ALTER', 'POLICY'];
@@ -9994,8 +9673,4 @@ export class Deparser {
9994
9673
  }
9995
9674
  return output.join(' ');
9996
9675
  }
9997
- containsMultilineStringLiteral(content) {
9998
- const stringLiteralRegex = /'[^']*\n[^']*'/g;
9999
- return stringLiteralRegex.test(content);
10000
- }
10001
9676
  }