pgsql-deparser 16.0.0 → 16.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -6
- package/deparser/deparser.d.ts +4 -3
- package/deparser/deparser.js +883 -437
- package/deparser/utils/sql-formatter.js +1 -1
- package/deparser/visitors/base.d.ts +49 -2
- package/deparser/visitors/base.js +89 -1
- package/esm/deparser/deparser.js +883 -437
- package/esm/deparser/utils/sql-formatter.js +1 -1
- package/esm/deparser/visitors/base.js +87 -0
- package/package.json +1 -1
package/deparser/deparser.js
CHANGED
|
@@ -5,9 +5,66 @@
|
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
exports.Deparser = void 0;
|
|
8
|
+
const base_1 = require("./visitors/base");
|
|
8
9
|
const sql_formatter_1 = require("./utils/sql-formatter");
|
|
9
10
|
const quote_utils_1 = require("./utils/quote-utils");
|
|
10
11
|
const list_utils_1 = require("./utils/list-utils");
|
|
12
|
+
/**
|
|
13
|
+
* List of real PostgreSQL built-in types as they appear in pg_catalog.pg_type.typname.
|
|
14
|
+
* These are stored in lowercase in PostgreSQL system catalogs.
|
|
15
|
+
* Use these for lookups, validations, or introspection logic.
|
|
16
|
+
*/
|
|
17
|
+
const pgCatalogTypes = [
|
|
18
|
+
// Integers
|
|
19
|
+
'int2', // smallint
|
|
20
|
+
'int4', // integer
|
|
21
|
+
'int8', // bigint
|
|
22
|
+
// Floating-point & numeric
|
|
23
|
+
'float4', // real
|
|
24
|
+
'float8', // double precision
|
|
25
|
+
'numeric', // arbitrary precision (aka "decimal")
|
|
26
|
+
// Text & string
|
|
27
|
+
'varchar', // variable-length string
|
|
28
|
+
'char', // internal one-byte type (used in special cases)
|
|
29
|
+
'bpchar', // blank-padded char(n)
|
|
30
|
+
'text', // unlimited string
|
|
31
|
+
'bool', // boolean
|
|
32
|
+
// Dates & times
|
|
33
|
+
'date', // calendar date
|
|
34
|
+
'time', // time without time zone
|
|
35
|
+
'timetz', // time with time zone
|
|
36
|
+
'timestamp', // timestamp without time zone
|
|
37
|
+
'timestamptz', // timestamp with time zone
|
|
38
|
+
'interval', // duration
|
|
39
|
+
// Binary & structured
|
|
40
|
+
'bytea', // binary data
|
|
41
|
+
'uuid', // universally unique identifier
|
|
42
|
+
// JSON & XML
|
|
43
|
+
'json', // textual JSON
|
|
44
|
+
'jsonb', // binary JSON
|
|
45
|
+
'xml', // XML format
|
|
46
|
+
// Money & bitstrings
|
|
47
|
+
'money', // currency value
|
|
48
|
+
'bit', // fixed-length bit string
|
|
49
|
+
'varbit', // variable-length bit string
|
|
50
|
+
// Network types
|
|
51
|
+
'inet', // IPv4 or IPv6 address
|
|
52
|
+
'cidr', // network address
|
|
53
|
+
'macaddr', // MAC address (6 bytes)
|
|
54
|
+
'macaddr8' // MAC address (8 bytes)
|
|
55
|
+
];
|
|
56
|
+
/**
|
|
57
|
+
* Parser-level type aliases accepted by PostgreSQL SQL syntax,
|
|
58
|
+
* but not present in pg_catalog.pg_type. These are resolved to
|
|
59
|
+
* real types during parsing and never appear in introspection.
|
|
60
|
+
*/
|
|
61
|
+
const pgCatalogTypeAliases = [
|
|
62
|
+
['numeric', ['decimal', 'dec']],
|
|
63
|
+
['int4', ['int', 'integer']],
|
|
64
|
+
['float8', ['float']],
|
|
65
|
+
['bpchar', ['character']],
|
|
66
|
+
['varchar', ['character varying']]
|
|
67
|
+
];
|
|
11
68
|
// Type guards for better type safety
|
|
12
69
|
function isParseResult(obj) {
|
|
13
70
|
// A ParseResult is an object that could have stmts (but not required)
|
|
@@ -51,11 +108,9 @@ function isWrappedParseResult(obj) {
|
|
|
51
108
|
* compatibility and wraps them internally for consistent processing.
|
|
52
109
|
*/
|
|
53
110
|
class Deparser {
|
|
54
|
-
formatter;
|
|
55
111
|
tree;
|
|
56
112
|
options;
|
|
57
113
|
constructor(tree, opts = {}) {
|
|
58
|
-
this.formatter = new sql_formatter_1.SqlFormatter(opts.newline, opts.tab, opts.pretty);
|
|
59
114
|
// Set default options
|
|
60
115
|
this.options = {
|
|
61
116
|
functionDelimiter: '$$',
|
|
@@ -92,15 +147,17 @@ class Deparser {
|
|
|
92
147
|
return new Deparser(query, opts).deparseQuery();
|
|
93
148
|
}
|
|
94
149
|
deparseQuery() {
|
|
150
|
+
const formatter = new sql_formatter_1.SqlFormatter(this.options.newline, this.options.tab, this.options.pretty);
|
|
151
|
+
const context = new base_1.DeparserContext({ formatter, prettyMode: this.options.pretty });
|
|
95
152
|
return this.tree
|
|
96
153
|
.map(node => {
|
|
97
154
|
// All nodes should go through the standard deparse method
|
|
98
155
|
// which will route to the appropriate handler
|
|
99
|
-
const result = this.deparse(node);
|
|
156
|
+
const result = this.deparse(node, context);
|
|
100
157
|
return result || '';
|
|
101
158
|
})
|
|
102
159
|
.filter(result => result !== '')
|
|
103
|
-
.join(
|
|
160
|
+
.join(context.newline() + context.newline());
|
|
104
161
|
}
|
|
105
162
|
/**
|
|
106
163
|
* Get the appropriate function delimiter based on the body content
|
|
@@ -114,10 +171,14 @@ class Deparser {
|
|
|
114
171
|
}
|
|
115
172
|
return delimiter;
|
|
116
173
|
}
|
|
117
|
-
deparse(node, context
|
|
174
|
+
deparse(node, context) {
|
|
118
175
|
if (node == null) {
|
|
119
176
|
return null;
|
|
120
177
|
}
|
|
178
|
+
if (!context) {
|
|
179
|
+
const formatter = new sql_formatter_1.SqlFormatter(this.options.newline, this.options.tab, this.options.pretty);
|
|
180
|
+
context = new base_1.DeparserContext({ formatter, prettyMode: this.options.pretty });
|
|
181
|
+
}
|
|
121
182
|
if (typeof node === 'number' || node instanceof Number) {
|
|
122
183
|
return node.toString();
|
|
123
184
|
}
|
|
@@ -129,7 +190,11 @@ class Deparser {
|
|
|
129
190
|
throw new Error(`Error deparsing ${nodeType}: ${error.message}`);
|
|
130
191
|
}
|
|
131
192
|
}
|
|
132
|
-
visit(node, context
|
|
193
|
+
visit(node, context) {
|
|
194
|
+
if (!context) {
|
|
195
|
+
const formatter = new sql_formatter_1.SqlFormatter(this.options.newline, this.options.tab, this.options.pretty);
|
|
196
|
+
context = new base_1.DeparserContext({ formatter, prettyMode: this.options.pretty });
|
|
197
|
+
}
|
|
133
198
|
const nodeType = this.getNodeType(node);
|
|
134
199
|
// Handle empty objects
|
|
135
200
|
if (!nodeType) {
|
|
@@ -138,11 +203,7 @@ class Deparser {
|
|
|
138
203
|
const nodeData = this.getNodeData(node);
|
|
139
204
|
const methodName = nodeType;
|
|
140
205
|
if (typeof this[methodName] === 'function') {
|
|
141
|
-
const
|
|
142
|
-
...context,
|
|
143
|
-
parentNodeTypes: [...context.parentNodeTypes, nodeType]
|
|
144
|
-
};
|
|
145
|
-
const result = this[methodName](nodeData, childContext);
|
|
206
|
+
const result = this[methodName](nodeData, context);
|
|
146
207
|
return result;
|
|
147
208
|
}
|
|
148
209
|
throw new Error(`Deparser does not handle node type: ${nodeType}`);
|
|
@@ -168,7 +229,7 @@ class Deparser {
|
|
|
168
229
|
.filter((rawStmt) => rawStmt != null)
|
|
169
230
|
.map((rawStmt) => this.RawStmt(rawStmt, context))
|
|
170
231
|
.filter((result) => result !== '')
|
|
171
|
-
.join(
|
|
232
|
+
.join(context.newline() + context.newline());
|
|
172
233
|
}
|
|
173
234
|
RawStmt(node, context) {
|
|
174
235
|
if (!node.stmt) {
|
|
@@ -188,7 +249,7 @@ class Deparser {
|
|
|
188
249
|
}
|
|
189
250
|
if (!node.op || node.op === 'SETOP_NONE') {
|
|
190
251
|
if (node.valuesLists == null) {
|
|
191
|
-
if (!
|
|
252
|
+
if (!context.isPretty() || !node.targetList) {
|
|
192
253
|
output.push('SELECT');
|
|
193
254
|
}
|
|
194
255
|
}
|
|
@@ -208,7 +269,7 @@ class Deparser {
|
|
|
208
269
|
(node.rarg).limitOffset ||
|
|
209
270
|
(node.rarg).withClause);
|
|
210
271
|
if (leftNeedsParens) {
|
|
211
|
-
output.push(
|
|
272
|
+
output.push(context.parens(leftStmt));
|
|
212
273
|
}
|
|
213
274
|
else {
|
|
214
275
|
output.push(leftStmt);
|
|
@@ -230,7 +291,7 @@ class Deparser {
|
|
|
230
291
|
output.push('ALL');
|
|
231
292
|
}
|
|
232
293
|
if (rightNeedsParens) {
|
|
233
|
-
output.push(
|
|
294
|
+
output.push(context.parens(rightStmt));
|
|
234
295
|
}
|
|
235
296
|
else {
|
|
236
297
|
output.push(rightStmt);
|
|
@@ -242,20 +303,20 @@ class Deparser {
|
|
|
242
303
|
const distinctClause = list_utils_1.ListUtils.unwrapList(node.distinctClause);
|
|
243
304
|
if (distinctClause.length > 0 && Object.keys(distinctClause[0]).length > 0) {
|
|
244
305
|
const clause = distinctClause
|
|
245
|
-
.map(e => this.visit(e,
|
|
306
|
+
.map(e => this.visit(e, context.spawn('SelectStmt', { select: true })))
|
|
246
307
|
.join(', ');
|
|
247
|
-
distinctPart = ' DISTINCT ON ' +
|
|
308
|
+
distinctPart = ' DISTINCT ON ' + context.parens(clause);
|
|
248
309
|
}
|
|
249
310
|
else {
|
|
250
311
|
distinctPart = ' DISTINCT';
|
|
251
312
|
}
|
|
252
|
-
if (!
|
|
313
|
+
if (!context.isPretty()) {
|
|
253
314
|
if (distinctClause.length > 0 && Object.keys(distinctClause[0]).length > 0) {
|
|
254
315
|
output.push('DISTINCT ON');
|
|
255
316
|
const clause = distinctClause
|
|
256
|
-
.map(e => this.visit(e,
|
|
317
|
+
.map(e => this.visit(e, context.spawn('SelectStmt', { select: true })))
|
|
257
318
|
.join(', ');
|
|
258
|
-
output.push(
|
|
319
|
+
output.push(context.parens(clause));
|
|
259
320
|
}
|
|
260
321
|
else {
|
|
261
322
|
output.push('DISTINCT');
|
|
@@ -264,22 +325,41 @@ class Deparser {
|
|
|
264
325
|
}
|
|
265
326
|
if (node.targetList) {
|
|
266
327
|
const targetList = list_utils_1.ListUtils.unwrapList(node.targetList);
|
|
267
|
-
if (
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
const
|
|
271
|
-
if
|
|
272
|
-
|
|
328
|
+
if (context.isPretty()) {
|
|
329
|
+
if (targetList.length === 1) {
|
|
330
|
+
const targetNode = targetList[0];
|
|
331
|
+
const target = this.visit(targetNode, context.spawn('SelectStmt', { select: true }));
|
|
332
|
+
// Check if single target is complex - if so, use multiline format
|
|
333
|
+
if (this.isComplexSelectTarget(targetNode)) {
|
|
334
|
+
output.push('SELECT' + distinctPart);
|
|
335
|
+
if (this.containsMultilineStringLiteral(target)) {
|
|
336
|
+
output.push(target);
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
output.push(context.indent(target));
|
|
340
|
+
}
|
|
273
341
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
342
|
+
else {
|
|
343
|
+
output.push('SELECT' + distinctPart + ' ' + target);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
const targetStrings = targetList
|
|
348
|
+
.map(e => {
|
|
349
|
+
const targetStr = this.visit(e, context.spawn('SelectStmt', { select: true }));
|
|
350
|
+
if (this.containsMultilineStringLiteral(targetStr)) {
|
|
351
|
+
return targetStr;
|
|
352
|
+
}
|
|
353
|
+
return context.indent(targetStr);
|
|
354
|
+
});
|
|
355
|
+
const formattedTargets = targetStrings.join(',' + context.newline());
|
|
356
|
+
output.push('SELECT' + distinctPart);
|
|
357
|
+
output.push(formattedTargets);
|
|
358
|
+
}
|
|
279
359
|
}
|
|
280
360
|
else {
|
|
281
361
|
const targets = targetList
|
|
282
|
-
.map(e => this.visit(e,
|
|
362
|
+
.map(e => this.visit(e, context.spawn('SelectStmt', { select: true })))
|
|
283
363
|
.join(', ');
|
|
284
364
|
output.push(targets);
|
|
285
365
|
}
|
|
@@ -291,22 +371,22 @@ class Deparser {
|
|
|
291
371
|
if (node.fromClause) {
|
|
292
372
|
const fromList = list_utils_1.ListUtils.unwrapList(node.fromClause);
|
|
293
373
|
const fromItems = fromList
|
|
294
|
-
.map(e => this.deparse(e,
|
|
374
|
+
.map(e => this.deparse(e, context.spawn('SelectStmt', { from: true })))
|
|
295
375
|
.join(', ');
|
|
296
376
|
output.push('FROM ' + fromItems.trim());
|
|
297
377
|
}
|
|
298
378
|
if (node.whereClause) {
|
|
299
|
-
if (
|
|
379
|
+
if (context.isPretty()) {
|
|
300
380
|
output.push('WHERE');
|
|
301
381
|
const whereExpr = this.visit(node.whereClause, context);
|
|
302
|
-
const lines = whereExpr.split(
|
|
382
|
+
const lines = whereExpr.split(context.newline());
|
|
303
383
|
const indentedLines = lines.map((line, index) => {
|
|
304
384
|
if (index === 0) {
|
|
305
|
-
return
|
|
385
|
+
return context.indent(line);
|
|
306
386
|
}
|
|
307
387
|
return line;
|
|
308
388
|
});
|
|
309
|
-
output.push(indentedLines.join(
|
|
389
|
+
output.push(indentedLines.join(context.newline()));
|
|
310
390
|
}
|
|
311
391
|
else {
|
|
312
392
|
output.push('WHERE');
|
|
@@ -314,45 +394,61 @@ class Deparser {
|
|
|
314
394
|
}
|
|
315
395
|
}
|
|
316
396
|
if (node.valuesLists) {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
const
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
397
|
+
if (context.isPretty()) {
|
|
398
|
+
output.push('VALUES');
|
|
399
|
+
const lists = list_utils_1.ListUtils.unwrapList(node.valuesLists).map(list => {
|
|
400
|
+
const values = list_utils_1.ListUtils.unwrapList(list).map(val => this.visit(val, context));
|
|
401
|
+
return context.parens(values.join(', '));
|
|
402
|
+
});
|
|
403
|
+
const indentedTuples = lists.map(tuple => {
|
|
404
|
+
if (this.containsMultilineStringLiteral(tuple)) {
|
|
405
|
+
return tuple;
|
|
406
|
+
}
|
|
407
|
+
return context.indent(tuple);
|
|
408
|
+
});
|
|
409
|
+
output.push(indentedTuples.join(',\n'));
|
|
410
|
+
}
|
|
411
|
+
else {
|
|
412
|
+
output.push('VALUES');
|
|
413
|
+
const lists = list_utils_1.ListUtils.unwrapList(node.valuesLists).map(list => {
|
|
414
|
+
const values = list_utils_1.ListUtils.unwrapList(list).map(val => this.visit(val, context));
|
|
415
|
+
return context.parens(values.join(', '));
|
|
416
|
+
});
|
|
417
|
+
output.push(lists.join(', '));
|
|
418
|
+
}
|
|
323
419
|
}
|
|
324
420
|
if (node.groupClause) {
|
|
325
421
|
const groupList = list_utils_1.ListUtils.unwrapList(node.groupClause);
|
|
326
|
-
if (
|
|
422
|
+
if (context.isPretty()) {
|
|
327
423
|
const groupItems = groupList
|
|
328
424
|
.map(e => {
|
|
329
|
-
const groupStr = this.visit(e,
|
|
425
|
+
const groupStr = this.visit(e, context.spawn('SelectStmt', { group: true, indentLevel: context.indentLevel + 1 }));
|
|
330
426
|
if (this.containsMultilineStringLiteral(groupStr)) {
|
|
331
427
|
return groupStr;
|
|
332
428
|
}
|
|
333
|
-
return
|
|
429
|
+
return context.indent(groupStr);
|
|
334
430
|
})
|
|
335
|
-
.join(',' +
|
|
431
|
+
.join(',' + context.newline());
|
|
336
432
|
output.push('GROUP BY');
|
|
337
433
|
output.push(groupItems);
|
|
338
434
|
}
|
|
339
435
|
else {
|
|
340
436
|
output.push('GROUP BY');
|
|
341
437
|
const groupItems = groupList
|
|
342
|
-
.map(e => this.visit(e,
|
|
438
|
+
.map(e => this.visit(e, context.spawn('SelectStmt', { group: true })))
|
|
343
439
|
.join(', ');
|
|
344
440
|
output.push(groupItems);
|
|
345
441
|
}
|
|
346
442
|
}
|
|
347
443
|
if (node.havingClause) {
|
|
348
|
-
if (
|
|
444
|
+
if (context.isPretty()) {
|
|
349
445
|
output.push('HAVING');
|
|
350
446
|
const havingStr = this.visit(node.havingClause, context);
|
|
351
447
|
if (this.containsMultilineStringLiteral(havingStr)) {
|
|
352
448
|
output.push(havingStr);
|
|
353
449
|
}
|
|
354
450
|
else {
|
|
355
|
-
output.push(
|
|
451
|
+
output.push(context.indent(havingStr));
|
|
356
452
|
}
|
|
357
453
|
}
|
|
358
454
|
else {
|
|
@@ -370,23 +466,23 @@ class Deparser {
|
|
|
370
466
|
}
|
|
371
467
|
if (node.sortClause) {
|
|
372
468
|
const sortList = list_utils_1.ListUtils.unwrapList(node.sortClause);
|
|
373
|
-
if (
|
|
469
|
+
if (context.isPretty()) {
|
|
374
470
|
const sortItems = sortList
|
|
375
471
|
.map(e => {
|
|
376
|
-
const sortStr = this.visit(e,
|
|
472
|
+
const sortStr = this.visit(e, context.spawn('SelectStmt', { sort: true, indentLevel: context.indentLevel + 1 }));
|
|
377
473
|
if (this.containsMultilineStringLiteral(sortStr)) {
|
|
378
474
|
return sortStr;
|
|
379
475
|
}
|
|
380
|
-
return
|
|
476
|
+
return context.indent(sortStr);
|
|
381
477
|
})
|
|
382
|
-
.join(',' +
|
|
478
|
+
.join(',' + context.newline());
|
|
383
479
|
output.push('ORDER BY');
|
|
384
480
|
output.push(sortItems);
|
|
385
481
|
}
|
|
386
482
|
else {
|
|
387
483
|
output.push('ORDER BY');
|
|
388
484
|
const sortItems = sortList
|
|
389
|
-
.map(e => this.visit(e,
|
|
485
|
+
.map(e => this.visit(e, context.spawn('SelectStmt', { sort: true })))
|
|
390
486
|
.join(', ');
|
|
391
487
|
output.push(sortItems);
|
|
392
488
|
}
|
|
@@ -404,9 +500,9 @@ class Deparser {
|
|
|
404
500
|
.join(' ');
|
|
405
501
|
output.push(lockingClauses);
|
|
406
502
|
}
|
|
407
|
-
if (
|
|
503
|
+
if (context.isPretty()) {
|
|
408
504
|
const filteredOutput = output.filter(item => item.trim() !== '');
|
|
409
|
-
return filteredOutput.join(
|
|
505
|
+
return filteredOutput.join(context.newline());
|
|
410
506
|
}
|
|
411
507
|
return output.join(' ');
|
|
412
508
|
}
|
|
@@ -418,13 +514,13 @@ class Deparser {
|
|
|
418
514
|
switch (kind) {
|
|
419
515
|
case 'AEXPR_OP':
|
|
420
516
|
if (lexpr && rexpr) {
|
|
421
|
-
const operator = this.deparseOperatorName(name);
|
|
517
|
+
const operator = this.deparseOperatorName(name, context);
|
|
422
518
|
let leftExpr = this.visit(lexpr, context);
|
|
423
519
|
let rightExpr = this.visit(rexpr, context);
|
|
424
520
|
// Check if left expression needs parentheses
|
|
425
521
|
let leftNeedsParens = false;
|
|
426
522
|
if (lexpr && 'A_Expr' in lexpr && lexpr.A_Expr?.kind === 'AEXPR_OP') {
|
|
427
|
-
const leftOp = this.deparseOperatorName(list_utils_1.ListUtils.unwrapList(lexpr.A_Expr.name));
|
|
523
|
+
const leftOp = this.deparseOperatorName(list_utils_1.ListUtils.unwrapList(lexpr.A_Expr.name), context);
|
|
428
524
|
if (this.needsParentheses(leftOp, operator, 'left')) {
|
|
429
525
|
leftNeedsParens = true;
|
|
430
526
|
}
|
|
@@ -433,12 +529,12 @@ class Deparser {
|
|
|
433
529
|
leftNeedsParens = true;
|
|
434
530
|
}
|
|
435
531
|
if (leftNeedsParens) {
|
|
436
|
-
leftExpr =
|
|
532
|
+
leftExpr = context.parens(leftExpr);
|
|
437
533
|
}
|
|
438
534
|
// Check if right expression needs parentheses
|
|
439
535
|
let rightNeedsParens = false;
|
|
440
536
|
if (rexpr && 'A_Expr' in rexpr && rexpr.A_Expr?.kind === 'AEXPR_OP') {
|
|
441
|
-
const rightOp = this.deparseOperatorName(list_utils_1.ListUtils.unwrapList(rexpr.A_Expr.name));
|
|
537
|
+
const rightOp = this.deparseOperatorName(list_utils_1.ListUtils.unwrapList(rexpr.A_Expr.name), context);
|
|
442
538
|
if (this.needsParentheses(rightOp, operator, 'right')) {
|
|
443
539
|
rightNeedsParens = true;
|
|
444
540
|
}
|
|
@@ -447,42 +543,42 @@ class Deparser {
|
|
|
447
543
|
rightNeedsParens = true;
|
|
448
544
|
}
|
|
449
545
|
if (rightNeedsParens) {
|
|
450
|
-
rightExpr =
|
|
546
|
+
rightExpr = context.parens(rightExpr);
|
|
451
547
|
}
|
|
452
|
-
return
|
|
548
|
+
return context.format([leftExpr, operator, rightExpr]);
|
|
453
549
|
}
|
|
454
550
|
else if (rexpr) {
|
|
455
|
-
return
|
|
456
|
-
this.deparseOperatorName(name),
|
|
551
|
+
return context.format([
|
|
552
|
+
this.deparseOperatorName(name, context),
|
|
457
553
|
this.visit(rexpr, context)
|
|
458
554
|
]);
|
|
459
555
|
}
|
|
460
556
|
break;
|
|
461
557
|
case 'AEXPR_OP_ANY':
|
|
462
|
-
return
|
|
558
|
+
return context.format([
|
|
463
559
|
this.visit(lexpr, context),
|
|
464
|
-
this.deparseOperatorName(name),
|
|
560
|
+
this.deparseOperatorName(name, context),
|
|
465
561
|
'ANY',
|
|
466
|
-
|
|
562
|
+
context.parens(this.visit(rexpr, context))
|
|
467
563
|
]);
|
|
468
564
|
case 'AEXPR_OP_ALL':
|
|
469
|
-
return
|
|
565
|
+
return context.format([
|
|
470
566
|
this.visit(lexpr, context),
|
|
471
|
-
this.deparseOperatorName(name),
|
|
567
|
+
this.deparseOperatorName(name, context),
|
|
472
568
|
'ALL',
|
|
473
|
-
|
|
569
|
+
context.parens(this.visit(rexpr, context))
|
|
474
570
|
]);
|
|
475
571
|
case 'AEXPR_DISTINCT': {
|
|
476
572
|
let leftExpr = this.visit(lexpr, context);
|
|
477
573
|
let rightExpr = this.visit(rexpr, context);
|
|
478
574
|
// Add parentheses for complex expressions
|
|
479
575
|
if (lexpr && this.isComplexExpression(lexpr)) {
|
|
480
|
-
leftExpr =
|
|
576
|
+
leftExpr = context.parens(leftExpr);
|
|
481
577
|
}
|
|
482
578
|
if (rexpr && this.isComplexExpression(rexpr)) {
|
|
483
|
-
rightExpr =
|
|
579
|
+
rightExpr = context.parens(rightExpr);
|
|
484
580
|
}
|
|
485
|
-
return
|
|
581
|
+
return context.format([
|
|
486
582
|
leftExpr,
|
|
487
583
|
'IS DISTINCT FROM',
|
|
488
584
|
rightExpr
|
|
@@ -493,75 +589,75 @@ class Deparser {
|
|
|
493
589
|
let rightExpr = this.visit(rexpr, context);
|
|
494
590
|
// Add parentheses for complex expressions
|
|
495
591
|
if (lexpr && this.isComplexExpression(lexpr)) {
|
|
496
|
-
leftExpr =
|
|
592
|
+
leftExpr = context.parens(leftExpr);
|
|
497
593
|
}
|
|
498
594
|
if (rexpr && this.isComplexExpression(rexpr)) {
|
|
499
|
-
rightExpr =
|
|
595
|
+
rightExpr = context.parens(rightExpr);
|
|
500
596
|
}
|
|
501
|
-
return
|
|
597
|
+
return context.format([
|
|
502
598
|
leftExpr,
|
|
503
599
|
'IS NOT DISTINCT FROM',
|
|
504
600
|
rightExpr
|
|
505
601
|
]);
|
|
506
602
|
}
|
|
507
603
|
case 'AEXPR_NULLIF':
|
|
508
|
-
return
|
|
604
|
+
return context.format([
|
|
509
605
|
'NULLIF',
|
|
510
|
-
|
|
606
|
+
context.parens([
|
|
511
607
|
this.visit(lexpr, context),
|
|
512
608
|
this.visit(rexpr, context)
|
|
513
609
|
].join(', '))
|
|
514
610
|
]);
|
|
515
611
|
case 'AEXPR_IN':
|
|
516
|
-
const inOperator = this.deparseOperatorName(name);
|
|
612
|
+
const inOperator = this.deparseOperatorName(name, context);
|
|
517
613
|
if (inOperator === '<>' || inOperator === '!=') {
|
|
518
|
-
return
|
|
614
|
+
return context.format([
|
|
519
615
|
this.visit(lexpr, context),
|
|
520
616
|
'NOT IN',
|
|
521
|
-
|
|
617
|
+
context.parens(this.visit(rexpr, context))
|
|
522
618
|
]);
|
|
523
619
|
}
|
|
524
620
|
else {
|
|
525
|
-
return
|
|
621
|
+
return context.format([
|
|
526
622
|
this.visit(lexpr, context),
|
|
527
623
|
'IN',
|
|
528
|
-
|
|
624
|
+
context.parens(this.visit(rexpr, context))
|
|
529
625
|
]);
|
|
530
626
|
}
|
|
531
627
|
case 'AEXPR_LIKE':
|
|
532
|
-
const likeOp = this.deparseOperatorName(name);
|
|
628
|
+
const likeOp = this.deparseOperatorName(name, context);
|
|
533
629
|
if (likeOp === '!~~') {
|
|
534
|
-
return
|
|
630
|
+
return context.format([
|
|
535
631
|
this.visit(lexpr, context),
|
|
536
632
|
'NOT LIKE',
|
|
537
633
|
this.visit(rexpr, context)
|
|
538
634
|
]);
|
|
539
635
|
}
|
|
540
636
|
else {
|
|
541
|
-
return
|
|
637
|
+
return context.format([
|
|
542
638
|
this.visit(lexpr, context),
|
|
543
639
|
'LIKE',
|
|
544
640
|
this.visit(rexpr, context)
|
|
545
641
|
]);
|
|
546
642
|
}
|
|
547
643
|
case 'AEXPR_ILIKE':
|
|
548
|
-
const ilikeOp = this.deparseOperatorName(name);
|
|
644
|
+
const ilikeOp = this.deparseOperatorName(name, context);
|
|
549
645
|
if (ilikeOp === '!~~*') {
|
|
550
|
-
return
|
|
646
|
+
return context.format([
|
|
551
647
|
this.visit(lexpr, context),
|
|
552
648
|
'NOT ILIKE',
|
|
553
649
|
this.visit(rexpr, context)
|
|
554
650
|
]);
|
|
555
651
|
}
|
|
556
652
|
else {
|
|
557
|
-
return
|
|
653
|
+
return context.format([
|
|
558
654
|
this.visit(lexpr, context),
|
|
559
655
|
'ILIKE',
|
|
560
656
|
this.visit(rexpr, context)
|
|
561
657
|
]);
|
|
562
658
|
}
|
|
563
659
|
case 'AEXPR_SIMILAR':
|
|
564
|
-
const similarOp = this.deparseOperatorName(name);
|
|
660
|
+
const similarOp = this.deparseOperatorName(name, context);
|
|
565
661
|
let rightExpr;
|
|
566
662
|
if (rexpr && 'FuncCall' in rexpr &&
|
|
567
663
|
rexpr.FuncCall?.funcname?.length === 2 &&
|
|
@@ -577,39 +673,39 @@ class Deparser {
|
|
|
577
673
|
rightExpr = this.visit(rexpr, context);
|
|
578
674
|
}
|
|
579
675
|
if (similarOp === '!~') {
|
|
580
|
-
return
|
|
676
|
+
return context.format([
|
|
581
677
|
this.visit(lexpr, context),
|
|
582
678
|
'NOT SIMILAR TO',
|
|
583
679
|
rightExpr
|
|
584
680
|
]);
|
|
585
681
|
}
|
|
586
682
|
else {
|
|
587
|
-
return
|
|
683
|
+
return context.format([
|
|
588
684
|
this.visit(lexpr, context),
|
|
589
685
|
'SIMILAR TO',
|
|
590
686
|
rightExpr
|
|
591
687
|
]);
|
|
592
688
|
}
|
|
593
689
|
case 'AEXPR_BETWEEN':
|
|
594
|
-
return
|
|
690
|
+
return context.format([
|
|
595
691
|
this.visit(lexpr, context),
|
|
596
692
|
'BETWEEN',
|
|
597
693
|
this.visitBetweenRange(rexpr, context)
|
|
598
694
|
]);
|
|
599
695
|
case 'AEXPR_NOT_BETWEEN':
|
|
600
|
-
return
|
|
696
|
+
return context.format([
|
|
601
697
|
this.visit(lexpr, context),
|
|
602
698
|
'NOT BETWEEN',
|
|
603
699
|
this.visitBetweenRange(rexpr, context)
|
|
604
700
|
]);
|
|
605
701
|
case 'AEXPR_BETWEEN_SYM':
|
|
606
|
-
return
|
|
702
|
+
return context.format([
|
|
607
703
|
this.visit(lexpr, context),
|
|
608
704
|
'BETWEEN SYMMETRIC',
|
|
609
705
|
this.visitBetweenRange(rexpr, context)
|
|
610
706
|
]);
|
|
611
707
|
case 'AEXPR_NOT_BETWEEN_SYM':
|
|
612
|
-
return
|
|
708
|
+
return context.format([
|
|
613
709
|
this.visit(lexpr, context),
|
|
614
710
|
'NOT BETWEEN SYMMETRIC',
|
|
615
711
|
this.visitBetweenRange(rexpr, context)
|
|
@@ -617,7 +713,7 @@ class Deparser {
|
|
|
617
713
|
}
|
|
618
714
|
throw new Error(`Unhandled A_Expr kind: ${kind}`);
|
|
619
715
|
}
|
|
620
|
-
deparseOperatorName(name) {
|
|
716
|
+
deparseOperatorName(name, context) {
|
|
621
717
|
if (!name || name.length === 0) {
|
|
622
718
|
return '';
|
|
623
719
|
}
|
|
@@ -625,7 +721,7 @@ class Deparser {
|
|
|
625
721
|
if (n.String) {
|
|
626
722
|
return n.String.sval || n.String.str;
|
|
627
723
|
}
|
|
628
|
-
return this.visit(n,
|
|
724
|
+
return this.visit(n, context);
|
|
629
725
|
});
|
|
630
726
|
if (parts.length > 1) {
|
|
631
727
|
return `OPERATOR(${parts.join('.')})`;
|
|
@@ -688,6 +784,64 @@ class Deparser {
|
|
|
688
784
|
node.SubLink ||
|
|
689
785
|
node.A_Expr);
|
|
690
786
|
}
|
|
787
|
+
isComplexSelectTarget(node) {
|
|
788
|
+
if (!node)
|
|
789
|
+
return false;
|
|
790
|
+
if (node.ResTarget?.val) {
|
|
791
|
+
return this.isComplexExpression(node.ResTarget.val);
|
|
792
|
+
}
|
|
793
|
+
// Always complex: CASE expressions
|
|
794
|
+
if (node.CaseExpr)
|
|
795
|
+
return true;
|
|
796
|
+
// Always complex: Subqueries and subselects
|
|
797
|
+
if (node.SubLink)
|
|
798
|
+
return true;
|
|
799
|
+
// Always complex: Boolean tests and expressions
|
|
800
|
+
if (node.NullTest || node.BooleanTest || node.BoolExpr)
|
|
801
|
+
return true;
|
|
802
|
+
// COALESCE and similar functions - complex if multiple arguments
|
|
803
|
+
if (node.CoalesceExpr) {
|
|
804
|
+
const args = node.CoalesceExpr.args;
|
|
805
|
+
if (args && Array.isArray(args) && args.length > 1)
|
|
806
|
+
return true;
|
|
807
|
+
}
|
|
808
|
+
// Function calls - complex if multiple args or has clauses
|
|
809
|
+
if (node.FuncCall) {
|
|
810
|
+
const funcCall = node.FuncCall;
|
|
811
|
+
const args = funcCall.args ? (Array.isArray(funcCall.args) ? funcCall.args : [funcCall.args]) : [];
|
|
812
|
+
// Complex if has window clause, filter, order by, etc.
|
|
813
|
+
if (funcCall.over || funcCall.agg_filter || funcCall.agg_order || funcCall.agg_distinct) {
|
|
814
|
+
return true;
|
|
815
|
+
}
|
|
816
|
+
// Complex if multiple arguments
|
|
817
|
+
if (args.length > 1)
|
|
818
|
+
return true;
|
|
819
|
+
if (args.length === 1) {
|
|
820
|
+
return this.isComplexSelectTarget(args[0]);
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
if (node.A_Expr) {
|
|
824
|
+
const expr = node.A_Expr;
|
|
825
|
+
// Check if operands are complex
|
|
826
|
+
if (expr.lexpr && this.isComplexSelectTarget(expr.lexpr))
|
|
827
|
+
return true;
|
|
828
|
+
if (expr.rexpr && this.isComplexSelectTarget(expr.rexpr))
|
|
829
|
+
return true;
|
|
830
|
+
return false;
|
|
831
|
+
}
|
|
832
|
+
if (node.TypeCast) {
|
|
833
|
+
return this.isComplexSelectTarget(node.TypeCast.arg);
|
|
834
|
+
}
|
|
835
|
+
if (node.A_ArrayExpr)
|
|
836
|
+
return true;
|
|
837
|
+
if (node.A_Indirection) {
|
|
838
|
+
return this.isComplexSelectTarget(node.A_Indirection.arg);
|
|
839
|
+
}
|
|
840
|
+
if (node.A_Const || node.ColumnRef || node.ParamRef || node.A_Star) {
|
|
841
|
+
return false;
|
|
842
|
+
}
|
|
843
|
+
return false;
|
|
844
|
+
}
|
|
691
845
|
visitBetweenRange(rexpr, context) {
|
|
692
846
|
if (rexpr && 'List' in rexpr && rexpr.List?.items) {
|
|
693
847
|
const items = rexpr.List.items.map((item) => this.visit(item, context));
|
|
@@ -704,9 +858,16 @@ class Deparser {
|
|
|
704
858
|
output.push(this.RangeVar(node.relation, context));
|
|
705
859
|
if (node.cols) {
|
|
706
860
|
const cols = list_utils_1.ListUtils.unwrapList(node.cols);
|
|
707
|
-
const insertContext =
|
|
861
|
+
const insertContext = context.spawn('InsertStmt', { insertColumns: true });
|
|
708
862
|
const columnNames = cols.map(col => this.visit(col, insertContext));
|
|
709
|
-
|
|
863
|
+
if (context.isPretty()) {
|
|
864
|
+
// Always format columns in multiline parentheses for pretty printing
|
|
865
|
+
const indentedColumns = columnNames.map(col => context.indent(col));
|
|
866
|
+
output.push('(\n' + indentedColumns.join(',\n') + '\n)');
|
|
867
|
+
}
|
|
868
|
+
else {
|
|
869
|
+
output.push(context.parens(columnNames.join(', ')));
|
|
870
|
+
}
|
|
710
871
|
}
|
|
711
872
|
if (node.selectStmt) {
|
|
712
873
|
output.push(this.visit(node.selectStmt, context));
|
|
@@ -727,7 +888,7 @@ class Deparser {
|
|
|
727
888
|
else if (infer.indexElems) {
|
|
728
889
|
const elems = list_utils_1.ListUtils.unwrapList(infer.indexElems);
|
|
729
890
|
const indexElems = elems.map(elem => this.visit(elem, context));
|
|
730
|
-
output.push(
|
|
891
|
+
output.push(context.parens(indexElems.join(', ')));
|
|
731
892
|
}
|
|
732
893
|
// Handle WHERE clause for conflict detection
|
|
733
894
|
if (infer.whereClause) {
|
|
@@ -743,12 +904,12 @@ class Deparser {
|
|
|
743
904
|
if (firstTarget.ResTarget?.val?.MultiAssignRef && targetList.every(target => target.ResTarget?.val?.MultiAssignRef)) {
|
|
744
905
|
const sortedTargets = targetList.sort((a, b) => a.ResTarget.val.MultiAssignRef.colno - b.ResTarget.val.MultiAssignRef.colno);
|
|
745
906
|
const names = sortedTargets.map(target => target.ResTarget.name);
|
|
746
|
-
output.push(
|
|
907
|
+
output.push(context.parens(names.join(', ')));
|
|
747
908
|
output.push('=');
|
|
748
909
|
output.push(this.visit(firstTarget.ResTarget.val.MultiAssignRef.source, context));
|
|
749
910
|
}
|
|
750
911
|
else {
|
|
751
|
-
const updateContext =
|
|
912
|
+
const updateContext = context.spawn('UpdateStmt', { update: true });
|
|
752
913
|
const targets = targetList.map(target => this.visit(target, updateContext));
|
|
753
914
|
output.push(targets.join(', '));
|
|
754
915
|
}
|
|
@@ -802,12 +963,12 @@ class Deparser {
|
|
|
802
963
|
}
|
|
803
964
|
}
|
|
804
965
|
const names = relatedTargets.map(t => t.ResTarget.name);
|
|
805
|
-
const multiAssignment = `${
|
|
966
|
+
const multiAssignment = `${context.parens(names.join(', '))} = ${this.visit(multiAssignRef.source, context)}`;
|
|
806
967
|
assignmentParts.push(multiAssignment);
|
|
807
968
|
}
|
|
808
969
|
else {
|
|
809
970
|
// Handle regular single-column assignment
|
|
810
|
-
assignmentParts.push(this.visit(target,
|
|
971
|
+
assignmentParts.push(this.visit(target, context.spawn('UpdateStmt', { update: true })));
|
|
811
972
|
processedTargets.add(i);
|
|
812
973
|
}
|
|
813
974
|
}
|
|
@@ -899,14 +1060,14 @@ class Deparser {
|
|
|
899
1060
|
}
|
|
900
1061
|
if (node.ctes && node.ctes.length > 0) {
|
|
901
1062
|
const ctes = list_utils_1.ListUtils.unwrapList(node.ctes);
|
|
902
|
-
if (
|
|
1063
|
+
if (context.isPretty()) {
|
|
903
1064
|
const cteStrings = ctes.map((cte, index) => {
|
|
904
1065
|
const cteStr = this.visit(cte, context);
|
|
905
|
-
const prefix = index === 0 ?
|
|
1066
|
+
const prefix = index === 0 ? context.newline() : ',' + context.newline();
|
|
906
1067
|
if (this.containsMultilineStringLiteral(cteStr)) {
|
|
907
1068
|
return prefix + cteStr;
|
|
908
1069
|
}
|
|
909
|
-
return prefix +
|
|
1070
|
+
return prefix + context.indent(cteStr);
|
|
910
1071
|
});
|
|
911
1072
|
output.push(cteStrings.join(''));
|
|
912
1073
|
}
|
|
@@ -992,14 +1153,14 @@ class Deparser {
|
|
|
992
1153
|
if (context.bool) {
|
|
993
1154
|
formatStr = '(%s)';
|
|
994
1155
|
}
|
|
995
|
-
const boolContext =
|
|
1156
|
+
const boolContext = context.spawn('BoolExpr', { bool: true });
|
|
996
1157
|
// explanation of our syntax/fix below:
|
|
997
1158
|
// return formatStr.replace('%s', andArgs); // ❌ Interprets $ as special syntax
|
|
998
1159
|
// return formatStr.replace('%s', () => andArgs); // ✅ Function callback prevents interpretation
|
|
999
1160
|
switch (boolop) {
|
|
1000
1161
|
case 'AND_EXPR':
|
|
1001
|
-
if (
|
|
1002
|
-
const andArgs = args.map(arg => this.visit(arg, boolContext)).join(
|
|
1162
|
+
if (context.isPretty() && args.length > 1) {
|
|
1163
|
+
const andArgs = args.map(arg => this.visit(arg, boolContext)).join(context.newline() + context.indent('AND '));
|
|
1003
1164
|
return formatStr.replace('%s', () => andArgs);
|
|
1004
1165
|
}
|
|
1005
1166
|
else {
|
|
@@ -1007,8 +1168,8 @@ class Deparser {
|
|
|
1007
1168
|
return formatStr.replace('%s', () => andArgs);
|
|
1008
1169
|
}
|
|
1009
1170
|
case 'OR_EXPR':
|
|
1010
|
-
if (
|
|
1011
|
-
const orArgs = args.map(arg => this.visit(arg, boolContext)).join(
|
|
1171
|
+
if (context.isPretty() && args.length > 1) {
|
|
1172
|
+
const orArgs = args.map(arg => this.visit(arg, boolContext)).join(context.newline() + context.indent('OR '));
|
|
1012
1173
|
return formatStr.replace('%s', () => orArgs);
|
|
1013
1174
|
}
|
|
1014
1175
|
else {
|
|
@@ -1139,9 +1300,9 @@ class Deparser {
|
|
|
1139
1300
|
const timezone = this.visit(args[0], context);
|
|
1140
1301
|
// Add parentheses around timestamp if it contains arithmetic operations
|
|
1141
1302
|
if (args[1] && 'A_Expr' in args[1] && args[1].A_Expr?.kind === 'AEXPR_OP') {
|
|
1142
|
-
const op = this.deparseOperatorName(list_utils_1.ListUtils.unwrapList(args[1].A_Expr.name));
|
|
1303
|
+
const op = this.deparseOperatorName(list_utils_1.ListUtils.unwrapList(args[1].A_Expr.name), context);
|
|
1143
1304
|
if (op === '+' || op === '-' || op === '*' || op === '/') {
|
|
1144
|
-
timestamp =
|
|
1305
|
+
timestamp = context.parens(timestamp);
|
|
1145
1306
|
}
|
|
1146
1307
|
}
|
|
1147
1308
|
return `${timestamp} AT TIME ZONE ${timezone}`;
|
|
@@ -1211,14 +1372,14 @@ class Deparser {
|
|
|
1211
1372
|
windowParts.push(`ORDER BY ${orderStrs.join(', ')}`);
|
|
1212
1373
|
}
|
|
1213
1374
|
// Handle window frame specifications using the dedicated formatWindowFrame method
|
|
1214
|
-
const frameClause = this.formatWindowFrame(node.over);
|
|
1375
|
+
const frameClause = this.formatWindowFrame(node.over, context.spawn('FuncCall'));
|
|
1215
1376
|
if (frameClause) {
|
|
1216
1377
|
windowParts.push(frameClause);
|
|
1217
1378
|
}
|
|
1218
1379
|
if (windowParts.length > 0) {
|
|
1219
|
-
if (
|
|
1220
|
-
const formattedParts = windowParts.map(part =>
|
|
1221
|
-
result += ` OVER (${
|
|
1380
|
+
if (context.isPretty() && windowParts.length > 1) {
|
|
1381
|
+
const formattedParts = windowParts.map(part => context.indent(part));
|
|
1382
|
+
result += ` OVER (${context.newline()}${formattedParts.join(context.newline())}${context.newline()})`;
|
|
1222
1383
|
}
|
|
1223
1384
|
else {
|
|
1224
1385
|
result += ` OVER (${windowParts.join(' ')})`;
|
|
@@ -1498,9 +1659,6 @@ class Deparser {
|
|
|
1498
1659
|
return output.join(' ');
|
|
1499
1660
|
}
|
|
1500
1661
|
if (catalog === 'pg_catalog') {
|
|
1501
|
-
const builtinTypes = ['int2', 'int4', 'int8', 'float4', 'float8', 'numeric', 'decimal',
|
|
1502
|
-
'varchar', 'char', 'bpchar', 'text', 'bool', 'date', 'time', 'timestamp',
|
|
1503
|
-
'timestamptz', 'interval', 'bytea', 'uuid', 'json', 'jsonb'];
|
|
1504
1662
|
let typeName = `${catalog}.${type}`;
|
|
1505
1663
|
if (type === 'bpchar' && args) {
|
|
1506
1664
|
typeName = 'char';
|
|
@@ -1557,6 +1715,24 @@ class Deparser {
|
|
|
1557
1715
|
typeName = 'time with time zone';
|
|
1558
1716
|
}
|
|
1559
1717
|
}
|
|
1718
|
+
else if (type === 'timestamp') {
|
|
1719
|
+
if (args) {
|
|
1720
|
+
typeName = `timestamp(${args})`;
|
|
1721
|
+
args = null; // Don't apply args again in mods()
|
|
1722
|
+
}
|
|
1723
|
+
else {
|
|
1724
|
+
typeName = 'timestamp';
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
else if (type === 'time') {
|
|
1728
|
+
if (args) {
|
|
1729
|
+
typeName = `time(${args})`;
|
|
1730
|
+
args = null; // Don't apply args again in mods()
|
|
1731
|
+
}
|
|
1732
|
+
else {
|
|
1733
|
+
typeName = 'time';
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1560
1736
|
let result = mods(typeName, args);
|
|
1561
1737
|
if (node.arrayBounds && node.arrayBounds.length > 0) {
|
|
1562
1738
|
result += formatArrayBounds(node.arrayBounds);
|
|
@@ -1586,7 +1762,7 @@ class Deparser {
|
|
|
1586
1762
|
}
|
|
1587
1763
|
return this.quoteIfNeeded(colStr);
|
|
1588
1764
|
});
|
|
1589
|
-
output.push('AS', this.quoteIfNeeded(name) +
|
|
1765
|
+
output.push('AS', this.quoteIfNeeded(name) + context.parens(quotedColnames.join(', ')));
|
|
1590
1766
|
}
|
|
1591
1767
|
else {
|
|
1592
1768
|
output.push('AS', this.quoteIfNeeded(name));
|
|
@@ -1598,7 +1774,7 @@ class Deparser {
|
|
|
1598
1774
|
// Handle ONLY keyword for inheritance control (but not for type definitions, ALTER TYPE, or CREATE FOREIGN TABLE)
|
|
1599
1775
|
if (node && (!('inh' in node) || node.inh === undefined) &&
|
|
1600
1776
|
!context.parentNodeTypes.includes('CompositeTypeStmt') &&
|
|
1601
|
-
!context.parentNodeTypes.includes('AlterTypeStmt') &&
|
|
1777
|
+
(!context.parentNodeTypes.includes('AlterTypeStmt') && context.objtype !== 'OBJECT_TYPE') &&
|
|
1602
1778
|
!context.parentNodeTypes.includes('CreateForeignTableStmt')) {
|
|
1603
1779
|
output.push('ONLY');
|
|
1604
1780
|
}
|
|
@@ -1795,6 +1971,18 @@ class Deparser {
|
|
|
1795
1971
|
return `pg_catalog.${typeName}`;
|
|
1796
1972
|
}
|
|
1797
1973
|
}
|
|
1974
|
+
isPgCatalogType(typeName) {
|
|
1975
|
+
const cleanTypeName = typeName.replace(/^pg_catalog\./, '');
|
|
1976
|
+
if (pgCatalogTypes.includes(cleanTypeName)) {
|
|
1977
|
+
return true;
|
|
1978
|
+
}
|
|
1979
|
+
for (const [realType, aliases] of pgCatalogTypeAliases) {
|
|
1980
|
+
if (aliases.includes(cleanTypeName)) {
|
|
1981
|
+
return true;
|
|
1982
|
+
}
|
|
1983
|
+
}
|
|
1984
|
+
return false;
|
|
1985
|
+
}
|
|
1798
1986
|
A_ArrayExpr(node, context) {
|
|
1799
1987
|
const elements = list_utils_1.ListUtils.unwrapList(node.elements);
|
|
1800
1988
|
const elementStrs = elements.map(el => this.visit(el, context));
|
|
@@ -1846,26 +2034,26 @@ class Deparser {
|
|
|
1846
2034
|
output.push(this.visit(node.arg, context));
|
|
1847
2035
|
}
|
|
1848
2036
|
const args = list_utils_1.ListUtils.unwrapList(node.args);
|
|
1849
|
-
if (
|
|
2037
|
+
if (context.isPretty() && args.length > 0) {
|
|
1850
2038
|
for (const arg of args) {
|
|
1851
2039
|
const whenClause = this.visit(arg, context);
|
|
1852
2040
|
if (this.containsMultilineStringLiteral(whenClause)) {
|
|
1853
|
-
output.push(
|
|
2041
|
+
output.push(context.newline() + whenClause);
|
|
1854
2042
|
}
|
|
1855
2043
|
else {
|
|
1856
|
-
output.push(
|
|
2044
|
+
output.push(context.newline() + context.indent(whenClause));
|
|
1857
2045
|
}
|
|
1858
2046
|
}
|
|
1859
2047
|
if (node.defresult) {
|
|
1860
2048
|
const elseResult = this.visit(node.defresult, context);
|
|
1861
2049
|
if (this.containsMultilineStringLiteral(elseResult)) {
|
|
1862
|
-
output.push(
|
|
2050
|
+
output.push(context.newline() + 'ELSE ' + elseResult);
|
|
1863
2051
|
}
|
|
1864
2052
|
else {
|
|
1865
|
-
output.push(
|
|
2053
|
+
output.push(context.newline() + context.indent('ELSE ' + elseResult));
|
|
1866
2054
|
}
|
|
1867
2055
|
}
|
|
1868
|
-
output.push(
|
|
2056
|
+
output.push(context.newline() + 'END');
|
|
1869
2057
|
return output.join(' ');
|
|
1870
2058
|
}
|
|
1871
2059
|
else {
|
|
@@ -1888,28 +2076,29 @@ class Deparser {
|
|
|
1888
2076
|
TypeCast(node, context) {
|
|
1889
2077
|
const arg = this.visit(node.arg, context);
|
|
1890
2078
|
const typeName = this.TypeName(node.typeName, context);
|
|
1891
|
-
// Check if this is a bpchar typecast that should
|
|
1892
|
-
if (typeName === 'bpchar'
|
|
1893
|
-
const names =
|
|
1894
|
-
|
|
1895
|
-
names[0]
|
|
1896
|
-
names[1]
|
|
1897
|
-
|
|
2079
|
+
// Check if this is a bpchar typecast that should preserve original syntax for AST consistency
|
|
2080
|
+
if (typeName === 'bpchar' || typeName === 'pg_catalog.bpchar') {
|
|
2081
|
+
const names = node.typeName?.names;
|
|
2082
|
+
const isQualifiedBpchar = names && names.length === 2 &&
|
|
2083
|
+
names[0]?.String?.sval === 'pg_catalog' &&
|
|
2084
|
+
names[1]?.String?.sval === 'bpchar';
|
|
2085
|
+
if (isQualifiedBpchar) {
|
|
2086
|
+
return `CAST(${arg} AS ${typeName})`;
|
|
1898
2087
|
}
|
|
1899
2088
|
}
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
2089
|
+
if (this.isPgCatalogType(typeName)) {
|
|
2090
|
+
const argType = this.getNodeType(node.arg);
|
|
2091
|
+
const isSimpleArgument = argType === 'A_Const' || argType === 'ColumnRef';
|
|
2092
|
+
const isFunctionCall = argType === 'FuncCall';
|
|
2093
|
+
if (isSimpleArgument || isFunctionCall) {
|
|
2094
|
+
// For simple arguments, avoid :: syntax if they have complex structure
|
|
2095
|
+
if (isSimpleArgument && (arg.includes('(') || arg.startsWith('-'))) {
|
|
2096
|
+
}
|
|
2097
|
+
else {
|
|
2098
|
+
const cleanTypeName = typeName.replace('pg_catalog.', '');
|
|
2099
|
+
return `${arg}::${cleanTypeName}`;
|
|
2100
|
+
}
|
|
2101
|
+
}
|
|
1913
2102
|
}
|
|
1914
2103
|
return `CAST(${arg} AS ${typeName})`;
|
|
1915
2104
|
}
|
|
@@ -1932,7 +2121,7 @@ class Deparser {
|
|
|
1932
2121
|
}
|
|
1933
2122
|
BooleanTest(node, context) {
|
|
1934
2123
|
const output = [];
|
|
1935
|
-
const boolContext =
|
|
2124
|
+
const boolContext = context.spawn('BooleanTest', { bool: true });
|
|
1936
2125
|
output.push(this.visit(node.arg, boolContext));
|
|
1937
2126
|
switch (node.booltesttype) {
|
|
1938
2127
|
case 'IS_TRUE':
|
|
@@ -2083,24 +2272,31 @@ class Deparser {
|
|
|
2083
2272
|
const elementStrs = elements.map(el => {
|
|
2084
2273
|
return this.deparse(el, context);
|
|
2085
2274
|
});
|
|
2086
|
-
output.push(
|
|
2275
|
+
output.push(context.parens(elementStrs.join(', ')));
|
|
2087
2276
|
}
|
|
2088
2277
|
}
|
|
2089
2278
|
else if (node.tableElts) {
|
|
2090
2279
|
const elements = list_utils_1.ListUtils.unwrapList(node.tableElts);
|
|
2091
2280
|
const elementStrs = elements.map(el => {
|
|
2092
|
-
return this.deparse(el, context);
|
|
2281
|
+
return this.deparse(el, context.spawn('CreateStmt'));
|
|
2093
2282
|
});
|
|
2094
|
-
if (
|
|
2095
|
-
const formattedElements = elementStrs.map(el =>
|
|
2096
|
-
|
|
2283
|
+
if (context.isPretty()) {
|
|
2284
|
+
const formattedElements = elementStrs.map(el => {
|
|
2285
|
+
const trimmedEl = el.trim();
|
|
2286
|
+
// Remove leading newlines from constraint elements to avoid extra blank lines
|
|
2287
|
+
if (trimmedEl.startsWith('\n')) {
|
|
2288
|
+
return context.indent(trimmedEl.substring(1));
|
|
2289
|
+
}
|
|
2290
|
+
return context.indent(trimmedEl);
|
|
2291
|
+
}).join(',' + context.newline());
|
|
2292
|
+
output.push('(' + context.newline() + formattedElements + context.newline() + ')');
|
|
2097
2293
|
}
|
|
2098
2294
|
else {
|
|
2099
|
-
output.push(
|
|
2295
|
+
output.push(context.parens(elementStrs.join(', ')));
|
|
2100
2296
|
}
|
|
2101
2297
|
}
|
|
2102
2298
|
else if (!node.partbound) {
|
|
2103
|
-
output.push(
|
|
2299
|
+
output.push(context.parens(''));
|
|
2104
2300
|
}
|
|
2105
2301
|
if (node.partbound && node.inhRelations && node.inhRelations.length > 0) {
|
|
2106
2302
|
output.push('PARTITION OF');
|
|
@@ -2143,7 +2339,7 @@ class Deparser {
|
|
|
2143
2339
|
output.push('INHERITS');
|
|
2144
2340
|
const inherits = list_utils_1.ListUtils.unwrapList(node.inhRelations);
|
|
2145
2341
|
const inheritStrs = inherits.map(rel => this.visit(rel, context));
|
|
2146
|
-
output.push(
|
|
2342
|
+
output.push(context.parens(inheritStrs.join(', ')));
|
|
2147
2343
|
}
|
|
2148
2344
|
if (node.partspec) {
|
|
2149
2345
|
output.push('PARTITION BY');
|
|
@@ -2181,7 +2377,7 @@ class Deparser {
|
|
|
2181
2377
|
}
|
|
2182
2378
|
// Handle table options like WITH (fillfactor=10)
|
|
2183
2379
|
if (node.options && node.options.length > 0) {
|
|
2184
|
-
const createStmtContext =
|
|
2380
|
+
const createStmtContext = context.spawn('CreateStmt');
|
|
2185
2381
|
const optionStrs = node.options.map((option) => {
|
|
2186
2382
|
return this.deparse(option, createStmtContext);
|
|
2187
2383
|
});
|
|
@@ -2204,7 +2400,7 @@ class Deparser {
|
|
|
2204
2400
|
}
|
|
2205
2401
|
if (node.fdwoptions && node.fdwoptions.length > 0) {
|
|
2206
2402
|
output.push('OPTIONS');
|
|
2207
|
-
const columnContext =
|
|
2403
|
+
const columnContext = context.spawn('ColumnDef');
|
|
2208
2404
|
const options = list_utils_1.ListUtils.unwrapList(node.fdwoptions).map(opt => this.visit(opt, columnContext));
|
|
2209
2405
|
output.push(`(${options.join(', ')})`);
|
|
2210
2406
|
}
|
|
@@ -2214,7 +2410,7 @@ class Deparser {
|
|
|
2214
2410
|
if (node.constraints) {
|
|
2215
2411
|
const constraints = list_utils_1.ListUtils.unwrapList(node.constraints);
|
|
2216
2412
|
const constraintStrs = constraints.map(constraint => {
|
|
2217
|
-
const columnConstraintContext =
|
|
2413
|
+
const columnConstraintContext = context.spawn('ColumnDef', { isColumnConstraint: true });
|
|
2218
2414
|
return this.visit(constraint, columnConstraintContext);
|
|
2219
2415
|
});
|
|
2220
2416
|
output.push(...constraintStrs);
|
|
@@ -2254,9 +2450,25 @@ class Deparser {
|
|
|
2254
2450
|
}
|
|
2255
2451
|
break;
|
|
2256
2452
|
case 'CONSTR_CHECK':
|
|
2257
|
-
|
|
2453
|
+
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2454
|
+
output.push('\n' + context.indent('CHECK'));
|
|
2455
|
+
}
|
|
2456
|
+
else {
|
|
2457
|
+
output.push('CHECK');
|
|
2458
|
+
}
|
|
2258
2459
|
if (node.raw_expr) {
|
|
2259
|
-
|
|
2460
|
+
if (context.isPretty()) {
|
|
2461
|
+
const checkExpr = this.visit(node.raw_expr, context);
|
|
2462
|
+
if (checkExpr.includes('\n')) {
|
|
2463
|
+
output.push('(\n' + context.indent(checkExpr) + '\n)');
|
|
2464
|
+
}
|
|
2465
|
+
else {
|
|
2466
|
+
output.push(`(${checkExpr})`);
|
|
2467
|
+
}
|
|
2468
|
+
}
|
|
2469
|
+
else {
|
|
2470
|
+
output.push(context.parens(this.visit(node.raw_expr, context)));
|
|
2471
|
+
}
|
|
2260
2472
|
}
|
|
2261
2473
|
// Handle NOT VALID for check constraints
|
|
2262
2474
|
if (node.skip_validation) {
|
|
@@ -2277,7 +2489,7 @@ class Deparser {
|
|
|
2277
2489
|
}
|
|
2278
2490
|
output.push('AS');
|
|
2279
2491
|
if (node.raw_expr) {
|
|
2280
|
-
output.push(
|
|
2492
|
+
output.push(context.parens(this.visit(node.raw_expr, context)));
|
|
2281
2493
|
}
|
|
2282
2494
|
output.push('STORED');
|
|
2283
2495
|
break;
|
|
@@ -2295,30 +2507,61 @@ class Deparser {
|
|
|
2295
2507
|
.map(option => {
|
|
2296
2508
|
if (option.DefElem) {
|
|
2297
2509
|
const defElem = option.DefElem;
|
|
2298
|
-
|
|
2299
|
-
|
|
2510
|
+
if (defElem.defname === 'sequence_name') {
|
|
2511
|
+
if (defElem.arg && defElem.arg.List) {
|
|
2512
|
+
const nameList = list_utils_1.ListUtils.unwrapList(defElem.arg)
|
|
2513
|
+
.map(item => this.visit(item, context))
|
|
2514
|
+
.join('.');
|
|
2515
|
+
return `SEQUENCE NAME ${nameList}`;
|
|
2516
|
+
}
|
|
2517
|
+
return 'SEQUENCE NAME';
|
|
2518
|
+
}
|
|
2519
|
+
else if (defElem.defname === 'start') {
|
|
2520
|
+
const argValue = defElem.arg ? this.visit(defElem.arg, context) : '';
|
|
2300
2521
|
return `START WITH ${argValue}`;
|
|
2301
2522
|
}
|
|
2302
2523
|
else if (defElem.defname === 'increment') {
|
|
2524
|
+
const argValue = defElem.arg ? this.visit(defElem.arg, context) : '';
|
|
2303
2525
|
return `INCREMENT BY ${argValue}`;
|
|
2304
2526
|
}
|
|
2305
2527
|
else if (defElem.defname === 'minvalue') {
|
|
2306
|
-
|
|
2528
|
+
if (defElem.arg) {
|
|
2529
|
+
const argValue = this.visit(defElem.arg, context);
|
|
2530
|
+
return `MINVALUE ${argValue}`;
|
|
2531
|
+
}
|
|
2532
|
+
else {
|
|
2533
|
+
return 'NO MINVALUE';
|
|
2534
|
+
}
|
|
2307
2535
|
}
|
|
2308
2536
|
else if (defElem.defname === 'maxvalue') {
|
|
2309
|
-
|
|
2537
|
+
if (defElem.arg) {
|
|
2538
|
+
const argValue = this.visit(defElem.arg, context);
|
|
2539
|
+
return `MAXVALUE ${argValue}`;
|
|
2540
|
+
}
|
|
2541
|
+
else {
|
|
2542
|
+
return 'NO MAXVALUE';
|
|
2543
|
+
}
|
|
2310
2544
|
}
|
|
2311
2545
|
else if (defElem.defname === 'cache') {
|
|
2546
|
+
const argValue = defElem.arg ? this.visit(defElem.arg, context) : '';
|
|
2312
2547
|
return `CACHE ${argValue}`;
|
|
2313
2548
|
}
|
|
2314
2549
|
else if (defElem.defname === 'cycle') {
|
|
2550
|
+
const argValue = defElem.arg ? this.visit(defElem.arg, context) : '';
|
|
2315
2551
|
return argValue === 'true' ? 'CYCLE' : 'NO CYCLE';
|
|
2316
2552
|
}
|
|
2553
|
+
const argValue = defElem.arg ? this.visit(defElem.arg, context) : '';
|
|
2317
2554
|
return `${defElem.defname.toUpperCase()} ${argValue}`;
|
|
2318
2555
|
}
|
|
2319
2556
|
return this.visit(option, context);
|
|
2320
2557
|
});
|
|
2321
|
-
|
|
2558
|
+
if (context.isPretty()) {
|
|
2559
|
+
const indentedOptions = optionStrs.map(option => context.indent(option));
|
|
2560
|
+
output.push('(\n' + indentedOptions.join('\n') + '\n)');
|
|
2561
|
+
}
|
|
2562
|
+
else {
|
|
2563
|
+
output.push(`(${optionStrs.join(' ')})`);
|
|
2564
|
+
}
|
|
2322
2565
|
}
|
|
2323
2566
|
break;
|
|
2324
2567
|
case 'CONSTR_PRIMARY':
|
|
@@ -2335,7 +2578,12 @@ class Deparser {
|
|
|
2335
2578
|
}
|
|
2336
2579
|
break;
|
|
2337
2580
|
case 'CONSTR_UNIQUE':
|
|
2338
|
-
|
|
2581
|
+
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2582
|
+
output.push('\n' + context.indent('UNIQUE'));
|
|
2583
|
+
}
|
|
2584
|
+
else {
|
|
2585
|
+
output.push('UNIQUE');
|
|
2586
|
+
}
|
|
2339
2587
|
if (node.nulls_not_distinct) {
|
|
2340
2588
|
output.push('NULLS NOT DISTINCT');
|
|
2341
2589
|
}
|
|
@@ -2353,33 +2601,77 @@ class Deparser {
|
|
|
2353
2601
|
case 'CONSTR_FOREIGN':
|
|
2354
2602
|
// Only add "FOREIGN KEY" for table-level constraints, not column-level constraints
|
|
2355
2603
|
if (!context.isColumnConstraint) {
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2604
|
+
if (context.isPretty()) {
|
|
2605
|
+
output.push('\n' + context.indent('FOREIGN KEY'));
|
|
2606
|
+
if (node.fk_attrs && node.fk_attrs.length > 0) {
|
|
2607
|
+
const fkAttrs = list_utils_1.ListUtils.unwrapList(node.fk_attrs)
|
|
2608
|
+
.map(attr => this.visit(attr, context))
|
|
2609
|
+
.join(', ');
|
|
2610
|
+
output.push(`(${fkAttrs})`);
|
|
2611
|
+
}
|
|
2612
|
+
output.push('\n' + context.indent('REFERENCES'));
|
|
2613
|
+
}
|
|
2614
|
+
else {
|
|
2615
|
+
output.push('FOREIGN KEY');
|
|
2616
|
+
if (node.fk_attrs && node.fk_attrs.length > 0) {
|
|
2617
|
+
const fkAttrs = list_utils_1.ListUtils.unwrapList(node.fk_attrs)
|
|
2618
|
+
.map(attr => this.visit(attr, context))
|
|
2619
|
+
.join(', ');
|
|
2620
|
+
output.push(`(${fkAttrs})`);
|
|
2621
|
+
}
|
|
2622
|
+
output.push('REFERENCES');
|
|
2362
2623
|
}
|
|
2363
2624
|
}
|
|
2364
|
-
|
|
2625
|
+
else {
|
|
2626
|
+
output.push('REFERENCES');
|
|
2627
|
+
}
|
|
2365
2628
|
if (node.pktable) {
|
|
2366
|
-
|
|
2629
|
+
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2630
|
+
const lastIndex = output.length - 1;
|
|
2631
|
+
if (lastIndex >= 0 && output[lastIndex].includes('REFERENCES')) {
|
|
2632
|
+
output[lastIndex] += ' ' + this.RangeVar(node.pktable, context);
|
|
2633
|
+
}
|
|
2634
|
+
else {
|
|
2635
|
+
output.push(this.RangeVar(node.pktable, context));
|
|
2636
|
+
}
|
|
2637
|
+
}
|
|
2638
|
+
else {
|
|
2639
|
+
output.push(this.RangeVar(node.pktable, context));
|
|
2640
|
+
}
|
|
2367
2641
|
}
|
|
2368
2642
|
if (node.pk_attrs && node.pk_attrs.length > 0) {
|
|
2369
2643
|
const pkAttrs = list_utils_1.ListUtils.unwrapList(node.pk_attrs)
|
|
2370
2644
|
.map(attr => this.visit(attr, context))
|
|
2371
2645
|
.join(', ');
|
|
2372
|
-
|
|
2646
|
+
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2647
|
+
const lastIndex = output.length - 1;
|
|
2648
|
+
if (lastIndex >= 0) {
|
|
2649
|
+
output[lastIndex] += ` (${pkAttrs})`;
|
|
2650
|
+
}
|
|
2651
|
+
else {
|
|
2652
|
+
output.push(`(${pkAttrs})`);
|
|
2653
|
+
}
|
|
2654
|
+
}
|
|
2655
|
+
else {
|
|
2656
|
+
output.push(`(${pkAttrs})`);
|
|
2657
|
+
}
|
|
2373
2658
|
}
|
|
2374
2659
|
if (node.fk_matchtype && node.fk_matchtype !== 's') {
|
|
2660
|
+
let matchClause = '';
|
|
2375
2661
|
switch (node.fk_matchtype) {
|
|
2376
2662
|
case 'f':
|
|
2377
|
-
|
|
2663
|
+
matchClause = 'MATCH FULL';
|
|
2378
2664
|
break;
|
|
2379
2665
|
case 'p':
|
|
2380
|
-
|
|
2666
|
+
matchClause = 'MATCH PARTIAL';
|
|
2381
2667
|
break;
|
|
2382
2668
|
}
|
|
2669
|
+
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2670
|
+
output.push('\n' + context.indent(matchClause));
|
|
2671
|
+
}
|
|
2672
|
+
else {
|
|
2673
|
+
output.push(matchClause);
|
|
2674
|
+
}
|
|
2383
2675
|
}
|
|
2384
2676
|
if (node.fk_upd_action && node.fk_upd_action !== 'a') {
|
|
2385
2677
|
let updateClause = 'ON UPDATE ';
|
|
@@ -2397,8 +2689,8 @@ class Deparser {
|
|
|
2397
2689
|
updateClause += 'SET DEFAULT';
|
|
2398
2690
|
break;
|
|
2399
2691
|
}
|
|
2400
|
-
if (
|
|
2401
|
-
output.push('\n' +
|
|
2692
|
+
if (context.isPretty()) {
|
|
2693
|
+
output.push('\n' + context.indent(updateClause));
|
|
2402
2694
|
}
|
|
2403
2695
|
else {
|
|
2404
2696
|
output.push('ON UPDATE');
|
|
@@ -2421,8 +2713,8 @@ class Deparser {
|
|
|
2421
2713
|
deleteClause += 'SET DEFAULT';
|
|
2422
2714
|
break;
|
|
2423
2715
|
}
|
|
2424
|
-
if (
|
|
2425
|
-
output.push('\n' +
|
|
2716
|
+
if (context.isPretty()) {
|
|
2717
|
+
output.push('\n' + context.indent(deleteClause));
|
|
2426
2718
|
}
|
|
2427
2719
|
else {
|
|
2428
2720
|
output.push('ON DELETE');
|
|
@@ -2431,7 +2723,12 @@ class Deparser {
|
|
|
2431
2723
|
}
|
|
2432
2724
|
// Handle NOT VALID for foreign key constraints - only for table constraints, not domain constraints
|
|
2433
2725
|
if (node.skip_validation && !context.isDomainConstraint) {
|
|
2434
|
-
|
|
2726
|
+
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2727
|
+
output.push('\n' + context.indent('NOT VALID'));
|
|
2728
|
+
}
|
|
2729
|
+
else {
|
|
2730
|
+
output.push('NOT VALID');
|
|
2731
|
+
}
|
|
2435
2732
|
}
|
|
2436
2733
|
break;
|
|
2437
2734
|
case 'CONSTR_ATTR_DEFERRABLE':
|
|
@@ -2485,13 +2782,13 @@ class Deparser {
|
|
|
2485
2782
|
// Handle deferrable constraints for all constraint types that support it
|
|
2486
2783
|
if (node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_FOREIGN') {
|
|
2487
2784
|
if (node.deferrable) {
|
|
2488
|
-
if (
|
|
2489
|
-
output.push('\n' +
|
|
2785
|
+
if (context.isPretty() && node.contype === 'CONSTR_FOREIGN') {
|
|
2786
|
+
output.push('\n' + context.indent('DEFERRABLE'));
|
|
2490
2787
|
if (node.initdeferred === true) {
|
|
2491
|
-
output.push('\n' +
|
|
2788
|
+
output.push('\n' + context.indent('INITIALLY DEFERRED'));
|
|
2492
2789
|
}
|
|
2493
2790
|
else if (node.initdeferred === false) {
|
|
2494
|
-
output.push('\n' +
|
|
2791
|
+
output.push('\n' + context.indent('INITIALLY IMMEDIATE'));
|
|
2495
2792
|
}
|
|
2496
2793
|
}
|
|
2497
2794
|
else {
|
|
@@ -2505,15 +2802,15 @@ class Deparser {
|
|
|
2505
2802
|
}
|
|
2506
2803
|
}
|
|
2507
2804
|
else if (node.deferrable === false) {
|
|
2508
|
-
if (
|
|
2509
|
-
output.push('\n' +
|
|
2805
|
+
if (context.isPretty() && node.contype === 'CONSTR_FOREIGN') {
|
|
2806
|
+
output.push('\n' + context.indent('NOT DEFERRABLE'));
|
|
2510
2807
|
}
|
|
2511
2808
|
else {
|
|
2512
2809
|
output.push('NOT DEFERRABLE');
|
|
2513
2810
|
}
|
|
2514
2811
|
}
|
|
2515
2812
|
}
|
|
2516
|
-
if (
|
|
2813
|
+
if (context.isPretty() && node.contype === 'CONSTR_FOREIGN') {
|
|
2517
2814
|
let result = '';
|
|
2518
2815
|
for (let i = 0; i < output.length; i++) {
|
|
2519
2816
|
if (output[i].startsWith('\n')) {
|
|
@@ -2531,12 +2828,12 @@ class Deparser {
|
|
|
2531
2828
|
return output.join(' ');
|
|
2532
2829
|
}
|
|
2533
2830
|
SubLink(node, context) {
|
|
2534
|
-
const subselect =
|
|
2831
|
+
const subselect = context.parens(this.visit(node.subselect, context));
|
|
2535
2832
|
switch (node.subLinkType) {
|
|
2536
2833
|
case 'ANY_SUBLINK':
|
|
2537
2834
|
if (node.testexpr && node.operName) {
|
|
2538
2835
|
const testExpr = this.visit(node.testexpr, context);
|
|
2539
|
-
const operator = this.deparseOperatorName(node.operName);
|
|
2836
|
+
const operator = this.deparseOperatorName(node.operName, context);
|
|
2540
2837
|
return `${testExpr} ${operator} ANY ${subselect}`;
|
|
2541
2838
|
}
|
|
2542
2839
|
else if (node.testexpr) {
|
|
@@ -2547,7 +2844,7 @@ class Deparser {
|
|
|
2547
2844
|
case 'ALL_SUBLINK':
|
|
2548
2845
|
if (node.testexpr && node.operName) {
|
|
2549
2846
|
const testExpr = this.visit(node.testexpr, context);
|
|
2550
|
-
const operator = this.deparseOperatorName(node.operName);
|
|
2847
|
+
const operator = this.deparseOperatorName(node.operName, context);
|
|
2551
2848
|
return `${testExpr} ${operator} ALL ${subselect}`;
|
|
2552
2849
|
}
|
|
2553
2850
|
return subselect;
|
|
@@ -2589,7 +2886,7 @@ class Deparser {
|
|
|
2589
2886
|
}
|
|
2590
2887
|
// Only add frame clause if frameOptions indicates non-default framing
|
|
2591
2888
|
if (node.frameOptions && node.frameOptions !== 1058) {
|
|
2592
|
-
const frameClause = this.formatWindowFrame(node);
|
|
2889
|
+
const frameClause = this.formatWindowFrame(node, context.spawn('WindowDef'));
|
|
2593
2890
|
if (frameClause) {
|
|
2594
2891
|
windowParts.push(frameClause);
|
|
2595
2892
|
}
|
|
@@ -2609,7 +2906,7 @@ class Deparser {
|
|
|
2609
2906
|
}
|
|
2610
2907
|
return output.join(' ');
|
|
2611
2908
|
}
|
|
2612
|
-
formatWindowFrame(node) {
|
|
2909
|
+
formatWindowFrame(node, context) {
|
|
2613
2910
|
if (!node.frameOptions)
|
|
2614
2911
|
return null;
|
|
2615
2912
|
const frameOptions = node.frameOptions;
|
|
@@ -2618,7 +2915,7 @@ class Deparser {
|
|
|
2618
2915
|
if (frameOptions & 0x02) { // FRAMEOPTION_RANGE
|
|
2619
2916
|
frameParts.push('RANGE');
|
|
2620
2917
|
}
|
|
2621
|
-
else if (frameOptions & 0x04) { // FRAMEOPTION_ROWS
|
|
2918
|
+
else if (frameOptions & 0x04) { // FRAMEOPTION_ROWS
|
|
2622
2919
|
frameParts.push('ROWS');
|
|
2623
2920
|
}
|
|
2624
2921
|
else if (frameOptions & 0x08) { // FRAMEOPTION_GROUPS
|
|
@@ -2639,8 +2936,8 @@ class Deparser {
|
|
|
2639
2936
|
}
|
|
2640
2937
|
else if (frameOptions === 18453) {
|
|
2641
2938
|
if (node.startOffset && node.endOffset) {
|
|
2642
|
-
boundsParts.push(`${this.visit(node.startOffset,
|
|
2643
|
-
boundsParts.push(`AND ${this.visit(node.endOffset,
|
|
2939
|
+
boundsParts.push(`${this.visit(node.startOffset, context)} PRECEDING`);
|
|
2940
|
+
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
2644
2941
|
}
|
|
2645
2942
|
}
|
|
2646
2943
|
else if (frameOptions === 1557) {
|
|
@@ -2650,7 +2947,7 @@ class Deparser {
|
|
|
2650
2947
|
else if (frameOptions === 16917) {
|
|
2651
2948
|
boundsParts.push('CURRENT ROW');
|
|
2652
2949
|
if (node.endOffset) {
|
|
2653
|
-
boundsParts.push(`AND ${this.visit(node.endOffset,
|
|
2950
|
+
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
2654
2951
|
}
|
|
2655
2952
|
}
|
|
2656
2953
|
else if (frameOptions === 1058) {
|
|
@@ -2660,13 +2957,13 @@ class Deparser {
|
|
|
2660
2957
|
// Handle start bound - prioritize explicit offset values over bit flags
|
|
2661
2958
|
if (node.startOffset) {
|
|
2662
2959
|
if (frameOptions & 0x400) { // FRAMEOPTION_START_VALUE_PRECEDING
|
|
2663
|
-
boundsParts.push(`${this.visit(node.startOffset,
|
|
2960
|
+
boundsParts.push(`${this.visit(node.startOffset, context)} PRECEDING`);
|
|
2664
2961
|
}
|
|
2665
2962
|
else if (frameOptions & 0x800) { // FRAMEOPTION_START_VALUE_FOLLOWING
|
|
2666
|
-
boundsParts.push(`${this.visit(node.startOffset,
|
|
2963
|
+
boundsParts.push(`${this.visit(node.startOffset, context)} FOLLOWING`);
|
|
2667
2964
|
}
|
|
2668
2965
|
else {
|
|
2669
|
-
boundsParts.push(`${this.visit(node.startOffset,
|
|
2966
|
+
boundsParts.push(`${this.visit(node.startOffset, context)} PRECEDING`);
|
|
2670
2967
|
}
|
|
2671
2968
|
}
|
|
2672
2969
|
else if (frameOptions & 0x10) { // FRAMEOPTION_START_UNBOUNDED_PRECEDING
|
|
@@ -2679,13 +2976,13 @@ class Deparser {
|
|
|
2679
2976
|
if (node.endOffset) {
|
|
2680
2977
|
if (boundsParts.length > 0) {
|
|
2681
2978
|
if (frameOptions & 0x1000) { // FRAMEOPTION_END_VALUE_PRECEDING
|
|
2682
|
-
boundsParts.push(`AND ${this.visit(node.endOffset,
|
|
2979
|
+
boundsParts.push(`AND ${this.visit(node.endOffset, context)} PRECEDING`);
|
|
2683
2980
|
}
|
|
2684
2981
|
else if (frameOptions & 0x2000) { // FRAMEOPTION_END_VALUE_FOLLOWING
|
|
2685
|
-
boundsParts.push(`AND ${this.visit(node.endOffset,
|
|
2982
|
+
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
2686
2983
|
}
|
|
2687
2984
|
else {
|
|
2688
|
-
boundsParts.push(`AND ${this.visit(node.endOffset,
|
|
2985
|
+
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
2689
2986
|
}
|
|
2690
2987
|
}
|
|
2691
2988
|
}
|
|
@@ -2770,7 +3067,7 @@ class Deparser {
|
|
|
2770
3067
|
const colnames = list_utils_1.ListUtils.unwrapList(node.aliascolnames);
|
|
2771
3068
|
const colnameStrs = colnames.map(col => this.visit(col, context));
|
|
2772
3069
|
// Don't add space before column list parentheses to match original formatting
|
|
2773
|
-
output[output.length - 1] +=
|
|
3070
|
+
output[output.length - 1] += context.parens(colnameStrs.join(', '));
|
|
2774
3071
|
}
|
|
2775
3072
|
output.push('AS');
|
|
2776
3073
|
// Handle materialization clauses
|
|
@@ -2781,7 +3078,7 @@ class Deparser {
|
|
|
2781
3078
|
output.push('MATERIALIZED');
|
|
2782
3079
|
}
|
|
2783
3080
|
if (node.ctequery) {
|
|
2784
|
-
output.push(
|
|
3081
|
+
output.push(context.parens(this.visit(node.ctequery, context)));
|
|
2785
3082
|
}
|
|
2786
3083
|
return output.join(' ');
|
|
2787
3084
|
}
|
|
@@ -2857,7 +3154,7 @@ class Deparser {
|
|
|
2857
3154
|
DistinctExpr(node, context) {
|
|
2858
3155
|
const args = list_utils_1.ListUtils.unwrapList(node.args);
|
|
2859
3156
|
if (args.length === 2) {
|
|
2860
|
-
const literalContext =
|
|
3157
|
+
const literalContext = context.spawn('DistinctExpr', { isStringLiteral: true });
|
|
2861
3158
|
const left = this.visit(args[0], literalContext);
|
|
2862
3159
|
const right = this.visit(args[1], literalContext);
|
|
2863
3160
|
return `${left} IS DISTINCT FROM ${right}`;
|
|
@@ -2867,7 +3164,7 @@ class Deparser {
|
|
|
2867
3164
|
NullIfExpr(node, context) {
|
|
2868
3165
|
const args = list_utils_1.ListUtils.unwrapList(node.args);
|
|
2869
3166
|
if (args.length === 2) {
|
|
2870
|
-
const literalContext =
|
|
3167
|
+
const literalContext = context.spawn('NullIfExpr', { isStringLiteral: true });
|
|
2871
3168
|
const left = this.visit(args[0], literalContext);
|
|
2872
3169
|
const right = this.visit(args[1], literalContext);
|
|
2873
3170
|
return `NULLIF(${left}, ${right})`;
|
|
@@ -2946,7 +3243,7 @@ class Deparser {
|
|
|
2946
3243
|
}
|
|
2947
3244
|
RelabelType(node, context) {
|
|
2948
3245
|
if (node.arg) {
|
|
2949
|
-
const literalContext =
|
|
3246
|
+
const literalContext = context.spawn('RelabelType', { isStringLiteral: true });
|
|
2950
3247
|
return this.visit(node.arg, literalContext);
|
|
2951
3248
|
}
|
|
2952
3249
|
return '';
|
|
@@ -2965,7 +3262,7 @@ class Deparser {
|
|
|
2965
3262
|
}
|
|
2966
3263
|
ConvertRowtypeExpr(node, context) {
|
|
2967
3264
|
if (node.arg) {
|
|
2968
|
-
const literalContext =
|
|
3265
|
+
const literalContext = context.spawn('ConvertRowtypeExpr', { isStringLiteral: true });
|
|
2969
3266
|
return this.visit(node.arg, literalContext);
|
|
2970
3267
|
}
|
|
2971
3268
|
return '';
|
|
@@ -2996,10 +3293,10 @@ class Deparser {
|
|
|
2996
3293
|
}
|
|
2997
3294
|
if (node.aliases && node.aliases.length > 0) {
|
|
2998
3295
|
const aliasStrs = list_utils_1.ListUtils.unwrapList(node.aliases).map(alias => this.visit(alias, context));
|
|
2999
|
-
output.push(
|
|
3296
|
+
output.push(context.parens(aliasStrs.join(', ')));
|
|
3000
3297
|
}
|
|
3001
3298
|
if (node.options && node.options.length > 0) {
|
|
3002
|
-
const viewContext =
|
|
3299
|
+
const viewContext = context.spawn('ViewStmt');
|
|
3003
3300
|
const optionStrs = list_utils_1.ListUtils.unwrapList(node.options)
|
|
3004
3301
|
.map(option => this.visit(option, viewContext));
|
|
3005
3302
|
output.push(`WITH (${optionStrs.join(', ')})`);
|
|
@@ -3046,22 +3343,22 @@ class Deparser {
|
|
|
3046
3343
|
}
|
|
3047
3344
|
if (node.indexParams && node.indexParams.length > 0) {
|
|
3048
3345
|
const paramStrs = list_utils_1.ListUtils.unwrapList(node.indexParams).map(param => this.visit(param, context));
|
|
3049
|
-
output.push(
|
|
3346
|
+
output.push(context.parens(paramStrs.join(', ')));
|
|
3050
3347
|
}
|
|
3051
3348
|
if (node.indexIncludingParams && node.indexIncludingParams.length > 0) {
|
|
3052
3349
|
const includeStrs = list_utils_1.ListUtils.unwrapList(node.indexIncludingParams).map(param => this.visit(param, context));
|
|
3053
3350
|
output.push('INCLUDE');
|
|
3054
|
-
output.push(
|
|
3351
|
+
output.push(context.parens(includeStrs.join(', ')));
|
|
3055
3352
|
}
|
|
3056
3353
|
if (node.whereClause) {
|
|
3057
3354
|
output.push('WHERE');
|
|
3058
3355
|
output.push(this.visit(node.whereClause, context));
|
|
3059
3356
|
}
|
|
3060
3357
|
if (node.options && node.options.length > 0) {
|
|
3061
|
-
const indexContext =
|
|
3358
|
+
const indexContext = context.spawn('IndexStmt');
|
|
3062
3359
|
const optionStrs = list_utils_1.ListUtils.unwrapList(node.options).map(option => this.visit(option, indexContext));
|
|
3063
3360
|
output.push('WITH');
|
|
3064
|
-
output.push(
|
|
3361
|
+
output.push(context.parens(optionStrs.join(', ')));
|
|
3065
3362
|
}
|
|
3066
3363
|
if (node.nulls_not_distinct) {
|
|
3067
3364
|
output.push('NULLS NOT DISTINCT');
|
|
@@ -3078,7 +3375,7 @@ class Deparser {
|
|
|
3078
3375
|
output.push(quote_utils_1.QuoteUtils.quote(node.name));
|
|
3079
3376
|
}
|
|
3080
3377
|
else if (node.expr) {
|
|
3081
|
-
output.push(
|
|
3378
|
+
output.push(context.parens(this.visit(node.expr, context)));
|
|
3082
3379
|
}
|
|
3083
3380
|
if (node.collation && node.collation.length > 0) {
|
|
3084
3381
|
const collationStrs = list_utils_1.ListUtils.unwrapList(node.collation).map(coll => this.visit(coll, context));
|
|
@@ -3095,7 +3392,7 @@ class Deparser {
|
|
|
3095
3392
|
const stringData = this.getNodeData(opt.DefElem.arg);
|
|
3096
3393
|
return `${opt.DefElem.defname}='${stringData.sval}'`;
|
|
3097
3394
|
}
|
|
3098
|
-
return this.visit(opt, context);
|
|
3395
|
+
return this.visit(opt, context.spawn('IndexElem'));
|
|
3099
3396
|
});
|
|
3100
3397
|
opclassStr += `(${opclassOpts.join(', ')})`;
|
|
3101
3398
|
}
|
|
@@ -3129,7 +3426,7 @@ class Deparser {
|
|
|
3129
3426
|
output.push(quote_utils_1.QuoteUtils.quote(node.name));
|
|
3130
3427
|
}
|
|
3131
3428
|
else if (node.expr) {
|
|
3132
|
-
output.push(
|
|
3429
|
+
output.push(context.parens(this.visit(node.expr, context)));
|
|
3133
3430
|
}
|
|
3134
3431
|
if (node.collation && node.collation.length > 0) {
|
|
3135
3432
|
const collationStrs = list_utils_1.ListUtils.unwrapList(node.collation).map(coll => this.visit(coll, context));
|
|
@@ -3277,16 +3574,16 @@ class Deparser {
|
|
|
3277
3574
|
if (node.rarg && 'JoinExpr' in node.rarg && !node.rarg.JoinExpr.alias) {
|
|
3278
3575
|
rargStr = `(${rargStr})`;
|
|
3279
3576
|
}
|
|
3280
|
-
if (
|
|
3281
|
-
output.push(
|
|
3577
|
+
if (context.isPretty()) {
|
|
3578
|
+
output.push(context.newline() + joinStr + ' ' + rargStr);
|
|
3282
3579
|
}
|
|
3283
3580
|
else {
|
|
3284
3581
|
output.push(joinStr + ' ' + rargStr);
|
|
3285
3582
|
}
|
|
3286
3583
|
}
|
|
3287
3584
|
else {
|
|
3288
|
-
if (
|
|
3289
|
-
output.push(
|
|
3585
|
+
if (context.isPretty()) {
|
|
3586
|
+
output.push(context.newline() + joinStr);
|
|
3290
3587
|
}
|
|
3291
3588
|
else {
|
|
3292
3589
|
output.push(joinStr);
|
|
@@ -3295,7 +3592,7 @@ class Deparser {
|
|
|
3295
3592
|
if (node.usingClause && node.usingClause.length > 0) {
|
|
3296
3593
|
const usingList = list_utils_1.ListUtils.unwrapList(node.usingClause);
|
|
3297
3594
|
const columnNames = usingList.map(col => this.visit(col, context));
|
|
3298
|
-
if (
|
|
3595
|
+
if (context.isPretty()) {
|
|
3299
3596
|
output.push(` USING (${columnNames.join(', ')})`);
|
|
3300
3597
|
}
|
|
3301
3598
|
else {
|
|
@@ -3304,14 +3601,14 @@ class Deparser {
|
|
|
3304
3601
|
}
|
|
3305
3602
|
else if (node.quals) {
|
|
3306
3603
|
const qualsStr = this.visit(node.quals, context);
|
|
3307
|
-
if (
|
|
3604
|
+
if (context.isPretty()) {
|
|
3308
3605
|
// For complex JOIN conditions, format with proper indentation
|
|
3309
3606
|
if (qualsStr.includes('AND') || qualsStr.includes('OR') || qualsStr.length > 50) {
|
|
3310
3607
|
if (this.containsMultilineStringLiteral(qualsStr)) {
|
|
3311
3608
|
output.push(` ON ${qualsStr}`);
|
|
3312
3609
|
}
|
|
3313
3610
|
else {
|
|
3314
|
-
output.push(` ON${
|
|
3611
|
+
output.push(` ON${context.newline()}${context.indent(qualsStr)}`);
|
|
3315
3612
|
}
|
|
3316
3613
|
}
|
|
3317
3614
|
else {
|
|
@@ -3323,7 +3620,7 @@ class Deparser {
|
|
|
3323
3620
|
}
|
|
3324
3621
|
}
|
|
3325
3622
|
let result;
|
|
3326
|
-
if (
|
|
3623
|
+
if (context.isPretty()) {
|
|
3327
3624
|
result = output.join('');
|
|
3328
3625
|
}
|
|
3329
3626
|
else {
|
|
@@ -3430,8 +3727,8 @@ class Deparser {
|
|
|
3430
3727
|
else if (nodeData.sval !== undefined) {
|
|
3431
3728
|
// Handle nested sval structure: { sval: { sval: "value" } }
|
|
3432
3729
|
const svalValue = typeof nodeData.sval === 'object' ? nodeData.sval.sval : nodeData.sval;
|
|
3433
|
-
const stringValue = svalValue.replace(/'/g, '')
|
|
3434
|
-
boolValue = stringValue === 'on' || stringValue === 'true';
|
|
3730
|
+
const stringValue = svalValue.replace(/'/g, '');
|
|
3731
|
+
boolValue = stringValue.toLowerCase() === 'on' || stringValue.toLowerCase() === 'true';
|
|
3435
3732
|
}
|
|
3436
3733
|
}
|
|
3437
3734
|
return boolValue ? 'READ ONLY' : 'READ WRITE';
|
|
@@ -3454,8 +3751,8 @@ class Deparser {
|
|
|
3454
3751
|
else if (nodeData.sval !== undefined) {
|
|
3455
3752
|
// Handle nested sval structure: { sval: { sval: "value" } }
|
|
3456
3753
|
const svalValue = typeof nodeData.sval === 'object' ? nodeData.sval.sval : nodeData.sval;
|
|
3457
|
-
const stringValue = svalValue.replace(/'/g, '')
|
|
3458
|
-
boolValue = stringValue === 'on' || stringValue === 'true';
|
|
3754
|
+
const stringValue = svalValue.replace(/'/g, '');
|
|
3755
|
+
boolValue = stringValue.toLowerCase() === 'on' || stringValue.toLowerCase() === 'true';
|
|
3459
3756
|
}
|
|
3460
3757
|
}
|
|
3461
3758
|
return boolValue ? 'DEFERRABLE' : 'NOT DEFERRABLE';
|
|
@@ -3522,8 +3819,8 @@ class Deparser {
|
|
|
3522
3819
|
else if (nodeData.sval !== undefined) {
|
|
3523
3820
|
// Handle nested sval structure: { sval: { sval: "value" } }
|
|
3524
3821
|
const svalValue = typeof nodeData.sval === 'object' ? nodeData.sval.sval : nodeData.sval;
|
|
3525
|
-
const stringValue = svalValue.replace(/'/g, '')
|
|
3526
|
-
boolValue = stringValue === 'on' || stringValue === 'true';
|
|
3822
|
+
const stringValue = svalValue.replace(/'/g, '');
|
|
3823
|
+
boolValue = stringValue.toLowerCase() === 'on' || stringValue.toLowerCase() === 'true';
|
|
3527
3824
|
}
|
|
3528
3825
|
}
|
|
3529
3826
|
transactionOptions.push(boolValue ? 'READ ONLY' : 'READ WRITE');
|
|
@@ -3541,8 +3838,8 @@ class Deparser {
|
|
|
3541
3838
|
else if (nodeData.sval !== undefined) {
|
|
3542
3839
|
// Handle nested sval structure: { sval: { sval: "value" } }
|
|
3543
3840
|
const svalValue = typeof nodeData.sval === 'object' ? nodeData.sval.sval : nodeData.sval;
|
|
3544
|
-
const stringValue = svalValue.replace(/'/g, '')
|
|
3545
|
-
boolValue = stringValue === 'on' || stringValue === 'true';
|
|
3841
|
+
const stringValue = svalValue.replace(/'/g, '');
|
|
3842
|
+
boolValue = stringValue.toLowerCase() === 'on' || stringValue.toLowerCase() === 'true';
|
|
3546
3843
|
}
|
|
3547
3844
|
}
|
|
3548
3845
|
transactionOptions.push(boolValue ? 'DEFERRABLE' : 'NOT DEFERRABLE');
|
|
@@ -3608,7 +3905,7 @@ class Deparser {
|
|
|
3608
3905
|
}
|
|
3609
3906
|
switch (node.roletype) {
|
|
3610
3907
|
case 'ROLESPEC_PUBLIC':
|
|
3611
|
-
return '
|
|
3908
|
+
return 'PUBLIC';
|
|
3612
3909
|
case 'ROLESPEC_CURRENT_USER':
|
|
3613
3910
|
return 'CURRENT_USER';
|
|
3614
3911
|
case 'ROLESPEC_SESSION_USER':
|
|
@@ -3616,7 +3913,7 @@ class Deparser {
|
|
|
3616
3913
|
case 'ROLESPEC_CURRENT_ROLE':
|
|
3617
3914
|
return 'CURRENT_ROLE';
|
|
3618
3915
|
default:
|
|
3619
|
-
return '
|
|
3916
|
+
return 'PUBLIC';
|
|
3620
3917
|
}
|
|
3621
3918
|
}
|
|
3622
3919
|
roletype(node, context) {
|
|
@@ -3926,7 +4223,7 @@ class Deparser {
|
|
|
3926
4223
|
}).filter((name) => name && name.trim());
|
|
3927
4224
|
return items.join('.');
|
|
3928
4225
|
}
|
|
3929
|
-
const objContext =
|
|
4226
|
+
const objContext = context.spawn('DropStmt', { objtype: node.removeType });
|
|
3930
4227
|
const objName = this.visit(objList, objContext);
|
|
3931
4228
|
return objName;
|
|
3932
4229
|
}).filter((name) => name && name.trim()).join(', ');
|
|
@@ -4026,7 +4323,7 @@ class Deparser {
|
|
|
4026
4323
|
if (node.options && node.options.length > 0) {
|
|
4027
4324
|
output.push('WITH');
|
|
4028
4325
|
const optionsStr = list_utils_1.ListUtils.unwrapList(node.options)
|
|
4029
|
-
.map(opt => this.visit(opt, context))
|
|
4326
|
+
.map(opt => this.visit(opt, context.spawn('CopyStmt')))
|
|
4030
4327
|
.join(', ');
|
|
4031
4328
|
output.push(`(${optionsStr})`);
|
|
4032
4329
|
}
|
|
@@ -4072,18 +4369,28 @@ class Deparser {
|
|
|
4072
4369
|
if (node.missing_ok) {
|
|
4073
4370
|
output.push('IF EXISTS');
|
|
4074
4371
|
}
|
|
4075
|
-
const alterContext = node.objtype
|
|
4076
|
-
? { ...context, parentNodeTypes: [...context.parentNodeTypes, 'AlterTypeStmt'] }
|
|
4077
|
-
: context;
|
|
4372
|
+
const alterContext = context.spawn('AlterTableStmt', { objtype: node.objtype });
|
|
4078
4373
|
if (node.relation) {
|
|
4079
4374
|
const relationStr = this.RangeVar(node.relation, alterContext);
|
|
4080
4375
|
output.push(relationStr);
|
|
4081
4376
|
}
|
|
4082
4377
|
if (node.cmds && node.cmds.length > 0) {
|
|
4083
|
-
const
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4378
|
+
const commands = list_utils_1.ListUtils.unwrapList(node.cmds);
|
|
4379
|
+
if (context.isPretty()) {
|
|
4380
|
+
const commandsStr = commands
|
|
4381
|
+
.map(cmd => {
|
|
4382
|
+
const cmdStr = this.visit(cmd, alterContext);
|
|
4383
|
+
return context.newline() + context.indent(cmdStr);
|
|
4384
|
+
})
|
|
4385
|
+
.join(',');
|
|
4386
|
+
output.push(commandsStr);
|
|
4387
|
+
}
|
|
4388
|
+
else {
|
|
4389
|
+
const commandsStr = commands
|
|
4390
|
+
.map(cmd => this.visit(cmd, alterContext))
|
|
4391
|
+
.join(', ');
|
|
4392
|
+
output.push(commandsStr);
|
|
4393
|
+
}
|
|
4087
4394
|
}
|
|
4088
4395
|
return output.join(' ');
|
|
4089
4396
|
}
|
|
@@ -4092,7 +4399,7 @@ class Deparser {
|
|
|
4092
4399
|
if (node.subtype) {
|
|
4093
4400
|
switch (node.subtype) {
|
|
4094
4401
|
case 'AT_AddColumn':
|
|
4095
|
-
if (context.
|
|
4402
|
+
if (context.objtype === 'OBJECT_TYPE') {
|
|
4096
4403
|
output.push('ADD ATTRIBUTE');
|
|
4097
4404
|
}
|
|
4098
4405
|
else {
|
|
@@ -4103,35 +4410,99 @@ class Deparser {
|
|
|
4103
4410
|
}
|
|
4104
4411
|
if (node.def) {
|
|
4105
4412
|
const colDefData = this.getNodeData(node.def);
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
const
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4413
|
+
if (context.isPretty()) {
|
|
4414
|
+
const parts = [];
|
|
4415
|
+
const indentedParts = [];
|
|
4416
|
+
if (colDefData.colname) {
|
|
4417
|
+
parts.push(quote_utils_1.QuoteUtils.quote(colDefData.colname));
|
|
4418
|
+
}
|
|
4419
|
+
if (colDefData.typeName) {
|
|
4420
|
+
parts.push(this.TypeName(colDefData.typeName, context));
|
|
4421
|
+
}
|
|
4422
|
+
if (colDefData.is_not_null) {
|
|
4423
|
+
indentedParts.push('NOT NULL');
|
|
4424
|
+
}
|
|
4425
|
+
if (colDefData.collClause) {
|
|
4426
|
+
indentedParts.push(this.CollateClause(colDefData.collClause, context));
|
|
4427
|
+
}
|
|
4428
|
+
if (colDefData.constraints) {
|
|
4429
|
+
const constraints = list_utils_1.ListUtils.unwrapList(colDefData.constraints);
|
|
4430
|
+
constraints.forEach(constraint => {
|
|
4431
|
+
const columnConstraintContext = context.spawn('ColumnDef', { isColumnConstraint: true });
|
|
4432
|
+
const constraintStr = this.visit(constraint, columnConstraintContext);
|
|
4433
|
+
if (constraintStr.includes('REFERENCES') && constraintStr.includes('ON DELETE')) {
|
|
4434
|
+
const refMatch = constraintStr.match(/^(.*REFERENCES[^)]*\([^)]*\))\s*(ON\s+DELETE\s+CASCADE.*)$/);
|
|
4435
|
+
if (refMatch) {
|
|
4436
|
+
indentedParts.push(refMatch[1]);
|
|
4437
|
+
indentedParts.push(refMatch[2]);
|
|
4438
|
+
}
|
|
4439
|
+
else {
|
|
4440
|
+
indentedParts.push(constraintStr);
|
|
4441
|
+
}
|
|
4442
|
+
}
|
|
4443
|
+
else if (constraintStr === 'UNIQUE' && colDefData.raw_default) {
|
|
4444
|
+
const defaultStr = 'DEFAULT ' + this.visit(colDefData.raw_default, context);
|
|
4445
|
+
indentedParts.push('UNIQUE ' + defaultStr);
|
|
4446
|
+
}
|
|
4447
|
+
else {
|
|
4448
|
+
indentedParts.push(constraintStr);
|
|
4449
|
+
}
|
|
4450
|
+
});
|
|
4451
|
+
}
|
|
4452
|
+
if (colDefData.raw_default && !colDefData.constraints?.some((c) => {
|
|
4453
|
+
const constraintStr = this.visit(c, context.spawn('ColumnDef', { isColumnConstraint: true }));
|
|
4454
|
+
return constraintStr === 'UNIQUE';
|
|
4455
|
+
})) {
|
|
4456
|
+
const defaultStr = 'DEFAULT ' + this.visit(colDefData.raw_default, context);
|
|
4457
|
+
indentedParts.push(defaultStr);
|
|
4458
|
+
}
|
|
4459
|
+
if (colDefData.fdwoptions && colDefData.fdwoptions.length > 0) {
|
|
4460
|
+
indentedParts.push('OPTIONS');
|
|
4461
|
+
const columnContext = context.spawn('ColumnDef');
|
|
4462
|
+
const options = list_utils_1.ListUtils.unwrapList(colDefData.fdwoptions).map(opt => this.visit(opt, columnContext));
|
|
4463
|
+
indentedParts.push(`(${options.join(', ')})`);
|
|
4464
|
+
}
|
|
4465
|
+
let result = parts.join(' ');
|
|
4466
|
+
if (indentedParts.length > 0) {
|
|
4467
|
+
const indentedStr = indentedParts.map(part => context.indent(part)).join(context.newline());
|
|
4468
|
+
result += context.newline() + indentedStr;
|
|
4469
|
+
}
|
|
4470
|
+
output.push(result);
|
|
4130
4471
|
}
|
|
4131
|
-
|
|
4132
|
-
parts
|
|
4472
|
+
else {
|
|
4473
|
+
const parts = [];
|
|
4474
|
+
if (colDefData.colname) {
|
|
4475
|
+
parts.push(quote_utils_1.QuoteUtils.quote(colDefData.colname));
|
|
4476
|
+
}
|
|
4477
|
+
if (colDefData.typeName) {
|
|
4478
|
+
parts.push(this.TypeName(colDefData.typeName, context));
|
|
4479
|
+
}
|
|
4480
|
+
if (colDefData.collClause) {
|
|
4481
|
+
parts.push(this.CollateClause(colDefData.collClause, context));
|
|
4482
|
+
}
|
|
4483
|
+
if (colDefData.fdwoptions && colDefData.fdwoptions.length > 0) {
|
|
4484
|
+
parts.push('OPTIONS');
|
|
4485
|
+
const columnContext = context.spawn('ColumnDef');
|
|
4486
|
+
const options = list_utils_1.ListUtils.unwrapList(colDefData.fdwoptions).map(opt => this.visit(opt, columnContext));
|
|
4487
|
+
parts.push(`(${options.join(', ')})`);
|
|
4488
|
+
}
|
|
4489
|
+
if (colDefData.constraints) {
|
|
4490
|
+
const constraints = list_utils_1.ListUtils.unwrapList(colDefData.constraints);
|
|
4491
|
+
const constraintStrs = constraints.map(constraint => {
|
|
4492
|
+
const columnConstraintContext = context.spawn('ColumnDef', { isColumnConstraint: true });
|
|
4493
|
+
return this.visit(constraint, columnConstraintContext);
|
|
4494
|
+
});
|
|
4495
|
+
parts.push(...constraintStrs);
|
|
4496
|
+
}
|
|
4497
|
+
if (colDefData.raw_default) {
|
|
4498
|
+
parts.push('DEFAULT');
|
|
4499
|
+
parts.push(this.visit(colDefData.raw_default, context));
|
|
4500
|
+
}
|
|
4501
|
+
if (colDefData.is_not_null) {
|
|
4502
|
+
parts.push('NOT NULL');
|
|
4503
|
+
}
|
|
4504
|
+
output.push(parts.join(' '));
|
|
4133
4505
|
}
|
|
4134
|
-
output.push(parts.join(' '));
|
|
4135
4506
|
}
|
|
4136
4507
|
if (node.behavior === 'DROP_CASCADE') {
|
|
4137
4508
|
output.push('CASCADE');
|
|
@@ -4139,7 +4510,7 @@ class Deparser {
|
|
|
4139
4510
|
break;
|
|
4140
4511
|
case 'AT_DropColumn':
|
|
4141
4512
|
if (node.missing_ok) {
|
|
4142
|
-
if (context.
|
|
4513
|
+
if (context.objtype === 'OBJECT_TYPE') {
|
|
4143
4514
|
output.push('DROP ATTRIBUTE IF EXISTS');
|
|
4144
4515
|
}
|
|
4145
4516
|
else {
|
|
@@ -4147,7 +4518,7 @@ class Deparser {
|
|
|
4147
4518
|
}
|
|
4148
4519
|
}
|
|
4149
4520
|
else {
|
|
4150
|
-
if (context.
|
|
4521
|
+
if (context.objtype === 'OBJECT_TYPE') {
|
|
4151
4522
|
output.push('DROP ATTRIBUTE');
|
|
4152
4523
|
}
|
|
4153
4524
|
else {
|
|
@@ -4165,7 +4536,7 @@ class Deparser {
|
|
|
4165
4536
|
}
|
|
4166
4537
|
break;
|
|
4167
4538
|
case 'AT_AlterColumnType':
|
|
4168
|
-
if (context.
|
|
4539
|
+
if (context.objtype === 'OBJECT_TYPE') {
|
|
4169
4540
|
output.push('ALTER ATTRIBUTE');
|
|
4170
4541
|
}
|
|
4171
4542
|
else {
|
|
@@ -4229,7 +4600,7 @@ class Deparser {
|
|
|
4229
4600
|
case 'AT_SetRelOptions':
|
|
4230
4601
|
output.push('SET');
|
|
4231
4602
|
if (node.def) {
|
|
4232
|
-
const alterTableContext =
|
|
4603
|
+
const alterTableContext = context.spawn('AlterTableCmd', { subtype: 'AT_SetRelOptions' });
|
|
4233
4604
|
const options = list_utils_1.ListUtils.unwrapList(node.def)
|
|
4234
4605
|
.map(option => this.visit(option, alterTableContext))
|
|
4235
4606
|
.join(', ');
|
|
@@ -4242,7 +4613,7 @@ class Deparser {
|
|
|
4242
4613
|
case 'AT_ResetRelOptions':
|
|
4243
4614
|
output.push('RESET');
|
|
4244
4615
|
if (node.def) {
|
|
4245
|
-
const alterTableContext =
|
|
4616
|
+
const alterTableContext = context.spawn('AlterTableCmd', { subtype: 'AT_ResetRelOptions' });
|
|
4246
4617
|
const options = list_utils_1.ListUtils.unwrapList(node.def)
|
|
4247
4618
|
.map(option => this.visit(option, alterTableContext))
|
|
4248
4619
|
.join(', ');
|
|
@@ -4337,7 +4708,7 @@ class Deparser {
|
|
|
4337
4708
|
}
|
|
4338
4709
|
output.push('SET');
|
|
4339
4710
|
if (node.def) {
|
|
4340
|
-
const alterTableContext =
|
|
4711
|
+
const alterTableContext = context.spawn('AlterTableCmd', { subtype: 'AT_SetOptions' });
|
|
4341
4712
|
const options = list_utils_1.ListUtils.unwrapList(node.def)
|
|
4342
4713
|
.map(option => this.visit(option, alterTableContext))
|
|
4343
4714
|
.join(', ');
|
|
@@ -4354,7 +4725,7 @@ class Deparser {
|
|
|
4354
4725
|
}
|
|
4355
4726
|
output.push('RESET');
|
|
4356
4727
|
if (node.def) {
|
|
4357
|
-
const alterTableContext =
|
|
4728
|
+
const alterTableContext = context.spawn('AlterTableCmd', { subtype: 'AT_ResetOptions' });
|
|
4358
4729
|
const options = list_utils_1.ListUtils.unwrapList(node.def)
|
|
4359
4730
|
.map(option => this.visit(option, alterTableContext))
|
|
4360
4731
|
.join(', ');
|
|
@@ -4595,7 +4966,7 @@ class Deparser {
|
|
|
4595
4966
|
}
|
|
4596
4967
|
output.push('OPTIONS');
|
|
4597
4968
|
if (node.def) {
|
|
4598
|
-
const alterColumnContext =
|
|
4969
|
+
const alterColumnContext = context.spawn('AlterTableCmd', { alterColumnOptions: true });
|
|
4599
4970
|
const options = list_utils_1.ListUtils.unwrapList(node.def)
|
|
4600
4971
|
.map(option => this.visit(option, alterColumnContext))
|
|
4601
4972
|
.join(', ');
|
|
@@ -4635,7 +5006,7 @@ class Deparser {
|
|
|
4635
5006
|
case 'AT_GenericOptions':
|
|
4636
5007
|
output.push('OPTIONS');
|
|
4637
5008
|
if (node.def) {
|
|
4638
|
-
const alterTableContext =
|
|
5009
|
+
const alterTableContext = context.spawn('AlterTableCmd', { alterTableOptions: true });
|
|
4639
5010
|
const options = list_utils_1.ListUtils.unwrapList(node.def)
|
|
4640
5011
|
.map(option => this.visit(option, alterTableContext))
|
|
4641
5012
|
.join(', ');
|
|
@@ -4647,11 +5018,10 @@ class Deparser {
|
|
|
4647
5018
|
if (node.name) {
|
|
4648
5019
|
output.push(quote_utils_1.QuoteUtils.quote(node.name));
|
|
4649
5020
|
}
|
|
4650
|
-
output.push('ADD
|
|
5021
|
+
output.push('ADD');
|
|
4651
5022
|
if (node.def) {
|
|
4652
5023
|
output.push(this.visit(node.def, context));
|
|
4653
5024
|
}
|
|
4654
|
-
output.push('AS IDENTITY');
|
|
4655
5025
|
break;
|
|
4656
5026
|
case 'AT_SetIdentity':
|
|
4657
5027
|
output.push('ALTER COLUMN');
|
|
@@ -4739,7 +5109,7 @@ class Deparser {
|
|
|
4739
5109
|
output.push(this.TypeName(node.returnType, context));
|
|
4740
5110
|
}
|
|
4741
5111
|
if (node.options && node.options.length > 0) {
|
|
4742
|
-
const funcContext =
|
|
5112
|
+
const funcContext = context.spawn('CreateFunctionStmt');
|
|
4743
5113
|
const options = node.options.map((opt) => this.visit(opt, funcContext));
|
|
4744
5114
|
output.push(...options);
|
|
4745
5115
|
}
|
|
@@ -4826,7 +5196,7 @@ class Deparser {
|
|
|
4826
5196
|
}
|
|
4827
5197
|
output.push('AS', 'ENUM');
|
|
4828
5198
|
if (node.vals && node.vals.length > 0) {
|
|
4829
|
-
const enumContext =
|
|
5199
|
+
const enumContext = context.spawn('CreateEnumStmt', { isEnumValue: true });
|
|
4830
5200
|
const values = list_utils_1.ListUtils.unwrapList(node.vals)
|
|
4831
5201
|
.map(val => this.visit(val, enumContext))
|
|
4832
5202
|
.join(', ');
|
|
@@ -4881,9 +5251,8 @@ class Deparser {
|
|
|
4881
5251
|
output.push(roleName);
|
|
4882
5252
|
}
|
|
4883
5253
|
if (node.options) {
|
|
4884
|
-
const roleContext = { ...context, parentNodeTypes: [...context.parentNodeTypes, 'CreateRoleStmt'] };
|
|
4885
5254
|
const options = list_utils_1.ListUtils.unwrapList(node.options)
|
|
4886
|
-
.map(option => this.visit(option,
|
|
5255
|
+
.map(option => this.visit(option, context.spawn('CreateRoleStmt')))
|
|
4887
5256
|
.join(' ');
|
|
4888
5257
|
if (options) {
|
|
4889
5258
|
output.push('WITH');
|
|
@@ -4914,7 +5283,7 @@ class Deparser {
|
|
|
4914
5283
|
const stringData = this.getNodeData(node.arg);
|
|
4915
5284
|
return `${node.defname}='${stringData.sval}'`;
|
|
4916
5285
|
}
|
|
4917
|
-
return `${node.defname}=${this.visit(node.arg,
|
|
5286
|
+
return `${node.defname}=${this.visit(node.arg, context.spawn('DefElem'))}`;
|
|
4918
5287
|
}
|
|
4919
5288
|
// Handle CREATE OPERATOR boolean flags - MUST be first to preserve case
|
|
4920
5289
|
if (context.parentNodeTypes.includes('DefineStmt') &&
|
|
@@ -4930,13 +5299,13 @@ class Deparser {
|
|
|
4930
5299
|
if (!node.arg) {
|
|
4931
5300
|
return `NO ${node.defname.toUpperCase()}`;
|
|
4932
5301
|
}
|
|
4933
|
-
const defElemContext =
|
|
5302
|
+
const defElemContext = context.spawn('DefElem');
|
|
4934
5303
|
const argValue = this.visit(node.arg, defElemContext);
|
|
4935
5304
|
return `${node.defname.toUpperCase()} ${argValue}`;
|
|
4936
5305
|
}
|
|
4937
5306
|
// Handle OPTIONS clause - use space format, not equals format
|
|
4938
5307
|
if (node.arg) {
|
|
4939
|
-
const defElemContext =
|
|
5308
|
+
const defElemContext = context.spawn('DefElem');
|
|
4940
5309
|
const argValue = this.visit(node.arg, defElemContext);
|
|
4941
5310
|
if (context.parentNodeTypes.includes('CreateFdwStmt') || context.parentNodeTypes.includes('AlterFdwStmt')) {
|
|
4942
5311
|
const finalValue = typeof argValue === 'string' && !argValue.startsWith("'")
|
|
@@ -4990,7 +5359,7 @@ class Deparser {
|
|
|
4990
5359
|
if (!node.arg) {
|
|
4991
5360
|
return 'PASSWORD NULL';
|
|
4992
5361
|
}
|
|
4993
|
-
const defElemContext =
|
|
5362
|
+
const defElemContext = context.spawn('DefElem');
|
|
4994
5363
|
const argValue = this.visit(node.arg, defElemContext);
|
|
4995
5364
|
const quotedValue = typeof argValue === 'string' && !argValue.startsWith("'")
|
|
4996
5365
|
? `'${argValue}'`
|
|
@@ -4999,7 +5368,7 @@ class Deparser {
|
|
|
4999
5368
|
}
|
|
5000
5369
|
}
|
|
5001
5370
|
if (node.arg) {
|
|
5002
|
-
const defElemContext =
|
|
5371
|
+
const defElemContext = context.spawn('DefElem');
|
|
5003
5372
|
const argValue = this.visit(node.arg, defElemContext);
|
|
5004
5373
|
if (context.parentNodeTypes.includes('AlterOperatorStmt')) {
|
|
5005
5374
|
if (node.arg && this.getNodeType(node.arg) === 'TypeName') {
|
|
@@ -5075,7 +5444,7 @@ class Deparser {
|
|
|
5075
5444
|
if (node.defname === 'sysid') {
|
|
5076
5445
|
return `SYSID ${argValue}`;
|
|
5077
5446
|
}
|
|
5078
|
-
if (argValue === 'true') {
|
|
5447
|
+
if (String(argValue) === 'true') {
|
|
5079
5448
|
// Handle special cases where the positive form has a different name
|
|
5080
5449
|
if (node.defname === 'isreplication') {
|
|
5081
5450
|
return 'REPLICATION';
|
|
@@ -5085,7 +5454,7 @@ class Deparser {
|
|
|
5085
5454
|
}
|
|
5086
5455
|
return node.defname.toUpperCase();
|
|
5087
5456
|
}
|
|
5088
|
-
else if (argValue === 'false') {
|
|
5457
|
+
else if (String(argValue) === 'false') {
|
|
5089
5458
|
// Handle special cases where the negative form has a different name
|
|
5090
5459
|
if (node.defname === 'canlogin') {
|
|
5091
5460
|
return 'NOLOGIN';
|
|
@@ -5149,7 +5518,7 @@ class Deparser {
|
|
|
5149
5518
|
}
|
|
5150
5519
|
if (context.parentNodeTypes.includes('DoStmt')) {
|
|
5151
5520
|
if (node.defname === 'as') {
|
|
5152
|
-
const defElemContext =
|
|
5521
|
+
const defElemContext = context.spawn('DefElem');
|
|
5153
5522
|
const argValue = node.arg ? this.visit(node.arg, defElemContext) : '';
|
|
5154
5523
|
if (Array.isArray(argValue)) {
|
|
5155
5524
|
const bodyParts = argValue;
|
|
@@ -5440,7 +5809,7 @@ class Deparser {
|
|
|
5440
5809
|
}
|
|
5441
5810
|
if (node.options && node.options.length > 0) {
|
|
5442
5811
|
output.push('WITH');
|
|
5443
|
-
const tsContext =
|
|
5812
|
+
const tsContext = context.spawn('CreateTableSpaceStmt');
|
|
5444
5813
|
const options = list_utils_1.ListUtils.unwrapList(node.options)
|
|
5445
5814
|
.map(option => this.visit(option, tsContext))
|
|
5446
5815
|
.join(', ');
|
|
@@ -5470,7 +5839,7 @@ class Deparser {
|
|
|
5470
5839
|
output.push('SET');
|
|
5471
5840
|
}
|
|
5472
5841
|
if (node.options && node.options.length > 0) {
|
|
5473
|
-
const tablespaceContext =
|
|
5842
|
+
const tablespaceContext = context.spawn('AlterTableSpaceOptionsStmt');
|
|
5474
5843
|
const options = list_utils_1.ListUtils.unwrapList(node.options)
|
|
5475
5844
|
.map(option => this.visit(option, tablespaceContext))
|
|
5476
5845
|
.join(', ');
|
|
@@ -5487,7 +5856,7 @@ class Deparser {
|
|
|
5487
5856
|
output.push(this.quoteIfNeeded(node.extname));
|
|
5488
5857
|
}
|
|
5489
5858
|
if (node.options && node.options.length > 0) {
|
|
5490
|
-
const extContext =
|
|
5859
|
+
const extContext = context.spawn('CreateExtensionStmt');
|
|
5491
5860
|
const options = list_utils_1.ListUtils.unwrapList(node.options)
|
|
5492
5861
|
.map(option => this.visit(option, extContext))
|
|
5493
5862
|
.join(' ');
|
|
@@ -5501,7 +5870,7 @@ class Deparser {
|
|
|
5501
5870
|
output.push(this.quoteIfNeeded(node.extname));
|
|
5502
5871
|
}
|
|
5503
5872
|
if (node.options && node.options.length > 0) {
|
|
5504
|
-
const extContext =
|
|
5873
|
+
const extContext = context.spawn('AlterExtensionStmt');
|
|
5505
5874
|
const options = list_utils_1.ListUtils.unwrapList(node.options)
|
|
5506
5875
|
.map(option => this.visit(option, extContext))
|
|
5507
5876
|
.join(' ');
|
|
@@ -5515,7 +5884,7 @@ class Deparser {
|
|
|
5515
5884
|
output.push(node.fdwname);
|
|
5516
5885
|
}
|
|
5517
5886
|
if (node.func_options && node.func_options.length > 0) {
|
|
5518
|
-
const fdwContext =
|
|
5887
|
+
const fdwContext = context.spawn('CreateFdwStmt');
|
|
5519
5888
|
const funcOptions = list_utils_1.ListUtils.unwrapList(node.func_options)
|
|
5520
5889
|
.map(option => this.visit(option, fdwContext))
|
|
5521
5890
|
.join(' ');
|
|
@@ -5523,7 +5892,7 @@ class Deparser {
|
|
|
5523
5892
|
}
|
|
5524
5893
|
if (node.options && node.options.length > 0) {
|
|
5525
5894
|
output.push('OPTIONS');
|
|
5526
|
-
const fdwContext =
|
|
5895
|
+
const fdwContext = context.spawn('CreateFdwStmt');
|
|
5527
5896
|
const options = list_utils_1.ListUtils.unwrapList(node.options)
|
|
5528
5897
|
.map(option => this.visit(option, fdwContext))
|
|
5529
5898
|
.join(', ');
|
|
@@ -5625,7 +5994,7 @@ class Deparser {
|
|
|
5625
5994
|
output.push('ADD');
|
|
5626
5995
|
if (node.def) {
|
|
5627
5996
|
// Pass domain context to avoid adding constraint names for domain constraints
|
|
5628
|
-
const domainContext =
|
|
5997
|
+
const domainContext = context.spawn('CreateDomainStmt', { isDomainConstraint: true });
|
|
5629
5998
|
output.push(this.visit(node.def, domainContext));
|
|
5630
5999
|
}
|
|
5631
6000
|
break;
|
|
@@ -5651,7 +6020,7 @@ class Deparser {
|
|
|
5651
6020
|
output.push('ADD');
|
|
5652
6021
|
if (node.def) {
|
|
5653
6022
|
// Pass domain context to avoid adding constraint names for domain constraints
|
|
5654
|
-
const domainContext =
|
|
6023
|
+
const domainContext = context.spawn('CreateDomainStmt', { isDomainConstraint: true });
|
|
5655
6024
|
output.push(this.visit(node.def, domainContext));
|
|
5656
6025
|
}
|
|
5657
6026
|
break;
|
|
@@ -6013,7 +6382,7 @@ class Deparser {
|
|
|
6013
6382
|
output.push(`${operatorName}(${args.join(', ')})`);
|
|
6014
6383
|
}
|
|
6015
6384
|
else {
|
|
6016
|
-
const objContext =
|
|
6385
|
+
const objContext = context.spawn('CommentStmt', { objtype: node.objtype });
|
|
6017
6386
|
output.push(this.visit(node.object, objContext));
|
|
6018
6387
|
}
|
|
6019
6388
|
}
|
|
@@ -6059,13 +6428,13 @@ class Deparser {
|
|
|
6059
6428
|
const output = [];
|
|
6060
6429
|
const initialParts = ['CREATE', 'POLICY'];
|
|
6061
6430
|
if (node.policy_name) {
|
|
6062
|
-
initialParts.push(
|
|
6431
|
+
initialParts.push(quote_utils_1.QuoteUtils.quote(node.policy_name));
|
|
6063
6432
|
}
|
|
6064
6433
|
output.push(initialParts.join(' '));
|
|
6065
6434
|
// Add ON clause on new line in pretty mode
|
|
6066
6435
|
if (node.table) {
|
|
6067
|
-
if (
|
|
6068
|
-
output.push(
|
|
6436
|
+
if (context.isPretty()) {
|
|
6437
|
+
output.push(context.newline() + context.indent(`ON ${this.RangeVar(node.table, context)}`));
|
|
6069
6438
|
}
|
|
6070
6439
|
else {
|
|
6071
6440
|
output.push('ON');
|
|
@@ -6074,24 +6443,24 @@ class Deparser {
|
|
|
6074
6443
|
}
|
|
6075
6444
|
// Handle AS RESTRICTIVE/PERMISSIVE clause
|
|
6076
6445
|
if (node.permissive === undefined) {
|
|
6077
|
-
if (
|
|
6078
|
-
output.push(
|
|
6446
|
+
if (context.isPretty()) {
|
|
6447
|
+
output.push(context.newline() + context.indent('AS RESTRICTIVE'));
|
|
6079
6448
|
}
|
|
6080
6449
|
else {
|
|
6081
6450
|
output.push('AS', 'RESTRICTIVE');
|
|
6082
6451
|
}
|
|
6083
6452
|
}
|
|
6084
6453
|
else if (node.permissive === true) {
|
|
6085
|
-
if (
|
|
6086
|
-
output.push(
|
|
6454
|
+
if (context.isPretty()) {
|
|
6455
|
+
output.push(context.newline() + context.indent('AS PERMISSIVE'));
|
|
6087
6456
|
}
|
|
6088
6457
|
else {
|
|
6089
6458
|
output.push('AS', 'PERMISSIVE');
|
|
6090
6459
|
}
|
|
6091
6460
|
}
|
|
6092
6461
|
if (node.cmd_name) {
|
|
6093
|
-
if (
|
|
6094
|
-
output.push(
|
|
6462
|
+
if (context.isPretty()) {
|
|
6463
|
+
output.push(context.newline() + context.indent(`FOR ${node.cmd_name.toUpperCase()}`));
|
|
6095
6464
|
}
|
|
6096
6465
|
else {
|
|
6097
6466
|
output.push('FOR', node.cmd_name.toUpperCase());
|
|
@@ -6099,8 +6468,8 @@ class Deparser {
|
|
|
6099
6468
|
}
|
|
6100
6469
|
if (node.roles && node.roles.length > 0) {
|
|
6101
6470
|
const roles = list_utils_1.ListUtils.unwrapList(node.roles).map(role => this.visit(role, context));
|
|
6102
|
-
if (
|
|
6103
|
-
output.push(
|
|
6471
|
+
if (context.isPretty()) {
|
|
6472
|
+
output.push(context.newline() + context.indent(`TO ${roles.join(', ')}`));
|
|
6104
6473
|
}
|
|
6105
6474
|
else {
|
|
6106
6475
|
output.push('TO');
|
|
@@ -6108,11 +6477,11 @@ class Deparser {
|
|
|
6108
6477
|
}
|
|
6109
6478
|
}
|
|
6110
6479
|
if (node.qual) {
|
|
6111
|
-
if (
|
|
6480
|
+
if (context.isPretty()) {
|
|
6112
6481
|
const qualExpr = this.visit(node.qual, context);
|
|
6113
|
-
output.push(
|
|
6114
|
-
output.push(
|
|
6115
|
-
output.push(
|
|
6482
|
+
output.push(context.newline() + context.indent('USING ('));
|
|
6483
|
+
output.push(context.newline() + context.indent(context.indent(qualExpr)));
|
|
6484
|
+
output.push(context.newline() + context.indent(')'));
|
|
6116
6485
|
}
|
|
6117
6486
|
else {
|
|
6118
6487
|
output.push('USING');
|
|
@@ -6120,23 +6489,23 @@ class Deparser {
|
|
|
6120
6489
|
}
|
|
6121
6490
|
}
|
|
6122
6491
|
if (node.with_check) {
|
|
6123
|
-
if (
|
|
6492
|
+
if (context.isPretty()) {
|
|
6124
6493
|
const checkExpr = this.visit(node.with_check, context);
|
|
6125
|
-
output.push(
|
|
6126
|
-
output.push(
|
|
6127
|
-
output.push(
|
|
6494
|
+
output.push(context.newline() + context.indent('WITH CHECK ('));
|
|
6495
|
+
output.push(context.newline() + context.indent(context.indent(checkExpr)));
|
|
6496
|
+
output.push(context.newline() + context.indent(')'));
|
|
6128
6497
|
}
|
|
6129
6498
|
else {
|
|
6130
6499
|
output.push('WITH CHECK');
|
|
6131
6500
|
output.push(`(${this.visit(node.with_check, context)})`);
|
|
6132
6501
|
}
|
|
6133
6502
|
}
|
|
6134
|
-
return
|
|
6503
|
+
return context.isPretty() ? output.join('') : output.join(' ');
|
|
6135
6504
|
}
|
|
6136
6505
|
AlterPolicyStmt(node, context) {
|
|
6137
6506
|
const output = ['ALTER', 'POLICY'];
|
|
6138
6507
|
if (node.policy_name) {
|
|
6139
|
-
output.push(
|
|
6508
|
+
output.push(quote_utils_1.QuoteUtils.quote(node.policy_name));
|
|
6140
6509
|
}
|
|
6141
6510
|
if (node.table) {
|
|
6142
6511
|
output.push('ON');
|
|
@@ -6176,7 +6545,7 @@ class Deparser {
|
|
|
6176
6545
|
}
|
|
6177
6546
|
if (node.options && node.options.length > 0) {
|
|
6178
6547
|
output.push('OPTIONS');
|
|
6179
|
-
const userMappingContext =
|
|
6548
|
+
const userMappingContext = context.spawn('CreateUserMappingStmt');
|
|
6180
6549
|
const options = list_utils_1.ListUtils.unwrapList(node.options).map(opt => this.visit(opt, userMappingContext));
|
|
6181
6550
|
output.push(`(${options.join(', ')})`);
|
|
6182
6551
|
}
|
|
@@ -6359,7 +6728,7 @@ class Deparser {
|
|
|
6359
6728
|
DoStmt(node, context) {
|
|
6360
6729
|
const output = ['DO'];
|
|
6361
6730
|
if (node.args && node.args.length > 0) {
|
|
6362
|
-
const doContext =
|
|
6731
|
+
const doContext = context.spawn('DoStmt');
|
|
6363
6732
|
const args = list_utils_1.ListUtils.unwrapList(node.args);
|
|
6364
6733
|
const processedArgs = [];
|
|
6365
6734
|
for (const arg of args) {
|
|
@@ -6664,7 +7033,7 @@ class Deparser {
|
|
|
6664
7033
|
ObjectWithArgs(node, context) {
|
|
6665
7034
|
let result = '';
|
|
6666
7035
|
if (node.objname && node.objname.length > 0) {
|
|
6667
|
-
const objContext =
|
|
7036
|
+
const objContext = context.spawn('ObjectWithArgs');
|
|
6668
7037
|
const names = list_utils_1.ListUtils.unwrapList(node.objname).map(name => this.visit(name, objContext));
|
|
6669
7038
|
result = names.join('.');
|
|
6670
7039
|
}
|
|
@@ -6706,7 +7075,7 @@ class Deparser {
|
|
|
6706
7075
|
}
|
|
6707
7076
|
output.push('SET');
|
|
6708
7077
|
if (node.options && node.options.length > 0) {
|
|
6709
|
-
const alterOpContext =
|
|
7078
|
+
const alterOpContext = context.spawn('AlterOperatorStmt');
|
|
6710
7079
|
const options = list_utils_1.ListUtils.unwrapList(node.options).map(opt => this.visit(opt, alterOpContext));
|
|
6711
7080
|
output.push(`(${options.join(', ')})`);
|
|
6712
7081
|
}
|
|
@@ -6718,13 +7087,13 @@ class Deparser {
|
|
|
6718
7087
|
output.push(quote_utils_1.QuoteUtils.quote(node.fdwname));
|
|
6719
7088
|
}
|
|
6720
7089
|
if (node.func_options && node.func_options.length > 0) {
|
|
6721
|
-
const fdwContext =
|
|
7090
|
+
const fdwContext = context.spawn('AlterFdwStmt');
|
|
6722
7091
|
const funcOptions = list_utils_1.ListUtils.unwrapList(node.func_options).map(opt => this.visit(opt, fdwContext));
|
|
6723
7092
|
output.push(funcOptions.join(' '));
|
|
6724
7093
|
}
|
|
6725
7094
|
if (node.options && node.options.length > 0) {
|
|
6726
7095
|
output.push('OPTIONS');
|
|
6727
|
-
const fdwContext =
|
|
7096
|
+
const fdwContext = context.spawn('AlterFdwStmt');
|
|
6728
7097
|
const options = list_utils_1.ListUtils.unwrapList(node.options).map(opt => this.visit(opt, fdwContext));
|
|
6729
7098
|
output.push(`(${options.join(', ')})`);
|
|
6730
7099
|
}
|
|
@@ -6750,7 +7119,7 @@ class Deparser {
|
|
|
6750
7119
|
if (node.options && node.options.length > 0) {
|
|
6751
7120
|
output.push('OPTIONS');
|
|
6752
7121
|
output.push('(');
|
|
6753
|
-
const optionsContext =
|
|
7122
|
+
const optionsContext = context.spawn('CreateForeignServerStmt');
|
|
6754
7123
|
const options = list_utils_1.ListUtils.unwrapList(node.options).map(opt => this.visit(opt, optionsContext));
|
|
6755
7124
|
output.push(options.join(', '));
|
|
6756
7125
|
output.push(')');
|
|
@@ -6768,7 +7137,7 @@ class Deparser {
|
|
|
6768
7137
|
if (node.options && node.options.length > 0) {
|
|
6769
7138
|
output.push('OPTIONS');
|
|
6770
7139
|
output.push('(');
|
|
6771
|
-
const optionsContext =
|
|
7140
|
+
const optionsContext = context.spawn('AlterForeignServerStmt');
|
|
6772
7141
|
const options = list_utils_1.ListUtils.unwrapList(node.options).map(opt => this.visit(opt, optionsContext));
|
|
6773
7142
|
output.push(options.join(', '));
|
|
6774
7143
|
output.push(')');
|
|
@@ -6789,7 +7158,7 @@ class Deparser {
|
|
|
6789
7158
|
}
|
|
6790
7159
|
if (node.options && node.options.length > 0) {
|
|
6791
7160
|
output.push('OPTIONS');
|
|
6792
|
-
const userMappingContext =
|
|
7161
|
+
const userMappingContext = context.spawn('AlterUserMappingStmt');
|
|
6793
7162
|
const options = list_utils_1.ListUtils.unwrapList(node.options).map(opt => this.visit(opt, userMappingContext));
|
|
6794
7163
|
output.push(`(${options.join(', ')})`);
|
|
6795
7164
|
}
|
|
@@ -6849,7 +7218,7 @@ class Deparser {
|
|
|
6849
7218
|
output.push(quote_utils_1.QuoteUtils.quote(node.local_schema));
|
|
6850
7219
|
}
|
|
6851
7220
|
if (node.options && node.options.length > 0) {
|
|
6852
|
-
const importSchemaContext =
|
|
7221
|
+
const importSchemaContext = context.spawn('ImportForeignSchemaStmt');
|
|
6853
7222
|
const options = list_utils_1.ListUtils.unwrapList(node.options).map(opt => this.visit(opt, importSchemaContext));
|
|
6854
7223
|
output.push(`OPTIONS (${options.join(', ')})`);
|
|
6855
7224
|
}
|
|
@@ -6884,7 +7253,7 @@ class Deparser {
|
|
|
6884
7253
|
ExplainStmt(node, context) {
|
|
6885
7254
|
const output = ['EXPLAIN'];
|
|
6886
7255
|
if (node.options && node.options.length > 0) {
|
|
6887
|
-
const explainContext =
|
|
7256
|
+
const explainContext = context.spawn('ExplainStmt');
|
|
6888
7257
|
const options = list_utils_1.ListUtils.unwrapList(node.options).map(option => this.visit(option, explainContext));
|
|
6889
7258
|
output.push(`(${options.join(', ')})`);
|
|
6890
7259
|
}
|
|
@@ -7142,9 +7511,7 @@ class Deparser {
|
|
|
7142
7511
|
output.push(this.RangeVar(node.relation, context));
|
|
7143
7512
|
}
|
|
7144
7513
|
else if (node.relation) {
|
|
7145
|
-
const rangeVarContext = node.relationType
|
|
7146
|
-
? { ...context, parentNodeTypes: [...context.parentNodeTypes, 'AlterTypeStmt'] }
|
|
7147
|
-
: context;
|
|
7514
|
+
const rangeVarContext = context.spawn('RenameStmt', { objtype: node.relationType });
|
|
7148
7515
|
// Add ON keyword for policy operations
|
|
7149
7516
|
if (node.renameType === 'OBJECT_POLICY') {
|
|
7150
7517
|
output.push('ON');
|
|
@@ -7326,7 +7693,7 @@ class Deparser {
|
|
|
7326
7693
|
}
|
|
7327
7694
|
}
|
|
7328
7695
|
if (node.privileges && node.privileges.length > 0) {
|
|
7329
|
-
const privilegeContext =
|
|
7696
|
+
const privilegeContext = context.spawn('GrantStmt');
|
|
7330
7697
|
const privileges = list_utils_1.ListUtils.unwrapList(node.privileges)
|
|
7331
7698
|
.map(priv => this.visit(priv, privilegeContext))
|
|
7332
7699
|
.join(', ');
|
|
@@ -7634,7 +8001,12 @@ class Deparser {
|
|
|
7634
8001
|
}
|
|
7635
8002
|
if (node.action) {
|
|
7636
8003
|
const actionStr = this.GrantStmt(node.action, context);
|
|
7637
|
-
|
|
8004
|
+
if (context.isPretty()) {
|
|
8005
|
+
return output.join(' ') + context.newline() + context.indent(actionStr);
|
|
8006
|
+
}
|
|
8007
|
+
else {
|
|
8008
|
+
output.push(actionStr);
|
|
8009
|
+
}
|
|
7638
8010
|
}
|
|
7639
8011
|
return output.join(' ');
|
|
7640
8012
|
}
|
|
@@ -7781,84 +8153,158 @@ class Deparser {
|
|
|
7781
8153
|
if (node.trigname) {
|
|
7782
8154
|
output.push(quote_utils_1.QuoteUtils.quote(node.trigname));
|
|
7783
8155
|
}
|
|
7784
|
-
|
|
7785
|
-
|
|
7786
|
-
timing
|
|
7787
|
-
|
|
7788
|
-
|
|
7789
|
-
|
|
7790
|
-
|
|
7791
|
-
|
|
7792
|
-
|
|
7793
|
-
|
|
7794
|
-
events
|
|
7795
|
-
|
|
7796
|
-
events
|
|
7797
|
-
|
|
7798
|
-
events
|
|
7799
|
-
|
|
7800
|
-
|
|
7801
|
-
|
|
7802
|
-
|
|
7803
|
-
|
|
7804
|
-
|
|
7805
|
-
|
|
7806
|
-
.
|
|
7807
|
-
|
|
7808
|
-
|
|
7809
|
-
|
|
7810
|
-
|
|
7811
|
-
|
|
7812
|
-
|
|
7813
|
-
|
|
7814
|
-
|
|
7815
|
-
|
|
7816
|
-
|
|
7817
|
-
|
|
7818
|
-
|
|
7819
|
-
|
|
7820
|
-
|
|
7821
|
-
|
|
7822
|
-
|
|
7823
|
-
|
|
7824
|
-
|
|
7825
|
-
|
|
7826
|
-
|
|
7827
|
-
.
|
|
7828
|
-
|
|
7829
|
-
|
|
7830
|
-
|
|
7831
|
-
|
|
7832
|
-
|
|
7833
|
-
|
|
7834
|
-
|
|
7835
|
-
|
|
7836
|
-
|
|
7837
|
-
|
|
7838
|
-
|
|
7839
|
-
|
|
7840
|
-
|
|
7841
|
-
|
|
7842
|
-
|
|
7843
|
-
|
|
7844
|
-
|
|
7845
|
-
|
|
7846
|
-
|
|
7847
|
-
|
|
7848
|
-
|
|
7849
|
-
|
|
7850
|
-
|
|
7851
|
-
|
|
7852
|
-
|
|
7853
|
-
|
|
7854
|
-
|
|
7855
|
-
output.push(args);
|
|
7856
|
-
output.push(')');
|
|
8156
|
+
if (context.isPretty()) {
|
|
8157
|
+
const components = [];
|
|
8158
|
+
const timing = [];
|
|
8159
|
+
if (node.timing & 2)
|
|
8160
|
+
timing.push('BEFORE');
|
|
8161
|
+
else if (node.timing & 64)
|
|
8162
|
+
timing.push('INSTEAD OF');
|
|
8163
|
+
else
|
|
8164
|
+
timing.push('AFTER');
|
|
8165
|
+
const events = [];
|
|
8166
|
+
if (node.events & 4)
|
|
8167
|
+
events.push('INSERT');
|
|
8168
|
+
if (node.events & 8)
|
|
8169
|
+
events.push('DELETE');
|
|
8170
|
+
if (node.events & 16) {
|
|
8171
|
+
let updateStr = 'UPDATE';
|
|
8172
|
+
if (node.columns && node.columns.length > 0) {
|
|
8173
|
+
const columnNames = list_utils_1.ListUtils.unwrapList(node.columns)
|
|
8174
|
+
.map(col => this.visit(col, context))
|
|
8175
|
+
.join(', ');
|
|
8176
|
+
updateStr += ' OF ' + columnNames;
|
|
8177
|
+
}
|
|
8178
|
+
events.push(updateStr);
|
|
8179
|
+
}
|
|
8180
|
+
if (node.events & 32)
|
|
8181
|
+
events.push('TRUNCATE');
|
|
8182
|
+
components.push(context.indent(timing.join(' ') + ' ' + events.join(' OR ')));
|
|
8183
|
+
if (node.relation) {
|
|
8184
|
+
components.push(context.indent('ON ' + this.RangeVar(node.relation, context)));
|
|
8185
|
+
}
|
|
8186
|
+
if (node.transitionRels && node.transitionRels.length > 0) {
|
|
8187
|
+
const transitionClauses = list_utils_1.ListUtils.unwrapList(node.transitionRels)
|
|
8188
|
+
.map(rel => this.visit(rel, context))
|
|
8189
|
+
.join(' ');
|
|
8190
|
+
components.push(context.indent('REFERENCING ' + transitionClauses));
|
|
8191
|
+
}
|
|
8192
|
+
if (node.deferrable) {
|
|
8193
|
+
components.push(context.indent('DEFERRABLE'));
|
|
8194
|
+
}
|
|
8195
|
+
if (node.initdeferred) {
|
|
8196
|
+
components.push(context.indent('INITIALLY DEFERRED'));
|
|
8197
|
+
}
|
|
8198
|
+
if (node.row) {
|
|
8199
|
+
components.push(context.indent('FOR EACH ROW'));
|
|
8200
|
+
}
|
|
8201
|
+
else {
|
|
8202
|
+
components.push(context.indent('FOR EACH STATEMENT'));
|
|
8203
|
+
}
|
|
8204
|
+
if (node.whenClause) {
|
|
8205
|
+
const whenStr = 'WHEN (' + this.visit(node.whenClause, context) + ')';
|
|
8206
|
+
components.push(context.indent(whenStr));
|
|
8207
|
+
}
|
|
8208
|
+
let executeStr = 'EXECUTE';
|
|
8209
|
+
if (node.funcname && node.funcname.length > 0) {
|
|
8210
|
+
const funcName = list_utils_1.ListUtils.unwrapList(node.funcname)
|
|
8211
|
+
.map(name => this.visit(name, context))
|
|
8212
|
+
.join('.');
|
|
8213
|
+
executeStr += ' PROCEDURE ' + funcName;
|
|
8214
|
+
}
|
|
8215
|
+
if (node.args && node.args.length > 0) {
|
|
8216
|
+
const argContext = context.spawn('CreateTrigStmt', { isStringLiteral: true });
|
|
8217
|
+
const args = list_utils_1.ListUtils.unwrapList(node.args)
|
|
8218
|
+
.map(arg => this.visit(arg, argContext))
|
|
8219
|
+
.join(', ');
|
|
8220
|
+
executeStr += '(' + args + ')';
|
|
8221
|
+
}
|
|
8222
|
+
else {
|
|
8223
|
+
executeStr += '()';
|
|
8224
|
+
}
|
|
8225
|
+
components.push(context.indent(executeStr));
|
|
8226
|
+
return output.join(' ') + context.newline() + components.join(context.newline());
|
|
7857
8227
|
}
|
|
7858
8228
|
else {
|
|
7859
|
-
|
|
8229
|
+
const timing = [];
|
|
8230
|
+
if (node.timing & 2)
|
|
8231
|
+
timing.push('BEFORE');
|
|
8232
|
+
else if (node.timing & 64)
|
|
8233
|
+
timing.push('INSTEAD OF');
|
|
8234
|
+
else
|
|
8235
|
+
timing.push('AFTER');
|
|
8236
|
+
output.push(timing.join(' '));
|
|
8237
|
+
const events = [];
|
|
8238
|
+
if (node.events & 4)
|
|
8239
|
+
events.push('INSERT');
|
|
8240
|
+
if (node.events & 8)
|
|
8241
|
+
events.push('DELETE');
|
|
8242
|
+
if (node.events & 16)
|
|
8243
|
+
events.push('UPDATE');
|
|
8244
|
+
if (node.events & 32)
|
|
8245
|
+
events.push('TRUNCATE');
|
|
8246
|
+
output.push(events.join(' OR '));
|
|
8247
|
+
if (node.columns && node.columns.length > 0) {
|
|
8248
|
+
output.push('OF');
|
|
8249
|
+
const columnNames = list_utils_1.ListUtils.unwrapList(node.columns)
|
|
8250
|
+
.map(col => this.visit(col, context))
|
|
8251
|
+
.join(', ');
|
|
8252
|
+
output.push(columnNames);
|
|
8253
|
+
}
|
|
8254
|
+
output.push('ON');
|
|
8255
|
+
if (node.relation) {
|
|
8256
|
+
output.push(this.RangeVar(node.relation, context));
|
|
8257
|
+
}
|
|
8258
|
+
if (node.constrrel) {
|
|
8259
|
+
output.push('FROM');
|
|
8260
|
+
output.push(this.RangeVar(node.constrrel, context));
|
|
8261
|
+
}
|
|
8262
|
+
if (node.deferrable) {
|
|
8263
|
+
output.push('DEFERRABLE');
|
|
8264
|
+
}
|
|
8265
|
+
if (node.initdeferred) {
|
|
8266
|
+
output.push('INITIALLY DEFERRED');
|
|
8267
|
+
}
|
|
8268
|
+
if (node.transitionRels && node.transitionRels.length > 0) {
|
|
8269
|
+
output.push('REFERENCING');
|
|
8270
|
+
const transitionClauses = list_utils_1.ListUtils.unwrapList(node.transitionRels)
|
|
8271
|
+
.map(rel => this.visit(rel, context))
|
|
8272
|
+
.join(' ');
|
|
8273
|
+
output.push(transitionClauses);
|
|
8274
|
+
}
|
|
8275
|
+
if (node.row) {
|
|
8276
|
+
output.push('FOR EACH ROW');
|
|
8277
|
+
}
|
|
8278
|
+
else {
|
|
8279
|
+
output.push('FOR EACH STATEMENT');
|
|
8280
|
+
}
|
|
8281
|
+
if (node.whenClause) {
|
|
8282
|
+
output.push('WHEN');
|
|
8283
|
+
output.push('(');
|
|
8284
|
+
output.push(this.visit(node.whenClause, context));
|
|
8285
|
+
output.push(')');
|
|
8286
|
+
}
|
|
8287
|
+
output.push('EXECUTE');
|
|
8288
|
+
if (node.funcname && node.funcname.length > 0) {
|
|
8289
|
+
const funcName = list_utils_1.ListUtils.unwrapList(node.funcname)
|
|
8290
|
+
.map(name => this.visit(name, context))
|
|
8291
|
+
.join('.');
|
|
8292
|
+
output.push('FUNCTION', funcName);
|
|
8293
|
+
}
|
|
8294
|
+
if (node.args && node.args.length > 0) {
|
|
8295
|
+
output.push('(');
|
|
8296
|
+
const argContext = context.spawn('CreateTrigStmt', { isStringLiteral: true });
|
|
8297
|
+
const args = list_utils_1.ListUtils.unwrapList(node.args)
|
|
8298
|
+
.map(arg => this.visit(arg, argContext))
|
|
8299
|
+
.join(', ');
|
|
8300
|
+
output.push(args);
|
|
8301
|
+
output.push(')');
|
|
8302
|
+
}
|
|
8303
|
+
else {
|
|
8304
|
+
output.push('()');
|
|
8305
|
+
}
|
|
8306
|
+
return output.join(' ');
|
|
7860
8307
|
}
|
|
7861
|
-
return output.join(' ');
|
|
7862
8308
|
}
|
|
7863
8309
|
TriggerTransition(node, context) {
|
|
7864
8310
|
const output = [];
|
|
@@ -7884,7 +8330,7 @@ class Deparser {
|
|
|
7884
8330
|
}
|
|
7885
8331
|
if (node.whenclause && node.whenclause.length > 0) {
|
|
7886
8332
|
output.push('WHEN');
|
|
7887
|
-
const eventTriggerContext =
|
|
8333
|
+
const eventTriggerContext = context.spawn('CreateEventTrigStmt');
|
|
7888
8334
|
const conditions = list_utils_1.ListUtils.unwrapList(node.whenclause)
|
|
7889
8335
|
.map(condition => this.visit(condition, eventTriggerContext))
|
|
7890
8336
|
.join(' AND ');
|
|
@@ -8073,7 +8519,7 @@ class Deparser {
|
|
|
8073
8519
|
output.push(sequenceName.join('.'));
|
|
8074
8520
|
}
|
|
8075
8521
|
if (node.options && node.options.length > 0) {
|
|
8076
|
-
const seqContext =
|
|
8522
|
+
const seqContext = context.spawn('CreateSeqStmt');
|
|
8077
8523
|
const optionStrs = list_utils_1.ListUtils.unwrapList(node.options)
|
|
8078
8524
|
.filter(option => option != null && this.getNodeType(option) !== 'undefined')
|
|
8079
8525
|
.map(option => {
|
|
@@ -8110,7 +8556,7 @@ class Deparser {
|
|
|
8110
8556
|
output.push(sequenceName.join('.'));
|
|
8111
8557
|
}
|
|
8112
8558
|
if (node.options && node.options.length > 0) {
|
|
8113
|
-
const seqContext =
|
|
8559
|
+
const seqContext = context.spawn('AlterSeqStmt');
|
|
8114
8560
|
const optionStrs = list_utils_1.ListUtils.unwrapList(node.options)
|
|
8115
8561
|
.filter(option => option && option !== undefined)
|
|
8116
8562
|
.map(option => {
|
|
@@ -8139,7 +8585,7 @@ class Deparser {
|
|
|
8139
8585
|
CompositeTypeStmt(node, context) {
|
|
8140
8586
|
const output = ['CREATE', 'TYPE'];
|
|
8141
8587
|
if (node.typevar) {
|
|
8142
|
-
const typeContext =
|
|
8588
|
+
const typeContext = context.spawn('CompositeTypeStmt');
|
|
8143
8589
|
output.push(this.RangeVar(node.typevar, typeContext));
|
|
8144
8590
|
}
|
|
8145
8591
|
output.push('AS');
|
|
@@ -8240,7 +8686,7 @@ class Deparser {
|
|
|
8240
8686
|
output.push(this.RoleSpec(node.role, context));
|
|
8241
8687
|
}
|
|
8242
8688
|
if (node.options) {
|
|
8243
|
-
const roleContext =
|
|
8689
|
+
const roleContext = context.spawn('AlterRoleStmt');
|
|
8244
8690
|
// Handle GROUP operations specially based on action value
|
|
8245
8691
|
if (isGroupStatement) {
|
|
8246
8692
|
const roleMembersOption = list_utils_1.ListUtils.unwrapList(node.options).find(option => option.DefElem && option.DefElem.defname === 'rolemembers');
|
|
@@ -8436,14 +8882,14 @@ class Deparser {
|
|
|
8436
8882
|
AccessPriv(node, context) {
|
|
8437
8883
|
const output = [];
|
|
8438
8884
|
if (node.priv_name) {
|
|
8439
|
-
output.push(node.priv_name);
|
|
8885
|
+
output.push(node.priv_name.toUpperCase());
|
|
8440
8886
|
}
|
|
8441
8887
|
else {
|
|
8442
8888
|
output.push('ALL');
|
|
8443
8889
|
}
|
|
8444
8890
|
if (node.cols && node.cols.length > 0) {
|
|
8445
8891
|
output.push('(');
|
|
8446
|
-
const colContext =
|
|
8892
|
+
const colContext = context.spawn('AccessPriv');
|
|
8447
8893
|
const columns = list_utils_1.ListUtils.unwrapList(node.cols).map(col => this.visit(col, colContext));
|
|
8448
8894
|
output.push(columns.join(', '));
|
|
8449
8895
|
output.push(')');
|
|
@@ -8523,7 +8969,7 @@ class Deparser {
|
|
|
8523
8969
|
output.push(list_utils_1.ListUtils.unwrapList(node.defnames).map(name => this.visit(name, context)).join('.'));
|
|
8524
8970
|
}
|
|
8525
8971
|
if (node.definition && node.definition.length > 0) {
|
|
8526
|
-
const defineStmtContext =
|
|
8972
|
+
const defineStmtContext = context.spawn('DefineStmt');
|
|
8527
8973
|
const definitions = list_utils_1.ListUtils.unwrapList(node.definition).map(def => {
|
|
8528
8974
|
return this.visit(def, defineStmtContext);
|
|
8529
8975
|
});
|
|
@@ -9009,7 +9455,7 @@ class Deparser {
|
|
|
9009
9455
|
const operatorNumber = node.number !== undefined ? node.number : 0;
|
|
9010
9456
|
output.push(operatorNumber.toString());
|
|
9011
9457
|
if (node.name) {
|
|
9012
|
-
const opClassContext =
|
|
9458
|
+
const opClassContext = context.spawn('CreateOpClassItem');
|
|
9013
9459
|
output.push(this.ObjectWithArgs(node.name, opClassContext));
|
|
9014
9460
|
}
|
|
9015
9461
|
}
|
|
@@ -9019,7 +9465,7 @@ class Deparser {
|
|
|
9019
9465
|
const functionNumber = node.number !== undefined ? node.number : 0;
|
|
9020
9466
|
output.push(functionNumber.toString());
|
|
9021
9467
|
if (node.name) {
|
|
9022
|
-
const opClassContext =
|
|
9468
|
+
const opClassContext = context.spawn('CreateOpClassItem');
|
|
9023
9469
|
output.push(this.ObjectWithArgs(node.name, opClassContext));
|
|
9024
9470
|
}
|
|
9025
9471
|
}
|
|
@@ -9717,7 +10163,7 @@ class Deparser {
|
|
|
9717
10163
|
output.push(this.ObjectWithArgs(node.func, context));
|
|
9718
10164
|
}
|
|
9719
10165
|
if (node.actions && node.actions.length > 0) {
|
|
9720
|
-
const alterFunctionContext =
|
|
10166
|
+
const alterFunctionContext = context.spawn('AlterFunctionStmt');
|
|
9721
10167
|
const actionStrs = list_utils_1.ListUtils.unwrapList(node.actions).map(action => this.visit(action, alterFunctionContext));
|
|
9722
10168
|
output.push(actionStrs.join(' '));
|
|
9723
10169
|
}
|
|
@@ -9961,7 +10407,7 @@ class Deparser {
|
|
|
9961
10407
|
CreateForeignTableStmt(node, context) {
|
|
9962
10408
|
const output = ['CREATE FOREIGN TABLE'];
|
|
9963
10409
|
if (node.base && node.base.relation) {
|
|
9964
|
-
const relationContext =
|
|
10410
|
+
const relationContext = context.spawn('CreateForeignTableStmt');
|
|
9965
10411
|
// Handle relation node directly as RangeVar since it contains the RangeVar properties
|
|
9966
10412
|
output.push(this.RangeVar(node.base.relation, relationContext));
|
|
9967
10413
|
}
|
|
@@ -9991,7 +10437,7 @@ class Deparser {
|
|
|
9991
10437
|
output.push(quote_utils_1.QuoteUtils.quote(node.servername));
|
|
9992
10438
|
}
|
|
9993
10439
|
if (node.options && node.options.length > 0) {
|
|
9994
|
-
const foreignTableContext =
|
|
10440
|
+
const foreignTableContext = context.spawn('CreateForeignTableStmt');
|
|
9995
10441
|
const optionStrs = list_utils_1.ListUtils.unwrapList(node.options).map(opt => this.visit(opt, foreignTableContext));
|
|
9996
10442
|
output.push(`OPTIONS (${optionStrs.join(', ')})`);
|
|
9997
10443
|
}
|