(** Letsqlite main interface. *) (** {1 Type definitions} Types used for monad composition. *) type stmt_wrap = bool * Sqlite3.stmt type 'a stmt_m = | Failed of Sqlite3.Rc.t | Norm of ('a * stmt_wrap) (** The ['a] value in the [stmt_m] is referred to as the bundled value. A function may "fail with [e]", in which it returns [Failed e], or it may "return a value", in which it returns [Norm v s]. They are collectively refered to as the monad's values. The bundled {!Sqlite.stmt} value is refered to as [S], and the value bundled is refered to as [V]. The boolean value is the {i preserve on failure} flag. When true, monadic functions will not call {!Sqlite3.finalize} on the contained statement. {b This will cause a memory leak if not handled correctly.} {i Never directly use [Failed].} You run the likelihood of leaking memory or causing a crash. *) type ('a,'b) monad_fun = ('a * stmt_wrap) -> 'b stmt_m type rowdata = (string, Sqlite3.Data.t) Hashtbl.t (** {1 Primary Functions} *) val (>>$) : 'a stmt_m -> ('a,'b) monad_fun -> 'b stmt_m (** [>>$] is the monadic composition function. [s >>$ f] return [s] if [s] is [Failed] and [f V S] otherwise. *) val (let$) : 'a stmt_m -> ('a,'b) monad_fun -> 'b stmt_m (** [let$ (v,s) = f (V,S) in ...] is equivalent to [f (V,S) >>$ (fun (v,s) -> ...)]. *) val (@>$) : ('a,'b) monad_fun -> ('b,'c) monad_fun -> ('a,'c) monad_fun (** [f @>$ g] composes to monadic functions so they become another monadic function. *) val (>-$) : 'a stmt_m -> ('a,'b) monad_fun -> 'a stmt_m (** [>-$] is the passthrough function. [s >-$ f] is equivalent to [s >>$ f] except that the bundled value from [f (V,S)] is discarded and replaced with [V]. This function passes the original [V] through. *) val gs : stmt_wrap -> Sqlite3.stmt (** [gs s] returns the statment in an instance of [stmt_wrap]. *) (** {1 Non-Execution Functions} These functions do not execute any SQL queries. They exist to make dealing with the monad easier. *) val transform : ('a -> 'b) -> ('a,'b) monad_fun (** [transform f] maps [V] to [f V]. *) val inject : 'a -> ('b,'a) monad_fun (** [inject x] returns [Norm x S], discarding [V]. *) val fail : Sqlite3.Rc.t -> ('a,'b) monad_fun (** [fail e] finalizes [S] and returns [Failure], where the error code is [e] if [e] is not a success error code, and the return code of {!Sqlite3.finalize} otherwise. *) val stmtfail : Sqlite3.Rc.t -> stmt_wrap -> unit stmt_m (** [stmtfail e s] is equivalent to [fail] except it assembles a statement with unit type. *) val lift_err : Sqlite3.Rc.t -> ('a,'a) monad_fun (** [lift_err e] is equivalent to [fail e] when [e] is not a success value, and otherwise returns the monad's values unchanged. {b NOTE}: You may be tempted to define a function like [lift : (Sqlite3.stmt -> Sqlite3.Rc.t) -> ('a,'a) monad_fun] which would take a function and apply [lift_err (f S) V S] to the function. However, the partial application [lift f] would leave you with a {i weak type}, which will force your type to have a fixed type. *) (** {1 Execution functions} All of these functions will (effectively) exceute {!fail} and return [Failed] on failure. All functions will omit error behavior unless there is something different across any of them. *) val prepare : Sqlite3.db -> string -> 'a -> 'a stmt_m (** [prepare db stmt v] returns a monad with bundled value [v] and the statement in [s]. *) val prepare0 : Sqlite3.db -> string -> unit stmt_m (** [prepare0 db stmt] is equivalent to [prepare db stmt ()]. *) val prepare_keep : bool -> Sqlite3.db -> string -> 'a -> 'a stmt_m (** [prepare_keep b] is like [prepare], but [b] is the preserve-on-failure file. *) val reprepare : Sqlite3.db -> string -> ('a,'a) monad_fun (** [reprepare db stmt] finalizes [S] and prepares [stmt] in its place. *) val reset : ('a,'a) monad_fun (** [reset] resets [S] so that it may be executed again. *) val step : ('a,'a) monad_fun (** [step] is equivalent to {!Sqlite3.step}. {b NOTE}: [step] will fail when the statement returns a row. *) val rowfold : ('a -> rowdata -> ('a,Sqlite3.Rc.t) Result.t) -> ('a,'a) monad_fun (** [rowfold f] iterates over each row returns by [S] and applies [f] to it, returning some value. *) val iter : (rowdata -> Sqlite3.Rc.t) -> ('a,unit) monad_fun (** [rowfold_unit f] is equivalent to [rowfold_init f ()] but [f] is not passed a unit argument. *) val map : ('a -> ('b,'c) monad_fun) -> 'a list -> ('b,'c list) monad_fun (** [map f l] applies the monadic function [f] to each element of [l], returning all the list of all their values. *) val fold : ('a -> ('b,'b) monad_fun) -> 'a list -> ('b,'b) monad_fun (** [fold f l] applies each element of [l] to make a monadic function [f]. *) val get_exactly_one_row : ('a,(unit * rowdata)) monad_fun (** [get_exactly_one_row] steps [S] and stores the returned row. The value in [S] is discarded. The function fails if there is not exactly one row. The function returns a tuple with the unit type to interact with {!extract}. *) val exec_extract : ('a -> 'b option) -> ('b -> 'c option) -> (('d * 'a),('c * 'a)) monad_fun (** [exec_extract extr conv] extracts a value from the second element in [V], and then applies [conv] to it. If both were successful, the function replaces the first element of [V] with the converted value. *) val extract : string -> (Sqlite3.Data.t -> 'b option) -> (('a * rowdata),('b * rowdata)) monad_fun (** [extract name f] finds the value in the row with header name [name] and applies [f] to it. If [f] succeeds then its return value is stored in [V]. The rowdata is preserved. *) val finalize : 'a stmt_m -> 'a (** [finalize] raises an exception if the execution failed, and [V] otherwise. *) val check : 'a stmt_m -> ('a * 'a stmt_m) (** [check] checks if the statement is an error value and throws an exception if it is. If it is not, then it returns [(V,S)]. *) val bind_values : Sqlite3.Data.t list -> ('a,'a) monad_fun (** [bind_values l] binds each index of [l] to a positional parameter in [S]. *) val clear_bindings : ('a,'a) monad_fun (** [clear_bindings] clears any values bound to [S]. *) val exec : Sqlite3.db -> string -> unit stmt_m (** [exec db s] is equivalent to a call to {!prepare} followed by {!step}. *) val reexec : Sqlite3.db -> string -> ('a,'a) monad_fun (** [reexec db s] is equivalent to [reprepare >>$ step]. *) val bsrc : Sqlite3.Data.t list -> ('a,'a) monad_fun (** [bsrc l] is equivalent to [bind_values >>$ step >>$ reset >>$ clear_bindings]. *)