]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-sql: Try to reuse prepared statements if possible
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Sun, 15 Sep 2019 18:39:07 +0000 (21:39 +0300)
committerTimo Sirainen <timo.sirainen@open-xchange.com>
Mon, 16 Sep 2019 08:00:54 +0000 (08:00 +0000)
src/lib-sql/driver-cassandra.c
src/lib-sql/sql-api-private.h
src/lib-sql/sql-api.c

index 1976dd27f1aa42e0fa39f8417b6475fdcd562cbe..daddaeca3cefab2eda25f48b1c82380446cb086f 100644 (file)
@@ -2048,6 +2048,7 @@ driver_cassandra_prepared_statement_init(struct sql_db *db,
        struct cassandra_sql_prepared_statement *prep_stmt =
                i_new(struct cassandra_sql_prepared_statement, 1);
        prep_stmt->prep_stmt.db = db;
+       prep_stmt->prep_stmt.refcount = 1;
        prep_stmt->prep_stmt.query_template = i_strdup(query_template);
        i_array_init(&prep_stmt->pending_statements, 4);
        prepare_start(prep_stmt);
index 022c5e9e391c61030a5d56715b4e70301c6607b4..f8b91c181833ce876fa0101b917f096152a9f06d 100644 (file)
@@ -135,6 +135,7 @@ struct sql_db {
        void *state_change_context;
 
        struct event *event;
+       HASH_TABLE(char *, struct sql_prepared_statement *) prepared_stmt_hash;
 
        enum sql_db_state state;
        /* last time we started connecting to this server
@@ -178,6 +179,7 @@ struct sql_result_vfuncs {
 
 struct sql_prepared_statement {
        struct sql_db *db;
+       int refcount;
        char *query_template;
 };
 
index 39b2913b29d0e276f76a0d659475f71004a6c0fc..d019b5f93421a37ec8ee7f56663191e32db8f695 100644 (file)
@@ -3,6 +3,7 @@
 #include "lib.h"
 #include "array.h"
 #include "ioloop.h"
+#include "hash.h"
 #include "str.h"
 #include "time-util.h"
 #include "sql-api-private.h"
@@ -104,6 +105,8 @@ int sql_init_full(const struct sql_settings *set, struct sql_db **db_r,
 
        i_array_init(&db->module_contexts, 5);
        db->refcount = 1;
+       hash_table_create(&db->prepared_stmt_hash, default_pool, 0,
+                         str_hash, strcmp);
        *db_r = db;
        return 0;
 }
@@ -125,6 +128,8 @@ void sql_unref(struct sql_db **_db)
                return;
 
        timeout_remove(&db->to_reconnect);
+       i_assert(hash_table_count(db->prepared_stmt_hash) == 0);
+       hash_table_destroy(&db->prepared_stmt_hash);
        db->v.deinit(db);
 }
 
@@ -197,6 +202,7 @@ default_sql_prepared_statement_init(struct sql_db *db,
 
        prep_stmt = i_new(struct sql_prepared_statement, 1);
        prep_stmt->db = db;
+       prep_stmt->refcount = 1;
        prep_stmt->query_template = i_strdup(query_template);
        return prep_stmt;
 }
@@ -271,10 +277,21 @@ static void default_sql_update_stmt(struct sql_transaction_context *ctx,
 struct sql_prepared_statement *
 sql_prepared_statement_init(struct sql_db *db, const char *query_template)
 {
+       struct sql_prepared_statement *stmt;
+
+       stmt = hash_table_lookup(db->prepared_stmt_hash, query_template);
+       if (stmt != NULL) {
+               stmt->refcount++;
+               return stmt;
+       }
+
        if (db->v.prepared_statement_init != NULL)
-               return db->v.prepared_statement_init(db, query_template);
+               stmt = db->v.prepared_statement_init(db, query_template);
        else
-               return default_sql_prepared_statement_init(db, query_template);
+               stmt = default_sql_prepared_statement_init(db, query_template);
+
+       hash_table_insert(db->prepared_stmt_hash, stmt->query_template, stmt);
+       return stmt;
 }
 
 void sql_prepared_statement_deinit(struct sql_prepared_statement **_prep_stmt)
@@ -282,6 +299,11 @@ void sql_prepared_statement_deinit(struct sql_prepared_statement **_prep_stmt)
        struct sql_prepared_statement *prep_stmt = *_prep_stmt;
 
        *_prep_stmt = NULL;
+
+       i_assert(prep_stmt->refcount > 0);
+       if (--prep_stmt->refcount > 0)
+               return;
+
        if (prep_stmt->db->v.prepared_statement_deinit != NULL)
                prep_stmt->db->v.prepared_statement_deinit(prep_stmt);
        else