]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
use as few calls to handle function as possible
authorRazvan Becheriu <razvan@isc.org>
Mon, 6 May 2019 10:06:46 +0000 (13:06 +0300)
committerRazvan Becheriu <razvan@isc.org>
Mon, 6 May 2019 10:06:46 +0000 (13:06 +0300)
src/lib/dhcpsrv/mysql_host_data_source.cc
src/lib/dhcpsrv/mysql_lease_mgr.cc
src/lib/dhcpsrv/pgsql_host_data_source.cc
src/lib/dhcpsrv/pgsql_lease_mgr.cc
src/lib/dhcpsrv/tests/mysql_host_data_source_unittest.cc
src/lib/dhcpsrv/tests/pgsql_host_data_source_unittest.cc
src/lib/mysql/mysql_connection.cc
src/lib/mysql/mysql_connection.h
src/lib/mysql/tests/mysql_connection_unittest.cc
src/lib/pgsql/pgsql_connection.cc
src/lib/pgsql/tests/pgsql_exchange_unittest.cc

index 0c263ec54bf17455b7fcddd6fbc6c4a013738407..71e4c6defb6f3a4462d175bbce94af17dd9cfe6c 100644 (file)
@@ -2462,11 +2462,13 @@ MySqlHostDataSourceImpl::getVersion() const {
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
               DHCPSRV_MYSQL_HOST_DB_GET_VERSION);
 
+    MySqlHolder& holderHandle = conn_.handle();
+
     // Allocate a new statement.
-    MYSQL_STMT *stmt = mysql_stmt_init(conn_.handle());
+    MYSQL_STMT *stmt = mysql_stmt_init(holderHandle);
     if (stmt == NULL) {
         isc_throw(DbOperationError, "unable to allocate MySQL prepared "
-                  "statement structure, reason: " << mysql_error(conn_.handle()));
+                  "statement structure, reason: " << mysql_error(holderHandle));
     }
 
     // Prepare the statement from SQL text.
@@ -2475,14 +2477,14 @@ MySqlHostDataSourceImpl::getVersion() const {
     if (status != 0) {
         mysql_stmt_close(stmt);
         isc_throw(DbOperationError, "unable to prepare MySQL statement <"
-                  << version_sql << ">, reason: " << mysql_error(conn_.handle()));
+                  << version_sql << ">, reason: " << mysql_error(holderHandle));
     }
 
     // Execute the prepared statement.
     if (mysql_stmt_execute(stmt) != 0) {
         mysql_stmt_close(stmt);
         isc_throw(DbOperationError, "cannot execute schema version query <"
-                  << version_sql << ">, reason: " << mysql_error(conn_.handle()));
+                  << version_sql << ">, reason: " << mysql_error(holderHandle));
     }
 
     // Bind the output of the statement to the appropriate variables.
@@ -2503,14 +2505,14 @@ MySqlHostDataSourceImpl::getVersion() const {
 
     if (mysql_stmt_bind_result(stmt, bind)) {
         isc_throw(DbOperationError, "unable to bind result set for <"
-                  << version_sql << ">, reason: " << mysql_error(conn_.handle()));
+                  << version_sql << ">, reason: " << mysql_error(holderHandle));
     }
 
     // Fetch the data.
     if (mysql_stmt_fetch(stmt)) {
         mysql_stmt_close(stmt);
         isc_throw(DbOperationError, "unable to bind result set for <"
-                  << version_sql << ">, reason: " << mysql_error(conn_.handle()));
+                  << version_sql << ">, reason: " << mysql_error(holderHandle));
     }
 
     // Discard the statement and its resources
