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

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

commit 3aa4faffb1ecee264af5c649ad36dec67a483f79
Author: Stephane Glondu <st...@glondu.net>
Date:   Wed Aug 3 15:37:19 2016 +0200

    Imported Upstream version 4.0.0
---
 CHANGES.txt         | 10 ++++++++
 _oasis              |  4 +--
 lib/META            |  4 +--
 lib/sqlite3.ml      |  4 +--
 lib/sqlite3.mli     |  1 -
 lib/sqlite3_stubs.c | 70 ++++++++++++++++++++++++++++++++++++++++++++---------
 myocamlbuild.ml     | 11 ++++++---
 setup.ml            | 11 +++++----
 test/test_error.ml  | 16 ++----------
 9 files changed, 88 insertions(+), 43 deletions(-)

diff --git a/CHANGES.txt b/CHANGES.txt
index 7677443..31a102a 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,13 @@
+2015-09-02: Major API change that is compatible with major release series 2:
+
+            It is now possible to return errors from user-defined SQL-functions
+            by simply raising (arbitrary) exceptions.  This somewhat
+            tricky internal change eliminates the need for Data.ERROR and
+            reestablishes compatibility with major release series 2.
+
+            Sorry for the churn, but the more elegant solution was not
+            quite obvious!
+
 2015-08-29: Added user function error handling (major API change).
 
             Thanks to Joseph Young for this patch!
diff --git a/_oasis b/_oasis
index ecdfa45..89fc385 100644
--- a/_oasis
+++ b/_oasis
@@ -1,6 +1,6 @@
 OASISFormat:      0.4
 Name:             sqlite3
-Version:          3.0.0
+Version:          4.0.0
 Synopsis:         sqlite3-ocaml - SQLite3 bindings
 Description:      sqlite3-ocaml is an OCaml library with bindings to the
                   SQLite3 client API.  Sqlite3 is a self-contained, serverless,
@@ -41,7 +41,7 @@ Library sqlite3
   CCOpt:          -g -O2 -fPIC -DPIC
   if flag(strict) && ccomp_type(cc)
     CCOpt+:       -Wall -pedantic -Wextra -Wunused -Wno-long-long
-  CCLib:          -lsqlite3
+  CCLib:          -lsqlite3 -lpthread
 
 
 # Tests
diff --git a/lib/META b/lib/META
index 83b8d13..2360e7e 100644
--- a/lib/META
+++ b/lib/META
@@ -1,6 +1,6 @@
 # OASIS_START
-# DO NOT EDIT (digest: fc7db74acb0529e253896e714e0a428b)
-version = "3.0.0"
+# DO NOT EDIT (digest: 5c96ba55072fdd9b0770a2d5872a8c6d)
+version = "4.0.0"
 description = "sqlite3-ocaml - SQLite3 bindings"
 archive(byte) = "sqlite3.cma"
 archive(byte, plugin) = "sqlite3.cma"
diff --git a/lib/sqlite3.ml b/lib/sqlite3.ml
index 1eb25be..4f5013a 100644
--- a/lib/sqlite3.ml
+++ b/lib/sqlite3.ml
@@ -112,13 +112,12 @@ module Data = struct
     | FLOAT of float
     | TEXT of string
     | BLOB of string
-    | ERROR of string
 
   let to_string = function
     | NONE | NULL -> ""
     | INT i -> Int64.to_string i
     | FLOAT f -> string_of_float f
-    | TEXT t | BLOB t | ERROR t -> t
+    | TEXT t | BLOB t -> t
 
   let to_string_debug = function
     | NONE -> "NONE"
@@ -127,7 +126,6 @@ module Data = struct
     | FLOAT f -> sprintf "FLOAT <%f>" f
     | TEXT t -> sprintf "TEXT <%S>" t
     | BLOB b -> sprintf "BLOB <%d>" (String.length b)
-    | ERROR e -> sprintf "ERROR <%S>" e
 end
 
 type header = string
diff --git a/lib/sqlite3.mli b/lib/sqlite3.mli
index 0cc7c6a..aa0749a 100644
--- a/lib/sqlite3.mli
+++ b/lib/sqlite3.mli
@@ -142,7 +142,6 @@ module Data : sig
     | FLOAT of float
     | TEXT of string
     | BLOB of string
