pgsql-deparser 18.3.7 → 18.3.9
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/deparser.d.ts +20 -25
- package/deparser.js +547 -344
- package/esm/deparser.js +547 -344
- package/package.json +2 -2
package/esm/deparser.js
CHANGED
|
@@ -2,6 +2,25 @@ import { QuoteUtils } from '@pgsql/quotes';
|
|
|
2
2
|
import { ListUtils } from './utils/list-utils';
|
|
3
3
|
import { SqlFormatter } from './utils/sql-formatter';
|
|
4
4
|
import { DeparserContext } from './visitors/base';
|
|
5
|
+
// WindowDef.frameOptions bit flags (src/include/nodes/parsenodes.h)
|
|
6
|
+
const FRAMEOPTION_NONDEFAULT = 0x00001;
|
|
7
|
+
const FRAMEOPTION_RANGE = 0x00002;
|
|
8
|
+
const FRAMEOPTION_ROWS = 0x00004;
|
|
9
|
+
const FRAMEOPTION_GROUPS = 0x00008;
|
|
10
|
+
const FRAMEOPTION_BETWEEN = 0x00010;
|
|
11
|
+
const FRAMEOPTION_START_UNBOUNDED_PRECEDING = 0x00020;
|
|
12
|
+
const FRAMEOPTION_END_UNBOUNDED_PRECEDING = 0x00040;
|
|
13
|
+
const FRAMEOPTION_START_UNBOUNDED_FOLLOWING = 0x00080;
|
|
14
|
+
const FRAMEOPTION_END_UNBOUNDED_FOLLOWING = 0x00100;
|
|
15
|
+
const FRAMEOPTION_START_CURRENT_ROW = 0x00200;
|
|
16
|
+
const FRAMEOPTION_END_CURRENT_ROW = 0x00400;
|
|
17
|
+
const FRAMEOPTION_START_OFFSET_PRECEDING = 0x00800;
|
|
18
|
+
const FRAMEOPTION_END_OFFSET_PRECEDING = 0x01000;
|
|
19
|
+
const FRAMEOPTION_START_OFFSET_FOLLOWING = 0x02000;
|
|
20
|
+
const FRAMEOPTION_END_OFFSET_FOLLOWING = 0x04000;
|
|
21
|
+
const FRAMEOPTION_EXCLUDE_CURRENT_ROW = 0x08000;
|
|
22
|
+
const FRAMEOPTION_EXCLUDE_GROUP = 0x10000;
|
|
23
|
+
const FRAMEOPTION_EXCLUDE_TIES = 0x20000;
|
|
5
24
|
/**
|
|
6
25
|
* List of real PostgreSQL built-in types as they appear in pg_catalog.pg_type.typname.
|
|
7
26
|
* These are stored in lowercase in PostgreSQL system catalogs.
|
|
@@ -100,6 +119,16 @@ function isWrappedParseResult(obj) {
|
|
|
100
119
|
* The deparser automatically detects bare ParseResult objects for backward
|
|
101
120
|
* compatibility and wraps them internally for consistent processing.
|
|
102
121
|
*/
|
|
122
|
+
function formatBitString(bsval) {
|
|
123
|
+
const quote = (value) => value.replace(/'/g, "''");
|
|
124
|
+
if (/^x[0-9A-Fa-f]+$/.test(bsval)) {
|
|
125
|
+
return `x'${bsval.substring(1)}'`;
|
|
126
|
+
}
|
|
127
|
+
if (bsval.startsWith('b')) {
|
|
128
|
+
return `b'${quote(bsval.substring(1))}'`;
|
|
129
|
+
}
|
|
130
|
+
return `b'${quote(bsval)}'`;
|
|
131
|
+
}
|
|
103
132
|
export class Deparser {
|
|
104
133
|
tree;
|
|
105
134
|
options;
|
|
@@ -981,6 +1010,12 @@ export class Deparser {
|
|
|
981
1010
|
output.push(context.parens(columnNames.join(', ')));
|
|
982
1011
|
}
|
|
983
1012
|
}
|
|
1013
|
+
if (node.override === 'OVERRIDING_USER_VALUE') {
|
|
1014
|
+
output.push('OVERRIDING USER VALUE');
|
|
1015
|
+
}
|
|
1016
|
+
else if (node.override === 'OVERRIDING_SYSTEM_VALUE') {
|
|
1017
|
+
output.push('OVERRIDING SYSTEM VALUE');
|
|
1018
|
+
}
|
|
984
1019
|
if (node.selectStmt) {
|
|
985
1020
|
output.push(this.visit(node.selectStmt, context));
|
|
986
1021
|
}
|
|
@@ -1057,38 +1092,8 @@ export class Deparser {
|
|
|
1057
1092
|
output.push(this.RangeVar(node.relation, context));
|
|
1058
1093
|
}
|
|
1059
1094
|
output.push('SET');
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
const firstTarget = targetList[0];
|
|
1063
|
-
const processedTargets = new Set();
|
|
1064
|
-
const assignmentParts = [];
|
|
1065
|
-
for (let i = 0; i < targetList.length; i++) {
|
|
1066
|
-
if (processedTargets.has(i))
|
|
1067
|
-
continue;
|
|
1068
|
-
const target = targetList[i];
|
|
1069
|
-
const multiAssignRef = target.ResTarget?.val?.MultiAssignRef;
|
|
1070
|
-
if (multiAssignRef) {
|
|
1071
|
-
const relatedTargets = [];
|
|
1072
|
-
for (let j = i; j < targetList.length; j++) {
|
|
1073
|
-
const otherTarget = targetList[j];
|
|
1074
|
-
const otherMultiAssignRef = otherTarget.ResTarget?.val?.MultiAssignRef;
|
|
1075
|
-
if (otherMultiAssignRef &&
|
|
1076
|
-
JSON.stringify(otherMultiAssignRef.source) === JSON.stringify(multiAssignRef.source)) {
|
|
1077
|
-
relatedTargets.push(otherTarget);
|
|
1078
|
-
processedTargets.add(j);
|
|
1079
|
-
}
|
|
1080
|
-
}
|
|
1081
|
-
const names = relatedTargets.map(t => t.ResTarget.name);
|
|
1082
|
-
const multiAssignment = `${context.parens(names.join(', '))} = ${this.visit(multiAssignRef.source, context)}`;
|
|
1083
|
-
assignmentParts.push(multiAssignment);
|
|
1084
|
-
}
|
|
1085
|
-
else {
|
|
1086
|
-
// Handle regular single-column assignment
|
|
1087
|
-
assignmentParts.push(this.visit(target, context.spawn('UpdateStmt', { update: true })));
|
|
1088
|
-
processedTargets.add(i);
|
|
1089
|
-
}
|
|
1090
|
-
}
|
|
1091
|
-
output.push(assignmentParts.join(','));
|
|
1095
|
+
if (node.targetList && node.targetList.length > 0) {
|
|
1096
|
+
output.push(this.formatUpdateAssignments(node.targetList, context));
|
|
1092
1097
|
}
|
|
1093
1098
|
if (node.fromClause) {
|
|
1094
1099
|
output.push('FROM');
|
|
@@ -1105,6 +1110,36 @@ export class Deparser {
|
|
|
1105
1110
|
}
|
|
1106
1111
|
return output.join(' ');
|
|
1107
1112
|
}
|
|
1113
|
+
formatUpdateAssignments(targets, context) {
|
|
1114
|
+
const targetList = ListUtils.unwrapList(targets);
|
|
1115
|
+
const processedTargets = new Set();
|
|
1116
|
+
const assignmentParts = [];
|
|
1117
|
+
for (let i = 0; i < targetList.length; i++) {
|
|
1118
|
+
if (processedTargets.has(i))
|
|
1119
|
+
continue;
|
|
1120
|
+
const target = targetList[i];
|
|
1121
|
+
const multiAssignRef = target.ResTarget?.val?.MultiAssignRef;
|
|
1122
|
+
if (multiAssignRef) {
|
|
1123
|
+
const relatedTargets = [];
|
|
1124
|
+
for (let j = i; j < targetList.length; j++) {
|
|
1125
|
+
const otherTarget = targetList[j];
|
|
1126
|
+
const otherMultiAssignRef = otherTarget.ResTarget?.val?.MultiAssignRef;
|
|
1127
|
+
if (otherMultiAssignRef &&
|
|
1128
|
+
JSON.stringify(otherMultiAssignRef.source) === JSON.stringify(multiAssignRef.source)) {
|
|
1129
|
+
relatedTargets.push(otherTarget);
|
|
1130
|
+
processedTargets.add(j);
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
const names = relatedTargets.map(t => QuoteUtils.quoteIdentifier(t.ResTarget.name));
|
|
1134
|
+
assignmentParts.push(`${context.parens(names.join(', '))} = ${this.visit(multiAssignRef.source, context)}`);
|
|
1135
|
+
}
|
|
1136
|
+
else {
|
|
1137
|
+
assignmentParts.push(this.visit(target, context.spawn('UpdateStmt', { update: true })));
|
|
1138
|
+
processedTargets.add(i);
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
return assignmentParts.join(', ');
|
|
1142
|
+
}
|
|
1108
1143
|
DeleteStmt(node, context) {
|
|
1109
1144
|
try {
|
|
1110
1145
|
const output = [];
|
|
@@ -1517,43 +1552,41 @@ export class Deparser {
|
|
|
1517
1552
|
result += ` FILTER (WHERE ${this.visit(node.agg_filter, context)})`;
|
|
1518
1553
|
}
|
|
1519
1554
|
if (node.over) {
|
|
1520
|
-
|
|
1521
|
-
if (node.over.name) {
|
|
1522
|
-
result += ` OVER ${node.over.name}`;
|
|
1523
|
-
}
|
|
1524
|
-
else {
|
|
1525
|
-
const windowParts = [];
|
|
1526
|
-
if (node.over.partitionClause) {
|
|
1527
|
-
const partitions = ListUtils.unwrapList(node.over.partitionClause);
|
|
1528
|
-
const partitionStrs = partitions.map(p => this.visit(p, context));
|
|
1529
|
-
windowParts.push(`PARTITION BY ${partitionStrs.join(', ')}`);
|
|
1530
|
-
}
|
|
1531
|
-
if (node.over.orderClause) {
|
|
1532
|
-
const orders = ListUtils.unwrapList(node.over.orderClause);
|
|
1533
|
-
const orderStrs = orders.map(o => this.visit(o, context));
|
|
1534
|
-
windowParts.push(`ORDER BY ${orderStrs.join(', ')}`);
|
|
1535
|
-
}
|
|
1536
|
-
// Handle window frame specifications using the dedicated formatWindowFrame method
|
|
1537
|
-
const frameClause = this.formatWindowFrame(node.over, context.spawn('FuncCall'));
|
|
1538
|
-
if (frameClause) {
|
|
1539
|
-
windowParts.push(frameClause);
|
|
1540
|
-
}
|
|
1541
|
-
if (windowParts.length > 0) {
|
|
1542
|
-
if (context.isPretty() && windowParts.length > 1) {
|
|
1543
|
-
const formattedParts = windowParts.map(part => context.indent(part));
|
|
1544
|
-
result += ` OVER (${context.newline()}${formattedParts.join(context.newline())}${context.newline()})`;
|
|
1545
|
-
}
|
|
1546
|
-
else {
|
|
1547
|
-
result += ` OVER (${windowParts.join(' ')})`;
|
|
1548
|
-
}
|
|
1549
|
-
}
|
|
1550
|
-
else {
|
|
1551
|
-
result += ` OVER ()`;
|
|
1552
|
-
}
|
|
1553
|
-
}
|
|
1555
|
+
result += this.formatOverClause(node.over, context);
|
|
1554
1556
|
}
|
|
1555
1557
|
return result;
|
|
1556
1558
|
}
|
|
1559
|
+
formatOverClause(over, context) {
|
|
1560
|
+
if (over.name) {
|
|
1561
|
+
return ` OVER ${over.name}`;
|
|
1562
|
+
}
|
|
1563
|
+
const windowParts = [];
|
|
1564
|
+
if (over.refname) {
|
|
1565
|
+
windowParts.push(over.refname);
|
|
1566
|
+
}
|
|
1567
|
+
if (over.partitionClause) {
|
|
1568
|
+
const partitions = ListUtils.unwrapList(over.partitionClause);
|
|
1569
|
+
const partitionStrs = partitions.map(p => this.visit(p, context));
|
|
1570
|
+
windowParts.push(`PARTITION BY ${partitionStrs.join(', ')}`);
|
|
1571
|
+
}
|
|
1572
|
+
if (over.orderClause) {
|
|
1573
|
+
const orders = ListUtils.unwrapList(over.orderClause);
|
|
1574
|
+
const orderStrs = orders.map(o => this.visit(o, context));
|
|
1575
|
+
windowParts.push(`ORDER BY ${orderStrs.join(', ')}`);
|
|
1576
|
+
}
|
|
1577
|
+
const frameClause = this.formatWindowFrame(over, context.spawn('FuncCall'));
|
|
1578
|
+
if (frameClause) {
|
|
1579
|
+
windowParts.push(frameClause);
|
|
1580
|
+
}
|
|
1581
|
+
if (windowParts.length === 0) {
|
|
1582
|
+
return ' OVER ()';
|
|
1583
|
+
}
|
|
1584
|
+
if (context.isPretty() && windowParts.length > 1) {
|
|
1585
|
+
const formattedParts = windowParts.map(part => context.indent(part));
|
|
1586
|
+
return ` OVER (${context.newline()}${formattedParts.join(context.newline())}${context.newline()})`;
|
|
1587
|
+
}
|
|
1588
|
+
return ` OVER (${windowParts.join(' ')})`;
|
|
1589
|
+
}
|
|
1557
1590
|
FuncExpr(node, context) {
|
|
1558
1591
|
const funcName = `func_${node.funcid}`;
|
|
1559
1592
|
const args = node.args ? ListUtils.unwrapList(node.args).map(arg => this.visit(arg, context)).join(', ') : '';
|
|
@@ -1643,15 +1676,7 @@ export class Deparser {
|
|
|
1643
1676
|
else if (nodeAny.bsval !== undefined) {
|
|
1644
1677
|
if (typeof nodeAny.bsval === 'object' && nodeAny.bsval !== null) {
|
|
1645
1678
|
if (nodeAny.bsval.bsval !== undefined) {
|
|
1646
|
-
|
|
1647
|
-
// Check if this is a hexadecimal bit string (starts with x and contains only hex digits)
|
|
1648
|
-
if (bsval.startsWith('x') && /^x[0-9A-Fa-f]+$/.test(bsval)) {
|
|
1649
|
-
return `x'${bsval.substring(1)}'`;
|
|
1650
|
-
}
|
|
1651
|
-
if (bsval.startsWith('b')) {
|
|
1652
|
-
return `b'${bsval.substring(1)}'`;
|
|
1653
|
-
}
|
|
1654
|
-
return `b'${bsval}'`;
|
|
1679
|
+
return formatBitString(nodeAny.bsval.bsval);
|
|
1655
1680
|
}
|
|
1656
1681
|
else if (Object.keys(nodeAny.bsval).length === 0) {
|
|
1657
1682
|
return "''";
|
|
@@ -1664,15 +1689,7 @@ export class Deparser {
|
|
|
1664
1689
|
return 'NULL';
|
|
1665
1690
|
}
|
|
1666
1691
|
else {
|
|
1667
|
-
|
|
1668
|
-
// Check if this is a hexadecimal bit string (starts with x and contains only hex digits)
|
|
1669
|
-
if (bsval.startsWith('x') && /^x[0-9A-Fa-f]+$/.test(bsval)) {
|
|
1670
|
-
return `x'${bsval.substring(1)}'`;
|
|
1671
|
-
}
|
|
1672
|
-
if (bsval.startsWith('b')) {
|
|
1673
|
-
return `b'${bsval.substring(1)}'`;
|
|
1674
|
-
}
|
|
1675
|
-
return `b'${bsval}'`;
|
|
1692
|
+
return formatBitString(nodeAny.bsval);
|
|
1676
1693
|
}
|
|
1677
1694
|
}
|
|
1678
1695
|
if (nodeAny.val) {
|
|
@@ -1689,7 +1706,7 @@ export class Deparser {
|
|
|
1689
1706
|
return nodeAny.val.Boolean.boolval ? 'true' : 'false';
|
|
1690
1707
|
}
|
|
1691
1708
|
else if (nodeAny.val.BitString?.bsval !== undefined) {
|
|
1692
|
-
return nodeAny.val.BitString.bsval;
|
|
1709
|
+
return formatBitString(nodeAny.val.BitString.bsval);
|
|
1693
1710
|
}
|
|
1694
1711
|
}
|
|
1695
1712
|
if (nodeAny.isnull === true) {
|
|
@@ -2369,15 +2386,7 @@ export class Deparser {
|
|
|
2369
2386
|
return node.boolval ? 'true' : 'false';
|
|
2370
2387
|
}
|
|
2371
2388
|
BitString(node, context) {
|
|
2372
|
-
|
|
2373
|
-
if (node.bsval.startsWith('x')) {
|
|
2374
|
-
return `x'${node.bsval.substring(1)}'`;
|
|
2375
|
-
}
|
|
2376
|
-
if (node.bsval.startsWith('b')) {
|
|
2377
|
-
return `b'${node.bsval.substring(1)}'`;
|
|
2378
|
-
}
|
|
2379
|
-
// Fallback for raw values without prefix
|
|
2380
|
-
return `b'${node.bsval}'`;
|
|
2389
|
+
return formatBitString(node.bsval);
|
|
2381
2390
|
}
|
|
2382
2391
|
Null(node, context) {
|
|
2383
2392
|
return 'NULL';
|
|
@@ -2416,7 +2425,7 @@ export class Deparser {
|
|
|
2416
2425
|
output.push(context.parens(elementStrs.join(', ')));
|
|
2417
2426
|
}
|
|
2418
2427
|
}
|
|
2419
|
-
else if (node.tableElts) {
|
|
2428
|
+
else if (node.tableElts && !node.partbound) {
|
|
2420
2429
|
const elements = ListUtils.unwrapList(node.tableElts);
|
|
2421
2430
|
const elementStrs = elements.map(el => {
|
|
2422
2431
|
return this.deparse(el, context.spawn('CreateStmt'));
|
|
@@ -2444,7 +2453,16 @@ export class Deparser {
|
|
|
2444
2453
|
const inherits = ListUtils.unwrapList(node.inhRelations);
|
|
2445
2454
|
const inheritStrs = inherits.map(rel => this.visit(rel, context));
|
|
2446
2455
|
output.push(inheritStrs[0]);
|
|
2447
|
-
if (node.
|
|
2456
|
+
if (node.tableElts) {
|
|
2457
|
+
const elementStrs = ListUtils.unwrapList(node.tableElts).map(el => {
|
|
2458
|
+
return this.deparse(el, context.spawn('CreateStmt'));
|
|
2459
|
+
});
|
|
2460
|
+
output.push(context.parens(elementStrs.join(', ')));
|
|
2461
|
+
}
|
|
2462
|
+
if (node.partbound.is_default) {
|
|
2463
|
+
output.push('DEFAULT');
|
|
2464
|
+
}
|
|
2465
|
+
else if (node.partbound.strategy === 'l' && node.partbound.listdatums) {
|
|
2448
2466
|
output.push('FOR VALUES IN');
|
|
2449
2467
|
const listValues = ListUtils.unwrapList(node.partbound.listdatums)
|
|
2450
2468
|
.map(datum => this.visit(datum, context))
|
|
@@ -2467,13 +2485,9 @@ export class Deparser {
|
|
|
2467
2485
|
output.push(`(${upperValues})`);
|
|
2468
2486
|
}
|
|
2469
2487
|
}
|
|
2470
|
-
else if (node.partbound.strategy === 'h'
|
|
2488
|
+
else if (node.partbound.strategy === 'h') {
|
|
2471
2489
|
output.push('FOR VALUES WITH');
|
|
2472
|
-
|
|
2473
|
-
output.push(`(MODULUS ${node.partbound.modulus}, REMAINDER ${remainder})`);
|
|
2474
|
-
}
|
|
2475
|
-
else if (node.partbound.is_default) {
|
|
2476
|
-
output.push('DEFAULT');
|
|
2490
|
+
output.push(`(MODULUS ${node.partbound.modulus ?? 0}, REMAINDER ${node.partbound.remainder ?? 0})`);
|
|
2477
2491
|
}
|
|
2478
2492
|
}
|
|
2479
2493
|
else if (node.inhRelations) {
|
|
@@ -2539,6 +2553,12 @@ export class Deparser {
|
|
|
2539
2553
|
if (node.typeName) {
|
|
2540
2554
|
output.push(this.TypeName(node.typeName, context));
|
|
2541
2555
|
}
|
|
2556
|
+
if (node.storage_name) {
|
|
2557
|
+
output.push('STORAGE', node.storage_name.toUpperCase());
|
|
2558
|
+
}
|
|
2559
|
+
if (node.compression) {
|
|
2560
|
+
output.push('COMPRESSION', QuoteUtils.quoteIdentifier(node.compression));
|
|
2561
|
+
}
|
|
2542
2562
|
if (node.fdwoptions && node.fdwoptions.length > 0) {
|
|
2543
2563
|
output.push('OPTIONS');
|
|
2544
2564
|
const columnContext = context.spawn('ColumnDef');
|
|
@@ -2599,7 +2619,8 @@ export class Deparser {
|
|
|
2599
2619
|
case 'CONSTR_DEFAULT':
|
|
2600
2620
|
output.push('DEFAULT');
|
|
2601
2621
|
if (node.raw_expr) {
|
|
2602
|
-
|
|
2622
|
+
const defaultExpr = this.visit(node.raw_expr, context);
|
|
2623
|
+
output.push(this.needsBExprParens(node.raw_expr) ? `(${defaultExpr})` : defaultExpr);
|
|
2603
2624
|
}
|
|
2604
2625
|
break;
|
|
2605
2626
|
case 'CONSTR_CHECK':
|
|
@@ -2963,7 +2984,7 @@ export class Deparser {
|
|
|
2963
2984
|
break;
|
|
2964
2985
|
}
|
|
2965
2986
|
// Handle deferrable constraints for all constraint types that support it
|
|
2966
|
-
if (node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_FOREIGN') {
|
|
2987
|
+
if (node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_FOREIGN' || node.contype === 'CONSTR_EXCLUSION') {
|
|
2967
2988
|
if (node.deferrable) {
|
|
2968
2989
|
if (context.isPretty() && node.contype === 'CONSTR_FOREIGN') {
|
|
2969
2990
|
output.push('\n' + context.indent('DEFERRABLE'));
|
|
@@ -2992,6 +3013,9 @@ export class Deparser {
|
|
|
2992
3013
|
output.push('NOT DEFERRABLE');
|
|
2993
3014
|
}
|
|
2994
3015
|
}
|
|
3016
|
+
else if (node.initdeferred) {
|
|
3017
|
+
output.push('INITIALLY DEFERRED');
|
|
3018
|
+
}
|
|
2995
3019
|
}
|
|
2996
3020
|
if (context.isPretty() && node.contype === 'CONSTR_FOREIGN') {
|
|
2997
3021
|
let result = '';
|
|
@@ -3057,6 +3081,9 @@ export class Deparser {
|
|
|
3057
3081
|
output.push(node.name);
|
|
3058
3082
|
}
|
|
3059
3083
|
const windowParts = [];
|
|
3084
|
+
if (node.refname) {
|
|
3085
|
+
windowParts.push(node.refname);
|
|
3086
|
+
}
|
|
3060
3087
|
if (node.partitionClause) {
|
|
3061
3088
|
const partitions = ListUtils.unwrapList(node.partitionClause);
|
|
3062
3089
|
const partitionStrs = partitions.map(p => this.visit(p, context));
|
|
@@ -3067,12 +3094,9 @@ export class Deparser {
|
|
|
3067
3094
|
const orderStrs = orders.map(o => this.visit(o, context));
|
|
3068
3095
|
windowParts.push(`ORDER BY ${orderStrs.join(', ')}`);
|
|
3069
3096
|
}
|
|
3070
|
-
|
|
3071
|
-
if (
|
|
3072
|
-
|
|
3073
|
-
if (frameClause) {
|
|
3074
|
-
windowParts.push(frameClause);
|
|
3075
|
-
}
|
|
3097
|
+
const frameClause = this.formatWindowFrame(node, context.spawn('WindowDef'));
|
|
3098
|
+
if (frameClause) {
|
|
3099
|
+
windowParts.push(frameClause);
|
|
3076
3100
|
}
|
|
3077
3101
|
if (windowParts.length > 0) {
|
|
3078
3102
|
if (node.name) {
|
|
@@ -3089,114 +3113,96 @@ export class Deparser {
|
|
|
3089
3113
|
}
|
|
3090
3114
|
return output.join(' ');
|
|
3091
3115
|
}
|
|
3116
|
+
formatIdentityColumnOptions(def, context) {
|
|
3117
|
+
const seqContext = context.spawn('AlterSeqStmt');
|
|
3118
|
+
return ListUtils.unwrapList(def).map(item => {
|
|
3119
|
+
const el = item.DefElem;
|
|
3120
|
+
if (!el)
|
|
3121
|
+
return this.visit(item, context);
|
|
3122
|
+
if (el.defname === 'generated') {
|
|
3123
|
+
const ival = el.arg?.Integer?.ival ?? 0;
|
|
3124
|
+
return ival === 97 ? 'SET GENERATED ALWAYS' : 'SET GENERATED BY DEFAULT';
|
|
3125
|
+
}
|
|
3126
|
+
if (el.defname === 'restart') {
|
|
3127
|
+
return el.arg ? `RESTART WITH ${this.visit(el.arg, context)}` : 'RESTART';
|
|
3128
|
+
}
|
|
3129
|
+
return `SET ${this.visit(item, seqContext)}`;
|
|
3130
|
+
}).join(' ');
|
|
3131
|
+
}
|
|
3132
|
+
// b_expr (used by DEFAULT) excludes IN/LIKE/BETWEEN and boolean operators.
|
|
3133
|
+
needsBExprParens(node) {
|
|
3134
|
+
const nodeType = this.getNodeType(node);
|
|
3135
|
+
if (nodeType === 'BoolExpr')
|
|
3136
|
+
return true;
|
|
3137
|
+
if (nodeType === 'A_Expr') {
|
|
3138
|
+
const kind = this.getNodeData(node).kind;
|
|
3139
|
+
return kind !== 'AEXPR_OP' && kind !== 'AEXPR_DISTINCT' && kind !== 'AEXPR_NOT_DISTINCT';
|
|
3140
|
+
}
|
|
3141
|
+
return false;
|
|
3142
|
+
}
|
|
3092
3143
|
formatWindowFrame(node, context) {
|
|
3093
|
-
if (!node.frameOptions)
|
|
3144
|
+
if (!node.frameOptions || !(node.frameOptions & FRAMEOPTION_NONDEFAULT))
|
|
3094
3145
|
return null;
|
|
3095
3146
|
const frameOptions = node.frameOptions;
|
|
3096
|
-
const EXCLUDE_MASK = 0x8000 | 0x10000 | 0x20000;
|
|
3097
|
-
const baseFrameOptions = frameOptions & ~EXCLUDE_MASK;
|
|
3098
3147
|
const frameParts = [];
|
|
3099
|
-
if (frameOptions &
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
frameParts.push('GROUPS');
|
|
3108
|
-
}
|
|
3148
|
+
if (frameOptions & FRAMEOPTION_RANGE) {
|
|
3149
|
+
frameParts.push('RANGE');
|
|
3150
|
+
}
|
|
3151
|
+
else if (frameOptions & FRAMEOPTION_ROWS) {
|
|
3152
|
+
frameParts.push('ROWS');
|
|
3153
|
+
}
|
|
3154
|
+
else if (frameOptions & FRAMEOPTION_GROUPS) {
|
|
3155
|
+
frameParts.push('GROUPS');
|
|
3109
3156
|
}
|
|
3110
3157
|
if (frameParts.length === 0)
|
|
3111
3158
|
return null;
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
boundsParts.push('CURRENT ROW');
|
|
3116
|
-
boundsParts.push('AND UNBOUNDED FOLLOWING');
|
|
3159
|
+
let start = null;
|
|
3160
|
+
if (frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING) {
|
|
3161
|
+
start = 'UNBOUNDED PRECEDING';
|
|
3117
3162
|
}
|
|
3118
|
-
else if (
|
|
3119
|
-
|
|
3120
|
-
boundsParts.push('AND CURRENT ROW');
|
|
3163
|
+
else if (frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING) {
|
|
3164
|
+
start = 'UNBOUNDED FOLLOWING';
|
|
3121
3165
|
}
|
|
3122
|
-
else if (
|
|
3123
|
-
|
|
3124
|
-
boundsParts.push(`${this.visit(node.startOffset, context)} PRECEDING`);
|
|
3125
|
-
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
3126
|
-
}
|
|
3166
|
+
else if (frameOptions & FRAMEOPTION_START_CURRENT_ROW) {
|
|
3167
|
+
start = 'CURRENT ROW';
|
|
3127
3168
|
}
|
|
3128
|
-
else if (
|
|
3129
|
-
|
|
3130
|
-
boundsParts.push('AND CURRENT ROW');
|
|
3169
|
+
else if (frameOptions & FRAMEOPTION_START_OFFSET_PRECEDING && node.startOffset) {
|
|
3170
|
+
start = `${this.visit(node.startOffset, context)} PRECEDING`;
|
|
3131
3171
|
}
|
|
3132
|
-
else if (
|
|
3133
|
-
|
|
3134
|
-
if (node.endOffset) {
|
|
3135
|
-
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
3136
|
-
}
|
|
3172
|
+
else if (frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING && node.startOffset) {
|
|
3173
|
+
start = `${this.visit(node.startOffset, context)} FOLLOWING`;
|
|
3137
3174
|
}
|
|
3138
|
-
|
|
3139
|
-
|
|
3175
|
+
let end = null;
|
|
3176
|
+
if (frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING) {
|
|
3177
|
+
end = 'UNBOUNDED PRECEDING';
|
|
3140
3178
|
}
|
|
3141
|
-
else {
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
}
|
|
3157
|
-
else if (frameOptions & 0x20) { // FRAMEOPTION_START_CURRENT_ROW
|
|
3158
|
-
boundsParts.push('CURRENT ROW');
|
|
3159
|
-
}
|
|
3160
|
-
// Handle end bound - prioritize explicit offset values over bit flags
|
|
3161
|
-
if (node.endOffset) {
|
|
3162
|
-
if (boundsParts.length > 0) {
|
|
3163
|
-
if (frameOptions & 0x1000) { // FRAMEOPTION_END_VALUE_PRECEDING
|
|
3164
|
-
boundsParts.push(`AND ${this.visit(node.endOffset, context)} PRECEDING`);
|
|
3165
|
-
}
|
|
3166
|
-
else if (frameOptions & 0x2000) { // FRAMEOPTION_END_VALUE_FOLLOWING
|
|
3167
|
-
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
3168
|
-
}
|
|
3169
|
-
else {
|
|
3170
|
-
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
3171
|
-
}
|
|
3172
|
-
}
|
|
3173
|
-
}
|
|
3174
|
-
else if (frameOptions & 0x80) { // FRAMEOPTION_END_UNBOUNDED_FOLLOWING
|
|
3175
|
-
if (boundsParts.length > 0) {
|
|
3176
|
-
boundsParts.push('AND UNBOUNDED FOLLOWING');
|
|
3177
|
-
}
|
|
3178
|
-
}
|
|
3179
|
-
else if (frameOptions & 0x100) { // FRAMEOPTION_END_CURRENT_ROW
|
|
3180
|
-
if (boundsParts.length > 0) {
|
|
3181
|
-
boundsParts.push('AND CURRENT ROW');
|
|
3182
|
-
}
|
|
3179
|
+
else if (frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING) {
|
|
3180
|
+
end = 'UNBOUNDED FOLLOWING';
|
|
3181
|
+
}
|
|
3182
|
+
else if (frameOptions & FRAMEOPTION_END_CURRENT_ROW) {
|
|
3183
|
+
end = 'CURRENT ROW';
|
|
3184
|
+
}
|
|
3185
|
+
else if (frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING && node.endOffset) {
|
|
3186
|
+
end = `${this.visit(node.endOffset, context)} PRECEDING`;
|
|
3187
|
+
}
|
|
3188
|
+
else if (frameOptions & FRAMEOPTION_END_OFFSET_FOLLOWING && node.endOffset) {
|
|
3189
|
+
end = `${this.visit(node.endOffset, context)} FOLLOWING`;
|
|
3190
|
+
}
|
|
3191
|
+
if (start) {
|
|
3192
|
+
if (frameOptions & FRAMEOPTION_BETWEEN) {
|
|
3193
|
+
frameParts.push(`BETWEEN ${start} AND ${end ?? 'CURRENT ROW'}`);
|
|
3183
3194
|
}
|
|
3184
|
-
else
|
|
3185
|
-
|
|
3195
|
+
else {
|
|
3196
|
+
frameParts.push(start);
|
|
3186
3197
|
}
|
|
3187
3198
|
}
|
|
3188
|
-
if (
|
|
3189
|
-
frameParts.push('BETWEEN');
|
|
3190
|
-
frameParts.push(boundsParts.join(' '));
|
|
3191
|
-
}
|
|
3192
|
-
// EXCLUDE clause
|
|
3193
|
-
if (frameOptions & 0x8000) { // FRAMEOPTION_EXCLUDE_CURRENT_ROW
|
|
3199
|
+
if (frameOptions & FRAMEOPTION_EXCLUDE_CURRENT_ROW) {
|
|
3194
3200
|
frameParts.push('EXCLUDE CURRENT ROW');
|
|
3195
3201
|
}
|
|
3196
|
-
else if (frameOptions &
|
|
3202
|
+
else if (frameOptions & FRAMEOPTION_EXCLUDE_GROUP) {
|
|
3197
3203
|
frameParts.push('EXCLUDE GROUP');
|
|
3198
3204
|
}
|
|
3199
|
-
else if (frameOptions &
|
|
3205
|
+
else if (frameOptions & FRAMEOPTION_EXCLUDE_TIES) {
|
|
3200
3206
|
frameParts.push('EXCLUDE TIES');
|
|
3201
3207
|
}
|
|
3202
3208
|
return frameParts.join(' ');
|
|
@@ -3275,8 +3281,35 @@ export class Deparser {
|
|
|
3275
3281
|
if (node.ctequery) {
|
|
3276
3282
|
output.push(context.parens(this.visit(node.ctequery, context)));
|
|
3277
3283
|
}
|
|
3284
|
+
if (node.search_clause) {
|
|
3285
|
+
const sc = node.search_clause;
|
|
3286
|
+
const cols = ListUtils.unwrapList(sc.search_col_list).map(c => this.visit(c, context));
|
|
3287
|
+
output.push('SEARCH', sc.search_breadth_first ? 'BREADTH' : 'DEPTH', 'FIRST BY');
|
|
3288
|
+
output.push(cols.join(', '));
|
|
3289
|
+
output.push('SET', QuoteUtils.quoteIdentifier(sc.search_seq_column));
|
|
3290
|
+
}
|
|
3291
|
+
if (node.cycle_clause) {
|
|
3292
|
+
const cc = node.cycle_clause;
|
|
3293
|
+
const cols = ListUtils.unwrapList(cc.cycle_col_list).map(c => this.visit(c, context));
|
|
3294
|
+
output.push('CYCLE', cols.join(', '));
|
|
3295
|
+
output.push('SET', QuoteUtils.quoteIdentifier(cc.cycle_mark_column));
|
|
3296
|
+
if (cc.cycle_mark_value && cc.cycle_mark_default) {
|
|
3297
|
+
output.push('TO', this.formatAexprConst(cc.cycle_mark_value, context));
|
|
3298
|
+
output.push('DEFAULT', this.formatAexprConst(cc.cycle_mark_default, context));
|
|
3299
|
+
}
|
|
3300
|
+
output.push('USING', QuoteUtils.quoteIdentifier(cc.cycle_path_column));
|
|
3301
|
+
}
|
|
3278
3302
|
return output.join(' ');
|
|
3279
3303
|
}
|
|
3304
|
+
// Renders a constant in the restricted AexprConst grammar (e.g. `point '(1,1)'`
|
|
3305
|
+
// rather than `CAST('(1,1)' AS point)`).
|
|
3306
|
+
formatAexprConst(node, context) {
|
|
3307
|
+
const cast = node.TypeCast;
|
|
3308
|
+
if (cast?.arg?.A_Const?.sval && cast.typeName) {
|
|
3309
|
+
return `${this.TypeName(cast.typeName, context)} ${this.visit(cast.arg, context)}`;
|
|
3310
|
+
}
|
|
3311
|
+
return this.visit(node, context);
|
|
3312
|
+
}
|
|
3280
3313
|
ParamRef(node, context) {
|
|
3281
3314
|
return `$${node.number}`;
|
|
3282
3315
|
}
|
|
@@ -3666,9 +3699,9 @@ export class Deparser {
|
|
|
3666
3699
|
output.push(`(${upperValues})`);
|
|
3667
3700
|
}
|
|
3668
3701
|
}
|
|
3669
|
-
else if (node.bound.strategy === 'h'
|
|
3702
|
+
else if (node.bound.strategy === 'h') {
|
|
3670
3703
|
output.push('FOR VALUES WITH');
|
|
3671
|
-
output.push(`(MODULUS ${node.bound.modulus}, REMAINDER ${node.bound.remainder ?? 0})`);
|
|
3704
|
+
output.push(`(MODULUS ${node.bound.modulus ?? 0}, REMAINDER ${node.bound.remainder ?? 0})`);
|
|
3672
3705
|
}
|
|
3673
3706
|
else if (node.bound.is_default) {
|
|
3674
3707
|
output.push('DEFAULT');
|
|
@@ -4521,10 +4554,10 @@ export class Deparser {
|
|
|
4521
4554
|
output.push('PROGRAM');
|
|
4522
4555
|
}
|
|
4523
4556
|
if (node.filename) {
|
|
4524
|
-
output.push(
|
|
4557
|
+
output.push(QuoteUtils.escape(node.filename));
|
|
4525
4558
|
}
|
|
4526
4559
|
else {
|
|
4527
|
-
output.push('STDIN');
|
|
4560
|
+
output.push(node.is_from ? 'STDIN' : 'STDOUT');
|
|
4528
4561
|
}
|
|
4529
4562
|
if (node.options && node.options.length > 0) {
|
|
4530
4563
|
output.push('WITH');
|
|
@@ -4756,6 +4789,9 @@ export class Deparser {
|
|
|
4756
4789
|
const nodeData = this.getNodeData(node.def);
|
|
4757
4790
|
if (nodeData && nodeData.typeName) {
|
|
4758
4791
|
output.push(this.TypeName(nodeData.typeName, context));
|
|
4792
|
+
if (nodeData.collClause) {
|
|
4793
|
+
output.push(this.CollateClause(nodeData.collClause, context));
|
|
4794
|
+
}
|
|
4759
4795
|
// Handle USING clause (stored in raw_default for ALTER COLUMN TYPE)
|
|
4760
4796
|
if (nodeData.raw_default) {
|
|
4761
4797
|
output.push('USING');
|
|
@@ -5236,9 +5272,8 @@ export class Deparser {
|
|
|
5236
5272
|
if (node.name) {
|
|
5237
5273
|
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
5238
5274
|
}
|
|
5239
|
-
output.push('SET');
|
|
5240
5275
|
if (node.def) {
|
|
5241
|
-
output.push(this.
|
|
5276
|
+
output.push(this.formatIdentityColumnOptions(node.def, context));
|
|
5242
5277
|
}
|
|
5243
5278
|
break;
|
|
5244
5279
|
case 'AT_DropIdentity':
|
|
@@ -5247,11 +5282,8 @@ export class Deparser {
|
|
|
5247
5282
|
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
5248
5283
|
}
|
|
5249
5284
|
output.push('DROP IDENTITY');
|
|
5250
|
-
if (node.
|
|
5251
|
-
output.push('
|
|
5252
|
-
}
|
|
5253
|
-
else if (node.behavior === 'DROP_RESTRICT') {
|
|
5254
|
-
output.push('RESTRICT');
|
|
5285
|
+
if (node.missing_ok) {
|
|
5286
|
+
output.push('IF EXISTS');
|
|
5255
5287
|
}
|
|
5256
5288
|
break;
|
|
5257
5289
|
case 'AT_ReAddStatistics':
|
|
@@ -5687,6 +5719,9 @@ export class Deparser {
|
|
|
5687
5719
|
if (node.arg && this.getNodeType(node.arg) === 'List') {
|
|
5688
5720
|
const listData = this.getNodeData(node.arg);
|
|
5689
5721
|
const listItems = ListUtils.unwrapList(listData.items);
|
|
5722
|
+
if (listItems.length === 1 && listItems[0].String?.sval === 'none') {
|
|
5723
|
+
return 'OWNED BY NONE';
|
|
5724
|
+
}
|
|
5690
5725
|
const parts = listItems.map(item => {
|
|
5691
5726
|
const itemData = this.getNodeData(item);
|
|
5692
5727
|
if (this.getNodeType(item) === 'String') {
|
|
@@ -5864,12 +5899,15 @@ export class Deparser {
|
|
|
5864
5899
|
}
|
|
5865
5900
|
// Handle CreateStmt table options - no quotes, compact formatting
|
|
5866
5901
|
if (context.parentNodeTypes.includes('CreateStmt')) {
|
|
5902
|
+
const relOptName = node.defnamespace
|
|
5903
|
+
? `${QuoteUtils.quoteIdentifier(node.defnamespace)}.${QuoteUtils.quoteIdentifier(node.defname)}`
|
|
5904
|
+
: QuoteUtils.quoteIdentifier(node.defname);
|
|
5867
5905
|
// For numeric values, use the raw value without quotes
|
|
5868
5906
|
if (node.arg && this.getNodeType(node.arg) === 'Integer') {
|
|
5869
5907
|
const integerData = this.getNodeData(node.arg);
|
|
5870
|
-
return `${
|
|
5908
|
+
return `${relOptName}=${integerData.ival}`;
|
|
5871
5909
|
}
|
|
5872
|
-
return `${
|
|
5910
|
+
return `${relOptName}=${argValue}`;
|
|
5873
5911
|
}
|
|
5874
5912
|
// Handle CreateEventTrigStmt WHEN clause - use IN syntax for List arguments
|
|
5875
5913
|
if (context.parentNodeTypes.includes('CreateEventTrigStmt')) {
|
|
@@ -5908,15 +5946,27 @@ export class Deparser {
|
|
|
5908
5946
|
}
|
|
5909
5947
|
// Handle CopyStmt WITH clause options - uppercase format without quotes
|
|
5910
5948
|
if (context.parentNodeTypes.includes('CopyStmt')) {
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
return
|
|
5949
|
+
const optName = node.defname.toUpperCase();
|
|
5950
|
+
if (!node.arg) {
|
|
5951
|
+
return optName;
|
|
5952
|
+
}
|
|
5953
|
+
const copyArgType = this.getNodeType(node.arg);
|
|
5954
|
+
if (copyArgType === 'Boolean' && this.getNodeData(node.arg).boolval !== false) {
|
|
5955
|
+
return optName;
|
|
5956
|
+
}
|
|
5957
|
+
if (copyArgType === 'List') {
|
|
5958
|
+
const items = ListUtils.unwrapList(this.getNodeData(node.arg).items)
|
|
5959
|
+
.map(item => this.visit(item, context));
|
|
5960
|
+
return `${optName} (${items.join(', ')})`;
|
|
5914
5961
|
}
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
|
|
5962
|
+
if (copyArgType === 'String') {
|
|
5963
|
+
const sval = this.getNodeData(node.arg).sval;
|
|
5964
|
+
if (node.defname === 'format') {
|
|
5965
|
+
return `${optName} ${sval}`;
|
|
5966
|
+
}
|
|
5967
|
+
return `${optName} ${QuoteUtils.escape(sval)}`;
|
|
5918
5968
|
}
|
|
5919
|
-
return
|
|
5969
|
+
return `${optName} ${argValue}`;
|
|
5920
5970
|
}
|
|
5921
5971
|
// Handle CREATE OPERATOR and CREATE TYPE context
|
|
5922
5972
|
if (context.parentNodeTypes.includes('DefineStmt')) {
|
|
@@ -5997,6 +6047,10 @@ export class Deparser {
|
|
|
5997
6047
|
return `${node.defname} = ${argValue}`;
|
|
5998
6048
|
}
|
|
5999
6049
|
}
|
|
6050
|
+
const argType = this.getNodeType(node.arg);
|
|
6051
|
+
if (argType === 'TypeName' || argType === 'Integer' || argType === 'Float' || argType === 'Boolean') {
|
|
6052
|
+
return `${node.defname} = ${argValue}`;
|
|
6053
|
+
}
|
|
6000
6054
|
const quotedValue = typeof argValue === 'string'
|
|
6001
6055
|
? QuoteUtils.escape(argValue)
|
|
6002
6056
|
: argValue;
|
|
@@ -6430,6 +6484,9 @@ export class Deparser {
|
|
|
6430
6484
|
case 'OBJECT_TABCONSTRAINT':
|
|
6431
6485
|
output.push('CONSTRAINT');
|
|
6432
6486
|
break;
|
|
6487
|
+
case 'OBJECT_DOMCONSTRAINT':
|
|
6488
|
+
output.push('CONSTRAINT');
|
|
6489
|
+
break;
|
|
6433
6490
|
case 'OBJECT_TRIGGER':
|
|
6434
6491
|
output.push('TRIGGER');
|
|
6435
6492
|
break;
|
|
@@ -6506,6 +6563,15 @@ export class Deparser {
|
|
|
6506
6563
|
output.push(objectParts.join('.'));
|
|
6507
6564
|
}
|
|
6508
6565
|
}
|
|
6566
|
+
else if (node.objtype === 'OBJECT_DOMCONSTRAINT') {
|
|
6567
|
+
if (objectParts.length === 2) {
|
|
6568
|
+
const [domain, constraint] = objectParts;
|
|
6569
|
+
output.push(constraint, 'ON DOMAIN', domain);
|
|
6570
|
+
}
|
|
6571
|
+
else {
|
|
6572
|
+
output.push(objectParts.join('.'));
|
|
6573
|
+
}
|
|
6574
|
+
}
|
|
6509
6575
|
else if (node.objtype === 'OBJECT_TRIGGER') {
|
|
6510
6576
|
if (objectParts.length === 2) {
|
|
6511
6577
|
const [table, trigger] = objectParts;
|
|
@@ -6837,7 +6903,7 @@ export class Deparser {
|
|
|
6837
6903
|
output.push(QuoteUtils.quoteIdentifier(node.pubname));
|
|
6838
6904
|
}
|
|
6839
6905
|
if (node.pubobjects && node.pubobjects.length > 0) {
|
|
6840
|
-
output.push('FOR'
|
|
6906
|
+
output.push('FOR');
|
|
6841
6907
|
const tables = ListUtils.unwrapList(node.pubobjects).map(table => this.visit(table, context));
|
|
6842
6908
|
output.push(tables.join(', '));
|
|
6843
6909
|
}
|
|
@@ -6877,8 +6943,9 @@ export class Deparser {
|
|
|
6877
6943
|
if (node.pubname) {
|
|
6878
6944
|
output.push(QuoteUtils.quoteIdentifier(node.pubname));
|
|
6879
6945
|
}
|
|
6880
|
-
|
|
6881
|
-
|
|
6946
|
+
const hasObjects = node.pubobjects && node.pubobjects.length > 0;
|
|
6947
|
+
if (hasObjects) {
|
|
6948
|
+
switch (node.action || 'AP_AddObjects') {
|
|
6882
6949
|
case 'AP_AddObjects':
|
|
6883
6950
|
output.push('ADD');
|
|
6884
6951
|
break;
|
|
@@ -6891,17 +6958,11 @@ export class Deparser {
|
|
|
6891
6958
|
default:
|
|
6892
6959
|
throw new Error(`Unsupported AlterPublicationStmt action: ${node.action}`);
|
|
6893
6960
|
}
|
|
6894
|
-
}
|
|
6895
|
-
if (node.for_all_tables) {
|
|
6896
|
-
output.push('FOR ALL TABLES');
|
|
6897
|
-
}
|
|
6898
|
-
else if (node.pubobjects && node.pubobjects.length > 0) {
|
|
6899
|
-
output.push('FOR TABLE');
|
|
6900
6961
|
const objects = ListUtils.unwrapList(node.pubobjects).map(obj => this.visit(obj, context));
|
|
6901
6962
|
output.push(objects.join(', '));
|
|
6902
6963
|
}
|
|
6903
|
-
if (node.options && node.options.length > 0) {
|
|
6904
|
-
output.push('
|
|
6964
|
+
else if (node.options && node.options.length > 0) {
|
|
6965
|
+
output.push('SET');
|
|
6905
6966
|
const options = ListUtils.unwrapList(node.options).map(opt => this.visit(opt, context));
|
|
6906
6967
|
output.push(`(${options.join(', ')})`);
|
|
6907
6968
|
}
|
|
@@ -6912,42 +6973,67 @@ export class Deparser {
|
|
|
6912
6973
|
if (node.subname) {
|
|
6913
6974
|
output.push(QuoteUtils.quoteIdentifier(node.subname));
|
|
6914
6975
|
}
|
|
6915
|
-
|
|
6916
|
-
|
|
6976
|
+
const options = node.options && node.options.length > 0
|
|
6977
|
+
? `(${ListUtils.unwrapList(node.options).map(opt => this.visit(opt, context)).join(', ')})`
|
|
6978
|
+
: null;
|
|
6979
|
+
const publications = node.publication && node.publication.length > 0
|
|
6980
|
+
? ListUtils.unwrapList(node.publication).map(pub => this.visit(pub, context)).join(', ')
|
|
6981
|
+
: null;
|
|
6982
|
+
{
|
|
6983
|
+
switch (node.kind || 'ALTER_SUBSCRIPTION_OPTIONS') {
|
|
6917
6984
|
case 'ALTER_SUBSCRIPTION_OPTIONS':
|
|
6918
6985
|
output.push('SET');
|
|
6986
|
+
if (options)
|
|
6987
|
+
output.push(options);
|
|
6919
6988
|
break;
|
|
6920
6989
|
case 'ALTER_SUBSCRIPTION_CONNECTION':
|
|
6921
6990
|
output.push('CONNECTION');
|
|
6922
6991
|
if (node.conninfo) {
|
|
6923
|
-
output.push(
|
|
6992
|
+
output.push(QuoteUtils.escape(node.conninfo));
|
|
6924
6993
|
}
|
|
6925
6994
|
break;
|
|
6926
6995
|
case 'ALTER_SUBSCRIPTION_SET_PUBLICATION':
|
|
6927
6996
|
output.push('SET PUBLICATION');
|
|
6928
|
-
if (
|
|
6929
|
-
|
|
6930
|
-
|
|
6931
|
-
|
|
6997
|
+
if (publications)
|
|
6998
|
+
output.push(publications);
|
|
6999
|
+
if (options)
|
|
7000
|
+
output.push('WITH', options);
|
|
7001
|
+
break;
|
|
7002
|
+
case 'ALTER_SUBSCRIPTION_ADD_PUBLICATION':
|
|
7003
|
+
output.push('ADD PUBLICATION');
|
|
7004
|
+
if (publications)
|
|
7005
|
+
output.push(publications);
|
|
7006
|
+
if (options)
|
|
7007
|
+
output.push('WITH', options);
|
|
7008
|
+
break;
|
|
7009
|
+
case 'ALTER_SUBSCRIPTION_DROP_PUBLICATION':
|
|
7010
|
+
output.push('DROP PUBLICATION');
|
|
7011
|
+
if (publications)
|
|
7012
|
+
output.push(publications);
|
|
7013
|
+
if (options)
|
|
7014
|
+
output.push('WITH', options);
|
|
6932
7015
|
break;
|
|
6933
7016
|
case 'ALTER_SUBSCRIPTION_REFRESH':
|
|
6934
7017
|
output.push('REFRESH PUBLICATION');
|
|
7018
|
+
if (options)
|
|
7019
|
+
output.push('WITH', options);
|
|
6935
7020
|
break;
|
|
6936
|
-
case 'ALTER_SUBSCRIPTION_ENABLED':
|
|
6937
|
-
|
|
7021
|
+
case 'ALTER_SUBSCRIPTION_ENABLED': {
|
|
7022
|
+
const enabled = ListUtils.unwrapList(node.options).find(opt => opt.DefElem?.defname === 'enabled');
|
|
7023
|
+
const arg = enabled?.DefElem?.arg;
|
|
7024
|
+
const isEnabled = arg?.Boolean ? arg.Boolean.boolval !== false : true;
|
|
7025
|
+
output.push(isEnabled ? 'ENABLE' : 'DISABLE');
|
|
6938
7026
|
break;
|
|
7027
|
+
}
|
|
6939
7028
|
case 'ALTER_SUBSCRIPTION_SKIP':
|
|
6940
7029
|
output.push('SKIP');
|
|
7030
|
+
if (options)
|
|
7031
|
+
output.push(options);
|
|
6941
7032
|
break;
|
|
6942
7033
|
default:
|
|
6943
7034
|
throw new Error(`Unsupported AlterSubscriptionStmt kind: ${node.kind}`);
|
|
6944
7035
|
}
|
|
6945
7036
|
}
|
|
6946
|
-
if (node.options && node.options.length > 0) {
|
|
6947
|
-
output.push('WITH');
|
|
6948
|
-
const options = ListUtils.unwrapList(node.options).map(opt => this.visit(opt, context));
|
|
6949
|
-
output.push(`(${options.join(', ')})`);
|
|
6950
|
-
}
|
|
6951
7037
|
return output.join(' ');
|
|
6952
7038
|
}
|
|
6953
7039
|
DropSubscriptionStmt(node, context) {
|
|
@@ -8013,6 +8099,9 @@ export class Deparser {
|
|
|
8013
8099
|
if (node.grant_option && node.is_grant) {
|
|
8014
8100
|
output.push('WITH GRANT OPTION');
|
|
8015
8101
|
}
|
|
8102
|
+
if (node.grantor) {
|
|
8103
|
+
output.push('GRANTED BY', this.RoleSpec(node.grantor, context));
|
|
8104
|
+
}
|
|
8016
8105
|
// Only add behavior clauses for REVOKE statements, not for GRANT statements in ALTER DEFAULT PRIVILEGES
|
|
8017
8106
|
if (!node.is_grant) {
|
|
8018
8107
|
if (node.behavior === 'DROP_CASCADE') {
|
|
@@ -8026,57 +8115,34 @@ export class Deparser {
|
|
|
8026
8115
|
}
|
|
8027
8116
|
GrantRoleStmt(node, context) {
|
|
8028
8117
|
const output = [];
|
|
8029
|
-
|
|
8030
|
-
|
|
8031
|
-
|
|
8032
|
-
|
|
8033
|
-
|
|
8034
|
-
|
|
8035
|
-
|
|
8036
|
-
|
|
8037
|
-
|
|
8038
|
-
|
|
8039
|
-
|
|
8040
|
-
|
|
8041
|
-
|
|
8042
|
-
|
|
8043
|
-
|
|
8044
|
-
|
|
8045
|
-
|
|
8046
|
-
|
|
8047
|
-
|
|
8048
|
-
if (adminOption.DefElem && adminOption.DefElem.arg) {
|
|
8049
|
-
adminValue = adminOption.DefElem.arg.Boolean?.boolval;
|
|
8050
|
-
}
|
|
8051
|
-
}
|
|
8052
|
-
if (setOption && setOption.DefElem) {
|
|
8053
|
-
hasSetOption = true;
|
|
8054
|
-
setValue = setOption.DefElem.arg?.Boolean?.boolval;
|
|
8055
|
-
}
|
|
8056
|
-
}
|
|
8118
|
+
const options = ListUtils.unwrapList(node.opt)
|
|
8119
|
+
.map(opt => opt.DefElem)
|
|
8120
|
+
.filter((opt) => !!opt && !!opt.defname);
|
|
8121
|
+
const optionValue = (opt) => {
|
|
8122
|
+
if (!opt.arg)
|
|
8123
|
+
return true;
|
|
8124
|
+
const argType = this.getNodeType(opt.arg);
|
|
8125
|
+
const argData = this.getNodeData(opt.arg);
|
|
8126
|
+
if (argType === 'Boolean')
|
|
8127
|
+
return argData.boolval !== false;
|
|
8128
|
+
if (argType === 'String')
|
|
8129
|
+
return argData.sval !== 'false';
|
|
8130
|
+
return true;
|
|
8131
|
+
};
|
|
8132
|
+
const roles = ListUtils.unwrapList(node.granted_roles)
|
|
8133
|
+
.map(role => role.AccessPriv?.priv_name
|
|
8134
|
+
? QuoteUtils.quoteIdentifier(role.AccessPriv.priv_name)
|
|
8135
|
+
: this.visit(role, context))
|
|
8136
|
+
.join(', ');
|
|
8057
8137
|
if (node.is_grant) {
|
|
8058
|
-
output.push('GRANT');
|
|
8138
|
+
output.push('GRANT', roles, 'TO');
|
|
8059
8139
|
}
|
|
8060
8140
|
else {
|
|
8061
8141
|
output.push('REVOKE');
|
|
8062
|
-
if (
|
|
8063
|
-
output.push(
|
|
8064
|
-
}
|
|
8065
|
-
else if (hasAdminOption) {
|
|
8066
|
-
output.push('ADMIN OPTION FOR');
|
|
8142
|
+
if (options.length > 0) {
|
|
8143
|
+
output.push(`${options[0].defname.toUpperCase()} OPTION FOR`);
|
|
8067
8144
|
}
|
|
8068
|
-
|
|
8069
|
-
if (node.granted_roles && node.granted_roles.length > 0) {
|
|
8070
|
-
const roles = ListUtils.unwrapList(node.granted_roles)
|
|
8071
|
-
.map(role => this.visit(role, context))
|
|
8072
|
-
.join(', ');
|
|
8073
|
-
output.push(roles);
|
|
8074
|
-
}
|
|
8075
|
-
if (node.is_grant) {
|
|
8076
|
-
output.push('TO');
|
|
8077
|
-
}
|
|
8078
|
-
else {
|
|
8079
|
-
output.push('FROM');
|
|
8145
|
+
output.push(roles, 'FROM');
|
|
8080
8146
|
}
|
|
8081
8147
|
if (node.grantee_roles && node.grantee_roles.length > 0) {
|
|
8082
8148
|
const grantees = ListUtils.unwrapList(node.grantee_roles)
|
|
@@ -8084,38 +8150,15 @@ export class Deparser {
|
|
|
8084
8150
|
.join(', ');
|
|
8085
8151
|
output.push(grantees);
|
|
8086
8152
|
}
|
|
8087
|
-
if (node.is_grant) {
|
|
8088
|
-
const withOptions =
|
|
8089
|
-
|
|
8090
|
-
|
|
8091
|
-
|
|
8092
|
-
|
|
8093
|
-
|
|
8094
|
-
|
|
8095
|
-
|
|
8096
|
-
else {
|
|
8097
|
-
withOptions.push('ADMIN OPTION');
|
|
8098
|
-
}
|
|
8099
|
-
}
|
|
8100
|
-
if (hasInheritOption) {
|
|
8101
|
-
if (inheritValue === true) {
|
|
8102
|
-
withOptions.push('INHERIT OPTION');
|
|
8103
|
-
}
|
|
8104
|
-
else if (inheritValue === false) {
|
|
8105
|
-
withOptions.push('INHERIT FALSE');
|
|
8106
|
-
}
|
|
8107
|
-
}
|
|
8108
|
-
if (hasSetOption) {
|
|
8109
|
-
if (setValue === true) {
|
|
8110
|
-
withOptions.push('SET TRUE');
|
|
8111
|
-
}
|
|
8112
|
-
else if (setValue === false) {
|
|
8113
|
-
withOptions.push('SET FALSE');
|
|
8114
|
-
}
|
|
8115
|
-
}
|
|
8116
|
-
if (withOptions.length > 0) {
|
|
8117
|
-
output.push('WITH', withOptions.join(', '));
|
|
8118
|
-
}
|
|
8153
|
+
if (node.is_grant && options.length > 0) {
|
|
8154
|
+
const withOptions = options.map(opt => `${opt.defname.toUpperCase()} ${optionValue(opt) ? 'TRUE' : 'FALSE'}`);
|
|
8155
|
+
output.push('WITH', withOptions.join(', '));
|
|
8156
|
+
}
|
|
8157
|
+
if (node.grantor) {
|
|
8158
|
+
output.push('GRANTED BY', this.RoleSpec(node.grantor, context));
|
|
8159
|
+
}
|
|
8160
|
+
if (!node.is_grant && node.behavior === 'DROP_CASCADE') {
|
|
8161
|
+
output.push('CASCADE');
|
|
8119
8162
|
}
|
|
8120
8163
|
return output.join(' ');
|
|
8121
8164
|
}
|
|
@@ -8695,10 +8738,9 @@ export class Deparser {
|
|
|
8695
8738
|
switch (node.commandType) {
|
|
8696
8739
|
case 'CMD_UPDATE': {
|
|
8697
8740
|
output.push('UPDATE SET');
|
|
8698
|
-
|
|
8699
|
-
.
|
|
8700
|
-
|
|
8701
|
-
output.push(assignments);
|
|
8741
|
+
if (node.targetList && node.targetList.length > 0) {
|
|
8742
|
+
output.push(this.formatUpdateAssignments(node.targetList, context));
|
|
8743
|
+
}
|
|
8702
8744
|
break;
|
|
8703
8745
|
}
|
|
8704
8746
|
case 'CMD_INSERT': {
|
|
@@ -9103,6 +9145,13 @@ export class Deparser {
|
|
|
9103
9145
|
output.push('USING');
|
|
9104
9146
|
output.push(node.into.accessMethod);
|
|
9105
9147
|
}
|
|
9148
|
+
if (node.into && node.into.options && node.into.options.length > 0) {
|
|
9149
|
+
output.push('WITH');
|
|
9150
|
+
const options = ListUtils.unwrapList(node.into.options)
|
|
9151
|
+
.map(option => this.visit(option, context.spawn('CreateStmt')))
|
|
9152
|
+
.join(', ');
|
|
9153
|
+
output.push(`(${options})`);
|
|
9154
|
+
}
|
|
9106
9155
|
if (node.into && node.into.onCommit && node.into.onCommit !== 'ONCOMMIT_NOOP') {
|
|
9107
9156
|
output.push('ON COMMIT');
|
|
9108
9157
|
switch (node.into.onCommit) {
|
|
@@ -9117,17 +9166,13 @@ export class Deparser {
|
|
|
9117
9166
|
break;
|
|
9118
9167
|
}
|
|
9119
9168
|
}
|
|
9169
|
+
if (node.into && node.into.tableSpaceName) {
|
|
9170
|
+
output.push('TABLESPACE', QuoteUtils.quoteIdentifier(node.into.tableSpaceName));
|
|
9171
|
+
}
|
|
9120
9172
|
output.push('AS');
|
|
9121
9173
|
if (node.query) {
|
|
9122
9174
|
output.push(this.visit(node.query, context));
|
|
9123
9175
|
}
|
|
9124
|
-
if (node.into && node.into.options && node.into.options.length > 0) {
|
|
9125
|
-
output.push('WITH');
|
|
9126
|
-
const options = ListUtils.unwrapList(node.into.options)
|
|
9127
|
-
.map(option => this.visit(option, context))
|
|
9128
|
-
.join(', ');
|
|
9129
|
-
output.push(`(${options})`);
|
|
9130
|
-
}
|
|
9131
9176
|
if (node.into && node.into.skipData) {
|
|
9132
9177
|
output.push('WITH NO DATA');
|
|
9133
9178
|
}
|
|
@@ -9600,7 +9645,7 @@ export class Deparser {
|
|
|
9600
9645
|
}
|
|
9601
9646
|
if (node.whereClause) {
|
|
9602
9647
|
output.push('WHERE');
|
|
9603
|
-
output.push(this.visit(node.whereClause, context));
|
|
9648
|
+
output.push(`(${this.visit(node.whereClause, context)})`);
|
|
9604
9649
|
}
|
|
9605
9650
|
return output.join(' ');
|
|
9606
9651
|
}
|
|
@@ -9843,24 +9888,182 @@ export class Deparser {
|
|
|
9843
9888
|
}
|
|
9844
9889
|
return output.join(' ');
|
|
9845
9890
|
}
|
|
9891
|
+
formatJsonFormat(format) {
|
|
9892
|
+
if (!format || !format.format_type || format.format_type === 'JS_FORMAT_DEFAULT') {
|
|
9893
|
+
return null;
|
|
9894
|
+
}
|
|
9895
|
+
const parts = ['FORMAT JSON'];
|
|
9896
|
+
switch (format.encoding) {
|
|
9897
|
+
case 'JS_ENC_UTF8':
|
|
9898
|
+
parts.push('ENCODING UTF8');
|
|
9899
|
+
break;
|
|
9900
|
+
case 'JS_ENC_UTF16':
|
|
9901
|
+
parts.push('ENCODING UTF16');
|
|
9902
|
+
break;
|
|
9903
|
+
case 'JS_ENC_UTF32':
|
|
9904
|
+
parts.push('ENCODING UTF32');
|
|
9905
|
+
break;
|
|
9906
|
+
}
|
|
9907
|
+
return parts.join(' ');
|
|
9908
|
+
}
|
|
9909
|
+
formatJsonOutput(output, context) {
|
|
9910
|
+
if (!output || !output.typeName)
|
|
9911
|
+
return null;
|
|
9912
|
+
const parts = ['RETURNING', this.TypeName(output.typeName, context)];
|
|
9913
|
+
const format = this.formatJsonFormat(output.returning?.format);
|
|
9914
|
+
if (format)
|
|
9915
|
+
parts.push(format);
|
|
9916
|
+
return parts.join(' ');
|
|
9917
|
+
}
|
|
9918
|
+
formatJsonNullClause(absentOnNull) {
|
|
9919
|
+
return absentOnNull ? 'ABSENT ON NULL' : 'NULL ON NULL';
|
|
9920
|
+
}
|
|
9921
|
+
formatJsonUniqueClause(unique) {
|
|
9922
|
+
return unique ? 'WITH UNIQUE KEYS' : null;
|
|
9923
|
+
}
|
|
9924
|
+
JsonValueExpr(node, context) {
|
|
9925
|
+
const parts = [];
|
|
9926
|
+
if (node.raw_expr) {
|
|
9927
|
+
parts.push(this.visit(node.raw_expr, context));
|
|
9928
|
+
}
|
|
9929
|
+
const format = this.formatJsonFormat(node.format);
|
|
9930
|
+
if (format)
|
|
9931
|
+
parts.push(format);
|
|
9932
|
+
return parts.join(' ');
|
|
9933
|
+
}
|
|
9934
|
+
JsonKeyValue(node, context) {
|
|
9935
|
+
const key = node.key ? this.visit(node.key, context) : '';
|
|
9936
|
+
const value = node.value ? this.JsonValueExpr(node.value, context) : '';
|
|
9937
|
+
return `${key} : ${value}`;
|
|
9938
|
+
}
|
|
9939
|
+
JsonObjectConstructor(node, context) {
|
|
9940
|
+
const args = [];
|
|
9941
|
+
if (node.exprs && node.exprs.length > 0) {
|
|
9942
|
+
args.push(ListUtils.unwrapList(node.exprs).map(e => this.visit(e, context)).join(', '));
|
|
9943
|
+
args.push(this.formatJsonNullClause(node.absent_on_null));
|
|
9944
|
+
const unique = this.formatJsonUniqueClause(node.unique);
|
|
9945
|
+
if (unique)
|
|
9946
|
+
args.push(unique);
|
|
9947
|
+
}
|
|
9948
|
+
const output = this.formatJsonOutput(node.output, context);
|
|
9949
|
+
if (output)
|
|
9950
|
+
args.push(output);
|
|
9951
|
+
return `JSON_OBJECT(${args.join(' ')})`;
|
|
9952
|
+
}
|
|
9953
|
+
JsonArrayConstructor(node, context) {
|
|
9954
|
+
const args = [];
|
|
9955
|
+
if (node.exprs && node.exprs.length > 0) {
|
|
9956
|
+
args.push(ListUtils.unwrapList(node.exprs).map(e => this.visit(e, context)).join(', '));
|
|
9957
|
+
args.push(this.formatJsonNullClause(node.absent_on_null));
|
|
9958
|
+
}
|
|
9959
|
+
const output = this.formatJsonOutput(node.output, context);
|
|
9960
|
+
if (output)
|
|
9961
|
+
args.push(output);
|
|
9962
|
+
return `JSON_ARRAY(${args.join(' ')})`;
|
|
9963
|
+
}
|
|
9846
9964
|
JsonArrayQueryConstructor(node, context) {
|
|
9847
|
-
const
|
|
9965
|
+
const args = [];
|
|
9848
9966
|
if (node.query) {
|
|
9849
|
-
|
|
9967
|
+
args.push(this.visit(node.query, context));
|
|
9968
|
+
}
|
|
9969
|
+
const format = this.formatJsonFormat(node.format);
|
|
9970
|
+
if (format)
|
|
9971
|
+
args.push(format);
|
|
9972
|
+
const output = this.formatJsonOutput(node.output, context);
|
|
9973
|
+
if (output)
|
|
9974
|
+
args.push(output);
|
|
9975
|
+
return `JSON_ARRAY(${args.join(' ')})`;
|
|
9976
|
+
}
|
|
9977
|
+
formatJsonAggSuffix(ctor, context) {
|
|
9978
|
+
if (!ctor)
|
|
9979
|
+
return '';
|
|
9980
|
+
let result = '';
|
|
9981
|
+
if (ctor.agg_filter) {
|
|
9982
|
+
result += ` FILTER (WHERE ${this.visit(ctor.agg_filter, context)})`;
|
|
9850
9983
|
}
|
|
9851
|
-
if (
|
|
9852
|
-
|
|
9984
|
+
if (ctor.over) {
|
|
9985
|
+
result += this.formatOverClause(ctor.over, context);
|
|
9853
9986
|
}
|
|
9854
|
-
|
|
9855
|
-
|
|
9987
|
+
return result;
|
|
9988
|
+
}
|
|
9989
|
+
JsonObjectAgg(node, context) {
|
|
9990
|
+
const args = [];
|
|
9991
|
+
if (node.arg) {
|
|
9992
|
+
args.push(this.JsonKeyValue(node.arg, context));
|
|
9993
|
+
}
|
|
9994
|
+
args.push(this.formatJsonNullClause(node.absent_on_null));
|
|
9995
|
+
const unique = this.formatJsonUniqueClause(node.unique);
|
|
9996
|
+
if (unique)
|
|
9997
|
+
args.push(unique);
|
|
9998
|
+
const output = this.formatJsonOutput(node.constructor?.output, context);
|
|
9999
|
+
if (output)
|
|
10000
|
+
args.push(output);
|
|
10001
|
+
return `JSON_OBJECTAGG(${args.join(' ')})${this.formatJsonAggSuffix(node.constructor, context)}`;
|
|
10002
|
+
}
|
|
10003
|
+
JsonArrayAgg(node, context) {
|
|
10004
|
+
const args = [];
|
|
10005
|
+
if (node.arg) {
|
|
10006
|
+
args.push(this.JsonValueExpr(node.arg, context));
|
|
9856
10007
|
}
|
|
9857
|
-
|
|
9858
|
-
|
|
10008
|
+
const aggOrder = node.constructor?.agg_order;
|
|
10009
|
+
if (aggOrder && aggOrder.length > 0) {
|
|
10010
|
+
const orderItems = ListUtils.unwrapList(aggOrder).map(item => this.visit(item, context));
|
|
10011
|
+
args.push(`ORDER BY ${orderItems.join(', ')}`);
|
|
9859
10012
|
}
|
|
9860
|
-
|
|
9861
|
-
|
|
10013
|
+
args.push(this.formatJsonNullClause(node.absent_on_null));
|
|
10014
|
+
const output = this.formatJsonOutput(node.constructor?.output, context);
|
|
10015
|
+
if (output)
|
|
10016
|
+
args.push(output);
|
|
10017
|
+
return `JSON_ARRAYAGG(${args.join(' ')})${this.formatJsonAggSuffix(node.constructor, context)}`;
|
|
10018
|
+
}
|
|
10019
|
+
JsonParseExpr(node, context) {
|
|
10020
|
+
const args = [];
|
|
10021
|
+
if (node.expr) {
|
|
10022
|
+
args.push(this.JsonValueExpr(node.expr, context));
|
|
9862
10023
|
}
|
|
9863
|
-
|
|
10024
|
+
const unique = this.formatJsonUniqueClause(node.unique_keys);
|
|
10025
|
+
if (unique)
|
|
10026
|
+
args.push(unique);
|
|
10027
|
+
return `JSON(${args.join(' ')})`;
|
|
10028
|
+
}
|
|
10029
|
+
JsonScalarExpr(node, context) {
|
|
10030
|
+
const expr = node.expr ? this.visit(node.expr, context) : '';
|
|
10031
|
+
return `JSON_SCALAR(${expr})`;
|
|
10032
|
+
}
|
|
10033
|
+
JsonSerializeExpr(node, context) {
|
|
10034
|
+
const args = [];
|
|
10035
|
+
if (node.expr) {
|
|
10036
|
+
args.push(this.JsonValueExpr(node.expr, context));
|
|
10037
|
+
}
|
|
10038
|
+
const output = this.formatJsonOutput(node.output, context);
|
|
10039
|
+
if (output)
|
|
10040
|
+
args.push(output);
|
|
10041
|
+
return `JSON_SERIALIZE(${args.join(' ')})`;
|
|
10042
|
+
}
|
|
10043
|
+
JsonIsPredicate(node, context) {
|
|
10044
|
+
const parts = [];
|
|
10045
|
+
if (node.expr) {
|
|
10046
|
+
parts.push(this.visit(node.expr, context));
|
|
10047
|
+
}
|
|
10048
|
+
const format = this.formatJsonFormat(node.format);
|
|
10049
|
+
if (format)
|
|
10050
|
+
parts.push(format);
|
|
10051
|
+
parts.push('IS JSON');
|
|
10052
|
+
switch (node.item_type) {
|
|
10053
|
+
case 'JS_TYPE_OBJECT':
|
|
10054
|
+
parts.push('OBJECT');
|
|
10055
|
+
break;
|
|
10056
|
+
case 'JS_TYPE_ARRAY':
|
|
10057
|
+
parts.push('ARRAY');
|
|
10058
|
+
break;
|
|
10059
|
+
case 'JS_TYPE_SCALAR':
|
|
10060
|
+
parts.push('SCALAR');
|
|
10061
|
+
break;
|
|
10062
|
+
}
|
|
10063
|
+
if (node.unique_keys) {
|
|
10064
|
+
parts.push('WITH UNIQUE KEYS');
|
|
10065
|
+
}
|
|
10066
|
+
return parts.join(' ');
|
|
9864
10067
|
}
|
|
9865
10068
|
RangeFunction(node, context) {
|
|
9866
10069
|
const output = [];
|