pgsql-deparser 13.19.0 → 13.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -16
- package/deparser/deparser.d.ts +37 -28
- package/deparser/deparser.js +1413 -948
- package/deparser/index.d.ts +3 -1
- package/deparser/index.js +5 -1
- package/deparser/utils/sql-formatter.d.ts +8 -0
- package/deparser/utils/sql-formatter.js +104 -1
- package/esm/deparser/deparser.js +1396 -931
- package/esm/deparser/index.js +3 -1
- package/esm/deparser/utils/sql-formatter.js +103 -1
- package/esm/index.js +101 -7
- package/esm/v13-to-v14.js +76 -29
- package/esm/v13-to-v18-direct.js +88 -0
- package/esm/v14-to-v15.js +34 -0
- package/esm/v15-to-v16.js +16 -5
- package/esm/v16-to-v17.js +50 -1
- package/esm/v17-to-v18.js +209 -0
- package/index.d.ts +18 -4
- package/index.js +104 -6
- package/package.json +7 -6
- package/v13-to-v14.d.ts +6 -0
- package/v13-to-v14.js +76 -29
- package/v13-to-v18-direct.d.ts +25 -0
- package/v13-to-v18-direct.js +92 -0
- package/v14-to-v15.d.ts +1 -0
- package/v14-to-v15.js +34 -0
- package/v15-to-v16.js +16 -5
- package/v16-to-v17.d.ts +3 -0
- package/v16-to-v17.js +50 -1
- package/v17-to-v18.d.ts +55 -0
- package/v17-to-v18.js +213 -0
package/esm/v16-to-v17.js
CHANGED
|
@@ -652,6 +652,12 @@ export class V16ToV17Transformer {
|
|
|
652
652
|
if (node.storage !== undefined) {
|
|
653
653
|
result.storage = node.storage;
|
|
654
654
|
}
|
|
655
|
+
if (node.storage_name !== undefined) {
|
|
656
|
+
result.storage_name = node.storage_name;
|
|
657
|
+
}
|
|
658
|
+
if (node.compression !== undefined) {
|
|
659
|
+
result.compression = node.compression;
|
|
660
|
+
}
|
|
655
661
|
if (node.raw_default !== undefined) {
|
|
656
662
|
result.raw_default = this.transform(node.raw_default, context);
|
|
657
663
|
}
|
|
@@ -1110,7 +1116,50 @@ export class V16ToV17Transformer {
|
|
|
1110
1116
|
return { AlterOpFamilyStmt: node };
|
|
1111
1117
|
}
|
|
1112
1118
|
MergeStmt(node, context) {
|
|
1113
|
-
|
|
1119
|
+
const result = {};
|
|
1120
|
+
if (node.relation !== undefined) {
|
|
1121
|
+
result.relation = node.relation;
|
|
1122
|
+
}
|
|
1123
|
+
if (node.sourceRelation !== undefined) {
|
|
1124
|
+
result.sourceRelation = this.transform(node.sourceRelation, context);
|
|
1125
|
+
}
|
|
1126
|
+
if (node.joinCondition !== undefined) {
|
|
1127
|
+
result.joinCondition = this.transform(node.joinCondition, context);
|
|
1128
|
+
}
|
|
1129
|
+
if (node.mergeWhenClauses !== undefined) {
|
|
1130
|
+
result.mergeWhenClauses = Array.isArray(node.mergeWhenClauses)
|
|
1131
|
+
? node.mergeWhenClauses.map(item => this.transform(item, context))
|
|
1132
|
+
: this.transform(node.mergeWhenClauses, context);
|
|
1133
|
+
}
|
|
1134
|
+
if (node.withClause !== undefined) {
|
|
1135
|
+
result.withClause = this.WithClause(node.withClause, context);
|
|
1136
|
+
}
|
|
1137
|
+
return { MergeStmt: result };
|
|
1138
|
+
}
|
|
1139
|
+
MergeWhenClause(node, context) {
|
|
1140
|
+
const result = {};
|
|
1141
|
+
// v17 replaces the boolean matched with matchKind
|
|
1142
|
+
result.matchKind = node.matched ? 'MERGE_WHEN_MATCHED' : 'MERGE_WHEN_NOT_MATCHED_BY_TARGET';
|
|
1143
|
+
if (node.commandType !== undefined) {
|
|
1144
|
+
result.commandType = node.commandType;
|
|
1145
|
+
}
|
|
1146
|
+
if (node.override !== undefined) {
|
|
1147
|
+
result.override = node.override;
|
|
1148
|
+
}
|
|
1149
|
+
if (node.condition !== undefined) {
|
|
1150
|
+
result.condition = this.transform(node.condition, context);
|
|
1151
|
+
}
|
|
1152
|
+
if (node.targetList !== undefined) {
|
|
1153
|
+
result.targetList = Array.isArray(node.targetList)
|
|
1154
|
+
? node.targetList.map(item => this.transform(item, context))
|
|
1155
|
+
: this.transform(node.targetList, context);
|
|
1156
|
+
}
|
|
1157
|
+
if (node.values !== undefined) {
|
|
1158
|
+
result.values = Array.isArray(node.values)
|
|
1159
|
+
? node.values.map(item => this.transform(item, context))
|
|
1160
|
+
: this.transform(node.values, context);
|
|
1161
|
+
}
|
|
1162
|
+
return { MergeWhenClause: result };
|
|
1114
1163
|
}
|
|
1115
1164
|
AlterTableMoveAllStmt(node, context) {
|
|
1116
1165
|
return { AlterTableMoveAllStmt: node };
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-generated file with types stripped for better tree-shaking
|
|
3
|
+
* DO NOT EDIT - Generated by strip-transformer-types.ts
|
|
4
|
+
*/
|
|
5
|
+
// @ts-nocheck
|
|
6
|
+
/**
|
|
7
|
+
* V17 to V18 AST Transformer
|
|
8
|
+
* Transforms PostgreSQL v17 AST nodes to v18 format
|
|
9
|
+
*
|
|
10
|
+
* Structural changes in v18:
|
|
11
|
+
* - InsertStmt/UpdateStmt/DeleteStmt/MergeStmt: returningList -> returningClause { exprs }
|
|
12
|
+
* - Constraint: new is_enforced flag (true by default for CHECK/FOREIGN/NOTNULL)
|
|
13
|
+
* - Constraint: CONSTR_GENERATED gains generated_kind ('s' = STORED, 'v' = VIRTUAL)
|
|
14
|
+
* - Column-level NOT NULL constraints gain initially_valid: true
|
|
15
|
+
*/
|
|
16
|
+
export class V17ToV18Transformer {
|
|
17
|
+
transform(node, context = { parentNodeTypes: [] }) {
|
|
18
|
+
if (node == null) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
if (typeof node === 'number' || node instanceof Number) {
|
|
22
|
+
return node;
|
|
23
|
+
}
|
|
24
|
+
if (typeof node === 'string') {
|
|
25
|
+
return node;
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
return this.visit(node, context);
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
const nodeType = Object.keys(node)[0];
|
|
32
|
+
throw new Error(`Error transforming ${nodeType}: ${error.message}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
visit(node, context = { parentNodeTypes: [] }) {
|
|
36
|
+
if (node && typeof node === 'object' && 'version' in node && 'stmts' in node) {
|
|
37
|
+
return this.ParseResult(node, context);
|
|
38
|
+
}
|
|
39
|
+
const nodeType = this.getNodeType(node);
|
|
40
|
+
// Handle empty objects
|
|
41
|
+
if (!nodeType) {
|
|
42
|
+
return {};
|
|
43
|
+
}
|
|
44
|
+
const nodeData = this.getNodeData(node);
|
|
45
|
+
const methodName = nodeType;
|
|
46
|
+
if (typeof this[methodName] === 'function') {
|
|
47
|
+
const childContext = {
|
|
48
|
+
...context,
|
|
49
|
+
parentNodeTypes: [...context.parentNodeTypes, nodeType]
|
|
50
|
+
};
|
|
51
|
+
const result = this[methodName](nodeData, childContext);
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
54
|
+
// No specific method: recurse into children so nested statements
|
|
55
|
+
// (e.g. DML inside CTEs) still get transformed
|
|
56
|
+
return this.walkValue(node, context);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Generic recursive walk that re-dispatches wrapped nodes with a
|
|
60
|
+
* dedicated transformer method and deep-copies everything else.
|
|
61
|
+
*/
|
|
62
|
+
walkValue(value, context) {
|
|
63
|
+
if (value == null || typeof value !== 'object') {
|
|
64
|
+
return value;
|
|
65
|
+
}
|
|
66
|
+
if (Array.isArray(value)) {
|
|
67
|
+
return value.map(item => this.walkValue(item, context));
|
|
68
|
+
}
|
|
69
|
+
const keys = Object.keys(value);
|
|
70
|
+
if (keys.length === 1 && typeof this[keys[0]] === 'function') {
|
|
71
|
+
// Wrapped node with a dedicated transformer method
|
|
72
|
+
return this.visit(value, context);
|
|
73
|
+
}
|
|
74
|
+
const result = {};
|
|
75
|
+
for (const key of keys) {
|
|
76
|
+
result[key] = this.walkValue(value[key], context);
|
|
77
|
+
}
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
getNodeType(node) {
|
|
81
|
+
return Object.keys(node)[0];
|
|
82
|
+
}
|
|
83
|
+
getNodeData(node) {
|
|
84
|
+
const keys = Object.keys(node);
|
|
85
|
+
if (keys.length === 1 && typeof node[keys[0]] === 'object') {
|
|
86
|
+
return node[keys[0]];
|
|
87
|
+
}
|
|
88
|
+
return node;
|
|
89
|
+
}
|
|
90
|
+
ParseResult(node, context) {
|
|
91
|
+
if (node && typeof node === 'object' && 'version' in node && 'stmts' in node) {
|
|
92
|
+
return {
|
|
93
|
+
version: 180004, // PG18 version
|
|
94
|
+
stmts: node.stmts.map((stmt) => {
|
|
95
|
+
if (stmt && typeof stmt === 'object' && 'stmt' in stmt) {
|
|
96
|
+
return {
|
|
97
|
+
...stmt,
|
|
98
|
+
stmt: this.transform(stmt.stmt, context)
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
return this.transform(stmt, context);
|
|
102
|
+
})
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
return node;
|
|
106
|
+
}
|
|
107
|
+
RawStmt(node, context) {
|
|
108
|
+
const result = {};
|
|
109
|
+
if (node.stmt !== undefined) {
|
|
110
|
+
result.stmt = this.transform(node.stmt, context);
|
|
111
|
+
}
|
|
112
|
+
if (node.stmt_location !== undefined) {
|
|
113
|
+
result.stmt_location = node.stmt_location;
|
|
114
|
+
}
|
|
115
|
+
if (node.stmt_len !== undefined) {
|
|
116
|
+
result.stmt_len = node.stmt_len;
|
|
117
|
+
}
|
|
118
|
+
return { RawStmt: result };
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Convert a v17 returningList into a v18 ReturningClause
|
|
122
|
+
*/
|
|
123
|
+
transformReturningList(returningList, context) {
|
|
124
|
+
return {
|
|
125
|
+
exprs: returningList.map(item => this.transform(item, context))
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
transformDmlStatement(nodeType, node, context) {
|
|
129
|
+
const result = {};
|
|
130
|
+
for (const key of Object.keys(node)) {
|
|
131
|
+
if (key === 'returningList') {
|
|
132
|
+
result.returningClause = this.transformReturningList(node.returningList, context);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
result[key] = this.walkValue(node[key], context);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return { [nodeType]: result };
|
|
139
|
+
}
|
|
140
|
+
InsertStmt(node, context) {
|
|
141
|
+
return this.transformDmlStatement('InsertStmt', node, context);
|
|
142
|
+
}
|
|
143
|
+
UpdateStmt(node, context) {
|
|
144
|
+
return this.transformDmlStatement('UpdateStmt', node, context);
|
|
145
|
+
}
|
|
146
|
+
DeleteStmt(node, context) {
|
|
147
|
+
return this.transformDmlStatement('DeleteStmt', node, context);
|
|
148
|
+
}
|
|
149
|
+
MergeStmt(node, context) {
|
|
150
|
+
return this.transformDmlStatement('MergeStmt', node, context);
|
|
151
|
+
}
|
|
152
|
+
AlterTableCmd(node, context) {
|
|
153
|
+
const result = {};
|
|
154
|
+
for (const key of Object.keys(node)) {
|
|
155
|
+
result[key] = this.walkValue(node[key], context);
|
|
156
|
+
}
|
|
157
|
+
// v18 wraps ALTER CONSTRAINT definitions in the new ATAlterConstraint node
|
|
158
|
+
if (node.subtype === 'AT_AlterConstraint' && node.def?.Constraint) {
|
|
159
|
+
const constraint = node.def.Constraint;
|
|
160
|
+
const alterConstraint = {};
|
|
161
|
+
if (constraint.conname !== undefined) {
|
|
162
|
+
alterConstraint.conname = constraint.conname;
|
|
163
|
+
}
|
|
164
|
+
alterConstraint.is_enforced = true;
|
|
165
|
+
// v17 ALTER CONSTRAINT could only change deferrability
|
|
166
|
+
alterConstraint.alterDeferrability = true;
|
|
167
|
+
if (constraint.deferrable !== undefined) {
|
|
168
|
+
alterConstraint.deferrable = constraint.deferrable;
|
|
169
|
+
}
|
|
170
|
+
if (constraint.initdeferred !== undefined) {
|
|
171
|
+
alterConstraint.initdeferred = constraint.initdeferred;
|
|
172
|
+
}
|
|
173
|
+
result.def = { ATAlterConstraint: alterConstraint };
|
|
174
|
+
}
|
|
175
|
+
return { AlterTableCmd: result };
|
|
176
|
+
}
|
|
177
|
+
VariableSetStmt(node, context) {
|
|
178
|
+
const result = {};
|
|
179
|
+
for (const key of Object.keys(node)) {
|
|
180
|
+
result[key] = this.walkValue(node[key], context);
|
|
181
|
+
}
|
|
182
|
+
// v18 marks SET TRANSACTION / SESSION CHARACTERISTICS args as jumbled
|
|
183
|
+
if (node.kind === 'VAR_SET_MULTI' && (node.name === 'TRANSACTION' || node.name === 'SESSION CHARACTERISTICS')) {
|
|
184
|
+
result.jumble_args = true;
|
|
185
|
+
}
|
|
186
|
+
return { VariableSetStmt: result };
|
|
187
|
+
}
|
|
188
|
+
Constraint(node, context) {
|
|
189
|
+
const result = {};
|
|
190
|
+
for (const key of Object.keys(node)) {
|
|
191
|
+
result[key] = this.walkValue(node[key], context);
|
|
192
|
+
}
|
|
193
|
+
// v18 constraints are enforced by default; v17 grammar had no ENFORCED syntax
|
|
194
|
+
if (node.contype === 'CONSTR_CHECK' || node.contype === 'CONSTR_FOREIGN') {
|
|
195
|
+
result.is_enforced = true;
|
|
196
|
+
}
|
|
197
|
+
if (node.contype === 'CONSTR_NOTNULL') {
|
|
198
|
+
// v17 only produces column-level NOT NULL constraints, which in v18
|
|
199
|
+
// carry is_enforced and initially_valid
|
|
200
|
+
result.is_enforced = true;
|
|
201
|
+
result.initially_valid = true;
|
|
202
|
+
}
|
|
203
|
+
if (node.contype === 'CONSTR_GENERATED' && result.generated_kind === undefined) {
|
|
204
|
+
// v17 only supports STORED generated columns
|
|
205
|
+
result.generated_kind = 's';
|
|
206
|
+
}
|
|
207
|
+
return { Constraint: result };
|
|
208
|
+
}
|
|
209
|
+
}
|
package/index.d.ts
CHANGED
|
@@ -3,7 +3,21 @@
|
|
|
3
3
|
* Auto-generated by generate-version-deparsers.ts
|
|
4
4
|
*/
|
|
5
5
|
import { Node, ParseResult } from '@pgsql/types';
|
|
6
|
-
import { DeparserOptions } from './deparser';
|
|
7
|
-
|
|
8
|
-
export declare
|
|
9
|
-
|
|
6
|
+
import { Deparser as Deparser18, DeparserOptions } from './deparser';
|
|
7
|
+
type Query = Node | Node[] | ParseResult;
|
|
8
|
+
export declare class Deparser extends Deparser18 {
|
|
9
|
+
constructor(tree: Query, opts?: DeparserOptions);
|
|
10
|
+
static deparse(query: Query, opts?: DeparserOptions): string;
|
|
11
|
+
DefElem(node: any, context: any): string;
|
|
12
|
+
GrantRoleStmt(node: any, context: any): string;
|
|
13
|
+
private publicationTableListed;
|
|
14
|
+
CreatePublicationStmt(node: any, context: any): string;
|
|
15
|
+
AlterPublicationStmt(node: any, context: any): string;
|
|
16
|
+
PublicationObjSpec(node: any, context: any): string;
|
|
17
|
+
ReindexStmt(node: any, context: any): string;
|
|
18
|
+
}
|
|
19
|
+
export declare function deparse(query: Query, opts?: DeparserOptions): Promise<string>;
|
|
20
|
+
export declare function deparseSync(query: Query, opts?: DeparserOptions): string;
|
|
21
|
+
export { DeparserOptions };
|
|
22
|
+
export { splitSqlLines } from './deparser/utils/sql-formatter';
|
|
23
|
+
export { QuoteUtils } from '@pgsql/quotes';
|
package/index.js
CHANGED
|
@@ -4,16 +4,114 @@
|
|
|
4
4
|
* Auto-generated by generate-version-deparsers.ts
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.QuoteUtils = exports.splitSqlLines = exports.Deparser = void 0;
|
|
7
8
|
exports.deparse = deparse;
|
|
8
9
|
exports.deparseSync = deparseSync;
|
|
9
10
|
const deparser_1 = require("./deparser");
|
|
10
|
-
const
|
|
11
|
-
const tx = new
|
|
11
|
+
const v13_to_v18_direct_1 = require("./v13-to-v18-direct");
|
|
12
|
+
const tx = new v13_to_v18_direct_1.PG13ToPG18Transformer();
|
|
13
|
+
const bare = (names, name) => Array.isArray(names) && names.length === 1 && (names[0]?.String?.sval ?? names[0]?.String?.str) === name;
|
|
14
|
+
const v16to17 = tx.v16to17;
|
|
15
|
+
const upgradeTypeName = v16to17.TypeName.bind(v16to17);
|
|
16
|
+
v16to17.TypeName = (node, context) => {
|
|
17
|
+
const out = upgradeTypeName(node, context);
|
|
18
|
+
if (bare(node.names, 'json'))
|
|
19
|
+
out.TypeName.names = [{ String: { sval: 'json' } }];
|
|
20
|
+
return out;
|
|
21
|
+
};
|
|
22
|
+
const upgradeTypeCast = v16to17.TypeCast.bind(v16to17);
|
|
23
|
+
v16to17.TypeCast = (node, context) => {
|
|
24
|
+
const out = upgradeTypeCast(node, context);
|
|
25
|
+
const typeName = out.TypeCast.typeName?.TypeName ?? out.TypeCast.typeName;
|
|
26
|
+
if (typeName && bare((node.typeName?.TypeName ?? node.typeName)?.names, 'json')) {
|
|
27
|
+
typeName.names = [{ String: { sval: 'json' } }];
|
|
28
|
+
}
|
|
29
|
+
return out;
|
|
30
|
+
};
|
|
31
|
+
const v15to16 = tx.v15to16;
|
|
32
|
+
const upgradeFuncCall = v15to16.FuncCall.bind(v15to16);
|
|
33
|
+
v15to16.FuncCall = (node, context) => {
|
|
34
|
+
const out = upgradeFuncCall(node, context);
|
|
35
|
+
if (out.FuncCall && bare(node.funcname, 'json_object')) {
|
|
36
|
+
out.FuncCall.funcname = [{ String: { sval: 'json_object' } }];
|
|
37
|
+
}
|
|
38
|
+
return out;
|
|
39
|
+
};
|
|
40
|
+
const v13to14 = tx.v13to14;
|
|
41
|
+
const upgradeSubstring = v13to14.FuncCall.bind(v13to14);
|
|
42
|
+
v13to14.FuncCall = (node, context) => {
|
|
43
|
+
const out = upgradeSubstring(node, context);
|
|
44
|
+
const [schema, name] = (node.funcname ?? []).map((part) => part?.String?.str ?? part?.String?.sval);
|
|
45
|
+
const argCount = node.args?.length;
|
|
46
|
+
if (out.FuncCall && node.funcname?.length === 2 && schema === 'pg_catalog' && name === 'substring' && (argCount === 2 || argCount === 3)) {
|
|
47
|
+
out.FuncCall.funcname = [{ String: { sval: 'pg_catalog' } }, { String: { sval: 'substring' } }];
|
|
48
|
+
out.FuncCall.funcformat = 'COERCE_SQL_SYNTAX';
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
};
|
|
52
|
+
const toAst18 = (query) => Array.isArray(query) ? query.map(node => tx.transform(node)) : tx.transform(query);
|
|
53
|
+
class Deparser extends deparser_1.Deparser {
|
|
54
|
+
constructor(tree, opts = {}) {
|
|
55
|
+
super(toAst18(tree), opts);
|
|
56
|
+
}
|
|
57
|
+
static deparse(query, opts = {}) {
|
|
58
|
+
return new Deparser(query, opts).deparseQuery();
|
|
59
|
+
}
|
|
60
|
+
DefElem(node, context) {
|
|
61
|
+
if (!node.arg && node.defaction !== 'DEFELEM_DROP' && context.parentNodeTypes.includes('AlterOperatorStmt')) {
|
|
62
|
+
return `${node.defname} = NONE`;
|
|
63
|
+
}
|
|
64
|
+
return super.DefElem(node, context);
|
|
65
|
+
}
|
|
66
|
+
GrantRoleStmt(node, context) {
|
|
67
|
+
const sql = super.GrantRoleStmt(node, context);
|
|
68
|
+
const opts = (Array.isArray(node.opt) ? node.opt : []).map((opt) => opt.DefElem);
|
|
69
|
+
const arg = opts[0]?.arg;
|
|
70
|
+
const off = arg?.Boolean ? arg.Boolean.boolval !== true : arg?.String?.sval === 'false';
|
|
71
|
+
if (!node.is_grant || opts.length !== 1 || opts[0]?.defname !== 'admin' || off)
|
|
72
|
+
return sql;
|
|
73
|
+
// locate the option by what the statement prints without GRANTED BY, so a role name can never match
|
|
74
|
+
const head = node.grantor ? super.GrantRoleStmt({ ...node, grantor: undefined }, context) : sql;
|
|
75
|
+
const option = ' WITH ADMIN TRUE';
|
|
76
|
+
if (!head.endsWith(option) || !sql.startsWith(head))
|
|
77
|
+
return sql;
|
|
78
|
+
return head.slice(0, -option.length) + ' WITH ADMIN OPTION' + sql.slice(head.length);
|
|
79
|
+
}
|
|
80
|
+
publicationTableListed = false;
|
|
81
|
+
CreatePublicationStmt(node, context) {
|
|
82
|
+
this.publicationTableListed = false;
|
|
83
|
+
return super.CreatePublicationStmt(node, context);
|
|
84
|
+
}
|
|
85
|
+
AlterPublicationStmt(node, context) {
|
|
86
|
+
this.publicationTableListed = false;
|
|
87
|
+
return super.AlterPublicationStmt(node, context);
|
|
88
|
+
}
|
|
89
|
+
PublicationObjSpec(node, context) {
|
|
90
|
+
const sql = super.PublicationObjSpec(node, context);
|
|
91
|
+
if (node.pubobjtype !== 'PUBLICATIONOBJ_TABLE')
|
|
92
|
+
return sql;
|
|
93
|
+
const first = !this.publicationTableListed;
|
|
94
|
+
this.publicationTableListed = true;
|
|
95
|
+
return first ? sql : sql.replace(/^TABLE /, '');
|
|
96
|
+
}
|
|
97
|
+
ReindexStmt(node, context) {
|
|
98
|
+
const params = Array.isArray(node.params) ? node.params : [];
|
|
99
|
+
const others = params.filter((param) => param?.DefElem?.defname !== 'concurrently');
|
|
100
|
+
if (others.length === params.length)
|
|
101
|
+
return super.ReindexStmt(node, context);
|
|
102
|
+
return super
|
|
103
|
+
.ReindexStmt({ ...node, params: others }, context)
|
|
104
|
+
.replace(/^REINDEX( \([^)]*\))? (INDEX|TABLE|SCHEMA|SYSTEM|DATABASE)/, match => `${match} CONCURRENTLY`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
exports.Deparser = Deparser;
|
|
12
108
|
async function deparse(query, opts) {
|
|
13
|
-
|
|
14
|
-
return await (0, deparser_1.deparse)(ast17, opts);
|
|
109
|
+
return Deparser.deparse(query, opts);
|
|
15
110
|
}
|
|
16
111
|
function deparseSync(query, opts) {
|
|
17
|
-
|
|
18
|
-
return (0, deparser_1.deparseSync)(ast17, opts);
|
|
112
|
+
return Deparser.deparse(query, opts);
|
|
19
113
|
}
|
|
114
|
+
var sql_formatter_1 = require("./deparser/utils/sql-formatter");
|
|
115
|
+
Object.defineProperty(exports, "splitSqlLines", { enumerable: true, get: function () { return sql_formatter_1.splitSqlLines; } });
|
|
116
|
+
var quotes_1 = require("@pgsql/quotes");
|
|
117
|
+
Object.defineProperty(exports, "QuoteUtils", { enumerable: true, get: function () { return quotes_1.QuoteUtils; } });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"author": "
|
|
3
|
-
"homepage": "https://github.com/
|
|
2
|
+
"author": "Constructive <developers@constructive.io>",
|
|
3
|
+
"homepage": "https://github.com/constructive-io/pgsql-parser",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "esm/index.js",
|
|
@@ -18,10 +18,10 @@
|
|
|
18
18
|
},
|
|
19
19
|
"repository": {
|
|
20
20
|
"type": "git",
|
|
21
|
-
"url": "https://github.com/
|
|
21
|
+
"url": "https://github.com/constructive-io/pgsql-parser"
|
|
22
22
|
},
|
|
23
23
|
"bugs": {
|
|
24
|
-
"url": "https://github.com/
|
|
24
|
+
"url": "https://github.com/constructive-io/pgsql-parser/issues"
|
|
25
25
|
},
|
|
26
26
|
"keywords": [
|
|
27
27
|
"sql",
|
|
@@ -34,8 +34,9 @@
|
|
|
34
34
|
"database"
|
|
35
35
|
],
|
|
36
36
|
"name": "pgsql-deparser",
|
|
37
|
-
"version": "13.
|
|
37
|
+
"version": "13.20.0",
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@pgsql/
|
|
39
|
+
"@pgsql/quotes": "18.2.4",
|
|
40
|
+
"@pgsql/types": "^13.11.2"
|
|
40
41
|
}
|
|
41
42
|
}
|
package/v13-to-v14.d.ts
CHANGED
|
@@ -145,6 +145,9 @@ export declare class V13ToV14Transformer {
|
|
|
145
145
|
};
|
|
146
146
|
private transformTableLikeOption;
|
|
147
147
|
private extractParameterNameFromFunctionName;
|
|
148
|
+
AlterExtensionContentsStmt(node: any, context: any): {
|
|
149
|
+
AlterExtensionContentsStmt: any;
|
|
150
|
+
};
|
|
148
151
|
ObjectWithArgs(node: any, context: any): {
|
|
149
152
|
ObjectWithArgs: any;
|
|
150
153
|
};
|
|
@@ -211,6 +214,9 @@ export declare class V13ToV14Transformer {
|
|
|
211
214
|
WithClause: any;
|
|
212
215
|
};
|
|
213
216
|
private shouldConvertCTEsToArray;
|
|
217
|
+
AlterSubscriptionStmt(node: any, context: any): {
|
|
218
|
+
AlterSubscriptionStmt: any;
|
|
219
|
+
};
|
|
214
220
|
AlterSeqStmt(node: any, context: any): {
|
|
215
221
|
AlterSeqStmt: any;
|
|
216
222
|
};
|
package/v13-to-v14.js
CHANGED
|
@@ -1019,10 +1019,13 @@ class V13ToV14Transformer {
|
|
|
1019
1019
|
}
|
|
1020
1020
|
if (node.func !== undefined) {
|
|
1021
1021
|
// Handle plain object func (not wrapped in ObjectWithArgs)
|
|
1022
|
-
if (typeof node.func === 'object' && !('ObjectWithArgs' in node.func) && 'objargs' in node.func) {
|
|
1022
|
+
if (typeof node.func === 'object' && !('ObjectWithArgs' in node.func) && ('objargs' in node.func || 'objname' in node.func)) {
|
|
1023
1023
|
const funcResult = {};
|
|
1024
|
-
|
|
1025
|
-
|
|
1024
|
+
const objname = node.func.objname;
|
|
1025
|
+
if (objname !== undefined) {
|
|
1026
|
+
funcResult.objname = Array.isArray(objname)
|
|
1027
|
+
? objname.map((item) => this.transform(item, childContext))
|
|
1028
|
+
: this.transform(objname, childContext);
|
|
1026
1029
|
}
|
|
1027
1030
|
if (node.func.objargs !== undefined) {
|
|
1028
1031
|
funcResult.objargs = this.transform(node.func.objargs, childContext);
|
|
@@ -1030,6 +1033,9 @@ class V13ToV14Transformer {
|
|
|
1030
1033
|
? node.func.objargs.map((arg, index) => this.createFunctionParameterFromTypeName(arg, childContext, index))
|
|
1031
1034
|
: [this.createFunctionParameterFromTypeName(node.func.objargs, childContext, 0)];
|
|
1032
1035
|
}
|
|
1036
|
+
if (node.func.args_unspecified !== undefined) {
|
|
1037
|
+
funcResult.args_unspecified = node.func.args_unspecified;
|
|
1038
|
+
}
|
|
1033
1039
|
result.func = funcResult;
|
|
1034
1040
|
}
|
|
1035
1041
|
else {
|
|
@@ -1640,6 +1646,25 @@ class V13ToV14Transformer {
|
|
|
1640
1646
|
// Functions like testfunc1(int), testfunc2(int), testfunc4(boolean) should NOT have parameter names
|
|
1641
1647
|
return undefined;
|
|
1642
1648
|
}
|
|
1649
|
+
AlterExtensionContentsStmt(node, context) {
|
|
1650
|
+
const result = {};
|
|
1651
|
+
const childContext = {
|
|
1652
|
+
...context,
|
|
1653
|
+
alterExtensionObjtype: node.objtype
|
|
1654
|
+
};
|
|
1655
|
+
for (const [key, value] of Object.entries(node)) {
|
|
1656
|
+
if (Array.isArray(value)) {
|
|
1657
|
+
result[key] = value.map(item => this.transform(item, childContext));
|
|
1658
|
+
}
|
|
1659
|
+
else if (typeof value === 'object' && value !== null) {
|
|
1660
|
+
result[key] = this.transform(value, childContext);
|
|
1661
|
+
}
|
|
1662
|
+
else {
|
|
1663
|
+
result[key] = value;
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
return { AlterExtensionContentsStmt: result };
|
|
1667
|
+
}
|
|
1643
1668
|
ObjectWithArgs(node, context) {
|
|
1644
1669
|
const result = { ...node };
|
|
1645
1670
|
if (result.objname !== undefined) {
|
|
@@ -1841,6 +1866,9 @@ class V13ToV14Transformer {
|
|
|
1841
1866
|
if (!context.parentNodeTypes || context.parentNodeTypes.length === 0) {
|
|
1842
1867
|
return false;
|
|
1843
1868
|
}
|
|
1869
|
+
if (context.alterExtensionObjtype === 'OBJECT_OPERATOR') {
|
|
1870
|
+
return false;
|
|
1871
|
+
}
|
|
1844
1872
|
if (context.commentObjtype === 'OBJECT_OPERATOR' &&
|
|
1845
1873
|
context.parentNodeTypes.includes('CommentStmt')) {
|
|
1846
1874
|
return false;
|
|
@@ -1897,7 +1925,7 @@ class V13ToV14Transformer {
|
|
|
1897
1925
|
}
|
|
1898
1926
|
}
|
|
1899
1927
|
const allowedNodeTypes = [
|
|
1900
|
-
'CommentStmt', 'AlterFunctionStmt', 'RenameStmt', 'AlterOwnerStmt', 'AlterObjectSchemaStmt', 'CreateCastStmt', 'CreateTransformStmt', 'AlterOpFamilyStmt', 'CreateOpClassItem', 'GrantStmt', 'RevokeStmt'
|
|
1928
|
+
'CommentStmt', 'AlterFunctionStmt', 'RenameStmt', 'AlterOwnerStmt', 'AlterObjectSchemaStmt', 'CreateCastStmt', 'CreateTransformStmt', 'AlterOpFamilyStmt', 'CreateOpClassItem', 'GrantStmt', 'RevokeStmt', 'AlterExtensionContentsStmt'
|
|
1901
1929
|
];
|
|
1902
1930
|
for (const node of path) {
|
|
1903
1931
|
if (node && typeof node === 'object') {
|
|
@@ -1972,7 +2000,7 @@ class V13ToV14Transformer {
|
|
|
1972
2000
|
const argType = transformedTypeName.TypeName ? transformedTypeName.TypeName : transformedTypeName;
|
|
1973
2001
|
// Check if this should be a variadic parameter
|
|
1974
2002
|
const isVariadic = this.isVariadicParameterType(typeNameNode, index, undefined, context);
|
|
1975
|
-
let mode = isVariadic ?
|
|
2003
|
+
let mode = isVariadic ? 'FUNC_PARAM_VARIADIC' : 'FUNC_PARAM_DEFAULT';
|
|
1976
2004
|
const functionParam = {
|
|
1977
2005
|
argType: argType,
|
|
1978
2006
|
mode: mode
|
|
@@ -2007,31 +2035,31 @@ class V13ToV14Transformer {
|
|
|
2007
2035
|
}
|
|
2008
2036
|
transformA_Expr_Kind(kind) {
|
|
2009
2037
|
const pg13ToP14Map = {
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2038
|
+
AEXPR_OP: 'AEXPR_OP',
|
|
2039
|
+
AEXPR_OP_ANY: 'AEXPR_OP_ANY',
|
|
2040
|
+
AEXPR_OP_ALL: 'AEXPR_OP_ALL',
|
|
2041
|
+
AEXPR_DISTINCT: 'AEXPR_DISTINCT',
|
|
2042
|
+
AEXPR_NOT_DISTINCT: 'AEXPR_NOT_DISTINCT',
|
|
2043
|
+
AEXPR_NULLIF: 'AEXPR_NULLIF',
|
|
2044
|
+
AEXPR_OF: 'AEXPR_IN', // AEXPR_OF removed, map to AEXPR_IN
|
|
2045
|
+
AEXPR_IN: 'AEXPR_IN',
|
|
2046
|
+
AEXPR_LIKE: 'AEXPR_LIKE',
|
|
2047
|
+
AEXPR_ILIKE: 'AEXPR_ILIKE',
|
|
2048
|
+
AEXPR_SIMILAR: 'AEXPR_SIMILAR',
|
|
2049
|
+
AEXPR_BETWEEN: 'AEXPR_BETWEEN',
|
|
2050
|
+
AEXPR_NOT_BETWEEN: 'AEXPR_NOT_BETWEEN',
|
|
2051
|
+
AEXPR_BETWEEN_SYM: 'AEXPR_BETWEEN_SYM',
|
|
2052
|
+
AEXPR_NOT_BETWEEN_SYM: 'AEXPR_NOT_BETWEEN_SYM',
|
|
2053
|
+
AEXPR_PAREN: 'AEXPR_OP' // AEXPR_PAREN removed, map to AEXPR_OP
|
|
2026
2054
|
};
|
|
2027
2055
|
return pg13ToP14Map[kind] || kind;
|
|
2028
2056
|
}
|
|
2029
2057
|
transformRoleSpecType(type) {
|
|
2030
2058
|
const pg13ToP14Map = {
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2059
|
+
ROLESPEC_CSTRING: 'ROLESPEC_CSTRING',
|
|
2060
|
+
ROLESPEC_CURRENT_USER: 'ROLESPEC_CURRENT_USER',
|
|
2061
|
+
ROLESPEC_SESSION_USER: 'ROLESPEC_SESSION_USER',
|
|
2062
|
+
ROLESPEC_PUBLIC: 'ROLESPEC_PUBLIC'
|
|
2035
2063
|
};
|
|
2036
2064
|
return pg13ToP14Map[type] || type;
|
|
2037
2065
|
}
|
|
@@ -2090,11 +2118,11 @@ class V13ToV14Transformer {
|
|
|
2090
2118
|
A_Expr(node, context) {
|
|
2091
2119
|
const result = {};
|
|
2092
2120
|
if (node.kind !== undefined) {
|
|
2093
|
-
if (node.kind ===
|
|
2094
|
-
result.kind =
|
|
2121
|
+
if (node.kind === 'AEXPR_OF') {
|
|
2122
|
+
result.kind = 'AEXPR_IN';
|
|
2095
2123
|
}
|
|
2096
|
-
else if (node.kind ===
|
|
2097
|
-
result.kind =
|
|
2124
|
+
else if (node.kind === 'AEXPR_PAREN') {
|
|
2125
|
+
result.kind = 'AEXPR_OP';
|
|
2098
2126
|
}
|
|
2099
2127
|
else {
|
|
2100
2128
|
result.kind = node.kind;
|
|
@@ -2333,6 +2361,14 @@ class V13ToV14Transformer {
|
|
|
2333
2361
|
shouldConvertCTEsToArray(context) {
|
|
2334
2362
|
return true;
|
|
2335
2363
|
}
|
|
2364
|
+
AlterSubscriptionStmt(node, context) {
|
|
2365
|
+
const result = this.transformGenericNode(node, context);
|
|
2366
|
+
// PG14 added ADD / DROP PUBLICATION and renamed the existing SET PUBLICATION kind
|
|
2367
|
+
if (result.kind === 'ALTER_SUBSCRIPTION_PUBLICATION') {
|
|
2368
|
+
result.kind = 'ALTER_SUBSCRIPTION_SET_PUBLICATION';
|
|
2369
|
+
}
|
|
2370
|
+
return { AlterSubscriptionStmt: result };
|
|
2371
|
+
}
|
|
2336
2372
|
AlterSeqStmt(node, context) {
|
|
2337
2373
|
const result = {};
|
|
2338
2374
|
if (node.sequence !== undefined) {
|
|
@@ -2748,6 +2784,17 @@ class V13ToV14Transformer {
|
|
|
2748
2784
|
else if (nodeAny.params !== undefined) {
|
|
2749
2785
|
result.params = this.transform(nodeAny.params, context);
|
|
2750
2786
|
}
|
|
2787
|
+
if (nodeAny.concurrent === true) {
|
|
2788
|
+
result.params = [
|
|
2789
|
+
...(result.params || []),
|
|
2790
|
+
{
|
|
2791
|
+
DefElem: {
|
|
2792
|
+
defname: 'concurrently',
|
|
2793
|
+
defaction: 'DEFELEM_UNSPEC'
|
|
2794
|
+
}
|
|
2795
|
+
}
|
|
2796
|
+
];
|
|
2797
|
+
}
|
|
2751
2798
|
return { ReindexStmt: result };
|
|
2752
2799
|
}
|
|
2753
2800
|
}
|