pgsql-deparser 17.18.5 → 17.19.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 +9 -9
- package/deparser/deparser.d.ts +311 -0
- package/{deparser.js → deparser/deparser.js} +941 -586
- package/deparser/index.d.ts +11 -0
- package/deparser/index.js +21 -0
- package/{utils → deparser/utils}/list-utils.d.ts +4 -0
- package/{utils → deparser/utils}/list-utils.js +4 -0
- package/deparser/utils/sql-formatter.d.ts +24 -0
- package/deparser/utils/sql-formatter.js +143 -0
- package/{visitors → deparser/visitors}/base.d.ts +8 -5
- package/{visitors → deparser/visitors}/base.js +4 -0
- package/esm/{deparser.js → deparser/deparser.js} +942 -587
- package/esm/deparser/index.js +15 -0
- package/esm/{utils → deparser/utils}/list-utils.js +4 -0
- package/esm/deparser/utils/sql-formatter.js +138 -0
- package/esm/{visitors → deparser/visitors}/base.js +4 -0
- package/esm/index.js +23 -9
- package/esm/v17-to-v18-direct.js +43 -0
- package/esm/v17-to-v18.js +209 -0
- package/index.d.ts +15 -5
- package/index.js +27 -10
- package/package.json +14 -36
- package/v17-to-v18-direct.d.ts +21 -0
- package/v17-to-v18-direct.js +47 -0
- package/v17-to-v18.d.ts +55 -0
- package/v17-to-v18.js +213 -0
- package/deparser.d.ts +0 -305
- package/esm/utils/sql-formatter.js +0 -32
- package/utils/sql-formatter.d.ts +0 -12
- package/utils/sql-formatter.js +0 -36
|
@@ -1,10 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Auto-generated file with types stripped for better tree-shaking
|
|
4
|
+
* DO NOT EDIT - Generated by strip-deparser-types.ts
|
|
5
|
+
*/
|
|
2
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
7
|
exports.Deparser = void 0;
|
|
4
|
-
const base_1 = require("./visitors/base");
|
|
5
|
-
const sql_formatter_1 = require("./utils/sql-formatter");
|
|
6
8
|
const quotes_1 = require("@pgsql/quotes");
|
|
7
9
|
const list_utils_1 = require("./utils/list-utils");
|
|
10
|
+
const sql_formatter_1 = require("./utils/sql-formatter");
|
|
11
|
+
const base_1 = require("./visitors/base");
|
|
12
|
+
// WindowDef.frameOptions bit flags (src/include/nodes/parsenodes.h)
|
|
13
|
+
const FRAMEOPTION_NONDEFAULT = 0x00001;
|
|
14
|
+
const FRAMEOPTION_RANGE = 0x00002;
|
|
15
|
+
const FRAMEOPTION_ROWS = 0x00004;
|
|
16
|
+
const FRAMEOPTION_GROUPS = 0x00008;
|
|
17
|
+
const FRAMEOPTION_BETWEEN = 0x00010;
|
|
18
|
+
const FRAMEOPTION_START_UNBOUNDED_PRECEDING = 0x00020;
|
|
19
|
+
const FRAMEOPTION_END_UNBOUNDED_PRECEDING = 0x00040;
|
|
20
|
+
const FRAMEOPTION_START_UNBOUNDED_FOLLOWING = 0x00080;
|
|
21
|
+
const FRAMEOPTION_END_UNBOUNDED_FOLLOWING = 0x00100;
|
|
22
|
+
const FRAMEOPTION_START_CURRENT_ROW = 0x00200;
|
|
23
|
+
const FRAMEOPTION_END_CURRENT_ROW = 0x00400;
|
|
24
|
+
const FRAMEOPTION_START_OFFSET_PRECEDING = 0x00800;
|
|
25
|
+
const FRAMEOPTION_END_OFFSET_PRECEDING = 0x01000;
|
|
26
|
+
const FRAMEOPTION_START_OFFSET_FOLLOWING = 0x02000;
|
|
27
|
+
const FRAMEOPTION_END_OFFSET_FOLLOWING = 0x04000;
|
|
28
|
+
const FRAMEOPTION_EXCLUDE_CURRENT_ROW = 0x08000;
|
|
29
|
+
const FRAMEOPTION_EXCLUDE_GROUP = 0x10000;
|
|
30
|
+
const FRAMEOPTION_EXCLUDE_TIES = 0x20000;
|
|
8
31
|
/**
|
|
9
32
|
* List of real PostgreSQL built-in types as they appear in pg_catalog.pg_type.typname.
|
|
10
33
|
* These are stored in lowercase in PostgreSQL system catalogs.
|
|
@@ -103,6 +126,36 @@ function isWrappedParseResult(obj) {
|
|
|
103
126
|
* The deparser automatically detects bare ParseResult objects for backward
|
|
104
127
|
* compatibility and wraps them internally for consistent processing.
|
|
105
128
|
*/
|
|
129
|
+
function formatBitString(bsval) {
|
|
130
|
+
const quote = (value) => value.replace(/'/g, "''");
|
|
131
|
+
if (/^x[0-9A-Fa-f]*$/.test(bsval)) {
|
|
132
|
+
return `x'${bsval.substring(1)}'`;
|
|
133
|
+
}
|
|
134
|
+
if (bsval.startsWith('b')) {
|
|
135
|
+
return `b'${quote(bsval.substring(1))}'`;
|
|
136
|
+
}
|
|
137
|
+
return `b'${quote(bsval)}'`;
|
|
138
|
+
}
|
|
139
|
+
// A dollar-quoted body ends at the first occurrence of its tag, including one
|
|
140
|
+
// formed by the body's trailing characters plus the closing tag (`...$` + `$$`).
|
|
141
|
+
function dollarTagConflicts(body, tag) {
|
|
142
|
+
return (body + tag).indexOf(tag) < body.length;
|
|
143
|
+
}
|
|
144
|
+
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)*)?)$/;
|
|
145
|
+
function formatInteger(ival) {
|
|
146
|
+
const value = String(ival);
|
|
147
|
+
if (!/^[+-]?\d+$/.test(value)) {
|
|
148
|
+
throw new Error(`Invalid integer literal: ${value}`);
|
|
149
|
+
}
|
|
150
|
+
return value;
|
|
151
|
+
}
|
|
152
|
+
function formatNumeric(fval) {
|
|
153
|
+
const value = String(fval);
|
|
154
|
+
if (!NUMERIC_LITERAL.test(value)) {
|
|
155
|
+
throw new Error(`Invalid numeric literal: ${value}`);
|
|
156
|
+
}
|
|
157
|
+
return value;
|
|
158
|
+
}
|
|
106
159
|
class Deparser {
|
|
107
160
|
tree;
|
|
108
161
|
options;
|
|
@@ -162,10 +215,19 @@ class Deparser {
|
|
|
162
215
|
*/
|
|
163
216
|
getFunctionDelimiter(body) {
|
|
164
217
|
const delimiter = this.options.functionDelimiter || '$$';
|
|
165
|
-
if (body
|
|
166
|
-
return
|
|
218
|
+
if (!dollarTagConflicts(body, delimiter)) {
|
|
219
|
+
return delimiter;
|
|
220
|
+
}
|
|
221
|
+
const fallback = this.options.functionDelimiterFallback || '$EOFCODE$';
|
|
222
|
+
if (!dollarTagConflicts(body, fallback)) {
|
|
223
|
+
return fallback;
|
|
224
|
+
}
|
|
225
|
+
const base = fallback.slice(0, -1);
|
|
226
|
+
let counter = 1;
|
|
227
|
+
while (dollarTagConflicts(body, `${base}${counter}$`)) {
|
|
228
|
+
counter++;
|
|
167
229
|
}
|
|
168
|
-
return
|
|
230
|
+
return `${base}${counter}$`;
|
|
169
231
|
}
|
|
170
232
|
/**
|
|
171
233
|
* Maps ObjectType enum values to their corresponding SQL keywords
|
|
@@ -368,16 +430,16 @@ class Deparser {
|
|
|
368
430
|
const leftStmt = this.SelectStmt(node.larg, context);
|
|
369
431
|
const rightStmt = this.SelectStmt(node.rarg, context);
|
|
370
432
|
// Add parentheses if the operand is a set operation OR has ORDER BY/LIMIT clauses OR has WITH clause
|
|
371
|
-
const leftNeedsParens = node.larg && ((node.larg.op && node.larg.op !== 'SETOP_NONE') ||
|
|
372
|
-
node.larg.sortClause ||
|
|
373
|
-
node.larg.limitCount ||
|
|
374
|
-
node.larg.limitOffset ||
|
|
375
|
-
node.larg.withClause);
|
|
376
|
-
const rightNeedsParens = node.rarg && ((node.rarg.op && node.rarg.op !== 'SETOP_NONE') ||
|
|
377
|
-
node.rarg.sortClause ||
|
|
378
|
-
node.rarg.limitCount ||
|
|
379
|
-
node.rarg.limitOffset ||
|
|
380
|
-
node.rarg.withClause);
|
|
433
|
+
const leftNeedsParens = node.larg && (((node.larg).op && (node.larg).op !== 'SETOP_NONE') ||
|
|
434
|
+
(node.larg).sortClause ||
|
|
435
|
+
(node.larg).limitCount ||
|
|
436
|
+
(node.larg).limitOffset ||
|
|
437
|
+
(node.larg).withClause);
|
|
438
|
+
const rightNeedsParens = node.rarg && (((node.rarg).op && (node.rarg).op !== 'SETOP_NONE') ||
|
|
439
|
+
(node.rarg).sortClause ||
|
|
440
|
+
(node.rarg).limitCount ||
|
|
441
|
+
(node.rarg).limitOffset ||
|
|
442
|
+
(node.rarg).withClause);
|
|
381
443
|
if (leftNeedsParens) {
|
|
382
444
|
output.push(context.parens(leftStmt));
|
|
383
445
|
}
|
|
@@ -442,12 +504,7 @@ class Deparser {
|
|
|
442
504
|
// Check if single target is complex - if so, use multiline format
|
|
443
505
|
if (this.isComplexSelectTarget(targetNode)) {
|
|
444
506
|
output.push('SELECT' + distinctPart);
|
|
445
|
-
|
|
446
|
-
output.push(target);
|
|
447
|
-
}
|
|
448
|
-
else {
|
|
449
|
-
output.push(context.indent(target));
|
|
450
|
-
}
|
|
507
|
+
output.push(context.indent(target));
|
|
451
508
|
}
|
|
452
509
|
else {
|
|
453
510
|
output.push('SELECT' + distinctPart + ' ' + target);
|
|
@@ -457,9 +514,6 @@ class Deparser {
|
|
|
457
514
|
const targetStrings = targetList
|
|
458
515
|
.map(e => {
|
|
459
516
|
const targetStr = this.visit(e, context.spawn('SelectStmt', { select: true }));
|
|
460
|
-
if (this.containsMultilineStringLiteral(targetStr)) {
|
|
461
|
-
return targetStr;
|
|
462
|
-
}
|
|
463
517
|
return context.indent(targetStr);
|
|
464
518
|
});
|
|
465
519
|
const formattedTargets = targetStrings.join(',' + context.newline());
|
|
@@ -511,9 +565,6 @@ class Deparser {
|
|
|
511
565
|
return context.parens(values.join(', '));
|
|
512
566
|
});
|
|
513
567
|
const indentedTuples = lists.map(tuple => {
|
|
514
|
-
if (this.containsMultilineStringLiteral(tuple)) {
|
|
515
|
-
return tuple;
|
|
516
|
-
}
|
|
517
568
|
return context.indent(tuple);
|
|
518
569
|
});
|
|
519
570
|
output.push(indentedTuples.join(',\n'));
|
|
@@ -533,9 +584,6 @@ class Deparser {
|
|
|
533
584
|
const groupItems = groupList
|
|
534
585
|
.map(e => {
|
|
535
586
|
const groupStr = this.visit(e, context.spawn('SelectStmt', { group: true, indentLevel: context.indentLevel + 1 }));
|
|
536
|
-
if (this.containsMultilineStringLiteral(groupStr)) {
|
|
537
|
-
return groupStr;
|
|
538
|
-
}
|
|
539
587
|
return context.indent(groupStr);
|
|
540
588
|
})
|
|
541
589
|
.join(',' + context.newline());
|
|
@@ -554,12 +602,7 @@ class Deparser {
|
|
|
554
602
|
if (context.isPretty()) {
|
|
555
603
|
output.push('HAVING');
|
|
556
604
|
const havingStr = this.visit(node.havingClause, context);
|
|
557
|
-
|
|
558
|
-
output.push(havingStr);
|
|
559
|
-
}
|
|
560
|
-
else {
|
|
561
|
-
output.push(context.indent(havingStr));
|
|
562
|
-
}
|
|
605
|
+
output.push(context.indent(havingStr));
|
|
563
606
|
}
|
|
564
607
|
else {
|
|
565
608
|
output.push('HAVING');
|
|
@@ -580,9 +623,6 @@ class Deparser {
|
|
|
580
623
|
const sortItems = sortList
|
|
581
624
|
.map(e => {
|
|
582
625
|
const sortStr = this.visit(e, context.spawn('SelectStmt', { sort: true, indentLevel: context.indentLevel + 1 }));
|
|
583
|
-
if (this.containsMultilineStringLiteral(sortStr)) {
|
|
584
|
-
return sortStr;
|
|
585
|
-
}
|
|
586
626
|
return context.indent(sortStr);
|
|
587
627
|
})
|
|
588
628
|
.join(',' + context.newline());
|
|
@@ -846,15 +886,15 @@ class Deparser {
|
|
|
846
886
|
getOperatorPrecedence(operator) {
|
|
847
887
|
const precedence = {
|
|
848
888
|
'||': 1, // string concatenation
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
889
|
+
OR: 2, // logical OR
|
|
890
|
+
AND: 3, // logical AND
|
|
891
|
+
NOT: 4, // logical NOT
|
|
892
|
+
IS: 5, // IS NULL, IS NOT NULL, etc.
|
|
893
|
+
IN: 5, // IN, NOT IN
|
|
894
|
+
BETWEEN: 5, // BETWEEN, NOT BETWEEN
|
|
895
|
+
LIKE: 5, // LIKE, ILIKE, SIMILAR TO
|
|
896
|
+
ILIKE: 5,
|
|
897
|
+
SIMILAR: 5,
|
|
858
898
|
'<': 6, // comparison operators
|
|
859
899
|
'<=': 6,
|
|
860
900
|
'>': 6,
|
|
@@ -984,6 +1024,12 @@ class Deparser {
|
|
|
984
1024
|
output.push(context.parens(columnNames.join(', ')));
|
|
985
1025
|
}
|
|
986
1026
|
}
|
|
1027
|
+
if (node.override === 'OVERRIDING_USER_VALUE') {
|
|
1028
|
+
output.push('OVERRIDING USER VALUE');
|
|
1029
|
+
}
|
|
1030
|
+
else if (node.override === 'OVERRIDING_SYSTEM_VALUE') {
|
|
1031
|
+
output.push('OVERRIDING SYSTEM VALUE');
|
|
1032
|
+
}
|
|
987
1033
|
if (node.selectStmt) {
|
|
988
1034
|
output.push(this.visit(node.selectStmt, context));
|
|
989
1035
|
}
|
|
@@ -1029,7 +1075,7 @@ class Deparser {
|
|
|
1029
1075
|
if (context.isPretty()) {
|
|
1030
1076
|
// Put each assignment on its own line for pretty printing
|
|
1031
1077
|
const indentedTargets = targets.map(target => context.indent(target));
|
|
1032
|
-
output.
|
|
1078
|
+
output[output.length - 1] += '\n' + indentedTargets.join(',\n');
|
|
1033
1079
|
}
|
|
1034
1080
|
else {
|
|
1035
1081
|
output.push(targets.join(', '));
|
|
@@ -1045,11 +1091,8 @@ class Deparser {
|
|
|
1045
1091
|
output.push('DO NOTHING');
|
|
1046
1092
|
}
|
|
1047
1093
|
}
|
|
1048
|
-
if (node.
|
|
1049
|
-
output.push(
|
|
1050
|
-
const returningList = list_utils_1.ListUtils.unwrapList(node.returningList);
|
|
1051
|
-
const returns = returningList.map(ret => this.visit(ret, context));
|
|
1052
|
-
output.push(returns.join(', '));
|
|
1094
|
+
if (node.returningClause) {
|
|
1095
|
+
output.push(this.ReturningClause(node.returningClause, context));
|
|
1053
1096
|
}
|
|
1054
1097
|
return output.join(' ');
|
|
1055
1098
|
}
|
|
@@ -1063,38 +1106,8 @@ class Deparser {
|
|
|
1063
1106
|
output.push(this.RangeVar(node.relation, context));
|
|
1064
1107
|
}
|
|
1065
1108
|
output.push('SET');
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
const firstTarget = targetList[0];
|
|
1069
|
-
const processedTargets = new Set();
|
|
1070
|
-
const assignmentParts = [];
|
|
1071
|
-
for (let i = 0; i < targetList.length; i++) {
|
|
1072
|
-
if (processedTargets.has(i))
|
|
1073
|
-
continue;
|
|
1074
|
-
const target = targetList[i];
|
|
1075
|
-
const multiAssignRef = target.ResTarget?.val?.MultiAssignRef;
|
|
1076
|
-
if (multiAssignRef) {
|
|
1077
|
-
const relatedTargets = [];
|
|
1078
|
-
for (let j = i; j < targetList.length; j++) {
|
|
1079
|
-
const otherTarget = targetList[j];
|
|
1080
|
-
const otherMultiAssignRef = otherTarget.ResTarget?.val?.MultiAssignRef;
|
|
1081
|
-
if (otherMultiAssignRef &&
|
|
1082
|
-
JSON.stringify(otherMultiAssignRef.source) === JSON.stringify(multiAssignRef.source)) {
|
|
1083
|
-
relatedTargets.push(otherTarget);
|
|
1084
|
-
processedTargets.add(j);
|
|
1085
|
-
}
|
|
1086
|
-
}
|
|
1087
|
-
const names = relatedTargets.map(t => t.ResTarget.name);
|
|
1088
|
-
const multiAssignment = `${context.parens(names.join(', '))} = ${this.visit(multiAssignRef.source, context)}`;
|
|
1089
|
-
assignmentParts.push(multiAssignment);
|
|
1090
|
-
}
|
|
1091
|
-
else {
|
|
1092
|
-
// Handle regular single-column assignment
|
|
1093
|
-
assignmentParts.push(this.visit(target, context.spawn('UpdateStmt', { update: true })));
|
|
1094
|
-
processedTargets.add(i);
|
|
1095
|
-
}
|
|
1096
|
-
}
|
|
1097
|
-
output.push(assignmentParts.join(','));
|
|
1109
|
+
if (node.targetList && node.targetList.length > 0) {
|
|
1110
|
+
output.push(this.formatUpdateAssignments(node.targetList, context));
|
|
1098
1111
|
}
|
|
1099
1112
|
if (node.fromClause) {
|
|
1100
1113
|
output.push('FROM');
|
|
@@ -1106,12 +1119,41 @@ class Deparser {
|
|
|
1106
1119
|
output.push('WHERE');
|
|
1107
1120
|
output.push(this.visit(node.whereClause, context));
|
|
1108
1121
|
}
|
|
1109
|
-
if (node.
|
|
1110
|
-
output.push(
|
|
1111
|
-
output.push(this.deparseReturningList(node.returningList, context));
|
|
1122
|
+
if (node.returningClause) {
|
|
1123
|
+
output.push(this.ReturningClause(node.returningClause, context));
|
|
1112
1124
|
}
|
|
1113
1125
|
return output.join(' ');
|
|
1114
1126
|
}
|
|
1127
|
+
formatUpdateAssignments(targets, context) {
|
|
1128
|
+
const targetList = list_utils_1.ListUtils.unwrapList(targets);
|
|
1129
|
+
const processedTargets = new Set();
|
|
1130
|
+
const assignmentParts = [];
|
|
1131
|
+
for (let i = 0; i < targetList.length; i++) {
|
|
1132
|
+
if (processedTargets.has(i))
|
|
1133
|
+
continue;
|
|
1134
|
+
const target = targetList[i];
|
|
1135
|
+
const multiAssignRef = target.ResTarget?.val?.MultiAssignRef;
|
|
1136
|
+
if (multiAssignRef) {
|
|
1137
|
+
const relatedTargets = [];
|
|
1138
|
+
for (let j = i; j < targetList.length; j++) {
|
|
1139
|
+
const otherTarget = targetList[j];
|
|
1140
|
+
const otherMultiAssignRef = otherTarget.ResTarget?.val?.MultiAssignRef;
|
|
1141
|
+
if (otherMultiAssignRef &&
|
|
1142
|
+
JSON.stringify(otherMultiAssignRef.source) === JSON.stringify(multiAssignRef.source)) {
|
|
1143
|
+
relatedTargets.push(otherTarget);
|
|
1144
|
+
processedTargets.add(j);
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
const names = relatedTargets.map(t => quotes_1.QuoteUtils.quoteIdentifier(t.ResTarget.name));
|
|
1148
|
+
assignmentParts.push(`${context.parens(names.join(', '))} = ${this.visit(multiAssignRef.source, context)}`);
|
|
1149
|
+
}
|
|
1150
|
+
else {
|
|
1151
|
+
assignmentParts.push(this.visit(target, context.spawn('UpdateStmt', { update: true })));
|
|
1152
|
+
processedTargets.add(i);
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
return assignmentParts.join(', ');
|
|
1156
|
+
}
|
|
1115
1157
|
DeleteStmt(node, context) {
|
|
1116
1158
|
try {
|
|
1117
1159
|
const output = [];
|
|
@@ -1159,13 +1201,12 @@ class Deparser {
|
|
|
1159
1201
|
throw new Error(`Error deparsing DeleteStmt: ${error instanceof Error ? error.message : String(error)}`);
|
|
1160
1202
|
}
|
|
1161
1203
|
}
|
|
1162
|
-
if (node.
|
|
1163
|
-
output.push('RETURNING');
|
|
1204
|
+
if (node.returningClause) {
|
|
1164
1205
|
try {
|
|
1165
|
-
output.push(this.
|
|
1206
|
+
output.push(this.ReturningClause(node.returningClause, context));
|
|
1166
1207
|
}
|
|
1167
1208
|
catch (error) {
|
|
1168
|
-
console.warn(`Error processing
|
|
1209
|
+
console.warn(`Error processing returningClause in DeleteStmt: ${error instanceof Error ? error.message : String(error)}`);
|
|
1169
1210
|
throw new Error(`Error deparsing DeleteStmt: ${error instanceof Error ? error.message : String(error)}`);
|
|
1170
1211
|
}
|
|
1171
1212
|
}
|
|
@@ -1186,9 +1227,6 @@ class Deparser {
|
|
|
1186
1227
|
const cteStrings = ctes.map((cte, index) => {
|
|
1187
1228
|
const cteStr = this.visit(cte, context);
|
|
1188
1229
|
const prefix = index === 0 ? context.newline() : ',' + context.newline();
|
|
1189
|
-
if (this.containsMultilineStringLiteral(cteStr)) {
|
|
1190
|
-
return prefix + cteStr;
|
|
1191
|
-
}
|
|
1192
1230
|
return prefix + context.indent(cteStr);
|
|
1193
1231
|
});
|
|
1194
1232
|
output.push(cteStrings.join(''));
|
|
@@ -1243,6 +1281,48 @@ class Deparser {
|
|
|
1243
1281
|
}
|
|
1244
1282
|
return output.join(' ');
|
|
1245
1283
|
}
|
|
1284
|
+
ATAlterConstraint(node, context) {
|
|
1285
|
+
const output = ['ALTER CONSTRAINT'];
|
|
1286
|
+
if (node.conname) {
|
|
1287
|
+
output.push(quotes_1.QuoteUtils.quoteIdentifier(node.conname));
|
|
1288
|
+
}
|
|
1289
|
+
if (node.alterEnforceability) {
|
|
1290
|
+
output.push(node.is_enforced ? 'ENFORCED' : 'NOT ENFORCED');
|
|
1291
|
+
}
|
|
1292
|
+
if (node.alterDeferrability) {
|
|
1293
|
+
output.push(node.deferrable ? 'DEFERRABLE' : 'NOT DEFERRABLE');
|
|
1294
|
+
if (node.initdeferred) {
|
|
1295
|
+
output.push('INITIALLY DEFERRED');
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
if (node.alterInheritability) {
|
|
1299
|
+
output.push(node.noinherit ? 'NO INHERIT' : 'INHERIT');
|
|
1300
|
+
}
|
|
1301
|
+
return output.join(' ');
|
|
1302
|
+
}
|
|
1303
|
+
deparseKeyAttrs(attrs, withPeriod, context) {
|
|
1304
|
+
const items = list_utils_1.ListUtils.unwrapList(attrs).map(attr => this.visit(attr, context));
|
|
1305
|
+
if (withPeriod && items.length > 0) {
|
|
1306
|
+
items[items.length - 1] = `PERIOD ${items[items.length - 1]}`;
|
|
1307
|
+
}
|
|
1308
|
+
return items.join(', ');
|
|
1309
|
+
}
|
|
1310
|
+
ReturningClause(node, context) {
|
|
1311
|
+
const output = ['RETURNING'];
|
|
1312
|
+
if (node.options && node.options.length > 0) {
|
|
1313
|
+
const options = list_utils_1.ListUtils.unwrapList(node.options)
|
|
1314
|
+
.map(option => this.visit(option, context));
|
|
1315
|
+
output.push(`WITH (${options.join(', ')})`);
|
|
1316
|
+
}
|
|
1317
|
+
if (node.exprs && node.exprs.length > 0) {
|
|
1318
|
+
output.push(this.deparseReturningList(node.exprs, context));
|
|
1319
|
+
}
|
|
1320
|
+
return output.join(' ');
|
|
1321
|
+
}
|
|
1322
|
+
ReturningOption(node, context) {
|
|
1323
|
+
const keyword = node.option === 'RETURNING_OPTION_NEW' ? 'NEW' : 'OLD';
|
|
1324
|
+
return `${keyword} AS ${quotes_1.QuoteUtils.quoteIdentifier(node.value)}`;
|
|
1325
|
+
}
|
|
1246
1326
|
deparseReturningList(list, context) {
|
|
1247
1327
|
return list_utils_1.ListUtils.unwrapList(list)
|
|
1248
1328
|
.filter(item => item != null && this.getNodeType(item) !== 'undefined')
|
|
@@ -1321,7 +1401,9 @@ class Deparser {
|
|
|
1321
1401
|
const source = this.visit(args[1], context);
|
|
1322
1402
|
// EXTRACT requires an unquoted uppercase keyword (EPOCH, YEAR, etc.)
|
|
1323
1403
|
// but A_Const sval deparsing wraps it in single quotes — strip and uppercase
|
|
1324
|
-
|
|
1404
|
+
// only when it is spelled the way the bare-keyword form parses back
|
|
1405
|
+
if (/^'(?:year|month|day|hour|minute|second)'$/.test(field)
|
|
1406
|
+
|| (/^'[a-z_][a-z0-9_]*'$/.test(field) && (0, quotes_1.keywordKindOf)(field.slice(1, -1)) === 'NO_KEYWORD')) {
|
|
1325
1407
|
field = field.slice(1, -1).toUpperCase();
|
|
1326
1408
|
}
|
|
1327
1409
|
return `EXTRACT(${field} FROM ${source})`;
|
|
@@ -1483,43 +1565,41 @@ class Deparser {
|
|
|
1483
1565
|
result += ` FILTER (WHERE ${this.visit(node.agg_filter, context)})`;
|
|
1484
1566
|
}
|
|
1485
1567
|
if (node.over) {
|
|
1486
|
-
|
|
1487
|
-
if (node.over.name) {
|
|
1488
|
-
result += ` OVER ${node.over.name}`;
|
|
1489
|
-
}
|
|
1490
|
-
else {
|
|
1491
|
-
const windowParts = [];
|
|
1492
|
-
if (node.over.partitionClause) {
|
|
1493
|
-
const partitions = list_utils_1.ListUtils.unwrapList(node.over.partitionClause);
|
|
1494
|
-
const partitionStrs = partitions.map(p => this.visit(p, context));
|
|
1495
|
-
windowParts.push(`PARTITION BY ${partitionStrs.join(', ')}`);
|
|
1496
|
-
}
|
|
1497
|
-
if (node.over.orderClause) {
|
|
1498
|
-
const orders = list_utils_1.ListUtils.unwrapList(node.over.orderClause);
|
|
1499
|
-
const orderStrs = orders.map(o => this.visit(o, context));
|
|
1500
|
-
windowParts.push(`ORDER BY ${orderStrs.join(', ')}`);
|
|
1501
|
-
}
|
|
1502
|
-
// Handle window frame specifications using the dedicated formatWindowFrame method
|
|
1503
|
-
const frameClause = this.formatWindowFrame(node.over, context.spawn('FuncCall'));
|
|
1504
|
-
if (frameClause) {
|
|
1505
|
-
windowParts.push(frameClause);
|
|
1506
|
-
}
|
|
1507
|
-
if (windowParts.length > 0) {
|
|
1508
|
-
if (context.isPretty() && windowParts.length > 1) {
|
|
1509
|
-
const formattedParts = windowParts.map(part => context.indent(part));
|
|
1510
|
-
result += ` OVER (${context.newline()}${formattedParts.join(context.newline())}${context.newline()})`;
|
|
1511
|
-
}
|
|
1512
|
-
else {
|
|
1513
|
-
result += ` OVER (${windowParts.join(' ')})`;
|
|
1514
|
-
}
|
|
1515
|
-
}
|
|
1516
|
-
else {
|
|
1517
|
-
result += ` OVER ()`;
|
|
1518
|
-
}
|
|
1519
|
-
}
|
|
1568
|
+
result += this.formatOverClause(node.over, context);
|
|
1520
1569
|
}
|
|
1521
1570
|
return result;
|
|
1522
1571
|
}
|
|
1572
|
+
formatOverClause(over, context) {
|
|
1573
|
+
if (over.name) {
|
|
1574
|
+
return ` OVER ${over.name}`;
|
|
1575
|
+
}
|
|
1576
|
+
const windowParts = [];
|
|
1577
|
+
if (over.refname) {
|
|
1578
|
+
windowParts.push(over.refname);
|
|
1579
|
+
}
|
|
1580
|
+
if (over.partitionClause) {
|
|
1581
|
+
const partitions = list_utils_1.ListUtils.unwrapList(over.partitionClause);
|
|
1582
|
+
const partitionStrs = partitions.map(p => this.visit(p, context));
|
|
1583
|
+
windowParts.push(`PARTITION BY ${partitionStrs.join(', ')}`);
|
|
1584
|
+
}
|
|
1585
|
+
if (over.orderClause) {
|
|
1586
|
+
const orders = list_utils_1.ListUtils.unwrapList(over.orderClause);
|
|
1587
|
+
const orderStrs = orders.map(o => this.visit(o, context));
|
|
1588
|
+
windowParts.push(`ORDER BY ${orderStrs.join(', ')}`);
|
|
1589
|
+
}
|
|
1590
|
+
const frameClause = this.formatWindowFrame(over, context.spawn('FuncCall'));
|
|
1591
|
+
if (frameClause) {
|
|
1592
|
+
windowParts.push(frameClause);
|
|
1593
|
+
}
|
|
1594
|
+
if (windowParts.length === 0) {
|
|
1595
|
+
return ' OVER ()';
|
|
1596
|
+
}
|
|
1597
|
+
if (context.isPretty() && windowParts.length > 1) {
|
|
1598
|
+
const formattedParts = windowParts.map(part => context.indent(part));
|
|
1599
|
+
return ` OVER (${context.newline()}${formattedParts.join(context.newline())}${context.newline()})`;
|
|
1600
|
+
}
|
|
1601
|
+
return ` OVER (${windowParts.join(' ')})`;
|
|
1602
|
+
}
|
|
1523
1603
|
FuncExpr(node, context) {
|
|
1524
1604
|
const funcName = `func_${node.funcid}`;
|
|
1525
1605
|
const args = node.args ? list_utils_1.ListUtils.unwrapList(node.args).map(arg => this.visit(arg, context)).join(', ') : '';
|
|
@@ -1530,39 +1610,39 @@ class Deparser {
|
|
|
1530
1610
|
if (nodeAny.ival !== undefined) {
|
|
1531
1611
|
if (typeof nodeAny.ival === 'object' && nodeAny.ival !== null) {
|
|
1532
1612
|
if (nodeAny.ival.ival !== undefined) {
|
|
1533
|
-
return nodeAny.ival.ival
|
|
1613
|
+
return formatInteger(nodeAny.ival.ival);
|
|
1534
1614
|
}
|
|
1535
1615
|
else if (Object.keys(nodeAny.ival).length === 0) {
|
|
1536
1616
|
return '0';
|
|
1537
1617
|
}
|
|
1538
1618
|
else {
|
|
1539
|
-
return nodeAny.ival
|
|
1619
|
+
return formatInteger(nodeAny.ival);
|
|
1540
1620
|
}
|
|
1541
1621
|
}
|
|
1542
1622
|
else if (nodeAny.ival === null) {
|
|
1543
1623
|
return 'NULL';
|
|
1544
1624
|
}
|
|
1545
1625
|
else {
|
|
1546
|
-
return nodeAny.ival
|
|
1626
|
+
return formatInteger(nodeAny.ival);
|
|
1547
1627
|
}
|
|
1548
1628
|
}
|
|
1549
1629
|
else if (nodeAny.fval !== undefined) {
|
|
1550
1630
|
if (typeof nodeAny.fval === 'object' && nodeAny.fval !== null) {
|
|
1551
1631
|
if (nodeAny.fval.fval !== undefined) {
|
|
1552
|
-
return nodeAny.fval.fval
|
|
1632
|
+
return formatNumeric(nodeAny.fval.fval);
|
|
1553
1633
|
}
|
|
1554
1634
|
else if (Object.keys(nodeAny.fval).length === 0) {
|
|
1555
1635
|
return '0.0';
|
|
1556
1636
|
}
|
|
1557
1637
|
else {
|
|
1558
|
-
return nodeAny.fval
|
|
1638
|
+
return formatNumeric(nodeAny.fval);
|
|
1559
1639
|
}
|
|
1560
1640
|
}
|
|
1561
1641
|
else if (nodeAny.fval === null) {
|
|
1562
1642
|
return 'NULL';
|
|
1563
1643
|
}
|
|
1564
1644
|
else {
|
|
1565
|
-
return nodeAny.fval
|
|
1645
|
+
return formatNumeric(nodeAny.fval);
|
|
1566
1646
|
}
|
|
1567
1647
|
}
|
|
1568
1648
|
else if (nodeAny.sval !== undefined) {
|
|
@@ -1609,15 +1689,7 @@ class Deparser {
|
|
|
1609
1689
|
else if (nodeAny.bsval !== undefined) {
|
|
1610
1690
|
if (typeof nodeAny.bsval === 'object' && nodeAny.bsval !== null) {
|
|
1611
1691
|
if (nodeAny.bsval.bsval !== undefined) {
|
|
1612
|
-
|
|
1613
|
-
// Check if this is a hexadecimal bit string (starts with x and contains only hex digits)
|
|
1614
|
-
if (bsval.startsWith('x') && /^x[0-9A-Fa-f]+$/.test(bsval)) {
|
|
1615
|
-
return `x'${bsval.substring(1)}'`;
|
|
1616
|
-
}
|
|
1617
|
-
if (bsval.startsWith('b')) {
|
|
1618
|
-
return `b'${bsval.substring(1)}'`;
|
|
1619
|
-
}
|
|
1620
|
-
return `b'${bsval}'`;
|
|
1692
|
+
return formatBitString(nodeAny.bsval.bsval);
|
|
1621
1693
|
}
|
|
1622
1694
|
else if (Object.keys(nodeAny.bsval).length === 0) {
|
|
1623
1695
|
return "''";
|
|
@@ -1630,23 +1702,15 @@ class Deparser {
|
|
|
1630
1702
|
return 'NULL';
|
|
1631
1703
|
}
|
|
1632
1704
|
else {
|
|
1633
|
-
|
|
1634
|
-
// Check if this is a hexadecimal bit string (starts with x and contains only hex digits)
|
|
1635
|
-
if (bsval.startsWith('x') && /^x[0-9A-Fa-f]+$/.test(bsval)) {
|
|
1636
|
-
return `x'${bsval.substring(1)}'`;
|
|
1637
|
-
}
|
|
1638
|
-
if (bsval.startsWith('b')) {
|
|
1639
|
-
return `b'${bsval.substring(1)}'`;
|
|
1640
|
-
}
|
|
1641
|
-
return `b'${bsval}'`;
|
|
1705
|
+
return formatBitString(nodeAny.bsval);
|
|
1642
1706
|
}
|
|
1643
1707
|
}
|
|
1644
1708
|
if (nodeAny.val) {
|
|
1645
1709
|
if (nodeAny.val.Integer?.ival !== undefined) {
|
|
1646
|
-
return nodeAny.val.Integer.ival
|
|
1710
|
+
return formatInteger(nodeAny.val.Integer.ival);
|
|
1647
1711
|
}
|
|
1648
1712
|
else if (nodeAny.val.Float?.fval !== undefined) {
|
|
1649
|
-
return nodeAny.val.Float.fval
|
|
1713
|
+
return formatNumeric(nodeAny.val.Float.fval);
|
|
1650
1714
|
}
|
|
1651
1715
|
else if (nodeAny.val.String?.sval !== undefined) {
|
|
1652
1716
|
return quotes_1.QuoteUtils.escape(nodeAny.val.String.sval);
|
|
@@ -1655,7 +1719,7 @@ class Deparser {
|
|
|
1655
1719
|
return nodeAny.val.Boolean.boolval ? 'true' : 'false';
|
|
1656
1720
|
}
|
|
1657
1721
|
else if (nodeAny.val.BitString?.bsval !== undefined) {
|
|
1658
|
-
return nodeAny.val.BitString.bsval;
|
|
1722
|
+
return formatBitString(nodeAny.val.BitString.bsval);
|
|
1659
1723
|
}
|
|
1660
1724
|
}
|
|
1661
1725
|
if (nodeAny.isnull === true) {
|
|
@@ -1667,15 +1731,15 @@ class Deparser {
|
|
|
1667
1731
|
}
|
|
1668
1732
|
if (nodeAny.Integer !== undefined) {
|
|
1669
1733
|
if (typeof nodeAny.Integer === 'object' && nodeAny.Integer.ival !== undefined) {
|
|
1670
|
-
return nodeAny.Integer.ival
|
|
1734
|
+
return formatInteger(nodeAny.Integer.ival);
|
|
1671
1735
|
}
|
|
1672
|
-
return nodeAny.Integer
|
|
1736
|
+
return formatInteger(nodeAny.Integer);
|
|
1673
1737
|
}
|
|
1674
1738
|
if (nodeAny.Float !== undefined) {
|
|
1675
1739
|
if (typeof nodeAny.Float === 'object' && nodeAny.Float.fval !== undefined) {
|
|
1676
|
-
return nodeAny.Float.fval
|
|
1740
|
+
return formatNumeric(nodeAny.Float.fval);
|
|
1677
1741
|
}
|
|
1678
|
-
return nodeAny.Float
|
|
1742
|
+
return formatNumeric(nodeAny.Float);
|
|
1679
1743
|
}
|
|
1680
1744
|
if (nodeAny.String !== undefined) {
|
|
1681
1745
|
if (typeof nodeAny.String === 'object' && nodeAny.String.sval !== undefined) {
|
|
@@ -2137,7 +2201,9 @@ class Deparser {
|
|
|
2137
2201
|
A_Indirection(node, context) {
|
|
2138
2202
|
let argStr = this.visit(node.arg, context);
|
|
2139
2203
|
const argType = this.getNodeType(node.arg);
|
|
2140
|
-
|
|
2204
|
+
// Grammar: only a parameter takes indirection bare; every other target is
|
|
2205
|
+
// `'(' a_expr ')' opt_indirection` (a plain column subscript is the same node).
|
|
2206
|
+
if (argType !== 'ParamRef') {
|
|
2141
2207
|
argStr = `(${argStr})`;
|
|
2142
2208
|
}
|
|
2143
2209
|
const output = [argStr];
|
|
@@ -2165,21 +2231,11 @@ class Deparser {
|
|
|
2165
2231
|
if (context.isPretty() && args.length > 0) {
|
|
2166
2232
|
for (const arg of args) {
|
|
2167
2233
|
const whenClause = this.visit(arg, context);
|
|
2168
|
-
|
|
2169
|
-
output.push(context.newline() + whenClause);
|
|
2170
|
-
}
|
|
2171
|
-
else {
|
|
2172
|
-
output.push(context.newline() + context.indent(whenClause));
|
|
2173
|
-
}
|
|
2234
|
+
output.push(context.newline() + context.indent(whenClause));
|
|
2174
2235
|
}
|
|
2175
2236
|
if (node.defresult) {
|
|
2176
2237
|
const elseResult = this.visit(node.defresult, context);
|
|
2177
|
-
|
|
2178
|
-
output.push(context.newline() + 'ELSE ' + elseResult);
|
|
2179
|
-
}
|
|
2180
|
-
else {
|
|
2181
|
-
output.push(context.newline() + context.indent('ELSE ' + elseResult));
|
|
2182
|
-
}
|
|
2238
|
+
output.push(context.newline() + context.indent('ELSE ' + elseResult));
|
|
2183
2239
|
}
|
|
2184
2240
|
output.push(context.newline() + 'END');
|
|
2185
2241
|
return output.join(' ');
|
|
@@ -2294,16 +2350,16 @@ class Deparser {
|
|
|
2294
2350
|
}
|
|
2295
2351
|
preserveOperatorDefElemCase(defName) {
|
|
2296
2352
|
const caseMap = {
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2353
|
+
leftarg: 'Leftarg',
|
|
2354
|
+
rightarg: 'Rightarg',
|
|
2355
|
+
procedure: 'Procedure',
|
|
2356
|
+
function: 'Function',
|
|
2357
|
+
commutator: 'Commutator',
|
|
2358
|
+
negator: 'Negator',
|
|
2359
|
+
restrict: 'Restrict',
|
|
2360
|
+
join: 'Join',
|
|
2361
|
+
hashes: 'Hashes',
|
|
2362
|
+
merges: 'Merges'
|
|
2307
2363
|
};
|
|
2308
2364
|
return caseMap[defName.toLowerCase()] || defName;
|
|
2309
2365
|
}
|
|
@@ -2326,24 +2382,16 @@ class Deparser {
|
|
|
2326
2382
|
return quotes_1.QuoteUtils.quoteIdentifier(value);
|
|
2327
2383
|
}
|
|
2328
2384
|
Integer(node, context) {
|
|
2329
|
-
return node.ival
|
|
2385
|
+
return node.ival === undefined || node.ival === null ? '0' : formatInteger(node.ival);
|
|
2330
2386
|
}
|
|
2331
2387
|
Float(node, context) {
|
|
2332
|
-
return node.fval
|
|
2388
|
+
return node.fval ? formatNumeric(node.fval) : '0.0';
|
|
2333
2389
|
}
|
|
2334
2390
|
Boolean(node, context) {
|
|
2335
2391
|
return node.boolval ? 'true' : 'false';
|
|
2336
2392
|
}
|
|
2337
2393
|
BitString(node, context) {
|
|
2338
|
-
|
|
2339
|
-
if (node.bsval.startsWith('x')) {
|
|
2340
|
-
return `x'${node.bsval.substring(1)}'`;
|
|
2341
|
-
}
|
|
2342
|
-
if (node.bsval.startsWith('b')) {
|
|
2343
|
-
return `b'${node.bsval.substring(1)}'`;
|
|
2344
|
-
}
|
|
2345
|
-
// Fallback for raw values without prefix
|
|
2346
|
-
return `b'${node.bsval}'`;
|
|
2394
|
+
return formatBitString(node.bsval);
|
|
2347
2395
|
}
|
|
2348
2396
|
Null(node, context) {
|
|
2349
2397
|
return 'NULL';
|
|
@@ -2382,7 +2430,7 @@ class Deparser {
|
|
|
2382
2430
|
output.push(context.parens(elementStrs.join(', ')));
|
|
2383
2431
|
}
|
|
2384
2432
|
}
|
|
2385
|
-
else if (node.tableElts) {
|
|
2433
|
+
else if (node.tableElts && !node.partbound) {
|
|
2386
2434
|
const elements = list_utils_1.ListUtils.unwrapList(node.tableElts);
|
|
2387
2435
|
const elementStrs = elements.map(el => {
|
|
2388
2436
|
return this.deparse(el, context.spawn('CreateStmt'));
|
|
@@ -2410,7 +2458,16 @@ class Deparser {
|
|
|
2410
2458
|
const inherits = list_utils_1.ListUtils.unwrapList(node.inhRelations);
|
|
2411
2459
|
const inheritStrs = inherits.map(rel => this.visit(rel, context));
|
|
2412
2460
|
output.push(inheritStrs[0]);
|
|
2413
|
-
if (node.
|
|
2461
|
+
if (node.tableElts) {
|
|
2462
|
+
const elementStrs = list_utils_1.ListUtils.unwrapList(node.tableElts).map(el => {
|
|
2463
|
+
return this.deparse(el, context.spawn('CreateStmt'));
|
|
2464
|
+
});
|
|
2465
|
+
output.push(context.parens(elementStrs.join(', ')));
|
|
2466
|
+
}
|
|
2467
|
+
if (node.partbound.is_default) {
|
|
2468
|
+
output.push('DEFAULT');
|
|
2469
|
+
}
|
|
2470
|
+
else if (node.partbound.strategy === 'l' && node.partbound.listdatums) {
|
|
2414
2471
|
output.push('FOR VALUES IN');
|
|
2415
2472
|
const listValues = list_utils_1.ListUtils.unwrapList(node.partbound.listdatums)
|
|
2416
2473
|
.map(datum => this.visit(datum, context))
|
|
@@ -2433,13 +2490,9 @@ class Deparser {
|
|
|
2433
2490
|
output.push(`(${upperValues})`);
|
|
2434
2491
|
}
|
|
2435
2492
|
}
|
|
2436
|
-
else if (node.partbound.strategy === 'h'
|
|
2493
|
+
else if (node.partbound.strategy === 'h') {
|
|
2437
2494
|
output.push('FOR VALUES WITH');
|
|
2438
|
-
|
|
2439
|
-
output.push(`(MODULUS ${node.partbound.modulus}, REMAINDER ${remainder})`);
|
|
2440
|
-
}
|
|
2441
|
-
else if (node.partbound.is_default) {
|
|
2442
|
-
output.push('DEFAULT');
|
|
2495
|
+
output.push(`(MODULUS ${node.partbound.modulus ?? 0}, REMAINDER ${node.partbound.remainder ?? 0})`);
|
|
2443
2496
|
}
|
|
2444
2497
|
}
|
|
2445
2498
|
else if (node.inhRelations) {
|
|
@@ -2505,6 +2558,12 @@ class Deparser {
|
|
|
2505
2558
|
if (node.typeName) {
|
|
2506
2559
|
output.push(this.TypeName(node.typeName, context));
|
|
2507
2560
|
}
|
|
2561
|
+
if (node.storage_name) {
|
|
2562
|
+
output.push('STORAGE', node.storage_name.toUpperCase());
|
|
2563
|
+
}
|
|
2564
|
+
if (node.compression) {
|
|
2565
|
+
output.push('COMPRESSION', quotes_1.QuoteUtils.quoteIdentifier(node.compression));
|
|
2566
|
+
}
|
|
2508
2567
|
if (node.fdwoptions && node.fdwoptions.length > 0) {
|
|
2509
2568
|
output.push('OPTIONS');
|
|
2510
2569
|
const columnContext = context.spawn('ColumnDef');
|
|
@@ -2539,7 +2598,7 @@ class Deparser {
|
|
|
2539
2598
|
Constraint(node, context) {
|
|
2540
2599
|
const output = [];
|
|
2541
2600
|
// Handle constraint name if present
|
|
2542
|
-
if (node.conname && (node.contype === 'CONSTR_CHECK' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_FOREIGN')) {
|
|
2601
|
+
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')) {
|
|
2543
2602
|
output.push('CONSTRAINT');
|
|
2544
2603
|
output.push(quotes_1.QuoteUtils.quoteIdentifier(node.conname));
|
|
2545
2604
|
}
|
|
@@ -2549,11 +2608,24 @@ class Deparser {
|
|
|
2549
2608
|
break;
|
|
2550
2609
|
case 'CONSTR_NOTNULL':
|
|
2551
2610
|
output.push('NOT NULL');
|
|
2611
|
+
if (node.keys && node.keys.length > 0 && !context.isColumnConstraint) {
|
|
2612
|
+
const keyList = list_utils_1.ListUtils.unwrapList(node.keys)
|
|
2613
|
+
.map(key => this.visit(key, context))
|
|
2614
|
+
.join(', ');
|
|
2615
|
+
output.push(keyList);
|
|
2616
|
+
}
|
|
2617
|
+
if (node.is_no_inherit) {
|
|
2618
|
+
output.push('NO INHERIT');
|
|
2619
|
+
}
|
|
2620
|
+
if (node.skip_validation) {
|
|
2621
|
+
output.push('NOT VALID');
|
|
2622
|
+
}
|
|
2552
2623
|
break;
|
|
2553
2624
|
case 'CONSTR_DEFAULT':
|
|
2554
2625
|
output.push('DEFAULT');
|
|
2555
2626
|
if (node.raw_expr) {
|
|
2556
|
-
|
|
2627
|
+
const defaultExpr = this.visit(node.raw_expr, context);
|
|
2628
|
+
output.push(this.needsBExprParens(node.raw_expr) ? `(${defaultExpr})` : defaultExpr);
|
|
2557
2629
|
}
|
|
2558
2630
|
break;
|
|
2559
2631
|
case 'CONSTR_CHECK':
|
|
@@ -2577,8 +2649,13 @@ class Deparser {
|
|
|
2577
2649
|
output.push(context.parens(this.visit(node.raw_expr, context)));
|
|
2578
2650
|
}
|
|
2579
2651
|
}
|
|
2580
|
-
//
|
|
2581
|
-
|
|
2652
|
+
// PG18: constraints are enforced unless explicitly NOT ENFORCED
|
|
2653
|
+
// (libpg-query omits false booleans, so undefined means not enforced)
|
|
2654
|
+
if (node.is_enforced !== true && !context.isDomainConstraint) {
|
|
2655
|
+
output.push('NOT ENFORCED');
|
|
2656
|
+
}
|
|
2657
|
+
else if (node.skip_validation) {
|
|
2658
|
+
// NOT ENFORCED implies NOT VALID, so only emit NOT VALID when enforced
|
|
2582
2659
|
output.push('NOT VALID');
|
|
2583
2660
|
}
|
|
2584
2661
|
// Handle NO INHERIT for check constraints - only for table constraints, not domain constraints
|
|
@@ -2598,7 +2675,7 @@ class Deparser {
|
|
|
2598
2675
|
if (node.raw_expr) {
|
|
2599
2676
|
output.push(context.parens(this.visit(node.raw_expr, context)));
|
|
2600
2677
|
}
|
|
2601
|
-
output.push('STORED');
|
|
2678
|
+
output.push(node.generated_kind === 'v' ? 'VIRTUAL' : 'STORED');
|
|
2602
2679
|
break;
|
|
2603
2680
|
case 'CONSTR_IDENTITY':
|
|
2604
2681
|
output.push('GENERATED');
|
|
@@ -2674,10 +2751,12 @@ class Deparser {
|
|
|
2674
2751
|
case 'CONSTR_PRIMARY':
|
|
2675
2752
|
output.push('PRIMARY KEY');
|
|
2676
2753
|
if (node.keys && node.keys.length > 0) {
|
|
2677
|
-
const
|
|
2678
|
-
.map(key => this.visit(key, context))
|
|
2679
|
-
|
|
2680
|
-
|
|
2754
|
+
const keyItems = list_utils_1.ListUtils.unwrapList(node.keys)
|
|
2755
|
+
.map(key => this.visit(key, context));
|
|
2756
|
+
if (node.without_overlaps) {
|
|
2757
|
+
keyItems[keyItems.length - 1] += ' WITHOUT OVERLAPS';
|
|
2758
|
+
}
|
|
2759
|
+
output.push(`(${keyItems.join(', ')})`);
|
|
2681
2760
|
}
|
|
2682
2761
|
if (node.indexname) {
|
|
2683
2762
|
output.push('USING INDEX');
|
|
@@ -2695,10 +2774,12 @@ class Deparser {
|
|
|
2695
2774
|
output.push('NULLS NOT DISTINCT');
|
|
2696
2775
|
}
|
|
2697
2776
|
if (node.keys && node.keys.length > 0) {
|
|
2698
|
-
const
|
|
2699
|
-
.map(key => this.visit(key, context))
|
|
2700
|
-
|
|
2701
|
-
|
|
2777
|
+
const keyItems = list_utils_1.ListUtils.unwrapList(node.keys)
|
|
2778
|
+
.map(key => this.visit(key, context));
|
|
2779
|
+
if (node.without_overlaps) {
|
|
2780
|
+
keyItems[keyItems.length - 1] += ' WITHOUT OVERLAPS';
|
|
2781
|
+
}
|
|
2782
|
+
output.push(`(${keyItems.join(', ')})`);
|
|
2702
2783
|
}
|
|
2703
2784
|
if (node.indexname) {
|
|
2704
2785
|
output.push('USING INDEX');
|
|
@@ -2711,20 +2792,14 @@ class Deparser {
|
|
|
2711
2792
|
if (context.isPretty()) {
|
|
2712
2793
|
output.push('\n' + context.indent('FOREIGN KEY'));
|
|
2713
2794
|
if (node.fk_attrs && node.fk_attrs.length > 0) {
|
|
2714
|
-
|
|
2715
|
-
.map(attr => this.visit(attr, context))
|
|
2716
|
-
.join(', ');
|
|
2717
|
-
output.push(`(${fkAttrs})`);
|
|
2795
|
+
output.push(`(${this.deparseKeyAttrs(node.fk_attrs, node.fk_with_period, context)})`);
|
|
2718
2796
|
}
|
|
2719
2797
|
output.push('\n' + context.indent('REFERENCES'));
|
|
2720
2798
|
}
|
|
2721
2799
|
else {
|
|
2722
2800
|
output.push('FOREIGN KEY');
|
|
2723
2801
|
if (node.fk_attrs && node.fk_attrs.length > 0) {
|
|
2724
|
-
|
|
2725
|
-
.map(attr => this.visit(attr, context))
|
|
2726
|
-
.join(', ');
|
|
2727
|
-
output.push(`(${fkAttrs})`);
|
|
2802
|
+
output.push(`(${this.deparseKeyAttrs(node.fk_attrs, node.fk_with_period, context)})`);
|
|
2728
2803
|
}
|
|
2729
2804
|
output.push('REFERENCES');
|
|
2730
2805
|
}
|
|
@@ -2747,9 +2822,7 @@ class Deparser {
|
|
|
2747
2822
|
}
|
|
2748
2823
|
}
|
|
2749
2824
|
if (node.pk_attrs && node.pk_attrs.length > 0) {
|
|
2750
|
-
const pkAttrs =
|
|
2751
|
-
.map(attr => this.visit(attr, context))
|
|
2752
|
-
.join(', ');
|
|
2825
|
+
const pkAttrs = this.deparseKeyAttrs(node.pk_attrs, node.pk_with_period, context);
|
|
2753
2826
|
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2754
2827
|
const lastIndex = output.length - 1;
|
|
2755
2828
|
if (lastIndex >= 0) {
|
|
@@ -2820,6 +2893,15 @@ class Deparser {
|
|
|
2820
2893
|
deleteClause += 'SET DEFAULT';
|
|
2821
2894
|
break;
|
|
2822
2895
|
}
|
|
2896
|
+
if ((node.fk_del_action === 'n' || node.fk_del_action === 'd') && node.fk_del_set_cols && node.fk_del_set_cols.length > 0) {
|
|
2897
|
+
const setColumns = list_utils_1.ListUtils.unwrapList(node.fk_del_set_cols)
|
|
2898
|
+
.map(column => {
|
|
2899
|
+
const stringNode = column.String;
|
|
2900
|
+
return quotes_1.QuoteUtils.quoteIdentifier(stringNode.sval || stringNode.str || '');
|
|
2901
|
+
})
|
|
2902
|
+
.join(', ');
|
|
2903
|
+
deleteClause += ` (${setColumns})`;
|
|
2904
|
+
}
|
|
2823
2905
|
if (context.isPretty()) {
|
|
2824
2906
|
output.push('\n' + context.indent(deleteClause));
|
|
2825
2907
|
}
|
|
@@ -2828,8 +2910,18 @@ class Deparser {
|
|
|
2828
2910
|
output.push(deleteClause.replace('ON DELETE ', ''));
|
|
2829
2911
|
}
|
|
2830
2912
|
}
|
|
2831
|
-
//
|
|
2832
|
-
|
|
2913
|
+
// PG18: constraints are enforced unless explicitly NOT ENFORCED
|
|
2914
|
+
// (libpg-query omits false booleans, so undefined means not enforced)
|
|
2915
|
+
if (node.is_enforced !== true && !context.isDomainConstraint) {
|
|
2916
|
+
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2917
|
+
output.push('\n' + context.indent('NOT ENFORCED'));
|
|
2918
|
+
}
|
|
2919
|
+
else {
|
|
2920
|
+
output.push('NOT ENFORCED');
|
|
2921
|
+
}
|
|
2922
|
+
}
|
|
2923
|
+
else if (node.skip_validation && !context.isDomainConstraint) {
|
|
2924
|
+
// NOT ENFORCED implies NOT VALID, so only emit NOT VALID when enforced
|
|
2833
2925
|
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2834
2926
|
output.push('\n' + context.indent('NOT VALID'));
|
|
2835
2927
|
}
|
|
@@ -2850,6 +2942,12 @@ class Deparser {
|
|
|
2850
2942
|
case 'CONSTR_ATTR_IMMEDIATE':
|
|
2851
2943
|
output.push('INITIALLY IMMEDIATE');
|
|
2852
2944
|
break;
|
|
2945
|
+
case 'CONSTR_ATTR_ENFORCED':
|
|
2946
|
+
output.push('ENFORCED');
|
|
2947
|
+
break;
|
|
2948
|
+
case 'CONSTR_ATTR_NOT_ENFORCED':
|
|
2949
|
+
output.push('NOT ENFORCED');
|
|
2950
|
+
break;
|
|
2853
2951
|
case 'CONSTR_EXCLUSION':
|
|
2854
2952
|
output.push('EXCLUDE');
|
|
2855
2953
|
if (node.access_method) {
|
|
@@ -2891,7 +2989,7 @@ class Deparser {
|
|
|
2891
2989
|
break;
|
|
2892
2990
|
}
|
|
2893
2991
|
// Handle deferrable constraints for all constraint types that support it
|
|
2894
|
-
if (node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_FOREIGN') {
|
|
2992
|
+
if (node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_FOREIGN' || node.contype === 'CONSTR_EXCLUSION') {
|
|
2895
2993
|
if (node.deferrable) {
|
|
2896
2994
|
if (context.isPretty() && node.contype === 'CONSTR_FOREIGN') {
|
|
2897
2995
|
output.push('\n' + context.indent('DEFERRABLE'));
|
|
@@ -2920,6 +3018,9 @@ class Deparser {
|
|
|
2920
3018
|
output.push('NOT DEFERRABLE');
|
|
2921
3019
|
}
|
|
2922
3020
|
}
|
|
3021
|
+
else if (node.initdeferred) {
|
|
3022
|
+
output.push('INITIALLY DEFERRED');
|
|
3023
|
+
}
|
|
2923
3024
|
}
|
|
2924
3025
|
if (context.isPretty() && node.contype === 'CONSTR_FOREIGN') {
|
|
2925
3026
|
let result = '';
|
|
@@ -2985,6 +3086,9 @@ class Deparser {
|
|
|
2985
3086
|
output.push(node.name);
|
|
2986
3087
|
}
|
|
2987
3088
|
const windowParts = [];
|
|
3089
|
+
if (node.refname) {
|
|
3090
|
+
windowParts.push(node.refname);
|
|
3091
|
+
}
|
|
2988
3092
|
if (node.partitionClause) {
|
|
2989
3093
|
const partitions = list_utils_1.ListUtils.unwrapList(node.partitionClause);
|
|
2990
3094
|
const partitionStrs = partitions.map(p => this.visit(p, context));
|
|
@@ -2995,12 +3099,9 @@ class Deparser {
|
|
|
2995
3099
|
const orderStrs = orders.map(o => this.visit(o, context));
|
|
2996
3100
|
windowParts.push(`ORDER BY ${orderStrs.join(', ')}`);
|
|
2997
3101
|
}
|
|
2998
|
-
|
|
2999
|
-
if (
|
|
3000
|
-
|
|
3001
|
-
if (frameClause) {
|
|
3002
|
-
windowParts.push(frameClause);
|
|
3003
|
-
}
|
|
3102
|
+
const frameClause = this.formatWindowFrame(node, context.spawn('WindowDef'));
|
|
3103
|
+
if (frameClause) {
|
|
3104
|
+
windowParts.push(frameClause);
|
|
3004
3105
|
}
|
|
3005
3106
|
if (windowParts.length > 0) {
|
|
3006
3107
|
if (node.name) {
|
|
@@ -3017,114 +3118,96 @@ class Deparser {
|
|
|
3017
3118
|
}
|
|
3018
3119
|
return output.join(' ');
|
|
3019
3120
|
}
|
|
3121
|
+
formatIdentityColumnOptions(def, context) {
|
|
3122
|
+
const seqContext = context.spawn('AlterSeqStmt');
|
|
3123
|
+
return list_utils_1.ListUtils.unwrapList(def).map(item => {
|
|
3124
|
+
const el = item.DefElem;
|
|
3125
|
+
if (!el)
|
|
3126
|
+
return this.visit(item, context);
|
|
3127
|
+
if (el.defname === 'generated') {
|
|
3128
|
+
const ival = el.arg?.Integer?.ival ?? 0;
|
|
3129
|
+
return ival === 97 ? 'SET GENERATED ALWAYS' : 'SET GENERATED BY DEFAULT';
|
|
3130
|
+
}
|
|
3131
|
+
if (el.defname === 'restart') {
|
|
3132
|
+
return el.arg ? `RESTART WITH ${this.visit(el.arg, context)}` : 'RESTART';
|
|
3133
|
+
}
|
|
3134
|
+
return `SET ${this.visit(item, seqContext)}`;
|
|
3135
|
+
}).join(' ');
|
|
3136
|
+
}
|
|
3137
|
+
// b_expr (used by DEFAULT) excludes IN/LIKE/BETWEEN and boolean operators.
|
|
3138
|
+
needsBExprParens(node) {
|
|
3139
|
+
const nodeType = this.getNodeType(node);
|
|
3140
|
+
if (nodeType === 'BoolExpr')
|
|
3141
|
+
return true;
|
|
3142
|
+
if (nodeType === 'A_Expr') {
|
|
3143
|
+
const kind = this.getNodeData(node).kind;
|
|
3144
|
+
return kind !== 'AEXPR_OP' && kind !== 'AEXPR_DISTINCT' && kind !== 'AEXPR_NOT_DISTINCT';
|
|
3145
|
+
}
|
|
3146
|
+
return false;
|
|
3147
|
+
}
|
|
3020
3148
|
formatWindowFrame(node, context) {
|
|
3021
|
-
if (!node.frameOptions)
|
|
3149
|
+
if (!node.frameOptions || !(node.frameOptions & FRAMEOPTION_NONDEFAULT))
|
|
3022
3150
|
return null;
|
|
3023
3151
|
const frameOptions = node.frameOptions;
|
|
3024
|
-
const EXCLUDE_MASK = 0x8000 | 0x10000 | 0x20000;
|
|
3025
|
-
const baseFrameOptions = frameOptions & ~EXCLUDE_MASK;
|
|
3026
3152
|
const frameParts = [];
|
|
3027
|
-
if (frameOptions &
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
frameParts.push('GROUPS');
|
|
3036
|
-
}
|
|
3153
|
+
if (frameOptions & FRAMEOPTION_RANGE) {
|
|
3154
|
+
frameParts.push('RANGE');
|
|
3155
|
+
}
|
|
3156
|
+
else if (frameOptions & FRAMEOPTION_ROWS) {
|
|
3157
|
+
frameParts.push('ROWS');
|
|
3158
|
+
}
|
|
3159
|
+
else if (frameOptions & FRAMEOPTION_GROUPS) {
|
|
3160
|
+
frameParts.push('GROUPS');
|
|
3037
3161
|
}
|
|
3038
3162
|
if (frameParts.length === 0)
|
|
3039
3163
|
return null;
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
boundsParts.push('CURRENT ROW');
|
|
3044
|
-
boundsParts.push('AND UNBOUNDED FOLLOWING');
|
|
3164
|
+
let start = null;
|
|
3165
|
+
if (frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING) {
|
|
3166
|
+
start = 'UNBOUNDED PRECEDING';
|
|
3045
3167
|
}
|
|
3046
|
-
else if (
|
|
3047
|
-
|
|
3048
|
-
boundsParts.push('AND CURRENT ROW');
|
|
3168
|
+
else if (frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING) {
|
|
3169
|
+
start = 'UNBOUNDED FOLLOWING';
|
|
3049
3170
|
}
|
|
3050
|
-
else if (
|
|
3051
|
-
|
|
3052
|
-
boundsParts.push(`${this.visit(node.startOffset, context)} PRECEDING`);
|
|
3053
|
-
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
3054
|
-
}
|
|
3171
|
+
else if (frameOptions & FRAMEOPTION_START_CURRENT_ROW) {
|
|
3172
|
+
start = 'CURRENT ROW';
|
|
3055
3173
|
}
|
|
3056
|
-
else if (
|
|
3057
|
-
|
|
3058
|
-
boundsParts.push('AND CURRENT ROW');
|
|
3174
|
+
else if (frameOptions & FRAMEOPTION_START_OFFSET_PRECEDING && node.startOffset) {
|
|
3175
|
+
start = `${this.visit(node.startOffset, context)} PRECEDING`;
|
|
3059
3176
|
}
|
|
3060
|
-
else if (
|
|
3061
|
-
|
|
3062
|
-
if (node.endOffset) {
|
|
3063
|
-
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
3064
|
-
}
|
|
3177
|
+
else if (frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING && node.startOffset) {
|
|
3178
|
+
start = `${this.visit(node.startOffset, context)} FOLLOWING`;
|
|
3065
3179
|
}
|
|
3066
|
-
|
|
3067
|
-
|
|
3180
|
+
let end = null;
|
|
3181
|
+
if (frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING) {
|
|
3182
|
+
end = 'UNBOUNDED PRECEDING';
|
|
3068
3183
|
}
|
|
3069
|
-
else {
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
}
|
|
3085
|
-
else if (frameOptions & 0x20) { // FRAMEOPTION_START_CURRENT_ROW
|
|
3086
|
-
boundsParts.push('CURRENT ROW');
|
|
3087
|
-
}
|
|
3088
|
-
// Handle end bound - prioritize explicit offset values over bit flags
|
|
3089
|
-
if (node.endOffset) {
|
|
3090
|
-
if (boundsParts.length > 0) {
|
|
3091
|
-
if (frameOptions & 0x1000) { // FRAMEOPTION_END_VALUE_PRECEDING
|
|
3092
|
-
boundsParts.push(`AND ${this.visit(node.endOffset, context)} PRECEDING`);
|
|
3093
|
-
}
|
|
3094
|
-
else if (frameOptions & 0x2000) { // FRAMEOPTION_END_VALUE_FOLLOWING
|
|
3095
|
-
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
3096
|
-
}
|
|
3097
|
-
else {
|
|
3098
|
-
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
3099
|
-
}
|
|
3100
|
-
}
|
|
3101
|
-
}
|
|
3102
|
-
else if (frameOptions & 0x80) { // FRAMEOPTION_END_UNBOUNDED_FOLLOWING
|
|
3103
|
-
if (boundsParts.length > 0) {
|
|
3104
|
-
boundsParts.push('AND UNBOUNDED FOLLOWING');
|
|
3105
|
-
}
|
|
3106
|
-
}
|
|
3107
|
-
else if (frameOptions & 0x100) { // FRAMEOPTION_END_CURRENT_ROW
|
|
3108
|
-
if (boundsParts.length > 0) {
|
|
3109
|
-
boundsParts.push('AND CURRENT ROW');
|
|
3110
|
-
}
|
|
3184
|
+
else if (frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING) {
|
|
3185
|
+
end = 'UNBOUNDED FOLLOWING';
|
|
3186
|
+
}
|
|
3187
|
+
else if (frameOptions & FRAMEOPTION_END_CURRENT_ROW) {
|
|
3188
|
+
end = 'CURRENT ROW';
|
|
3189
|
+
}
|
|
3190
|
+
else if (frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING && node.endOffset) {
|
|
3191
|
+
end = `${this.visit(node.endOffset, context)} PRECEDING`;
|
|
3192
|
+
}
|
|
3193
|
+
else if (frameOptions & FRAMEOPTION_END_OFFSET_FOLLOWING && node.endOffset) {
|
|
3194
|
+
end = `${this.visit(node.endOffset, context)} FOLLOWING`;
|
|
3195
|
+
}
|
|
3196
|
+
if (start) {
|
|
3197
|
+
if (frameOptions & FRAMEOPTION_BETWEEN) {
|
|
3198
|
+
frameParts.push(`BETWEEN ${start} AND ${end ?? 'CURRENT ROW'}`);
|
|
3111
3199
|
}
|
|
3112
|
-
else
|
|
3113
|
-
|
|
3200
|
+
else {
|
|
3201
|
+
frameParts.push(start);
|
|
3114
3202
|
}
|
|
3115
3203
|
}
|
|
3116
|
-
if (
|
|
3117
|
-
frameParts.push('BETWEEN');
|
|
3118
|
-
frameParts.push(boundsParts.join(' '));
|
|
3119
|
-
}
|
|
3120
|
-
// EXCLUDE clause
|
|
3121
|
-
if (frameOptions & 0x8000) { // FRAMEOPTION_EXCLUDE_CURRENT_ROW
|
|
3204
|
+
if (frameOptions & FRAMEOPTION_EXCLUDE_CURRENT_ROW) {
|
|
3122
3205
|
frameParts.push('EXCLUDE CURRENT ROW');
|
|
3123
3206
|
}
|
|
3124
|
-
else if (frameOptions &
|
|
3207
|
+
else if (frameOptions & FRAMEOPTION_EXCLUDE_GROUP) {
|
|
3125
3208
|
frameParts.push('EXCLUDE GROUP');
|
|
3126
3209
|
}
|
|
3127
|
-
else if (frameOptions &
|
|
3210
|
+
else if (frameOptions & FRAMEOPTION_EXCLUDE_TIES) {
|
|
3128
3211
|
frameParts.push('EXCLUDE TIES');
|
|
3129
3212
|
}
|
|
3130
3213
|
return frameParts.join(' ');
|
|
@@ -3203,8 +3286,35 @@ class Deparser {
|
|
|
3203
3286
|
if (node.ctequery) {
|
|
3204
3287
|
output.push(context.parens(this.visit(node.ctequery, context)));
|
|
3205
3288
|
}
|
|
3289
|
+
if (node.search_clause) {
|
|
3290
|
+
const sc = node.search_clause;
|
|
3291
|
+
const cols = list_utils_1.ListUtils.unwrapList(sc.search_col_list).map(c => this.visit(c, context));
|
|
3292
|
+
output.push('SEARCH', sc.search_breadth_first ? 'BREADTH' : 'DEPTH', 'FIRST BY');
|
|
3293
|
+
output.push(cols.join(', '));
|
|
3294
|
+
output.push('SET', quotes_1.QuoteUtils.quoteIdentifier(sc.search_seq_column));
|
|
3295
|
+
}
|
|
3296
|
+
if (node.cycle_clause) {
|
|
3297
|
+
const cc = node.cycle_clause;
|
|
3298
|
+
const cols = list_utils_1.ListUtils.unwrapList(cc.cycle_col_list).map(c => this.visit(c, context));
|
|
3299
|
+
output.push('CYCLE', cols.join(', '));
|
|
3300
|
+
output.push('SET', quotes_1.QuoteUtils.quoteIdentifier(cc.cycle_mark_column));
|
|
3301
|
+
if (cc.cycle_mark_value && cc.cycle_mark_default) {
|
|
3302
|
+
output.push('TO', this.formatAexprConst(cc.cycle_mark_value, context));
|
|
3303
|
+
output.push('DEFAULT', this.formatAexprConst(cc.cycle_mark_default, context));
|
|
3304
|
+
}
|
|
3305
|
+
output.push('USING', quotes_1.QuoteUtils.quoteIdentifier(cc.cycle_path_column));
|
|
3306
|
+
}
|
|
3206
3307
|
return output.join(' ');
|
|
3207
3308
|
}
|
|
3309
|
+
// Renders a constant in the restricted AexprConst grammar (e.g. `point '(1,1)'`
|
|
3310
|
+
// rather than `CAST('(1,1)' AS point)`).
|
|
3311
|
+
formatAexprConst(node, context) {
|
|
3312
|
+
const cast = node.TypeCast;
|
|
3313
|
+
if (cast?.arg?.A_Const?.sval && cast.typeName) {
|
|
3314
|
+
return `${this.TypeName(cast.typeName, context)} ${this.visit(cast.arg, context)}`;
|
|
3315
|
+
}
|
|
3316
|
+
return this.visit(node, context);
|
|
3317
|
+
}
|
|
3208
3318
|
ParamRef(node, context) {
|
|
3209
3319
|
return `$${node.number}`;
|
|
3210
3320
|
}
|
|
@@ -3473,9 +3583,8 @@ class Deparser {
|
|
|
3473
3583
|
output.push('INCLUDE');
|
|
3474
3584
|
output.push(context.parens(includeStrs.join(', ')));
|
|
3475
3585
|
}
|
|
3476
|
-
if (node.
|
|
3477
|
-
output.push('
|
|
3478
|
-
output.push(this.visit(node.whereClause, context));
|
|
3586
|
+
if (node.nulls_not_distinct) {
|
|
3587
|
+
output.push('NULLS NOT DISTINCT');
|
|
3479
3588
|
}
|
|
3480
3589
|
if (node.options && node.options.length > 0) {
|
|
3481
3590
|
const indexContext = context.spawn('IndexStmt');
|
|
@@ -3483,13 +3592,14 @@ class Deparser {
|
|
|
3483
3592
|
output.push('WITH');
|
|
3484
3593
|
output.push(context.parens(optionStrs.join(', ')));
|
|
3485
3594
|
}
|
|
3486
|
-
if (node.nulls_not_distinct) {
|
|
3487
|
-
output.push('NULLS NOT DISTINCT');
|
|
3488
|
-
}
|
|
3489
3595
|
if (node.tableSpace) {
|
|
3490
3596
|
output.push('TABLESPACE');
|
|
3491
3597
|
output.push(quotes_1.QuoteUtils.quoteIdentifier(node.tableSpace));
|
|
3492
3598
|
}
|
|
3599
|
+
if (node.whereClause) {
|
|
3600
|
+
output.push('WHERE');
|
|
3601
|
+
output.push(this.visit(node.whereClause, context));
|
|
3602
|
+
}
|
|
3493
3603
|
return output.join(' ');
|
|
3494
3604
|
}
|
|
3495
3605
|
IndexElem(node, context) {
|
|
@@ -3513,7 +3623,7 @@ class Deparser {
|
|
|
3513
3623
|
const opclassOpts = list_utils_1.ListUtils.unwrapList(node.opclassopts).map(opt => {
|
|
3514
3624
|
if (opt.DefElem && opt.DefElem.arg && this.getNodeType(opt.DefElem.arg) === 'String') {
|
|
3515
3625
|
const stringData = this.getNodeData(opt.DefElem.arg);
|
|
3516
|
-
return `${opt.DefElem.defname}
|
|
3626
|
+
return `${quotes_1.QuoteUtils.quoteIdentifierAfterDot(opt.DefElem.defname)}=${quotes_1.QuoteUtils.escape(stringData.sval)}`;
|
|
3517
3627
|
}
|
|
3518
3628
|
return this.visit(opt, context.spawn('IndexElem'));
|
|
3519
3629
|
});
|
|
@@ -3564,12 +3674,12 @@ class Deparser {
|
|
|
3564
3674
|
}
|
|
3565
3675
|
PartitionCmd(node, context) {
|
|
3566
3676
|
const output = [];
|
|
3677
|
+
if (node.name) {
|
|
3678
|
+
output.push(this.RangeVar(node.name, context));
|
|
3679
|
+
}
|
|
3567
3680
|
if (node.concurrent) {
|
|
3568
3681
|
output.push('CONCURRENTLY');
|
|
3569
3682
|
}
|
|
3570
|
-
if (node.name) {
|
|
3571
|
-
output.push(this.visit(node.name, context));
|
|
3572
|
-
}
|
|
3573
3683
|
if (node.bound) {
|
|
3574
3684
|
if (node.bound.strategy === 'l' && node.bound.listdatums) {
|
|
3575
3685
|
output.push('FOR VALUES IN');
|
|
@@ -3594,9 +3704,9 @@ class Deparser {
|
|
|
3594
3704
|
output.push(`(${upperValues})`);
|
|
3595
3705
|
}
|
|
3596
3706
|
}
|
|
3597
|
-
else if (node.bound.strategy === 'h'
|
|
3707
|
+
else if (node.bound.strategy === 'h') {
|
|
3598
3708
|
output.push('FOR VALUES WITH');
|
|
3599
|
-
output.push(`(
|
|
3709
|
+
output.push(`(MODULUS ${node.bound.modulus ?? 0}, REMAINDER ${node.bound.remainder ?? 0})`);
|
|
3600
3710
|
}
|
|
3601
3711
|
else if (node.bound.is_default) {
|
|
3602
3712
|
output.push('DEFAULT');
|
|
@@ -3727,12 +3837,7 @@ class Deparser {
|
|
|
3727
3837
|
if (context.isPretty()) {
|
|
3728
3838
|
// For complex JOIN conditions, format with proper indentation
|
|
3729
3839
|
if (qualsStr.includes('AND') || qualsStr.includes('OR') || qualsStr.length > 50) {
|
|
3730
|
-
|
|
3731
|
-
output.push(` ON ${qualsStr}`);
|
|
3732
|
-
}
|
|
3733
|
-
else {
|
|
3734
|
-
output.push(` ON${context.newline()}${context.indent(qualsStr)}`);
|
|
3735
|
-
}
|
|
3840
|
+
output.push(` ON${context.newline()}${context.indent(qualsStr)}`);
|
|
3736
3841
|
}
|
|
3737
3842
|
else {
|
|
3738
3843
|
output.push(` ON ${qualsStr}`);
|
|
@@ -3814,19 +3919,19 @@ class Deparser {
|
|
|
3814
3919
|
case 'TRANS_STMT_PREPARE':
|
|
3815
3920
|
output.push('PREPARE TRANSACTION');
|
|
3816
3921
|
if (node.gid) {
|
|
3817
|
-
output.push(
|
|
3922
|
+
output.push(quotes_1.QuoteUtils.escape(node.gid));
|
|
3818
3923
|
}
|
|
3819
3924
|
break;
|
|
3820
3925
|
case 'TRANS_STMT_COMMIT_PREPARED':
|
|
3821
3926
|
output.push('COMMIT PREPARED');
|
|
3822
3927
|
if (node.gid) {
|
|
3823
|
-
output.push(
|
|
3928
|
+
output.push(quotes_1.QuoteUtils.escape(node.gid));
|
|
3824
3929
|
}
|
|
3825
3930
|
break;
|
|
3826
3931
|
case 'TRANS_STMT_ROLLBACK_PREPARED':
|
|
3827
3932
|
output.push('ROLLBACK PREPARED');
|
|
3828
3933
|
if (node.gid) {
|
|
3829
|
-
output.push(
|
|
3934
|
+
output.push(quotes_1.QuoteUtils.escape(node.gid));
|
|
3830
3935
|
}
|
|
3831
3936
|
break;
|
|
3832
3937
|
default:
|
|
@@ -3893,17 +3998,25 @@ class Deparser {
|
|
|
3893
3998
|
switch (node.kind) {
|
|
3894
3999
|
case 'VAR_SET_VALUE':
|
|
3895
4000
|
const localPrefix = node.is_local ? 'LOCAL ' : '';
|
|
4001
|
+
if (node.jumble_args && node.name === 'xmloption' && node.args) {
|
|
4002
|
+
const xmlValue = this.getNodeData(list_utils_1.ListUtils.unwrapList(node.args)[0]);
|
|
4003
|
+
const xmlOption = (typeof xmlValue.sval === 'object' ? xmlValue.sval.sval : xmlValue.sval) || '';
|
|
4004
|
+
return `SET ${localPrefix}XML OPTION ${xmlOption.toUpperCase()}`;
|
|
4005
|
+
}
|
|
3896
4006
|
const args = node.args ? list_utils_1.ListUtils.unwrapList(node.args).map(arg => {
|
|
3897
4007
|
const nodeData = this.getNodeData(arg);
|
|
3898
4008
|
if (nodeData.sval !== undefined) {
|
|
3899
4009
|
const svalValue = typeof nodeData.sval === 'object' ? nodeData.sval.sval : nodeData.sval;
|
|
3900
|
-
if (svalValue
|
|
3901
|
-
return
|
|
4010
|
+
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)) {
|
|
4011
|
+
return quotes_1.QuoteUtils.escape(svalValue);
|
|
3902
4012
|
}
|
|
3903
4013
|
return svalValue;
|
|
3904
4014
|
}
|
|
3905
4015
|
return this.visit(arg, context);
|
|
3906
4016
|
}).join(', ') : '';
|
|
4017
|
+
if (node.jumble_args && node.name === 'timezone') {
|
|
4018
|
+
return `SET ${localPrefix}TIME ZONE ${args}`;
|
|
4019
|
+
}
|
|
3907
4020
|
// Handle args - always include TO clause if args exist (even if empty string)
|
|
3908
4021
|
const paramName = quotes_1.QuoteUtils.quoteIdentifier(node.name);
|
|
3909
4022
|
if (!node.args || node.args.length === 0) {
|
|
@@ -3911,6 +4024,9 @@ class Deparser {
|
|
|
3911
4024
|
}
|
|
3912
4025
|
return `SET ${localPrefix}${paramName} TO ${args}`;
|
|
3913
4026
|
case 'VAR_SET_DEFAULT':
|
|
4027
|
+
if (node.jumble_args && node.name === 'timezone') {
|
|
4028
|
+
return `SET ${node.is_local ? 'LOCAL ' : ''}TIME ZONE DEFAULT`;
|
|
4029
|
+
}
|
|
3914
4030
|
const defaultParamName = quotes_1.QuoteUtils.quoteIdentifier(node.name);
|
|
3915
4031
|
return `SET ${defaultParamName} TO DEFAULT`;
|
|
3916
4032
|
case 'VAR_SET_CURRENT':
|
|
@@ -4215,7 +4331,7 @@ class Deparser {
|
|
|
4215
4331
|
if (objList && objList.List && objList.List.items) {
|
|
4216
4332
|
const items = objList.List.items.map((item) => {
|
|
4217
4333
|
if (item.String && item.String.sval) {
|
|
4218
|
-
return item.String.sval;
|
|
4334
|
+
return quotes_1.QuoteUtils.quoteIdentifier(item.String.sval);
|
|
4219
4335
|
}
|
|
4220
4336
|
return this.visit(item, context);
|
|
4221
4337
|
});
|
|
@@ -4438,10 +4554,10 @@ class Deparser {
|
|
|
4438
4554
|
output.push('PROGRAM');
|
|
4439
4555
|
}
|
|
4440
4556
|
if (node.filename) {
|
|
4441
|
-
output.push(
|
|
4557
|
+
output.push(quotes_1.QuoteUtils.escape(node.filename));
|
|
4442
4558
|
}
|
|
4443
4559
|
else {
|
|
4444
|
-
output.push('STDIN');
|
|
4560
|
+
output.push(node.is_from ? 'STDIN' : 'STDOUT');
|
|
4445
4561
|
}
|
|
4446
4562
|
if (node.options && node.options.length > 0) {
|
|
4447
4563
|
output.push('WITH');
|
|
@@ -4673,6 +4789,9 @@ class Deparser {
|
|
|
4673
4789
|
const nodeData = this.getNodeData(node.def);
|
|
4674
4790
|
if (nodeData && nodeData.typeName) {
|
|
4675
4791
|
output.push(this.TypeName(nodeData.typeName, context));
|
|
4792
|
+
if (nodeData.collClause) {
|
|
4793
|
+
output.push(this.CollateClause(nodeData.collClause, context));
|
|
4794
|
+
}
|
|
4676
4795
|
// Handle USING clause (stored in raw_default for ALTER COLUMN TYPE)
|
|
4677
4796
|
if (nodeData.raw_default) {
|
|
4678
4797
|
output.push('USING');
|
|
@@ -5022,13 +5141,6 @@ class Deparser {
|
|
|
5022
5141
|
output.push('IF EXISTS');
|
|
5023
5142
|
}
|
|
5024
5143
|
break;
|
|
5025
|
-
case 'AT_CheckNotNull':
|
|
5026
|
-
output.push('ALTER COLUMN');
|
|
5027
|
-
if (node.name) {
|
|
5028
|
-
output.push(quotes_1.QuoteUtils.quoteIdentifier(node.name));
|
|
5029
|
-
}
|
|
5030
|
-
output.push('SET NOT NULL');
|
|
5031
|
-
break;
|
|
5032
5144
|
case 'AT_AddIndex':
|
|
5033
5145
|
output.push('ADD');
|
|
5034
5146
|
if (node.def) {
|
|
@@ -5054,23 +5166,28 @@ class Deparser {
|
|
|
5054
5166
|
}
|
|
5055
5167
|
break;
|
|
5056
5168
|
case 'AT_AlterConstraint':
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
|
|
5169
|
+
if (node.def && this.getNodeType(node.def) === 'ATAlterConstraint') {
|
|
5170
|
+
output.push(this.ATAlterConstraint(this.getNodeData(node.def), context));
|
|
5171
|
+
}
|
|
5172
|
+
else {
|
|
5173
|
+
output.push('ALTER CONSTRAINT');
|
|
5174
|
+
if (node.def && this.getNodeType(node.def) === 'Constraint') {
|
|
5175
|
+
const constraintData = this.getNodeData(node.def);
|
|
5176
|
+
if (constraintData.conname) {
|
|
5177
|
+
output.push(quotes_1.QuoteUtils.quoteIdentifier(constraintData.conname));
|
|
5178
|
+
if (constraintData.deferrable !== undefined) {
|
|
5179
|
+
output.push(constraintData.deferrable ? 'DEFERRABLE' : 'NOT DEFERRABLE');
|
|
5180
|
+
}
|
|
5181
|
+
if (constraintData.initdeferred !== undefined) {
|
|
5182
|
+
output.push(constraintData.initdeferred ? 'INITIALLY DEFERRED' : 'INITIALLY IMMEDIATE');
|
|
5183
|
+
}
|
|
5067
5184
|
}
|
|
5068
5185
|
}
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5186
|
+
else if (node.name) {
|
|
5187
|
+
output.push(quotes_1.QuoteUtils.quoteIdentifier(node.name));
|
|
5188
|
+
if (node.def) {
|
|
5189
|
+
output.push(this.visit(node.def, context));
|
|
5190
|
+
}
|
|
5074
5191
|
}
|
|
5075
5192
|
}
|
|
5076
5193
|
break;
|
|
@@ -5155,9 +5272,8 @@ class Deparser {
|
|
|
5155
5272
|
if (node.name) {
|
|
5156
5273
|
output.push(quotes_1.QuoteUtils.quoteIdentifier(node.name));
|
|
5157
5274
|
}
|
|
5158
|
-
output.push('SET');
|
|
5159
5275
|
if (node.def) {
|
|
5160
|
-
output.push(this.
|
|
5276
|
+
output.push(this.formatIdentityColumnOptions(node.def, context));
|
|
5161
5277
|
}
|
|
5162
5278
|
break;
|
|
5163
5279
|
case 'AT_DropIdentity':
|
|
@@ -5166,11 +5282,8 @@ class Deparser {
|
|
|
5166
5282
|
output.push(quotes_1.QuoteUtils.quoteIdentifier(node.name));
|
|
5167
5283
|
}
|
|
5168
5284
|
output.push('DROP IDENTITY');
|
|
5169
|
-
if (node.
|
|
5170
|
-
output.push('
|
|
5171
|
-
}
|
|
5172
|
-
else if (node.behavior === 'DROP_RESTRICT') {
|
|
5173
|
-
output.push('RESTRICT');
|
|
5285
|
+
if (node.missing_ok) {
|
|
5286
|
+
output.push('IF EXISTS');
|
|
5174
5287
|
}
|
|
5175
5288
|
break;
|
|
5176
5289
|
case 'AT_ReAddStatistics':
|
|
@@ -5264,6 +5377,7 @@ class Deparser {
|
|
|
5264
5377
|
if (bodyType === 'List') {
|
|
5265
5378
|
const statements = list_utils_1.ListUtils.unwrapList(node.sql_body);
|
|
5266
5379
|
if (statements.length === 0 || (statements.length === 1 && Object.keys(statements[0]).length === 0)) {
|
|
5380
|
+
// empty body: nothing to emit
|
|
5267
5381
|
}
|
|
5268
5382
|
else {
|
|
5269
5383
|
// Handle nested List structure in BEGIN ATOMIC blocks
|
|
@@ -5411,19 +5525,22 @@ class Deparser {
|
|
|
5411
5525
|
if (node.arg && this.getNodeType(node.arg) === 'List') {
|
|
5412
5526
|
const listData = this.getNodeData(node.arg);
|
|
5413
5527
|
const listItems = list_utils_1.ListUtils.unwrapList(listData.items);
|
|
5528
|
+
const preservedName = this.preserveOperatorDefElemCase(node.defname);
|
|
5414
5529
|
if (listItems.length === 1 && listItems[0].String) {
|
|
5415
|
-
const preservedName = this.preserveOperatorDefElemCase(node.defname);
|
|
5416
5530
|
return `${preservedName} = ${listItems[0].String.sval}`;
|
|
5417
5531
|
}
|
|
5532
|
+
if (listItems.length > 1 && listItems.every((item) => item.String)) {
|
|
5533
|
+
return `${preservedName} = OPERATOR(${this.qualifiedOperatorName(listItems)})`;
|
|
5534
|
+
}
|
|
5418
5535
|
}
|
|
5419
5536
|
}
|
|
5420
5537
|
// Handle IndexElem opclassopts - MUST be first to preserve string types
|
|
5421
5538
|
if (context.parentNodeTypes.includes('IndexElem')) {
|
|
5422
5539
|
if (node.arg && this.getNodeType(node.arg) === 'String') {
|
|
5423
5540
|
const stringData = this.getNodeData(node.arg);
|
|
5424
|
-
return `${node.defname}
|
|
5541
|
+
return `${quotes_1.QuoteUtils.quoteIdentifierAfterDot(node.defname)}=${quotes_1.QuoteUtils.escape(stringData.sval)}`;
|
|
5425
5542
|
}
|
|
5426
|
-
return `${node.defname}=${this.visit(node.arg, context.spawn('DefElem'))}`;
|
|
5543
|
+
return `${quotes_1.QuoteUtils.quoteIdentifierAfterDot(node.defname)}=${this.formatOptionValue(node.arg, this.visit(node.arg, context.spawn('DefElem')))}`;
|
|
5427
5544
|
}
|
|
5428
5545
|
// Handle CREATE OPERATOR boolean flags - MUST be first to preserve case
|
|
5429
5546
|
if (context.parentNodeTypes.includes('DefineStmt') &&
|
|
@@ -5448,9 +5565,7 @@ class Deparser {
|
|
|
5448
5565
|
const defElemContext = context.spawn('DefElem');
|
|
5449
5566
|
const argValue = this.visit(node.arg, defElemContext);
|
|
5450
5567
|
if (context.parentNodeTypes.includes('CreateFdwStmt') || context.parentNodeTypes.includes('AlterFdwStmt')) {
|
|
5451
|
-
const finalValue =
|
|
5452
|
-
? `'${argValue}'`
|
|
5453
|
-
: argValue;
|
|
5568
|
+
const finalValue = this.quoteDefElemArg(node.arg, argValue);
|
|
5454
5569
|
const quotedDefname = quotes_1.QuoteUtils.quoteIdentifier(node.defname);
|
|
5455
5570
|
if (node.defaction === 'DEFELEM_ADD') {
|
|
5456
5571
|
return `ADD ${quotedDefname} ${finalValue}`;
|
|
@@ -5463,9 +5578,7 @@ class Deparser {
|
|
|
5463
5578
|
}
|
|
5464
5579
|
return `${quotedDefname} ${finalValue}`;
|
|
5465
5580
|
}
|
|
5466
|
-
const quotedValue =
|
|
5467
|
-
? `'${argValue}'`
|
|
5468
|
-
: argValue;
|
|
5581
|
+
const quotedValue = this.quoteDefElemArg(node.arg, argValue);
|
|
5469
5582
|
if (node.defaction === 'DEFELEM_ADD') {
|
|
5470
5583
|
return `ADD ${node.defname} ${quotedValue}`;
|
|
5471
5584
|
}
|
|
@@ -5497,9 +5610,7 @@ class Deparser {
|
|
|
5497
5610
|
}
|
|
5498
5611
|
const defElemContext = context.spawn('DefElem');
|
|
5499
5612
|
const argValue = this.visit(node.arg, defElemContext);
|
|
5500
|
-
const quotedValue =
|
|
5501
|
-
? `'${argValue}'`
|
|
5502
|
-
: argValue;
|
|
5613
|
+
const quotedValue = this.quoteDefElemArg(node.arg, argValue);
|
|
5503
5614
|
return `PASSWORD ${quotedValue}`;
|
|
5504
5615
|
}
|
|
5505
5616
|
}
|
|
@@ -5522,6 +5633,9 @@ class Deparser {
|
|
|
5522
5633
|
if (listItems.length === 1 && listItems[0].String) {
|
|
5523
5634
|
return `${node.defname} = ${listItems[0].String.sval}`;
|
|
5524
5635
|
}
|
|
5636
|
+
if (listItems.length > 1 && listItems.every((item) => item.String)) {
|
|
5637
|
+
return `${node.defname} = OPERATOR(${this.qualifiedOperatorName(listItems)})`;
|
|
5638
|
+
}
|
|
5525
5639
|
}
|
|
5526
5640
|
}
|
|
5527
5641
|
if (context.parentNodeTypes.includes('CreatedbStmt') || context.parentNodeTypes.includes('DropdbStmt')) {
|
|
@@ -5564,9 +5678,7 @@ class Deparser {
|
|
|
5564
5678
|
}
|
|
5565
5679
|
}
|
|
5566
5680
|
if (node.defname === 'validUntil') {
|
|
5567
|
-
const quotedValue =
|
|
5568
|
-
? `'${argValue}'`
|
|
5569
|
-
: argValue;
|
|
5681
|
+
const quotedValue = this.quoteDefElemArg(node.arg, argValue);
|
|
5570
5682
|
return `VALID UNTIL ${quotedValue}`;
|
|
5571
5683
|
}
|
|
5572
5684
|
if (node.defname === 'adminmembers') {
|
|
@@ -5605,6 +5717,9 @@ class Deparser {
|
|
|
5605
5717
|
if (node.arg && this.getNodeType(node.arg) === 'List') {
|
|
5606
5718
|
const listData = this.getNodeData(node.arg);
|
|
5607
5719
|
const listItems = list_utils_1.ListUtils.unwrapList(listData.items);
|
|
5720
|
+
if (listItems.length === 1 && listItems[0].String?.sval === 'none') {
|
|
5721
|
+
return 'OWNED BY NONE';
|
|
5722
|
+
}
|
|
5608
5723
|
const parts = listItems.map(item => {
|
|
5609
5724
|
const itemData = this.getNodeData(item);
|
|
5610
5725
|
if (this.getNodeType(item) === 'String') {
|
|
@@ -5743,10 +5858,8 @@ class Deparser {
|
|
|
5743
5858
|
if (context.parentNodeTypes.includes('AlterExtensionStmt')) {
|
|
5744
5859
|
if (node.defname === 'new_version') {
|
|
5745
5860
|
// argValue is unquoted due to DefElem context, so we need to quote it
|
|
5746
|
-
const quotedValue =
|
|
5747
|
-
|
|
5748
|
-
: argValue;
|
|
5749
|
-
return `UPDATE TO ${quotedValue}`;
|
|
5861
|
+
const quotedValue = this.quoteDefElemArg(node.arg, argValue);
|
|
5862
|
+
return `TO ${quotedValue}`;
|
|
5750
5863
|
}
|
|
5751
5864
|
if (node.defname === 'schema') {
|
|
5752
5865
|
return `SET SCHEMA ${argValue}`;
|
|
@@ -5766,28 +5879,37 @@ class Deparser {
|
|
|
5766
5879
|
if (node.defname === 'cascade') {
|
|
5767
5880
|
return argValue === 'true' ? 'CASCADE' : '';
|
|
5768
5881
|
}
|
|
5882
|
+
if (node.defname === 'new_version') {
|
|
5883
|
+
return `VERSION ${this.quoteDefElemArg(node.arg, argValue)}`;
|
|
5884
|
+
}
|
|
5885
|
+
if (node.defname === 'schema' && node.arg && this.getNodeType(node.arg) === 'String') {
|
|
5886
|
+
return `SCHEMA ${quotes_1.QuoteUtils.quoteIdentifier(this.getNodeData(node.arg).sval)}`;
|
|
5887
|
+
}
|
|
5769
5888
|
return `${node.defname.toUpperCase()} ${argValue}`;
|
|
5770
5889
|
}
|
|
5771
5890
|
// Handle IndexStmt WITH clause options - no quotes, compact formatting
|
|
5772
5891
|
if (context.parentNodeTypes.includes('IndexStmt')) {
|
|
5773
|
-
return `${node.defname}=${argValue}`;
|
|
5892
|
+
return `${quotes_1.QuoteUtils.quoteIdentifierAfterDot(node.defname)}=${this.formatOptionValue(node.arg, argValue)}`;
|
|
5774
5893
|
}
|
|
5775
5894
|
// Handle IndexElem opclassopts - preserve string values as strings
|
|
5776
5895
|
if (context.parentNodeTypes.includes('IndexElem')) {
|
|
5777
5896
|
if (node.arg && this.getNodeType(node.arg) === 'String') {
|
|
5778
5897
|
const stringData = this.getNodeData(node.arg);
|
|
5779
|
-
return `${node.defname}
|
|
5898
|
+
return `${quotes_1.QuoteUtils.quoteIdentifierAfterDot(node.defname)}=${quotes_1.QuoteUtils.escape(stringData.sval)}`;
|
|
5780
5899
|
}
|
|
5781
|
-
return `${node.defname}=${argValue}`;
|
|
5900
|
+
return `${quotes_1.QuoteUtils.quoteIdentifierAfterDot(node.defname)}=${this.formatOptionValue(node.arg, argValue)}`;
|
|
5782
5901
|
}
|
|
5783
5902
|
// Handle CreateStmt table options - no quotes, compact formatting
|
|
5784
5903
|
if (context.parentNodeTypes.includes('CreateStmt')) {
|
|
5904
|
+
const relOptName = node.defnamespace
|
|
5905
|
+
? `${quotes_1.QuoteUtils.quoteIdentifier(node.defnamespace)}.${quotes_1.QuoteUtils.quoteIdentifier(node.defname)}`
|
|
5906
|
+
: quotes_1.QuoteUtils.quoteIdentifier(node.defname);
|
|
5785
5907
|
// For numeric values, use the raw value without quotes
|
|
5786
5908
|
if (node.arg && this.getNodeType(node.arg) === 'Integer') {
|
|
5787
5909
|
const integerData = this.getNodeData(node.arg);
|
|
5788
|
-
return `${
|
|
5910
|
+
return `${relOptName}=${formatInteger(integerData.ival)}`;
|
|
5789
5911
|
}
|
|
5790
|
-
return `${
|
|
5912
|
+
return `${relOptName}=${this.formatOptionValue(node.arg, argValue)}`;
|
|
5791
5913
|
}
|
|
5792
5914
|
// Handle CreateEventTrigStmt WHEN clause - use IN syntax for List arguments
|
|
5793
5915
|
if (context.parentNodeTypes.includes('CreateEventTrigStmt')) {
|
|
@@ -5797,7 +5919,7 @@ class Deparser {
|
|
|
5797
5919
|
const values = listItems.map(item => {
|
|
5798
5920
|
if (this.getNodeType(item) === 'String') {
|
|
5799
5921
|
const stringData = this.getNodeData(item);
|
|
5800
|
-
return
|
|
5922
|
+
return quotes_1.QuoteUtils.escape(stringData.sval || '');
|
|
5801
5923
|
}
|
|
5802
5924
|
return this.visit(item, context);
|
|
5803
5925
|
});
|
|
@@ -5812,7 +5934,7 @@ class Deparser {
|
|
|
5812
5934
|
if (node.arg && this.getNodeType(node.arg) === 'TypeName') {
|
|
5813
5935
|
return `${optionName} = ${argValue}`;
|
|
5814
5936
|
}
|
|
5815
|
-
return `${optionName} = ${argValue}`;
|
|
5937
|
+
return `${optionName} = ${this.formatOptionValue(node.arg, argValue)}`;
|
|
5816
5938
|
}
|
|
5817
5939
|
// Handle ViewStmt WITH options - don't quote numeric values
|
|
5818
5940
|
if (context.parentNodeTypes.includes('ViewStmt')) {
|
|
@@ -5826,15 +5948,27 @@ class Deparser {
|
|
|
5826
5948
|
}
|
|
5827
5949
|
// Handle CopyStmt WITH clause options - uppercase format without quotes
|
|
5828
5950
|
if (context.parentNodeTypes.includes('CopyStmt')) {
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
return
|
|
5951
|
+
const optName = node.defname.toUpperCase();
|
|
5952
|
+
if (!node.arg) {
|
|
5953
|
+
return optName;
|
|
5954
|
+
}
|
|
5955
|
+
const copyArgType = this.getNodeType(node.arg);
|
|
5956
|
+
if (copyArgType === 'Boolean' && this.getNodeData(node.arg).boolval !== false) {
|
|
5957
|
+
return optName;
|
|
5832
5958
|
}
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5959
|
+
if (copyArgType === 'List') {
|
|
5960
|
+
const items = list_utils_1.ListUtils.unwrapList(this.getNodeData(node.arg).items)
|
|
5961
|
+
.map(item => this.visit(item, context));
|
|
5962
|
+
return `${optName} (${items.join(', ')})`;
|
|
5963
|
+
}
|
|
5964
|
+
if (copyArgType === 'String') {
|
|
5965
|
+
const sval = this.getNodeData(node.arg).sval;
|
|
5966
|
+
if (node.defname === 'format') {
|
|
5967
|
+
return `${optName} ${sval}`;
|
|
5968
|
+
}
|
|
5969
|
+
return `${optName} ${quotes_1.QuoteUtils.escape(sval)}`;
|
|
5836
5970
|
}
|
|
5837
|
-
return
|
|
5971
|
+
return `${optName} ${argValue}`;
|
|
5838
5972
|
}
|
|
5839
5973
|
// Handle CREATE OPERATOR and CREATE TYPE context
|
|
5840
5974
|
if (context.parentNodeTypes.includes('DefineStmt')) {
|
|
@@ -5873,7 +6007,7 @@ class Deparser {
|
|
|
5873
6007
|
return `${quotedDefname} = ${stringData.sval}`;
|
|
5874
6008
|
}
|
|
5875
6009
|
// Regular string literals get single quotes
|
|
5876
|
-
return `${quotedDefname} =
|
|
6010
|
+
return `${quotedDefname} = ${quotes_1.QuoteUtils.escape(stringData.sval)}`;
|
|
5877
6011
|
}
|
|
5878
6012
|
return `${quotedDefname} = ${argValue}`;
|
|
5879
6013
|
}
|
|
@@ -5894,7 +6028,7 @@ class Deparser {
|
|
|
5894
6028
|
return `${node.defname} = ${stringData.sval}`;
|
|
5895
6029
|
}
|
|
5896
6030
|
// Regular string literals get single quotes
|
|
5897
|
-
return `${node.defname} =
|
|
6031
|
+
return `${node.defname} = ${quotes_1.QuoteUtils.escape(stringData.sval)}`;
|
|
5898
6032
|
}
|
|
5899
6033
|
if (node.arg && this.getNodeType(node.arg) === 'Boolean') {
|
|
5900
6034
|
const boolData = this.getNodeData(node.arg);
|
|
@@ -5915,6 +6049,10 @@ class Deparser {
|
|
|
5915
6049
|
return `${node.defname} = ${argValue}`;
|
|
5916
6050
|
}
|
|
5917
6051
|
}
|
|
6052
|
+
const argType = this.getNodeType(node.arg);
|
|
6053
|
+
if (argType === 'TypeName' || argType === 'Integer' || argType === 'Float' || argType === 'Boolean') {
|
|
6054
|
+
return `${node.defname} = ${argValue}`;
|
|
6055
|
+
}
|
|
5918
6056
|
const quotedValue = typeof argValue === 'string'
|
|
5919
6057
|
? quotes_1.QuoteUtils.escape(argValue)
|
|
5920
6058
|
: argValue;
|
|
@@ -5940,7 +6078,7 @@ class Deparser {
|
|
|
5940
6078
|
}
|
|
5941
6079
|
if (node.location) {
|
|
5942
6080
|
output.push('LOCATION');
|
|
5943
|
-
output.push(
|
|
6081
|
+
output.push(quotes_1.QuoteUtils.escape(node.location));
|
|
5944
6082
|
}
|
|
5945
6083
|
if (node.options && node.options.length > 0) {
|
|
5946
6084
|
output.push('WITH');
|
|
@@ -6004,6 +6142,7 @@ class Deparser {
|
|
|
6004
6142
|
if (node.extname) {
|
|
6005
6143
|
output.push(this.quoteIfNeeded(node.extname));
|
|
6006
6144
|
}
|
|
6145
|
+
output.push('UPDATE');
|
|
6007
6146
|
if (node.options && node.options.length > 0) {
|
|
6008
6147
|
const extContext = context.spawn('AlterExtensionStmt');
|
|
6009
6148
|
const options = list_utils_1.ListUtils.unwrapList(node.options)
|
|
@@ -6273,7 +6412,7 @@ class Deparser {
|
|
|
6273
6412
|
}
|
|
6274
6413
|
if (node.payload !== null && node.payload !== undefined) {
|
|
6275
6414
|
output.push(',');
|
|
6276
|
-
output.push(
|
|
6415
|
+
output.push(quotes_1.QuoteUtils.escape(node.payload));
|
|
6277
6416
|
}
|
|
6278
6417
|
return output.join(' ');
|
|
6279
6418
|
}
|
|
@@ -6301,7 +6440,7 @@ class Deparser {
|
|
|
6301
6440
|
if (!node.filename) {
|
|
6302
6441
|
throw new Error('LoadStmt requires filename');
|
|
6303
6442
|
}
|
|
6304
|
-
return `LOAD
|
|
6443
|
+
return `LOAD ${quotes_1.QuoteUtils.escape(node.filename)}`;
|
|
6305
6444
|
}
|
|
6306
6445
|
DiscardStmt(node, context) {
|
|
6307
6446
|
switch (node.target) {
|
|
@@ -6317,6 +6456,13 @@ class Deparser {
|
|
|
6317
6456
|
throw new Error(`Unsupported DiscardStmt target: ${node.target}`);
|
|
6318
6457
|
}
|
|
6319
6458
|
}
|
|
6459
|
+
/** `schema.op` for an operator name list: schema parts quoted, the operator symbol as is. */
|
|
6460
|
+
qualifiedOperatorName(objname) {
|
|
6461
|
+
const names = list_utils_1.ListUtils.unwrapList(objname ?? []).map((n) => (n.String ? n.String.sval : 'unknown'));
|
|
6462
|
+
if (names.length === 0)
|
|
6463
|
+
return 'unknown';
|
|
6464
|
+
return [...names.slice(0, -1).map((n) => quotes_1.QuoteUtils.quoteIdentifier(n)), names[names.length - 1]].join('.');
|
|
6465
|
+
}
|
|
6320
6466
|
CommentStmt(node, context) {
|
|
6321
6467
|
const output = ['COMMENT ON'];
|
|
6322
6468
|
if (node.objtype) {
|
|
@@ -6348,6 +6494,9 @@ class Deparser {
|
|
|
6348
6494
|
case 'OBJECT_TABCONSTRAINT':
|
|
6349
6495
|
output.push('CONSTRAINT');
|
|
6350
6496
|
break;
|
|
6497
|
+
case 'OBJECT_DOMCONSTRAINT':
|
|
6498
|
+
output.push('CONSTRAINT');
|
|
6499
|
+
break;
|
|
6351
6500
|
case 'OBJECT_TRIGGER':
|
|
6352
6501
|
output.push('TRIGGER');
|
|
6353
6502
|
break;
|
|
@@ -6424,23 +6573,30 @@ class Deparser {
|
|
|
6424
6573
|
output.push(objectParts.join('.'));
|
|
6425
6574
|
}
|
|
6426
6575
|
}
|
|
6427
|
-
else if (node.objtype === '
|
|
6576
|
+
else if (node.objtype === 'OBJECT_DOMCONSTRAINT') {
|
|
6428
6577
|
if (objectParts.length === 2) {
|
|
6429
|
-
const [
|
|
6430
|
-
output.push(
|
|
6578
|
+
const [domain, constraint] = objectParts;
|
|
6579
|
+
output.push(constraint, 'ON DOMAIN', domain);
|
|
6580
|
+
}
|
|
6581
|
+
else {
|
|
6582
|
+
output.push(objectParts.join('.'));
|
|
6583
|
+
}
|
|
6584
|
+
}
|
|
6585
|
+
else if (node.objtype === 'OBJECT_TRIGGER') {
|
|
6586
|
+
if (objectParts.length >= 2) {
|
|
6587
|
+
output.push(objectParts[objectParts.length - 1]);
|
|
6431
6588
|
output.push('ON');
|
|
6432
|
-
output.push(
|
|
6589
|
+
output.push(objectParts.slice(0, -1).join('.'));
|
|
6433
6590
|
}
|
|
6434
6591
|
else {
|
|
6435
6592
|
output.push(objectParts.join('.'));
|
|
6436
6593
|
}
|
|
6437
6594
|
}
|
|
6438
6595
|
else if (node.objtype === 'OBJECT_RULE') {
|
|
6439
|
-
if (objectParts.length
|
|
6440
|
-
|
|
6441
|
-
output.push(rule);
|
|
6596
|
+
if (objectParts.length >= 2) {
|
|
6597
|
+
output.push(objectParts[objectParts.length - 1]);
|
|
6442
6598
|
output.push('ON');
|
|
6443
|
-
output.push(
|
|
6599
|
+
output.push(objectParts.slice(0, -1).join('.'));
|
|
6444
6600
|
}
|
|
6445
6601
|
else {
|
|
6446
6602
|
output.push(objectParts.join('.'));
|
|
@@ -6451,8 +6607,7 @@ class Deparser {
|
|
|
6451
6607
|
// For operators, we need to handle ObjectWithArgs structure
|
|
6452
6608
|
if (node.object && node.object.ObjectWithArgs) {
|
|
6453
6609
|
const objWithArgs = node.object.ObjectWithArgs;
|
|
6454
|
-
let operatorName =
|
|
6455
|
-
? objWithArgs.objname[0].String.sval : 'unknown';
|
|
6610
|
+
let operatorName = this.qualifiedOperatorName(objWithArgs.objname);
|
|
6456
6611
|
if (operatorName.startsWith('"') && operatorName.endsWith('"')) {
|
|
6457
6612
|
operatorName = operatorName.slice(1, -1);
|
|
6458
6613
|
}
|
|
@@ -6490,7 +6645,13 @@ class Deparser {
|
|
|
6490
6645
|
}
|
|
6491
6646
|
else if (node.objtype === 'OBJECT_POLICY') {
|
|
6492
6647
|
// Handle POLICY syntax: COMMENT ON POLICY policy_name ON table_name IS 'comment'
|
|
6493
|
-
if (objectParts.length ===
|
|
6648
|
+
if (objectParts.length === 3) {
|
|
6649
|
+
const [schema, table, policy] = objectParts;
|
|
6650
|
+
output.push(policy);
|
|
6651
|
+
output.push('ON');
|
|
6652
|
+
output.push(`${schema}.${table}`);
|
|
6653
|
+
}
|
|
6654
|
+
else if (objectParts.length === 2) {
|
|
6494
6655
|
const [table, policy] = objectParts;
|
|
6495
6656
|
output.push(policy);
|
|
6496
6657
|
output.push('ON');
|
|
@@ -6513,6 +6674,9 @@ class Deparser {
|
|
|
6513
6674
|
output.push(objectParts.join('.'));
|
|
6514
6675
|
}
|
|
6515
6676
|
}
|
|
6677
|
+
else if (node.objtype === 'OBJECT_CAST' && objectParts.length === 2) {
|
|
6678
|
+
output.push(`(${objectParts[0]} AS ${objectParts[1]})`);
|
|
6679
|
+
}
|
|
6516
6680
|
else {
|
|
6517
6681
|
output.push(objectParts.join('.'));
|
|
6518
6682
|
}
|
|
@@ -6521,8 +6685,7 @@ class Deparser {
|
|
|
6521
6685
|
else if (node.objtype === 'OBJECT_OPERATOR' && node.object && node.object.ObjectWithArgs) {
|
|
6522
6686
|
// Handle direct ObjectWithArgs for OPERATOR syntax: COMMENT ON OPERATOR -(NONE, integer) IS 'comment'
|
|
6523
6687
|
const objWithArgs = node.object.ObjectWithArgs;
|
|
6524
|
-
let operatorName =
|
|
6525
|
-
? objWithArgs.objname[0].String.sval : 'unknown';
|
|
6688
|
+
let operatorName = this.qualifiedOperatorName(objWithArgs.objname);
|
|
6526
6689
|
// Remove quotes from operator name if present
|
|
6527
6690
|
if (operatorName.startsWith('"') && operatorName.endsWith('"')) {
|
|
6528
6691
|
operatorName = operatorName.slice(1, -1);
|
|
@@ -6755,7 +6918,7 @@ class Deparser {
|
|
|
6755
6918
|
output.push(quotes_1.QuoteUtils.quoteIdentifier(node.pubname));
|
|
6756
6919
|
}
|
|
6757
6920
|
if (node.pubobjects && node.pubobjects.length > 0) {
|
|
6758
|
-
output.push('FOR'
|
|
6921
|
+
output.push('FOR');
|
|
6759
6922
|
const tables = list_utils_1.ListUtils.unwrapList(node.pubobjects).map(table => this.visit(table, context));
|
|
6760
6923
|
output.push(tables.join(', '));
|
|
6761
6924
|
}
|
|
@@ -6776,7 +6939,7 @@ class Deparser {
|
|
|
6776
6939
|
}
|
|
6777
6940
|
output.push('CONNECTION');
|
|
6778
6941
|
if (node.conninfo) {
|
|
6779
|
-
output.push(
|
|
6942
|
+
output.push(quotes_1.QuoteUtils.escape(node.conninfo));
|
|
6780
6943
|
}
|
|
6781
6944
|
output.push('PUBLICATION');
|
|
6782
6945
|
if (node.publication && node.publication.length > 0) {
|
|
@@ -6795,8 +6958,9 @@ class Deparser {
|
|
|
6795
6958
|
if (node.pubname) {
|
|
6796
6959
|
output.push(quotes_1.QuoteUtils.quoteIdentifier(node.pubname));
|
|
6797
6960
|
}
|
|
6798
|
-
|
|
6799
|
-
|
|
6961
|
+
const hasObjects = node.pubobjects && node.pubobjects.length > 0;
|
|
6962
|
+
if (hasObjects) {
|
|
6963
|
+
switch (node.action || 'AP_AddObjects') {
|
|
6800
6964
|
case 'AP_AddObjects':
|
|
6801
6965
|
output.push('ADD');
|
|
6802
6966
|
break;
|
|
@@ -6809,17 +6973,11 @@ class Deparser {
|
|
|
6809
6973
|
default:
|
|
6810
6974
|
throw new Error(`Unsupported AlterPublicationStmt action: ${node.action}`);
|
|
6811
6975
|
}
|
|
6812
|
-
}
|
|
6813
|
-
if (node.for_all_tables) {
|
|
6814
|
-
output.push('FOR ALL TABLES');
|
|
6815
|
-
}
|
|
6816
|
-
else if (node.pubobjects && node.pubobjects.length > 0) {
|
|
6817
|
-
output.push('FOR TABLE');
|
|
6818
6976
|
const objects = list_utils_1.ListUtils.unwrapList(node.pubobjects).map(obj => this.visit(obj, context));
|
|
6819
6977
|
output.push(objects.join(', '));
|
|
6820
6978
|
}
|
|
6821
|
-
if (node.options && node.options.length > 0) {
|
|
6822
|
-
output.push('
|
|
6979
|
+
else if (node.options && node.options.length > 0) {
|
|
6980
|
+
output.push('SET');
|
|
6823
6981
|
const options = list_utils_1.ListUtils.unwrapList(node.options).map(opt => this.visit(opt, context));
|
|
6824
6982
|
output.push(`(${options.join(', ')})`);
|
|
6825
6983
|
}
|
|
@@ -6830,42 +6988,67 @@ class Deparser {
|
|
|
6830
6988
|
if (node.subname) {
|
|
6831
6989
|
output.push(quotes_1.QuoteUtils.quoteIdentifier(node.subname));
|
|
6832
6990
|
}
|
|
6833
|
-
|
|
6834
|
-
|
|
6991
|
+
const options = node.options && node.options.length > 0
|
|
6992
|
+
? `(${list_utils_1.ListUtils.unwrapList(node.options).map(opt => this.visit(opt, context)).join(', ')})`
|
|
6993
|
+
: null;
|
|
6994
|
+
const publications = node.publication && node.publication.length > 0
|
|
6995
|
+
? list_utils_1.ListUtils.unwrapList(node.publication).map(pub => this.visit(pub, context)).join(', ')
|
|
6996
|
+
: null;
|
|
6997
|
+
{
|
|
6998
|
+
switch (node.kind || 'ALTER_SUBSCRIPTION_OPTIONS') {
|
|
6835
6999
|
case 'ALTER_SUBSCRIPTION_OPTIONS':
|
|
6836
7000
|
output.push('SET');
|
|
7001
|
+
if (options)
|
|
7002
|
+
output.push(options);
|
|
6837
7003
|
break;
|
|
6838
7004
|
case 'ALTER_SUBSCRIPTION_CONNECTION':
|
|
6839
7005
|
output.push('CONNECTION');
|
|
6840
7006
|
if (node.conninfo) {
|
|
6841
|
-
output.push(
|
|
7007
|
+
output.push(quotes_1.QuoteUtils.escape(node.conninfo));
|
|
6842
7008
|
}
|
|
6843
7009
|
break;
|
|
6844
7010
|
case 'ALTER_SUBSCRIPTION_SET_PUBLICATION':
|
|
6845
7011
|
output.push('SET PUBLICATION');
|
|
6846
|
-
if (
|
|
6847
|
-
|
|
6848
|
-
|
|
6849
|
-
|
|
7012
|
+
if (publications)
|
|
7013
|
+
output.push(publications);
|
|
7014
|
+
if (options)
|
|
7015
|
+
output.push('WITH', options);
|
|
7016
|
+
break;
|
|
7017
|
+
case 'ALTER_SUBSCRIPTION_ADD_PUBLICATION':
|
|
7018
|
+
output.push('ADD PUBLICATION');
|
|
7019
|
+
if (publications)
|
|
7020
|
+
output.push(publications);
|
|
7021
|
+
if (options)
|
|
7022
|
+
output.push('WITH', options);
|
|
7023
|
+
break;
|
|
7024
|
+
case 'ALTER_SUBSCRIPTION_DROP_PUBLICATION':
|
|
7025
|
+
output.push('DROP PUBLICATION');
|
|
7026
|
+
if (publications)
|
|
7027
|
+
output.push(publications);
|
|
7028
|
+
if (options)
|
|
7029
|
+
output.push('WITH', options);
|
|
6850
7030
|
break;
|
|
6851
7031
|
case 'ALTER_SUBSCRIPTION_REFRESH':
|
|
6852
7032
|
output.push('REFRESH PUBLICATION');
|
|
7033
|
+
if (options)
|
|
7034
|
+
output.push('WITH', options);
|
|
6853
7035
|
break;
|
|
6854
|
-
case 'ALTER_SUBSCRIPTION_ENABLED':
|
|
6855
|
-
|
|
7036
|
+
case 'ALTER_SUBSCRIPTION_ENABLED': {
|
|
7037
|
+
const enabled = list_utils_1.ListUtils.unwrapList(node.options).find(opt => opt.DefElem?.defname === 'enabled');
|
|
7038
|
+
const arg = enabled?.DefElem?.arg;
|
|
7039
|
+
const isEnabled = arg?.Boolean ? arg.Boolean.boolval !== false : true;
|
|
7040
|
+
output.push(isEnabled ? 'ENABLE' : 'DISABLE');
|
|
6856
7041
|
break;
|
|
7042
|
+
}
|
|
6857
7043
|
case 'ALTER_SUBSCRIPTION_SKIP':
|
|
6858
7044
|
output.push('SKIP');
|
|
7045
|
+
if (options)
|
|
7046
|
+
output.push(options);
|
|
6859
7047
|
break;
|
|
6860
7048
|
default:
|
|
6861
7049
|
throw new Error(`Unsupported AlterSubscriptionStmt kind: ${node.kind}`);
|
|
6862
7050
|
}
|
|
6863
7051
|
}
|
|
6864
|
-
if (node.options && node.options.length > 0) {
|
|
6865
|
-
output.push('WITH');
|
|
6866
|
-
const options = list_utils_1.ListUtils.unwrapList(node.options).map(opt => this.visit(opt, context));
|
|
6867
|
-
output.push(`(${options.join(', ')})`);
|
|
6868
|
-
}
|
|
6869
7052
|
return output.join(' ');
|
|
6870
7053
|
}
|
|
6871
7054
|
DropSubscriptionStmt(node, context) {
|
|
@@ -7694,6 +7877,15 @@ class Deparser {
|
|
|
7694
7877
|
output.push(this.visit(node.object, context));
|
|
7695
7878
|
}
|
|
7696
7879
|
}
|
|
7880
|
+
else if ((node.renameType === 'OBJECT_TYPE' || node.renameType === 'OBJECT_DOMAIN') && node.object.List) {
|
|
7881
|
+
// Qualified type names - join List parts with dots
|
|
7882
|
+
const items = list_utils_1.ListUtils.unwrapList(node.object);
|
|
7883
|
+
const parts = items
|
|
7884
|
+
.map((item) => item.String?.sval)
|
|
7885
|
+
.filter((s) => typeof s === 'string')
|
|
7886
|
+
.map((s) => this.quoteIfNeeded(s));
|
|
7887
|
+
output.push(parts.join('.'));
|
|
7888
|
+
}
|
|
7697
7889
|
else if (node.renameType === 'OBJECT_SCHEMA' && node.object.List) {
|
|
7698
7890
|
// Handle schema names - extract from List structure
|
|
7699
7891
|
const items = list_utils_1.ListUtils.unwrapList(node.object);
|
|
@@ -7833,6 +8025,9 @@ class Deparser {
|
|
|
7833
8025
|
else if (node.objtype === 'OBJECT_LANGUAGE') {
|
|
7834
8026
|
output.push('LANGUAGE');
|
|
7835
8027
|
}
|
|
8028
|
+
else if (node.objtype === 'OBJECT_SEQUENCE') {
|
|
8029
|
+
output.push('SEQUENCE');
|
|
8030
|
+
}
|
|
7836
8031
|
else if (node.objtype === 'OBJECT_FUNCTION') {
|
|
7837
8032
|
output.push('FUNCTION');
|
|
7838
8033
|
}
|
|
@@ -7858,8 +8053,11 @@ class Deparser {
|
|
|
7858
8053
|
output.push('DATABASE');
|
|
7859
8054
|
}
|
|
7860
8055
|
if (node.objects && node.objects.length > 0) {
|
|
8056
|
+
const qualifiedKinds = ['OBJECT_TYPE', 'OBJECT_DOMAIN'];
|
|
7861
8057
|
const objects = list_utils_1.ListUtils.unwrapList(node.objects)
|
|
7862
|
-
.map(obj =>
|
|
8058
|
+
.map(obj => qualifiedKinds.includes(node.objtype) && obj.List
|
|
8059
|
+
? list_utils_1.ListUtils.unwrapList(obj.List.items).map((item) => this.visit(item, context)).join('.')
|
|
8060
|
+
: this.visit(obj, context))
|
|
7863
8061
|
.join(', ');
|
|
7864
8062
|
output.push(objects);
|
|
7865
8063
|
}
|
|
@@ -7898,8 +8096,11 @@ class Deparser {
|
|
|
7898
8096
|
break;
|
|
7899
8097
|
default:
|
|
7900
8098
|
if (node.objects && node.objects.length > 0) {
|
|
8099
|
+
const qualifiedKinds = ['OBJECT_TYPE', 'OBJECT_DOMAIN'];
|
|
7901
8100
|
const objects = list_utils_1.ListUtils.unwrapList(node.objects)
|
|
7902
|
-
.map(obj =>
|
|
8101
|
+
.map(obj => qualifiedKinds.includes(node.objtype) && obj.List
|
|
8102
|
+
? list_utils_1.ListUtils.unwrapList(obj.List.items).map((item) => this.visit(item, context)).join('.')
|
|
8103
|
+
: this.visit(obj, context))
|
|
7903
8104
|
.join(', ');
|
|
7904
8105
|
output.push(objects);
|
|
7905
8106
|
}
|
|
@@ -7919,6 +8120,9 @@ class Deparser {
|
|
|
7919
8120
|
if (node.grant_option && node.is_grant) {
|
|
7920
8121
|
output.push('WITH GRANT OPTION');
|
|
7921
8122
|
}
|
|
8123
|
+
if (node.grantor) {
|
|
8124
|
+
output.push('GRANTED BY', this.RoleSpec(node.grantor, context));
|
|
8125
|
+
}
|
|
7922
8126
|
// Only add behavior clauses for REVOKE statements, not for GRANT statements in ALTER DEFAULT PRIVILEGES
|
|
7923
8127
|
if (!node.is_grant) {
|
|
7924
8128
|
if (node.behavior === 'DROP_CASCADE') {
|
|
@@ -7932,57 +8136,34 @@ class Deparser {
|
|
|
7932
8136
|
}
|
|
7933
8137
|
GrantRoleStmt(node, context) {
|
|
7934
8138
|
const output = [];
|
|
7935
|
-
|
|
7936
|
-
|
|
7937
|
-
|
|
7938
|
-
|
|
7939
|
-
|
|
7940
|
-
|
|
7941
|
-
|
|
7942
|
-
|
|
7943
|
-
|
|
7944
|
-
|
|
7945
|
-
|
|
7946
|
-
|
|
7947
|
-
|
|
7948
|
-
|
|
7949
|
-
|
|
7950
|
-
|
|
7951
|
-
|
|
7952
|
-
|
|
7953
|
-
|
|
7954
|
-
if (adminOption.DefElem && adminOption.DefElem.arg) {
|
|
7955
|
-
adminValue = adminOption.DefElem.arg.Boolean?.boolval;
|
|
7956
|
-
}
|
|
7957
|
-
}
|
|
7958
|
-
if (setOption && setOption.DefElem) {
|
|
7959
|
-
hasSetOption = true;
|
|
7960
|
-
setValue = setOption.DefElem.arg?.Boolean?.boolval;
|
|
7961
|
-
}
|
|
7962
|
-
}
|
|
8139
|
+
const options = list_utils_1.ListUtils.unwrapList(node.opt)
|
|
8140
|
+
.map(opt => opt.DefElem)
|
|
8141
|
+
.filter((opt) => !!opt && !!opt.defname);
|
|
8142
|
+
const optionValue = (opt) => {
|
|
8143
|
+
if (!opt.arg)
|
|
8144
|
+
return true;
|
|
8145
|
+
const argType = this.getNodeType(opt.arg);
|
|
8146
|
+
const argData = this.getNodeData(opt.arg);
|
|
8147
|
+
if (argType === 'Boolean')
|
|
8148
|
+
return argData.boolval !== false;
|
|
8149
|
+
if (argType === 'String')
|
|
8150
|
+
return argData.sval !== 'false';
|
|
8151
|
+
return true;
|
|
8152
|
+
};
|
|
8153
|
+
const roles = list_utils_1.ListUtils.unwrapList(node.granted_roles)
|
|
8154
|
+
.map(role => role.AccessPriv?.priv_name
|
|
8155
|
+
? quotes_1.QuoteUtils.quoteIdentifier(role.AccessPriv.priv_name)
|
|
8156
|
+
: this.visit(role, context))
|
|
8157
|
+
.join(', ');
|
|
7963
8158
|
if (node.is_grant) {
|
|
7964
|
-
output.push('GRANT');
|
|
8159
|
+
output.push('GRANT', roles, 'TO');
|
|
7965
8160
|
}
|
|
7966
8161
|
else {
|
|
7967
8162
|
output.push('REVOKE');
|
|
7968
|
-
if (
|
|
7969
|
-
output.push(
|
|
7970
|
-
}
|
|
7971
|
-
else if (hasAdminOption) {
|
|
7972
|
-
output.push('ADMIN OPTION FOR');
|
|
8163
|
+
if (options.length > 0) {
|
|
8164
|
+
output.push(`${options[0].defname.toUpperCase()} OPTION FOR`);
|
|
7973
8165
|
}
|
|
7974
|
-
|
|
7975
|
-
if (node.granted_roles && node.granted_roles.length > 0) {
|
|
7976
|
-
const roles = list_utils_1.ListUtils.unwrapList(node.granted_roles)
|
|
7977
|
-
.map(role => this.visit(role, context))
|
|
7978
|
-
.join(', ');
|
|
7979
|
-
output.push(roles);
|
|
7980
|
-
}
|
|
7981
|
-
if (node.is_grant) {
|
|
7982
|
-
output.push('TO');
|
|
7983
|
-
}
|
|
7984
|
-
else {
|
|
7985
|
-
output.push('FROM');
|
|
8166
|
+
output.push(roles, 'FROM');
|
|
7986
8167
|
}
|
|
7987
8168
|
if (node.grantee_roles && node.grantee_roles.length > 0) {
|
|
7988
8169
|
const grantees = list_utils_1.ListUtils.unwrapList(node.grantee_roles)
|
|
@@ -7990,38 +8171,15 @@ class Deparser {
|
|
|
7990
8171
|
.join(', ');
|
|
7991
8172
|
output.push(grantees);
|
|
7992
8173
|
}
|
|
7993
|
-
if (node.is_grant) {
|
|
7994
|
-
const withOptions =
|
|
7995
|
-
|
|
7996
|
-
|
|
7997
|
-
|
|
7998
|
-
|
|
7999
|
-
|
|
8000
|
-
|
|
8001
|
-
|
|
8002
|
-
else {
|
|
8003
|
-
withOptions.push('ADMIN OPTION');
|
|
8004
|
-
}
|
|
8005
|
-
}
|
|
8006
|
-
if (hasInheritOption) {
|
|
8007
|
-
if (inheritValue === true) {
|
|
8008
|
-
withOptions.push('INHERIT OPTION');
|
|
8009
|
-
}
|
|
8010
|
-
else if (inheritValue === false) {
|
|
8011
|
-
withOptions.push('INHERIT FALSE');
|
|
8012
|
-
}
|
|
8013
|
-
}
|
|
8014
|
-
if (hasSetOption) {
|
|
8015
|
-
if (setValue === true) {
|
|
8016
|
-
withOptions.push('SET TRUE');
|
|
8017
|
-
}
|
|
8018
|
-
else if (setValue === false) {
|
|
8019
|
-
withOptions.push('SET FALSE');
|
|
8020
|
-
}
|
|
8021
|
-
}
|
|
8022
|
-
if (withOptions.length > 0) {
|
|
8023
|
-
output.push('WITH', withOptions.join(', '));
|
|
8024
|
-
}
|
|
8174
|
+
if (node.is_grant && options.length > 0) {
|
|
8175
|
+
const withOptions = options.map(opt => `${opt.defname.toUpperCase()} ${optionValue(opt) ? 'TRUE' : 'FALSE'}`);
|
|
8176
|
+
output.push('WITH', withOptions.join(', '));
|
|
8177
|
+
}
|
|
8178
|
+
if (node.grantor) {
|
|
8179
|
+
output.push('GRANTED BY', this.RoleSpec(node.grantor, context));
|
|
8180
|
+
}
|
|
8181
|
+
if (!node.is_grant && node.behavior === 'DROP_CASCADE') {
|
|
8182
|
+
output.push('CASCADE');
|
|
8025
8183
|
}
|
|
8026
8184
|
return output.join(' ');
|
|
8027
8185
|
}
|
|
@@ -8070,7 +8228,7 @@ class Deparser {
|
|
|
8070
8228
|
}
|
|
8071
8229
|
output.push('IS');
|
|
8072
8230
|
if (node.label) {
|
|
8073
|
-
output.push(
|
|
8231
|
+
output.push(quotes_1.QuoteUtils.escape(node.label));
|
|
8074
8232
|
}
|
|
8075
8233
|
else {
|
|
8076
8234
|
output.push('NULL');
|
|
@@ -8127,10 +8285,10 @@ class Deparser {
|
|
|
8127
8285
|
output.push(conversionName);
|
|
8128
8286
|
}
|
|
8129
8287
|
if (node.for_encoding_name) {
|
|
8130
|
-
output.push('FOR',
|
|
8288
|
+
output.push('FOR', quotes_1.QuoteUtils.escape(node.for_encoding_name));
|
|
8131
8289
|
}
|
|
8132
8290
|
if (node.to_encoding_name) {
|
|
8133
|
-
output.push('TO',
|
|
8291
|
+
output.push('TO', quotes_1.QuoteUtils.escape(node.to_encoding_name));
|
|
8134
8292
|
}
|
|
8135
8293
|
if (node.func_name && node.func_name.length > 0) {
|
|
8136
8294
|
output.push('FROM');
|
|
@@ -8293,6 +8451,9 @@ class Deparser {
|
|
|
8293
8451
|
.join(' ');
|
|
8294
8452
|
components.push(context.indent('REFERENCING ' + transitionClauses));
|
|
8295
8453
|
}
|
|
8454
|
+
if (node.constrrel) {
|
|
8455
|
+
components.push(context.indent('FROM ' + this.RangeVar(node.constrrel, context)));
|
|
8456
|
+
}
|
|
8296
8457
|
if (node.deferrable) {
|
|
8297
8458
|
components.push(context.indent('DEFERRABLE'));
|
|
8298
8459
|
}
|
|
@@ -8314,7 +8475,7 @@ class Deparser {
|
|
|
8314
8475
|
const funcName = list_utils_1.ListUtils.unwrapList(node.funcname)
|
|
8315
8476
|
.map(name => this.visit(name, context))
|
|
8316
8477
|
.join('.');
|
|
8317
|
-
executeStr += '
|
|
8478
|
+
executeStr += ' FUNCTION ' + funcName;
|
|
8318
8479
|
}
|
|
8319
8480
|
if (node.args && node.args.length > 0) {
|
|
8320
8481
|
const argContext = context.spawn('CreateTrigStmt', { isStringLiteral: true });
|
|
@@ -8572,15 +8733,14 @@ class Deparser {
|
|
|
8572
8733
|
.join(' ');
|
|
8573
8734
|
output.push(whenClauses);
|
|
8574
8735
|
}
|
|
8575
|
-
if (node.
|
|
8576
|
-
output.push(
|
|
8577
|
-
const returningList = list_utils_1.ListUtils.unwrapList(node.returningList)
|
|
8578
|
-
.map(target => this.visit(target, context))
|
|
8579
|
-
.join(', ');
|
|
8580
|
-
output.push(returningList);
|
|
8736
|
+
if (node.returningClause) {
|
|
8737
|
+
output.push(this.ReturningClause(node.returningClause, context));
|
|
8581
8738
|
}
|
|
8582
8739
|
return output.join(' ');
|
|
8583
8740
|
}
|
|
8741
|
+
MergeSupportFunc(node, context) {
|
|
8742
|
+
return 'merge_action()';
|
|
8743
|
+
}
|
|
8584
8744
|
MergeWhenClause(node, context) {
|
|
8585
8745
|
const output = ['WHEN'];
|
|
8586
8746
|
switch (node.matchKind) {
|
|
@@ -8602,10 +8762,9 @@ class Deparser {
|
|
|
8602
8762
|
switch (node.commandType) {
|
|
8603
8763
|
case 'CMD_UPDATE': {
|
|
8604
8764
|
output.push('UPDATE SET');
|
|
8605
|
-
|
|
8606
|
-
.
|
|
8607
|
-
|
|
8608
|
-
output.push(assignments);
|
|
8765
|
+
if (node.targetList && node.targetList.length > 0) {
|
|
8766
|
+
output.push(this.formatUpdateAssignments(node.targetList, context));
|
|
8767
|
+
}
|
|
8609
8768
|
break;
|
|
8610
8769
|
}
|
|
8611
8770
|
case 'CMD_INSERT': {
|
|
@@ -9010,6 +9169,13 @@ class Deparser {
|
|
|
9010
9169
|
output.push('USING');
|
|
9011
9170
|
output.push(node.into.accessMethod);
|
|
9012
9171
|
}
|
|
9172
|
+
if (node.into && node.into.options && node.into.options.length > 0) {
|
|
9173
|
+
output.push('WITH');
|
|
9174
|
+
const options = list_utils_1.ListUtils.unwrapList(node.into.options)
|
|
9175
|
+
.map(option => this.visit(option, context.spawn('CreateStmt')))
|
|
9176
|
+
.join(', ');
|
|
9177
|
+
output.push(`(${options})`);
|
|
9178
|
+
}
|
|
9013
9179
|
if (node.into && node.into.onCommit && node.into.onCommit !== 'ONCOMMIT_NOOP') {
|
|
9014
9180
|
output.push('ON COMMIT');
|
|
9015
9181
|
switch (node.into.onCommit) {
|
|
@@ -9024,17 +9190,13 @@ class Deparser {
|
|
|
9024
9190
|
break;
|
|
9025
9191
|
}
|
|
9026
9192
|
}
|
|
9193
|
+
if (node.into && node.into.tableSpaceName) {
|
|
9194
|
+
output.push('TABLESPACE', quotes_1.QuoteUtils.quoteIdentifier(node.into.tableSpaceName));
|
|
9195
|
+
}
|
|
9027
9196
|
output.push('AS');
|
|
9028
9197
|
if (node.query) {
|
|
9029
9198
|
output.push(this.visit(node.query, context));
|
|
9030
9199
|
}
|
|
9031
|
-
if (node.into && node.into.options && node.into.options.length > 0) {
|
|
9032
|
-
output.push('WITH');
|
|
9033
|
-
const options = list_utils_1.ListUtils.unwrapList(node.into.options)
|
|
9034
|
-
.map(option => this.visit(option, context))
|
|
9035
|
-
.join(', ');
|
|
9036
|
-
output.push(`(${options})`);
|
|
9037
|
-
}
|
|
9038
9200
|
if (node.into && node.into.skipData) {
|
|
9039
9201
|
output.push('WITH NO DATA');
|
|
9040
9202
|
}
|
|
@@ -9111,6 +9273,9 @@ class Deparser {
|
|
|
9111
9273
|
if (listItems.length === 1 && listItems[0].String) {
|
|
9112
9274
|
return `${preservedDefName} = ${listItems[0].String.sval}`;
|
|
9113
9275
|
}
|
|
9276
|
+
if (listItems.length > 1 && listItems.every(item => item.String)) {
|
|
9277
|
+
return `${preservedDefName} = OPERATOR(${this.qualifiedOperatorName(listItems)})`;
|
|
9278
|
+
}
|
|
9114
9279
|
}
|
|
9115
9280
|
// For commutator/negator, we already handled them above
|
|
9116
9281
|
if ((defName.toLowerCase() === 'commutator' || defName.toLowerCase() === 'negator')) {
|
|
@@ -9264,7 +9429,7 @@ class Deparser {
|
|
|
9264
9429
|
const preservedDefName = quotedDefName !== defName ? quotedDefName : defName;
|
|
9265
9430
|
// Handle String arguments with single quotes for string literals
|
|
9266
9431
|
if (defValue.String) {
|
|
9267
|
-
return `${preservedDefName} =
|
|
9432
|
+
return `${preservedDefName} = ${quotes_1.QuoteUtils.escape(defValue.String.sval)}`;
|
|
9268
9433
|
}
|
|
9269
9434
|
return `${preservedDefName} = ${this.visit(defValue, context)}`;
|
|
9270
9435
|
}
|
|
@@ -9387,7 +9552,7 @@ class Deparser {
|
|
|
9387
9552
|
// For CREATE COLLATION, ensure String nodes are quoted as string literals
|
|
9388
9553
|
let valueStr;
|
|
9389
9554
|
if (defValue.String) {
|
|
9390
|
-
valueStr =
|
|
9555
|
+
valueStr = quotes_1.QuoteUtils.escape(defValue.String.sval);
|
|
9391
9556
|
}
|
|
9392
9557
|
else {
|
|
9393
9558
|
valueStr = this.visit(defValue, context);
|
|
@@ -9507,7 +9672,7 @@ class Deparser {
|
|
|
9507
9672
|
}
|
|
9508
9673
|
if (node.whereClause) {
|
|
9509
9674
|
output.push('WHERE');
|
|
9510
|
-
output.push(this.visit(node.whereClause, context));
|
|
9675
|
+
output.push(`(${this.visit(node.whereClause, context)})`);
|
|
9511
9676
|
}
|
|
9512
9677
|
return output.join(' ');
|
|
9513
9678
|
}
|
|
@@ -9654,6 +9819,23 @@ class Deparser {
|
|
|
9654
9819
|
}
|
|
9655
9820
|
return output.join(' ');
|
|
9656
9821
|
}
|
|
9822
|
+
quoteDefElemArg(arg, argValue) {
|
|
9823
|
+
if (arg && this.getNodeType(arg) === 'String') {
|
|
9824
|
+
return quotes_1.QuoteUtils.escape(this.getNodeData(arg).sval || '');
|
|
9825
|
+
}
|
|
9826
|
+
return typeof argValue === 'string' && !argValue.startsWith("'")
|
|
9827
|
+
? quotes_1.QuoteUtils.escape(argValue)
|
|
9828
|
+
: argValue;
|
|
9829
|
+
}
|
|
9830
|
+
formatOptionValue(arg, argValue) {
|
|
9831
|
+
if (arg && this.getNodeType(arg) === 'String') {
|
|
9832
|
+
const sval = this.getNodeData(arg).sval || '';
|
|
9833
|
+
return /^[a-z_][a-z0-9_]*$/.test(sval) && (0, quotes_1.keywordKindOf)(sval) === 'NO_KEYWORD'
|
|
9834
|
+
? sval
|
|
9835
|
+
: quotes_1.QuoteUtils.escape(sval);
|
|
9836
|
+
}
|
|
9837
|
+
return argValue;
|
|
9838
|
+
}
|
|
9657
9839
|
Var(node, context) {
|
|
9658
9840
|
if (node.varno && node.varattno) {
|
|
9659
9841
|
return `$${node.varno}.${node.varattno}`;
|
|
@@ -9693,7 +9875,7 @@ class Deparser {
|
|
|
9693
9875
|
}
|
|
9694
9876
|
if (node.rowexpr) {
|
|
9695
9877
|
output.push(',');
|
|
9696
|
-
output.push(
|
|
9878
|
+
output.push(this.visit(node.rowexpr, context));
|
|
9697
9879
|
}
|
|
9698
9880
|
if (node.colexprs && node.colexprs.length > 0) {
|
|
9699
9881
|
output.push('COLUMNS');
|
|
@@ -9710,25 +9892,40 @@ class Deparser {
|
|
|
9710
9892
|
if (node.lateral) {
|
|
9711
9893
|
output.push('LATERAL');
|
|
9712
9894
|
}
|
|
9713
|
-
|
|
9714
|
-
|
|
9895
|
+
const args = [];
|
|
9896
|
+
if (node.namespaces && node.namespaces.length > 0) {
|
|
9897
|
+
const namespaces = list_utils_1.ListUtils.unwrapList(node.namespaces).map(ns => {
|
|
9898
|
+
const target = this.getNodeData(ns);
|
|
9899
|
+
const uri = this.visit(target.val, context);
|
|
9900
|
+
return target.name ? `${uri} AS ${quotes_1.QuoteUtils.quoteIdentifier(target.name)}` : `DEFAULT ${uri}`;
|
|
9901
|
+
});
|
|
9902
|
+
args.push(`XMLNAMESPACES(${namespaces.join(', ')}),`);
|
|
9715
9903
|
}
|
|
9716
9904
|
if (node.rowexpr) {
|
|
9717
|
-
|
|
9718
|
-
|
|
9905
|
+
args.push(this.formatXmlTableExpr(node.rowexpr, context));
|
|
9906
|
+
}
|
|
9907
|
+
if (node.docexpr) {
|
|
9908
|
+
args.push('PASSING');
|
|
9909
|
+
args.push(this.formatXmlTableExpr(node.docexpr, context));
|
|
9719
9910
|
}
|
|
9720
9911
|
if (node.columns && node.columns.length > 0) {
|
|
9721
|
-
|
|
9722
|
-
|
|
9912
|
+
args.push('COLUMNS');
|
|
9913
|
+
args.push(list_utils_1.ListUtils.unwrapList(node.columns)
|
|
9723
9914
|
.map(col => this.visit(col, context))
|
|
9724
|
-
.join(', ');
|
|
9725
|
-
output.push(`(${columns})`);
|
|
9915
|
+
.join(', '));
|
|
9726
9916
|
}
|
|
9917
|
+
output.push(`XMLTABLE(${args.join(' ')})`);
|
|
9727
9918
|
if (node.alias) {
|
|
9728
9919
|
output.push(this.Alias(node.alias, context));
|
|
9729
9920
|
}
|
|
9730
9921
|
return output.join(' ');
|
|
9731
9922
|
}
|
|
9923
|
+
formatXmlTableExpr(expr, context) {
|
|
9924
|
+
const value = this.visit(expr, context);
|
|
9925
|
+
return ['A_Const', 'ColumnRef', 'ParamRef', 'FuncCall'].includes(this.getNodeType(expr))
|
|
9926
|
+
? value
|
|
9927
|
+
: `(${value})`;
|
|
9928
|
+
}
|
|
9732
9929
|
RangeTableFuncCol(node, context) {
|
|
9733
9930
|
const output = [];
|
|
9734
9931
|
if (node.colname) {
|
|
@@ -9742,32 +9939,193 @@ class Deparser {
|
|
|
9742
9939
|
}
|
|
9743
9940
|
if (node.colexpr) {
|
|
9744
9941
|
output.push('PATH');
|
|
9745
|
-
output.push(
|
|
9942
|
+
output.push(this.visit(node.colexpr, context));
|
|
9746
9943
|
}
|
|
9747
9944
|
if (node.coldefexpr) {
|
|
9748
9945
|
output.push('DEFAULT');
|
|
9749
9946
|
output.push(this.visit(node.coldefexpr, context));
|
|
9750
9947
|
}
|
|
9948
|
+
if (node.is_not_null) {
|
|
9949
|
+
output.push('NOT NULL');
|
|
9950
|
+
}
|
|
9751
9951
|
return output.join(' ');
|
|
9752
9952
|
}
|
|
9953
|
+
formatJsonFormat(format) {
|
|
9954
|
+
if (!format || !format.format_type || format.format_type === 'JS_FORMAT_DEFAULT') {
|
|
9955
|
+
return null;
|
|
9956
|
+
}
|
|
9957
|
+
const parts = ['FORMAT JSON'];
|
|
9958
|
+
switch (format.encoding) {
|
|
9959
|
+
case 'JS_ENC_UTF8':
|
|
9960
|
+
parts.push('ENCODING UTF8');
|
|
9961
|
+
break;
|
|
9962
|
+
case 'JS_ENC_UTF16':
|
|
9963
|
+
parts.push('ENCODING UTF16');
|
|
9964
|
+
break;
|
|
9965
|
+
case 'JS_ENC_UTF32':
|
|
9966
|
+
parts.push('ENCODING UTF32');
|
|
9967
|
+
break;
|
|
9968
|
+
}
|
|
9969
|
+
return parts.join(' ');
|
|
9970
|
+
}
|
|
9971
|
+
formatJsonOutput(output, context) {
|
|
9972
|
+
if (!output || !output.typeName)
|
|
9973
|
+
return null;
|
|
9974
|
+
const parts = ['RETURNING', this.TypeName(output.typeName, context)];
|
|
9975
|
+
const format = this.formatJsonFormat(output.returning?.format);
|
|
9976
|
+
if (format)
|
|
9977
|
+
parts.push(format);
|
|
9978
|
+
return parts.join(' ');
|
|
9979
|
+
}
|
|
9980
|
+
formatJsonNullClause(absentOnNull) {
|
|
9981
|
+
return absentOnNull ? 'ABSENT ON NULL' : 'NULL ON NULL';
|
|
9982
|
+
}
|
|
9983
|
+
formatJsonUniqueClause(unique) {
|
|
9984
|
+
return unique ? 'WITH UNIQUE KEYS' : null;
|
|
9985
|
+
}
|
|
9986
|
+
JsonValueExpr(node, context) {
|
|
9987
|
+
const parts = [];
|
|
9988
|
+
if (node.raw_expr) {
|
|
9989
|
+
parts.push(this.visit(node.raw_expr, context));
|
|
9990
|
+
}
|
|
9991
|
+
const format = this.formatJsonFormat(node.format);
|
|
9992
|
+
if (format)
|
|
9993
|
+
parts.push(format);
|
|
9994
|
+
return parts.join(' ');
|
|
9995
|
+
}
|
|
9996
|
+
JsonKeyValue(node, context) {
|
|
9997
|
+
const key = node.key ? this.visit(node.key, context) : '';
|
|
9998
|
+
const value = node.value ? this.JsonValueExpr(node.value, context) : '';
|
|
9999
|
+
return `${key} : ${value}`;
|
|
10000
|
+
}
|
|
10001
|
+
JsonObjectConstructor(node, context) {
|
|
10002
|
+
const args = [];
|
|
10003
|
+
if (node.exprs && node.exprs.length > 0) {
|
|
10004
|
+
args.push(list_utils_1.ListUtils.unwrapList(node.exprs).map(e => this.visit(e, context)).join(', '));
|
|
10005
|
+
args.push(this.formatJsonNullClause(node.absent_on_null));
|
|
10006
|
+
const unique = this.formatJsonUniqueClause(node.unique);
|
|
10007
|
+
if (unique)
|
|
10008
|
+
args.push(unique);
|
|
10009
|
+
}
|
|
10010
|
+
const output = this.formatJsonOutput(node.output, context);
|
|
10011
|
+
if (output)
|
|
10012
|
+
args.push(output);
|
|
10013
|
+
return `JSON_OBJECT(${args.join(' ')})`;
|
|
10014
|
+
}
|
|
10015
|
+
JsonArrayConstructor(node, context) {
|
|
10016
|
+
const args = [];
|
|
10017
|
+
if (node.exprs && node.exprs.length > 0) {
|
|
10018
|
+
args.push(list_utils_1.ListUtils.unwrapList(node.exprs).map(e => this.visit(e, context)).join(', '));
|
|
10019
|
+
args.push(this.formatJsonNullClause(node.absent_on_null));
|
|
10020
|
+
}
|
|
10021
|
+
const output = this.formatJsonOutput(node.output, context);
|
|
10022
|
+
if (output)
|
|
10023
|
+
args.push(output);
|
|
10024
|
+
return `JSON_ARRAY(${args.join(' ')})`;
|
|
10025
|
+
}
|
|
9753
10026
|
JsonArrayQueryConstructor(node, context) {
|
|
9754
|
-
const
|
|
10027
|
+
const args = [];
|
|
9755
10028
|
if (node.query) {
|
|
9756
|
-
|
|
10029
|
+
args.push(this.visit(node.query, context));
|
|
10030
|
+
}
|
|
10031
|
+
const format = this.formatJsonFormat(node.format);
|
|
10032
|
+
if (format)
|
|
10033
|
+
args.push(format);
|
|
10034
|
+
const output = this.formatJsonOutput(node.output, context);
|
|
10035
|
+
if (output)
|
|
10036
|
+
args.push(output);
|
|
10037
|
+
return `JSON_ARRAY(${args.join(' ')})`;
|
|
10038
|
+
}
|
|
10039
|
+
formatJsonAggSuffix(ctor, context) {
|
|
10040
|
+
if (!ctor)
|
|
10041
|
+
return '';
|
|
10042
|
+
let result = '';
|
|
10043
|
+
if (ctor.agg_filter) {
|
|
10044
|
+
result += ` FILTER (WHERE ${this.visit(ctor.agg_filter, context)})`;
|
|
9757
10045
|
}
|
|
9758
|
-
if (
|
|
9759
|
-
|
|
10046
|
+
if (ctor.over) {
|
|
10047
|
+
result += this.formatOverClause(ctor.over, context);
|
|
9760
10048
|
}
|
|
9761
|
-
|
|
9762
|
-
|
|
10049
|
+
return result;
|
|
10050
|
+
}
|
|
10051
|
+
JsonObjectAgg(node, context) {
|
|
10052
|
+
const args = [];
|
|
10053
|
+
if (node.arg) {
|
|
10054
|
+
args.push(this.JsonKeyValue(node.arg, context));
|
|
10055
|
+
}
|
|
10056
|
+
args.push(this.formatJsonNullClause(node.absent_on_null));
|
|
10057
|
+
const unique = this.formatJsonUniqueClause(node.unique);
|
|
10058
|
+
if (unique)
|
|
10059
|
+
args.push(unique);
|
|
10060
|
+
const output = this.formatJsonOutput(node.constructor?.output, context);
|
|
10061
|
+
if (output)
|
|
10062
|
+
args.push(output);
|
|
10063
|
+
return `JSON_OBJECTAGG(${args.join(' ')})${this.formatJsonAggSuffix(node.constructor, context)}`;
|
|
10064
|
+
}
|
|
10065
|
+
JsonArrayAgg(node, context) {
|
|
10066
|
+
const args = [];
|
|
10067
|
+
if (node.arg) {
|
|
10068
|
+
args.push(this.JsonValueExpr(node.arg, context));
|
|
9763
10069
|
}
|
|
9764
|
-
|
|
9765
|
-
|
|
10070
|
+
const aggOrder = node.constructor?.agg_order;
|
|
10071
|
+
if (aggOrder && aggOrder.length > 0) {
|
|
10072
|
+
const orderItems = list_utils_1.ListUtils.unwrapList(aggOrder).map(item => this.visit(item, context));
|
|
10073
|
+
args.push(`ORDER BY ${orderItems.join(', ')}`);
|
|
9766
10074
|
}
|
|
9767
|
-
|
|
9768
|
-
|
|
10075
|
+
args.push(this.formatJsonNullClause(node.absent_on_null));
|
|
10076
|
+
const output = this.formatJsonOutput(node.constructor?.output, context);
|
|
10077
|
+
if (output)
|
|
10078
|
+
args.push(output);
|
|
10079
|
+
return `JSON_ARRAYAGG(${args.join(' ')})${this.formatJsonAggSuffix(node.constructor, context)}`;
|
|
10080
|
+
}
|
|
10081
|
+
JsonParseExpr(node, context) {
|
|
10082
|
+
const args = [];
|
|
10083
|
+
if (node.expr) {
|
|
10084
|
+
args.push(this.JsonValueExpr(node.expr, context));
|
|
9769
10085
|
}
|
|
9770
|
-
|
|
10086
|
+
const unique = this.formatJsonUniqueClause(node.unique_keys);
|
|
10087
|
+
if (unique)
|
|
10088
|
+
args.push(unique);
|
|
10089
|
+
return `JSON(${args.join(' ')})`;
|
|
10090
|
+
}
|
|
10091
|
+
JsonScalarExpr(node, context) {
|
|
10092
|
+
const expr = node.expr ? this.visit(node.expr, context) : '';
|
|
10093
|
+
return `JSON_SCALAR(${expr})`;
|
|
10094
|
+
}
|
|
10095
|
+
JsonSerializeExpr(node, context) {
|
|
10096
|
+
const args = [];
|
|
10097
|
+
if (node.expr) {
|
|
10098
|
+
args.push(this.JsonValueExpr(node.expr, context));
|
|
10099
|
+
}
|
|
10100
|
+
const output = this.formatJsonOutput(node.output, context);
|
|
10101
|
+
if (output)
|
|
10102
|
+
args.push(output);
|
|
10103
|
+
return `JSON_SERIALIZE(${args.join(' ')})`;
|
|
10104
|
+
}
|
|
10105
|
+
JsonIsPredicate(node, context) {
|
|
10106
|
+
const parts = [];
|
|
10107
|
+
if (node.expr) {
|
|
10108
|
+
parts.push(this.visit(node.expr, context));
|
|
10109
|
+
}
|
|
10110
|
+
const format = this.formatJsonFormat(node.format);
|
|
10111
|
+
if (format)
|
|
10112
|
+
parts.push(format);
|
|
10113
|
+
parts.push('IS JSON');
|
|
10114
|
+
switch (node.item_type) {
|
|
10115
|
+
case 'JS_TYPE_OBJECT':
|
|
10116
|
+
parts.push('OBJECT');
|
|
10117
|
+
break;
|
|
10118
|
+
case 'JS_TYPE_ARRAY':
|
|
10119
|
+
parts.push('ARRAY');
|
|
10120
|
+
break;
|
|
10121
|
+
case 'JS_TYPE_SCALAR':
|
|
10122
|
+
parts.push('SCALAR');
|
|
10123
|
+
break;
|
|
10124
|
+
}
|
|
10125
|
+
if (node.unique_keys) {
|
|
10126
|
+
parts.push('WITH UNIQUE KEYS');
|
|
10127
|
+
}
|
|
10128
|
+
return parts.join(' ');
|
|
9771
10129
|
}
|
|
9772
10130
|
RangeFunction(node, context) {
|
|
9773
10131
|
const output = [];
|
|
@@ -9961,6 +10319,7 @@ class Deparser {
|
|
|
9961
10319
|
rootParts.push('STANDALONE NO VALUE');
|
|
9962
10320
|
}
|
|
9963
10321
|
else if (standaloneArg.A_Const.ival.ival === 3) {
|
|
10322
|
+
// STANDALONE omitted
|
|
9964
10323
|
}
|
|
9965
10324
|
else if (Object.keys(standaloneArg.A_Const.ival).length === 0) {
|
|
9966
10325
|
rootParts.push('STANDALONE YES');
|
|
@@ -10553,9 +10912,5 @@ class Deparser {
|
|
|
10553
10912
|
}
|
|
10554
10913
|
return output.join(' ');
|
|
10555
10914
|
}
|
|
10556
|
-
containsMultilineStringLiteral(content) {
|
|
10557
|
-
const stringLiteralRegex = /'[^']*\n[^']*'/g;
|
|
10558
|
-
return stringLiteralRegex.test(content);
|
|
10559
|
-
}
|
|
10560
10915
|
}
|
|
10561
10916
|
exports.Deparser = Deparser;
|