squirreling 0.2.5 → 0.2.6
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 +1 -1
- package/src/execute/expression.js +29 -0
- package/src/parse/expression.js +42 -0
- package/src/parse/parse.js +1 -1
- package/src/types.d.ts +13 -0
package/package.json
CHANGED
|
@@ -224,5 +224,34 @@ export function evaluateExpr(node, row) {
|
|
|
224
224
|
throw new Error('WHERE NOT EXISTS with subqueries is not yet supported.')
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
+
// CASE expressions
|
|
228
|
+
if (node.type === 'case') {
|
|
229
|
+
// For simple CASE: evaluate the case expression once
|
|
230
|
+
const caseValue = node.caseExpr ? evaluateExpr(node.caseExpr, row) : undefined
|
|
231
|
+
|
|
232
|
+
// Iterate through WHEN clauses
|
|
233
|
+
for (const whenClause of node.whenClauses) {
|
|
234
|
+
let conditionResult
|
|
235
|
+
if (caseValue !== undefined) {
|
|
236
|
+
// Simple CASE: compare caseValue with condition
|
|
237
|
+
const whenValue = evaluateExpr(whenClause.condition, row)
|
|
238
|
+
conditionResult = caseValue === whenValue
|
|
239
|
+
} else {
|
|
240
|
+
// Searched CASE: evaluate condition as boolean
|
|
241
|
+
conditionResult = evaluateExpr(whenClause.condition, row)
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (conditionResult) {
|
|
245
|
+
return evaluateExpr(whenClause.result, row)
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// No WHEN clause matched, return ELSE result or NULL
|
|
250
|
+
if (node.elseResult) {
|
|
251
|
+
return evaluateExpr(node.elseResult, row)
|
|
252
|
+
}
|
|
253
|
+
return null
|
|
254
|
+
}
|
|
255
|
+
|
|
227
256
|
throw new Error('Unknown expression node type ' + node.type)
|
|
228
257
|
}
|
package/src/parse/expression.js
CHANGED
|
@@ -141,6 +141,48 @@ function parsePrimary(c) {
|
|
|
141
141
|
subquery,
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
|
+
if (tok.value === 'CASE') {
|
|
145
|
+
c.consume() // CASE
|
|
146
|
+
|
|
147
|
+
// Check if it's simple CASE (CASE expr WHEN ...) or searched CASE (CASE WHEN ...)
|
|
148
|
+
/** @type {import('../types.js').ExprNode | undefined} */
|
|
149
|
+
let caseExpr
|
|
150
|
+
const nextTok = c.current()
|
|
151
|
+
if (nextTok.type !== 'keyword' || nextTok.value !== 'WHEN') {
|
|
152
|
+
// Simple CASE: parse the case expression
|
|
153
|
+
caseExpr = parseExpression(c)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Parse WHEN clauses
|
|
157
|
+
/** @type {import('../types.js').WhenClause[]} */
|
|
158
|
+
const whenClauses = []
|
|
159
|
+
while (c.match('keyword', 'WHEN')) {
|
|
160
|
+
const condition = parseExpression(c)
|
|
161
|
+
c.expect('keyword', 'THEN')
|
|
162
|
+
const result = parseExpression(c)
|
|
163
|
+
whenClauses.push({ condition, result })
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (whenClauses.length === 0) {
|
|
167
|
+
throw new Error('CASE expression must have at least one WHEN clause')
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Parse optional ELSE clause
|
|
171
|
+
/** @type {import('../types.js').ExprNode | undefined} */
|
|
172
|
+
let elseResult
|
|
173
|
+
if (c.match('keyword', 'ELSE')) {
|
|
174
|
+
elseResult = parseExpression(c)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
c.expect('keyword', 'END')
|
|
178
|
+
|
|
179
|
+
return {
|
|
180
|
+
type: 'case',
|
|
181
|
+
caseExpr,
|
|
182
|
+
whenClauses,
|
|
183
|
+
elseResult,
|
|
184
|
+
}
|
|
185
|
+
}
|
|
144
186
|
}
|
|
145
187
|
|
|
146
188
|
if (tok.type === 'operator' && tok.value === '-') {
|
package/src/parse/parse.js
CHANGED
|
@@ -177,7 +177,7 @@ function parseSelectList(state) {
|
|
|
177
177
|
function parseSelectItem(state) {
|
|
178
178
|
const tok = current(state)
|
|
179
179
|
|
|
180
|
-
if (tok.type
|
|
180
|
+
if (tok.type === 'keyword' && tok.value !== 'CASE' || tok.type === 'eof') {
|
|
181
181
|
throw parseError(state, 'column name or expression')
|
|
182
182
|
}
|
|
183
183
|
|
package/src/types.d.ts
CHANGED
|
@@ -105,6 +105,18 @@ export interface ExistsNode {
|
|
|
105
105
|
subquery: SelectStatement
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
+
export interface WhenClause {
|
|
109
|
+
condition: ExprNode
|
|
110
|
+
result: ExprNode
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export interface CaseNode {
|
|
114
|
+
type: 'case'
|
|
115
|
+
caseExpr?: ExprNode
|
|
116
|
+
whenClauses: WhenClause[]
|
|
117
|
+
elseResult?: ExprNode
|
|
118
|
+
}
|
|
119
|
+
|
|
108
120
|
export type ExprNode =
|
|
109
121
|
| LiteralNode
|
|
110
122
|
| IdentifierNode
|
|
@@ -116,6 +128,7 @@ export type ExprNode =
|
|
|
116
128
|
| InSubqueryNode
|
|
117
129
|
| InValuesNode
|
|
118
130
|
| ExistsNode
|
|
131
|
+
| CaseNode
|
|
119
132
|
|
|
120
133
|
export interface StarColumn {
|
|
121
134
|
kind: 'star'
|