@uwdata/mosaic-core 0.15.0 → 0.16.2
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/dist/types/Coordinator.d.ts +22 -25
- package/dist/types/MosaicClient.d.ts +20 -11
- package/dist/types/QueryManager.d.ts +42 -17
- package/dist/types/Selection.d.ts +1 -1
- package/dist/types/SelectionClause.d.ts +1 -1
- package/dist/types/connectors/Connector.d.ts +25 -0
- package/dist/types/connectors/rest.d.ts +13 -17
- package/dist/types/connectors/socket.d.ts +98 -16
- package/dist/types/connectors/wasm.d.ts +133 -14
- package/dist/types/index-types.d.ts +1 -0
- package/dist/types/preagg/PreAggregator.d.ts +1 -1
- package/dist/types/preagg/preagg-columns.d.ts +2 -2
- package/dist/types/preagg/sufficient-statistics.d.ts +2 -2
- package/dist/types/types.d.ts +21 -0
- package/dist/types/util/cache.d.ts +14 -10
- package/dist/types/util/decode-ipc.d.ts +9 -4
- package/dist/types/util/void-logger.d.ts +3 -0
- package/package.json +4 -4
- package/src/Coordinator.js +15 -12
- package/src/MosaicClient.js +17 -5
- package/src/QueryConsolidator.js +2 -1
- package/src/QueryManager.js +31 -0
- package/src/Selection.js +4 -2
- package/src/SelectionClause.js +5 -2
- package/src/connectors/Connector.ts +30 -0
- package/src/connectors/rest.js +14 -12
- package/src/connectors/socket.js +112 -77
- package/src/connectors/wasm.js +118 -55
- package/src/index-types.ts +1 -0
- package/src/make-client.js +0 -4
- package/src/preagg/PreAggregator.js +8 -6
- package/src/preagg/preagg-columns.js +5 -2
- package/src/preagg/sufficient-statistics.js +2 -1
- package/src/types.ts +23 -0
- package/src/util/cache.js +20 -5
- package/src/util/decode-ipc.js +9 -5
- package/src/util/field-info.js +2 -1
- package/src/util/js-type.js +3 -1
- package/src/util/void-logger.js +4 -1
package/src/connectors/wasm.js
CHANGED
|
@@ -1,81 +1,144 @@
|
|
|
1
|
+
/** @import { ExtractionOptions, Table } from '@uwdata/flechette' */
|
|
2
|
+
/** @import { ArrowQueryRequest, Connector, ExecQueryRequest, JSONQueryRequest } from './Connector.js' */
|
|
1
3
|
import * as duckdb from '@duckdb/duckdb-wasm';
|
|
2
4
|
import { decodeIPC } from '../util/decode-ipc.js';
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {object} DuckDBWASMOptions
|
|
8
|
+
* @property {boolean} [log] Flag to enable logging.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @typedef {object} DuckDBWASMConnectorOptions
|
|
13
|
+
* @property {boolean} [log] Flag to enable logging.
|
|
14
|
+
* @property {ExtractionOptions} [ipc]
|
|
15
|
+
* Arrow IPC extraction options.
|
|
16
|
+
* @property {duckdb.AsyncDuckDB} [duckdb]
|
|
17
|
+
* Optional pre-existing DuckDB-WASM instance.
|
|
18
|
+
* @property {duckdb.AsyncDuckDBConnection} [connection]
|
|
19
|
+
* Optional pre-existing DuckDB-WASM connection.
|
|
20
|
+
*/
|
|
18
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Connect to a DuckDB-WASM instance.
|
|
24
|
+
* @param {DuckDBWASMConnectorOptions} [options] Connector options.
|
|
25
|
+
* @returns {DuckDBWASMConnector} A connector instance.
|
|
26
|
+
*/
|
|
19
27
|
export function wasmConnector(options = {}) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
let con = connection;
|
|
23
|
-
let loadPromise;
|
|
28
|
+
return new DuckDBWASMConnector(options);
|
|
29
|
+
}
|
|
24
30
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
/**
|
|
32
|
+
* DuckDB-WASM connector.
|
|
33
|
+
* @implements {Connector}
|
|
34
|
+
*/
|
|
35
|
+
export class DuckDBWASMConnector {
|
|
36
|
+
/**
|
|
37
|
+
* Create a new DuckDB-WASM connector instance.
|
|
38
|
+
* @param {DuckDBWASMConnectorOptions} [options]
|
|
39
|
+
*/
|
|
40
|
+
constructor(options = {}) {
|
|
41
|
+
const { ipc, duckdb, connection, ...opts } = options;
|
|
42
|
+
/** @type {ExtractionOptions} */
|
|
43
|
+
this._ipc = ipc;
|
|
44
|
+
/** @type {DuckDBWASMOptions} */
|
|
45
|
+
this._options = opts;
|
|
46
|
+
/** @type {duckdb.AsyncDuckDB} */
|
|
47
|
+
this._db = duckdb;
|
|
48
|
+
/** @type {duckdb.AsyncDuckDBConnection} */
|
|
49
|
+
this._con = connection;
|
|
50
|
+
/** @type {Promise<unknown>} */
|
|
51
|
+
this._loadPromise;
|
|
36
52
|
}
|
|
37
53
|
|
|
38
54
|
/**
|
|
39
55
|
* Get the backing DuckDB-WASM instance.
|
|
40
|
-
*
|
|
56
|
+
* Lazily initializes DuckDB-WASM if not already loaded.
|
|
41
57
|
* @returns {Promise<duckdb.AsyncDuckDB>} The DuckDB-WASM instance.
|
|
42
58
|
*/
|
|
43
|
-
async
|
|
44
|
-
if (!
|
|
45
|
-
return
|
|
59
|
+
async getDuckDB() {
|
|
60
|
+
if (!this._db) await connect(this);
|
|
61
|
+
return this._db;
|
|
46
62
|
}
|
|
47
63
|
|
|
48
64
|
/**
|
|
49
65
|
* Get the backing DuckDB-WASM connection.
|
|
50
|
-
*
|
|
66
|
+
* Lazily initializes DuckDB-WASM if not already loaded.
|
|
51
67
|
* @returns {Promise<duckdb.AsyncDuckDBConnection>} The DuckDB-WASM connection.
|
|
52
68
|
*/
|
|
53
|
-
async
|
|
54
|
-
if (!
|
|
55
|
-
return
|
|
69
|
+
async getConnection() {
|
|
70
|
+
if (!this._con) await connect(this);
|
|
71
|
+
return this._con;
|
|
56
72
|
}
|
|
57
73
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
74
|
+
/**
|
|
75
|
+
* @overload
|
|
76
|
+
* @param {ArrowQueryRequest} query
|
|
77
|
+
* @returns {Promise<Table>}
|
|
78
|
+
*
|
|
79
|
+
* @overload
|
|
80
|
+
* @param {ExecQueryRequest} query
|
|
81
|
+
* @returns {Promise<void>}
|
|
82
|
+
*
|
|
83
|
+
* @overload
|
|
84
|
+
* @param {JSONQueryRequest} query
|
|
85
|
+
* @returns {Promise<Record<string, any>[]>}
|
|
86
|
+
*
|
|
87
|
+
* @param {ArrowQueryRequest | ExecQueryRequest | JSONQueryRequest} query
|
|
88
|
+
* @returns {Promise<Table | void | Record<string, any>[]>}}
|
|
89
|
+
*/
|
|
90
|
+
async query(query) {
|
|
91
|
+
const { type, sql } = query;
|
|
92
|
+
const con = await this.getConnection();
|
|
93
|
+
const result = await getArrowIPC(con, sql);
|
|
94
|
+
return type === 'exec' ? undefined
|
|
95
|
+
: type === 'arrow' ? decodeIPC(result, this._ipc)
|
|
96
|
+
: decodeIPC(result).toArray();
|
|
76
97
|
};
|
|
77
98
|
}
|
|
78
99
|
|
|
100
|
+
/**
|
|
101
|
+
* Bypass duckdb-wasm query method to get Arrow IPC bytes directly.
|
|
102
|
+
* https://github.com/duckdb/duckdb-wasm/issues/267#issuecomment-2252749509
|
|
103
|
+
* @param {duckdb.AsyncDuckDBConnection} con The DuckDB-WASM connection.
|
|
104
|
+
* @param {string} query The SQL query to run.
|
|
105
|
+
*/
|
|
106
|
+
function getArrowIPC(con, query) {
|
|
107
|
+
return new Promise((resolve, reject) => {
|
|
108
|
+
con.useUnsafe(async (bindings, conn) => {
|
|
109
|
+
try {
|
|
110
|
+
const buffer = await bindings.runQuery(conn, query);
|
|
111
|
+
resolve(buffer);
|
|
112
|
+
} catch (error) {
|
|
113
|
+
reject(error);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Establish a new database connection for the given connector.
|
|
121
|
+
* @param {DuckDBWASMConnector} c The connector.
|
|
122
|
+
* @returns {Promise<unknown>}
|
|
123
|
+
*/
|
|
124
|
+
function connect(c) {
|
|
125
|
+
if (!c._loadPromise) {
|
|
126
|
+
// use a loading promise to avoid race conditions
|
|
127
|
+
// synchronizes multiple callees on the same load
|
|
128
|
+
c._loadPromise = (
|
|
129
|
+
c._db
|
|
130
|
+
? Promise.resolve(c._db)
|
|
131
|
+
: initDatabase(c._options).then(result => c._db = result))
|
|
132
|
+
.then(db => db.connect())
|
|
133
|
+
.then(result => c._con = result);
|
|
134
|
+
}
|
|
135
|
+
return c._loadPromise;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Initialize a new DuckDB-WASM instance.
|
|
140
|
+
* @param {DuckDBWASMOptions} options
|
|
141
|
+
*/
|
|
79
142
|
async function initDatabase({
|
|
80
143
|
log = false
|
|
81
144
|
} = {}) {
|
package/src/index-types.ts
CHANGED
package/src/make-client.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import {
|
|
1
|
+
/**
|
|
2
|
+
* @import { ExprNode, SelectQuery } from '@uwdata/mosaic-sql'
|
|
3
|
+
* @import { Coordinator } from '../Coordinator.js'
|
|
4
|
+
* @import { MosaicClient } from '../MosaicClient.js'
|
|
5
|
+
* @import { Selection } from '../Selection.js'
|
|
6
|
+
* @import { BinMethod, Scale, SelectionClause } from '../util/selection-types.js'
|
|
7
|
+
*/
|
|
8
|
+
import { Query, and, asNode, ceil, collectColumns, createTable, float64, floor, isBetween, int32, mul, round, scaleTransform, sub, isSelectQuery, isAggregateExpression, ColumnNameRefNode } from '@uwdata/mosaic-sql';
|
|
7
9
|
import { preaggColumns } from './preagg-columns.js';
|
|
8
10
|
import { fnv_hash } from '../util/hash.js';
|
|
9
11
|
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
1
|
+
/**
|
|
2
|
+
* @import { AggregateNode, ExprNode, Query, SelectQuery } from '@uwdata/mosaic-sql'
|
|
3
|
+
* @import { MosaicClient } from '../MosaicClient.js'
|
|
4
|
+
*/
|
|
5
|
+
import { collectAggregates, isAggregateExpression, isSelectQuery, isTableRef, rewrite, sql } from '@uwdata/mosaic-sql';
|
|
3
6
|
import { sufficientStatistics } from './sufficient-statistics.js';
|
|
4
7
|
|
|
5
8
|
/**
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { AggregateNode,
|
|
1
|
+
/** @import { AggregateNode, ExprNode } from '@uwdata/mosaic-sql' */
|
|
2
|
+
import { and, argmax, argmin, coalesce, count, div, exp, isNotNull, ln, max, min, mul, pow, regrAvgX, regrAvgY, regrCount, sql, sqrt, sub, sum } from '@uwdata/mosaic-sql';
|
|
2
3
|
import { fnv_hash } from '../util/hash.js';
|
|
3
4
|
|
|
4
5
|
/**
|
package/src/types.ts
CHANGED
|
@@ -62,3 +62,26 @@ export interface Activatable {
|
|
|
62
62
|
*/
|
|
63
63
|
activate(): void;
|
|
64
64
|
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Interface for cache implementations.
|
|
68
|
+
*/
|
|
69
|
+
export interface Cache {
|
|
70
|
+
get(key: string): any;
|
|
71
|
+
set(key: string, value: any): any;
|
|
72
|
+
clear(): void;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Interface for logger implementations
|
|
77
|
+
*/
|
|
78
|
+
export interface Logger {
|
|
79
|
+
debug(...args: any[]): void;
|
|
80
|
+
info(...args: any[]): void;
|
|
81
|
+
log(...args: any[]): void;
|
|
82
|
+
warn(...args: any[]): void;
|
|
83
|
+
error(...args: any[]): void;
|
|
84
|
+
group(label?: any): void;
|
|
85
|
+
groupCollapsed(label?: any): void;
|
|
86
|
+
groupEnd(): void;
|
|
87
|
+
}
|
package/src/util/cache.js
CHANGED
|
@@ -1,13 +1,28 @@
|
|
|
1
|
+
/** @import { Cache } from '../types.js' */
|
|
2
|
+
|
|
1
3
|
const requestIdle = typeof requestIdleCallback !== 'undefined'
|
|
2
4
|
? requestIdleCallback
|
|
3
5
|
: setTimeout;
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Create a new cache that ignores all values.
|
|
9
|
+
* @returns {Cache}
|
|
10
|
+
*/
|
|
11
|
+
export function voidCache() {
|
|
12
|
+
return {
|
|
13
|
+
get: () => undefined,
|
|
14
|
+
set: (key, value) => value,
|
|
15
|
+
clear: () => {}
|
|
16
|
+
};
|
|
17
|
+
}
|
|
10
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Create a new cache that uses an LRU eviction policy.
|
|
21
|
+
* @param {object} [options] Cache options.
|
|
22
|
+
* @param {number} [options.max] Maximum number of cache entries.
|
|
23
|
+
* @param {number} [options.ttl] Time-to-live for cache entries.
|
|
24
|
+
* @returns {Cache}
|
|
25
|
+
*/
|
|
11
26
|
export function lruCache({
|
|
12
27
|
max = 1000, // max entries
|
|
13
28
|
ttl = 3 * 60 * 60 * 1000 // time-to-live, default 3 hours
|
package/src/util/decode-ipc.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
+
/** @import { ExtractionOptions, Table } from '@uwdata/flechette' */
|
|
1
2
|
import { tableFromIPC } from '@uwdata/flechette';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
|
-
* Decode Arrow IPC bytes to a table instance
|
|
5
|
-
* timestamp values to JS Date objects.
|
|
5
|
+
* Decode Arrow IPC bytes to a table instance.
|
|
6
|
+
* The default options map date and timestamp values to JS Date objects.
|
|
6
7
|
* @param {ArrayBuffer | Uint8Array} data Arrow IPC bytes.
|
|
7
|
-
* @
|
|
8
|
+
* @param {ExtractionOptions} [options] Arrow IPC extraction options.
|
|
9
|
+
* If unspecified, the default options will extract date and timestamp
|
|
10
|
+
* values to JS Date objects.
|
|
11
|
+
* @returns {Table} A table instance.
|
|
8
12
|
*/
|
|
9
|
-
export function decodeIPC(data) {
|
|
10
|
-
return tableFromIPC(data,
|
|
13
|
+
export function decodeIPC(data, options = { useDate: true }) {
|
|
14
|
+
return tableFromIPC(data, options);
|
|
11
15
|
}
|
package/src/util/field-info.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { AggregateNode
|
|
1
|
+
/** @import { AggregateNode } from '@uwdata/mosaic-sql' */
|
|
2
|
+
import { Query, asTableRef, count, isAggregateExpression, isNode, isNull, max, min, sql } from '@uwdata/mosaic-sql';
|
|
2
3
|
import { jsType } from './js-type.js';
|
|
3
4
|
|
|
4
5
|
export const Count = 'count';
|
package/src/util/js-type.js
CHANGED
|
@@ -41,7 +41,9 @@ export function jsType(type) {
|
|
|
41
41
|
case 'GEOMETRY':
|
|
42
42
|
return 'object';
|
|
43
43
|
default:
|
|
44
|
-
if (type.startsWith('
|
|
44
|
+
if (type.startsWith('ENUM')) {
|
|
45
|
+
return 'string';
|
|
46
|
+
} else if (type.startsWith('DECIMAL')) {
|
|
45
47
|
return 'number';
|
|
46
48
|
} else if (type.startsWith('STRUCT') || type.startsWith('MAP')) {
|
|
47
49
|
return 'object';
|