-    | ERROR of string
 
   val to_string : t -> string
   (** [to_string data] converts [data] to a string.  Both [NONE] and
diff --git a/lib/sqlite3_stubs.c b/lib/sqlite3_stubs.c
index 2abcedb..f34d90d 100644
--- a/lib/sqlite3_stubs.c
+++ b/lib/sqlite3_stubs.c
@@ -37,6 +37,7 @@
 #include <caml/signals.h>
 
 #include <sqlite3.h>
+#include <pthread.h>
 
 #if __GNUC__ >= 3
 # define inline inline __attribute__ ((always_inline))
@@ -105,6 +106,46 @@ typedef struct stmt_wrap {
 } stmt_wrap;
 
 
+/* Handling of exceptions in user-defined SQL-functions */
+
+/* For propagating exceptions from user-defined SQL-functions */
+static pthread_key_t user_exception_key;
+
+typedef struct user_exception { value exn; } user_exception;
+
+static inline void create_user_exception(value v_exn)
+{
+  user_exception *user_exn = caml_stat_alloc(sizeof(user_exception));
+  user_exn->exn = v_exn;
+  caml_register_global_root(&user_exn->exn);
+  pthread_setspecific(user_exception_key, user_exn);
+}
+
+static inline void destroy_user_exception(void *user_exc_)
+{
+  user_exception *user_exn = user_exc_;
+  caml_remove_global_root(&user_exn->exn);
+  free(user_exn);
+}
+
+static inline void maybe_raise_user_exception(int rc)
+{
+  if (rc == SQLITE_ERROR) {
+    user_exception *user_exn = pthread_getspecific(user_exception_key);
+
+    if (user_exn != NULL) {
+      CAMLparam0();
+      CAMLlocal1(v_exn);
+      v_exn = user_exn->exn;
+      destroy_user_exception(user_exn);
+      pthread_setspecific(user_exception_key, NULL);
+      caml_raise(v_exn);
+      CAMLnoreturn;
+    }
+  }
+}
+
+
 /* Macros to access the wrapper structures stored in the custom blocks */
 
 #define Sqlite3_val(x) (*((db_wrap **) (Data_custom_val(x))))
@@ -120,11 +161,11 @@ static value *caml_sqlite3_RangeError = NULL;
 static inline void raise_with_two_args(value v_tag, value v_arg1, value v_arg2)
 {
   CAMLparam3(v_tag, v_arg1, v_arg2);
-  value v_exc = caml_alloc_small(3, 0);
-  Field(v_exc, 0) = v_tag;
-  Field(v_exc, 1) = v_arg1;
-  Field(v_exc, 2) = v_arg2;
-  caml_raise(v_exc);
+  value v_exn = caml_alloc_small(3, 0);
+  Field(v_exn, 0) = v_tag;
+  Field(v_exn, 1) = v_arg1;
+  Field(v_exn, 2) = v_arg2;
+  caml_raise(v_exn);
   CAMLnoreturn;
 }
 
@@ -215,6 +256,7 @@ CAMLprim value caml_sqlite3_init(value __unused v_unit)
   caml_sqlite3_InternalError = caml_named_value("Sqlite3.InternalError");
   caml_sqlite3_Error = caml_named_value("Sqlite3.Error");
   caml_sqlite3_RangeError = caml_named_value("Sqlite3.RangeError");
+  pthread_key_create(&user_exception_key, destroy_user_exception);
   return Val_unit;
 }
 
@@ -521,6 +563,7 @@ CAMLprim value caml_sqlite3_exec(value v_db, value 
v_maybe_cb, value v_sql)
   caml_leave_blocking_section();
 
   if (rc == SQLITE_ABORT) caml_raise(*cbx.exn);
+  maybe_raise_user_exception(rc);
 
   CAMLreturn(Val_rc(rc));
 }
@@ -570,6 +613,7 @@ CAMLprim value caml_sqlite3_exec_no_headers(value v_db, 
value v_cb, value v_sql)
   caml_leave_blocking_section();
 
   if (rc == SQLITE_ABORT) caml_raise(*cbx.exn);
+  maybe_raise_user_exception(rc);
 
   CAMLreturn(Val_rc(rc));
 }
