@uwdata/mosaic-inputs 0.8.0 → 0.10.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/dist/mosaic-inputs.js +1220 -550
- package/dist/mosaic-inputs.min.js +6 -6
- package/package.json +5 -5
- package/src/Menu.js +66 -21
- package/src/Search.js +31 -15
- package/src/Slider.js +91 -34
- package/src/Table.js +53 -10
package/dist/mosaic-inputs.js
CHANGED
|
@@ -123,7 +123,6 @@ var MosaicClient = class {
|
|
|
123
123
|
* @returns {this}
|
|
124
124
|
*/
|
|
125
125
|
queryError(error) {
|
|
126
|
-
console.error(error);
|
|
127
126
|
return this;
|
|
128
127
|
}
|
|
129
128
|
/**
|
|
@@ -147,7 +146,7 @@ var MosaicClient = class {
|
|
|
147
146
|
/**
|
|
148
147
|
* Requests a client update.
|
|
149
148
|
* For example to (re-)render an interface component.
|
|
150
|
-
*
|
|
149
|
+
*
|
|
151
150
|
* @returns {this | Promise<any>}
|
|
152
151
|
*/
|
|
153
152
|
update() {
|
|
@@ -211,16 +210,24 @@ function __await(v) {
|
|
|
211
210
|
function __asyncGenerator(thisArg, _arguments, generator) {
|
|
212
211
|
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
213
212
|
var g = generator.apply(thisArg, _arguments || []), i, q = [];
|
|
214
|
-
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function() {
|
|
213
|
+
return i = {}, verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function() {
|
|
215
214
|
return this;
|
|
216
215
|
}, i;
|
|
217
|
-
function
|
|
218
|
-
|
|
219
|
-
return
|
|
220
|
-
q.push([n, v, a, b]) > 1 || resume(n, v);
|
|
221
|
-
});
|
|
216
|
+
function awaitReturn(f) {
|
|
217
|
+
return function(v) {
|
|
218
|
+
return Promise.resolve(v).then(f, reject);
|
|
222
219
|
};
|
|
223
220
|
}
|
|
221
|
+
function verb(n, f) {
|
|
222
|
+
if (g[n]) {
|
|
223
|
+
i[n] = function(v) {
|
|
224
|
+
return new Promise(function(a, b) {
|
|
225
|
+
q.push([n, v, a, b]) > 1 || resume(n, v);
|
|
226
|
+
});
|
|
227
|
+
};
|
|
228
|
+
if (f) i[n] = f(i[n]);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
224
231
|
function resume(n, v) {
|
|
225
232
|
try {
|
|
226
233
|
step(g[n](v));
|
|
@@ -840,26 +847,26 @@ var IntervalUnit;
|
|
|
840
847
|
IntervalUnit2[IntervalUnit2["MONTH_DAY_NANO"] = 2] = "MONTH_DAY_NANO";
|
|
841
848
|
})(IntervalUnit || (IntervalUnit = {}));
|
|
842
849
|
|
|
843
|
-
// ../../node_modules/flatbuffers/mjs/constants.js
|
|
850
|
+
// ../../node_modules/apache-arrow/node_modules/flatbuffers/mjs/constants.js
|
|
844
851
|
var SIZEOF_SHORT = 2;
|
|
845
852
|
var SIZEOF_INT = 4;
|
|
846
853
|
var FILE_IDENTIFIER_LENGTH = 4;
|
|
847
854
|
var SIZE_PREFIX_LENGTH = 4;
|
|
848
855
|
|
|
849
|
-
// ../../node_modules/flatbuffers/mjs/utils.js
|
|
856
|
+
// ../../node_modules/apache-arrow/node_modules/flatbuffers/mjs/utils.js
|
|
850
857
|
var int32 = new Int32Array(2);
|
|
851
858
|
var float32 = new Float32Array(int32.buffer);
|
|
852
859
|
var float64 = new Float64Array(int32.buffer);
|
|
853
860
|
var isLittleEndian = new Uint16Array(new Uint8Array([1, 0]).buffer)[0] === 1;
|
|
854
861
|
|
|
855
|
-
// ../../node_modules/flatbuffers/mjs/encoding.js
|
|
862
|
+
// ../../node_modules/apache-arrow/node_modules/flatbuffers/mjs/encoding.js
|
|
856
863
|
var Encoding;
|
|
857
864
|
(function(Encoding2) {
|
|
858
865
|
Encoding2[Encoding2["UTF8_BYTES"] = 1] = "UTF8_BYTES";
|
|
859
866
|
Encoding2[Encoding2["UTF16_STRING"] = 2] = "UTF16_STRING";
|
|
860
867
|
})(Encoding || (Encoding = {}));
|
|
861
868
|
|
|
862
|
-
// ../../node_modules/flatbuffers/mjs/byte-buffer.js
|
|
869
|
+
// ../../node_modules/apache-arrow/node_modules/flatbuffers/mjs/byte-buffer.js
|
|
863
870
|
var ByteBuffer = class _ByteBuffer {
|
|
864
871
|
/**
|
|
865
872
|
* Create a new ByteBuffer with a given array of bytes (`Uint8Array`)
|
|
@@ -1103,7 +1110,7 @@ var ByteBuffer = class _ByteBuffer {
|
|
|
1103
1110
|
}
|
|
1104
1111
|
};
|
|
1105
1112
|
|
|
1106
|
-
// ../../node_modules/flatbuffers/mjs/builder.js
|
|
1113
|
+
// ../../node_modules/apache-arrow/node_modules/flatbuffers/mjs/builder.js
|
|
1107
1114
|
var Builder = class _Builder {
|
|
1108
1115
|
/**
|
|
1109
1116
|
* Create a FlatBufferBuilder.
|
|
@@ -1543,9 +1550,22 @@ var Builder = class _Builder {
|
|
|
1543
1550
|
this.addInt8(0);
|
|
1544
1551
|
this.startVector(1, utf8.length, 1);
|
|
1545
1552
|
this.bb.setPosition(this.space -= utf8.length);
|
|
1546
|
-
|
|
1547
|
-
|
|
1553
|
+
this.bb.bytes().set(utf8, this.space);
|
|
1554
|
+
return this.endVector();
|
|
1555
|
+
}
|
|
1556
|
+
/**
|
|
1557
|
+
* Create a byte vector.
|
|
1558
|
+
*
|
|
1559
|
+
* @param v The bytes to add
|
|
1560
|
+
* @returns The offset in the buffer where the byte vector starts
|
|
1561
|
+
*/
|
|
1562
|
+
createByteVector(v) {
|
|
1563
|
+
if (v === null || v === void 0) {
|
|
1564
|
+
return 0;
|
|
1548
1565
|
}
|
|
1566
|
+
this.startVector(1, v.length, 1);
|
|
1567
|
+
this.bb.setPosition(this.space -= v.length);
|
|
1568
|
+
this.bb.bytes().set(v, this.space);
|
|
1549
1569
|
return this.endVector();
|
|
1550
1570
|
}
|
|
1551
1571
|
/**
|
|
@@ -3148,9 +3168,9 @@ var BufferType;
|
|
|
3148
3168
|
// ../../node_modules/apache-arrow/util/vector.mjs
|
|
3149
3169
|
var vector_exports = {};
|
|
3150
3170
|
__export(vector_exports, {
|
|
3151
|
-
clampIndex: () => clampIndex,
|
|
3152
3171
|
clampRange: () => clampRange,
|
|
3153
|
-
createElementComparator: () => createElementComparator
|
|
3172
|
+
createElementComparator: () => createElementComparator,
|
|
3173
|
+
wrapIndex: () => wrapIndex
|
|
3154
3174
|
});
|
|
3155
3175
|
|
|
3156
3176
|
// ../../node_modules/apache-arrow/util/pretty.mjs
|
|
@@ -3191,9 +3211,23 @@ var bn_exports = {};
|
|
|
3191
3211
|
__export(bn_exports, {
|
|
3192
3212
|
BN: () => BN,
|
|
3193
3213
|
bigNumToBigInt: () => bigNumToBigInt,
|
|
3214
|
+
bigNumToNumber: () => bigNumToNumber,
|
|
3194
3215
|
bigNumToString: () => bigNumToString,
|
|
3195
3216
|
isArrowBigNumSymbol: () => isArrowBigNumSymbol
|
|
3196
3217
|
});
|
|
3218
|
+
|
|
3219
|
+
// ../../node_modules/apache-arrow/util/bigint.mjs
|
|
3220
|
+
function bigIntToNumber(number) {
|
|
3221
|
+
if (typeof number === "bigint" && (number < Number.MIN_SAFE_INTEGER || number > Number.MAX_SAFE_INTEGER)) {
|
|
3222
|
+
throw new TypeError(`${number} is not safe to convert to a number.`);
|
|
3223
|
+
}
|
|
3224
|
+
return Number(number);
|
|
3225
|
+
}
|
|
3226
|
+
function divideBigInts(number, divisor) {
|
|
3227
|
+
return bigIntToNumber(number / divisor) + bigIntToNumber(number % divisor) / bigIntToNumber(divisor);
|
|
3228
|
+
}
|
|
3229
|
+
|
|
3230
|
+
// ../../node_modules/apache-arrow/util/bn.mjs
|
|
3197
3231
|
var isArrowBigNumSymbol = Symbol.for("isArrowBigNum");
|
|
3198
3232
|
function BigNum(x2, ...xs) {
|
|
3199
3233
|
if (xs.length === 0) {
|
|
@@ -3205,8 +3239,8 @@ BigNum.prototype[isArrowBigNumSymbol] = true;
|
|
|
3205
3239
|
BigNum.prototype.toJSON = function() {
|
|
3206
3240
|
return `"${bigNumToString(this)}"`;
|
|
3207
3241
|
};
|
|
3208
|
-
BigNum.prototype.valueOf = function() {
|
|
3209
|
-
return bigNumToNumber(this);
|
|
3242
|
+
BigNum.prototype.valueOf = function(scale) {
|
|
3243
|
+
return bigNumToNumber(this, scale);
|
|
3210
3244
|
};
|
|
3211
3245
|
BigNum.prototype.toString = function() {
|
|
3212
3246
|
return bigNumToString(this);
|
|
@@ -3237,25 +3271,34 @@ Object.setPrototypeOf(DecimalBigNum.prototype, Object.create(Uint32Array.prototy
|
|
|
3237
3271
|
Object.assign(SignedBigNum.prototype, BigNum.prototype, { "constructor": SignedBigNum, "signed": true, "TypedArray": Int32Array, "BigIntArray": BigInt64Array });
|
|
3238
3272
|
Object.assign(UnsignedBigNum.prototype, BigNum.prototype, { "constructor": UnsignedBigNum, "signed": false, "TypedArray": Uint32Array, "BigIntArray": BigUint64Array });
|
|
3239
3273
|
Object.assign(DecimalBigNum.prototype, BigNum.prototype, { "constructor": DecimalBigNum, "signed": true, "TypedArray": Uint32Array, "BigIntArray": BigUint64Array });
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3274
|
+
var TWO_TO_THE_64 = BigInt(4294967296) * BigInt(4294967296);
|
|
3275
|
+
var TWO_TO_THE_64_MINUS_1 = TWO_TO_THE_64 - BigInt(1);
|
|
3276
|
+
function bigNumToNumber(bn, scale) {
|
|
3277
|
+
const { buffer, byteOffset, byteLength, "signed": signed } = bn;
|
|
3278
|
+
const words = new BigUint64Array(buffer, byteOffset, byteLength / 8);
|
|
3243
3279
|
const negative = signed && words.at(-1) & BigInt(1) << BigInt(63);
|
|
3244
|
-
let number =
|
|
3245
|
-
let i =
|
|
3246
|
-
if (
|
|
3280
|
+
let number = BigInt(0);
|
|
3281
|
+
let i = 0;
|
|
3282
|
+
if (negative) {
|
|
3247
3283
|
for (const word of words) {
|
|
3248
|
-
number
|
|
3284
|
+
number |= (word ^ TWO_TO_THE_64_MINUS_1) * (BigInt(1) << BigInt(64 * i++));
|
|
3249
3285
|
}
|
|
3286
|
+
number *= BigInt(-1);
|
|
3287
|
+
number -= BigInt(1);
|
|
3250
3288
|
} else {
|
|
3251
3289
|
for (const word of words) {
|
|
3252
|
-
number
|
|
3290
|
+
number |= word * (BigInt(1) << BigInt(64 * i++));
|
|
3253
3291
|
}
|
|
3254
|
-
number *= BigInt(-1);
|
|
3255
3292
|
}
|
|
3256
|
-
|
|
3293
|
+
if (typeof scale === "number") {
|
|
3294
|
+
const denominator = BigInt(Math.pow(10, scale));
|
|
3295
|
+
const quotient = number / denominator;
|
|
3296
|
+
const remainder = number % denominator;
|
|
3297
|
+
return bigIntToNumber(quotient) + bigIntToNumber(remainder) / bigIntToNumber(denominator);
|
|
3298
|
+
}
|
|
3299
|
+
return bigIntToNumber(number);
|
|
3257
3300
|
}
|
|
3258
|
-
|
|
3301
|
+
function bigNumToString(a) {
|
|
3259
3302
|
if (a.byteLength === 8) {
|
|
3260
3303
|
const bigIntArray = new a["BigIntArray"](a.buffer, a.byteOffset, 1);
|
|
3261
3304
|
return `${bigIntArray[0]}`;
|
|
@@ -3278,15 +3321,15 @@ var bigNumToString = (a) => {
|
|
|
3278
3321
|
}
|
|
3279
3322
|
const negated = unsignedBigNumToString(array);
|
|
3280
3323
|
return `-${negated}`;
|
|
3281
|
-
}
|
|
3282
|
-
|
|
3324
|
+
}
|
|
3325
|
+
function bigNumToBigInt(a) {
|
|
3283
3326
|
if (a.byteLength === 8) {
|
|
3284
3327
|
const bigIntArray = new a["BigIntArray"](a.buffer, a.byteOffset, 1);
|
|
3285
3328
|
return bigIntArray[0];
|
|
3286
3329
|
} else {
|
|
3287
3330
|
return bigNumToString(a);
|
|
3288
3331
|
}
|
|
3289
|
-
}
|
|
3332
|
+
}
|
|
3290
3333
|
function unsignedBigNumToString(a) {
|
|
3291
3334
|
let digits = "";
|
|
3292
3335
|
const base64 = new Uint32Array(2);
|
|
@@ -3343,14 +3386,6 @@ var BN = class _BN {
|
|
|
3343
3386
|
}
|
|
3344
3387
|
};
|
|
3345
3388
|
|
|
3346
|
-
// ../../node_modules/apache-arrow/util/bigint.mjs
|
|
3347
|
-
function bigIntToNumber(number) {
|
|
3348
|
-
if (typeof number === "bigint" && (number < Number.MIN_SAFE_INTEGER || number > Number.MAX_SAFE_INTEGER)) {
|
|
3349
|
-
throw new TypeError(`${number} is not safe to convert to a number.`);
|
|
3350
|
-
}
|
|
3351
|
-
return Number(number);
|
|
3352
|
-
}
|
|
3353
|
-
|
|
3354
3389
|
// ../../node_modules/apache-arrow/type.mjs
|
|
3355
3390
|
var _a;
|
|
3356
3391
|
var _b;
|
|
@@ -3725,11 +3760,13 @@ var Date_ = class extends DataType {
|
|
|
3725
3760
|
toString() {
|
|
3726
3761
|
return `Date${(this.unit + 1) * 32}<${DateUnit[this.unit]}>`;
|
|
3727
3762
|
}
|
|
3763
|
+
get ArrayType() {
|
|
3764
|
+
return this.unit === DateUnit.DAY ? Int32Array : BigInt64Array;
|
|
3765
|
+
}
|
|
3728
3766
|
};
|
|
3729
3767
|
_l = Symbol.toStringTag;
|
|
3730
3768
|
Date_[_l] = ((proto) => {
|
|
3731
3769
|
proto.unit = null;
|
|
3732
|
-
proto.ArrayType = Int32Array;
|
|
3733
3770
|
return proto[Symbol.toStringTag] = "Date";
|
|
3734
3771
|
})(Date_.prototype);
|
|
3735
3772
|
var Time_ = class extends DataType {
|
|
@@ -3771,7 +3808,7 @@ _o = Symbol.toStringTag;
|
|
|
3771
3808
|
Timestamp_[_o] = ((proto) => {
|
|
3772
3809
|
proto.unit = null;
|
|
3773
3810
|
proto.timezone = null;
|
|
3774
|
-
proto.ArrayType =
|
|
3811
|
+
proto.ArrayType = BigInt64Array;
|
|
3775
3812
|
return proto[Symbol.toStringTag] = "Timestamp";
|
|
3776
3813
|
})(Timestamp_.prototype);
|
|
3777
3814
|
var Interval_ = class extends DataType {
|
|
@@ -3976,10 +4013,6 @@ function strideForType(type) {
|
|
|
3976
4013
|
switch (type.typeId) {
|
|
3977
4014
|
case Type2.Decimal:
|
|
3978
4015
|
return type.bitWidth / 32;
|
|
3979
|
-
case Type2.Timestamp:
|
|
3980
|
-
return 2;
|
|
3981
|
-
case Type2.Date:
|
|
3982
|
-
return 1 + t.unit;
|
|
3983
4016
|
case Type2.Interval:
|
|
3984
4017
|
return 1 + t.unit;
|
|
3985
4018
|
case Type2.FixedSizeList:
|
|
@@ -4446,19 +4479,7 @@ function wrapSet(fn) {
|
|
|
4446
4479
|
};
|
|
4447
4480
|
}
|
|
4448
4481
|
var setEpochMsToDays = (data, index, epochMs) => {
|
|
4449
|
-
data[index] = Math.
|
|
4450
|
-
};
|
|
4451
|
-
var setEpochMsToMillisecondsLong = (data, index, epochMs) => {
|
|
4452
|
-
data[index] = Math.trunc(epochMs % 4294967296);
|
|
4453
|
-
data[index + 1] = Math.trunc(epochMs / 4294967296);
|
|
4454
|
-
};
|
|
4455
|
-
var setEpochMsToMicrosecondsLong = (data, index, epochMs) => {
|
|
4456
|
-
data[index] = Math.trunc(epochMs * 1e3 % 4294967296);
|
|
4457
|
-
data[index + 1] = Math.trunc(epochMs * 1e3 / 4294967296);
|
|
4458
|
-
};
|
|
4459
|
-
var setEpochMsToNanosecondsLong = (data, index, epochMs) => {
|
|
4460
|
-
data[index] = Math.trunc(epochMs * 1e6 % 4294967296);
|
|
4461
|
-
data[index + 1] = Math.trunc(epochMs * 1e6 / 4294967296);
|
|
4482
|
+
data[index] = Math.floor(epochMs / 864e5);
|
|
4462
4483
|
};
|
|
4463
4484
|
var setVariableWidthBytes = (values, valueOffsets, index, value) => {
|
|
4464
4485
|
if (index + 1 < valueOffsets.length) {
|
|
@@ -4493,7 +4514,7 @@ var setDateDay = ({ values }, index, value) => {
|
|
|
4493
4514
|
setEpochMsToDays(values, index, value.valueOf());
|
|
4494
4515
|
};
|
|
4495
4516
|
var setDateMillisecond = ({ values }, index, value) => {
|
|
4496
|
-
|
|
4517
|
+
values[index] = BigInt(value);
|
|
4497
4518
|
};
|
|
4498
4519
|
var setFixedSizeBinary = ({ stride, values }, index, value) => {
|
|
4499
4520
|
values.set(value.subarray(0, stride), stride * index);
|
|
@@ -4503,10 +4524,18 @@ var setUtf8 = ({ values, valueOffsets }, index, value) => setVariableWidthBytes(
|
|
|
4503
4524
|
var setDate = (data, index, value) => {
|
|
4504
4525
|
data.type.unit === DateUnit.DAY ? setDateDay(data, index, value) : setDateMillisecond(data, index, value);
|
|
4505
4526
|
};
|
|
4506
|
-
var setTimestampSecond = ({ values }, index, value) =>
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
var
|
|
4527
|
+
var setTimestampSecond = ({ values }, index, value) => {
|
|
4528
|
+
values[index] = BigInt(value / 1e3);
|
|
4529
|
+
};
|
|
4530
|
+
var setTimestampMillisecond = ({ values }, index, value) => {
|
|
4531
|
+
values[index] = BigInt(value);
|
|
4532
|
+
};
|
|
4533
|
+
var setTimestampMicrosecond = ({ values }, index, value) => {
|
|
4534
|
+
values[index] = BigInt(value * 1e3);
|
|
4535
|
+
};
|
|
4536
|
+
var setTimestampNanosecond = ({ values }, index, value) => {
|
|
4537
|
+
values[index] = BigInt(value * 1e6);
|
|
4538
|
+
};
|
|
4510
4539
|
var setTimestamp = (data, index, value) => {
|
|
4511
4540
|
switch (data.type.unit) {
|
|
4512
4541
|
case TimeUnit.SECOND:
|
|
@@ -4811,12 +4840,6 @@ function wrapGet(fn) {
|
|
|
4811
4840
|
return (data, _1) => data.getValid(_1) ? fn(data, _1) : null;
|
|
4812
4841
|
}
|
|
4813
4842
|
var epochDaysToMs = (data, index) => 864e5 * data[index];
|
|
4814
|
-
var epochMillisecondsLongToMs = (data, index) => 4294967296 * data[index + 1] + (data[index] >>> 0);
|
|
4815
|
-
var epochMicrosecondsLongToMs = (data, index) => 4294967296 * (data[index + 1] / 1e3) + (data[index] >>> 0) / 1e3;
|
|
4816
|
-
var epochNanosecondsLongToMs = (data, index) => 4294967296 * (data[index + 1] / 1e6) + (data[index] >>> 0) / 1e6;
|
|
4817
|
-
var epochMillisecondsToDate = (epochMs) => new Date(epochMs);
|
|
4818
|
-
var epochDaysToDate = (data, index) => epochMillisecondsToDate(epochDaysToMs(data, index));
|
|
4819
|
-
var epochMillisecondsLongToDate = (data, index) => epochMillisecondsToDate(epochMillisecondsLongToMs(data, index));
|
|
4820
4843
|
var getNull = (_data, _index) => null;
|
|
4821
4844
|
var getVariableWidthBytes = (values, valueOffsets, index) => {
|
|
4822
4845
|
if (index + 1 >= valueOffsets.length) {
|
|
@@ -4831,8 +4854,8 @@ var getBool = ({ offset, values }, index) => {
|
|
|
4831
4854
|
const byte = values[idx >> 3];
|
|
4832
4855
|
return (byte & 1 << idx % 8) !== 0;
|
|
4833
4856
|
};
|
|
4834
|
-
var getDateDay = ({ values }, index) =>
|
|
4835
|
-
var getDateMillisecond = ({ values }, index) =>
|
|
4857
|
+
var getDateDay = ({ values }, index) => epochDaysToMs(values, index);
|
|
4858
|
+
var getDateMillisecond = ({ values }, index) => bigIntToNumber(values[index]);
|
|
4836
4859
|
var getNumeric = ({ stride, values }, index) => values[stride * index];
|
|
4837
4860
|
var getFloat16 = ({ stride, values }, index) => uint16ToFloat64(values[stride * index]);
|
|
4838
4861
|
var getBigInts = ({ values }, index) => values[index];
|
|
@@ -4845,10 +4868,10 @@ var getUtf8 = ({ values, valueOffsets }, index) => {
|
|
|
4845
4868
|
var getInt = ({ values }, index) => values[index];
|
|
4846
4869
|
var getFloat = ({ type, values }, index) => type.precision !== Precision.HALF ? values[index] : uint16ToFloat64(values[index]);
|
|
4847
4870
|
var getDate = (data, index) => data.type.unit === DateUnit.DAY ? getDateDay(data, index) : getDateMillisecond(data, index);
|
|
4848
|
-
var getTimestampSecond = ({ values }, index) => 1e3 *
|
|
4849
|
-
var getTimestampMillisecond = ({ values }, index) =>
|
|
4850
|
-
var getTimestampMicrosecond = ({ values }, index) =>
|
|
4851
|
-
var getTimestampNanosecond = ({ values }, index) =>
|
|
4871
|
+
var getTimestampSecond = ({ values }, index) => 1e3 * bigIntToNumber(values[index]);
|
|
4872
|
+
var getTimestampMillisecond = ({ values }, index) => bigIntToNumber(values[index]);
|
|
4873
|
+
var getTimestampMicrosecond = ({ values }, index) => divideBigInts(values[index], BigInt(1e3));
|
|
4874
|
+
var getTimestampNanosecond = ({ values }, index) => divideBigInts(values[index], BigInt(1e6));
|
|
4852
4875
|
var getTimestamp = (data, index) => {
|
|
4853
4876
|
switch (data.type.unit) {
|
|
4854
4877
|
case TimeUnit.SECOND:
|
|
@@ -4997,12 +5020,18 @@ var instance2 = new GetVisitor();
|
|
|
4997
5020
|
// ../../node_modules/apache-arrow/row/map.mjs
|
|
4998
5021
|
var kKeys = Symbol.for("keys");
|
|
4999
5022
|
var kVals = Symbol.for("vals");
|
|
5023
|
+
var kKeysAsStrings = Symbol.for("kKeysAsStrings");
|
|
5024
|
+
var _kKeysAsStrings = Symbol.for("_kKeysAsStrings");
|
|
5000
5025
|
var MapRow = class {
|
|
5001
5026
|
constructor(slice) {
|
|
5002
5027
|
this[kKeys] = new Vector([slice.children[0]]).memoize();
|
|
5003
5028
|
this[kVals] = slice.children[1];
|
|
5004
5029
|
return new Proxy(this, new MapRowProxyHandler());
|
|
5005
5030
|
}
|
|
5031
|
+
/** @ignore */
|
|
5032
|
+
get [kKeysAsStrings]() {
|
|
5033
|
+
return this[_kKeysAsStrings] || (this[_kKeysAsStrings] = Array.from(this[kKeys].toArray(), String));
|
|
5034
|
+
}
|
|
5006
5035
|
[Symbol.iterator]() {
|
|
5007
5036
|
return new MapRowIterator(this[kKeys], this[kVals]);
|
|
5008
5037
|
}
|
|
@@ -5064,13 +5093,13 @@ var MapRowProxyHandler = class {
|
|
|
5064
5093
|
return true;
|
|
5065
5094
|
}
|
|
5066
5095
|
ownKeys(row) {
|
|
5067
|
-
return row[
|
|
5096
|
+
return row[kKeysAsStrings];
|
|
5068
5097
|
}
|
|
5069
5098
|
has(row, key) {
|
|
5070
|
-
return row[
|
|
5099
|
+
return row[kKeysAsStrings].includes(key);
|
|
5071
5100
|
}
|
|
5072
5101
|
getOwnPropertyDescriptor(row, key) {
|
|
5073
|
-
const idx = row[
|
|
5102
|
+
const idx = row[kKeysAsStrings].indexOf(key);
|
|
5074
5103
|
if (idx !== -1) {
|
|
5075
5104
|
return { writable: true, enumerable: true, configurable: true };
|
|
5076
5105
|
}
|
|
@@ -5080,7 +5109,7 @@ var MapRowProxyHandler = class {
|
|
|
5080
5109
|
if (Reflect.has(row, key)) {
|
|
5081
5110
|
return row[key];
|
|
5082
5111
|
}
|
|
5083
|
-
const idx = row[
|
|
5112
|
+
const idx = row[kKeysAsStrings].indexOf(key);
|
|
5084
5113
|
if (idx !== -1) {
|
|
5085
5114
|
const val = instance2.visit(Reflect.get(row, kVals), idx);
|
|
5086
5115
|
Reflect.set(row, key, val);
|
|
@@ -5088,7 +5117,7 @@ var MapRowProxyHandler = class {
|
|
|
5088
5117
|
}
|
|
5089
5118
|
}
|
|
5090
5119
|
set(row, key, val) {
|
|
5091
|
-
const idx = row[
|
|
5120
|
+
const idx = row[kKeysAsStrings].indexOf(key);
|
|
5092
5121
|
if (idx !== -1) {
|
|
5093
5122
|
instance.visit(Reflect.get(row, kVals), idx, val);
|
|
5094
5123
|
return Reflect.set(row, key, val);
|
|
@@ -5101,15 +5130,11 @@ var MapRowProxyHandler = class {
|
|
|
5101
5130
|
Object.defineProperties(MapRow.prototype, {
|
|
5102
5131
|
[Symbol.toStringTag]: { enumerable: false, configurable: false, value: "Row" },
|
|
5103
5132
|
[kKeys]: { writable: true, enumerable: false, configurable: false, value: null },
|
|
5104
|
-
[kVals]: { writable: true, enumerable: false, configurable: false, value: null }
|
|
5133
|
+
[kVals]: { writable: true, enumerable: false, configurable: false, value: null },
|
|
5134
|
+
[_kKeysAsStrings]: { writable: true, enumerable: false, configurable: false, value: null }
|
|
5105
5135
|
});
|
|
5106
5136
|
|
|
5107
5137
|
// ../../node_modules/apache-arrow/util/vector.mjs
|
|
5108
|
-
function clampIndex(source, index, then) {
|
|
5109
|
-
const length2 = source.length;
|
|
5110
|
-
const adjust = index > -1 ? index : length2 + index % length2;
|
|
5111
|
-
return then ? then(source, adjust) : adjust;
|
|
5112
|
-
}
|
|
5113
5138
|
var tmp;
|
|
5114
5139
|
function clampRange(source, begin, end, then) {
|
|
5115
5140
|
const { length: len = 0 } = source;
|
|
@@ -5121,6 +5146,7 @@ function clampRange(source, begin, end, then) {
|
|
|
5121
5146
|
rhs > len && (rhs = len);
|
|
5122
5147
|
return then ? then(source, lhs, rhs) : [lhs, rhs];
|
|
5123
5148
|
}
|
|
5149
|
+
var wrapIndex = (index, len) => index < 0 ? len + index : index;
|
|
5124
5150
|
var isNaNFast = (value) => value !== value;
|
|
5125
5151
|
function createElementComparator(search2) {
|
|
5126
5152
|
const typeofSearch = typeof search2;
|
|
@@ -5409,7 +5435,10 @@ var Data = class _Data {
|
|
|
5409
5435
|
let nullCount = this._nullCount;
|
|
5410
5436
|
let nullBitmap;
|
|
5411
5437
|
if (nullCount <= kUnknownNullCount && (nullBitmap = this.nullBitmap)) {
|
|
5412
|
-
this._nullCount = nullCount =
|
|
5438
|
+
this._nullCount = nullCount = nullBitmap.length === 0 ? (
|
|
5439
|
+
// no null bitmap, so all values are valid
|
|
5440
|
+
0
|
|
5441
|
+
) : this.length - popcnt_bit_range(nullBitmap, this.offset, this.offset + this.length);
|
|
5413
5442
|
}
|
|
5414
5443
|
return nullCount;
|
|
5415
5444
|
}
|
|
@@ -5471,12 +5500,14 @@ var Data = class _Data {
|
|
|
5471
5500
|
nullBitmap = new Uint8Array((offset + length2 + 63 & ~63) >> 3).fill(255);
|
|
5472
5501
|
if (this.nullCount > 0) {
|
|
5473
5502
|
nullBitmap.set(truncateBitmap(offset, length2, this.nullBitmap), 0);
|
|
5503
|
+
Object.assign(this, { nullBitmap });
|
|
5504
|
+
} else {
|
|
5505
|
+
Object.assign(this, { nullBitmap, _nullCount: 0 });
|
|
5474
5506
|
}
|
|
5475
|
-
Object.assign(this, { nullBitmap, _nullCount: -1 });
|
|
5476
5507
|
}
|
|
5477
5508
|
const byte = nullBitmap[byteOffset];
|
|
5478
5509
|
prev = (byte & mask) !== 0;
|
|
5479
|
-
|
|
5510
|
+
nullBitmap[byteOffset] = value ? byte | mask : byte & ~mask;
|
|
5480
5511
|
}
|
|
5481
5512
|
if (prev !== !!value) {
|
|
5482
5513
|
this._nullCount = this.nullCount + (value ? -1 : 1);
|
|
@@ -5917,7 +5948,9 @@ var IteratorVisitor = class extends Visitor {
|
|
|
5917
5948
|
};
|
|
5918
5949
|
function vectorIterator(vector) {
|
|
5919
5950
|
const { type } = vector;
|
|
5920
|
-
if (vector.nullCount === 0 && vector.stride === 1 &&
|
|
5951
|
+
if (vector.nullCount === 0 && vector.stride === 1 && // Don't defer to native iterator for timestamps since Numbers are expected
|
|
5952
|
+
// (DataType.isTimestamp(type)) && type.unit === TimeUnit.MILLISECOND ||
|
|
5953
|
+
(DataType.isInt(type) && type.bitWidth !== 64 || DataType.isTime(type) && type.bitWidth !== 64 || DataType.isFloat(type) && type.precision !== Precision.HALF)) {
|
|
5921
5954
|
return new ChunkedIterator(vector.data.length, (chunkIndex) => {
|
|
5922
5955
|
const data = vector.data[chunkIndex];
|
|
5923
5956
|
return data.values.subarray(0, data.length)[Symbol.iterator]();
|
|
@@ -6091,6 +6124,13 @@ var Vector = class _Vector {
|
|
|
6091
6124
|
get(index) {
|
|
6092
6125
|
return null;
|
|
6093
6126
|
}
|
|
6127
|
+
/**
|
|
6128
|
+
* Get an element value by position.
|
|
6129
|
+
* @param index The index of the element to read. A negative index will count back from the last element.
|
|
6130
|
+
*/
|
|
6131
|
+
at(index) {
|
|
6132
|
+
return this.get(wrapIndex(index, this.length));
|
|
6133
|
+
}
|
|
6094
6134
|
/**
|
|
6095
6135
|
* Set an element value by position.
|
|
6096
6136
|
* @param index The index of the element to write.
|
|
@@ -7368,8 +7408,8 @@ var AsyncByteStreamSource = class {
|
|
|
7368
7408
|
return (yield this.next(size, "peek")).value;
|
|
7369
7409
|
});
|
|
7370
7410
|
}
|
|
7371
|
-
next(
|
|
7372
|
-
return __awaiter(this,
|
|
7411
|
+
next(size_1) {
|
|
7412
|
+
return __awaiter(this, arguments, void 0, function* (size, cmd = "read") {
|
|
7373
7413
|
return yield this.source.next({ cmd, size });
|
|
7374
7414
|
});
|
|
7375
7415
|
}
|
|
@@ -8946,6 +8986,14 @@ var Table = class _Table {
|
|
|
8946
8986
|
get(index) {
|
|
8947
8987
|
return null;
|
|
8948
8988
|
}
|
|
8989
|
+
/**
|
|
8990
|
+
* Get an element value by position.
|
|
8991
|
+
* @param index The index of the element to read. A negative index will count back from the last element.
|
|
8992
|
+
*/
|
|
8993
|
+
// @ts-ignore
|
|
8994
|
+
at(index) {
|
|
8995
|
+
return this.get(wrapIndex(index, this.numRows));
|
|
8996
|
+
}
|
|
8949
8997
|
/**
|
|
8950
8998
|
* Set an element value by position.
|
|
8951
8999
|
*
|
|
@@ -9183,7 +9231,7 @@ var RecordBatch2 = class _RecordBatch {
|
|
|
9183
9231
|
return this.data.nullCount;
|
|
9184
9232
|
}
|
|
9185
9233
|
/**
|
|
9186
|
-
* Check whether an
|
|
9234
|
+
* Check whether an row is null.
|
|
9187
9235
|
* @param index The index at which to read the validity bitmap.
|
|
9188
9236
|
*/
|
|
9189
9237
|
isValid(index) {
|
|
@@ -9191,14 +9239,21 @@ var RecordBatch2 = class _RecordBatch {
|
|
|
9191
9239
|
}
|
|
9192
9240
|
/**
|
|
9193
9241
|
* Get a row by position.
|
|
9194
|
-
* @param index The index of the
|
|
9242
|
+
* @param index The index of the row to read.
|
|
9195
9243
|
*/
|
|
9196
9244
|
get(index) {
|
|
9197
9245
|
return instance2.visit(this.data, index);
|
|
9198
9246
|
}
|
|
9247
|
+
/**
|
|
9248
|
+
* Get a row value by position.
|
|
9249
|
+
* @param index The index of the row to read. A negative index will count back from the last row.
|
|
9250
|
+
*/
|
|
9251
|
+
at(index) {
|
|
9252
|
+
return this.get(wrapIndex(index, this.numRows));
|
|
9253
|
+
}
|
|
9199
9254
|
/**
|
|
9200
9255
|
* Set a row by position.
|
|
9201
|
-
* @param index The index of the
|
|
9256
|
+
* @param index The index of the row to write.
|
|
9202
9257
|
* @param value The value to set.
|
|
9203
9258
|
*/
|
|
9204
9259
|
set(index, value) {
|
|
@@ -9235,7 +9290,7 @@ var RecordBatch2 = class _RecordBatch {
|
|
|
9235
9290
|
/**
|
|
9236
9291
|
* Return a zero-copy sub-section of this RecordBatch.
|
|
9237
9292
|
* @param start The beginning of the specified portion of the RecordBatch.
|
|
9238
|
-
* @param end The end of the specified portion of the RecordBatch. This is exclusive of the
|
|
9293
|
+
* @param end The end of the specified portion of the RecordBatch. This is exclusive of the row at the index 'end'.
|
|
9239
9294
|
*/
|
|
9240
9295
|
slice(begin, end) {
|
|
9241
9296
|
const [slice] = new Vector([this.data]).slice(begin, end).data;
|
|
@@ -10323,8 +10378,8 @@ var AsyncMessageReader = class {
|
|
|
10323
10378
|
);
|
|
10324
10379
|
});
|
|
10325
10380
|
}
|
|
10326
|
-
readSchema(
|
|
10327
|
-
return __awaiter(this,
|
|
10381
|
+
readSchema() {
|
|
10382
|
+
return __awaiter(this, arguments, void 0, function* (throwIfNull = false) {
|
|
10328
10383
|
const type = MessageHeader.Schema;
|
|
10329
10384
|
const message = yield this.readMessage(type);
|
|
10330
10385
|
const schema = message === null || message === void 0 ? void 0 : message.header();
|
|
@@ -10572,8 +10627,8 @@ var AsyncRecordBatchStreamReader = class extends RecordBatchReader {
|
|
|
10572
10627
|
this._impl = _impl;
|
|
10573
10628
|
}
|
|
10574
10629
|
readAll() {
|
|
10575
|
-
var _a5, e_1, _b2, _c2;
|
|
10576
10630
|
return __awaiter(this, void 0, void 0, function* () {
|
|
10631
|
+
var _a5, e_1, _b2, _c2;
|
|
10577
10632
|
const batches = new Array();
|
|
10578
10633
|
try {
|
|
10579
10634
|
for (var _d2 = true, _e2 = __asyncValues(this), _f2; _f2 = yield _e2.next(), _a5 = _f2.done, !_a5; _d2 = true) {
|
|
@@ -10946,8 +11001,8 @@ var AsyncRecordBatchFileReaderImpl = class extends AsyncRecordBatchStreamReaderI
|
|
|
10946
11001
|
});
|
|
10947
11002
|
}
|
|
10948
11003
|
readRecordBatch(index) {
|
|
10949
|
-
var _a5;
|
|
10950
11004
|
return __awaiter(this, void 0, void 0, function* () {
|
|
11005
|
+
var _a5;
|
|
10951
11006
|
if (this.closed) {
|
|
10952
11007
|
return null;
|
|
10953
11008
|
}
|
|
@@ -10968,8 +11023,8 @@ var AsyncRecordBatchFileReaderImpl = class extends AsyncRecordBatchStreamReaderI
|
|
|
10968
11023
|
});
|
|
10969
11024
|
}
|
|
10970
11025
|
_readDictionaryBatch(index) {
|
|
10971
|
-
var _a5;
|
|
10972
11026
|
return __awaiter(this, void 0, void 0, function* () {
|
|
11027
|
+
var _a5;
|
|
10973
11028
|
const block = (_a5 = this._footer) === null || _a5 === void 0 ? void 0 : _a5.getDictionaryBatch(index);
|
|
10974
11029
|
if (block && (yield this._handle.seek(block.offset))) {
|
|
10975
11030
|
const message = yield this._reader.readMessage(MessageHeader.DictionaryBatch);
|
|
@@ -11474,9 +11529,9 @@ function writeAll(writer, input2) {
|
|
|
11474
11529
|
return writer.finish();
|
|
11475
11530
|
}
|
|
11476
11531
|
function writeAllAsync(writer, batches) {
|
|
11477
|
-
var _a5, batches_1, batches_1_1;
|
|
11478
|
-
var _b2, e_1, _c2, _d2;
|
|
11479
11532
|
return __awaiter(this, void 0, void 0, function* () {
|
|
11533
|
+
var _a5, batches_1, batches_1_1;
|
|
11534
|
+
var _b2, e_1, _c2, _d2;
|
|
11480
11535
|
try {
|
|
11481
11536
|
for (_a5 = true, batches_1 = __asyncValues(batches); batches_1_1 = yield batches_1.next(), _b2 = batches_1_1.done, !_b2; _a5 = true) {
|
|
11482
11537
|
_d2 = batches_1_1.value;
|
|
@@ -11839,6 +11894,13 @@ function socketConnector(uri = "ws://localhost:3000/") {
|
|
|
11839
11894
|
get connected() {
|
|
11840
11895
|
return connected;
|
|
11841
11896
|
},
|
|
11897
|
+
/**
|
|
11898
|
+
* Query the DuckDB server.
|
|
11899
|
+
* @param {object} query
|
|
11900
|
+
* @param {'exec' | 'arrow' | 'json'} [query.type] The query type: 'exec', 'arrow', or 'json'.
|
|
11901
|
+
* @param {string} query.sql A SQL query string.
|
|
11902
|
+
* @returns the query result
|
|
11903
|
+
*/
|
|
11842
11904
|
query(query) {
|
|
11843
11905
|
return new Promise(
|
|
11844
11906
|
(resolve, reject) => enqueue(query, resolve, reject)
|
|
@@ -11909,7 +11971,7 @@ function literalToSQL(value) {
|
|
|
11909
11971
|
case "boolean":
|
|
11910
11972
|
return value ? "TRUE" : "FALSE";
|
|
11911
11973
|
case "string":
|
|
11912
|
-
return `'${value}'`;
|
|
11974
|
+
return `'${value.replace(`'`, `''`)}'`;
|
|
11913
11975
|
case "number":
|
|
11914
11976
|
return Number.isFinite(value) ? String(value) : "NULL";
|
|
11915
11977
|
default:
|
|
@@ -11992,7 +12054,7 @@ var SQLExpression = class {
|
|
|
11992
12054
|
/**
|
|
11993
12055
|
* Annotate this expression instance with additional properties.
|
|
11994
12056
|
* @param {object[]} [props] One or more objects with properties to add.
|
|
11995
|
-
* @returns
|
|
12057
|
+
* @returns This SQL expression.
|
|
11996
12058
|
*/
|
|
11997
12059
|
annotate(...props) {
|
|
11998
12060
|
return Object.assign(this, ...props);
|
|
@@ -12260,6 +12322,9 @@ var last_value = winf("LAST_VALUE");
|
|
|
12260
12322
|
var nth_value = winf("NTH_VALUE");
|
|
12261
12323
|
|
|
12262
12324
|
// ../sql/src/aggregates.js
|
|
12325
|
+
function agg(strings, ...exprs) {
|
|
12326
|
+
return sql(strings, ...exprs).annotate({ aggregate: true });
|
|
12327
|
+
}
|
|
12263
12328
|
var AggregateFunction = class _AggregateFunction extends SQLExpression {
|
|
12264
12329
|
/**
|
|
12265
12330
|
* Create a new AggregateFunction instance.
|
|
@@ -12390,6 +12455,7 @@ var entropy = aggf("ENTROPY");
|
|
|
12390
12455
|
var varPop = aggf("VAR_POP");
|
|
12391
12456
|
var stddevPop = aggf("STDDEV_POP");
|
|
12392
12457
|
var corr = aggf("CORR");
|
|
12458
|
+
var covariance = aggf("COVAR_SAMP");
|
|
12393
12459
|
var covarPop = aggf("COVAR_POP");
|
|
12394
12460
|
var regrIntercept = aggf("REGR_INTERCEPT");
|
|
12395
12461
|
var regrSlope = aggf("REGR_SLOPE");
|
|
@@ -12532,7 +12598,8 @@ var Query = class _Query {
|
|
|
12532
12598
|
}
|
|
12533
12599
|
}
|
|
12534
12600
|
}
|
|
12535
|
-
|
|
12601
|
+
const keys = new Set(list.map((x2) => x2.as));
|
|
12602
|
+
query.select = query.select.filter((x2) => !keys.has(x2.as)).concat(list.filter((x2) => x2.expr));
|
|
12536
12603
|
return this;
|
|
12537
12604
|
}
|
|
12538
12605
|
}
|
|
@@ -13005,6 +13072,7 @@ function scaleTime() {
|
|
|
13005
13072
|
};
|
|
13006
13073
|
}
|
|
13007
13074
|
var scales = {
|
|
13075
|
+
identity: scaleLinear,
|
|
13008
13076
|
linear: scaleLinear,
|
|
13009
13077
|
log: scaleLog,
|
|
13010
13078
|
symlog: scaleSymlog,
|
|
@@ -13027,179 +13095,97 @@ function create(name, query, {
|
|
|
13027
13095
|
return "CREATE" + (replace ? " OR REPLACE " : " ") + (temp ? "TEMP " : "") + (view ? "VIEW" : "TABLE") + (replace ? " " : " IF NOT EXISTS ") + name + " AS " + query;
|
|
13028
13096
|
}
|
|
13029
13097
|
|
|
13030
|
-
// ../core/src/util/
|
|
13031
|
-
function
|
|
13032
|
-
|
|
13033
|
-
for (let i = 0, n = v.length; i < n; ++i) {
|
|
13034
|
-
const c = v.charCodeAt(i);
|
|
13035
|
-
const d = c & 65280;
|
|
13036
|
-
if (d) a = fnv_multiply(a ^ d >> 8);
|
|
13037
|
-
a = fnv_multiply(a ^ c & 255);
|
|
13038
|
-
}
|
|
13039
|
-
return fnv_mix(a);
|
|
13040
|
-
}
|
|
13041
|
-
function fnv_multiply(a) {
|
|
13042
|
-
return a + (a << 1) + (a << 4) + (a << 7) + (a << 8) + (a << 24);
|
|
13043
|
-
}
|
|
13044
|
-
function fnv_mix(a) {
|
|
13045
|
-
a += a << 13;
|
|
13046
|
-
a ^= a >>> 7;
|
|
13047
|
-
a += a << 3;
|
|
13048
|
-
a ^= a >>> 17;
|
|
13049
|
-
a += a << 5;
|
|
13050
|
-
return a & 4294967295;
|
|
13051
|
-
}
|
|
13052
|
-
|
|
13053
|
-
// ../core/src/DataCubeIndexer.js
|
|
13054
|
-
var DataCubeIndexer = class {
|
|
13055
|
-
/**
|
|
13056
|
-
*
|
|
13057
|
-
* @param {import('./Coordinator.js').Coordinator} mc a Mosaic coordinator
|
|
13058
|
-
* @param {*} options Options hash to configure the data cube indexes and pass selections to the coordinator.
|
|
13059
|
-
*/
|
|
13060
|
-
constructor(mc, { selection, temp = true }) {
|
|
13061
|
-
this.mc = mc;
|
|
13062
|
-
this.selection = selection;
|
|
13063
|
-
this.temp = temp;
|
|
13064
|
-
this.reset();
|
|
13065
|
-
}
|
|
13066
|
-
reset() {
|
|
13067
|
-
this.enabled = false;
|
|
13068
|
-
this.clients = null;
|
|
13069
|
-
this.indices = null;
|
|
13070
|
-
this.activeView = null;
|
|
13071
|
-
}
|
|
13072
|
-
clear() {
|
|
13073
|
-
if (this.indices) {
|
|
13074
|
-
this.mc.cancel(Array.from(this.indices.values(), (index) => index.result));
|
|
13075
|
-
this.indices = null;
|
|
13076
|
-
}
|
|
13077
|
-
}
|
|
13078
|
-
index(clients, active) {
|
|
13079
|
-
if (this.clients !== clients) {
|
|
13080
|
-
const cols = Array.from(clients, getIndexColumns);
|
|
13081
|
-
const from = cols[0]?.from;
|
|
13082
|
-
this.enabled = cols.every((c) => c && c.from === from);
|
|
13083
|
-
this.clients = clients;
|
|
13084
|
-
this.activeView = null;
|
|
13085
|
-
this.clear();
|
|
13086
|
-
}
|
|
13087
|
-
if (!this.enabled) return false;
|
|
13088
|
-
active = active || this.selection.active;
|
|
13089
|
-
const { source } = active;
|
|
13090
|
-
if (source && source === this.activeView?.source) return true;
|
|
13091
|
-
this.clear();
|
|
13092
|
-
if (!source) return false;
|
|
13093
|
-
const activeView = this.activeView = getActiveView(active);
|
|
13094
|
-
if (!activeView) return false;
|
|
13095
|
-
this.mc.logger().warn("DATA CUBE INDEX CONSTRUCTION");
|
|
13096
|
-
const sel = this.selection.remove(source);
|
|
13097
|
-
const indices = this.indices = /* @__PURE__ */ new Map();
|
|
13098
|
-
const { mc, temp } = this;
|
|
13099
|
-
for (const client of clients) {
|
|
13100
|
-
if (sel.skip(client, active)) continue;
|
|
13101
|
-
const index = getIndexColumns(client);
|
|
13102
|
-
const query = client.query(sel.predicate(client)).select({ ...activeView.columns, ...index.aux }).groupby(Object.keys(activeView.columns));
|
|
13103
|
-
const [subq] = query.subqueries;
|
|
13104
|
-
if (subq) {
|
|
13105
|
-
const cols = Object.values(activeView.columns).map((c) => c.columns[0]);
|
|
13106
|
-
subqueryPushdown(subq, cols);
|
|
13107
|
-
}
|
|
13108
|
-
const order = query.orderby();
|
|
13109
|
-
query.query.orderby = [];
|
|
13110
|
-
const sql2 = query.toString();
|
|
13111
|
-
const id = (fnv_hash(sql2) >>> 0).toString(16);
|
|
13112
|
-
const table2 = `cube_index_${id}`;
|
|
13113
|
-
const result = mc.exec(create(table2, sql2, { temp }));
|
|
13114
|
-
indices.set(client, { table: table2, result, order, ...index });
|
|
13115
|
-
}
|
|
13116
|
-
return true;
|
|
13117
|
-
}
|
|
13118
|
-
async update() {
|
|
13119
|
-
const { clients, selection, activeView } = this;
|
|
13120
|
-
const filter = activeView.predicate(selection.active.predicate);
|
|
13121
|
-
return Promise.all(
|
|
13122
|
-
Array.from(clients).map((client) => this.updateClient(client, filter))
|
|
13123
|
-
);
|
|
13124
|
-
}
|
|
13125
|
-
async updateClient(client, filter) {
|
|
13126
|
-
const index = this.indices.get(client);
|
|
13127
|
-
if (!index) return;
|
|
13128
|
-
if (!filter) {
|
|
13129
|
-
filter = this.activeView.predicate(this.selection.active.predicate);
|
|
13130
|
-
}
|
|
13131
|
-
const { table: table2, dims, aggr, order = [] } = index;
|
|
13132
|
-
const query = Query.select(dims, aggr).from(table2).groupby(dims).where(filter).orderby(order);
|
|
13133
|
-
return this.mc.updateClient(client, query);
|
|
13134
|
-
}
|
|
13135
|
-
};
|
|
13136
|
-
function getActiveView(clause) {
|
|
13137
|
-
const { source, schema } = clause;
|
|
13138
|
-
let columns = clause.predicate?.columns;
|
|
13139
|
-
if (!schema || !columns) return null;
|
|
13140
|
-
const { type, scales: scales2, pixelSize = 1 } = schema;
|
|
13141
|
-
let predicate;
|
|
13142
|
-
if (type === "interval" && scales2) {
|
|
13143
|
-
const bins = scales2.map((s) => binInterval(s, pixelSize));
|
|
13144
|
-
if (bins.some((b) => b == null)) return null;
|
|
13145
|
-
if (bins.length === 1) {
|
|
13146
|
-
predicate = (p) => p ? isBetween("active0", p.range.map(bins[0])) : [];
|
|
13147
|
-
columns = { active0: bins[0](clause.predicate.field) };
|
|
13148
|
-
} else {
|
|
13149
|
-
predicate = (p) => p ? and(p.children.map(({ range }, i) => isBetween(`active${i}`, range.map(bins[i])))) : [];
|
|
13150
|
-
columns = Object.fromEntries(
|
|
13151
|
-
clause.predicate.children.map((p, i) => [`active${i}`, bins[i](p.field)])
|
|
13152
|
-
);
|
|
13153
|
-
}
|
|
13154
|
-
} else if (type === "point") {
|
|
13155
|
-
predicate = (x2) => x2;
|
|
13156
|
-
columns = Object.fromEntries(columns.map((col) => [col.toString(), col]));
|
|
13157
|
-
} else {
|
|
13158
|
-
return null;
|
|
13159
|
-
}
|
|
13160
|
-
return { source, columns, predicate };
|
|
13161
|
-
}
|
|
13162
|
-
function binInterval(scale, pixelSize) {
|
|
13163
|
-
const { apply, sqlApply } = scaleTransform(scale);
|
|
13164
|
-
if (apply) {
|
|
13165
|
-
const { domain, range } = scale;
|
|
13166
|
-
const lo = apply(Math.min(...domain));
|
|
13167
|
-
const hi = apply(Math.max(...domain));
|
|
13168
|
-
const a = Math.abs(range[1] - range[0]) / (hi - lo) / pixelSize;
|
|
13169
|
-
const s = pixelSize === 1 ? "" : `${pixelSize}::INTEGER * `;
|
|
13170
|
-
return (value) => sql`${s}FLOOR(${a}::DOUBLE * (${sqlApply(value)} - ${lo}::DOUBLE))::INTEGER`;
|
|
13171
|
-
}
|
|
13172
|
-
}
|
|
13173
|
-
var NO_INDEX = { from: NaN };
|
|
13174
|
-
function getIndexColumns(client) {
|
|
13175
|
-
if (!client.filterIndexable) return NO_INDEX;
|
|
13098
|
+
// ../core/src/util/index-columns.js
|
|
13099
|
+
function indexColumns(client) {
|
|
13100
|
+
if (!client.filterIndexable) return null;
|
|
13176
13101
|
const q = client.query();
|
|
13177
13102
|
const from = getBaseTable(q);
|
|
13178
|
-
if (
|
|
13179
|
-
const g = new Set(q.groupby().map((c) => c.column));
|
|
13103
|
+
if (typeof from !== "string" || !q.select) return null;
|
|
13180
13104
|
const aggr = [];
|
|
13181
13105
|
const dims = [];
|
|
13182
13106
|
const aux = {};
|
|
13183
|
-
let auxAs;
|
|
13184
13107
|
for (const entry of q.select()) {
|
|
13185
13108
|
const { as, expr: { aggregate, args } } = entry;
|
|
13186
13109
|
const op = aggregate?.toUpperCase?.();
|
|
13187
13110
|
switch (op) {
|
|
13188
13111
|
case "COUNT":
|
|
13189
13112
|
case "SUM":
|
|
13190
|
-
aggr.push({ [as]:
|
|
13113
|
+
aggr.push({ [as]: agg`SUM("${as}")::DOUBLE` });
|
|
13191
13114
|
break;
|
|
13192
13115
|
case "AVG":
|
|
13193
|
-
|
|
13194
|
-
aggr.push({ [as]: sql`(SUM("${as}" * ${auxAs}) / SUM(${auxAs}))::DOUBLE` });
|
|
13116
|
+
aggr.push({ [as]: avgExpr(aux, as, args[0]) });
|
|
13195
13117
|
break;
|
|
13196
13118
|
case "ARG_MAX":
|
|
13197
|
-
|
|
13198
|
-
aggr.push({ [as]: sql`ARG_MAX("${as}", ${auxAs})` });
|
|
13119
|
+
aggr.push({ [as]: argmaxExpr(aux, as, args) });
|
|
13199
13120
|
break;
|
|
13200
13121
|
case "ARG_MIN":
|
|
13201
|
-
|
|
13202
|
-
|
|
13122
|
+
aggr.push({ [as]: argminExpr(aux, as, args) });
|
|
13123
|
+
break;
|
|
13124
|
+
case "VARIANCE":
|
|
13125
|
+
case "VAR_SAMP":
|
|
13126
|
+
aux[as] = null;
|
|
13127
|
+
aggr.push({ [as]: varianceExpr(aux, args[0], from) });
|
|
13128
|
+
break;
|
|
13129
|
+
case "VAR_POP":
|
|
13130
|
+
aux[as] = null;
|
|
13131
|
+
aggr.push({ [as]: varianceExpr(aux, args[0], from, false) });
|
|
13132
|
+
break;
|
|
13133
|
+
case "STDDEV":
|
|
13134
|
+
case "STDDEV_SAMP":
|
|
13135
|
+
aux[as] = null;
|
|
13136
|
+
aggr.push({ [as]: agg`SQRT(${varianceExpr(aux, args[0], from)})` });
|
|
13137
|
+
break;
|
|
13138
|
+
case "STDDEV_POP":
|
|
13139
|
+
aux[as] = null;
|
|
13140
|
+
aggr.push({ [as]: agg`SQRT(${varianceExpr(aux, args[0], from, false)})` });
|
|
13141
|
+
break;
|
|
13142
|
+
case "COVAR_SAMP":
|
|
13143
|
+
aux[as] = null;
|
|
13144
|
+
aggr.push({ [as]: covarianceExpr(aux, args, from) });
|
|
13145
|
+
break;
|
|
13146
|
+
case "COVAR_POP":
|
|
13147
|
+
aux[as] = null;
|
|
13148
|
+
aggr.push({ [as]: covarianceExpr(aux, args, from, false) });
|
|
13149
|
+
break;
|
|
13150
|
+
case "CORR":
|
|
13151
|
+
aux[as] = null;
|
|
13152
|
+
aggr.push({ [as]: corrExpr(aux, args, from) });
|
|
13153
|
+
break;
|
|
13154
|
+
case "REGR_COUNT":
|
|
13155
|
+
aux[as] = null;
|
|
13156
|
+
aggr.push({ [as]: agg`${regrCountExpr(aux, args)}::DOUBLE` });
|
|
13157
|
+
break;
|
|
13158
|
+
case "REGR_AVGX":
|
|
13159
|
+
aux[as] = null;
|
|
13160
|
+
aggr.push({ [as]: regrAvgXExpr(aux, args) });
|
|
13161
|
+
break;
|
|
13162
|
+
case "REGR_AVGY":
|
|
13163
|
+
aux[as] = null;
|
|
13164
|
+
aggr.push({ [as]: regrAvgYExpr(aux, args) });
|
|
13165
|
+
break;
|
|
13166
|
+
case "REGR_SYY":
|
|
13167
|
+
aux[as] = null;
|
|
13168
|
+
aggr.push({ [as]: regrVarExpr(aux, 0, args, from) });
|
|
13169
|
+
break;
|
|
13170
|
+
case "REGR_SXX":
|
|
13171
|
+
aux[as] = null;
|
|
13172
|
+
aggr.push({ [as]: regrVarExpr(aux, 1, args, from) });
|
|
13173
|
+
break;
|
|
13174
|
+
case "REGR_SXY":
|
|
13175
|
+
aux[as] = null;
|
|
13176
|
+
aggr.push({ [as]: covarianceExpr(aux, args, from, null) });
|
|
13177
|
+
break;
|
|
13178
|
+
case "REGR_SLOPE":
|
|
13179
|
+
aux[as] = null;
|
|
13180
|
+
aggr.push({ [as]: regrSlopeExpr(aux, args, from) });
|
|
13181
|
+
break;
|
|
13182
|
+
case "REGR_INTERCEPT":
|
|
13183
|
+
aux[as] = null;
|
|
13184
|
+
aggr.push({ [as]: regrInterceptExpr(aux, args, from) });
|
|
13185
|
+
break;
|
|
13186
|
+
case "REGR_R2":
|
|
13187
|
+
aux[as] = null;
|
|
13188
|
+
aggr.push({ [as]: agg`(${corrExpr(aux, args, from)}) ** 2` });
|
|
13203
13189
|
break;
|
|
13204
13190
|
case "MAX":
|
|
13205
13191
|
case "MIN":
|
|
@@ -13209,14 +13195,22 @@ function getIndexColumns(client) {
|
|
|
13209
13195
|
case "BOOL_AND":
|
|
13210
13196
|
case "BOOL_OR":
|
|
13211
13197
|
case "PRODUCT":
|
|
13212
|
-
aggr.push({ [as]:
|
|
13198
|
+
aggr.push({ [as]: agg`${op}("${as}")` });
|
|
13213
13199
|
break;
|
|
13214
13200
|
default:
|
|
13215
|
-
if (
|
|
13201
|
+
if (!aggregate) dims.push(as);
|
|
13216
13202
|
else return null;
|
|
13217
13203
|
}
|
|
13218
13204
|
}
|
|
13219
|
-
|
|
13205
|
+
if (!aggr.length) return null;
|
|
13206
|
+
return { from, dims, aggr, aux };
|
|
13207
|
+
}
|
|
13208
|
+
function auxName(type, ...args) {
|
|
13209
|
+
const cols = args.length ? "_" + args.map(sanitize).join("_") : "";
|
|
13210
|
+
return `__${type}${cols}__`;
|
|
13211
|
+
}
|
|
13212
|
+
function sanitize(col) {
|
|
13213
|
+
return `${col}`.replaceAll('"', "").replaceAll(" ", "_");
|
|
13220
13214
|
}
|
|
13221
13215
|
function getBaseTable(query) {
|
|
13222
13216
|
const subq = query.subqueries;
|
|
@@ -13233,6 +13227,291 @@ function getBaseTable(query) {
|
|
|
13233
13227
|
}
|
|
13234
13228
|
return base;
|
|
13235
13229
|
}
|
|
13230
|
+
function countExpr(aux, arg) {
|
|
13231
|
+
const n = auxName("count", arg);
|
|
13232
|
+
aux[n] = agg`COUNT(${arg})`;
|
|
13233
|
+
return agg`SUM(${n})`.annotate({ name: n });
|
|
13234
|
+
}
|
|
13235
|
+
function avgExpr(aux, as, arg) {
|
|
13236
|
+
const n = countExpr(aux, arg);
|
|
13237
|
+
return agg`(SUM("${as}" * ${n.name}) / ${n})`;
|
|
13238
|
+
}
|
|
13239
|
+
function avg2(x2, from) {
|
|
13240
|
+
return sql`(SELECT AVG(${x2}) FROM "${from}")`;
|
|
13241
|
+
}
|
|
13242
|
+
function argmaxExpr(aux, as, [, y2]) {
|
|
13243
|
+
const max2 = auxName("max", y2);
|
|
13244
|
+
aux[max2] = agg`MAX(${y2})`;
|
|
13245
|
+
return agg`ARG_MAX("${as}", ${max2})`;
|
|
13246
|
+
}
|
|
13247
|
+
function argminExpr(aux, as, [, y2]) {
|
|
13248
|
+
const min2 = auxName("min", y2);
|
|
13249
|
+
aux[min2] = agg`MIN(${y2})`;
|
|
13250
|
+
return agg`ARG_MIN("${as}", ${min2})`;
|
|
13251
|
+
}
|
|
13252
|
+
function varianceExpr(aux, x2, from, correction = true) {
|
|
13253
|
+
const n = countExpr(aux, x2);
|
|
13254
|
+
const ssq = auxName("rssq", x2);
|
|
13255
|
+
const sum2 = auxName("rsum", x2);
|
|
13256
|
+
const delta = sql`${x2} - ${avg2(x2, from)}`;
|
|
13257
|
+
aux[ssq] = agg`SUM((${delta}) ** 2)`;
|
|
13258
|
+
aux[sum2] = agg`SUM(${delta})`;
|
|
13259
|
+
const adj = correction ? ` - 1` : "";
|
|
13260
|
+
return agg`(SUM(${ssq}) - (SUM(${sum2}) ** 2 / ${n})) / (${n}${adj})`;
|
|
13261
|
+
}
|
|
13262
|
+
function covarianceExpr(aux, args, from, correction = true) {
|
|
13263
|
+
const n = regrCountExpr(aux, args);
|
|
13264
|
+
const sxy = regrSumXYExpr(aux, args, from);
|
|
13265
|
+
const sx = regrSumExpr(aux, 1, args, from);
|
|
13266
|
+
const sy = regrSumExpr(aux, 0, args, from);
|
|
13267
|
+
const adj = correction === null ? "" : correction ? ` / (${n} - 1)` : ` / ${n}`;
|
|
13268
|
+
return agg`(${sxy} - ${sx} * ${sy} / ${n})${adj}`;
|
|
13269
|
+
}
|
|
13270
|
+
function corrExpr(aux, args, from) {
|
|
13271
|
+
const n = regrCountExpr(aux, args);
|
|
13272
|
+
const sxy = regrSumXYExpr(aux, args, from);
|
|
13273
|
+
const sxx = regrSumSqExpr(aux, 1, args, from);
|
|
13274
|
+
const syy = regrSumSqExpr(aux, 0, args, from);
|
|
13275
|
+
const sx = regrSumExpr(aux, 1, args, from);
|
|
13276
|
+
const sy = regrSumExpr(aux, 0, args, from);
|
|
13277
|
+
const vx = agg`(${sxx} - (${sx} ** 2) / ${n})`;
|
|
13278
|
+
const vy = agg`(${syy} - (${sy} ** 2) / ${n})`;
|
|
13279
|
+
return agg`(${sxy} - ${sx} * ${sy} / ${n}) / SQRT(${vx} * ${vy})`;
|
|
13280
|
+
}
|
|
13281
|
+
function regrCountExpr(aux, [y2, x2]) {
|
|
13282
|
+
const n = auxName("count", y2, x2);
|
|
13283
|
+
aux[n] = agg`REGR_COUNT(${y2}, ${x2})`;
|
|
13284
|
+
return agg`SUM(${n})`.annotate({ name: n });
|
|
13285
|
+
}
|
|
13286
|
+
function regrSumExpr(aux, i, args, from) {
|
|
13287
|
+
const v = args[i];
|
|
13288
|
+
const o = args[1 - i];
|
|
13289
|
+
const sum2 = auxName("rs", v);
|
|
13290
|
+
aux[sum2] = agg`SUM(${v} - ${avg2(v, from)}) FILTER (${o} IS NOT NULL)`;
|
|
13291
|
+
return agg`SUM(${sum2})`;
|
|
13292
|
+
}
|
|
13293
|
+
function regrSumSqExpr(aux, i, args, from) {
|
|
13294
|
+
const v = args[i];
|
|
13295
|
+
const u = args[1 - i];
|
|
13296
|
+
const ssq = auxName("rss", v);
|
|
13297
|
+
aux[ssq] = agg`SUM((${v} - ${avg2(v, from)}) ** 2) FILTER (${u} IS NOT NULL)`;
|
|
13298
|
+
return agg`SUM(${ssq})`;
|
|
13299
|
+
}
|
|
13300
|
+
function regrSumXYExpr(aux, args, from) {
|
|
13301
|
+
const [y2, x2] = args;
|
|
13302
|
+
const sxy = auxName("sxy", y2, x2);
|
|
13303
|
+
aux[sxy] = agg`SUM((${x2} - ${avg2(x2, from)}) * (${y2} - ${avg2(y2, from)}))`;
|
|
13304
|
+
return agg`SUM(${sxy})`;
|
|
13305
|
+
}
|
|
13306
|
+
function regrAvgXExpr(aux, args) {
|
|
13307
|
+
const [y2, x2] = args;
|
|
13308
|
+
const n = regrCountExpr(aux, args);
|
|
13309
|
+
const a = auxName("avg", x2, y2);
|
|
13310
|
+
aux[a] = agg`REGR_AVGX(${y2}, ${x2})`;
|
|
13311
|
+
return agg`(SUM(${a} * ${n.name}) / ${n})`;
|
|
13312
|
+
}
|
|
13313
|
+
function regrAvgYExpr(aux, args) {
|
|
13314
|
+
const [y2, x2] = args;
|
|
13315
|
+
const n = regrCountExpr(aux, args);
|
|
13316
|
+
const a = auxName("avg", y2, x2);
|
|
13317
|
+
aux[a] = agg`REGR_AVGY(${y2}, ${x2})`;
|
|
13318
|
+
return agg`(SUM(${a} * ${n.name}) / ${n})`;
|
|
13319
|
+
}
|
|
13320
|
+
function regrVarExpr(aux, i, args, from) {
|
|
13321
|
+
const n = regrCountExpr(aux, args);
|
|
13322
|
+
const sum2 = regrSumExpr(aux, i, args, from);
|
|
13323
|
+
const ssq = regrSumSqExpr(aux, i, args, from);
|
|
13324
|
+
return agg`(${ssq} - (${sum2} ** 2 / ${n}))`;
|
|
13325
|
+
}
|
|
13326
|
+
function regrSlopeExpr(aux, args, from) {
|
|
13327
|
+
const cov = covarianceExpr(aux, args, from, null);
|
|
13328
|
+
const varx = regrVarExpr(aux, 1, args, from);
|
|
13329
|
+
return agg`(${cov}) / ${varx}`;
|
|
13330
|
+
}
|
|
13331
|
+
function regrInterceptExpr(aux, args, from) {
|
|
13332
|
+
const ax = regrAvgXExpr(aux, args);
|
|
13333
|
+
const ay = regrAvgYExpr(aux, args);
|
|
13334
|
+
const m = regrSlopeExpr(aux, args, from);
|
|
13335
|
+
return agg`${ay} - (${m}) * ${ax}`;
|
|
13336
|
+
}
|
|
13337
|
+
|
|
13338
|
+
// ../core/src/util/hash.js
|
|
13339
|
+
function fnv_hash(v) {
|
|
13340
|
+
let a = 2166136261;
|
|
13341
|
+
for (let i = 0, n = v.length; i < n; ++i) {
|
|
13342
|
+
const c = v.charCodeAt(i);
|
|
13343
|
+
const d = c & 65280;
|
|
13344
|
+
if (d) a = fnv_multiply(a ^ d >> 8);
|
|
13345
|
+
a = fnv_multiply(a ^ c & 255);
|
|
13346
|
+
}
|
|
13347
|
+
return fnv_mix(a);
|
|
13348
|
+
}
|
|
13349
|
+
function fnv_multiply(a) {
|
|
13350
|
+
return a + (a << 1) + (a << 4) + (a << 7) + (a << 8) + (a << 24);
|
|
13351
|
+
}
|
|
13352
|
+
function fnv_mix(a) {
|
|
13353
|
+
a += a << 13;
|
|
13354
|
+
a ^= a >>> 7;
|
|
13355
|
+
a += a << 3;
|
|
13356
|
+
a ^= a >>> 17;
|
|
13357
|
+
a += a << 5;
|
|
13358
|
+
return a & 4294967295;
|
|
13359
|
+
}
|
|
13360
|
+
|
|
13361
|
+
// ../core/src/DataCubeIndexer.js
|
|
13362
|
+
var Skip = { skip: true, result: null };
|
|
13363
|
+
var DataCubeIndexer = class {
|
|
13364
|
+
/**
|
|
13365
|
+
* Create a new data cube index table manager.
|
|
13366
|
+
* @param {import('./Coordinator.js').Coordinator} coordinator A Mosaic coordinator.
|
|
13367
|
+
* @param {object} [options] Indexer options.
|
|
13368
|
+
* @param {boolean} [options.enabled=true] Flag to enable/disable indexer.
|
|
13369
|
+
* @param {boolean} [options.temp=true] Flag to indicate if generated data
|
|
13370
|
+
* cube index tables should be temporary tables.
|
|
13371
|
+
*/
|
|
13372
|
+
constructor(coordinator2, {
|
|
13373
|
+
enabled = true,
|
|
13374
|
+
temp = true
|
|
13375
|
+
} = {}) {
|
|
13376
|
+
this.indexes = /* @__PURE__ */ new Map();
|
|
13377
|
+
this.active = null;
|
|
13378
|
+
this.temp = temp;
|
|
13379
|
+
this.mc = coordinator2;
|
|
13380
|
+
this._enabled = enabled;
|
|
13381
|
+
}
|
|
13382
|
+
/**
|
|
13383
|
+
* Set the enabled state of this indexer. If false, any cached state is
|
|
13384
|
+
* cleared and subsequent index calls will return null until re-enabled.
|
|
13385
|
+
* @param {boolean} state The enabled state.
|
|
13386
|
+
*/
|
|
13387
|
+
enabled(state) {
|
|
13388
|
+
if (state === void 0) {
|
|
13389
|
+
return this._enabled;
|
|
13390
|
+
} else if (this._enabled !== state) {
|
|
13391
|
+
if (!state) this.clear();
|
|
13392
|
+
this._enabled = state;
|
|
13393
|
+
}
|
|
13394
|
+
}
|
|
13395
|
+
/**
|
|
13396
|
+
* Clear the cache of data cube index table entries for the current active
|
|
13397
|
+
* selection clause. This method will also cancel any queued data cube table
|
|
13398
|
+
* creation queries that have not yet been submitted to the database. This
|
|
13399
|
+
* method does _not_ drop any existing data cube tables.
|
|
13400
|
+
*/
|
|
13401
|
+
clear() {
|
|
13402
|
+
this.mc.cancel(Array.from(this.indexes.values(), (info) => info?.result));
|
|
13403
|
+
this.indexes.clear();
|
|
13404
|
+
this.active = null;
|
|
13405
|
+
}
|
|
13406
|
+
/**
|
|
13407
|
+
* Return data cube index table information for the active state of a
|
|
13408
|
+
* client-selection pair, or null if the client is not indexable. This
|
|
13409
|
+
* method has multiple possible side effects, including data cube table
|
|
13410
|
+
* generation and updating internal caches.
|
|
13411
|
+
* @param {import('./MosaicClient.js').MosaicClient} client A Mosaic client.
|
|
13412
|
+
* @param {import('./Selection.js').Selection} selection A Mosaic selection
|
|
13413
|
+
* to filter the client by.
|
|
13414
|
+
* @param {import('./util/selection-types.js').SelectionClause} activeClause
|
|
13415
|
+
* A representative active selection clause for which to (possibly) generate
|
|
13416
|
+
* data cube index tables.
|
|
13417
|
+
* @returns {DataCubeInfo | Skip | null} Data cube index table
|
|
13418
|
+
* information and query generator, or null if the client is not indexable.
|
|
13419
|
+
*/
|
|
13420
|
+
index(client, selection, activeClause) {
|
|
13421
|
+
if (!this._enabled) return null;
|
|
13422
|
+
const { indexes, mc, temp } = this;
|
|
13423
|
+
const { source } = activeClause;
|
|
13424
|
+
if (!source) return null;
|
|
13425
|
+
if (this.active) {
|
|
13426
|
+
if (this.active.source !== source) this.clear();
|
|
13427
|
+
if (this.active?.source === null) return null;
|
|
13428
|
+
}
|
|
13429
|
+
let { active } = this;
|
|
13430
|
+
if (!active) {
|
|
13431
|
+
this.active = active = activeColumns(activeClause);
|
|
13432
|
+
if (active.source === null) return null;
|
|
13433
|
+
}
|
|
13434
|
+
if (indexes.has(client)) {
|
|
13435
|
+
return indexes.get(client);
|
|
13436
|
+
}
|
|
13437
|
+
const indexCols = indexColumns(client);
|
|
13438
|
+
let info;
|
|
13439
|
+
if (!indexCols) {
|
|
13440
|
+
info = null;
|
|
13441
|
+
} else if (selection.skip(client, activeClause)) {
|
|
13442
|
+
info = Skip;
|
|
13443
|
+
} else {
|
|
13444
|
+
const filter = selection.remove(source).predicate(client);
|
|
13445
|
+
info = dataCubeInfo(client.query(filter), active, indexCols);
|
|
13446
|
+
info.result = mc.exec(create(info.table, info.create, { temp }));
|
|
13447
|
+
info.result.catch((e) => mc.logger().error(e));
|
|
13448
|
+
}
|
|
13449
|
+
indexes.set(client, info);
|
|
13450
|
+
return info;
|
|
13451
|
+
}
|
|
13452
|
+
};
|
|
13453
|
+
function activeColumns(clause) {
|
|
13454
|
+
const { source, meta } = clause;
|
|
13455
|
+
const clausePred = clause.predicate;
|
|
13456
|
+
const clauseCols = clausePred?.columns;
|
|
13457
|
+
let predicate;
|
|
13458
|
+
let columns;
|
|
13459
|
+
if (!meta || !clauseCols) {
|
|
13460
|
+
return { source: null, columns, predicate };
|
|
13461
|
+
}
|
|
13462
|
+
const { type, scales: scales2, bin, pixelSize = 1 } = meta;
|
|
13463
|
+
if (type === "point") {
|
|
13464
|
+
predicate = (x2) => x2;
|
|
13465
|
+
columns = Object.fromEntries(
|
|
13466
|
+
clauseCols.map((col) => [`${col}`, asColumn(col)])
|
|
13467
|
+
);
|
|
13468
|
+
} else if (type === "interval" && scales2) {
|
|
13469
|
+
const bins = scales2.map((s) => binInterval(s, pixelSize, bin));
|
|
13470
|
+
if (bins.some((b) => !b)) {
|
|
13471
|
+
} else if (bins.length === 1) {
|
|
13472
|
+
predicate = (p) => p ? isBetween("active0", p.range.map(bins[0])) : [];
|
|
13473
|
+
columns = { active0: bins[0](clausePred.field) };
|
|
13474
|
+
} else {
|
|
13475
|
+
predicate = (p) => p ? and(p.children.map(
|
|
13476
|
+
({ range }, i) => isBetween(`active${i}`, range.map(bins[i]))
|
|
13477
|
+
)) : [];
|
|
13478
|
+
columns = Object.fromEntries(
|
|
13479
|
+
// @ts-ignore
|
|
13480
|
+
clausePred.children.map((p, i) => [`active${i}`, bins[i](p.field)])
|
|
13481
|
+
);
|
|
13482
|
+
}
|
|
13483
|
+
}
|
|
13484
|
+
return { source: columns ? source : null, columns, predicate };
|
|
13485
|
+
}
|
|
13486
|
+
var BIN = { ceil: "CEIL", round: "ROUND" };
|
|
13487
|
+
function binInterval(scale, pixelSize, bin) {
|
|
13488
|
+
const { type, domain, range, apply, sqlApply } = scaleTransform(scale);
|
|
13489
|
+
if (!apply) return;
|
|
13490
|
+
const fn = BIN[`${bin}`.toLowerCase()] || "FLOOR";
|
|
13491
|
+
const lo = apply(Math.min(...domain));
|
|
13492
|
+
const hi = apply(Math.max(...domain));
|
|
13493
|
+
const a = type === "identity" ? 1 : Math.abs(range[1] - range[0]) / (hi - lo);
|
|
13494
|
+
const s = a / pixelSize === 1 ? "" : `${a / pixelSize}::DOUBLE * `;
|
|
13495
|
+
const d = lo === 0 ? "" : ` - ${lo}::DOUBLE`;
|
|
13496
|
+
return (value) => sql`${fn}(${s}(${sqlApply(value)}${d}))::INTEGER`;
|
|
13497
|
+
}
|
|
13498
|
+
function dataCubeInfo(clientQuery, active, indexCols) {
|
|
13499
|
+
const { dims, aggr, aux } = indexCols;
|
|
13500
|
+
const { columns } = active;
|
|
13501
|
+
const query = clientQuery.select({ ...columns, ...aux }).groupby(Object.keys(columns));
|
|
13502
|
+
const [subq] = query.subqueries;
|
|
13503
|
+
if (subq) {
|
|
13504
|
+
const cols = Object.values(columns).flatMap((c) => c.columns);
|
|
13505
|
+
subqueryPushdown(subq, cols);
|
|
13506
|
+
}
|
|
13507
|
+
const order = query.orderby();
|
|
13508
|
+
query.query.orderby = [];
|
|
13509
|
+
const create2 = query.toString();
|
|
13510
|
+
const id = (fnv_hash(create2) >>> 0).toString(16);
|
|
13511
|
+
const table2 = `cube_index_${id}`;
|
|
13512
|
+
const select = Query.select(dims, aggr).from(table2).groupby(dims).orderby(order);
|
|
13513
|
+
return new DataCubeInfo({ table: table2, create: create2, active, select });
|
|
13514
|
+
}
|
|
13236
13515
|
function subqueryPushdown(query, cols) {
|
|
13237
13516
|
const memo = /* @__PURE__ */ new Set();
|
|
13238
13517
|
const pushdown = (q) => {
|
|
@@ -13245,78 +13524,65 @@ function subqueryPushdown(query, cols) {
|
|
|
13245
13524
|
};
|
|
13246
13525
|
pushdown(query);
|
|
13247
13526
|
}
|
|
13248
|
-
|
|
13249
|
-
// ../core/src/FilterGroup.js
|
|
13250
|
-
var FilterGroup = class {
|
|
13527
|
+
var DataCubeInfo = class {
|
|
13251
13528
|
/**
|
|
13252
|
-
*
|
|
13253
|
-
* @param {
|
|
13254
|
-
* @param {*} index Boolean flag or options hash for data cube indexer.
|
|
13255
|
-
* Falsy values disable indexing.
|
|
13529
|
+
* Create a new DataCubeInfo instance.
|
|
13530
|
+
* @param {object} options
|
|
13256
13531
|
*/
|
|
13257
|
-
constructor(
|
|
13258
|
-
this.
|
|
13259
|
-
this.
|
|
13260
|
-
this.
|
|
13261
|
-
this.
|
|
13262
|
-
|
|
13263
|
-
|
|
13264
|
-
activate: (clause) => this.indexer?.index(this.clients, clause)
|
|
13265
|
-
};
|
|
13266
|
-
selection.addEventListener("value", value);
|
|
13267
|
-
selection.addEventListener("activate", activate);
|
|
13532
|
+
constructor({ table: table2, create: create2, active, select } = {}) {
|
|
13533
|
+
this.table = table2;
|
|
13534
|
+
this.create = create2;
|
|
13535
|
+
this.result = null;
|
|
13536
|
+
this.active = active;
|
|
13537
|
+
this.select = select;
|
|
13538
|
+
this.skip = false;
|
|
13268
13539
|
}
|
|
13269
|
-
|
|
13270
|
-
|
|
13271
|
-
|
|
13272
|
-
|
|
13273
|
-
|
|
13274
|
-
|
|
13275
|
-
|
|
13540
|
+
/**
|
|
13541
|
+
* Generate a data cube index table query for the given predicate.
|
|
13542
|
+
* @param {import('@uwdata/mosaic-sql').SQLExpression} predicate The current
|
|
13543
|
+
* active clause predicate.
|
|
13544
|
+
* @returns {Query} A data cube index table query.
|
|
13545
|
+
*/
|
|
13546
|
+
query(predicate) {
|
|
13547
|
+
return this.select.clone().where(this.active.predicate(predicate));
|
|
13276
13548
|
}
|
|
13277
|
-
|
|
13278
|
-
|
|
13279
|
-
|
|
13549
|
+
};
|
|
13550
|
+
|
|
13551
|
+
// ../core/src/util/query-result.js
|
|
13552
|
+
var QueryResult = class extends Promise {
|
|
13553
|
+
/**
|
|
13554
|
+
* Create a new query result Promise.
|
|
13555
|
+
*/
|
|
13556
|
+
constructor() {
|
|
13557
|
+
let resolve;
|
|
13558
|
+
let reject;
|
|
13559
|
+
super((r, e) => {
|
|
13560
|
+
resolve = r;
|
|
13561
|
+
reject = e;
|
|
13562
|
+
});
|
|
13563
|
+
this._resolve = resolve;
|
|
13564
|
+
this._reject = reject;
|
|
13280
13565
|
}
|
|
13281
|
-
|
|
13282
|
-
|
|
13283
|
-
|
|
13284
|
-
|
|
13566
|
+
/**
|
|
13567
|
+
* Resolve the result Promise with the provided value.
|
|
13568
|
+
* @param {*} value The result value.
|
|
13569
|
+
* @returns {this}
|
|
13570
|
+
*/
|
|
13571
|
+
fulfill(value) {
|
|
13572
|
+
this._resolve(value);
|
|
13285
13573
|
return this;
|
|
13286
13574
|
}
|
|
13287
13575
|
/**
|
|
13288
|
-
*
|
|
13289
|
-
*
|
|
13290
|
-
* @returns {
|
|
13576
|
+
* Rejects the result Promise with the provided error.
|
|
13577
|
+
* @param {*} error The error value.
|
|
13578
|
+
* @returns {this}
|
|
13291
13579
|
*/
|
|
13292
|
-
|
|
13293
|
-
|
|
13294
|
-
|
|
13295
|
-
return hasIndex ? indexer.update() : defaultUpdate(mc, clients, selection);
|
|
13580
|
+
reject(error) {
|
|
13581
|
+
this._reject(error);
|
|
13582
|
+
return this;
|
|
13296
13583
|
}
|
|
13297
13584
|
};
|
|
13298
|
-
|
|
13299
|
-
return Promise.all(Array.from(clients).map((client) => {
|
|
13300
|
-
const filter = selection.predicate(client);
|
|
13301
|
-
if (filter != null) {
|
|
13302
|
-
return mc.updateClient(client, client.query(filter));
|
|
13303
|
-
}
|
|
13304
|
-
}));
|
|
13305
|
-
}
|
|
13306
|
-
|
|
13307
|
-
// ../core/src/util/query-result.js
|
|
13308
|
-
function queryResult() {
|
|
13309
|
-
let resolve;
|
|
13310
|
-
let reject;
|
|
13311
|
-
const p = new Promise((r, e) => {
|
|
13312
|
-
resolve = r;
|
|
13313
|
-
reject = e;
|
|
13314
|
-
});
|
|
13315
|
-
return Object.assign(p, {
|
|
13316
|
-
fulfill: (value) => (resolve(value), p),
|
|
13317
|
-
reject: (err) => (reject(err), p)
|
|
13318
|
-
});
|
|
13319
|
-
}
|
|
13585
|
+
QueryResult.prototype.constructor = Promise;
|
|
13320
13586
|
|
|
13321
13587
|
// ../core/src/QueryConsolidator.js
|
|
13322
13588
|
function wait(callback) {
|
|
@@ -13392,7 +13658,7 @@ function consolidate(group, enqueue, record) {
|
|
|
13392
13658
|
record: false,
|
|
13393
13659
|
query: group.query = consolidatedQuery(group, record)
|
|
13394
13660
|
},
|
|
13395
|
-
result: group.result =
|
|
13661
|
+
result: group.result = new QueryResult()
|
|
13396
13662
|
});
|
|
13397
13663
|
} else {
|
|
13398
13664
|
for (const { entry, priority } of group) {
|
|
@@ -13608,115 +13874,124 @@ function priorityQueue(ranks) {
|
|
|
13608
13874
|
|
|
13609
13875
|
// ../core/src/QueryManager.js
|
|
13610
13876
|
var Priority = { High: 0, Normal: 1, Low: 2 };
|
|
13611
|
-
|
|
13612
|
-
|
|
13613
|
-
|
|
13614
|
-
|
|
13615
|
-
|
|
13616
|
-
|
|
13617
|
-
|
|
13618
|
-
|
|
13619
|
-
|
|
13620
|
-
|
|
13621
|
-
|
|
13622
|
-
|
|
13623
|
-
pending.
|
|
13624
|
-
|
|
13625
|
-
|
|
13877
|
+
var QueryManager = class {
|
|
13878
|
+
constructor() {
|
|
13879
|
+
this.queue = priorityQueue(3);
|
|
13880
|
+
this.db = null;
|
|
13881
|
+
this.clientCache = null;
|
|
13882
|
+
this._logger = null;
|
|
13883
|
+
this._logQueries = false;
|
|
13884
|
+
this.recorders = [];
|
|
13885
|
+
this.pending = null;
|
|
13886
|
+
this._consolidate = null;
|
|
13887
|
+
}
|
|
13888
|
+
next() {
|
|
13889
|
+
if (this.pending || this.queue.isEmpty()) return;
|
|
13890
|
+
const { request, result } = this.queue.next();
|
|
13891
|
+
this.pending = this.submit(request, result);
|
|
13892
|
+
this.pending.finally(() => {
|
|
13893
|
+
this.pending = null;
|
|
13894
|
+
this.next();
|
|
13626
13895
|
});
|
|
13627
13896
|
}
|
|
13628
|
-
|
|
13629
|
-
queue.insert(entry, priority);
|
|
13630
|
-
next();
|
|
13897
|
+
enqueue(entry, priority = Priority.Normal) {
|
|
13898
|
+
this.queue.insert(entry, priority);
|
|
13899
|
+
this.next();
|
|
13631
13900
|
}
|
|
13632
|
-
|
|
13633
|
-
if (recorders.length && sql2) {
|
|
13634
|
-
recorders.forEach((rec) => rec.add(sql2));
|
|
13901
|
+
recordQuery(sql2) {
|
|
13902
|
+
if (this.recorders.length && sql2) {
|
|
13903
|
+
this.recorders.forEach((rec) => rec.add(sql2));
|
|
13635
13904
|
}
|
|
13636
13905
|
}
|
|
13637
|
-
async
|
|
13906
|
+
async submit(request, result) {
|
|
13638
13907
|
try {
|
|
13639
13908
|
const { query, type, cache = false, record = true, options } = request;
|
|
13640
13909
|
const sql2 = query ? `${query}` : null;
|
|
13641
13910
|
if (record) {
|
|
13642
|
-
recordQuery(sql2);
|
|
13911
|
+
this.recordQuery(sql2);
|
|
13643
13912
|
}
|
|
13644
13913
|
if (cache) {
|
|
13645
|
-
const cached = clientCache.get(sql2);
|
|
13914
|
+
const cached = this.clientCache.get(sql2);
|
|
13646
13915
|
if (cached) {
|
|
13647
|
-
|
|
13916
|
+
this._logger.debug("Cache");
|
|
13648
13917
|
result.fulfill(cached);
|
|
13649
13918
|
return;
|
|
13650
13919
|
}
|
|
13651
13920
|
}
|
|
13652
13921
|
const t0 = performance.now();
|
|
13653
|
-
|
|
13654
|
-
|
|
13655
|
-
|
|
13922
|
+
if (this._logQueries) {
|
|
13923
|
+
this._logger.debug("Query", { type, sql: sql2, ...options });
|
|
13924
|
+
}
|
|
13925
|
+
const data = await this.db.query({ type, sql: sql2, ...options });
|
|
13926
|
+
if (cache) this.clientCache.set(sql2, data);
|
|
13927
|
+
this._logger.debug(`Request: ${(performance.now() - t0).toFixed(1)}`);
|
|
13656
13928
|
result.fulfill(data);
|
|
13657
13929
|
} catch (err) {
|
|
13658
13930
|
result.reject(err);
|
|
13659
13931
|
}
|
|
13660
13932
|
}
|
|
13661
|
-
|
|
13662
|
-
|
|
13663
|
-
|
|
13664
|
-
|
|
13665
|
-
|
|
13666
|
-
|
|
13667
|
-
|
|
13668
|
-
|
|
13669
|
-
|
|
13670
|
-
|
|
13671
|
-
|
|
13672
|
-
|
|
13673
|
-
|
|
13674
|
-
|
|
13675
|
-
|
|
13676
|
-
|
|
13677
|
-
|
|
13678
|
-
request(request, priority = Priority.Normal) {
|
|
13679
|
-
const result = queryResult();
|
|
13680
|
-
const entry = { request, result };
|
|
13681
|
-
if (consolidate2) {
|
|
13682
|
-
consolidate2.add(entry, priority);
|
|
13683
|
-
} else {
|
|
13684
|
-
enqueue(entry, priority);
|
|
13685
|
-
}
|
|
13686
|
-
return result;
|
|
13687
|
-
},
|
|
13688
|
-
cancel(requests) {
|
|
13689
|
-
const set = new Set(requests);
|
|
13690
|
-
queue.remove(({ result }) => set.has(result));
|
|
13691
|
-
},
|
|
13692
|
-
clear() {
|
|
13693
|
-
queue.remove(({ result }) => {
|
|
13694
|
-
result.reject("Cleared");
|
|
13695
|
-
return true;
|
|
13696
|
-
});
|
|
13697
|
-
},
|
|
13698
|
-
record() {
|
|
13699
|
-
let state = [];
|
|
13700
|
-
const recorder = {
|
|
13701
|
-
add(query) {
|
|
13702
|
-
state.push(query);
|
|
13703
|
-
},
|
|
13704
|
-
reset() {
|
|
13705
|
-
state = [];
|
|
13706
|
-
},
|
|
13707
|
-
snapshot() {
|
|
13708
|
-
return state.slice();
|
|
13709
|
-
},
|
|
13710
|
-
stop() {
|
|
13711
|
-
recorders = recorders.filter((x2) => x2 !== recorder);
|
|
13712
|
-
return state;
|
|
13713
|
-
}
|
|
13714
|
-
};
|
|
13715
|
-
recorders.push(recorder);
|
|
13716
|
-
return recorder;
|
|
13933
|
+
cache(value) {
|
|
13934
|
+
return value !== void 0 ? this.clientCache = value === true ? lruCache() : value || voidCache() : this.clientCache;
|
|
13935
|
+
}
|
|
13936
|
+
logger(value) {
|
|
13937
|
+
return value ? this._logger = value : this._logger;
|
|
13938
|
+
}
|
|
13939
|
+
logQueries(value) {
|
|
13940
|
+
return value !== void 0 ? this._logQueries = !!value : this._logQueries;
|
|
13941
|
+
}
|
|
13942
|
+
connector(connector) {
|
|
13943
|
+
return connector ? this.db = connector : this.db;
|
|
13944
|
+
}
|
|
13945
|
+
consolidate(flag) {
|
|
13946
|
+
if (flag && !this._consolidate) {
|
|
13947
|
+
this._consolidate = consolidator(this.enqueue.bind(this), this.clientCache, this.recordQuery.bind(this));
|
|
13948
|
+
} else if (!flag && this._consolidate) {
|
|
13949
|
+
this._consolidate = null;
|
|
13717
13950
|
}
|
|
13718
|
-
}
|
|
13719
|
-
|
|
13951
|
+
}
|
|
13952
|
+
request(request, priority = Priority.Normal) {
|
|
13953
|
+
const result = new QueryResult();
|
|
13954
|
+
const entry = { request, result };
|
|
13955
|
+
if (this._consolidate) {
|
|
13956
|
+
this._consolidate.add(entry, priority);
|
|
13957
|
+
} else {
|
|
13958
|
+
this.enqueue(entry, priority);
|
|
13959
|
+
}
|
|
13960
|
+
return result;
|
|
13961
|
+
}
|
|
13962
|
+
cancel(requests) {
|
|
13963
|
+
const set = new Set(requests);
|
|
13964
|
+
if (set.size) {
|
|
13965
|
+
this.queue.remove(({ result }) => set.has(result));
|
|
13966
|
+
}
|
|
13967
|
+
}
|
|
13968
|
+
clear() {
|
|
13969
|
+
this.queue.remove(({ result }) => {
|
|
13970
|
+
result.reject("Cleared");
|
|
13971
|
+
return true;
|
|
13972
|
+
});
|
|
13973
|
+
}
|
|
13974
|
+
record() {
|
|
13975
|
+
let state = [];
|
|
13976
|
+
const recorder = {
|
|
13977
|
+
add(query) {
|
|
13978
|
+
state.push(query);
|
|
13979
|
+
},
|
|
13980
|
+
reset() {
|
|
13981
|
+
state = [];
|
|
13982
|
+
},
|
|
13983
|
+
snapshot() {
|
|
13984
|
+
return state.slice();
|
|
13985
|
+
},
|
|
13986
|
+
stop() {
|
|
13987
|
+
this.recorders = this.recorders.filter((x2) => x2 !== recorder);
|
|
13988
|
+
return state;
|
|
13989
|
+
}
|
|
13990
|
+
};
|
|
13991
|
+
this.recorders.push(recorder);
|
|
13992
|
+
return recorder;
|
|
13993
|
+
}
|
|
13994
|
+
};
|
|
13720
13995
|
|
|
13721
13996
|
// ../core/src/util/js-type.js
|
|
13722
13997
|
function jsType(type) {
|
|
@@ -13768,6 +14043,9 @@ function jsType(type) {
|
|
|
13768
14043
|
}
|
|
13769
14044
|
|
|
13770
14045
|
// ../core/src/util/convert-arrow.js
|
|
14046
|
+
function isArrowTable(values) {
|
|
14047
|
+
return typeof values?.getChild === "function";
|
|
14048
|
+
}
|
|
13771
14049
|
function convertArrowValue(type) {
|
|
13772
14050
|
if (DataType.isTimestamp(type)) {
|
|
13773
14051
|
return (v) => v == null ? v : new Date(v);
|
|
@@ -13781,6 +14059,41 @@ function convertArrowValue(type) {
|
|
|
13781
14059
|
}
|
|
13782
14060
|
return (v) => v;
|
|
13783
14061
|
}
|
|
14062
|
+
function convertArrowColumn(column2) {
|
|
14063
|
+
const { type } = column2;
|
|
14064
|
+
if (DataType.isTimestamp(type)) {
|
|
14065
|
+
const size = column2.length;
|
|
14066
|
+
const array = new Array(size);
|
|
14067
|
+
for (let row = 0; row < size; ++row) {
|
|
14068
|
+
const v = column2.get(row);
|
|
14069
|
+
array[row] = v == null ? null : new Date(v);
|
|
14070
|
+
}
|
|
14071
|
+
return array;
|
|
14072
|
+
}
|
|
14073
|
+
if (DataType.isInt(type) && type.bitWidth >= 64) {
|
|
14074
|
+
const size = column2.length;
|
|
14075
|
+
const array = column2.nullCount ? new Array(size) : new Float64Array(size);
|
|
14076
|
+
for (let row = 0; row < size; ++row) {
|
|
14077
|
+
const v = column2.get(row);
|
|
14078
|
+
array[row] = v == null ? null : Number(v);
|
|
14079
|
+
}
|
|
14080
|
+
return array;
|
|
14081
|
+
}
|
|
14082
|
+
if (DataType.isDecimal(type)) {
|
|
14083
|
+
const scale = 1 / Math.pow(10, type.scale);
|
|
14084
|
+
const size = column2.length;
|
|
14085
|
+
const array = column2.nullCount ? new Array(size) : new Float64Array(size);
|
|
14086
|
+
for (let row = 0; row < size; ++row) {
|
|
14087
|
+
const v = column2.get(row);
|
|
14088
|
+
array[row] = v == null ? null : decimalToNumber(v, scale);
|
|
14089
|
+
}
|
|
14090
|
+
return array;
|
|
14091
|
+
}
|
|
14092
|
+
if (column2.nullCount) {
|
|
14093
|
+
return Array.from(column2);
|
|
14094
|
+
}
|
|
14095
|
+
return column2.toArray();
|
|
14096
|
+
}
|
|
13784
14097
|
var BASE32 = Array.from(
|
|
13785
14098
|
{ length: 8 },
|
|
13786
14099
|
(_, i) => Math.pow(2, i * 32)
|
|
@@ -13885,58 +14198,92 @@ function coordinator(instance8) {
|
|
|
13885
14198
|
return _instance;
|
|
13886
14199
|
}
|
|
13887
14200
|
var Coordinator = class {
|
|
13888
|
-
constructor(db = socketConnector(),
|
|
13889
|
-
|
|
13890
|
-
|
|
13891
|
-
|
|
13892
|
-
|
|
14201
|
+
constructor(db = socketConnector(), {
|
|
14202
|
+
logger = console,
|
|
14203
|
+
manager = new QueryManager(),
|
|
14204
|
+
cache = true,
|
|
14205
|
+
consolidate: consolidate2 = true,
|
|
14206
|
+
indexes = {}
|
|
14207
|
+
} = {}) {
|
|
13893
14208
|
this.manager = manager;
|
|
14209
|
+
this.manager.cache(cache);
|
|
14210
|
+
this.manager.consolidate(consolidate2);
|
|
14211
|
+
this.dataCubeIndexer = new DataCubeIndexer(this, indexes);
|
|
13894
14212
|
this.logger(logger);
|
|
13895
|
-
this.configure(options);
|
|
13896
14213
|
this.databaseConnector(db);
|
|
13897
14214
|
this.clear();
|
|
13898
14215
|
}
|
|
13899
|
-
logger(logger) {
|
|
13900
|
-
if (arguments.length) {
|
|
13901
|
-
this._logger = logger || voidLogger();
|
|
13902
|
-
this.manager.logger(this._logger);
|
|
13903
|
-
}
|
|
13904
|
-
return this._logger;
|
|
13905
|
-
}
|
|
13906
14216
|
/**
|
|
13907
|
-
*
|
|
13908
|
-
* @param {object} [options]
|
|
13909
|
-
* @param {boolean} [options.
|
|
13910
|
-
* @param {boolean} [options.
|
|
13911
|
-
* @param {boolean|object} [options.indexes=true] Boolean flag to enable/disable
|
|
13912
|
-
* automatic data cube indexes or an index options object.
|
|
14217
|
+
* Clear the coordinator state.
|
|
14218
|
+
* @param {object} [options] Options object.
|
|
14219
|
+
* @param {boolean} [options.clients=true] If true, disconnect all clients.
|
|
14220
|
+
* @param {boolean} [options.cache=true] If true, clear the query cache.
|
|
13913
14221
|
*/
|
|
13914
|
-
configure({ cache = true, consolidate: consolidate2 = true, indexes = true } = {}) {
|
|
13915
|
-
this.manager.cache(cache);
|
|
13916
|
-
this.manager.consolidate(consolidate2);
|
|
13917
|
-
this.indexes = indexes;
|
|
13918
|
-
}
|
|
13919
14222
|
clear({ clients = true, cache = true } = {}) {
|
|
13920
14223
|
this.manager.clear();
|
|
13921
14224
|
if (clients) {
|
|
14225
|
+
this.filterGroups?.forEach((group) => group.disconnect());
|
|
14226
|
+
this.filterGroups = /* @__PURE__ */ new Map();
|
|
13922
14227
|
this.clients?.forEach((client) => this.disconnect(client));
|
|
13923
|
-
this.filterGroups?.forEach((group) => group.finalize());
|
|
13924
14228
|
this.clients = /* @__PURE__ */ new Set();
|
|
13925
|
-
this.filterGroups = /* @__PURE__ */ new Map();
|
|
13926
14229
|
}
|
|
13927
14230
|
if (cache) this.manager.cache().clear();
|
|
13928
14231
|
}
|
|
14232
|
+
/**
|
|
14233
|
+
* Get or set the database connector.
|
|
14234
|
+
* @param {*} [db] The database connector to use.
|
|
14235
|
+
* @returns The current database connector.
|
|
14236
|
+
*/
|
|
13929
14237
|
databaseConnector(db) {
|
|
13930
14238
|
return this.manager.connector(db);
|
|
13931
14239
|
}
|
|
14240
|
+
/**
|
|
14241
|
+
* Get or set the logger.
|
|
14242
|
+
* @param {*} logger The logger to use.
|
|
14243
|
+
* @returns The current logger
|
|
14244
|
+
*/
|
|
14245
|
+
logger(logger) {
|
|
14246
|
+
if (arguments.length) {
|
|
14247
|
+
this._logger = logger || voidLogger();
|
|
14248
|
+
this.manager.logger(this._logger);
|
|
14249
|
+
}
|
|
14250
|
+
return this._logger;
|
|
14251
|
+
}
|
|
13932
14252
|
// -- Query Management ----
|
|
14253
|
+
/**
|
|
14254
|
+
* Cancel previosuly submitted query requests. These queries will be
|
|
14255
|
+
* canceled if they are queued but have not yet been submitted.
|
|
14256
|
+
* @param {import('./util/query-result.js').QueryResult[]} requests An array
|
|
14257
|
+
* of query result objects, such as those returned by the `query` method.
|
|
14258
|
+
*/
|
|
13933
14259
|
cancel(requests) {
|
|
13934
14260
|
this.manager.cancel(requests);
|
|
13935
14261
|
}
|
|
14262
|
+
/**
|
|
14263
|
+
* Issue a query for which no result (return value) is needed.
|
|
14264
|
+
* @param {import('@uwdata/mosaic-sql').Query | string} query The query.
|
|
14265
|
+
* @param {object} [options] An options object.
|
|
14266
|
+
* @param {number} [options.priority] The query priority, defaults to
|
|
14267
|
+
* `Priority.Normal`.
|
|
14268
|
+
* @returns {import('./util/query-result.js').QueryResult} A query result
|
|
14269
|
+
* promise.
|
|
14270
|
+
*/
|
|
13936
14271
|
exec(query, { priority = Priority.Normal } = {}) {
|
|
13937
14272
|
query = Array.isArray(query) ? query.join(";\n") : query;
|
|
13938
14273
|
return this.manager.request({ type: "exec", query }, priority);
|
|
13939
14274
|
}
|
|
14275
|
+
/**
|
|
14276
|
+
* Issue a query to the backing database. The submitted query may be
|
|
14277
|
+
* consolidate with other queries and its results may be cached.
|
|
14278
|
+
* @param {import('@uwdata/mosaic-sql').Query | string} query The query.
|
|
14279
|
+
* @param {object} [options] An options object.
|
|
14280
|
+
* @param {'arrow' | 'json'} [options.type] The query result format type.
|
|
14281
|
+
* @param {boolean} [options.cache=true] If true, cache the query result.
|
|
14282
|
+
* @param {number} [options.priority] The query priority, defaults to
|
|
14283
|
+
* `Priority.Normal`.
|
|
14284
|
+
* @returns {import('./util/query-result.js').QueryResult} A query result
|
|
14285
|
+
* promise.
|
|
14286
|
+
*/
|
|
13940
14287
|
query(query, {
|
|
13941
14288
|
type = "arrow",
|
|
13942
14289
|
cache = true,
|
|
@@ -13945,6 +14292,15 @@ var Coordinator = class {
|
|
|
13945
14292
|
} = {}) {
|
|
13946
14293
|
return this.manager.request({ type, query, cache, options }, priority);
|
|
13947
14294
|
}
|
|
14295
|
+
/**
|
|
14296
|
+
* Issue a query to prefetch data for later use. The query result is cached
|
|
14297
|
+
* for efficient future access.
|
|
14298
|
+
* @param {import('@uwdata/mosaic-sql').Query | string} query The query.
|
|
14299
|
+
* @param {object} [options] An options object.
|
|
14300
|
+
* @param {'arrow' | 'json'} [options.type] The query result format type.
|
|
14301
|
+
* @returns {import('./util/query-result.js').QueryResult} A query result
|
|
14302
|
+
* promise.
|
|
14303
|
+
*/
|
|
13948
14304
|
prefetch(query, options = {}) {
|
|
13949
14305
|
return this.query(query, { ...options, cache: true, priority: Priority.Low });
|
|
13950
14306
|
}
|
|
@@ -13957,26 +14313,44 @@ var Coordinator = class {
|
|
|
13957
14313
|
return this.manager.request({ type: "load-bundle", options }, priority);
|
|
13958
14314
|
}
|
|
13959
14315
|
// -- Client Management ----
|
|
14316
|
+
/**
|
|
14317
|
+
* Update client data by submitting the given query and returning the
|
|
14318
|
+
* data (or error) to the client.
|
|
14319
|
+
* @param {import('./MosaicClient.js').MosaicClient} client A Mosaic client.
|
|
14320
|
+
* @param {import('@uwdata/mosaic-sql').Query | string} query The data query.
|
|
14321
|
+
* @param {number} [priority] The query priority.
|
|
14322
|
+
* @returns {Promise} A Promise that resolves upon completion of the update.
|
|
14323
|
+
*/
|
|
13960
14324
|
updateClient(client, query, priority = Priority.Normal) {
|
|
13961
14325
|
client.queryPending();
|
|
13962
14326
|
return this.query(query, { priority }).then(
|
|
13963
14327
|
(data) => client.queryResult(data).update(),
|
|
13964
14328
|
(err) => {
|
|
13965
|
-
client.queryError(err);
|
|
13966
14329
|
this._logger.error(err);
|
|
14330
|
+
client.queryError(err);
|
|
13967
14331
|
}
|
|
13968
|
-
);
|
|
14332
|
+
).catch((err) => this._logger.error(err));
|
|
13969
14333
|
}
|
|
14334
|
+
/**
|
|
14335
|
+
* Issue a query request for a client. If the query is null or undefined,
|
|
14336
|
+
* the client is simply updated. Otherwise `updateClient` is called. As a
|
|
14337
|
+
* side effect, this method clears the current data cube indexer state.
|
|
14338
|
+
* @param {import('./MosaicClient.js').MosaicClient} client The client
|
|
14339
|
+
* to update.
|
|
14340
|
+
* @param {import('@uwdata/mosaic-sql').Query | string | null} [query]
|
|
14341
|
+
* The query to issue.
|
|
14342
|
+
*/
|
|
13970
14343
|
requestQuery(client, query) {
|
|
13971
|
-
this.
|
|
14344
|
+
this.dataCubeIndexer.clear();
|
|
13972
14345
|
return query ? this.updateClient(client, query) : client.update();
|
|
13973
14346
|
}
|
|
13974
14347
|
/**
|
|
13975
14348
|
* Connect a client to the coordinator.
|
|
13976
|
-
* @param {import('./MosaicClient.js').MosaicClient} client
|
|
14349
|
+
* @param {import('./MosaicClient.js').MosaicClient} client The Mosaic
|
|
14350
|
+
* client to connect.
|
|
13977
14351
|
*/
|
|
13978
14352
|
async connect(client) {
|
|
13979
|
-
const { clients
|
|
14353
|
+
const { clients } = this;
|
|
13980
14354
|
if (clients.has(client)) {
|
|
13981
14355
|
throw new Error("Client already connected.");
|
|
13982
14356
|
}
|
|
@@ -13986,30 +14360,64 @@ var Coordinator = class {
|
|
|
13986
14360
|
if (fields?.length) {
|
|
13987
14361
|
client.fieldInfo(await queryFieldInfo(this, fields));
|
|
13988
14362
|
}
|
|
13989
|
-
|
|
13990
|
-
if (filter) {
|
|
13991
|
-
if (filterGroups.has(filter)) {
|
|
13992
|
-
filterGroups.get(filter).add(client);
|
|
13993
|
-
} else {
|
|
13994
|
-
const group = new FilterGroup(this, filter, indexes);
|
|
13995
|
-
filterGroups.set(filter, group.add(client));
|
|
13996
|
-
}
|
|
13997
|
-
}
|
|
14363
|
+
connectSelection(this, client.filterBy, client);
|
|
13998
14364
|
client.requestQuery();
|
|
13999
14365
|
}
|
|
14000
14366
|
/**
|
|
14001
14367
|
* Disconnect a client from the coordinator.
|
|
14002
|
-
*
|
|
14003
|
-
*
|
|
14368
|
+
* @param {import('./MosaicClient.js').MosaicClient} client The Mosaic
|
|
14369
|
+
* client to disconnect.
|
|
14004
14370
|
*/
|
|
14005
14371
|
disconnect(client) {
|
|
14006
14372
|
const { clients, filterGroups } = this;
|
|
14007
14373
|
if (!clients.has(client)) return;
|
|
14008
14374
|
clients.delete(client);
|
|
14009
|
-
filterGroups.get(client.filterBy)?.remove(client);
|
|
14010
14375
|
client.coordinator = null;
|
|
14376
|
+
const group = filterGroups.get(client.filterBy);
|
|
14377
|
+
if (group) {
|
|
14378
|
+
group.clients.delete(client);
|
|
14379
|
+
}
|
|
14011
14380
|
}
|
|
14012
14381
|
};
|
|
14382
|
+
function connectSelection(mc, selection, client) {
|
|
14383
|
+
if (!selection) return;
|
|
14384
|
+
let entry = mc.filterGroups.get(selection);
|
|
14385
|
+
if (!entry) {
|
|
14386
|
+
const activate = (clause) => activateSelection(mc, selection, clause);
|
|
14387
|
+
const value = () => updateSelection(mc, selection);
|
|
14388
|
+
selection.addEventListener("activate", activate);
|
|
14389
|
+
selection.addEventListener("value", value);
|
|
14390
|
+
entry = {
|
|
14391
|
+
selection,
|
|
14392
|
+
clients: /* @__PURE__ */ new Set(),
|
|
14393
|
+
disconnect() {
|
|
14394
|
+
selection.removeEventListener("activate", activate);
|
|
14395
|
+
selection.removeEventListener("value", value);
|
|
14396
|
+
}
|
|
14397
|
+
};
|
|
14398
|
+
mc.filterGroups.set(selection, entry);
|
|
14399
|
+
}
|
|
14400
|
+
entry.clients.add(client);
|
|
14401
|
+
}
|
|
14402
|
+
function activateSelection(mc, selection, clause) {
|
|
14403
|
+
const { dataCubeIndexer, filterGroups } = mc;
|
|
14404
|
+
const { clients } = filterGroups.get(selection);
|
|
14405
|
+
for (const client of clients) {
|
|
14406
|
+
dataCubeIndexer.index(client, selection, clause);
|
|
14407
|
+
}
|
|
14408
|
+
}
|
|
14409
|
+
function updateSelection(mc, selection) {
|
|
14410
|
+
const { dataCubeIndexer, filterGroups } = mc;
|
|
14411
|
+
const { clients } = filterGroups.get(selection);
|
|
14412
|
+
const { active } = selection;
|
|
14413
|
+
return Promise.allSettled(Array.from(clients, (client) => {
|
|
14414
|
+
const info = dataCubeIndexer.index(client, selection, active);
|
|
14415
|
+
const filter = info ? null : selection.predicate(client);
|
|
14416
|
+
if (info?.skip || !info && !filter) return;
|
|
14417
|
+
const query = info?.query(active.predicate) ?? client.query(filter);
|
|
14418
|
+
return mc.updateClient(client, query);
|
|
14419
|
+
}));
|
|
14420
|
+
}
|
|
14013
14421
|
|
|
14014
14422
|
// ../core/src/util/AsyncDispatch.js
|
|
14015
14423
|
var AsyncDispatch = class {
|
|
@@ -14066,7 +14474,7 @@ var AsyncDispatch = class {
|
|
|
14066
14474
|
* queue of unemitted event values prior to enqueueing a new value.
|
|
14067
14475
|
* This default implementation simply returns null, indicating that
|
|
14068
14476
|
* any other unemitted event values should be dropped (that is, all
|
|
14069
|
-
* queued events are filtered)
|
|
14477
|
+
* queued events are filtered).
|
|
14070
14478
|
* @param {string} type The event type.
|
|
14071
14479
|
* @param {*} value The new event value that will be enqueued.
|
|
14072
14480
|
* @returns {(value: *) => boolean|null} A dispatch queue filter
|
|
@@ -14083,6 +14491,16 @@ var AsyncDispatch = class {
|
|
|
14083
14491
|
const entry = this._callbacks.get(type);
|
|
14084
14492
|
entry?.queue.clear();
|
|
14085
14493
|
}
|
|
14494
|
+
/**
|
|
14495
|
+
* Returns a promise that resolves when any pending updates complete for
|
|
14496
|
+
* the event of the given type currently being processed. The Promise will
|
|
14497
|
+
* resolve immediately if the queue for the given event type is empty.
|
|
14498
|
+
* @param {string} type The event type to wait for.
|
|
14499
|
+
* @returns {Promise} A pending event promise.
|
|
14500
|
+
*/
|
|
14501
|
+
async pending(type) {
|
|
14502
|
+
await this._callbacks.get(type)?.pending;
|
|
14503
|
+
}
|
|
14086
14504
|
/**
|
|
14087
14505
|
* Emit an event value to listeners for the given event type.
|
|
14088
14506
|
* If a previous emit has not yet resolved, the event value
|
|
@@ -14270,10 +14688,13 @@ var Selection = class _Selection extends Param {
|
|
|
14270
14688
|
* @param {boolean} [options.cross=false] Boolean flag indicating
|
|
14271
14689
|
* cross-filtered resolution. If true, selection clauses will not
|
|
14272
14690
|
* be applied to the clients they are associated with.
|
|
14691
|
+
* @param {boolean} [options.empty=false] Boolean flag indicating if a lack
|
|
14692
|
+
* of clauses should correspond to an empty selection with no records. This
|
|
14693
|
+
* setting determines the default selection state.
|
|
14273
14694
|
* @returns {Selection} The new Selection instance.
|
|
14274
14695
|
*/
|
|
14275
|
-
static intersect({ cross = false } = {}) {
|
|
14276
|
-
return new _Selection(new SelectionResolver({ cross }));
|
|
14696
|
+
static intersect({ cross = false, empty = false } = {}) {
|
|
14697
|
+
return new _Selection(new SelectionResolver({ cross, empty }));
|
|
14277
14698
|
}
|
|
14278
14699
|
/**
|
|
14279
14700
|
* Create a new Selection instance with a
|
|
@@ -14282,10 +14703,13 @@ var Selection = class _Selection extends Param {
|
|
|
14282
14703
|
* @param {boolean} [options.cross=false] Boolean flag indicating
|
|
14283
14704
|
* cross-filtered resolution. If true, selection clauses will not
|
|
14284
14705
|
* be applied to the clients they are associated with.
|
|
14706
|
+
* @param {boolean} [options.empty=false] Boolean flag indicating if a lack
|
|
14707
|
+
* of clauses should correspond to an empty selection with no records. This
|
|
14708
|
+
* setting determines the default selection state.
|
|
14285
14709
|
* @returns {Selection} The new Selection instance.
|
|
14286
14710
|
*/
|
|
14287
|
-
static union({ cross = false } = {}) {
|
|
14288
|
-
return new _Selection(new SelectionResolver({ cross, union: true }));
|
|
14711
|
+
static union({ cross = false, empty = false } = {}) {
|
|
14712
|
+
return new _Selection(new SelectionResolver({ cross, empty, union: true }));
|
|
14289
14713
|
}
|
|
14290
14714
|
/**
|
|
14291
14715
|
* Create a new Selection instance with a singular resolution strategy
|
|
@@ -14294,18 +14718,25 @@ var Selection = class _Selection extends Param {
|
|
|
14294
14718
|
* @param {boolean} [options.cross=false] Boolean flag indicating
|
|
14295
14719
|
* cross-filtered resolution. If true, selection clauses will not
|
|
14296
14720
|
* be applied to the clients they are associated with.
|
|
14721
|
+
* @param {boolean} [options.empty=false] Boolean flag indicating if a lack
|
|
14722
|
+
* of clauses should correspond to an empty selection with no records. This
|
|
14723
|
+
* setting determines the default selection state.
|
|
14297
14724
|
* @returns {Selection} The new Selection instance.
|
|
14298
14725
|
*/
|
|
14299
|
-
static single({ cross = false } = {}) {
|
|
14300
|
-
return new _Selection(new SelectionResolver({ cross, single: true }));
|
|
14726
|
+
static single({ cross = false, empty = false } = {}) {
|
|
14727
|
+
return new _Selection(new SelectionResolver({ cross, empty, single: true }));
|
|
14301
14728
|
}
|
|
14302
14729
|
/**
|
|
14303
14730
|
* Create a new Selection instance with a
|
|
14304
14731
|
* cross-filtered intersect resolution strategy.
|
|
14732
|
+
* @param {object} [options] The selection options.
|
|
14733
|
+
* @param {boolean} [options.empty=false] Boolean flag indicating if a lack
|
|
14734
|
+
* of clauses should correspond to an empty selection with no records. This
|
|
14735
|
+
* setting determines the default selection state.
|
|
14305
14736
|
* @returns {Selection} The new Selection instance.
|
|
14306
14737
|
*/
|
|
14307
|
-
static crossfilter() {
|
|
14308
|
-
return new _Selection(new SelectionResolver({ cross: true }));
|
|
14738
|
+
static crossfilter({ empty = false } = {}) {
|
|
14739
|
+
return new _Selection(new SelectionResolver({ cross: true, empty }));
|
|
14309
14740
|
}
|
|
14310
14741
|
/**
|
|
14311
14742
|
* Create a new Selection instance.
|
|
@@ -14338,6 +14769,24 @@ var Selection = class _Selection extends Param {
|
|
|
14338
14769
|
s._value.active = { source };
|
|
14339
14770
|
return s;
|
|
14340
14771
|
}
|
|
14772
|
+
/**
|
|
14773
|
+
* The selection clause resolver.
|
|
14774
|
+
*/
|
|
14775
|
+
get resolver() {
|
|
14776
|
+
return this._resolver;
|
|
14777
|
+
}
|
|
14778
|
+
/**
|
|
14779
|
+
* Indicate if this selection has a single resolution strategy.
|
|
14780
|
+
*/
|
|
14781
|
+
get single() {
|
|
14782
|
+
return this._resolver.single;
|
|
14783
|
+
}
|
|
14784
|
+
/**
|
|
14785
|
+
* The current array of selection clauses.
|
|
14786
|
+
*/
|
|
14787
|
+
get clauses() {
|
|
14788
|
+
return super.value;
|
|
14789
|
+
}
|
|
14341
14790
|
/**
|
|
14342
14791
|
* The current active (most recently updated) selection clause.
|
|
14343
14792
|
*/
|
|
@@ -14352,16 +14801,12 @@ var Selection = class _Selection extends Param {
|
|
|
14352
14801
|
return this.active?.value;
|
|
14353
14802
|
}
|
|
14354
14803
|
/**
|
|
14355
|
-
* The
|
|
14356
|
-
|
|
14357
|
-
|
|
14358
|
-
return super.value;
|
|
14359
|
-
}
|
|
14360
|
-
/**
|
|
14361
|
-
* Indicate if this selection has a single resolution strategy.
|
|
14804
|
+
* The value corresponding to a given source. Returns undefined if
|
|
14805
|
+
* this selection does not include a clause from this source.
|
|
14806
|
+
* @param {*} source The clause source to look up the value for.
|
|
14362
14807
|
*/
|
|
14363
|
-
|
|
14364
|
-
return this.
|
|
14808
|
+
valueFor(source) {
|
|
14809
|
+
return this.clauses.find((c) => c.source === source)?.value;
|
|
14365
14810
|
}
|
|
14366
14811
|
/**
|
|
14367
14812
|
* Emit an activate event with the given selection clause.
|
|
@@ -14439,11 +14884,15 @@ var SelectionResolver = class {
|
|
|
14439
14884
|
* If false, an intersection strategy is used.
|
|
14440
14885
|
* @param {boolean} [options.cross=false] Boolean flag to indicate cross-filtering.
|
|
14441
14886
|
* @param {boolean} [options.single=false] Boolean flag to indicate single clauses only.
|
|
14887
|
+
* @param {boolean} [options.empty=false] Boolean flag indicating if a lack
|
|
14888
|
+
* of clauses should correspond to an empty selection with no records. This
|
|
14889
|
+
* setting determines the default selection state.
|
|
14442
14890
|
*/
|
|
14443
|
-
constructor({ union, cross, single } = {}) {
|
|
14891
|
+
constructor({ union, cross, single, empty } = {}) {
|
|
14444
14892
|
this.union = !!union;
|
|
14445
14893
|
this.cross = !!cross;
|
|
14446
14894
|
this.single = !!single;
|
|
14895
|
+
this.empty = !!empty;
|
|
14447
14896
|
}
|
|
14448
14897
|
/**
|
|
14449
14898
|
* Resolve a list of selection clauses according to the resolution strategy.
|
|
@@ -14478,7 +14927,10 @@ var SelectionResolver = class {
|
|
|
14478
14927
|
* based on the current state of this selection.
|
|
14479
14928
|
*/
|
|
14480
14929
|
predicate(clauseList, active, client) {
|
|
14481
|
-
const { union } = this;
|
|
14930
|
+
const { empty, union } = this;
|
|
14931
|
+
if (empty && !clauseList.length) {
|
|
14932
|
+
return ["FALSE"];
|
|
14933
|
+
}
|
|
14482
14934
|
if (this.skip(client, active)) return void 0;
|
|
14483
14935
|
const predicates = clauseList.filter((clause) => !this.skip(client, clause)).map((clause) => clause.predicate);
|
|
14484
14936
|
return union && predicates.length > 1 ? or(predicates) : predicates;
|
|
@@ -14498,6 +14950,96 @@ var SelectionResolver = class {
|
|
|
14498
14950
|
}
|
|
14499
14951
|
};
|
|
14500
14952
|
|
|
14953
|
+
// ../core/src/SelectionClause.js
|
|
14954
|
+
function clausePoint(field, value, {
|
|
14955
|
+
source,
|
|
14956
|
+
clients = source ? /* @__PURE__ */ new Set([source]) : void 0
|
|
14957
|
+
}) {
|
|
14958
|
+
const predicate = value !== void 0 ? isNotDistinct(field, literal(value)) : null;
|
|
14959
|
+
return {
|
|
14960
|
+
meta: { type: "point" },
|
|
14961
|
+
source,
|
|
14962
|
+
clients,
|
|
14963
|
+
value,
|
|
14964
|
+
predicate
|
|
14965
|
+
};
|
|
14966
|
+
}
|
|
14967
|
+
function clausePoints(fields, value, {
|
|
14968
|
+
source,
|
|
14969
|
+
clients = source ? /* @__PURE__ */ new Set([source]) : void 0
|
|
14970
|
+
}) {
|
|
14971
|
+
let predicate = null;
|
|
14972
|
+
if (value) {
|
|
14973
|
+
const clauses = value.map((vals) => {
|
|
14974
|
+
const list = vals.map((v, i) => isNotDistinct(fields[i], literal(v)));
|
|
14975
|
+
return list.length > 1 ? and(list) : list[0];
|
|
14976
|
+
});
|
|
14977
|
+
predicate = clauses.length > 1 ? or(clauses) : clauses[0];
|
|
14978
|
+
}
|
|
14979
|
+
return {
|
|
14980
|
+
meta: { type: "point" },
|
|
14981
|
+
source,
|
|
14982
|
+
clients,
|
|
14983
|
+
value,
|
|
14984
|
+
predicate
|
|
14985
|
+
};
|
|
14986
|
+
}
|
|
14987
|
+
function clauseInterval(field, value, {
|
|
14988
|
+
source,
|
|
14989
|
+
clients = source ? /* @__PURE__ */ new Set([source]) : void 0,
|
|
14990
|
+
bin,
|
|
14991
|
+
scale,
|
|
14992
|
+
pixelSize = 1
|
|
14993
|
+
}) {
|
|
14994
|
+
const predicate = value != null ? isBetween(field, value) : null;
|
|
14995
|
+
const meta = { type: "interval", scales: scale && [scale], bin, pixelSize };
|
|
14996
|
+
return { meta, source, clients, value, predicate };
|
|
14997
|
+
}
|
|
14998
|
+
var MATCH_METHODS = { contains, prefix, suffix, regexp: regexp_matches };
|
|
14999
|
+
function clauseMatch(field, value, {
|
|
15000
|
+
source,
|
|
15001
|
+
clients = void 0,
|
|
15002
|
+
method = "contains"
|
|
15003
|
+
}) {
|
|
15004
|
+
let fn = MATCH_METHODS[method];
|
|
15005
|
+
const predicate = value ? fn(field, literal(value)) : null;
|
|
15006
|
+
const meta = { type: "match", method };
|
|
15007
|
+
return { meta, source, clients, value, predicate };
|
|
15008
|
+
}
|
|
15009
|
+
|
|
15010
|
+
// ../core/src/util/to-data-columns.js
|
|
15011
|
+
function toDataColumns(data) {
|
|
15012
|
+
return isArrowTable(data) ? arrowToColumns(data) : arrayToColumns(data);
|
|
15013
|
+
}
|
|
15014
|
+
function arrowToColumns(data) {
|
|
15015
|
+
const { numRows, numCols, schema: { fields } } = data;
|
|
15016
|
+
const columns = {};
|
|
15017
|
+
for (let col = 0; col < numCols; ++col) {
|
|
15018
|
+
const name = fields[col].name;
|
|
15019
|
+
if (columns[name]) {
|
|
15020
|
+
console.warn(`Redundant column name "${name}". Skipping...`);
|
|
15021
|
+
} else {
|
|
15022
|
+
columns[name] = convertArrowColumn(data.getChildAt(col));
|
|
15023
|
+
}
|
|
15024
|
+
}
|
|
15025
|
+
return { numRows, columns };
|
|
15026
|
+
}
|
|
15027
|
+
function arrayToColumns(data) {
|
|
15028
|
+
const numRows = data.length;
|
|
15029
|
+
if (typeof data[0] === "object") {
|
|
15030
|
+
const names = numRows ? Object.keys(data[0]) : [];
|
|
15031
|
+
const columns = {};
|
|
15032
|
+
if (names.length > 0) {
|
|
15033
|
+
names.forEach((name) => {
|
|
15034
|
+
columns[name] = data.map((d) => d[name]);
|
|
15035
|
+
});
|
|
15036
|
+
}
|
|
15037
|
+
return { numRows, columns };
|
|
15038
|
+
} else {
|
|
15039
|
+
return { numRows, values: data };
|
|
15040
|
+
}
|
|
15041
|
+
}
|
|
15042
|
+
|
|
14501
15043
|
// src/input.js
|
|
14502
15044
|
function input(InputClass, options) {
|
|
14503
15045
|
const input2 = new InputClass(options);
|
|
@@ -14512,8 +15054,31 @@ var isObject2 = (v) => {
|
|
|
14512
15054
|
var menu = (options) => input(Menu, options);
|
|
14513
15055
|
var Menu = class extends MosaicClient {
|
|
14514
15056
|
/**
|
|
14515
|
-
* Create a new
|
|
14516
|
-
* @param {object} options Options object
|
|
15057
|
+
* Create a new menu input.
|
|
15058
|
+
* @param {object} [options] Options object
|
|
15059
|
+
* @param {HTMLElement} [options.element] The parent DOM element in which to
|
|
15060
|
+
* place the menu elements. If undefined, a new `div` element is created.
|
|
15061
|
+
* @param {Selection} [options.filterBy] A selection to filter the database
|
|
15062
|
+
* table indicated by the *from* option.
|
|
15063
|
+
* @param {Param} [options.as] The output param or selection. A selection
|
|
15064
|
+
* clause is added for the currently selected menu option.
|
|
15065
|
+
* @param {string} [options.field] The database column name to use within
|
|
15066
|
+
* generated selection clause predicates. Defaults to the *column* option.
|
|
15067
|
+
* @param {(any | { value: any, label?: string })[]} [options.options] An
|
|
15068
|
+
* array of menu options, as literal values or option objects. Option
|
|
15069
|
+
* objects have a `value` property and an optional `label` property. If no
|
|
15070
|
+
* label or *format* function is provided, the string-coerced value is used.
|
|
15071
|
+
* @param {(value: any) => string} [options.format] A format function that
|
|
15072
|
+
* takes an option value as input and generates a string label. The format
|
|
15073
|
+
* function is not applied when an explicit label is provided in an option
|
|
15074
|
+
* object.
|
|
15075
|
+
* @param {*} [options.value] The initial selected menu value.
|
|
15076
|
+
* @param {string} [options.from] The name of a database table to use as a data
|
|
15077
|
+
* source for this widget. Used in conjunction with the *column* option.
|
|
15078
|
+
* @param {string} [options.column] The name of a database column from which
|
|
15079
|
+
* to pull menu options. The unique column values are used as menu options.
|
|
15080
|
+
* Used in conjunction with the *from* option.
|
|
15081
|
+
* @param {string} [options.label] A text label for this input.
|
|
14517
15082
|
*/
|
|
14518
15083
|
constructor({
|
|
14519
15084
|
element,
|
|
@@ -14525,32 +15090,37 @@ var Menu = class extends MosaicClient {
|
|
|
14525
15090
|
// TODO
|
|
14526
15091
|
options,
|
|
14527
15092
|
value,
|
|
15093
|
+
field = column2,
|
|
14528
15094
|
as
|
|
14529
15095
|
} = {}) {
|
|
14530
15096
|
super(filterBy);
|
|
14531
15097
|
this.from = from;
|
|
14532
15098
|
this.column = column2;
|
|
14533
|
-
this.selection = as;
|
|
14534
15099
|
this.format = format2;
|
|
15100
|
+
this.field = field;
|
|
15101
|
+
const selection = this.selection = as;
|
|
14535
15102
|
this.element = element ?? document.createElement("div");
|
|
14536
15103
|
this.element.setAttribute("class", "input");
|
|
14537
|
-
this.element
|
|
15104
|
+
Object.defineProperty(this.element, "value", { value: this });
|
|
14538
15105
|
const lab = document.createElement("label");
|
|
14539
15106
|
lab.innerText = label || column2;
|
|
14540
15107
|
this.element.appendChild(lab);
|
|
14541
15108
|
this.select = document.createElement("select");
|
|
15109
|
+
this.element.appendChild(this.select);
|
|
14542
15110
|
if (options) {
|
|
14543
15111
|
this.data = options.map((value2) => isObject2(value2) ? value2 : { value: value2 });
|
|
15112
|
+
this.selectedValue(value ?? "");
|
|
14544
15113
|
this.update();
|
|
14545
15114
|
}
|
|
14546
|
-
|
|
14547
|
-
|
|
14548
|
-
|
|
14549
|
-
|
|
15115
|
+
if (selection) {
|
|
15116
|
+
const isParam2 = !isSelection(selection);
|
|
15117
|
+
if (value != null && (!isParam2 || selection.value === void 0)) {
|
|
15118
|
+
this.publish(value);
|
|
15119
|
+
}
|
|
14550
15120
|
this.select.addEventListener("input", () => {
|
|
14551
15121
|
this.publish(this.selectedValue() ?? null);
|
|
14552
15122
|
});
|
|
14553
|
-
if (
|
|
15123
|
+
if (isParam2) {
|
|
14554
15124
|
this.selection.addEventListener("value", (value2) => {
|
|
14555
15125
|
if (value2 !== this.select.value) {
|
|
14556
15126
|
this.selectedValue(value2);
|
|
@@ -14576,14 +15146,11 @@ var Menu = class extends MosaicClient {
|
|
|
14576
15146
|
this.select.selectedIndex = this.from ? 0 : -1;
|
|
14577
15147
|
}
|
|
14578
15148
|
publish(value) {
|
|
14579
|
-
const { selection,
|
|
15149
|
+
const { selection, field } = this;
|
|
14580
15150
|
if (isSelection(selection)) {
|
|
14581
|
-
|
|
14582
|
-
|
|
14583
|
-
|
|
14584
|
-
value,
|
|
14585
|
-
predicate: value !== "" && value !== void 0 ? eq(column2, literal(value)) : null
|
|
14586
|
-
});
|
|
15151
|
+
if (value === "") value = void 0;
|
|
15152
|
+
const clause = clausePoint(field, value, { source: this });
|
|
15153
|
+
selection.update(clause);
|
|
14587
15154
|
} else if (isParam(selection)) {
|
|
14588
15155
|
selection.update(value);
|
|
14589
15156
|
}
|
|
@@ -14598,7 +15165,7 @@ var Menu = class extends MosaicClient {
|
|
|
14598
15165
|
return this;
|
|
14599
15166
|
}
|
|
14600
15167
|
update() {
|
|
14601
|
-
const { data, format: format2, select } = this;
|
|
15168
|
+
const { data, format: format2, select, selection } = this;
|
|
14602
15169
|
select.replaceChildren();
|
|
14603
15170
|
for (const { value, label } of data) {
|
|
14604
15171
|
const opt = document.createElement("option");
|
|
@@ -14606,21 +15173,42 @@ var Menu = class extends MosaicClient {
|
|
|
14606
15173
|
opt.innerText = label ?? format2(value);
|
|
14607
15174
|
this.select.appendChild(opt);
|
|
14608
15175
|
}
|
|
14609
|
-
if (
|
|
14610
|
-
|
|
15176
|
+
if (selection) {
|
|
15177
|
+
const value = isSelection(selection) ? selection.valueFor(this) : selection.value;
|
|
15178
|
+
this.selectedValue(value ?? "");
|
|
14611
15179
|
}
|
|
14612
15180
|
return this;
|
|
14613
15181
|
}
|
|
14614
15182
|
};
|
|
14615
15183
|
|
|
14616
15184
|
// src/Search.js
|
|
14617
|
-
var FUNCTIONS = { contains, prefix, suffix, regexp: regexp_matches };
|
|
14618
15185
|
var _id = 0;
|
|
14619
15186
|
var search = (options) => input(Search, options);
|
|
14620
15187
|
var Search = class extends MosaicClient {
|
|
14621
15188
|
/**
|
|
14622
|
-
* Create a new
|
|
14623
|
-
* @param {object} options Options object
|
|
15189
|
+
* Create a new text search input.
|
|
15190
|
+
* @param {object} [options] Options object
|
|
15191
|
+
* @param {HTMLElement} [options.element] The parent DOM element in which to
|
|
15192
|
+
* place the search elements. If undefined, a new `div` element is created.
|
|
15193
|
+
* @param {Selection} [options.filterBy] A selection to filter the database
|
|
15194
|
+
* table indicated by the *from* option.
|
|
15195
|
+
* @param {Param} [options.as] The output param or selection. A selection
|
|
15196
|
+
* clause is added based on the current text search query.
|
|
15197
|
+
* @param {string} [options.field] The database column name to use within
|
|
15198
|
+
* generated selection clause predicates. Defaults to the *column* option.
|
|
15199
|
+
* @param {'contains' | 'prefix' | 'suffix' | 'regexp'} [options.type] The
|
|
15200
|
+
* type of text search query to perform. One of:
|
|
15201
|
+
* - `"contains"` (default): the query string may appear anywhere in the text
|
|
15202
|
+
* - `"prefix"`: the query string must appear at the start of the text
|
|
15203
|
+
* - `"suffix"`: the query string must appear at the end of the text
|
|
15204
|
+
* - `"regexp"`: the query string is a regular expression the text must match
|
|
15205
|
+
* @param {string} [options.from] The name of a database table to use as an
|
|
15206
|
+
* autocomplete data source for this widget. Used in conjunction with the
|
|
15207
|
+
* *column* option.
|
|
15208
|
+
* @param {string} [options.column] The name of a database column from which
|
|
15209
|
+
* to pull valid search results. The unique column values are used as search
|
|
15210
|
+
* autocomplete values. Used in conjunction with the *from* option.
|
|
15211
|
+
* @param {string} [options.label] A text label for this input.
|
|
14624
15212
|
*/
|
|
14625
15213
|
constructor({
|
|
14626
15214
|
element,
|
|
@@ -14629,6 +15217,7 @@ var Search = class extends MosaicClient {
|
|
|
14629
15217
|
column: column2,
|
|
14630
15218
|
label,
|
|
14631
15219
|
type = "contains",
|
|
15220
|
+
field = column2,
|
|
14632
15221
|
as
|
|
14633
15222
|
} = {}) {
|
|
14634
15223
|
super(filterBy);
|
|
@@ -14637,9 +15226,10 @@ var Search = class extends MosaicClient {
|
|
|
14637
15226
|
this.from = from;
|
|
14638
15227
|
this.column = column2;
|
|
14639
15228
|
this.selection = as;
|
|
15229
|
+
this.field = field;
|
|
14640
15230
|
this.element = element ?? document.createElement("div");
|
|
14641
15231
|
this.element.setAttribute("class", "input");
|
|
14642
|
-
this.element
|
|
15232
|
+
Object.defineProperty(this.element, "value", { value: this });
|
|
14643
15233
|
if (label) {
|
|
14644
15234
|
const lab = document.createElement("label");
|
|
14645
15235
|
lab.setAttribute("for", this.id);
|
|
@@ -14668,14 +15258,10 @@ var Search = class extends MosaicClient {
|
|
|
14668
15258
|
this.searchbox.value = "";
|
|
14669
15259
|
}
|
|
14670
15260
|
publish(value) {
|
|
14671
|
-
const { selection,
|
|
15261
|
+
const { selection, field, type } = this;
|
|
14672
15262
|
if (isSelection(selection)) {
|
|
14673
|
-
|
|
14674
|
-
|
|
14675
|
-
schema: { type },
|
|
14676
|
-
value,
|
|
14677
|
-
predicate: value ? FUNCTIONS[type](column2, literal(value)) : null
|
|
14678
|
-
});
|
|
15263
|
+
const clause = clauseMatch(field, value, { source: this, method: type });
|
|
15264
|
+
selection.update(clause);
|
|
14679
15265
|
} else if (isParam(selection)) {
|
|
14680
15266
|
selection.update(value);
|
|
14681
15267
|
}
|
|
@@ -14710,8 +15296,34 @@ var _id2 = 0;
|
|
|
14710
15296
|
var slider = (options) => input(Slider, options);
|
|
14711
15297
|
var Slider = class extends MosaicClient {
|
|
14712
15298
|
/**
|
|
14713
|
-
* Create a new
|
|
14714
|
-
* @param {object} options Options object
|
|
15299
|
+
* Create a new slider input.
|
|
15300
|
+
* @param {object} [options] Options object
|
|
15301
|
+
* @param {HTMLElement} [options.element] The parent DOM element in which to
|
|
15302
|
+
* place the slider elements. If undefined, a new `div` element is created.
|
|
15303
|
+
* @param {Selection} [options.filterBy] A selection to filter the database
|
|
15304
|
+
* table indicated by the *from* option.
|
|
15305
|
+
* @param {Param} [options.as] The output param or selection. A selection
|
|
15306
|
+
* clause is added based on the currently selected slider option.
|
|
15307
|
+
* @param {string} [options.field] The database column name to use within
|
|
15308
|
+
* generated selection clause predicates. Defaults to the *column* option.
|
|
15309
|
+
* @param {'point' | 'interval'} [options.select] The type of selection clause
|
|
15310
|
+
* predicate to generate if the **as** option is a Selection. If `'point'`
|
|
15311
|
+
* (the default), the selection predicate is an equality check for the slider
|
|
15312
|
+
* value. If `'interval'`, the predicate checks an interval from the minimum
|
|
15313
|
+
* to the current slider value.
|
|
15314
|
+
* @param {number} [options.min] The minimum slider value.
|
|
15315
|
+
* @param {number} [options.max] The maximum slider value.
|
|
15316
|
+
* @param {number} [options.step] The slider step, the amount to increment
|
|
15317
|
+
* between consecutive values.
|
|
15318
|
+
* @param {number} [options.value] The initial slider value.
|
|
15319
|
+
* @param {string} [options.from] The name of a database table to use as a data
|
|
15320
|
+
* source for this widget. Used in conjunction with the *column* option.
|
|
15321
|
+
* The minimum and maximum values of the column determine the slider range.
|
|
15322
|
+
* @param {string} [options.column] The name of a database column whose values
|
|
15323
|
+
* determine the slider range. Used in conjunction with the *from* option.
|
|
15324
|
+
* The minimum and maximum values of the column determine the slider range.
|
|
15325
|
+
* @param {string} [options.label] A text label for this input.
|
|
15326
|
+
* @param {number} [options.width] The width of the slider in screen pixels.
|
|
14715
15327
|
*/
|
|
14716
15328
|
constructor({
|
|
14717
15329
|
element,
|
|
@@ -14724,6 +15336,8 @@ var Slider = class extends MosaicClient {
|
|
|
14724
15336
|
column: column2,
|
|
14725
15337
|
label = column2,
|
|
14726
15338
|
value = as?.value,
|
|
15339
|
+
select = "point",
|
|
15340
|
+
field = column2,
|
|
14727
15341
|
width
|
|
14728
15342
|
} = {}) {
|
|
14729
15343
|
super(filterBy);
|
|
@@ -14731,41 +15345,49 @@ var Slider = class extends MosaicClient {
|
|
|
14731
15345
|
this.from = from;
|
|
14732
15346
|
this.column = column2 || "value";
|
|
14733
15347
|
this.selection = as;
|
|
15348
|
+
this.selectionType = select;
|
|
15349
|
+
this.field = field;
|
|
14734
15350
|
this.min = min2;
|
|
14735
15351
|
this.max = max2;
|
|
14736
15352
|
this.step = step;
|
|
14737
15353
|
this.element = element || document.createElement("div");
|
|
14738
15354
|
this.element.setAttribute("class", "input");
|
|
14739
|
-
this.element
|
|
15355
|
+
Object.defineProperty(this.element, "value", { value: this });
|
|
14740
15356
|
if (label) {
|
|
14741
|
-
const
|
|
14742
|
-
|
|
14743
|
-
|
|
14744
|
-
this.element.appendChild(
|
|
15357
|
+
const desc2 = document.createElement("label");
|
|
15358
|
+
desc2.setAttribute("for", this.id);
|
|
15359
|
+
desc2.innerText = label;
|
|
15360
|
+
this.element.appendChild(desc2);
|
|
14745
15361
|
}
|
|
14746
15362
|
this.slider = document.createElement("input");
|
|
14747
15363
|
this.slider.setAttribute("id", this.id);
|
|
14748
15364
|
this.slider.setAttribute("type", "range");
|
|
14749
15365
|
if (width != null) this.slider.style.width = `${+width}px`;
|
|
14750
|
-
if (min2 != null) this.slider.setAttribute("min", min2);
|
|
14751
|
-
if (max2 != null) this.slider.setAttribute("max", max2);
|
|
14752
|
-
if (step != null) this.slider.setAttribute("step", step);
|
|
15366
|
+
if (min2 != null) this.slider.setAttribute("min", `${min2}`);
|
|
15367
|
+
if (max2 != null) this.slider.setAttribute("max", `${max2}`);
|
|
15368
|
+
if (step != null) this.slider.setAttribute("step", `${step}`);
|
|
15369
|
+
this.element.appendChild(this.slider);
|
|
15370
|
+
this.curval = document.createElement("label");
|
|
15371
|
+
this.curval.setAttribute("for", this.id);
|
|
15372
|
+
this.curval.setAttribute("class", "value");
|
|
15373
|
+
this.element.appendChild(this.curval);
|
|
14753
15374
|
if (value != null) {
|
|
14754
|
-
this.slider.setAttribute("value", value);
|
|
15375
|
+
this.slider.setAttribute("value", `${value}`);
|
|
14755
15376
|
if (this.selection?.value === void 0) this.publish(value);
|
|
14756
15377
|
}
|
|
14757
|
-
this.
|
|
14758
|
-
|
|
14759
|
-
this.slider
|
|
14760
|
-
|
|
15378
|
+
this.curval.innerText = this.slider.value;
|
|
15379
|
+
this.slider.addEventListener("input", () => {
|
|
15380
|
+
const { value: value2 } = this.slider;
|
|
15381
|
+
this.curval.innerText = value2;
|
|
15382
|
+
if (this.selection) this.publish(+value2);
|
|
15383
|
+
});
|
|
15384
|
+
if (this.selection && !isSelection(this.selection)) {
|
|
15385
|
+
this.selection.addEventListener("value", (value2) => {
|
|
15386
|
+
if (value2 !== +this.slider.value) {
|
|
15387
|
+
this.slider.value = value2;
|
|
15388
|
+
this.curval.innerText = value2;
|
|
15389
|
+
}
|
|
14761
15390
|
});
|
|
14762
|
-
if (!isSelection(this.selection)) {
|
|
14763
|
-
this.selection.addEventListener("value", (value2) => {
|
|
14764
|
-
if (value2 !== +this.slider.value) {
|
|
14765
|
-
this.slider.value = value2;
|
|
14766
|
-
}
|
|
14767
|
-
});
|
|
14768
|
-
}
|
|
14769
15391
|
}
|
|
14770
15392
|
}
|
|
14771
15393
|
query(filter = []) {
|
|
@@ -14775,20 +15397,34 @@ var Slider = class extends MosaicClient {
|
|
|
14775
15397
|
}
|
|
14776
15398
|
queryResult(data) {
|
|
14777
15399
|
const { min: min2, max: max2 } = Array.from(data)[0];
|
|
14778
|
-
if (this.min == null)
|
|
14779
|
-
|
|
14780
|
-
|
|
15400
|
+
if (this.min == null) {
|
|
15401
|
+
this.min = min2;
|
|
15402
|
+
this.slider.setAttribute("min", `${min2}`);
|
|
15403
|
+
}
|
|
15404
|
+
if (this.max == null) {
|
|
15405
|
+
this.max = max2;
|
|
15406
|
+
this.slider.setAttribute("max", `${max2}`);
|
|
15407
|
+
}
|
|
15408
|
+
if (this.step == null) {
|
|
15409
|
+
this.step = (max2 - min2) / 500;
|
|
15410
|
+
this.slider.setAttribute("step", `${this.step}`);
|
|
15411
|
+
}
|
|
14781
15412
|
return this;
|
|
14782
15413
|
}
|
|
14783
15414
|
publish(value) {
|
|
14784
|
-
const {
|
|
15415
|
+
const { field, selectionType, selection } = this;
|
|
14785
15416
|
if (isSelection(selection)) {
|
|
14786
|
-
|
|
14787
|
-
|
|
14788
|
-
|
|
14789
|
-
|
|
14790
|
-
|
|
14791
|
-
|
|
15417
|
+
if (selectionType === "interval") {
|
|
15418
|
+
const domain = [this.min ?? 0, value];
|
|
15419
|
+
selection.update(clauseInterval(field, domain, {
|
|
15420
|
+
source: this,
|
|
15421
|
+
bin: "ceil",
|
|
15422
|
+
scale: { type: "identity", domain },
|
|
15423
|
+
pixelSize: this.step
|
|
15424
|
+
}));
|
|
15425
|
+
} else {
|
|
15426
|
+
selection.update(clausePoint(field, value, { source: this }));
|
|
15427
|
+
}
|
|
14792
15428
|
} else if (isParam(this.selection)) {
|
|
14793
15429
|
selection.update(value);
|
|
14794
15430
|
}
|
|
@@ -14849,7 +15485,8 @@ var Table2 = class extends MosaicClient {
|
|
|
14849
15485
|
width,
|
|
14850
15486
|
maxWidth,
|
|
14851
15487
|
height = 500,
|
|
14852
|
-
rowBatch = 100
|
|
15488
|
+
rowBatch = 100,
|
|
15489
|
+
as
|
|
14853
15490
|
} = {}) {
|
|
14854
15491
|
super(filterBy);
|
|
14855
15492
|
this.id = `table-${++_id3}`;
|
|
@@ -14861,12 +15498,14 @@ var Table2 = class extends MosaicClient {
|
|
|
14861
15498
|
this.offset = 0;
|
|
14862
15499
|
this.limit = +rowBatch;
|
|
14863
15500
|
this.pending = false;
|
|
15501
|
+
this.selection = as;
|
|
15502
|
+
this.currentRow = -1;
|
|
14864
15503
|
this.sortHeader = null;
|
|
14865
15504
|
this.sortColumn = null;
|
|
14866
15505
|
this.sortDesc = false;
|
|
14867
15506
|
this.element = element || document.createElement("div");
|
|
14868
15507
|
this.element.setAttribute("id", this.id);
|
|
14869
|
-
this.element
|
|
15508
|
+
Object.defineProperty(this.element, "value", { value: this });
|
|
14870
15509
|
if (typeof width === "number") this.element.style.width = `${width}px`;
|
|
14871
15510
|
if (maxWidth) this.element.style.maxWidth = `${maxWidth}px`;
|
|
14872
15511
|
this.element.style.maxHeight = `${height}px`;
|
|
@@ -14889,9 +15528,31 @@ var Table2 = class extends MosaicClient {
|
|
|
14889
15528
|
this.tbl.appendChild(this.head);
|
|
14890
15529
|
this.body = document.createElement("tbody");
|
|
14891
15530
|
this.tbl.appendChild(this.body);
|
|
15531
|
+
if (this.selection) {
|
|
15532
|
+
this.body.addEventListener("pointerover", (evt) => {
|
|
15533
|
+
const row = resolveRow(evt.target);
|
|
15534
|
+
if (row > -1 && row !== this.currentRow) {
|
|
15535
|
+
this.currentRow = row;
|
|
15536
|
+
this.selection.update(this.clause([row]));
|
|
15537
|
+
}
|
|
15538
|
+
});
|
|
15539
|
+
this.body.addEventListener("pointerleave", () => {
|
|
15540
|
+
this.currentRow = -1;
|
|
15541
|
+
this.selection.update(this.clause());
|
|
15542
|
+
});
|
|
15543
|
+
}
|
|
14892
15544
|
this.style = document.createElement("style");
|
|
14893
15545
|
this.element.appendChild(this.style);
|
|
14894
15546
|
}
|
|
15547
|
+
clause(rows = []) {
|
|
15548
|
+
const { data, limit, schema } = this;
|
|
15549
|
+
const fields = schema.map((s) => s.column);
|
|
15550
|
+
const values = rows.map((row) => {
|
|
15551
|
+
const { columns } = data[~~(row / limit)];
|
|
15552
|
+
return fields.map((f) => columns[f][row % limit]);
|
|
15553
|
+
});
|
|
15554
|
+
return clausePoints(fields, values, { source: this });
|
|
15555
|
+
}
|
|
14895
15556
|
requestData(offset = 0) {
|
|
14896
15557
|
this.offset = offset;
|
|
14897
15558
|
const query = this.query(this.filterBy?.predicate(this));
|
|
@@ -14929,27 +15590,32 @@ var Table2 = class extends MosaicClient {
|
|
|
14929
15590
|
queryResult(data) {
|
|
14930
15591
|
if (!this.pending) {
|
|
14931
15592
|
this.loaded = false;
|
|
15593
|
+
this.data = [];
|
|
14932
15594
|
this.body.replaceChildren();
|
|
15595
|
+
this.offset = 0;
|
|
14933
15596
|
}
|
|
14934
|
-
this.data
|
|
15597
|
+
this.data.push(toDataColumns(data));
|
|
14935
15598
|
return this;
|
|
14936
15599
|
}
|
|
14937
15600
|
update() {
|
|
14938
15601
|
const { body, formats, data, schema, limit } = this;
|
|
14939
15602
|
const nf = schema.length;
|
|
14940
|
-
|
|
14941
|
-
|
|
14942
|
-
|
|
15603
|
+
const n = data.length - 1;
|
|
15604
|
+
const rowCount = limit * n;
|
|
15605
|
+
const { numRows, columns } = data[n];
|
|
15606
|
+
const cols = schema.map((s) => columns[s.column]);
|
|
15607
|
+
for (let i = 0; i < numRows; ++i) {
|
|
14943
15608
|
const tr = document.createElement("tr");
|
|
14944
|
-
|
|
14945
|
-
|
|
15609
|
+
Object.assign(tr, { __row__: rowCount + i });
|
|
15610
|
+
for (let j = 0; j < nf; ++j) {
|
|
15611
|
+
const value = cols[j][i];
|
|
14946
15612
|
const td = document.createElement("td");
|
|
14947
|
-
td.innerText = value == null ? "" : formats[
|
|
15613
|
+
td.innerText = value == null ? "" : formats[j](value);
|
|
14948
15614
|
tr.appendChild(td);
|
|
14949
15615
|
}
|
|
14950
15616
|
body.appendChild(tr);
|
|
14951
15617
|
}
|
|
14952
|
-
if (
|
|
15618
|
+
if (numRows < limit) {
|
|
14953
15619
|
this.loaded = true;
|
|
14954
15620
|
}
|
|
14955
15621
|
this.pending = false;
|
|
@@ -14976,6 +15642,10 @@ var Table2 = class extends MosaicClient {
|
|
|
14976
15642
|
this.requestData();
|
|
14977
15643
|
}
|
|
14978
15644
|
};
|
|
15645
|
+
function resolveRow(element) {
|
|
15646
|
+
const p = element.parentElement;
|
|
15647
|
+
return Object.hasOwn(p, "__row__") ? +p.__row__ : -1;
|
|
15648
|
+
}
|
|
14979
15649
|
function formatof(base = {}, schema, locale) {
|
|
14980
15650
|
return schema.map(({ column: column2, type }) => {
|
|
14981
15651
|
if (column2 in base) {
|