Repodb.Types

repodb · API reference

type _ t = 
  | Int : int t
  | Int32 : int32 t
  | Int64 : int64 t
  | Float : float t
  | String : string t
  | Bool : bool t
  | Blob : string t
  | Ptime : Ptime.t t
  | Pdate : Ptime.date t
  | Uuid : Uuidm.t t
  | Json : string t
  | Option : 'a t -> 'a option t
  | Array : 'a t -> 'a list t
  | Tup2 : 'a t * 'b t -> ('a * 'b) t
  | Tup3 : 'a t * 'b t * 'c t -> ('a * 'b * 'c) t
  | Tup4 : 'a t * 'b t * 'c t * 'd t -> ('a * 'b * 'c * 'd) t
  | Custom : {
    encode : 'a -> (string, string) result;
    decode : string -> ('a, string) result;
    sql_type : string;
  } -> 'a t

Typed descriptions of OCaml values stored in SQL columns and parameters.

('a t) is Repodb's runtime witness for the OCaml type 'a. Fields, schema columns, expressions, query parameters, and result conversions all use these witnesses to keep database values and OCaml values aligned.

Use the predefined witnesses for ordinary columns:

let id = Types.int64
  let email = Types.string
  let published_at = Types.option Types.ptime
  let tags = Types.array Types.string

The same witness drives dialect-specific DDL rendering and conversion to and from Driver.Value.t:

Types.sql_type_name_for_dialect Repodb.Driver.PostgreSQL Types.uuid
  (* "UUID" *)

  let value = Types.to_value Types.bool true
  let decoded = Types.of_value Types.bool value

Option ty marks a nullable value. Array ty maps to native arrays only on dialects that support them; SQLite and MySQL render arrays using their fallback SQL type mapping. Json stores JSON text from OCaml's point of view while dialect renderers choose JSONB, JSON, or TEXT.

Use custom for small domain types that have a stable string representation:

type status = Draft | Published

  let status =
    Types.custom
      ~sql_type:"TEXT"
      ~encode:(function Draft -> Ok "draft" | Published -> Ok "published")
      ~decode:(function
        | "draft" -> Ok Draft
        | "published" -> Ok Published
        | other -> Error ("unknown status: " ^ other))

Custom encoders are used for parameters and custom decoders are used when converting driver values back to domain values. Keep custom encodings stable because they become persisted data.

val int : int t
val int32 : int32 t
val int64 : int64 t
val float : float t
val string : string t
val bool : bool t
val blob : string t
val ptime : Ptime.t t
val pdate : Ptime.date t
val uuid : Uuidm.t t
val json : string t
val option : 'a t -> 'a option t
val array : 'a t -> 'a list t
val tup2 : 'a t -> 'b t -> ('a * 'b) t
val tup3 : 'a t -> 'b t -> 'c t -> ('a * 'b * 'c) t
val tup4 : 'a t -> 'b t -> 'c t -> 'd t -> ('a * 'b * 'c * 'd) t
val custom : 
  encode:('a -> (string, string) result) ->
  decode:(string -> ('a, string) result) ->
  sql_type:string ->
  'a t
val (**) : 'a t -> 'b t -> ('a * 'b) t
type sql_type_names = {
  int : string;
  int32 : string;
  int64 : string;
  float : string;
  string : string;
  bool : string;
  blob : string;
  ptime : string;
  pdate : string;
  uuid : string;
  json : string;
  array : string option;
  tuple : string;
}
val postgres_sql_type_names : sql_type_names
val sqlite_sql_type_names : sql_type_names
val mysql_sql_type_names : sql_type_names
val sql_type_name_with : 'a. sql_type_names -> 'a t -> string
val sql_type_name : 'a t -> string
val sql_type_name_for_sqlite : 'a t -> string
val sql_type_name_for_mysql : 'a t -> string
val sql_type_name_for_dialect : 'a. Driver.dialect -> 'a t -> string
val is_nullable : 'a. 'a t -> bool
val to_value : 'a. 'a t -> 'a -> Driver.Value.t
val of_value : 'a. 'a t -> Driver.Value.t -> ('a, string) result