Repodb.Expr

repodb · API reference

type json_path_elem = 
  | JsonKey of string
  | JsonIdx of int

Type-indexed SQL expressions for filters, projections, updates, and inserts.

An ('a t) is an SQL expression that evaluates to an OCaml value of type 'a. Expressions are used by Query, JSON helpers, and update/insert builders. Constructors preserve enough type information to catch many query mistakes before SQL is generated.

Build expressions from fields and literals:

let active_users =
    Query.from User.table
    |> Query.where Expr.(column User.active = bool true)
    |> Query.where Expr.(column User.age >= int 18)
    |> Query.order_by Expr.(lower (column User.email))

The infix operators in this module intentionally shadow Stdlib comparison and arithmetic operators. Open Expr locally, as above, instead of at the top of a large module.

to_sql_params renders parameterized SQL fragments and returns the collected Driver.Value.t parameters. to_sql is convenient for DDL tests and generated SQL inspection; prefer parameterized rendering when user input is involved.

JSON functions render backend-specific syntax for PostgreSQL, SQLite, and MySQL. Some operators are not available everywhere; unsupported features raise Error.Unsupported_dialect_feature with a suggested alternative when one exists.

raw and subquery are escape hatches. They are not parameterized and should be limited to trusted SQL snippets, generated SQL, or tests.

type json_path = json_path_elem list
type json_extract_mode = 
  | AsJson
  | AsText
type 'a t = 
  | Lit : 'a * 'a Types.t -> 'a t
  | Column : ('record, 'a) Field.t -> 'a t
  | Null : 'a Types.t -> 'a option t
  | Some : 'a t -> 'a option t
  | Binop : string * 'a t * 'b t * 'c Types.t -> 'c t
  | Unop : string * 'a t * 'b Types.t -> 'b t
  | Func : string * wrapped list * 'a Types.t -> 'a t
  | Raw : string -> 'a t
  | Param : int * 'a Types.t -> 'a t
  | Cast : 'a t * 'b Types.t -> 'b t
  | Case : (bool t * 'a t) list * 'a t option * 'a Types.t -> 'a t
  | Between : 'a t * 'a t * 'a t -> bool t
  | InList : 'a t * 'a t list -> bool t
  | Subquery : string -> 'a t
  | JsonGet : ('r, string) Field.t * json_path * json_extract_mode -> string t
  | JsonContains : ('r, string) Field.t * string -> bool t
  | JsonContainedBy : ('r, string) Field.t * string -> bool t
  | JsonHasKey : ('r, string) Field.t * string -> bool t
  | JsonHasPath : ('r, string) Field.t * json_path -> bool t
  | JsonHasAnyKeys : ('r, string) Field.t * string list -> bool t
  | JsonHasAllKeys : ('r, string) Field.t * string list -> bool t
  | JsonArrayLength : ('r, string) Field.t * json_path option -> int t
  | JsonTypeof : ('r, string) Field.t * json_path option -> string t
and wrapped = 
  | Wrapped : 'a t -> wrapped
val int : int -> int t
val int32 : int32 -> int32 t
val int64 : int64 -> int64 t
val float : float -> float t
val string : string -> string t
val bool : bool -> bool t
val null : 'a Types.t -> 'a option t
val some : 'a t -> 'a option t
val int_opt : int Option.t -> int option t
val int32_opt : int32 Option.t -> int32 option t
val int64_opt : int64 Option.t -> int64 option t
val float_opt : float Option.t -> float option t
val string_opt : string Option.t -> string option t
val bool_opt : bool Option.t -> bool option t
val column : ('a, 'b) Field.t -> 'b t
val raw : string -> 'a t
val param : int -> 'a Types.t -> 'a t
val cast : 'a t -> 'b Types.t -> 'b t
val subquery : string -> 'a t
val between : 'a t -> 'a t -> 'a t -> bool t
val in_list : 'a t -> 'a t list -> bool t
val case : (bool t * 'a t) list -> else_:'a t -> 'a Types.t -> 'a t
val case_no_else : (bool t * 'a t) list -> 'a Types.t -> 'a t
val coalesce : 'a t list -> 'b Types.t -> 'b t
val nullif : 'a t -> 'b t -> 'c Types.t -> 'c option t
val greatest : 'a t list -> 'b Types.t -> 'b t
val least : 'a t list -> 'b Types.t -> 'b t
val count : 'a t -> int64 t
val count_distinct : 'a t -> int64 t
val count_all : int64 t
val sum : 'a t -> int64 t
val avg : 'a t -> float t
val max_ : 'a t -> 'b Types.t -> 'b t
val min_ : 'a t -> 'b Types.t -> 'b t
val lower : 'a t -> string t
val upper : 'a t -> string t
val length : 'a t -> int t
val trim : 'a t -> string t
val ltrim : 'a t -> string t
val rtrim : 'a t -> string t
val concat : 'a t list -> string t
val concat_ws : string -> 'a t list -> string t
val substring : 'a t -> from:int -> for_:int -> string t
val replace : 'a t -> from:string -> to_:string -> string t
val left : 'a t -> int -> string t
val right : 'a t -> int -> string t
val now : unit -> Ptime.t t
val current_date : Ptime.date t
val current_timestamp : Ptime.t t
val date_part : string -> 'a t -> float t
val extract : string -> 'a t -> float t
val abs_ : 'a t -> int t
val ceil : 'a t -> float t
val floor : 'a t -> float t
val round : 'a t -> float t
val sqrt : 'a t -> float t
val power : 'a t -> 'b t -> float t
val random : float t
val gen_random_uuid : Uuidm.t t
type wrapped_expr = 
  | W : 'a t -> wrapped_expr
type 'a expr_list = 
  | [] : unit expr_list
  | :: : 'a t * 'b expr_list -> ('a * 'b) expr_list
val expr_list_to_list : 'a. 'a expr_list -> wrapped_expr list
val escape_string_buf : Buffer.t -> string -> unit
val escape_string : string -> string
val lit_to_sql_buf : 'a. Buffer.t -> 'a -> 'a Types.t -> unit
val json_path_to_pg : Buffer.t -> json_path_elem list -> unit
val json_path_to_sqlite : Buffer.t -> json_path_elem list -> unit
val json_path_to_mysql : Buffer.t -> json_path_elem list -> unit
type param_ctx = {
  dialect : Driver.dialect;
  mutable next_idx : int;
  params : Driver.Value.t Queue.t;
}
val create_param_ctx : Driver.dialect -> param_ctx
val add_param : param_ctx -> Driver.Value.t -> string
val unsupported_json_contains : dialect:Driver.dialect -> 'a
val unsupported_json_feature : feature:string -> dialect:Driver.dialect -> 'a
val json_path_writer : 
  Driver.dialect ->
  Buffer.t ->
  json_path_elem list ->
  unit
val json_contains_path_sql : 
  Buffer.t ->
  ('a, 'b) Field.t ->
  string ->
  json_path_elem list list ->
  unit
val emit_json_get : 
  dialect:Driver.dialect ->
  Buffer.t ->
  ('a, 'b) Field.t ->
  json_path_elem list ->
  json_extract_mode ->
  unit
val emit_json_contains : 
  dialect:Driver.dialect ->
  Buffer.t ->
  ('a, 'b) Field.t ->
  string ->
  unit
val emit_json_contains_params : 
  dialect:Driver.dialect ->
  ctx:param_ctx ->
  Buffer.t ->
  ('a, 'b) Field.t ->
  string ->
  unit
val emit_json_contained_by : 
  dialect:Driver.dialect ->
  Buffer.t ->
  ('a, 'b) Field.t ->
  string ->
  unit
val emit_json_contained_by_params : 
  dialect:Driver.dialect ->
  ctx:param_ctx ->
  Buffer.t ->
  ('a, 'b) Field.t ->
  string ->
  unit
val emit_json_has_key : 
  dialect:Driver.dialect ->
  Buffer.t ->
  ('a, 'b) Field.t ->
  string ->
  unit
val emit_json_has_key_params : 
  dialect:Driver.dialect ->
  ctx:param_ctx ->
  Buffer.t ->
  ('a, 'b) Field.t ->
  string ->
  unit
val emit_json_has_path : 
  dialect:Driver.dialect ->
  Buffer.t ->
  ('a, 'b) Field.t ->
  json_path_elem list ->
  unit
val emit_json_has_keys : 
  dialect:Driver.dialect ->
  Buffer.t ->
  ('a, 'b) Field.t ->
  string ->
  string list ->
  unit
val emit_json_has_keys_params : 
  dialect:Driver.dialect ->
  ctx:param_ctx ->
  Buffer.t ->
  ('a, 'b) Field.t ->
  string ->
  string list ->
  unit
val emit_json_array_length : 
  dialect:Driver.dialect ->
  Buffer.t ->
  ('a, 'b) Field.t ->
  json_path_elem list option ->
  unit
val emit_json_typeof : 
  dialect:Driver.dialect ->
  Buffer.t ->
  ('a, 'b) Field.t ->
  json_path_elem list option ->
  unit
val to_sql_buf : 'a. dialect:Driver.dialect -> Buffer.t -> 'a t -> unit
val to_sql : ?dialect:Driver.dialect -> 'a t -> string
val lit_to_value : 'a. 'a -> 'a Types.t -> Driver.Value.t
val to_sql_params_buf : 'a. ctx:param_ctx -> Buffer.t -> 'a t -> unit
val to_sql_params : 
  ?dialect:Driver.dialect ->
  'a t ->
  string * Driver.Value.t array
val wrapped_to_sql_params : ctx:param_ctx -> Buffer.t -> wrapped_expr -> unit
val lit_to_sql : 'a. 'a -> 'a Types.t -> string
val eq : 'a t -> 'b t -> bool t
val neq : 'a t -> 'b t -> bool t
val lt : 'a t -> 'b t -> bool t
val gt : 'a t -> 'b t -> bool t
val lte : 'a t -> 'b t -> bool t
val gte : 'a t -> 'b t -> bool t
val and_ : 'a t -> 'b t -> bool t
val or_ : 'a t -> 'b t -> bool t
val not_ : 'a t -> bool t
val is_null : 'a t -> bool t
val is_not_null : 'a t -> bool t
val add : 'a t -> 'b t -> int t
val sub : 'a t -> 'b t -> int t
val mul : 'a t -> 'b t -> int t
val div : 'a t -> 'b t -> int t
val mod_ : 'a t -> 'b t -> int t
val addf : 'a t -> 'b t -> float t
val subf : 'a t -> 'b t -> float t
val mulf : 'a t -> 'b t -> float t
val divf : 'a t -> 'b t -> float t
val not_in_list : 'a t -> 'a t list -> bool t
val like : 'a t -> string -> bool t
val ilike : 'a t -> string -> bool t
val similar_to : 'a t -> string -> bool t
val regexp : 'a t -> string -> bool t
val regexp_i : 'a t -> string -> bool t
val json_key : string -> json_path_elem
val json_idx : int -> json_path_elem
val json_path : string list -> json_path_elem list
val json_get : 
  ('a, string) Field.t ->
  json_path ->
  json_extract_mode ->
  string t
val json_contains : ('a, string) Field.t -> string -> bool t
val json_contained_by : ('a, string) Field.t -> string -> bool t
val json_has_key : ('a, string) Field.t -> string -> bool t
val json_has_path : ('a, string) Field.t -> json_path -> bool t
val json_has_any_keys : ('a, string) Field.t -> string list -> bool t
val json_has_all_keys : ('a, string) Field.t -> string list -> bool t
val json_array_length : ('a, string) Field.t -> json_path option -> int t
val json_typeof : ('a, string) Field.t -> json_path option -> string t
val (=) : 'a t -> 'b t -> bool t
val (<>) : 'a t -> 'b t -> bool t
val (<) : 'a t -> 'b t -> bool t
val (>) : 'a t -> 'b t -> bool t
val (<=) : 'a t -> 'b t -> bool t
val (>=) : 'a t -> 'b t -> bool t
val (&&) : 'a t -> 'b t -> bool t
val (||) : 'a t -> 'b t -> bool t
val (+) : 'a t -> 'b t -> int t
val (-) : 'a t -> 'b t -> int t
val (*) : 'a t -> 'b t -> int t
val (/) : 'a t -> 'b t -> int t
val (mod) : 'a t -> 'b t -> int t
val (+.) : 'a t -> 'b t -> float t
val (-.) : 'a t -> 'b t -> float t
val (*.) : 'a t -> 'b t -> float t
val (/.) : 'a t -> 'b t -> float t