squirreling 0.15.0 → 0.15.1
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.15.
|
|
3
|
+
"version": "0.15.1",
|
|
4
4
|
"description": "Squirreling Async SQL Engine",
|
|
5
5
|
"author": "Hyperparam",
|
|
6
6
|
"homepage": "https://hyperparam.app",
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"test": "vitest run"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@types/node": "26.
|
|
42
|
+
"@types/node": "26.2.0",
|
|
43
43
|
"@vitest/coverage-v8": "4.1.10",
|
|
44
44
|
"eslint": "9.39.4",
|
|
45
|
-
"eslint-plugin-jsdoc": "
|
|
45
|
+
"eslint-plugin-jsdoc": "64.1.0",
|
|
46
46
|
"typescript": "7.0.2",
|
|
47
47
|
"vitest": "4.1.10"
|
|
48
48
|
}
|
|
@@ -166,6 +166,9 @@ export function planStreamingAggregates({ columns, having, orderBy, groupBy }, c
|
|
|
166
166
|
case 'function': {
|
|
167
167
|
const funcName = node.funcName.toUpperCase()
|
|
168
168
|
if (!isAggregateFunc(funcName)) {
|
|
169
|
+
if (funcName === 'COALESCE') {
|
|
170
|
+
return node.args.every((arg, i) => walk(arg, lazy || i > 0))
|
|
171
|
+
}
|
|
169
172
|
return node.args.every(arg => walk(arg, lazy))
|
|
170
173
|
}
|
|
171
174
|
if (!STREAMABLE_FUNCS.has(funcName)) return false
|
|
@@ -394,6 +394,18 @@ export async function evaluateExpr({ node, row, rowIndex, rows, context }) {
|
|
|
394
394
|
}
|
|
395
395
|
}
|
|
396
396
|
|
|
397
|
+
// COALESCE must be handled before the eager arg evaluation below, or it
|
|
398
|
+
// evaluates every argument once eagerly and the arguments up to the first
|
|
399
|
+
// non-null value a second time. Nested calls compound that duplication.
|
|
400
|
+
if (funcName === 'COALESCE') {
|
|
401
|
+
// Short-circuit: evaluate args one at a time, return first non-null
|
|
402
|
+
for (const arg of node.args) {
|
|
403
|
+
const val = await evaluateExpr({ node: arg, row, rowIndex, rows, context })
|
|
404
|
+
if (val != null) return val
|
|
405
|
+
}
|
|
406
|
+
return null
|
|
407
|
+
}
|
|
408
|
+
|
|
397
409
|
/** @type {SqlPrimitive[]} */
|
|
398
410
|
const args = node.args.length === 1
|
|
399
411
|
? [await evaluateExpr({ node: node.args[0], row, rowIndex, rows, context })]
|
|
@@ -415,20 +427,9 @@ export async function evaluateExpr({ node, row, rowIndex, rows, context }) {
|
|
|
415
427
|
return evaluateSpatialFunc({ funcName, args })
|
|
416
428
|
}
|
|
417
429
|
|
|
418
|
-
if (funcName === 'COALESCE') {
|
|
419
|
-
// Short-circuit: evaluate args one at a time, return first non-null
|
|
420
|
-
for (const arg of node.args) {
|
|
421
|
-
const val = await evaluateExpr({ node: arg, row, rowIndex, rows, context })
|
|
422
|
-
if (val != null) return val
|
|
423
|
-
}
|
|
424
|
-
return null
|
|
425
|
-
}
|
|
426
|
-
|
|
427
430
|
if (funcName === 'NULLIF') {
|
|
428
431
|
// NULLIF(a, b) returns null if a = b, otherwise returns a
|
|
429
|
-
|
|
430
|
-
const val1 = await evaluateExpr({ node: node.args[0], row, rowIndex, rows, context })
|
|
431
|
-
return val1 == await val2 ? null : val1
|
|
432
|
+
return args[0] == args[1] ? null : args[0]
|
|
432
433
|
}
|
|
433
434
|
|
|
434
435
|
if (funcName === 'GREATEST' || funcName === 'LEAST') {
|