#pragma once #include "tlibc/tlibc.h" #include "tlibc/errors.h" #include "tlibc/string/str.h" #include "tlibc/collections/Array.h" #include "tlibc/collections/Array_impl/Array_u8.h" #include Result(void) tsqlite_init(); void tsqlite_deinit(); /// @param code primary : 8 bits | extended : 24 bits /// @return heap-allocated string str tsqlite_ResultCode_toStr(int code); ErrorCodePage_declare(SQLITE); #define RESULT_ERROR_SQLITE_CODE(CODE) RESULT_ERROR_CODE(SQLITE, CODE & 0xff, tsqlite_ResultCode_toStr(CODE), true) #define _try_sqlite3(CALL, N) do {\ int _rname(N) = CALL;\ if((_rname(N) & 0xff) != SQLITE_OK){\ return RESULT_ERROR_SQLITE_CODE(_rname(N));\ }\ } while(0) #define try_sqlite3(CALL) _try_sqlite3(CALL, __LINE__) typedef void(*sqlite3_error_log_func_t)(void* ctx, int code, cstr msg); typedef sqlite3 tsqlite_connection; /// @param file_path sqlite file /// @param logger /// @param log_func /// @return new sqlite connection Result(tsqlite_connection*) tsqlite_connection_open(cstr file_path, NULLABLE(void*) logger, NULLABLE(sqlite3_error_log_func_t) log_func); /// all statements and blobs must be destroyed before calling this Result(void) tsqlite_connection_close(tsqlite_connection* db); typedef struct tsqlite_statement { sqlite3_stmt* st; i32 bind_arg_pos; i32 result_row; i32 result_col; } tsqlite_statement; /// @brief compile SQL statement to bytecode /// @param db /// @param sql_code SQL statement code. May contain placeholders /// @return compiled statement Result(tsqlite_statement*) tsqlite_statement_prepare(tsqlite_connection* db, str sql_code); /// Bind value to placeholder at `self->bind_arg_pos`. Increases `self->bind_arg_pos` on success. Result(void) tsqlite_statement_bind_null(tsqlite_statement* self); Result(void) tsqlite_statement_bind_i32(tsqlite_statement* self, i32 v); Result(void) tsqlite_statement_bind_i64(tsqlite_statement* self, i64 v); Result(void) tsqlite_statement_bind_f64(tsqlite_statement* self, f64 v); Result(void) tsqlite_statement_bind_str(tsqlite_statement* self, str v, NULLABLE(Destructor_t) d); Result(void) tsqlite_statement_bind_blob(tsqlite_statement* self, Array(u8) v, NULLABLE(Destructor_t) d); Result(void) tsqlite_statement_bind_zeroblob(tsqlite_statement* self, i32 size); /// @brief execute statement or move to next result row /// @return is next result row avaliable Result(bool) sqlite3_statement_moveNext(tsqlite_statement* self); /// Get value at `self->result_col`. Increases `self->result_col` on success. Result(i64) tsqlite_statement_getResult_i64(tsqlite_statement* self); Result(i64) tsqlite_statement_getResult_f64(tsqlite_statement* self); Result(void) tsqlite_statement_getResult_str(tsqlite_statement* self, str* out_v); Result(void) tsqlite_statement_getResult_blob(tsqlite_statement* self, Array(u8)* out_v); /// call this after executing prepared statement to use it again Result(void) tsqlite_statement_reset(tsqlite_statement* st); void tsqlite_statement_free(tsqlite_statement* st);