[Pkg-ocaml-maint-commits] [mysql-ocaml] 01/05: Imported Upstream version 1.1.2

Stéphane Glondu glondu at moszumanska.debian.org
Thu Nov 28 07:16:07 UTC 2013


This is an automated email from the git hooks/post-receive script.

glondu pushed a commit to branch master
in repository mysql-ocaml.

commit 0d5af89d7a44c958114586b1370e046d8fc2c0f4
Author: Stephane Glondu <steph at glondu.net>
Date:   Thu Nov 28 08:05:08 2013 +0100

    Imported Upstream version 1.1.2
---
 .gitignore    |  17 ++++++++++
 CHANGES       |   3 ++
 Makefile.in   |   4 +--
 Makefile.msvc |   1 +
 VERSION       |   2 +-
 demo2.ml      |  24 +++++++-------
 mysql.ml      | 104 ++++++++++++++++++++++++++--------------------------------
 mysql.mli     |  99 +++++++++++++++++++++++++++++--------------------------
 mysql_stubs.c |  46 +++++++++++++++++++-------
 9 files changed, 170 insertions(+), 130 deletions(-)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6bc8797
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,17 @@
+doc/
+._d/
+._bcdi/
+._ncdi/
+Makefile
+config.log
+config.status
+*.byte
+*.native
+*.cm[aiox]
+*.cmxa
+*.o
+*.obj
+*.so
+*.dll
+*.lib
+*.a
diff --git a/CHANGES b/CHANGES
index 0a59451..149730f 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+* Tue Nov 19 2013 (1.1.2)
+  * Mysql.Prepared.execute_null (Gregory Bellier)
+
 * Sat May 19 2012 (1.1.1)
   * Support build with ocaml/msvc and ocaml/mingw (Dmitry Grebeniuk)
   * Update build tools (Dmitry Grebeniuk)
diff --git a/Makefile.in b/Makefile.in
index bff0a29..457f27b 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -13,6 +13,7 @@ LDFLAGS=@LDFLAGS@
 export OCAMLMKLIB_FLAGS=@LDFLAGS@
 export OCAMLFIND_INSTFLAGS=-patch-version "$(VERSION)"
 
+build: all opt
 all: byte-code-library 
 opt: native-code-library
 reallyall: byte-code-library native-code-library htdoc
@@ -37,6 +38,5 @@ NAME=ocaml-mysql-$(VERSION)
 .PHONY: release
 release:
 	git tag -a -m $(VERSION) v$(VERSION)
-	git archive --prefix=$(NAME)/ v$(VERSION) | tar --delete $(NAME)/web | gzip > $(NAME).tar.gz
+	git archive --prefix=$(NAME)/ v$(VERSION) | gzip > $(NAME).tar.gz
 	gpg -a -b $(NAME).tar.gz
-
diff --git a/Makefile.msvc b/Makefile.msvc
index ba4107e..cdba215 100644
--- a/Makefile.msvc
+++ b/Makefile.msvc
@@ -13,6 +13,7 @@ LIBINSTALL_FILES=$(wildcard mysql.mli mysql.cm* mysql.a libmysql_stubs.a dllmysq
 
 OCAMLMKLIB=ocamlmklib -ocamlc ocamlc -ocamlopt ocamlopt -verbose
 
+build: all
 all: mysql.cma mysql.cmxa
 
 mysql.cma mysql.cmxa: mysql.ml mysql.mli mysql_stubs.c
diff --git a/VERSION b/VERSION
index 9fdd21e..8ba0ac1 100644
--- a/VERSION
+++ b/VERSION
@@ -2,5 +2,5 @@
   VERSION -- Version Information for mysql (syntax: Text)
   [automatically generated and maintained by GNU shtool]
 
-  This is mysql, Version 1.1.1 (19-May-2012)
+  This is mysql, Version 1.1.2 (19-Nov-2013)
 
diff --git a/demo2.ml b/demo2.ml
index a2c1782..5616ce6 100644
--- a/demo2.ml
+++ b/demo2.ml
@@ -9,7 +9,7 @@ module P = Mysql.Prepared
   Verify safe GC interaction (see CAML_TEST_GC_SAFE in mysql_stubs.c)
   For such test need strings on heap, not statically allocated atoms, hence String.copy
 *)
