netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jeremy Sowden <jeremy@azazel.net>
To: Netfilter Devel <netfilter-devel@vger.kernel.org>
Subject: [PATCH ulogd2 v2 v2 34/34] output: sqlite3: reimplement using the common DB API
Date: Tue, 29 Nov 2022 21:47:49 +0000	[thread overview]
Message-ID: <20221129214749.247878-35-jeremy@azazel.net> (raw)
In-Reply-To: <20221129214749.247878-1-jeremy@azazel.net>

SQLite doesn't have support for escaping strings to embed them in SQL
statements.  Therefore, the sqlite3 plug-in has not used the `util_db`
API.  Now that the common API supports prep & exec, convert the sqlite3
plug-in to use it.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
 output/sqlite3/ulogd_output_SQLITE3.c | 459 +++++++++-----------------
 1 file changed, 150 insertions(+), 309 deletions(-)

diff --git a/output/sqlite3/ulogd_output_SQLITE3.c b/output/sqlite3/ulogd_output_SQLITE3.c
index 32459dd6c4c5..2875c504d20e 100644
--- a/output/sqlite3/ulogd_output_SQLITE3.c
+++ b/output/sqlite3/ulogd_output_SQLITE3.c
@@ -30,392 +30,232 @@
  *  	- port to ulogd-2.00
  */
 
+#ifdef DEBUG_SQLITE3
+#include <stdio.h>
+#endif
 #include <stdlib.h>
 #include <string.h>
-#include <arpa/inet.h>
+#include <sqlite3.h>
 #include <ulogd/ulogd.h>
 #include <ulogd/conffile.h>
-#include <sqlite3.h>
-#include <sys/queue.h>
+#include <ulogd/db.h>
 
-#define CFG_BUFFER_DEFAULT		10
-
-#if 0
+#ifdef DEBUG_SQLITE3
 #define DEBUGP(x, args...)	fprintf(stderr, x, ## args)
 #else
 #define DEBUGP(x, args...)
 #endif
 
-struct field {
-	TAILQ_ENTRY(field) link;
-	char name[ULOGD_MAX_KEYLEN + 1];
-	struct ulogd_key *key;
-};
-
-TAILQ_HEAD(field_lh, field);
-
-#define tailq_for_each(pos, head, link) \
-        for (pos = (head).tqh_first; pos != NULL; pos = pos->link.tqe_next)
-
+#define SQLITE3_BUSY_TIMEOUT 300
 
