@uwdata/mosaic-inputs 0.9.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 +1695 -1385
- package/dist/mosaic-inputs.min.js +6 -6
- package/package.json +5 -5
- package/src/Menu.js +2 -2
- package/src/Search.js +2 -2
- package/src/Slider.js +3 -3
- package/src/Table.js +52 -9
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:
|
|
@@ -4914,10 +4937,10 @@ var getDictionary = (data, index) => {
|
|
|
4914
4937
|
var getInterval = (data, index) => data.type.unit === IntervalUnit.DAY_TIME ? getIntervalDayTime(data, index) : getIntervalYearMonth(data, index);
|
|
4915
4938
|
var getIntervalDayTime = ({ values }, index) => values.subarray(2 * index, 2 * (index + 1));
|
|
4916
4939
|
var getIntervalYearMonth = ({ values }, index) => {
|
|
4917
|
-
const
|
|
4940
|
+
const interval = values[index];
|
|
4918
4941
|
const int32s = new Int32Array(2);
|
|
4919
|
-
int32s[0] = Math.trunc(
|
|
4920
|
-
int32s[1] = Math.trunc(
|
|
4942
|
+
int32s[0] = Math.trunc(interval / 12);
|
|
4943
|
+
int32s[1] = Math.trunc(interval % 12);
|
|
4921
4944
|
return int32s;
|
|
4922
4945
|
};
|
|
4923
4946
|
var getDurationSecond = ({ values }, index) => values[index];
|
|
@@ -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;
|
|
@@ -13040,37 +13095,12 @@ function create(name, query, {
|
|
|
13040
13095
|
return "CREATE" + (replace ? " OR REPLACE " : " ") + (temp ? "TEMP " : "") + (view ? "VIEW" : "TABLE") + (replace ? " " : " IF NOT EXISTS ") + name + " AS " + query;
|
|
13041
13096
|
}
|
|
13042
13097
|
|
|
13043
|
-
// ../core/src/util/hash.js
|
|
13044
|
-
function fnv_hash(v) {
|
|
13045
|
-
let a = 2166136261;
|
|
13046
|
-
for (let i = 0, n = v.length; i < n; ++i) {
|
|
13047
|
-
const c = v.charCodeAt(i);
|
|
13048
|
-
const d = c & 65280;
|
|
13049
|
-
if (d) a = fnv_multiply(a ^ d >> 8);
|
|
13050
|
-
a = fnv_multiply(a ^ c & 255);
|
|
13051
|
-
}
|
|
13052
|
-
return fnv_mix(a);
|
|
13053
|
-
}
|
|
13054
|
-
function fnv_multiply(a) {
|
|
13055
|
-
return a + (a << 1) + (a << 4) + (a << 7) + (a << 8) + (a << 24);
|
|
13056
|
-
}
|
|
13057
|
-
function fnv_mix(a) {
|
|
13058
|
-
a += a << 13;
|
|
13059
|
-
a ^= a >>> 7;
|
|
13060
|
-
a += a << 3;
|
|
13061
|
-
a ^= a >>> 17;
|
|
13062
|
-
a += a << 5;
|
|
13063
|
-
return a & 4294967295;
|
|
13064
|
-
}
|
|
13065
|
-
|
|
13066
13098
|
// ../core/src/util/index-columns.js
|
|
13067
|
-
var NO_INDEX = { from: NaN };
|
|
13068
13099
|
function indexColumns(client) {
|
|
13069
|
-
if (!client.filterIndexable) return
|
|
13100
|
+
if (!client.filterIndexable) return null;
|
|
13070
13101
|
const q = client.query();
|
|
13071
13102
|
const from = getBaseTable(q);
|
|
13072
|
-
if (typeof from !== "string" || !q.
|
|
13073
|
-
const g = new Set(q.groupby().map((c) => c.column));
|
|
13103
|
+
if (typeof from !== "string" || !q.select) return null;
|
|
13074
13104
|
const aggr = [];
|
|
13075
13105
|
const dims = [];
|
|
13076
13106
|
const aux = {};
|
|
@@ -13168,10 +13198,11 @@ function indexColumns(client) {
|
|
|
13168
13198
|
aggr.push({ [as]: agg`${op}("${as}")` });
|
|
13169
13199
|
break;
|
|
13170
13200
|
default:
|
|
13171
|
-
if (
|
|
13201
|
+
if (!aggregate) dims.push(as);
|
|
13172
13202
|
else return null;
|
|
13173
13203
|
}
|
|
13174
13204
|
}
|
|
13205
|
+
if (!aggr.length) return null;
|
|
13175
13206
|
return { from, dims, aggr, aux };
|
|
13176
13207
|
}
|
|
13177
13208
|
function auxName(type, ...args) {
|
|
@@ -13304,125 +13335,153 @@ function regrInterceptExpr(aux, args, from) {
|
|
|
13304
13335
|
return agg`${ay} - (${m}) * ${ax}`;
|
|
13305
13336
|
}
|
|
13306
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
|
+
|
|
13307
13361
|
// ../core/src/DataCubeIndexer.js
|
|
13362
|
+
var Skip = { skip: true, result: null };
|
|
13308
13363
|
var DataCubeIndexer = class {
|
|
13309
13364
|
/**
|
|
13310
|
-
*
|
|
13311
|
-
* @param {import('./Coordinator.js').Coordinator}
|
|
13312
|
-
* @param {
|
|
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.
|
|
13313
13371
|
*/
|
|
13314
|
-
constructor(
|
|
13315
|
-
|
|
13316
|
-
|
|
13372
|
+
constructor(coordinator2, {
|
|
13373
|
+
enabled = true,
|
|
13374
|
+
temp = true
|
|
13375
|
+
} = {}) {
|
|
13376
|
+
this.indexes = /* @__PURE__ */ new Map();
|
|
13377
|
+
this.active = null;
|
|
13317
13378
|
this.temp = temp;
|
|
13318
|
-
this.
|
|
13379
|
+
this.mc = coordinator2;
|
|
13380
|
+
this._enabled = enabled;
|
|
13319
13381
|
}
|
|
13320
|
-
|
|
13321
|
-
|
|
13322
|
-
|
|
13323
|
-
|
|
13324
|
-
|
|
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
|
+
}
|
|
13325
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
|
+
*/
|
|
13326
13401
|
clear() {
|
|
13327
|
-
|
|
13328
|
-
|
|
13329
|
-
|
|
13330
|
-
|
|
13331
|
-
|
|
13332
|
-
|
|
13333
|
-
|
|
13334
|
-
|
|
13335
|
-
|
|
13336
|
-
|
|
13337
|
-
|
|
13338
|
-
|
|
13339
|
-
|
|
13340
|
-
|
|
13341
|
-
|
|
13342
|
-
|
|
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;
|
|
13343
13423
|
const { source } = activeClause;
|
|
13344
|
-
if (source
|
|
13345
|
-
this.
|
|
13346
|
-
|
|
13347
|
-
|
|
13348
|
-
|
|
13349
|
-
|
|
13350
|
-
|
|
13351
|
-
|
|
13352
|
-
|
|
13353
|
-
|
|
13354
|
-
|
|
13355
|
-
|
|
13356
|
-
|
|
13357
|
-
|
|
13358
|
-
|
|
13359
|
-
|
|
13360
|
-
|
|
13361
|
-
|
|
13362
|
-
|
|
13363
|
-
|
|
13364
|
-
const
|
|
13365
|
-
|
|
13366
|
-
|
|
13367
|
-
|
|
13368
|
-
}
|
|
13369
|
-
const order = query.orderby();
|
|
13370
|
-
query.query.orderby = [];
|
|
13371
|
-
const sql2 = query.toString();
|
|
13372
|
-
const id = (fnv_hash(sql2) >>> 0).toString(16);
|
|
13373
|
-
const table2 = `cube_index_${id}`;
|
|
13374
|
-
const result = mc.exec(create(table2, sql2, { temp }));
|
|
13375
|
-
result.catch((e) => logger.error(e));
|
|
13376
|
-
indices.set(client, { table: table2, result, order, ...index });
|
|
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));
|
|
13377
13448
|
}
|
|
13378
|
-
|
|
13379
|
-
|
|
13380
|
-
async update() {
|
|
13381
|
-
const { clients, selection, active } = this;
|
|
13382
|
-
const filter = active.predicate(selection.active.predicate);
|
|
13383
|
-
return Promise.all(
|
|
13384
|
-
Array.from(clients).map((client) => this.updateClient(client, filter))
|
|
13385
|
-
);
|
|
13386
|
-
}
|
|
13387
|
-
async updateClient(client, filter) {
|
|
13388
|
-
const { mc, indices, selection } = this;
|
|
13389
|
-
if (!indices.has(client)) {
|
|
13390
|
-
filter = selection.predicate(client);
|
|
13391
|
-
return mc.updateClient(client, client.query(filter));
|
|
13392
|
-
}
|
|
13393
|
-
;
|
|
13394
|
-
const index = this.indices.get(client);
|
|
13395
|
-
if (!index) return;
|
|
13396
|
-
const { table: table2, dims, aggr, order = [] } = index;
|
|
13397
|
-
const query = Query.select(dims, aggr).from(table2).groupby(dims).where(filter).orderby(order);
|
|
13398
|
-
return mc.updateClient(client, query);
|
|
13449
|
+
indexes.set(client, info);
|
|
13450
|
+
return info;
|
|
13399
13451
|
}
|
|
13400
13452
|
};
|
|
13401
13453
|
function activeColumns(clause) {
|
|
13402
13454
|
const { source, meta } = clause;
|
|
13403
|
-
|
|
13404
|
-
|
|
13405
|
-
const { type, scales: scales2, bin, pixelSize = 1 } = meta;
|
|
13455
|
+
const clausePred = clause.predicate;
|
|
13456
|
+
const clauseCols = clausePred?.columns;
|
|
13406
13457
|
let predicate;
|
|
13407
|
-
|
|
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) {
|
|
13408
13469
|
const bins = scales2.map((s) => binInterval(s, pixelSize, bin));
|
|
13409
|
-
if (bins.some((b) => b
|
|
13410
|
-
if (bins.length === 1) {
|
|
13470
|
+
if (bins.some((b) => !b)) {
|
|
13471
|
+
} else if (bins.length === 1) {
|
|
13411
13472
|
predicate = (p) => p ? isBetween("active0", p.range.map(bins[0])) : [];
|
|
13412
|
-
columns = { active0: bins[0](
|
|
13473
|
+
columns = { active0: bins[0](clausePred.field) };
|
|
13413
13474
|
} else {
|
|
13414
|
-
predicate = (p) => p ? and(p.children.map(
|
|
13475
|
+
predicate = (p) => p ? and(p.children.map(
|
|
13476
|
+
({ range }, i) => isBetween(`active${i}`, range.map(bins[i]))
|
|
13477
|
+
)) : [];
|
|
13415
13478
|
columns = Object.fromEntries(
|
|
13416
|
-
|
|
13479
|
+
// @ts-ignore
|
|
13480
|
+
clausePred.children.map((p, i) => [`active${i}`, bins[i](p.field)])
|
|
13417
13481
|
);
|
|
13418
13482
|
}
|
|
13419
|
-
} else if (type === "point") {
|
|
13420
|
-
predicate = (x2) => x2;
|
|
13421
|
-
columns = Object.fromEntries(columns.map((col) => [`${col}`, asColumn(col)]));
|
|
13422
|
-
} else {
|
|
13423
|
-
return null;
|
|
13424
13483
|
}
|
|
13425
|
-
return { source, columns, predicate };
|
|
13484
|
+
return { source: columns ? source : null, columns, predicate };
|
|
13426
13485
|
}
|
|
13427
13486
|
var BIN = { ceil: "CEIL", round: "ROUND" };
|
|
13428
13487
|
function binInterval(scale, pixelSize, bin) {
|
|
@@ -13436,6 +13495,23 @@ function binInterval(scale, pixelSize, bin) {
|
|
|
13436
13495
|
const d = lo === 0 ? "" : ` - ${lo}::DOUBLE`;
|
|
13437
13496
|
return (value) => sql`${fn}(${s}(${sqlApply(value)}${d}))::INTEGER`;
|
|
13438
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
|
+
}
|
|
13439
13515
|
function subqueryPushdown(query, cols) {
|
|
13440
13516
|
const memo = /* @__PURE__ */ new Set();
|
|
13441
13517
|
const pushdown = (q) => {
|
|
@@ -13448,1290 +13524,1437 @@ function subqueryPushdown(query, cols) {
|
|
|
13448
13524
|
};
|
|
13449
13525
|
pushdown(query);
|
|
13450
13526
|
}
|
|
13451
|
-
|
|
13452
|
-
// ../core/src/util/AsyncDispatch.js
|
|
13453
|
-
var AsyncDispatch = class {
|
|
13454
|
-
/**
|
|
13455
|
-
* Create a new asynchronous dispatcher instance.
|
|
13456
|
-
*/
|
|
13457
|
-
constructor() {
|
|
13458
|
-
this._callbacks = /* @__PURE__ */ new Map();
|
|
13459
|
-
}
|
|
13460
|
-
/**
|
|
13461
|
-
* Add an event listener callback for the provided event type.
|
|
13462
|
-
* @param {string} type The event type.
|
|
13463
|
-
* @param {(value: *) => void | Promise} callback The event handler
|
|
13464
|
-
* callback function to add. If the callback has already been
|
|
13465
|
-
* added for the event type, this method has no effect.
|
|
13466
|
-
*/
|
|
13467
|
-
addEventListener(type, callback) {
|
|
13468
|
-
if (!this._callbacks.has(type)) {
|
|
13469
|
-
this._callbacks.set(type, {
|
|
13470
|
-
callbacks: /* @__PURE__ */ new Set(),
|
|
13471
|
-
pending: null,
|
|
13472
|
-
queue: new DispatchQueue()
|
|
13473
|
-
});
|
|
13474
|
-
}
|
|
13475
|
-
const entry = this._callbacks.get(type);
|
|
13476
|
-
entry.callbacks.add(callback);
|
|
13477
|
-
}
|
|
13527
|
+
var DataCubeInfo = class {
|
|
13478
13528
|
/**
|
|
13479
|
-
*
|
|
13480
|
-
* @param {
|
|
13481
|
-
* @param {(value: *) => void | Promise} callback The event handler
|
|
13482
|
-
* callback function to remove.
|
|
13529
|
+
* Create a new DataCubeInfo instance.
|
|
13530
|
+
* @param {object} options
|
|
13483
13531
|
*/
|
|
13484
|
-
|
|
13485
|
-
|
|
13486
|
-
|
|
13487
|
-
|
|
13488
|
-
|
|
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;
|
|
13489
13539
|
}
|
|
13490
13540
|
/**
|
|
13491
|
-
*
|
|
13492
|
-
*
|
|
13493
|
-
*
|
|
13494
|
-
*
|
|
13495
|
-
* @param {string} type The event type.
|
|
13496
|
-
* @param {*} value The event value.
|
|
13497
|
-
* @returns The (possibly transformed) event value to emit.
|
|
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.
|
|
13498
13545
|
*/
|
|
13499
|
-
|
|
13500
|
-
return
|
|
13546
|
+
query(predicate) {
|
|
13547
|
+
return this.select.clone().where(this.active.predicate(predicate));
|
|
13501
13548
|
}
|
|
13549
|
+
};
|
|
13550
|
+
|
|
13551
|
+
// ../core/src/util/query-result.js
|
|
13552
|
+
var QueryResult = class extends Promise {
|
|
13502
13553
|
/**
|
|
13503
|
-
*
|
|
13504
|
-
* queue of unemitted event values prior to enqueueing a new value.
|
|
13505
|
-
* This default implementation simply returns null, indicating that
|
|
13506
|
-
* any other unemitted event values should be dropped (that is, all
|
|
13507
|
-
* queued events are filtered)
|
|
13508
|
-
* @param {string} type The event type.
|
|
13509
|
-
* @param {*} value The new event value that will be enqueued.
|
|
13510
|
-
* @returns {(value: *) => boolean|null} A dispatch queue filter
|
|
13511
|
-
* function, or null if all unemitted event values should be filtered.
|
|
13554
|
+
* Create a new query result Promise.
|
|
13512
13555
|
*/
|
|
13513
|
-
|
|
13514
|
-
|
|
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;
|
|
13515
13565
|
}
|
|
13516
13566
|
/**
|
|
13517
|
-
*
|
|
13518
|
-
* @param {
|
|
13567
|
+
* Resolve the result Promise with the provided value.
|
|
13568
|
+
* @param {*} value The result value.
|
|
13569
|
+
* @returns {this}
|
|
13519
13570
|
*/
|
|
13520
|
-
|
|
13521
|
-
|
|
13522
|
-
|
|
13571
|
+
fulfill(value) {
|
|
13572
|
+
this._resolve(value);
|
|
13573
|
+
return this;
|
|
13523
13574
|
}
|
|
13524
13575
|
/**
|
|
13525
|
-
*
|
|
13526
|
-
*
|
|
13527
|
-
*
|
|
13528
|
-
* The actual event value given to listeners will be the result
|
|
13529
|
-
* of passing the input value through the emitValue() method.
|
|
13530
|
-
* @param {string} type The event type.
|
|
13531
|
-
* @param {*} value The event value.
|
|
13576
|
+
* Rejects the result Promise with the provided error.
|
|
13577
|
+
* @param {*} error The error value.
|
|
13578
|
+
* @returns {this}
|
|
13532
13579
|
*/
|
|
13533
|
-
|
|
13534
|
-
|
|
13535
|
-
|
|
13536
|
-
entry.queue.enqueue(value, this.emitQueueFilter(type, value));
|
|
13537
|
-
} else {
|
|
13538
|
-
const event = this.willEmit(type, value);
|
|
13539
|
-
const { callbacks, queue } = entry;
|
|
13540
|
-
if (callbacks?.size) {
|
|
13541
|
-
const callbackValues = Array.from(callbacks, (cb) => cb(event));
|
|
13542
|
-
entry.pending = Promise.allSettled(callbackValues).then(() => {
|
|
13543
|
-
entry.pending = null;
|
|
13544
|
-
if (!queue.isEmpty()) {
|
|
13545
|
-
this.emit(type, queue.dequeue());
|
|
13546
|
-
}
|
|
13547
|
-
});
|
|
13548
|
-
}
|
|
13549
|
-
}
|
|
13580
|
+
reject(error) {
|
|
13581
|
+
this._reject(error);
|
|
13582
|
+
return this;
|
|
13550
13583
|
}
|
|
13551
13584
|
};
|
|
13552
|
-
|
|
13553
|
-
|
|
13554
|
-
|
|
13555
|
-
|
|
13556
|
-
|
|
13557
|
-
|
|
13558
|
-
|
|
13559
|
-
|
|
13560
|
-
|
|
13561
|
-
|
|
13562
|
-
|
|
13563
|
-
|
|
13564
|
-
|
|
13565
|
-
|
|
13566
|
-
|
|
13567
|
-
|
|
13568
|
-
|
|
13569
|
-
|
|
13570
|
-
return !this.next;
|
|
13585
|
+
QueryResult.prototype.constructor = Promise;
|
|
13586
|
+
|
|
13587
|
+
// ../core/src/QueryConsolidator.js
|
|
13588
|
+
function wait(callback) {
|
|
13589
|
+
const method = typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : typeof setImmediate !== "undefined" ? setImmediate : setTimeout;
|
|
13590
|
+
return method(callback);
|
|
13591
|
+
}
|
|
13592
|
+
function consolidator(enqueue, cache, record) {
|
|
13593
|
+
let pending = [];
|
|
13594
|
+
let id = 0;
|
|
13595
|
+
function run() {
|
|
13596
|
+
const groups = entryGroups(pending, cache);
|
|
13597
|
+
pending = [];
|
|
13598
|
+
id = 0;
|
|
13599
|
+
for (const group of groups) {
|
|
13600
|
+
consolidate(group, enqueue, record);
|
|
13601
|
+
processResults(group, cache);
|
|
13602
|
+
}
|
|
13571
13603
|
}
|
|
13572
|
-
|
|
13573
|
-
|
|
13574
|
-
|
|
13575
|
-
|
|
13576
|
-
|
|
13577
|
-
|
|
13578
|
-
|
|
13579
|
-
* the provided function is applied to all queue entries. The
|
|
13580
|
-
* entry is retained if the filter function returns a truthy value,
|
|
13581
|
-
* otherwise the entry is removed.
|
|
13582
|
-
*/
|
|
13583
|
-
enqueue(value, filter) {
|
|
13584
|
-
const tail = { value };
|
|
13585
|
-
if (filter && this.next) {
|
|
13586
|
-
let curr = this;
|
|
13587
|
-
while (curr.next) {
|
|
13588
|
-
if (filter(curr.next.value)) {
|
|
13589
|
-
curr = curr.next;
|
|
13590
|
-
} else {
|
|
13591
|
-
curr.next = curr.next.next;
|
|
13592
|
-
}
|
|
13604
|
+
return {
|
|
13605
|
+
add(entry, priority) {
|
|
13606
|
+
if (entry.request.type === "arrow") {
|
|
13607
|
+
id = id || wait(() => run());
|
|
13608
|
+
pending.push({ entry, priority, index: pending.length });
|
|
13609
|
+
} else {
|
|
13610
|
+
enqueue(entry, priority);
|
|
13593
13611
|
}
|
|
13594
|
-
curr.next = tail;
|
|
13595
|
-
} else {
|
|
13596
|
-
this.next = tail;
|
|
13597
13612
|
}
|
|
13598
|
-
}
|
|
13599
|
-
/**
|
|
13600
|
-
* Remove and return the next queued event value.
|
|
13601
|
-
* @returns {*} The next event value in the queue.
|
|
13602
|
-
*/
|
|
13603
|
-
dequeue() {
|
|
13604
|
-
const { next } = this;
|
|
13605
|
-
this.next = next?.next;
|
|
13606
|
-
return next?.value;
|
|
13607
|
-
}
|
|
13608
|
-
};
|
|
13609
|
-
|
|
13610
|
-
// ../core/src/util/distinct.js
|
|
13611
|
-
function distinct(a, b) {
|
|
13612
|
-
return a === b ? false : a instanceof Date && b instanceof Date ? +a !== +b : Array.isArray(a) && Array.isArray(b) ? distinctArray(a, b) : true;
|
|
13613
|
+
};
|
|
13613
13614
|
}
|
|
13614
|
-
function
|
|
13615
|
-
|
|
13616
|
-
|
|
13617
|
-
|
|
13615
|
+
function entryGroups(entries, cache) {
|
|
13616
|
+
const groups = [];
|
|
13617
|
+
const groupMap = /* @__PURE__ */ new Map();
|
|
13618
|
+
for (const query of entries) {
|
|
13619
|
+
const { entry: { request } } = query;
|
|
13620
|
+
const key = consolidationKey(request.query, cache);
|
|
13621
|
+
if (!groupMap.has(key)) {
|
|
13622
|
+
const list = [];
|
|
13623
|
+
groups.push(list);
|
|
13624
|
+
groupMap.set(key, list);
|
|
13625
|
+
}
|
|
13626
|
+
groupMap.get(key).push(query);
|
|
13618
13627
|
}
|
|
13619
|
-
return
|
|
13628
|
+
return groups;
|
|
13620
13629
|
}
|
|
13621
|
-
|
|
13622
|
-
|
|
13623
|
-
|
|
13624
|
-
|
|
13630
|
+
function consolidationKey(query, cache) {
|
|
13631
|
+
const sql2 = `${query}`;
|
|
13632
|
+
if (query instanceof Query && !cache.get(sql2)) {
|
|
13633
|
+
if (
|
|
13634
|
+
// @ts-ignore
|
|
13635
|
+
query.orderby().length || query.where().length || // @ts-ignore
|
|
13636
|
+
query.qualify().length || query.having().length
|
|
13637
|
+
) {
|
|
13638
|
+
return sql2;
|
|
13639
|
+
}
|
|
13640
|
+
const q = query.clone().$select("*");
|
|
13641
|
+
const groupby = query.groupby();
|
|
13642
|
+
if (groupby.length) {
|
|
13643
|
+
const map = {};
|
|
13644
|
+
query.select().forEach(({ as, expr }) => map[as] = expr);
|
|
13645
|
+
q.$groupby(groupby.map((e) => e instanceof Ref && map[e.column] || e));
|
|
13646
|
+
}
|
|
13647
|
+
return `${q}`;
|
|
13648
|
+
} else {
|
|
13649
|
+
return sql2;
|
|
13650
|
+
}
|
|
13625
13651
|
}
|
|
13626
|
-
|
|
13627
|
-
|
|
13628
|
-
|
|
13629
|
-
|
|
13630
|
-
|
|
13631
|
-
|
|
13632
|
-
|
|
13633
|
-
|
|
13652
|
+
function consolidate(group, enqueue, record) {
|
|
13653
|
+
if (shouldConsolidate(group)) {
|
|
13654
|
+
enqueue({
|
|
13655
|
+
request: {
|
|
13656
|
+
type: "arrow",
|
|
13657
|
+
cache: false,
|
|
13658
|
+
record: false,
|
|
13659
|
+
query: group.query = consolidatedQuery(group, record)
|
|
13660
|
+
},
|
|
13661
|
+
result: group.result = new QueryResult()
|
|
13662
|
+
});
|
|
13663
|
+
} else {
|
|
13664
|
+
for (const { entry, priority } of group) {
|
|
13665
|
+
enqueue(entry, priority);
|
|
13666
|
+
}
|
|
13634
13667
|
}
|
|
13635
|
-
|
|
13636
|
-
|
|
13637
|
-
|
|
13638
|
-
|
|
13639
|
-
|
|
13640
|
-
|
|
13641
|
-
|
|
13668
|
+
}
|
|
13669
|
+
function shouldConsolidate(group) {
|
|
13670
|
+
if (group.length > 1) {
|
|
13671
|
+
const sql2 = `${group[0].entry.request.query}`;
|
|
13672
|
+
for (let i = 1; i < group.length; ++i) {
|
|
13673
|
+
if (sql2 !== `${group[i].entry.request.query}`) {
|
|
13674
|
+
return true;
|
|
13675
|
+
}
|
|
13676
|
+
}
|
|
13642
13677
|
}
|
|
13643
|
-
|
|
13644
|
-
|
|
13645
|
-
|
|
13646
|
-
|
|
13647
|
-
|
|
13648
|
-
|
|
13649
|
-
|
|
13650
|
-
|
|
13651
|
-
|
|
13652
|
-
|
|
13653
|
-
|
|
13654
|
-
|
|
13655
|
-
|
|
13656
|
-
|
|
13657
|
-
|
|
13678
|
+
return false;
|
|
13679
|
+
}
|
|
13680
|
+
function consolidatedQuery(group, record) {
|
|
13681
|
+
const maps = group.maps = [];
|
|
13682
|
+
const fields = /* @__PURE__ */ new Map();
|
|
13683
|
+
for (const item of group) {
|
|
13684
|
+
const { query: query2 } = item.entry.request;
|
|
13685
|
+
const fieldMap = [];
|
|
13686
|
+
maps.push(fieldMap);
|
|
13687
|
+
for (const { as, expr } of query2.select()) {
|
|
13688
|
+
const e = `${expr}`;
|
|
13689
|
+
if (!fields.has(e)) {
|
|
13690
|
+
fields.set(e, [`col${fields.size}`, expr]);
|
|
13691
|
+
}
|
|
13692
|
+
const [name] = fields.get(e);
|
|
13693
|
+
fieldMap.push([name, as]);
|
|
13658
13694
|
}
|
|
13659
|
-
|
|
13695
|
+
record(`${query2}`);
|
|
13660
13696
|
}
|
|
13661
|
-
|
|
13662
|
-
|
|
13663
|
-
|
|
13664
|
-
|
|
13665
|
-
|
|
13697
|
+
const query = group[0].entry.request.query.clone();
|
|
13698
|
+
const groupby = query.groupby();
|
|
13699
|
+
if (groupby.length) {
|
|
13700
|
+
const map = {};
|
|
13701
|
+
group.maps[0].forEach(([name, as]) => map[as] = name);
|
|
13702
|
+
query.$groupby(groupby.map((e) => e instanceof Ref && map[e.column] || e));
|
|
13666
13703
|
}
|
|
13667
|
-
|
|
13668
|
-
|
|
13669
|
-
|
|
13670
|
-
|
|
13671
|
-
|
|
13672
|
-
|
|
13673
|
-
|
|
13674
|
-
|
|
13675
|
-
|
|
13676
|
-
const
|
|
13677
|
-
|
|
13678
|
-
this.emit("value", value);
|
|
13679
|
-
} else {
|
|
13680
|
-
this.cancel("value");
|
|
13704
|
+
return query.$select(Array.from(fields.values()));
|
|
13705
|
+
}
|
|
13706
|
+
async function processResults(group, cache) {
|
|
13707
|
+
const { maps, query, result } = group;
|
|
13708
|
+
if (!maps) return;
|
|
13709
|
+
let data;
|
|
13710
|
+
try {
|
|
13711
|
+
data = await result;
|
|
13712
|
+
} catch (err) {
|
|
13713
|
+
for (const { entry } of group) {
|
|
13714
|
+
entry.result.reject(err);
|
|
13681
13715
|
}
|
|
13682
|
-
return
|
|
13716
|
+
return;
|
|
13683
13717
|
}
|
|
13684
|
-
|
|
13685
|
-
|
|
13686
|
-
|
|
13687
|
-
|
|
13688
|
-
|
|
13689
|
-
|
|
13690
|
-
|
|
13691
|
-
willEmit(type, value) {
|
|
13692
|
-
if (type === "value") {
|
|
13693
|
-
this._value = value;
|
|
13718
|
+
const describe = isDescribeQuery(query);
|
|
13719
|
+
group.forEach(({ entry }, index) => {
|
|
13720
|
+
const { request, result: result2 } = entry;
|
|
13721
|
+
const map = maps[index];
|
|
13722
|
+
const extract = describe && map ? filterResult(data, map) : map ? projectResult(data, map) : data;
|
|
13723
|
+
if (request.cache) {
|
|
13724
|
+
cache.set(String(request.query), extract);
|
|
13694
13725
|
}
|
|
13695
|
-
|
|
13696
|
-
}
|
|
13697
|
-
};
|
|
13698
|
-
|
|
13699
|
-
// ../core/src/Selection.js
|
|
13700
|
-
function isSelection(x2) {
|
|
13701
|
-
return x2 instanceof Selection;
|
|
13726
|
+
result2.fulfill(extract);
|
|
13727
|
+
});
|
|
13702
13728
|
}
|
|
13703
|
-
|
|
13704
|
-
|
|
13705
|
-
|
|
13706
|
-
|
|
13707
|
-
* @param {object} [options] The selection options.
|
|
13708
|
-
* @param {boolean} [options.cross=false] Boolean flag indicating
|
|
13709
|
-
* cross-filtered resolution. If true, selection clauses will not
|
|
13710
|
-
* be applied to the clients they are associated with.
|
|
13711
|
-
* @returns {Selection} The new Selection instance.
|
|
13712
|
-
*/
|
|
13713
|
-
static intersect({ cross = false } = {}) {
|
|
13714
|
-
return new _Selection(new SelectionResolver({ cross }));
|
|
13715
|
-
}
|
|
13716
|
-
/**
|
|
13717
|
-
* Create a new Selection instance with a
|
|
13718
|
-
* union (disjunction) resolution strategy.
|
|
13719
|
-
* @param {object} [options] The selection options.
|
|
13720
|
-
* @param {boolean} [options.cross=false] Boolean flag indicating
|
|
13721
|
-
* cross-filtered resolution. If true, selection clauses will not
|
|
13722
|
-
* be applied to the clients they are associated with.
|
|
13723
|
-
* @returns {Selection} The new Selection instance.
|
|
13724
|
-
*/
|
|
13725
|
-
static union({ cross = false } = {}) {
|
|
13726
|
-
return new _Selection(new SelectionResolver({ cross, union: true }));
|
|
13727
|
-
}
|
|
13728
|
-
/**
|
|
13729
|
-
* Create a new Selection instance with a singular resolution strategy
|
|
13730
|
-
* that keeps only the most recent selection clause.
|
|
13731
|
-
* @param {object} [options] The selection options.
|
|
13732
|
-
* @param {boolean} [options.cross=false] Boolean flag indicating
|
|
13733
|
-
* cross-filtered resolution. If true, selection clauses will not
|
|
13734
|
-
* be applied to the clients they are associated with.
|
|
13735
|
-
* @returns {Selection} The new Selection instance.
|
|
13736
|
-
*/
|
|
13737
|
-
static single({ cross = false } = {}) {
|
|
13738
|
-
return new _Selection(new SelectionResolver({ cross, single: true }));
|
|
13739
|
-
}
|
|
13740
|
-
/**
|
|
13741
|
-
* Create a new Selection instance with a
|
|
13742
|
-
* cross-filtered intersect resolution strategy.
|
|
13743
|
-
* @returns {Selection} The new Selection instance.
|
|
13744
|
-
*/
|
|
13745
|
-
static crossfilter() {
|
|
13746
|
-
return new _Selection(new SelectionResolver({ cross: true }));
|
|
13747
|
-
}
|
|
13748
|
-
/**
|
|
13749
|
-
* Create a new Selection instance.
|
|
13750
|
-
* @param {SelectionResolver} resolver The selection resolution
|
|
13751
|
-
* strategy to apply.
|
|
13752
|
-
*/
|
|
13753
|
-
constructor(resolver = new SelectionResolver()) {
|
|
13754
|
-
super([]);
|
|
13755
|
-
this._resolved = this._value;
|
|
13756
|
-
this._resolver = resolver;
|
|
13757
|
-
}
|
|
13758
|
-
/**
|
|
13759
|
-
* Create a cloned copy of this Selection instance.
|
|
13760
|
-
* @returns {Selection} A clone of this selection.
|
|
13761
|
-
*/
|
|
13762
|
-
clone() {
|
|
13763
|
-
const s = new _Selection(this._resolver);
|
|
13764
|
-
s._value = s._resolved = this._value;
|
|
13765
|
-
return s;
|
|
13766
|
-
}
|
|
13767
|
-
/**
|
|
13768
|
-
* Create a clone of this Selection with clauses corresponding
|
|
13769
|
-
* to the provided source removed.
|
|
13770
|
-
* @param {*} source The clause source to remove.
|
|
13771
|
-
* @returns {Selection} A cloned and updated Selection.
|
|
13772
|
-
*/
|
|
13773
|
-
remove(source) {
|
|
13774
|
-
const s = this.clone();
|
|
13775
|
-
s._value = s._resolved = s._resolver.resolve(this._resolved, { source });
|
|
13776
|
-
s._value.active = { source };
|
|
13777
|
-
return s;
|
|
13778
|
-
}
|
|
13779
|
-
/**
|
|
13780
|
-
* The selection clause resolver.
|
|
13781
|
-
*/
|
|
13782
|
-
get resolver() {
|
|
13783
|
-
return this._resolver;
|
|
13784
|
-
}
|
|
13785
|
-
/**
|
|
13786
|
-
* Indicate if this selection has a single resolution strategy.
|
|
13787
|
-
*/
|
|
13788
|
-
get single() {
|
|
13789
|
-
return this._resolver.single;
|
|
13790
|
-
}
|
|
13791
|
-
/**
|
|
13792
|
-
* The current array of selection clauses.
|
|
13793
|
-
*/
|
|
13794
|
-
get clauses() {
|
|
13795
|
-
return super.value;
|
|
13729
|
+
function projectResult(data, map) {
|
|
13730
|
+
const cols = {};
|
|
13731
|
+
for (const [name, as] of map) {
|
|
13732
|
+
cols[as] = data.getChild(name);
|
|
13796
13733
|
}
|
|
13797
|
-
|
|
13798
|
-
|
|
13799
|
-
|
|
13800
|
-
|
|
13801
|
-
|
|
13734
|
+
return new data.constructor(cols);
|
|
13735
|
+
}
|
|
13736
|
+
function filterResult(data, map) {
|
|
13737
|
+
const lookup = new Map(map);
|
|
13738
|
+
const result = [];
|
|
13739
|
+
for (const d of data) {
|
|
13740
|
+
if (lookup.has(d.column_name)) {
|
|
13741
|
+
result.push({ ...d, column_name: lookup.get(d.column_name) });
|
|
13742
|
+
}
|
|
13802
13743
|
}
|
|
13803
|
-
|
|
13804
|
-
|
|
13805
|
-
|
|
13806
|
-
|
|
13807
|
-
|
|
13808
|
-
|
|
13744
|
+
return result;
|
|
13745
|
+
}
|
|
13746
|
+
|
|
13747
|
+
// ../core/src/util/cache.js
|
|
13748
|
+
var requestIdle = typeof requestIdleCallback !== "undefined" ? requestIdleCallback : setTimeout;
|
|
13749
|
+
var voidCache = () => ({
|
|
13750
|
+
get: () => void 0,
|
|
13751
|
+
set: (key, value) => value,
|
|
13752
|
+
clear: () => {
|
|
13809
13753
|
}
|
|
13810
|
-
|
|
13811
|
-
|
|
13812
|
-
|
|
13813
|
-
|
|
13814
|
-
|
|
13815
|
-
|
|
13816
|
-
|
|
13754
|
+
});
|
|
13755
|
+
function lruCache({
|
|
13756
|
+
max: max2 = 1e3,
|
|
13757
|
+
// max entries
|
|
13758
|
+
ttl = 3 * 60 * 60 * 1e3
|
|
13759
|
+
// time-to-live, default 3 hours
|
|
13760
|
+
} = {}) {
|
|
13761
|
+
let cache = /* @__PURE__ */ new Map();
|
|
13762
|
+
function evict() {
|
|
13763
|
+
const expire = performance.now() - ttl;
|
|
13764
|
+
let lruKey = null;
|
|
13765
|
+
let lruLast = Infinity;
|
|
13766
|
+
for (const [key, value] of cache) {
|
|
13767
|
+
const { last: last2 } = value;
|
|
13768
|
+
if (last2 < lruLast) {
|
|
13769
|
+
lruKey = key;
|
|
13770
|
+
lruLast = last2;
|
|
13771
|
+
}
|
|
13772
|
+
if (expire > last2) {
|
|
13773
|
+
cache.delete(key);
|
|
13774
|
+
}
|
|
13775
|
+
}
|
|
13776
|
+
if (lruKey) {
|
|
13777
|
+
cache.delete(lruKey);
|
|
13778
|
+
}
|
|
13817
13779
|
}
|
|
13818
|
-
|
|
13819
|
-
|
|
13820
|
-
|
|
13821
|
-
|
|
13822
|
-
|
|
13823
|
-
|
|
13780
|
+
return {
|
|
13781
|
+
get(key) {
|
|
13782
|
+
const entry = cache.get(key);
|
|
13783
|
+
if (entry) {
|
|
13784
|
+
entry.last = performance.now();
|
|
13785
|
+
return entry.value;
|
|
13786
|
+
}
|
|
13787
|
+
},
|
|
13788
|
+
set(key, value) {
|
|
13789
|
+
cache.set(key, { last: performance.now(), value });
|
|
13790
|
+
if (cache.size > max2) requestIdle(evict);
|
|
13791
|
+
return value;
|
|
13792
|
+
},
|
|
13793
|
+
clear() {
|
|
13794
|
+
cache = /* @__PURE__ */ new Map();
|
|
13795
|
+
}
|
|
13796
|
+
};
|
|
13797
|
+
}
|
|
13798
|
+
|
|
13799
|
+
// ../core/src/util/priority-queue.js
|
|
13800
|
+
function priorityQueue(ranks) {
|
|
13801
|
+
const queue = Array.from(
|
|
13802
|
+
{ length: ranks },
|
|
13803
|
+
() => ({ head: null, tail: null })
|
|
13804
|
+
);
|
|
13805
|
+
return {
|
|
13806
|
+
/**
|
|
13807
|
+
* Indicate if the queue is empty.
|
|
13808
|
+
* @returns [boolean] true if empty, false otherwise.
|
|
13809
|
+
*/
|
|
13810
|
+
isEmpty() {
|
|
13811
|
+
return queue.every((list) => !list.head);
|
|
13812
|
+
},
|
|
13813
|
+
/**
|
|
13814
|
+
* Insert an item into the queue with a given priority rank.
|
|
13815
|
+
* @param {*} item The item to add.
|
|
13816
|
+
* @param {number} rank The integer priority rank.
|
|
13817
|
+
* Priority ranks are integers starting at zero.
|
|
13818
|
+
* Lower ranks indicate higher priority.
|
|
13819
|
+
*/
|
|
13820
|
+
insert(item, rank2) {
|
|
13821
|
+
const list = queue[rank2];
|
|
13822
|
+
if (!list) {
|
|
13823
|
+
throw new Error(`Invalid queue priority rank: ${rank2}`);
|
|
13824
|
+
}
|
|
13825
|
+
const node = { item, next: null };
|
|
13826
|
+
if (list.head === null) {
|
|
13827
|
+
list.head = list.tail = node;
|
|
13828
|
+
} else {
|
|
13829
|
+
list.tail = list.tail.next = node;
|
|
13830
|
+
}
|
|
13831
|
+
},
|
|
13832
|
+
/**
|
|
13833
|
+
* Remove a set of items from the queue, regardless of priority rank.
|
|
13834
|
+
* If a provided item is not in the queue it will be ignored.
|
|
13835
|
+
* @param {(item: *) => boolean} test A predicate function to test
|
|
13836
|
+
* if an item should be removed (true to drop, false to keep).
|
|
13837
|
+
*/
|
|
13838
|
+
remove(test) {
|
|
13839
|
+
for (const list of queue) {
|
|
13840
|
+
let { head, tail } = list;
|
|
13841
|
+
for (let prev = null, curr = head; curr; prev = curr, curr = curr.next) {
|
|
13842
|
+
if (test(curr.item)) {
|
|
13843
|
+
if (curr === head) {
|
|
13844
|
+
head = curr.next;
|
|
13845
|
+
} else {
|
|
13846
|
+
prev.next = curr.next;
|
|
13847
|
+
}
|
|
13848
|
+
if (curr === tail) tail = prev || head;
|
|
13849
|
+
}
|
|
13850
|
+
}
|
|
13851
|
+
list.head = head;
|
|
13852
|
+
list.tail = tail;
|
|
13853
|
+
}
|
|
13854
|
+
},
|
|
13855
|
+
/**
|
|
13856
|
+
* Remove and return the next highest priority item.
|
|
13857
|
+
* @returns {*} The next item in the queue,
|
|
13858
|
+
* or undefined if this queue is empty.
|
|
13859
|
+
*/
|
|
13860
|
+
next() {
|
|
13861
|
+
for (const list of queue) {
|
|
13862
|
+
const { head } = list;
|
|
13863
|
+
if (head !== null) {
|
|
13864
|
+
list.head = head.next;
|
|
13865
|
+
if (list.tail === head) {
|
|
13866
|
+
list.tail = null;
|
|
13867
|
+
}
|
|
13868
|
+
return head.item;
|
|
13869
|
+
}
|
|
13870
|
+
}
|
|
13871
|
+
}
|
|
13872
|
+
};
|
|
13873
|
+
}
|
|
13874
|
+
|
|
13875
|
+
// ../core/src/QueryManager.js
|
|
13876
|
+
var Priority = { High: 0, Normal: 1, Low: 2 };
|
|
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;
|
|
13824
13887
|
}
|
|
13825
|
-
|
|
13826
|
-
|
|
13827
|
-
|
|
13828
|
-
|
|
13829
|
-
|
|
13830
|
-
|
|
13831
|
-
|
|
13832
|
-
|
|
13833
|
-
return super.update(this._resolved);
|
|
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();
|
|
13895
|
+
});
|
|
13834
13896
|
}
|
|
13835
|
-
|
|
13836
|
-
|
|
13837
|
-
|
|
13838
|
-
|
|
13839
|
-
|
|
13840
|
-
|
|
13841
|
-
|
|
13842
|
-
*/
|
|
13843
|
-
willEmit(type, value) {
|
|
13844
|
-
if (type === "value") {
|
|
13845
|
-
this._value = value;
|
|
13846
|
-
return this.value;
|
|
13897
|
+
enqueue(entry, priority = Priority.Normal) {
|
|
13898
|
+
this.queue.insert(entry, priority);
|
|
13899
|
+
this.next();
|
|
13900
|
+
}
|
|
13901
|
+
recordQuery(sql2) {
|
|
13902
|
+
if (this.recorders.length && sql2) {
|
|
13903
|
+
this.recorders.forEach((rec) => rec.add(sql2));
|
|
13847
13904
|
}
|
|
13848
|
-
return value;
|
|
13849
13905
|
}
|
|
13850
|
-
|
|
13851
|
-
|
|
13852
|
-
|
|
13853
|
-
|
|
13854
|
-
|
|
13855
|
-
|
|
13856
|
-
|
|
13857
|
-
|
|
13858
|
-
|
|
13859
|
-
|
|
13906
|
+
async submit(request, result) {
|
|
13907
|
+
try {
|
|
13908
|
+
const { query, type, cache = false, record = true, options } = request;
|
|
13909
|
+
const sql2 = query ? `${query}` : null;
|
|
13910
|
+
if (record) {
|
|
13911
|
+
this.recordQuery(sql2);
|
|
13912
|
+
}
|
|
13913
|
+
if (cache) {
|
|
13914
|
+
const cached = this.clientCache.get(sql2);
|
|
13915
|
+
if (cached) {
|
|
13916
|
+
this._logger.debug("Cache");
|
|
13917
|
+
result.fulfill(cached);
|
|
13918
|
+
return;
|
|
13919
|
+
}
|
|
13920
|
+
}
|
|
13921
|
+
const t0 = performance.now();
|
|
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)}`);
|
|
13928
|
+
result.fulfill(data);
|
|
13929
|
+
} catch (err) {
|
|
13930
|
+
result.reject(err);
|
|
13931
|
+
}
|
|
13860
13932
|
}
|
|
13861
|
-
|
|
13862
|
-
|
|
13863
|
-
* The return value depends on the selection resolution strategy.
|
|
13864
|
-
* @param {*} client The selection clause.
|
|
13865
|
-
* @param {*} clause The client to test.
|
|
13866
|
-
* @returns True if the client should be skipped, false otherwise.
|
|
13867
|
-
*/
|
|
13868
|
-
skip(client, clause) {
|
|
13869
|
-
return this._resolver.skip(client, clause);
|
|
13933
|
+
cache(value) {
|
|
13934
|
+
return value !== void 0 ? this.clientCache = value === true ? lruCache() : value || voidCache() : this.clientCache;
|
|
13870
13935
|
}
|
|
13871
|
-
|
|
13872
|
-
|
|
13873
|
-
* @param {*} client The client whose data may be filtered.
|
|
13874
|
-
* @param {boolean} [noSkip=false] Disable skipping of active
|
|
13875
|
-
* cross-filtered sources. If set true, the source of the active
|
|
13876
|
-
* clause in a cross-filtered selection will not be skipped.
|
|
13877
|
-
* @returns {*} The query predicate for filtering client data,
|
|
13878
|
-
* based on the current state of this selection.
|
|
13879
|
-
*/
|
|
13880
|
-
predicate(client, noSkip = false) {
|
|
13881
|
-
const { clauses } = this;
|
|
13882
|
-
const active = noSkip ? null : clauses.active;
|
|
13883
|
-
return this._resolver.predicate(clauses, active, client);
|
|
13936
|
+
logger(value) {
|
|
13937
|
+
return value ? this._logger = value : this._logger;
|
|
13884
13938
|
}
|
|
13885
|
-
|
|
13886
|
-
|
|
13887
|
-
/**
|
|
13888
|
-
* Create a new selection resolved instance.
|
|
13889
|
-
* @param {object} [options] The resolution strategy options.
|
|
13890
|
-
* @param {boolean} [options.union=false] Boolean flag to indicate a union strategy.
|
|
13891
|
-
* If false, an intersection strategy is used.
|
|
13892
|
-
* @param {boolean} [options.cross=false] Boolean flag to indicate cross-filtering.
|
|
13893
|
-
* @param {boolean} [options.single=false] Boolean flag to indicate single clauses only.
|
|
13894
|
-
*/
|
|
13895
|
-
constructor({ union, cross, single } = {}) {
|
|
13896
|
-
this.union = !!union;
|
|
13897
|
-
this.cross = !!cross;
|
|
13898
|
-
this.single = !!single;
|
|
13939
|
+
logQueries(value) {
|
|
13940
|
+
return value !== void 0 ? this._logQueries = !!value : this._logQueries;
|
|
13899
13941
|
}
|
|
13900
|
-
|
|
13901
|
-
|
|
13902
|
-
* @param {*[]} clauseList An array of selection clauses.
|
|
13903
|
-
* @param {*} clause A new selection clause to add.
|
|
13904
|
-
* @returns {*[]} An updated array of selection clauses.
|
|
13905
|
-
*/
|
|
13906
|
-
resolve(clauseList, clause, reset = false) {
|
|
13907
|
-
const { source, predicate } = clause;
|
|
13908
|
-
const filtered = clauseList.filter((c) => source !== c.source);
|
|
13909
|
-
const clauses = this.single ? [] : filtered;
|
|
13910
|
-
if (this.single && reset) filtered.forEach((c) => c.source?.reset?.());
|
|
13911
|
-
if (predicate) clauses.push(clause);
|
|
13912
|
-
return clauses;
|
|
13942
|
+
connector(connector) {
|
|
13943
|
+
return connector ? this.db = connector : this.db;
|
|
13913
13944
|
}
|
|
13914
|
-
|
|
13915
|
-
|
|
13916
|
-
|
|
13917
|
-
|
|
13918
|
-
|
|
13919
|
-
|
|
13920
|
-
*/
|
|
13921
|
-
skip(client, clause) {
|
|
13922
|
-
return this.cross && clause?.clients?.has(client);
|
|
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;
|
|
13950
|
+
}
|
|
13923
13951
|
}
|
|
13924
|
-
|
|
13925
|
-
|
|
13926
|
-
|
|
13927
|
-
|
|
13928
|
-
|
|
13929
|
-
|
|
13930
|
-
|
|
13931
|
-
|
|
13932
|
-
|
|
13933
|
-
const { union } = this;
|
|
13934
|
-
if (this.skip(client, active)) return void 0;
|
|
13935
|
-
const predicates = clauseList.filter((clause) => !this.skip(client, clause)).map((clause) => clause.predicate);
|
|
13936
|
-
return union && predicates.length > 1 ? or(predicates) : predicates;
|
|
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;
|
|
13937
13961
|
}
|
|
13938
|
-
|
|
13939
|
-
|
|
13940
|
-
|
|
13941
|
-
|
|
13942
|
-
* function, or null if all unemitted event values should be filtered.
|
|
13943
|
-
*/
|
|
13944
|
-
queueFilter(value) {
|
|
13945
|
-
if (this.cross) {
|
|
13946
|
-
const source = value.active?.source;
|
|
13947
|
-
return (clauses) => clauses.active?.source !== source;
|
|
13962
|
+
cancel(requests) {
|
|
13963
|
+
const set = new Set(requests);
|
|
13964
|
+
if (set.size) {
|
|
13965
|
+
this.queue.remove(({ result }) => set.has(result));
|
|
13948
13966
|
}
|
|
13949
|
-
return null;
|
|
13950
13967
|
}
|
|
13951
|
-
|
|
13952
|
-
|
|
13953
|
-
|
|
13954
|
-
|
|
13955
|
-
|
|
13956
|
-
|
|
13957
|
-
|
|
13958
|
-
|
|
13959
|
-
|
|
13960
|
-
|
|
13961
|
-
|
|
13962
|
-
|
|
13963
|
-
|
|
13964
|
-
|
|
13965
|
-
|
|
13966
|
-
|
|
13967
|
-
|
|
13968
|
-
|
|
13969
|
-
|
|
13970
|
-
this.
|
|
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;
|
|
13971
13989
|
}
|
|
13972
13990
|
};
|
|
13973
|
-
|
|
13974
|
-
|
|
13975
|
-
}
|
|
13976
|
-
finalize() {
|
|
13977
|
-
const { value, activate } = this.handlers;
|
|
13978
|
-
this.selection.removeEventListener("value", value);
|
|
13979
|
-
this.selection.removeEventListener("activate", activate);
|
|
13980
|
-
}
|
|
13981
|
-
index(state) {
|
|
13982
|
-
const { selection } = this;
|
|
13983
|
-
const { resolver } = selection;
|
|
13984
|
-
this.indexer = state && (resolver.single || !resolver.union) ? new DataCubeIndexer(this.mc, { ...state, selection }) : null;
|
|
13985
|
-
}
|
|
13986
|
-
reset() {
|
|
13987
|
-
this.indexer?.reset();
|
|
13988
|
-
}
|
|
13989
|
-
add(client) {
|
|
13990
|
-
(this.clients = new Set(this.clients)).add(client);
|
|
13991
|
-
return this;
|
|
13992
|
-
}
|
|
13993
|
-
remove(client) {
|
|
13994
|
-
if (this.clients.has(client)) {
|
|
13995
|
-
(this.clients = new Set(this.clients)).delete(client);
|
|
13996
|
-
}
|
|
13997
|
-
return this;
|
|
13998
|
-
}
|
|
13999
|
-
/**
|
|
14000
|
-
* Internal method to process a selection update.
|
|
14001
|
-
* The return value is passed as a selection callback value.
|
|
14002
|
-
* @returns {Promise} A Promise that resolves when the update completes.
|
|
14003
|
-
*/
|
|
14004
|
-
update() {
|
|
14005
|
-
const { mc, indexer, clients, selection } = this;
|
|
14006
|
-
const hasIndex = indexer?.index(clients);
|
|
14007
|
-
return hasIndex ? indexer.update() : defaultUpdate(mc, clients, selection);
|
|
13991
|
+
this.recorders.push(recorder);
|
|
13992
|
+
return recorder;
|
|
14008
13993
|
}
|
|
14009
13994
|
};
|
|
14010
|
-
function defaultUpdate(mc, clients, selection) {
|
|
14011
|
-
return Promise.all(Array.from(clients).map((client) => {
|
|
14012
|
-
const filter = selection.predicate(client);
|
|
14013
|
-
if (filter != null) {
|
|
14014
|
-
return mc.updateClient(client, client.query(filter));
|
|
14015
|
-
}
|
|
14016
|
-
}));
|
|
14017
|
-
}
|
|
14018
13995
|
|
|
14019
|
-
// ../core/src/util/
|
|
14020
|
-
function
|
|
14021
|
-
|
|
14022
|
-
|
|
14023
|
-
|
|
14024
|
-
|
|
14025
|
-
|
|
14026
|
-
|
|
14027
|
-
|
|
14028
|
-
|
|
14029
|
-
|
|
14030
|
-
|
|
13996
|
+
// ../core/src/util/js-type.js
|
|
13997
|
+
function jsType(type) {
|
|
13998
|
+
switch (type) {
|
|
13999
|
+
case "BIGINT":
|
|
14000
|
+
case "HUGEINT":
|
|
14001
|
+
case "INTEGER":
|
|
14002
|
+
case "SMALLINT":
|
|
14003
|
+
case "TINYINT":
|
|
14004
|
+
case "UBIGINT":
|
|
14005
|
+
case "UINTEGER":
|
|
14006
|
+
case "USMALLINT":
|
|
14007
|
+
case "UTINYINT":
|
|
14008
|
+
case "DOUBLE":
|
|
14009
|
+
case "FLOAT":
|
|
14010
|
+
case "REAL":
|
|
14011
|
+
return "number";
|
|
14012
|
+
case "DATE":
|
|
14013
|
+
case "TIMESTAMP":
|
|
14014
|
+
case "TIMESTAMPTZ":
|
|
14015
|
+
case "TIMESTAMP WITH TIME ZONE":
|
|
14016
|
+
case "TIME":
|
|
14017
|
+
case "TIMESTAMP_NS":
|
|
14018
|
+
return "date";
|
|
14019
|
+
case "BOOLEAN":
|
|
14020
|
+
return "boolean";
|
|
14021
|
+
case "VARCHAR":
|
|
14022
|
+
case "UUID":
|
|
14023
|
+
case "JSON":
|
|
14024
|
+
return "string";
|
|
14025
|
+
case "ARRAY":
|
|
14026
|
+
case "LIST":
|
|
14027
|
+
return "array";
|
|
14028
|
+
case "BLOB":
|
|
14029
|
+
case "STRUCT":
|
|
14030
|
+
case "MAP":
|
|
14031
|
+
case "GEOMETRY":
|
|
14032
|
+
return "object";
|
|
14033
|
+
default:
|
|
14034
|
+
if (type.startsWith("DECIMAL")) {
|
|
14035
|
+
return "number";
|
|
14036
|
+
} else if (type.startsWith("STRUCT") || type.startsWith("MAP")) {
|
|
14037
|
+
return "object";
|
|
14038
|
+
} else if (type.endsWith("]")) {
|
|
14039
|
+
return "array";
|
|
14040
|
+
}
|
|
14041
|
+
throw new Error(`Unsupported type: ${type}`);
|
|
14042
|
+
}
|
|
14031
14043
|
}
|
|
14032
14044
|
|
|
14033
|
-
// ../core/src/
|
|
14034
|
-
function
|
|
14035
|
-
|
|
14036
|
-
return method(callback);
|
|
14045
|
+
// ../core/src/util/convert-arrow.js
|
|
14046
|
+
function isArrowTable(values) {
|
|
14047
|
+
return typeof values?.getChild === "function";
|
|
14037
14048
|
}
|
|
14038
|
-
function
|
|
14039
|
-
|
|
14040
|
-
|
|
14041
|
-
function run() {
|
|
14042
|
-
const groups = entryGroups(pending, cache);
|
|
14043
|
-
pending = [];
|
|
14044
|
-
id = 0;
|
|
14045
|
-
for (const group of groups) {
|
|
14046
|
-
consolidate(group, enqueue, record);
|
|
14047
|
-
processResults(group, cache);
|
|
14048
|
-
}
|
|
14049
|
+
function convertArrowValue(type) {
|
|
14050
|
+
if (DataType.isTimestamp(type)) {
|
|
14051
|
+
return (v) => v == null ? v : new Date(v);
|
|
14049
14052
|
}
|
|
14050
|
-
|
|
14051
|
-
|
|
14052
|
-
if (entry.request.type === "arrow") {
|
|
14053
|
-
id = id || wait(() => run());
|
|
14054
|
-
pending.push({ entry, priority, index: pending.length });
|
|
14055
|
-
} else {
|
|
14056
|
-
enqueue(entry, priority);
|
|
14057
|
-
}
|
|
14058
|
-
}
|
|
14059
|
-
};
|
|
14060
|
-
}
|
|
14061
|
-
function entryGroups(entries, cache) {
|
|
14062
|
-
const groups = [];
|
|
14063
|
-
const groupMap = /* @__PURE__ */ new Map();
|
|
14064
|
-
for (const query of entries) {
|
|
14065
|
-
const { entry: { request } } = query;
|
|
14066
|
-
const key = consolidationKey(request.query, cache);
|
|
14067
|
-
if (!groupMap.has(key)) {
|
|
14068
|
-
const list = [];
|
|
14069
|
-
groups.push(list);
|
|
14070
|
-
groupMap.set(key, list);
|
|
14071
|
-
}
|
|
14072
|
-
groupMap.get(key).push(query);
|
|
14053
|
+
if (DataType.isInt(type) && type.bitWidth >= 64) {
|
|
14054
|
+
return (v) => v == null ? v : Number(v);
|
|
14073
14055
|
}
|
|
14074
|
-
|
|
14075
|
-
|
|
14076
|
-
|
|
14077
|
-
const sql2 = `${query}`;
|
|
14078
|
-
if (query instanceof Query && !cache.get(sql2)) {
|
|
14079
|
-
if (
|
|
14080
|
-
// @ts-ignore
|
|
14081
|
-
query.orderby().length || query.where().length || // @ts-ignore
|
|
14082
|
-
query.qualify().length || query.having().length
|
|
14083
|
-
) {
|
|
14084
|
-
return sql2;
|
|
14085
|
-
}
|
|
14086
|
-
const q = query.clone().$select("*");
|
|
14087
|
-
const groupby = query.groupby();
|
|
14088
|
-
if (groupby.length) {
|
|
14089
|
-
const map = {};
|
|
14090
|
-
query.select().forEach(({ as, expr }) => map[as] = expr);
|
|
14091
|
-
q.$groupby(groupby.map((e) => e instanceof Ref && map[e.column] || e));
|
|
14092
|
-
}
|
|
14093
|
-
return `${q}`;
|
|
14094
|
-
} else {
|
|
14095
|
-
return sql2;
|
|
14056
|
+
if (DataType.isDecimal(type)) {
|
|
14057
|
+
const scale = 1 / Math.pow(10, type.scale);
|
|
14058
|
+
return (v) => v == null ? v : decimalToNumber(v, scale);
|
|
14096
14059
|
}
|
|
14060
|
+
return (v) => v;
|
|
14097
14061
|
}
|
|
14098
|
-
function
|
|
14099
|
-
|
|
14100
|
-
|
|
14101
|
-
|
|
14102
|
-
|
|
14103
|
-
|
|
14104
|
-
|
|
14105
|
-
|
|
14106
|
-
},
|
|
14107
|
-
result: group.result = queryResult()
|
|
14108
|
-
});
|
|
14109
|
-
} else {
|
|
14110
|
-
for (const { entry, priority } of group) {
|
|
14111
|
-
enqueue(entry, priority);
|
|
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);
|
|
14112
14070
|
}
|
|
14071
|
+
return array;
|
|
14113
14072
|
}
|
|
14114
|
-
|
|
14115
|
-
|
|
14116
|
-
|
|
14117
|
-
|
|
14118
|
-
|
|
14119
|
-
|
|
14120
|
-
return true;
|
|
14121
|
-
}
|
|
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);
|
|
14122
14079
|
}
|
|
14080
|
+
return array;
|
|
14123
14081
|
}
|
|
14124
|
-
|
|
14125
|
-
|
|
14126
|
-
|
|
14127
|
-
|
|
14128
|
-
|
|
14129
|
-
|
|
14130
|
-
|
|
14131
|
-
const fieldMap = [];
|
|
14132
|
-
maps.push(fieldMap);
|
|
14133
|
-
for (const { as, expr } of query2.select()) {
|
|
14134
|
-
const e = `${expr}`;
|
|
14135
|
-
if (!fields.has(e)) {
|
|
14136
|
-
fields.set(e, [`col${fields.size}`, expr]);
|
|
14137
|
-
}
|
|
14138
|
-
const [name] = fields.get(e);
|
|
14139
|
-
fieldMap.push([name, as]);
|
|
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);
|
|
14140
14089
|
}
|
|
14141
|
-
|
|
14090
|
+
return array;
|
|
14142
14091
|
}
|
|
14143
|
-
|
|
14144
|
-
|
|
14145
|
-
if (groupby.length) {
|
|
14146
|
-
const map = {};
|
|
14147
|
-
group.maps[0].forEach(([name, as]) => map[as] = name);
|
|
14148
|
-
query.$groupby(groupby.map((e) => e instanceof Ref && map[e.column] || e));
|
|
14092
|
+
if (column2.nullCount) {
|
|
14093
|
+
return Array.from(column2);
|
|
14149
14094
|
}
|
|
14150
|
-
return
|
|
14095
|
+
return column2.toArray();
|
|
14151
14096
|
}
|
|
14152
|
-
|
|
14153
|
-
|
|
14154
|
-
|
|
14155
|
-
|
|
14156
|
-
|
|
14157
|
-
|
|
14158
|
-
|
|
14159
|
-
|
|
14160
|
-
|
|
14161
|
-
|
|
14162
|
-
return;
|
|
14163
|
-
}
|
|
14164
|
-
const describe = isDescribeQuery(query);
|
|
14165
|
-
group.forEach(({ entry }, index) => {
|
|
14166
|
-
const { request, result: result2 } = entry;
|
|
14167
|
-
const map = maps[index];
|
|
14168
|
-
const extract = describe && map ? filterResult(data, map) : map ? projectResult(data, map) : data;
|
|
14169
|
-
if (request.cache) {
|
|
14170
|
-
cache.set(String(request.query), extract);
|
|
14097
|
+
var BASE32 = Array.from(
|
|
14098
|
+
{ length: 8 },
|
|
14099
|
+
(_, i) => Math.pow(2, i * 32)
|
|
14100
|
+
);
|
|
14101
|
+
function decimalToNumber(v, scale) {
|
|
14102
|
+
const n = v.length;
|
|
14103
|
+
let x2 = 0;
|
|
14104
|
+
if (v.signed && (v[n - 1] | 0) < 0) {
|
|
14105
|
+
for (let i = 0; i < n; ++i) {
|
|
14106
|
+
x2 += ~v[i] * BASE32[i];
|
|
14171
14107
|
}
|
|
14172
|
-
|
|
14173
|
-
}
|
|
14174
|
-
|
|
14175
|
-
|
|
14176
|
-
const cols = {};
|
|
14177
|
-
for (const [name, as] of map) {
|
|
14178
|
-
cols[as] = data.getChild(name);
|
|
14179
|
-
}
|
|
14180
|
-
return new data.constructor(cols);
|
|
14181
|
-
}
|
|
14182
|
-
function filterResult(data, map) {
|
|
14183
|
-
const lookup = new Map(map);
|
|
14184
|
-
const result = [];
|
|
14185
|
-
for (const d of data) {
|
|
14186
|
-
if (lookup.has(d.column_name)) {
|
|
14187
|
-
result.push({ ...d, column_name: lookup.get(d.column_name) });
|
|
14108
|
+
x2 = -(x2 + 1);
|
|
14109
|
+
} else {
|
|
14110
|
+
for (let i = 0; i < n; ++i) {
|
|
14111
|
+
x2 += v[i] * BASE32[i];
|
|
14188
14112
|
}
|
|
14189
14113
|
}
|
|
14190
|
-
return
|
|
14114
|
+
return x2 * scale;
|
|
14191
14115
|
}
|
|
14192
14116
|
|
|
14193
|
-
// ../core/src/util/
|
|
14194
|
-
var
|
|
14195
|
-
var
|
|
14196
|
-
|
|
14197
|
-
|
|
14198
|
-
|
|
14199
|
-
|
|
14200
|
-
|
|
14201
|
-
|
|
14202
|
-
|
|
14203
|
-
|
|
14204
|
-
|
|
14205
|
-
|
|
14206
|
-
|
|
14207
|
-
|
|
14208
|
-
|
|
14209
|
-
|
|
14210
|
-
|
|
14211
|
-
|
|
14212
|
-
|
|
14213
|
-
|
|
14214
|
-
if (last2 < lruLast) {
|
|
14215
|
-
lruKey = key;
|
|
14216
|
-
lruLast = last2;
|
|
14217
|
-
}
|
|
14218
|
-
if (expire > last2) {
|
|
14219
|
-
cache.delete(key);
|
|
14220
|
-
}
|
|
14221
|
-
}
|
|
14222
|
-
if (lruKey) {
|
|
14223
|
-
cache.delete(lruKey);
|
|
14224
|
-
}
|
|
14117
|
+
// ../core/src/util/field-info.js
|
|
14118
|
+
var Count = "count";
|
|
14119
|
+
var Nulls = "nulls";
|
|
14120
|
+
var Max = "max";
|
|
14121
|
+
var Min = "min";
|
|
14122
|
+
var Distinct = "distinct";
|
|
14123
|
+
var statMap = {
|
|
14124
|
+
[Count]: count,
|
|
14125
|
+
[Distinct]: (column2) => count(column2).distinct(),
|
|
14126
|
+
[Max]: max,
|
|
14127
|
+
[Min]: min,
|
|
14128
|
+
[Nulls]: (column2) => count().where(isNull(column2))
|
|
14129
|
+
};
|
|
14130
|
+
function summarize(table2, column2, stats) {
|
|
14131
|
+
return Query.from(table2).select(Array.from(stats, (s) => [s, statMap[s](column2)]));
|
|
14132
|
+
}
|
|
14133
|
+
async function queryFieldInfo(mc, fields) {
|
|
14134
|
+
if (fields.length === 1 && `${fields[0].column}` === "*") {
|
|
14135
|
+
return getTableInfo(mc, fields[0].table);
|
|
14136
|
+
} else {
|
|
14137
|
+
return (await Promise.all(fields.map((f) => getFieldInfo(mc, f)))).filter((x2) => x2);
|
|
14225
14138
|
}
|
|
14226
|
-
|
|
14227
|
-
|
|
14228
|
-
|
|
14229
|
-
|
|
14230
|
-
|
|
14231
|
-
|
|
14232
|
-
|
|
14233
|
-
|
|
14234
|
-
|
|
14235
|
-
|
|
14236
|
-
if (cache.size > max2) requestIdle(evict);
|
|
14237
|
-
return value;
|
|
14238
|
-
},
|
|
14239
|
-
clear() {
|
|
14240
|
-
cache = /* @__PURE__ */ new Map();
|
|
14241
|
-
}
|
|
14139
|
+
}
|
|
14140
|
+
async function getFieldInfo(mc, { table: table2, column: column2, stats }) {
|
|
14141
|
+
const q = Query.from({ source: table2 }).select({ column: column2 }).groupby(column2.aggregate ? sql`ALL` : []);
|
|
14142
|
+
const [desc2] = Array.from(await mc.query(Query.describe(q)));
|
|
14143
|
+
const info = {
|
|
14144
|
+
table: table2,
|
|
14145
|
+
column: `${column2}`,
|
|
14146
|
+
sqlType: desc2.column_type,
|
|
14147
|
+
type: jsType(desc2.column_type),
|
|
14148
|
+
nullable: desc2.null === "YES"
|
|
14242
14149
|
};
|
|
14150
|
+
if (!(stats?.length || stats?.size)) return info;
|
|
14151
|
+
const result = await mc.query(
|
|
14152
|
+
summarize(table2, column2, stats),
|
|
14153
|
+
{ persist: true }
|
|
14154
|
+
);
|
|
14155
|
+
for (let i = 0; i < result.numCols; ++i) {
|
|
14156
|
+
const { name } = result.schema.fields[i];
|
|
14157
|
+
const child = result.getChildAt(i);
|
|
14158
|
+
const convert = convertArrowValue(child.type);
|
|
14159
|
+
info[name] = convert(child.get(0));
|
|
14160
|
+
}
|
|
14161
|
+
return info;
|
|
14162
|
+
}
|
|
14163
|
+
async function getTableInfo(mc, table2) {
|
|
14164
|
+
const result = await mc.query(`DESCRIBE ${asRelation(table2)}`);
|
|
14165
|
+
return Array.from(result).map((desc2) => ({
|
|
14166
|
+
table: table2,
|
|
14167
|
+
column: desc2.column_name,
|
|
14168
|
+
sqlType: desc2.column_type,
|
|
14169
|
+
type: jsType(desc2.column_type),
|
|
14170
|
+
nullable: desc2.null === "YES"
|
|
14171
|
+
}));
|
|
14243
14172
|
}
|
|
14244
14173
|
|
|
14245
|
-
// ../core/src/util/
|
|
14246
|
-
function
|
|
14247
|
-
const queue = Array.from(
|
|
14248
|
-
{ length: ranks },
|
|
14249
|
-
() => ({ head: null, tail: null })
|
|
14250
|
-
);
|
|
14174
|
+
// ../core/src/util/void-logger.js
|
|
14175
|
+
function voidLogger() {
|
|
14251
14176
|
return {
|
|
14252
|
-
|
|
14253
|
-
* Indicate if the queue is empty.
|
|
14254
|
-
* @returns [boolean] true if empty, false otherwise.
|
|
14255
|
-
*/
|
|
14256
|
-
isEmpty() {
|
|
14257
|
-
return queue.every((list) => !list.head);
|
|
14177
|
+
debug() {
|
|
14258
14178
|
},
|
|
14259
|
-
|
|
14260
|
-
* Insert an item into the queue with a given priority rank.
|
|
14261
|
-
* @param {*} item The item to add.
|
|
14262
|
-
* @param {number} rank The integer priority rank.
|
|
14263
|
-
* Priority ranks are integers starting at zero.
|
|
14264
|
-
* Lower ranks indicate higher priority.
|
|
14265
|
-
*/
|
|
14266
|
-
insert(item, rank2) {
|
|
14267
|
-
const list = queue[rank2];
|
|
14268
|
-
if (!list) {
|
|
14269
|
-
throw new Error(`Invalid queue priority rank: ${rank2}`);
|
|
14270
|
-
}
|
|
14271
|
-
const node = { item, next: null };
|
|
14272
|
-
if (list.head === null) {
|
|
14273
|
-
list.head = list.tail = node;
|
|
14274
|
-
} else {
|
|
14275
|
-
list.tail = list.tail.next = node;
|
|
14276
|
-
}
|
|
14179
|
+
info() {
|
|
14277
14180
|
},
|
|
14278
|
-
|
|
14279
|
-
* Remove a set of items from the queue, regardless of priority rank.
|
|
14280
|
-
* If a provided item is not in the queue it will be ignored.
|
|
14281
|
-
* @param {(item: *) => boolean} test A predicate function to test
|
|
14282
|
-
* if an item should be removed (true to drop, false to keep).
|
|
14283
|
-
*/
|
|
14284
|
-
remove(test) {
|
|
14285
|
-
for (const list of queue) {
|
|
14286
|
-
let { head, tail } = list;
|
|
14287
|
-
for (let prev = null, curr = head; curr; prev = curr, curr = curr.next) {
|
|
14288
|
-
if (test(curr.item)) {
|
|
14289
|
-
if (curr === head) {
|
|
14290
|
-
head = curr.next;
|
|
14291
|
-
} else {
|
|
14292
|
-
prev.next = curr.next;
|
|
14293
|
-
}
|
|
14294
|
-
if (curr === tail) tail = prev || head;
|
|
14295
|
-
}
|
|
14296
|
-
}
|
|
14297
|
-
list.head = head;
|
|
14298
|
-
list.tail = tail;
|
|
14299
|
-
}
|
|
14181
|
+
log() {
|
|
14300
14182
|
},
|
|
14301
|
-
|
|
14302
|
-
|
|
14303
|
-
|
|
14304
|
-
* or undefined if this queue is empty.
|
|
14305
|
-
*/
|
|
14306
|
-
next() {
|
|
14307
|
-
for (const list of queue) {
|
|
14308
|
-
const { head } = list;
|
|
14309
|
-
if (head !== null) {
|
|
14310
|
-
list.head = head.next;
|
|
14311
|
-
if (list.tail === head) {
|
|
14312
|
-
list.tail = null;
|
|
14313
|
-
}
|
|
14314
|
-
return head.item;
|
|
14315
|
-
}
|
|
14316
|
-
}
|
|
14183
|
+
warn() {
|
|
14184
|
+
},
|
|
14185
|
+
error() {
|
|
14317
14186
|
}
|
|
14318
14187
|
};
|
|
14319
14188
|
}
|
|
14320
14189
|
|
|
14321
|
-
// ../core/src/
|
|
14322
|
-
var
|
|
14323
|
-
|
|
14324
|
-
|
|
14325
|
-
|
|
14326
|
-
|
|
14327
|
-
|
|
14328
|
-
this._logger = null;
|
|
14329
|
-
this._logQueries = false;
|
|
14330
|
-
this.recorders = [];
|
|
14331
|
-
this.pending = null;
|
|
14332
|
-
this._consolidate = null;
|
|
14190
|
+
// ../core/src/Coordinator.js
|
|
14191
|
+
var _instance;
|
|
14192
|
+
function coordinator(instance8) {
|
|
14193
|
+
if (instance8) {
|
|
14194
|
+
_instance = instance8;
|
|
14195
|
+
} else if (_instance == null) {
|
|
14196
|
+
_instance = new Coordinator();
|
|
14333
14197
|
}
|
|
14334
|
-
|
|
14335
|
-
|
|
14336
|
-
|
|
14337
|
-
|
|
14338
|
-
|
|
14339
|
-
|
|
14340
|
-
|
|
14341
|
-
|
|
14198
|
+
return _instance;
|
|
14199
|
+
}
|
|
14200
|
+
var Coordinator = class {
|
|
14201
|
+
constructor(db = socketConnector(), {
|
|
14202
|
+
logger = console,
|
|
14203
|
+
manager = new QueryManager(),
|
|
14204
|
+
cache = true,
|
|
14205
|
+
consolidate: consolidate2 = true,
|
|
14206
|
+
indexes = {}
|
|
14207
|
+
} = {}) {
|
|
14208
|
+
this.manager = manager;
|
|
14209
|
+
this.manager.cache(cache);
|
|
14210
|
+
this.manager.consolidate(consolidate2);
|
|
14211
|
+
this.dataCubeIndexer = new DataCubeIndexer(this, indexes);
|
|
14212
|
+
this.logger(logger);
|
|
14213
|
+
this.databaseConnector(db);
|
|
14214
|
+
this.clear();
|
|
14342
14215
|
}
|
|
14343
|
-
|
|
14344
|
-
|
|
14345
|
-
|
|
14216
|
+
/**
|
|
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.
|
|
14221
|
+
*/
|
|
14222
|
+
clear({ clients = true, cache = true } = {}) {
|
|
14223
|
+
this.manager.clear();
|
|
14224
|
+
if (clients) {
|
|
14225
|
+
this.filterGroups?.forEach((group) => group.disconnect());
|
|
14226
|
+
this.filterGroups = /* @__PURE__ */ new Map();
|
|
14227
|
+
this.clients?.forEach((client) => this.disconnect(client));
|
|
14228
|
+
this.clients = /* @__PURE__ */ new Set();
|
|
14229
|
+
}
|
|
14230
|
+
if (cache) this.manager.cache().clear();
|
|
14346
14231
|
}
|
|
14347
|
-
|
|
14348
|
-
|
|
14349
|
-
|
|
14232
|
+
/**
|
|
14233
|
+
* Get or set the database connector.
|
|
14234
|
+
* @param {*} [db] The database connector to use.
|
|
14235
|
+
* @returns The current database connector.
|
|
14236
|
+
*/
|
|
14237
|
+
databaseConnector(db) {
|
|
14238
|
+
return this.manager.connector(db);
|
|
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);
|
|
14350
14249
|
}
|
|
14250
|
+
return this._logger;
|
|
14351
14251
|
}
|
|
14352
|
-
|
|
14353
|
-
|
|
14354
|
-
|
|
14355
|
-
|
|
14356
|
-
|
|
14357
|
-
|
|
14358
|
-
|
|
14359
|
-
|
|
14360
|
-
|
|
14361
|
-
|
|
14362
|
-
|
|
14363
|
-
|
|
14364
|
-
|
|
14365
|
-
|
|
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
|
+
*/
|
|
14259
|
+
cancel(requests) {
|
|
14260
|
+
this.manager.cancel(requests);
|
|
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
|
+
*/
|
|
14271
|
+
exec(query, { priority = Priority.Normal } = {}) {
|
|
14272
|
+
query = Array.isArray(query) ? query.join(";\n") : query;
|
|
14273
|
+
return this.manager.request({ type: "exec", query }, priority);
|
|
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
|
+
*/
|
|
14287
|
+
query(query, {
|
|
14288
|
+
type = "arrow",
|
|
14289
|
+
cache = true,
|
|
14290
|
+
priority = Priority.Normal,
|
|
14291
|
+
...options
|
|
14292
|
+
} = {}) {
|
|
14293
|
+
return this.manager.request({ type, query, cache, options }, priority);
|
|
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
|
+
*/
|
|
14304
|
+
prefetch(query, options = {}) {
|
|
14305
|
+
return this.query(query, { ...options, cache: true, priority: Priority.Low });
|
|
14306
|
+
}
|
|
14307
|
+
createBundle(name, queries, priority = Priority.Low) {
|
|
14308
|
+
const options = { name, queries };
|
|
14309
|
+
return this.manager.request({ type: "create-bundle", options }, priority);
|
|
14310
|
+
}
|
|
14311
|
+
loadBundle(name, priority = Priority.High) {
|
|
14312
|
+
const options = { name };
|
|
14313
|
+
return this.manager.request({ type: "load-bundle", options }, priority);
|
|
14314
|
+
}
|
|
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
|
+
*/
|
|
14324
|
+
updateClient(client, query, priority = Priority.Normal) {
|
|
14325
|
+
client.queryPending();
|
|
14326
|
+
return this.query(query, { priority }).then(
|
|
14327
|
+
(data) => client.queryResult(data).update(),
|
|
14328
|
+
(err) => {
|
|
14329
|
+
this._logger.error(err);
|
|
14330
|
+
client.queryError(err);
|
|
14366
14331
|
}
|
|
14367
|
-
|
|
14368
|
-
|
|
14369
|
-
|
|
14332
|
+
).catch((err) => this._logger.error(err));
|
|
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
|
+
*/
|
|
14343
|
+
requestQuery(client, query) {
|
|
14344
|
+
this.dataCubeIndexer.clear();
|
|
14345
|
+
return query ? this.updateClient(client, query) : client.update();
|
|
14346
|
+
}
|
|
14347
|
+
/**
|
|
14348
|
+
* Connect a client to the coordinator.
|
|
14349
|
+
* @param {import('./MosaicClient.js').MosaicClient} client The Mosaic
|
|
14350
|
+
* client to connect.
|
|
14351
|
+
*/
|
|
14352
|
+
async connect(client) {
|
|
14353
|
+
const { clients } = this;
|
|
14354
|
+
if (clients.has(client)) {
|
|
14355
|
+
throw new Error("Client already connected.");
|
|
14356
|
+
}
|
|
14357
|
+
clients.add(client);
|
|
14358
|
+
client.coordinator = this;
|
|
14359
|
+
const fields = client.fields();
|
|
14360
|
+
if (fields?.length) {
|
|
14361
|
+
client.fieldInfo(await queryFieldInfo(this, fields));
|
|
14362
|
+
}
|
|
14363
|
+
connectSelection(this, client.filterBy, client);
|
|
14364
|
+
client.requestQuery();
|
|
14365
|
+
}
|
|
14366
|
+
/**
|
|
14367
|
+
* Disconnect a client from the coordinator.
|
|
14368
|
+
* @param {import('./MosaicClient.js').MosaicClient} client The Mosaic
|
|
14369
|
+
* client to disconnect.
|
|
14370
|
+
*/
|
|
14371
|
+
disconnect(client) {
|
|
14372
|
+
const { clients, filterGroups } = this;
|
|
14373
|
+
if (!clients.has(client)) return;
|
|
14374
|
+
clients.delete(client);
|
|
14375
|
+
client.coordinator = null;
|
|
14376
|
+
const group = filterGroups.get(client.filterBy);
|
|
14377
|
+
if (group) {
|
|
14378
|
+
group.clients.delete(client);
|
|
14379
|
+
}
|
|
14380
|
+
}
|
|
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);
|
|
14370
14396
|
}
|
|
14371
|
-
|
|
14372
|
-
|
|
14373
|
-
|
|
14374
|
-
|
|
14375
|
-
|
|
14376
|
-
|
|
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
|
+
}
|
|
14421
|
+
|
|
14422
|
+
// ../core/src/util/AsyncDispatch.js
|
|
14423
|
+
var AsyncDispatch = class {
|
|
14424
|
+
/**
|
|
14425
|
+
* Create a new asynchronous dispatcher instance.
|
|
14426
|
+
*/
|
|
14427
|
+
constructor() {
|
|
14428
|
+
this._callbacks = /* @__PURE__ */ new Map();
|
|
14429
|
+
}
|
|
14430
|
+
/**
|
|
14431
|
+
* Add an event listener callback for the provided event type.
|
|
14432
|
+
* @param {string} type The event type.
|
|
14433
|
+
* @param {(value: *) => void | Promise} callback The event handler
|
|
14434
|
+
* callback function to add. If the callback has already been
|
|
14435
|
+
* added for the event type, this method has no effect.
|
|
14436
|
+
*/
|
|
14437
|
+
addEventListener(type, callback) {
|
|
14438
|
+
if (!this._callbacks.has(type)) {
|
|
14439
|
+
this._callbacks.set(type, {
|
|
14440
|
+
callbacks: /* @__PURE__ */ new Set(),
|
|
14441
|
+
pending: null,
|
|
14442
|
+
queue: new DispatchQueue()
|
|
14443
|
+
});
|
|
14377
14444
|
}
|
|
14445
|
+
const entry = this._callbacks.get(type);
|
|
14446
|
+
entry.callbacks.add(callback);
|
|
14378
14447
|
}
|
|
14379
|
-
|
|
14380
|
-
|
|
14448
|
+
/**
|
|
14449
|
+
* Remove an event listener callback for the provided event type.
|
|
14450
|
+
* @param {string} type The event type.
|
|
14451
|
+
* @param {(value: *) => void | Promise} callback The event handler
|
|
14452
|
+
* callback function to remove.
|
|
14453
|
+
*/
|
|
14454
|
+
removeEventListener(type, callback) {
|
|
14455
|
+
const entry = this._callbacks.get(type);
|
|
14456
|
+
if (entry) {
|
|
14457
|
+
entry.callbacks.delete(callback);
|
|
14458
|
+
}
|
|
14381
14459
|
}
|
|
14382
|
-
|
|
14383
|
-
|
|
14460
|
+
/**
|
|
14461
|
+
* Lifecycle method that returns the event value to emit.
|
|
14462
|
+
* This default implementation simply returns the input value as-is.
|
|
14463
|
+
* Subclasses may override this method to implement custom transformations
|
|
14464
|
+
* prior to emitting an event value to all listeners.
|
|
14465
|
+
* @param {string} type The event type.
|
|
14466
|
+
* @param {*} value The event value.
|
|
14467
|
+
* @returns The (possibly transformed) event value to emit.
|
|
14468
|
+
*/
|
|
14469
|
+
willEmit(type, value) {
|
|
14470
|
+
return value;
|
|
14384
14471
|
}
|
|
14385
|
-
|
|
14386
|
-
|
|
14472
|
+
/**
|
|
14473
|
+
* Lifecycle method that returns a filter function for updating the
|
|
14474
|
+
* queue of unemitted event values prior to enqueueing a new value.
|
|
14475
|
+
* This default implementation simply returns null, indicating that
|
|
14476
|
+
* any other unemitted event values should be dropped (that is, all
|
|
14477
|
+
* queued events are filtered).
|
|
14478
|
+
* @param {string} type The event type.
|
|
14479
|
+
* @param {*} value The new event value that will be enqueued.
|
|
14480
|
+
* @returns {(value: *) => boolean|null} A dispatch queue filter
|
|
14481
|
+
* function, or null if all unemitted event values should be filtered.
|
|
14482
|
+
*/
|
|
14483
|
+
emitQueueFilter(type, value) {
|
|
14484
|
+
return null;
|
|
14387
14485
|
}
|
|
14388
|
-
|
|
14389
|
-
|
|
14486
|
+
/**
|
|
14487
|
+
* Cancel all unemitted event values for the given event type.
|
|
14488
|
+
* @param {string} type The event type.
|
|
14489
|
+
*/
|
|
14490
|
+
cancel(type) {
|
|
14491
|
+
const entry = this._callbacks.get(type);
|
|
14492
|
+
entry?.queue.clear();
|
|
14390
14493
|
}
|
|
14391
|
-
|
|
14392
|
-
|
|
14393
|
-
|
|
14394
|
-
|
|
14395
|
-
|
|
14396
|
-
|
|
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;
|
|
14397
14503
|
}
|
|
14398
|
-
|
|
14399
|
-
|
|
14400
|
-
|
|
14401
|
-
|
|
14402
|
-
|
|
14504
|
+
/**
|
|
14505
|
+
* Emit an event value to listeners for the given event type.
|
|
14506
|
+
* If a previous emit has not yet resolved, the event value
|
|
14507
|
+
* will be queued to be emitted later.
|
|
14508
|
+
* The actual event value given to listeners will be the result
|
|
14509
|
+
* of passing the input value through the emitValue() method.
|
|
14510
|
+
* @param {string} type The event type.
|
|
14511
|
+
* @param {*} value The event value.
|
|
14512
|
+
*/
|
|
14513
|
+
emit(type, value) {
|
|
14514
|
+
const entry = this._callbacks.get(type) || {};
|
|
14515
|
+
if (entry.pending) {
|
|
14516
|
+
entry.queue.enqueue(value, this.emitQueueFilter(type, value));
|
|
14403
14517
|
} else {
|
|
14404
|
-
this.
|
|
14518
|
+
const event = this.willEmit(type, value);
|
|
14519
|
+
const { callbacks, queue } = entry;
|
|
14520
|
+
if (callbacks?.size) {
|
|
14521
|
+
const callbackValues = Array.from(callbacks, (cb) => cb(event));
|
|
14522
|
+
entry.pending = Promise.allSettled(callbackValues).then(() => {
|
|
14523
|
+
entry.pending = null;
|
|
14524
|
+
if (!queue.isEmpty()) {
|
|
14525
|
+
this.emit(type, queue.dequeue());
|
|
14526
|
+
}
|
|
14527
|
+
});
|
|
14528
|
+
}
|
|
14405
14529
|
}
|
|
14406
|
-
return result;
|
|
14407
14530
|
}
|
|
14408
|
-
|
|
14409
|
-
|
|
14410
|
-
|
|
14531
|
+
};
|
|
14532
|
+
var DispatchQueue = class {
|
|
14533
|
+
/**
|
|
14534
|
+
* Create a new dispatch queue instance.
|
|
14535
|
+
*/
|
|
14536
|
+
constructor() {
|
|
14537
|
+
this.clear();
|
|
14411
14538
|
}
|
|
14539
|
+
/**
|
|
14540
|
+
* Clear the queue state of all event values.
|
|
14541
|
+
*/
|
|
14412
14542
|
clear() {
|
|
14413
|
-
this.
|
|
14414
|
-
result.reject("Cleared");
|
|
14415
|
-
return true;
|
|
14416
|
-
});
|
|
14543
|
+
this.next = null;
|
|
14417
14544
|
}
|
|
14418
|
-
|
|
14419
|
-
|
|
14420
|
-
|
|
14421
|
-
|
|
14422
|
-
|
|
14423
|
-
|
|
14424
|
-
|
|
14425
|
-
|
|
14426
|
-
|
|
14427
|
-
|
|
14428
|
-
|
|
14429
|
-
|
|
14430
|
-
|
|
14431
|
-
|
|
14432
|
-
|
|
14545
|
+
/**
|
|
14546
|
+
* Indicate if the queue is empty.
|
|
14547
|
+
* @returns {boolean} True if queue is empty, false otherwise.
|
|
14548
|
+
*/
|
|
14549
|
+
isEmpty() {
|
|
14550
|
+
return !this.next;
|
|
14551
|
+
}
|
|
14552
|
+
/**
|
|
14553
|
+
* Add a new value to the queue, and optionally filter the
|
|
14554
|
+
* current queue content in response.
|
|
14555
|
+
* @param {*} value The value to add.
|
|
14556
|
+
* @param {(value: *) => boolean} [filter] An optional filter
|
|
14557
|
+
* function to apply to existing queue content. If unspecified
|
|
14558
|
+
* or falsy, all previously queued values are removed. Otherwise,
|
|
14559
|
+
* the provided function is applied to all queue entries. The
|
|
14560
|
+
* entry is retained if the filter function returns a truthy value,
|
|
14561
|
+
* otherwise the entry is removed.
|
|
14562
|
+
*/
|
|
14563
|
+
enqueue(value, filter) {
|
|
14564
|
+
const tail = { value };
|
|
14565
|
+
if (filter && this.next) {
|
|
14566
|
+
let curr = this;
|
|
14567
|
+
while (curr.next) {
|
|
14568
|
+
if (filter(curr.next.value)) {
|
|
14569
|
+
curr = curr.next;
|
|
14570
|
+
} else {
|
|
14571
|
+
curr.next = curr.next.next;
|
|
14572
|
+
}
|
|
14433
14573
|
}
|
|
14434
|
-
|
|
14435
|
-
|
|
14436
|
-
|
|
14574
|
+
curr.next = tail;
|
|
14575
|
+
} else {
|
|
14576
|
+
this.next = tail;
|
|
14577
|
+
}
|
|
14578
|
+
}
|
|
14579
|
+
/**
|
|
14580
|
+
* Remove and return the next queued event value.
|
|
14581
|
+
* @returns {*} The next event value in the queue.
|
|
14582
|
+
*/
|
|
14583
|
+
dequeue() {
|
|
14584
|
+
const { next } = this;
|
|
14585
|
+
this.next = next?.next;
|
|
14586
|
+
return next?.value;
|
|
14437
14587
|
}
|
|
14438
14588
|
};
|
|
14439
14589
|
|
|
14440
|
-
// ../core/src/util/
|
|
14441
|
-
function
|
|
14442
|
-
|
|
14443
|
-
|
|
14444
|
-
|
|
14445
|
-
|
|
14446
|
-
|
|
14447
|
-
|
|
14448
|
-
case "UBIGINT":
|
|
14449
|
-
case "UINTEGER":
|
|
14450
|
-
case "USMALLINT":
|
|
14451
|
-
case "UTINYINT":
|
|
14452
|
-
case "DOUBLE":
|
|
14453
|
-
case "FLOAT":
|
|
14454
|
-
case "REAL":
|
|
14455
|
-
return "number";
|
|
14456
|
-
case "DATE":
|
|
14457
|
-
case "TIMESTAMP":
|
|
14458
|
-
case "TIMESTAMPTZ":
|
|
14459
|
-
case "TIMESTAMP WITH TIME ZONE":
|
|
14460
|
-
case "TIME":
|
|
14461
|
-
case "TIMESTAMP_NS":
|
|
14462
|
-
return "date";
|
|
14463
|
-
case "BOOLEAN":
|
|
14464
|
-
return "boolean";
|
|
14465
|
-
case "VARCHAR":
|
|
14466
|
-
case "UUID":
|
|
14467
|
-
case "JSON":
|
|
14468
|
-
return "string";
|
|
14469
|
-
case "ARRAY":
|
|
14470
|
-
case "LIST":
|
|
14471
|
-
return "array";
|
|
14472
|
-
case "BLOB":
|
|
14473
|
-
case "STRUCT":
|
|
14474
|
-
case "MAP":
|
|
14475
|
-
case "GEOMETRY":
|
|
14476
|
-
return "object";
|
|
14477
|
-
default:
|
|
14478
|
-
if (type.startsWith("DECIMAL")) {
|
|
14479
|
-
return "number";
|
|
14480
|
-
} else if (type.startsWith("STRUCT") || type.startsWith("MAP")) {
|
|
14481
|
-
return "object";
|
|
14482
|
-
} else if (type.endsWith("]")) {
|
|
14483
|
-
return "array";
|
|
14484
|
-
}
|
|
14485
|
-
throw new Error(`Unsupported type: ${type}`);
|
|
14590
|
+
// ../core/src/util/distinct.js
|
|
14591
|
+
function distinct(a, b) {
|
|
14592
|
+
return a === b ? false : a instanceof Date && b instanceof Date ? +a !== +b : Array.isArray(a) && Array.isArray(b) ? distinctArray(a, b) : true;
|
|
14593
|
+
}
|
|
14594
|
+
function distinctArray(a, b) {
|
|
14595
|
+
if (a.length !== b.length) return true;
|
|
14596
|
+
for (let i = 0; i < a.length; ++i) {
|
|
14597
|
+
if (a[i] !== b[i]) return true;
|
|
14486
14598
|
}
|
|
14599
|
+
return false;
|
|
14487
14600
|
}
|
|
14488
14601
|
|
|
14489
|
-
// ../core/src/
|
|
14490
|
-
function
|
|
14491
|
-
|
|
14492
|
-
|
|
14602
|
+
// ../core/src/Param.js
|
|
14603
|
+
function isParam(x2) {
|
|
14604
|
+
return x2 instanceof Param;
|
|
14605
|
+
}
|
|
14606
|
+
var Param = class _Param extends AsyncDispatch {
|
|
14607
|
+
/**
|
|
14608
|
+
* Create a new Param instance.
|
|
14609
|
+
* @param {*} value The initial value of the Param.
|
|
14610
|
+
*/
|
|
14611
|
+
constructor(value) {
|
|
14612
|
+
super();
|
|
14613
|
+
this._value = value;
|
|
14493
14614
|
}
|
|
14494
|
-
|
|
14495
|
-
|
|
14615
|
+
/**
|
|
14616
|
+
* Create a new Param instance with the given initial value.
|
|
14617
|
+
* @param {*} value The initial value of the Param.
|
|
14618
|
+
* @returns {Param} The new Param instance.
|
|
14619
|
+
*/
|
|
14620
|
+
static value(value) {
|
|
14621
|
+
return new _Param(value);
|
|
14496
14622
|
}
|
|
14497
|
-
|
|
14498
|
-
|
|
14499
|
-
|
|
14623
|
+
/**
|
|
14624
|
+
* Create a new Param instance over an array of initial values,
|
|
14625
|
+
* which may contain nested Params.
|
|
14626
|
+
* @param {*} values The initial values of the Param.
|
|
14627
|
+
* @returns {Param} The new Param instance.
|
|
14628
|
+
*/
|
|
14629
|
+
static array(values) {
|
|
14630
|
+
if (values.some((v) => isParam(v))) {
|
|
14631
|
+
const p = new _Param();
|
|
14632
|
+
const update2 = () => {
|
|
14633
|
+
p.update(values.map((v) => isParam(v) ? v.value : v));
|
|
14634
|
+
};
|
|
14635
|
+
update2();
|
|
14636
|
+
values.forEach((v) => isParam(v) ? v.addEventListener("value", update2) : 0);
|
|
14637
|
+
return p;
|
|
14638
|
+
}
|
|
14639
|
+
return new _Param(values);
|
|
14500
14640
|
}
|
|
14501
|
-
|
|
14502
|
-
|
|
14503
|
-
|
|
14504
|
-
|
|
14505
|
-
|
|
14506
|
-
|
|
14507
|
-
|
|
14508
|
-
|
|
14509
|
-
|
|
14510
|
-
|
|
14511
|
-
|
|
14512
|
-
|
|
14641
|
+
/**
|
|
14642
|
+
* The current value of the Param.
|
|
14643
|
+
*/
|
|
14644
|
+
get value() {
|
|
14645
|
+
return this._value;
|
|
14646
|
+
}
|
|
14647
|
+
/**
|
|
14648
|
+
* Update the Param value
|
|
14649
|
+
* @param {*} value The new value of the Param.
|
|
14650
|
+
* @param {object} [options] The update options.
|
|
14651
|
+
* @param {boolean} [options.force] A boolean flag indicating if the Param
|
|
14652
|
+
* should emit a 'value' event even if the internal value is unchanged.
|
|
14653
|
+
* @returns {this} This Param instance.
|
|
14654
|
+
*/
|
|
14655
|
+
update(value, { force } = {}) {
|
|
14656
|
+
const shouldEmit = distinct(this._value, value) || force;
|
|
14657
|
+
if (shouldEmit) {
|
|
14658
|
+
this.emit("value", value);
|
|
14659
|
+
} else {
|
|
14660
|
+
this.cancel("value");
|
|
14513
14661
|
}
|
|
14514
|
-
|
|
14515
|
-
}
|
|
14516
|
-
|
|
14517
|
-
|
|
14662
|
+
return this;
|
|
14663
|
+
}
|
|
14664
|
+
/**
|
|
14665
|
+
* Upon value-typed updates, sets the current value to the input value
|
|
14666
|
+
* immediately prior to the event value being emitted to listeners.
|
|
14667
|
+
* @param {string} type The event type.
|
|
14668
|
+
* @param {*} value The input event value.
|
|
14669
|
+
* @returns {*} The input event value.
|
|
14670
|
+
*/
|
|
14671
|
+
willEmit(type, value) {
|
|
14672
|
+
if (type === "value") {
|
|
14673
|
+
this._value = value;
|
|
14518
14674
|
}
|
|
14675
|
+
return value;
|
|
14519
14676
|
}
|
|
14520
|
-
return x2 * scale;
|
|
14521
|
-
}
|
|
14522
|
-
|
|
14523
|
-
// ../core/src/util/field-info.js
|
|
14524
|
-
var Count = "count";
|
|
14525
|
-
var Nulls = "nulls";
|
|
14526
|
-
var Max = "max";
|
|
14527
|
-
var Min = "min";
|
|
14528
|
-
var Distinct = "distinct";
|
|
14529
|
-
var statMap = {
|
|
14530
|
-
[Count]: count,
|
|
14531
|
-
[Distinct]: (column2) => count(column2).distinct(),
|
|
14532
|
-
[Max]: max,
|
|
14533
|
-
[Min]: min,
|
|
14534
|
-
[Nulls]: (column2) => count().where(isNull(column2))
|
|
14535
14677
|
};
|
|
14536
|
-
|
|
14537
|
-
|
|
14678
|
+
|
|
14679
|
+
// ../core/src/Selection.js
|
|
14680
|
+
function isSelection(x2) {
|
|
14681
|
+
return x2 instanceof Selection;
|
|
14538
14682
|
}
|
|
14539
|
-
|
|
14540
|
-
|
|
14541
|
-
|
|
14542
|
-
|
|
14543
|
-
|
|
14683
|
+
var Selection = class _Selection extends Param {
|
|
14684
|
+
/**
|
|
14685
|
+
* Create a new Selection instance with an
|
|
14686
|
+
* intersect (conjunction) resolution strategy.
|
|
14687
|
+
* @param {object} [options] The selection options.
|
|
14688
|
+
* @param {boolean} [options.cross=false] Boolean flag indicating
|
|
14689
|
+
* cross-filtered resolution. If true, selection clauses will not
|
|
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.
|
|
14694
|
+
* @returns {Selection} The new Selection instance.
|
|
14695
|
+
*/
|
|
14696
|
+
static intersect({ cross = false, empty = false } = {}) {
|
|
14697
|
+
return new _Selection(new SelectionResolver({ cross, empty }));
|
|
14544
14698
|
}
|
|
14545
|
-
|
|
14546
|
-
|
|
14547
|
-
|
|
14548
|
-
|
|
14549
|
-
|
|
14550
|
-
|
|
14551
|
-
|
|
14552
|
-
|
|
14553
|
-
|
|
14554
|
-
|
|
14555
|
-
|
|
14556
|
-
|
|
14557
|
-
|
|
14558
|
-
|
|
14559
|
-
{ persist: true }
|
|
14560
|
-
);
|
|
14561
|
-
for (let i = 0; i < result.numCols; ++i) {
|
|
14562
|
-
const { name } = result.schema.fields[i];
|
|
14563
|
-
const child = result.getChildAt(i);
|
|
14564
|
-
const convert = convertArrowValue(child.type);
|
|
14565
|
-
info[name] = convert(child.get(0));
|
|
14699
|
+
/**
|
|
14700
|
+
* Create a new Selection instance with a
|
|
14701
|
+
* union (disjunction) resolution strategy.
|
|
14702
|
+
* @param {object} [options] The selection options.
|
|
14703
|
+
* @param {boolean} [options.cross=false] Boolean flag indicating
|
|
14704
|
+
* cross-filtered resolution. If true, selection clauses will not
|
|
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.
|
|
14709
|
+
* @returns {Selection} The new Selection instance.
|
|
14710
|
+
*/
|
|
14711
|
+
static union({ cross = false, empty = false } = {}) {
|
|
14712
|
+
return new _Selection(new SelectionResolver({ cross, empty, union: true }));
|
|
14566
14713
|
}
|
|
14567
|
-
|
|
14568
|
-
|
|
14569
|
-
|
|
14570
|
-
|
|
14571
|
-
|
|
14572
|
-
|
|
14573
|
-
|
|
14574
|
-
|
|
14575
|
-
|
|
14576
|
-
|
|
14577
|
-
|
|
14578
|
-
|
|
14579
|
-
|
|
14580
|
-
|
|
14581
|
-
|
|
14582
|
-
|
|
14583
|
-
|
|
14584
|
-
|
|
14585
|
-
|
|
14586
|
-
|
|
14587
|
-
|
|
14588
|
-
|
|
14589
|
-
|
|
14590
|
-
|
|
14591
|
-
|
|
14592
|
-
}
|
|
14593
|
-
}
|
|
14594
|
-
|
|
14595
|
-
|
|
14596
|
-
|
|
14597
|
-
|
|
14598
|
-
|
|
14599
|
-
|
|
14600
|
-
|
|
14601
|
-
|
|
14602
|
-
|
|
14714
|
+
/**
|
|
14715
|
+
* Create a new Selection instance with a singular resolution strategy
|
|
14716
|
+
* that keeps only the most recent selection clause.
|
|
14717
|
+
* @param {object} [options] The selection options.
|
|
14718
|
+
* @param {boolean} [options.cross=false] Boolean flag indicating
|
|
14719
|
+
* cross-filtered resolution. If true, selection clauses will not
|
|
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.
|
|
14724
|
+
* @returns {Selection} The new Selection instance.
|
|
14725
|
+
*/
|
|
14726
|
+
static single({ cross = false, empty = false } = {}) {
|
|
14727
|
+
return new _Selection(new SelectionResolver({ cross, empty, single: true }));
|
|
14728
|
+
}
|
|
14729
|
+
/**
|
|
14730
|
+
* Create a new Selection instance with a
|
|
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.
|
|
14736
|
+
* @returns {Selection} The new Selection instance.
|
|
14737
|
+
*/
|
|
14738
|
+
static crossfilter({ empty = false } = {}) {
|
|
14739
|
+
return new _Selection(new SelectionResolver({ cross: true, empty }));
|
|
14740
|
+
}
|
|
14741
|
+
/**
|
|
14742
|
+
* Create a new Selection instance.
|
|
14743
|
+
* @param {SelectionResolver} resolver The selection resolution
|
|
14744
|
+
* strategy to apply.
|
|
14745
|
+
*/
|
|
14746
|
+
constructor(resolver = new SelectionResolver()) {
|
|
14747
|
+
super([]);
|
|
14748
|
+
this._resolved = this._value;
|
|
14749
|
+
this._resolver = resolver;
|
|
14750
|
+
}
|
|
14751
|
+
/**
|
|
14752
|
+
* Create a cloned copy of this Selection instance.
|
|
14753
|
+
* @returns {Selection} A clone of this selection.
|
|
14754
|
+
*/
|
|
14755
|
+
clone() {
|
|
14756
|
+
const s = new _Selection(this._resolver);
|
|
14757
|
+
s._value = s._resolved = this._value;
|
|
14758
|
+
return s;
|
|
14759
|
+
}
|
|
14760
|
+
/**
|
|
14761
|
+
* Create a clone of this Selection with clauses corresponding
|
|
14762
|
+
* to the provided source removed.
|
|
14763
|
+
* @param {*} source The clause source to remove.
|
|
14764
|
+
* @returns {Selection} A cloned and updated Selection.
|
|
14765
|
+
*/
|
|
14766
|
+
remove(source) {
|
|
14767
|
+
const s = this.clone();
|
|
14768
|
+
s._value = s._resolved = s._resolver.resolve(this._resolved, { source });
|
|
14769
|
+
s._value.active = { source };
|
|
14770
|
+
return s;
|
|
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;
|
|
14603
14783
|
}
|
|
14604
|
-
|
|
14605
|
-
|
|
14606
|
-
|
|
14607
|
-
|
|
14608
|
-
|
|
14609
|
-
logger = console,
|
|
14610
|
-
manager = new QueryManager()
|
|
14611
|
-
} = options;
|
|
14612
|
-
this.manager = manager;
|
|
14613
|
-
this.logger(logger);
|
|
14614
|
-
this.configure(options);
|
|
14615
|
-
this.databaseConnector(db);
|
|
14616
|
-
this.clear();
|
|
14784
|
+
/**
|
|
14785
|
+
* The current array of selection clauses.
|
|
14786
|
+
*/
|
|
14787
|
+
get clauses() {
|
|
14788
|
+
return super.value;
|
|
14617
14789
|
}
|
|
14618
|
-
|
|
14619
|
-
|
|
14620
|
-
|
|
14621
|
-
|
|
14622
|
-
|
|
14623
|
-
return this._logger;
|
|
14790
|
+
/**
|
|
14791
|
+
* The current active (most recently updated) selection clause.
|
|
14792
|
+
*/
|
|
14793
|
+
get active() {
|
|
14794
|
+
return this.clauses.active;
|
|
14624
14795
|
}
|
|
14625
14796
|
/**
|
|
14626
|
-
*
|
|
14627
|
-
*
|
|
14628
|
-
* @param {boolean} [options.cache=true] Boolean flag to enable/disable query caching.
|
|
14629
|
-
* @param {boolean} [options.consolidate=true] Boolean flag to enable/disable query consolidation.
|
|
14630
|
-
* @param {boolean|object} [options.indexes=true] Boolean flag to enable/disable
|
|
14631
|
-
* automatic data cube indexes or an index options object.
|
|
14797
|
+
* The value corresponding to the current active selection clause.
|
|
14798
|
+
* This method ensures compatibility where a normal Param is expected.
|
|
14632
14799
|
*/
|
|
14633
|
-
|
|
14634
|
-
this.
|
|
14635
|
-
this.manager.consolidate(consolidate2);
|
|
14636
|
-
this.indexes = indexes;
|
|
14800
|
+
get value() {
|
|
14801
|
+
return this.active?.value;
|
|
14637
14802
|
}
|
|
14638
|
-
|
|
14639
|
-
|
|
14640
|
-
|
|
14641
|
-
|
|
14642
|
-
|
|
14643
|
-
|
|
14644
|
-
|
|
14645
|
-
}
|
|
14646
|
-
if (cache) this.manager.cache().clear();
|
|
14803
|
+
/**
|
|
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.
|
|
14807
|
+
*/
|
|
14808
|
+
valueFor(source) {
|
|
14809
|
+
return this.clauses.find((c) => c.source === source)?.value;
|
|
14647
14810
|
}
|
|
14648
|
-
|
|
14649
|
-
|
|
14811
|
+
/**
|
|
14812
|
+
* Emit an activate event with the given selection clause.
|
|
14813
|
+
* @param {*} clause The clause repesenting the potential activation.
|
|
14814
|
+
*/
|
|
14815
|
+
activate(clause) {
|
|
14816
|
+
this.emit("activate", clause);
|
|
14650
14817
|
}
|
|
14651
|
-
|
|
14652
|
-
|
|
14653
|
-
|
|
14818
|
+
/**
|
|
14819
|
+
* Update the selection with a new selection clause.
|
|
14820
|
+
* @param {*} clause The selection clause to add.
|
|
14821
|
+
* @returns {this} This Selection instance.
|
|
14822
|
+
*/
|
|
14823
|
+
update(clause) {
|
|
14824
|
+
this._resolved = this._resolver.resolve(this._resolved, clause, true);
|
|
14825
|
+
this._resolved.active = clause;
|
|
14826
|
+
return super.update(this._resolved);
|
|
14654
14827
|
}
|
|
14655
|
-
|
|
14656
|
-
|
|
14657
|
-
|
|
14828
|
+
/**
|
|
14829
|
+
* Upon value-typed updates, sets the current clause list to the
|
|
14830
|
+
* input value and returns the active clause value.
|
|
14831
|
+
* @param {string} type The event type.
|
|
14832
|
+
* @param {*} value The input event value.
|
|
14833
|
+
* @returns {*} For value-typed events, returns the active clause
|
|
14834
|
+
* values. Otherwise returns the input event value as-is.
|
|
14835
|
+
*/
|
|
14836
|
+
willEmit(type, value) {
|
|
14837
|
+
if (type === "value") {
|
|
14838
|
+
this._value = value;
|
|
14839
|
+
return this.value;
|
|
14840
|
+
}
|
|
14841
|
+
return value;
|
|
14658
14842
|
}
|
|
14659
|
-
|
|
14660
|
-
|
|
14661
|
-
|
|
14662
|
-
|
|
14663
|
-
|
|
14664
|
-
|
|
14665
|
-
|
|
14843
|
+
/**
|
|
14844
|
+
* Upon value-typed updates, returns a dispatch queue filter function.
|
|
14845
|
+
* The return value depends on the selection resolution strategy.
|
|
14846
|
+
* @param {string} type The event type.
|
|
14847
|
+
* @param {*} value The new event value that will be enqueued.
|
|
14848
|
+
* @returns {(value: *) => boolean|null} For value-typed events,
|
|
14849
|
+
* returns a dispatch queue filter function. Otherwise returns null.
|
|
14850
|
+
*/
|
|
14851
|
+
emitQueueFilter(type, value) {
|
|
14852
|
+
return type === "value" ? this._resolver.queueFilter(value) : null;
|
|
14666
14853
|
}
|
|
14667
|
-
|
|
14668
|
-
|
|
14854
|
+
/**
|
|
14855
|
+
* Indicates if a selection clause should not be applied to a given client.
|
|
14856
|
+
* The return value depends on the selection resolution strategy.
|
|
14857
|
+
* @param {*} client The selection clause.
|
|
14858
|
+
* @param {*} clause The client to test.
|
|
14859
|
+
* @returns True if the client should be skipped, false otherwise.
|
|
14860
|
+
*/
|
|
14861
|
+
skip(client, clause) {
|
|
14862
|
+
return this._resolver.skip(client, clause);
|
|
14669
14863
|
}
|
|
14670
|
-
|
|
14671
|
-
|
|
14672
|
-
|
|
14864
|
+
/**
|
|
14865
|
+
* Return a selection query predicate for the given client.
|
|
14866
|
+
* @param {*} client The client whose data may be filtered.
|
|
14867
|
+
* @param {boolean} [noSkip=false] Disable skipping of active
|
|
14868
|
+
* cross-filtered sources. If set true, the source of the active
|
|
14869
|
+
* clause in a cross-filtered selection will not be skipped.
|
|
14870
|
+
* @returns {*} The query predicate for filtering client data,
|
|
14871
|
+
* based on the current state of this selection.
|
|
14872
|
+
*/
|
|
14873
|
+
predicate(client, noSkip = false) {
|
|
14874
|
+
const { clauses } = this;
|
|
14875
|
+
const active = noSkip ? null : clauses.active;
|
|
14876
|
+
return this._resolver.predicate(clauses, active, client);
|
|
14673
14877
|
}
|
|
14674
|
-
|
|
14675
|
-
|
|
14676
|
-
|
|
14878
|
+
};
|
|
14879
|
+
var SelectionResolver = class {
|
|
14880
|
+
/**
|
|
14881
|
+
* Create a new selection resolved instance.
|
|
14882
|
+
* @param {object} [options] The resolution strategy options.
|
|
14883
|
+
* @param {boolean} [options.union=false] Boolean flag to indicate a union strategy.
|
|
14884
|
+
* If false, an intersection strategy is used.
|
|
14885
|
+
* @param {boolean} [options.cross=false] Boolean flag to indicate cross-filtering.
|
|
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.
|
|
14890
|
+
*/
|
|
14891
|
+
constructor({ union, cross, single, empty } = {}) {
|
|
14892
|
+
this.union = !!union;
|
|
14893
|
+
this.cross = !!cross;
|
|
14894
|
+
this.single = !!single;
|
|
14895
|
+
this.empty = !!empty;
|
|
14677
14896
|
}
|
|
14678
|
-
|
|
14679
|
-
|
|
14680
|
-
|
|
14681
|
-
|
|
14682
|
-
|
|
14683
|
-
|
|
14684
|
-
|
|
14685
|
-
|
|
14686
|
-
|
|
14687
|
-
|
|
14897
|
+
/**
|
|
14898
|
+
* Resolve a list of selection clauses according to the resolution strategy.
|
|
14899
|
+
* @param {*[]} clauseList An array of selection clauses.
|
|
14900
|
+
* @param {*} clause A new selection clause to add.
|
|
14901
|
+
* @returns {*[]} An updated array of selection clauses.
|
|
14902
|
+
*/
|
|
14903
|
+
resolve(clauseList, clause, reset = false) {
|
|
14904
|
+
const { source, predicate } = clause;
|
|
14905
|
+
const filtered = clauseList.filter((c) => source !== c.source);
|
|
14906
|
+
const clauses = this.single ? [] : filtered;
|
|
14907
|
+
if (this.single && reset) filtered.forEach((c) => c.source?.reset?.());
|
|
14908
|
+
if (predicate) clauses.push(clause);
|
|
14909
|
+
return clauses;
|
|
14688
14910
|
}
|
|
14689
|
-
|
|
14690
|
-
|
|
14691
|
-
|
|
14911
|
+
/**
|
|
14912
|
+
* Indicates if a selection clause should not be applied to a given client.
|
|
14913
|
+
* The return value depends on the resolution strategy.
|
|
14914
|
+
* @param {*} client The selection clause.
|
|
14915
|
+
* @param {*} clause The client to test.
|
|
14916
|
+
* @returns True if the client should be skipped, false otherwise.
|
|
14917
|
+
*/
|
|
14918
|
+
skip(client, clause) {
|
|
14919
|
+
return this.cross && clause?.clients?.has(client);
|
|
14692
14920
|
}
|
|
14693
14921
|
/**
|
|
14694
|
-
*
|
|
14695
|
-
* @param {
|
|
14922
|
+
* Return a selection query predicate for the given client.
|
|
14923
|
+
* @param {*[]} clauseList An array of selection clauses.
|
|
14924
|
+
* @param {*} active The current active selection clause.
|
|
14925
|
+
* @param {*} client The client whose data may be filtered.
|
|
14926
|
+
* @returns {*} The query predicate for filtering client data,
|
|
14927
|
+
* based on the current state of this selection.
|
|
14696
14928
|
*/
|
|
14697
|
-
|
|
14698
|
-
const {
|
|
14699
|
-
if (
|
|
14700
|
-
|
|
14701
|
-
}
|
|
14702
|
-
clients.add(client);
|
|
14703
|
-
client.coordinator = this;
|
|
14704
|
-
const fields = client.fields();
|
|
14705
|
-
if (fields?.length) {
|
|
14706
|
-
client.fieldInfo(await queryFieldInfo(this, fields));
|
|
14707
|
-
}
|
|
14708
|
-
const filter = client.filterBy;
|
|
14709
|
-
if (filter) {
|
|
14710
|
-
if (filterGroups.has(filter)) {
|
|
14711
|
-
filterGroups.get(filter).add(client);
|
|
14712
|
-
} else {
|
|
14713
|
-
const group = new FilterGroup(this, filter, indexes);
|
|
14714
|
-
filterGroups.set(filter, group.add(client));
|
|
14715
|
-
}
|
|
14929
|
+
predicate(clauseList, active, client) {
|
|
14930
|
+
const { empty, union } = this;
|
|
14931
|
+
if (empty && !clauseList.length) {
|
|
14932
|
+
return ["FALSE"];
|
|
14716
14933
|
}
|
|
14717
|
-
|
|
14934
|
+
if (this.skip(client, active)) return void 0;
|
|
14935
|
+
const predicates = clauseList.filter((clause) => !this.skip(client, clause)).map((clause) => clause.predicate);
|
|
14936
|
+
return union && predicates.length > 1 ? or(predicates) : predicates;
|
|
14718
14937
|
}
|
|
14719
14938
|
/**
|
|
14720
|
-
*
|
|
14721
|
-
*
|
|
14722
|
-
* @
|
|
14939
|
+
* Returns a filter function for queued selection updates.
|
|
14940
|
+
* @param {*} value The new event value that will be enqueued.
|
|
14941
|
+
* @returns {(value: *) => boolean|null} A dispatch queue filter
|
|
14942
|
+
* function, or null if all unemitted event values should be filtered.
|
|
14723
14943
|
*/
|
|
14724
|
-
|
|
14725
|
-
|
|
14726
|
-
|
|
14727
|
-
|
|
14728
|
-
|
|
14729
|
-
|
|
14944
|
+
queueFilter(value) {
|
|
14945
|
+
if (this.cross) {
|
|
14946
|
+
const source = value.active?.source;
|
|
14947
|
+
return (clauses) => clauses.active?.source !== source;
|
|
14948
|
+
}
|
|
14949
|
+
return null;
|
|
14730
14950
|
}
|
|
14731
14951
|
};
|
|
14732
14952
|
|
|
14733
14953
|
// ../core/src/SelectionClause.js
|
|
14734
|
-
function
|
|
14954
|
+
function clausePoint(field, value, {
|
|
14955
|
+
source,
|
|
14956
|
+
clients = source ? /* @__PURE__ */ new Set([source]) : void 0
|
|
14957
|
+
}) {
|
|
14735
14958
|
const predicate = value !== void 0 ? isNotDistinct(field, literal(value)) : null;
|
|
14736
14959
|
return {
|
|
14737
14960
|
meta: { type: "point" },
|
|
@@ -14741,19 +14964,39 @@ function point(field, value, { source, clients = void 0 }) {
|
|
|
14741
14964
|
predicate
|
|
14742
14965
|
};
|
|
14743
14966
|
}
|
|
14744
|
-
function
|
|
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, {
|
|
14745
14988
|
source,
|
|
14746
|
-
clients,
|
|
14989
|
+
clients = source ? /* @__PURE__ */ new Set([source]) : void 0,
|
|
14747
14990
|
bin,
|
|
14748
14991
|
scale,
|
|
14749
14992
|
pixelSize = 1
|
|
14750
14993
|
}) {
|
|
14751
14994
|
const predicate = value != null ? isBetween(field, value) : null;
|
|
14752
|
-
const meta = { type: "interval", scales: [scale], bin, pixelSize };
|
|
14995
|
+
const meta = { type: "interval", scales: scale && [scale], bin, pixelSize };
|
|
14753
14996
|
return { meta, source, clients, value, predicate };
|
|
14754
14997
|
}
|
|
14755
14998
|
var MATCH_METHODS = { contains, prefix, suffix, regexp: regexp_matches };
|
|
14756
|
-
function
|
|
14999
|
+
function clauseMatch(field, value, {
|
|
14757
15000
|
source,
|
|
14758
15001
|
clients = void 0,
|
|
14759
15002
|
method = "contains"
|
|
@@ -14764,6 +15007,39 @@ function match(field, value, {
|
|
|
14764
15007
|
return { meta, source, clients, value, predicate };
|
|
14765
15008
|
}
|
|
14766
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
|
+
|
|
14767
15043
|
// src/input.js
|
|
14768
15044
|
function input(InputClass, options) {
|
|
14769
15045
|
const input2 = new InputClass(options);
|
|
@@ -14873,7 +15149,7 @@ var Menu = class extends MosaicClient {
|
|
|
14873
15149
|
const { selection, field } = this;
|
|
14874
15150
|
if (isSelection(selection)) {
|
|
14875
15151
|
if (value === "") value = void 0;
|
|
14876
|
-
const clause =
|
|
15152
|
+
const clause = clausePoint(field, value, { source: this });
|
|
14877
15153
|
selection.update(clause);
|
|
14878
15154
|
} else if (isParam(selection)) {
|
|
14879
15155
|
selection.update(value);
|
|
@@ -14984,7 +15260,7 @@ var Search = class extends MosaicClient {
|
|
|
14984
15260
|
publish(value) {
|
|
14985
15261
|
const { selection, field, type } = this;
|
|
14986
15262
|
if (isSelection(selection)) {
|
|
14987
|
-
const clause =
|
|
15263
|
+
const clause = clauseMatch(field, value, { source: this, method: type });
|
|
14988
15264
|
selection.update(clause);
|
|
14989
15265
|
} else if (isParam(selection)) {
|
|
14990
15266
|
selection.update(value);
|
|
@@ -15140,14 +15416,14 @@ var Slider = class extends MosaicClient {
|
|
|
15140
15416
|
if (isSelection(selection)) {
|
|
15141
15417
|
if (selectionType === "interval") {
|
|
15142
15418
|
const domain = [this.min ?? 0, value];
|
|
15143
|
-
selection.update(
|
|
15419
|
+
selection.update(clauseInterval(field, domain, {
|
|
15144
15420
|
source: this,
|
|
15145
15421
|
bin: "ceil",
|
|
15146
15422
|
scale: { type: "identity", domain },
|
|
15147
15423
|
pixelSize: this.step
|
|
15148
15424
|
}));
|
|
15149
15425
|
} else {
|
|
15150
|
-
selection.update(
|
|
15426
|
+
selection.update(clausePoint(field, value, { source: this }));
|
|
15151
15427
|
}
|
|
15152
15428
|
} else if (isParam(this.selection)) {
|
|
15153
15429
|
selection.update(value);
|
|
@@ -15209,7 +15485,8 @@ var Table2 = class extends MosaicClient {
|
|
|
15209
15485
|
width,
|
|
15210
15486
|
maxWidth,
|
|
15211
15487
|
height = 500,
|
|
15212
|
-
rowBatch = 100
|
|
15488
|
+
rowBatch = 100,
|
|
15489
|
+
as
|
|
15213
15490
|
} = {}) {
|
|
15214
15491
|
super(filterBy);
|
|
15215
15492
|
this.id = `table-${++_id3}`;
|
|
@@ -15221,6 +15498,8 @@ var Table2 = class extends MosaicClient {
|
|
|
15221
15498
|
this.offset = 0;
|
|
15222
15499
|
this.limit = +rowBatch;
|
|
15223
15500
|
this.pending = false;
|
|
15501
|
+
this.selection = as;
|
|
15502
|
+
this.currentRow = -1;
|
|
15224
15503
|
this.sortHeader = null;
|
|
15225
15504
|
this.sortColumn = null;
|
|
15226
15505
|
this.sortDesc = false;
|
|
@@ -15249,9 +15528,31 @@ var Table2 = class extends MosaicClient {
|
|
|
15249
15528
|
this.tbl.appendChild(this.head);
|
|
15250
15529
|
this.body = document.createElement("tbody");
|
|
15251
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
|
+
}
|
|
15252
15544
|
this.style = document.createElement("style");
|
|
15253
15545
|
this.element.appendChild(this.style);
|
|
15254
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
|
+
}
|
|
15255
15556
|
requestData(offset = 0) {
|
|
15256
15557
|
this.offset = offset;
|
|
15257
15558
|
const query = this.query(this.filterBy?.predicate(this));
|
|
@@ -15289,27 +15590,32 @@ var Table2 = class extends MosaicClient {
|
|
|
15289
15590
|
queryResult(data) {
|
|
15290
15591
|
if (!this.pending) {
|
|
15291
15592
|
this.loaded = false;
|
|
15593
|
+
this.data = [];
|
|
15292
15594
|
this.body.replaceChildren();
|
|
15595
|
+
this.offset = 0;
|
|
15293
15596
|
}
|
|
15294
|
-
this.data
|
|
15597
|
+
this.data.push(toDataColumns(data));
|
|
15295
15598
|
return this;
|
|
15296
15599
|
}
|
|
15297
15600
|
update() {
|
|
15298
15601
|
const { body, formats, data, schema, limit } = this;
|
|
15299
15602
|
const nf = schema.length;
|
|
15300
|
-
|
|
15301
|
-
|
|
15302
|
-
|
|
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) {
|
|
15303
15608
|
const tr = document.createElement("tr");
|
|
15304
|
-
|
|
15305
|
-
|
|
15609
|
+
Object.assign(tr, { __row__: rowCount + i });
|
|
15610
|
+
for (let j = 0; j < nf; ++j) {
|
|
15611
|
+
const value = cols[j][i];
|
|
15306
15612
|
const td = document.createElement("td");
|
|
15307
|
-
td.innerText = value == null ? "" : formats[
|
|
15613
|
+
td.innerText = value == null ? "" : formats[j](value);
|
|
15308
15614
|
tr.appendChild(td);
|
|
15309
15615
|
}
|
|
15310
15616
|
body.appendChild(tr);
|
|
15311
15617
|
}
|
|
15312
|
-
if (
|
|
15618
|
+
if (numRows < limit) {
|
|
15313
15619
|
this.loaded = true;
|
|
15314
15620
|
}
|
|
15315
15621
|
this.pending = false;
|
|
@@ -15336,6 +15642,10 @@ var Table2 = class extends MosaicClient {
|
|
|
15336
15642
|
this.requestData();
|
|
15337
15643
|
}
|
|
15338
15644
|
};
|
|
15645
|
+
function resolveRow(element) {
|
|
15646
|
+
const p = element.parentElement;
|
|
15647
|
+
return Object.hasOwn(p, "__row__") ? +p.__row__ : -1;
|
|
15648
|
+
}
|
|
15339
15649
|
function formatof(base = {}, schema, locale) {
|
|
15340
15650
|
return schema.map(({ column: column2, type }) => {
|
|
15341
15651
|
if (column2 in base) {
|