Repodb.Query
repodb · API reference
type join_kind =
| Inner
| Left
| Right
| FullComposable SQL query builder with phantom-typed query kinds.
('result, 'kind) t represents a SELECT, INSERT, UPDATE, or DELETE query. The phantom 'kind prevents passing an update query to a select executor and lets Repo.Make expose separate execution functions for each query type.
Query construction is pipeline-friendly:
let users_by_domain domain =
Query.from User.table
|> Query.select Expr.(column User.id ** column User.email)
|> Query.where Expr.(Expr.like (column User.email) ("%@" ^ domain))
|> Query.order_by Expr.(column User.inserted_at) ~direction:Query.Desc
|> Query.limit 50For inserts, use Query_values to build heterogeneous typed rows:
let q =
Query.insert_into User.table
|> Query.values
[ User.email; User.name; User.active ]
[ Query_values.values3 "ada@example.com" "Ada" true ]
|> Query.returning Expr.(column User.id)where clauses are combined with AND. Use or_where to combine the most recent predicate with OR. Repeated order_by, group_by, and join calls preserve the order in which they were added when rendered.
to_sql_params is the preferred renderer for execution because it returns SQL plus driver parameters. to_sql is useful for debugging and test assertions. Dialect-specific rendering handles placeholder style, upsert syntax, JSON expressions, and RETURNING support checks.
type order_direction =
| Asc
| Desctype select_querytype insert_querytype update_querytype delete_querytype ('result, 'kind) t = {
query_type : query_type;
table : Schema.table;
select : Expr.wrapped_expr list option;
wheres : bool Expr.t list;
joins : join list;
order_by : (Expr.wrapped_expr * order_direction) list;
group_by : Expr.wrapped_expr list;
having : bool Expr.t list;
limit : int option;
offset : int option;
distinct : bool;
returning : Expr.wrapped_expr list option;
set_values : (string * Expr.wrapped_expr) list;
insert_columns : string list;
insert_values : Expr.wrapped_expr list list;
conflict_target : string list option;
conflict_action : conflict_action option;
}and query_type =
| Select
| Insert
| Update
| Deleteand join = {
kind : join_kind;
table : Schema.table;
on : Expr.wrapped_expr;
}and conflict_action =
| DoNothing
| DoUpdate of (string * Expr.wrapped_expr) listval empty_query : Schema.table -> query_type -> ('a, 'b) tval from : Schema.table -> ('a, 'b) tval insert_into : Schema.table -> ('a, 'b) tval update : Schema.table -> ('a, 'b) tval delete_from : Schema.table -> ('a, 'b) tval select : 'a Expr.expr_list -> ('b, 'c) t -> ('d, 'e) tval select_all : ('a, 'b) t -> ('c, 'd) tval where : bool Expr.t -> ('a, 'b) t -> ('c, 'd) tval and_where : bool Expr.t -> ('a, 'b) t -> ('c, 'd) tval or_where : bool Expr.t -> ('a, 'b) t -> ('c, 'd) tval join :
?kind:join_kind ->
on:'a Expr.t ->
Schema.table ->
('b, 'c) t ->
('d, 'e) tval left_join : on:'a Expr.t -> Schema.table -> ('b, 'c) t -> ('d, 'e) tval right_join : on:'a Expr.t -> Schema.table -> ('b, 'c) t -> ('d, 'e) tval inner_join : on:'a Expr.t -> Schema.table -> ('b, 'c) t -> ('d, 'e) tval full_join : on:'a Expr.t -> Schema.table -> ('b, 'c) t -> ('d, 'e) tval order_by :
?direction:order_direction ->
'a Expr.t ->
('b, 'c) t ->
('d, 'e) tval asc : 'a Expr.t -> ('b, 'c) t -> ('d, 'e) tval desc : 'a Expr.t -> ('b, 'c) t -> ('d, 'e) tval group_by : 'a Expr.expr_list -> ('b, 'c) t -> ('d, 'e) tval having : bool Expr.t -> ('a, 'b) t -> ('c, 'd) tval limit : int -> ('a, 'b) t -> ('c, 'd) tval offset : int -> ('a, 'b) t -> ('c, 'd) tval distinct : ('a, 'b) t -> ('c, 'd) tval returning : 'a Expr.expr_list -> ('b, 'c) t -> ('d, 'e) tval set : ('a, 'b) Field.t -> 'c Expr.t -> ('d, 'e) t -> ('f, 'g) tval values :
('a, 'b) Field.t list ->
'c Expr.t list list ->
('d, 'e) t ->
('f, 'g) tval on_conflict_do_nothing :
?target:('a, 'b) Field.t list ->
('c, 'd) t ->
('e, 'f) tval on_conflict_do_update :
target:('a, 'b) Field.t list ->
set:(('c, 'd) Field.t * 'e Expr.t) list ->
('f, 'g) t ->
('h, 'i) tval join_kind_to_sql : join_kind -> stringval direction_to_sql : order_direction -> stringval wrapped_to_sql : dialect:Driver.dialect -> Expr.wrapped_expr -> stringval non_empty_clause : string -> ('a list -> string) -> 'a list -> stringval render_in_order : ('a -> 'b) -> 'a list -> 'b listval limit_clause : int option -> stringval offset_clause : int option -> stringval join_clauses : ('a -> 'b) -> 'a list -> 'b listval order_clause : ('a -> string) -> ('a * order_direction) list -> stringval where_clause : ('a -> string) -> 'a list -> stringval group_clause : ('a -> string) -> 'a list -> stringval having_clause : ('a -> string) -> 'a list -> stringval returning_clause : ('a -> string) -> 'a list option -> stringval values_clause : ('a -> string) -> 'a list list -> stringval render_parts : string list -> stringval mysql_noop_update : string list -> stringval conflict_clause_to_sql :
dialect:Driver.dialect ->
insert_columns:string list ->
conflict_target:string list option ->
conflict_action:conflict_action option ->
render_expr:(Expr.wrapped_expr -> string) ->
stringval wrapped_to_sql_params :
ctx:Expr.param_ctx ->
Buffer.t ->
Expr.wrapped_expr ->
unitval to_sql : ?dialect:Driver.dialect -> ('a, 'b) t -> stringval to_sql_params :
?dialect:Driver.dialect ->
('a, 'b) t ->
string * Driver.Value.t array