@quereus/quereus 4.21.1 → 4.23.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.
Files changed (142) hide show
  1. package/dist/src/core/database-cardinality-feedback.d.ts +259 -0
  2. package/dist/src/core/database-cardinality-feedback.d.ts.map +1 -0
  3. package/dist/src/core/database-cardinality-feedback.js +547 -0
  4. package/dist/src/core/database-cardinality-feedback.js.map +1 -0
  5. package/dist/src/core/database-transaction.d.ts +9 -2
  6. package/dist/src/core/database-transaction.d.ts.map +1 -1
  7. package/dist/src/core/database-transaction.js +27 -9
  8. package/dist/src/core/database-transaction.js.map +1 -1
  9. package/dist/src/core/database.d.ts +5 -0
  10. package/dist/src/core/database.d.ts.map +1 -1
  11. package/dist/src/core/database.js +86 -7
  12. package/dist/src/core/database.js.map +1 -1
  13. package/dist/src/core/statement.d.ts +16 -2
  14. package/dist/src/core/statement.d.ts.map +1 -1
  15. package/dist/src/core/statement.js +55 -2
  16. package/dist/src/core/statement.js.map +1 -1
  17. package/dist/src/func/builtins/cardinality-feedback.d.ts +15 -0
  18. package/dist/src/func/builtins/cardinality-feedback.d.ts.map +1 -0
  19. package/dist/src/func/builtins/cardinality-feedback.js +106 -0
  20. package/dist/src/func/builtins/cardinality-feedback.js.map +1 -0
  21. package/dist/src/func/builtins/explain.d.ts.map +1 -1
  22. package/dist/src/func/builtins/explain.js +3 -1
  23. package/dist/src/func/builtins/explain.js.map +1 -1
  24. package/dist/src/func/builtins/index.d.ts.map +1 -1
  25. package/dist/src/func/builtins/index.js +3 -0
  26. package/dist/src/func/builtins/index.js.map +1 -1
  27. package/dist/src/index.d.ts +1 -1
  28. package/dist/src/index.d.ts.map +1 -1
  29. package/dist/src/planner/cost/index.d.ts +25 -19
  30. package/dist/src/planner/cost/index.d.ts.map +1 -1
  31. package/dist/src/planner/cost/index.js +28 -21
  32. package/dist/src/planner/cost/index.js.map +1 -1
  33. package/dist/src/planner/framework/trace.js +2 -2
  34. package/dist/src/planner/framework/trace.js.map +1 -1
  35. package/dist/src/planner/nodes/aggregate-node.d.ts +2 -1
  36. package/dist/src/planner/nodes/aggregate-node.d.ts.map +1 -1
  37. package/dist/src/planner/nodes/aggregate-node.js +1 -0
  38. package/dist/src/planner/nodes/aggregate-node.js.map +1 -1
  39. package/dist/src/planner/nodes/filter.d.ts.map +1 -1
  40. package/dist/src/planner/nodes/filter.js +5 -10
  41. package/dist/src/planner/nodes/filter.js.map +1 -1
  42. package/dist/src/planner/nodes/hash-aggregate.d.ts +2 -1
  43. package/dist/src/planner/nodes/hash-aggregate.d.ts.map +1 -1
  44. package/dist/src/planner/nodes/hash-aggregate.js +1 -0
  45. package/dist/src/planner/nodes/hash-aggregate.js.map +1 -1
  46. package/dist/src/planner/nodes/plan-node.d.ts +11 -0
  47. package/dist/src/planner/nodes/plan-node.d.ts.map +1 -1
  48. package/dist/src/planner/nodes/plan-node.js +3 -0
  49. package/dist/src/planner/nodes/plan-node.js.map +1 -1
  50. package/dist/src/planner/nodes/reference.d.ts +7 -0
  51. package/dist/src/planner/nodes/reference.d.ts.map +1 -1
  52. package/dist/src/planner/nodes/reference.js +17 -3
  53. package/dist/src/planner/nodes/reference.js.map +1 -1
  54. package/dist/src/planner/nodes/stream-aggregate.d.ts +2 -1
  55. package/dist/src/planner/nodes/stream-aggregate.d.ts.map +1 -1
  56. package/dist/src/planner/nodes/stream-aggregate.js +1 -0
  57. package/dist/src/planner/nodes/stream-aggregate.js.map +1 -1
  58. package/dist/src/planner/nodes/table-access-nodes.d.ts +14 -1
  59. package/dist/src/planner/nodes/table-access-nodes.d.ts.map +1 -1
  60. package/dist/src/planner/nodes/table-access-nodes.js +52 -20
  61. package/dist/src/planner/nodes/table-access-nodes.js.map +1 -1
  62. package/dist/src/planner/optimizer-tuning.d.ts +67 -7
  63. package/dist/src/planner/optimizer-tuning.d.ts.map +1 -1
  64. package/dist/src/planner/optimizer-tuning.js +14 -3
  65. package/dist/src/planner/optimizer-tuning.js.map +1 -1
  66. package/dist/src/planner/rules/access/rule-key-set-seek.d.ts +9 -0
  67. package/dist/src/planner/rules/access/rule-key-set-seek.d.ts.map +1 -1
  68. package/dist/src/planner/rules/access/rule-key-set-seek.js +18 -12
  69. package/dist/src/planner/rules/access/rule-key-set-seek.js.map +1 -1
  70. package/dist/src/planner/rules/access/rule-select-access-path.d.ts.map +1 -1
  71. package/dist/src/planner/rules/access/rule-select-access-path.js +7 -8
  72. package/dist/src/planner/rules/access/rule-select-access-path.js.map +1 -1
  73. package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.js +1 -1
  74. package/dist/src/planner/rules/aggregate/rule-aggregate-streaming.js.map +1 -1
  75. package/dist/src/planner/rules/cache/rule-nested-loop-right-cache.d.ts.map +1 -1
  76. package/dist/src/planner/rules/cache/rule-nested-loop-right-cache.js +7 -0
  77. package/dist/src/planner/rules/cache/rule-nested-loop-right-cache.js.map +1 -1
  78. package/dist/src/planner/rules/join/index-nested-loop.d.ts +6 -2
  79. package/dist/src/planner/rules/join/index-nested-loop.d.ts.map +1 -1
  80. package/dist/src/planner/rules/join/index-nested-loop.js +20 -14
  81. package/dist/src/planner/rules/join/index-nested-loop.js.map +1 -1
  82. package/dist/src/planner/rules/join/rule-fanout-batched-outer.d.ts.map +1 -1
  83. package/dist/src/planner/rules/join/rule-fanout-batched-outer.js +5 -0
  84. package/dist/src/planner/rules/join/rule-fanout-batched-outer.js.map +1 -1
  85. package/dist/src/planner/rules/join/rule-join-physical-selection.d.ts.map +1 -1
  86. package/dist/src/planner/rules/join/rule-join-physical-selection.js +102 -53
  87. package/dist/src/planner/rules/join/rule-join-physical-selection.js.map +1 -1
  88. package/dist/src/planner/rules/join/rule-monotonic-merge-join.d.ts +1 -1
  89. package/dist/src/planner/rules/join/rule-monotonic-merge-join.d.ts.map +1 -1
  90. package/dist/src/planner/rules/join/rule-monotonic-merge-join.js +15 -6
  91. package/dist/src/planner/rules/join/rule-monotonic-merge-join.js.map +1 -1
  92. package/dist/src/planner/rules/join/rule-quickpick-enumeration.d.ts.map +1 -1
  93. package/dist/src/planner/rules/join/rule-quickpick-enumeration.js +8 -1
  94. package/dist/src/planner/rules/join/rule-quickpick-enumeration.js.map +1 -1
  95. package/dist/src/planner/rules/retrieve/rule-grow-retrieve.d.ts.map +1 -1
  96. package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js +7 -6
  97. package/dist/src/planner/rules/retrieve/rule-grow-retrieve.js.map +1 -1
  98. package/dist/src/planner/stats/catalog-stats.d.ts +11 -2
  99. package/dist/src/planner/stats/catalog-stats.d.ts.map +1 -1
  100. package/dist/src/planner/stats/catalog-stats.js +14 -5
  101. package/dist/src/planner/stats/catalog-stats.js.map +1 -1
  102. package/dist/src/planner/stats/table-cardinality.d.ts +146 -23
  103. package/dist/src/planner/stats/table-cardinality.d.ts.map +1 -1
  104. package/dist/src/planner/stats/table-cardinality.js +159 -23
  105. package/dist/src/planner/stats/table-cardinality.js.map +1 -1
  106. package/dist/src/planner/util/relative-rows.d.ts +29 -0
  107. package/dist/src/planner/util/relative-rows.d.ts.map +1 -0
  108. package/dist/src/planner/util/relative-rows.js +67 -0
  109. package/dist/src/planner/util/relative-rows.js.map +1 -0
  110. package/dist/src/planner/util/row-estimates.d.ts +23 -0
  111. package/dist/src/planner/util/row-estimates.d.ts.map +1 -1
  112. package/dist/src/planner/util/row-estimates.js +29 -0
  113. package/dist/src/planner/util/row-estimates.js.map +1 -1
  114. package/dist/src/runtime/cardinality-observations.d.ts +85 -0
  115. package/dist/src/runtime/cardinality-observations.d.ts.map +1 -0
  116. package/dist/src/runtime/cardinality-observations.js +103 -0
  117. package/dist/src/runtime/cardinality-observations.js.map +1 -0
  118. package/dist/src/runtime/emit/scan.d.ts +1 -1
  119. package/dist/src/runtime/emit/scan.d.ts.map +1 -1
  120. package/dist/src/runtime/emit/scan.js +100 -3
  121. package/dist/src/runtime/emit/scan.js.map +1 -1
  122. package/dist/src/runtime/parallel-driver.d.ts +3 -0
  123. package/dist/src/runtime/parallel-driver.d.ts.map +1 -1
  124. package/dist/src/runtime/parallel-driver.js +4 -0
  125. package/dist/src/runtime/parallel-driver.js.map +1 -1
  126. package/dist/src/runtime/types.d.ts +12 -0
  127. package/dist/src/runtime/types.d.ts.map +1 -1
  128. package/dist/src/runtime/types.js.map +1 -1
  129. package/dist/src/schema/manager.d.ts +7 -0
  130. package/dist/src/schema/manager.d.ts.map +1 -1
  131. package/dist/src/schema/manager.js +8 -0
  132. package/dist/src/schema/manager.js.map +1 -1
  133. package/dist/src/vtab/filter-info.d.ts +16 -0
  134. package/dist/src/vtab/filter-info.d.ts.map +1 -1
  135. package/dist/src/vtab/filter-info.js +29 -0
  136. package/dist/src/vtab/filter-info.js.map +1 -1
  137. package/dist/src/vtab/memory/module.d.ts.map +1 -1
  138. package/dist/src/vtab/memory/module.js +5 -3
  139. package/dist/src/vtab/memory/module.js.map +1 -1
  140. package/dist/src/vtab/module.d.ts +53 -0
  141. package/dist/src/vtab/module.d.ts.map +1 -1
  142. package/package.json +3 -3
