From fcd0b9e69f106c259a512ee039172217d9e5c7f3 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Sat, 9 Nov 2024 16:20:08 -0500 Subject: [PATCH 01/62] Fix some issues found by cppcheck --- app/overwrite.c | 69 ++++++++++++++++--------------------------------- 1 file changed, 22 insertions(+), 47 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index d77b699f..634fdaa0 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -105,7 +105,6 @@ static int zsv_overwrites_init(struct zsv_overwrite_ctx *ctx, struct zsv_overwri } sqlite3_stmt *query = NULL; - int ret = 0; /* if ((ret = sqlite3_initialize()) != SQLITE_OK) { @@ -114,38 +113,38 @@ static int zsv_overwrites_init(struct zsv_overwrite_ctx *ctx, struct zsv_overwri } */ - if ((ret = sqlite3_open_v2(overwrites_fn, &ctx->sqlite3.db, SQLITE_OPEN_READONLY, NULL)) != SQLITE_OK || args->add || + if (sqlite3_open_v2(overwrites_fn, &ctx->sqlite3.db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK || args->add || args->clear) { sqlite3_close(ctx->sqlite3.db); - if ((ret = sqlite3_open_v2(overwrites_fn, &ctx->sqlite3.db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL)) != + if (sqlite3_open_v2(overwrites_fn, &ctx->sqlite3.db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != SQLITE_OK) { err = 1; - fprintf(stderr, "Failed to open conn: %d, %s\n", ret, sqlite3_errmsg(ctx->sqlite3.db)); + fprintf(stderr, "Failed to open conn: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); return err; } - if ((ret = sqlite3_prepare_v2(ctx->sqlite3.db, + if (sqlite3_prepare_v2(ctx->sqlite3.db, "CREATE TABLE IF NOT EXISTS overwrites ( row integer, column integer, value string, " "timestamp varchar(25), author varchar(25) );", - -1, &query, NULL)) == SQLITE_OK) { - if ((ret = sqlite3_step(query)) != SQLITE_DONE) { + -1, &query, NULL) == SQLITE_OK) { + if (sqlite3_step(query) != SQLITE_DONE) { err = 1; - fprintf(stderr, "Failed to step: %d, %s\n", ret, sqlite3_errmsg(ctx->sqlite3.db)); + fprintf(stderr, "Failed to step: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); return err; } } else { err = 1; - fprintf(stderr, "Failed to prepare: %d, %s\n", ret, sqlite3_errmsg(ctx->sqlite3.db)); + fprintf(stderr, "Failed to prepare: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); } if (query) sqlite3_finalize(query); - if ((ret = sqlite3_prepare_v2(ctx->sqlite3.db, "CREATE UNIQUE INDEX overwrites_uix ON overwrites (row, column)", -1, - &query, NULL)) == SQLITE_OK) { - if ((ret = sqlite3_step(query)) != SQLITE_DONE) { + if (sqlite3_prepare_v2(ctx->sqlite3.db, "CREATE UNIQUE INDEX overwrites_uix ON overwrites (row, column)", -1, + &query, NULL) == SQLITE_OK) { + if (sqlite3_step(query) != SQLITE_DONE) { err = 1; - fprintf(stderr, "Failed to step: %d, %s\n", ret, sqlite3_errmsg(ctx->sqlite3.db)); + fprintf(stderr, "Failed to step: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); return err; } if (query) @@ -162,39 +161,16 @@ static int zsv_overwrites_init(struct zsv_overwrite_ctx *ctx, struct zsv_overwri static int zsv_overwrites_clear(struct zsv_overwrite_ctx *ctx) { int err = 0; sqlite3_stmt *query = NULL; - int ret; - if ((ret = sqlite3_prepare_v2(ctx->sqlite3.db, "DELETE FROM overwrites", -1, &query, NULL)) == SQLITE_OK) { - if ((ret = sqlite3_step(query)) != SQLITE_DONE) { + if (sqlite3_prepare_v2(ctx->sqlite3.db, "DELETE FROM overwrites", -1, &query, NULL) == SQLITE_OK) { + if (sqlite3_step(query) != SQLITE_DONE) { err = 1; - fprintf(stderr, "Failed to step: %d, %s\n", ret, sqlite3_errmsg(ctx->sqlite3.db)); + fprintf(stderr, "Failed to step: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); return err; } } else { err = 1; - fprintf(stderr, "Could not prepare: %d, %s\n", ret, sqlite3_errmsg(ctx->sqlite3.db)); - } - if (query) - sqlite3_finalize(query); - return err; -} - -static int zsv_overwrite_check_for_value(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite) { - sqlite3_stmt *query = NULL; - int ret = 0; - int err = 0; - if ((ret = sqlite3_prepare_v2(ctx->sqlite3.db, "SELECT 1 FROM overwrites WHERE row = ? AND column = ?", -1, &query, - NULL)) != SQLITE_OK) { - err = 1; - fprintf(stderr, "Failed to prepare: %d, %s\n", ret, sqlite3_errmsg(ctx->sqlite3.db)); - return err; + fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); } - sqlite3_bind_int64(query, 1, overwrite->row_ix); - sqlite3_bind_int64(query, 2, overwrite->col_ix); - if ((ret = sqlite3_step(query)) == SQLITE_ROW) // Value exists - err = 1; - else // Value does not exist - err = 0; - if (query) sqlite3_finalize(query); return err; @@ -204,11 +180,10 @@ static int zsv_overwrites_insert(struct zsv_overwrite_ctx *ctx, struct zsv_overw struct zsv_overwrite_args *args) { int err = 0; sqlite3_stmt *query = NULL; - int ret; - if ((ret = sqlite3_prepare_v2(ctx->sqlite3.db, + if (sqlite3_prepare_v2(ctx->sqlite3.db, "INSERT INTO overwrites (row, column, value, timestamp, author) VALUES (?, ?, ?, ?, ?)", - -1, &query, NULL)) == SQLITE_OK) { + -1, &query, NULL) == SQLITE_OK) { sqlite3_bind_int64(query, 1, overwrite->row_ix); sqlite3_bind_int64(query, 2, overwrite->col_ix); sqlite3_bind_text(query, 3, (const char *)overwrite->val.str, -1, SQLITE_STATIC); @@ -217,7 +192,7 @@ static int zsv_overwrites_insert(struct zsv_overwrite_ctx *ctx, struct zsv_overw else sqlite3_bind_null(query, 4); sqlite3_bind_text(query, 5, "", -1, SQLITE_STATIC); // author - if ((ret = sqlite3_step(query)) != SQLITE_DONE) { + if (sqlite3_step(query) != SQLITE_DONE) { err = 1; fprintf(stderr, "Value already exists at row %zu and column %zu, use --force to force insert\n", overwrite->row_ix, overwrite->col_ix); @@ -225,7 +200,7 @@ static int zsv_overwrites_insert(struct zsv_overwrite_ctx *ctx, struct zsv_overw } } else { err = 1; - fprintf(stderr, "Failed to prepare: %d, %s\n", ret, sqlite3_errmsg(ctx->sqlite3.db)); + fprintf(stderr, "Failed to prepare: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); } if (query) @@ -275,7 +250,7 @@ static int show_all_overwrites(struct zsv_overwrite_ctx *ctx, struct zsv_overwri int err = 0; sqlite3_stmt *stmt; int ret; - if ((ret = sqlite3_prepare_v2(ctx->sqlite3.db, "SELECT * FROM overwrites", -1, &stmt, NULL) != SQLITE_OK)) { + if (sqlite3_prepare_v2(ctx->sqlite3.db, "SELECT * FROM overwrites", -1, &stmt, NULL) != SQLITE_OK) { err = 1; fprintf(stderr, "Failed to prepare statement: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); return err; @@ -379,7 +354,7 @@ static int zsv_overwrite_parse_pos(struct zsv_overwrite_data *overwrite, const c int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *opts, struct zsv_prop_handler *custom_prop_handler, const char *opts_used) { int err = 0; - if (argc < 3 || (argc > 1 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")))) { + if (argc < 3 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { zsv_overwrite_usage(); return err; } From ef02b3a321e429f5ba3e3109b10150c881ff0e42 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Sat, 9 Nov 2024 16:24:55 -0500 Subject: [PATCH 02/62] add const to args --- app/overwrite.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 634fdaa0..b40d0ba0 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -177,7 +177,7 @@ static int zsv_overwrites_clear(struct zsv_overwrite_ctx *ctx) { } static int zsv_overwrites_insert(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, - struct zsv_overwrite_args *args) { + const struct zsv_overwrite_args *args) { int err = 0; sqlite3_stmt *query = NULL; @@ -246,7 +246,7 @@ static char *row_col_to_a1(size_t col, size_t row) { return result; } -static int show_all_overwrites(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_args *args, zsv_csv_writer writer) { +static int show_all_overwrites(struct zsv_overwrite_ctx *ctx, const struct zsv_overwrite_args *args, zsv_csv_writer writer) { int err = 0; sqlite3_stmt *stmt; int ret; From 931b13dfeb820abf82e1a7b2c1c820f5419d8e8f Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Sat, 9 Nov 2024 16:25:18 -0500 Subject: [PATCH 03/62] format --- app/overwrite.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index b40d0ba0..cac2e943 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -124,9 +124,9 @@ static int zsv_overwrites_init(struct zsv_overwrite_ctx *ctx, struct zsv_overwri } if (sqlite3_prepare_v2(ctx->sqlite3.db, - "CREATE TABLE IF NOT EXISTS overwrites ( row integer, column integer, value string, " - "timestamp varchar(25), author varchar(25) );", - -1, &query, NULL) == SQLITE_OK) { + "CREATE TABLE IF NOT EXISTS overwrites ( row integer, column integer, value string, " + "timestamp varchar(25), author varchar(25) );", + -1, &query, NULL) == SQLITE_OK) { if (sqlite3_step(query) != SQLITE_DONE) { err = 1; fprintf(stderr, "Failed to step: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); @@ -141,7 +141,7 @@ static int zsv_overwrites_init(struct zsv_overwrite_ctx *ctx, struct zsv_overwri sqlite3_finalize(query); if (sqlite3_prepare_v2(ctx->sqlite3.db, "CREATE UNIQUE INDEX overwrites_uix ON overwrites (row, column)", -1, - &query, NULL) == SQLITE_OK) { + &query, NULL) == SQLITE_OK) { if (sqlite3_step(query) != SQLITE_DONE) { err = 1; fprintf(stderr, "Failed to step: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); @@ -182,8 +182,8 @@ static int zsv_overwrites_insert(struct zsv_overwrite_ctx *ctx, struct zsv_overw sqlite3_stmt *query = NULL; if (sqlite3_prepare_v2(ctx->sqlite3.db, - "INSERT INTO overwrites (row, column, value, timestamp, author) VALUES (?, ?, ?, ?, ?)", - -1, &query, NULL) == SQLITE_OK) { + "INSERT INTO overwrites (row, column, value, timestamp, author) VALUES (?, ?, ?, ?, ?)", -1, + &query, NULL) == SQLITE_OK) { sqlite3_bind_int64(query, 1, overwrite->row_ix); sqlite3_bind_int64(query, 2, overwrite->col_ix); sqlite3_bind_text(query, 3, (const char *)overwrite->val.str, -1, SQLITE_STATIC); @@ -246,7 +246,8 @@ static char *row_col_to_a1(size_t col, size_t row) { return result; } -static int show_all_overwrites(struct zsv_overwrite_ctx *ctx, const struct zsv_overwrite_args *args, zsv_csv_writer writer) { +static int show_all_overwrites(struct zsv_overwrite_ctx *ctx, const struct zsv_overwrite_args *args, + zsv_csv_writer writer) { int err = 0; sqlite3_stmt *stmt; int ret; From 20f4c023a6daed559fdf2ab984a3bfc066620912 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Mon, 11 Nov 2024 18:32:08 -0500 Subject: [PATCH 04/62] Add --force flag, replace functionality, and remove function (unused right now) --- app/overwrite.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 2 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index cac2e943..19db03bc 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -29,6 +29,7 @@ struct zsv_overwrite_args { char *filepath; // options + unsigned char force : 1; unsigned char a1 : 1; unsigned char timestamp : 1; // commands @@ -176,8 +177,72 @@ static int zsv_overwrites_clear(struct zsv_overwrite_ctx *ctx) { return err; } +static int zsv_overwrites_remove(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite) { + int err = 0; + sqlite3_stmt *query = NULL; + if (sqlite3_prepare_v2(ctx->sqlite3.db, + "DELETE FROM overwrites WHERE row = ? AND column = ?", -1, + &query, NULL) != SQLITE_OK) { + err = 1; + return err; + } + sqlite3_bind_int64(query, 1, overwrite->row_ix); + sqlite3_bind_int64(query, 2, overwrite->col_ix); + + if (sqlite3_step(query) != SQLITE_DONE) { + err = 1; + return err; + } + if(query) + sqlite3_finalize(query); + return err; +} + +static int zsv_overwrites_check_value(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite) { + sqlite3_stmt *query; + if (sqlite3_prepare_v2(ctx->sqlite3.db, + "SELECT 1 FROM overwrites WHERE row = ? AND column = ?", -1, + &query, NULL) != SQLITE_OK) { + fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); + return 1; + } + sqlite3_bind_int64(query, 1, overwrite->row_ix); + sqlite3_bind_int64(query, 2, overwrite->col_ix); + if(sqlite3_step(query) == SQLITE_ROW) { + if(query) sqlite3_finalize(query); + return 1; // value exists + } + return 0; // value does not exist +} + +static int zsv_overwrites_replace(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, const struct zsv_overwrite_args *args) { + sqlite3_stmt *query = NULL; + if (sqlite3_prepare_v2(ctx->sqlite3.db, + "UPDATE overwrites SET value = ?, timestamp = ?, author = ? WHERE row = ? AND column = ?", -1, + &query, NULL) != SQLITE_OK) { + fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); + return 1; + } + sqlite3_bind_text(query, 1, (const char *)overwrite->val.str, -1, SQLITE_STATIC); + if (args->timestamp) + sqlite3_bind_int64(query, 2, time(NULL)); + else + sqlite3_bind_null(query, 2); + sqlite3_bind_text(query, 3, "", -1, SQLITE_STATIC); // author + sqlite3_bind_int64(query, 4, overwrite->row_ix); + sqlite3_bind_int64(query, 5, overwrite->col_ix); + if(sqlite3_step(query) != SQLITE_DONE) { + fprintf(stderr, "Could not step: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); + return 1; + } + return 0; +} + static int zsv_overwrites_insert(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, const struct zsv_overwrite_args *args) { + if(args->force && zsv_overwrites_check_value(ctx, overwrite)) + return zsv_overwrites_replace(ctx, overwrite, args); + int err = 0; sqlite3_stmt *query = NULL; @@ -373,8 +438,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op for (int i = 2; !err && i < argc; i++) { const char *opt = argv[i]; if (!strcmp(opt, "-f") || !strcmp(opt, "--force")) { - err = 1; - fprintf(stderr, "Error: %s is not implemented\n", opt); + args.force = 1; } else if (!strcmp(opt, "--old-value")) { fprintf(stderr, "Error: %s is not implemented\n", opt); err = 1; From 777b5b46d0a0a00358f3cbe7265d3c7ed648f913 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Mon, 11 Nov 2024 21:10:11 -0500 Subject: [PATCH 05/62] Implement remove functionality and fix issue with list --A1 not working properly --- app/overwrite.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 19db03bc..11c1d8df 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -36,6 +36,7 @@ struct zsv_overwrite_args { unsigned char list : 1; unsigned char clear : 1; unsigned char add : 1; + unsigned char remove : 1; }; const char *zsv_overwrite_usage_msg[] = { @@ -114,7 +115,7 @@ static int zsv_overwrites_init(struct zsv_overwrite_ctx *ctx, struct zsv_overwri } */ - if (sqlite3_open_v2(overwrites_fn, &ctx->sqlite3.db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK || args->add || + if (sqlite3_open_v2(overwrites_fn, &ctx->sqlite3.db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK || args->add || args->remove || args->clear) { sqlite3_close(ctx->sqlite3.db); if (sqlite3_open_v2(overwrites_fn, &ctx->sqlite3.db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != @@ -184,6 +185,7 @@ static int zsv_overwrites_remove(struct zsv_overwrite_ctx *ctx, struct zsv_overw "DELETE FROM overwrites WHERE row = ? AND column = ?", -1, &query, NULL) != SQLITE_OK) { err = 1; + fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); return err; } sqlite3_bind_int64(query, 1, overwrite->row_ix); @@ -191,6 +193,7 @@ static int zsv_overwrites_remove(struct zsv_overwrite_ctx *ctx, struct zsv_overw if (sqlite3_step(query) != SQLITE_DONE) { err = 1; + fprintf(stderr, "Could not step: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); return err; } if(query) @@ -303,7 +306,6 @@ static char *row_col_to_a1(size_t col, size_t row) { if (col == 0) break; } - printf("%s\n", &buffer[index]); // 20 extra bytes for row char *result = malloc(strlen(&buffer[index]) + 20 + 1); if (result) @@ -340,7 +342,7 @@ static int show_all_overwrites(struct zsv_overwrite_ctx *ctx, const struct zsv_o const unsigned char *author = sqlite3_column_text(stmt, 4); size_t author_len = sqlite3_column_bytes(stmt, 4); if (args->a1) { - char *col_a1 = row_col_to_a1(col, row); + char *col_a1 = row_col_to_a1(col+1, row); // add one to display the correct letter if (!col_a1) { err = 1; fprintf(stderr, "Error converting column number to A1-notation\n"); @@ -464,6 +466,17 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op fprintf(stderr, "Expected row, column, and value\n"); err = 1; } + } else if(!strcmp(opt, "remove")) { + if(argc - i != 0) { + args.remove = 1; + err = zsv_overwrite_parse_pos(&overwrite, argv[++i]); + if(err) { + fprintf(stderr, "Expected row and column\n"); + } + } else { + fprintf(stderr, "Expected row and column\n"); + err = 1; + } } else { err = 1; if (*opt == '-') @@ -487,6 +500,8 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op zsv_overwrites_clear(&ctx); else if (!err && args.add && ctx.sqlite3.db) zsv_overwrites_insert(&ctx, &overwrite, &args); + else if(args.remove && ctx.sqlite3.db) + zsv_overwrites_remove(&ctx, &overwrite); zsv_overwrites_free(&ctx, &overwrite, writer); From 90c4683d442ba17c90eba622415486bfa34a4161 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Mon, 11 Nov 2024 21:38:37 -0500 Subject: [PATCH 06/62] Implement --old-value flag --- app/overwrite.c | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 11c1d8df..c6e9f450 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -32,6 +32,7 @@ struct zsv_overwrite_args { unsigned char force : 1; unsigned char a1 : 1; unsigned char timestamp : 1; + unsigned char *old_value; // commands unsigned char list : 1; unsigned char clear : 1; @@ -201,21 +202,29 @@ static int zsv_overwrites_remove(struct zsv_overwrite_ctx *ctx, struct zsv_overw return err; } -static int zsv_overwrites_check_value(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite) { +static sqlite3_stmt *zsv_overwrites_check_value(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite) { sqlite3_stmt *query; if (sqlite3_prepare_v2(ctx->sqlite3.db, - "SELECT 1 FROM overwrites WHERE row = ? AND column = ?", -1, + "SELECT value FROM overwrites WHERE row = ? AND column = ?", -1, &query, NULL) != SQLITE_OK) { fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); - return 1; + return NULL; } sqlite3_bind_int64(query, 1, overwrite->row_ix); sqlite3_bind_int64(query, 2, overwrite->col_ix); if(sqlite3_step(query) == SQLITE_ROW) { + return query; // value exists + } + return NULL; // value does not exist +} + +static int zsv_overwrites_has_value(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite) { + sqlite3_stmt *query = zsv_overwrites_check_value(ctx, overwrite); + if(query) { if(query) sqlite3_finalize(query); - return 1; // value exists + return 1; } - return 0; // value does not exist + return 0; } static int zsv_overwrites_replace(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, const struct zsv_overwrite_args *args) { @@ -241,14 +250,31 @@ static int zsv_overwrites_replace(struct zsv_overwrite_ctx *ctx, struct zsv_over return 0; } +static int zsv_overwrites_compare(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, const struct zsv_overwrite_args *args) { + sqlite3_stmt *query = zsv_overwrites_check_value(ctx, overwrite); + if(query) { + const unsigned char *text = sqlite3_column_text(query, 0); + if(text) + return strcmp((const char*)text, (const char*)args->old_value); + sqlite3_finalize(query); + } + return 1; // Value doesn't exist +} + static int zsv_overwrites_insert(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, const struct zsv_overwrite_args *args) { - if(args->force && zsv_overwrites_check_value(ctx, overwrite)) + if(args->force && zsv_overwrites_has_value(ctx, overwrite)) return zsv_overwrites_replace(ctx, overwrite, args); int err = 0; sqlite3_stmt *query = NULL; + if(args->old_value && (err = zsv_overwrites_compare(ctx, overwrite, args))) { + return err; + } else { + return zsv_overwrites_replace(ctx, overwrite, args); + } + if (sqlite3_prepare_v2(ctx->sqlite3.db, "INSERT INTO overwrites (row, column, value, timestamp, author) VALUES (?, ?, ?, ?, ?)", -1, &query, NULL) == SQLITE_OK) { @@ -442,8 +468,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op if (!strcmp(opt, "-f") || !strcmp(opt, "--force")) { args.force = 1; } else if (!strcmp(opt, "--old-value")) { - fprintf(stderr, "Error: %s is not implemented\n", opt); - err = 1; + args.old_value = (unsigned char*)argv[++i]; } else if (!strcmp(opt, "--no-timestamp")) { args.timestamp = 0; } else if (!strcmp(opt, "--A1")) { From 27c8cf3ded12cd2dba1825fb2a3cff68c07aab0d Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Tue, 12 Nov 2024 15:03:26 -0500 Subject: [PATCH 07/62] format --- app/overwrite.c | 55 +++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index c6e9f450..04ffab4c 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -116,8 +116,8 @@ static int zsv_overwrites_init(struct zsv_overwrite_ctx *ctx, struct zsv_overwri } */ - if (sqlite3_open_v2(overwrites_fn, &ctx->sqlite3.db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK || args->add || args->remove || - args->clear) { + if (sqlite3_open_v2(overwrites_fn, &ctx->sqlite3.db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK || args->add || + args->remove || args->clear) { sqlite3_close(ctx->sqlite3.db); if (sqlite3_open_v2(overwrites_fn, &ctx->sqlite3.db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != SQLITE_OK) { @@ -182,9 +182,8 @@ static int zsv_overwrites_clear(struct zsv_overwrite_ctx *ctx) { static int zsv_overwrites_remove(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite) { int err = 0; sqlite3_stmt *query = NULL; - if (sqlite3_prepare_v2(ctx->sqlite3.db, - "DELETE FROM overwrites WHERE row = ? AND column = ?", -1, - &query, NULL) != SQLITE_OK) { + if (sqlite3_prepare_v2(ctx->sqlite3.db, "DELETE FROM overwrites WHERE row = ? AND column = ?", -1, &query, NULL) != + SQLITE_OK) { err = 1; fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); return err; @@ -197,22 +196,21 @@ static int zsv_overwrites_remove(struct zsv_overwrite_ctx *ctx, struct zsv_overw fprintf(stderr, "Could not step: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); return err; } - if(query) + if (query) sqlite3_finalize(query); return err; } static sqlite3_stmt *zsv_overwrites_check_value(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite) { sqlite3_stmt *query; - if (sqlite3_prepare_v2(ctx->sqlite3.db, - "SELECT value FROM overwrites WHERE row = ? AND column = ?", -1, - &query, NULL) != SQLITE_OK) { + if (sqlite3_prepare_v2(ctx->sqlite3.db, "SELECT value FROM overwrites WHERE row = ? AND column = ?", -1, &query, + NULL) != SQLITE_OK) { fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); return NULL; } sqlite3_bind_int64(query, 1, overwrite->row_ix); sqlite3_bind_int64(query, 2, overwrite->col_ix); - if(sqlite3_step(query) == SQLITE_ROW) { + if (sqlite3_step(query) == SQLITE_ROW) { return query; // value exists } return NULL; // value does not exist @@ -220,14 +218,16 @@ static sqlite3_stmt *zsv_overwrites_check_value(struct zsv_overwrite_ctx *ctx, s static int zsv_overwrites_has_value(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite) { sqlite3_stmt *query = zsv_overwrites_check_value(ctx, overwrite); - if(query) { - if(query) sqlite3_finalize(query); + if (query) { + if (query) + sqlite3_finalize(query); return 1; } return 0; } -static int zsv_overwrites_replace(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, const struct zsv_overwrite_args *args) { +static int zsv_overwrites_replace(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, + const struct zsv_overwrite_args *args) { sqlite3_stmt *query = NULL; if (sqlite3_prepare_v2(ctx->sqlite3.db, "UPDATE overwrites SET value = ?, timestamp = ?, author = ? WHERE row = ? AND column = ?", -1, @@ -243,19 +243,20 @@ static int zsv_overwrites_replace(struct zsv_overwrite_ctx *ctx, struct zsv_over sqlite3_bind_text(query, 3, "", -1, SQLITE_STATIC); // author sqlite3_bind_int64(query, 4, overwrite->row_ix); sqlite3_bind_int64(query, 5, overwrite->col_ix); - if(sqlite3_step(query) != SQLITE_DONE) { + if (sqlite3_step(query) != SQLITE_DONE) { fprintf(stderr, "Could not step: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); - return 1; + return 1; } return 0; } -static int zsv_overwrites_compare(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, const struct zsv_overwrite_args *args) { +static int zsv_overwrites_compare(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, + const struct zsv_overwrite_args *args) { sqlite3_stmt *query = zsv_overwrites_check_value(ctx, overwrite); - if(query) { + if (query) { const unsigned char *text = sqlite3_column_text(query, 0); - if(text) - return strcmp((const char*)text, (const char*)args->old_value); + if (text) + return strcmp((const char *)text, (const char *)args->old_value); sqlite3_finalize(query); } return 1; // Value doesn't exist @@ -263,13 +264,13 @@ static int zsv_overwrites_compare(struct zsv_overwrite_ctx *ctx, struct zsv_over static int zsv_overwrites_insert(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, const struct zsv_overwrite_args *args) { - if(args->force && zsv_overwrites_has_value(ctx, overwrite)) + if (args->force && zsv_overwrites_has_value(ctx, overwrite)) return zsv_overwrites_replace(ctx, overwrite, args); int err = 0; sqlite3_stmt *query = NULL; - if(args->old_value && (err = zsv_overwrites_compare(ctx, overwrite, args))) { + if (args->old_value && (err = zsv_overwrites_compare(ctx, overwrite, args))) { return err; } else { return zsv_overwrites_replace(ctx, overwrite, args); @@ -368,7 +369,7 @@ static int show_all_overwrites(struct zsv_overwrite_ctx *ctx, const struct zsv_o const unsigned char *author = sqlite3_column_text(stmt, 4); size_t author_len = sqlite3_column_bytes(stmt, 4); if (args->a1) { - char *col_a1 = row_col_to_a1(col+1, row); // add one to display the correct letter + char *col_a1 = row_col_to_a1(col + 1, row); // add one to display the correct letter if (!col_a1) { err = 1; fprintf(stderr, "Error converting column number to A1-notation\n"); @@ -468,7 +469,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op if (!strcmp(opt, "-f") || !strcmp(opt, "--force")) { args.force = 1; } else if (!strcmp(opt, "--old-value")) { - args.old_value = (unsigned char*)argv[++i]; + args.old_value = (unsigned char *)argv[++i]; } else if (!strcmp(opt, "--no-timestamp")) { args.timestamp = 0; } else if (!strcmp(opt, "--A1")) { @@ -491,11 +492,11 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op fprintf(stderr, "Expected row, column, and value\n"); err = 1; } - } else if(!strcmp(opt, "remove")) { - if(argc - i != 0) { + } else if (!strcmp(opt, "remove")) { + if (argc - i != 0) { args.remove = 1; err = zsv_overwrite_parse_pos(&overwrite, argv[++i]); - if(err) { + if (err) { fprintf(stderr, "Expected row and column\n"); } } else { @@ -525,7 +526,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op zsv_overwrites_clear(&ctx); else if (!err && args.add && ctx.sqlite3.db) zsv_overwrites_insert(&ctx, &overwrite, &args); - else if(args.remove && ctx.sqlite3.db) + else if (args.remove && ctx.sqlite3.db) zsv_overwrites_remove(&ctx, &overwrite); zsv_overwrites_free(&ctx, &overwrite, writer); From 2e53096e12afa249ba4d9b714d760f6b7c82ccba Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Tue, 12 Nov 2024 15:13:38 -0500 Subject: [PATCH 08/62] Fix issue with add --- app/overwrite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/overwrite.c b/app/overwrite.c index 04ffab4c..e753b93c 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -272,7 +272,7 @@ static int zsv_overwrites_insert(struct zsv_overwrite_ctx *ctx, struct zsv_overw if (args->old_value && (err = zsv_overwrites_compare(ctx, overwrite, args))) { return err; - } else { + } else if(args->old_value) { return zsv_overwrites_replace(ctx, overwrite, args); } From 02e1f56760320c53c41f969e79bd5a784a85884b Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Tue, 12 Nov 2024 15:57:06 -0500 Subject: [PATCH 09/62] Add --old-value support in remove --- app/overwrite.c | 62 ++++++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index e753b93c..0cf76000 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -179,8 +179,39 @@ static int zsv_overwrites_clear(struct zsv_overwrite_ctx *ctx) { return err; } -static int zsv_overwrites_remove(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite) { +static sqlite3_stmt *zsv_overwrites_check_value(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite) { + sqlite3_stmt *query; + if (sqlite3_prepare_v2(ctx->sqlite3.db, "SELECT value FROM overwrites WHERE row = ? AND column = ?", -1, &query, + NULL) != SQLITE_OK) { + fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); + return NULL; + } + sqlite3_bind_int64(query, 1, overwrite->row_ix); + sqlite3_bind_int64(query, 2, overwrite->col_ix); + if (sqlite3_step(query) == SQLITE_ROW) { + return query; // value exists + } + return NULL; // value does not exist +} + +static int zsv_overwrites_compare(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, + const struct zsv_overwrite_args *args) { + sqlite3_stmt *query = zsv_overwrites_check_value(ctx, overwrite); + if (query) { + const unsigned char *text = sqlite3_column_text(query, 0); + if (text) + return strcmp((const char *)text, (const char *)args->old_value); + sqlite3_finalize(query); + } + return 1; // Value doesn't exist +} + +static int zsv_overwrites_remove(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, struct zsv_overwrite_args *args) { int err = 0; + if(args->old_value && zsv_overwrites_compare(ctx, overwrite, args)) { + err = 1; + return err; // value does not match + } sqlite3_stmt *query = NULL; if (sqlite3_prepare_v2(ctx->sqlite3.db, "DELETE FROM overwrites WHERE row = ? AND column = ?", -1, &query, NULL) != SQLITE_OK) { @@ -201,21 +232,6 @@ static int zsv_overwrites_remove(struct zsv_overwrite_ctx *ctx, struct zsv_overw return err; } -static sqlite3_stmt *zsv_overwrites_check_value(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite) { - sqlite3_stmt *query; - if (sqlite3_prepare_v2(ctx->sqlite3.db, "SELECT value FROM overwrites WHERE row = ? AND column = ?", -1, &query, - NULL) != SQLITE_OK) { - fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); - return NULL; - } - sqlite3_bind_int64(query, 1, overwrite->row_ix); - sqlite3_bind_int64(query, 2, overwrite->col_ix); - if (sqlite3_step(query) == SQLITE_ROW) { - return query; // value exists - } - return NULL; // value does not exist -} - static int zsv_overwrites_has_value(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite) { sqlite3_stmt *query = zsv_overwrites_check_value(ctx, overwrite); if (query) { @@ -250,18 +266,6 @@ static int zsv_overwrites_replace(struct zsv_overwrite_ctx *ctx, struct zsv_over return 0; } -static int zsv_overwrites_compare(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, - const struct zsv_overwrite_args *args) { - sqlite3_stmt *query = zsv_overwrites_check_value(ctx, overwrite); - if (query) { - const unsigned char *text = sqlite3_column_text(query, 0); - if (text) - return strcmp((const char *)text, (const char *)args->old_value); - sqlite3_finalize(query); - } - return 1; // Value doesn't exist -} - static int zsv_overwrites_insert(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, const struct zsv_overwrite_args *args) { if (args->force && zsv_overwrites_has_value(ctx, overwrite)) @@ -527,7 +531,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op else if (!err && args.add && ctx.sqlite3.db) zsv_overwrites_insert(&ctx, &overwrite, &args); else if (args.remove && ctx.sqlite3.db) - zsv_overwrites_remove(&ctx, &overwrite); + zsv_overwrites_remove(&ctx, &overwrite, &args); zsv_overwrites_free(&ctx, &overwrite, writer); From 9efbf90e2f62f3e5b1bff252e94456dfd58d23f0 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Tue, 12 Nov 2024 16:14:31 -0500 Subject: [PATCH 10/62] Add tests for the new features --- app/test/overwrite/Makefile | 45 ++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/app/test/overwrite/Makefile b/app/test/overwrite/Makefile index 0fb21708..412ffa01 100644 --- a/app/test/overwrite/Makefile +++ b/app/test/overwrite/Makefile @@ -40,7 +40,7 @@ ifeq ($(EXE),) $(error EXE is not defined) endif -test: test-1 test-2 test-excel-cells test-add test-echo-overwrite-auto test-timestamp +test: test-1 test-2 test-excel-cells test-add test-remove test-old-value test-force test-echo-overwrite-auto test-timestamp test-1: @${TEST_INIT} @@ -74,6 +74,49 @@ test-add: @${PREFIX} ${ECHO_EXE} --overwrite-auto dummy2.csv > ${TMP_DIR}/$@.out @${CMP} ${TMP_DIR}/$@.out expected/$@.out && ${TEST_PASS} || ${TEST_FAIL} +test-remove: + @${TEST_INIT} + @${PREFIX} ${EXE} dummy2.csv clear + @${PREFIX} ${EXE} dummy2.csv add 1-1 V1 --no-timestamp + @${PREFIX} ${EXE} dummy2.csv add 2-1 V2 --no-timestamp + @${PREFIX} ${EXE} dummy2.csv add 3-1 V3 --no-timestamp + @${PREFIX} ${EXE} dummy2.csv add 4-1 V4 --no-timestamp + @${PREFIX} ${EXE} dummy2.csv remove 2-1 + @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,V1,,\n3,1,V3,,\n4,1,V4,,\n\"`" ] \ + && ${TEST_PASS} || ${TEST_FAIL} + @${PREFIX} ${EXE} dummy2.csv remove 4-1 + @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,V1,,\n3,1,V3,,\n\"`" ] \ + && ${TEST_PASS} || ${TEST_FAIL} + +test-old-value: + @${TEST_INIT} + @${PREFIX} ${EXE} dummy2.csv clear + @${PREFIX} ${EXE} dummy2.csv add 1-1 V1 --no-timestamp + @${PREFIX} ${EXE} dummy2.csv add 2-1 V2 --no-timestamp + @${PREFIX} ${EXE} dummy2.csv add 3-1 V3 --no-timestamp + @${PREFIX} ${EXE} dummy2.csv add 4-1 V4 --no-timestamp + @${PREFIX} ${EXE} dummy2.csv remove 2-1 --old-value V3 + @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,V1,,\n2,1,V2,,\n3,1,V3,,\n4,1,V4,,\n\"`" ] \ + && ${TEST_PASS} || ${TEST_FAIL} + @${PREFIX} ${EXE} dummy2.csv add 2-1 NEW_V2 --old-value V2 --no-timestamp + @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,V1,,\n2,1,NEW_V2,,\n3,1,V3,,\n4,1,V4,,\n\"`" ] \ + && ${TEST_PASS} || ${TEST_FAIL} + @${PREFIX} ${EXE} dummy2.csv remove 3-1 --old-value V3 + @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,V1,,\n2,1,NEW_V2,,\n4,1,V4,,\n\"`" ] \ + && ${TEST_PASS} || ${TEST_FAIL} + +test-force: + @${TEST_INIT} + @${PREFIX} ${EXE} dummy2.csv clear + @${PREFIX} ${EXE} dummy2.csv add 1-2 VAL1 --no-timestamp + @${PREFIX} ${EXE} dummy2.csv add 2-2 VAL2 --no-timestamp + @${PREFIX} ${EXE} dummy2.csv add 2-3 VAL3 --no-timestamp + @${PREFIX} ${EXE} dummy2.csv add 2-4 VAL4 --no-timestamp + @${PREFIX} ${EXE} dummy2.csv add 2-4 NEW_VAL4 --no-timestamp --force + @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,2,VAL1,,\n2,2,VAL2,,\n2,3,VAL3,,\n2,4,NEW_VAL4,,\n\"`" ] \ + && ${TEST_PASS} || ${TEST_FAIL} + + STAT_MOD_TS=$(shell if stat -c %Y Makefile >/dev/null 2>/dev/null; then echo 'stat -c %Y' ; else echo 'stat -f %m' ; fi) test-timestamp: @${TEST_INIT} From bdd7f21f9a9e48d2b33ddeaaa6aaa070e9dd10ab Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Tue, 12 Nov 2024 22:09:36 -0500 Subject: [PATCH 11/62] Implement start of bulk operations. Not finished yet --- app/overwrite.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/app/overwrite.c b/app/overwrite.c index 0cf76000..2f6cd762 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -28,10 +28,13 @@ struct zsv_overwrite_args { char *filepath; + struct zsv_opts *opts; // options unsigned char force : 1; unsigned char a1 : 1; unsigned char timestamp : 1; + unsigned char bulk_add: 1; + unsigned char bulk_remove: 1; unsigned char *old_value; // commands unsigned char list : 1; @@ -308,6 +311,34 @@ static int zsv_overwrites_insert(struct zsv_overwrite_ctx *ctx, struct zsv_overw return err; } +static void zsv_overwrites_bulk_add(void *ctx_v) { + struct zsv_overwrite_ctx *ctx = (struct zsv_overwrite_ctx*)ctx_v; + if(zsv_row_is_blank(ctx->csv.parser)) + return; + struct zsv_overwrite_data overwrite = {0}; + size_t c_count = zsv_cell_count(ctx->csv.parser); + if(c_count > 3) { + fprintf(stderr, "Author and timestamp rows are not supported yet\n"); + } + for (size_t i = 0; i < c_count; i++) { + struct zsv_cell cell = zsv_get_cell(ctx->csv.parser, i); + if(cell.len > 0 && !strncmp((const char*)cell.str, "row", cell.len)) { + printf("Skipping header\n"); + return; + } + if(!overwrite.row_ix) + overwrite.row_ix = atol((const char*)cell.str); + else if(!overwrite.col_ix) + overwrite.col_ix = atol((const char*)cell.str); + else if(!overwrite.val.str) { + overwrite.val.str = cell.str; + overwrite.val.len = cell.len; + } + } + struct zsv_overwrite_args args = {0}; + zsv_overwrites_insert(ctx, &overwrite, &args); +} + static int zsv_overwrites_free(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, zsv_csv_writer writer) { if (writer) @@ -497,7 +528,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op err = 1; } } else if (!strcmp(opt, "remove")) { - if (argc - i != 0) { + if (argc - i > 1) { args.remove = 1; err = zsv_overwrite_parse_pos(&overwrite, argv[++i]); if (err) { @@ -507,6 +538,14 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op fprintf(stderr, "Expected row and column\n"); err = 1; } + } else if(!strcmp(opt, "bulk-add")) { + if(argc - i > 1) { + args.bulk_add = 1; + ctx.csv.f = fopen((const char*)argv[++i], "rb"); + } else { + fprintf(stderr, "Expected row and column\n"); + err = 1; + } } else { err = 1; if (*opt == '-') @@ -532,6 +571,13 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op zsv_overwrites_insert(&ctx, &overwrite, &args); else if (args.remove && ctx.sqlite3.db) zsv_overwrites_remove(&ctx, &overwrite, &args); + else if ((args.bulk_add || args.bulk_remove) && ctx.sqlite3.db) { + opts->row_handler = zsv_overwrites_bulk_add; + opts->ctx = &ctx; + opts->stream = ctx.csv.f; + ctx.csv.parser = zsv_new(opts); + while(zsv_parse_more(ctx.csv.parser) == zsv_status_ok); + } zsv_overwrites_free(&ctx, &overwrite, writer); From 572e3dad45c8458eaa1198e450657af1a09ce153 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Wed, 13 Nov 2024 20:33:29 -0500 Subject: [PATCH 12/62] Fix issue with bulk-add cell length not being checked --- app/overwrite.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 2f6cd762..8c4f350c 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -119,7 +119,7 @@ static int zsv_overwrites_init(struct zsv_overwrite_ctx *ctx, struct zsv_overwri } */ - if (sqlite3_open_v2(overwrites_fn, &ctx->sqlite3.db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK || args->add || + if (sqlite3_open_v2(overwrites_fn, &ctx->sqlite3.db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK || args->add || args->bulk_add || args->bulk_remove || args->remove || args->clear) { sqlite3_close(ctx->sqlite3.db); if (sqlite3_open_v2(overwrites_fn, &ctx->sqlite3.db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != @@ -271,6 +271,8 @@ static int zsv_overwrites_replace(struct zsv_overwrite_ctx *ctx, struct zsv_over static int zsv_overwrites_insert(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, const struct zsv_overwrite_args *args) { + if(!overwrite->val.str) + return 1; if (args->force && zsv_overwrites_has_value(ctx, overwrite)) return zsv_overwrites_replace(ctx, overwrite, args); @@ -317,13 +319,9 @@ static void zsv_overwrites_bulk_add(void *ctx_v) { return; struct zsv_overwrite_data overwrite = {0}; size_t c_count = zsv_cell_count(ctx->csv.parser); - if(c_count > 3) { - fprintf(stderr, "Author and timestamp rows are not supported yet\n"); - } for (size_t i = 0; i < c_count; i++) { struct zsv_cell cell = zsv_get_cell(ctx->csv.parser, i); if(cell.len > 0 && !strncmp((const char*)cell.str, "row", cell.len)) { - printf("Skipping header\n"); return; } if(!overwrite.row_ix) @@ -331,11 +329,16 @@ static void zsv_overwrites_bulk_add(void *ctx_v) { else if(!overwrite.col_ix) overwrite.col_ix = atol((const char*)cell.str); else if(!overwrite.val.str) { - overwrite.val.str = cell.str; + if(cell.len == 0 || !cell.str) + return; + overwrite.val.str = (unsigned char*)strndup((const char*)cell.str, cell.len); overwrite.val.len = cell.len; } } + if(!overwrite.row_ix || !overwrite.col_ix || !overwrite.val.str) + return; // cannot continue without a proper row, col, value overwrite struct zsv_overwrite_args args = {0}; + args.timestamp = 1; zsv_overwrites_insert(ctx, &overwrite, &args); } From 36715599798ba94bd3a70e84d7df9f416392856a Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Wed, 13 Nov 2024 20:43:39 -0500 Subject: [PATCH 13/62] Add timestamp and author support to bulk-add --- app/overwrite.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 8c4f350c..23cbbf5a 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -32,10 +32,11 @@ struct zsv_overwrite_args { // options unsigned char force : 1; unsigned char a1 : 1; - unsigned char timestamp : 1; unsigned char bulk_add: 1; unsigned char bulk_remove: 1; unsigned char *old_value; + unsigned char *author; + size_t timestamp; // commands unsigned char list : 1; unsigned char clear : 1; @@ -292,10 +293,13 @@ static int zsv_overwrites_insert(struct zsv_overwrite_ctx *ctx, struct zsv_overw sqlite3_bind_int64(query, 2, overwrite->col_ix); sqlite3_bind_text(query, 3, (const char *)overwrite->val.str, -1, SQLITE_STATIC); if (args->timestamp) - sqlite3_bind_int64(query, 4, time(NULL)); + sqlite3_bind_int64(query, 4, args->timestamp); else sqlite3_bind_null(query, 4); - sqlite3_bind_text(query, 5, "", -1, SQLITE_STATIC); // author + if(args->author) + sqlite3_bind_text(query, 5, (const char*)args->author, -1, SQLITE_STATIC); + else + sqlite3_bind_text(query, 5, "", -1, SQLITE_STATIC); if (sqlite3_step(query) != SQLITE_DONE) { err = 1; fprintf(stderr, "Value already exists at row %zu and column %zu, use --force to force insert\n", @@ -318,10 +322,14 @@ static void zsv_overwrites_bulk_add(void *ctx_v) { if(zsv_row_is_blank(ctx->csv.parser)) return; struct zsv_overwrite_data overwrite = {0}; + struct zsv_overwrite_args args = {0}; + args.timestamp = 0; size_t c_count = zsv_cell_count(ctx->csv.parser); for (size_t i = 0; i < c_count; i++) { struct zsv_cell cell = zsv_get_cell(ctx->csv.parser, i); - if(cell.len > 0 && !strncmp((const char*)cell.str, "row", cell.len)) { + if(cell.len == 0 || !cell.str) + continue; + if(!strncmp((const char*)cell.str, "row", cell.len)) { return; } if(!overwrite.row_ix) @@ -329,16 +337,16 @@ static void zsv_overwrites_bulk_add(void *ctx_v) { else if(!overwrite.col_ix) overwrite.col_ix = atol((const char*)cell.str); else if(!overwrite.val.str) { - if(cell.len == 0 || !cell.str) - return; overwrite.val.str = (unsigned char*)strndup((const char*)cell.str, cell.len); overwrite.val.len = cell.len; + } else if(!args.timestamp) { + args.timestamp = (size_t)atol((const char*)cell.str); + } else if(!args.author) { + args.author = (unsigned char*)strndup((const char*)cell.str, cell.len); } } if(!overwrite.row_ix || !overwrite.col_ix || !overwrite.val.str) return; // cannot continue without a proper row, col, value overwrite - struct zsv_overwrite_args args = {0}; - args.timestamp = 1; zsv_overwrites_insert(ctx, &overwrite, &args); } @@ -495,7 +503,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op struct zsv_overwrite_ctx ctx = {0}; struct zsv_overwrite_args args = {0}; // By default, save timestamps - args.timestamp = 1; + args.timestamp = (size_t)time(NULL); struct zsv_overwrite_data overwrite = {0}; struct zsv_csv_writer_options writer_opts = {0}; From b68c78ca5385d433901ab596916e21a303e81ed9 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Wed, 13 Nov 2024 20:58:08 -0500 Subject: [PATCH 14/62] Fix some issues and memory leak --- app/overwrite.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 23cbbf5a..a1c651df 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -304,7 +304,6 @@ static int zsv_overwrites_insert(struct zsv_overwrite_ctx *ctx, struct zsv_overw err = 1; fprintf(stderr, "Value already exists at row %zu and column %zu, use --force to force insert\n", overwrite->row_ix, overwrite->col_ix); - return err; } } else { err = 1; @@ -348,6 +347,10 @@ static void zsv_overwrites_bulk_add(void *ctx_v) { if(!overwrite.row_ix || !overwrite.col_ix || !overwrite.val.str) return; // cannot continue without a proper row, col, value overwrite zsv_overwrites_insert(ctx, &overwrite, &args); + if(overwrite.val.str) + free(overwrite.val.str); + if(args.author) + free(args.author); } static int zsv_overwrites_free(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, @@ -553,6 +556,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op if(argc - i > 1) { args.bulk_add = 1; ctx.csv.f = fopen((const char*)argv[++i], "rb"); + opts->row_handler = zsv_overwrites_bulk_add; } else { fprintf(stderr, "Expected row and column\n"); err = 1; @@ -583,11 +587,13 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op else if (args.remove && ctx.sqlite3.db) zsv_overwrites_remove(&ctx, &overwrite, &args); else if ((args.bulk_add || args.bulk_remove) && ctx.sqlite3.db) { - opts->row_handler = zsv_overwrites_bulk_add; opts->ctx = &ctx; opts->stream = ctx.csv.f; ctx.csv.parser = zsv_new(opts); while(zsv_parse_more(ctx.csv.parser) == zsv_status_ok); + zsv_finish(ctx.csv.parser); + zsv_delete(ctx.csv.parser); + fclose(ctx.csv.f); } zsv_overwrites_free(&ctx, &overwrite, writer); From 07a2ff8ba56a2bd8ef456ed470bc3f0d0fafdb9c Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Wed, 13 Nov 2024 21:55:11 -0500 Subject: [PATCH 15/62] Implement bulk-remove functionality. Needs some polish and tests --- app/overwrite.c | 67 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 20 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index a1c651df..56998bf9 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -316,13 +316,8 @@ static int zsv_overwrites_insert(struct zsv_overwrite_ctx *ctx, struct zsv_overw return err; } -static void zsv_overwrites_bulk_add(void *ctx_v) { - struct zsv_overwrite_ctx *ctx = (struct zsv_overwrite_ctx*)ctx_v; - if(zsv_row_is_blank(ctx->csv.parser)) - return; - struct zsv_overwrite_data overwrite = {0}; - struct zsv_overwrite_args args = {0}; - args.timestamp = 0; +static void zsv_overwrites_bulk(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, struct zsv_overwrite_args *args) { + args->timestamp = 0; size_t c_count = zsv_cell_count(ctx->csv.parser); for (size_t i = 0; i < c_count; i++) { struct zsv_cell cell = zsv_get_cell(ctx->csv.parser, i); @@ -331,21 +326,30 @@ static void zsv_overwrites_bulk_add(void *ctx_v) { if(!strncmp((const char*)cell.str, "row", cell.len)) { return; } - if(!overwrite.row_ix) - overwrite.row_ix = atol((const char*)cell.str); - else if(!overwrite.col_ix) - overwrite.col_ix = atol((const char*)cell.str); - else if(!overwrite.val.str) { - overwrite.val.str = (unsigned char*)strndup((const char*)cell.str, cell.len); - overwrite.val.len = cell.len; - } else if(!args.timestamp) { - args.timestamp = (size_t)atol((const char*)cell.str); - } else if(!args.author) { - args.author = (unsigned char*)strndup((const char*)cell.str, cell.len); + if(!overwrite->row_ix) + overwrite->row_ix = atol((const char*)cell.str); + else if(!overwrite->col_ix) + overwrite->col_ix = atol((const char*)cell.str); + else if(!overwrite->val.str) { + overwrite->val.str = (unsigned char*)strndup((const char*)cell.str, cell.len); + overwrite->val.len = cell.len; + } else if(!args->timestamp) { + args->timestamp = (size_t)atol((const char*)cell.str); + } else if(!args->author) { + args->author = (unsigned char*)strndup((const char*)cell.str, cell.len); } } - if(!overwrite.row_ix || !overwrite.col_ix || !overwrite.val.str) + if(!overwrite->row_ix || !overwrite->col_ix || !overwrite->val.str) return; // cannot continue without a proper row, col, value overwrite +} + +static void zsv_overwrites_bulk_add(void *ctx_v) { + struct zsv_overwrite_ctx *ctx = (struct zsv_overwrite_ctx*)ctx_v; + if(zsv_row_is_blank(ctx->csv.parser)) + return; + struct zsv_overwrite_data overwrite = {0}; + struct zsv_overwrite_args args = {0}; + zsv_overwrites_bulk(ctx, &overwrite, &args); zsv_overwrites_insert(ctx, &overwrite, &args); if(overwrite.val.str) free(overwrite.val.str); @@ -353,6 +357,20 @@ static void zsv_overwrites_bulk_add(void *ctx_v) { free(args.author); } +static void zsv_overwrites_bulk_remove(void *ctx_v) { + struct zsv_overwrite_ctx *ctx = (struct zsv_overwrite_ctx*)ctx_v; + if(zsv_row_is_blank(ctx->csv.parser)) + return; + struct zsv_overwrite_data overwrite = {0}; + struct zsv_overwrite_args args = {0}; + zsv_overwrites_bulk(ctx, &overwrite, &args); + zsv_overwrites_remove(ctx, &overwrite, &args); + if(overwrite.val.str) + free(overwrite.val.str); + if(args.author) + free(args.author); +} + static int zsv_overwrites_free(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, zsv_csv_writer writer) { if (writer) @@ -558,7 +576,16 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op ctx.csv.f = fopen((const char*)argv[++i], "rb"); opts->row_handler = zsv_overwrites_bulk_add; } else { - fprintf(stderr, "Expected row and column\n"); + fprintf(stderr, "Expected overwrite filename\n"); + err = 1; + } + } else if(!strcmp(opt, "bulk-remove")) { + if(argc - i > 1) { + args.bulk_remove = 1; + ctx.csv.f = fopen((const char*)argv[++i], "rb"); + opts->row_handler = zsv_overwrites_bulk_remove; + } else { + fprintf(stderr, "Expected overwrite filename\n"); err = 1; } } else { From 771ac7a4d3a504fe2ea1e2b132fe6ead7d320df5 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Wed, 13 Nov 2024 22:14:59 -0500 Subject: [PATCH 16/62] Add row and start of header parsing --- app/overwrite.c | 87 ++++++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 41 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 56998bf9..ad249e67 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -32,8 +32,8 @@ struct zsv_overwrite_args { // options unsigned char force : 1; unsigned char a1 : 1; - unsigned char bulk_add: 1; - unsigned char bulk_remove: 1; + unsigned char bulk_add : 1; + unsigned char bulk_remove : 1; unsigned char *old_value; unsigned char *author; size_t timestamp; @@ -120,8 +120,8 @@ static int zsv_overwrites_init(struct zsv_overwrite_ctx *ctx, struct zsv_overwri } */ - if (sqlite3_open_v2(overwrites_fn, &ctx->sqlite3.db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK || args->add || args->bulk_add || args->bulk_remove || - args->remove || args->clear) { + if (sqlite3_open_v2(overwrites_fn, &ctx->sqlite3.db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK || args->add || + args->bulk_add || args->bulk_remove || args->remove || args->clear) { sqlite3_close(ctx->sqlite3.db); if (sqlite3_open_v2(overwrites_fn, &ctx->sqlite3.db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != SQLITE_OK) { @@ -210,9 +210,10 @@ static int zsv_overwrites_compare(struct zsv_overwrite_ctx *ctx, struct zsv_over return 1; // Value doesn't exist } -static int zsv_overwrites_remove(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, struct zsv_overwrite_args *args) { +static int zsv_overwrites_remove(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, + struct zsv_overwrite_args *args) { int err = 0; - if(args->old_value && zsv_overwrites_compare(ctx, overwrite, args)) { + if (args->old_value && zsv_overwrites_compare(ctx, overwrite, args)) { err = 1; return err; // value does not match } @@ -272,7 +273,7 @@ static int zsv_overwrites_replace(struct zsv_overwrite_ctx *ctx, struct zsv_over static int zsv_overwrites_insert(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, const struct zsv_overwrite_args *args) { - if(!overwrite->val.str) + if (!overwrite->val.str) return 1; if (args->force && zsv_overwrites_has_value(ctx, overwrite)) return zsv_overwrites_replace(ctx, overwrite, args); @@ -282,7 +283,7 @@ static int zsv_overwrites_insert(struct zsv_overwrite_ctx *ctx, struct zsv_overw if (args->old_value && (err = zsv_overwrites_compare(ctx, overwrite, args))) { return err; - } else if(args->old_value) { + } else if (args->old_value) { return zsv_overwrites_replace(ctx, overwrite, args); } @@ -296,8 +297,8 @@ static int zsv_overwrites_insert(struct zsv_overwrite_ctx *ctx, struct zsv_overw sqlite3_bind_int64(query, 4, args->timestamp); else sqlite3_bind_null(query, 4); - if(args->author) - sqlite3_bind_text(query, 5, (const char*)args->author, -1, SQLITE_STATIC); + if (args->author) + sqlite3_bind_text(query, 5, (const char *)args->author, -1, SQLITE_STATIC); else sqlite3_bind_text(query, 5, "", -1, SQLITE_STATIC); if (sqlite3_step(query) != SQLITE_DONE) { @@ -316,58 +317,61 @@ static int zsv_overwrites_insert(struct zsv_overwrite_ctx *ctx, struct zsv_overw return err; } -static void zsv_overwrites_bulk(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, struct zsv_overwrite_args *args) { +static void zsv_overwrites_bulk(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, + struct zsv_overwrite_args *args) { args->timestamp = 0; size_t c_count = zsv_cell_count(ctx->csv.parser); + if (ctx->row_ix == 0) { // header + // TODO: handle header parsing + return; + } for (size_t i = 0; i < c_count; i++) { struct zsv_cell cell = zsv_get_cell(ctx->csv.parser, i); - if(cell.len == 0 || !cell.str) + if (cell.len == 0 || !cell.str) continue; - if(!strncmp((const char*)cell.str, "row", cell.len)) { - return; - } - if(!overwrite->row_ix) - overwrite->row_ix = atol((const char*)cell.str); - else if(!overwrite->col_ix) - overwrite->col_ix = atol((const char*)cell.str); - else if(!overwrite->val.str) { - overwrite->val.str = (unsigned char*)strndup((const char*)cell.str, cell.len); + if (!overwrite->row_ix) + overwrite->row_ix = atol((const char *)cell.str); + else if (!overwrite->col_ix) + overwrite->col_ix = atol((const char *)cell.str); + else if (!overwrite->val.str) { + overwrite->val.str = (unsigned char *)strndup((const char *)cell.str, cell.len); overwrite->val.len = cell.len; - } else if(!args->timestamp) { - args->timestamp = (size_t)atol((const char*)cell.str); - } else if(!args->author) { - args->author = (unsigned char*)strndup((const char*)cell.str, cell.len); + } else if (!args->timestamp) { + args->timestamp = (size_t)atol((const char *)cell.str); + } else if (!args->author) { + args->author = (unsigned char *)strndup((const char *)cell.str, cell.len); } } - if(!overwrite->row_ix || !overwrite->col_ix || !overwrite->val.str) + if (!overwrite->row_ix || !overwrite->col_ix || !overwrite->val.str) return; // cannot continue without a proper row, col, value overwrite + ctx->row_ix++; } static void zsv_overwrites_bulk_add(void *ctx_v) { - struct zsv_overwrite_ctx *ctx = (struct zsv_overwrite_ctx*)ctx_v; - if(zsv_row_is_blank(ctx->csv.parser)) + struct zsv_overwrite_ctx *ctx = (struct zsv_overwrite_ctx *)ctx_v; + if (zsv_row_is_blank(ctx->csv.parser)) return; struct zsv_overwrite_data overwrite = {0}; struct zsv_overwrite_args args = {0}; zsv_overwrites_bulk(ctx, &overwrite, &args); zsv_overwrites_insert(ctx, &overwrite, &args); - if(overwrite.val.str) + if (overwrite.val.str) free(overwrite.val.str); - if(args.author) + if (args.author) free(args.author); } static void zsv_overwrites_bulk_remove(void *ctx_v) { - struct zsv_overwrite_ctx *ctx = (struct zsv_overwrite_ctx*)ctx_v; - if(zsv_row_is_blank(ctx->csv.parser)) + struct zsv_overwrite_ctx *ctx = (struct zsv_overwrite_ctx *)ctx_v; + if (zsv_row_is_blank(ctx->csv.parser)) return; struct zsv_overwrite_data overwrite = {0}; struct zsv_overwrite_args args = {0}; zsv_overwrites_bulk(ctx, &overwrite, &args); zsv_overwrites_remove(ctx, &overwrite, &args); - if(overwrite.val.str) + if (overwrite.val.str) free(overwrite.val.str); - if(args.author) + if (args.author) free(args.author); } @@ -570,19 +574,19 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op fprintf(stderr, "Expected row and column\n"); err = 1; } - } else if(!strcmp(opt, "bulk-add")) { - if(argc - i > 1) { + } else if (!strcmp(opt, "bulk-add")) { + if (argc - i > 1) { args.bulk_add = 1; - ctx.csv.f = fopen((const char*)argv[++i], "rb"); + ctx.csv.f = fopen((const char *)argv[++i], "rb"); opts->row_handler = zsv_overwrites_bulk_add; } else { fprintf(stderr, "Expected overwrite filename\n"); err = 1; } - } else if(!strcmp(opt, "bulk-remove")) { - if(argc - i > 1) { + } else if (!strcmp(opt, "bulk-remove")) { + if (argc - i > 1) { args.bulk_remove = 1; - ctx.csv.f = fopen((const char*)argv[++i], "rb"); + ctx.csv.f = fopen((const char *)argv[++i], "rb"); opts->row_handler = zsv_overwrites_bulk_remove; } else { fprintf(stderr, "Expected overwrite filename\n"); @@ -617,7 +621,8 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op opts->ctx = &ctx; opts->stream = ctx.csv.f; ctx.csv.parser = zsv_new(opts); - while(zsv_parse_more(ctx.csv.parser) == zsv_status_ok); + while (zsv_parse_more(ctx.csv.parser) == zsv_status_ok) + ; zsv_finish(ctx.csv.parser); zsv_delete(ctx.csv.parser); fclose(ctx.csv.f); From d188316780e53d497655b5f6a7233622428b23da Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Thu, 14 Nov 2024 18:17:36 -0500 Subject: [PATCH 17/62] Improve bulk-add and add parsing for the header of overwrite file --- app/overwrite.c | 103 ++++++++++++++++++++++++---------- include/zsv/utils/overwrite.h | 1 + 2 files changed, 75 insertions(+), 29 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index ad249e67..50c19199 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -44,6 +44,19 @@ struct zsv_overwrite_args { unsigned char remove : 1; }; +struct zsv_overwrite { + struct zsv_overwrite_ctx *ctx; + struct zsv_overwrite_args *args; + struct zsv_overwrite_data *overwrite; + // bulk indexes + size_t row_ix; + size_t col_ix; + size_t val_ix; + size_t old_value_ix; + size_t timestamp_ix; + size_t author_ix; +}; + const char *zsv_overwrite_usage_msg[] = { APPNAME " - Manage overwrites associated with a CSV file", "", @@ -317,44 +330,69 @@ static int zsv_overwrites_insert(struct zsv_overwrite_ctx *ctx, struct zsv_overw return err; } -static void zsv_overwrites_bulk(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, - struct zsv_overwrite_args *args) { - args->timestamp = 0; - size_t c_count = zsv_cell_count(ctx->csv.parser); - if (ctx->row_ix == 0) { // header - // TODO: handle header parsing +static void zsv_overwrites_bulk(struct zsv_overwrite *data) { + data->args->timestamp = 0; + size_t c_count = zsv_cell_count(data->ctx->csv.parser); + if (data->ctx->row_ix == 0) { // header + for(size_t i = 0; i < c_count; i++) { + struct zsv_cell cell = zsv_get_cell(data->ctx->csv.parser, i); + if(cell.len == 0 || !cell.str) + continue; + if(!strncmp((const char*)cell.str, "row", cell.len)) + data->row_ix = i; + else if(!strncmp((const char*)cell.str, "col", cell.len)) + data->col_ix = i; + else if(!strncmp((const char*)cell.str, "value", cell.len)) + data->val_ix = i; + else if(!strncmp((const char*)cell.str, "timestamp", cell.len)) + data->timestamp_ix = i; + else if(!strncmp((const char*)cell.str, "old value", cell.len)) + data->old_value_ix = i; + else if(!strncmp((const char*)cell.str, "author", cell.len)) + data->author_ix = i; + else + fprintf(stderr, "Unregonized column %.*s\n", (int)cell.len, cell.str); + } + data->ctx->row_ix++; return; } + for (size_t i = 0; i < c_count; i++) { - struct zsv_cell cell = zsv_get_cell(ctx->csv.parser, i); + struct zsv_cell cell = zsv_get_cell(data->ctx->csv.parser, i); if (cell.len == 0 || !cell.str) continue; - if (!overwrite->row_ix) - overwrite->row_ix = atol((const char *)cell.str); - else if (!overwrite->col_ix) - overwrite->col_ix = atol((const char *)cell.str); - else if (!overwrite->val.str) { - overwrite->val.str = (unsigned char *)strndup((const char *)cell.str, cell.len); - overwrite->val.len = cell.len; - } else if (!args->timestamp) { - args->timestamp = (size_t)atol((const char *)cell.str); - } else if (!args->author) { - args->author = (unsigned char *)strndup((const char *)cell.str, cell.len); + if (i == data->row_ix) + data->overwrite->row_ix = atol((const char *)cell.str); + else if (i == data->col_ix) + data->overwrite->col_ix = atol((const char *)cell.str); + else if (i == data->timestamp_ix) + data->args->timestamp = (size_t)atol((const char *)cell.str); + else if (i == data->author_ix) + data->args->author = (unsigned char *)strndup((const char *)cell.str, cell.len); + else if (i == data->old_value_ix) + data->args->old_value = (unsigned char *)strndup((const char *)cell.str, cell.len); + else if (i == data->val_ix) { + data->overwrite->val.str = (unsigned char *)strndup((const char *)cell.str, cell.len); + data->overwrite->val.len = cell.len; } } - if (!overwrite->row_ix || !overwrite->col_ix || !overwrite->val.str) + if (!data->overwrite->row_ix || !data->overwrite->col_ix || !data->overwrite->val.str) { + printf("Overwrite failed: %zu %zu %zu\n", data->val_ix, data->row_ix, data->col_ix); return; // cannot continue without a proper row, col, value overwrite - ctx->row_ix++; + } + data->ctx->row_ix++; } static void zsv_overwrites_bulk_add(void *ctx_v) { - struct zsv_overwrite_ctx *ctx = (struct zsv_overwrite_ctx *)ctx_v; - if (zsv_row_is_blank(ctx->csv.parser)) + struct zsv_overwrite *data = (struct zsv_overwrite *)ctx_v; + if (zsv_row_is_blank(data->ctx->csv.parser)) return; struct zsv_overwrite_data overwrite = {0}; struct zsv_overwrite_args args = {0}; - zsv_overwrites_bulk(ctx, &overwrite, &args); - zsv_overwrites_insert(ctx, &overwrite, &args); + data->args = &args; + data->overwrite = &overwrite; + zsv_overwrites_bulk(data); + zsv_overwrites_insert(data->ctx, data->overwrite, data->args); if (overwrite.val.str) free(overwrite.val.str); if (args.author) @@ -362,13 +400,15 @@ static void zsv_overwrites_bulk_add(void *ctx_v) { } static void zsv_overwrites_bulk_remove(void *ctx_v) { - struct zsv_overwrite_ctx *ctx = (struct zsv_overwrite_ctx *)ctx_v; - if (zsv_row_is_blank(ctx->csv.parser)) + struct zsv_overwrite *data = (struct zsv_overwrite *)ctx_v; + if (zsv_row_is_blank(data->ctx->csv.parser)) return; struct zsv_overwrite_data overwrite = {0}; struct zsv_overwrite_args args = {0}; - zsv_overwrites_bulk(ctx, &overwrite, &args); - zsv_overwrites_remove(ctx, &overwrite, &args); + data->args = &args; + data->overwrite = &overwrite; + zsv_overwrites_bulk(data); + zsv_overwrites_remove(data->ctx, data->overwrite, data->args); if (overwrite.val.str) free(overwrite.val.str); if (args.author) @@ -601,6 +641,11 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op } } + struct zsv_overwrite data = {0}; + data.ctx = &ctx; + data.args = &args; + data.overwrite = &overwrite; + if (err) return err; @@ -618,7 +663,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op else if (args.remove && ctx.sqlite3.db) zsv_overwrites_remove(&ctx, &overwrite, &args); else if ((args.bulk_add || args.bulk_remove) && ctx.sqlite3.db) { - opts->ctx = &ctx; + opts->ctx = &data; opts->stream = ctx.csv.f; ctx.csv.parser = zsv_new(opts); while (zsv_parse_more(ctx.csv.parser) == zsv_status_ok) diff --git a/include/zsv/utils/overwrite.h b/include/zsv/utils/overwrite.h index 02e6b667..9fe4fa4a 100644 --- a/include/zsv/utils/overwrite.h +++ b/include/zsv/utils/overwrite.h @@ -17,6 +17,7 @@ struct zsv_overwrite_ctx { sqlite3_stmt *stmt; // select row, column, overwrite const char *sql; } sqlite3; + size_t row_ix; }; /** From 34073d737d0b05dfee57235cdaf7c96130cde894 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Thu, 14 Nov 2024 19:25:57 -0500 Subject: [PATCH 18/62] Add test-bulk-add and fix issue with replacement when using bulk-add --- app/overwrite.c | 4 ++-- app/test/overwrite/Makefile | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 50c19199..8d0bc11b 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -271,7 +271,7 @@ static int zsv_overwrites_replace(struct zsv_overwrite_ctx *ctx, struct zsv_over } sqlite3_bind_text(query, 1, (const char *)overwrite->val.str, -1, SQLITE_STATIC); if (args->timestamp) - sqlite3_bind_int64(query, 2, time(NULL)); + sqlite3_bind_int64(query, 2, args->timestamp); else sqlite3_bind_null(query, 2); sqlite3_bind_text(query, 3, "", -1, SQLITE_STATIC); // author @@ -365,7 +365,7 @@ static void zsv_overwrites_bulk(struct zsv_overwrite *data) { data->overwrite->row_ix = atol((const char *)cell.str); else if (i == data->col_ix) data->overwrite->col_ix = atol((const char *)cell.str); - else if (i == data->timestamp_ix) + else if (i == data->timestamp_ix) data->args->timestamp = (size_t)atol((const char *)cell.str); else if (i == data->author_ix) data->args->author = (unsigned char *)strndup((const char *)cell.str, cell.len); diff --git a/app/test/overwrite/Makefile b/app/test/overwrite/Makefile index 412ffa01..ec482076 100644 --- a/app/test/overwrite/Makefile +++ b/app/test/overwrite/Makefile @@ -40,7 +40,7 @@ ifeq ($(EXE),) $(error EXE is not defined) endif -test: test-1 test-2 test-excel-cells test-add test-remove test-old-value test-force test-echo-overwrite-auto test-timestamp +test: test-1 test-2 test-excel-cells test-add test-remove test-old-value test-force test-bulk-add test-echo-overwrite-auto test-timestamp test-1: @${TEST_INIT} @@ -116,6 +116,23 @@ test-force: @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,2,VAL1,,\n2,2,VAL2,,\n2,3,VAL3,,\n2,4,NEW_VAL4,,\n\"`" ] \ && ${TEST_PASS} || ${TEST_FAIL} +test-bulk-add: + @${TEST_INIT} + @${PREFIX} ${EXE} dummy2.csv clear + @${PREFIX} ${EXE} dummy2.csv add 1-1 OLD_V1 --no-timestamp # for old value test + @${PREFIX} ${EXE} dummy2.csv add 2-1 OLD_VAL2 --no-timestamp + @${PREFIX} ${EXE} dummy2.csv bulk-add overwrite.csv + @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,VAL1,1731620001,\n2,1,OLD_VAL2,,\n3,1,VAL3,,\n4,1,VAL4,1731620001,\n\"`" ] \ + && ${TEST_PASS} || ${TEST_FAIL} + +test-bulk-remove: + @${TEST_INIT} + @${PREFIX} ${EXE} dummy2.csv clear + @${PREFIX} ${EXE} dummy2.csv add 1-1 OLD_V1 --no-timestamp # for old value test + @${PREFIX} ${EXE} dummy2.csv add 2-1 OLD_VAL2 --no-timestamp + @${PREFIX} ${EXE} dummy2.csv bulk-remove overwrite.csv + @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,VAL1,1731620001,\n2,1,OLD_VAL2,,\n3,1,VAL3,,\n4,1,VAL4,1731620001,\n\"`" ] \ + && ${TEST_PASS} || ${TEST_FAIL} STAT_MOD_TS=$(shell if stat -c %Y Makefile >/dev/null 2>/dev/null; then echo 'stat -c %Y' ; else echo 'stat -f %m' ; fi) test-timestamp: From 1fb72ab25b1cbea47a109ee24c4b325c4188550a Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Thu, 14 Nov 2024 19:30:03 -0500 Subject: [PATCH 19/62] Add test overwrite file --- app/test/overwrite/overwrite.csv | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 app/test/overwrite/overwrite.csv diff --git a/app/test/overwrite/overwrite.csv b/app/test/overwrite/overwrite.csv new file mode 100644 index 00000000..7acfbf8d --- /dev/null +++ b/app/test/overwrite/overwrite.csv @@ -0,0 +1,5 @@ +row,col,val,timestamp,author,old value +1,1,VAL1,1731620001,,OLD_V1 +2,1,VAL2,1731620001,,V2 +3,1,VAL3,,, +4,1,VAL4,1731620001,, From 1fcdab5d0e181274311a2c296e3de1c5bdefefac Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Thu, 14 Nov 2024 20:02:50 -0500 Subject: [PATCH 20/62] Add bulk-remove test --- app/test/overwrite/Makefile | 7 ++++--- app/test/overwrite/remove.csv | 5 +++++ 2 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 app/test/overwrite/remove.csv diff --git a/app/test/overwrite/Makefile b/app/test/overwrite/Makefile index ec482076..11e58bce 100644 --- a/app/test/overwrite/Makefile +++ b/app/test/overwrite/Makefile @@ -40,7 +40,7 @@ ifeq ($(EXE),) $(error EXE is not defined) endif -test: test-1 test-2 test-excel-cells test-add test-remove test-old-value test-force test-bulk-add test-echo-overwrite-auto test-timestamp +test: test-1 test-2 test-excel-cells test-add test-remove test-old-value test-force test-bulk-add test-bulk-remove test-echo-overwrite-auto test-timestamp test-1: @${TEST_INIT} @@ -130,8 +130,9 @@ test-bulk-remove: @${PREFIX} ${EXE} dummy2.csv clear @${PREFIX} ${EXE} dummy2.csv add 1-1 OLD_V1 --no-timestamp # for old value test @${PREFIX} ${EXE} dummy2.csv add 2-1 OLD_VAL2 --no-timestamp - @${PREFIX} ${EXE} dummy2.csv bulk-remove overwrite.csv - @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,VAL1,1731620001,\n2,1,OLD_VAL2,,\n3,1,VAL3,,\n4,1,VAL4,1731620001,\n\"`" ] \ + @${PREFIX} ${EXE} dummy2.csv bulk-add overwrite.csv + @${PREFIX} ${EXE} dummy2.csv bulk-remove remove.csv + @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n3,1,VAL3,,\n\"`" ] \ && ${TEST_PASS} || ${TEST_FAIL} STAT_MOD_TS=$(shell if stat -c %Y Makefile >/dev/null 2>/dev/null; then echo 'stat -c %Y' ; else echo 'stat -f %m' ; fi) diff --git a/app/test/overwrite/remove.csv b/app/test/overwrite/remove.csv new file mode 100644 index 00000000..c4a418c2 --- /dev/null +++ b/app/test/overwrite/remove.csv @@ -0,0 +1,5 @@ +row,col,val,timestamp,author,old value +1,1,VAL1,,,VAL1 +2,1,VAL2,,,OLD_VAL2 +3,1,VAL3,,,V3 +4,1,VAL4,,, From c0161b5d64f8acbe1a411897bcfc258aae40d743 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Thu, 14 Nov 2024 20:03:04 -0500 Subject: [PATCH 21/62] format --- app/overwrite.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 8d0bc11b..b7c17d1d 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -334,21 +334,21 @@ static void zsv_overwrites_bulk(struct zsv_overwrite *data) { data->args->timestamp = 0; size_t c_count = zsv_cell_count(data->ctx->csv.parser); if (data->ctx->row_ix == 0) { // header - for(size_t i = 0; i < c_count; i++) { + for (size_t i = 0; i < c_count; i++) { struct zsv_cell cell = zsv_get_cell(data->ctx->csv.parser, i); - if(cell.len == 0 || !cell.str) + if (cell.len == 0 || !cell.str) continue; - if(!strncmp((const char*)cell.str, "row", cell.len)) + if (!strncmp((const char *)cell.str, "row", cell.len)) data->row_ix = i; - else if(!strncmp((const char*)cell.str, "col", cell.len)) + else if (!strncmp((const char *)cell.str, "col", cell.len)) data->col_ix = i; - else if(!strncmp((const char*)cell.str, "value", cell.len)) + else if (!strncmp((const char *)cell.str, "value", cell.len)) data->val_ix = i; - else if(!strncmp((const char*)cell.str, "timestamp", cell.len)) + else if (!strncmp((const char *)cell.str, "timestamp", cell.len)) data->timestamp_ix = i; - else if(!strncmp((const char*)cell.str, "old value", cell.len)) + else if (!strncmp((const char *)cell.str, "old value", cell.len)) data->old_value_ix = i; - else if(!strncmp((const char*)cell.str, "author", cell.len)) + else if (!strncmp((const char *)cell.str, "author", cell.len)) data->author_ix = i; else fprintf(stderr, "Unregonized column %.*s\n", (int)cell.len, cell.str); From 9a4259d0f26800a577769594971f29b337d8cb82 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Thu, 14 Nov 2024 20:18:40 -0500 Subject: [PATCH 22/62] Fix cppcheck issues --- app/overwrite.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index b7c17d1d..42167e30 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -28,7 +28,6 @@ struct zsv_overwrite_args { char *filepath; - struct zsv_opts *opts; // options unsigned char force : 1; unsigned char a1 : 1; @@ -224,7 +223,7 @@ static int zsv_overwrites_compare(struct zsv_overwrite_ctx *ctx, struct zsv_over } static int zsv_overwrites_remove(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, - struct zsv_overwrite_args *args) { + const struct zsv_overwrite_args *args) { int err = 0; if (args->old_value && zsv_overwrites_compare(ctx, overwrite, args)) { err = 1; @@ -253,8 +252,7 @@ static int zsv_overwrites_remove(struct zsv_overwrite_ctx *ctx, struct zsv_overw static int zsv_overwrites_has_value(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite) { sqlite3_stmt *query = zsv_overwrites_check_value(ctx, overwrite); if (query) { - if (query) - sqlite3_finalize(query); + sqlite3_finalize(query); return 1; } return 0; @@ -415,7 +413,7 @@ static void zsv_overwrites_bulk_remove(void *ctx_v) { free(args.author); } -static int zsv_overwrites_free(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, +static int zsv_overwrites_free(struct zsv_overwrite *data, struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, zsv_csv_writer writer) { if (writer) zsv_writer_delete(writer); @@ -425,6 +423,8 @@ static int zsv_overwrites_free(struct zsv_overwrite_ctx *ctx, struct zsv_overwri } if (overwrite) free(overwrite->val.str); + if(data) + free(data); // sqlite3_shutdown(); return 0; @@ -641,29 +641,32 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op } } - struct zsv_overwrite data = {0}; - data.ctx = &ctx; - data.args = &args; - data.overwrite = &overwrite; - - if (err) - return err; + struct zsv_overwrite *data = calloc(1, sizeof(struct zsv_overwrite)); + data->ctx = &ctx; + data->args = &args; + data->overwrite = &overwrite; if ((err = zsv_overwrites_init(&ctx, &args))) { fprintf(stderr, "Failed to initalize database\n"); } zsv_csv_writer writer = zsv_writer_new(&writer_opts); + + if (err) { + zsv_overwrites_free(data, &ctx, &overwrite, writer); + return err; + } + if (args.list) show_all_overwrites(&ctx, &args, writer); else if (args.clear) zsv_overwrites_clear(&ctx); - else if (!err && args.add && ctx.sqlite3.db) + else if (args.add && ctx.sqlite3.db) zsv_overwrites_insert(&ctx, &overwrite, &args); else if (args.remove && ctx.sqlite3.db) zsv_overwrites_remove(&ctx, &overwrite, &args); else if ((args.bulk_add || args.bulk_remove) && ctx.sqlite3.db) { - opts->ctx = &data; + opts->ctx = data; opts->stream = ctx.csv.f; ctx.csv.parser = zsv_new(opts); while (zsv_parse_more(ctx.csv.parser) == zsv_status_ok) @@ -673,7 +676,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op fclose(ctx.csv.f); } - zsv_overwrites_free(&ctx, &overwrite, writer); + zsv_overwrites_free(data, &ctx, &overwrite, writer); return err; } From 7213366ca92ed15535ea57cd0cc25bbfc0423386 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Thu, 14 Nov 2024 21:10:09 -0500 Subject: [PATCH 23/62] Fix issues after cppcheck and format --- app/overwrite.c | 170 +++++++++++++++++++++++++----------------------- 1 file changed, 87 insertions(+), 83 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 42167e30..1b22fe4d 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -110,11 +110,11 @@ static int zsv_overwrite_usage() { return 1; } -static int zsv_overwrites_init(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_args *args) { - char *filepath = args->filepath; +static int zsv_overwrites_init(struct zsv_overwrite *data) { + char *filepath = data->args->filepath; const char *overwrites_fn = (const char *)zsv_cache_filepath((const unsigned char *)filepath, zsv_cache_type_overwrite, 0, 0); - ctx->src = (char *)overwrites_fn; + data->ctx->src = (char *)overwrites_fn; int err = 0; if (zsv_mkdirs(overwrites_fn, 1) && !zsv_file_readable(overwrites_fn, &err, NULL)) { @@ -132,38 +132,38 @@ static int zsv_overwrites_init(struct zsv_overwrite_ctx *ctx, struct zsv_overwri } */ - if (sqlite3_open_v2(overwrites_fn, &ctx->sqlite3.db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK || args->add || - args->bulk_add || args->bulk_remove || args->remove || args->clear) { - sqlite3_close(ctx->sqlite3.db); - if (sqlite3_open_v2(overwrites_fn, &ctx->sqlite3.db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != + if (sqlite3_open_v2(overwrites_fn, &data->ctx->sqlite3.db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK || + data->args->add || data->args->bulk_add || data->args->bulk_remove || data->args->remove || data->args->clear) { + sqlite3_close(data->ctx->sqlite3.db); + if (sqlite3_open_v2(overwrites_fn, &data->ctx->sqlite3.db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != SQLITE_OK) { err = 1; - fprintf(stderr, "Failed to open conn: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); + fprintf(stderr, "Failed to open conn: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); return err; } - if (sqlite3_prepare_v2(ctx->sqlite3.db, + if (sqlite3_prepare_v2(data->ctx->sqlite3.db, "CREATE TABLE IF NOT EXISTS overwrites ( row integer, column integer, value string, " "timestamp varchar(25), author varchar(25) );", -1, &query, NULL) == SQLITE_OK) { if (sqlite3_step(query) != SQLITE_DONE) { err = 1; - fprintf(stderr, "Failed to step: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); + fprintf(stderr, "Failed to step: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); return err; } } else { err = 1; - fprintf(stderr, "Failed to prepare: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); + fprintf(stderr, "Failed to prepare1: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); } if (query) sqlite3_finalize(query); - if (sqlite3_prepare_v2(ctx->sqlite3.db, "CREATE UNIQUE INDEX overwrites_uix ON overwrites (row, column)", -1, + if (sqlite3_prepare_v2(data->ctx->sqlite3.db, "CREATE UNIQUE INDEX overwrites_uix ON overwrites (row, column)", -1, &query, NULL) == SQLITE_OK) { if (sqlite3_step(query) != SQLITE_DONE) { err = 1; - fprintf(stderr, "Failed to step: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); + fprintf(stderr, "Failed to step: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); return err; } if (query) @@ -171,7 +171,7 @@ static int zsv_overwrites_init(struct zsv_overwrite_ctx *ctx, struct zsv_overwri } } - if (!ctx->sqlite3.db) + if (!data->ctx->sqlite3.db) err = 1; return err; @@ -195,53 +195,51 @@ static int zsv_overwrites_clear(struct zsv_overwrite_ctx *ctx) { return err; } -static sqlite3_stmt *zsv_overwrites_check_value(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite) { +static sqlite3_stmt *zsv_overwrites_check_value(struct zsv_overwrite *data) { sqlite3_stmt *query; - if (sqlite3_prepare_v2(ctx->sqlite3.db, "SELECT value FROM overwrites WHERE row = ? AND column = ?", -1, &query, + if (sqlite3_prepare_v2(data->ctx->sqlite3.db, "SELECT value FROM overwrites WHERE row = ? AND column = ?", -1, &query, NULL) != SQLITE_OK) { - fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); + fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); return NULL; } - sqlite3_bind_int64(query, 1, overwrite->row_ix); - sqlite3_bind_int64(query, 2, overwrite->col_ix); + sqlite3_bind_int64(query, 1, data->overwrite->row_ix); + sqlite3_bind_int64(query, 2, data->overwrite->col_ix); if (sqlite3_step(query) == SQLITE_ROW) { return query; // value exists } return NULL; // value does not exist } -static int zsv_overwrites_compare(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, - const struct zsv_overwrite_args *args) { - sqlite3_stmt *query = zsv_overwrites_check_value(ctx, overwrite); +static int zsv_overwrites_compare(struct zsv_overwrite *data) { + sqlite3_stmt *query = zsv_overwrites_check_value(data); if (query) { const unsigned char *text = sqlite3_column_text(query, 0); if (text) - return strcmp((const char *)text, (const char *)args->old_value); + return strcmp((const char *)text, (const char *)data->args->old_value); sqlite3_finalize(query); } return 1; // Value doesn't exist } -static int zsv_overwrites_remove(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, - const struct zsv_overwrite_args *args) { +static int zsv_overwrites_remove(struct zsv_overwrite *data) { int err = 0; - if (args->old_value && zsv_overwrites_compare(ctx, overwrite, args)) { + if (data->args->old_value && zsv_overwrites_compare(data)) { err = 1; return err; // value does not match } sqlite3_stmt *query = NULL; - if (sqlite3_prepare_v2(ctx->sqlite3.db, "DELETE FROM overwrites WHERE row = ? AND column = ?", -1, &query, NULL) != - SQLITE_OK) { + if (sqlite3_prepare_v2(data->ctx->sqlite3.db, "DELETE FROM overwrites WHERE row = ? AND column = ?", -1, &query, + NULL) != SQLITE_OK) { err = 1; - fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); + fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); return err; } - sqlite3_bind_int64(query, 1, overwrite->row_ix); - sqlite3_bind_int64(query, 2, overwrite->col_ix); + sqlite3_bind_int64(query, 1, data->overwrite->row_ix); + sqlite3_bind_int64(query, 2, data->overwrite->col_ix); if (sqlite3_step(query) != SQLITE_DONE) { err = 1; - fprintf(stderr, "Could not step: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); + fprintf(stderr, "Could not step: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); return err; } if (query) @@ -249,8 +247,8 @@ static int zsv_overwrites_remove(struct zsv_overwrite_ctx *ctx, struct zsv_overw return err; } -static int zsv_overwrites_has_value(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite) { - sqlite3_stmt *query = zsv_overwrites_check_value(ctx, overwrite); +static int zsv_overwrites_has_value(struct zsv_overwrite *data) { + sqlite3_stmt *query = zsv_overwrites_check_value(data); if (query) { sqlite3_finalize(query); return 1; @@ -258,68 +256,66 @@ static int zsv_overwrites_has_value(struct zsv_overwrite_ctx *ctx, struct zsv_ov return 0; } -static int zsv_overwrites_replace(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, - const struct zsv_overwrite_args *args) { +static int zsv_overwrites_replace(struct zsv_overwrite *data) { sqlite3_stmt *query = NULL; - if (sqlite3_prepare_v2(ctx->sqlite3.db, + if (sqlite3_prepare_v2(data->ctx->sqlite3.db, "UPDATE overwrites SET value = ?, timestamp = ?, author = ? WHERE row = ? AND column = ?", -1, &query, NULL) != SQLITE_OK) { - fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); + fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); return 1; } - sqlite3_bind_text(query, 1, (const char *)overwrite->val.str, -1, SQLITE_STATIC); - if (args->timestamp) - sqlite3_bind_int64(query, 2, args->timestamp); + sqlite3_bind_text(query, 1, (const char *)data->overwrite->val.str, -1, SQLITE_STATIC); + if (data->args->timestamp) + sqlite3_bind_int64(query, 2, data->args->timestamp); else sqlite3_bind_null(query, 2); sqlite3_bind_text(query, 3, "", -1, SQLITE_STATIC); // author - sqlite3_bind_int64(query, 4, overwrite->row_ix); - sqlite3_bind_int64(query, 5, overwrite->col_ix); + sqlite3_bind_int64(query, 4, data->overwrite->row_ix); + sqlite3_bind_int64(query, 5, data->overwrite->col_ix); if (sqlite3_step(query) != SQLITE_DONE) { - fprintf(stderr, "Could not step: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); + fprintf(stderr, "Could not step: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); return 1; } return 0; } -static int zsv_overwrites_insert(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, - const struct zsv_overwrite_args *args) { - if (!overwrite->val.str) +static int zsv_overwrites_insert(struct zsv_overwrite *data) { + if (!data->overwrite->val.str) return 1; - if (args->force && zsv_overwrites_has_value(ctx, overwrite)) - return zsv_overwrites_replace(ctx, overwrite, args); + if (data->args->force && zsv_overwrites_has_value(data)) + return zsv_overwrites_replace(data); int err = 0; sqlite3_stmt *query = NULL; - if (args->old_value && (err = zsv_overwrites_compare(ctx, overwrite, args))) { + if (data->args->old_value && (err = zsv_overwrites_compare(data))) { return err; - } else if (args->old_value) { - return zsv_overwrites_replace(ctx, overwrite, args); + } else if (data->args->old_value) { + return zsv_overwrites_replace(data); } - if (sqlite3_prepare_v2(ctx->sqlite3.db, + if (sqlite3_prepare_v2(data->ctx->sqlite3.db, "INSERT INTO overwrites (row, column, value, timestamp, author) VALUES (?, ?, ?, ?, ?)", -1, &query, NULL) == SQLITE_OK) { - sqlite3_bind_int64(query, 1, overwrite->row_ix); - sqlite3_bind_int64(query, 2, overwrite->col_ix); - sqlite3_bind_text(query, 3, (const char *)overwrite->val.str, -1, SQLITE_STATIC); - if (args->timestamp) - sqlite3_bind_int64(query, 4, args->timestamp); + sqlite3_bind_int64(query, 1, data->overwrite->row_ix); + sqlite3_bind_int64(query, 2, data->overwrite->col_ix); + sqlite3_bind_text(query, 3, (const char *)data->overwrite->val.str, -1, SQLITE_STATIC); + if (data->args->timestamp) + sqlite3_bind_int64(query, 4, data->args->timestamp); else sqlite3_bind_null(query, 4); - if (args->author) - sqlite3_bind_text(query, 5, (const char *)args->author, -1, SQLITE_STATIC); + if (data->args->author) + sqlite3_bind_text(query, 5, (const char *)data->args->author, -1, SQLITE_STATIC); else sqlite3_bind_text(query, 5, "", -1, SQLITE_STATIC); if (sqlite3_step(query) != SQLITE_DONE) { err = 1; fprintf(stderr, "Value already exists at row %zu and column %zu, use --force to force insert\n", - overwrite->row_ix, overwrite->col_ix); + data->overwrite->row_ix, data->overwrite->col_ix); } } else { err = 1; - fprintf(stderr, "Failed to prepare: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); + fprintf(stderr, "Failed to prepare2: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); } if (query) @@ -390,11 +386,15 @@ static void zsv_overwrites_bulk_add(void *ctx_v) { data->args = &args; data->overwrite = &overwrite; zsv_overwrites_bulk(data); - zsv_overwrites_insert(data->ctx, data->overwrite, data->args); - if (overwrite.val.str) + zsv_overwrites_insert(data); + if (overwrite.val.str) { free(overwrite.val.str); + overwrite.val.str = NULL; + } if (args.author) free(args.author); + if (args.old_value) + free(args.old_value); } static void zsv_overwrites_bulk_remove(void *ctx_v) { @@ -406,25 +406,27 @@ static void zsv_overwrites_bulk_remove(void *ctx_v) { data->args = &args; data->overwrite = &overwrite; zsv_overwrites_bulk(data); - zsv_overwrites_remove(data->ctx, data->overwrite, data->args); - if (overwrite.val.str) + zsv_overwrites_remove(data); + if (overwrite.val.str) { free(overwrite.val.str); + overwrite.val.str = NULL; + } if (args.author) free(args.author); + if (args.old_value) + free(args.old_value); } -static int zsv_overwrites_free(struct zsv_overwrite *data, struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, - zsv_csv_writer writer) { +static int zsv_overwrites_free(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, + const struct zsv_overwrite_args *args, zsv_csv_writer writer) { if (writer) zsv_writer_delete(writer); if (ctx) { free(ctx->src); sqlite3_close(ctx->sqlite3.db); } - if (overwrite) + if (overwrite && (!args->bulk_add || !args->bulk_remove)) free(overwrite->val.str); - if(data) - free(data); // sqlite3_shutdown(); return 0; @@ -451,14 +453,13 @@ static char *row_col_to_a1(size_t col, size_t row) { return result; } -static int show_all_overwrites(struct zsv_overwrite_ctx *ctx, const struct zsv_overwrite_args *args, - zsv_csv_writer writer) { +static int show_all_overwrites(struct zsv_overwrite *data, zsv_csv_writer writer) { int err = 0; sqlite3_stmt *stmt; int ret; - if (sqlite3_prepare_v2(ctx->sqlite3.db, "SELECT * FROM overwrites", -1, &stmt, NULL) != SQLITE_OK) { + if (sqlite3_prepare_v2(data->ctx->sqlite3.db, "SELECT * FROM overwrites", -1, &stmt, NULL) != SQLITE_OK) { err = 1; - fprintf(stderr, "Failed to prepare statement: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); + fprintf(stderr, "Failed to prepare statement: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); return err; } zsv_writer_cell(writer, 0, (const unsigned char *)"row", 3, 0); @@ -479,7 +480,7 @@ static int show_all_overwrites(struct zsv_overwrite_ctx *ctx, const struct zsv_o timestamp = sqlite3_column_int64(stmt, 3); const unsigned char *author = sqlite3_column_text(stmt, 4); size_t author_len = sqlite3_column_bytes(stmt, 4); - if (args->a1) { + if (data->args->a1) { char *col_a1 = row_col_to_a1(col + 1, row); // add one to display the correct letter if (!col_a1) { err = 1; @@ -501,7 +502,7 @@ static int show_all_overwrites(struct zsv_overwrite_ctx *ctx, const struct zsv_o } if (ret != SQLITE_DONE) { - fprintf(stderr, "Error during fetching rows: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); + fprintf(stderr, "Error during fetching rows: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); } if (stmt) @@ -646,25 +647,25 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op data->args = &args; data->overwrite = &overwrite; - if ((err = zsv_overwrites_init(&ctx, &args))) { + if ((err = zsv_overwrites_init(data))) { fprintf(stderr, "Failed to initalize database\n"); } zsv_csv_writer writer = zsv_writer_new(&writer_opts); if (err) { - zsv_overwrites_free(data, &ctx, &overwrite, writer); + zsv_overwrites_free(&ctx, &overwrite, &args, writer); return err; } if (args.list) - show_all_overwrites(&ctx, &args, writer); + show_all_overwrites(data, writer); else if (args.clear) zsv_overwrites_clear(&ctx); else if (args.add && ctx.sqlite3.db) - zsv_overwrites_insert(&ctx, &overwrite, &args); + zsv_overwrites_insert(data); else if (args.remove && ctx.sqlite3.db) - zsv_overwrites_remove(&ctx, &overwrite, &args); + zsv_overwrites_remove(data); else if ((args.bulk_add || args.bulk_remove) && ctx.sqlite3.db) { opts->ctx = data; opts->stream = ctx.csv.f; @@ -676,7 +677,10 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op fclose(ctx.csv.f); } - zsv_overwrites_free(data, &ctx, &overwrite, writer); + zsv_overwrites_free(&ctx, &overwrite, &args, writer); + + if (data) + free(data); return err; } From daaf8afca7694ae7556b7d9e1a13332db8684854 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Thu, 14 Nov 2024 21:24:36 -0500 Subject: [PATCH 24/62] Fix strndup issue --- app/overwrite.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 1b22fe4d..fb3aa42e 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -104,6 +104,17 @@ const char *zsv_overwrite_usage_msg[] = { " and may optionally include \"old value\", \"timestamp\" and/or \"author\"", NULL}; +static const char* strdup_n(const char *str, size_t chars) { + char *buffer = malloc(chars+1); + size_t i; + if(buffer) { + for(i = 0; i < chars && str[i] != '\0'; i++) + buffer[i] = str[i]; + buffer[i] = '\0'; + } + return buffer; +} + static int zsv_overwrite_usage() { for (size_t i = 0; zsv_overwrite_usage_msg[i]; i++) fprintf(stdout, "%s\n", zsv_overwrite_usage_msg[i]); @@ -362,11 +373,11 @@ static void zsv_overwrites_bulk(struct zsv_overwrite *data) { else if (i == data->timestamp_ix) data->args->timestamp = (size_t)atol((const char *)cell.str); else if (i == data->author_ix) - data->args->author = (unsigned char *)strndup((const char *)cell.str, cell.len); + data->args->author = (unsigned char *)strdup_n((const char *)cell.str, cell.len); else if (i == data->old_value_ix) - data->args->old_value = (unsigned char *)strndup((const char *)cell.str, cell.len); + data->args->old_value = (unsigned char *)strdup_n((const char *)cell.str, cell.len); else if (i == data->val_ix) { - data->overwrite->val.str = (unsigned char *)strndup((const char *)cell.str, cell.len); + data->overwrite->val.str = (unsigned char *)strdup_n((const char *)cell.str, cell.len); data->overwrite->val.len = cell.len; } } From e80cb9bcf0798d10849325a7af3a103e107b48f2 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Thu, 14 Nov 2024 21:25:45 -0500 Subject: [PATCH 25/62] format --- app/overwrite.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index fb3aa42e..efef8ac3 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -104,11 +104,11 @@ const char *zsv_overwrite_usage_msg[] = { " and may optionally include \"old value\", \"timestamp\" and/or \"author\"", NULL}; -static const char* strdup_n(const char *str, size_t chars) { - char *buffer = malloc(chars+1); +static const char *strdup_n(const char *str, size_t chars) { + char *buffer = malloc(chars + 1); size_t i; - if(buffer) { - for(i = 0; i < chars && str[i] != '\0'; i++) + if (buffer) { + for (i = 0; i < chars && str[i] != '\0'; i++) buffer[i] = str[i]; buffer[i] = '\0'; } From 2d55e6533a01572ac9b04d134f9f0c2c1510bac6 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Sat, 16 Nov 2024 19:26:57 -0500 Subject: [PATCH 26/62] Add remove --all and switch to zsv_memdup --- app/overwrite.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index efef8ac3..50b20167 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -22,6 +22,7 @@ #include #include #include +#include #define ZSV_COMMAND overwrite #include "zsv_command.h" @@ -31,6 +32,7 @@ struct zsv_overwrite_args { // options unsigned char force : 1; unsigned char a1 : 1; + unsigned char all : 1; unsigned char bulk_add : 1; unsigned char bulk_remove : 1; unsigned char *old_value; @@ -89,6 +91,7 @@ const char *zsv_overwrite_usage_msg[] = { " For `remove`, exit without error even if no overwrite for", " the specified cell already exists", " --no-timestamp : For `add`, don't save timestamp when adding an overwrite", + " --all : For `remove`, remove all overwrites and delete sqlite file", " --A1 : For `list`, Display addresses in A1-notation", "", "Description:", @@ -104,17 +107,6 @@ const char *zsv_overwrite_usage_msg[] = { " and may optionally include \"old value\", \"timestamp\" and/or \"author\"", NULL}; -static const char *strdup_n(const char *str, size_t chars) { - char *buffer = malloc(chars + 1); - size_t i; - if (buffer) { - for (i = 0; i < chars && str[i] != '\0'; i++) - buffer[i] = str[i]; - buffer[i] = '\0'; - } - return buffer; -} - static int zsv_overwrite_usage() { for (size_t i = 0; zsv_overwrite_usage_msg[i]; i++) fprintf(stdout, "%s\n", zsv_overwrite_usage_msg[i]); @@ -234,6 +226,11 @@ static int zsv_overwrites_compare(struct zsv_overwrite *data) { static int zsv_overwrites_remove(struct zsv_overwrite *data) { int err = 0; + if(data->args->all) { + zsv_overwrites_clear(data->ctx); + return err; + } + if (data->args->old_value && zsv_overwrites_compare(data)) { err = 1; return err; // value does not match @@ -373,11 +370,11 @@ static void zsv_overwrites_bulk(struct zsv_overwrite *data) { else if (i == data->timestamp_ix) data->args->timestamp = (size_t)atol((const char *)cell.str); else if (i == data->author_ix) - data->args->author = (unsigned char *)strdup_n((const char *)cell.str, cell.len); + data->args->author = (unsigned char *)zsv_memdup(cell.str, cell.len); else if (i == data->old_value_ix) - data->args->old_value = (unsigned char *)strdup_n((const char *)cell.str, cell.len); + data->args->old_value = (unsigned char *)zsv_memdup(cell.str, cell.len); else if (i == data->val_ix) { - data->overwrite->val.str = (unsigned char *)strdup_n((const char *)cell.str, cell.len); + data->overwrite->val.str = (unsigned char *)zsv_memdup((const char *)cell.str, cell.len); data->overwrite->val.len = cell.len; } } @@ -433,8 +430,10 @@ static int zsv_overwrites_free(struct zsv_overwrite_ctx *ctx, struct zsv_overwri if (writer) zsv_writer_delete(writer); if (ctx) { - free(ctx->src); sqlite3_close(ctx->sqlite3.db); + if(args->all) + remove(ctx->src); + free(ctx->src); } if (overwrite && (!args->bulk_add || !args->bulk_remove)) free(overwrite->val.str); @@ -597,6 +596,8 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op args.timestamp = 0; } else if (!strcmp(opt, "--A1")) { args.a1 = 1; + } else if (!strcmp(opt, "--all")) { + args.all = 1; } else if (!strcmp(opt, "list")) { args.list = 1; } else if (!strcmp(opt, "clear")) { @@ -618,7 +619,10 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op } else if (!strcmp(opt, "remove")) { if (argc - i > 1) { args.remove = 1; - err = zsv_overwrite_parse_pos(&overwrite, argv[++i]); + if(!strcmp(argv[++i], "--all")) + args.all = 1; + else + err = zsv_overwrite_parse_pos(&overwrite, argv[i]); if (err) { fprintf(stderr, "Expected row and column\n"); } From 1f7db781207d5cd682b7a331faf67c36cf0bab2c Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Sat, 16 Nov 2024 19:27:39 -0500 Subject: [PATCH 27/62] format --- app/overwrite.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 50b20167..00f51b86 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -226,7 +226,7 @@ static int zsv_overwrites_compare(struct zsv_overwrite *data) { static int zsv_overwrites_remove(struct zsv_overwrite *data) { int err = 0; - if(data->args->all) { + if (data->args->all) { zsv_overwrites_clear(data->ctx); return err; } @@ -431,7 +431,7 @@ static int zsv_overwrites_free(struct zsv_overwrite_ctx *ctx, struct zsv_overwri zsv_writer_delete(writer); if (ctx) { sqlite3_close(ctx->sqlite3.db); - if(args->all) + if (args->all) remove(ctx->src); free(ctx->src); } @@ -619,10 +619,10 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op } else if (!strcmp(opt, "remove")) { if (argc - i > 1) { args.remove = 1; - if(!strcmp(argv[++i], "--all")) - args.all = 1; + if (!strcmp(argv[++i], "--all")) + args.all = 1; else - err = zsv_overwrite_parse_pos(&overwrite, argv[i]); + err = zsv_overwrite_parse_pos(&overwrite, argv[i]); if (err) { fprintf(stderr, "Expected row and column\n"); } From 6b7d7dfd97e680274f9383d6688d2c5a9f9cdb94 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Sat, 16 Nov 2024 19:40:42 -0500 Subject: [PATCH 28/62] Enable forein_keys and change INSERT to INSERT OR REPLACE on --force --- app/overwrite.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 00f51b86..08107ba9 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -145,6 +145,12 @@ static int zsv_overwrites_init(struct zsv_overwrite *data) { return err; } + if (sqlite3_exec(data->ctx->sqlite3.db, "PRAGMA foreign_keys = on", NULL, NULL, NULL) != SQLITE_OK) { + err = 1; + fprintf(stderr, "Could not enable foreign keys: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); + return err; + } + if (sqlite3_prepare_v2(data->ctx->sqlite3.db, "CREATE TABLE IF NOT EXISTS overwrites ( row integer, column integer, value string, " "timestamp varchar(25), author varchar(25) );", @@ -290,21 +296,20 @@ static int zsv_overwrites_replace(struct zsv_overwrite *data) { static int zsv_overwrites_insert(struct zsv_overwrite *data) { if (!data->overwrite->val.str) return 1; - if (data->args->force && zsv_overwrites_has_value(data)) - return zsv_overwrites_replace(data); + if (data->args->force) + data->ctx->sqlite3.sql = + "INSERT OR REPLACE INTO overwrites (row, column, value, timestamp, author) VALUES (?, ?, ?, ?, ?)"; + else + data->ctx->sqlite3.sql = "INSERT INTO overwrites (row, column, value, timestamp, author) VALUES (?, ?, ?, ?, ?)"; int err = 0; sqlite3_stmt *query = NULL; if (data->args->old_value && (err = zsv_overwrites_compare(data))) { return err; - } else if (data->args->old_value) { - return zsv_overwrites_replace(data); } - if (sqlite3_prepare_v2(data->ctx->sqlite3.db, - "INSERT INTO overwrites (row, column, value, timestamp, author) VALUES (?, ?, ?, ?, ?)", -1, - &query, NULL) == SQLITE_OK) { + if (sqlite3_prepare_v2(data->ctx->sqlite3.db, data->ctx->sqlite3.sql, -1, &query, NULL) == SQLITE_OK) { sqlite3_bind_int64(query, 1, data->overwrite->row_ix); sqlite3_bind_int64(query, 2, data->overwrite->col_ix); sqlite3_bind_text(query, 3, (const char *)data->overwrite->val.str, -1, SQLITE_STATIC); From bd55a9a7e0d422fa0653f8649b585dfeaabccfee Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Sat, 16 Nov 2024 19:41:32 -0500 Subject: [PATCH 29/62] Remove unused functions --- app/overwrite.c | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 08107ba9..00e94f15 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -261,38 +261,6 @@ static int zsv_overwrites_remove(struct zsv_overwrite *data) { return err; } -static int zsv_overwrites_has_value(struct zsv_overwrite *data) { - sqlite3_stmt *query = zsv_overwrites_check_value(data); - if (query) { - sqlite3_finalize(query); - return 1; - } - return 0; -} - -static int zsv_overwrites_replace(struct zsv_overwrite *data) { - sqlite3_stmt *query = NULL; - if (sqlite3_prepare_v2(data->ctx->sqlite3.db, - "UPDATE overwrites SET value = ?, timestamp = ?, author = ? WHERE row = ? AND column = ?", -1, - &query, NULL) != SQLITE_OK) { - fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); - return 1; - } - sqlite3_bind_text(query, 1, (const char *)data->overwrite->val.str, -1, SQLITE_STATIC); - if (data->args->timestamp) - sqlite3_bind_int64(query, 2, data->args->timestamp); - else - sqlite3_bind_null(query, 2); - sqlite3_bind_text(query, 3, "", -1, SQLITE_STATIC); // author - sqlite3_bind_int64(query, 4, data->overwrite->row_ix); - sqlite3_bind_int64(query, 5, data->overwrite->col_ix); - if (sqlite3_step(query) != SQLITE_DONE) { - fprintf(stderr, "Could not step: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); - return 1; - } - return 0; -} - static int zsv_overwrites_insert(struct zsv_overwrite *data) { if (!data->overwrite->val.str) return 1; From 09d199535c2b675acc707e5dca7b1856cfec6da5 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Sat, 16 Nov 2024 19:54:47 -0500 Subject: [PATCH 30/62] Fix test errors --- app/overwrite.c | 2 +- app/test/overwrite/Makefile | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 00e94f15..2e497a30 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -264,7 +264,7 @@ static int zsv_overwrites_remove(struct zsv_overwrite *data) { static int zsv_overwrites_insert(struct zsv_overwrite *data) { if (!data->overwrite->val.str) return 1; - if (data->args->force) + if (data->args->force || data->args->old_value) data->ctx->sqlite3.sql = "INSERT OR REPLACE INTO overwrites (row, column, value, timestamp, author) VALUES (?, ?, ?, ?, ?)"; else diff --git a/app/test/overwrite/Makefile b/app/test/overwrite/Makefile index 11e58bce..6ec20a96 100644 --- a/app/test/overwrite/Makefile +++ b/app/test/overwrite/Makefile @@ -99,10 +99,10 @@ test-old-value: @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,V1,,\n2,1,V2,,\n3,1,V3,,\n4,1,V4,,\n\"`" ] \ && ${TEST_PASS} || ${TEST_FAIL} @${PREFIX} ${EXE} dummy2.csv add 2-1 NEW_V2 --old-value V2 --no-timestamp - @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,V1,,\n2,1,NEW_V2,,\n3,1,V3,,\n4,1,V4,,\n\"`" ] \ + @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,V1,,\n3,1,V3,,\n4,1,V4,,\n2,1,NEW_V2,,\n\"`" ] \ && ${TEST_PASS} || ${TEST_FAIL} @${PREFIX} ${EXE} dummy2.csv remove 3-1 --old-value V3 - @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,V1,,\n2,1,NEW_V2,,\n4,1,V4,,\n\"`" ] \ + @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,V1,,\n4,1,V4,,\n2,1,NEW_V2,,\n\"`" ] \ && ${TEST_PASS} || ${TEST_FAIL} test-force: @@ -122,7 +122,7 @@ test-bulk-add: @${PREFIX} ${EXE} dummy2.csv add 1-1 OLD_V1 --no-timestamp # for old value test @${PREFIX} ${EXE} dummy2.csv add 2-1 OLD_VAL2 --no-timestamp @${PREFIX} ${EXE} dummy2.csv bulk-add overwrite.csv - @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,VAL1,1731620001,\n2,1,OLD_VAL2,,\n3,1,VAL3,,\n4,1,VAL4,1731620001,\n\"`" ] \ + @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n2,1,OLD_VAL2,,\n1,1,VAL1,1731620001,\n3,1,VAL3,,\n4,1,VAL4,1731620001,\n\"`" ] \ && ${TEST_PASS} || ${TEST_FAIL} test-bulk-remove: From 3e90bff8cb4be4f920025ad66da97ea8ca8de4ee Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Sat, 16 Nov 2024 20:24:06 -0500 Subject: [PATCH 31/62] Add BEGIN transaction and COMMIT to bulk operations --- app/overwrite.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 2e497a30..6996c98d 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -658,11 +658,17 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op opts->ctx = data; opts->stream = ctx.csv.f; ctx.csv.parser = zsv_new(opts); - while (zsv_parse_more(ctx.csv.parser) == zsv_status_ok) - ; - zsv_finish(ctx.csv.parser); - zsv_delete(ctx.csv.parser); - fclose(ctx.csv.f); + if (sqlite3_exec(ctx.sqlite3.db, "BEGIN TRANSACTION", NULL, NULL, NULL) == SQLITE_OK) { + while (zsv_parse_more(ctx.csv.parser) == zsv_status_ok) + ; + zsv_finish(ctx.csv.parser); + zsv_delete(ctx.csv.parser); + fclose(ctx.csv.f); + if(sqlite3_exec(ctx.sqlite3.db, "COMMIT", NULL, NULL, NULL) != SQLITE_OK) + fprintf(stderr, "Could not commit changes: %s\n", sqlite3_errmsg(ctx.sqlite3.db)); + } else + fprintf(stderr, "Could not begin transaction: %s\n", sqlite3_errmsg(ctx.sqlite3.db)); + } zsv_overwrites_free(&ctx, &overwrite, &args, writer); From 877570c89220deff40d639507e8337b9fabedb96 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Sat, 16 Nov 2024 20:26:25 -0500 Subject: [PATCH 32/62] Add rollback on fail during bulk operations --- app/overwrite.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 6996c98d..52cac59e 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -245,6 +245,8 @@ static int zsv_overwrites_remove(struct zsv_overwrite *data) { if (sqlite3_prepare_v2(data->ctx->sqlite3.db, "DELETE FROM overwrites WHERE row = ? AND column = ?", -1, &query, NULL) != SQLITE_OK) { err = 1; + if (data->args->bulk_remove) + sqlite3_exec(data->ctx->sqlite3.db, "ROLLBACK", NULL, NULL, NULL); fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); return err; } @@ -253,6 +255,8 @@ static int zsv_overwrites_remove(struct zsv_overwrite *data) { if (sqlite3_step(query) != SQLITE_DONE) { err = 1; + if (data->args->bulk_remove) + sqlite3_exec(data->ctx->sqlite3.db, "ROLLBACK", NULL, NULL, NULL); fprintf(stderr, "Could not step: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); return err; } @@ -291,11 +295,15 @@ static int zsv_overwrites_insert(struct zsv_overwrite *data) { sqlite3_bind_text(query, 5, "", -1, SQLITE_STATIC); if (sqlite3_step(query) != SQLITE_DONE) { err = 1; + if (data->args->bulk_add) + sqlite3_exec(data->ctx->sqlite3.db, "ROLLBACK", NULL, NULL, NULL); fprintf(stderr, "Value already exists at row %zu and column %zu, use --force to force insert\n", data->overwrite->row_ix, data->overwrite->col_ix); } } else { err = 1; + if (data->args->bulk_add) + sqlite3_exec(data->ctx->sqlite3.db, "ROLLBACK", NULL, NULL, NULL); fprintf(stderr, "Failed to prepare2: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); } @@ -664,11 +672,10 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op zsv_finish(ctx.csv.parser); zsv_delete(ctx.csv.parser); fclose(ctx.csv.f); - if(sqlite3_exec(ctx.sqlite3.db, "COMMIT", NULL, NULL, NULL) != SQLITE_OK) + if (sqlite3_exec(ctx.sqlite3.db, "COMMIT", NULL, NULL, NULL) != SQLITE_OK) fprintf(stderr, "Could not commit changes: %s\n", sqlite3_errmsg(ctx.sqlite3.db)); - } else + } else fprintf(stderr, "Could not begin transaction: %s\n", sqlite3_errmsg(ctx.sqlite3.db)); - } zsv_overwrites_free(&ctx, &overwrite, &args, writer); From b7a7b0c2694169859d1b1aeef933bdad0b411517 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Sat, 16 Nov 2024 20:51:06 -0500 Subject: [PATCH 33/62] Update force test, updating more tests shortly --- app/test/overwrite/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/test/overwrite/Makefile b/app/test/overwrite/Makefile index 6ec20a96..e8943765 100644 --- a/app/test/overwrite/Makefile +++ b/app/test/overwrite/Makefile @@ -112,6 +112,10 @@ test-force: @${PREFIX} ${EXE} dummy2.csv add 2-2 VAL2 --no-timestamp @${PREFIX} ${EXE} dummy2.csv add 2-3 VAL3 --no-timestamp @${PREFIX} ${EXE} dummy2.csv add 2-4 VAL4 --no-timestamp + @${EXE} dummy2.csv add 2-4 NEW_VAL4 --no-timestamp 2> ${TMP_DIR}/$@.out + @${CMP} ${TMP_DIR}/$@.out expected/$@-fail.out && ${TEST_PASS} || ${TEST_FAIL} + @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,2,VAL1,,\n2,2,VAL2,,\n2,3,VAL3,,\n2,4,VAL4,,\n\"`" ] \ + && ${TEST_PASS} || ${TEST_FAIL} @${PREFIX} ${EXE} dummy2.csv add 2-4 NEW_VAL4 --no-timestamp --force @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,2,VAL1,,\n2,2,VAL2,,\n2,3,VAL3,,\n2,4,NEW_VAL4,,\n\"`" ] \ && ${TEST_PASS} || ${TEST_FAIL} From 819ec11cb53cef577a5cdebdcc08ae2f6931515a Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Sat, 16 Nov 2024 20:59:12 -0500 Subject: [PATCH 34/62] Add expected file --- app/test/overwrite/expected/test-force-fail.out | 1 + 1 file changed, 1 insertion(+) create mode 100644 app/test/overwrite/expected/test-force-fail.out diff --git a/app/test/overwrite/expected/test-force-fail.out b/app/test/overwrite/expected/test-force-fail.out new file mode 100644 index 00000000..d69a13d6 --- /dev/null +++ b/app/test/overwrite/expected/test-force-fail.out @@ -0,0 +1 @@ +Value already exists at row 2 and column 4, use --force to force insert From c85a7d296e986924760e89f48ef899988d7749cc Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Sat, 16 Nov 2024 22:03:48 -0500 Subject: [PATCH 35/62] make bulk operations cleaner --- app/overwrite.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 52cac59e..247d888a 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -33,8 +33,7 @@ struct zsv_overwrite_args { unsigned char force : 1; unsigned char a1 : 1; unsigned char all : 1; - unsigned char bulk_add : 1; - unsigned char bulk_remove : 1; + unsigned char bulk : 1; unsigned char *old_value; unsigned char *author; size_t timestamp; @@ -136,7 +135,7 @@ static int zsv_overwrites_init(struct zsv_overwrite *data) { */ if (sqlite3_open_v2(overwrites_fn, &data->ctx->sqlite3.db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK || - data->args->add || data->args->bulk_add || data->args->bulk_remove || data->args->remove || data->args->clear) { + data->args->add || data->args->bulk || data->args->remove || data->args->clear) { sqlite3_close(data->ctx->sqlite3.db); if (sqlite3_open_v2(overwrites_fn, &data->ctx->sqlite3.db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != SQLITE_OK) { @@ -245,7 +244,7 @@ static int zsv_overwrites_remove(struct zsv_overwrite *data) { if (sqlite3_prepare_v2(data->ctx->sqlite3.db, "DELETE FROM overwrites WHERE row = ? AND column = ?", -1, &query, NULL) != SQLITE_OK) { err = 1; - if (data->args->bulk_remove) + if (data->args->bulk) sqlite3_exec(data->ctx->sqlite3.db, "ROLLBACK", NULL, NULL, NULL); fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); return err; @@ -255,7 +254,7 @@ static int zsv_overwrites_remove(struct zsv_overwrite *data) { if (sqlite3_step(query) != SQLITE_DONE) { err = 1; - if (data->args->bulk_remove) + if (data->args->bulk) sqlite3_exec(data->ctx->sqlite3.db, "ROLLBACK", NULL, NULL, NULL); fprintf(stderr, "Could not step: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); return err; @@ -295,14 +294,14 @@ static int zsv_overwrites_insert(struct zsv_overwrite *data) { sqlite3_bind_text(query, 5, "", -1, SQLITE_STATIC); if (sqlite3_step(query) != SQLITE_DONE) { err = 1; - if (data->args->bulk_add) + if (data->args->bulk) sqlite3_exec(data->ctx->sqlite3.db, "ROLLBACK", NULL, NULL, NULL); fprintf(stderr, "Value already exists at row %zu and column %zu, use --force to force insert\n", data->overwrite->row_ix, data->overwrite->col_ix); } } else { err = 1; - if (data->args->bulk_add) + if (data->args->bulk) sqlite3_exec(data->ctx->sqlite3.db, "ROLLBACK", NULL, NULL, NULL); fprintf(stderr, "Failed to prepare2: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); } @@ -416,7 +415,7 @@ static int zsv_overwrites_free(struct zsv_overwrite_ctx *ctx, struct zsv_overwri remove(ctx->src); free(ctx->src); } - if (overwrite && (!args->bulk_add || !args->bulk_remove)) + if (overwrite && (!args->bulk)) free(overwrite->val.str); // sqlite3_shutdown(); @@ -613,7 +612,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op } } else if (!strcmp(opt, "bulk-add")) { if (argc - i > 1) { - args.bulk_add = 1; + args.bulk = 1; ctx.csv.f = fopen((const char *)argv[++i], "rb"); opts->row_handler = zsv_overwrites_bulk_add; } else { @@ -622,7 +621,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op } } else if (!strcmp(opt, "bulk-remove")) { if (argc - i > 1) { - args.bulk_remove = 1; + args.bulk = 1; ctx.csv.f = fopen((const char *)argv[++i], "rb"); opts->row_handler = zsv_overwrites_bulk_remove; } else { @@ -662,7 +661,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op zsv_overwrites_insert(data); else if (args.remove && ctx.sqlite3.db) zsv_overwrites_remove(data); - else if ((args.bulk_add || args.bulk_remove) && ctx.sqlite3.db) { + else if (args.bulk && ctx.sqlite3.db) { opts->ctx = data; opts->stream = ctx.csv.f; ctx.csv.parser = zsv_new(opts); From dcb78fd1daf0b688e94ba7a594ce1f78d0c315f6 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Sun, 17 Nov 2024 16:22:54 -0500 Subject: [PATCH 36/62] Remove overwrites_compare() and instead modify the sql statement --- app/overwrite.c | 51 ++++++++++++++----------------------------------- 1 file changed, 14 insertions(+), 37 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 247d888a..1a44d6e0 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -203,32 +203,6 @@ static int zsv_overwrites_clear(struct zsv_overwrite_ctx *ctx) { return err; } -static sqlite3_stmt *zsv_overwrites_check_value(struct zsv_overwrite *data) { - sqlite3_stmt *query; - if (sqlite3_prepare_v2(data->ctx->sqlite3.db, "SELECT value FROM overwrites WHERE row = ? AND column = ?", -1, &query, - NULL) != SQLITE_OK) { - fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); - return NULL; - } - sqlite3_bind_int64(query, 1, data->overwrite->row_ix); - sqlite3_bind_int64(query, 2, data->overwrite->col_ix); - if (sqlite3_step(query) == SQLITE_ROW) { - return query; // value exists - } - return NULL; // value does not exist -} - -static int zsv_overwrites_compare(struct zsv_overwrite *data) { - sqlite3_stmt *query = zsv_overwrites_check_value(data); - if (query) { - const unsigned char *text = sqlite3_column_text(query, 0); - if (text) - return strcmp((const char *)text, (const char *)data->args->old_value); - sqlite3_finalize(query); - } - return 1; // Value doesn't exist -} - static int zsv_overwrites_remove(struct zsv_overwrite *data) { int err = 0; if (data->args->all) { @@ -236,13 +210,11 @@ static int zsv_overwrites_remove(struct zsv_overwrite *data) { return err; } - if (data->args->old_value && zsv_overwrites_compare(data)) { - err = 1; - return err; // value does not match - } + data->ctx->sqlite3.sql = data->args->old_value ? "DELETE FROM overwrites WHERE row = ? AND column = ? AND value = ?" + : "DELETE FROM overwrites WHERE row = ? AND column = ?"; + sqlite3_stmt *query = NULL; - if (sqlite3_prepare_v2(data->ctx->sqlite3.db, "DELETE FROM overwrites WHERE row = ? AND column = ?", -1, &query, - NULL) != SQLITE_OK) { + if (sqlite3_prepare_v2(data->ctx->sqlite3.db, data->ctx->sqlite3.sql, -1, &query, NULL) != SQLITE_OK) { err = 1; if (data->args->bulk) sqlite3_exec(data->ctx->sqlite3.db, "ROLLBACK", NULL, NULL, NULL); @@ -251,6 +223,8 @@ static int zsv_overwrites_remove(struct zsv_overwrite *data) { } sqlite3_bind_int64(query, 1, data->overwrite->row_ix); sqlite3_bind_int64(query, 2, data->overwrite->col_ix); + if (data->args->old_value) + sqlite3_bind_text(query, 3, (const char *)data->args->old_value, -1, SQLITE_STATIC); if (sqlite3_step(query) != SQLITE_DONE) { err = 1; @@ -267,19 +241,18 @@ static int zsv_overwrites_remove(struct zsv_overwrite *data) { static int zsv_overwrites_insert(struct zsv_overwrite *data) { if (!data->overwrite->val.str) return 1; - if (data->args->force || data->args->old_value) + if (data->args->force) data->ctx->sqlite3.sql = "INSERT OR REPLACE INTO overwrites (row, column, value, timestamp, author) VALUES (?, ?, ?, ?, ?)"; + else if (data->args->old_value) + data->ctx->sqlite3.sql = "INSERT OR REPLACE INTO overwrites (row, column, value, timestamp, author) SELECT ?, ?, " + "?, ?, ? WHERE EXISTS (SELECT 1 FROM overwrites WHERE value = ?)"; else data->ctx->sqlite3.sql = "INSERT INTO overwrites (row, column, value, timestamp, author) VALUES (?, ?, ?, ?, ?)"; int err = 0; sqlite3_stmt *query = NULL; - if (data->args->old_value && (err = zsv_overwrites_compare(data))) { - return err; - } - if (sqlite3_prepare_v2(data->ctx->sqlite3.db, data->ctx->sqlite3.sql, -1, &query, NULL) == SQLITE_OK) { sqlite3_bind_int64(query, 1, data->overwrite->row_ix); sqlite3_bind_int64(query, 2, data->overwrite->col_ix); @@ -292,6 +265,10 @@ static int zsv_overwrites_insert(struct zsv_overwrite *data) { sqlite3_bind_text(query, 5, (const char *)data->args->author, -1, SQLITE_STATIC); else sqlite3_bind_text(query, 5, "", -1, SQLITE_STATIC); + + if (data->args->old_value) + sqlite3_bind_text(query, 6, (const char *)data->args->old_value, -1, SQLITE_STATIC); + if (sqlite3_step(query) != SQLITE_DONE) { err = 1; if (data->args->bulk) From eb5fa512292937f8da304d9334000c2eb4ded206 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Sun, 17 Nov 2024 17:13:36 -0500 Subject: [PATCH 37/62] Update tests --- app/test/overwrite/Makefile | 8 ++++++++ app/test/overwrite/expected/test-old-value-fail.out | 1 + 2 files changed, 9 insertions(+) create mode 100644 app/test/overwrite/expected/test-old-value-fail.out diff --git a/app/test/overwrite/Makefile b/app/test/overwrite/Makefile index e8943765..843912dd 100644 --- a/app/test/overwrite/Makefile +++ b/app/test/overwrite/Makefile @@ -61,6 +61,7 @@ test-excel-cells: @${PREFIX} ${EXE} dummy.csv clear @${PREFIX} ${EXE} dummy.csv add C2 EXCEL --no-timestamp @${CHECK} [ "`${EXE} dummy.csv list`" = "`printf \"$(HEADER)\n1,2,EXCEL,,\n\"`" ] && ${TEST_PASS} || ${TEST_FAIL} + @${CHECK} [ "`${EXE} dummy.csv list --A1`" = "`printf \"$(HEADER)\nC2,EXCEL,,\n\"`" ] && ${TEST_PASS} || ${TEST_FAIL} test-add: @${TEST_INIT} @@ -87,6 +88,9 @@ test-remove: @${PREFIX} ${EXE} dummy2.csv remove 4-1 @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,V1,,\n3,1,V3,,\n\"`" ] \ && ${TEST_PASS} || ${TEST_FAIL} + @${PREFIX} ${EXE} dummy2.csv remove --all + @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n\"`" ] \ + && ${TEST_PASS} || ${TEST_FAIL} test-old-value: @${TEST_INIT} @@ -95,6 +99,10 @@ test-old-value: @${PREFIX} ${EXE} dummy2.csv add 2-1 V2 --no-timestamp @${PREFIX} ${EXE} dummy2.csv add 3-1 V3 --no-timestamp @${PREFIX} ${EXE} dummy2.csv add 4-1 V4 --no-timestamp + @${PREFIX} ${EXE} dummy2.csv add 3-1 NEW_V4 --no-timestamp 2> ${TMP_DIR}/$@.out + @${CMP} ${TMP_DIR}/$@.out expected/$@-fail.out && ${TEST_PASS} || ${TEST_FAIL} + @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,V1,,\n2,1,V2,,\n3,1,V3,,\n4,1,V4,,\n\"`" ] \ + && ${TEST_PASS} || ${TEST_FAIL} @${PREFIX} ${EXE} dummy2.csv remove 2-1 --old-value V3 @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,V1,,\n2,1,V2,,\n3,1,V3,,\n4,1,V4,,\n\"`" ] \ && ${TEST_PASS} || ${TEST_FAIL} diff --git a/app/test/overwrite/expected/test-old-value-fail.out b/app/test/overwrite/expected/test-old-value-fail.out new file mode 100644 index 00000000..5a5b604a --- /dev/null +++ b/app/test/overwrite/expected/test-old-value-fail.out @@ -0,0 +1 @@ +Value already exists at row 3 and column 1, use --force to force insert From a89268b32e603810fb253bb3adeb738733d71adb Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Tue, 19 Nov 2024 19:34:31 -0500 Subject: [PATCH 38/62] Switch to an enum for the modes rather than individual variables --- app/overwrite.c | 48 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 1a44d6e0..f63a98c2 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -27,21 +27,25 @@ #define ZSV_COMMAND overwrite #include "zsv_command.h" +enum zsvsheet_mode { + zsvsheet_mode_add, + zsvsheet_mode_remove, + zsvsheet_mode_clear, + zsvsheet_mode_list, + zsvsheet_mode_bulk, +}; + struct zsv_overwrite_args { char *filepath; // options unsigned char force : 1; unsigned char a1 : 1; unsigned char all : 1; - unsigned char bulk : 1; unsigned char *old_value; unsigned char *author; size_t timestamp; // commands - unsigned char list : 1; - unsigned char clear : 1; - unsigned char add : 1; - unsigned char remove : 1; + enum zsvsheet_mode mode; }; struct zsv_overwrite { @@ -135,7 +139,7 @@ static int zsv_overwrites_init(struct zsv_overwrite *data) { */ if (sqlite3_open_v2(overwrites_fn, &data->ctx->sqlite3.db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK || - data->args->add || data->args->bulk || data->args->remove || data->args->clear) { + data->args->mode == zsvsheet_mode_add || data->args->mode == zsvsheet_mode_bulk || data->args->mode == zsvsheet_mode_remove || data->args->mode == zsvsheet_mode_clear) { sqlite3_close(data->ctx->sqlite3.db); if (sqlite3_open_v2(overwrites_fn, &data->ctx->sqlite3.db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != SQLITE_OK) { @@ -216,7 +220,7 @@ static int zsv_overwrites_remove(struct zsv_overwrite *data) { sqlite3_stmt *query = NULL; if (sqlite3_prepare_v2(data->ctx->sqlite3.db, data->ctx->sqlite3.sql, -1, &query, NULL) != SQLITE_OK) { err = 1; - if (data->args->bulk) + if (data->args->mode == zsvsheet_mode_bulk) sqlite3_exec(data->ctx->sqlite3.db, "ROLLBACK", NULL, NULL, NULL); fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); return err; @@ -228,7 +232,7 @@ static int zsv_overwrites_remove(struct zsv_overwrite *data) { if (sqlite3_step(query) != SQLITE_DONE) { err = 1; - if (data->args->bulk) + if (data->args->mode == zsvsheet_mode_bulk) sqlite3_exec(data->ctx->sqlite3.db, "ROLLBACK", NULL, NULL, NULL); fprintf(stderr, "Could not step: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); return err; @@ -271,14 +275,14 @@ static int zsv_overwrites_insert(struct zsv_overwrite *data) { if (sqlite3_step(query) != SQLITE_DONE) { err = 1; - if (data->args->bulk) + if (data->args->mode == zsvsheet_mode_bulk) sqlite3_exec(data->ctx->sqlite3.db, "ROLLBACK", NULL, NULL, NULL); fprintf(stderr, "Value already exists at row %zu and column %zu, use --force to force insert\n", data->overwrite->row_ix, data->overwrite->col_ix); } } else { err = 1; - if (data->args->bulk) + if (data->args->mode == zsvsheet_mode_bulk) sqlite3_exec(data->ctx->sqlite3.db, "ROLLBACK", NULL, NULL, NULL); fprintf(stderr, "Failed to prepare2: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); } @@ -392,7 +396,7 @@ static int zsv_overwrites_free(struct zsv_overwrite_ctx *ctx, struct zsv_overwri remove(ctx->src); free(ctx->src); } - if (overwrite && (!args->bulk)) + if (overwrite && args->mode != zsvsheet_mode_bulk) free(overwrite->val.str); // sqlite3_shutdown(); @@ -556,12 +560,12 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op } else if (!strcmp(opt, "--all")) { args.all = 1; } else if (!strcmp(opt, "list")) { - args.list = 1; + args.mode = zsvsheet_mode_list; } else if (!strcmp(opt, "clear")) { - args.clear = 1; + args.mode = zsvsheet_mode_clear; } else if (!strcmp(opt, "add")) { if (argc - i > 2) { - args.add = 1; + args.mode = zsvsheet_mode_add; err = zsv_overwrite_parse_pos(&overwrite, argv[++i]); overwrite.val.str = (unsigned char *)strdup(argv[++i]); overwrite.val.len = strlen((const char *)overwrite.val.str); @@ -575,7 +579,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op } } else if (!strcmp(opt, "remove")) { if (argc - i > 1) { - args.remove = 1; + args.mode = zsvsheet_mode_remove; if (!strcmp(argv[++i], "--all")) args.all = 1; else @@ -589,7 +593,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op } } else if (!strcmp(opt, "bulk-add")) { if (argc - i > 1) { - args.bulk = 1; + args.mode = zsvsheet_mode_bulk; ctx.csv.f = fopen((const char *)argv[++i], "rb"); opts->row_handler = zsv_overwrites_bulk_add; } else { @@ -598,7 +602,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op } } else if (!strcmp(opt, "bulk-remove")) { if (argc - i > 1) { - args.bulk = 1; + args.mode = zsvsheet_mode_bulk; ctx.csv.f = fopen((const char *)argv[++i], "rb"); opts->row_handler = zsv_overwrites_bulk_remove; } else { @@ -630,15 +634,15 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op return err; } - if (args.list) + if (args.mode == zsvsheet_mode_list) show_all_overwrites(data, writer); - else if (args.clear) + else if (args.mode == zsvsheet_mode_clear) zsv_overwrites_clear(&ctx); - else if (args.add && ctx.sqlite3.db) + else if (args.mode == zsvsheet_mode_add && ctx.sqlite3.db) zsv_overwrites_insert(data); - else if (args.remove && ctx.sqlite3.db) + else if (args.mode == zsvsheet_mode_remove && ctx.sqlite3.db) zsv_overwrites_remove(data); - else if (args.bulk && ctx.sqlite3.db) { + else if (args.mode == zsvsheet_mode_bulk && ctx.sqlite3.db) { opts->ctx = data; opts->stream = ctx.csv.f; ctx.csv.parser = zsv_new(opts); From af03faf02e6ca05f540e83f001886c7293f36884 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Tue, 19 Nov 2024 22:03:17 -0500 Subject: [PATCH 39/62] Replace overwrite list to use utils/overwrite.c functions. Excel style not supported yet --- app/overwrite.c | 85 +++++++++++++------------------------------ app/utils/overwrite.c | 7 +++- include/zsv/common.h | 2 + 3 files changed, 34 insertions(+), 60 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index f63a98c2..6840e7f5 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -117,15 +117,10 @@ static int zsv_overwrite_usage() { } static int zsv_overwrites_init(struct zsv_overwrite *data) { - char *filepath = data->args->filepath; - const char *overwrites_fn = - (const char *)zsv_cache_filepath((const unsigned char *)filepath, zsv_cache_type_overwrite, 0, 0); - data->ctx->src = (char *)overwrites_fn; - int err = 0; - if (zsv_mkdirs(overwrites_fn, 1) && !zsv_file_readable(overwrites_fn, &err, NULL)) { + if (zsv_mkdirs(data->ctx->src, 1) && !zsv_file_readable(data->ctx->src, &err, NULL)) { err = 1; - perror(overwrites_fn); + perror(data->ctx->src); return err; } @@ -138,10 +133,10 @@ static int zsv_overwrites_init(struct zsv_overwrite *data) { } */ - if (sqlite3_open_v2(overwrites_fn, &data->ctx->sqlite3.db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK || + if (sqlite3_open_v2(data->ctx->src, &data->ctx->sqlite3.db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK || data->args->mode == zsvsheet_mode_add || data->args->mode == zsvsheet_mode_bulk || data->args->mode == zsvsheet_mode_remove || data->args->mode == zsvsheet_mode_clear) { sqlite3_close(data->ctx->sqlite3.db); - if (sqlite3_open_v2(overwrites_fn, &data->ctx->sqlite3.db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != + if (sqlite3_open_v2(data->ctx->src, &data->ctx->sqlite3.db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != SQLITE_OK) { err = 1; fprintf(stderr, "Failed to open conn: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); @@ -425,61 +420,26 @@ static char *row_col_to_a1(size_t col, size_t row) { } static int show_all_overwrites(struct zsv_overwrite *data, zsv_csv_writer writer) { - int err = 0; - sqlite3_stmt *stmt; - int ret; - if (sqlite3_prepare_v2(data->ctx->sqlite3.db, "SELECT * FROM overwrites", -1, &stmt, NULL) != SQLITE_OK) { - err = 1; - fprintf(stderr, "Failed to prepare statement: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); - return err; - } zsv_writer_cell(writer, 0, (const unsigned char *)"row", 3, 0); zsv_writer_cell(writer, 0, (const unsigned char *)"column", 6, 0); zsv_writer_cell(writer, 0, (const unsigned char *)"value", 5, 0); zsv_writer_cell(writer, 0, (const unsigned char *)"timestamp", 9, 0); zsv_writer_cell(writer, 0, (const unsigned char *)"author", 6, 0); - - while ((ret = sqlite3_step(stmt)) == SQLITE_ROW) { - size_t row = sqlite3_column_int64(stmt, 0); - size_t col = sqlite3_column_int64(stmt, 1); - const unsigned char *val = sqlite3_column_text(stmt, 2); - size_t val_len = sqlite3_column_bytes(stmt, 2); - size_t timestamp = 0; - // If timestamp is null, that means --no-timestamp was passed on insertion - int timestamp_is_null = sqlite3_column_type(stmt, 3) == SQLITE_NULL; - if (!timestamp_is_null) - timestamp = sqlite3_column_int64(stmt, 3); - const unsigned char *author = sqlite3_column_text(stmt, 4); - size_t author_len = sqlite3_column_bytes(stmt, 4); - if (data->args->a1) { - char *col_a1 = row_col_to_a1(col + 1, row); // add one to display the correct letter - if (!col_a1) { - err = 1; - fprintf(stderr, "Error converting column number to A1-notation\n"); - return err; - } - zsv_writer_cell(writer, 1, (const unsigned char *)col_a1, strlen(col_a1), 0); - free(col_a1); - } else { - zsv_writer_cell_zu(writer, 1, row); - zsv_writer_cell_zu(writer, 0, col); - } - zsv_writer_cell(writer, 0, val, val_len, 0); - if (!timestamp_is_null) - zsv_writer_cell_zu(writer, 0, timestamp); + struct zsv_overwrite_data odata = {.have = 1}; + while((data->ctx->next(data->ctx, &odata) == zsv_status_ok) && odata.have) { + zsv_writer_cell_zu(writer, 1, odata.row_ix); + zsv_writer_cell_zu(writer, 0, odata.col_ix); + zsv_writer_cell(writer, 0, odata.val.str, odata.val.len, 0); + if(odata.timestamp) + zsv_writer_cell_zu(writer, 0, odata.timestamp); else - zsv_writer_cell(writer, 0, (const unsigned char *)"", 0, 0); // write an empty cell if null - zsv_writer_cell(writer, 0, author, author_len, 0); - } - - if (ret != SQLITE_DONE) { - fprintf(stderr, "Error during fetching rows: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); + zsv_writer_cell(writer, 0, (unsigned char*)"", 0, 0); + if(odata.author.len > 0 && odata.author.str) + zsv_writer_cell(writer, 0, odata.author.str, odata.author.len, 0); + else + zsv_writer_cell(writer, 0, (unsigned char*)"", 0, 0); } - - if (stmt) - sqlite3_finalize(stmt); - - return err; + return 0; } struct xl_address { @@ -546,6 +506,9 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op char *filepath = (char *)argv[1]; args.filepath = filepath; + const char *overwrites_fn = + (const char *)zsv_cache_filepath((const unsigned char *)filepath, zsv_cache_type_overwrite, 0, 0); + ctx.src = (char *)overwrites_fn; for (int i = 2; !err && i < argc; i++) { const char *opt = argv[i]; @@ -623,8 +586,12 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op data->args = &args; data->overwrite = &overwrite; - if ((err = zsv_overwrites_init(data))) { - fprintf(stderr, "Failed to initalize database\n"); + if(args.mode == zsvsheet_mode_bulk || args.mode == zsvsheet_mode_list) { + if((err = (zsv_overwrite_open(data->ctx) != zsv_status_ok))) + fprintf(stderr, "Failed to initalize database\n"); + } else { + if ((err = zsv_overwrites_init(data))) + fprintf(stderr, "Failed to initalize database\n"); } zsv_csv_writer writer = zsv_writer_new(&writer_opts); diff --git a/app/utils/overwrite.c b/app/utils/overwrite.c index 0911cffd..5c976171 100644 --- a/app/utils/overwrite.c +++ b/app/utils/overwrite.c @@ -75,10 +75,15 @@ static enum zsv_status zsv_next_overwrite_sqlite3(void *h, struct zsv_overwrite_ odata->col_ix = sqlite3_column_int64(stmt, 1); odata->val.str = (unsigned char *)sqlite3_column_text(stmt, 2); odata->val.len = sqlite3_column_bytes(stmt, 2); + odata->timestamp = sqlite3_column_int64(stmt, 3); + odata->author.str = (unsigned char *)sqlite3_column_text(stmt, 4); + odata->author.len = sqlite3_column_bytes(stmt, 4); } else { odata->row_ix = 0; odata->col_ix = 0; odata->val.len = 0; + odata->timestamp = 0; + odata->author.len = 0; odata->have = 0; } } @@ -122,7 +127,7 @@ static enum zsv_status zsv_overwrite_init_sqlite3(struct zsv_overwrite_ctx *ctx, ok = 1; } else if (len > strlen(".sqlite3") && !strcmp(source + len - strlen(".sqlite3"), ".sqlite3")) { ctx->sqlite3.filename = strdup(source); - ctx->sqlite3.sql = "select row, column, value from overwrites order by row, column"; + ctx->sqlite3.sql = "select row, column, value, timestamp, author from overwrites order by row, column"; ok = 1; } diff --git a/include/zsv/common.h b/include/zsv/common.h index a245c702..f48bca6b 100644 --- a/include/zsv/common.h +++ b/include/zsv/common.h @@ -99,7 +99,9 @@ typedef void (*zsv_completed_callback)(void *ctx, int code); struct zsv_overwrite_data { size_t row_ix; // 0-based size_t col_ix; // 0-based + size_t timestamp; struct zsv_cell val; + struct zsv_cell author; char have; // 1 = we have unprocessed overwrites }; From 605dd139ae793a4cdc69c3ccce3823727b81b5b6 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Wed, 20 Nov 2024 14:19:25 -0500 Subject: [PATCH 40/62] Add excel-style to refactored list command WIP --- app/overwrite.c | 70 +++++++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 26 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 6840e7f5..e31b0f68 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -427,8 +427,15 @@ static int show_all_overwrites(struct zsv_overwrite *data, zsv_csv_writer writer zsv_writer_cell(writer, 0, (const unsigned char *)"author", 6, 0); struct zsv_overwrite_data odata = {.have = 1}; while((data->ctx->next(data->ctx, &odata) == zsv_status_ok) && odata.have) { - zsv_writer_cell_zu(writer, 1, odata.row_ix); - zsv_writer_cell_zu(writer, 0, odata.col_ix); + if(data->args->a1) { + char *a1_ix = row_col_to_a1(odata.col_ix+1, odata.row_ix); + if(a1_ix) + zsv_writer_cell(writer, 1, (unsigned char*)a1_ix, strlen(a1_ix), 0); + free(a1_ix); + } else { + zsv_writer_cell_zu(writer, 1, odata.row_ix); + zsv_writer_cell_zu(writer, 0, odata.col_ix); + } zsv_writer_cell(writer, 0, odata.val.str, odata.val.len, 0); if(odata.timestamp) zsv_writer_cell_zu(writer, 0, odata.timestamp); @@ -497,18 +504,16 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op return err; } - struct zsv_overwrite_ctx ctx = {0}; + struct zsv_overwrite_opts ctx_opts = {0}; struct zsv_overwrite_args args = {0}; // By default, save timestamps args.timestamp = (size_t)time(NULL); struct zsv_overwrite_data overwrite = {0}; struct zsv_csv_writer_options writer_opts = {0}; + FILE *bulk_fp = NULL; char *filepath = (char *)argv[1]; args.filepath = filepath; - const char *overwrites_fn = - (const char *)zsv_cache_filepath((const unsigned char *)filepath, zsv_cache_type_overwrite, 0, 0); - ctx.src = (char *)overwrites_fn; for (int i = 2; !err && i < argc; i++) { const char *opt = argv[i]; @@ -557,7 +562,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op } else if (!strcmp(opt, "bulk-add")) { if (argc - i > 1) { args.mode = zsvsheet_mode_bulk; - ctx.csv.f = fopen((const char *)argv[++i], "rb"); + bulk_fp = fopen((const char *)argv[++i], "rb"); opts->row_handler = zsv_overwrites_bulk_add; } else { fprintf(stderr, "Expected overwrite filename\n"); @@ -566,7 +571,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op } else if (!strcmp(opt, "bulk-remove")) { if (argc - i > 1) { args.mode = zsvsheet_mode_bulk; - ctx.csv.f = fopen((const char *)argv[++i], "rb"); + bulk_fp = fopen((const char *)argv[++i], "rb"); opts->row_handler = zsv_overwrites_bulk_remove; } else { fprintf(stderr, "Expected overwrite filename\n"); @@ -581,12 +586,21 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op } } + char *overwrites_fn = + (char *)zsv_cache_filepath((const unsigned char *)filepath, zsv_cache_type_overwrite, 0, 0); + ctx_opts.src = (char *)overwrites_fn; + + struct zsv_overwrite_ctx *ctx = zsv_overwrite_context_new(&ctx_opts); + free(overwrites_fn); + if(bulk_fp) + ctx->csv.f = bulk_fp; + struct zsv_overwrite *data = calloc(1, sizeof(struct zsv_overwrite)); - data->ctx = &ctx; + data->ctx = ctx; data->args = &args; data->overwrite = &overwrite; - if(args.mode == zsvsheet_mode_bulk || args.mode == zsvsheet_mode_list) { + if(args.mode == zsvsheet_mode_list) { if((err = (zsv_overwrite_open(data->ctx) != zsv_status_ok))) fprintf(stderr, "Failed to initalize database\n"); } else { @@ -597,35 +611,39 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op zsv_csv_writer writer = zsv_writer_new(&writer_opts); if (err) { - zsv_overwrites_free(&ctx, &overwrite, &args, writer); + zsv_overwrites_free(ctx, &overwrite, &args, writer); return err; } if (args.mode == zsvsheet_mode_list) show_all_overwrites(data, writer); else if (args.mode == zsvsheet_mode_clear) - zsv_overwrites_clear(&ctx); - else if (args.mode == zsvsheet_mode_add && ctx.sqlite3.db) + zsv_overwrites_clear(ctx); + else if (args.mode == zsvsheet_mode_add && ctx->sqlite3.db) zsv_overwrites_insert(data); - else if (args.mode == zsvsheet_mode_remove && ctx.sqlite3.db) + else if (args.mode == zsvsheet_mode_remove && ctx->sqlite3.db) zsv_overwrites_remove(data); - else if (args.mode == zsvsheet_mode_bulk && ctx.sqlite3.db) { + else if (args.mode == zsvsheet_mode_bulk && ctx->sqlite3.db) { opts->ctx = data; - opts->stream = ctx.csv.f; - ctx.csv.parser = zsv_new(opts); - if (sqlite3_exec(ctx.sqlite3.db, "BEGIN TRANSACTION", NULL, NULL, NULL) == SQLITE_OK) { - while (zsv_parse_more(ctx.csv.parser) == zsv_status_ok) + opts->stream = ctx->csv.f; + ctx->csv.parser = zsv_new(opts); + if (sqlite3_exec(ctx->sqlite3.db, "BEGIN TRANSACTION", NULL, NULL, NULL) == SQLITE_OK) { + while (zsv_parse_more(ctx->csv.parser) == zsv_status_ok) ; - zsv_finish(ctx.csv.parser); - zsv_delete(ctx.csv.parser); - fclose(ctx.csv.f); - if (sqlite3_exec(ctx.sqlite3.db, "COMMIT", NULL, NULL, NULL) != SQLITE_OK) - fprintf(stderr, "Could not commit changes: %s\n", sqlite3_errmsg(ctx.sqlite3.db)); + zsv_finish(ctx->csv.parser); + zsv_delete(ctx->csv.parser); + fclose(ctx->csv.f); + if (sqlite3_exec(ctx->sqlite3.db, "COMMIT", NULL, NULL, NULL) != SQLITE_OK) + fprintf(stderr, "Could not commit changes: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); } else - fprintf(stderr, "Could not begin transaction: %s\n", sqlite3_errmsg(ctx.sqlite3.db)); + fprintf(stderr, "Could not begin transaction: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); } - zsv_overwrites_free(&ctx, &overwrite, &args, writer); + if(args.mode == zsvsheet_mode_list) { + zsv_overwrite_context_delete(data->ctx); + zsv_writer_delete(writer); + } else + zsv_overwrites_free(ctx, &overwrite, &args, writer); if (data) free(data); From d5656f6b284825f4e1ec97b5adbc3d20f0692e14 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Wed, 20 Nov 2024 14:22:15 -0500 Subject: [PATCH 41/62] format --- app/overwrite.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 854a0355..5a2716b1 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -134,7 +134,8 @@ static int zsv_overwrites_init(struct zsv_overwrite *data) { */ if (sqlite3_open_v2(data->ctx->src, &data->ctx->sqlite3.db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK || - data->args->mode == zsvsheet_mode_add || data->args->mode == zsvsheet_mode_bulk || data->args->mode == zsvsheet_mode_remove || data->args->mode == zsvsheet_mode_clear) { + data->args->mode == zsvsheet_mode_add || data->args->mode == zsvsheet_mode_bulk || + data->args->mode == zsvsheet_mode_remove || data->args->mode == zsvsheet_mode_clear) { sqlite3_close(data->ctx->sqlite3.db); if (sqlite3_open_v2(data->ctx->src, &data->ctx->sqlite3.db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != SQLITE_OK) { @@ -425,26 +426,26 @@ static int show_all_overwrites(struct zsv_overwrite *data, zsv_csv_writer writer zsv_writer_cell(writer, 0, (const unsigned char *)"value", 5, 0); zsv_writer_cell(writer, 0, (const unsigned char *)"timestamp", 9, 0); zsv_writer_cell(writer, 0, (const unsigned char *)"author", 6, 0); - struct zsv_overwrite_data odata = {.have = 1}; - while((data->ctx->next(data->ctx, &odata) == zsv_status_ok) && odata.have) { - if(data->args->a1) { - char *a1_ix = row_col_to_a1(odata.col_ix+1, odata.row_ix); - if(a1_ix) - zsv_writer_cell(writer, 1, (unsigned char*)a1_ix, strlen(a1_ix), 0); + struct zsv_overwrite_data odata = {.have = 1}; + while ((data->ctx->next(data->ctx, &odata) == zsv_status_ok) && odata.have) { + if (data->args->a1) { + char *a1_ix = row_col_to_a1(odata.col_ix + 1, odata.row_ix); + if (a1_ix) + zsv_writer_cell(writer, 1, (unsigned char *)a1_ix, strlen(a1_ix), 0); free(a1_ix); } else { zsv_writer_cell_zu(writer, 1, odata.row_ix); zsv_writer_cell_zu(writer, 0, odata.col_ix); } zsv_writer_cell(writer, 0, odata.val.str, odata.val.len, 0); - if(odata.timestamp) + if (odata.timestamp) zsv_writer_cell_zu(writer, 0, odata.timestamp); else - zsv_writer_cell(writer, 0, (unsigned char*)"", 0, 0); - if(odata.author.len > 0 && odata.author.str) + zsv_writer_cell(writer, 0, (unsigned char *)"", 0, 0); + if (odata.author.len > 0 && odata.author.str) zsv_writer_cell(writer, 0, odata.author.str, odata.author.len, 0); else - zsv_writer_cell(writer, 0, (unsigned char*)"", 0, 0); + zsv_writer_cell(writer, 0, (unsigned char *)"", 0, 0); } return 0; } @@ -589,13 +590,12 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op } } - char *overwrites_fn = - (char *)zsv_cache_filepath((const unsigned char *)filepath, zsv_cache_type_overwrite, 0, 0); + char *overwrites_fn = (char *)zsv_cache_filepath((const unsigned char *)filepath, zsv_cache_type_overwrite, 0, 0); ctx_opts.src = (char *)overwrites_fn; struct zsv_overwrite_ctx *ctx = zsv_overwrite_context_new(&ctx_opts); free(overwrites_fn); - if(bulk_fp) + if (bulk_fp) ctx->csv.f = bulk_fp; struct zsv_overwrite *data = calloc(1, sizeof(struct zsv_overwrite)); @@ -603,8 +603,8 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op data->args = &args; data->overwrite = &overwrite; - if(args.mode == zsvsheet_mode_list) { - if((err = (zsv_overwrite_open(data->ctx) != zsv_status_ok))) + if (args.mode == zsvsheet_mode_list) { + if ((err = (zsv_overwrite_open(data->ctx) != zsv_status_ok))) fprintf(stderr, "Failed to initalize database\n"); } else { if ((err = zsv_overwrites_init(data))) @@ -642,7 +642,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op fprintf(stderr, "Could not begin transaction: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); } - if(args.mode == zsvsheet_mode_list) { + if (args.mode == zsvsheet_mode_list) { zsv_overwrite_context_delete(data->ctx); zsv_writer_delete(writer); } else From 3a124005150769ac63d4e4b18bc9228db19fb19e Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Wed, 20 Nov 2024 14:31:24 -0500 Subject: [PATCH 42/62] Change sql query to use *, may need to change in the future --- app/utils/overwrite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/utils/overwrite.c b/app/utils/overwrite.c index 5c976171..c1fcee27 100644 --- a/app/utils/overwrite.c +++ b/app/utils/overwrite.c @@ -127,7 +127,7 @@ static enum zsv_status zsv_overwrite_init_sqlite3(struct zsv_overwrite_ctx *ctx, ok = 1; } else if (len > strlen(".sqlite3") && !strcmp(source + len - strlen(".sqlite3"), ".sqlite3")) { ctx->sqlite3.filename = strdup(source); - ctx->sqlite3.sql = "select row, column, value, timestamp, author from overwrites order by row, column"; + ctx->sqlite3.sql = "select * from overwrites order by row, column"; ok = 1; } From df57d2637554a9954a2e2b35dfa4b0cafe306404 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Wed, 20 Nov 2024 15:10:25 -0500 Subject: [PATCH 43/62] Update check in makefile to ensure the file is removed --- app/test/overwrite/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/test/overwrite/Makefile b/app/test/overwrite/Makefile index 635bfe99..173d438a 100644 --- a/app/test/overwrite/Makefile +++ b/app/test/overwrite/Makefile @@ -89,8 +89,8 @@ test-remove: @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,V1,,\n3,1,V3,,\n\"`" ] \ && ${TEST_PASS} || ${TEST_FAIL} @${PREFIX} ${EXE} dummy2.csv remove --all - @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n\"`" ] \ - && ${TEST_PASS} || ${TEST_FAIL} + @${CHECK} [ ! -f ".zsv/overwrite/dummy2.csv/overwrite.sqlite3" ] \ + && ${TEST_PASS} || ${TEST_FAIL} test-old-value: @${TEST_INIT} From 0a765f0e47f207d02b67bd57474148c3bad35d21 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Wed, 20 Nov 2024 15:24:40 -0500 Subject: [PATCH 44/62] Fix placing issue in test --- app/test/overwrite/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/test/overwrite/Makefile b/app/test/overwrite/Makefile index 173d438a..84f4efac 100644 --- a/app/test/overwrite/Makefile +++ b/app/test/overwrite/Makefile @@ -107,10 +107,10 @@ test-old-value: @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,V1,,\n2,1,V2,,\n3,1,V3,,\n4,1,V4,,\n\"`" ] \ && ${TEST_PASS} || ${TEST_FAIL} @${PREFIX} ${EXE} dummy2.csv add 2-1 NEW_V2 --old-value V2 --no-timestamp - @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,V1,,\n3,1,V3,,\n4,1,V4,,\n2,1,NEW_V2,,\n\"`" ] \ + @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,V1,,\n2,1,NEW_V2,,\n3,1,V3,,\n4,1,V4,,\n\"`" ] \ && ${TEST_PASS} || ${TEST_FAIL} @${PREFIX} ${EXE} dummy2.csv remove 3-1 --old-value V3 - @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,V1,,\n4,1,V4,,\n2,1,NEW_V2,,\n\"`" ] \ + @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,V1,,\n2,1,NEW_V2,,\n4,1,V4,,\n\"`" ] \ && ${TEST_PASS} || ${TEST_FAIL} test-force: From 41e496bc6fc8fc7199a39d93d87b7089f84f2c1d Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Wed, 20 Nov 2024 15:28:56 -0500 Subject: [PATCH 45/62] Fix another test placement issue --- app/test/overwrite/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/test/overwrite/Makefile b/app/test/overwrite/Makefile index 84f4efac..2c527018 100644 --- a/app/test/overwrite/Makefile +++ b/app/test/overwrite/Makefile @@ -134,7 +134,8 @@ test-bulk-add: @${PREFIX} ${EXE} dummy2.csv add 1-1 OLD_V1 --no-timestamp # for old value test @${PREFIX} ${EXE} dummy2.csv add 2-1 OLD_VAL2 --no-timestamp @${PREFIX} ${EXE} dummy2.csv bulk-add overwrite.csv - @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n2,1,OLD_VAL2,,\n1,1,VAL1,1731620001,\n3,1,VAL3,,\n4,1,VAL4,1731620001,\n\"`" ] \ + @${EXE} dummy2.csv list + @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,VAL1,1731620001,\n2,1,OLD_VAL2,,\n3,1,VAL3,,\n4,1,VAL4,1731620001,\n\"`" ] \ && ${TEST_PASS} || ${TEST_FAIL} test-bulk-remove: From 30b94ce95201b1fab5c2976ae1f59e98099a2a95 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Wed, 20 Nov 2024 20:57:51 -0500 Subject: [PATCH 46/62] Modify bulk operations to use utils/overwrite.h functions --- app/overwrite.c | 171 ++++++++-------------------------- app/utils/overwrite.c | 29 ++++++ include/zsv/common.h | 1 + include/zsv/utils/overwrite.h | 3 + 4 files changed, 73 insertions(+), 131 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 5a2716b1..2f8ca353 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -41,9 +41,7 @@ struct zsv_overwrite_args { unsigned char force : 1; unsigned char a1 : 1; unsigned char all : 1; - unsigned char *old_value; - unsigned char *author; - size_t timestamp; + unsigned char *bulk_file; // commands enum zsvsheet_mode mode; }; @@ -52,6 +50,7 @@ struct zsv_overwrite { struct zsv_overwrite_ctx *ctx; struct zsv_overwrite_args *args; struct zsv_overwrite_data *overwrite; + int (*next)(struct zsv_overwrite *data); // bulk indexes size_t row_ix; size_t col_ix; @@ -210,7 +209,7 @@ static int zsv_overwrites_remove(struct zsv_overwrite *data) { return err; } - data->ctx->sqlite3.sql = data->args->old_value ? "DELETE FROM overwrites WHERE row = ? AND column = ? AND value = ?" + data->ctx->sqlite3.sql = data->overwrite->old_value.len > 0 ? "DELETE FROM overwrites WHERE row = ? AND column = ? AND value = ?" : "DELETE FROM overwrites WHERE row = ? AND column = ?"; sqlite3_stmt *query = NULL; @@ -223,8 +222,8 @@ static int zsv_overwrites_remove(struct zsv_overwrite *data) { } sqlite3_bind_int64(query, 1, data->overwrite->row_ix); sqlite3_bind_int64(query, 2, data->overwrite->col_ix); - if (data->args->old_value) - sqlite3_bind_text(query, 3, (const char *)data->args->old_value, -1, SQLITE_STATIC); + if (data->overwrite->old_value.len > 0) + sqlite3_bind_text(query, 3, (const char *)data->overwrite->old_value.str, data->overwrite->old_value.len, SQLITE_STATIC); if (sqlite3_step(query) != SQLITE_DONE) { err = 1; @@ -244,7 +243,7 @@ static int zsv_overwrites_insert(struct zsv_overwrite *data) { if (data->args->force) data->ctx->sqlite3.sql = "INSERT OR REPLACE INTO overwrites (row, column, value, timestamp, author) VALUES (?, ?, ?, ?, ?)"; - else if (data->args->old_value) + else if (data->overwrite->old_value.len > 0) data->ctx->sqlite3.sql = "INSERT OR REPLACE INTO overwrites (row, column, value, timestamp, author) SELECT ?, ?, " "?, ?, ? WHERE EXISTS (SELECT 1 FROM overwrites WHERE value = ?)"; else @@ -256,18 +255,18 @@ static int zsv_overwrites_insert(struct zsv_overwrite *data) { if (sqlite3_prepare_v2(data->ctx->sqlite3.db, data->ctx->sqlite3.sql, -1, &query, NULL) == SQLITE_OK) { sqlite3_bind_int64(query, 1, data->overwrite->row_ix); sqlite3_bind_int64(query, 2, data->overwrite->col_ix); - sqlite3_bind_text(query, 3, (const char *)data->overwrite->val.str, -1, SQLITE_STATIC); - if (data->args->timestamp) - sqlite3_bind_int64(query, 4, data->args->timestamp); + sqlite3_bind_text(query, 3, (const char *)data->overwrite->val.str, data->overwrite->val.len, SQLITE_STATIC); + if (data->overwrite->timestamp) + sqlite3_bind_int64(query, 4, data->overwrite->timestamp); else sqlite3_bind_null(query, 4); - if (data->args->author) - sqlite3_bind_text(query, 5, (const char *)data->args->author, -1, SQLITE_STATIC); + if (data->overwrite->author.len > 0) + sqlite3_bind_text(query, 5, (const char *)data->overwrite->author.str, data->overwrite->author.len, SQLITE_STATIC); else sqlite3_bind_text(query, 5, "", -1, SQLITE_STATIC); - if (data->args->old_value) - sqlite3_bind_text(query, 6, (const char *)data->args->old_value, -1, SQLITE_STATIC); + if (data->overwrite->old_value.len > 0) + sqlite3_bind_text(query, 6, (const char *)data->overwrite->old_value.str, data->overwrite->old_value.len, SQLITE_STATIC); if (sqlite3_step(query) != SQLITE_DONE) { err = 1; @@ -290,96 +289,22 @@ static int zsv_overwrites_insert(struct zsv_overwrite *data) { } static void zsv_overwrites_bulk(struct zsv_overwrite *data) { - data->args->timestamp = 0; - size_t c_count = zsv_cell_count(data->ctx->csv.parser); - if (data->ctx->row_ix == 0) { // header - for (size_t i = 0; i < c_count; i++) { - struct zsv_cell cell = zsv_get_cell(data->ctx->csv.parser, i); - if (cell.len == 0 || !cell.str) - continue; - if (!strncmp((const char *)cell.str, "row", cell.len)) - data->row_ix = i; - else if (!strncmp((const char *)cell.str, "col", cell.len)) - data->col_ix = i; - else if (!strncmp((const char *)cell.str, "value", cell.len)) - data->val_ix = i; - else if (!strncmp((const char *)cell.str, "timestamp", cell.len)) - data->timestamp_ix = i; - else if (!strncmp((const char *)cell.str, "old value", cell.len)) - data->old_value_ix = i; - else if (!strncmp((const char *)cell.str, "author", cell.len)) - data->author_ix = i; - else - fprintf(stderr, "Unregonized column %.*s\n", (int)cell.len, cell.str); - } - data->ctx->row_ix++; - return; + free(data->ctx->src); + data->ctx->src = (char*)data->args->bulk_file; + if(zsv_overwrite_open(data->ctx) != zsv_status_ok) { + fprintf(stderr, "Could not open\n"); + return; } - - for (size_t i = 0; i < c_count; i++) { - struct zsv_cell cell = zsv_get_cell(data->ctx->csv.parser, i); - if (cell.len == 0 || !cell.str) - continue; - if (i == data->row_ix) - data->overwrite->row_ix = atol((const char *)cell.str); - else if (i == data->col_ix) - data->overwrite->col_ix = atol((const char *)cell.str); - else if (i == data->timestamp_ix) - data->args->timestamp = (size_t)atol((const char *)cell.str); - else if (i == data->author_ix) - data->args->author = (unsigned char *)zsv_memdup(cell.str, cell.len); - else if (i == data->old_value_ix) - data->args->old_value = (unsigned char *)zsv_memdup(cell.str, cell.len); - else if (i == data->val_ix) { - data->overwrite->val.str = (unsigned char *)zsv_memdup((const char *)cell.str, cell.len); - data->overwrite->val.len = cell.len; + data->overwrite->have = 1; + data->ctx->row_ix = 1; + if (sqlite3_exec(data->ctx->sqlite3.db, "BEGIN TRANSACTION", NULL, NULL, NULL) == SQLITE_OK) { + while(data->ctx->next(data->ctx, data->overwrite) == zsv_status_ok && data->overwrite->have) { + data->next(data); } - } - if (!data->overwrite->row_ix || !data->overwrite->col_ix || !data->overwrite->val.str) { - printf("Overwrite failed: %zu %zu %zu\n", data->val_ix, data->row_ix, data->col_ix); - return; // cannot continue without a proper row, col, value overwrite - } - data->ctx->row_ix++; -} - -static void zsv_overwrites_bulk_add(void *ctx_v) { - struct zsv_overwrite *data = (struct zsv_overwrite *)ctx_v; - if (zsv_row_is_blank(data->ctx->csv.parser)) - return; - struct zsv_overwrite_data overwrite = {0}; - struct zsv_overwrite_args args = {0}; - data->args = &args; - data->overwrite = &overwrite; - zsv_overwrites_bulk(data); - zsv_overwrites_insert(data); - if (overwrite.val.str) { - free(overwrite.val.str); - overwrite.val.str = NULL; - } - if (args.author) - free(args.author); - if (args.old_value) - free(args.old_value); -} - -static void zsv_overwrites_bulk_remove(void *ctx_v) { - struct zsv_overwrite *data = (struct zsv_overwrite *)ctx_v; - if (zsv_row_is_blank(data->ctx->csv.parser)) - return; - struct zsv_overwrite_data overwrite = {0}; - struct zsv_overwrite_args args = {0}; - data->args = &args; - data->overwrite = &overwrite; - zsv_overwrites_bulk(data); - zsv_overwrites_remove(data); - if (overwrite.val.str) { - free(overwrite.val.str); - overwrite.val.str = NULL; - } - if (args.author) - free(args.author); - if (args.old_value) - free(args.old_value); + if (sqlite3_exec(data->ctx->sqlite3.db, "COMMIT", NULL, NULL, NULL) != SQLITE_OK) + fprintf(stderr, "Could not commit changes: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); + } else + fprintf(stderr, "Could not begin transaction: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); } static int zsv_overwrites_free(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, @@ -388,8 +313,6 @@ static int zsv_overwrites_free(struct zsv_overwrite_ctx *ctx, struct zsv_overwri zsv_writer_delete(writer); if (ctx) { sqlite3_close(ctx->sqlite3.db); - if (args->all) - remove(ctx->src); free(ctx->src); } if (overwrite && args->mode != zsvsheet_mode_bulk) @@ -509,12 +432,12 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op (void)(opts); (void)(custom_prop_handler); (void)(opts_used); + struct zsv_overwrite *data = calloc(1, sizeof(struct zsv_overwrite)); struct zsv_overwrite_args args = {0}; // By default, save timestamps - args.timestamp = (size_t)time(NULL); struct zsv_overwrite_data overwrite = {0}; + overwrite.timestamp = (size_t)time(NULL); struct zsv_csv_writer_options writer_opts = {0}; - FILE *bulk_fp = NULL; char *filepath = (char *)argv[1]; args.filepath = filepath; @@ -524,13 +447,12 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op if (!strcmp(opt, "-f") || !strcmp(opt, "--force")) { args.force = 1; } else if (!strcmp(opt, "--old-value")) { - args.old_value = (unsigned char *)argv[++i]; + overwrite.old_value.str = (unsigned char *)argv[++i]; + overwrite.old_value.len = strlen((const char*)overwrite.old_value.str); } else if (!strcmp(opt, "--no-timestamp")) { - args.timestamp = 0; + overwrite.timestamp = 0; } else if (!strcmp(opt, "--A1")) { args.a1 = 1; - } else if (!strcmp(opt, "--all")) { - args.all = 1; } else if (!strcmp(opt, "list")) { args.mode = zsvsheet_mode_list; } else if (!strcmp(opt, "clear")) { @@ -566,8 +488,8 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op } else if (!strcmp(opt, "bulk-add")) { if (argc - i > 1) { args.mode = zsvsheet_mode_bulk; - bulk_fp = fopen((const char *)argv[++i], "rb"); - opts->row_handler = zsv_overwrites_bulk_add; + args.bulk_file = (unsigned char*)strdup(argv[++i]); + data->next = zsv_overwrites_insert; } else { fprintf(stderr, "Expected overwrite filename\n"); err = 1; @@ -575,8 +497,8 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op } else if (!strcmp(opt, "bulk-remove")) { if (argc - i > 1) { args.mode = zsvsheet_mode_bulk; - bulk_fp = fopen((const char *)argv[++i], "rb"); - opts->row_handler = zsv_overwrites_bulk_remove; + args.bulk_file = (unsigned char*)strdup(argv[++i]); + data->next = zsv_overwrites_remove; } else { fprintf(stderr, "Expected overwrite filename\n"); err = 1; @@ -595,10 +517,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op struct zsv_overwrite_ctx *ctx = zsv_overwrite_context_new(&ctx_opts); free(overwrites_fn); - if (bulk_fp) - ctx->csv.f = bulk_fp; - struct zsv_overwrite *data = calloc(1, sizeof(struct zsv_overwrite)); data->ctx = ctx; data->args = &args; data->overwrite = &overwrite; @@ -627,27 +546,17 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op else if (args.mode == zsvsheet_mode_remove && ctx->sqlite3.db) zsv_overwrites_remove(data); else if (args.mode == zsvsheet_mode_bulk && ctx->sqlite3.db) { - opts->ctx = data; - opts->stream = ctx->csv.f; - ctx->csv.parser = zsv_new(opts); - if (sqlite3_exec(ctx->sqlite3.db, "BEGIN TRANSACTION", NULL, NULL, NULL) == SQLITE_OK) { - while (zsv_parse_more(ctx->csv.parser) == zsv_status_ok) - ; - zsv_finish(ctx->csv.parser); - zsv_delete(ctx->csv.parser); - fclose(ctx->csv.f); - if (sqlite3_exec(ctx->sqlite3.db, "COMMIT", NULL, NULL, NULL) != SQLITE_OK) - fprintf(stderr, "Could not commit changes: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); - } else - fprintf(stderr, "Could not begin transaction: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); + zsv_overwrites_bulk(data); } - if (args.mode == zsvsheet_mode_list) { + if (args.mode == zsvsheet_mode_list || args.mode == zsvsheet_mode_bulk) { zsv_overwrite_context_delete(data->ctx); zsv_writer_delete(writer); } else zsv_overwrites_free(ctx, &overwrite, &args, writer); + if (data->args->all) + remove(ctx->src); if (data) free(data); diff --git a/app/utils/overwrite.c b/app/utils/overwrite.c index c1fcee27..42acca94 100644 --- a/app/utils/overwrite.c +++ b/app/utils/overwrite.c @@ -48,6 +48,15 @@ static enum zsv_status zsv_next_overwrite_csv(void *h, struct zsv_overwrite_data struct zsv_cell row = zsv_get_cell(ctx->csv.parser, 0); struct zsv_cell col = zsv_get_cell(ctx->csv.parser, 1); struct zsv_cell val = zsv_get_cell(ctx->csv.parser, 2); + struct zsv_cell author = {0}; + struct zsv_cell timestamp = {0}; + struct zsv_cell old_value = {0}; + if(ctx->author_ix) + author = zsv_get_cell(ctx->csv.parser, ctx->author_ix); + if(ctx->timestamp_ix) + timestamp = zsv_get_cell(ctx->csv.parser, ctx->timestamp_ix); + if(ctx->old_value_ix) + old_value = zsv_get_cell(ctx->csv.parser, ctx->old_value_ix); if (row.len && col.len) { char *end = (char *)(row.str + row.len); char **endp = &end; @@ -55,10 +64,20 @@ static enum zsv_status zsv_next_overwrite_csv(void *h, struct zsv_overwrite_data end = (char *)(col.str + col.len); odata->col_ix = strtoumax((char *)col.str, endp, 10); odata->val = val; + odata->author = author; + odata->old_value = old_value; } else { odata->row_ix = 0; odata->col_ix = 0; odata->val.len = 0; + odata->old_value.len = 0; + odata->author.len = 0; + } + + if(timestamp.len) { + char *end = (char *)(timestamp.str + timestamp.len); + char **endp = &end; + odata->timestamp = strtoumax((char *)timestamp.str, endp, 10); } } return zsv_status_ok; @@ -186,6 +205,16 @@ enum zsv_status zsv_overwrite_open(void *h) { memcmp(val.str, "val", 3)) fprintf(stderr, "Warning! overwrite expects 'row,col,value' header, got '%.*s,%.*s,%.*s'\n", (int)row.len, row.str, (int)col.len, col.str, (int)val.len, val.str); + struct zsv_cell next; + for(size_t i = 3; (next = zsv_get_cell(ctx->csv.parser, i)).len > 0; i++) { + if(!memcmp(next.str, "timestamp", 9)) { + ctx->timestamp_ix = i; + } else if(!memcmp(next.str, "author", 6)) { + ctx->author_ix = i; + } else if(!memcmp(next.str, "old value", 9)) { + ctx->old_value_ix = i; + } + } } ctx->next = zsv_next_overwrite_csv; ok = 1; diff --git a/include/zsv/common.h b/include/zsv/common.h index f48bca6b..3c69a2db 100644 --- a/include/zsv/common.h +++ b/include/zsv/common.h @@ -102,6 +102,7 @@ struct zsv_overwrite_data { size_t timestamp; struct zsv_cell val; struct zsv_cell author; + struct zsv_cell old_value; char have; // 1 = we have unprocessed overwrites }; diff --git a/include/zsv/utils/overwrite.h b/include/zsv/utils/overwrite.h index cb8fc688..296925b4 100644 --- a/include/zsv/utils/overwrite.h +++ b/include/zsv/utils/overwrite.h @@ -5,6 +5,9 @@ struct zsv_overwrite_ctx { char *src; + size_t author_ix; + size_t timestamp_ix; + size_t old_value_ix; // enum zsv_overwrite_type type; enum zsv_status (*next)(void *ctx, struct zsv_overwrite_data *odata); struct { From e20ddf08f9ad0f47c1d5d1309fb37b13872bea17 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Wed, 20 Nov 2024 20:58:33 -0500 Subject: [PATCH 47/62] format --- app/overwrite.c | 30 +++++++++++++++++------------- app/utils/overwrite.c | 18 +++++++++--------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 2f8ca353..05ca4b89 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -209,8 +209,9 @@ static int zsv_overwrites_remove(struct zsv_overwrite *data) { return err; } - data->ctx->sqlite3.sql = data->overwrite->old_value.len > 0 ? "DELETE FROM overwrites WHERE row = ? AND column = ? AND value = ?" - : "DELETE FROM overwrites WHERE row = ? AND column = ?"; + data->ctx->sqlite3.sql = data->overwrite->old_value.len > 0 + ? "DELETE FROM overwrites WHERE row = ? AND column = ? AND value = ?" + : "DELETE FROM overwrites WHERE row = ? AND column = ?"; sqlite3_stmt *query = NULL; if (sqlite3_prepare_v2(data->ctx->sqlite3.db, data->ctx->sqlite3.sql, -1, &query, NULL) != SQLITE_OK) { @@ -223,7 +224,8 @@ static int zsv_overwrites_remove(struct zsv_overwrite *data) { sqlite3_bind_int64(query, 1, data->overwrite->row_ix); sqlite3_bind_int64(query, 2, data->overwrite->col_ix); if (data->overwrite->old_value.len > 0) - sqlite3_bind_text(query, 3, (const char *)data->overwrite->old_value.str, data->overwrite->old_value.len, SQLITE_STATIC); + sqlite3_bind_text(query, 3, (const char *)data->overwrite->old_value.str, data->overwrite->old_value.len, + SQLITE_STATIC); if (sqlite3_step(query) != SQLITE_DONE) { err = 1; @@ -261,12 +263,14 @@ static int zsv_overwrites_insert(struct zsv_overwrite *data) { else sqlite3_bind_null(query, 4); if (data->overwrite->author.len > 0) - sqlite3_bind_text(query, 5, (const char *)data->overwrite->author.str, data->overwrite->author.len, SQLITE_STATIC); + sqlite3_bind_text(query, 5, (const char *)data->overwrite->author.str, data->overwrite->author.len, + SQLITE_STATIC); else sqlite3_bind_text(query, 5, "", -1, SQLITE_STATIC); if (data->overwrite->old_value.len > 0) - sqlite3_bind_text(query, 6, (const char *)data->overwrite->old_value.str, data->overwrite->old_value.len, SQLITE_STATIC); + sqlite3_bind_text(query, 6, (const char *)data->overwrite->old_value.str, data->overwrite->old_value.len, + SQLITE_STATIC); if (sqlite3_step(query) != SQLITE_DONE) { err = 1; @@ -290,15 +294,15 @@ static int zsv_overwrites_insert(struct zsv_overwrite *data) { static void zsv_overwrites_bulk(struct zsv_overwrite *data) { free(data->ctx->src); - data->ctx->src = (char*)data->args->bulk_file; - if(zsv_overwrite_open(data->ctx) != zsv_status_ok) { - fprintf(stderr, "Could not open\n"); - return; + data->ctx->src = (char *)data->args->bulk_file; + if (zsv_overwrite_open(data->ctx) != zsv_status_ok) { + fprintf(stderr, "Could not open\n"); + return; } data->overwrite->have = 1; data->ctx->row_ix = 1; if (sqlite3_exec(data->ctx->sqlite3.db, "BEGIN TRANSACTION", NULL, NULL, NULL) == SQLITE_OK) { - while(data->ctx->next(data->ctx, data->overwrite) == zsv_status_ok && data->overwrite->have) { + while (data->ctx->next(data->ctx, data->overwrite) == zsv_status_ok && data->overwrite->have) { data->next(data); } if (sqlite3_exec(data->ctx->sqlite3.db, "COMMIT", NULL, NULL, NULL) != SQLITE_OK) @@ -448,7 +452,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op args.force = 1; } else if (!strcmp(opt, "--old-value")) { overwrite.old_value.str = (unsigned char *)argv[++i]; - overwrite.old_value.len = strlen((const char*)overwrite.old_value.str); + overwrite.old_value.len = strlen((const char *)overwrite.old_value.str); } else if (!strcmp(opt, "--no-timestamp")) { overwrite.timestamp = 0; } else if (!strcmp(opt, "--A1")) { @@ -488,7 +492,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op } else if (!strcmp(opt, "bulk-add")) { if (argc - i > 1) { args.mode = zsvsheet_mode_bulk; - args.bulk_file = (unsigned char*)strdup(argv[++i]); + args.bulk_file = (unsigned char *)strdup(argv[++i]); data->next = zsv_overwrites_insert; } else { fprintf(stderr, "Expected overwrite filename\n"); @@ -497,7 +501,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op } else if (!strcmp(opt, "bulk-remove")) { if (argc - i > 1) { args.mode = zsvsheet_mode_bulk; - args.bulk_file = (unsigned char*)strdup(argv[++i]); + args.bulk_file = (unsigned char *)strdup(argv[++i]); data->next = zsv_overwrites_remove; } else { fprintf(stderr, "Expected overwrite filename\n"); diff --git a/app/utils/overwrite.c b/app/utils/overwrite.c index 42acca94..357774bd 100644 --- a/app/utils/overwrite.c +++ b/app/utils/overwrite.c @@ -51,11 +51,11 @@ static enum zsv_status zsv_next_overwrite_csv(void *h, struct zsv_overwrite_data struct zsv_cell author = {0}; struct zsv_cell timestamp = {0}; struct zsv_cell old_value = {0}; - if(ctx->author_ix) + if (ctx->author_ix) author = zsv_get_cell(ctx->csv.parser, ctx->author_ix); - if(ctx->timestamp_ix) + if (ctx->timestamp_ix) timestamp = zsv_get_cell(ctx->csv.parser, ctx->timestamp_ix); - if(ctx->old_value_ix) + if (ctx->old_value_ix) old_value = zsv_get_cell(ctx->csv.parser, ctx->old_value_ix); if (row.len && col.len) { char *end = (char *)(row.str + row.len); @@ -74,7 +74,7 @@ static enum zsv_status zsv_next_overwrite_csv(void *h, struct zsv_overwrite_data odata->author.len = 0; } - if(timestamp.len) { + if (timestamp.len) { char *end = (char *)(timestamp.str + timestamp.len); char **endp = &end; odata->timestamp = strtoumax((char *)timestamp.str, endp, 10); @@ -205,13 +205,13 @@ enum zsv_status zsv_overwrite_open(void *h) { memcmp(val.str, "val", 3)) fprintf(stderr, "Warning! overwrite expects 'row,col,value' header, got '%.*s,%.*s,%.*s'\n", (int)row.len, row.str, (int)col.len, col.str, (int)val.len, val.str); - struct zsv_cell next; - for(size_t i = 3; (next = zsv_get_cell(ctx->csv.parser, i)).len > 0; i++) { - if(!memcmp(next.str, "timestamp", 9)) { + struct zsv_cell next; + for (size_t i = 3; (next = zsv_get_cell(ctx->csv.parser, i)).len > 0; i++) { + if (!memcmp(next.str, "timestamp", 9)) { ctx->timestamp_ix = i; - } else if(!memcmp(next.str, "author", 6)) { + } else if (!memcmp(next.str, "author", 6)) { ctx->author_ix = i; - } else if(!memcmp(next.str, "old value", 9)) { + } else if (!memcmp(next.str, "old value", 9)) { ctx->old_value_ix = i; } } From f50cff1cfe29d8dc58414126d37f89ee1d38631f Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Wed, 20 Nov 2024 21:08:48 -0500 Subject: [PATCH 48/62] Fix issue with timestamp in bulk operations --- app/overwrite.c | 1 + app/test/overwrite/Makefile | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/app/overwrite.c b/app/overwrite.c index 05ca4b89..ef23bd49 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -304,6 +304,7 @@ static void zsv_overwrites_bulk(struct zsv_overwrite *data) { if (sqlite3_exec(data->ctx->sqlite3.db, "BEGIN TRANSACTION", NULL, NULL, NULL) == SQLITE_OK) { while (data->ctx->next(data->ctx, data->overwrite) == zsv_status_ok && data->overwrite->have) { data->next(data); + data->overwrite->timestamp = 0; } if (sqlite3_exec(data->ctx->sqlite3.db, "COMMIT", NULL, NULL, NULL) != SQLITE_OK) fprintf(stderr, "Could not commit changes: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); diff --git a/app/test/overwrite/Makefile b/app/test/overwrite/Makefile index 2c527018..68cafce7 100644 --- a/app/test/overwrite/Makefile +++ b/app/test/overwrite/Makefile @@ -134,7 +134,6 @@ test-bulk-add: @${PREFIX} ${EXE} dummy2.csv add 1-1 OLD_V1 --no-timestamp # for old value test @${PREFIX} ${EXE} dummy2.csv add 2-1 OLD_VAL2 --no-timestamp @${PREFIX} ${EXE} dummy2.csv bulk-add overwrite.csv - @${EXE} dummy2.csv list @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,VAL1,1731620001,\n2,1,OLD_VAL2,,\n3,1,VAL3,,\n4,1,VAL4,1731620001,\n\"`" ] \ && ${TEST_PASS} || ${TEST_FAIL} From c4b5abd6b8b6b534c212a3ae81d99448ea122072 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Wed, 20 Nov 2024 21:43:53 -0500 Subject: [PATCH 49/62] Update overwrites_free --- app/overwrite.c | 9 ++------- app/utils/overwrite.c | 3 ++- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index ef23bd49..73b5d9c5 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -317,8 +317,7 @@ static int zsv_overwrites_free(struct zsv_overwrite_ctx *ctx, struct zsv_overwri if (writer) zsv_writer_delete(writer); if (ctx) { - sqlite3_close(ctx->sqlite3.db); - free(ctx->src); + zsv_overwrite_context_delete(ctx); } if (overwrite && args->mode != zsvsheet_mode_bulk) free(overwrite->val.str); @@ -554,11 +553,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op zsv_overwrites_bulk(data); } - if (args.mode == zsvsheet_mode_list || args.mode == zsvsheet_mode_bulk) { - zsv_overwrite_context_delete(data->ctx); - zsv_writer_delete(writer); - } else - zsv_overwrites_free(ctx, &overwrite, &args, writer); + zsv_overwrites_free(ctx, &overwrite, &args, writer); if (data->args->all) remove(ctx->src); diff --git a/app/utils/overwrite.c b/app/utils/overwrite.c index 357774bd..8ff912d7 100644 --- a/app/utils/overwrite.c +++ b/app/utils/overwrite.c @@ -25,7 +25,8 @@ void *zsv_overwrite_context_new(struct zsv_overwrite_opts *opts) { enum zsv_status zsv_overwrite_context_delete(void *h) { struct zsv_overwrite_ctx *ctx = h; - free(ctx->sqlite3.filename); + if(ctx->sqlite3.filename) + free(ctx->sqlite3.filename); if (ctx->sqlite3.stmt) sqlite3_finalize(ctx->sqlite3.stmt); if (ctx->sqlite3.db) From 69bc5317b72f49c9d8cadf22ea4ad374b9463de5 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Wed, 20 Nov 2024 21:46:12 -0500 Subject: [PATCH 50/62] format --- app/utils/overwrite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/utils/overwrite.c b/app/utils/overwrite.c index 8ff912d7..3f9675c2 100644 --- a/app/utils/overwrite.c +++ b/app/utils/overwrite.c @@ -25,7 +25,7 @@ void *zsv_overwrite_context_new(struct zsv_overwrite_opts *opts) { enum zsv_status zsv_overwrite_context_delete(void *h) { struct zsv_overwrite_ctx *ctx = h; - if(ctx->sqlite3.filename) + if (ctx->sqlite3.filename) free(ctx->sqlite3.filename); if (ctx->sqlite3.stmt) sqlite3_finalize(ctx->sqlite3.stmt); From 49ab29c0abcc3420fdf18c17946bdf7fd0eca969 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Thu, 21 Nov 2024 20:41:08 -0500 Subject: [PATCH 51/62] Add utils/overwrite_writer.h, needs a little bit more work --- app/Makefile | 2 +- app/overwrite.c | 228 +++------------------------ app/utils/overwrite_writer.c | 175 ++++++++++++++++++++ include/zsv/utils/overwrite_writer.h | 53 +++++++ 4 files changed, 253 insertions(+), 205 deletions(-) create mode 100644 app/utils/overwrite_writer.c create mode 100644 include/zsv/utils/overwrite_writer.h diff --git a/app/Makefile b/app/Makefile index bdbfb4de..7da0b9b0 100644 --- a/app/Makefile +++ b/app/Makefile @@ -154,7 +154,7 @@ CFLAGS+= -I${PREFIX}/include THIS_LIB_BASE=$(shell cd .. && pwd) INCLUDE_DIR=${THIS_LIB_BASE}/include BUILD_DIR=${THIS_LIB_BASE}/build/${BUILD_SUBDIR}/${CCBN} -UTILS1=writer file err signal mem clock arg dl string dirs prop cache jq os overwrite index +UTILS1=writer file err signal mem clock arg dl string dirs prop cache jq os overwrite index overwrite_writer ZSV_EXTRAS ?= diff --git a/app/overwrite.c b/app/overwrite.c index 73b5d9c5..b870fbcc 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -23,43 +23,11 @@ #include #include #include +#include #define ZSV_COMMAND overwrite #include "zsv_command.h" -enum zsvsheet_mode { - zsvsheet_mode_add, - zsvsheet_mode_remove, - zsvsheet_mode_clear, - zsvsheet_mode_list, - zsvsheet_mode_bulk, -}; - -struct zsv_overwrite_args { - char *filepath; - // options - unsigned char force : 1; - unsigned char a1 : 1; - unsigned char all : 1; - unsigned char *bulk_file; - // commands - enum zsvsheet_mode mode; -}; - -struct zsv_overwrite { - struct zsv_overwrite_ctx *ctx; - struct zsv_overwrite_args *args; - struct zsv_overwrite_data *overwrite; - int (*next)(struct zsv_overwrite *data); - // bulk indexes - size_t row_ix; - size_t col_ix; - size_t val_ix; - size_t old_value_ix; - size_t timestamp_ix; - size_t author_ix; -}; - const char *zsv_overwrite_usage_msg[] = { APPNAME " - Manage overwrites associated with a CSV file", "", @@ -125,16 +93,9 @@ static int zsv_overwrites_init(struct zsv_overwrite *data) { sqlite3_stmt *query = NULL; - /* - if ((ret = sqlite3_initialize()) != SQLITE_OK) { - fprintf(stderr, "Failed to initialize library: %d, %s\n", ret, sqlite3_errmsg(ctx->sqlite3.db)); - return err; - } - */ - if (sqlite3_open_v2(data->ctx->src, &data->ctx->sqlite3.db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK || - data->args->mode == zsvsheet_mode_add || data->args->mode == zsvsheet_mode_bulk || - data->args->mode == zsvsheet_mode_remove || data->args->mode == zsvsheet_mode_clear) { + data->mode == zsvsheet_mode_add || data->mode == zsvsheet_mode_bulk || + data->mode == zsvsheet_mode_remove || data->mode == zsvsheet_mode_clear) { sqlite3_close(data->ctx->sqlite3.db); if (sqlite3_open_v2(data->ctx->src, &data->ctx->sqlite3.db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != SQLITE_OK) { @@ -184,134 +145,6 @@ static int zsv_overwrites_init(struct zsv_overwrite *data) { return err; } -static int zsv_overwrites_clear(struct zsv_overwrite_ctx *ctx) { - int err = 0; - sqlite3_stmt *query = NULL; - if (sqlite3_prepare_v2(ctx->sqlite3.db, "DELETE FROM overwrites", -1, &query, NULL) == SQLITE_OK) { - if (sqlite3_step(query) != SQLITE_DONE) { - err = 1; - fprintf(stderr, "Failed to step: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); - return err; - } - } else { - err = 1; - fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(ctx->sqlite3.db)); - } - if (query) - sqlite3_finalize(query); - return err; -} - -static int zsv_overwrites_remove(struct zsv_overwrite *data) { - int err = 0; - if (data->args->all) { - zsv_overwrites_clear(data->ctx); - return err; - } - - data->ctx->sqlite3.sql = data->overwrite->old_value.len > 0 - ? "DELETE FROM overwrites WHERE row = ? AND column = ? AND value = ?" - : "DELETE FROM overwrites WHERE row = ? AND column = ?"; - - sqlite3_stmt *query = NULL; - if (sqlite3_prepare_v2(data->ctx->sqlite3.db, data->ctx->sqlite3.sql, -1, &query, NULL) != SQLITE_OK) { - err = 1; - if (data->args->mode == zsvsheet_mode_bulk) - sqlite3_exec(data->ctx->sqlite3.db, "ROLLBACK", NULL, NULL, NULL); - fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); - return err; - } - sqlite3_bind_int64(query, 1, data->overwrite->row_ix); - sqlite3_bind_int64(query, 2, data->overwrite->col_ix); - if (data->overwrite->old_value.len > 0) - sqlite3_bind_text(query, 3, (const char *)data->overwrite->old_value.str, data->overwrite->old_value.len, - SQLITE_STATIC); - - if (sqlite3_step(query) != SQLITE_DONE) { - err = 1; - if (data->args->mode == zsvsheet_mode_bulk) - sqlite3_exec(data->ctx->sqlite3.db, "ROLLBACK", NULL, NULL, NULL); - fprintf(stderr, "Could not step: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); - return err; - } - if (query) - sqlite3_finalize(query); - return err; -} - -static int zsv_overwrites_insert(struct zsv_overwrite *data) { - if (!data->overwrite->val.str) - return 1; - if (data->args->force) - data->ctx->sqlite3.sql = - "INSERT OR REPLACE INTO overwrites (row, column, value, timestamp, author) VALUES (?, ?, ?, ?, ?)"; - else if (data->overwrite->old_value.len > 0) - data->ctx->sqlite3.sql = "INSERT OR REPLACE INTO overwrites (row, column, value, timestamp, author) SELECT ?, ?, " - "?, ?, ? WHERE EXISTS (SELECT 1 FROM overwrites WHERE value = ?)"; - else - data->ctx->sqlite3.sql = "INSERT INTO overwrites (row, column, value, timestamp, author) VALUES (?, ?, ?, ?, ?)"; - - int err = 0; - sqlite3_stmt *query = NULL; - - if (sqlite3_prepare_v2(data->ctx->sqlite3.db, data->ctx->sqlite3.sql, -1, &query, NULL) == SQLITE_OK) { - sqlite3_bind_int64(query, 1, data->overwrite->row_ix); - sqlite3_bind_int64(query, 2, data->overwrite->col_ix); - sqlite3_bind_text(query, 3, (const char *)data->overwrite->val.str, data->overwrite->val.len, SQLITE_STATIC); - if (data->overwrite->timestamp) - sqlite3_bind_int64(query, 4, data->overwrite->timestamp); - else - sqlite3_bind_null(query, 4); - if (data->overwrite->author.len > 0) - sqlite3_bind_text(query, 5, (const char *)data->overwrite->author.str, data->overwrite->author.len, - SQLITE_STATIC); - else - sqlite3_bind_text(query, 5, "", -1, SQLITE_STATIC); - - if (data->overwrite->old_value.len > 0) - sqlite3_bind_text(query, 6, (const char *)data->overwrite->old_value.str, data->overwrite->old_value.len, - SQLITE_STATIC); - - if (sqlite3_step(query) != SQLITE_DONE) { - err = 1; - if (data->args->mode == zsvsheet_mode_bulk) - sqlite3_exec(data->ctx->sqlite3.db, "ROLLBACK", NULL, NULL, NULL); - fprintf(stderr, "Value already exists at row %zu and column %zu, use --force to force insert\n", - data->overwrite->row_ix, data->overwrite->col_ix); - } - } else { - err = 1; - if (data->args->mode == zsvsheet_mode_bulk) - sqlite3_exec(data->ctx->sqlite3.db, "ROLLBACK", NULL, NULL, NULL); - fprintf(stderr, "Failed to prepare2: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); - } - - if (query) - sqlite3_finalize(query); - - return err; -} - -static void zsv_overwrites_bulk(struct zsv_overwrite *data) { - free(data->ctx->src); - data->ctx->src = (char *)data->args->bulk_file; - if (zsv_overwrite_open(data->ctx) != zsv_status_ok) { - fprintf(stderr, "Could not open\n"); - return; - } - data->overwrite->have = 1; - data->ctx->row_ix = 1; - if (sqlite3_exec(data->ctx->sqlite3.db, "BEGIN TRANSACTION", NULL, NULL, NULL) == SQLITE_OK) { - while (data->ctx->next(data->ctx, data->overwrite) == zsv_status_ok && data->overwrite->have) { - data->next(data); - data->overwrite->timestamp = 0; - } - if (sqlite3_exec(data->ctx->sqlite3.db, "COMMIT", NULL, NULL, NULL) != SQLITE_OK) - fprintf(stderr, "Could not commit changes: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); - } else - fprintf(stderr, "Could not begin transaction: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); -} - static int zsv_overwrites_free(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, const struct zsv_overwrite_args *args, zsv_csv_writer writer) { if (writer) @@ -322,7 +155,6 @@ static int zsv_overwrites_free(struct zsv_overwrite_ctx *ctx, struct zsv_overwri if (overwrite && args->mode != zsvsheet_mode_bulk) free(overwrite->val.str); - // sqlite3_shutdown(); return 0; } @@ -355,7 +187,7 @@ static int show_all_overwrites(struct zsv_overwrite *data, zsv_csv_writer writer zsv_writer_cell(writer, 0, (const unsigned char *)"author", 6, 0); struct zsv_overwrite_data odata = {.have = 1}; while ((data->ctx->next(data->ctx, &odata) == zsv_status_ok) && odata.have) { - if (data->args->a1) { + if (data->a1) { char *a1_ix = row_col_to_a1(odata.col_ix + 1, odata.row_ix); if (a1_ix) zsv_writer_cell(writer, 1, (unsigned char *)a1_ix, strlen(a1_ix), 0); @@ -436,12 +268,10 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op (void)(opts); (void)(custom_prop_handler); (void)(opts_used); - struct zsv_overwrite *data = calloc(1, sizeof(struct zsv_overwrite)); struct zsv_overwrite_args args = {0}; // By default, save timestamps struct zsv_overwrite_data overwrite = {0}; overwrite.timestamp = (size_t)time(NULL); - struct zsv_csv_writer_options writer_opts = {0}; char *filepath = (char *)argv[1]; args.filepath = filepath; @@ -451,8 +281,8 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op if (!strcmp(opt, "-f") || !strcmp(opt, "--force")) { args.force = 1; } else if (!strcmp(opt, "--old-value")) { - overwrite.old_value.str = (unsigned char *)argv[++i]; - overwrite.old_value.len = strlen((const char *)overwrite.old_value.str); + overwrite.old_value.str = (unsigned char *)strdup(argv[++i]); + overwrite.old_value.len = strlen((const char*)overwrite.old_value.str); } else if (!strcmp(opt, "--no-timestamp")) { overwrite.timestamp = 0; } else if (!strcmp(opt, "--A1")) { @@ -466,7 +296,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op args.mode = zsvsheet_mode_add; err = zsv_overwrite_parse_pos(&overwrite, argv[++i]); overwrite.val.str = (unsigned char *)strdup(argv[++i]); - overwrite.val.len = strlen((const char *)overwrite.val.str); + overwrite.val.len= strlen((const char*)overwrite.val.str); if (err || !overwrite.val.str) { fprintf(stderr, "Expected row, column, and value\n"); err = 1; @@ -493,7 +323,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op if (argc - i > 1) { args.mode = zsvsheet_mode_bulk; args.bulk_file = (unsigned char *)strdup(argv[++i]); - data->next = zsv_overwrites_insert; + args.next = zsv_overwrite_writer_add; } else { fprintf(stderr, "Expected overwrite filename\n"); err = 1; @@ -502,7 +332,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op if (argc - i > 1) { args.mode = zsvsheet_mode_bulk; args.bulk_file = (unsigned char *)strdup(argv[++i]); - data->next = zsv_overwrites_remove; + args.next = zsv_overwrite_writer_remove; } else { fprintf(stderr, "Expected overwrite filename\n"); err = 1; @@ -516,16 +346,13 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op } } + args.overwrite = &overwrite; + char *overwrites_fn = (char *)zsv_cache_filepath((const unsigned char *)filepath, zsv_cache_type_overwrite, 0, 0); ctx_opts.src = (char *)overwrites_fn; - - struct zsv_overwrite_ctx *ctx = zsv_overwrite_context_new(&ctx_opts); + struct zsv_overwrite *data = zsv_overwrite_writer_new(&args, &ctx_opts); free(overwrites_fn); - data->ctx = ctx; - data->args = &args; - data->overwrite = &overwrite; - if (args.mode == zsvsheet_mode_list) { if ((err = (zsv_overwrite_open(data->ctx) != zsv_status_ok))) fprintf(stderr, "Failed to initalize database\n"); @@ -534,31 +361,24 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op fprintf(stderr, "Failed to initalize database\n"); } - zsv_csv_writer writer = zsv_writer_new(&writer_opts); - if (err) { - zsv_overwrites_free(ctx, &overwrite, &args, writer); + zsv_overwrite_writer_delete(data->ctx, &overwrite, &args, data->writer); return err; } - if (args.mode == zsvsheet_mode_list) - show_all_overwrites(data, writer); - else if (args.mode == zsvsheet_mode_clear) - zsv_overwrites_clear(ctx); - else if (args.mode == zsvsheet_mode_add && ctx->sqlite3.db) - zsv_overwrites_insert(data); - else if (args.mode == zsvsheet_mode_remove && ctx->sqlite3.db) - zsv_overwrites_remove(data); - else if (args.mode == zsvsheet_mode_bulk && ctx->sqlite3.db) { - zsv_overwrites_bulk(data); + if (data->mode == zsvsheet_mode_list) + show_all_overwrites(data, data->writer); + else if (data->mode == zsvsheet_mode_clear) + zsv_overwrite_writer_clear(data); + else if (data->mode == zsvsheet_mode_add && data->ctx->sqlite3.db) + zsv_overwrite_writer_add(data); + else if (data->mode == zsvsheet_mode_remove && data->ctx->sqlite3.db) + zsv_overwrite_writer_remove(data); + else if (data->mode == zsvsheet_mode_bulk && data->ctx->sqlite3.db) { + zsv_overwrite_writer_bulk(data); } - zsv_overwrites_free(ctx, &overwrite, &args, writer); - - if (data->args->all) - remove(ctx->src); - if (data) - free(data); + zsv_overwrite_writer_delete(data); return err; } diff --git a/app/utils/overwrite_writer.c b/app/utils/overwrite_writer.c new file mode 100644 index 00000000..7891a5ca --- /dev/null +++ b/app/utils/overwrite_writer.c @@ -0,0 +1,175 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +struct zsv_overwrite *zsv_overwrite_writer_new(struct zsv_overwrite_args *args, struct zsv_overwrite_opts *ctx_opts) { + struct zsv_overwrite *data = calloc(1, sizeof(*data)); + data->overwrite = calloc(1, sizeof(*data->overwrite)); + data->overwrite->old_value = args->overwrite->old_value; + data->force = args->force; + data->all = args->all; + data->a1 = args->a1; + data->bulk_file = args->bulk_file; + data->mode = args->mode; + data->ctx = zsv_overwrite_context_new(ctx_opts); + data->overwrite = args->overwrite; + data->next = args->next; + struct zsv_csv_writer_options writer_opts = {0}; + data->writer = zsv_writer_new(&writer_opts); + return data; +} + +void zsv_overwrite_writer_delete(struct zsv_overwrite *data) { + //if(data->overwrite) + //free(data->overwrite); + if(data->writer) + zsv_writer_delete(data->writer); + if(data->ctx) + zsv_overwrite_context_delete(data->ctx); + + if (data->overwrite && data->mode != zsvsheet_mode_bulk) + free(data->overwrite->val.str); + + if (data->all) + remove(data->ctx->src); + free(data); +} + +enum zsv_status zsv_overwrite_writer_add(struct zsv_overwrite *data) { + if (!data->overwrite->val.str) + return 1; + if (data->force) + data->ctx->sqlite3.sql = + "INSERT OR REPLACE INTO overwrites (row, column, value, timestamp, author) VALUES (?, ?, ?, ?, ?)"; + else if (data->overwrite->old_value.len > 0) + data->ctx->sqlite3.sql = "INSERT OR REPLACE INTO overwrites (row, column, value, timestamp, author) SELECT ?, ?, " + "?, ?, ? WHERE EXISTS (SELECT 1 FROM overwrites WHERE value = ?)"; + else + data->ctx->sqlite3.sql = "INSERT INTO overwrites (row, column, value, timestamp, author) VALUES (?, ?, ?, ?, ?)"; + + int err = 0; + sqlite3_stmt *query = NULL; + + if (sqlite3_prepare_v2(data->ctx->sqlite3.db, data->ctx->sqlite3.sql, -1, &query, NULL) == SQLITE_OK) { + sqlite3_bind_int64(query, 1, data->overwrite->row_ix); + sqlite3_bind_int64(query, 2, data->overwrite->col_ix); + sqlite3_bind_text(query, 3, (const char *)data->overwrite->val.str, data->overwrite->val.len, SQLITE_STATIC); + if (data->overwrite->timestamp) + sqlite3_bind_int64(query, 4, data->overwrite->timestamp); + else + sqlite3_bind_null(query, 4); + if (data->overwrite->author.len > 0) + sqlite3_bind_text(query, 5, (const char *)data->overwrite->author.str, data->overwrite->author.len, + SQLITE_STATIC); + else + sqlite3_bind_text(query, 5, "", -1, SQLITE_STATIC); + + if (data->overwrite->old_value.len > 0) + sqlite3_bind_text(query, 6, (const char *)data->overwrite->old_value.str, data->overwrite->old_value.len, + SQLITE_STATIC); + + if (sqlite3_step(query) != SQLITE_DONE) { + err = 1; + if (data->mode == zsvsheet_mode_bulk) + sqlite3_exec(data->ctx->sqlite3.db, "ROLLBACK", NULL, NULL, NULL); + fprintf(stderr, "Value already exists at row %zu and column %zu, use --force to force insert\n", + data->overwrite->row_ix, data->overwrite->col_ix); + } + } else { + err = 1; + if (data->mode == zsvsheet_mode_bulk) + sqlite3_exec(data->ctx->sqlite3.db, "ROLLBACK", NULL, NULL, NULL); + fprintf(stderr, "Failed to prepare2: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); + } + + if (query) + sqlite3_finalize(query); + + return err; + +} + +enum zsv_status zsv_overwrite_writer_remove(struct zsv_overwrite *data) { + int err = 0; + if (data->all) { + zsv_overwrite_writer_clear(data); + return err; + } + + data->ctx->sqlite3.sql = data->overwrite->old_value.len > 0 + ? "DELETE FROM overwrites WHERE row = ? AND column = ? AND value = ?" + : "DELETE FROM overwrites WHERE row = ? AND column = ?"; + + sqlite3_stmt *query = NULL; + if (sqlite3_prepare_v2(data->ctx->sqlite3.db, data->ctx->sqlite3.sql, -1, &query, NULL) != SQLITE_OK) { + err = 1; + if (data->mode == zsvsheet_mode_bulk) + sqlite3_exec(data->ctx->sqlite3.db, "ROLLBACK", NULL, NULL, NULL); + fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); + return err; + } + sqlite3_bind_int64(query, 1, data->overwrite->row_ix); + sqlite3_bind_int64(query, 2, data->overwrite->col_ix); + if (data->overwrite->old_value.len > 0) + sqlite3_bind_text(query, 3, (const char *)data->overwrite->old_value.str, data->overwrite->old_value.len, + SQLITE_STATIC); + + if (sqlite3_step(query) != SQLITE_DONE) { + err = 1; + if (data->mode == zsvsheet_mode_bulk) + sqlite3_exec(data->ctx->sqlite3.db, "ROLLBACK", NULL, NULL, NULL); + fprintf(stderr, "Could not step: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); + return err; + } + if (query) + sqlite3_finalize(query); + return err; +} + +enum zsv_status zsv_overwrite_writer_bulk(struct zsv_overwrite *data) { + free(data->ctx->src); + data->ctx->src = (char *)data->bulk_file; + if (zsv_overwrite_open(data->ctx) != zsv_status_ok) { + fprintf(stderr, "Could not open\n"); + return zsv_status_error; + } + data->overwrite->have = 1; + data->ctx->row_ix = 1; + if (sqlite3_exec(data->ctx->sqlite3.db, "BEGIN TRANSACTION", NULL, NULL, NULL) == SQLITE_OK) { + while (data->ctx->next(data->ctx, data->overwrite) == zsv_status_ok && data->overwrite->have) { + data->next(data); + data->overwrite->timestamp = 0; + } + if (sqlite3_exec(data->ctx->sqlite3.db, "COMMIT", NULL, NULL, NULL) != SQLITE_OK) + fprintf(stderr, "Could not commit changes: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); + } else + fprintf(stderr, "Could not begin transaction: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); + return zsv_status_ok; +} + +enum zsv_status zsv_overwrite_writer_clear(struct zsv_overwrite *data) { + int err = 0; + sqlite3_stmt *query = NULL; + if (sqlite3_prepare_v2(data->ctx->sqlite3.db, "DELETE FROM overwrites", -1, &query, NULL) == SQLITE_OK) { + if (sqlite3_step(query) != SQLITE_DONE) { + err = 1; + fprintf(stderr, "Failed to step: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); + return err; + } + } else { + err = 1; + fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); + } + if (query) + sqlite3_finalize(query); + return err; + return zsv_status_ok; +} + diff --git a/include/zsv/utils/overwrite_writer.h b/include/zsv/utils/overwrite_writer.h new file mode 100644 index 00000000..82ede346 --- /dev/null +++ b/include/zsv/utils/overwrite_writer.h @@ -0,0 +1,53 @@ +#include + +enum zsvsheet_mode { + zsvsheet_mode_add, + zsvsheet_mode_remove, + zsvsheet_mode_clear, + zsvsheet_mode_list, + zsvsheet_mode_bulk, +}; + +struct zsv_overwrite { + struct zsv_overwrite_ctx *ctx; + struct zsv_overwrite_data *overwrite; + zsv_csv_writer writer; + enum zsv_status (*next)(struct zsv_overwrite *data); + enum zsvsheet_mode mode; + unsigned char force : 1; + unsigned char a1 : 1; + unsigned char all : 1; + unsigned char *bulk_file; + // bulk indexes + size_t row_ix; + size_t col_ix; + size_t val_ix; + size_t old_value_ix; + size_t timestamp_ix; + size_t author_ix; +}; + +struct zsv_overwrite_args { + char *filepath; + enum zsv_status (*next)(struct zsv_overwrite *data); + // options + unsigned char force : 1; + unsigned char a1 : 1; + unsigned char all : 1; + unsigned char *bulk_file; + struct zsv_overwrite_data *overwrite; + // commands + enum zsvsheet_mode mode; +}; + +struct zsv_overwrite *zsv_overwrite_writer_new(struct zsv_overwrite_args *args, struct zsv_overwrite_opts *ctx_opts); + +void zsv_overwrite_writer_delete(); + +enum zsv_status zsv_overwrite_writer_add(struct zsv_overwrite *data); + +enum zsv_status zsv_overwrite_writer_remove(struct zsv_overwrite *data); + +enum zsv_status zsv_overwrite_writer_bulk(struct zsv_overwrite *data); + +enum zsv_status zsv_overwrite_writer_clear(struct zsv_overwrite *data); From e61dba3c53bd16b07a84c12c6153c60c40ae45bf Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Thu, 21 Nov 2024 20:42:29 -0500 Subject: [PATCH 52/62] format --- app/overwrite.c | 8 ++++---- app/utils/overwrite_writer.c | 10 ++++------ include/zsv/utils/overwrite_writer.h | 2 +- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index b870fbcc..428d0c72 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -94,8 +94,8 @@ static int zsv_overwrites_init(struct zsv_overwrite *data) { sqlite3_stmt *query = NULL; if (sqlite3_open_v2(data->ctx->src, &data->ctx->sqlite3.db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK || - data->mode == zsvsheet_mode_add || data->mode == zsvsheet_mode_bulk || - data->mode == zsvsheet_mode_remove || data->mode == zsvsheet_mode_clear) { + data->mode == zsvsheet_mode_add || data->mode == zsvsheet_mode_bulk || data->mode == zsvsheet_mode_remove || + data->mode == zsvsheet_mode_clear) { sqlite3_close(data->ctx->sqlite3.db); if (sqlite3_open_v2(data->ctx->src, &data->ctx->sqlite3.db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != SQLITE_OK) { @@ -282,7 +282,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op args.force = 1; } else if (!strcmp(opt, "--old-value")) { overwrite.old_value.str = (unsigned char *)strdup(argv[++i]); - overwrite.old_value.len = strlen((const char*)overwrite.old_value.str); + overwrite.old_value.len = strlen((const char *)overwrite.old_value.str); } else if (!strcmp(opt, "--no-timestamp")) { overwrite.timestamp = 0; } else if (!strcmp(opt, "--A1")) { @@ -296,7 +296,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op args.mode = zsvsheet_mode_add; err = zsv_overwrite_parse_pos(&overwrite, argv[++i]); overwrite.val.str = (unsigned char *)strdup(argv[++i]); - overwrite.val.len= strlen((const char*)overwrite.val.str); + overwrite.val.len = strlen((const char *)overwrite.val.str); if (err || !overwrite.val.str) { fprintf(stderr, "Expected row, column, and value\n"); err = 1; diff --git a/app/utils/overwrite_writer.c b/app/utils/overwrite_writer.c index 7891a5ca..dfb3469e 100644 --- a/app/utils/overwrite_writer.c +++ b/app/utils/overwrite_writer.c @@ -27,11 +27,11 @@ struct zsv_overwrite *zsv_overwrite_writer_new(struct zsv_overwrite_args *args, } void zsv_overwrite_writer_delete(struct zsv_overwrite *data) { - //if(data->overwrite) - //free(data->overwrite); - if(data->writer) + // if(data->overwrite) + // free(data->overwrite); + if (data->writer) zsv_writer_delete(data->writer); - if(data->ctx) + if (data->ctx) zsv_overwrite_context_delete(data->ctx); if (data->overwrite && data->mode != zsvsheet_mode_bulk) @@ -93,7 +93,6 @@ enum zsv_status zsv_overwrite_writer_add(struct zsv_overwrite *data) { sqlite3_finalize(query); return err; - } enum zsv_status zsv_overwrite_writer_remove(struct zsv_overwrite *data) { @@ -172,4 +171,3 @@ enum zsv_status zsv_overwrite_writer_clear(struct zsv_overwrite *data) { return err; return zsv_status_ok; } - diff --git a/include/zsv/utils/overwrite_writer.h b/include/zsv/utils/overwrite_writer.h index 82ede346..0ec8e851 100644 --- a/include/zsv/utils/overwrite_writer.h +++ b/include/zsv/utils/overwrite_writer.h @@ -49,5 +49,5 @@ enum zsv_status zsv_overwrite_writer_add(struct zsv_overwrite *data); enum zsv_status zsv_overwrite_writer_remove(struct zsv_overwrite *data); enum zsv_status zsv_overwrite_writer_bulk(struct zsv_overwrite *data); - + enum zsv_status zsv_overwrite_writer_clear(struct zsv_overwrite *data); From 45ed974399412b9dd8710be4c8c75b8d492ab07c Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Thu, 21 Nov 2024 20:59:38 -0500 Subject: [PATCH 53/62] Change writer to use zsv_status instead of int --- app/overwrite.c | 10 +++++----- app/utils/overwrite_writer.c | 25 +++++++++++-------------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 428d0c72..7a6f2ed8 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -367,15 +367,15 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op } if (data->mode == zsvsheet_mode_list) - show_all_overwrites(data, data->writer); + err = show_all_overwrites(data, data->writer); else if (data->mode == zsvsheet_mode_clear) - zsv_overwrite_writer_clear(data); + err = zsv_overwrite_writer_clear(data); else if (data->mode == zsvsheet_mode_add && data->ctx->sqlite3.db) - zsv_overwrite_writer_add(data); + err = zsv_overwrite_writer_add(data); else if (data->mode == zsvsheet_mode_remove && data->ctx->sqlite3.db) - zsv_overwrite_writer_remove(data); + err = zsv_overwrite_writer_remove(data); else if (data->mode == zsvsheet_mode_bulk && data->ctx->sqlite3.db) { - zsv_overwrite_writer_bulk(data); + err = zsv_overwrite_writer_bulk(data); } zsv_overwrite_writer_delete(data); diff --git a/app/utils/overwrite_writer.c b/app/utils/overwrite_writer.c index dfb3469e..f95bb1a6 100644 --- a/app/utils/overwrite_writer.c +++ b/app/utils/overwrite_writer.c @@ -27,8 +27,6 @@ struct zsv_overwrite *zsv_overwrite_writer_new(struct zsv_overwrite_args *args, } void zsv_overwrite_writer_delete(struct zsv_overwrite *data) { - // if(data->overwrite) - // free(data->overwrite); if (data->writer) zsv_writer_delete(data->writer); if (data->ctx) @@ -44,7 +42,7 @@ void zsv_overwrite_writer_delete(struct zsv_overwrite *data) { enum zsv_status zsv_overwrite_writer_add(struct zsv_overwrite *data) { if (!data->overwrite->val.str) - return 1; + return zsv_status_error; if (data->force) data->ctx->sqlite3.sql = "INSERT OR REPLACE INTO overwrites (row, column, value, timestamp, author) VALUES (?, ?, ?, ?, ?)"; @@ -54,7 +52,7 @@ enum zsv_status zsv_overwrite_writer_add(struct zsv_overwrite *data) { else data->ctx->sqlite3.sql = "INSERT INTO overwrites (row, column, value, timestamp, author) VALUES (?, ?, ?, ?, ?)"; - int err = 0; + enum zsv_status err = zsv_status_ok; sqlite3_stmt *query = NULL; if (sqlite3_prepare_v2(data->ctx->sqlite3.db, data->ctx->sqlite3.sql, -1, &query, NULL) == SQLITE_OK) { @@ -76,14 +74,14 @@ enum zsv_status zsv_overwrite_writer_add(struct zsv_overwrite *data) { SQLITE_STATIC); if (sqlite3_step(query) != SQLITE_DONE) { - err = 1; + err = zsv_status_error; if (data->mode == zsvsheet_mode_bulk) sqlite3_exec(data->ctx->sqlite3.db, "ROLLBACK", NULL, NULL, NULL); fprintf(stderr, "Value already exists at row %zu and column %zu, use --force to force insert\n", data->overwrite->row_ix, data->overwrite->col_ix); } } else { - err = 1; + err = zsv_status_error; if (data->mode == zsvsheet_mode_bulk) sqlite3_exec(data->ctx->sqlite3.db, "ROLLBACK", NULL, NULL, NULL); fprintf(stderr, "Failed to prepare2: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); @@ -96,9 +94,9 @@ enum zsv_status zsv_overwrite_writer_add(struct zsv_overwrite *data) { } enum zsv_status zsv_overwrite_writer_remove(struct zsv_overwrite *data) { - int err = 0; + enum zsv_status err = zsv_status_ok; if (data->all) { - zsv_overwrite_writer_clear(data); + err = zsv_overwrite_writer_clear(data); return err; } @@ -108,7 +106,7 @@ enum zsv_status zsv_overwrite_writer_remove(struct zsv_overwrite *data) { sqlite3_stmt *query = NULL; if (sqlite3_prepare_v2(data->ctx->sqlite3.db, data->ctx->sqlite3.sql, -1, &query, NULL) != SQLITE_OK) { - err = 1; + err = zsv_status_error; if (data->mode == zsvsheet_mode_bulk) sqlite3_exec(data->ctx->sqlite3.db, "ROLLBACK", NULL, NULL, NULL); fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); @@ -121,7 +119,7 @@ enum zsv_status zsv_overwrite_writer_remove(struct zsv_overwrite *data) { SQLITE_STATIC); if (sqlite3_step(query) != SQLITE_DONE) { - err = 1; + err = zsv_status_error; if (data->mode == zsvsheet_mode_bulk) sqlite3_exec(data->ctx->sqlite3.db, "ROLLBACK", NULL, NULL, NULL); fprintf(stderr, "Could not step: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); @@ -154,20 +152,19 @@ enum zsv_status zsv_overwrite_writer_bulk(struct zsv_overwrite *data) { } enum zsv_status zsv_overwrite_writer_clear(struct zsv_overwrite *data) { - int err = 0; + enum zsv_status err = zsv_status_ok; sqlite3_stmt *query = NULL; if (sqlite3_prepare_v2(data->ctx->sqlite3.db, "DELETE FROM overwrites", -1, &query, NULL) == SQLITE_OK) { if (sqlite3_step(query) != SQLITE_DONE) { - err = 1; + err = zsv_status_error; fprintf(stderr, "Failed to step: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); return err; } } else { - err = 1; + err = zsv_status_error; fprintf(stderr, "Could not prepare: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); } if (query) sqlite3_finalize(query); return err; - return zsv_status_ok; } From db550e968b6522d4cb0a8666a1547204e19ad8bf Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Thu, 21 Nov 2024 21:50:58 -0500 Subject: [PATCH 54/62] fix old-value test error --- app/test/overwrite/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/test/overwrite/Makefile b/app/test/overwrite/Makefile index 68cafce7..64d70108 100644 --- a/app/test/overwrite/Makefile +++ b/app/test/overwrite/Makefile @@ -99,7 +99,7 @@ test-old-value: @${PREFIX} ${EXE} dummy2.csv add 2-1 V2 --no-timestamp @${PREFIX} ${EXE} dummy2.csv add 3-1 V3 --no-timestamp @${PREFIX} ${EXE} dummy2.csv add 4-1 V4 --no-timestamp - @${PREFIX} ${EXE} dummy2.csv add 3-1 NEW_V4 --no-timestamp 2> ${TMP_DIR}/$@.out + @${PREFIX} ${EXE} dummy2.csv add 3-1 NEW_V4 --no-timestamp 2> ${TMP_DIR}/$@.out @${CMP} ${TMP_DIR}/$@.out expected/$@-fail.out && ${TEST_PASS} || ${TEST_FAIL} @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,V1,,\n2,1,V2,,\n3,1,V3,,\n4,1,V4,,\n\"`" ] \ && ${TEST_PASS} || ${TEST_FAIL} From 476ffe157c92d5c78ff86ba18f9c40987377e50a Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Thu, 21 Nov 2024 21:54:35 -0500 Subject: [PATCH 55/62] modify makefile --- app/test/overwrite/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/test/overwrite/Makefile b/app/test/overwrite/Makefile index 64d70108..b538f735 100644 --- a/app/test/overwrite/Makefile +++ b/app/test/overwrite/Makefile @@ -99,8 +99,8 @@ test-old-value: @${PREFIX} ${EXE} dummy2.csv add 2-1 V2 --no-timestamp @${PREFIX} ${EXE} dummy2.csv add 3-1 V3 --no-timestamp @${PREFIX} ${EXE} dummy2.csv add 4-1 V4 --no-timestamp - @${PREFIX} ${EXE} dummy2.csv add 3-1 NEW_V4 --no-timestamp 2> ${TMP_DIR}/$@.out - @${CMP} ${TMP_DIR}/$@.out expected/$@-fail.out && ${TEST_PASS} || ${TEST_FAIL} + @${PREFIX} ${EXE} dummy2.csv add 3-1 NEW_V4 --no-timestamp 2> $@.out + @${CMP} $@.out expected/$@-fail.out && ${TEST_PASS} || ${TEST_FAIL} @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,V1,,\n2,1,V2,,\n3,1,V3,,\n4,1,V4,,\n\"`" ] \ && ${TEST_PASS} || ${TEST_FAIL} @${PREFIX} ${EXE} dummy2.csv remove 2-1 --old-value V3 From 7d327add2108db4d3eec5711ba48c644f2ed781b Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Thu, 21 Nov 2024 22:28:14 -0500 Subject: [PATCH 56/62] fix issue in makefile --- app/test/overwrite/Makefile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/test/overwrite/Makefile b/app/test/overwrite/Makefile index b538f735..2d083063 100644 --- a/app/test/overwrite/Makefile +++ b/app/test/overwrite/Makefile @@ -99,9 +99,7 @@ test-old-value: @${PREFIX} ${EXE} dummy2.csv add 2-1 V2 --no-timestamp @${PREFIX} ${EXE} dummy2.csv add 3-1 V3 --no-timestamp @${PREFIX} ${EXE} dummy2.csv add 4-1 V4 --no-timestamp - @${PREFIX} ${EXE} dummy2.csv add 3-1 NEW_V4 --no-timestamp 2> $@.out - @${CMP} $@.out expected/$@-fail.out && ${TEST_PASS} || ${TEST_FAIL} - @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,V1,,\n2,1,V2,,\n3,1,V3,,\n4,1,V4,,\n\"`" ] \ + @${CHECK} [ "`printf \"$$(${PREFIX} ${EXE} dummy2.csv add 3-1 NEW_V4 --no-timestamp 2>&1)\"`" = "`cat expected/$@-fail.out`" ] \ && ${TEST_PASS} || ${TEST_FAIL} @${PREFIX} ${EXE} dummy2.csv remove 2-1 --old-value V3 @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,1,V1,,\n2,1,V2,,\n3,1,V3,,\n4,1,V4,,\n\"`" ] \ From b2e8a9b78532990b51687d493a517a54ef411165 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Thu, 21 Nov 2024 22:32:37 -0500 Subject: [PATCH 57/62] Fix issue with force test as well --- app/test/overwrite/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/test/overwrite/Makefile b/app/test/overwrite/Makefile index 2d083063..75546b8f 100644 --- a/app/test/overwrite/Makefile +++ b/app/test/overwrite/Makefile @@ -118,8 +118,8 @@ test-force: @${PREFIX} ${EXE} dummy2.csv add 2-2 VAL2 --no-timestamp @${PREFIX} ${EXE} dummy2.csv add 2-3 VAL3 --no-timestamp @${PREFIX} ${EXE} dummy2.csv add 2-4 VAL4 --no-timestamp - @${EXE} dummy2.csv add 2-4 NEW_VAL4 --no-timestamp 2> ${TMP_DIR}/$@.out - @${CMP} ${TMP_DIR}/$@.out expected/$@-fail.out && ${TEST_PASS} || ${TEST_FAIL} + @${CHECK} [ "`printf \"$$(${PREFIX} ${EXE} dummy2.csv add 2-4 NEW_VAL4 --no-timestamp 2>&1)\"`" = "`cat expected/$@-fail.out`" ] \ + && ${TEST_PASS} || ${TEST_FAIL} @${CHECK} [ "`${EXE} dummy2.csv list`" = "`printf \"$(HEADER)\n1,2,VAL1,,\n2,2,VAL2,,\n2,3,VAL3,,\n2,4,VAL4,,\n\"`" ] \ && ${TEST_PASS} || ${TEST_FAIL} @${PREFIX} ${EXE} dummy2.csv add 2-4 NEW_VAL4 --no-timestamp --force From 22088e638231b882877b2d7734c6a1a99fd769cc Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Fri, 22 Nov 2024 19:18:52 -0500 Subject: [PATCH 58/62] Update functions to use zsv_status and move init into overwrite_open --- app/overwrite.c | 99 +++++------------------------------- app/utils/overwrite_writer.c | 77 +++++++++++++++++++++++++++- 2 files changed, 89 insertions(+), 87 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 7a6f2ed8..0d34bc0c 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -18,8 +18,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -83,68 +83,6 @@ static int zsv_overwrite_usage() { return 1; } -static int zsv_overwrites_init(struct zsv_overwrite *data) { - int err = 0; - if (zsv_mkdirs(data->ctx->src, 1) && !zsv_file_readable(data->ctx->src, &err, NULL)) { - err = 1; - perror(data->ctx->src); - return err; - } - - sqlite3_stmt *query = NULL; - - if (sqlite3_open_v2(data->ctx->src, &data->ctx->sqlite3.db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK || - data->mode == zsvsheet_mode_add || data->mode == zsvsheet_mode_bulk || data->mode == zsvsheet_mode_remove || - data->mode == zsvsheet_mode_clear) { - sqlite3_close(data->ctx->sqlite3.db); - if (sqlite3_open_v2(data->ctx->src, &data->ctx->sqlite3.db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != - SQLITE_OK) { - err = 1; - fprintf(stderr, "Failed to open conn: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); - return err; - } - - if (sqlite3_exec(data->ctx->sqlite3.db, "PRAGMA foreign_keys = on", NULL, NULL, NULL) != SQLITE_OK) { - err = 1; - fprintf(stderr, "Could not enable foreign keys: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); - return err; - } - - if (sqlite3_prepare_v2(data->ctx->sqlite3.db, - "CREATE TABLE IF NOT EXISTS overwrites ( row integer, column integer, value string, " - "timestamp varchar(25), author varchar(25) );", - -1, &query, NULL) == SQLITE_OK) { - if (sqlite3_step(query) != SQLITE_DONE) { - err = 1; - fprintf(stderr, "Failed to step: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); - return err; - } - } else { - err = 1; - fprintf(stderr, "Failed to prepare1: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); - } - - if (query) - sqlite3_finalize(query); - - if (sqlite3_prepare_v2(data->ctx->sqlite3.db, "CREATE UNIQUE INDEX overwrites_uix ON overwrites (row, column)", -1, - &query, NULL) == SQLITE_OK) { - if (sqlite3_step(query) != SQLITE_DONE) { - err = 1; - fprintf(stderr, "Failed to step: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); - return err; - } - if (query) - sqlite3_finalize(query); - } - } - - if (!data->ctx->sqlite3.db) - err = 1; - - return err; -} - static int zsv_overwrites_free(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, const struct zsv_overwrite_args *args, zsv_csv_writer writer) { if (writer) @@ -353,29 +291,18 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op struct zsv_overwrite *data = zsv_overwrite_writer_new(&args, &ctx_opts); free(overwrites_fn); - if (args.mode == zsvsheet_mode_list) { - if ((err = (zsv_overwrite_open(data->ctx) != zsv_status_ok))) - fprintf(stderr, "Failed to initalize database\n"); - } else { - if ((err = zsv_overwrites_init(data))) - fprintf(stderr, "Failed to initalize database\n"); - } - - if (err) { - zsv_overwrite_writer_delete(data->ctx, &overwrite, &args, data->writer); - return err; - } - - if (data->mode == zsvsheet_mode_list) - err = show_all_overwrites(data, data->writer); - else if (data->mode == zsvsheet_mode_clear) - err = zsv_overwrite_writer_clear(data); - else if (data->mode == zsvsheet_mode_add && data->ctx->sqlite3.db) - err = zsv_overwrite_writer_add(data); - else if (data->mode == zsvsheet_mode_remove && data->ctx->sqlite3.db) - err = zsv_overwrite_writer_remove(data); - else if (data->mode == zsvsheet_mode_bulk && data->ctx->sqlite3.db) { - err = zsv_overwrite_writer_bulk(data); + if (!err && data) { + if (data->mode == zsvsheet_mode_list) + err = show_all_overwrites(data, data->writer) == zsv_status_ok; + else if (data->mode == zsvsheet_mode_clear) + err = zsv_overwrite_writer_clear(data) == zsv_status_ok; + else if (data->mode == zsvsheet_mode_add && data->ctx->sqlite3.db) + err = zsv_overwrite_writer_add(data) == zsv_status_ok; + else if (data->mode == zsvsheet_mode_remove && data->ctx->sqlite3.db) + err = zsv_overwrite_writer_remove(data) == zsv_status_ok; + else if (data->mode == zsvsheet_mode_bulk && data->ctx->sqlite3.db) { + err = zsv_overwrite_writer_bulk(data) == zsv_status_ok; + } } zsv_overwrite_writer_delete(data); diff --git a/app/utils/overwrite_writer.c b/app/utils/overwrite_writer.c index f95bb1a6..2be7ea2e 100644 --- a/app/utils/overwrite_writer.c +++ b/app/utils/overwrite_writer.c @@ -6,9 +6,74 @@ #include #include +#include +#include #include #include +static enum zsv_status zsv_overwrite_writer_init(struct zsv_overwrite *data) { + enum zsv_status err = zsv_status_ok; + int tmp_err = 0; + if (zsv_mkdirs(data->ctx->src, 1) && !zsv_file_readable(data->ctx->src, &tmp_err, NULL)) { + err = zsv_status_error; + perror(data->ctx->src); + return err; + } + + sqlite3_stmt *query = NULL; + + if (sqlite3_open_v2(data->ctx->src, &data->ctx->sqlite3.db, SQLITE_OPEN_READONLY, NULL) != SQLITE_OK || + data->mode == zsvsheet_mode_add || data->mode == zsvsheet_mode_bulk || data->mode == zsvsheet_mode_remove || + data->mode == zsvsheet_mode_clear) { + sqlite3_close(data->ctx->sqlite3.db); + if (sqlite3_open_v2(data->ctx->src, &data->ctx->sqlite3.db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != + SQLITE_OK) { + err = zsv_status_error; + fprintf(stderr, "Failed to open conn: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); + return err; + } + + if (sqlite3_exec(data->ctx->sqlite3.db, "PRAGMA foreign_keys = on", NULL, NULL, NULL) != SQLITE_OK) { + err = zsv_status_error; + fprintf(stderr, "Could not enable foreign keys: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); + return err; + } + + if (sqlite3_prepare_v2(data->ctx->sqlite3.db, + "CREATE TABLE IF NOT EXISTS overwrites ( row integer, column integer, value string, " + "timestamp varchar(25), author varchar(25) );", + -1, &query, NULL) == SQLITE_OK) { + if (sqlite3_step(query) != SQLITE_DONE) { + err = zsv_status_error; + fprintf(stderr, "Failed to step: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); + return err; + } + } else { + err = zsv_status_error; + fprintf(stderr, "Failed to prepare1: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); + } + + if (query) + sqlite3_finalize(query); + + if (sqlite3_prepare_v2(data->ctx->sqlite3.db, "CREATE UNIQUE INDEX overwrites_uix ON overwrites (row, column)", -1, + &query, NULL) == SQLITE_OK) { + if (sqlite3_step(query) != SQLITE_DONE) { + err = zsv_status_error; + fprintf(stderr, "Failed to step: %s\n", sqlite3_errmsg(data->ctx->sqlite3.db)); + return err; + } + if (query) + sqlite3_finalize(query); + } + } + + if (!data->ctx->sqlite3.db) + err = zsv_status_error; + + return err; +} + struct zsv_overwrite *zsv_overwrite_writer_new(struct zsv_overwrite_args *args, struct zsv_overwrite_opts *ctx_opts) { struct zsv_overwrite *data = calloc(1, sizeof(*data)); data->overwrite = calloc(1, sizeof(*data->overwrite)); @@ -23,7 +88,17 @@ struct zsv_overwrite *zsv_overwrite_writer_new(struct zsv_overwrite_args *args, data->next = args->next; struct zsv_csv_writer_options writer_opts = {0}; data->writer = zsv_writer_new(&writer_opts); - return data; + + enum zsv_status err = zsv_status_ok; + if (data->mode == zsvsheet_mode_list) { + if ((err = (zsv_overwrite_open(data->ctx)))) // use open when it's read-only + fprintf(stderr, "Failed to initalize database\n"); + } else { + if ((err = zsv_overwrite_writer_init(data))) // use init when writing to db + fprintf(stderr, "Failed to initalize database\n"); + } + + return err == zsv_status_ok ? data : NULL; } void zsv_overwrite_writer_delete(struct zsv_overwrite *data) { From 12de367db194565b42522aa40d087550e437ab97 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Fri, 22 Nov 2024 19:35:12 -0500 Subject: [PATCH 59/62] Fix issue with main returning an error value --- app/overwrite.c | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 0d34bc0c..ee2ce507 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -83,19 +83,6 @@ static int zsv_overwrite_usage() { return 1; } -static int zsv_overwrites_free(struct zsv_overwrite_ctx *ctx, struct zsv_overwrite_data *overwrite, - const struct zsv_overwrite_args *args, zsv_csv_writer writer) { - if (writer) - zsv_writer_delete(writer); - if (ctx) { - zsv_overwrite_context_delete(ctx); - } - if (overwrite && args->mode != zsvsheet_mode_bulk) - free(overwrite->val.str); - - return 0; -} - static char *row_col_to_a1(size_t col, size_t row) { char buffer[64]; int index = 63; @@ -293,15 +280,15 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op if (!err && data) { if (data->mode == zsvsheet_mode_list) - err = show_all_overwrites(data, data->writer) == zsv_status_ok; + err = show_all_overwrites(data, data->writer); else if (data->mode == zsvsheet_mode_clear) - err = zsv_overwrite_writer_clear(data) == zsv_status_ok; + err = zsv_overwrite_writer_clear(data); else if (data->mode == zsvsheet_mode_add && data->ctx->sqlite3.db) - err = zsv_overwrite_writer_add(data) == zsv_status_ok; + err = zsv_overwrite_writer_add(data); else if (data->mode == zsvsheet_mode_remove && data->ctx->sqlite3.db) - err = zsv_overwrite_writer_remove(data) == zsv_status_ok; + err = zsv_overwrite_writer_remove(data); else if (data->mode == zsvsheet_mode_bulk && data->ctx->sqlite3.db) { - err = zsv_overwrite_writer_bulk(data) == zsv_status_ok; + err = zsv_overwrite_writer_bulk(data); } } From 708ca02488fb6ef508a7781c5d5ebf8596b37d50 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Fri, 22 Nov 2024 19:55:27 -0500 Subject: [PATCH 60/62] remove redundant variable --- app/overwrite.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index ee2ce507..f14c099b 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -198,8 +198,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op struct zsv_overwrite_data overwrite = {0}; overwrite.timestamp = (size_t)time(NULL); - char *filepath = (char *)argv[1]; - args.filepath = filepath; + args.filepath = (char*)argv[1]; for (int i = 2; !err && i < argc; i++) { const char *opt = argv[i]; @@ -273,7 +272,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op args.overwrite = &overwrite; - char *overwrites_fn = (char *)zsv_cache_filepath((const unsigned char *)filepath, zsv_cache_type_overwrite, 0, 0); + char *overwrites_fn = (char *)zsv_cache_filepath((const unsigned char *)args.filepath, zsv_cache_type_overwrite, 0, 0); ctx_opts.src = (char *)overwrites_fn; struct zsv_overwrite *data = zsv_overwrite_writer_new(&args, &ctx_opts); free(overwrites_fn); From a1a66adf2f28832b477ddefa65ad1d74be9abed2 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Fri, 22 Nov 2024 19:55:45 -0500 Subject: [PATCH 61/62] format --- app/overwrite.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index f14c099b..64e5e033 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -198,7 +198,7 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op struct zsv_overwrite_data overwrite = {0}; overwrite.timestamp = (size_t)time(NULL); - args.filepath = (char*)argv[1]; + args.filepath = (char *)argv[1]; for (int i = 2; !err && i < argc; i++) { const char *opt = argv[i]; @@ -272,7 +272,8 @@ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *op args.overwrite = &overwrite; - char *overwrites_fn = (char *)zsv_cache_filepath((const unsigned char *)args.filepath, zsv_cache_type_overwrite, 0, 0); + char *overwrites_fn = + (char *)zsv_cache_filepath((const unsigned char *)args.filepath, zsv_cache_type_overwrite, 0, 0); ctx_opts.src = (char *)overwrites_fn; struct zsv_overwrite *data = zsv_overwrite_writer_new(&args, &ctx_opts); free(overwrites_fn); From 200a4775e2bd6230d384620f2021b08e155eb881 Mon Sep 17 00:00:00 2001 From: CobbCoding Date: Fri, 22 Nov 2024 20:41:36 -0500 Subject: [PATCH 62/62] remove unused #includes --- app/overwrite.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/overwrite.c b/app/overwrite.c index 64e5e033..8d24b492 100644 --- a/app/overwrite.c +++ b/app/overwrite.c @@ -18,11 +18,8 @@ #include #include #include -#include -#include #include #include -#include #include #define ZSV_COMMAND overwrite