@pgsql/transform 18.1.1 → 18.3.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 +29 -73
- package/categorize.d.ts +52 -0
- package/categorize.js +56 -0
- package/esm/categorize.js +51 -0
- package/esm/facts.js +289 -0
- package/esm/fixture-closure.js +197 -0
- package/esm/index.js +7 -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/fixture-closure.d.ts +71 -0
- package/fixture-closure.js +200 -0
- package/index.d.ts +14 -28
- package/index.js +43 -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
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Round-trip validation for the schema transform.
|
|
3
|
+
*
|
|
4
|
+
* After the transform deparses its mutated AST to SQL text, the emitted text
|
|
5
|
+
* must parse back to an AST that is structurally identical to the AST we
|
|
6
|
+
* deparsed (AST1 === AST2 after normalization). Any mismatch means the
|
|
7
|
+
* deparser dropped or mangled something (e.g. array bounds on a DECLAREd
|
|
8
|
+
* type), even though the output may still be syntactically valid SQL.
|
|
9
|
+
*
|
|
10
|
+
* Two comparisons are performed per file:
|
|
11
|
+
* - the SQL-level parse tree (with volatile fields and function body strings
|
|
12
|
+
* normalized — PL/pgSQL bodies are compared separately)
|
|
13
|
+
* - each PL/pgSQL function body, compared in dehydrated form so both sides
|
|
14
|
+
* go through the same hydrate -> dehydrate rendering
|
|
15
|
+
*/
|
|
16
|
+
import { dehydratePlpgsqlAst, transformSync } from 'plpgsql-parser';
|
|
17
|
+
import { CLEAN_TREE_VOLATILE_KEYS, firstDifference, normalizeTree, } from './round-trip-core';
|
|
18
|
+
export { firstDifference };
|
|
19
|
+
/**
|
|
20
|
+
* Fields that legitimately differ between parses. Extends the upstream
|
|
21
|
+
* `cleanTree` volatile set (location/stmt_location/stmt_len) with:
|
|
22
|
+
* - lineno: source positions in PL/pgSQL nodes
|
|
23
|
+
* - dno/varno/recparentno: PL/pgSQL datum numbers — compiler bookkeeping
|
|
24
|
+
* assigned in parse-encounter order, which shifts when the deparser
|
|
25
|
+
* emits an equivalent-but-reordered statement (e.g. INTO placement).
|
|
26
|
+
* Structural identity is still checked via names/fieldnames.
|
|
27
|
+
*/
|
|
28
|
+
const VOLATILE_KEYS = new Set([
|
|
29
|
+
...CLEAN_TREE_VOLATILE_KEYS,
|
|
30
|
+
'lineno',
|
|
31
|
+
'dno',
|
|
32
|
+
'varno',
|
|
33
|
+
'recparentno',
|
|
34
|
+
]);
|
|
35
|
+
/**
|
|
36
|
+
* PLpgSQL_recfield datums are created lazily by the PL/pgSQL compiler as
|
|
37
|
+
* record.field references are encountered while parsing expressions, so
|
|
38
|
+
* their presence/order in the datums array depends on expression text
|
|
39
|
+
* layout, not semantics.
|
|
40
|
+
*/
|
|
41
|
+
function isRecfieldDatum(node) {
|
|
42
|
+
return !!node && typeof node === 'object' && 'PLpgSQL_recfield' in node;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Fortified, mutation-aware normalizer built on the shared round-trip core.
|
|
46
|
+
* Beyond the upstream `cleanTree` (position stripping + body trimming), it
|
|
47
|
+
* additionally sorts keys, drops lazily-created recfield datums, and replaces
|
|
48
|
+
* DefElem "as" bodies with a sentinel (PL/pgSQL body fidelity is checked
|
|
49
|
+
* separately via the dehydrated PL/pgSQL ASTs).
|
|
50
|
+
*/
|
|
51
|
+
export function normalizeParseTree(node) {
|
|
52
|
+
return normalizeTree(node, {
|
|
53
|
+
volatileKeys: VOLATILE_KEYS,
|
|
54
|
+
sortKeys: true,
|
|
55
|
+
dropArrayItem: isRecfieldDatum,
|
|
56
|
+
keyHandlers: {
|
|
57
|
+
DefElem: (defElem, recurse) => defElem?.defname === 'as'
|
|
58
|
+
? { ...recurse(defElem), arg: '<body>' }
|
|
59
|
+
: recurse(defElem),
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Capture the normalized SQL parse tree and dehydrated PL/pgSQL function
|
|
65
|
+
* ASTs from a transform context (as produced by plpgsql-parser's
|
|
66
|
+
* transformSync callback). Call this AFTER mutating the context.
|
|
67
|
+
*/
|
|
68
|
+
export function captureTransformAsts(ctx) {
|
|
69
|
+
const plpgsqlAsts = [];
|
|
70
|
+
for (const fn of ctx.functions) {
|
|
71
|
+
if (fn.plpgsql?.hydrated) {
|
|
72
|
+
plpgsqlAsts.push(normalizeParseTree(dehydratePlpgsqlAst(structuredClone(fn.plpgsql.hydrated))));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
sqlAst: normalizeParseTree(ctx.sql),
|
|
77
|
+
plpgsqlAsts,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Parse already-transformed SQL text and capture its ASTs the same way
|
|
82
|
+
* capture_transform_asts does for the pre-deparse context, so the two
|
|
83
|
+
* sides are directly comparable.
|
|
84
|
+
*/
|
|
85
|
+
export function captureAstsFromSql(sql) {
|
|
86
|
+
let captured;
|
|
87
|
+
transformSync(sql, (ctx) => {
|
|
88
|
+
captured = captureTransformAsts(ctx);
|
|
89
|
+
}, { hydrate: true, pretty: true });
|
|
90
|
+
if (!captured) {
|
|
91
|
+
throw new Error('round-trip: failed to capture ASTs from transformed SQL');
|
|
92
|
+
}
|
|
93
|
+
return captured;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Assert that the transformed AST (captured before deparse) matches the AST
|
|
97
|
+
* obtained by re-parsing the emitted SQL. Throws with the first differing
|
|
98
|
+
* path on mismatch.
|
|
99
|
+
*/
|
|
100
|
+
export function validateRoundTrip(before, transformedSql) {
|
|
101
|
+
const after = captureAstsFromSql(transformedSql);
|
|
102
|
+
const sqlDiff = firstDifference(before.sqlAst, after.sqlAst);
|
|
103
|
+
if (sqlDiff) {
|
|
104
|
+
throw new Error(`round-trip validation failed: SQL AST mismatch after deparse at ${sqlDiff}`);
|
|
105
|
+
}
|
|
106
|
+
if (before.plpgsqlAsts.length !== after.plpgsqlAsts.length) {
|
|
107
|
+
throw new Error(`round-trip validation failed: PL/pgSQL function count mismatch ` +
|
|
108
|
+
`(${before.plpgsqlAsts.length} before deparse vs ${after.plpgsqlAsts.length} after re-parse)`);
|
|
109
|
+
}
|
|
110
|
+
for (let i = 0; i < before.plpgsqlAsts.length; i++) {
|
|
111
|
+
const diff = firstDifference(before.plpgsqlAsts[i], after.plpgsqlAsts[i]);
|
|
112
|
+
if (diff) {
|
|
113
|
+
throw new Error(`round-trip validation failed: PL/pgSQL AST mismatch in function #${i} at ${diff}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|