import type { SQLInputValue } from "node:sqlite"; import type { BrowseCursorPayload } from "./browse-cursor.js"; import type { ResolvedBrowseSort } from "./browse-order.js"; import type { BrowseFilter } from "./types.js"; /** * Append one normalized filter to a SQLite WHERE list. Column names come from this * switch and nowhere else; every value is bound. * * Text matching uses literal substring primitives (`instr`, `substr`) rather than * LIKE, so `%`, `_` and `\` in a user's search term need no escaping and can never * change the predicate. Case-insensitivity is `lower()`, which folds ASCII only in * SQLite without ICU: `lower('CAFÉ')` is `'cafÉ'` here and `'café'` in Postgres, so a * non-ASCII needle matches on one backend and misses on the other. The conformance * suite asserts ONE reading for both stores and therefore cannot pin that divergence — * every fixture there is ASCII, and this comment is the whole documentation of it. */ export declare function appendSqliteBrowseFilter(filter: BrowseFilter, where: string[], params: SQLInputValue[]): void; /** * Everything strictly after `cursor` in `order`, as a WHERE fragment. * * Row-value comparisons cannot express mixed asc/desc, so this is the expanded * OR-chain — plus a REDUNDANT leading range guard. The guard is logically implied by * the chain and is still mandatory: it is what lets the planner seek the leading index * column instead of scanning the whole index (0.54 ms vs 22.8 ms at 1M rows). * * Parameters are pushed in the exact textual order they appear, so the caller can * concatenate this fragment after its filter clauses without renumbering. */ export declare function sqliteKeysetWhere(order: readonly ResolvedBrowseSort[], cursor: BrowseCursorPayload, params: SQLInputValue[]): string; //# sourceMappingURL=sqlite-browse-sql.d.ts.map