From: Aki Tuomi Date: Mon, 6 Jun 2016 09:19:15 +0000 (+0300) Subject: gpgsql: Use lazy statements X-Git-Tag: auth-4.0.0-rc1~5^2~9 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=936dfaf7e85210f3d9d0ef261a3c7e6ebbf39bbf;p=thirdparty%2Fpdns.git gpgsql: Use lazy statements --- diff --git a/modules/gpgsqlbackend/spgsql.cc b/modules/gpgsqlbackend/spgsql.cc index d45c34bde4..cac0814d1f 100644 --- a/modules/gpgsqlbackend/spgsql.cc +++ b/modules/gpgsqlbackend/spgsql.cc @@ -17,31 +17,11 @@ class SPgSQLStatement: public SSqlStatement { public: SPgSQLStatement(const string& query, bool dolog, int nparams, SPgSQL* db) { - struct timeval tv; - d_query = query; d_dolog = dolog; d_parent = db; - - // prepare a statement - gettimeofday(&tv,NULL); - this->d_stmt = string("stmt") + std::to_string(tv.tv_sec) + std::to_string(tv.tv_usec); - + d_prepared = false; d_nparams = nparams; - - PGresult* res = PQprepare(d_db(), d_stmt.c_str(), d_query.c_str(), d_nparams, NULL); - ExecStatusType status = PQresultStatus(res); - string errmsg(PQresultErrorMessage(res)); - PQclear(res); - if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK && status != PGRES_NONFATAL_ERROR) { - throw SSqlException("Fatal error during prepare: " + d_query + string(": ") + errmsg); - } - paramValues=NULL; - d_cur_set=d_paridx=d_residx=d_resnum=d_fnum=0; - paramLengths=NULL; - d_res=NULL; - d_res_set=NULL; - d_do_commit=false; } SSqlStatement* bind(const string& name, bool value) { return bind(name, string(value ? "t" : "f")); } @@ -52,9 +32,12 @@ public: SSqlStatement* bind(const string& name, long long value) { return bind(name, std::to_string(value)); } SSqlStatement* bind(const string& name, unsigned long long value) { return bind(name, std::to_string(value)); } SSqlStatement* bind(const string& name, const std::string& value) { + prepareStatement(); allocate(); - if (d_paridx>=d_nparams) + if (d_paridx>=d_nparams) { + releaseStatement(); throw SSqlException("Attempt to bind more parameters than query has: " + d_query); + } paramValues[d_paridx] = new char[value.size()+1]; memset(paramValues[d_paridx], 0, sizeof(char)*(value.size()+1)); value.copy(paramValues[d_paridx], value.size()); @@ -62,8 +45,9 @@ public: d_paridx++; return this; } - SSqlStatement* bindNull(const string& name) { d_paridx++; return this; } // these are set null in allocate() + SSqlStatement* bindNull(const string& name) { prepareStatement(); d_paridx++; return this; } // these are set null in allocate() SSqlStatement* execute() { + prepareStatement(); if (d_dolog) { L<in_trx() && d_do_commit) { - PQexec(d_db(),"COMMIT"); + PGresult *res = PQexec(d_db(),"COMMIT"); + PQclear(res); } d_do_commit = false; if (d_res) @@ -185,13 +169,44 @@ public: const std::string& getQuery() { return d_query; } ~SPgSQLStatement() { - reset(); + releaseStatement(); } private: PGconn* d_db() { return d_parent->db(); } + void releaseStatement() { + d_prepared = false; + reset(); + string cmd = string("DEALLOCATE " + d_stmt); + PGresult *res = PQexec(d_db(), cmd.c_str()); + PQclear(res); + } + + void prepareStatement() { + struct timeval tv; + if (d_prepared) return; + // prepare a statement + gettimeofday(&tv,NULL); + this->d_stmt = string("stmt") + std::to_string(tv.tv_sec) + std::to_string(tv.tv_usec); + PGresult* res = PQprepare(d_db(), d_stmt.c_str(), d_query.c_str(), d_nparams, NULL); + ExecStatusType status = PQresultStatus(res); + string errmsg(PQresultErrorMessage(res)); + PQclear(res); + if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK && status != PGRES_NONFATAL_ERROR) { + releaseStatement(); + throw SSqlException("Fatal error during prepare: " + d_query + string(": ") + errmsg); + } + paramValues=NULL; + d_cur_set=d_paridx=d_residx=d_resnum=d_fnum=0; + paramLengths=NULL; + d_res=NULL; + d_res_set=NULL; + d_do_commit=false; + d_prepared = true; + } + void allocate() { if (paramValues != NULL) return; paramValues = new char*[d_nparams]; @@ -206,6 +221,7 @@ private: PGresult *d_res_set; PGresult *d_res; bool d_dolog; + bool d_prepared; int d_nparams; int d_paridx; char **paramValues;