From 162450118be816d81341d0e59eb88db56b8fc70c Mon Sep 17 00:00:00 2001 From: "C. McEnroe" Date: Wed, 18 Dec 2019 00:59:05 -0500 Subject: Rewrite litterbox statements with functions --- database.h | 8 ++-- litterbox.c | 129 +++++++++++++++++++++++++++++------------------------------- unscoop.c | 8 ++-- 3 files changed, 70 insertions(+), 75 deletions(-) diff --git a/database.h b/database.h index fad5265..6efe9d0 100644 --- a/database.h +++ b/database.h @@ -100,9 +100,11 @@ static inline sqlite3 *dbFind(int flags) { } static inline sqlite3_stmt * -dbPrepare(sqlite3 *db, unsigned flags, const char *sql) { +dbPrepare(sqlite3 *db, bool persistent, const char *sql) { sqlite3_stmt *stmt; - int error = sqlite3_prepare_v3(db, sql, -1, flags, &stmt, NULL); + int error = sqlite3_prepare_v3( + db, sql, -1, (persistent ? SQLITE_PREPARE_PERSISTENT : 0), &stmt, NULL + ); if (error) errx(EX_SOFTWARE, "%s: %s", sqlite3_errmsg(db), sql); return stmt; } @@ -172,7 +174,7 @@ static inline int dbStep(sqlite3_stmt *stmt) { } static inline int dbVersion(sqlite3 *db) { - sqlite3_stmt *stmt = dbPrepare(db, 0, SQL(PRAGMA user_version;)); + sqlite3_stmt *stmt = dbPrepare(db, false, SQL(PRAGMA user_version;)); dbStep(stmt); int version = sqlite3_column_int(stmt, 0); sqlite3_finalize(stmt); diff --git a/litterbox.c b/litterbox.c index c032c2b..e37f78a 100644 --- a/litterbox.c +++ b/litterbox.c @@ -103,24 +103,36 @@ static void require(const struct Message *msg, size_t len) { } } -static sqlite3_stmt *insertContext; -static sqlite3_stmt *insertName; -static sqlite3_stmt *insertEvent; +enum { + InsertContext, + InsertName, + InsertEvent, + StmtsLen, +}; +static sqlite3_stmt *stmts[StmtsLen]; -static void prepareInsert(void) { - const char *InsertContext = SQL( +static void printSQL(sqlite3_stmt *stmt) { + if (!verbose) return; + char *sql = sqlite3_expanded_sql(stmt); + if (!sql) return; + fprintf(stderr, "%s\n", sql); + sqlite3_free(sql); +} + +static void prepare(void) { + const char *insertContext = SQL( INSERT OR IGNORE INTO contexts (network, name, query) VALUES (:network, :context, :query); ); - insertContext = dbPrepare(db, SQLITE_PREPARE_PERSISTENT, InsertContext); + stmts[InsertContext] = dbPrepare(db, true, insertContext); - const char *InsertName = SQL( + const char *insertName = SQL( INSERT OR IGNORE INTO names (nick, user, host) VALUES (:nick, :user, :host); ); - insertName = dbPrepare(db, SQLITE_PREPARE_PERSISTENT, InsertName); + stmts[InsertName] = dbPrepare(db, true, insertName); - const char *InsertEvent = SQL( + const char *insertEvent = SQL( INSERT INTO events (time, type, context, name, target, message) SELECT coalesce(datetime(:time), datetime('now')), @@ -132,57 +144,45 @@ static void prepareInsert(void) { AND names.user = :user AND names.host = :host; ); - insertEvent = dbPrepare(db, SQLITE_PREPARE_PERSISTENT, InsertEvent); + stmts[InsertEvent] = dbPrepare(db, true, insertEvent); } static void bindNetwork(const char *network) { - dbBindTextCopy(insertContext, ":network", network); - dbBindTextCopy(insertEvent, ":network", network); -} -static void bindContext(const char *context, bool query) { - dbBindText(insertContext, ":context", context); - dbBindInt(insertContext, ":query", query); - dbBindText(insertEvent, ":context", context); -} -static void bindName(const char *nick, const char *user, const char *host) { - dbBindText(insertName, ":nick", nick); - dbBindText(insertName, ":user", user); - dbBindText(insertName, ":host", host); - dbBindText(insertEvent, ":nick", nick); - dbBindText(insertEvent, ":user", user); - dbBindText(insertEvent, ":host", host); + dbBindTextCopy(stmts[InsertContext], ":network", network); + dbBindTextCopy(stmts[InsertEvent], ":network", network); } -static void printSQL(sqlite3_stmt *stmt) { - char *sql = sqlite3_expanded_sql(stmt); - if (!sql) return; - fprintf(stderr, "%s\n", sql); - sqlite3_free(sql); +static void insertContext(const char *context, bool query) { + dbBindText(stmts[InsertContext], ":context", context); + dbBindInt(stmts[InsertContext], ":query", query); + dbStep(stmts[InsertContext]); + dbBindText(stmts[InsertEvent], ":context", context); + if (sqlite3_changes(db)) printSQL(stmts[InsertContext]); + sqlite3_reset(stmts[InsertContext]); } -static void insert(void) { - dbExec(db, SQL(BEGIN TRANSACTION;)); - - dbStep(insertContext); - if (verbose && sqlite3_changes(db)) printSQL(insertContext); - - dbStep(insertName); - if (verbose && sqlite3_changes(db)) printSQL(insertName); - - dbStep(insertEvent); - if (verbose) printSQL(insertEvent); - - dbExec(db, SQL(COMMIT TRANSACTION;)); +static void insertName(const char *nick, const char *user, const char *host) { + dbBindText(stmts[InsertName], ":nick", nick); + dbBindText(stmts[InsertName], ":user", user); + dbBindText(stmts[InsertName], ":host", host); + dbStep(stmts[InsertName]); + dbBindText(stmts[InsertEvent], ":nick", nick); + dbBindText(stmts[InsertEvent], ":user", user); + dbBindText(stmts[InsertEvent], ":host", host); + if (sqlite3_changes(db)) printSQL(stmts[InsertName]); + sqlite3_reset(stmts[InsertName]); +} - sqlite3_reset(insertContext); - sqlite3_reset(insertName); - sqlite3_reset(insertEvent); - bindContext(NULL, false); - bindName(NULL, NULL, NULL); - dbBindNull(insertEvent, ":time"); - dbBindNull(insertEvent, ":type"); - dbBindNull(insertEvent, ":target"); - dbBindNull(insertEvent, ":message"); +static void insertEvent( + const char *time, enum Type type, const char *target, const char *message +) { + dbBindText(stmts[InsertEvent], ":time", time); + dbBindInt(stmts[InsertEvent], ":type", type); + dbBindText(stmts[InsertEvent], ":target", target); + dbBindText(stmts[InsertEvent], ":message", message); + dbStep(stmts[InsertEvent]); + printSQL(stmts[InsertEvent]); + sqlite3_reset(stmts[InsertEvent]); } static const char *join; @@ -231,29 +231,24 @@ static void handlePrivmsg(struct Message *msg) { require(msg, 2); if (!msg->nick) return; - bindName(msg->nick, msg->user, msg->host); + insertName(msg->nick, msg->user, msg->host); if (strchr(chanTypes, msg->params[0][0])) { - bindContext(msg->params[0], false); + insertContext(msg->params[0], false); } else if (strcmp(msg->params[0], self)) { - bindContext(msg->params[0], true); + insertContext(msg->params[0], true); } else { - bindContext(msg->nick, true); + insertContext(msg->nick, true); } - dbBindText(insertEvent, ":time", msg->time); - dbBindText(insertEvent, ":message", msg->params[1]); if (!strncmp(msg->params[1], "\1ACTION ", 8)) { - msg->params[1] += 8; - msg->params[1][strcspn(msg->params[1], "\1")] = '\0'; - dbBindInt(insertEvent, ":type", Action); - dbBindText(insertEvent, ":message", msg->params[1]); + char *action = &msg->params[1][8]; + action[strcspn(action, "\1")] = '\0'; + insertEvent(msg->time, Action, NULL, action); } else if (!strcmp(msg->cmd, "NOTICE")) { - dbBindInt(insertEvent, ":type", Notice); + insertEvent(msg->time, Notice, NULL, msg->params[1]); } else { - dbBindInt(insertEvent, ":type", Privmsg); + insertEvent(msg->time, Privmsg, NULL, msg->params[1]); } - - insert(); } static void handlePing(struct Message *msg) { @@ -336,7 +331,7 @@ int main(int argc, char *argv[]) { set(&chanTypes, "#&"); set(&prefixes, "@+"); - prepareInsert(); + prepare(); bindNetwork(host); client = tls_client(); diff --git a/unscoop.c b/unscoop.c index 6fd8c28..d9015a6 100644 --- a/unscoop.c +++ b/unscoop.c @@ -226,7 +226,7 @@ static void prepareInsert(sqlite3 *db) { INSERT OR IGNORE INTO names (nick, user, host) VALUES (:nick, coalesce(:user, '*'), coalesce(:host, '*')); ); - insertName = dbPrepare(db, SQLITE_PREPARE_PERSISTENT, InsertName); + insertName = dbPrepare(db, true, InsertName); const char *InsertEvent = SQL( INSERT INTO events (time, type, context, name, target, message) @@ -244,7 +244,7 @@ static void prepareInsert(sqlite3 *db) { AND names.user = coalesce(:user, '*') AND names.host = coalesce(:host, '*'); ); - insertEvent = dbPrepare(db, SQLITE_PREPARE_PERSISTENT, InsertEvent); + insertEvent = dbPrepare(db, true, InsertEvent); paramNetwork = dbParam(insertEvent, ":network"); paramContext = dbParam(insertEvent, ":context"); } @@ -345,9 +345,7 @@ int main(int argc, char *argv[]) { NOT (:context LIKE '#%' OR :context LIKE '&%') ); ); - sqlite3_stmt *insertContext = dbPrepare( - db, SQLITE_PREPARE_PERSISTENT, InsertContext - ); + sqlite3_stmt *insertContext = dbPrepare(db, true, InsertContext); dbBindText(insertContext, ":network", network); dbBindText(insertContext, ":context", context); -- cgit 1.4.1