@pgsql/transform 18.1.1 → 18.3.1
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 +24 -76
- package/esm/facts.js +289 -0
- package/esm/index.js +5 -22
- package/esm/qualify.js +297 -0
- package/esm/round-trip-core.js +126 -0
- package/esm/round-trip.js +116 -0
- package/esm/transform.js +1169 -0
- package/facts.d.ts +69 -0
- package/facts.js +292 -0
- package/index.d.ts +10 -28
- package/index.js +37 -76
- package/package.json +22 -14
- package/qualify.d.ts +125 -0
- package/qualify.js +303 -0
- package/round-trip-core.d.ts +60 -0
- package/round-trip-core.js +133 -0
- package/round-trip.d.ts +47 -0
- package/round-trip.js +123 -0
- package/transform.d.ts +259 -0
- package/transform.js +1190 -0
- package/13/enums.d.ts +0 -62
- package/13/enums.js +0 -2
- package/13/types.d.ts +0 -2103
- package/13/types.js +0 -2
- package/14/enums.d.ts +0 -62
- package/14/enums.js +0 -2
- package/14/types.d.ts +0 -2164
- package/14/types.js +0 -2
- package/15/enums.d.ts +0 -64
- package/15/enums.js +0 -2
- package/15/types.d.ts +0 -2222
- package/15/types.js +0 -2
- package/16/enums.d.ts +0 -69
- package/16/enums.js +0 -2
- package/16/types.d.ts +0 -2328
- package/16/types.js +0 -2
- package/17/enums.d.ts +0 -76
- package/17/enums.js +0 -2
- package/17/types.d.ts +0 -2488
- package/17/types.js +0 -2
- package/18/enums.d.ts +0 -78
- package/18/enums.js +0 -2
- package/18/types.d.ts +0 -2538
- package/18/types.js +0 -2
- package/esm/13/enums.js +0 -1
- package/esm/13/types.js +0 -1
- package/esm/14/enums.js +0 -1
- package/esm/14/types.js +0 -1
- package/esm/15/enums.js +0 -1
- package/esm/15/types.js +0 -1
- package/esm/16/enums.js +0 -1
- package/esm/16/types.js +0 -1
- package/esm/17/enums.js +0 -1
- package/esm/17/types.js +0 -1
- package/esm/18/enums.js +0 -1
- package/esm/18/types.js +0 -1
- package/esm/multi-version-transformer.js +0 -80
- package/esm/transformers/context.js +0 -1
- package/esm/transformers/v13-to-v14.js +0 -2767
- package/esm/transformers/v14-to-v15.js +0 -1218
- package/esm/transformers/v15-to-v16.js +0 -2935
- package/esm/transformers/v16-to-v17.js +0 -1526
- package/esm/transformers/v17-to-v18.js +0 -204
- package/esm/transformers-direct/index.js +0 -13
- package/esm/transformers-direct/v13-to-v17/index.js +0 -74
- package/esm/transformers-direct/v13-to-v18/index.js +0 -84
- package/esm/transformers-direct/v14-to-v17/index.js +0 -63
- package/esm/transformers-direct/v14-to-v18/index.js +0 -73
- package/esm/transformers-direct/v15-to-v17/index.js +0 -53
- package/esm/transformers-direct/v15-to-v18/index.js +0 -62
- package/esm/transformers-direct/v16-to-v17/index.js +0 -40
- package/esm/transformers-direct/v16-to-v18/index.js +0 -51
- package/esm/transformers-direct/v17-to-v18/index.js +0 -39
- package/multi-version-transformer.d.ts +0 -14
- package/multi-version-transformer.js +0 -84
- package/transformers/context.d.ts +0 -4
- package/transformers/context.js +0 -2
- package/transformers/v13-to-v14.d.ts +0 -255
- package/transformers/v13-to-v14.js +0 -2771
- package/transformers/v14-to-v15.d.ts +0 -615
- package/transformers/v14-to-v15.js +0 -1222
- package/transformers/v15-to-v16.d.ts +0 -632
- package/transformers/v15-to-v16.js +0 -2939
- package/transformers/v16-to-v17.d.ts +0 -640
- package/transformers/v16-to-v17.js +0 -1530
- package/transformers/v17-to-v18.d.ts +0 -54
- package/transformers/v17-to-v18.js +0 -208
- package/transformers-direct/index.d.ts +0 -13
- package/transformers-direct/index.js +0 -25
- package/transformers-direct/v13-to-v17/index.d.ts +0 -27
- package/transformers-direct/v13-to-v17/index.js +0 -78
- package/transformers-direct/v13-to-v18/index.d.ts +0 -28
- package/transformers-direct/v13-to-v18/index.js +0 -88
- package/transformers-direct/v14-to-v17/index.d.ts +0 -26
- package/transformers-direct/v14-to-v17/index.js +0 -67
- package/transformers-direct/v14-to-v18/index.d.ts +0 -27
- package/transformers-direct/v14-to-v18/index.js +0 -77
- package/transformers-direct/v15-to-v17/index.d.ts +0 -25
- package/transformers-direct/v15-to-v17/index.js +0 -57
- package/transformers-direct/v15-to-v18/index.d.ts +0 -26
- package/transformers-direct/v15-to-v18/index.js +0 -66
- package/transformers-direct/v16-to-v17/index.d.ts +0 -24
- package/transformers-direct/v16-to-v17/index.js +0 -44
- package/transformers-direct/v16-to-v18/index.d.ts +0 -25
- package/transformers-direct/v16-to-v18/index.js +0 -55
- package/transformers-direct/v17-to-v18/index.d.ts +0 -24
- package/transformers-direct/v17-to-v18/index.js +0 -43
package/facts.d.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A (possibly schema-qualified) object name extracted from a statement.
|
|
3
|
+
*/
|
|
4
|
+
export interface QualifiedName {
|
|
5
|
+
schema: string | null;
|
|
6
|
+
name: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Coarse statement classification used for tier/package sorting.
|
|
10
|
+
*/
|
|
11
|
+
export type StatementKind = 'schema' | 'table' | 'view' | 'index' | 'type' | 'function' | 'trigger' | 'policy' | 'grant' | 'rls_enable' | 'fk_constraint' | 'constraint' | 'comment' | 'seed_dml' | 'other';
|
|
12
|
+
/**
|
|
13
|
+
* AST-derived facts about a single top-level SQL statement.
|
|
14
|
+
*
|
|
15
|
+
* Read-only: classification never modifies the statement. Facts are the
|
|
16
|
+
* substrate for classifier-driven slicing (schema / functionality / security
|
|
17
|
+
* tiers) — replacing path/name-glob decisions with computed properties like
|
|
18
|
+
* "this trigger function references billing".
|
|
19
|
+
*/
|
|
20
|
+
export interface StatementFacts {
|
|
21
|
+
/** Coarse category of the statement. */
|
|
22
|
+
kind: StatementKind;
|
|
23
|
+
/** The raw parser node tag (e.g. `CreateStmt`, `CreatePolicyStmt`). */
|
|
24
|
+
nodeTag: string;
|
|
25
|
+
/** Objects this statement creates or directly targets. */
|
|
26
|
+
creates: QualifiedName[];
|
|
27
|
+
/**
|
|
28
|
+
* Schema-qualified objects this statement references — tables, functions
|
|
29
|
+
* and types reached anywhere in the statement, including PL/pgSQL bodies.
|
|
30
|
+
* Unqualified references are omitted (they resolve via search_path and
|
|
31
|
+
* carry no cross-schema information).
|
|
32
|
+
*/
|
|
33
|
+
references: QualifiedName[];
|
|
34
|
+
/**
|
|
35
|
+
* The subset of `references` reached only inside a PL/pgSQL body. These
|
|
36
|
+
* are late-binding: Postgres resolves them at call time, not at CREATE
|
|
37
|
+
* time, so they do not constrain deploy order (and legitimately form
|
|
38
|
+
* recursion cycles between functions).
|
|
39
|
+
*/
|
|
40
|
+
bodyReferences: QualifiedName[];
|
|
41
|
+
/** Distinct schemas reached by `references`. */
|
|
42
|
+
referencedSchemas: string[];
|
|
43
|
+
/** Role names granted to, owning, or bound by this statement. */
|
|
44
|
+
roles: string[];
|
|
45
|
+
/** Foreign-key target tables (from column/table FK constraints). */
|
|
46
|
+
fkTargets: QualifiedName[];
|
|
47
|
+
/**
|
|
48
|
+
* Whether the statement is part of the security surface: policies, grants,
|
|
49
|
+
* RLS enable/force, security labels, ownership.
|
|
50
|
+
*/
|
|
51
|
+
securityRelevant: boolean;
|
|
52
|
+
/** For functions: declared with SECURITY DEFINER. */
|
|
53
|
+
securityDefiner: boolean;
|
|
54
|
+
/**
|
|
55
|
+
* For functions: the body executes dynamic SQL (EXECUTE / EXECUTE ... USING
|
|
56
|
+
* / FOR ... IN EXECUTE). Analogous to `eval` — references inside the
|
|
57
|
+
* dynamic string are invisible to the AST, so edges from this statement
|
|
58
|
+
* are incomplete and slicing should treat it conservatively.
|
|
59
|
+
*/
|
|
60
|
+
dynamicSql: boolean;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Classify each top-level statement in a SQL script into {@link StatementFacts}.
|
|
64
|
+
*
|
|
65
|
+
* Uses the same parser stack as the schema transformer (pgsql AST walk plus
|
|
66
|
+
* hydrated PL/pgSQL body walk), so references inside function bodies are
|
|
67
|
+
* included. The input SQL is never modified.
|
|
68
|
+
*/
|
|
69
|
+
export declare function classifyStatements(sql: string): StatementFacts[];
|
package/facts.js
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.classifyStatements = classifyStatements;
|
|
4
|
+
const traverse_1 = require("@pgsql/traverse");
|
|
5
|
+
const plpgsql_parser_1 = require("plpgsql-parser");
|
|
6
|
+
const SECURITY_TAGS = new Set([
|
|
7
|
+
'CreatePolicyStmt',
|
|
8
|
+
'AlterPolicyStmt',
|
|
9
|
+
'GrantStmt',
|
|
10
|
+
'GrantRoleStmt',
|
|
11
|
+
'AlterDefaultPrivilegesStmt',
|
|
12
|
+
'SecLabelStmt',
|
|
13
|
+
'AlterOwnerStmt',
|
|
14
|
+
'CreateRoleStmt',
|
|
15
|
+
'AlterRoleStmt'
|
|
16
|
+
]);
|
|
17
|
+
const KIND_BY_TAG = {
|
|
18
|
+
CreateSchemaStmt: 'schema',
|
|
19
|
+
CreateStmt: 'table',
|
|
20
|
+
ViewStmt: 'view',
|
|
21
|
+
IndexStmt: 'index',
|
|
22
|
+
CompositeTypeStmt: 'type',
|
|
23
|
+
CreateEnumStmt: 'type',
|
|
24
|
+
CreateDomainStmt: 'type',
|
|
25
|
+
CreateRangeStmt: 'type',
|
|
26
|
+
DefineStmt: 'type',
|
|
27
|
+
CreateFunctionStmt: 'function',
|
|
28
|
+
CreateTrigStmt: 'trigger',
|
|
29
|
+
CreateEventTrigStmt: 'trigger',
|
|
30
|
+
CreatePolicyStmt: 'policy',
|
|
31
|
+
AlterPolicyStmt: 'policy',
|
|
32
|
+
GrantStmt: 'grant',
|
|
33
|
+
GrantRoleStmt: 'grant',
|
|
34
|
+
AlterDefaultPrivilegesStmt: 'grant',
|
|
35
|
+
CommentStmt: 'comment',
|
|
36
|
+
InsertStmt: 'seed_dml',
|
|
37
|
+
UpdateStmt: 'seed_dml',
|
|
38
|
+
DeleteStmt: 'seed_dml'
|
|
39
|
+
};
|
|
40
|
+
function qn(schema, name) {
|
|
41
|
+
return { schema: schema ?? null, name };
|
|
42
|
+
}
|
|
43
|
+
function nameListToQualified(names) {
|
|
44
|
+
if (!Array.isArray(names) || names.length === 0)
|
|
45
|
+
return null;
|
|
46
|
+
const parts = names
|
|
47
|
+
.map((n) => n?.String?.sval)
|
|
48
|
+
.filter((s) => typeof s === 'string');
|
|
49
|
+
if (parts.length === 0)
|
|
50
|
+
return null;
|
|
51
|
+
if (parts.length === 1)
|
|
52
|
+
return qn(null, parts[0]);
|
|
53
|
+
return qn(parts[parts.length - 2], parts[parts.length - 1]);
|
|
54
|
+
}
|
|
55
|
+
function isCatalogSchema(schema) {
|
|
56
|
+
return schema === 'pg_catalog' || schema === 'information_schema';
|
|
57
|
+
}
|
|
58
|
+
function pushRef(refs, ref) {
|
|
59
|
+
if (!ref || !ref.schema || isCatalogSchema(ref.schema))
|
|
60
|
+
return;
|
|
61
|
+
if (refs.some(r => r.schema === ref.schema && r.name === ref.name))
|
|
62
|
+
return;
|
|
63
|
+
refs.push(ref);
|
|
64
|
+
}
|
|
65
|
+
function collectRoles(node, roles) {
|
|
66
|
+
const push = (role) => {
|
|
67
|
+
if (typeof role === 'string' && role.length > 0 && !roles.includes(role)) {
|
|
68
|
+
roles.push(role);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
if (Array.isArray(node?.grantees)) {
|
|
72
|
+
for (const g of node.grantees)
|
|
73
|
+
push(g?.RoleSpec?.rolename);
|
|
74
|
+
}
|
|
75
|
+
if (Array.isArray(node?.roles)) {
|
|
76
|
+
for (const r of node.roles)
|
|
77
|
+
push(r?.RoleSpec?.rolename);
|
|
78
|
+
}
|
|
79
|
+
push(node?.newowner?.rolename);
|
|
80
|
+
push(node?.role?.rolename);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Create a read-only visitor that accumulates references, roles and FK
|
|
84
|
+
* targets into the provided facts object.
|
|
85
|
+
*/
|
|
86
|
+
function createFactsVisitor(facts, bodyRefs) {
|
|
87
|
+
const push = (ref) => {
|
|
88
|
+
pushRef(facts.references, ref);
|
|
89
|
+
if (bodyRefs)
|
|
90
|
+
pushRef(bodyRefs, ref);
|
|
91
|
+
};
|
|
92
|
+
return {
|
|
93
|
+
RangeVar: (path) => {
|
|
94
|
+
const node = path.node;
|
|
95
|
+
if (node.schemaname) {
|
|
96
|
+
push(qn(node.schemaname, node.relname));
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
FuncCall: (path) => {
|
|
100
|
+
push(nameListToQualified(path.node.funcname));
|
|
101
|
+
},
|
|
102
|
+
TypeName: (path) => {
|
|
103
|
+
push(nameListToQualified(path.node.names));
|
|
104
|
+
},
|
|
105
|
+
ColumnRef: (path) => {
|
|
106
|
+
// schema.table.column references carry cross-schema information
|
|
107
|
+
const fields = path.node.fields;
|
|
108
|
+
if (Array.isArray(fields) && fields.length >= 3) {
|
|
109
|
+
const parts = fields
|
|
110
|
+
.map((f) => f?.String?.sval)
|
|
111
|
+
.filter((s) => typeof s === 'string');
|
|
112
|
+
if (parts.length >= 3) {
|
|
113
|
+
push(qn(parts[0], parts[1]));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
Constraint: (path) => {
|
|
118
|
+
const node = path.node;
|
|
119
|
+
if (node.contype === 'CONSTR_FOREIGN' && node.pktable) {
|
|
120
|
+
const target = qn(node.pktable.schemaname ?? null, node.pktable.relname);
|
|
121
|
+
if (!facts.fkTargets.some(t => t.schema === target.schema && t.name === target.name)) {
|
|
122
|
+
facts.fkTargets.push(target);
|
|
123
|
+
}
|
|
124
|
+
if (target.schema)
|
|
125
|
+
pushRef(facts.references, target);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
function classifyOne(nodeTag, node) {
|
|
131
|
+
const facts = {
|
|
132
|
+
kind: KIND_BY_TAG[nodeTag] ?? 'other',
|
|
133
|
+
nodeTag,
|
|
134
|
+
creates: [],
|
|
135
|
+
references: [],
|
|
136
|
+
referencedSchemas: [],
|
|
137
|
+
roles: [],
|
|
138
|
+
fkTargets: [],
|
|
139
|
+
bodyReferences: [],
|
|
140
|
+
securityRelevant: SECURITY_TAGS.has(nodeTag),
|
|
141
|
+
securityDefiner: false,
|
|
142
|
+
dynamicSql: false
|
|
143
|
+
};
|
|
144
|
+
switch (nodeTag) {
|
|
145
|
+
case 'CreateSchemaStmt':
|
|
146
|
+
facts.creates.push(qn(null, node.schemaname));
|
|
147
|
+
break;
|
|
148
|
+
case 'CreateStmt':
|
|
149
|
+
case 'ViewStmt': {
|
|
150
|
+
const rel = nodeTag === 'ViewStmt' ? node.view : node.relation;
|
|
151
|
+
if (rel)
|
|
152
|
+
facts.creates.push(qn(rel.schemaname ?? null, rel.relname));
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
case 'IndexStmt':
|
|
156
|
+
if (node.relation) {
|
|
157
|
+
facts.creates.push(qn(node.relation.schemaname ?? null, node.idxname ?? node.relation.relname));
|
|
158
|
+
}
|
|
159
|
+
break;
|
|
160
|
+
case 'CreateFunctionStmt': {
|
|
161
|
+
const name = nameListToQualified(node.funcname);
|
|
162
|
+
if (name)
|
|
163
|
+
facts.creates.push(name);
|
|
164
|
+
for (const opt of node.options ?? []) {
|
|
165
|
+
const def = opt?.DefElem;
|
|
166
|
+
if (def?.defname === 'security' && def?.arg?.Boolean?.boolval === true) {
|
|
167
|
+
facts.securityDefiner = true;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
case 'CreateTrigStmt':
|
|
173
|
+
if (node.relation) {
|
|
174
|
+
// Trigger names are only unique per table; qualify with the table.
|
|
175
|
+
facts.creates.push(qn(node.relation.schemaname ?? null, `${node.relation.relname}.${node.trigname}`));
|
|
176
|
+
}
|
|
177
|
+
pushRef(facts.references, nameListToQualified(node.funcname));
|
|
178
|
+
break;
|
|
179
|
+
case 'CreatePolicyStmt':
|
|
180
|
+
case 'AlterPolicyStmt':
|
|
181
|
+
if (node.table) {
|
|
182
|
+
// Policy names are only unique per table; qualify with the table.
|
|
183
|
+
facts.creates.push(qn(node.table.schemaname ?? null, `${node.table.relname}.${node.policy_name}`));
|
|
184
|
+
// The guarded table lives on `node.table`; the generic RangeVar walker
|
|
185
|
+
// does not descend into it, so capture the reference explicitly.
|
|
186
|
+
if (node.table.schemaname) {
|
|
187
|
+
pushRef(facts.references, qn(node.table.schemaname, node.table.relname));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
break;
|
|
191
|
+
case 'CreateSeqStmt':
|
|
192
|
+
if (node.sequence) {
|
|
193
|
+
facts.creates.push(qn(node.sequence.schemaname ?? null, node.sequence.relname));
|
|
194
|
+
}
|
|
195
|
+
break;
|
|
196
|
+
case 'CompositeTypeStmt':
|
|
197
|
+
if (node.typevar) {
|
|
198
|
+
facts.creates.push(qn(node.typevar.schemaname ?? null, node.typevar.relname));
|
|
199
|
+
}
|
|
200
|
+
break;
|
|
201
|
+
case 'CreateEnumStmt':
|
|
202
|
+
case 'CreateDomainStmt':
|
|
203
|
+
case 'CreateRangeStmt': {
|
|
204
|
+
const name = nameListToQualified(node.typeName ?? node.domainname);
|
|
205
|
+
if (name)
|
|
206
|
+
facts.creates.push(name);
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
case 'AlterTableStmt': {
|
|
210
|
+
if (node.relation) {
|
|
211
|
+
facts.creates.push(qn(node.relation.schemaname ?? null, node.relation.relname));
|
|
212
|
+
}
|
|
213
|
+
const cmds = node.cmds ?? [];
|
|
214
|
+
for (const cmd of cmds) {
|
|
215
|
+
const subtype = cmd?.AlterTableCmd?.subtype;
|
|
216
|
+
if (subtype === 'AT_EnableRowSecurity' || subtype === 'AT_ForceRowSecurity' ||
|
|
217
|
+
subtype === 'AT_DisableRowSecurity' || subtype === 'AT_NoForceRowSecurity') {
|
|
218
|
+
facts.kind = 'rls_enable';
|
|
219
|
+
facts.securityRelevant = true;
|
|
220
|
+
}
|
|
221
|
+
else if (subtype === 'AT_AddConstraint') {
|
|
222
|
+
const contype = cmd?.AlterTableCmd?.def?.Constraint?.contype;
|
|
223
|
+
facts.kind = contype === 'CONSTR_FOREIGN' ? 'fk_constraint' : 'constraint';
|
|
224
|
+
}
|
|
225
|
+
else if (subtype === 'AT_ChangeOwner') {
|
|
226
|
+
facts.securityRelevant = true;
|
|
227
|
+
const owner = cmd?.AlterTableCmd?.newowner?.rolename;
|
|
228
|
+
if (owner && !facts.roles.includes(owner))
|
|
229
|
+
facts.roles.push(owner);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
case 'InsertStmt':
|
|
235
|
+
case 'UpdateStmt':
|
|
236
|
+
case 'DeleteStmt':
|
|
237
|
+
if (node.relation) {
|
|
238
|
+
facts.creates.push(qn(node.relation.schemaname ?? null, node.relation.relname));
|
|
239
|
+
}
|
|
240
|
+
break;
|
|
241
|
+
default:
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
collectRoles(node, facts.roles);
|
|
245
|
+
return facts;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Classify each top-level statement in a SQL script into {@link StatementFacts}.
|
|
249
|
+
*
|
|
250
|
+
* Uses the same parser stack as the schema transformer (pgsql AST walk plus
|
|
251
|
+
* hydrated PL/pgSQL body walk), so references inside function bodies are
|
|
252
|
+
* included. The input SQL is never modified.
|
|
253
|
+
*/
|
|
254
|
+
function classifyStatements(sql) {
|
|
255
|
+
const allFacts = [];
|
|
256
|
+
(0, plpgsql_parser_1.transformSync)(sql, (ctx) => {
|
|
257
|
+
const stmts = ctx.sql?.stmts ?? [];
|
|
258
|
+
for (const stmt of stmts) {
|
|
259
|
+
const stmtNode = stmt?.stmt;
|
|
260
|
+
const nodeTag = stmtNode ? Object.keys(stmtNode)[0] : 'other';
|
|
261
|
+
const node = stmtNode?.[nodeTag] ?? {};
|
|
262
|
+
const facts = classifyOne(nodeTag, node);
|
|
263
|
+
if (stmtNode) {
|
|
264
|
+
(0, traverse_1.walk)(stmtNode, createFactsVisitor(facts));
|
|
265
|
+
}
|
|
266
|
+
allFacts.push(facts);
|
|
267
|
+
}
|
|
268
|
+
for (const fn of ctx.functions ?? []) {
|
|
269
|
+
const facts = allFacts[fn.stmtIndex];
|
|
270
|
+
if (!facts || !fn.plpgsql?.hydrated)
|
|
271
|
+
continue;
|
|
272
|
+
// Refs already found outside the body (signature types, defaults)
|
|
273
|
+
// constrain deploy order and are not body-only.
|
|
274
|
+
const outer = new Set(facts.references.map(r => `${r.schema ?? '?'}.${r.name}`));
|
|
275
|
+
(0, plpgsql_parser_1.walk)(fn.plpgsql.hydrated, {
|
|
276
|
+
PLpgSQL_stmt_dynexecute: () => { facts.dynamicSql = true; },
|
|
277
|
+
PLpgSQL_stmt_dynfors: () => { facts.dynamicSql = true; }
|
|
278
|
+
}, {
|
|
279
|
+
walkSqlExpressions: true,
|
|
280
|
+
sqlVisitor: createFactsVisitor(facts, facts.bodyReferences)
|
|
281
|
+
});
|
|
282
|
+
facts.bodyReferences = facts.bodyReferences.filter(r => !outer.has(`${r.schema ?? '?'}.${r.name}`));
|
|
283
|
+
}
|
|
284
|
+
}, { hydrate: true });
|
|
285
|
+
for (const facts of allFacts) {
|
|
286
|
+
const selfRef = (r) => facts.creates.some(c => c.schema === r.schema && c.name === r.name);
|
|
287
|
+
facts.references = facts.references.filter(r => !selfRef(r));
|
|
288
|
+
facts.bodyReferences = facts.bodyReferences.filter(r => !selfRef(r));
|
|
289
|
+
facts.referencedSchemas = [...new Set(facts.references.map(r => r.schema).filter(Boolean))];
|
|
290
|
+
}
|
|
291
|
+
return allFacts;
|
|
292
|
+
}
|
package/index.d.ts
CHANGED
|
@@ -1,28 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
import * as PG17Types from './17/types';
|
|
12
|
-
import * as PG18Types from './18/types';
|
|
13
|
-
export { ASTTransformer } from './multi-version-transformer';
|
|
14
|
-
export { V13ToV14Transformer } from './transformers/v13-to-v14';
|
|
15
|
-
export { V14ToV15Transformer } from './transformers/v14-to-v15';
|
|
16
|
-
export { V15ToV16Transformer } from './transformers/v15-to-v16';
|
|
17
|
-
export { V16ToV17Transformer } from './transformers/v16-to-v17';
|
|
18
|
-
export { V17ToV18Transformer } from './transformers/v17-to-v18';
|
|
19
|
-
export { PG13ToPG17Transformer } from './transformers-direct/v13-to-v17';
|
|
20
|
-
export { PG14ToPG17Transformer } from './transformers-direct/v14-to-v17';
|
|
21
|
-
export { PG15ToPG17Transformer } from './transformers-direct/v15-to-v17';
|
|
22
|
-
export { PG16ToPG17Transformer } from './transformers-direct/v16-to-v17';
|
|
23
|
-
export { PG13ToPG18Transformer } from './transformers-direct/v13-to-v18';
|
|
24
|
-
export { PG14ToPG18Transformer } from './transformers-direct/v14-to-v18';
|
|
25
|
-
export { PG15ToPG18Transformer } from './transformers-direct/v15-to-v18';
|
|
26
|
-
export { PG16ToPG18Transformer } from './transformers-direct/v16-to-v18';
|
|
27
|
-
export { PG17ToPG18Transformer } from './transformers-direct/v17-to-v18';
|
|
28
|
-
export { PG13Node, PG14Node, PG15Node, PG16Node, PG17Node, PG18Node, PG13Types, PG14Types, PG15Types, PG16Types, PG17Types, PG18Types };
|
|
1
|
+
export type { QualifiedName, StatementFacts, StatementKind, } from './facts';
|
|
2
|
+
export { classifyStatements } from './facts';
|
|
3
|
+
export type { ObjectInventory, QualifyResult, QualifyRoutes, QualifyTargetSelector, QualifyUnqualifiedOptions, } from './qualify';
|
|
4
|
+
export { collectCreatedObjects, createQualifyVisitor, mergeInventories, qualifyUnqualified, } from './qualify';
|
|
5
|
+
export type { CapturedAsts } from './round-trip';
|
|
6
|
+
export { captureAstsFromSql, captureTransformAsts, firstDifference, normalizeParseTree, validateRoundTrip, } from './round-trip';
|
|
7
|
+
export type { NormalizeTreeOptions } from './round-trip-core';
|
|
8
|
+
export { CLEAN_TREE_VOLATILE_KEYS, cleanTree, normalizeTree, trimDefElemBody, } from './round-trip-core';
|
|
9
|
+
export type { SchemaTransformPass, SchemaTransformResult, TransformSqlOptions, } from './transform';
|
|
10
|
+
export { createPlpgsqlVisitor, createSqlVisitor, escapeRegexp, extractPgpmHeader, shouldTransformSchema, transformComments, transformJsonStringValues, transformNameList, transformPlpgsqlTypeAst, transformPlpgsqlTypeString, transformRelation, transformSchemaName, transformSql, transformSqlStatement, transformVerifyCalls, validateNoUntransformedSchemas, walkPlpgsqlForSchemas, } from './transform';
|
package/index.js
CHANGED
|
@@ -1,78 +1,39 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.
|
|
37
|
-
|
|
38
|
-
exports.
|
|
39
|
-
|
|
40
|
-
exports.
|
|
41
|
-
|
|
42
|
-
exports.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
exports.
|
|
47
|
-
|
|
48
|
-
exports.
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
Object.defineProperty(exports, "
|
|
53
|
-
|
|
54
|
-
Object.defineProperty(exports, "
|
|
55
|
-
var
|
|
56
|
-
Object.defineProperty(exports, "
|
|
57
|
-
|
|
58
|
-
Object.defineProperty(exports, "
|
|
59
|
-
|
|
60
|
-
Object.defineProperty(exports, "
|
|
61
|
-
|
|
62
|
-
Object.defineProperty(exports, "
|
|
63
|
-
|
|
64
|
-
Object.defineProperty(exports, "
|
|
65
|
-
|
|
66
|
-
Object.defineProperty(exports, "
|
|
67
|
-
|
|
68
|
-
Object.defineProperty(exports, "
|
|
69
|
-
|
|
70
|
-
Object.defineProperty(exports, "
|
|
71
|
-
|
|
72
|
-
Object.defineProperty(exports, "
|
|
73
|
-
var v15_to_v18_1 = require("./transformers-direct/v15-to-v18");
|
|
74
|
-
Object.defineProperty(exports, "PG15ToPG18Transformer", { enumerable: true, get: function () { return v15_to_v18_1.PG15ToPG18Transformer; } });
|
|
75
|
-
var v16_to_v18_1 = require("./transformers-direct/v16-to-v18");
|
|
76
|
-
Object.defineProperty(exports, "PG16ToPG18Transformer", { enumerable: true, get: function () { return v16_to_v18_1.PG16ToPG18Transformer; } });
|
|
77
|
-
var v17_to_v18_2 = require("./transformers-direct/v17-to-v18");
|
|
78
|
-
Object.defineProperty(exports, "PG17ToPG18Transformer", { enumerable: true, get: function () { return v17_to_v18_2.PG17ToPG18Transformer; } });
|
|
3
|
+
exports.walkPlpgsqlForSchemas = exports.validateNoUntransformedSchemas = exports.transformVerifyCalls = exports.transformSqlStatement = exports.transformSql = exports.transformSchemaName = exports.transformRelation = exports.transformPlpgsqlTypeString = exports.transformPlpgsqlTypeAst = exports.transformNameList = exports.transformJsonStringValues = exports.transformComments = exports.shouldTransformSchema = exports.extractPgpmHeader = exports.escapeRegexp = exports.createSqlVisitor = exports.createPlpgsqlVisitor = exports.trimDefElemBody = exports.normalizeTree = exports.cleanTree = exports.CLEAN_TREE_VOLATILE_KEYS = exports.validateRoundTrip = exports.normalizeParseTree = exports.firstDifference = exports.captureTransformAsts = exports.captureAstsFromSql = exports.qualifyUnqualified = exports.mergeInventories = exports.createQualifyVisitor = exports.collectCreatedObjects = exports.classifyStatements = void 0;
|
|
4
|
+
var facts_1 = require("./facts");
|
|
5
|
+
Object.defineProperty(exports, "classifyStatements", { enumerable: true, get: function () { return facts_1.classifyStatements; } });
|
|
6
|
+
var qualify_1 = require("./qualify");
|
|
7
|
+
Object.defineProperty(exports, "collectCreatedObjects", { enumerable: true, get: function () { return qualify_1.collectCreatedObjects; } });
|
|
8
|
+
Object.defineProperty(exports, "createQualifyVisitor", { enumerable: true, get: function () { return qualify_1.createQualifyVisitor; } });
|
|
9
|
+
Object.defineProperty(exports, "mergeInventories", { enumerable: true, get: function () { return qualify_1.mergeInventories; } });
|
|
10
|
+
Object.defineProperty(exports, "qualifyUnqualified", { enumerable: true, get: function () { return qualify_1.qualifyUnqualified; } });
|
|
11
|
+
var round_trip_1 = require("./round-trip");
|
|
12
|
+
Object.defineProperty(exports, "captureAstsFromSql", { enumerable: true, get: function () { return round_trip_1.captureAstsFromSql; } });
|
|
13
|
+
Object.defineProperty(exports, "captureTransformAsts", { enumerable: true, get: function () { return round_trip_1.captureTransformAsts; } });
|
|
14
|
+
Object.defineProperty(exports, "firstDifference", { enumerable: true, get: function () { return round_trip_1.firstDifference; } });
|
|
15
|
+
Object.defineProperty(exports, "normalizeParseTree", { enumerable: true, get: function () { return round_trip_1.normalizeParseTree; } });
|
|
16
|
+
Object.defineProperty(exports, "validateRoundTrip", { enumerable: true, get: function () { return round_trip_1.validateRoundTrip; } });
|
|
17
|
+
var round_trip_core_1 = require("./round-trip-core");
|
|
18
|
+
Object.defineProperty(exports, "CLEAN_TREE_VOLATILE_KEYS", { enumerable: true, get: function () { return round_trip_core_1.CLEAN_TREE_VOLATILE_KEYS; } });
|
|
19
|
+
Object.defineProperty(exports, "cleanTree", { enumerable: true, get: function () { return round_trip_core_1.cleanTree; } });
|
|
20
|
+
Object.defineProperty(exports, "normalizeTree", { enumerable: true, get: function () { return round_trip_core_1.normalizeTree; } });
|
|
21
|
+
Object.defineProperty(exports, "trimDefElemBody", { enumerable: true, get: function () { return round_trip_core_1.trimDefElemBody; } });
|
|
22
|
+
var transform_1 = require("./transform");
|
|
23
|
+
Object.defineProperty(exports, "createPlpgsqlVisitor", { enumerable: true, get: function () { return transform_1.createPlpgsqlVisitor; } });
|
|
24
|
+
Object.defineProperty(exports, "createSqlVisitor", { enumerable: true, get: function () { return transform_1.createSqlVisitor; } });
|
|
25
|
+
Object.defineProperty(exports, "escapeRegexp", { enumerable: true, get: function () { return transform_1.escapeRegexp; } });
|
|
26
|
+
Object.defineProperty(exports, "extractPgpmHeader", { enumerable: true, get: function () { return transform_1.extractPgpmHeader; } });
|
|
27
|
+
Object.defineProperty(exports, "shouldTransformSchema", { enumerable: true, get: function () { return transform_1.shouldTransformSchema; } });
|
|
28
|
+
Object.defineProperty(exports, "transformComments", { enumerable: true, get: function () { return transform_1.transformComments; } });
|
|
29
|
+
Object.defineProperty(exports, "transformJsonStringValues", { enumerable: true, get: function () { return transform_1.transformJsonStringValues; } });
|
|
30
|
+
Object.defineProperty(exports, "transformNameList", { enumerable: true, get: function () { return transform_1.transformNameList; } });
|
|
31
|
+
Object.defineProperty(exports, "transformPlpgsqlTypeAst", { enumerable: true, get: function () { return transform_1.transformPlpgsqlTypeAst; } });
|
|
32
|
+
Object.defineProperty(exports, "transformPlpgsqlTypeString", { enumerable: true, get: function () { return transform_1.transformPlpgsqlTypeString; } });
|
|
33
|
+
Object.defineProperty(exports, "transformRelation", { enumerable: true, get: function () { return transform_1.transformRelation; } });
|
|
34
|
+
Object.defineProperty(exports, "transformSchemaName", { enumerable: true, get: function () { return transform_1.transformSchemaName; } });
|
|
35
|
+
Object.defineProperty(exports, "transformSql", { enumerable: true, get: function () { return transform_1.transformSql; } });
|
|
36
|
+
Object.defineProperty(exports, "transformSqlStatement", { enumerable: true, get: function () { return transform_1.transformSqlStatement; } });
|
|
37
|
+
Object.defineProperty(exports, "transformVerifyCalls", { enumerable: true, get: function () { return transform_1.transformVerifyCalls; } });
|
|
38
|
+
Object.defineProperty(exports, "validateNoUntransformedSchemas", { enumerable: true, get: function () { return transform_1.validateNoUntransformedSchemas; } });
|
|
39
|
+
Object.defineProperty(exports, "walkPlpgsqlForSchemas", { enumerable: true, get: function () { return transform_1.walkPlpgsqlForSchemas; } });
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pgsql/transform",
|
|
3
|
-
"version": "18.
|
|
3
|
+
"version": "18.3.1",
|
|
4
4
|
"author": "Constructive <developers@constructive.io>",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "AST-based SQL transformation, qualification, classification and closure analysis for PostgreSQL",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"module": "esm/index.js",
|
|
8
8
|
"types": "index.d.ts",
|
|
@@ -23,23 +23,31 @@
|
|
|
23
23
|
"copy": "makage assets",
|
|
24
24
|
"clean": "makage clean dist",
|
|
25
25
|
"prepublishOnly": "npm run build",
|
|
26
|
-
"build": "npm run
|
|
26
|
+
"build": "npm run clean && tsc && tsc -p tsconfig.esm.json && npm run copy",
|
|
27
27
|
"build:dev": "npm run clean && tsc --declarationMap && tsc -p tsconfig.esm.json && npm run copy",
|
|
28
|
-
"build:proto": "ts-node scripts/pg-proto-parser",
|
|
29
28
|
"lint": "eslint . --fix",
|
|
30
29
|
"test": "jest",
|
|
31
30
|
"test:watch": "jest --watch",
|
|
32
|
-
"
|
|
33
|
-
"
|
|
31
|
+
"fixtures": "ts-node scripts/make-fixtures.ts",
|
|
32
|
+
"scan-corpus": "node scripts/scan-corpus.js"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@pgsql/quotes": "18.1.0",
|
|
36
|
+
"@pgsql/traverse": "18.3.0",
|
|
37
|
+
"plpgsql-parser": "18.2.1"
|
|
34
38
|
},
|
|
35
39
|
"devDependencies": {
|
|
36
|
-
"
|
|
37
|
-
"@pgsql/types": "^18.0.0",
|
|
38
|
-
"libpg-query": "18.1.2",
|
|
39
|
-
"makage": "^0.1.8",
|
|
40
|
-
"pg-proto-parser": "1.31.0",
|
|
41
|
-
"pgsql-deparser": "18.1.1"
|
|
40
|
+
"makage": "^0.1.8"
|
|
42
41
|
},
|
|
43
|
-
"keywords": [
|
|
44
|
-
|
|
42
|
+
"keywords": [
|
|
43
|
+
"sql",
|
|
44
|
+
"postgres",
|
|
45
|
+
"postgresql",
|
|
46
|
+
"pg",
|
|
47
|
+
"ast",
|
|
48
|
+
"transform",
|
|
49
|
+
"classify",
|
|
50
|
+
"plpgsql"
|
|
51
|
+
],
|
|
52
|
+
"gitHead": "ef29a3eb49d020f309f7289dbf1fd1e642ed5008"
|
|
45
53
|
}
|