]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#888,!573] implement pgsql thread handle
authorRazvan Becheriu <razvan@isc.org>
Mon, 28 Oct 2019 17:27:43 +0000 (19:27 +0200)
committerRazvan Becheriu <razvan@isc.org>
Wed, 6 Nov 2019 17:28:24 +0000 (19:28 +0200)
src/lib/dhcpsrv/pgsql_host_data_source.cc
src/lib/dhcpsrv/pgsql_lease_mgr.cc
src/lib/dhcpsrv/tests/pgsql_host_data_source_unittest.cc
src/lib/pgsql/pgsql_connection.cc
src/lib/pgsql/pgsql_connection.h
src/lib/pgsql/pgsql_exchange.h
src/lib/pgsql/tests/pgsql_exchange_unittest.cc

index aa6d773024edf59f5402cf791dfad508170536a7..97258f9878e6de67e555c1db45aeb9fcdd89709f 100644 (file)
@@ -1929,8 +1929,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_, tagged_statements[stindex].name,
+
+    PgSqlResult r(PQexecPrepared(holderHandle, tagged_statements[stindex].name,
                                  tagged_statements[stindex].nbparams,
                                  &bind_array->values_[0],
                                  &bind_array->lengths_[0],
@@ -1959,7 +1961,9 @@ PgSqlHostDataSourceImpl::addStatement(StatementIndex stindex,
 bool
 PgSqlHostDataSourceImpl::delStatement(StatementIndex stindex,
                                       PsqlBindArrayPtr& bind_array) {
-    PgSqlResult r(PQexecPrepared(conn_, 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],
@@ -2041,9 +2045,10 @@ PgSqlHostDataSourceImpl::
 getHostCollection(StatementIndex stindex, PsqlBindArrayPtr bind_array,
                   std::shared_ptr<PgSqlHostExchange> exchange,
                   ConstHostCollection& result, bool single) const {
+    PgSqlHolder& holderHandle = conn_.handle();
 
     exchange->clear();
-    PgSqlResult r(PQexecPrepared(conn_, tagged_statements[stindex].name,
+    PgSqlResult r(PQexecPrepared(holderHandle, tagged_statements[stindex].name,
                                  tagged_statements[stindex].nbparams,
                                  &bind_array->values_[0],
                                  &bind_array->lengths_[0],
@@ -2100,11 +2105,14 @@ pair<uint32_t, uint32_t>
 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_, 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_));
+                  << version_sql << ">, reason: " << PQerrorMessage(holderHandle));
     }
 
     uint32_t major;
index 83ce3c21d5156dd5b23b229f6bb93488fcf9c392..c5193cb47d67961e46f2d2dccca7cb0efc7a80f3 100644 (file)
@@ -1019,10 +1019,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_, statement_.name,
+            result_set_.reset(new PgSqlResult(PQexecPrepared(holderHandle, statement_.name,
                                                              0, 0, 0, 0, 0)));
         } else {
             // Set up the WHERE clause values
@@ -1040,7 +1041,7 @@ public:
             }
 
             // Run the query with where clause parameters.
-            result_set_.reset(new PgSqlResult(PQexecPrepared(conn_, statement_.name,
+            result_set_.reset(new PgSqlResult(PQexecPrepared(holderHandle, statement_.name,
                                               parms.size(), &parms.values_[0],
                                               &parms.lengths_[0], &parms.formats_[0], 0)));
         }
@@ -1158,7 +1159,9 @@ PgSqlLeaseMgr::getDBVersion() {
 bool
 PgSqlLeaseMgr::addLeaseCommon(StatementIndex stindex,
                               PsqlBindArray& bind_array) {
-    PgSqlResult r(PQexecPrepared(conn_, 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],
@@ -1212,8 +1215,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_, 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));
@@ -1738,7 +1743,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_, 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],
@@ -1812,7 +1819,9 @@ PgSqlLeaseMgr::updateLease6(const Lease6Ptr& lease) {
 uint64_t
 PgSqlLeaseMgr::deleteLeaseCommon(StatementIndex stindex,
                                  PsqlBindArray& bind_array) {
-    PgSqlResult r(PQexecPrepared(conn_, 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],
@@ -1963,11 +1972,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_, 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_));
+                  << version_sql << ">, reason: " << PQerrorMessage(holderHandle));
     }
 
     uint32_t major;
index e8e149d48226c5ad97439d8f35a3686025694252..88238f0d88bb7537cf03e1c30a6ed7c9284aaabe 100644 (file)
@@ -119,9 +119,11 @@ public:
         PgSqlConnection conn(params);
         conn.openDatabase();
 
-        PgSqlResult r(PQexec(conn, 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));
+            isc_throw(DbOperationError, "Query failed:" << PQerrorMessage(holderHandle));
         }
 
         int numrows = PQntuples(r);
@@ -644,9 +646,14 @@ TEST_F(PgSqlHostDataSourceTest, testAddRollback) {
     PgSqlConnection conn(params);
     ASSERT_NO_THROW(conn.openDatabase());
 
-    PgSqlResult r(PQexec(conn, "DROP TABLE IF EXISTS ipv6_reservations"));
-    ASSERT_TRUE (PQresultStatus(r) == PGRES_COMMAND_OK)
-                 << " drop command failed :" << PQerrorMessage(conn);
+    PgSqlHolder& holderHandle = conn.handle();
+
+    ConstHostCollection collection = hdsptr_->getAll4(0);
+    ASSERT_EQ(collection.size(), 0);
+
+    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 af98f098cb1468af6300cdb1743326d979fd1dc6..b33a7334aa50c19e0ba5b797d2caa92dd93bcb3c 100644 (file)
@@ -37,6 +37,62 @@ const int PGSQL_DEFAULT_CONNECTION_TIMEOUT = 5; // seconds
 
 const char PgSqlConnection::DUPLICATE_KEY[] = ERRCODE_UNIQUE_VIOLATION;
 
+void
+PgSqlHolder::setConnection(PGconn* connection) {
+    clearPrepared();
+    if (pgconn_ != NULL) {
+        PQfinish(pgconn_);
+    }
+    pgconn_ = connection;
+    connected_ = false;
+    prepared_ = false;
+}
+
+void
+PgSqlHolder::clearPrepared() {
+    if (pgconn_ != NULL) {
+        // Deallocate the prepared queries.
+        if (PQstatus(pgconn_) == CONNECTION_OK) {
+            PgSqlResult r(PQexec(pgconn_, "DEALLOCATE all"));
+            if(PQresultStatus(r) != PGRES_COMMAND_OK) {
+                // Highly unlikely but we'll log it and go on.
+                DB_LOG_ERROR(PGSQL_DEALLOC_ERROR)
+                    .arg(PQerrorMessage(pgconn_));
+            }
+        }
+    }
+}
+
+void
+PgSqlHolder::openDatabase(PgSqlConnection& connection) {
+    if (connected_) {
+        return;
+    }
+    connected_ = true;
+    prepared_ = true;
+    connection.openDatabase();
+    prepared_ = false;
+}
+
+void
+PgSqlHolder::prepareStatements(PgSqlConnection& connection) {
+    if (prepared_) {
+        return;
+    }
+    clearPrepared();
+    // Prepare all statements queries with all known fields datatype
+    for (auto it = connection.statements_.begin();
+        it != connection.statements_.end(); ++it) {
+        PgSqlResult r(PQprepare(pgconn_, (*it)->name, (*it)->text,
+                                (*it)->nbparams, (*it)->types));
+        if (PQresultStatus(r) != PGRES_COMMAND_OK) {
+            isc_throw(DbOperationError, "unable to prepare PostgreSQL statement: "
+                      << (*it)->text << ", reason: " << PQerrorMessage(pgconn_));
+        }
+    }
+    prepared_ = true;
+}
+
 PgSqlResult::PgSqlResult(PGresult *result)
     : result_(result), rows_(0), cols_(0) {
     if (!result) {
@@ -103,7 +159,10 @@ PgSqlTransaction::PgSqlTransaction(PgSqlConnection& conn)
 PgSqlTransaction::~PgSqlTransaction() {
     // If commit() wasn't explicitly called, rollback.
     if (!committed_) {
-        conn_.rollback();
+        try {
+            conn_.rollback();
+        } catch (...) {
+        }
     }
 }
 
@@ -114,28 +173,14 @@ PgSqlTransaction::commit() {
 }
 
 PgSqlConnection::~PgSqlConnection() {
-    if (conn_) {
-        // Deallocate the prepared queries.
-        if (PQstatus(conn_) == CONNECTION_OK) {
-            PgSqlResult r(PQexec(conn_, "DEALLOCATE all"));
-            if(PQresultStatus(r) != PGRES_COMMAND_OK) {
-                // Highly unlikely but we'll log it and go on.
-                DB_LOG_ERROR(PGSQL_DEALLOC_ERROR)
-                    .arg(PQerrorMessage(conn_));
-            }
-        }
-    }
+    statements_.clear();
+    handle().clear();
 }
 
 void
 PgSqlConnection::prepareStatement(const PgSqlTaggedStatement& statement) {
-    // Prepare all statements queries with all known fields datatype
-    PgSqlResult r(PQprepare(conn_, statement.name, statement.text,
-                            statement.nbparams, statement.types));
-    if(PQresultStatus(r) != PGRES_COMMAND_OK) {
-        isc_throw(DbOperationError, "unable to prepare PostgreSQL statement: "
-                  << statement.text << ", reason: " << PQerrorMessage(conn_));
-    }
+    statements_.push_back(&statement);
+    prepared_ = true;
 }
 
 void
@@ -276,7 +321,10 @@ PgSqlConnection::openDatabase() {
     }
 
     // We have a valid connection, so let's save it to our holder
-    conn_.setConnection(new_conn);
+    PgSqlHolder& holderHandle = handle();
+    holderHandle.setConnection(new_conn);
+    holderHandle.connected_ = true;
+    connected_ = true;
 }
 
 bool
@@ -296,6 +344,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
@@ -305,7 +356,7 @@ PgSqlConnection::checkStatementError(const PgSqlResult& r,
              (memcmp(sqlstate, "58", 2) == 0))) { // System error
             DB_LOG_ERROR(PGSQL_FATAL_ERROR)
                 .arg(statement.name)
-                .arg(PQerrorMessage(conn_))
+                .arg(PQerrorMessage(holderHandle))
                 .arg(sqlstate ? sqlstate : "<sqlstate null>");
 
             // If there's no lost db callback or it returns false,
@@ -321,7 +372,7 @@ PgSqlConnection::checkStatementError(const PgSqlResult& r,
         }
 
         // Apparently it wasn't fatal, so we throw with a helpful message.
-        const char* error_message = PQerrorMessage(conn_);
+        const char* error_message = PQerrorMessage(holderHandle);
         isc_throw(DbOperationError, "Statement exec failed:" << " for: "
                 << statement.name << ", status: " << s
                 << "sqlstate:[ " << (sqlstate ? sqlstate : "<null>")
@@ -332,9 +383,12 @@ PgSqlConnection::checkStatementError(const PgSqlResult& r,
 void
 PgSqlConnection::startTransaction() {
     DB_LOG_DEBUG(DB_DBG_TRACE_DETAIL, PGSQL_START_TRANSACTION);
-    PgSqlResult r(PQexec(conn_, "START TRANSACTION"));
+
+    PgSqlHolder& holderHandle = handle();
+
+    PgSqlResult r(PQexec(holderHandle, "START TRANSACTION"));
     if (PQresultStatus(r) != PGRES_COMMAND_OK) {
-        const char* error_message = PQerrorMessage(conn_);
+        const char* error_message = PQerrorMessage(holderHandle);
         isc_throw(DbOperationError, "unable to start transaction"
                   << error_message);
     }
@@ -343,9 +397,12 @@ PgSqlConnection::startTransaction() {
 void
 PgSqlConnection::commit() {
     DB_LOG_DEBUG(DB_DBG_TRACE_DETAIL, PGSQL_COMMIT);
-    PgSqlResult r(PQexec(conn_, "COMMIT"));
+
+    PgSqlHolder& holderHandle = handle();
+
+    PgSqlResult r(PQexec(holderHandle, "COMMIT"));
     if (PQresultStatus(r) != PGRES_COMMAND_OK) {
-        const char* error_message = PQerrorMessage(conn_);
+        const char* error_message = PQerrorMessage(holderHandle);
         isc_throw(DbOperationError, "commit failed: " << error_message);
     }
 }
@@ -353,12 +410,16 @@ PgSqlConnection::commit() {
 void
 PgSqlConnection::rollback() {
     DB_LOG_DEBUG(DB_DBG_TRACE_DETAIL, PGSQL_ROLLBACK);
-    PgSqlResult r(PQexec(conn_, "ROLLBACK"));
+
+    PgSqlHolder& holderHandle = handle();
+
+    PgSqlResult r(PQexec(holderHandle, "ROLLBACK"));
     if (PQresultStatus(r) != PGRES_COMMAND_OK) {
-        const char* error_message = PQerrorMessage(conn_);
+        const char* error_message = PQerrorMessage(holderHandle);
         isc_throw(DbOperationError, "rollback failed: " << error_message);
     }
 }
 
-}; // end of isc::db namespace
-}; // end of isc namespace
+}  // namespace db
+}  // namespace isc
+
index 339ec7eefccc6d15f25497322db486184878fa1a..40dd05df6f106a54fab5b7945fadaa453dbefa02 100644 (file)
@@ -7,6 +7,7 @@
 #define PGSQL_CONNECTION_H
 
 #include <database/database_connection.h>
+#include <dhcpsrv/thread_resource_mgr.h>
 
 #include <libpq-fe.h>
 #include <boost/scoped_ptr.hpp>
@@ -160,11 +161,13 @@ public:
     }
 
 private:
-    PGresult*     result_;     ///< Result set to be freed
-    int rows_;   ///< Number of rows in the result set
-    int cols_;   ///< Number of columns in the result set
+    PGresult* result_;     ///< Result set to be freed
+    int rows_;             ///< Number of rows in the result set
+    int cols_;             ///< Number of columns in the result set
 };
 
+/// @brief Forward declaration to @ref PgSqlConnection.
+class PgSqlConnection;
 
 /// @brief Postgresql connection handle Holder
 ///
@@ -179,35 +182,34 @@ private:
 /// For this reason, the class is declared noncopyable.
 class PgSqlHolder : public boost::noncopyable {
 public:
-
     /// @brief Constructor
     ///
     /// Sets the Postgresql API connector handle to NULL.
     ///
-    PgSqlHolder() : pgconn_(NULL) {
+    PgSqlHolder() : connected_(false), prepared_(false), pgconn_(NULL) {
     }
 
     /// @brief Destructor
     ///
     /// Frees up resources allocated by the connection.
     ~PgSqlHolder() {
-        if (pgconn_ != NULL) {
-            PQfinish(pgconn_);
-        }
+        clear();
     }
 
+    void clear() {
+        setConnection(NULL);
+    }
+
+    void clearPrepared();
+
     /// @brief Sets the connection to the value given
     ///
     /// @param connection - pointer to the Postgresql connection instance
-    void setConnection(PGconn* connection) {
-        if (pgconn_ != NULL) {
-            // Already set? Release the current connection first.
-            // Maybe this should be an error instead?
-            PQfinish(pgconn_);
-        }
+    void setConnection(PGconn* connection);
 
-        pgconn_ = connection;
-    }
+    void openDatabase(PgSqlConnection& connection);
+
+    void prepareStatements(PgSqlConnection& connection);
 
     /// @brief Conversion Operator
     ///
@@ -217,19 +219,13 @@ public:
         return (pgconn_);
     }
 
-    /// @brief Boolean Operator
-    ///
-    /// Allows testing the connection for emptiness: "if (holder)"
-    operator bool() const {
-        return (pgconn_);
-    }
+    bool connected_;     ///< Flag to indicate openDatabase has been called
 
 private:
-    PGconn* pgconn_;      ///< Postgresql connection
-};
+    bool prepared_;      ///< Flag to indicate prepareStatements has been called
 
-/// @brief Forward declaration to @ref PgSqlConnection.
-class PgSqlConnection;
+    PGconn* pgconn_;     ///< Postgresql connection
+};
 
 /// @brief RAII object representing a PostgreSQL transaction.
 ///
@@ -304,8 +300,8 @@ public:
     /// @brief Constructor
     ///
     /// Initialize PgSqlConnection object with parameters needed for connection.
-    PgSqlConnection(const ParameterMap& parameters)
-        : DatabaseConnection(parameters) {
+    PgSqlConnection(const ParameterMap& parameters) :
+        DatabaseConnection(parameters), connected_(false), prepared_(false) {
     }
 
     /// @brief Destructor
@@ -400,30 +396,37 @@ public:
     void checkStatementError(const PgSqlResult& r,
                              PgSqlTaggedStatement& statement) const;
 
-    /// @brief PgSql connection handle
+    /// @brief Raw statements
     ///
-    /// This field is public, because it is used heavily from PgSqlLeaseMgr
+    /// This field is public, because it is used heavily from PgSqlConnection
     /// and from PgSqlHostDataSource.
-    PgSqlHolder conn_;
+    std::vector<const PgSqlTaggedStatement*> statements_;
 
-    /// @brief Conversion Operator
+    /// @brief PgSql connection handle
     ///
-    /// Allows the PgConnection object to be passed as the context argument to
-    /// PQxxxx functions.
-    operator PGconn*() const {
-        return (conn_);
+    /// This field is public, because it is used heavily from PgSqlLeaseMgr
+    /// and from PgSqlHostDataSource.
+    PgSqlHolder& handle() const {
+        auto result = handles_.resource();
+        // thread_local std::shared_ptr<PgSqlHolder> result(std::make_shared<PgSqlHolder>());
+        if (connected_) {
+            result->openDatabase(*(const_cast<PgSqlConnection*>(this)));
+        }
+        if (prepared_) {
+            result->prepareStatements(*(const_cast<PgSqlConnection*>(this)));
+        }
+        return *result;
     }
 
-    /// @brief Boolean Operator
-    ///
-    /// Allows testing the PgConnection for initialized connection
-    operator bool() const {
-        return (conn_);
-    }
+private:
+    bool connected_;     ///< Flag to indicate openDatabase has been called
+
+    bool prepared_;      ///< Flag to indicate prepareStatements has been called
 
+    mutable isc::dhcp::ThreadResourceMgr<PgSqlHolder> handles_;
 };
 
-}; // end of isc::db namespace
-}; // end of isc namespace
+}  // namespace db
+}  // namespace isc
 
 #endif // PGSQL_CONNECTION_H
index 4aa82b22357491dbf0194dc39b5c998b5c45be34..fd9518a00fa2f2353137514c6386a4bd00d59cca 100644 (file)
@@ -70,7 +70,6 @@ struct PsqlBindArray {
     /// @return Returns true if there are no entries in the array, false
     /// otherwise.
     bool empty() const {
-
         return (values_.empty());
     }
 
@@ -393,7 +392,7 @@ public:
 protected:
     /// @brief Stores text labels for columns, currently only used for
     /// logging and errors.
-    std::vector<std::string>columns_;
+    std::vector<std::string> columns_;
 };
 
 }; // end of isc::db namespace
index 173665ac94c3e768c4914527b6cb811a8749bef2..a1f597c3d7089360bd6ef0fbe07f4a6544df8927 100644 (file)
@@ -198,18 +198,22 @@ public:
             "    varchar_col VARCHAR(255) "
             "); ";
 
-        PgSqlResult r(PQexec(*conn_, sql));
+        PgSqlHolder& holderHandle = conn_->handle();
+
+        PgSqlResult r(PQexec(holderHandle, sql));
         ASSERT_EQ(PQresultStatus(r), PGRES_COMMAND_OK)
-                 << " create basics table failed: " << PQerrorMessage(*conn_);
+                 << " create basics table failed: " << PQerrorMessage(holderHandle);
     }
 
     /// @brief Destroys the basics table
     /// Asserts if the destruction fails
     void destroySchema() {
         if (conn_) {
-            PgSqlResult r(PQexec(*conn_, "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_);
+                 << " 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_, 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_);
+                  << "]\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_, 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_);
+                  << "]\n reason: " << PQerrorMessage(holderHandle);
     }
 
     /// @brief Fetches all of the rows currently in the table