diff options
| author | Anders Betts <anders.betts@gmail.com> | 2026-09-20 14:53:46 +0200 |
|---|---|---|
| committer | Anders Betts <anders.betts@gmail.com> | 2026-09-20 14:53:46 +0200 |
| commit | 480640a747b81cb39deb1ec24e6e199a9c837fbe (patch) | |
| tree | a0823b8a06f2043061f4b61b1cd0b060b85ec68e /src/ledger.c | |
| parent | 8607260080dd1eca2d724d6e5b07622fad2d4ac8 (diff) | |
| download | bokf-480640a747b81cb39deb1ec24e6e199a9c837fbe.tar.gz bokf-480640a747b81cb39deb1ec24e6e199a9c837fbe.zip | |
db: schema v9 for invoicing, vouchers source rebuild
Diffstat (limited to 'src/ledger.c')
| -rw-r--r-- | src/ledger.c | 46 |
1 files changed, 29 insertions, 17 deletions
diff --git a/src/ledger.c b/src/ledger.c index 2de794e..a22e15e 100644 --- a/src/ledger.c +++ b/src/ledger.c @@ -345,6 +345,12 @@ static int db_step(sqlite3 *db, sqlite3_stmt *st, char *errbuf, size_t n) return rc; } +static void tx_rollback(sqlite3 *db, int owner) +{ + if (owner) + sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL); +} + int ledger_post(sqlite3 *db, const struct ledger_post_opts *o, struct ledger_error *e, char **out_result_json) { @@ -417,9 +423,12 @@ int ledger_post(sqlite3 *db, const struct ledger_post_opts *o, (long long)(sum_debit - sum_credit)); } - if (sqlite3_exec(db, "BEGIN IMMEDIATE", NULL, NULL, NULL) != SQLITE_OK) { - free(series_owned); - return fail(e, "DB_BUSY", "could not start transaction"); + if (!o->already_in_tx) { + if (sqlite3_exec(db, "BEGIN IMMEDIATE", NULL, NULL, NULL) != + SQLITE_OK) { + free(series_owned); + return fail(e, "DB_BUSY", "could not start transaction"); + } } int rc = -1; @@ -443,7 +452,7 @@ int ledger_post(sqlite3 *db, const struct ledger_post_opts *o, sqlite3_bind_text(st, 2, o->date, -1, SQLITE_TRANSIENT); if (sqlite3_step(st) != SQLITE_ROW) { sqlite3_finalize(st); - sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL); + tx_rollback(db, !o->already_in_tx); free(series_owned); return fail(e, "DATE_OUT_OF_RANGE", "no fiscal year contains %s; open one first", o->date); @@ -462,13 +471,13 @@ int ledger_post(sqlite3 *db, const struct ledger_post_opts *o, sqlite3_finalize(st); if (strcmp(fy_status, "closed") == 0) { - sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL); + tx_rollback(db, !o->already_in_tx); free(series_owned); return fail(e, "FISCAL_YEAR_CLOSED", "fiscal year %s is closed", fy_label); } if (locked_until[0] && strcmp(o->date, locked_until) <= 0) { - sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL); + tx_rollback(db, !o->already_in_tx); free(series_owned); return fail(e, "PERIOD_LOCKED", "period is locked through %s", locked_until); @@ -490,7 +499,7 @@ int ledger_post(sqlite3 *db, const struct ledger_post_opts *o, if (sqlite3_step(st) != SQLITE_ROW) { sqlite3_finalize(st); free(acct_ids); - sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL); + tx_rollback(db, !o->already_in_tx); free(series_owned); return fail(e, "ACCOUNT_NOT_FOUND", "account %s does not exist", o->rows[i].account); @@ -500,7 +509,7 @@ int ledger_post(sqlite3 *db, const struct ledger_post_opts *o, sqlite3_finalize(st); if (!active) { free(acct_ids); - sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL); + tx_rollback(db, !o->already_in_tx); free(series_owned); return fail(e, "ACCOUNT_INACTIVE", "account %s is inactive", o->rows[i].account); @@ -524,7 +533,7 @@ int ledger_post(sqlite3 *db, const struct ledger_post_opts *o, sqlite3_finalize(st); if (!exists) { free(acct_ids); - sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL); + tx_rollback(db, !o->already_in_tx); free(series_owned); return fail(e, "NOT_FOUND", "voucher %lld does not exist", (long long)o->corrects_voucher_id); @@ -624,7 +633,7 @@ int ledger_post(sqlite3 *db, const struct ledger_post_opts *o, *out_result_json = yyjson_mut_write(doc, 0, NULL); yyjson_mut_doc_free(doc); free(acct_ids); - sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL); + tx_rollback(db, !o->already_in_tx); free(series_owned); return 0; } @@ -722,13 +731,13 @@ int ledger_post(sqlite3 *db, const struct ledger_post_opts *o, } sqlite3_finalize(st); if (!exists) { - sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL); + tx_rollback(db, !o->already_in_tx); free(series_owned); return fail(e, "NOT_FOUND", "attachment %lld does not exist", (long long)aid); } if (linked) { - sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL); + tx_rollback(db, !o->already_in_tx); free(series_owned); return fail(e, "CONFLICT", "attachment %lld is already linked", (long long)aid); @@ -783,10 +792,13 @@ int ledger_post(sqlite3 *db, const struct ledger_post_opts *o, } } - if (sqlite3_exec(db, "COMMIT", NULL, NULL, NULL) != SQLITE_OK) { - free(result_json); - free(series_owned); - return fail(e, "DB_BUSY", "commit failed: %s", sqlite3_errmsg(db)); + if (!o->already_in_tx) { + if (sqlite3_exec(db, "COMMIT", NULL, NULL, NULL) != SQLITE_OK) { + free(result_json); + free(series_owned); + return fail(e, "DB_BUSY", "commit failed: %s", + sqlite3_errmsg(db)); + } } free(series_owned); *out_result_json = result_json; @@ -794,7 +806,7 @@ int ledger_post(sqlite3 *db, const struct ledger_post_opts *o, busy: free(series_owned); - sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL); + tx_rollback(db, !o->already_in_tx); e->code = "DB_BUSY"; if (!e->msg[0]) snprintf(e->msg, sizeof e->msg, "database error: %s", |
