initial commit
This commit is contained in:
16
src/connection.c
Normal file
16
src/connection.c
Normal file
@@ -0,0 +1,16 @@
|
||||
#include "tsqlite.h"
|
||||
|
||||
Result(tsqlite_connection*) tsqlite_connection_open(cstr file_path,
|
||||
NULLABLE(void*) logger, NULLABLE(sqlite3_error_log_func_t) log_func)
|
||||
{
|
||||
tsqlite_connection* conn = NULL;
|
||||
try_sqlite3(sqlite3_open(file_path, &conn));
|
||||
try_sqlite3(sqlite3_db_config(conn, SQLITE_CONFIG_LOG, log_func, logger));
|
||||
try_sqlite3(sqlite3_extended_result_codes(conn, true));
|
||||
return RESULT_VALUE(p, conn);
|
||||
}
|
||||
|
||||
Result(void) tsqlite_connection_close(tsqlite_connection* conn){
|
||||
try_sqlite3(sqlite3_close(conn));
|
||||
return RESULT_VOID;
|
||||
}
|
||||
151
src/errors.c
Normal file
151
src/errors.c
Normal file
@@ -0,0 +1,151 @@
|
||||
#include "tsqlite.h"
|
||||
#include "tlibc/string/StringBuilder.h"
|
||||
|
||||
#define PRIMARY_CODE_X(X)\
|
||||
X(SQLITE_OK)\
|
||||
X(SQLITE_ERROR)\
|
||||
X(SQLITE_INTERNAL)\
|
||||
X(SQLITE_PERM)\
|
||||
X(SQLITE_ABORT)\
|
||||
X(SQLITE_BUSY)\
|
||||
X(SQLITE_LOCKED)\
|
||||
X(SQLITE_NOMEM)\
|
||||
X(SQLITE_READONLY)\
|
||||
X(SQLITE_INTERRUPT)\
|
||||
X(SQLITE_IOERR)\
|
||||
X(SQLITE_CORRUPT)\
|
||||
X(SQLITE_NOTFOUND)\
|
||||
X(SQLITE_FULL)\
|
||||
X(SQLITE_CANTOPEN)\
|
||||
X(SQLITE_PROTOCOL)\
|
||||
X(SQLITE_EMPTY)\
|
||||
X(SQLITE_SCHEMA)\
|
||||
X(SQLITE_TOOBIG)\
|
||||
X(SQLITE_CONSTRAINT)\
|
||||
X(SQLITE_MISMATCH)\
|
||||
X(SQLITE_MISUSE)\
|
||||
X(SQLITE_NOLFS)\
|
||||
X(SQLITE_AUTH)\
|
||||
X(SQLITE_FORMAT)\
|
||||
X(SQLITE_RANGE)\
|
||||
X(SQLITE_NOTADB)\
|
||||
X(SQLITE_NOTICE)\
|
||||
X(SQLITE_WARNING)\
|
||||
X(SQLITE_ROW)\
|
||||
X(SQLITE_DONE)\
|
||||
|
||||
#define EXTENDED_CODE_X(X)\
|
||||
X(SQLITE_ERROR_MISSING_COLLSEQ)\
|
||||
X(SQLITE_ERROR_RETRY)\
|
||||
X(SQLITE_ERROR_SNAPSHOT)\
|
||||
X(SQLITE_ERROR_RESERVESIZE)\
|
||||
X(SQLITE_ERROR_KEY)\
|
||||
X(SQLITE_ERROR_UNABLE)\
|
||||
X(SQLITE_IOERR_READ)\
|
||||
X(SQLITE_IOERR_SHORT_READ)\
|
||||
X(SQLITE_IOERR_WRITE)\
|
||||
X(SQLITE_IOERR_FSYNC)\
|
||||
X(SQLITE_IOERR_DIR_FSYNC)\
|
||||
X(SQLITE_IOERR_TRUNCATE)\
|
||||
X(SQLITE_IOERR_FSTAT)\
|
||||
X(SQLITE_IOERR_UNLOCK)\
|
||||
X(SQLITE_IOERR_RDLOCK)\
|
||||
X(SQLITE_IOERR_DELETE)\
|
||||
X(SQLITE_IOERR_BLOCKED)\
|
||||
X(SQLITE_IOERR_NOMEM)\
|
||||
X(SQLITE_IOERR_ACCESS)\
|
||||
X(SQLITE_IOERR_CHECKRESERVEDLOCK)\
|
||||
X(SQLITE_IOERR_LOCK)\
|
||||
X(SQLITE_IOERR_CLOSE)\
|
||||
X(SQLITE_IOERR_DIR_CLOSE)\
|
||||
X(SQLITE_IOERR_SHMOPEN)\
|
||||
X(SQLITE_IOERR_SHMSIZE)\
|
||||
X(SQLITE_IOERR_SHMLOCK)\
|
||||
X(SQLITE_IOERR_SHMMAP)\
|
||||
X(SQLITE_IOERR_SEEK)\
|
||||
X(SQLITE_IOERR_DELETE_NOENT)\
|
||||
X(SQLITE_IOERR_MMAP)\
|
||||
X(SQLITE_IOERR_GETTEMPPATH)\
|
||||
X(SQLITE_IOERR_CONVPATH)\
|
||||
X(SQLITE_IOERR_VNODE)\
|
||||
X(SQLITE_IOERR_AUTH)\
|
||||
X(SQLITE_IOERR_BEGIN_ATOMIC)\
|
||||
X(SQLITE_IOERR_COMMIT_ATOMIC)\
|
||||
X(SQLITE_IOERR_ROLLBACK_ATOMIC)\
|
||||
X(SQLITE_IOERR_DATA)\
|
||||
X(SQLITE_IOERR_CORRUPTFS)\
|
||||
X(SQLITE_IOERR_IN_PAGE)\
|
||||
X(SQLITE_IOERR_BADKEY)\
|
||||
X(SQLITE_IOERR_CODEC)\
|
||||
X(SQLITE_LOCKED_SHAREDCACHE)\
|
||||
X(SQLITE_LOCKED_VTAB)\
|
||||
X(SQLITE_BUSY_RECOVERY)\
|
||||
X(SQLITE_BUSY_SNAPSHOT)\
|
||||
X(SQLITE_BUSY_TIMEOUT)\
|
||||
X(SQLITE_CANTOPEN_NOTEMPDIR)\
|
||||
X(SQLITE_CANTOPEN_ISDIR)\
|
||||
X(SQLITE_CANTOPEN_FULLPATH)\
|
||||
X(SQLITE_CANTOPEN_CONVPATH)\
|
||||
X(SQLITE_CANTOPEN_DIRTYWAL)\
|
||||
X(SQLITE_CANTOPEN_SYMLINK)\
|
||||
X(SQLITE_CORRUPT_VTAB)\
|
||||
X(SQLITE_CORRUPT_SEQUENCE)\
|
||||
X(SQLITE_CORRUPT_INDEX)\
|
||||
X(SQLITE_READONLY_RECOVERY)\
|
||||
X(SQLITE_READONLY_CANTLOCK)\
|
||||
X(SQLITE_READONLY_ROLLBACK)\
|
||||
X(SQLITE_READONLY_DBMOVED)\
|
||||
X(SQLITE_READONLY_CANTINIT)\
|
||||
X(SQLITE_READONLY_DIRECTORY)\
|
||||
X(SQLITE_ABORT_ROLLBACK)\
|
||||
X(SQLITE_CONSTRAINT_CHECK)\
|
||||
X(SQLITE_CONSTRAINT_COMMITHOOK)\
|
||||
X(SQLITE_CONSTRAINT_FOREIGNKEY)\
|
||||
X(SQLITE_CONSTRAINT_FUNCTION)\
|
||||
X(SQLITE_CONSTRAINT_NOTNULL)\
|
||||
X(SQLITE_CONSTRAINT_PRIMARYKEY)\
|
||||
X(SQLITE_CONSTRAINT_TRIGGER)\
|
||||
X(SQLITE_CONSTRAINT_UNIQUE)\
|
||||
X(SQLITE_CONSTRAINT_VTAB)\
|
||||
X(SQLITE_CONSTRAINT_ROWID)\
|
||||
X(SQLITE_CONSTRAINT_PINNED)\
|
||||
X(SQLITE_CONSTRAINT_DATATYPE)\
|
||||
X(SQLITE_NOTICE_RECOVER_WAL)\
|
||||
X(SQLITE_NOTICE_RECOVER_ROLLBACK)\
|
||||
X(SQLITE_NOTICE_RBU)\
|
||||
X(SQLITE_WARNING_AUTOINDEX)\
|
||||
X(SQLITE_AUTH_USER)\
|
||||
X(SQLITE_OK_LOAD_PERMANENTLY)\
|
||||
X(SQLITE_OK_SYMLINK)\
|
||||
|
||||
#define PRIMARY_CODE_CASE(C) case C: return STR(#C);
|
||||
|
||||
static str PrimaryCode_toStr(int code){
|
||||
switch(code & 0xff){
|
||||
default: return STR("!! ERROR: INVALID SQLITE_CODE !!");
|
||||
PRIMARY_CODE_X(PRIMARY_CODE_CASE)
|
||||
}
|
||||
}
|
||||
|
||||
#define EXTENDED_CODE_IF(C) \
|
||||
if(C & code) {\
|
||||
if(multiple_extended_codes){\
|
||||
StringBuilder_append_char(&sb, ',');\
|
||||
StringBuilder_append_char(&sb, ' ');\
|
||||
}\
|
||||
else multiple_extended_codes = true;\
|
||||
StringBuilder_append_str(&sb, STR(#C));\
|
||||
}\
|
||||
|
||||
str tsqlite_ResultCode_toStr(int code){
|
||||
StringBuilder sb = StringBuilder_alloc(128);
|
||||
bool multiple_extended_codes = false;
|
||||
|
||||
StringBuilder_append_str(&sb, PrimaryCode_toStr(code));
|
||||
StringBuilder_append_char(&sb, ':');
|
||||
StringBuilder_append_char(&sb, ' ');
|
||||
|
||||
EXTENDED_CODE_X(EXTENDED_CODE_IF);
|
||||
|
||||
return StringBuilder_getStr(&sb);
|
||||
}
|
||||
109
src/statement.c
Normal file
109
src/statement.c
Normal file
@@ -0,0 +1,109 @@
|
||||
#include "tsqlite.h"
|
||||
|
||||
Result(tsqlite_statement*) tsqlite_statement_prepare(sqlite3* conn, str sql_code){
|
||||
sqlite3_stmt* st = NULL;
|
||||
i32 flags = SQLITE_PREPARE_PERSISTENT;
|
||||
try_sqlite3(sqlite3_prepare_v3(conn, sql_code.data, sql_code.len, flags, &st, NULL));
|
||||
tsqlite_statement* self = malloc(sizeof(*self));
|
||||
zeroStruct(self);
|
||||
self->st = st;
|
||||
return RESULT_VALUE(p, self);
|
||||
}
|
||||
|
||||
void tsqlite_statement_free(tsqlite_statement* self){
|
||||
if(!self)
|
||||
return;
|
||||
sqlite3_finalize(self->st);
|
||||
free(self);
|
||||
}
|
||||
|
||||
Result(void) tsqlite_statement_reset(tsqlite_statement* self){
|
||||
try_sqlite3(sqlite3_reset(self->st));
|
||||
self->bind_arg_pos = 0;
|
||||
self->result_row = 0;
|
||||
self->result_col = 0;
|
||||
return RESULT_VOID;
|
||||
}
|
||||
|
||||
|
||||
Result(void) tsqlite_statement_bind_null(tsqlite_statement* self){
|
||||
try_sqlite3(sqlite3_bind_null(self->st, self->bind_arg_pos));
|
||||
self->bind_arg_pos++;
|
||||
return RESULT_VOID;
|
||||
}
|
||||
|
||||
Result(void) tsqlite_statement_bind_i32(tsqlite_statement* self, i32 v){
|
||||
try_sqlite3(sqlite3_bind_int(self->st, self->bind_arg_pos, v));
|
||||
self->bind_arg_pos++;
|
||||
return RESULT_VOID;
|
||||
}
|
||||
|
||||
Result(void) tsqlite_statement_bind_i64(tsqlite_statement* self, i64 v){
|
||||
try_sqlite3(sqlite3_bind_int64(self->st, self->bind_arg_pos, v));
|
||||
self->bind_arg_pos++;
|
||||
return RESULT_VOID;
|
||||
}
|
||||
|
||||
Result(void) tsqlite_statement_bind_f64(tsqlite_statement* self, f64 v){
|
||||
try_sqlite3(sqlite3_bind_double(self->st, self->bind_arg_pos, v));
|
||||
self->bind_arg_pos++;
|
||||
return RESULT_VOID;
|
||||
}
|
||||
|
||||
Result(void) tsqlite_statement_bind_str(tsqlite_statement* self, str v, NULLABLE(Destructor_t) d){
|
||||
try_sqlite3(sqlite3_bind_text(self->st, self->bind_arg_pos, v.data, v.len, d));
|
||||
self->bind_arg_pos++;
|
||||
return RESULT_VOID;
|
||||
}
|
||||
|
||||
Result(void) tsqlite_statement_bind_blob(tsqlite_statement* self, Array(u8) v, NULLABLE(Destructor_t) d){
|
||||
try_sqlite3(sqlite3_bind_blob(self->st, self->bind_arg_pos, v.data, v.len, d));
|
||||
self->bind_arg_pos++;
|
||||
return RESULT_VOID;
|
||||
}
|
||||
|
||||
Result(void) tsqlite_statement_bind_zeroblob(tsqlite_statement* self, i32 size){
|
||||
try_sqlite3(sqlite3_bind_zeroblob(self->st, self->bind_arg_pos, size));
|
||||
self->bind_arg_pos++;
|
||||
return RESULT_VOID;
|
||||
}
|
||||
|
||||
Result(bool) sqlite3_statement_moveNext(tsqlite_statement* self){
|
||||
int r = sqlite3_step(self->st);
|
||||
if(r == SQLITE_ROW){
|
||||
return RESULT_VALUE(i, true);
|
||||
}
|
||||
if(r == SQLITE_DONE){
|
||||
return RESULT_VALUE(i, false);
|
||||
}
|
||||
|
||||
return RESULT_ERROR_SQLITE_CODE(r);
|
||||
}
|
||||
|
||||
Result(i64) tsqlite_statement_getResult_i64(tsqlite_statement* self){
|
||||
i64 r = sqlite3_column_int64(self->st, self->result_col);
|
||||
// TODO: error checking in sqlite3_column
|
||||
self->result_col++;
|
||||
return RESULT_VALUE(i, r);
|
||||
}
|
||||
|
||||
Result(i64) tsqlite_statement_getResult_f64(tsqlite_statement* self){
|
||||
f64 r = sqlite3_column_double(self->st, self->result_col);
|
||||
// TODO: error checking in sqlite3_column
|
||||
self->result_col++;
|
||||
return RESULT_VALUE(f, r);
|
||||
}
|
||||
|
||||
Result(void) tsqlite_statement_getResult_str(tsqlite_statement* self, str* out_v){
|
||||
(void)self;
|
||||
(void)out_v;
|
||||
// TODO: tsqlite_statement_getResult_str
|
||||
return RESULT_VOID;
|
||||
}
|
||||
|
||||
Result(void) tsqlite_statement_getResult_blob(tsqlite_statement* self, Array(u8)* out_v){
|
||||
(void)self;
|
||||
(void)out_v;
|
||||
// TODO: tsqlite_statement_getResult_blob
|
||||
return RESULT_VOID;
|
||||
}
|
||||
15
src/tsqlite.c
Normal file
15
src/tsqlite.c
Normal file
@@ -0,0 +1,15 @@
|
||||
#include "tsqlite.h"
|
||||
|
||||
ErrorCodePage_define(SQLITE);
|
||||
|
||||
Result(void) tsqlite_init(){
|
||||
Deferral(4);
|
||||
|
||||
ErrorCodePage_register(SQLITE);
|
||||
|
||||
Return RESULT_VOID;
|
||||
}
|
||||
|
||||
void tsqlite_deinit(){
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user