squirreling 0.2.1 → 0.2.2
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/README.md +1 -1
- package/package.json +2 -2
- package/src/execute/execute.js +6 -5
- package/src/execute/having.js +5 -3
- package/src/index.d.ts +1 -1
- package/src/types.d.ts +1 -1
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@ const source = [
|
|
|
30
30
|
{ id: 2, name: 'Bob' },
|
|
31
31
|
]
|
|
32
32
|
|
|
33
|
-
const result = executeSql({ source,
|
|
33
|
+
const result = executeSql({ source, query: 'SELECT UPPER(name) AS name_upper FROM users' })
|
|
34
34
|
console.log(result)
|
|
35
35
|
// Output: [ { name_upper: 'ALICE' }, { name_upper: 'BOB' } ]
|
|
36
36
|
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "squirreling",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Squirreling SQL Engine",
|
|
5
5
|
"author": "Hyperparam",
|
|
6
6
|
"homepage": "https://hyperparam.app",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"@types/node": "24.10.1",
|
|
41
41
|
"@vitest/coverage-v8": "4.0.13",
|
|
42
42
|
"eslint": "9.39.1",
|
|
43
|
-
"eslint-plugin-jsdoc": "61.4.
|
|
43
|
+
"eslint-plugin-jsdoc": "61.4.1",
|
|
44
44
|
"typescript": "5.9.3",
|
|
45
45
|
"vitest": "4.0.13"
|
|
46
46
|
}
|
package/src/execute/execute.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { defaultAggregateAlias, evaluateAggregate } from './aggregates.js'
|
|
6
6
|
import { evaluateExpr } from './expression.js'
|
|
7
|
-
import {
|
|
7
|
+
import { evaluateHavingExpr } from './having.js'
|
|
8
8
|
import { parseSql } from '../parse/parse.js'
|
|
9
9
|
import { createMemorySource, createRowAccessor } from '../backend/memory.js'
|
|
10
10
|
|
|
@@ -14,8 +14,8 @@ import { createMemorySource, createRowAccessor } from '../backend/memory.js'
|
|
|
14
14
|
* @param {ExecuteSqlOptions} options - the execution options
|
|
15
15
|
* @returns {Record<string, any>[]} the result rows matching the query
|
|
16
16
|
*/
|
|
17
|
-
export function executeSql({ source,
|
|
18
|
-
const select = parseSql(
|
|
17
|
+
export function executeSql({ source, query }) {
|
|
18
|
+
const select = parseSql(query)
|
|
19
19
|
const dataSource = Array.isArray(source) ? createMemorySource(source) : source
|
|
20
20
|
return evaluateSelectAst(select, dataSource)
|
|
21
21
|
}
|
|
@@ -142,6 +142,8 @@ function evaluateSelectAst(select, dataSource) {
|
|
|
142
142
|
throw new Error('JOIN is not supported')
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
+
// SQL priority: from, where, group by, having, select, order by, offset, limit
|
|
146
|
+
|
|
145
147
|
// WHERE clause filtering
|
|
146
148
|
/** @type {RowSource[]} */
|
|
147
149
|
const working = []
|
|
@@ -244,8 +246,7 @@ function evaluateSelectAst(select, dataSource) {
|
|
|
244
246
|
if (select.having) {
|
|
245
247
|
// For HAVING, we need to evaluate aggregates in the context of the group
|
|
246
248
|
// Create a special row context that includes both the group data and aggregate values
|
|
247
|
-
|
|
248
|
-
if (!evaluateHavingExpr(select.having, havingContext, group)) {
|
|
249
|
+
if (!evaluateHavingExpr(select.having, resultRow, group)) {
|
|
249
250
|
continue
|
|
250
251
|
}
|
|
251
252
|
}
|
package/src/execute/having.js
CHANGED
|
@@ -12,7 +12,7 @@ import { evaluateExpr } from './expression.js'
|
|
|
12
12
|
* @param {RowSource[]} group - the group of rows
|
|
13
13
|
* @returns {RowSource} a context row for HAVING evaluation
|
|
14
14
|
*/
|
|
15
|
-
|
|
15
|
+
function createHavingContext(resultRow, group) {
|
|
16
16
|
// Include the first row of the group (for GROUP BY columns)
|
|
17
17
|
const firstRow = group[0]
|
|
18
18
|
/** @type {Record<string, any>} */
|
|
@@ -41,11 +41,13 @@ export function createHavingContext(resultRow, group) {
|
|
|
41
41
|
* Evaluates a HAVING expression with support for aggregate functions
|
|
42
42
|
*
|
|
43
43
|
* @param {ExprNode} expr - the HAVING expression
|
|
44
|
-
* @param {
|
|
44
|
+
* @param {Record<string, any>} row - the aggregated result row
|
|
45
45
|
* @param {RowSource[]} group - the group of rows for re-evaluating aggregates
|
|
46
46
|
* @returns {boolean} whether the HAVING condition is satisfied
|
|
47
47
|
*/
|
|
48
|
-
export function evaluateHavingExpr(expr,
|
|
48
|
+
export function evaluateHavingExpr(expr, row, group) {
|
|
49
|
+
const context = createHavingContext(row, group)
|
|
50
|
+
|
|
49
51
|
// For HAVING, we need special handling of aggregate functions
|
|
50
52
|
// They need to be re-evaluated against the group
|
|
51
53
|
if (expr.type === 'function') {
|
package/src/index.d.ts
CHANGED
|
@@ -16,4 +16,4 @@ export function executeSql(options: ExecuteSqlOptions): Record<string, any>[]
|
|
|
16
16
|
* @param sql - SQL query string to parse
|
|
17
17
|
* @returns parsed SQL select statement
|
|
18
18
|
*/
|
|
19
|
-
export function parseSql(
|
|
19
|
+
export function parseSql(query: string): SelectStatement
|
package/src/types.d.ts
CHANGED