-let _ = Thread.create (fun () -> 
+let (_:Thread.t) = Thread.create (fun () ->
   let i = ref 0 in 
   while true do Gc.compact(); incr i; if !i mod 100 = 0 then (print_char '.'; flush stdout) done) ()
 
@@ -17,11 +17,14 @@ let s = String.copy
 
 let db = Mysql.quick_connect ~database:(s "test") ~user:(s "root") ()
 
-let _ = Mysql.exec db (s "CREATE TABLE IF NOT EXISTS test(id INT) ENGINE=MEMORY")
+let (_:Mysql.result) = Mysql.exec db (s "CREATE TABLE test(id INT, v VARCHAR(10)) ENGINE=MEMORY")
 let () =
-  let insert = P.create db (s "INSERT INTO test VALUES (?)") in
-  for i = 10 to 20 do
-    ignore (P.execute insert [|string_of_int i|])
+  let insert = P.create db (s "INSERT INTO test VALUES (?,?)") in
+  for i = 10 to 15 do
+    ignore (P.execute insert [|string_of_int i; sprintf "value %d" i|])
+  done;
+  for i = 16 to 20 do
+    ignore (P.execute_null insert [|Some (string_of_int i); None|])
   done;
   P.close insert
 
@@ -32,17 +35,16 @@ let () =
     | None -> ()
   in
   let select = P.create db (s "SELECT * FROM test WHERE id > ?") in
-  print_endline "> 15";
-  loop (P.execute select [|s "15"|]);
-  print_endline "> 20";
-  loop (P.execute select [|s "20"|]);
+  print_endline "> 13";
+  loop (P.execute select [|s "13"|]);
   print_endline "> 19";
   loop (P.execute select [|s "19"|]);
+  print_endline "> 20";
+  loop (P.execute select [|s "20"|]);
   P.close select;
   print_endline "done all";
   ()
 
-let _ = Mysql.exec db (s "DROP TABLE test")
+let (_:Mysql.result) = Mysql.exec db (s "DROP TABLE test")
 
 let () = Mysql.disconnect db
-
diff --git a/mysql.ml b/mysql.ml
index 36b8d48..6d66b00 100644
--- a/mysql.ml
+++ b/mysql.ml
@@ -249,28 +249,27 @@ let error_of_int code = match code with
 
 (* Status of MySQL database after an operation. Especially indicates empty 
    result sets *)
-
-type status     =
-                | StatusOK
-                | StatusEmpty
-                | StatusError of error_code
+type status =
+| StatusOK
+| StatusEmpty
+| StatusError of error_code
 
 (* database field type *)
-
-type dbty       = IntTy         (* 0  *)
-                | FloatTy       (* 1  *)
-                | StringTy      (* 2  *)
-                | SetTy         (* 3  *)
-                | EnumTy        (* 4  *)
-                | DateTimeTy    (* 5  *)
-                | DateTy        (* 6  *)
-                | TimeTy        (* 7  *)
-                | YearTy        (* 8  *)
-                | TimeStampTy   (* 9  *)
-                | UnknownTy     (* 10 *)
-                | Int64Ty       (* 11 *)
-		| BlobTy        (* 12 *)
-		| DecimalTy	(* 13 *)
+type dbty =
+| IntTy         (* 0  *)
+| FloatTy       (* 1  *)
+| StringTy      (* 2  *)
+| SetTy         (* 3  *)
+| EnumTy        (* 4  *)
+| DateTimeTy    (* 5  *)
+| DateTy        (* 6  *)
+| TimeTy        (* 7  *)
+| YearTy        (* 8  *)
+| TimeStampTy   (* 9  *)
+| UnknownTy     (* 10 *)
+| Int64Ty       (* 11 *)
+| BlobTy        (* 12 *)
+| DecimalTy     (* 13 *)
 
 let pretty_type = function
   | IntTy -> "integer"
@@ -351,8 +350,7 @@ let quick_connect ?options ?host ?database ?port ?password ?user ?socket () =
 external change_user : dbd -> db -> unit                    = "db_change_user"
 
 let quick_change ?user ?password ?database conn =
-  change_user conn { defaults with
-		       dbuser = user; dbpwd = password; dbname = database }
+  change_user conn { defaults with dbuser = user; dbpwd = password; dbname = database }
 
 external select_db   : dbd -> string -> unit                = "db_select_db"
 external list_dbs    : dbd -> ?pat:string -> unit -> string array option = "db_list_dbs"
@@ -381,7 +379,7 @@ external fetch_field_dir : result -> int -> field option = "db_fetch_field_dir"
 let status dbd =
   let x = real_status dbd in
   match x with
-    0 -> StatusOK
+  | 0 -> StatusOK
   | 1065 -> StatusEmpty
   | _ -> StatusError (error_of_int x)
 
@@ -389,20 +387,20 @@ let errno dbd = error_of_int (real_status dbd)
 
 (* [sub start len str] returns integer obtained from substring of length 
    [len] from [str] *)
-  
+
 let sub start len str = int_of_string (String.sub str ~pos:start ~len)
 
 (* xxx2ml parses a string returned from a MySQL field typed xxx and turns it into a 
    corresponding OCaml value.
 
    MySQL uses the following representations for date/time values
-    
+
    DATETIME     yyyy-mm-dd hh:mm:ss
    DATE         yyyy-mm-dd'
    TIME         hh:mm:ss'
    YEAR         yyyy'
    TIMESTAMP    YYYYMMDDHHMMSS'
-*)   
+*)
  
 
 let int2ml   str        = int_of_string str
