Blob


1 // This is free and unencumbered software released into the public domain.
2 //
3 // Anyone is free to copy, modify, publish, use, compile, sell, or
4 // distribute this software, either in source code form or as a compiled
5 // binary, for any purpose, commercial or non-commercial, and by any
6 // means.
7 //
8 // In jurisdictions that recognize copyright laws, the author or authors
9 // of this software dedicate any and all copyright interest in the
10 // software to the public domain. We make this dedication for the benefit
11 // of the public at large and to the detriment of our heirs and
12 // successors. We intend this dedication to be an overt act of
13 // relinquishment in perpetuity of all present and future rights to this
14 // software under copyright law.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 // OTHER DEALINGS IN THE SOFTWARE.
24 use strings;
25 use types;
26 use types::c;
28 export type conn = *opaque;
29 export type statement = *opaque;
31 export def OPEN_READONLY: int = 0x00000001;
32 export def OPEN_READWRITE: int = 0x00000002;
33 export def OPEN_CREATE: int = 0x00000004;
34 export def OPEN_DELETEONCLOSE: int = 0x00000008; // VFS only
35 export def OPEN_EXCLUSIVE: int = 0x00000010; // VFS only
36 export def OPEN_AUTOPROXY: int = 0x00000020; // VFS only
37 export def OPEN_URI: int = 0x00000040;
38 // ...
39 export def OPEN_NOMUTEX: int = 0x00008000;
40 // ..
41 export def OPEN_WAL: int = 0x00080000; // VFS only
42 export def OPEN_NOFOLLOW: int = 0x01000000;
43 export def OPEN_EXRESCODE: int = 0x02000000;
45 export def def_open_flags = OPEN_READWRITE | OPEN_CREATE | OPEN_WAL |
46 OPEN_URI | OPEN_NOMUTEX;
48 @symbol("sqlite3_open_v2") fn libsqlite3_open_v2(
49 filename: *const c::char,
50 sqlite3: *opaque,
51 flags: int,
52 vfs: nullable *const c::char,
53 ) int;
55 // XXX vfs support?
56 export fn open(filename: const str, flags: int...) (conn | error) = {
57 let f = if (len(flags) == 0) def_open_flags else flags[0];
59 let path = c::fromstr(filename);
60 defer free(path);
62 let addr: uintptr = 0;
63 let ret = libsqlite3_open_v2(path, &addr: *opaque, f, null);
64 if (ret == sqlite_ok) {
65 return (addr: *opaque): conn;
66 };
67 return code2err(ret);
68 };
70 @symbol("sqlite3_close_v2") fn libsqlite3_close_v2(sqlite3: *opaque) int;
72 export fn close(conn: conn) (void | error) = {
73 let ret = libsqlite3_close_v2(conn: *opaque);
74 if (ret != sqlite_ok) {
75 return code2err(ret);
76 };
77 };
79 @symbol("sqlite3_prepare_v2") fn libsqlite3_prepare_v2(
80 sqlite3: *opaque,
81 sql: *const c::char,
82 nbyte: int,
83 stmt: *opaque,
84 tail: nullable *opaque,
85 ) int;
87 export fn prepare(conn: conn, sql: const str) (statement | error) = {
88 let s = c::fromstr(sql);
89 defer free(s);
91 let stmt: uintptr = 0;
92 let ret = libsqlite3_prepare_v2(conn: *opaque, s, -1, &stmt: *opaque,
93 null);
94 if (ret == sqlite_ok) {
95 return stmt: statement;
96 };
97 return code2err(ret);
98 };
100 // XXX missing
101 // sqlite3_bind_blob
102 // sqlite3_bind_blob64
103 // sqlite3_bind_double
105 @symbol("sqlite3_bind_parameter_index") fn libsqlite3_bind_parameter_index(
106 stmt: *opaque,
107 name: *const c::char,
108 ) int;
110 fn bind_parameter_index(stmt: statement, col: (str | int)) (int | error) = {
111 let name = match (col) {
112 case let n: int => return n;
113 case let n: str => yield n;
114 };
116 let n = c::fromstr(name);
117 defer free(n);
119 let ret = libsqlite3_bind_parameter_index(stmt: *opaque, n);
120 if (ret == 0) {
121 return sqlite_error;
122 };
124 return ret;
125 };
127 @symbol("sqlite3_bind_int") fn libsqlite3_bind_int(
128 stmt: *opaque,
129 col: int,
130 val: int,
131 ) int;
133 export fn bind_int(stmt: statement, col: (str | int), v: int) (void | error) = {
134 let n = bind_parameter_index(stmt, col)?;
135 let ret = libsqlite3_bind_int(stmt: *opaque, n, v);
136 if (ret != sqlite_ok) {
137 return code2err(ret);
138 };
139 };
141 @symbol("sqlite3_bind_null") fn libsqlite3_bind_null(
142 stmt: *opaque,
143 col: int,
144 ) int;
146 export fn bind_null(stmt: statement, col: (str | int)) (void | error) = {
147 let n = bind_parameter_index(stmt, col)?;
148 let ret = libsqlite3_bind_null(stmt: *opaque, n);
149 if (ret != sqlite_ok) {
150 return code2err(ret);
151 };
152 };
154 fn freecstr(s: *opaque) void = free(s: *c::char);
156 @symbol("sqlite3_bind_text") fn libsqlite3_bind_text(
157 stmt: *opaque,
158 col: int,
159 val: *const c::char,
160 bytelen: int,
161 freefn: *fn(*opaque) void
162 ) int;
164 export fn bind_text(stmt: statement, col: (str | int), v: str) (void | error) = {
165 let n = bind_parameter_index(stmt, col)?;
167 let s = c::fromstr(v);
168 // free'd via the callback
170 let ret = libsqlite3_bind_text(stmt: *opaque, n, s, -1, &freecstr);
171 if (ret != sqlite_ok) {
172 return code2err(ret);
173 };
174 };
176 export fn bind(
177 stmt: statement,
178 col: (str | int),
179 val: (int | void | str),
180 ) (void | error) = {
181 match (val) {
182 case let v: int => return bind_int(stmt, col, v);
183 case let v: void => return bind_null(stmt, col);
184 case let v: str => return bind_text(stmt, col, v);
185 };
186 };
188 @symbol("sqlite3_step") fn libsqlite3_step(stmt: *opaque) int;
190 export fn step(stmt: statement) (bool | error) = {
191 let ret = libsqlite3_step(stmt: *opaque);
192 switch (ret) {
193 case sqlite_row => return true;
194 case sqlite_done => return false;
195 case => return code2err(ret);
196 };
197 };
199 @symbol("sqlite3_column_text") fn libsqlite3_column_text(
200 stmt: *opaque,
201 col: int,
202 ) *const c::char;
204 export fn column_text(stmt: statement, col: int) const str = {
205 let s = libsqlite3_column_text(stmt: *opaque, col);
206 if (s == null) {
207 return "";
208 };
209 return c::tostr_unsafe(s);
210 };
212 @symbol("sqlite3_column_int") fn libsqlite3_column_int(
213 stmt: *opaque,
214 col: int,
215 ) int;
217 export fn column_int(stmt: statement, col: int) int = {
218 return libsqlite3_column_int(stmt: *opaque, col);
219 };
221 @symbol("sqlite3_finalize") fn libsqlite3_finalize(stmt: *opaque) int;
223 export fn finalize(stmt: statement) (void | error) = {
224 let ret = libsqlite3_finalize(stmt: *opaque);
225 if (ret != sqlite_ok) {
226 return code2err(ret);
227 };
228 };
230 @symbol("sqlite3_reset") fn libsqlite3_reset(stmt: *opaque) int;
232 export fn reset(stmt: statement) (void | error) = {
233 let ret = libsqlite3_reset(stmt: *opaque);
234 if (ret != sqlite_ok) {
235 return code2err(ret);
236 };
237 };
239 @symbol("sqlite3_clear_bindings") fn libsqlite3_clear_bindings(stmt: *opaque) int;
241 export fn clear_bindings(stmt: statement) (void | error) = {
242 let ret = libsqlite3_clear_bindings(stmt: *opaque);
243 if (ret != sqlite_ok) {
244 return code2err(ret);
245 };
246 };