squirreling 0.1.0 → 0.1.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/README.md +5 -1
- package/package.json +2 -2
- package/src/execute/aggregates.js +35 -8
- package/src/parse/parse.js +15 -2
- package/src/types.d.ts +4 -4
package/README.md
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
# Squirreling SQL Engine
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/squirreling)
|
|
4
|
+
[](https://www.npmjs.com/package/squirreling)
|
|
5
|
+
[](https://www.npmjs.com/package/squirreling)
|
|
6
|
+
[](https://github.com/hyparam/squirreling/actions)
|
|
3
7
|
[](https://opensource.org/licenses/MIT)
|
|
4
|
-
|
|
8
|
+
[](https://www.npmjs.com/package/squirreling?activeTab=dependencies)
|
|
5
9
|
Squirreling is a lightweight SQL engine for JavaScript applications, designed to provide efficient and easy-to-use database functionalities in the browser.
|
|
6
10
|
|
|
7
11
|
## Features
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "squirreling",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"author": "Hyperparam",
|
|
5
5
|
"homepage": "https://hyperparam.app",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/hyparam/
|
|
9
|
+
"url": "git+https://github.com/hyparam/squirreling.git"
|
|
10
10
|
},
|
|
11
11
|
"type": "module",
|
|
12
12
|
"sideEffects": false,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { evaluateExpr } from './expression.js'
|
|
1
2
|
|
|
2
3
|
/**
|
|
3
4
|
* Evaluates an aggregate function over a set of rows
|
|
4
5
|
*
|
|
5
|
-
* @import { AggregateColumn, Row } from '../types.js'
|
|
6
|
+
* @import { AggregateColumn, ExprNode, Row } from '../types.js'
|
|
6
7
|
* @param {AggregateColumn} col - aggregate column definition
|
|
7
8
|
* @param {Row[]} rows - rows to aggregate
|
|
8
9
|
* @returns {number | null} aggregated result
|
|
@@ -12,10 +13,9 @@ export function evaluateAggregate(col, rows) {
|
|
|
12
13
|
|
|
13
14
|
if (func === 'COUNT') {
|
|
14
15
|
if (arg.kind === 'star') return rows.length
|
|
15
|
-
const field = arg.column
|
|
16
16
|
let count = 0
|
|
17
17
|
for (let i = 0; i < rows.length; i += 1) {
|
|
18
|
-
const v = rows[i]
|
|
18
|
+
const v = evaluateExpr(arg.expr, rows[i])
|
|
19
19
|
if (v !== null && v !== undefined) {
|
|
20
20
|
count += 1
|
|
21
21
|
}
|
|
@@ -27,7 +27,6 @@ export function evaluateAggregate(col, rows) {
|
|
|
27
27
|
if (arg.kind === 'star') {
|
|
28
28
|
throw new Error(func + '(*) is not supported, use a column name')
|
|
29
29
|
}
|
|
30
|
-
const field = arg.column
|
|
31
30
|
let sum = 0
|
|
32
31
|
let count = 0
|
|
33
32
|
/** @type {number | null} */
|
|
@@ -36,7 +35,7 @@ export function evaluateAggregate(col, rows) {
|
|
|
36
35
|
let max = null
|
|
37
36
|
|
|
38
37
|
for (let i = 0; i < rows.length; i += 1) {
|
|
39
|
-
const raw = rows[i]
|
|
38
|
+
const raw = evaluateExpr(arg.expr, rows[i])
|
|
40
39
|
if (raw == null) continue
|
|
41
40
|
const num = Number(raw)
|
|
42
41
|
if (!Number.isFinite(num)) continue
|
|
@@ -63,11 +62,39 @@ export function evaluateAggregate(col, rows) {
|
|
|
63
62
|
|
|
64
63
|
/**
|
|
65
64
|
* Generates a default alias name for an aggregate function
|
|
66
|
-
*
|
|
67
|
-
*
|
|
65
|
+
* (e.g., "count_all", "sum_amount")
|
|
66
|
+
*
|
|
67
|
+
* @param {AggregateColumn} col
|
|
68
|
+
* @returns {string}
|
|
68
69
|
*/
|
|
69
70
|
export function defaultAggregateAlias(col) {
|
|
70
71
|
const base = col.func.toLowerCase()
|
|
71
72
|
if (col.arg.kind === 'star') return base + '_all'
|
|
72
|
-
return base + '_' + col.arg.
|
|
73
|
+
return base + '_' + defaultAggregateAliasExpr(col.arg.expr)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @param {ExprNode} expr
|
|
78
|
+
* @returns {string}
|
|
79
|
+
*/
|
|
80
|
+
export
|
|
81
|
+
function defaultAggregateAliasExpr(expr) {
|
|
82
|
+
if (expr.type === 'identifier') {
|
|
83
|
+
return expr.name
|
|
84
|
+
}
|
|
85
|
+
if (expr.type === 'literal') {
|
|
86
|
+
return String(expr.value)
|
|
87
|
+
}
|
|
88
|
+
if (expr.type === 'cast') {
|
|
89
|
+
return defaultAggregateAliasExpr(expr.expr) + '_as_' + expr.toType
|
|
90
|
+
}
|
|
91
|
+
if (expr.type === 'unary') {
|
|
92
|
+
return expr.op + '_' + defaultAggregateAliasExpr(expr.argument)
|
|
93
|
+
}
|
|
94
|
+
if (expr.type === 'binary') {
|
|
95
|
+
return defaultAggregateAliasExpr(expr.left) + '_' + expr.op + '_' + defaultAggregateAliasExpr(expr.right)
|
|
96
|
+
}
|
|
97
|
+
if (expr.type === 'function') {
|
|
98
|
+
return expr.name.toLowerCase() + '_' + expr.args.map(defaultAggregateAliasExpr).join('_')
|
|
99
|
+
}
|
|
73
100
|
}
|
package/src/parse/parse.js
CHANGED
|
@@ -226,11 +226,24 @@ function parseAggregateItem(state, func) {
|
|
|
226
226
|
if (cur.type === 'operator' && cur.value === '*') {
|
|
227
227
|
consume(state)
|
|
228
228
|
arg = { kind: 'star' }
|
|
229
|
+
} else if (cur.type === 'identifier' && cur.value === 'CAST') {
|
|
230
|
+
// Handle CAST inside aggregate: SUM(CAST(x AS type))
|
|
231
|
+
expectIdentifier(state) // consume CAST
|
|
232
|
+
expect(state, 'paren', '(')
|
|
233
|
+
const cursor = createExprCursor(state)
|
|
234
|
+
const expr = parseExpression(cursor)
|
|
235
|
+
expect(state, 'keyword', 'AS')
|
|
236
|
+
const typeTok = expectIdentifier(state)
|
|
237
|
+
expect(state, 'paren', ')')
|
|
238
|
+
arg = {
|
|
239
|
+
kind: 'expression',
|
|
240
|
+
expr: { type: 'cast', expr, toType: typeTok.value },
|
|
241
|
+
}
|
|
229
242
|
} else {
|
|
230
243
|
const colTok = expectIdentifier(state)
|
|
231
244
|
arg = {
|
|
232
|
-
kind: '
|
|
233
|
-
|
|
245
|
+
kind: 'expression',
|
|
246
|
+
expr: { type: 'identifier', name: colTok.value },
|
|
234
247
|
}
|
|
235
248
|
}
|
|
236
249
|
|
package/src/types.d.ts
CHANGED
|
@@ -102,12 +102,12 @@ export interface AggregateArgStar {
|
|
|
102
102
|
kind: 'star'
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
export interface
|
|
106
|
-
kind: '
|
|
107
|
-
|
|
105
|
+
export interface AggregateArgExpression {
|
|
106
|
+
kind: 'expression'
|
|
107
|
+
expr: ExprNode
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
export type AggregateArg = AggregateArgStar |
|
|
110
|
+
export type AggregateArg = AggregateArgStar | AggregateArgExpression
|
|
111
111
|
|
|
112
112
|
export interface AggregateColumn {
|
|
113
113
|
kind: 'aggregate'
|