@@ -0,0 +1,547 @@
1
+ /**
2
+ * The observed row-count overlay: exact base-table sizes seen during execution.
3
+ *
4
+ * One per `Database`. The planner reads it through `plannedRowCount`
5
+ * (`planner/stats/table-cardinality.ts`), where an answering entry outranks the
6
+ * catalog's `ANALYZE` count and a module's approximate count, but not a module's
7
+ * exact one, and through `plannedRowsPerKey`, where an entry's rows per key answers
8
+ * unless the catalog's statistics cover the column set. This module owns the record
9
+ * policy — which observations are worth keeping, and when one has moved far enough
10
+ * from what plans were costed against to call it a *shift* — and the entries' lifetime.
11
+ *
12
+ * Validity is schema identity: an entry answers only for the exact `TableSchema`
13
+ * object it was observed under. Any swap (`ANALYZE`, `ALTER TABLE`, drop and
14
+ * re-create) silences it, and a schema-change listener evicts it. The identity
15
+ * check is the correctness guard; the listener is memory hygiene.
16
+ *
17
+ * An entry holds an exact count from a complete read, a floor ("at least N rows") from a
18
+ * partial one, or both; a floor only ever raises an estimate, and an exact count clears it.
19
+ * Beside them it keeps, per equality column set the table is seeked on through a
20
+ * non-unique index, a running mean of the rows one key matched ({@link PerKeyEntry}).
21
+ *
22
+ * Execution feeds it through {@link CardinalityFeedbackManager.publish}, which admits
23
+ * only observations of committed state: one made inside a transaction is held until
24
+ * that transaction commits ({@link CardinalityFeedbackManager.onCommitted}) and
25
+ * dropped if it rolls back ({@link CardinalityFeedbackManager.onRolledBack}).
26
+ *
27
+ * A shift reaches prepared statements through `onShift`; each statement paces its
28
+ * re-plans with a {@link FeedbackReplanState}. A module-reported size, which moves with
29
+ * no observation at all, is re-checked by each statement at execution start against the
30
+ * size its plan was costed with ({@link ReportedSizeSnapshot}).
31
+ *
32
+ * Nothing here is persisted: a new `Database` starts empty. See
33
+ * docs/progressive-optimizer.md §3.2–3.6.
34
+ */
35
+ import { createLogger } from '../common/logger.js';
36
+ import { CardinalityObservations, columnSetKey } from '../runtime/cardinality-observations.js';
37
+ import { catalogRowCount, moduleReportsRowCount, plannedRowCount, } from '../planner/stats/table-cardinality.js';
38
+ const log = createLogger('core:cardinality-feedback');
39
+ const debugLog = log.extend('debug');
40
+ /**
41
+ * Samples a rows-per-key mean tracks exactly before it becomes an exponential average:
42
+ * up to this many, the mean is the exact running mean of every sample; past it, each
43
+ * sample weighs 1/32, so a changing distribution is followed rather than averaged away.
44
+ * A module constant, not a tuning knob — nothing a deployment would turn.
45
+ */
46
+ const ROWS_PER_KEY_WINDOW = 32;
47
+ /**
48
+ * Distance between two counts as a ratio ≥ 1. The `+ 1` on both sides keeps a zero
49
+ * count finite and makes tiny counts compare sanely (0 vs 3 is 4×, not infinite).
50
+ */
51
+ function rowCountSpread(a, b) {
52
+ return (Math.max(a, b) + 1) / (Math.min(a, b) + 1);
53
+ }
54
+ /** The overlay's key for a table: lowercased `schema.table`. Shifts are reported under it. */
55
+ export function overlayTableKey(schemaName, tableName) {
56
+ return `${schemaName}.${tableName}`.toLowerCase();
57
+ }
58
+ function tableKey(table) {
59
+ return overlayTableKey(table.schemaName, table.name);
60
+ }
61
+ function newEntry(schema, baselineRows) {
62
+ return { schema, rows: undefined, atLeast: undefined, baselineRows, observations: 0, shifts: 0, perKey: new Map() };
63
+ }
64
+ /**
65
+ * Folds a batch of `count` samples averaging `batchMean` into `entry` (docs/progressive-optimizer.md
66
+ * §3.4): with `n` samples already held the batch weighs `min(1, count / min(n + count, WINDOW))` —
67
+ * the exact running mean up to the window, 1/32 per sample past it, and a batch at least the
68
+ * window's size replaces the mean outright.
69
+ */
70
+ function foldRowsPerKey(entry, batchMean, count) {
71
+ const weight = Math.min(1, count / Math.min(entry.samples + count, ROWS_PER_KEY_WINDOW));
72
+ entry.mean += (batchMean - entry.mean) * weight;
73
+ entry.samples += count;
74
+ }
75
+ /** Cap on the cooldown's doubling: re-plans past the seventh wait `64 × replanCooldown` executions. */
76
+ const MAX_COOLDOWN_DOUBLINGS = 6;
77
+ /**
78
+ * One prepared statement's feedback re-plan cooldown (docs/progressive-optimizer.md §3.6).
79
+ * A shift marks the cached plan; the mark is acted on at an execution start, never
80
+ * mid-execution. The first feedback re-plan is immediate; re-plan `k + 1` waits until the
81
+ * statement has executed `cooldown × 2^min(k − 1, 6)` times since re-plan `k` — a mark
82
+ * arriving sooner stays pending until then.
83
+ */
84
+ export class FeedbackReplanState {
85
+ marked = false;
86
+ /** Feedback re-plans so far. */
87
+ replans = 0;
88
+ /** Executions started since the last feedback re-plan, the re-planning one included. */
89
+ executionsSinceReplan = 0;
90
+ /** A table the cached plan reads shifted. */
91
+ markShift() {
92
+ this.marked = true;
93
+ }
94
+ /** The cached plan was dropped for any reason; whatever compiles next reads the current overlay. */
95
+ onPlanDropped() {
96
+ this.marked = false;
97
+ }
98
+ /** Counts one execution; true when the marked plan must be dropped before it runs. */
99
+ onExecutionStart(cooldown) {
100
+ const due = this.marked && (this.replans === 0 || this.executionsSinceReplan >= this.requiredExecutions(cooldown));
101
+ if (due) {
102
+ this.marked = false;
103
+ this.replans++;
104
+ this.executionsSinceReplan = 0;
105
+ }
106
+ this.executionsSinceReplan++;
107
+ return due;
108
+ }
109
+ requiredExecutions(cooldown) {
110
+ return cooldown * 2 ** Math.min(this.replans - 1, MAX_COOLDOWN_DOUBLINGS);
111
+ }
112
+ }
113
+ /**
114
+ * The planned sizes, as of one compile, of the tables the plan reads whose module reports
115
+ * its own count (docs/progressive-optimizer.md §3.6). Such a count moves on every write
116
+ * with no event the planner hears, and a plan that no longer reads the table in full
117
+ * never produces an observation, so nothing else notices that a table planned at 10 rows
118
+ * now holds a million. A prepared statement compares its snapshot with the current
119
+ * planned sizes at each execution start and treats a drift like an overlay shift.
120
+ *
121
+ * Planned sizes, not raw module answers, are compared, so an approximate count the
122
+ * overlay outranks drifts only when what planning would use drifts.
123
+ */
124
+ export class ReportedSizeSnapshot {
125
+ sizes;
126
+ static empty = new ReportedSizeSnapshot([]);
127
+ constructor(sizes) {
128
+ this.sizes = sizes;
129
+ }
130
+ /**
131
+ * Called right after a compile, in the same synchronous turn, so each size is the one
132
+ * the plan's table references were costed with. Tables whose module has no
133
+ * `getRowCount` are left out: overlay shifts and schema changes already cover them.
134
+ */
135
+ static capture(db, dependencies) {
136
+ // NOTE: write targets are kept too (dependencies do not record read vs write), so a
137
+ // prepared `insert` driving a bulk load re-plans at each 10× of its target, paced by
138
+ // the cooldown; if those re-plans ever show up in a profile, record dependency roles
139
+ // in the builder and keep only read tables here.
140
+ const sizes = [];
141
+ for (const dep of dependencies) {
142
+ if (dep.type !== 'table' || !dep.schemaName)
143
+ continue;
144
+ const table = db.schemaManager.findTable(dep.objectName, dep.schemaName);
145
+ if (table && moduleReportsRowCount(db, table))
146
+ sizes.push({ table, rows: currentPlannedRows(db, table) });
147
+ }
148
+ return sizes.length > 0 ? new ReportedSizeSnapshot(sizes) : ReportedSizeSnapshot.empty;
149
+ }
150
+ /**
151
+ * True when some table's planned size has moved `shiftFactor` from the captured one
152
+ * with the larger side above `minRows` — the overlay's shift rule (§3.4). A table whose
153
+ * catalog object was replaced is skipped: that schema change already dropped the plan.
154
+ */
155
+ drifted(db) {
156
+ if (this.sizes.length === 0)
157
+ return false;
158
+ const { shiftFactor, minRows } = db.optimizer.tuning.cardinalityFeedback;
159
+ for (const { table, rows } of this.sizes) {
160
+ if (db.schemaManager.findTable(table.name, table.schemaName) !== table)
161
+ continue;
162
+ const now = currentPlannedRows(db, table);
163
+ if (Math.max(now, rows) > minRows && rowCountSpread(now, rows) >= shiftFactor) {
164
+ debugLog('Reported size drift on %s: planned %d, now %d rows', tableKey(table), rows, now);
165
+ return true;
166
+ }
167
+ }
168
+ return false;
169
+ }
170
+ }
171
+ /** What planning would size `table` at now; an unknown size reads as `defaultRowEstimate`, as in the overlay's record policy. */
172
+ function currentPlannedRows(db, table) {
173
+ return plannedRowCount(table, db._rowCountSources) ?? db.optimizer.tuning.defaultRowEstimate;
174
+ }
175
+ export class CardinalityFeedbackManager {
176
+ ctx;
177
+ /**
178
+ * Lowercased `schema.table` → entry, the change-log / work-counter key convention.
179
+ * `Map` insertion order doubles as recency: a hit or a record re-inserts, so the
180
+ * first key is the least recently used.
181
+ */
182
+ entries = new Map();
183
+ /**
184
+ * Observations made inside the open transaction, held until it ends; same key as
185
+ * `entries`, last count and largest floor per table win. Bounded by the distinct
186
+ * tables one transaction observes.
187
+ */
188
+ pending = new Map();
189
+ /** {@link onRolledBack} calls so far; each execution's sink records it at start. */
190
+ rollbacks = 0;
191
+ unsubscribeSchemaChanges = null;
192
+ constructor(ctx) {
193
+ this.ctx = ctx;
194
+ this.subscribeToSchemaChanges();
195
+ }
196
+ observedRows(table) {
197
+ const key = tableKey(table);
198
+ const entry = this.entries.get(key);
199
+ if (!entry || entry.schema !== table)
200
+ return undefined;
201
+ this.touch(key, entry);
202
+ return entry;
203
+ }
204
+ /** The running mean for `columns` on `table`, under the same identity rule as {@link observedRows}; a hit refreshes the table's recency. */
205
+ observedRowsPerKey(table, columns) {
206
+ const key = tableKey(table);
207
+ const entry = this.entries.get(key);
208
+ if (!entry || entry.schema !== table)
209
+ return undefined;
210
+ const keyEntry = entry.perKey.get(columnSetKey(columns));
211
+ if (!keyEntry)
212
+ return undefined;
213
+ this.touch(key, entry);
214
+ return keyEntry.mean;
215
+ }
216
+ /**
217
+ * Offer one exact row count of `table`, observed by a complete enumeration of
218
+ * committed state. Applies the record policy (docs/progressive-optimizer.md §3.4):
219
+ * ignored when the schema object is superseded or when both the observation and the
220
+ * current estimate are small; otherwise recorded — clearing any floor, which the newer
221
+ * complete count supersedes — and reported through `onShift` when it has moved
222
+ * `shiftFactor` from the entry's baseline.
223
+ */
224
+ record(table, rows) {
225
+ if (this.isSuperseded(table))
226
+ return;
227
+ const policy = this.ctx.getTuning().cardinalityFeedback;
228
+ const key = tableKey(table);
229
+ const existing = this.validEntry(key, table);
230
+ // NOTE: an exactly module-sized table still records an entry, which `plannedRowCount`
231
+ // never reads while the module answers — one LRU slot each; if `maxTables` pressure
232
+ // ever matters, skip recording when the module's count is exact.
233
+ const before = this.plannedBefore(table, existing);
234
+ if (Math.max(before, rows) <= policy.minRows)
235
+ return;
236
+ const entry = this.upsert(key, existing ?? newEntry(table, before));
237
+ entry.rows = rows;
238
+ entry.atLeast = undefined;
239
+ debugLog('Recorded %d rows for %s (was %d, baseline %d)', rows, key, before, entry.baselineRows);
240
+ this.shiftIfMoved(key, entry, rows);
241
+ }
242
+ /**
243
+ * Offer one floor for `table`: a read of committed state yielded `rows` distinct rows of
244
+ * it, so it holds at least that many (docs/progressive-optimizer.md §3.4). Recorded only
245
+ * when it exceeds both what planning would use now and `minRows`, so a floor never
246
+ * lowers an estimate and never makes an unknown table look smaller than the default it
247
+ * plans at today. Shifts like a count; floors only raise, so they cannot oscillate.
248
+ */
249
+ recordAtLeast(table, rows) {
250
+ if (this.isSuperseded(table))
251
+ return;
252
+ const policy = this.ctx.getTuning().cardinalityFeedback;
253
+ const key = tableKey(table);
254
+ const existing = this.validEntry(key, table);
255
+ const before = this.plannedBefore(table, existing);
256
+ if (rows <= before || rows <= policy.minRows)
257
+ return;
258
+ const entry = this.upsert(key, existing ?? newEntry(table, before));
259
+ entry.atLeast = Math.max(entry.atLeast ?? 0, rows);
260
+ debugLog('Recorded at least %d rows for %s (was %d, baseline %d)', rows, key, before, entry.baselineRows);
261
+ this.shiftIfMoved(key, entry, rows);
262
+ }
263
+ /**
264
+ * Offer `count` samples of rows per key for `spec`'s column set on `table`, summing to
265
+ * `sum` rows — one sample per exhausted equality seek with non-NULL keys
266
+ * (docs/progressive-optimizer.md §3.4). Ignored under a superseded schema, and unless
267
+ * the table's planned size exceeds `minRows`: below that every plan finishes fast, and
268
+ * the gate keeps small-table plans unchanged exactly as the count gate does. So a table
269
+ * of unknown size learns rows per key only once its size is learned (a complete scan,
270
+ * a floor, or a module count above the gate); publication applies per-key batches
271
+ * after the same execution's counts and floors, so one execution can open the gate for
272
+ * itself. A new column-set entry's baseline is the rows per key the plan was priced
273
+ * with; the table remembers at most `maxKeySetsPerTable` sets, least recently recorded
274
+ * evicted. Accepted bias: frequently probed keys weigh more than a uniform sample would.
275
+ * Reported through `onShift` under the table's key when the folded mean has moved
276
+ * `shiftFactor` from the set's baseline — the count rule, applied to the mean.
277
+ */
278
+ recordRowsPerKey(table, spec, sum, count) {
279
+ if (count <= 0 || this.isSuperseded(table))
280
+ return;
281
+ const policy = this.ctx.getTuning().cardinalityFeedback;
282
+ const key = tableKey(table);
283
+ const existing = this.validEntry(key, table);
284
+ const before = this.plannedBefore(table, existing);
285
+ if (before <= policy.minRows)
286
+ return;
287
+ // NOTE: a set the catalog's statistics cover is recorded too, though `plannedRowsPerKey`
288
+ // never consults it under this schema object (an `ANALYZE` swaps the object before
289
+ // coverage can change), so under a stale catalog its first record can shift once and
290
+ // re-plan statements that land the same plan; if that re-plan ever shows in a profile,
291
+ // skip the record when `catalogCoversColumns` holds.
292
+ const entry = this.upsert(key, existing ?? newEntry(table, before));
293
+ const batchMean = sum / count;
294
+ let keyEntry = entry.perKey.get(spec.key);
295
+ if (keyEntry) {
296
+ entry.perKey.delete(spec.key);
297
+ foldRowsPerKey(keyEntry, batchMean, count);
298
+ }
299
+ else {
300
+ keyEntry = { columns: spec.columns, mean: batchMean, samples: count, baseline: spec.plannedRowsPerKey, shifts: 0 };
301
+ }
302
+ entry.perKey.set(spec.key, keyEntry);
303
+ for (const staleKey of entry.perKey.keys()) {
304
+ if (entry.perKey.size <= policy.maxKeySetsPerTable)
305
+ break;
306
+ entry.perKey.delete(staleKey);
307
+ }
308
+ debugLog('Recorded %d rows per key over %d samples for %s (%s) (mean now %d, baseline %d)', batchMean, count, key, spec.key, keyEntry.mean, keyEntry.baseline);
309
+ this.shiftIfRowsPerKeyMoved(key, spec.key, keyEntry);
310
+ }
311
+ /**
312
+ * Offer one finished execution's observations (docs/progressive-optimizer.md §3.5).
313
+ * A committed read (`readCommitted`) or an execution that ended with no transaction
314
+ * open saw committed state and is recorded now. Anything else may include the open
315
+ * transaction's uncommitted writes, so it is held for {@link onCommitted} — unless a
316
+ * rollback ran during the execution (typically a failing statement's own statement
317
+ * savepoint, which fires before publication): then a completed scan may have counted
318
+ * rows that no longer exist, and the whole execution is discarded.
319
+ */
320
+ publish(observations, options) {
321
+ if (options.readCommitted) {
322
+ this.recordAll(observations);
323
+ }
324
+ else if (observations.rollbacksAtStart !== this.rollbacks) {
325
+ debugLog('Discarded observations: work was rolled back during the execution');
326
+ }
327
+ else if (this.ctx.getAutocommit()) {
328
+ this.recordAll(observations);
329
+ }
330
+ else {
331
+ this.holdAll(observations);
332
+ }
333
+ }
334
+ /**
335
+ * A fresh per-execution sink, stamped so {@link publish} can tell whether a rollback ran
336
+ * under it, and carrying the record floor so it can drop floors that could never record.
337
+ */
338
+ beginObservations() {
339
+ return new CardinalityObservations(this.rollbacks, this.ctx.getTuning().cardinalityFeedback.minRows);
340
+ }
341
+ /**
342
+ * The open transaction committed: record what it held, except tables it wrote.
343
+ * Such an observation was made mid-transaction, possibly before later writes in the
344
+ * same transaction, and the change log cannot say which came first. `changedCounts` is
345
+ * the change log keyed like `entries` — every table the transaction wrote, even one
346
+ * whose writes cancelled out — and is not built when nothing is held.
347
+ */
348
+ onCommitted(changedCounts) {
349
+ // NOTE: external-change ingestion with `captureChanges: false` writes rows the change
350
+ // log never sees, so a count held from before such a batch is applied. Only an estimate
351
+ // lags; if those batches ever routinely shrink or grow tables, have them veto here too.
352
+ if (this.pending.size === 0)
353
+ return;
354
+ try {
355
+ const changed = changedCounts();
356
+ for (const [key, held] of this.pending) {
357
+ if (changed.has(key)) {
358
+ debugLog('Dropped observations of %s: the committing transaction wrote it', key);
359
+ continue;
360
+ }
361
+ this.recordHeld(held);
362
+ }
363
+ }
364
+ finally {
365
+ this.pending.clear();
366
+ }
367
+ }
368
+ /** The open transaction, or some of its work, was undone: forget everything held. */
369
+ onRolledBack() {
370
+ this.pending.clear();
371
+ this.rollbacks++;
372
+ }
373
+ /** Forget every observation, held ones included; later compiles read the catalog only. */
374
+ clear() {
375
+ this.entries.clear();
376
+ this.pending.clear();
377
+ }
378
+ /** Valid entries, by value, least recently used first. Does not refresh recency. */
379
+ snapshot() {
380
+ const out = [];
381
+ for (const entry of this.entries.values()) {
382
+ const { schema } = entry;
383
+ if (this.ctx.schemaManager.findTable(schema.name, schema.schemaName) !== schema)
384
+ continue;
385
+ out.push({
386
+ schemaName: schema.schemaName,
387
+ tableName: schema.name,
388
+ rows: entry.rows,
389
+ atLeast: entry.atLeast,
390
+ catalogRows: catalogRowCount(schema),
391
+ baselineRows: entry.baselineRows,
392
+ observations: entry.observations,
393
+ shifts: entry.shifts,
394
+ perKey: [...entry.perKey.values()].map(keyEntry => ({
395
+ keyColumns: keyEntry.columns.map(i => schema.columns[i].name),
396
+ rowsPerKey: keyEntry.mean,
397
+ samples: keyEntry.samples,
398
+ baselineRowsPerKey: keyEntry.baseline,
399
+ shifts: keyEntry.shifts,
400
+ })),
401
+ });
402
+ }
403
+ return out;
404
+ }
405
+ dispose() {
406
+ if (this.unsubscribeSchemaChanges) {
407
+ this.unsubscribeSchemaChanges();
408
+ this.unsubscribeSchemaChanges = null;
409
+ }
410
+ this.clear();
411
+ }
412
+ subscribeToSchemaChanges() {
413
+ const notifier = this.ctx.schemaManager.getChangeNotifier();
414
+ this.unsubscribeSchemaChanges = notifier.addListener((event) => {
415
+ // Keyed by `oldObject`, not the event's name: a rename reports the NEW name.
416
+ // `DETACH` fires no per-table events; its tables' entries never match again
417
+ // and age out under the LRU cap.
418
+ if (event.type === 'table_modified' || event.type === 'table_removed') {
419
+ this.entries.delete(tableKey(event.oldObject));
420
+ }
421
+ });
422
+ }
423
+ /**
424
+ * Exact counts first: a floor at or below the count just recorded is then ignored.
425
+ * Rows per key last, so a count or floor from the same execution can open its table-size gate.
426
+ */
427
+ recordAll(observations) {
428
+ for (const [table, rows] of observations.entries()) {
429
+ this.record(table, rows);
430
+ }
431
+ for (const [table, rows] of observations.lowerBounds()) {
432
+ this.recordAtLeast(table, rows);
433
+ }
434
+ for (const [table, { spec, sum, count }] of observations.rowsPerKey()) {
435
+ this.recordRowsPerKey(table, spec, sum, count);
436
+ }
437
+ }
438
+ holdAll(observations) {
439
+ for (const [table, rows] of observations.entries()) {
440
+ this.held(table).rows = rows;
441
+ }
442
+ for (const [table, rows] of observations.lowerBounds()) {
443
+ const held = this.held(table);
444
+ held.atLeast = Math.max(held.atLeast ?? 0, rows);
445
+ }
446
+ for (const [table, { spec, sum, count }] of observations.rowsPerKey()) {
447
+ const held = this.held(table).perKey;
448
+ const heldSamples = held.get(spec.key);
449
+ if (heldSamples) {
450
+ heldSamples.sum += sum;
451
+ heldSamples.count += count;
452
+ }
453
+ else {
454
+ held.set(spec.key, { spec, sum, count });
455
+ }
456
+ }
457
+ }
458
+ /** What is held for `table`; anything held under an older schema object for its name is superseded. */
459
+ held(table) {
460
+ const key = tableKey(table);
461
+ const existing = this.pending.get(key);
462
+ if (existing?.table === table)
463
+ return existing;
464
+ const fresh = { table, rows: undefined, atLeast: undefined, perKey: new Map() };
465
+ this.pending.set(key, fresh);
466
+ return fresh;
467
+ }
468
+ /** As {@link recordAll}: the count first, so a floor it already covers is ignored, and rows per key last. */
469
+ recordHeld({ table, rows, atLeast, perKey }) {
470
+ if (rows !== undefined)
471
+ this.record(table, rows);
472
+ if (atLeast !== undefined)
473
+ this.recordAtLeast(table, atLeast);
474
+ for (const { spec, sum, count } of perKey.values())
475
+ this.recordRowsPerKey(table, spec, sum, count);
476
+ }
477
+ isSuperseded(table) {
478
+ if (this.ctx.schemaManager.findTable(table.name, table.schemaName) === table)
479
+ return false;
480
+ debugLog('Ignored an observation of %s.%s: made under a superseded schema', table.schemaName, table.name);
481
+ return true;
482
+ }
483
+ /**
484
+ * What planning would use for `table` right now — `existing` ranked with the module's
485
+ * count and the catalog's (§3.3), else the default — so an exactly module-sized table
486
+ * compares against the module and a scan agreeing with it shifts nothing.
487
+ */
488
+ plannedBefore(table, existing) {
489
+ return plannedRowCount(table, {
490
+ observedRows: () => existing,
491
+ reportedRows: t => this.ctx.reportedRows(t),
492
+ }) ?? this.ctx.getTuning().defaultRowEstimate;
493
+ }
494
+ /** Counts one recorded observation on `entry`, makes it the most recent, and enforces the cap. */
495
+ upsert(key, entry) {
496
+ entry.observations++;
497
+ this.touch(key, entry);
498
+ this.evictBeyond(this.ctx.getTuning().cardinalityFeedback.maxTables);
499
+ return entry;
500
+ }
501
+ /** Reports a shift through `onShift` when `rows` has moved `shiftFactor` from the entry's baseline. */
502
+ shiftIfMoved(key, entry, rows) {
503
+ if (rowCountSpread(rows, entry.baselineRows) < this.ctx.getTuning().cardinalityFeedback.shiftFactor)
504
+ return;
505
+ log('Shift on %s: baseline %d -> %d rows', key, entry.baselineRows, rows);
506
+ entry.baselineRows = rows;
507
+ entry.shifts++;
508
+ this.ctx.onShift(key);
509
+ }
510
+ /**
511
+ * Reports a shift through `onShift` when a column set's mean has moved `shiftFactor`
512
+ * from its baseline. The table key is reported, not the set: a statement that reads the
513
+ * table re-plans and every seek node in it re-snapshots the overlay (§3.6). A set's first
514
+ * record cannot shift when its plan was already priced from the mean (the baseline is what
515
+ * the plan used); a set re-created after eviction carries the module's estimate again and
516
+ * may shift once, landing the same plan.
517
+ */
518
+ shiftIfRowsPerKeyMoved(key, setKey, keyEntry) {
519
+ if (rowCountSpread(keyEntry.mean, keyEntry.baseline) < this.ctx.getTuning().cardinalityFeedback.shiftFactor)
520
+ return;
521
+ log('Shift on %s (%s): rows per key baseline %d -> %d', key, setKey, keyEntry.baseline, keyEntry.mean);
522
+ keyEntry.baseline = keyEntry.mean;
523
+ keyEntry.shifts++;
524
+ this.ctx.onShift(key);
525
+ }
526
+ /** The entry under `key` if it was observed against `table`; a stale one is replaced on record. */
527
+ validEntry(key, table) {
528
+ const entry = this.entries.get(key);
529
+ return entry?.schema === table ? entry : undefined;
530
+ }
531
+ touch(key, entry) {
532
+ this.entries.delete(key);
533
+ this.entries.set(key, entry);
534
+ }
535
+ /**
536
+ * Drop least-recently-used entries past the cap. No `onShift`: plans already built
537
+ * keep their snapshot, and the next compile falls back to catalog or default numbers.
538
+ */
539
+ evictBeyond(maxTables) {
540
+ for (const key of this.entries.keys()) {
541
+ if (this.entries.size <= maxTables)
542
+ return;
543
+ this.entries.delete(key);
544
+ }
545
+ }
546
+ }
547
+ //# sourceMappingURL=database-cardinality-feedback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database-cardinality-feedback.js","sourceRoot":"","sources":["../../../src/core/database-cardinality-feedback.ts"],"names":[],"mappings":"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"}
@@ -41,6 +41,9 @@ export interface TransactionManagerContext {
41
41
  /** Called after a successful commit, before the change log is cleared. The callback
42
42
  * materializes per-table committed row counts only if a consumer wants them. */
43
43
  recordCommittedChangeCounts(counts: () => Map<string, number>): void;
44
+ /** Called when work of the open transaction is undone: a rollback, a failed commit,
45
+ * or a `rollback to savepoint`. Bookkeeping only — errors are logged, never thrown. */
46
+ transactionRolledBack(): void;
44
47
  }
