@fjader/svelte 0.2.4 → 0.2.5
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/README.md +1 -1
- package/dist/animation/EntranceGate.d.ts +52 -0
- package/dist/animation/EntranceGate.js +93 -0
- package/dist/animation/TransitionClock.d.ts +61 -30
- package/dist/animation/TransitionClock.js +67 -29
- package/dist/animation/transition-log.d.ts +41 -0
- package/dist/animation/transition-log.js +57 -0
- package/dist/components/axes/AxisBottom.svelte +4 -2
- package/dist/components/axes/AxisCenter.svelte +4 -2
- package/dist/components/axes/AxisLeft.svelte +4 -2
- package/dist/components/axes/BandAxisTicks.svelte +3 -2
- package/dist/components/charts/ChartCell.svelte +32 -5
- package/dist/components/charts/ChartCell.svelte.d.ts +9 -0
- package/dist/components/charts/ChartContainer.svelte +45 -3
- package/dist/components/charts/ChartContainer.svelte.d.ts +7 -1
- package/dist/components/charts/ChartHover.svelte.d.ts +14 -0
- package/dist/components/charts/ChartHover.svelte.js +22 -0
- package/dist/components/charts/ChartVisibility.svelte.d.ts +43 -0
- package/dist/components/charts/ChartVisibility.svelte.js +67 -0
- package/dist/components/guides/Grid.svelte +12 -1
- package/dist/components/marks/AreaMarkX.svelte +16 -4
- package/dist/components/marks/AreaMarkY.svelte +16 -4
- package/dist/components/marks/BarMarkX.svelte +7 -3
- package/dist/components/marks/BarMarkY.svelte +7 -3
- package/dist/components/marks/DotsMark.svelte +6 -3
- package/dist/components/marks/LineMark.svelte +11 -8
- package/dist/components/marks/ParallelCoordinatesMark.svelte +7 -2
- package/dist/components/marks/ParallelCoordinatesMark.svelte.d.ts +2 -0
- package/dist/components/marks/RectMark.svelte +6 -3
- package/dist/components/marks/RectXMark.svelte +7 -3
- package/dist/components/marks/RectYMark.svelte +7 -3
- package/dist/components/marks/RuleMarkX.svelte +30 -26
- package/dist/components/marks/RuleMarkY.svelte +30 -26
- package/dist/components/marks/TextMark.svelte +44 -5
- package/dist/components/marks/lifecycle/MarkLifecycleV2.svelte.d.ts +16 -0
- package/dist/components/marks/lifecycle/MarkLifecycleV2.svelte.js +398 -54
- package/dist/components/marks/lifecycle/domain-queries.d.ts +11 -2
- package/dist/components/marks/lifecycle/domain-queries.js +33 -6
- package/dist/components/marks/lifecycle/domain-registration.d.ts +6 -1
- package/dist/components/marks/lifecycle/domain-registration.js +15 -14
- package/dist/components/marks/lifecycle/other-rows.svelte.d.ts +9 -1
- package/dist/components/marks/lifecycle/other-rows.svelte.js +2 -2
- package/dist/components/marks/lifecycle/query-builder.d.ts +27 -2
- package/dist/components/marks/lifecycle/query-builder.js +23 -20
- package/dist/components/marks/utils/MarkColor.svelte.d.ts +3 -1
- package/dist/components/marks/utils/MarkColor.svelte.js +33 -3
- package/dist/components/marks/utils/MarkSeries.svelte.d.ts +14 -1
- package/dist/components/marks/utils/MarkSeries.svelte.js +25 -1
- package/dist/components/marks/utils/MarkSize.svelte.js +4 -0
- package/dist/components/marks/utils/reactive-config.d.ts +1 -1
- package/dist/components/marks/utils/reactive-config.js +3 -0
- package/dist/components/rendering/Areas.svelte +57 -19
- package/dist/components/rendering/Areas.svelte.d.ts +12 -0
- package/dist/components/rendering/BaseGPURenderer.svelte.d.ts +1 -1
- package/dist/components/rendering/Dots.svelte +23 -3
- package/dist/components/rendering/Dots.svelte.d.ts +6 -0
- package/dist/components/rendering/GridLine.svelte +13 -1
- package/dist/components/rendering/GridLine.svelte.d.ts +5 -0
- package/dist/components/rendering/Lines.svelte +48 -13
- package/dist/components/rendering/Lines.svelte.d.ts +12 -0
- package/dist/components/rendering/ParallelLines.svelte +5 -5
- package/dist/components/rendering/Rects.svelte +51 -11
- package/dist/components/rendering/Rects.svelte.d.ts +16 -2
- package/dist/components/rendering/RuleX.svelte +1 -1
- package/dist/components/rendering/RuleY.svelte +1 -1
- package/dist/components/rendering/WebGPUCanvas.svelte +4 -2
- package/dist/components/rendering/activity-reads.d.ts +41 -24
- package/dist/components/rendering/activity-reads.js +54 -31
- package/dist/components/rendering/uniform-sizes.d.ts +1 -1
- package/dist/components/rendering/uniform-sizes.js +1 -1
- package/dist/config/ChartConfig.svelte.d.ts +7 -0
- package/dist/config/ChartConfig.svelte.js +17 -0
- package/dist/gpu/GPUCoordinator.svelte.d.ts +31 -1
- package/dist/gpu/GPUCoordinator.svelte.js +164 -7
- package/dist/gpu/MorphedChannels.d.ts +11 -2
- package/dist/gpu/MorphedChannels.js +33 -11
- package/dist/gpu/ScaleTemplateSystem.d.ts +20 -2
- package/dist/gpu/ScaleTemplateSystem.js +58 -2
- package/dist/index.d.ts +17 -4
- package/dist/index.js +19 -4
- package/dist/interactors/TooltipManager.svelte.js +14 -5
- package/dist/query-engine/CrossfilterSelection.svelte.d.ts +4 -2
- package/dist/query-engine/CrossfilterSelection.svelte.js +2 -0
- package/dist/query-engine/FieldActivity.svelte.d.ts +2 -3
- package/dist/query-engine/FieldActivity.svelte.js +1 -2
- package/dist/query-engine/MarkHandle.svelte.d.ts +28 -1
- package/dist/query-engine/MarkHandle.svelte.js +33 -1
- package/dist/query-engine/QueryEngine.d.ts +225 -5
- package/dist/query-engine/QueryEngine.js +671 -41
- package/dist/query-engine/categorical-identity.d.ts +34 -8
- package/dist/query-engine/categorical-identity.js +138 -73
- package/dist/query-engine/debug/query-log.d.ts +39 -0
- package/dist/query-engine/debug/query-log.js +90 -0
- package/dist/query-engine/duckdb.d.ts +55 -8
- package/dist/query-engine/duckdb.js +82 -30
- package/dist/query-engine/index.d.ts +7 -4
- package/dist/query-engine/index.js +3 -3
- package/dist/query-engine/preagg/BuildQueue.d.ts +33 -13
- package/dist/query-engine/preagg/BuildQueue.js +51 -15
- package/dist/query-engine/preagg/Preagg.d.ts +46 -3
- package/dist/query-engine/preagg/Preagg.js +159 -31
- package/dist/query-engine/preagg/plan.d.ts +28 -1
- package/dist/query-engine/preagg/plan.js +128 -8
- package/dist/query-engine/sliced-lane.d.ts +108 -0
- package/dist/query-engine/sliced-lane.js +299 -0
- package/dist/query-engine/source-routing.d.ts +106 -0
- package/dist/query-engine/source-routing.js +189 -0
- package/dist/scales/BandScaleState.svelte.d.ts +9 -1
- package/dist/scales/BandScaleState.svelte.js +16 -5
- package/dist/scales/ChartScales.svelte.d.ts +3 -0
- package/dist/scales/ChartScales.svelte.js +26 -8
- package/dist/scales/ColorScaleState.svelte.d.ts +18 -2
- package/dist/scales/ColorScaleState.svelte.js +138 -26
- package/dist/scales/LinearScaleState.svelte.d.ts +7 -10
- package/dist/scales/LinearScaleState.svelte.js +21 -39
- package/dist/scales/ScaleGeneration.svelte.d.ts +48 -0
- package/dist/scales/ScaleGeneration.svelte.js +42 -0
- package/dist/scales/ScaleRegistry.svelte.js +3 -1
- package/dist/scales/SlotTransition.d.ts +15 -1
- package/dist/scales/SlotTransition.js +33 -4
- package/dist/scales/TimeScaleState.svelte.d.ts +7 -3
- package/dist/scales/TimeScaleState.svelte.js +7 -7
- package/dist/scales/color-utils.d.ts +0 -3
- package/dist/scales/color-utils.js +0 -3
- package/dist/scales/entered.d.ts +8 -0
- package/dist/scales/entered.js +10 -0
- package/dist/spec/LazyQueryEngine.js +2 -19
- package/dist/spec/MarkRegistry.d.ts +3 -1
- package/dist/spec/MarkRegistry.js +13 -1
- package/dist/spec/PlotFromSpec.svelte +1 -0
- package/dist/spec/export.js +11 -2
- package/dist/spec/types.d.ts +41 -13
- package/dist/sql/bin.d.ts +25 -0
- package/dist/sql/bin.js +108 -5
- package/dist/transforms/TransformCompiler.d.ts +10 -0
- package/dist/transforms/TransformCompiler.js +26 -0
- package/dist/transforms/index.js +144 -24
- package/dist/types.d.ts +136 -2
- package/package.json +2 -2
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { ClockLoop } from '../animation';
|
|
2
2
|
import { ActivityTable } from '../scales/ActivityTable';
|
|
3
3
|
import type { FieldIdentity } from './categorical-identity';
|
|
4
|
-
/** What a FieldActivity needs from the page around it. */
|
|
5
4
|
/** One mark's Other rows for one bucket: what a click on it selects. */
|
|
6
5
|
export interface OtherEntry {
|
|
7
6
|
/** The mark's filter group, or null when it is filtered by the selection (`'filter'`). */
|
|
@@ -17,6 +16,7 @@ export interface OtherClick {
|
|
|
17
16
|
action: 'replace' | 'add' | 'remove';
|
|
18
17
|
values: unknown[];
|
|
19
18
|
}
|
|
19
|
+
/** What a FieldActivity needs from the page around it. */
|
|
20
20
|
export interface FieldActivityHost {
|
|
21
21
|
/** Drives the fades; null in unit tests and before a coordinator exists, and fades land at once. */
|
|
22
22
|
readonly loop: ClockLoop | null;
|
|
@@ -49,8 +49,7 @@ export declare const DETACHED_HOST: FieldActivityHost;
|
|
|
49
49
|
* existing ids keep their fades while new ones start in their state.
|
|
50
50
|
* `reconcile` runs from the packer and from `set`, never from a reader, so
|
|
51
51
|
* nothing is resized or retargeted while a template renders.
|
|
52
|
-
|
|
53
|
-
/**
|
|
52
|
+
*
|
|
54
53
|
* THE FREE SLOT. Each group's table holds one slot past the field's ids: 1 while
|
|
55
54
|
* the group selects nothing on the field, 0 while it selects anything, faded on
|
|
56
55
|
* the same clock as every id. The shader reads it as the last slot of the
|
|
@@ -44,8 +44,7 @@ class GroupFade {
|
|
|
44
44
|
* existing ids keep their fades while new ones start in their state.
|
|
45
45
|
* `reconcile` runs from the packer and from `set`, never from a reader, so
|
|
46
46
|
* nothing is resized or retargeted while a template renders.
|
|
47
|
-
|
|
48
|
-
/**
|
|
47
|
+
*
|
|
49
48
|
* THE FREE SLOT. Each group's table holds one slot past the field's ids: 1 while
|
|
50
49
|
* the group selects nothing on the field, 0 while it selects anything, faded on
|
|
51
50
|
* the same clock as every id. The shader reads it as the last slot of the
|
|
@@ -15,15 +15,42 @@ export interface QueryParams {
|
|
|
15
15
|
sort?: NormalizedSortConfig;
|
|
16
16
|
limit?: number;
|
|
17
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Why a result was queried. `catchUp`: the mark came back into view stale (see
|
|
20
|
+
* `active`), so the result brings it up to date with changes it missed, which
|
|
21
|
+
* nobody just made; it lands without animating. `update`: anything else.
|
|
22
|
+
*/
|
|
23
|
+
export type ResultCause = 'update' | 'catchUp';
|
|
18
24
|
export declare class MarkHandle {
|
|
19
25
|
#private;
|
|
20
26
|
arrowTable: Table<import("@uwdata/flechette").TypeMap>;
|
|
21
27
|
dataVersion: number;
|
|
28
|
+
/**
|
|
29
|
+
* The cause of the result `dataVersion` counts, set with it. Plain, not
|
|
30
|
+
* $state: read by whatever reacts to `dataVersion`, never on its own.
|
|
31
|
+
*/
|
|
32
|
+
resultCause: ResultCause;
|
|
22
33
|
error: Error;
|
|
23
34
|
get params(): QueryParams;
|
|
24
35
|
/** Called by mark lifecycle when sort/limit change. */
|
|
25
36
|
updateParams(params: QueryParams): void;
|
|
26
37
|
_onParamsChange: (() => void) | null;
|
|
38
|
+
/**
|
|
39
|
+
* Whether the mark is on screen (or about to be). The engine does not
|
|
40
|
+
* re-query an inactive mark that has its first result: a filter or params
|
|
41
|
+
* change only marks it stale, and it queries once, with whatever is current,
|
|
42
|
+
* when it becomes active again. Its first query always runs, since the
|
|
43
|
+
* first result can feed domains other charts share. Not reactive: the
|
|
44
|
+
* engine reads it when it would send.
|
|
45
|
+
*/
|
|
46
|
+
get active(): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Returns whether this call sent a catch-up query: the mark came back
|
|
49
|
+
* stale. A return with no query means the data it holds is current, so
|
|
50
|
+
* the caller can act on its return now rather than after a result.
|
|
51
|
+
*/
|
|
52
|
+
setActive(active: boolean): boolean;
|
|
53
|
+
_onActivate: (() => boolean) | null;
|
|
27
54
|
/**
|
|
28
55
|
* Engine-internal: called to deliver query results.
|
|
29
56
|
*
|
|
@@ -33,7 +60,7 @@ export declare class MarkHandle {
|
|
|
33
60
|
* The error is cleared either way, so a success after a failure still
|
|
34
61
|
* clears it.
|
|
35
62
|
*/
|
|
36
|
-
_setResult(table: Table): void;
|
|
63
|
+
_setResult(table: Table, cause?: ResultCause): void;
|
|
37
64
|
/** Engine-internal: called on query error. */
|
|
38
65
|
_setError(error: Error): void;
|
|
39
66
|
/** Clean up registration. Set by engine during registerMark. */
|
|
@@ -8,6 +8,11 @@
|
|
|
8
8
|
export class MarkHandle {
|
|
9
9
|
arrowTable = $state(null);
|
|
10
10
|
dataVersion = $state(0);
|
|
11
|
+
/**
|
|
12
|
+
* The cause of the result `dataVersion` counts, set with it. Plain, not
|
|
13
|
+
* $state: read by whatever reacts to `dataVersion`, never on its own.
|
|
14
|
+
*/
|
|
15
|
+
resultCause = 'update';
|
|
11
16
|
error = $state(null);
|
|
12
17
|
#params = $state({ sort: undefined, limit: undefined });
|
|
13
18
|
get params() {
|
|
@@ -21,6 +26,32 @@ export class MarkHandle {
|
|
|
21
26
|
// Engine sets this callback during registration.
|
|
22
27
|
// Conventional underscore — engine needs external access.
|
|
23
28
|
_onParamsChange = null;
|
|
29
|
+
/**
|
|
30
|
+
* Whether the mark is on screen (or about to be). The engine does not
|
|
31
|
+
* re-query an inactive mark that has its first result: a filter or params
|
|
32
|
+
* change only marks it stale, and it queries once, with whatever is current,
|
|
33
|
+
* when it becomes active again. Its first query always runs, since the
|
|
34
|
+
* first result can feed domains other charts share. Not reactive: the
|
|
35
|
+
* engine reads it when it would send.
|
|
36
|
+
*/
|
|
37
|
+
get active() {
|
|
38
|
+
return this.#active;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Returns whether this call sent a catch-up query: the mark came back
|
|
42
|
+
* stale. A return with no query means the data it holds is current, so
|
|
43
|
+
* the caller can act on its return now rather than after a result.
|
|
44
|
+
*/
|
|
45
|
+
setActive(active) {
|
|
46
|
+
if (active === this.#active)
|
|
47
|
+
return false;
|
|
48
|
+
this.#active = active;
|
|
49
|
+
return active ? (this._onActivate?.() ?? false) : false;
|
|
50
|
+
}
|
|
51
|
+
#active = true;
|
|
52
|
+
// Engine sets this during registration: query a mark that went stale, and
|
|
53
|
+
// say whether it did.
|
|
54
|
+
_onActivate = null;
|
|
24
55
|
/**
|
|
25
56
|
* Engine-internal: called to deliver query results.
|
|
26
57
|
*
|
|
@@ -30,10 +61,11 @@ export class MarkHandle {
|
|
|
30
61
|
* The error is cleared either way, so a success after a failure still
|
|
31
62
|
* clears it.
|
|
32
63
|
*/
|
|
33
|
-
_setResult(table) {
|
|
64
|
+
_setResult(table, cause = 'update') {
|
|
34
65
|
this.error = null;
|
|
35
66
|
if (table === this.arrowTable)
|
|
36
67
|
return;
|
|
68
|
+
this.resultCause = cause;
|
|
37
69
|
this.arrowTable = table;
|
|
38
70
|
this.dataVersion++;
|
|
39
71
|
}
|
|
@@ -20,9 +20,11 @@
|
|
|
20
20
|
import { type Table } from '@uwdata/flechette';
|
|
21
21
|
export type { BrushActivation } from './sufficient-statistics';
|
|
22
22
|
import { type QueryParts } from '../components/marks/lifecycle/query-builder';
|
|
23
|
+
import { type BuildEvent } from './preagg/Preagg';
|
|
23
24
|
import type { ActivationSource } from './preagg/plan';
|
|
24
25
|
export type { ActiveDim, ActivationSource } from './preagg/plan';
|
|
25
26
|
import { MarkHandle } from './MarkHandle.svelte';
|
|
27
|
+
import { type LaneHold, type SlicedLane } from './sliced-lane';
|
|
26
28
|
import { type DimValue, type FieldIdentity, type IdentityField, type SyntheticId } from './categorical-identity';
|
|
27
29
|
import type { FilterGroup } from './FilterGroup.svelte';
|
|
28
30
|
import { type Clause, type MarkRoute } from './CrossfilterSelection.svelte';
|
|
@@ -33,13 +35,141 @@ export interface QueryOpts {
|
|
|
33
35
|
callerId?: string;
|
|
34
36
|
/** AbortSignal for external cancellation. */
|
|
35
37
|
signal?: AbortSignal;
|
|
36
|
-
/**
|
|
37
|
-
*
|
|
38
|
+
/**
|
|
39
|
+
* Result caching, and sharing an identical query already running.
|
|
40
|
+
*
|
|
41
|
+
* - Mark queries (with a `callerId`): on by default; `false` for queries
|
|
42
|
+
* against tables whose contents change without the SQL changing.
|
|
43
|
+
* - Ad-hoc queries (no `callerId`): off unless `true`, so an app re-reading
|
|
44
|
+
* a table it writes to sees its writes. fjader's own setup queries pass
|
|
45
|
+
* `true`: they read base tables, which change only on a data reload, after
|
|
46
|
+
* which `clearQueryCache()` is the contract.
|
|
47
|
+
*
|
|
48
|
+
* The key includes the dims' version (see #cacheKey).
|
|
49
|
+
*/
|
|
38
50
|
cache?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Who is waiting for it; see StatementClass. Default 'interaction'.
|
|
53
|
+
*
|
|
54
|
+
* `'background'` runs on another connection when the engine has one (a
|
|
55
|
+
* sliced lane on DuckDB-WASM), so a TEMP table created with `exec` on the
|
|
56
|
+
* main connection is invisible there and the query fails: pass
|
|
57
|
+
* `connectionLocal: true` for statements on connection-local state.
|
|
58
|
+
*/
|
|
59
|
+
class?: StatementClass;
|
|
60
|
+
/** Reads or writes connection-local state; see StatementPlacement. */
|
|
61
|
+
connectionLocal?: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* The table this read reads (base table, view or preagg table). An
|
|
64
|
+
* interaction read with one is routed by its source's cost (see
|
|
65
|
+
* SourceRouting): known-fast on the main connection, unknown or slow sliced
|
|
66
|
+
* on that source's lane. Without one it stays on the main connection.
|
|
67
|
+
*/
|
|
68
|
+
source?: string;
|
|
69
|
+
/** A mark's data read: its cost updates the source's record. */
|
|
70
|
+
data?: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* This read is known to be slow (a heavy query on whatever table, as a
|
|
73
|
+
* mark with `holdsEntrance={false}` says). The engine reads it where a
|
|
74
|
+
* slow read cannot hold up others (on DuckDB-WASM, sliced on its source's
|
|
75
|
+
* lane) and does not learn the source's cost from it: the source's other
|
|
76
|
+
* reads may be quick. A backend with one connection can ignore it.
|
|
77
|
+
*/
|
|
78
|
+
slow?: boolean;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Where a statement may run, beside who waits for it.
|
|
82
|
+
*
|
|
83
|
+
* `connectionLocal`: it reads or writes state that belongs to one connection
|
|
84
|
+
* (a TEMP table, a session setting), so it stays on the main connection
|
|
85
|
+
* whatever its class. fjader's tooltip tables are TEMP: their writes, drops,
|
|
86
|
+
* hover lookups and the fits that read them pass it. Each table is written
|
|
87
|
+
* through one connection only, so statements on it keep their order. A
|
|
88
|
+
* backend with one connection, or truly shared state, can ignore it.
|
|
89
|
+
*/
|
|
90
|
+
export interface StatementPlacement {
|
|
91
|
+
class: StatementClass;
|
|
92
|
+
connectionLocal?: boolean;
|
|
93
|
+
/** See QueryOpts.source. */
|
|
94
|
+
source?: string;
|
|
95
|
+
/** See QueryOpts.data. */
|
|
96
|
+
data?: boolean;
|
|
97
|
+
/**
|
|
98
|
+
* When the read was asked for (query() called): for a mark's
|
|
99
|
+
* execute-latest read, the state it reflects. Recorded, for data age.
|
|
100
|
+
*/
|
|
101
|
+
requestedAt?: number;
|
|
102
|
+
/** The caller (a mark's id), for the log. */
|
|
103
|
+
callerId?: string;
|
|
104
|
+
/** See QueryOpts.slow. */
|
|
105
|
+
slow?: boolean;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Who is waiting for a statement. Callers state a class, never a connection:
|
|
109
|
+
* which connection (or later, which backend) serves it is the engine's
|
|
110
|
+
* business, decided in one place, `#send`.
|
|
111
|
+
*
|
|
112
|
+
* - `'interaction'`: someone is looking at the result or about to: mark data,
|
|
113
|
+
* hover lookups, a mark's setup (domains, dims). The default.
|
|
114
|
+
* - `'background'`: nobody waits for it directly: preagg builds, tooltip-table
|
|
115
|
+
* writes, cleanup. On DuckDB-WASM it runs on a sliced lane (another
|
|
116
|
+
* connection, see SlicedLane) unless `connectionLocal`, so a slow build no
|
|
117
|
+
* longer holds up interaction. Without a lane, preagg builds yield to
|
|
118
|
+
* interaction statements, not to each other's background work.
|
|
119
|
+
*/
|
|
120
|
+
export type StatementClass = 'interaction' | 'background';
|
|
121
|
+
/**
|
|
122
|
+
* For `observeIdentityRequests`: a mark asking for categorical identity
|
|
123
|
+
* columns, or a table's drain starting (when its dims actually begin to build,
|
|
124
|
+
* which is what a chart's first read waits on).
|
|
125
|
+
*/
|
|
126
|
+
export interface IdentityRequest {
|
|
127
|
+
/** 'request': a mark's ensureColumns call; 'drain': one pass of a table's drain started. */
|
|
128
|
+
kind: 'request' | 'drain';
|
|
129
|
+
table: string;
|
|
130
|
+
/** For a request, the fields asked for; for a drain pass, the fields it took. */
|
|
131
|
+
fields: string[];
|
|
132
|
+
/** performance.now() when asked. */
|
|
133
|
+
time: number;
|
|
134
|
+
}
|
|
135
|
+
/** One statement as it reached the connection, for `observeStatements`. */
|
|
136
|
+
export interface StatementRecord {
|
|
137
|
+
sql: string;
|
|
138
|
+
/** How it was sent: a query returning rows, a statement, a DESCRIBE, an Arrow insert. */
|
|
139
|
+
kind: 'query' | 'exec' | 'describe' | 'insert' | 'batch';
|
|
140
|
+
/** For a batch (execBatch): how many statements it ran as one message. */
|
|
141
|
+
count?: number;
|
|
142
|
+
class: StatementClass;
|
|
143
|
+
/** Which connection ran it: the main one, or a sliced lane. */
|
|
144
|
+
connection: 'main' | 'lane';
|
|
145
|
+
/** The source it was routed by, when it named one. */
|
|
146
|
+
source?: string;
|
|
147
|
+
/**
|
|
148
|
+
* When the read was asked for (StatementPlacement.requestedAt). With
|
|
149
|
+
* `end`, how old the state a result reflects is when it lands.
|
|
150
|
+
*/
|
|
151
|
+
requested?: number;
|
|
152
|
+
/** Who asked (a mark's id), when it said. */
|
|
153
|
+
caller?: string;
|
|
154
|
+
/** performance.now() when handed to the connection, and when it settled. */
|
|
155
|
+
start: number;
|
|
156
|
+
end: number;
|
|
157
|
+
error?: unknown;
|
|
39
158
|
}
|
|
40
159
|
export interface QueryEngineOptions {
|
|
41
160
|
/** Overrides BUILD_MAX_WAIT_MS; tests use it to make the queue deterministic. */
|
|
42
161
|
buildMaxWaitMs?: number;
|
|
162
|
+
/**
|
|
163
|
+
* Debug. Send an execBatch's statements one by one, for per-statement
|
|
164
|
+
* timing. It changes what it measures: each statement then re-enters the
|
|
165
|
+
* queue behind whatever was sent meanwhile, which a batch avoids.
|
|
166
|
+
*/
|
|
167
|
+
unbatch?: boolean;
|
|
168
|
+
/**
|
|
169
|
+
* Advanced. While the main connection works, all sliced lanes together get
|
|
170
|
+
* one slice per this many ms (see SLICE_SHARE_MS, the default).
|
|
171
|
+
*/
|
|
172
|
+
sliceShareMs?: number;
|
|
43
173
|
}
|
|
44
174
|
export interface ColumnInfo {
|
|
45
175
|
name: string;
|
|
@@ -58,11 +188,15 @@ export declare function buildSchemaMap(columns: ColumnInfo[]): Map<string, Colum
|
|
|
58
188
|
/**
|
|
59
189
|
* Minimal connection interface.
|
|
60
190
|
* Supports two query paths:
|
|
61
|
-
* - queryIPC (fast): returns raw Arrow IPC bytes, decoded by flechette
|
|
191
|
+
* - queryIPC (fast): returns raw Arrow IPC bytes, decoded by flechette into typed arrays
|
|
62
192
|
* - query (fallback): returns a Table directly (for mocks/testing)
|
|
63
193
|
*/
|
|
64
194
|
export interface DuckDBConnection {
|
|
65
|
-
/**
|
|
195
|
+
/**
|
|
196
|
+
* Fast path: raw Arrow IPC bytes → flechette tableFromIPC → typed arrays. Views on
|
|
197
|
+
* the bytes within one record batch (~2k rows from DuckDB-WASM); past that,
|
|
198
|
+
* flechette concatenates each column once.
|
|
199
|
+
*/
|
|
66
200
|
queryIPC?(sql: string): Promise<Uint8Array>;
|
|
67
201
|
/** Fallback query path. Used when queryIPC is not available (mocks, testing). */
|
|
68
202
|
query(sql: string): Promise<Table>;
|
|
@@ -75,6 +209,17 @@ export interface DuckDBConnection {
|
|
|
75
209
|
name: string;
|
|
76
210
|
create: boolean;
|
|
77
211
|
}): Promise<void>;
|
|
212
|
+
/**
|
|
213
|
+
* Open another connection on the same database whose statements run
|
|
214
|
+
* sliced (see SlicedLane): a slow read there no longer blocks this
|
|
215
|
+
* connection's queries. DuckDB-WASM via `connectionFrom`; a connection
|
|
216
|
+
* without it keeps everything on itself. The engine opens lanes itself and
|
|
217
|
+
* sends through them from `#send`, so every statement keeps its record,
|
|
218
|
+
* class and accounting; nothing hands a raw lane to an app.
|
|
219
|
+
*/
|
|
220
|
+
openSlicedLane?(options?: {
|
|
221
|
+
hold?: LaneHold;
|
|
222
|
+
}): Promise<SlicedLane>;
|
|
78
223
|
}
|
|
79
224
|
export interface QueryDescriptor {
|
|
80
225
|
/** The table the mark queries: its identity view when it has categorical channels. */
|
|
@@ -86,7 +231,29 @@ export interface QueryDescriptor {
|
|
|
86
231
|
transformCompiler: TransformCompiler;
|
|
87
232
|
/** What routing needs to know about the mark. Absent in tests that route nothing. */
|
|
88
233
|
route?: MarkRoute;
|
|
234
|
+
/**
|
|
235
|
+
* The mark is known to be slow (`holdsEntrance={false}`): its data reads
|
|
236
|
+
* go sliced from the first, whatever its source's cost. The mark, not its
|
|
237
|
+
* source: other marks on a fast table keep reading on the main connection.
|
|
238
|
+
*/
|
|
239
|
+
slow?: boolean;
|
|
89
240
|
}
|
|
241
|
+
/**
|
|
242
|
+
* How a mark's data read is placed. Routed by the table it reads
|
|
243
|
+
* (SourceRouting): the preagg table when one answers, else the mark's BASE
|
|
244
|
+
* table (its identity view reads the same rows, and its range and stats reads
|
|
245
|
+
* name the base table: one record per source). `slow` (holdsEntrance={false})
|
|
246
|
+
* applies to the base query only: a preagg read is ~1 ms, and forced onto a
|
|
247
|
+
* lane during a brush it would cost ~20 ms of round trips in exactly the case
|
|
248
|
+
* preagg exists to make fast.
|
|
249
|
+
*/
|
|
250
|
+
export declare function markReadOptions(markId: string, descriptor: Pick<QueryDescriptor, 'baseTable' | 'slow'>, preaggTable: string | null): QueryOpts;
|
|
251
|
+
/**
|
|
252
|
+
* DuckDB's catalog error for a table or view this connection cannot see.
|
|
253
|
+
* Matched by its wording, which an upgrade could change: the integration
|
|
254
|
+
* test missing-relation.integration.test.ts checks it against real DuckDB.
|
|
255
|
+
*/
|
|
256
|
+
export declare function isMissingRelation(e: unknown): boolean;
|
|
90
257
|
export declare class QueryEngine {
|
|
91
258
|
#private;
|
|
92
259
|
constructor(connection: DuckDBConnection | Promise<DuckDBConnection>, options?: QueryEngineOptions);
|
|
@@ -178,6 +345,29 @@ export declare class QueryEngine {
|
|
|
178
345
|
* dropped state still invalidates every id handed out before it.
|
|
179
346
|
*/
|
|
180
347
|
onIdentityReset(listener: () => void): () => void;
|
|
348
|
+
/**
|
|
349
|
+
* Debug: every categorical identity request (a mark's ensureColumns call),
|
|
350
|
+
* with its table, fields and time, before deduplication, and every drain
|
|
351
|
+
* start (a table's dims beginning to build, with the fields it found
|
|
352
|
+
* pending). Returns the unsubscribe; costs nothing while no one listens, and
|
|
353
|
+
* a listener that throws is logged without failing identity work.
|
|
354
|
+
*/
|
|
355
|
+
observeIdentityRequests(listener: (request: IdentityRequest) => void): () => void;
|
|
356
|
+
/**
|
|
357
|
+
* Debug: every step of every preagg build (BuildEvent): planned or
|
|
358
|
+
* skipped (with the size guard's numbers), queued (with its hover batch),
|
|
359
|
+
* started, then built, failed or dropped (with the check that failed and
|
|
360
|
+
* the values it compared). Returns the unsubscribe; costs nothing while no
|
|
361
|
+
* one listens, and a listener that throws is logged without failing the
|
|
362
|
+
* build.
|
|
363
|
+
*/
|
|
364
|
+
observeBuilds(listener: (event: BuildEvent) => void): () => void;
|
|
365
|
+
/**
|
|
366
|
+
* Listen to every statement sent to the connection, as it settles. For
|
|
367
|
+
* debugging and measurement; returns the unsubscribe. Costs nothing while
|
|
368
|
+
* no one listens.
|
|
369
|
+
*/
|
|
370
|
+
observeStatements(listener: (record: StatementRecord) => void): () => void;
|
|
181
371
|
/**
|
|
182
372
|
* Execute a query and return the Arrow result table.
|
|
183
373
|
* Accepts a SQL string or any object with toString() (e.g. mosaic-sql Query).
|
|
@@ -190,17 +380,47 @@ export declare class QueryEngine {
|
|
|
190
380
|
query(sql: string | {
|
|
191
381
|
toString(): string;
|
|
192
382
|
}, opts?: QueryOpts): Promise<Table>;
|
|
383
|
+
/**
|
|
384
|
+
* Run several statements as ONE message on the main connection, returning
|
|
385
|
+
* the last statement's rows. Each statement commits on its own and
|
|
386
|
+
* execution stops at the first failure, as when sent one by one (measured
|
|
387
|
+
* on DuckDB-WASM, /test/query-slicing §13); the error does not say which
|
|
388
|
+
* statement failed.
|
|
389
|
+
*
|
|
390
|
+
* For statements on tables the main connection owns (fjader's identity
|
|
391
|
+
* dims, present tables, views): one connection per table. Deliberately no
|
|
392
|
+
* class, source or routing options: it always runs on the main connection
|
|
393
|
+
* as interaction (so lanes hold their slices while it runs). What it saves
|
|
394
|
+
* is queue entries: a dependent chain sent one by one goes to the back of
|
|
395
|
+
* the queue at every step.
|
|
396
|
+
*
|
|
397
|
+
* Logged as one record, kind 'batch', with the joined text and `count`.
|
|
398
|
+
* Without `queryIPC` (mocks, custom connections), or with
|
|
399
|
+
* `QueryEngineOptions.unbatch`, the statements go one by one.
|
|
400
|
+
*/
|
|
401
|
+
execBatch(statements: string[]): Promise<Table>;
|
|
193
402
|
/**
|
|
194
403
|
* Execute DDL/DML statements (CREATE TABLE, DROP TABLE, INSERT, etc.).
|
|
195
404
|
* Accepts a single SQL string or an array of statements to execute
|
|
196
405
|
* sequentially.
|
|
197
406
|
*/
|
|
198
|
-
exec(sql: string | string[]
|
|
407
|
+
exec(sql: string | string[], opts?: {
|
|
408
|
+
class?: StatementClass;
|
|
409
|
+
connectionLocal?: boolean;
|
|
410
|
+
signal?: AbortSignal;
|
|
411
|
+
}): Promise<void>;
|
|
199
412
|
/**
|
|
200
413
|
* Get column info for a table via DESCRIBE.
|
|
201
414
|
* Results are cached — same table returns the same promise.
|
|
202
415
|
*/
|
|
203
416
|
describe(table: string): Promise<ColumnInfo[]>;
|
|
417
|
+
/**
|
|
418
|
+
* Tell the engine how a source reads, overriding its prior: `'slow'` for a
|
|
419
|
+
* table that is slow to query (it reads sliced, so it never holds up
|
|
420
|
+
* other charts), `'fast'` for a view that is cheap (it reads on the main
|
|
421
|
+
* connection from its first query). A measured read still corrects it.
|
|
422
|
+
*/
|
|
423
|
+
sourceCost(source: string, cost: 'fast' | 'slow'): void;
|
|
204
424
|
/** Clear cached DESCRIBE results. Pass a table name to clear one, or omit for all. */
|
|
205
425
|
clearDescribeCache(table?: string): void;
|
|
206
426
|
/**
|