From: Jeremy Sowden <jeremy@azazel.net>
To: Netfilter Devel <netfilter-devel@vger.kernel.org>
Subject: [PATCH ulogd2 v2 v2 19/34] db: improve calculation of sql statement length
Date: Tue, 29 Nov 2022 21:47:34 +0000 [thread overview]
Message-ID: <20221129214749.247878-20-jeremy@azazel.net> (raw)
In-Reply-To: <20221129214749.247878-1-jeremy@azazel.net>
Currently, we calculate the space required from a prefix which doesn't
correspond to anything we use, space for each key, although the SQL
statement may not contain the keys, and a fixed amount for each value.
However, we can use snprintf to tighten up the estimate by using
`snprintf(NULL, 0, ...)` to tell us how much room we actually need for
the parts we know in advance.
Rename a couple of variables and replace `strlen` with `sizeof` where
appropriate.
Sort included headers.
Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
util/db.c | 149 ++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 105 insertions(+), 44 deletions(-)
diff --git a/util/db.c b/util/db.c
index afa86a3f137b..ce1273638ae0 100644
--- a/util/db.c
+++ b/util/db.c
@@ -24,15 +24,16 @@
*
*/
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
#include <errno.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <time.h>
#include <inttypes.h>
#include <pthread.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
#include <ulogd/ulogd.h>
#include <ulogd/db.h>
@@ -47,6 +48,10 @@ static void _stop_db(struct ulogd_pluginstance *upi);
static char *_format_key(char *key);
static int _create_sql_stmt(struct ulogd_pluginstance *upi);
+static unsigned int _calc_sql_stmt_size(const char *procedure,
+ const char *schema, const char *table,
+ struct ulogd_key *keys,
+ unsigned int num_keys);
static void _bind_sql_stmt(struct ulogd_pluginstance *upi,
char *stmt);
@@ -410,33 +415,23 @@ _format_key(char *key)
return key;
}
-#define SQL_INSERTTEMPL "SELECT P(Y)"
-#define SQL_VALSIZE 100
-
/* create the static part of our insert statement */
static int
_create_sql_stmt(struct ulogd_pluginstance *upi)
{
struct db_instance *di = (struct db_instance *) upi->private;
+ char *procedure = procedure_ce(upi->config_kset).u.string;
+ char *table = table_ce(upi->config_kset).u.string;
unsigned int size;
unsigned int i;
- char *table = table_ce(upi->config_kset).u.string;
- char *procedure = procedure_ce(upi->config_kset).u.string;
+ char *stmtp;
if (di->stmt)
free(di->stmt);
- /* caclulate the size for the insert statement */
- size = strlen(SQL_INSERTTEMPL) + strlen(table);
-
- for (i = 0; i < upi->input.num_keys; i++) {
- if (upi->input.keys[i].flags & ULOGD_KEYF_INACTIVE)
- continue;
- /* we need space for the key and a comma, as well as
- * enough space for the values */
- size += strlen(upi->input.keys[i].name) + 1 + SQL_VALSIZE;
- }
- size += strlen(procedure);
+ /* calculate the size for the insert statement */
+ size = _calc_sql_stmt_size(procedure, di->schema, table,
+ upi->input.keys, upi->input.num_keys);
ulogd_log(ULOGD_DEBUG, "allocating %u bytes for statement\n", size);
@@ -447,22 +442,22 @@ _create_sql_stmt(struct ulogd_pluginstance *upi)
}
di->ring.length = size + 1;
- if (strncasecmp(procedure,"INSERT", strlen("INSERT")) == 0 &&
- (procedure[strlen("INSERT")] == '\0' ||
- procedure[strlen("INSERT")] == ' ')) {
- char *stmt_val = di->stmt;
+ stmtp = di->stmt;
+
+ if (strncasecmp(procedure, "INSERT", sizeof("INSERT") - 1) == 0 &&
+ (procedure[sizeof("INSERT") - 1] == '\0' ||
+ procedure[sizeof("INSERT") - 1] == ' ')) {
- if(procedure[6] == '\0') {
+ if(procedure[sizeof("INSERT") - 1] == '\0') {
/* procedure == "INSERT" */
if (di->schema)
- stmt_val += sprintf(stmt_val,
- "insert into %s.%s (",
- di->schema, table);
+ stmtp += sprintf(stmtp, "insert into %s.%s (",
+ di->schema, table);
else
- stmt_val += sprintf(stmt_val,
- "insert into %s (", table);
+ stmtp += sprintf(stmtp, "insert into %s (",
+ table);
} else
- stmt_val += sprintf(stmt_val, "%s (", procedure);
+ stmtp += sprintf(stmtp, "%s (", procedure);
for (i = 0; i < upi->input.num_keys; i++) {
char *underscore;
@@ -470,30 +465,96 @@ _create_sql_stmt(struct ulogd_pluginstance *upi)
if (upi->input.keys[i].flags & ULOGD_KEYF_INACTIVE)
continue;
- underscore = stmt_val;
+ underscore = stmtp;
- stmt_val += sprintf(stmt_val, "%s,",
- upi->input.keys[i].name);
+ stmtp += sprintf(stmtp, "%s,",
+ upi->input.keys[i].name);
while ((underscore = strchr(underscore, '.')))
*underscore = '_';
}
- *(stmt_val - 1) = ')';
+ stmtp --;
- sprintf(stmt_val, " values (");
- } else if (strncasecmp(procedure,"CALL", strlen("CALL")) == 0) {
- sprintf(di->stmt, "CALL %s(", procedure);
- } else {
- sprintf(di->stmt, "SELECT %s(", procedure);
- }
+ stmtp += sprintf(stmtp, ") values (");
+
+ } else if (strncasecmp(procedure, "CALL", sizeof("CALL") - 1) == 0)
+ stmtp += sprintf(stmtp, "CALL %s(", procedure);
+ else
+ stmtp += sprintf(stmtp, "SELECT %s(", procedure);
- di->stmt_offset = strlen(di->stmt);
+ di->stmt_offset = stmtp - di->stmt;
ulogd_log(ULOGD_DEBUG, "stmt='%s'\n", di->stmt);
return 0;
}
+#define SQL_VALSIZE 100
+
+static unsigned int
+_calc_sql_stmt_size(const char *procedure,
+ const char *schema, const char *table,
+ struct ulogd_key *keys, unsigned int num_keys)
+{
+ unsigned int i, size = 0;
+ bool include_keys;
+
+ /* Fixed size bit */
+
+ if (strncasecmp(procedure, "INSERT", sizeof("INSERT") - 1) == 0 &&
+ (procedure[sizeof("INSERT") - 1] == '\0' ||
+ procedure[sizeof("INSERT") - 1] == ' ')) {
+
+ /* insert into t (k0, k1, ...) values (v0, v1, ...) */
+
+ if(procedure[sizeof("INSERT") - 1] == '\0') {
+ /* procedure == "INSERT" */
+ if (schema)
+ size += snprintf(NULL, 0,
+ "insert into %s.%s (",
+ schema, table);
+ else
+ size += snprintf(NULL, 0,
+ "insert into %s (", table);
+ } else
+ size += snprintf(NULL, 0, "%s (", procedure);
+
+ size += snprintf(NULL, 0, ") values (");
+
+ include_keys = true;
+
+ } else {
+
+ /* `call p(v0, v1, ...)` or `select p(v0, v1, ...)` */
+
+ if (strncasecmp(procedure, "CALL", sizeof("CALL") - 1) == 0)
+ size += snprintf(NULL, 0, "CALL %s(", procedure);
+ else
+ size += snprintf(NULL, 0, "SELECT %s(", procedure);
+
+ include_keys = false;
+
+ }
+
+ /* Per-field bits.
+ *
+ * We need space for the value and a comma or the closing parenthesis.
+ * We may also need space for the key and a comma.
+ */
+
+ for (i = 0; i < num_keys; i++) {
+ if (keys[i].flags & ULOGD_KEYF_INACTIVE)
+ continue;
+ if (include_keys)
+ size += strlen(keys[i].name) + 1;
+ size += SQL_VALSIZE + 1;
+ }
+
+ size++; /* Allow for the final NUL */
+
+ return size;
+}
+
static void
_bind_sql_stmt(struct ulogd_pluginstance *upi, char *start)
{
--
2.35.1
next prev parent reply other threads:[~2022-11-29 21:58 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 ` Jeremy Sowden [this message]
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 ` [PATCH ulogd2 v2 v2 34/34] output: sqlite3: reimplement using the common DB API Jeremy Sowden
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-20-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).