@quereus/quereus 4.7.0 → 4.9.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/dist/src/common/types.d.ts +19 -0
- package/dist/src/common/types.d.ts.map +1 -1
- package/dist/src/common/types.js.map +1 -1
- package/dist/src/core/database.d.ts +45 -1
- package/dist/src/core/database.d.ts.map +1 -1
- package/dist/src/core/database.js +212 -2
- package/dist/src/core/database.js.map +1 -1
- package/dist/src/core/statement.d.ts.map +1 -1
- package/dist/src/core/statement.js +86 -0
- package/dist/src/core/statement.js.map +1 -1
- package/dist/src/func/builtins/aggregate.d.ts.map +1 -1
- package/dist/src/func/builtins/aggregate.js +3 -2
- package/dist/src/func/builtins/aggregate.js.map +1 -1
- package/dist/src/func/builtins/conversion.d.ts +5 -0
- package/dist/src/func/builtins/conversion.d.ts.map +1 -1
- package/dist/src/func/builtins/conversion.js +16 -2
- package/dist/src/func/builtins/conversion.js.map +1 -1
- package/dist/src/func/builtins/index.d.ts.map +1 -1
- package/dist/src/func/builtins/index.js +5 -2
- package/dist/src/func/builtins/index.js.map +1 -1
- package/dist/src/func/builtins/string.d.ts +2 -0
- package/dist/src/func/builtins/string.d.ts.map +1 -1
- package/dist/src/func/builtins/string.js +60 -4
- package/dist/src/func/builtins/string.js.map +1 -1
- package/dist/src/index.d.ts +11 -4
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +18 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/planner/building/constraint-builder.js +1 -1
- package/dist/src/planner/building/constraint-builder.js.map +1 -1
- package/dist/src/planner/rules/retrieve/rule-grow-retrieve.d.ts.map +1 -1
- package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js +121 -51
- package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js.map +1 -1
- package/dist/src/planner/rules/shared/index-style-context.d.ts +14 -4
- package/dist/src/planner/rules/shared/index-style-context.d.ts.map +1 -1
- package/dist/src/planner/rules/shared/index-style-context.js +14 -4
- package/dist/src/planner/rules/shared/index-style-context.js.map +1 -1
- package/dist/src/runtime/emit/alter-table.d.ts.map +1 -1
- package/dist/src/runtime/emit/alter-table.js +212 -155
- package/dist/src/runtime/emit/alter-table.js.map +1 -1
- package/dist/src/runtime/emit/assertion-drop-guard.d.ts +26 -12
- package/dist/src/runtime/emit/assertion-drop-guard.d.ts.map +1 -1
- package/dist/src/runtime/emit/assertion-drop-guard.js +45 -26
- package/dist/src/runtime/emit/assertion-drop-guard.js.map +1 -1
- package/dist/src/runtime/emit/assertion-rename-helpers.d.ts +6 -6
- package/dist/src/runtime/emit/assertion-rename-helpers.d.ts.map +1 -1
- package/dist/src/runtime/emit/assertion-rename-helpers.js +18 -20
- package/dist/src/runtime/emit/assertion-rename-helpers.js.map +1 -1
- package/dist/src/runtime/emit/binary.d.ts.map +1 -1
- package/dist/src/runtime/emit/binary.js +12 -10
- package/dist/src/runtime/emit/binary.js.map +1 -1
- package/dist/src/runtime/emit/column-rename-cascade.d.ts +84 -0
- package/dist/src/runtime/emit/column-rename-cascade.d.ts.map +1 -0
- package/dist/src/runtime/emit/column-rename-cascade.js +134 -0
- package/dist/src/runtime/emit/column-rename-cascade.js.map +1 -0
- package/dist/src/runtime/emit/drop-column-guards.d.ts +82 -53
- package/dist/src/runtime/emit/drop-column-guards.d.ts.map +1 -1
- package/dist/src/runtime/emit/drop-column-guards.js +155 -90
- package/dist/src/runtime/emit/drop-column-guards.js.map +1 -1
- package/dist/src/runtime/emit/drop-table.d.ts.map +1 -1
- package/dist/src/runtime/emit/drop-table.js +5 -0
- package/dist/src/runtime/emit/drop-table.js.map +1 -1
- package/dist/src/runtime/emit/drop-view.d.ts.map +1 -1
- package/dist/src/runtime/emit/drop-view.js +5 -0
- package/dist/src/runtime/emit/drop-view.js.map +1 -1
- package/dist/src/runtime/emit/expression-drop-guard.d.ts +57 -0
- package/dist/src/runtime/emit/expression-drop-guard.d.ts.map +1 -0
- package/dist/src/runtime/emit/expression-drop-guard.js +82 -0
- package/dist/src/runtime/emit/expression-drop-guard.js.map +1 -0
- package/dist/src/runtime/emit/materialized-view-helpers.d.ts +26 -9
- package/dist/src/runtime/emit/materialized-view-helpers.d.ts.map +1 -1
- package/dist/src/runtime/emit/materialized-view-helpers.js +37 -17
- package/dist/src/runtime/emit/materialized-view-helpers.js.map +1 -1
- package/dist/src/runtime/emit/materialized-view.d.ts.map +1 -1
- package/dist/src/runtime/emit/materialized-view.js +3 -0
- package/dist/src/runtime/emit/materialized-view.js.map +1 -1
- package/dist/src/runtime/emit/remote-query.d.ts.map +1 -1
- package/dist/src/runtime/emit/remote-query.js +8 -3
- package/dist/src/runtime/emit/remote-query.js.map +1 -1
- package/dist/src/runtime/emit/scan.d.ts.map +1 -1
- package/dist/src/runtime/emit/scan.js +4 -1
- package/dist/src/runtime/emit/scan.js.map +1 -1
- package/dist/src/runtime/emit/schema-declarative.js +2 -2
- package/dist/src/runtime/emit/schema-declarative.js.map +1 -1
- package/dist/src/runtime/parallel-driver.d.ts +4 -3
- package/dist/src/runtime/parallel-driver.d.ts.map +1 -1
- package/dist/src/runtime/parallel-driver.js +8 -3
- package/dist/src/runtime/parallel-driver.js.map +1 -1
- package/dist/src/runtime/types.d.ts +10 -0
- package/dist/src/runtime/types.d.ts.map +1 -1
- package/dist/src/runtime/types.js.map +1 -1
- package/dist/src/runtime/utils.d.ts.map +1 -1
- package/dist/src/runtime/utils.js +11 -0
- package/dist/src/runtime/utils.js.map +1 -1
- package/dist/src/schema/assertion.d.ts +58 -0
- package/dist/src/schema/assertion.d.ts.map +1 -1
- package/dist/src/schema/assertion.js +78 -0
- package/dist/src/schema/assertion.js.map +1 -1
- package/dist/src/schema/catalog-persistability.d.ts +11 -3
- package/dist/src/schema/catalog-persistability.d.ts.map +1 -1
- package/dist/src/schema/catalog-persistability.js +48 -29
- package/dist/src/schema/catalog-persistability.js.map +1 -1
- package/dist/src/schema/catalog.d.ts +22 -0
- package/dist/src/schema/catalog.d.ts.map +1 -1
- package/dist/src/schema/catalog.js +4 -1
- package/dist/src/schema/catalog.js.map +1 -1
- package/dist/src/schema/column-republication.d.ts +126 -0
- package/dist/src/schema/column-republication.d.ts.map +1 -0
- package/dist/src/schema/column-republication.js +121 -0
- package/dist/src/schema/column-republication.js.map +1 -0
- package/dist/src/schema/column-source-resolver.d.ts +29 -6
- package/dist/src/schema/column-source-resolver.d.ts.map +1 -1
- package/dist/src/schema/column-source-resolver.js +78 -9
- package/dist/src/schema/column-source-resolver.js.map +1 -1
- package/dist/src/schema/expression-dependents.d.ts +160 -0
- package/dist/src/schema/expression-dependents.d.ts.map +1 -0
- package/dist/src/schema/expression-dependents.js +228 -0
- package/dist/src/schema/expression-dependents.js.map +1 -0
- package/dist/src/schema/object-dependency-closure.d.ts +127 -0
- package/dist/src/schema/object-dependency-closure.d.ts.map +1 -0
- package/dist/src/schema/object-dependency-closure.js +117 -0
- package/dist/src/schema/object-dependency-closure.js.map +1 -0
- package/dist/src/schema/object-ref-resolver.d.ts +83 -0
- package/dist/src/schema/object-ref-resolver.d.ts.map +1 -0
- package/dist/src/schema/object-ref-resolver.js +135 -0
- package/dist/src/schema/object-ref-resolver.js.map +1 -0
- package/dist/src/schema/rename/column-rename.d.ts +228 -0
- package/dist/src/schema/rename/column-rename.d.ts.map +1 -0
- package/dist/src/schema/rename/column-rename.js +1225 -0
- package/dist/src/schema/rename/column-rename.js.map +1 -0
- package/dist/src/schema/rename/self-qualifier-strip.d.ts +29 -0
- package/dist/src/schema/rename/self-qualifier-strip.d.ts.map +1 -0
- package/dist/src/schema/rename/self-qualifier-strip.js +267 -0
- package/dist/src/schema/rename/self-qualifier-strip.js.map +1 -0
- package/dist/src/schema/rename/shared.d.ts +108 -0
- package/dist/src/schema/rename/shared.d.ts.map +1 -0
- package/dist/src/schema/rename/shared.js +49 -0
- package/dist/src/schema/rename/shared.js.map +1 -0
- package/dist/src/schema/rename/table-rename.d.ts +263 -0
- package/dist/src/schema/rename/table-rename.d.ts.map +1 -0
- package/dist/src/schema/rename/table-rename.js +860 -0
- package/dist/src/schema/rename/table-rename.js.map +1 -0
- package/dist/src/schema/rename-rewriter.d.ts +18 -278
- package/dist/src/schema/rename-rewriter.d.ts.map +1 -1
- package/dist/src/schema/rename-rewriter.js +17 -1506
- package/dist/src/schema/rename-rewriter.js.map +1 -1
- package/dist/src/schema/schema-differ.d.ts.map +1 -1
- package/dist/src/schema/schema-differ.js +228 -21
- package/dist/src/schema/schema-differ.js.map +1 -1
- package/dist/src/types/builtin-types.d.ts.map +1 -1
- package/dist/src/types/builtin-types.js +12 -28
- package/dist/src/types/builtin-types.js.map +1 -1
- package/dist/src/types/cast-semantics.d.ts +7 -5
- package/dist/src/types/cast-semantics.d.ts.map +1 -1
- package/dist/src/types/cast-semantics.js +20 -9
- package/dist/src/types/cast-semantics.js.map +1 -1
- package/dist/src/types/index.d.ts +1 -1
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/types/index.js +1 -1
- package/dist/src/types/index.js.map +1 -1
- package/dist/src/types/registry.d.ts.map +1 -1
- package/dist/src/types/registry.js +2 -1
- package/dist/src/types/registry.js.map +1 -1
- package/dist/src/types/temporal-types.d.ts +11 -0
- package/dist/src/types/temporal-types.d.ts.map +1 -1
- package/dist/src/types/temporal-types.js +82 -0
- package/dist/src/types/temporal-types.js.map +1 -1
- package/dist/src/util/abort-signal.d.ts +25 -0
- package/dist/src/util/abort-signal.d.ts.map +1 -0
- package/dist/src/util/abort-signal.js +40 -0
- package/dist/src/util/abort-signal.js.map +1 -0
- package/dist/src/util/affinity.d.ts +2 -1
- package/dist/src/util/affinity.d.ts.map +1 -1
- package/dist/src/util/affinity.js +16 -5
- package/dist/src/util/affinity.js.map +1 -1
- package/dist/src/util/ast-spine-clone.d.ts +2 -2
- package/dist/src/util/ast-spine-clone.js +2 -2
- package/dist/src/util/value-text.d.ts +48 -0
- package/dist/src/util/value-text.d.ts.map +1 -0
- package/dist/src/util/value-text.js +35 -0
- package/dist/src/util/value-text.js.map +1 -0
- package/dist/src/vtab/concurrency.d.ts +15 -0
- package/dist/src/vtab/concurrency.d.ts.map +1 -1
- package/dist/src/vtab/concurrency.js +17 -0
- package/dist/src/vtab/concurrency.js.map +1 -1
- package/dist/src/vtab/memory/layer/base.d.ts +10 -0
- package/dist/src/vtab/memory/layer/base.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/base.js +10 -0
- package/dist/src/vtab/memory/layer/base.js.map +1 -1
- package/dist/src/vtab/memory/layer/interface.d.ts +24 -0
- package/dist/src/vtab/memory/layer/interface.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/manager.d.ts +21 -3
- package/dist/src/vtab/memory/layer/manager.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/manager.js +118 -93
- package/dist/src/vtab/memory/layer/manager.js.map +1 -1
- package/dist/src/vtab/memory/layer/transaction.d.ts +11 -0
- package/dist/src/vtab/memory/layer/transaction.d.ts.map +1 -1
- package/dist/src/vtab/memory/layer/transaction.js +19 -0
- package/dist/src/vtab/memory/layer/transaction.js.map +1 -1
- package/dist/src/vtab/memory/module.d.ts +41 -0
- package/dist/src/vtab/memory/module.d.ts.map +1 -1
- package/dist/src/vtab/memory/module.js +41 -0
- package/dist/src/vtab/memory/module.js.map +1 -1
- package/dist/src/vtab/memory/table.d.ts +12 -1
- package/dist/src/vtab/memory/table.d.ts.map +1 -1
- package/dist/src/vtab/memory/table.js +12 -1
- package/dist/src/vtab/memory/table.js.map +1 -1
- package/dist/src/vtab/module.d.ts +33 -0
- package/dist/src/vtab/module.d.ts.map +1 -1
- package/dist/src/vtab/test-support/commit-stall.d.ts +53 -0
- package/dist/src/vtab/test-support/commit-stall.d.ts.map +1 -0
- package/dist/src/vtab/test-support/commit-stall.js +73 -0
- package/dist/src/vtab/test-support/commit-stall.js.map +1 -0
- package/dist/src/vtab/test-support/committed-read-conformance.d.ts +96 -0
- package/dist/src/vtab/test-support/committed-read-conformance.d.ts.map +1 -0
- package/dist/src/vtab/test-support/committed-read-conformance.js +364 -0
- package/dist/src/vtab/test-support/committed-read-conformance.js.map +1 -0
- package/package.json +3 -3
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import type * as AST from '../parser/ast.js';
|
|
2
|
+
import type { Database } from '../core/database.js';
|
|
3
|
+
import { type ResolveObjectRef, type TableRenameOpts } from './rename-rewriter.js';
|
|
4
|
+
import type { ObjectRefResolvers } from './object-ref-resolver.js';
|
|
5
|
+
/**
|
|
6
|
+
* The catalog query "can this stored body REACH that object?", as opposed to the
|
|
7
|
+
* one-hop "does this stored body NAME that object?" the rename walkers answer.
|
|
8
|
+
*
|
|
9
|
+
* A DROP guard that only asks the one-hop question is defeated by a view: an
|
|
10
|
+
* assertion body reading `v` where `create view v as select * from t` names `t`
|
|
11
|
+
* nowhere, so `drop table t` is accepted and every later write to the whole
|
|
12
|
+
* database fails on an assertion whose text does not mention `t`. Reach is the
|
|
13
|
+
* closure over STORED bodies — an assertion body names views and materialized
|
|
14
|
+
* views, whose bodies name further views and base tables — and this module is
|
|
15
|
+
* the one place that closure is computed, so the guard families that consume it
|
|
16
|
+
* cannot end up disagreeing about what "reaches" means.
|
|
17
|
+
*
|
|
18
|
+
* Each body is walked under ITS OWN home-schema resolver, so an unqualified
|
|
19
|
+
* name in a view body means what the planner would make of it *in that body*,
|
|
20
|
+
* not what it would mean in the root body. That is the whole reason
|
|
21
|
+
* {@link ObjectRefResolvers} is a per-home-schema factory over one snapshot.
|
|
22
|
+
*
|
|
23
|
+
* Scope-awareness survives the widening because the walk is
|
|
24
|
+
* {@link collectTableRefsInAst}, the third sink over the very traversal the
|
|
25
|
+
* rename uses: a body whose `with t as (…)` merely shadows the name still
|
|
26
|
+
* contributes no reference, so the closure cannot false-refuse where the direct
|
|
27
|
+
* probe already does not.
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* One stored body the closure walked, and how the root got to it.
|
|
31
|
+
*
|
|
32
|
+
* The root body itself is a `ReachedBody` with an empty {@link path} and no
|
|
33
|
+
* {@link ownerKey} — it is an assertion's CHECK, or a table's CHECK / DEFAULT /
|
|
34
|
+
* generated expression, none of which is a catalog object with a key of its own.
|
|
35
|
+
*/
|
|
36
|
+
export interface ReachedBody {
|
|
37
|
+
/**
|
|
38
|
+
* Canonical `<schema>.<name>` key of the view / materialized view owning this
|
|
39
|
+
* body, or `undefined` for the ROOT body the closure started from.
|
|
40
|
+
*/
|
|
41
|
+
ownerKey: string | undefined;
|
|
42
|
+
/**
|
|
43
|
+
* The stored bodies traversed from the root to this one INCLUSIVE, root-first,
|
|
44
|
+
* each described for an error message: `view 'v'`, `materialized view 'm'`.
|
|
45
|
+
* Empty for the root body itself, which is what tells a caller its match is
|
|
46
|
+
* direct and needs no "reaches it through …" clause.
|
|
47
|
+
*/
|
|
48
|
+
path: ReadonlyArray<string>;
|
|
49
|
+
/** The AST to walk — an assertion/CHECK expression at the root, a view body below it. */
|
|
50
|
+
body: AST.AstNode;
|
|
51
|
+
/** Planner-parity resolver for THIS body's home schema. */
|
|
52
|
+
resolve: ResolveObjectRef;
|
|
53
|
+
}
|
|
54
|
+
/** What {@link reachableObjects} returns: the walked bodies, and who named what. */
|
|
55
|
+
export interface ObjectReach {
|
|
56
|
+
/**
|
|
57
|
+
* The root body followed by every stored body reached from it, breadth-first.
|
|
58
|
+
* A caller asking a question the closure does not answer itself — "does any
|
|
59
|
+
* body in the reach name `t.x`?" — probes these in order.
|
|
60
|
+
*/
|
|
61
|
+
readonly bodies: ReadonlyArray<ReachedBody>;
|
|
62
|
+
/**
|
|
63
|
+
* The body that NAMES `key`, or `undefined` when nothing in the reach does.
|
|
64
|
+
* Breadth-first, so the answer is the shortest chain from the root and its
|
|
65
|
+
* {@link ReachedBody.path} is the shortest path to quote in an error.
|
|
66
|
+
*
|
|
67
|
+
* NOTE: two chains of EQUAL length to the same object tie on queue order,
|
|
68
|
+
* i.e. the order the parent bodies happened to name their children. Harmless
|
|
69
|
+
* while the path is advisory — either chain is a true one, and dropping the
|
|
70
|
+
* rule is the escape hatch for both — but a caller that ever needs a
|
|
71
|
+
* deterministic chain (a stable error-message fixture, say) has to order the
|
|
72
|
+
* candidates itself.
|
|
73
|
+
*/
|
|
74
|
+
namerOf(key: string): ReachedBody | undefined;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Every object reachable from `root` through stored view / materialized-view
|
|
78
|
+
* bodies, plus the bodies traversed to get there.
|
|
79
|
+
*
|
|
80
|
+
* `homeSchemaName` is the root body's OWN schema — the assertion's schema, or
|
|
81
|
+
* the schema of the table carrying the CHECK / DEFAULT — because that is what
|
|
82
|
+
* the root's unqualified names resolve against.
|
|
83
|
+
*
|
|
84
|
+
* `resolvers` is REQUIRED rather than built here, and the reason is snapshot
|
|
85
|
+
* discipline (see {@link import('./object-ref-resolver.js').snapshotObjectRefResolvers}):
|
|
86
|
+
* a caller looping over many roots must share ONE pre-mutation snapshot, and a
|
|
87
|
+
* default would silently give each root its own.
|
|
88
|
+
*
|
|
89
|
+
* Termination is a visited set of object keys, so a mutually-referencing or
|
|
90
|
+
* otherwise malformed catalog is walked once per object rather than forever. A
|
|
91
|
+
* body naming an object that does not exist is not an error: the resolver's
|
|
92
|
+
* miss→home fallback keys it stably and the expansion below simply finds
|
|
93
|
+
* nothing to expand.
|
|
94
|
+
*
|
|
95
|
+
* `rootOpts` applies to the ROOT body's collection ONLY, never to a body
|
|
96
|
+
* reached below it. Every reached body is a view / materialized-view body — a
|
|
97
|
+
* relation, with no written-row context — so
|
|
98
|
+
* {@link import('./rename/table-rename.js').TableRenameOpts.rowImageContext}
|
|
99
|
+
* would be wrong there. It is REQUIRED at a root that is a table's CHECK
|
|
100
|
+
* constraint or column DEFAULT / generated body, where a bare `new.a` names the
|
|
101
|
+
* row image: rooted there without the flag, a table literally called `new`
|
|
102
|
+
* would land in the reach and false-refuse its own drop
|
|
103
|
+
* (`schema/expression-dependents.ts` passes it for exactly that reason). The
|
|
104
|
+
* assertion guards pass nothing: an assertion CHECK owns no `new.` / `old.`
|
|
105
|
+
* namespace either.
|
|
106
|
+
*
|
|
107
|
+
* Root-only stays correct even though a reached body CAN carry a bare unbound
|
|
108
|
+
* `new.` qualifier — a `with inverse` / `with defaults` expression holds one
|
|
109
|
+
* legitimately (`CREATE VIEW` accepts it there; the refs name the enclosing
|
|
110
|
+
* select's output row) — because the walker suppresses those SUBTREES itself,
|
|
111
|
+
* unconditionally, wherever the walk entered (`rename/table-rename.ts`,
|
|
112
|
+
* `visitRowImageSubtree`). The suppression travels with the position, not with
|
|
113
|
+
* this flag, so a reached view body self-suppresses and leaking `rootOpts`
|
|
114
|
+
* downward would change no answer. Pinned by
|
|
115
|
+
* `test/logic/41.10.4-drop-object-expression-dependents.sqllogic` (drop of a
|
|
116
|
+
* table named `new` reached through a `with inverse` view).
|
|
117
|
+
*/
|
|
118
|
+
export declare function reachableObjects(db: Database, root: AST.AstNode, homeSchemaName: string, resolvers: ObjectRefResolvers, rootOpts?: TableRenameOpts): ObjectReach;
|
|
119
|
+
/**
|
|
120
|
+
* The `reaches it through view 'v2' -> view 'v1'` clause for a
|
|
121
|
+
* {@link ReachedBody.path}, or the empty string when the match is direct.
|
|
122
|
+
* Shared so every guard consuming the closure phrases an indirect refusal the
|
|
123
|
+
* same way — a user told to fix a rule whose body does not mention the dropped
|
|
124
|
+
* object needs the chain, or the message is unactionable.
|
|
125
|
+
*/
|
|
126
|
+
export declare function describeReachPath(path: ReadonlyArray<string>): string;
|
|
127
|
+
//# sourceMappingURL=object-dependency-closure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"object-dependency-closure.d.ts","sourceRoot":"","sources":["../../../src/schema/object-dependency-closure.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,GAAG,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAA6C,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC9H,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAGnE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC3B;;;OAGG;IACH,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B;;;;;OAKG;IACH,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC5B,yFAAyF;IACzF,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC;IAClB,2DAA2D;IAC3D,OAAO,EAAE,gBAAgB,CAAC;CAC1B;AAED,oFAAoF;AACpF,MAAM,WAAW,WAAW;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;IAC5C;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAAC;CAC9C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,wBAAgB,gBAAgB,CAC/B,EAAE,EAAE,QAAQ,EACZ,IAAI,EAAE,GAAG,CAAC,OAAO,EACjB,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,kBAAkB,EAC7B,QAAQ,CAAC,EAAE,eAAe,GACxB,WAAW,CA+Bb;AAgDD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,MAAM,CAErE"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { collectTableRefsInAst, objectRefKeySchema } from './rename-rewriter.js';
|
|
2
|
+
import { isMaintainedTable } from './derivation.js';
|
|
3
|
+
/**
|
|
4
|
+
* Every object reachable from `root` through stored view / materialized-view
|
|
5
|
+
* bodies, plus the bodies traversed to get there.
|
|
6
|
+
*
|
|
7
|
+
* `homeSchemaName` is the root body's OWN schema — the assertion's schema, or
|
|
8
|
+
* the schema of the table carrying the CHECK / DEFAULT — because that is what
|
|
9
|
+
* the root's unqualified names resolve against.
|
|
10
|
+
*
|
|
11
|
+
* `resolvers` is REQUIRED rather than built here, and the reason is snapshot
|
|
12
|
+
* discipline (see {@link import('./object-ref-resolver.js').snapshotObjectRefResolvers}):
|
|
13
|
+
* a caller looping over many roots must share ONE pre-mutation snapshot, and a
|
|
14
|
+
* default would silently give each root its own.
|
|
15
|
+
*
|
|
16
|
+
* Termination is a visited set of object keys, so a mutually-referencing or
|
|
17
|
+
* otherwise malformed catalog is walked once per object rather than forever. A
|
|
18
|
+
* body naming an object that does not exist is not an error: the resolver's
|
|
19
|
+
* miss→home fallback keys it stably and the expansion below simply finds
|
|
20
|
+
* nothing to expand.
|
|
21
|
+
*
|
|
22
|
+
* `rootOpts` applies to the ROOT body's collection ONLY, never to a body
|
|
23
|
+
* reached below it. Every reached body is a view / materialized-view body — a
|
|
24
|
+
* relation, with no written-row context — so
|
|
25
|
+
* {@link import('./rename/table-rename.js').TableRenameOpts.rowImageContext}
|
|
26
|
+
* would be wrong there. It is REQUIRED at a root that is a table's CHECK
|
|
27
|
+
* constraint or column DEFAULT / generated body, where a bare `new.a` names the
|
|
28
|
+
* row image: rooted there without the flag, a table literally called `new`
|
|
29
|
+
* would land in the reach and false-refuse its own drop
|
|
30
|
+
* (`schema/expression-dependents.ts` passes it for exactly that reason). The
|
|
31
|
+
* assertion guards pass nothing: an assertion CHECK owns no `new.` / `old.`
|
|
32
|
+
* namespace either.
|
|
33
|
+
*
|
|
34
|
+
* Root-only stays correct even though a reached body CAN carry a bare unbound
|
|
35
|
+
* `new.` qualifier — a `with inverse` / `with defaults` expression holds one
|
|
36
|
+
* legitimately (`CREATE VIEW` accepts it there; the refs name the enclosing
|
|
37
|
+
* select's output row) — because the walker suppresses those SUBTREES itself,
|
|
38
|
+
* unconditionally, wherever the walk entered (`rename/table-rename.ts`,
|
|
39
|
+
* `visitRowImageSubtree`). The suppression travels with the position, not with
|
|
40
|
+
* this flag, so a reached view body self-suppresses and leaking `rootOpts`
|
|
41
|
+
* downward would change no answer. Pinned by
|
|
42
|
+
* `test/logic/41.10.4-drop-object-expression-dependents.sqllogic` (drop of a
|
|
43
|
+
* table named `new` reached through a `with inverse` view).
|
|
44
|
+
*/
|
|
45
|
+
export function reachableObjects(db, root, homeSchemaName, resolvers, rootOpts) {
|
|
46
|
+
const bodies = [];
|
|
47
|
+
const namer = new Map();
|
|
48
|
+
/** Object keys already expanded (or found not to be a stored body). */
|
|
49
|
+
const visited = new Set();
|
|
50
|
+
const queue = [{
|
|
51
|
+
ownerKey: undefined,
|
|
52
|
+
path: [],
|
|
53
|
+
body: root,
|
|
54
|
+
resolve: resolvers.forHomeSchema(homeSchemaName),
|
|
55
|
+
}];
|
|
56
|
+
// Breadth-first: `namer` and `path` then carry the SHORTEST chain to each
|
|
57
|
+
// object, which is the one an error message should quote.
|
|
58
|
+
for (let head = 0; head < queue.length; head++) {
|
|
59
|
+
const current = queue[head];
|
|
60
|
+
bodies.push(current);
|
|
61
|
+
// `ownerKey === undefined` identifies the ROOT uniquely — every body reached
|
|
62
|
+
// below it gets one from `childBody`.
|
|
63
|
+
const opts = current.ownerKey === undefined ? rootOpts : undefined;
|
|
64
|
+
for (const [key, nameLower] of collectTableRefsInAst(current.body, current.resolve, opts)) {
|
|
65
|
+
if (!namer.has(key))
|
|
66
|
+
namer.set(key, current);
|
|
67
|
+
if (visited.has(key))
|
|
68
|
+
continue;
|
|
69
|
+
visited.add(key);
|
|
70
|
+
const child = expandStoredBody(db, key, nameLower, resolvers, current);
|
|
71
|
+
if (child)
|
|
72
|
+
queue.push(child);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return { bodies, namerOf: key => namer.get(key) };
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The stored body of the object `key` names, as a child of `parent` — or
|
|
79
|
+
* `undefined` when the key names something with no body to follow: a base table,
|
|
80
|
+
* or nothing at all.
|
|
81
|
+
*
|
|
82
|
+
* A materialized view is looked up as a TABLE (one `TableSchema`, one catalog
|
|
83
|
+
* name) and its body hangs off `derivation.selectAst`; see `schema/derivation.ts`.
|
|
84
|
+
*/
|
|
85
|
+
function expandStoredBody(db, key, nameLower, resolvers, parent) {
|
|
86
|
+
const schema = db.schemaManager.getSchema(objectRefKeySchema(key, nameLower));
|
|
87
|
+
if (!schema)
|
|
88
|
+
return undefined;
|
|
89
|
+
const view = schema.getView(nameLower);
|
|
90
|
+
if (view)
|
|
91
|
+
return childBody(key, `view '${view.name}'`, view.selectAst, view.schemaName, resolvers, parent);
|
|
92
|
+
const table = schema.getTable(nameLower);
|
|
93
|
+
if (isMaintainedTable(table)) {
|
|
94
|
+
return childBody(key, `materialized view '${table.name}'`, table.derivation.selectAst, table.schemaName, resolvers, parent);
|
|
95
|
+
}
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
/** A reached stored body, with the parent's path extended by its own description. */
|
|
99
|
+
function childBody(ownerKey, describe, body, ownerSchemaName, resolvers, parent) {
|
|
100
|
+
return {
|
|
101
|
+
ownerKey,
|
|
102
|
+
path: [...parent.path, describe],
|
|
103
|
+
body,
|
|
104
|
+
resolve: resolvers.forHomeSchema(ownerSchemaName),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* The `reaches it through view 'v2' -> view 'v1'` clause for a
|
|
109
|
+
* {@link ReachedBody.path}, or the empty string when the match is direct.
|
|
110
|
+
* Shared so every guard consuming the closure phrases an indirect refusal the
|
|
111
|
+
* same way — a user told to fix a rule whose body does not mention the dropped
|
|
112
|
+
* object needs the chain, or the message is unactionable.
|
|
113
|
+
*/
|
|
114
|
+
export function describeReachPath(path) {
|
|
115
|
+
return path.length === 0 ? '' : ` through ${path.join(' -> ')}`;
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=object-dependency-closure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"object-dependency-closure.js","sourceRoot":"","sources":["../../../src/schema/object-dependency-closure.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { Database } from '../core/database.js';
|
|
2
|
+
import { type ResolveObjectRef, type TableRenameTarget } from './rename-rewriter.js';
|
|
3
|
+
/**
|
|
4
|
+
* Per-home-schema {@link ResolveObjectRef} factory over ONE catalog snapshot.
|
|
5
|
+
* The rename propagation walks dependents living in many schemas, and each
|
|
6
|
+
* dependent's unqualified names resolve under ITS OWN home schema path — so
|
|
7
|
+
* one statement needs one snapshot and many resolvers derived from it.
|
|
8
|
+
*/
|
|
9
|
+
export interface ObjectRefResolvers {
|
|
10
|
+
/** Resolver for a stored body owned by `homeSchemaName`. Cached per home schema. */
|
|
11
|
+
forHomeSchema(homeSchemaName: string): ResolveObjectRef;
|
|
12
|
+
/**
|
|
13
|
+
* A sibling snapshot with one table rename applied — the catalog as it will
|
|
14
|
+
* look AFTER the statement. Used only to check the rename post-condition
|
|
15
|
+
* ({@link import('./rename/table-rename.js').renameTableInAst}: a rewritten
|
|
16
|
+
* reference must still resolve to the renamed object). Derived from this
|
|
17
|
+
* snapshot's name sets, never the live catalog, so the SNAPSHOT DISCIPLINE
|
|
18
|
+
* below holds for both.
|
|
19
|
+
*/
|
|
20
|
+
withTableRenamed(schemaName: string, oldName: string, newName: string): ObjectRefResolvers;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The catalog-backed {@link ResolveObjectRef} the rename walkers consult to decide
|
|
24
|
+
* whether a table/view reference written in a stored body denotes the object being
|
|
25
|
+
* renamed / probed. It answers the way the PLANNER answers for that body — against
|
|
26
|
+
* the owning object's home schema path ({@link Database._homeSchemaPath}:
|
|
27
|
+
* `[homeSchema, ...session default path]`) — not against a single "default schema".
|
|
28
|
+
*
|
|
29
|
+
* Resolution rules:
|
|
30
|
+
* - **Qualified** (`schema` present) → `objectRefKey(schema, name)`, no catalog
|
|
31
|
+
* lookup. A qualified name means what it says even when the object does not
|
|
32
|
+
* exist (it may be the one about to be created, or the one just renamed away).
|
|
33
|
+
* - **Unqualified** → the first schema in the home path holding a table or view
|
|
34
|
+
* (a materialized view is a table) of that name.
|
|
35
|
+
* - **Miss in every schema** → the home schema's key, so a body naming an object
|
|
36
|
+
* that does not exist still gets a stable key rather than `undefined` —
|
|
37
|
+
* `undefined` is reserved for "no resolver could be consulted at all".
|
|
38
|
+
*
|
|
39
|
+
* NOTE: "the way the planner answers" is exact for the body kinds that plan under
|
|
40
|
+
* {@link Database._homeSchemaPath} — view bodies, materialized-view bodies, and
|
|
41
|
+
* assertion checks (`planner/stored-body-context.ts`). A CHECK constraint or a
|
|
42
|
+
* column DEFAULT / generated expression is stricter still: it plans under
|
|
43
|
+
* `schemaAuthoredContext` (`planner/building/schema-authored-context.ts`), the
|
|
44
|
+
* owning schema and NOTHING else, so an unqualified name the owning schema does
|
|
45
|
+
* not hold is an error there rather than a fallthrough down the session path.
|
|
46
|
+
* This resolver applies the looser home-path rule to all of them, which is
|
|
47
|
+
* deliberately safe rather than exact: the two rules can only disagree when the
|
|
48
|
+
* home schema lacks the name, and such a CHECK / DEFAULT cannot be evaluated at
|
|
49
|
+
* all — so no VALID body is ever matched (or missed) differently. Tighten to a
|
|
50
|
+
* per-body-kind path only if a rename ever needs to be right about a body the
|
|
51
|
+
* planner itself rejects.
|
|
52
|
+
*
|
|
53
|
+
* SNAPSHOT DISCIPLINE — the single most likely way to get this wrong: build the
|
|
54
|
+
* snapshot (`snapshotObjectRefResolvers` / `buildObjectRefResolver`) BEFORE the
|
|
55
|
+
* statement's first catalog mutation, and pass the same instance through the whole
|
|
56
|
+
* statement. Name-set lookups answer from the snapshot, NOT the live catalog, and
|
|
57
|
+
* that is load-bearing: rename propagation runs after the catalog swap, when the
|
|
58
|
+
* old name is gone — a live lookup of a bare `t` under `[main, temp]` after
|
|
59
|
+
* `main.t` was renamed would fall through to `temp.t` and silently match (or miss)
|
|
60
|
+
* the wrong object. The pre-mutation snapshot resolves every reference the way the
|
|
61
|
+
* body planned before the statement started, which is the question the rename is
|
|
62
|
+
* asking. (The session `schema_path` option is read at resolver-derivation time;
|
|
63
|
+
* it cannot change mid-statement.)
|
|
64
|
+
*/
|
|
65
|
+
export declare function snapshotObjectRefResolvers(db: Database): ObjectRefResolvers;
|
|
66
|
+
/**
|
|
67
|
+
* Per-home-schema {@link TableRenameTarget} factory for one `ALTER TABLE … RENAME TO`
|
|
68
|
+
* statement: binds the renamed object's identity to a pre-mutation `resolve` and a
|
|
69
|
+
* post-rename `resolveAfter` (the {@link ObjectRefResolvers.withTableRenamed} sibling),
|
|
70
|
+
* both derived per body-owning home schema. One statement builds this once and hands
|
|
71
|
+
* every walk the target for the walked body's owner, which is what lets the rewrite
|
|
72
|
+
* enforce its post-condition — a rewritten reference must still resolve to the renamed
|
|
73
|
+
* object — at the sink.
|
|
74
|
+
*/
|
|
75
|
+
export declare function tableRenameTargetsFor(resolvers: ObjectRefResolvers, schemaName: string, oldName: string, newName: string): (homeSchemaName: string) => TableRenameTarget;
|
|
76
|
+
/**
|
|
77
|
+
* Single-home convenience over {@link snapshotObjectRefResolvers}, for callers
|
|
78
|
+
* that walk bodies of one owning schema only (the DROP guards, a store module's
|
|
79
|
+
* own-table rewrite). Same snapshot discipline: build before the statement's
|
|
80
|
+
* first catalog mutation.
|
|
81
|
+
*/
|
|
82
|
+
export declare function buildObjectRefResolver(db: Database, homeSchemaName: string): ResolveObjectRef;
|
|
83
|
+
//# sourceMappingURL=object-ref-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"object-ref-resolver.d.ts","sourceRoot":"","sources":["../../../src/schema/object-ref-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAgB,KAAK,gBAAgB,EAAE,KAAK,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEnG;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IAClC,oFAAoF;IACpF,aAAa,CAAC,cAAc,EAAE,MAAM,GAAG,gBAAgB,CAAC;IACxD;;;;;;;OAOG;IACH,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,kBAAkB,CAAC;CAC3F;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,wBAAgB,0BAA0B,CAAC,EAAE,EAAE,QAAQ,GAAG,kBAAkB,CAa3E;AAqCD;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACpC,SAAS,EAAE,kBAAkB,EAC7B,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACb,CAAC,cAAc,EAAE,MAAM,KAAK,iBAAiB,CAiB/C;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,GAAG,gBAAgB,CAE7F"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { objectRefKey } from './rename-rewriter.js';
|
|
2
|
+
/**
|
|
3
|
+
* The catalog-backed {@link ResolveObjectRef} the rename walkers consult to decide
|
|
4
|
+
* whether a table/view reference written in a stored body denotes the object being
|
|
5
|
+
* renamed / probed. It answers the way the PLANNER answers for that body — against
|
|
6
|
+
* the owning object's home schema path ({@link Database._homeSchemaPath}:
|
|
7
|
+
* `[homeSchema, ...session default path]`) — not against a single "default schema".
|
|
8
|
+
*
|
|
9
|
+
* Resolution rules:
|
|
10
|
+
* - **Qualified** (`schema` present) → `objectRefKey(schema, name)`, no catalog
|
|
11
|
+
* lookup. A qualified name means what it says even when the object does not
|
|
12
|
+
* exist (it may be the one about to be created, or the one just renamed away).
|
|
13
|
+
* - **Unqualified** → the first schema in the home path holding a table or view
|
|
14
|
+
* (a materialized view is a table) of that name.
|
|
15
|
+
* - **Miss in every schema** → the home schema's key, so a body naming an object
|
|
16
|
+
* that does not exist still gets a stable key rather than `undefined` —
|
|
17
|
+
* `undefined` is reserved for "no resolver could be consulted at all".
|
|
18
|
+
*
|
|
19
|
+
* NOTE: "the way the planner answers" is exact for the body kinds that plan under
|
|
20
|
+
* {@link Database._homeSchemaPath} — view bodies, materialized-view bodies, and
|
|
21
|
+
* assertion checks (`planner/stored-body-context.ts`). A CHECK constraint or a
|
|
22
|
+
* column DEFAULT / generated expression is stricter still: it plans under
|
|
23
|
+
* `schemaAuthoredContext` (`planner/building/schema-authored-context.ts`), the
|
|
24
|
+
* owning schema and NOTHING else, so an unqualified name the owning schema does
|
|
25
|
+
* not hold is an error there rather than a fallthrough down the session path.
|
|
26
|
+
* This resolver applies the looser home-path rule to all of them, which is
|
|
27
|
+
* deliberately safe rather than exact: the two rules can only disagree when the
|
|
28
|
+
* home schema lacks the name, and such a CHECK / DEFAULT cannot be evaluated at
|
|
29
|
+
* all — so no VALID body is ever matched (or missed) differently. Tighten to a
|
|
30
|
+
* per-body-kind path only if a rename ever needs to be right about a body the
|
|
31
|
+
* planner itself rejects.
|
|
32
|
+
*
|
|
33
|
+
* SNAPSHOT DISCIPLINE — the single most likely way to get this wrong: build the
|
|
34
|
+
* snapshot (`snapshotObjectRefResolvers` / `buildObjectRefResolver`) BEFORE the
|
|
35
|
+
* statement's first catalog mutation, and pass the same instance through the whole
|
|
36
|
+
* statement. Name-set lookups answer from the snapshot, NOT the live catalog, and
|
|
37
|
+
* that is load-bearing: rename propagation runs after the catalog swap, when the
|
|
38
|
+
* old name is gone — a live lookup of a bare `t` under `[main, temp]` after
|
|
39
|
+
* `main.t` was renamed would fall through to `temp.t` and silently match (or miss)
|
|
40
|
+
* the wrong object. The pre-mutation snapshot resolves every reference the way the
|
|
41
|
+
* body planned before the statement started, which is the question the rename is
|
|
42
|
+
* asking. (The session `schema_path` option is read at resolver-derivation time;
|
|
43
|
+
* it cannot change mid-statement.)
|
|
44
|
+
*/
|
|
45
|
+
export function snapshotObjectRefResolvers(db) {
|
|
46
|
+
// NOTE: snapshots every schema's table+view name set on each DDL statement, and
|
|
47
|
+
// resolves per reference after that; both are Map/Set work over handfuls of
|
|
48
|
+
// names. If a schema-heavy workload ever shows this hot, snapshot lazily per
|
|
49
|
+
// schema actually consulted.
|
|
50
|
+
const bySchema = new Map();
|
|
51
|
+
for (const schema of db.schemaManager._getAllSchemas()) {
|
|
52
|
+
const names = new Set();
|
|
53
|
+
for (const table of schema.getAllTables())
|
|
54
|
+
names.add(table.name.toLowerCase());
|
|
55
|
+
for (const view of schema.getAllViews())
|
|
56
|
+
names.add(view.name.toLowerCase());
|
|
57
|
+
bySchema.set(schema.name.toLowerCase(), names);
|
|
58
|
+
}
|
|
59
|
+
return buildResolvers(db, bySchema);
|
|
60
|
+
}
|
|
61
|
+
/** The shared builder over `(db, bySchema)`, so a {@link ObjectRefResolvers.withTableRenamed}
|
|
62
|
+
* sibling reuses the base snapshot's resolution logic over its own name-set map. */
|
|
63
|
+
function buildResolvers(db, bySchema) {
|
|
64
|
+
const cache = new Map();
|
|
65
|
+
return {
|
|
66
|
+
forHomeSchema(homeSchemaName) {
|
|
67
|
+
const homeLower = homeSchemaName.toLowerCase();
|
|
68
|
+
const cached = cache.get(homeLower);
|
|
69
|
+
if (cached)
|
|
70
|
+
return cached;
|
|
71
|
+
const path = db._homeSchemaPath(homeSchemaName).map(s => s.toLowerCase());
|
|
72
|
+
const resolve = (schema, name) => {
|
|
73
|
+
if (schema !== undefined)
|
|
74
|
+
return objectRefKey(schema, name);
|
|
75
|
+
const nameLower = name.toLowerCase();
|
|
76
|
+
for (const schemaLower of path) {
|
|
77
|
+
if (bySchema.get(schemaLower)?.has(nameLower))
|
|
78
|
+
return `${schemaLower}.${nameLower}`;
|
|
79
|
+
}
|
|
80
|
+
return `${homeLower}.${nameLower}`;
|
|
81
|
+
};
|
|
82
|
+
cache.set(homeLower, resolve);
|
|
83
|
+
return resolve;
|
|
84
|
+
},
|
|
85
|
+
withTableRenamed(schemaName, oldName, newName) {
|
|
86
|
+
// Copy the affected schema's Set and the outer Map shallowly — the base
|
|
87
|
+
// snapshot must keep answering pre-rename.
|
|
88
|
+
const schemaLower = schemaName.toLowerCase();
|
|
89
|
+
const sibling = new Map(bySchema);
|
|
90
|
+
const names = new Set(bySchema.get(schemaLower) ?? []);
|
|
91
|
+
names.delete(oldName.toLowerCase());
|
|
92
|
+
names.add(newName.toLowerCase());
|
|
93
|
+
sibling.set(schemaLower, names);
|
|
94
|
+
return buildResolvers(db, sibling);
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Per-home-schema {@link TableRenameTarget} factory for one `ALTER TABLE … RENAME TO`
|
|
100
|
+
* statement: binds the renamed object's identity to a pre-mutation `resolve` and a
|
|
101
|
+
* post-rename `resolveAfter` (the {@link ObjectRefResolvers.withTableRenamed} sibling),
|
|
102
|
+
* both derived per body-owning home schema. One statement builds this once and hands
|
|
103
|
+
* every walk the target for the walked body's owner, which is what lets the rewrite
|
|
104
|
+
* enforce its post-condition — a rewritten reference must still resolve to the renamed
|
|
105
|
+
* object — at the sink.
|
|
106
|
+
*/
|
|
107
|
+
export function tableRenameTargetsFor(resolvers, schemaName, oldName, newName) {
|
|
108
|
+
const after = resolvers.withTableRenamed(schemaName, oldName, newName);
|
|
109
|
+
const cache = new Map();
|
|
110
|
+
return homeSchemaName => {
|
|
111
|
+
const homeLower = homeSchemaName.toLowerCase();
|
|
112
|
+
const cached = cache.get(homeLower);
|
|
113
|
+
if (cached)
|
|
114
|
+
return cached;
|
|
115
|
+
const target = {
|
|
116
|
+
oldName,
|
|
117
|
+
newName,
|
|
118
|
+
schemaName,
|
|
119
|
+
resolve: resolvers.forHomeSchema(homeSchemaName),
|
|
120
|
+
resolveAfter: after.forHomeSchema(homeSchemaName),
|
|
121
|
+
};
|
|
122
|
+
cache.set(homeLower, target);
|
|
123
|
+
return target;
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Single-home convenience over {@link snapshotObjectRefResolvers}, for callers
|
|
128
|
+
* that walk bodies of one owning schema only (the DROP guards, a store module's
|
|
129
|
+
* own-table rewrite). Same snapshot discipline: build before the statement's
|
|
130
|
+
* first catalog mutation.
|
|
131
|
+
*/
|
|
132
|
+
export function buildObjectRefResolver(db, homeSchemaName) {
|
|
133
|
+
return snapshotObjectRefResolvers(db).forHomeSchema(homeSchemaName);
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=object-ref-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"object-ref-resolver.js","sourceRoot":"","sources":["../../../src/schema/object-ref-resolver.ts"],"names":[],"mappings":"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"}
|