@memberjunction/codegen-lib 6.1.0-edge.2 → 6.1.0-edge.4

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.
Files changed (133) hide show
  1. package/LICENSE +180 -4
  2. package/README.md +89 -43
  3. package/dist/Angular/angular-codegen.d.ts +0 -8
  4. package/dist/Angular/angular-codegen.d.ts.map +1 -1
  5. package/dist/Angular/angular-codegen.js +32 -22
  6. package/dist/Angular/angular-codegen.js.map +1 -1
  7. package/dist/Angular/entity-data-grid-related-entity-component.js +2 -2
  8. package/dist/Angular/entity-data-grid-related-entity-component.js.map +1 -1
  9. package/dist/Angular/related-entity-components.d.ts +1 -1
  10. package/dist/Angular/related-entity-components.js +1 -1
  11. package/dist/Config/config.d.ts +118 -1
  12. package/dist/Config/config.d.ts.map +1 -1
  13. package/dist/Config/config.js +202 -8
  14. package/dist/Config/config.js.map +1 -1
  15. package/dist/Database/__tests__/exclude-schema-permissions.test.d.ts +2 -0
  16. package/dist/Database/__tests__/exclude-schema-permissions.test.d.ts.map +1 -0
  17. package/dist/Database/__tests__/exclude-schema-permissions.test.js +32 -0
  18. package/dist/Database/__tests__/exclude-schema-permissions.test.js.map +1 -0
  19. package/dist/Database/codeGenDatabaseProvider.d.ts +178 -2
  20. package/dist/Database/codeGenDatabaseProvider.d.ts.map +1 -1
  21. package/dist/Database/codeGenDatabaseProvider.js +175 -10
  22. package/dist/Database/codeGenDatabaseProvider.js.map +1 -1
  23. package/dist/Database/heal-schema-params.d.ts +33 -0
  24. package/dist/Database/heal-schema-params.d.ts.map +1 -0
  25. package/dist/Database/heal-schema-params.js +51 -0
  26. package/dist/Database/heal-schema-params.js.map +1 -0
  27. package/dist/Database/manage-metadata.d.ts +301 -2
  28. package/dist/Database/manage-metadata.d.ts.map +1 -1
  29. package/dist/Database/manage-metadata.js +1242 -96
  30. package/dist/Database/manage-metadata.js.map +1 -1
  31. package/dist/Database/materializationAnalysis.d.ts +241 -0
  32. package/dist/Database/materializationAnalysis.d.ts.map +1 -0
  33. package/dist/Database/materializationAnalysis.js +415 -0
  34. package/dist/Database/materializationAnalysis.js.map +1 -0
  35. package/dist/Database/materializationBroadRender.d.ts +67 -0
  36. package/dist/Database/materializationBroadRender.d.ts.map +1 -0
  37. package/dist/Database/materializationBroadRender.js +104 -0
  38. package/dist/Database/materializationBroadRender.js.map +1 -0
  39. package/dist/Database/materializationDrift.d.ts +59 -0
  40. package/dist/Database/materializationDrift.d.ts.map +1 -0
  41. package/dist/Database/materializationDrift.js +85 -0
  42. package/dist/Database/materializationDrift.js.map +1 -0
  43. package/dist/Database/materializationParamClassifier.d.ts +92 -0
  44. package/dist/Database/materializationParamClassifier.d.ts.map +1 -0
  45. package/dist/Database/materializationParamClassifier.js +224 -0
  46. package/dist/Database/materializationParamClassifier.js.map +1 -0
  47. package/dist/Database/materializationParamVerifier.d.ts +71 -0
  48. package/dist/Database/materializationParamVerifier.d.ts.map +1 -0
  49. package/dist/Database/materializationParamVerifier.js +302 -0
  50. package/dist/Database/materializationParamVerifier.js.map +1 -0
  51. package/dist/Database/materializationSqlAst.d.ts +78 -0
  52. package/dist/Database/materializationSqlAst.d.ts.map +1 -0
  53. package/dist/Database/materializationSqlAst.js +142 -0
  54. package/dist/Database/materializationSqlAst.js.map +1 -0
  55. package/dist/Database/providers/postgresql/PostgreSQLCodeGenProvider.d.ts +93 -56
  56. package/dist/Database/providers/postgresql/PostgreSQLCodeGenProvider.d.ts.map +1 -1
  57. package/dist/Database/providers/postgresql/PostgreSQLCodeGenProvider.js +399 -247
  58. package/dist/Database/providers/postgresql/PostgreSQLCodeGenProvider.js.map +1 -1
  59. package/dist/Database/providers/postgresql/__tests__/PostgreSQLCodeGenProvider.materialization.test.d.ts +2 -0
  60. package/dist/Database/providers/postgresql/__tests__/PostgreSQLCodeGenProvider.materialization.test.d.ts.map +1 -0
  61. package/dist/Database/providers/postgresql/__tests__/PostgreSQLCodeGenProvider.materialization.test.js +119 -0
  62. package/dist/Database/providers/postgresql/__tests__/PostgreSQLCodeGenProvider.materialization.test.js.map +1 -0
  63. package/dist/Database/providers/postgresql/__tests__/PostgreSQLHierarchyFunctions.test.d.ts +2 -0
  64. package/dist/Database/providers/postgresql/__tests__/PostgreSQLHierarchyFunctions.test.d.ts.map +1 -0
  65. package/dist/Database/providers/postgresql/__tests__/PostgreSQLHierarchyFunctions.test.js +155 -0
  66. package/dist/Database/providers/postgresql/__tests__/PostgreSQLHierarchyFunctions.test.js.map +1 -0
  67. package/dist/Database/providers/postgresql/__tests__/SoftPrimaryKeyIndex.test.d.ts +2 -0
  68. package/dist/Database/providers/postgresql/__tests__/SoftPrimaryKeyIndex.test.d.ts.map +1 -0
  69. package/dist/Database/providers/postgresql/__tests__/SoftPrimaryKeyIndex.test.js +110 -0
  70. package/dist/Database/providers/postgresql/__tests__/SoftPrimaryKeyIndex.test.js.map +1 -0
  71. package/dist/Database/providers/postgresql/metadataSupportObjects.js +78 -10
  72. package/dist/Database/providers/postgresql/metadataSupportObjects.js.map +1 -1
  73. package/dist/Database/providers/sqlserver/SQLServerCodeGenProvider.d.ts +72 -1
  74. package/dist/Database/providers/sqlserver/SQLServerCodeGenProvider.d.ts.map +1 -1
  75. package/dist/Database/providers/sqlserver/SQLServerCodeGenProvider.js +322 -0
  76. package/dist/Database/providers/sqlserver/SQLServerCodeGenProvider.js.map +1 -1
  77. package/dist/Database/providers/sqlserver/__tests__/BaseViewEmissionGoldenMaster.test.d.ts +2 -0
  78. package/dist/Database/providers/sqlserver/__tests__/BaseViewEmissionGoldenMaster.test.d.ts.map +1 -0
  79. package/dist/Database/providers/sqlserver/__tests__/BaseViewEmissionGoldenMaster.test.js +547 -0
  80. package/dist/Database/providers/sqlserver/__tests__/BaseViewEmissionGoldenMaster.test.js.map +1 -0
  81. package/dist/Database/providers/sqlserver/__tests__/BaseViewRegenDecision.test.d.ts +2 -0
  82. package/dist/Database/providers/sqlserver/__tests__/BaseViewRegenDecision.test.d.ts.map +1 -0
  83. package/dist/Database/providers/sqlserver/__tests__/BaseViewRegenDecision.test.js +721 -0
  84. package/dist/Database/providers/sqlserver/__tests__/BaseViewRegenDecision.test.js.map +1 -0
  85. package/dist/Database/providers/sqlserver/__tests__/SQLServerCodeGenProvider.materialization.test.d.ts +2 -0
  86. package/dist/Database/providers/sqlserver/__tests__/SQLServerCodeGenProvider.materialization.test.d.ts.map +1 -0
  87. package/dist/Database/providers/sqlserver/__tests__/SQLServerCodeGenProvider.materialization.test.js +78 -0
  88. package/dist/Database/providers/sqlserver/__tests__/SQLServerCodeGenProvider.materialization.test.js.map +1 -0
  89. package/dist/Database/providers/sqlserver/__tests__/SQLServerHierarchyTVF.test.d.ts +2 -0
  90. package/dist/Database/providers/sqlserver/__tests__/SQLServerHierarchyTVF.test.d.ts.map +1 -0
  91. package/dist/Database/providers/sqlserver/__tests__/SQLServerHierarchyTVF.test.js +155 -0
  92. package/dist/Database/providers/sqlserver/__tests__/SQLServerHierarchyTVF.test.js.map +1 -0
  93. package/dist/Database/providers/sqlserver/__tests__/SoftPrimaryKeyIndex.test.d.ts +2 -0
  94. package/dist/Database/providers/sqlserver/__tests__/SoftPrimaryKeyIndex.test.d.ts.map +1 -0
  95. package/dist/Database/providers/sqlserver/__tests__/SoftPrimaryKeyIndex.test.js +195 -0
  96. package/dist/Database/providers/sqlserver/__tests__/SoftPrimaryKeyIndex.test.js.map +1 -0
  97. package/dist/Database/schema-filters.d.ts +23 -0
  98. package/dist/Database/schema-filters.d.ts.map +1 -0
  99. package/dist/Database/schema-filters.js +42 -0
  100. package/dist/Database/schema-filters.js.map +1 -0
  101. package/dist/Database/schema-scope.d.ts.map +1 -1
  102. package/dist/Database/schema-scope.js +4 -0
  103. package/dist/Database/schema-scope.js.map +1 -1
  104. package/dist/Database/sql_codegen.d.ts +39 -5
  105. package/dist/Database/sql_codegen.d.ts.map +1 -1
  106. package/dist/Database/sql_codegen.js +176 -67
  107. package/dist/Database/sql_codegen.js.map +1 -1
  108. package/dist/EntityNameScanner/EntityNameScanner.d.ts.map +1 -1
  109. package/dist/EntityNameScanner/EntityNameScanner.js +33 -2
  110. package/dist/EntityNameScanner/EntityNameScanner.js.map +1 -1
  111. package/dist/Manifest/GenerateClassRegistrationsManifest.d.ts +8 -4
  112. package/dist/Manifest/GenerateClassRegistrationsManifest.d.ts.map +1 -1
  113. package/dist/Manifest/GenerateClassRegistrationsManifest.js +63 -20
  114. package/dist/Manifest/GenerateClassRegistrationsManifest.js.map +1 -1
  115. package/dist/Misc/action_subclasses_codegen.d.ts.map +1 -1
  116. package/dist/Misc/action_subclasses_codegen.js +4 -4
  117. package/dist/Misc/action_subclasses_codegen.js.map +1 -1
  118. package/dist/Misc/entity_subclasses_codegen.d.ts +61 -0
  119. package/dist/Misc/entity_subclasses_codegen.d.ts.map +1 -1
  120. package/dist/Misc/entity_subclasses_codegen.js +437 -158
  121. package/dist/Misc/entity_subclasses_codegen.js.map +1 -1
  122. package/dist/Misc/graphql_server_codegen.d.ts +4 -58
  123. package/dist/Misc/graphql_server_codegen.d.ts.map +1 -1
  124. package/dist/Misc/graphql_server_codegen.js +22 -236
  125. package/dist/Misc/graphql_server_codegen.js.map +1 -1
  126. package/dist/Misc/sql_logging.d.ts +25 -0
  127. package/dist/Misc/sql_logging.d.ts.map +1 -1
  128. package/dist/Misc/sql_logging.js +51 -8
  129. package/dist/Misc/sql_logging.js.map +1 -1
  130. package/dist/Misc/system_integrity.d.ts.map +1 -1
  131. package/dist/Misc/system_integrity.js +5 -0
  132. package/dist/Misc/system_integrity.js.map +1 -1
  133. 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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"}