* Builds SQL clauses from nested filters and joins them with the specified operator. * * @example * // OR operator * buildLogicalClause( * [{ status: 'active' }, { status: 'pending' }], * 'user_table_rows', * 'OR' * ) * // Returns: (data @> '{"status":"active"}'::jsonb OR data @> '{"s
( subFilters: Filter[], tableName: string, operator: 'OR' | 'AND', columnTypeMap: ColumnTypeMap )
| 433 | * // Returns: ((data->>'age')::numeric >= 18 AND data @> '{"verified":true}'::jsonb) |
| 434 | */ |
| 435 | function buildLogicalClause( |
| 436 | subFilters: Filter[], |
| 437 | tableName: string, |
| 438 | operator: 'OR' | 'AND', |
| 439 | columnTypeMap: ColumnTypeMap |
| 440 | ): SQL | undefined { |
| 441 | const clauses: SQL[] = [] |
| 442 | for (const subFilter of subFilters) { |
| 443 | const clause = buildFilterClauseInternal(subFilter, tableName, columnTypeMap) |
| 444 | if (clause) { |
| 445 | clauses.push(clause) |
| 446 | } |
| 447 | } |
| 448 | |
| 449 | if (clauses.length === 0) return undefined |
| 450 | if (clauses.length === 1) return clauses[0] |
| 451 | |
| 452 | return sql`(${sql.join(clauses, sql.raw(` ${operator} `))})` |
| 453 | } |
| 454 | |
| 455 | /** Builds JSONB containment clause: `data @> '{"field": value}'::jsonb` (uses GIN index) */ |
| 456 | function buildContainmentClause(tableName: string, field: string, value: JsonValue): SQL { |
no test coverage detected