Skip to content

Commit 0704d05

Browse files
committed
Expose sqlstate in the connection and stmt APIs.
1 parent 572396b commit 0704d05

File tree

7 files changed

+64
-0
lines changed

7 files changed

+64
-0
lines changed

bindings/ffi_bindings.ml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,9 @@ module Functions (F : Ctypes.FOREIGN) = struct
320320
let mysql_get_proto_info = foreign "mysql_get_proto_info"
321321
(mysql @-> returning uint)
322322

323+
let mysql_sqlstate = foreign "mysql_sqlstate"
324+
(mysql @-> returning string)
325+
323326
let mysql_stmt_prepare = foreign "mysql_stmt_prepare"
324327
(stmt @-> ptr char @-> ulong @-> returning int)
325328

@@ -332,6 +335,9 @@ module Functions (F : Ctypes.FOREIGN) = struct
332335
let mysql_stmt_fetch = foreign "mysql_stmt_fetch"
333336
(stmt @-> returning int)
334337

338+
let mysql_stmt_sqlstate = foreign "mysql_stmt_sqlstate"
339+
(stmt @-> returning string)
340+
335341
let mysql_stmt_close = foreign "mysql_stmt_close"
336342
(stmt @-> returning my_bool)
337343

examples/blocking/blocking_example.ml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,37 @@ let stream res =
4747
| Error e -> raise (F.E e) in
4848
next
4949

50+
let test_sqlstate mariadb =
51+
assert (M.sqlstate mariadb = "00000");
52+
(match M.prepare mariadb "SELECT * FROM inexistent_table" with
53+
| Error _ -> assert (M.sqlstate mariadb <> "00000") (* actually "42S02" *)
54+
| Ok _ -> assert false);
55+
begin
56+
let stmt =
57+
M.prepare mariadb
58+
"CREATE TEMPORARY TABLE test_sqlstate (i integer PRIMARY KEY)"
59+
|> or_die "prepare CREATE TABLE test_sqlstate"
60+
in
61+
let _ =
62+
M.Stmt.execute stmt [||]
63+
|> or_die "exec CREATE TABLE test_sqlstate"
64+
in
65+
M.Stmt.close stmt |> or_die "stmt close CREATE TABLE test_sqlstate"
66+
end;
67+
for i = 0 to 1 do
68+
let stmt =
69+
M.prepare mariadb "INSERT INTO test_sqlstate VALUES (?)"
70+
|> or_die "prepare in test_sqlstate"
71+
in
72+
(match M.Stmt.execute stmt [|`Int 1|] with
73+
| Error (_, _) ->
74+
assert (i = 1);
75+
assert (M.Stmt.sqlstate stmt <> "00000") (* actually "23000" *)
76+
| Ok _ -> assert (i = 0));
77+
78+
M.Stmt.close stmt |> or_die "stmt close in test_sqlstate"
79+
done
80+
5081
let main () =
5182
let mariadb = connect () |> or_die "connect" in
5283
let query = env "OCAML_MARIADB_QUERY"
@@ -58,6 +89,7 @@ let main () =
5889
let s = stream res in
5990
Seq.iter print_row s;
6091
M.Stmt.close stmt |> or_die "stmt close";
92+
test_sqlstate mariadb;
6193
M.close mariadb;
6294
M.library_end ();
6395
printf "done\n%!"

lib/blocking.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,8 @@ let prepare mariadb query =
158158
let start_txn mariadb =
159159
wrap_unit mariadb (B.mysql_real_query mariadb.Common.raw "START TRANSACTION")
160160

161+
let sqlstate = Common.sqlstate
162+
161163
module Res = struct
162164
type t = [`Blocking] Common.Res.t
163165

@@ -208,6 +210,8 @@ module Stmt = struct
208210
else
209211
Error (Common.Stmt.error stmt)
210212

213+
let sqlstate = Common.Stmt.sqlstate
214+
211215
let close stmt =
212216
Common.Stmt.free_meta stmt;
213217
let raw = stmt.Common.Stmt.raw in

lib/common.ml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ type error = int * string
8585
let error mariadb =
8686
(B.mysql_errno mariadb.raw, B.mysql_error mariadb.raw)
8787

88+
let sqlstate mariadb =
89+
B.mysql_sqlstate mariadb.raw
90+
8891
let int_of_server_option = function
8992
| Multi_statements true -> T.Server_options.multi_statements_on
9093
| Multi_statements false -> T.Server_options.multi_statements_off
@@ -295,6 +298,9 @@ module Stmt = struct
295298
let error stmt =
296299
(B.mysql_stmt_errno stmt.raw, B.mysql_stmt_error stmt.raw)
297300

301+
let sqlstate stmt =
302+
B.mysql_stmt_sqlstate stmt.raw
303+
298304
let fetch_field res i =
299305
coerce (ptr void) (ptr T.Field.t) (B.mysql_fetch_field_direct res i)
300306

lib/mariadb.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ module type S = sig
8080

8181
val execute : t -> Field.value array -> Res.t result
8282
val reset : t -> unit result
83+
val sqlstate : t -> string
8384
val close : t -> unit result
8485
end
8586

@@ -168,6 +169,7 @@ module type S = sig
168169
val commit : t -> unit result
169170
val rollback : t -> unit result
170171
val prepare : t -> string -> Stmt.t result
172+
val sqlstate : t -> string
171173
end
172174

173175
module B = Binding_wrappers

lib/mariadb.mli

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,12 @@ module type S = sig
160160
were after [stmt] was prepared, and frees up any {!Res.t} produced by
161161
[stmt]. *)
162162

163+
val sqlstate : t -> string
164+
(** [sqlstate stmt] is the SQLSTATE with MariaDB extensions indicating the
165+
status of the previous execution of the statement. The string
166+
["00000"] is returned if no error occurred or if the statement has not
167+
been executed. *)
168+
163169
val close : t -> unit result
164170
(** [close stmt] closes the prepapred statement [stmt] and frees any
165171
allocated memory associated with it and its result. *)
@@ -294,6 +300,10 @@ module type S = sig
294300
(** [prepare mariadb query] creates a prepared statement for [query]. The
295301
query may contain [?] as placeholders for parameters that can be bound
296302
by calling [Stmt.execute]. *)
303+
304+
val sqlstate : t -> string
305+
(* [sqlstate mariadb] is the SQLSTATE with MariaDB extensions of the last
306+
* operation on [mariadb]. Returns ["00000"] if no error occurred. *)
297307
end
298308

299309
(** The module for blocking MariaDB API calls. It should be possible to call

lib/nonblocking.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,8 @@ let prepare mariadb query =
218218
`Ok (prepare_start mariadb stmt, prepare_cont mariadb stmt)
219219
| None -> `Error (Common.error mariadb)
220220

221+
let sqlstate = Common.sqlstate
222+
221223
module Res = struct
222224
type t = [`Nonblocking] Common.Res.t
223225

@@ -354,6 +356,8 @@ module Stmt = struct
354356

355357
let next_result_cont stmt status =
356358
handle_next stmt (B.mysql_stmt_next_result_cont stmt.Common.Stmt.raw status)
359+
360+
let sqlstate = Common.Stmt.sqlstate
357361
end
358362

359363
module type Wait = sig

0 commit comments

Comments
 (0)