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.
- package/README.md +45 -88
- package/deparser.d.ts +297 -0
- package/{deparser/deparser.js → deparser.js} +110 -435
- package/esm/{deparser/deparser.js → deparser.js} +110 -435
- package/esm/index.js +3 -15
- package/esm/utils/index.js +90 -0
- package/esm/{deparser/utils → utils}/list-utils.js +0 -4
- package/esm/{deparser/utils → utils}/quote-utils.js +0 -34
- package/esm/utils/sql-formatter.js +23 -0
- package/esm/{deparser/visitors → visitors}/base.js +0 -4
- package/index.d.ts +3 -9
- package/index.js +4 -16
- package/package.json +27 -14
- package/utils/index.d.ts +4 -0
- package/utils/index.js +97 -0
- package/{deparser/utils → utils}/list-utils.d.ts +0 -4
- package/{deparser/utils → utils}/list-utils.js +0 -4
- package/utils/quote-utils.d.ts +5 -0
- package/{deparser/utils → utils}/quote-utils.js +0 -34
- package/{deparser/utils → utils}/sql-formatter.d.ts +1 -7
- package/{deparser/utils → utils}/sql-formatter.js +2 -15
- package/{deparser/visitors → visitors}/base.d.ts +5 -8
- package/{deparser/visitors → visitors}/base.js +0 -4
- package/deparser/deparser.d.ts +0 -301
- package/deparser/index.d.ts +0 -9
- package/deparser/index.js +0 -17
- package/deparser/utils/quote-utils.d.ts +0 -24
- package/esm/deparser/index.js +0 -13
- package/esm/deparser/utils/sql-formatter.js +0 -36
- package/esm/v16-to-v17-direct.js +0 -44
- package/esm/v16-to-v17.js +0 -1488
- package/v16-to-v17-direct.d.ts +0 -21
- package/v16-to-v17-direct.js +0 -48
- package/v16-to-v17.d.ts +0 -638
- 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
|
|
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
|
-
|
|
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 && ((
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
const rightNeedsParens = node.rarg && ((
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
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
|
-
|
|
237
|
+
output.push(this.formatter.parens(clause));
|
|
245
238
|
}
|
|
246
239
|
else {
|
|
247
|
-
|
|
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
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
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(
|
|
260
|
+
output.push(fromItems);
|
|
294
261
|
}
|
|
295
262
|
if (node.whereClause) {
|
|
296
|
-
|
|
297
|
-
|
|
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
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
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
|
-
|
|
346
|
-
|
|
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
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
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
|
|
303
|
+
output.push('LIMIT');
|
|
304
|
+
output.push(this.visit(node.limitCount, context));
|
|
393
305
|
}
|
|
394
306
|
if (node.limitOffset) {
|
|
395
|
-
output.push('OFFSET
|
|
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
|
-
|
|
383
|
+
this.visit(lexpr, context),
|
|
484
384
|
'IS DISTINCT FROM',
|
|
485
|
-
|
|
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
|
-
|
|
389
|
+
this.visit(lexpr, context),
|
|
500
390
|
'IS NOT DISTINCT FROM',
|
|
501
|
-
|
|
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
|
-
|
|
898
|
-
|
|
899
|
-
|
|
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
|
-
|
|
999
|
-
|
|
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
|
-
|
|
1008
|
-
|
|
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
|
-
|
|
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.
|
|
1132
|
+
return QuoteUtils.escape(nodeAny.sval.sval);
|
|
1280
1133
|
}
|
|
1281
1134
|
else if (nodeAny.sval.String && nodeAny.sval.String.sval !== undefined) {
|
|
1282
|
-
return QuoteUtils.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
1847
|
-
|
|
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
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
2195
|
+
output.push('ON UPDATE');
|
|
2383
2196
|
switch (node.fk_upd_action) {
|
|
2384
2197
|
case 'r':
|
|
2385
|
-
|
|
2198
|
+
output.push('RESTRICT');
|
|
2386
2199
|
break;
|
|
2387
2200
|
case 'c':
|
|
2388
|
-
|
|
2201
|
+
output.push('CASCADE');
|
|
2389
2202
|
break;
|
|
2390
2203
|
case 'n':
|
|
2391
|
-
|
|
2204
|
+
output.push('SET NULL');
|
|
2392
2205
|
break;
|
|
2393
2206
|
case 'd':
|
|
2394
|
-
|
|
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
|
-
|
|
2212
|
+
output.push('ON DELETE');
|
|
2407
2213
|
switch (node.fk_del_action) {
|
|
2408
2214
|
case 'r':
|
|
2409
|
-
|
|
2215
|
+
output.push('RESTRICT');
|
|
2410
2216
|
break;
|
|
2411
2217
|
case 'c':
|
|
2412
|
-
|
|
2218
|
+
output.push('CASCADE');
|
|
2413
2219
|
break;
|
|
2414
2220
|
case 'n':
|
|
2415
|
-
|
|
2221
|
+
output.push('SET NULL');
|
|
2416
2222
|
break;
|
|
2417
2223
|
case 'd':
|
|
2418
|
-
|
|
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
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
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('
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3304
|
-
|
|
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
|
-
|
|
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
|
-
|
|
5781
|
+
output.push(`"${node.policy_name}"`);
|
|
6060
5782
|
}
|
|
6061
|
-
output.push(
|
|
6062
|
-
// Add ON clause on new line in pretty mode
|
|
5783
|
+
output.push('ON');
|
|
6063
5784
|
if (node.table) {
|
|
6064
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
6109
|
-
|
|
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
|
-
|
|
6121
|
-
|
|
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
|
|
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
|
}
|