@memberjunction/codegen-lib 6.1.0-edge.2 → 6.1.0-edge.3
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/LICENSE +180 -4
- package/README.md +39 -22
- package/dist/Angular/angular-codegen.d.ts +0 -8
- package/dist/Angular/angular-codegen.d.ts.map +1 -1
- package/dist/Angular/angular-codegen.js +32 -22
- package/dist/Angular/angular-codegen.js.map +1 -1
- package/dist/Angular/entity-data-grid-related-entity-component.js +2 -2
- package/dist/Angular/entity-data-grid-related-entity-component.js.map +1 -1
- package/dist/Angular/related-entity-components.d.ts +1 -1
- package/dist/Angular/related-entity-components.js +1 -1
- package/dist/Database/codeGenDatabaseProvider.d.ts +101 -0
- package/dist/Database/codeGenDatabaseProvider.d.ts.map +1 -1
- package/dist/Database/codeGenDatabaseProvider.js +77 -10
- package/dist/Database/codeGenDatabaseProvider.js.map +1 -1
- package/dist/Database/manage-metadata.d.ts +292 -2
- package/dist/Database/manage-metadata.d.ts.map +1 -1
- package/dist/Database/manage-metadata.js +1176 -45
- package/dist/Database/manage-metadata.js.map +1 -1
- package/dist/Database/materializationAnalysis.d.ts +241 -0
- package/dist/Database/materializationAnalysis.d.ts.map +1 -0
- package/dist/Database/materializationAnalysis.js +415 -0
- package/dist/Database/materializationAnalysis.js.map +1 -0
- package/dist/Database/materializationBroadRender.d.ts +67 -0
- package/dist/Database/materializationBroadRender.d.ts.map +1 -0
- package/dist/Database/materializationBroadRender.js +104 -0
- package/dist/Database/materializationBroadRender.js.map +1 -0
- package/dist/Database/materializationDrift.d.ts +59 -0
- package/dist/Database/materializationDrift.d.ts.map +1 -0
- package/dist/Database/materializationDrift.js +85 -0
- package/dist/Database/materializationDrift.js.map +1 -0
- package/dist/Database/materializationParamClassifier.d.ts +92 -0
- package/dist/Database/materializationParamClassifier.d.ts.map +1 -0
- package/dist/Database/materializationParamClassifier.js +224 -0
- package/dist/Database/materializationParamClassifier.js.map +1 -0
- package/dist/Database/materializationParamVerifier.d.ts +71 -0
- package/dist/Database/materializationParamVerifier.d.ts.map +1 -0
- package/dist/Database/materializationParamVerifier.js +302 -0
- package/dist/Database/materializationParamVerifier.js.map +1 -0
- package/dist/Database/materializationSqlAst.d.ts +78 -0
- package/dist/Database/materializationSqlAst.d.ts.map +1 -0
- package/dist/Database/materializationSqlAst.js +142 -0
- package/dist/Database/materializationSqlAst.js.map +1 -0
- package/dist/Database/providers/postgresql/PostgreSQLCodeGenProvider.d.ts +68 -21
- package/dist/Database/providers/postgresql/PostgreSQLCodeGenProvider.d.ts.map +1 -1
- package/dist/Database/providers/postgresql/PostgreSQLCodeGenProvider.js +303 -197
- package/dist/Database/providers/postgresql/PostgreSQLCodeGenProvider.js.map +1 -1
- package/dist/Database/providers/postgresql/__tests__/PostgreSQLCodeGenProvider.materialization.test.d.ts +2 -0
- package/dist/Database/providers/postgresql/__tests__/PostgreSQLCodeGenProvider.materialization.test.d.ts.map +1 -0
- package/dist/Database/providers/postgresql/__tests__/PostgreSQLCodeGenProvider.materialization.test.js +119 -0
- package/dist/Database/providers/postgresql/__tests__/PostgreSQLCodeGenProvider.materialization.test.js.map +1 -0
- package/dist/Database/providers/postgresql/__tests__/PostgreSQLHierarchyFunctions.test.d.ts +2 -0
- package/dist/Database/providers/postgresql/__tests__/PostgreSQLHierarchyFunctions.test.d.ts.map +1 -0
- package/dist/Database/providers/postgresql/__tests__/PostgreSQLHierarchyFunctions.test.js +155 -0
- package/dist/Database/providers/postgresql/__tests__/PostgreSQLHierarchyFunctions.test.js.map +1 -0
- package/dist/Database/providers/sqlserver/SQLServerCodeGenProvider.d.ts +60 -1
- package/dist/Database/providers/sqlserver/SQLServerCodeGenProvider.d.ts.map +1 -1
- package/dist/Database/providers/sqlserver/SQLServerCodeGenProvider.js +294 -0
- package/dist/Database/providers/sqlserver/SQLServerCodeGenProvider.js.map +1 -1
- package/dist/Database/providers/sqlserver/__tests__/BaseViewEmissionGoldenMaster.test.d.ts +2 -0
- package/dist/Database/providers/sqlserver/__tests__/BaseViewEmissionGoldenMaster.test.d.ts.map +1 -0
- package/dist/Database/providers/sqlserver/__tests__/BaseViewEmissionGoldenMaster.test.js +547 -0
- package/dist/Database/providers/sqlserver/__tests__/BaseViewEmissionGoldenMaster.test.js.map +1 -0
- package/dist/Database/providers/sqlserver/__tests__/BaseViewRegenDecision.test.d.ts +2 -0
- package/dist/Database/providers/sqlserver/__tests__/BaseViewRegenDecision.test.d.ts.map +1 -0
- package/dist/Database/providers/sqlserver/__tests__/BaseViewRegenDecision.test.js +721 -0
- package/dist/Database/providers/sqlserver/__tests__/BaseViewRegenDecision.test.js.map +1 -0
- package/dist/Database/providers/sqlserver/__tests__/SQLServerCodeGenProvider.materialization.test.d.ts +2 -0
- package/dist/Database/providers/sqlserver/__tests__/SQLServerCodeGenProvider.materialization.test.d.ts.map +1 -0
- package/dist/Database/providers/sqlserver/__tests__/SQLServerCodeGenProvider.materialization.test.js +78 -0
- package/dist/Database/providers/sqlserver/__tests__/SQLServerCodeGenProvider.materialization.test.js.map +1 -0
- package/dist/Database/providers/sqlserver/__tests__/SQLServerHierarchyTVF.test.d.ts +2 -0
- package/dist/Database/providers/sqlserver/__tests__/SQLServerHierarchyTVF.test.d.ts.map +1 -0
- package/dist/Database/providers/sqlserver/__tests__/SQLServerHierarchyTVF.test.js +155 -0
- package/dist/Database/providers/sqlserver/__tests__/SQLServerHierarchyTVF.test.js.map +1 -0
- package/dist/Database/sql_codegen.d.ts +21 -5
- package/dist/Database/sql_codegen.d.ts.map +1 -1
- package/dist/Database/sql_codegen.js +84 -26
- package/dist/Database/sql_codegen.js.map +1 -1
- package/dist/Misc/action_subclasses_codegen.d.ts.map +1 -1
- package/dist/Misc/action_subclasses_codegen.js +4 -4
- package/dist/Misc/action_subclasses_codegen.js.map +1 -1
- package/dist/Misc/entity_subclasses_codegen.d.ts +44 -0
- package/dist/Misc/entity_subclasses_codegen.d.ts.map +1 -1
- package/dist/Misc/entity_subclasses_codegen.js +369 -156
- package/dist/Misc/entity_subclasses_codegen.js.map +1 -1
- package/dist/Misc/graphql_server_codegen.d.ts +4 -58
- package/dist/Misc/graphql_server_codegen.d.ts.map +1 -1
- package/dist/Misc/graphql_server_codegen.js +22 -236
- package/dist/Misc/graphql_server_codegen.js.map +1 -1
- package/dist/Misc/sql_logging.d.ts +25 -0
- package/dist/Misc/sql_logging.d.ts.map +1 -1
- package/dist/Misc/sql_logging.js +51 -8
- package/dist/Misc/sql_logging.js.map +1 -1
- package/package.json +30 -30
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { MaterializedColumnSpec } from './codeGenDatabaseProvider.js';
|
|
2
|
+
import type { SQLParserDialect } from '@memberjunction/sql-dialect';
|
|
3
|
+
/**
|
|
4
|
+
* Result-shape + key analysis for query materialization (CodeGen materialization phase,
|
|
5
|
+
* sub-step C — plan/query-entity-materialization.md §4.2 / §5 / §9).
|
|
6
|
+
*
|
|
7
|
+
* This is the deterministic, engine-agnostic core: given a query's declared output shape
|
|
8
|
+
* (its `MJ: Query Fields`) and whether it is parameterized, decide whether it qualifies for
|
|
9
|
+
* materialization in v1 and produce the physical column spec for its materialized table.
|
|
10
|
+
*
|
|
11
|
+
* **v1 scope (Phase 1):** only **unparameterized** queries materialize; parameterized ones
|
|
12
|
+
* are deferred to Phase 2 (row-filter) / later. The single-column key is a **synthetic
|
|
13
|
+
* surrogate** (full-rebuild compatible) — the deterministic combined-key-set hashing in §5
|
|
14
|
+
* is Phase 3 and will replace the surrogate when incremental refresh lands.
|
|
15
|
+
*/
|
|
16
|
+
/** A query's declared output column (subset of `MJ: Query Fields` relevant to the shape). */
|
|
17
|
+
export interface QueryFieldShape {
|
|
18
|
+
/** Output column name. */
|
|
19
|
+
Name: string;
|
|
20
|
+
/** Engine-native SQL type for the column (from `QueryField.SQLFullType`). */
|
|
21
|
+
SQLFullType: string;
|
|
22
|
+
/** Whether the column is a computed expression (informational; still materializable as a snapshot column). */
|
|
23
|
+
IsComputed?: boolean;
|
|
24
|
+
}
|
|
25
|
+
/** The outcome of analyzing a query for materialization. */
|
|
26
|
+
export interface MaterializationAnalysis {
|
|
27
|
+
/** True only if the query can be materialized in v1. */
|
|
28
|
+
qualifies: boolean;
|
|
29
|
+
/** When `qualifies` is false, a human-readable reason (logged, never guessed-past). */
|
|
30
|
+
reason?: string;
|
|
31
|
+
/** Physical column spec for the materialized table (surrogate PK first, then the query's output columns). */
|
|
32
|
+
columns: MaterializedColumnSpec[];
|
|
33
|
+
/** Name of the synthetic surrogate primary-key column. */
|
|
34
|
+
surrogateColumnName: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Name of the synthetic surrogate key column added to every query-materialized table in v1.
|
|
38
|
+
* Namespaced to avoid colliding with a query's own output columns.
|
|
39
|
+
*/
|
|
40
|
+
export declare const MATERIALIZATION_SURROGATE_COLUMN = "__mj_MaterializedRowID";
|
|
41
|
+
/** Default surrogate column SQL type (SQL Server). Callers on other engines pass their own. */
|
|
42
|
+
export declare const DEFAULT_SURROGATE_SQL_TYPE = "int IDENTITY(1,1)";
|
|
43
|
+
/**
|
|
44
|
+
* Analyzes a query for v1 materialization. Pure function — no DB/IO — so it is fully unit-testable.
|
|
45
|
+
*
|
|
46
|
+
* Qualifying rule (§9 / §10, asymmetric-risk: default to NOT materializable when unsure):
|
|
47
|
+
* - parameterized queries do not qualify in v1 (deferred);
|
|
48
|
+
* - a query with no declared output fields does not qualify (run query analysis first);
|
|
49
|
+
* - a query whose output already contains a column named like the surrogate does not qualify
|
|
50
|
+
* (we won't silently shadow it).
|
|
51
|
+
*
|
|
52
|
+
* On success, returns the column spec with a synthetic surrogate PK prepended; the query's
|
|
53
|
+
* own output columns are emitted as nullable snapshot columns (a snapshot may contain NULLs).
|
|
54
|
+
*/
|
|
55
|
+
export declare function analyzeQueryForMaterialization(opts: {
|
|
56
|
+
queryName: string;
|
|
57
|
+
isParameterized: boolean;
|
|
58
|
+
fields: QueryFieldShape[];
|
|
59
|
+
/** Engine-specific surrogate column type; defaults to SQL Server's identity. */
|
|
60
|
+
surrogateSQLType?: string;
|
|
61
|
+
}): MaterializationAnalysis;
|
|
62
|
+
/**
|
|
63
|
+
* Verified role of a single query parameter, produced by the render-and-diff verifier (Phase 2b)
|
|
64
|
+
* with an LLM proposer (Phase 2c). The verifier is the oracle; this module only consumes its
|
|
65
|
+
* verdict — so `RowFilter` here means *proven* row-filter (the render-and-diff confirmed the only
|
|
66
|
+
* difference across param values is a substituted literal at a WHERE predicate on `filterColumn`).
|
|
67
|
+
*/
|
|
68
|
+
export type ParamRole = 'RowFilter' | 'Structural' | 'Unbounded';
|
|
69
|
+
/** Persisted parameterization mode (mirrors the `MaterializedResult.ParamMode` CHECK values). */
|
|
70
|
+
export type ParamMode = 'None' | 'RowFilterBroad' | 'PerValueCache' | 'BoundFixed';
|
|
71
|
+
/**
|
|
72
|
+
* Phase 2 read-time-injectable operators — the SAFE whitelist. A `column <op> value` predicate in this
|
|
73
|
+
* set can be faithfully re-applied against the broad materialized table with a bound parameter (§3 of the
|
|
74
|
+
* Phase-2 plan). `LIKE`/`IS`/`BETWEEN` and their negations are intentionally EXCLUDED in v1 (subtler
|
|
75
|
+
* pattern/null/two-operand semantics) — a query using them stays live-only, which is harmless (§10).
|
|
76
|
+
*/
|
|
77
|
+
export declare const SAFE_READ_FILTER_OPERATORS: ReadonlySet<string>;
|
|
78
|
+
/**
|
|
79
|
+
* One read-time filter predicate persisted as the contract between CodeGen (classify-time) and the runtime
|
|
80
|
+
* provider (read-time): `column <operator> value(s)` against the broad materialized table. Self-sufficient —
|
|
81
|
+
* the provider consumes this JSON directly and never re-parses the query. Values are ALWAYS bound as SQL
|
|
82
|
+
* parameters at read time (never interpolated), so `column`/`operator` are the only trusted-from-here fields.
|
|
83
|
+
*/
|
|
84
|
+
export interface ReadFilterSpecEntry {
|
|
85
|
+
/** The materialized output column to filter (proven present in the output at qualify time). */
|
|
86
|
+
column: string;
|
|
87
|
+
/** The normalized `column <op> value` operator — always one of {@link SAFE_READ_FILTER_OPERATORS}. */
|
|
88
|
+
operator: string;
|
|
89
|
+
/** The `MJ: Query Parameter` name whose incoming value binds into this predicate. */
|
|
90
|
+
paramName: string;
|
|
91
|
+
/** `scalar` → single bound value; `list` → `IN (@p0,@p1,…)` bound element-wise. */
|
|
92
|
+
kind: 'scalar' | 'list';
|
|
93
|
+
}
|
|
94
|
+
/** One parameter's verified classification (input to {@link qualifyParameterizedQuery}). */
|
|
95
|
+
export interface ParamClassification {
|
|
96
|
+
/** Parameter name (the Nunjucks variable). */
|
|
97
|
+
name: string;
|
|
98
|
+
/** Verified role. `RowFilter` requires `filterColumn`; `Structural` may carry a bounded domain. */
|
|
99
|
+
role: ParamRole;
|
|
100
|
+
/** Bucket 1: the output column the param filters on (must be present in the materialized output). */
|
|
101
|
+
filterColumn?: string;
|
|
102
|
+
/** Bucket 1: the normalized `column <op> value` operator (Phase 2 — required to reconstruct the predicate). */
|
|
103
|
+
filterOperator?: string;
|
|
104
|
+
/** Bucket 1: scalar vs. list (`IN`/`NOT IN`) value shape. */
|
|
105
|
+
filterKind?: 'scalar' | 'list';
|
|
106
|
+
/** Bucket 2: the verifier-bounded value domain (advisory — the runtime guard still recomputes on a miss). */
|
|
107
|
+
boundedDomain?: string[];
|
|
108
|
+
}
|
|
109
|
+
/** The parameterization-qualification decision for a query. */
|
|
110
|
+
export interface ParamQualification {
|
|
111
|
+
/** True only if the query's params are all safely materializable. */
|
|
112
|
+
qualifies: boolean;
|
|
113
|
+
/** When `qualifies` is false, a human-readable reason (logged, never guessed past). */
|
|
114
|
+
reason?: string;
|
|
115
|
+
/** Resolved mode. `None` for an unparameterized query. */
|
|
116
|
+
paramMode: ParamMode;
|
|
117
|
+
/** RowFilterBroad: the columns to apply as read-time predicates against the broad materialized table (§6.4). */
|
|
118
|
+
rowFilterColumns: string[];
|
|
119
|
+
/**
|
|
120
|
+
* RowFilterBroad: the structured, self-sufficient predicate spec the runtime provider injects at read time
|
|
121
|
+
* (Phase 2). Empty for every other mode. Persisted as JSON on `MJ: Materialized Results . ReadFilterSpec`.
|
|
122
|
+
*/
|
|
123
|
+
readFilterSpec: ReadFilterSpecEntry[];
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Decides the {@link ParamMode} for a (possibly parameterized) query from its per-param
|
|
127
|
+
* classifications — the §9 qualifying rule under the §10 asymmetric-risk posture
|
|
128
|
+
* (**default to NOT materializable unless every param is provably safe**). Pure — no DB/IO/LLM.
|
|
129
|
+
*
|
|
130
|
+
* Rules:
|
|
131
|
+
* - no params → `None` (qualifies; caller materializes the static query).
|
|
132
|
+
* - any `Unbounded` param (Bucket 3) → refuse (author can bind it to a fixed value → BoundFixed,
|
|
133
|
+
* which arrives here as effectively unparameterized).
|
|
134
|
+
* - `RowFilter` (Bucket 1) → the `filterColumn` MUST be present in the materialized output, else
|
|
135
|
+
* refuse (filtering on a projected-away column would be unsound).
|
|
136
|
+
* - `Structural` (Bucket 2) → only when `allowPerValueCache` is enabled AND the verifier bounded
|
|
137
|
+
* the domain; otherwise refuse (recompute live). Open decision §17 — defaults OFF.
|
|
138
|
+
* - a mix of row-filter and structural params is not modeled in v1 → refuse.
|
|
139
|
+
*/
|
|
140
|
+
export declare function qualifyParameterizedQuery(opts: {
|
|
141
|
+
queryName: string;
|
|
142
|
+
params: ParamClassification[];
|
|
143
|
+
/** The query's materialized output column names (for the Bucket-1 column-presence check). */
|
|
144
|
+
outputColumns: string[];
|
|
145
|
+
/** Whether Bucket-2 per-value cache is supported in this build (default false → structural recomputes). */
|
|
146
|
+
allowPerValueCache?: boolean;
|
|
147
|
+
/**
|
|
148
|
+
* Whether Bucket-1 row-filter broad materialization is enabled in this build (default false).
|
|
149
|
+
* Phase 2 is not shipped: the read-time row-filter predicate is NOT auto-injected by the provider,
|
|
150
|
+
* so a caller reading a RowFilterBroad materialization must supply the filter themselves (via
|
|
151
|
+
* ExtraFilter) or they get the broad/unfiltered set. To avoid that footgun, parameterized row-filter
|
|
152
|
+
* queries are refused (stay live-only) unless a build explicitly opts in. Flipping this to true is the
|
|
153
|
+
* Phase-2 enablement switch (finalize the read-time predicate injection first).
|
|
154
|
+
*/
|
|
155
|
+
allowRowFilterBroad?: boolean;
|
|
156
|
+
/**
|
|
157
|
+
* The query's **rendered** SQL (a concrete instance — parameters already substituted). REQUIRED to
|
|
158
|
+
* qualify a `RowFilter` param: the verifier reports `filterColumn` as a BARE column name, and matching
|
|
159
|
+
* that name against the output-column list alone cannot tell `o.Status` (the predicate) apart from
|
|
160
|
+
* `c.Status` (the projected output) in a join, nor `BillRegion` (an alias over `ShipRegion`) apart from
|
|
161
|
+
* a real `BillRegion` column. Both mis-matches produce a materialized read that filters on a DIFFERENT
|
|
162
|
+
* column than the live query, with no error and no count-guard signal. See
|
|
163
|
+
* {@link proveFilterColumnBinding}. When omitted, RowFilter params are REFUSED (fail closed, §10) —
|
|
164
|
+
* the query stays live-only, which is always correct.
|
|
165
|
+
*/
|
|
166
|
+
sql?: string;
|
|
167
|
+
/** Dialect used to parse {@link sql}. Required alongside it; RowFilter params refuse without both. */
|
|
168
|
+
dialect?: SQLParserDialect;
|
|
169
|
+
}): ParamQualification;
|
|
170
|
+
/** Verdict of {@link proveFilterColumnBinding}: provable, or refused with the precise reason. */
|
|
171
|
+
export interface FilterColumnBindingProof {
|
|
172
|
+
/** True ONLY when the predicate column is proven to be the same source column the output column carries. */
|
|
173
|
+
provable: boolean;
|
|
174
|
+
/** When not provable, the precise reason (logged; never guessed past). */
|
|
175
|
+
reason?: string;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Proves that a verified row-filter predicate on `filterColumn` refers to **exactly** the materialized
|
|
179
|
+
* output column of that same name — the gap a bare-name `outputColumns.includes(filterColumn)` check leaves
|
|
180
|
+
* open, and which nothing downstream can close.
|
|
181
|
+
*
|
|
182
|
+
* Two silently-wrong-data cases motivate it, both of which pass every existing guard (in particular the
|
|
183
|
+
* broad-render count guard, since exactly ONE predicate is stripped in each):
|
|
184
|
+
*
|
|
185
|
+
* - **Join collision** — `SELECT o.ID, c.Status FROM Orders o JOIN Customers c … WHERE o.Status = {{s}}`.
|
|
186
|
+
* The output `Status` is the CUSTOMER's; the predicate is the ORDER's. The materialized read emits
|
|
187
|
+
* `WHERE [Status] = @p0` against the customer's value.
|
|
188
|
+
* - **Alias rebinding** — `SELECT ID, ShipRegion AS BillRegion FROM Orders WHERE BillRegion = {{r}}` on a
|
|
189
|
+
* table that has BOTH columns. The materialized `BillRegion` column holds `ShipRegion` values, so the
|
|
190
|
+
* read filters `ShipRegion = 'East'` while live filters `BillRegion = 'East'`.
|
|
191
|
+
*
|
|
192
|
+
* Refuses (never guesses) unless ALL of the following hold — falling back to the live query, always correct:
|
|
193
|
+
* 1. `sql` parses to a single plain SELECT (not multi-statement, not a set operation — a `UNION` root
|
|
194
|
+
* exposes only its first branch, so nothing about the whole result can be proven from it);
|
|
195
|
+
* 2. the SELECT list is readable and not a wildcard (`SELECT *` hides the real output↔source mapping);
|
|
196
|
+
* 3. exactly ONE output column is named `filterColumn` (two would make the read-time predicate ambiguous);
|
|
197
|
+
* 4. that output column is a plain column reference, not a computed expression;
|
|
198
|
+
* 5. it projects the SAME source column name (no alias rebinding);
|
|
199
|
+
* 6. the WHERE clause references `filterColumn` under a single, consistent qualifier; and
|
|
200
|
+
* 7. that qualifier provably denotes the same relation as the output column's — trivially true for a
|
|
201
|
+
* single-relation FROM, otherwise both must carry the same explicit qualifier ({@link sourceRefsMatch}).
|
|
202
|
+
*
|
|
203
|
+
* Pure — no DB/IO.
|
|
204
|
+
*/
|
|
205
|
+
export declare function proveFilterColumnBinding(opts: {
|
|
206
|
+
/** The query's RENDERED SQL (parameters substituted), still carrying the row-filter predicate. */
|
|
207
|
+
sql: string;
|
|
208
|
+
/** Dialect to parse with. */
|
|
209
|
+
dialect: SQLParserDialect;
|
|
210
|
+
/** The verifier-reported bare filter column name. */
|
|
211
|
+
filterColumn: string;
|
|
212
|
+
}): FilterColumnBindingProof;
|
|
213
|
+
/**
|
|
214
|
+
* Phase 3: detect the combined KEY of an aggregation query (for the surrogate hash). Conservative and
|
|
215
|
+
* safe-by-default — returns the grouping columns as the key ONLY when it can confidently identify an
|
|
216
|
+
* aggregation whose key is expressible in the materialized output; ANY ambiguity → null, and the caller
|
|
217
|
+
* then uses the synthetic surrogate + full rebuild (always correct, just not incrementally optimizable —
|
|
218
|
+
* the §10 "refuse under uncertainty" bias applied to keying). See the inline comment for the exact rules;
|
|
219
|
+
* the key is built from the AST GROUP BY terms (not a SELECT-list split), so grouping expressions and
|
|
220
|
+
* grouped-but-unprojected columns both refuse rather than silently producing a too-narrow key.
|
|
221
|
+
*/
|
|
222
|
+
export declare function detectAggregationKeyColumns(opts: {
|
|
223
|
+
sql: string;
|
|
224
|
+
dialect: SQLParserDialect;
|
|
225
|
+
fields: QueryFieldShape[];
|
|
226
|
+
}): {
|
|
227
|
+
name: string;
|
|
228
|
+
type: string;
|
|
229
|
+
}[] | null;
|
|
230
|
+
/**
|
|
231
|
+
* Phase 4: is an aggregation's measure set PURELY ADDITIVE (only SUM / plain COUNT)? Drives the
|
|
232
|
+
* refresh-strategy choice: additive keyed aggregations use the MERGE-upsert `Incremental` path
|
|
233
|
+
* (in-place measure update, no row churn), non-additive ones use `DirtyGroupRecompute` (whole-group
|
|
234
|
+
* delete+reinsert). Conservative and safe-by-default: returns false on ANY sign of a non-additive
|
|
235
|
+
* aggregate (`AVG`/`MIN`/`MAX`/`STDEV*`/`VAR*`/`MEDIAN`/`PERCENTILE`/`*_AGG`, or `COUNT(DISTINCT …)`),
|
|
236
|
+
* and requires at least one additive aggregate to be present — anything ambiguous → false (the caller
|
|
237
|
+
* then uses DirtyGroupRecompute, which is correct for all measure types). Regex-based because the SQL
|
|
238
|
+
* parser doesn't expose per-measure expression text; the bias is toward the safe (non-additive) answer.
|
|
239
|
+
*/
|
|
240
|
+
export declare function detectAdditiveMeasures(sql: string): boolean;
|
|
241
|
+
//# sourceMappingURL=materializationAnalysis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"materializationAnalysis.d.ts","sourceRoot":"","sources":["../../src/Database/materializationAnalysis.ts"],"names":[],"mappings":"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"}
|