mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-29 13:07:50 +00:00
[1008-move-database-schema-version-check-to-database-libraries] Moved getVersion codes to databases
This commit is contained in:
parent
6f9dfacd55
commit
c131e65e82
@ -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() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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:
|
|||||||
/// @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:
|
|||||||
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) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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&
|
|||||||
<< 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 {
|
|||||||
|
|
||||||
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
|
|||||||
}
|
}
|
||||||
|
|
||||||
CqlLeaseMgr::CqlLeaseMgr(const DatabaseConnection::ParameterMap ¶meters)
|
CqlLeaseMgr::CqlLeaseMgr(const DatabaseConnection::ParameterMap ¶meters)
|
||||||
: 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 ¶meters)
|
|||||||
<< 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
|
|||||||
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:
|
|||||||
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:
|
|||||||
|
|
||||||
/// @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:
|
|||||||
/// 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)
|
|||||||
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)
|
|||||||
<< 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 {
|
|||||||
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 {
|
|||||||
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:
|
|||||||
|
|
||||||
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)
|
|||||||
<< 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 {
|
|||||||
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:
|
|||||||
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() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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:
|
|||||||
/// @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>
|
||||||
|
getVersion(const ParameterMap& parameters);
|
||||||
|
|
||||||
/// @brief Prepare Single Statement
|
/// @brief Prepare Single Statement
|
||||||
///
|
///
|
||||||
/// Creates a prepared statement from the text given and adds it to the
|
/// Creates a prepared statement from the text given and adds it to the
|
||||||
|
@ -390,4 +390,29 @@ TEST_F(MySqlConnectionTest, deleteByValue) {
|
|||||||
EXPECT_TRUE(deleted);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
#define PGSQL_STATECODE_LEN 5
|
#define PGSQL_STATECODE_LEN 5
|
||||||
#include <utils/errcodes.h>
|
#include <utils/errcodes.h>
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace isc {
|
namespace isc {
|
||||||
@ -127,6 +129,35 @@ PgSqlConnection::~PgSqlConnection() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
void
|
||||||
PgSqlConnection::prepareStatement(const PgSqlTaggedStatement& statement) {
|
PgSqlConnection::prepareStatement(const PgSqlTaggedStatement& statement) {
|
||||||
// Prepare all statements queries with all known fields datatype
|
// Prepare all statements queries with all known fields datatype
|
||||||
|
@ -311,6 +311,19 @@ public:
|
|||||||
/// @brief Destructor
|
/// @brief Destructor
|
||||||
virtual ~PgSqlConnection();
|
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
|
/// @brief Prepare Single Statement
|
||||||
///
|
///
|
||||||
/// Creates a prepared statement from the text given and adds it to the
|
/// Creates a prepared statement from the text given and adds it to the
|
||||||
@ -318,7 +331,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// @param statement SQL statement to be prepared.
|
/// @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.
|
/// failed.
|
||||||
void prepareStatement(const PgSqlTaggedStatement& statement);
|
void prepareStatement(const PgSqlTaggedStatement& statement);
|
||||||
|
|
||||||
@ -332,7 +345,7 @@ public:
|
|||||||
/// @param end_statement Pointer to the statement marking end of the
|
/// @param end_statement Pointer to the statement marking end of the
|
||||||
/// range of statements to be compiled. This last statement is not compiled.
|
/// 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.
|
/// failed.
|
||||||
void prepareStatements(const PgSqlTaggedStatement* start_statement,
|
void prepareStatements(const PgSqlTaggedStatement* start_statement,
|
||||||
const PgSqlTaggedStatement* end_statement);
|
const PgSqlTaggedStatement* end_statement);
|
||||||
@ -396,7 +409,7 @@ public:
|
|||||||
/// @param r result of the last PostgreSQL operation
|
/// @param r result of the last PostgreSQL operation
|
||||||
/// @param statement - tagged statement that was executed
|
/// @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,
|
void checkStatementError(const PgSqlResult& r,
|
||||||
PgSqlTaggedStatement& statement) const;
|
PgSqlTaggedStatement& statement) const;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user