Commit c131e65e authored by Francis Dupont's avatar Francis Dupont

[1008-move-database-schema-version-check-to-database-libraries] Moved getVersion codes to databases

parent 6f9dfacd
...@@ -44,19 +44,20 @@ ScopedAuditRevision::~ScopedAuditRevision() { ...@@ -44,19 +44,20 @@ ScopedAuditRevision::~ScopedAuditRevision() {
MySqlConfigBackendImpl:: MySqlConfigBackendImpl::
MySqlConfigBackendImpl(const DatabaseConnection::ParameterMap& parameters) MySqlConfigBackendImpl(const DatabaseConnection::ParameterMap& parameters)
: conn_(parameters), audit_revision_created_(false) { : conn_(parameters), audit_revision_created_(false) {
// Open the database. // Test schema version first.
conn_.openDatabase();
// Test schema version before we try to prepare statements.
std::pair<uint32_t, uint32_t> code_version(MYSQL_SCHEMA_VERSION_MAJOR, std::pair<uint32_t, uint32_t> code_version(MYSQL_SCHEMA_VERSION_MAJOR,
MYSQL_SCHEMA_VERSION_MINOR); 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) { if (code_version != db_version) {
isc_throw(DbOpenError, "MySQL schema version mismatch: need version: " isc_throw(DbOpenError, "MySQL schema version mismatch: need version: "
<< code_version.first << "." << code_version.second << code_version.first << "." << code_version.second
<< " found version: " << db_version.first << "." << " found version: " << db_version.first << "."
<< db_version.second); << db_version.second);
} */ }
// Open the database.
conn_.openDatabase();
// Enable autocommit. In case transaction is explicitly used, this // Enable autocommit. In case transaction is explicitly used, this
// setting will be overwritten for the transaction. However, there are // setting will be overwritten for the transaction. However, there are
......
...@@ -75,6 +75,21 @@ CqlConnection::~CqlConnection() { ...@@ -75,6 +75,21 @@ CqlConnection::~CqlConnection() {
} }
} }
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) { CassConsistency CqlConnection::parseConsistency(std::string value) {
static std::map<std::string, CassConsistency> consistency_map { static std::map<std::string, CassConsistency> consistency_map {
{"any", CASS_CONSISTENCY_ANY}, {"any", CASS_CONSISTENCY_ANY},
......
...@@ -127,6 +127,19 @@ public: ...@@ -127,6 +127,19 @@ public:
/// @brief Destructor /// @brief Destructor
virtual ~CqlConnection(); 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 /// @brief Prepare statements
/// ///
/// Creates the prepared statements for all of the CQL statements used /// Creates the prepared statements for all of the CQL statements used
......
...@@ -2320,6 +2320,9 @@ protected: ...@@ -2320,6 +2320,9 @@ protected:
HostPtr& target_host) const; HostPtr& target_host) const;
private: private:
/// @brief Parameters
db::DatabaseConnection::ParameterMap parameters_;
/// @brief CQL connection /// @brief CQL connection
mutable CqlConnection dbconn_; mutable CqlConnection dbconn_;
}; // class CqlHostDataSourceImpl }; // class CqlHostDataSourceImpl
...@@ -2366,14 +2369,8 @@ operator==(const HostKey& key1, const HostKey& key2) { ...@@ -2366,14 +2369,8 @@ operator==(const HostKey& key1, const HostKey& key2) {
} }
CqlHostDataSourceImpl::CqlHostDataSourceImpl(const CqlConnection::ParameterMap& parameters) CqlHostDataSourceImpl::CqlHostDataSourceImpl(const CqlConnection::ParameterMap& parameters)
: dbconn_(parameters) { : parameters_(parameters), dbconn_(parameters) {
// Open the database. // Validate the schema version first.
dbconn_.openDatabase();
// Prepare the version exchange first.
dbconn_.prepareStatements(CqlVersionExchange::tagged_statements_);
// Validate the schema version.
std::pair<uint32_t, uint32_t> code_version(CQL_SCHEMA_VERSION_MAJOR, std::pair<uint32_t, uint32_t> code_version(CQL_SCHEMA_VERSION_MAJOR,
CQL_SCHEMA_VERSION_MINOR); CQL_SCHEMA_VERSION_MINOR);
std::pair<uint32_t, uint32_t> db_version = getVersion(); std::pair<uint32_t, uint32_t> db_version = getVersion();
...@@ -2384,6 +2381,9 @@ CqlHostDataSourceImpl::CqlHostDataSourceImpl(const CqlConnection::ParameterMap& ...@@ -2384,6 +2381,9 @@ CqlHostDataSourceImpl::CqlHostDataSourceImpl(const CqlConnection::ParameterMap&
<< db_version.second); << db_version.second);
} }
// Open the database.
dbconn_.openDatabase();
// Prepare all possible statements. // Prepare all possible statements.
dbconn_.prepareStatements(CqlHostExchange::tagged_statements_); dbconn_.prepareStatements(CqlHostExchange::tagged_statements_);
} }
...@@ -2748,8 +2748,7 @@ CqlHostDataSourceImpl::getName() const { ...@@ -2748,8 +2748,7 @@ CqlHostDataSourceImpl::getName() const {
VersionPair VersionPair
CqlHostDataSourceImpl::getVersion() const { CqlHostDataSourceImpl::getVersion() const {
std::unique_ptr<CqlVersionExchange> version_exchange(new CqlVersionExchange()); return CqlConnection::getVersion(parameters_);
return (version_exchange->retrieveVersion(dbconn_));
} }
bool bool
......
...@@ -2029,13 +2029,8 @@ CqlLeaseStatsQuery::executeSelect(const CqlConnection& connection, const AnyArra ...@@ -2029,13 +2029,8 @@ CqlLeaseStatsQuery::executeSelect(const CqlConnection& connection, const AnyArra
} }
CqlLeaseMgr::CqlLeaseMgr(const DatabaseConnection::ParameterMap &parameters) CqlLeaseMgr::CqlLeaseMgr(const DatabaseConnection::ParameterMap &parameters)
: LeaseMgr(), dbconn_(parameters) { : LeaseMgr(), parameters_(parameters), dbconn_(parameters) {
dbconn_.openDatabase(); // Validate the schema version first.
// Prepare the version exchange first.
dbconn_.prepareStatements(CqlVersionExchange::tagged_statements_);
// Validate the schema version.
std::pair<uint32_t, uint32_t> code_version(CQL_SCHEMA_VERSION_MAJOR, std::pair<uint32_t, uint32_t> code_version(CQL_SCHEMA_VERSION_MAJOR,
CQL_SCHEMA_VERSION_MINOR); CQL_SCHEMA_VERSION_MINOR);
std::pair<uint32_t, uint32_t> db_version = getVersion(); std::pair<uint32_t, uint32_t> db_version = getVersion();
...@@ -2046,6 +2041,9 @@ CqlLeaseMgr::CqlLeaseMgr(const DatabaseConnection::ParameterMap &parameters) ...@@ -2046,6 +2041,9 @@ CqlLeaseMgr::CqlLeaseMgr(const DatabaseConnection::ParameterMap &parameters)
<< db_version.second); << db_version.second);
} }
// Open the database.
dbconn_.openDatabase();
// Now prepare the rest of the exchanges. // Now prepare the rest of the exchanges.
dbconn_.prepareStatements(CqlLease4Exchange::tagged_statements_); dbconn_.prepareStatements(CqlLease4Exchange::tagged_statements_);
dbconn_.prepareStatements(CqlLease6Exchange::tagged_statements_); dbconn_.prepareStatements(CqlLease6Exchange::tagged_statements_);
...@@ -2744,8 +2742,7 @@ VersionPair ...@@ -2744,8 +2742,7 @@ VersionPair
CqlLeaseMgr::getVersion() const { CqlLeaseMgr::getVersion() const {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_VERSION); LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_CQL_GET_VERSION);
std::unique_ptr<CqlVersionExchange> version_exchange(new CqlVersionExchange()); return CqlConnection::getVersion(parameters_);
return version_exchange->retrieveVersion(dbconn_);
} }
void void
......
...@@ -578,6 +578,9 @@ public: ...@@ -578,6 +578,9 @@ public:
virtual void rollback() override; virtual void rollback() override;
private: private:
/// @brief Connection parameters
db::DatabaseConnection::ParameterMap parameters_;
/// @brief Database connection object /// @brief Database connection object
mutable db::CqlConnection dbconn_; mutable db::CqlConnection dbconn_;
}; };
......
...@@ -1948,11 +1948,9 @@ public: ...@@ -1948,11 +1948,9 @@ public:
/// @brief Returns backend version. /// @brief Returns backend version.
/// ///
/// The method is called by the constructor after opening the database /// The method is called by the constructor before opening the database
/// but prior to preparing SQL statements, to verify that the schema version /// to verify that the schema version is correct.
/// is correct. Thus it must not rely on a pre-prepared statement or ///
/// formal statement execution error checking.
//
/// @return Version number stored in the database, as a pair of unsigned /// @return Version number stored in the database, as a pair of unsigned
/// integers. "first" is the major version number, "second" the /// integers. "first" is the major version number, "second" the
/// minor number. /// minor number.
...@@ -2097,6 +2095,9 @@ public: ...@@ -2097,6 +2095,9 @@ public:
/// or dhcp6_options table. /// or dhcp6_options table.
boost::shared_ptr<MySqlOptionExchange> host_option_exchange_; boost::shared_ptr<MySqlOptionExchange> host_option_exchange_;
/// @brief The parameters
db::DatabaseConnection::ParameterMap parameters_;
/// @brief MySQL connection /// @brief MySQL connection
MySqlConnection conn_; MySqlConnection conn_;
...@@ -2481,13 +2482,11 @@ MySqlHostDataSourceImpl(const MySqlConnection::ParameterMap& parameters) ...@@ -2481,13 +2482,11 @@ MySqlHostDataSourceImpl(const MySqlConnection::ParameterMap& parameters)
DHCP4_AND_DHCP6)), DHCP4_AND_DHCP6)),
host_ipv6_reservation_exchange_(new MySqlIPv6ReservationExchange()), host_ipv6_reservation_exchange_(new MySqlIPv6ReservationExchange()),
host_option_exchange_(new MySqlOptionExchange()), host_option_exchange_(new MySqlOptionExchange()),
parameters_(parameters),
conn_(parameters), conn_(parameters),
is_readonly_(false) { is_readonly_(false) {
// Open the database. // Test schema version first.
conn_.openDatabase();
// Test schema version before we try to prepare statements.
std::pair<uint32_t, uint32_t> code_version(MYSQL_SCHEMA_VERSION_MAJOR, std::pair<uint32_t, uint32_t> code_version(MYSQL_SCHEMA_VERSION_MAJOR,
MYSQL_SCHEMA_VERSION_MINOR); MYSQL_SCHEMA_VERSION_MINOR);
std::pair<uint32_t, uint32_t> db_version = getVersion(); std::pair<uint32_t, uint32_t> db_version = getVersion();
...@@ -2498,6 +2497,9 @@ MySqlHostDataSourceImpl(const MySqlConnection::ParameterMap& parameters) ...@@ -2498,6 +2497,9 @@ MySqlHostDataSourceImpl(const MySqlConnection::ParameterMap& parameters)
<< db_version.second); << db_version.second);
} }
// Open the database.
conn_.openDatabase();
// Enable autocommit. In case transaction is explicitly used, this // Enable autocommit. In case transaction is explicitly used, this
// setting will be overwritten for the transaction. However, there are // setting will be overwritten for the transaction. However, there are
// cases when lack of autocommit could cause transactions to hang // cases when lack of autocommit could cause transactions to hang
...@@ -2551,62 +2553,9 @@ MySqlHostDataSourceImpl::getVersion() const { ...@@ -2551,62 +2553,9 @@ MySqlHostDataSourceImpl::getVersion() const {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_MYSQL_HOST_DB_GET_VERSION); DHCPSRV_MYSQL_HOST_DB_GET_VERSION);
// Allocate a new statement. return (MySqlConnection::getVersion(parameters_));
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));
} }
void void
MySqlHostDataSourceImpl::addStatement(StatementIndex stindex, MySqlHostDataSourceImpl::addStatement(StatementIndex stindex,
std::vector<MYSQL_BIND>& bind) { std::vector<MYSQL_BIND>& bind) {
......
...@@ -2961,65 +2961,7 @@ MySqlLeaseMgr::getVersion() const { ...@@ -2961,65 +2961,7 @@ MySqlLeaseMgr::getVersion() const {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_MYSQL_GET_VERSION); DHCPSRV_MYSQL_GET_VERSION);
// Get a connection. return (MySqlConnection::getVersion(parameters_));
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));
} }
void void
......
...@@ -1115,9 +1115,8 @@ protected: ...@@ -1115,9 +1115,8 @@ protected:
PgSqlLeaseMgr::PgSqlLeaseMgr(const DatabaseConnection::ParameterMap& parameters) PgSqlLeaseMgr::PgSqlLeaseMgr(const DatabaseConnection::ParameterMap& parameters)
: LeaseMgr(), exchange4_(new PgSqlLease4Exchange()), : LeaseMgr(), exchange4_(new PgSqlLease4Exchange()),
exchange6_(new PgSqlLease6Exchange()), conn_(parameters) { exchange6_(new PgSqlLease6Exchange()), parameters_(parameters),
conn_.openDatabase(); conn_(parameters) {
// Validate schema version first. // Validate schema version first.
std::pair<uint32_t, uint32_t> code_version(PG_SCHEMA_VERSION_MAJOR, std::pair<uint32_t, uint32_t> code_version(PG_SCHEMA_VERSION_MAJOR,
PG_SCHEMA_VERSION_MINOR); PG_SCHEMA_VERSION_MINOR);
...@@ -1130,6 +1129,9 @@ PgSqlLeaseMgr::PgSqlLeaseMgr(const DatabaseConnection::ParameterMap& parameters) ...@@ -1130,6 +1129,9 @@ PgSqlLeaseMgr::PgSqlLeaseMgr(const DatabaseConnection::ParameterMap& parameters)
<< db_version.second); << db_version.second);
} }
// Open the database.
conn_.openDatabase();
// Now prepare the SQL statements. // Now prepare the SQL statements.
int i = 0; int i = 0;
for( ; tagged_statements[i].text != NULL ; ++i) { for( ; tagged_statements[i].text != NULL ; ++i) {
...@@ -1929,25 +1931,7 @@ PgSqlLeaseMgr::getVersion() const { ...@@ -1929,25 +1931,7 @@ PgSqlLeaseMgr::getVersion() const {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_PGSQL_GET_VERSION); DHCPSRV_PGSQL_GET_VERSION);
const char* version_sql = "SELECT version, minor FROM schema_version;"; return (PgSqlConnection::getVersion(parameters_));
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));
} }
void void
......
...@@ -770,6 +770,9 @@ private: ...@@ -770,6 +770,9 @@ private:
boost::scoped_ptr<PgSqlLease4Exchange> exchange4_; ///< Exchange object boost::scoped_ptr<PgSqlLease4Exchange> exchange4_; ///< Exchange object
boost::scoped_ptr<PgSqlLease6Exchange> exchange6_; ///< Exchange object boost::scoped_ptr<PgSqlLease6Exchange> exchange6_; ///< Exchange object
/// The parameters.
db::DatabaseConnection::ParameterMap parameters_;
/// PostgreSQL connection handle /// PostgreSQL connection handle
db::PgSqlConnection conn_; db::PgSqlConnection conn_;
}; };
......
...@@ -212,6 +212,70 @@ MySqlConnection::openDatabase() { ...@@ -212,6 +212,70 @@ MySqlConnection::openDatabase() {
} }
} }
// 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 // 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 // in a vector of strings (text_statements_) and is used in the output of
......
...@@ -210,6 +210,19 @@ public: ...@@ -210,6 +210,19 @@ public:
/// @brief Destructor /// @brief Destructor
virtual ~MySqlConnection(); 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>