Package not found. Please check the package name and try again.

@uwdata/mosaic-core 0.8.0 → 0.9.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.
@@ -0,0 +1,147 @@
1
+ import {
2
+ SQLExpression, and, contains, isBetween, isNotDistinct, literal,
3
+ or, prefix, regexp_matches, suffix
4
+ } from '@uwdata/mosaic-sql';
5
+ import { MosaicClient } from './MosaicClient.js';
6
+
7
+ /**
8
+ * @typedef {import('./util/selection-types.js').SelectionClause} SelectionClause
9
+ * @typedef {import('./util/selection-types.js').Scale} Scale
10
+ * @typedef {import('./util/selection-types.js').Extent} Extent
11
+ * @typedef {import('./util/selection-types.js').MatchMethod} MatchMethod
12
+ * @typedef {import('./util/selection-types.js').BinMethod} BinMethod
13
+ * @typedef {SQLExpression | string} Field
14
+ */
15
+
16
+ /**
17
+ * Generate a selection clause for a single selected point value.
18
+ * @param {Field} field The table column or expression to select.
19
+ * @param {*} value The selected value.
20
+ * @param {object} options Additional clause properties.
21
+ * @param {*} options.source The source component generating this clause.
22
+ * @param {Set<MosaicClient>} [options.clients] The Mosaic clients associated
23
+ * with this clause. These clients are not filtered by this clause in
24
+ * cross-filtering contexts.
25
+ * @returns {SelectionClause} The generated selection clause.
26
+ */
27
+ export function point(field, value, { source, clients = undefined }) {
28
+ /** @type {SQLExpression | null} */
29
+ const predicate = value !== undefined
30
+ ? isNotDistinct(field, literal(value))
31
+ : null;
32
+ return {
33
+ meta: { type: 'point' },
34
+ source,
35
+ clients,
36
+ value,
37
+ predicate
38
+ };
39
+ }
40
+
41
+ /**
42
+ * Generate a selection clause for multiple selected point values.
43
+ * @param {Field[]} fields The table columns or expressions to select.
44
+ * @param {any[][]} value The selected values, as an array of arrays where
45
+ * each subarray contains values corresponding to each *fields* entry.
46
+ * @param {object} options Additional clause properties.
47
+ * @param {*} options.source The source component generating this clause.
48
+ * @param {Set<MosaicClient>} [options.clients] The Mosaic clients associated
49
+ * with this clause. These clients are not filtered by this clause in
50
+ * cross-filtering contexts.
51
+ * @returns {SelectionClause} The generated selection clause.
52
+ */
53
+ export function points(fields, value, { source, clients = undefined }) {
54
+ /** @type {SQLExpression | null} */
55
+ let predicate = null;
56
+ if (value) {
57
+ const clauses = value.map(vals => {
58
+ const list = vals.map((v, i) => isNotDistinct(fields[i], literal(v)));
59
+ return list.length > 1 ? and(list) : list[0];
60
+ });
61
+ predicate = clauses.length > 1 ? or(clauses) : clauses[0];
62
+ }
63
+ return {
64
+ meta: { type: 'point' },
65
+ source,
66
+ clients,
67
+ value,
68
+ predicate
69
+ };
70
+ }
71
+
72
+ /**
73
+ * Generate a selection clause for a selected 1D interval.
74
+ * @param {Field} field The table column or expression to select.
75
+ * @param {Extent} value The selected interval as a [lo, hi] array.
76
+ * @param {object} options Additional clause properties.
77
+ * @param {*} options.source The source component generating this clause.
78
+ * @param {Set<MosaicClient>} [options.clients] The Mosaic clients associated
79
+ * with this clause. These clients are not filtered by this clause in
80
+ * cross-filtering contexts.
81
+ * @param {Scale} [options.scale] The scale mapping descriptor.
82
+ * @param {BinMethod} [options.bin] A binning method hint.
83
+ * @param {number} [options.pixelSize=1] The interactive pixel size.
84
+ * @returns {SelectionClause} The generated selection clause.
85
+ */
86
+ export function interval(field, value, {
87
+ source, clients, bin, scale, pixelSize = 1
88
+ }) {
89
+ /** @type {SQLExpression | null} */
90
+ const predicate = value != null ? isBetween(field, value) : null;
91
+ /** @type {import('./util/selection-types.js').IntervalMetadata} */
92
+ const meta = { type: 'interval', scales: [scale], bin, pixelSize };
93
+ return { meta, source, clients, value, predicate };
94
+ }
95
+
96
+ /**
97
+ * Generate a selection clause for multiple selected intervals.
98
+ * @param {Field[]} fields The table columns or expressions to select.
99
+ * @param {Extent[]} value The selected intervals, as an array of extents.
100
+ * @param {object} options Additional clause properties.
101
+ * @param {*} options.source The source component generating this clause.
102
+ * @param {Set<MosaicClient>} [options.clients] The Mosaic clients associated
103
+ * with this clause. These clients are not filtered by this clause in
104
+ * cross-filtering contexts.
105
+ * @param {Scale[]} [options.scales] The scale mapping descriptors,
106
+ * in an order matching the given *fields* and *value* extents.
107
+ * @param {BinMethod} [options.bin] A binning method hint.
108
+ * @param {number} [options.pixelSize=1] The interactive pixel size.
109
+ * @returns {SelectionClause} The generated selection clause.
110
+ */
111
+ export function intervals(fields, value, {
112
+ source, clients, bin, scales = [], pixelSize = 1
113
+ }) {
114
+ /** @type {SQLExpression | null} */
115
+ const predicate = value != null
116
+ ? and(fields.map((f, i) => isBetween(f, value[i])))
117
+ : null;
118
+ /** @type {import('./util/selection-types.js').IntervalMetadata} */
119
+ const meta = { type: 'interval', scales, bin, pixelSize };
120
+ return { meta, source, clients, value, predicate };
121
+ }
122
+
123
+ const MATCH_METHODS = { contains, prefix, suffix, regexp: regexp_matches };
124
+
125
+ /**
126
+ * Generate a selection clause for text search matching.
127
+ * @param {Field} field The table column or expression to select.
128
+ * @param {string} value The selected text search query string.
129
+ * @param {object} options Additional clause properties.
130
+ * @param {*} options.source The source component generating this clause.
131
+ * @param {Set<MosaicClient>} [options.clients] The Mosaic clients associated
132
+ * with this clause. These clients are not filtered by this clause in
133
+ * cross-filtering contexts.
134
+ * @param {MatchMethod} [options.method] The
135
+ * text matching method to use. Defaults to `'contains'`.
136
+ * @returns {SelectionClause} The generated selection clause.
137
+ */
138
+ export function match(field, value, {
139
+ source, clients = undefined, method = 'contains'
140
+ }) {
141
+ let fn = MATCH_METHODS[method];
142
+ /** @type {SQLExpression | null} */
143
+ const predicate = value ? fn(field, literal(value)) : null;
144
+ /** @type {import('./util/selection-types.js').MatchMetadata} */
145
+ const meta = { type: 'match', method };
146
+ return { meta, source, clients, value, predicate };
147
+ }
@@ -2,6 +2,13 @@ import { tableFromIPC } from 'apache-arrow';
2
2
 
