pgsql-deparser 18.3.7 → 18.3.8
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 -0
- package/deparser.js +533 -316
- package/esm/deparser.js +533 -316
- 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.
|
|
@@ -981,6 +1000,12 @@ export class Deparser {
|
|
|
981
1000
|
output.push(context.parens(columnNames.join(', ')));
|
|
982
1001
|
}
|
|
983
1002
|
}
|
|
1003
|
+
if (node.override === 'OVERRIDING_USER_VALUE') {
|
|
1004
|
+
output.push('OVERRIDING USER VALUE');
|
|
1005
|
+
}
|
|
1006
|
+
else if (node.override === 'OVERRIDING_SYSTEM_VALUE') {
|
|
1007
|
+
output.push('OVERRIDING SYSTEM VALUE');
|
|
1008
|
+
}
|
|
984
1009
|
if (node.selectStmt) {
|
|
985
1010
|
output.push(this.visit(node.selectStmt, context));
|
|
986
1011
|
}
|
|
@@ -1057,38 +1082,8 @@ export class Deparser {
|
|
|
1057
1082
|
output.push(this.RangeVar(node.relation, context));
|
|
1058
1083
|
}
|
|
1059
1084
|
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(','));
|
|
1085
|
+
if (node.targetList && node.targetList.length > 0) {
|
|
1086
|
+
output.push(this.formatUpdateAssignments(node.targetList, context));
|
|
1092
1087
|
}
|
|
1093
1088
|
if (node.fromClause) {
|
|
1094
1089
|
output.push('FROM');
|
|
@@ -1105,6 +1100,36 @@ export class Deparser {
|
|
|
1105
1100
|
}
|
|
1106
1101
|
return output.join(' ');
|
|
1107
1102
|
}
|
|
1103
|
+
formatUpdateAssignments(targets, context) {
|
|
1104
|
+
const targetList = ListUtils.unwrapList(targets);
|
|
1105
|
+
const processedTargets = new Set();
|
|
1106
|
+
const assignmentParts = [];
|
|
1107
|
+
for (let i = 0; i < targetList.length; i++) {
|
|
1108
|
+
if (processedTargets.has(i))
|
|
1109
|
+
continue;
|
|
1110
|
+
const target = targetList[i];
|
|
1111
|
+
const multiAssignRef = target.ResTarget?.val?.MultiAssignRef;
|
|
1112
|
+
if (multiAssignRef) {
|
|
1113
|
+
const relatedTargets = [];
|
|
1114
|
+
for (let j = i; j < targetList.length; j++) {
|
|
1115
|
+
const otherTarget = targetList[j];
|
|
1116
|
+
const otherMultiAssignRef = otherTarget.ResTarget?.val?.MultiAssignRef;
|
|
1117
|
+
if (otherMultiAssignRef &&
|
|
1118
|
+
JSON.stringify(otherMultiAssignRef.source) === JSON.stringify(multiAssignRef.source)) {
|
|
1119
|
+
relatedTargets.push(otherTarget);
|
|
1120
|
+
processedTargets.add(j);
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
const names = relatedTargets.map(t => QuoteUtils.quoteIdentifier(t.ResTarget.name));
|
|
1124
|
+
assignmentParts.push(`${context.parens(names.join(', '))} = ${this.visit(multiAssignRef.source, context)}`);
|
|
1125
|
+
}
|
|
1126
|
+
else {
|
|
1127
|
+
assignmentParts.push(this.visit(target, context.spawn('UpdateStmt', { update: true })));
|
|
1128
|
+
processedTargets.add(i);
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
return assignmentParts.join(', ');
|
|
1132
|
+
}
|
|
1108
1133
|
DeleteStmt(node, context) {
|
|
1109
1134
|
try {
|
|
1110
1135
|
const output = [];
|
|
@@ -1517,43 +1542,41 @@ export class Deparser {
|
|
|
1517
1542
|
result += ` FILTER (WHERE ${this.visit(node.agg_filter, context)})`;
|
|
1518
1543
|
}
|
|
1519
1544
|
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
|
-
}
|
|
1545
|
+
result += this.formatOverClause(node.over, context);
|
|
1554
1546
|
}
|
|
1555
1547
|
return result;
|
|
1556
1548
|
}
|
|
1549
|
+
formatOverClause(over, context) {
|
|
1550
|
+
if (over.name) {
|
|
1551
|
+
return ` OVER ${over.name}`;
|
|
1552
|
+
}
|
|
1553
|
+
const windowParts = [];
|
|
1554
|
+
if (over.refname) {
|
|
1555
|
+
windowParts.push(over.refname);
|
|
1556
|
+
}
|
|
1557
|
+
if (over.partitionClause) {
|
|
1558
|
+
const partitions = ListUtils.unwrapList(over.partitionClause);
|
|
1559
|
+
const partitionStrs = partitions.map(p => this.visit(p, context));
|
|
1560
|
+
windowParts.push(`PARTITION BY ${partitionStrs.join(', ')}`);
|
|
1561
|
+
}
|
|
1562
|
+
if (over.orderClause) {
|
|
1563
|
+
const orders = ListUtils.unwrapList(over.orderClause);
|
|
1564
|
+
const orderStrs = orders.map(o => this.visit(o, context));
|
|
1565
|
+
windowParts.push(`ORDER BY ${orderStrs.join(', ')}`);
|
|
1566
|
+
}
|
|
1567
|
+
const frameClause = this.formatWindowFrame(over, context.spawn('FuncCall'));
|
|
1568
|
+
if (frameClause) {
|
|
1569
|
+
windowParts.push(frameClause);
|
|
1570
|
+
}
|
|
1571
|
+
if (windowParts.length === 0) {
|
|
1572
|
+
return ' OVER ()';
|
|
1573
|
+
}
|
|
1574
|
+
if (context.isPretty() && windowParts.length > 1) {
|
|
1575
|
+
const formattedParts = windowParts.map(part => context.indent(part));
|
|
1576
|
+
return ` OVER (${context.newline()}${formattedParts.join(context.newline())}${context.newline()})`;
|
|
1577
|
+
}
|
|
1578
|
+
return ` OVER (${windowParts.join(' ')})`;
|
|
1579
|
+
}
|
|
1557
1580
|
FuncExpr(node, context) {
|
|
1558
1581
|
const funcName = `func_${node.funcid}`;
|
|
1559
1582
|
const args = node.args ? ListUtils.unwrapList(node.args).map(arg => this.visit(arg, context)).join(', ') : '';
|
|
@@ -2416,7 +2439,7 @@ export class Deparser {
|
|
|
2416
2439
|
output.push(context.parens(elementStrs.join(', ')));
|
|
2417
2440
|
}
|
|
2418
2441
|
}
|
|
2419
|
-
else if (node.tableElts) {
|
|
2442
|
+
else if (node.tableElts && !node.partbound) {
|
|
2420
2443
|
const elements = ListUtils.unwrapList(node.tableElts);
|
|
2421
2444
|
const elementStrs = elements.map(el => {
|
|
2422
2445
|
return this.deparse(el, context.spawn('CreateStmt'));
|
|
@@ -2444,7 +2467,16 @@ export class Deparser {
|
|
|
2444
2467
|
const inherits = ListUtils.unwrapList(node.inhRelations);
|
|
2445
2468
|
const inheritStrs = inherits.map(rel => this.visit(rel, context));
|
|
2446
2469
|
output.push(inheritStrs[0]);
|
|
2447
|
-
if (node.
|
|
2470
|
+
if (node.tableElts) {
|
|
2471
|
+
const elementStrs = ListUtils.unwrapList(node.tableElts).map(el => {
|
|
2472
|
+
return this.deparse(el, context.spawn('CreateStmt'));
|
|
2473
|
+
});
|
|
2474
|
+
output.push(context.parens(elementStrs.join(', ')));
|
|
2475
|
+
}
|
|
2476
|
+
if (node.partbound.is_default) {
|
|
2477
|
+
output.push('DEFAULT');
|
|
2478
|
+
}
|
|
2479
|
+
else if (node.partbound.strategy === 'l' && node.partbound.listdatums) {
|
|
2448
2480
|
output.push('FOR VALUES IN');
|
|
2449
2481
|
const listValues = ListUtils.unwrapList(node.partbound.listdatums)
|
|
2450
2482
|
.map(datum => this.visit(datum, context))
|
|
@@ -2467,13 +2499,9 @@ export class Deparser {
|
|
|
2467
2499
|
output.push(`(${upperValues})`);
|
|
2468
2500
|
}
|
|
2469
2501
|
}
|
|
2470
|
-
else if (node.partbound.strategy === 'h'
|
|
2502
|
+
else if (node.partbound.strategy === 'h') {
|
|
2471
2503
|
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');
|
|
2504
|
+
output.push(`(MODULUS ${node.partbound.modulus ?? 0}, REMAINDER ${node.partbound.remainder ?? 0})`);
|
|
2477
2505
|
}
|
|
2478
2506
|
}
|
|
2479
2507
|
else if (node.inhRelations) {
|
|
@@ -2539,6 +2567,12 @@ export class Deparser {
|
|
|
2539
2567
|
if (node.typeName) {
|
|
2540
2568
|
output.push(this.TypeName(node.typeName, context));
|
|
2541
2569
|
}
|
|
2570
|
+
if (node.storage_name) {
|
|
2571
|
+
output.push('STORAGE', node.storage_name.toUpperCase());
|
|
2572
|
+
}
|
|
2573
|
+
if (node.compression) {
|
|
2574
|
+
output.push('COMPRESSION', QuoteUtils.quoteIdentifier(node.compression));
|
|
2575
|
+
}
|
|
2542
2576
|
if (node.fdwoptions && node.fdwoptions.length > 0) {
|
|
2543
2577
|
output.push('OPTIONS');
|
|
2544
2578
|
const columnContext = context.spawn('ColumnDef');
|
|
@@ -2599,7 +2633,8 @@ export class Deparser {
|
|
|
2599
2633
|
case 'CONSTR_DEFAULT':
|
|
2600
2634
|
output.push('DEFAULT');
|
|
2601
2635
|
if (node.raw_expr) {
|
|
2602
|
-
|
|
2636
|
+
const defaultExpr = this.visit(node.raw_expr, context);
|
|
2637
|
+
output.push(this.needsBExprParens(node.raw_expr) ? `(${defaultExpr})` : defaultExpr);
|
|
2603
2638
|
}
|
|
2604
2639
|
break;
|
|
2605
2640
|
case 'CONSTR_CHECK':
|
|
@@ -2963,7 +2998,7 @@ export class Deparser {
|
|
|
2963
2998
|
break;
|
|
2964
2999
|
}
|
|
2965
3000
|
// Handle deferrable constraints for all constraint types that support it
|
|
2966
|
-
if (node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_FOREIGN') {
|
|
3001
|
+
if (node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_FOREIGN' || node.contype === 'CONSTR_EXCLUSION') {
|
|
2967
3002
|
if (node.deferrable) {
|
|
2968
3003
|
if (context.isPretty() && node.contype === 'CONSTR_FOREIGN') {
|
|
2969
3004
|
output.push('\n' + context.indent('DEFERRABLE'));
|
|
@@ -2992,6 +3027,9 @@ export class Deparser {
|
|
|
2992
3027
|
output.push('NOT DEFERRABLE');
|
|
2993
3028
|
}
|
|
2994
3029
|
}
|
|
3030
|
+
else if (node.initdeferred) {
|
|
3031
|
+
output.push('INITIALLY DEFERRED');
|
|
3032
|
+
}
|
|
2995
3033
|
}
|
|
2996
3034
|
if (context.isPretty() && node.contype === 'CONSTR_FOREIGN') {
|
|
2997
3035
|
let result = '';
|
|
@@ -3057,6 +3095,9 @@ export class Deparser {
|
|
|
3057
3095
|
output.push(node.name);
|
|
3058
3096
|
}
|
|
3059
3097
|
const windowParts = [];
|
|
3098
|
+
if (node.refname) {
|
|
3099
|
+
windowParts.push(node.refname);
|
|
3100
|
+
}
|
|
3060
3101
|
if (node.partitionClause) {
|
|
3061
3102
|
const partitions = ListUtils.unwrapList(node.partitionClause);
|
|
3062
3103
|
const partitionStrs = partitions.map(p => this.visit(p, context));
|
|
@@ -3067,12 +3108,9 @@ export class Deparser {
|
|
|
3067
3108
|
const orderStrs = orders.map(o => this.visit(o, context));
|
|
3068
3109
|
windowParts.push(`ORDER BY ${orderStrs.join(', ')}`);
|
|
3069
3110
|
}
|
|
3070
|
-
|
|
3071
|
-
if (
|
|
3072
|
-
|
|
3073
|
-
if (frameClause) {
|
|
3074
|
-
windowParts.push(frameClause);
|
|
3075
|
-
}
|
|
3111
|
+
const frameClause = this.formatWindowFrame(node, context.spawn('WindowDef'));
|
|
3112
|
+
if (frameClause) {
|
|
3113
|
+
windowParts.push(frameClause);
|
|
3076
3114
|
}
|
|
3077
3115
|
if (windowParts.length > 0) {
|
|
3078
3116
|
if (node.name) {
|
|
@@ -3089,114 +3127,96 @@ export class Deparser {
|
|
|
3089
3127
|
}
|
|
3090
3128
|
return output.join(' ');
|
|
3091
3129
|
}
|
|
3130
|
+
formatIdentityColumnOptions(def, context) {
|
|
3131
|
+
const seqContext = context.spawn('AlterSeqStmt');
|
|
3132
|
+
return ListUtils.unwrapList(def).map(item => {
|
|
3133
|
+
const el = item.DefElem;
|
|
3134
|
+
if (!el)
|
|
3135
|
+
return this.visit(item, context);
|
|
3136
|
+
if (el.defname === 'generated') {
|
|
3137
|
+
const ival = el.arg?.Integer?.ival ?? 0;
|
|
3138
|
+
return ival === 97 ? 'SET GENERATED ALWAYS' : 'SET GENERATED BY DEFAULT';
|
|
3139
|
+
}
|
|
3140
|
+
if (el.defname === 'restart') {
|
|
3141
|
+
return el.arg ? `RESTART WITH ${this.visit(el.arg, context)}` : 'RESTART';
|
|
3142
|
+
}
|
|
3143
|
+
return `SET ${this.visit(item, seqContext)}`;
|
|
3144
|
+
}).join(' ');
|
|
3145
|
+
}
|
|
3146
|
+
// b_expr (used by DEFAULT) excludes IN/LIKE/BETWEEN and boolean operators.
|
|
3147
|
+
needsBExprParens(node) {
|
|
3148
|
+
const nodeType = this.getNodeType(node);
|
|
3149
|
+
if (nodeType === 'BoolExpr')
|
|
3150
|
+
return true;
|
|
3151
|
+
if (nodeType === 'A_Expr') {
|
|
3152
|
+
const kind = this.getNodeData(node).kind;
|
|
3153
|
+
return kind !== 'AEXPR_OP' && kind !== 'AEXPR_DISTINCT' && kind !== 'AEXPR_NOT_DISTINCT';
|
|
3154
|
+
}
|
|
3155
|
+
return false;
|
|
3156
|
+
}
|
|
3092
3157
|
formatWindowFrame(node, context) {
|
|
3093
|
-
if (!node.frameOptions)
|
|
3158
|
+
if (!node.frameOptions || !(node.frameOptions & FRAMEOPTION_NONDEFAULT))
|
|
3094
3159
|
return null;
|
|
3095
3160
|
const frameOptions = node.frameOptions;
|
|
3096
|
-
const EXCLUDE_MASK = 0x8000 | 0x10000 | 0x20000;
|
|
3097
|
-
const baseFrameOptions = frameOptions & ~EXCLUDE_MASK;
|
|
3098
3161
|
const frameParts = [];
|
|
3099
|
-
if (frameOptions &
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
frameParts.push('GROUPS');
|
|
3108
|
-
}
|
|
3162
|
+
if (frameOptions & FRAMEOPTION_RANGE) {
|
|
3163
|
+
frameParts.push('RANGE');
|
|
3164
|
+
}
|
|
3165
|
+
else if (frameOptions & FRAMEOPTION_ROWS) {
|
|
3166
|
+
frameParts.push('ROWS');
|
|
3167
|
+
}
|
|
3168
|
+
else if (frameOptions & FRAMEOPTION_GROUPS) {
|
|
3169
|
+
frameParts.push('GROUPS');
|
|
3109
3170
|
}
|
|
3110
3171
|
if (frameParts.length === 0)
|
|
3111
3172
|
return null;
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
boundsParts.push('CURRENT ROW');
|
|
3116
|
-
boundsParts.push('AND UNBOUNDED FOLLOWING');
|
|
3173
|
+
let start = null;
|
|
3174
|
+
if (frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING) {
|
|
3175
|
+
start = 'UNBOUNDED PRECEDING';
|
|
3117
3176
|
}
|
|
3118
|
-
else if (
|
|
3119
|
-
|
|
3120
|
-
boundsParts.push('AND CURRENT ROW');
|
|
3177
|
+
else if (frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING) {
|
|
3178
|
+
start = 'UNBOUNDED FOLLOWING';
|
|
3121
3179
|
}
|
|
3122
|
-
else if (
|
|
3123
|
-
|
|
3124
|
-
boundsParts.push(`${this.visit(node.startOffset, context)} PRECEDING`);
|
|
3125
|
-
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
3126
|
-
}
|
|
3180
|
+
else if (frameOptions & FRAMEOPTION_START_CURRENT_ROW) {
|
|
3181
|
+
start = 'CURRENT ROW';
|
|
3127
3182
|
}
|
|
3128
|
-
else if (
|
|
3129
|
-
|
|
3130
|
-
boundsParts.push('AND CURRENT ROW');
|
|
3183
|
+
else if (frameOptions & FRAMEOPTION_START_OFFSET_PRECEDING && node.startOffset) {
|
|
3184
|
+
start = `${this.visit(node.startOffset, context)} PRECEDING`;
|
|
3131
3185
|
}
|
|
3132
|
-
else if (
|
|
3133
|
-
|
|
3134
|
-
if (node.endOffset) {
|
|
3135
|
-
boundsParts.push(`AND ${this.visit(node.endOffset, context)} FOLLOWING`);
|
|
3136
|
-
}
|
|
3186
|
+
else if (frameOptions & FRAMEOPTION_START_OFFSET_FOLLOWING && node.startOffset) {
|
|
3187
|
+
start = `${this.visit(node.startOffset, context)} FOLLOWING`;
|
|
3137
3188
|
}
|
|
3138
|
-
|
|
3139
|
-
|
|
3189
|
+
let end = null;
|
|
3190
|
+
if (frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING) {
|
|
3191
|
+
end = 'UNBOUNDED PRECEDING';
|
|
3140
3192
|
}
|
|
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
|
-
}
|
|
3193
|
+
else if (frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING) {
|
|
3194
|
+
end = 'UNBOUNDED FOLLOWING';
|
|
3195
|
+
}
|
|
3196
|
+
else if (frameOptions & FRAMEOPTION_END_CURRENT_ROW) {
|
|
3197
|
+
end = 'CURRENT ROW';
|
|
3198
|
+
}
|
|
3199
|
+
else if (frameOptions & FRAMEOPTION_END_OFFSET_PRECEDING && node.endOffset) {
|
|
3200
|
+
end = `${this.visit(node.endOffset, context)} PRECEDING`;
|
|
3201
|
+
}
|
|
3202
|
+
else if (frameOptions & FRAMEOPTION_END_OFFSET_FOLLOWING && node.endOffset) {
|
|
3203
|
+
end = `${this.visit(node.endOffset, context)} FOLLOWING`;
|
|
3204
|
+
}
|
|
3205
|
+
if (start) {
|
|
3206
|
+
if (frameOptions & FRAMEOPTION_BETWEEN) {
|
|
3207
|
+
frameParts.push(`BETWEEN ${start} AND ${end ?? 'CURRENT ROW'}`);
|
|
3183
3208
|
}
|
|
3184
|
-
else
|
|
3185
|
-
|
|
3209
|
+
else {
|
|
3210
|
+
frameParts.push(start);
|
|
3186
3211
|
}
|
|
3187
3212
|
}
|
|
3188
|
-
if (
|
|
3189
|
-
frameParts.push('BETWEEN');
|
|
3190
|
-
frameParts.push(boundsParts.join(' '));
|
|
3191
|
-
}
|
|
3192
|
-
// EXCLUDE clause
|
|
3193
|
-
if (frameOptions & 0x8000) { // FRAMEOPTION_EXCLUDE_CURRENT_ROW
|
|
3213
|
+
if (frameOptions & FRAMEOPTION_EXCLUDE_CURRENT_ROW) {
|
|
3194
3214
|
frameParts.push('EXCLUDE CURRENT ROW');
|
|
3195
3215
|
}
|
|
3196
|
-
else if (frameOptions &
|
|
3216
|
+
else if (frameOptions & FRAMEOPTION_EXCLUDE_GROUP) {
|
|
3197
3217
|
frameParts.push('EXCLUDE GROUP');
|
|
3198
3218
|
}
|
|
3199
|
-
else if (frameOptions &
|
|
3219
|
+
else if (frameOptions & FRAMEOPTION_EXCLUDE_TIES) {
|
|
3200
3220
|
frameParts.push('EXCLUDE TIES');
|
|
3201
3221
|
}
|
|
3202
3222
|
return frameParts.join(' ');
|
|
@@ -3275,8 +3295,35 @@ export class Deparser {
|
|
|
3275
3295
|
if (node.ctequery) {
|
|
3276
3296
|
output.push(context.parens(this.visit(node.ctequery, context)));
|
|
3277
3297
|
}
|
|
3298
|
+
if (node.search_clause) {
|
|
3299
|
+
const sc = node.search_clause;
|
|
3300
|
+
const cols = ListUtils.unwrapList(sc.search_col_list).map(c => this.visit(c, context));
|
|
3301
|
+
output.push('SEARCH', sc.search_breadth_first ? 'BREADTH' : 'DEPTH', 'FIRST BY');
|
|
3302
|
+
output.push(cols.join(', '));
|
|
3303
|
+
output.push('SET', QuoteUtils.quoteIdentifier(sc.search_seq_column));
|
|
3304
|
+
}
|
|
3305
|
+
if (node.cycle_clause) {
|
|
3306
|
+
const cc = node.cycle_clause;
|
|
3307
|
+
const cols = ListUtils.unwrapList(cc.cycle_col_list).map(c => this.visit(c, context));
|
|
3308
|
+
output.push('CYCLE', cols.join(', '));
|
|
3309
|
+
output.push('SET', QuoteUtils.quoteIdentifier(cc.cycle_mark_column));
|
|
3310
|
+
if (cc.cycle_mark_value && cc.cycle_mark_default) {
|
|
3311
|
+
output.push('TO', this.formatAexprConst(cc.cycle_mark_value, context));
|
|
3312
|
+
output.push('DEFAULT', this.formatAexprConst(cc.cycle_mark_default, context));
|
|
3313
|
+
}
|
|
3314
|
+
output.push('USING', QuoteUtils.quoteIdentifier(cc.cycle_path_column));
|
|
3315
|
+
}
|
|
3278
3316
|
return output.join(' ');
|
|
3279
3317
|
}
|
|
3318
|
+
// Renders a constant in the restricted AexprConst grammar (e.g. `point '(1,1)'`
|
|
3319
|
+
// rather than `CAST('(1,1)' AS point)`).
|
|
3320
|
+
formatAexprConst(node, context) {
|
|
3321
|
+
const cast = node.TypeCast;
|
|
3322
|
+
if (cast?.arg?.A_Const?.sval && cast.typeName) {
|
|
3323
|
+
return `${this.TypeName(cast.typeName, context)} ${this.visit(cast.arg, context)}`;
|
|
3324
|
+
}
|
|
3325
|
+
return this.visit(node, context);
|
|
3326
|
+
}
|
|
3280
3327
|
ParamRef(node, context) {
|
|
3281
3328
|
return `$${node.number}`;
|
|
3282
3329
|
}
|
|
@@ -3666,9 +3713,9 @@ export class Deparser {
|
|
|
3666
3713
|
output.push(`(${upperValues})`);
|
|
3667
3714
|
}
|
|
3668
3715
|
}
|
|
3669
|
-
else if (node.bound.strategy === 'h'
|
|
3716
|
+
else if (node.bound.strategy === 'h') {
|
|
3670
3717
|
output.push('FOR VALUES WITH');
|
|
3671
|
-
output.push(`(MODULUS ${node.bound.modulus}, REMAINDER ${node.bound.remainder ?? 0})`);
|
|
3718
|
+
output.push(`(MODULUS ${node.bound.modulus ?? 0}, REMAINDER ${node.bound.remainder ?? 0})`);
|
|
3672
3719
|
}
|
|
3673
3720
|
else if (node.bound.is_default) {
|
|
3674
3721
|
output.push('DEFAULT');
|
|
@@ -4521,10 +4568,10 @@ export class Deparser {
|
|
|
4521
4568
|
output.push('PROGRAM');
|
|
4522
4569
|
}
|
|
4523
4570
|
if (node.filename) {
|
|
4524
|
-
output.push(
|
|
4571
|
+
output.push(QuoteUtils.escape(node.filename));
|
|
4525
4572
|
}
|
|
4526
4573
|
else {
|
|
4527
|
-
output.push('STDIN');
|
|
4574
|
+
output.push(node.is_from ? 'STDIN' : 'STDOUT');
|
|
4528
4575
|
}
|
|
4529
4576
|
if (node.options && node.options.length > 0) {
|
|
4530
4577
|
output.push('WITH');
|
|
@@ -4756,6 +4803,9 @@ export class Deparser {
|
|
|
4756
4803
|
const nodeData = this.getNodeData(node.def);
|
|
4757
4804
|
if (nodeData && nodeData.typeName) {
|
|
4758
4805
|
output.push(this.TypeName(nodeData.typeName, context));
|
|
4806
|
+
if (nodeData.collClause) {
|
|
4807
|
+
output.push(this.CollateClause(nodeData.collClause, context));
|
|
4808
|
+
}
|
|
4759
4809
|
// Handle USING clause (stored in raw_default for ALTER COLUMN TYPE)
|
|
4760
4810
|
if (nodeData.raw_default) {
|
|
4761
4811
|
output.push('USING');
|
|
@@ -5236,9 +5286,8 @@ export class Deparser {
|
|
|
5236
5286
|
if (node.name) {
|
|
5237
5287
|
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
5238
5288
|
}
|
|
5239
|
-
output.push('SET');
|
|
5240
5289
|
if (node.def) {
|
|
5241
|
-
output.push(this.
|
|
5290
|
+
output.push(this.formatIdentityColumnOptions(node.def, context));
|
|
5242
5291
|
}
|
|
5243
5292
|
break;
|
|
5244
5293
|
case 'AT_DropIdentity':
|
|
@@ -5247,11 +5296,8 @@ export class Deparser {
|
|
|
5247
5296
|
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
5248
5297
|
}
|
|
5249
5298
|
output.push('DROP IDENTITY');
|
|
5250
|
-
if (node.
|
|
5251
|
-
output.push('
|
|
5252
|
-
}
|
|
5253
|
-
else if (node.behavior === 'DROP_RESTRICT') {
|
|
5254
|
-
output.push('RESTRICT');
|
|
5299
|
+
if (node.missing_ok) {
|
|
5300
|
+
output.push('IF EXISTS');
|
|
5255
5301
|
}
|
|
5256
5302
|
break;
|
|
5257
5303
|
case 'AT_ReAddStatistics':
|
|
@@ -5687,6 +5733,9 @@ export class Deparser {
|
|
|
5687
5733
|
if (node.arg && this.getNodeType(node.arg) === 'List') {
|
|
5688
5734
|
const listData = this.getNodeData(node.arg);
|
|
5689
5735
|
const listItems = ListUtils.unwrapList(listData.items);
|
|
5736
|
+
if (listItems.length === 1 && listItems[0].String?.sval === 'none') {
|
|
5737
|
+
return 'OWNED BY NONE';
|
|
5738
|
+
}
|
|
5690
5739
|
const parts = listItems.map(item => {
|
|
5691
5740
|
const itemData = this.getNodeData(item);
|
|
5692
5741
|
if (this.getNodeType(item) === 'String') {
|
|
@@ -5864,12 +5913,15 @@ export class Deparser {
|
|
|
5864
5913
|
}
|
|
5865
5914
|
// Handle CreateStmt table options - no quotes, compact formatting
|
|
5866
5915
|
if (context.parentNodeTypes.includes('CreateStmt')) {
|
|
5916
|
+
const relOptName = node.defnamespace
|
|
5917
|
+
? `${QuoteUtils.quoteIdentifier(node.defnamespace)}.${QuoteUtils.quoteIdentifier(node.defname)}`
|
|
5918
|
+
: QuoteUtils.quoteIdentifier(node.defname);
|
|
5867
5919
|
// For numeric values, use the raw value without quotes
|
|
5868
5920
|
if (node.arg && this.getNodeType(node.arg) === 'Integer') {
|
|
5869
5921
|
const integerData = this.getNodeData(node.arg);
|
|
5870
|
-
return `${
|
|
5922
|
+
return `${relOptName}=${integerData.ival}`;
|
|
5871
5923
|
}
|
|
5872
|
-
return `${
|
|
5924
|
+
return `${relOptName}=${argValue}`;
|
|
5873
5925
|
}
|
|
5874
5926
|
// Handle CreateEventTrigStmt WHEN clause - use IN syntax for List arguments
|
|
5875
5927
|
if (context.parentNodeTypes.includes('CreateEventTrigStmt')) {
|
|
@@ -5908,15 +5960,27 @@ export class Deparser {
|
|
|
5908
5960
|
}
|
|
5909
5961
|
// Handle CopyStmt WITH clause options - uppercase format without quotes
|
|
5910
5962
|
if (context.parentNodeTypes.includes('CopyStmt')) {
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
return
|
|
5963
|
+
const optName = node.defname.toUpperCase();
|
|
5964
|
+
if (!node.arg) {
|
|
5965
|
+
return optName;
|
|
5966
|
+
}
|
|
5967
|
+
const copyArgType = this.getNodeType(node.arg);
|
|
5968
|
+
if (copyArgType === 'Boolean' && this.getNodeData(node.arg).boolval !== false) {
|
|
5969
|
+
return optName;
|
|
5970
|
+
}
|
|
5971
|
+
if (copyArgType === 'List') {
|
|
5972
|
+
const items = ListUtils.unwrapList(this.getNodeData(node.arg).items)
|
|
5973
|
+
.map(item => this.visit(item, context));
|
|
5974
|
+
return `${optName} (${items.join(', ')})`;
|
|
5914
5975
|
}
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
|
|
5976
|
+
if (copyArgType === 'String') {
|
|
5977
|
+
const sval = this.getNodeData(node.arg).sval;
|
|
5978
|
+
if (node.defname === 'format') {
|
|
5979
|
+
return `${optName} ${sval}`;
|
|
5980
|
+
}
|
|
5981
|
+
return `${optName} ${QuoteUtils.escape(sval)}`;
|
|
5918
5982
|
}
|
|
5919
|
-
return
|
|
5983
|
+
return `${optName} ${argValue}`;
|
|
5920
5984
|
}
|
|
5921
5985
|
// Handle CREATE OPERATOR and CREATE TYPE context
|
|
5922
5986
|
if (context.parentNodeTypes.includes('DefineStmt')) {
|
|
@@ -5997,6 +6061,10 @@ export class Deparser {
|
|
|
5997
6061
|
return `${node.defname} = ${argValue}`;
|
|
5998
6062
|
}
|
|
5999
6063
|
}
|
|
6064
|
+
const argType = this.getNodeType(node.arg);
|
|
6065
|
+
if (argType === 'TypeName' || argType === 'Integer' || argType === 'Float' || argType === 'Boolean') {
|
|
6066
|
+
return `${node.defname} = ${argValue}`;
|
|
6067
|
+
}
|
|
6000
6068
|
const quotedValue = typeof argValue === 'string'
|
|
6001
6069
|
? QuoteUtils.escape(argValue)
|
|
6002
6070
|
: argValue;
|
|
@@ -6430,6 +6498,9 @@ export class Deparser {
|
|
|
6430
6498
|
case 'OBJECT_TABCONSTRAINT':
|
|
6431
6499
|
output.push('CONSTRAINT');
|
|
6432
6500
|
break;
|
|
6501
|
+
case 'OBJECT_DOMCONSTRAINT':
|
|
6502
|
+
output.push('CONSTRAINT');
|
|
6503
|
+
break;
|
|
6433
6504
|
case 'OBJECT_TRIGGER':
|
|
6434
6505
|
output.push('TRIGGER');
|
|
6435
6506
|
break;
|
|
@@ -6506,6 +6577,15 @@ export class Deparser {
|
|
|
6506
6577
|
output.push(objectParts.join('.'));
|
|
6507
6578
|
}
|
|
6508
6579
|
}
|
|
6580
|
+
else if (node.objtype === 'OBJECT_DOMCONSTRAINT') {
|
|
6581
|
+
if (objectParts.length === 2) {
|
|
6582
|
+
const [domain, constraint] = objectParts;
|
|
6583
|
+
output.push(constraint, 'ON DOMAIN', domain);
|
|
6584
|
+
}
|
|
6585
|
+
else {
|
|
6586
|
+
output.push(objectParts.join('.'));
|
|
6587
|
+
}
|
|
6588
|
+
}
|
|
6509
6589
|
else if (node.objtype === 'OBJECT_TRIGGER') {
|
|
6510
6590
|
if (objectParts.length === 2) {
|
|
6511
6591
|
const [table, trigger] = objectParts;
|
|
@@ -6837,7 +6917,7 @@ export class Deparser {
|
|
|
6837
6917
|
output.push(QuoteUtils.quoteIdentifier(node.pubname));
|
|
6838
6918
|
}
|
|
6839
6919
|
if (node.pubobjects && node.pubobjects.length > 0) {
|
|
6840
|
-
output.push('FOR'
|
|
6920
|
+
output.push('FOR');
|
|
6841
6921
|
const tables = ListUtils.unwrapList(node.pubobjects).map(table => this.visit(table, context));
|
|
6842
6922
|
output.push(tables.join(', '));
|
|
6843
6923
|
}
|
|
@@ -6877,8 +6957,9 @@ export class Deparser {
|
|
|
6877
6957
|
if (node.pubname) {
|
|
6878
6958
|
output.push(QuoteUtils.quoteIdentifier(node.pubname));
|
|
6879
6959
|
}
|
|
6880
|
-
|
|
6881
|
-
|
|
6960
|
+
const hasObjects = node.pubobjects && node.pubobjects.length > 0;
|
|
6961
|
+
if (hasObjects) {
|
|
6962
|
+
switch (node.action || 'AP_AddObjects') {
|
|
6882
6963
|
case 'AP_AddObjects':
|
|
6883
6964
|
output.push('ADD');
|
|
6884
6965
|
break;
|
|
@@ -6891,17 +6972,11 @@ export class Deparser {
|
|
|
6891
6972
|
default:
|
|
6892
6973
|
throw new Error(`Unsupported AlterPublicationStmt action: ${node.action}`);
|
|
6893
6974
|
}
|
|
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
6975
|
const objects = ListUtils.unwrapList(node.pubobjects).map(obj => this.visit(obj, context));
|
|
6901
6976
|
output.push(objects.join(', '));
|
|
6902
6977
|
}
|
|
6903
|
-
if (node.options && node.options.length > 0) {
|
|
6904
|
-
output.push('
|
|
6978
|
+
else if (node.options && node.options.length > 0) {
|
|
6979
|
+
output.push('SET');
|
|
6905
6980
|
const options = ListUtils.unwrapList(node.options).map(opt => this.visit(opt, context));
|
|
6906
6981
|
output.push(`(${options.join(', ')})`);
|
|
6907
6982
|
}
|
|
@@ -6912,42 +6987,67 @@ export class Deparser {
|
|
|
6912
6987
|
if (node.subname) {
|
|
6913
6988
|
output.push(QuoteUtils.quoteIdentifier(node.subname));
|
|
6914
6989
|
}
|
|
6915
|
-
|
|
6916
|
-
|
|
6990
|
+
const options = node.options && node.options.length > 0
|
|
6991
|
+
? `(${ListUtils.unwrapList(node.options).map(opt => this.visit(opt, context)).join(', ')})`
|
|
6992
|
+
: null;
|
|
6993
|
+
const publications = node.publication && node.publication.length > 0
|
|
6994
|
+
? ListUtils.unwrapList(node.publication).map(pub => this.visit(pub, context)).join(', ')
|
|
6995
|
+
: null;
|
|
6996
|
+
{
|
|
6997
|
+
switch (node.kind || 'ALTER_SUBSCRIPTION_OPTIONS') {
|
|
6917
6998
|
case 'ALTER_SUBSCRIPTION_OPTIONS':
|
|
6918
6999
|
output.push('SET');
|
|
7000
|
+
if (options)
|
|
7001
|
+
output.push(options);
|
|
6919
7002
|
break;
|
|
6920
7003
|
case 'ALTER_SUBSCRIPTION_CONNECTION':
|
|
6921
7004
|
output.push('CONNECTION');
|
|
6922
7005
|
if (node.conninfo) {
|
|
6923
|
-
output.push(
|
|
7006
|
+
output.push(QuoteUtils.escape(node.conninfo));
|
|
6924
7007
|
}
|
|
6925
7008
|
break;
|
|
6926
7009
|
case 'ALTER_SUBSCRIPTION_SET_PUBLICATION':
|
|
6927
7010
|
output.push('SET PUBLICATION');
|
|
6928
|
-
if (
|
|
6929
|
-
|
|
6930
|
-
|
|
6931
|
-
|
|
7011
|
+
if (publications)
|
|
7012
|
+
output.push(publications);
|
|
7013
|
+
if (options)
|
|
7014
|
+
output.push('WITH', options);
|
|
7015
|
+
break;
|
|
7016
|
+
case 'ALTER_SUBSCRIPTION_ADD_PUBLICATION':
|
|
7017
|
+
output.push('ADD PUBLICATION');
|
|
7018
|
+
if (publications)
|
|
7019
|
+
output.push(publications);
|
|
7020
|
+
if (options)
|
|
7021
|
+
output.push('WITH', options);
|
|
7022
|
+
break;
|
|
7023
|
+
case 'ALTER_SUBSCRIPTION_DROP_PUBLICATION':
|
|
7024
|
+
output.push('DROP PUBLICATION');
|
|
7025
|
+
if (publications)
|
|
7026
|
+
output.push(publications);
|
|
7027
|
+
if (options)
|
|
7028
|
+
output.push('WITH', options);
|
|
6932
7029
|
break;
|
|
6933
7030
|
case 'ALTER_SUBSCRIPTION_REFRESH':
|
|
6934
7031
|
output.push('REFRESH PUBLICATION');
|
|
7032
|
+
if (options)
|
|
7033
|
+
output.push('WITH', options);
|
|
6935
7034
|
break;
|
|
6936
|
-
case 'ALTER_SUBSCRIPTION_ENABLED':
|
|
6937
|
-
|
|
7035
|
+
case 'ALTER_SUBSCRIPTION_ENABLED': {
|
|
7036
|
+
const enabled = ListUtils.unwrapList(node.options).find(opt => opt.DefElem?.defname === 'enabled');
|
|
7037
|
+
const arg = enabled?.DefElem?.arg;
|
|
7038
|
+
const isEnabled = arg?.Boolean ? arg.Boolean.boolval !== false : true;
|
|
7039
|
+
output.push(isEnabled ? 'ENABLE' : 'DISABLE');
|
|
6938
7040
|
break;
|
|
7041
|
+
}
|
|
6939
7042
|
case 'ALTER_SUBSCRIPTION_SKIP':
|
|
6940
7043
|
output.push('SKIP');
|
|
7044
|
+
if (options)
|
|
7045
|
+
output.push(options);
|
|
6941
7046
|
break;
|
|
6942
7047
|
default:
|
|
6943
7048
|
throw new Error(`Unsupported AlterSubscriptionStmt kind: ${node.kind}`);
|
|
6944
7049
|
}
|
|
6945
7050
|
}
|
|
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
7051
|
return output.join(' ');
|
|
6952
7052
|
}
|
|
6953
7053
|
DropSubscriptionStmt(node, context) {
|
|
@@ -8013,6 +8113,9 @@ export class Deparser {
|
|
|
8013
8113
|
if (node.grant_option && node.is_grant) {
|
|
8014
8114
|
output.push('WITH GRANT OPTION');
|
|
8015
8115
|
}
|
|
8116
|
+
if (node.grantor) {
|
|
8117
|
+
output.push('GRANTED BY', this.RoleSpec(node.grantor, context));
|
|
8118
|
+
}
|
|
8016
8119
|
// Only add behavior clauses for REVOKE statements, not for GRANT statements in ALTER DEFAULT PRIVILEGES
|
|
8017
8120
|
if (!node.is_grant) {
|
|
8018
8121
|
if (node.behavior === 'DROP_CASCADE') {
|
|
@@ -8026,57 +8129,34 @@ export class Deparser {
|
|
|
8026
8129
|
}
|
|
8027
8130
|
GrantRoleStmt(node, context) {
|
|
8028
8131
|
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
|
-
}
|
|
8132
|
+
const options = ListUtils.unwrapList(node.opt)
|
|
8133
|
+
.map(opt => opt.DefElem)
|
|
8134
|
+
.filter((opt) => !!opt && !!opt.defname);
|
|
8135
|
+
const optionValue = (opt) => {
|
|
8136
|
+
if (!opt.arg)
|
|
8137
|
+
return true;
|
|
8138
|
+
const argType = this.getNodeType(opt.arg);
|
|
8139
|
+
const argData = this.getNodeData(opt.arg);
|
|
8140
|
+
if (argType === 'Boolean')
|
|
8141
|
+
return argData.boolval !== false;
|
|
8142
|
+
if (argType === 'String')
|
|
8143
|
+
return argData.sval !== 'false';
|
|
8144
|
+
return true;
|
|
8145
|
+
};
|
|
8146
|
+
const roles = ListUtils.unwrapList(node.granted_roles)
|
|
8147
|
+
.map(role => role.AccessPriv?.priv_name
|
|
8148
|
+
? QuoteUtils.quoteIdentifier(role.AccessPriv.priv_name)
|
|
8149
|
+
: this.visit(role, context))
|
|
8150
|
+
.join(', ');
|
|
8057
8151
|
if (node.is_grant) {
|
|
8058
|
-
output.push('GRANT');
|
|
8152
|
+
output.push('GRANT', roles, 'TO');
|
|
8059
8153
|
}
|
|
8060
8154
|
else {
|
|
8061
8155
|
output.push('REVOKE');
|
|
8062
|
-
if (
|
|
8063
|
-
output.push(
|
|
8064
|
-
}
|
|
8065
|
-
else if (hasAdminOption) {
|
|
8066
|
-
output.push('ADMIN OPTION FOR');
|
|
8156
|
+
if (options.length > 0) {
|
|
8157
|
+
output.push(`${options[0].defname.toUpperCase()} OPTION FOR`);
|
|
8067
8158
|
}
|
|
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');
|
|
8159
|
+
output.push(roles, 'FROM');
|
|
8080
8160
|
}
|
|
8081
8161
|
if (node.grantee_roles && node.grantee_roles.length > 0) {
|
|
8082
8162
|
const grantees = ListUtils.unwrapList(node.grantee_roles)
|
|
@@ -8084,38 +8164,15 @@ export class Deparser {
|
|
|
8084
8164
|
.join(', ');
|
|
8085
8165
|
output.push(grantees);
|
|
8086
8166
|
}
|
|
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
|
-
}
|
|
8167
|
+
if (node.is_grant && options.length > 0) {
|
|
8168
|
+
const withOptions = options.map(opt => `${opt.defname.toUpperCase()} ${optionValue(opt) ? 'TRUE' : 'FALSE'}`);
|
|
8169
|
+
output.push('WITH', withOptions.join(', '));
|
|
8170
|
+
}
|
|
8171
|
+
if (node.grantor) {
|
|
8172
|
+
output.push('GRANTED BY', this.RoleSpec(node.grantor, context));
|
|
8173
|
+
}
|
|
8174
|
+
if (!node.is_grant && node.behavior === 'DROP_CASCADE') {
|
|
8175
|
+
output.push('CASCADE');
|
|
8119
8176
|
}
|
|
8120
8177
|
return output.join(' ');
|
|
8121
8178
|
}
|
|
@@ -8695,10 +8752,9 @@ export class Deparser {
|
|
|
8695
8752
|
switch (node.commandType) {
|
|
8696
8753
|
case 'CMD_UPDATE': {
|
|
8697
8754
|
output.push('UPDATE SET');
|
|
8698
|
-
|
|
8699
|
-
.
|
|
8700
|
-
|
|
8701
|
-
output.push(assignments);
|
|
8755
|
+
if (node.targetList && node.targetList.length > 0) {
|
|
8756
|
+
output.push(this.formatUpdateAssignments(node.targetList, context));
|
|
8757
|
+
}
|
|
8702
8758
|
break;
|
|
8703
8759
|
}
|
|
8704
8760
|
case 'CMD_INSERT': {
|
|
@@ -9103,6 +9159,13 @@ export class Deparser {
|
|
|
9103
9159
|
output.push('USING');
|
|
9104
9160
|
output.push(node.into.accessMethod);
|
|
9105
9161
|
}
|
|
9162
|
+
if (node.into && node.into.options && node.into.options.length > 0) {
|
|
9163
|
+
output.push('WITH');
|
|
9164
|
+
const options = ListUtils.unwrapList(node.into.options)
|
|
9165
|
+
.map(option => this.visit(option, context.spawn('CreateStmt')))
|
|
9166
|
+
.join(', ');
|
|
9167
|
+
output.push(`(${options})`);
|
|
9168
|
+
}
|
|
9106
9169
|
if (node.into && node.into.onCommit && node.into.onCommit !== 'ONCOMMIT_NOOP') {
|
|
9107
9170
|
output.push('ON COMMIT');
|
|
9108
9171
|
switch (node.into.onCommit) {
|
|
@@ -9117,17 +9180,13 @@ export class Deparser {
|
|
|
9117
9180
|
break;
|
|
9118
9181
|
}
|
|
9119
9182
|
}
|
|
9183
|
+
if (node.into && node.into.tableSpaceName) {
|
|
9184
|
+
output.push('TABLESPACE', QuoteUtils.quoteIdentifier(node.into.tableSpaceName));
|
|
9185
|
+
}
|
|
9120
9186
|
output.push('AS');
|
|
9121
9187
|
if (node.query) {
|
|
9122
9188
|
output.push(this.visit(node.query, context));
|
|
9123
9189
|
}
|
|
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
9190
|
if (node.into && node.into.skipData) {
|
|
9132
9191
|
output.push('WITH NO DATA');
|
|
9133
9192
|
}
|
|
@@ -9600,7 +9659,7 @@ export class Deparser {
|
|
|
9600
9659
|
}
|
|
9601
9660
|
if (node.whereClause) {
|
|
9602
9661
|
output.push('WHERE');
|
|
9603
|
-
output.push(this.visit(node.whereClause, context));
|
|
9662
|
+
output.push(`(${this.visit(node.whereClause, context)})`);
|
|
9604
9663
|
}
|
|
9605
9664
|
return output.join(' ');
|
|
9606
9665
|
}
|
|
@@ -9843,24 +9902,182 @@ export class Deparser {
|
|
|
9843
9902
|
}
|
|
9844
9903
|
return output.join(' ');
|
|
9845
9904
|
}
|
|
9905
|
+
formatJsonFormat(format) {
|
|
9906
|
+
if (!format || !format.format_type || format.format_type === 'JS_FORMAT_DEFAULT') {
|
|
9907
|
+
return null;
|
|
9908
|
+
}
|
|
9909
|
+
const parts = ['FORMAT JSON'];
|
|
9910
|
+
switch (format.encoding) {
|
|
9911
|
+
case 'JS_ENC_UTF8':
|
|
9912
|
+
parts.push('ENCODING UTF8');
|
|
9913
|
+
break;
|
|
9914
|
+
case 'JS_ENC_UTF16':
|
|
9915
|
+
parts.push('ENCODING UTF16');
|
|
9916
|
+
break;
|
|
9917
|
+
case 'JS_ENC_UTF32':
|
|
9918
|
+
parts.push('ENCODING UTF32');
|
|
9919
|
+
break;
|
|
9920
|
+
}
|
|
9921
|
+
return parts.join(' ');
|
|
9922
|
+
}
|
|
9923
|
+
formatJsonOutput(output, context) {
|
|
9924
|
+
if (!output || !output.typeName)
|
|
9925
|
+
return null;
|
|
9926
|
+
const parts = ['RETURNING', this.TypeName(output.typeName, context)];
|
|
9927
|
+
const format = this.formatJsonFormat(output.returning?.format);
|
|
9928
|
+
if (format)
|
|
9929
|
+
parts.push(format);
|
|
9930
|
+
return parts.join(' ');
|
|
9931
|
+
}
|
|
9932
|
+
formatJsonNullClause(absentOnNull) {
|
|
9933
|
+
return absentOnNull ? 'ABSENT ON NULL' : 'NULL ON NULL';
|
|
9934
|
+
}
|
|
9935
|
+
formatJsonUniqueClause(unique) {
|
|
9936
|
+
return unique ? 'WITH UNIQUE KEYS' : null;
|
|
9937
|
+
}
|
|
9938
|
+
JsonValueExpr(node, context) {
|
|
9939
|
+
const parts = [];
|
|
9940
|
+
if (node.raw_expr) {
|
|
9941
|
+
parts.push(this.visit(node.raw_expr, context));
|
|
9942
|
+
}
|
|
9943
|
+
const format = this.formatJsonFormat(node.format);
|
|
9944
|
+
if (format)
|
|
9945
|
+
parts.push(format);
|
|
9946
|
+
return parts.join(' ');
|
|
9947
|
+
}
|
|
9948
|
+
JsonKeyValue(node, context) {
|
|
9949
|
+
const key = node.key ? this.visit(node.key, context) : '';
|
|
9950
|
+
const value = node.value ? this.JsonValueExpr(node.value, context) : '';
|
|
9951
|
+
return `${key} : ${value}`;
|
|
9952
|
+
}
|
|
9953
|
+
JsonObjectConstructor(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
|
+
const unique = this.formatJsonUniqueClause(node.unique);
|
|
9959
|
+
if (unique)
|
|
9960
|
+
args.push(unique);
|
|
9961
|
+
}
|
|
9962
|
+
const output = this.formatJsonOutput(node.output, context);
|
|
9963
|
+
if (output)
|
|
9964
|
+
args.push(output);
|
|
9965
|
+
return `JSON_OBJECT(${args.join(' ')})`;
|
|
9966
|
+
}
|
|
9967
|
+
JsonArrayConstructor(node, context) {
|
|
9968
|
+
const args = [];
|
|
9969
|
+
if (node.exprs && node.exprs.length > 0) {
|
|
9970
|
+
args.push(ListUtils.unwrapList(node.exprs).map(e => this.visit(e, context)).join(', '));
|
|
9971
|
+
args.push(this.formatJsonNullClause(node.absent_on_null));
|
|
9972
|
+
}
|
|
9973
|
+
const output = this.formatJsonOutput(node.output, context);
|
|
9974
|
+
if (output)
|
|
9975
|
+
args.push(output);
|
|
9976
|
+
return `JSON_ARRAY(${args.join(' ')})`;
|
|
9977
|
+
}
|
|
9846
9978
|
JsonArrayQueryConstructor(node, context) {
|
|
9847
|
-
const
|
|
9979
|
+
const args = [];
|
|
9848
9980
|
if (node.query) {
|
|
9849
|
-
|
|
9981
|
+
args.push(this.visit(node.query, context));
|
|
9982
|
+
}
|
|
9983
|
+
const format = this.formatJsonFormat(node.format);
|
|
9984
|
+
if (format)
|
|
9985
|
+
args.push(format);
|
|
9986
|
+
const output = this.formatJsonOutput(node.output, context);
|
|
9987
|
+
if (output)
|
|
9988
|
+
args.push(output);
|
|
9989
|
+
return `JSON_ARRAY(${args.join(' ')})`;
|
|
9990
|
+
}
|
|
9991
|
+
formatJsonAggSuffix(ctor, context) {
|
|
9992
|
+
if (!ctor)
|
|
9993
|
+
return '';
|
|
9994
|
+
let result = '';
|
|
9995
|
+
if (ctor.agg_filter) {
|
|
9996
|
+
result += ` FILTER (WHERE ${this.visit(ctor.agg_filter, context)})`;
|
|
9850
9997
|
}
|
|
9851
|
-
if (
|
|
9852
|
-
|
|
9998
|
+
if (ctor.over) {
|
|
9999
|
+
result += this.formatOverClause(ctor.over, context);
|
|
9853
10000
|
}
|
|
9854
|
-
|
|
9855
|
-
|
|
10001
|
+
return result;
|
|
10002
|
+
}
|
|
10003
|
+
JsonObjectAgg(node, context) {
|
|
10004
|
+
const args = [];
|
|
10005
|
+
if (node.arg) {
|
|
10006
|
+
args.push(this.JsonKeyValue(node.arg, context));
|
|
10007
|
+
}
|
|
10008
|
+
args.push(this.formatJsonNullClause(node.absent_on_null));
|
|
10009
|
+
const unique = this.formatJsonUniqueClause(node.unique);
|
|
10010
|
+
if (unique)
|
|
10011
|
+
args.push(unique);
|
|
10012
|
+
const output = this.formatJsonOutput(node.constructor?.output, context);
|
|
10013
|
+
if (output)
|
|
10014
|
+
args.push(output);
|
|
10015
|
+
return `JSON_OBJECTAGG(${args.join(' ')})${this.formatJsonAggSuffix(node.constructor, context)}`;
|
|
10016
|
+
}
|
|
10017
|
+
JsonArrayAgg(node, context) {
|
|
10018
|
+
const args = [];
|
|
10019
|
+
if (node.arg) {
|
|
10020
|
+
args.push(this.JsonValueExpr(node.arg, context));
|
|
9856
10021
|
}
|
|
9857
|
-
|
|
9858
|
-
|
|
10022
|
+
const aggOrder = node.constructor?.agg_order;
|
|
10023
|
+
if (aggOrder && aggOrder.length > 0) {
|
|
10024
|
+
const orderItems = ListUtils.unwrapList(aggOrder).map(item => this.visit(item, context));
|
|
10025
|
+
args.push(`ORDER BY ${orderItems.join(', ')}`);
|
|
9859
10026
|
}
|
|
9860
|
-
|
|
9861
|
-
|
|
10027
|
+
args.push(this.formatJsonNullClause(node.absent_on_null));
|
|
10028
|
+
const output = this.formatJsonOutput(node.constructor?.output, context);
|
|
10029
|
+
if (output)
|
|
10030
|
+
args.push(output);
|
|
10031
|
+
return `JSON_ARRAYAGG(${args.join(' ')})${this.formatJsonAggSuffix(node.constructor, context)}`;
|
|
10032
|
+
}
|
|
10033
|
+
JsonParseExpr(node, context) {
|
|
10034
|
+
const args = [];
|
|
10035
|
+
if (node.expr) {
|
|
10036
|
+
args.push(this.JsonValueExpr(node.expr, context));
|
|
9862
10037
|
}
|
|
9863
|
-
|
|
10038
|
+
const unique = this.formatJsonUniqueClause(node.unique_keys);
|
|
10039
|
+
if (unique)
|
|
10040
|
+
args.push(unique);
|
|
10041
|
+
return `JSON(${args.join(' ')})`;
|
|
10042
|
+
}
|
|
10043
|
+
JsonScalarExpr(node, context) {
|
|
10044
|
+
const expr = node.expr ? this.visit(node.expr, context) : '';
|
|
10045
|
+
return `JSON_SCALAR(${expr})`;
|
|
10046
|
+
}
|
|
10047
|
+
JsonSerializeExpr(node, context) {
|
|
10048
|
+
const args = [];
|
|
10049
|
+
if (node.expr) {
|
|
10050
|
+
args.push(this.JsonValueExpr(node.expr, context));
|
|
10051
|
+
}
|
|
10052
|
+
const output = this.formatJsonOutput(node.output, context);
|
|
10053
|
+
if (output)
|
|
10054
|
+
args.push(output);
|
|
10055
|
+
return `JSON_SERIALIZE(${args.join(' ')})`;
|
|
10056
|
+
}
|
|
10057
|
+
JsonIsPredicate(node, context) {
|
|
10058
|
+
const parts = [];
|
|
10059
|
+
if (node.expr) {
|
|
10060
|
+
parts.push(this.visit(node.expr, context));
|
|
10061
|
+
}
|
|
10062
|
+
const format = this.formatJsonFormat(node.format);
|
|
10063
|
+
if (format)
|
|
10064
|
+
parts.push(format);
|
|
10065
|
+
parts.push('IS JSON');
|
|
10066
|
+
switch (node.item_type) {
|
|
10067
|
+
case 'JS_TYPE_OBJECT':
|
|
10068
|
+
parts.push('OBJECT');
|
|
10069
|
+
break;
|
|
10070
|
+
case 'JS_TYPE_ARRAY':
|
|
10071
|
+
parts.push('ARRAY');
|
|
10072
|
+
break;
|
|
10073
|
+
case 'JS_TYPE_SCALAR':
|
|
10074
|
+
parts.push('SCALAR');
|
|
10075
|
+
break;
|
|
10076
|
+
}
|
|
10077
|
+
if (node.unique_keys) {
|
|
10078
|
+
parts.push('WITH UNIQUE KEYS');
|
|
10079
|
+
}
|
|
10080
|
+
return parts.join(' ');
|
|
9864
10081
|
}
|
|
9865
10082
|
RangeFunction(node, context) {
|
|
9866
10083
|
const output = [];
|