Skip to content

Commit

Permalink
Expose sqlstate in the connection and stmt APIs.
Browse files Browse the repository at this point in the history
  • Loading branch information
paurkedal committed Oct 17, 2024
1 parent aaf2c7a commit e855ae1
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 0 deletions.
6 changes: 6 additions & 0 deletions bindings/ffi_bindings.ml
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,9 @@ module Functions (F : Ctypes.FOREIGN) = struct
let mysql_ping = foreign "mysql_ping"
(mysql @-> returning int)

let mysql_sqlstate = foreign "mysql_sqlstate"
(mysql @-> returning string)

let mysql_stmt_prepare = foreign "mysql_stmt_prepare"
(stmt @-> ptr char @-> ulong @-> returning int)

Expand All @@ -320,6 +323,9 @@ module Functions (F : Ctypes.FOREIGN) = struct
let mysql_stmt_fetch = foreign "mysql_stmt_fetch"
(stmt @-> returning int)

let mysql_stmt_sqlstate = foreign "mysql_stmt_sqlstate"
(stmt @-> returning string)

let mysql_stmt_close = foreign "mysql_stmt_close"
(stmt @-> returning my_bool)

Expand Down
32 changes: 32 additions & 0 deletions examples/blocking/blocking_example.ml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,37 @@ let stream res =
| Error e -> raise (F.E e) in
next

let test_sqlstate mariadb =
assert (M.sqlstate mariadb = "00000");
(match M.prepare mariadb "SELECT * FROM inexistent_table" with
| Error _ -> assert (M.sqlstate mariadb <> "00000") (* actually "42S02" *)
| Ok _ -> assert false);
begin
let stmt =
M.prepare mariadb
"CREATE TEMPORARY TABLE test_sqlstate (i integer PRIMARY KEY)"
|> or_die "prepare CREATE TABLE test_sqlstate"
in
let _ =
M.Stmt.execute stmt [||]
|> or_die "exec CREATE TABLE test_sqlstate"
in
M.Stmt.close stmt |> or_die "stmt close CREATE TABLE test_sqlstate"
end;
for i = 0 to 1 do
let stmt =
M.prepare mariadb "INSERT INTO test_sqlstate VALUES (?)"
|> or_die "prepare in test_sqlstate"
in
(match M.Stmt.execute stmt [|`Int 1|] with
| Error (_, _) ->
assert (i = 1);
assert (M.Stmt.sqlstate stmt <> "00000") (* actually "23000" *)
| Ok _ -> assert (i = 0));

M.Stmt.close stmt |> or_die "stmt close in test_sqlstate"
done

let main () =
let mariadb = connect () |> or_die "connect" in
let query = env "OCAML_MARIADB_QUERY"
Expand All @@ -58,6 +89,7 @@ let main () =
let s = stream res in
Seq.iter print_row s;
M.Stmt.close stmt |> or_die "stmt close";
test_sqlstate mariadb;
M.close mariadb;
M.library_end ();
printf "done\n%!"
Expand Down
4 changes: 4 additions & 0 deletions lib/blocking.ml
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ let prepare mariadb query =
let start_txn mariadb =
wrap_unit mariadb (B.mysql_real_query mariadb.Common.raw "START TRANSACTION")

let sqlstate = Common.sqlstate

module Res = struct
type t = [`Blocking] Common.Res.t

Expand Down Expand Up @@ -203,6 +205,8 @@ module Stmt = struct
else
Error (Common.Stmt.error stmt)

let sqlstate = Common.Stmt.sqlstate

let close stmt =
Common.Stmt.free_meta stmt;
let raw = stmt.Common.Stmt.raw in
Expand Down
6 changes: 6 additions & 0 deletions lib/common.ml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ type error = int * string
let error mariadb =
(B.mysql_errno mariadb.raw, B.mysql_error mariadb.raw)

let sqlstate mariadb =
B.mysql_sqlstate mariadb.raw

let int_of_server_option = function
| Multi_statements true -> T.Server_options.multi_statements_on
| Multi_statements false -> T.Server_options.multi_statements_off
Expand Down Expand Up @@ -283,6 +286,9 @@ module Stmt = struct
let error stmt =
(B.mysql_stmt_errno stmt.raw, B.mysql_stmt_error stmt.raw)

let sqlstate stmt =
B.mysql_stmt_sqlstate stmt.raw

let fetch_field res i =
coerce (ptr void) (ptr T.Field.t) (B.mysql_fetch_field_direct res i)

Expand Down
2 changes: 2 additions & 0 deletions lib/mariadb.ml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ module type S = sig

val execute : t -> Field.value array -> Res.t result
val reset : t -> unit result
val sqlstate : t -> string
val close : t -> unit result
end

Expand Down Expand Up @@ -164,6 +165,7 @@ module type S = sig
val commit : t -> unit result
val rollback : t -> unit result
val prepare : t -> string -> Stmt.t result
val sqlstate : t -> string
end

module B = Binding_wrappers
Expand Down
10 changes: 10 additions & 0 deletions lib/mariadb.mli
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,12 @@ module type S = sig
were after [stmt] was prepared, and frees up any {!Res.t} produced by
[stmt]. *)

val sqlstate : t -> string
(** [sqlstate stmt] is the SQLSTATE with MariaDB extensions indicating the
status of the previous execution of the statement. The string
["00000"] is returned if no error occurred or if the statement has not
been executed. *)

val close : t -> unit result
(** [close stmt] closes the prepapred statement [stmt] and frees any
allocated memory associated with it and its result. *)
Expand Down Expand Up @@ -282,6 +288,10 @@ module type S = sig
(** [prepare mariadb query] creates a prepared statement for [query]. The
query may contain [?] as placeholders for parameters that can be bound
by calling [Stmt.execute]. *)

val sqlstate : t -> string
(* [sqlstate mariadb] is the SQLSTATE with MariaDB extensions of the last
* operation on [mariadb]. Returns ["00000"] if no error occurred. *)
end

(** The module for blocking MariaDB API calls. It should be possible to call
Expand Down
4 changes: 4 additions & 0 deletions lib/nonblocking.ml
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,8 @@ let prepare mariadb query =
`Ok (prepare_start mariadb stmt, prepare_cont mariadb stmt)
| None -> `Error (Common.error mariadb)

let sqlstate = Common.sqlstate

module Res = struct
type t = [`Nonblocking] Common.Res.t

Expand Down Expand Up @@ -354,6 +356,8 @@ module Stmt = struct

let next_result_cont stmt status =
handle_next stmt (B.mysql_stmt_next_result_cont stmt.Common.Stmt.raw status)

let sqlstate = Common.Stmt.sqlstate
end

module type Wait = sig
Expand Down

0 comments on commit e855ae1

Please sign in to comment.