3
3
  export function restConnector(uri = 'http://localhost:3000/') {
4
4
  return {
5
+ /**
6
+ * Query the DuckDB server.
7
+ * @param {object} query
8
+ * @param {'exec' | 'arrow' | 'json'} [query.type] The query type: 'exec', 'arrow', or 'json'.
9
+ * @param {string} query.sql A SQL query string.
10
+ * @returns the query result
11
+ */
5
12
  async query(query) {
6
13
  const req = fetch(uri, {
7
14
  method: 'POST',
@@ -81,6 +81,13 @@ export function socketConnector(uri = 'ws://localhost:3000/') {
81
81
  get connected() {
82
82
  return connected;
83
83
  },
84
+ /**
85
+ * Query the DuckDB server.
86
+ * @param {object} query
87
+ * @param {'exec' | 'arrow' | 'json'} [query.type] The query type: 'exec', 'arrow', or 'json'.
88
+ * @param {string} query.sql A SQL query string.
89
+ * @returns the query result
90
+ */
84
91
  query(query) {
85
92
  return new Promise(
86
93
  (resolve, reject) => enqueue(query, resolve, reject)
@@ -45,7 +45,7 @@ export function wasmConnector(options = {}) {
45
45
  /**
46
46
  * Query the DuckDB-WASM instance.
47
47
  * @param {object} query
48
- * @param {string} [query.type] The query type: 'exec', 'arrow', or 'json'.
48
+ * @param {'exec' | 'arrow' | 'json'} [query.type] The query type: 'exec', 'arrow', or 'json'.
49
49
  * @param {string} query.sql A SQL query string.
50
50
  * @returns the query result
51
51
  */
@@ -55,7 +55,7 @@ export function wasmConnector(options = {}) {
55
55
  const result = await con.query(sql);
56
56
  return type === 'exec' ? undefined
57
57
  : type === 'arrow' ? result
58
- : Array.from(result);
58
+ : result.toArray();
59
59
  }
60
60
  };
61
61
  }
package/src/index.js CHANGED
@@ -3,6 +3,7 @@ export { Coordinator, coordinator } from './Coordinator.js';
3
3
  export { Selection, isSelection } from './Selection.js';
4
4
  export { Param, isParam } from './Param.js';
5
5
  export { Priority } from './QueryManager.js';
6
+ export { point, points, interval, intervals, match } from './SelectionClause.js';
6
7
 
7
8
  export { restConnector } from './connectors/rest.js';
8
9
  export { socketConnector } from './connectors/socket.js';
@@ -1,5 +1,9 @@
1
1
  import { DataType } from 'apache-arrow';
2
2
 
3
+ /**
4
+ * @typedef {import('apache-arrow').Vector} Vector
5
+ */
6
+
3
7
  /**
4
8
  * Test if a value is an Apache Arrow table.
5
9
  * As sometimes multiple Arrow versions may be used simultaneously,
@@ -58,7 +62,7 @@ export function convertArrowValue(type) {
58
62
  * Large integers (BigInt) are converted to Float64 numbers.
59
63
  * Fixed-point decimal values are convert to Float64 numbers.
60
64
  * Otherwise, the default Arrow values are used.
61
- * @param {*} column An Apache Arrow column
65
+ * @param {Vector} column An Apache Arrow column
62
66
  * @returns an array of values
63
67
  */
64
68
  export function convertArrowColumn(column) {
@@ -78,10 +82,10 @@ export function convertArrowColumn(column) {
78
82
  // map bigint to number
79
83
  if (DataType.isInt(type) && type.bitWidth >= 64) {
80
84
  const size = column.length;
81
- const array = new Float64Array(size);
85
+ const array = column.nullCount ? new Array(size) : new Float64Array(size);
82
86
  for (let row = 0; row < size; ++row) {
83
87
  const v = column.get(row);
84
- array[row] = v == null ? NaN : Number(v);
88
+ array[row] = v == null ? null : Number(v);
85
89
  }
86
90
  return array;
87
91
  }
@@ -90,14 +94,19 @@ export function convertArrowColumn(column) {
90
94
  if (DataType.isDecimal(type)) {
91
95
  const scale = 1 / Math.pow(10, type.scale);
92
96
  const size = column.length;
93
- const array = new Float64Array(size);
97
+ const array = column.nullCount ? new Array(size) : new Float64Array(size);
94
98
  for (let row = 0; row < size; ++row) {
95
99
  const v = column.get(row);
96
- array[row] = v == null ? NaN : decimalToNumber(v, scale);
100
+ array[row] = v == null ? null : decimalToNumber(v, scale);
97
101
  }
98
102
  return array;
99
103
  }
100
104
 
105
+ // if there are null values, use a standard array
106
+ if (column.nullCount) {
107
+ return Array.from(column);
108
+ }
109
+
101
110
  // otherwise use Arrow JS defaults
102
111
  return column.toArray();
103
112
  }