From mboxrd@z Thu Jan 1 00:00:00 1970 Received: (from majordomo@localhost) by pauillac.inria.fr (8.7.6/8.7.3) id XAA08367; Fri, 14 Feb 2003 23:36:13 +0100 (MET) X-Authentication-Warning: pauillac.inria.fr: majordomo set sender to owner-caml-list@pauillac.inria.fr using -f Received: from concorde.inria.fr (concorde.inria.fr [192.93.2.39]) by pauillac.inria.fr (8.7.6/8.7.3) with ESMTP id XAA08362 for ; Fri, 14 Feb 2003 23:36:12 +0100 (MET) X-SPAM-Warning: Sending machine is listed in blackholes.five-ten-sg.com Received: from mail2.atl.registeredsite.com (mail2.atl.registeredsite.com [64.224.219.76]) by concorde.inria.fr (8.11.1/8.11.1) with ESMTP id h1EMaBf09467 for ; Fri, 14 Feb 2003 23:36:11 +0100 (MET) Received: from badgersys.com (technomediasolutions.com [66.111.64.35] (may be forged)) by mail2.atl.registeredsite.com (8.12.2/8.12.6) with ESMTP id h1EMa9rV008765 (version=TLSv1/SSLv3 cipher=EDH-RSA-DES-CBC3-SHA bits=168 verify=NOT) for ; Fri, 14 Feb 2003 17:36:10 -0500 Received: from [199.125.217.206] ([199.125.217.206]) by badgersys.com (8.11.6/8.11.0) with ESMTP id h1EMa5w43452 for ; Fri, 14 Feb 2003 16:36:05 -0600 (CST) (envelope-from mattwb@alve.com) Subject: [Caml-list] Re: New Features (Common Database Interface) From: Matt Boyd To: caml-list@inria.fr Content-Type: multipart/mixed; boundary="=-32S2qDINrUpu3OARDi+o" X-Mailer: Ximian Evolution 1.0.8 Date: 14 Feb 2003 16:35:58 -0600 Message-Id: <1045262163.652.6.camel@valery5> Mime-Version: 1.0 Sender: owner-caml-list@pauillac.inria.fr Precedence: bulk --=-32S2qDINrUpu3OARDi+o Content-Type: text/plain Content-Transfer-Encoding: 7bit This is what I've been using. It has been useful for creating a common database interface that, at least, meets my basic needs. I've written bindings for ODBC, PostgreSQL, and Sybase(dblib). The bindparam stuff hasn't been worked on too much, but I haven't really needed it. If anyone thinks this is a starting point, let me know. --=-32S2qDINrUpu3OARDi+o Content-Disposition: attachment; filename=camlDB.mli Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; name=camlDB.mli; charset=ANSI_X3.4-1968 (** {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 (**=20 {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 =3D { year : int; month : int; day : int }=20 (** Basic time components *) type time =3D { hour : int; minute : int; second : int }=20 (** Database timestamp type *) type timestamp =3D { date : date; time : time; fraction : int }=20 (** {4 Fields and rows} *) (** Database field data types *) type data =3D=20 | Null=20 | 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 =3D 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 (**=20 {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 =3D | Input | Output (** {3 Caml Database Signatures} *) (** Basic database interface *) module type ELT =3D=20 sig (**=20 Implement this signature for a type of database and you can=20 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=20 A connection. An exception that is database-specific will be=20 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 establis= hed with {e conn-args}.=20 *) (** {5 Query functions} *) val direct : string -> connection -> unit=20 (** {b direct {e query connection}} {ul {li {e query}: The query string.} {li {e connection}: The connection.}} @return=20 Nothing. Executes the query. Any results will be discarded. *) val execute : string -> connection -> result=20 (** {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. =20 *) 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}: =20 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 (**=20 {b iter {e query iter-fun conn}} {ul {li {e query}: The query string.} {li {e iter-fun}: =20 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=20 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 =3D=20 sig type result (** Bind result columns *) module Col :=20 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 :=20 sig type t val bind : result -> int -> bind_io -> data ->t (** {b bind {e result param-num bind-dir data}} {ul=20 {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 =3D sig type t val of_row : row -> t (**=20 {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 =3D sig type t type connection type result val of_row : row -> t (**=20 {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) :=20 ROW_STREAM=20 with type t =3D Row.t=20 and type connection =3D Elt.connection and type result =3D Elt.result --=-32S2qDINrUpu3OARDi+o-- ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners