import { Cursor, OrderBy } from './Cursor.js';
import { ExprData } from './ExprData.js';
import { Projection } from './Projection.js';
import type { Selection } from './Selection.js';
/** Expression or value of type T */
export type EV<T> = Expr<T> | T;
export interface Expr<T> extends ExprI<T> {
}
export declare function Expr<T>(expr: ExprData): Expr<T>;
export interface ExprI<T> {
    [Expr.Data]: ExprData;
    [Expr.IsExpr]: boolean;
}
export declare class ExprI<T> {
    constructor(expr: ExprData);
    asc(): OrderBy;
    desc(): OrderBy;
    not(): Expr<boolean>;
    or(this: Expr<boolean>, ...that: Array<EV<boolean>>): Expr<boolean>;
    and(this: Expr<boolean>, ...that: Array<EV<boolean>>): Expr<boolean>;
    is(that: EV<T>): Expr<boolean>;
    isConstant(value: T): boolean;
    isNot(that: EV<T>): Expr<boolean>;
    isNull(): Expr<boolean>;
    isNotNull(): Expr<boolean>;
    isIn(that: EV<ReadonlyArray<T>> | Cursor.Find<T>): Expr<boolean>;
    isNotIn(that: EV<ReadonlyArray<T>> | Cursor.Find<T>): Expr<boolean>;
    isGreater(that: EV<any>): Expr<boolean>;
    isGreaterOrEqual(that: EV<any>): Expr<boolean>;
    isLess(that: EV<any>): Expr<boolean>;
    isLessOrEqual(that: EV<any>): Expr<boolean>;
    add(this: Expr<number>, that: EV<number>): Expr<number>;
    substract(this: Expr<number>, that: EV<number>): Expr<number>;
    multiply(this: Expr<number>, that: EV<number>): Expr<number>;
    remainder(this: Expr<number>, that: EV<number>): Expr<number>;
    divide(this: Expr<number>, that: EV<number>): Expr<number>;
    concat(this: Expr<string>, that: EV<string>): Expr<string>;
    like(this: Expr<string>, that: EV<string>): Expr<boolean>;
    when<S extends Projection>(expr: EV<T>, select: S): CaseBuilder<T, Projection.Infer<S>>;
    at<T>(this: Expr<Array<T>>, index: number): Expr<T | null>;
    includes<T>(this: Expr<Array<T>>, value: EV<T>): Expr<boolean>;
    sure(): Expr<NonNullable<T>>;
    get<T>(name: string): Expr<T>;
    toJSON(): ExprData;
}
export declare class CaseBuilder<T, Res> {
    protected expr: Expr<T>;
    protected cases: Array<[ExprData, Selection]>;
    constructor(expr: Expr<T>, cases?: Array<[ExprData, Selection]>);
    when<S extends Projection>(expr: EV<T>, select: S): CaseBuilder<T, Res | Projection.Infer<S>>;
    orElse<S extends Projection>(select: S): Expr<Res | Projection.Infer<S>>;
    end(): Expr<Res>;
}
export declare function and(...conditions: Array<EV<boolean>>): Expr<boolean>;
export declare function or(...conditions: Array<EV<boolean>>): Expr<boolean>;
export declare namespace Expr {
    const Data: unique symbol;
    const IsExpr: unique symbol;
    const ToExpr: unique symbol;
    const NULL: Expr<null>;
    function create<T>(input: EV<T>): Expr<T>;
    function hasExpr<T>(input: any): input is {
        [Expr.ToExpr](): Expr<T>;
    };
    function isExpr<T>(input: any): input is Expr<T>;
}