@@ -633,6 +677,8 @@ CAMLprim value caml_sqlite3_exec_not_null(value v_db, value 
v_cb, value v_sql)
     if (*cbx.exn != 0) caml_raise(*cbx.exn);
     else raise_sqlite3_Error("Null element in row");
   }
+  maybe_raise_user_exception(rc);
+
   CAMLreturn(Val_rc(rc));
 }
 
@@ -692,6 +738,8 @@ CAMLprim value caml_sqlite3_exec_not_null_no_headers(
     if (*cbx.exn != 0) caml_raise(*cbx.exn);
     else raise_sqlite3_Error("Null element in row");
   }
+  maybe_raise_user_exception(rc);
+
   CAMLreturn(Val_rc(rc));
 }
 
@@ -847,7 +895,6 @@ CAMLprim value caml_sqlite3_bind(value v_stmt, value 
v_index, value v_data)
                                         String_val(v_field),
                                         caml_string_length(v_field),
                                         SQLITE_TRANSIENT));
-      case 4 : return Val_rc(SQLITE_ERROR);
     }
   }
   return Val_rc(SQLITE_ERROR);
@@ -1002,14 +1049,16 @@ static inline value caml_sqlite3_wrap_values(int argc, 
sqlite3_value **args)
   }
 }
 
-static inline void exception_result(sqlite3_context *ctx)
+static inline void exception_result(sqlite3_context *ctx, value v_res)
 {
+  value v_exn = Extract_exception(v_res);
+  create_user_exception(v_exn);
   sqlite3_result_error(ctx, "OCaml callback raised an exception", -1);
 }
 
 static inline void set_sqlite3_result(sqlite3_context *ctx, value v_res)
 {
-  if (Is_exception_result(v_res)) exception_result(ctx);
+  if (Is_exception_result(v_res)) exception_result(ctx, v_res);
   else if (Is_long(v_res)) sqlite3_result_null(ctx);
   else {
     value v = Field(v_res, 0);
@@ -1024,9 +1073,6 @@ static inline void set_sqlite3_result(sqlite3_context 
*ctx, value v_res)
         sqlite3_result_blob(
           ctx, String_val(v), caml_string_length(v), SQLITE_TRANSIENT);
         break;
-      case 4 :
-        sqlite3_result_error(ctx, String_val(v), caml_string_length(v));
-        break;
       default :
         sqlite3_result_error(ctx, "unknown value returned by callback", -1);
     }
@@ -1064,7 +1110,7 @@ static inline void caml_sqlite3_user_function_step(
     }
     v_args = caml_sqlite3_wrap_values(argc, argv);
     v_res = caml_callback2_exn(Field(data->v_fun, 2), agg_ctx->v_acc, v_args);
-    if (Is_exception_result(v_res)) exception_result(ctx);
+    if (Is_exception_result(v_res)) exception_result(ctx, v_res);
     else agg_ctx->v_acc = v_res;
   caml_enter_blocking_section();
 }
diff --git a/myocamlbuild.ml b/myocamlbuild.ml
index 6e97ca5..ae55ac0 100644
--- a/myocamlbuild.ml
+++ b/myocamlbuild.ml
@@ -1,5 +1,5 @@
 (* OASIS_START *)
-(* DO NOT EDIT (digest: 8856c7fbdf56cf3b352c8f24a59be7a0) *)
+(* DO NOT EDIT (digest: 1308fb3d48472c2edc4cc51c862b6705) *)
 module OASISGettext = struct
 (* # 22 "src/oasis/OASISGettext.ml" *)
 
@@ -651,9 +651,12 @@ let package_default =
                    ])
             ]);
           (["oasis_library_sqlite3_cclib"; "link"],
-            [(OASISExpr.EBool true, S [A "-cclib"; A "-lsqlite3"])]);
+            [
+               (OASISExpr.EBool true,
+                 S [A "-cclib"; A "-lsqlite3"; A "-cclib"; A "-lpthread"])
+            ]);
           (["oasis_library_sqlite3_cclib"; "ocamlmklib"; "c"],
-            [(OASISExpr.EBool true, S [A "-lsqlite3"])])
+            [(OASISExpr.EBool true, S [A "-lsqlite3"; A "-lpthread"])])
        ];
      includes = [("test", ["lib"])]
   }
