pgsql-deparser 13.19.1 → 13.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -7
- package/deparser/deparser.d.ts +31 -28
- package/deparser/deparser.js +1253 -814
- package/deparser/index.d.ts +3 -1
- package/deparser/index.js +5 -1
- package/deparser/utils/sql-formatter.d.ts +8 -0
- package/deparser/utils/sql-formatter.js +104 -1
- package/esm/deparser/deparser.js +1236 -797
- package/esm/deparser/index.js +3 -1
- package/esm/deparser/utils/sql-formatter.js +103 -1
- package/esm/index.js +101 -7
- package/esm/v13-to-v14.js +76 -29
- package/esm/v13-to-v18-direct.js +88 -0
- package/esm/v14-to-v15.js +34 -0
- package/esm/v15-to-v16.js +16 -5
- package/esm/v16-to-v17.js +50 -1
- package/esm/v17-to-v18.js +209 -0
- package/index.d.ts +18 -4
- package/index.js +104 -6
- package/package.json +3 -2
- package/v13-to-v14.d.ts +6 -0
- package/v13-to-v14.js +76 -29
- package/v13-to-v18-direct.d.ts +25 -0
- package/v13-to-v18-direct.js +92 -0
- package/v14-to-v15.d.ts +1 -0
- package/v14-to-v15.js +34 -0
- package/v15-to-v16.js +16 -5
- package/v16-to-v17.d.ts +3 -0
- package/v16-to-v17.js +50 -1
- package/v17-to-v18.d.ts +55 -0
- package/v17-to-v18.js +213 -0
package/esm/deparser/deparser.js
CHANGED
|
@@ -2,10 +2,29 @@
|
|
|
2
2
|
* Auto-generated file with types stripped for better tree-shaking
|
|
3
3
|
* DO NOT EDIT - Generated by strip-deparser-types.ts
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
6
|
-
import { SqlFormatter } from './utils/sql-formatter';
|
|
7
|
-
import { QuoteUtils } from './utils/quote-utils';
|
|
5
|
+
import { keywordKindOf, QuoteUtils } from '@pgsql/quotes';
|
|
8
6
|
import { ListUtils } from './utils/list-utils';
|
|
7
|
+
import { SqlFormatter } from './utils/sql-formatter';
|
|
8
|
+
import { DeparserContext } from './visitors/base';
|
|
9
|
+
// WindowDef.frameOptions bit flags (src/include/nodes/parsenodes.h)
|
|
10
|
+
const FRAMEOPTION_NONDEFAULT = 0x00001;
|
|
11
|
+
const FRAMEOPTION_RANGE = 0x00002;
|
|
12
|
+
const FRAMEOPTION_ROWS = 0x00004;
|
|
13
|
+
const FRAMEOPTION_GROUPS = 0x00008;
|
|
14
|
+
const FRAMEOPTION_BETWEEN = 0x00010;
|
|
15
|
+
const FRAMEOPTION_START_UNBOUNDED_PRECEDING = 0x00020;
|
|
16
|
+
const FRAMEOPTION_END_UNBOUNDED_PRECEDING = 0x00040;
|
|
17
|
+
const FRAMEOPTION_START_UNBOUNDED_FOLLOWING = 0x00080;
|
|
18
|
+
const FRAMEOPTION_END_UNBOUNDED_FOLLOWING = 0x00100;
|
|
19
|
+
const FRAMEOPTION_START_CURRENT_ROW = 0x00200;
|
|
20
|
+
const FRAMEOPTION_END_CURRENT_ROW = 0x00400;
|
|
21
|
+
const FRAMEOPTION_START_OFFSET_PRECEDING = 0x00800;
|
|
22
|
+
const FRAMEOPTION_END_OFFSET_PRECEDING = 0x01000;
|
|
23
|
+
const FRAMEOPTION_START_OFFSET_FOLLOWING = 0x02000;
|
|
24
|
+
const FRAMEOPTION_END_OFFSET_FOLLOWING = 0x04000;
|
|
25
|
+
const FRAMEOPTION_EXCLUDE_CURRENT_ROW = 0x08000;
|
|
26
|
+
const FRAMEOPTION_EXCLUDE_GROUP = 0x10000;
|
|
27
|
+
const FRAMEOPTION_EXCLUDE_TIES = 0x20000;
|
|
9
28
|
/**
|
|
10
29
|
* List of real PostgreSQL built-in types as they appear in pg_catalog.pg_type.typname.
|
|
11
30
|
* These are stored in lowercase in PostgreSQL system catalogs.
|
|
@@ -104,6 +123,36 @@ function isWrappedParseResult(obj) {
|
|
|
104
123
|
* The deparser automatically detects bare ParseResult objects for backward
|
|
105
124
|
* compatibility and wraps them internally for consistent processing.
|
|
106
125
|
*/
|
|
126
|
+
function formatBitString(bsval) {
|
|
127
|
+
const quote = (value) => value.replace(/'/g, "''");
|
|
128
|
+
if (/^x[0-9A-Fa-f]*$/.test(bsval)) {
|
|
129
|
+
return `x'${bsval.substring(1)}'`;
|
|
130
|
+
}
|
|
131
|
+
if (bsval.startsWith('b')) {
|
|
132
|
+
return `b'${quote(bsval.substring(1))}'`;
|
|
133
|
+
}
|
|
134
|
+
return `b'${quote(bsval)}'`;
|
|
135
|
+
}
|
|
136
|
+
// A dollar-quoted body ends at the first occurrence of its tag, including one
|
|
137
|
+
// formed by the body's trailing characters plus the closing tag (`...$` + `$$`).
|
|
138
|
+
function dollarTagConflicts(body, tag) {
|
|
139
|
+
return (body + tag).indexOf(tag) < body.length;
|
|
140
|
+
}
|
|
141
|
+
const NUMERIC_LITERAL = /^[+-]?(?:0[xX](?:_?[0-9A-Fa-f])+|0[oO](?:_?[0-7])+|0[bB](?:_?[01])+|(?:\d(?:_?\d)*(?:\.(?:\d(?:_?\d)*)?)?|\.\d(?:_?\d)*)(?:[eE][+-]?\d(?:_?\d)*)?)$/;
|
|
142
|
+
function formatInteger(ival) {
|
|
143
|
+
const value = String(ival);
|
|
144
|
+
if (!/^[+-]?\d+$/.test(value)) {
|
|
145
|
+
throw new Error(`Invalid integer literal: ${value}`);
|
|
146
|
+
}
|
|
147
|
+
return value;
|
|
148
|
+
}
|
|
149
|
+
function formatNumeric(fval) {
|
|
150
|
+
const value = String(fval);
|
|
151
|
+
if (!NUMERIC_LITERAL.test(value)) {
|
|
152
|
+
throw new Error(`Invalid numeric literal: ${value}`);
|
|
153
|
+
}
|
|
154
|
+
return value;
|
|
155
|
+
}
|
|
107
156
|
export class Deparser {
|
|
108
157
|
tree;
|
|
109
158
|
options;
|
|
@@ -163,10 +212,19 @@ export class Deparser {
|
|
|
163
212
|
*/
|
|
164
213
|
getFunctionDelimiter(body) {
|
|
165
214
|
const delimiter = this.options.functionDelimiter || '$$';
|
|
166
|
-
if (body
|
|
167
|
-
return
|
|
215
|
+
if (!dollarTagConflicts(body, delimiter)) {
|
|
216
|
+
return delimiter;
|
|
168
217
|
}
|
|
169
|
-
|
|
218
|
+
const fallback = this.options.functionDelimiterFallback || '$EOFCODE$';
|
|
219
|
+
if (!dollarTagConflicts(body, fallback)) {
|
|
220
|
+
return fallback;
|
|
221
|
+
}
|
|
222
|
+
const base = fallback.slice(0, -1);
|
|
223
|
+
let counter = 1;
|
|
224
|
+
while (dollarTagConflicts(body, `${base}${counter}$`)) {
|
|
225
|
+
counter++;
|
|
226
|
+
}
|
|
227
|
+
return `${base}${counter}$`;
|
|
170
228
|
}
|
|
171
229
|
/**
|
|
172
230
|
* Maps ObjectType enum values to their corresponding SQL keywords
|
|
@@ -443,12 +501,7 @@ export class Deparser {
|
|
|
443
501
|
// Check if single target is complex - if so, use multiline format
|
|
444
502
|
if (this.isComplexSelectTarget(targetNode)) {
|
|
445
503
|
output.push('SELECT' + distinctPart);
|
|
446
|
-
|
|
447
|
-
output.push(target);
|
|
448
|
-
}
|
|
449
|
-
else {
|
|
450
|
-
output.push(context.indent(target));
|
|
451
|
-
}
|
|
504
|
+
output.push(context.indent(target));
|
|
452
505
|
}
|
|
453
506
|
else {
|
|
454
507
|
output.push('SELECT' + distinctPart + ' ' + target);
|
|
@@ -458,9 +511,6 @@ export class Deparser {
|
|
|
458
511
|
const targetStrings = targetList
|
|
459
512
|
.map(e => {
|
|
460
513
|
const targetStr = this.visit(e, context.spawn('SelectStmt', { select: true }));
|
|
461
|
-
if (this.containsMultilineStringLiteral(targetStr)) {
|
|
462
|
-
return targetStr;
|
|
463
|
-
}
|
|
464
514
|
return context.indent(targetStr);
|
|
465
515
|
});
|
|
466
516
|
const formattedTargets = targetStrings.join(',' + context.newline());
|
|
@@ -512,9 +562,6 @@ export class Deparser {
|
|
|
512
562
|
return context.parens(values.join(', '));
|
|
513
563
|
});
|
|
514
564
|
const indentedTuples = lists.map(tuple => {
|
|
515
|
-
if (this.containsMultilineStringLiteral(tuple)) {
|
|
516
|
-
return tuple;
|
|
517
|
-
}
|
|
518
565
|
return context.indent(tuple);
|
|
519
566
|
});
|
|
520
567
|
output.push(indentedTuples.join(',\n'));
|
|
@@ -534,9 +581,6 @@ export class Deparser {
|
|
|
534
581
|
const groupItems = groupList
|
|
535
582
|
.map(e => {
|
|
536
583
|
const groupStr = this.visit(e, context.spawn('SelectStmt', { group: true, indentLevel: context.indentLevel + 1 }));
|
|
537
|
-
if (this.containsMultilineStringLiteral(groupStr)) {
|
|
538
|
-
return groupStr;
|
|
539
|
-
}
|
|
540
584
|
return context.indent(groupStr);
|
|
541
585
|
})
|
|
542
586
|
.join(',' + context.newline());
|
|
@@ -555,12 +599,7 @@ export class Deparser {
|
|
|
555
599
|
if (context.isPretty()) {
|
|
556
600
|
output.push('HAVING');
|
|
557
601
|
const havingStr = this.visit(node.havingClause, context);
|
|
558
|
-
|
|
559
|
-
output.push(havingStr);
|
|
560
|
-
}
|
|
561
|
-
else {
|
|
562
|
-
output.push(context.indent(havingStr));
|
|
563
|
-
}
|
|
602
|
+
output.push(context.indent(havingStr));
|
|
564
603
|
}
|
|
565
604
|
else {
|
|
566
605
|
output.push('HAVING');
|
|
@@ -581,9 +620,6 @@ export class Deparser {
|
|
|
581
620
|
const sortItems = sortList
|
|
582
621
|
.map(e => {
|
|
583
622
|
const sortStr = this.visit(e, context.spawn('SelectStmt', { sort: true, indentLevel: context.indentLevel + 1 }));
|
|
584
|
-
if (this.containsMultilineStringLiteral(sortStr)) {
|
|
585
|
-
return sortStr;
|
|
586
|
-
}
|
|
587
623
|
return context.indent(sortStr);
|
|
588
624
|
})
|
|
589
625
|
.join(',' + context.newline());
|
|
@@ -659,10 +695,15 @@ export class Deparser {
|
|
|
659
695
|
return context.format([leftExpr, operator, rightExpr]);
|
|
660
696
|
}
|
|
661
697
|
else if (rexpr) {
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
698
|
+
// Unary operator (e.g., unary minus: - expr)
|
|
699
|
+
const operator = this.deparseOperatorName(name, context);
|
|
700
|
+
let rightExpr = this.visit(rexpr, context);
|
|
701
|
+
// Wrap in parentheses if rexpr is a binary A_Expr to preserve semantics
|
|
702
|
+
// e.g., -(a - b) must stay -(a - b), not become -a - b
|
|
703
|
+
if (rexpr && 'A_Expr' in rexpr && rexpr.A_Expr?.kind === 'AEXPR_OP' && rexpr.A_Expr?.lexpr) {
|
|
704
|
+
rightExpr = context.parens(rightExpr);
|
|
705
|
+
}
|
|
706
|
+
return context.format([operator, rightExpr]);
|
|
666
707
|
}
|
|
667
708
|
break;
|
|
668
709
|
case 'AEXPR_OP_ANY':
|
|
@@ -842,15 +883,15 @@ export class Deparser {
|
|
|
842
883
|
getOperatorPrecedence(operator) {
|
|
843
884
|
const precedence = {
|
|
844
885
|
'||': 1, // string concatenation
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
886
|
+
OR: 2, // logical OR
|
|
887
|
+
AND: 3, // logical AND
|
|
888
|
+
NOT: 4, // logical NOT
|
|
889
|
+
IS: 5, // IS NULL, IS NOT NULL, etc.
|
|
890
|
+
IN: 5, // IN, NOT IN
|
|
891
|
+
BETWEEN: 5, // BETWEEN, NOT BETWEEN
|
|
892
|
+
LIKE: 5, // LIKE, ILIKE, SIMILAR TO
|
|
893
|
+
ILIKE: 5,
|
|
894
|
+
SIMILAR: 5,
|
|
854
895
|
'<': 6, // comparison operators
|
|
855
896
|
'<=': 6,
|
|
856
897
|
'>': 6,
|
|
@@ -980,6 +1021,12 @@ export class Deparser {
|
|
|
980
1021
|
output.push(context.parens(columnNames.join(', ')));
|
|
981
1022
|
}
|
|
982
1023
|
}
|
|
1024
|
+
if (node.override === 'OVERRIDING_USER_VALUE') {
|
|
1025
|
+
output.push('OVERRIDING USER VALUE');
|
|
1026
|
+
}
|
|
1027
|
+
else if (node.override === 'OVERRIDING_SYSTEM_VALUE') {
|
|
1028
|
+
output.push('OVERRIDING SYSTEM VALUE');
|
|
1029
|
+
}
|
|
983
1030
|
if (node.selectStmt) {
|
|
984
1031
|
output.push(this.visit(node.selectStmt, context));
|
|
985
1032
|
}
|
|
@@ -1022,7 +1069,14 @@ export class Deparser {
|
|
|
1022
1069
|
else {
|
|
1023
1070
|
const updateContext = context.spawn('UpdateStmt', { update: true });
|
|
1024
1071
|
const targets = targetList.map(target => this.visit(target, updateContext));
|
|
1025
|
-
|
|
1072
|
+
if (context.isPretty()) {
|
|
1073
|
+
// Put each assignment on its own line for pretty printing
|
|
1074
|
+
const indentedTargets = targets.map(target => context.indent(target));
|
|
1075
|
+
output[output.length - 1] += '\n' + indentedTargets.join(',\n');
|
|
1076
|
+
}
|
|
1077
|
+
else {
|
|
1078
|
+
output.push(targets.join(', '));
|
|
1079
|
+
}
|
|
1026
1080
|
}
|
|
1027
1081
|
}
|
|
1028
1082
|
if (node.onConflictClause.whereClause) {
|
|
@@ -1034,11 +1088,8 @@ export class Deparser {
|
|
|
1034
1088
|
output.push('DO NOTHING');
|
|
1035
1089
|
}
|
|
1036
1090
|
}
|
|
1037
|
-
if (node.
|
|
1038
|
-
output.push(
|
|
1039
|
-
const returningList = ListUtils.unwrapList(node.returningList);
|
|
1040
|
-
const returns = returningList.map(ret => this.visit(ret, context));
|
|
1041
|
-
output.push(returns.join(', '));
|
|
1091
|
+
if (node.returningClause) {
|
|
1092
|
+
output.push(this.ReturningClause(node.returningClause, context));
|
|
1042
1093
|
}
|
|
1043
1094
|
return output.join(' ');
|
|
1044
1095
|
}
|
|
@@ -1052,38 +1103,8 @@ export class Deparser {
|
|
|
1052
1103
|
output.push(this.RangeVar(node.relation, context));
|
|
1053
1104
|
}
|
|
1054
1105
|
output.push('SET');
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
const firstTarget = targetList[0];
|
|
1058
|
-
const processedTargets = new Set();
|
|
1059
|
-
const assignmentParts = [];
|
|
1060
|
-
for (let i = 0; i < targetList.length; i++) {
|
|
1061
|
-
if (processedTargets.has(i))
|
|
1062
|
-
continue;
|
|
1063
|
-
const target = targetList[i];
|
|
1064
|
-
const multiAssignRef = target.ResTarget?.val?.MultiAssignRef;
|
|
1065
|
-
if (multiAssignRef) {
|
|
1066
|
-
const relatedTargets = [];
|
|
1067
|
-
for (let j = i; j < targetList.length; j++) {
|
|
1068
|
-
const otherTarget = targetList[j];
|
|
1069
|
-
const otherMultiAssignRef = otherTarget.ResTarget?.val?.MultiAssignRef;
|
|
1070
|
-
if (otherMultiAssignRef &&
|
|
1071
|
-
JSON.stringify(otherMultiAssignRef.source) === JSON.stringify(multiAssignRef.source)) {
|
|
1072
|
-
relatedTargets.push(otherTarget);
|
|
1073
|
-
processedTargets.add(j);
|
|
1074
|
-
}
|
|
1075
|
-
}
|
|
1076
|
-
const names = relatedTargets.map(t => t.ResTarget.name);
|
|
1077
|
-
const multiAssignment = `${context.parens(names.join(', '))} = ${this.visit(multiAssignRef.source, context)}`;
|
|
1078
|
-
assignmentParts.push(multiAssignment);
|
|
1079
|
-
}
|
|
1080
|
-
else {
|
|
1081
|
-
// Handle regular single-column assignment
|
|
1082
|
-
assignmentParts.push(this.visit(target, context.spawn('UpdateStmt', { update: true })));
|
|
1083
|
-
processedTargets.add(i);
|
|
1084
|
-
}
|
|
1085
|
-
}
|
|
1086
|
-
output.push(assignmentParts.join(','));
|
|
1106
|
+
if (node.targetList && node.targetList.length > 0) {
|
|
1107
|
+
output.push(this.formatUpdateAssignments(node.targetList, context));
|
|
1087
1108
|
}
|
|
1088
1109
|
if (node.fromClause) {
|
|
1089
1110
|
output.push('FROM');
|
|
@@ -1095,12 +1116,41 @@ export class Deparser {
|
|
|
1095
1116
|
output.push('WHERE');
|
|
1096
1117
|
output.push(this.visit(node.whereClause, context));
|
|
1097
1118
|
}
|
|
1098
|
-
if (node.
|
|
1099
|
-
output.push(
|
|
1100
|
-
output.push(this.deparseReturningList(node.returningList, context));
|
|
1119
|
+
if (node.returningClause) {
|
|
1120
|
+
output.push(this.ReturningClause(node.returningClause, context));
|
|
1101
1121
|
}
|
|
1102
1122
|
return output.join(' ');
|
|
1103
1123
|
}
|
|
1124
|
+
formatUpdateAssignments(targets, context) {
|
|
1125
|
+
const targetList = ListUtils.unwrapList(targets);
|
|
1126
|
+
const processedTargets = new Set();
|
|
1127
|
+
const assignmentParts = [];
|
|
1128
|
+
for (let i = 0; i < targetList.length; i++) {
|
|
1129
|
+
if (processedTargets.has(i))
|
|
1130
|
+
continue;
|
|
1131
|
+
const target = targetList[i];
|
|
1132
|
+
const multiAssignRef = target.ResTarget?.val?.MultiAssignRef;
|
|
1133
|
+
if (multiAssignRef) {
|
|
1134
|
+
const relatedTargets = [];
|
|
1135
|
+
for (let j = i; j < targetList.length; j++) {
|
|
1136
|
+
const otherTarget = targetList[j];
|
|
1137
|
+
const otherMultiAssignRef = otherTarget.ResTarget?.val?.MultiAssignRef;
|
|
1138
|
+
if (otherMultiAssignRef &&
|
|
1139
|
+
JSON.stringify(otherMultiAssignRef.source) === JSON.stringify(multiAssignRef.source)) {
|
|
1140
|
+
relatedTargets.push(otherTarget);
|
|
1141
|
+
processedTargets.add(j);
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
const names = relatedTargets.map(t => QuoteUtils.quoteIdentifier(t.ResTarget.name));
|
|
1145
|
+
assignmentParts.push(`${context.parens(names.join(', '))} = ${this.visit(multiAssignRef.source, context)}`);
|
|
1146
|
+
}
|
|
1147
|
+
else {
|
|
1148
|
+
assignmentParts.push(this.visit(target, context.spawn('UpdateStmt', { update: true })));
|
|
1149
|
+
processedTargets.add(i);
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
return assignmentParts.join(', ');
|
|
1153
|
+
}
|
|
1104
1154
|
DeleteStmt(node, context) {
|
|
1105
1155
|
try {
|
|
1106
1156
|
const output = [];
|
|
@@ -1148,13 +1198,12 @@ export class Deparser {
|
|
|
1148
1198
|
throw new Error(`Error deparsing DeleteStmt: ${error instanceof Error ? error.message : String(error)}`);
|
|
1149
1199
|
}
|
|
1150
1200
|
}
|
|
1151
|
-
if (node.
|
|
1152
|
-
output.push('RETURNING');
|
|
1201
|
+
if (node.returningClause) {
|
|
1153
1202
|
try {
|
|
1154
|
-
output.push(this.
|
|
1203
|
+
output.push(this.ReturningClause(node.returningClause, context));
|
|
1155
1204
|
}
|
|
1156
1205
|
catch (error) {
|
|
1157
|
-
console.warn(`Error processing
|
|
1206
|
+
console.warn(`Error processing returningClause in DeleteStmt: ${error instanceof Error ? error.message : String(error)}`);
|
|
1158
1207
|
throw new Error(`Error deparsing DeleteStmt: ${error instanceof Error ? error.message : String(error)}`);
|
|
1159
1208
|
}
|
|
1160
1209
|
}
|
|
@@ -1175,9 +1224,6 @@ export class Deparser {
|
|
|
1175
1224
|
const cteStrings = ctes.map((cte, index) => {
|
|
1176
1225
|
const cteStr = this.visit(cte, context);
|
|
1177
1226
|
const prefix = index === 0 ? context.newline() : ',' + context.newline();
|
|
1178
|
-
if (this.containsMultilineStringLiteral(cteStr)) {
|
|
1179
|
-
return prefix + cteStr;
|
|
1180
|
-
}
|
|
1181
1227
|
return prefix + context.indent(cteStr);
|
|
1182
1228
|
});
|
|
1183
1229
|
output.push(cteStrings.join(''));
|
|
@@ -1192,12 +1238,12 @@ export class Deparser {
|
|
|
1192
1238
|
ResTarget(node, context) {
|
|
1193
1239
|
const output = [];
|
|
1194
1240
|
if (context.update && node.name) {
|
|
1195
|
-
output.push(QuoteUtils.
|
|
1241
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
1196
1242
|
// Handle indirection (array indexing, field access, etc.)
|
|
1197
1243
|
if (node.indirection && node.indirection.length > 0) {
|
|
1198
1244
|
const indirectionStrs = ListUtils.unwrapList(node.indirection).map(item => {
|
|
1199
1245
|
if (item.String) {
|
|
1200
|
-
return `.${QuoteUtils.
|
|
1246
|
+
return `.${QuoteUtils.quoteIdentifierAfterDot(item.String.sval || item.String.str)}`;
|
|
1201
1247
|
}
|
|
1202
1248
|
return this.visit(item, context);
|
|
1203
1249
|
});
|
|
@@ -1209,12 +1255,12 @@ export class Deparser {
|
|
|
1209
1255
|
}
|
|
1210
1256
|
}
|
|
1211
1257
|
else if (context.insertColumns && node.name) {
|
|
1212
|
-
output.push(QuoteUtils.
|
|
1258
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
1213
1259
|
// Handle indirection for INSERT column lists (e.g., q.c1.r)
|
|
1214
1260
|
if (node.indirection && node.indirection.length > 0) {
|
|
1215
1261
|
const indirectionStrs = ListUtils.unwrapList(node.indirection).map(item => {
|
|
1216
1262
|
if (item.String) {
|
|
1217
|
-
return `.${QuoteUtils.
|
|
1263
|
+
return `.${QuoteUtils.quoteIdentifierAfterDot(item.String.sval || item.String.str)}`;
|
|
1218
1264
|
}
|
|
1219
1265
|
return this.visit(item, context);
|
|
1220
1266
|
});
|
|
@@ -1227,11 +1273,53 @@ export class Deparser {
|
|
|
1227
1273
|
}
|
|
1228
1274
|
if (node.name) {
|
|
1229
1275
|
output.push('AS');
|
|
1230
|
-
output.push(QuoteUtils.
|
|
1276
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
1231
1277
|
}
|
|
1232
1278
|
}
|
|
1233
1279
|
return output.join(' ');
|
|
1234
1280
|
}
|
|
1281
|
+
ATAlterConstraint(node, context) {
|
|
1282
|
+
const output = ['ALTER CONSTRAINT'];
|
|
1283
|
+
if (node.conname) {
|
|
1284
|
+
output.push(QuoteUtils.quoteIdentifier(node.conname));
|
|
1285
|
+
}
|
|
1286
|
+
if (node.alterEnforceability) {
|
|
1287
|
+
output.push(node.is_enforced ? 'ENFORCED' : 'NOT ENFORCED');
|
|
1288
|
+
}
|
|
1289
|
+
if (node.alterDeferrability) {
|
|
1290
|
+
output.push(node.deferrable ? 'DEFERRABLE' : 'NOT DEFERRABLE');
|
|
1291
|
+
if (node.initdeferred) {
|
|
1292
|
+
output.push('INITIALLY DEFERRED');
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
if (node.alterInheritability) {
|
|
1296
|
+
output.push(node.noinherit ? 'NO INHERIT' : 'INHERIT');
|
|
1297
|
+
}
|
|
1298
|
+
return output.join(' ');
|
|
1299
|
+
}
|
|
1300
|
+
deparseKeyAttrs(attrs, withPeriod, context) {
|
|
1301
|
+
const items = ListUtils.unwrapList(attrs).map(attr => this.visit(attr, context));
|
|
1302
|
+
if (withPeriod && items.length > 0) {
|
|
1303
|
+
items[items.length - 1] = `PERIOD ${items[items.length - 1]}`;
|
|
1304
|
+
}
|
|
1305
|
+
return items.join(', ');
|
|
1306
|
+
}
|
|
1307
|
+
ReturningClause(node, context) {
|
|
1308
|
+
const output = ['RETURNING'];
|
|
1309
|
+
if (node.options && node.options.length > 0) {
|
|
1310
|
+
const options = ListUtils.unwrapList(node.options)
|
|
1311
|
+
.map(option => this.visit(option, context));
|
|
1312
|
+
output.push(`WITH (${options.join(', ')})`);
|
|
1313
|
+
}
|
|
1314
|
+
if (node.exprs && node.exprs.length > 0) {
|
|
1315
|
+
output.push(this.deparseReturningList(node.exprs, context));
|
|
1316
|
+
}
|
|
1317
|
+
return output.join(' ');
|
|
1318
|
+
}
|
|
1319
|
+
ReturningOption(node, context) {
|
|
1320
|
+
const keyword = node.option === 'RETURNING_OPTION_NEW' ? 'NEW' : 'OLD';
|
|
1321
|
+
return `${keyword} AS ${QuoteUtils.quoteIdentifier(node.value)}`;
|
|
1322
|
+
}
|
|
1235
1323
|
deparseReturningList(list, context) {
|
|
1236
1324
|
return ListUtils.unwrapList(list)
|
|
1237
1325
|
.filter(item => item != null && this.getNodeType(item) !== 'undefined')
|
|
@@ -1241,7 +1329,7 @@ export class Deparser {
|
|
|
1241
1329
|
if (this.getNodeType(item) === 'ResTarget') {
|
|
1242
1330
|
const resTarget = this.getNodeData(item);
|
|
1243
1331
|
const val = resTarget.val ? this.visit(resTarget.val, context) : '';
|
|
1244
|
-
const alias = resTarget.name ? ` AS ${QuoteUtils.
|
|
1332
|
+
const alias = resTarget.name ? ` AS ${QuoteUtils.quoteIdentifier(resTarget.name)}` : '';
|
|
1245
1333
|
return val + alias;
|
|
1246
1334
|
}
|
|
1247
1335
|
else {
|
|
@@ -1296,7 +1384,8 @@ export class Deparser {
|
|
|
1296
1384
|
FuncCall(node, context) {
|
|
1297
1385
|
const funcname = ListUtils.unwrapList(node.funcname);
|
|
1298
1386
|
const args = ListUtils.unwrapList(node.args);
|
|
1299
|
-
const
|
|
1387
|
+
const funcnameParts = funcname.map((n) => n.String?.sval || n.String?.str || '').filter((s) => s);
|
|
1388
|
+
const name = QuoteUtils.quoteDottedName(funcnameParts);
|
|
1300
1389
|
// Handle special SQL syntax functions like XMLEXISTS and EXTRACT
|
|
1301
1390
|
if (node.funcformat === 'COERCE_SQL_SYNTAX' && name === 'pg_catalog.xmlexists' && args.length >= 2) {
|
|
1302
1391
|
const xpath = this.visit(args[0], context);
|
|
@@ -1305,8 +1394,15 @@ export class Deparser {
|
|
|
1305
1394
|
}
|
|
1306
1395
|
// Handle EXTRACT function with SQL syntax
|
|
1307
1396
|
if (node.funcformat === 'COERCE_SQL_SYNTAX' && name === 'pg_catalog.extract' && args.length >= 2) {
|
|
1308
|
-
|
|
1397
|
+
let field = this.visit(args[0], context);
|
|
1309
1398
|
const source = this.visit(args[1], context);
|
|
1399
|
+
// EXTRACT requires an unquoted uppercase keyword (EPOCH, YEAR, etc.)
|
|
1400
|
+
// but A_Const sval deparsing wraps it in single quotes — strip and uppercase
|
|
1401
|
+
// only when it is spelled the way the bare-keyword form parses back
|
|
1402
|
+
if (/^'(?:year|month|day|hour|minute|second)'$/.test(field)
|
|
1403
|
+
|| (/^'[a-z_][a-z0-9_]*'$/.test(field) && keywordKindOf(field.slice(1, -1)) === 'NO_KEYWORD')) {
|
|
1404
|
+
field = field.slice(1, -1).toUpperCase();
|
|
1405
|
+
}
|
|
1310
1406
|
return `EXTRACT(${field} FROM ${source})`;
|
|
1311
1407
|
}
|
|
1312
1408
|
// Handle TRIM function with SQL syntax (TRIM TRAILING/LEADING/BOTH)
|
|
@@ -1466,43 +1562,41 @@ export class Deparser {
|
|
|
1466
1562
|
result += ` FILTER (WHERE ${this.visit(node.agg_filter, context)})`;
|
|
1467
1563
|
}
|
|
1468
1564
|
if (node.over) {
|
|
1469
|
-
|
|
1470
|
-
if (node.over.name) {
|
|
1471
|
-
result += ` OVER ${node.over.name}`;
|
|
1472
|
-
}
|
|
1473
|
-
else {
|
|
1474
|
-
const windowParts = [];
|
|
1475
|
-
if (node.over.partitionClause) {
|
|
1476
|
-
const partitions = ListUtils.unwrapList(node.over.partitionClause);
|
|
1477
|
-
const partitionStrs = partitions.map(p => this.visit(p, context));
|
|
1478
|
-
windowParts.push(`PARTITION BY ${partitionStrs.join(', ')}`);
|
|
1479
|
-
}
|
|
1480
|
-
if (node.over.orderClause) {
|
|
1481
|
-
const orders = ListUtils.unwrapList(node.over.orderClause);
|
|
1482
|
-
const orderStrs = orders.map(o => this.visit(o, context));
|
|
1483
|
-
windowParts.push(`ORDER BY ${orderStrs.join(', ')}`);
|
|
1484
|
-
}
|
|
1485
|
-
// Handle window frame specifications using the dedicated formatWindowFrame method
|
|
1486
|
-
const frameClause = this.formatWindowFrame(node.over, context.spawn('FuncCall'));
|
|
1487
|
-
if (frameClause) {
|
|
1488
|
-
windowParts.push(frameClause);
|
|
1489
|
-
}
|
|
1490
|
-
if (windowParts.length > 0) {
|
|
1491
|
-
if (context.isPretty() && windowParts.length > 1) {
|
|
1492
|
-
const formattedParts = windowParts.map(part => context.indent(part));
|
|
1493
|
-
result += ` OVER (${context.newline()}${formattedParts.join(context.newline())}${context.newline()})`;
|
|
1494
|
-
}
|
|
1495
|
-
else {
|
|
1496
|
-
result += ` OVER (${windowParts.join(' ')})`;
|
|
1497
|
-
}
|
|
1498
|
-
}
|
|
1499
|
-
else {
|
|
1500
|
-
result += ` OVER ()`;
|
|
1501
|
-
}
|
|
1502
|
-
}
|
|
1565
|
+
result += this.formatOverClause(node.over, context);
|
|
1503
1566
|
}
|
|
1504
1567
|
return result;
|
|
1505
1568
|
}
|
|
1569
|
+
formatOverClause(over, context) {
|
|
1570
|
+
if (over.name) {
|
|
1571
|
+
return ` OVER ${over.name}`;
|
|
1572
|
+
}
|
|
1573
|
+
const windowParts = [];
|
|
1574
|
+
if (over.refname) {
|
|
1575
|
+
windowParts.push(over.refname);
|
|
1576
|
+
}
|
|
1577
|
+
if (over.partitionClause) {
|
|
1578
|
+
const partitions = ListUtils.unwrapList(over.partitionClause);
|
|
1579
|
+
const partitionStrs = partitions.map(p => this.visit(p, context));
|
|
1580
|
+
windowParts.push(`PARTITION BY ${partitionStrs.join(', ')}`);
|
|
1581
|
+
}
|
|
1582
|
+
if (over.orderClause) {
|
|
1583
|
+
const orders = ListUtils.unwrapList(over.orderClause);
|
|
1584
|
+
const orderStrs = orders.map(o => this.visit(o, context));
|
|
1585
|
+
windowParts.push(`ORDER BY ${orderStrs.join(', ')}`);
|
|
1586
|
+
}
|
|
1587
|
+
const frameClause = this.formatWindowFrame(over, context.spawn('FuncCall'));
|
|
1588
|
+
if (frameClause) {
|
|
1589
|
+
windowParts.push(frameClause);
|
|
1590
|
+
}
|
|
1591
|
+
if (windowParts.length === 0) {
|
|
1592
|
+
return ' OVER ()';
|
|
1593
|
+
}
|
|
1594
|
+
if (context.isPretty() && windowParts.length > 1) {
|
|
1595
|
+
const formattedParts = windowParts.map(part => context.indent(part));
|
|
1596
|
+
return ` OVER (${context.newline()}${formattedParts.join(context.newline())}${context.newline()})`;
|
|
1597
|
+
}
|
|
1598
|
+
return ` OVER (${windowParts.join(' ')})`;
|
|
1599
|
+
}
|
|
1506
1600
|
FuncExpr(node, context) {
|
|
1507
1601
|
const funcName = `func_${node.funcid}`;
|
|
1508
1602
|
const args = node.args ? ListUtils.unwrapList(node.args).map(arg => this.visit(arg, context)).join(', ') : '';
|
|
@@ -1513,39 +1607,39 @@ export class Deparser {
|
|
|
1513
1607
|
if (nodeAny.ival !== undefined) {
|
|
1514
1608
|
if (typeof nodeAny.ival === 'object' && nodeAny.ival !== null) {
|
|
1515
1609
|
if (nodeAny.ival.ival !== undefined) {
|
|
1516
|
-
return nodeAny.ival.ival
|
|
1610
|
+
return formatInteger(nodeAny.ival.ival);
|
|
1517
1611
|
}
|
|
1518
1612
|
else if (Object.keys(nodeAny.ival).length === 0) {
|
|
1519
1613
|
return '0';
|
|
1520
1614
|
}
|
|
1521
1615
|
else {
|
|
1522
|
-
return nodeAny.ival
|
|
1616
|
+
return formatInteger(nodeAny.ival);
|
|
1523
1617
|
}
|
|
1524
1618
|
}
|
|
1525
1619
|
else if (nodeAny.ival === null) {
|
|
1526
1620
|
return 'NULL';
|
|
1527
1621
|
}
|
|
1528
1622
|
else {
|
|
1529
|
-
return nodeAny.ival
|
|
1623
|
+
return formatInteger(nodeAny.ival);
|
|
1530
1624
|
}
|
|
1531
1625
|
}
|
|
1532
1626
|
else if (nodeAny.fval !== undefined) {
|
|
1533
1627
|
if (typeof nodeAny.fval === 'object' && nodeAny.fval !== null) {
|
|
1534
1628
|
if (nodeAny.fval.fval !== undefined) {
|
|
1535
|
-
return nodeAny.fval.fval
|
|
1629
|
+
return formatNumeric(nodeAny.fval.fval);
|
|
1536
1630
|
}
|
|
1537
1631
|
else if (Object.keys(nodeAny.fval).length === 0) {
|
|
1538
1632
|
return '0.0';
|
|
1539
1633
|
}
|
|
1540
1634
|
else {
|
|
1541
|
-
return nodeAny.fval
|
|
1635
|
+
return formatNumeric(nodeAny.fval);
|
|
1542
1636
|
}
|
|
1543
1637
|
}
|
|
1544
1638
|
else if (nodeAny.fval === null) {
|
|
1545
1639
|
return 'NULL';
|
|
1546
1640
|
}
|
|
1547
1641
|
else {
|
|
1548
|
-
return nodeAny.fval
|
|
1642
|
+
return formatNumeric(nodeAny.fval);
|
|
1549
1643
|
}
|
|
1550
1644
|
}
|
|
1551
1645
|
else if (nodeAny.sval !== undefined) {
|
|
@@ -1592,15 +1686,7 @@ export class Deparser {
|
|
|
1592
1686
|
else if (nodeAny.bsval !== undefined) {
|
|
1593
1687
|
if (typeof nodeAny.bsval === 'object' && nodeAny.bsval !== null) {
|
|
1594
1688
|
if (nodeAny.bsval.bsval !== undefined) {
|
|
1595
|
-
|
|
1596
|
-
// Check if this is a hexadecimal bit string (starts with x and contains only hex digits)
|
|
1597
|
-
if (bsval.startsWith('x') && /^x[0-9A-Fa-f]+$/.test(bsval)) {
|
|
1598
|
-
return `x'${bsval.substring(1)}'`;
|
|
1599
|
-
}
|
|
1600
|
-
if (bsval.startsWith('b')) {
|
|
1601
|
-
return `b'${bsval.substring(1)}'`;
|
|
1602
|
-
}
|
|
1603
|
-
return `b'${bsval}'`;
|
|
1689
|
+
return formatBitString(nodeAny.bsval.bsval);
|
|
1604
1690
|
}
|
|
1605
1691
|
else if (Object.keys(nodeAny.bsval).length === 0) {
|
|
1606
1692
|
return "''";
|
|
@@ -1613,23 +1699,15 @@ export class Deparser {
|
|
|
1613
1699
|
return 'NULL';
|
|
1614
1700
|
}
|
|
1615
1701
|
else {
|
|
1616
|
-
|
|
1617
|
-
// Check if this is a hexadecimal bit string (starts with x and contains only hex digits)
|
|
1618
|
-
if (bsval.startsWith('x') && /^x[0-9A-Fa-f]+$/.test(bsval)) {
|
|
1619
|
-
return `x'${bsval.substring(1)}'`;
|
|
1620
|
-
}
|
|
1621
|
-
if (bsval.startsWith('b')) {
|
|
1622
|
-
return `b'${bsval.substring(1)}'`;
|
|
1623
|
-
}
|
|
1624
|
-
return `b'${bsval}'`;
|
|
1702
|
+
return formatBitString(nodeAny.bsval);
|
|
1625
1703
|
}
|
|
1626
1704
|
}
|
|
1627
1705
|
if (nodeAny.val) {
|
|
1628
1706
|
if (nodeAny.val.Integer?.ival !== undefined) {
|
|
1629
|
-
return nodeAny.val.Integer.ival
|
|
1707
|
+
return formatInteger(nodeAny.val.Integer.ival);
|
|
1630
1708
|
}
|
|
1631
1709
|
else if (nodeAny.val.Float?.fval !== undefined) {
|
|
1632
|
-
return nodeAny.val.Float.fval
|
|
1710
|
+
return formatNumeric(nodeAny.val.Float.fval);
|
|
1633
1711
|
}
|
|
1634
1712
|
else if (nodeAny.val.String?.sval !== undefined) {
|
|
1635
1713
|
return QuoteUtils.escape(nodeAny.val.String.sval);
|
|
@@ -1638,7 +1716,7 @@ export class Deparser {
|
|
|
1638
1716
|
return nodeAny.val.Boolean.boolval ? 'true' : 'false';
|
|
1639
1717
|
}
|
|
1640
1718
|
else if (nodeAny.val.BitString?.bsval !== undefined) {
|
|
1641
|
-
return nodeAny.val.BitString.bsval;
|
|
1719
|
+
return formatBitString(nodeAny.val.BitString.bsval);
|
|
1642
1720
|
}
|
|
1643
1721
|
}
|
|
1644
1722
|
if (nodeAny.isnull === true) {
|
|
@@ -1650,15 +1728,15 @@ export class Deparser {
|
|
|
1650
1728
|
}
|
|
1651
1729
|
if (nodeAny.Integer !== undefined) {
|
|
1652
1730
|
if (typeof nodeAny.Integer === 'object' && nodeAny.Integer.ival !== undefined) {
|
|
1653
|
-
return nodeAny.Integer.ival
|
|
1731
|
+
return formatInteger(nodeAny.Integer.ival);
|
|
1654
1732
|
}
|
|
1655
|
-
return nodeAny.Integer
|
|
1733
|
+
return formatInteger(nodeAny.Integer);
|
|
1656
1734
|
}
|
|
1657
1735
|
if (nodeAny.Float !== undefined) {
|
|
1658
1736
|
if (typeof nodeAny.Float === 'object' && nodeAny.Float.fval !== undefined) {
|
|
1659
|
-
return nodeAny.Float.fval
|
|
1737
|
+
return formatNumeric(nodeAny.Float.fval);
|
|
1660
1738
|
}
|
|
1661
|
-
return nodeAny.Float
|
|
1739
|
+
return formatNumeric(nodeAny.Float);
|
|
1662
1740
|
}
|
|
1663
1741
|
if (nodeAny.String !== undefined) {
|
|
1664
1742
|
if (typeof nodeAny.String === 'object' && nodeAny.String.sval !== undefined) {
|
|
@@ -1678,7 +1756,7 @@ export class Deparser {
|
|
|
1678
1756
|
const fields = ListUtils.unwrapList(node.fields);
|
|
1679
1757
|
return fields.map(field => {
|
|
1680
1758
|
if (field.String) {
|
|
1681
|
-
return QuoteUtils.
|
|
1759
|
+
return QuoteUtils.quoteIdentifier(field.String.sval || field.String.str);
|
|
1682
1760
|
}
|
|
1683
1761
|
else if (field.A_Star) {
|
|
1684
1762
|
return '*';
|
|
@@ -1755,8 +1833,7 @@ export class Deparser {
|
|
|
1755
1833
|
}
|
|
1756
1834
|
return output.join(' ');
|
|
1757
1835
|
}
|
|
1758
|
-
|
|
1759
|
-
let result = mods(quotedTypeName, args);
|
|
1836
|
+
let result = mods(QuoteUtils.quoteIdentifierTypeName(typeName), args);
|
|
1760
1837
|
if (node.arrayBounds && node.arrayBounds.length > 0) {
|
|
1761
1838
|
result += formatArrayBounds(node.arrayBounds);
|
|
1762
1839
|
}
|
|
@@ -1852,8 +1929,9 @@ export class Deparser {
|
|
|
1852
1929
|
return output.join(' ');
|
|
1853
1930
|
}
|
|
1854
1931
|
}
|
|
1855
|
-
|
|
1856
|
-
|
|
1932
|
+
// Use type-name quoting for non-pg_catalog types
|
|
1933
|
+
// This allows keywords like 'json', 'int', 'boolean' to remain unquoted in type positions
|
|
1934
|
+
let result = mods(QuoteUtils.quoteTypeDottedName(names), args);
|
|
1857
1935
|
if (node.arrayBounds && node.arrayBounds.length > 0) {
|
|
1858
1936
|
result += formatArrayBounds(node.arrayBounds);
|
|
1859
1937
|
}
|
|
@@ -1891,17 +1969,17 @@ export class Deparser {
|
|
|
1891
1969
|
}
|
|
1892
1970
|
let tableName = '';
|
|
1893
1971
|
if (node.catalogname) {
|
|
1894
|
-
tableName = QuoteUtils.
|
|
1972
|
+
tableName = QuoteUtils.quoteIdentifier(node.catalogname);
|
|
1895
1973
|
if (node.schemaname) {
|
|
1896
|
-
tableName += '.' + QuoteUtils.
|
|
1974
|
+
tableName += '.' + QuoteUtils.quoteIdentifierAfterDot(node.schemaname);
|
|
1897
1975
|
}
|
|
1898
|
-
tableName += '.' + QuoteUtils.
|
|
1976
|
+
tableName += '.' + QuoteUtils.quoteIdentifierAfterDot(node.relname);
|
|
1899
1977
|
}
|
|
1900
1978
|
else if (node.schemaname) {
|
|
1901
|
-
tableName = QuoteUtils.
|
|
1979
|
+
tableName = QuoteUtils.quoteQualifiedIdentifier(node.schemaname, node.relname);
|
|
1902
1980
|
}
|
|
1903
1981
|
else {
|
|
1904
|
-
tableName = QuoteUtils.
|
|
1982
|
+
tableName = QuoteUtils.quoteIdentifier(node.relname);
|
|
1905
1983
|
}
|
|
1906
1984
|
output.push(tableName);
|
|
1907
1985
|
if (node.alias) {
|
|
@@ -2055,7 +2133,7 @@ export class Deparser {
|
|
|
2055
2133
|
if (size != null) {
|
|
2056
2134
|
return 'char';
|
|
2057
2135
|
}
|
|
2058
|
-
return '
|
|
2136
|
+
return 'bpchar';
|
|
2059
2137
|
case 'varchar':
|
|
2060
2138
|
return 'varchar';
|
|
2061
2139
|
case 'numeric':
|
|
@@ -2069,7 +2147,7 @@ export class Deparser {
|
|
|
2069
2147
|
case 'int8':
|
|
2070
2148
|
return 'bigint';
|
|
2071
2149
|
case 'real':
|
|
2072
|
-
return '
|
|
2150
|
+
return 'float4';
|
|
2073
2151
|
case 'time':
|
|
2074
2152
|
return 'time';
|
|
2075
2153
|
case 'timestamp':
|
|
@@ -2079,7 +2157,7 @@ export class Deparser {
|
|
|
2079
2157
|
case 'bit':
|
|
2080
2158
|
return 'bit';
|
|
2081
2159
|
default:
|
|
2082
|
-
return
|
|
2160
|
+
return typeName;
|
|
2083
2161
|
}
|
|
2084
2162
|
}
|
|
2085
2163
|
isPgCatalogType(typeName) {
|
|
@@ -2120,14 +2198,16 @@ export class Deparser {
|
|
|
2120
2198
|
A_Indirection(node, context) {
|
|
2121
2199
|
let argStr = this.visit(node.arg, context);
|
|
2122
2200
|
const argType = this.getNodeType(node.arg);
|
|
2123
|
-
|
|
2201
|
+
// Grammar: only a parameter takes indirection bare; every other target is
|
|
2202
|
+
// `'(' a_expr ')' opt_indirection` (a plain column subscript is the same node).
|
|
2203
|
+
if (argType !== 'ParamRef') {
|
|
2124
2204
|
argStr = `(${argStr})`;
|
|
2125
2205
|
}
|
|
2126
2206
|
const output = [argStr];
|
|
2127
2207
|
const indirection = ListUtils.unwrapList(node.indirection);
|
|
2128
2208
|
for (const subnode of indirection) {
|
|
2129
2209
|
if (subnode.String || subnode.A_Star) {
|
|
2130
|
-
const value = subnode.A_Star ? '*' : QuoteUtils.
|
|
2210
|
+
const value = subnode.A_Star ? '*' : QuoteUtils.quoteIdentifier(subnode.String.sval || subnode.String.str);
|
|
2131
2211
|
output.push(`.${value}`);
|
|
2132
2212
|
}
|
|
2133
2213
|
else {
|
|
@@ -2148,21 +2228,11 @@ export class Deparser {
|
|
|
2148
2228
|
if (context.isPretty() && args.length > 0) {
|
|
2149
2229
|
for (const arg of args) {
|
|
2150
2230
|
const whenClause = this.visit(arg, context);
|
|
2151
|
-
|
|
2152
|
-
output.push(context.newline() + whenClause);
|
|
2153
|
-
}
|
|
2154
|
-
else {
|
|
2155
|
-
output.push(context.newline() + context.indent(whenClause));
|
|
2156
|
-
}
|
|
2231
|
+
output.push(context.newline() + context.indent(whenClause));
|
|
2157
2232
|
}
|
|
2158
2233
|
if (node.defresult) {
|
|
2159
2234
|
const elseResult = this.visit(node.defresult, context);
|
|
2160
|
-
|
|
2161
|
-
output.push(context.newline() + 'ELSE ' + elseResult);
|
|
2162
|
-
}
|
|
2163
|
-
else {
|
|
2164
|
-
output.push(context.newline() + context.indent('ELSE ' + elseResult));
|
|
2165
|
-
}
|
|
2235
|
+
output.push(context.newline() + context.indent('ELSE ' + elseResult));
|
|
2166
2236
|
}
|
|
2167
2237
|
output.push(context.newline() + 'END');
|
|
2168
2238
|
return output.join(' ');
|
|
@@ -2272,45 +2342,21 @@ export class Deparser {
|
|
|
2272
2342
|
}
|
|
2273
2343
|
return output.join(' ');
|
|
2274
2344
|
}
|
|
2275
|
-
static RESERVED_WORDS = new Set([
|
|
2276
|
-
'all', 'analyse', 'analyze', 'and', 'any', 'array', 'as', 'asc', 'asymmetric', 'both',
|
|
2277
|
-
'case', 'cast', 'check', 'collate', 'column', 'constraint', 'create', 'current_catalog',
|
|
2278
|
-
'current_date', 'current_role', 'current_time', 'current_timestamp', 'current_user',
|
|
2279
|
-
'default', 'deferrable', 'desc', 'distinct', 'do', 'else', 'end', 'except', 'false',
|
|
2280
|
-
'fetch', 'for', 'foreign', 'from', 'grant', 'group', 'having', 'in', 'initially',
|
|
2281
|
-
'intersect', 'into', 'lateral', 'leading', 'limit', 'localtime', 'localtimestamp',
|
|
2282
|
-
'not', 'null', 'offset', 'on', 'only', 'or', 'order', 'placing', 'primary',
|
|
2283
|
-
'references', 'returning', 'select', 'session_user', 'some', 'symmetric', 'table',
|
|
2284
|
-
'then', 'to', 'trailing', 'true', 'union', 'unique', 'user', 'using', 'variadic',
|
|
2285
|
-
'when', 'where', 'window', 'with'
|
|
2286
|
-
]);
|
|
2287
|
-
static needsQuotes(value) {
|
|
2288
|
-
if (!value)
|
|
2289
|
-
return false;
|
|
2290
|
-
const needsQuotesRegex = /[a-z]+[\W\w]*[A-Z]+|[A-Z]+[\W\w]*[a-z]+|\W/;
|
|
2291
|
-
const isAllUppercase = /^[A-Z]+$/.test(value);
|
|
2292
|
-
return needsQuotesRegex.test(value) ||
|
|
2293
|
-
Deparser.RESERVED_WORDS.has(value.toLowerCase()) ||
|
|
2294
|
-
isAllUppercase;
|
|
2295
|
-
}
|
|
2296
2345
|
quoteIfNeeded(value) {
|
|
2297
|
-
|
|
2298
|
-
return `"${value}"`;
|
|
2299
|
-
}
|
|
2300
|
-
return value;
|
|
2346
|
+
return QuoteUtils.quoteIdentifier(value);
|
|
2301
2347
|
}
|
|
2302
2348
|
preserveOperatorDefElemCase(defName) {
|
|
2303
2349
|
const caseMap = {
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2350
|
+
leftarg: 'Leftarg',
|
|
2351
|
+
rightarg: 'Rightarg',
|
|
2352
|
+
procedure: 'Procedure',
|
|
2353
|
+
function: 'Function',
|
|
2354
|
+
commutator: 'Commutator',
|
|
2355
|
+
negator: 'Negator',
|
|
2356
|
+
restrict: 'Restrict',
|
|
2357
|
+
join: 'Join',
|
|
2358
|
+
hashes: 'Hashes',
|
|
2359
|
+
merges: 'Merges'
|
|
2314
2360
|
};
|
|
2315
2361
|
return caseMap[defName.toLowerCase()] || defName;
|
|
2316
2362
|
}
|
|
@@ -2330,27 +2376,19 @@ export class Deparser {
|
|
|
2330
2376
|
return value; // Don't quote pure operator symbols like "=" or "-"
|
|
2331
2377
|
}
|
|
2332
2378
|
}
|
|
2333
|
-
return
|
|
2379
|
+
return QuoteUtils.quoteIdentifier(value);
|
|
2334
2380
|
}
|
|
2335
2381
|
Integer(node, context) {
|
|
2336
|
-
return node.ival
|
|
2382
|
+
return node.ival === undefined || node.ival === null ? '0' : formatInteger(node.ival);
|
|
2337
2383
|
}
|
|
2338
2384
|
Float(node, context) {
|
|
2339
|
-
return node.fval
|
|
2385
|
+
return node.fval ? formatNumeric(node.fval) : '0.0';
|
|
2340
2386
|
}
|
|
2341
2387
|
Boolean(node, context) {
|
|
2342
2388
|
return node.boolval ? 'true' : 'false';
|
|
2343
2389
|
}
|
|
2344
2390
|
BitString(node, context) {
|
|
2345
|
-
|
|
2346
|
-
if (node.bsval.startsWith('x')) {
|
|
2347
|
-
return `x'${node.bsval.substring(1)}'`;
|
|
2348
|
-
}
|
|
2349
|
-
if (node.bsval.startsWith('b')) {
|
|
2350
|
-
return `b'${node.bsval.substring(1)}'`;
|
|
2351
|
-
}
|
|
2352
|
-
// Fallback for raw values without prefix
|
|
2353
|
-
return `b'${node.bsval}'`;
|
|
2391
|
+
return formatBitString(node.bsval);
|
|
2354
2392
|
}
|
|
2355
2393
|
Null(node, context) {
|
|
2356
2394
|
return 'NULL';
|
|
@@ -2389,7 +2427,7 @@ export class Deparser {
|
|
|
2389
2427
|
output.push(context.parens(elementStrs.join(', ')));
|
|
2390
2428
|
}
|
|
2391
2429
|
}
|
|
2392
|
-
else if (node.tableElts) {
|
|
2430
|
+
else if (node.tableElts && !node.partbound) {
|
|
2393
2431
|
const elements = ListUtils.unwrapList(node.tableElts);
|
|
2394
2432
|
const elementStrs = elements.map(el => {
|
|
2395
2433
|
return this.deparse(el, context.spawn('CreateStmt'));
|
|
@@ -2417,7 +2455,16 @@ export class Deparser {
|
|
|
2417
2455
|
const inherits = ListUtils.unwrapList(node.inhRelations);
|
|
2418
2456
|
const inheritStrs = inherits.map(rel => this.visit(rel, context));
|
|
2419
2457
|
output.push(inheritStrs[0]);
|
|
2420
|
-
if (node.
|
|
2458
|
+
if (node.tableElts) {
|
|
2459
|
+
const elementStrs = ListUtils.unwrapList(node.tableElts).map(el => {
|
|
2460
|
+
return this.deparse(el, context.spawn('CreateStmt'));
|
|
2461
|
+
});
|
|
2462
|
+
output.push(context.parens(elementStrs.join(', ')));
|
|
2463
|
+
}
|
|
2464
|
+
if (node.partbound.is_default) {
|
|
2465
|
+
output.push('DEFAULT');
|
|
2466
|
+
}
|
|
2467
|
+
else if (node.partbound.strategy === 'l' && node.partbound.listdatums) {
|
|
2421
2468
|
output.push('FOR VALUES IN');
|
|
2422
2469
|
const listValues = ListUtils.unwrapList(node.partbound.listdatums)
|
|
2423
2470
|
.map(datum => this.visit(datum, context))
|
|
@@ -2440,13 +2487,9 @@ export class Deparser {
|
|
|
2440
2487
|
output.push(`(${upperValues})`);
|
|
2441
2488
|
}
|
|
2442
2489
|
}
|
|
2443
|
-
else if (node.partbound.strategy === 'h'
|
|
2490
|
+
else if (node.partbound.strategy === 'h') {
|
|
2444
2491
|
output.push('FOR VALUES WITH');
|
|
2445
|
-
|
|
2446
|
-
output.push(`(MODULUS ${node.partbound.modulus}, REMAINDER ${remainder})`);
|
|
2447
|
-
}
|
|
2448
|
-
else if (node.partbound.is_default) {
|
|
2449
|
-
output.push('DEFAULT');
|
|
2492
|
+
output.push(`(MODULUS ${node.partbound.modulus ?? 0}, REMAINDER ${node.partbound.remainder ?? 0})`);
|
|
2450
2493
|
}
|
|
2451
2494
|
}
|
|
2452
2495
|
else if (node.inhRelations) {
|
|
@@ -2507,11 +2550,17 @@ export class Deparser {
|
|
|
2507
2550
|
ColumnDef(node, context) {
|
|
2508
2551
|
const output = [];
|
|
2509
2552
|
if (node.colname) {
|
|
2510
|
-
output.push(QuoteUtils.
|
|
2553
|
+
output.push(QuoteUtils.quoteIdentifier(node.colname));
|
|
2511
2554
|
}
|
|
2512
2555
|
if (node.typeName) {
|
|
2513
2556
|
output.push(this.TypeName(node.typeName, context));
|
|
2514
2557
|
}
|
|
2558
|
+
if (node.storage_name) {
|
|
2559
|
+
output.push('STORAGE', node.storage_name.toUpperCase());
|
|
2560
|
+
}
|
|
2561
|
+
if (node.compression) {
|
|
2562
|
+
output.push('COMPRESSION', QuoteUtils.quoteIdentifier(node.compression));
|
|
2563
|
+
}
|
|
2515
2564
|
if (node.fdwoptions && node.fdwoptions.length > 0) {
|
|
2516
2565
|
output.push('OPTIONS');
|
|
2517
2566
|
const columnContext = context.spawn('ColumnDef');
|
|
@@ -2546,9 +2595,9 @@ export class Deparser {
|
|
|
2546
2595
|
Constraint(node, context) {
|
|
2547
2596
|
const output = [];
|
|
2548
2597
|
// Handle constraint name if present
|
|
2549
|
-
if (node.conname && (node.contype === 'CONSTR_CHECK' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_FOREIGN')) {
|
|
2598
|
+
if (node.conname && (node.contype === 'CONSTR_CHECK' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_FOREIGN' || node.contype === 'CONSTR_NOTNULL' || node.contype === 'CONSTR_EXCLUSION')) {
|
|
2550
2599
|
output.push('CONSTRAINT');
|
|
2551
|
-
output.push(QuoteUtils.
|
|
2600
|
+
output.push(QuoteUtils.quoteIdentifier(node.conname));
|
|
2552
2601
|
}
|
|
2553
2602
|
switch (node.contype) {
|
|
2554
2603
|
case 'CONSTR_NULL':
|
|
@@ -2556,11 +2605,24 @@ export class Deparser {
|
|
|
2556
2605
|
break;
|
|
2557
2606
|
case 'CONSTR_NOTNULL':
|
|
2558
2607
|
output.push('NOT NULL');
|
|
2608
|
+
if (node.keys && node.keys.length > 0 && !context.isColumnConstraint) {
|
|
2609
|
+
const keyList = ListUtils.unwrapList(node.keys)
|
|
2610
|
+
.map(key => this.visit(key, context))
|
|
2611
|
+
.join(', ');
|
|
2612
|
+
output.push(keyList);
|
|
2613
|
+
}
|
|
2614
|
+
if (node.is_no_inherit) {
|
|
2615
|
+
output.push('NO INHERIT');
|
|
2616
|
+
}
|
|
2617
|
+
if (node.skip_validation) {
|
|
2618
|
+
output.push('NOT VALID');
|
|
2619
|
+
}
|
|
2559
2620
|
break;
|
|
2560
2621
|
case 'CONSTR_DEFAULT':
|
|
2561
2622
|
output.push('DEFAULT');
|
|
2562
2623
|
if (node.raw_expr) {
|
|
2563
|
-
|
|
2624
|
+
const defaultExpr = this.visit(node.raw_expr, context);
|
|
2625
|
+
output.push(this.needsBExprParens(node.raw_expr) ? `(${defaultExpr})` : defaultExpr);
|
|
2564
2626
|
}
|
|
2565
2627
|
break;
|
|
2566
2628
|
case 'CONSTR_CHECK':
|
|
@@ -2584,8 +2646,13 @@ export class Deparser {
|
|
|
2584
2646
|
output.push(context.parens(this.visit(node.raw_expr, context)));
|
|
2585
2647
|
}
|
|
2586
2648
|
}
|
|
2587
|
-
//
|
|
2588
|
-
|
|
2649
|
+
// PG18: constraints are enforced unless explicitly NOT ENFORCED
|
|
2650
|
+
// (libpg-query omits false booleans, so undefined means not enforced)
|
|
2651
|
+
if (node.is_enforced !== true && !context.isDomainConstraint) {
|
|
2652
|
+
output.push('NOT ENFORCED');
|
|
2653
|
+
}
|
|
2654
|
+
else if (node.skip_validation) {
|
|
2655
|
+
// NOT ENFORCED implies NOT VALID, so only emit NOT VALID when enforced
|
|
2589
2656
|
output.push('NOT VALID');
|
|
2590
2657
|
}
|
|
2591
2658
|
// Handle NO INHERIT for check constraints - only for table constraints, not domain constraints
|
|
@@ -2605,7 +2672,7 @@ export class Deparser {
|
|
|
2605
2672
|
if (node.raw_expr) {
|
|
2606
2673
|
output.push(context.parens(this.visit(node.raw_expr, context)));
|
|
2607
2674
|
}
|
|
2608
|
-
output.push('STORED');
|
|
2675
|
+
output.push(node.generated_kind === 'v' ? 'VIRTUAL' : 'STORED');
|
|
2609
2676
|
break;
|
|
2610
2677
|
case 'CONSTR_IDENTITY':
|
|
2611
2678
|
output.push('GENERATED');
|
|
@@ -2681,10 +2748,12 @@ export class Deparser {
|
|
|
2681
2748
|
case 'CONSTR_PRIMARY':
|
|
2682
2749
|
output.push('PRIMARY KEY');
|
|
2683
2750
|
if (node.keys && node.keys.length > 0) {
|
|
2684
|
-
const
|
|
2685
|
-
.map(key => this.visit(key, context))
|
|
2686
|
-
|
|
2687
|
-
|
|
2751
|
+
const keyItems = ListUtils.unwrapList(node.keys)
|
|
2752
|
+
.map(key => this.visit(key, context));
|
|
2753
|
+
if (node.without_overlaps) {
|
|
2754
|
+
keyItems[keyItems.length - 1] += ' WITHOUT OVERLAPS';
|
|
2755
|
+
}
|
|
2756
|
+
output.push(`(${keyItems.join(', ')})`);
|
|
2688
2757
|
}
|
|
2689
2758
|
if (node.indexname) {
|
|
2690
2759
|
output.push('USING INDEX');
|
|
@@ -2702,10 +2771,12 @@ export class Deparser {
|
|
|
2702
2771
|
output.push('NULLS NOT DISTINCT');
|
|
2703
2772
|
}
|
|
2704
2773
|
if (node.keys && node.keys.length > 0) {
|
|
2705
|
-
const
|
|
2706
|
-
.map(key => this.visit(key, context))
|
|
2707
|
-
|
|
2708
|
-
|
|
2774
|
+
const keyItems = ListUtils.unwrapList(node.keys)
|
|
2775
|
+
.map(key => this.visit(key, context));
|
|
2776
|
+
if (node.without_overlaps) {
|
|
2777
|
+
keyItems[keyItems.length - 1] += ' WITHOUT OVERLAPS';
|
|
2778
|
+
}
|
|
2779
|
+
output.push(`(${keyItems.join(', ')})`);
|
|
2709
2780
|
}
|
|
2710
2781
|
if (node.indexname) {
|
|
2711
2782
|
output.push('USING INDEX');
|
|
@@ -2718,20 +2789,14 @@ export class Deparser {
|
|
|
2718
2789
|
if (context.isPretty()) {
|
|
2719
2790
|
output.push('\n' + context.indent('FOREIGN KEY'));
|
|
2720
2791
|
if (node.fk_attrs && node.fk_attrs.length > 0) {
|
|
2721
|
-
|
|
2722
|
-
.map(attr => this.visit(attr, context))
|
|
2723
|
-
.join(', ');
|
|
2724
|
-
output.push(`(${fkAttrs})`);
|
|
2792
|
+
output.push(`(${this.deparseKeyAttrs(node.fk_attrs, node.fk_with_period, context)})`);
|
|
2725
2793
|
}
|
|
2726
2794
|
output.push('\n' + context.indent('REFERENCES'));
|
|
2727
2795
|
}
|
|
2728
2796
|
else {
|
|
2729
2797
|
output.push('FOREIGN KEY');
|
|
2730
2798
|
if (node.fk_attrs && node.fk_attrs.length > 0) {
|
|
2731
|
-
|
|
2732
|
-
.map(attr => this.visit(attr, context))
|
|
2733
|
-
.join(', ');
|
|
2734
|
-
output.push(`(${fkAttrs})`);
|
|
2799
|
+
output.push(`(${this.deparseKeyAttrs(node.fk_attrs, node.fk_with_period, context)})`);
|
|
2735
2800
|
}
|
|
2736
2801
|
output.push('REFERENCES');
|
|
2737
2802
|
}
|
|
@@ -2754,9 +2819,7 @@ export class Deparser {
|
|
|
2754
2819
|
}
|
|
2755
2820
|
}
|
|
2756
2821
|
if (node.pk_attrs && node.pk_attrs.length > 0) {
|
|
2757
|
-
const pkAttrs =
|
|
2758
|
-
.map(attr => this.visit(attr, context))
|
|
2759
|
-
.join(', ');
|
|
2822
|
+
const pkAttrs = this.deparseKeyAttrs(node.pk_attrs, node.pk_with_period, context);
|
|
2760
2823
|
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2761
2824
|
const lastIndex = output.length - 1;
|
|
2762
2825
|
if (lastIndex >= 0) {
|
|
@@ -2827,6 +2890,15 @@ export class Deparser {
|
|
|
2827
2890
|
deleteClause += 'SET DEFAULT';
|
|
2828
2891
|
break;
|
|
2829
2892
|
}
|
|
2893
|
+
if ((node.fk_del_action === 'n' || node.fk_del_action === 'd') && node.fk_del_set_cols && node.fk_del_set_cols.length > 0) {
|
|
2894
|
+
const setColumns = ListUtils.unwrapList(node.fk_del_set_cols)
|
|
2895
|
+
.map(column => {
|
|
2896
|
+
const stringNode = column.String;
|
|
2897
|
+
return QuoteUtils.quoteIdentifier(stringNode.sval || stringNode.str || '');
|
|
2898
|
+
})
|
|
2899
|
+
.join(', ');
|
|
2900
|
+
deleteClause += ` (${setColumns})`;
|
|
2901
|
+
}
|
|
2830
2902
|
if (context.isPretty()) {
|
|
2831
2903
|
output.push('\n' + context.indent(deleteClause));
|
|
2832
2904
|
}
|
|
@@ -2835,8 +2907,18 @@ export class Deparser {
|
|
|
2835
2907
|
output.push(deleteClause.replace('ON DELETE ', ''));
|
|
2836
2908
|
}
|
|
2837
2909
|
}
|
|
2838
|
-
//
|
|
2839
|
-
|
|
2910
|
+
// PG18: constraints are enforced unless explicitly NOT ENFORCED
|
|
2911
|
+
// (libpg-query omits false booleans, so undefined means not enforced)
|
|
2912
|
+
if (node.is_enforced !== true && !context.isDomainConstraint) {
|
|
2913
|
+
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2914
|
+
output.push('\n' + context.indent('NOT ENFORCED'));
|
|
2915
|
+
}
|
|
2916
|
+
else {
|
|
2917
|
+
output.push('NOT ENFORCED');
|
|
2918
|
+
}
|
|
2919
|
+
}
|
|
2920
|
+
else if (node.skip_validation && !context.isDomainConstraint) {
|
|
2921
|
+
// NOT ENFORCED implies NOT VALID, so only emit NOT VALID when enforced
|
|
2840
2922
|
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2841
2923
|
output.push('\n' + context.indent('NOT VALID'));
|
|
2842
2924
|
}
|
|
@@ -2857,6 +2939,12 @@ export class Deparser {
|
|
|
2857
2939
|
case 'CONSTR_ATTR_IMMEDIATE':
|
|
2858
2940
|
output.push('INITIALLY IMMEDIATE');
|
|
2859
2941
|
break;
|
|
2942
|
+
case 'CONSTR_ATTR_ENFORCED':
|
|
2943
|
+
output.push('ENFORCED');
|
|
2944
|
+
break;
|
|
2945
|
+
case 'CONSTR_ATTR_NOT_ENFORCED':
|
|
2946
|
+
output.push('NOT ENFORCED');
|
|
2947
|
+
break;
|
|
2860
2948
|
case 'CONSTR_EXCLUSION':
|
|
2861
2949
|
output.push('EXCLUDE');
|
|
2862
2950
|
if (node.access_method) {
|
|
@@ -2891,10 +2979,14 @@ export class Deparser {
|
|
|
2891
2979
|
});
|
|
2892
2980
|
output.push(`(${exclusionElements.join(', ')})`);
|
|
2893
2981
|
}
|
|
2982
|
+
if (node.where_clause) {
|
|
2983
|
+
output.push('WHERE');
|
|
2984
|
+
output.push(context.parens(this.visit(node.where_clause, context)));
|
|
2985
|
+
}
|
|
2894
2986
|
break;
|
|
2895
2987
|
}
|
|
2896
2988
|
// Handle deferrable constraints for all constraint types that support it
|
|
2897
|
-
if (node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_FOREIGN') {
|
|
2989
|
+
if (node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_FOREIGN' || node.contype === 'CONSTR_EXCLUSION') {
|
|
2898
2990
|
if (node.deferrable) {
|
|
2899
2991
|
if (context.isPretty() && node.contype === 'CONSTR_FOREIGN') {
|
|
2900
2992
|
output.push('\n' + context.indent('DEFERRABLE'));
|
|
@@ -2923,6 +3015,9 @@ export class Deparser {
|
|
|
2923
3015
|
output.push('NOT DEFERRABLE');
|
|
2924
3016
|
}
|
|
2925
3017
|
}
|
|
3018
|
+
else if (node.initdeferred) {
|
|
3019
|
+
output.push('INITIALLY DEFERRED');
|
|
3020
|
+
}
|
|
2926
3021
|
}
|
|
2927
3022
|
if (context.isPretty() && node.contype === 'CONSTR_FOREIGN') {
|
|
2928
3023
|
let result = '';
|
|
@@ -2988,6 +3083,9 @@ export class Deparser {
|
|
|
2988
3083
|
output.push(node.name);
|
|
2989
3084
|
}
|
|
2990
3085
|
const windowParts = [];
|
|
3086
|
+
if (node.refname) {
|
|
3087
|
+
windowParts.push(node.refname);
|
|
3088
|
+
}
|
|
2991
3089
|
if (node.partitionClause) {
|
|
2992
3090
|
const partitions = ListUtils.unwrapList(node.partitionClause);
|
|
2993
3091
|
const partitionStrs = partitions.map(p => this.visit(p, context));
|
|
@@ -2998,12 +3096,9 @@ export class Deparser {
|
|
|
2998
3096
|
const orderStrs = orders.map(o => this.visit(o, context));
|
|
2999
3097
|
windowParts.push(`ORDER BY ${orderStrs.join(', ')}`);
|
|
3000
3098
|
}
|
|
3001
|
-
|
|
3002
|
-
if (
|
|
3003
|
-
|
|
3004
|
-
if (frameClause) {
|
|
3005
|
-
windowParts.push(frameClause);
|
|
3006
|
-
}
|
|
3099
|
+
const frameClause = this.formatWindowFrame(node, context.spawn('WindowDef'));
|
|
3100
|
+
if (frameClause) {
|
|
3101
|
+
windowParts.push(frameClause);
|
|
3007
3102
|
}
|
|
3008
3103
|
if (windowParts.length > 0) {
|
|
3009
3104
|
if (node.name) {
|
|
@@ -3020,103 +3115,97 @@ export class Deparser {
|
|
|
3020
3115
|
}
|
|
3021
3116
|
return output.join(' ');
|
|
3022
3117
|
}
|
|
3118
|
+
formatIdentityColumnOptions(def, context) {
|
|
3119
|
+
const seqContext = context.spawn('AlterSeqStmt');
|
|
3120
|
+
return ListUtils.unwrapList(def).map(item => {
|
|
3121
|
+
const el = item.DefElem;
|
|
3122
|
+
if (!el)
|
|
3123
|
+
return this.visit(item, context);
|
|
3124
|
+
if (el.defname === 'generated') {
|
|
3125
|
+
const ival = el.arg?.Integer?.ival ?? 0;
|
|
3126
|
+
return ival === 97 ? 'SET GENERATED ALWAYS' : 'SET GENERATED BY DEFAULT';
|
|
3127
|
+
}
|
|
3128
|
+
if (el.defname === 'restart') {
|
|
3129
|
+
return el.arg ? `RESTART WITH ${this.visit(el.arg, context)}` : 'RESTART';
|
|
3130
|
+
}
|
|
3131
|
+
return `SET ${this.visit(item, seqContext)}`;
|
|
3132
|
+
}).join(' ');
|
|
3133
|
+
}
|
|
3134
|
+
// b_expr (used by DEFAULT) excludes IN/LIKE/BETWEEN and boolean operators.
|
|
3135
|
+
needsBExprParens(node) {
|
|
3136
|
+
const nodeType = this.getNodeType(node);
|
|
3137
|
+
if (nodeType === 'BoolExpr')
|
|
3138
|
+
return true;
|
|
3139
|
+
if (nodeType === 'A_Expr') {
|
|
3140
|
+
const kind = this.getNodeData(node).kind;
|
|
3141
|
+
return kind !== 'AEXPR_OP' && kind !== 'AEXPR_DISTINCT' && kind !== 'AEXPR_NOT_DISTINCT';
|
|
3142
|
+
}
|
|
3143
|
+
return false;
|
|
3144
|
+
}
|
|
3023
3145
|
formatWindowFrame(node, context) {
|
|
3024
|
-
if (!node.frameOptions)
|
|
3146
|
+
if (!node.frameOptions || !(node.frameOptions & FRAMEOPTION_NONDEFAULT))
|
|
3025
3147
|
return null;
|
|
3026
3148
|
const frameOptions = node.frameOptions;
|
|
3027
3149
|
const frameParts = [];
|
|
3028
|
-
if (frameOptions &
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
frameParts.push('GROUPS');
|
|
3037
|
-
}
|
|
3150
|
+
if (frameOptions & FRAMEOPTION_RANGE) {
|
|
3151
|
+
frameParts.push('RANGE');
|
|
3152
|
+
}
|
|
3153
|
+
else if (frameOptions & FRAMEOPTION_ROWS) {
|
|
3154
|
+
frameParts.push('ROWS');
|
|
3155
|
+
}
|
|
3156
|
+
else if (frameOptions & FRAMEOPTION_GROUPS) {
|
|
3157
|
+
frameParts.push('GROUPS');
|
|
3038
3158
|
}
|
|
3039
3159
|
if (frameParts.length === 0)
|
|
3040
3160
|
return null;
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
boundsParts.push('CURRENT ROW');
|
|
3045
|
-
boundsParts.push('AND UNBOUNDED FOLLOWING');
|
|
3161
|
+
let start = null;
|
|
3162
|
+
if (frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING) {
|
|
3163
|
+
start = 'UNBOUNDED PRECEDING';
|
|
3046
3164
|
}
|
|
3047
|
-
else if (frameOptions
|
|
3048
|
-
|
|
3049
|
-
boundsParts.push('AND CURRENT ROW');
|
|
3165
|
+
else if (frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING) {
|
|
3166
|
+
start = 'UNBOUNDED FOLLOWING';
|
|
3050
3167
|
}
|
|
3051
|
-
else if (frameOptions
|
|
3052
|
-
|
|
3053
|
-
boundsParts.push(`${this.visit(node.startOffset, context)} PRECEDING`);
|
|
3054
|
-
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
3055
|
-
}
|
|
3168
|
+
else if (frameOptions & FRAMEOPTION_START_CURRENT_ROW) {
|
|
3169
|
+
start = 'CURRENT ROW';
|
|
3056
3170
|
}
|
|
3057
|
-
else if (frameOptions
|
|
3058
|
-
|
|
3059
|
-
boundsParts.push('AND CURRENT ROW');
|
|
3171
|
+
else if (frameOptions & FRAMEOPTION_START_OFFSET_PRECEDING && node.startOffset) {
|
|
3172
|
+
start = `${this.visit(node.startOffset, context)} PRECEDING`;
|
|
3060
3173
|
}
|
|
3061
|
-
else if (frameOptions
|
|
3062
|
-
|
|
3063
|
-
if (node.endOffset) {
|
|
3064
|
-
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
3065
|
-
}
|
|
3174
|
+
else if (frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING && node.startOffset) {
|
|
3175
|
+
start = `${this.visit(node.startOffset, context)} FOLLOWING`;
|
|
3066
3176
|
}
|
|
3067
|
-
|
|
3068
|
-
|
|
3177
|
+
let end = null;
|
|
3178
|
+
if (frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING) {
|
|
3179
|
+
end = 'UNBOUNDED PRECEDING';
|
|
3069
3180
|
}
|
|
3070
|
-
else {
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
}
|
|
3086
|
-
else if (frameOptions & 0x20) { // FRAMEOPTION_START_CURRENT_ROW
|
|
3087
|
-
boundsParts.push('CURRENT ROW');
|
|
3088
|
-
}
|
|
3089
|
-
// Handle end bound - prioritize explicit offset values over bit flags
|
|
3090
|
-
if (node.endOffset) {
|
|
3091
|
-
if (boundsParts.length > 0) {
|
|
3092
|
-
if (frameOptions & 0x1000) { // FRAMEOPTION_END_VALUE_PRECEDING
|
|
3093
|
-
boundsParts.push(`AND ${this.visit(node.endOffset, context)} PRECEDING`);
|
|
3094
|
-
}
|
|
3095
|
-
else if (frameOptions & 0x2000) { // FRAMEOPTION_END_VALUE_FOLLOWING
|
|
3096
|
-
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
3097
|
-
}
|
|
3098
|
-
else {
|
|
3099
|
-
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
3100
|
-
}
|
|
3101
|
-
}
|
|
3102
|
-
}
|
|
3103
|
-
else if (frameOptions & 0x80) { // FRAMEOPTION_END_UNBOUNDED_FOLLOWING
|
|
3104
|
-
if (boundsParts.length > 0) {
|
|
3105
|
-
boundsParts.push('AND UNBOUNDED FOLLOWING');
|
|
3106
|
-
}
|
|
3107
|
-
}
|
|
3108
|
-
else if (frameOptions & 0x100) { // FRAMEOPTION_END_CURRENT_ROW
|
|
3109
|
-
if (boundsParts.length > 0) {
|
|
3110
|
-
boundsParts.push('AND CURRENT ROW');
|
|
3111
|
-
}
|
|
3181
|
+
else if (frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING) {
|
|
3182
|
+
end = 'UNBOUNDED FOLLOWING';
|
|
3183
|
+
}
|
|
3184
|
+
else if (frameOptions & FRAMEOPTION_END_CURRENT_ROW) {
|
|
3185
|
+
end = 'CURRENT ROW';
|
|
3186
|
+
}
|
|
3187
|
+
else if (frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING && node.endOffset) {
|
|
3188
|
+
end = `${this.visit(node.endOffset, context)} PRECEDING`;
|
|
3189
|
+
}
|
|
3190
|
+
else if (frameOptions & FRAMEOPTION_END_OFFSET_FOLLOWING && node.endOffset) {
|
|
3191
|
+
end = `${this.visit(node.endOffset, context)} FOLLOWING`;
|
|
3192
|
+
}
|
|
3193
|
+
if (start) {
|
|
3194
|
+
if (frameOptions & FRAMEOPTION_BETWEEN) {
|
|
3195
|
+
frameParts.push(`BETWEEN ${start} AND ${end ?? 'CURRENT ROW'}`);
|
|
3112
3196
|
}
|
|
3113
|
-
else
|
|
3114
|
-
|
|
3197
|
+
else {
|
|
3198
|
+
frameParts.push(start);
|
|
3115
3199
|
}
|
|
3116
3200
|
}
|
|
3117
|
-
if (
|
|
3118
|
-
frameParts.push('
|
|
3119
|
-
|
|
3201
|
+
if (frameOptions & FRAMEOPTION_EXCLUDE_CURRENT_ROW) {
|
|
3202
|
+
frameParts.push('EXCLUDE CURRENT ROW');
|
|
3203
|
+
}
|
|
3204
|
+
else if (frameOptions & FRAMEOPTION_EXCLUDE_GROUP) {
|
|
3205
|
+
frameParts.push('EXCLUDE GROUP');
|
|
3206
|
+
}
|
|
3207
|
+
else if (frameOptions & FRAMEOPTION_EXCLUDE_TIES) {
|
|
3208
|
+
frameParts.push('EXCLUDE TIES');
|
|
3120
3209
|
}
|
|
3121
3210
|
return frameParts.join(' ');
|
|
3122
3211
|
}
|
|
@@ -3194,8 +3283,35 @@ export class Deparser {
|
|
|
3194
3283
|
if (node.ctequery) {
|
|
3195
3284
|
output.push(context.parens(this.visit(node.ctequery, context)));
|
|
3196
3285
|
}
|
|
3286
|
+
if (node.search_clause) {
|
|
3287
|
+
const sc = node.search_clause;
|
|
3288
|
+
const cols = ListUtils.unwrapList(sc.search_col_list).map(c => this.visit(c, context));
|
|
3289
|
+
output.push('SEARCH', sc.search_breadth_first ? 'BREADTH' : 'DEPTH', 'FIRST BY');
|
|
3290
|
+
output.push(cols.join(', '));
|
|
3291
|
+
output.push('SET', QuoteUtils.quoteIdentifier(sc.search_seq_column));
|
|
3292
|
+
}
|
|
3293
|
+
if (node.cycle_clause) {
|
|
3294
|
+
const cc = node.cycle_clause;
|
|
3295
|
+
const cols = ListUtils.unwrapList(cc.cycle_col_list).map(c => this.visit(c, context));
|
|
3296
|
+
output.push('CYCLE', cols.join(', '));
|
|
3297
|
+
output.push('SET', QuoteUtils.quoteIdentifier(cc.cycle_mark_column));
|
|
3298
|
+
if (cc.cycle_mark_value && cc.cycle_mark_default) {
|
|
3299
|
+
output.push('TO', this.formatAexprConst(cc.cycle_mark_value, context));
|
|
3300
|
+
output.push('DEFAULT', this.formatAexprConst(cc.cycle_mark_default, context));
|
|
3301
|
+
}
|
|
3302
|
+
output.push('USING', QuoteUtils.quoteIdentifier(cc.cycle_path_column));
|
|
3303
|
+
}
|
|
3197
3304
|
return output.join(' ');
|
|
3198
3305
|
}
|
|
3306
|
+
// Renders a constant in the restricted AexprConst grammar (e.g. `point '(1,1)'`
|
|
3307
|
+
// rather than `CAST('(1,1)' AS point)`).
|
|
3308
|
+
formatAexprConst(node, context) {
|
|
3309
|
+
const cast = node.TypeCast;
|
|
3310
|
+
if (cast?.arg?.A_Const?.sval && cast.typeName) {
|
|
3311
|
+
return `${this.TypeName(cast.typeName, context)} ${this.visit(cast.arg, context)}`;
|
|
3312
|
+
}
|
|
3313
|
+
return this.visit(node, context);
|
|
3314
|
+
}
|
|
3199
3315
|
ParamRef(node, context) {
|
|
3200
3316
|
return `$${node.number}`;
|
|
3201
3317
|
}
|
|
@@ -3445,7 +3561,7 @@ export class Deparser {
|
|
|
3445
3561
|
output.push('IF NOT EXISTS');
|
|
3446
3562
|
}
|
|
3447
3563
|
if (node.idxname) {
|
|
3448
|
-
output.push(QuoteUtils.
|
|
3564
|
+
output.push(QuoteUtils.quoteIdentifier(node.idxname));
|
|
3449
3565
|
}
|
|
3450
3566
|
output.push('ON');
|
|
3451
3567
|
if (node.relation) {
|
|
@@ -3464,9 +3580,8 @@ export class Deparser {
|
|
|
3464
3580
|
output.push('INCLUDE');
|
|
3465
3581
|
output.push(context.parens(includeStrs.join(', ')));
|
|
3466
3582
|
}
|
|
3467
|
-
if (node.
|
|
3468
|
-
output.push('
|
|
3469
|
-
output.push(this.visit(node.whereClause, context));
|
|
3583
|
+
if (node.nulls_not_distinct) {
|
|
3584
|
+
output.push('NULLS NOT DISTINCT');
|
|
3470
3585
|
}
|
|
3471
3586
|
if (node.options && node.options.length > 0) {
|
|
3472
3587
|
const indexContext = context.spawn('IndexStmt');
|
|
@@ -3474,19 +3589,20 @@ export class Deparser {
|
|
|
3474
3589
|
output.push('WITH');
|
|
3475
3590
|
output.push(context.parens(optionStrs.join(', ')));
|
|
3476
3591
|
}
|
|
3477
|
-
if (node.nulls_not_distinct) {
|
|
3478
|
-
output.push('NULLS NOT DISTINCT');
|
|
3479
|
-
}
|
|
3480
3592
|
if (node.tableSpace) {
|
|
3481
3593
|
output.push('TABLESPACE');
|
|
3482
|
-
output.push(QuoteUtils.
|
|
3594
|
+
output.push(QuoteUtils.quoteIdentifier(node.tableSpace));
|
|
3595
|
+
}
|
|
3596
|
+
if (node.whereClause) {
|
|
3597
|
+
output.push('WHERE');
|
|
3598
|
+
output.push(this.visit(node.whereClause, context));
|
|
3483
3599
|
}
|
|
3484
3600
|
return output.join(' ');
|
|
3485
3601
|
}
|
|
3486
3602
|
IndexElem(node, context) {
|
|
3487
3603
|
const output = [];
|
|
3488
3604
|
if (node.name) {
|
|
3489
|
-
output.push(QuoteUtils.
|
|
3605
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
3490
3606
|
}
|
|
3491
3607
|
else if (node.expr) {
|
|
3492
3608
|
output.push(context.parens(this.visit(node.expr, context)));
|
|
@@ -3504,7 +3620,7 @@ export class Deparser {
|
|
|
3504
3620
|
const opclassOpts = ListUtils.unwrapList(node.opclassopts).map(opt => {
|
|
3505
3621
|
if (opt.DefElem && opt.DefElem.arg && this.getNodeType(opt.DefElem.arg) === 'String') {
|
|
3506
3622
|
const stringData = this.getNodeData(opt.DefElem.arg);
|
|
3507
|
-
return `${opt.DefElem.defname}
|
|
3623
|
+
return `${QuoteUtils.quoteIdentifierAfterDot(opt.DefElem.defname)}=${QuoteUtils.escape(stringData.sval)}`;
|
|
3508
3624
|
}
|
|
3509
3625
|
return this.visit(opt, context.spawn('IndexElem'));
|
|
3510
3626
|
});
|
|
@@ -3537,7 +3653,7 @@ export class Deparser {
|
|
|
3537
3653
|
PartitionElem(node, context) {
|
|
3538
3654
|
const output = [];
|
|
3539
3655
|
if (node.name) {
|
|
3540
|
-
output.push(QuoteUtils.
|
|
3656
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
3541
3657
|
}
|
|
3542
3658
|
else if (node.expr) {
|
|
3543
3659
|
output.push(context.parens(this.visit(node.expr, context)));
|
|
@@ -3555,12 +3671,12 @@ export class Deparser {
|
|
|
3555
3671
|
}
|
|
3556
3672
|
PartitionCmd(node, context) {
|
|
3557
3673
|
const output = [];
|
|
3674
|
+
if (node.name) {
|
|
3675
|
+
output.push(this.RangeVar(node.name, context));
|
|
3676
|
+
}
|
|
3558
3677
|
if (node.concurrent) {
|
|
3559
3678
|
output.push('CONCURRENTLY');
|
|
3560
3679
|
}
|
|
3561
|
-
if (node.name) {
|
|
3562
|
-
output.push(this.visit(node.name, context));
|
|
3563
|
-
}
|
|
3564
3680
|
if (node.bound) {
|
|
3565
3681
|
if (node.bound.strategy === 'l' && node.bound.listdatums) {
|
|
3566
3682
|
output.push('FOR VALUES IN');
|
|
@@ -3585,9 +3701,9 @@ export class Deparser {
|
|
|
3585
3701
|
output.push(`(${upperValues})`);
|
|
3586
3702
|
}
|
|
3587
3703
|
}
|
|
3588
|
-
else if (node.bound.strategy === 'h'
|
|
3704
|
+
else if (node.bound.strategy === 'h') {
|
|
3589
3705
|
output.push('FOR VALUES WITH');
|
|
3590
|
-
output.push(`(
|
|
3706
|
+
output.push(`(MODULUS ${node.bound.modulus ?? 0}, REMAINDER ${node.bound.remainder ?? 0})`);
|
|
3591
3707
|
}
|
|
3592
3708
|
else if (node.bound.is_default) {
|
|
3593
3709
|
output.push('DEFAULT');
|
|
@@ -3718,12 +3834,7 @@ export class Deparser {
|
|
|
3718
3834
|
if (context.isPretty()) {
|
|
3719
3835
|
// For complex JOIN conditions, format with proper indentation
|
|
3720
3836
|
if (qualsStr.includes('AND') || qualsStr.includes('OR') || qualsStr.length > 50) {
|
|
3721
|
-
|
|
3722
|
-
output.push(` ON ${qualsStr}`);
|
|
3723
|
-
}
|
|
3724
|
-
else {
|
|
3725
|
-
output.push(` ON${context.newline()}${context.indent(qualsStr)}`);
|
|
3726
|
-
}
|
|
3837
|
+
output.push(` ON${context.newline()}${context.indent(qualsStr)}`);
|
|
3727
3838
|
}
|
|
3728
3839
|
else {
|
|
3729
3840
|
output.push(` ON ${qualsStr}`);
|
|
@@ -3787,37 +3898,37 @@ export class Deparser {
|
|
|
3787
3898
|
case 'TRANS_STMT_SAVEPOINT':
|
|
3788
3899
|
output.push('SAVEPOINT');
|
|
3789
3900
|
if (node.savepoint_name) {
|
|
3790
|
-
output.push(QuoteUtils.
|
|
3901
|
+
output.push(QuoteUtils.quoteIdentifier(node.savepoint_name));
|
|
3791
3902
|
}
|
|
3792
3903
|
break;
|
|
3793
3904
|
case 'TRANS_STMT_RELEASE':
|
|
3794
3905
|
output.push('RELEASE SAVEPOINT');
|
|
3795
3906
|
if (node.savepoint_name) {
|
|
3796
|
-
output.push(QuoteUtils.
|
|
3907
|
+
output.push(QuoteUtils.quoteIdentifier(node.savepoint_name));
|
|
3797
3908
|
}
|
|
3798
3909
|
break;
|
|
3799
3910
|
case 'TRANS_STMT_ROLLBACK_TO':
|
|
3800
3911
|
output.push('ROLLBACK TO');
|
|
3801
3912
|
if (node.savepoint_name) {
|
|
3802
|
-
output.push(QuoteUtils.
|
|
3913
|
+
output.push(QuoteUtils.quoteIdentifier(node.savepoint_name));
|
|
3803
3914
|
}
|
|
3804
3915
|
break;
|
|
3805
3916
|
case 'TRANS_STMT_PREPARE':
|
|
3806
3917
|
output.push('PREPARE TRANSACTION');
|
|
3807
3918
|
if (node.gid) {
|
|
3808
|
-
output.push(
|
|
3919
|
+
output.push(QuoteUtils.escape(node.gid));
|
|
3809
3920
|
}
|
|
3810
3921
|
break;
|
|
3811
3922
|
case 'TRANS_STMT_COMMIT_PREPARED':
|
|
3812
3923
|
output.push('COMMIT PREPARED');
|
|
3813
3924
|
if (node.gid) {
|
|
3814
|
-
output.push(
|
|
3925
|
+
output.push(QuoteUtils.escape(node.gid));
|
|
3815
3926
|
}
|
|
3816
3927
|
break;
|
|
3817
3928
|
case 'TRANS_STMT_ROLLBACK_PREPARED':
|
|
3818
3929
|
output.push('ROLLBACK PREPARED');
|
|
3819
3930
|
if (node.gid) {
|
|
3820
|
-
output.push(
|
|
3931
|
+
output.push(QuoteUtils.escape(node.gid));
|
|
3821
3932
|
}
|
|
3822
3933
|
break;
|
|
3823
3934
|
default:
|
|
@@ -3884,28 +3995,39 @@ export class Deparser {
|
|
|
3884
3995
|
switch (node.kind) {
|
|
3885
3996
|
case 'VAR_SET_VALUE':
|
|
3886
3997
|
const localPrefix = node.is_local ? 'LOCAL ' : '';
|
|
3998
|
+
if (node.jumble_args && node.name === 'xmloption' && node.args) {
|
|
3999
|
+
const xmlValue = this.getNodeData(ListUtils.unwrapList(node.args)[0]);
|
|
4000
|
+
const xmlOption = (typeof xmlValue.sval === 'object' ? xmlValue.sval.sval : xmlValue.sval) || '';
|
|
4001
|
+
return `SET ${localPrefix}XML OPTION ${xmlOption.toUpperCase()}`;
|
|
4002
|
+
}
|
|
3887
4003
|
const args = node.args ? ListUtils.unwrapList(node.args).map(arg => {
|
|
3888
4004
|
const nodeData = this.getNodeData(arg);
|
|
3889
4005
|
if (nodeData.sval !== undefined) {
|
|
3890
4006
|
const svalValue = typeof nodeData.sval === 'object' ? nodeData.sval.sval : nodeData.sval;
|
|
3891
|
-
if (svalValue
|
|
3892
|
-
return
|
|
4007
|
+
if (!/^[a-z_][a-z0-9_]*$/.test(svalValue) || svalValue.includes(' ') || svalValue.includes('-') || /[A-Z]/.test(svalValue) || /^\d/.test(svalValue) || svalValue.includes('.') || svalValue.includes('$') || svalValue.toLowerCase() === 'all' || /^[+-]\d/.test(svalValue)) {
|
|
4008
|
+
return QuoteUtils.escape(svalValue);
|
|
3893
4009
|
}
|
|
3894
4010
|
return svalValue;
|
|
3895
4011
|
}
|
|
3896
4012
|
return this.visit(arg, context);
|
|
3897
4013
|
}).join(', ') : '';
|
|
4014
|
+
if (node.jumble_args && node.name === 'timezone') {
|
|
4015
|
+
return `SET ${localPrefix}TIME ZONE ${args}`;
|
|
4016
|
+
}
|
|
3898
4017
|
// Handle args - always include TO clause if args exist (even if empty string)
|
|
3899
|
-
const paramName =
|
|
4018
|
+
const paramName = QuoteUtils.quoteIdentifier(node.name);
|
|
3900
4019
|
if (!node.args || node.args.length === 0) {
|
|
3901
4020
|
return `SET ${localPrefix}${paramName}`;
|
|
3902
4021
|
}
|
|
3903
4022
|
return `SET ${localPrefix}${paramName} TO ${args}`;
|
|
3904
4023
|
case 'VAR_SET_DEFAULT':
|
|
3905
|
-
|
|
4024
|
+
if (node.jumble_args && node.name === 'timezone') {
|
|
4025
|
+
return `SET ${node.is_local ? 'LOCAL ' : ''}TIME ZONE DEFAULT`;
|
|
4026
|
+
}
|
|
4027
|
+
const defaultParamName = QuoteUtils.quoteIdentifier(node.name);
|
|
3906
4028
|
return `SET ${defaultParamName} TO DEFAULT`;
|
|
3907
4029
|
case 'VAR_SET_CURRENT':
|
|
3908
|
-
const currentParamName =
|
|
4030
|
+
const currentParamName = QuoteUtils.quoteIdentifier(node.name);
|
|
3909
4031
|
return `SET ${currentParamName} FROM CURRENT`;
|
|
3910
4032
|
case 'VAR_SET_MULTI':
|
|
3911
4033
|
if (node.name === 'TRANSACTION' || node.name === 'SESSION CHARACTERISTICS') {
|
|
@@ -3979,7 +4101,7 @@ export class Deparser {
|
|
|
3979
4101
|
return `SET ${assignments}`;
|
|
3980
4102
|
}
|
|
3981
4103
|
case 'VAR_RESET':
|
|
3982
|
-
const resetParamName =
|
|
4104
|
+
const resetParamName = QuoteUtils.quoteIdentifier(node.name);
|
|
3983
4105
|
return `RESET ${resetParamName}`;
|
|
3984
4106
|
case 'VAR_RESET_ALL':
|
|
3985
4107
|
return 'RESET ALL';
|
|
@@ -3999,7 +4121,7 @@ export class Deparser {
|
|
|
3999
4121
|
output.push('IF NOT EXISTS');
|
|
4000
4122
|
}
|
|
4001
4123
|
if (node.schemaname) {
|
|
4002
|
-
output.push(node.schemaname);
|
|
4124
|
+
output.push(QuoteUtils.quoteIdentifier(node.schemaname));
|
|
4003
4125
|
}
|
|
4004
4126
|
if (node.authrole) {
|
|
4005
4127
|
output.push('AUTHORIZATION');
|
|
@@ -4206,7 +4328,7 @@ export class Deparser {
|
|
|
4206
4328
|
if (objList && objList.List && objList.List.items) {
|
|
4207
4329
|
const items = objList.List.items.map((item) => {
|
|
4208
4330
|
if (item.String && item.String.sval) {
|
|
4209
|
-
return item.String.sval;
|
|
4331
|
+
return QuoteUtils.quoteIdentifier(item.String.sval);
|
|
4210
4332
|
}
|
|
4211
4333
|
return this.visit(item, context);
|
|
4212
4334
|
});
|
|
@@ -4248,7 +4370,7 @@ export class Deparser {
|
|
|
4248
4370
|
if (objList && objList.List && objList.List.items) {
|
|
4249
4371
|
const items = objList.List.items.map((item) => {
|
|
4250
4372
|
if (item.String && item.String.sval) {
|
|
4251
|
-
return QuoteUtils.
|
|
4373
|
+
return QuoteUtils.quoteIdentifier(item.String.sval);
|
|
4252
4374
|
}
|
|
4253
4375
|
return this.visit(item, context);
|
|
4254
4376
|
}).filter((name) => name && name.trim());
|
|
@@ -4282,13 +4404,13 @@ export class Deparser {
|
|
|
4282
4404
|
if (items.length === 2) {
|
|
4283
4405
|
const accessMethod = items[0];
|
|
4284
4406
|
const objectName = items[1];
|
|
4285
|
-
return `${QuoteUtils.
|
|
4407
|
+
return `${QuoteUtils.quoteIdentifier(objectName)} USING ${accessMethod}`;
|
|
4286
4408
|
}
|
|
4287
4409
|
else if (items.length === 3) {
|
|
4288
4410
|
const accessMethod = items[0];
|
|
4289
4411
|
const schemaName = items[1];
|
|
4290
4412
|
const objectName = items[2];
|
|
4291
|
-
return `${QuoteUtils.
|
|
4413
|
+
return `${QuoteUtils.quoteQualifiedIdentifier(schemaName, objectName)} USING ${accessMethod}`;
|
|
4292
4414
|
}
|
|
4293
4415
|
return items.join('.');
|
|
4294
4416
|
}
|
|
@@ -4331,7 +4453,7 @@ export class Deparser {
|
|
|
4331
4453
|
if (objList && objList.List && objList.List.items) {
|
|
4332
4454
|
const items = objList.List.items.map((item) => {
|
|
4333
4455
|
if (item.String && item.String.sval) {
|
|
4334
|
-
return QuoteUtils.
|
|
4456
|
+
return QuoteUtils.quoteIdentifier(item.String.sval);
|
|
4335
4457
|
}
|
|
4336
4458
|
return this.visit(item, context);
|
|
4337
4459
|
}).filter((name) => name && name.trim());
|
|
@@ -4379,7 +4501,7 @@ export class Deparser {
|
|
|
4379
4501
|
PLAssignStmt(node, context) {
|
|
4380
4502
|
const output = [];
|
|
4381
4503
|
if (node.name) {
|
|
4382
|
-
let nameWithIndirection = QuoteUtils.
|
|
4504
|
+
let nameWithIndirection = QuoteUtils.quoteIdentifier(node.name);
|
|
4383
4505
|
if (node.indirection && node.indirection.length > 0) {
|
|
4384
4506
|
const indirectionStr = node.indirection
|
|
4385
4507
|
.map((ind) => this.visit(ind, context))
|
|
@@ -4429,10 +4551,10 @@ export class Deparser {
|
|
|
4429
4551
|
output.push('PROGRAM');
|
|
4430
4552
|
}
|
|
4431
4553
|
if (node.filename) {
|
|
4432
|
-
output.push(
|
|
4554
|
+
output.push(QuoteUtils.escape(node.filename));
|
|
4433
4555
|
}
|
|
4434
4556
|
else {
|
|
4435
|
-
output.push('STDIN');
|
|
4557
|
+
output.push(node.is_from ? 'STDIN' : 'STDOUT');
|
|
4436
4558
|
}
|
|
4437
4559
|
if (node.options && node.options.length > 0) {
|
|
4438
4560
|
output.push('WITH');
|
|
@@ -4528,7 +4650,7 @@ export class Deparser {
|
|
|
4528
4650
|
const parts = [];
|
|
4529
4651
|
const indentedParts = [];
|
|
4530
4652
|
if (colDefData.colname) {
|
|
4531
|
-
parts.push(QuoteUtils.
|
|
4653
|
+
parts.push(QuoteUtils.quoteIdentifier(colDefData.colname));
|
|
4532
4654
|
}
|
|
4533
4655
|
if (colDefData.typeName) {
|
|
4534
4656
|
parts.push(this.TypeName(colDefData.typeName, context));
|
|
@@ -4586,7 +4708,7 @@ export class Deparser {
|
|
|
4586
4708
|
else {
|
|
4587
4709
|
const parts = [];
|
|
4588
4710
|
if (colDefData.colname) {
|
|
4589
|
-
parts.push(QuoteUtils.
|
|
4711
|
+
parts.push(QuoteUtils.quoteIdentifier(colDefData.colname));
|
|
4590
4712
|
}
|
|
4591
4713
|
if (colDefData.typeName) {
|
|
4592
4714
|
parts.push(this.TypeName(colDefData.typeName, context));
|
|
@@ -4640,7 +4762,7 @@ export class Deparser {
|
|
|
4640
4762
|
}
|
|
4641
4763
|
}
|
|
4642
4764
|
if (node.name) {
|
|
4643
|
-
output.push(QuoteUtils.
|
|
4765
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4644
4766
|
}
|
|
4645
4767
|
if (node.behavior === 'DROP_CASCADE') {
|
|
4646
4768
|
output.push('CASCADE');
|
|
@@ -4657,13 +4779,16 @@ export class Deparser {
|
|
|
4657
4779
|
output.push('ALTER COLUMN');
|
|
4658
4780
|
}
|
|
4659
4781
|
if (node.name) {
|
|
4660
|
-
output.push(QuoteUtils.
|
|
4782
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4661
4783
|
}
|
|
4662
4784
|
output.push('TYPE');
|
|
4663
4785
|
if (node.def) {
|
|
4664
4786
|
const nodeData = this.getNodeData(node.def);
|
|
4665
4787
|
if (nodeData && nodeData.typeName) {
|
|
4666
4788
|
output.push(this.TypeName(nodeData.typeName, context));
|
|
4789
|
+
if (nodeData.collClause) {
|
|
4790
|
+
output.push(this.CollateClause(nodeData.collClause, context));
|
|
4791
|
+
}
|
|
4667
4792
|
// Handle USING clause (stored in raw_default for ALTER COLUMN TYPE)
|
|
4668
4793
|
if (nodeData.raw_default) {
|
|
4669
4794
|
output.push('USING');
|
|
@@ -4684,7 +4809,7 @@ export class Deparser {
|
|
|
4684
4809
|
case 'AT_SetTableSpace':
|
|
4685
4810
|
output.push('SET TABLESPACE');
|
|
4686
4811
|
if (node.name) {
|
|
4687
|
-
output.push(QuoteUtils.
|
|
4812
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4688
4813
|
}
|
|
4689
4814
|
break;
|
|
4690
4815
|
case 'AT_AddConstraint':
|
|
@@ -4702,7 +4827,7 @@ export class Deparser {
|
|
|
4702
4827
|
output.push('DROP CONSTRAINT');
|
|
4703
4828
|
}
|
|
4704
4829
|
if (node.name) {
|
|
4705
|
-
output.push(QuoteUtils.
|
|
4830
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4706
4831
|
}
|
|
4707
4832
|
if (node.behavior === 'DROP_CASCADE') {
|
|
4708
4833
|
output.push('CASCADE');
|
|
@@ -4740,7 +4865,7 @@ export class Deparser {
|
|
|
4740
4865
|
case 'AT_ColumnDefault':
|
|
4741
4866
|
output.push('ALTER COLUMN');
|
|
4742
4867
|
if (node.name) {
|
|
4743
|
-
output.push(QuoteUtils.
|
|
4868
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4744
4869
|
}
|
|
4745
4870
|
if (node.def) {
|
|
4746
4871
|
output.push('SET DEFAULT');
|
|
@@ -4753,7 +4878,7 @@ export class Deparser {
|
|
|
4753
4878
|
case 'AT_SetStorage':
|
|
4754
4879
|
output.push('ALTER COLUMN');
|
|
4755
4880
|
if (node.name) {
|
|
4756
|
-
output.push(QuoteUtils.
|
|
4881
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4757
4882
|
}
|
|
4758
4883
|
output.push('SET STORAGE');
|
|
4759
4884
|
if (node.def) {
|
|
@@ -4764,7 +4889,7 @@ export class Deparser {
|
|
|
4764
4889
|
case 'AT_ClusterOn':
|
|
4765
4890
|
output.push('CLUSTER ON');
|
|
4766
4891
|
if (node.name) {
|
|
4767
|
-
output.push(QuoteUtils.
|
|
4892
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4768
4893
|
}
|
|
4769
4894
|
break;
|
|
4770
4895
|
case 'AT_DropCluster':
|
|
@@ -4791,21 +4916,21 @@ export class Deparser {
|
|
|
4791
4916
|
case 'AT_SetNotNull':
|
|
4792
4917
|
output.push('ALTER COLUMN');
|
|
4793
4918
|
if (node.name) {
|
|
4794
|
-
output.push(QuoteUtils.
|
|
4919
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4795
4920
|
}
|
|
4796
4921
|
output.push('SET NOT NULL');
|
|
4797
4922
|
break;
|
|
4798
4923
|
case 'AT_DropNotNull':
|
|
4799
4924
|
output.push('ALTER COLUMN');
|
|
4800
4925
|
if (node.name) {
|
|
4801
|
-
output.push(QuoteUtils.
|
|
4926
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4802
4927
|
}
|
|
4803
4928
|
output.push('DROP NOT NULL');
|
|
4804
4929
|
break;
|
|
4805
4930
|
case 'AT_SetStatistics':
|
|
4806
4931
|
output.push('ALTER COLUMN');
|
|
4807
4932
|
if (node.name) {
|
|
4808
|
-
output.push(QuoteUtils.
|
|
4933
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4809
4934
|
}
|
|
4810
4935
|
else if (node.num !== undefined && node.num !== null) {
|
|
4811
4936
|
output.push(node.num.toString());
|
|
@@ -4818,7 +4943,7 @@ export class Deparser {
|
|
|
4818
4943
|
case 'AT_SetOptions':
|
|
4819
4944
|
output.push('ALTER COLUMN');
|
|
4820
4945
|
if (node.name) {
|
|
4821
|
-
output.push(QuoteUtils.
|
|
4946
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4822
4947
|
}
|
|
4823
4948
|
output.push('SET');
|
|
4824
4949
|
if (node.def) {
|
|
@@ -4835,7 +4960,7 @@ export class Deparser {
|
|
|
4835
4960
|
case 'AT_ResetOptions':
|
|
4836
4961
|
output.push('ALTER COLUMN');
|
|
4837
4962
|
if (node.name) {
|
|
4838
|
-
output.push(QuoteUtils.
|
|
4963
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4839
4964
|
}
|
|
4840
4965
|
output.push('RESET');
|
|
4841
4966
|
if (node.def) {
|
|
@@ -4852,7 +4977,7 @@ export class Deparser {
|
|
|
4852
4977
|
case 'AT_SetCompression':
|
|
4853
4978
|
output.push('ALTER COLUMN');
|
|
4854
4979
|
if (node.name) {
|
|
4855
|
-
output.push(QuoteUtils.
|
|
4980
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4856
4981
|
}
|
|
4857
4982
|
output.push('SET COMPRESSION');
|
|
4858
4983
|
if (node.def) {
|
|
@@ -4862,31 +4987,31 @@ export class Deparser {
|
|
|
4862
4987
|
case 'AT_ValidateConstraint':
|
|
4863
4988
|
output.push('VALIDATE CONSTRAINT');
|
|
4864
4989
|
if (node.name) {
|
|
4865
|
-
output.push(QuoteUtils.
|
|
4990
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4866
4991
|
}
|
|
4867
4992
|
break;
|
|
4868
4993
|
case 'AT_EnableTrig':
|
|
4869
4994
|
output.push('ENABLE TRIGGER');
|
|
4870
4995
|
if (node.name) {
|
|
4871
|
-
output.push(QuoteUtils.
|
|
4996
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4872
4997
|
}
|
|
4873
4998
|
break;
|
|
4874
4999
|
case 'AT_EnableAlwaysTrig':
|
|
4875
5000
|
output.push('ENABLE ALWAYS TRIGGER');
|
|
4876
5001
|
if (node.name) {
|
|
4877
|
-
output.push(QuoteUtils.
|
|
5002
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4878
5003
|
}
|
|
4879
5004
|
break;
|
|
4880
5005
|
case 'AT_EnableReplicaTrig':
|
|
4881
5006
|
output.push('ENABLE REPLICA TRIGGER');
|
|
4882
5007
|
if (node.name) {
|
|
4883
|
-
output.push(QuoteUtils.
|
|
5008
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4884
5009
|
}
|
|
4885
5010
|
break;
|
|
4886
5011
|
case 'AT_DisableTrig':
|
|
4887
5012
|
output.push('DISABLE TRIGGER');
|
|
4888
5013
|
if (node.name) {
|
|
4889
|
-
output.push(QuoteUtils.
|
|
5014
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4890
5015
|
}
|
|
4891
5016
|
break;
|
|
4892
5017
|
case 'AT_EnableTrigAll':
|
|
@@ -4904,31 +5029,31 @@ export class Deparser {
|
|
|
4904
5029
|
case 'AT_EnableRule':
|
|
4905
5030
|
output.push('ENABLE RULE');
|
|
4906
5031
|
if (node.name) {
|
|
4907
|
-
output.push(QuoteUtils.
|
|
5032
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4908
5033
|
}
|
|
4909
5034
|
break;
|
|
4910
5035
|
case 'AT_EnableAlwaysRule':
|
|
4911
5036
|
output.push('ENABLE ALWAYS RULE');
|
|
4912
5037
|
if (node.name) {
|
|
4913
|
-
output.push(QuoteUtils.
|
|
5038
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4914
5039
|
}
|
|
4915
5040
|
break;
|
|
4916
5041
|
case 'AT_EnableReplicaRule':
|
|
4917
5042
|
output.push('ENABLE REPLICA RULE');
|
|
4918
5043
|
if (node.name) {
|
|
4919
|
-
output.push(QuoteUtils.
|
|
5044
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4920
5045
|
}
|
|
4921
5046
|
break;
|
|
4922
5047
|
case 'AT_DisableRule':
|
|
4923
5048
|
output.push('DISABLE RULE');
|
|
4924
5049
|
if (node.name) {
|
|
4925
|
-
output.push(QuoteUtils.
|
|
5050
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4926
5051
|
}
|
|
4927
5052
|
break;
|
|
4928
5053
|
case 'AT_SetAccessMethod':
|
|
4929
5054
|
output.push('SET ACCESS METHOD');
|
|
4930
5055
|
if (node.name) {
|
|
4931
|
-
output.push(QuoteUtils.
|
|
5056
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4932
5057
|
}
|
|
4933
5058
|
else {
|
|
4934
5059
|
// Handle DEFAULT access method case
|
|
@@ -4982,7 +5107,7 @@ export class Deparser {
|
|
|
4982
5107
|
case 'AT_CookedColumnDefault':
|
|
4983
5108
|
output.push('ALTER COLUMN');
|
|
4984
5109
|
if (node.name) {
|
|
4985
|
-
output.push(QuoteUtils.
|
|
5110
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4986
5111
|
}
|
|
4987
5112
|
if (node.def) {
|
|
4988
5113
|
output.push('SET DEFAULT');
|
|
@@ -4995,26 +5120,23 @@ export class Deparser {
|
|
|
4995
5120
|
case 'AT_SetExpression':
|
|
4996
5121
|
output.push('ALTER COLUMN');
|
|
4997
5122
|
if (node.name) {
|
|
4998
|
-
output.push(QuoteUtils.
|
|
5123
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
4999
5124
|
}
|
|
5000
5125
|
output.push('SET EXPRESSION');
|
|
5001
5126
|
if (node.def) {
|
|
5002
|
-
output.push(
|
|
5127
|
+
output.push('AS');
|
|
5128
|
+
output.push(context.parens(this.visit(node.def, context)));
|
|
5003
5129
|
}
|
|
5004
5130
|
break;
|
|
5005
5131
|
case 'AT_DropExpression':
|
|
5006
5132
|
output.push('ALTER COLUMN');
|
|
5007
5133
|
if (node.name) {
|
|
5008
|
-
output.push(QuoteUtils.
|
|
5134
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
5009
5135
|
}
|
|
5010
5136
|
output.push('DROP EXPRESSION');
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
output.push('ALTER COLUMN');
|
|
5014
|
-
if (node.name) {
|
|
5015
|
-
output.push(QuoteUtils.quote(node.name));
|
|
5137
|
+
if (node.missing_ok) {
|
|
5138
|
+
output.push('IF EXISTS');
|
|
5016
5139
|
}
|
|
5017
|
-
output.push('SET NOT NULL');
|
|
5018
5140
|
break;
|
|
5019
5141
|
case 'AT_AddIndex':
|
|
5020
5142
|
output.push('ADD');
|
|
@@ -5041,23 +5163,28 @@ export class Deparser {
|
|
|
5041
5163
|
}
|
|
5042
5164
|
break;
|
|
5043
5165
|
case 'AT_AlterConstraint':
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
|
|
5053
|
-
|
|
5166
|
+
if (node.def && this.getNodeType(node.def) === 'ATAlterConstraint') {
|
|
5167
|
+
output.push(this.ATAlterConstraint(this.getNodeData(node.def), context));
|
|
5168
|
+
}
|
|
5169
|
+
else {
|
|
5170
|
+
output.push('ALTER CONSTRAINT');
|
|
5171
|
+
if (node.def && this.getNodeType(node.def) === 'Constraint') {
|
|
5172
|
+
const constraintData = this.getNodeData(node.def);
|
|
5173
|
+
if (constraintData.conname) {
|
|
5174
|
+
output.push(QuoteUtils.quoteIdentifier(constraintData.conname));
|
|
5175
|
+
if (constraintData.deferrable !== undefined) {
|
|
5176
|
+
output.push(constraintData.deferrable ? 'DEFERRABLE' : 'NOT DEFERRABLE');
|
|
5177
|
+
}
|
|
5178
|
+
if (constraintData.initdeferred !== undefined) {
|
|
5179
|
+
output.push(constraintData.initdeferred ? 'INITIALLY DEFERRED' : 'INITIALLY IMMEDIATE');
|
|
5180
|
+
}
|
|
5054
5181
|
}
|
|
5055
5182
|
}
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5183
|
+
else if (node.name) {
|
|
5184
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
5185
|
+
if (node.def) {
|
|
5186
|
+
output.push(this.visit(node.def, context));
|
|
5187
|
+
}
|
|
5061
5188
|
}
|
|
5062
5189
|
}
|
|
5063
5190
|
break;
|
|
@@ -5076,7 +5203,7 @@ export class Deparser {
|
|
|
5076
5203
|
case 'AT_AlterColumnGenericOptions':
|
|
5077
5204
|
output.push('ALTER COLUMN');
|
|
5078
5205
|
if (node.name) {
|
|
5079
|
-
output.push(QuoteUtils.
|
|
5206
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
5080
5207
|
}
|
|
5081
5208
|
output.push('OPTIONS');
|
|
5082
5209
|
if (node.def) {
|
|
@@ -5130,7 +5257,7 @@ export class Deparser {
|
|
|
5130
5257
|
case 'AT_AddIdentity':
|
|
5131
5258
|
output.push('ALTER COLUMN');
|
|
5132
5259
|
if (node.name) {
|
|
5133
|
-
output.push(QuoteUtils.
|
|
5260
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
5134
5261
|
}
|
|
5135
5262
|
output.push('ADD');
|
|
5136
5263
|
if (node.def) {
|
|
@@ -5140,24 +5267,20 @@ export class Deparser {
|
|
|
5140
5267
|
case 'AT_SetIdentity':
|
|
5141
5268
|
output.push('ALTER COLUMN');
|
|
5142
5269
|
if (node.name) {
|
|
5143
|
-
output.push(QuoteUtils.
|
|
5270
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
5144
5271
|
}
|
|
5145
|
-
output.push('SET');
|
|
5146
5272
|
if (node.def) {
|
|
5147
|
-
output.push(this.
|
|
5273
|
+
output.push(this.formatIdentityColumnOptions(node.def, context));
|
|
5148
5274
|
}
|
|
5149
5275
|
break;
|
|
5150
5276
|
case 'AT_DropIdentity':
|
|
5151
5277
|
output.push('ALTER COLUMN');
|
|
5152
5278
|
if (node.name) {
|
|
5153
|
-
output.push(QuoteUtils.
|
|
5279
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
5154
5280
|
}
|
|
5155
5281
|
output.push('DROP IDENTITY');
|
|
5156
|
-
if (node.
|
|
5157
|
-
output.push('
|
|
5158
|
-
}
|
|
5159
|
-
else if (node.behavior === 'DROP_RESTRICT') {
|
|
5160
|
-
output.push('RESTRICT');
|
|
5282
|
+
if (node.missing_ok) {
|
|
5283
|
+
output.push('IF EXISTS');
|
|
5161
5284
|
}
|
|
5162
5285
|
break;
|
|
5163
5286
|
case 'AT_ReAddStatistics':
|
|
@@ -5184,7 +5307,8 @@ export class Deparser {
|
|
|
5184
5307
|
output.push('FUNCTION');
|
|
5185
5308
|
}
|
|
5186
5309
|
if (node.funcname && node.funcname.length > 0) {
|
|
5187
|
-
const
|
|
5310
|
+
const funcnameParts = node.funcname.map((name) => name.String?.sval || name.String?.str || '').filter((s) => s);
|
|
5311
|
+
const funcName = QuoteUtils.quoteDottedName(funcnameParts);
|
|
5188
5312
|
if (node.parameters && node.parameters.length > 0) {
|
|
5189
5313
|
const params = node.parameters
|
|
5190
5314
|
.filter((param) => {
|
|
@@ -5193,7 +5317,13 @@ export class Deparser {
|
|
|
5193
5317
|
})
|
|
5194
5318
|
.map((param) => this.visit(param, context));
|
|
5195
5319
|
if (params.length > 0) {
|
|
5196
|
-
|
|
5320
|
+
if (context.isPretty()) {
|
|
5321
|
+
const formattedParams = params.map(p => context.indent(p)).join(',' + context.newline());
|
|
5322
|
+
output.push(funcName + '(' + context.newline() + formattedParams + context.newline() + ')');
|
|
5323
|
+
}
|
|
5324
|
+
else {
|
|
5325
|
+
output.push(funcName + '(' + params.join(', ') + ')');
|
|
5326
|
+
}
|
|
5197
5327
|
}
|
|
5198
5328
|
else {
|
|
5199
5329
|
output.push(funcName + '()');
|
|
@@ -5208,15 +5338,21 @@ export class Deparser {
|
|
|
5208
5338
|
return paramData.mode === 'FUNC_PARAM_TABLE';
|
|
5209
5339
|
});
|
|
5210
5340
|
if (hasTableParams) {
|
|
5211
|
-
output.push('RETURNS TABLE (');
|
|
5212
5341
|
const tableParams = node.parameters
|
|
5213
5342
|
.filter((param) => {
|
|
5214
5343
|
const paramData = this.getNodeData(param);
|
|
5215
5344
|
return paramData.mode === 'FUNC_PARAM_TABLE';
|
|
5216
5345
|
})
|
|
5217
5346
|
.map((param) => this.visit(param, context));
|
|
5218
|
-
|
|
5219
|
-
|
|
5347
|
+
if (context.isPretty()) {
|
|
5348
|
+
const formattedTableParams = tableParams.map(p => context.indent(p)).join(',' + context.newline());
|
|
5349
|
+
output.push('RETURNS TABLE (' + context.newline() + formattedTableParams + context.newline() + ')');
|
|
5350
|
+
}
|
|
5351
|
+
else {
|
|
5352
|
+
output.push('RETURNS TABLE (');
|
|
5353
|
+
output.push(tableParams.join(', '));
|
|
5354
|
+
output.push(')');
|
|
5355
|
+
}
|
|
5220
5356
|
}
|
|
5221
5357
|
else if (node.returnType) {
|
|
5222
5358
|
output.push('RETURNS');
|
|
@@ -5238,6 +5374,7 @@ export class Deparser {
|
|
|
5238
5374
|
if (bodyType === 'List') {
|
|
5239
5375
|
const statements = ListUtils.unwrapList(node.sql_body);
|
|
5240
5376
|
if (statements.length === 0 || (statements.length === 1 && Object.keys(statements[0]).length === 0)) {
|
|
5377
|
+
// empty body: nothing to emit
|
|
5241
5378
|
}
|
|
5242
5379
|
else {
|
|
5243
5380
|
// Handle nested List structure in BEGIN ATOMIC blocks
|
|
@@ -5289,7 +5426,7 @@ export class Deparser {
|
|
|
5289
5426
|
}
|
|
5290
5427
|
}
|
|
5291
5428
|
if (node.name) {
|
|
5292
|
-
output.push(QuoteUtils.
|
|
5429
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
5293
5430
|
}
|
|
5294
5431
|
if (node.argType) {
|
|
5295
5432
|
output.push(this.TypeName(node.argType, context));
|
|
@@ -5361,7 +5498,7 @@ export class Deparser {
|
|
|
5361
5498
|
output.push('ROLE');
|
|
5362
5499
|
}
|
|
5363
5500
|
if (node.role) {
|
|
5364
|
-
const roleName =
|
|
5501
|
+
const roleName = QuoteUtils.quoteIdentifier(node.role);
|
|
5365
5502
|
output.push(roleName);
|
|
5366
5503
|
}
|
|
5367
5504
|
if (node.options) {
|
|
@@ -5385,25 +5522,28 @@ export class Deparser {
|
|
|
5385
5522
|
if (node.arg && this.getNodeType(node.arg) === 'List') {
|
|
5386
5523
|
const listData = this.getNodeData(node.arg);
|
|
5387
5524
|
const listItems = ListUtils.unwrapList(listData.items);
|
|
5525
|
+
const preservedName = this.preserveOperatorDefElemCase(node.defname);
|
|
5388
5526
|
if (listItems.length === 1 && listItems[0].String) {
|
|
5389
|
-
const preservedName = this.preserveOperatorDefElemCase(node.defname);
|
|
5390
5527
|
return `${preservedName} = ${listItems[0].String.sval}`;
|
|
5391
5528
|
}
|
|
5529
|
+
if (listItems.length > 1 && listItems.every((item) => item.String)) {
|
|
5530
|
+
return `${preservedName} = OPERATOR(${this.qualifiedOperatorName(listItems)})`;
|
|
5531
|
+
}
|
|
5392
5532
|
}
|
|
5393
5533
|
}
|
|
5394
5534
|
// Handle IndexElem opclassopts - MUST be first to preserve string types
|
|
5395
5535
|
if (context.parentNodeTypes.includes('IndexElem')) {
|
|
5396
5536
|
if (node.arg && this.getNodeType(node.arg) === 'String') {
|
|
5397
5537
|
const stringData = this.getNodeData(node.arg);
|
|
5398
|
-
return `${node.defname}
|
|
5538
|
+
return `${QuoteUtils.quoteIdentifierAfterDot(node.defname)}=${QuoteUtils.escape(stringData.sval)}`;
|
|
5399
5539
|
}
|
|
5400
|
-
return `${node.defname}=${this.visit(node.arg, context.spawn('DefElem'))}`;
|
|
5540
|
+
return `${QuoteUtils.quoteIdentifierAfterDot(node.defname)}=${this.formatOptionValue(node.arg, this.visit(node.arg, context.spawn('DefElem')))}`;
|
|
5401
5541
|
}
|
|
5402
5542
|
// Handle CREATE OPERATOR boolean flags - MUST be first to preserve case
|
|
5403
5543
|
if (context.parentNodeTypes.includes('DefineStmt') &&
|
|
5404
5544
|
['hashes', 'merges'].includes(node.defname.toLowerCase()) && !node.arg) {
|
|
5405
5545
|
if (node.defname !== node.defname.toLowerCase() && node.defname !== node.defname.toUpperCase()) {
|
|
5406
|
-
return
|
|
5546
|
+
return QuoteUtils.quoteIdentifier(node.defname);
|
|
5407
5547
|
}
|
|
5408
5548
|
return node.defname.charAt(0).toUpperCase() + node.defname.slice(1).toLowerCase();
|
|
5409
5549
|
}
|
|
@@ -5422,12 +5562,8 @@ export class Deparser {
|
|
|
5422
5562
|
const defElemContext = context.spawn('DefElem');
|
|
5423
5563
|
const argValue = this.visit(node.arg, defElemContext);
|
|
5424
5564
|
if (context.parentNodeTypes.includes('CreateFdwStmt') || context.parentNodeTypes.includes('AlterFdwStmt')) {
|
|
5425
|
-
const finalValue =
|
|
5426
|
-
|
|
5427
|
-
: argValue;
|
|
5428
|
-
const quotedDefname = node.defname.includes(' ') || node.defname.includes('-') || Deparser.needsQuotes(node.defname)
|
|
5429
|
-
? `"${node.defname}"`
|
|
5430
|
-
: node.defname;
|
|
5565
|
+
const finalValue = this.quoteDefElemArg(node.arg, argValue);
|
|
5566
|
+
const quotedDefname = QuoteUtils.quoteIdentifier(node.defname);
|
|
5431
5567
|
if (node.defaction === 'DEFELEM_ADD') {
|
|
5432
5568
|
return `ADD ${quotedDefname} ${finalValue}`;
|
|
5433
5569
|
}
|
|
@@ -5439,9 +5575,7 @@ export class Deparser {
|
|
|
5439
5575
|
}
|
|
5440
5576
|
return `${quotedDefname} ${finalValue}`;
|
|
5441
5577
|
}
|
|
5442
|
-
const quotedValue =
|
|
5443
|
-
? `'${argValue}'`
|
|
5444
|
-
: argValue;
|
|
5578
|
+
const quotedValue = this.quoteDefElemArg(node.arg, argValue);
|
|
5445
5579
|
if (node.defaction === 'DEFELEM_ADD') {
|
|
5446
5580
|
return `ADD ${node.defname} ${quotedValue}`;
|
|
5447
5581
|
}
|
|
@@ -5451,9 +5585,7 @@ export class Deparser {
|
|
|
5451
5585
|
else if (node.defaction === 'DEFELEM_SET') {
|
|
5452
5586
|
return `SET ${node.defname} ${quotedValue}`;
|
|
5453
5587
|
}
|
|
5454
|
-
const quotedDefname =
|
|
5455
|
-
? `"${node.defname}"`
|
|
5456
|
-
: node.defname;
|
|
5588
|
+
const quotedDefname = QuoteUtils.quoteIdentifier(node.defname);
|
|
5457
5589
|
return `${quotedDefname} ${quotedValue}`;
|
|
5458
5590
|
}
|
|
5459
5591
|
else if (node.defaction === 'DEFELEM_DROP') {
|
|
@@ -5475,9 +5607,7 @@ export class Deparser {
|
|
|
5475
5607
|
}
|
|
5476
5608
|
const defElemContext = context.spawn('DefElem');
|
|
5477
5609
|
const argValue = this.visit(node.arg, defElemContext);
|
|
5478
|
-
const quotedValue =
|
|
5479
|
-
? `'${argValue}'`
|
|
5480
|
-
: argValue;
|
|
5610
|
+
const quotedValue = this.quoteDefElemArg(node.arg, argValue);
|
|
5481
5611
|
return `PASSWORD ${quotedValue}`;
|
|
5482
5612
|
}
|
|
5483
5613
|
}
|
|
@@ -5500,6 +5630,9 @@ export class Deparser {
|
|
|
5500
5630
|
if (listItems.length === 1 && listItems[0].String) {
|
|
5501
5631
|
return `${node.defname} = ${listItems[0].String.sval}`;
|
|
5502
5632
|
}
|
|
5633
|
+
if (listItems.length > 1 && listItems.every((item) => item.String)) {
|
|
5634
|
+
return `${node.defname} = OPERATOR(${this.qualifiedOperatorName(listItems)})`;
|
|
5635
|
+
}
|
|
5503
5636
|
}
|
|
5504
5637
|
}
|
|
5505
5638
|
if (context.parentNodeTypes.includes('CreatedbStmt') || context.parentNodeTypes.includes('DropdbStmt')) {
|
|
@@ -5513,9 +5646,7 @@ export class Deparser {
|
|
|
5513
5646
|
const quotedValue = typeof argValue === 'string'
|
|
5514
5647
|
? QuoteUtils.escape(argValue)
|
|
5515
5648
|
: argValue;
|
|
5516
|
-
const quotedDefname =
|
|
5517
|
-
? `"${node.defname}"`
|
|
5518
|
-
: node.defname;
|
|
5649
|
+
const quotedDefname = QuoteUtils.quoteIdentifier(node.defname);
|
|
5519
5650
|
return `${quotedDefname} ${quotedValue}`;
|
|
5520
5651
|
}
|
|
5521
5652
|
if (context.parentNodeTypes.includes('CreateRoleStmt') || context.parentNodeTypes.includes('AlterRoleStmt')) {
|
|
@@ -5544,9 +5675,7 @@ export class Deparser {
|
|
|
5544
5675
|
}
|
|
5545
5676
|
}
|
|
5546
5677
|
if (node.defname === 'validUntil') {
|
|
5547
|
-
const quotedValue =
|
|
5548
|
-
? `'${argValue}'`
|
|
5549
|
-
: argValue;
|
|
5678
|
+
const quotedValue = this.quoteDefElemArg(node.arg, argValue);
|
|
5550
5679
|
return `VALID UNTIL ${quotedValue}`;
|
|
5551
5680
|
}
|
|
5552
5681
|
if (node.defname === 'adminmembers') {
|
|
@@ -5585,15 +5714,15 @@ export class Deparser {
|
|
|
5585
5714
|
if (node.arg && this.getNodeType(node.arg) === 'List') {
|
|
5586
5715
|
const listData = this.getNodeData(node.arg);
|
|
5587
5716
|
const listItems = ListUtils.unwrapList(listData.items);
|
|
5717
|
+
if (listItems.length === 1 && listItems[0].String?.sval === 'none') {
|
|
5718
|
+
return 'OWNED BY NONE';
|
|
5719
|
+
}
|
|
5588
5720
|
const parts = listItems.map(item => {
|
|
5589
5721
|
const itemData = this.getNodeData(item);
|
|
5590
5722
|
if (this.getNodeType(item) === 'String') {
|
|
5591
5723
|
// Check if this identifier needs quotes to preserve case
|
|
5592
5724
|
const value = itemData.sval;
|
|
5593
|
-
|
|
5594
|
-
return `"${value}"`;
|
|
5595
|
-
}
|
|
5596
|
-
return value;
|
|
5725
|
+
return QuoteUtils.quoteIdentifier(value);
|
|
5597
5726
|
}
|
|
5598
5727
|
return this.visit(item, context);
|
|
5599
5728
|
});
|
|
@@ -5726,10 +5855,8 @@ export class Deparser {
|
|
|
5726
5855
|
if (context.parentNodeTypes.includes('AlterExtensionStmt')) {
|
|
5727
5856
|
if (node.defname === 'new_version') {
|
|
5728
5857
|
// argValue is unquoted due to DefElem context, so we need to quote it
|
|
5729
|
-
const quotedValue =
|
|
5730
|
-
|
|
5731
|
-
: argValue;
|
|
5732
|
-
return `UPDATE TO ${quotedValue}`;
|
|
5858
|
+
const quotedValue = this.quoteDefElemArg(node.arg, argValue);
|
|
5859
|
+
return `TO ${quotedValue}`;
|
|
5733
5860
|
}
|
|
5734
5861
|
if (node.defname === 'schema') {
|
|
5735
5862
|
return `SET SCHEMA ${argValue}`;
|
|
@@ -5749,28 +5876,37 @@ export class Deparser {
|
|
|
5749
5876
|
if (node.defname === 'cascade') {
|
|
5750
5877
|
return argValue === 'true' ? 'CASCADE' : '';
|
|
5751
5878
|
}
|
|
5879
|
+
if (node.defname === 'new_version') {
|
|
5880
|
+
return `VERSION ${this.quoteDefElemArg(node.arg, argValue)}`;
|
|
5881
|
+
}
|
|
5882
|
+
if (node.defname === 'schema' && node.arg && this.getNodeType(node.arg) === 'String') {
|
|
5883
|
+
return `SCHEMA ${QuoteUtils.quoteIdentifier(this.getNodeData(node.arg).sval)}`;
|
|
5884
|
+
}
|
|
5752
5885
|
return `${node.defname.toUpperCase()} ${argValue}`;
|
|
5753
5886
|
}
|
|
5754
5887
|
// Handle IndexStmt WITH clause options - no quotes, compact formatting
|
|
5755
5888
|
if (context.parentNodeTypes.includes('IndexStmt')) {
|
|
5756
|
-
return `${node.defname}=${argValue}`;
|
|
5889
|
+
return `${QuoteUtils.quoteIdentifierAfterDot(node.defname)}=${this.formatOptionValue(node.arg, argValue)}`;
|
|
5757
5890
|
}
|
|
5758
5891
|
// Handle IndexElem opclassopts - preserve string values as strings
|
|
5759
5892
|
if (context.parentNodeTypes.includes('IndexElem')) {
|
|
5760
5893
|
if (node.arg && this.getNodeType(node.arg) === 'String') {
|
|
5761
5894
|
const stringData = this.getNodeData(node.arg);
|
|
5762
|
-
return `${node.defname}
|
|
5895
|
+
return `${QuoteUtils.quoteIdentifierAfterDot(node.defname)}=${QuoteUtils.escape(stringData.sval)}`;
|
|
5763
5896
|
}
|
|
5764
|
-
return `${node.defname}=${argValue}`;
|
|
5897
|
+
return `${QuoteUtils.quoteIdentifierAfterDot(node.defname)}=${this.formatOptionValue(node.arg, argValue)}`;
|
|
5765
5898
|
}
|
|
5766
5899
|
// Handle CreateStmt table options - no quotes, compact formatting
|
|
5767
5900
|
if (context.parentNodeTypes.includes('CreateStmt')) {
|
|
5901
|
+
const relOptName = node.defnamespace
|
|
5902
|
+
? `${QuoteUtils.quoteIdentifier(node.defnamespace)}.${QuoteUtils.quoteIdentifier(node.defname)}`
|
|
5903
|
+
: QuoteUtils.quoteIdentifier(node.defname);
|
|
5768
5904
|
// For numeric values, use the raw value without quotes
|
|
5769
5905
|
if (node.arg && this.getNodeType(node.arg) === 'Integer') {
|
|
5770
5906
|
const integerData = this.getNodeData(node.arg);
|
|
5771
|
-
return `${
|
|
5907
|
+
return `${relOptName}=${formatInteger(integerData.ival)}`;
|
|
5772
5908
|
}
|
|
5773
|
-
return `${
|
|
5909
|
+
return `${relOptName}=${this.formatOptionValue(node.arg, argValue)}`;
|
|
5774
5910
|
}
|
|
5775
5911
|
// Handle CreateEventTrigStmt WHEN clause - use IN syntax for List arguments
|
|
5776
5912
|
if (context.parentNodeTypes.includes('CreateEventTrigStmt')) {
|
|
@@ -5780,7 +5916,7 @@ export class Deparser {
|
|
|
5780
5916
|
const values = listItems.map(item => {
|
|
5781
5917
|
if (this.getNodeType(item) === 'String') {
|
|
5782
5918
|
const stringData = this.getNodeData(item);
|
|
5783
|
-
return
|
|
5919
|
+
return QuoteUtils.escape(stringData.sval || '');
|
|
5784
5920
|
}
|
|
5785
5921
|
return this.visit(item, context);
|
|
5786
5922
|
});
|
|
@@ -5795,7 +5931,7 @@ export class Deparser {
|
|
|
5795
5931
|
if (node.arg && this.getNodeType(node.arg) === 'TypeName') {
|
|
5796
5932
|
return `${optionName} = ${argValue}`;
|
|
5797
5933
|
}
|
|
5798
|
-
return `${optionName} = ${argValue}`;
|
|
5934
|
+
return `${optionName} = ${this.formatOptionValue(node.arg, argValue)}`;
|
|
5799
5935
|
}
|
|
5800
5936
|
// Handle ViewStmt WITH options - don't quote numeric values
|
|
5801
5937
|
if (context.parentNodeTypes.includes('ViewStmt')) {
|
|
@@ -5809,15 +5945,27 @@ export class Deparser {
|
|
|
5809
5945
|
}
|
|
5810
5946
|
// Handle CopyStmt WITH clause options - uppercase format without quotes
|
|
5811
5947
|
if (context.parentNodeTypes.includes('CopyStmt')) {
|
|
5812
|
-
|
|
5813
|
-
|
|
5814
|
-
return
|
|
5948
|
+
const optName = node.defname.toUpperCase();
|
|
5949
|
+
if (!node.arg) {
|
|
5950
|
+
return optName;
|
|
5815
5951
|
}
|
|
5816
|
-
|
|
5817
|
-
if (node.arg) {
|
|
5818
|
-
return
|
|
5952
|
+
const copyArgType = this.getNodeType(node.arg);
|
|
5953
|
+
if (copyArgType === 'Boolean' && this.getNodeData(node.arg).boolval !== false) {
|
|
5954
|
+
return optName;
|
|
5819
5955
|
}
|
|
5820
|
-
|
|
5956
|
+
if (copyArgType === 'List') {
|
|
5957
|
+
const items = ListUtils.unwrapList(this.getNodeData(node.arg).items)
|
|
5958
|
+
.map(item => this.visit(item, context));
|
|
5959
|
+
return `${optName} (${items.join(', ')})`;
|
|
5960
|
+
}
|
|
5961
|
+
if (copyArgType === 'String') {
|
|
5962
|
+
const sval = this.getNodeData(node.arg).sval;
|
|
5963
|
+
if (node.defname === 'format') {
|
|
5964
|
+
return `${optName} ${sval}`;
|
|
5965
|
+
}
|
|
5966
|
+
return `${optName} ${QuoteUtils.escape(sval)}`;
|
|
5967
|
+
}
|
|
5968
|
+
return `${optName} ${argValue}`;
|
|
5821
5969
|
}
|
|
5822
5970
|
// Handle CREATE OPERATOR and CREATE TYPE context
|
|
5823
5971
|
if (context.parentNodeTypes.includes('DefineStmt')) {
|
|
@@ -5841,13 +5989,13 @@ export class Deparser {
|
|
|
5841
5989
|
// Handle boolean flags (no arguments) - preserve quoted case
|
|
5842
5990
|
if (['hashes', 'merges'].includes(node.defname.toLowerCase())) {
|
|
5843
5991
|
if (node.defname !== node.defname.toLowerCase() && node.defname !== node.defname.toUpperCase()) {
|
|
5844
|
-
return
|
|
5992
|
+
return QuoteUtils.quoteIdentifier(node.defname);
|
|
5845
5993
|
}
|
|
5846
5994
|
return preservedName.toUpperCase();
|
|
5847
5995
|
}
|
|
5848
5996
|
// Handle CREATE AGGREGATE quoted identifiers - preserve quotes when needed
|
|
5849
|
-
|
|
5850
|
-
|
|
5997
|
+
const quotedDefname = QuoteUtils.quoteIdentifier(node.defname);
|
|
5998
|
+
if (quotedDefname !== node.defname) {
|
|
5851
5999
|
if (node.arg) {
|
|
5852
6000
|
if (this.getNodeType(node.arg) === 'String') {
|
|
5853
6001
|
const stringData = this.getNodeData(node.arg);
|
|
@@ -5856,7 +6004,7 @@ export class Deparser {
|
|
|
5856
6004
|
return `${quotedDefname} = ${stringData.sval}`;
|
|
5857
6005
|
}
|
|
5858
6006
|
// Regular string literals get single quotes
|
|
5859
|
-
return `${quotedDefname} =
|
|
6007
|
+
return `${quotedDefname} = ${QuoteUtils.escape(stringData.sval)}`;
|
|
5860
6008
|
}
|
|
5861
6009
|
return `${quotedDefname} = ${argValue}`;
|
|
5862
6010
|
}
|
|
@@ -5877,7 +6025,7 @@ export class Deparser {
|
|
|
5877
6025
|
return `${node.defname} = ${stringData.sval}`;
|
|
5878
6026
|
}
|
|
5879
6027
|
// Regular string literals get single quotes
|
|
5880
|
-
return `${node.defname} =
|
|
6028
|
+
return `${node.defname} = ${QuoteUtils.escape(stringData.sval)}`;
|
|
5881
6029
|
}
|
|
5882
6030
|
if (node.arg && this.getNodeType(node.arg) === 'Boolean') {
|
|
5883
6031
|
const boolData = this.getNodeData(node.arg);
|
|
@@ -5898,6 +6046,10 @@ export class Deparser {
|
|
|
5898
6046
|
return `${node.defname} = ${argValue}`;
|
|
5899
6047
|
}
|
|
5900
6048
|
}
|
|
6049
|
+
const argType = this.getNodeType(node.arg);
|
|
6050
|
+
if (argType === 'TypeName' || argType === 'Integer' || argType === 'Float' || argType === 'Boolean') {
|
|
6051
|
+
return `${node.defname} = ${argValue}`;
|
|
6052
|
+
}
|
|
5901
6053
|
const quotedValue = typeof argValue === 'string'
|
|
5902
6054
|
? QuoteUtils.escape(argValue)
|
|
5903
6055
|
: argValue;
|
|
@@ -5907,7 +6059,7 @@ export class Deparser {
|
|
|
5907
6059
|
if (context.parentNodeTypes.includes('DefineStmt') && !node.arg) {
|
|
5908
6060
|
// Check if the original defname appears to be quoted (mixed case that's not all upper/lower)
|
|
5909
6061
|
if (node.defname !== node.defname.toLowerCase() && node.defname !== node.defname.toUpperCase()) {
|
|
5910
|
-
return
|
|
6062
|
+
return QuoteUtils.quoteIdentifier(node.defname);
|
|
5911
6063
|
}
|
|
5912
6064
|
}
|
|
5913
6065
|
return node.defname.toUpperCase();
|
|
@@ -5923,7 +6075,7 @@ export class Deparser {
|
|
|
5923
6075
|
}
|
|
5924
6076
|
if (node.location) {
|
|
5925
6077
|
output.push('LOCATION');
|
|
5926
|
-
output.push(
|
|
6078
|
+
output.push(QuoteUtils.escape(node.location));
|
|
5927
6079
|
}
|
|
5928
6080
|
if (node.options && node.options.length > 0) {
|
|
5929
6081
|
output.push('WITH');
|
|
@@ -5987,6 +6139,7 @@ export class Deparser {
|
|
|
5987
6139
|
if (node.extname) {
|
|
5988
6140
|
output.push(this.quoteIfNeeded(node.extname));
|
|
5989
6141
|
}
|
|
6142
|
+
output.push('UPDATE');
|
|
5990
6143
|
if (node.options && node.options.length > 0) {
|
|
5991
6144
|
const extContext = context.spawn('AlterExtensionStmt');
|
|
5992
6145
|
const options = ListUtils.unwrapList(node.options)
|
|
@@ -6091,7 +6244,7 @@ export class Deparser {
|
|
|
6091
6244
|
case 'REPLICA_IDENTITY_INDEX':
|
|
6092
6245
|
output.push('USING', 'INDEX');
|
|
6093
6246
|
if (node.name) {
|
|
6094
|
-
output.push(QuoteUtils.
|
|
6247
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
6095
6248
|
}
|
|
6096
6249
|
break;
|
|
6097
6250
|
default:
|
|
@@ -6150,7 +6303,7 @@ export class Deparser {
|
|
|
6150
6303
|
output.push('IF', 'EXISTS');
|
|
6151
6304
|
}
|
|
6152
6305
|
if (node.name) {
|
|
6153
|
-
output.push(QuoteUtils.
|
|
6306
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
6154
6307
|
}
|
|
6155
6308
|
if (node.behavior === 'DROP_CASCADE') {
|
|
6156
6309
|
output.push('CASCADE');
|
|
@@ -6159,7 +6312,7 @@ export class Deparser {
|
|
|
6159
6312
|
case 'AT_ValidateConstraint':
|
|
6160
6313
|
output.push('VALIDATE', 'CONSTRAINT');
|
|
6161
6314
|
if (node.name) {
|
|
6162
|
-
output.push(QuoteUtils.
|
|
6315
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
6163
6316
|
}
|
|
6164
6317
|
break;
|
|
6165
6318
|
case 'C':
|
|
@@ -6176,7 +6329,7 @@ export class Deparser {
|
|
|
6176
6329
|
output.push('IF', 'EXISTS');
|
|
6177
6330
|
}
|
|
6178
6331
|
if (node.name) {
|
|
6179
|
-
output.push(QuoteUtils.
|
|
6332
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
6180
6333
|
}
|
|
6181
6334
|
if (node.behavior === 'DROP_CASCADE') {
|
|
6182
6335
|
output.push('CASCADE');
|
|
@@ -6185,7 +6338,7 @@ export class Deparser {
|
|
|
6185
6338
|
case 'V':
|
|
6186
6339
|
output.push('VALIDATE', 'CONSTRAINT');
|
|
6187
6340
|
if (node.name) {
|
|
6188
|
-
output.push(QuoteUtils.
|
|
6341
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
6189
6342
|
}
|
|
6190
6343
|
break;
|
|
6191
6344
|
case 'O':
|
|
@@ -6256,7 +6409,7 @@ export class Deparser {
|
|
|
6256
6409
|
}
|
|
6257
6410
|
if (node.payload !== null && node.payload !== undefined) {
|
|
6258
6411
|
output.push(',');
|
|
6259
|
-
output.push(
|
|
6412
|
+
output.push(QuoteUtils.escape(node.payload));
|
|
6260
6413
|
}
|
|
6261
6414
|
return output.join(' ');
|
|
6262
6415
|
}
|
|
@@ -6284,7 +6437,7 @@ export class Deparser {
|
|
|
6284
6437
|
if (!node.filename) {
|
|
6285
6438
|
throw new Error('LoadStmt requires filename');
|
|
6286
6439
|
}
|
|
6287
|
-
return `LOAD
|
|
6440
|
+
return `LOAD ${QuoteUtils.escape(node.filename)}`;
|
|
6288
6441
|
}
|
|
6289
6442
|
DiscardStmt(node, context) {
|
|
6290
6443
|
switch (node.target) {
|
|
@@ -6300,6 +6453,13 @@ export class Deparser {
|
|
|
6300
6453
|
throw new Error(`Unsupported DiscardStmt target: ${node.target}`);
|
|
6301
6454
|
}
|
|
6302
6455
|
}
|
|
6456
|
+
/** `schema.op` for an operator name list: schema parts quoted, the operator symbol as is. */
|
|
6457
|
+
qualifiedOperatorName(objname) {
|
|
6458
|
+
const names = ListUtils.unwrapList(objname ?? []).map((n) => (n.String ? n.String.sval : 'unknown'));
|
|
6459
|
+
if (names.length === 0)
|
|
6460
|
+
return 'unknown';
|
|
6461
|
+
return [...names.slice(0, -1).map((n) => QuoteUtils.quoteIdentifier(n)), names[names.length - 1]].join('.');
|
|
6462
|
+
}
|
|
6303
6463
|
CommentStmt(node, context) {
|
|
6304
6464
|
const output = ['COMMENT ON'];
|
|
6305
6465
|
if (node.objtype) {
|
|
@@ -6331,6 +6491,9 @@ export class Deparser {
|
|
|
6331
6491
|
case 'OBJECT_TABCONSTRAINT':
|
|
6332
6492
|
output.push('CONSTRAINT');
|
|
6333
6493
|
break;
|
|
6494
|
+
case 'OBJECT_DOMCONSTRAINT':
|
|
6495
|
+
output.push('CONSTRAINT');
|
|
6496
|
+
break;
|
|
6334
6497
|
case 'OBJECT_TRIGGER':
|
|
6335
6498
|
output.push('TRIGGER');
|
|
6336
6499
|
break;
|
|
@@ -6407,23 +6570,30 @@ export class Deparser {
|
|
|
6407
6570
|
output.push(objectParts.join('.'));
|
|
6408
6571
|
}
|
|
6409
6572
|
}
|
|
6410
|
-
else if (node.objtype === '
|
|
6573
|
+
else if (node.objtype === 'OBJECT_DOMCONSTRAINT') {
|
|
6411
6574
|
if (objectParts.length === 2) {
|
|
6412
|
-
const [
|
|
6413
|
-
output.push(
|
|
6575
|
+
const [domain, constraint] = objectParts;
|
|
6576
|
+
output.push(constraint, 'ON DOMAIN', domain);
|
|
6577
|
+
}
|
|
6578
|
+
else {
|
|
6579
|
+
output.push(objectParts.join('.'));
|
|
6580
|
+
}
|
|
6581
|
+
}
|
|
6582
|
+
else if (node.objtype === 'OBJECT_TRIGGER') {
|
|
6583
|
+
if (objectParts.length >= 2) {
|
|
6584
|
+
output.push(objectParts[objectParts.length - 1]);
|
|
6414
6585
|
output.push('ON');
|
|
6415
|
-
output.push(
|
|
6586
|
+
output.push(objectParts.slice(0, -1).join('.'));
|
|
6416
6587
|
}
|
|
6417
6588
|
else {
|
|
6418
6589
|
output.push(objectParts.join('.'));
|
|
6419
6590
|
}
|
|
6420
6591
|
}
|
|
6421
6592
|
else if (node.objtype === 'OBJECT_RULE') {
|
|
6422
|
-
if (objectParts.length
|
|
6423
|
-
|
|
6424
|
-
output.push(rule);
|
|
6593
|
+
if (objectParts.length >= 2) {
|
|
6594
|
+
output.push(objectParts[objectParts.length - 1]);
|
|
6425
6595
|
output.push('ON');
|
|
6426
|
-
output.push(
|
|
6596
|
+
output.push(objectParts.slice(0, -1).join('.'));
|
|
6427
6597
|
}
|
|
6428
6598
|
else {
|
|
6429
6599
|
output.push(objectParts.join('.'));
|
|
@@ -6434,8 +6604,7 @@ export class Deparser {
|
|
|
6434
6604
|
// For operators, we need to handle ObjectWithArgs structure
|
|
6435
6605
|
if (node.object && node.object.ObjectWithArgs) {
|
|
6436
6606
|
const objWithArgs = node.object.ObjectWithArgs;
|
|
6437
|
-
let operatorName =
|
|
6438
|
-
? objWithArgs.objname[0].String.sval : 'unknown';
|
|
6607
|
+
let operatorName = this.qualifiedOperatorName(objWithArgs.objname);
|
|
6439
6608
|
if (operatorName.startsWith('"') && operatorName.endsWith('"')) {
|
|
6440
6609
|
operatorName = operatorName.slice(1, -1);
|
|
6441
6610
|
}
|
|
@@ -6473,7 +6642,13 @@ export class Deparser {
|
|
|
6473
6642
|
}
|
|
6474
6643
|
else if (node.objtype === 'OBJECT_POLICY') {
|
|
6475
6644
|
// Handle POLICY syntax: COMMENT ON POLICY policy_name ON table_name IS 'comment'
|
|
6476
|
-
if (objectParts.length ===
|
|
6645
|
+
if (objectParts.length === 3) {
|
|
6646
|
+
const [schema, table, policy] = objectParts;
|
|
6647
|
+
output.push(policy);
|
|
6648
|
+
output.push('ON');
|
|
6649
|
+
output.push(`${schema}.${table}`);
|
|
6650
|
+
}
|
|
6651
|
+
else if (objectParts.length === 2) {
|
|
6477
6652
|
const [table, policy] = objectParts;
|
|
6478
6653
|
output.push(policy);
|
|
6479
6654
|
output.push('ON');
|
|
@@ -6496,6 +6671,9 @@ export class Deparser {
|
|
|
6496
6671
|
output.push(objectParts.join('.'));
|
|
6497
6672
|
}
|
|
6498
6673
|
}
|
|
6674
|
+
else if (node.objtype === 'OBJECT_CAST' && objectParts.length === 2) {
|
|
6675
|
+
output.push(`(${objectParts[0]} AS ${objectParts[1]})`);
|
|
6676
|
+
}
|
|
6499
6677
|
else {
|
|
6500
6678
|
output.push(objectParts.join('.'));
|
|
6501
6679
|
}
|
|
@@ -6504,8 +6682,7 @@ export class Deparser {
|
|
|
6504
6682
|
else if (node.objtype === 'OBJECT_OPERATOR' && node.object && node.object.ObjectWithArgs) {
|
|
6505
6683
|
// Handle direct ObjectWithArgs for OPERATOR syntax: COMMENT ON OPERATOR -(NONE, integer) IS 'comment'
|
|
6506
6684
|
const objWithArgs = node.object.ObjectWithArgs;
|
|
6507
|
-
let operatorName =
|
|
6508
|
-
? objWithArgs.objname[0].String.sval : 'unknown';
|
|
6685
|
+
let operatorName = this.qualifiedOperatorName(objWithArgs.objname);
|
|
6509
6686
|
// Remove quotes from operator name if present
|
|
6510
6687
|
if (operatorName.startsWith('"') && operatorName.endsWith('"')) {
|
|
6511
6688
|
operatorName = operatorName.slice(1, -1);
|
|
@@ -6574,7 +6751,7 @@ export class Deparser {
|
|
|
6574
6751
|
const output = [];
|
|
6575
6752
|
const initialParts = ['CREATE', 'POLICY'];
|
|
6576
6753
|
if (node.policy_name) {
|
|
6577
|
-
initialParts.push(QuoteUtils.
|
|
6754
|
+
initialParts.push(QuoteUtils.quoteIdentifier(node.policy_name));
|
|
6578
6755
|
}
|
|
6579
6756
|
output.push(initialParts.join(' '));
|
|
6580
6757
|
// Add ON clause on new line in pretty mode
|
|
@@ -6651,7 +6828,7 @@ export class Deparser {
|
|
|
6651
6828
|
AlterPolicyStmt(node, context) {
|
|
6652
6829
|
const output = ['ALTER', 'POLICY'];
|
|
6653
6830
|
if (node.policy_name) {
|
|
6654
|
-
output.push(QuoteUtils.
|
|
6831
|
+
output.push(QuoteUtils.quoteIdentifier(node.policy_name));
|
|
6655
6832
|
}
|
|
6656
6833
|
if (node.table) {
|
|
6657
6834
|
output.push('ON');
|
|
@@ -6687,7 +6864,7 @@ export class Deparser {
|
|
|
6687
6864
|
}
|
|
6688
6865
|
output.push('SERVER');
|
|
6689
6866
|
if (node.servername) {
|
|
6690
|
-
output.push(
|
|
6867
|
+
output.push(QuoteUtils.quoteIdentifier(node.servername));
|
|
6691
6868
|
}
|
|
6692
6869
|
if (node.options && node.options.length > 0) {
|
|
6693
6870
|
output.push('OPTIONS');
|
|
@@ -6735,10 +6912,10 @@ export class Deparser {
|
|
|
6735
6912
|
CreatePublicationStmt(node, context) {
|
|
6736
6913
|
const output = ['CREATE', 'PUBLICATION'];
|
|
6737
6914
|
if (node.pubname) {
|
|
6738
|
-
output.push(
|
|
6915
|
+
output.push(QuoteUtils.quoteIdentifier(node.pubname));
|
|
6739
6916
|
}
|
|
6740
6917
|
if (node.pubobjects && node.pubobjects.length > 0) {
|
|
6741
|
-
output.push('FOR'
|
|
6918
|
+
output.push('FOR');
|
|
6742
6919
|
const tables = ListUtils.unwrapList(node.pubobjects).map(table => this.visit(table, context));
|
|
6743
6920
|
output.push(tables.join(', '));
|
|
6744
6921
|
}
|
|
@@ -6755,11 +6932,11 @@ export class Deparser {
|
|
|
6755
6932
|
CreateSubscriptionStmt(node, context) {
|
|
6756
6933
|
const output = ['CREATE', 'SUBSCRIPTION'];
|
|
6757
6934
|
if (node.subname) {
|
|
6758
|
-
output.push(
|
|
6935
|
+
output.push(QuoteUtils.quoteIdentifier(node.subname));
|
|
6759
6936
|
}
|
|
6760
6937
|
output.push('CONNECTION');
|
|
6761
6938
|
if (node.conninfo) {
|
|
6762
|
-
output.push(
|
|
6939
|
+
output.push(QuoteUtils.escape(node.conninfo));
|
|
6763
6940
|
}
|
|
6764
6941
|
output.push('PUBLICATION');
|
|
6765
6942
|
if (node.publication && node.publication.length > 0) {
|
|
@@ -6776,10 +6953,11 @@ export class Deparser {
|
|
|
6776
6953
|
AlterPublicationStmt(node, context) {
|
|
6777
6954
|
const output = ['ALTER', 'PUBLICATION'];
|
|
6778
6955
|
if (node.pubname) {
|
|
6779
|
-
output.push(
|
|
6956
|
+
output.push(QuoteUtils.quoteIdentifier(node.pubname));
|
|
6780
6957
|
}
|
|
6781
|
-
|
|
6782
|
-
|
|
6958
|
+
const hasObjects = node.pubobjects && node.pubobjects.length > 0;
|
|
6959
|
+
if (hasObjects) {
|
|
6960
|
+
switch (node.action || 'AP_AddObjects') {
|
|
6783
6961
|
case 'AP_AddObjects':
|
|
6784
6962
|
output.push('ADD');
|
|
6785
6963
|
break;
|
|
@@ -6792,17 +6970,11 @@ export class Deparser {
|
|
|
6792
6970
|
default:
|
|
6793
6971
|
throw new Error(`Unsupported AlterPublicationStmt action: ${node.action}`);
|
|
6794
6972
|
}
|
|
6795
|
-
}
|
|
6796
|
-
if (node.for_all_tables) {
|
|
6797
|
-
output.push('FOR ALL TABLES');
|
|
6798
|
-
}
|
|
6799
|
-
else if (node.pubobjects && node.pubobjects.length > 0) {
|
|
6800
|
-
output.push('FOR TABLE');
|
|
6801
6973
|
const objects = ListUtils.unwrapList(node.pubobjects).map(obj => this.visit(obj, context));
|
|
6802
6974
|
output.push(objects.join(', '));
|
|
6803
6975
|
}
|
|
6804
|
-
if (node.options && node.options.length > 0) {
|
|
6805
|
-
output.push('
|
|
6976
|
+
else if (node.options && node.options.length > 0) {
|
|
6977
|
+
output.push('SET');
|
|
6806
6978
|
const options = ListUtils.unwrapList(node.options).map(opt => this.visit(opt, context));
|
|
6807
6979
|
output.push(`(${options.join(', ')})`);
|
|
6808
6980
|
}
|
|
@@ -6811,44 +6983,69 @@ export class Deparser {
|
|
|
6811
6983
|
AlterSubscriptionStmt(node, context) {
|
|
6812
6984
|
const output = ['ALTER', 'SUBSCRIPTION'];
|
|
6813
6985
|
if (node.subname) {
|
|
6814
|
-
output.push(
|
|
6815
|
-
}
|
|
6816
|
-
|
|
6817
|
-
|
|
6986
|
+
output.push(QuoteUtils.quoteIdentifier(node.subname));
|
|
6987
|
+
}
|
|
6988
|
+
const options = node.options && node.options.length > 0
|
|
6989
|
+
? `(${ListUtils.unwrapList(node.options).map(opt => this.visit(opt, context)).join(', ')})`
|
|
6990
|
+
: null;
|
|
6991
|
+
const publications = node.publication && node.publication.length > 0
|
|
6992
|
+
? ListUtils.unwrapList(node.publication).map(pub => this.visit(pub, context)).join(', ')
|
|
6993
|
+
: null;
|
|
6994
|
+
{
|
|
6995
|
+
switch (node.kind || 'ALTER_SUBSCRIPTION_OPTIONS') {
|
|
6818
6996
|
case 'ALTER_SUBSCRIPTION_OPTIONS':
|
|
6819
6997
|
output.push('SET');
|
|
6998
|
+
if (options)
|
|
6999
|
+
output.push(options);
|
|
6820
7000
|
break;
|
|
6821
7001
|
case 'ALTER_SUBSCRIPTION_CONNECTION':
|
|
6822
7002
|
output.push('CONNECTION');
|
|
6823
7003
|
if (node.conninfo) {
|
|
6824
|
-
output.push(
|
|
7004
|
+
output.push(QuoteUtils.escape(node.conninfo));
|
|
6825
7005
|
}
|
|
6826
7006
|
break;
|
|
6827
7007
|
case 'ALTER_SUBSCRIPTION_SET_PUBLICATION':
|
|
6828
7008
|
output.push('SET PUBLICATION');
|
|
6829
|
-
if (
|
|
6830
|
-
|
|
6831
|
-
|
|
6832
|
-
|
|
7009
|
+
if (publications)
|
|
7010
|
+
output.push(publications);
|
|
7011
|
+
if (options)
|
|
7012
|
+
output.push('WITH', options);
|
|
7013
|
+
break;
|
|
7014
|
+
case 'ALTER_SUBSCRIPTION_ADD_PUBLICATION':
|
|
7015
|
+
output.push('ADD PUBLICATION');
|
|
7016
|
+
if (publications)
|
|
7017
|
+
output.push(publications);
|
|
7018
|
+
if (options)
|
|
7019
|
+
output.push('WITH', options);
|
|
7020
|
+
break;
|
|
7021
|
+
case 'ALTER_SUBSCRIPTION_DROP_PUBLICATION':
|
|
7022
|
+
output.push('DROP PUBLICATION');
|
|
7023
|
+
if (publications)
|
|
7024
|
+
output.push(publications);
|
|
7025
|
+
if (options)
|
|
7026
|
+
output.push('WITH', options);
|
|
6833
7027
|
break;
|
|
6834
7028
|
case 'ALTER_SUBSCRIPTION_REFRESH':
|
|
6835
7029
|
output.push('REFRESH PUBLICATION');
|
|
7030
|
+
if (options)
|
|
7031
|
+
output.push('WITH', options);
|
|
6836
7032
|
break;
|
|
6837
|
-
case 'ALTER_SUBSCRIPTION_ENABLED':
|
|
6838
|
-
|
|
7033
|
+
case 'ALTER_SUBSCRIPTION_ENABLED': {
|
|
7034
|
+
const enabled = ListUtils.unwrapList(node.options).find(opt => opt.DefElem?.defname === 'enabled');
|
|
7035
|
+
const arg = enabled?.DefElem?.arg;
|
|
7036
|
+
const isEnabled = arg?.Boolean ? arg.Boolean.boolval !== false : true;
|
|
7037
|
+
output.push(isEnabled ? 'ENABLE' : 'DISABLE');
|
|
6839
7038
|
break;
|
|
7039
|
+
}
|
|
6840
7040
|
case 'ALTER_SUBSCRIPTION_SKIP':
|
|
6841
7041
|
output.push('SKIP');
|
|
7042
|
+
if (options)
|
|
7043
|
+
output.push(options);
|
|
6842
7044
|
break;
|
|
6843
7045
|
default:
|
|
6844
7046
|
throw new Error(`Unsupported AlterSubscriptionStmt kind: ${node.kind}`);
|
|
6845
7047
|
}
|
|
6846
7048
|
}
|
|
6847
|
-
if (node.options && node.options.length > 0) {
|
|
6848
|
-
output.push('WITH');
|
|
6849
|
-
const options = ListUtils.unwrapList(node.options).map(opt => this.visit(opt, context));
|
|
6850
|
-
output.push(`(${options.join(', ')})`);
|
|
6851
|
-
}
|
|
6852
7049
|
return output.join(' ');
|
|
6853
7050
|
}
|
|
6854
7051
|
DropSubscriptionStmt(node, context) {
|
|
@@ -6857,7 +7054,7 @@ export class Deparser {
|
|
|
6857
7054
|
output.push('IF EXISTS');
|
|
6858
7055
|
}
|
|
6859
7056
|
if (node.subname) {
|
|
6860
|
-
output.push(
|
|
7057
|
+
output.push(QuoteUtils.quoteIdentifier(node.subname));
|
|
6861
7058
|
}
|
|
6862
7059
|
if (node.behavior) {
|
|
6863
7060
|
switch (node.behavior) {
|
|
@@ -7102,7 +7299,7 @@ export class Deparser {
|
|
|
7102
7299
|
ClosePortalStmt(node, context) {
|
|
7103
7300
|
const output = ['CLOSE'];
|
|
7104
7301
|
if (node.portalname) {
|
|
7105
|
-
output.push(QuoteUtils.
|
|
7302
|
+
output.push(QuoteUtils.quoteIdentifier(node.portalname));
|
|
7106
7303
|
}
|
|
7107
7304
|
else {
|
|
7108
7305
|
output.push('ALL');
|
|
@@ -7160,7 +7357,7 @@ export class Deparser {
|
|
|
7160
7357
|
output.push('ALL');
|
|
7161
7358
|
}
|
|
7162
7359
|
if (node.portalname) {
|
|
7163
|
-
output.push(QuoteUtils.
|
|
7360
|
+
output.push(QuoteUtils.quoteIdentifier(node.portalname));
|
|
7164
7361
|
}
|
|
7165
7362
|
return output.join(' ');
|
|
7166
7363
|
}
|
|
@@ -7230,7 +7427,7 @@ export class Deparser {
|
|
|
7230
7427
|
AlterFdwStmt(node, context) {
|
|
7231
7428
|
const output = ['ALTER', 'FOREIGN', 'DATA', 'WRAPPER'];
|
|
7232
7429
|
if (node.fdwname) {
|
|
7233
|
-
output.push(QuoteUtils.
|
|
7430
|
+
output.push(QuoteUtils.quoteIdentifier(node.fdwname));
|
|
7234
7431
|
}
|
|
7235
7432
|
if (node.func_options && node.func_options.length > 0) {
|
|
7236
7433
|
const fdwContext = context.spawn('AlterFdwStmt');
|
|
@@ -7251,7 +7448,7 @@ export class Deparser {
|
|
|
7251
7448
|
output.push('IF', 'NOT', 'EXISTS');
|
|
7252
7449
|
}
|
|
7253
7450
|
if (node.servername) {
|
|
7254
|
-
output.push(QuoteUtils.
|
|
7451
|
+
output.push(QuoteUtils.quoteIdentifier(node.servername));
|
|
7255
7452
|
}
|
|
7256
7453
|
if (node.servertype) {
|
|
7257
7454
|
output.push('TYPE', QuoteUtils.escape(node.servertype));
|
|
@@ -7260,7 +7457,7 @@ export class Deparser {
|
|
|
7260
7457
|
output.push('VERSION', QuoteUtils.escape(node.version));
|
|
7261
7458
|
}
|
|
7262
7459
|
if (node.fdwname) {
|
|
7263
|
-
output.push('FOREIGN', 'DATA', 'WRAPPER', QuoteUtils.
|
|
7460
|
+
output.push('FOREIGN', 'DATA', 'WRAPPER', QuoteUtils.quoteIdentifier(node.fdwname));
|
|
7264
7461
|
}
|
|
7265
7462
|
if (node.options && node.options.length > 0) {
|
|
7266
7463
|
output.push('OPTIONS');
|
|
@@ -7275,7 +7472,7 @@ export class Deparser {
|
|
|
7275
7472
|
AlterForeignServerStmt(node, context) {
|
|
7276
7473
|
const output = ['ALTER', 'SERVER'];
|
|
7277
7474
|
if (node.servername) {
|
|
7278
|
-
output.push(QuoteUtils.
|
|
7475
|
+
output.push(QuoteUtils.quoteIdentifier(node.servername));
|
|
7279
7476
|
}
|
|
7280
7477
|
if (node.version) {
|
|
7281
7478
|
output.push('VERSION', QuoteUtils.escape(node.version));
|
|
@@ -7300,7 +7497,7 @@ export class Deparser {
|
|
|
7300
7497
|
}
|
|
7301
7498
|
output.push('SERVER');
|
|
7302
7499
|
if (node.servername) {
|
|
7303
|
-
output.push(QuoteUtils.
|
|
7500
|
+
output.push(QuoteUtils.quoteIdentifier(node.servername));
|
|
7304
7501
|
}
|
|
7305
7502
|
if (node.options && node.options.length > 0) {
|
|
7306
7503
|
output.push('OPTIONS');
|
|
@@ -7324,14 +7521,14 @@ export class Deparser {
|
|
|
7324
7521
|
}
|
|
7325
7522
|
output.push('SERVER');
|
|
7326
7523
|
if (node.servername) {
|
|
7327
|
-
output.push(QuoteUtils.
|
|
7524
|
+
output.push(QuoteUtils.quoteIdentifier(node.servername));
|
|
7328
7525
|
}
|
|
7329
7526
|
return output.join(' ');
|
|
7330
7527
|
}
|
|
7331
7528
|
ImportForeignSchemaStmt(node, context) {
|
|
7332
7529
|
const output = ['IMPORT', 'FOREIGN', 'SCHEMA'];
|
|
7333
7530
|
if (node.remote_schema) {
|
|
7334
|
-
output.push(QuoteUtils.
|
|
7531
|
+
output.push(QuoteUtils.quoteIdentifier(node.remote_schema));
|
|
7335
7532
|
}
|
|
7336
7533
|
if (node.list_type) {
|
|
7337
7534
|
switch (node.list_type) {
|
|
@@ -7357,11 +7554,11 @@ export class Deparser {
|
|
|
7357
7554
|
}
|
|
7358
7555
|
output.push('FROM', 'SERVER');
|
|
7359
7556
|
if (node.server_name) {
|
|
7360
|
-
output.push(QuoteUtils.
|
|
7557
|
+
output.push(QuoteUtils.quoteIdentifier(node.server_name));
|
|
7361
7558
|
}
|
|
7362
7559
|
output.push('INTO');
|
|
7363
7560
|
if (node.local_schema) {
|
|
7364
|
-
output.push(QuoteUtils.
|
|
7561
|
+
output.push(QuoteUtils.quoteIdentifier(node.local_schema));
|
|
7365
7562
|
}
|
|
7366
7563
|
if (node.options && node.options.length > 0) {
|
|
7367
7564
|
const importSchemaContext = context.spawn('ImportForeignSchemaStmt');
|
|
@@ -7375,7 +7572,7 @@ export class Deparser {
|
|
|
7375
7572
|
if (node.relation) {
|
|
7376
7573
|
output.push(this.RangeVar(node.relation, context));
|
|
7377
7574
|
if (node.indexname) {
|
|
7378
|
-
output.push('USING',
|
|
7575
|
+
output.push('USING', QuoteUtils.quoteIdentifier(node.indexname));
|
|
7379
7576
|
}
|
|
7380
7577
|
}
|
|
7381
7578
|
if (node.params && node.params.length > 0) {
|
|
@@ -7439,7 +7636,7 @@ export class Deparser {
|
|
|
7439
7636
|
output.push(this.RangeVar(node.relation, context));
|
|
7440
7637
|
}
|
|
7441
7638
|
if (node.name) {
|
|
7442
|
-
output.push(
|
|
7639
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
7443
7640
|
}
|
|
7444
7641
|
return output.join(' ');
|
|
7445
7642
|
}
|
|
@@ -7479,7 +7676,7 @@ export class Deparser {
|
|
|
7479
7676
|
if (!node.dbname) {
|
|
7480
7677
|
throw new Error('CreatedbStmt requires dbname');
|
|
7481
7678
|
}
|
|
7482
|
-
output.push(
|
|
7679
|
+
output.push(QuoteUtils.quoteIdentifier(node.dbname));
|
|
7483
7680
|
if (node.options && node.options.length > 0) {
|
|
7484
7681
|
const options = ListUtils.unwrapList(node.options)
|
|
7485
7682
|
.map(option => this.visit(option, context))
|
|
@@ -7496,7 +7693,7 @@ export class Deparser {
|
|
|
7496
7693
|
if (!node.dbname) {
|
|
7497
7694
|
throw new Error('DropdbStmt requires dbname');
|
|
7498
7695
|
}
|
|
7499
|
-
output.push(
|
|
7696
|
+
output.push(QuoteUtils.quoteIdentifier(node.dbname));
|
|
7500
7697
|
if (node.options && node.options.length > 0) {
|
|
7501
7698
|
const options = ListUtils.unwrapList(node.options)
|
|
7502
7699
|
.map(option => this.visit(option, context))
|
|
@@ -7594,7 +7791,7 @@ export class Deparser {
|
|
|
7594
7791
|
case 'OBJECT_POLICY':
|
|
7595
7792
|
output.push('POLICY');
|
|
7596
7793
|
if (node.subname) {
|
|
7597
|
-
output.push(QuoteUtils.
|
|
7794
|
+
output.push(QuoteUtils.quoteIdentifier(node.subname));
|
|
7598
7795
|
}
|
|
7599
7796
|
break;
|
|
7600
7797
|
case 'OBJECT_PUBLICATION':
|
|
@@ -7652,7 +7849,7 @@ export class Deparser {
|
|
|
7652
7849
|
}
|
|
7653
7850
|
// Handle OBJECT_RULE special case: rule_name ON table_name format
|
|
7654
7851
|
if (node.renameType === 'OBJECT_RULE' && node.subname && node.relation) {
|
|
7655
|
-
output.push(QuoteUtils.
|
|
7852
|
+
output.push(QuoteUtils.quoteIdentifier(node.subname));
|
|
7656
7853
|
output.push('ON');
|
|
7657
7854
|
output.push(this.RangeVar(node.relation, context));
|
|
7658
7855
|
}
|
|
@@ -7671,12 +7868,21 @@ export class Deparser {
|
|
|
7671
7868
|
if (items.length === 2) {
|
|
7672
7869
|
const accessMethod = items[0].String?.sval || '';
|
|
7673
7870
|
const objectName = items[1].String?.sval || '';
|
|
7674
|
-
output.push(`${QuoteUtils.
|
|
7871
|
+
output.push(`${QuoteUtils.quoteIdentifier(objectName)} USING ${accessMethod}`);
|
|
7675
7872
|
}
|
|
7676
7873
|
else {
|
|
7677
7874
|
output.push(this.visit(node.object, context));
|
|
7678
7875
|
}
|
|
7679
7876
|
}
|
|
7877
|
+
else if ((node.renameType === 'OBJECT_TYPE' || node.renameType === 'OBJECT_DOMAIN') && node.object.List) {
|
|
7878
|
+
// Qualified type names - join List parts with dots
|
|
7879
|
+
const items = ListUtils.unwrapList(node.object);
|
|
7880
|
+
const parts = items
|
|
7881
|
+
.map((item) => item.String?.sval)
|
|
7882
|
+
.filter((s) => typeof s === 'string')
|
|
7883
|
+
.map((s) => this.quoteIfNeeded(s));
|
|
7884
|
+
output.push(parts.join('.'));
|
|
7885
|
+
}
|
|
7680
7886
|
else if (node.renameType === 'OBJECT_SCHEMA' && node.object.List) {
|
|
7681
7887
|
// Handle schema names - extract from List structure
|
|
7682
7888
|
const items = ListUtils.unwrapList(node.object);
|
|
@@ -7692,19 +7898,19 @@ export class Deparser {
|
|
|
7692
7898
|
}
|
|
7693
7899
|
}
|
|
7694
7900
|
if (node.renameType === 'OBJECT_COLUMN' && node.subname) {
|
|
7695
|
-
output.push('RENAME COLUMN',
|
|
7901
|
+
output.push('RENAME COLUMN', QuoteUtils.quoteIdentifier(node.subname), 'TO');
|
|
7696
7902
|
}
|
|
7697
7903
|
else if (node.renameType === 'OBJECT_DOMCONSTRAINT' && node.subname) {
|
|
7698
|
-
output.push('RENAME CONSTRAINT',
|
|
7904
|
+
output.push('RENAME CONSTRAINT', QuoteUtils.quoteIdentifier(node.subname), 'TO');
|
|
7699
7905
|
}
|
|
7700
7906
|
else if (node.renameType === 'OBJECT_TABCONSTRAINT' && node.subname) {
|
|
7701
|
-
output.push('RENAME CONSTRAINT',
|
|
7907
|
+
output.push('RENAME CONSTRAINT', QuoteUtils.quoteIdentifier(node.subname), 'TO');
|
|
7702
7908
|
}
|
|
7703
7909
|
else if (node.renameType === 'OBJECT_ATTRIBUTE' && node.subname) {
|
|
7704
|
-
output.push('RENAME ATTRIBUTE',
|
|
7910
|
+
output.push('RENAME ATTRIBUTE', QuoteUtils.quoteIdentifier(node.subname), 'TO');
|
|
7705
7911
|
}
|
|
7706
7912
|
else if (node.renameType === 'OBJECT_ROLE' && node.subname) {
|
|
7707
|
-
output.push(
|
|
7913
|
+
output.push(QuoteUtils.quoteIdentifier(node.subname), 'RENAME TO');
|
|
7708
7914
|
}
|
|
7709
7915
|
else if (node.renameType === 'OBJECT_SCHEMA' && node.subname) {
|
|
7710
7916
|
output.push(this.quoteIfNeeded(node.subname), 'RENAME TO');
|
|
@@ -7718,7 +7924,7 @@ export class Deparser {
|
|
|
7718
7924
|
if (!node.newname) {
|
|
7719
7925
|
throw new Error('RenameStmt requires newname');
|
|
7720
7926
|
}
|
|
7721
|
-
output.push(QuoteUtils.
|
|
7927
|
+
output.push(QuoteUtils.quoteIdentifier(node.newname));
|
|
7722
7928
|
// Handle CASCADE/RESTRICT behavior for RENAME operations
|
|
7723
7929
|
if (node.behavior === 'DROP_CASCADE') {
|
|
7724
7930
|
output.push('CASCADE');
|
|
@@ -7741,7 +7947,7 @@ export class Deparser {
|
|
|
7741
7947
|
if (items.length === 2) {
|
|
7742
7948
|
const accessMethod = items[0].String?.sval || '';
|
|
7743
7949
|
const objectName = items[1].String?.sval || '';
|
|
7744
|
-
output.push(`${QuoteUtils.
|
|
7950
|
+
output.push(`${QuoteUtils.quoteIdentifier(objectName)} USING ${accessMethod}`);
|
|
7745
7951
|
}
|
|
7746
7952
|
else {
|
|
7747
7953
|
output.push(this.visit(node.object, context));
|
|
@@ -7816,6 +8022,9 @@ export class Deparser {
|
|
|
7816
8022
|
else if (node.objtype === 'OBJECT_LANGUAGE') {
|
|
7817
8023
|
output.push('LANGUAGE');
|
|
7818
8024
|
}
|
|
8025
|
+
else if (node.objtype === 'OBJECT_SEQUENCE') {
|
|
8026
|
+
output.push('SEQUENCE');
|
|
8027
|
+
}
|
|
7819
8028
|
else if (node.objtype === 'OBJECT_FUNCTION') {
|
|
7820
8029
|
output.push('FUNCTION');
|
|
7821
8030
|
}
|
|
@@ -7841,8 +8050,11 @@ export class Deparser {
|
|
|
7841
8050
|
output.push('DATABASE');
|
|
7842
8051
|
}
|
|
7843
8052
|
if (node.objects && node.objects.length > 0) {
|
|
8053
|
+
const qualifiedKinds = ['OBJECT_TYPE', 'OBJECT_DOMAIN'];
|
|
7844
8054
|
const objects = ListUtils.unwrapList(node.objects)
|
|
7845
|
-
.map(obj =>
|
|
8055
|
+
.map(obj => qualifiedKinds.includes(node.objtype) && obj.List
|
|
8056
|
+
? ListUtils.unwrapList(obj.List.items).map((item) => this.visit(item, context)).join('.')
|
|
8057
|
+
: this.visit(obj, context))
|
|
7846
8058
|
.join(', ');
|
|
7847
8059
|
output.push(objects);
|
|
7848
8060
|
}
|
|
@@ -7881,8 +8093,11 @@ export class Deparser {
|
|
|
7881
8093
|
break;
|
|
7882
8094
|
default:
|
|
7883
8095
|
if (node.objects && node.objects.length > 0) {
|
|
8096
|
+
const qualifiedKinds = ['OBJECT_TYPE', 'OBJECT_DOMAIN'];
|
|
7884
8097
|
const objects = ListUtils.unwrapList(node.objects)
|
|
7885
|
-
.map(obj =>
|
|
8098
|
+
.map(obj => qualifiedKinds.includes(node.objtype) && obj.List
|
|
8099
|
+
? ListUtils.unwrapList(obj.List.items).map((item) => this.visit(item, context)).join('.')
|
|
8100
|
+
: this.visit(obj, context))
|
|
7886
8101
|
.join(', ');
|
|
7887
8102
|
output.push(objects);
|
|
7888
8103
|
}
|
|
@@ -7902,6 +8117,9 @@ export class Deparser {
|
|
|
7902
8117
|
if (node.grant_option && node.is_grant) {
|
|
7903
8118
|
output.push('WITH GRANT OPTION');
|
|
7904
8119
|
}
|
|
8120
|
+
if (node.grantor) {
|
|
8121
|
+
output.push('GRANTED BY', this.RoleSpec(node.grantor, context));
|
|
8122
|
+
}
|
|
7905
8123
|
// Only add behavior clauses for REVOKE statements, not for GRANT statements in ALTER DEFAULT PRIVILEGES
|
|
7906
8124
|
if (!node.is_grant) {
|
|
7907
8125
|
if (node.behavior === 'DROP_CASCADE') {
|
|
@@ -7915,57 +8133,34 @@ export class Deparser {
|
|
|
7915
8133
|
}
|
|
7916
8134
|
GrantRoleStmt(node, context) {
|
|
7917
8135
|
const output = [];
|
|
7918
|
-
|
|
7919
|
-
|
|
7920
|
-
|
|
7921
|
-
|
|
7922
|
-
|
|
7923
|
-
|
|
7924
|
-
|
|
7925
|
-
|
|
7926
|
-
|
|
7927
|
-
|
|
7928
|
-
|
|
7929
|
-
|
|
7930
|
-
|
|
7931
|
-
|
|
7932
|
-
|
|
7933
|
-
|
|
7934
|
-
|
|
7935
|
-
|
|
7936
|
-
|
|
7937
|
-
if (adminOption.DefElem && adminOption.DefElem.arg) {
|
|
7938
|
-
adminValue = adminOption.DefElem.arg.Boolean?.boolval;
|
|
7939
|
-
}
|
|
7940
|
-
}
|
|
7941
|
-
if (setOption && setOption.DefElem) {
|
|
7942
|
-
hasSetOption = true;
|
|
7943
|
-
setValue = setOption.DefElem.arg?.Boolean?.boolval;
|
|
7944
|
-
}
|
|
7945
|
-
}
|
|
8136
|
+
const options = ListUtils.unwrapList(node.opt)
|
|
8137
|
+
.map(opt => opt.DefElem)
|
|
8138
|
+
.filter((opt) => !!opt && !!opt.defname);
|
|
8139
|
+
const optionValue = (opt) => {
|
|
8140
|
+
if (!opt.arg)
|
|
8141
|
+
return true;
|
|
8142
|
+
const argType = this.getNodeType(opt.arg);
|
|
8143
|
+
const argData = this.getNodeData(opt.arg);
|
|
8144
|
+
if (argType === 'Boolean')
|
|
8145
|
+
return argData.boolval !== false;
|
|
8146
|
+
if (argType === 'String')
|
|
8147
|
+
return argData.sval !== 'false';
|
|
8148
|
+
return true;
|
|
8149
|
+
};
|
|
8150
|
+
const roles = ListUtils.unwrapList(node.granted_roles)
|
|
8151
|
+
.map(role => role.AccessPriv?.priv_name
|
|
8152
|
+
? QuoteUtils.quoteIdentifier(role.AccessPriv.priv_name)
|
|
8153
|
+
: this.visit(role, context))
|
|
8154
|
+
.join(', ');
|
|
7946
8155
|
if (node.is_grant) {
|
|
7947
|
-
output.push('GRANT');
|
|
8156
|
+
output.push('GRANT', roles, 'TO');
|
|
7948
8157
|
}
|
|
7949
8158
|
else {
|
|
7950
8159
|
output.push('REVOKE');
|
|
7951
|
-
if (
|
|
7952
|
-
output.push(
|
|
7953
|
-
}
|
|
7954
|
-
else if (hasAdminOption) {
|
|
7955
|
-
output.push('ADMIN OPTION FOR');
|
|
8160
|
+
if (options.length > 0) {
|
|
8161
|
+
output.push(`${options[0].defname.toUpperCase()} OPTION FOR`);
|
|
7956
8162
|
}
|
|
7957
|
-
|
|
7958
|
-
if (node.granted_roles && node.granted_roles.length > 0) {
|
|
7959
|
-
const roles = ListUtils.unwrapList(node.granted_roles)
|
|
7960
|
-
.map(role => this.visit(role, context))
|
|
7961
|
-
.join(', ');
|
|
7962
|
-
output.push(roles);
|
|
7963
|
-
}
|
|
7964
|
-
if (node.is_grant) {
|
|
7965
|
-
output.push('TO');
|
|
7966
|
-
}
|
|
7967
|
-
else {
|
|
7968
|
-
output.push('FROM');
|
|
8163
|
+
output.push(roles, 'FROM');
|
|
7969
8164
|
}
|
|
7970
8165
|
if (node.grantee_roles && node.grantee_roles.length > 0) {
|
|
7971
8166
|
const grantees = ListUtils.unwrapList(node.grantee_roles)
|
|
@@ -7973,45 +8168,22 @@ export class Deparser {
|
|
|
7973
8168
|
.join(', ');
|
|
7974
8169
|
output.push(grantees);
|
|
7975
8170
|
}
|
|
7976
|
-
if (node.is_grant) {
|
|
7977
|
-
const withOptions =
|
|
7978
|
-
|
|
7979
|
-
|
|
7980
|
-
|
|
7981
|
-
|
|
7982
|
-
|
|
7983
|
-
|
|
7984
|
-
|
|
7985
|
-
else {
|
|
7986
|
-
withOptions.push('ADMIN OPTION');
|
|
7987
|
-
}
|
|
7988
|
-
}
|
|
7989
|
-
if (hasInheritOption) {
|
|
7990
|
-
if (inheritValue === true) {
|
|
7991
|
-
withOptions.push('INHERIT OPTION');
|
|
7992
|
-
}
|
|
7993
|
-
else if (inheritValue === false) {
|
|
7994
|
-
withOptions.push('INHERIT FALSE');
|
|
7995
|
-
}
|
|
7996
|
-
}
|
|
7997
|
-
if (hasSetOption) {
|
|
7998
|
-
if (setValue === true) {
|
|
7999
|
-
withOptions.push('SET TRUE');
|
|
8000
|
-
}
|
|
8001
|
-
else if (setValue === false) {
|
|
8002
|
-
withOptions.push('SET FALSE');
|
|
8003
|
-
}
|
|
8004
|
-
}
|
|
8005
|
-
if (withOptions.length > 0) {
|
|
8006
|
-
output.push('WITH', withOptions.join(', '));
|
|
8007
|
-
}
|
|
8171
|
+
if (node.is_grant && options.length > 0) {
|
|
8172
|
+
const withOptions = options.map(opt => `${opt.defname.toUpperCase()} ${optionValue(opt) ? 'TRUE' : 'FALSE'}`);
|
|
8173
|
+
output.push('WITH', withOptions.join(', '));
|
|
8174
|
+
}
|
|
8175
|
+
if (node.grantor) {
|
|
8176
|
+
output.push('GRANTED BY', this.RoleSpec(node.grantor, context));
|
|
8177
|
+
}
|
|
8178
|
+
if (!node.is_grant && node.behavior === 'DROP_CASCADE') {
|
|
8179
|
+
output.push('CASCADE');
|
|
8008
8180
|
}
|
|
8009
8181
|
return output.join(' ');
|
|
8010
8182
|
}
|
|
8011
8183
|
SecLabelStmt(node, context) {
|
|
8012
8184
|
const output = ['SECURITY LABEL'];
|
|
8013
8185
|
if (node.provider) {
|
|
8014
|
-
output.push('FOR',
|
|
8186
|
+
output.push('FOR', QuoteUtils.quoteIdentifier(node.provider));
|
|
8015
8187
|
}
|
|
8016
8188
|
output.push('ON');
|
|
8017
8189
|
if (node.objtype) {
|
|
@@ -8039,11 +8211,21 @@ export class Deparser {
|
|
|
8039
8211
|
}
|
|
8040
8212
|
}
|
|
8041
8213
|
if (node.object) {
|
|
8042
|
-
|
|
8214
|
+
// Qualified names arrive as a List of String nodes and must be
|
|
8215
|
+
// dot-joined (visiting the List directly would comma-join them).
|
|
8216
|
+
if (typeof node.object === 'object' && 'List' in node.object) {
|
|
8217
|
+
const list = node.object.List;
|
|
8218
|
+
const objectParts = ListUtils.unwrapList(list.items)
|
|
8219
|
+
.map(item => this.visit(item, context));
|
|
8220
|
+
output.push(objectParts.join('.'));
|
|
8221
|
+
}
|
|
8222
|
+
else {
|
|
8223
|
+
output.push(this.visit(node.object, context));
|
|
8224
|
+
}
|
|
8043
8225
|
}
|
|
8044
8226
|
output.push('IS');
|
|
8045
8227
|
if (node.label) {
|
|
8046
|
-
output.push(
|
|
8228
|
+
output.push(QuoteUtils.escape(node.label));
|
|
8047
8229
|
}
|
|
8048
8230
|
else {
|
|
8049
8231
|
output.push('NULL');
|
|
@@ -8100,10 +8282,10 @@ export class Deparser {
|
|
|
8100
8282
|
output.push(conversionName);
|
|
8101
8283
|
}
|
|
8102
8284
|
if (node.for_encoding_name) {
|
|
8103
|
-
output.push('FOR',
|
|
8285
|
+
output.push('FOR', QuoteUtils.escape(node.for_encoding_name));
|
|
8104
8286
|
}
|
|
8105
8287
|
if (node.to_encoding_name) {
|
|
8106
|
-
output.push('TO',
|
|
8288
|
+
output.push('TO', QuoteUtils.escape(node.to_encoding_name));
|
|
8107
8289
|
}
|
|
8108
8290
|
if (node.func_name && node.func_name.length > 0) {
|
|
8109
8291
|
output.push('FROM');
|
|
@@ -8164,7 +8346,7 @@ export class Deparser {
|
|
|
8164
8346
|
}
|
|
8165
8347
|
output.push('LANGUAGE');
|
|
8166
8348
|
if (node.plname) {
|
|
8167
|
-
output.push(QuoteUtils.
|
|
8349
|
+
output.push(QuoteUtils.quoteIdentifier(node.plname));
|
|
8168
8350
|
}
|
|
8169
8351
|
if (node.plhandler && node.plhandler.length > 0) {
|
|
8170
8352
|
output.push('HANDLER');
|
|
@@ -8200,7 +8382,7 @@ export class Deparser {
|
|
|
8200
8382
|
}
|
|
8201
8383
|
output.push('LANGUAGE');
|
|
8202
8384
|
if (node.lang) {
|
|
8203
|
-
output.push(QuoteUtils.
|
|
8385
|
+
output.push(QuoteUtils.quoteIdentifier(node.lang));
|
|
8204
8386
|
}
|
|
8205
8387
|
output.push('(');
|
|
8206
8388
|
const transforms = [];
|
|
@@ -8228,7 +8410,7 @@ export class Deparser {
|
|
|
8228
8410
|
}
|
|
8229
8411
|
output.push('TRIGGER');
|
|
8230
8412
|
if (node.trigname) {
|
|
8231
|
-
output.push(QuoteUtils.
|
|
8413
|
+
output.push(QuoteUtils.quoteIdentifier(node.trigname));
|
|
8232
8414
|
}
|
|
8233
8415
|
if (context.isPretty()) {
|
|
8234
8416
|
const components = [];
|
|
@@ -8266,6 +8448,9 @@ export class Deparser {
|
|
|
8266
8448
|
.join(' ');
|
|
8267
8449
|
components.push(context.indent('REFERENCING ' + transitionClauses));
|
|
8268
8450
|
}
|
|
8451
|
+
if (node.constrrel) {
|
|
8452
|
+
components.push(context.indent('FROM ' + this.RangeVar(node.constrrel, context)));
|
|
8453
|
+
}
|
|
8269
8454
|
if (node.deferrable) {
|
|
8270
8455
|
components.push(context.indent('DEFERRABLE'));
|
|
8271
8456
|
}
|
|
@@ -8287,7 +8472,7 @@ export class Deparser {
|
|
|
8287
8472
|
const funcName = ListUtils.unwrapList(node.funcname)
|
|
8288
8473
|
.map(name => this.visit(name, context))
|
|
8289
8474
|
.join('.');
|
|
8290
|
-
executeStr += '
|
|
8475
|
+
executeStr += ' FUNCTION ' + funcName;
|
|
8291
8476
|
}
|
|
8292
8477
|
if (node.args && node.args.length > 0) {
|
|
8293
8478
|
const argContext = context.spawn('CreateTrigStmt', { isStringLiteral: true });
|
|
@@ -8392,14 +8577,14 @@ export class Deparser {
|
|
|
8392
8577
|
output.push('OLD TABLE AS');
|
|
8393
8578
|
}
|
|
8394
8579
|
if (node.name) {
|
|
8395
|
-
output.push(QuoteUtils.
|
|
8580
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
8396
8581
|
}
|
|
8397
8582
|
return output.join(' ');
|
|
8398
8583
|
}
|
|
8399
8584
|
CreateEventTrigStmt(node, context) {
|
|
8400
8585
|
const output = ['CREATE EVENT TRIGGER'];
|
|
8401
8586
|
if (node.trigname) {
|
|
8402
|
-
output.push(QuoteUtils.
|
|
8587
|
+
output.push(QuoteUtils.quoteIdentifier(node.trigname));
|
|
8403
8588
|
}
|
|
8404
8589
|
output.push('ON');
|
|
8405
8590
|
if (node.eventname) {
|
|
@@ -8425,7 +8610,7 @@ export class Deparser {
|
|
|
8425
8610
|
AlterEventTrigStmt(node, context) {
|
|
8426
8611
|
const output = ['ALTER EVENT TRIGGER'];
|
|
8427
8612
|
if (node.trigname) {
|
|
8428
|
-
output.push(QuoteUtils.
|
|
8613
|
+
output.push(QuoteUtils.quoteIdentifier(node.trigname));
|
|
8429
8614
|
}
|
|
8430
8615
|
if (node.tgenabled) {
|
|
8431
8616
|
switch (node.tgenabled) {
|
|
@@ -8545,6 +8730,74 @@ export class Deparser {
|
|
|
8545
8730
|
.join(' ');
|
|
8546
8731
|
output.push(whenClauses);
|
|
8547
8732
|
}
|
|
8733
|
+
if (node.returningClause) {
|
|
8734
|
+
output.push(this.ReturningClause(node.returningClause, context));
|
|
8735
|
+
}
|
|
8736
|
+
return output.join(' ');
|
|
8737
|
+
}
|
|
8738
|
+
MergeSupportFunc(node, context) {
|
|
8739
|
+
return 'merge_action()';
|
|
8740
|
+
}
|
|
8741
|
+
MergeWhenClause(node, context) {
|
|
8742
|
+
const output = ['WHEN'];
|
|
8743
|
+
switch (node.matchKind) {
|
|
8744
|
+
case 'MERGE_WHEN_MATCHED':
|
|
8745
|
+
output.push('MATCHED');
|
|
8746
|
+
break;
|
|
8747
|
+
case 'MERGE_WHEN_NOT_MATCHED_BY_SOURCE':
|
|
8748
|
+
output.push('NOT MATCHED BY SOURCE');
|
|
8749
|
+
break;
|
|
8750
|
+
case 'MERGE_WHEN_NOT_MATCHED_BY_TARGET':
|
|
8751
|
+
output.push('NOT MATCHED');
|
|
8752
|
+
break;
|
|
8753
|
+
}
|
|
8754
|
+
if (node.condition) {
|
|
8755
|
+
output.push('AND');
|
|
8756
|
+
output.push(this.visit(node.condition, context));
|
|
8757
|
+
}
|
|
8758
|
+
output.push('THEN');
|
|
8759
|
+
switch (node.commandType) {
|
|
8760
|
+
case 'CMD_UPDATE': {
|
|
8761
|
+
output.push('UPDATE SET');
|
|
8762
|
+
if (node.targetList && node.targetList.length > 0) {
|
|
8763
|
+
output.push(this.formatUpdateAssignments(node.targetList, context));
|
|
8764
|
+
}
|
|
8765
|
+
break;
|
|
8766
|
+
}
|
|
8767
|
+
case 'CMD_INSERT': {
|
|
8768
|
+
output.push('INSERT');
|
|
8769
|
+
const targetList = ListUtils.unwrapList(node.targetList);
|
|
8770
|
+
if (targetList.length > 0) {
|
|
8771
|
+
const columns = targetList
|
|
8772
|
+
.map(target => QuoteUtils.quoteIdentifier(target.ResTarget?.name))
|
|
8773
|
+
.join(', ');
|
|
8774
|
+
output.push(`(${columns})`);
|
|
8775
|
+
}
|
|
8776
|
+
if (node.override === 'OVERRIDING_USER_VALUE') {
|
|
8777
|
+
output.push('OVERRIDING USER VALUE');
|
|
8778
|
+
}
|
|
8779
|
+
else if (node.override === 'OVERRIDING_SYSTEM_VALUE') {
|
|
8780
|
+
output.push('OVERRIDING SYSTEM VALUE');
|
|
8781
|
+
}
|
|
8782
|
+
const values = ListUtils.unwrapList(node.values);
|
|
8783
|
+
if (values.length > 0) {
|
|
8784
|
+
const valueItems = values
|
|
8785
|
+
.map(value => this.visit(value, context))
|
|
8786
|
+
.join(', ');
|
|
8787
|
+
output.push(`VALUES (${valueItems})`);
|
|
8788
|
+
}
|
|
8789
|
+
else {
|
|
8790
|
+
output.push('DEFAULT VALUES');
|
|
8791
|
+
}
|
|
8792
|
+
break;
|
|
8793
|
+
}
|
|
8794
|
+
case 'CMD_DELETE':
|
|
8795
|
+
output.push('DELETE');
|
|
8796
|
+
break;
|
|
8797
|
+
case 'CMD_NOTHING':
|
|
8798
|
+
output.push('DO NOTHING');
|
|
8799
|
+
break;
|
|
8800
|
+
}
|
|
8548
8801
|
return output.join(' ');
|
|
8549
8802
|
}
|
|
8550
8803
|
AlterTableMoveAllStmt(node, context) {
|
|
@@ -8560,11 +8813,11 @@ export class Deparser {
|
|
|
8560
8813
|
}
|
|
8561
8814
|
output.push('ALL', 'IN', 'TABLESPACE');
|
|
8562
8815
|
if (node.orig_tablespacename) {
|
|
8563
|
-
output.push(QuoteUtils.
|
|
8816
|
+
output.push(QuoteUtils.quoteIdentifier(node.orig_tablespacename));
|
|
8564
8817
|
}
|
|
8565
8818
|
output.push('SET', 'TABLESPACE');
|
|
8566
8819
|
if (node.new_tablespacename) {
|
|
8567
|
-
output.push(QuoteUtils.
|
|
8820
|
+
output.push(QuoteUtils.quoteIdentifier(node.new_tablespacename));
|
|
8568
8821
|
}
|
|
8569
8822
|
if (node.nowait) {
|
|
8570
8823
|
output.push('NOWAIT');
|
|
@@ -8588,10 +8841,10 @@ export class Deparser {
|
|
|
8588
8841
|
const sequenceName = [];
|
|
8589
8842
|
const seq = node.sequence;
|
|
8590
8843
|
if (seq.schemaname) {
|
|
8591
|
-
sequenceName.push(QuoteUtils.
|
|
8844
|
+
sequenceName.push(QuoteUtils.quoteIdentifier(seq.schemaname));
|
|
8592
8845
|
}
|
|
8593
8846
|
if (seq.relname) {
|
|
8594
|
-
sequenceName.push(QuoteUtils.
|
|
8847
|
+
sequenceName.push(QuoteUtils.quoteIdentifier(seq.relname));
|
|
8595
8848
|
}
|
|
8596
8849
|
output.push(sequenceName.join('.'));
|
|
8597
8850
|
}
|
|
@@ -8625,10 +8878,10 @@ export class Deparser {
|
|
|
8625
8878
|
const sequenceName = [];
|
|
8626
8879
|
const seq = node.sequence;
|
|
8627
8880
|
if (seq.schemaname) {
|
|
8628
|
-
sequenceName.push(QuoteUtils.
|
|
8881
|
+
sequenceName.push(QuoteUtils.quoteIdentifier(seq.schemaname));
|
|
8629
8882
|
}
|
|
8630
8883
|
if (seq.relname) {
|
|
8631
|
-
sequenceName.push(QuoteUtils.
|
|
8884
|
+
sequenceName.push(QuoteUtils.quoteIdentifier(seq.relname));
|
|
8632
8885
|
}
|
|
8633
8886
|
output.push(sequenceName.join('.'));
|
|
8634
8887
|
}
|
|
@@ -8913,6 +9166,13 @@ export class Deparser {
|
|
|
8913
9166
|
output.push('USING');
|
|
8914
9167
|
output.push(node.into.accessMethod);
|
|
8915
9168
|
}
|
|
9169
|
+
if (node.into && node.into.options && node.into.options.length > 0) {
|
|
9170
|
+
output.push('WITH');
|
|
9171
|
+
const options = ListUtils.unwrapList(node.into.options)
|
|
9172
|
+
.map(option => this.visit(option, context.spawn('CreateStmt')))
|
|
9173
|
+
.join(', ');
|
|
9174
|
+
output.push(`(${options})`);
|
|
9175
|
+
}
|
|
8916
9176
|
if (node.into && node.into.onCommit && node.into.onCommit !== 'ONCOMMIT_NOOP') {
|
|
8917
9177
|
output.push('ON COMMIT');
|
|
8918
9178
|
switch (node.into.onCommit) {
|
|
@@ -8927,17 +9187,13 @@ export class Deparser {
|
|
|
8927
9187
|
break;
|
|
8928
9188
|
}
|
|
8929
9189
|
}
|
|
9190
|
+
if (node.into && node.into.tableSpaceName) {
|
|
9191
|
+
output.push('TABLESPACE', QuoteUtils.quoteIdentifier(node.into.tableSpaceName));
|
|
9192
|
+
}
|
|
8930
9193
|
output.push('AS');
|
|
8931
9194
|
if (node.query) {
|
|
8932
9195
|
output.push(this.visit(node.query, context));
|
|
8933
9196
|
}
|
|
8934
|
-
if (node.into && node.into.options && node.into.options.length > 0) {
|
|
8935
|
-
output.push('WITH');
|
|
8936
|
-
const options = ListUtils.unwrapList(node.into.options)
|
|
8937
|
-
.map(option => this.visit(option, context))
|
|
8938
|
-
.join(', ');
|
|
8939
|
-
output.push(`(${options})`);
|
|
8940
|
-
}
|
|
8941
9197
|
if (node.into && node.into.skipData) {
|
|
8942
9198
|
output.push('WITH NO DATA');
|
|
8943
9199
|
}
|
|
@@ -8975,7 +9231,7 @@ export class Deparser {
|
|
|
8975
9231
|
}
|
|
8976
9232
|
aliasname(node, context) {
|
|
8977
9233
|
if (typeof node === 'string') {
|
|
8978
|
-
return QuoteUtils.
|
|
9234
|
+
return QuoteUtils.quoteIdentifier(node);
|
|
8979
9235
|
}
|
|
8980
9236
|
return this.visit(node, context);
|
|
8981
9237
|
}
|
|
@@ -9007,18 +9263,16 @@ export class Deparser {
|
|
|
9007
9263
|
const defName = defElem.defname;
|
|
9008
9264
|
const defValue = defElem.arg;
|
|
9009
9265
|
if (defName && defValue) {
|
|
9010
|
-
|
|
9011
|
-
|
|
9012
|
-
preservedDefName = `"${defName}"`;
|
|
9013
|
-
}
|
|
9014
|
-
else {
|
|
9015
|
-
preservedDefName = this.preserveOperatorDefElemCase(defName);
|
|
9016
|
-
}
|
|
9266
|
+
const quotedDefName = QuoteUtils.quoteIdentifier(defName);
|
|
9267
|
+
const preservedDefName = quotedDefName !== defName ? quotedDefName : this.preserveOperatorDefElemCase(defName);
|
|
9017
9268
|
if ((defName.toLowerCase() === 'commutator' || defName.toLowerCase() === 'negator') && defValue.List) {
|
|
9018
9269
|
const listItems = ListUtils.unwrapList(defValue.List.items);
|
|
9019
9270
|
if (listItems.length === 1 && listItems[0].String) {
|
|
9020
9271
|
return `${preservedDefName} = ${listItems[0].String.sval}`;
|
|
9021
9272
|
}
|
|
9273
|
+
if (listItems.length > 1 && listItems.every(item => item.String)) {
|
|
9274
|
+
return `${preservedDefName} = OPERATOR(${this.qualifiedOperatorName(listItems)})`;
|
|
9275
|
+
}
|
|
9022
9276
|
}
|
|
9023
9277
|
// For commutator/negator, we already handled them above
|
|
9024
9278
|
if ((defName.toLowerCase() === 'commutator' || defName.toLowerCase() === 'negator')) {
|
|
@@ -9029,7 +9283,7 @@ export class Deparser {
|
|
|
9029
9283
|
else if (defName && !defValue) {
|
|
9030
9284
|
// Handle boolean flags like HASHES, MERGES - preserve original case
|
|
9031
9285
|
if (defName === 'Hashes' || defName === 'Merges') {
|
|
9032
|
-
return
|
|
9286
|
+
return QuoteUtils.quoteIdentifier(defName);
|
|
9033
9287
|
}
|
|
9034
9288
|
return this.preserveOperatorDefElemCase(defName).toUpperCase();
|
|
9035
9289
|
}
|
|
@@ -9168,16 +9422,11 @@ export class Deparser {
|
|
|
9168
9422
|
const defName = defElem.defname;
|
|
9169
9423
|
const defValue = defElem.arg;
|
|
9170
9424
|
if (defName && defValue) {
|
|
9171
|
-
|
|
9172
|
-
|
|
9173
|
-
preservedDefName = `"${defName}"`;
|
|
9174
|
-
}
|
|
9175
|
-
else {
|
|
9176
|
-
preservedDefName = defName;
|
|
9177
|
-
}
|
|
9425
|
+
const quotedDefName = QuoteUtils.quoteIdentifier(defName);
|
|
9426
|
+
const preservedDefName = quotedDefName !== defName ? quotedDefName : defName;
|
|
9178
9427
|
// Handle String arguments with single quotes for string literals
|
|
9179
9428
|
if (defValue.String) {
|
|
9180
|
-
return `${preservedDefName} =
|
|
9429
|
+
return `${preservedDefName} = ${QuoteUtils.escape(defValue.String.sval)}`;
|
|
9181
9430
|
}
|
|
9182
9431
|
return `${preservedDefName} = ${this.visit(defValue, context)}`;
|
|
9183
9432
|
}
|
|
@@ -9300,7 +9549,7 @@ export class Deparser {
|
|
|
9300
9549
|
// For CREATE COLLATION, ensure String nodes are quoted as string literals
|
|
9301
9550
|
let valueStr;
|
|
9302
9551
|
if (defValue.String) {
|
|
9303
|
-
valueStr =
|
|
9552
|
+
valueStr = QuoteUtils.escape(defValue.String.sval);
|
|
9304
9553
|
}
|
|
9305
9554
|
else {
|
|
9306
9555
|
valueStr = this.visit(defValue, context);
|
|
@@ -9329,7 +9578,7 @@ export class Deparser {
|
|
|
9329
9578
|
AlterDatabaseStmt(node, context) {
|
|
9330
9579
|
const output = ['ALTER', 'DATABASE'];
|
|
9331
9580
|
if (node.dbname) {
|
|
9332
|
-
output.push(QuoteUtils.
|
|
9581
|
+
output.push(QuoteUtils.quoteIdentifier(node.dbname));
|
|
9333
9582
|
}
|
|
9334
9583
|
if (node.options && node.options.length > 0) {
|
|
9335
9584
|
const options = ListUtils.unwrapList(node.options).map(opt => this.visit(opt, context));
|
|
@@ -9340,7 +9589,7 @@ export class Deparser {
|
|
|
9340
9589
|
AlterDatabaseRefreshCollStmt(node, context) {
|
|
9341
9590
|
const output = ['ALTER', 'DATABASE'];
|
|
9342
9591
|
if (node.dbname) {
|
|
9343
|
-
output.push(QuoteUtils.
|
|
9592
|
+
output.push(QuoteUtils.quoteIdentifier(node.dbname));
|
|
9344
9593
|
}
|
|
9345
9594
|
output.push('REFRESH', 'COLLATION', 'VERSION');
|
|
9346
9595
|
return output.join(' ');
|
|
@@ -9348,7 +9597,7 @@ export class Deparser {
|
|
|
9348
9597
|
AlterDatabaseSetStmt(node, context) {
|
|
9349
9598
|
const output = ['ALTER', 'DATABASE'];
|
|
9350
9599
|
if (node.dbname) {
|
|
9351
|
-
output.push(QuoteUtils.
|
|
9600
|
+
output.push(QuoteUtils.quoteIdentifier(node.dbname));
|
|
9352
9601
|
}
|
|
9353
9602
|
if (node.setstmt) {
|
|
9354
9603
|
const setClause = this.VariableSetStmt(node.setstmt, context);
|
|
@@ -9359,7 +9608,7 @@ export class Deparser {
|
|
|
9359
9608
|
DeclareCursorStmt(node, context) {
|
|
9360
9609
|
const output = ['DECLARE'];
|
|
9361
9610
|
if (node.portalname) {
|
|
9362
|
-
output.push(QuoteUtils.
|
|
9611
|
+
output.push(QuoteUtils.quoteIdentifier(node.portalname));
|
|
9363
9612
|
}
|
|
9364
9613
|
// Handle cursor options before CURSOR keyword
|
|
9365
9614
|
const cursorOptions = [];
|
|
@@ -9401,7 +9650,7 @@ export class Deparser {
|
|
|
9401
9650
|
else if (node.pubobjtype === 'PUBLICATIONOBJ_TABLES_IN_SCHEMA') {
|
|
9402
9651
|
output.push('TABLES IN SCHEMA');
|
|
9403
9652
|
if (node.name) {
|
|
9404
|
-
output.push(QuoteUtils.
|
|
9653
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
9405
9654
|
}
|
|
9406
9655
|
}
|
|
9407
9656
|
else if (node.pubobjtype === 'PUBLICATIONOBJ_TABLES_IN_CUR_SCHEMA') {
|
|
@@ -9420,14 +9669,14 @@ export class Deparser {
|
|
|
9420
9669
|
}
|
|
9421
9670
|
if (node.whereClause) {
|
|
9422
9671
|
output.push('WHERE');
|
|
9423
|
-
output.push(this.visit(node.whereClause, context));
|
|
9672
|
+
output.push(`(${this.visit(node.whereClause, context)})`);
|
|
9424
9673
|
}
|
|
9425
9674
|
return output.join(' ');
|
|
9426
9675
|
}
|
|
9427
9676
|
CreateAmStmt(node, context) {
|
|
9428
9677
|
const output = ['CREATE', 'ACCESS', 'METHOD'];
|
|
9429
9678
|
if (node.amname) {
|
|
9430
|
-
output.push(QuoteUtils.
|
|
9679
|
+
output.push(QuoteUtils.quoteIdentifier(node.amname));
|
|
9431
9680
|
}
|
|
9432
9681
|
output.push('TYPE');
|
|
9433
9682
|
switch (node.amtype) {
|
|
@@ -9487,7 +9736,7 @@ export class Deparser {
|
|
|
9487
9736
|
}
|
|
9488
9737
|
}
|
|
9489
9738
|
if (node.tableSpaceName) {
|
|
9490
|
-
output.push('TABLESPACE', QuoteUtils.
|
|
9739
|
+
output.push('TABLESPACE', QuoteUtils.quoteIdentifier(node.tableSpaceName));
|
|
9491
9740
|
}
|
|
9492
9741
|
return output.join(' ');
|
|
9493
9742
|
}
|
|
@@ -9567,6 +9816,23 @@ export class Deparser {
|
|
|
9567
9816
|
}
|
|
9568
9817
|
return output.join(' ');
|
|
9569
9818
|
}
|
|
9819
|
+
quoteDefElemArg(arg, argValue) {
|
|
9820
|
+
if (arg && this.getNodeType(arg) === 'String') {
|
|
9821
|
+
return QuoteUtils.escape(this.getNodeData(arg).sval || '');
|
|
9822
|
+
}
|
|
9823
|
+
return typeof argValue === 'string' && !argValue.startsWith("'")
|
|
9824
|
+
? QuoteUtils.escape(argValue)
|
|
9825
|
+
: argValue;
|
|
9826
|
+
}
|
|
9827
|
+
formatOptionValue(arg, argValue) {
|
|
9828
|
+
if (arg && this.getNodeType(arg) === 'String') {
|
|
9829
|
+
const sval = this.getNodeData(arg).sval || '';
|
|
9830
|
+
return /^[a-z_][a-z0-9_]*$/.test(sval) && keywordKindOf(sval) === 'NO_KEYWORD'
|
|
9831
|
+
? sval
|
|
9832
|
+
: QuoteUtils.escape(sval);
|
|
9833
|
+
}
|
|
9834
|
+
return argValue;
|
|
9835
|
+
}
|
|
9570
9836
|
Var(node, context) {
|
|
9571
9837
|
if (node.varno && node.varattno) {
|
|
9572
9838
|
return `$${node.varno}.${node.varattno}`;
|
|
@@ -9606,7 +9872,7 @@ export class Deparser {
|
|
|
9606
9872
|
}
|
|
9607
9873
|
if (node.rowexpr) {
|
|
9608
9874
|
output.push(',');
|
|
9609
|
-
output.push(
|
|
9875
|
+
output.push(this.visit(node.rowexpr, context));
|
|
9610
9876
|
}
|
|
9611
9877
|
if (node.colexprs && node.colexprs.length > 0) {
|
|
9612
9878
|
output.push('COLUMNS');
|
|
@@ -9623,29 +9889,44 @@ export class Deparser {
|
|
|
9623
9889
|
if (node.lateral) {
|
|
9624
9890
|
output.push('LATERAL');
|
|
9625
9891
|
}
|
|
9626
|
-
|
|
9627
|
-
|
|
9892
|
+
const args = [];
|
|
9893
|
+
if (node.namespaces && node.namespaces.length > 0) {
|
|
9894
|
+
const namespaces = ListUtils.unwrapList(node.namespaces).map(ns => {
|
|
9895
|
+
const target = this.getNodeData(ns);
|
|
9896
|
+
const uri = this.visit(target.val, context);
|
|
9897
|
+
return target.name ? `${uri} AS ${QuoteUtils.quoteIdentifier(target.name)}` : `DEFAULT ${uri}`;
|
|
9898
|
+
});
|
|
9899
|
+
args.push(`XMLNAMESPACES(${namespaces.join(', ')}),`);
|
|
9628
9900
|
}
|
|
9629
9901
|
if (node.rowexpr) {
|
|
9630
|
-
|
|
9631
|
-
|
|
9902
|
+
args.push(this.formatXmlTableExpr(node.rowexpr, context));
|
|
9903
|
+
}
|
|
9904
|
+
if (node.docexpr) {
|
|
9905
|
+
args.push('PASSING');
|
|
9906
|
+
args.push(this.formatXmlTableExpr(node.docexpr, context));
|
|
9632
9907
|
}
|
|
9633
9908
|
if (node.columns && node.columns.length > 0) {
|
|
9634
|
-
|
|
9635
|
-
|
|
9909
|
+
args.push('COLUMNS');
|
|
9910
|
+
args.push(ListUtils.unwrapList(node.columns)
|
|
9636
9911
|
.map(col => this.visit(col, context))
|
|
9637
|
-
.join(', ');
|
|
9638
|
-
output.push(`(${columns})`);
|
|
9912
|
+
.join(', '));
|
|
9639
9913
|
}
|
|
9914
|
+
output.push(`XMLTABLE(${args.join(' ')})`);
|
|
9640
9915
|
if (node.alias) {
|
|
9641
9916
|
output.push(this.Alias(node.alias, context));
|
|
9642
9917
|
}
|
|
9643
9918
|
return output.join(' ');
|
|
9644
9919
|
}
|
|
9920
|
+
formatXmlTableExpr(expr, context) {
|
|
9921
|
+
const value = this.visit(expr, context);
|
|
9922
|
+
return ['A_Const', 'ColumnRef', 'ParamRef', 'FuncCall'].includes(this.getNodeType(expr))
|
|
9923
|
+
? value
|
|
9924
|
+
: `(${value})`;
|
|
9925
|
+
}
|
|
9645
9926
|
RangeTableFuncCol(node, context) {
|
|
9646
9927
|
const output = [];
|
|
9647
9928
|
if (node.colname) {
|
|
9648
|
-
output.push(QuoteUtils.
|
|
9929
|
+
output.push(QuoteUtils.quoteIdentifier(node.colname));
|
|
9649
9930
|
}
|
|
9650
9931
|
if (node.for_ordinality) {
|
|
9651
9932
|
output.push('FOR ORDINALITY');
|
|
@@ -9655,32 +9936,193 @@ export class Deparser {
|
|
|
9655
9936
|
}
|
|
9656
9937
|
if (node.colexpr) {
|
|
9657
9938
|
output.push('PATH');
|
|
9658
|
-
output.push(
|
|
9939
|
+
output.push(this.visit(node.colexpr, context));
|
|
9659
9940
|
}
|
|
9660
9941
|
if (node.coldefexpr) {
|
|
9661
9942
|
output.push('DEFAULT');
|
|
9662
9943
|
output.push(this.visit(node.coldefexpr, context));
|
|
9663
9944
|
}
|
|
9945
|
+
if (node.is_not_null) {
|
|
9946
|
+
output.push('NOT NULL');
|
|
9947
|
+
}
|
|
9664
9948
|
return output.join(' ');
|
|
9665
9949
|
}
|
|
9950
|
+
formatJsonFormat(format) {
|
|
9951
|
+
if (!format || !format.format_type || format.format_type === 'JS_FORMAT_DEFAULT') {
|
|
9952
|
+
return null;
|
|
9953
|
+
}
|
|
9954
|
+
const parts = ['FORMAT JSON'];
|
|
9955
|
+
switch (format.encoding) {
|
|
9956
|
+
case 'JS_ENC_UTF8':
|
|
9957
|
+
parts.push('ENCODING UTF8');
|
|
9958
|
+
break;
|
|
9959
|
+
case 'JS_ENC_UTF16':
|
|
9960
|
+
parts.push('ENCODING UTF16');
|
|
9961
|
+
break;
|
|
9962
|
+
case 'JS_ENC_UTF32':
|
|
9963
|
+
parts.push('ENCODING UTF32');
|
|
9964
|
+
break;
|
|
9965
|
+
}
|
|
9966
|
+
return parts.join(' ');
|
|
9967
|
+
}
|
|
9968
|
+
formatJsonOutput(output, context) {
|
|
9969
|
+
if (!output || !output.typeName)
|
|
9970
|
+
return null;
|
|
9971
|
+
const parts = ['RETURNING', this.TypeName(output.typeName, context)];
|
|
9972
|
+
const format = this.formatJsonFormat(output.returning?.format);
|
|
9973
|
+
if (format)
|
|
9974
|
+
parts.push(format);
|
|
9975
|
+
return parts.join(' ');
|
|
9976
|
+
}
|
|
9977
|
+
formatJsonNullClause(absentOnNull) {
|
|
9978
|
+
return absentOnNull ? 'ABSENT ON NULL' : 'NULL ON NULL';
|
|
9979
|
+
}
|
|
9980
|
+
formatJsonUniqueClause(unique) {
|
|
9981
|
+
return unique ? 'WITH UNIQUE KEYS' : null;
|
|
9982
|
+
}
|
|
9983
|
+
JsonValueExpr(node, context) {
|
|
9984
|
+
const parts = [];
|
|
9985
|
+
if (node.raw_expr) {
|
|
9986
|
+
parts.push(this.visit(node.raw_expr, context));
|
|
9987
|
+
}
|
|
9988
|
+
const format = this.formatJsonFormat(node.format);
|
|
9989
|
+
if (format)
|
|
9990
|
+
parts.push(format);
|
|
9991
|
+
return parts.join(' ');
|
|
9992
|
+
}
|
|
9993
|
+
JsonKeyValue(node, context) {
|
|
9994
|
+
const key = node.key ? this.visit(node.key, context) : '';
|
|
9995
|
+
const value = node.value ? this.JsonValueExpr(node.value, context) : '';
|
|
9996
|
+
return `${key} : ${value}`;
|
|
9997
|
+
}
|
|
9998
|
+
JsonObjectConstructor(node, context) {
|
|
9999
|
+
const args = [];
|
|
10000
|
+
if (node.exprs && node.exprs.length > 0) {
|
|
10001
|
+
args.push(ListUtils.unwrapList(node.exprs).map(e => this.visit(e, context)).join(', '));
|
|
10002
|
+
args.push(this.formatJsonNullClause(node.absent_on_null));
|
|
10003
|
+
const unique = this.formatJsonUniqueClause(node.unique);
|
|
10004
|
+
if (unique)
|
|
10005
|
+
args.push(unique);
|
|
10006
|
+
}
|
|
10007
|
+
const output = this.formatJsonOutput(node.output, context);
|
|
10008
|
+
if (output)
|
|
10009
|
+
args.push(output);
|
|
10010
|
+
return `JSON_OBJECT(${args.join(' ')})`;
|
|
10011
|
+
}
|
|
10012
|
+
JsonArrayConstructor(node, context) {
|
|
10013
|
+
const args = [];
|
|
10014
|
+
if (node.exprs && node.exprs.length > 0) {
|
|
10015
|
+
args.push(ListUtils.unwrapList(node.exprs).map(e => this.visit(e, context)).join(', '));
|
|
10016
|
+
args.push(this.formatJsonNullClause(node.absent_on_null));
|
|
10017
|
+
}
|
|
10018
|
+
const output = this.formatJsonOutput(node.output, context);
|
|
10019
|
+
if (output)
|
|
10020
|
+
args.push(output);
|
|
10021
|
+
return `JSON_ARRAY(${args.join(' ')})`;
|
|
10022
|
+
}
|
|
9666
10023
|
JsonArrayQueryConstructor(node, context) {
|
|
9667
|
-
const
|
|
10024
|
+
const args = [];
|
|
9668
10025
|
if (node.query) {
|
|
9669
|
-
|
|
10026
|
+
args.push(this.visit(node.query, context));
|
|
10027
|
+
}
|
|
10028
|
+
const format = this.formatJsonFormat(node.format);
|
|
10029
|
+
if (format)
|
|
10030
|
+
args.push(format);
|
|
10031
|
+
const output = this.formatJsonOutput(node.output, context);
|
|
10032
|
+
if (output)
|
|
10033
|
+
args.push(output);
|
|
10034
|
+
return `JSON_ARRAY(${args.join(' ')})`;
|
|
10035
|
+
}
|
|
10036
|
+
formatJsonAggSuffix(ctor, context) {
|
|
10037
|
+
if (!ctor)
|
|
10038
|
+
return '';
|
|
10039
|
+
let result = '';
|
|
10040
|
+
if (ctor.agg_filter) {
|
|
10041
|
+
result += ` FILTER (WHERE ${this.visit(ctor.agg_filter, context)})`;
|
|
9670
10042
|
}
|
|
9671
|
-
if (
|
|
9672
|
-
|
|
10043
|
+
if (ctor.over) {
|
|
10044
|
+
result += this.formatOverClause(ctor.over, context);
|
|
9673
10045
|
}
|
|
9674
|
-
|
|
9675
|
-
|
|
10046
|
+
return result;
|
|
10047
|
+
}
|
|
10048
|
+
JsonObjectAgg(node, context) {
|
|
10049
|
+
const args = [];
|
|
10050
|
+
if (node.arg) {
|
|
10051
|
+
args.push(this.JsonKeyValue(node.arg, context));
|
|
10052
|
+
}
|
|
10053
|
+
args.push(this.formatJsonNullClause(node.absent_on_null));
|
|
10054
|
+
const unique = this.formatJsonUniqueClause(node.unique);
|
|
10055
|
+
if (unique)
|
|
10056
|
+
args.push(unique);
|
|
10057
|
+
const output = this.formatJsonOutput(node.constructor?.output, context);
|
|
10058
|
+
if (output)
|
|
10059
|
+
args.push(output);
|
|
10060
|
+
return `JSON_OBJECTAGG(${args.join(' ')})${this.formatJsonAggSuffix(node.constructor, context)}`;
|
|
10061
|
+
}
|
|
10062
|
+
JsonArrayAgg(node, context) {
|
|
10063
|
+
const args = [];
|
|
10064
|
+
if (node.arg) {
|
|
10065
|
+
args.push(this.JsonValueExpr(node.arg, context));
|
|
9676
10066
|
}
|
|
9677
|
-
|
|
9678
|
-
|
|
10067
|
+
const aggOrder = node.constructor?.agg_order;
|
|
10068
|
+
if (aggOrder && aggOrder.length > 0) {
|
|
10069
|
+
const orderItems = ListUtils.unwrapList(aggOrder).map(item => this.visit(item, context));
|
|
10070
|
+
args.push(`ORDER BY ${orderItems.join(', ')}`);
|
|
9679
10071
|
}
|
|
9680
|
-
|
|
9681
|
-
|
|
10072
|
+
args.push(this.formatJsonNullClause(node.absent_on_null));
|
|
10073
|
+
const output = this.formatJsonOutput(node.constructor?.output, context);
|
|
10074
|
+
if (output)
|
|
10075
|
+
args.push(output);
|
|
10076
|
+
return `JSON_ARRAYAGG(${args.join(' ')})${this.formatJsonAggSuffix(node.constructor, context)}`;
|
|
10077
|
+
}
|
|
10078
|
+
JsonParseExpr(node, context) {
|
|
10079
|
+
const args = [];
|
|
10080
|
+
if (node.expr) {
|
|
10081
|
+
args.push(this.JsonValueExpr(node.expr, context));
|
|
9682
10082
|
}
|
|
9683
|
-
|
|
10083
|
+
const unique = this.formatJsonUniqueClause(node.unique_keys);
|
|
10084
|
+
if (unique)
|
|
10085
|
+
args.push(unique);
|
|
10086
|
+
return `JSON(${args.join(' ')})`;
|
|
10087
|
+
}
|
|
10088
|
+
JsonScalarExpr(node, context) {
|
|
10089
|
+
const expr = node.expr ? this.visit(node.expr, context) : '';
|
|
10090
|
+
return `JSON_SCALAR(${expr})`;
|
|
10091
|
+
}
|
|
10092
|
+
JsonSerializeExpr(node, context) {
|
|
10093
|
+
const args = [];
|
|
10094
|
+
if (node.expr) {
|
|
10095
|
+
args.push(this.JsonValueExpr(node.expr, context));
|
|
10096
|
+
}
|
|
10097
|
+
const output = this.formatJsonOutput(node.output, context);
|
|
10098
|
+
if (output)
|
|
10099
|
+
args.push(output);
|
|
10100
|
+
return `JSON_SERIALIZE(${args.join(' ')})`;
|
|
10101
|
+
}
|
|
10102
|
+
JsonIsPredicate(node, context) {
|
|
10103
|
+
const parts = [];
|
|
10104
|
+
if (node.expr) {
|
|
10105
|
+
parts.push(this.visit(node.expr, context));
|
|
10106
|
+
}
|
|
10107
|
+
const format = this.formatJsonFormat(node.format);
|
|
10108
|
+
if (format)
|
|
10109
|
+
parts.push(format);
|
|
10110
|
+
parts.push('IS JSON');
|
|
10111
|
+
switch (node.item_type) {
|
|
10112
|
+
case 'JS_TYPE_OBJECT':
|
|
10113
|
+
parts.push('OBJECT');
|
|
10114
|
+
break;
|
|
10115
|
+
case 'JS_TYPE_ARRAY':
|
|
10116
|
+
parts.push('ARRAY');
|
|
10117
|
+
break;
|
|
10118
|
+
case 'JS_TYPE_SCALAR':
|
|
10119
|
+
parts.push('SCALAR');
|
|
10120
|
+
break;
|
|
10121
|
+
}
|
|
10122
|
+
if (node.unique_keys) {
|
|
10123
|
+
parts.push('WITH UNIQUE KEYS');
|
|
10124
|
+
}
|
|
10125
|
+
return parts.join(' ');
|
|
9684
10126
|
}
|
|
9685
10127
|
RangeFunction(node, context) {
|
|
9686
10128
|
const output = [];
|
|
@@ -9791,10 +10233,10 @@ export class Deparser {
|
|
|
9791
10233
|
if (node.op === 'IS_XMLPI') {
|
|
9792
10234
|
if (node.name && node.args && node.args.length > 0) {
|
|
9793
10235
|
const argStrs = ListUtils.unwrapList(node.args).map(arg => this.visit(arg, context));
|
|
9794
|
-
return `xmlpi(name ${QuoteUtils.
|
|
10236
|
+
return `xmlpi(name ${QuoteUtils.quoteIdentifier(node.name)}, ${argStrs.join(', ')})`;
|
|
9795
10237
|
}
|
|
9796
10238
|
else if (node.name) {
|
|
9797
|
-
return `xmlpi(name ${QuoteUtils.
|
|
10239
|
+
return `xmlpi(name ${QuoteUtils.quoteIdentifier(node.name)})`;
|
|
9798
10240
|
}
|
|
9799
10241
|
else {
|
|
9800
10242
|
return 'XMLPI()';
|
|
@@ -9809,7 +10251,7 @@ export class Deparser {
|
|
|
9809
10251
|
output.push('XMLELEMENT');
|
|
9810
10252
|
const elementParts = [];
|
|
9811
10253
|
if (node.name) {
|
|
9812
|
-
elementParts.push(`NAME ${QuoteUtils.
|
|
10254
|
+
elementParts.push(`NAME ${QuoteUtils.quoteIdentifier(node.name)}`);
|
|
9813
10255
|
}
|
|
9814
10256
|
if (node.named_args && node.named_args.length > 0) {
|
|
9815
10257
|
const namedArgStrs = ListUtils.unwrapList(node.named_args).map(arg => this.visit(arg, context));
|
|
@@ -9874,6 +10316,7 @@ export class Deparser {
|
|
|
9874
10316
|
rootParts.push('STANDALONE NO VALUE');
|
|
9875
10317
|
}
|
|
9876
10318
|
else if (standaloneArg.A_Const.ival.ival === 3) {
|
|
10319
|
+
// STANDALONE omitted
|
|
9877
10320
|
}
|
|
9878
10321
|
else if (Object.keys(standaloneArg.A_Const.ival).length === 0) {
|
|
9879
10322
|
rootParts.push('STANDALONE YES');
|
|
@@ -9909,7 +10352,7 @@ export class Deparser {
|
|
|
9909
10352
|
// Handle name and args for operations that don't have special handling
|
|
9910
10353
|
if (node.op !== 'IS_XMLELEMENT' && node.op !== 'IS_XMLPARSE' && node.op !== 'IS_XMLROOT' && node.op !== 'IS_DOCUMENT') {
|
|
9911
10354
|
if (node.name) {
|
|
9912
|
-
const quotedName = QuoteUtils.
|
|
10355
|
+
const quotedName = QuoteUtils.quoteIdentifier(node.name);
|
|
9913
10356
|
output.push(`NAME ${quotedName}`);
|
|
9914
10357
|
}
|
|
9915
10358
|
if (node.args && node.args.length > 0) {
|
|
@@ -9930,26 +10373,26 @@ export class Deparser {
|
|
|
9930
10373
|
}
|
|
9931
10374
|
schemaname(node, context) {
|
|
9932
10375
|
if (typeof node === 'string') {
|
|
9933
|
-
return QuoteUtils.
|
|
10376
|
+
return QuoteUtils.quoteIdentifier(node);
|
|
9934
10377
|
}
|
|
9935
10378
|
if (node && node.String && node.String.sval) {
|
|
9936
|
-
return QuoteUtils.
|
|
10379
|
+
return QuoteUtils.quoteIdentifier(node.String.sval);
|
|
9937
10380
|
}
|
|
9938
10381
|
// Handle other node types without recursion
|
|
9939
10382
|
if (node && typeof node === 'object') {
|
|
9940
10383
|
if (node.sval !== undefined) {
|
|
9941
|
-
return QuoteUtils.
|
|
10384
|
+
return QuoteUtils.quoteIdentifier(node.sval);
|
|
9942
10385
|
}
|
|
9943
10386
|
// Handle List nodes that might contain schema names
|
|
9944
10387
|
if (node.List && Array.isArray(node.List.items)) {
|
|
9945
10388
|
const items = node.List.items;
|
|
9946
10389
|
if (items.length > 0 && items[0].String && items[0].String.sval) {
|
|
9947
|
-
return QuoteUtils.
|
|
10390
|
+
return QuoteUtils.quoteIdentifier(items[0].String.sval);
|
|
9948
10391
|
}
|
|
9949
10392
|
}
|
|
9950
10393
|
// For other complex nodes, try to extract string value without recursion
|
|
9951
10394
|
if (node.val !== undefined) {
|
|
9952
|
-
return QuoteUtils.
|
|
10395
|
+
return QuoteUtils.quoteIdentifier(node.val);
|
|
9953
10396
|
}
|
|
9954
10397
|
return '';
|
|
9955
10398
|
}
|
|
@@ -10012,7 +10455,7 @@ export class Deparser {
|
|
|
10012
10455
|
}
|
|
10013
10456
|
output.push('RULE');
|
|
10014
10457
|
if (node.rulename) {
|
|
10015
|
-
output.push(QuoteUtils.
|
|
10458
|
+
output.push(QuoteUtils.quoteIdentifier(node.rulename));
|
|
10016
10459
|
}
|
|
10017
10460
|
output.push('AS ON');
|
|
10018
10461
|
if (node.event) {
|
|
@@ -10079,42 +10522,42 @@ export class Deparser {
|
|
|
10079
10522
|
}
|
|
10080
10523
|
relname(node, context) {
|
|
10081
10524
|
if (typeof node === 'string') {
|
|
10082
|
-
return QuoteUtils.
|
|
10525
|
+
return QuoteUtils.quoteIdentifier(node);
|
|
10083
10526
|
}
|
|
10084
10527
|
if (node && node.String && node.String.sval) {
|
|
10085
|
-
return QuoteUtils.
|
|
10528
|
+
return QuoteUtils.quoteIdentifier(node.String.sval);
|
|
10086
10529
|
}
|
|
10087
10530
|
if (node && typeof node === 'object' && node.relname) {
|
|
10088
|
-
return QuoteUtils.
|
|
10531
|
+
return QuoteUtils.quoteIdentifier(node.relname);
|
|
10089
10532
|
}
|
|
10090
10533
|
return this.visit(node, context);
|
|
10091
10534
|
}
|
|
10092
10535
|
rel(node, context) {
|
|
10093
10536
|
if (typeof node === 'string') {
|
|
10094
|
-
return QuoteUtils.
|
|
10537
|
+
return QuoteUtils.quoteIdentifier(node);
|
|
10095
10538
|
}
|
|
10096
10539
|
if (node && node.String && node.String.sval) {
|
|
10097
|
-
return QuoteUtils.
|
|
10540
|
+
return QuoteUtils.quoteIdentifier(node.String.sval);
|
|
10098
10541
|
}
|
|
10099
10542
|
if (node && node.RangeVar) {
|
|
10100
10543
|
return this.RangeVar(node.RangeVar, context);
|
|
10101
10544
|
}
|
|
10102
10545
|
if (node && typeof node === 'object' && node.relname) {
|
|
10103
|
-
return QuoteUtils.
|
|
10546
|
+
return QuoteUtils.quoteIdentifier(node.relname);
|
|
10104
10547
|
}
|
|
10105
10548
|
return this.visit(node, context);
|
|
10106
10549
|
}
|
|
10107
10550
|
objname(node, context) {
|
|
10108
10551
|
if (typeof node === 'string') {
|
|
10109
|
-
return QuoteUtils.
|
|
10552
|
+
return QuoteUtils.quoteIdentifier(node);
|
|
10110
10553
|
}
|
|
10111
10554
|
if (node && node.String && node.String.sval) {
|
|
10112
|
-
return QuoteUtils.
|
|
10555
|
+
return QuoteUtils.quoteIdentifier(node.String.sval);
|
|
10113
10556
|
}
|
|
10114
10557
|
if (Array.isArray(node)) {
|
|
10115
10558
|
const parts = node.map(part => {
|
|
10116
10559
|
if (part && part.String && part.String.sval) {
|
|
10117
|
-
return QuoteUtils.
|
|
10560
|
+
return QuoteUtils.quoteIdentifier(part.String.sval);
|
|
10118
10561
|
}
|
|
10119
10562
|
return this.visit(part, context);
|
|
10120
10563
|
});
|
|
@@ -10185,7 +10628,7 @@ export class Deparser {
|
|
|
10185
10628
|
CurrentOfExpr(node, context) {
|
|
10186
10629
|
const output = ['CURRENT OF'];
|
|
10187
10630
|
if (node.cursor_name) {
|
|
10188
|
-
output.push(QuoteUtils.
|
|
10631
|
+
output.push(QuoteUtils.quoteIdentifier(node.cursor_name));
|
|
10189
10632
|
}
|
|
10190
10633
|
if (node.cursor_param > 0) {
|
|
10191
10634
|
output.push(`$${node.cursor_param}`);
|
|
@@ -10268,7 +10711,7 @@ export class Deparser {
|
|
|
10268
10711
|
if (items.length === 2) {
|
|
10269
10712
|
const schemaName = items[0].String?.sval || '';
|
|
10270
10713
|
const domainName = items[1].String?.sval || '';
|
|
10271
|
-
output.push(
|
|
10714
|
+
output.push(QuoteUtils.quoteQualifiedIdentifier(schemaName, domainName));
|
|
10272
10715
|
}
|
|
10273
10716
|
else {
|
|
10274
10717
|
output.push(this.visit(node.object, context));
|
|
@@ -10280,7 +10723,7 @@ export class Deparser {
|
|
|
10280
10723
|
if (items.length === 2) {
|
|
10281
10724
|
const schemaName = items[0].String?.sval || '';
|
|
10282
10725
|
const typeName = items[1].String?.sval || '';
|
|
10283
|
-
output.push(
|
|
10726
|
+
output.push(QuoteUtils.quoteQualifiedIdentifier(schemaName, typeName));
|
|
10284
10727
|
}
|
|
10285
10728
|
else {
|
|
10286
10729
|
output.push(this.visit(node.object, context));
|
|
@@ -10292,7 +10735,7 @@ export class Deparser {
|
|
|
10292
10735
|
if (items.length === 2) {
|
|
10293
10736
|
const schemaName = items[0].String?.sval || '';
|
|
10294
10737
|
const conversionName = items[1].String?.sval || '';
|
|
10295
|
-
output.push(
|
|
10738
|
+
output.push(QuoteUtils.quoteQualifiedIdentifier(schemaName, conversionName));
|
|
10296
10739
|
}
|
|
10297
10740
|
else {
|
|
10298
10741
|
output.push(this.visit(node.object, context));
|
|
@@ -10304,7 +10747,7 @@ export class Deparser {
|
|
|
10304
10747
|
if (items.length === 2) {
|
|
10305
10748
|
const schemaName = items[0].String?.sval || '';
|
|
10306
10749
|
const parserName = items[1].String?.sval || '';
|
|
10307
|
-
output.push(
|
|
10750
|
+
output.push(QuoteUtils.quoteQualifiedIdentifier(schemaName, parserName));
|
|
10308
10751
|
}
|
|
10309
10752
|
else {
|
|
10310
10753
|
output.push(this.visit(node.object, context));
|
|
@@ -10316,7 +10759,7 @@ export class Deparser {
|
|
|
10316
10759
|
if (items.length === 2) {
|
|
10317
10760
|
const schemaName = items[0].String?.sval || '';
|
|
10318
10761
|
const configName = items[1].String?.sval || '';
|
|
10319
|
-
output.push(
|
|
10762
|
+
output.push(QuoteUtils.quoteQualifiedIdentifier(schemaName, configName));
|
|
10320
10763
|
}
|
|
10321
10764
|
else {
|
|
10322
10765
|
output.push(this.visit(node.object, context));
|
|
@@ -10328,7 +10771,7 @@ export class Deparser {
|
|
|
10328
10771
|
if (items.length === 2) {
|
|
10329
10772
|
const schemaName = items[0].String?.sval || '';
|
|
10330
10773
|
const templateName = items[1].String?.sval || '';
|
|
10331
|
-
output.push(
|
|
10774
|
+
output.push(QuoteUtils.quoteQualifiedIdentifier(schemaName, templateName));
|
|
10332
10775
|
}
|
|
10333
10776
|
else {
|
|
10334
10777
|
output.push(this.visit(node.object, context));
|
|
@@ -10340,7 +10783,7 @@ export class Deparser {
|
|
|
10340
10783
|
if (items.length === 2) {
|
|
10341
10784
|
const schemaName = items[0].String?.sval || '';
|
|
10342
10785
|
const dictionaryName = items[1].String?.sval || '';
|
|
10343
|
-
output.push(
|
|
10786
|
+
output.push(QuoteUtils.quoteQualifiedIdentifier(schemaName, dictionaryName));
|
|
10344
10787
|
}
|
|
10345
10788
|
else {
|
|
10346
10789
|
output.push(this.visit(node.object, context));
|
|
@@ -10352,13 +10795,13 @@ export class Deparser {
|
|
|
10352
10795
|
if (items.length === 2) {
|
|
10353
10796
|
const accessMethod = items[0].String?.sval || '';
|
|
10354
10797
|
const opClassName = items[1].String?.sval || '';
|
|
10355
|
-
output.push(`${QuoteUtils.
|
|
10798
|
+
output.push(`${QuoteUtils.quoteIdentifier(opClassName)} USING ${accessMethod}`);
|
|
10356
10799
|
}
|
|
10357
10800
|
else if (items.length === 3) {
|
|
10358
10801
|
const accessMethod = items[0].String?.sval || '';
|
|
10359
10802
|
const schemaName = items[1].String?.sval || '';
|
|
10360
10803
|
const opClassName = items[2].String?.sval || '';
|
|
10361
|
-
output.push(`${QuoteUtils.
|
|
10804
|
+
output.push(`${QuoteUtils.quoteQualifiedIdentifier(schemaName, opClassName)} USING ${accessMethod}`);
|
|
10362
10805
|
}
|
|
10363
10806
|
else {
|
|
10364
10807
|
output.push(this.visit(node.object, context));
|
|
@@ -10370,13 +10813,13 @@ export class Deparser {
|
|
|
10370
10813
|
if (items.length === 2) {
|
|
10371
10814
|
const accessMethod = items[0].String?.sval || '';
|
|
10372
10815
|
const opFamilyName = items[1].String?.sval || '';
|
|
10373
|
-
output.push(`${QuoteUtils.
|
|
10816
|
+
output.push(`${QuoteUtils.quoteIdentifier(opFamilyName)} USING ${accessMethod}`);
|
|
10374
10817
|
}
|
|
10375
10818
|
else if (items.length === 3) {
|
|
10376
10819
|
const accessMethod = items[0].String?.sval || '';
|
|
10377
10820
|
const schemaName = items[1].String?.sval || '';
|
|
10378
10821
|
const opFamilyName = items[2].String?.sval || '';
|
|
10379
|
-
output.push(`${QuoteUtils.
|
|
10822
|
+
output.push(`${QuoteUtils.quoteQualifiedIdentifier(schemaName, opFamilyName)} USING ${accessMethod}`);
|
|
10380
10823
|
}
|
|
10381
10824
|
else {
|
|
10382
10825
|
output.push(this.visit(node.object, context));
|
|
@@ -10388,7 +10831,7 @@ export class Deparser {
|
|
|
10388
10831
|
}
|
|
10389
10832
|
output.push('SET SCHEMA');
|
|
10390
10833
|
if (node.newschema) {
|
|
10391
|
-
output.push(QuoteUtils.
|
|
10834
|
+
output.push(QuoteUtils.quoteIdentifier(node.newschema));
|
|
10392
10835
|
}
|
|
10393
10836
|
return output.join(' ');
|
|
10394
10837
|
}
|
|
@@ -10457,7 +10900,7 @@ export class Deparser {
|
|
|
10457
10900
|
}
|
|
10458
10901
|
if (node.servername) {
|
|
10459
10902
|
output.push('SERVER');
|
|
10460
|
-
output.push(QuoteUtils.
|
|
10903
|
+
output.push(QuoteUtils.quoteIdentifier(node.servername));
|
|
10461
10904
|
}
|
|
10462
10905
|
if (node.options && node.options.length > 0) {
|
|
10463
10906
|
const foreignTableContext = context.spawn('CreateForeignTableStmt');
|
|
@@ -10466,8 +10909,4 @@ export class Deparser {
|
|
|
10466
10909
|
}
|
|
10467
10910
|
return output.join(' ');
|
|
10468
10911
|
}
|
|
10469
|
-
containsMultilineStringLiteral(content) {
|
|
10470
|
-
const stringLiteralRegex = /'[^']*\n[^']*'/g;
|
|
10471
|
-
return stringLiteralRegex.test(content);
|
|
10472
|
-
}
|
|
10473
10912
|
}
|