@carbonorm/carbonnode 3.9.3 → 3.9.4

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.
@@ -187,10 +187,30 @@ export abstract class ConditionBuilder<
187
187
  this.OPERATORS.has(column) &&
188
188
  Array.isArray(op)
189
189
  ) {
190
+ // Helper to serialize operand which may be a qualified identifier or a nested function array
191
+ const serializeOperand = (arg: any): string => {
192
+ const identifierPathRegex = /^[A-Za-z_][A-Za-z0-9_]*\.[A-Za-z_][A-Za-z0-9_]*$/;
193
+ if (Array.isArray(arg)) {
194
+ // Delegate to aggregate builder to handle nested functions/params
195
+ // @ts-ignore - buildAggregateField is defined upstream in AggregateBuilder
196
+ return this.buildAggregateField(arg, params);
197
+ }
198
+ if (typeof arg === 'string') {
199
+ if (identifierPathRegex.test(arg)) {
200
+ this.assertValidIdentifier(arg, 'WHERE argument');
201
+ return arg;
202
+ }
203
+ return arg;
204
+ }
205
+ return String(arg);
206
+ };
207
+
190
208
  if (column === C6C.ST_DISTANCE_SPHERE) {
191
209
  const [col1, col2] = op;
192
210
  const threshold = Array.isArray(value) ? value[0] : value;
193
- return `ST_Distance_Sphere(${col1}, ${col2}) < ${this.addParam(params, '', threshold)}`;
211
+ const left = serializeOperand(col1);
212
+ const right = serializeOperand(col2);
213
+ return `ST_Distance_Sphere(${left}, ${right}) < ${this.addParam(params, '', threshold)}`;
194
214
  }
195
215
  if ([
196
216
  C6C.ST_CONTAINS,
@@ -203,7 +223,9 @@ export abstract class ConditionBuilder<
203
223
  C6C.ST_TOUCHES
204
224
  ].includes(column)) {
205
225
  const [geom1, geom2] = op;
206
- return `${column}(${geom1}, ${geom2})`;
226
+ const left = serializeOperand(geom1);
227
+ const right = serializeOperand(geom2);
228
+ return `${column}(${left}, ${right})`;
207
229
  }
208
230
  }
209
231
 
@@ -308,6 +330,24 @@ export abstract class ConditionBuilder<
308
330
  const numeric = entries.filter(([k]) => !isNaN(Number(k)));
309
331
 
310
332
  const processEntry = (k: string, v: any) => {
333
+ // Operator-as-key handling, e.g., { [C6C.ST_DISTANCE_SPHERE]: [arg1, arg2, threshold] }
334
+ if (typeof k === 'string' && this.OPERATORS.has(k) && Array.isArray(v)) {
335
+ if (k === C6C.ST_DISTANCE_SPHERE) {
336
+ // Accept either [arg1, arg2, threshold] or [[arg1, arg2], threshold]
337
+ let args: any[];
338
+ let threshold: any;
339
+ if (Array.isArray(v[0]) && v.length >= 2) {
340
+ args = v[0];
341
+ threshold = v[1];
342
+ } else {
343
+ args = v.slice(0, 2);
344
+ threshold = v[2];
345
+ }
346
+ subParts.push(addCondition(k, args as any, threshold));
347
+ return;
348
+ }
349
+ }
350
+
311
351
  if (typeof v === 'object' && v !== null && Object.keys(v).length === 1) {
312
352
  const [op, val] = Object.entries(v)[0];
313
353
  subParts.push(addCondition(k, op, val));