-struct sqlite3_priv {
+struct sqlite3_instance {
+	struct db_instance db_inst;
 	sqlite3 *dbh;				/* database handle we are using */
-	struct field_lh fields;
-	char *stmt;
 	sqlite3_stmt *p_stmt;
-	struct {
-		unsigned err_tbl_busy;	/* "Table busy" */
-	} stats;
 };
 
-static struct config_keyset sqlite3_kset = {
-	.num_ces = 3,
+static struct config_keyset kset_sqlite3 = {
+	.num_ces = DB_CE_NUM + 1,
 	.ces = {
+		DB_CES,
 		{
 			.key = "db",
 			.type = CONFIG_TYPE_STRING,
 			.options = CONFIG_OPT_MANDATORY,
 		},
-		{
-			.key = "table",
-			.type = CONFIG_TYPE_STRING,
-			.options = CONFIG_OPT_MANDATORY,
-		},
 	},
 };
 
-#define db_ce(pi)		(pi)->config_kset->ces[0].u.string
-#define table_ce(pi)	(pi)->config_kset->ces[1].u.string
-
-/* forward declarations */
-static int sqlite3_createstmt(struct ulogd_pluginstance *);
+#define db_ce(x) ((x)->ces[DB_CE_NUM + 0])
 
+#define SELECT_ALL_FROM "select * from "
 
 static int
-add_row(struct ulogd_pluginstance *pi)
+get_columns_sqlite3(struct ulogd_pluginstance *upi)
 {
-	struct sqlite3_priv *priv = (void *)pi->private;
-	int ret;
-
-	ret = sqlite3_step(priv->p_stmt);
-	if (ret == SQLITE_BUSY)
-		priv->stats.err_tbl_busy++;
-	else if (ret == SQLITE_ERROR) {
-		ret = sqlite3_finalize(priv->p_stmt);
-		priv->p_stmt = NULL;
-
-		if (ret != SQLITE_SCHEMA) {
-			ulogd_log(ULOGD_ERROR, "SQLITE3: step: %s\n",
-				  sqlite3_errmsg(priv->dbh));
-			goto err_reset;
-		}
-		if (sqlite3_createstmt(pi) < 0) {
-			ulogd_log(ULOGD_ERROR,
-				  "SQLITE3: Could not create statement.\n");
-			goto err_reset;
-		}
-	}
+	struct sqlite3_instance *si = (struct sqlite3_instance *) upi->private;
+	char query[sizeof(SELECT_ALL_FROM) + CONFIG_VAL_STRING_LEN];
+	sqlite3_stmt *stmt;
+	int rv;
 
-	ret = sqlite3_reset(priv->p_stmt);
+	snprintf(query, sizeof(query), SELECT_ALL_FROM "%s",
+		 table_ce(upi->config_kset).u.string);
 
-	return 0;
+	if (sqlite3_prepare_v2(si->dbh, query, -1, &stmt, NULL) != SQLITE_OK) {
+		ulogd_log(ULOGD_ERROR, "%s: prepare failed: %s\n",
+			  __func__, sqlite3_errmsg(si->dbh));
+		return -1;
+	}
 
- err_reset:
-	sqlite3_reset(priv->p_stmt);
+	rv = ulogd_db_alloc_input_keys(upi, sqlite3_column_count(stmt), stmt);
 
-	return -1;
+	sqlite3_finalize(stmt);
+	return rv;
 }
 
-
-/* our main output function, called by ulogd */
-static int
-sqlite3_interp(struct ulogd_pluginstance *pi)
+static const char *
+get_column_sqlite3(void *vp, unsigned int i)
 {
-	struct sqlite3_priv *priv = (void *)pi->private;
-	struct field *f;
-	int ret, i = 1;
-
-	tailq_for_each(f, priv->fields, link) {
-		struct ulogd_key *k_ret = f->key->u.source;
-
-		if (f->key == NULL || !IS_VALID(*k_ret)) {
-			sqlite3_bind_null(priv->p_stmt, i);
-			i++;
-			continue;
-		}
-
-		switch (f->key->type) {
-		case ULOGD_RET_INT8:
-			ret = sqlite3_bind_int(priv->p_stmt, i, k_ret->u.value.i8);
-			break;
-
-		case ULOGD_RET_INT16:
-			ret = sqlite3_bind_int(priv->p_stmt, i, k_ret->u.value.i16);
-			break;
-
-		case ULOGD_RET_INT32:
-			ret = sqlite3_bind_int(priv->p_stmt, i, k_ret->u.value.i32);
-			break;
-
-		case ULOGD_RET_INT64:
-			ret = sqlite3_bind_int(priv->p_stmt, i, k_ret->u.value.i64);
-			break;
+	sqlite3_stmt *schema_stmt = vp;
 
-		case ULOGD_RET_UINT8:
-			ret = sqlite3_bind_int(priv->p_stmt, i, k_ret->u.value.ui8);
-			break;
-
-		case ULOGD_RET_UINT16:
-			ret = sqlite3_bind_int(priv->p_stmt, i, k_ret->u.value.ui16);
-			break;
-
-		case ULOGD_RET_UINT32:
-			ret = sqlite3_bind_int(priv->p_stmt, i, k_ret->u.value.ui32);
-			break;
-
-		case ULOGD_RET_IPADDR:
-		case ULOGD_RET_UINT64:
-			ret = sqlite3_bind_int64(priv->p_stmt, i, k_ret->u.value.ui64);
-			break;
-
-		case ULOGD_RET_BOOL:
-			ret = sqlite3_bind_int(priv->p_stmt, i, k_ret->u.value.b);
-			break;
-
-		case ULOGD_RET_STRING:
-			ret = sqlite3_bind_text(priv->p_stmt, i, k_ret->u.value.ptr,
-									strlen(k_ret->u.value.ptr), SQLITE_STATIC);
-			break;
-
-		default:
-			ret = SQLITE_OK;
-			ulogd_log(ULOGD_NOTICE, "unknown type %d for %s\n",
-					  f->key->type, f->key->name);
-		}
-		if (ret != SQLITE_OK)
-			goto err_bind;
-
-		i++;
-	}
-
-	if (add_row(pi) < 0)
-		return ULOGD_IRET_ERR;
-
-	return ULOGD_IRET_OK;
-
- err_bind:
-	ulogd_log(ULOGD_ERROR, "SQLITE: bind: %s\n", sqlite3_errmsg(priv->dbh));
-
-	return ULOGD_IRET_ERR;
+	return sqlite3_column_name(schema_stmt, i);
 }
 
-#define _SQLITE3_INSERTTEMPL   "insert into X (Y) values (Z)"
-
-/* create the static part of our insert statement */
 static int
-sqlite3_createstmt(struct ulogd_pluginstance *pi)
+open_db_sqlite3(struct ulogd_pluginstance *upi)
 {
-	struct sqlite3_priv *priv = (void *)pi->private;
-	struct field *f;
-	int i, cols = 0;
-	char *stmt_pos;
-
-	if (priv->stmt != NULL)
-		free(priv->stmt);
-
-	if ((priv->stmt = calloc(1, 1024)) == NULL) {
-		ulogd_log(ULOGD_ERROR, "SQLITE3: out of memory\n");
-		return -1;
-	}
-	stmt_pos = priv->stmt;
-
-	stmt_pos += sprintf(stmt_pos, "insert into %s (", table_ce(pi));
-
-	tailq_for_each(f, priv->fields, link) {
-		stmt_pos += sprintf(stmt_pos, "%s,", f->name);
-		cols++;
-	}
-
-	*(stmt_pos - 1) = ')';
-
-	stmt_pos += sprintf(stmt_pos, " values (");
-
-	for (i = 0; i < cols - 1; i++)
-		stmt_pos += sprintf(stmt_pos, "?,");
-
-	sprintf(stmt_pos, "?)");
-	ulogd_log(ULOGD_DEBUG, "%s: stmt='%s'\n", pi->id, priv->stmt);
+	struct sqlite3_instance *si = (struct sqlite3_instance *) upi->private;
 
-	DEBUGP("about to prepare statement.\n");
-
-	sqlite3_prepare(priv->dbh, priv->stmt, -1, &priv->p_stmt, 0);
-	if (priv->p_stmt == NULL) {
-		ulogd_log(ULOGD_ERROR, "SQLITE3: prepare: %s\n",
-			  sqlite3_errmsg(priv->dbh));
+	if (sqlite3_open(db_ce(upi->config_kset).u.string,
+			 &si->dbh) != SQLITE_OK) {
+		ulogd_log(ULOGD_ERROR, "%s: open failed: %s\n",
+			  __func__, sqlite3_errmsg(si->dbh));
 		return -1;
 	}
 
-	DEBUGP("statement prepared.\n");
+	/* Set the timeout so that we don't automatically fail if the table is
+	 * busy.
+	 */
+	sqlite3_busy_timeout(si->dbh, SQLITE3_BUSY_TIMEOUT);
 
 	return 0;
 }
 
-
-static struct ulogd_key *
-ulogd_find_key(struct ulogd_pluginstance *pi, const char *name)
+static int
+close_db_sqlite3(struct ulogd_pluginstance *upi)
 {
-	char buf[ULOGD_MAX_KEYLEN + 1] = "";
-	unsigned int i;
+	struct sqlite3_instance *si = (struct sqlite3_instance *) upi->private;
 
-	/* replace all underscores with dots */
-	for (i = 0; i < sizeof(buf) - 1 && name[i]; ++i)
-		buf[i] = name[i] != '_' ? name[i] : '.';
+	if (si->p_stmt) {
+		sqlite3_finalize(si->p_stmt);
+		si->p_stmt = NULL;
+	}
 
-	for (i = 0; i < pi->input.num_keys; i++) {
-		if (strcmp(pi->input.keys[i].name, buf) == 0)
-			return &pi->input.keys[i];
+	if (si->dbh) {
+		sqlite3_close(si->dbh);
+		si->dbh = NULL;
 	}
 
-	return NULL;
+	return 0;
 }
 
-#define SELECT_ALL_STR			"select * from "
-#define SELECT_ALL_LEN			sizeof(SELECT_ALL_STR)
-
 static int
-db_count_cols(struct ulogd_pluginstance *pi, sqlite3_stmt **stmt)
+prepare_sqlite3(struct ulogd_pluginstance *upi, const struct db_stmt *stmt)
 {
-	struct sqlite3_priv *priv = (void *)pi->private;
-	char query[SELECT_ALL_LEN + CONFIG_VAL_STRING_LEN] = SELECT_ALL_STR;
+	struct sqlite3_instance *si = (struct sqlite3_instance *) upi->private;
 
-	strncat(query, table_ce(pi), sizeof(query) - strlen(query) - 1);
+	if (si->p_stmt) {
+		sqlite3_finalize(si->p_stmt);
+		si->p_stmt = NULL;
+	}
 
-	if (sqlite3_prepare(priv->dbh, query, -1, stmt, 0) != SQLITE_OK)
+	if (sqlite3_prepare_v2(si->dbh, stmt->sql, stmt->len + 1,
+			       &si->p_stmt, NULL) != SQLITE_OK) {
+		ulogd_log(ULOGD_ERROR, "%s: prepare failed: %s\n",
+			  __func__, sqlite3_errmsg(si->dbh));
 		return -1;
+	}
 
-	return sqlite3_column_count(*stmt);
+	return 0;
 }
 
-/* initialize DB, possibly creating it */
 static int
-sqlite3_init_db(struct ulogd_pluginstance *pi)
+execute_sqlite3(struct ulogd_pluginstance *upi, const struct db_stmt *stmt)
 {
-	struct sqlite3_priv *priv = (void *)pi->private;
-	sqlite3_stmt *schema_stmt;
-	int col, num_cols;
-
-	if (priv->dbh == NULL) {
-		ulogd_log(ULOGD_ERROR, "SQLITE3: No database handle.\n");
-		return -1;
-	}
-
-	num_cols = db_count_cols(pi, &schema_stmt);
-	if (num_cols <= 0) {
-		ulogd_log(ULOGD_ERROR, "table `%s' is empty or missing in "
-				       "file `%s'. Did you created this "
-				       "table in the database file? Please, "
-				       "see ulogd2 documentation.\n",
-					table_ce(pi), db_ce(pi));
-		return -1;
-	}
+	struct sqlite3_instance *si = (struct sqlite3_instance *) upi->private;
+	unsigned int i;
+	int rv;
 
-	for (col = 0; col < num_cols; col++) {
-		struct field *f;
+	for (i = 0; i < stmt->nr_params; i++) {
+		struct db_stmt_arg *arg = &stmt->args[i];
+		union db_stmt_arg_value *val = &arg->value;
 
-		/* prepend it to the linked list */
-		if ((f = calloc(1, sizeof(struct field))) == NULL) {
-			ulogd_log(ULOGD_ERROR, "SQLITE3: out of memory\n");
-			return -1;
+		if (arg->null) {
+			sqlite3_bind_null(si->p_stmt, i + 1);
+			continue;
 		}
-		snprintf(f->name, sizeof(f->name),
-			 "%s", sqlite3_column_name(schema_stmt, col));
-
-		DEBUGP("field '%s' found\n", f->name);
 
-		if ((f->key = ulogd_find_key(pi, f->name)) == NULL) {
-			ulogd_log(ULOGD_ERROR,
-				  "SQLITE3: unknown input key: %s\n", f->name);
-			free(f);
-			return -1;
+		switch (arg->type) {
+		case ULOGD_RET_BOOL:
+			rv = sqlite3_bind_int(si->p_stmt, i + 1, val->b);
+			break;
+		case ULOGD_RET_INT8:
+			rv = sqlite3_bind_int(si->p_stmt, i + 1, val->i8);
+			break;
+		case ULOGD_RET_INT16:
+			rv = sqlite3_bind_int(si->p_stmt, i + 1, val->i16);
+			break;
+		case ULOGD_RET_INT32:
+			rv = sqlite3_bind_int(si->p_stmt, i + 1, val->i32);
+			break;
+		case ULOGD_RET_INT64:
+			rv = sqlite3_bind_int(si->p_stmt, i + 1, val->i64);
+			break;
+		case ULOGD_RET_UINT8:
+			rv = sqlite3_bind_int(si->p_stmt, i + 1, val->ui8);
+			break;
+		case ULOGD_RET_UINT16:
+			rv = sqlite3_bind_int(si->p_stmt, i + 1, val->ui16);
+			break;
+		case ULOGD_RET_UINT32:
+			rv = sqlite3_bind_int(si->p_stmt, i + 1, val->ui32);
+			break;
+		case ULOGD_RET_IPADDR:
+		case ULOGD_RET_UINT64:
+			rv = sqlite3_bind_int64(si->p_stmt, i + 1, val->ui64);
+			break;
+		case ULOGD_RET_STRING:
+			rv = sqlite3_bind_text(si->p_stmt, i + 1, val->ptr,
+					       arg->len, SQLITE_STATIC);
+			break;
+		case ULOGD_RET_RAWSTR:
+			rv = sqlite3_bind_blob(si->p_stmt, i + 1, val->ptr,
+					       arg->len, SQLITE_STATIC);
+			break;
 		}
 
-		TAILQ_INSERT_TAIL(&priv->fields, f, link);
+		if (rv != SQLITE_OK) {
+			ulogd_log(ULOGD_ERROR, "%s: bind %u failed: %s\n",
+				  __func__, i + 1, sqlite3_errmsg(si->dbh));
+			rv = -1;
+			goto err_clear_bindings;
+		}
 	}
 
-	sqlite3_finalize(schema_stmt);
-
-	return 0;
-}
+	rv = sqlite3_step(si->p_stmt);
 
-#define SQLITE3_BUSY_TIMEOUT 300
+	if (rv != SQLITE_DONE) {
+		ulogd_log(ULOGD_ERROR, "%s: step failed: %s\n",
+			  __func__, sqlite3_errmsg(si->dbh));
+		rv = -1;
+	} else
+		rv = 0;
 
-static int
-sqlite3_configure(struct ulogd_pluginstance *pi,
-				  struct ulogd_pluginstance_stack *stack)
-{
-	/* struct sqlite_priv *priv = (void *)pi->private; */
+	sqlite3_reset(si->p_stmt);
 
-	config_parse_file(pi->id, pi->config_kset);
+err_clear_bindings:
+	sqlite3_clear_bindings(si->p_stmt);
 
-	if (ulogd_wildcard_inputkeys(pi) < 0)
-		return -1;
-
-	DEBUGP("%s: db='%s' table='%s'\n", pi->id, db_ce(pi), table_ce(pi));
-
-	return 0;
+	return rv;
 }
 
-static int
-sqlite3_start(struct ulogd_pluginstance *pi)
-{
-	struct sqlite3_priv *priv = (void *)pi->private;
-
-	TAILQ_INIT(&priv->fields);
-
-	if (sqlite3_open(db_ce(pi), &priv->dbh) != SQLITE_OK) {
-		ulogd_log(ULOGD_ERROR, "SQLITE3: %s\n", sqlite3_errmsg(priv->dbh));
-		return -1;
-	}
-
-	/* set the timeout so that we don't automatically fail
-	   if the table is busy */
-	sqlite3_busy_timeout(priv->dbh, SQLITE3_BUSY_TIMEOUT);
-
-	/* read the fieldnames to know which values to insert */
-	if (sqlite3_init_db(pi) < 0) {
-		ulogd_log(ULOGD_ERROR, "SQLITE3: Could not read database fieldnames.\n");
-		return -1;
-	}
-
-	/* create and prepare the actual insert statement */
-	if (sqlite3_createstmt(pi) < 0) {
-		ulogd_log(ULOGD_ERROR, "SQLITE3: Could not create statement.\n");
-		return -1;
-	}
-
-	return 0;
-}
+static struct db_driver sqlite3_db_driver = {
+	.get_columns	= get_columns_sqlite3,
+	.get_column	= get_column_sqlite3,
+	.open_db	= open_db_sqlite3,
+	.close_db	= close_db_sqlite3,
+	.prepare	= prepare_sqlite3,
+	.execute	= execute_sqlite3,
+};
 
-/* give us an opportunity to close the database down properly */
 static int
-sqlite3_stop(struct ulogd_pluginstance *pi)
+configure_sqlite3(struct ulogd_pluginstance *upi,
+		  struct ulogd_pluginstance_stack *stack)
 {
-	struct sqlite3_priv *priv = (void *)pi->private;
+	struct db_instance *di = (struct db_instance *) &upi->private;
+	di->driver = &sqlite3_db_driver;
 
-	/* free up our prepared statements so we can close the db */
-	if (priv->p_stmt) {
-		sqlite3_finalize(priv->p_stmt);
-		DEBUGP("prepared statement finalized\n");
-	}
-
-	if (priv->dbh == NULL)
-		return -1;
-
-	sqlite3_close(priv->dbh);
-
-	priv->dbh = NULL;
-
-	return 0;
+	return ulogd_db_configure(upi, stack);
 }
 
 static struct ulogd_plugin sqlite3_plugin = {
@@ -426,12 +266,13 @@ static struct ulogd_plugin sqlite3_plugin = {
 	.output	     = {
 		.type = ULOGD_DTYPE_SINK,
 	},
-	.config_kset = &sqlite3_kset,
-	.priv_size   = sizeof(struct sqlite3_priv),
-	.configure   = sqlite3_configure,
-	.start	     = sqlite3_start,
-	.stop	     = sqlite3_stop,
-	.interp	     = sqlite3_interp,
+	.config_kset = &kset_sqlite3,
+	.priv_size   = sizeof(struct sqlite3_instance),
+	.configure   = configure_sqlite3,
+	.start	     = ulogd_db_start,
+	.stop	     = ulogd_db_stop,
+	.signal	     = ulogd_db_signal,
+	.interp	     = ulogd_db_interp,
 	.version     = VERSION,
 };
 
-- 
2.35.1


  parent reply	other threads:[~2022-11-29 21:59 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-29 21:47 [PATCH ulogd2 v2 v2 00/34] Refactor of the DB output plug-ins Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 01/34] ulogd: fix parse-error check Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 02/34] filter: fix buffer sizes in filter plug-ins Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 03/34] output: JSON: remove incorrect config value check Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 04/34] db: fix back-log capacity checks Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 05/34] build: add checks to configure.ac Jeremy Sowden
2022-11-30 10:04   ` Jan Engelhardt
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 06/34] src: remove some trailing white space Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 07/34] src: remove zero-valued config-key fields Jeremy Sowden
2022-11-30 10:21   ` Jan Engelhardt
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 08/34] src: parenthesize config-entry macro arguments Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 09/34] src: define constructors and destructors consistently Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 10/34] src: remove `TIME_ERR` macro Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 11/34] src: remove superfluous casts Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 12/34] conffile: replace malloc+strcpy with strdup Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 13/34] output: remove zero-initialized `struct ulogd_plugin` members Jeremy Sowden
2022-11-30 10:26   ` Jan Engelhardt
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 14/34] output: de-duplicate allocation of input keys Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 15/34] db: reorganize source Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 16/34] db: use consistent integer return values to indicate errors Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 17/34] db: change return type of two functions to `void` Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 18/34] db: open-code `_loop_reconnect_db` Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 19/34] db: improve calculation of sql statement length Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 20/34] db: refactor configuration Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 21/34] db: refactor ring-buffer initialization Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 22/34] db: refactor ring-buffer Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 23/34] db: refactor backlog Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 24/34] db: use `struct db_stmt` objects more widely Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 25/34] db: synchronize access to ring-buffer Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 26/34] db: avoid cancelling ring-buffer thread Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 27/34] db, IP2BIN: defer formatting of raw strings Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 28/34] db: add prep & exec support Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 29/34] output: mysql: " Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 30/34] output: pgsql: remove a couple of struct members Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 31/34] output: pgsql: remove variable-length arrays Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 32/34] output: pgsql: tidy up `open_db_pgsql` and fix memory leak Jeremy Sowden
2022-11-29 21:47 ` [PATCH ulogd2 v2 v2 33/34] output: pgsql: add prep & exec support Jeremy Sowden
2022-11-29 21:47 ` Jeremy Sowden [this message]
2022-11-30 10:27 ` [PATCH ulogd2 v2 v2 00/34] Refactor of the DB output plug-ins Pablo Neira Ayuso
2022-11-30 16:03   ` Jeremy Sowden

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221129214749.247878-35-jeremy@azazel.net \
    --to=jeremy@azazel.net \
    --cc=netfilter-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).