summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--database.h8
-rw-r--r--litterbox.c129
-rw-r--r--unscoop.c8
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);