simplified error message generation

This commit is contained in:
2025-12-15 14:10:51 +05:00
parent 52a19d8db8
commit 3a528c00c2
4 changed files with 20 additions and 174 deletions

View File

@@ -8,12 +8,16 @@ void tsqlite_deinit();
ErrorCodePage_declare(SQLITE); ErrorCodePage_declare(SQLITE);
#define RESULT_ERROR_SQLITE_CODE(CONN, SHORT_CODE) RESULT_ERROR_CODE(SQLITE, SHORT_CODE, tsqlite_error_toStr(CONN, SHORT_CODE), true) /// @param code SQLITE_* result code
/// @return heap-allocated string
str tsqlite_error_toStr(i32 code, cstr msg);
#define RESULT_ERROR_SQLITE_CODE(CODE, MSG) RESULT_ERROR_CODE(SQLITE, CODE, tsqlite_error_toStr(CODE, MSG), true)
#define _try_sqlite3(CONN, CALL, N) do {\ #define _try_sqlite3(CONN, CALL, N) do {\
i32 _rname(N) = CALL;\ i32 _rname(N) = CALL;\
if((_rname(N) & 0xff) != SQLITE_OK){\ if((_rname(N) & 0xff) != SQLITE_OK){\
return RESULT_ERROR_SQLITE_CODE(CONN, _rname(N));\ return RESULT_ERROR_SQLITE_CODE(_rname(N), sqlite3_errmsg(CONN));\
}\ }\
} while(0) } while(0)
@@ -29,12 +33,6 @@ Result(tsqlite_connection*) tsqlite_connection_open(cstr file_path);
/// all statements and blobs must be destroyed before calling this /// all statements and blobs must be destroyed before calling this
Result(void) tsqlite_connection_close(tsqlite_connection* db); Result(void) tsqlite_connection_close(tsqlite_connection* db);
/// @param conn a database connection with error code and error message
/// @return heap-allocated string
str tsqlite_error_toStr(tsqlite_connection* conn, i32 short_code);
void tsqlite_resultCode_append(StringBuilder* sb, i32 short_code, i32 extended_code);
void tsqlite_resultCodeAndMsg_append(StringBuilder* sb, i32 short_code, i32 extended_code, str msg);
typedef struct tsqlite_statement { typedef struct tsqlite_statement {
tsqlite_connection* conn; tsqlite_connection* conn;

View File

@@ -1,164 +0,0 @@
#include "tsqlite.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(i32 code){
switch(code & 0xff){
default: return STR("!! ERROR: INVALID SQLITE_CODE !!");
PRIMARY_CODE_X(PRIMARY_CODE_CASE)
}
}
#define EXTENDED_CODE_IF(C) \
if(C & extended_code_part) {\
if(multiple_extended_codes){\
StringBuilder_append_char(sb, ',');\
StringBuilder_append_char(sb, ' ');\
}\
else multiple_extended_codes = true;\
StringBuilder_append_str(sb, STR(#C));\
}\
void tsqlite_resultCode_append(StringBuilder* sb, i32 short_code, i32 extended_code){
i32 extended_code_part = extended_code ^ (extended_code & 0xff);
if(extended_code_part == 0){
StringBuilder_append_str(sb, PrimaryCode_toStr(short_code));
}
else {
bool multiple_extended_codes = false;
EXTENDED_CODE_X(EXTENDED_CODE_IF);
}
}
;
void tsqlite_resultCodeAndMsg_append(StringBuilder* sb, i32 short_code, i32 extended_code, str msg){
tsqlite_resultCode_append(sb, short_code, extended_code);
StringBuilder_append_char(sb, ':');
StringBuilder_append_char(sb, ' ');
StringBuilder_append_str(sb, msg);
}
str tsqlite_error_toStr(tsqlite_connection* conn, i32 short_code){
i32 extended_code = sqlite3_extended_errcode(conn);
str msg = str_from_cstr(sqlite3_errmsg(conn));
StringBuilder sb = StringBuilder_alloc(64 + msg.len);
tsqlite_resultCodeAndMsg_append(&sb, short_code, extended_code, msg);
return StringBuilder_getStr(&sb);
}

View File

@@ -91,13 +91,13 @@ Result(bool) tsqlite_statement_execNext(tsqlite_statement* self){
return RESULT_VALUE(i, false); return RESULT_VALUE(i, false);
} }
return RESULT_ERROR_SQLITE_CODE(self->conn, r); return RESULT_ERROR_SQLITE_CODE(r, sqlite3_errmsg(self->conn));
} }
#define validate_column()\ #define validate_column()\
i32 errcode = sqlite3_errcode(self->conn);\ i32 errcode = sqlite3_errcode(self->conn);\
if(errcode != SQLITE_OK && errcode != SQLITE_ROW){\ if(errcode != SQLITE_OK && errcode != SQLITE_ROW){\
return RESULT_ERROR_SQLITE_CODE(self->conn, errcode);\ return RESULT_ERROR_SQLITE_CODE(errcode, sqlite3_errmsg(self->conn));\
} }
Result(i64) tsqlite_statement_getResult_i64(tsqlite_statement* self){ Result(i64) tsqlite_statement_getResult_i64(tsqlite_statement* self){

View File

@@ -13,3 +13,15 @@ Result(void) tsqlite_init(){
void tsqlite_deinit(){ void tsqlite_deinit(){
} }
str tsqlite_error_toStr(i32 code, cstr msg_cstr){
str msg = str_from_cstr(msg_cstr);
StringBuilder sb = StringBuilder_alloc(64 + msg.len);
StringBuilder_append_cstr(&sb, sqlite3_errstr(code));
StringBuilder_append_char(&sb, ':');
StringBuilder_append_char(&sb, ' ');
StringBuilder_append_str(&sb, msg);
return StringBuilder_getStr(&sb);
}