* Compiles a function expression for both namespaced and single-row evaluation
(func: Func, isSingleRow: boolean)
| 233 | * Compiles a function expression for both namespaced and single-row evaluation |
| 234 | */ |
| 235 | function compileFunction(func: Func, isSingleRow: boolean): (data: any) => any { |
| 236 | // Pre-compile all arguments using the appropriate compiler |
| 237 | const compiledArgs = func.args.map((arg) => |
| 238 | compileExpressionInternal(arg, isSingleRow), |
| 239 | ) |
| 240 | |
| 241 | switch (func.name) { |
| 242 | // Comparison operators |
| 243 | case `eq`: { |
| 244 | const argA = compiledArgs[0]! |
| 245 | const argB = compiledArgs[1]! |
| 246 | return (data) => { |
| 247 | const a = normalizeValue(argA(data)) |
| 248 | const b = normalizeValue(argB(data)) |
| 249 | // In 3-valued logic, any comparison with null/undefined returns UNKNOWN |
| 250 | if (isUnknown(a) || isUnknown(b)) { |
| 251 | return null |
| 252 | } |
| 253 | // NaN/invalid Dates are equal to one another (PostgreSQL semantics); |
| 254 | // otherwise use areValuesEqual for proper Uint8Array/Buffer comparison |
| 255 | return valuesEqual(a, b) |
| 256 | } |
| 257 | } |
| 258 | case `gt`: { |
| 259 | const argA = compiledArgs[0]! |
| 260 | const argB = compiledArgs[1]! |
| 261 | return (data) => { |
| 262 | const a = argA(data) |
| 263 | const b = argB(data) |
| 264 | // In 3-valued logic, any comparison with null/undefined returns UNKNOWN |
| 265 | if (isUnknown(a) || isUnknown(b)) { |
| 266 | return null |
| 267 | } |
| 268 | // NaN/invalid Dates sort greater than every other value, and are equal |
| 269 | // to one another (PostgreSQL semantics) |
| 270 | if (isUnorderable(a) || isUnorderable(b)) { |
| 271 | return isUnorderable(a) && !isUnorderable(b) |
| 272 | } |
| 273 | return a > b |
| 274 | } |
| 275 | } |
| 276 | case `gte`: { |
| 277 | const argA = compiledArgs[0]! |
| 278 | const argB = compiledArgs[1]! |
| 279 | return (data) => { |
| 280 | const a = argA(data) |
| 281 | const b = argB(data) |
| 282 | // In 3-valued logic, any comparison with null/undefined returns UNKNOWN |
| 283 | if (isUnknown(a) || isUnknown(b)) { |
| 284 | return null |
| 285 | } |
| 286 | if (isUnorderable(a) || isUnorderable(b)) { |
| 287 | return isUnorderable(a) |
| 288 | } |
| 289 | return a >= b |
| 290 | } |
| 291 | } |
| 292 | case `lt`: { |
no test coverage detected