diff options
author | June McEnroe <june@causal.agency> | 2019-12-24 00:58:26 -0500 |
---|---|---|
committer | June McEnroe <june@causal.agency> | 2019-12-24 00:58:26 -0500 |
commit | 2d7108f29b9f7d80709dfbe0c2e2434b07c5a45c (patch) | |
tree | 4e00cf884cd6b0291694f830140d79b240d19c28 /database.h | |
parent | Actually only use a transaction for handlers that need it (diff) | |
download | litterbox-2d7108f29b9f7d80709dfbe0c2e2434b07c5a45c.tar.gz litterbox-2d7108f29b9f7d80709dfbe0c2e2434b07c5a45c.zip |
It's The Big Refactor
Diffstat (limited to 'database.h')
-rw-r--r-- | database.h | 106 |
1 files changed, 59 insertions, 47 deletions
diff --git a/database.h b/database.h index 1d5ef1c..8d8c985 100644 --- a/database.h +++ b/database.h @@ -45,13 +45,14 @@ enum Type { }; static bool verbose; +static sqlite3 *db; -static inline void dbExec(sqlite3 *db, const char *sql) { +static inline void dbExec(const char *sql) { int error = sqlite3_exec(db, sql, NULL, NULL, NULL); if (error) errx(EX_SOFTWARE, "%s: %s", sqlite3_errmsg(db), sql); } -static inline sqlite3 *dbOpen(char *path, int flags) { +static inline void dbOpen(char *path, int flags) { char *base = strrchr(path, '/'); if (flags & SQLITE_OPEN_CREATE && base) { *base = '\0'; @@ -60,22 +61,24 @@ static inline sqlite3 *dbOpen(char *path, int flags) { *base = '/'; } - sqlite3 *db; int error = sqlite3_open_v2(path, &db, flags, NULL); if (error == SQLITE_CANTOPEN) { sqlite3_close(db); - return NULL; + db = NULL; + return; } if (error) errx(EX_NOINPUT, "%s: %s", path, sqlite3_errmsg(db)); sqlite3_busy_timeout(db, 1000); - dbExec(db, SQL(PRAGMA foreign_keys = true;)); - - return db; + dbExec(SQL(PRAGMA foreign_keys = true;)); } -static inline sqlite3 *dbFind(char *path, int flags) { - if (path) return dbOpen(path, flags); +static inline void dbFind(char *path, int flags) { + if (path) { + dbOpen(path, flags); + if (db) return; + errx(EX_NOINPUT, "%s: database not found", path); + } const char *home = getenv("HOME"); const char *dataHome = getenv("XDG_DATA_HOME"); @@ -88,55 +91,71 @@ static inline sqlite3 *dbFind(char *path, int flags) { if (!home) errx(EX_CONFIG, "HOME unset"); snprintf(buf, sizeof(buf), "%s/.local/share/" DATABASE_PATH, home); } - sqlite3 *db = dbOpen(buf, flags); - if (db) return db; + dbOpen(buf, flags); + if (db) return; if (!dataDirs) dataDirs = "/usr/local/share:/usr/share"; while (*dataDirs) { size_t len = strcspn(dataDirs, ":"); snprintf(buf, sizeof(buf), "%.*s/" DATABASE_PATH, (int)len, dataDirs); - db = dbOpen(buf, flags); - if (db) return db; + dbOpen(buf, flags); + if (db) return; dataDirs += len; if (*dataDirs) dataDirs++; } - return NULL; + errx(EX_NOINPUT, "database not found"); } -static inline sqlite3_stmt * -dbPrepare(sqlite3 *db, bool persistent, const char *sql) { +static struct Persist { sqlite3_stmt *stmt; + struct Persist *prev; +} *persistHead; + +static inline void dbPersist(sqlite3_stmt **stmt, const char *sql) { + if (*stmt) return; + int error = sqlite3_prepare_v3( - db, sql, -1, (persistent ? SQLITE_PREPARE_PERSISTENT : 0), &stmt, NULL + db, sql, -1, SQLITE_PREPARE_PERSISTENT, stmt, NULL ); if (error) errx(EX_SOFTWARE, "%s: %s", sqlite3_errmsg(db), sql); + + struct Persist *persist = malloc(sizeof(*persist)); + persist->stmt = *stmt; + persist->prev = persistHead; + persistHead = persist; +} + +static inline void dbClose(void) { + for (struct Persist *persist = persistHead; persist;) { + sqlite3_finalize(persist->stmt); + struct Persist *prev = persist->prev; + free(persist); + persist = prev; + } + sqlite3_close(db); +} + +static inline sqlite3_stmt *dbPrepare(const char *sql) { + sqlite3_stmt *stmt; + int error = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); + if (error) err(EX_SOFTWARE, "%s: %s", sqlite3_errmsg(db), sql); return stmt; } static inline int dbParam(sqlite3_stmt *stmt, const char *param) { int index = sqlite3_bind_parameter_index(stmt, param); if (index) return index; - errx( - EX_SOFTWARE, "no such parameter %s: %s", - param, sqlite3_sql(stmt) - ); + errx(EX_SOFTWARE, "no such parameter %s: %s", param, sqlite3_sql(stmt)); } static inline void dbBindNull(sqlite3_stmt *stmt, const char *param) { if (!sqlite3_bind_null(stmt, dbParam(stmt, param))) return; - errx( - EX_SOFTWARE, "sqlite3_bind_null: %s", - sqlite3_errmsg(sqlite3_db_handle(stmt)) - ); + errx(EX_SOFTWARE, "sqlite3_bind_null: %s", sqlite3_errmsg(db)); } -static inline void -dbBindInt(sqlite3_stmt *stmt, const char *param, int value) { +static inline void dbBindInt(sqlite3_stmt *stmt, const char *param, int value) { if (!sqlite3_bind_int(stmt, dbParam(stmt, param), value)) return; - errx( - EX_SOFTWARE, "sqlite3_bind_int: %s", - sqlite3_errmsg(sqlite3_db_handle(stmt)) - ); + errx(EX_SOFTWARE, "sqlite3_bind_int: %s", sqlite3_errmsg(db)); } static inline void dbBindText5( @@ -146,11 +165,7 @@ static inline void dbBindText5( int error = sqlite3_bind_text( stmt, dbParam(stmt, param), text, len, (copy ? SQLITE_TRANSIENT : NULL) ); - if (!error) return; - errx( - EX_SOFTWARE, "sqlite3_bind_text: %s", - sqlite3_errmsg(sqlite3_db_handle(stmt)) - ); + if (error) err(EX_SOFTWARE, "sqlite3_bind_text: %s", sqlite3_errmsg(db)); } static inline void @@ -171,10 +186,7 @@ dbBindTextCopy(sqlite3_stmt *stmt, const char *param, const char *text) { static inline int dbStep(sqlite3_stmt *stmt) { int error = sqlite3_step(stmt); if (error == SQLITE_ROW || error == SQLITE_DONE) return error; - errx( - EX_SOFTWARE, "%s: %s", - sqlite3_errmsg(sqlite3_db_handle(stmt)), sqlite3_expanded_sql(stmt) - ); + errx(EX_SOFTWARE, "%s: %s", sqlite3_errmsg(db), sqlite3_expanded_sql(stmt)); } static inline void dbRun(sqlite3_stmt *stmt) { @@ -187,8 +199,8 @@ static inline void dbRun(sqlite3_stmt *stmt) { sqlite3_reset(stmt); } -static inline int dbVersion(sqlite3 *db) { - sqlite3_stmt *stmt = dbPrepare(db, false, SQL(PRAGMA user_version;)); +static inline int dbVersion(void) { + sqlite3_stmt *stmt = dbPrepare(SQL(PRAGMA user_version;)); dbStep(stmt); int version = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); @@ -258,16 +270,16 @@ static const char *InitSQL = SQL( COMMIT TRANSACTION; ); -static inline void dbInit(sqlite3 *db) { - dbExec(db, InitSQL); +static inline void dbInit(void) { + dbExec(InitSQL); } static const char *MigrationSQL[] = { NULL, }; -static inline void dbMigrate(sqlite3 *db) { - for (int version = dbVersion(db); version < DatabaseVersion; ++version) { - dbExec(db, MigrationSQL[version]); +static inline void dbMigrate(void) { + for (int version = dbVersion(); version < DatabaseVersion; ++version) { + dbExec(MigrationSQL[version]); } } |