pgsql-deparser 13.19.0 → 13.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -16
- package/deparser/deparser.d.ts +37 -28
- package/deparser/deparser.js +1413 -948
- package/deparser/index.d.ts +3 -1
- package/deparser/index.js +5 -1
- package/deparser/utils/sql-formatter.d.ts +8 -0
- package/deparser/utils/sql-formatter.js +104 -1
- package/esm/deparser/deparser.js +1396 -931
- package/esm/deparser/index.js +3 -1
- package/esm/deparser/utils/sql-formatter.js +103 -1
- package/esm/index.js +101 -7
- package/esm/v13-to-v14.js +76 -29
- package/esm/v13-to-v18-direct.js +88 -0
- package/esm/v14-to-v15.js +34 -0
- package/esm/v15-to-v16.js +16 -5
- package/esm/v16-to-v17.js +50 -1
- package/esm/v17-to-v18.js +209 -0
- package/index.d.ts +18 -4
- package/index.js +104 -6
- package/package.json +7 -6
- package/v13-to-v14.d.ts +6 -0
- package/v13-to-v14.js +76 -29
- package/v13-to-v18-direct.d.ts +25 -0
- package/v13-to-v18-direct.js +92 -0
- package/v14-to-v15.d.ts +1 -0
- package/v14-to-v15.js +34 -0
- package/v15-to-v16.js +16 -5
- package/v16-to-v17.d.ts +3 -0
- package/v16-to-v17.js +50 -1
- package/v17-to-v18.d.ts +55 -0
- package/v17-to-v18.js +213 -0
package/esm/deparser/deparser.js
CHANGED
|
@@ -2,10 +2,29 @@
|
|
|
2
2
|
* Auto-generated file with types stripped for better tree-shaking
|
|
3
3
|
* DO NOT EDIT - Generated by strip-deparser-types.ts
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
6
|
-
import { SqlFormatter } from './utils/sql-formatter';
|
|
7
|
-
import { QuoteUtils } from './utils/quote-utils';
|
|
5
|
+
import { keywordKindOf, QuoteUtils } from '@pgsql/quotes';
|
|
8
6
|
import { ListUtils } from './utils/list-utils';
|
|
7
|
+
import { SqlFormatter } from './utils/sql-formatter';
|
|
8
|
+
import { DeparserContext } from './visitors/base';
|
|
9
|
+
// WindowDef.frameOptions bit flags (src/include/nodes/parsenodes.h)
|
|
10
|
+
const FRAMEOPTION_NONDEFAULT = 0x00001;
|
|
11
|
+
const FRAMEOPTION_RANGE = 0x00002;
|
|
12
|
+
const FRAMEOPTION_ROWS = 0x00004;
|
|
13
|
+
const FRAMEOPTION_GROUPS = 0x00008;
|
|
14
|
+
const FRAMEOPTION_BETWEEN = 0x00010;
|
|
15
|
+
const FRAMEOPTION_START_UNBOUNDED_PRECEDING = 0x00020;
|
|
16
|
+
const FRAMEOPTION_END_UNBOUNDED_PRECEDING = 0x00040;
|
|
17
|
+
const FRAMEOPTION_START_UNBOUNDED_FOLLOWING = 0x00080;
|
|
18
|
+
const FRAMEOPTION_END_UNBOUNDED_FOLLOWING = 0x00100;
|
|
19
|
+
const FRAMEOPTION_START_CURRENT_ROW = 0x00200;
|
|
20
|
+
const FRAMEOPTION_END_CURRENT_ROW = 0x00400;
|
|
21
|
+
const FRAMEOPTION_START_OFFSET_PRECEDING = 0x00800;
|
|
22
|
+
const FRAMEOPTION_END_OFFSET_PRECEDING = 0x01000;
|
|
23
|
+
const FRAMEOPTION_START_OFFSET_FOLLOWING = 0x02000;
|
|
24
|
+
const FRAMEOPTION_END_OFFSET_FOLLOWING = 0x04000;
|
|
25
|
+
const FRAMEOPTION_EXCLUDE_CURRENT_ROW = 0x08000;
|
|
26
|
+
const FRAMEOPTION_EXCLUDE_GROUP = 0x10000;
|
|
27
|
+
const FRAMEOPTION_EXCLUDE_TIES = 0x20000;
|
|
9
28
|
/**
|
|
10
29
|
* List of real PostgreSQL built-in types as they appear in pg_catalog.pg_type.typname.
|
|
11
30
|
* These are stored in lowercase in PostgreSQL system catalogs.
|
|
@@ -104,6 +123,36 @@ function isWrappedParseResult(obj) {
|
|
|
104
123
|
* The deparser automatically detects bare ParseResult objects for backward
|
|
105
124
|
* compatibility and wraps them internally for consistent processing.
|
|
106
125
|
*/
|
|
126
|
+
function formatBitString(bsval) {
|
|
127
|
+
const quote = (value) => value.replace(/'/g, "''");
|
|
128
|
+
if (/^x[0-9A-Fa-f]*$/.test(bsval)) {
|
|
129
|
+
return `x'${bsval.substring(1)}'`;
|
|
130
|
+
}
|
|
131
|
+
if (bsval.startsWith('b')) {
|
|
132
|
+
return `b'${quote(bsval.substring(1))}'`;
|
|
133
|
+
}
|
|
134
|
+
return `b'${quote(bsval)}'`;
|
|
135
|
+
}
|
|
136
|
+
// A dollar-quoted body ends at the first occurrence of its tag, including one
|
|
137
|
+
// formed by the body's trailing characters plus the closing tag (`...$` + `$$`).
|
|
138
|
+
function dollarTagConflicts(body, tag) {
|
|
139
|
+
return (body + tag).indexOf(tag) < body.length;
|
|
140
|
+
}
|
|
141
|
+
const NUMERIC_LITERAL = /^[+-]?(?:0[xX](?:_?[0-9A-Fa-f])+|0[oO](?:_?[0-7])+|0[bB](?:_?[01])+|(?:\d(?:_?\d)*(?:\.(?:\d(?:_?\d)*)?)?|\.\d(?:_?\d)*)(?:[eE][+-]?\d(?:_?\d)*)?)$/;
|
|
142
|
+
function formatInteger(ival) {
|
|
143
|
+
const value = String(ival);
|
|
144
|
+
if (!/^[+-]?\d+$/.test(value)) {
|
|
145
|
+
throw new Error(`Invalid integer literal: ${value}`);
|
|
146
|
+
}
|
|
147
|
+
return value;
|
|
148
|
+
}
|
|
149
|
+
function formatNumeric(fval) {
|
|
150
|
+
const value = String(fval);
|
|
151
|
+
if (!NUMERIC_LITERAL.test(value)) {
|
|
152
|
+
throw new Error(`Invalid numeric literal: ${value}`);
|
|
153
|
+
}
|
|
154
|
+
return value;
|
|
155
|
+
}
|
|
107
156
|
export class Deparser {
|
|
108
157
|
tree;
|
|
109
158
|
options;
|
|
@@ -163,10 +212,133 @@ export class Deparser {
|
|
|
163
212
|
*/
|
|
164
213
|
getFunctionDelimiter(body) {
|
|
165
214
|
const delimiter = this.options.functionDelimiter || '$$';
|
|
166
|
-
if (body
|
|
167
|
-
return
|
|
215
|
+
if (!dollarTagConflicts(body, delimiter)) {
|
|
216
|
+
return delimiter;
|
|
217
|
+
}
|
|
218
|
+
const fallback = this.options.functionDelimiterFallback || '$EOFCODE$';
|
|
219
|
+
if (!dollarTagConflicts(body, fallback)) {
|
|
220
|
+
return fallback;
|
|
221
|
+
}
|
|
222
|
+
const base = fallback.slice(0, -1);
|
|
223
|
+
let counter = 1;
|
|
224
|
+
while (dollarTagConflicts(body, `${base}${counter}$`)) {
|
|
225
|
+
counter++;
|
|
226
|
+
}
|
|
227
|
+
return `${base}${counter}$`;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Maps ObjectType enum values to their corresponding SQL keywords
|
|
231
|
+
* Used by AlterOwnerStmt, AlterObjectSchemaStmt, and other statements that need object type keywords
|
|
232
|
+
*/
|
|
233
|
+
getObjectTypeKeyword(objectType) {
|
|
234
|
+
switch (objectType) {
|
|
235
|
+
case 'OBJECT_TABLE':
|
|
236
|
+
return 'TABLE';
|
|
237
|
+
case 'OBJECT_VIEW':
|
|
238
|
+
return 'VIEW';
|
|
239
|
+
case 'OBJECT_INDEX':
|
|
240
|
+
return 'INDEX';
|
|
241
|
+
case 'OBJECT_SEQUENCE':
|
|
242
|
+
return 'SEQUENCE';
|
|
243
|
+
case 'OBJECT_FUNCTION':
|
|
244
|
+
return 'FUNCTION';
|
|
245
|
+
case 'OBJECT_PROCEDURE':
|
|
246
|
+
return 'PROCEDURE';
|
|
247
|
+
case 'OBJECT_SCHEMA':
|
|
248
|
+
return 'SCHEMA';
|
|
249
|
+
case 'OBJECT_DATABASE':
|
|
250
|
+
return 'DATABASE';
|
|
251
|
+
case 'OBJECT_DOMAIN':
|
|
252
|
+
return 'DOMAIN';
|
|
253
|
+
case 'OBJECT_AGGREGATE':
|
|
254
|
+
return 'AGGREGATE';
|
|
255
|
+
case 'OBJECT_CONVERSION':
|
|
256
|
+
return 'CONVERSION';
|
|
257
|
+
case 'OBJECT_LANGUAGE':
|
|
258
|
+
return 'LANGUAGE';
|
|
259
|
+
case 'OBJECT_OPERATOR':
|
|
260
|
+
return 'OPERATOR';
|
|
261
|
+
case 'OBJECT_OPFAMILY':
|
|
262
|
+
return 'OPERATOR FAMILY';
|
|
263
|
+
case 'OBJECT_OPCLASS':
|
|
264
|
+
return 'OPERATOR CLASS';
|
|
265
|
+
case 'OBJECT_TSDICTIONARY':
|
|
266
|
+
return 'TEXT SEARCH DICTIONARY';
|
|
267
|
+
case 'OBJECT_TSCONFIGURATION':
|
|
268
|
+
return 'TEXT SEARCH CONFIGURATION';
|
|
269
|
+
case 'OBJECT_EVENT_TRIGGER':
|
|
270
|
+
return 'EVENT TRIGGER';
|
|
271
|
+
case 'OBJECT_FDW':
|
|
272
|
+
return 'FOREIGN DATA WRAPPER';
|
|
273
|
+
case 'OBJECT_FOREIGN_SERVER':
|
|
274
|
+
return 'SERVER';
|
|
275
|
+
case 'OBJECT_TYPE':
|
|
276
|
+
return 'TYPE';
|
|
277
|
+
case 'OBJECT_COLLATION':
|
|
278
|
+
return 'COLLATION';
|
|
279
|
+
case 'OBJECT_PUBLICATION':
|
|
280
|
+
return 'PUBLICATION';
|
|
281
|
+
case 'OBJECT_ACCESS_METHOD':
|
|
282
|
+
return 'ACCESS METHOD';
|
|
283
|
+
case 'OBJECT_AMOP':
|
|
284
|
+
return 'OPERATOR CLASS';
|
|
285
|
+
case 'OBJECT_AMPROC':
|
|
286
|
+
return 'OPERATOR CLASS';
|
|
287
|
+
case 'OBJECT_ATTRIBUTE':
|
|
288
|
+
return 'ATTRIBUTE';
|
|
289
|
+
case 'OBJECT_CAST':
|
|
290
|
+
return 'CAST';
|
|
291
|
+
case 'OBJECT_COLUMN':
|
|
292
|
+
return 'COLUMN';
|
|
293
|
+
case 'OBJECT_DEFAULT':
|
|
294
|
+
return 'DEFAULT';
|
|
295
|
+
case 'OBJECT_DEFACL':
|
|
296
|
+
return 'DEFAULT PRIVILEGES';
|
|
297
|
+
case 'OBJECT_DOMCONSTRAINT':
|
|
298
|
+
return 'DOMAIN';
|
|
299
|
+
case 'OBJECT_EXTENSION':
|
|
300
|
+
return 'EXTENSION';
|
|
301
|
+
case 'OBJECT_FOREIGN_TABLE':
|
|
302
|
+
return 'FOREIGN TABLE';
|
|
303
|
+
case 'OBJECT_LARGEOBJECT':
|
|
304
|
+
return 'LARGE OBJECT';
|
|
305
|
+
case 'OBJECT_MATVIEW':
|
|
306
|
+
return 'MATERIALIZED VIEW';
|
|
307
|
+
case 'OBJECT_PARAMETER_ACL':
|
|
308
|
+
return 'PARAMETER';
|
|
309
|
+
case 'OBJECT_POLICY':
|
|
310
|
+
return 'POLICY';
|
|
311
|
+
case 'OBJECT_PUBLICATION_NAMESPACE':
|
|
312
|
+
return 'PUBLICATION';
|
|
313
|
+
case 'OBJECT_PUBLICATION_REL':
|
|
314
|
+
return 'PUBLICATION';
|
|
315
|
+
case 'OBJECT_ROLE':
|
|
316
|
+
return 'ROLE';
|
|
317
|
+
case 'OBJECT_ROUTINE':
|
|
318
|
+
return 'ROUTINE';
|
|
319
|
+
case 'OBJECT_RULE':
|
|
320
|
+
return 'RULE';
|
|
321
|
+
case 'OBJECT_STATISTIC_EXT':
|
|
322
|
+
return 'STATISTICS';
|
|
323
|
+
case 'OBJECT_SUBSCRIPTION':
|
|
324
|
+
return 'SUBSCRIPTION';
|
|
325
|
+
case 'OBJECT_TABCONSTRAINT':
|
|
326
|
+
return 'CONSTRAINT';
|
|
327
|
+
case 'OBJECT_TABLESPACE':
|
|
328
|
+
return 'TABLESPACE';
|
|
329
|
+
case 'OBJECT_TRANSFORM':
|
|
330
|
+
return 'TRANSFORM';
|
|
331
|
+
case 'OBJECT_TRIGGER':
|
|
332
|
+
return 'TRIGGER';
|
|
333
|
+
case 'OBJECT_TSPARSER':
|
|
334
|
+
return 'TEXT SEARCH PARSER';
|
|
335
|
+
case 'OBJECT_TSTEMPLATE':
|
|
336
|
+
return 'TEXT SEARCH TEMPLATE';
|
|
337
|
+
case 'OBJECT_USER_MAPPING':
|
|
338
|
+
return 'USER MAPPING';
|
|
339
|
+
default:
|
|
340
|
+
throw new Error(`Unsupported objectType: ${objectType}`);
|
|
168
341
|
}
|
|
169
|
-
return delimiter;
|
|
170
342
|
}
|
|
171
343
|
deparse(node, context) {
|
|
172
344
|
if (node == null) {
|
|
@@ -329,12 +501,7 @@ export class Deparser {
|
|
|
329
501
|
// Check if single target is complex - if so, use multiline format
|
|
330
502
|
if (this.isComplexSelectTarget(targetNode)) {
|
|
331
503
|
output.push('SELECT' + distinctPart);
|
|
332
|
-
|
|
333
|
-
output.push(target);
|
|
334
|
-
}
|
|
335
|
-
else {
|
|
336
|
-
output.push(context.indent(target));
|
|
337
|
-
}
|
|
504
|
+
output.push(context.indent(target));
|
|
338
505
|
}
|
|
339
506
|
else {
|
|
340
507
|
output.push('SELECT' + distinctPart + ' ' + target);
|
|
@@ -344,9 +511,6 @@ export class Deparser {
|
|
|
344
511
|
const targetStrings = targetList
|
|
345
512
|
.map(e => {
|
|
346
513
|
const targetStr = this.visit(e, context.spawn('SelectStmt', { select: true }));
|
|
347
|
-
if (this.containsMultilineStringLiteral(targetStr)) {
|
|
348
|
-
return targetStr;
|
|
349
|
-
}
|
|
350
514
|
return context.indent(targetStr);
|
|
351
515
|
});
|
|
352
516
|
const formattedTargets = targetStrings.join(',' + context.newline());
|
|
@@ -398,9 +562,6 @@ export class Deparser {
|
|
|
398
562
|
return context.parens(values.join(', '));
|
|
399
563
|
});
|
|
400
564
|
const indentedTuples = lists.map(tuple => {
|
|
401
|
-
if (this.containsMultilineStringLiteral(tuple)) {
|
|
402
|
-
return tuple;
|
|
403
|
-
}
|
|
404
565
|
return context.indent(tuple);
|
|
405
566
|
});
|
|
406
567
|
output.push(indentedTuples.join(',\n'));
|
|
@@ -420,9 +581,6 @@ export class Deparser {
|
|
|
420
581
|
const groupItems = groupList
|
|
421
582
|
.map(e => {
|
|
422
583
|
const groupStr = this.visit(e, context.spawn('SelectStmt', { group: true, indentLevel: context.indentLevel + 1 }));
|
|
423
|
-
if (this.containsMultilineStringLiteral(groupStr)) {
|
|
424
|
-
return groupStr;
|
|
425
|
-
}
|
|
426
584
|
return context.indent(groupStr);
|
|
427
585
|
})
|
|
428
586
|
.join(',' + context.newline());
|
|
@@ -441,12 +599,7 @@ export class Deparser {
|
|
|
441
599
|
if (context.isPretty()) {
|
|
442
600
|
output.push('HAVING');
|
|
443
601
|
const havingStr = this.visit(node.havingClause, context);
|
|
444
|
-
|
|
445
|
-
output.push(havingStr);
|
|
446
|
-
}
|
|
447
|
-
else {
|
|
448
|
-
output.push(context.indent(havingStr));
|
|
449
|
-
}
|
|
602
|
+
output.push(context.indent(havingStr));
|
|
450
603
|
}
|
|
451
604
|
else {
|
|
452
605
|
output.push('HAVING');
|
|
@@ -467,9 +620,6 @@ export class Deparser {
|
|
|
467
620
|
const sortItems = sortList
|
|
468
621
|
.map(e => {
|
|
469
622
|
const sortStr = this.visit(e, context.spawn('SelectStmt', { sort: true, indentLevel: context.indentLevel + 1 }));
|
|
470
|
-
if (this.containsMultilineStringLiteral(sortStr)) {
|
|
471
|
-
return sortStr;
|
|
472
|
-
}
|
|
473
623
|
return context.indent(sortStr);
|
|
474
624
|
})
|
|
475
625
|
.join(',' + context.newline());
|
|
@@ -545,10 +695,15 @@ export class Deparser {
|
|
|
545
695
|
return context.format([leftExpr, operator, rightExpr]);
|
|
546
696
|
}
|
|
547
697
|
else if (rexpr) {
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
698
|
+
// Unary operator (e.g., unary minus: - expr)
|
|
699
|
+
const operator = this.deparseOperatorName(name, context);
|
|
700
|
+
let rightExpr = this.visit(rexpr, context);
|
|
701
|
+
// Wrap in parentheses if rexpr is a binary A_Expr to preserve semantics
|
|
702
|
+
// e.g., -(a - b) must stay -(a - b), not become -a - b
|
|
703
|
+
if (rexpr && 'A_Expr' in rexpr && rexpr.A_Expr?.kind === 'AEXPR_OP' && rexpr.A_Expr?.lexpr) {
|
|
704
|
+
rightExpr = context.parens(rightExpr);
|
|
705
|
+
}
|
|
706
|
+
return context.format([operator, rightExpr]);
|
|
552
707
|
}
|
|
553
708
|
break;
|
|
554
709
|
case 'AEXPR_OP_ANY':
|
|
@@ -728,15 +883,15 @@ export class Deparser {
|
|
|
728
883
|
getOperatorPrecedence(operator) {
|
|
729
884
|
const precedence = {
|
|
730
885
|
'||': 1, // string concatenation
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
886
|
+
OR: 2, // logical OR
|
|
887
|
+
AND: 3, // logical AND
|
|
888
|
+
NOT: 4, // logical NOT
|
|
889
|
+
IS: 5, // IS NULL, IS NOT NULL, etc.
|
|
890
|
+
IN: 5, // IN, NOT IN
|
|
891
|
+
BETWEEN: 5, // BETWEEN, NOT BETWEEN
|
|
892
|
+
LIKE: 5, // LIKE, ILIKE, SIMILAR TO
|
|
893
|
+
ILIKE: 5,
|
|
894
|
+
SIMILAR: 5,
|
|
740
895
|
'<': 6, // comparison operators
|
|
741
896
|
'<=': 6,
|
|
742
897
|
'>': 6,
|
|
@@ -866,6 +1021,12 @@ export class Deparser {
|
|
|
866
1021
|
output.push(context.parens(columnNames.join(', ')));
|
|
867
1022
|
}
|
|
868
1023
|
}
|
|
1024
|
+
if (node.override === 'OVERRIDING_USER_VALUE') {
|
|
1025
|
+
output.push('OVERRIDING USER VALUE');
|
|
1026
|
+
}
|
|
1027
|
+
else if (node.override === 'OVERRIDING_SYSTEM_VALUE') {
|
|
1028
|
+
output.push('OVERRIDING SYSTEM VALUE');
|
|
1029
|
+
}
|
|
869
1030
|
if (node.selectStmt) {
|
|
870
1031
|
output.push(this.visit(node.selectStmt, context));
|
|
871
1032
|
}
|
|
@@ -908,7 +1069,14 @@ export class Deparser {
|
|
|
908
1069
|
else {
|
|
909
1070
|
const updateContext = context.spawn('UpdateStmt', { update: true });
|
|
910
1071
|
const targets = targetList.map(target => this.visit(target, updateContext));
|
|
911
|
-
|
|
1072
|
+
if (context.isPretty()) {
|
|
1073
|
+
// Put each assignment on its own line for pretty printing
|
|
1074
|
+
const indentedTargets = targets.map(target => context.indent(target));
|
|
1075
|
+
output[output.length - 1] += '\n' + indentedTargets.join(',\n');
|
|
1076
|
+
}
|
|
1077
|
+
else {
|
|
1078
|
+
output.push(targets.join(', '));
|
|
1079
|
+
}
|
|
912
1080
|
}
|
|
913
1081
|
}
|
|
914
1082
|
if (node.onConflictClause.whereClause) {
|
|
@@ -920,11 +1088,8 @@ export class Deparser {
|
|
|
920
1088
|
output.push('DO NOTHING');
|
|
921
1089
|
}
|
|
922
1090
|
}
|
|
923
|
-
if (node.
|
|
924
|
-
output.push(
|
|
925
|
-
const returningList = ListUtils.unwrapList(node.returningList);
|
|
926
|
-
const returns = returningList.map(ret => this.visit(ret, context));
|
|
927
|
-
output.push(returns.join(', '));
|
|
1091
|
+
if (node.returningClause) {
|
|
1092
|
+
output.push(this.ReturningClause(node.returningClause, context));
|
|
928
1093
|
}
|
|
929
1094
|
return output.join(' ');
|
|
930
1095
|
}
|
|
@@ -938,38 +1103,8 @@ export class Deparser {
|
|
|
938
1103
|
output.push(this.RangeVar(node.relation, context));
|
|
939
1104
|
}
|
|
940
1105
|
output.push('SET');
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
const firstTarget = targetList[0];
|
|
944
|
-
const processedTargets = new Set();
|
|
945
|
-
const assignmentParts = [];
|
|
946
|
-
for (let i = 0; i < targetList.length; i++) {
|
|
947
|
-
if (processedTargets.has(i))
|
|
948
|
-
continue;
|
|
949
|
-
const target = targetList[i];
|
|
950
|
-
const multiAssignRef = target.ResTarget?.val?.MultiAssignRef;
|
|
951
|
-
if (multiAssignRef) {
|
|
952
|
-
const relatedTargets = [];
|
|
953
|
-
for (let j = i; j < targetList.length; j++) {
|
|
954
|
-
const otherTarget = targetList[j];
|
|
955
|
-
const otherMultiAssignRef = otherTarget.ResTarget?.val?.MultiAssignRef;
|
|
956
|
-
if (otherMultiAssignRef &&
|
|
957
|
-
JSON.stringify(otherMultiAssignRef.source) === JSON.stringify(multiAssignRef.source)) {
|
|
958
|
-
relatedTargets.push(otherTarget);
|
|
959
|
-
processedTargets.add(j);
|
|
960
|
-
}
|
|
961
|
-
}
|
|
962
|
-
const names = relatedTargets.map(t => t.ResTarget.name);
|
|
963
|
-
const multiAssignment = `${context.parens(names.join(', '))} = ${this.visit(multiAssignRef.source, context)}`;
|
|
964
|
-
assignmentParts.push(multiAssignment);
|
|
965
|
-
}
|
|
966
|
-
else {
|
|
967
|
-
// Handle regular single-column assignment
|
|
968
|
-
assignmentParts.push(this.visit(target, context.spawn('UpdateStmt', { update: true })));
|
|
969
|
-
processedTargets.add(i);
|
|
970
|
-
}
|
|
971
|
-
}
|
|
972
|
-
output.push(assignmentParts.join(','));
|
|
1106
|
+
if (node.targetList && node.targetList.length > 0) {
|
|
1107
|
+
output.push(this.formatUpdateAssignments(node.targetList, context));
|
|
973
1108
|
}
|
|
974
1109
|
if (node.fromClause) {
|
|
975
1110
|
output.push('FROM');
|
|
@@ -981,12 +1116,41 @@ export class Deparser {
|
|
|
981
1116
|
output.push('WHERE');
|
|
982
1117
|
output.push(this.visit(node.whereClause, context));
|
|
983
1118
|
}
|
|
984
|
-
if (node.
|
|
985
|
-
output.push(
|
|
986
|
-
output.push(this.deparseReturningList(node.returningList, context));
|
|
1119
|
+
if (node.returningClause) {
|
|
1120
|
+
output.push(this.ReturningClause(node.returningClause, context));
|
|
987
1121
|
}
|
|
988
1122
|
return output.join(' ');
|
|
989
1123
|
}
|
|
1124
|
+
formatUpdateAssignments(targets, context) {
|
|
1125
|
+
const targetList = ListUtils.unwrapList(targets);
|
|
1126
|
+
const processedTargets = new Set();
|
|
1127
|
+
const assignmentParts = [];
|
|
1128
|
+
for (let i = 0; i < targetList.length; i++) {
|
|
1129
|
+
if (processedTargets.has(i))
|
|
1130
|
+
continue;
|
|
1131
|
+
const target = targetList[i];
|
|
1132
|
+
const multiAssignRef = target.ResTarget?.val?.MultiAssignRef;
|
|
1133
|
+
if (multiAssignRef) {
|
|
1134
|
+
const relatedTargets = [];
|
|
1135
|
+
for (let j = i; j < targetList.length; j++) {
|
|
1136
|
+
const otherTarget = targetList[j];
|
|
1137
|
+
const otherMultiAssignRef = otherTarget.ResTarget?.val?.MultiAssignRef;
|
|
1138
|
+
if (otherMultiAssignRef &&
|
|
1139
|
+
JSON.stringify(otherMultiAssignRef.source) === JSON.stringify(multiAssignRef.source)) {
|
|
1140
|
+
relatedTargets.push(otherTarget);
|
|
1141
|
+
processedTargets.add(j);
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
const names = relatedTargets.map(t => QuoteUtils.quoteIdentifier(t.ResTarget.name));
|
|
1145
|
+
assignmentParts.push(`${context.parens(names.join(', '))} = ${this.visit(multiAssignRef.source, context)}`);
|
|
1146
|
+
}
|
|
1147
|
+
else {
|
|
1148
|
+
assignmentParts.push(this.visit(target, context.spawn('UpdateStmt', { update: true })));
|
|
1149
|
+
processedTargets.add(i);
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
return assignmentParts.join(', ');
|
|
1153
|
+
}
|
|
990
1154
|
DeleteStmt(node, context) {
|
|
991
1155
|
try {
|
|
992
1156
|
const output = [];
|
|
@@ -1034,13 +1198,12 @@ export class Deparser {
|
|
|
1034
1198
|
throw new Error(`Error deparsing DeleteStmt: ${error instanceof Error ? error.message : String(error)}`);
|
|
1035
1199
|
}
|
|
1036
1200
|
}
|
|
1037
|
-
if (node.
|
|
1038
|
-
output.push('RETURNING');
|
|
1201
|
+
if (node.returningClause) {
|
|
1039
1202
|
try {
|
|
1040
|
-
output.push(this.
|
|
1203
|
+
output.push(this.ReturningClause(node.returningClause, context));
|
|
1041
1204
|
}
|
|
1042
1205
|
catch (error) {
|
|
1043
|
-
console.warn(`Error processing
|
|
1206
|
+
console.warn(`Error processing returningClause in DeleteStmt: ${error instanceof Error ? error.message : String(error)}`);
|
|
1044
1207
|
throw new Error(`Error deparsing DeleteStmt: ${error instanceof Error ? error.message : String(error)}`);
|
|
1045
1208
|
}
|
|
1046
1209
|
}
|
|
@@ -1061,9 +1224,6 @@ export class Deparser {
|
|
|
1061
1224
|
const cteStrings = ctes.map((cte, index) => {
|
|
1062
1225
|
const cteStr = this.visit(cte, context);
|
|
1063
1226
|
const prefix = index === 0 ? context.newline() : ',' + context.newline();
|
|
1064
|
-
if (this.containsMultilineStringLiteral(cteStr)) {
|
|
1065
|
-
return prefix + cteStr;
|
|
1066
|
-
}
|
|
1067
1227
|
return prefix + context.indent(cteStr);
|
|
1068
1228
|
});
|
|
1069
1229
|
output.push(cteStrings.join(''));
|
|
@@ -1078,12 +1238,12 @@ export class Deparser {
|
|
|
1078
1238
|
ResTarget(node, context) {
|
|
1079
1239
|
const output = [];
|
|
1080
1240
|
if (context.update && node.name) {
|
|
1081
|
-
output.push(QuoteUtils.
|
|
1241
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
1082
1242
|
// Handle indirection (array indexing, field access, etc.)
|
|
1083
1243
|
if (node.indirection && node.indirection.length > 0) {
|
|
1084
1244
|
const indirectionStrs = ListUtils.unwrapList(node.indirection).map(item => {
|
|
1085
1245
|
if (item.String) {
|
|
1086
|
-
return `.${QuoteUtils.
|
|
1246
|
+
return `.${QuoteUtils.quoteIdentifierAfterDot(item.String.sval || item.String.str)}`;
|
|
1087
1247
|
}
|
|
1088
1248
|
return this.visit(item, context);
|
|
1089
1249
|
});
|
|
@@ -1095,12 +1255,12 @@ export class Deparser {
|
|
|
1095
1255
|
}
|
|
1096
1256
|
}
|
|
1097
1257
|
else if (context.insertColumns && node.name) {
|
|
1098
|
-
output.push(QuoteUtils.
|
|
1258
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
1099
1259
|
// Handle indirection for INSERT column lists (e.g., q.c1.r)
|
|
1100
1260
|
if (node.indirection && node.indirection.length > 0) {
|
|
1101
1261
|
const indirectionStrs = ListUtils.unwrapList(node.indirection).map(item => {
|
|
1102
1262
|
if (item.String) {
|
|
1103
|
-
return `.${QuoteUtils.
|
|
1263
|
+
return `.${QuoteUtils.quoteIdentifierAfterDot(item.String.sval || item.String.str)}`;
|
|
1104
1264
|
}
|
|
1105
1265
|
return this.visit(item, context);
|
|
1106
1266
|
});
|
|
@@ -1113,11 +1273,53 @@ export class Deparser {
|
|
|
1113
1273
|
}
|
|
1114
1274
|
if (node.name) {
|
|
1115
1275
|
output.push('AS');
|
|
1116
|
-
output.push(QuoteUtils.
|
|
1276
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
return output.join(' ');
|
|
1280
|
+
}
|
|
1281
|
+
ATAlterConstraint(node, context) {
|
|
1282
|
+
const output = ['ALTER CONSTRAINT'];
|
|
1283
|
+
if (node.conname) {
|
|
1284
|
+
output.push(QuoteUtils.quoteIdentifier(node.conname));
|
|
1285
|
+
}
|
|
1286
|
+
if (node.alterEnforceability) {
|
|
1287
|
+
output.push(node.is_enforced ? 'ENFORCED' : 'NOT ENFORCED');
|
|
1288
|
+
}
|
|
1289
|
+
if (node.alterDeferrability) {
|
|
1290
|
+
output.push(node.deferrable ? 'DEFERRABLE' : 'NOT DEFERRABLE');
|
|
1291
|
+
if (node.initdeferred) {
|
|
1292
|
+
output.push('INITIALLY DEFERRED');
|
|
1117
1293
|
}
|
|
1118
1294
|
}
|
|
1295
|
+
if (node.alterInheritability) {
|
|
1296
|
+
output.push(node.noinherit ? 'NO INHERIT' : 'INHERIT');
|
|
1297
|
+
}
|
|
1298
|
+
return output.join(' ');
|
|
1299
|
+
}
|
|
1300
|
+
deparseKeyAttrs(attrs, withPeriod, context) {
|
|
1301
|
+
const items = ListUtils.unwrapList(attrs).map(attr => this.visit(attr, context));
|
|
1302
|
+
if (withPeriod && items.length > 0) {
|
|
1303
|
+
items[items.length - 1] = `PERIOD ${items[items.length - 1]}`;
|
|
1304
|
+
}
|
|
1305
|
+
return items.join(', ');
|
|
1306
|
+
}
|
|
1307
|
+
ReturningClause(node, context) {
|
|
1308
|
+
const output = ['RETURNING'];
|
|
1309
|
+
if (node.options && node.options.length > 0) {
|
|
1310
|
+
const options = ListUtils.unwrapList(node.options)
|
|
1311
|
+
.map(option => this.visit(option, context));
|
|
1312
|
+
output.push(`WITH (${options.join(', ')})`);
|
|
1313
|
+
}
|
|
1314
|
+
if (node.exprs && node.exprs.length > 0) {
|
|
1315
|
+
output.push(this.deparseReturningList(node.exprs, context));
|
|
1316
|
+
}
|
|
1119
1317
|
return output.join(' ');
|
|
1120
1318
|
}
|
|
1319
|
+
ReturningOption(node, context) {
|
|
1320
|
+
const keyword = node.option === 'RETURNING_OPTION_NEW' ? 'NEW' : 'OLD';
|
|
1321
|
+
return `${keyword} AS ${QuoteUtils.quoteIdentifier(node.value)}`;
|
|
1322
|
+
}
|
|
1121
1323
|
deparseReturningList(list, context) {
|
|
1122
1324
|
return ListUtils.unwrapList(list)
|
|
1123
1325
|
.filter(item => item != null && this.getNodeType(item) !== 'undefined')
|
|
@@ -1127,7 +1329,7 @@ export class Deparser {
|
|
|
1127
1329
|
if (this.getNodeType(item) === 'ResTarget') {
|
|
1128
1330
|
const resTarget = this.getNodeData(item);
|
|
1129
1331
|
const val = resTarget.val ? this.visit(resTarget.val, context) : '';
|
|
1130
|
-
const alias = resTarget.name ? ` AS ${QuoteUtils.
|
|
1332
|
+
const alias = resTarget.name ? ` AS ${QuoteUtils.quoteIdentifier(resTarget.name)}` : '';
|
|
1131
1333
|
return val + alias;
|
|
1132
1334
|
}
|
|
1133
1335
|
else {
|
|
@@ -1182,7 +1384,8 @@ export class Deparser {
|
|
|
1182
1384
|
FuncCall(node, context) {
|
|
1183
1385
|
const funcname = ListUtils.unwrapList(node.funcname);
|
|
1184
1386
|
const args = ListUtils.unwrapList(node.args);
|
|
1185
|
-
const
|
|
1387
|
+
const funcnameParts = funcname.map((n) => n.String?.sval || n.String?.str || '').filter((s) => s);
|
|
1388
|
+
const name = QuoteUtils.quoteDottedName(funcnameParts);
|
|
1186
1389
|
// Handle special SQL syntax functions like XMLEXISTS and EXTRACT
|
|
1187
1390
|
if (node.funcformat === 'COERCE_SQL_SYNTAX' && name === 'pg_catalog.xmlexists' && args.length >= 2) {
|
|
1188
1391
|
const xpath = this.visit(args[0], context);
|
|
@@ -1191,8 +1394,15 @@ export class Deparser {
|
|
|
1191
1394
|
}
|
|
1192
1395
|
// Handle EXTRACT function with SQL syntax
|
|
1193
1396
|
if (node.funcformat === 'COERCE_SQL_SYNTAX' && name === 'pg_catalog.extract' && args.length >= 2) {
|
|
1194
|
-
|
|
1397
|
+
let field = this.visit(args[0], context);
|
|
1195
1398
|
const source = this.visit(args[1], context);
|
|
1399
|
+
// EXTRACT requires an unquoted uppercase keyword (EPOCH, YEAR, etc.)
|
|
1400
|
+
// but A_Const sval deparsing wraps it in single quotes — strip and uppercase
|
|
1401
|
+
// only when it is spelled the way the bare-keyword form parses back
|
|
1402
|
+
if (/^'(?:year|month|day|hour|minute|second)'$/.test(field)
|
|
1403
|
+
|| (/^'[a-z_][a-z0-9_]*'$/.test(field) && keywordKindOf(field.slice(1, -1)) === 'NO_KEYWORD')) {
|
|
1404
|
+
field = field.slice(1, -1).toUpperCase();
|
|
1405
|
+
}
|
|
1196
1406
|
return `EXTRACT(${field} FROM ${source})`;
|
|
1197
1407
|
}
|
|
1198
1408
|
// Handle TRIM function with SQL syntax (TRIM TRAILING/LEADING/BOTH)
|
|
@@ -1352,43 +1562,41 @@ export class Deparser {
|
|
|
1352
1562
|
result += ` FILTER (WHERE ${this.visit(node.agg_filter, context)})`;
|
|
1353
1563
|
}
|
|
1354
1564
|
if (node.over) {
|
|
1355
|
-
|
|
1356
|
-
if (node.over.name) {
|
|
1357
|
-
result += ` OVER ${node.over.name}`;
|
|
1358
|
-
}
|
|
1359
|
-
else {
|
|
1360
|
-
const windowParts = [];
|
|
1361
|
-
if (node.over.partitionClause) {
|
|
1362
|
-
const partitions = ListUtils.unwrapList(node.over.partitionClause);
|
|
1363
|
-
const partitionStrs = partitions.map(p => this.visit(p, context));
|
|
1364
|
-
windowParts.push(`PARTITION BY ${partitionStrs.join(', ')}`);
|
|
1365
|
-
}
|
|
1366
|
-
if (node.over.orderClause) {
|
|
1367
|
-
const orders = ListUtils.unwrapList(node.over.orderClause);
|
|
1368
|
-
const orderStrs = orders.map(o => this.visit(o, context));
|
|
1369
|
-
windowParts.push(`ORDER BY ${orderStrs.join(', ')}`);
|
|
1370
|
-
}
|
|
1371
|
-
// Handle window frame specifications using the dedicated formatWindowFrame method
|
|
1372
|
-
const frameClause = this.formatWindowFrame(node.over, context.spawn('FuncCall'));
|
|
1373
|
-
if (frameClause) {
|
|
1374
|
-
windowParts.push(frameClause);
|
|
1375
|
-
}
|
|
1376
|
-
if (windowParts.length > 0) {
|
|
1377
|
-
if (context.isPretty() && windowParts.length > 1) {
|
|
1378
|
-
const formattedParts = windowParts.map(part => context.indent(part));
|
|
1379
|
-
result += ` OVER (${context.newline()}${formattedParts.join(context.newline())}${context.newline()})`;
|
|
1380
|
-
}
|
|
1381
|
-
else {
|
|
1382
|
-
result += ` OVER (${windowParts.join(' ')})`;
|
|
1383
|
-
}
|
|
1384
|
-
}
|
|
1385
|
-
else {
|
|
1386
|
-
result += ` OVER ()`;
|
|
1387
|
-
}
|
|
1388
|
-
}
|
|
1565
|
+
result += this.formatOverClause(node.over, context);
|
|
1389
1566
|
}
|
|
1390
1567
|
return result;
|
|
1391
1568
|
}
|
|
1569
|
+
formatOverClause(over, context) {
|
|
1570
|
+
if (over.name) {
|
|
1571
|
+
return ` OVER ${over.name}`;
|
|
1572
|
+
}
|
|
1573
|
+
const windowParts = [];
|
|
1574
|
+
if (over.refname) {
|
|
1575
|
+
windowParts.push(over.refname);
|
|
1576
|
+
}
|
|
1577
|
+
if (over.partitionClause) {
|
|
1578
|
+
const partitions = ListUtils.unwrapList(over.partitionClause);
|
|
1579
|
+
const partitionStrs = partitions.map(p => this.visit(p, context));
|
|
1580
|
+
windowParts.push(`PARTITION BY ${partitionStrs.join(', ')}`);
|
|
1581
|
+
}
|
|
1582
|
+
if (over.orderClause) {
|
|
1583
|
+
const orders = ListUtils.unwrapList(over.orderClause);
|
|
1584
|
+
const orderStrs = orders.map(o => this.visit(o, context));
|
|
1585
|
+
windowParts.push(`ORDER BY ${orderStrs.join(', ')}`);
|
|
1586
|
+
}
|
|
1587
|
+
const frameClause = this.formatWindowFrame(over, context.spawn('FuncCall'));
|
|
1588
|
+
if (frameClause) {
|
|
1589
|
+
windowParts.push(frameClause);
|
|
1590
|
+
}
|
|
1591
|
+
if (windowParts.length === 0) {
|
|
1592
|
+
return ' OVER ()';
|
|
1593
|
+
}
|
|
1594
|
+
if (context.isPretty() && windowParts.length > 1) {
|
|
1595
|
+
const formattedParts = windowParts.map(part => context.indent(part));
|
|
1596
|
+
return ` OVER (${context.newline()}${formattedParts.join(context.newline())}${context.newline()})`;
|
|
1597
|
+
}
|
|
1598
|
+
return ` OVER (${windowParts.join(' ')})`;
|
|
1599
|
+
}
|
|
1392
1600
|
FuncExpr(node, context) {
|
|
1393
1601
|
const funcName = `func_${node.funcid}`;
|
|
1394
1602
|
const args = node.args ? ListUtils.unwrapList(node.args).map(arg => this.visit(arg, context)).join(', ') : '';
|
|
@@ -1399,39 +1607,39 @@ export class Deparser {
|
|
|
1399
1607
|
if (nodeAny.ival !== undefined) {
|
|
1400
1608
|
if (typeof nodeAny.ival === 'object' && nodeAny.ival !== null) {
|
|
1401
1609
|
if (nodeAny.ival.ival !== undefined) {
|
|
1402
|
-
return nodeAny.ival.ival
|
|
1610
|
+
return formatInteger(nodeAny.ival.ival);
|
|
1403
1611
|
}
|
|
1404
1612
|
else if (Object.keys(nodeAny.ival).length === 0) {
|
|
1405
1613
|
return '0';
|
|
1406
1614
|
}
|
|
1407
1615
|
else {
|
|
1408
|
-
return nodeAny.ival
|
|
1616
|
+
return formatInteger(nodeAny.ival);
|
|
1409
1617
|
}
|
|
1410
1618
|
}
|
|
1411
1619
|
else if (nodeAny.ival === null) {
|
|
1412
1620
|
return 'NULL';
|
|
1413
1621
|
}
|
|
1414
1622
|
else {
|
|
1415
|
-
return nodeAny.ival
|
|
1623
|
+
return formatInteger(nodeAny.ival);
|
|
1416
1624
|
}
|
|
1417
1625
|
}
|
|
1418
1626
|
else if (nodeAny.fval !== undefined) {
|
|
1419
1627
|
if (typeof nodeAny.fval === 'object' && nodeAny.fval !== null) {
|
|
1420
1628
|
if (nodeAny.fval.fval !== undefined) {
|
|
1421
|
-
return nodeAny.fval.fval
|
|
1629
|
+
return formatNumeric(nodeAny.fval.fval);
|
|
1422
1630
|
}
|
|
1423
1631
|
else if (Object.keys(nodeAny.fval).length === 0) {
|
|
1424
1632
|
return '0.0';
|
|
1425
1633
|
}
|
|
1426
1634
|
else {
|
|
1427
|
-
return nodeAny.fval
|
|
1635
|
+
return formatNumeric(nodeAny.fval);
|
|
1428
1636
|
}
|
|
1429
1637
|
}
|
|
1430
1638
|
else if (nodeAny.fval === null) {
|
|
1431
1639
|
return 'NULL';
|
|
1432
1640
|
}
|
|
1433
1641
|
else {
|
|
1434
|
-
return nodeAny.fval
|
|
1642
|
+
return formatNumeric(nodeAny.fval);
|
|
1435
1643
|
}
|
|
1436
1644
|
}
|
|
1437
1645
|
else if (nodeAny.sval !== undefined) {
|
|
@@ -1478,15 +1686,7 @@ export class Deparser {
|
|
|
1478
1686
|
else if (nodeAny.bsval !== undefined) {
|
|
1479
1687
|
if (typeof nodeAny.bsval === 'object' && nodeAny.bsval !== null) {
|
|
1480
1688
|
if (nodeAny.bsval.bsval !== undefined) {
|
|
1481
|
-
|
|
1482
|
-
// Check if this is a hexadecimal bit string (starts with x and contains only hex digits)
|
|
1483
|
-
if (bsval.startsWith('x') && /^x[0-9A-Fa-f]+$/.test(bsval)) {
|
|
1484
|
-
return `x'${bsval.substring(1)}'`;
|
|
1485
|
-
}
|
|
1486
|
-
if (bsval.startsWith('b')) {
|
|
1487
|
-
return `b'${bsval.substring(1)}'`;
|
|
1488
|
-
}
|
|
1489
|
-
return `b'${bsval}'`;
|
|
1689
|
+
return formatBitString(nodeAny.bsval.bsval);
|
|
1490
1690
|
}
|
|
1491
1691
|
else if (Object.keys(nodeAny.bsval).length === 0) {
|
|
1492
1692
|
return "''";
|
|
@@ -1499,23 +1699,15 @@ export class Deparser {
|
|
|
1499
1699
|
return 'NULL';
|
|
1500
1700
|
}
|
|
1501
1701
|
else {
|
|
1502
|
-
|
|
1503
|
-
// Check if this is a hexadecimal bit string (starts with x and contains only hex digits)
|
|
1504
|
-
if (bsval.startsWith('x') && /^x[0-9A-Fa-f]+$/.test(bsval)) {
|
|
1505
|
-
return `x'${bsval.substring(1)}'`;
|
|
1506
|
-
}
|
|
1507
|
-
if (bsval.startsWith('b')) {
|
|
1508
|
-
return `b'${bsval.substring(1)}'`;
|
|
1509
|
-
}
|
|
1510
|
-
return `b'${bsval}'`;
|
|
1702
|
+
return formatBitString(nodeAny.bsval);
|
|
1511
1703
|
}
|
|
1512
1704
|
}
|
|
1513
1705
|
if (nodeAny.val) {
|
|
1514
1706
|
if (nodeAny.val.Integer?.ival !== undefined) {
|
|
1515
|
-
return nodeAny.val.Integer.ival
|
|
1707
|
+
return formatInteger(nodeAny.val.Integer.ival);
|
|
1516
1708
|
}
|
|
1517
1709
|
else if (nodeAny.val.Float?.fval !== undefined) {
|
|
1518
|
-
return nodeAny.val.Float.fval
|
|
1710
|
+
return formatNumeric(nodeAny.val.Float.fval);
|
|
1519
1711
|
}
|
|
1520
1712
|
else if (nodeAny.val.String?.sval !== undefined) {
|
|
1521
1713
|
return QuoteUtils.escape(nodeAny.val.String.sval);
|
|
@@ -1524,7 +1716,7 @@ export class Deparser {
|
|
|
1524
1716
|
return nodeAny.val.Boolean.boolval ? 'true' : 'false';
|
|
1525
1717
|
}
|
|
1526
1718
|
else if (nodeAny.val.BitString?.bsval !== undefined) {
|
|
1527
|
-
return nodeAny.val.BitString.bsval;
|
|
1719
|
+
return formatBitString(nodeAny.val.BitString.bsval);
|
|
1528
1720
|
}
|
|
1529
1721
|
}
|
|
1530
1722
|
if (nodeAny.isnull === true) {
|
|
@@ -1536,15 +1728,15 @@ export class Deparser {
|
|
|
1536
1728
|
}
|
|
1537
1729
|
if (nodeAny.Integer !== undefined) {
|
|
1538
1730
|
if (typeof nodeAny.Integer === 'object' && nodeAny.Integer.ival !== undefined) {
|
|
1539
|
-
return nodeAny.Integer.ival
|
|
1731
|
+
return formatInteger(nodeAny.Integer.ival);
|
|
1540
1732
|
}
|
|
1541
|
-
return nodeAny.Integer
|
|
1733
|
+
return formatInteger(nodeAny.Integer);
|
|
1542
1734
|
}
|
|
1543
1735
|
if (nodeAny.Float !== undefined) {
|
|
1544
1736
|
if (typeof nodeAny.Float === 'object' && nodeAny.Float.fval !== undefined) {
|
|
1545
|
-
return nodeAny.Float.fval
|
|
1737
|
+
return formatNumeric(nodeAny.Float.fval);
|
|
1546
1738
|
}
|
|
1547
|
-
return nodeAny.Float
|
|
1739
|
+
return formatNumeric(nodeAny.Float);
|
|
1548
1740
|
}
|
|
1549
1741
|
if (nodeAny.String !== undefined) {
|
|
1550
1742
|
if (typeof nodeAny.String === 'object' && nodeAny.String.sval !== undefined) {
|
|
@@ -1564,7 +1756,7 @@ export class Deparser {
|
|
|
1564
1756
|
const fields = ListUtils.unwrapList(node.fields);
|
|
1565
1757
|
return fields.map(field => {
|
|
1566
1758
|
if (field.String) {
|
|
1567
|
-
return QuoteUtils.
|
|
1759
|
+
return QuoteUtils.quoteIdentifier(field.String.sval || field.String.str);
|
|
1568
1760
|
}
|
|
1569
1761
|
else if (field.A_Star) {
|
|
1570
1762
|
return '*';
|
|
@@ -1641,8 +1833,7 @@ export class Deparser {
|
|
|
1641
1833
|
}
|
|
1642
1834
|
return output.join(' ');
|
|
1643
1835
|
}
|
|
1644
|
-
|
|
1645
|
-
let result = mods(quotedTypeName, args);
|
|
1836
|
+
let result = mods(QuoteUtils.quoteIdentifierTypeName(typeName), args);
|
|
1646
1837
|
if (node.arrayBounds && node.arrayBounds.length > 0) {
|
|
1647
1838
|
result += formatArrayBounds(node.arrayBounds);
|
|
1648
1839
|
}
|
|
@@ -1738,8 +1929,9 @@ export class Deparser {
|
|
|
1738
1929
|
return output.join(' ');
|
|
1739
1930
|
}
|
|
1740
1931
|
}
|
|
1741
|
-
|
|
1742
|
-
|
|
1932
|
+
// Use type-name quoting for non-pg_catalog types
|
|
1933
|
+
// This allows keywords like 'json', 'int', 'boolean' to remain unquoted in type positions
|
|
1934
|
+
let result = mods(QuoteUtils.quoteTypeDottedName(names), args);
|
|
1743
1935
|
if (node.arrayBounds && node.arrayBounds.length > 0) {
|
|
1744
1936
|
result += formatArrayBounds(node.arrayBounds);
|
|
1745
1937
|
}
|
|
@@ -1777,17 +1969,17 @@ export class Deparser {
|
|
|
1777
1969
|
}
|
|
1778
1970
|
let tableName = '';
|
|
1779
1971
|
if (node.catalogname) {
|
|
1780
|
-
tableName = QuoteUtils.
|
|
1972
|
+
tableName = QuoteUtils.quoteIdentifier(node.catalogname);
|
|
1781
1973
|
if (node.schemaname) {
|
|
1782
|
-
tableName += '.' + QuoteUtils.
|
|
1974
|
+
tableName += '.' + QuoteUtils.quoteIdentifierAfterDot(node.schemaname);
|
|
1783
1975
|
}
|
|
1784
|
-
tableName += '.' + QuoteUtils.
|
|
1976
|
+
tableName += '.' + QuoteUtils.quoteIdentifierAfterDot(node.relname);
|
|
1785
1977
|
}
|
|
1786
1978
|
else if (node.schemaname) {
|
|
1787
|
-
tableName = QuoteUtils.
|
|
1979
|
+
tableName = QuoteUtils.quoteQualifiedIdentifier(node.schemaname, node.relname);
|
|
1788
1980
|
}
|
|
1789
1981
|
else {
|
|
1790
|
-
tableName = QuoteUtils.
|
|
1982
|
+
tableName = QuoteUtils.quoteIdentifier(node.relname);
|
|
1791
1983
|
}
|
|
1792
1984
|
output.push(tableName);
|
|
1793
1985
|
if (node.alias) {
|
|
@@ -1941,7 +2133,7 @@ export class Deparser {
|
|
|
1941
2133
|
if (size != null) {
|
|
1942
2134
|
return 'char';
|
|
1943
2135
|
}
|
|
1944
|
-
return '
|
|
2136
|
+
return 'bpchar';
|
|
1945
2137
|
case 'varchar':
|
|
1946
2138
|
return 'varchar';
|
|
1947
2139
|
case 'numeric':
|
|
@@ -1955,7 +2147,7 @@ export class Deparser {
|
|
|
1955
2147
|
case 'int8':
|
|
1956
2148
|
return 'bigint';
|
|
1957
2149
|
case 'real':
|
|
1958
|
-
return '
|
|
2150
|
+
return 'float4';
|
|
1959
2151
|
case 'time':
|
|
1960
2152
|
return 'time';
|
|
1961
2153
|
case 'timestamp':
|
|
@@ -1965,7 +2157,7 @@ export class Deparser {
|
|
|
1965
2157
|
case 'bit':
|
|
1966
2158
|
return 'bit';
|
|
1967
2159
|
default:
|
|
1968
|
-
return
|
|
2160
|
+
return typeName;
|
|
1969
2161
|
}
|
|
1970
2162
|
}
|
|
1971
2163
|
isPgCatalogType(typeName) {
|
|
@@ -2006,14 +2198,16 @@ export class Deparser {
|
|
|
2006
2198
|
A_Indirection(node, context) {
|
|
2007
2199
|
let argStr = this.visit(node.arg, context);
|
|
2008
2200
|
const argType = this.getNodeType(node.arg);
|
|
2009
|
-
|
|
2201
|
+
// Grammar: only a parameter takes indirection bare; every other target is
|
|
2202
|
+
// `'(' a_expr ')' opt_indirection` (a plain column subscript is the same node).
|
|
2203
|
+
if (argType !== 'ParamRef') {
|
|
2010
2204
|
argStr = `(${argStr})`;
|
|
2011
2205
|
}
|
|
2012
2206
|
const output = [argStr];
|
|
2013
2207
|
const indirection = ListUtils.unwrapList(node.indirection);
|
|
2014
2208
|
for (const subnode of indirection) {
|
|
2015
2209
|
if (subnode.String || subnode.A_Star) {
|
|
2016
|
-
const value = subnode.A_Star ? '*' : QuoteUtils.
|
|
2210
|
+
const value = subnode.A_Star ? '*' : QuoteUtils.quoteIdentifier(subnode.String.sval || subnode.String.str);
|
|
2017
2211
|
output.push(`.${value}`);
|
|
2018
2212
|
}
|
|
2019
2213
|
else {
|
|
@@ -2034,21 +2228,11 @@ export class Deparser {
|
|
|
2034
2228
|
if (context.isPretty() && args.length > 0) {
|
|
2035
2229
|
for (const arg of args) {
|
|
2036
2230
|
const whenClause = this.visit(arg, context);
|
|
2037
|
-
|
|
2038
|
-
output.push(context.newline() + whenClause);
|
|
2039
|
-
}
|
|
2040
|
-
else {
|
|
2041
|
-
output.push(context.newline() + context.indent(whenClause));
|
|
2042
|
-
}
|
|
2231
|
+
output.push(context.newline() + context.indent(whenClause));
|
|
2043
2232
|
}
|
|
2044
2233
|
if (node.defresult) {
|
|
2045
2234
|
const elseResult = this.visit(node.defresult, context);
|
|
2046
|
-
|
|
2047
|
-
output.push(context.newline() + 'ELSE ' + elseResult);
|
|
2048
|
-
}
|
|
2049
|
-
else {
|
|
2050
|
-
output.push(context.newline() + context.indent('ELSE ' + elseResult));
|
|
2051
|
-
}
|
|
2235
|
+
output.push(context.newline() + context.indent('ELSE ' + elseResult));
|
|
2052
2236
|
}
|
|
2053
2237
|
output.push(context.newline() + 'END');
|
|
2054
2238
|
return output.join(' ');
|
|
@@ -2089,10 +2273,13 @@ export class Deparser {
|
|
|
2089
2273
|
const isFunctionCall = argType === 'FuncCall';
|
|
2090
2274
|
if (isSimpleArgument || isFunctionCall) {
|
|
2091
2275
|
// For simple arguments, avoid :: syntax if they have complex structure
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
else {
|
|
2276
|
+
const shouldUseCastSyntax = isSimpleArgument && (arg.includes('(') || arg.startsWith('-'));
|
|
2277
|
+
if (!shouldUseCastSyntax) {
|
|
2095
2278
|
const cleanTypeName = typeName.replace('pg_catalog.', '');
|
|
2279
|
+
// Wrap FuncCall arguments in parentheses to prevent operator precedence issues
|
|
2280
|
+
if (isFunctionCall) {
|
|
2281
|
+
return `${context.parens(arg)}::${cleanTypeName}`;
|
|
2282
|
+
}
|
|
2096
2283
|
return `${arg}::${cleanTypeName}`;
|
|
2097
2284
|
}
|
|
2098
2285
|
}
|
|
@@ -2155,45 +2342,21 @@ export class Deparser {
|
|
|
2155
2342
|
}
|
|
2156
2343
|
return output.join(' ');
|
|
2157
2344
|
}
|
|
2158
|
-
static RESERVED_WORDS = new Set([
|
|
2159
|
-
'all', 'analyse', 'analyze', 'and', 'any', 'array', 'as', 'asc', 'asymmetric', 'both',
|
|
2160
|
-
'case', 'cast', 'check', 'collate', 'column', 'constraint', 'create', 'current_catalog',
|
|
2161
|
-
'current_date', 'current_role', 'current_time', 'current_timestamp', 'current_user',
|
|
2162
|
-
'default', 'deferrable', 'desc', 'distinct', 'do', 'else', 'end', 'except', 'false',
|
|
2163
|
-
'fetch', 'for', 'foreign', 'from', 'grant', 'group', 'having', 'in', 'initially',
|
|
2164
|
-
'intersect', 'into', 'lateral', 'leading', 'limit', 'localtime', 'localtimestamp',
|
|
2165
|
-
'not', 'null', 'offset', 'on', 'only', 'or', 'order', 'placing', 'primary',
|
|
2166
|
-
'references', 'returning', 'select', 'session_user', 'some', 'symmetric', 'table',
|
|
2167
|
-
'then', 'to', 'trailing', 'true', 'union', 'unique', 'user', 'using', 'variadic',
|
|
2168
|
-
'when', 'where', 'window', 'with'
|
|
2169
|
-
]);
|
|
2170
|
-
static needsQuotes(value) {
|
|
2171
|
-
if (!value)
|
|
2172
|
-
return false;
|
|
2173
|
-
const needsQuotesRegex = /[a-z]+[\W\w]*[A-Z]+|[A-Z]+[\W\w]*[a-z]+|\W/;
|
|
2174
|
-
const isAllUppercase = /^[A-Z]+$/.test(value);
|
|
2175
|
-
return needsQuotesRegex.test(value) ||
|
|
2176
|
-
Deparser.RESERVED_WORDS.has(value.toLowerCase()) ||
|
|
2177
|
-
isAllUppercase;
|
|
2178
|
-
}
|
|
2179
2345
|
quoteIfNeeded(value) {
|
|
2180
|
-
|
|
2181
|
-
return `"${value}"`;
|
|
2182
|
-
}
|
|
2183
|
-
return value;
|
|
2346
|
+
return QuoteUtils.quoteIdentifier(value);
|
|
2184
2347
|
}
|
|
2185
2348
|
preserveOperatorDefElemCase(defName) {
|
|
2186
2349
|
const caseMap = {
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2350
|
+
leftarg: 'Leftarg',
|
|
2351
|
+
rightarg: 'Rightarg',
|
|
2352
|
+
procedure: 'Procedure',
|
|
2353
|
+
function: 'Function',
|
|
2354
|
+
commutator: 'Commutator',
|
|
2355
|
+
negator: 'Negator',
|
|
2356
|
+
restrict: 'Restrict',
|
|
2357
|
+
join: 'Join',
|
|
2358
|
+
hashes: 'Hashes',
|
|
2359
|
+
merges: 'Merges'
|
|
2197
2360
|
};
|
|
2198
2361
|
return caseMap[defName.toLowerCase()] || defName;
|
|
2199
2362
|
}
|
|
@@ -2213,27 +2376,19 @@ export class Deparser {
|
|
|
2213
2376
|
return value; // Don't quote pure operator symbols like "=" or "-"
|
|
2214
2377
|
}
|
|
2215
2378
|
}
|
|
2216
|
-
return
|
|
2379
|
+
return QuoteUtils.quoteIdentifier(value);
|
|
2217
2380
|
}
|
|
2218
2381
|
Integer(node, context) {
|
|
2219
|
-
return node.ival
|
|
2382
|
+
return node.ival === undefined || node.ival === null ? '0' : formatInteger(node.ival);
|
|
2220
2383
|
}
|
|
2221
2384
|
Float(node, context) {
|
|
2222
|
-
return node.fval
|
|
2385
|
+
return node.fval ? formatNumeric(node.fval) : '0.0';
|
|
2223
2386
|
}
|
|
2224
2387
|
Boolean(node, context) {
|
|
2225
2388
|
return node.boolval ? 'true' : 'false';
|
|
2226
2389
|
}
|
|
2227
2390
|
BitString(node, context) {
|
|
2228
|
-
|
|
2229
|
-
if (node.bsval.startsWith('x')) {
|
|
2230
|
-
return `x'${node.bsval.substring(1)}'`;
|
|
2231
|
-
}
|
|
2232
|
-
if (node.bsval.startsWith('b')) {
|
|
2233
|
-
return `b'${node.bsval.substring(1)}'`;
|
|
2234
|
-
}
|
|
2235
|
-
// Fallback for raw values without prefix
|
|
2236
|
-
return `b'${node.bsval}'`;
|
|
2391
|
+
return formatBitString(node.bsval);
|
|
2237
2392
|
}
|
|
2238
2393
|
Null(node, context) {
|
|
2239
2394
|
return 'NULL';
|
|
@@ -2272,7 +2427,7 @@ export class Deparser {
|
|
|
2272
2427
|
output.push(context.parens(elementStrs.join(', ')));
|
|
2273
2428
|
}
|
|
2274
2429
|
}
|
|
2275
|
-
else if (node.tableElts) {
|
|
2430
|
+
else if (node.tableElts && !node.partbound) {
|
|
2276
2431
|
const elements = ListUtils.unwrapList(node.tableElts);
|
|
2277
2432
|
const elementStrs = elements.map(el => {
|
|
2278
2433
|
return this.deparse(el, context.spawn('CreateStmt'));
|
|
@@ -2300,7 +2455,16 @@ export class Deparser {
|
|
|
2300
2455
|
const inherits = ListUtils.unwrapList(node.inhRelations);
|
|
2301
2456
|
const inheritStrs = inherits.map(rel => this.visit(rel, context));
|
|
2302
2457
|
output.push(inheritStrs[0]);
|
|
2303
|
-
if (node.
|
|
2458
|
+
if (node.tableElts) {
|
|
2459
|
+
const elementStrs = ListUtils.unwrapList(node.tableElts).map(el => {
|
|
2460
|
+
return this.deparse(el, context.spawn('CreateStmt'));
|
|
2461
|
+
});
|
|
2462
|
+
output.push(context.parens(elementStrs.join(', ')));
|
|
2463
|
+
}
|
|
2464
|
+
if (node.partbound.is_default) {
|
|
2465
|
+
output.push('DEFAULT');
|
|
2466
|
+
}
|
|
2467
|
+
else if (node.partbound.strategy === 'l' && node.partbound.listdatums) {
|
|
2304
2468
|
output.push('FOR VALUES IN');
|
|
2305
2469
|
const listValues = ListUtils.unwrapList(node.partbound.listdatums)
|
|
2306
2470
|
.map(datum => this.visit(datum, context))
|
|
@@ -2323,13 +2487,9 @@ export class Deparser {
|
|
|
2323
2487
|
output.push(`(${upperValues})`);
|
|
2324
2488
|
}
|
|
2325
2489
|
}
|
|
2326
|
-
else if (node.partbound.strategy === 'h'
|
|
2490
|
+
else if (node.partbound.strategy === 'h') {
|
|
2327
2491
|
output.push('FOR VALUES WITH');
|
|
2328
|
-
|
|
2329
|
-
output.push(`(MODULUS ${node.partbound.modulus}, REMAINDER ${remainder})`);
|
|
2330
|
-
}
|
|
2331
|
-
else if (node.partbound.is_default) {
|
|
2332
|
-
output.push('DEFAULT');
|
|
2492
|
+
output.push(`(MODULUS ${node.partbound.modulus ?? 0}, REMAINDER ${node.partbound.remainder ?? 0})`);
|
|
2333
2493
|
}
|
|
2334
2494
|
}
|
|
2335
2495
|
else if (node.inhRelations) {
|
|
@@ -2390,11 +2550,17 @@ export class Deparser {
|
|
|
2390
2550
|
ColumnDef(node, context) {
|
|
2391
2551
|
const output = [];
|
|
2392
2552
|
if (node.colname) {
|
|
2393
|
-
output.push(QuoteUtils.
|
|
2553
|
+
output.push(QuoteUtils.quoteIdentifier(node.colname));
|
|
2394
2554
|
}
|
|
2395
2555
|
if (node.typeName) {
|
|
2396
2556
|
output.push(this.TypeName(node.typeName, context));
|
|
2397
2557
|
}
|
|
2558
|
+
if (node.storage_name) {
|
|
2559
|
+
output.push('STORAGE', node.storage_name.toUpperCase());
|
|
2560
|
+
}
|
|
2561
|
+
if (node.compression) {
|
|
2562
|
+
output.push('COMPRESSION', QuoteUtils.quoteIdentifier(node.compression));
|
|
2563
|
+
}
|
|
2398
2564
|
if (node.fdwoptions && node.fdwoptions.length > 0) {
|
|
2399
2565
|
output.push('OPTIONS');
|
|
2400
2566
|
const columnContext = context.spawn('ColumnDef');
|
|
@@ -2429,9 +2595,9 @@ export class Deparser {
|
|
|
2429
2595
|
Constraint(node, context) {
|
|
2430
2596
|
const output = [];
|
|
2431
2597
|
// Handle constraint name if present
|
|
2432
|
-
if (node.conname && (node.contype === 'CONSTR_CHECK' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_FOREIGN')) {
|
|
2598
|
+
if (node.conname && (node.contype === 'CONSTR_CHECK' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_FOREIGN' || node.contype === 'CONSTR_NOTNULL' || node.contype === 'CONSTR_EXCLUSION')) {
|
|
2433
2599
|
output.push('CONSTRAINT');
|
|
2434
|
-
output.push(QuoteUtils.
|
|
2600
|
+
output.push(QuoteUtils.quoteIdentifier(node.conname));
|
|
2435
2601
|
}
|
|
2436
2602
|
switch (node.contype) {
|
|
2437
2603
|
case 'CONSTR_NULL':
|
|
@@ -2439,11 +2605,24 @@ export class Deparser {
|
|
|
2439
2605
|
break;
|
|
2440
2606
|
case 'CONSTR_NOTNULL':
|
|
2441
2607
|
output.push('NOT NULL');
|
|
2608
|
+
if (node.keys && node.keys.length > 0 && !context.isColumnConstraint) {
|
|
2609
|
+
const keyList = ListUtils.unwrapList(node.keys)
|
|
2610
|
+
.map(key => this.visit(key, context))
|
|
2611
|
+
.join(', ');
|
|
2612
|
+
output.push(keyList);
|
|
2613
|
+
}
|
|
2614
|
+
if (node.is_no_inherit) {
|
|
2615
|
+
output.push('NO INHERIT');
|
|
2616
|
+
}
|
|
2617
|
+
if (node.skip_validation) {
|
|
2618
|
+
output.push('NOT VALID');
|
|
2619
|
+
}
|
|
2442
2620
|
break;
|
|
2443
2621
|
case 'CONSTR_DEFAULT':
|
|
2444
2622
|
output.push('DEFAULT');
|
|
2445
2623
|
if (node.raw_expr) {
|
|
2446
|
-
|
|
2624
|
+
const defaultExpr = this.visit(node.raw_expr, context);
|
|
2625
|
+
output.push(this.needsBExprParens(node.raw_expr) ? `(${defaultExpr})` : defaultExpr);
|
|
2447
2626
|
}
|
|
2448
2627
|
break;
|
|
2449
2628
|
case 'CONSTR_CHECK':
|
|
@@ -2467,8 +2646,13 @@ export class Deparser {
|
|
|
2467
2646
|
output.push(context.parens(this.visit(node.raw_expr, context)));
|
|
2468
2647
|
}
|
|
2469
2648
|
}
|
|
2470
|
-
//
|
|
2471
|
-
|
|
2649
|
+
// PG18: constraints are enforced unless explicitly NOT ENFORCED
|
|
2650
|
+
// (libpg-query omits false booleans, so undefined means not enforced)
|
|
2651
|
+
if (node.is_enforced !== true && !context.isDomainConstraint) {
|
|
2652
|
+
output.push('NOT ENFORCED');
|
|
2653
|
+
}
|
|
2654
|
+
else if (node.skip_validation) {
|
|
2655
|
+
// NOT ENFORCED implies NOT VALID, so only emit NOT VALID when enforced
|
|
2472
2656
|
output.push('NOT VALID');
|
|
2473
2657
|
}
|
|
2474
2658
|
// Handle NO INHERIT for check constraints - only for table constraints, not domain constraints
|
|
@@ -2488,7 +2672,7 @@ export class Deparser {
|
|
|
2488
2672
|
if (node.raw_expr) {
|
|
2489
2673
|
output.push(context.parens(this.visit(node.raw_expr, context)));
|
|
2490
2674
|
}
|
|
2491
|
-
output.push('STORED');
|
|
2675
|
+
output.push(node.generated_kind === 'v' ? 'VIRTUAL' : 'STORED');
|
|
2492
2676
|
break;
|
|
2493
2677
|
case 'CONSTR_IDENTITY':
|
|
2494
2678
|
output.push('GENERATED');
|
|
@@ -2564,10 +2748,12 @@ export class Deparser {
|
|
|
2564
2748
|
case 'CONSTR_PRIMARY':
|
|
2565
2749
|
output.push('PRIMARY KEY');
|
|
2566
2750
|
if (node.keys && node.keys.length > 0) {
|
|
2567
|
-
const
|
|
2568
|
-
.map(key => this.visit(key, context))
|
|
2569
|
-
|
|
2570
|
-
|
|
2751
|
+
const keyItems = ListUtils.unwrapList(node.keys)
|
|
2752
|
+
.map(key => this.visit(key, context));
|
|
2753
|
+
if (node.without_overlaps) {
|
|
2754
|
+
keyItems[keyItems.length - 1] += ' WITHOUT OVERLAPS';
|
|
2755
|
+
}
|
|
2756
|
+
output.push(`(${keyItems.join(', ')})`);
|
|
2571
2757
|
}
|
|
2572
2758
|
if (node.indexname) {
|
|
2573
2759
|
output.push('USING INDEX');
|
|
@@ -2585,10 +2771,12 @@ export class Deparser {
|
|
|
2585
2771
|
output.push('NULLS NOT DISTINCT');
|
|
2586
2772
|
}
|
|
2587
2773
|
if (node.keys && node.keys.length > 0) {
|
|
2588
|
-
const
|
|
2589
|
-
.map(key => this.visit(key, context))
|
|
2590
|
-
|
|
2591
|
-
|
|
2774
|
+
const keyItems = ListUtils.unwrapList(node.keys)
|
|
2775
|
+
.map(key => this.visit(key, context));
|
|
2776
|
+
if (node.without_overlaps) {
|
|
2777
|
+
keyItems[keyItems.length - 1] += ' WITHOUT OVERLAPS';
|
|
2778
|
+
}
|
|
2779
|
+
output.push(`(${keyItems.join(', ')})`);
|
|
2592
2780
|
}
|
|
2593
2781
|
if (node.indexname) {
|
|
2594
2782
|
output.push('USING INDEX');
|
|
@@ -2601,20 +2789,14 @@ export class Deparser {
|
|
|
2601
2789
|
if (context.isPretty()) {
|
|
2602
2790
|
output.push('\n' + context.indent('FOREIGN KEY'));
|
|
2603
2791
|
if (node.fk_attrs && node.fk_attrs.length > 0) {
|
|
2604
|
-
|
|
2605
|
-
.map(attr => this.visit(attr, context))
|
|
2606
|
-
.join(', ');
|
|
2607
|
-
output.push(`(${fkAttrs})`);
|
|
2792
|
+
output.push(`(${this.deparseKeyAttrs(node.fk_attrs, node.fk_with_period, context)})`);
|
|
2608
2793
|
}
|
|
2609
2794
|
output.push('\n' + context.indent('REFERENCES'));
|
|
2610
2795
|
}
|
|
2611
2796
|
else {
|
|
2612
2797
|
output.push('FOREIGN KEY');
|
|
2613
2798
|
if (node.fk_attrs && node.fk_attrs.length > 0) {
|
|
2614
|
-
|
|
2615
|
-
.map(attr => this.visit(attr, context))
|
|
2616
|
-
.join(', ');
|
|
2617
|
-
output.push(`(${fkAttrs})`);
|
|
2799
|
+
output.push(`(${this.deparseKeyAttrs(node.fk_attrs, node.fk_with_period, context)})`);
|
|
2618
2800
|
}
|
|
2619
2801
|
output.push('REFERENCES');
|
|
2620
2802
|
}
|
|
@@ -2637,9 +2819,7 @@ export class Deparser {
|
|
|
2637
2819
|
}
|
|
2638
2820
|
}
|
|
2639
2821
|
if (node.pk_attrs && node.pk_attrs.length > 0) {
|
|
2640
|
-
const pkAttrs =
|
|
2641
|
-
.map(attr => this.visit(attr, context))
|
|
2642
|
-
.join(', ');
|
|
2822
|
+
const pkAttrs = this.deparseKeyAttrs(node.pk_attrs, node.pk_with_period, context);
|
|
2643
2823
|
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2644
2824
|
const lastIndex = output.length - 1;
|
|
2645
2825
|
if (lastIndex >= 0) {
|
|
@@ -2710,6 +2890,15 @@ export class Deparser {
|
|
|
2710
2890
|
deleteClause += 'SET DEFAULT';
|
|
2711
2891
|
break;
|
|
2712
2892
|
}
|
|
2893
|
+
if ((node.fk_del_action === 'n' || node.fk_del_action === 'd') && node.fk_del_set_cols && node.fk_del_set_cols.length > 0) {
|
|
2894
|
+
const setColumns = ListUtils.unwrapList(node.fk_del_set_cols)
|
|
2895
|
+
.map(column => {
|
|
2896
|
+
const stringNode = column.String;
|
|
2897
|
+
return QuoteUtils.quoteIdentifier(stringNode.sval || stringNode.str || '');
|
|
2898
|
+
})
|
|
2899
|
+
.join(', ');
|
|
2900
|
+
deleteClause += ` (${setColumns})`;
|
|
2901
|
+
}
|
|
2713
2902
|
if (context.isPretty()) {
|
|
2714
2903
|
output.push('\n' + context.indent(deleteClause));
|
|
2715
2904
|
}
|
|
@@ -2718,8 +2907,18 @@ export class Deparser {
|
|
|
2718
2907
|
output.push(deleteClause.replace('ON DELETE ', ''));
|
|
2719
2908
|
}
|
|
2720
2909
|
}
|
|
2721
|
-
//
|
|
2722
|
-
|
|
2910
|
+
// PG18: constraints are enforced unless explicitly NOT ENFORCED
|
|
2911
|
+
// (libpg-query omits false booleans, so undefined means not enforced)
|
|
2912
|
+
if (node.is_enforced !== true && !context.isDomainConstraint) {
|
|
2913
|
+
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2914
|
+
output.push('\n' + context.indent('NOT ENFORCED'));
|
|
2915
|
+
}
|
|
2916
|
+
else {
|
|
2917
|
+
output.push('NOT ENFORCED');
|
|
2918
|
+
}
|
|
2919
|
+
}
|
|
2920
|
+
else if (node.skip_validation && !context.isDomainConstraint) {
|
|
2921
|
+
// NOT ENFORCED implies NOT VALID, so only emit NOT VALID when enforced
|
|
2723
2922
|
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2724
2923
|
output.push('\n' + context.indent('NOT VALID'));
|
|
2725
2924
|
}
|
|
@@ -2740,6 +2939,12 @@ export class Deparser {
|
|
|
2740
2939
|
case 'CONSTR_ATTR_IMMEDIATE':
|
|
2741
2940
|
output.push('INITIALLY IMMEDIATE');
|
|
2742
2941
|
break;
|
|
2942
|
+
case 'CONSTR_ATTR_ENFORCED':
|
|
2943
|
+
output.push('ENFORCED');
|
|
2944
|
+
break;
|
|
2945
|
+
case 'CONSTR_ATTR_NOT_ENFORCED':
|
|
2946
|
+
output.push('NOT ENFORCED');
|
|
2947
|
+
break;
|
|
2743
2948
|
case 'CONSTR_EXCLUSION':
|
|
2744
2949
|
output.push('EXCLUDE');
|
|
2745
2950
|
if (node.access_method) {
|
|
@@ -2774,10 +2979,14 @@ export class Deparser {
|
|
|
2774
2979
|
});
|
|
2775
2980
|
output.push(`(${exclusionElements.join(', ')})`);
|
|
2776
2981
|
}
|
|
2982
|
+
if (node.where_clause) {
|
|
2983
|
+
output.push('WHERE');
|
|
2984
|
+
output.push(context.parens(this.visit(node.where_clause, context)));
|
|
2985
|
+
}
|
|
2777
2986
|
break;
|
|
2778
2987
|
}
|
|
2779
2988
|
// Handle deferrable constraints for all constraint types that support it
|
|
2780
|
-
if (node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_FOREIGN') {
|
|
2989
|
+
if (node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_FOREIGN' || node.contype === 'CONSTR_EXCLUSION') {
|
|
2781
2990
|
if (node.deferrable) {
|
|
2782
2991
|
if (context.isPretty() && node.contype === 'CONSTR_FOREIGN') {
|
|
2783
2992
|
output.push('\n' + context.indent('DEFERRABLE'));
|
|
@@ -2806,6 +3015,9 @@ export class Deparser {
|
|
|
2806
3015
|
output.push('NOT DEFERRABLE');
|
|
2807
3016
|
}
|
|
2808
3017
|
}
|
|
3018
|
+
else if (node.initdeferred) {
|
|
3019
|
+
output.push('INITIALLY DEFERRED');
|
|
3020
|
+
}
|
|
2809
3021
|
}
|
|
2810
3022
|
if (context.isPretty() && node.contype === 'CONSTR_FOREIGN') {
|
|
2811
3023
|
let result = '';
|
|
@@ -2871,6 +3083,9 @@ export class Deparser {
|
|
|
2871
3083
|
output.push(node.name);
|
|
2872
3084
|
}
|
|
2873
3085
|
const windowParts = [];
|
|
3086
|
+
if (node.refname) {
|
|
3087
|
+
windowParts.push(node.refname);
|
|
3088
|
+
}
|
|
2874
3089
|
if (node.partitionClause) {
|
|
2875
3090
|
const partitions = ListUtils.unwrapList(node.partitionClause);
|
|
2876
3091
|
const partitionStrs = partitions.map(p => this.visit(p, context));
|
|
@@ -2881,12 +3096,9 @@ export class Deparser {
|
|
|
2881
3096
|
const orderStrs = orders.map(o => this.visit(o, context));
|
|
2882
3097
|
windowParts.push(`ORDER BY ${orderStrs.join(', ')}`);
|
|
2883
3098
|
}
|
|
2884
|
-
|
|
2885
|
-
if (
|
|
2886
|
-
|
|
2887
|
-
if (frameClause) {
|
|
2888
|
-
windowParts.push(frameClause);
|
|
2889
|
-
}
|
|
3099
|
+
const frameClause = this.formatWindowFrame(node, context.spawn('WindowDef'));
|
|
3100
|
+
if (frameClause) {
|
|
3101
|
+
windowParts.push(frameClause);
|
|
2890
3102
|
}
|
|
2891
3103
|
if (windowParts.length > 0) {
|
|
2892
3104
|
if (node.name) {
|
|
@@ -2903,103 +3115,97 @@ export class Deparser {
|
|
|
2903
3115
|
}
|
|
2904
3116
|
return output.join(' ');
|
|
2905
3117
|
}
|
|
3118
|
+
formatIdentityColumnOptions(def, context) {
|
|
3119
|
+
const seqContext = context.spawn('AlterSeqStmt');
|
|
3120
|
+
return ListUtils.unwrapList(def).map(item => {
|
|
3121
|
+
const el = item.DefElem;
|
|
3122
|
+
if (!el)
|
|
3123
|
+
return this.visit(item, context);
|
|
3124
|
+
if (el.defname === 'generated') {
|
|
3125
|
+
const ival = el.arg?.Integer?.ival ?? 0;
|
|
3126
|
+
return ival === 97 ? 'SET GENERATED ALWAYS' : 'SET GENERATED BY DEFAULT';
|
|
3127
|
+
}
|
|
3128
|
+
if (el.defname === 'restart') {
|
|
3129
|
+
return el.arg ? `RESTART WITH ${this.visit(el.arg, context)}` : 'RESTART';
|
|
3130
|
+
}
|
|
3131
|
+
return `SET ${this.visit(item, seqContext)}`;
|
|
3132
|
+
}).join(' ');
|
|
3133
|
+
}
|
|
3134
|
+
// b_expr (used by DEFAULT) excludes IN/LIKE/BETWEEN and boolean operators.
|
|
3135
|
+
needsBExprParens(node) {
|
|
3136
|
+
const nodeType = this.getNodeType(node);
|
|
3137
|
+
if (nodeType === 'BoolExpr')
|
|
3138
|
+
return true;
|
|
3139
|
+
if (nodeType === 'A_Expr') {
|
|
3140
|
+
const kind = this.getNodeData(node).kind;
|
|
3141
|
+
return kind !== 'AEXPR_OP' && kind !== 'AEXPR_DISTINCT' && kind !== 'AEXPR_NOT_DISTINCT';
|
|
3142
|
+
}
|
|
3143
|
+
return false;
|
|
3144
|
+
}
|
|
2906
3145
|
formatWindowFrame(node, context) {
|
|
2907
|
-
if (!node.frameOptions)
|
|
3146
|
+
if (!node.frameOptions || !(node.frameOptions & FRAMEOPTION_NONDEFAULT))
|
|
2908
3147
|
return null;
|
|
2909
3148
|
const frameOptions = node.frameOptions;
|
|
2910
3149
|
const frameParts = [];
|
|
2911
|
-
if (frameOptions &
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
frameParts.push('GROUPS');
|
|
2920
|
-
}
|
|
3150
|
+
if (frameOptions & FRAMEOPTION_RANGE) {
|
|
3151
|
+
frameParts.push('RANGE');
|
|
3152
|
+
}
|
|
3153
|
+
else if (frameOptions & FRAMEOPTION_ROWS) {
|
|
3154
|
+
frameParts.push('ROWS');
|
|
3155
|
+
}
|
|
3156
|
+
else if (frameOptions & FRAMEOPTION_GROUPS) {
|
|
3157
|
+
frameParts.push('GROUPS');
|
|
2921
3158
|
}
|
|
2922
3159
|
if (frameParts.length === 0)
|
|
2923
3160
|
return null;
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
boundsParts.push('CURRENT ROW');
|
|
2928
|
-
boundsParts.push('AND UNBOUNDED FOLLOWING');
|
|
3161
|
+
let start = null;
|
|
3162
|
+
if (frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING) {
|
|
3163
|
+
start = 'UNBOUNDED PRECEDING';
|
|
2929
3164
|
}
|
|
2930
|
-
else if (frameOptions
|
|
2931
|
-
|
|
2932
|
-
boundsParts.push('AND CURRENT ROW');
|
|
3165
|
+
else if (frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING) {
|
|
3166
|
+
start = 'UNBOUNDED FOLLOWING';
|
|
2933
3167
|
}
|
|
2934
|
-
else if (frameOptions
|
|
2935
|
-
|
|
2936
|
-
boundsParts.push(`${this.visit(node.startOffset, context)} PRECEDING`);
|
|
2937
|
-
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
2938
|
-
}
|
|
3168
|
+
else if (frameOptions & FRAMEOPTION_START_CURRENT_ROW) {
|
|
3169
|
+
start = 'CURRENT ROW';
|
|
2939
3170
|
}
|
|
2940
|
-
else if (frameOptions
|
|
2941
|
-
|
|
2942
|
-
boundsParts.push('AND CURRENT ROW');
|
|
3171
|
+
else if (frameOptions & FRAMEOPTION_START_OFFSET_PRECEDING && node.startOffset) {
|
|
3172
|
+
start = `${this.visit(node.startOffset, context)} PRECEDING`;
|
|
2943
3173
|
}
|
|
2944
|
-
else if (frameOptions
|
|
2945
|
-
|
|
2946
|
-
if (node.endOffset) {
|
|
2947
|
-
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
2948
|
-
}
|
|
3174
|
+
else if (frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING && node.startOffset) {
|
|
3175
|
+
start = `${this.visit(node.startOffset, context)} FOLLOWING`;
|
|
2949
3176
|
}
|
|
2950
|
-
|
|
2951
|
-
|
|
3177
|
+
let end = null;
|
|
3178
|
+
if (frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING) {
|
|
3179
|
+
end = 'UNBOUNDED PRECEDING';
|
|
2952
3180
|
}
|
|
2953
|
-
else {
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
}
|
|
2969
|
-
else if (frameOptions & 0x20) { // FRAMEOPTION_START_CURRENT_ROW
|
|
2970
|
-
boundsParts.push('CURRENT ROW');
|
|
2971
|
-
}
|
|
2972
|
-
// Handle end bound - prioritize explicit offset values over bit flags
|
|
2973
|
-
if (node.endOffset) {
|
|
2974
|
-
if (boundsParts.length > 0) {
|
|
2975
|
-
if (frameOptions & 0x1000) { // FRAMEOPTION_END_VALUE_PRECEDING
|
|
2976
|
-
boundsParts.push(`AND ${this.visit(node.endOffset, context)} PRECEDING`);
|
|
2977
|
-
}
|
|
2978
|
-
else if (frameOptions & 0x2000) { // FRAMEOPTION_END_VALUE_FOLLOWING
|
|
2979
|
-
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
2980
|
-
}
|
|
2981
|
-
else {
|
|
2982
|
-
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
2983
|
-
}
|
|
2984
|
-
}
|
|
2985
|
-
}
|
|
2986
|
-
else if (frameOptions & 0x80) { // FRAMEOPTION_END_UNBOUNDED_FOLLOWING
|
|
2987
|
-
if (boundsParts.length > 0) {
|
|
2988
|
-
boundsParts.push('AND UNBOUNDED FOLLOWING');
|
|
2989
|
-
}
|
|
2990
|
-
}
|
|
2991
|
-
else if (frameOptions & 0x100) { // FRAMEOPTION_END_CURRENT_ROW
|
|
2992
|
-
if (boundsParts.length > 0) {
|
|
2993
|
-
boundsParts.push('AND CURRENT ROW');
|
|
2994
|
-
}
|
|
3181
|
+
else if (frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING) {
|
|
3182
|
+
end = 'UNBOUNDED FOLLOWING';
|
|
3183
|
+
}
|
|
3184
|
+
else if (frameOptions & FRAMEOPTION_END_CURRENT_ROW) {
|
|
3185
|
+
end = 'CURRENT ROW';
|
|
3186
|
+
}
|
|
3187
|
+
else if (frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING && node.endOffset) {
|
|
3188
|
+
end = `${this.visit(node.endOffset, context)} PRECEDING`;
|
|
3189
|
+
}
|
|
3190
|
+
else if (frameOptions & FRAMEOPTION_END_OFFSET_FOLLOWING && node.endOffset) {
|
|
3191
|
+
end = `${this.visit(node.endOffset, context)} FOLLOWING`;
|
|
3192
|
+
}
|
|
3193
|
+
if (start) {
|
|
3194
|
+
if (frameOptions & FRAMEOPTION_BETWEEN) {
|
|
3195
|
+
frameParts.push(`BETWEEN ${start} AND ${end ?? 'CURRENT ROW'}`);
|
|
2995
3196
|
}
|
|
2996
|
-
else
|
|
2997
|
-
|
|
3197
|
+
else {
|
|
3198
|
+
frameParts.push(start);
|
|
2998
3199
|
}
|
|
2999
3200
|
}
|
|
3000
|
-
if (
|
|
3001
|
-
frameParts.push('
|
|
3002
|
-
|
|
3201
|
+
if (frameOptions & FRAMEOPTION_EXCLUDE_CURRENT_ROW) {
|
|
3202
|
+
frameParts.push('EXCLUDE CURRENT ROW');
|
|
3203
|
+
}
|
|
3204
|
+
else if (frameOptions & FRAMEOPTION_EXCLUDE_GROUP) {
|
|
3205
|
+
frameParts.push('EXCLUDE GROUP');
|
|
3206
|
+
}
|
|
3207
|
+
else if (frameOptions & FRAMEOPTION_EXCLUDE_TIES) {
|
|
3208
|
+
frameParts.push('EXCLUDE TIES');
|
|
3003
3209
|
}
|
|
3004
3210
|
return frameParts.join(' ');
|
|
3005
3211
|
}
|
|
@@ -3077,8 +3283,35 @@ export class Deparser {
|
|
|
3077
3283
|
if (node.ctequery) {
|
|
3078
3284
|
output.push(context.parens(this.visit(node.ctequery, context)));
|
|
3079
3285
|
}
|
|
3286
|
+
if (node.search_clause) {
|
|
3287
|
+
const sc = node.search_clause;
|
|
3288
|
+
const cols = ListUtils.unwrapList(sc.search_col_list).map(c => this.visit(c, context));
|
|
3289
|
+
output.push('SEARCH', sc.search_breadth_first ? 'BREADTH' : 'DEPTH', 'FIRST BY');
|
|
3290
|
+
output.push(cols.join(', '));
|
|
3291
|
+
output.push('SET', QuoteUtils.quoteIdentifier(sc.search_seq_column));
|
|
3292
|
+
}
|
|
3293
|
+
if (node.cycle_clause) {
|
|
3294
|
+
const cc = node.cycle_clause;
|
|
3295
|
+
const cols = ListUtils.unwrapList(cc.cycle_col_list).map(c => this.visit(c, context));
|
|
3296
|
+
output.push('CYCLE', cols.join(', '));
|
|
3297
|
+
output.push('SET', QuoteUtils.quoteIdentifier(cc.cycle_mark_column));
|
|
3298
|
+
if (cc.cycle_mark_value && cc.cycle_mark_default) {
|
|
3299
|
+
output.push('TO', this.formatAexprConst(cc.cycle_mark_value, context));
|
|
3300
|
+
output.push('DEFAULT', this.formatAexprConst(cc.cycle_mark_default, context));
|
|
3301
|
+
}
|
|
3302
|
+
output.push('USING', QuoteUtils.quoteIdentifier(cc.cycle_path_column));
|
|
3303
|
+
}
|
|
3080
3304
|
return output.join(' ');
|
|
3081
3305
|
}
|
|
3306
|
+
// Renders a constant in the restricted AexprConst grammar (e.g. `point '(1,1)'`
|
|
3307
|
+
// rather than `CAST('(1,1)' AS point)`).
|
|
3308
|
+
formatAexprConst(node, context) {
|
|
3309
|
+
const cast = node.TypeCast;
|
|
3310
|
+
if (cast?.arg?.A_Const?.sval && cast.typeName) {
|
|
3311
|
+
return `${this.TypeName(cast.typeName, context)} ${this.visit(cast.arg, context)}`;
|
|
3312
|
+
}
|
|
3313
|
+
return this.visit(node, context);
|
|
3314
|
+
}
|
|
3082
3315
|
ParamRef(node, context) {
|
|
3083
3316
|
return `$${node.number}`;
|
|
3084
3317
|
}
|
|
@@ -3328,7 +3561,7 @@ export class Deparser {
|
|
|
3328
3561
|
output.push('IF NOT EXISTS');
|
|
3329
3562
|
}
|
|
3330
3563
|
if (node.idxname) {
|
|
3331
|
-
output.push(QuoteUtils.
|
|
3564
|
+
output.push(QuoteUtils.quoteIdentifier(node.idxname));
|
|
3332
3565
|
}
|
|
3333
3566
|
output.push('ON');
|
|
3334
3567
|
if (node.relation) {
|
|
@@ -3347,9 +3580,8 @@ export class Deparser {
|
|
|
3347
3580
|
output.push('INCLUDE');
|
|
3348
3581
|
output.push(context.parens(includeStrs.join(', ')));
|
|
3349
3582
|
}
|
|
3350
|
-
if (node.
|
|
3351
|
-
output.push('
|
|
3352
|
-
output.push(this.visit(node.whereClause, context));
|
|
3583
|
+
if (node.nulls_not_distinct) {
|
|
3584
|
+
output.push('NULLS NOT DISTINCT');
|
|
3353
3585
|
}
|
|
3354
3586
|
if (node.options && node.options.length > 0) {
|
|
3355
3587
|
const indexContext = context.spawn('IndexStmt');
|
|
@@ -3357,19 +3589,20 @@ export class Deparser {
|
|
|
3357
3589
|
output.push('WITH');
|
|
3358
3590
|
output.push(context.parens(optionStrs.join(', ')));
|
|
3359
3591
|
}
|
|
3360
|
-
if (node.nulls_not_distinct) {
|
|
3361
|
-
output.push('NULLS NOT DISTINCT');
|
|
3362
|
-
}
|
|
3363
3592
|
if (node.tableSpace) {
|
|
3364
3593
|
output.push('TABLESPACE');
|
|
3365
|
-
output.push(QuoteUtils.
|
|
3594
|
+
output.push(QuoteUtils.quoteIdentifier(node.tableSpace));
|
|
3366
3595
|
}
|
|
3367
|
-
|
|
3368
|
-
|
|
3596
|
+
if (node.whereClause) {
|
|
3597
|
+
output.push('WHERE');
|
|
3598
|
+
output.push(this.visit(node.whereClause, context));
|
|
3599
|
+
}
|
|
3600
|
+
return output.join(' ');
|
|
3601
|
+
}
|
|
3369
3602
|
IndexElem(node, context) {
|
|
3370
3603
|
const output = [];
|
|
3371
3604
|
if (node.name) {
|
|
3372
|
-
output.push(QuoteUtils.
|
|
3605
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
3373
3606
|
}
|
|
3374
3607
|
else if (node.expr) {
|
|
3375
3608
|
output.push(context.parens(this.visit(node.expr, context)));
|
|
@@ -3387,7 +3620,7 @@ export class Deparser {
|
|
|
3387
3620
|
const opclassOpts = ListUtils.unwrapList(node.opclassopts).map(opt => {
|
|
3388
3621
|
if (opt.DefElem && opt.DefElem.arg && this.getNodeType(opt.DefElem.arg) === 'String') {
|
|
3389
3622
|
const stringData = this.getNodeData(opt.DefElem.arg);
|
|
3390
|
-
return `${opt.DefElem.defname}
|
|
3623
|
+
return `${QuoteUtils.quoteIdentifierAfterDot(opt.DefElem.defname)}=${QuoteUtils.escape(stringData.sval)}`;
|
|
3391
3624
|
}
|
|
3392
3625
|
return this.visit(opt, context.spawn('IndexElem'));
|
|
3393
3626
|
});
|
|
@@ -3420,7 +3653,7 @@ export class Deparser {
|
|
|
3420
3653
|
PartitionElem(node, context) {
|
|
3421
3654
|
const output = [];
|
|
3422
3655
|
if (node.name) {
|
|
3423
|
-
output.push(QuoteUtils.
|
|
3656
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
3424
3657
|
}
|
|
3425
3658
|
else if (node.expr) {
|
|
3426
3659
|
output.push(context.parens(this.visit(node.expr, context)));
|
|
@@ -3438,12 +3671,12 @@ export class Deparser {
|
|
|
3438
3671
|
}
|
|
3439
3672
|
PartitionCmd(node, context) {
|
|
3440
3673
|
const output = [];
|
|
3674
|
+
if (node.name) {
|
|
3675
|
+
output.push(this.RangeVar(node.name, context));
|
|
3676
|
+
}
|
|
3441
3677
|
if (node.concurrent) {
|
|
3442
3678
|
output.push('CONCURRENTLY');
|
|
3443
3679
|
}
|
|
3444
|
-
if (node.name) {
|
|
3445
|
-
output.push(this.visit(node.name, context));
|
|
3446
|
-
}
|
|
3447
3680
|
if (node.bound) {
|
|
3448
3681
|
if (node.bound.strategy === 'l' && node.bound.listdatums) {
|
|
3449
3682
|
output.push('FOR VALUES IN');
|
|
@@ -3468,9 +3701,9 @@ export class Deparser {
|
|
|
3468
3701
|
output.push(`(${upperValues})`);
|
|
3469
3702
|
}
|
|
3470
3703
|
}
|
|
3471
|
-
else if (node.bound.strategy === 'h'
|
|
3704
|
+
else if (node.bound.strategy === 'h') {
|
|
3472
3705
|
output.push('FOR VALUES WITH');
|
|
3473
|
-
output.push(`(
|
|
3706
|
+
output.push(`(MODULUS ${node.bound.modulus ?? 0}, REMAINDER ${node.bound.remainder ?? 0})`);
|
|
3474
3707
|
}
|
|
3475
3708
|
else if (node.bound.is_default) {
|
|
3476
3709
|
output.push('DEFAULT');
|
|
@@ -3601,12 +3834,7 @@ export class Deparser {
|
|
|
3601
3834
|
if (context.isPretty()) {
|
|
3602
3835
|
// For complex JOIN conditions, format with proper indentation
|
|
3603
3836
|
if (qualsStr.includes('AND') || qualsStr.includes('OR') || qualsStr.length > 50) {
|
|
3604
|
-
|
|
3605
|
-
output.push(` ON ${qualsStr}`);
|
|
3606
|
-
}
|
|
3607
|
-
else {
|
|
3608
|
-
output.push(` ON${context.newline()}${context.indent(qualsStr)}`);
|
|
3609
|
-
}
|
|
3837
|
+
output.push(` ON${context.newline()}${context.indent(qualsStr)}`);
|
|
3610
3838
|
}
|
|
3611
3839
|
else {
|
|
3612
3840
|
output.push(` ON ${qualsStr}`);
|
|
@@ -3670,37 +3898,37 @@ export class Deparser {
|
|
|
3670
3898
|
case 'TRANS_STMT_SAVEPOINT':
|
|
3671
3899
|
output.push('SAVEPOINT');
|
|
3672
3900
|
if (node.savepoint_name) {
|
|
3673
|
-
output.push(QuoteUtils.
|
|
3901
|
+
output.push(QuoteUtils.quoteIdentifier(node.savepoint_name));
|
|
3674
3902
|
}
|
|
3675
3903
|
break;
|
|
3676
3904
|
case 'TRANS_STMT_RELEASE':
|
|
3677
3905
|
output.push('RELEASE SAVEPOINT');
|
|
3678
3906
|
if (node.savepoint_name) {
|
|
3679
|
-
output.push(QuoteUtils.
|
|
3907
|
+
output.push(QuoteUtils.quoteIdentifier(node.savepoint_name));
|
|
3680
3908
|
}
|
|
3681
3909
|
break;
|
|
3682
3910
|
case 'TRANS_STMT_ROLLBACK_TO':
|
|
3683
3911
|
output.push('ROLLBACK TO');
|
|
3684
3912
|
if (node.savepoint_name) {
|
|
3685
|
-
output.push(QuoteUtils.
|
|
3913
|
+
output.push(QuoteUtils.quoteIdentifier(node.savepoint_name));
|
|
3686
3914
|
}
|
|
3687
3915
|
break;
|
|
3688
3916
|
case 'TRANS_STMT_PREPARE':
|
|
3689
3917
|
output.push('PREPARE TRANSACTION');
|
|
3690
3918
|
if (node.gid) {
|
|
3691
|
-
output.push(
|
|
3919
|
+
output.push(QuoteUtils.escape(node.gid));
|
|
3692
3920
|
}
|
|
3693
3921
|
break;
|
|
3694
3922
|
case 'TRANS_STMT_COMMIT_PREPARED':
|
|
3695
3923
|
output.push('COMMIT PREPARED');
|
|
3696
3924
|
if (node.gid) {
|
|
3697
|
-
output.push(
|
|
3925
|
+
output.push(QuoteUtils.escape(node.gid));
|
|
3698
3926
|
}
|
|
3699
3927
|
break;
|
|
3700
3928
|
case 'TRANS_STMT_ROLLBACK_PREPARED':
|
|
3701
3929
|
output.push('ROLLBACK PREPARED');
|
|
3702
3930
|
if (node.gid) {
|
|
3703
|
-
output.push(
|
|
3931
|
+
output.push(QuoteUtils.escape(node.gid));
|
|
3704
3932
|
}
|
|
3705
3933
|
break;
|
|
3706
3934
|
default:
|
|
@@ -3767,28 +3995,39 @@ export class Deparser {
|
|
|
3767
3995
|
switch (node.kind) {
|
|
3768
3996
|
case 'VAR_SET_VALUE':
|
|
3769
3997
|
const localPrefix = node.is_local ? 'LOCAL ' : '';
|
|
3998
|
+
if (node.jumble_args && node.name === 'xmloption' && node.args) {
|
|
3999
|
+
const xmlValue = this.getNodeData(ListUtils.unwrapList(node.args)[0]);
|
|
4000
|
+
const xmlOption = (typeof xmlValue.sval === 'object' ? xmlValue.sval.sval : xmlValue.sval) || '';
|
|
4001
|
+
return `SET ${localPrefix}XML OPTION ${xmlOption.toUpperCase()}`;
|
|
4002
|
+
}
|
|
3770
4003
|
const args = node.args ? ListUtils.unwrapList(node.args).map(arg => {
|
|
3771
4004
|
const nodeData = this.getNodeData(arg);
|
|
3772
4005
|
if (nodeData.sval !== undefined) {
|
|
3773
4006
|
const svalValue = typeof nodeData.sval === 'object' ? nodeData.sval.sval : nodeData.sval;
|
|
3774
|
-
if (svalValue
|
|
3775
|
-
return
|
|
4007
|
+
if (!/^[a-z_][a-z0-9_]*$/.test(svalValue) || svalValue.includes(' ') || svalValue.includes('-') || /[A-Z]/.test(svalValue) || /^\d/.test(svalValue) || svalValue.includes('.') || svalValue.includes('$') || svalValue.toLowerCase() === 'all' || /^[+-]\d/.test(svalValue)) {
|
|
4008
|
+
return QuoteUtils.escape(svalValue);
|
|
3776
4009
|
}
|
|
3777
4010
|
return svalValue;
|
|
3778
4011
|
}
|
|
3779
4012
|
return this.visit(arg, context);
|
|
3780
4013
|
}).join(', ') : '';
|
|
4014
|
+
if (node.jumble_args && node.name === 'timezone') {
|
|
4015
|
+
return `SET ${localPrefix}TIME ZONE ${args}`;
|
|
4016
|
+
}
|
|
3781
4017
|
// Handle args - always include TO clause if args exist (even if empty string)
|
|
3782
|
-
const paramName =
|
|
4018
|
+
const paramName = QuoteUtils.quoteIdentifier(node.name);
|
|
3783
4019
|
if (!node.args || node.args.length === 0) {
|
|
3784
4020
|
return `SET ${localPrefix}${paramName}`;
|
|
3785
4021
|
}
|
|
3786
4022
|
return `SET ${localPrefix}${paramName} TO ${args}`;
|
|
3787
4023
|
case 'VAR_SET_DEFAULT':
|
|
3788
|
-
|
|
4024
|
+
if (node.jumble_args && node.name === 'timezone') {
|
|
4025
|
+
return `SET ${node.is_local ? 'LOCAL ' : ''}TIME ZONE DEFAULT`;
|
|
4026
|
+
}
|
|
4027
|
+
const defaultParamName = QuoteUtils.quoteIdentifier(node.name);
|
|
3789
4028
|
return `SET ${defaultParamName} TO DEFAULT`;
|
|
3790
4029
|
case 'VAR_SET_CURRENT':
|
|
3791
|
-
const currentParamName =
|
|
4030
|
+
const currentParamName = QuoteUtils.quoteIdentifier(node.name);
|
|
3792
4031
|
return `SET ${currentParamName} FROM CURRENT`;
|
|
3793
4032
|
case 'VAR_SET_MULTI':
|
|
3794
4033
|
if (node.name === 'TRANSACTION' || node.name === 'SESSION CHARACTERISTICS') {
|
|
@@ -3862,7 +4101,7 @@ export class Deparser {
|
|
|
3862
4101
|
return `SET ${assignments}`;
|
|
3863
4102
|
}
|
|
3864
4103
|
case 'VAR_RESET':
|
|
3865
|
-
const resetParamName =
|
|
4104
|
+
const resetParamName = QuoteUtils.quoteIdentifier(node.name);
|
|
3866
4105
|
return `RESET ${resetParamName}`;
|
|
3867
4106
|
case 'VAR_RESET_ALL':
|
|
3868
4107
|
return 'RESET ALL';
|
|
@@ -3882,7 +4121,7 @@ export class Deparser {
|
|
|
3882
4121
|
output.push('IF NOT EXISTS');
|
|
3883
4122
|
}
|
|
3884
4123
|
if (node.schemaname) {
|
|
3885
|
-
output.push(node.schemaname);
|
|
4124
|
+
output.push(QuoteUtils.quoteIdentifier(node.schemaname));
|
|
3886
4125
|
}
|
|
3887
4126
|
if (node.authrole) {
|
|
3888
4127
|
output.push('AUTHORIZATION');
|
|
@@ -4089,7 +4328,7 @@ export class Deparser {
|
|
|
4089
4328
|
if (objList && objList.List && objList.List.items) {
|
|
4090
4329
|
const items = objList.List.items.map((item) => {
|
|
4091
4330
|
if (item.String && item.String.sval) {
|
|
4092
|
-
return item.String.sval;
|
|
4331
|
+
return QuoteUtils.quoteIdentifier(item.String.sval);
|
|
4093
4332
|
}
|
|
4094
4333
|
return this.visit(item, context);
|
|
4095
4334
|
});
|
|
@@ -4131,7 +4370,7 @@ export class Deparser {
|
|
|
4131
4370
|
if (objList && objList.List && objList.List.items) {
|
|
4132
4371
|
const items = objList.List.items.map((item) => {
|
|
4133
4372
|
if (item.String && item.String.sval) {
|
|
4134
|
-
return QuoteUtils.
|
|
4373
|
+
return QuoteUtils.quoteIdentifier(item.String.sval);
|
|
4135
4374
|
}
|
|
4136
4375
|
return this.visit(item, context);
|
|
4137
4376
|
}).filter((name) => name && name.trim());
|
|
@@ -4165,13 +4404,13 @@ export class Deparser {
|
|
|
4165
4404
|
if (items.length === 2) {
|
|
4166
4405
|
const accessMethod = items[0];
|
|
4167
4406
|
const objectName = items[1];
|
|
4168
|
-
return `${QuoteUtils.
|
|
4407
|
+
return `${QuoteUtils.quoteIdentifier(objectName)} USING ${accessMethod}`;
|
|
4169
4408
|
}
|
|
4170
4409
|
else if (items.length === 3) {
|
|
4171
4410
|
const accessMethod = items[0];
|
|
4172
4411
|
const schemaName = items[1];
|
|
4173
4412
|
const objectName = items[2];
|
|
4174
|
-
return `${QuoteUtils.
|
|
4413
|
+
return `${QuoteUtils.quoteQualifiedIdentifier(schemaName, objectName)} USING ${accessMethod}`;
|
|
4175
4414
|
}
|
|
4176
4415
|
return items.join('.');
|
|
4177
4416
|
}
|
|
@@ -4214,7 +4453,7 @@ export class Deparser {
|
|
|
4214
4453
|
if (objList && objList.List && objList.List.items) {
|
|
4215
4454
|
const items = objList.List.items.map((item) => {
|
|
4216
4455
|
if (item.String && item.String.sval) {
|
|
4217
|
-
return QuoteUtils.
|
|
4456
|
+
return QuoteUtils.quoteIdentifier(item.String.sval);
|
|
4218
4457
|
}
|
|
4219
4458
|
return this.visit(item, context);
|
|
4220
4459
|
}).filter((name) => name && name.trim());
|
|
@@ -4262,7 +4501,7 @@ export class Deparser {
|
|
|
4262
4501
|
PLAssignStmt(node, context) {
|
|
4263
4502
|
const output = [];
|
|
4264
4503
|
if (node.name) {
|
|
4265
|
-
let nameWithIndirection = QuoteUtils.
|
|
4504
|
+
let nameWithIndirection = QuoteUtils.quoteIdentifier(node.name);
|
|
4266
4505
|
if (node.indirection && node.indirection.length > 0) {
|
|
4267
4506
|
const indirectionStr = node.indirection
|
|
4268
4507
|
.map((ind) => this.visit(ind, context))
|
|
@@ -4312,10 +4551,10 @@ export class Deparser {
|
|
|
4312
4551
|
output.push('PROGRAM');
|
|
4313
4552
|
}
|
|
4314
4553
|
if (node.filename) {
|
|
4315
|
-
output.push(
|
|
4554
|
+
output.push(QuoteUtils.escape(node.filename));
|
|
4316
4555
|
}
|
|
4317
4556
|
else {
|
|
4318
|
-
output.push('STDIN');
|
|
4557
|
+
output.push(node.is_from ? 'STDIN' : 'STDOUT');
|
|
4319
4558
|
}
|
|
4320
4559
|
if (node.options && node.options.length > 0) {
|
|
4321
4560
|
output.push('WITH');
|
|
@@ -4411,7 +4650,7 @@ export class Deparser {
|
|
|
4411
4650
|
const parts = [];
|
|
4412
4651
|
const indentedParts = [];
|
|
4413
4652
|
if (colDefData.colname) {
|
|
4414
|
-
parts.push(QuoteUtils.
|
|
4653
|
+
parts.push(QuoteUtils.quoteIdentifier(colDefData.colname));
|
|
4415
4654
|
}
|
|
4416
4655
|
if (colDefData.typeName) {
|
|
4417
4656
|
parts.push(this.TypeName(colDefData.typeName, context));
|
|
@@ -4469,7 +4708,7 @@ export class Deparser {
|
|
|
4469
4708
|
else {
|
|
4470
4709
|
const parts = [];
|
|
4471
4710
|
if (colDefData.colname) {
|
|
4472
|
-
parts.push(QuoteUtils.
|
|
4711
|
+
parts.push(QuoteUtils.quoteIdentifier(colDefData.colname));
|
|
4473
4712
|
}
|
|
4474
4713
|
if (colDefData.typeName) {
|
|
4475
4714
|
parts.push(this.TypeName(colDefData.typeName, context));
|
|
@@ -4523,7 +4762,7 @@ export class Deparser {
|
|
|
4523
4762
|
}
|
|
4524
4763
|
}
|
|
4525
4764
|
if (node.name) {
|
|
4526
|
-
output.push(QuoteUtils.
|
|
4765
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4527
4766
|
}
|
|
4528
4767
|
if (node.behavior === 'DROP_CASCADE') {
|
|
4529
4768
|
output.push('CASCADE');
|
|
@@ -4540,13 +4779,16 @@ export class Deparser {
|
|
|
4540
4779
|
output.push('ALTER COLUMN');
|
|
4541
4780
|
}
|
|
4542
4781
|
if (node.name) {
|
|
4543
|
-
output.push(QuoteUtils.
|
|
4782
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4544
4783
|
}
|
|
4545
4784
|
output.push('TYPE');
|
|
4546
4785
|
if (node.def) {
|
|
4547
4786
|
const nodeData = this.getNodeData(node.def);
|
|
4548
4787
|
if (nodeData && nodeData.typeName) {
|
|
4549
4788
|
output.push(this.TypeName(nodeData.typeName, context));
|
|
4789
|
+
if (nodeData.collClause) {
|
|
4790
|
+
output.push(this.CollateClause(nodeData.collClause, context));
|
|
4791
|
+
}
|
|
4550
4792
|
// Handle USING clause (stored in raw_default for ALTER COLUMN TYPE)
|
|
4551
4793
|
if (nodeData.raw_default) {
|
|
4552
4794
|
output.push('USING');
|
|
@@ -4567,7 +4809,7 @@ export class Deparser {
|
|
|
4567
4809
|
case 'AT_SetTableSpace':
|
|
4568
4810
|
output.push('SET TABLESPACE');
|
|
4569
4811
|
if (node.name) {
|
|
4570
|
-
output.push(QuoteUtils.
|
|
4812
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4571
4813
|
}
|
|
4572
4814
|
break;
|
|
4573
4815
|
case 'AT_AddConstraint':
|
|
@@ -4585,7 +4827,7 @@ export class Deparser {
|
|
|
4585
4827
|
output.push('DROP CONSTRAINT');
|
|
4586
4828
|
}
|
|
4587
4829
|
if (node.name) {
|
|
4588
|
-
output.push(QuoteUtils.
|
|
4830
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4589
4831
|
}
|
|
4590
4832
|
if (node.behavior === 'DROP_CASCADE') {
|
|
4591
4833
|
output.push('CASCADE');
|
|
@@ -4623,7 +4865,7 @@ export class Deparser {
|
|
|
4623
4865
|
case 'AT_ColumnDefault':
|
|
4624
4866
|
output.push('ALTER COLUMN');
|
|
4625
4867
|
if (node.name) {
|
|
4626
|
-
output.push(QuoteUtils.
|
|
4868
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4627
4869
|
}
|
|
4628
4870
|
if (node.def) {
|
|
4629
4871
|
output.push('SET DEFAULT');
|
|
@@ -4636,7 +4878,7 @@ export class Deparser {
|
|
|
4636
4878
|
case 'AT_SetStorage':
|
|
4637
4879
|
output.push('ALTER COLUMN');
|
|
4638
4880
|
if (node.name) {
|
|
4639
|
-
output.push(QuoteUtils.
|
|
4881
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4640
4882
|
}
|
|
4641
4883
|
output.push('SET STORAGE');
|
|
4642
4884
|
if (node.def) {
|
|
@@ -4647,7 +4889,7 @@ export class Deparser {
|
|
|
4647
4889
|
case 'AT_ClusterOn':
|
|
4648
4890
|
output.push('CLUSTER ON');
|
|
4649
4891
|
if (node.name) {
|
|
4650
|
-
output.push(QuoteUtils.
|
|
4892
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4651
4893
|
}
|
|
4652
4894
|
break;
|
|
4653
4895
|
case 'AT_DropCluster':
|
|
@@ -4674,21 +4916,21 @@ export class Deparser {
|
|
|
4674
4916
|
case 'AT_SetNotNull':
|
|
4675
4917
|
output.push('ALTER COLUMN');
|
|
4676
4918
|
if (node.name) {
|
|
4677
|
-
output.push(QuoteUtils.
|
|
4919
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4678
4920
|
}
|
|
4679
4921
|
output.push('SET NOT NULL');
|
|
4680
4922
|
break;
|
|
4681
4923
|
case 'AT_DropNotNull':
|
|
4682
4924
|
output.push('ALTER COLUMN');
|
|
4683
4925
|
if (node.name) {
|
|
4684
|
-
output.push(QuoteUtils.
|
|
4926
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4685
4927
|
}
|
|
4686
4928
|
output.push('DROP NOT NULL');
|
|
4687
4929
|
break;
|
|
4688
4930
|
case 'AT_SetStatistics':
|
|
4689
4931
|
output.push('ALTER COLUMN');
|
|
4690
4932
|
if (node.name) {
|
|
4691
|
-
output.push(QuoteUtils.
|
|
4933
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4692
4934
|
}
|
|
4693
4935
|
else if (node.num !== undefined && node.num !== null) {
|
|
4694
4936
|
output.push(node.num.toString());
|
|
@@ -4701,7 +4943,7 @@ export class Deparser {
|
|
|
4701
4943
|
case 'AT_SetOptions':
|
|
4702
4944
|
output.push('ALTER COLUMN');
|
|
4703
4945
|
if (node.name) {
|
|
4704
|
-
output.push(QuoteUtils.
|
|
4946
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4705
4947
|
}
|
|
4706
4948
|
output.push('SET');
|
|
4707
4949
|
if (node.def) {
|
|
@@ -4718,7 +4960,7 @@ export class Deparser {
|
|
|
4718
4960
|
case 'AT_ResetOptions':
|
|
4719
4961
|
output.push('ALTER COLUMN');
|
|
4720
4962
|
if (node.name) {
|
|
4721
|
-
output.push(QuoteUtils.
|
|
4963
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4722
4964
|
}
|
|
4723
4965
|
output.push('RESET');
|
|
4724
4966
|
if (node.def) {
|
|
@@ -4735,7 +4977,7 @@ export class Deparser {
|
|
|
4735
4977
|
case 'AT_SetCompression':
|
|
4736
4978
|
output.push('ALTER COLUMN');
|
|
4737
4979
|
if (node.name) {
|
|
4738
|
-
output.push(QuoteUtils.
|
|
4980
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4739
4981
|
}
|
|
4740
4982
|
output.push('SET COMPRESSION');
|
|
4741
4983
|
if (node.def) {
|
|
@@ -4745,31 +4987,31 @@ export class Deparser {
|
|
|
4745
4987
|
case 'AT_ValidateConstraint':
|
|
4746
4988
|
output.push('VALIDATE CONSTRAINT');
|
|
4747
4989
|
if (node.name) {
|
|
4748
|
-
output.push(QuoteUtils.
|
|
4990
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4749
4991
|
}
|
|
4750
4992
|
break;
|
|
4751
4993
|
case 'AT_EnableTrig':
|
|
4752
4994
|
output.push('ENABLE TRIGGER');
|
|
4753
4995
|
if (node.name) {
|
|
4754
|
-
output.push(QuoteUtils.
|
|
4996
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4755
4997
|
}
|
|
4756
4998
|
break;
|
|
4757
4999
|
case 'AT_EnableAlwaysTrig':
|
|
4758
5000
|
output.push('ENABLE ALWAYS TRIGGER');
|
|
4759
5001
|
if (node.name) {
|
|
4760
|
-
output.push(QuoteUtils.
|
|
5002
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4761
5003
|
}
|
|
4762
5004
|
break;
|
|
4763
5005
|
case 'AT_EnableReplicaTrig':
|
|
4764
5006
|
output.push('ENABLE REPLICA TRIGGER');
|
|
4765
5007
|
if (node.name) {
|
|
4766
|
-
output.push(QuoteUtils.
|
|
5008
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4767
5009
|
}
|
|
4768
5010
|
break;
|
|
4769
5011
|
case 'AT_DisableTrig':
|
|
4770
5012
|
output.push('DISABLE TRIGGER');
|
|
4771
5013
|
if (node.name) {
|
|
4772
|
-
output.push(QuoteUtils.
|
|
5014
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4773
5015
|
}
|
|
4774
5016
|
break;
|
|
4775
5017
|
case 'AT_EnableTrigAll':
|
|
@@ -4787,31 +5029,31 @@ export class Deparser {
|
|
|
4787
5029
|
case 'AT_EnableRule':
|
|
4788
5030
|
output.push('ENABLE RULE');
|
|
4789
5031
|
if (node.name) {
|
|
4790
|
-
output.push(QuoteUtils.
|
|
5032
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4791
5033
|
}
|
|
4792
5034
|
break;
|
|
4793
5035
|
case 'AT_EnableAlwaysRule':
|
|
4794
5036
|
output.push('ENABLE ALWAYS RULE');
|
|
4795
5037
|
if (node.name) {
|
|
4796
|
-
output.push(QuoteUtils.
|
|
5038
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4797
5039
|
}
|
|
4798
5040
|
break;
|
|
4799
5041
|
case 'AT_EnableReplicaRule':
|
|
4800
5042
|
output.push('ENABLE REPLICA RULE');
|
|
4801
5043
|
if (node.name) {
|
|
4802
|
-
output.push(QuoteUtils.
|
|
5044
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4803
5045
|
}
|
|
4804
5046
|
break;
|
|
4805
5047
|
case 'AT_DisableRule':
|
|
4806
5048
|
output.push('DISABLE RULE');
|
|
4807
5049
|
if (node.name) {
|
|
4808
|
-
output.push(QuoteUtils.
|
|
5050
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4809
5051
|
}
|
|
4810
5052
|
break;
|
|
4811
5053
|
case 'AT_SetAccessMethod':
|
|
4812
5054
|
output.push('SET ACCESS METHOD');
|
|
4813
5055
|
if (node.name) {
|
|
4814
|
-
output.push(QuoteUtils.
|
|
5056
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4815
5057
|
}
|
|
4816
5058
|
else {
|
|
4817
5059
|
// Handle DEFAULT access method case
|
|
@@ -4865,7 +5107,7 @@ export class Deparser {
|
|
|
4865
5107
|
case 'AT_CookedColumnDefault':
|
|
4866
5108
|
output.push('ALTER COLUMN');
|
|
4867
5109
|
if (node.name) {
|
|
4868
|
-
output.push(QuoteUtils.
|
|
5110
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4869
5111
|
}
|
|
4870
5112
|
if (node.def) {
|
|
4871
5113
|
output.push('SET DEFAULT');
|
|
@@ -4878,26 +5120,23 @@ export class Deparser {
|
|
|
4878
5120
|
case 'AT_SetExpression':
|
|
4879
5121
|
output.push('ALTER COLUMN');
|
|
4880
5122
|
if (node.name) {
|
|
4881
|
-
output.push(QuoteUtils.
|
|
5123
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4882
5124
|
}
|
|
4883
5125
|
output.push('SET EXPRESSION');
|
|
4884
5126
|
if (node.def) {
|
|
4885
|
-
output.push(
|
|
5127
|
+
output.push('AS');
|
|
5128
|
+
output.push(context.parens(this.visit(node.def, context)));
|
|
4886
5129
|
}
|
|
4887
5130
|
break;
|
|
4888
5131
|
case 'AT_DropExpression':
|
|
4889
5132
|
output.push('ALTER COLUMN');
|
|
4890
5133
|
if (node.name) {
|
|
4891
|
-
output.push(QuoteUtils.
|
|
5134
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4892
5135
|
}
|
|
4893
5136
|
output.push('DROP EXPRESSION');
|
|
4894
|
-
|
|
4895
|
-
|
|
4896
|
-
output.push('ALTER COLUMN');
|
|
4897
|
-
if (node.name) {
|
|
4898
|
-
output.push(QuoteUtils.quote(node.name));
|
|
5137
|
+
if (node.missing_ok) {
|
|
5138
|
+
output.push('IF EXISTS');
|
|
4899
5139
|
}
|
|
4900
|
-
output.push('SET NOT NULL');
|
|
4901
5140
|
break;
|
|
4902
5141
|
case 'AT_AddIndex':
|
|
4903
5142
|
output.push('ADD');
|
|
@@ -4924,23 +5163,28 @@ export class Deparser {
|
|
|
4924
5163
|
}
|
|
4925
5164
|
break;
|
|
4926
5165
|
case 'AT_AlterConstraint':
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
|
|
4934
|
-
|
|
4935
|
-
|
|
4936
|
-
|
|
5166
|
+
if (node.def && this.getNodeType(node.def) === 'ATAlterConstraint') {
|
|
5167
|
+
output.push(this.ATAlterConstraint(this.getNodeData(node.def), context));
|
|
5168
|
+
}
|
|
5169
|
+
else {
|
|
5170
|
+
output.push('ALTER CONSTRAINT');
|
|
5171
|
+
if (node.def && this.getNodeType(node.def) === 'Constraint') {
|
|
5172
|
+
const constraintData = this.getNodeData(node.def);
|
|
5173
|
+
if (constraintData.conname) {
|
|
5174
|
+
output.push(QuoteUtils.quoteIdentifier(constraintData.conname));
|
|
5175
|
+
if (constraintData.deferrable !== undefined) {
|
|
5176
|
+
output.push(constraintData.deferrable ? 'DEFERRABLE' : 'NOT DEFERRABLE');
|
|
5177
|
+
}
|
|
5178
|
+
if (constraintData.initdeferred !== undefined) {
|
|
5179
|
+
output.push(constraintData.initdeferred ? 'INITIALLY DEFERRED' : 'INITIALLY IMMEDIATE');
|
|
5180
|
+
}
|
|
4937
5181
|
}
|
|
4938
5182
|
}
|
|
4939
|
-
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
|
|
5183
|
+
else if (node.name) {
|
|
5184
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
5185
|
+
if (node.def) {
|
|
5186
|
+
output.push(this.visit(node.def, context));
|
|
5187
|
+
}
|
|
4944
5188
|
}
|
|
4945
5189
|
}
|
|
4946
5190
|
break;
|
|
@@ -4959,7 +5203,7 @@ export class Deparser {
|
|
|
4959
5203
|
case 'AT_AlterColumnGenericOptions':
|
|
4960
5204
|
output.push('ALTER COLUMN');
|
|
4961
5205
|
if (node.name) {
|
|
4962
|
-
output.push(QuoteUtils.
|
|
5206
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4963
5207
|
}
|
|
4964
5208
|
output.push('OPTIONS');
|
|
4965
5209
|
if (node.def) {
|
|
@@ -5013,7 +5257,7 @@ export class Deparser {
|
|
|
5013
5257
|
case 'AT_AddIdentity':
|
|
5014
5258
|
output.push('ALTER COLUMN');
|
|
5015
5259
|
if (node.name) {
|
|
5016
|
-
output.push(QuoteUtils.
|
|
5260
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
5017
5261
|
}
|
|
5018
5262
|
output.push('ADD');
|
|
5019
5263
|
if (node.def) {
|
|
@@ -5023,24 +5267,20 @@ export class Deparser {
|
|
|
5023
5267
|
case 'AT_SetIdentity':
|
|
5024
5268
|
output.push('ALTER COLUMN');
|
|
5025
5269
|
if (node.name) {
|
|
5026
|
-
output.push(QuoteUtils.
|
|
5270
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
5027
5271
|
}
|
|
5028
|
-
output.push('SET');
|
|
5029
5272
|
if (node.def) {
|
|
5030
|
-
output.push(this.
|
|
5273
|
+
output.push(this.formatIdentityColumnOptions(node.def, context));
|
|
5031
5274
|
}
|
|
5032
5275
|
break;
|
|
5033
5276
|
case 'AT_DropIdentity':
|
|
5034
5277
|
output.push('ALTER COLUMN');
|
|
5035
5278
|
if (node.name) {
|
|
5036
|
-
output.push(QuoteUtils.
|
|
5279
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
5037
5280
|
}
|
|
5038
5281
|
output.push('DROP IDENTITY');
|
|
5039
|
-
if (node.
|
|
5040
|
-
output.push('
|
|
5041
|
-
}
|
|
5042
|
-
else if (node.behavior === 'DROP_RESTRICT') {
|
|
5043
|
-
output.push('RESTRICT');
|
|
5282
|
+
if (node.missing_ok) {
|
|
5283
|
+
output.push('IF EXISTS');
|
|
5044
5284
|
}
|
|
5045
5285
|
break;
|
|
5046
5286
|
case 'AT_ReAddStatistics':
|
|
@@ -5067,7 +5307,8 @@ export class Deparser {
|
|
|
5067
5307
|
output.push('FUNCTION');
|
|
5068
5308
|
}
|
|
5069
5309
|
if (node.funcname && node.funcname.length > 0) {
|
|
5070
|
-
const
|
|
5310
|
+
const funcnameParts = node.funcname.map((name) => name.String?.sval || name.String?.str || '').filter((s) => s);
|
|
5311
|
+
const funcName = QuoteUtils.quoteDottedName(funcnameParts);
|
|
5071
5312
|
if (node.parameters && node.parameters.length > 0) {
|
|
5072
5313
|
const params = node.parameters
|
|
5073
5314
|
.filter((param) => {
|
|
@@ -5076,7 +5317,13 @@ export class Deparser {
|
|
|
5076
5317
|
})
|
|
5077
5318
|
.map((param) => this.visit(param, context));
|
|
5078
5319
|
if (params.length > 0) {
|
|
5079
|
-
|
|
5320
|
+
if (context.isPretty()) {
|
|
5321
|
+
const formattedParams = params.map(p => context.indent(p)).join(',' + context.newline());
|
|
5322
|
+
output.push(funcName + '(' + context.newline() + formattedParams + context.newline() + ')');
|
|
5323
|
+
}
|
|
5324
|
+
else {
|
|
5325
|
+
output.push(funcName + '(' + params.join(', ') + ')');
|
|
5326
|
+
}
|
|
5080
5327
|
}
|
|
5081
5328
|
else {
|
|
5082
5329
|
output.push(funcName + '()');
|
|
@@ -5091,15 +5338,21 @@ export class Deparser {
|
|
|
5091
5338
|
return paramData.mode === 'FUNC_PARAM_TABLE';
|
|
5092
5339
|
});
|
|
5093
5340
|
if (hasTableParams) {
|
|
5094
|
-
output.push('RETURNS TABLE (');
|
|
5095
5341
|
const tableParams = node.parameters
|
|
5096
5342
|
.filter((param) => {
|
|
5097
5343
|
const paramData = this.getNodeData(param);
|
|
5098
5344
|
return paramData.mode === 'FUNC_PARAM_TABLE';
|
|
5099
5345
|
})
|
|
5100
5346
|
.map((param) => this.visit(param, context));
|
|
5101
|
-
|
|
5102
|
-
|
|
5347
|
+
if (context.isPretty()) {
|
|
5348
|
+
const formattedTableParams = tableParams.map(p => context.indent(p)).join(',' + context.newline());
|
|
5349
|
+
output.push('RETURNS TABLE (' + context.newline() + formattedTableParams + context.newline() + ')');
|
|
5350
|
+
}
|
|
5351
|
+
else {
|
|
5352
|
+
output.push('RETURNS TABLE (');
|
|
5353
|
+
output.push(tableParams.join(', '));
|
|
5354
|
+
output.push(')');
|
|
5355
|
+
}
|
|
5103
5356
|
}
|
|
5104
5357
|
else if (node.returnType) {
|
|
5105
5358
|
output.push('RETURNS');
|
|
@@ -5121,6 +5374,7 @@ export class Deparser {
|
|
|
5121
5374
|
if (bodyType === 'List') {
|
|
5122
5375
|
const statements = ListUtils.unwrapList(node.sql_body);
|
|
5123
5376
|
if (statements.length === 0 || (statements.length === 1 && Object.keys(statements[0]).length === 0)) {
|
|
5377
|
+
// empty body: nothing to emit
|
|
5124
5378
|
}
|
|
5125
5379
|
else {
|
|
5126
5380
|
// Handle nested List structure in BEGIN ATOMIC blocks
|
|
@@ -5172,7 +5426,7 @@ export class Deparser {
|
|
|
5172
5426
|
}
|
|
5173
5427
|
}
|
|
5174
5428
|
if (node.name) {
|
|
5175
|
-
output.push(QuoteUtils.
|
|
5429
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
5176
5430
|
}
|
|
5177
5431
|
if (node.argType) {
|
|
5178
5432
|
output.push(this.TypeName(node.argType, context));
|
|
@@ -5244,7 +5498,7 @@ export class Deparser {
|
|
|
5244
5498
|
output.push('ROLE');
|
|
5245
5499
|
}
|
|
5246
5500
|
if (node.role) {
|
|
5247
|
-
const roleName =
|
|
5501
|
+
const roleName = QuoteUtils.quoteIdentifier(node.role);
|
|
5248
5502
|
output.push(roleName);
|
|
5249
5503
|
}
|
|
5250
5504
|
if (node.options) {
|
|
@@ -5268,25 +5522,28 @@ export class Deparser {
|
|
|
5268
5522
|
if (node.arg && this.getNodeType(node.arg) === 'List') {
|
|
5269
5523
|
const listData = this.getNodeData(node.arg);
|
|
5270
5524
|
const listItems = ListUtils.unwrapList(listData.items);
|
|
5525
|
+
const preservedName = this.preserveOperatorDefElemCase(node.defname);
|
|
5271
5526
|
if (listItems.length === 1 && listItems[0].String) {
|
|
5272
|
-
const preservedName = this.preserveOperatorDefElemCase(node.defname);
|
|
5273
5527
|
return `${preservedName} = ${listItems[0].String.sval}`;
|
|
5274
5528
|
}
|
|
5529
|
+
if (listItems.length > 1 && listItems.every((item) => item.String)) {
|
|
5530
|
+
return `${preservedName} = OPERATOR(${this.qualifiedOperatorName(listItems)})`;
|
|
5531
|
+
}
|
|
5275
5532
|
}
|
|
5276
5533
|
}
|
|
5277
5534
|
// Handle IndexElem opclassopts - MUST be first to preserve string types
|
|
5278
5535
|
if (context.parentNodeTypes.includes('IndexElem')) {
|
|
5279
5536
|
if (node.arg && this.getNodeType(node.arg) === 'String') {
|
|
5280
5537
|
const stringData = this.getNodeData(node.arg);
|
|
5281
|
-
return `${node.defname}
|
|
5538
|
+
return `${QuoteUtils.quoteIdentifierAfterDot(node.defname)}=${QuoteUtils.escape(stringData.sval)}`;
|
|
5282
5539
|
}
|
|
5283
|
-
return `${node.defname}=${this.visit(node.arg, context.spawn('DefElem'))}`;
|
|
5540
|
+
return `${QuoteUtils.quoteIdentifierAfterDot(node.defname)}=${this.formatOptionValue(node.arg, this.visit(node.arg, context.spawn('DefElem')))}`;
|
|
5284
5541
|
}
|
|
5285
5542
|
// Handle CREATE OPERATOR boolean flags - MUST be first to preserve case
|
|
5286
5543
|
if (context.parentNodeTypes.includes('DefineStmt') &&
|
|
5287
5544
|
['hashes', 'merges'].includes(node.defname.toLowerCase()) && !node.arg) {
|
|
5288
5545
|
if (node.defname !== node.defname.toLowerCase() && node.defname !== node.defname.toUpperCase()) {
|
|
5289
|
-
return
|
|
5546
|
+
return QuoteUtils.quoteIdentifier(node.defname);
|
|
5290
5547
|
}
|
|
5291
5548
|
return node.defname.charAt(0).toUpperCase() + node.defname.slice(1).toLowerCase();
|
|
5292
5549
|
}
|
|
@@ -5305,12 +5562,8 @@ export class Deparser {
|
|
|
5305
5562
|
const defElemContext = context.spawn('DefElem');
|
|
5306
5563
|
const argValue = this.visit(node.arg, defElemContext);
|
|
5307
5564
|
if (context.parentNodeTypes.includes('CreateFdwStmt') || context.parentNodeTypes.includes('AlterFdwStmt')) {
|
|
5308
|
-
const finalValue =
|
|
5309
|
-
|
|
5310
|
-
: argValue;
|
|
5311
|
-
const quotedDefname = node.defname.includes(' ') || node.defname.includes('-') || Deparser.needsQuotes(node.defname)
|
|
5312
|
-
? `"${node.defname}"`
|
|
5313
|
-
: node.defname;
|
|
5565
|
+
const finalValue = this.quoteDefElemArg(node.arg, argValue);
|
|
5566
|
+
const quotedDefname = QuoteUtils.quoteIdentifier(node.defname);
|
|
5314
5567
|
if (node.defaction === 'DEFELEM_ADD') {
|
|
5315
5568
|
return `ADD ${quotedDefname} ${finalValue}`;
|
|
5316
5569
|
}
|
|
@@ -5322,9 +5575,7 @@ export class Deparser {
|
|
|
5322
5575
|
}
|
|
5323
5576
|
return `${quotedDefname} ${finalValue}`;
|
|
5324
5577
|
}
|
|
5325
|
-
const quotedValue =
|
|
5326
|
-
? `'${argValue}'`
|
|
5327
|
-
: argValue;
|
|
5578
|
+
const quotedValue = this.quoteDefElemArg(node.arg, argValue);
|
|
5328
5579
|
if (node.defaction === 'DEFELEM_ADD') {
|
|
5329
5580
|
return `ADD ${node.defname} ${quotedValue}`;
|
|
5330
5581
|
}
|
|
@@ -5334,9 +5585,7 @@ export class Deparser {
|
|
|
5334
5585
|
else if (node.defaction === 'DEFELEM_SET') {
|
|
5335
5586
|
return `SET ${node.defname} ${quotedValue}`;
|
|
5336
5587
|
}
|
|
5337
|
-
const quotedDefname =
|
|
5338
|
-
? `"${node.defname}"`
|
|
5339
|
-
: node.defname;
|
|
5588
|
+
const quotedDefname = QuoteUtils.quoteIdentifier(node.defname);
|
|
5340
5589
|
return `${quotedDefname} ${quotedValue}`;
|
|
5341
5590
|
}
|
|
5342
5591
|
else if (node.defaction === 'DEFELEM_DROP') {
|
|
@@ -5358,9 +5607,7 @@ export class Deparser {
|
|
|
5358
5607
|
}
|
|
5359
5608
|
const defElemContext = context.spawn('DefElem');
|
|
5360
5609
|
const argValue = this.visit(node.arg, defElemContext);
|
|
5361
|
-
const quotedValue =
|
|
5362
|
-
? `'${argValue}'`
|
|
5363
|
-
: argValue;
|
|
5610
|
+
const quotedValue = this.quoteDefElemArg(node.arg, argValue);
|
|
5364
5611
|
return `PASSWORD ${quotedValue}`;
|
|
5365
5612
|
}
|
|
5366
5613
|
}
|
|
@@ -5383,6 +5630,9 @@ export class Deparser {
|
|
|
5383
5630
|
if (listItems.length === 1 && listItems[0].String) {
|
|
5384
5631
|
return `${node.defname} = ${listItems[0].String.sval}`;
|
|
5385
5632
|
}
|
|
5633
|
+
if (listItems.length > 1 && listItems.every((item) => item.String)) {
|
|
5634
|
+
return `${node.defname} = OPERATOR(${this.qualifiedOperatorName(listItems)})`;
|
|
5635
|
+
}
|
|
5386
5636
|
}
|
|
5387
5637
|
}
|
|
5388
5638
|
if (context.parentNodeTypes.includes('CreatedbStmt') || context.parentNodeTypes.includes('DropdbStmt')) {
|
|
@@ -5396,9 +5646,7 @@ export class Deparser {
|
|
|
5396
5646
|
const quotedValue = typeof argValue === 'string'
|
|
5397
5647
|
? QuoteUtils.escape(argValue)
|
|
5398
5648
|
: argValue;
|
|
5399
|
-
const quotedDefname =
|
|
5400
|
-
? `"${node.defname}"`
|
|
5401
|
-
: node.defname;
|
|
5649
|
+
const quotedDefname = QuoteUtils.quoteIdentifier(node.defname);
|
|
5402
5650
|
return `${quotedDefname} ${quotedValue}`;
|
|
5403
5651
|
}
|
|
5404
5652
|
if (context.parentNodeTypes.includes('CreateRoleStmt') || context.parentNodeTypes.includes('AlterRoleStmt')) {
|
|
@@ -5427,9 +5675,7 @@ export class Deparser {
|
|
|
5427
5675
|
}
|
|
5428
5676
|
}
|
|
5429
5677
|
if (node.defname === 'validUntil') {
|
|
5430
|
-
const quotedValue =
|
|
5431
|
-
? `'${argValue}'`
|
|
5432
|
-
: argValue;
|
|
5678
|
+
const quotedValue = this.quoteDefElemArg(node.arg, argValue);
|
|
5433
5679
|
return `VALID UNTIL ${quotedValue}`;
|
|
5434
5680
|
}
|
|
5435
5681
|
if (node.defname === 'adminmembers') {
|
|
@@ -5468,15 +5714,15 @@ export class Deparser {
|
|
|
5468
5714
|
if (node.arg && this.getNodeType(node.arg) === 'List') {
|
|
5469
5715
|
const listData = this.getNodeData(node.arg);
|
|
5470
5716
|
const listItems = ListUtils.unwrapList(listData.items);
|
|
5717
|
+
if (listItems.length === 1 && listItems[0].String?.sval === 'none') {
|
|
5718
|
+
return 'OWNED BY NONE';
|
|
5719
|
+
}
|
|
5471
5720
|
const parts = listItems.map(item => {
|
|
5472
5721
|
const itemData = this.getNodeData(item);
|
|
5473
5722
|
if (this.getNodeType(item) === 'String') {
|
|
5474
5723
|
// Check if this identifier needs quotes to preserve case
|
|
5475
5724
|
const value = itemData.sval;
|
|
5476
|
-
|
|
5477
|
-
return `"${value}"`;
|
|
5478
|
-
}
|
|
5479
|
-
return value;
|
|
5725
|
+
return QuoteUtils.quoteIdentifier(value);
|
|
5480
5726
|
}
|
|
5481
5727
|
return this.visit(item, context);
|
|
5482
5728
|
});
|
|
@@ -5607,11 +5853,13 @@ export class Deparser {
|
|
|
5607
5853
|
if (context.parentNodeTypes.includes('CreateExtensionStmt') || context.parentNodeTypes.includes('AlterExtensionStmt') || context.parentNodeTypes.includes('CreateFdwStmt') || context.parentNodeTypes.includes('AlterFdwStmt')) {
|
|
5608
5854
|
// AlterExtensionStmt specific cases
|
|
5609
5855
|
if (context.parentNodeTypes.includes('AlterExtensionStmt')) {
|
|
5610
|
-
if (node.defname === '
|
|
5611
|
-
|
|
5856
|
+
if (node.defname === 'new_version') {
|
|
5857
|
+
// argValue is unquoted due to DefElem context, so we need to quote it
|
|
5858
|
+
const quotedValue = this.quoteDefElemArg(node.arg, argValue);
|
|
5859
|
+
return `TO ${quotedValue}`;
|
|
5612
5860
|
}
|
|
5613
5861
|
if (node.defname === 'schema') {
|
|
5614
|
-
return `SCHEMA ${argValue}`;
|
|
5862
|
+
return `SET SCHEMA ${argValue}`;
|
|
5615
5863
|
}
|
|
5616
5864
|
}
|
|
5617
5865
|
// CreateFdwStmt specific cases
|
|
@@ -5628,28 +5876,37 @@ export class Deparser {
|
|
|
5628
5876
|
if (node.defname === 'cascade') {
|
|
5629
5877
|
return argValue === 'true' ? 'CASCADE' : '';
|
|
5630
5878
|
}
|
|
5879
|
+
if (node.defname === 'new_version') {
|
|
5880
|
+
return `VERSION ${this.quoteDefElemArg(node.arg, argValue)}`;
|
|
5881
|
+
}
|
|
5882
|
+
if (node.defname === 'schema' && node.arg && this.getNodeType(node.arg) === 'String') {
|
|
5883
|
+
return `SCHEMA ${QuoteUtils.quoteIdentifier(this.getNodeData(node.arg).sval)}`;
|
|
5884
|
+
}
|
|
5631
5885
|
return `${node.defname.toUpperCase()} ${argValue}`;
|
|
5632
5886
|
}
|
|
5633
5887
|
// Handle IndexStmt WITH clause options - no quotes, compact formatting
|
|
5634
5888
|
if (context.parentNodeTypes.includes('IndexStmt')) {
|
|
5635
|
-
return `${node.defname}=${argValue}`;
|
|
5889
|
+
return `${QuoteUtils.quoteIdentifierAfterDot(node.defname)}=${this.formatOptionValue(node.arg, argValue)}`;
|
|
5636
5890
|
}
|
|
5637
5891
|
// Handle IndexElem opclassopts - preserve string values as strings
|
|
5638
5892
|
if (context.parentNodeTypes.includes('IndexElem')) {
|
|
5639
5893
|
if (node.arg && this.getNodeType(node.arg) === 'String') {
|
|
5640
5894
|
const stringData = this.getNodeData(node.arg);
|
|
5641
|
-
return `${node.defname}
|
|
5895
|
+
return `${QuoteUtils.quoteIdentifierAfterDot(node.defname)}=${QuoteUtils.escape(stringData.sval)}`;
|
|
5642
5896
|
}
|
|
5643
|
-
return `${node.defname}=${argValue}`;
|
|
5897
|
+
return `${QuoteUtils.quoteIdentifierAfterDot(node.defname)}=${this.formatOptionValue(node.arg, argValue)}`;
|
|
5644
5898
|
}
|
|
5645
5899
|
// Handle CreateStmt table options - no quotes, compact formatting
|
|
5646
5900
|
if (context.parentNodeTypes.includes('CreateStmt')) {
|
|
5901
|
+
const relOptName = node.defnamespace
|
|
5902
|
+
? `${QuoteUtils.quoteIdentifier(node.defnamespace)}.${QuoteUtils.quoteIdentifier(node.defname)}`
|
|
5903
|
+
: QuoteUtils.quoteIdentifier(node.defname);
|
|
5647
5904
|
// For numeric values, use the raw value without quotes
|
|
5648
5905
|
if (node.arg && this.getNodeType(node.arg) === 'Integer') {
|
|
5649
5906
|
const integerData = this.getNodeData(node.arg);
|
|
5650
|
-
return `${
|
|
5907
|
+
return `${relOptName}=${formatInteger(integerData.ival)}`;
|
|
5651
5908
|
}
|
|
5652
|
-
return `${
|
|
5909
|
+
return `${relOptName}=${this.formatOptionValue(node.arg, argValue)}`;
|
|
5653
5910
|
}
|
|
5654
5911
|
// Handle CreateEventTrigStmt WHEN clause - use IN syntax for List arguments
|
|
5655
5912
|
if (context.parentNodeTypes.includes('CreateEventTrigStmt')) {
|
|
@@ -5659,7 +5916,7 @@ export class Deparser {
|
|
|
5659
5916
|
const values = listItems.map(item => {
|
|
5660
5917
|
if (this.getNodeType(item) === 'String') {
|
|
5661
5918
|
const stringData = this.getNodeData(item);
|
|
5662
|
-
return
|
|
5919
|
+
return QuoteUtils.escape(stringData.sval || '');
|
|
5663
5920
|
}
|
|
5664
5921
|
return this.visit(item, context);
|
|
5665
5922
|
});
|
|
@@ -5674,7 +5931,7 @@ export class Deparser {
|
|
|
5674
5931
|
if (node.arg && this.getNodeType(node.arg) === 'TypeName') {
|
|
5675
5932
|
return `${optionName} = ${argValue}`;
|
|
5676
5933
|
}
|
|
5677
|
-
return `${optionName} = ${argValue}`;
|
|
5934
|
+
return `${optionName} = ${this.formatOptionValue(node.arg, argValue)}`;
|
|
5678
5935
|
}
|
|
5679
5936
|
// Handle ViewStmt WITH options - don't quote numeric values
|
|
5680
5937
|
if (context.parentNodeTypes.includes('ViewStmt')) {
|
|
@@ -5688,15 +5945,27 @@ export class Deparser {
|
|
|
5688
5945
|
}
|
|
5689
5946
|
// Handle CopyStmt WITH clause options - uppercase format without quotes
|
|
5690
5947
|
if (context.parentNodeTypes.includes('CopyStmt')) {
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
return
|
|
5948
|
+
const optName = node.defname.toUpperCase();
|
|
5949
|
+
if (!node.arg) {
|
|
5950
|
+
return optName;
|
|
5694
5951
|
}
|
|
5695
|
-
|
|
5696
|
-
if (node.arg) {
|
|
5697
|
-
return
|
|
5952
|
+
const copyArgType = this.getNodeType(node.arg);
|
|
5953
|
+
if (copyArgType === 'Boolean' && this.getNodeData(node.arg).boolval !== false) {
|
|
5954
|
+
return optName;
|
|
5698
5955
|
}
|
|
5699
|
-
|
|
5956
|
+
if (copyArgType === 'List') {
|
|
5957
|
+
const items = ListUtils.unwrapList(this.getNodeData(node.arg).items)
|
|
5958
|
+
.map(item => this.visit(item, context));
|
|
5959
|
+
return `${optName} (${items.join(', ')})`;
|
|
5960
|
+
}
|
|
5961
|
+
if (copyArgType === 'String') {
|
|
5962
|
+
const sval = this.getNodeData(node.arg).sval;
|
|
5963
|
+
if (node.defname === 'format') {
|
|
5964
|
+
return `${optName} ${sval}`;
|
|
5965
|
+
}
|
|
5966
|
+
return `${optName} ${QuoteUtils.escape(sval)}`;
|
|
5967
|
+
}
|
|
5968
|
+
return `${optName} ${argValue}`;
|
|
5700
5969
|
}
|
|
5701
5970
|
// Handle CREATE OPERATOR and CREATE TYPE context
|
|
5702
5971
|
if (context.parentNodeTypes.includes('DefineStmt')) {
|
|
@@ -5720,13 +5989,13 @@ export class Deparser {
|
|
|
5720
5989
|
// Handle boolean flags (no arguments) - preserve quoted case
|
|
5721
5990
|
if (['hashes', 'merges'].includes(node.defname.toLowerCase())) {
|
|
5722
5991
|
if (node.defname !== node.defname.toLowerCase() && node.defname !== node.defname.toUpperCase()) {
|
|
5723
|
-
return
|
|
5992
|
+
return QuoteUtils.quoteIdentifier(node.defname);
|
|
5724
5993
|
}
|
|
5725
5994
|
return preservedName.toUpperCase();
|
|
5726
5995
|
}
|
|
5727
5996
|
// Handle CREATE AGGREGATE quoted identifiers - preserve quotes when needed
|
|
5728
|
-
|
|
5729
|
-
|
|
5997
|
+
const quotedDefname = QuoteUtils.quoteIdentifier(node.defname);
|
|
5998
|
+
if (quotedDefname !== node.defname) {
|
|
5730
5999
|
if (node.arg) {
|
|
5731
6000
|
if (this.getNodeType(node.arg) === 'String') {
|
|
5732
6001
|
const stringData = this.getNodeData(node.arg);
|
|
@@ -5735,7 +6004,7 @@ export class Deparser {
|
|
|
5735
6004
|
return `${quotedDefname} = ${stringData.sval}`;
|
|
5736
6005
|
}
|
|
5737
6006
|
// Regular string literals get single quotes
|
|
5738
|
-
return `${quotedDefname} =
|
|
6007
|
+
return `${quotedDefname} = ${QuoteUtils.escape(stringData.sval)}`;
|
|
5739
6008
|
}
|
|
5740
6009
|
return `${quotedDefname} = ${argValue}`;
|
|
5741
6010
|
}
|
|
@@ -5756,7 +6025,7 @@ export class Deparser {
|
|
|
5756
6025
|
return `${node.defname} = ${stringData.sval}`;
|
|
5757
6026
|
}
|
|
5758
6027
|
// Regular string literals get single quotes
|
|
5759
|
-
return `${node.defname} =
|
|
6028
|
+
return `${node.defname} = ${QuoteUtils.escape(stringData.sval)}`;
|
|
5760
6029
|
}
|
|
5761
6030
|
if (node.arg && this.getNodeType(node.arg) === 'Boolean') {
|
|
5762
6031
|
const boolData = this.getNodeData(node.arg);
|
|
@@ -5777,6 +6046,10 @@ export class Deparser {
|
|
|
5777
6046
|
return `${node.defname} = ${argValue}`;
|
|
5778
6047
|
}
|
|
5779
6048
|
}
|
|
6049
|
+
const argType = this.getNodeType(node.arg);
|
|
6050
|
+
if (argType === 'TypeName' || argType === 'Integer' || argType === 'Float' || argType === 'Boolean') {
|
|
6051
|
+
return `${node.defname} = ${argValue}`;
|
|
6052
|
+
}
|
|
5780
6053
|
const quotedValue = typeof argValue === 'string'
|
|
5781
6054
|
? QuoteUtils.escape(argValue)
|
|
5782
6055
|
: argValue;
|
|
@@ -5786,7 +6059,7 @@ export class Deparser {
|
|
|
5786
6059
|
if (context.parentNodeTypes.includes('DefineStmt') && !node.arg) {
|
|
5787
6060
|
// Check if the original defname appears to be quoted (mixed case that's not all upper/lower)
|
|
5788
6061
|
if (node.defname !== node.defname.toLowerCase() && node.defname !== node.defname.toUpperCase()) {
|
|
5789
|
-
return
|
|
6062
|
+
return QuoteUtils.quoteIdentifier(node.defname);
|
|
5790
6063
|
}
|
|
5791
6064
|
}
|
|
5792
6065
|
return node.defname.toUpperCase();
|
|
@@ -5802,7 +6075,7 @@ export class Deparser {
|
|
|
5802
6075
|
}
|
|
5803
6076
|
if (node.location) {
|
|
5804
6077
|
output.push('LOCATION');
|
|
5805
|
-
output.push(
|
|
6078
|
+
output.push(QuoteUtils.escape(node.location));
|
|
5806
6079
|
}
|
|
5807
6080
|
if (node.options && node.options.length > 0) {
|
|
5808
6081
|
output.push('WITH');
|
|
@@ -5866,6 +6139,7 @@ export class Deparser {
|
|
|
5866
6139
|
if (node.extname) {
|
|
5867
6140
|
output.push(this.quoteIfNeeded(node.extname));
|
|
5868
6141
|
}
|
|
6142
|
+
output.push('UPDATE');
|
|
5869
6143
|
if (node.options && node.options.length > 0) {
|
|
5870
6144
|
const extContext = context.spawn('AlterExtensionStmt');
|
|
5871
6145
|
const options = ListUtils.unwrapList(node.options)
|
|
@@ -5875,6 +6149,34 @@ export class Deparser {
|
|
|
5875
6149
|
}
|
|
5876
6150
|
return output.join(' ');
|
|
5877
6151
|
}
|
|
6152
|
+
AlterExtensionContentsStmt(node, context) {
|
|
6153
|
+
const output = ['ALTER', 'EXTENSION'];
|
|
6154
|
+
if (node.extname) {
|
|
6155
|
+
output.push(this.quoteIfNeeded(node.extname));
|
|
6156
|
+
}
|
|
6157
|
+
// Handle action: 1 = ADD, -1 = DROP
|
|
6158
|
+
if (node.action === 1) {
|
|
6159
|
+
output.push('ADD');
|
|
6160
|
+
}
|
|
6161
|
+
else if (node.action === -1) {
|
|
6162
|
+
output.push('DROP');
|
|
6163
|
+
}
|
|
6164
|
+
// Add object type keyword
|
|
6165
|
+
if (node.objtype) {
|
|
6166
|
+
try {
|
|
6167
|
+
output.push(this.getObjectTypeKeyword(node.objtype));
|
|
6168
|
+
}
|
|
6169
|
+
catch {
|
|
6170
|
+
// Fallback to the raw objtype if not supported
|
|
6171
|
+
output.push(node.objtype.toString());
|
|
6172
|
+
}
|
|
6173
|
+
}
|
|
6174
|
+
// Add the object itself
|
|
6175
|
+
if (node.object) {
|
|
6176
|
+
output.push(this.visit(node.object, context));
|
|
6177
|
+
}
|
|
6178
|
+
return output.join(' ');
|
|
6179
|
+
}
|
|
5878
6180
|
CreateFdwStmt(node, context) {
|
|
5879
6181
|
const output = ['CREATE', 'FOREIGN', 'DATA', 'WRAPPER'];
|
|
5880
6182
|
if (node.fdwname) {
|
|
@@ -5942,7 +6244,7 @@ export class Deparser {
|
|
|
5942
6244
|
case 'REPLICA_IDENTITY_INDEX':
|
|
5943
6245
|
output.push('USING', 'INDEX');
|
|
5944
6246
|
if (node.name) {
|
|
5945
|
-
output.push(QuoteUtils.
|
|
6247
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
5946
6248
|
}
|
|
5947
6249
|
break;
|
|
5948
6250
|
default:
|
|
@@ -6001,7 +6303,7 @@ export class Deparser {
|
|
|
6001
6303
|
output.push('IF', 'EXISTS');
|
|
6002
6304
|
}
|
|
6003
6305
|
if (node.name) {
|
|
6004
|
-
output.push(QuoteUtils.
|
|
6306
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
6005
6307
|
}
|
|
6006
6308
|
if (node.behavior === 'DROP_CASCADE') {
|
|
6007
6309
|
output.push('CASCADE');
|
|
@@ -6010,7 +6312,7 @@ export class Deparser {
|
|
|
6010
6312
|
case 'AT_ValidateConstraint':
|
|
6011
6313
|
output.push('VALIDATE', 'CONSTRAINT');
|
|
6012
6314
|
if (node.name) {
|
|
6013
|
-
output.push(QuoteUtils.
|
|
6315
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
6014
6316
|
}
|
|
6015
6317
|
break;
|
|
6016
6318
|
case 'C':
|
|
@@ -6027,7 +6329,7 @@ export class Deparser {
|
|
|
6027
6329
|
output.push('IF', 'EXISTS');
|
|
6028
6330
|
}
|
|
6029
6331
|
if (node.name) {
|
|
6030
|
-
output.push(QuoteUtils.
|
|
6332
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
6031
6333
|
}
|
|
6032
6334
|
if (node.behavior === 'DROP_CASCADE') {
|
|
6033
6335
|
output.push('CASCADE');
|
|
@@ -6036,7 +6338,7 @@ export class Deparser {
|
|
|
6036
6338
|
case 'V':
|
|
6037
6339
|
output.push('VALIDATE', 'CONSTRAINT');
|
|
6038
6340
|
if (node.name) {
|
|
6039
|
-
output.push(QuoteUtils.
|
|
6341
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
6040
6342
|
}
|
|
6041
6343
|
break;
|
|
6042
6344
|
case 'O':
|
|
@@ -6107,7 +6409,7 @@ export class Deparser {
|
|
|
6107
6409
|
}
|
|
6108
6410
|
if (node.payload !== null && node.payload !== undefined) {
|
|
6109
6411
|
output.push(',');
|
|
6110
|
-
output.push(
|
|
6412
|
+
output.push(QuoteUtils.escape(node.payload));
|
|
6111
6413
|
}
|
|
6112
6414
|
return output.join(' ');
|
|
6113
6415
|
}
|
|
@@ -6135,7 +6437,7 @@ export class Deparser {
|
|
|
6135
6437
|
if (!node.filename) {
|
|
6136
6438
|
throw new Error('LoadStmt requires filename');
|
|
6137
6439
|
}
|
|
6138
|
-
return `LOAD
|
|
6440
|
+
return `LOAD ${QuoteUtils.escape(node.filename)}`;
|
|
6139
6441
|
}
|
|
6140
6442
|
DiscardStmt(node, context) {
|
|
6141
6443
|
switch (node.target) {
|
|
@@ -6151,6 +6453,13 @@ export class Deparser {
|
|
|
6151
6453
|
throw new Error(`Unsupported DiscardStmt target: ${node.target}`);
|
|
6152
6454
|
}
|
|
6153
6455
|
}
|
|
6456
|
+
/** `schema.op` for an operator name list: schema parts quoted, the operator symbol as is. */
|
|
6457
|
+
qualifiedOperatorName(objname) {
|
|
6458
|
+
const names = ListUtils.unwrapList(objname ?? []).map((n) => (n.String ? n.String.sval : 'unknown'));
|
|
6459
|
+
if (names.length === 0)
|
|
6460
|
+
return 'unknown';
|
|
6461
|
+
return [...names.slice(0, -1).map((n) => QuoteUtils.quoteIdentifier(n)), names[names.length - 1]].join('.');
|
|
6462
|
+
}
|
|
6154
6463
|
CommentStmt(node, context) {
|
|
6155
6464
|
const output = ['COMMENT ON'];
|
|
6156
6465
|
if (node.objtype) {
|
|
@@ -6182,6 +6491,9 @@ export class Deparser {
|
|
|
6182
6491
|
case 'OBJECT_TABCONSTRAINT':
|
|
6183
6492
|
output.push('CONSTRAINT');
|
|
6184
6493
|
break;
|
|
6494
|
+
case 'OBJECT_DOMCONSTRAINT':
|
|
6495
|
+
output.push('CONSTRAINT');
|
|
6496
|
+
break;
|
|
6185
6497
|
case 'OBJECT_TRIGGER':
|
|
6186
6498
|
output.push('TRIGGER');
|
|
6187
6499
|
break;
|
|
@@ -6258,23 +6570,30 @@ export class Deparser {
|
|
|
6258
6570
|
output.push(objectParts.join('.'));
|
|
6259
6571
|
}
|
|
6260
6572
|
}
|
|
6261
|
-
else if (node.objtype === '
|
|
6573
|
+
else if (node.objtype === 'OBJECT_DOMCONSTRAINT') {
|
|
6262
6574
|
if (objectParts.length === 2) {
|
|
6263
|
-
const [
|
|
6264
|
-
output.push(
|
|
6575
|
+
const [domain, constraint] = objectParts;
|
|
6576
|
+
output.push(constraint, 'ON DOMAIN', domain);
|
|
6577
|
+
}
|
|
6578
|
+
else {
|
|
6579
|
+
output.push(objectParts.join('.'));
|
|
6580
|
+
}
|
|
6581
|
+
}
|
|
6582
|
+
else if (node.objtype === 'OBJECT_TRIGGER') {
|
|
6583
|
+
if (objectParts.length >= 2) {
|
|
6584
|
+
output.push(objectParts[objectParts.length - 1]);
|
|
6265
6585
|
output.push('ON');
|
|
6266
|
-
output.push(
|
|
6586
|
+
output.push(objectParts.slice(0, -1).join('.'));
|
|
6267
6587
|
}
|
|
6268
6588
|
else {
|
|
6269
6589
|
output.push(objectParts.join('.'));
|
|
6270
6590
|
}
|
|
6271
6591
|
}
|
|
6272
6592
|
else if (node.objtype === 'OBJECT_RULE') {
|
|
6273
|
-
if (objectParts.length
|
|
6274
|
-
|
|
6275
|
-
output.push(rule);
|
|
6593
|
+
if (objectParts.length >= 2) {
|
|
6594
|
+
output.push(objectParts[objectParts.length - 1]);
|
|
6276
6595
|
output.push('ON');
|
|
6277
|
-
output.push(
|
|
6596
|
+
output.push(objectParts.slice(0, -1).join('.'));
|
|
6278
6597
|
}
|
|
6279
6598
|
else {
|
|
6280
6599
|
output.push(objectParts.join('.'));
|
|
@@ -6285,8 +6604,7 @@ export class Deparser {
|
|
|
6285
6604
|
// For operators, we need to handle ObjectWithArgs structure
|
|
6286
6605
|
if (node.object && node.object.ObjectWithArgs) {
|
|
6287
6606
|
const objWithArgs = node.object.ObjectWithArgs;
|
|
6288
|
-
let operatorName =
|
|
6289
|
-
? objWithArgs.objname[0].String.sval : 'unknown';
|
|
6607
|
+
let operatorName = this.qualifiedOperatorName(objWithArgs.objname);
|
|
6290
6608
|
if (operatorName.startsWith('"') && operatorName.endsWith('"')) {
|
|
6291
6609
|
operatorName = operatorName.slice(1, -1);
|
|
6292
6610
|
}
|
|
@@ -6324,7 +6642,13 @@ export class Deparser {
|
|
|
6324
6642
|
}
|
|
6325
6643
|
else if (node.objtype === 'OBJECT_POLICY') {
|
|
6326
6644
|
// Handle POLICY syntax: COMMENT ON POLICY policy_name ON table_name IS 'comment'
|
|
6327
|
-
if (objectParts.length ===
|
|
6645
|
+
if (objectParts.length === 3) {
|
|
6646
|
+
const [schema, table, policy] = objectParts;
|
|
6647
|
+
output.push(policy);
|
|
6648
|
+
output.push('ON');
|
|
6649
|
+
output.push(`${schema}.${table}`);
|
|
6650
|
+
}
|
|
6651
|
+
else if (objectParts.length === 2) {
|
|
6328
6652
|
const [table, policy] = objectParts;
|
|
6329
6653
|
output.push(policy);
|
|
6330
6654
|
output.push('ON');
|
|
@@ -6347,6 +6671,9 @@ export class Deparser {
|
|
|
6347
6671
|
output.push(objectParts.join('.'));
|
|
6348
6672
|
}
|
|
6349
6673
|
}
|
|
6674
|
+
else if (node.objtype === 'OBJECT_CAST' && objectParts.length === 2) {
|
|
6675
|
+
output.push(`(${objectParts[0]} AS ${objectParts[1]})`);
|
|
6676
|
+
}
|
|
6350
6677
|
else {
|
|
6351
6678
|
output.push(objectParts.join('.'));
|
|
6352
6679
|
}
|
|
@@ -6355,8 +6682,7 @@ export class Deparser {
|
|
|
6355
6682
|
else if (node.objtype === 'OBJECT_OPERATOR' && node.object && node.object.ObjectWithArgs) {
|
|
6356
6683
|
// Handle direct ObjectWithArgs for OPERATOR syntax: COMMENT ON OPERATOR -(NONE, integer) IS 'comment'
|
|
6357
6684
|
const objWithArgs = node.object.ObjectWithArgs;
|
|
6358
|
-
let operatorName =
|
|
6359
|
-
? objWithArgs.objname[0].String.sval : 'unknown';
|
|
6685
|
+
let operatorName = this.qualifiedOperatorName(objWithArgs.objname);
|
|
6360
6686
|
// Remove quotes from operator name if present
|
|
6361
6687
|
if (operatorName.startsWith('"') && operatorName.endsWith('"')) {
|
|
6362
6688
|
operatorName = operatorName.slice(1, -1);
|
|
@@ -6425,7 +6751,7 @@ export class Deparser {
|
|
|
6425
6751
|
const output = [];
|
|
6426
6752
|
const initialParts = ['CREATE', 'POLICY'];
|
|
6427
6753
|
if (node.policy_name) {
|
|
6428
|
-
initialParts.push(QuoteUtils.
|
|
6754
|
+
initialParts.push(QuoteUtils.quoteIdentifier(node.policy_name));
|
|
6429
6755
|
}
|
|
6430
6756
|
output.push(initialParts.join(' '));
|
|
6431
6757
|
// Add ON clause on new line in pretty mode
|
|
@@ -6502,7 +6828,7 @@ export class Deparser {
|
|
|
6502
6828
|
AlterPolicyStmt(node, context) {
|
|
6503
6829
|
const output = ['ALTER', 'POLICY'];
|
|
6504
6830
|
if (node.policy_name) {
|
|
6505
|
-
output.push(QuoteUtils.
|
|
6831
|
+
output.push(QuoteUtils.quoteIdentifier(node.policy_name));
|
|
6506
6832
|
}
|
|
6507
6833
|
if (node.table) {
|
|
6508
6834
|
output.push('ON');
|
|
@@ -6538,7 +6864,7 @@ export class Deparser {
|
|
|
6538
6864
|
}
|
|
6539
6865
|
output.push('SERVER');
|
|
6540
6866
|
if (node.servername) {
|
|
6541
|
-
output.push(
|
|
6867
|
+
output.push(QuoteUtils.quoteIdentifier(node.servername));
|
|
6542
6868
|
}
|
|
6543
6869
|
if (node.options && node.options.length > 0) {
|
|
6544
6870
|
output.push('OPTIONS');
|
|
@@ -6586,10 +6912,10 @@ export class Deparser {
|
|
|
6586
6912
|
CreatePublicationStmt(node, context) {
|
|
6587
6913
|
const output = ['CREATE', 'PUBLICATION'];
|
|
6588
6914
|
if (node.pubname) {
|
|
6589
|
-
output.push(
|
|
6915
|
+
output.push(QuoteUtils.quoteIdentifier(node.pubname));
|
|
6590
6916
|
}
|
|
6591
6917
|
if (node.pubobjects && node.pubobjects.length > 0) {
|
|
6592
|
-
output.push('FOR'
|
|
6918
|
+
output.push('FOR');
|
|
6593
6919
|
const tables = ListUtils.unwrapList(node.pubobjects).map(table => this.visit(table, context));
|
|
6594
6920
|
output.push(tables.join(', '));
|
|
6595
6921
|
}
|
|
@@ -6606,11 +6932,11 @@ export class Deparser {
|
|
|
6606
6932
|
CreateSubscriptionStmt(node, context) {
|
|
6607
6933
|
const output = ['CREATE', 'SUBSCRIPTION'];
|
|
6608
6934
|
if (node.subname) {
|
|
6609
|
-
output.push(
|
|
6935
|
+
output.push(QuoteUtils.quoteIdentifier(node.subname));
|
|
6610
6936
|
}
|
|
6611
6937
|
output.push('CONNECTION');
|
|
6612
6938
|
if (node.conninfo) {
|
|
6613
|
-
output.push(
|
|
6939
|
+
output.push(QuoteUtils.escape(node.conninfo));
|
|
6614
6940
|
}
|
|
6615
6941
|
output.push('PUBLICATION');
|
|
6616
6942
|
if (node.publication && node.publication.length > 0) {
|
|
@@ -6627,10 +6953,11 @@ export class Deparser {
|
|
|
6627
6953
|
AlterPublicationStmt(node, context) {
|
|
6628
6954
|
const output = ['ALTER', 'PUBLICATION'];
|
|
6629
6955
|
if (node.pubname) {
|
|
6630
|
-
output.push(
|
|
6956
|
+
output.push(QuoteUtils.quoteIdentifier(node.pubname));
|
|
6631
6957
|
}
|
|
6632
|
-
|
|
6633
|
-
|
|
6958
|
+
const hasObjects = node.pubobjects && node.pubobjects.length > 0;
|
|
6959
|
+
if (hasObjects) {
|
|
6960
|
+
switch (node.action || 'AP_AddObjects') {
|
|
6634
6961
|
case 'AP_AddObjects':
|
|
6635
6962
|
output.push('ADD');
|
|
6636
6963
|
break;
|
|
@@ -6643,17 +6970,11 @@ export class Deparser {
|
|
|
6643
6970
|
default:
|
|
6644
6971
|
throw new Error(`Unsupported AlterPublicationStmt action: ${node.action}`);
|
|
6645
6972
|
}
|
|
6646
|
-
}
|
|
6647
|
-
if (node.for_all_tables) {
|
|
6648
|
-
output.push('FOR ALL TABLES');
|
|
6649
|
-
}
|
|
6650
|
-
else if (node.pubobjects && node.pubobjects.length > 0) {
|
|
6651
|
-
output.push('FOR TABLE');
|
|
6652
6973
|
const objects = ListUtils.unwrapList(node.pubobjects).map(obj => this.visit(obj, context));
|
|
6653
6974
|
output.push(objects.join(', '));
|
|
6654
6975
|
}
|
|
6655
|
-
if (node.options && node.options.length > 0) {
|
|
6656
|
-
output.push('
|
|
6976
|
+
else if (node.options && node.options.length > 0) {
|
|
6977
|
+
output.push('SET');
|
|
6657
6978
|
const options = ListUtils.unwrapList(node.options).map(opt => this.visit(opt, context));
|
|
6658
6979
|
output.push(`(${options.join(', ')})`);
|
|
6659
6980
|
}
|
|
@@ -6662,44 +6983,69 @@ export class Deparser {
|
|
|
6662
6983
|
AlterSubscriptionStmt(node, context) {
|
|
6663
6984
|
const output = ['ALTER', 'SUBSCRIPTION'];
|
|
6664
6985
|
if (node.subname) {
|
|
6665
|
-
output.push(
|
|
6666
|
-
}
|
|
6667
|
-
|
|
6668
|
-
|
|
6986
|
+
output.push(QuoteUtils.quoteIdentifier(node.subname));
|
|
6987
|
+
}
|
|
6988
|
+
const options = node.options && node.options.length > 0
|
|
6989
|
+
? `(${ListUtils.unwrapList(node.options).map(opt => this.visit(opt, context)).join(', ')})`
|
|
6990
|
+
: null;
|
|
6991
|
+
const publications = node.publication && node.publication.length > 0
|
|
6992
|
+
? ListUtils.unwrapList(node.publication).map(pub => this.visit(pub, context)).join(', ')
|
|
6993
|
+
: null;
|
|
6994
|
+
{
|
|
6995
|
+
switch (node.kind || 'ALTER_SUBSCRIPTION_OPTIONS') {
|
|
6669
6996
|
case 'ALTER_SUBSCRIPTION_OPTIONS':
|
|
6670
6997
|
output.push('SET');
|
|
6998
|
+
if (options)
|
|
6999
|
+
output.push(options);
|
|
6671
7000
|
break;
|
|
6672
7001
|
case 'ALTER_SUBSCRIPTION_CONNECTION':
|
|
6673
7002
|
output.push('CONNECTION');
|
|
6674
7003
|
if (node.conninfo) {
|
|
6675
|
-
output.push(
|
|
7004
|
+
output.push(QuoteUtils.escape(node.conninfo));
|
|
6676
7005
|
}
|
|
6677
7006
|
break;
|
|
6678
7007
|
case 'ALTER_SUBSCRIPTION_SET_PUBLICATION':
|
|
6679
7008
|
output.push('SET PUBLICATION');
|
|
6680
|
-
if (
|
|
6681
|
-
|
|
6682
|
-
|
|
6683
|
-
|
|
7009
|
+
if (publications)
|
|
7010
|
+
output.push(publications);
|
|
7011
|
+
if (options)
|
|
7012
|
+
output.push('WITH', options);
|
|
7013
|
+
break;
|
|
7014
|
+
case 'ALTER_SUBSCRIPTION_ADD_PUBLICATION':
|
|
7015
|
+
output.push('ADD PUBLICATION');
|
|
7016
|
+
if (publications)
|
|
7017
|
+
output.push(publications);
|
|
7018
|
+
if (options)
|
|
7019
|
+
output.push('WITH', options);
|
|
7020
|
+
break;
|
|
7021
|
+
case 'ALTER_SUBSCRIPTION_DROP_PUBLICATION':
|
|
7022
|
+
output.push('DROP PUBLICATION');
|
|
7023
|
+
if (publications)
|
|
7024
|
+
output.push(publications);
|
|
7025
|
+
if (options)
|
|
7026
|
+
output.push('WITH', options);
|
|
6684
7027
|
break;
|
|
6685
7028
|
case 'ALTER_SUBSCRIPTION_REFRESH':
|
|
6686
7029
|
output.push('REFRESH PUBLICATION');
|
|
7030
|
+
if (options)
|
|
7031
|
+
output.push('WITH', options);
|
|
6687
7032
|
break;
|
|
6688
|
-
case 'ALTER_SUBSCRIPTION_ENABLED':
|
|
6689
|
-
|
|
7033
|
+
case 'ALTER_SUBSCRIPTION_ENABLED': {
|
|
7034
|
+
const enabled = ListUtils.unwrapList(node.options).find(opt => opt.DefElem?.defname === 'enabled');
|
|
7035
|
+
const arg = enabled?.DefElem?.arg;
|
|
7036
|
+
const isEnabled = arg?.Boolean ? arg.Boolean.boolval !== false : true;
|
|
7037
|
+
output.push(isEnabled ? 'ENABLE' : 'DISABLE');
|
|
6690
7038
|
break;
|
|
7039
|
+
}
|
|
6691
7040
|
case 'ALTER_SUBSCRIPTION_SKIP':
|
|
6692
7041
|
output.push('SKIP');
|
|
7042
|
+
if (options)
|
|
7043
|
+
output.push(options);
|
|
6693
7044
|
break;
|
|
6694
7045
|
default:
|
|
6695
7046
|
throw new Error(`Unsupported AlterSubscriptionStmt kind: ${node.kind}`);
|
|
6696
7047
|
}
|
|
6697
7048
|
}
|
|
6698
|
-
if (node.options && node.options.length > 0) {
|
|
6699
|
-
output.push('WITH');
|
|
6700
|
-
const options = ListUtils.unwrapList(node.options).map(opt => this.visit(opt, context));
|
|
6701
|
-
output.push(`(${options.join(', ')})`);
|
|
6702
|
-
}
|
|
6703
7049
|
return output.join(' ');
|
|
6704
7050
|
}
|
|
6705
7051
|
DropSubscriptionStmt(node, context) {
|
|
@@ -6708,7 +7054,7 @@ export class Deparser {
|
|
|
6708
7054
|
output.push('IF EXISTS');
|
|
6709
7055
|
}
|
|
6710
7056
|
if (node.subname) {
|
|
6711
|
-
output.push(
|
|
7057
|
+
output.push(QuoteUtils.quoteIdentifier(node.subname));
|
|
6712
7058
|
}
|
|
6713
7059
|
if (node.behavior) {
|
|
6714
7060
|
switch (node.behavior) {
|
|
@@ -6953,7 +7299,7 @@ export class Deparser {
|
|
|
6953
7299
|
ClosePortalStmt(node, context) {
|
|
6954
7300
|
const output = ['CLOSE'];
|
|
6955
7301
|
if (node.portalname) {
|
|
6956
|
-
output.push(QuoteUtils.
|
|
7302
|
+
output.push(QuoteUtils.quoteIdentifier(node.portalname));
|
|
6957
7303
|
}
|
|
6958
7304
|
else {
|
|
6959
7305
|
output.push('ALL');
|
|
@@ -7011,7 +7357,7 @@ export class Deparser {
|
|
|
7011
7357
|
output.push('ALL');
|
|
7012
7358
|
}
|
|
7013
7359
|
if (node.portalname) {
|
|
7014
|
-
output.push(QuoteUtils.
|
|
7360
|
+
output.push(QuoteUtils.quoteIdentifier(node.portalname));
|
|
7015
7361
|
}
|
|
7016
7362
|
return output.join(' ');
|
|
7017
7363
|
}
|
|
@@ -7081,7 +7427,7 @@ export class Deparser {
|
|
|
7081
7427
|
AlterFdwStmt(node, context) {
|
|
7082
7428
|
const output = ['ALTER', 'FOREIGN', 'DATA', 'WRAPPER'];
|
|
7083
7429
|
if (node.fdwname) {
|
|
7084
|
-
output.push(QuoteUtils.
|
|
7430
|
+
output.push(QuoteUtils.quoteIdentifier(node.fdwname));
|
|
7085
7431
|
}
|
|
7086
7432
|
if (node.func_options && node.func_options.length > 0) {
|
|
7087
7433
|
const fdwContext = context.spawn('AlterFdwStmt');
|
|
@@ -7102,7 +7448,7 @@ export class Deparser {
|
|
|
7102
7448
|
output.push('IF', 'NOT', 'EXISTS');
|
|
7103
7449
|
}
|
|
7104
7450
|
if (node.servername) {
|
|
7105
|
-
output.push(QuoteUtils.
|
|
7451
|
+
output.push(QuoteUtils.quoteIdentifier(node.servername));
|
|
7106
7452
|
}
|
|
7107
7453
|
if (node.servertype) {
|
|
7108
7454
|
output.push('TYPE', QuoteUtils.escape(node.servertype));
|
|
@@ -7111,7 +7457,7 @@ export class Deparser {
|
|
|
7111
7457
|
output.push('VERSION', QuoteUtils.escape(node.version));
|
|
7112
7458
|
}
|
|
7113
7459
|
if (node.fdwname) {
|
|
7114
|
-
output.push('FOREIGN', 'DATA', 'WRAPPER', QuoteUtils.
|
|
7460
|
+
output.push('FOREIGN', 'DATA', 'WRAPPER', QuoteUtils.quoteIdentifier(node.fdwname));
|
|
7115
7461
|
}
|
|
7116
7462
|
if (node.options && node.options.length > 0) {
|
|
7117
7463
|
output.push('OPTIONS');
|
|
@@ -7126,7 +7472,7 @@ export class Deparser {
|
|
|
7126
7472
|
AlterForeignServerStmt(node, context) {
|
|
7127
7473
|
const output = ['ALTER', 'SERVER'];
|
|
7128
7474
|
if (node.servername) {
|
|
7129
|
-
output.push(QuoteUtils.
|
|
7475
|
+
output.push(QuoteUtils.quoteIdentifier(node.servername));
|
|
7130
7476
|
}
|
|
7131
7477
|
if (node.version) {
|
|
7132
7478
|
output.push('VERSION', QuoteUtils.escape(node.version));
|
|
@@ -7151,7 +7497,7 @@ export class Deparser {
|
|
|
7151
7497
|
}
|
|
7152
7498
|
output.push('SERVER');
|
|
7153
7499
|
if (node.servername) {
|
|
7154
|
-
output.push(QuoteUtils.
|
|
7500
|
+
output.push(QuoteUtils.quoteIdentifier(node.servername));
|
|
7155
7501
|
}
|
|
7156
7502
|
if (node.options && node.options.length > 0) {
|
|
7157
7503
|
output.push('OPTIONS');
|
|
@@ -7175,14 +7521,14 @@ export class Deparser {
|
|
|
7175
7521
|
}
|
|
7176
7522
|
output.push('SERVER');
|
|
7177
7523
|
if (node.servername) {
|
|
7178
|
-
output.push(QuoteUtils.
|
|
7524
|
+
output.push(QuoteUtils.quoteIdentifier(node.servername));
|
|
7179
7525
|
}
|
|
7180
7526
|
return output.join(' ');
|
|
7181
7527
|
}
|
|
7182
7528
|
ImportForeignSchemaStmt(node, context) {
|
|
7183
7529
|
const output = ['IMPORT', 'FOREIGN', 'SCHEMA'];
|
|
7184
7530
|
if (node.remote_schema) {
|
|
7185
|
-
output.push(QuoteUtils.
|
|
7531
|
+
output.push(QuoteUtils.quoteIdentifier(node.remote_schema));
|
|
7186
7532
|
}
|
|
7187
7533
|
if (node.list_type) {
|
|
7188
7534
|
switch (node.list_type) {
|
|
@@ -7208,11 +7554,11 @@ export class Deparser {
|
|
|
7208
7554
|
}
|
|
7209
7555
|
output.push('FROM', 'SERVER');
|
|
7210
7556
|
if (node.server_name) {
|
|
7211
|
-
output.push(QuoteUtils.
|
|
7557
|
+
output.push(QuoteUtils.quoteIdentifier(node.server_name));
|
|
7212
7558
|
}
|
|
7213
7559
|
output.push('INTO');
|
|
7214
7560
|
if (node.local_schema) {
|
|
7215
|
-
output.push(QuoteUtils.
|
|
7561
|
+
output.push(QuoteUtils.quoteIdentifier(node.local_schema));
|
|
7216
7562
|
}
|
|
7217
7563
|
if (node.options && node.options.length > 0) {
|
|
7218
7564
|
const importSchemaContext = context.spawn('ImportForeignSchemaStmt');
|
|
@@ -7226,7 +7572,7 @@ export class Deparser {
|
|
|
7226
7572
|
if (node.relation) {
|
|
7227
7573
|
output.push(this.RangeVar(node.relation, context));
|
|
7228
7574
|
if (node.indexname) {
|
|
7229
|
-
output.push('USING',
|
|
7575
|
+
output.push('USING', QuoteUtils.quoteIdentifier(node.indexname));
|
|
7230
7576
|
}
|
|
7231
7577
|
}
|
|
7232
7578
|
if (node.params && node.params.length > 0) {
|
|
@@ -7290,7 +7636,7 @@ export class Deparser {
|
|
|
7290
7636
|
output.push(this.RangeVar(node.relation, context));
|
|
7291
7637
|
}
|
|
7292
7638
|
if (node.name) {
|
|
7293
|
-
output.push(
|
|
7639
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
7294
7640
|
}
|
|
7295
7641
|
return output.join(' ');
|
|
7296
7642
|
}
|
|
@@ -7330,7 +7676,7 @@ export class Deparser {
|
|
|
7330
7676
|
if (!node.dbname) {
|
|
7331
7677
|
throw new Error('CreatedbStmt requires dbname');
|
|
7332
7678
|
}
|
|
7333
|
-
output.push(
|
|
7679
|
+
output.push(QuoteUtils.quoteIdentifier(node.dbname));
|
|
7334
7680
|
if (node.options && node.options.length > 0) {
|
|
7335
7681
|
const options = ListUtils.unwrapList(node.options)
|
|
7336
7682
|
.map(option => this.visit(option, context))
|
|
@@ -7347,7 +7693,7 @@ export class Deparser {
|
|
|
7347
7693
|
if (!node.dbname) {
|
|
7348
7694
|
throw new Error('DropdbStmt requires dbname');
|
|
7349
7695
|
}
|
|
7350
|
-
output.push(
|
|
7696
|
+
output.push(QuoteUtils.quoteIdentifier(node.dbname));
|
|
7351
7697
|
if (node.options && node.options.length > 0) {
|
|
7352
7698
|
const options = ListUtils.unwrapList(node.options)
|
|
7353
7699
|
.map(option => this.visit(option, context))
|
|
@@ -7445,7 +7791,7 @@ export class Deparser {
|
|
|
7445
7791
|
case 'OBJECT_POLICY':
|
|
7446
7792
|
output.push('POLICY');
|
|
7447
7793
|
if (node.subname) {
|
|
7448
|
-
output.push(QuoteUtils.
|
|
7794
|
+
output.push(QuoteUtils.quoteIdentifier(node.subname));
|
|
7449
7795
|
}
|
|
7450
7796
|
break;
|
|
7451
7797
|
case 'OBJECT_PUBLICATION':
|
|
@@ -7503,7 +7849,7 @@ export class Deparser {
|
|
|
7503
7849
|
}
|
|
7504
7850
|
// Handle OBJECT_RULE special case: rule_name ON table_name format
|
|
7505
7851
|
if (node.renameType === 'OBJECT_RULE' && node.subname && node.relation) {
|
|
7506
|
-
output.push(QuoteUtils.
|
|
7852
|
+
output.push(QuoteUtils.quoteIdentifier(node.subname));
|
|
7507
7853
|
output.push('ON');
|
|
7508
7854
|
output.push(this.RangeVar(node.relation, context));
|
|
7509
7855
|
}
|
|
@@ -7522,12 +7868,21 @@ export class Deparser {
|
|
|
7522
7868
|
if (items.length === 2) {
|
|
7523
7869
|
const accessMethod = items[0].String?.sval || '';
|
|
7524
7870
|
const objectName = items[1].String?.sval || '';
|
|
7525
|
-
output.push(`${QuoteUtils.
|
|
7871
|
+
output.push(`${QuoteUtils.quoteIdentifier(objectName)} USING ${accessMethod}`);
|
|
7526
7872
|
}
|
|
7527
7873
|
else {
|
|
7528
7874
|
output.push(this.visit(node.object, context));
|
|
7529
7875
|
}
|
|
7530
7876
|
}
|
|
7877
|
+
else if ((node.renameType === 'OBJECT_TYPE' || node.renameType === 'OBJECT_DOMAIN') && node.object.List) {
|
|
7878
|
+
// Qualified type names - join List parts with dots
|
|
7879
|
+
const items = ListUtils.unwrapList(node.object);
|
|
7880
|
+
const parts = items
|
|
7881
|
+
.map((item) => item.String?.sval)
|
|
7882
|
+
.filter((s) => typeof s === 'string')
|
|
7883
|
+
.map((s) => this.quoteIfNeeded(s));
|
|
7884
|
+
output.push(parts.join('.'));
|
|
7885
|
+
}
|
|
7531
7886
|
else if (node.renameType === 'OBJECT_SCHEMA' && node.object.List) {
|
|
7532
7887
|
// Handle schema names - extract from List structure
|
|
7533
7888
|
const items = ListUtils.unwrapList(node.object);
|
|
@@ -7543,19 +7898,19 @@ export class Deparser {
|
|
|
7543
7898
|
}
|
|
7544
7899
|
}
|
|
7545
7900
|
if (node.renameType === 'OBJECT_COLUMN' && node.subname) {
|
|
7546
|
-
output.push('RENAME COLUMN',
|
|
7901
|
+
output.push('RENAME COLUMN', QuoteUtils.quoteIdentifier(node.subname), 'TO');
|
|
7547
7902
|
}
|
|
7548
7903
|
else if (node.renameType === 'OBJECT_DOMCONSTRAINT' && node.subname) {
|
|
7549
|
-
output.push('RENAME CONSTRAINT',
|
|
7904
|
+
output.push('RENAME CONSTRAINT', QuoteUtils.quoteIdentifier(node.subname), 'TO');
|
|
7550
7905
|
}
|
|
7551
7906
|
else if (node.renameType === 'OBJECT_TABCONSTRAINT' && node.subname) {
|
|
7552
|
-
output.push('RENAME CONSTRAINT',
|
|
7907
|
+
output.push('RENAME CONSTRAINT', QuoteUtils.quoteIdentifier(node.subname), 'TO');
|
|
7553
7908
|
}
|
|
7554
7909
|
else if (node.renameType === 'OBJECT_ATTRIBUTE' && node.subname) {
|
|
7555
|
-
output.push('RENAME ATTRIBUTE',
|
|
7910
|
+
output.push('RENAME ATTRIBUTE', QuoteUtils.quoteIdentifier(node.subname), 'TO');
|
|
7556
7911
|
}
|
|
7557
7912
|
else if (node.renameType === 'OBJECT_ROLE' && node.subname) {
|
|
7558
|
-
output.push(
|
|
7913
|
+
output.push(QuoteUtils.quoteIdentifier(node.subname), 'RENAME TO');
|
|
7559
7914
|
}
|
|
7560
7915
|
else if (node.renameType === 'OBJECT_SCHEMA' && node.subname) {
|
|
7561
7916
|
output.push(this.quoteIfNeeded(node.subname), 'RENAME TO');
|
|
@@ -7569,7 +7924,7 @@ export class Deparser {
|
|
|
7569
7924
|
if (!node.newname) {
|
|
7570
7925
|
throw new Error('RenameStmt requires newname');
|
|
7571
7926
|
}
|
|
7572
|
-
output.push(QuoteUtils.
|
|
7927
|
+
output.push(QuoteUtils.quoteIdentifier(node.newname));
|
|
7573
7928
|
// Handle CASCADE/RESTRICT behavior for RENAME operations
|
|
7574
7929
|
if (node.behavior === 'DROP_CASCADE') {
|
|
7575
7930
|
output.push('CASCADE');
|
|
@@ -7581,76 +7936,7 @@ export class Deparser {
|
|
|
7581
7936
|
if (!node.objectType) {
|
|
7582
7937
|
throw new Error('AlterOwnerStmt requires objectType');
|
|
7583
7938
|
}
|
|
7584
|
-
|
|
7585
|
-
case 'OBJECT_TABLE':
|
|
7586
|
-
output.push('TABLE');
|
|
7587
|
-
break;
|
|
7588
|
-
case 'OBJECT_VIEW':
|
|
7589
|
-
output.push('VIEW');
|
|
7590
|
-
break;
|
|
7591
|
-
case 'OBJECT_INDEX':
|
|
7592
|
-
output.push('INDEX');
|
|
7593
|
-
break;
|
|
7594
|
-
case 'OBJECT_SEQUENCE':
|
|
7595
|
-
output.push('SEQUENCE');
|
|
7596
|
-
break;
|
|
7597
|
-
case 'OBJECT_FUNCTION':
|
|
7598
|
-
output.push('FUNCTION');
|
|
7599
|
-
break;
|
|
7600
|
-
case 'OBJECT_PROCEDURE':
|
|
7601
|
-
output.push('PROCEDURE');
|
|
7602
|
-
break;
|
|
7603
|
-
case 'OBJECT_SCHEMA':
|
|
7604
|
-
output.push('SCHEMA');
|
|
7605
|
-
break;
|
|
7606
|
-
case 'OBJECT_DATABASE':
|
|
7607
|
-
output.push('DATABASE');
|
|
7608
|
-
break;
|
|
7609
|
-
case 'OBJECT_DOMAIN':
|
|
7610
|
-
output.push('DOMAIN');
|
|
7611
|
-
break;
|
|
7612
|
-
case 'OBJECT_AGGREGATE':
|
|
7613
|
-
output.push('AGGREGATE');
|
|
7614
|
-
break;
|
|
7615
|
-
case 'OBJECT_CONVERSION':
|
|
7616
|
-
output.push('CONVERSION');
|
|
7617
|
-
break;
|
|
7618
|
-
case 'OBJECT_LANGUAGE':
|
|
7619
|
-
output.push('LANGUAGE');
|
|
7620
|
-
break;
|
|
7621
|
-
case 'OBJECT_OPERATOR':
|
|
7622
|
-
output.push('OPERATOR');
|
|
7623
|
-
break;
|
|
7624
|
-
case 'OBJECT_OPFAMILY':
|
|
7625
|
-
output.push('OPERATOR FAMILY');
|
|
7626
|
-
break;
|
|
7627
|
-
case 'OBJECT_OPCLASS':
|
|
7628
|
-
output.push('OPERATOR CLASS');
|
|
7629
|
-
break;
|
|
7630
|
-
case 'OBJECT_TSDICTIONARY':
|
|
7631
|
-
output.push('TEXT SEARCH DICTIONARY');
|
|
7632
|
-
break;
|
|
7633
|
-
case 'OBJECT_TSCONFIGURATION':
|
|
7634
|
-
output.push('TEXT SEARCH CONFIGURATION');
|
|
7635
|
-
break;
|
|
7636
|
-
case 'OBJECT_EVENT_TRIGGER':
|
|
7637
|
-
output.push('EVENT TRIGGER');
|
|
7638
|
-
break;
|
|
7639
|
-
case 'OBJECT_FDW':
|
|
7640
|
-
output.push('FOREIGN DATA WRAPPER');
|
|
7641
|
-
break;
|
|
7642
|
-
case 'OBJECT_FOREIGN_SERVER':
|
|
7643
|
-
output.push('SERVER');
|
|
7644
|
-
break;
|
|
7645
|
-
case 'OBJECT_TYPE':
|
|
7646
|
-
output.push('TYPE');
|
|
7647
|
-
break;
|
|
7648
|
-
case 'OBJECT_COLLATION':
|
|
7649
|
-
output.push('COLLATION');
|
|
7650
|
-
break;
|
|
7651
|
-
default:
|
|
7652
|
-
throw new Error(`Unsupported AlterOwnerStmt objectType: ${node.objectType}`);
|
|
7653
|
-
}
|
|
7939
|
+
output.push(this.getObjectTypeKeyword(node.objectType));
|
|
7654
7940
|
if (node.relation) {
|
|
7655
7941
|
output.push(this.RangeVar(node.relation, context));
|
|
7656
7942
|
}
|
|
@@ -7661,7 +7947,7 @@ export class Deparser {
|
|
|
7661
7947
|
if (items.length === 2) {
|
|
7662
7948
|
const accessMethod = items[0].String?.sval || '';
|
|
7663
7949
|
const objectName = items[1].String?.sval || '';
|
|
7664
|
-
output.push(`${QuoteUtils.
|
|
7950
|
+
output.push(`${QuoteUtils.quoteIdentifier(objectName)} USING ${accessMethod}`);
|
|
7665
7951
|
}
|
|
7666
7952
|
else {
|
|
7667
7953
|
output.push(this.visit(node.object, context));
|
|
@@ -7736,6 +8022,9 @@ export class Deparser {
|
|
|
7736
8022
|
else if (node.objtype === 'OBJECT_LANGUAGE') {
|
|
7737
8023
|
output.push('LANGUAGE');
|
|
7738
8024
|
}
|
|
8025
|
+
else if (node.objtype === 'OBJECT_SEQUENCE') {
|
|
8026
|
+
output.push('SEQUENCE');
|
|
8027
|
+
}
|
|
7739
8028
|
else if (node.objtype === 'OBJECT_FUNCTION') {
|
|
7740
8029
|
output.push('FUNCTION');
|
|
7741
8030
|
}
|
|
@@ -7761,8 +8050,11 @@ export class Deparser {
|
|
|
7761
8050
|
output.push('DATABASE');
|
|
7762
8051
|
}
|
|
7763
8052
|
if (node.objects && node.objects.length > 0) {
|
|
8053
|
+
const qualifiedKinds = ['OBJECT_TYPE', 'OBJECT_DOMAIN'];
|
|
7764
8054
|
const objects = ListUtils.unwrapList(node.objects)
|
|
7765
|
-
.map(obj =>
|
|
8055
|
+
.map(obj => qualifiedKinds.includes(node.objtype) && obj.List
|
|
8056
|
+
? ListUtils.unwrapList(obj.List.items).map((item) => this.visit(item, context)).join('.')
|
|
8057
|
+
: this.visit(obj, context))
|
|
7766
8058
|
.join(', ');
|
|
7767
8059
|
output.push(objects);
|
|
7768
8060
|
}
|
|
@@ -7801,8 +8093,11 @@ export class Deparser {
|
|
|
7801
8093
|
break;
|
|
7802
8094
|
default:
|
|
7803
8095
|
if (node.objects && node.objects.length > 0) {
|
|
8096
|
+
const qualifiedKinds = ['OBJECT_TYPE', 'OBJECT_DOMAIN'];
|
|
7804
8097
|
const objects = ListUtils.unwrapList(node.objects)
|
|
7805
|
-
.map(obj =>
|
|
8098
|
+
.map(obj => qualifiedKinds.includes(node.objtype) && obj.List
|
|
8099
|
+
? ListUtils.unwrapList(obj.List.items).map((item) => this.visit(item, context)).join('.')
|
|
8100
|
+
: this.visit(obj, context))
|
|
7806
8101
|
.join(', ');
|
|
7807
8102
|
output.push(objects);
|
|
7808
8103
|
}
|
|
@@ -7822,6 +8117,9 @@ export class Deparser {
|
|
|
7822
8117
|
if (node.grant_option && node.is_grant) {
|
|
7823
8118
|
output.push('WITH GRANT OPTION');
|
|
7824
8119
|
}
|
|
8120
|
+
if (node.grantor) {
|
|
8121
|
+
output.push('GRANTED BY', this.RoleSpec(node.grantor, context));
|
|
8122
|
+
}
|
|
7825
8123
|
// Only add behavior clauses for REVOKE statements, not for GRANT statements in ALTER DEFAULT PRIVILEGES
|
|
7826
8124
|
if (!node.is_grant) {
|
|
7827
8125
|
if (node.behavior === 'DROP_CASCADE') {
|
|
@@ -7835,57 +8133,34 @@ export class Deparser {
|
|
|
7835
8133
|
}
|
|
7836
8134
|
GrantRoleStmt(node, context) {
|
|
7837
8135
|
const output = [];
|
|
7838
|
-
|
|
7839
|
-
|
|
7840
|
-
|
|
7841
|
-
|
|
7842
|
-
|
|
7843
|
-
|
|
7844
|
-
|
|
7845
|
-
|
|
7846
|
-
|
|
7847
|
-
|
|
7848
|
-
|
|
7849
|
-
|
|
7850
|
-
|
|
7851
|
-
|
|
7852
|
-
|
|
7853
|
-
|
|
7854
|
-
|
|
7855
|
-
|
|
7856
|
-
|
|
7857
|
-
if (adminOption.DefElem && adminOption.DefElem.arg) {
|
|
7858
|
-
adminValue = adminOption.DefElem.arg.Boolean?.boolval;
|
|
7859
|
-
}
|
|
7860
|
-
}
|
|
7861
|
-
if (setOption && setOption.DefElem) {
|
|
7862
|
-
hasSetOption = true;
|
|
7863
|
-
setValue = setOption.DefElem.arg?.Boolean?.boolval;
|
|
7864
|
-
}
|
|
7865
|
-
}
|
|
8136
|
+
const options = ListUtils.unwrapList(node.opt)
|
|
8137
|
+
.map(opt => opt.DefElem)
|
|
8138
|
+
.filter((opt) => !!opt && !!opt.defname);
|
|
8139
|
+
const optionValue = (opt) => {
|
|
8140
|
+
if (!opt.arg)
|
|
8141
|
+
return true;
|
|
8142
|
+
const argType = this.getNodeType(opt.arg);
|
|
8143
|
+
const argData = this.getNodeData(opt.arg);
|
|
8144
|
+
if (argType === 'Boolean')
|
|
8145
|
+
return argData.boolval !== false;
|
|
8146
|
+
if (argType === 'String')
|
|
8147
|
+
return argData.sval !== 'false';
|
|
8148
|
+
return true;
|
|
8149
|
+
};
|
|
8150
|
+
const roles = ListUtils.unwrapList(node.granted_roles)
|
|
8151
|
+
.map(role => role.AccessPriv?.priv_name
|
|
8152
|
+
? QuoteUtils.quoteIdentifier(role.AccessPriv.priv_name)
|
|
8153
|
+
: this.visit(role, context))
|
|
8154
|
+
.join(', ');
|
|
7866
8155
|
if (node.is_grant) {
|
|
7867
|
-
output.push('GRANT');
|
|
8156
|
+
output.push('GRANT', roles, 'TO');
|
|
7868
8157
|
}
|
|
7869
8158
|
else {
|
|
7870
8159
|
output.push('REVOKE');
|
|
7871
|
-
if (
|
|
7872
|
-
output.push(
|
|
7873
|
-
}
|
|
7874
|
-
else if (hasAdminOption) {
|
|
7875
|
-
output.push('ADMIN OPTION FOR');
|
|
8160
|
+
if (options.length > 0) {
|
|
8161
|
+
output.push(`${options[0].defname.toUpperCase()} OPTION FOR`);
|
|
7876
8162
|
}
|
|
7877
|
-
|
|
7878
|
-
if (node.granted_roles && node.granted_roles.length > 0) {
|
|
7879
|
-
const roles = ListUtils.unwrapList(node.granted_roles)
|
|
7880
|
-
.map(role => this.visit(role, context))
|
|
7881
|
-
.join(', ');
|
|
7882
|
-
output.push(roles);
|
|
7883
|
-
}
|
|
7884
|
-
if (node.is_grant) {
|
|
7885
|
-
output.push('TO');
|
|
7886
|
-
}
|
|
7887
|
-
else {
|
|
7888
|
-
output.push('FROM');
|
|
8163
|
+
output.push(roles, 'FROM');
|
|
7889
8164
|
}
|
|
7890
8165
|
if (node.grantee_roles && node.grantee_roles.length > 0) {
|
|
7891
8166
|
const grantees = ListUtils.unwrapList(node.grantee_roles)
|
|
@@ -7893,45 +8168,22 @@ export class Deparser {
|
|
|
7893
8168
|
.join(', ');
|
|
7894
8169
|
output.push(grantees);
|
|
7895
8170
|
}
|
|
7896
|
-
if (node.is_grant) {
|
|
7897
|
-
const withOptions =
|
|
7898
|
-
|
|
7899
|
-
|
|
7900
|
-
|
|
7901
|
-
|
|
7902
|
-
|
|
7903
|
-
|
|
7904
|
-
|
|
7905
|
-
else {
|
|
7906
|
-
withOptions.push('ADMIN OPTION');
|
|
7907
|
-
}
|
|
7908
|
-
}
|
|
7909
|
-
if (hasInheritOption) {
|
|
7910
|
-
if (inheritValue === true) {
|
|
7911
|
-
withOptions.push('INHERIT OPTION');
|
|
7912
|
-
}
|
|
7913
|
-
else if (inheritValue === false) {
|
|
7914
|
-
withOptions.push('INHERIT FALSE');
|
|
7915
|
-
}
|
|
7916
|
-
}
|
|
7917
|
-
if (hasSetOption) {
|
|
7918
|
-
if (setValue === true) {
|
|
7919
|
-
withOptions.push('SET TRUE');
|
|
7920
|
-
}
|
|
7921
|
-
else if (setValue === false) {
|
|
7922
|
-
withOptions.push('SET FALSE');
|
|
7923
|
-
}
|
|
7924
|
-
}
|
|
7925
|
-
if (withOptions.length > 0) {
|
|
7926
|
-
output.push('WITH', withOptions.join(', '));
|
|
7927
|
-
}
|
|
8171
|
+
if (node.is_grant && options.length > 0) {
|
|
8172
|
+
const withOptions = options.map(opt => `${opt.defname.toUpperCase()} ${optionValue(opt) ? 'TRUE' : 'FALSE'}`);
|
|
8173
|
+
output.push('WITH', withOptions.join(', '));
|
|
8174
|
+
}
|
|
8175
|
+
if (node.grantor) {
|
|
8176
|
+
output.push('GRANTED BY', this.RoleSpec(node.grantor, context));
|
|
8177
|
+
}
|
|
8178
|
+
if (!node.is_grant && node.behavior === 'DROP_CASCADE') {
|
|
8179
|
+
output.push('CASCADE');
|
|
7928
8180
|
}
|
|
7929
8181
|
return output.join(' ');
|
|
7930
8182
|
}
|
|
7931
8183
|
SecLabelStmt(node, context) {
|
|
7932
8184
|
const output = ['SECURITY LABEL'];
|
|
7933
8185
|
if (node.provider) {
|
|
7934
|
-
output.push('FOR',
|
|
8186
|
+
output.push('FOR', QuoteUtils.quoteIdentifier(node.provider));
|
|
7935
8187
|
}
|
|
7936
8188
|
output.push('ON');
|
|
7937
8189
|
if (node.objtype) {
|
|
@@ -7959,11 +8211,21 @@ export class Deparser {
|
|
|
7959
8211
|
}
|
|
7960
8212
|
}
|
|
7961
8213
|
if (node.object) {
|
|
7962
|
-
|
|
8214
|
+
// Qualified names arrive as a List of String nodes and must be
|
|
8215
|
+
// dot-joined (visiting the List directly would comma-join them).
|
|
8216
|
+
if (typeof node.object === 'object' && 'List' in node.object) {
|
|
8217
|
+
const list = node.object.List;
|
|
8218
|
+
const objectParts = ListUtils.unwrapList(list.items)
|
|
8219
|
+
.map(item => this.visit(item, context));
|
|
8220
|
+
output.push(objectParts.join('.'));
|
|
8221
|
+
}
|
|
8222
|
+
else {
|
|
8223
|
+
output.push(this.visit(node.object, context));
|
|
8224
|
+
}
|
|
7963
8225
|
}
|
|
7964
8226
|
output.push('IS');
|
|
7965
8227
|
if (node.label) {
|
|
7966
|
-
output.push(
|
|
8228
|
+
output.push(QuoteUtils.escape(node.label));
|
|
7967
8229
|
}
|
|
7968
8230
|
else {
|
|
7969
8231
|
output.push('NULL');
|
|
@@ -8020,10 +8282,10 @@ export class Deparser {
|
|
|
8020
8282
|
output.push(conversionName);
|
|
8021
8283
|
}
|
|
8022
8284
|
if (node.for_encoding_name) {
|
|
8023
|
-
output.push('FOR',
|
|
8285
|
+
output.push('FOR', QuoteUtils.escape(node.for_encoding_name));
|
|
8024
8286
|
}
|
|
8025
8287
|
if (node.to_encoding_name) {
|
|
8026
|
-
output.push('TO',
|
|
8288
|
+
output.push('TO', QuoteUtils.escape(node.to_encoding_name));
|
|
8027
8289
|
}
|
|
8028
8290
|
if (node.func_name && node.func_name.length > 0) {
|
|
8029
8291
|
output.push('FROM');
|
|
@@ -8084,7 +8346,7 @@ export class Deparser {
|
|
|
8084
8346
|
}
|
|
8085
8347
|
output.push('LANGUAGE');
|
|
8086
8348
|
if (node.plname) {
|
|
8087
|
-
output.push(QuoteUtils.
|
|
8349
|
+
output.push(QuoteUtils.quoteIdentifier(node.plname));
|
|
8088
8350
|
}
|
|
8089
8351
|
if (node.plhandler && node.plhandler.length > 0) {
|
|
8090
8352
|
output.push('HANDLER');
|
|
@@ -8120,7 +8382,7 @@ export class Deparser {
|
|
|
8120
8382
|
}
|
|
8121
8383
|
output.push('LANGUAGE');
|
|
8122
8384
|
if (node.lang) {
|
|
8123
|
-
output.push(QuoteUtils.
|
|
8385
|
+
output.push(QuoteUtils.quoteIdentifier(node.lang));
|
|
8124
8386
|
}
|
|
8125
8387
|
output.push('(');
|
|
8126
8388
|
const transforms = [];
|
|
@@ -8148,7 +8410,7 @@ export class Deparser {
|
|
|
8148
8410
|
}
|
|
8149
8411
|
output.push('TRIGGER');
|
|
8150
8412
|
if (node.trigname) {
|
|
8151
|
-
output.push(QuoteUtils.
|
|
8413
|
+
output.push(QuoteUtils.quoteIdentifier(node.trigname));
|
|
8152
8414
|
}
|
|
8153
8415
|
if (context.isPretty()) {
|
|
8154
8416
|
const components = [];
|
|
@@ -8186,6 +8448,9 @@ export class Deparser {
|
|
|
8186
8448
|
.join(' ');
|
|
8187
8449
|
components.push(context.indent('REFERENCING ' + transitionClauses));
|
|
8188
8450
|
}
|
|
8451
|
+
if (node.constrrel) {
|
|
8452
|
+
components.push(context.indent('FROM ' + this.RangeVar(node.constrrel, context)));
|
|
8453
|
+
}
|
|
8189
8454
|
if (node.deferrable) {
|
|
8190
8455
|
components.push(context.indent('DEFERRABLE'));
|
|
8191
8456
|
}
|
|
@@ -8207,7 +8472,7 @@ export class Deparser {
|
|
|
8207
8472
|
const funcName = ListUtils.unwrapList(node.funcname)
|
|
8208
8473
|
.map(name => this.visit(name, context))
|
|
8209
8474
|
.join('.');
|
|
8210
|
-
executeStr += '
|
|
8475
|
+
executeStr += ' FUNCTION ' + funcName;
|
|
8211
8476
|
}
|
|
8212
8477
|
if (node.args && node.args.length > 0) {
|
|
8213
8478
|
const argContext = context.spawn('CreateTrigStmt', { isStringLiteral: true });
|
|
@@ -8312,14 +8577,14 @@ export class Deparser {
|
|
|
8312
8577
|
output.push('OLD TABLE AS');
|
|
8313
8578
|
}
|
|
8314
8579
|
if (node.name) {
|
|
8315
|
-
output.push(QuoteUtils.
|
|
8580
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
8316
8581
|
}
|
|
8317
8582
|
return output.join(' ');
|
|
8318
8583
|
}
|
|
8319
8584
|
CreateEventTrigStmt(node, context) {
|
|
8320
8585
|
const output = ['CREATE EVENT TRIGGER'];
|
|
8321
8586
|
if (node.trigname) {
|
|
8322
|
-
output.push(QuoteUtils.
|
|
8587
|
+
output.push(QuoteUtils.quoteIdentifier(node.trigname));
|
|
8323
8588
|
}
|
|
8324
8589
|
output.push('ON');
|
|
8325
8590
|
if (node.eventname) {
|
|
@@ -8345,7 +8610,7 @@ export class Deparser {
|
|
|
8345
8610
|
AlterEventTrigStmt(node, context) {
|
|
8346
8611
|
const output = ['ALTER EVENT TRIGGER'];
|
|
8347
8612
|
if (node.trigname) {
|
|
8348
|
-
output.push(QuoteUtils.
|
|
8613
|
+
output.push(QuoteUtils.quoteIdentifier(node.trigname));
|
|
8349
8614
|
}
|
|
8350
8615
|
if (node.tgenabled) {
|
|
8351
8616
|
switch (node.tgenabled) {
|
|
@@ -8465,6 +8730,74 @@ export class Deparser {
|
|
|
8465
8730
|
.join(' ');
|
|
8466
8731
|
output.push(whenClauses);
|
|
8467
8732
|
}
|
|
8733
|
+
if (node.returningClause) {
|
|
8734
|
+
output.push(this.ReturningClause(node.returningClause, context));
|
|
8735
|
+
}
|
|
8736
|
+
return output.join(' ');
|
|
8737
|
+
}
|
|
8738
|
+
MergeSupportFunc(node, context) {
|
|
8739
|
+
return 'merge_action()';
|
|
8740
|
+
}
|
|
8741
|
+
MergeWhenClause(node, context) {
|
|
8742
|
+
const output = ['WHEN'];
|
|
8743
|
+
switch (node.matchKind) {
|
|
8744
|
+
case 'MERGE_WHEN_MATCHED':
|
|
8745
|
+
output.push('MATCHED');
|
|
8746
|
+
break;
|
|
8747
|
+
case 'MERGE_WHEN_NOT_MATCHED_BY_SOURCE':
|
|
8748
|
+
output.push('NOT MATCHED BY SOURCE');
|
|
8749
|
+
break;
|
|
8750
|
+
case 'MERGE_WHEN_NOT_MATCHED_BY_TARGET':
|
|
8751
|
+
output.push('NOT MATCHED');
|
|
8752
|
+
break;
|
|
8753
|
+
}
|
|
8754
|
+
if (node.condition) {
|
|
8755
|
+
output.push('AND');
|
|
8756
|
+
output.push(this.visit(node.condition, context));
|
|
8757
|
+
}
|
|
8758
|
+
output.push('THEN');
|
|
8759
|
+
switch (node.commandType) {
|
|
8760
|
+
case 'CMD_UPDATE': {
|
|
8761
|
+
output.push('UPDATE SET');
|
|
8762
|
+
if (node.targetList && node.targetList.length > 0) {
|
|
8763
|
+
output.push(this.formatUpdateAssignments(node.targetList, context));
|
|
8764
|
+
}
|
|
8765
|
+
break;
|
|
8766
|
+
}
|
|
8767
|
+
case 'CMD_INSERT': {
|
|
8768
|
+
output.push('INSERT');
|
|
8769
|
+
const targetList = ListUtils.unwrapList(node.targetList);
|
|
8770
|
+
if (targetList.length > 0) {
|
|
8771
|
+
const columns = targetList
|
|
8772
|
+
.map(target => QuoteUtils.quoteIdentifier(target.ResTarget?.name))
|
|
8773
|
+
.join(', ');
|
|
8774
|
+
output.push(`(${columns})`);
|
|
8775
|
+
}
|
|
8776
|
+
if (node.override === 'OVERRIDING_USER_VALUE') {
|
|
8777
|
+
output.push('OVERRIDING USER VALUE');
|
|
8778
|
+
}
|
|
8779
|
+
else if (node.override === 'OVERRIDING_SYSTEM_VALUE') {
|
|
8780
|
+
output.push('OVERRIDING SYSTEM VALUE');
|
|
8781
|
+
}
|
|
8782
|
+
const values = ListUtils.unwrapList(node.values);
|
|
8783
|
+
if (values.length > 0) {
|
|
8784
|
+
const valueItems = values
|
|
8785
|
+
.map(value => this.visit(value, context))
|
|
8786
|
+
.join(', ');
|
|
8787
|
+
output.push(`VALUES (${valueItems})`);
|
|
8788
|
+
}
|
|
8789
|
+
else {
|
|
8790
|
+
output.push('DEFAULT VALUES');
|
|
8791
|
+
}
|
|
8792
|
+
break;
|
|
8793
|
+
}
|
|
8794
|
+
case 'CMD_DELETE':
|
|
8795
|
+
output.push('DELETE');
|
|
8796
|
+
break;
|
|
8797
|
+
case 'CMD_NOTHING':
|
|
8798
|
+
output.push('DO NOTHING');
|
|
8799
|
+
break;
|
|
8800
|
+
}
|
|
8468
8801
|
return output.join(' ');
|
|
8469
8802
|
}
|
|
8470
8803
|
AlterTableMoveAllStmt(node, context) {
|
|
@@ -8480,11 +8813,11 @@ export class Deparser {
|
|
|
8480
8813
|
}
|
|
8481
8814
|
output.push('ALL', 'IN', 'TABLESPACE');
|
|
8482
8815
|
if (node.orig_tablespacename) {
|
|
8483
|
-
output.push(QuoteUtils.
|
|
8816
|
+
output.push(QuoteUtils.quoteIdentifier(node.orig_tablespacename));
|
|
8484
8817
|
}
|
|
8485
8818
|
output.push('SET', 'TABLESPACE');
|
|
8486
8819
|
if (node.new_tablespacename) {
|
|
8487
|
-
output.push(QuoteUtils.
|
|
8820
|
+
output.push(QuoteUtils.quoteIdentifier(node.new_tablespacename));
|
|
8488
8821
|
}
|
|
8489
8822
|
if (node.nowait) {
|
|
8490
8823
|
output.push('NOWAIT');
|
|
@@ -8508,10 +8841,10 @@ export class Deparser {
|
|
|
8508
8841
|
const sequenceName = [];
|
|
8509
8842
|
const seq = node.sequence;
|
|
8510
8843
|
if (seq.schemaname) {
|
|
8511
|
-
sequenceName.push(QuoteUtils.
|
|
8844
|
+
sequenceName.push(QuoteUtils.quoteIdentifier(seq.schemaname));
|
|
8512
8845
|
}
|
|
8513
8846
|
if (seq.relname) {
|
|
8514
|
-
sequenceName.push(QuoteUtils.
|
|
8847
|
+
sequenceName.push(QuoteUtils.quoteIdentifier(seq.relname));
|
|
8515
8848
|
}
|
|
8516
8849
|
output.push(sequenceName.join('.'));
|
|
8517
8850
|
}
|
|
@@ -8545,10 +8878,10 @@ export class Deparser {
|
|
|
8545
8878
|
const sequenceName = [];
|
|
8546
8879
|
const seq = node.sequence;
|
|
8547
8880
|
if (seq.schemaname) {
|
|
8548
|
-
sequenceName.push(QuoteUtils.
|
|
8881
|
+
sequenceName.push(QuoteUtils.quoteIdentifier(seq.schemaname));
|
|
8549
8882
|
}
|
|
8550
8883
|
if (seq.relname) {
|
|
8551
|
-
sequenceName.push(QuoteUtils.
|
|
8884
|
+
sequenceName.push(QuoteUtils.quoteIdentifier(seq.relname));
|
|
8552
8885
|
}
|
|
8553
8886
|
output.push(sequenceName.join('.'));
|
|
8554
8887
|
}
|
|
@@ -8833,6 +9166,13 @@ export class Deparser {
|
|
|
8833
9166
|
output.push('USING');
|
|
8834
9167
|
output.push(node.into.accessMethod);
|
|
8835
9168
|
}
|
|
9169
|
+
if (node.into && node.into.options && node.into.options.length > 0) {
|
|
9170
|
+
output.push('WITH');
|
|
9171
|
+
const options = ListUtils.unwrapList(node.into.options)
|
|
9172
|
+
.map(option => this.visit(option, context.spawn('CreateStmt')))
|
|
9173
|
+
.join(', ');
|
|
9174
|
+
output.push(`(${options})`);
|
|
9175
|
+
}
|
|
8836
9176
|
if (node.into && node.into.onCommit && node.into.onCommit !== 'ONCOMMIT_NOOP') {
|
|
8837
9177
|
output.push('ON COMMIT');
|
|
8838
9178
|
switch (node.into.onCommit) {
|
|
@@ -8847,17 +9187,13 @@ export class Deparser {
|
|
|
8847
9187
|
break;
|
|
8848
9188
|
}
|
|
8849
9189
|
}
|
|
9190
|
+
if (node.into && node.into.tableSpaceName) {
|
|
9191
|
+
output.push('TABLESPACE', QuoteUtils.quoteIdentifier(node.into.tableSpaceName));
|
|
9192
|
+
}
|
|
8850
9193
|
output.push('AS');
|
|
8851
9194
|
if (node.query) {
|
|
8852
9195
|
output.push(this.visit(node.query, context));
|
|
8853
9196
|
}
|
|
8854
|
-
if (node.into && node.into.options && node.into.options.length > 0) {
|
|
8855
|
-
output.push('WITH');
|
|
8856
|
-
const options = ListUtils.unwrapList(node.into.options)
|
|
8857
|
-
.map(option => this.visit(option, context))
|
|
8858
|
-
.join(', ');
|
|
8859
|
-
output.push(`(${options})`);
|
|
8860
|
-
}
|
|
8861
9197
|
if (node.into && node.into.skipData) {
|
|
8862
9198
|
output.push('WITH NO DATA');
|
|
8863
9199
|
}
|
|
@@ -8895,7 +9231,7 @@ export class Deparser {
|
|
|
8895
9231
|
}
|
|
8896
9232
|
aliasname(node, context) {
|
|
8897
9233
|
if (typeof node === 'string') {
|
|
8898
|
-
return QuoteUtils.
|
|
9234
|
+
return QuoteUtils.quoteIdentifier(node);
|
|
8899
9235
|
}
|
|
8900
9236
|
return this.visit(node, context);
|
|
8901
9237
|
}
|
|
@@ -8927,18 +9263,16 @@ export class Deparser {
|
|
|
8927
9263
|
const defName = defElem.defname;
|
|
8928
9264
|
const defValue = defElem.arg;
|
|
8929
9265
|
if (defName && defValue) {
|
|
8930
|
-
|
|
8931
|
-
|
|
8932
|
-
preservedDefName = `"${defName}"`;
|
|
8933
|
-
}
|
|
8934
|
-
else {
|
|
8935
|
-
preservedDefName = this.preserveOperatorDefElemCase(defName);
|
|
8936
|
-
}
|
|
9266
|
+
const quotedDefName = QuoteUtils.quoteIdentifier(defName);
|
|
9267
|
+
const preservedDefName = quotedDefName !== defName ? quotedDefName : this.preserveOperatorDefElemCase(defName);
|
|
8937
9268
|
if ((defName.toLowerCase() === 'commutator' || defName.toLowerCase() === 'negator') && defValue.List) {
|
|
8938
9269
|
const listItems = ListUtils.unwrapList(defValue.List.items);
|
|
8939
9270
|
if (listItems.length === 1 && listItems[0].String) {
|
|
8940
9271
|
return `${preservedDefName} = ${listItems[0].String.sval}`;
|
|
8941
9272
|
}
|
|
9273
|
+
if (listItems.length > 1 && listItems.every(item => item.String)) {
|
|
9274
|
+
return `${preservedDefName} = OPERATOR(${this.qualifiedOperatorName(listItems)})`;
|
|
9275
|
+
}
|
|
8942
9276
|
}
|
|
8943
9277
|
// For commutator/negator, we already handled them above
|
|
8944
9278
|
if ((defName.toLowerCase() === 'commutator' || defName.toLowerCase() === 'negator')) {
|
|
@@ -8949,7 +9283,7 @@ export class Deparser {
|
|
|
8949
9283
|
else if (defName && !defValue) {
|
|
8950
9284
|
// Handle boolean flags like HASHES, MERGES - preserve original case
|
|
8951
9285
|
if (defName === 'Hashes' || defName === 'Merges') {
|
|
8952
|
-
return
|
|
9286
|
+
return QuoteUtils.quoteIdentifier(defName);
|
|
8953
9287
|
}
|
|
8954
9288
|
return this.preserveOperatorDefElemCase(defName).toUpperCase();
|
|
8955
9289
|
}
|
|
@@ -9088,16 +9422,11 @@ export class Deparser {
|
|
|
9088
9422
|
const defName = defElem.defname;
|
|
9089
9423
|
const defValue = defElem.arg;
|
|
9090
9424
|
if (defName && defValue) {
|
|
9091
|
-
|
|
9092
|
-
|
|
9093
|
-
preservedDefName = `"${defName}"`;
|
|
9094
|
-
}
|
|
9095
|
-
else {
|
|
9096
|
-
preservedDefName = defName;
|
|
9097
|
-
}
|
|
9425
|
+
const quotedDefName = QuoteUtils.quoteIdentifier(defName);
|
|
9426
|
+
const preservedDefName = quotedDefName !== defName ? quotedDefName : defName;
|
|
9098
9427
|
// Handle String arguments with single quotes for string literals
|
|
9099
9428
|
if (defValue.String) {
|
|
9100
|
-
return `${preservedDefName} =
|
|
9429
|
+
return `${preservedDefName} = ${QuoteUtils.escape(defValue.String.sval)}`;
|
|
9101
9430
|
}
|
|
9102
9431
|
return `${preservedDefName} = ${this.visit(defValue, context)}`;
|
|
9103
9432
|
}
|
|
@@ -9220,7 +9549,7 @@ export class Deparser {
|
|
|
9220
9549
|
// For CREATE COLLATION, ensure String nodes are quoted as string literals
|
|
9221
9550
|
let valueStr;
|
|
9222
9551
|
if (defValue.String) {
|
|
9223
|
-
valueStr =
|
|
9552
|
+
valueStr = QuoteUtils.escape(defValue.String.sval);
|
|
9224
9553
|
}
|
|
9225
9554
|
else {
|
|
9226
9555
|
valueStr = this.visit(defValue, context);
|
|
@@ -9249,7 +9578,7 @@ export class Deparser {
|
|
|
9249
9578
|
AlterDatabaseStmt(node, context) {
|
|
9250
9579
|
const output = ['ALTER', 'DATABASE'];
|
|
9251
9580
|
if (node.dbname) {
|
|
9252
|
-
output.push(QuoteUtils.
|
|
9581
|
+
output.push(QuoteUtils.quoteIdentifier(node.dbname));
|
|
9253
9582
|
}
|
|
9254
9583
|
if (node.options && node.options.length > 0) {
|
|
9255
9584
|
const options = ListUtils.unwrapList(node.options).map(opt => this.visit(opt, context));
|
|
@@ -9260,7 +9589,7 @@ export class Deparser {
|
|
|
9260
9589
|
AlterDatabaseRefreshCollStmt(node, context) {
|
|
9261
9590
|
const output = ['ALTER', 'DATABASE'];
|
|
9262
9591
|
if (node.dbname) {
|
|
9263
|
-
output.push(QuoteUtils.
|
|
9592
|
+
output.push(QuoteUtils.quoteIdentifier(node.dbname));
|
|
9264
9593
|
}
|
|
9265
9594
|
output.push('REFRESH', 'COLLATION', 'VERSION');
|
|
9266
9595
|
return output.join(' ');
|
|
@@ -9268,7 +9597,7 @@ export class Deparser {
|
|
|
9268
9597
|
AlterDatabaseSetStmt(node, context) {
|
|
9269
9598
|
const output = ['ALTER', 'DATABASE'];
|
|
9270
9599
|
if (node.dbname) {
|
|
9271
|
-
output.push(QuoteUtils.
|
|
9600
|
+
output.push(QuoteUtils.quoteIdentifier(node.dbname));
|
|
9272
9601
|
}
|
|
9273
9602
|
if (node.setstmt) {
|
|
9274
9603
|
const setClause = this.VariableSetStmt(node.setstmt, context);
|
|
@@ -9279,7 +9608,7 @@ export class Deparser {
|
|
|
9279
9608
|
DeclareCursorStmt(node, context) {
|
|
9280
9609
|
const output = ['DECLARE'];
|
|
9281
9610
|
if (node.portalname) {
|
|
9282
|
-
output.push(QuoteUtils.
|
|
9611
|
+
output.push(QuoteUtils.quoteIdentifier(node.portalname));
|
|
9283
9612
|
}
|
|
9284
9613
|
// Handle cursor options before CURSOR keyword
|
|
9285
9614
|
const cursorOptions = [];
|
|
@@ -9321,7 +9650,7 @@ export class Deparser {
|
|
|
9321
9650
|
else if (node.pubobjtype === 'PUBLICATIONOBJ_TABLES_IN_SCHEMA') {
|
|
9322
9651
|
output.push('TABLES IN SCHEMA');
|
|
9323
9652
|
if (node.name) {
|
|
9324
|
-
output.push(QuoteUtils.
|
|
9653
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
9325
9654
|
}
|
|
9326
9655
|
}
|
|
9327
9656
|
else if (node.pubobjtype === 'PUBLICATIONOBJ_TABLES_IN_CUR_SCHEMA') {
|
|
@@ -9340,14 +9669,14 @@ export class Deparser {
|
|
|
9340
9669
|
}
|
|
9341
9670
|
if (node.whereClause) {
|
|
9342
9671
|
output.push('WHERE');
|
|
9343
|
-
output.push(this.visit(node.whereClause, context));
|
|
9672
|
+
output.push(`(${this.visit(node.whereClause, context)})`);
|
|
9344
9673
|
}
|
|
9345
9674
|
return output.join(' ');
|
|
9346
9675
|
}
|
|
9347
9676
|
CreateAmStmt(node, context) {
|
|
9348
9677
|
const output = ['CREATE', 'ACCESS', 'METHOD'];
|
|
9349
9678
|
if (node.amname) {
|
|
9350
|
-
output.push(QuoteUtils.
|
|
9679
|
+
output.push(QuoteUtils.quoteIdentifier(node.amname));
|
|
9351
9680
|
}
|
|
9352
9681
|
output.push('TYPE');
|
|
9353
9682
|
switch (node.amtype) {
|
|
@@ -9407,7 +9736,7 @@ export class Deparser {
|
|
|
9407
9736
|
}
|
|
9408
9737
|
}
|
|
9409
9738
|
if (node.tableSpaceName) {
|
|
9410
|
-
output.push('TABLESPACE', QuoteUtils.
|
|
9739
|
+
output.push('TABLESPACE', QuoteUtils.quoteIdentifier(node.tableSpaceName));
|
|
9411
9740
|
}
|
|
9412
9741
|
return output.join(' ');
|
|
9413
9742
|
}
|
|
@@ -9487,6 +9816,23 @@ export class Deparser {
|
|
|
9487
9816
|
}
|
|
9488
9817
|
return output.join(' ');
|
|
9489
9818
|
}
|
|
9819
|
+
quoteDefElemArg(arg, argValue) {
|
|
9820
|
+
if (arg && this.getNodeType(arg) === 'String') {
|
|
9821
|
+
return QuoteUtils.escape(this.getNodeData(arg).sval || '');
|
|
9822
|
+
}
|
|
9823
|
+
return typeof argValue === 'string' && !argValue.startsWith("'")
|
|
9824
|
+
? QuoteUtils.escape(argValue)
|
|
9825
|
+
: argValue;
|
|
9826
|
+
}
|
|
9827
|
+
formatOptionValue(arg, argValue) {
|
|
9828
|
+
if (arg && this.getNodeType(arg) === 'String') {
|
|
9829
|
+
const sval = this.getNodeData(arg).sval || '';
|
|
9830
|
+
return /^[a-z_][a-z0-9_]*$/.test(sval) && keywordKindOf(sval) === 'NO_KEYWORD'
|
|
9831
|
+
? sval
|
|
9832
|
+
: QuoteUtils.escape(sval);
|
|
9833
|
+
}
|
|
9834
|
+
return argValue;
|
|
9835
|
+
}
|
|
9490
9836
|
Var(node, context) {
|
|
9491
9837
|
if (node.varno && node.varattno) {
|
|
9492
9838
|
return `$${node.varno}.${node.varattno}`;
|
|
@@ -9526,7 +9872,7 @@ export class Deparser {
|
|
|
9526
9872
|
}
|
|
9527
9873
|
if (node.rowexpr) {
|
|
9528
9874
|
output.push(',');
|
|
9529
|
-
output.push(
|
|
9875
|
+
output.push(this.visit(node.rowexpr, context));
|
|
9530
9876
|
}
|
|
9531
9877
|
if (node.colexprs && node.colexprs.length > 0) {
|
|
9532
9878
|
output.push('COLUMNS');
|
|
@@ -9543,29 +9889,44 @@ export class Deparser {
|
|
|
9543
9889
|
if (node.lateral) {
|
|
9544
9890
|
output.push('LATERAL');
|
|
9545
9891
|
}
|
|
9546
|
-
|
|
9547
|
-
|
|
9892
|
+
const args = [];
|
|
9893
|
+
if (node.namespaces && node.namespaces.length > 0) {
|
|
9894
|
+
const namespaces = ListUtils.unwrapList(node.namespaces).map(ns => {
|
|
9895
|
+
const target = this.getNodeData(ns);
|
|
9896
|
+
const uri = this.visit(target.val, context);
|
|
9897
|
+
return target.name ? `${uri} AS ${QuoteUtils.quoteIdentifier(target.name)}` : `DEFAULT ${uri}`;
|
|
9898
|
+
});
|
|
9899
|
+
args.push(`XMLNAMESPACES(${namespaces.join(', ')}),`);
|
|
9548
9900
|
}
|
|
9549
9901
|
if (node.rowexpr) {
|
|
9550
|
-
|
|
9551
|
-
|
|
9902
|
+
args.push(this.formatXmlTableExpr(node.rowexpr, context));
|
|
9903
|
+
}
|
|
9904
|
+
if (node.docexpr) {
|
|
9905
|
+
args.push('PASSING');
|
|
9906
|
+
args.push(this.formatXmlTableExpr(node.docexpr, context));
|
|
9552
9907
|
}
|
|
9553
9908
|
if (node.columns && node.columns.length > 0) {
|
|
9554
|
-
|
|
9555
|
-
|
|
9909
|
+
args.push('COLUMNS');
|
|
9910
|
+
args.push(ListUtils.unwrapList(node.columns)
|
|
9556
9911
|
.map(col => this.visit(col, context))
|
|
9557
|
-
.join(', ');
|
|
9558
|
-
output.push(`(${columns})`);
|
|
9912
|
+
.join(', '));
|
|
9559
9913
|
}
|
|
9914
|
+
output.push(`XMLTABLE(${args.join(' ')})`);
|
|
9560
9915
|
if (node.alias) {
|
|
9561
9916
|
output.push(this.Alias(node.alias, context));
|
|
9562
9917
|
}
|
|
9563
9918
|
return output.join(' ');
|
|
9564
9919
|
}
|
|
9920
|
+
formatXmlTableExpr(expr, context) {
|
|
9921
|
+
const value = this.visit(expr, context);
|
|
9922
|
+
return ['A_Const', 'ColumnRef', 'ParamRef', 'FuncCall'].includes(this.getNodeType(expr))
|
|
9923
|
+
? value
|
|
9924
|
+
: `(${value})`;
|
|
9925
|
+
}
|
|
9565
9926
|
RangeTableFuncCol(node, context) {
|
|
9566
9927
|
const output = [];
|
|
9567
9928
|
if (node.colname) {
|
|
9568
|
-
output.push(QuoteUtils.
|
|
9929
|
+
output.push(QuoteUtils.quoteIdentifier(node.colname));
|
|
9569
9930
|
}
|
|
9570
9931
|
if (node.for_ordinality) {
|
|
9571
9932
|
output.push('FOR ORDINALITY');
|
|
@@ -9575,32 +9936,193 @@ export class Deparser {
|
|
|
9575
9936
|
}
|
|
9576
9937
|
if (node.colexpr) {
|
|
9577
9938
|
output.push('PATH');
|
|
9578
|
-
output.push(
|
|
9939
|
+
output.push(this.visit(node.colexpr, context));
|
|
9579
9940
|
}
|
|
9580
9941
|
if (node.coldefexpr) {
|
|
9581
9942
|
output.push('DEFAULT');
|
|
9582
9943
|
output.push(this.visit(node.coldefexpr, context));
|
|
9583
9944
|
}
|
|
9945
|
+
if (node.is_not_null) {
|
|
9946
|
+
output.push('NOT NULL');
|
|
9947
|
+
}
|
|
9584
9948
|
return output.join(' ');
|
|
9585
9949
|
}
|
|
9950
|
+
formatJsonFormat(format) {
|
|
9951
|
+
if (!format || !format.format_type || format.format_type === 'JS_FORMAT_DEFAULT') {
|
|
9952
|
+
return null;
|
|
9953
|
+
}
|
|
9954
|
+
const parts = ['FORMAT JSON'];
|
|
9955
|
+
switch (format.encoding) {
|
|
9956
|
+
case 'JS_ENC_UTF8':
|
|
9957
|
+
parts.push('ENCODING UTF8');
|
|
9958
|
+
break;
|
|
9959
|
+
case 'JS_ENC_UTF16':
|
|
9960
|
+
parts.push('ENCODING UTF16');
|
|
9961
|
+
break;
|
|
9962
|
+
case 'JS_ENC_UTF32':
|
|
9963
|
+
parts.push('ENCODING UTF32');
|
|
9964
|
+
break;
|
|
9965
|
+
}
|
|
9966
|
+
return parts.join(' ');
|
|
9967
|
+
}
|
|
9968
|
+
formatJsonOutput(output, context) {
|
|
9969
|
+
if (!output || !output.typeName)
|
|
9970
|
+
return null;
|
|
9971
|
+
const parts = ['RETURNING', this.TypeName(output.typeName, context)];
|
|
9972
|
+
const format = this.formatJsonFormat(output.returning?.format);
|
|
9973
|
+
if (format)
|
|
9974
|
+
parts.push(format);
|
|
9975
|
+
return parts.join(' ');
|
|
9976
|
+
}
|
|
9977
|
+
formatJsonNullClause(absentOnNull) {
|
|
9978
|
+
return absentOnNull ? 'ABSENT ON NULL' : 'NULL ON NULL';
|
|
9979
|
+
}
|
|
9980
|
+
formatJsonUniqueClause(unique) {
|
|
9981
|
+
return unique ? 'WITH UNIQUE KEYS' : null;
|
|
9982
|
+
}
|
|
9983
|
+
JsonValueExpr(node, context) {
|
|
9984
|
+
const parts = [];
|
|
9985
|
+
if (node.raw_expr) {
|
|
9986
|
+
parts.push(this.visit(node.raw_expr, context));
|
|
9987
|
+
}
|
|
9988
|
+
const format = this.formatJsonFormat(node.format);
|
|
9989
|
+
if (format)
|
|
9990
|
+
parts.push(format);
|
|
9991
|
+
return parts.join(' ');
|
|
9992
|
+
}
|
|
9993
|
+
JsonKeyValue(node, context) {
|
|
9994
|
+
const key = node.key ? this.visit(node.key, context) : '';
|
|
9995
|
+
const value = node.value ? this.JsonValueExpr(node.value, context) : '';
|
|
9996
|
+
return `${key} : ${value}`;
|
|
9997
|
+
}
|
|
9998
|
+
JsonObjectConstructor(node, context) {
|
|
9999
|
+
const args = [];
|
|
10000
|
+
if (node.exprs && node.exprs.length > 0) {
|
|
10001
|
+
args.push(ListUtils.unwrapList(node.exprs).map(e => this.visit(e, context)).join(', '));
|
|
10002
|
+
args.push(this.formatJsonNullClause(node.absent_on_null));
|
|
10003
|
+
const unique = this.formatJsonUniqueClause(node.unique);
|
|
10004
|
+
if (unique)
|
|
10005
|
+
args.push(unique);
|
|
10006
|
+
}
|
|
10007
|
+
const output = this.formatJsonOutput(node.output, context);
|
|
10008
|
+
if (output)
|
|
10009
|
+
args.push(output);
|
|
10010
|
+
return `JSON_OBJECT(${args.join(' ')})`;
|
|
10011
|
+
}
|
|
10012
|
+
JsonArrayConstructor(node, context) {
|
|
10013
|
+
const args = [];
|
|
10014
|
+
if (node.exprs && node.exprs.length > 0) {
|
|
10015
|
+
args.push(ListUtils.unwrapList(node.exprs).map(e => this.visit(e, context)).join(', '));
|
|
10016
|
+
args.push(this.formatJsonNullClause(node.absent_on_null));
|
|
10017
|
+
}
|
|
10018
|
+
const output = this.formatJsonOutput(node.output, context);
|
|
10019
|
+
if (output)
|
|
10020
|
+
args.push(output);
|
|
10021
|
+
return `JSON_ARRAY(${args.join(' ')})`;
|
|
10022
|
+
}
|
|
9586
10023
|
JsonArrayQueryConstructor(node, context) {
|
|
9587
|
-
const
|
|
10024
|
+
const args = [];
|
|
9588
10025
|
if (node.query) {
|
|
9589
|
-
|
|
10026
|
+
args.push(this.visit(node.query, context));
|
|
10027
|
+
}
|
|
10028
|
+
const format = this.formatJsonFormat(node.format);
|
|
10029
|
+
if (format)
|
|
10030
|
+
args.push(format);
|
|
10031
|
+
const output = this.formatJsonOutput(node.output, context);
|
|
10032
|
+
if (output)
|
|
10033
|
+
args.push(output);
|
|
10034
|
+
return `JSON_ARRAY(${args.join(' ')})`;
|
|
10035
|
+
}
|
|
10036
|
+
formatJsonAggSuffix(ctor, context) {
|
|
10037
|
+
if (!ctor)
|
|
10038
|
+
return '';
|
|
10039
|
+
let result = '';
|
|
10040
|
+
if (ctor.agg_filter) {
|
|
10041
|
+
result += ` FILTER (WHERE ${this.visit(ctor.agg_filter, context)})`;
|
|
9590
10042
|
}
|
|
9591
|
-
if (
|
|
9592
|
-
|
|
10043
|
+
if (ctor.over) {
|
|
10044
|
+
result += this.formatOverClause(ctor.over, context);
|
|
9593
10045
|
}
|
|
9594
|
-
|
|
9595
|
-
|
|
10046
|
+
return result;
|
|
10047
|
+
}
|
|
10048
|
+
JsonObjectAgg(node, context) {
|
|
10049
|
+
const args = [];
|
|
10050
|
+
if (node.arg) {
|
|
10051
|
+
args.push(this.JsonKeyValue(node.arg, context));
|
|
10052
|
+
}
|
|
10053
|
+
args.push(this.formatJsonNullClause(node.absent_on_null));
|
|
10054
|
+
const unique = this.formatJsonUniqueClause(node.unique);
|
|
10055
|
+
if (unique)
|
|
10056
|
+
args.push(unique);
|
|
10057
|
+
const output = this.formatJsonOutput(node.constructor?.output, context);
|
|
10058
|
+
if (output)
|
|
10059
|
+
args.push(output);
|
|
10060
|
+
return `JSON_OBJECTAGG(${args.join(' ')})${this.formatJsonAggSuffix(node.constructor, context)}`;
|
|
10061
|
+
}
|
|
10062
|
+
JsonArrayAgg(node, context) {
|
|
10063
|
+
const args = [];
|
|
10064
|
+
if (node.arg) {
|
|
10065
|
+
args.push(this.JsonValueExpr(node.arg, context));
|
|
9596
10066
|
}
|
|
9597
|
-
|
|
9598
|
-
|
|
10067
|
+
const aggOrder = node.constructor?.agg_order;
|
|
10068
|
+
if (aggOrder && aggOrder.length > 0) {
|
|
10069
|
+
const orderItems = ListUtils.unwrapList(aggOrder).map(item => this.visit(item, context));
|
|
10070
|
+
args.push(`ORDER BY ${orderItems.join(', ')}`);
|
|
9599
10071
|
}
|
|
9600
|
-
|
|
9601
|
-
|
|
10072
|
+
args.push(this.formatJsonNullClause(node.absent_on_null));
|
|
10073
|
+
const output = this.formatJsonOutput(node.constructor?.output, context);
|
|
10074
|
+
if (output)
|
|
10075
|
+
args.push(output);
|
|
10076
|
+
return `JSON_ARRAYAGG(${args.join(' ')})${this.formatJsonAggSuffix(node.constructor, context)}`;
|
|
10077
|
+
}
|
|
10078
|
+
JsonParseExpr(node, context) {
|
|
10079
|
+
const args = [];
|
|
10080
|
+
if (node.expr) {
|
|
10081
|
+
args.push(this.JsonValueExpr(node.expr, context));
|
|
9602
10082
|
}
|
|
9603
|
-
|
|
10083
|
+
const unique = this.formatJsonUniqueClause(node.unique_keys);
|
|
10084
|
+
if (unique)
|
|
10085
|
+
args.push(unique);
|
|
10086
|
+
return `JSON(${args.join(' ')})`;
|
|
10087
|
+
}
|
|
10088
|
+
JsonScalarExpr(node, context) {
|
|
10089
|
+
const expr = node.expr ? this.visit(node.expr, context) : '';
|
|
10090
|
+
return `JSON_SCALAR(${expr})`;
|
|
10091
|
+
}
|
|
10092
|
+
JsonSerializeExpr(node, context) {
|
|
10093
|
+
const args = [];
|
|
10094
|
+
if (node.expr) {
|
|
10095
|
+
args.push(this.JsonValueExpr(node.expr, context));
|
|
10096
|
+
}
|
|
10097
|
+
const output = this.formatJsonOutput(node.output, context);
|
|
10098
|
+
if (output)
|
|
10099
|
+
args.push(output);
|
|
10100
|
+
return `JSON_SERIALIZE(${args.join(' ')})`;
|
|
10101
|
+
}
|
|
10102
|
+
JsonIsPredicate(node, context) {
|
|
10103
|
+
const parts = [];
|
|
10104
|
+
if (node.expr) {
|
|
10105
|
+
parts.push(this.visit(node.expr, context));
|
|
10106
|
+
}
|
|
10107
|
+
const format = this.formatJsonFormat(node.format);
|
|
10108
|
+
if (format)
|
|
10109
|
+
parts.push(format);
|
|
10110
|
+
parts.push('IS JSON');
|
|
10111
|
+
switch (node.item_type) {
|
|
10112
|
+
case 'JS_TYPE_OBJECT':
|
|
10113
|
+
parts.push('OBJECT');
|
|
10114
|
+
break;
|
|
10115
|
+
case 'JS_TYPE_ARRAY':
|
|
10116
|
+
parts.push('ARRAY');
|
|
10117
|
+
break;
|
|
10118
|
+
case 'JS_TYPE_SCALAR':
|
|
10119
|
+
parts.push('SCALAR');
|
|
10120
|
+
break;
|
|
10121
|
+
}
|
|
10122
|
+
if (node.unique_keys) {
|
|
10123
|
+
parts.push('WITH UNIQUE KEYS');
|
|
10124
|
+
}
|
|
10125
|
+
return parts.join(' ');
|
|
9604
10126
|
}
|
|
9605
10127
|
RangeFunction(node, context) {
|
|
9606
10128
|
const output = [];
|
|
@@ -9711,10 +10233,10 @@ export class Deparser {
|
|
|
9711
10233
|
if (node.op === 'IS_XMLPI') {
|
|
9712
10234
|
if (node.name && node.args && node.args.length > 0) {
|
|
9713
10235
|
const argStrs = ListUtils.unwrapList(node.args).map(arg => this.visit(arg, context));
|
|
9714
|
-
return `xmlpi(name ${QuoteUtils.
|
|
10236
|
+
return `xmlpi(name ${QuoteUtils.quoteIdentifier(node.name)}, ${argStrs.join(', ')})`;
|
|
9715
10237
|
}
|
|
9716
10238
|
else if (node.name) {
|
|
9717
|
-
return `xmlpi(name ${QuoteUtils.
|
|
10239
|
+
return `xmlpi(name ${QuoteUtils.quoteIdentifier(node.name)})`;
|
|
9718
10240
|
}
|
|
9719
10241
|
else {
|
|
9720
10242
|
return 'XMLPI()';
|
|
@@ -9729,7 +10251,7 @@ export class Deparser {
|
|
|
9729
10251
|
output.push('XMLELEMENT');
|
|
9730
10252
|
const elementParts = [];
|
|
9731
10253
|
if (node.name) {
|
|
9732
|
-
elementParts.push(`NAME ${QuoteUtils.
|
|
10254
|
+
elementParts.push(`NAME ${QuoteUtils.quoteIdentifier(node.name)}`);
|
|
9733
10255
|
}
|
|
9734
10256
|
if (node.named_args && node.named_args.length > 0) {
|
|
9735
10257
|
const namedArgStrs = ListUtils.unwrapList(node.named_args).map(arg => this.visit(arg, context));
|
|
@@ -9794,6 +10316,7 @@ export class Deparser {
|
|
|
9794
10316
|
rootParts.push('STANDALONE NO VALUE');
|
|
9795
10317
|
}
|
|
9796
10318
|
else if (standaloneArg.A_Const.ival.ival === 3) {
|
|
10319
|
+
// STANDALONE omitted
|
|
9797
10320
|
}
|
|
9798
10321
|
else if (Object.keys(standaloneArg.A_Const.ival).length === 0) {
|
|
9799
10322
|
rootParts.push('STANDALONE YES');
|
|
@@ -9829,7 +10352,7 @@ export class Deparser {
|
|
|
9829
10352
|
// Handle name and args for operations that don't have special handling
|
|
9830
10353
|
if (node.op !== 'IS_XMLELEMENT' && node.op !== 'IS_XMLPARSE' && node.op !== 'IS_XMLROOT' && node.op !== 'IS_DOCUMENT') {
|
|
9831
10354
|
if (node.name) {
|
|
9832
|
-
const quotedName = QuoteUtils.
|
|
10355
|
+
const quotedName = QuoteUtils.quoteIdentifier(node.name);
|
|
9833
10356
|
output.push(`NAME ${quotedName}`);
|
|
9834
10357
|
}
|
|
9835
10358
|
if (node.args && node.args.length > 0) {
|
|
@@ -9850,26 +10373,26 @@ export class Deparser {
|
|
|
9850
10373
|
}
|
|
9851
10374
|
schemaname(node, context) {
|
|
9852
10375
|
if (typeof node === 'string') {
|
|
9853
|
-
return QuoteUtils.
|
|
10376
|
+
return QuoteUtils.quoteIdentifier(node);
|
|
9854
10377
|
}
|
|
9855
10378
|
if (node && node.String && node.String.sval) {
|
|
9856
|
-
return QuoteUtils.
|
|
10379
|
+
return QuoteUtils.quoteIdentifier(node.String.sval);
|
|
9857
10380
|
}
|
|
9858
10381
|
// Handle other node types without recursion
|
|
9859
10382
|
if (node && typeof node === 'object') {
|
|
9860
10383
|
if (node.sval !== undefined) {
|
|
9861
|
-
return QuoteUtils.
|
|
10384
|
+
return QuoteUtils.quoteIdentifier(node.sval);
|
|
9862
10385
|
}
|
|
9863
10386
|
// Handle List nodes that might contain schema names
|
|
9864
10387
|
if (node.List && Array.isArray(node.List.items)) {
|
|
9865
10388
|
const items = node.List.items;
|
|
9866
10389
|
if (items.length > 0 && items[0].String && items[0].String.sval) {
|
|
9867
|
-
return QuoteUtils.
|
|
10390
|
+
return QuoteUtils.quoteIdentifier(items[0].String.sval);
|
|
9868
10391
|
}
|
|
9869
10392
|
}
|
|
9870
10393
|
// For other complex nodes, try to extract string value without recursion
|
|
9871
10394
|
if (node.val !== undefined) {
|
|
9872
|
-
return QuoteUtils.
|
|
10395
|
+
return QuoteUtils.quoteIdentifier(node.val);
|
|
9873
10396
|
}
|
|
9874
10397
|
return '';
|
|
9875
10398
|
}
|
|
@@ -9932,7 +10455,7 @@ export class Deparser {
|
|
|
9932
10455
|
}
|
|
9933
10456
|
output.push('RULE');
|
|
9934
10457
|
if (node.rulename) {
|
|
9935
|
-
output.push(QuoteUtils.
|
|
10458
|
+
output.push(QuoteUtils.quoteIdentifier(node.rulename));
|
|
9936
10459
|
}
|
|
9937
10460
|
output.push('AS ON');
|
|
9938
10461
|
if (node.event) {
|
|
@@ -9999,42 +10522,42 @@ export class Deparser {
|
|
|
9999
10522
|
}
|
|
10000
10523
|
relname(node, context) {
|
|
10001
10524
|
if (typeof node === 'string') {
|
|
10002
|
-
return QuoteUtils.
|
|
10525
|
+
return QuoteUtils.quoteIdentifier(node);
|
|
10003
10526
|
}
|
|
10004
10527
|
if (node && node.String && node.String.sval) {
|
|
10005
|
-
return QuoteUtils.
|
|
10528
|
+
return QuoteUtils.quoteIdentifier(node.String.sval);
|
|
10006
10529
|
}
|
|
10007
10530
|
if (node && typeof node === 'object' && node.relname) {
|
|
10008
|
-
return QuoteUtils.
|
|
10531
|
+
return QuoteUtils.quoteIdentifier(node.relname);
|
|
10009
10532
|
}
|
|
10010
10533
|
return this.visit(node, context);
|
|
10011
10534
|
}
|
|
10012
10535
|
rel(node, context) {
|
|
10013
10536
|
if (typeof node === 'string') {
|
|
10014
|
-
return QuoteUtils.
|
|
10537
|
+
return QuoteUtils.quoteIdentifier(node);
|
|
10015
10538
|
}
|
|
10016
10539
|
if (node && node.String && node.String.sval) {
|
|
10017
|
-
return QuoteUtils.
|
|
10540
|
+
return QuoteUtils.quoteIdentifier(node.String.sval);
|
|
10018
10541
|
}
|
|
10019
10542
|
if (node && node.RangeVar) {
|
|
10020
10543
|
return this.RangeVar(node.RangeVar, context);
|
|
10021
10544
|
}
|
|
10022
10545
|
if (node && typeof node === 'object' && node.relname) {
|
|
10023
|
-
return QuoteUtils.
|
|
10546
|
+
return QuoteUtils.quoteIdentifier(node.relname);
|
|
10024
10547
|
}
|
|
10025
10548
|
return this.visit(node, context);
|
|
10026
10549
|
}
|
|
10027
10550
|
objname(node, context) {
|
|
10028
10551
|
if (typeof node === 'string') {
|
|
10029
|
-
return QuoteUtils.
|
|
10552
|
+
return QuoteUtils.quoteIdentifier(node);
|
|
10030
10553
|
}
|
|
10031
10554
|
if (node && node.String && node.String.sval) {
|
|
10032
|
-
return QuoteUtils.
|
|
10555
|
+
return QuoteUtils.quoteIdentifier(node.String.sval);
|
|
10033
10556
|
}
|
|
10034
10557
|
if (Array.isArray(node)) {
|
|
10035
10558
|
const parts = node.map(part => {
|
|
10036
10559
|
if (part && part.String && part.String.sval) {
|
|
10037
|
-
return QuoteUtils.
|
|
10560
|
+
return QuoteUtils.quoteIdentifier(part.String.sval);
|
|
10038
10561
|
}
|
|
10039
10562
|
return this.visit(part, context);
|
|
10040
10563
|
});
|
|
@@ -10105,7 +10628,7 @@ export class Deparser {
|
|
|
10105
10628
|
CurrentOfExpr(node, context) {
|
|
10106
10629
|
const output = ['CURRENT OF'];
|
|
10107
10630
|
if (node.cursor_name) {
|
|
10108
|
-
output.push(QuoteUtils.
|
|
10631
|
+
output.push(QuoteUtils.quoteIdentifier(node.cursor_name));
|
|
10109
10632
|
}
|
|
10110
10633
|
if (node.cursor_param > 0) {
|
|
10111
10634
|
output.push(`$${node.cursor_param}`);
|
|
@@ -10168,66 +10691,12 @@ export class Deparser {
|
|
|
10168
10691
|
}
|
|
10169
10692
|
AlterObjectSchemaStmt(node, context) {
|
|
10170
10693
|
const output = ['ALTER'];
|
|
10171
|
-
|
|
10172
|
-
|
|
10173
|
-
|
|
10174
|
-
|
|
10175
|
-
|
|
10176
|
-
|
|
10177
|
-
break;
|
|
10178
|
-
case 'OBJECT_FUNCTION':
|
|
10179
|
-
output.push('FUNCTION');
|
|
10180
|
-
break;
|
|
10181
|
-
case 'OBJECT_TYPE':
|
|
10182
|
-
output.push('TYPE');
|
|
10183
|
-
break;
|
|
10184
|
-
case 'OBJECT_DOMAIN':
|
|
10185
|
-
output.push('DOMAIN');
|
|
10186
|
-
break;
|
|
10187
|
-
case 'OBJECT_SEQUENCE':
|
|
10188
|
-
output.push('SEQUENCE');
|
|
10189
|
-
break;
|
|
10190
|
-
case 'OBJECT_OPCLASS':
|
|
10191
|
-
output.push('OPERATOR CLASS');
|
|
10192
|
-
break;
|
|
10193
|
-
case 'OBJECT_OPFAMILY':
|
|
10194
|
-
output.push('OPERATOR FAMILY');
|
|
10195
|
-
break;
|
|
10196
|
-
case 'OBJECT_OPERATOR':
|
|
10197
|
-
output.push('OPERATOR');
|
|
10198
|
-
break;
|
|
10199
|
-
case 'OBJECT_TYPE':
|
|
10200
|
-
output.push('TYPE');
|
|
10201
|
-
break;
|
|
10202
|
-
case 'OBJECT_COLLATION':
|
|
10203
|
-
output.push('COLLATION');
|
|
10204
|
-
break;
|
|
10205
|
-
case 'OBJECT_CONVERSION':
|
|
10206
|
-
output.push('CONVERSION');
|
|
10207
|
-
break;
|
|
10208
|
-
case 'OBJECT_TSPARSER':
|
|
10209
|
-
output.push('TEXT SEARCH PARSER');
|
|
10210
|
-
break;
|
|
10211
|
-
case 'OBJECT_TSCONFIGURATION':
|
|
10212
|
-
output.push('TEXT SEARCH CONFIGURATION');
|
|
10213
|
-
break;
|
|
10214
|
-
case 'OBJECT_TSTEMPLATE':
|
|
10215
|
-
output.push('TEXT SEARCH TEMPLATE');
|
|
10216
|
-
break;
|
|
10217
|
-
case 'OBJECT_TSDICTIONARY':
|
|
10218
|
-
output.push('TEXT SEARCH DICTIONARY');
|
|
10219
|
-
break;
|
|
10220
|
-
case 'OBJECT_AGGREGATE':
|
|
10221
|
-
output.push('AGGREGATE');
|
|
10222
|
-
break;
|
|
10223
|
-
case 'OBJECT_FOREIGN_TABLE':
|
|
10224
|
-
output.push('FOREIGN TABLE');
|
|
10225
|
-
break;
|
|
10226
|
-
case 'OBJECT_MATVIEW':
|
|
10227
|
-
output.push('MATERIALIZED VIEW');
|
|
10228
|
-
break;
|
|
10229
|
-
default:
|
|
10230
|
-
output.push(node.objectType.toString());
|
|
10694
|
+
try {
|
|
10695
|
+
output.push(this.getObjectTypeKeyword(node.objectType));
|
|
10696
|
+
}
|
|
10697
|
+
catch {
|
|
10698
|
+
// Fallback to objectType string if not supported
|
|
10699
|
+
output.push(node.objectType.toString());
|
|
10231
10700
|
}
|
|
10232
10701
|
if (node.missing_ok) {
|
|
10233
10702
|
output.push('IF EXISTS');
|
|
@@ -10242,7 +10711,7 @@ export class Deparser {
|
|
|
10242
10711
|
if (items.length === 2) {
|
|
10243
10712
|
const schemaName = items[0].String?.sval || '';
|
|
10244
10713
|
const domainName = items[1].String?.sval || '';
|
|
10245
|
-
output.push(
|
|
10714
|
+
output.push(QuoteUtils.quoteQualifiedIdentifier(schemaName, domainName));
|
|
10246
10715
|
}
|
|
10247
10716
|
else {
|
|
10248
10717
|
output.push(this.visit(node.object, context));
|
|
@@ -10254,7 +10723,7 @@ export class Deparser {
|
|
|
10254
10723
|
if (items.length === 2) {
|
|
10255
10724
|
const schemaName = items[0].String?.sval || '';
|
|
10256
10725
|
const typeName = items[1].String?.sval || '';
|
|
10257
|
-
output.push(
|
|
10726
|
+
output.push(QuoteUtils.quoteQualifiedIdentifier(schemaName, typeName));
|
|
10258
10727
|
}
|
|
10259
10728
|
else {
|
|
10260
10729
|
output.push(this.visit(node.object, context));
|
|
@@ -10266,7 +10735,7 @@ export class Deparser {
|
|
|
10266
10735
|
if (items.length === 2) {
|
|
10267
10736
|
const schemaName = items[0].String?.sval || '';
|
|
10268
10737
|
const conversionName = items[1].String?.sval || '';
|
|
10269
|
-
output.push(
|
|
10738
|
+
output.push(QuoteUtils.quoteQualifiedIdentifier(schemaName, conversionName));
|
|
10270
10739
|
}
|
|
10271
10740
|
else {
|
|
10272
10741
|
output.push(this.visit(node.object, context));
|
|
@@ -10278,7 +10747,7 @@ export class Deparser {
|
|
|
10278
10747
|
if (items.length === 2) {
|
|
10279
10748
|
const schemaName = items[0].String?.sval || '';
|
|
10280
10749
|
const parserName = items[1].String?.sval || '';
|
|
10281
|
-
output.push(
|
|
10750
|
+
output.push(QuoteUtils.quoteQualifiedIdentifier(schemaName, parserName));
|
|
10282
10751
|
}
|
|
10283
10752
|
else {
|
|
10284
10753
|
output.push(this.visit(node.object, context));
|
|
@@ -10290,7 +10759,7 @@ export class Deparser {
|
|
|
10290
10759
|
if (items.length === 2) {
|
|
10291
10760
|
const schemaName = items[0].String?.sval || '';
|
|
10292
10761
|
const configName = items[1].String?.sval || '';
|
|
10293
|
-
output.push(
|
|
10762
|
+
output.push(QuoteUtils.quoteQualifiedIdentifier(schemaName, configName));
|
|
10294
10763
|
}
|
|
10295
10764
|
else {
|
|
10296
10765
|
output.push(this.visit(node.object, context));
|
|
@@ -10302,7 +10771,7 @@ export class Deparser {
|
|
|
10302
10771
|
if (items.length === 2) {
|
|
10303
10772
|
const schemaName = items[0].String?.sval || '';
|
|
10304
10773
|
const templateName = items[1].String?.sval || '';
|
|
10305
|
-
output.push(
|
|
10774
|
+
output.push(QuoteUtils.quoteQualifiedIdentifier(schemaName, templateName));
|
|
10306
10775
|
}
|
|
10307
10776
|
else {
|
|
10308
10777
|
output.push(this.visit(node.object, context));
|
|
@@ -10314,7 +10783,7 @@ export class Deparser {
|
|
|
10314
10783
|
if (items.length === 2) {
|
|
10315
10784
|
const schemaName = items[0].String?.sval || '';
|
|
10316
10785
|
const dictionaryName = items[1].String?.sval || '';
|
|
10317
|
-
output.push(
|
|
10786
|
+
output.push(QuoteUtils.quoteQualifiedIdentifier(schemaName, dictionaryName));
|
|
10318
10787
|
}
|
|
10319
10788
|
else {
|
|
10320
10789
|
output.push(this.visit(node.object, context));
|
|
@@ -10326,13 +10795,13 @@ export class Deparser {
|
|
|
10326
10795
|
if (items.length === 2) {
|
|
10327
10796
|
const accessMethod = items[0].String?.sval || '';
|
|
10328
10797
|
const opClassName = items[1].String?.sval || '';
|
|
10329
|
-
output.push(`${QuoteUtils.
|
|
10798
|
+
output.push(`${QuoteUtils.quoteIdentifier(opClassName)} USING ${accessMethod}`);
|
|
10330
10799
|
}
|
|
10331
10800
|
else if (items.length === 3) {
|
|
10332
10801
|
const accessMethod = items[0].String?.sval || '';
|
|
10333
10802
|
const schemaName = items[1].String?.sval || '';
|
|
10334
10803
|
const opClassName = items[2].String?.sval || '';
|
|
10335
|
-
output.push(`${QuoteUtils.
|
|
10804
|
+
output.push(`${QuoteUtils.quoteQualifiedIdentifier(schemaName, opClassName)} USING ${accessMethod}`);
|
|
10336
10805
|
}
|
|
10337
10806
|
else {
|
|
10338
10807
|
output.push(this.visit(node.object, context));
|
|
@@ -10344,13 +10813,13 @@ export class Deparser {
|
|
|
10344
10813
|
if (items.length === 2) {
|
|
10345
10814
|
const accessMethod = items[0].String?.sval || '';
|
|
10346
10815
|
const opFamilyName = items[1].String?.sval || '';
|
|
10347
|
-
output.push(`${QuoteUtils.
|
|
10816
|
+
output.push(`${QuoteUtils.quoteIdentifier(opFamilyName)} USING ${accessMethod}`);
|
|
10348
10817
|
}
|
|
10349
10818
|
else if (items.length === 3) {
|
|
10350
10819
|
const accessMethod = items[0].String?.sval || '';
|
|
10351
10820
|
const schemaName = items[1].String?.sval || '';
|
|
10352
10821
|
const opFamilyName = items[2].String?.sval || '';
|
|
10353
|
-
output.push(`${QuoteUtils.
|
|
10822
|
+
output.push(`${QuoteUtils.quoteQualifiedIdentifier(schemaName, opFamilyName)} USING ${accessMethod}`);
|
|
10354
10823
|
}
|
|
10355
10824
|
else {
|
|
10356
10825
|
output.push(this.visit(node.object, context));
|
|
@@ -10362,7 +10831,7 @@ export class Deparser {
|
|
|
10362
10831
|
}
|
|
10363
10832
|
output.push('SET SCHEMA');
|
|
10364
10833
|
if (node.newschema) {
|
|
10365
|
-
output.push(QuoteUtils.
|
|
10834
|
+
output.push(QuoteUtils.quoteIdentifier(node.newschema));
|
|
10366
10835
|
}
|
|
10367
10836
|
return output.join(' ');
|
|
10368
10837
|
}
|
|
@@ -10431,7 +10900,7 @@ export class Deparser {
|
|
|
10431
10900
|
}
|
|
10432
10901
|
if (node.servername) {
|
|
10433
10902
|
output.push('SERVER');
|
|
10434
|
-
output.push(QuoteUtils.
|
|
10903
|
+
output.push(QuoteUtils.quoteIdentifier(node.servername));
|
|
10435
10904
|
}
|
|
10436
10905
|
if (node.options && node.options.length > 0) {
|
|
10437
10906
|
const foreignTableContext = context.spawn('CreateForeignTableStmt');
|
|
@@ -10440,8 +10909,4 @@ export class Deparser {
|
|
|
10440
10909
|
}
|
|
10441
10910
|
return output.join(' ');
|
|
10442
10911
|
}
|
|
10443
|
-
containsMultilineStringLiteral(content) {
|
|
10444
|
-
const stringLiteralRegex = /'[^']*\n[^']*'/g;
|
|
10445
|
-
return stringLiteralRegex.test(content);
|
|
10446
|
-
}
|
|
10447
10912
|
}
|