@uwdata/mosaic-core 0.17.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +47 -0
- package/README.md +0 -1
- package/dist/src/Coordinator.d.ts +159 -0
- package/dist/src/Coordinator.d.ts.map +1 -0
- package/dist/src/Coordinator.js +250 -0
- package/dist/src/Coordinator.js.map +1 -0
- package/dist/src/MosaicClient.d.ts +138 -0
- package/dist/src/MosaicClient.d.ts.map +1 -0
- package/dist/src/MosaicClient.js +214 -0
- package/dist/src/MosaicClient.js.map +1 -0
- package/dist/src/Param.d.ts +56 -0
- package/dist/src/Param.d.ts.map +1 -0
- package/dist/src/Param.js +89 -0
- package/dist/src/Param.js.map +1 -0
- package/dist/src/QueryConsolidator.d.ts +11 -0
- package/dist/src/QueryConsolidator.d.ts.map +1 -0
- package/dist/src/QueryConsolidator.js +249 -0
- package/dist/src/QueryConsolidator.js.map +1 -0
- package/dist/src/QueryManager.d.ts +77 -0
- package/dist/src/QueryManager.d.ts.map +1 -0
- package/dist/src/QueryManager.js +174 -0
- package/dist/src/QueryManager.js.map +1 -0
- package/dist/src/Selection.d.ts +222 -0
- package/dist/src/Selection.d.ts.map +1 -0
- package/dist/src/Selection.js +322 -0
- package/dist/src/Selection.js.map +1 -0
- package/dist/src/SelectionClause.d.ts +222 -0
- package/dist/src/SelectionClause.d.ts.map +1 -0
- package/dist/src/SelectionClause.js +168 -0
- package/dist/src/SelectionClause.js.map +1 -0
- package/dist/src/connectors/Connector.d.ts +26 -0
- package/dist/src/connectors/Connector.d.ts.map +1 -0
- package/dist/src/connectors/Connector.js +2 -0
- package/dist/src/connectors/Connector.js.map +1 -0
- package/dist/src/connectors/rest.d.ts +24 -0
- package/dist/src/connectors/rest.d.ts.map +1 -0
- package/dist/src/connectors/rest.js +37 -0
- package/dist/src/connectors/rest.js.map +1 -0
- package/dist/src/connectors/socket.d.ts +40 -0
- package/dist/src/connectors/socket.d.ts.map +1 -0
- package/dist/src/connectors/socket.js +115 -0
- package/dist/src/connectors/socket.js.map +1 -0
- package/dist/src/connectors/wasm.d.ts +56 -0
- package/dist/src/connectors/wasm.d.ts.map +1 -0
- package/dist/src/connectors/wasm.js +116 -0
- package/dist/src/connectors/wasm.js.map +1 -0
- package/dist/src/index.d.ts +28 -0
- package/dist/src/index.d.ts.map +1 -0
- package/{src → dist/src}/index.js +8 -11
- package/dist/src/index.js.map +1 -0
- package/dist/src/make-client.d.ts +33 -0
- package/dist/src/make-client.d.ts.map +1 -0
- package/dist/src/make-client.js +52 -0
- package/dist/src/make-client.js.map +1 -0
- package/dist/src/preagg/PreAggregator.d.ts +150 -0
- package/dist/src/preagg/PreAggregator.d.ts.map +1 -0
- package/dist/src/preagg/PreAggregator.js +382 -0
- package/dist/src/preagg/PreAggregator.js.map +1 -0
- package/dist/src/preagg/preagg-columns.d.ts +16 -0
- package/dist/src/preagg/preagg-columns.d.ts.map +1 -0
- package/dist/src/preagg/preagg-columns.js +95 -0
- package/dist/src/preagg/preagg-columns.js.map +1 -0
- package/dist/src/preagg/sufficient-statistics.d.ts +14 -0
- package/dist/src/preagg/sufficient-statistics.d.ts.map +1 -0
- package/dist/src/preagg/sufficient-statistics.js +446 -0
- package/dist/src/preagg/sufficient-statistics.js.map +1 -0
- package/dist/src/types.d.ts +77 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/util/AsyncDispatch.d.ts +121 -0
- package/dist/src/util/AsyncDispatch.d.ts.map +1 -0
- package/dist/src/util/AsyncDispatch.js +188 -0
- package/dist/src/util/AsyncDispatch.js.map +1 -0
- package/dist/src/util/cache.d.ts +19 -0
- package/dist/src/util/cache.d.ts.map +1 -0
- package/dist/src/util/cache.js +66 -0
- package/dist/src/util/cache.js.map +1 -0
- package/dist/src/util/decode-ipc.d.ts +12 -0
- package/dist/src/util/decode-ipc.d.ts.map +1 -0
- package/{src → dist/src}/util/decode-ipc.js +5 -6
- package/dist/src/util/decode-ipc.js.map +1 -0
- package/dist/src/util/distinct.d.ts +3 -0
- package/dist/src/util/distinct.d.ts.map +1 -0
- package/dist/src/util/distinct.js +16 -0
- package/dist/src/util/distinct.js.map +1 -0
- package/dist/src/util/field-info.d.ts +26 -0
- package/dist/src/util/field-info.d.ts.map +1 -0
- package/dist/src/util/field-info.js +91 -0
- package/dist/src/util/field-info.js.map +1 -0
- package/dist/src/util/hash.d.ts +2 -0
- package/dist/src/util/hash.d.ts.map +1 -0
- package/dist/src/util/hash.js +26 -0
- package/dist/src/util/hash.js.map +1 -0
- package/dist/src/util/is-activatable.d.ts +8 -0
- package/dist/src/util/is-activatable.d.ts.map +1 -0
- package/dist/src/util/is-activatable.js +10 -0
- package/dist/src/util/is-activatable.js.map +1 -0
- package/dist/src/util/is-arrow-table.d.ts +9 -0
- package/dist/src/util/is-arrow-table.d.ts.map +1 -0
- package/dist/src/util/is-arrow-table.js +11 -0
- package/dist/src/util/is-arrow-table.js.map +1 -0
- package/dist/src/util/js-type.d.ts +9 -0
- package/dist/src/util/js-type.d.ts.map +1 -0
- package/dist/src/util/js-type.js +59 -0
- package/dist/src/util/js-type.js.map +1 -0
- package/dist/src/util/priority-queue.d.ts +35 -0
- package/dist/src/util/priority-queue.d.ts.map +1 -0
- package/dist/src/util/priority-queue.js +81 -0
- package/dist/src/util/priority-queue.js.map +1 -0
- package/dist/src/util/query-result.d.ts +47 -0
- package/dist/src/util/query-result.d.ts.map +1 -0
- package/dist/src/util/query-result.js +83 -0
- package/dist/src/util/query-result.js.map +1 -0
- package/dist/src/util/synchronizer.d.ts +36 -0
- package/dist/src/util/synchronizer.d.ts.map +1 -0
- package/dist/src/util/synchronizer.js +52 -0
- package/dist/src/util/synchronizer.js.map +1 -0
- package/dist/src/util/throttle.d.ts +12 -0
- package/dist/src/util/throttle.d.ts.map +1 -0
- package/dist/src/util/throttle.js +51 -0
- package/dist/src/util/throttle.js.map +1 -0
- package/dist/src/util/to-data-columns.d.ts +22 -0
- package/dist/src/util/to-data-columns.d.ts.map +1 -0
- package/dist/src/util/to-data-columns.js +51 -0
- package/dist/src/util/to-data-columns.js.map +1 -0
- package/dist/src/util/void-logger.d.ts +13 -0
- package/dist/src/util/void-logger.d.ts.map +1 -0
- package/dist/src/util/void-logger.js +13 -0
- package/dist/src/util/void-logger.js.map +1 -0
- package/package.json +17 -11
- package/src/Coordinator.ts +396 -0
- package/src/{MosaicClient.js → MosaicClient.ts} +50 -43
- package/src/{Param.js → Param.ts} +29 -28
- package/src/{QueryConsolidator.js → QueryConsolidator.ts} +85 -62
- package/src/{QueryManager.js → QueryManager.ts} +61 -54
- package/src/Selection.ts +391 -0
- package/src/SelectionClause.ts +357 -0
- package/src/connectors/Connector.ts +6 -6
- package/src/connectors/rest.ts +56 -0
- package/src/connectors/{socket.js → socket.ts} +53 -42
- package/src/connectors/{wasm.js → wasm.ts} +52 -63
- package/src/index.ts +42 -0
- package/src/make-client.ts +93 -0
- package/src/preagg/{PreAggregator.js → PreAggregator.ts} +164 -145
- package/src/preagg/{preagg-columns.js → preagg-columns.ts} +27 -24
- package/src/preagg/{sufficient-statistics.js → sufficient-statistics.ts} +160 -110
- package/src/types.ts +24 -9
- package/src/util/{AsyncDispatch.js → AsyncDispatch.ts} +62 -43
- package/src/util/{cache.js → cache.ts} +25 -15
- package/src/util/decode-ipc.ts +15 -0
- package/src/util/{distinct.js → distinct.ts} +3 -3
- package/src/util/{field-info.js → field-info.ts} +30 -31
- package/src/util/{hash.js → hash.ts} +4 -4
- package/src/util/is-activatable.ts +11 -0
- package/src/util/is-arrow-table.ts +12 -0
- package/src/util/{js-type.js → js-type.ts} +7 -5
- package/src/util/{priority-queue.js → priority-queue.ts} +32 -20
- package/src/util/{query-result.js → query-result.ts} +24 -17
- package/src/util/synchronizer.ts +56 -0
- package/src/util/throttle.ts +59 -0
- package/src/util/to-data-columns.ts +65 -0
- package/src/util/void-logger.ts +23 -0
- package/src/Coordinator.js +0 -313
- package/src/Selection.js +0 -380
- package/src/SelectionClause.js +0 -159
- package/src/connectors/rest.js +0 -38
- package/src/index-types.ts +0 -5
- package/src/make-client.js +0 -101
- package/src/util/is-activatable.js +0 -8
- package/src/util/is-arrow-table.js +0 -10
- package/src/util/selection-types.ts +0 -137
- package/src/util/synchronizer.js +0 -47
- package/src/util/throttle.js +0 -54
- package/src/util/to-data-columns.js +0 -60
- package/src/util/void-logger.js +0 -13
- package/tsconfig.json +0 -9
- package/vitest.config.ts +0 -3
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { throttle } from './util/throttle.js';
|
|
2
|
+
export function isMosaicClient(x) {
|
|
3
|
+
return x instanceof MosaicClient;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* A Mosaic client is a data consumer that indicates its data needs to a
|
|
7
|
+
* Mosaic coordinator via the query method. The coordinator is responsible
|
|
8
|
+
* for issuing queries and returning results to the client.
|
|
9
|
+
*
|
|
10
|
+
* The client life-cycle consists of connection to a coordinator,
|
|
11
|
+
* initialization (potentially involving queries for data schema and summary
|
|
12
|
+
* statistic information), and then interactive queries that may be driven by
|
|
13
|
+
* an associated selection. When no longer needed, a client should be
|
|
14
|
+
* disconnected from the coordinator.
|
|
15
|
+
*
|
|
16
|
+
* When enabled, a client will initialize and respond to query update requests.
|
|
17
|
+
* If disabled, the client will delay initialization and not respond to queries
|
|
18
|
+
* until enabled again. Disabling a client can improve system performance when
|
|
19
|
+
* associated interface elements are offscreen or disabled.
|
|
20
|
+
*/
|
|
21
|
+
export class MosaicClient {
|
|
22
|
+
_filterBy;
|
|
23
|
+
_requestUpdate;
|
|
24
|
+
_coordinator;
|
|
25
|
+
_pending;
|
|
26
|
+
_enabled;
|
|
27
|
+
_initialized;
|
|
28
|
+
_request;
|
|
29
|
+
/**
|
|
30
|
+
* Create a new client instance.
|
|
31
|
+
* @param filterSelection An optional selection to
|
|
32
|
+
* interactively filter this client's data. If provided, a coordinator
|
|
33
|
+
* will re-query and update the client when the selection updates.
|
|
34
|
+
*/
|
|
35
|
+
constructor(filterSelection) {
|
|
36
|
+
this._filterBy = filterSelection;
|
|
37
|
+
this._requestUpdate = throttle(() => this.requestQuery(), true);
|
|
38
|
+
this._coordinator = null;
|
|
39
|
+
this._pending = Promise.resolve();
|
|
40
|
+
this._enabled = true;
|
|
41
|
+
this._initialized = false;
|
|
42
|
+
this._request = null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* @returns this client's connected coordinator.
|
|
46
|
+
*/
|
|
47
|
+
get coordinator() {
|
|
48
|
+
return this._coordinator;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Set this client's connected coordinator.
|
|
52
|
+
*/
|
|
53
|
+
set coordinator(coordinator) {
|
|
54
|
+
this._coordinator = coordinator;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Return this client's enabled state.
|
|
58
|
+
*/
|
|
59
|
+
get enabled() {
|
|
60
|
+
return this._enabled;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Set this client's enabled state;
|
|
64
|
+
*/
|
|
65
|
+
set enabled(state) {
|
|
66
|
+
state = !!state; // ensure boolean
|
|
67
|
+
if (this._enabled !== state) {
|
|
68
|
+
this._enabled = state;
|
|
69
|
+
if (state) {
|
|
70
|
+
if (!this._initialized) {
|
|
71
|
+
// initialization includes a query request
|
|
72
|
+
this.initialize();
|
|
73
|
+
}
|
|
74
|
+
else if (this._request) {
|
|
75
|
+
// request query now if requested while disabled
|
|
76
|
+
this.requestQuery(this._request === true ? undefined : this._request);
|
|
77
|
+
}
|
|
78
|
+
this._request = null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Return a Promise that resolves once the client has updated.
|
|
84
|
+
*/
|
|
85
|
+
get pending() {
|
|
86
|
+
return this._pending;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* @returns this client's filter selection.
|
|
90
|
+
*/
|
|
91
|
+
get filterBy() {
|
|
92
|
+
return this._filterBy;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Return a boolean indicating if the client query can be sped up with
|
|
96
|
+
* materialized views of pre-aggregated data. Should return true if changes
|
|
97
|
+
* to the filterBy selection do not change the groupby domain of the client
|
|
98
|
+
* query.
|
|
99
|
+
*/
|
|
100
|
+
get filterStable() {
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Prepare the client before the `query()` method is called. Subclasses
|
|
105
|
+
* should override this method as needed, potentially issuing one or more
|
|
106
|
+
* queries to gather data or metadata needed prior to `query` calls.
|
|
107
|
+
*/
|
|
108
|
+
async prepare() {
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Return a query specifying the data needed by this client.
|
|
112
|
+
* @param filter The filtering criteria to apply in the query.
|
|
113
|
+
* @returns The client query
|
|
114
|
+
*/
|
|
115
|
+
query(filter) {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Called by the coordinator to inform the client that a query is pending.
|
|
120
|
+
* @returns this
|
|
121
|
+
*/
|
|
122
|
+
queryPending() {
|
|
123
|
+
return this;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Called by the coordinator to return a query result.
|
|
127
|
+
* @param data The query result.
|
|
128
|
+
* @returns this
|
|
129
|
+
*/
|
|
130
|
+
queryResult(data) {
|
|
131
|
+
return this;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Called by the coordinator to report a query execution error.
|
|
135
|
+
* @param error
|
|
136
|
+
* @returns this
|
|
137
|
+
*/
|
|
138
|
+
queryError(error) {
|
|
139
|
+
// do nothing, the coordinator logs the error
|
|
140
|
+
return this;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Request the coordinator to execute a query for this client.
|
|
144
|
+
* If an explicit query is not provided, the client `query` method will
|
|
145
|
+
* be called, filtered by the current `filterBy` selection. This method has
|
|
146
|
+
* no effect if the client is not connected to a coordinator. If the client
|
|
147
|
+
* is connected by currently disabled, the request will be serviced if the
|
|
148
|
+
* client is later enabled.
|
|
149
|
+
* @param query The query to request. If unspecified, the query
|
|
150
|
+
* will be determined by the client's `query` method and the current
|
|
151
|
+
* `filterBy` selection state.
|
|
152
|
+
*/
|
|
153
|
+
requestQuery(query) {
|
|
154
|
+
if (this._enabled) {
|
|
155
|
+
const q = query || this.query(this.filterBy?.predicate(this));
|
|
156
|
+
return this._coordinator.requestQuery(this, q);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
this._request = query ?? true;
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Request that the coordinator perform a throttled update of this client
|
|
165
|
+
* using the default query. Unlike requestQuery, for which every call results
|
|
166
|
+
* in an executed query, multiple calls to requestUpdate may be consolidated
|
|
167
|
+
* into a single update. This method has no effect if the client is not
|
|
168
|
+
* connected to a coordinator. If the client is connected but currently
|
|
169
|
+
* disabled, the request will be serviced if the client is later enabled.
|
|
170
|
+
*/
|
|
171
|
+
requestUpdate() {
|
|
172
|
+
if (this._enabled) {
|
|
173
|
+
this._requestUpdate();
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
this.requestQuery();
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Reset this client, calling the prepare method and query requests. This
|
|
181
|
+
* method has no effect if the client is not registered with a coordinator.
|
|
182
|
+
*/
|
|
183
|
+
initialize() {
|
|
184
|
+
if (!this._enabled) {
|
|
185
|
+
// clear flag so we initialize when enabled again
|
|
186
|
+
this._initialized = false;
|
|
187
|
+
}
|
|
188
|
+
else if (this._coordinator) {
|
|
189
|
+
// if connected, let's initialize
|
|
190
|
+
this._initialized = true;
|
|
191
|
+
this._pending = this.prepare().then(() => this.requestQuery());
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Remove this client: disconnect from the coordinator and free up any
|
|
196
|
+
* resource use. This method has no effect if the client is not connected
|
|
197
|
+
* to a coordinator.
|
|
198
|
+
*
|
|
199
|
+
* If overriding this method in a client subclass, be sure to also
|
|
200
|
+
* disconnect from the coordinator.
|
|
201
|
+
*/
|
|
202
|
+
destroy() {
|
|
203
|
+
this._enabled = false;
|
|
204
|
+
this.coordinator?.disconnect(this);
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Requests a client update, for example to (re-)render an interface
|
|
208
|
+
* component.
|
|
209
|
+
*/
|
|
210
|
+
update() {
|
|
211
|
+
return this;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=MosaicClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MosaicClient.js","sourceRoot":"","sources":["../../src/MosaicClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { AsyncDispatch } from './util/AsyncDispatch.js';
|
|
2
|
+
/**
|
|
3
|
+
* Test if a value is a Param instance.
|
|
4
|
+
* @param x The value to test.
|
|
5
|
+
* @returns True if the input is a Param, false otherwise.
|
|
6
|
+
*/
|
|
7
|
+
export declare function isParam<T>(x: unknown): x is Param<T>;
|
|
8
|
+
/**
|
|
9
|
+
* Represents a dynamic parameter that dispatches updates
|
|
10
|
+
* upon parameter changes.
|
|
11
|
+
*/
|
|
12
|
+
export declare class Param<T> extends AsyncDispatch<T> {
|
|
13
|
+
protected _value?: T;
|
|
14
|
+
/**
|
|
15
|
+
* Create a new Param instance.
|
|
16
|
+
* @param value The initial value of the Param.
|
|
17
|
+
*/
|
|
18
|
+
constructor(value?: T);
|
|
19
|
+
/**
|
|
20
|
+
* Create a new Param instance with the given initial value.
|
|
21
|
+
* @param value The initial value of the Param.
|
|
22
|
+
* @returns The new Param instance.
|
|
23
|
+
*/
|
|
24
|
+
static value<T>(value: T): Param<T>;
|
|
25
|
+
/**
|
|
26
|
+
* Create a new Param instance over an array of initial values,
|
|
27
|
+
* which may contain nested Params.
|
|
28
|
+
* @param values The initial values of the Param.
|
|
29
|
+
* @returns The new Param instance.
|
|
30
|
+
*/
|
|
31
|
+
static array<T>(values: (T | Param<T>)[]): Param<T[]>;
|
|
32
|
+
/**
|
|
33
|
+
* The current value of the Param.
|
|
34
|
+
*/
|
|
35
|
+
get value(): T | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* Update the Param value
|
|
38
|
+
* @param value The new value of the Param.
|
|
39
|
+
* @param options The update options.
|
|
40
|
+
* @param options.force A boolean flag indicating if the Param
|
|
41
|
+
* should emit a 'value' event even if the internal value is unchanged.
|
|
42
|
+
* @returns This Param instance.
|
|
43
|
+
*/
|
|
44
|
+
update(value: T, { force }?: {
|
|
45
|
+
force?: boolean;
|
|
46
|
+
}): this;
|
|
47
|
+
/**
|
|
48
|
+
* Upon value-typed updates, sets the current value to the input value
|
|
49
|
+
* immediately prior to the event value being emitted to listeners.
|
|
50
|
+
* @param type The event type.
|
|
51
|
+
* @param value The input event value.
|
|
52
|
+
* @returns The input event value.
|
|
53
|
+
*/
|
|
54
|
+
willEmit(type: string, value: T): T;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=Param.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Param.d.ts","sourceRoot":"","sources":["../../src/Param.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAGxD;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAEpD;AAED;;;GAGG;AACH,qBAAa,KAAK,CAAC,CAAC,CAAE,SAAQ,aAAa,CAAC,CAAC,CAAC;IAC5C,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAErB;;;OAGG;gBACS,KAAK,CAAC,EAAE,CAAC;IAKrB;;;;OAIG;IACH,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;IAInC;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,GAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;IAanD;;OAEG;IACH,IAAI,KAAK,IAAI,CAAC,GAAG,SAAS,CAEzB;IAED;;;;;;;OAOG;IACH,MAAM,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,IAAI;IAU3D;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC;CAMpC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { AsyncDispatch } from './util/AsyncDispatch.js';
|
|
2
|
+
import { distinct } from './util/distinct.js';
|
|
3
|
+
/**
|
|
4
|
+
* Test if a value is a Param instance.
|
|
5
|
+
* @param x The value to test.
|
|
6
|
+
* @returns True if the input is a Param, false otherwise.
|
|
7
|
+
*/
|
|
8
|
+
export function isParam(x) {
|
|
9
|
+
return x instanceof Param;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Represents a dynamic parameter that dispatches updates
|
|
13
|
+
* upon parameter changes.
|
|
14
|
+
*/
|
|
15
|
+
export class Param extends AsyncDispatch {
|
|
16
|
+
_value;
|
|
17
|
+
/**
|
|
18
|
+
* Create a new Param instance.
|
|
19
|
+
* @param value The initial value of the Param.
|
|
20
|
+
*/
|
|
21
|
+
constructor(value) {
|
|
22
|
+
super();
|
|
23
|
+
this._value = value;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Create a new Param instance with the given initial value.
|
|
27
|
+
* @param value The initial value of the Param.
|
|
28
|
+
* @returns The new Param instance.
|
|
29
|
+
*/
|
|
30
|
+
static value(value) {
|
|
31
|
+
return new Param(value);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Create a new Param instance over an array of initial values,
|
|
35
|
+
* which may contain nested Params.
|
|
36
|
+
* @param values The initial values of the Param.
|
|
37
|
+
* @returns The new Param instance.
|
|
38
|
+
*/
|
|
39
|
+
static array(values) {
|
|
40
|
+
if (values.some(v => isParam(v))) {
|
|
41
|
+
const p = new Param();
|
|
42
|
+
const update = () => {
|
|
43
|
+
p.update(values.map(v => isParam(v) ? v.value : v));
|
|
44
|
+
};
|
|
45
|
+
update();
|
|
46
|
+
values.forEach(v => isParam(v) ? v.addEventListener('value', update) : 0);
|
|
47
|
+
return p;
|
|
48
|
+
}
|
|
49
|
+
return new Param(values);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The current value of the Param.
|
|
53
|
+
*/
|
|
54
|
+
get value() {
|
|
55
|
+
return this._value;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Update the Param value
|
|
59
|
+
* @param value The new value of the Param.
|
|
60
|
+
* @param options The update options.
|
|
61
|
+
* @param options.force A boolean flag indicating if the Param
|
|
62
|
+
* should emit a 'value' event even if the internal value is unchanged.
|
|
63
|
+
* @returns This Param instance.
|
|
64
|
+
*/
|
|
65
|
+
update(value, { force } = {}) {
|
|
66
|
+
const shouldEmit = distinct(this._value, value) || force;
|
|
67
|
+
if (shouldEmit) {
|
|
68
|
+
this.emit('value', value);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
this.cancel('value');
|
|
72
|
+
}
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Upon value-typed updates, sets the current value to the input value
|
|
77
|
+
* immediately prior to the event value being emitted to listeners.
|
|
78
|
+
* @param type The event type.
|
|
79
|
+
* @param value The input event value.
|
|
80
|
+
* @returns The input event value.
|
|
81
|
+
*/
|
|
82
|
+
willEmit(type, value) {
|
|
83
|
+
if (type === 'value') {
|
|
84
|
+
this._value = value;
|
|
85
|
+
}
|
|
86
|
+
return value;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=Param.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Param.js","sourceRoot":"","sources":["../../src/Param.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAI,CAAU;IACnC,OAAO,CAAC,YAAY,KAAK,CAAC;AAC5B,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,KAAS,SAAQ,aAAgB;IAClC,MAAM,CAAK;IAErB;;;OAGG;IACH,YAAY,KAAS;QACnB,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;IACtB,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,KAAK,CAAI,KAAQ;QACtB,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAI,MAAsB;QACpC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACjC,MAAM,CAAC,GAAG,IAAI,KAAK,EAAO,CAAC;YAC3B,MAAM,MAAM,GAAG,GAAS,EAAE;gBACxB,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1D,CAAC,CAAC;YACF,MAAM,EAAE,CAAC;YACT,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1E,OAAO,CAAC,CAAC;QACX,CAAC;QACD,OAAO,IAAI,KAAK,CAAC,MAAM,CAAe,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED;;;;;;;OAOG;IACH,MAAM,CAAC,KAAQ,EAAE,EAAE,KAAK,KAA0B,EAAE;QAClD,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,KAAK,CAAC;QACzD,IAAI,UAAU,EAAE,CAAC;YACf,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACvB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;OAMG;IACH,QAAQ,CAAC,IAAY,EAAE,KAAQ;QAC7B,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YACrB,IAAI,CAAC,MAAM,GAAG,KAAU,CAAC;QAC3B,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Cache, QueryEntry } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Create a consolidator to combine structurally compatible queries.
|
|
4
|
+
* @param enqueue Query manager enqueue method
|
|
5
|
+
* @param cache Client-side query cache (sql -> data)
|
|
6
|
+
* @returns A consolidator object
|
|
7
|
+
*/
|
|
8
|
+
export declare function consolidator(enqueue: (entry: QueryEntry, priority?: number) => void, cache: Cache): {
|
|
9
|
+
add(entry: QueryEntry, priority: number): void;
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=QueryConsolidator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QueryConsolidator.d.ts","sourceRoot":"","sources":["../../src/QueryConsolidator.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAa,MAAM,YAAY,CAAC;AAwB/D;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,EACvD,KAAK,EAAE,KAAK;eAmBC,UAAU,YAAY,MAAM,GAAG,IAAI;EAWjD"}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { isAggregateExpression, isColumnRef, isDescribeQuery, isSelectQuery } from '@uwdata/mosaic-sql';
|
|
2
|
+
import { QueryResult } from './util/query-result.js';
|
|
3
|
+
function wait(callback) {
|
|
4
|
+
if (typeof requestAnimationFrame !== 'undefined') {
|
|
5
|
+
return requestAnimationFrame(callback);
|
|
6
|
+
}
|
|
7
|
+
else if (typeof setImmediate !== 'undefined') {
|
|
8
|
+
return setImmediate(callback);
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
return setTimeout(callback);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Create a consolidator to combine structurally compatible queries.
|
|
16
|
+
* @param enqueue Query manager enqueue method
|
|
17
|
+
* @param cache Client-side query cache (sql -> data)
|
|
18
|
+
* @returns A consolidator object
|
|
19
|
+
*/
|
|
20
|
+
export function consolidator(enqueue, cache) {
|
|
21
|
+
let pending = [];
|
|
22
|
+
let id = 0;
|
|
23
|
+
function run() {
|
|
24
|
+
// group queries into bundles that can be consolidated
|
|
25
|
+
const groups = entryGroups(pending, cache);
|
|
26
|
+
pending = [];
|
|
27
|
+
id = 0;
|
|
28
|
+
// build and issue consolidated queries
|
|
29
|
+
for (const group of groups) {
|
|
30
|
+
consolidate(group, enqueue);
|
|
31
|
+
processResults(group, cache);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
add(entry, priority) {
|
|
36
|
+
if (entry.request.type === 'arrow') {
|
|
37
|
+
// wait one frame, gather an ordered list of queries
|
|
38
|
+
// only Apache Arrow is supported, so we can project efficiently
|
|
39
|
+
id ||= wait(() => run());
|
|
40
|
+
pending.push({ entry, priority, index: pending.length });
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
enqueue(entry, priority);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Segment query requests into consolidation-compatible groups.
|
|
50
|
+
* @param entries Query request entries ({ request, result } objects)
|
|
51
|
+
* @param cache Client-side query cache
|
|
52
|
+
* @returns An array of grouped entry arrays
|
|
53
|
+
*/
|
|
54
|
+
function entryGroups(entries, cache) {
|
|
55
|
+
const groups = [];
|
|
56
|
+
const groupMap = new Map();
|
|
57
|
+
for (const query of entries) {
|
|
58
|
+
const { entry: { request } } = query;
|
|
59
|
+
const key = consolidationKey(request.query, cache);
|
|
60
|
+
if (!groupMap.has(key)) {
|
|
61
|
+
const list = [];
|
|
62
|
+
groups.push(list);
|
|
63
|
+
groupMap.set(key, list);
|
|
64
|
+
}
|
|
65
|
+
groupMap.get(key).push(query);
|
|
66
|
+
}
|
|
67
|
+
return groups;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Generate a key string for query consolidation.
|
|
71
|
+
* Queries with matching keys are conosolidation-compatible.
|
|
72
|
+
* If a query is found in the cache, it is exempted from consolidation,
|
|
73
|
+
* which is indicated by returning the precise query SQL as the key.
|
|
74
|
+
* @param query The input query.
|
|
75
|
+
* @param cache The query cache (sql -> data).
|
|
76
|
+
* @returns a key string
|
|
77
|
+
*/
|
|
78
|
+
function consolidationKey(query, cache) {
|
|
79
|
+
const sql = `${query}`;
|
|
80
|
+
if (isSelectQuery(query) && !cache.get(sql)) {
|
|
81
|
+
if (query._where.length || query._qualify.length || query._having.length ||
|
|
82
|
+
query._orderby.length || query._distinct) {
|
|
83
|
+
// bail if query includes clauses that may refer to *derived* columns
|
|
84
|
+
// that we can't resolve. also do not consolidate distinct queries
|
|
85
|
+
return sql;
|
|
86
|
+
}
|
|
87
|
+
// create a derived query stripped of selections
|
|
88
|
+
const q = query.clone().setSelect('*');
|
|
89
|
+
// check group by criteria for compatibility
|
|
90
|
+
// queries may refer to *derived* columns as group by criteria
|
|
91
|
+
// we resolve these against the true grouping expressions
|
|
92
|
+
const groupby = query._groupby;
|
|
93
|
+
if (groupby.length) {
|
|
94
|
+
const map = {}; // expression map (alias -> expr)
|
|
95
|
+
query._select.forEach(({ alias, expr }) => map[alias] = expr);
|
|
96
|
+
q.setGroupby(groupby.map(e => (isColumnRef(e) && map[e.column]) || e));
|
|
97
|
+
}
|
|
98
|
+
else if (query._select.some(e => isAggregateExpression(e.expr))) {
|
|
99
|
+
// if query is an ungrouped aggregate, add an explicit groupby to
|
|
100
|
+
// prevent improper consolidation with non-aggregate queries
|
|
101
|
+
q.setGroupby('ALL');
|
|
102
|
+
}
|
|
103
|
+
// key is just the transformed query as SQL
|
|
104
|
+
return `${q}`;
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
// can not analyze query, simply return as string
|
|
108
|
+
return sql;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Issue queries, consolidating where possible.
|
|
113
|
+
* @param group Array of bundled query entries
|
|
114
|
+
* @param enqueue Add entry to query queue
|
|
115
|
+
*/
|
|
116
|
+
function consolidate(group, enqueue) {
|
|
117
|
+
if (shouldConsolidate(group)) {
|
|
118
|
+
// issue a single consolidated query
|
|
119
|
+
enqueue({
|
|
120
|
+
request: {
|
|
121
|
+
type: 'arrow',
|
|
122
|
+
cache: false,
|
|
123
|
+
query: (group.query = consolidatedQuery(group))
|
|
124
|
+
},
|
|
125
|
+
result: (group.result = new QueryResult())
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
// issue queries directly
|
|
130
|
+
for (const { entry, priority } of group) {
|
|
131
|
+
enqueue(entry, priority);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Check if a group contains multiple distinct queries.
|
|
137
|
+
* @param group Array of bundled query entries
|
|
138
|
+
* @returns false if group contains a single (possibly repeated) query,
|
|
139
|
+
* otherwise true
|
|
140
|
+
*/
|
|
141
|
+
function shouldConsolidate(group) {
|
|
142
|
+
if (group.length > 1) {
|
|
143
|
+
const sql = `${group[0].entry.request.query}`;
|
|
144
|
+
for (let i = 1; i < group.length; ++i) {
|
|
145
|
+
if (sql !== `${group[i].entry.request.query}`) {
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Create a consolidated query for a group.
|
|
154
|
+
* @param group Array of bundled query entries
|
|
155
|
+
* @returns A consolidated Query instance
|
|
156
|
+
*/
|
|
157
|
+
function consolidatedQuery(group) {
|
|
158
|
+
const maps = group.maps = [];
|
|
159
|
+
const fields = new Map();
|
|
160
|
+
// gather select fields
|
|
161
|
+
for (const item of group) {
|
|
162
|
+
const query = item.entry.request.query;
|
|
163
|
+
const fieldMap = [];
|
|
164
|
+
maps.push(fieldMap);
|
|
165
|
+
for (const { alias, expr } of query._select) {
|
|
166
|
+
const e = `${expr}`;
|
|
167
|
+
if (!fields.has(e)) {
|
|
168
|
+
fields.set(e, [`col${fields.size}`, expr]);
|
|
169
|
+
}
|
|
170
|
+
const [name] = fields.get(e);
|
|
171
|
+
fieldMap.push([name, alias]);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// use a cloned query as a starting point
|
|
175
|
+
const query = group[0].entry.request.query.clone();
|
|
176
|
+
// update group by statement as needed
|
|
177
|
+
const groupby = query._groupby;
|
|
178
|
+
if (groupby.length) {
|
|
179
|
+
const map = {};
|
|
180
|
+
group.maps[0].forEach(([name, as]) => map[as] = name);
|
|
181
|
+
query.setGroupby(groupby.map((e) => (isColumnRef(e) && map[e.column]) || e));
|
|
182
|
+
}
|
|
183
|
+
// update select statement and return
|
|
184
|
+
return query.setSelect(Array.from(fields.values()));
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Process query results, dispatch results to original requests
|
|
188
|
+
* @param group Array of query requests
|
|
189
|
+
* @param cache Client-side query cache (sql -> data)
|
|
190
|
+
*/
|
|
191
|
+
async function processResults(group, cache) {
|
|
192
|
+
const { maps, query, result } = group;
|
|
193
|
+
// exit early if no consolidation performed
|
|
194
|
+
// in this case results are passed directly
|
|
195
|
+
if (!maps)
|
|
196
|
+
return;
|
|
197
|
+
// await consolidated query result, pass errors if needed
|
|
198
|
+
let data;
|
|
199
|
+
try {
|
|
200
|
+
data = await result;
|
|
201
|
+
}
|
|
202
|
+
catch (err) {
|
|
203
|
+
// pass error to consolidated queries
|
|
204
|
+
for (const { entry } of group) {
|
|
205
|
+
entry.result.reject(err);
|
|
206
|
+
}
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
// extract result for each query in the consolidation group
|
|
210
|
+
// update cache and pass extract to original issuer
|
|
211
|
+
const describe = isDescribeQuery(query);
|
|
212
|
+
group.forEach(({ entry }, index) => {
|
|
213
|
+
const { request, result } = entry;
|
|
214
|
+
const map = maps[index];
|
|
215
|
+
const extract = describe && map ? filterResult(data, map)
|
|
216
|
+
: map ? projectResult(data, map)
|
|
217
|
+
: data;
|
|
218
|
+
if (request.cache) {
|
|
219
|
+
cache.set(String(request.query), extract);
|
|
220
|
+
}
|
|
221
|
+
result.fulfill(extract);
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Project a consolidated result to a client result
|
|
226
|
+
* @param data Consolidated query result, as an Arrow Table
|
|
227
|
+
* @param map Column name map as [source, target] pairs
|
|
228
|
+
* @returns the projected Apache Arrow table
|
|
229
|
+
*/
|
|
230
|
+
function projectResult(data, map) {
|
|
231
|
+
return data.select(map.map(x => x[0]), map.map(x => x[1]));
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Filter a consolidated describe query result to a client result
|
|
235
|
+
* @param data Consolidated query result, as an Arrow Table
|
|
236
|
+
* @param map Column name map as [source, target] pairs
|
|
237
|
+
* @returns the filtered table data
|
|
238
|
+
*/
|
|
239
|
+
function filterResult(data, map) {
|
|
240
|
+
const lookup = new Map(map);
|
|
241
|
+
const result = [];
|
|
242
|
+
for (const d of data) {
|
|
243
|
+
if (lookup.has(d.column_name)) {
|
|
244
|
+
result.push({ ...d, column_name: lookup.get(d.column_name) });
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return result;
|
|
248
|
+
}
|
|
249
|
+
//# sourceMappingURL=QueryConsolidator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QueryConsolidator.js","sourceRoot":"","sources":["../../src/QueryConsolidator.ts"],"names":[],"mappings":"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"}
|