Skip to content

Commit 1881896

Browse files
committed
Expose sqlstate in the connection and stmt APIs.
1 parent 3ae20e7 commit 1881896

File tree

7 files changed

+64
-0
lines changed

7 files changed

+64
-0
lines changed

bindings/ffi_bindings.ml

+6
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,9 @@ module Bindings (F : Cstubs.FOREIGN) = struct
305305
let mysql_ping = foreign "mysql_ping"
306306
(mysql @-> returning int)
307307

308+
let mysql_sqlstate = foreign "mysql_sqlstate"
309+
(mysql @-> returning string)
310+
308311
let mysql_stmt_prepare = foreign "mysql_stmt_prepare"
309312
(stmt @-> ptr char @-> ulong @-> returning int)
310313

@@ -317,6 +320,9 @@ module Bindings (F : Cstubs.FOREIGN) = struct
317320
let mysql_stmt_fetch = foreign "mysql_stmt_fetch"
318321
(stmt @-> returning int)
319322

323+
let mysql_stmt_sqlstate = foreign "mysql_stmt_sqlstate"
324+
(stmt @-> returning string)
325+
320326
let mysql_stmt_close = foreign "mysql_stmt_close"
321327
(stmt @-> returning my_bool)
322328

examples/blocking/blocking_example.ml

+32
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,37 @@ let stream res =
4848
try Ok (Stream.from next)
4949
with F.E e -> Error e
5050

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

lib/blocking.ml

+4
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ let prepare mariadb query =
152152
| Some raw -> build_stmt raw
153153
| None -> Error (2008, "out of memory")
154154

155+
let sqlstate = Common.sqlstate
156+
155157
module Res = struct
156158
type t = [`Blocking] Common.Res.t
157159

@@ -198,6 +200,8 @@ module Stmt = struct
198200
else
199201
Error (Common.Stmt.error stmt)
200202

203+
let sqlstate = Common.Stmt.sqlstate
204+
201205
let close stmt =
202206
let raw = stmt.Common.Stmt.raw in
203207
if B.mysql_stmt_free_result raw && B.mysql_stmt_close raw then

lib/common.ml

+6
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
@@ -280,6 +283,9 @@ module Stmt = struct
280283
let error stmt =
281284
(B.mysql_stmt_errno stmt.raw, B.mysql_stmt_error stmt.raw)
282285

286+
let sqlstate stmt =
287+
B.mysql_stmt_sqlstate stmt.raw
288+
283289
let fetch_field res i =
284290
coerce (ptr void) (ptr T.Field.t) (B.mysql_fetch_field_direct res i)
285291

lib/mariadb.ml

+2
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ module type S = sig
7979

8080
val execute : t -> Field.value array -> Res.t result
8181
val reset : t -> unit result
82+
val sqlstate : t -> string
8283
val close : t -> unit result
8384
end
8485

@@ -162,6 +163,7 @@ module type S = sig
162163
val commit : t -> unit result
163164
val rollback : t -> unit result
164165
val prepare : t -> string -> Stmt.t result
166+
val sqlstate : t -> string
165167
end
166168

167169
module B = Binding_wrappers

lib/mariadb.mli

+10
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,12 @@ module type S = sig
154154
were after [stmt] was prepared, and frees up any {!Res.t} produced by
155155
[stmt]. *)
156156

157+
val sqlstate : t -> string
158+
(** [sqlstate stmt] is the SQLSTATE with MariaDB extensions indicating the
159+
status of the previous execution of the statement. The string
160+
["00000"] is returned if no error occurred or if the statement has not
161+
been executed. *)
162+
157163
val close : t -> unit result
158164
(** [close stmt] closes the prepapred statement [stmt] and frees
159165
any allocated memory associated with it and its result. *)
@@ -275,6 +281,10 @@ module type S = sig
275281
(** [prepare mariadb query] creates a prepared statement for [query].
276282
The query may contain [?] as placeholders for parameters that
277283
can be bound by calling [Stmt.execute]. *)
284+
285+
val sqlstate : t -> string
286+
(* [sqlstate mariadb] is the SQLSTATE with MariaDB extensions of the last
287+
* operation on [mariadb]. Returns ["00000"] if no error occurred. *)
278288
end
279289

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

lib/nonblocking.ml

+4
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,8 @@ let prepare mariadb query =
211211
`Ok (prepare_start mariadb stmt query, prepare_cont mariadb stmt)
212212
| None -> `Error (Common.error mariadb)
213213

214+
let sqlstate = Common.sqlstate
215+
214216
module Res = struct
215217
type t = [`Nonblocking] Common.Res.t
216218

@@ -344,6 +346,8 @@ module Stmt = struct
344346

345347
let next_result_cont stmt status =
346348
handle_next stmt (B.mysql_stmt_next_result_cont stmt.Common.Stmt.raw status)
349+
350+
let sqlstate = Common.Stmt.sqlstate
347351
end
348352

349353
module type Wait = sig

0 commit comments

Comments
 (0)