// This is free and unencumbered software released into the public domain. // // Anyone is free to copy, modify, publish, use, compile, sell, or // distribute this software, either in source code form or as a compiled // binary, for any purpose, commercial or non-commercial, and by any // means. // // In jurisdictions that recognize copyright laws, the author or authors // of this software dedicate any and all copyright interest in the // software to the public domain. We make this dedication for the benefit // of the public at large and to the detriment of our heirs and // successors. We intend this dedication to be an overt act of // relinquishment in perpetuity of all present and future rights to this // software under copyright law. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. use strings; use types; use types::c; export type conn = *opaque; export type statement = *opaque; export def OPEN_READONLY: int = 0x00000001; export def OPEN_READWRITE: int = 0x00000002; export def OPEN_CREATE: int = 0x00000004; export def OPEN_DELETEONCLOSE: int = 0x00000008; // VFS only export def OPEN_EXCLUSIVE: int = 0x00000010; // VFS only export def OPEN_AUTOPROXY: int = 0x00000020; // VFS only export def OPEN_URI: int = 0x00000040; // ... export def OPEN_NOMUTEX: int = 0x00008000; // .. export def OPEN_WAL: int = 0x00080000; // VFS only export def OPEN_NOFOLLOW: int = 0x01000000; export def OPEN_EXRESCODE: int = 0x02000000; export def def_open_flags = OPEN_READWRITE | OPEN_CREATE | OPEN_WAL | OPEN_URI | OPEN_NOMUTEX; @symbol("sqlite3_open_v2") fn libsqlite3_open_v2( filename: *const c::char, sqlite3: *opaque, flags: int, vfs: nullable *const c::char, ) int; // XXX vfs support? export fn open(filename: const str, flags: int...) (conn | error) = { let f = if (len(flags) == 0) def_open_flags else flags[0]; let path = c::fromstr(filename); defer free(path); let addr: uintptr = 0; let ret = libsqlite3_open_v2(path, &addr: *opaque, f, null); if (ret == sqlite_ok) { return (addr: *opaque): conn; }; return code2err(ret); }; @symbol("sqlite3_close_v2") fn libsqlite3_close_v2(sqlite3: *opaque) int; export fn close(conn: conn) (void | error) = { let ret = libsqlite3_close_v2(conn: *opaque); if (ret != sqlite_ok) { return code2err(ret); }; }; @symbol("sqlite3_prepare_v2") fn libsqlite3_prepare_v2( sqlite3: *opaque, sql: *const c::char, nbyte: int, stmt: *opaque, tail: nullable *opaque, ) int; export fn prepare(conn: conn, sql: const str) (statement | error) = { let s = c::fromstr(sql); defer free(s); let stmt: uintptr = 0; let ret = libsqlite3_prepare_v2(conn: *opaque, s, -1, &stmt: *opaque, null); if (ret == sqlite_ok) { return stmt: statement; }; return code2err(ret); }; // XXX missing // sqlite3_bind_blob // sqlite3_bind_blob64 // sqlite3_bind_double @symbol("sqlite3_bind_parameter_index") fn libsqlite3_bind_parameter_index( stmt: *opaque, name: *const c::char, ) int; fn bind_parameter_index(stmt: statement, col: (str | int)) (int | error) = { let name = match (col) { case let n: int => return n; case let n: str => yield n; }; let n = c::fromstr(name); defer free(n); let ret = libsqlite3_bind_parameter_index(stmt: *opaque, n); if (ret == 0) { return sqlite_error; }; return ret; }; @symbol("sqlite3_bind_int") fn libsqlite3_bind_int( stmt: *opaque, col: int, val: int, ) int; export fn bind_int(stmt: statement, col: (str | int), v: int) (void | error) = { let n = bind_parameter_index(stmt, col)?; let ret = libsqlite3_bind_int(stmt: *opaque, n, v); if (ret != sqlite_ok) { return code2err(ret); }; }; @symbol("sqlite3_bind_null") fn libsqlite3_bind_null( stmt: *opaque, col: int, ) int; export fn bind_null(stmt: statement, col: (str | int)) (void | error) = { let n = bind_parameter_index(stmt, col)?; let ret = libsqlite3_bind_null(stmt: *opaque, n); if (ret != sqlite_ok) { return code2err(ret); }; }; fn freecstr(s: *opaque) void = free(s: *c::char); @symbol("sqlite3_bind_text") fn libsqlite3_bind_text( stmt: *opaque, col: int, val: *const c::char, bytelen: int, freefn: *fn(*opaque) void ) int; export fn bind_text(stmt: statement, col: (str | int), v: str) (void | error) = { let n = bind_parameter_index(stmt, col)?; let s = c::fromstr(v); // free'd via the callback let ret = libsqlite3_bind_text(stmt: *opaque, n, s, -1, &freecstr); if (ret != sqlite_ok) { return code2err(ret); }; }; export fn bind( stmt: statement, col: (str | int), val: (int | void | str), ) (void | error) = { match (val) { case let v: int => return bind_int(stmt, col, v); case let v: void => return bind_null(stmt, col); case let v: str => return bind_text(stmt, col, v); }; }; @symbol("sqlite3_step") fn libsqlite3_step(stmt: *opaque) int; export fn step(stmt: statement) (bool | error) = { let ret = libsqlite3_step(stmt: *opaque); switch (ret) { case sqlite_row => return true; case sqlite_done => return false; case => return code2err(ret); }; }; @symbol("sqlite3_column_text") fn libsqlite3_column_text( stmt: *opaque, col: int, ) *const c::char; export fn column_text(stmt: statement, col: int) const str = { let s = libsqlite3_column_text(stmt: *opaque, col); if (s == null) { return ""; }; return c::tostr_unsafe(s); }; @symbol("sqlite3_column_int") fn libsqlite3_column_int( stmt: *opaque, col: int, ) int; export fn column_int(stmt: statement, col: int) int = { return libsqlite3_column_int(stmt: *opaque, col); }; @symbol("sqlite3_finalize") fn libsqlite3_finalize(stmt: *opaque) int; export fn finalize(stmt: statement) (void | error) = { let ret = libsqlite3_finalize(stmt: *opaque); if (ret != sqlite_ok) { return code2err(ret); }; }; @symbol("sqlite3_reset") fn libsqlite3_reset(stmt: *opaque) int; export fn reset(stmt: statement) (void | error) = { let ret = libsqlite3_reset(stmt: *opaque); if (ret != sqlite_ok) { return code2err(ret); }; }; @symbol("sqlite3_clear_bindings") fn libsqlite3_clear_bindings(stmt: *opaque) int; export fn clear_bindings(stmt: statement) (void | error) = { let ret = libsqlite3_clear_bindings(stmt: *opaque); if (ret != sqlite_ok) { return code2err(ret); }; };