@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
|
@@ -1,18 +1,41 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Database } from '../core/database.js';
|
|
2
2
|
import type { ResolveColumnInSource } from './rename-rewriter.js';
|
|
3
3
|
/**
|
|
4
4
|
* The catalog-backed {@link ResolveColumnInSource} every scope-aware walk over a
|
|
5
5
|
* schema-object expression consults to tell an unqualified reference that binds to an
|
|
6
6
|
* inner FROM source from one that binds to the table under consideration.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
8
|
+
* Four callers, one definition, so no two of them can disagree about what a name
|
|
9
9
|
* resolves to: `runRenameColumn`'s pre-flight probe and its real propagation, the
|
|
10
|
-
* DROP COLUMN guards
|
|
11
|
-
* planner's self-qualifier
|
|
10
|
+
* DROP COLUMN guards (`runtime/emit/drop-column-guards.ts` and
|
|
11
|
+
* `schema/expression-dependents.ts`), and the constraint planner's self-qualifier
|
|
12
|
+
* strip (`planner/building/constraint-builder.ts`).
|
|
13
|
+
*
|
|
14
|
+
* A source may be a TABLE (a maintained table included — its backing columns are
|
|
15
|
+
* real) or a VIEW. A view exposes a column when its explicit column list names it,
|
|
16
|
+
* or — with no list — when its body publishes it ({@link bodyPublishesColumnNamed}:
|
|
17
|
+
* a result-column alias, a bare projection, or a `*` / `t.*` / `a.*` over a source
|
|
18
|
+
* that exposes it — a FROM alias only changes which qualifier names the source, so
|
|
19
|
+
* `select * from t a` publishes exactly what `select * from t` does). The view arm
|
|
20
|
+
* recurses through this same resolver, so a view over a
|
|
21
|
+
* view answers too; views cannot be recursive, so the per-question in-flight set is
|
|
22
|
+
* insurance against a malformed catalog, the same role the visited set plays in
|
|
23
|
+
* `reachableObjects`.
|
|
12
24
|
*
|
|
13
25
|
* Resolves against the LIVE catalog on every call, so sharing one instance across
|
|
14
26
|
* passes does not by itself freeze the answer between them — see the rename
|
|
15
|
-
* pre-flight's comment for why its two passes agree anyway.
|
|
27
|
+
* pre-flight's comment for why its two passes agree anyway. The view arm's
|
|
28
|
+
* unqualified names likewise resolve LIVE down the view's home schema path
|
|
29
|
+
* ({@link Database._homeSchemaPath}), matching how the view body plans.
|
|
30
|
+
*
|
|
31
|
+
* NOTE: deliberately NO cross-call memo. The rename propagation shares one
|
|
32
|
+
* instance across its pre-flight and its live cascade rounds, and the rounds
|
|
33
|
+
* rewrite view bodies in place — a memoized "does view X expose col?" answer taken
|
|
34
|
+
* before a round would be stale after it. The per-question in-flight set bounds the
|
|
35
|
+
* recursion instead. The one hot-ish caller is `constraint-builder.ts` at
|
|
36
|
+
* plan-build time, where the view arm only runs for a CHECK whose subquery FROMs a
|
|
37
|
+
* view; if that ever profiles hot, add a cross-call memo guarded by a catalog
|
|
38
|
+
* generation counter.
|
|
16
39
|
*/
|
|
17
|
-
export declare function buildColumnSourceResolver(
|
|
40
|
+
export declare function buildColumnSourceResolver(db: Database): ResolveColumnInSource;
|
|
18
41
|
//# sourceMappingURL=column-source-resolver.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"column-source-resolver.d.ts","sourceRoot":"","sources":["../../../src/schema/column-source-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"column-source-resolver.d.ts","sourceRoot":"","sources":["../../../src/schema/column-source-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,KAAK,EAAE,qBAAqB,EAAoB,MAAM,sBAAsB,CAAC;AAEpF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,QAAQ,GAAG,qBAAqB,CAyB7E"}
|
|
@@ -1,22 +1,91 @@
|
|
|
1
|
+
import { bodyPublishesColumnNamed, objectRefKey } from './rename-rewriter.js';
|
|
1
2
|
/**
|
|
2
3
|
* The catalog-backed {@link ResolveColumnInSource} every scope-aware walk over a
|
|
3
4
|
* schema-object expression consults to tell an unqualified reference that binds to an
|
|
4
5
|
* inner FROM source from one that binds to the table under consideration.
|
|
5
6
|
*
|
|
6
|
-
*
|
|
7
|
+
* Four callers, one definition, so no two of them can disagree about what a name
|
|
7
8
|
* resolves to: `runRenameColumn`'s pre-flight probe and its real propagation, the
|
|
8
|
-
* DROP COLUMN guards
|
|
9
|
-
* planner's self-qualifier
|
|
9
|
+
* DROP COLUMN guards (`runtime/emit/drop-column-guards.ts` and
|
|
10
|
+
* `schema/expression-dependents.ts`), and the constraint planner's self-qualifier
|
|
11
|
+
* strip (`planner/building/constraint-builder.ts`).
|
|
12
|
+
*
|
|
13
|
+
* A source may be a TABLE (a maintained table included — its backing columns are
|
|
14
|
+
* real) or a VIEW. A view exposes a column when its explicit column list names it,
|
|
15
|
+
* or — with no list — when its body publishes it ({@link bodyPublishesColumnNamed}:
|
|
16
|
+
* a result-column alias, a bare projection, or a `*` / `t.*` / `a.*` over a source
|
|
17
|
+
* that exposes it — a FROM alias only changes which qualifier names the source, so
|
|
18
|
+
* `select * from t a` publishes exactly what `select * from t` does). The view arm
|
|
19
|
+
* recurses through this same resolver, so a view over a
|
|
20
|
+
* view answers too; views cannot be recursive, so the per-question in-flight set is
|
|
21
|
+
* insurance against a malformed catalog, the same role the visited set plays in
|
|
22
|
+
* `reachableObjects`.
|
|
10
23
|
*
|
|
11
24
|
* Resolves against the LIVE catalog on every call, so sharing one instance across
|
|
12
25
|
* passes does not by itself freeze the answer between them — see the rename
|
|
13
|
-
* pre-flight's comment for why its two passes agree anyway.
|
|
26
|
+
* pre-flight's comment for why its two passes agree anyway. The view arm's
|
|
27
|
+
* unqualified names likewise resolve LIVE down the view's home schema path
|
|
28
|
+
* ({@link Database._homeSchemaPath}), matching how the view body plans.
|
|
29
|
+
*
|
|
30
|
+
* NOTE: deliberately NO cross-call memo. The rename propagation shares one
|
|
31
|
+
* instance across its pre-flight and its live cascade rounds, and the rounds
|
|
32
|
+
* rewrite view bodies in place — a memoized "does view X expose col?" answer taken
|
|
33
|
+
* before a round would be stale after it. The per-question in-flight set bounds the
|
|
34
|
+
* recursion instead. The one hot-ish caller is `constraint-builder.ts` at
|
|
35
|
+
* plan-build time, where the view arm only runs for a CHECK whose subquery FROMs a
|
|
36
|
+
* view; if that ever profiles hot, add a cross-call memo guarded by a catalog
|
|
37
|
+
* generation counter.
|
|
38
|
+
*/
|
|
39
|
+
export function buildColumnSourceResolver(db) {
|
|
40
|
+
const answer = (schemaName, sourceName, columnName, inFlight) => {
|
|
41
|
+
const targetSchema = db.schemaManager.getSchema(schemaName);
|
|
42
|
+
if (!targetSchema)
|
|
43
|
+
return false;
|
|
44
|
+
const colLower = columnName.toLowerCase();
|
|
45
|
+
const table = targetSchema.getTable(sourceName);
|
|
46
|
+
if (table)
|
|
47
|
+
return table.columnIndexMap.has(colLower);
|
|
48
|
+
const view = targetSchema.getView(sourceName);
|
|
49
|
+
if (!view)
|
|
50
|
+
return false;
|
|
51
|
+
if (view.columns && view.columns.length > 0) {
|
|
52
|
+
return view.columns.some(c => c.toLowerCase() === colLower);
|
|
53
|
+
}
|
|
54
|
+
const key = `${objectRefKey(targetSchema.name, view.name)}:${colLower}`;
|
|
55
|
+
if (inFlight.has(key))
|
|
56
|
+
return false;
|
|
57
|
+
inFlight.add(key);
|
|
58
|
+
try {
|
|
59
|
+
const recurse = (s, t, c) => answer(s, t, c, inFlight);
|
|
60
|
+
return bodyPublishesColumnNamed(view.selectAst, columnName, liveHomePathResolver(db, view.schemaName), recurse);
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
inFlight.delete(key);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
return (schemaName, sourceName, columnName) => answer(schemaName, sourceName, columnName, new Set());
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Live {@link ResolveObjectRef} for one home schema — the same resolution rule
|
|
70
|
+
* `snapshotObjectRefResolvers` snapshots (qualified passthrough; unqualified →
|
|
71
|
+
* first home-path schema holding a table or view of the name; miss → home key),
|
|
72
|
+
* answered against the live catalog. Live is right here: this resolver's contract
|
|
73
|
+
* is live answers, and the rename cascade's mid-statement body rewrites change
|
|
74
|
+
* published COLUMNS, never the object names this resolves.
|
|
14
75
|
*/
|
|
15
|
-
|
|
16
|
-
return (
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
76
|
+
function liveHomePathResolver(db, homeSchemaName) {
|
|
77
|
+
return (schema, name) => {
|
|
78
|
+
if (schema !== undefined)
|
|
79
|
+
return objectRefKey(schema, name);
|
|
80
|
+
for (const pathSchemaName of db._homeSchemaPath(homeSchemaName)) {
|
|
81
|
+
const pathSchema = db.schemaManager.getSchema(pathSchemaName);
|
|
82
|
+
if (!pathSchema)
|
|
83
|
+
continue;
|
|
84
|
+
if (pathSchema.getTable(name) !== undefined || pathSchema.getView(name) !== undefined) {
|
|
85
|
+
return objectRefKey(pathSchemaName, name);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return objectRefKey(homeSchemaName, name);
|
|
20
89
|
};
|
|
21
90
|
}
|
|
22
91
|
//# sourceMappingURL=column-source-resolver.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"column-source-resolver.js","sourceRoot":"","sources":["../../../src/schema/column-source-resolver.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"column-source-resolver.js","sourceRoot":"","sources":["../../../src/schema/column-source-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import type { Database } from '../core/database.js';
|
|
2
|
+
import type { TableSchema } from './table.js';
|
|
3
|
+
/**
|
|
4
|
+
* The catalog query "which stored, table-attached expressions reference this object?",
|
|
5
|
+
* shared by every DROP guard that has to refuse breaking one.
|
|
6
|
+
*
|
|
7
|
+
* A CHECK constraint, a column DEFAULT and a `GENERATED ALWAYS AS` body may all contain
|
|
8
|
+
* a subquery, so any of them can legitimately name a column or a table belonging to some
|
|
9
|
+
* OTHER table, in some other schema. `ALTER TABLE … RENAME` has always known this — it
|
|
10
|
+
* rewrites those expressions across every table in every schema — while the DROP guards
|
|
11
|
+
* used to scan only the altered table's own constraints and columns. The gap let
|
|
12
|
+
* `alter table t drop column v` and `drop table t` succeed while another table's CHECK
|
|
13
|
+
* still read `t.v`, leaving that table unwritable with an error naming neither the
|
|
14
|
+
* dropped object nor the constraint that broke.
|
|
15
|
+
*
|
|
16
|
+
* Everything here therefore walks the catalog the same way the rename propagation does —
|
|
17
|
+
* ONE {@link snapshotObjectRefResolvers} snapshot, a resolver per OWNING schema, the same
|
|
18
|
+
* scope-aware probes — so "the drop refuses exactly what a rename would have rewritten"
|
|
19
|
+
* holds by construction rather than by comment.
|
|
20
|
+
*
|
|
21
|
+
* **The own-table / other-table probe split is load-bearing.** It mirrors
|
|
22
|
+
* `rewriteTableForColumnRename`'s `isRenamedTable` branch:
|
|
23
|
+
*
|
|
24
|
+
* - On the **probed table itself**, the *seeded* probe
|
|
25
|
+
* ({@link columnReferencedInCheckExpression}) — an unqualified name in a CHECK /
|
|
26
|
+
* DEFAULT there binds the owning table implicitly.
|
|
27
|
+
* - On **any other table**, the *unseeded* probe ({@link columnReferencedInAst}) — no
|
|
28
|
+
* implicit binding, so only an explicit reference through a subquery counts. Getting
|
|
29
|
+
* this backwards false-refuses on every table that merely happens to have a like-named
|
|
30
|
+
* column.
|
|
31
|
+
*
|
|
32
|
+
* The seed answers only that binding question. What a bare `new.` / `old.` qualifier
|
|
33
|
+
* NAMES is a separate, explicitly-passed
|
|
34
|
+
* {@link import('./rename-rewriter.js').RowImageContext} — `'own'` on the seeded
|
|
35
|
+
* base-target probe, `'foreign'` on every other ROOT body (that table's row image is its
|
|
36
|
+
* own columns, not ours), `'none'` on the view / MV bodies below the root. See
|
|
37
|
+
* {@link columnProbe}.
|
|
38
|
+
*
|
|
39
|
+
* Partial-index predicates need no arm: the parser rejects a subquery in a partial-index
|
|
40
|
+
* predicate, so such a predicate can only name its own table, and `runDropColumn`'s
|
|
41
|
+
* existing predicate guard covers that case.
|
|
42
|
+
*
|
|
43
|
+
* Views are deliberately NOT probed as *dependents*. Dropping a table or column out from
|
|
44
|
+
* under a plain view stays allowed and breaks the view — the engine's stated asymmetry
|
|
45
|
+
* (see `runtime/emit/assertion-drop-guard.ts`): a broken view breaks queries OF that view,
|
|
46
|
+
* while a broken CHECK makes a whole table unwritable.
|
|
47
|
+
*
|
|
48
|
+
* Each probe runs over the REACH of the stored expression — {@link reachableObjects}, the
|
|
49
|
+
* same breadth-first closure over stored view / materialized-view bodies the assertion
|
|
50
|
+
* guards consume — not over the expression alone. Two consequences, both load-bearing:
|
|
51
|
+
*
|
|
52
|
+
* - A DIRECT reference matches exactly where a rename would have rewritten it, so the two
|
|
53
|
+
* definitions still cannot drift; the reach path is empty there, which is what keeps the
|
|
54
|
+
* guards' direct message spelling unchanged.
|
|
55
|
+
* - An INDIRECT reference — the expression names a view, whose body names the dropped
|
|
56
|
+
* object, to any depth — matches too. Without that, `check (n < (select max(v) from vv))`
|
|
57
|
+
* over `create view vv as select v from t` let `drop table t` /
|
|
58
|
+
* `alter table t drop column v` through and left the referencing table unwritable with
|
|
59
|
+
* an error naming neither the dropped object nor the constraint that broke.
|
|
60
|
+
*
|
|
61
|
+
* The root body is walked with `rowImageContext` and every body below it without — see
|
|
62
|
+
* `reachableObjects`' `rootOpts`. Rooting a CHECK / DEFAULT without it would put a table
|
|
63
|
+
* literally called `new` in the reach and false-refuse its own drop.
|
|
64
|
+
*
|
|
65
|
+
* NOTE: each probe walks every table in every schema, re-walking already-parsed ASTs, and
|
|
66
|
+
* now builds one closure PER STORED EXPRESSION rather than per table. The closure only
|
|
67
|
+
* expands objects a body actually names, so an expression naming no view adds no reached
|
|
68
|
+
* bodies at all — but it is still one extra walk per expression for the COLUMN verb, which
|
|
69
|
+
* pays `collectTableRefsInAst` to build the reach and then the column probe on top (the
|
|
70
|
+
* table verb reads its answer straight off the reach, so it is walk-for-walk with the
|
|
71
|
+
* one-hop probe it replaced). The COLUMN verb additionally runs one republication
|
|
72
|
+
* fixpoint per guard call (`schema/column-republication.ts` — a catalog sweep per round)
|
|
73
|
+
* and probes bodies × targets instead of bodies × 1; targets beyond the base table exist
|
|
74
|
+
* only when some view republishes the dropped column, so the common case pays one sweep
|
|
75
|
+
* and nothing else. Reasoned from the call shape, not measured. DDL is rare and
|
|
76
|
+
* schemas hold handfuls of tables, so this is not worth optimising now; if it ever shows as
|
|
77
|
+
* hot, gate each table on a cheap literal name scan of its stored SQL before paying for the
|
|
78
|
+
* AST walk.
|
|
79
|
+
*/
|
|
80
|
+
/** A stored, table-attached expression that references a probed object. */
|
|
81
|
+
export interface ExpressionDependent {
|
|
82
|
+
/** The table carrying the expression. */
|
|
83
|
+
table: TableSchema;
|
|
84
|
+
/** True when {@link table} IS the probed table (a self-reference), false otherwise. */
|
|
85
|
+
ownTable: boolean;
|
|
86
|
+
/** What to call it in an error: `CHECK constraint 'ck1'`, `the DEFAULT of column 'w'`, … */
|
|
87
|
+
describe: string;
|
|
88
|
+
/**
|
|
89
|
+
* The stored bodies the expression traversed to reach the probed object, each already
|
|
90
|
+
* described (`view 'v'`, `materialized view 'm'`) — EMPTY when the expression names the
|
|
91
|
+
* object itself. Feed it to `describeReachPath` to phrase an indirect refusal.
|
|
92
|
+
*/
|
|
93
|
+
path: ReadonlyArray<string>;
|
|
94
|
+
/**
|
|
95
|
+
* Present when the match is not a body NAMING the column but a view / MV the drop
|
|
96
|
+
* would BREAK OUTRIGHT: the object declares an explicit column list over a body
|
|
97
|
+
* whose `*` republishes the dropped column, so the drop changes the star's arity
|
|
98
|
+
* and every reference to the object breaks — not just references to one column.
|
|
99
|
+
* The value is the object's description (`view 'v'`), for the refusal message.
|
|
100
|
+
*/
|
|
101
|
+
breaksEntirely?: string;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Which family of stored expressions a column probe walks. The two exist separately
|
|
105
|
+
* because `runDropColumn` reports them through two guards with two different messages,
|
|
106
|
+
* ordered by widening blast radius.
|
|
107
|
+
*/
|
|
108
|
+
export type ColumnExpressionArm =
|
|
109
|
+
/** CHECK constraint expressions. */
|
|
110
|
+
'check'
|
|
111
|
+
/** Column DEFAULT and `GENERATED ALWAYS AS` expressions. */
|
|
112
|
+
| 'columnExpression';
|
|
113
|
+
/**
|
|
114
|
+
* The FIRST table in ANY schema whose `arm` expressions name
|
|
115
|
+
* `<tableSchema.schemaName>.<tableSchema.name>.<columnName>`, or `undefined` when none
|
|
116
|
+
* does. The probed table itself is scanned first, so a self-reference is always the one
|
|
117
|
+
* reported and the guards' own-table messages never change spelling because an unrelated
|
|
118
|
+
* schema happens to sort earlier.
|
|
119
|
+
*
|
|
120
|
+
* Only the first hit is returned: every caller is a guard that throws on it, and stopping
|
|
121
|
+
* early keeps the walk off the remaining schemas.
|
|
122
|
+
*
|
|
123
|
+
* Two expressions are skipped on the probed table itself, both deliberately:
|
|
124
|
+
*
|
|
125
|
+
* - The dropped column's **own** DEFAULT / generated body — it goes away with the column,
|
|
126
|
+
* so a self-naming default (`a integer default (new.a)`) is not something the drop
|
|
127
|
+
* orphans.
|
|
128
|
+
* - **Every** own-table generated body — `runDropColumn` already refuses off
|
|
129
|
+
* `generatedColumnDependencies`, the resolved column-index map
|
|
130
|
+
* `extractGeneratedColumnDependencies` builds, and reporting it twice would only change
|
|
131
|
+
* which of two messages the user sees. A generated body on ANOTHER table is not covered
|
|
132
|
+
* by that map and IS reported here.
|
|
133
|
+
*/
|
|
134
|
+
export declare function findColumnExpressionDependent(db: Database, tableSchema: TableSchema, columnName: string, arm: ColumnExpressionArm): ExpressionDependent | undefined;
|
|
135
|
+
/**
|
|
136
|
+
* The FIRST table in ANY schema whose CHECK / DEFAULT / `GENERATED ALWAYS AS` expressions
|
|
137
|
+
* name `<schemaName>.<objectName>`, or `undefined` when none does.
|
|
138
|
+
*
|
|
139
|
+
* The dropped object itself is skipped: its own CHECKs naming itself vanish with it, so
|
|
140
|
+
* refusing on them would make every self-referencing table undroppable. (The column verb
|
|
141
|
+
* keeps its target in the walk — a column drop leaves the rest of the table behind.)
|
|
142
|
+
*
|
|
143
|
+
* All three arms run with the walker's `rowImageContext` on the ROOT expression, exactly as
|
|
144
|
+
* `renameTableInCheckConstraints` / `renameTableInColumnExpressions` do: these
|
|
145
|
+
* expressions evaluate against a written row, so a bare `new.` / `old.` qualifier names
|
|
146
|
+
* that row image rather than a table literally called `new`.
|
|
147
|
+
*
|
|
148
|
+
* The match is `namerOf` over the expression's whole reach, so a CHECK that reads a view
|
|
149
|
+
* whose body reads the dropped object matches too, and `path` carries the shortest chain
|
|
150
|
+
* for the error to quote — empty exactly when the expression names the object itself.
|
|
151
|
+
*/
|
|
152
|
+
export declare function findTableExpressionDependent(db: Database, schemaName: string, objectName: string): ExpressionDependent | undefined;
|
|
153
|
+
/**
|
|
154
|
+
* How an error should spell `table` when the object being dropped lives in `homeSchemaName`:
|
|
155
|
+
* bare when the two share a schema, schema-qualified when they do not — the same rule the
|
|
156
|
+
* rest of the engine's messages follow, and the only way a cross-schema refusal names a
|
|
157
|
+
* table the user can actually find.
|
|
158
|
+
*/
|
|
159
|
+
export declare function describeDependentTable(table: TableSchema, homeSchemaName: string): string;
|
|
160
|
+
//# sourceMappingURL=expression-dependents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expression-dependents.d.ts","sourceRoot":"","sources":["../../../src/schema/expression-dependents.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAuB,MAAM,YAAY,CAAC;AAanE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4EG;AAEH,2EAA2E;AAC3E,MAAM,WAAW,mBAAmB;IACnC,yCAAyC;IACzC,KAAK,EAAE,WAAW,CAAC;IACnB,uFAAuF;IACvF,QAAQ,EAAE,OAAO,CAAC;IAClB,4FAA4F;IAC5F,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC5B;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;GAIG;AACH,MAAM,MAAM,mBAAmB;AAC9B,oCAAoC;AAClC,OAAO;AACT,4DAA4D;GAC1D,kBAAkB,CAAC;AAEtB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,6BAA6B,CAC5C,EAAE,EAAE,QAAQ,EACZ,WAAW,EAAE,WAAW,EACxB,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,mBAAmB,GACtB,mBAAmB,GAAG,SAAS,CAoBjC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,4BAA4B,CAC3C,EAAE,EAAE,QAAQ,EACZ,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GAChB,mBAAmB,GAAG,SAAS,CAgBjC;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CAIzF"}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { expressionToString } from '../emit/ast-stringify.js';
|
|
2
|
+
import { columnReferencedInAst, columnReferencedInCheckExpression, objectRefKey, } from './rename-rewriter.js';
|
|
3
|
+
import { buildColumnSourceResolver } from './column-source-resolver.js';
|
|
4
|
+
import { snapshotObjectRefResolvers } from './object-ref-resolver.js';
|
|
5
|
+
import { reachableObjects } from './object-dependency-closure.js';
|
|
6
|
+
import { collectColumnRepublication } from './column-republication.js';
|
|
7
|
+
/**
|
|
8
|
+
* The FIRST table in ANY schema whose `arm` expressions name
|
|
9
|
+
* `<tableSchema.schemaName>.<tableSchema.name>.<columnName>`, or `undefined` when none
|
|
10
|
+
* does. The probed table itself is scanned first, so a self-reference is always the one
|
|
11
|
+
* reported and the guards' own-table messages never change spelling because an unrelated
|
|
12
|
+
* schema happens to sort earlier.
|
|
13
|
+
*
|
|
14
|
+
* Only the first hit is returned: every caller is a guard that throws on it, and stopping
|
|
15
|
+
* early keeps the walk off the remaining schemas.
|
|
16
|
+
*
|
|
17
|
+
* Two expressions are skipped on the probed table itself, both deliberately:
|
|
18
|
+
*
|
|
19
|
+
* - The dropped column's **own** DEFAULT / generated body — it goes away with the column,
|
|
20
|
+
* so a self-naming default (`a integer default (new.a)`) is not something the drop
|
|
21
|
+
* orphans.
|
|
22
|
+
* - **Every** own-table generated body — `runDropColumn` already refuses off
|
|
23
|
+
* `generatedColumnDependencies`, the resolved column-index map
|
|
24
|
+
* `extractGeneratedColumnDependencies` builds, and reporting it twice would only change
|
|
25
|
+
* which of two messages the user sees. A generated body on ANOTHER table is not covered
|
|
26
|
+
* by that map and IS reported here.
|
|
27
|
+
*/
|
|
28
|
+
export function findColumnExpressionDependent(db, tableSchema, columnName, arm) {
|
|
29
|
+
const resolvers = snapshotObjectRefResolvers(db);
|
|
30
|
+
const resolveColumnInSource = buildColumnSourceResolver(db);
|
|
31
|
+
const targetKey = objectRefKey(tableSchema.schemaName, tableSchema.name);
|
|
32
|
+
// One republication fixpoint per drop (seed first), shared by every probe below:
|
|
33
|
+
// a view republishing the column by a star (`select * from t`) is a target its
|
|
34
|
+
// readers reference the column THROUGH, without any body spelling the name.
|
|
35
|
+
const republication = collectColumnRepublication(db, { targetKey, tableName: tableSchema.name }, columnName, resolvers, resolveColumnInSource);
|
|
36
|
+
for (const table of tablesProbedTargetFirst(db, targetKey)) {
|
|
37
|
+
const ownTable = objectRefKey(table.schemaName, table.name) === targetKey;
|
|
38
|
+
const names = columnProbe(db, resolvers, table.schemaName, ownTable, republication, columnName, resolveColumnInSource);
|
|
39
|
+
const found = arm === 'check'
|
|
40
|
+
? findInChecks(table, names)
|
|
41
|
+
: findInColumnExpressions(table, ownTable, columnName, names);
|
|
42
|
+
if (found)
|
|
43
|
+
return { table, ownTable, ...found };
|
|
44
|
+
}
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The FIRST table in ANY schema whose CHECK / DEFAULT / `GENERATED ALWAYS AS` expressions
|
|
49
|
+
* name `<schemaName>.<objectName>`, or `undefined` when none does.
|
|
50
|
+
*
|
|
51
|
+
* The dropped object itself is skipped: its own CHECKs naming itself vanish with it, so
|
|
52
|
+
* refusing on them would make every self-referencing table undroppable. (The column verb
|
|
53
|
+
* keeps its target in the walk — a column drop leaves the rest of the table behind.)
|
|
54
|
+
*
|
|
55
|
+
* All three arms run with the walker's `rowImageContext` on the ROOT expression, exactly as
|
|
56
|
+
* `renameTableInCheckConstraints` / `renameTableInColumnExpressions` do: these
|
|
57
|
+
* expressions evaluate against a written row, so a bare `new.` / `old.` qualifier names
|
|
58
|
+
* that row image rather than a table literally called `new`.
|
|
59
|
+
*
|
|
60
|
+
* The match is `namerOf` over the expression's whole reach, so a CHECK that reads a view
|
|
61
|
+
* whose body reads the dropped object matches too, and `path` carries the shortest chain
|
|
62
|
+
* for the error to quote — empty exactly when the expression names the object itself.
|
|
63
|
+
*/
|
|
64
|
+
export function findTableExpressionDependent(db, schemaName, objectName) {
|
|
65
|
+
const resolvers = snapshotObjectRefResolvers(db);
|
|
66
|
+
const targetKey = objectRefKey(schemaName, objectName);
|
|
67
|
+
for (const table of tablesProbedTargetFirst(db, targetKey)) {
|
|
68
|
+
if (objectRefKey(table.schemaName, table.name) === targetKey)
|
|
69
|
+
continue;
|
|
70
|
+
const names = expr => {
|
|
71
|
+
if (expr === undefined)
|
|
72
|
+
return undefined;
|
|
73
|
+
const path = reachableObjects(db, expr, table.schemaName, resolvers, { rowImageContext: true })
|
|
74
|
+
.namerOf(targetKey)?.path;
|
|
75
|
+
return path === undefined ? undefined : { path };
|
|
76
|
+
};
|
|
77
|
+
const found = findInChecks(table, names) ?? findInColumnExpressions(table, false, undefined, names);
|
|
78
|
+
if (found)
|
|
79
|
+
return { table, ownTable: false, ...found };
|
|
80
|
+
}
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* How an error should spell `table` when the object being dropped lives in `homeSchemaName`:
|
|
85
|
+
* bare when the two share a schema, schema-qualified when they do not — the same rule the
|
|
86
|
+
* rest of the engine's messages follow, and the only way a cross-schema refusal names a
|
|
87
|
+
* table the user can actually find.
|
|
88
|
+
*/
|
|
89
|
+
export function describeDependentTable(table, homeSchemaName) {
|
|
90
|
+
return table.schemaName.toLowerCase() === homeSchemaName.toLowerCase()
|
|
91
|
+
? `'${table.name}'`
|
|
92
|
+
: `'${table.schemaName}.${table.name}'`;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Every table in every schema, with the probed table (if it exists) first.
|
|
96
|
+
*
|
|
97
|
+
* Order is not cosmetic: the guards report the FIRST hit, and the own-table messages are
|
|
98
|
+
* the ones users and tests already know. Scanning the target first keeps a self-reference
|
|
99
|
+
* winning over an unrelated schema's.
|
|
100
|
+
*
|
|
101
|
+
* NOTE: past the probed table the order is `_getAllSchemas()` × `getAllTables()` insertion
|
|
102
|
+
* order, so with TWO referencing tables which one the refusal names follows catalog
|
|
103
|
+
* insertion rather than any user-visible rule. Harmless while the message is advisory —
|
|
104
|
+
* every referencing table has to be dealt with anyway. If a caller ever needs to *list*
|
|
105
|
+
* dependents (a `CASCADE` arm, an introspection function), give it a collect-all entry
|
|
106
|
+
* point with a defined order rather than calling this in a loop.
|
|
107
|
+
*/
|
|
108
|
+
function* tablesProbedTargetFirst(db, targetKey) {
|
|
109
|
+
const rest = [];
|
|
110
|
+
for (const schema of db.schemaManager._getAllSchemas()) {
|
|
111
|
+
for (const table of schema.getAllTables()) {
|
|
112
|
+
if (objectRefKey(table.schemaName, table.name) === targetKey)
|
|
113
|
+
yield table;
|
|
114
|
+
else
|
|
115
|
+
rest.push(table);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
yield* rest;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* The column probe for one scanned table — seeded on the probed table itself, unseeded
|
|
122
|
+
* everywhere else. See this module's header for why that split is load-bearing.
|
|
123
|
+
*
|
|
124
|
+
* The column question is not "does the reach CONTAIN this key?" (which is all the table
|
|
125
|
+
* verb needs) but "does any body in the reach NAME this column?", so this loops the reach's
|
|
126
|
+
* bodies the way `assertNoAssertionNamesColumn` already does, each under its own resolver.
|
|
127
|
+
* `homeSchemaName` is the SCANNED table's schema — the root expression's own — because that
|
|
128
|
+
* is what its unqualified names resolve against.
|
|
129
|
+
*
|
|
130
|
+
* Each body is probed against EVERY republication target, not the base table alone: a
|
|
131
|
+
* reference through `create view v as select * from t` spells the column against `v`, and
|
|
132
|
+
* only the target sweep sees it. Targets are swept OUTER, bodies inner, base table first —
|
|
133
|
+
* so every match the base-table sweep finds is found at the body it always was, and the
|
|
134
|
+
* existing message spellings (`reaches it through view 'v'`) do not move; the widened
|
|
135
|
+
* targets only ever ADD refusals.
|
|
136
|
+
*
|
|
137
|
+
* After the target sweep, the broken-listed arm: a view / MV with an explicit column list
|
|
138
|
+
* over a `*` covering the column breaks OUTRIGHT on the drop (the star's arity changes),
|
|
139
|
+
* so an expression whose reach names such an object at all refuses, marked
|
|
140
|
+
* {@link ProbeMatch.breaksEntirely} so the guard can phrase it honestly.
|
|
141
|
+
*/
|
|
142
|
+
function columnProbe(db, resolvers, homeSchemaName, ownTable, republication, columnName, resolveColumnInSource) {
|
|
143
|
+
return expr => {
|
|
144
|
+
if (!expr)
|
|
145
|
+
return undefined;
|
|
146
|
+
const reach = reachableObjects(db, expr, homeSchemaName, resolvers, { rowImageContext: true });
|
|
147
|
+
for (const [targetIndex, target] of republication.targets.entries()) {
|
|
148
|
+
for (const reached of reach.bodies) {
|
|
149
|
+
// Seeded ONLY on the probed table's own ROOT body, probing the BASE target: a
|
|
150
|
+
// CHECK / DEFAULT there is written against the row being written, so an
|
|
151
|
+
// unqualified name binds the owning table implicitly. A view body below it is
|
|
152
|
+
// a relation with no such seed, the root body of ANOTHER table's expression
|
|
153
|
+
// binds that table's row, not ours — and no expression ever binds a VIEW
|
|
154
|
+
// target implicitly, so a republication target takes the unseeded probe even
|
|
155
|
+
// at the root (a reference to it can only sit inside a subquery FROM).
|
|
156
|
+
const seeded = targetIndex === 0 && ownTable && reached.ownerKey === undefined;
|
|
157
|
+
// Row-image mode, the one non-constant site: a ROOT body is a table's CHECK /
|
|
158
|
+
// DEFAULT / generated expression and therefore always written-row context —
|
|
159
|
+
// `'own'` only for the seeded base-target case, `'foreign'` otherwise (another
|
|
160
|
+
// table's root body binds that table's image; a republication target at the
|
|
161
|
+
// root still binds the OWNING table's image, not the view being probed).
|
|
162
|
+
// Anything REACHED below the root is a view / MV body — a relation with no
|
|
163
|
+
// written row — so `'none'`.
|
|
164
|
+
const rowImage = reached.ownerKey === undefined ? (seeded ? 'own' : 'foreign') : 'none';
|
|
165
|
+
const hit = seeded
|
|
166
|
+
? columnReferencedInCheckExpression(reached.body, target.tableName, columnName, reached.resolve, target.targetKey, rowImage, resolveColumnInSource)
|
|
167
|
+
: columnReferencedInAst(reached.body, target.tableName, columnName, reached.resolve, target.targetKey, rowImage, resolveColumnInSource);
|
|
168
|
+
if (hit)
|
|
169
|
+
return { path: reached.path };
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
for (const broken of republication.brokenListed) {
|
|
173
|
+
const namer = reach.namerOf(broken.key);
|
|
174
|
+
if (namer)
|
|
175
|
+
return { path: namer.path, breaksEntirely: broken.describe };
|
|
176
|
+
}
|
|
177
|
+
return undefined;
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/** The first CHECK constraint of `table` the probe matches, described for an error. */
|
|
181
|
+
function findInChecks(table, names) {
|
|
182
|
+
for (const check of table.checkConstraints ?? []) {
|
|
183
|
+
// `!== undefined`, not truthiness: a match with an EMPTY path is a direct match.
|
|
184
|
+
const match = names(check.expr);
|
|
185
|
+
if (match !== undefined)
|
|
186
|
+
return { describe: describeCheck(check), ...match };
|
|
187
|
+
}
|
|
188
|
+
return undefined;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* The first column DEFAULT / generated body of `table` the probe matches, described for
|
|
192
|
+
* an error. `skipColumnName` is the column being dropped, skipped only on the probed
|
|
193
|
+
* table itself; own-table generated bodies are skipped outright (see
|
|
194
|
+
* {@link findColumnExpressionDependent}).
|
|
195
|
+
*/
|
|
196
|
+
function findInColumnExpressions(table, ownTable, skipColumnName, names) {
|
|
197
|
+
const lowerSkip = ownTable ? skipColumnName?.toLowerCase() : undefined;
|
|
198
|
+
for (const col of table.columns) {
|
|
199
|
+
if (lowerSkip !== undefined && col.name.toLowerCase() === lowerSkip)
|
|
200
|
+
continue;
|
|
201
|
+
// `!== undefined` for the same reason as in {@link findInChecks}: an empty-path
|
|
202
|
+
// match is a direct hit.
|
|
203
|
+
const defaultMatch = names(col.defaultValue ?? undefined);
|
|
204
|
+
if (defaultMatch !== undefined) {
|
|
205
|
+
return { describe: `the DEFAULT of column '${col.name}'`, ...defaultMatch };
|
|
206
|
+
}
|
|
207
|
+
if (ownTable)
|
|
208
|
+
continue;
|
|
209
|
+
const generatedMatch = names(col.generatedExpr);
|
|
210
|
+
if (generatedMatch !== undefined) {
|
|
211
|
+
return { describe: `the GENERATED expression of column '${col.name}'`, ...generatedMatch };
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return undefined;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* A table-level unnamed CHECK genuinely carries `name: undefined` — the `_check_<table>`
|
|
218
|
+
* spelling `manager.ts` produces is error text, not stored identity — so there is no name
|
|
219
|
+
* to quote and the expression stands in for one. That is also the only handle the user
|
|
220
|
+
* has on it: `DROP CONSTRAINT` resolves by name only, so an unnamed CHECK can only be
|
|
221
|
+
* removed by rebuilding its table.
|
|
222
|
+
*/
|
|
223
|
+
function describeCheck(check) {
|
|
224
|
+
return check.name
|
|
225
|
+
? `CHECK constraint '${check.name}'`
|
|
226
|
+
: `the CHECK constraint (${expressionToString(check.expr)})`;
|
|
227
|
+
}
|
|
228
|
+
//# sourceMappingURL=expression-dependents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expression-dependents.js","sourceRoot":"","sources":["../../../src/schema/expression-dependents.ts"],"names":[],"mappings":"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"}
|