pgsql-deparser 17.8.2 → 17.8.4
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 +17 -0
- package/deparser.d.ts +2 -3
- package/deparser.js +304 -304
- package/esm/deparser.js +304 -304
- package/esm/visitors/base.js +87 -0
- package/package.json +11 -4
- package/visitors/base.d.ts +48 -2
- package/visitors/base.js +89 -1
- package/esm/utils/index.js +0 -90
- package/esm/utils/statement-splitter.js +0 -125
- package/utils/index.d.ts +0 -4
- package/utils/index.js +0 -97
- package/utils/statement-splitter.d.ts +0 -38
- package/utils/statement-splitter.js +0 -131
package/esm/deparser.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { DeparserContext } from './visitors/base';
|
|
1
2
|
import { SqlFormatter } from './utils/sql-formatter';
|
|
2
3
|
import { QuoteUtils } from './utils/quote-utils';
|
|
3
4
|
import { ListUtils } from './utils/list-utils';
|
|
@@ -100,11 +101,9 @@ function isWrappedParseResult(obj) {
|
|
|
100
101
|
* compatibility and wraps them internally for consistent processing.
|
|
101
102
|
*/
|
|
102
103
|
export class Deparser {
|
|
103
|
-
formatter;
|
|
104
104
|
tree;
|
|
105
105
|
options;
|
|
106
106
|
constructor(tree, opts = {}) {
|
|
107
|
-
this.formatter = new SqlFormatter(opts.newline, opts.tab, opts.pretty);
|
|
108
107
|
// Set default options
|
|
109
108
|
this.options = {
|
|
110
109
|
functionDelimiter: '$$',
|
|
@@ -141,15 +140,17 @@ export class Deparser {
|
|
|
141
140
|
return new Deparser(query, opts).deparseQuery();
|
|
142
141
|
}
|
|
143
142
|
deparseQuery() {
|
|
143
|
+
const formatter = new SqlFormatter(this.options.newline, this.options.tab, this.options.pretty);
|
|
144
|
+
const context = new DeparserContext({ formatter, prettyMode: this.options.pretty });
|
|
144
145
|
return this.tree
|
|
145
146
|
.map(node => {
|
|
146
147
|
// All nodes should go through the standard deparse method
|
|
147
148
|
// which will route to the appropriate handler
|
|
148
|
-
const result = this.deparse(node);
|
|
149
|
+
const result = this.deparse(node, context);
|
|
149
150
|
return result || '';
|
|
150
151
|
})
|
|
151
152
|
.filter(result => result !== '')
|
|
152
|
-
.join(
|
|
153
|
+
.join(context.newline() + context.newline());
|
|
153
154
|
}
|
|
154
155
|
/**
|
|
155
156
|
* Get the appropriate function delimiter based on the body content
|
|
@@ -163,10 +164,14 @@ export class Deparser {
|
|
|
163
164
|
}
|
|
164
165
|
return delimiter;
|
|
165
166
|
}
|
|
166
|
-
deparse(node, context
|
|
167
|
+
deparse(node, context) {
|
|
167
168
|
if (node == null) {
|
|
168
169
|
return null;
|
|
169
170
|
}
|
|
171
|
+
if (!context) {
|
|
172
|
+
const formatter = new SqlFormatter(this.options.newline, this.options.tab, this.options.pretty);
|
|
173
|
+
context = new DeparserContext({ formatter, prettyMode: this.options.pretty });
|
|
174
|
+
}
|
|
170
175
|
if (typeof node === 'number' || node instanceof Number) {
|
|
171
176
|
return node.toString();
|
|
172
177
|
}
|
|
@@ -178,7 +183,11 @@ export class Deparser {
|
|
|
178
183
|
throw new Error(`Error deparsing ${nodeType}: ${error.message}`);
|
|
179
184
|
}
|
|
180
185
|
}
|
|
181
|
-
visit(node, context
|
|
186
|
+
visit(node, context) {
|
|
187
|
+
if (!context) {
|
|
188
|
+
const formatter = new SqlFormatter(this.options.newline, this.options.tab, this.options.pretty);
|
|
189
|
+
context = new DeparserContext({ formatter, prettyMode: this.options.pretty });
|
|
190
|
+
}
|
|
182
191
|
const nodeType = this.getNodeType(node);
|
|
183
192
|
// Handle empty objects
|
|
184
193
|
if (!nodeType) {
|
|
@@ -187,11 +196,7 @@ export class Deparser {
|
|
|
187
196
|
const nodeData = this.getNodeData(node);
|
|
188
197
|
const methodName = nodeType;
|
|
189
198
|
if (typeof this[methodName] === 'function') {
|
|
190
|
-
const
|
|
191
|
-
...context,
|
|
192
|
-
parentNodeTypes: [...context.parentNodeTypes, nodeType]
|
|
193
|
-
};
|
|
194
|
-
const result = this[methodName](nodeData, childContext);
|
|
199
|
+
const result = this[methodName](nodeData, context);
|
|
195
200
|
return result;
|
|
196
201
|
}
|
|
197
202
|
throw new Error(`Deparser does not handle node type: ${nodeType}`);
|
|
@@ -217,7 +222,7 @@ export class Deparser {
|
|
|
217
222
|
.filter((rawStmt) => rawStmt != null)
|
|
218
223
|
.map((rawStmt) => this.RawStmt(rawStmt, context))
|
|
219
224
|
.filter((result) => result !== '')
|
|
220
|
-
.join(
|
|
225
|
+
.join(context.newline() + context.newline());
|
|
221
226
|
}
|
|
222
227
|
RawStmt(node, context) {
|
|
223
228
|
if (!node.stmt) {
|
|
@@ -237,7 +242,7 @@ export class Deparser {
|
|
|
237
242
|
}
|
|
238
243
|
if (!node.op || node.op === 'SETOP_NONE') {
|
|
239
244
|
if (node.valuesLists == null) {
|
|
240
|
-
if (!
|
|
245
|
+
if (!context.isPretty() || !node.targetList) {
|
|
241
246
|
output.push('SELECT');
|
|
242
247
|
}
|
|
243
248
|
}
|
|
@@ -257,7 +262,7 @@ export class Deparser {
|
|
|
257
262
|
node.rarg.limitOffset ||
|
|
258
263
|
node.rarg.withClause);
|
|
259
264
|
if (leftNeedsParens) {
|
|
260
|
-
output.push(
|
|
265
|
+
output.push(context.parens(leftStmt));
|
|
261
266
|
}
|
|
262
267
|
else {
|
|
263
268
|
output.push(leftStmt);
|
|
@@ -279,7 +284,7 @@ export class Deparser {
|
|
|
279
284
|
output.push('ALL');
|
|
280
285
|
}
|
|
281
286
|
if (rightNeedsParens) {
|
|
282
|
-
output.push(
|
|
287
|
+
output.push(context.parens(rightStmt));
|
|
283
288
|
}
|
|
284
289
|
else {
|
|
285
290
|
output.push(rightStmt);
|
|
@@ -291,20 +296,20 @@ export class Deparser {
|
|
|
291
296
|
const distinctClause = ListUtils.unwrapList(node.distinctClause);
|
|
292
297
|
if (distinctClause.length > 0 && Object.keys(distinctClause[0]).length > 0) {
|
|
293
298
|
const clause = distinctClause
|
|
294
|
-
.map(e => this.visit(e,
|
|
299
|
+
.map(e => this.visit(e, context.spawn('SelectStmt', { select: true })))
|
|
295
300
|
.join(', ');
|
|
296
|
-
distinctPart = ' DISTINCT ON ' +
|
|
301
|
+
distinctPart = ' DISTINCT ON ' + context.parens(clause);
|
|
297
302
|
}
|
|
298
303
|
else {
|
|
299
304
|
distinctPart = ' DISTINCT';
|
|
300
305
|
}
|
|
301
|
-
if (!
|
|
306
|
+
if (!context.isPretty()) {
|
|
302
307
|
if (distinctClause.length > 0 && Object.keys(distinctClause[0]).length > 0) {
|
|
303
308
|
output.push('DISTINCT ON');
|
|
304
309
|
const clause = distinctClause
|
|
305
|
-
.map(e => this.visit(e,
|
|
310
|
+
.map(e => this.visit(e, context.spawn('SelectStmt', { select: true })))
|
|
306
311
|
.join(', ');
|
|
307
|
-
output.push(
|
|
312
|
+
output.push(context.parens(clause));
|
|
308
313
|
}
|
|
309
314
|
else {
|
|
310
315
|
output.push('DISTINCT');
|
|
@@ -313,10 +318,10 @@ export class Deparser {
|
|
|
313
318
|
}
|
|
314
319
|
if (node.targetList) {
|
|
315
320
|
const targetList = ListUtils.unwrapList(node.targetList);
|
|
316
|
-
if (
|
|
321
|
+
if (context.isPretty()) {
|
|
317
322
|
if (targetList.length === 1) {
|
|
318
323
|
const targetNode = targetList[0];
|
|
319
|
-
const target = this.visit(targetNode,
|
|
324
|
+
const target = this.visit(targetNode, context.spawn('SelectStmt', { select: true }));
|
|
320
325
|
// Check if single target is complex - if so, use multiline format
|
|
321
326
|
if (this.isComplexSelectTarget(targetNode)) {
|
|
322
327
|
output.push('SELECT' + distinctPart);
|
|
@@ -324,7 +329,7 @@ export class Deparser {
|
|
|
324
329
|
output.push(target);
|
|
325
330
|
}
|
|
326
331
|
else {
|
|
327
|
-
output.push(
|
|
332
|
+
output.push(context.indent(target));
|
|
328
333
|
}
|
|
329
334
|
}
|
|
330
335
|
else {
|
|
@@ -334,20 +339,20 @@ export class Deparser {
|
|
|
334
339
|
else {
|
|
335
340
|
const targetStrings = targetList
|
|
336
341
|
.map(e => {
|
|
337
|
-
const targetStr = this.visit(e,
|
|
342
|
+
const targetStr = this.visit(e, context.spawn('SelectStmt', { select: true }));
|
|
338
343
|
if (this.containsMultilineStringLiteral(targetStr)) {
|
|
339
344
|
return targetStr;
|
|
340
345
|
}
|
|
341
|
-
return
|
|
346
|
+
return context.indent(targetStr);
|
|
342
347
|
});
|
|
343
|
-
const formattedTargets = targetStrings.join(',' +
|
|
348
|
+
const formattedTargets = targetStrings.join(',' + context.newline());
|
|
344
349
|
output.push('SELECT' + distinctPart);
|
|
345
350
|
output.push(formattedTargets);
|
|
346
351
|
}
|
|
347
352
|
}
|
|
348
353
|
else {
|
|
349
354
|
const targets = targetList
|
|
350
|
-
.map(e => this.visit(e,
|
|
355
|
+
.map(e => this.visit(e, context.spawn('SelectStmt', { select: true })))
|
|
351
356
|
.join(', ');
|
|
352
357
|
output.push(targets);
|
|
353
358
|
}
|
|
@@ -359,22 +364,22 @@ export class Deparser {
|
|
|
359
364
|
if (node.fromClause) {
|
|
360
365
|
const fromList = ListUtils.unwrapList(node.fromClause);
|
|
361
366
|
const fromItems = fromList
|
|
362
|
-
.map(e => this.deparse(e,
|
|
367
|
+
.map(e => this.deparse(e, context.spawn('SelectStmt', { from: true })))
|
|
363
368
|
.join(', ');
|
|
364
369
|
output.push('FROM ' + fromItems.trim());
|
|
365
370
|
}
|
|
366
371
|
if (node.whereClause) {
|
|
367
|
-
if (
|
|
372
|
+
if (context.isPretty()) {
|
|
368
373
|
output.push('WHERE');
|
|
369
374
|
const whereExpr = this.visit(node.whereClause, context);
|
|
370
|
-
const lines = whereExpr.split(
|
|
375
|
+
const lines = whereExpr.split(context.newline());
|
|
371
376
|
const indentedLines = lines.map((line, index) => {
|
|
372
377
|
if (index === 0) {
|
|
373
|
-
return
|
|
378
|
+
return context.indent(line);
|
|
374
379
|
}
|
|
375
380
|
return line;
|
|
376
381
|
});
|
|
377
|
-
output.push(indentedLines.join(
|
|
382
|
+
output.push(indentedLines.join(context.newline()));
|
|
378
383
|
}
|
|
379
384
|
else {
|
|
380
385
|
output.push('WHERE');
|
|
@@ -382,17 +387,17 @@ export class Deparser {
|
|
|
382
387
|
}
|
|
383
388
|
}
|
|
384
389
|
if (node.valuesLists) {
|
|
385
|
-
if (
|
|
390
|
+
if (context.isPretty()) {
|
|
386
391
|
output.push('VALUES');
|
|
387
392
|
const lists = ListUtils.unwrapList(node.valuesLists).map(list => {
|
|
388
393
|
const values = ListUtils.unwrapList(list).map(val => this.visit(val, context));
|
|
389
|
-
return
|
|
394
|
+
return context.parens(values.join(', '));
|
|
390
395
|
});
|
|
391
396
|
const indentedTuples = lists.map(tuple => {
|
|
392
397
|
if (this.containsMultilineStringLiteral(tuple)) {
|
|
393
398
|
return tuple;
|
|
394
399
|
}
|
|
395
|
-
return
|
|
400
|
+
return context.indent(tuple);
|
|
396
401
|
});
|
|
397
402
|
output.push(indentedTuples.join(',\n'));
|
|
398
403
|
}
|
|
@@ -400,43 +405,43 @@ export class Deparser {
|
|
|
400
405
|
output.push('VALUES');
|
|
401
406
|
const lists = ListUtils.unwrapList(node.valuesLists).map(list => {
|
|
402
407
|
const values = ListUtils.unwrapList(list).map(val => this.visit(val, context));
|
|
403
|
-
return
|
|
408
|
+
return context.parens(values.join(', '));
|
|
404
409
|
});
|
|
405
410
|
output.push(lists.join(', '));
|
|
406
411
|
}
|
|
407
412
|
}
|
|
408
413
|
if (node.groupClause) {
|
|
409
414
|
const groupList = ListUtils.unwrapList(node.groupClause);
|
|
410
|
-
if (
|
|
415
|
+
if (context.isPretty()) {
|
|
411
416
|
const groupItems = groupList
|
|
412
417
|
.map(e => {
|
|
413
|
-
const groupStr = this.visit(e,
|
|
418
|
+
const groupStr = this.visit(e, context.spawn('SelectStmt', { group: true, indentLevel: context.indentLevel + 1 }));
|
|
414
419
|
if (this.containsMultilineStringLiteral(groupStr)) {
|
|
415
420
|
return groupStr;
|
|
416
421
|
}
|
|
417
|
-
return
|
|
422
|
+
return context.indent(groupStr);
|
|
418
423
|
})
|
|
419
|
-
.join(',' +
|
|
424
|
+
.join(',' + context.newline());
|
|
420
425
|
output.push('GROUP BY');
|
|
421
426
|
output.push(groupItems);
|
|
422
427
|
}
|
|
423
428
|
else {
|
|
424
429
|
output.push('GROUP BY');
|
|
425
430
|
const groupItems = groupList
|
|
426
|
-
.map(e => this.visit(e,
|
|
431
|
+
.map(e => this.visit(e, context.spawn('SelectStmt', { group: true })))
|
|
427
432
|
.join(', ');
|
|
428
433
|
output.push(groupItems);
|
|
429
434
|
}
|
|
430
435
|
}
|
|
431
436
|
if (node.havingClause) {
|
|
432
|
-
if (
|
|
437
|
+
if (context.isPretty()) {
|
|
433
438
|
output.push('HAVING');
|
|
434
439
|
const havingStr = this.visit(node.havingClause, context);
|
|
435
440
|
if (this.containsMultilineStringLiteral(havingStr)) {
|
|
436
441
|
output.push(havingStr);
|
|
437
442
|
}
|
|
438
443
|
else {
|
|
439
|
-
output.push(
|
|
444
|
+
output.push(context.indent(havingStr));
|
|
440
445
|
}
|
|
441
446
|
}
|
|
442
447
|
else {
|
|
@@ -454,23 +459,23 @@ export class Deparser {
|
|
|
454
459
|
}
|
|
455
460
|
if (node.sortClause) {
|
|
456
461
|
const sortList = ListUtils.unwrapList(node.sortClause);
|
|
457
|
-
if (
|
|
462
|
+
if (context.isPretty()) {
|
|
458
463
|
const sortItems = sortList
|
|
459
464
|
.map(e => {
|
|
460
|
-
const sortStr = this.visit(e,
|
|
465
|
+
const sortStr = this.visit(e, context.spawn('SelectStmt', { sort: true, indentLevel: context.indentLevel + 1 }));
|
|
461
466
|
if (this.containsMultilineStringLiteral(sortStr)) {
|
|
462
467
|
return sortStr;
|
|
463
468
|
}
|
|
464
|
-
return
|
|
469
|
+
return context.indent(sortStr);
|
|
465
470
|
})
|
|
466
|
-
.join(',' +
|
|
471
|
+
.join(',' + context.newline());
|
|
467
472
|
output.push('ORDER BY');
|
|
468
473
|
output.push(sortItems);
|
|
469
474
|
}
|
|
470
475
|
else {
|
|
471
476
|
output.push('ORDER BY');
|
|
472
477
|
const sortItems = sortList
|
|
473
|
-
.map(e => this.visit(e,
|
|
478
|
+
.map(e => this.visit(e, context.spawn('SelectStmt', { sort: true })))
|
|
474
479
|
.join(', ');
|
|
475
480
|
output.push(sortItems);
|
|
476
481
|
}
|
|
@@ -488,9 +493,9 @@ export class Deparser {
|
|
|
488
493
|
.join(' ');
|
|
489
494
|
output.push(lockingClauses);
|
|
490
495
|
}
|
|
491
|
-
if (
|
|
496
|
+
if (context.isPretty()) {
|
|
492
497
|
const filteredOutput = output.filter(item => item.trim() !== '');
|
|
493
|
-
return filteredOutput.join(
|
|
498
|
+
return filteredOutput.join(context.newline());
|
|
494
499
|
}
|
|
495
500
|
return output.join(' ');
|
|
496
501
|
}
|
|
@@ -502,13 +507,13 @@ export class Deparser {
|
|
|
502
507
|
switch (kind) {
|
|
503
508
|
case 'AEXPR_OP':
|
|
504
509
|
if (lexpr && rexpr) {
|
|
505
|
-
const operator = this.deparseOperatorName(name);
|
|
510
|
+
const operator = this.deparseOperatorName(name, context);
|
|
506
511
|
let leftExpr = this.visit(lexpr, context);
|
|
507
512
|
let rightExpr = this.visit(rexpr, context);
|
|
508
513
|
// Check if left expression needs parentheses
|
|
509
514
|
let leftNeedsParens = false;
|
|
510
515
|
if (lexpr && 'A_Expr' in lexpr && lexpr.A_Expr?.kind === 'AEXPR_OP') {
|
|
511
|
-
const leftOp = this.deparseOperatorName(ListUtils.unwrapList(lexpr.A_Expr.name));
|
|
516
|
+
const leftOp = this.deparseOperatorName(ListUtils.unwrapList(lexpr.A_Expr.name), context);
|
|
512
517
|
if (this.needsParentheses(leftOp, operator, 'left')) {
|
|
513
518
|
leftNeedsParens = true;
|
|
514
519
|
}
|
|
@@ -517,12 +522,12 @@ export class Deparser {
|
|
|
517
522
|
leftNeedsParens = true;
|
|
518
523
|
}
|
|
519
524
|
if (leftNeedsParens) {
|
|
520
|
-
leftExpr =
|
|
525
|
+
leftExpr = context.parens(leftExpr);
|
|
521
526
|
}
|
|
522
527
|
// Check if right expression needs parentheses
|
|
523
528
|
let rightNeedsParens = false;
|
|
524
529
|
if (rexpr && 'A_Expr' in rexpr && rexpr.A_Expr?.kind === 'AEXPR_OP') {
|
|
525
|
-
const rightOp = this.deparseOperatorName(ListUtils.unwrapList(rexpr.A_Expr.name));
|
|
530
|
+
const rightOp = this.deparseOperatorName(ListUtils.unwrapList(rexpr.A_Expr.name), context);
|
|
526
531
|
if (this.needsParentheses(rightOp, operator, 'right')) {
|
|
527
532
|
rightNeedsParens = true;
|
|
528
533
|
}
|
|
@@ -531,42 +536,42 @@ export class Deparser {
|
|
|
531
536
|
rightNeedsParens = true;
|
|
532
537
|
}
|
|
533
538
|
if (rightNeedsParens) {
|
|
534
|
-
rightExpr =
|
|
539
|
+
rightExpr = context.parens(rightExpr);
|
|
535
540
|
}
|
|
536
|
-
return
|
|
541
|
+
return context.format([leftExpr, operator, rightExpr]);
|
|
537
542
|
}
|
|
538
543
|
else if (rexpr) {
|
|
539
|
-
return
|
|
540
|
-
this.deparseOperatorName(name),
|
|
544
|
+
return context.format([
|
|
545
|
+
this.deparseOperatorName(name, context),
|
|
541
546
|
this.visit(rexpr, context)
|
|
542
547
|
]);
|
|
543
548
|
}
|
|
544
549
|
break;
|
|
545
550
|
case 'AEXPR_OP_ANY':
|
|
546
|
-
return
|
|
551
|
+
return context.format([
|
|
547
552
|
this.visit(lexpr, context),
|
|
548
|
-
this.deparseOperatorName(name),
|
|
553
|
+
this.deparseOperatorName(name, context),
|
|
549
554
|
'ANY',
|
|
550
|
-
|
|
555
|
+
context.parens(this.visit(rexpr, context))
|
|
551
556
|
]);
|
|
552
557
|
case 'AEXPR_OP_ALL':
|
|
553
|
-
return
|
|
558
|
+
return context.format([
|
|
554
559
|
this.visit(lexpr, context),
|
|
555
|
-
this.deparseOperatorName(name),
|
|
560
|
+
this.deparseOperatorName(name, context),
|
|
556
561
|
'ALL',
|
|
557
|
-
|
|
562
|
+
context.parens(this.visit(rexpr, context))
|
|
558
563
|
]);
|
|
559
564
|
case 'AEXPR_DISTINCT': {
|
|
560
565
|
let leftExpr = this.visit(lexpr, context);
|
|
561
566
|
let rightExpr = this.visit(rexpr, context);
|
|
562
567
|
// Add parentheses for complex expressions
|
|
563
568
|
if (lexpr && this.isComplexExpression(lexpr)) {
|
|
564
|
-
leftExpr =
|
|
569
|
+
leftExpr = context.parens(leftExpr);
|
|
565
570
|
}
|
|
566
571
|
if (rexpr && this.isComplexExpression(rexpr)) {
|
|
567
|
-
rightExpr =
|
|
572
|
+
rightExpr = context.parens(rightExpr);
|
|
568
573
|
}
|
|
569
|
-
return
|
|
574
|
+
return context.format([
|
|
570
575
|
leftExpr,
|
|
571
576
|
'IS DISTINCT FROM',
|
|
572
577
|
rightExpr
|
|
@@ -577,75 +582,75 @@ export class Deparser {
|
|
|
577
582
|
let rightExpr = this.visit(rexpr, context);
|
|
578
583
|
// Add parentheses for complex expressions
|
|
579
584
|
if (lexpr && this.isComplexExpression(lexpr)) {
|
|
580
|
-
leftExpr =
|
|
585
|
+
leftExpr = context.parens(leftExpr);
|
|
581
586
|
}
|
|
582
587
|
if (rexpr && this.isComplexExpression(rexpr)) {
|
|
583
|
-
rightExpr =
|
|
588
|
+
rightExpr = context.parens(rightExpr);
|
|
584
589
|
}
|
|
585
|
-
return
|
|
590
|
+
return context.format([
|
|
586
591
|
leftExpr,
|
|
587
592
|
'IS NOT DISTINCT FROM',
|
|
588
593
|
rightExpr
|
|
589
594
|
]);
|
|
590
595
|
}
|
|
591
596
|
case 'AEXPR_NULLIF':
|
|
592
|
-
return
|
|
597
|
+
return context.format([
|
|
593
598
|
'NULLIF',
|
|
594
|
-
|
|
599
|
+
context.parens([
|
|
595
600
|
this.visit(lexpr, context),
|
|
596
601
|
this.visit(rexpr, context)
|
|
597
602
|
].join(', '))
|
|
598
603
|
]);
|
|
599
604
|
case 'AEXPR_IN':
|
|
600
|
-
const inOperator = this.deparseOperatorName(name);
|
|
605
|
+
const inOperator = this.deparseOperatorName(name, context);
|
|
601
606
|
if (inOperator === '<>' || inOperator === '!=') {
|
|
602
|
-
return
|
|
607
|
+
return context.format([
|
|
603
608
|
this.visit(lexpr, context),
|
|
604
609
|
'NOT IN',
|
|
605
|
-
|
|
610
|
+
context.parens(this.visit(rexpr, context))
|
|
606
611
|
]);
|
|
607
612
|
}
|
|
608
613
|
else {
|
|
609
|
-
return
|
|
614
|
+
return context.format([
|
|
610
615
|
this.visit(lexpr, context),
|
|
611
616
|
'IN',
|
|
612
|
-
|
|
617
|
+
context.parens(this.visit(rexpr, context))
|
|
613
618
|
]);
|
|
614
619
|
}
|
|
615
620
|
case 'AEXPR_LIKE':
|
|
616
|
-
const likeOp = this.deparseOperatorName(name);
|
|
621
|
+
const likeOp = this.deparseOperatorName(name, context);
|
|
617
622
|
if (likeOp === '!~~') {
|
|
618
|
-
return
|
|
623
|
+
return context.format([
|
|
619
624
|
this.visit(lexpr, context),
|
|
620
625
|
'NOT LIKE',
|
|
621
626
|
this.visit(rexpr, context)
|
|
622
627
|
]);
|
|
623
628
|
}
|
|
624
629
|
else {
|
|
625
|
-
return
|
|
630
|
+
return context.format([
|
|
626
631
|
this.visit(lexpr, context),
|
|
627
632
|
'LIKE',
|
|
628
633
|
this.visit(rexpr, context)
|
|
629
634
|
]);
|
|
630
635
|
}
|
|
631
636
|
case 'AEXPR_ILIKE':
|
|
632
|
-
const ilikeOp = this.deparseOperatorName(name);
|
|
637
|
+
const ilikeOp = this.deparseOperatorName(name, context);
|
|
633
638
|
if (ilikeOp === '!~~*') {
|
|
634
|
-
return
|
|
639
|
+
return context.format([
|
|
635
640
|
this.visit(lexpr, context),
|
|
636
641
|
'NOT ILIKE',
|
|
637
642
|
this.visit(rexpr, context)
|
|
638
643
|
]);
|
|
639
644
|
}
|
|
640
645
|
else {
|
|
641
|
-
return
|
|
646
|
+
return context.format([
|
|
642
647
|
this.visit(lexpr, context),
|
|
643
648
|
'ILIKE',
|
|
644
649
|
this.visit(rexpr, context)
|
|
645
650
|
]);
|
|
646
651
|
}
|
|
647
652
|
case 'AEXPR_SIMILAR':
|
|
648
|
-
const similarOp = this.deparseOperatorName(name);
|
|
653
|
+
const similarOp = this.deparseOperatorName(name, context);
|
|
649
654
|
let rightExpr;
|
|
650
655
|
if (rexpr && 'FuncCall' in rexpr &&
|
|
651
656
|
rexpr.FuncCall?.funcname?.length === 2 &&
|
|
@@ -661,39 +666,39 @@ export class Deparser {
|
|
|
661
666
|
rightExpr = this.visit(rexpr, context);
|
|
662
667
|
}
|
|
663
668
|
if (similarOp === '!~') {
|
|
664
|
-
return
|
|
669
|
+
return context.format([
|
|
665
670
|
this.visit(lexpr, context),
|
|
666
671
|
'NOT SIMILAR TO',
|
|
667
672
|
rightExpr
|
|
668
673
|
]);
|
|
669
674
|
}
|
|
670
675
|
else {
|
|
671
|
-
return
|
|
676
|
+
return context.format([
|
|
672
677
|
this.visit(lexpr, context),
|
|
673
678
|
'SIMILAR TO',
|
|
674
679
|
rightExpr
|
|
675
680
|
]);
|
|
676
681
|
}
|
|
677
682
|
case 'AEXPR_BETWEEN':
|
|
678
|
-
return
|
|
683
|
+
return context.format([
|
|
679
684
|
this.visit(lexpr, context),
|
|
680
685
|
'BETWEEN',
|
|
681
686
|
this.visitBetweenRange(rexpr, context)
|
|
682
687
|
]);
|
|
683
688
|
case 'AEXPR_NOT_BETWEEN':
|
|
684
|
-
return
|
|
689
|
+
return context.format([
|
|
685
690
|
this.visit(lexpr, context),
|
|
686
691
|
'NOT BETWEEN',
|
|
687
692
|
this.visitBetweenRange(rexpr, context)
|
|
688
693
|
]);
|
|
689
694
|
case 'AEXPR_BETWEEN_SYM':
|
|
690
|
-
return
|
|
695
|
+
return context.format([
|
|
691
696
|
this.visit(lexpr, context),
|
|
692
697
|
'BETWEEN SYMMETRIC',
|
|
693
698
|
this.visitBetweenRange(rexpr, context)
|
|
694
699
|
]);
|
|
695
700
|
case 'AEXPR_NOT_BETWEEN_SYM':
|
|
696
|
-
return
|
|
701
|
+
return context.format([
|
|
697
702
|
this.visit(lexpr, context),
|
|
698
703
|
'NOT BETWEEN SYMMETRIC',
|
|
699
704
|
this.visitBetweenRange(rexpr, context)
|
|
@@ -701,7 +706,7 @@ export class Deparser {
|
|
|
701
706
|
}
|
|
702
707
|
throw new Error(`Unhandled A_Expr kind: ${kind}`);
|
|
703
708
|
}
|
|
704
|
-
deparseOperatorName(name) {
|
|
709
|
+
deparseOperatorName(name, context) {
|
|
705
710
|
if (!name || name.length === 0) {
|
|
706
711
|
return '';
|
|
707
712
|
}
|
|
@@ -709,7 +714,7 @@ export class Deparser {
|
|
|
709
714
|
if (n.String) {
|
|
710
715
|
return n.String.sval || n.String.str;
|
|
711
716
|
}
|
|
712
|
-
return this.visit(n,
|
|
717
|
+
return this.visit(n, context);
|
|
713
718
|
});
|
|
714
719
|
if (parts.length > 1) {
|
|
715
720
|
return `OPERATOR(${parts.join('.')})`;
|
|
@@ -846,15 +851,15 @@ export class Deparser {
|
|
|
846
851
|
output.push(this.RangeVar(node.relation, context));
|
|
847
852
|
if (node.cols) {
|
|
848
853
|
const cols = ListUtils.unwrapList(node.cols);
|
|
849
|
-
const insertContext =
|
|
854
|
+
const insertContext = context.spawn('InsertStmt', { insertColumns: true });
|
|
850
855
|
const columnNames = cols.map(col => this.visit(col, insertContext));
|
|
851
|
-
if (
|
|
856
|
+
if (context.isPretty()) {
|
|
852
857
|
// Always format columns in multiline parentheses for pretty printing
|
|
853
|
-
const indentedColumns = columnNames.map(col =>
|
|
858
|
+
const indentedColumns = columnNames.map(col => context.indent(col));
|
|
854
859
|
output.push('(\n' + indentedColumns.join(',\n') + '\n)');
|
|
855
860
|
}
|
|
856
861
|
else {
|
|
857
|
-
output.push(
|
|
862
|
+
output.push(context.parens(columnNames.join(', ')));
|
|
858
863
|
}
|
|
859
864
|
}
|
|
860
865
|
if (node.selectStmt) {
|
|
@@ -876,7 +881,7 @@ export class Deparser {
|
|
|
876
881
|
else if (infer.indexElems) {
|
|
877
882
|
const elems = ListUtils.unwrapList(infer.indexElems);
|
|
878
883
|
const indexElems = elems.map(elem => this.visit(elem, context));
|
|
879
|
-
output.push(
|
|
884
|
+
output.push(context.parens(indexElems.join(', ')));
|
|
880
885
|
}
|
|
881
886
|
// Handle WHERE clause for conflict detection
|
|
882
887
|
if (infer.whereClause) {
|
|
@@ -892,12 +897,12 @@ export class Deparser {
|
|
|
892
897
|
if (firstTarget.ResTarget?.val?.MultiAssignRef && targetList.every(target => target.ResTarget?.val?.MultiAssignRef)) {
|
|
893
898
|
const sortedTargets = targetList.sort((a, b) => a.ResTarget.val.MultiAssignRef.colno - b.ResTarget.val.MultiAssignRef.colno);
|
|
894
899
|
const names = sortedTargets.map(target => target.ResTarget.name);
|
|
895
|
-
output.push(
|
|
900
|
+
output.push(context.parens(names.join(', ')));
|
|
896
901
|
output.push('=');
|
|
897
902
|
output.push(this.visit(firstTarget.ResTarget.val.MultiAssignRef.source, context));
|
|
898
903
|
}
|
|
899
904
|
else {
|
|
900
|
-
const updateContext =
|
|
905
|
+
const updateContext = context.spawn('UpdateStmt', { update: true });
|
|
901
906
|
const targets = targetList.map(target => this.visit(target, updateContext));
|
|
902
907
|
output.push(targets.join(', '));
|
|
903
908
|
}
|
|
@@ -951,12 +956,12 @@ export class Deparser {
|
|
|
951
956
|
}
|
|
952
957
|
}
|
|
953
958
|
const names = relatedTargets.map(t => t.ResTarget.name);
|
|
954
|
-
const multiAssignment = `${
|
|
959
|
+
const multiAssignment = `${context.parens(names.join(', '))} = ${this.visit(multiAssignRef.source, context)}`;
|
|
955
960
|
assignmentParts.push(multiAssignment);
|
|
956
961
|
}
|
|
957
962
|
else {
|
|
958
963
|
// Handle regular single-column assignment
|
|
959
|
-
assignmentParts.push(this.visit(target,
|
|
964
|
+
assignmentParts.push(this.visit(target, context.spawn('UpdateStmt', { update: true })));
|
|
960
965
|
processedTargets.add(i);
|
|
961
966
|
}
|
|
962
967
|
}
|
|
@@ -1048,14 +1053,14 @@ export class Deparser {
|
|
|
1048
1053
|
}
|
|
1049
1054
|
if (node.ctes && node.ctes.length > 0) {
|
|
1050
1055
|
const ctes = ListUtils.unwrapList(node.ctes);
|
|
1051
|
-
if (
|
|
1056
|
+
if (context.isPretty()) {
|
|
1052
1057
|
const cteStrings = ctes.map((cte, index) => {
|
|
1053
1058
|
const cteStr = this.visit(cte, context);
|
|
1054
|
-
const prefix = index === 0 ?
|
|
1059
|
+
const prefix = index === 0 ? context.newline() : ',' + context.newline();
|
|
1055
1060
|
if (this.containsMultilineStringLiteral(cteStr)) {
|
|
1056
1061
|
return prefix + cteStr;
|
|
1057
1062
|
}
|
|
1058
|
-
return prefix +
|
|
1063
|
+
return prefix + context.indent(cteStr);
|
|
1059
1064
|
});
|
|
1060
1065
|
output.push(cteStrings.join(''));
|
|
1061
1066
|
}
|
|
@@ -1141,14 +1146,14 @@ export class Deparser {
|
|
|
1141
1146
|
if (context.bool) {
|
|
1142
1147
|
formatStr = '(%s)';
|
|
1143
1148
|
}
|
|
1144
|
-
const boolContext =
|
|
1149
|
+
const boolContext = context.spawn('BoolExpr', { bool: true });
|
|
1145
1150
|
// explanation of our syntax/fix below:
|
|
1146
1151
|
// return formatStr.replace('%s', andArgs); // ❌ Interprets $ as special syntax
|
|
1147
1152
|
// return formatStr.replace('%s', () => andArgs); // ✅ Function callback prevents interpretation
|
|
1148
1153
|
switch (boolop) {
|
|
1149
1154
|
case 'AND_EXPR':
|
|
1150
|
-
if (
|
|
1151
|
-
const andArgs = args.map(arg => this.visit(arg, boolContext)).join(
|
|
1155
|
+
if (context.isPretty() && args.length > 1) {
|
|
1156
|
+
const andArgs = args.map(arg => this.visit(arg, boolContext)).join(context.newline() + context.indent('AND '));
|
|
1152
1157
|
return formatStr.replace('%s', () => andArgs);
|
|
1153
1158
|
}
|
|
1154
1159
|
else {
|
|
@@ -1156,8 +1161,8 @@ export class Deparser {
|
|
|
1156
1161
|
return formatStr.replace('%s', () => andArgs);
|
|
1157
1162
|
}
|
|
1158
1163
|
case 'OR_EXPR':
|
|
1159
|
-
if (
|
|
1160
|
-
const orArgs = args.map(arg => this.visit(arg, boolContext)).join(
|
|
1164
|
+
if (context.isPretty() && args.length > 1) {
|
|
1165
|
+
const orArgs = args.map(arg => this.visit(arg, boolContext)).join(context.newline() + context.indent('OR '));
|
|
1161
1166
|
return formatStr.replace('%s', () => orArgs);
|
|
1162
1167
|
}
|
|
1163
1168
|
else {
|
|
@@ -1288,9 +1293,9 @@ export class Deparser {
|
|
|
1288
1293
|
const timezone = this.visit(args[0], context);
|
|
1289
1294
|
// Add parentheses around timestamp if it contains arithmetic operations
|
|
1290
1295
|
if (args[1] && 'A_Expr' in args[1] && args[1].A_Expr?.kind === 'AEXPR_OP') {
|
|
1291
|
-
const op = this.deparseOperatorName(ListUtils.unwrapList(args[1].A_Expr.name));
|
|
1296
|
+
const op = this.deparseOperatorName(ListUtils.unwrapList(args[1].A_Expr.name), context);
|
|
1292
1297
|
if (op === '+' || op === '-' || op === '*' || op === '/') {
|
|
1293
|
-
timestamp =
|
|
1298
|
+
timestamp = context.parens(timestamp);
|
|
1294
1299
|
}
|
|
1295
1300
|
}
|
|
1296
1301
|
return `${timestamp} AT TIME ZONE ${timezone}`;
|
|
@@ -1360,14 +1365,14 @@ export class Deparser {
|
|
|
1360
1365
|
windowParts.push(`ORDER BY ${orderStrs.join(', ')}`);
|
|
1361
1366
|
}
|
|
1362
1367
|
// Handle window frame specifications using the dedicated formatWindowFrame method
|
|
1363
|
-
const frameClause = this.formatWindowFrame(node.over);
|
|
1368
|
+
const frameClause = this.formatWindowFrame(node.over, context.spawn('FuncCall'));
|
|
1364
1369
|
if (frameClause) {
|
|
1365
1370
|
windowParts.push(frameClause);
|
|
1366
1371
|
}
|
|
1367
1372
|
if (windowParts.length > 0) {
|
|
1368
|
-
if (
|
|
1369
|
-
const formattedParts = windowParts.map(part =>
|
|
1370
|
-
result += ` OVER (${
|
|
1373
|
+
if (context.isPretty() && windowParts.length > 1) {
|
|
1374
|
+
const formattedParts = windowParts.map(part => context.indent(part));
|
|
1375
|
+
result += ` OVER (${context.newline()}${formattedParts.join(context.newline())}${context.newline()})`;
|
|
1371
1376
|
}
|
|
1372
1377
|
else {
|
|
1373
1378
|
result += ` OVER (${windowParts.join(' ')})`;
|
|
@@ -1732,7 +1737,7 @@ export class Deparser {
|
|
|
1732
1737
|
}
|
|
1733
1738
|
return this.quoteIfNeeded(colStr);
|
|
1734
1739
|
});
|
|
1735
|
-
output.push('AS', this.quoteIfNeeded(name) +
|
|
1740
|
+
output.push('AS', this.quoteIfNeeded(name) + context.parens(quotedColnames.join(', ')));
|
|
1736
1741
|
}
|
|
1737
1742
|
else {
|
|
1738
1743
|
output.push('AS', this.quoteIfNeeded(name));
|
|
@@ -1744,7 +1749,7 @@ export class Deparser {
|
|
|
1744
1749
|
// Handle ONLY keyword for inheritance control (but not for type definitions, ALTER TYPE, or CREATE FOREIGN TABLE)
|
|
1745
1750
|
if (node && (!('inh' in node) || node.inh === undefined) &&
|
|
1746
1751
|
!context.parentNodeTypes.includes('CompositeTypeStmt') &&
|
|
1747
|
-
!context.parentNodeTypes.includes('AlterTypeStmt') &&
|
|
1752
|
+
(!context.parentNodeTypes.includes('AlterTypeStmt') && context.objtype !== 'OBJECT_TYPE') &&
|
|
1748
1753
|
!context.parentNodeTypes.includes('CreateForeignTableStmt')) {
|
|
1749
1754
|
output.push('ONLY');
|
|
1750
1755
|
}
|
|
@@ -2004,26 +2009,26 @@ export class Deparser {
|
|
|
2004
2009
|
output.push(this.visit(node.arg, context));
|
|
2005
2010
|
}
|
|
2006
2011
|
const args = ListUtils.unwrapList(node.args);
|
|
2007
|
-
if (
|
|
2012
|
+
if (context.isPretty() && args.length > 0) {
|
|
2008
2013
|
for (const arg of args) {
|
|
2009
2014
|
const whenClause = this.visit(arg, context);
|
|
2010
2015
|
if (this.containsMultilineStringLiteral(whenClause)) {
|
|
2011
|
-
output.push(
|
|
2016
|
+
output.push(context.newline() + whenClause);
|
|
2012
2017
|
}
|
|
2013
2018
|
else {
|
|
2014
|
-
output.push(
|
|
2019
|
+
output.push(context.newline() + context.indent(whenClause));
|
|
2015
2020
|
}
|
|
2016
2021
|
}
|
|
2017
2022
|
if (node.defresult) {
|
|
2018
2023
|
const elseResult = this.visit(node.defresult, context);
|
|
2019
2024
|
if (this.containsMultilineStringLiteral(elseResult)) {
|
|
2020
|
-
output.push(
|
|
2025
|
+
output.push(context.newline() + 'ELSE ' + elseResult);
|
|
2021
2026
|
}
|
|
2022
2027
|
else {
|
|
2023
|
-
output.push(
|
|
2028
|
+
output.push(context.newline() + context.indent('ELSE ' + elseResult));
|
|
2024
2029
|
}
|
|
2025
2030
|
}
|
|
2026
|
-
output.push(
|
|
2031
|
+
output.push(context.newline() + 'END');
|
|
2027
2032
|
return output.join(' ');
|
|
2028
2033
|
}
|
|
2029
2034
|
else {
|
|
@@ -2091,7 +2096,7 @@ export class Deparser {
|
|
|
2091
2096
|
}
|
|
2092
2097
|
BooleanTest(node, context) {
|
|
2093
2098
|
const output = [];
|
|
2094
|
-
const boolContext =
|
|
2099
|
+
const boolContext = context.spawn('BooleanTest', { bool: true });
|
|
2095
2100
|
output.push(this.visit(node.arg, boolContext));
|
|
2096
2101
|
switch (node.booltesttype) {
|
|
2097
2102
|
case 'IS_TRUE':
|
|
@@ -2242,31 +2247,31 @@ export class Deparser {
|
|
|
2242
2247
|
const elementStrs = elements.map(el => {
|
|
2243
2248
|
return this.deparse(el, context);
|
|
2244
2249
|
});
|
|
2245
|
-
output.push(
|
|
2250
|
+
output.push(context.parens(elementStrs.join(', ')));
|
|
2246
2251
|
}
|
|
2247
2252
|
}
|
|
2248
2253
|
else if (node.tableElts) {
|
|
2249
2254
|
const elements = ListUtils.unwrapList(node.tableElts);
|
|
2250
2255
|
const elementStrs = elements.map(el => {
|
|
2251
|
-
return this.deparse(el, context);
|
|
2256
|
+
return this.deparse(el, context.spawn('CreateStmt'));
|
|
2252
2257
|
});
|
|
2253
|
-
if (
|
|
2258
|
+
if (context.isPretty()) {
|
|
2254
2259
|
const formattedElements = elementStrs.map(el => {
|
|
2255
2260
|
const trimmedEl = el.trim();
|
|
2256
2261
|
// Remove leading newlines from constraint elements to avoid extra blank lines
|
|
2257
2262
|
if (trimmedEl.startsWith('\n')) {
|
|
2258
|
-
return
|
|
2263
|
+
return context.indent(trimmedEl.substring(1));
|
|
2259
2264
|
}
|
|
2260
|
-
return
|
|
2261
|
-
}).join(',' +
|
|
2262
|
-
output.push('(' +
|
|
2265
|
+
return context.indent(trimmedEl);
|
|
2266
|
+
}).join(',' + context.newline());
|
|
2267
|
+
output.push('(' + context.newline() + formattedElements + context.newline() + ')');
|
|
2263
2268
|
}
|
|
2264
2269
|
else {
|
|
2265
|
-
output.push(
|
|
2270
|
+
output.push(context.parens(elementStrs.join(', ')));
|
|
2266
2271
|
}
|
|
2267
2272
|
}
|
|
2268
2273
|
else if (!node.partbound) {
|
|
2269
|
-
output.push(
|
|
2274
|
+
output.push(context.parens(''));
|
|
2270
2275
|
}
|
|
2271
2276
|
if (node.partbound && node.inhRelations && node.inhRelations.length > 0) {
|
|
2272
2277
|
output.push('PARTITION OF');
|
|
@@ -2309,7 +2314,7 @@ export class Deparser {
|
|
|
2309
2314
|
output.push('INHERITS');
|
|
2310
2315
|
const inherits = ListUtils.unwrapList(node.inhRelations);
|
|
2311
2316
|
const inheritStrs = inherits.map(rel => this.visit(rel, context));
|
|
2312
|
-
output.push(
|
|
2317
|
+
output.push(context.parens(inheritStrs.join(', ')));
|
|
2313
2318
|
}
|
|
2314
2319
|
if (node.partspec) {
|
|
2315
2320
|
output.push('PARTITION BY');
|
|
@@ -2347,7 +2352,7 @@ export class Deparser {
|
|
|
2347
2352
|
}
|
|
2348
2353
|
// Handle table options like WITH (fillfactor=10)
|
|
2349
2354
|
if (node.options && node.options.length > 0) {
|
|
2350
|
-
const createStmtContext =
|
|
2355
|
+
const createStmtContext = context.spawn('CreateStmt');
|
|
2351
2356
|
const optionStrs = node.options.map((option) => {
|
|
2352
2357
|
return this.deparse(option, createStmtContext);
|
|
2353
2358
|
});
|
|
@@ -2370,7 +2375,7 @@ export class Deparser {
|
|
|
2370
2375
|
}
|
|
2371
2376
|
if (node.fdwoptions && node.fdwoptions.length > 0) {
|
|
2372
2377
|
output.push('OPTIONS');
|
|
2373
|
-
const columnContext =
|
|
2378
|
+
const columnContext = context.spawn('ColumnDef');
|
|
2374
2379
|
const options = ListUtils.unwrapList(node.fdwoptions).map(opt => this.visit(opt, columnContext));
|
|
2375
2380
|
output.push(`(${options.join(', ')})`);
|
|
2376
2381
|
}
|
|
@@ -2380,7 +2385,7 @@ export class Deparser {
|
|
|
2380
2385
|
if (node.constraints) {
|
|
2381
2386
|
const constraints = ListUtils.unwrapList(node.constraints);
|
|
2382
2387
|
const constraintStrs = constraints.map(constraint => {
|
|
2383
|
-
const columnConstraintContext =
|
|
2388
|
+
const columnConstraintContext = context.spawn('ColumnDef', { isColumnConstraint: true });
|
|
2384
2389
|
return this.visit(constraint, columnConstraintContext);
|
|
2385
2390
|
});
|
|
2386
2391
|
output.push(...constraintStrs);
|
|
@@ -2420,24 +2425,24 @@ export class Deparser {
|
|
|
2420
2425
|
}
|
|
2421
2426
|
break;
|
|
2422
2427
|
case 'CONSTR_CHECK':
|
|
2423
|
-
if (
|
|
2424
|
-
output.push('\n' +
|
|
2428
|
+
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2429
|
+
output.push('\n' + context.indent('CHECK'));
|
|
2425
2430
|
}
|
|
2426
2431
|
else {
|
|
2427
2432
|
output.push('CHECK');
|
|
2428
2433
|
}
|
|
2429
2434
|
if (node.raw_expr) {
|
|
2430
|
-
if (
|
|
2435
|
+
if (context.isPretty()) {
|
|
2431
2436
|
const checkExpr = this.visit(node.raw_expr, context);
|
|
2432
2437
|
if (checkExpr.includes('\n')) {
|
|
2433
|
-
output.push('(\n' +
|
|
2438
|
+
output.push('(\n' + context.indent(checkExpr) + '\n)');
|
|
2434
2439
|
}
|
|
2435
2440
|
else {
|
|
2436
2441
|
output.push(`(${checkExpr})`);
|
|
2437
2442
|
}
|
|
2438
2443
|
}
|
|
2439
2444
|
else {
|
|
2440
|
-
output.push(
|
|
2445
|
+
output.push(context.parens(this.visit(node.raw_expr, context)));
|
|
2441
2446
|
}
|
|
2442
2447
|
}
|
|
2443
2448
|
// Handle NOT VALID for check constraints
|
|
@@ -2459,7 +2464,7 @@ export class Deparser {
|
|
|
2459
2464
|
}
|
|
2460
2465
|
output.push('AS');
|
|
2461
2466
|
if (node.raw_expr) {
|
|
2462
|
-
output.push(
|
|
2467
|
+
output.push(context.parens(this.visit(node.raw_expr, context)));
|
|
2463
2468
|
}
|
|
2464
2469
|
output.push('STORED');
|
|
2465
2470
|
break;
|
|
@@ -2517,8 +2522,8 @@ export class Deparser {
|
|
|
2517
2522
|
}
|
|
2518
2523
|
break;
|
|
2519
2524
|
case 'CONSTR_UNIQUE':
|
|
2520
|
-
if (
|
|
2521
|
-
output.push('\n' +
|
|
2525
|
+
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2526
|
+
output.push('\n' + context.indent('UNIQUE'));
|
|
2522
2527
|
}
|
|
2523
2528
|
else {
|
|
2524
2529
|
output.push('UNIQUE');
|
|
@@ -2540,15 +2545,15 @@ export class Deparser {
|
|
|
2540
2545
|
case 'CONSTR_FOREIGN':
|
|
2541
2546
|
// Only add "FOREIGN KEY" for table-level constraints, not column-level constraints
|
|
2542
2547
|
if (!context.isColumnConstraint) {
|
|
2543
|
-
if (
|
|
2544
|
-
output.push('\n' +
|
|
2548
|
+
if (context.isPretty()) {
|
|
2549
|
+
output.push('\n' + context.indent('FOREIGN KEY'));
|
|
2545
2550
|
if (node.fk_attrs && node.fk_attrs.length > 0) {
|
|
2546
2551
|
const fkAttrs = ListUtils.unwrapList(node.fk_attrs)
|
|
2547
2552
|
.map(attr => this.visit(attr, context))
|
|
2548
2553
|
.join(', ');
|
|
2549
2554
|
output.push(`(${fkAttrs})`);
|
|
2550
2555
|
}
|
|
2551
|
-
output.push('\n' +
|
|
2556
|
+
output.push('\n' + context.indent('REFERENCES'));
|
|
2552
2557
|
}
|
|
2553
2558
|
else {
|
|
2554
2559
|
output.push('FOREIGN KEY');
|
|
@@ -2565,7 +2570,7 @@ export class Deparser {
|
|
|
2565
2570
|
output.push('REFERENCES');
|
|
2566
2571
|
}
|
|
2567
2572
|
if (node.pktable) {
|
|
2568
|
-
if (
|
|
2573
|
+
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2569
2574
|
const lastIndex = output.length - 1;
|
|
2570
2575
|
if (lastIndex >= 0 && output[lastIndex].includes('REFERENCES')) {
|
|
2571
2576
|
output[lastIndex] += ' ' + this.RangeVar(node.pktable, context);
|
|
@@ -2582,7 +2587,7 @@ export class Deparser {
|
|
|
2582
2587
|
const pkAttrs = ListUtils.unwrapList(node.pk_attrs)
|
|
2583
2588
|
.map(attr => this.visit(attr, context))
|
|
2584
2589
|
.join(', ');
|
|
2585
|
-
if (
|
|
2590
|
+
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2586
2591
|
const lastIndex = output.length - 1;
|
|
2587
2592
|
if (lastIndex >= 0) {
|
|
2588
2593
|
output[lastIndex] += ` (${pkAttrs})`;
|
|
@@ -2605,8 +2610,8 @@ export class Deparser {
|
|
|
2605
2610
|
matchClause = 'MATCH PARTIAL';
|
|
2606
2611
|
break;
|
|
2607
2612
|
}
|
|
2608
|
-
if (
|
|
2609
|
-
output.push('\n' +
|
|
2613
|
+
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2614
|
+
output.push('\n' + context.indent(matchClause));
|
|
2610
2615
|
}
|
|
2611
2616
|
else {
|
|
2612
2617
|
output.push(matchClause);
|
|
@@ -2628,8 +2633,8 @@ export class Deparser {
|
|
|
2628
2633
|
updateClause += 'SET DEFAULT';
|
|
2629
2634
|
break;
|
|
2630
2635
|
}
|
|
2631
|
-
if (
|
|
2632
|
-
output.push('\n' +
|
|
2636
|
+
if (context.isPretty()) {
|
|
2637
|
+
output.push('\n' + context.indent(updateClause));
|
|
2633
2638
|
}
|
|
2634
2639
|
else {
|
|
2635
2640
|
output.push('ON UPDATE');
|
|
@@ -2652,8 +2657,8 @@ export class Deparser {
|
|
|
2652
2657
|
deleteClause += 'SET DEFAULT';
|
|
2653
2658
|
break;
|
|
2654
2659
|
}
|
|
2655
|
-
if (
|
|
2656
|
-
output.push('\n' +
|
|
2660
|
+
if (context.isPretty()) {
|
|
2661
|
+
output.push('\n' + context.indent(deleteClause));
|
|
2657
2662
|
}
|
|
2658
2663
|
else {
|
|
2659
2664
|
output.push('ON DELETE');
|
|
@@ -2662,8 +2667,8 @@ export class Deparser {
|
|
|
2662
2667
|
}
|
|
2663
2668
|
// Handle NOT VALID for foreign key constraints - only for table constraints, not domain constraints
|
|
2664
2669
|
if (node.skip_validation && !context.isDomainConstraint) {
|
|
2665
|
-
if (
|
|
2666
|
-
output.push('\n' +
|
|
2670
|
+
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2671
|
+
output.push('\n' + context.indent('NOT VALID'));
|
|
2667
2672
|
}
|
|
2668
2673
|
else {
|
|
2669
2674
|
output.push('NOT VALID');
|
|
@@ -2721,13 +2726,13 @@ export class Deparser {
|
|
|
2721
2726
|
// Handle deferrable constraints for all constraint types that support it
|
|
2722
2727
|
if (node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_FOREIGN') {
|
|
2723
2728
|
if (node.deferrable) {
|
|
2724
|
-
if (
|
|
2725
|
-
output.push('\n' +
|
|
2729
|
+
if (context.isPretty() && node.contype === 'CONSTR_FOREIGN') {
|
|
2730
|
+
output.push('\n' + context.indent('DEFERRABLE'));
|
|
2726
2731
|
if (node.initdeferred === true) {
|
|
2727
|
-
output.push('\n' +
|
|
2732
|
+
output.push('\n' + context.indent('INITIALLY DEFERRED'));
|
|
2728
2733
|
}
|
|
2729
2734
|
else if (node.initdeferred === false) {
|
|
2730
|
-
output.push('\n' +
|
|
2735
|
+
output.push('\n' + context.indent('INITIALLY IMMEDIATE'));
|
|
2731
2736
|
}
|
|
2732
2737
|
}
|
|
2733
2738
|
else {
|
|
@@ -2741,15 +2746,15 @@ export class Deparser {
|
|
|
2741
2746
|
}
|
|
2742
2747
|
}
|
|
2743
2748
|
else if (node.deferrable === false) {
|
|
2744
|
-
if (
|
|
2745
|
-
output.push('\n' +
|
|
2749
|
+
if (context.isPretty() && node.contype === 'CONSTR_FOREIGN') {
|
|
2750
|
+
output.push('\n' + context.indent('NOT DEFERRABLE'));
|
|
2746
2751
|
}
|
|
2747
2752
|
else {
|
|
2748
2753
|
output.push('NOT DEFERRABLE');
|
|
2749
2754
|
}
|
|
2750
2755
|
}
|
|
2751
2756
|
}
|
|
2752
|
-
if (
|
|
2757
|
+
if (context.isPretty() && node.contype === 'CONSTR_FOREIGN') {
|
|
2753
2758
|
let result = '';
|
|
2754
2759
|
for (let i = 0; i < output.length; i++) {
|
|
2755
2760
|
if (output[i].startsWith('\n')) {
|
|
@@ -2767,12 +2772,12 @@ export class Deparser {
|
|
|
2767
2772
|
return output.join(' ');
|
|
2768
2773
|
}
|
|
2769
2774
|
SubLink(node, context) {
|
|
2770
|
-
const subselect =
|
|
2775
|
+
const subselect = context.parens(this.visit(node.subselect, context));
|
|
2771
2776
|
switch (node.subLinkType) {
|
|
2772
2777
|
case 'ANY_SUBLINK':
|
|
2773
2778
|
if (node.testexpr && node.operName) {
|
|
2774
2779
|
const testExpr = this.visit(node.testexpr, context);
|
|
2775
|
-
const operator = this.deparseOperatorName(node.operName);
|
|
2780
|
+
const operator = this.deparseOperatorName(node.operName, context);
|
|
2776
2781
|
return `${testExpr} ${operator} ANY ${subselect}`;
|
|
2777
2782
|
}
|
|
2778
2783
|
else if (node.testexpr) {
|
|
@@ -2783,7 +2788,7 @@ export class Deparser {
|
|
|
2783
2788
|
case 'ALL_SUBLINK':
|
|
2784
2789
|
if (node.testexpr && node.operName) {
|
|
2785
2790
|
const testExpr = this.visit(node.testexpr, context);
|
|
2786
|
-
const operator = this.deparseOperatorName(node.operName);
|
|
2791
|
+
const operator = this.deparseOperatorName(node.operName, context);
|
|
2787
2792
|
return `${testExpr} ${operator} ALL ${subselect}`;
|
|
2788
2793
|
}
|
|
2789
2794
|
return subselect;
|
|
@@ -2825,7 +2830,7 @@ export class Deparser {
|
|
|
2825
2830
|
}
|
|
2826
2831
|
// Only add frame clause if frameOptions indicates non-default framing
|
|
2827
2832
|
if (node.frameOptions && node.frameOptions !== 1058) {
|
|
2828
|
-
const frameClause = this.formatWindowFrame(node);
|
|
2833
|
+
const frameClause = this.formatWindowFrame(node, context.spawn('WindowDef'));
|
|
2829
2834
|
if (frameClause) {
|
|
2830
2835
|
windowParts.push(frameClause);
|
|
2831
2836
|
}
|
|
@@ -2845,7 +2850,7 @@ export class Deparser {
|
|
|
2845
2850
|
}
|
|
2846
2851
|
return output.join(' ');
|
|
2847
2852
|
}
|
|
2848
|
-
formatWindowFrame(node) {
|
|
2853
|
+
formatWindowFrame(node, context) {
|
|
2849
2854
|
if (!node.frameOptions)
|
|
2850
2855
|
return null;
|
|
2851
2856
|
const frameOptions = node.frameOptions;
|
|
@@ -2854,7 +2859,7 @@ export class Deparser {
|
|
|
2854
2859
|
if (frameOptions & 0x02) { // FRAMEOPTION_RANGE
|
|
2855
2860
|
frameParts.push('RANGE');
|
|
2856
2861
|
}
|
|
2857
|
-
else if (frameOptions & 0x04) { // FRAMEOPTION_ROWS
|
|
2862
|
+
else if (frameOptions & 0x04) { // FRAMEOPTION_ROWS
|
|
2858
2863
|
frameParts.push('ROWS');
|
|
2859
2864
|
}
|
|
2860
2865
|
else if (frameOptions & 0x08) { // FRAMEOPTION_GROUPS
|
|
@@ -2875,8 +2880,8 @@ export class Deparser {
|
|
|
2875
2880
|
}
|
|
2876
2881
|
else if (frameOptions === 18453) {
|
|
2877
2882
|
if (node.startOffset && node.endOffset) {
|
|
2878
|
-
boundsParts.push(`${this.visit(node.startOffset,
|
|
2879
|
-
boundsParts.push(`AND ${this.visit(node.endOffset,
|
|
2883
|
+
boundsParts.push(`${this.visit(node.startOffset, context)} PRECEDING`);
|
|
2884
|
+
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
2880
2885
|
}
|
|
2881
2886
|
}
|
|
2882
2887
|
else if (frameOptions === 1557) {
|
|
@@ -2886,7 +2891,7 @@ export class Deparser {
|
|
|
2886
2891
|
else if (frameOptions === 16917) {
|
|
2887
2892
|
boundsParts.push('CURRENT ROW');
|
|
2888
2893
|
if (node.endOffset) {
|
|
2889
|
-
boundsParts.push(`AND ${this.visit(node.endOffset,
|
|
2894
|
+
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
2890
2895
|
}
|
|
2891
2896
|
}
|
|
2892
2897
|
else if (frameOptions === 1058) {
|
|
@@ -2896,13 +2901,13 @@ export class Deparser {
|
|
|
2896
2901
|
// Handle start bound - prioritize explicit offset values over bit flags
|
|
2897
2902
|
if (node.startOffset) {
|
|
2898
2903
|
if (frameOptions & 0x400) { // FRAMEOPTION_START_VALUE_PRECEDING
|
|
2899
|
-
boundsParts.push(`${this.visit(node.startOffset,
|
|
2904
|
+
boundsParts.push(`${this.visit(node.startOffset, context)} PRECEDING`);
|
|
2900
2905
|
}
|
|
2901
2906
|
else if (frameOptions & 0x800) { // FRAMEOPTION_START_VALUE_FOLLOWING
|
|
2902
|
-
boundsParts.push(`${this.visit(node.startOffset,
|
|
2907
|
+
boundsParts.push(`${this.visit(node.startOffset, context)} FOLLOWING`);
|
|
2903
2908
|
}
|
|
2904
2909
|
else {
|
|
2905
|
-
boundsParts.push(`${this.visit(node.startOffset,
|
|
2910
|
+
boundsParts.push(`${this.visit(node.startOffset, context)} PRECEDING`);
|
|
2906
2911
|
}
|
|
2907
2912
|
}
|
|
2908
2913
|
else if (frameOptions & 0x10) { // FRAMEOPTION_START_UNBOUNDED_PRECEDING
|
|
@@ -2915,13 +2920,13 @@ export class Deparser {
|
|
|
2915
2920
|
if (node.endOffset) {
|
|
2916
2921
|
if (boundsParts.length > 0) {
|
|
2917
2922
|
if (frameOptions & 0x1000) { // FRAMEOPTION_END_VALUE_PRECEDING
|
|
2918
|
-
boundsParts.push(`AND ${this.visit(node.endOffset,
|
|
2923
|
+
boundsParts.push(`AND ${this.visit(node.endOffset, context)} PRECEDING`);
|
|
2919
2924
|
}
|
|
2920
2925
|
else if (frameOptions & 0x2000) { // FRAMEOPTION_END_VALUE_FOLLOWING
|
|
2921
|
-
boundsParts.push(`AND ${this.visit(node.endOffset,
|
|
2926
|
+
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
2922
2927
|
}
|
|
2923
2928
|
else {
|
|
2924
|
-
boundsParts.push(`AND ${this.visit(node.endOffset,
|
|
2929
|
+
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
2925
2930
|
}
|
|
2926
2931
|
}
|
|
2927
2932
|
}
|
|
@@ -3006,7 +3011,7 @@ export class Deparser {
|
|
|
3006
3011
|
const colnames = ListUtils.unwrapList(node.aliascolnames);
|
|
3007
3012
|
const colnameStrs = colnames.map(col => this.visit(col, context));
|
|
3008
3013
|
// Don't add space before column list parentheses to match original formatting
|
|
3009
|
-
output[output.length - 1] +=
|
|
3014
|
+
output[output.length - 1] += context.parens(colnameStrs.join(', '));
|
|
3010
3015
|
}
|
|
3011
3016
|
output.push('AS');
|
|
3012
3017
|
// Handle materialization clauses
|
|
@@ -3017,7 +3022,7 @@ export class Deparser {
|
|
|
3017
3022
|
output.push('MATERIALIZED');
|
|
3018
3023
|
}
|
|
3019
3024
|
if (node.ctequery) {
|
|
3020
|
-
output.push(
|
|
3025
|
+
output.push(context.parens(this.visit(node.ctequery, context)));
|
|
3021
3026
|
}
|
|
3022
3027
|
return output.join(' ');
|
|
3023
3028
|
}
|
|
@@ -3093,7 +3098,7 @@ export class Deparser {
|
|
|
3093
3098
|
DistinctExpr(node, context) {
|
|
3094
3099
|
const args = ListUtils.unwrapList(node.args);
|
|
3095
3100
|
if (args.length === 2) {
|
|
3096
|
-
const literalContext =
|
|
3101
|
+
const literalContext = context.spawn('DistinctExpr', { isStringLiteral: true });
|
|
3097
3102
|
const left = this.visit(args[0], literalContext);
|
|
3098
3103
|
const right = this.visit(args[1], literalContext);
|
|
3099
3104
|
return `${left} IS DISTINCT FROM ${right}`;
|
|
@@ -3103,7 +3108,7 @@ export class Deparser {
|
|
|
3103
3108
|
NullIfExpr(node, context) {
|
|
3104
3109
|
const args = ListUtils.unwrapList(node.args);
|
|
3105
3110
|
if (args.length === 2) {
|
|
3106
|
-
const literalContext =
|
|
3111
|
+
const literalContext = context.spawn('NullIfExpr', { isStringLiteral: true });
|
|
3107
3112
|
const left = this.visit(args[0], literalContext);
|
|
3108
3113
|
const right = this.visit(args[1], literalContext);
|
|
3109
3114
|
return `NULLIF(${left}, ${right})`;
|
|
@@ -3182,7 +3187,7 @@ export class Deparser {
|
|
|
3182
3187
|
}
|
|
3183
3188
|
RelabelType(node, context) {
|
|
3184
3189
|
if (node.arg) {
|
|
3185
|
-
const literalContext =
|
|
3190
|
+
const literalContext = context.spawn('RelabelType', { isStringLiteral: true });
|
|
3186
3191
|
return this.visit(node.arg, literalContext);
|
|
3187
3192
|
}
|
|
3188
3193
|
return '';
|
|
@@ -3201,7 +3206,7 @@ export class Deparser {
|
|
|
3201
3206
|
}
|
|
3202
3207
|
ConvertRowtypeExpr(node, context) {
|
|
3203
3208
|
if (node.arg) {
|
|
3204
|
-
const literalContext =
|
|
3209
|
+
const literalContext = context.spawn('ConvertRowtypeExpr', { isStringLiteral: true });
|
|
3205
3210
|
return this.visit(node.arg, literalContext);
|
|
3206
3211
|
}
|
|
3207
3212
|
return '';
|
|
@@ -3232,10 +3237,10 @@ export class Deparser {
|
|
|
3232
3237
|
}
|
|
3233
3238
|
if (node.aliases && node.aliases.length > 0) {
|
|
3234
3239
|
const aliasStrs = ListUtils.unwrapList(node.aliases).map(alias => this.visit(alias, context));
|
|
3235
|
-
output.push(
|
|
3240
|
+
output.push(context.parens(aliasStrs.join(', ')));
|
|
3236
3241
|
}
|
|
3237
3242
|
if (node.options && node.options.length > 0) {
|
|
3238
|
-
const viewContext =
|
|
3243
|
+
const viewContext = context.spawn('ViewStmt');
|
|
3239
3244
|
const optionStrs = ListUtils.unwrapList(node.options)
|
|
3240
3245
|
.map(option => this.visit(option, viewContext));
|
|
3241
3246
|
output.push(`WITH (${optionStrs.join(', ')})`);
|
|
@@ -3282,22 +3287,22 @@ export class Deparser {
|
|
|
3282
3287
|
}
|
|
3283
3288
|
if (node.indexParams && node.indexParams.length > 0) {
|
|
3284
3289
|
const paramStrs = ListUtils.unwrapList(node.indexParams).map(param => this.visit(param, context));
|
|
3285
|
-
output.push(
|
|
3290
|
+
output.push(context.parens(paramStrs.join(', ')));
|
|
3286
3291
|
}
|
|
3287
3292
|
if (node.indexIncludingParams && node.indexIncludingParams.length > 0) {
|
|
3288
3293
|
const includeStrs = ListUtils.unwrapList(node.indexIncludingParams).map(param => this.visit(param, context));
|
|
3289
3294
|
output.push('INCLUDE');
|
|
3290
|
-
output.push(
|
|
3295
|
+
output.push(context.parens(includeStrs.join(', ')));
|
|
3291
3296
|
}
|
|
3292
3297
|
if (node.whereClause) {
|
|
3293
3298
|
output.push('WHERE');
|
|
3294
3299
|
output.push(this.visit(node.whereClause, context));
|
|
3295
3300
|
}
|
|
3296
3301
|
if (node.options && node.options.length > 0) {
|
|
3297
|
-
const indexContext =
|
|
3302
|
+
const indexContext = context.spawn('IndexStmt');
|
|
3298
3303
|
const optionStrs = ListUtils.unwrapList(node.options).map(option => this.visit(option, indexContext));
|
|
3299
3304
|
output.push('WITH');
|
|
3300
|
-
output.push(
|
|
3305
|
+
output.push(context.parens(optionStrs.join(', ')));
|
|
3301
3306
|
}
|
|
3302
3307
|
if (node.nulls_not_distinct) {
|
|
3303
3308
|
output.push('NULLS NOT DISTINCT');
|
|
@@ -3314,7 +3319,7 @@ export class Deparser {
|
|
|
3314
3319
|
output.push(QuoteUtils.quote(node.name));
|
|
3315
3320
|
}
|
|
3316
3321
|
else if (node.expr) {
|
|
3317
|
-
output.push(
|
|
3322
|
+
output.push(context.parens(this.visit(node.expr, context)));
|
|
3318
3323
|
}
|
|
3319
3324
|
if (node.collation && node.collation.length > 0) {
|
|
3320
3325
|
const collationStrs = ListUtils.unwrapList(node.collation).map(coll => this.visit(coll, context));
|
|
@@ -3331,7 +3336,7 @@ export class Deparser {
|
|
|
3331
3336
|
const stringData = this.getNodeData(opt.DefElem.arg);
|
|
3332
3337
|
return `${opt.DefElem.defname}='${stringData.sval}'`;
|
|
3333
3338
|
}
|
|
3334
|
-
return this.visit(opt, context);
|
|
3339
|
+
return this.visit(opt, context.spawn('IndexElem'));
|
|
3335
3340
|
});
|
|
3336
3341
|
opclassStr += `(${opclassOpts.join(', ')})`;
|
|
3337
3342
|
}
|
|
@@ -3365,7 +3370,7 @@ export class Deparser {
|
|
|
3365
3370
|
output.push(QuoteUtils.quote(node.name));
|
|
3366
3371
|
}
|
|
3367
3372
|
else if (node.expr) {
|
|
3368
|
-
output.push(
|
|
3373
|
+
output.push(context.parens(this.visit(node.expr, context)));
|
|
3369
3374
|
}
|
|
3370
3375
|
if (node.collation && node.collation.length > 0) {
|
|
3371
3376
|
const collationStrs = ListUtils.unwrapList(node.collation).map(coll => this.visit(coll, context));
|
|
@@ -3513,16 +3518,16 @@ export class Deparser {
|
|
|
3513
3518
|
if (node.rarg && 'JoinExpr' in node.rarg && !node.rarg.JoinExpr.alias) {
|
|
3514
3519
|
rargStr = `(${rargStr})`;
|
|
3515
3520
|
}
|
|
3516
|
-
if (
|
|
3517
|
-
output.push(
|
|
3521
|
+
if (context.isPretty()) {
|
|
3522
|
+
output.push(context.newline() + joinStr + ' ' + rargStr);
|
|
3518
3523
|
}
|
|
3519
3524
|
else {
|
|
3520
3525
|
output.push(joinStr + ' ' + rargStr);
|
|
3521
3526
|
}
|
|
3522
3527
|
}
|
|
3523
3528
|
else {
|
|
3524
|
-
if (
|
|
3525
|
-
output.push(
|
|
3529
|
+
if (context.isPretty()) {
|
|
3530
|
+
output.push(context.newline() + joinStr);
|
|
3526
3531
|
}
|
|
3527
3532
|
else {
|
|
3528
3533
|
output.push(joinStr);
|
|
@@ -3531,7 +3536,7 @@ export class Deparser {
|
|
|
3531
3536
|
if (node.usingClause && node.usingClause.length > 0) {
|
|
3532
3537
|
const usingList = ListUtils.unwrapList(node.usingClause);
|
|
3533
3538
|
const columnNames = usingList.map(col => this.visit(col, context));
|
|
3534
|
-
if (
|
|
3539
|
+
if (context.isPretty()) {
|
|
3535
3540
|
output.push(` USING (${columnNames.join(', ')})`);
|
|
3536
3541
|
}
|
|
3537
3542
|
else {
|
|
@@ -3540,14 +3545,14 @@ export class Deparser {
|
|
|
3540
3545
|
}
|
|
3541
3546
|
else if (node.quals) {
|
|
3542
3547
|
const qualsStr = this.visit(node.quals, context);
|
|
3543
|
-
if (
|
|
3548
|
+
if (context.isPretty()) {
|
|
3544
3549
|
// For complex JOIN conditions, format with proper indentation
|
|
3545
3550
|
if (qualsStr.includes('AND') || qualsStr.includes('OR') || qualsStr.length > 50) {
|
|
3546
3551
|
if (this.containsMultilineStringLiteral(qualsStr)) {
|
|
3547
3552
|
output.push(` ON ${qualsStr}`);
|
|
3548
3553
|
}
|
|
3549
3554
|
else {
|
|
3550
|
-
output.push(` ON${
|
|
3555
|
+
output.push(` ON${context.newline()}${context.indent(qualsStr)}`);
|
|
3551
3556
|
}
|
|
3552
3557
|
}
|
|
3553
3558
|
else {
|
|
@@ -3559,7 +3564,7 @@ export class Deparser {
|
|
|
3559
3564
|
}
|
|
3560
3565
|
}
|
|
3561
3566
|
let result;
|
|
3562
|
-
if (
|
|
3567
|
+
if (context.isPretty()) {
|
|
3563
3568
|
result = output.join('');
|
|
3564
3569
|
}
|
|
3565
3570
|
else {
|
|
@@ -4162,7 +4167,7 @@ export class Deparser {
|
|
|
4162
4167
|
}).filter((name) => name && name.trim());
|
|
4163
4168
|
return items.join('.');
|
|
4164
4169
|
}
|
|
4165
|
-
const objContext =
|
|
4170
|
+
const objContext = context.spawn('DropStmt', { objtype: node.removeType });
|
|
4166
4171
|
const objName = this.visit(objList, objContext);
|
|
4167
4172
|
return objName;
|
|
4168
4173
|
}).filter((name) => name && name.trim()).join(', ');
|
|
@@ -4262,7 +4267,7 @@ export class Deparser {
|
|
|
4262
4267
|
if (node.options && node.options.length > 0) {
|
|
4263
4268
|
output.push('WITH');
|
|
4264
4269
|
const optionsStr = ListUtils.unwrapList(node.options)
|
|
4265
|
-
.map(opt => this.visit(opt, context))
|
|
4270
|
+
.map(opt => this.visit(opt, context.spawn('CopyStmt')))
|
|
4266
4271
|
.join(', ');
|
|
4267
4272
|
output.push(`(${optionsStr})`);
|
|
4268
4273
|
}
|
|
@@ -4308,21 +4313,19 @@ export class Deparser {
|
|
|
4308
4313
|
if (node.missing_ok) {
|
|
4309
4314
|
output.push('IF EXISTS');
|
|
4310
4315
|
}
|
|
4311
|
-
const alterContext = node.objtype
|
|
4312
|
-
? { ...context, parentNodeTypes: [...context.parentNodeTypes, 'AlterTypeStmt'] }
|
|
4313
|
-
: context;
|
|
4316
|
+
const alterContext = context.spawn('AlterTableStmt', { objtype: node.objtype });
|
|
4314
4317
|
if (node.relation) {
|
|
4315
4318
|
const relationStr = this.RangeVar(node.relation, alterContext);
|
|
4316
4319
|
output.push(relationStr);
|
|
4317
4320
|
}
|
|
4318
4321
|
if (node.cmds && node.cmds.length > 0) {
|
|
4319
4322
|
const commands = ListUtils.unwrapList(node.cmds);
|
|
4320
|
-
if (
|
|
4323
|
+
if (context.isPretty()) {
|
|
4321
4324
|
const commandsStr = commands
|
|
4322
4325
|
.map(cmd => {
|
|
4323
4326
|
const cmdStr = this.visit(cmd, alterContext);
|
|
4324
4327
|
if (cmdStr.startsWith('ADD CONSTRAINT') || cmdStr.startsWith('ADD ')) {
|
|
4325
|
-
return
|
|
4328
|
+
return context.newline() + context.indent(cmdStr);
|
|
4326
4329
|
}
|
|
4327
4330
|
return cmdStr;
|
|
4328
4331
|
})
|
|
@@ -4343,7 +4346,7 @@ export class Deparser {
|
|
|
4343
4346
|
if (node.subtype) {
|
|
4344
4347
|
switch (node.subtype) {
|
|
4345
4348
|
case 'AT_AddColumn':
|
|
4346
|
-
if (context.
|
|
4349
|
+
if (context.objtype === 'OBJECT_TYPE') {
|
|
4347
4350
|
output.push('ADD ATTRIBUTE');
|
|
4348
4351
|
}
|
|
4349
4352
|
else {
|
|
@@ -4363,14 +4366,14 @@ export class Deparser {
|
|
|
4363
4366
|
}
|
|
4364
4367
|
if (colDefData.fdwoptions && colDefData.fdwoptions.length > 0) {
|
|
4365
4368
|
parts.push('OPTIONS');
|
|
4366
|
-
const columnContext =
|
|
4369
|
+
const columnContext = context.spawn('ColumnDef');
|
|
4367
4370
|
const options = ListUtils.unwrapList(colDefData.fdwoptions).map(opt => this.visit(opt, columnContext));
|
|
4368
4371
|
parts.push(`(${options.join(', ')})`);
|
|
4369
4372
|
}
|
|
4370
4373
|
if (colDefData.constraints) {
|
|
4371
4374
|
const constraints = ListUtils.unwrapList(colDefData.constraints);
|
|
4372
4375
|
const constraintStrs = constraints.map(constraint => {
|
|
4373
|
-
const columnConstraintContext =
|
|
4376
|
+
const columnConstraintContext = context.spawn('ColumnDef', { isColumnConstraint: true });
|
|
4374
4377
|
return this.visit(constraint, columnConstraintContext);
|
|
4375
4378
|
});
|
|
4376
4379
|
parts.push(...constraintStrs);
|
|
@@ -4390,7 +4393,7 @@ export class Deparser {
|
|
|
4390
4393
|
break;
|
|
4391
4394
|
case 'AT_DropColumn':
|
|
4392
4395
|
if (node.missing_ok) {
|
|
4393
|
-
if (context.
|
|
4396
|
+
if (context.objtype === 'OBJECT_TYPE') {
|
|
4394
4397
|
output.push('DROP ATTRIBUTE IF EXISTS');
|
|
4395
4398
|
}
|
|
4396
4399
|
else {
|
|
@@ -4398,7 +4401,7 @@ export class Deparser {
|
|
|
4398
4401
|
}
|
|
4399
4402
|
}
|
|
4400
4403
|
else {
|
|
4401
|
-
if (context.
|
|
4404
|
+
if (context.objtype === 'OBJECT_TYPE') {
|
|
4402
4405
|
output.push('DROP ATTRIBUTE');
|
|
4403
4406
|
}
|
|
4404
4407
|
else {
|
|
@@ -4416,7 +4419,7 @@ export class Deparser {
|
|
|
4416
4419
|
}
|
|
4417
4420
|
break;
|
|
4418
4421
|
case 'AT_AlterColumnType':
|
|
4419
|
-
if (context.
|
|
4422
|
+
if (context.objtype === 'OBJECT_TYPE') {
|
|
4420
4423
|
output.push('ALTER ATTRIBUTE');
|
|
4421
4424
|
}
|
|
4422
4425
|
else {
|
|
@@ -4480,7 +4483,7 @@ export class Deparser {
|
|
|
4480
4483
|
case 'AT_SetRelOptions':
|
|
4481
4484
|
output.push('SET');
|
|
4482
4485
|
if (node.def) {
|
|
4483
|
-
const alterTableContext =
|
|
4486
|
+
const alterTableContext = context.spawn('AlterTableCmd', { subtype: 'AT_SetRelOptions' });
|
|
4484
4487
|
const options = ListUtils.unwrapList(node.def)
|
|
4485
4488
|
.map(option => this.visit(option, alterTableContext))
|
|
4486
4489
|
.join(', ');
|
|
@@ -4493,7 +4496,7 @@ export class Deparser {
|
|
|
4493
4496
|
case 'AT_ResetRelOptions':
|
|
4494
4497
|
output.push('RESET');
|
|
4495
4498
|
if (node.def) {
|
|
4496
|
-
const alterTableContext =
|
|
4499
|
+
const alterTableContext = context.spawn('AlterTableCmd', { subtype: 'AT_ResetRelOptions' });
|
|
4497
4500
|
const options = ListUtils.unwrapList(node.def)
|
|
4498
4501
|
.map(option => this.visit(option, alterTableContext))
|
|
4499
4502
|
.join(', ');
|
|
@@ -4588,7 +4591,7 @@ export class Deparser {
|
|
|
4588
4591
|
}
|
|
4589
4592
|
output.push('SET');
|
|
4590
4593
|
if (node.def) {
|
|
4591
|
-
const alterTableContext =
|
|
4594
|
+
const alterTableContext = context.spawn('AlterTableCmd', { subtype: 'AT_SetOptions' });
|
|
4592
4595
|
const options = ListUtils.unwrapList(node.def)
|
|
4593
4596
|
.map(option => this.visit(option, alterTableContext))
|
|
4594
4597
|
.join(', ');
|
|
@@ -4605,7 +4608,7 @@ export class Deparser {
|
|
|
4605
4608
|
}
|
|
4606
4609
|
output.push('RESET');
|
|
4607
4610
|
if (node.def) {
|
|
4608
|
-
const alterTableContext =
|
|
4611
|
+
const alterTableContext = context.spawn('AlterTableCmd', { subtype: 'AT_ResetOptions' });
|
|
4609
4612
|
const options = ListUtils.unwrapList(node.def)
|
|
4610
4613
|
.map(option => this.visit(option, alterTableContext))
|
|
4611
4614
|
.join(', ');
|
|
@@ -4846,7 +4849,7 @@ export class Deparser {
|
|
|
4846
4849
|
}
|
|
4847
4850
|
output.push('OPTIONS');
|
|
4848
4851
|
if (node.def) {
|
|
4849
|
-
const alterColumnContext =
|
|
4852
|
+
const alterColumnContext = context.spawn('AlterTableCmd', { alterColumnOptions: true });
|
|
4850
4853
|
const options = ListUtils.unwrapList(node.def)
|
|
4851
4854
|
.map(option => this.visit(option, alterColumnContext))
|
|
4852
4855
|
.join(', ');
|
|
@@ -4886,7 +4889,7 @@ export class Deparser {
|
|
|
4886
4889
|
case 'AT_GenericOptions':
|
|
4887
4890
|
output.push('OPTIONS');
|
|
4888
4891
|
if (node.def) {
|
|
4889
|
-
const alterTableContext =
|
|
4892
|
+
const alterTableContext = context.spawn('AlterTableCmd', { alterTableOptions: true });
|
|
4890
4893
|
const options = ListUtils.unwrapList(node.def)
|
|
4891
4894
|
.map(option => this.visit(option, alterTableContext))
|
|
4892
4895
|
.join(', ');
|
|
@@ -4990,7 +4993,7 @@ export class Deparser {
|
|
|
4990
4993
|
output.push(this.TypeName(node.returnType, context));
|
|
4991
4994
|
}
|
|
4992
4995
|
if (node.options && node.options.length > 0) {
|
|
4993
|
-
const funcContext =
|
|
4996
|
+
const funcContext = context.spawn('CreateFunctionStmt');
|
|
4994
4997
|
const options = node.options.map((opt) => this.visit(opt, funcContext));
|
|
4995
4998
|
output.push(...options);
|
|
4996
4999
|
}
|
|
@@ -5077,7 +5080,7 @@ export class Deparser {
|
|
|
5077
5080
|
}
|
|
5078
5081
|
output.push('AS', 'ENUM');
|
|
5079
5082
|
if (node.vals && node.vals.length > 0) {
|
|
5080
|
-
const enumContext =
|
|
5083
|
+
const enumContext = context.spawn('CreateEnumStmt', { isEnumValue: true });
|
|
5081
5084
|
const values = ListUtils.unwrapList(node.vals)
|
|
5082
5085
|
.map(val => this.visit(val, enumContext))
|
|
5083
5086
|
.join(', ');
|
|
@@ -5132,9 +5135,8 @@ export class Deparser {
|
|
|
5132
5135
|
output.push(roleName);
|
|
5133
5136
|
}
|
|
5134
5137
|
if (node.options) {
|
|
5135
|
-
const roleContext = { ...context, parentNodeTypes: [...context.parentNodeTypes, 'CreateRoleStmt'] };
|
|
5136
5138
|
const options = ListUtils.unwrapList(node.options)
|
|
5137
|
-
.map(option => this.visit(option,
|
|
5139
|
+
.map(option => this.visit(option, context.spawn('CreateRoleStmt')))
|
|
5138
5140
|
.join(' ');
|
|
5139
5141
|
if (options) {
|
|
5140
5142
|
output.push('WITH');
|
|
@@ -5165,7 +5167,7 @@ export class Deparser {
|
|
|
5165
5167
|
const stringData = this.getNodeData(node.arg);
|
|
5166
5168
|
return `${node.defname}='${stringData.sval}'`;
|
|
5167
5169
|
}
|
|
5168
|
-
return `${node.defname}=${this.visit(node.arg,
|
|
5170
|
+
return `${node.defname}=${this.visit(node.arg, context.spawn('DefElem'))}`;
|
|
5169
5171
|
}
|
|
5170
5172
|
// Handle CREATE OPERATOR boolean flags - MUST be first to preserve case
|
|
5171
5173
|
if (context.parentNodeTypes.includes('DefineStmt') &&
|
|
@@ -5181,13 +5183,13 @@ export class Deparser {
|
|
|
5181
5183
|
if (!node.arg) {
|
|
5182
5184
|
return `NO ${node.defname.toUpperCase()}`;
|
|
5183
5185
|
}
|
|
5184
|
-
const defElemContext =
|
|
5186
|
+
const defElemContext = context.spawn('DefElem');
|
|
5185
5187
|
const argValue = this.visit(node.arg, defElemContext);
|
|
5186
5188
|
return `${node.defname.toUpperCase()} ${argValue}`;
|
|
5187
5189
|
}
|
|
5188
5190
|
// Handle OPTIONS clause - use space format, not equals format
|
|
5189
5191
|
if (node.arg) {
|
|
5190
|
-
const defElemContext =
|
|
5192
|
+
const defElemContext = context.spawn('DefElem');
|
|
5191
5193
|
const argValue = this.visit(node.arg, defElemContext);
|
|
5192
5194
|
if (context.parentNodeTypes.includes('CreateFdwStmt') || context.parentNodeTypes.includes('AlterFdwStmt')) {
|
|
5193
5195
|
const finalValue = typeof argValue === 'string' && !argValue.startsWith("'")
|
|
@@ -5241,7 +5243,7 @@ export class Deparser {
|
|
|
5241
5243
|
if (!node.arg) {
|
|
5242
5244
|
return 'PASSWORD NULL';
|
|
5243
5245
|
}
|
|
5244
|
-
const defElemContext =
|
|
5246
|
+
const defElemContext = context.spawn('DefElem');
|
|
5245
5247
|
const argValue = this.visit(node.arg, defElemContext);
|
|
5246
5248
|
const quotedValue = typeof argValue === 'string' && !argValue.startsWith("'")
|
|
5247
5249
|
? `'${argValue}'`
|
|
@@ -5250,7 +5252,7 @@ export class Deparser {
|
|
|
5250
5252
|
}
|
|
5251
5253
|
}
|
|
5252
5254
|
if (node.arg) {
|
|
5253
|
-
const defElemContext =
|
|
5255
|
+
const defElemContext = context.spawn('DefElem');
|
|
5254
5256
|
const argValue = this.visit(node.arg, defElemContext);
|
|
5255
5257
|
if (context.parentNodeTypes.includes('AlterOperatorStmt')) {
|
|
5256
5258
|
if (node.arg && this.getNodeType(node.arg) === 'TypeName') {
|
|
@@ -5326,7 +5328,7 @@ export class Deparser {
|
|
|
5326
5328
|
if (node.defname === 'sysid') {
|
|
5327
5329
|
return `SYSID ${argValue}`;
|
|
5328
5330
|
}
|
|
5329
|
-
if (argValue === 'true') {
|
|
5331
|
+
if (String(argValue) === 'true') {
|
|
5330
5332
|
// Handle special cases where the positive form has a different name
|
|
5331
5333
|
if (node.defname === 'isreplication') {
|
|
5332
5334
|
return 'REPLICATION';
|
|
@@ -5336,7 +5338,7 @@ export class Deparser {
|
|
|
5336
5338
|
}
|
|
5337
5339
|
return node.defname.toUpperCase();
|
|
5338
5340
|
}
|
|
5339
|
-
else if (argValue === 'false') {
|
|
5341
|
+
else if (String(argValue) === 'false') {
|
|
5340
5342
|
// Handle special cases where the negative form has a different name
|
|
5341
5343
|
if (node.defname === 'canlogin') {
|
|
5342
5344
|
return 'NOLOGIN';
|
|
@@ -5400,7 +5402,7 @@ export class Deparser {
|
|
|
5400
5402
|
}
|
|
5401
5403
|
if (context.parentNodeTypes.includes('DoStmt')) {
|
|
5402
5404
|
if (node.defname === 'as') {
|
|
5403
|
-
const defElemContext =
|
|
5405
|
+
const defElemContext = context.spawn('DefElem');
|
|
5404
5406
|
const argValue = node.arg ? this.visit(node.arg, defElemContext) : '';
|
|
5405
5407
|
if (Array.isArray(argValue)) {
|
|
5406
5408
|
const bodyParts = argValue;
|
|
@@ -5691,7 +5693,7 @@ export class Deparser {
|
|
|
5691
5693
|
}
|
|
5692
5694
|
if (node.options && node.options.length > 0) {
|
|
5693
5695
|
output.push('WITH');
|
|
5694
|
-
const tsContext =
|
|
5696
|
+
const tsContext = context.spawn('CreateTableSpaceStmt');
|
|
5695
5697
|
const options = ListUtils.unwrapList(node.options)
|
|
5696
5698
|
.map(option => this.visit(option, tsContext))
|
|
5697
5699
|
.join(', ');
|
|
@@ -5721,7 +5723,7 @@ export class Deparser {
|
|
|
5721
5723
|
output.push('SET');
|
|
5722
5724
|
}
|
|
5723
5725
|
if (node.options && node.options.length > 0) {
|
|
5724
|
-
const tablespaceContext =
|
|
5726
|
+
const tablespaceContext = context.spawn('AlterTableSpaceOptionsStmt');
|
|
5725
5727
|
const options = ListUtils.unwrapList(node.options)
|
|
5726
5728
|
.map(option => this.visit(option, tablespaceContext))
|
|
5727
5729
|
.join(', ');
|
|
@@ -5738,7 +5740,7 @@ export class Deparser {
|
|
|
5738
5740
|
output.push(this.quoteIfNeeded(node.extname));
|
|
5739
5741
|
}
|
|
5740
5742
|
if (node.options && node.options.length > 0) {
|
|
5741
|
-
const extContext =
|
|
5743
|
+
const extContext = context.spawn('CreateExtensionStmt');
|
|
5742
5744
|
const options = ListUtils.unwrapList(node.options)
|
|
5743
5745
|
.map(option => this.visit(option, extContext))
|
|
5744
5746
|
.join(' ');
|
|
@@ -5752,7 +5754,7 @@ export class Deparser {
|
|
|
5752
5754
|
output.push(this.quoteIfNeeded(node.extname));
|
|
5753
5755
|
}
|
|
5754
5756
|
if (node.options && node.options.length > 0) {
|
|
5755
|
-
const extContext =
|
|
5757
|
+
const extContext = context.spawn('AlterExtensionStmt');
|
|
5756
5758
|
const options = ListUtils.unwrapList(node.options)
|
|
5757
5759
|
.map(option => this.visit(option, extContext))
|
|
5758
5760
|
.join(' ');
|
|
@@ -5766,7 +5768,7 @@ export class Deparser {
|
|
|
5766
5768
|
output.push(node.fdwname);
|
|
5767
5769
|
}
|
|
5768
5770
|
if (node.func_options && node.func_options.length > 0) {
|
|
5769
|
-
const fdwContext =
|
|
5771
|
+
const fdwContext = context.spawn('CreateFdwStmt');
|
|
5770
5772
|
const funcOptions = ListUtils.unwrapList(node.func_options)
|
|
5771
5773
|
.map(option => this.visit(option, fdwContext))
|
|
5772
5774
|
.join(' ');
|
|
@@ -5774,7 +5776,7 @@ export class Deparser {
|
|
|
5774
5776
|
}
|
|
5775
5777
|
if (node.options && node.options.length > 0) {
|
|
5776
5778
|
output.push('OPTIONS');
|
|
5777
|
-
const fdwContext =
|
|
5779
|
+
const fdwContext = context.spawn('CreateFdwStmt');
|
|
5778
5780
|
const options = ListUtils.unwrapList(node.options)
|
|
5779
5781
|
.map(option => this.visit(option, fdwContext))
|
|
5780
5782
|
.join(', ');
|
|
@@ -5876,7 +5878,7 @@ export class Deparser {
|
|
|
5876
5878
|
output.push('ADD');
|
|
5877
5879
|
if (node.def) {
|
|
5878
5880
|
// Pass domain context to avoid adding constraint names for domain constraints
|
|
5879
|
-
const domainContext =
|
|
5881
|
+
const domainContext = context.spawn('CreateDomainStmt', { isDomainConstraint: true });
|
|
5880
5882
|
output.push(this.visit(node.def, domainContext));
|
|
5881
5883
|
}
|
|
5882
5884
|
break;
|
|
@@ -5902,7 +5904,7 @@ export class Deparser {
|
|
|
5902
5904
|
output.push('ADD');
|
|
5903
5905
|
if (node.def) {
|
|
5904
5906
|
// Pass domain context to avoid adding constraint names for domain constraints
|
|
5905
|
-
const domainContext =
|
|
5907
|
+
const domainContext = context.spawn('CreateDomainStmt', { isDomainConstraint: true });
|
|
5906
5908
|
output.push(this.visit(node.def, domainContext));
|
|
5907
5909
|
}
|
|
5908
5910
|
break;
|
|
@@ -6264,7 +6266,7 @@ export class Deparser {
|
|
|
6264
6266
|
output.push(`${operatorName}(${args.join(', ')})`);
|
|
6265
6267
|
}
|
|
6266
6268
|
else {
|
|
6267
|
-
const objContext =
|
|
6269
|
+
const objContext = context.spawn('CommentStmt', { objtype: node.objtype });
|
|
6268
6270
|
output.push(this.visit(node.object, objContext));
|
|
6269
6271
|
}
|
|
6270
6272
|
}
|
|
@@ -6315,8 +6317,8 @@ export class Deparser {
|
|
|
6315
6317
|
output.push(initialParts.join(' '));
|
|
6316
6318
|
// Add ON clause on new line in pretty mode
|
|
6317
6319
|
if (node.table) {
|
|
6318
|
-
if (
|
|
6319
|
-
output.push(
|
|
6320
|
+
if (context.isPretty()) {
|
|
6321
|
+
output.push(context.newline() + context.indent(`ON ${this.RangeVar(node.table, context)}`));
|
|
6320
6322
|
}
|
|
6321
6323
|
else {
|
|
6322
6324
|
output.push('ON');
|
|
@@ -6325,24 +6327,24 @@ export class Deparser {
|
|
|
6325
6327
|
}
|
|
6326
6328
|
// Handle AS RESTRICTIVE/PERMISSIVE clause
|
|
6327
6329
|
if (node.permissive === undefined) {
|
|
6328
|
-
if (
|
|
6329
|
-
output.push(
|
|
6330
|
+
if (context.isPretty()) {
|
|
6331
|
+
output.push(context.newline() + context.indent('AS RESTRICTIVE'));
|
|
6330
6332
|
}
|
|
6331
6333
|
else {
|
|
6332
6334
|
output.push('AS', 'RESTRICTIVE');
|
|
6333
6335
|
}
|
|
6334
6336
|
}
|
|
6335
6337
|
else if (node.permissive === true) {
|
|
6336
|
-
if (
|
|
6337
|
-
output.push(
|
|
6338
|
+
if (context.isPretty()) {
|
|
6339
|
+
output.push(context.newline() + context.indent('AS PERMISSIVE'));
|
|
6338
6340
|
}
|
|
6339
6341
|
else {
|
|
6340
6342
|
output.push('AS', 'PERMISSIVE');
|
|
6341
6343
|
}
|
|
6342
6344
|
}
|
|
6343
6345
|
if (node.cmd_name) {
|
|
6344
|
-
if (
|
|
6345
|
-
output.push(
|
|
6346
|
+
if (context.isPretty()) {
|
|
6347
|
+
output.push(context.newline() + context.indent(`FOR ${node.cmd_name.toUpperCase()}`));
|
|
6346
6348
|
}
|
|
6347
6349
|
else {
|
|
6348
6350
|
output.push('FOR', node.cmd_name.toUpperCase());
|
|
@@ -6350,8 +6352,8 @@ export class Deparser {
|
|
|
6350
6352
|
}
|
|
6351
6353
|
if (node.roles && node.roles.length > 0) {
|
|
6352
6354
|
const roles = ListUtils.unwrapList(node.roles).map(role => this.visit(role, context));
|
|
6353
|
-
if (
|
|
6354
|
-
output.push(
|
|
6355
|
+
if (context.isPretty()) {
|
|
6356
|
+
output.push(context.newline() + context.indent(`TO ${roles.join(', ')}`));
|
|
6355
6357
|
}
|
|
6356
6358
|
else {
|
|
6357
6359
|
output.push('TO');
|
|
@@ -6359,11 +6361,11 @@ export class Deparser {
|
|
|
6359
6361
|
}
|
|
6360
6362
|
}
|
|
6361
6363
|
if (node.qual) {
|
|
6362
|
-
if (
|
|
6364
|
+
if (context.isPretty()) {
|
|
6363
6365
|
const qualExpr = this.visit(node.qual, context);
|
|
6364
|
-
output.push(
|
|
6365
|
-
output.push(
|
|
6366
|
-
output.push(
|
|
6366
|
+
output.push(context.newline() + context.indent('USING ('));
|
|
6367
|
+
output.push(context.newline() + context.indent(context.indent(qualExpr)));
|
|
6368
|
+
output.push(context.newline() + context.indent(')'));
|
|
6367
6369
|
}
|
|
6368
6370
|
else {
|
|
6369
6371
|
output.push('USING');
|
|
@@ -6371,18 +6373,18 @@ export class Deparser {
|
|
|
6371
6373
|
}
|
|
6372
6374
|
}
|
|
6373
6375
|
if (node.with_check) {
|
|
6374
|
-
if (
|
|
6376
|
+
if (context.isPretty()) {
|
|
6375
6377
|
const checkExpr = this.visit(node.with_check, context);
|
|
6376
|
-
output.push(
|
|
6377
|
-
output.push(
|
|
6378
|
-
output.push(
|
|
6378
|
+
output.push(context.newline() + context.indent('WITH CHECK ('));
|
|
6379
|
+
output.push(context.newline() + context.indent(context.indent(checkExpr)));
|
|
6380
|
+
output.push(context.newline() + context.indent(')'));
|
|
6379
6381
|
}
|
|
6380
6382
|
else {
|
|
6381
6383
|
output.push('WITH CHECK');
|
|
6382
6384
|
output.push(`(${this.visit(node.with_check, context)})`);
|
|
6383
6385
|
}
|
|
6384
6386
|
}
|
|
6385
|
-
return
|
|
6387
|
+
return context.isPretty() ? output.join('') : output.join(' ');
|
|
6386
6388
|
}
|
|
6387
6389
|
AlterPolicyStmt(node, context) {
|
|
6388
6390
|
const output = ['ALTER', 'POLICY'];
|
|
@@ -6427,7 +6429,7 @@ export class Deparser {
|
|
|
6427
6429
|
}
|
|
6428
6430
|
if (node.options && node.options.length > 0) {
|
|
6429
6431
|
output.push('OPTIONS');
|
|
6430
|
-
const userMappingContext =
|
|
6432
|
+
const userMappingContext = context.spawn('CreateUserMappingStmt');
|
|
6431
6433
|
const options = ListUtils.unwrapList(node.options).map(opt => this.visit(opt, userMappingContext));
|
|
6432
6434
|
output.push(`(${options.join(', ')})`);
|
|
6433
6435
|
}
|
|
@@ -6610,7 +6612,7 @@ export class Deparser {
|
|
|
6610
6612
|
DoStmt(node, context) {
|
|
6611
6613
|
const output = ['DO'];
|
|
6612
6614
|
if (node.args && node.args.length > 0) {
|
|
6613
|
-
const doContext =
|
|
6615
|
+
const doContext = context.spawn('DoStmt');
|
|
6614
6616
|
const args = ListUtils.unwrapList(node.args);
|
|
6615
6617
|
const processedArgs = [];
|
|
6616
6618
|
for (const arg of args) {
|
|
@@ -6915,7 +6917,7 @@ export class Deparser {
|
|
|
6915
6917
|
ObjectWithArgs(node, context) {
|
|
6916
6918
|
let result = '';
|
|
6917
6919
|
if (node.objname && node.objname.length > 0) {
|
|
6918
|
-
const objContext =
|
|
6920
|
+
const objContext = context.spawn('ObjectWithArgs');
|
|
6919
6921
|
const names = ListUtils.unwrapList(node.objname).map(name => this.visit(name, objContext));
|
|
6920
6922
|
result = names.join('.');
|
|
6921
6923
|
}
|
|
@@ -6957,7 +6959,7 @@ export class Deparser {
|
|
|
6957
6959
|
}
|
|
6958
6960
|
output.push('SET');
|
|
6959
6961
|
if (node.options && node.options.length > 0) {
|
|
6960
|
-
const alterOpContext =
|
|
6962
|
+
const alterOpContext = context.spawn('AlterOperatorStmt');
|
|
6961
6963
|
const options = ListUtils.unwrapList(node.options).map(opt => this.visit(opt, alterOpContext));
|
|
6962
6964
|
output.push(`(${options.join(', ')})`);
|
|
6963
6965
|
}
|
|
@@ -6969,13 +6971,13 @@ export class Deparser {
|
|
|
6969
6971
|
output.push(QuoteUtils.quote(node.fdwname));
|
|
6970
6972
|
}
|
|
6971
6973
|
if (node.func_options && node.func_options.length > 0) {
|
|
6972
|
-
const fdwContext =
|
|
6974
|
+
const fdwContext = context.spawn('AlterFdwStmt');
|
|
6973
6975
|
const funcOptions = ListUtils.unwrapList(node.func_options).map(opt => this.visit(opt, fdwContext));
|
|
6974
6976
|
output.push(funcOptions.join(' '));
|
|
6975
6977
|
}
|
|
6976
6978
|
if (node.options && node.options.length > 0) {
|
|
6977
6979
|
output.push('OPTIONS');
|
|
6978
|
-
const fdwContext =
|
|
6980
|
+
const fdwContext = context.spawn('AlterFdwStmt');
|
|
6979
6981
|
const options = ListUtils.unwrapList(node.options).map(opt => this.visit(opt, fdwContext));
|
|
6980
6982
|
output.push(`(${options.join(', ')})`);
|
|
6981
6983
|
}
|
|
@@ -7001,7 +7003,7 @@ export class Deparser {
|
|
|
7001
7003
|
if (node.options && node.options.length > 0) {
|
|
7002
7004
|
output.push('OPTIONS');
|
|
7003
7005
|
output.push('(');
|
|
7004
|
-
const optionsContext =
|
|
7006
|
+
const optionsContext = context.spawn('CreateForeignServerStmt');
|
|
7005
7007
|
const options = ListUtils.unwrapList(node.options).map(opt => this.visit(opt, optionsContext));
|
|
7006
7008
|
output.push(options.join(', '));
|
|
7007
7009
|
output.push(')');
|
|
@@ -7019,7 +7021,7 @@ export class Deparser {
|
|
|
7019
7021
|
if (node.options && node.options.length > 0) {
|
|
7020
7022
|
output.push('OPTIONS');
|
|
7021
7023
|
output.push('(');
|
|
7022
|
-
const optionsContext =
|
|
7024
|
+
const optionsContext = context.spawn('AlterForeignServerStmt');
|
|
7023
7025
|
const options = ListUtils.unwrapList(node.options).map(opt => this.visit(opt, optionsContext));
|
|
7024
7026
|
output.push(options.join(', '));
|
|
7025
7027
|
output.push(')');
|
|
@@ -7040,7 +7042,7 @@ export class Deparser {
|
|
|
7040
7042
|
}
|
|
7041
7043
|
if (node.options && node.options.length > 0) {
|
|
7042
7044
|
output.push('OPTIONS');
|
|
7043
|
-
const userMappingContext =
|
|
7045
|
+
const userMappingContext = context.spawn('AlterUserMappingStmt');
|
|
7044
7046
|
const options = ListUtils.unwrapList(node.options).map(opt => this.visit(opt, userMappingContext));
|
|
7045
7047
|
output.push(`(${options.join(', ')})`);
|
|
7046
7048
|
}
|
|
@@ -7100,7 +7102,7 @@ export class Deparser {
|
|
|
7100
7102
|
output.push(QuoteUtils.quote(node.local_schema));
|
|
7101
7103
|
}
|
|
7102
7104
|
if (node.options && node.options.length > 0) {
|
|
7103
|
-
const importSchemaContext =
|
|
7105
|
+
const importSchemaContext = context.spawn('ImportForeignSchemaStmt');
|
|
7104
7106
|
const options = ListUtils.unwrapList(node.options).map(opt => this.visit(opt, importSchemaContext));
|
|
7105
7107
|
output.push(`OPTIONS (${options.join(', ')})`);
|
|
7106
7108
|
}
|
|
@@ -7135,7 +7137,7 @@ export class Deparser {
|
|
|
7135
7137
|
ExplainStmt(node, context) {
|
|
7136
7138
|
const output = ['EXPLAIN'];
|
|
7137
7139
|
if (node.options && node.options.length > 0) {
|
|
7138
|
-
const explainContext =
|
|
7140
|
+
const explainContext = context.spawn('ExplainStmt');
|
|
7139
7141
|
const options = ListUtils.unwrapList(node.options).map(option => this.visit(option, explainContext));
|
|
7140
7142
|
output.push(`(${options.join(', ')})`);
|
|
7141
7143
|
}
|
|
@@ -7393,9 +7395,7 @@ export class Deparser {
|
|
|
7393
7395
|
output.push(this.RangeVar(node.relation, context));
|
|
7394
7396
|
}
|
|
7395
7397
|
else if (node.relation) {
|
|
7396
|
-
const rangeVarContext = node.relationType
|
|
7397
|
-
? { ...context, parentNodeTypes: [...context.parentNodeTypes, 'AlterTypeStmt'] }
|
|
7398
|
-
: context;
|
|
7398
|
+
const rangeVarContext = context.spawn('RenameStmt', { objtype: node.relationType });
|
|
7399
7399
|
// Add ON keyword for policy operations
|
|
7400
7400
|
if (node.renameType === 'OBJECT_POLICY') {
|
|
7401
7401
|
output.push('ON');
|
|
@@ -7577,7 +7577,7 @@ export class Deparser {
|
|
|
7577
7577
|
}
|
|
7578
7578
|
}
|
|
7579
7579
|
if (node.privileges && node.privileges.length > 0) {
|
|
7580
|
-
const privilegeContext =
|
|
7580
|
+
const privilegeContext = context.spawn('GrantStmt');
|
|
7581
7581
|
const privileges = ListUtils.unwrapList(node.privileges)
|
|
7582
7582
|
.map(priv => this.visit(priv, privilegeContext))
|
|
7583
7583
|
.join(', ');
|
|
@@ -7885,8 +7885,8 @@ export class Deparser {
|
|
|
7885
7885
|
}
|
|
7886
7886
|
if (node.action) {
|
|
7887
7887
|
const actionStr = this.GrantStmt(node.action, context);
|
|
7888
|
-
if (
|
|
7889
|
-
return output.join(' ') +
|
|
7888
|
+
if (context.isPretty()) {
|
|
7889
|
+
return output.join(' ') + context.newline() + context.indent(actionStr);
|
|
7890
7890
|
}
|
|
7891
7891
|
else {
|
|
7892
7892
|
output.push(actionStr);
|
|
@@ -8037,7 +8037,7 @@ export class Deparser {
|
|
|
8037
8037
|
if (node.trigname) {
|
|
8038
8038
|
output.push(QuoteUtils.quote(node.trigname));
|
|
8039
8039
|
}
|
|
8040
|
-
if (
|
|
8040
|
+
if (context.isPretty()) {
|
|
8041
8041
|
const components = [];
|
|
8042
8042
|
const timing = [];
|
|
8043
8043
|
if (node.timing & 2)
|
|
@@ -8063,31 +8063,31 @@ export class Deparser {
|
|
|
8063
8063
|
}
|
|
8064
8064
|
if (node.events & 32)
|
|
8065
8065
|
events.push('TRUNCATE');
|
|
8066
|
-
components.push(
|
|
8066
|
+
components.push(context.indent(timing.join(' ') + ' ' + events.join(' OR ')));
|
|
8067
8067
|
if (node.relation) {
|
|
8068
|
-
components.push(
|
|
8068
|
+
components.push(context.indent('ON ' + this.RangeVar(node.relation, context)));
|
|
8069
8069
|
}
|
|
8070
8070
|
if (node.transitionRels && node.transitionRels.length > 0) {
|
|
8071
8071
|
const transitionClauses = ListUtils.unwrapList(node.transitionRels)
|
|
8072
8072
|
.map(rel => this.visit(rel, context))
|
|
8073
8073
|
.join(' ');
|
|
8074
|
-
components.push(
|
|
8074
|
+
components.push(context.indent('REFERENCING ' + transitionClauses));
|
|
8075
8075
|
}
|
|
8076
8076
|
if (node.deferrable) {
|
|
8077
|
-
components.push(
|
|
8077
|
+
components.push(context.indent('DEFERRABLE'));
|
|
8078
8078
|
}
|
|
8079
8079
|
if (node.initdeferred) {
|
|
8080
|
-
components.push(
|
|
8080
|
+
components.push(context.indent('INITIALLY DEFERRED'));
|
|
8081
8081
|
}
|
|
8082
8082
|
if (node.row) {
|
|
8083
|
-
components.push(
|
|
8083
|
+
components.push(context.indent('FOR EACH ROW'));
|
|
8084
8084
|
}
|
|
8085
8085
|
else {
|
|
8086
|
-
components.push(
|
|
8086
|
+
components.push(context.indent('FOR EACH STATEMENT'));
|
|
8087
8087
|
}
|
|
8088
8088
|
if (node.whenClause) {
|
|
8089
8089
|
const whenStr = 'WHEN (' + this.visit(node.whenClause, context) + ')';
|
|
8090
|
-
components.push(
|
|
8090
|
+
components.push(context.indent(whenStr));
|
|
8091
8091
|
}
|
|
8092
8092
|
let executeStr = 'EXECUTE';
|
|
8093
8093
|
if (node.funcname && node.funcname.length > 0) {
|
|
@@ -8097,7 +8097,7 @@ export class Deparser {
|
|
|
8097
8097
|
executeStr += ' PROCEDURE ' + funcName;
|
|
8098
8098
|
}
|
|
8099
8099
|
if (node.args && node.args.length > 0) {
|
|
8100
|
-
const argContext =
|
|
8100
|
+
const argContext = context.spawn('CreateTrigStmt', { isStringLiteral: true });
|
|
8101
8101
|
const args = ListUtils.unwrapList(node.args)
|
|
8102
8102
|
.map(arg => this.visit(arg, argContext))
|
|
8103
8103
|
.join(', ');
|
|
@@ -8106,8 +8106,8 @@ export class Deparser {
|
|
|
8106
8106
|
else {
|
|
8107
8107
|
executeStr += '()';
|
|
8108
8108
|
}
|
|
8109
|
-
components.push(
|
|
8110
|
-
return output.join(' ') +
|
|
8109
|
+
components.push(context.indent(executeStr));
|
|
8110
|
+
return output.join(' ') + context.newline() + components.join(context.newline());
|
|
8111
8111
|
}
|
|
8112
8112
|
else {
|
|
8113
8113
|
const timing = [];
|
|
@@ -8177,7 +8177,7 @@ export class Deparser {
|
|
|
8177
8177
|
}
|
|
8178
8178
|
if (node.args && node.args.length > 0) {
|
|
8179
8179
|
output.push('(');
|
|
8180
|
-
const argContext =
|
|
8180
|
+
const argContext = context.spawn('CreateTrigStmt', { isStringLiteral: true });
|
|
8181
8181
|
const args = ListUtils.unwrapList(node.args)
|
|
8182
8182
|
.map(arg => this.visit(arg, argContext))
|
|
8183
8183
|
.join(', ');
|
|
@@ -8214,7 +8214,7 @@ export class Deparser {
|
|
|
8214
8214
|
}
|
|
8215
8215
|
if (node.whenclause && node.whenclause.length > 0) {
|
|
8216
8216
|
output.push('WHEN');
|
|
8217
|
-
const eventTriggerContext =
|
|
8217
|
+
const eventTriggerContext = context.spawn('CreateEventTrigStmt');
|
|
8218
8218
|
const conditions = ListUtils.unwrapList(node.whenclause)
|
|
8219
8219
|
.map(condition => this.visit(condition, eventTriggerContext))
|
|
8220
8220
|
.join(' AND ');
|
|
@@ -8403,7 +8403,7 @@ export class Deparser {
|
|
|
8403
8403
|
output.push(sequenceName.join('.'));
|
|
8404
8404
|
}
|
|
8405
8405
|
if (node.options && node.options.length > 0) {
|
|
8406
|
-
const seqContext =
|
|
8406
|
+
const seqContext = context.spawn('CreateSeqStmt');
|
|
8407
8407
|
const optionStrs = ListUtils.unwrapList(node.options)
|
|
8408
8408
|
.filter(option => option != null && this.getNodeType(option) !== 'undefined')
|
|
8409
8409
|
.map(option => {
|
|
@@ -8440,7 +8440,7 @@ export class Deparser {
|
|
|
8440
8440
|
output.push(sequenceName.join('.'));
|
|
8441
8441
|
}
|
|
8442
8442
|
if (node.options && node.options.length > 0) {
|
|
8443
|
-
const seqContext =
|
|
8443
|
+
const seqContext = context.spawn('AlterSeqStmt');
|
|
8444
8444
|
const optionStrs = ListUtils.unwrapList(node.options)
|
|
8445
8445
|
.filter(option => option && option !== undefined)
|
|
8446
8446
|
.map(option => {
|
|
@@ -8469,7 +8469,7 @@ export class Deparser {
|
|
|
8469
8469
|
CompositeTypeStmt(node, context) {
|
|
8470
8470
|
const output = ['CREATE', 'TYPE'];
|
|
8471
8471
|
if (node.typevar) {
|
|
8472
|
-
const typeContext =
|
|
8472
|
+
const typeContext = context.spawn('CompositeTypeStmt');
|
|
8473
8473
|
output.push(this.RangeVar(node.typevar, typeContext));
|
|
8474
8474
|
}
|
|
8475
8475
|
output.push('AS');
|
|
@@ -8570,7 +8570,7 @@ export class Deparser {
|
|
|
8570
8570
|
output.push(this.RoleSpec(node.role, context));
|
|
8571
8571
|
}
|
|
8572
8572
|
if (node.options) {
|
|
8573
|
-
const roleContext =
|
|
8573
|
+
const roleContext = context.spawn('AlterRoleStmt');
|
|
8574
8574
|
// Handle GROUP operations specially based on action value
|
|
8575
8575
|
if (isGroupStatement) {
|
|
8576
8576
|
const roleMembersOption = ListUtils.unwrapList(node.options).find(option => option.DefElem && option.DefElem.defname === 'rolemembers');
|
|
@@ -8773,7 +8773,7 @@ export class Deparser {
|
|
|
8773
8773
|
}
|
|
8774
8774
|
if (node.cols && node.cols.length > 0) {
|
|
8775
8775
|
output.push('(');
|
|
8776
|
-
const colContext =
|
|
8776
|
+
const colContext = context.spawn('AccessPriv');
|
|
8777
8777
|
const columns = ListUtils.unwrapList(node.cols).map(col => this.visit(col, colContext));
|
|
8778
8778
|
output.push(columns.join(', '));
|
|
8779
8779
|
output.push(')');
|
|
@@ -8853,7 +8853,7 @@ export class Deparser {
|
|
|
8853
8853
|
output.push(ListUtils.unwrapList(node.defnames).map(name => this.visit(name, context)).join('.'));
|
|
8854
8854
|
}
|
|
8855
8855
|
if (node.definition && node.definition.length > 0) {
|
|
8856
|
-
const defineStmtContext =
|
|
8856
|
+
const defineStmtContext = context.spawn('DefineStmt');
|
|
8857
8857
|
const definitions = ListUtils.unwrapList(node.definition).map(def => {
|
|
8858
8858
|
return this.visit(def, defineStmtContext);
|
|
8859
8859
|
});
|
|
@@ -9339,7 +9339,7 @@ export class Deparser {
|
|
|
9339
9339
|
const operatorNumber = node.number !== undefined ? node.number : 0;
|
|
9340
9340
|
output.push(operatorNumber.toString());
|
|
9341
9341
|
if (node.name) {
|
|
9342
|
-
const opClassContext =
|
|
9342
|
+
const opClassContext = context.spawn('CreateOpClassItem');
|
|
9343
9343
|
output.push(this.ObjectWithArgs(node.name, opClassContext));
|
|
9344
9344
|
}
|
|
9345
9345
|
}
|
|
@@ -9349,7 +9349,7 @@ export class Deparser {
|
|
|
9349
9349
|
const functionNumber = node.number !== undefined ? node.number : 0;
|
|
9350
9350
|
output.push(functionNumber.toString());
|
|
9351
9351
|
if (node.name) {
|
|
9352
|
-
const opClassContext =
|
|
9352
|
+
const opClassContext = context.spawn('CreateOpClassItem');
|
|
9353
9353
|
output.push(this.ObjectWithArgs(node.name, opClassContext));
|
|
9354
9354
|
}
|
|
9355
9355
|
}
|
|
@@ -10047,7 +10047,7 @@ export class Deparser {
|
|
|
10047
10047
|
output.push(this.ObjectWithArgs(node.func, context));
|
|
10048
10048
|
}
|
|
10049
10049
|
if (node.actions && node.actions.length > 0) {
|
|
10050
|
-
const alterFunctionContext =
|
|
10050
|
+
const alterFunctionContext = context.spawn('AlterFunctionStmt');
|
|
10051
10051
|
const actionStrs = ListUtils.unwrapList(node.actions).map(action => this.visit(action, alterFunctionContext));
|
|
10052
10052
|
output.push(actionStrs.join(' '));
|
|
10053
10053
|
}
|
|
@@ -10291,7 +10291,7 @@ export class Deparser {
|
|
|
10291
10291
|
CreateForeignTableStmt(node, context) {
|
|
10292
10292
|
const output = ['CREATE FOREIGN TABLE'];
|
|
10293
10293
|
if (node.base && node.base.relation) {
|
|
10294
|
-
const relationContext =
|
|
10294
|
+
const relationContext = context.spawn('CreateForeignTableStmt');
|
|
10295
10295
|
// Handle relation node directly as RangeVar since it contains the RangeVar properties
|
|
10296
10296
|
output.push(this.RangeVar(node.base.relation, relationContext));
|
|
10297
10297
|
}
|
|
@@ -10321,7 +10321,7 @@ export class Deparser {
|
|
|
10321
10321
|
output.push(QuoteUtils.quote(node.servername));
|
|
10322
10322
|
}
|
|
10323
10323
|
if (node.options && node.options.length > 0) {
|
|
10324
|
-
const foreignTableContext =
|
|
10324
|
+
const foreignTableContext = context.spawn('CreateForeignTableStmt');
|
|
10325
10325
|
const optionStrs = ListUtils.unwrapList(node.options).map(opt => this.visit(opt, foreignTableContext));
|
|
10326
10326
|
output.push(`OPTIONS (${optionStrs.join(', ')})`);
|
|
10327
10327
|
}
|