#include "tsqlite.h" Result(tsqlite_statement*) tsqlite_statement_compile(tsqlite_connection* conn, str sql_code){ sqlite3_stmt* st = NULL; i32 flags = SQLITE_PREPARE_PERSISTENT; try_sqlite3(conn, sqlite3_prepare_v3(conn, sql_code.data, sql_code.len, flags, &st, NULL)); tsqlite_statement* self = malloc(sizeof(*self)); self->conn = conn; self->st = st; self->result_row = 0; self->result_col = 0; 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(self->conn, sqlite3_reset(self->st)); self->result_row = 0; self->result_col = 0; return RESULT_VOID; } #define tryGetBindIndex(key) \ i32 bind_index = sqlite3_bind_parameter_index(self->st, key);\ if(bind_index == 0){\ return RESULT_ERROR_SQLITE_CODE(self->conn, sqlite3_errcode(self->conn));\ }\ Result(void) tsqlite_statement_bind_null(tsqlite_statement* self, cstr key){ tryGetBindIndex(key); try_sqlite3(self->conn, sqlite3_bind_null(self->st, bind_index)); return RESULT_VOID; } Result(void) tsqlite_statement_bind_i64(tsqlite_statement* self, cstr key, i64 v){ tryGetBindIndex(key); try_sqlite3(self->conn, sqlite3_bind_int64(self->st, bind_index, v)); return RESULT_VOID; } Result(void) tsqlite_statement_bind_f64(tsqlite_statement* self, cstr key, f64 v){ tryGetBindIndex(key); try_sqlite3(self->conn, sqlite3_bind_double(self->st, bind_index, v)); return RESULT_VOID; } Result(void) tsqlite_statement_bind_str(tsqlite_statement* self, cstr key, str v, NULLABLE(Destructor_t) d){ tryGetBindIndex(key); try_sqlite3(self->conn, sqlite3_bind_text(self->st, bind_index, v.data, v.len, d)); return RESULT_VOID; } Result(void) tsqlite_statement_bind_blob(tsqlite_statement* self, cstr key, Array(u8) v, NULLABLE(Destructor_t) d){ tryGetBindIndex(key); try_sqlite3(self->conn, sqlite3_bind_blob(self->st, bind_index, v.data, v.len, d)); return RESULT_VOID; } Result(void) tsqlite_statement_bind_zeroblob(tsqlite_statement* self, cstr key, i32 size){ tryGetBindIndex(key); try_sqlite3(self->conn, sqlite3_bind_zeroblob(self->st, bind_index, size)); return RESULT_VOID; } Result(bool) tsqlite_statement_execNext(tsqlite_statement* self){ int r = sqlite3_step(self->st); if(r == SQLITE_ROW){ self->result_row++; return RESULT_VALUE(i, true); } if(r == SQLITE_DONE){ self->result_row++; return RESULT_VALUE(i, false); } return RESULT_ERROR_SQLITE_CODE(self->conn, r); } Result(i64) tsqlite_statement_getResult_i64(tsqlite_statement* self){ i64 r = sqlite3_column_int64(self->st, self->result_col); try_sqlite3(self->conn, sqlite3_errcode(self->conn)); 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); try_sqlite3(self->conn, sqlite3_errcode(self->conn)); self->result_col++; return RESULT_VALUE(f, r); } Result(void) tsqlite_statement_getResult_str(tsqlite_statement* self, str* out_v){ void* data = (void*)sqlite3_column_text(self->st, self->result_col); try_sqlite3(self->conn, sqlite3_errcode(self->conn)); u32 size = sqlite3_column_bytes(self->st, self->result_col); *out_v = str_construct(data, size, true); self->result_col++; return RESULT_VOID; } Result(void) tsqlite_statement_getResult_blob(tsqlite_statement* self, Array(u8)* out_v){ void* data = (void*)sqlite3_column_blob(self->st, self->result_col); try_sqlite3(self->conn, sqlite3_errcode(self->conn)); u32 size = sqlite3_column_bytes(self->st, self->result_col); *out_v = Array_u8_construct(data, size); self->result_col++; return RESULT_VOID; }