@pgsql/transform 18.6.0 → 18.8.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/esm/facts.js +4 -1
- package/esm/router.js +69 -5
- package/esm/transform.js +106 -194
- package/facts.d.ts +15 -0
- package/facts.js +4 -1
- package/index.d.ts +1 -1
- package/package.json +4 -4
- package/router.d.ts +63 -6
- package/router.js +69 -5
- package/transform.d.ts +4 -22
- package/transform.js +106 -194
package/router.d.ts
CHANGED
|
@@ -20,6 +20,19 @@
|
|
|
20
20
|
* `types` — matching `pg_class` / `pg_proc` / `pg_type`), mirroring the routing
|
|
21
21
|
* model already used by {@link qualifyUnqualified}. Resolution is
|
|
22
22
|
* object-route-first, then the schema-level default, then "leave unchanged".
|
|
23
|
+
*
|
|
24
|
+
* An object route may also *rebind* — change the object's **name**, not just
|
|
25
|
+
* the schema it lives in. Routing preserves identity (the same function, a new
|
|
26
|
+
* address); rebinding repoints a reference at a *different* object, which is
|
|
27
|
+
* what lets one implementation of a contract be substituted for another:
|
|
28
|
+
*
|
|
29
|
+
* ```ts
|
|
30
|
+
* { auth: { functions: { uid: { schema: null, name: 'current_user_id' } } } }
|
|
31
|
+
* // auth.uid() -> current_user_id()
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* A `null` target schema de-qualifies the reference (relying on `search_path`),
|
|
35
|
+
* matching the convention used by the extension router.
|
|
23
36
|
*/
|
|
24
37
|
/** PostgreSQL object namespaces relevant to schema routing. */
|
|
25
38
|
export type ObjectNamespace = 'relation' | 'function' | 'type';
|
|
@@ -30,6 +43,24 @@ export type ObjectNamespace = 'relation' | 'function' | 'type';
|
|
|
30
43
|
* which case only the schema-level default applies.
|
|
31
44
|
*/
|
|
32
45
|
export type RouteNamespace = ObjectNamespace | 'schema' | 'unknown';
|
|
46
|
+
/**
|
|
47
|
+
* Where a specific object should be reached instead. Either field may be
|
|
48
|
+
* omitted: omitting `schema` keeps the schema-level default (or the current
|
|
49
|
+
* schema when the route has none), and omitting `name` keeps the object's own
|
|
50
|
+
* name — so `{ name }` alone is a pure rebind and `{ schema }` alone is
|
|
51
|
+
* equivalent to the shorthand string form.
|
|
52
|
+
*/
|
|
53
|
+
export interface ObjectRoute {
|
|
54
|
+
/** Target schema, or `null` to make the reference unqualified. */
|
|
55
|
+
schema?: string | null;
|
|
56
|
+
/** Target object name — rebinds the reference to a different object. */
|
|
57
|
+
name?: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* An object route target. The shorthand `string` form is the target schema,
|
|
61
|
+
* identical to `{ schema: target }`.
|
|
62
|
+
*/
|
|
63
|
+
export type ObjectRouteTarget = string | ObjectRoute;
|
|
33
64
|
/** Per-source-schema routing: a schema-level default plus per-object routes. */
|
|
34
65
|
export interface SchemaRoute {
|
|
35
66
|
/**
|
|
@@ -38,12 +69,12 @@ export interface SchemaRoute {
|
|
|
38
69
|
* and leave the rest (and the schema itself) untouched.
|
|
39
70
|
*/
|
|
40
71
|
schema?: string;
|
|
41
|
-
/** Relation name (table/view/sequence/matview) → target schema. */
|
|
42
|
-
relations?: Record<string,
|
|
43
|
-
/** Function/procedure/aggregate name → target schema. */
|
|
44
|
-
functions?: Record<string,
|
|
45
|
-
/** Type/domain name → target schema. */
|
|
46
|
-
types?: Record<string,
|
|
72
|
+
/** Relation name (table/view/sequence/matview) → target schema or rebind. */
|
|
73
|
+
relations?: Record<string, ObjectRouteTarget>;
|
|
74
|
+
/** Function/procedure/aggregate name → target schema or rebind. */
|
|
75
|
+
functions?: Record<string, ObjectRouteTarget>;
|
|
76
|
+
/** Type/domain name → target schema or rebind. */
|
|
77
|
+
types?: Record<string, ObjectRouteTarget>;
|
|
47
78
|
}
|
|
48
79
|
/** The full routing specification: one {@link SchemaRoute} per source schema. */
|
|
49
80
|
export type RouteSpec = Record<string, SchemaRoute>;
|
|
@@ -68,6 +99,22 @@ export declare class SchemaRouter {
|
|
|
68
99
|
* bodies; whole-schema routes are handled by the cheaper string passes.
|
|
69
100
|
*/
|
|
70
101
|
hasObjectRoutes(): boolean;
|
|
102
|
+
/**
|
|
103
|
+
* True when any object route changes a name or de-qualifies (rather than
|
|
104
|
+
* only moving between schemas). Such rewrites cannot be expressed by the
|
|
105
|
+
* string-level passes at all, so callers use this to require the AST path.
|
|
106
|
+
*/
|
|
107
|
+
hasNameRebinds(): boolean;
|
|
108
|
+
/**
|
|
109
|
+
* Every object route that rebinds a name or de-qualifies, keyed by source
|
|
110
|
+
* schema and namespace. Callers use this to report or verify substitutions.
|
|
111
|
+
*/
|
|
112
|
+
nameRebinds(): Array<{
|
|
113
|
+
schema: string;
|
|
114
|
+
ns: ObjectNamespace;
|
|
115
|
+
from: string;
|
|
116
|
+
to: ObjectRoute;
|
|
117
|
+
}>;
|
|
71
118
|
/** Every source schema this router may touch. */
|
|
72
119
|
sourceSchemas(): string[];
|
|
73
120
|
/**
|
|
@@ -77,6 +124,16 @@ export declare class SchemaRouter {
|
|
|
77
124
|
* to any object without a specific route.
|
|
78
125
|
*/
|
|
79
126
|
resolve(sourceSchema: string | undefined | null, name?: string, ns?: RouteNamespace): string | undefined;
|
|
127
|
+
/**
|
|
128
|
+
* Resolve the full target for `(sourceSchema, name)` in namespace `ns` — both
|
|
129
|
+
* the schema the reference should live in and, when the route rebinds, the
|
|
130
|
+
* name it should be reached by. Returns `undefined` to leave it unchanged.
|
|
131
|
+
*
|
|
132
|
+
* In the result, `schema` is `null` when the reference should become
|
|
133
|
+
* unqualified and `undefined` when only the name changes; `name` is
|
|
134
|
+
* `undefined` when only the schema changes.
|
|
135
|
+
*/
|
|
136
|
+
resolveObject(sourceSchema: string | undefined | null, name?: string, ns?: RouteNamespace): ObjectRoute | undefined;
|
|
80
137
|
/**
|
|
81
138
|
* Source schemas whose *every* object is guaranteed to move — i.e. those
|
|
82
139
|
* with a schema-level default. After a transform, none of these should
|
package/router.js
CHANGED
|
@@ -21,6 +21,19 @@
|
|
|
21
21
|
* `types` — matching `pg_class` / `pg_proc` / `pg_type`), mirroring the routing
|
|
22
22
|
* model already used by {@link qualifyUnqualified}. Resolution is
|
|
23
23
|
* object-route-first, then the schema-level default, then "leave unchanged".
|
|
24
|
+
*
|
|
25
|
+
* An object route may also *rebind* — change the object's **name**, not just
|
|
26
|
+
* the schema it lives in. Routing preserves identity (the same function, a new
|
|
27
|
+
* address); rebinding repoints a reference at a *different* object, which is
|
|
28
|
+
* what lets one implementation of a contract be substituted for another:
|
|
29
|
+
*
|
|
30
|
+
* ```ts
|
|
31
|
+
* { auth: { functions: { uid: { schema: null, name: 'current_user_id' } } } }
|
|
32
|
+
* // auth.uid() -> current_user_id()
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* A `null` target schema de-qualifies the reference (relying on `search_path`),
|
|
36
|
+
* matching the convention used by the extension router.
|
|
24
37
|
*/
|
|
25
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
39
|
exports.SchemaRouter = void 0;
|
|
@@ -74,6 +87,36 @@ class SchemaRouter {
|
|
|
74
87
|
}
|
|
75
88
|
return false;
|
|
76
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* True when any object route changes a name or de-qualifies (rather than
|
|
92
|
+
* only moving between schemas). Such rewrites cannot be expressed by the
|
|
93
|
+
* string-level passes at all, so callers use this to require the AST path.
|
|
94
|
+
*/
|
|
95
|
+
hasNameRebinds() {
|
|
96
|
+
return this.nameRebinds().length > 0;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Every object route that rebinds a name or de-qualifies, keyed by source
|
|
100
|
+
* schema and namespace. Callers use this to report or verify substitutions.
|
|
101
|
+
*/
|
|
102
|
+
nameRebinds() {
|
|
103
|
+
const out = [];
|
|
104
|
+
for (const [schema, route] of this.routes) {
|
|
105
|
+
for (const ns of ['relation', 'function', 'type']) {
|
|
106
|
+
const bucket = route[NS_BUCKET[ns]];
|
|
107
|
+
if (!bucket)
|
|
108
|
+
continue;
|
|
109
|
+
for (const [from, target] of Object.entries(bucket)) {
|
|
110
|
+
if (typeof target === 'string')
|
|
111
|
+
continue;
|
|
112
|
+
if (target.name === undefined && target.schema !== null)
|
|
113
|
+
continue;
|
|
114
|
+
out.push({ schema, ns, from, to: target });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return out;
|
|
119
|
+
}
|
|
77
120
|
/** Every source schema this router may touch. */
|
|
78
121
|
sourceSchemas() {
|
|
79
122
|
return [...this.routes.keys()];
|
|
@@ -85,18 +128,39 @@ class SchemaRouter {
|
|
|
85
128
|
* to any object without a specific route.
|
|
86
129
|
*/
|
|
87
130
|
resolve(sourceSchema, name, ns = 'unknown') {
|
|
131
|
+
// A `null` target de-qualifies the reference; the schema-only API cannot
|
|
132
|
+
// express that, so it reads as "unchanged" here.
|
|
133
|
+
return this.resolveObject(sourceSchema, name, ns)?.schema ?? undefined;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Resolve the full target for `(sourceSchema, name)` in namespace `ns` — both
|
|
137
|
+
* the schema the reference should live in and, when the route rebinds, the
|
|
138
|
+
* name it should be reached by. Returns `undefined` to leave it unchanged.
|
|
139
|
+
*
|
|
140
|
+
* In the result, `schema` is `null` when the reference should become
|
|
141
|
+
* unqualified and `undefined` when only the name changes; `name` is
|
|
142
|
+
* `undefined` when only the schema changes.
|
|
143
|
+
*/
|
|
144
|
+
resolveObject(sourceSchema, name, ns = 'unknown') {
|
|
88
145
|
if (!sourceSchema)
|
|
89
146
|
return undefined;
|
|
90
147
|
const route = this.routes.get(sourceSchema);
|
|
91
148
|
if (!route)
|
|
92
149
|
return undefined;
|
|
93
150
|
if (name && (ns === 'relation' || ns === 'function' || ns === 'type')) {
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
151
|
+
const target = route[NS_BUCKET[ns]]?.[name];
|
|
152
|
+
if (target !== undefined) {
|
|
153
|
+
if (typeof target === 'string')
|
|
154
|
+
return { schema: target };
|
|
155
|
+
// An object route naming no schema inherits the schema-level default,
|
|
156
|
+
// so a pure rebind leaves placement alone.
|
|
157
|
+
return {
|
|
158
|
+
schema: target.schema !== undefined ? target.schema : route.schema,
|
|
159
|
+
name: target.name
|
|
160
|
+
};
|
|
161
|
+
}
|
|
98
162
|
}
|
|
99
|
-
return route.schema;
|
|
163
|
+
return route.schema !== undefined ? { schema: route.schema } : undefined;
|
|
100
164
|
}
|
|
101
165
|
/**
|
|
102
166
|
* Source schemas whose *every* object is guaranteed to move — i.e. those
|
package/transform.d.ts
CHANGED
|
@@ -110,7 +110,10 @@ export declare function transformNameList(names: any[] | undefined, schemaMappin
|
|
|
110
110
|
export declare function transformSchemaNameField(container: any, field: string, schemaMapping: SchemaMappingInput, result: SchemaTransformResult): void;
|
|
111
111
|
/**
|
|
112
112
|
* Transform a RangeVar-like relation object (has schemaname/relname fields).
|
|
113
|
-
*
|
|
113
|
+
* The walker auto-recurses into embedded relations (concrete `RangeVar`
|
|
114
|
+
* fields are tag-synthesized), so the generic `RangeVar` visitor covers
|
|
115
|
+
* every occurrence; statement handlers call this directly only when they
|
|
116
|
+
* carry extra context, and the claim guard keeps each relation routed once.
|
|
114
117
|
*/
|
|
115
118
|
export declare function transformRelation(relation: any, schemaMapping: SchemaMappingInput, result: SchemaTransformResult): void;
|
|
116
119
|
/**
|
|
@@ -134,34 +137,13 @@ export declare function createSqlVisitor(schemaMapping: SchemaMappingInput, resu
|
|
|
134
137
|
RangeVar: (path: any) => void;
|
|
135
138
|
CreateSchemaStmt: (path: any) => void;
|
|
136
139
|
FuncCall: (path: any) => void;
|
|
137
|
-
CallStmt: (path: any) => void;
|
|
138
140
|
TypeName: (path: any) => void;
|
|
139
141
|
ColumnRef: (path: any) => void;
|
|
140
142
|
GrantStmt: (path: any) => void;
|
|
141
143
|
VariableSetStmt: (path: any) => void;
|
|
142
144
|
AlterDefaultPrivilegesStmt: (path: any) => void;
|
|
143
145
|
DropStmt: (path: any) => void;
|
|
144
|
-
InsertStmt: (path: any) => void;
|
|
145
|
-
CreateStmt: (path: any) => void;
|
|
146
|
-
UpdateStmt: (path: any) => void;
|
|
147
|
-
DeleteStmt: (path: any) => void;
|
|
148
|
-
MergeStmt: (path: any) => void;
|
|
149
|
-
IndexStmt: (path: any) => void;
|
|
150
|
-
Constraint: (path: any) => void;
|
|
151
|
-
CompositeTypeStmt: (path: any) => void;
|
|
152
|
-
ColumnDef: (path: any) => void;
|
|
153
|
-
ViewStmt: (path: any) => void;
|
|
154
|
-
AlterTableStmt: (path: any) => void;
|
|
155
|
-
CreateSeqStmt: (path: any) => void;
|
|
156
146
|
AlterSeqStmt: (path: any) => void;
|
|
157
|
-
CreatePolicyStmt: (path: any) => void;
|
|
158
|
-
RuleStmt: (path: any) => void;
|
|
159
|
-
CopyStmt: (path: any) => void;
|
|
160
|
-
ClusterStmt: (path: any) => void;
|
|
161
|
-
VacuumRelation: (path: any) => void;
|
|
162
|
-
RefreshMatViewStmt: (path: any) => void;
|
|
163
|
-
CreateTableAsStmt: (path: any) => void;
|
|
164
|
-
TypeCast: (path: any) => void;
|
|
165
147
|
CreateFunctionStmt: (path: any) => void;
|
|
166
148
|
CreateTrigStmt: (path: any) => void;
|
|
167
149
|
CommentStmt: (path: any) => void;
|