@@ -424,7 +422,7 @@ let set2ml str =
     let tokens      = lexer(Stream.of_string str)                       in
     let rec list    = parser
                       | [< 'Ident i; t = tail >]    -> i :: t
-                      | [< >]                       -> []               
+                      | [< >]                       -> []
     and tail        = parser
                       | [< 'Kwd ","; l = list >]    -> l
                       | [< >]                       -> []               in
@@ -446,30 +444,25 @@ let datetime2ml str =
 
 let date2ml str =
     assert (String.length str = 10);
-
     let year    = sub 0  4 str   in
     let month   = sub 5  2 str   in 
     let day     = sub 8  2 str   in
         (year,month,day)
 
-   
 let time2ml str =
     assert (String.length str = 8);
-     
+
     let hour    = sub 0 2 str   in
     let minute  = sub 3 2 str   in
     let second  = sub 6 2 str   in
         (hour,minute,second)
-    
-                                  
+
 let year2ml str =
     assert (String.length str = 4);
     sub 0 4 str
-    
 
 let timestamp2ml str =
     assert (String.length str = 14);
-
     let year    = sub 0  4 str   in
     let month   = sub 4  2 str   in 
     let day     = sub 6  2 str   in
@@ -479,20 +472,16 @@ let timestamp2ml str =
         (year,month,day,hour,minute,second)
 
 
-            
-
 (* [opt f v] applies [f] to optional value [v]. Use this to fetch
    data of known type from database fields which might be NULL:
    [opt int2ml str] *)
-
 let opt f arg = match arg with 
     | None      -> None
     | Some x    -> Some (f x)
-    
+
 (* [not_null f v] applies [f] to [Some v]. Use this to fetch data of known 
    type from database fields which never can be NULL: [not_null int2ml str] 
 *)
-    
 let not_null f arg = match arg with
     | None      -> fail "not_null was applied to None"
     | Some x    -> f x 
@@ -501,19 +490,19 @@ let not_null f arg = match arg with
 let names result =
   Array.init (fields result) ~f:(function offset ->
     match fetch_field_dir result offset with
-      Some field -> field.name
+    | Some field -> field.name
     | None -> "")
-  
+
 let types result =
   Array.init (fields result) ~f:(function offset ->
     match fetch_field_dir result offset with
-      Some field -> field.ty
+    | Some field -> field.ty
     | None -> (fail "Unknown type in field"))
 
 (* [column result] returns a function [col] which fetches columns from
    results by column name.  [col] has type string -> 'a array -> 'b. 
    Where the first argument is the name of the column. 
-   
+
 
         let r   = exec dbd "select * from table"  in
         let col = col r                           in
@@ -522,10 +511,9 @@ let types result =
             Some a -> not_null int2ml (col "label" a) :: loop (fetch r)
         in 
             loop (fetch r)
-        
+
 *)
 
-        
 let column result =
     let names = names result                                    in
     let map   = (* maps names to positions *)
@@ -541,11 +529,11 @@ let column result =
      let col ~key ~row =
        row.(StrMap.find key map)
      in
-        col
+     col
 
 (* ml2xxx encodes OCaml values into strings that match the MysQL syntax of 
    the corresponding type *)
-  
+
 let ml2str str  = "'" ^ escape str ^ "'"
 let ml2rstr conn str = "'" ^ real_escape conn str ^ "'"
 let ml2blob     = ml2str
@@ -609,10 +597,11 @@ let iter res ~f =
   if size res > Int64.zero then
     let rec loop () =
       match fetch res with
-	  Some row -> f row; loop ()
-	| None -> () in
-      to_row res Int64.zero;
-      loop ()
+      | Some row -> f row; loop ()
+      | None -> ()
+    in
+    to_row res Int64.zero;
+    loop ()
 
 let iter_col res ~key ~f =
   let col = column res ~key in
@@ -626,13 +615,14 @@ let map res ~f =
   if size res > Int64.zero then
     let rec loop lst = 
       match fetch res with
-	  Some row -> loop (f row :: lst)
-	| None -> lst in
-      to_row res Int64.zero;
-      List.rev (loop [])
+      | Some row -> loop (f row :: lst)
+      | None -> lst
+    in
+    to_row res Int64.zero;
+    List.rev (loop [])
   else
     []
-      
+
 let map_col res ~key ~f =
   let col = column res ~key in
   map res ~f:(function row -> f (col ~row))
@@ -648,6 +638,7 @@ type stmt_result
 
 external create : dbd -> string -> stmt = "caml_mysql_stmt_prepare"
 external execute : stmt -> string array -> stmt_result = "caml_mysql_stmt_execute"
+external execute_null : stmt -> string option array -> stmt_result = "caml_mysql_stmt_execute_null"
 external affected : stmt -> int64 = "caml_mysql_stmt_affected"
 external insert_id : stmt -> int64 = "caml_mysql_stmt_insert_id"
 external real_status : stmt -> int = "caml_mysql_stmt_status"
@@ -656,4 +647,3 @@ external result_metadata : stmt -> result = "caml_mysql_stmt_result_metadata"
 external close : stmt -> unit = "caml_mysql_stmt_close"
 
 end
-
diff --git a/mysql.mli b/mysql.mli
index 99397c9..53a8a74 100644
--- a/mysql.mli
+++ b/mysql.mli
@@ -19,9 +19,7 @@
 *)
 
 (**
-
     This module provides access to MySQL databases, roughly following the C API
-
 *)
 
 (** {1 Database connections} *)
@@ -32,13 +30,14 @@
 type dbd
 
 (** Login information for a database. Use [None] for default values *)
-type db         = { dbhost    : string option;  (**    database server host *)
-                dbname    : string option;  (**    database name        *)
-                dbport    : int option;     (**    port                 *)
-                dbpwd     : string option;  (**    user password        *)
-                dbuser    : string option;  (**    database user        *)
-                dbsocket  : string option;  (**    unix socket path     *)
-                } 
+type db = {
+  dbhost    : string option;  (** database server host *)
+  dbname    : string option;  (** database name        *)
+  dbport    : int option;     (** port                 *)
+  dbpwd     : string option;  (** user password        *)
+  dbuser    : string option;  (** database user        *)
+  dbsocket  : string option;  (** unix socket path     *)
+} 
 
 (** Login information using all defaults *)
 val defaults: db
@@ -76,8 +75,7 @@ type db_option =
 | SHARED_MEMORY_BASE_NAME of string (** The name of the shared-memory object for communication to the server 
                                         on Windows, if the server supports shared-memory connections *)
 
-(** [connect ?options db] connects to the database [db] and returns a handle for
-   further use
+(** [connect ?options db] connects to the database [db] and returns a handle for further use
    @param options connection specific options, default empty list
 *)
 val connect : ?options:db_option list -> db -> dbd
@@ -100,15 +98,13 @@ val change_user : dbd -> db -> unit
 (** Another shortcut *)
 val quick_change: ?user:string -> ?password:string -> ?database:string -> dbd -> unit
 
-(** [select_db] Switch to a new db, using the current user and password. *)
+(** [select_db] switches to a new db, using the current user and password. *)
 val select_db   : dbd -> string -> unit
 
-(** [disconnect dbd] releases a database connection [dbd]. The handle [dbd] 
-   becomes invalid *)
+(** [disconnect dbd] releases a database connection [dbd]. The handle [dbd] becomes invalid *)
 val disconnect : dbd -> unit
 
-(** [ping dbd] makes sure the connection to the server is up, and
-   re-establishes it if needed. *)
+(** [ping dbd] makes sure the connection to the server is up, and re-establishes it if needed. *)
 val ping : dbd -> unit
 
 (** {2 Information about a connection} *)
@@ -138,9 +134,10 @@ exception Error of string
 type error_code = Aborting_connection | Access_denied_error | Alter_info | Bad_db_error | Bad_field_error | Bad_host_error | Bad_null_error | Bad_table_error | Blob_cant_have_default | Blob_key_without_length | Blob_used_as_key | Blobs_and_no_terminated | Cant_create_db | Cant_create_file | Cant_create_table | Cant_create_thread | Cant_delete_file | Cant_drop_field_or_key | Cant_find_dl_entry | Cant_find_system_rec | Cant_find_udf | Cant_get_stat | Cant_get_wd | Cant_initialize_udf | Can [...]
 
 (** The status of a query *)
-type status = StatusOK (** The query was successful *)
-	      | StatusEmpty (** The query was successful, but found no results *)
-	      | StatusError of error_code (** There was some problem with the query *)
+type status =
+| StatusOK (** The query was successful *)
+| StatusEmpty (** The query was successful, but found no results *)
+| StatusError of error_code (** There was some problem with the query *)
 
 (** [status dbd] returns the status of the last action on [dbd] *)
 val status : dbd -> status
@@ -158,7 +155,7 @@ val errmsg : dbd -> string option
 (** {2 Making a query} *)
 
 (** handle to access the result of a query *)
-type result     
+type result
 
 (** [exec dbd str] executes a SQL statement and returns a handle to obtain 
    the result. Check [status] for errors! *) 
@@ -184,8 +181,8 @@ val to_row : result -> int64 -> unit
 val size : result -> int64
 
 (** [iter result f] applies f to each row of result in turn, starting
-from the first. iter_col applies f to the value of the named column
-in every row.
+   from the first. iter_col applies f to the value of the named column
+   in every row.
 
    The iter versions return unit, the map versions return a list of
    the results of all the function applications. If there were no rows
@@ -205,24 +202,24 @@ val map_cols : result -> key:string array -> f:(string option array -> 'a) -> 'a
 (** Returns one field of a result row based on column name. *)
 val column : result -> key:string -> row:string option array -> string option
 
-
 (** {2 Metainformation about a result set} *)
 
 (** The type of a database field. Each of these represents one or more MySQL data types. *)
-type dbty       = IntTy          
-                | FloatTy        
-                | StringTy       
-                | SetTy          
-                | EnumTy         
-                | DateTimeTy     
-                | DateTy         
-                | TimeTy         
-                | YearTy         
-                | TimeStampTy    
-                | UnknownTy      
-                | Int64Ty        
-		| BlobTy          
-		| DecimalTy
+type dbty =
+| IntTy
+| FloatTy
+| StringTy
+| SetTy
+| EnumTy
+| DateTimeTy
+| DateTy
+| TimeTy
+| YearTy
+| TimeStampTy
+| UnknownTy
+| Int64Ty
+| BlobTy
+| DecimalTy
 
 (** The type that describes a field of a table or result *)
 type field = { name : string; (** Name of the field *)
@@ -243,19 +240,17 @@ val pretty_type: dbty -> string
 val affected : dbd -> int64
 
 (** [insert_id result] returns the ID generated by the last INSERT
-query in a table with an AUTO_INCREMENT column. See the MySQL
-documentation for caveats. *)
+  query in a table with an AUTO_INCREMENT column. See the MySQL
+  documentation for caveats. *)
 val insert_id: dbd -> int64
-				     
+
 (** [fields result] returns the number of fields in a row *)
 val fields : result -> int
 
-(** [names result] returns an array of the field names for the current result
- *)
+(** [names result] returns an array of the field names for the current result *)
 val names : result -> string array
 
-(** [types result] returns an array with the MySQL types of the current 
-  result *)
+(** [types result] returns an array with the MySQL types of the current result *)
 val types : result -> dbty array
 
 (** Returns the information on the next field *)
@@ -270,15 +265,19 @@ val fetch_field_dir : result -> int -> field option
 (** {1 Working with MySQL data types} *)
 
 (** [escape str] returns the same string as [str] in MySQL syntax with
-  special characters quoted to not confuse the MySQL parser *)
+  special characters quoted to not confuse the MySQL parser.
+
+ at deprecated This function poses a security risk (doesn't take into consideration
+  the character set of the current connection and may allow SQL injection pass through).
+  Use {!real_escape} instead.
+*)
 val escape : string -> string 
 
 (** [real_escape dbd str] returns [str] encoded
   to an escaped SQL string according to the current character set of [dbd] *)
 val real_escape : dbd -> string -> string
 
-(** [xxx2ml str] decodes a MySQL value of type xxx into a corresponding
-  OCaml value *)
+(** [xxx2ml str] decodes a MySQL value of type xxx into a corresponding OCaml value *)
 
 (** Use for all MySQL signed integer types but BIGINT *)
 val int2ml          : string -> int
@@ -325,8 +324,11 @@ val not_null : ('a -> 'b) -> 'a option -> 'b
   [ml2rxxx v] encodes [v] into MySQL syntax using [real_escape].
 *)
 
+(** @deprecated This function uses {!escape} which poses a security risk. Use {!ml2rstr} instead. *)
 val ml2str          : string -> string
 val ml2rstr         : dbd -> string -> string
+
+(** @deprecated This function uses {!escape} which poses a security risk. Use {!ml2rblob} instead. *)
 val ml2blob         : string -> string
 val ml2rblob        : dbd -> string -> string
 val ml2int          : int -> string
@@ -375,6 +377,9 @@ val create : dbd -> string -> stmt
 (** Execute the prepared statement with the specified values for parameters. *)
 val execute : stmt -> string array -> stmt_result
 
+(** Same as {!execute}, but with support for NULL values. *)
+val execute_null : stmt -> string option array -> stmt_result
+
 (** @return Number of rows affected by the last execution of this statement. *)
 val affected : stmt -> int64
 
diff --git a/mysql_stubs.c b/mysql_stubs.c
index 0520560..574a3fb 100644
--- a/mysql_stubs.c
+++ b/mysql_stubs.c
@@ -965,15 +965,25 @@ row_t* create_row(MYSQL_STMT* stmt, size_t count)
   return row;
 }
 
-void set_param(row_t *r, char* str, size_t len, int index)
+void set_param_string(row_t *r, value v, int index)
 {
   MYSQL_BIND* bind = &r->bind[index];
+  size_t len = caml_string_length(v);
 
   r->length[index] = len;
   bind->length = &r->length[index];
   bind->buffer_length = len;
   bind->buffer_type = MYSQL_TYPE_STRING;
-  bind->buffer = (void*)str;
+  bind->buffer = malloc(len);
+  memcpy(bind->buffer, String_val(v), len);
+}
+
+void set_param_null(row_t *r, int index)
+{
+  MYSQL_BIND* bind = &r->bind[index];
+
+  bind->buffer_type = MYSQL_TYPE_NULL;
+  bind->buffer = NULL;
 }
 
 void bind_result(row_t* r, int index)
@@ -1044,45 +1054,47 @@ struct custom_operations stmt_result_ops = {
 #endif
 };
 
-EXTERNAL value
-caml_mysql_stmt_execute(value v_stmt, value v_params)
+value
+caml_mysql_stmt_execute_gen(value v_stmt, value v_params, int with_null)
 {
   CAMLparam2(v_stmt,v_params);
   CAMLlocal2(res,v);
   unsigned int i = 0;
   unsigned int len = Wosize_val(v_params);
   int err = 0;
-  char* bufs[256];
   row_t* row = NULL;
   MYSQL_STMT* stmt = STMTval(v_stmt);
   check_stmt(stmt,"execute");
   if (len != mysql_stmt_param_count(stmt))
     mysqlfailmsg("Prepared.execute : Got %i parameters, but expected %i", len, mysql_stmt_param_count(stmt));
-  if (len > 256)
-    mysqlfailwith("Prepared.execute : too many parameters");
   row = create_row(stmt, len);
   if (!row)
     mysqlfailwith("Prepared.execute : create_row for params");
   for (i = 0; i < len; i++)
   {
     v = Field(v_params,i);
-    bufs[i] = malloc(caml_string_length(v));
-    memcpy(bufs[i],String_val(v),caml_string_length(v));
-    set_param(row,bufs[i],caml_string_length(v),i);
+    if (with_null)
+      if (Val_none == v)
+        set_param_null(row, i);
+      else
+        set_param_string(row, Some_val(v), i);
+    else
+      set_param_string(row, v, i);
   }
   err = mysql_stmt_bind_param(stmt, row->bind);
   if (err)
   {
+    for (i = 0; i < len; i++) free(row->bind[i].buffer);
     destroy_row(row);
-    for (i = 0; i < len; i++) free(bufs[i]);
     mysqlfailmsg("Prepared.execute : mysql_stmt_bind_param = %i",err);
   }
   caml_enter_blocking_section();
   err = mysql_stmt_execute(stmt);
   caml_leave_blocking_section();
 
+  for (i = 0; i < len; i++) free(row->bind[i].buffer);
   destroy_row(row);
-  for (i = 0; i < len; i++) free(bufs[i]);
+
   if (err)
   {
     mysqlfailmsg("Prepared.execute : mysql_stmt_execute = %i, %s",err,mysql_stmt_error(stmt));
@@ -1109,6 +1121,16 @@ caml_mysql_stmt_execute(value v_stmt, value v_params)
   CAMLreturn(res);
 }
 
+EXTERNAL value caml_mysql_stmt_execute(value v_stmt, value v_param)
+{
+  return caml_mysql_stmt_execute_gen(v_stmt, v_param, 0);
+}
+
+EXTERNAL value caml_mysql_stmt_execute_null(value v_stmt, value v_param)
+{
+  return caml_mysql_stmt_execute_gen(v_stmt, v_param, 1);
+}
+
 EXTERNAL value
 caml_mysql_stmt_fetch(value result)
 {

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ocaml-maint/packages/mysql-ocaml.git



More information about the Pkg-ocaml-maint-commits mailing list