squirreling 0.16.7 → 0.16.8
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "squirreling",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.8",
|
|
4
4
|
"description": "Squirreling Async SQL Engine",
|
|
5
5
|
"author": "Hyperparam",
|
|
6
6
|
"homepage": "https://hyperparam.app",
|
|
@@ -40,10 +40,10 @@
|
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@eslint/js": "10.0.1",
|
|
43
|
-
"@types/node": "26.6.
|
|
43
|
+
"@types/node": "26.6.3",
|
|
44
44
|
"@vitest/coverage-v8": "5.0.2",
|
|
45
45
|
"eslint": "10.11.0",
|
|
46
|
-
"eslint-plugin-jsdoc": "
|
|
46
|
+
"eslint-plugin-jsdoc": "65.0.0",
|
|
47
47
|
"globals": "17.12.0",
|
|
48
48
|
"typescript": "7.0.2",
|
|
49
49
|
"vitest": "5.0.2"
|
package/src/backend/batch.js
CHANGED
|
@@ -125,6 +125,7 @@ export function selectVector(vector, selection) {
|
|
|
125
125
|
throw new Error(`Cannot select ${selection.length} rows from vector length ${vector.length}`)
|
|
126
126
|
}
|
|
127
127
|
if (selection.type === 'all') return vector
|
|
128
|
+
if (vector.type === 'constant') return { ...vector, length: selectedRowCount(selection) }
|
|
128
129
|
if (vector.type === 'selected') {
|
|
129
130
|
const composed = composeSelections(vector.selection, selection)
|
|
130
131
|
return {
|
|
@@ -309,6 +309,9 @@ function tryColumnScanAggregate(plan, { tables, signal }) {
|
|
|
309
309
|
specs.push(spec)
|
|
310
310
|
}
|
|
311
311
|
|
|
312
|
+
// Prepared batches can count selected rows without decoding a physical column.
|
|
313
|
+
if (table.prepareScan && specs.every(spec => spec.funcName === 'COUNT' && spec.star)) return
|
|
314
|
+
|
|
312
315
|
const physicalColumns = new Set(specs.map(spec => spec.column))
|
|
313
316
|
const hasPushdown = where || limit !== undefined || offset !== undefined
|
|
314
317
|
if (hasPushdown) {
|
package/src/execute/batches.js
CHANGED
|
@@ -238,12 +238,16 @@ function projectedBatchColumn(batch, columnIndex) {
|
|
|
238
238
|
/**
|
|
239
239
|
* @param {ColumnVector} predicate
|
|
240
240
|
* @param {number} rowCount
|
|
241
|
-
* @returns {{ selection:
|
|
241
|
+
* @returns {{ selection: RowSelection, selectedCount: number }}
|
|
242
242
|
*/
|
|
243
243
|
function predicateSelection(predicate, rowCount) {
|
|
244
244
|
if (predicate.length !== rowCount) {
|
|
245
245
|
throw new Error(`Predicate returned ${predicate.length} rows, expected ${rowCount}`)
|
|
246
246
|
}
|
|
247
|
+
if (predicate.type === 'constant') {
|
|
248
|
+
const selectedCount = predicate.value ? rowCount : 0
|
|
249
|
+
return { selection: { type: 'range', start: 0, end: selectedCount, length: rowCount }, selectedCount }
|
|
250
|
+
}
|
|
247
251
|
const indices = new Uint32Array(rowCount)
|
|
248
252
|
let selectedCount = 0
|
|
249
253
|
for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
|
|
@@ -523,6 +523,25 @@ async function accumulateBatch({ batch, inputs, specs, groups, context, rowOffse
|
|
|
523
523
|
evaluateBatchInputs(inputs.args, batch, context, rowOffset),
|
|
524
524
|
])
|
|
525
525
|
const rowCount = selectedRowCount(batch.selection)
|
|
526
|
+
context.signal?.throwIfAborted()
|
|
527
|
+
if (rowCount > 0 && keys.every(vector => vector?.type === 'constant') &&
|
|
528
|
+
specs.every(spec => spec.star && spec.funcName === 'COUNT' && !spec.node.distinct && !spec.node.filter)) {
|
|
529
|
+
const keyValues = keys.map(vector => valueAt(/** @type {ColumnVector} */ vector, 0))
|
|
530
|
+
const key = keyValues.length === 0
|
|
531
|
+
? true
|
|
532
|
+
: keyValues.length === 1 ? keyify(keyValues[0]) : keyify(...keyValues)
|
|
533
|
+
let group = groups.get(key)
|
|
534
|
+
if (!group) {
|
|
535
|
+
group = {
|
|
536
|
+
firstRow: undefined,
|
|
537
|
+
keyValues,
|
|
538
|
+
accumulators: specs.map(spec => newAccumulator(spec.funcName, spec.node.distinct)),
|
|
539
|
+
}
|
|
540
|
+
groups.set(key, group)
|
|
541
|
+
}
|
|
542
|
+
for (const accumulator of group.accumulators) accumulator.count += rowCount
|
|
543
|
+
return
|
|
544
|
+
}
|
|
526
545
|
for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
|
|
527
546
|
if (rowIndex > 0 && rowIndex % CHUNK_SIZE === 0) {
|
|
528
547
|
await yieldToEventLoop()
|
package/src/expression/batch.js
CHANGED
|
@@ -626,6 +626,13 @@ function resolveIdentifier(identifier, columns) {
|
|
|
626
626
|
*/
|
|
627
627
|
function evaluateKernel(kernel, vectors, selection, signal, rowOffset = 0, rowOrdinals) {
|
|
628
628
|
const length = selectedRowCount(selection)
|
|
629
|
+
// Supported kernels are deterministic; streamRowIndex only labels errors.
|
|
630
|
+
// Empty selections must not evaluate expressions (including invalid casts).
|
|
631
|
+
if (length > 0 && vectors.every(vector => vector.type === 'constant')) {
|
|
632
|
+
signal?.throwIfAborted()
|
|
633
|
+
const ordinal = rowOrdinals ? Number(valueAt(rowOrdinals, 0)) : 0
|
|
634
|
+
return { type: 'constant', value: kernel(vectors, 0, rowOffset + ordinal), length }
|
|
635
|
+
}
|
|
629
636
|
if (signal && length > YIELD_INTERVAL) {
|
|
630
637
|
return evaluateKernelAsync(kernel, vectors, length, signal, rowOffset, rowOrdinals)
|
|
631
638
|
}
|