import type { ColumnFilter } from '@dudousxd/nestjs-filter';
import { Column, type SQL } from 'drizzle-orm';
/** The SQL dialect a query renders for — decides LIKE/ILIKE, casts and escapes. */
export type DrizzleDialect = 'postgres' | 'mysql' | 'sqlite';
/**
 * What an operator compares: a real column (its type drives value coercion and
 * the `isEmpty` shape) or a developer-provided SQL expression (a computed field,
 * a correlated aggregate subquery).
 */
export type OperatorTarget = Column | SQL;
/**
 * Coerces a client value to what the column's driver encoder expects.
 *
 * Drizzle binds a comparison value THROUGH the column (`mapToDriverValue`), so
 * a value of the wrong JS type is not merely compared loosely — it can break
 * the encoder: a `timestamp` column in `mode: 'date'` calls `.toISOString()` on
 * whatever it is handed, and a SQLite boolean encodes the string `'false'` as
 * truthy `1`. Query strings and decoded cursors deliver exactly those strings.
 * Values that do not parse are passed through untouched (the database then
 * reports the mismatch, rather than this layer inventing a value).
 */
export declare function coerceValue(column: Column, value: unknown): unknown;
/**
 * Builds a LIKE predicate. The pattern is always a bound parameter, already
 * escaped with {@link escapeLike} (backslash escapes). Postgres and MySQL treat
 * backslash as the default LIKE escape; SQLite has NO default escape character,
 * so the clause is spelled out there — without it `%` in user input would still
 * be a wildcard.
 *
 * Case-insensitive matching uses `ILIKE` on Postgres (index-friendly with a
 * trigram index) and `lower(x) LIKE lower(p)` elsewhere.
 */
export declare function likeCondition(target: OperatorTarget, pattern: string, dialect: DrizzleDialect, opts?: {
    caseInsensitive?: boolean;
    negate?: boolean;
}): SQL;
/**
 * Translates ONE `ColumnFilter` operator into a drizzle SQL condition over
 * `target`. Every client value is a bound parameter (drizzle's `eq`/`gt`/…
 * bind through the column's encoder); nothing client-supplied is inlined.
 *
 * `isEmpty`/`isNotEmpty` compare against `''` only for string columns — `col =
 * ''` on a date or integer column is a type error on Postgres/MySQL — and
 * collapse to the NULL check everywhere else.
 */
export declare function buildOperatorCondition(target: OperatorTarget, filter: ColumnFilter, dialect: DrizzleDialect, 
/**
 * For an expression target whose values are those of a known column (a
 * `MIN`/`MAX` over a child column), bind comparison values through that
 * column's encoder — so a date compares as the column stores dates (an epoch
 * integer on SQLite, a timestamp on Postgres) rather than as a raw JS value.
 */
encoder?: Column): SQL;
/**
 * Resolves a leaf filter to its condition — the adapter supplies this, since it
 * knows how to reach a field (a root column, or a relation path that needs an
 * `EXISTS` subquery). Returning `undefined` drops the leaf (an unresolvable
 * field never reaches SQL).
 */
export type LeafResolver = (filter: ColumnFilter) => SQL | undefined;
/**
 * Folds a list of `ColumnFilter`s (with arbitrarily nested `AND`/`OR`) into one
 * condition: top-level entries are ANDed; a node contributes
 * `base AND (...AND) AND (OR₁ OR OR₂ …)`, the same grouping the MikroORM
 * adapter emits. A pure group node (no `field`) contributes only its children.
 */
export declare function buildColumnFiltersCondition(filters: ColumnFilter[], leaf: LeafResolver): SQL | undefined;
//# sourceMappingURL=operator-resolver.d.ts.map