From 89b7f484f799caea633ed7f87ea7e6c3b929ad24 Mon Sep 17 00:00:00 2001 From: theBreadCompany Date: Fri, 13 Jun 2025 03:13:36 +0200 Subject: [PATCH] bug fixing, custom logging method, stuff --- src/main/include/models.h | 40 +++++++-------- src/main/include/sql.h | 1 - src/main/include/util.h | 21 +++++++- src/main/main.c | 97 +++++++++++++++++------------------ src/main/models.c | 104 +++++++++++++++++++++----------------- src/main/sql.c | 26 +++++----- src/main/util.c | 30 +++++++++-- 7 files changed, 185 insertions(+), 134 deletions(-) diff --git a/src/main/include/models.h b/src/main/include/models.h index b619281..e5714b4 100644 --- a/src/main/include/models.h +++ b/src/main/include/models.h @@ -13,12 +13,12 @@ typedef struct klist_user klist_user; klist_user *klist_user_init(); klist_user *klist_user_init_from_sql(sqlite3_stmt *); -klist_user *klist_user_get_by_id(klist *, u_int); -klist_user *klist_user_get_by_local(klist *, u_int); -klist_user *klist_user_get_by_discord(klist *, u_int); -klist_user *klist_user_get_by_google(klist *, u_int); -void klist_user_save(klist *, klist_user *); -void klist_user_delete(klist *, klist_user *); +klist_user *klist_user_get_by_id(const klist *, u_int); +klist_user *klist_user_get_by_local(const klist *, u_int); +klist_user *klist_user_get_by_discord(const klist *, u_int); +klist_user *klist_user_get_by_google(const klist *, u_int); +void klist_user_save(const klist *, klist_user *); +void klist_user_delete(const klist *, const klist_user *); void klist_user_deinit(klist_user *); struct klist_list { @@ -31,11 +31,11 @@ typedef struct klist_list klist_list; klist_list *klist_list_init(); klist_list *klist_list_init_from_sql(sqlite3_stmt *); -klist_list *klist_list_get_by_id(klist *, u_int); -klist_list **klist_list_get_all_by_user(klist *, u_int, size_t *); -klist_list *klist_list_get_by_user_and_name(klist *, u_int, const char *); -void klist_list_save(klist *, klist_list *, klist_user *); -void klist_list_delete(klist *, klist_list *); +klist_list *klist_list_get_by_id(const klist *, u_int); +klist_list **klist_list_get_all_by_user(const klist *, u_int, size_t *); +klist_list *klist_list_get_by_user_and_name(const klist *, u_int, const char *); +void klist_list_save(const klist *, klist_list *, const klist_user *); +void klist_list_delete(const klist *, klist_list *); void klist_list_deinit(klist_list *); struct klist_stage { @@ -48,10 +48,10 @@ typedef struct klist_stage klist_stage; klist_stage *klist_stage_init(); klist_stage *klist_stage_init_from_sql(sqlite3_stmt *); -klist_stage *klist_stage_get_by_id(klist *, u_int); -klist_stage **klist_stage_get_all_for_list(klist *, u_int, size_t *); -void klist_stage_save(klist *, klist_stage *); -void klist_stage_delete(klist *, klist_stage *); +klist_stage *klist_stage_get_by_id(const klist *, u_int); +klist_stage **klist_stage_get_all_for_list(const klist *, u_int, size_t *); +void klist_stage_save(const klist *, klist_stage *); +void klist_stage_delete(const klist *, const klist_stage *); void klist_stage_deinit(klist_stage *); struct klist_task { @@ -66,9 +66,9 @@ typedef struct klist_task klist_task; klist_task *klist_task_init(); klist_task *klist_task_init_from_sql(sqlite3_stmt *); -klist_task *klist_task_get_by_id(klist *, u_int); -klist_task **klist_task_get_for_list(klist *, u_int, size_t *); -klist_task *klist_task_get_for_list_by_name(klist *, u_int, const char *); -void klist_task_save(klist *, klist_task *); -void klist_task_delete(klist *, klist_task *); +klist_task *klist_task_get_by_id(const klist *, u_int); +klist_task **klist_task_get_for_list(const klist *, u_int, size_t *); +klist_task *klist_task_get_for_list_by_name(const klist *, u_int, const char *); +void klist_task_save(const klist *, klist_task *); +void klist_task_delete(const klist *, const klist_task *); void klist_task_deinit(klist_task *); diff --git a/src/main/include/sql.h b/src/main/include/sql.h index e6b475b..219dcde 100644 --- a/src/main/include/sql.h +++ b/src/main/include/sql.h @@ -1,5 +1,4 @@ #pragma once -#include enum KLIST_SQL { INIT, diff --git a/src/main/include/util.h b/src/main/include/util.h index d3ef110..198f9f0 100644 --- a/src/main/include/util.h +++ b/src/main/include/util.h @@ -2,11 +2,20 @@ #include #include #include +#include /* * command parsing */ +enum KLIST_LOG_LEVEL { + KLIST_LOG_ERROR, + KLIST_LOG_WARNING, + KLIST_LOG_INFO, + KLIST_LOG_DEBUG +}; +typedef enum KLIST_LOG_LEVEL KLIST_LOG_LEVEL; + enum klist_command { USER, LIST, @@ -18,6 +27,8 @@ struct klist { u_int cmd; void *cmd_ctx; int error; + KLIST_LOG_LEVEL log_level; + FILE *log_target; }; typedef struct klist klist; @@ -84,4 +95,12 @@ void klist_sql_prepare(klist *, char *); bool klist_assure_user(klist *, __uid_t, char *); void klist_assure_list(klist *, char *); -void klist_assure_task(klist *, char *); \ No newline at end of file +void klist_assure_task(klist *, char *); + +/* + * printing methods + * + * json printing will be implemented eventually + */ + +void klist_print(const klist *, KLIST_LOG_LEVEL, const char *format, ...); \ No newline at end of file diff --git a/src/main/main.c b/src/main/main.c index 16ea997..016a33a 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -6,14 +6,14 @@ #include "models.h" #include "util.h" -void print_help(char **argv); +void print_help(klist *ctx, char **argv); void setup(klist *ctx, int argc, char **argv); int main(int argc, char **argv) { klist *ctx = klist_init("test.db"); if (argc == 1) { - print_help(argv); + print_help(ctx, argv); ctx->error = 1; } @@ -28,27 +28,27 @@ int main(int argc, char **argv) { switch (user_ctx->cmd) { case USER_GET: if (user) { - fprintf(stderr, "User: %p\nID: %lu\n", user->name, user->id); + printf("User: %p\nID: %lu\n", user->name, user->id); size_t lists_len = 0; klist_list **lists = klist_list_get_all_by_user(ctx, user->id, &lists_len); - fprintf(stderr, "Lists: %lu\n", lists_len); + printf("Lists: %lu\n", lists_len); for (; i < lists_len; i++) klist_list_deinit(lists[i]); } else - fprintf(stderr, "No user for '%s' found.\n", getlogin()); + klist_print(ctx, KLIST_LOG_ERROR, "No user for '%s' found.\n", getlogin()); break; case USER_CREATE: - fprintf(stderr, (klist_assure_user(ctx, getuid(), getlogin())) + klist_print(ctx, KLIST_LOG_INFO, (klist_assure_user(ctx, getuid(), getlogin())) ? "User created.\n" : "User already exists.\n"); break; case USER_DELETE: if (user) { klist_user_delete(ctx, user); - fprintf(stderr, "User deleted.\n"); + printf("User deleted.\n"); } else - fprintf(stderr, "User not found, no changes done.\n"); + klist_print(ctx, KLIST_LOG_ERROR, "User not found, no changes done.\n"); break; } klist_user_context_deinit(user_ctx); @@ -56,13 +56,13 @@ int main(int argc, char **argv) { case LIST: klist_list_context *list_ctx = ctx->cmd_ctx; if (!list_ctx->name && list_ctx->cmd != LIST_GET) { - fprintf(stderr, "Missing name.\n"); + klist_print(ctx, KLIST_LOG_ERROR, "Missing name.\n"); break; } switch (list_ctx->cmd) { case LIST_ADD: if (!list_ctx->stages_len) { - fprintf(stderr, "Missing stages.\n"); + klist_print(ctx, KLIST_LOG_ERROR, "Missing stages.\n"); break; } klist_assure_user(ctx, getuid(), getlogin()); @@ -84,7 +84,7 @@ int main(int argc, char **argv) { } break; case LIST_EDIT: - fprintf(stderr, "Not implemented\n"); + klist_print(ctx, KLIST_LOG_ERROR, "Not implemented\n"); break; case LIST_GET: size_t lists_len = 0; @@ -100,15 +100,17 @@ int main(int argc, char **argv) { }; } else lists = klist_list_get_all_by_user(ctx, user->id, &lists_len); - if (lists) { + + if (lists_len) { i = 0; for (; i < lists_len; i++) { klist_list *list = lists[i]; size_t tasks_len = 0; klist_task **tasks = klist_task_get_for_list(ctx, list->id, &tasks_len); - fprintf(stderr, "Name: %s\nDescription: %s\nTasks: %ld\n", - (char *)list->name, (char *)list->desc, tasks_len); + printf("Name: %s\n", (char *)list->name); + printf("Description: %s\n", list->desc ? (char *)list->desc : "N/A"); + printf("Tasks: %ld\n", tasks_len); i = 0; for (; i < tasks_len; i++) klist_task_deinit(tasks[i]); @@ -117,9 +119,9 @@ int main(int argc, char **argv) { } free(lists); } else if (list_ctx->name) - fprintf(stderr, "List '%s' not found.\n", list_ctx->name); + klist_print(ctx, KLIST_LOG_ERROR, "List '%s' not found.\n", list_ctx->name); else - fprintf(stderr, "No lists found.\n"); + klist_print(ctx, KLIST_LOG_WARNING, "No lists found.\n"); break; case LIST_DELETE: list = klist_list_get_by_user_and_name(ctx, user->id, list_ctx->name); @@ -151,11 +153,11 @@ int main(int argc, char **argv) { klist_stage **stages = klist_stage_get_all_for_list(ctx, list->id, &stages_len); if (!task_ctx->stage) { - fprintf(stderr, "Stage missing/wrong, please pass one of: "); + klist_print(ctx, KLIST_LOG_ERROR, "Stage missing/wrong, please pass one of: "); i = 0; for (; i < stages_len; i++) - fprintf(stderr, "%s ", (char *)stages[i]->name); - fprintf(stderr, "\n"); + fprintf(ctx->log_target, "%s ", (char *)stages[i]->name); + fprintf(ctx->log_target, "\n"); break; } i = 0; @@ -165,12 +167,12 @@ int main(int argc, char **argv) { stage_id = stages[i]->id; if (stage_id == -1) { - fprintf(stderr, + klist_print(ctx, KLIST_LOG_ERROR, "Stage %s not found. Use one of: ", task_ctx->stage); i = 0; for (; i < stages_len; i++) - fprintf(stderr, "%s ", (char *)stages[i]->name); - fprintf(stderr, "\n"); + fprintf(ctx->log_target, "%s ", (char *)stages[i]->name); + fprintf(ctx->log_target, "\n"); } i = 0; for (; i < stages_len; i++) @@ -194,7 +196,7 @@ int main(int argc, char **argv) { klist_task_save(ctx, task); klist_task_deinit(task); } else - fprintf(stderr, "List not found.\n"); + klist_print(ctx, KLIST_LOG_ERROR, "List not found.\n"); break; case TASK_GET: klist_assure_user(ctx, getuid(), getlogin()); @@ -205,33 +207,33 @@ int main(int argc, char **argv) { klist_task *task = klist_task_get_for_list_by_name(ctx, list->id, task_ctx->name); if (task) { - fprintf(stderr, "Name: %s\n", (char *)task->name); - fprintf(stderr, "Description: %s\n", (char *)task->desc); + printf("Name: %s\n", (char *)task->name); + printf("Description: %s\n", task->desc ? (char *)task->desc : "N/A"); klist_stage *stage = klist_stage_get_by_id(ctx, task->stage_id); - fprintf(stderr, "Stage: %s\n", (char *)stage->name); + printf("Stage: %s\n", (char *)stage->name); klist_stage_deinit(stage); klist_task_deinit(task); } else - fprintf(stderr, "Task not found.\n"); + klist_print(ctx, KLIST_LOG_ERROR, "Task not found.\n"); } else { size_t tasks_len = 0; klist_task **tasks = klist_task_get_for_list(ctx, list->id, &tasks_len); i = 0; for (; i < tasks_len; i++) { - fprintf(stderr, "Name: %s\n", (char *)tasks[i]->name); - fprintf(stderr, "Description: %s\n", (char *)tasks[i]->desc); + printf("Name: %s\n", (char *)tasks[i]->name); + printf("Description: %s\n", tasks[i]->desc ? (char *)tasks[i]->desc : "N/A"); klist_stage *stage = klist_stage_get_by_id(ctx, tasks[i]->stage_id); - fprintf(stderr, "Stage: %s\n", (char *)stage->name); + printf("Stage: %s\n", (char *)stage->name); klist_stage_deinit(stage); klist_task_deinit(tasks[i]); if ((i + 1) < tasks_len) - fprintf(stderr, "\n"); + fprintf(ctx->log_target, "\n"); } } } else - fprintf(stderr, "list not found\n"); + klist_print(ctx, KLIST_LOG_ERROR, "list not found\n"); case TASK_DELETE: klist_assure_user(ctx, getuid(), getlogin()); user = klist_user_get_by_local(ctx, getuid()); @@ -241,16 +243,16 @@ int main(int argc, char **argv) { klist_task *task = klist_task_get_for_list_by_name(ctx, list->id, task_ctx->name); if (task) { - fprintf(stderr, "Deleting task '%s'.\n", (char *)task->name); + klist_print(ctx, KLIST_LOG_WARNING, "Deleting task '%s'.\n", (char *)task->name); klist_task_delete(ctx, task); klist_task_deinit(task); } else - fprintf(stderr, "Task not found.\n"); + klist_print(ctx, KLIST_LOG_ERROR, "Task not found.\n"); } else - fprintf(stderr, "Task not found, only deletion by name is " + klist_print(ctx, KLIST_LOG_ERROR, "Task not found, only deletion by name is " "currently supoprted.\n"); } else - fprintf(stderr, "Not implemented\n"); + klist_print(ctx, KLIST_LOG_ERROR, "Not implemented\n"); } klist_task_context_deinit(task_ctx); default:; @@ -266,8 +268,8 @@ int main(int argc, char **argv) { return error; } -void print_help(char **argv) { - fprintf(stderr, "Usage: %s \n", argv[0]); +void print_help(klist *ctx, char **argv) { + printf("Usage: %s \n", argv[0]); } void setup(klist *ctx, int argc, char **argv) { @@ -278,7 +280,7 @@ void setup(klist *ctx, int argc, char **argv) { else if (strcmp(argv[1], "task") == 0) ctx->cmd = TASK; else - print_help(argv); + print_help(ctx, argv); int opt; switch (ctx->cmd) { @@ -297,7 +299,7 @@ void setup(klist *ctx, int argc, char **argv) { user_ctx->cmd = USER_GET; break; default: - print_help(argv); + print_help(ctx, argv); } ctx->cmd_ctx = user_ctx; break; @@ -330,15 +332,14 @@ void setup(klist *ctx, int argc, char **argv) { case 's': char *stage = NULL; while ((stage = strsep(&optarg, ","))) { - fprintf(stderr, "found stage %s\n", stage); list_ctx->stages = realloc(list_ctx->stages, (++list_ctx->stages_len) * sizeof(char *)); list_ctx->stages[list_ctx->stages_len - 1] = strdup(stage); } break; default: - print_help(argv); - fprintf(stderr, + print_help(ctx, argv); + klist_print(ctx, KLIST_LOG_ERROR, "" "list options:\n" "-a\t\tadd a list\n" @@ -352,7 +353,7 @@ void setup(klist *ctx, int argc, char **argv) { break; case TASK: if (argc < 3) { - fprintf(stderr, "Prints all lists.\n"); + klist_print(ctx, KLIST_LOG_ERROR, "Prints all lists.\n"); break; } klist_task_context *task_ctx = klist_task_context_init(ctx); @@ -380,8 +381,8 @@ void setup(klist *ctx, int argc, char **argv) { task_ctx->stage = strdup(optarg); break; default: - print_help(argv); - fprintf(stderr, + print_help(ctx, argv); + klist_print(ctx, KLIST_LOG_ERROR, "" "task options:" "-a\tadd a task" @@ -395,8 +396,8 @@ void setup(klist *ctx, int argc, char **argv) { ctx->cmd_ctx = task_ctx; break; default: - fprintf(stderr, "How did we land here?! Pls report argv[1] = %s\n", + klist_print(ctx, KLIST_LOG_ERROR, "How did we land here?! Pls report argv[1] = %s\n", argv[1]); - print_help(argv); + print_help(ctx, argv); } } diff --git a/src/main/models.c b/src/main/models.c index ae5cddc..72c1b3c 100644 --- a/src/main/models.c +++ b/src/main/models.c @@ -22,7 +22,7 @@ klist_user *klist_user_init_from_sql(sqlite3_stmt *stmt) { return user; } -klist_user *klist_user_get_by_id(klist *ctx, u_int id) { +klist_user *klist_user_get_by_id(const klist *ctx, u_int id) { sqlite3_stmt *stmt = ctx->stmts[GET_USER]; klist_user *user = NULL; sqlite3_bind_int(stmt, 1, id); @@ -32,44 +32,47 @@ klist_user *klist_user_get_by_id(klist *ctx, u_int id) { return user; } -klist_user *klist_user_get_by_local(klist *ctx, u_int local_id) { +klist_user *klist_user_get_by_local(const klist *ctx, u_int local_id) { sqlite3_stmt *stmt = ctx->stmts[GET_USER_BY_LOCAL]; klist_user *user = NULL; sqlite3_bind_int(stmt, 1, local_id); if (sqlite3_step(stmt) == SQLITE_ROW) { user = klist_user_init_from_sql(stmt); } else - fprintf(stderr, "failed to get user by local id %u: %s\n", local_id, + klist_print(ctx, KLIST_LOG_ERROR, "failed to get user by local id %u: %s\n", local_id, sqlite3_errmsg(ctx->db)); sqlite3_reset(stmt); + return user; } -void klist_user_save(klist *ctx, klist_user *user) { +void klist_user_save(const klist *ctx, klist_user *user) { sqlite3_stmt *stmt = ctx->stmts[ADD_USER]; int result = 0; - sqlite3_bind_text(stmt, 1, (char *)user->name, -1, SQLITE_STATIC); + if (user->id > -1) + sqlite3_bind_int(stmt, 1, user->id); + sqlite3_bind_text(stmt, 2, (char *)user->name, -1, SQLITE_STATIC); + if ((result = sqlite3_step(stmt)) == SQLITE_ROW) user->id = sqlite3_column_int(stmt, 0); else - fprintf(stderr, "failed to save user: %s - %d\n", sqlite3_errmsg(ctx->db), + klist_print(ctx, KLIST_LOG_ERROR, "failed to save user: %s - %d\n", sqlite3_errmsg(ctx->db), result); sqlite3_reset(stmt); if (user->local_id != -1) { - sqlite3_stmt *stmt = ctx->stmts[ADD_LOGIN]; - int result = 0; + stmt = ctx->stmts[ADD_LOGIN]; sqlite3_bind_int(stmt, 1, user->id); sqlite3_bind_int(stmt, 2, user->local_id); - if ((result = sqlite3_step(stmt)) != SQLITE_ROW) - fprintf(stderr, "failed to save logins for user: %s - %d\n", + if (sqlite3_step(stmt) != SQLITE_ROW) + klist_print(ctx, KLIST_LOG_ERROR, "failed to save logins for user: %s - %d\n", sqlite3_errmsg(ctx->db), result); sqlite3_reset(stmt); } else - fprintf(stderr, "no local uid saved for user %s", user->name); + klist_print(ctx, KLIST_LOG_ERROR, "no local uid saved for user %s", (char *)user->name); } -void klist_user_delete(klist *ctx, klist_user *user) { +void klist_user_delete(const klist *ctx, const klist_user *user) { sqlite3_stmt *stmt = ctx->stmts[DEL_USER]; sqlite3_bind_int(stmt, 1, (int)user->id); if (sqlite3_step(stmt) == SQLITE_ROW) @@ -101,7 +104,7 @@ klist_stage *klist_stage_init_from_sql(sqlite3_stmt *stmt) { return stage; } -klist_stage *klist_stage_get_by_id(klist *ctx, u_int id) { +klist_stage *klist_stage_get_by_id(const klist *ctx, u_int id) { sqlite3_stmt *stmt = ctx->stmts[GET_STAGE]; sqlite3_bind_int(stmt, 1, id); if (sqlite3_step(stmt) == SQLITE_ROW) { @@ -111,15 +114,15 @@ klist_stage *klist_stage_get_by_id(klist *ctx, u_int id) { return NULL; } -klist_stage **klist_stage_get_all_for_list(klist *ctx, u_int id, +klist_stage **klist_stage_get_all_for_list(const klist *ctx, u_int id, size_t *count) { sqlite3_stmt *stmt = ctx->stmts[GET_STAGES_FOR_LIST]; sqlite3_bind_int(stmt, 1, id); klist_stage **stages = NULL; size_t stages_len = 0; while (sqlite3_step(stmt) == SQLITE_ROW) { - stages_len++; - klist_stage **_stages = realloc(stages, stages_len * sizeof(klist_stage *)); + klist_stage **_stages = + realloc(stages, ++stages_len * sizeof(klist_stage *)); if (_stages) { stages = _stages; stages[stages_len - 1] = klist_stage_init_from_sql(stmt); @@ -130,17 +133,19 @@ klist_stage **klist_stage_get_all_for_list(klist *ctx, u_int id, return stages; } -void klist_stage_save(klist *ctx, klist_stage *stage) { +void klist_stage_save(const klist *ctx, klist_stage *stage) { sqlite3_stmt *stmt = ctx->stmts[ADD_STAGE]; int result = 0; - sqlite3_bind_text(stmt, 1, (char *)stage->name, -1, SQLITE_STATIC); + if (stage->id > -1) + sqlite3_bind_int(stmt, 1, stage->id); sqlite3_bind_text(stmt, 2, (char *)stage->name, -1, SQLITE_STATIC); - sqlite3_bind_int(stmt, 3, stage->list_id); + sqlite3_bind_text(stmt, 3, (char *)stage->name, -1, SQLITE_STATIC); + sqlite3_bind_int(stmt, 4, stage->list_id); if ((result = sqlite3_step(stmt)) == SQLITE_ROW || result == SQLITE_DONE) { stage->id = sqlite3_column_int(stmt, 0); sqlite3_reset(stmt); } else - fprintf(stderr, "failed to save stage: %s - %d\n", sqlite3_errmsg(ctx->db), + klist_print(ctx, KLIST_LOG_ERROR, "failed to save stage: %s - %d\n", sqlite3_errmsg(ctx->db), result); } @@ -173,7 +178,7 @@ klist_list *klist_list_init_from_sql(sqlite3_stmt *stmt) { return list; } -klist_list *klist_list_get_by_id(klist *ctx, u_int id) { +klist_list *klist_list_get_by_id(const klist *ctx, u_int id) { sqlite3_stmt *stmt = ctx->stmts[GET_LIST]; sqlite3_bind_int(stmt, 1, id); if (sqlite3_step(stmt) == SQLITE_ROW) { @@ -183,15 +188,14 @@ klist_list *klist_list_get_by_id(klist *ctx, u_int id) { return NULL; } -klist_list **klist_list_get_all_by_user(klist *ctx, u_int user_id, +klist_list **klist_list_get_all_by_user(const klist *ctx, u_int user_id, size_t *count) { sqlite3_stmt *stmt = ctx->stmts[GET_LISTS_BY_USER]; sqlite3_bind_int(stmt, 1, user_id); klist_list **lists = NULL; size_t lists_len = 0; while (sqlite3_step(stmt) == SQLITE_ROW) { - lists_len++; - klist_list **_lists = realloc(lists, lists_len * sizeof(klist_list *)); + klist_list **_lists = realloc(lists, ++lists_len * sizeof(klist_list *)); if (_lists) { lists = _lists; lists[lists_len - 1] = klist_list_init_from_sql(stmt); @@ -202,7 +206,7 @@ klist_list **klist_list_get_all_by_user(klist *ctx, u_int user_id, return lists; } -klist_list *klist_list_get_by_user_and_name(klist *ctx, u_int user_id, +klist_list *klist_list_get_by_user_and_name(const klist *ctx, u_int user_id, const char *name) { sqlite3_stmt *stmt = ctx->stmts[GET_LISTS_BY_USER_NAME]; klist_list *list = NULL; @@ -212,31 +216,36 @@ klist_list *klist_list_get_by_user_and_name(klist *ctx, u_int user_id, if (sqlite3_step(stmt) == SQLITE_ROW) list = klist_list_init_from_sql(stmt); else - fprintf(stderr, "failed to get lists for user\n"); + klist_print(ctx, KLIST_LOG_ERROR, "failed to get lists for user: %s\n", sqlite3_errmsg(ctx->db)); sqlite3_reset(stmt); return list; } -void klist_list_save(klist *ctx, klist_list *list, klist_user *user) { +void klist_list_save(const klist *ctx, klist_list *list, + const klist_user *user) { sqlite3_stmt *stmt = ctx->stmts[ADD_LIST]; int result = 0; - sqlite3_bind_text(stmt, 1, (char *)list->name, -1, SQLITE_STATIC); - sqlite3_bind_text(stmt, 2, (char *)list->desc, -1, SQLITE_STATIC); - sqlite3_bind_int(stmt, 3, list->is_preset); - if ((result = sqlite3_step(stmt)) == SQLITE_ROW) { + if (list->id > -1) + sqlite3_bind_int(stmt, 1, list->id); + sqlite3_bind_text(stmt, 2, (char *)list->name, -1, SQLITE_STATIC); + sqlite3_bind_text(stmt, 3, (char *)list->desc, -1, SQLITE_STATIC); + sqlite3_bind_int(stmt, 4, list->is_preset); + if ((result = sqlite3_step(stmt)) == SQLITE_ROW) list->id = sqlite3_column_int(stmt, 0); - sqlite3_reset(stmt); - } else - fprintf(stderr, "failed to save list: %s - %d\n", sqlite3_errmsg(ctx->db), + else + klist_print(ctx, KLIST_LOG_ERROR, "failed to save list: %s - %d\n", sqlite3_errmsg(ctx->db), result); - if (list->id) { - sqlite3_stmt *stmt = ctx->stmts[ADD_USER_LIST]; + sqlite3_reset(stmt); + + + if (list->id > -1) { + stmt = ctx->stmts[ADD_USER_LIST]; sqlite3_bind_int(stmt, 1, list->id); sqlite3_bind_int(stmt, 2, user->id); if (sqlite3_step(stmt) == SQLITE_DONE) sqlite3_reset(stmt); else - fprintf(stderr, "failed to save user - list relation in join table: %s\n", + klist_print(ctx, KLIST_LOG_ERROR, "failed to save user - list relation in join table: %s\n", sqlite3_errmsg(ctx->db)); } } @@ -272,7 +281,7 @@ klist_task *klist_task_init_from_sql(sqlite3_stmt *stmt) { return task; } -klist_task *klist_task_get_by_id(klist *ctx, u_int id) { +klist_task *klist_task_get_by_id(const klist *ctx, u_int id) { sqlite3_stmt *stmt = ctx->stmts[GET_TASK]; sqlite3_bind_int(stmt, 1, id); if (sqlite3_step(stmt) == SQLITE_ROW) { @@ -282,7 +291,8 @@ klist_task *klist_task_get_by_id(klist *ctx, u_int id) { return NULL; } -klist_task **klist_task_get_for_list(klist *ctx, u_int list_id, size_t *count) { +klist_task **klist_task_get_for_list(const klist *ctx, u_int list_id, + size_t *count) { sqlite3_stmt *stmt = ctx->stmts[GET_TASKS_FOR_LIST]; sqlite3_bind_int(stmt, 1, list_id); klist_task **tasks = NULL; @@ -300,7 +310,7 @@ klist_task **klist_task_get_for_list(klist *ctx, u_int list_id, size_t *count) { return tasks; } -klist_task *klist_task_get_for_list_by_name(klist *ctx, u_int list_id, +klist_task *klist_task_get_for_list_by_name(const klist *ctx, u_int list_id, const char *name) { sqlite3_stmt *stmt = ctx->stmts[GET_TASKS_FOR_LIST_BY_NAME]; klist_task *task = NULL; @@ -309,13 +319,13 @@ klist_task *klist_task_get_for_list_by_name(klist *ctx, u_int list_id, if (sqlite3_step(stmt) == SQLITE_ROW) task = klist_task_init_from_sql(stmt); else - fprintf(stderr, "no tasks found for list %d, name '%s': %s\n", list_id, + klist_print(ctx, KLIST_LOG_WARNING, "no tasks found for list %d, name '%s': %s\n", list_id, name, sqlite3_errmsg(ctx->db)); sqlite3_reset(stmt); return task; } -void klist_task_save(klist *ctx, klist_task *task) { +void klist_task_save(const klist *ctx, klist_task *task) { sqlite3_stmt *stmt = ctx->stmts[ADD_TASK]; int result = 0; if (task->id > -1) @@ -323,24 +333,24 @@ void klist_task_save(klist *ctx, klist_task *task) { sqlite3_bind_text(stmt, 2, (char *)task->name, -1, SQLITE_STATIC); sqlite3_bind_text(stmt, 3, (char *)task->desc, -1, SQLITE_STATIC); sqlite3_bind_int(stmt, 4, task->stage_id); - if (task->due) + if (task->due > 0) sqlite3_bind_int(stmt, 5, task->due); - if (task->target_stage) + if (task->target_stage > 0) sqlite3_bind_int(stmt, 6, task->target_stage); if ((result = sqlite3_step(stmt)) == SQLITE_ROW) { task->id = sqlite3_column_int(stmt, 0); } else - fprintf(stderr, "failed to save list: %s - %d\n", sqlite3_errmsg(ctx->db), + klist_print(ctx, KLIST_LOG_ERROR, "failed to save list: %s - %d\n", sqlite3_errmsg(ctx->db), result); sqlite3_reset(stmt); } -void klist_task_delete(klist *ctx, klist_task *task) { +void klist_task_delete(const klist *ctx, const klist_task *task) { sqlite3_stmt *stmt = ctx->stmts[DEL_TASK]; sqlite3_bind_int(stmt, 1, task->id); if (sqlite3_step(stmt) == SQLITE_DONE) sqlite3_reset(stmt); else - fprintf(stderr, "failed to delete task: %s\n", sqlite3_errmsg(ctx->db)); + klist_print(ctx, KLIST_LOG_ERROR, "failed to delete task: %s\n", sqlite3_errmsg(ctx->db)); } void klist_task_deinit(klist_task *task) { diff --git a/src/main/sql.c b/src/main/sql.c index 87dd18f..07506b0 100644 --- a/src/main/sql.c +++ b/src/main/sql.c @@ -17,7 +17,9 @@ const char *klist_sql_get(const enum KLIST_SQL sql) { " id integer primary key,\n" " user_id integer not null,\n" " local_id integer,\n" - " foreign key (user_id) references users(id)" + " foreign key (user_id) references users(id),\n" + " unique(user_id, local_id) on conflict ignore,\n" + " unique(user_id)\n" ");\n" "create table if not exists user_lists (\n" " id integer primary key,\n" @@ -39,8 +41,6 @@ const char *klist_sql_get(const enum KLIST_SQL sql) { " list_id integer not null,\n" " foreign key (list_id) references lists(id)\n" ");\n" - "-- this currently enables moving tasks _between lists_ (planned of " - "course)\n" "create table if not exists tasks (\n" " id integer primary key,\n" " name text not null,\n" @@ -53,16 +53,17 @@ const char *klist_sql_get(const enum KLIST_SQL sql) { ")"; case ADD_LOGIN: return "insert into user_logins (user_id, local_id) values (?1, ?2) on " - "conflict (id) do update set user_id=excluded.user_id, " - "local_id=excluded.local_id returning id"; + "conflict (user_id) do update set local_id=excluded.local_id " + "returning id"; case ADD_USER: - return "insert into users (name) values (?1) on conflict (id) do update " + return "insert into users (id, name) values (?1, ?2) on conflict (id) do " + "update " "set name=excluded.name returning id"; case GET_USER: return "select users.*, user_logins.local_id from users inner join " "user_logins on user_logins.user_id = users.id where users.id = ?1"; case GET_USER_BY_LOCAL: - return "select * from users inner join user_logins on user_logins.user_id " + return "select users.* from users inner join user_logins on user_logins.user_id " "= users.id where user_logins.local_id = ?1"; case GET_USERS: return "select * from users"; @@ -71,8 +72,8 @@ const char *klist_sql_get(const enum KLIST_SQL sql) { case DEL_USER: return "delete from users where id = ?1"; case ADD_LIST: - return "insert into lists (name, desc, is_preset) values (?1, ?2, ?3) on " - "conflict (id) do update set name=excluded.name, " + return "insert into lists (id, name, desc, is_preset) values (?1, ?2, ?3, " + "?4) on conflict (id) do update set name=excluded.name, " "desc=excluded.desc, is_preset=excluded.is_preset returning id"; case ADD_USER_LIST: return "insert into user_lists (user_id, list_id) values (?1, ?2)"; @@ -91,8 +92,8 @@ const char *klist_sql_get(const enum KLIST_SQL sql) { case DEL_LIST: return "delete from lists where id = ?1"; case ADD_STAGE: - return "insert into task_stages (name, desc, list_id) values (?1, ?2, ?3) " - "on conflict (id) do update set name=excluded.name, " + return "insert into task_stages (id, name, desc, list_id) values (?1, ?2, " + "?3, ?4) on conflict (id) do update set name=excluded.name, " "desc=excluded.desc returning id"; case GET_STAGE: return "select * from task_stages where id = ?1"; @@ -102,8 +103,7 @@ const char *klist_sql_get(const enum KLIST_SQL sql) { return "delete from task_stages where id = ?1"; case ADD_TASK: return "insert into tasks (id, name, desc, stage, due, target_stage) " - "values " - "(?1, ?2, ?3, ?4, ?5, ?6) on conflict (id) do update set " + "values (?1, ?2, ?3, ?4, ?5, ?6) on conflict (id) do update set " "name=excluded.name, desc=excluded.desc, stage=excluded.stage, " "due=excluded.due, target_stage=excluded.target_stage returning id"; case GET_TASK: diff --git a/src/main/util.c b/src/main/util.c index a5fcd35..a15d9b7 100644 --- a/src/main/util.c +++ b/src/main/util.c @@ -17,6 +17,8 @@ klist *klist_init(char *db) { ctx->stmts = malloc(_KLIST_SQL_COUNT * sizeof(sqlite3_stmt *)); ctx->cmd_ctx = NULL; ctx->error = 0; + ctx->log_level = KLIST_LOG_WARNING; + ctx->log_target = stderr; klist_sql_prepare(ctx, db); @@ -95,14 +97,15 @@ void klist_task_context_deinit(klist_task_context *ctx) { */ void klist_sql_prepare(klist *ctx, char *db) { + if (!db) klist_print(ctx, KLIST_LOG_WARNING, "Database will be in-memory only, changes are not persistent!\n"); if (sqlite3_open(db ? db : ":memory:", &ctx->db) != SQLITE_OK) { - fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(ctx->db)); + klist_print(ctx, KLIST_LOG_ERROR, "Can't open database: %s\n", sqlite3_errmsg(ctx->db)); return; } char *errmsg = NULL; sqlite3_exec(ctx->db, klist_sql_get(INIT), NULL, NULL, &errmsg); if (errmsg) { - fprintf(stderr, "Database initialization failed (%s), expect issues.\n", + klist_print(ctx, KLIST_LOG_ERROR, "Database initialization failed (%s), expect issues.\n", sqlite3_errmsg(ctx->db)); sqlite3_free(errmsg); } @@ -110,7 +113,7 @@ void klist_sql_prepare(klist *ctx, char *db) { for (; i < _KLIST_SQL_COUNT; i++) if (sqlite3_prepare(ctx->db, klist_sql_get(i), -1, &ctx->stmts[i], NULL) != SQLITE_OK) - fprintf(stderr, "sqlite3_prepare: %s\n", sqlite3_errmsg(ctx->db)); + klist_print(ctx, KLIST_LOG_WARNING, "sqlite3_prepare for '%s' failed: %s\n", klist_sql_get(i), sqlite3_errmsg(ctx->db)); } void klist_sql_seed(klist *ctx) {} @@ -134,4 +137,23 @@ bool klist_assure_user(klist *ctx, __uid_t id, char *name) { return created; } void klist_assure_list(klist *, char *); -void klist_assure_task(klist *, char *); \ No newline at end of file +void klist_assure_task(klist *, char *); + +/* + * printing methods + */ + +void klist_print(const klist *ctx, KLIST_LOG_LEVEL log_level, const char *format, ...) { + if (ctx->log_level >= log_level) { + switch (log_level) { + case KLIST_LOG_DEBUG: fprintf(ctx->log_target, "[\x1B[34mDBG\x1B[0m] "); break; + case KLIST_LOG_INFO: fprintf(ctx->log_target, "[\x1B[36mINF\x1B[0m] "); break; + case KLIST_LOG_WARNING: fprintf(ctx->log_target, "[\x1B[33mWRN\x1B[0m] "); break; + case KLIST_LOG_ERROR: fprintf(ctx->log_target, "[\x1B[31mERR\x1B[0m] "); break; + } + va_list args; + va_start(args, format); + vprintf(format, args); + va_end(args); + } +} \ No newline at end of file