pgsql-deparser 17.18.5 → 18.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/deparser.d.ts +5 -0
- package/deparser.js +139 -65
- package/esm/deparser.js +139 -65
- package/package.json +5 -5
package/deparser.d.ts
CHANGED
|
@@ -80,6 +80,10 @@ export declare class Deparser implements DeparserVisitor {
|
|
|
80
80
|
DeleteStmt(node: t.DeleteStmt, context: DeparserContext): string;
|
|
81
81
|
WithClause(node: t.WithClause, context: DeparserContext): string;
|
|
82
82
|
ResTarget(node: t.ResTarget, context: DeparserContext): string;
|
|
83
|
+
ATAlterConstraint(node: t.ATAlterConstraint, context: DeparserContext): string;
|
|
84
|
+
deparseKeyAttrs(attrs: t.Node[], withPeriod: boolean | undefined, context: DeparserContext): string;
|
|
85
|
+
ReturningClause(node: t.ReturningClause, context: DeparserContext): string;
|
|
86
|
+
ReturningOption(node: t.ReturningOption, context: DeparserContext): string;
|
|
83
87
|
deparseReturningList(list: t.Node[], context: DeparserContext): string;
|
|
84
88
|
BoolExpr(node: t.BoolExpr, context: DeparserContext): string;
|
|
85
89
|
FuncCall(node: t.FuncCall, context: DeparserContext): string;
|
|
@@ -247,6 +251,7 @@ export declare class Deparser implements DeparserVisitor {
|
|
|
247
251
|
CreateOpFamilyStmt(node: t.CreateOpFamilyStmt, context: DeparserContext): string;
|
|
248
252
|
AlterOpFamilyStmt(node: t.AlterOpFamilyStmt, context: DeparserContext): string;
|
|
249
253
|
MergeStmt(node: t.MergeStmt, context: DeparserContext): string;
|
|
254
|
+
MergeSupportFunc(node: t.MergeSupportFunc, context: DeparserContext): string;
|
|
250
255
|
MergeWhenClause(node: t.MergeWhenClause, context: DeparserContext): string;
|
|
251
256
|
AlterTableMoveAllStmt(node: t.AlterTableMoveAllStmt, context: DeparserContext): string;
|
|
252
257
|
CreateSeqStmt(node: t.CreateSeqStmt, context: DeparserContext): string;
|
package/deparser.js
CHANGED
|
@@ -1045,11 +1045,8 @@ class Deparser {
|
|
|
1045
1045
|
output.push('DO NOTHING');
|
|
1046
1046
|
}
|
|
1047
1047
|
}
|
|
1048
|
-
if (node.
|
|
1049
|
-
output.push(
|
|
1050
|
-
const returningList = list_utils_1.ListUtils.unwrapList(node.returningList);
|
|
1051
|
-
const returns = returningList.map(ret => this.visit(ret, context));
|
|
1052
|
-
output.push(returns.join(', '));
|
|
1048
|
+
if (node.returningClause) {
|
|
1049
|
+
output.push(this.ReturningClause(node.returningClause, context));
|
|
1053
1050
|
}
|
|
1054
1051
|
return output.join(' ');
|
|
1055
1052
|
}
|
|
@@ -1106,9 +1103,8 @@ class Deparser {
|
|
|
1106
1103
|
output.push('WHERE');
|
|
1107
1104
|
output.push(this.visit(node.whereClause, context));
|
|
1108
1105
|
}
|
|
1109
|
-
if (node.
|
|
1110
|
-
output.push(
|
|
1111
|
-
output.push(this.deparseReturningList(node.returningList, context));
|
|
1106
|
+
if (node.returningClause) {
|
|
1107
|
+
output.push(this.ReturningClause(node.returningClause, context));
|
|
1112
1108
|
}
|
|
1113
1109
|
return output.join(' ');
|
|
1114
1110
|
}
|
|
@@ -1159,13 +1155,12 @@ class Deparser {
|
|
|
1159
1155
|
throw new Error(`Error deparsing DeleteStmt: ${error instanceof Error ? error.message : String(error)}`);
|
|
1160
1156
|
}
|
|
1161
1157
|
}
|
|
1162
|
-
if (node.
|
|
1163
|
-
output.push('RETURNING');
|
|
1158
|
+
if (node.returningClause) {
|
|
1164
1159
|
try {
|
|
1165
|
-
output.push(this.
|
|
1160
|
+
output.push(this.ReturningClause(node.returningClause, context));
|
|
1166
1161
|
}
|
|
1167
1162
|
catch (error) {
|
|
1168
|
-
console.warn(`Error processing
|
|
1163
|
+
console.warn(`Error processing returningClause in DeleteStmt: ${error instanceof Error ? error.message : String(error)}`);
|
|
1169
1164
|
throw new Error(`Error deparsing DeleteStmt: ${error instanceof Error ? error.message : String(error)}`);
|
|
1170
1165
|
}
|
|
1171
1166
|
}
|
|
@@ -1243,6 +1238,48 @@ class Deparser {
|
|
|
1243
1238
|
}
|
|
1244
1239
|
return output.join(' ');
|
|
1245
1240
|
}
|
|
1241
|
+
ATAlterConstraint(node, context) {
|
|
1242
|
+
const output = ['ALTER CONSTRAINT'];
|
|
1243
|
+
if (node.conname) {
|
|
1244
|
+
output.push(quotes_1.QuoteUtils.quoteIdentifier(node.conname));
|
|
1245
|
+
}
|
|
1246
|
+
if (node.alterEnforceability) {
|
|
1247
|
+
output.push(node.is_enforced ? 'ENFORCED' : 'NOT ENFORCED');
|
|
1248
|
+
}
|
|
1249
|
+
if (node.alterDeferrability) {
|
|
1250
|
+
output.push(node.deferrable ? 'DEFERRABLE' : 'NOT DEFERRABLE');
|
|
1251
|
+
if (node.initdeferred) {
|
|
1252
|
+
output.push('INITIALLY DEFERRED');
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
if (node.alterInheritability) {
|
|
1256
|
+
output.push(node.noinherit ? 'NO INHERIT' : 'INHERIT');
|
|
1257
|
+
}
|
|
1258
|
+
return output.join(' ');
|
|
1259
|
+
}
|
|
1260
|
+
deparseKeyAttrs(attrs, withPeriod, context) {
|
|
1261
|
+
const items = list_utils_1.ListUtils.unwrapList(attrs).map(attr => this.visit(attr, context));
|
|
1262
|
+
if (withPeriod && items.length > 0) {
|
|
1263
|
+
items[items.length - 1] = `PERIOD ${items[items.length - 1]}`;
|
|
1264
|
+
}
|
|
1265
|
+
return items.join(', ');
|
|
1266
|
+
}
|
|
1267
|
+
ReturningClause(node, context) {
|
|
1268
|
+
const output = ['RETURNING'];
|
|
1269
|
+
if (node.options && node.options.length > 0) {
|
|
1270
|
+
const options = list_utils_1.ListUtils.unwrapList(node.options)
|
|
1271
|
+
.map(option => this.visit(option, context));
|
|
1272
|
+
output.push(`WITH (${options.join(', ')})`);
|
|
1273
|
+
}
|
|
1274
|
+
if (node.exprs && node.exprs.length > 0) {
|
|
1275
|
+
output.push(this.deparseReturningList(node.exprs, context));
|
|
1276
|
+
}
|
|
1277
|
+
return output.join(' ');
|
|
1278
|
+
}
|
|
1279
|
+
ReturningOption(node, context) {
|
|
1280
|
+
const keyword = node.option === 'RETURNING_OPTION_NEW' ? 'NEW' : 'OLD';
|
|
1281
|
+
return `${keyword} AS ${quotes_1.QuoteUtils.quoteIdentifier(node.value)}`;
|
|
1282
|
+
}
|
|
1246
1283
|
deparseReturningList(list, context) {
|
|
1247
1284
|
return list_utils_1.ListUtils.unwrapList(list)
|
|
1248
1285
|
.filter(item => item != null && this.getNodeType(item) !== 'undefined')
|
|
@@ -2539,7 +2576,7 @@ class Deparser {
|
|
|
2539
2576
|
Constraint(node, context) {
|
|
2540
2577
|
const output = [];
|
|
2541
2578
|
// Handle constraint name if present
|
|
2542
|
-
if (node.conname && (node.contype === 'CONSTR_CHECK' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_FOREIGN')) {
|
|
2579
|
+
if (node.conname && (node.contype === 'CONSTR_CHECK' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_FOREIGN' || node.contype === 'CONSTR_NOTNULL')) {
|
|
2543
2580
|
output.push('CONSTRAINT');
|
|
2544
2581
|
output.push(quotes_1.QuoteUtils.quoteIdentifier(node.conname));
|
|
2545
2582
|
}
|
|
@@ -2549,6 +2586,18 @@ class Deparser {
|
|
|
2549
2586
|
break;
|
|
2550
2587
|
case 'CONSTR_NOTNULL':
|
|
2551
2588
|
output.push('NOT NULL');
|
|
2589
|
+
if (node.keys && node.keys.length > 0 && !context.isColumnConstraint) {
|
|
2590
|
+
const keyList = list_utils_1.ListUtils.unwrapList(node.keys)
|
|
2591
|
+
.map(key => this.visit(key, context))
|
|
2592
|
+
.join(', ');
|
|
2593
|
+
output.push(keyList);
|
|
2594
|
+
}
|
|
2595
|
+
if (node.is_no_inherit) {
|
|
2596
|
+
output.push('NO INHERIT');
|
|
2597
|
+
}
|
|
2598
|
+
if (node.skip_validation) {
|
|
2599
|
+
output.push('NOT VALID');
|
|
2600
|
+
}
|
|
2552
2601
|
break;
|
|
2553
2602
|
case 'CONSTR_DEFAULT':
|
|
2554
2603
|
output.push('DEFAULT');
|
|
@@ -2577,8 +2626,13 @@ class Deparser {
|
|
|
2577
2626
|
output.push(context.parens(this.visit(node.raw_expr, context)));
|
|
2578
2627
|
}
|
|
2579
2628
|
}
|
|
2580
|
-
//
|
|
2581
|
-
|
|
2629
|
+
// PG18: constraints are enforced unless explicitly NOT ENFORCED
|
|
2630
|
+
// (libpg-query omits false booleans, so undefined means not enforced)
|
|
2631
|
+
if (node.is_enforced !== true && !context.isDomainConstraint) {
|
|
2632
|
+
output.push('NOT ENFORCED');
|
|
2633
|
+
}
|
|
2634
|
+
else if (node.skip_validation) {
|
|
2635
|
+
// NOT ENFORCED implies NOT VALID, so only emit NOT VALID when enforced
|
|
2582
2636
|
output.push('NOT VALID');
|
|
2583
2637
|
}
|
|
2584
2638
|
// Handle NO INHERIT for check constraints - only for table constraints, not domain constraints
|
|
@@ -2598,7 +2652,7 @@ class Deparser {
|
|
|
2598
2652
|
if (node.raw_expr) {
|
|
2599
2653
|
output.push(context.parens(this.visit(node.raw_expr, context)));
|
|
2600
2654
|
}
|
|
2601
|
-
output.push('STORED');
|
|
2655
|
+
output.push(node.generated_kind === 'v' ? 'VIRTUAL' : 'STORED');
|
|
2602
2656
|
break;
|
|
2603
2657
|
case 'CONSTR_IDENTITY':
|
|
2604
2658
|
output.push('GENERATED');
|
|
@@ -2674,10 +2728,12 @@ class Deparser {
|
|
|
2674
2728
|
case 'CONSTR_PRIMARY':
|
|
2675
2729
|
output.push('PRIMARY KEY');
|
|
2676
2730
|
if (node.keys && node.keys.length > 0) {
|
|
2677
|
-
const
|
|
2678
|
-
.map(key => this.visit(key, context))
|
|
2679
|
-
|
|
2680
|
-
|
|
2731
|
+
const keyItems = list_utils_1.ListUtils.unwrapList(node.keys)
|
|
2732
|
+
.map(key => this.visit(key, context));
|
|
2733
|
+
if (node.without_overlaps) {
|
|
2734
|
+
keyItems[keyItems.length - 1] += ' WITHOUT OVERLAPS';
|
|
2735
|
+
}
|
|
2736
|
+
output.push(`(${keyItems.join(', ')})`);
|
|
2681
2737
|
}
|
|
2682
2738
|
if (node.indexname) {
|
|
2683
2739
|
output.push('USING INDEX');
|
|
@@ -2695,10 +2751,12 @@ class Deparser {
|
|
|
2695
2751
|
output.push('NULLS NOT DISTINCT');
|
|
2696
2752
|
}
|
|
2697
2753
|
if (node.keys && node.keys.length > 0) {
|
|
2698
|
-
const
|
|
2699
|
-
.map(key => this.visit(key, context))
|
|
2700
|
-
|
|
2701
|
-
|
|
2754
|
+
const keyItems = list_utils_1.ListUtils.unwrapList(node.keys)
|
|
2755
|
+
.map(key => this.visit(key, context));
|
|
2756
|
+
if (node.without_overlaps) {
|
|
2757
|
+
keyItems[keyItems.length - 1] += ' WITHOUT OVERLAPS';
|
|
2758
|
+
}
|
|
2759
|
+
output.push(`(${keyItems.join(', ')})`);
|
|
2702
2760
|
}
|
|
2703
2761
|
if (node.indexname) {
|
|
2704
2762
|
output.push('USING INDEX');
|
|
@@ -2711,20 +2769,14 @@ class Deparser {
|
|
|
2711
2769
|
if (context.isPretty()) {
|
|
2712
2770
|
output.push('\n' + context.indent('FOREIGN KEY'));
|
|
2713
2771
|
if (node.fk_attrs && node.fk_attrs.length > 0) {
|
|
2714
|
-
|
|
2715
|
-
.map(attr => this.visit(attr, context))
|
|
2716
|
-
.join(', ');
|
|
2717
|
-
output.push(`(${fkAttrs})`);
|
|
2772
|
+
output.push(`(${this.deparseKeyAttrs(node.fk_attrs, node.fk_with_period, context)})`);
|
|
2718
2773
|
}
|
|
2719
2774
|
output.push('\n' + context.indent('REFERENCES'));
|
|
2720
2775
|
}
|
|
2721
2776
|
else {
|
|
2722
2777
|
output.push('FOREIGN KEY');
|
|
2723
2778
|
if (node.fk_attrs && node.fk_attrs.length > 0) {
|
|
2724
|
-
|
|
2725
|
-
.map(attr => this.visit(attr, context))
|
|
2726
|
-
.join(', ');
|
|
2727
|
-
output.push(`(${fkAttrs})`);
|
|
2779
|
+
output.push(`(${this.deparseKeyAttrs(node.fk_attrs, node.fk_with_period, context)})`);
|
|
2728
2780
|
}
|
|
2729
2781
|
output.push('REFERENCES');
|
|
2730
2782
|
}
|
|
@@ -2747,9 +2799,7 @@ class Deparser {
|
|
|
2747
2799
|
}
|
|
2748
2800
|
}
|
|
2749
2801
|
if (node.pk_attrs && node.pk_attrs.length > 0) {
|
|
2750
|
-
const pkAttrs =
|
|
2751
|
-
.map(attr => this.visit(attr, context))
|
|
2752
|
-
.join(', ');
|
|
2802
|
+
const pkAttrs = this.deparseKeyAttrs(node.pk_attrs, node.pk_with_period, context);
|
|
2753
2803
|
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2754
2804
|
const lastIndex = output.length - 1;
|
|
2755
2805
|
if (lastIndex >= 0) {
|
|
@@ -2828,8 +2878,18 @@ class Deparser {
|
|
|
2828
2878
|
output.push(deleteClause.replace('ON DELETE ', ''));
|
|
2829
2879
|
}
|
|
2830
2880
|
}
|
|
2831
|
-
//
|
|
2832
|
-
|
|
2881
|
+
// PG18: constraints are enforced unless explicitly NOT ENFORCED
|
|
2882
|
+
// (libpg-query omits false booleans, so undefined means not enforced)
|
|
2883
|
+
if (node.is_enforced !== true && !context.isDomainConstraint) {
|
|
2884
|
+
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2885
|
+
output.push('\n' + context.indent('NOT ENFORCED'));
|
|
2886
|
+
}
|
|
2887
|
+
else {
|
|
2888
|
+
output.push('NOT ENFORCED');
|
|
2889
|
+
}
|
|
2890
|
+
}
|
|
2891
|
+
else if (node.skip_validation && !context.isDomainConstraint) {
|
|
2892
|
+
// NOT ENFORCED implies NOT VALID, so only emit NOT VALID when enforced
|
|
2833
2893
|
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2834
2894
|
output.push('\n' + context.indent('NOT VALID'));
|
|
2835
2895
|
}
|
|
@@ -2850,6 +2910,12 @@ class Deparser {
|
|
|
2850
2910
|
case 'CONSTR_ATTR_IMMEDIATE':
|
|
2851
2911
|
output.push('INITIALLY IMMEDIATE');
|
|
2852
2912
|
break;
|
|
2913
|
+
case 'CONSTR_ATTR_ENFORCED':
|
|
2914
|
+
output.push('ENFORCED');
|
|
2915
|
+
break;
|
|
2916
|
+
case 'CONSTR_ATTR_NOT_ENFORCED':
|
|
2917
|
+
output.push('NOT ENFORCED');
|
|
2918
|
+
break;
|
|
2853
2919
|
case 'CONSTR_EXCLUSION':
|
|
2854
2920
|
output.push('EXCLUDE');
|
|
2855
2921
|
if (node.access_method) {
|
|
@@ -3893,6 +3959,11 @@ class Deparser {
|
|
|
3893
3959
|
switch (node.kind) {
|
|
3894
3960
|
case 'VAR_SET_VALUE':
|
|
3895
3961
|
const localPrefix = node.is_local ? 'LOCAL ' : '';
|
|
3962
|
+
if (node.jumble_args && node.name === 'xmloption' && node.args) {
|
|
3963
|
+
const xmlValue = this.getNodeData(list_utils_1.ListUtils.unwrapList(node.args)[0]);
|
|
3964
|
+
const xmlOption = (typeof xmlValue.sval === 'object' ? xmlValue.sval.sval : xmlValue.sval) || '';
|
|
3965
|
+
return `SET ${localPrefix}XML OPTION ${xmlOption.toUpperCase()}`;
|
|
3966
|
+
}
|
|
3896
3967
|
const args = node.args ? list_utils_1.ListUtils.unwrapList(node.args).map(arg => {
|
|
3897
3968
|
const nodeData = this.getNodeData(arg);
|
|
3898
3969
|
if (nodeData.sval !== undefined) {
|
|
@@ -3904,6 +3975,9 @@ class Deparser {
|
|
|
3904
3975
|
}
|
|
3905
3976
|
return this.visit(arg, context);
|
|
3906
3977
|
}).join(', ') : '';
|
|
3978
|
+
if (node.jumble_args && node.name === 'timezone') {
|
|
3979
|
+
return `SET ${localPrefix}TIME ZONE ${args}`;
|
|
3980
|
+
}
|
|
3907
3981
|
// Handle args - always include TO clause if args exist (even if empty string)
|
|
3908
3982
|
const paramName = quotes_1.QuoteUtils.quoteIdentifier(node.name);
|
|
3909
3983
|
if (!node.args || node.args.length === 0) {
|
|
@@ -3911,6 +3985,9 @@ class Deparser {
|
|
|
3911
3985
|
}
|
|
3912
3986
|
return `SET ${localPrefix}${paramName} TO ${args}`;
|
|
3913
3987
|
case 'VAR_SET_DEFAULT':
|
|
3988
|
+
if (node.jumble_args && node.name === 'timezone') {
|
|
3989
|
+
return `SET ${node.is_local ? 'LOCAL ' : ''}TIME ZONE DEFAULT`;
|
|
3990
|
+
}
|
|
3914
3991
|
const defaultParamName = quotes_1.QuoteUtils.quoteIdentifier(node.name);
|
|
3915
3992
|
return `SET ${defaultParamName} TO DEFAULT`;
|
|
3916
3993
|
case 'VAR_SET_CURRENT':
|
|
@@ -5022,13 +5099,6 @@ class Deparser {
|
|
|
5022
5099
|
output.push('IF EXISTS');
|
|
5023
5100
|
}
|
|
5024
5101
|
break;
|
|
5025
|
-
case 'AT_CheckNotNull':
|
|
5026
|
-
output.push('ALTER COLUMN');
|
|
5027
|
-
if (node.name) {
|
|
5028
|
-
output.push(quotes_1.QuoteUtils.quoteIdentifier(node.name));
|
|
5029
|
-
}
|
|
5030
|
-
output.push('SET NOT NULL');
|
|
5031
|
-
break;
|
|
5032
5102
|
case 'AT_AddIndex':
|
|
5033
5103
|
output.push('ADD');
|
|
5034
5104
|
if (node.def) {
|
|
@@ -5054,23 +5124,28 @@ class Deparser {
|
|
|
5054
5124
|
}
|
|
5055
5125
|
break;
|
|
5056
5126
|
case 'AT_AlterConstraint':
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5065
|
-
|
|
5066
|
-
|
|
5127
|
+
if (node.def && this.getNodeType(node.def) === 'ATAlterConstraint') {
|
|
5128
|
+
output.push(this.ATAlterConstraint(this.getNodeData(node.def), context));
|
|
5129
|
+
}
|
|
5130
|
+
else {
|
|
5131
|
+
output.push('ALTER CONSTRAINT');
|
|
5132
|
+
if (node.def && this.getNodeType(node.def) === 'Constraint') {
|
|
5133
|
+
const constraintData = this.getNodeData(node.def);
|
|
5134
|
+
if (constraintData.conname) {
|
|
5135
|
+
output.push(quotes_1.QuoteUtils.quoteIdentifier(constraintData.conname));
|
|
5136
|
+
if (constraintData.deferrable !== undefined) {
|
|
5137
|
+
output.push(constraintData.deferrable ? 'DEFERRABLE' : 'NOT DEFERRABLE');
|
|
5138
|
+
}
|
|
5139
|
+
if (constraintData.initdeferred !== undefined) {
|
|
5140
|
+
output.push(constraintData.initdeferred ? 'INITIALLY DEFERRED' : 'INITIALLY IMMEDIATE');
|
|
5141
|
+
}
|
|
5067
5142
|
}
|
|
5068
5143
|
}
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5144
|
+
else if (node.name) {
|
|
5145
|
+
output.push(quotes_1.QuoteUtils.quoteIdentifier(node.name));
|
|
5146
|
+
if (node.def) {
|
|
5147
|
+
output.push(this.visit(node.def, context));
|
|
5148
|
+
}
|
|
5074
5149
|
}
|
|
5075
5150
|
}
|
|
5076
5151
|
break;
|
|
@@ -8572,15 +8647,14 @@ class Deparser {
|
|
|
8572
8647
|
.join(' ');
|
|
8573
8648
|
output.push(whenClauses);
|
|
8574
8649
|
}
|
|
8575
|
-
if (node.
|
|
8576
|
-
output.push(
|
|
8577
|
-
const returningList = list_utils_1.ListUtils.unwrapList(node.returningList)
|
|
8578
|
-
.map(target => this.visit(target, context))
|
|
8579
|
-
.join(', ');
|
|
8580
|
-
output.push(returningList);
|
|
8650
|
+
if (node.returningClause) {
|
|
8651
|
+
output.push(this.ReturningClause(node.returningClause, context));
|
|
8581
8652
|
}
|
|
8582
8653
|
return output.join(' ');
|
|
8583
8654
|
}
|
|
8655
|
+
MergeSupportFunc(node, context) {
|
|
8656
|
+
return 'merge_action()';
|
|
8657
|
+
}
|
|
8584
8658
|
MergeWhenClause(node, context) {
|
|
8585
8659
|
const output = ['WHEN'];
|
|
8586
8660
|
switch (node.matchKind) {
|
package/esm/deparser.js
CHANGED
|
@@ -1042,11 +1042,8 @@ export class Deparser {
|
|
|
1042
1042
|
output.push('DO NOTHING');
|
|
1043
1043
|
}
|
|
1044
1044
|
}
|
|
1045
|
-
if (node.
|
|
1046
|
-
output.push(
|
|
1047
|
-
const returningList = ListUtils.unwrapList(node.returningList);
|
|
1048
|
-
const returns = returningList.map(ret => this.visit(ret, context));
|
|
1049
|
-
output.push(returns.join(', '));
|
|
1045
|
+
if (node.returningClause) {
|
|
1046
|
+
output.push(this.ReturningClause(node.returningClause, context));
|
|
1050
1047
|
}
|
|
1051
1048
|
return output.join(' ');
|
|
1052
1049
|
}
|
|
@@ -1103,9 +1100,8 @@ export class Deparser {
|
|
|
1103
1100
|
output.push('WHERE');
|
|
1104
1101
|
output.push(this.visit(node.whereClause, context));
|
|
1105
1102
|
}
|
|
1106
|
-
if (node.
|
|
1107
|
-
output.push(
|
|
1108
|
-
output.push(this.deparseReturningList(node.returningList, context));
|
|
1103
|
+
if (node.returningClause) {
|
|
1104
|
+
output.push(this.ReturningClause(node.returningClause, context));
|
|
1109
1105
|
}
|
|
1110
1106
|
return output.join(' ');
|
|
1111
1107
|
}
|
|
@@ -1156,13 +1152,12 @@ export class Deparser {
|
|
|
1156
1152
|
throw new Error(`Error deparsing DeleteStmt: ${error instanceof Error ? error.message : String(error)}`);
|
|
1157
1153
|
}
|
|
1158
1154
|
}
|
|
1159
|
-
if (node.
|
|
1160
|
-
output.push('RETURNING');
|
|
1155
|
+
if (node.returningClause) {
|
|
1161
1156
|
try {
|
|
1162
|
-
output.push(this.
|
|
1157
|
+
output.push(this.ReturningClause(node.returningClause, context));
|
|
1163
1158
|
}
|
|
1164
1159
|
catch (error) {
|
|
1165
|
-
console.warn(`Error processing
|
|
1160
|
+
console.warn(`Error processing returningClause in DeleteStmt: ${error instanceof Error ? error.message : String(error)}`);
|
|
1166
1161
|
throw new Error(`Error deparsing DeleteStmt: ${error instanceof Error ? error.message : String(error)}`);
|
|
1167
1162
|
}
|
|
1168
1163
|
}
|
|
@@ -1240,6 +1235,48 @@ export class Deparser {
|
|
|
1240
1235
|
}
|
|
1241
1236
|
return output.join(' ');
|
|
1242
1237
|
}
|
|
1238
|
+
ATAlterConstraint(node, context) {
|
|
1239
|
+
const output = ['ALTER CONSTRAINT'];
|
|
1240
|
+
if (node.conname) {
|
|
1241
|
+
output.push(QuoteUtils.quoteIdentifier(node.conname));
|
|
1242
|
+
}
|
|
1243
|
+
if (node.alterEnforceability) {
|
|
1244
|
+
output.push(node.is_enforced ? 'ENFORCED' : 'NOT ENFORCED');
|
|
1245
|
+
}
|
|
1246
|
+
if (node.alterDeferrability) {
|
|
1247
|
+
output.push(node.deferrable ? 'DEFERRABLE' : 'NOT DEFERRABLE');
|
|
1248
|
+
if (node.initdeferred) {
|
|
1249
|
+
output.push('INITIALLY DEFERRED');
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
if (node.alterInheritability) {
|
|
1253
|
+
output.push(node.noinherit ? 'NO INHERIT' : 'INHERIT');
|
|
1254
|
+
}
|
|
1255
|
+
return output.join(' ');
|
|
1256
|
+
}
|
|
1257
|
+
deparseKeyAttrs(attrs, withPeriod, context) {
|
|
1258
|
+
const items = ListUtils.unwrapList(attrs).map(attr => this.visit(attr, context));
|
|
1259
|
+
if (withPeriod && items.length > 0) {
|
|
1260
|
+
items[items.length - 1] = `PERIOD ${items[items.length - 1]}`;
|
|
1261
|
+
}
|
|
1262
|
+
return items.join(', ');
|
|
1263
|
+
}
|
|
1264
|
+
ReturningClause(node, context) {
|
|
1265
|
+
const output = ['RETURNING'];
|
|
1266
|
+
if (node.options && node.options.length > 0) {
|
|
1267
|
+
const options = ListUtils.unwrapList(node.options)
|
|
1268
|
+
.map(option => this.visit(option, context));
|
|
1269
|
+
output.push(`WITH (${options.join(', ')})`);
|
|
1270
|
+
}
|
|
1271
|
+
if (node.exprs && node.exprs.length > 0) {
|
|
1272
|
+
output.push(this.deparseReturningList(node.exprs, context));
|
|
1273
|
+
}
|
|
1274
|
+
return output.join(' ');
|
|
1275
|
+
}
|
|
1276
|
+
ReturningOption(node, context) {
|
|
1277
|
+
const keyword = node.option === 'RETURNING_OPTION_NEW' ? 'NEW' : 'OLD';
|
|
1278
|
+
return `${keyword} AS ${QuoteUtils.quoteIdentifier(node.value)}`;
|
|
1279
|
+
}
|
|
1243
1280
|
deparseReturningList(list, context) {
|
|
1244
1281
|
return ListUtils.unwrapList(list)
|
|
1245
1282
|
.filter(item => item != null && this.getNodeType(item) !== 'undefined')
|
|
@@ -2536,7 +2573,7 @@ export class Deparser {
|
|
|
2536
2573
|
Constraint(node, context) {
|
|
2537
2574
|
const output = [];
|
|
2538
2575
|
// Handle constraint name if present
|
|
2539
|
-
if (node.conname && (node.contype === 'CONSTR_CHECK' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_FOREIGN')) {
|
|
2576
|
+
if (node.conname && (node.contype === 'CONSTR_CHECK' || node.contype === 'CONSTR_UNIQUE' || node.contype === 'CONSTR_PRIMARY' || node.contype === 'CONSTR_FOREIGN' || node.contype === 'CONSTR_NOTNULL')) {
|
|
2540
2577
|
output.push('CONSTRAINT');
|
|
2541
2578
|
output.push(QuoteUtils.quoteIdentifier(node.conname));
|
|
2542
2579
|
}
|
|
@@ -2546,6 +2583,18 @@ export class Deparser {
|
|
|
2546
2583
|
break;
|
|
2547
2584
|
case 'CONSTR_NOTNULL':
|
|
2548
2585
|
output.push('NOT NULL');
|
|
2586
|
+
if (node.keys && node.keys.length > 0 && !context.isColumnConstraint) {
|
|
2587
|
+
const keyList = ListUtils.unwrapList(node.keys)
|
|
2588
|
+
.map(key => this.visit(key, context))
|
|
2589
|
+
.join(', ');
|
|
2590
|
+
output.push(keyList);
|
|
2591
|
+
}
|
|
2592
|
+
if (node.is_no_inherit) {
|
|
2593
|
+
output.push('NO INHERIT');
|
|
2594
|
+
}
|
|
2595
|
+
if (node.skip_validation) {
|
|
2596
|
+
output.push('NOT VALID');
|
|
2597
|
+
}
|
|
2549
2598
|
break;
|
|
2550
2599
|
case 'CONSTR_DEFAULT':
|
|
2551
2600
|
output.push('DEFAULT');
|
|
@@ -2574,8 +2623,13 @@ export class Deparser {
|
|
|
2574
2623
|
output.push(context.parens(this.visit(node.raw_expr, context)));
|
|
2575
2624
|
}
|
|
2576
2625
|
}
|
|
2577
|
-
//
|
|
2578
|
-
|
|
2626
|
+
// PG18: constraints are enforced unless explicitly NOT ENFORCED
|
|
2627
|
+
// (libpg-query omits false booleans, so undefined means not enforced)
|
|
2628
|
+
if (node.is_enforced !== true && !context.isDomainConstraint) {
|
|
2629
|
+
output.push('NOT ENFORCED');
|
|
2630
|
+
}
|
|
2631
|
+
else if (node.skip_validation) {
|
|
2632
|
+
// NOT ENFORCED implies NOT VALID, so only emit NOT VALID when enforced
|
|
2579
2633
|
output.push('NOT VALID');
|
|
2580
2634
|
}
|
|
2581
2635
|
// Handle NO INHERIT for check constraints - only for table constraints, not domain constraints
|
|
@@ -2595,7 +2649,7 @@ export class Deparser {
|
|
|
2595
2649
|
if (node.raw_expr) {
|
|
2596
2650
|
output.push(context.parens(this.visit(node.raw_expr, context)));
|
|
2597
2651
|
}
|
|
2598
|
-
output.push('STORED');
|
|
2652
|
+
output.push(node.generated_kind === 'v' ? 'VIRTUAL' : 'STORED');
|
|
2599
2653
|
break;
|
|
2600
2654
|
case 'CONSTR_IDENTITY':
|
|
2601
2655
|
output.push('GENERATED');
|
|
@@ -2671,10 +2725,12 @@ export class Deparser {
|
|
|
2671
2725
|
case 'CONSTR_PRIMARY':
|
|
2672
2726
|
output.push('PRIMARY KEY');
|
|
2673
2727
|
if (node.keys && node.keys.length > 0) {
|
|
2674
|
-
const
|
|
2675
|
-
.map(key => this.visit(key, context))
|
|
2676
|
-
|
|
2677
|
-
|
|
2728
|
+
const keyItems = ListUtils.unwrapList(node.keys)
|
|
2729
|
+
.map(key => this.visit(key, context));
|
|
2730
|
+
if (node.without_overlaps) {
|
|
2731
|
+
keyItems[keyItems.length - 1] += ' WITHOUT OVERLAPS';
|
|
2732
|
+
}
|
|
2733
|
+
output.push(`(${keyItems.join(', ')})`);
|
|
2678
2734
|
}
|
|
2679
2735
|
if (node.indexname) {
|
|
2680
2736
|
output.push('USING INDEX');
|
|
@@ -2692,10 +2748,12 @@ export class Deparser {
|
|
|
2692
2748
|
output.push('NULLS NOT DISTINCT');
|
|
2693
2749
|
}
|
|
2694
2750
|
if (node.keys && node.keys.length > 0) {
|
|
2695
|
-
const
|
|
2696
|
-
.map(key => this.visit(key, context))
|
|
2697
|
-
|
|
2698
|
-
|
|
2751
|
+
const keyItems = ListUtils.unwrapList(node.keys)
|
|
2752
|
+
.map(key => this.visit(key, context));
|
|
2753
|
+
if (node.without_overlaps) {
|
|
2754
|
+
keyItems[keyItems.length - 1] += ' WITHOUT OVERLAPS';
|
|
2755
|
+
}
|
|
2756
|
+
output.push(`(${keyItems.join(', ')})`);
|
|
2699
2757
|
}
|
|
2700
2758
|
if (node.indexname) {
|
|
2701
2759
|
output.push('USING INDEX');
|
|
@@ -2708,20 +2766,14 @@ export class Deparser {
|
|
|
2708
2766
|
if (context.isPretty()) {
|
|
2709
2767
|
output.push('\n' + context.indent('FOREIGN KEY'));
|
|
2710
2768
|
if (node.fk_attrs && node.fk_attrs.length > 0) {
|
|
2711
|
-
|
|
2712
|
-
.map(attr => this.visit(attr, context))
|
|
2713
|
-
.join(', ');
|
|
2714
|
-
output.push(`(${fkAttrs})`);
|
|
2769
|
+
output.push(`(${this.deparseKeyAttrs(node.fk_attrs, node.fk_with_period, context)})`);
|
|
2715
2770
|
}
|
|
2716
2771
|
output.push('\n' + context.indent('REFERENCES'));
|
|
2717
2772
|
}
|
|
2718
2773
|
else {
|
|
2719
2774
|
output.push('FOREIGN KEY');
|
|
2720
2775
|
if (node.fk_attrs && node.fk_attrs.length > 0) {
|
|
2721
|
-
|
|
2722
|
-
.map(attr => this.visit(attr, context))
|
|
2723
|
-
.join(', ');
|
|
2724
|
-
output.push(`(${fkAttrs})`);
|
|
2776
|
+
output.push(`(${this.deparseKeyAttrs(node.fk_attrs, node.fk_with_period, context)})`);
|
|
2725
2777
|
}
|
|
2726
2778
|
output.push('REFERENCES');
|
|
2727
2779
|
}
|
|
@@ -2744,9 +2796,7 @@ export class Deparser {
|
|
|
2744
2796
|
}
|
|
2745
2797
|
}
|
|
2746
2798
|
if (node.pk_attrs && node.pk_attrs.length > 0) {
|
|
2747
|
-
const pkAttrs =
|
|
2748
|
-
.map(attr => this.visit(attr, context))
|
|
2749
|
-
.join(', ');
|
|
2799
|
+
const pkAttrs = this.deparseKeyAttrs(node.pk_attrs, node.pk_with_period, context);
|
|
2750
2800
|
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2751
2801
|
const lastIndex = output.length - 1;
|
|
2752
2802
|
if (lastIndex >= 0) {
|
|
@@ -2825,8 +2875,18 @@ export class Deparser {
|
|
|
2825
2875
|
output.push(deleteClause.replace('ON DELETE ', ''));
|
|
2826
2876
|
}
|
|
2827
2877
|
}
|
|
2828
|
-
//
|
|
2829
|
-
|
|
2878
|
+
// PG18: constraints are enforced unless explicitly NOT ENFORCED
|
|
2879
|
+
// (libpg-query omits false booleans, so undefined means not enforced)
|
|
2880
|
+
if (node.is_enforced !== true && !context.isDomainConstraint) {
|
|
2881
|
+
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2882
|
+
output.push('\n' + context.indent('NOT ENFORCED'));
|
|
2883
|
+
}
|
|
2884
|
+
else {
|
|
2885
|
+
output.push('NOT ENFORCED');
|
|
2886
|
+
}
|
|
2887
|
+
}
|
|
2888
|
+
else if (node.skip_validation && !context.isDomainConstraint) {
|
|
2889
|
+
// NOT ENFORCED implies NOT VALID, so only emit NOT VALID when enforced
|
|
2830
2890
|
if (context.isPretty() && !context.isColumnConstraint) {
|
|
2831
2891
|
output.push('\n' + context.indent('NOT VALID'));
|
|
2832
2892
|
}
|
|
@@ -2847,6 +2907,12 @@ export class Deparser {
|
|
|
2847
2907
|
case 'CONSTR_ATTR_IMMEDIATE':
|
|
2848
2908
|
output.push('INITIALLY IMMEDIATE');
|
|
2849
2909
|
break;
|
|
2910
|
+
case 'CONSTR_ATTR_ENFORCED':
|
|
2911
|
+
output.push('ENFORCED');
|
|
2912
|
+
break;
|
|
2913
|
+
case 'CONSTR_ATTR_NOT_ENFORCED':
|
|
2914
|
+
output.push('NOT ENFORCED');
|
|
2915
|
+
break;
|
|
2850
2916
|
case 'CONSTR_EXCLUSION':
|
|
2851
2917
|
output.push('EXCLUDE');
|
|
2852
2918
|
if (node.access_method) {
|
|
@@ -3890,6 +3956,11 @@ export class Deparser {
|
|
|
3890
3956
|
switch (node.kind) {
|
|
3891
3957
|
case 'VAR_SET_VALUE':
|
|
3892
3958
|
const localPrefix = node.is_local ? 'LOCAL ' : '';
|
|
3959
|
+
if (node.jumble_args && node.name === 'xmloption' && node.args) {
|
|
3960
|
+
const xmlValue = this.getNodeData(ListUtils.unwrapList(node.args)[0]);
|
|
3961
|
+
const xmlOption = (typeof xmlValue.sval === 'object' ? xmlValue.sval.sval : xmlValue.sval) || '';
|
|
3962
|
+
return `SET ${localPrefix}XML OPTION ${xmlOption.toUpperCase()}`;
|
|
3963
|
+
}
|
|
3893
3964
|
const args = node.args ? ListUtils.unwrapList(node.args).map(arg => {
|
|
3894
3965
|
const nodeData = this.getNodeData(arg);
|
|
3895
3966
|
if (nodeData.sval !== undefined) {
|
|
@@ -3901,6 +3972,9 @@ export class Deparser {
|
|
|
3901
3972
|
}
|
|
3902
3973
|
return this.visit(arg, context);
|
|
3903
3974
|
}).join(', ') : '';
|
|
3975
|
+
if (node.jumble_args && node.name === 'timezone') {
|
|
3976
|
+
return `SET ${localPrefix}TIME ZONE ${args}`;
|
|
3977
|
+
}
|
|
3904
3978
|
// Handle args - always include TO clause if args exist (even if empty string)
|
|
3905
3979
|
const paramName = QuoteUtils.quoteIdentifier(node.name);
|
|
3906
3980
|
if (!node.args || node.args.length === 0) {
|
|
@@ -3908,6 +3982,9 @@ export class Deparser {
|
|
|
3908
3982
|
}
|
|
3909
3983
|
return `SET ${localPrefix}${paramName} TO ${args}`;
|
|
3910
3984
|
case 'VAR_SET_DEFAULT':
|
|
3985
|
+
if (node.jumble_args && node.name === 'timezone') {
|
|
3986
|
+
return `SET ${node.is_local ? 'LOCAL ' : ''}TIME ZONE DEFAULT`;
|
|
3987
|
+
}
|
|
3911
3988
|
const defaultParamName = QuoteUtils.quoteIdentifier(node.name);
|
|
3912
3989
|
return `SET ${defaultParamName} TO DEFAULT`;
|
|
3913
3990
|
case 'VAR_SET_CURRENT':
|
|
@@ -5019,13 +5096,6 @@ export class Deparser {
|
|
|
5019
5096
|
output.push('IF EXISTS');
|
|
5020
5097
|
}
|
|
5021
5098
|
break;
|
|
5022
|
-
case 'AT_CheckNotNull':
|
|
5023
|
-
output.push('ALTER COLUMN');
|
|
5024
|
-
if (node.name) {
|
|
5025
|
-
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
5026
|
-
}
|
|
5027
|
-
output.push('SET NOT NULL');
|
|
5028
|
-
break;
|
|
5029
5099
|
case 'AT_AddIndex':
|
|
5030
5100
|
output.push('ADD');
|
|
5031
5101
|
if (node.def) {
|
|
@@ -5051,23 +5121,28 @@ export class Deparser {
|
|
|
5051
5121
|
}
|
|
5052
5122
|
break;
|
|
5053
5123
|
case 'AT_AlterConstraint':
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5124
|
+
if (node.def && this.getNodeType(node.def) === 'ATAlterConstraint') {
|
|
5125
|
+
output.push(this.ATAlterConstraint(this.getNodeData(node.def), context));
|
|
5126
|
+
}
|
|
5127
|
+
else {
|
|
5128
|
+
output.push('ALTER CONSTRAINT');
|
|
5129
|
+
if (node.def && this.getNodeType(node.def) === 'Constraint') {
|
|
5130
|
+
const constraintData = this.getNodeData(node.def);
|
|
5131
|
+
if (constraintData.conname) {
|
|
5132
|
+
output.push(QuoteUtils.quoteIdentifier(constraintData.conname));
|
|
5133
|
+
if (constraintData.deferrable !== undefined) {
|
|
5134
|
+
output.push(constraintData.deferrable ? 'DEFERRABLE' : 'NOT DEFERRABLE');
|
|
5135
|
+
}
|
|
5136
|
+
if (constraintData.initdeferred !== undefined) {
|
|
5137
|
+
output.push(constraintData.initdeferred ? 'INITIALLY DEFERRED' : 'INITIALLY IMMEDIATE');
|
|
5138
|
+
}
|
|
5064
5139
|
}
|
|
5065
5140
|
}
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
5069
|
-
|
|
5070
|
-
|
|
5141
|
+
else if (node.name) {
|
|
5142
|
+
output.push(QuoteUtils.quoteIdentifier(node.name));
|
|
5143
|
+
if (node.def) {
|
|
5144
|
+
output.push(this.visit(node.def, context));
|
|
5145
|
+
}
|
|
5071
5146
|
}
|
|
5072
5147
|
}
|
|
5073
5148
|
break;
|
|
@@ -8569,15 +8644,14 @@ export class Deparser {
|
|
|
8569
8644
|
.join(' ');
|
|
8570
8645
|
output.push(whenClauses);
|
|
8571
8646
|
}
|
|
8572
|
-
if (node.
|
|
8573
|
-
output.push(
|
|
8574
|
-
const returningList = ListUtils.unwrapList(node.returningList)
|
|
8575
|
-
.map(target => this.visit(target, context))
|
|
8576
|
-
.join(', ');
|
|
8577
|
-
output.push(returningList);
|
|
8647
|
+
if (node.returningClause) {
|
|
8648
|
+
output.push(this.ReturningClause(node.returningClause, context));
|
|
8578
8649
|
}
|
|
8579
8650
|
return output.join(' ');
|
|
8580
8651
|
}
|
|
8652
|
+
MergeSupportFunc(node, context) {
|
|
8653
|
+
return 'merge_action()';
|
|
8654
|
+
}
|
|
8581
8655
|
MergeWhenClause(node, context) {
|
|
8582
8656
|
const output = ['WHEN'];
|
|
8583
8657
|
switch (node.matchKind) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pgsql-deparser",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "18.1.0",
|
|
4
4
|
"author": "Constructive <developers@constructive.io>",
|
|
5
5
|
"description": "PostgreSQL AST Deparser",
|
|
6
6
|
"main": "index.js",
|
|
@@ -53,12 +53,12 @@
|
|
|
53
53
|
"database"
|
|
54
54
|
],
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"libpg-query": "
|
|
56
|
+
"libpg-query": "18.1.1",
|
|
57
57
|
"makage": "^0.1.8"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@pgsql/quotes": "
|
|
61
|
-
"@pgsql/types": "^
|
|
60
|
+
"@pgsql/quotes": "18.1.0",
|
|
61
|
+
"@pgsql/types": "^18.0.0"
|
|
62
62
|
},
|
|
63
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "13f064c263eb304d704fd21148add24a9d60a8ee"
|
|
64
64
|
}
|