@@ -663,7 +666,7 @@ let conf = {MyOCamlbuildFindlib.no_automatic_syntax = false}
 
 let dispatch_default = MyOCamlbuildBase.dispatch_default conf package_default;;
 
-# 667 "myocamlbuild.ml"
+# 670 "myocamlbuild.ml"
 (* OASIS_STOP *)
 
 let read_lines_from_cmd ~max_lines cmd =
diff --git a/setup.ml b/setup.ml
index 19c2d02..5e395db 100644
--- a/setup.ml
+++ b/setup.ml
@@ -1,7 +1,7 @@
 (* setup.ml generated for the first time by OASIS v0.3.0 *)
 
 (* OASIS_START *)
-(* DO NOT EDIT (digest: 51146b2c34f38bae10732375ae42aa0e) *)
+(* DO NOT EDIT (digest: 1b6fe2a99f7d4b7e0a8fcaf32a49dc1a) *)
 (*
    Regenerated by OASIS v0.4.5
    Visit http://oasis.forge.ocamlcore.org for more information and
@@ -6981,7 +6981,7 @@ let setup_t =
           alpha_features = [];
           beta_features = [];
           name = "sqlite3";
-          version = "3.0.0";
+          version = "4.0.0";
           license =
             OASISLicense.DEP5License
               (OASISLicense.DEP5Unit
@@ -7097,7 +7097,8 @@ let setup_t =
                                 "-Wno-long-long"
                              ])
                         ];
-                      bs_cclib = [(OASISExpr.EBool true, ["-lsqlite3"])];
+                      bs_cclib =
+                        [(OASISExpr.EBool true, ["-lsqlite3"; "-lpthread"])];
                       bs_dlllib = [(OASISExpr.EBool true, [])];
                       bs_dllpath = [(OASISExpr.EBool true, [])];
                       bs_byteopt = [(OASISExpr.EBool true, [])];
@@ -7511,7 +7512,7 @@ let setup_t =
        };
      oasis_fn = Some "_oasis";
      oasis_version = "0.4.5";
-     oasis_digest = Some "��]]�\1486t\133\000&�� M�";
+     oasis_digest = Some "�7�\022\139Ku�e��_��\019?";
      oasis_exec = None;
      oasis_setup_args = [];
      setup_update = false
@@ -7519,6 +7520,6 @@ let setup_t =
 
 let setup () = BaseSetup.setup setup_t;;
 
-# 7523 "setup.ml"
+# 7524 "setup.ml"
 (* OASIS_STOP *)
 let () = setup ();;
diff --git a/test/test_error.ml b/test/test_error.ml
index 2b805f8..048e8e6 100644
--- a/test/test_error.ml
+++ b/test/test_error.ml
@@ -3,18 +3,6 @@ open Sqlite3
 (* Tests our ability to return an error from a user defined function *)
 let () =
   let db = db_open "t" in
-  create_fun0 db "MYERROR" (fun () -> Data.ERROR "This function always 
errors");
+  create_fun0 db "MYERROR" (fun () -> failwith "This function always errors");
   let res = exec db "SELECT MYERROR();" in
-  match res with
-  | Rc.ERROR -> print_endline (errmsg db)
-  | x -> prerr_endline ("Should have thrown an error: " ^ Rc.to_string x)
-
-(* Insures that we can't bind an error to a query *)
-let () =
-  let db = db_open "t" in
-  let _ : Rc.t = exec db "CREATE TABLE foo (val text);" in
-  let s = Sqlite3.prepare db "INSERT INTO foo values (?);" in
-  let res = Sqlite3.bind s 1 (Sqlite3.Data.ERROR "Should be impossible") in
-  match res with
-  | Rc.ERROR -> print_endline ("Bind threw an error")
-  | x -> prerr_endline ("Should have thrown an error: " ^ Rc.to_string x)
+  prerr_endline ("Should have thrown an error: " ^ Rc.to_string res)

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

_______________________________________________
Pkg-ocaml-maint-commits mailing list
Pkg-ocaml-maint-commits@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-ocaml-maint-commits

Reply via email to