]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
gpgsql: Use lazy statements
authorAki Tuomi <cmouse@cmouse.fi>
Mon, 6 Jun 2016 09:19:15 +0000 (12:19 +0300)
committerAki Tuomi <cmouse@cmouse.fi>
Mon, 6 Jun 2016 18:02:45 +0000 (21:02 +0300)
modules/gpgsqlbackend/spgsql.cc

index d45c34bde401bac742a4a86522190f25fd43ea07..cac0814d1f30c70a8ce98aeb5bc64b0bc2ac8424 100644 (file)
@@ -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<<Logger::Warning<<"Query: "<<d_query<<endl;
     }
@@ -76,8 +60,7 @@ public:
     string errmsg(PQresultErrorMessage(d_res_set));
     if (status != PGRES_COMMAND_OK && status != PGRES_TUPLES_OK && status != PGRES_NONFATAL_ERROR) {
       string errmsg(PQresultErrorMessage(d_res_set));
-      PQclear(d_res_set);
-      d_res_set = NULL;
+      releaseStatement();
       throw SSqlException("Fatal error during query: " + d_query + string(": ") + errmsg);
     }
     d_cur_set = 0;
@@ -162,7 +145,8 @@ public:
   SSqlStatement* reset() {
      int i;
      if (!d_parent->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;