45
48
  /**
46
49
  * Op kind for a captured row change.
@@ -126,6 +129,8 @@ export declare class TransactionManager {
126
129
  * Rolls back the current transaction on all connections.
127
130
  */
128
131
  rollbackTransaction(): Promise<void>;
132
+ /** Tell the context work was undone, isolated like commit bookkeeping. */
133
+ private notifyRolledBack;
129
134
  /**
130
135
  * Ensures we're in a transaction. If in autocommit mode, starts an implicit transaction.
131
136
  */
@@ -220,8 +225,10 @@ export declare class TransactionManager {
220
225
  * so the whole reading is O(tables × layers) with no scan.
221
226
  *
222
227
  * Inherits the change log's coalescing — ten updates to one row count as one,
223
- * and an insert followed by a delete of the same key leaves no entry at all.
224
- * That makes this a *distinct rows touched* measure.
228
+ * and an insert followed by a delete of the same key counts zero. That makes
229
+ * this a *distinct rows touched* measure. A table written whose changes all
230
+ * cancelled out still appears, with count 0: the key set is every table the
231
+ * transaction wrote, which held cardinality observations rely on.
225
232
  *
226
233
  * Deliberately approximate across layers: the same key changed in two live
227
234
  * savepoint layers is counted twice. Deduplicating would cost a scan of every
@@ -1 +1 @@
1
- {"version":3,"file":"database-transaction.d.ts","sourceRoot":"","sources":["../../../src/core/database-transaction.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"database-transaction.d.ts","sourceRoot":"","sources":["../../../src/core/database-transaction.ts"],"names":[],"mappings":"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"}