(** {b Caml Database Interface} Common interface for connecting to databases. *) (** {3 Exceptions} *) exception End_of_rows (** Raised when query results ends. *) exception Row_failure of string * string (** {b Row_failure ({e table}, {e row-as-string})} {ul {li {e table}: Table query failed.} {li {e row-as-string}: Actual row contents changed to a string}} *) (** {3 Data Types} *) (** {4 Date and Time Types} *) (** Basic date components *) type date = { year : int; month : int; day : int } (** Basic time components *) type time = { hour : int; minute : int; second : int } (** Database timestamp type *) type timestamp = { date : date; time : time; fraction : int } (** {4 Fields and rows} *) (** Database field data types *) type data = | Null | String of string | Integer of int | Float of float | Date of date | Time of time | Timestamp of timestamp (** A row is a list of fields *) type row = data list (** {4 Conversion to String} *) val string_of_date : date -> string val string_of_time : time -> string val string_of_timestamp : timestamp -> string val string_of_data : data -> string val string_of_row : row -> string val raise_row_failure : string -> row -> 'a (** {b raise_row_failure {e table row}} {ul {li {e table}: Name of the table} {li {e row}: Row that was actually retrieved}} @raise Row_failure Raised when this function is called. @return Nothing. Raises {e Row_failure} with the parameters. *) (** {4 Conversion from Unix Time} *) val timestamp_of_unix_time : float -> timestamp val date_of_unix_time : float -> date val time_of_unix_time : float -> time (** {4 Conversion to Unix Time} *) val unix_time : Unix.tm -> float val unix_time_of_timestamp : timestamp -> float val unix_time_of_date : date -> float val unix_time_of_time : time -> float (** Bind parameter direction *) type bind_io = | Input | Output (** {3 Caml Database Signatures} *) (** Basic database interface *) module type ELT = sig (** Implement this signature for a type of database and you can use it interchangeably in applications. *) type args (** Connection arguments *) type connection (** Connection type *) type result (** Result set *) (** {5 Connection functions} *) val connect : args -> connection (** {b connect {e connection-args}} {ul {li {e connection-args}: Arguments needed to initiate a connection}} @return A connection. An exception that is database-specific will be raised if a connection cannot be established. *) val disconnect : connection -> unit (** {b disconnect {e connection}} {ul {li {e connection}: A valid connection}} @return Nothing. If the connection has already been disconnected, then it's unspecified how this will behave (It may just return or it may raise an exception) *) val useConn : (connection -> 'a) -> args -> 'a (** {b useConn {e conn-function conn-args}} {ul {li {e conn-function}: A function which takes a {e connection} argument} {li {e conn-args}: Arguments to the {e connect} function which can be used to create a connection.}} @return The result of applying {e conn-function} to the connection established with {e conn-args}. *) (** {5 Query functions} *) val direct : string -> connection -> unit (** {b direct {e query connection}} {ul {li {e query}: The query string.} {li {e connection}: The connection.}} @return Nothing. Executes the query. Any results will be discarded. *) val execute : string -> connection -> result (** {b execute {e query connection}} {ul {li {e query}: Query string.} {li {e connection}: Connection}} @return A result set. The query is executed and the results are returned as a result type. *) val cancel : result -> unit (** {b cancel {e result}} {ul {li {e result}: The result set.}} @return Nothing. The result information is cleaned-up if there is any. This may raise an exception or may not. In most cases it should just return even if the result has already been cancelled. *) val useQuery : (result -> 'a) -> string -> connection -> 'a (** {b useQuery {e result-fun query conn}} {ul {li {e result-fun}: Function to pass the result returned by executing {e query} using {e connection}.} {li {e query}: The query string} {li {e conn}: The connection.}} @return The result of applying {e result-fun} to the result returned by executing {e query} with {e conn}. *) (** {5 Row Information Functions} *) val numberOfColumns : result -> int (** {b numberOfColumns {e result}} {ul {li {e result}: The result set.}} @return The number of columns in each row *) val numberOfRows : result -> int (** {b numberOfRows {e result}} {ul {li {e result}: The result set.}} @return the number of rows returned by the query. *) val nextRow : result -> row (** {b nextRow {e result}} {ul {li {e result}: The result set.}} @return the next row in the set of rows. *) (** {5 Higher-level Functions} *) val iter : string -> (row -> unit) -> connection -> unit (** {b iter {e query iter-fun conn}} {ul {li {e query}: The query string.} {li {e iter-fun}: Function to execute for each row in the query set.} {li {e conn}: The connection}} @return Nothing. Executes {e query} and then iterates over the rows returned with {e iter-fun}. *) val map : string -> (row -> 'b) -> connection -> 'b list (** {b map {e query map-fun conn}} {ul {li {e query}: The query string.} {li {e map-fun}: Function to run on each row.} {li {e conn}: Connection to use.}} @return A list of all elements returned by applying {e map-fun} to every row returned by executing {e query}. *) val stream : string -> connection -> data Stream.t (** {b stream {e query conn}} {ul {li {e query}: The query string.} {li {e conn}: Connection.}} @return A stream that will return the next row when used with {e Stream.next}. *) end (** Bind Signature Interface *) module type BIND = sig type result (** Bind result columns *) module Col : sig type t val bind : result -> int -> data ->t (** {b bind {e result column data}} {ul {li {e result}: Result returned by executing a query.} {li {e column}: Column number.} {li {e data}: Initialized data value.}} @return A column binding value. *) val free : t -> unit (** {b free {e binding}} {ul {li {e binding}: Binding to free}} @return Nothing. The binding is undone. *) val replace : t -> data -> unit (** {b replace {e binding data}} {ul {li {e binding}: Binding to use.} {li {e data}: Data to replace in the binding.}} @return. Nothing. Replace the data in {e binding} *) val get : t -> data (** {b get {e binding}} {ul {li {e binding}: Binding to extract from.}} @return. The information contained in {e binding} *) val use : (t -> 'a) -> result -> int -> data -> 'a (** {b use {e bind-fun result col init}} {ul {li {e bind-fun}: Function which uses binding.} {li {e result}: Used to create binding.} {li {e col}: Used to create binding.} {li {e init}: Initial binding value.}} @return The result returned by applying {e bind-fun} to the binding created with the other parameters. *) end (** Bind query parameters *) module Param : sig type t val bind : result -> int -> bind_io -> data ->t (** {b bind {e result param-num bind-dir data}} {ul {li {e result}: The query result set.} {li {e param-num}: The parameter number to bind to.} {li {e bind-dir}: The parameter direction.} {li {e data}: Initial binding value.}} @return A bound value. *) val free : t -> unit (** {b free {e binding}} {ul {li {e binding}: Binding to free}} @return Nothing. The binding is undone. *) val replace : t -> data -> unit (** {b replace {e binding data}} {ul {li {e binding}: Binding to use.} {li {e data}: Data to replace in the binding.}} @return. Nothing. Replace the data in {e binding} *) val get : t -> data (** {b get {e binding}} {ul {li {e binding}: Binding to extract from.}} @return. The information contained in {e binding} *) val use : (t -> 'a) -> result -> int -> bind_io -> data -> 'a (** {b use {e bind-fun result param-num bind-dir init}} {ul {li {e bind-fun}: Function which uses binding.} {li {e result}: Used to create binding.} {li {e param-num}: Used to create binding.} {li {e bind-dir}: The parameter direction.} {li {e init}: Initial binding value.}} @return The result returned by applying {e bind-fun} to the binding created with the other parameters. *) end end (** {4 Row Manipulation Signatures} *) (** Row Constructor *) module type ROW = sig type t val of_row : row -> t (** {b of_row {e row}} {ul {li {e row}: Row to convert.}} @raise Row_failure if it cannot convert the row. @return the result of constructing {e t} from a {e row}. *) end (** Row Stream Interface *) module type ROW_STREAM = sig type t type connection type result val of_row : row -> t (** {b of_row {e row}} {ul {li {e row}: Row to convert.}} @raise Row_failure if it cannot convert the row. @return the result of constructing {e t} from a {e row}. *) val next_row : result -> t (** {b next_row {e result}} {ul {li {e result}; Result to convert.}} @return the construction of a {e t} from the next row in {e result}. *) val iter : string -> (t -> unit) -> connection -> unit val map : string -> (t -> 'a) -> connection -> 'a list val stream : string -> connection -> t Stream.t val fold : string -> (t -> 'a -> 'a) -> 'a -> connection -> 'a end module MakeRow (Elt : ELT)(Row : ROW) : ROW_STREAM with type t = Row.t and type connection = Elt.connection and type result = Elt.result