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 export def OPEN_MEMORY: int = 0x00000080;
39 export def OPEN_MAIN_DB: int = 0x00000100; // VFS only
40 export def OPEN_TEMP_DB: int = 0x00000200; // VFS only
41 export def OPEN_TRANSIENT_DB: int = 0x00000400; // VFS ONLY
42 export def OPEN_MAIN_JOURNAL: int = 0x00000800; // VFS ONLY
43 export def OPEN_TEMP_JOURNAL: int = 0x00001000; // VFS ONLY
44 export def OPEN_SUBJOURNAL: int = 0x00002000; // VFS ONLY
45 export def OPEN_SUPER_JOURNAL: int = 0x00004000; // VFS ONLY
46 export def OPEN_NOMUTEX: int = 0x00008000;
47 export def OPEN_FULLMUTEX: int = 0x00010000;
48 export def OPEN_SHAREDCACHE: int = 0x00020000;
49 export def OPEN_PRIVATECACHE: int = 0x00040000;
50 export def OPEN_WAL: int = 0x00080000; // VFS only
51 export def OPEN_NOFOLLOW: int = 0x01000000;
52 export def OPEN_EXRESCODE: int = 0x02000000;
54 export def def_open_flags = OPEN_READWRITE | OPEN_CREATE | OPEN_WAL |
55 OPEN_URI | OPEN_NOMUTEX;
57 @symbol("sqlite3_open_v2") fn libsqlite3_open_v2(
58 filename: *const c::char,
59 sqlite3: *opaque,
60 flags: int,
61 vfs: nullable *const c::char,
62 ) int;
64 // Opens an SQLite database file as specified by the filename
65 // argument. If no flags are provided, [[def_open_flags]] is assumed.
66 // The OPEN_WAL flag is "abused" to implicitly enable the WAL journal
67 // mode if specified, as it's not a valid open flag otherwise.
68 export fn open(filename: const str, flags: int...) (conn | error) = {
69 // XXX VFS support?
71 let f = if (len(flags) == 0) def_open_flags else flags[0];
73 let use_wal: bool = (f & OPEN_WAL) != 0;
74 f &= ~OPEN_WAL;
76 let path = c::fromstr(filename);
77 defer free(path);
79 let addr: uintptr = 0;
80 let ret = libsqlite3_open_v2(path, &addr: *opaque, f, null);
81 if (ret != sqlite_ok) {
82 return code2err(ret);
83 };
85 let conn = addr: *opaque: conn;
87 if (use_wal) {
88 let stmt = prepare(conn, "PRAGMA journal_mode=wal;")?;
89 defer finalize(stmt)!; // cannot propagate error in defer
90 runstmt(stmt)?;
91 };
93 return conn;
94 };
96 @symbol("sqlite3_close_v2") fn libsqlite3_close_v2(sqlite3: *opaque) int;
98 // Closes a database connection.
99 export fn close(conn: conn) (void | error) = {
100 let ret = libsqlite3_close_v2(conn: *opaque);
101 if (ret != sqlite_ok) {
102 return code2err(ret);
103 };
104 };
106 @symbol("sqlite3_prepare_v2") fn libsqlite3_prepare_v2(
107 sqlite3: *opaque,
108 sql: *const c::char,
109 nbyte: int,
110 stmt: *opaque,
111 tail: nullable *opaque,
112 ) int;
114 // Prepares a statement that would run the given SQL. Parameters in
115 // the query can be specified using ?, ?NNN, :VVV, @VVV or $VVV (with
116 // NNN being a integer literal and VVV an alphanumeric identifier) and
117 // later set with [[bind]]. The statement can then ran with [[step]].
118 // A statement can be reused by calling [[reset]] (and optionally
119 // [[clear_bindings]] too). Once a statement is no longer needed it
120 // should be destroyed with [[finalize]].
121 export fn prepare(conn: conn, sql: const str) (statement | error) = {
122 let s = c::fromstr(sql);
123 defer free(s);
125 let stmt: uintptr = 0;
126 let ret = libsqlite3_prepare_v2(conn: *opaque, s, -1, &stmt: *opaque,
127 null);
128 if (ret == sqlite_ok) {
129 return stmt: statement;
130 };
131 return code2err(ret);
132 };
134 // XXX missing
135 // sqlite3_bind_blob
136 // sqlite3_bind_blob64
137 // sqlite3_bind_double
139 @symbol("sqlite3_bind_parameter_index") fn libsqlite3_bind_parameter_index(
140 stmt: *opaque,
141 name: *const c::char,
142 ) int;
144 fn bind_parameter_index(stmt: statement, col: (str | int)) (int | error) = {
145 let name = match (col) {
146 case let n: int => return n;
147 case let n: str => yield n;
148 };
150 let n = c::fromstr(name);
151 defer free(n);
153 let ret = libsqlite3_bind_parameter_index(stmt: *opaque, n);
154 if (ret == 0) {
155 return range;
156 };
158 return ret;
159 };
161 @symbol("sqlite3_bind_int") fn libsqlite3_bind_int(
162 stmt: *opaque,
163 col: int,
164 val: int,
165 ) int;
167 // Binds an integer value to the parameter given by name or index.
168 export fn bind_int(stmt: statement, col: (str | int), v: int) (void | error) = {
169 let n = bind_parameter_index(stmt, col)?;
170 let ret = libsqlite3_bind_int(stmt: *opaque, n, v);
171 if (ret != sqlite_ok) {
172 return code2err(ret);
173 };
174 };
176 @symbol("sqlite3_bind_null") fn libsqlite3_bind_null(
177 stmt: *opaque,
178 col: int,
179 ) int;
181 // Binds a NULL value to the parameter given by name or index.
182 export fn bind_null(stmt: statement, col: (str | int)) (void | error) = {
183 let n = bind_parameter_index(stmt, col)?;
184 let ret = libsqlite3_bind_null(stmt: *opaque, n);
185 if (ret != sqlite_ok) {
186 return code2err(ret);
187 };
188 };
190 fn freecstr(s: *opaque) void = free(s: *c::char);
192 @symbol("sqlite3_bind_text") fn libsqlite3_bind_text(
193 stmt: *opaque,
194 col: int,
195 val: *const c::char,
196 bytelen: int,
197 freefn: *fn(*opaque) void
198 ) int;
200 // Binds a text value to the parameter given by name or index.
201 export fn bind_text(stmt: statement, col: (str | int), v: str) (void | error) = {
202 let n = bind_parameter_index(stmt, col)?;
204 let s = c::fromstr(v);
205 // free'd via the callback
207 let ret = libsqlite3_bind_text(stmt: *opaque, n, s, -1, &freecstr);
208 if (ret != sqlite_ok) {
209 return code2err(ret);
210 };
211 };
213 // Binds a value to the parameter given by name or index.
214 export fn bind(
215 stmt: statement,
216 col: (str | int),
217 val: (int | void | str),
218 ) (void | error) = {
219 match (val) {
220 case let v: int => return bind_int(stmt, col, v);
221 case let v: void => return bind_null(stmt, col);
222 case let v: str => return bind_text(stmt, col, v);
223 };
224 };
226 @symbol("sqlite3_step") fn libsqlite3_step(stmt: *opaque) int;
228 // Runs the statement. This function may need to be called more than
229 // one time to evaluate a statement. A return value of false means
230 // that the statement was completely executed, true that it should be
231 // called again, otherwise an error is returned.
232 export fn step(stmt: statement) (bool | error) = {
233 let ret = libsqlite3_step(stmt: *opaque);
234 switch (ret) {
235 case sqlite_row => return true;
236 case sqlite_done => return false;
237 case => return code2err(ret);
238 };
239 };
241 @symbol("sqlite3_column_text") fn libsqlite3_column_text(
242 stmt: *opaque,
243 col: int,
244 ) *const c::char;
246 // Extracts the value of a column as a string. A NULL value is turned
247 // into the empty string "".
248 export fn column_text(stmt: statement, col: int) const str = {
249 let s = libsqlite3_column_text(stmt: *opaque, col);
250 if (s == null) {
251 return "";
252 };
253 return c::tostr_unsafe(s);
254 };
256 @symbol("sqlite3_column_int") fn libsqlite3_column_int(
257 stmt: *opaque,
258 col: int,
259 ) int;
261 // Extracts the values of a column as an integer.
262 export fn column_int(stmt: statement, col: int) int = {
263 return libsqlite3_column_int(stmt: *opaque, col);
264 };
266 @symbol("sqlite3_finalize") fn libsqlite3_finalize(stmt: *opaque) int;
268 // Deallocates a statement.
269 export fn finalize(stmt: statement) (void | error) = {
270 let ret = libsqlite3_finalize(stmt: *opaque);
271 if (ret != sqlite_ok) {
272 return code2err(ret);
273 };
274 };
276 @symbol("sqlite3_reset") fn libsqlite3_reset(stmt: *opaque) int;
278 // Resets a statement so that it can be run again. It doesn't clear
279 // the bindings, for that use [[clear_bindings]] too.
280 export fn reset(stmt: statement) (void | error) = {
281 let ret = libsqlite3_reset(stmt: *opaque);
282 if (ret != sqlite_ok) {
283 return code2err(ret);
284 };
285 };
287 @symbol("sqlite3_clear_bindings") fn libsqlite3_clear_bindings(stmt: *opaque) int;
289 // Clears the bindings associated with a statement.
290 export fn clear_bindings(stmt: statement) (void | error) = {
291 let ret = libsqlite3_clear_bindings(stmt: *opaque);
292 if (ret != sqlite_ok) {
293 return code2err(ret);
294 };
295 };
297 // Helper that runs a statement until it has been fully processed.
298 export fn runstmt(stmt: statement) (void | error) = {
299 for (step(stmt)?) {
300 continue;
301 };
302 };