MySqlConfigBackendImpl::
MySqlConfigBackendImpl(const DatabaseConnection::ParameterMap& parameters)
: conn_(parameters), audit_revision_created_(false) {
- // Open the database.
- conn_.openDatabase();
-
- // Test schema version before we try to prepare statements.
+ // Test schema version first.
std::pair<uint32_t, uint32_t> code_version(MYSQL_SCHEMA_VERSION_MAJOR,
MYSQL_SCHEMA_VERSION_MINOR);
-/* std::pair<uint32_t, uint32_t> db_version = getVersion();
+ std::pair<uint32_t, uint32_t> db_version =
+ MySqlConnection::getVersion(parameters);
if (code_version != db_version) {
isc_throw(DbOpenError, "MySQL schema version mismatch: need version: "
<< code_version.first << "." << code_version.second
<< " found version: " << db_version.first << "."
<< db_version.second);
- } */
+ }
+
+ // Open the database.
+ conn_.openDatabase();
// Enable autocommit. In case transaction is explicitly used, this
// setting will be overwritten for the transaction. However, there are
}
}
+std::pair<uint32_t, uint32_t>
+CqlConnection::getVersion(const ParameterMap& parameters) {
+ // Get a connection.
+ CqlConnection conn(parameters);
+
+ // Open the database.
+ conn.openDatabase();
+
+ // Prepare statement.
+ conn.prepareStatements(CqlVersionExchange::tagged_statements_);
+
+ std::unique_ptr<CqlVersionExchange> version_exchange(new CqlVersionExchange());
+ return version_exchange->retrieveVersion(conn);
+}
+
CassConsistency CqlConnection::parseConsistency(std::string value) {
static std::map<std::string, CassConsistency> consistency_map {
{"any", CASS_CONSISTENCY_ANY},
/// @brief Destructor
virtual ~CqlConnection();
+ /// @brief Get the schema version.
+ ///
+ /// @param parameters A data structure relating keywords and values
+ /// concerned with the database.
+ ///
+ /// @return Version number as a pair of unsigned integers. "first" is the
+ /// major version number, "second" the minor number.
+ ///
+ /// @throw isc::db::DbOperationError An operation on the open database has
+ /// failed.
+ static std::pair<uint32_t, uint32_t>
+ getVersion(const ParameterMap& parameters);
+
/// @brief Prepare statements
///
/// Creates the prepared statements for all of the CQL statements used
HostPtr& target_host) const;
private:
+ /// @brief Parameters
+ db::DatabaseConnection::ParameterMap parameters_;
+
/// @brief CQL connection
mutable CqlConnection dbconn_;
}; // class CqlHostDataSourceImpl
}
CqlHostDataSourceImpl::CqlHostDataSourceImpl(const CqlConnection::ParameterMap& parameters)
- : dbconn_(parameters) {
- // Open the database.
- dbconn_.openDatabase();
-
- // Prepare the version exchange first.
- dbconn_.prepareStatements(CqlVersionExchange::tagged_statements_);
-
- // Validate the schema version.
+ : parameters_(parameters), dbconn_(parameters) {
+ // Validate the schema version first.
std::pair<uint32_t, uint32_t> code_version(CQL_SCHEMA_VERSION_MAJOR,
CQL_SCHEMA_VERSION_MINOR);
std::pair<uint32_t, uint32_t> db_version = getVersion();
<< db_version.second);
}
+ // Open the database.
+ dbconn_.openDatabase();
+
// Prepare all possible statements.
dbconn_.prepareStatements(CqlHostExchange::tagged_statements_);
}
VersionPair
CqlHostDataSourceImpl::getVersion() const {
- std::unique_ptr<CqlVersionExchange> version_exchange(new CqlVersionExchange());
- return (version_exchange->retrieveVersion(dbconn_));
+ return CqlConnection::getVersion(parameters_);
}
bool
}
CqlLeaseMgr::CqlLeaseMgr(const DatabaseConnection::ParameterMap ¶meters)
- : LeaseMgr(), dbconn_(parameters) {
- dbconn_.openDatabase();
-
- // Prepare the version exchange first.
- dbconn_.prepareStatements(CqlVersionExchange::tagged_statements_);
-
- // Validate the schema version.
+ : LeaseMgr(), parameters_(parameters), dbconn_(parameters) {
+ // Validate the schema version first.
std::pair<uint32_t, uint32_t> code_version(CQL_SCHEMA_VERSION_MAJOR,
CQL_SCHEMA_VERSION_MINOR);
std::pair<uint32_t, uint32_t> db_version = getVersion();
<< db_version.second);
}
+ // Open the database.
+ dbconn_.openDatabase();
+
// Now prepare the rest of the exchanges.
dbconn_.prepareStatements(CqlLease4Exchange::tagged_statements_);
dbconn_.prepareStatements(CqlLease6Exchange::tagged_statements_);
CqlLeaseMgr::getVersion() const {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_VERSION);
- std::unique_ptr<CqlVersionExchange> version_exchange(new CqlVersionExchange());
- return version_exchange->retrieveVersion(dbconn_);
+ return CqlConnection::getVersion(parameters_);
}
void
virtual void rollback() override;
private:
+ /// @brief Connection parameters
+ db::DatabaseConnection::ParameterMap parameters_;
+
/// @brief Database connection object
mutable db::CqlConnection dbconn_;
};
/// @brief Returns backend version.
///
- /// The method is called by the constructor after opening the database
- /// but prior to preparing SQL statements, to verify that the schema version
- /// is correct. Thus it must not rely on a pre-prepared statement or
- /// formal statement execution error checking.
- //
+ /// The method is called by the constructor before opening the database
+ /// to verify that the schema version is correct.
+ ///
/// @return Version number stored in the database, as a pair of unsigned
/// integers. "first" is the major version number, "second" the
/// minor number.
/// or dhcp6_options table.
boost::shared_ptr<MySqlOptionExchange> host_option_exchange_;
+ /// @brief The parameters
+ db::DatabaseConnection::ParameterMap parameters_;
+
/// @brief MySQL connection
MySqlConnection conn_;
DHCP4_AND_DHCP6)),
host_ipv6_reservation_exchange_(new MySqlIPv6ReservationExchange()),
host_option_exchange_(new MySqlOptionExchange()),
+ parameters_(parameters),
conn_(parameters),
is_readonly_(false) {
- // Open the database.
- conn_.openDatabase();
-
- // Test schema version before we try to prepare statements.
+ // Test schema version first.
std::pair<uint32_t, uint32_t> code_version(MYSQL_SCHEMA_VERSION_MAJOR,
MYSQL_SCHEMA_VERSION_MINOR);
std::pair<uint32_t, uint32_t> db_version = getVersion();
<< db_version.second);
}
+ // Open the database.
+ conn_.openDatabase();
+
// Enable autocommit. In case transaction is explicitly used, this
// setting will be overwritten for the transaction. However, there are
// cases when lack of autocommit could cause transactions to hang
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_MYSQL_HOST_DB_GET_VERSION);
- // Allocate a new statement.
- MYSQL_STMT *stmt = mysql_stmt_init(conn_.mysql_);
- if (stmt == NULL) {
- isc_throw(DbOperationError, "unable to allocate MySQL prepared "
- "statement structure, reason: " << mysql_error(conn_.mysql_));
- }
-
- // Prepare the statement from SQL text.
- const char* version_sql = "SELECT version, minor FROM schema_version";
- int status = mysql_stmt_prepare(stmt, version_sql, strlen(version_sql));
- if (status != 0) {
- isc_throw(DbOperationError, "unable to prepare MySQL statement <"
- << version_sql << ">, reason: " << mysql_errno(conn_.mysql_));
- }
-
- // Execute the prepared statement.
- if (mysql_stmt_execute(stmt) != 0) {
- isc_throw(DbOperationError, "cannot execute schema version query <"
- << version_sql << ">, reason: " << mysql_errno(conn_.mysql_));
- }
-
- // Bind the output of the statement to the appropriate variables.
- MYSQL_BIND bind[2];
- memset(bind, 0, sizeof(bind));
-
- uint32_t major;
- bind[0].buffer_type = MYSQL_TYPE_LONG;
- bind[0].is_unsigned = 1;
- bind[0].buffer = &major;
- bind[0].buffer_length = sizeof(major);
-
- uint32_t minor;
- bind[1].buffer_type = MYSQL_TYPE_LONG;
- bind[1].is_unsigned = 1;
- bind[1].buffer = &minor;
- bind[1].buffer_length = sizeof(minor);
-
- if (mysql_stmt_bind_result(stmt, bind)) {
- isc_throw(DbOperationError, "unable to bind result set for <"
- << version_sql << ">, reason: " << mysql_errno(conn_.mysql_));
- }
-
- // 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_errno(conn_.mysql_));
- }
-
- // Discard the statement and its resources
- mysql_stmt_close(stmt);
-
- return (std::make_pair(major, minor));
+ return (MySqlConnection::getVersion(parameters_));
}
-
void
MySqlHostDataSourceImpl::addStatement(StatementIndex stindex,
std::vector<MYSQL_BIND>& bind) {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_MYSQL_GET_VERSION);
- // Get a connection.
- MySqlConnection conn(parameters_);
-
- // Open the database.
- conn.openDatabase();
-
- // Allocate a new statement.
- MYSQL_STMT *stmt = mysql_stmt_init(conn.mysql_);
- if (stmt == NULL) {
- isc_throw(DbOperationError, "unable to allocate MySQL prepared "
- "statement structure, reason: " << mysql_error(conn.mysql_));
- }
-
- // Prepare the statement from SQL text.
- const char* version_sql = "SELECT version, minor FROM schema_version";
- int status = mysql_stmt_prepare(stmt, version_sql, strlen(version_sql));
- if (status != 0) {
- isc_throw(DbOperationError, "unable to prepare MySQL statement <"
- << version_sql << ">, reason: " << mysql_error(conn.mysql_));
- }
-
- // Execute the prepared statement.
- if (mysql_stmt_execute(stmt) != 0) {
- isc_throw(DbOperationError, "cannot execute schema version query <"
- << version_sql << ">, reason: " << mysql_errno(conn.mysql_));
- }
-
- // Bind the output of the statement to the appropriate variables.
- MYSQL_BIND bind[2];
- memset(bind, 0, sizeof(bind));
-
- uint32_t major;
- bind[0].buffer_type = MYSQL_TYPE_LONG;
- bind[0].is_unsigned = 1;
- bind[0].buffer = &major;
- bind[0].buffer_length = sizeof(major);
-
- uint32_t minor;
- bind[1].buffer_type = MYSQL_TYPE_LONG;
- bind[1].is_unsigned = 1;
- bind[1].buffer = &minor;
- bind[1].buffer_length = sizeof(minor);
-
- if (mysql_stmt_bind_result(stmt, bind)) {
- isc_throw(DbOperationError, "unable to bind result set for <"
- << version_sql << ">, reason: " << mysql_errno(conn.mysql_));
- }
-
- // 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_errno(conn.mysql_));
- }
-
- // Discard the statement and its resources
- mysql_stmt_close(stmt);
-
- return (std::make_pair(major, minor));
+ return (MySqlConnection::getVersion(parameters_));
}
void
PgSqlLeaseMgr::PgSqlLeaseMgr(const DatabaseConnection::ParameterMap& parameters)
: LeaseMgr(), exchange4_(new PgSqlLease4Exchange()),
- exchange6_(new PgSqlLease6Exchange()), conn_(parameters) {
- conn_.openDatabase();
-
+ exchange6_(new PgSqlLease6Exchange()), parameters_(parameters),
+ conn_(parameters) {
// Validate schema version first.
std::pair<uint32_t, uint32_t> code_version(PG_SCHEMA_VERSION_MAJOR,
PG_SCHEMA_VERSION_MINOR);
<< db_version.second);
}
+ // Open the database.
+ conn_.openDatabase();
+
// Now prepare the SQL statements.
int i = 0;
for( ; tagged_statements[i].text != NULL ; ++i) {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_PGSQL_GET_VERSION);
- const char* version_sql = "SELECT version, minor FROM schema_version;";
- PgSqlResult r(PQexec(conn_, version_sql));
- if(PQresultStatus(r) != PGRES_TUPLES_OK) {
- isc_throw(DbOperationError, "unable to execute PostgreSQL statement <"
- << version_sql << ", reason: " << PQerrorMessage(conn_));
- }
-
- istringstream tmp;
- uint32_t version;
- tmp.str(PQgetvalue(r, 0, 0));
- tmp >> version;
- tmp.str("");
- tmp.clear();
-
- uint32_t minor;
- tmp.str(PQgetvalue(r, 0, 1));
- tmp >> minor;
-
- return (make_pair(version, minor));
+ return (PgSqlConnection::getVersion(parameters_));
}
void
boost::scoped_ptr<PgSqlLease4Exchange> exchange4_; ///< Exchange object
boost::scoped_ptr<PgSqlLease6Exchange> exchange6_; ///< Exchange object
+ /// The parameters.
+ db::DatabaseConnection::ParameterMap parameters_;
+
/// PostgreSQL connection handle
db::PgSqlConnection conn_;
};
}
}
+// Get schema version.
+
+std::pair<uint32_t, uint32_t>
+MySqlConnection::getVersion(const ParameterMap& parameters) {
+ // Get a connection.
+ MySqlConnection conn(parameters);
+
+ // Open the database.
+ conn.openDatabase();
+
+ // Allocate a new statement.
+ MYSQL_STMT *stmt = mysql_stmt_init(conn.mysql_);
+ if (stmt == NULL) {
+ isc_throw(DbOperationError, "unable to allocate MySQL prepared "
+ "statement structure, reason: " << mysql_error(conn.mysql_));
+ }
+
+ // Prepare the statement from SQL text.
+ const char* version_sql = "SELECT version, minor FROM schema_version";
+ int status = mysql_stmt_prepare(stmt, version_sql, strlen(version_sql));
+ if (status != 0) {
+ isc_throw(DbOperationError, "unable to prepare MySQL statement <"
+ << version_sql << ">, reason: " << mysql_error(conn.mysql_));
+ }
+
+ // Execute the prepared statement.
+ if (mysql_stmt_execute(stmt) != 0) {
+ isc_throw(DbOperationError, "cannot execute schema version query <"
+ << version_sql << ">, reason: " << mysql_errno(conn.mysql_));
+ }
+
+ // Bind the output of the statement to the appropriate variables.
+ MYSQL_BIND bind[2];
+ memset(bind, 0, sizeof(bind));
+
+ uint32_t major;
+ bind[0].buffer_type = MYSQL_TYPE_LONG;
+ bind[0].is_unsigned = 1;
+ bind[0].buffer = &major;
+ bind[0].buffer_length = sizeof(major);
+
+ uint32_t minor;
+ bind[1].buffer_type = MYSQL_TYPE_LONG;
+ bind[1].is_unsigned = 1;
+ bind[1].buffer = &minor;
+ bind[1].buffer_length = sizeof(minor);
+
+ if (mysql_stmt_bind_result(stmt, bind)) {
+ isc_throw(DbOperationError, "unable to bind result set for <"
+ << version_sql << ">, reason: " << mysql_errno(conn.mysql_));
+ }
+
+ // 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_errno(conn.mysql_));
+ }
+
+ // Discard the statement and its resources
+ mysql_stmt_close(stmt);
+
+ return (std::make_pair(major, minor));
+}
// Prepared statement setup. The textual form of an SQL statement is stored
// in a vector of strings (text_statements_) and is used in the output of
/// @brief Destructor
virtual ~MySqlConnection();
+ /// @brief Get the schema version.
+ ///
+ /// @param parameters A data structure relating keywords and values
+ /// concerned with the database.
+ ///
+ /// @return Version number as a pair of unsigned integers. "first" is the
+ /// major version number, "second" the minor number.
+ ///
+ /// @throw isc::db::DbOperationError An operation on the open database has
+ /// failed.
+ static std::pair<uint32_t, uint32_t>
+ getVersion(const ParameterMap& parameters);
+
/// @brief Prepare Single Statement
///
/// Creates a prepared statement from the text given and adds it to the
EXPECT_TRUE(deleted);
}
+/// @brief Test fixture class for @c MySqlConnection class methods.
+class MySqlSchemaTest : public ::testing::Test {
+public:
+ /// @brief Constructor.
+ MySqlSchemaTest() {
+ // Ensure we have the proper schema.
+ createMySQLSchema();
+ }
+
+ /// @brief Destructor.
+ virtual ~MySqlSchemaTest() {
+ destroyMySQLSchema();
+ }
+};
+
+/// @brief Check that getVersion() returns the expected version.
+TEST_F(MySqlSchemaTest, checkVersion) {
+ // Check version
+ auto parameters = DatabaseConnection::parse(validMySQLConnectionString());
+ std::pair<uint32_t, uint32_t> version;
+ ASSERT_NO_THROW(version = MySqlConnection::getVersion(parameters));
+ EXPECT_EQ(MYSQL_SCHEMA_VERSION_MAJOR, version.first);
+ EXPECT_EQ(MYSQL_SCHEMA_VERSION_MINOR, version.second);
+}
+
}
#define PGSQL_STATECODE_LEN 5
#include <utils/errcodes.h>
+#include <sstream>
+
using namespace std;
namespace isc {
}
}
+std::pair<uint32_t, uint32_t>
+PgSqlConnection::getVersion(const ParameterMap& parameters) {
+ // Get a connection.
+ PgSqlConnection conn(parameters);
+
+ // Open the database.
+ conn.openDatabase();
+
+ const char* version_sql = "SELECT version, minor FROM schema_version;";
+ PgSqlResult r(PQexec(conn.conn_, version_sql));
+ if (PQresultStatus(r) != PGRES_TUPLES_OK) {
+ isc_throw(DbOperationError, "unable to execute PostgreSQL statement <"
+ << version_sql << ", reason: " << PQerrorMessage(conn.conn_));
+ }
+
+ istringstream tmp;
+ uint32_t version;
+ tmp.str(PQgetvalue(r, 0, 0));
+ tmp >> version;
+ tmp.str("");
+ tmp.clear();
+
+ uint32_t minor;
+ tmp.str(PQgetvalue(r, 0, 1));
+ tmp >> minor;
+
+ return (make_pair(version, minor));
+}
+
void
PgSqlConnection::prepareStatement(const PgSqlTaggedStatement& statement) {
// Prepare all statements queries with all known fields datatype
/// @brief Destructor
virtual ~PgSqlConnection();
+ /// @brief Get the schema version.
+ ///
+ /// @param parameters A data structure relating keywords and values
+ /// concerned with the database.
+ ///
+ /// @return Version number as a pair of unsigned integers. "first" is the
+ /// major version number, "second" the minor number.
+ ///
+ /// @throw isc::db::DbOperationError An operation on the open database has
+ /// failed.
+ static std::pair<uint32_t, uint32_t>
+ getVersion(const ParameterMap& parameters);
+
/// @brief Prepare Single Statement
///
/// Creates a prepared statement from the text given and adds it to the
///
/// @param statement SQL statement to be prepared.
///
- /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// @throw isc::db::DbOperationError An operation on the open database has
/// failed.
void prepareStatement(const PgSqlTaggedStatement& statement);
/// @param end_statement Pointer to the statement marking end of the
/// range of statements to be compiled. This last statement is not compiled.
///
- /// @throw isc::dhcp::DbOperationError An operation on the open database has
+ /// @throw isc::db::DbOperationError An operation on the open database has
/// failed.
void prepareStatements(const PgSqlTaggedStatement* start_statement,
const PgSqlTaggedStatement* end_statement);
/// @param r result of the last PostgreSQL operation
/// @param statement - tagged statement that was executed
///
- /// @throw isc::dhcp::DbOperationError Detailed PostgreSQL failure
+ /// @throw isc::db::DbOperationError Detailed PostgreSQL failure
void checkStatementError(const PgSqlResult& r,
PgSqlTaggedStatement& statement) const;