@tanstack/db 0.0.13 → 0.0.15
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/dist/cjs/collection.cjs +117 -104
- package/dist/cjs/collection.cjs.map +1 -1
- package/dist/cjs/collection.d.cts +19 -22
- package/dist/cjs/index.cjs +35 -13
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +0 -1
- package/dist/cjs/query/builder/functions.cjs +107 -0
- package/dist/cjs/query/builder/functions.cjs.map +1 -0
- package/dist/cjs/query/builder/functions.d.cts +38 -0
- package/dist/cjs/query/builder/index.cjs +499 -0
- package/dist/cjs/query/builder/index.cjs.map +1 -0
- package/dist/cjs/query/builder/index.d.cts +324 -0
- package/dist/cjs/query/builder/ref-proxy.cjs +96 -0
- package/dist/cjs/query/builder/ref-proxy.cjs.map +1 -0
- package/dist/cjs/query/builder/ref-proxy.d.cts +28 -0
- package/dist/cjs/query/builder/types.d.cts +80 -0
- package/dist/cjs/query/compiler/evaluators.cjs +261 -0
- package/dist/cjs/query/compiler/evaluators.cjs.map +1 -0
- package/dist/cjs/query/compiler/evaluators.d.cts +11 -0
- package/dist/cjs/query/compiler/group-by.cjs +271 -0
- package/dist/cjs/query/compiler/group-by.cjs.map +1 -0
- package/dist/cjs/query/compiler/group-by.d.cts +7 -0
- package/dist/cjs/query/compiler/index.cjs +181 -0
- package/dist/cjs/query/compiler/index.cjs.map +1 -0
- package/dist/cjs/query/compiler/index.d.cts +15 -0
- package/dist/cjs/query/compiler/joins.cjs +116 -0
- package/dist/cjs/query/compiler/joins.cjs.map +1 -0
- package/dist/cjs/query/compiler/joins.d.cts +11 -0
- package/dist/cjs/query/compiler/order-by.cjs +89 -0
- package/dist/cjs/query/compiler/order-by.cjs.map +1 -0
- package/dist/cjs/query/compiler/order-by.d.cts +9 -0
- package/dist/cjs/query/compiler/select.cjs +57 -0
- package/dist/cjs/query/compiler/select.cjs.map +1 -0
- package/dist/cjs/query/compiler/select.d.cts +15 -0
- package/dist/cjs/query/index.d.cts +6 -5
- package/dist/cjs/query/ir.cjs +57 -0
- package/dist/cjs/query/ir.cjs.map +1 -0
- package/dist/cjs/query/ir.d.cts +81 -0
- package/dist/cjs/query/live-query-collection.cjs +224 -0
- package/dist/cjs/query/live-query-collection.cjs.map +1 -0
- package/dist/cjs/query/live-query-collection.d.cts +124 -0
- package/dist/cjs/transactions.cjs +20 -13
- package/dist/cjs/transactions.cjs.map +1 -1
- package/dist/cjs/transactions.d.cts +13 -4
- package/dist/cjs/types.d.cts +14 -1
- package/dist/esm/collection.d.ts +19 -22
- package/dist/esm/collection.js +118 -105
- package/dist/esm/collection.js.map +1 -1
- package/dist/esm/index.d.ts +0 -1
- package/dist/esm/index.js +34 -12
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/query/builder/functions.d.ts +38 -0
- package/dist/esm/query/builder/functions.js +107 -0
- package/dist/esm/query/builder/functions.js.map +1 -0
- package/dist/esm/query/builder/index.d.ts +324 -0
- package/dist/esm/query/builder/index.js +499 -0
- package/dist/esm/query/builder/index.js.map +1 -0
- package/dist/esm/query/builder/ref-proxy.d.ts +28 -0
- package/dist/esm/query/builder/ref-proxy.js +96 -0
- package/dist/esm/query/builder/ref-proxy.js.map +1 -0
- package/dist/esm/query/builder/types.d.ts +80 -0
- package/dist/esm/query/compiler/evaluators.d.ts +11 -0
- package/dist/esm/query/compiler/evaluators.js +261 -0
- package/dist/esm/query/compiler/evaluators.js.map +1 -0
- package/dist/esm/query/compiler/group-by.d.ts +7 -0
- package/dist/esm/query/compiler/group-by.js +271 -0
- package/dist/esm/query/compiler/group-by.js.map +1 -0
- package/dist/esm/query/compiler/index.d.ts +15 -0
- package/dist/esm/query/compiler/index.js +181 -0
- package/dist/esm/query/compiler/index.js.map +1 -0
- package/dist/esm/query/compiler/joins.d.ts +11 -0
- package/dist/esm/query/compiler/joins.js +116 -0
- package/dist/esm/query/compiler/joins.js.map +1 -0
- package/dist/esm/query/compiler/order-by.d.ts +9 -0
- package/dist/esm/query/compiler/order-by.js +89 -0
- package/dist/esm/query/compiler/order-by.js.map +1 -0
- package/dist/esm/query/compiler/select.d.ts +15 -0
- package/dist/esm/query/compiler/select.js +57 -0
- package/dist/esm/query/compiler/select.js.map +1 -0
- package/dist/esm/query/index.d.ts +6 -5
- package/dist/esm/query/ir.d.ts +81 -0
- package/dist/esm/query/ir.js +57 -0
- package/dist/esm/query/ir.js.map +1 -0
- package/dist/esm/query/live-query-collection.d.ts +124 -0
- package/dist/esm/query/live-query-collection.js +224 -0
- package/dist/esm/query/live-query-collection.js.map +1 -0
- package/dist/esm/transactions.d.ts +13 -4
- package/dist/esm/transactions.js +20 -13
- package/dist/esm/transactions.js.map +1 -1
- package/dist/esm/types.d.ts +14 -1
- package/package.json +3 -4
- package/src/collection.ts +152 -129
- package/src/index.ts +0 -1
- package/src/query/builder/functions.ts +267 -0
- package/src/query/builder/index.ts +648 -0
- package/src/query/builder/ref-proxy.ts +156 -0
- package/src/query/builder/types.ts +278 -0
- package/src/query/compiler/evaluators.ts +315 -0
- package/src/query/compiler/group-by.ts +428 -0
- package/src/query/compiler/index.ts +276 -0
- package/src/query/compiler/joins.ts +228 -0
- package/src/query/compiler/order-by.ts +139 -0
- package/src/query/compiler/select.ts +173 -0
- package/src/query/index.ts +64 -5
- package/src/query/ir.ts +128 -0
- package/src/query/live-query-collection.ts +509 -0
- package/src/transactions.ts +34 -19
- package/src/types.ts +16 -1
- package/dist/cjs/query/compiled-query.cjs +0 -160
- package/dist/cjs/query/compiled-query.cjs.map +0 -1
- package/dist/cjs/query/compiled-query.d.cts +0 -20
- package/dist/cjs/query/evaluators.cjs +0 -161
- package/dist/cjs/query/evaluators.cjs.map +0 -1
- package/dist/cjs/query/evaluators.d.cts +0 -14
- package/dist/cjs/query/extractors.cjs +0 -122
- package/dist/cjs/query/extractors.cjs.map +0 -1
- package/dist/cjs/query/extractors.d.cts +0 -22
- package/dist/cjs/query/functions.cjs +0 -152
- package/dist/cjs/query/functions.cjs.map +0 -1
- package/dist/cjs/query/functions.d.cts +0 -21
- package/dist/cjs/query/group-by.cjs +0 -88
- package/dist/cjs/query/group-by.cjs.map +0 -1
- package/dist/cjs/query/group-by.d.cts +0 -40
- package/dist/cjs/query/joins.cjs +0 -141
- package/dist/cjs/query/joins.cjs.map +0 -1
- package/dist/cjs/query/joins.d.cts +0 -14
- package/dist/cjs/query/order-by.cjs +0 -185
- package/dist/cjs/query/order-by.cjs.map +0 -1
- package/dist/cjs/query/order-by.d.cts +0 -3
- package/dist/cjs/query/pipeline-compiler.cjs +0 -89
- package/dist/cjs/query/pipeline-compiler.cjs.map +0 -1
- package/dist/cjs/query/pipeline-compiler.d.cts +0 -10
- package/dist/cjs/query/query-builder.cjs +0 -307
- package/dist/cjs/query/query-builder.cjs.map +0 -1
- package/dist/cjs/query/query-builder.d.cts +0 -225
- package/dist/cjs/query/schema.d.cts +0 -100
- package/dist/cjs/query/select.cjs +0 -130
- package/dist/cjs/query/select.cjs.map +0 -1
- package/dist/cjs/query/select.d.cts +0 -3
- package/dist/cjs/query/types.d.cts +0 -189
- package/dist/cjs/query/utils.cjs +0 -154
- package/dist/cjs/query/utils.cjs.map +0 -1
- package/dist/cjs/query/utils.d.cts +0 -37
- package/dist/cjs/utils.cjs +0 -17
- package/dist/cjs/utils.cjs.map +0 -1
- package/dist/cjs/utils.d.cts +0 -3
- package/dist/esm/query/compiled-query.d.ts +0 -20
- package/dist/esm/query/compiled-query.js +0 -160
- package/dist/esm/query/compiled-query.js.map +0 -1
- package/dist/esm/query/evaluators.d.ts +0 -14
- package/dist/esm/query/evaluators.js +0 -161
- package/dist/esm/query/evaluators.js.map +0 -1
- package/dist/esm/query/extractors.d.ts +0 -22
- package/dist/esm/query/extractors.js +0 -122
- package/dist/esm/query/extractors.js.map +0 -1
- package/dist/esm/query/functions.d.ts +0 -21
- package/dist/esm/query/functions.js +0 -152
- package/dist/esm/query/functions.js.map +0 -1
- package/dist/esm/query/group-by.d.ts +0 -40
- package/dist/esm/query/group-by.js +0 -88
- package/dist/esm/query/group-by.js.map +0 -1
- package/dist/esm/query/joins.d.ts +0 -14
- package/dist/esm/query/joins.js +0 -141
- package/dist/esm/query/joins.js.map +0 -1
- package/dist/esm/query/order-by.d.ts +0 -3
- package/dist/esm/query/order-by.js +0 -185
- package/dist/esm/query/order-by.js.map +0 -1
- package/dist/esm/query/pipeline-compiler.d.ts +0 -10
- package/dist/esm/query/pipeline-compiler.js +0 -89
- package/dist/esm/query/pipeline-compiler.js.map +0 -1
- package/dist/esm/query/query-builder.d.ts +0 -225
- package/dist/esm/query/query-builder.js +0 -307
- package/dist/esm/query/query-builder.js.map +0 -1
- package/dist/esm/query/schema.d.ts +0 -100
- package/dist/esm/query/select.d.ts +0 -3
- package/dist/esm/query/select.js +0 -130
- package/dist/esm/query/select.js.map +0 -1
- package/dist/esm/query/types.d.ts +0 -189
- package/dist/esm/query/utils.d.ts +0 -37
- package/dist/esm/query/utils.js +0 -154
- package/dist/esm/query/utils.js.map +0 -1
- package/dist/esm/utils.d.ts +0 -3
- package/dist/esm/utils.js +0 -17
- package/dist/esm/utils.js.map +0 -1
- package/src/query/compiled-query.ts +0 -234
- package/src/query/evaluators.ts +0 -250
- package/src/query/extractors.ts +0 -214
- package/src/query/functions.ts +0 -297
- package/src/query/group-by.ts +0 -139
- package/src/query/joins.ts +0 -260
- package/src/query/order-by.ts +0 -264
- package/src/query/pipeline-compiler.ts +0 -149
- package/src/query/query-builder.ts +0 -902
- package/src/query/schema.ts +0 -268
- package/src/query/select.ts +0 -208
- package/src/query/types.ts +0 -418
- package/src/query/utils.ts +0 -245
- package/src/utils.ts +0 -15
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import type { BasicExpression, Func, Ref } from "../ir.js"
|
|
2
|
+
import type { NamespacedRow } from "../../types.js"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Compiled expression evaluator function type
|
|
6
|
+
*/
|
|
7
|
+
export type CompiledExpression = (namespacedRow: NamespacedRow) => any
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Compiles an expression into an optimized evaluator function.
|
|
11
|
+
* This eliminates branching during evaluation by pre-compiling the expression structure.
|
|
12
|
+
*/
|
|
13
|
+
export function compileExpression(expr: BasicExpression): CompiledExpression {
|
|
14
|
+
switch (expr.type) {
|
|
15
|
+
case `val`: {
|
|
16
|
+
// For constant values, return a function that just returns the value
|
|
17
|
+
const value = expr.value
|
|
18
|
+
return () => value
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
case `ref`: {
|
|
22
|
+
// For references, pre-compile the property path navigation
|
|
23
|
+
return compileRef(expr)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
case `func`: {
|
|
27
|
+
// For functions, pre-compile the function and its arguments
|
|
28
|
+
return compileFunction(expr)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
default:
|
|
32
|
+
throw new Error(`Unknown expression type: ${(expr as any).type}`)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Compiles a reference expression into an optimized evaluator
|
|
38
|
+
*/
|
|
39
|
+
function compileRef(ref: Ref): CompiledExpression {
|
|
40
|
+
const [tableAlias, ...propertyPath] = ref.path
|
|
41
|
+
|
|
42
|
+
if (!tableAlias) {
|
|
43
|
+
throw new Error(`Reference path cannot be empty`)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Pre-compile the property path navigation
|
|
47
|
+
if (propertyPath.length === 0) {
|
|
48
|
+
// Simple table reference
|
|
49
|
+
return (namespacedRow) => namespacedRow[tableAlias]
|
|
50
|
+
} else if (propertyPath.length === 1) {
|
|
51
|
+
// Single property access - most common case
|
|
52
|
+
const prop = propertyPath[0]!
|
|
53
|
+
return (namespacedRow) => {
|
|
54
|
+
const tableData = namespacedRow[tableAlias]
|
|
55
|
+
return tableData?.[prop]
|
|
56
|
+
}
|
|
57
|
+
} else {
|
|
58
|
+
// Multiple property navigation
|
|
59
|
+
return (namespacedRow) => {
|
|
60
|
+
const tableData = namespacedRow[tableAlias]
|
|
61
|
+
if (tableData === undefined) {
|
|
62
|
+
return undefined
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
let value: any = tableData
|
|
66
|
+
for (const prop of propertyPath) {
|
|
67
|
+
if (value == null) {
|
|
68
|
+
return value
|
|
69
|
+
}
|
|
70
|
+
value = value[prop]
|
|
71
|
+
}
|
|
72
|
+
return value
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Compiles a function expression into an optimized evaluator
|
|
79
|
+
*/
|
|
80
|
+
function compileFunction(func: Func): CompiledExpression {
|
|
81
|
+
// Pre-compile all arguments
|
|
82
|
+
const compiledArgs = func.args.map(compileExpression)
|
|
83
|
+
|
|
84
|
+
switch (func.name) {
|
|
85
|
+
// Comparison operators
|
|
86
|
+
case `eq`: {
|
|
87
|
+
const argA = compiledArgs[0]!
|
|
88
|
+
const argB = compiledArgs[1]!
|
|
89
|
+
return (namespacedRow) => {
|
|
90
|
+
const a = argA(namespacedRow)
|
|
91
|
+
const b = argB(namespacedRow)
|
|
92
|
+
return a === b
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
case `gt`: {
|
|
96
|
+
const argA = compiledArgs[0]!
|
|
97
|
+
const argB = compiledArgs[1]!
|
|
98
|
+
return (namespacedRow) => {
|
|
99
|
+
const a = argA(namespacedRow)
|
|
100
|
+
const b = argB(namespacedRow)
|
|
101
|
+
return a > b
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
case `gte`: {
|
|
105
|
+
const argA = compiledArgs[0]!
|
|
106
|
+
const argB = compiledArgs[1]!
|
|
107
|
+
return (namespacedRow) => {
|
|
108
|
+
const a = argA(namespacedRow)
|
|
109
|
+
const b = argB(namespacedRow)
|
|
110
|
+
return a >= b
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
case `lt`: {
|
|
114
|
+
const argA = compiledArgs[0]!
|
|
115
|
+
const argB = compiledArgs[1]!
|
|
116
|
+
return (namespacedRow) => {
|
|
117
|
+
const a = argA(namespacedRow)
|
|
118
|
+
const b = argB(namespacedRow)
|
|
119
|
+
return a < b
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
case `lte`: {
|
|
123
|
+
const argA = compiledArgs[0]!
|
|
124
|
+
const argB = compiledArgs[1]!
|
|
125
|
+
return (namespacedRow) => {
|
|
126
|
+
const a = argA(namespacedRow)
|
|
127
|
+
const b = argB(namespacedRow)
|
|
128
|
+
return a <= b
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Boolean operators
|
|
133
|
+
case `and`:
|
|
134
|
+
return (namespacedRow) => {
|
|
135
|
+
for (const compiledArg of compiledArgs) {
|
|
136
|
+
if (!compiledArg(namespacedRow)) {
|
|
137
|
+
return false
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return true
|
|
141
|
+
}
|
|
142
|
+
case `or`:
|
|
143
|
+
return (namespacedRow) => {
|
|
144
|
+
for (const compiledArg of compiledArgs) {
|
|
145
|
+
if (compiledArg(namespacedRow)) {
|
|
146
|
+
return true
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return false
|
|
150
|
+
}
|
|
151
|
+
case `not`: {
|
|
152
|
+
const arg = compiledArgs[0]!
|
|
153
|
+
return (namespacedRow) => !arg(namespacedRow)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Array operators
|
|
157
|
+
case `in`: {
|
|
158
|
+
const valueEvaluator = compiledArgs[0]!
|
|
159
|
+
const arrayEvaluator = compiledArgs[1]!
|
|
160
|
+
return (namespacedRow) => {
|
|
161
|
+
const value = valueEvaluator(namespacedRow)
|
|
162
|
+
const array = arrayEvaluator(namespacedRow)
|
|
163
|
+
if (!Array.isArray(array)) {
|
|
164
|
+
return false
|
|
165
|
+
}
|
|
166
|
+
return array.includes(value)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// String operators
|
|
171
|
+
case `like`: {
|
|
172
|
+
const valueEvaluator = compiledArgs[0]!
|
|
173
|
+
const patternEvaluator = compiledArgs[1]!
|
|
174
|
+
return (namespacedRow) => {
|
|
175
|
+
const value = valueEvaluator(namespacedRow)
|
|
176
|
+
const pattern = patternEvaluator(namespacedRow)
|
|
177
|
+
return evaluateLike(value, pattern, false)
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
case `ilike`: {
|
|
181
|
+
const valueEvaluator = compiledArgs[0]!
|
|
182
|
+
const patternEvaluator = compiledArgs[1]!
|
|
183
|
+
return (namespacedRow) => {
|
|
184
|
+
const value = valueEvaluator(namespacedRow)
|
|
185
|
+
const pattern = patternEvaluator(namespacedRow)
|
|
186
|
+
return evaluateLike(value, pattern, true)
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// String functions
|
|
191
|
+
case `upper`: {
|
|
192
|
+
const arg = compiledArgs[0]!
|
|
193
|
+
return (namespacedRow) => {
|
|
194
|
+
const value = arg(namespacedRow)
|
|
195
|
+
return typeof value === `string` ? value.toUpperCase() : value
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
case `lower`: {
|
|
199
|
+
const arg = compiledArgs[0]!
|
|
200
|
+
return (namespacedRow) => {
|
|
201
|
+
const value = arg(namespacedRow)
|
|
202
|
+
return typeof value === `string` ? value.toLowerCase() : value
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
case `length`: {
|
|
206
|
+
const arg = compiledArgs[0]!
|
|
207
|
+
return (namespacedRow) => {
|
|
208
|
+
const value = arg(namespacedRow)
|
|
209
|
+
if (typeof value === `string`) {
|
|
210
|
+
return value.length
|
|
211
|
+
}
|
|
212
|
+
if (Array.isArray(value)) {
|
|
213
|
+
return value.length
|
|
214
|
+
}
|
|
215
|
+
return 0
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
case `concat`:
|
|
219
|
+
return (namespacedRow) => {
|
|
220
|
+
return compiledArgs
|
|
221
|
+
.map((evaluator) => {
|
|
222
|
+
const arg = evaluator(namespacedRow)
|
|
223
|
+
try {
|
|
224
|
+
return String(arg ?? ``)
|
|
225
|
+
} catch {
|
|
226
|
+
try {
|
|
227
|
+
return JSON.stringify(arg) || ``
|
|
228
|
+
} catch {
|
|
229
|
+
return `[object]`
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
})
|
|
233
|
+
.join(``)
|
|
234
|
+
}
|
|
235
|
+
case `coalesce`:
|
|
236
|
+
return (namespacedRow) => {
|
|
237
|
+
for (const evaluator of compiledArgs) {
|
|
238
|
+
const value = evaluator(namespacedRow)
|
|
239
|
+
if (value !== null && value !== undefined) {
|
|
240
|
+
return value
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return null
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Math functions
|
|
247
|
+
case `add`: {
|
|
248
|
+
const argA = compiledArgs[0]!
|
|
249
|
+
const argB = compiledArgs[1]!
|
|
250
|
+
return (namespacedRow) => {
|
|
251
|
+
const a = argA(namespacedRow)
|
|
252
|
+
const b = argB(namespacedRow)
|
|
253
|
+
return (a ?? 0) + (b ?? 0)
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
case `subtract`: {
|
|
257
|
+
const argA = compiledArgs[0]!
|
|
258
|
+
const argB = compiledArgs[1]!
|
|
259
|
+
return (namespacedRow) => {
|
|
260
|
+
const a = argA(namespacedRow)
|
|
261
|
+
const b = argB(namespacedRow)
|
|
262
|
+
return (a ?? 0) - (b ?? 0)
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
case `multiply`: {
|
|
266
|
+
const argA = compiledArgs[0]!
|
|
267
|
+
const argB = compiledArgs[1]!
|
|
268
|
+
return (namespacedRow) => {
|
|
269
|
+
const a = argA(namespacedRow)
|
|
270
|
+
const b = argB(namespacedRow)
|
|
271
|
+
return (a ?? 0) * (b ?? 0)
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
case `divide`: {
|
|
275
|
+
const argA = compiledArgs[0]!
|
|
276
|
+
const argB = compiledArgs[1]!
|
|
277
|
+
return (namespacedRow) => {
|
|
278
|
+
const a = argA(namespacedRow)
|
|
279
|
+
const b = argB(namespacedRow)
|
|
280
|
+
const divisor = b ?? 0
|
|
281
|
+
return divisor !== 0 ? (a ?? 0) / divisor : null
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
default:
|
|
286
|
+
throw new Error(`Unknown function: ${func.name}`)
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Evaluates LIKE/ILIKE patterns
|
|
292
|
+
*/
|
|
293
|
+
function evaluateLike(
|
|
294
|
+
value: any,
|
|
295
|
+
pattern: any,
|
|
296
|
+
caseInsensitive: boolean
|
|
297
|
+
): boolean {
|
|
298
|
+
if (typeof value !== `string` || typeof pattern !== `string`) {
|
|
299
|
+
return false
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const searchValue = caseInsensitive ? value.toLowerCase() : value
|
|
303
|
+
const searchPattern = caseInsensitive ? pattern.toLowerCase() : pattern
|
|
304
|
+
|
|
305
|
+
// Convert SQL LIKE pattern to regex
|
|
306
|
+
// First escape all regex special chars except % and _
|
|
307
|
+
let regexPattern = searchPattern.replace(/[.*+?^${}()|[\]\\]/g, `\\$&`)
|
|
308
|
+
|
|
309
|
+
// Then convert SQL wildcards to regex
|
|
310
|
+
regexPattern = regexPattern.replace(/%/g, `.*`) // % matches any sequence
|
|
311
|
+
regexPattern = regexPattern.replace(/_/g, `.`) // _ matches any single char
|
|
312
|
+
|
|
313
|
+
const regex = new RegExp(`^${regexPattern}$`)
|
|
314
|
+
return regex.test(searchValue)
|
|
315
|
+
}
|