@powersync/service-sync-rules 0.17.10 → 0.18.0

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.
@@ -1,8 +1,10 @@
1
+ import { ExpressionType, TYPE_NONE } from './ExpressionType.js';
1
2
  import { SqlRuleError } from './errors.js';
2
- import { BASIC_OPERATORS, cast, CAST_TYPES, jsonExtract, SQL_FUNCTIONS, sqliteTypeOf } from './sql_functions.js';
3
+ import { BASIC_OPERATORS, OPERATOR_IS_NOT_NULL, OPERATOR_IS_NULL, OPERATOR_JSON_EXTRACT_JSON, OPERATOR_JSON_EXTRACT_SQL, OPERATOR_NOT, SQL_FUNCTIONS, castOperator, sqliteTypeOf } from './sql_functions.js';
4
+ import { SQLITE_FALSE, SQLITE_TRUE, andFilters, compileStaticOperator, getOperatorFunction, isClauseError, isParameterMatchClause, isParameterValueClause, isRowValueClause, isStaticValueClause, orFilters, toBooleanParameterSetClause } from './sql_support.js';
3
5
  import { isJsonValue } from './utils.js';
4
- import { andFilters, compileStaticOperator, isClauseError, isParameterMatchClause, isParameterValueClause, isStaticRowValueClause, orFilters, SQLITE_FALSE, SQLITE_TRUE, sqliteNot, toBooleanParameterSetClause } from './sql_support.js';
5
- import { ExpressionType, TYPE_NONE } from './ExpressionType.js';
6
+ import { JSONBig } from '@powersync/service-jsonbig';
7
+ import { REQUEST_FUNCTIONS } from './request_functions.js';
6
8
  export const MATCH_CONST_FALSE = [];
7
9
  export const MATCH_CONST_TRUE = [{}];
8
10
  Object.freeze(MATCH_CONST_TRUE);
@@ -24,6 +26,7 @@ export class SqlTools {
24
26
  this.parameter_tables = options.parameter_tables ?? [];
25
27
  this.sql = options.sql;
26
28
  this.supports_expanding_parameters = options.supports_expanding_parameters ?? false;
29
+ this.supports_parameter_expressions = options.supports_parameter_expressions ?? false;
27
30
  }