@@ -2522,17 +2524,18 @@ MySqlHostDataSourceImpl::getVersion() const {
 void
 MySqlHostDataSourceImpl::addStatement(StatementIndex stindex,
                                       std::vector<MYSQL_BIND>& bind) {
+    MySqlHolder& holderHandle = conn_.handle();
 
     // Bind the parameters to the statement
-    int status = mysql_stmt_bind_param(conn_.handle().statements_[stindex], &bind[0]);
+    int status = mysql_stmt_bind_param(holderHandle.statements_[stindex], &bind[0]);
     checkError(status, stindex, "unable to bind parameters");
 
     // Execute the statement
-    status = mysql_stmt_execute(conn_.handle().statements_[stindex]);
+    status = mysql_stmt_execute(holderHandle.statements_[stindex]);
 
     if (status != 0) {
         // Failure: check for the special case of duplicate entry.
-        if (mysql_errno(conn_.handle()) == ER_DUP_ENTRY) {
+        if (mysql_errno(holderHandle) == ER_DUP_ENTRY) {
             isc_throw(DuplicateEntry, "Database duplicate entry error");
         }
         checkError(status, stindex, "unable to execute");
@@ -2542,19 +2545,21 @@ MySqlHostDataSourceImpl::addStatement(StatementIndex stindex,
 bool
 MySqlHostDataSourceImpl::delStatement(StatementIndex stindex,
                                       MYSQL_BIND* bind) {
+    MySqlHolder& holderHandle = conn_.handle();
+
     // Bind the parameters to the statement
-    int status = mysql_stmt_bind_param(conn_.handle().statements_[stindex], &bind[0]);
+    int status = mysql_stmt_bind_param(holderHandle.statements_[stindex], &bind[0]);
     checkError(status, stindex, "unable to bind parameters");
 
     // Execute the statement
-    status = mysql_stmt_execute(conn_.handle().statements_[stindex]);
+    status = mysql_stmt_execute(holderHandle.statements_[stindex]);
 
     if (status != 0) {
         checkError(status, stindex, "unable to execute");
     }
 
     // Let's check how many hosts were deleted.
-    my_ulonglong numrows = mysql_stmt_affected_rows(conn_.handle().statements_[stindex]);
+    my_ulonglong numrows = mysql_stmt_affected_rows(holderHandle.statements_[stindex]);
     return (numrows != 0);
 }
 
@@ -2623,32 +2628,33 @@ MySqlHostDataSourceImpl::
 getHostCollection(StatementIndex stindex, MYSQL_BIND* bind,
                   boost::shared_ptr<MySqlHostExchange> exchange,
                   ConstHostCollection& result, bool single) const {
+    MySqlHolder& holderHandle = conn_.handle();
 
     // Bind the selection parameters to the statement
-    int status = mysql_stmt_bind_param(conn_.handle().statements_[stindex], bind);
+    int status = mysql_stmt_bind_param(holderHandle.statements_[stindex], bind);
     checkError(status, stindex, "unable to bind WHERE clause parameter");
 
     // Set up the MYSQL_BIND array for the data being returned and bind it to
     // the statement.
     std::vector<MYSQL_BIND> outbind = exchange->createBindForReceive();
-    status = mysql_stmt_bind_result(conn_.handle().statements_[stindex], &outbind[0]);
+    status = mysql_stmt_bind_result(holderHandle.statements_[stindex], &outbind[0]);
     checkError(status, stindex, "unable to bind SELECT clause parameters");
 
     // Execute the statement
-    status = mysql_stmt_execute(conn_.handle().statements_[stindex]);
+    status = mysql_stmt_execute(holderHandle.statements_[stindex]);
     checkError(status, stindex, "unable to execute");
 
     // Ensure that all the lease information is retrieved in one go to avoid
     // overhead of going back and forth between client and server.
-    status = mysql_stmt_store_result(conn_.handle().statements_[stindex]);
+    status = mysql_stmt_store_result(holderHandle.statements_[stindex]);
     checkError(status, stindex, "unable to set up for storing all results");
 
     // Set up the fetch "release" object to release resources associated
     // with the call to mysql_stmt_fetch when this method exits, then
     // retrieve the data. mysql_stmt_fetch return value equal to 0 represents
     // successful data fetch.
-    MySqlFreeResult fetch_release(conn_.handle().statements_[stindex]);
-    while ((status = mysql_stmt_fetch(conn_.handle().statements_[stindex])) ==
+    MySqlFreeResult fetch_release(holderHandle.statements_[stindex]);
+    while ((status = mysql_stmt_fetch(holderHandle.statements_[stindex])) ==
            MLM_MYSQL_FETCH_SUCCESS) {
         try {
             exchange->processFetchedData(result);
@@ -2744,6 +2750,8 @@ MySqlHostDataSource::~MySqlHostDataSource() {
 
 void
 MySqlHostDataSource::add(const HostPtr& host) {
+    MySqlHolder& holderHandle = impl_->conn_.handle();
+
     // If operating in read-only mode, throw exception.
     impl_->checkReadOnly();
 
@@ -2763,7 +2771,7 @@ MySqlHostDataSource::add(const HostPtr& host) {
     impl_->addStatement(MySqlHostDataSourceImpl::INSERT_HOST, bind);
 
     // Gets the last inserted hosts id
-    uint64_t host_id = mysql_insert_id(impl_->conn_.handle());
+    uint64_t host_id = mysql_insert_id(holderHandle);
 
     // Insert DHCPv4 options.
     ConstCfgOptionPtr cfg_option4 = host->getCfgOption4();
index 34ecd73b836420f1ac05eb158bd6520ce048cc69..38e6fb8d971794d44dcd3ff65b0b75ab02d8c970 100644 (file)
@@ -1633,12 +1633,14 @@ private:
     /// Safely fetch the statement from the connection based on statement index
     /// @throw  BadValue if statement index is out of range
     void validateStatement() {
+        MySqlHolder& holderHandle = conn_.handle();
+
         if (statement_index_ >= MySqlLeaseMgr::NUM_STATEMENTS) {
             isc_throw(BadValue, "MySqlLeaseStatsQuery"
                       " - invalid statement index" << statement_index_);
         }
 
-        statement_ = conn_.handle().statements_[statement_index_];
+        statement_ = holderHandle.statements_[statement_index_];
     }
 
     /// @brief Database connection to use to execute the query
@@ -1710,19 +1712,20 @@ MySqlLeaseMgr::getDBVersion() {
 bool
 MySqlLeaseMgr::addLeaseCommon(StatementIndex stindex,
                               std::vector<MYSQL_BIND>& bind) {
+    MySqlHolder& holderHandle = conn_.handle();
 
     // Bind the parameters to the statement
-    int status = mysql_stmt_bind_param(conn_.handle().statements_[stindex], &bind[0]);
+    int status = mysql_stmt_bind_param(holderHandle.statements_[stindex], &bind[0]);
     checkError(status, stindex, "unable to bind parameters");
 
     // Execute the statement
-    status = mysql_stmt_execute(conn_.handle().statements_[stindex]);
+    status = mysql_stmt_execute(holderHandle.statements_[stindex]);
     if (status != 0) {
 
         // Failure: check for the special case of duplicate entry.  If this is
         // the case, we return false to indicate that the row was not added.
         // Otherwise we throw an exception.
-        if (mysql_errno(conn_.handle()) == ER_DUP_ENTRY) {
+        if (mysql_errno(holderHandle) == ER_DUP_ENTRY) {
             return (false);
         }
         checkError(status, stindex, "unable to execute");
@@ -1792,36 +1795,36 @@ void MySqlLeaseMgr::getLeaseCollection(StatementIndex stindex,
                                        Exchange& exchange,
                                        LeaseCollection& result,
                                        bool single) const {
-
+    MySqlHolder& holderHandle = conn_.handle();
     int status;
 
     if (bind) {
         // Bind the selection parameters to the statement
-        status = mysql_stmt_bind_param(conn_.handle().statements_[stindex], bind);
+        status = mysql_stmt_bind_param(holderHandle.statements_[stindex], bind);
         checkError(status, stindex, "unable to bind WHERE clause parameter");
     }
 
     // Set up the MYSQL_BIND array for the data being returned and bind it to
     // the statement.
     std::vector<MYSQL_BIND> outbind = exchange->createBindForReceive();
-    status = mysql_stmt_bind_result(conn_.handle().statements_[stindex], &outbind[0]);
+    status = mysql_stmt_bind_result(holderHandle.statements_[stindex], &outbind[0]);
     checkError(status, stindex, "unable to bind SELECT clause parameters");
 
     // Execute the statement
-    status = mysql_stmt_execute(conn_.handle().statements_[stindex]);
+    status = mysql_stmt_execute(holderHandle.statements_[stindex]);
     checkError(status, stindex, "unable to execute");
 
     // Ensure that all the lease information is retrieved in one go to avoid
     // overhead of going back and forth between client and server.
-    status = mysql_stmt_store_result(conn_.handle().statements_[stindex]);
+    status = mysql_stmt_store_result(holderHandle.statements_[stindex]);
     checkError(status, stindex, "unable to set up for storing all results");
 
     // Set up the fetch "release" object to release resources associated
     // with the call to mysql_stmt_fetch when this method exits, then
     // retrieve the data.
-    MySqlFreeResult fetch_release(conn_.handle().statements_[stindex]);
+    MySqlFreeResult fetch_release(holderHandle.statements_[stindex]);
     int count = 0;
-    while ((status = mysql_stmt_fetch(conn_.handle().statements_[stindex])) == 0) {
+    while ((status = mysql_stmt_fetch(holderHandle.statements_[stindex])) == 0) {
         try {
             result.push_back(exchange->getLeaseData());
 
@@ -2442,18 +2445,19 @@ template <typename LeasePtr>
 void
 MySqlLeaseMgr::updateLeaseCommon(StatementIndex stindex, MYSQL_BIND* bind,
                                  const LeasePtr& lease) {
+    MySqlHolder& holderHandle = conn_.handle();
 
     // Bind the parameters to the statement
-    int status = mysql_stmt_bind_param(conn_.handle().statements_[stindex], bind);
+    int status = mysql_stmt_bind_param(holderHandle.statements_[stindex], bind);
     checkError(status, stindex, "unable to bind parameters");
 
     // Execute
-    status = mysql_stmt_execute(conn_.handle().statements_[stindex]);
+    status = mysql_stmt_execute(holderHandle.statements_[stindex]);
     checkError(status, stindex, "unable to execute");
 
     // See how many rows were affected.  The statement should only update a
     // single row.
-    int affected_rows = mysql_stmt_affected_rows(conn_.handle().statements_[stindex]);
+    int affected_rows = mysql_stmt_affected_rows(holderHandle.statements_[stindex]);
     if (affected_rows == 0) {
         isc_throw(NoSuchLease, "unable to update lease for address " <<
                   lease->addr_ << " as it does not exist");
@@ -2530,18 +2534,19 @@ MySqlLeaseMgr::updateLease6(const Lease6Ptr& lease) {
 
 uint64_t
 MySqlLeaseMgr::deleteLeaseCommon(StatementIndex stindex, MYSQL_BIND* bind) {
+    MySqlHolder& holderHandle = conn_.handle();
 
     // Bind the input parameters to the statement
-    int status = mysql_stmt_bind_param(conn_.handle().statements_[stindex], bind);
+    int status = mysql_stmt_bind_param(holderHandle.statements_[stindex], bind);
     checkError(status, stindex, "unable to bind WHERE clause parameter");
 
     // Execute
-    status = mysql_stmt_execute(conn_.handle().statements_[stindex]);
+    status = mysql_stmt_execute(holderHandle.statements_[stindex]);
     checkError(status, stindex, "unable to execute");
 
     // See how many rows were affected.  Note that the statement may delete
     // multiple rows.
-    return (static_cast<uint64_t>(mysql_stmt_affected_rows(conn_.handle().statements_[stindex])));
+    return (static_cast<uint64_t>(mysql_stmt_affected_rows(holderHandle.statements_[stindex])));
 }
 
 bool
@@ -2715,11 +2720,13 @@ MySqlLeaseMgr::getVersion() const {
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
               DHCPSRV_MYSQL_GET_VERSION);
 
+    MySqlHolder& holderHandle = conn_.handle();
+
     // Allocate a new statement.
-    MYSQL_STMT *stmt = mysql_stmt_init(conn_.handle());
+    MYSQL_STMT *stmt = mysql_stmt_init(holderHandle);
     if (stmt == NULL) {
         isc_throw(DbOperationError, "unable to allocate MySQL prepared "
-                  "statement structure, reason: " << mysql_error(conn_.handle()));
+                  "statement structure, reason: " << mysql_error(holderHandle));
     }
 
     // Prepare the statement from SQL text.
@@ -2728,14 +2735,14 @@ MySqlLeaseMgr::getVersion() const {
     if (status != 0) {
         mysql_stmt_close(stmt);
         isc_throw(DbOperationError, "unable to prepare MySQL statement <"
-                  << version_sql << ">, reason: " << mysql_error(conn_.handle()));
+                  << version_sql << ">, reason: " << mysql_error(holderHandle));
     }
 
     // Execute the prepared statement.
     if (mysql_stmt_execute(stmt) != 0) {
         mysql_stmt_close(stmt);
         isc_throw(DbOperationError, "cannot execute schema version query <"
-                  << version_sql << ">, reason: " << mysql_error(conn_.handle()));
+                  << version_sql << ">, reason: " << mysql_error(holderHandle));
     }
 
     // Bind the output of the statement to the appropriate variables.
@@ -2756,14 +2763,14 @@ MySqlLeaseMgr::getVersion() const {
 
     if (mysql_stmt_bind_result(stmt, bind)) {
         isc_throw(DbOperationError, "unable to bind result set for <"
-                  << version_sql << ">, reason: " << mysql_error(conn_.handle()));
+                  << version_sql << ">, reason: " << mysql_error(holderHandle));
     }
 
     // Fetch the data.
     if (mysql_stmt_fetch(stmt)) {
         mysql_stmt_close(stmt);
         isc_throw(DbOperationError, "unable to bind result set for <"
-                  << version_sql << ">, reason: " << mysql_error(conn_.handle()));
+                  << version_sql << ">, reason: " << mysql_error(holderHandle));
     }
 
     // Discard the statement and its resources
@@ -2775,16 +2782,22 @@ MySqlLeaseMgr::getVersion() const {
 void
 MySqlLeaseMgr::commit() {
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MYSQL_COMMIT);
-    if (mysql_commit(conn_.handle()) != 0) {
-        isc_throw(DbOperationError, "commit failed: " << mysql_error(conn_.handle()));
+
+    MySqlHolder& holderHandle = conn_.handle();
+
+    if (mysql_commit(holderHandle) != 0) {
+        isc_throw(DbOperationError, "commit failed: " << mysql_error(holderHandle));
     }
 }
 
 void
 MySqlLeaseMgr::rollback() {
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MYSQL_ROLLBACK);
-    if (mysql_rollback(conn_.handle()) != 0) {
-        isc_throw(DbOperationError, "rollback failed: " << mysql_error(conn_.handle()));
+
+    MySqlHolder& holderHandle = conn_.handle();
+
+    if (mysql_rollback(holderHandle) != 0) {
+        isc_throw(DbOperationError, "rollback failed: " << mysql_error(holderHandle));
     }
 }
 
index 9cf7f7756b2a5574c73640f97895228f1b27afb3..1a51b345c8823ad18b96401497b0c33626c3c8b4 100644 (file)
@@ -1847,8 +1847,10 @@ uint64_t
 PgSqlHostDataSourceImpl::addStatement(StatementIndex stindex,
                                       PsqlBindArrayPtr& bind_array,
                                       const bool return_last_id) {
+    PgSqlHolder& holderHandle = conn_.handle();
     uint64_t last_id = 0;
-    PgSqlResult r(PQexecPrepared(conn_.handle(), tagged_statements[stindex].name,
+
+    PgSqlResult r(PQexecPrepared(holderHandle, tagged_statements[stindex].name,
                                  tagged_statements[stindex].nbparams,
                                  &bind_array->values_[0],
                                  &bind_array->lengths_[0],
@@ -1877,7 +1879,9 @@ PgSqlHostDataSourceImpl::addStatement(StatementIndex stindex,
 bool
 PgSqlHostDataSourceImpl::delStatement(StatementIndex stindex,
                                       PsqlBindArrayPtr& bind_array) {
-    PgSqlResult r(PQexecPrepared(conn_.handle(), tagged_statements[stindex].name,
+    PgSqlHolder& holderHandle = conn_.handle();
+
+    PgSqlResult r(PQexecPrepared(holderHandle, tagged_statements[stindex].name,
                                  tagged_statements[stindex].nbparams,
                                  &bind_array->values_[0],
                                  &bind_array->lengths_[0],
@@ -1958,9 +1962,10 @@ PgSqlHostDataSourceImpl::
 getHostCollection(StatementIndex stindex, PsqlBindArrayPtr bind_array,
                   boost::shared_ptr<PgSqlHostExchange> exchange,
                   ConstHostCollection& result, bool single) const {
+    PgSqlHolder& holderHandle = conn_.handle();
 
     exchange->clear();
-    PgSqlResult r(PQexecPrepared(conn_.handle(), tagged_statements[stindex].name,
+    PgSqlResult r(PQexecPrepared(holderHandle, tagged_statements[stindex].name,
                                  tagged_statements[stindex].nbparams,
                                  &bind_array->values_[0],
                                  &bind_array->lengths_[0],
@@ -2018,11 +2023,13 @@ PgSqlHostDataSourceImpl::getVersion() const {
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
               DHCPSRV_PGSQL_HOST_DB_GET_VERSION);
 
+    PgSqlHolder& holderHandle = conn_.handle();
     const char* version_sql =  "SELECT version, minor FROM schema_version;";
-    PgSqlResult r(PQexec(conn_.handle(), version_sql));
+
+    PgSqlResult r(PQexec(holderHandle, version_sql));
     if(PQresultStatus(r) != PGRES_TUPLES_OK) {
         isc_throw(DbOperationError, "unable to execute PostgreSQL statement <"
-                  << version_sql << ">, reason: " << PQerrorMessage(conn_.handle()));
+                  << version_sql << ">, reason: " << PQerrorMessage(holderHandle));
     }
 
     uint32_t major;
index 573e503027603f22addda0f3fa822a26308ddbb5..691f867ed82e693b643346aa3eb697ace3db69f1 100644 (file)
@@ -986,10 +986,11 @@ public:
     /// parameters (for all subnets), a subnet id for a single subnet, or
     /// a first and last subnet id for a subnet range.
     void start() {
+        PgSqlHolder& holderHandle = conn_.handle();
 
         if (getSelectMode() == ALL_SUBNETS) {
             // Run the query with no where clause parameters.
-            result_set_.reset(new PgSqlResult(PQexecPrepared(conn_.handle(), statement_.name,
+            result_set_.reset(new PgSqlResult(PQexecPrepared(holderHandle, statement_.name,
                                                              0, 0, 0, 0, 0)));
         } else {
             // Set up the WHERE clause values
@@ -1007,7 +1008,7 @@ public:
             }
 
             // Run the query with where clause parameters.
-            result_set_.reset(new PgSqlResult(PQexecPrepared(conn_.handle(), statement_.name,
+            result_set_.reset(new PgSqlResult(PQexecPrepared(holderHandle, statement_.name,
                                               parms.size(), &parms.values_[0],
                                               &parms.lengths_[0], &parms.formats_[0], 0)));
         }
@@ -1125,7 +1126,9 @@ PgSqlLeaseMgr::getDBVersion() {
 bool
 PgSqlLeaseMgr::addLeaseCommon(StatementIndex stindex,
                               PsqlBindArray& bind_array) {
-    PgSqlResult r(PQexecPrepared(conn_.handle(), tagged_statements[stindex].name,
+    PgSqlHolder& holderHandle = conn_.handle();
+
+    PgSqlResult r(PQexecPrepared(holderHandle, tagged_statements[stindex].name,
                                  tagged_statements[stindex].nbparams,
                                  &bind_array.values_[0],
                                  &bind_array.lengths_[0],
@@ -1177,8 +1180,10 @@ void PgSqlLeaseMgr::getLeaseCollection(StatementIndex stindex,
                                        Exchange& exchange,
                                        LeaseCollection& result,
                                        bool single) const {
+    PgSqlHolder& holderHandle = conn_.handle();
     const int n = tagged_statements[stindex].nbparams;
-    PgSqlResult r(PQexecPrepared(conn_.handle(), tagged_statements[stindex].name, n,
+
+    PgSqlResult r(PQexecPrepared(holderHandle, tagged_statements[stindex].name, n,
                                  n > 0 ? &bind_array.values_[0] : NULL,
                                  n > 0 ? &bind_array.lengths_[0] : NULL,
                                  n > 0 ? &bind_array.formats_[0] : NULL, 0));
@@ -1663,7 +1668,9 @@ PgSqlLeaseMgr::updateLeaseCommon(StatementIndex stindex,
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
               DHCPSRV_PGSQL_ADD_ADDR4).arg(tagged_statements[stindex].name);
 
-    PgSqlResult r(PQexecPrepared(conn_.handle(), tagged_statements[stindex].name,
+    PgSqlHolder& holderHandle = conn_.handle();
+
+    PgSqlResult r(PQexecPrepared(holderHandle, tagged_statements[stindex].name,
                                  tagged_statements[stindex].nbparams,
                                  &bind_array.values_[0],
                                  &bind_array.lengths_[0],
@@ -1735,7 +1742,9 @@ PgSqlLeaseMgr::updateLease6(const Lease6Ptr& lease) {
 uint64_t
 PgSqlLeaseMgr::deleteLeaseCommon(StatementIndex stindex,
                                  PsqlBindArray& bind_array) {
-    PgSqlResult r(PQexecPrepared(conn_.handle(), tagged_statements[stindex].name,
+    PgSqlHolder& holderHandle = conn_.handle();
+
+    PgSqlResult r(PQexecPrepared(holderHandle, tagged_statements[stindex].name,
                                  tagged_statements[stindex].nbparams,
                                  &bind_array.values_[0],
                                  &bind_array.lengths_[0],
@@ -1886,11 +1895,13 @@ PgSqlLeaseMgr::getVersion() const {
     LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
               DHCPSRV_PGSQL_GET_VERSION);
 
+    PgSqlHolder& holderHandle = conn_.handle();
     const char* version_sql =  "SELECT version, minor FROM schema_version;";
-    PgSqlResult r(PQexec(conn_.handle(), version_sql));
+
+    PgSqlResult r(PQexec(holderHandle, version_sql));
     if(PQresultStatus(r) != PGRES_TUPLES_OK) {
         isc_throw(DbOperationError, "unable to execute PostgreSQL statement <"
-                  << version_sql << ">, reason: " << PQerrorMessage(conn_.handle()));
+                  << version_sql << ">, reason: " << PQerrorMessage(holderHandle));
     }
 
     uint32_t major;
index fc75ec707f78e4a6202af6cd423ddbf3a17c6cef..73f5faecd6ece13bf4c6dc7f39bab4b565b45f28 100644 (file)
@@ -120,12 +120,14 @@ public:
         MySqlConnection conn(params);
         conn.openDatabase();
 
-        int status = mysql_query(conn.handle(), query.c_str());
+        MySqlHolder& holderHandle = conn.handle();
+
+        int status = mysql_query(holderHandle, query.c_str());
         if (status !=0) {
-            isc_throw(DbOperationError, "Query failed: " << mysql_error(conn.handle()));
+            isc_throw(DbOperationError, "Query failed: " << mysql_error(holderHandle));
         }
 
-        MYSQL_RES * res = mysql_store_result(conn.handle());
+        MYSQL_RES * res = mysql_store_result(holderHandle);
         int numrows = static_cast<int>(mysql_num_rows(res));
         mysql_free_result(res);
 
@@ -641,9 +643,10 @@ TEST_F(MySqlHostDataSourceTest, testAddRollback) {
     MySqlConnection conn(params);
     ASSERT_NO_THROW(conn.openDatabase());
 
-    int status = mysql_query(conn.handle(),
-                             "DROP TABLE IF EXISTS ipv6_reservations");
-    ASSERT_EQ(0, status) << mysql_error(conn.handle());
+    MySqlHolder& holderHandle = conn.handle();
+
+    int status = mysql_query(holderHandle, "DROP TABLE IF EXISTS ipv6_reservations");
+    ASSERT_EQ(0, status) << mysql_error(holderHandle);
 
     // Create a host with a reservation.
     HostPtr host = HostDataSourceUtils::initializeHost6("2001:db8:1::1", Host::IDENT_HWADDR, false);
index 01582ce4222f392eb7fbe8a8e57e29d2706198d7..3badd7d777c484acee3192bafa9543eda851f74e 100644 (file)
@@ -119,9 +119,11 @@ public:
         PgSqlConnection conn(params);
         conn.openDatabase();
 
-        PgSqlResult r(PQexec(conn.handle(), query.c_str()));
+        PgSqlHolder& holderHandle = conn.handle();
+
+        PgSqlResult r(PQexec(holderHandle, query.c_str()));
         if (PQresultStatus(r) != PGRES_TUPLES_OK) {
-            isc_throw(DbOperationError, "Query failed:" << PQerrorMessage(conn.handle()));
+            isc_throw(DbOperationError, "Query failed:" << PQerrorMessage(holderHandle));
         }
 
         int numrows = PQntuples(r);
@@ -626,9 +628,11 @@ TEST_F(PgSqlHostDataSourceTest, testAddRollback) {
     PgSqlConnection conn(params);
     ASSERT_NO_THROW(conn.openDatabase());
 
-    PgSqlResult r(PQexec(conn.handle(), "DROP TABLE IF EXISTS ipv6_reservations"));
-    ASSERT_TRUE (PQresultStatus(r) == PGRES_COMMAND_OK)
-                 << " drop command failed :" << PQerrorMessage(conn.handle());
+    PgSqlHolder& holderHandle = conn.handle();
+
+    PgSqlResult r(PQexec(holderHandle, "DROP TABLE IF EXISTS ipv6_reservations"));
+    ASSERT_TRUE(PQresultStatus(r) == PGRES_COMMAND_OK)
+                << " drop command failed :" << PQerrorMessage(holderHandle);
 
     // Create a host with a reservation.
     HostPtr host = HostDataSourceUtils::initializeHost6("2001:db8:1::1",
index 874b43884d0c89063a8f546d78ec896f6f5546f6..3c573646102e559869de8e03b92fd7df47e587da 100644 (file)
@@ -200,18 +200,20 @@ MySqlConnection::openDatabase() {
     // connection after a reconnect as among other things, it drops all our
     // pre-compiled statements.
     my_bool auto_reconnect = MLM_FALSE;
-    int result = mysql_options(handle(), MYSQL_OPT_RECONNECT, &auto_reconnect);
+    MySqlHolder& holderHandle = handle();
+
+    int result = mysql_options(holderHandle, MYSQL_OPT_RECONNECT, &auto_reconnect);
     if (result != 0) {
         isc_throw(DbOpenError, "unable to set auto-reconnect option: " <<
-                  mysql_error(handle()));
+                  mysql_error(holderHandle));
     }
 
     // Make sure we have a large idle time window ... say 30 days...
     const char *wait_time = "SET SESSION wait_timeout = 30 * 86400";
-    result = mysql_options(handle(), MYSQL_INIT_COMMAND, wait_time);
+    result = mysql_options(holderHandle, MYSQL_INIT_COMMAND, wait_time);
     if (result != 0) {
         isc_throw(DbOpenError, "unable to set wait_timeout " <<
-                  mysql_error(handle()));
+                  mysql_error(holderHandle));
     }
 
     // Set SQL mode options for the connection:  SQL mode governs how what
@@ -219,18 +221,18 @@ MySqlConnection::openDatabase() {
     // invalid data.  We want to ensure we get the strictest behavior and
     // to reject invalid data with an error.
     const char *sql_mode = "SET SESSION sql_mode ='STRICT_ALL_TABLES'";
-    result = mysql_options(handle(), MYSQL_INIT_COMMAND, sql_mode);
+    result = mysql_options(holderHandle, MYSQL_INIT_COMMAND, sql_mode);
     if (result != 0) {
         isc_throw(DbOpenError, "unable to set SQL mode options: " <<
-                  mysql_error(handle()));
+                  mysql_error(holderHandle));
     }
 
     // Connection timeout, the amount of time taken for the client to drop
     // the connection if the server is not responding.
-    result = mysql_options(handle(), MYSQL_OPT_CONNECT_TIMEOUT, &connect_timeout);
+    result = mysql_options(holderHandle, MYSQL_OPT_CONNECT_TIMEOUT, &connect_timeout);
     if (result != 0) {
         isc_throw(DbOpenError, "unable to set database connection timeout: " <<
-                  mysql_error(handle()));
+                  mysql_error(holderHandle));
     }
 
     // Open the database.
@@ -243,10 +245,10 @@ MySqlConnection::openDatabase() {
     // This makes it hard to distinguish whether the UPDATE changed no rows
     // because no row matching the WHERE clause was found, or because a
     // row was found but no data was altered.
-    MYSQL* status = mysql_real_connect(handle(), host, user, password, name,
+    MYSQL* status = mysql_real_connect(holderHandle, host, user, password, name,
                                        port, NULL, CLIENT_FOUND_ROWS);
-    if (status != handle()) {
-        isc_throw(DbOpenError, mysql_error(handle()));
+    if (status != holderHandle) {
+        isc_throw(DbOpenError, mysql_error(holderHandle));
     }
 
     // Enable autocommit. In case transaction is explicitly used, this
@@ -256,11 +258,11 @@ MySqlConnection::openDatabase() {
     // caused issues for some unit tests which were unable to cleanup
     // the database after the test because of pending transactions.
     // Use of autocommit will eliminate this problem.
-    my_bool auto_commit = mysql_autocommit(handle(), 1);
+    my_bool auto_commit = mysql_autocommit(holderHandle, 1);
     if (auto_commit != MLM_FALSE) {
-        isc_throw(DbOperationError, mysql_error(handle()));
+        isc_throw(DbOperationError, mysql_error(holderHandle));
     }
-    handle().connected_ = true;
+    holderHandle.connected_ = true;
     connected_ = true;
 }
 
@@ -340,28 +342,37 @@ MySqlConnection::startTransaction() {
     DB_LOG_DEBUG(DB_DBG_TRACE_DETAIL, MYSQL_START_TRANSACTION);
     // We create prepared statements for all other queries, but MySQL
     // don't support prepared statements for START TRANSACTION.
-    int status = mysql_query(handle(), "START TRANSACTION");
+
+    MySqlHolder& holderHandle = handle();
+
+    int status = mysql_query(holderHandle, "START TRANSACTION");
     if (status != 0) {
         isc_throw(DbOperationError, "unable to start transaction, "
-                  "reason: " << mysql_error(handle()));
+                  "reason: " << mysql_error(holderHandle));
     }
 }
 
 void
 MySqlConnection::commit() {
     DB_LOG_DEBUG(DB_DBG_TRACE_DETAIL, MYSQL_COMMIT);
-    if (mysql_commit(handle()) != 0) {
+
+    MySqlHolder& holderHandle = handle();
+
+    if (mysql_commit(holderHandle) != 0) {
         isc_throw(DbOperationError, "commit failed: "
-                  << mysql_error(handle()));
+                  << mysql_error(holderHandle));
     }
 }
 
 void
 MySqlConnection::rollback() {
     DB_LOG_DEBUG(DB_DBG_TRACE_DETAIL, MYSQL_ROLLBACK);
-    if (mysql_rollback(handle()) != 0) {
+
+    MySqlHolder& holderHandle = handle();
+
+    if (mysql_rollback(holderHandle) != 0) {
         isc_throw(DbOperationError, "rollback failed: "
-                  << mysql_error(handle()));
+                  << mysql_error(holderHandle));
     }
 }
 
index 7ce62009d5cc06f61a4c938b311975e9a1be7131..3d9108b961a7adc69719dac8cee52e82f1a2195b 100644 (file)
@@ -367,6 +367,8 @@ public:
                      const MySqlBindingCollection& in_bindings,
                      MySqlBindingCollection& out_bindings,
                      ConsumeResultFun process_result) {
+        MySqlHolder& holderHandle = handle();
+
         // Extract native input bindings.
         std::vector<MYSQL_BIND> in_bind_vec;
         for (MySqlBindingPtr in_binding : in_bindings) {
@@ -376,7 +378,7 @@ public:
         int status = 0;
         if (!in_bind_vec.empty()) {
             // Bind parameters to the prepared statement.
-            status = mysql_stmt_bind_param(handle().statements_[index], &in_bind_vec[0]);
+            status = mysql_stmt_bind_param(holderHandle.statements_[index], &in_bind_vec[0]);
             checkError(status, index, "unable to bind parameters for select");
         }
 
@@ -386,20 +388,20 @@ public:
             out_bind_vec.push_back(out_binding->getMySqlBinding());
         }
         if (!out_bind_vec.empty()) {
-            status = mysql_stmt_bind_result(handle().statements_[index], &out_bind_vec[0]);
+            status = mysql_stmt_bind_result(holderHandle.statements_[index], &out_bind_vec[0]);
             checkError(status, index, "unable to bind result parameters for select");
         }
 
         // Execute query.
-        status = mysql_stmt_execute(handle().statements_[index]);
+        status = mysql_stmt_execute(holderHandle.statements_[index]);
         checkError(status, index, "unable to execute");
 
-        status = mysql_stmt_store_result(handle().statements_[index]);
+        status = mysql_stmt_store_result(holderHandle.statements_[index]);
         checkError(status, index, "unable to set up for storing all results");
 
         // Fetch results.
-        MySqlFreeResult fetch_release(handle().statements_[index]);
-        while ((status = mysql_stmt_fetch(handle().statements_[index])) ==
+        MySqlFreeResult fetch_release(holderHandle.statements_[index]);
+        while ((status = mysql_stmt_fetch(holderHandle.statements_[index])) ==
                MLM_MYSQL_FETCH_SUCCESS) {
             try {
                 // For each returned row call user function which should
@@ -443,21 +445,23 @@ public:
     template<typename StatementIndex>
     void insertQuery(const StatementIndex& index,
                      const MySqlBindingCollection& in_bindings) {
+        MySqlHolder& holderHandle = handle();
         std::vector<MYSQL_BIND> in_bind_vec;
+
         for (MySqlBindingPtr in_binding : in_bindings) {
             in_bind_vec.push_back(in_binding->getMySqlBinding());
         }
 
         // Bind the parameters to the statement
-        int status = mysql_stmt_bind_param(handle().statements_[index], &in_bind_vec[0]);
+        int status = mysql_stmt_bind_param(holderHandle.statements_[index], &in_bind_vec[0]);
         checkError(status, index, "unable to bind parameters");
 
         // Execute the statement
-        status = mysql_stmt_execute(handle().statements_[index]);
+        status = mysql_stmt_execute(holderHandle.statements_[index]);
 
         if (status != 0) {
             // Failure: check for the special case of duplicate entry.
-            if (mysql_errno(handle()) == ER_DUP_ENTRY) {
+            if (mysql_errno(holderHandle) == ER_DUP_ENTRY) {
                 isc_throw(DuplicateEntry, "Database duplicate entry error");
             }
             checkError(status, index, "unable to execute");
@@ -481,29 +485,31 @@ public:
     template<typename StatementIndex>
     uint64_t updateDeleteQuery(const StatementIndex& index,
                                const MySqlBindingCollection& in_bindings) {
+        MySqlHolder& holderHandle = handle();
         std::vector<MYSQL_BIND> in_bind_vec;
+
         for (MySqlBindingPtr in_binding : in_bindings) {
             in_bind_vec.push_back(in_binding->getMySqlBinding());
         }
 
         // Bind the parameters to the statement
-        int status = mysql_stmt_bind_param(handle().statements_[index], &in_bind_vec[0]);
+        int status = mysql_stmt_bind_param(holderHandle.statements_[index], &in_bind_vec[0]);
         checkError(status, index, "unable to bind parameters");
 
         // Execute the statement
-        status = mysql_stmt_execute(handle().statements_[index]);
+        status = mysql_stmt_execute(holderHandle.statements_[index]);
 
         if (status != 0) {
             // Failure: check for the special case of duplicate entry.
-            if ((mysql_errno(handle()) == ER_DUP_ENTRY)
+            if ((mysql_errno(holderHandle) == ER_DUP_ENTRY)
 #ifdef ER_FOREIGN_DUPLICATE_KEY
-                || (mysql_errno(handle()) == ER_FOREIGN_DUPLICATE_KEY)
+                || (mysql_errno(holderHandle) == ER_FOREIGN_DUPLICATE_KEY)
 #endif
 #ifdef ER_FOREIGN_DUPLICATE_KEY_WITH_CHILD_INFO
-                || (mysql_errno(handle()) == ER_FOREIGN_DUPLICATE_KEY_WITH_CHILD_INFO)
+                || (mysql_errno(holderHandle) == ER_FOREIGN_DUPLICATE_KEY_WITH_CHILD_INFO)
 #endif
 #ifdef ER_FOREIGN_DUPLICATE_KEY_WITHOUT_CHILD_INFO
-                || (mysql_errno(handle()) == ER_FOREIGN_DUPLICATE_KEY_WITHOUT_CHILD_INFO)
+                || (mysql_errno(holderHandle) == ER_FOREIGN_DUPLICATE_KEY_WITHOUT_CHILD_INFO)
 #endif
                 ) {
                 isc_throw(DuplicateEntry, "Database duplicate entry error");
@@ -512,7 +518,7 @@ public:
         }
 
         // Let's return how many rows were affected.
-        return (static_cast<uint64_t>(mysql_stmt_affected_rows(handle().statements_[index])));
+        return (static_cast<uint64_t>(mysql_stmt_affected_rows(holderHandle.statements_[index])));
     }
 
 
@@ -565,8 +571,10 @@ public:
     template <typename StatementIndex>
     void checkError(const int status, const StatementIndex& index,
                     const char* what) const {
+        MySqlHolder& holderHandle = handle();
+
         if (status != 0) {
-            switch(mysql_errno(handle())) {
+            switch(mysql_errno(holderHandle)) {
                 // These are the ones we consider fatal. Remember this method is
                 // used to check errors of API calls made subsequent to successfully
                 // connecting.  Errors occurring while attempting to connect are
@@ -580,8 +588,8 @@ public:
                 DB_LOG_ERROR(db::MYSQL_FATAL_ERROR)
                     .arg(what)
                     .arg(text_statements_[static_cast<int>(index)])
-                    .arg(mysql_error(handle()))
-                    .arg(mysql_errno(handle()));
+                    .arg(mysql_error(holderHandle))
+                    .arg(mysql_errno(holderHandle));
 
                 // If there's no lost db callback or it returns false,
                 // then we're not attempting to recover so we're done
@@ -598,8 +606,8 @@ public:
                 isc_throw(db::DbOperationError, what << " for <"
                           << text_statements_[static_cast<int>(index)]
                           << ">, reason: "
-                          << mysql_error(handle()) << " (error code "
-                          << mysql_errno(handle()) << ")");
+                          << mysql_error(holderHandle) << " (error code "
+                          << mysql_errno(holderHandle) << ")");
             }
         }
     }
index 3b3f2daef051635172fbdbb6585b9ae345f4de23..5519160577a226e82a50467f5cb663cee1cb1eda 100644 (file)
@@ -119,22 +119,24 @@ public:
     ///
     /// @param sql Query in the textual form.
     void runQuery(const std::string& sql) {
-        MYSQL_STMT *stmt = mysql_stmt_init(conn_.handle());
+        MySqlHolder& holderHandle = conn_.handle();
+
+        MYSQL_STMT *stmt = mysql_stmt_init(holderHandle);
         if (stmt == NULL) {
             isc_throw(DbOperationError, "unable to allocate MySQL prepared "
-                  "statement structure, reason: " << mysql_error(conn_.handle()));
+                  "statement structure, reason: " << mysql_error(holderHandle));
         }
 
         int status = mysql_stmt_prepare(stmt, sql.c_str(), sql.length());
         if (status != 0) {
             isc_throw(DbOperationError, "unable to prepare MySQL statement <"
-                      << sql << ">, reason: " << mysql_errno(conn_.handle()));
+                      << sql << ">, reason: " << mysql_errno(holderHandle));
         }
 
         // Execute the prepared statement.
         if (mysql_stmt_execute(stmt) != 0) {
             isc_throw(DbOperationError, "cannot execute MySQL query <"
-                  << sql << ">, reason: " << mysql_errno(conn_.handle()));
+                  << sql << ">, reason: " << mysql_errno(holderHandle));
         }
 
         // Discard the statement and its resources
index 9b3257e8526653d09672c11f3bec6a6202b4a201..a51fa69cfbdc8e76d4f89784f9b933e8c7320d59 100644 (file)
@@ -307,8 +307,9 @@ PgSqlConnection::openDatabase() {
     }
 
     // We have a valid connection, so let's save it to our holder
-    handle().setConnection(new_conn);
-    handle().connected_ = true;
+    PgSqlHolder& holderHandle = handle();
+    holderHandle.setConnection(new_conn);
+    holderHandle.connected_ = true;
     connected_ = true;
 }
 
@@ -329,6 +330,9 @@ PgSqlConnection::checkStatementError(const PgSqlResult& r,
         // error class. Note, there is a severity field, but it can be
         // misleadingly returned as fatal. However, a loss of connectivity
         // can lead to a NULL sqlstate with a status of PGRES_FATAL_ERROR.
+
+        PgSqlHolder& holderHandle = handle();
+
         const char* sqlstate = PQresultErrorField(r, PG_DIAG_SQLSTATE);
         if  ((sqlstate == NULL) ||
             ((memcmp(sqlstate, "08", 2) == 0) ||  // Connection Exception
@@ -338,7 +342,7 @@ PgSqlConnection::checkStatementError(const PgSqlResult& r,
              (memcmp(sqlstate, "58", 2) == 0))) { // System error
             DB_LOG_ERROR(PGSQL_FATAL_ERROR)
                 .arg(statement.name)
-                .arg(PQerrorMessage(handle()))
+                .arg(PQerrorMessage(holderHandle))
                 .arg(sqlstate ? sqlstate : "<sqlstate null>");
 
             // If there's no lost db callback or it returns false,
@@ -354,7 +358,7 @@ PgSqlConnection::checkStatementError(const PgSqlResult& r,
         }
 
         // Apparently it wasn't fatal, so we throw with a helpful message.
-        const char* error_message = PQerrorMessage(handle());
+        const char* error_message = PQerrorMessage(holderHandle);
         isc_throw(DbOperationError, "Statement exec failed:" << " for: "
                 << statement.name << ", status: " << s
                 << "sqlstate:[ " << (sqlstate ? sqlstate : "<null>")
@@ -365,9 +369,12 @@ PgSqlConnection::checkStatementError(const PgSqlResult& r,
 void
 PgSqlConnection::startTransaction() {
     DB_LOG_DEBUG(DB_DBG_TRACE_DETAIL, PGSQL_START_TRANSACTION);
-    PgSqlResult r(PQexec(handle(), "START TRANSACTION"));
+
+    PgSqlHolder& holderHandle = handle();
+
+    PgSqlResult r(PQexec(holderHandle, "START TRANSACTION"));
     if (PQresultStatus(r) != PGRES_COMMAND_OK) {
-        const char* error_message = PQerrorMessage(handle());
+        const char* error_message = PQerrorMessage(holderHandle);
         isc_throw(DbOperationError, "unable to start transaction"
                   << error_message);
     }
@@ -376,9 +383,12 @@ PgSqlConnection::startTransaction() {
 void
 PgSqlConnection::commit() {
     DB_LOG_DEBUG(DB_DBG_TRACE_DETAIL, PGSQL_COMMIT);
-    PgSqlResult r(PQexec(handle(), "COMMIT"));
+
+    PgSqlHolder& holderHandle = handle();
+
+    PgSqlResult r(PQexec(holderHandle, "COMMIT"));
     if (PQresultStatus(r) != PGRES_COMMAND_OK) {
-        const char* error_message = PQerrorMessage(handle());
+        const char* error_message = PQerrorMessage(holderHandle);
         isc_throw(DbOperationError, "commit failed: " << error_message);
     }
 }
@@ -386,9 +396,12 @@ PgSqlConnection::commit() {
 void
 PgSqlConnection::rollback() {
     DB_LOG_DEBUG(DB_DBG_TRACE_DETAIL, PGSQL_ROLLBACK);
-    PgSqlResult r(PQexec(handle(), "ROLLBACK"));
+
+    PgSqlHolder& holderHandle = handle();
+
+    PgSqlResult r(PQexec(holderHandle, "ROLLBACK"));
     if (PQresultStatus(r) != PGRES_COMMAND_OK) {
-        const char* error_message = PQerrorMessage(handle());
+        const char* error_message = PQerrorMessage(holderHandle);
         isc_throw(DbOperationError, "rollback failed: " << error_message);
     }
 }
index cc44a785f2a656836f5d412fd0eb821efcaa27cd..a1f597c3d7089360bd6ef0fbe07f4a6544df8927 100644 (file)
@@ -198,18 +198,22 @@ public:
             "    varchar_col VARCHAR(255) "
             "); ";
 
-        PgSqlResult r(PQexec(conn_->handle(), sql));
+        PgSqlHolder& holderHandle = conn_->handle();
+
+        PgSqlResult r(PQexec(holderHandle, sql));
         ASSERT_EQ(PQresultStatus(r), PGRES_COMMAND_OK)
-                 << " create basics table failed: " << PQerrorMessage(conn_->handle());
+                 << " create basics table failed: " << PQerrorMessage(holderHandle);
     }
 
     /// @brief Destroys the basics table
     /// Asserts if the destruction fails
     void destroySchema() {
         if (conn_) {
-            PgSqlResult r(PQexec(conn_->handle(), "DROP TABLE IF EXISTS basics;"));
+            PgSqlHolder& holderHandle = conn_->handle();
+
+            PgSqlResult r(PQexec(holderHandle, "DROP TABLE IF EXISTS basics;"));
             ASSERT_EQ(PQresultStatus(r), PGRES_COMMAND_OK)
-                 << " drop basics table failed: " << PQerrorMessage(conn_->handle());
+                 << " drop basics table failed: " << PQerrorMessage(holderHandle);
         }
     }
 
@@ -227,10 +231,12 @@ public:
     /// Asserts if the result set status does not equal the expected outcome.
     void runSql(PgSqlResultPtr& r, const std::string& sql, int exp_outcome,
                 int lineno) {
-        r.reset(new PgSqlResult(PQexec(conn_->handle(), sql.c_str())));
+        PgSqlHolder& holderHandle = conn_->handle();
+
+        r.reset(new PgSqlResult(PQexec(holderHandle, sql.c_str())));
         ASSERT_EQ(PQresultStatus(*r), exp_outcome)
                   << " runSql at line: " << lineno << " failed, sql:[" << sql
-                  << "]\n reason: " << PQerrorMessage(conn_->handle());
+                  << "]\n reason: " << PQerrorMessage(holderHandle);
     }
 
     /// @brief Executes a SQL statement and tests for an expected outcome
@@ -250,7 +256,9 @@ public:
                               PgSqlTaggedStatement& statement,
                               PsqlBindArrayPtr bind_array, int exp_outcome,
                               int lineno) {
-        r.reset(new PgSqlResult(PQexecPrepared(conn_->handle(), statement.name,
+        PgSqlHolder& holderHandle = conn_->handle();
+
+        r.reset(new PgSqlResult(PQexecPrepared(holderHandle, statement.name,
                                 statement.nbparams,
                                 &bind_array->values_[0],
                                 &bind_array->lengths_[0],
@@ -258,7 +266,7 @@ public:
         ASSERT_EQ(PQresultStatus(*r), exp_outcome)
                   << " runPreparedStatement at line: " << lineno
                   << " statement name:[" << statement.name
-                  << "]\n reason: " << PQerrorMessage(conn_->handle());
+                  << "]\n reason: " << PQerrorMessage(holderHandle);
     }
 
     /// @brief Fetches all of the rows currently in the table