@@ -219,6 +219,110 @@ struct
219219
220220 M. close dbh
221221
222+ let test_exec () =
223+ connect () >> = or_die " connect" >> = fun dbh ->
224+
225+ M. exec dbh
226+ " CREATE TEMPORARY TABLE ocaml_mariadb_test \
227+ (id integer PRIMARY KEY AUTO_INCREMENT, v integer, s text)"
228+ >> = or_die " exec create" >> = fun res ->
229+ assert (res.M. affected_rows = 0 );
230+ assert (res.M. insert_id = 0 );
231+
232+ M. exec dbh " INSERT INTO ocaml_mariadb_test (v) VALUES (10), (20), (30)"
233+ >> = or_die " exec multi-row insert" >> = fun res ->
234+ assert (res.M. affected_rows = 3 );
235+ assert (res.M. insert_id = 1 );
236+
237+ M. exec dbh " INSERT INTO ocaml_mariadb_test (v) VALUES (40)"
238+ >> = or_die " exec single-row insert" >> = fun res ->
239+ assert (res.M. affected_rows = 1 );
240+ assert (res.M. insert_id = 4 );
241+
242+ M. exec dbh " UPDATE ocaml_mariadb_test SET v = v + 1 WHERE v >= 30"
243+ >> = or_die " exec update" >> = fun res ->
244+ assert (res.M. affected_rows = 2 );
245+ assert (res.M. insert_id = 0 );
246+
247+ M. exec dbh
248+ " INSERT INTO ocaml_mariadb_test (id, v) VALUES (2, 25) \
249+ ON DUPLICATE KEY UPDATE v = 25"
250+ >> = or_die " exec insert on duplicate key update" >> = fun res ->
251+ assert (res.M. affected_rows = 2 );
252+
253+ M. exec dbh " DELETE FROM ocaml_mariadb_test WHERE v = 10"
254+ >> = or_die " exec delete" >> = fun res ->
255+ assert (res.M. affected_rows = 1 );
256+
257+ M. exec dbh " SELECT v FROM ocaml_mariadb_test"
258+ >> = (function
259+ | Ok _ -> die_f " exec of a SELECT unexpectedly succeeded"
260+ | Error _ -> return () ) >> = fun () ->
261+
262+ M. prepare dbh " SELECT v FROM ocaml_mariadb_test WHERE id = 3"
263+ >> = or_die " prepare after rejected exec"
264+ >> = fun stmt ->
265+ M.Stmt. execute stmt [||] >> = or_die " execute" >> = fun res ->
266+ fetch_single_row res >> = fun row ->
267+ assert (Array. length row = 1 && M.Field. int row.(0 ) = 31 );
268+ M.Stmt. close stmt >> = or_die " Stmt.close" >> = fun () ->
269+
270+ M. exec dbh " MALFORMED STATEMENT"
271+ >> = (function
272+ | Ok _ -> die_f " exec of a malformed statement unexpectedly succeeded"
273+ | Error (errno , _ ) ->
274+ assert (errno = 1064 );
275+ return () ) >> = fun () ->
276+
277+ let n = 16 * 1024 in
278+ let pad = String. make 256 'x' in
279+ let buf = Buffer. create (n * 280 ) in
280+ Buffer. add_string buf " INSERT INTO ocaml_mariadb_test (v, s) VALUES " ;
281+ for i = 0 to n - 1 do
282+ if i > 0 then Buffer. add_char buf ',' ;
283+ bprintf buf " (%d, '%s')" i pad
284+ done ;
285+ M. exec dbh (Buffer. contents buf)
286+ >> = or_die " exec bulk insert" >> = fun res ->
287+ assert (res.M. affected_rows = n);
288+ assert (res.M. insert_id = 5 );
289+
290+ M. close dbh
291+
292+ let test_exec_no_stmt_prepare () =
293+ connect () >> = or_die " connect" >> = fun dbh ->
294+ M. prepare dbh
295+ " SELECT VARIABLE_VALUE FROM information_schema.SESSION_STATUS \
296+ WHERE VARIABLE_NAME = 'Com_stmt_prepare'"
297+ >> = or_die " prepare status" >> = fun status_stmt ->
298+ let stmt_prepare_count () =
299+ M.Stmt. execute status_stmt [||] >> = or_die " execute status" >> = fun res ->
300+ if M.Res. num_rows res = 0 then return None else
301+ fetch_single_row res > |= fun row ->
302+ Some (int_of_string (M.Field. string row.(0 )))
303+ in
304+ stmt_prepare_count () >> = (function
305+ | None -> return ()
306+ | Some count ->
307+ M. exec dbh " CREATE TEMPORARY TABLE ocaml_mariadb_test (v integer)"
308+ >> = or_die " exec create" >> = fun _ ->
309+ repeat 10
310+ (fun () ->
311+ M. exec dbh " INSERT INTO ocaml_mariadb_test (v) VALUES (1), (2)"
312+ >> = or_die " exec insert" >> = fun res ->
313+ assert (res.M. affected_rows = 2 );
314+ return () ) >> = fun () ->
315+ stmt_prepare_count () >> = fun count' ->
316+ assert (count' = Some count);
317+ M. prepare dbh " SELECT v FROM ocaml_mariadb_test WHERE v = ?"
318+ >> = or_die " prepare control" >> = fun control_stmt ->
319+ stmt_prepare_count () >> = fun count'' ->
320+ assert (count'' = Some (count + 1 ));
321+ M.Stmt. close control_stmt >> = or_die " Stmt.close control" )
322+ >> = fun () ->
323+ M.Stmt. close status_stmt >> = or_die " Stmt.close status" >> = fun () ->
324+ M. close dbh
325+
222326 (* Make sure the conversion between timestamps and strings are consistent
223327 * between MariaDB and OCaml. By sending timestamps to be compared as binary
224328 * and as string, this also verifies the MYSQL_TIME encoding. *)
@@ -449,6 +553,8 @@ struct
449553 test_server_properties () >> = fun () ->
450554 test_insert_id () >> = fun () ->
451555 test_txn () >> = fun () ->
556+ test_exec () >> = fun () ->
557+ test_exec_no_stmt_prepare () >> = fun () ->
452558 test_json () >> = fun () ->
453559 test_many_select () >> = fun () ->
454560 test_integer () >> = fun () -> test_bigint ()
0 commit comments