pgsql-deparser 16.0.0 → 16.1.1
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 +24 -16
- package/deparser/deparser.d.ts +10 -3
- package/deparser/deparser.js +1042 -570
- 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 +1042 -570
- package/esm/deparser/utils/sql-formatter.js +1 -1
- package/esm/deparser/visitors/base.js +87 -0
- package/package.json +5 -5
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,128 @@ class Deparser {
|
|
|
114
171
|
}
|
|
115
172
|
return delimiter;
|
|
116
173
|
}
|
|
117
|
-
|
|
174
|
+
/**
|
|
175
|
+
* Maps ObjectType enum values to their corresponding SQL keywords
|
|
176
|
+
* Used by AlterOwnerStmt, AlterObjectSchemaStmt, and other statements that need object type keywords
|
|
177
|
+
*/
|
|
178
|
+
getObjectTypeKeyword(objectType) {
|
|
179
|
+
switch (objectType) {
|
|
180
|
+
case 'OBJECT_TABLE':
|
|
181
|
+
return 'TABLE';
|
|
182
|
+
case 'OBJECT_VIEW':
|
|
183
|
+
return 'VIEW';
|
|
184
|
+
case 'OBJECT_INDEX':
|
|
185
|
+
return 'INDEX';
|
|
186
|
+
case 'OBJECT_SEQUENCE':
|
|
187
|
+
return 'SEQUENCE';
|
|
188
|
+
case 'OBJECT_FUNCTION':
|
|
189
|
+
return 'FUNCTION';
|
|
190
|
+
case 'OBJECT_PROCEDURE':
|
|
191
|
+
return 'PROCEDURE';
|
|
192
|
+
case 'OBJECT_SCHEMA':
|
|
193
|
+
return 'SCHEMA';
|
|
194
|
+
case 'OBJECT_DATABASE':
|
|
195
|
+
return 'DATABASE';
|
|
196
|
+
case 'OBJECT_DOMAIN':
|
|
197
|
+
return 'DOMAIN';
|
|
198
|
+
case 'OBJECT_AGGREGATE':
|
|
199
|
+
return 'AGGREGATE';
|
|
200
|
+
case 'OBJECT_CONVERSION':
|
|
201
|
+
return 'CONVERSION';
|
|
202
|
+
case 'OBJECT_LANGUAGE':
|
|
203
|
+
return 'LANGUAGE';
|
|
204
|
+
case 'OBJECT_OPERATOR':
|
|
205
|
+
return 'OPERATOR';
|
|
206
|
+
case 'OBJECT_OPFAMILY':
|
|
207
|
+
return 'OPERATOR FAMILY';
|
|
208
|
+
case 'OBJECT_OPCLASS':
|
|
209
|
+
return 'OPERATOR CLASS';
|
|
210
|
+
case 'OBJECT_TSDICTIONARY':
|
|
211
|
+
return 'TEXT SEARCH DICTIONARY';
|
|
212
|
+
case 'OBJECT_TSCONFIGURATION':
|
|
213
|
+
return 'TEXT SEARCH CONFIGURATION';
|
|
214
|
+
case 'OBJECT_EVENT_TRIGGER':
|
|
215
|
+
return 'EVENT TRIGGER';
|
|
216
|
+
case 'OBJECT_FDW':
|
|
217
|
+
return 'FOREIGN DATA WRAPPER';
|
|
218
|
+
case 'OBJECT_FOREIGN_SERVER':
|
|
219
|
+
return 'SERVER';
|
|
220
|
+
case 'OBJECT_TYPE':
|
|
221
|
+
return 'TYPE';
|
|
222
|
+
case 'OBJECT_COLLATION':
|
|
223
|
+
return 'COLLATION';
|
|
224
|
+
case 'OBJECT_PUBLICATION':
|
|
225
|
+
return 'PUBLICATION';
|
|
226
|
+
case 'OBJECT_ACCESS_METHOD':
|
|
227
|
+
return 'ACCESS METHOD';
|
|
228
|
+
case 'OBJECT_AMOP':
|
|
229
|
+
return 'OPERATOR CLASS';
|
|
230
|
+
case 'OBJECT_AMPROC':
|
|
231
|
+
return 'OPERATOR CLASS';
|
|
232
|
+
case 'OBJECT_ATTRIBUTE':
|
|
233
|
+
return 'ATTRIBUTE';
|
|
234
|
+
case 'OBJECT_CAST':
|
|
235
|
+
return 'CAST';
|
|
236
|
+
case 'OBJECT_COLUMN':
|
|
237
|
+
return 'COLUMN';
|
|
238
|
+
case 'OBJECT_DEFAULT':
|
|
239
|
+
return 'DEFAULT';
|
|
240
|
+
case 'OBJECT_DEFACL':
|
|
241
|
+
return 'DEFAULT PRIVILEGES';
|
|
242
|
+
case 'OBJECT_DOMCONSTRAINT':
|
|
243
|
+
return 'DOMAIN';
|
|
244
|
+
case 'OBJECT_EXTENSION':
|
|
245
|
+
return 'EXTENSION';
|
|
246
|
+
case 'OBJECT_FOREIGN_TABLE':
|
|
247
|
+
return 'FOREIGN TABLE';
|
|
248
|
+
case 'OBJECT_LARGEOBJECT':
|
|
249
|
+
return 'LARGE OBJECT';
|
|
250
|
+
case 'OBJECT_MATVIEW':
|
|
251
|
+
return 'MATERIALIZED VIEW';
|
|
252
|
+
case 'OBJECT_PARAMETER_ACL':
|
|
253
|
+
return 'PARAMETER';
|
|
254
|
+
case 'OBJECT_POLICY':
|
|
255
|
+
return 'POLICY';
|
|
256
|
+
case 'OBJECT_PUBLICATION_NAMESPACE':
|
|
257
|
+
return 'PUBLICATION';
|
|
258
|
+
case 'OBJECT_PUBLICATION_REL':
|
|
259
|
+
return 'PUBLICATION';
|
|
260
|
+
case 'OBJECT_ROLE':
|
|
261
|
+
return 'ROLE';
|
|
262
|
+
case 'OBJECT_ROUTINE':
|
|
263
|
+
return 'ROUTINE';
|
|
264
|
+
case 'OBJECT_RULE':
|
|
265
|
+
return 'RULE';
|
|
266
|
+
case 'OBJECT_STATISTIC_EXT':
|
|
267
|
+
return 'STATISTICS';
|
|
268
|
+
case 'OBJECT_SUBSCRIPTION':
|
|
269
|
+
return 'SUBSCRIPTION';
|
|
270
|
+
case 'OBJECT_TABCONSTRAINT':
|
|
271
|
+
return 'CONSTRAINT';
|
|
272
|
+
case 'OBJECT_TABLESPACE':
|
|
273
|
+
return 'TABLESPACE';
|
|
274
|
+
case 'OBJECT_TRANSFORM':
|
|
275
|
+
return 'TRANSFORM';
|
|
276
|
+
case 'OBJECT_TRIGGER':
|
|
277
|
+
return 'TRIGGER';
|
|
278
|
+
case 'OBJECT_TSPARSER':
|
|
279
|
+
return 'TEXT SEARCH PARSER';
|
|
280
|
+
case 'OBJECT_TSTEMPLATE':
|
|
281
|
+
return 'TEXT SEARCH TEMPLATE';
|
|
282
|
+
case 'OBJECT_USER_MAPPING':
|
|
283
|
+
return 'USER MAPPING';
|
|
284
|
+
default:
|
|
285
|
+
throw new Error(`Unsupported objectType: ${objectType}`);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
deparse(node, context) {
|
|
118
289
|
if (node == null) {
|
|
119
290
|
return null;
|
|
120
291
|
}
|
|
292
|
+
if (!context) {
|
|
293
|
+
const formatter = new sql_formatter_1.SqlFormatter(this.options.newline, this.options.tab, this.options.pretty);
|
|
294
|
+
context = new base_1.DeparserContext({ formatter, prettyMode: this.options.pretty });
|
|
295
|
+
}
|
|
121
296
|
if (typeof node === 'number' || node instanceof Number) {
|
|
122
297
|
return node.toString();
|
|
123
298
|
}
|
|
@@ -129,7 +304,11 @@ class Deparser {
|
|
|
129
304
|
throw new Error(`Error deparsing ${nodeType}: ${error.message}`);
|
|
130
305
|
}
|
|
131
306
|
}
|
|
132
|
-
visit(node, context
|
|
307
|
+
visit(node, context) {
|
|
308
|
+
if (!context) {
|
|
309
|
+
const formatter = new sql_formatter_1.SqlFormatter(this.options.newline, this.options.tab, this.options.pretty);
|
|
310
|
+
context = new base_1.DeparserContext({ formatter, prettyMode: this.options.pretty });
|
|
311
|
+
}
|
|
133
312
|
const nodeType = this.getNodeType(node);
|
|
134
313
|
// Handle empty objects
|
|
135
314
|
if (!nodeType) {
|
|
@@ -138,11 +317,7 @@ class Deparser {
|
|
|
138
317
|
const nodeData = this.getNodeData(node);
|
|
139
318
|
const methodName = nodeType;
|
|
140
319
|
if (typeof this[methodName] === 'function') {
|
|
141
|
-
const
|
|
142
|
-
...context,
|
|
143
|
-
parentNodeTypes: [...context.parentNodeTypes, nodeType]
|
|
144
|
-
};
|
|
145
|
-
const result = this[methodName](nodeData, childContext);
|
|
320
|
+
const result = this[methodName](nodeData, context);
|
|
146
321
|
return result;
|
|
147
322
|
}
|
|
148
323
|
throw new Error(`Deparser does not handle node type: ${nodeType}`);
|
|
@@ -168,7 +343,7 @@ class Deparser {
|
|
|
168
343
|
.filter((rawStmt) => rawStmt != null)
|
|
169
344
|
.map((rawStmt) => this.RawStmt(rawStmt, context))
|
|
170
345
|
.filter((result) => result !== '')
|
|
171
|
-
.join(
|
|
346
|
+
.join(context.newline() + context.newline());
|
|
172
347
|
}
|
|
173
348
|
RawStmt(node, context) {
|
|
174
349
|
if (!node.stmt) {
|
|
@@ -188,7 +363,7 @@ class Deparser {
|
|
|
188
363
|
}
|
|
189
364
|
if (!node.op || node.op === 'SETOP_NONE') {
|
|
190
365
|
if (node.valuesLists == null) {
|
|
191
|
-
if (!
|
|
366
|
+
if (!context.isPretty() || !node.targetList) {
|
|
192
367
|
output.push('SELECT');
|
|
193
368
|
}
|
|
194
369
|
}
|
|
@@ -208,7 +383,7 @@ class Deparser {
|
|
|
208
383
|
(node.rarg).limitOffset ||
|
|
209
384
|
(node.rarg).withClause);
|
|
210
385
|
if (leftNeedsParens) {
|
|
211
|
-
output.push(
|
|
386
|
+
output.push(context.parens(leftStmt));
|
|
212
387
|
}
|
|
213
388
|
else {
|
|
214
389
|
output.push(leftStmt);
|
|
@@ -230,7 +405,7 @@ class Deparser {
|
|
|
230
405
|
output.push('ALL');
|
|
231
406
|
}
|
|
232
407
|
if (rightNeedsParens) {
|
|
233
|
-
output.push(
|
|
408
|
+
output.push(context.parens(rightStmt));
|
|
234
409
|
}
|
|
235
410
|
else {
|
|
236
411
|
output.push(rightStmt);
|
|
@@ -242,20 +417,20 @@ class Deparser {
|
|
|
242
417
|
const distinctClause = list_utils_1.ListUtils.unwrapList(node.distinctClause);
|
|
243
418
|
if (distinctClause.length > 0 && Object.keys(distinctClause[0]).length > 0) {
|
|
244
419
|
const clause = distinctClause
|
|
245
|
-
.map(e => this.visit(e,
|
|
420
|
+
.map(e => this.visit(e, context.spawn('SelectStmt', { select: true })))
|
|
246
421
|
.join(', ');
|
|
247
|
-
distinctPart = ' DISTINCT ON ' +
|
|
422
|
+
distinctPart = ' DISTINCT ON ' + context.parens(clause);
|
|
248
423
|
}
|
|
249
424
|
else {
|
|
250
425
|
distinctPart = ' DISTINCT';
|
|
251
426
|
}
|
|
252
|
-
if (!
|
|
427
|
+
if (!context.isPretty()) {
|
|
253
428
|
if (distinctClause.length > 0 && Object.keys(distinctClause[0]).length > 0) {
|
|
254
429
|
output.push('DISTINCT ON');
|
|
255
430
|
const clause = distinctClause
|
|
256
|
-
.map(e => this.visit(e,
|
|
431
|
+
.map(e => this.visit(e, context.spawn('SelectStmt', { select: true })))
|
|
257
432
|
.join(', ');
|
|
258
|
-
output.push(
|
|
433
|
+
output.push(context.parens(clause));
|
|
259
434
|
}
|
|
260
435
|
else {
|
|
261
436
|
output.push('DISTINCT');
|
|
@@ -264,22 +439,41 @@ class Deparser {
|
|
|
264
439
|
}
|
|
265
440
|
if (node.targetList) {
|
|
266
441
|
const targetList = list_utils_1.ListUtils.unwrapList(node.targetList);
|
|
267
|
-
if (
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
const
|
|
271
|
-
if
|
|
272
|
-
|
|
442
|
+
if (context.isPretty()) {
|
|
443
|
+
if (targetList.length === 1) {
|
|
444
|
+
const targetNode = targetList[0];
|
|
445
|
+
const target = this.visit(targetNode, context.spawn('SelectStmt', { select: true }));
|
|
446
|
+
// Check if single target is complex - if so, use multiline format
|
|
447
|
+
if (this.isComplexSelectTarget(targetNode)) {
|
|
448
|
+
output.push('SELECT' + distinctPart);
|
|
449
|
+
if (this.containsMultilineStringLiteral(target)) {
|
|
450
|
+
output.push(target);
|
|
451
|
+
}
|
|
452
|
+
else {
|
|
453
|
+
output.push(context.indent(target));
|
|
454
|
+
}
|
|
273
455
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
456
|
+
else {
|
|
457
|
+
output.push('SELECT' + distinctPart + ' ' + target);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
const targetStrings = targetList
|
|
462
|
+
.map(e => {
|
|
463
|
+
const targetStr = this.visit(e, context.spawn('SelectStmt', { select: true }));
|
|
464
|
+
if (this.containsMultilineStringLiteral(targetStr)) {
|
|
465
|
+
return targetStr;
|
|
466
|
+
}
|
|
467
|
+
return context.indent(targetStr);
|
|
468
|
+
});
|
|
469
|
+
const formattedTargets = targetStrings.join(',' + context.newline());
|
|
470
|
+
output.push('SELECT' + distinctPart);
|
|
471
|
+
output.push(formattedTargets);
|
|
472
|
+
}
|
|
279
473
|
}
|
|
280
474
|
else {
|
|
281
475
|
const targets = targetList
|
|
282
|
-
.map(e => this.visit(e,
|
|
476
|
+
.map(e => this.visit(e, context.spawn('SelectStmt', { select: true })))
|
|
283
477
|
.join(', ');
|
|
284
478
|
output.push(targets);
|
|
285
479
|
}
|
|
@@ -291,22 +485,22 @@ class Deparser {
|
|
|
291
485
|
if (node.fromClause) {
|
|
292
486
|
const fromList = list_utils_1.ListUtils.unwrapList(node.fromClause);
|
|
293
487
|
const fromItems = fromList
|
|
294
|
-
.map(e => this.deparse(e,
|
|
488
|
+
.map(e => this.deparse(e, context.spawn('SelectStmt', { from: true })))
|
|
295
489
|
.join(', ');
|
|
296
490
|
output.push('FROM ' + fromItems.trim());
|
|
297
491
|
}
|
|
298
492
|
if (node.whereClause) {
|
|
299
|
-
if (
|
|
493
|
+
if (context.isPretty()) {
|
|
300
494
|
output.push('WHERE');
|
|
301
495
|
const whereExpr = this.visit(node.whereClause, context);
|
|
302
|
-
const lines = whereExpr.split(
|
|
496
|
+
const lines = whereExpr.split(context.newline());
|
|
303
497
|
const indentedLines = lines.map((line, index) => {
|
|
304
498
|
if (index === 0) {
|
|
305
|
-
return
|
|
499
|
+
return context.indent(line);
|
|
306
500
|
}
|
|
307
501
|
return line;
|
|
308
502
|
});
|
|
309
|
-
output.push(indentedLines.join(
|
|
503
|
+
output.push(indentedLines.join(context.newline()));
|
|
310
504
|
}
|
|
311
505
|
else {
|
|
312
506
|
output.push('WHERE');
|
|
@@ -314,45 +508,61 @@ class Deparser {
|
|
|
314
508
|
}
|
|
315
509
|
}
|
|
316
510
|
if (node.valuesLists) {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
const
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
511
|
+
if (context.isPretty()) {
|
|
512
|
+
output.push('VALUES');
|
|
513
|
+
const lists = list_utils_1.ListUtils.unwrapList(node.valuesLists).map(list => {
|
|
514
|
+
const values = list_utils_1.ListUtils.unwrapList(list).map(val => this.visit(val, context));
|
|
515
|
+
return context.parens(values.join(', '));
|
|
516
|
+
});
|
|
517
|
+
const indentedTuples = lists.map(tuple => {
|
|
518
|
+
if (this.containsMultilineStringLiteral(tuple)) {
|
|
519
|
+
return tuple;
|
|
520
|
+
}
|
|
521
|
+
return context.indent(tuple);
|
|
522
|
+
});
|
|
523
|
+
output.push(indentedTuples.join(',\n'));
|
|
524
|
+
}
|
|
525
|
+
else {
|
|
526
|
+
output.push('VALUES');
|
|
527
|
+
const lists = list_utils_1.ListUtils.unwrapList(node.valuesLists).map(list => {
|
|
528
|
+
const values = list_utils_1.ListUtils.unwrapList(list).map(val => this.visit(val, context));
|
|
529
|
+
return context.parens(values.join(', '));
|
|
530
|
+
});
|
|
531
|
+
output.push(lists.join(', '));
|
|
532
|
+
}
|
|
323
533
|
}
|
|
324
534
|
if (node.groupClause) {
|
|
325
535
|
const groupList = list_utils_1.ListUtils.unwrapList(node.groupClause);
|
|
326
|
-
if (
|
|
536
|
+
if (context.isPretty()) {
|
|
327
537
|
const groupItems = groupList
|
|
328
538
|
.map(e => {
|
|
329
|
-
const groupStr = this.visit(e,
|
|
539
|
+
const groupStr = this.visit(e, context.spawn('SelectStmt', { group: true, indentLevel: context.indentLevel + 1 }));
|
|
330
540
|
if (this.containsMultilineStringLiteral(groupStr)) {
|
|
331
541
|
return groupStr;
|
|
332
542
|
}
|
|
333
|
-
return
|
|
543
|
+
return context.indent(groupStr);
|
|
334
544
|
})
|
|
335
|
-
.join(',' +
|
|
545
|
+
.join(',' + context.newline());
|
|
336
546
|
output.push('GROUP BY');
|
|
337
547
|
output.push(groupItems);
|
|
338
548
|
}
|
|
339
549
|
else {
|
|
340
550
|
output.push('GROUP BY');
|
|
341
551
|
const groupItems = groupList
|
|
342
|
-
.map(e => this.visit(e,
|
|
552
|
+
.map(e => this.visit(e, context.spawn('SelectStmt', { group: true })))
|
|
343
553
|
.join(', ');
|
|
344
554
|
output.push(groupItems);
|
|
345
555
|
}
|
|
346
556
|
}
|
|
347
557
|
if (node.havingClause) {
|
|
348
|
-
if (
|
|
558
|
+
if (context.isPretty()) {
|
|
349
559
|
output.push('HAVING');
|
|
350
560
|
const havingStr = this.visit(node.havingClause, context);
|
|
351
561
|
if (this.containsMultilineStringLiteral(havingStr)) {
|
|
352
562
|
output.push(havingStr);
|
|
353
563
|
}
|
|
354
564
|
else {
|
|
355
|
-
output.push(
|
|
565
|
+
output.push(context.indent(havingStr));
|
|
356
566
|
}
|
|
357
567
|
}
|
|
358
568
|
else {
|
|
@@ -370,23 +580,23 @@ class Deparser {
|
|
|
370
580
|
}
|
|
371
581
|
if (node.sortClause) {
|
|
372
582
|
const sortList = list_utils_1.ListUtils.unwrapList(node.sortClause);
|
|
373
|
-
if (
|
|
583
|
+
if (context.isPretty()) {
|
|
374
584
|
const sortItems = sortList
|
|
375
585
|
.map(e => {
|
|
376
|
-
const sortStr = this.visit(e,
|
|
586
|
+
const sortStr = this.visit(e, context.spawn('SelectStmt', { sort: true, indentLevel: context.indentLevel + 1 }));
|
|
377
587
|
if (this.containsMultilineStringLiteral(sortStr)) {
|
|
378
588
|
return sortStr;
|
|
379
589
|
}
|
|
380
|
-
return
|
|
590
|
+
return context.indent(sortStr);
|
|
381
591
|
})
|
|
382
|
-
.join(',' +
|
|
592
|
+
.join(',' + context.newline());
|
|
383
593
|
output.push('ORDER BY');
|
|
384
594
|
output.push(sortItems);
|
|
385
595
|
}
|
|
386
596
|
else {
|
|
387
597
|
output.push('ORDER BY');
|
|
388
598
|
const sortItems = sortList
|
|
389
|
-
.map(e => this.visit(e,
|
|
599
|
+
.map(e => this.visit(e, context.spawn('SelectStmt', { sort: true })))
|
|
390
600
|
.join(', ');
|
|
391
601
|
output.push(sortItems);
|
|
392
602
|
}
|
|
@@ -404,9 +614,9 @@ class Deparser {
|
|
|
404
614
|
.join(' ');
|
|
405
615
|
output.push(lockingClauses);
|
|
406
616
|
}
|
|
407
|
-
if (
|
|
617
|
+
if (context.isPretty()) {
|
|
408
618
|
const filteredOutput = output.filter(item => item.trim() !== '');
|
|
409
|
-
return filteredOutput.join(
|
|
619
|
+
return filteredOutput.join(context.newline());
|
|
410
620
|
}
|
|
411
621
|
return output.join(' ');
|
|
412
622
|
}
|
|
@@ -418,13 +628,13 @@ class Deparser {
|
|
|
418
628
|
switch (kind) {
|
|
419
629
|
case 'AEXPR_OP':
|
|
420
630
|
if (lexpr && rexpr) {
|
|
421
|
-
const operator = this.deparseOperatorName(name);
|
|
631
|
+
const operator = this.deparseOperatorName(name, context);
|
|
422
632
|
let leftExpr = this.visit(lexpr, context);
|
|
423
633
|
let rightExpr = this.visit(rexpr, context);
|
|
424
634
|
// Check if left expression needs parentheses
|
|
425
635
|
let leftNeedsParens = false;
|
|
426
636
|
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));
|
|
637
|
+
const leftOp = this.deparseOperatorName(list_utils_1.ListUtils.unwrapList(lexpr.A_Expr.name), context);
|
|
428
638
|
if (this.needsParentheses(leftOp, operator, 'left')) {
|
|
429
639
|
leftNeedsParens = true;
|
|
430
640
|
}
|
|
@@ -433,12 +643,12 @@ class Deparser {
|
|
|
433
643
|
leftNeedsParens = true;
|
|
434
644
|
}
|
|
435
645
|
if (leftNeedsParens) {
|
|
436
|
-
leftExpr =
|
|
646
|
+
leftExpr = context.parens(leftExpr);
|
|
437
647
|
}
|
|
438
648
|
// Check if right expression needs parentheses
|
|
439
649
|
let rightNeedsParens = false;
|
|
440
650
|
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));
|
|
651
|
+
const rightOp = this.deparseOperatorName(list_utils_1.ListUtils.unwrapList(rexpr.A_Expr.name), context);
|
|
442
652
|
if (this.needsParentheses(rightOp, operator, 'right')) {
|
|
443
653
|
rightNeedsParens = true;
|
|
444
654
|
}
|
|
@@ -447,42 +657,42 @@ class Deparser {
|
|
|
447
657
|
rightNeedsParens = true;
|
|
448
658
|
}
|
|
449
659
|
if (rightNeedsParens) {
|
|
450
|
-
rightExpr =
|
|
660
|
+
rightExpr = context.parens(rightExpr);
|
|
451
661
|
}
|
|
452
|
-
return
|
|
662
|
+
return context.format([leftExpr, operator, rightExpr]);
|
|
453
663
|
}
|
|
454
664
|
else if (rexpr) {
|
|
455
|
-
return
|
|
456
|
-
this.deparseOperatorName(name),
|
|
665
|
+
return context.format([
|
|
666
|
+
this.deparseOperatorName(name, context),
|
|
457
667
|
this.visit(rexpr, context)
|
|
458
668
|
]);
|
|
459
669
|
}
|
|
460
670
|
break;
|
|
461
671
|
case 'AEXPR_OP_ANY':
|
|
462
|
-
return
|
|
672
|
+
return context.format([
|
|
463
673
|
this.visit(lexpr, context),
|
|
464
|
-
this.deparseOperatorName(name),
|
|
674
|
+
this.deparseOperatorName(name, context),
|
|
465
675
|
'ANY',
|
|
466
|
-
|
|
676
|
+
context.parens(this.visit(rexpr, context))
|
|
467
677
|
]);
|
|
468
678
|
case 'AEXPR_OP_ALL':
|
|
469
|
-
return
|
|
679
|
+
return context.format([
|
|
470
680
|
this.visit(lexpr, context),
|
|
471
|
-
this.deparseOperatorName(name),
|
|
681
|
+
this.deparseOperatorName(name, context),
|
|
472
682
|
'ALL',
|
|
473
|
-
|
|
683
|
+
context.parens(this.visit(rexpr, context))
|
|
474
684
|
]);
|
|
475
685
|
case 'AEXPR_DISTINCT': {
|
|
476
686
|
let leftExpr = this.visit(lexpr, context);
|
|
477
687
|
let rightExpr = this.visit(rexpr, context);
|
|
478
688
|
// Add parentheses for complex expressions
|
|
479
689
|
if (lexpr && this.isComplexExpression(lexpr)) {
|
|
480
|
-
leftExpr =
|
|
690
|
+
leftExpr = context.parens(leftExpr);
|
|
481
691
|
}
|
|
482
692
|
if (rexpr && this.isComplexExpression(rexpr)) {
|
|
483
|
-
rightExpr =
|
|
693
|
+
rightExpr = context.parens(rightExpr);
|
|
484
694
|
}
|
|
485
|
-
return
|
|
695
|
+
return context.format([
|
|
486
696
|
leftExpr,
|
|
487
697
|
'IS DISTINCT FROM',
|
|
488
698
|
rightExpr
|
|
@@ -493,75 +703,75 @@ class Deparser {
|
|
|
493
703
|
let rightExpr = this.visit(rexpr, context);
|
|
494
704
|
// Add parentheses for complex expressions
|
|
495
705
|
if (lexpr && this.isComplexExpression(lexpr)) {
|
|
496
|
-
leftExpr =
|
|
706
|
+
leftExpr = context.parens(leftExpr);
|
|
497
707
|
}
|
|
498
708
|
if (rexpr && this.isComplexExpression(rexpr)) {
|
|
499
|
-
rightExpr =
|
|
709
|
+
rightExpr = context.parens(rightExpr);
|
|
500
710
|
}
|
|
501
|
-
return
|
|
711
|
+
return context.format([
|
|
502
712
|
leftExpr,
|
|
503
713
|
'IS NOT DISTINCT FROM',
|
|
504
714
|
rightExpr
|
|
505
715
|
]);
|
|
506
716
|
}
|
|
507
717
|
case 'AEXPR_NULLIF':
|
|
508
|
-
return
|
|
718
|
+
return context.format([
|
|
509
719
|
'NULLIF',
|
|
510
|
-
|
|
720
|
+
context.parens([
|
|
511
721
|
this.visit(lexpr, context),
|
|
512
722
|
this.visit(rexpr, context)
|
|
513
723
|
].join(', '))
|
|
514
724
|
]);
|
|
515
725
|
case 'AEXPR_IN':
|
|
516
|
-
const inOperator = this.deparseOperatorName(name);
|
|
726
|
+
const inOperator = this.deparseOperatorName(name, context);
|
|
517
727
|
if (inOperator === '<>' || inOperator === '!=') {
|
|
518
|
-
return
|
|
728
|
+
return context.format([
|
|
519
729
|
this.visit(lexpr, context),
|
|
520
730
|
'NOT IN',
|
|
521
|
-
|
|
731
|
+
context.parens(this.visit(rexpr, context))
|
|
522
732
|
]);
|
|
523
733
|
}
|
|
524
734
|
else {
|
|
525
|
-
return
|
|
735
|
+
return context.format([
|
|
526
736
|
this.visit(lexpr, context),
|
|
527
737
|
'IN',
|
|
528
|
-
|
|
738
|
+
context.parens(this.visit(rexpr, context))
|
|
529
739
|
]);
|
|
530
740
|
}
|
|
531
741
|
case 'AEXPR_LIKE':
|
|
532
|
-
const likeOp = this.deparseOperatorName(name);
|
|
742
|
+
const likeOp = this.deparseOperatorName(name, context);
|
|
533
743
|
if (likeOp === '!~~') {
|
|
534
|
-
return
|
|
744
|
+
return context.format([
|
|
535
745
|
this.visit(lexpr, context),
|
|
536
746
|
'NOT LIKE',
|
|
537
747
|
this.visit(rexpr, context)
|
|
538
748
|
]);
|
|
539
749
|
}
|
|
540
750
|
else {
|
|
541
|
-
return
|
|
751
|
+
return context.format([
|
|
542
752
|
this.visit(lexpr, context),
|
|
543
753
|
'LIKE',
|
|
544
754
|
this.visit(rexpr, context)
|
|
545
755
|
]);
|
|
546
756
|
}
|
|
547
757
|
case 'AEXPR_ILIKE':
|
|
548
|
-
const ilikeOp = this.deparseOperatorName(name);
|
|
758
|
+
const ilikeOp = this.deparseOperatorName(name, context);
|
|
549
759
|
if (ilikeOp === '!~~*') {
|
|
550
|
-
return
|
|
760
|
+
return context.format([
|
|
551
761
|
this.visit(lexpr, context),
|
|
552
762
|
'NOT ILIKE',
|
|
553
763
|
this.visit(rexpr, context)
|
|
554
764
|
]);
|
|
555
765
|
}
|
|
556
766
|
else {
|
|
557
|
-
return
|
|
767
|
+
return context.format([
|
|
558
768
|
this.visit(lexpr, context),
|
|
559
769
|
'ILIKE',
|
|
560
770
|
this.visit(rexpr, context)
|
|
561
771
|
]);
|
|
562
772
|
}
|
|
563
773
|
case 'AEXPR_SIMILAR':
|
|
564
|
-
const similarOp = this.deparseOperatorName(name);
|
|
774
|
+
const similarOp = this.deparseOperatorName(name, context);
|
|
565
775
|
let rightExpr;
|
|
566
776
|
if (rexpr && 'FuncCall' in rexpr &&
|
|
567
777
|
rexpr.FuncCall?.funcname?.length === 2 &&
|
|
@@ -577,39 +787,39 @@ class Deparser {
|
|
|
577
787
|
rightExpr = this.visit(rexpr, context);
|
|
578
788
|
}
|
|
579
789
|
if (similarOp === '!~') {
|
|
580
|
-
return
|
|
790
|
+
return context.format([
|
|
581
791
|
this.visit(lexpr, context),
|
|
582
792
|
'NOT SIMILAR TO',
|
|
583
793
|
rightExpr
|
|
584
794
|
]);
|
|
585
795
|
}
|
|
586
796
|
else {
|
|
587
|
-
return
|
|
797
|
+
return context.format([
|
|
588
798
|
this.visit(lexpr, context),
|
|
589
799
|
'SIMILAR TO',
|
|
590
800
|
rightExpr
|
|
591
801
|
]);
|
|
592
802
|
}
|
|
593
803
|
case 'AEXPR_BETWEEN':
|
|
594
|
-
return
|
|
804
|
+
return context.format([
|
|
595
805
|
this.visit(lexpr, context),
|
|
596
806
|
'BETWEEN',
|
|
597
807
|
this.visitBetweenRange(rexpr, context)
|
|
598
808
|
]);
|
|
599
809
|
case 'AEXPR_NOT_BETWEEN':
|
|
600
|
-
return
|
|
810
|
+
return context.format([
|
|
601
811
|
this.visit(lexpr, context),
|
|
602
812
|
'NOT BETWEEN',
|
|
603
813
|
this.visitBetweenRange(rexpr, context)
|
|
604
814
|
]);
|
|
605
815
|
case 'AEXPR_BETWEEN_SYM':
|
|
606
|
-
return
|
|
816
|
+
return context.format([
|
|
607
817
|
this.visit(lexpr, context),
|
|
608
818
|
'BETWEEN SYMMETRIC',
|
|
609
819
|
this.visitBetweenRange(rexpr, context)
|
|
610
820
|
]);
|
|
611
821
|
case 'AEXPR_NOT_BETWEEN_SYM':
|
|
612
|
-
return
|
|
822
|
+
return context.format([
|
|
613
823
|
this.visit(lexpr, context),
|
|
614
824
|
'NOT BETWEEN SYMMETRIC',
|
|
615
825
|
this.visitBetweenRange(rexpr, context)
|
|
@@ -617,7 +827,7 @@ class Deparser {
|
|
|
617
827
|
}
|
|
618
828
|
throw new Error(`Unhandled A_Expr kind: ${kind}`);
|
|
619
829
|
}
|
|
620
|
-
deparseOperatorName(name) {
|
|
830
|
+
deparseOperatorName(name, context) {
|
|
621
831
|
if (!name || name.length === 0) {
|
|
622
832
|
return '';
|
|
623
833
|
}
|
|
@@ -625,7 +835,7 @@ class Deparser {
|
|
|
625
835
|
if (n.String) {
|
|
626
836
|
return n.String.sval || n.String.str;
|
|
627
837
|
}
|
|
628
|
-
return this.visit(n,
|
|
838
|
+
return this.visit(n, context);
|
|
629
839
|
});
|
|
630
840
|
if (parts.length > 1) {
|
|
631
841
|
return `OPERATOR(${parts.join('.')})`;
|
|
@@ -688,6 +898,64 @@ class Deparser {
|
|
|
688
898
|
node.SubLink ||
|
|
689
899
|
node.A_Expr);
|
|
690
900
|
}
|
|
901
|
+
isComplexSelectTarget(node) {
|
|
902
|
+
if (!node)
|
|
903
|
+
return false;
|
|
904
|
+
if (node.ResTarget?.val) {
|
|
905
|
+
return this.isComplexExpression(node.ResTarget.val);
|
|
906
|
+
}
|
|
907
|
+
// Always complex: CASE expressions
|
|
908
|
+
if (node.CaseExpr)
|
|
909
|
+
return true;
|
|
910
|
+
// Always complex: Subqueries and subselects
|
|
911
|
+
if (node.SubLink)
|
|
912
|
+
return true;
|
|
913
|
+
// Always complex: Boolean tests and expressions
|
|
914
|
+
if (node.NullTest || node.BooleanTest || node.BoolExpr)
|
|
915
|
+
return true;
|
|
916
|
+
// COALESCE and similar functions - complex if multiple arguments
|
|
917
|
+
if (node.CoalesceExpr) {
|
|
918
|
+
const args = node.CoalesceExpr.args;
|
|
919
|
+
if (args && Array.isArray(args) && args.length > 1)
|
|
920
|
+
return true;
|
|
921
|
+
}
|
|
922
|
+
// Function calls - complex if multiple args or has clauses
|
|
923
|
+
if (node.FuncCall) {
|
|
924
|
+
const funcCall = node.FuncCall;
|
|
925
|
+
const args = funcCall.args ? (Array.isArray(funcCall.args) ? funcCall.args : [funcCall.args]) : [];
|
|
926
|
+
// Complex if has window clause, filter, order by, etc.
|
|
927
|
+
if (funcCall.over || funcCall.agg_filter || funcCall.agg_order || funcCall.agg_distinct) {
|
|
928
|
+
return true;
|
|
929
|
+
}
|
|
930
|
+
// Complex if multiple arguments
|
|
931
|
+
if (args.length > 1)
|
|
932
|
+
return true;
|
|
933
|
+
if (args.length === 1) {
|
|
934
|
+
return this.isComplexSelectTarget(args[0]);
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
if (node.A_Expr) {
|
|
938
|
+
const expr = node.A_Expr;
|
|
939
|
+
// Check if operands are complex
|
|
940
|
+
if (expr.lexpr && this.isComplexSelectTarget(expr.lexpr))
|
|
941
|
+
return true;
|
|
942
|
+
if (expr.rexpr && this.isComplexSelectTarget(expr.rexpr))
|
|
943
|
+
return true;
|
|
944
|
+
return false;
|
|
945
|
+
}
|
|
946
|
+
if (node.TypeCast) {
|
|
947
|
+
return this.isComplexSelectTarget(node.TypeCast.arg);
|
|
948
|
+
}
|
|
949
|
+
if (node.A_ArrayExpr)
|
|
950
|
+
return true;
|
|
951
|
+
if (node.A_Indirection) {
|
|
952
|
+
return this.isComplexSelectTarget(node.A_Indirection.arg);
|
|
953
|
+
}
|
|
954
|
+
if (node.A_Const || node.ColumnRef || node.ParamRef || node.A_Star) {
|
|
955
|
+
return false;
|
|
956
|
+
}
|
|
957
|
+
return false;
|
|
958
|
+
}
|
|
691
959
|
visitBetweenRange(rexpr, context) {
|
|
692
960
|
if (rexpr && 'List' in rexpr && rexpr.List?.items) {
|
|
693
961
|
const items = rexpr.List.items.map((item) => this.visit(item, context));
|
|
@@ -704,9 +972,16 @@ class Deparser {
|
|
|
704
972
|
output.push(this.RangeVar(node.relation, context));
|
|
705
973
|
if (node.cols) {
|
|
706
974
|
const cols = list_utils_1.ListUtils.unwrapList(node.cols);
|
|
707
|
-
const insertContext =
|
|
975
|
+
const insertContext = context.spawn('InsertStmt', { insertColumns: true });
|
|
708
976
|
const columnNames = cols.map(col => this.visit(col, insertContext));
|
|
709
|
-
|
|
977
|
+
if (context.isPretty()) {
|
|
978
|
+
// Always format columns in multiline parentheses for pretty printing
|
|
979
|
+
const indentedColumns = columnNames.map(col => context.indent(col));
|
|
980
|
+
output.push('(\n' + indentedColumns.join(',\n') + '\n)');
|
|
981
|
+
}
|
|
982
|
+
else {
|
|
983
|
+
output.push(context.parens(columnNames.join(', ')));
|
|
984
|
+
}
|
|
710
985
|
}
|
|
711
986
|
if (node.selectStmt) {
|
|
712
987
|
output.push(this.visit(node.selectStmt, context));
|
|
@@ -727,7 +1002,7 @@ class Deparser {
|
|
|
727
1002
|
else if (infer.indexElems) {
|
|
728
1003
|
const elems = list_utils_1.ListUtils.unwrapList(infer.indexElems);
|
|
729
1004
|
const indexElems = elems.map(elem => this.visit(elem, context));
|
|
730
|
-
output.push(
|
|
1005
|
+
output.push(context.parens(indexElems.join(', ')));
|
|
731
1006
|
}
|
|
732
1007
|
// Handle WHERE clause for conflict detection
|
|
733
1008
|
if (infer.whereClause) {
|
|
@@ -743,12 +1018,12 @@ class Deparser {
|
|
|
743
1018
|
if (firstTarget.ResTarget?.val?.MultiAssignRef && targetList.every(target => target.ResTarget?.val?.MultiAssignRef)) {
|
|
744
1019
|
const sortedTargets = targetList.sort((a, b) => a.ResTarget.val.MultiAssignRef.colno - b.ResTarget.val.MultiAssignRef.colno);
|
|
745
1020
|
const names = sortedTargets.map(target => target.ResTarget.name);
|
|
746
|
-
output.push(
|
|
1021
|
+
output.push(context.parens(names.join(', ')));
|
|
747
1022
|
output.push('=');
|
|
748
1023
|
output.push(this.visit(firstTarget.ResTarget.val.MultiAssignRef.source, context));
|
|
749
1024
|
}
|
|
750
1025
|
else {
|
|
751
|
-
const updateContext =
|
|
1026
|
+
const updateContext = context.spawn('UpdateStmt', { update: true });
|
|
752
1027
|
const targets = targetList.map(target => this.visit(target, updateContext));
|
|
753
1028
|
output.push(targets.join(', '));
|
|
754
1029
|
}
|
|
@@ -802,12 +1077,12 @@ class Deparser {
|
|
|
802
1077
|
}
|
|
803
1078
|
}
|
|
804
1079
|
const names = relatedTargets.map(t => t.ResTarget.name);
|
|
805
|
-
const multiAssignment = `${
|
|
1080
|
+
const multiAssignment = `${context.parens(names.join(', '))} = ${this.visit(multiAssignRef.source, context)}`;
|
|
806
1081
|
assignmentParts.push(multiAssignment);
|
|
807
1082
|
}
|
|
808
1083
|
else {
|
|
809
1084
|
// Handle regular single-column assignment
|
|
810
|
-
assignmentParts.push(this.visit(target,
|
|
1085
|
+
assignmentParts.push(this.visit(target, context.spawn('UpdateStmt', { update: true })));
|
|
811
1086
|
processedTargets.add(i);
|
|
812
1087
|
}
|
|
813
1088
|
}
|
|
@@ -899,14 +1174,14 @@ class Deparser {
|
|
|
899
1174
|
}
|
|
900
1175
|
if (node.ctes && node.ctes.length > 0) {
|
|
901
1176
|
const ctes = list_utils_1.ListUtils.unwrapList(node.ctes);
|
|
902
|
-
if (
|
|
1177
|
+
if (context.isPretty()) {
|
|
903
1178
|
const cteStrings = ctes.map((cte, index) => {
|
|
904
1179
|
const cteStr = this.visit(cte, context);
|
|
905
|
-
const prefix = index === 0 ?
|
|
1180
|
+
const prefix = index === 0 ? context.newline() : ',' + context.newline();
|
|
906
1181
|
if (this.containsMultilineStringLiteral(cteStr)) {
|
|
907
1182
|
return prefix + cteStr;
|
|
908
1183
|
}
|
|
909
|
-
return prefix +
|
|
1184
|
+
return prefix + context.indent(cteStr);
|
|
910
1185
|
});
|
|
911
1186
|
output.push(cteStrings.join(''));
|
|
912
1187
|
}
|
|
@@ -992,14 +1267,14 @@ class Deparser {
|
|
|
992
1267
|
if (context.bool) {
|
|
993
1268
|
formatStr = '(%s)';
|
|
994
1269
|
}
|
|
995
|
-
const boolContext =
|
|
1270
|
+
const boolContext = context.spawn('BoolExpr', { bool: true });
|
|
996
1271
|
// explanation of our syntax/fix below:
|
|
997
1272
|
// return formatStr.replace('%s', andArgs); // ❌ Interprets $ as special syntax
|
|
998
1273
|
// return formatStr.replace('%s', () => andArgs); // ✅ Function callback prevents interpretation
|
|
999
1274
|
switch (boolop) {
|
|
1000
1275
|
case 'AND_EXPR':
|
|
1001
|
-
if (
|
|
1002
|
-
const andArgs = args.map(arg => this.visit(arg, boolContext)).join(
|
|
1276
|
+
if (context.isPretty() && args.length > 1) {
|
|
1277
|
+
const andArgs = args.map(arg => this.visit(arg, boolContext)).join(context.newline() + context.indent('AND '));
|
|
1003
1278
|
return formatStr.replace('%s', () => andArgs);
|
|
1004
1279
|
}
|
|
1005
1280
|
else {
|
|
@@ -1007,8 +1282,8 @@ class Deparser {
|
|
|
1007
1282
|
return formatStr.replace('%s', () => andArgs);
|
|
1008
1283
|
}
|
|
1009
1284
|
case 'OR_EXPR':
|
|
1010
|
-
if (
|
|
1011
|
-
const orArgs = args.map(arg => this.visit(arg, boolContext)).join(
|
|
1285
|
+
if (context.isPretty() && args.length > 1) {
|
|
1286
|
+
const orArgs = args.map(arg => this.visit(arg, boolContext)).join(context.newline() + context.indent('OR '));
|
|
1012
1287
|
return formatStr.replace('%s', () => orArgs);
|
|
1013
1288
|
}
|
|
1014
1289
|
else {
|
|
@@ -1139,9 +1414,9 @@ class Deparser {
|
|
|
1139
1414
|
const timezone = this.visit(args[0], context);
|
|
1140
1415
|
// Add parentheses around timestamp if it contains arithmetic operations
|
|
1141
1416
|
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));
|
|
1417
|
+
const op = this.deparseOperatorName(list_utils_1.ListUtils.unwrapList(args[1].A_Expr.name), context);
|
|
1143
1418
|
if (op === '+' || op === '-' || op === '*' || op === '/') {
|
|
1144
|
-
timestamp =
|
|
1419
|
+
timestamp = context.parens(timestamp);
|
|
1145
1420
|
}
|
|
1146
1421
|
}
|
|
1147
1422
|
return `${timestamp} AT TIME ZONE ${timezone}`;
|
|
@@ -1211,14 +1486,14 @@ class Deparser {
|
|
|
1211
1486
|
windowParts.push(`ORDER BY ${orderStrs.join(', ')}`);
|
|
1212
1487
|
}
|
|
1213
1488
|
// Handle window frame specifications using the dedicated formatWindowFrame method
|
|
1214
|
-
const frameClause = this.formatWindowFrame(node.over);
|
|
1489
|
+
const frameClause = this.formatWindowFrame(node.over, context.spawn('FuncCall'));
|
|
1215
1490
|
if (frameClause) {
|
|
1216
1491
|
windowParts.push(frameClause);
|
|
1217
1492
|
}
|
|
1218
1493
|
if (windowParts.length > 0) {
|
|
1219
|
-
if (
|
|
1220
|
-
const formattedParts = windowParts.map(part =>
|
|
1221
|
-
result += ` OVER (${
|
|
1494
|
+
if (context.isPretty() && windowParts.length > 1) {
|
|
1495
|
+
const formattedParts = windowParts.map(part => context.indent(part));
|
|
1496
|
+
result += ` OVER (${context.newline()}${formattedParts.join(context.newline())}${context.newline()})`;
|
|
1222
1497
|
}
|
|
1223
1498
|
else {
|
|
1224
1499
|
result += ` OVER (${windowParts.join(' ')})`;
|
|
@@ -1498,9 +1773,6 @@ class Deparser {
|
|
|
1498
1773
|
return output.join(' ');
|
|
1499
1774
|
}
|
|
1500
1775
|
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
1776
|
let typeName = `${catalog}.${type}`;
|
|
1505
1777
|
if (type === 'bpchar' && args) {
|
|
1506
1778
|
typeName = 'char';
|
|
@@ -1557,6 +1829,24 @@ class Deparser {
|
|
|
1557
1829
|
typeName = 'time with time zone';
|
|
1558
1830
|
}
|
|
1559
1831
|
}
|
|
1832
|
+
else if (type === 'timestamp') {
|
|
1833
|
+
if (args) {
|
|
1834
|
+
typeName = `timestamp(${args})`;
|
|
1835
|
+
args = null; // Don't apply args again in mods()
|
|
1836
|
+
}
|
|
1837
|
+
else {
|
|
1838
|
+
typeName = 'timestamp';
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
else if (type === 'time') {
|
|
1842
|
+
if (args) {
|
|
1843
|
+
typeName = `time(${args})`;
|
|
1844
|
+
args = null; // Don't apply args again in mods()
|
|
1845
|
+
}
|
|
1846
|
+
else {
|
|
1847
|
+
typeName = 'time';
|
|
1848
|
+
}
|
|
1849
|
+
}
|
|
1560
1850
|
let result = mods(typeName, args);
|
|
1561
1851
|
if (node.arrayBounds && node.arrayBounds.length > 0) {
|
|
1562
1852
|
result += formatArrayBounds(node.arrayBounds);
|
|
@@ -1586,7 +1876,7 @@ class Deparser {
|
|
|
1586
1876
|
}
|
|
1587
1877
|
return this.quoteIfNeeded(colStr);
|
|
1588
1878
|
});
|
|
1589
|
-
output.push('AS', this.quoteIfNeeded(name) +
|
|
1879
|
+
output.push('AS', this.quoteIfNeeded(name) + context.parens(quotedColnames.join(', ')));
|
|
1590
1880
|
}
|
|
1591
1881
|
else {
|
|
1592
1882
|
output.push('AS', this.quoteIfNeeded(name));
|
|
@@ -1598,7 +1888,7 @@ class Deparser {
|
|
|
1598
1888
|
// Handle ONLY keyword for inheritance control (but not for type definitions, ALTER TYPE, or CREATE FOREIGN TABLE)
|
|
1599
1889
|
if (node && (!('inh' in node) || node.inh === undefined) &&
|
|
1600
1890
|
!context.parentNodeTypes.includes('CompositeTypeStmt') &&
|
|
1601
|
-
!context.parentNodeTypes.includes('AlterTypeStmt') &&
|
|
1891
|
+
(!context.parentNodeTypes.includes('AlterTypeStmt') && context.objtype !== 'OBJECT_TYPE') &&
|
|
1602
1892
|
!context.parentNodeTypes.includes('CreateForeignTableStmt')) {
|
|
1603
1893
|
output.push('ONLY');
|
|
1604
1894
|
}
|
|
@@ -1795,6 +2085,18 @@ class Deparser {
|
|
|
1795
2085
|
return `pg_catalog.${typeName}`;
|
|
1796
2086
|
}
|
|
1797
2087
|
}
|
|
2088
|
+
isPgCatalogType(typeName) {
|
|
2089
|
+
const cleanTypeName = typeName.replace(/^pg_catalog\./, '');
|
|
2090
|
+
if (pgCatalogTypes.includes(cleanTypeName)) {
|
|
2091
|
+
return true;
|
|
2092
|
+
}
|
|
2093
|
+
for (const [realType, aliases] of pgCatalogTypeAliases) {
|
|
2094
|
+
if (aliases.includes(cleanTypeName)) {
|
|
2095
|
+
return true;
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
return false;
|
|
2099
|
+
}
|
|
1798
2100
|
A_ArrayExpr(node, context) {
|
|
1799
2101
|
const elements = list_utils_1.ListUtils.unwrapList(node.elements);
|
|
1800
2102
|
const elementStrs = elements.map(el => this.visit(el, context));
|
|
@@ -1846,26 +2148,26 @@ class Deparser {
|
|
|
1846
2148
|
output.push(this.visit(node.arg, context));
|
|
1847
2149
|
}
|
|
1848
2150
|
const args = list_utils_1.ListUtils.unwrapList(node.args);
|
|
1849
|
-
if (
|
|
2151
|
+
if (context.isPretty() && args.length > 0) {
|
|
1850
2152
|
for (const arg of args) {
|
|
1851
2153
|
const whenClause = this.visit(arg, context);
|
|
1852
2154
|
if (this.containsMultilineStringLiteral(whenClause)) {
|
|
1853
|
-
output.push(
|
|
2155
|
+
output.push(context.newline() + whenClause);
|
|
1854
2156
|
}
|
|
1855
2157
|
else {
|
|
1856
|
-
output.push(
|
|
2158
|
+
output.push(context.newline() + context.indent(whenClause));
|
|
1857
2159
|
}
|
|
1858
2160
|
}
|
|
1859
2161
|
if (node.defresult) {
|
|
1860
2162
|
const elseResult = this.visit(node.defresult, context);
|
|
1861
2163
|
if (this.containsMultilineStringLiteral(elseResult)) {
|
|
1862
|
-
output.push(
|
|
2164
|
+
output.push(context.newline() + 'ELSE ' + elseResult);
|
|
1863
2165
|
}
|
|
1864
2166
|
else {
|
|
1865
|
-
output.push(
|
|
2167
|
+
output.push(context.newline() + context.indent('ELSE ' + elseResult));
|
|
1866
2168
|
}
|
|
1867
2169
|
}
|
|
1868
|
-
output.push(
|
|
2170
|
+
output.push(context.newline() + 'END');
|
|
1869
2171
|
return output.join(' ');
|
|
1870
2172
|
}
|
|
1871
2173
|
else {
|
|
@@ -1888,28 +2190,32 @@ class Deparser {
|
|
|
1888
2190
|
TypeCast(node, context) {
|
|
1889
2191
|
const arg = this.visit(node.arg, context);
|
|
1890
2192
|
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
|
-
|
|
2193
|
+
// Check if this is a bpchar typecast that should preserve original syntax for AST consistency
|
|
2194
|
+
if (typeName === 'bpchar' || typeName === 'pg_catalog.bpchar') {
|
|
2195
|
+
const names = node.typeName?.names;
|
|
2196
|
+
const isQualifiedBpchar = names && names.length === 2 &&
|
|
2197
|
+
names[0]?.String?.sval === 'pg_catalog' &&
|
|
2198
|
+
names[1]?.String?.sval === 'bpchar';
|
|
2199
|
+
if (isQualifiedBpchar) {
|
|
2200
|
+
return `CAST(${arg} AS ${typeName})`;
|
|
1898
2201
|
}
|
|
1899
2202
|
}
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
2203
|
+
if (this.isPgCatalogType(typeName)) {
|
|
2204
|
+
const argType = this.getNodeType(node.arg);
|
|
2205
|
+
const isSimpleArgument = argType === 'A_Const' || argType === 'ColumnRef';
|
|
2206
|
+
const isFunctionCall = argType === 'FuncCall';
|
|
2207
|
+
if (isSimpleArgument || isFunctionCall) {
|
|
2208
|
+
// For simple arguments, avoid :: syntax if they have complex structure
|
|
2209
|
+
const shouldUseCastSyntax = isSimpleArgument && (arg.includes('(') || arg.startsWith('-'));
|
|
2210
|
+
if (!shouldUseCastSyntax) {
|
|
2211
|
+
const cleanTypeName = typeName.replace('pg_catalog.', '');
|
|
2212
|
+
// Wrap FuncCall arguments in parentheses to prevent operator precedence issues
|
|
2213
|
+
if (isFunctionCall) {
|
|
2214
|
+
return `${context.parens(arg)}::${cleanTypeName}`;
|
|
2215
|
+
}
|
|
2216
|
+
return `${arg}::${cleanTypeName}`;
|
|
2217
|
+
}
|
|
2218
|
+
}
|
|
1913
2219
|
}
|
|
1914
2220
|
return `CAST(${arg} AS ${typeName})`;
|
|
1915
2221
|
}
|
|
@@ -1932,7 +2238,7 @@ class Deparser {
|
|
|
1932
2238
|
}
|
|
1933
2239
|
BooleanTest(node, context) {
|
|
1934
2240
|
const output = [];
|
|
1935
|
-
const boolContext =
|
|
2241
|
+
const boolContext = context.spawn('BooleanTest', { bool: true });
|
|
1936
2242
|
output.push(this.visit(node.arg, boolContext));
|
|
1937
2243
|
switch (node.booltesttype) {
|
|
1938
2244
|
case 'IS_TRUE':
|
|
@@ -2083,24 +2389,31 @@ class Deparser {
|
|
|
2083
2389
|
const elementStrs = elements.map(el => {
|
|
2084
2390
|
return this.deparse(el, context);
|
|
2085
2391
|
});
|
|
2086
|
-
output.push(
|
|
2392
|
+
output.push(context.parens(elementStrs.join(', ')));
|
|
2087
2393
|
}
|
|
2088
2394
|
}
|
|
2089
2395
|
else if (node.tableElts) {
|
|
2090
2396
|
const elements = list_utils_1.ListUtils.unwrapList(node.tableElts);
|
|
2091
2397
|
const elementStrs = elements.map(el => {
|
|
2092
|
-
return this.deparse(el, context);
|
|
2398
|
+
return this.deparse(el, context.spawn('CreateStmt'));
|
|
2093
2399
|
});
|
|
2094
|
-
if (
|
|
2095
|
-
const formattedElements = elementStrs.map(el =>
|
|
2096
|
-
|
|
2400
|
+
if (context.isPretty()) {
|
|
2401
|
+
const formattedElements = elementStrs.map(el => {
|
|
2402
|
+
const trimmedEl = el.trim();
|
|
2403
|
+
// Remove leading newlines from constraint elements to avoid extra blank lines
|
|
2404
|
+
if (trimmedEl.startsWith('\n')) {
|
|
2405
|
+
return context.indent(trimmedEl.substring(1));
|
|
2406
|
+
}
|
|
2407
|
+
return context.indent(trimmedEl);
|
|
2408
|
+
}).join(',' + context.newline());
|
|
2409
|
+
output.push('(' + context.newline() + formattedElements + context.newline() + ')');
|
|
2097
2410
|
}
|
|
2098
2411
|
else {
|
|
2099
|
-
output.push(
|
|
2412
|
+
output.push(context.parens(elementStrs.join(', ')));
|
|
2100
2413
|
}
|
|
2101
2414
|
}
|
|
2102
2415
|
else if (!node.partbound) {
|
|
2103
|
-
output.push(
|
|
2416
|
+
output.push(context.parens(''));
|
|
2104
2417
|
}
|
|
2105
2418
|
if (node.partbound && node.inhRelations && node.inhRelations.length > 0) {
|
|
2106
2419
|
output.push('PARTITION OF');
|
|
@@ -2143,7 +2456,7 @@ class Deparser {
|
|
|
2143
2456
|
output.push('INHERITS');
|
|
2144
2457
|
const inherits = list_utils_1.ListUtils.unwrapList(node.inhRelations);
|
|
2145
2458
|
const inheritStrs = inherits.map(rel => this.visit(rel, context));
|
|
2146
|
-
output.push(
|
|
2459
|
+
output.push(context.parens(inheritStrs.join(', ')));
|
|
2147
2460
|
}
|
|
2148
2461
|
if (node.partspec) {
|
|
2149
2462
|
output.push('PARTITION BY');
|
|
@@ -2181,7 +2494,7 @@ class Deparser {
|
|
|
2181
2494
|
}
|
|
2182
2495
|
// Handle table options like WITH (fillfactor=10)
|
|
2183
2496
|
if (node.options && node.options.length > 0) {
|
|
2184
|
-
const createStmtContext =
|
|
2497
|
+
const createStmtContext = context.spawn('CreateStmt');
|
|
2185
2498
|
const optionStrs = node.options.map((option) => {
|
|
2186
2499
|
return this.deparse(option, createStmtContext);
|
|
2187
2500
|
});
|
|
@@ -2204,7 +2517,7 @@ class Deparser {
|
|
|
2204
2517
|
}
|
|
2205
2518
|
if (node.fdwoptions && node.fdwoptions.length > 0) {
|
|
2206
2519
|
output.push('OPTIONS');
|
|
2207
|
-
const columnContext =
|
|
2520
|
+
const columnContext = context.spawn('ColumnDef');
|
|
2208
2521
|
const options = list_utils_1.ListUtils.unwrapList(node.fdwoptions).map(opt => this.visit(opt, columnContext));
|
|
2209
2522
|
output.push(`(${options.join(', ')})`);
|
|
2210
2523
|
}
|
|
@@ -2214,7 +2527,7 @@ class Deparser {
|
|
|
2214
2527
|
if (node.constraints) {
|
|
2215
2528
|
const constraints = list_utils_1.ListUtils.unwrapList(node.constraints);
|
|
2216
2529
|
const constraintStrs = constraints.map(constraint => {
|
|
2217
|
-
const columnConstraintContext =
|
|
2530
|
+
const columnConstraintContext = context.spawn('ColumnDef', { isColumnConstraint: true });
|
|
2218
2531
|
return this.visit(constraint, columnConstraintContext);
|
|
2219
2532
|
});
|
|
2220
2533
|
output.push(...constraintStrs);
|
|
@@ -2254,9 +2567,25 @@ class Deparser {
|
|
|
2254
2567
|
}
|
|
2255
2568
|
break;
|
|
2256
2569
|
case 'CONSTR_CHECK':
|
|
2257
|
-
|
|
2570
|
+
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2571
|
+
output.push('\n' + context.indent('CHECK'));
|
|
2572
|
+
}
|
|
2573
|
+
else {
|
|
2574
|
+
output.push('CHECK');
|
|
2575
|
+
}
|
|
2258
2576
|
if (node.raw_expr) {
|
|
2259
|
-
|
|
2577
|
+
if (context.isPretty()) {
|
|
2578
|
+
const checkExpr = this.visit(node.raw_expr, context);
|
|
2579
|
+
if (checkExpr.includes('\n')) {
|
|
2580
|
+
output.push('(\n' + context.indent(checkExpr) + '\n)');
|
|
2581
|
+
}
|
|
2582
|
+
else {
|
|
2583
|
+
output.push(`(${checkExpr})`);
|
|
2584
|
+
}
|
|
2585
|
+
}
|
|
2586
|
+
else {
|
|
2587
|
+
output.push(context.parens(this.visit(node.raw_expr, context)));
|
|
2588
|
+
}
|
|
2260
2589
|
}
|
|
2261
2590
|
// Handle NOT VALID for check constraints
|
|
2262
2591
|
if (node.skip_validation) {
|
|
@@ -2277,7 +2606,7 @@ class Deparser {
|
|
|
2277
2606
|
}
|
|
2278
2607
|
output.push('AS');
|
|
2279
2608
|
if (node.raw_expr) {
|
|
2280
|
-
output.push(
|
|
2609
|
+
output.push(context.parens(this.visit(node.raw_expr, context)));
|
|
2281
2610
|
}
|
|
2282
2611
|
output.push('STORED');
|
|
2283
2612
|
break;
|
|
@@ -2295,30 +2624,61 @@ class Deparser {
|
|
|
2295
2624
|
.map(option => {
|
|
2296
2625
|
if (option.DefElem) {
|
|
2297
2626
|
const defElem = option.DefElem;
|
|
2298
|
-
|
|
2299
|
-
|
|
2627
|
+
if (defElem.defname === 'sequence_name') {
|
|
2628
|
+
if (defElem.arg && defElem.arg.List) {
|
|
2629
|
+
const nameList = list_utils_1.ListUtils.unwrapList(defElem.arg)
|
|
2630
|
+
.map(item => this.visit(item, context))
|
|
2631
|
+
.join('.');
|
|
2632
|
+
return `SEQUENCE NAME ${nameList}`;
|
|
2633
|
+
}
|
|
2634
|
+
return 'SEQUENCE NAME';
|
|
2635
|
+
}
|
|
2636
|
+
else if (defElem.defname === 'start') {
|
|
2637
|
+
const argValue = defElem.arg ? this.visit(defElem.arg, context) : '';
|
|
2300
2638
|
return `START WITH ${argValue}`;
|
|
2301
2639
|
}
|
|
2302
2640
|
else if (defElem.defname === 'increment') {
|
|
2641
|
+
const argValue = defElem.arg ? this.visit(defElem.arg, context) : '';
|
|
2303
2642
|
return `INCREMENT BY ${argValue}`;
|
|
2304
2643
|
}
|
|
2305
2644
|
else if (defElem.defname === 'minvalue') {
|
|
2306
|
-
|
|
2645
|
+
if (defElem.arg) {
|
|
2646
|
+
const argValue = this.visit(defElem.arg, context);
|
|
2647
|
+
return `MINVALUE ${argValue}`;
|
|
2648
|
+
}
|
|
2649
|
+
else {
|
|
2650
|
+
return 'NO MINVALUE';
|
|
2651
|
+
}
|
|
2307
2652
|
}
|
|
2308
2653
|
else if (defElem.defname === 'maxvalue') {
|
|
2309
|
-
|
|
2654
|
+
if (defElem.arg) {
|
|
2655
|
+
const argValue = this.visit(defElem.arg, context);
|
|
2656
|
+
return `MAXVALUE ${argValue}`;
|
|
2657
|
+
}
|
|
2658
|
+
else {
|
|
2659
|
+
return 'NO MAXVALUE';
|
|
2660
|
+
}
|
|
2310
2661
|
}
|
|
2311
2662
|
else if (defElem.defname === 'cache') {
|
|
2663
|
+
const argValue = defElem.arg ? this.visit(defElem.arg, context) : '';
|
|
2312
2664
|
return `CACHE ${argValue}`;
|
|
2313
2665
|
}
|
|
2314
2666
|
else if (defElem.defname === 'cycle') {
|
|
2667
|
+
const argValue = defElem.arg ? this.visit(defElem.arg, context) : '';
|
|
2315
2668
|
return argValue === 'true' ? 'CYCLE' : 'NO CYCLE';
|
|
2316
2669
|
}
|
|
2670
|
+
const argValue = defElem.arg ? this.visit(defElem.arg, context) : '';
|
|
2317
2671
|
return `${defElem.defname.toUpperCase()} ${argValue}`;
|
|
2318
2672
|
}
|
|
2319
2673
|
return this.visit(option, context);
|
|
2320
2674
|
});
|
|
2321
|
-
|
|
2675
|
+
if (context.isPretty()) {
|
|
2676
|
+
const indentedOptions = optionStrs.map(option => context.indent(option));
|
|
2677
|
+
output.push('(\n' + indentedOptions.join('\n') + '\n)');
|
|
2678
|
+
}
|
|
2679
|
+
else {
|
|
2680
|
+
output.push(`(${optionStrs.join(' ')})`);
|
|
2681
|
+
}
|
|
2322
2682
|
}
|
|
2323
2683
|
break;
|
|
2324
2684
|
case 'CONSTR_PRIMARY':
|
|
@@ -2335,7 +2695,12 @@ class Deparser {
|
|
|
2335
2695
|
}
|
|
2336
2696
|
break;
|
|
2337
2697
|
case 'CONSTR_UNIQUE':
|
|
2338
|
-
|
|
2698
|
+
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2699
|
+
output.push('\n' + context.indent('UNIQUE'));
|
|
2700
|
+
}
|
|
2701
|
+
else {
|
|
2702
|
+
output.push('UNIQUE');
|
|
2703
|
+
}
|
|
2339
2704
|
if (node.nulls_not_distinct) {
|
|
2340
2705
|
output.push('NULLS NOT DISTINCT');
|
|
2341
2706
|
}
|
|
@@ -2353,33 +2718,77 @@ class Deparser {
|
|
|
2353
2718
|
case 'CONSTR_FOREIGN':
|
|
2354
2719
|
// Only add "FOREIGN KEY" for table-level constraints, not column-level constraints
|
|
2355
2720
|
if (!context.isColumnConstraint) {
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2721
|
+
if (context.isPretty()) {
|
|
2722
|
+
output.push('\n' + context.indent('FOREIGN KEY'));
|
|
2723
|
+
if (node.fk_attrs && node.fk_attrs.length > 0) {
|
|
2724
|
+
const fkAttrs = list_utils_1.ListUtils.unwrapList(node.fk_attrs)
|
|
2725
|
+
.map(attr => this.visit(attr, context))
|
|
2726
|
+
.join(', ');
|
|
2727
|
+
output.push(`(${fkAttrs})`);
|
|
2728
|
+
}
|
|
2729
|
+
output.push('\n' + context.indent('REFERENCES'));
|
|
2362
2730
|
}
|
|
2731
|
+
else {
|
|
2732
|
+
output.push('FOREIGN KEY');
|
|
2733
|
+
if (node.fk_attrs && node.fk_attrs.length > 0) {
|
|
2734
|
+
const fkAttrs = list_utils_1.ListUtils.unwrapList(node.fk_attrs)
|
|
2735
|
+
.map(attr => this.visit(attr, context))
|
|
2736
|
+
.join(', ');
|
|
2737
|
+
output.push(`(${fkAttrs})`);
|
|
2738
|
+
}
|
|
2739
|
+
output.push('REFERENCES');
|
|
2740
|
+
}
|
|
2741
|
+
}
|
|
2742
|
+
else {
|
|
2743
|
+
output.push('REFERENCES');
|
|
2363
2744
|
}
|
|
2364
|
-
output.push('REFERENCES');
|
|
2365
2745
|
if (node.pktable) {
|
|
2366
|
-
|
|
2746
|
+
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2747
|
+
const lastIndex = output.length - 1;
|
|
2748
|
+
if (lastIndex >= 0 && output[lastIndex].includes('REFERENCES')) {
|
|
2749
|
+
output[lastIndex] += ' ' + this.RangeVar(node.pktable, context);
|
|
2750
|
+
}
|
|
2751
|
+
else {
|
|
2752
|
+
output.push(this.RangeVar(node.pktable, context));
|
|
2753
|
+
}
|
|
2754
|
+
}
|
|
2755
|
+
else {
|
|
2756
|
+
output.push(this.RangeVar(node.pktable, context));
|
|
2757
|
+
}
|
|
2367
2758
|
}
|
|
2368
2759
|
if (node.pk_attrs && node.pk_attrs.length > 0) {
|
|
2369
2760
|
const pkAttrs = list_utils_1.ListUtils.unwrapList(node.pk_attrs)
|
|
2370
2761
|
.map(attr => this.visit(attr, context))
|
|
2371
2762
|
.join(', ');
|
|
2372
|
-
|
|
2763
|
+
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2764
|
+
const lastIndex = output.length - 1;
|
|
2765
|
+
if (lastIndex >= 0) {
|
|
2766
|
+
output[lastIndex] += ` (${pkAttrs})`;
|
|
2767
|
+
}
|
|
2768
|
+
else {
|
|
2769
|
+
output.push(`(${pkAttrs})`);
|
|
2770
|
+
}
|
|
2771
|
+
}
|
|
2772
|
+
else {
|
|
2773
|
+
output.push(`(${pkAttrs})`);
|
|
2774
|
+
}
|
|
2373
2775
|
}
|
|
2374
2776
|
if (node.fk_matchtype && node.fk_matchtype !== 's') {
|
|
2777
|
+
let matchClause = '';
|
|
2375
2778
|
switch (node.fk_matchtype) {
|
|
2376
2779
|
case 'f':
|
|
2377
|
-
|
|
2780
|
+
matchClause = 'MATCH FULL';
|
|
2378
2781
|
break;
|
|
2379
2782
|
case 'p':
|
|
2380
|
-
|
|
2783
|
+
matchClause = 'MATCH PARTIAL';
|
|
2381
2784
|
break;
|
|
2382
2785
|
}
|
|
2786
|
+
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2787
|
+
output.push('\n' + context.indent(matchClause));
|
|
2788
|
+
}
|
|
2789
|
+
else {
|
|
2790
|
+
output.push(matchClause);
|
|
2791
|
+
}
|
|
2383
2792
|
}
|
|
2384
2793
|
if (node.fk_upd_action && node.fk_upd_action !== 'a') {
|
|
2385
2794
|
let updateClause = 'ON UPDATE ';
|
|
@@ -2397,8 +2806,8 @@ class Deparser {
|
|
|
2397
2806
|
updateClause += 'SET DEFAULT';
|
|
2398
2807
|
break;
|
|
2399
2808
|
}
|
|
2400
|
-
if (
|
|
2401
|
-
output.push('\n' +
|
|
2809
|
+
if (context.isPretty()) {
|
|
2810
|
+
output.push('\n' + context.indent(updateClause));
|
|
2402
2811
|
}
|
|
2403
2812
|
else {
|
|
2404
2813
|
output.push('ON UPDATE');
|
|
@@ -2421,8 +2830,8 @@ class Deparser {
|
|
|
2421
2830
|
deleteClause += 'SET DEFAULT';
|
|
2422
2831
|
break;
|
|
2423
2832
|
}
|
|
2424
|
-
if (
|
|
2425
|
-
output.push('\n' +
|
|
2833
|
+
if (context.isPretty()) {
|
|
2834
|
+
output.push('\n' + context.indent(deleteClause));
|
|
2426
2835
|
}
|
|
2427
2836
|
else {
|
|
2428
2837
|
output.push('ON DELETE');
|
|
@@ -2431,7 +2840,12 @@ class Deparser {
|
|
|
2431
2840
|
}
|
|
2432
2841
|
// Handle NOT VALID for foreign key constraints - only for table constraints, not domain constraints
|
|
2433
2842
|
if (node.skip_validation && !context.isDomainConstraint) {
|
|
2434
|
-
|
|
2843
|
+
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2844
|
+
output.push('\n' + context.indent('NOT VALID'));
|
|
2845
|
+
}
|
|
2846
|
+
else {
|
|
2847
|
+
output.push('NOT VALID');
|
|
2848
|
+
}
|
|
2435
2849
|
}
|
|
2436
2850
|
break;
|
|
2437
2851
|
case 'CONSTR_ATTR_DEFERRABLE':
|
|
@@ -2485,13 +2899,13 @@ class Deparser {
|
|
|
2485
2899
|
// Handle deferrable constraints for all constraint types that support it
|
|
2486
2900
|
if (node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_FOREIGN') {
|
|
2487
2901
|
if (node.deferrable) {
|
|
2488
|
-
if (
|
|
2489
|
-
output.push('\n' +
|
|
2902
|
+
if (context.isPretty() && node.contype === 'CONSTR_FOREIGN') {
|
|
2903
|
+
output.push('\n' + context.indent('DEFERRABLE'));
|
|
2490
2904
|
if (node.initdeferred === true) {
|
|
2491
|
-
output.push('\n' +
|
|
2905
|
+
output.push('\n' + context.indent('INITIALLY DEFERRED'));
|
|
2492
2906
|
}
|
|
2493
2907
|
else if (node.initdeferred === false) {
|
|
2494
|
-
output.push('\n' +
|
|
2908
|
+
output.push('\n' + context.indent('INITIALLY IMMEDIATE'));
|
|
2495
2909
|
}
|
|
2496
2910
|
}
|
|
2497
2911
|
else {
|
|
@@ -2505,15 +2919,15 @@ class Deparser {
|
|
|
2505
2919
|
}
|
|
2506
2920
|
}
|
|
2507
2921
|
else if (node.deferrable === false) {
|
|
2508
|
-
if (
|
|
2509
|
-
output.push('\n' +
|
|
2922
|
+
if (context.isPretty() && node.contype === 'CONSTR_FOREIGN') {
|
|
2923
|
+
output.push('\n' + context.indent('NOT DEFERRABLE'));
|
|
2510
2924
|
}
|
|
2511
2925
|
else {
|
|
2512
2926
|
output.push('NOT DEFERRABLE');
|
|
2513
2927
|
}
|
|
2514
2928
|
}
|
|
2515
2929
|
}
|
|
2516
|
-
if (
|
|
2930
|
+
if (context.isPretty() && node.contype === 'CONSTR_FOREIGN') {
|
|
2517
2931
|
let result = '';
|
|
2518
2932
|
for (let i = 0; i < output.length; i++) {
|
|
2519
2933
|
if (output[i].startsWith('\n')) {
|
|
@@ -2531,12 +2945,12 @@ class Deparser {
|
|
|
2531
2945
|
return output.join(' ');
|
|
2532
2946
|
}
|
|
2533
2947
|
SubLink(node, context) {
|
|
2534
|
-
const subselect =
|
|
2948
|
+
const subselect = context.parens(this.visit(node.subselect, context));
|
|
2535
2949
|
switch (node.subLinkType) {
|
|
2536
2950
|
case 'ANY_SUBLINK':
|
|
2537
2951
|
if (node.testexpr && node.operName) {
|
|
2538
2952
|
const testExpr = this.visit(node.testexpr, context);
|
|
2539
|
-
const operator = this.deparseOperatorName(node.operName);
|
|
2953
|
+
const operator = this.deparseOperatorName(node.operName, context);
|
|
2540
2954
|
return `${testExpr} ${operator} ANY ${subselect}`;
|
|
2541
2955
|
}
|
|
2542
2956
|
else if (node.testexpr) {
|
|
@@ -2547,7 +2961,7 @@ class Deparser {
|
|
|
2547
2961
|
case 'ALL_SUBLINK':
|
|
2548
2962
|
if (node.testexpr && node.operName) {
|
|
2549
2963
|
const testExpr = this.visit(node.testexpr, context);
|
|
2550
|
-
const operator = this.deparseOperatorName(node.operName);
|
|
2964
|
+
const operator = this.deparseOperatorName(node.operName, context);
|
|
2551
2965
|
return `${testExpr} ${operator} ALL ${subselect}`;
|
|
2552
2966
|
}
|
|
2553
2967
|
return subselect;
|
|
@@ -2589,7 +3003,7 @@ class Deparser {
|
|
|
2589
3003
|
}
|
|
2590
3004
|
// Only add frame clause if frameOptions indicates non-default framing
|
|
2591
3005
|
if (node.frameOptions && node.frameOptions !== 1058) {
|
|
2592
|
-
const frameClause = this.formatWindowFrame(node);
|
|
3006
|
+
const frameClause = this.formatWindowFrame(node, context.spawn('WindowDef'));
|
|
2593
3007
|
if (frameClause) {
|
|
2594
3008
|
windowParts.push(frameClause);
|
|
2595
3009
|
}
|
|
@@ -2609,7 +3023,7 @@ class Deparser {
|
|
|
2609
3023
|
}
|
|
2610
3024
|
return output.join(' ');
|
|
2611
3025
|
}
|
|
2612
|
-
formatWindowFrame(node) {
|
|
3026
|
+
formatWindowFrame(node, context) {
|
|
2613
3027
|
if (!node.frameOptions)
|
|
2614
3028
|
return null;
|
|
2615
3029
|
const frameOptions = node.frameOptions;
|
|
@@ -2618,7 +3032,7 @@ class Deparser {
|
|
|
2618
3032
|
if (frameOptions & 0x02) { // FRAMEOPTION_RANGE
|
|
2619
3033
|
frameParts.push('RANGE');
|
|
2620
3034
|
}
|
|
2621
|
-
else if (frameOptions & 0x04) { // FRAMEOPTION_ROWS
|
|
3035
|
+
else if (frameOptions & 0x04) { // FRAMEOPTION_ROWS
|
|
2622
3036
|
frameParts.push('ROWS');
|
|
2623
3037
|
}
|
|
2624
3038
|
else if (frameOptions & 0x08) { // FRAMEOPTION_GROUPS
|
|
@@ -2639,8 +3053,8 @@ class Deparser {
|
|
|
2639
3053
|
}
|
|
2640
3054
|
else if (frameOptions === 18453) {
|
|
2641
3055
|
if (node.startOffset && node.endOffset) {
|
|
2642
|
-
boundsParts.push(`${this.visit(node.startOffset,
|
|
2643
|
-
boundsParts.push(`AND ${this.visit(node.endOffset,
|
|
3056
|
+
boundsParts.push(`${this.visit(node.startOffset, context)} PRECEDING`);
|
|
3057
|
+
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
2644
3058
|
}
|
|
2645
3059
|
}
|
|
2646
3060
|
else if (frameOptions === 1557) {
|
|
@@ -2650,7 +3064,7 @@ class Deparser {
|
|
|
2650
3064
|
else if (frameOptions === 16917) {
|
|
2651
3065
|
boundsParts.push('CURRENT ROW');
|
|
2652
3066
|
if (node.endOffset) {
|
|
2653
|
-
boundsParts.push(`AND ${this.visit(node.endOffset,
|
|
3067
|
+
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
2654
3068
|
}
|
|
2655
3069
|
}
|
|
2656
3070
|
else if (frameOptions === 1058) {
|
|
@@ -2660,13 +3074,13 @@ class Deparser {
|
|
|
2660
3074
|
// Handle start bound - prioritize explicit offset values over bit flags
|
|
2661
3075
|
if (node.startOffset) {
|
|
2662
3076
|
if (frameOptions & 0x400) { // FRAMEOPTION_START_VALUE_PRECEDING
|
|
2663
|
-
boundsParts.push(`${this.visit(node.startOffset,
|
|
3077
|
+
boundsParts.push(`${this.visit(node.startOffset, context)} PRECEDING`);
|
|
2664
3078
|
}
|
|
2665
3079
|
else if (frameOptions & 0x800) { // FRAMEOPTION_START_VALUE_FOLLOWING
|
|
2666
|
-
boundsParts.push(`${this.visit(node.startOffset,
|
|
3080
|
+
boundsParts.push(`${this.visit(node.startOffset, context)} FOLLOWING`);
|
|
2667
3081
|
}
|
|
2668
3082
|
else {
|
|
2669
|
-
boundsParts.push(`${this.visit(node.startOffset,
|
|
3083
|
+
boundsParts.push(`${this.visit(node.startOffset, context)} PRECEDING`);
|
|
2670
3084
|
}
|
|
2671
3085
|
}
|
|
2672
3086
|
else if (frameOptions & 0x10) { // FRAMEOPTION_START_UNBOUNDED_PRECEDING
|
|
@@ -2679,13 +3093,13 @@ class Deparser {
|
|
|
2679
3093
|
if (node.endOffset) {
|
|
2680
3094
|
if (boundsParts.length > 0) {
|
|
2681
3095
|
if (frameOptions & 0x1000) { // FRAMEOPTION_END_VALUE_PRECEDING
|
|
2682
|
-
boundsParts.push(`AND ${this.visit(node.endOffset,
|
|
3096
|
+
boundsParts.push(`AND ${this.visit(node.endOffset, context)} PRECEDING`);
|
|
2683
3097
|
}
|
|
2684
3098
|
else if (frameOptions & 0x2000) { // FRAMEOPTION_END_VALUE_FOLLOWING
|
|
2685
|
-
boundsParts.push(`AND ${this.visit(node.endOffset,
|
|
3099
|
+
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
2686
3100
|
}
|
|
2687
3101
|
else {
|
|
2688
|
-
boundsParts.push(`AND ${this.visit(node.endOffset,
|
|
3102
|
+
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
2689
3103
|
}
|
|
2690
3104
|
}
|
|
2691
3105
|
}
|
|
@@ -2770,7 +3184,7 @@ class Deparser {
|
|
|
2770
3184
|
const colnames = list_utils_1.ListUtils.unwrapList(node.aliascolnames);
|
|
2771
3185
|
const colnameStrs = colnames.map(col => this.visit(col, context));
|
|
2772
3186
|
// Don't add space before column list parentheses to match original formatting
|
|
2773
|
-
output[output.length - 1] +=
|
|
3187
|
+
output[output.length - 1] += context.parens(colnameStrs.join(', '));
|
|
2774
3188
|
}
|
|
2775
3189
|
output.push('AS');
|
|
2776
3190
|
// Handle materialization clauses
|
|
@@ -2781,7 +3195,7 @@ class Deparser {
|
|
|
2781
3195
|
output.push('MATERIALIZED');
|
|
2782
3196
|
}
|
|
2783
3197
|
if (node.ctequery) {
|
|
2784
|
-
output.push(
|
|
3198
|
+
output.push(context.parens(this.visit(node.ctequery, context)));
|
|
2785
3199
|
}
|
|
2786
3200
|
return output.join(' ');
|
|
2787
3201
|
}
|
|
@@ -2857,7 +3271,7 @@ class Deparser {
|
|
|
2857
3271
|
DistinctExpr(node, context) {
|
|
2858
3272
|
const args = list_utils_1.ListUtils.unwrapList(node.args);
|
|
2859
3273
|
if (args.length === 2) {
|
|
2860
|
-
const literalContext =
|
|
3274
|
+
const literalContext = context.spawn('DistinctExpr', { isStringLiteral: true });
|
|
2861
3275
|
const left = this.visit(args[0], literalContext);
|
|
2862
3276
|
const right = this.visit(args[1], literalContext);
|
|
2863
3277
|
return `${left} IS DISTINCT FROM ${right}`;
|
|
@@ -2867,7 +3281,7 @@ class Deparser {
|
|
|
2867
3281
|
NullIfExpr(node, context) {
|
|
2868
3282
|
const args = list_utils_1.ListUtils.unwrapList(node.args);
|
|
2869
3283
|
if (args.length === 2) {
|
|
2870
|
-
const literalContext =
|
|
3284
|
+
const literalContext = context.spawn('NullIfExpr', { isStringLiteral: true });
|
|
2871
3285
|
const left = this.visit(args[0], literalContext);
|
|
2872
3286
|
const right = this.visit(args[1], literalContext);
|
|
2873
3287
|
return `NULLIF(${left}, ${right})`;
|
|
@@ -2946,7 +3360,7 @@ class Deparser {
|
|
|
2946
3360
|
}
|
|
2947
3361
|
RelabelType(node, context) {
|
|
2948
3362
|
if (node.arg) {
|
|
2949
|
-
const literalContext =
|
|
3363
|
+
const literalContext = context.spawn('RelabelType', { isStringLiteral: true });
|
|
2950
3364
|
return this.visit(node.arg, literalContext);
|
|
2951
3365
|
}
|
|
2952
3366
|
return '';
|
|
@@ -2965,7 +3379,7 @@ class Deparser {
|
|
|
2965
3379
|
}
|
|
2966
3380
|
ConvertRowtypeExpr(node, context) {
|
|
2967
3381
|
if (node.arg) {
|
|
2968
|
-
const literalContext =
|
|
3382
|
+
const literalContext = context.spawn('ConvertRowtypeExpr', { isStringLiteral: true });
|
|
2969
3383
|
return this.visit(node.arg, literalContext);
|
|
2970
3384
|
}
|
|
2971
3385
|
return '';
|
|
@@ -2996,10 +3410,10 @@ class Deparser {
|
|
|
2996
3410
|
}
|
|
2997
3411
|
if (node.aliases && node.aliases.length > 0) {
|
|
2998
3412
|
const aliasStrs = list_utils_1.ListUtils.unwrapList(node.aliases).map(alias => this.visit(alias, context));
|
|
2999
|
-
output.push(
|
|
3413
|
+
output.push(context.parens(aliasStrs.join(', ')));
|
|
3000
3414
|
}
|
|
3001
3415
|
if (node.options && node.options.length > 0) {
|
|
3002
|
-
const viewContext =
|
|
3416
|
+
const viewContext = context.spawn('ViewStmt');
|
|
3003
3417
|
const optionStrs = list_utils_1.ListUtils.unwrapList(node.options)
|
|
3004
3418
|
.map(option => this.visit(option, viewContext));
|
|
3005
3419
|
output.push(`WITH (${optionStrs.join(', ')})`);
|
|
@@ -3046,22 +3460,22 @@ class Deparser {
|
|
|
3046
3460
|
}
|
|
3047
3461
|
if (node.indexParams && node.indexParams.length > 0) {
|
|
3048
3462
|
const paramStrs = list_utils_1.ListUtils.unwrapList(node.indexParams).map(param => this.visit(param, context));
|
|
3049
|
-
output.push(
|
|
3463
|
+
output.push(context.parens(paramStrs.join(', ')));
|
|
3050
3464
|
}
|
|
3051
3465
|
if (node.indexIncludingParams && node.indexIncludingParams.length > 0) {
|
|
3052
3466
|
const includeStrs = list_utils_1.ListUtils.unwrapList(node.indexIncludingParams).map(param => this.visit(param, context));
|
|
3053
3467
|
output.push('INCLUDE');
|
|
3054
|
-
output.push(
|
|
3468
|
+
output.push(context.parens(includeStrs.join(', ')));
|
|
3055
3469
|
}
|
|
3056
3470
|
if (node.whereClause) {
|
|
3057
3471
|
output.push('WHERE');
|
|
3058
3472
|
output.push(this.visit(node.whereClause, context));
|
|
3059
3473
|
}
|
|
3060
3474
|
if (node.options && node.options.length > 0) {
|
|
3061
|
-
const indexContext =
|
|
3475
|
+
const indexContext = context.spawn('IndexStmt');
|
|
3062
3476
|
const optionStrs = list_utils_1.ListUtils.unwrapList(node.options).map(option => this.visit(option, indexContext));
|
|
3063
3477
|
output.push('WITH');
|
|
3064
|
-
output.push(
|
|
3478
|
+
output.push(context.parens(optionStrs.join(', ')));
|
|
3065
3479
|
}
|
|
3066
3480
|
if (node.nulls_not_distinct) {
|
|
3067
3481
|
output.push('NULLS NOT DISTINCT');
|
|
@@ -3078,7 +3492,7 @@ class Deparser {
|
|
|
3078
3492
|
output.push(quote_utils_1.QuoteUtils.quote(node.name));
|
|
3079
3493
|
}
|
|
3080
3494
|
else if (node.expr) {
|
|
3081
|
-
output.push(
|
|
3495
|
+
output.push(context.parens(this.visit(node.expr, context)));
|
|
3082
3496
|
}
|
|
3083
3497
|
if (node.collation && node.collation.length > 0) {
|
|
3084
3498
|
const collationStrs = list_utils_1.ListUtils.unwrapList(node.collation).map(coll => this.visit(coll, context));
|
|
@@ -3095,7 +3509,7 @@ class Deparser {
|
|
|
3095
3509
|
const stringData = this.getNodeData(opt.DefElem.arg);
|
|
3096
3510
|
return `${opt.DefElem.defname}='${stringData.sval}'`;
|
|
3097
3511
|
}
|
|
3098
|
-
return this.visit(opt, context);
|
|
3512
|
+
return this.visit(opt, context.spawn('IndexElem'));
|
|
3099
3513
|
});
|
|
3100
3514
|
opclassStr += `(${opclassOpts.join(', ')})`;
|
|
3101
3515
|
}
|
|
@@ -3129,7 +3543,7 @@ class Deparser {
|
|
|
3129
3543
|
output.push(quote_utils_1.QuoteUtils.quote(node.name));
|
|
3130
3544
|
}
|
|
3131
3545
|
else if (node.expr) {
|
|
3132
|
-
output.push(
|
|
3546
|
+
output.push(context.parens(this.visit(node.expr, context)));
|
|
3133
3547
|
}
|
|
3134
3548
|
if (node.collation && node.collation.length > 0) {
|
|
3135
3549
|
const collationStrs = list_utils_1.ListUtils.unwrapList(node.collation).map(coll => this.visit(coll, context));
|
|
@@ -3277,16 +3691,16 @@ class Deparser {
|
|
|
3277
3691
|
if (node.rarg && 'JoinExpr' in node.rarg && !node.rarg.JoinExpr.alias) {
|
|
3278
3692
|
rargStr = `(${rargStr})`;
|
|
3279
3693
|
}
|
|
3280
|
-
if (
|
|
3281
|
-
output.push(
|
|
3694
|
+
if (context.isPretty()) {
|
|
3695
|
+
output.push(context.newline() + joinStr + ' ' + rargStr);
|
|
3282
3696
|
}
|
|
3283
3697
|
else {
|
|
3284
3698
|
output.push(joinStr + ' ' + rargStr);
|
|
3285
3699
|
}
|
|
3286
3700
|
}
|
|
3287
3701
|
else {
|
|
3288
|
-
if (
|
|
3289
|
-
output.push(
|
|
3702
|
+
if (context.isPretty()) {
|
|
3703
|
+
output.push(context.newline() + joinStr);
|
|
3290
3704
|
}
|
|
3291
3705
|
else {
|
|
3292
3706
|
output.push(joinStr);
|
|
@@ -3295,7 +3709,7 @@ class Deparser {
|
|
|
3295
3709
|
if (node.usingClause && node.usingClause.length > 0) {
|
|
3296
3710
|
const usingList = list_utils_1.ListUtils.unwrapList(node.usingClause);
|
|
3297
3711
|
const columnNames = usingList.map(col => this.visit(col, context));
|
|
3298
|
-
if (
|
|
3712
|
+
if (context.isPretty()) {
|
|
3299
3713
|
output.push(` USING (${columnNames.join(', ')})`);
|
|
3300
3714
|
}
|
|
3301
3715
|
else {
|
|
@@ -3304,14 +3718,14 @@ class Deparser {
|
|
|
3304
3718
|
}
|
|
3305
3719
|
else if (node.quals) {
|
|
3306
3720
|
const qualsStr = this.visit(node.quals, context);
|
|
3307
|
-
if (
|
|
3721
|
+
if (context.isPretty()) {
|
|
3308
3722
|
// For complex JOIN conditions, format with proper indentation
|
|
3309
3723
|
if (qualsStr.includes('AND') || qualsStr.includes('OR') || qualsStr.length > 50) {
|
|
3310
3724
|
if (this.containsMultilineStringLiteral(qualsStr)) {
|
|
3311
3725
|
output.push(` ON ${qualsStr}`);
|
|
3312
3726
|
}
|
|
3313
3727
|
else {
|
|
3314
|
-
output.push(` ON${
|
|
3728
|
+
output.push(` ON${context.newline()}${context.indent(qualsStr)}`);
|
|
3315
3729
|
}
|
|
3316
3730
|
}
|
|
3317
3731
|
else {
|
|
@@ -3323,7 +3737,7 @@ class Deparser {
|
|
|
3323
3737
|
}
|
|
3324
3738
|
}
|
|
3325
3739
|
let result;
|
|
3326
|
-
if (
|
|
3740
|
+
if (context.isPretty()) {
|
|
3327
3741
|
result = output.join('');
|
|
3328
3742
|
}
|
|
3329
3743
|
else {
|
|
@@ -3430,8 +3844,8 @@ class Deparser {
|
|
|
3430
3844
|
else if (nodeData.sval !== undefined) {
|
|
3431
3845
|
// Handle nested sval structure: { sval: { sval: "value" } }
|
|
3432
3846
|
const svalValue = typeof nodeData.sval === 'object' ? nodeData.sval.sval : nodeData.sval;
|
|
3433
|
-
const stringValue = svalValue.replace(/'/g, '')
|
|
3434
|
-
boolValue = stringValue === 'on' || stringValue === 'true';
|
|
3847
|
+
const stringValue = svalValue.replace(/'/g, '');
|
|
3848
|
+
boolValue = stringValue.toLowerCase() === 'on' || stringValue.toLowerCase() === 'true';
|
|
3435
3849
|
}
|
|
3436
3850
|
}
|
|
3437
3851
|
return boolValue ? 'READ ONLY' : 'READ WRITE';
|
|
@@ -3454,8 +3868,8 @@ class Deparser {
|
|
|
3454
3868
|
else if (nodeData.sval !== undefined) {
|
|
3455
3869
|
// Handle nested sval structure: { sval: { sval: "value" } }
|
|
3456
3870
|
const svalValue = typeof nodeData.sval === 'object' ? nodeData.sval.sval : nodeData.sval;
|
|
3457
|
-
const stringValue = svalValue.replace(/'/g, '')
|
|
3458
|
-
boolValue = stringValue === 'on' || stringValue === 'true';
|
|
3871
|
+
const stringValue = svalValue.replace(/'/g, '');
|
|
3872
|
+
boolValue = stringValue.toLowerCase() === 'on' || stringValue.toLowerCase() === 'true';
|
|
3459
3873
|
}
|
|
3460
3874
|
}
|
|
3461
3875
|
return boolValue ? 'DEFERRABLE' : 'NOT DEFERRABLE';
|
|
@@ -3522,8 +3936,8 @@ class Deparser {
|
|
|
3522
3936
|
else if (nodeData.sval !== undefined) {
|
|
3523
3937
|
// Handle nested sval structure: { sval: { sval: "value" } }
|
|
3524
3938
|
const svalValue = typeof nodeData.sval === 'object' ? nodeData.sval.sval : nodeData.sval;
|
|
3525
|
-
const stringValue = svalValue.replace(/'/g, '')
|
|
3526
|
-
boolValue = stringValue === 'on' || stringValue === 'true';
|
|
3939
|
+
const stringValue = svalValue.replace(/'/g, '');
|
|
3940
|
+
boolValue = stringValue.toLowerCase() === 'on' || stringValue.toLowerCase() === 'true';
|
|
3527
3941
|
}
|
|
3528
3942
|
}
|
|
3529
3943
|
transactionOptions.push(boolValue ? 'READ ONLY' : 'READ WRITE');
|
|
@@ -3541,8 +3955,8 @@ class Deparser {
|
|
|
3541
3955
|
else if (nodeData.sval !== undefined) {
|
|
3542
3956
|
// Handle nested sval structure: { sval: { sval: "value" } }
|
|
3543
3957
|
const svalValue = typeof nodeData.sval === 'object' ? nodeData.sval.sval : nodeData.sval;
|
|
3544
|
-
const stringValue = svalValue.replace(/'/g, '')
|
|
3545
|
-
boolValue = stringValue === 'on' || stringValue === 'true';
|
|
3958
|
+
const stringValue = svalValue.replace(/'/g, '');
|
|
3959
|
+
boolValue = stringValue.toLowerCase() === 'on' || stringValue.toLowerCase() === 'true';
|
|
3546
3960
|
}
|
|
3547
3961
|
}
|
|
3548
3962
|
transactionOptions.push(boolValue ? 'DEFERRABLE' : 'NOT DEFERRABLE');
|
|
@@ -3608,7 +4022,7 @@ class Deparser {
|
|
|
3608
4022
|
}
|
|
3609
4023
|
switch (node.roletype) {
|
|
3610
4024
|
case 'ROLESPEC_PUBLIC':
|
|
3611
|
-
return '
|
|
4025
|
+
return 'PUBLIC';
|
|
3612
4026
|
case 'ROLESPEC_CURRENT_USER':
|
|
3613
4027
|
return 'CURRENT_USER';
|
|
3614
4028
|
case 'ROLESPEC_SESSION_USER':
|
|
@@ -3616,7 +4030,7 @@ class Deparser {
|
|
|
3616
4030
|
case 'ROLESPEC_CURRENT_ROLE':
|
|
3617
4031
|
return 'CURRENT_ROLE';
|
|
3618
4032
|
default:
|
|
3619
|
-
return '
|
|
4033
|
+
return 'PUBLIC';
|
|
3620
4034
|
}
|
|
3621
4035
|
}
|
|
3622
4036
|
roletype(node, context) {
|
|
@@ -3926,7 +4340,7 @@ class Deparser {
|
|
|
3926
4340
|
}).filter((name) => name && name.trim());
|
|
3927
4341
|
return items.join('.');
|
|
3928
4342
|
}
|
|
3929
|
-
const objContext =
|
|
4343
|
+
const objContext = context.spawn('DropStmt', { objtype: node.removeType });
|
|
3930
4344
|
const objName = this.visit(objList, objContext);
|
|
3931
4345
|
return objName;
|
|
3932
4346
|
}).filter((name) => name && name.trim()).join(', ');
|
|
@@ -4026,7 +4440,7 @@ class Deparser {
|
|
|
4026
4440
|
if (node.options && node.options.length > 0) {
|
|
4027
4441
|
output.push('WITH');
|
|
4028
4442
|
const optionsStr = list_utils_1.ListUtils.unwrapList(node.options)
|
|
4029
|
-
.map(opt => this.visit(opt, context))
|
|
4443
|
+
.map(opt => this.visit(opt, context.spawn('CopyStmt')))
|
|
4030
4444
|
.join(', ');
|
|
4031
4445
|
output.push(`(${optionsStr})`);
|
|
4032
4446
|
}
|
|
@@ -4072,18 +4486,28 @@ class Deparser {
|
|
|
4072
4486
|
if (node.missing_ok) {
|
|
4073
4487
|
output.push('IF EXISTS');
|
|
4074
4488
|
}
|
|
4075
|
-
const alterContext = node.objtype
|
|
4076
|
-
? { ...context, parentNodeTypes: [...context.parentNodeTypes, 'AlterTypeStmt'] }
|
|
4077
|
-
: context;
|
|
4489
|
+
const alterContext = context.spawn('AlterTableStmt', { objtype: node.objtype });
|
|
4078
4490
|
if (node.relation) {
|
|
4079
4491
|
const relationStr = this.RangeVar(node.relation, alterContext);
|
|
4080
4492
|
output.push(relationStr);
|
|
4081
4493
|
}
|
|
4082
4494
|
if (node.cmds && node.cmds.length > 0) {
|
|
4083
|
-
const
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4495
|
+
const commands = list_utils_1.ListUtils.unwrapList(node.cmds);
|
|
4496
|
+
if (context.isPretty()) {
|
|
4497
|
+
const commandsStr = commands
|
|
4498
|
+
.map(cmd => {
|
|
4499
|
+
const cmdStr = this.visit(cmd, alterContext);
|
|
4500
|
+
return context.newline() + context.indent(cmdStr);
|
|
4501
|
+
})
|
|
4502
|
+
.join(',');
|
|
4503
|
+
output.push(commandsStr);
|
|
4504
|
+
}
|
|
4505
|
+
else {
|
|
4506
|
+
const commandsStr = commands
|
|
4507
|
+
.map(cmd => this.visit(cmd, alterContext))
|
|
4508
|
+
.join(', ');
|
|
4509
|
+
output.push(commandsStr);
|
|
4510
|
+
}
|
|
4087
4511
|
}
|
|
4088
4512
|
return output.join(' ');
|
|
4089
4513
|
}
|
|
@@ -4092,7 +4516,7 @@ class Deparser {
|
|
|
4092
4516
|
if (node.subtype) {
|
|
4093
4517
|
switch (node.subtype) {
|
|
4094
4518
|
case 'AT_AddColumn':
|
|
4095
|
-
if (context.
|
|
4519
|
+
if (context.objtype === 'OBJECT_TYPE') {
|
|
4096
4520
|
output.push('ADD ATTRIBUTE');
|
|
4097
4521
|
}
|
|
4098
4522
|
else {
|
|
@@ -4103,35 +4527,99 @@ class Deparser {
|
|
|
4103
4527
|
}
|
|
4104
4528
|
if (node.def) {
|
|
4105
4529
|
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
|
-
|
|
4530
|
+
if (context.isPretty()) {
|
|
4531
|
+
const parts = [];
|
|
4532
|
+
const indentedParts = [];
|
|
4533
|
+
if (colDefData.colname) {
|
|
4534
|
+
parts.push(quote_utils_1.QuoteUtils.quote(colDefData.colname));
|
|
4535
|
+
}
|
|
4536
|
+
if (colDefData.typeName) {
|
|
4537
|
+
parts.push(this.TypeName(colDefData.typeName, context));
|
|
4538
|
+
}
|
|
4539
|
+
if (colDefData.is_not_null) {
|
|
4540
|
+
indentedParts.push('NOT NULL');
|
|
4541
|
+
}
|
|
4542
|
+
if (colDefData.collClause) {
|
|
4543
|
+
indentedParts.push(this.CollateClause(colDefData.collClause, context));
|
|
4544
|
+
}
|
|
4545
|
+
if (colDefData.constraints) {
|
|
4546
|
+
const constraints = list_utils_1.ListUtils.unwrapList(colDefData.constraints);
|
|
4547
|
+
constraints.forEach(constraint => {
|
|
4548
|
+
const columnConstraintContext = context.spawn('ColumnDef', { isColumnConstraint: true });
|
|
4549
|
+
const constraintStr = this.visit(constraint, columnConstraintContext);
|
|
4550
|
+
if (constraintStr.includes('REFERENCES') && constraintStr.includes('ON DELETE')) {
|
|
4551
|
+
const refMatch = constraintStr.match(/^(.*REFERENCES[^)]*\([^)]*\))\s*(ON\s+DELETE\s+CASCADE.*)$/);
|
|
4552
|
+
if (refMatch) {
|
|
4553
|
+
indentedParts.push(refMatch[1]);
|
|
4554
|
+
indentedParts.push(refMatch[2]);
|
|
4555
|
+
}
|
|
4556
|
+
else {
|
|
4557
|
+
indentedParts.push(constraintStr);
|
|
4558
|
+
}
|
|
4559
|
+
}
|
|
4560
|
+
else if (constraintStr === 'UNIQUE' && colDefData.raw_default) {
|
|
4561
|
+
const defaultStr = 'DEFAULT ' + this.visit(colDefData.raw_default, context);
|
|
4562
|
+
indentedParts.push('UNIQUE ' + defaultStr);
|
|
4563
|
+
}
|
|
4564
|
+
else {
|
|
4565
|
+
indentedParts.push(constraintStr);
|
|
4566
|
+
}
|
|
4567
|
+
});
|
|
4568
|
+
}
|
|
4569
|
+
if (colDefData.raw_default && !colDefData.constraints?.some((c) => {
|
|
4570
|
+
const constraintStr = this.visit(c, context.spawn('ColumnDef', { isColumnConstraint: true }));
|
|
4571
|
+
return constraintStr === 'UNIQUE';
|
|
4572
|
+
})) {
|
|
4573
|
+
const defaultStr = 'DEFAULT ' + this.visit(colDefData.raw_default, context);
|
|
4574
|
+
indentedParts.push(defaultStr);
|
|
4575
|
+
}
|
|
4576
|
+
if (colDefData.fdwoptions && colDefData.fdwoptions.length > 0) {
|
|
4577
|
+
indentedParts.push('OPTIONS');
|
|
4578
|
+
const columnContext = context.spawn('ColumnDef');
|
|
4579
|
+
const options = list_utils_1.ListUtils.unwrapList(colDefData.fdwoptions).map(opt => this.visit(opt, columnContext));
|
|
4580
|
+
indentedParts.push(`(${options.join(', ')})`);
|
|
4581
|
+
}
|
|
4582
|
+
let result = parts.join(' ');
|
|
4583
|
+
if (indentedParts.length > 0) {
|
|
4584
|
+
const indentedStr = indentedParts.map(part => context.indent(part)).join(context.newline());
|
|
4585
|
+
result += context.newline() + indentedStr;
|
|
4586
|
+
}
|
|
4587
|
+
output.push(result);
|
|
4130
4588
|
}
|
|
4131
|
-
|
|
4132
|
-
parts
|
|
4589
|
+
else {
|
|
4590
|
+
const parts = [];
|
|
4591
|
+
if (colDefData.colname) {
|
|
4592
|
+
parts.push(quote_utils_1.QuoteUtils.quote(colDefData.colname));
|
|
4593
|
+
}
|
|
4594
|
+
if (colDefData.typeName) {
|
|
4595
|
+
parts.push(this.TypeName(colDefData.typeName, context));
|
|
4596
|
+
}
|
|
4597
|
+
if (colDefData.collClause) {
|
|
4598
|
+
parts.push(this.CollateClause(colDefData.collClause, context));
|
|
4599
|
+
}
|
|
4600
|
+
if (colDefData.fdwoptions && colDefData.fdwoptions.length > 0) {
|
|
4601
|
+
parts.push('OPTIONS');
|
|
4602
|
+
const columnContext = context.spawn('ColumnDef');
|
|
4603
|
+
const options = list_utils_1.ListUtils.unwrapList(colDefData.fdwoptions).map(opt => this.visit(opt, columnContext));
|
|
4604
|
+
parts.push(`(${options.join(', ')})`);
|
|
4605
|
+
}
|
|
4606
|
+
if (colDefData.constraints) {
|
|
4607
|
+
const constraints = list_utils_1.ListUtils.unwrapList(colDefData.constraints);
|
|
4608
|
+
const constraintStrs = constraints.map(constraint => {
|
|
4609
|
+
const columnConstraintContext = context.spawn('ColumnDef', { isColumnConstraint: true });
|
|
4610
|
+
return this.visit(constraint, columnConstraintContext);
|
|
4611
|
+
});
|
|
4612
|
+
parts.push(...constraintStrs);
|
|
4613
|
+
}
|
|
4614
|
+
if (colDefData.raw_default) {
|
|
4615
|
+
parts.push('DEFAULT');
|
|
4616
|
+
parts.push(this.visit(colDefData.raw_default, context));
|
|
4617
|
+
}
|
|
4618
|
+
if (colDefData.is_not_null) {
|
|
4619
|
+
parts.push('NOT NULL');
|
|
4620
|
+
}
|
|
4621
|
+
output.push(parts.join(' '));
|
|
4133
4622
|
}
|
|
4134
|
-
output.push(parts.join(' '));
|
|
4135
4623
|
}
|
|
4136
4624
|
if (node.behavior === 'DROP_CASCADE') {
|
|
4137
4625
|
output.push('CASCADE');
|
|
@@ -4139,7 +4627,7 @@ class Deparser {
|
|
|
4139
4627
|
break;
|
|
4140
4628
|
case 'AT_DropColumn':
|
|
4141
4629
|
if (node.missing_ok) {
|
|
4142
|
-
if (context.
|
|
4630
|
+
if (context.objtype === 'OBJECT_TYPE') {
|
|
4143
4631
|
output.push('DROP ATTRIBUTE IF EXISTS');
|
|
4144
4632
|
}
|
|
4145
4633
|
else {
|
|
@@ -4147,7 +4635,7 @@ class Deparser {
|
|
|
4147
4635
|
}
|
|
4148
4636
|
}
|
|
4149
4637
|
else {
|
|
4150
|
-
if (context.
|
|
4638
|
+
if (context.objtype === 'OBJECT_TYPE') {
|
|
4151
4639
|
output.push('DROP ATTRIBUTE');
|
|
4152
4640
|
}
|
|
4153
4641
|
else {
|
|
@@ -4165,7 +4653,7 @@ class Deparser {
|
|
|
4165
4653
|
}
|
|
4166
4654
|
break;
|
|
4167
4655
|
case 'AT_AlterColumnType':
|
|
4168
|
-
if (context.
|
|
4656
|
+
if (context.objtype === 'OBJECT_TYPE') {
|
|
4169
4657
|
output.push('ALTER ATTRIBUTE');
|
|
4170
4658
|
}
|
|
4171
4659
|
else {
|
|
@@ -4229,7 +4717,7 @@ class Deparser {
|
|
|
4229
4717
|
case 'AT_SetRelOptions':
|
|
4230
4718
|
output.push('SET');
|
|
4231
4719
|
if (node.def) {
|
|
4232
|
-
const alterTableContext =
|
|
4720
|
+
const alterTableContext = context.spawn('AlterTableCmd', { subtype: 'AT_SetRelOptions' });
|
|
4233
4721
|
const options = list_utils_1.ListUtils.unwrapList(node.def)
|
|
4234
4722
|
.map(option => this.visit(option, alterTableContext))
|
|
4235
4723
|
.join(', ');
|
|
@@ -4242,7 +4730,7 @@ class Deparser {
|
|
|
4242
4730
|
case 'AT_ResetRelOptions':
|
|
4243
4731
|
output.push('RESET');
|
|
4244
4732
|
if (node.def) {
|
|
4245
|
-
const alterTableContext =
|
|
4733
|
+
const alterTableContext = context.spawn('AlterTableCmd', { subtype: 'AT_ResetRelOptions' });
|
|
4246
4734
|
const options = list_utils_1.ListUtils.unwrapList(node.def)
|
|
4247
4735
|
.map(option => this.visit(option, alterTableContext))
|
|
4248
4736
|
.join(', ');
|
|
@@ -4337,7 +4825,7 @@ class Deparser {
|
|
|
4337
4825
|
}
|
|
4338
4826
|
output.push('SET');
|
|
4339
4827
|
if (node.def) {
|
|
4340
|
-
const alterTableContext =
|
|
4828
|
+
const alterTableContext = context.spawn('AlterTableCmd', { subtype: 'AT_SetOptions' });
|
|
4341
4829
|
const options = list_utils_1.ListUtils.unwrapList(node.def)
|
|
4342
4830
|
.map(option => this.visit(option, alterTableContext))
|
|
4343
4831
|
.join(', ');
|
|
@@ -4354,7 +4842,7 @@ class Deparser {
|
|
|
4354
4842
|
}
|
|
4355
4843
|
output.push('RESET');
|
|
4356
4844
|
if (node.def) {
|
|
4357
|
-
const alterTableContext =
|
|
4845
|
+
const alterTableContext = context.spawn('AlterTableCmd', { subtype: 'AT_ResetOptions' });
|
|
4358
4846
|
const options = list_utils_1.ListUtils.unwrapList(node.def)
|
|
4359
4847
|
.map(option => this.visit(option, alterTableContext))
|
|
4360
4848
|
.join(', ');
|
|
@@ -4595,7 +5083,7 @@ class Deparser {
|
|
|
4595
5083
|
}
|
|
4596
5084
|
output.push('OPTIONS');
|
|
4597
5085
|
if (node.def) {
|
|
4598
|
-
const alterColumnContext =
|
|
5086
|
+
const alterColumnContext = context.spawn('AlterTableCmd', { alterColumnOptions: true });
|
|
4599
5087
|
const options = list_utils_1.ListUtils.unwrapList(node.def)
|
|
4600
5088
|
.map(option => this.visit(option, alterColumnContext))
|
|
4601
5089
|
.join(', ');
|
|
@@ -4635,7 +5123,7 @@ class Deparser {
|
|
|
4635
5123
|
case 'AT_GenericOptions':
|
|
4636
5124
|
output.push('OPTIONS');
|
|
4637
5125
|
if (node.def) {
|
|
4638
|
-
const alterTableContext =
|
|
5126
|
+
const alterTableContext = context.spawn('AlterTableCmd', { alterTableOptions: true });
|
|
4639
5127
|
const options = list_utils_1.ListUtils.unwrapList(node.def)
|
|
4640
5128
|
.map(option => this.visit(option, alterTableContext))
|
|
4641
5129
|
.join(', ');
|
|
@@ -4647,11 +5135,10 @@ class Deparser {
|
|
|
4647
5135
|
if (node.name) {
|
|
4648
5136
|
output.push(quote_utils_1.QuoteUtils.quote(node.name));
|
|
4649
5137
|
}
|
|
4650
|
-
output.push('ADD
|
|
5138
|
+
output.push('ADD');
|
|
4651
5139
|
if (node.def) {
|
|
4652
5140
|
output.push(this.visit(node.def, context));
|
|
4653
5141
|
}
|
|
4654
|
-
output.push('AS IDENTITY');
|
|
4655
5142
|
break;
|
|
4656
5143
|
case 'AT_SetIdentity':
|
|
4657
5144
|
output.push('ALTER COLUMN');
|
|
@@ -4739,7 +5226,7 @@ class Deparser {
|
|
|
4739
5226
|
output.push(this.TypeName(node.returnType, context));
|
|
4740
5227
|
}
|
|
4741
5228
|
if (node.options && node.options.length > 0) {
|
|
4742
|
-
const funcContext =
|
|
5229
|
+
const funcContext = context.spawn('CreateFunctionStmt');
|
|
4743
5230
|
const options = node.options.map((opt) => this.visit(opt, funcContext));
|
|
4744
5231
|
output.push(...options);
|
|
4745
5232
|
}
|
|
@@ -4826,7 +5313,7 @@ class Deparser {
|
|
|
4826
5313
|
}
|
|
4827
5314
|
output.push('AS', 'ENUM');
|
|
4828
5315
|
if (node.vals && node.vals.length > 0) {
|
|
4829
|
-
const enumContext =
|
|
5316
|
+
const enumContext = context.spawn('CreateEnumStmt', { isEnumValue: true });
|
|
4830
5317
|
const values = list_utils_1.ListUtils.unwrapList(node.vals)
|
|
4831
5318
|
.map(val => this.visit(val, enumContext))
|
|
4832
5319
|
.join(', ');
|
|
@@ -4881,9 +5368,8 @@ class Deparser {
|
|
|
4881
5368
|
output.push(roleName);
|
|
4882
5369
|
}
|
|
4883
5370
|
if (node.options) {
|
|
4884
|
-
const roleContext = { ...context, parentNodeTypes: [...context.parentNodeTypes, 'CreateRoleStmt'] };
|
|
4885
5371
|
const options = list_utils_1.ListUtils.unwrapList(node.options)
|
|
4886
|
-
.map(option => this.visit(option,
|
|
5372
|
+
.map(option => this.visit(option, context.spawn('CreateRoleStmt')))
|
|
4887
5373
|
.join(' ');
|
|
4888
5374
|
if (options) {
|
|
4889
5375
|
output.push('WITH');
|
|
@@ -4914,7 +5400,7 @@ class Deparser {
|
|
|
4914
5400
|
const stringData = this.getNodeData(node.arg);
|
|
4915
5401
|
return `${node.defname}='${stringData.sval}'`;
|
|
4916
5402
|
}
|
|
4917
|
-
return `${node.defname}=${this.visit(node.arg,
|
|
5403
|
+
return `${node.defname}=${this.visit(node.arg, context.spawn('DefElem'))}`;
|
|
4918
5404
|
}
|
|
4919
5405
|
// Handle CREATE OPERATOR boolean flags - MUST be first to preserve case
|
|
4920
5406
|
if (context.parentNodeTypes.includes('DefineStmt') &&
|
|
@@ -4930,13 +5416,13 @@ class Deparser {
|
|
|
4930
5416
|
if (!node.arg) {
|
|
4931
5417
|
return `NO ${node.defname.toUpperCase()}`;
|
|
4932
5418
|
}
|
|
4933
|
-
const defElemContext =
|
|
5419
|
+
const defElemContext = context.spawn('DefElem');
|
|
4934
5420
|
const argValue = this.visit(node.arg, defElemContext);
|
|
4935
5421
|
return `${node.defname.toUpperCase()} ${argValue}`;
|
|
4936
5422
|
}
|
|
4937
5423
|
// Handle OPTIONS clause - use space format, not equals format
|
|
4938
5424
|
if (node.arg) {
|
|
4939
|
-
const defElemContext =
|
|
5425
|
+
const defElemContext = context.spawn('DefElem');
|
|
4940
5426
|
const argValue = this.visit(node.arg, defElemContext);
|
|
4941
5427
|
if (context.parentNodeTypes.includes('CreateFdwStmt') || context.parentNodeTypes.includes('AlterFdwStmt')) {
|
|
4942
5428
|
const finalValue = typeof argValue === 'string' && !argValue.startsWith("'")
|
|
@@ -4990,7 +5476,7 @@ class Deparser {
|
|
|
4990
5476
|
if (!node.arg) {
|
|
4991
5477
|
return 'PASSWORD NULL';
|
|
4992
5478
|
}
|
|
4993
|
-
const defElemContext =
|
|
5479
|
+
const defElemContext = context.spawn('DefElem');
|
|
4994
5480
|
const argValue = this.visit(node.arg, defElemContext);
|
|
4995
5481
|
const quotedValue = typeof argValue === 'string' && !argValue.startsWith("'")
|
|
4996
5482
|
? `'${argValue}'`
|
|
@@ -4999,7 +5485,7 @@ class Deparser {
|
|
|
4999
5485
|
}
|
|
5000
5486
|
}
|
|
5001
5487
|
if (node.arg) {
|
|
5002
|
-
const defElemContext =
|
|
5488
|
+
const defElemContext = context.spawn('DefElem');
|
|
5003
5489
|
const argValue = this.visit(node.arg, defElemContext);
|
|
5004
5490
|
if (context.parentNodeTypes.includes('AlterOperatorStmt')) {
|
|
5005
5491
|
if (node.arg && this.getNodeType(node.arg) === 'TypeName') {
|
|
@@ -5075,7 +5561,7 @@ class Deparser {
|
|
|
5075
5561
|
if (node.defname === 'sysid') {
|
|
5076
5562
|
return `SYSID ${argValue}`;
|
|
5077
5563
|
}
|
|
5078
|
-
if (argValue === 'true') {
|
|
5564
|
+
if (String(argValue) === 'true') {
|
|
5079
5565
|
// Handle special cases where the positive form has a different name
|
|
5080
5566
|
if (node.defname === 'isreplication') {
|
|
5081
5567
|
return 'REPLICATION';
|
|
@@ -5085,7 +5571,7 @@ class Deparser {
|
|
|
5085
5571
|
}
|
|
5086
5572
|
return node.defname.toUpperCase();
|
|
5087
5573
|
}
|
|
5088
|
-
else if (argValue === 'false') {
|
|
5574
|
+
else if (String(argValue) === 'false') {
|
|
5089
5575
|
// Handle special cases where the negative form has a different name
|
|
5090
5576
|
if (node.defname === 'canlogin') {
|
|
5091
5577
|
return 'NOLOGIN';
|
|
@@ -5149,7 +5635,7 @@ class Deparser {
|
|
|
5149
5635
|
}
|
|
5150
5636
|
if (context.parentNodeTypes.includes('DoStmt')) {
|
|
5151
5637
|
if (node.defname === 'as') {
|
|
5152
|
-
const defElemContext =
|
|
5638
|
+
const defElemContext = context.spawn('DefElem');
|
|
5153
5639
|
const argValue = node.arg ? this.visit(node.arg, defElemContext) : '';
|
|
5154
5640
|
if (Array.isArray(argValue)) {
|
|
5155
5641
|
const bodyParts = argValue;
|
|
@@ -5241,11 +5727,15 @@ class Deparser {
|
|
|
5241
5727
|
if (context.parentNodeTypes.includes('CreateExtensionStmt') || context.parentNodeTypes.includes('AlterExtensionStmt') || context.parentNodeTypes.includes('CreateFdwStmt') || context.parentNodeTypes.includes('AlterFdwStmt')) {
|
|
5242
5728
|
// AlterExtensionStmt specific cases
|
|
5243
5729
|
if (context.parentNodeTypes.includes('AlterExtensionStmt')) {
|
|
5244
|
-
if (node.defname === '
|
|
5245
|
-
|
|
5730
|
+
if (node.defname === 'new_version') {
|
|
5731
|
+
// argValue is unquoted due to DefElem context, so we need to quote it
|
|
5732
|
+
const quotedValue = typeof argValue === 'string' && !argValue.startsWith("'")
|
|
5733
|
+
? `'${argValue}'`
|
|
5734
|
+
: argValue;
|
|
5735
|
+
return `UPDATE TO ${quotedValue}`;
|
|
5246
5736
|
}
|
|
5247
5737
|
if (node.defname === 'schema') {
|
|
5248
|
-
return `SCHEMA ${argValue}`;
|
|
5738
|
+
return `SET SCHEMA ${argValue}`;
|
|
5249
5739
|
}
|
|
5250
5740
|
}
|
|
5251
5741
|
// CreateFdwStmt specific cases
|
|
@@ -5440,7 +5930,7 @@ class Deparser {
|
|
|
5440
5930
|
}
|
|
5441
5931
|
if (node.options && node.options.length > 0) {
|
|
5442
5932
|
output.push('WITH');
|
|
5443
|
-
const tsContext =
|
|
5933
|
+
const tsContext = context.spawn('CreateTableSpaceStmt');
|
|
5444
5934
|
const options = list_utils_1.ListUtils.unwrapList(node.options)
|
|
5445
5935
|
.map(option => this.visit(option, tsContext))
|
|
5446
5936
|
.join(', ');
|
|
@@ -5470,7 +5960,7 @@ class Deparser {
|
|
|
5470
5960
|
output.push('SET');
|
|
5471
5961
|
}
|
|
5472
5962
|
if (node.options && node.options.length > 0) {
|
|
5473
|
-
const tablespaceContext =
|
|
5963
|
+
const tablespaceContext = context.spawn('AlterTableSpaceOptionsStmt');
|
|
5474
5964
|
const options = list_utils_1.ListUtils.unwrapList(node.options)
|
|
5475
5965
|
.map(option => this.visit(option, tablespaceContext))
|
|
5476
5966
|
.join(', ');
|
|
@@ -5487,7 +5977,7 @@ class Deparser {
|
|
|
5487
5977
|
output.push(this.quoteIfNeeded(node.extname));
|
|
5488
5978
|
}
|
|
5489
5979
|
if (node.options && node.options.length > 0) {
|
|
5490
|
-
const extContext =
|
|
5980
|
+
const extContext = context.spawn('CreateExtensionStmt');
|
|
5491
5981
|
const options = list_utils_1.ListUtils.unwrapList(node.options)
|
|
5492
5982
|
.map(option => this.visit(option, extContext))
|
|
5493
5983
|
.join(' ');
|
|
@@ -5501,7 +5991,7 @@ class Deparser {
|
|
|
5501
5991
|
output.push(this.quoteIfNeeded(node.extname));
|
|
5502
5992
|
}
|
|
5503
5993
|
if (node.options && node.options.length > 0) {
|
|
5504
|
-
const extContext =
|
|
5994
|
+
const extContext = context.spawn('AlterExtensionStmt');
|
|
5505
5995
|
const options = list_utils_1.ListUtils.unwrapList(node.options)
|
|
5506
5996
|
.map(option => this.visit(option, extContext))
|
|
5507
5997
|
.join(' ');
|
|
@@ -5509,13 +5999,41 @@ class Deparser {
|
|
|
5509
5999
|
}
|
|
5510
6000
|
return output.join(' ');
|
|
5511
6001
|
}
|
|
6002
|
+
AlterExtensionContentsStmt(node, context) {
|
|
6003
|
+
const output = ['ALTER', 'EXTENSION'];
|
|
6004
|
+
if (node.extname) {
|
|
6005
|
+
output.push(this.quoteIfNeeded(node.extname));
|
|
6006
|
+
}
|
|
6007
|
+
// Handle action: 1 = ADD, -1 = DROP
|
|
6008
|
+
if (node.action === 1) {
|
|
6009
|
+
output.push('ADD');
|
|
6010
|
+
}
|
|
6011
|
+
else if (node.action === -1) {
|
|
6012
|
+
output.push('DROP');
|
|
6013
|
+
}
|
|
6014
|
+
// Add object type keyword
|
|
6015
|
+
if (node.objtype) {
|
|
6016
|
+
try {
|
|
6017
|
+
output.push(this.getObjectTypeKeyword(node.objtype));
|
|
6018
|
+
}
|
|
6019
|
+
catch {
|
|
6020
|
+
// Fallback to the raw objtype if not supported
|
|
6021
|
+
output.push(node.objtype.toString());
|
|
6022
|
+
}
|
|
6023
|
+
}
|
|
6024
|
+
// Add the object itself
|
|
6025
|
+
if (node.object) {
|
|
6026
|
+
output.push(this.visit(node.object, context));
|
|
6027
|
+
}
|
|
6028
|
+
return output.join(' ');
|
|
6029
|
+
}
|
|
5512
6030
|
CreateFdwStmt(node, context) {
|
|
5513
6031
|
const output = ['CREATE', 'FOREIGN', 'DATA', 'WRAPPER'];
|
|
5514
6032
|
if (node.fdwname) {
|
|
5515
6033
|
output.push(node.fdwname);
|
|
5516
6034
|
}
|
|
5517
6035
|
if (node.func_options && node.func_options.length > 0) {
|
|
5518
|
-
const fdwContext =
|
|
6036
|
+
const fdwContext = context.spawn('CreateFdwStmt');
|
|
5519
6037
|
const funcOptions = list_utils_1.ListUtils.unwrapList(node.func_options)
|
|
5520
6038
|
.map(option => this.visit(option, fdwContext))
|
|
5521
6039
|
.join(' ');
|
|
@@ -5523,7 +6041,7 @@ class Deparser {
|
|
|
5523
6041
|
}
|
|
5524
6042
|
if (node.options && node.options.length > 0) {
|
|
5525
6043
|
output.push('OPTIONS');
|
|
5526
|
-
const fdwContext =
|
|
6044
|
+
const fdwContext = context.spawn('CreateFdwStmt');
|
|
5527
6045
|
const options = list_utils_1.ListUtils.unwrapList(node.options)
|
|
5528
6046
|
.map(option => this.visit(option, fdwContext))
|
|
5529
6047
|
.join(', ');
|
|
@@ -5625,7 +6143,7 @@ class Deparser {
|
|
|
5625
6143
|
output.push('ADD');
|
|
5626
6144
|
if (node.def) {
|
|
5627
6145
|
// Pass domain context to avoid adding constraint names for domain constraints
|
|
5628
|
-
const domainContext =
|
|
6146
|
+
const domainContext = context.spawn('CreateDomainStmt', { isDomainConstraint: true });
|
|
5629
6147
|
output.push(this.visit(node.def, domainContext));
|
|
5630
6148
|
}
|
|
5631
6149
|
break;
|
|
@@ -5651,7 +6169,7 @@ class Deparser {
|
|
|
5651
6169
|
output.push('ADD');
|
|
5652
6170
|
if (node.def) {
|
|
5653
6171
|
// Pass domain context to avoid adding constraint names for domain constraints
|
|
5654
|
-
const domainContext =
|
|
6172
|
+
const domainContext = context.spawn('CreateDomainStmt', { isDomainConstraint: true });
|
|
5655
6173
|
output.push(this.visit(node.def, domainContext));
|
|
5656
6174
|
}
|
|
5657
6175
|
break;
|
|
@@ -6013,7 +6531,7 @@ class Deparser {
|
|
|
6013
6531
|
output.push(`${operatorName}(${args.join(', ')})`);
|
|
6014
6532
|
}
|
|
6015
6533
|
else {
|
|
6016
|
-
const objContext =
|
|
6534
|
+
const objContext = context.spawn('CommentStmt', { objtype: node.objtype });
|
|
6017
6535
|
output.push(this.visit(node.object, objContext));
|
|
6018
6536
|
}
|
|
6019
6537
|
}
|
|
@@ -6059,13 +6577,13 @@ class Deparser {
|
|
|
6059
6577
|
const output = [];
|
|
6060
6578
|
const initialParts = ['CREATE', 'POLICY'];
|
|
6061
6579
|
if (node.policy_name) {
|
|
6062
|
-
initialParts.push(
|
|
6580
|
+
initialParts.push(quote_utils_1.QuoteUtils.quote(node.policy_name));
|
|
6063
6581
|
}
|
|
6064
6582
|
output.push(initialParts.join(' '));
|
|
6065
6583
|
// Add ON clause on new line in pretty mode
|
|
6066
6584
|
if (node.table) {
|
|
6067
|
-
if (
|
|
6068
|
-
output.push(
|
|
6585
|
+
if (context.isPretty()) {
|
|
6586
|
+
output.push(context.newline() + context.indent(`ON ${this.RangeVar(node.table, context)}`));
|
|
6069
6587
|
}
|
|
6070
6588
|
else {
|
|
6071
6589
|
output.push('ON');
|
|
@@ -6074,24 +6592,24 @@ class Deparser {
|
|
|
6074
6592
|
}
|
|
6075
6593
|
// Handle AS RESTRICTIVE/PERMISSIVE clause
|
|
6076
6594
|
if (node.permissive === undefined) {
|
|
6077
|
-
if (
|
|
6078
|
-
output.push(
|
|
6595
|
+
if (context.isPretty()) {
|
|
6596
|
+
output.push(context.newline() + context.indent('AS RESTRICTIVE'));
|
|
6079
6597
|
}
|
|
6080
6598
|
else {
|
|
6081
6599
|
output.push('AS', 'RESTRICTIVE');
|
|
6082
6600
|
}
|
|
6083
6601
|
}
|
|
6084
6602
|
else if (node.permissive === true) {
|
|
6085
|
-
if (
|
|
6086
|
-
output.push(
|
|
6603
|
+
if (context.isPretty()) {
|
|
6604
|
+
output.push(context.newline() + context.indent('AS PERMISSIVE'));
|
|
6087
6605
|
}
|
|
6088
6606
|
else {
|
|
6089
6607
|
output.push('AS', 'PERMISSIVE');
|
|
6090
6608
|
}
|
|
6091
6609
|
}
|
|
6092
6610
|
if (node.cmd_name) {
|
|
6093
|
-
if (
|
|
6094
|
-
output.push(
|
|
6611
|
+
if (context.isPretty()) {
|
|
6612
|
+
output.push(context.newline() + context.indent(`FOR ${node.cmd_name.toUpperCase()}`));
|
|
6095
6613
|
}
|
|
6096
6614
|
else {
|
|
6097
6615
|
output.push('FOR', node.cmd_name.toUpperCase());
|
|
@@ -6099,8 +6617,8 @@ class Deparser {
|
|
|
6099
6617
|
}
|
|
6100
6618
|
if (node.roles && node.roles.length > 0) {
|
|
6101
6619
|
const roles = list_utils_1.ListUtils.unwrapList(node.roles).map(role => this.visit(role, context));
|
|
6102
|
-
if (
|
|
6103
|
-
output.push(
|
|
6620
|
+
if (context.isPretty()) {
|
|
6621
|
+
output.push(context.newline() + context.indent(`TO ${roles.join(', ')}`));
|
|
6104
6622
|
}
|
|
6105
6623
|
else {
|
|
6106
6624
|
output.push('TO');
|
|
@@ -6108,11 +6626,11 @@ class Deparser {
|
|
|
6108
6626
|
}
|
|
6109
6627
|
}
|
|
6110
6628
|
if (node.qual) {
|
|
6111
|
-
if (
|
|
6629
|
+
if (context.isPretty()) {
|
|
6112
6630
|
const qualExpr = this.visit(node.qual, context);
|
|
6113
|
-
output.push(
|
|
6114
|
-
output.push(
|
|
6115
|
-
output.push(
|
|
6631
|
+
output.push(context.newline() + context.indent('USING ('));
|
|
6632
|
+
output.push(context.newline() + context.indent(context.indent(qualExpr)));
|
|
6633
|
+
output.push(context.newline() + context.indent(')'));
|
|
6116
6634
|
}
|
|
6117
6635
|
else {
|
|
6118
6636
|
output.push('USING');
|
|
@@ -6120,23 +6638,23 @@ class Deparser {
|
|
|
6120
6638
|
}
|
|
6121
6639
|
}
|
|
6122
6640
|
if (node.with_check) {
|
|
6123
|
-
if (
|
|
6641
|
+
if (context.isPretty()) {
|
|
6124
6642
|
const checkExpr = this.visit(node.with_check, context);
|
|
6125
|
-
output.push(
|
|
6126
|
-
output.push(
|
|
6127
|
-
output.push(
|
|
6643
|
+
output.push(context.newline() + context.indent('WITH CHECK ('));
|
|
6644
|
+
output.push(context.newline() + context.indent(context.indent(checkExpr)));
|
|
6645
|
+
output.push(context.newline() + context.indent(')'));
|
|
6128
6646
|
}
|
|
6129
6647
|
else {
|
|
6130
6648
|
output.push('WITH CHECK');
|
|
6131
6649
|
output.push(`(${this.visit(node.with_check, context)})`);
|
|
6132
6650
|
}
|
|
6133
6651
|
}
|
|
6134
|
-
return
|
|
6652
|
+
return context.isPretty() ? output.join('') : output.join(' ');
|
|
6135
6653
|
}
|
|
6136
6654
|
AlterPolicyStmt(node, context) {
|
|
6137
6655
|
const output = ['ALTER', 'POLICY'];
|
|
6138
6656
|
if (node.policy_name) {
|
|
6139
|
-
output.push(
|
|
6657
|
+
output.push(quote_utils_1.QuoteUtils.quote(node.policy_name));
|
|
6140
6658
|
}
|
|
6141
6659
|
if (node.table) {
|
|
6142
6660
|
output.push('ON');
|
|
@@ -6176,7 +6694,7 @@ class Deparser {
|
|
|
6176
6694
|
}
|
|
6177
6695
|
if (node.options && node.options.length > 0) {
|
|
6178
6696
|
output.push('OPTIONS');
|
|
6179
|
-
const userMappingContext =
|
|
6697
|
+
const userMappingContext = context.spawn('CreateUserMappingStmt');
|
|
6180
6698
|
const options = list_utils_1.ListUtils.unwrapList(node.options).map(opt => this.visit(opt, userMappingContext));
|
|
6181
6699
|
output.push(`(${options.join(', ')})`);
|
|
6182
6700
|
}
|
|
@@ -6359,7 +6877,7 @@ class Deparser {
|
|
|
6359
6877
|
DoStmt(node, context) {
|
|
6360
6878
|
const output = ['DO'];
|
|
6361
6879
|
if (node.args && node.args.length > 0) {
|
|
6362
|
-
const doContext =
|
|
6880
|
+
const doContext = context.spawn('DoStmt');
|
|
6363
6881
|
const args = list_utils_1.ListUtils.unwrapList(node.args);
|
|
6364
6882
|
const processedArgs = [];
|
|
6365
6883
|
for (const arg of args) {
|
|
@@ -6664,7 +7182,7 @@ class Deparser {
|
|
|
6664
7182
|
ObjectWithArgs(node, context) {
|
|
6665
7183
|
let result = '';
|
|
6666
7184
|
if (node.objname && node.objname.length > 0) {
|
|
6667
|
-
const objContext =
|
|
7185
|
+
const objContext = context.spawn('ObjectWithArgs');
|
|
6668
7186
|
const names = list_utils_1.ListUtils.unwrapList(node.objname).map(name => this.visit(name, objContext));
|
|
6669
7187
|
result = names.join('.');
|
|
6670
7188
|
}
|
|
@@ -6706,7 +7224,7 @@ class Deparser {
|
|
|
6706
7224
|
}
|
|
6707
7225
|
output.push('SET');
|
|
6708
7226
|
if (node.options && node.options.length > 0) {
|
|
6709
|
-
const alterOpContext =
|
|
7227
|
+
const alterOpContext = context.spawn('AlterOperatorStmt');
|
|
6710
7228
|
const options = list_utils_1.ListUtils.unwrapList(node.options).map(opt => this.visit(opt, alterOpContext));
|
|
6711
7229
|
output.push(`(${options.join(', ')})`);
|
|
6712
7230
|
}
|
|
@@ -6718,13 +7236,13 @@ class Deparser {
|
|
|
6718
7236
|
output.push(quote_utils_1.QuoteUtils.quote(node.fdwname));
|
|
6719
7237
|
}
|
|
6720
7238
|
if (node.func_options && node.func_options.length > 0) {
|
|
6721
|
-
const fdwContext =
|
|
7239
|
+
const fdwContext = context.spawn('AlterFdwStmt');
|
|
6722
7240
|
const funcOptions = list_utils_1.ListUtils.unwrapList(node.func_options).map(opt => this.visit(opt, fdwContext));
|
|
6723
7241
|
output.push(funcOptions.join(' '));
|
|
6724
7242
|
}
|
|
6725
7243
|
if (node.options && node.options.length > 0) {
|
|
6726
7244
|
output.push('OPTIONS');
|
|
6727
|
-
const fdwContext =
|
|
7245
|
+
const fdwContext = context.spawn('AlterFdwStmt');
|
|
6728
7246
|
const options = list_utils_1.ListUtils.unwrapList(node.options).map(opt => this.visit(opt, fdwContext));
|
|
6729
7247
|
output.push(`(${options.join(', ')})`);
|
|
6730
7248
|
}
|
|
@@ -6750,7 +7268,7 @@ class Deparser {
|
|
|
6750
7268
|
if (node.options && node.options.length > 0) {
|
|
6751
7269
|
output.push('OPTIONS');
|
|
6752
7270
|
output.push('(');
|
|
6753
|
-
const optionsContext =
|
|
7271
|
+
const optionsContext = context.spawn('CreateForeignServerStmt');
|
|
6754
7272
|
const options = list_utils_1.ListUtils.unwrapList(node.options).map(opt => this.visit(opt, optionsContext));
|
|
6755
7273
|
output.push(options.join(', '));
|
|
6756
7274
|
output.push(')');
|
|
@@ -6768,7 +7286,7 @@ class Deparser {
|
|
|
6768
7286
|
if (node.options && node.options.length > 0) {
|
|
6769
7287
|
output.push('OPTIONS');
|
|
6770
7288
|
output.push('(');
|
|
6771
|
-
const optionsContext =
|
|
7289
|
+
const optionsContext = context.spawn('AlterForeignServerStmt');
|
|
6772
7290
|
const options = list_utils_1.ListUtils.unwrapList(node.options).map(opt => this.visit(opt, optionsContext));
|
|
6773
7291
|
output.push(options.join(', '));
|
|
6774
7292
|
output.push(')');
|
|
@@ -6789,7 +7307,7 @@ class Deparser {
|
|
|
6789
7307
|
}
|
|
6790
7308
|
if (node.options && node.options.length > 0) {
|
|
6791
7309
|
output.push('OPTIONS');
|
|
6792
|
-
const userMappingContext =
|
|
7310
|
+
const userMappingContext = context.spawn('AlterUserMappingStmt');
|
|
6793
7311
|
const options = list_utils_1.ListUtils.unwrapList(node.options).map(opt => this.visit(opt, userMappingContext));
|
|
6794
7312
|
output.push(`(${options.join(', ')})`);
|
|
6795
7313
|
}
|
|
@@ -6849,7 +7367,7 @@ class Deparser {
|
|
|
6849
7367
|
output.push(quote_utils_1.QuoteUtils.quote(node.local_schema));
|
|
6850
7368
|
}
|
|
6851
7369
|
if (node.options && node.options.length > 0) {
|
|
6852
|
-
const importSchemaContext =
|
|
7370
|
+
const importSchemaContext = context.spawn('ImportForeignSchemaStmt');
|
|
6853
7371
|
const options = list_utils_1.ListUtils.unwrapList(node.options).map(opt => this.visit(opt, importSchemaContext));
|
|
6854
7372
|
output.push(`OPTIONS (${options.join(', ')})`);
|
|
6855
7373
|
}
|
|
@@ -6884,7 +7402,7 @@ class Deparser {
|
|
|
6884
7402
|
ExplainStmt(node, context) {
|
|
6885
7403
|
const output = ['EXPLAIN'];
|
|
6886
7404
|
if (node.options && node.options.length > 0) {
|
|
6887
|
-
const explainContext =
|
|
7405
|
+
const explainContext = context.spawn('ExplainStmt');
|
|
6888
7406
|
const options = list_utils_1.ListUtils.unwrapList(node.options).map(option => this.visit(option, explainContext));
|
|
6889
7407
|
output.push(`(${options.join(', ')})`);
|
|
6890
7408
|
}
|
|
@@ -7142,9 +7660,7 @@ class Deparser {
|
|
|
7142
7660
|
output.push(this.RangeVar(node.relation, context));
|
|
7143
7661
|
}
|
|
7144
7662
|
else if (node.relation) {
|
|
7145
|
-
const rangeVarContext = node.relationType
|
|
7146
|
-
? { ...context, parentNodeTypes: [...context.parentNodeTypes, 'AlterTypeStmt'] }
|
|
7147
|
-
: context;
|
|
7663
|
+
const rangeVarContext = context.spawn('RenameStmt', { objtype: node.relationType });
|
|
7148
7664
|
// Add ON keyword for policy operations
|
|
7149
7665
|
if (node.renameType === 'OBJECT_POLICY') {
|
|
7150
7666
|
output.push('ON');
|
|
@@ -7217,76 +7733,7 @@ class Deparser {
|
|
|
7217
7733
|
if (!node.objectType) {
|
|
7218
7734
|
throw new Error('AlterOwnerStmt requires objectType');
|
|
7219
7735
|
}
|
|
7220
|
-
|
|
7221
|
-
case 'OBJECT_TABLE':
|
|
7222
|
-
output.push('TABLE');
|
|
7223
|
-
break;
|
|
7224
|
-
case 'OBJECT_VIEW':
|
|
7225
|
-
output.push('VIEW');
|
|
7226
|
-
break;
|
|
7227
|
-
case 'OBJECT_INDEX':
|
|
7228
|
-
output.push('INDEX');
|
|
7229
|
-
break;
|
|
7230
|
-
case 'OBJECT_SEQUENCE':
|
|
7231
|
-
output.push('SEQUENCE');
|
|
7232
|
-
break;
|
|
7233
|
-
case 'OBJECT_FUNCTION':
|
|
7234
|
-
output.push('FUNCTION');
|
|
7235
|
-
break;
|
|
7236
|
-
case 'OBJECT_PROCEDURE':
|
|
7237
|
-
output.push('PROCEDURE');
|
|
7238
|
-
break;
|
|
7239
|
-
case 'OBJECT_SCHEMA':
|
|
7240
|
-
output.push('SCHEMA');
|
|
7241
|
-
break;
|
|
7242
|
-
case 'OBJECT_DATABASE':
|
|
7243
|
-
output.push('DATABASE');
|
|
7244
|
-
break;
|
|
7245
|
-
case 'OBJECT_DOMAIN':
|
|
7246
|
-
output.push('DOMAIN');
|
|
7247
|
-
break;
|
|
7248
|
-
case 'OBJECT_AGGREGATE':
|
|
7249
|
-
output.push('AGGREGATE');
|
|
7250
|
-
break;
|
|
7251
|
-
case 'OBJECT_CONVERSION':
|
|
7252
|
-
output.push('CONVERSION');
|
|
7253
|
-
break;
|
|
7254
|
-
case 'OBJECT_LANGUAGE':
|
|
7255
|
-
output.push('LANGUAGE');
|
|
7256
|
-
break;
|
|
7257
|
-
case 'OBJECT_OPERATOR':
|
|
7258
|
-
output.push('OPERATOR');
|
|
7259
|
-
break;
|
|
7260
|
-
case 'OBJECT_OPFAMILY':
|
|
7261
|
-
output.push('OPERATOR FAMILY');
|
|
7262
|
-
break;
|
|
7263
|
-
case 'OBJECT_OPCLASS':
|
|
7264
|
-
output.push('OPERATOR CLASS');
|
|
7265
|
-
break;
|
|
7266
|
-
case 'OBJECT_TSDICTIONARY':
|
|
7267
|
-
output.push('TEXT SEARCH DICTIONARY');
|
|
7268
|
-
break;
|
|
7269
|
-
case 'OBJECT_TSCONFIGURATION':
|
|
7270
|
-
output.push('TEXT SEARCH CONFIGURATION');
|
|
7271
|
-
break;
|
|
7272
|
-
case 'OBJECT_EVENT_TRIGGER':
|
|
7273
|
-
output.push('EVENT TRIGGER');
|
|
7274
|
-
break;
|
|
7275
|
-
case 'OBJECT_FDW':
|
|
7276
|
-
output.push('FOREIGN DATA WRAPPER');
|
|
7277
|
-
break;
|
|
7278
|
-
case 'OBJECT_FOREIGN_SERVER':
|
|
7279
|
-
output.push('SERVER');
|
|
7280
|
-
break;
|
|
7281
|
-
case 'OBJECT_TYPE':
|
|
7282
|
-
output.push('TYPE');
|
|
7283
|
-
break;
|
|
7284
|
-
case 'OBJECT_COLLATION':
|
|
7285
|
-
output.push('COLLATION');
|
|
7286
|
-
break;
|
|
7287
|
-
default:
|
|
7288
|
-
throw new Error(`Unsupported AlterOwnerStmt objectType: ${node.objectType}`);
|
|
7289
|
-
}
|
|
7736
|
+
output.push(this.getObjectTypeKeyword(node.objectType));
|
|
7290
7737
|
if (node.relation) {
|
|
7291
7738
|
output.push(this.RangeVar(node.relation, context));
|
|
7292
7739
|
}
|
|
@@ -7326,7 +7773,7 @@ class Deparser {
|
|
|
7326
7773
|
}
|
|
7327
7774
|
}
|
|
7328
7775
|
if (node.privileges && node.privileges.length > 0) {
|
|
7329
|
-
const privilegeContext =
|
|
7776
|
+
const privilegeContext = context.spawn('GrantStmt');
|
|
7330
7777
|
const privileges = list_utils_1.ListUtils.unwrapList(node.privileges)
|
|
7331
7778
|
.map(priv => this.visit(priv, privilegeContext))
|
|
7332
7779
|
.join(', ');
|
|
@@ -7634,7 +8081,12 @@ class Deparser {
|
|
|
7634
8081
|
}
|
|
7635
8082
|
if (node.action) {
|
|
7636
8083
|
const actionStr = this.GrantStmt(node.action, context);
|
|
7637
|
-
|
|
8084
|
+
if (context.isPretty()) {
|
|
8085
|
+
return output.join(' ') + context.newline() + context.indent(actionStr);
|
|
8086
|
+
}
|
|
8087
|
+
else {
|
|
8088
|
+
output.push(actionStr);
|
|
8089
|
+
}
|
|
7638
8090
|
}
|
|
7639
8091
|
return output.join(' ');
|
|
7640
8092
|
}
|
|
@@ -7781,84 +8233,158 @@ class Deparser {
|
|
|
7781
8233
|
if (node.trigname) {
|
|
7782
8234
|
output.push(quote_utils_1.QuoteUtils.quote(node.trigname));
|
|
7783
8235
|
}
|
|
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(')');
|
|
8236
|
+
if (context.isPretty()) {
|
|
8237
|
+
const components = [];
|
|
8238
|
+
const timing = [];
|
|
8239
|
+
if (node.timing & 2)
|
|
8240
|
+
timing.push('BEFORE');
|
|
8241
|
+
else if (node.timing & 64)
|
|
8242
|
+
timing.push('INSTEAD OF');
|
|
8243
|
+
else
|
|
8244
|
+
timing.push('AFTER');
|
|
8245
|
+
const events = [];
|
|
8246
|
+
if (node.events & 4)
|
|
8247
|
+
events.push('INSERT');
|
|
8248
|
+
if (node.events & 8)
|
|
8249
|
+
events.push('DELETE');
|
|
8250
|
+
if (node.events & 16) {
|
|
8251
|
+
let updateStr = 'UPDATE';
|
|
8252
|
+
if (node.columns && node.columns.length > 0) {
|
|
8253
|
+
const columnNames = list_utils_1.ListUtils.unwrapList(node.columns)
|
|
8254
|
+
.map(col => this.visit(col, context))
|
|
8255
|
+
.join(', ');
|
|
8256
|
+
updateStr += ' OF ' + columnNames;
|
|
8257
|
+
}
|
|
8258
|
+
events.push(updateStr);
|
|
8259
|
+
}
|
|
8260
|
+
if (node.events & 32)
|
|
8261
|
+
events.push('TRUNCATE');
|
|
8262
|
+
components.push(context.indent(timing.join(' ') + ' ' + events.join(' OR ')));
|
|
8263
|
+
if (node.relation) {
|
|
8264
|
+
components.push(context.indent('ON ' + this.RangeVar(node.relation, context)));
|
|
8265
|
+
}
|
|
8266
|
+
if (node.transitionRels && node.transitionRels.length > 0) {
|
|
8267
|
+
const transitionClauses = list_utils_1.ListUtils.unwrapList(node.transitionRels)
|
|
8268
|
+
.map(rel => this.visit(rel, context))
|
|
8269
|
+
.join(' ');
|
|
8270
|
+
components.push(context.indent('REFERENCING ' + transitionClauses));
|
|
8271
|
+
}
|
|
8272
|
+
if (node.deferrable) {
|
|
8273
|
+
components.push(context.indent('DEFERRABLE'));
|
|
8274
|
+
}
|
|
8275
|
+
if (node.initdeferred) {
|
|
8276
|
+
components.push(context.indent('INITIALLY DEFERRED'));
|
|
8277
|
+
}
|
|
8278
|
+
if (node.row) {
|
|
8279
|
+
components.push(context.indent('FOR EACH ROW'));
|
|
8280
|
+
}
|
|
8281
|
+
else {
|
|
8282
|
+
components.push(context.indent('FOR EACH STATEMENT'));
|
|
8283
|
+
}
|
|
8284
|
+
if (node.whenClause) {
|
|
8285
|
+
const whenStr = 'WHEN (' + this.visit(node.whenClause, context) + ')';
|
|
8286
|
+
components.push(context.indent(whenStr));
|
|
8287
|
+
}
|
|
8288
|
+
let executeStr = 'EXECUTE';
|
|
8289
|
+
if (node.funcname && node.funcname.length > 0) {
|
|
8290
|
+
const funcName = list_utils_1.ListUtils.unwrapList(node.funcname)
|
|
8291
|
+
.map(name => this.visit(name, context))
|
|
8292
|
+
.join('.');
|
|
8293
|
+
executeStr += ' PROCEDURE ' + funcName;
|
|
8294
|
+
}
|
|
8295
|
+
if (node.args && node.args.length > 0) {
|
|
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
|
+
executeStr += '(' + args + ')';
|
|
8301
|
+
}
|
|
8302
|
+
else {
|
|
8303
|
+
executeStr += '()';
|
|
8304
|
+
}
|
|
8305
|
+
components.push(context.indent(executeStr));
|
|
8306
|
+
return output.join(' ') + context.newline() + components.join(context.newline());
|
|
7857
8307
|
}
|
|
7858
8308
|
else {
|
|
7859
|
-
|
|
8309
|
+
const timing = [];
|
|
8310
|
+
if (node.timing & 2)
|
|
8311
|
+
timing.push('BEFORE');
|
|
8312
|
+
else if (node.timing & 64)
|
|
8313
|
+
timing.push('INSTEAD OF');
|
|
8314
|
+
else
|
|
8315
|
+
timing.push('AFTER');
|
|
8316
|
+
output.push(timing.join(' '));
|
|
8317
|
+
const events = [];
|
|
8318
|
+
if (node.events & 4)
|
|
8319
|
+
events.push('INSERT');
|
|
8320
|
+
if (node.events & 8)
|
|
8321
|
+
events.push('DELETE');
|
|
8322
|
+
if (node.events & 16)
|
|
8323
|
+
events.push('UPDATE');
|
|
8324
|
+
if (node.events & 32)
|
|
8325
|
+
events.push('TRUNCATE');
|
|
8326
|
+
output.push(events.join(' OR '));
|
|
8327
|
+
if (node.columns && node.columns.length > 0) {
|
|
8328
|
+
output.push('OF');
|
|
8329
|
+
const columnNames = list_utils_1.ListUtils.unwrapList(node.columns)
|
|
8330
|
+
.map(col => this.visit(col, context))
|
|
8331
|
+
.join(', ');
|
|
8332
|
+
output.push(columnNames);
|
|
8333
|
+
}
|
|
8334
|
+
output.push('ON');
|
|
8335
|
+
if (node.relation) {
|
|
8336
|
+
output.push(this.RangeVar(node.relation, context));
|
|
8337
|
+
}
|
|
8338
|
+
if (node.constrrel) {
|
|
8339
|
+
output.push('FROM');
|
|
8340
|
+
output.push(this.RangeVar(node.constrrel, context));
|
|
8341
|
+
}
|
|
8342
|
+
if (node.deferrable) {
|
|
8343
|
+
output.push('DEFERRABLE');
|
|
8344
|
+
}
|
|
8345
|
+
if (node.initdeferred) {
|
|
8346
|
+
output.push('INITIALLY DEFERRED');
|
|
8347
|
+
}
|
|
8348
|
+
if (node.transitionRels && node.transitionRels.length > 0) {
|
|
8349
|
+
output.push('REFERENCING');
|
|
8350
|
+
const transitionClauses = list_utils_1.ListUtils.unwrapList(node.transitionRels)
|
|
8351
|
+
.map(rel => this.visit(rel, context))
|
|
8352
|
+
.join(' ');
|
|
8353
|
+
output.push(transitionClauses);
|
|
8354
|
+
}
|
|
8355
|
+
if (node.row) {
|
|
8356
|
+
output.push('FOR EACH ROW');
|
|
8357
|
+
}
|
|
8358
|
+
else {
|
|
8359
|
+
output.push('FOR EACH STATEMENT');
|
|
8360
|
+
}
|
|
8361
|
+
if (node.whenClause) {
|
|
8362
|
+
output.push('WHEN');
|
|
8363
|
+
output.push('(');
|
|
8364
|
+
output.push(this.visit(node.whenClause, context));
|
|
8365
|
+
output.push(')');
|
|
8366
|
+
}
|
|
8367
|
+
output.push('EXECUTE');
|
|
8368
|
+
if (node.funcname && node.funcname.length > 0) {
|
|
8369
|
+
const funcName = list_utils_1.ListUtils.unwrapList(node.funcname)
|
|
8370
|
+
.map(name => this.visit(name, context))
|
|
8371
|
+
.join('.');
|
|
8372
|
+
output.push('FUNCTION', funcName);
|
|
8373
|
+
}
|
|
8374
|
+
if (node.args && node.args.length > 0) {
|
|
8375
|
+
output.push('(');
|
|
8376
|
+
const argContext = context.spawn('CreateTrigStmt', { isStringLiteral: true });
|
|
8377
|
+
const args = list_utils_1.ListUtils.unwrapList(node.args)
|
|
8378
|
+
.map(arg => this.visit(arg, argContext))
|
|
8379
|
+
.join(', ');
|
|
8380
|
+
output.push(args);
|
|
8381
|
+
output.push(')');
|
|
8382
|
+
}
|
|
8383
|
+
else {
|
|
8384
|
+
output.push('()');
|
|
8385
|
+
}
|
|
8386
|
+
return output.join(' ');
|
|
7860
8387
|
}
|
|
7861
|
-
return output.join(' ');
|
|
7862
8388
|
}
|
|
7863
8389
|
TriggerTransition(node, context) {
|
|
7864
8390
|
const output = [];
|
|
@@ -7884,7 +8410,7 @@ class Deparser {
|
|
|
7884
8410
|
}
|
|
7885
8411
|
if (node.whenclause && node.whenclause.length > 0) {
|
|
7886
8412
|
output.push('WHEN');
|
|
7887
|
-
const eventTriggerContext =
|
|
8413
|
+
const eventTriggerContext = context.spawn('CreateEventTrigStmt');
|
|
7888
8414
|
const conditions = list_utils_1.ListUtils.unwrapList(node.whenclause)
|
|
7889
8415
|
.map(condition => this.visit(condition, eventTriggerContext))
|
|
7890
8416
|
.join(' AND ');
|
|
@@ -8073,7 +8599,7 @@ class Deparser {
|
|
|
8073
8599
|
output.push(sequenceName.join('.'));
|
|
8074
8600
|
}
|
|
8075
8601
|
if (node.options && node.options.length > 0) {
|
|
8076
|
-
const seqContext =
|
|
8602
|
+
const seqContext = context.spawn('CreateSeqStmt');
|
|
8077
8603
|
const optionStrs = list_utils_1.ListUtils.unwrapList(node.options)
|
|
8078
8604
|
.filter(option => option != null && this.getNodeType(option) !== 'undefined')
|
|
8079
8605
|
.map(option => {
|
|
@@ -8110,7 +8636,7 @@ class Deparser {
|
|
|
8110
8636
|
output.push(sequenceName.join('.'));
|
|
8111
8637
|
}
|
|
8112
8638
|
if (node.options && node.options.length > 0) {
|
|
8113
|
-
const seqContext =
|
|
8639
|
+
const seqContext = context.spawn('AlterSeqStmt');
|
|
8114
8640
|
const optionStrs = list_utils_1.ListUtils.unwrapList(node.options)
|
|
8115
8641
|
.filter(option => option && option !== undefined)
|
|
8116
8642
|
.map(option => {
|
|
@@ -8139,7 +8665,7 @@ class Deparser {
|
|
|
8139
8665
|
CompositeTypeStmt(node, context) {
|
|
8140
8666
|
const output = ['CREATE', 'TYPE'];
|
|
8141
8667
|
if (node.typevar) {
|
|
8142
|
-
const typeContext =
|
|
8668
|
+
const typeContext = context.spawn('CompositeTypeStmt');
|
|
8143
8669
|
output.push(this.RangeVar(node.typevar, typeContext));
|
|
8144
8670
|
}
|
|
8145
8671
|
output.push('AS');
|
|
@@ -8240,7 +8766,7 @@ class Deparser {
|
|
|
8240
8766
|
output.push(this.RoleSpec(node.role, context));
|
|
8241
8767
|
}
|
|
8242
8768
|
if (node.options) {
|
|
8243
|
-
const roleContext =
|
|
8769
|
+
const roleContext = context.spawn('AlterRoleStmt');
|
|
8244
8770
|
// Handle GROUP operations specially based on action value
|
|
8245
8771
|
if (isGroupStatement) {
|
|
8246
8772
|
const roleMembersOption = list_utils_1.ListUtils.unwrapList(node.options).find(option => option.DefElem && option.DefElem.defname === 'rolemembers');
|
|
@@ -8436,14 +8962,14 @@ class Deparser {
|
|
|
8436
8962
|
AccessPriv(node, context) {
|
|
8437
8963
|
const output = [];
|
|
8438
8964
|
if (node.priv_name) {
|
|
8439
|
-
output.push(node.priv_name);
|
|
8965
|
+
output.push(node.priv_name.toUpperCase());
|
|
8440
8966
|
}
|
|
8441
8967
|
else {
|
|
8442
8968
|
output.push('ALL');
|
|
8443
8969
|
}
|
|
8444
8970
|
if (node.cols && node.cols.length > 0) {
|
|
8445
8971
|
output.push('(');
|
|
8446
|
-
const colContext =
|
|
8972
|
+
const colContext = context.spawn('AccessPriv');
|
|
8447
8973
|
const columns = list_utils_1.ListUtils.unwrapList(node.cols).map(col => this.visit(col, colContext));
|
|
8448
8974
|
output.push(columns.join(', '));
|
|
8449
8975
|
output.push(')');
|
|
@@ -8523,7 +9049,7 @@ class Deparser {
|
|
|
8523
9049
|
output.push(list_utils_1.ListUtils.unwrapList(node.defnames).map(name => this.visit(name, context)).join('.'));
|
|
8524
9050
|
}
|
|
8525
9051
|
if (node.definition && node.definition.length > 0) {
|
|
8526
|
-
const defineStmtContext =
|
|
9052
|
+
const defineStmtContext = context.spawn('DefineStmt');
|
|
8527
9053
|
const definitions = list_utils_1.ListUtils.unwrapList(node.definition).map(def => {
|
|
8528
9054
|
return this.visit(def, defineStmtContext);
|
|
8529
9055
|
});
|
|
@@ -9009,7 +9535,7 @@ class Deparser {
|
|
|
9009
9535
|
const operatorNumber = node.number !== undefined ? node.number : 0;
|
|
9010
9536
|
output.push(operatorNumber.toString());
|
|
9011
9537
|
if (node.name) {
|
|
9012
|
-
const opClassContext =
|
|
9538
|
+
const opClassContext = context.spawn('CreateOpClassItem');
|
|
9013
9539
|
output.push(this.ObjectWithArgs(node.name, opClassContext));
|
|
9014
9540
|
}
|
|
9015
9541
|
}
|
|
@@ -9019,7 +9545,7 @@ class Deparser {
|
|
|
9019
9545
|
const functionNumber = node.number !== undefined ? node.number : 0;
|
|
9020
9546
|
output.push(functionNumber.toString());
|
|
9021
9547
|
if (node.name) {
|
|
9022
|
-
const opClassContext =
|
|
9548
|
+
const opClassContext = context.spawn('CreateOpClassItem');
|
|
9023
9549
|
output.push(this.ObjectWithArgs(node.name, opClassContext));
|
|
9024
9550
|
}
|
|
9025
9551
|
}
|
|
@@ -9717,7 +10243,7 @@ class Deparser {
|
|
|
9717
10243
|
output.push(this.ObjectWithArgs(node.func, context));
|
|
9718
10244
|
}
|
|
9719
10245
|
if (node.actions && node.actions.length > 0) {
|
|
9720
|
-
const alterFunctionContext =
|
|
10246
|
+
const alterFunctionContext = context.spawn('AlterFunctionStmt');
|
|
9721
10247
|
const actionStrs = list_utils_1.ListUtils.unwrapList(node.actions).map(action => this.visit(action, alterFunctionContext));
|
|
9722
10248
|
output.push(actionStrs.join(' '));
|
|
9723
10249
|
}
|
|
@@ -9725,66 +10251,12 @@ class Deparser {
|
|
|
9725
10251
|
}
|
|
9726
10252
|
AlterObjectSchemaStmt(node, context) {
|
|
9727
10253
|
const output = ['ALTER'];
|
|
9728
|
-
|
|
9729
|
-
|
|
9730
|
-
|
|
9731
|
-
|
|
9732
|
-
|
|
9733
|
-
|
|
9734
|
-
break;
|
|
9735
|
-
case 'OBJECT_FUNCTION':
|
|
9736
|
-
output.push('FUNCTION');
|
|
9737
|
-
break;
|
|
9738
|
-
case 'OBJECT_TYPE':
|
|
9739
|
-
output.push('TYPE');
|
|
9740
|
-
break;
|
|
9741
|
-
case 'OBJECT_DOMAIN':
|
|
9742
|
-
output.push('DOMAIN');
|
|
9743
|
-
break;
|
|
9744
|
-
case 'OBJECT_SEQUENCE':
|
|
9745
|
-
output.push('SEQUENCE');
|
|
9746
|
-
break;
|
|
9747
|
-
case 'OBJECT_OPCLASS':
|
|
9748
|
-
output.push('OPERATOR CLASS');
|
|
9749
|
-
break;
|
|
9750
|
-
case 'OBJECT_OPFAMILY':
|
|
9751
|
-
output.push('OPERATOR FAMILY');
|
|
9752
|
-
break;
|
|
9753
|
-
case 'OBJECT_OPERATOR':
|
|
9754
|
-
output.push('OPERATOR');
|
|
9755
|
-
break;
|
|
9756
|
-
case 'OBJECT_TYPE':
|
|
9757
|
-
output.push('TYPE');
|
|
9758
|
-
break;
|
|
9759
|
-
case 'OBJECT_COLLATION':
|
|
9760
|
-
output.push('COLLATION');
|
|
9761
|
-
break;
|
|
9762
|
-
case 'OBJECT_CONVERSION':
|
|
9763
|
-
output.push('CONVERSION');
|
|
9764
|
-
break;
|
|
9765
|
-
case 'OBJECT_TSPARSER':
|
|
9766
|
-
output.push('TEXT SEARCH PARSER');
|
|
9767
|
-
break;
|
|
9768
|
-
case 'OBJECT_TSCONFIGURATION':
|
|
9769
|
-
output.push('TEXT SEARCH CONFIGURATION');
|
|
9770
|
-
break;
|
|
9771
|
-
case 'OBJECT_TSTEMPLATE':
|
|
9772
|
-
output.push('TEXT SEARCH TEMPLATE');
|
|
9773
|
-
break;
|
|
9774
|
-
case 'OBJECT_TSDICTIONARY':
|
|
9775
|
-
output.push('TEXT SEARCH DICTIONARY');
|
|
9776
|
-
break;
|
|
9777
|
-
case 'OBJECT_AGGREGATE':
|
|
9778
|
-
output.push('AGGREGATE');
|
|
9779
|
-
break;
|
|
9780
|
-
case 'OBJECT_FOREIGN_TABLE':
|
|
9781
|
-
output.push('FOREIGN TABLE');
|
|
9782
|
-
break;
|
|
9783
|
-
case 'OBJECT_MATVIEW':
|
|
9784
|
-
output.push('MATERIALIZED VIEW');
|
|
9785
|
-
break;
|
|
9786
|
-
default:
|
|
9787
|
-
output.push(node.objectType.toString());
|
|
10254
|
+
try {
|
|
10255
|
+
output.push(this.getObjectTypeKeyword(node.objectType));
|
|
10256
|
+
}
|
|
10257
|
+
catch {
|
|
10258
|
+
// Fallback to objectType string if not supported
|
|
10259
|
+
output.push(node.objectType.toString());
|
|
9788
10260
|
}
|
|
9789
10261
|
if (node.missing_ok) {
|
|
9790
10262
|
output.push('IF EXISTS');
|
|
@@ -9961,7 +10433,7 @@ class Deparser {
|
|
|
9961
10433
|
CreateForeignTableStmt(node, context) {
|
|
9962
10434
|
const output = ['CREATE FOREIGN TABLE'];
|
|
9963
10435
|
if (node.base && node.base.relation) {
|
|
9964
|
-
const relationContext =
|
|
10436
|
+
const relationContext = context.spawn('CreateForeignTableStmt');
|
|
9965
10437
|
// Handle relation node directly as RangeVar since it contains the RangeVar properties
|
|
9966
10438
|
output.push(this.RangeVar(node.base.relation, relationContext));
|
|
9967
10439
|
}
|
|
@@ -9991,7 +10463,7 @@ class Deparser {
|
|
|
9991
10463
|
output.push(quote_utils_1.QuoteUtils.quote(node.servername));
|
|
9992
10464
|
}
|
|
9993
10465
|
if (node.options && node.options.length > 0) {
|
|
9994
|
-
const foreignTableContext =
|
|
10466
|
+
const foreignTableContext = context.spawn('CreateForeignTableStmt');
|
|
9995
10467
|
const optionStrs = list_utils_1.ListUtils.unwrapList(node.options).map(opt => this.visit(opt, foreignTableContext));
|
|
9996
10468
|
output.push(`OPTIONS (${optionStrs.join(', ')})`);
|
|
9997
10469
|
}
|