Skip to content

Commit f8e8400

Browse files
committed
Added support for user-defined function errors
I added a new data type called ERROR, which should allow user defined functions to return errors, which are then raised by SQLite3.
1 parent 5fe410b commit f8e8400

File tree

5 files changed

+42
-1
lines changed

5 files changed

+42
-1
lines changed

_oasis

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,19 @@ Test test_stmt
112112
WorkingDirectory: test
113113
PostCommand: rm t
114114

115+
Executable test_error
116+
Path: test
117+
MainIs: test_error.ml
118+
Build$: flag(tests)
119+
Install: false
120+
BuildDepends: sqlite3
121+
CompiledObject: best
122+
123+
Test test_error
124+
Run$: flag(tests)
125+
Command: $test_error
126+
WorkingDirectory: test
127+
115128
#
116129

117130
Document API

lib/sqlite3.ml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,13 @@ module Data = struct
112112
| FLOAT of float
113113
| TEXT of string
114114
| BLOB of string
115+
| ERROR of string
115116

116117
let to_string = function
117118
| NONE | NULL -> ""
118119
| INT i -> Int64.to_string i
119120
| FLOAT f -> string_of_float f
120-
| TEXT t | BLOB t -> t
121+
| TEXT t | BLOB t | ERROR t -> t
121122

122123
let to_string_debug = function
123124
| NONE -> "NONE"
@@ -126,6 +127,7 @@ module Data = struct
126127
| FLOAT f -> sprintf "FLOAT <%f>" f
127128
| TEXT t -> sprintf "TEXT <%S>" t
128129
| BLOB b -> sprintf "BLOB <%d>" (String.length b)
130+
| ERROR e -> sprintf "ERROR <%S>" e
129131
end
130132

131133
type header = string

lib/sqlite3.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ module Data : sig
142142
| FLOAT of float
143143
| TEXT of string
144144
| BLOB of string
145+
| ERROR of string
145146

146147
val to_string : t -> string
147148
(** [to_string data] converts [data] to a string. Both [NONE] and

lib/sqlite3_stubs.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,8 @@ CAMLprim value caml_sqlite3_bind(value v_stmt, value v_index, value v_data)
847847
String_val(v_field),
848848
caml_string_length(v_field),
849849
SQLITE_TRANSIENT));
850+
case 4 :
851+
return Val_rc(SQLITE_ERROR);
850852
}
851853
}
852854
return Val_rc(SQLITE_ERROR);
@@ -1023,6 +1025,9 @@ static inline void set_sqlite3_result(sqlite3_context *ctx, value v_res)
10231025
sqlite3_result_blob(
10241026
ctx, String_val(v), caml_string_length(v), SQLITE_TRANSIENT);
10251027
break;
1028+
case 4 :
1029+
sqlite3_result_error(ctx, String_val(v), caml_string_length(v));
1030+
break;
10261031
default :
10271032
sqlite3_result_error(ctx, "unknown value returned by callback", -1);
10281033
}

test/test_error.ml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
open Sqlite3
2+
3+
(* Tests our ability to return an error from a user defined function *)
4+
let _ =
5+
let db = db_open "t" in
6+
create_fun0 db "MYERROR" (fun () -> Data.ERROR "This function always errors");
7+
let res = exec db "SELECT MYERROR();" in
8+
match res with
9+
| Rc.ERROR -> print_endline (errmsg db)
10+
| x -> prerr_endline ("Should have thrown an error: " ^ Rc.to_string x)
11+
12+
(* Insures that we can't bind an error to a query *)
13+
let _ =
14+
let db = db_open "t" in
15+
let _ = exec db "CREATE TABLE foo (val text);" in
16+
let s = Sqlite3.prepare db "INSERT INTO foo values (?);" in
17+
let res = Sqlite3.bind s 1 (Sqlite3.Data.ERROR "Should be impossible") in
18+
match res with
19+
| Rc.ERROR -> print_endline ("Bind threw an error")
20+
| x -> prerr_endline ("Should have thrown an error: " ^ Rc.to_string x)

0 commit comments

Comments
 (0)