28
31
  error(message, expr) {
29
32
  this.errors.push(new SqlRuleError(message, this.sql, expr));
@@ -44,33 +47,30 @@ export class SqlTools {
44
47
  const base = this.compileClause(where);
45
48
  return toBooleanParameterSetClause(base);
46
49
  }
47
- compileStaticExtractor(expr) {
50
+ compileRowValueExtractor(expr) {
48
51
  const clause = this.compileClause(expr);
49
- if (!isStaticRowValueClause(clause) && !isClauseError(clause)) {
50
- throw new SqlRuleError('Bucket parameters are not allowed here', this.sql, expr ?? undefined);
52
+ if (!isRowValueClause(clause) && !isClauseError(clause)) {
53
+ return this.error('Parameter match expression is not allowed here', expr ?? undefined);
51
54
  }
52
55
  return clause;
53
56
  }
57
+ compileParameterValueExtractor(expr) {
58
+ const clause = this.compileClause(expr);
59
+ if (isClauseError(clause) || isStaticValueClause(clause) || isParameterValueClause(clause)) {
60
+ return clause;
61
+ }
62
+ return this.error('Parameter match expression is not allowed here', expr ?? undefined);
63
+ }
54
64
  /**
55
65
  * Given an expression, return a compiled clause.
56
66
  */
57
67
  compileClause(expr) {
58
68
  if (expr == null) {
59
- return {
60
- evaluate: () => SQLITE_TRUE,
61
- getType() {
62
- return ExpressionType.INTEGER;
63
- }
64
- };
69
+ return staticValueClause(SQLITE_TRUE);
65
70
  }
66
71
  else if (isStatic(expr)) {
67
72
  const value = staticValue(expr);
68
- return {
69
- evaluate: () => value,
70
- getType() {
71
- return ExpressionType.fromTypeText(sqliteTypeOf(value));
72
- }
73
- };
73
+ return staticValueClause(value);
74
74
  }
75
75
  else if (expr.type == 'ref') {
76
76
  const column = expr.name;
@@ -81,8 +81,7 @@ export class SqlTools {
81
81
  return this.error(`Schema is not supported in column references`, expr);
82
82
  }
83
83
  if (this.isParameterRef(expr)) {
84
- const param = this.getParameterRef(expr);
85
- return { bucketParameter: param };
84
+ return this.getParameterRefClause(expr);
86
85
  }
87
86
  else if (this.isTableRef(expr)) {
88
87
  const table = this.getTableName(expr);
@@ -128,15 +127,27 @@ export class SqlTools {
128
127
  }
129
128
  else if (op == '=') {
130
129
  // Options:
131
- // 1. static, static
132
- // 2. static, parameterValue
130
+ // 1. row value, row value
131
+ // 2. row value, parameter value
133
132
  // 3. static true, parameterMatch - not supported yet
133
+ // 4. parameter value, parameter value
134
134
  let staticFilter1;
135
135
  let otherFilter1;
136
- if (!isStaticRowValueClause(leftFilter) && !isStaticRowValueClause(rightFilter)) {
136
+ if (this.supports_parameter_expressions &&
137
+ isParameterValueClause(leftFilter) &&
138
+ isParameterValueClause(rightFilter)) {
139
+ // 4. parameterValue, parameterValue
140
+ // This includes (static value, parameter value)
141
+ // Not applicable to data queries (composeFunction will error).
142
+ // Some of those cases can still be handled with case (2),
143
+ // so we filter for supports_parameter_expressions above.
144
+ const fnImpl = getOperatorFunction('=');
145
+ return this.composeFunction(fnImpl, [leftFilter, rightFilter], [left, right]);
146
+ }
147
+ if (!isRowValueClause(leftFilter) && !isRowValueClause(rightFilter)) {
137
148
  return this.error(`Cannot have bucket parameters on both sides of = operator`, expr);
138
149
  }
139
- else if (isStaticRowValueClause(leftFilter)) {
150
+ else if (isRowValueClause(leftFilter)) {
140
151
  staticFilter1 = leftFilter;
141
152
  otherFilter1 = rightFilter;
142
153
  }
@@ -146,17 +157,18 @@ export class SqlTools {
146
157
  }
147
158
  const staticFilter = staticFilter1;
148
159
  const otherFilter = otherFilter1;
149
- if (isStaticRowValueClause(otherFilter)) {
150
- // 1. static, static
160
+ if (isRowValueClause(otherFilter)) {
161
+ // 1. row value = row value
151
162
  return compileStaticOperator(op, leftFilter, rightFilter);
152
163
  }
153
164
  else if (isParameterValueClause(otherFilter)) {
154
- // 2. static, parameterValue
165
+ // 2. row value = parameter value
166
+ const inputParam = basicInputParameter(otherFilter);
155
167
  return {
156
168
  error: false,
157
- bucketParameters: [otherFilter.bucketParameter],
169
+ inputParameters: [inputParam],
158
170
  unbounded: false,
159
- filter(tables) {
171
+ filterRow(tables) {
160
172
  const value = staticFilter.evaluate(tables);
161
173
  if (value == null) {
162
174
  // null never matches on =
@@ -167,15 +179,17 @@ export class SqlTools {
167
179
  // Cannot persist this, e.g. BLOB
168
180
  return MATCH_CONST_FALSE;
169
181
  }
170
- return [{ [otherFilter.bucketParameter]: value }];
171
- }
182
+ return [{ [inputParam.key]: value }];
183
+ },
184
+ usesAuthenticatedRequestParameters: otherFilter.usesAuthenticatedRequestParameters,
185
+ usesUnauthenticatedRequestParameters: otherFilter.usesUnauthenticatedRequestParameters
172
186
  };
173
187
  }
174
188
  else if (isParameterMatchClause(otherFilter)) {
175
- // 3. static, parameterMatch
189
+ // 3. row value = parameterMatch
176
190
  // (bucket.param = 'something') = staticValue
177
191
  // To implement this, we need to ensure the static value here can only be true.
178
- return this.error(`Bucket parameter clauses cannot currently be combined with other operators`, expr);
192
+ return this.error(`Parameter match clauses cannot be used here`, expr);
179
193
  }
180
194
  else {
181
195
  throw new Error('Unexpected');
@@ -185,16 +199,19 @@ export class SqlTools {
185
199
  // Options:
186
200
  // static IN static
187
201
  // parameterValue IN static
188
- if (isStaticRowValueClause(leftFilter) && isStaticRowValueClause(rightFilter)) {
202
+ if (isRowValueClause(leftFilter) && isRowValueClause(rightFilter)) {
203
+ // static1 IN static2
189
204
  return compileStaticOperator(op, leftFilter, rightFilter);
190
205
  }
191
- else if (isParameterValueClause(leftFilter) && isStaticRowValueClause(rightFilter)) {
192
- const param = leftFilter.bucketParameter;
206
+ else if (isParameterValueClause(leftFilter) && isRowValueClause(rightFilter)) {
207
+ // token_parameters.value IN table.some_array
208
+ // bucket.param IN table.some_array
209
+ const inputParam = basicInputParameter(leftFilter);
193
210
  return {
194
211
  error: false,
195
- bucketParameters: [param],
212
+ inputParameters: [inputParam],
196
213
  unbounded: true,
197
- filter(tables) {
214
+ filterRow(tables) {
198
215
  const aValue = rightFilter.evaluate(tables);
199
216
  if (aValue == null) {
200
217
  return MATCH_CONST_FALSE;
@@ -204,27 +221,44 @@ export class SqlTools {
204
221
  throw new Error('Not an array');
205
222
  }
206
223
  return values.map((value) => {
207
- return { [param]: value };
224
+ return { [inputParam.key]: value };
208
225
  });
209
- }
226
+ },
227
+ usesAuthenticatedRequestParameters: leftFilter.usesAuthenticatedRequestParameters,
228
+ usesUnauthenticatedRequestParameters: leftFilter.usesUnauthenticatedRequestParameters
210
229
  };
211
230
  }
212
231
  else if (this.supports_expanding_parameters &&
213
- isStaticRowValueClause(leftFilter) &&
232
+ isRowValueClause(leftFilter) &&
214
233
  isParameterValueClause(rightFilter)) {
215
- const param = `${rightFilter.bucketParameter}[*]`;
234
+ // table.some_value IN token_parameters.some_array
235
+ // This expands into "table_some_value = <value>" for each value of the array.
236
+ // We only support one such filter per query
237
+ const key = `${rightFilter.key}[*]`;
238
+ const inputParam = {
239
+ key: key,
240
+ expands: true,
241
+ filteredRowToLookupValue: (filterParameters) => {
242
+ return filterParameters[key];
243
+ },
244
+ parametersToLookupValue: (parameters) => {
245
+ return rightFilter.lookupParameterValue(parameters);
246
+ }
247
+ };
216
248
  return {
217
249
  error: false,
218
- bucketParameters: [param],
250
+ inputParameters: [inputParam],
219
251
  unbounded: false,
220
- filter(tables) {
252
+ filterRow(tables) {
221
253
  const value = leftFilter.evaluate(tables);
222
254
  if (!isJsonValue(value)) {
223
255
  // Cannot persist, e.g. BLOB
224
256
  return MATCH_CONST_FALSE;
225
257
  }
226
- return [{ [param]: value }];
227
- }
258
+ return [{ [inputParam.key]: value }];
259
+ },
260
+ usesAuthenticatedRequestParameters: rightFilter.usesAuthenticatedRequestParameters,
261
+ usesUnauthenticatedRequestParameters: rightFilter.usesUnauthenticatedRequestParameters
228
262
  };
229
263
  }
230
264
  else {
@@ -232,10 +266,8 @@ export class SqlTools {
232
266
  }
233
267
  }
234
268
  else if (BASIC_OPERATORS.has(op)) {
235
- if (!isStaticRowValueClause(leftFilter) || !isStaticRowValueClause(rightFilter)) {
236
- return this.error(`Operator ${op} is not supported on bucket parameters`, expr);
237
- }
238
- return compileStaticOperator(op, leftFilter, rightFilter);
269
+ const fnImpl = getOperatorFunction(op);
270
+ return this.composeFunction(fnImpl, [leftFilter, rightFilter], [left, right]);
239
271
  }
240
272
  else {
241
273
  return this.error(`Operator not supported: ${op}`, expr);
@@ -243,157 +275,84 @@ export class SqlTools {
243
275
  }
244
276
  else if (expr.type == 'unary') {
245
277
  if (expr.op == 'NOT') {
246
- const filter = this.compileClause(expr.operand);
247
- if (isClauseError(filter)) {
248
- return filter;
249
- }
250
- else if (!isStaticRowValueClause(filter)) {
251
- return this.error('Cannot use NOT on bucket parameter filters', expr);
252
- }
253
- return {
254
- evaluate: (tables) => {
255
- const value = filter.evaluate(tables);
256
- return sqliteNot(value);
257
- },
258
- getType() {
259
- return ExpressionType.INTEGER;
260
- }
261
- };
278
+ const clause = this.compileClause(expr.operand);
279
+ return this.composeFunction(OPERATOR_NOT, [clause], [expr.operand]);
262
280
  }
263
281
  else if (expr.op == 'IS NULL') {
264
- const leftFilter = this.compileClause(expr.operand);
265
- if (isClauseError(leftFilter)) {
266
- return leftFilter;
267
- }
268
- else if (isStaticRowValueClause(leftFilter)) {
269
- // 1. static IS NULL
270
- const nullValue = {
271
- evaluate: () => null,
272
- getType() {
273
- return ExpressionType.INTEGER;
274
- }
275
- };
276
- return compileStaticOperator('IS', leftFilter, nullValue);
277
- }
278
- else if (isParameterValueClause(leftFilter)) {
279
- // 2. param IS NULL
280
- return {
281
- error: false,
282
- bucketParameters: [leftFilter.bucketParameter],
283
- unbounded: false,
284
- filter(tables) {
285
- return [{ [leftFilter.bucketParameter]: null }];
286
- }
287
- };
288
- }
289
- else {
290
- return this.error(`Cannot use IS NULL here`, expr);
291
- }
282
+ const clause = this.compileClause(expr.operand);
283
+ return this.composeFunction(OPERATOR_IS_NULL, [clause], [expr.operand]);
292
284
  }
293
285
  else if (expr.op == 'IS NOT NULL') {
294
- const leftFilter = this.compileClause(expr.operand);
295
- if (isClauseError(leftFilter)) {
296
- return leftFilter;
297
- }
298
- else if (isStaticRowValueClause(leftFilter)) {
299
- // 1. static IS NULL
300
- const nullValue = {
301
- evaluate: () => null,
302
- getType() {
303
- return ExpressionType.INTEGER;
304
- }
305
- };
306
- return compileStaticOperator('IS NOT', leftFilter, nullValue);
307
- }
308
- else {
309
- return this.error(`Cannot use IS NOT NULL here`, expr);
310
- }
286
+ const clause = this.compileClause(expr.operand);
287
+ return this.composeFunction(OPERATOR_IS_NOT_NULL, [clause], [expr.operand]);
311
288
  }
312
289
  else {
313
290
  return this.error(`Operator ${expr.op} is not supported`, expr);
314
291
  }
315
292
  }
316
293
  else if (expr.type == 'call' && expr.function?.name != null) {
294
+ const schema = expr.function.schema; // schema.function()
317
295
  const fn = expr.function.name;
318
- const fnImpl = SQL_FUNCTIONS[fn];
319
- if (fnImpl == null) {
320
- return this.error(`Function '${fn}' is not defined`, expr);
296
+ if (schema == null) {
297
+ // Just fn()
298
+ const fnImpl = SQL_FUNCTIONS[fn];
299
+ if (fnImpl == null) {
300
+ return this.error(`Function '${fn}' is not defined`, expr);
301
+ }
302
+ const argClauses = expr.args.map((arg) => this.compileClause(arg));
303
+ const composed = this.composeFunction(fnImpl, argClauses, expr.args);
304
+ return composed;
321
305
  }
322
- let error = false;
323
- const argExtractors = expr.args.map((arg) => {
324
- const clause = this.compileClause(arg);
325
- if (isClauseError(clause)) {
326
- error = true;
306
+ else if (schema == 'request') {
307
+ // Special function
308
+ if (!this.supports_parameter_expressions) {
309
+ return this.error(`${schema} schema is not available in data queries`, expr);
327
310
  }
328
- else if (!isStaticRowValueClause(clause)) {
329
- error = true;
330
- return this.error(`Bucket parameters are not supported in function call arguments`, arg);
311
+ if (expr.args.length > 0) {
312
+ return this.error(`Function '${schema}.${fn}' does not take arguments`, expr);
331
313
  }
332
- return clause;
333
- });
334
- if (error) {
335
- return { error: true };
336
- }
337
- return {
338
- evaluate: (tables) => {
339
- const args = argExtractors.map((e) => e.evaluate(tables));
340
- return fnImpl.call(...args);
341
- },
342
- getType(schema) {
343
- const argTypes = argExtractors.map((e) => e.getType(schema));
344
- return fnImpl.getReturnType(argTypes);
314
+ if (fn in REQUEST_FUNCTIONS) {
315
+ const fnImpl = REQUEST_FUNCTIONS[fn];
316
+ return {
317
+ key: 'request.parameters()',
318
+ lookupParameterValue(parameters) {
319
+ return fnImpl.call(parameters);
320
+ },
321
+ usesAuthenticatedRequestParameters: fnImpl.usesAuthenticatedRequestParameters,
322
+ usesUnauthenticatedRequestParameters: fnImpl.usesUnauthenticatedRequestParameters
323
+ };
345
324
  }
346
- };
325
+ else {
326
+ return this.error(`Function '${schema}.${fn}' is not defined`, expr);
327
+ }
328
+ }
329
+ else {
330
+ // Unknown function with schema
331
+ return this.error(`Function '${schema}.${fn}' is not defined`, expr);
332
+ }
347
333
  }
348
334
  else if (expr.type == 'member') {
349
335
  const operand = this.compileClause(expr.operand);
350
- if (isClauseError(operand)) {
351
- return operand;
352
- }
353
- else if (!isStaticRowValueClause(operand)) {
354
- return this.error(`Bucket parameters are not supported in member lookups`, expr.operand);
336
+ if (!(typeof expr.member == 'string' && (expr.op == '->>' || expr.op == '->'))) {
337
+ return this.error(`Unsupported member operation ${expr.op}`, expr);
355
338
  }
356
- if (typeof expr.member == 'string' && (expr.op == '->>' || expr.op == '->')) {
357
- return {
358
- evaluate: (tables) => {
359
- const containerString = operand.evaluate(tables);
360
- return jsonExtract(containerString, expr.member, expr.op);
361
- },
362
- getType() {
363
- return ExpressionType.ANY_JSON;
364
- }
365
- };
339
+ const debugArgs = [expr.operand, expr];
340
+ const args = [operand, staticValueClause(expr.member)];
341
+ if (expr.op == '->') {
342
+ return this.composeFunction(OPERATOR_JSON_EXTRACT_JSON, args, debugArgs);
366
343
  }
367
344
  else {
368
- return this.error(`Unsupported member operation ${expr.op}`, expr);
345
+ return this.composeFunction(OPERATOR_JSON_EXTRACT_SQL, args, debugArgs);
369
346
  }
370
347
  }
371
348
  else if (expr.type == 'cast') {
372
349
  const operand = this.compileClause(expr.operand);
373
- if (isClauseError(operand)) {
374
- return operand;
375
- }
376
- else if (!isStaticRowValueClause(operand)) {
377
- return this.error(`Bucket parameters are not supported in cast expressions`, expr.operand);
378
- }
379
350
  const to = expr.to?.name?.toLowerCase();
380
- if (CAST_TYPES.has(to)) {
381
- return {
382
- evaluate: (tables) => {
383
- const value = operand.evaluate(tables);
384
- if (value == null) {
385
- return null;
386
- }
387
- return cast(value, to);
388
- },
389
- getType() {
390
- return ExpressionType.fromTypeText(to);
391
- }
392
- };
393
- }
394
- else {
351
+ const castFn = castOperator(to);
352
+ if (castFn == null) {
395
353
  return this.error(`CAST not supported for '${to}'`, expr);
396
354
  }
355
+ return this.composeFunction(castFn, [operand], [expr.operand]);
397
356
  }
398
357
  else {
399
358
  return this.error(`${expr.type} not supported here`, expr);
@@ -458,10 +417,18 @@ export class SqlTools {
458
417
  }
459
418
  }
460
419
  }
461
- getParameterRef(expr) {
462
- if (this.isParameterRef(expr)) {
463
- return `${expr.table.name}.${expr.name}`;
464
- }
420
+ getParameterRefClause(expr) {
421
+ const table = expr.table.name;
422
+ const column = expr.name;
423
+ return {
424
+ key: `${table}.${column}`,
425
+ lookupParameterValue: (parameters) => {
426
+ const pt = parameters[table];
427
+ return pt?.[column] ?? null;
428
+ },
429
+ usesAuthenticatedRequestParameters: table == 'token_parameters',
430
+ usesUnauthenticatedRequestParameters: table == 'user_parameters'
431
+ };
465
432
  }
466
433
  refHasSchema(ref) {
467
434
  return ref.table?.schema != null;
@@ -488,6 +455,103 @@ export class SqlTools {
488
455
  throw new SqlRuleError(`Undefined table ${ref.table?.name}`, this.sql, ref);
489
456
  }
490
457
  }
458
+ /**
459
+ * Given a function, compile a clause with the function over compiled arguments.
460
+ *
461
+ * For functions with multiple arguments, the following combinations are supported:
462
+ * fn(StaticValueClause, StaticValueClause) => StaticValueClause
463
+ * fn(ParameterValueClause, ParameterValueClause) => ParameterValueClause
464
+ * fn(RowValueClause, RowValueClause) => RowValueClause
465
+ * fn(ParameterValueClause, StaticValueClause) => ParameterValueClause
466
+ * fn(RowValueClause, StaticValueClause) => RowValueClause
467
+ *
468
+ * This is not supported, and will likely never be supported:
469
+ * fn(ParameterValueClause, RowValueClause) => error
470
+ *
471
+ * @param fnImpl The function or operator implementation
472
+ * @param argClauses The compiled argument clauses
473
+ * @param debugArgExpressions The original parsed expressions, for debug info only
474
+ * @returns a compiled function clause
475
+ */
476
+ composeFunction(fnImpl, argClauses, debugArgExpressions) {
477
+ let argsType = 'static';
478
+ for (let i = 0; i < argClauses.length; i++) {
479
+ const debugArg = debugArgExpressions[i];
480
+ const clause = argClauses[i];
481
+ if (isClauseError(clause)) {
482
+ // Return immediately on error
483
+ return clause;
484
+ }
485
+ else if (isStaticValueClause(clause)) {
486
+ // argsType unchanged
487
+ }
488
+ else if (isParameterValueClause(clause)) {
489
+ if (!this.supports_parameter_expressions) {
490
+ return this.error(`Cannot use bucket parameters in expressions`, debugArg);
491
+ }
492
+ if (argsType == 'static' || argsType == 'param') {
493
+ argsType = 'param';
494
+ }
495
+ else {
496
+ return this.error(`Cannot use table values and parameters in the same clauses`, debugArg);
497
+ }
498
+ }
499
+ else if (isRowValueClause(clause)) {
500
+ if (argsType == 'static' || argsType == 'row') {
501
+ argsType = 'row';
502
+ }
503
+ else {
504
+ return this.error(`Cannot use table values and parameters in the same clauses`, debugArg);
505
+ }
506
+ }
507
+ else {
508
+ return this.error(`Parameter match clauses cannot be used here`, debugArg);
509
+ }
510
+ }
511
+ if (argsType == 'row' || argsType == 'static') {
512
+ return {
513
+ evaluate: (tables) => {
514
+ const args = argClauses.map((e) => e.evaluate(tables));
515
+ return fnImpl.call(...args);
516
+ },
517
+ getType(schema) {
518
+ const argTypes = argClauses.map((e) => e.getType(schema));
519
+ return fnImpl.getReturnType(argTypes);
520
+ }
521
+ };
522
+ }
523
+ else if (argsType == 'param') {
524
+ const argStrings = argClauses.map((e) => e.key);
525
+ const name = `${fnImpl.debugName}(${argStrings.join(',')})`;
526
+ const usesAuthenticatedRequestParameters = argClauses.find((clause) => isParameterValueClause(clause) && clause.usesAuthenticatedRequestParameters) !=
527
+ null;
528
+ const usesUnauthenticatedRequestParameters = argClauses.find((clause) => isParameterValueClause(clause) && clause.usesUnauthenticatedRequestParameters) !=
529
+ null;
530
+ return {
531
+ key: name,
532
+ lookupParameterValue: (parameters) => {
533
+ const args = argClauses.map((e) => {
534
+ if (isParameterValueClause(e)) {
535
+ return e.lookupParameterValue(parameters);
536
+ }
537
+ else if (isStaticValueClause(e)) {
538
+ return e.value;
539
+ }
540
+ else {
541
+ throw new Error('unreachable condition');
542
+ }
543
+ });
544
+ return fnImpl.call(...args);
545
+ },
546
+ usesAuthenticatedRequestParameters,
547
+ usesUnauthenticatedRequestParameters
548
+ };
549
+ }
550
+ else {
551
+ throw new Error('unreachable condition');
552
+ }
553
+ }
554
+ parameterFunction() { }
491
555
  }
492
556
  function isStatic(expr) {
493
557
  return ['integer', 'string', 'numeric', 'boolean', 'null'].includes(expr.type);
@@ -503,4 +567,33 @@ function staticValue(expr) {
503
567
  return expr.value;
504
568
  }
505
569
  }
570
+ function staticValueClause(value) {
571
+ return {
572
+ value: value,
573
+ // RowValueClause compatibility
574
+ evaluate: () => value,
575
+ getType() {
576
+ return ExpressionType.fromTypeText(sqliteTypeOf(value));
577
+ },
578
+ // ParamterValueClause compatibility
579
+ key: JSONBig.stringify(value),
580
+ lookupParameterValue(_parameters) {
581
+ return value;
582
+ },
583
+ usesAuthenticatedRequestParameters: false,
584
+ usesUnauthenticatedRequestParameters: false
585
+ };
586
+ }
587
+ function basicInputParameter(clause) {
588
+ return {
589
+ key: clause.key,
590
+ expands: false,
591
+ filteredRowToLookupValue: (filterParameters) => {
592
+ return filterParameters[clause.key];
593
+ },
594
+ parametersToLookupValue: (parameters) => {
595
+ return clause.lookupParameterValue(parameters);
596
+ }
597
+ };
598
+ }
506
599
  //# sourceMappingURL=sql_filters.js.map