Skip to content

Commit e855ae1

Browse files
committed
Expose sqlstate in the connection and stmt APIs.
1 parent aaf2c7a commit e855ae1

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
@@ -308,6 +308,9 @@ module Functions (F : Ctypes.FOREIGN) = struct
308308
let mysql_ping = foreign "mysql_ping"
309309
(mysql @-> returning int)
310310

311+
let mysql_sqlstate = foreign "mysql_sqlstate"
312+
(mysql @-> returning string)
313+
311314
let mysql_stmt_prepare = foreign "mysql_stmt_prepare"
312315
(stmt @-> ptr char @-> ulong @-> returning int)
313316

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

326+
let mysql_stmt_sqlstate = foreign "mysql_stmt_sqlstate"
327+
(stmt @-> returning string)
328+
323329
let mysql_stmt_close = foreign "mysql_stmt_close"
324330
(stmt @-> returning my_bool)
325331

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
@@ -153,6 +153,8 @@ let prepare mariadb query =
153153
let start_txn mariadb =
154154
wrap_unit mariadb (B.mysql_real_query mariadb.Common.raw "START TRANSACTION")
155155

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

@@ -203,6 +205,8 @@ module Stmt = struct
203205
else
204206
Error (Common.Stmt.error stmt)
205207

208+
let sqlstate = Common.Stmt.sqlstate
209+
206210
let close stmt =
207211
Common.Stmt.free_meta stmt;
208212
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
@@ -283,6 +286,9 @@ module Stmt = struct
283286
let error stmt =
284287
(B.mysql_stmt_errno stmt.raw, B.mysql_stmt_error stmt.raw)
285288

289+
let sqlstate stmt =
290+
B.mysql_stmt_sqlstate stmt.raw
291+
286292
let fetch_field res i =
287293
coerce (ptr void) (ptr T.Field.t) (B.mysql_fetch_field_direct res i)
288294

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

@@ -164,6 +165,7 @@ module type S = sig
164165
val commit : t -> unit result
165166
val rollback : t -> unit result
166167
val prepare : t -> string -> Stmt.t result
168+
val sqlstate : t -> string
167169
end
168170

169171
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. *)
@@ -282,6 +288,10 @@ module type S = sig
282288
(** [prepare mariadb query] creates a prepared statement for [query]. The
283289
query may contain [?] as placeholders for parameters that can be bound
284290
by calling [Stmt.execute]. *)
291+
292+
val sqlstate : t -> string
293+
(* [sqlstate mariadb] is the SQLSTATE with MariaDB extensions of the last
294+
* operation on [mariadb]. Returns ["00000"] if no error occurred. *)
285295
end
286296

287297
(** 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)