-// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
{PgSqlLeaseMgr::GET_LEASE4_ADDR, 1,
{ 20 },
"get_lease4_addr",
- "DECLARE get_lease4_addr CURSOR FOR "
"SELECT address, hwaddr, client_id, "
"valid_lifetime, extract(epoch from expire), subnet_id, fqdn_fwd, fqdn_rev, hostname "
"FROM lease4 "
{PgSqlLeaseMgr::GET_LEASE4_CLIENTID, 1,
{ 17 },
"get_lease4_clientid",
- "DECLARE get_lease4_clientid CURSOR FOR "
"SELECT address, hwaddr, client_id, "
"valid_lifetime, extract(epoch from expire), subnet_id, fqdn_fwd, fqdn_rev, hostname "
"FROM lease4 "
{PgSqlLeaseMgr::GET_LEASE4_CLIENTID_SUBID, 2,
{ 17, 20 },
"get_lease4_clientid_subid",
- "DECLARE get_lease4_clientid_subid CURSOR FOR "
"SELECT address, hwaddr, client_id, "
"valid_lifetime, extract(epoch from expire)::bigint, subnet_id, fqdn_fwd, fqdn_rev, hostname "
"FROM lease4 "
{PgSqlLeaseMgr::GET_LEASE4_HWADDR, 1,
{ 17 },
"get_lease4_hwaddr",
- "DECLARE get_lease4_hwaddr CURSOR FOR "
"SELECT address, hwaddr, client_id, "
"valid_lifetime, extract(epoch from expire)::bigint, subnet_id, fqdn_fwd, fqdn_rev, hostname "
"FROM lease4 "
{PgSqlLeaseMgr::GET_LEASE4_HWADDR_SUBID, 2,
{ 17, 20 },
"get_lease4_hwaddr_subid",
- "DECLARE get_lease4_hwaddr_subid CURSOR FOR "
"SELECT address, hwaddr, client_id, "
"valid_lifetime, extract(epoch from expire)::bigint, subnet_id, fqdn_fwd, fqdn_rev, hostname "
"FROM lease4 "
{PgSqlLeaseMgr::GET_LEASE6_ADDR, 2,
{ 1043, 21 },
"get_lease6_addr",
- "DECLARE get_lease6_addr CURSOR FOR "
"SELECT address, duid, valid_lifetime, "
"extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
"lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname "
{PgSqlLeaseMgr::GET_LEASE6_DUID_IAID, 3,
{ 17, 20, 21 },
"get_lease6_duid_iaid",
- "DECLARE get_lease6_duid_iaid CURSOR FOR "
"SELECT address, duid, valid_lifetime, "
"extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
"lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname "
{PgSqlLeaseMgr::GET_LEASE6_DUID_IAID_SUBID, 4,
{ 21, 17, 20, 20 },
"get_lease6_duid_iaid_subid",
- "DECLARE get_lease6_duid_iaid_subid CURSOR FOR "
"SELECT address, duid, valid_lifetime, "
"extract(epoch from expire)::bigint, subnet_id, pref_lifetime, "
"lease_type, iaid, prefix_len, fqdn_fwd, fqdn_rev, hostname "
{PgSqlLeaseMgr::GET_VERSION, 0,
{ 0 },
"get_version",
- "DECLARE get_version CURSOR FOR "
"SELECT version, minor FROM schema_version"},
{PgSqlLeaseMgr::INSERT_LEASE4, 9,
{ 20, 17, 17, 20, 1114, 20, 16, 16, 1043 },
}
/// Compiled statement bind parameters
- bindparams params;
+ BindParams params;
};
/// @brief Represents a single Lease4 exchange
params.reserve(LEASE_COLUMNS);
}
- bindparams
+ BindParams
createBindForSend(const Lease4Ptr& lease) {
lease_ = lease;
params.clear();
params.push_back(PgSqlParam(tmp.str()));
tmp.str("");
- // Although HWADDR object will always be there, it may be just an empty vector
+ // Although HWADDR object will always be there, it may be just an
+ // empty vector
if (!lease_->hwaddr_.empty()) {
if (lease->hwaddr_.size() > HWAddr::MAX_HWADDR_LEN) {
- isc_throw(DbOperationError, "Attempted to store Hardware address longer ("
- << lease->hwaddr_.size() << " than allowed maximum of "
+ isc_throw(DbOperationError,
+ "Attempted to store Hardware address longer ("
+ << lease->hwaddr_.size()
+ << " than allowed maximum of "
<< HWAddr::MAX_HWADDR_LEN);
}
const char* valid_lifetime_str = PQgetvalue(r, line, 3);
const char* expire_str = PQgetvalue(r, line, 4);
const char* subnet_id_str = PQgetvalue(r, line, 5);
- unsigned long valid_lifetime, subnet_id;
+ unsigned long valid_lifetime;
+ unsigned long subnet_id;
istringstream tmp;
tmp.str(addr4_str);
tmp >> addr4_;
- tmp.str("");
tmp.clear();
memcpy(hwaddr_buffer_, hwaddr_str, hwaddr_length_);
tmp.str(valid_lifetime_str);
tmp >> valid_lifetime;
- tmp.str("");
- tmp.clear();
valid_lifetime_ = static_cast<uint32_t>(valid_lifetime);
+ tmp.clear();
expire_ = convertFromDatabaseTime(expire_str);
tmp.str(subnet_id_str);
tmp >> subnet_id;
subnet_id_ = static_cast<uint32_t>(subnet_id);
+ tmp.clear();
time_t cltt = expire_ - valid_lifetime_;
// Extract fqdn_fwd, fqdn_rev
- // boolean is represented as one of 3 possible strings:
- // "" (means NULL or not set), "t" (means true), "f" (means false)
bool fwd = stringToBool(PQgetvalue(r, line, 6));
bool rev = stringToBool(PQgetvalue(r, line, 7));
params.reserve(LEASE_COLUMNS);
}
- bindparams
+ BindParams
createBindForSend(const Lease6Ptr& lease) {
lease_ = lease;
params.clear();
tmp.str(valid_lifetime_str);
tmp >> valid_lifetime;
- tmp.str("");
- tmp.clear();
valid_lifetime_ = static_cast<uint32_t>(valid_lifetime);
+ tmp.clear();
expire_ = convertFromDatabaseTime(expire_str);
tmp.str(subnet_id_str);
tmp >> subnet_id;
- tmp.str("");
- tmp.clear();
subnet_id_ = static_cast<uint32_t>(subnet_id);
+ tmp.clear();
tmp.str(pref_lifetime_str);
tmp >> pref_lifetime;
- tmp.str("");
- tmp.clear();
pref_lifetime_ = static_cast<uint32_t>(pref_lifetime);
+ tmp.clear();
tmp.str(lease_type_str);
tmp >> lease_type;
- tmp.str("");
tmp.clear();
tmp.str(iaid_str);
tmp >> iaid;
- tmp.str("");
- tmp.clear();
iaid_ = static_cast<uint32_t>(iaid);
+ tmp.clear();
tmp.str(prefixlen_str);
tmp >> prefixlen;
prefixlen_ = static_cast<uint8_t>(prefixlen);
+ tmp.clear();
Lease6::Type type = Lease6::TYPE_NA;
switch (lease_type) {
}
// Extract fqdn_fwd, fqdn_rev
- // boolean is represented as one of 3 possible strings:
- // "" (means NULL or not set), "t" (means true), "f" (means false)
bool fwd = stringToBool(PQgetvalue(r, line, 9));
bool rev = stringToBool(PQgetvalue(r, line, 10));
Lease6Ptr result(new Lease6(type, addr, duid_ptr, iaid_,
pref_lifetime_, valid_lifetime_, 0, 0,
- subnet_id_, fwd, rev, hostname, prefixlen_));
+ subnet_id_, fwd, rev, hostname,
+ prefixlen_));
time_t cltt = expire_ - valid_lifetime_;
result->cltt_ = cltt;
};
PgSqlLeaseMgr::PgSqlLeaseMgr(const LeaseMgr::ParameterMap& parameters)
- : LeaseMgr(parameters){
- status = NULL;
+ : LeaseMgr(parameters) {
+ conn_ = NULL;
openDatabase();
prepareStatements();
}
PgSqlLeaseMgr::~PgSqlLeaseMgr() {
- if (status) {
- // Attempt to deallocate prepared queries set previously with DEALLOCATE query
- // No internal libpq function for that, no errors checking as well
- /// @todo Can't this be done as a single string with list of statements?
- for(int i = 0; tagged_statements[i].text != NULL; ++ i) {
- string deallocate = "DEALLOCATE \"";
- deallocate += tagged_statements[i].name;
- deallocate += "\"";
- PGresult* r = PQexec(status, deallocate.c_str());
- PQclear(r);
+ if (conn_) {
+ // Deallocate the prepared queries.
+ PGresult* r = PQexec(conn_, "DEALLOCATE all");
+ if(PQresultStatus(r) != PGRES_COMMAND_OK) {
+ /// @todo log it for posterity but go on
+ std::cout << "deallocate error: "
+ << PQerrorMessage(conn_) << std::endl;
}
- PQfinish(status);
+ PQclear(r);
+ PQfinish(conn_);
}
}
statements_.resize(NUM_STATEMENTS, PgSqlStatementBind());
for(int i = 0; tagged_statements[i].text != NULL; ++ i) {
- /// @todo why do we bother with select here? If they are already
- /// defined we should let the error occur because we only do this
- /// once per open anyway.
- string checkstatement = "SELECT * FROM pg_prepared_statements "
- "WHERE name = '";
- checkstatement += tagged_statements[i].name;
- checkstatement += "'";
-
- PGresult* r = PQexec(status, checkstatement.c_str());
+ // Prepare all statements queries with all known fields datatype
+ PGresult* r = PQprepare(conn_, tagged_statements[i].name,
+ tagged_statements[i].text,
+ tagged_statements[i].nbparams,
+ tagged_statements[i].types);
- if(!PQntuples(r)) {
- PQclear(r);
- r = PQexec(status, "BEGIN");
- PQclear(r);
- // Prepare all statements queries with all known fields datatype
- // No need to remind them when called
- r = PQprepare(status, tagged_statements[i].name,
- tagged_statements[i].text,
- tagged_statements[i].nbparams,
- tagged_statements[i].types);
-
- if(PQresultStatus(r) != PGRES_COMMAND_OK) {
- PQclear(r);
- isc_throw(DbOperationError, "unable to prepare PostgreSQL statement <" <<
- tagged_statements[i].text << ">, reason: " << PQerrorMessage(status));
- }
-
- PQclear(r);
-
- r = PQexec(status, "END");
+ if(PQresultStatus(r) != PGRES_COMMAND_OK) {
PQclear(r);
+ isc_throw(DbOperationError,
+ "unable to prepare PostgreSQL statement: "
+ << tagged_statements[i].text << ", reason: "
+ << PQerrorMessage(conn_));
+ }
- statements_[i].stmt_name = tagged_statements[i].name;
- statements_[i].stmt_nbparams = tagged_statements[i].nbparams;
- } else {
- PQclear(r);
- }
+ statements_[i].stmt_name = tagged_statements[i].name;
+ statements_[i].stmt_nbparams = tagged_statements[i].nbparams;
+ PQclear(r);
}
}
isc_throw(NoDatabaseName, "must specified a name for the database");
}
- status = PQconnectdb(dbconnparameters.c_str());
- if (status == NULL) {
+ conn_ = PQconnectdb(dbconnparameters.c_str());
+ if (conn_ == NULL) {
isc_throw(DbOpenError, "could not allocate connection object");
}
- if (PQstatus(status) != CONNECTION_OK) {
+ if (PQstatus(conn_) != CONNECTION_OK) {
// If we have a connection object, we have to call finish
// to release it, but grab the error message first.
- std::string error_message = PQerrorMessage(status);
- PQfinish(status);
+ std::string error_message = PQerrorMessage(conn_);
+ PQfinish(conn_);
isc_throw(DbOpenError, error_message);
}
}
bool
PgSqlLeaseMgr::addLeaseCommon(StatementIndex stindex,
- bindparams& params) {
+ BindParams& params) {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_PGSQL_ADD_ADDR4).arg(statements_[stindex].stmt_name);
vector<int> out_formats;
convertToQuery(params, out_values, out_lengths, out_formats);
- PGresult * r = PQexecPrepared(status, statements_[stindex].stmt_name,
+ PGresult * r = PQexecPrepared(conn_, statements_[stindex].stmt_name,
statements_[stindex].stmt_nbparams,
- &out_values[0], &out_lengths[0], &out_formats[0], 0);
+ &out_values[0], &out_lengths[0],
+ &out_formats[0], 0);
int s = PQresultStatus(r);
if (s != PGRES_COMMAND_OK) {
- const char * errorMsg = PQerrorMessage(status);
+ const char * errorMsg = PQerrorMessage(conn_);
PQclear(r);
+ /// @todo - ok, do we have to rely on error message text??
+ /// and why is failing on duplicate key NOT an error?
+ /// should be looking at global sqlca struct
if(!strncmp(errorMsg, "ERROR: duplicate key",
sizeof("ERROR: duplicate key") - 1)) {
return (false);
}
- isc_throw(DbOperationError, "unable to INSERT for <" <<
- statements_[stindex].stmt_name << ">, " <<
+ isc_throw(DbOperationError, "unable to INSERT for " <<
+ statements_[stindex].stmt_name << ", reason: " <<
errorMsg);
}
PgSqlLeaseMgr::addLease(const Lease4Ptr& lease) {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_PGSQL_ADD_ADDR4).arg(lease->addr_.toText());
- bindparams params = exchange4_->createBindForSend(lease);
+ BindParams params = exchange4_->createBindForSend(lease);
return (addLeaseCommon(INSERT_LEASE4, params));
}
PgSqlLeaseMgr::addLease(const Lease6Ptr& lease) {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_PGSQL_ADD_ADDR6).arg(lease->addr_.toText());
- bindparams params = exchange6_->createBindForSend(lease);
+ BindParams params = exchange6_->createBindForSend(lease);
return (addLeaseCommon(INSERT_LEASE6, params));
}
template <typename Exchange, typename LeaseCollection>
void PgSqlLeaseMgr::getLeaseCollection(StatementIndex stindex,
- bindparams & params,
+ BindParams & params,
Exchange& exchange,
LeaseCollection& result,
bool single) const {
vector<int> out_lengths;
vector<int> out_formats;
convertToQuery(params, out_values, out_lengths, out_formats);
- PGresult* r = PQexec(status, "BEGIN");
- PQclear(r);
- r = PQexecPrepared(status, statements_[stindex].stmt_name,
+ PGresult* r = PQexecPrepared(conn_, statements_[stindex].stmt_name,
statements_[stindex].stmt_nbparams, &out_values[0],
&out_lengths[0], &out_formats[0], 0);
- checkError(r, stindex, "unable to bind WHERE clause parameter");
- PQclear(r);
-
- string fetchall = "FETCH ALL in ";
- fetchall += statements_[stindex].stmt_name;
-
- r = PQexec(status, fetchall.c_str());
- checkError(r, stindex, "unable to FETCH ALL");
+ checkStatementError(r, stindex);
int lines = PQntuples(r);
-
- if(single && lines > 1) {
- PQclear(r);
- r = PQexec(status, "END");
+ if (single && lines > 1) {
PQclear(r);
isc_throw(MultipleRecords, "multiple records were found in the "
"database where only one was expected for query "
}
PQclear(r);
-
- string closecursor = "CLOSE ";
- closecursor += statements_[stindex].stmt_name;
- r = PQexec(status, closecursor.c_str());
- PQclear(r);
-
- r = PQexec(status, "END");
- PQclear(r);
}
void
-PgSqlLeaseMgr::getLease(StatementIndex stindex, bindparams & params,
+PgSqlLeaseMgr::getLease(StatementIndex stindex, BindParams & params,
Lease4Ptr& result) const {
// Create appropriate collection object and get all leases matching
// the selection criteria. The "single" paraeter is true to indicate
}
void
-PgSqlLeaseMgr::getLease(StatementIndex stindex, bindparams & params,
+PgSqlLeaseMgr::getLease(StatementIndex stindex, BindParams & params,
Lease6Ptr& result) const {
// Create appropriate collection object and get all leases matching
// the selection criteria. The "single" paraeter is true to indicate
DHCPSRV_PGSQL_GET_ADDR4).arg(addr.toText());
// Set up the WHERE clause value
- bindparams inparams;
+ BindParams inparams;
ostringstream tmp;
tmp << static_cast<uint32_t>(addr);
DHCPSRV_PGSQL_GET_HWADDR).arg(hwaddr.toText());
// Set up the WHERE clause value
- bindparams inparams;
+ BindParams inparams;
if (!hwaddr.hwaddr_.empty()) {
inparams.push_back(PgSqlParam(hwaddr.hwaddr_));
PgSqlLeaseMgr::getLease4(const HWAddr& hwaddr, SubnetID subnet_id) const {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_PGSQL_GET_SUBID_HWADDR)
- .arg(subnet_id).arg(hwaddr.toText());
+ .arg(subnet_id).arg(hwaddr.toText());
// Set up the WHERE clause value
- bindparams inparams;
+ BindParams inparams;
ostringstream tmp;
if (!hwaddr.hwaddr_.empty()) {
DHCPSRV_PGSQL_GET_CLIENTID).arg(clientid.toText());
// Set up the WHERE clause value
- bindparams inparams;
+ BindParams inparams;
// CLIENT_ID
inparams.push_back(PgSqlParam(clientid.getClientId()));
.arg(subnet_id).arg(clientid.toText());
// Set up the WHERE clause value
- bindparams inparams;
+ BindParams inparams;
ostringstream tmp;
// CLIENT_ID
}
Lease4Ptr
-PgSqlLeaseMgr::getLease4(const ClientId& /*client_id*/, const HWAddr& /*hwaddr*/,
+PgSqlLeaseMgr::getLease4(const ClientId& /*client_id*/,
+ const HWAddr& /*hwaddr*/,
SubnetID /*subnet_id*/) const {
/// @todo
-
Lease4Ptr result;
return (result);
}
.arg(addr.toText()).arg(lease_type);
// Set up the WHERE clause value
- bindparams inparams;
+ BindParams inparams;
ostringstream tmp;
// ADDRESS
}
Lease6Collection
-PgSqlLeaseMgr::getLeases6(Lease::Type type, const DUID& duid, uint32_t iaid) const {
- LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_PGSQL_GET_IAID_DUID)
- .arg(iaid).arg(duid.toText()).arg(type);
+PgSqlLeaseMgr::getLeases6(Lease::Type type, const DUID& duid,
+ uint32_t iaid) const {
+ LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
+ DHCPSRV_PGSQL_GET_IAID_DUID)
+ .arg(iaid).arg(duid.toText()).arg(type);
// Set up the WHERE clause value
- bindparams inparams;
+ BindParams inparams;
ostringstream tmp;
// DUID
.arg(iaid).arg(subnet_id).arg(duid.toText()).arg(lease_type);
// Set up the WHERE clause value
- bindparams inparams;
+ BindParams inparams;
ostringstream tmp;
// LEASE_TYPE
template <typename LeasePtr>
void
-PgSqlLeaseMgr::updateLeaseCommon(StatementIndex stindex, bindparams & params,
+PgSqlLeaseMgr::updateLeaseCommon(StatementIndex stindex, BindParams & params,
const LeasePtr& lease) {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_PGSQL_ADD_ADDR4).arg(statements_[stindex].stmt_name);
vector<int> formats_;
convertToQuery(params, params_, lengths_, formats_);
- PGresult * r = PQexecPrepared(status, statements_[stindex].stmt_name,
+ PGresult * r = PQexecPrepared(conn_, statements_[stindex].stmt_name,
statements_[stindex].stmt_nbparams,
¶ms_[0], &lengths_[0], &formats_[0], 0);
- checkError(r, stindex, "unable to bind UPDATE parameters");
- int affected_rows = boost::lexical_cast<int>(PQcmdTuples(r));
+ checkStatementError(r, stindex);
+ int affected_rows = boost::lexical_cast<int>(PQcmdTuples(r));
PQclear(r);
- if (!affected_rows) {
+ // Check success case first as it is the most likely outcome.
+ if (affected_rows == 1) {
+ return;
+ }
+
+ // If no rows affected, lease doesn't exist.
+ if (affected_rows == 0) {
isc_throw(NoSuchLease, "unable to update lease for address " <<
lease->addr_.toText() << " as it does not exist");
- } else if (affected_rows > 1) {
- // Should not happen - primary key constraint should only have selected
- // one row.
- isc_throw(DbOperationError, "apparently updated more than one lease "
- "that had the address " << lease->addr_.toText());
}
+
+ // Should not happen - primary key constraint should only have selected
+ // one row.
+ isc_throw(DbOperationError, "apparently updated more than one lease "
+ "that had the address " << lease->addr_.toText());
}
void
// Create the MYSQL_BIND array for the data being updated
ostringstream tmp;
- bindparams params = exchange4_->createBindForSend(lease);
+ BindParams params = exchange4_->createBindForSend(lease);
// Set up the WHERE clause and append it to the MYSQL_BIND array
tmp << static_cast<uint32_t>(lease->addr_);
DHCPSRV_PGSQL_UPDATE_ADDR6).arg(lease->addr_.toText());
// Create the MYSQL_BIND array for the data being updated
- bindparams params = exchange6_->createBindForSend(lease);
+ BindParams params = exchange6_->createBindForSend(lease);
// Set up the WHERE clause and append it to the MYSQL_BIND array
params.push_back(PgSqlParam(lease->addr_.toText()));
}
bool
-PgSqlLeaseMgr::deleteLeaseCommon(StatementIndex stindex, bindparams & params) {
+PgSqlLeaseMgr::deleteLeaseCommon(StatementIndex stindex, BindParams & params) {
vector<const char *> params_;
vector<int> lengths_;
vector<int> formats_;
convertToQuery(params, params_, lengths_, formats_);
- PGresult * r = PQexecPrepared(status, statements_[stindex].stmt_name,
+ PGresult * r = PQexecPrepared(conn_, statements_[stindex].stmt_name,
statements_[stindex].stmt_nbparams,
¶ms_[0], &lengths_[0], &formats_[0], 0);
- checkError(r, stindex, "unable to bind WHERE clause parameter");
+ checkStatementError(r, stindex);
int affected_rows = boost::lexical_cast<int>(PQcmdTuples(r));
PQclear(r);
DHCPSRV_PGSQL_DELETE_ADDR).arg(addr.toText());
// Set up the WHERE clause value
- bindparams inparams;
+ BindParams inparams;
if (addr.isV4()) {
ostringstream tmp;
}
void
-PgSqlLeaseMgr::checkError(PGresult* r, StatementIndex index,
- const char* what) const {
+PgSqlLeaseMgr::checkStatementError(PGresult* r, StatementIndex index) const {
int s = PQresultStatus(r);
if (s != PGRES_COMMAND_OK && s != PGRES_TUPLES_OK) {
PQclear(r);
- isc_throw(DbOperationError, what << " for <" <<
- statements_[index].stmt_name << ">, " <<
- PQerrorMessage(status));
+ isc_throw(DbOperationError, "Statement exec faild:" << " for: " <<
+ statements_[index].stmt_name << ", reason: " <<
+ PQerrorMessage(conn_));
}
}
inline void
-PgSqlLeaseMgr::convertToQuery(const bindparams& params,
+PgSqlLeaseMgr::convertToQuery(const BindParams& params,
std::vector<const char *>& out_values,
std::vector<int>& out_lengths,
std::vector<int>& out_formats) const {
out_lengths.reserve(params.size());
out_formats.reserve(params.size());
- for(bindparams::const_iterator it = params.begin(); it != params.end();
+ for(BindParams::const_iterator it = params.begin(); it != params.end();
++it) {
out_values.push_back((* it).value.c_str());
out_lengths.push_back((* it).binarylen);
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL,
DHCPSRV_PGSQL_GET_VERSION);
- PGresult* r = PQexec(status, "BEGIN");
- PQclear(r);
-
- r = PQexecPrepared(status, "get_version", 0, NULL, NULL, NULL, 0);
-
- PQclear(r);
-
- r = PQexec(status, "FETCH ALL in get_version");
-
- const char* version_str = PQgetvalue(r, 0, 0);
- const char* minor_str = PQgetvalue(r, 0, 1);
+ PGresult* r = PQexecPrepared(conn_, "get_version", 0, NULL, NULL, NULL, 0);
+ checkStatementError(r, GET_VERSION);
istringstream tmp;
-
uint32_t version;
- tmp.str(version_str);
+ tmp.str(PQgetvalue(r, 0, 0));
tmp >> version;
tmp.str("");
tmp.clear();
uint32_t minor;
- tmp.str(minor_str);
+ tmp.str(PQgetvalue(r, 0, 1));
tmp >> minor;
- PQclear(r);
- r = PQexec(status, "CLOSE get_version");
- PQclear(r);
-
- r = PQexec(status, "END");
PQclear(r);
return make_pair<uint32_t, uint32_t>(version, minor);
void
PgSqlLeaseMgr::commit() {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MYSQL_COMMIT);
- PGresult * r = PQexec(status, "COMMIT");
+ PGresult * r = PQexec(conn_, "COMMIT");
if (PQresultStatus(r) != PGRES_COMMAND_OK) {
- isc_throw(DbOperationError, "commit failed: " << PQerrorMessage(status));
+ isc_throw(DbOperationError, "commit failed: " << PQerrorMessage(conn_));
}
PQclear(r);
void
PgSqlLeaseMgr::rollback() {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE_DETAIL, DHCPSRV_MYSQL_ROLLBACK);
- PGresult * r = PQexec(status, "ROLLBACK");
+ PGresult * r = PQexec(conn_, "ROLLBACK");
if (PQresultStatus(r) != PGRES_COMMAND_OK) {
- isc_throw(DbOperationError, "rollback failed: " << PQerrorMessage(status));
+ isc_throw(DbOperationError, "rollback failed: "
+ << PQerrorMessage(conn_));
}
PQclear(r);
};
/// @brief Defines all parameters for binding a compiled statement
-typedef std::vector<PgSqlParam> bindparams;
+typedef std::vector<PgSqlParam> BindParams;
/// @brief Describes a single compiled statement
struct PgSqlStatementBind {
///
/// @throw isc::dhcp::DbOperationError An operation on the open database has
/// failed.
- bool addLeaseCommon(StatementIndex stindex, bindparams& params);
+ bool addLeaseCommon(StatementIndex stindex, BindParams& params);
/// @brief Get Lease Collection Common Code
///
/// @throw isc::dhcp::MultipleRecords Multiple records were retrieved
/// from the database where only one was expected.
template <typename Exchange, typename LeaseCollection>
- void getLeaseCollection(StatementIndex stindex, bindparams& params,
+ void getLeaseCollection(StatementIndex stindex, BindParams& params,
Exchange& exchange, LeaseCollection& result,
bool single = false) const;
/// failed.
/// @throw isc::dhcp::MultipleRecords Multiple records were retrieved
/// from the database where only one was expected.
- void getLeaseCollection(StatementIndex stindex, bindparams& params,
+ void getLeaseCollection(StatementIndex stindex, BindParams& params,
Lease4Collection& result) const {
getLeaseCollection(stindex, params, exchange4_, result);
}
/// failed.
/// @throw isc::dhcp::MultipleRecords Multiple records were retrieved
/// from the database where only one was expected.
- void getLeaseCollection(StatementIndex stindex, bindparams& params,
+ void getLeaseCollection(StatementIndex stindex, BindParams& params,
Lease6Collection& result) const {
getLeaseCollection(stindex, params, exchange6_, result);
}
///
/// @param r result of the last PostgreSQL operation
/// @param index will be used to print out compiled statement name
- /// @param what operation that cause the error
///
/// @throw isc::dhcp::DbOperationError Detailed PostgreSQL failure
- inline void checkError(PGresult* r, StatementIndex index, const char* what) const;
+ inline void checkStatementError(PGresult* r, StatementIndex index) const;
/// @brief Converts query parameters to format accepted by PostgreSQL
///
/// @param out_values [out] values of specified parameters
/// @param out_lengths [out] lengths of specified values
/// @param out_formats [out] specifies format (text (0) or binary (1))
- inline void convertToQuery(const bindparams& params,
+ inline void convertToQuery(const BindParams& params,
std::vector<const char *>& out_values,
std::vector<int>& out_lengths,
std::vector<int>& out_formats) const;
/// but retrieveing only a single lease.
///
/// @param stindex Index of statement being executed
- /// @param bindparams PostgreSQL array for input parameters
+ /// @param BindParams PostgreSQL array for input parameters
/// @param lease Lease4 object returned
- void getLease(StatementIndex stindex, bindparams& params,
+ void getLease(StatementIndex stindex, BindParams& params,
Lease4Ptr& result) const;
/// @brief Get Lease6 Common Code
/// but retrieveing only a single lease.
///
/// @param stindex Index of statement being executed
- /// @param bindparams PostgreSQL array for input parameters
+ /// @param BindParams PostgreSQL array for input parameters
/// @param lease Lease6 object returned
- void getLease(StatementIndex stindex, bindparams& params,
+ void getLease(StatementIndex stindex, BindParams& params,
Lease6Ptr& result) const;
/// were affected.
///
/// @param stindex Index of prepared statement to be executed
- /// @param bindparams Array of PostgreSQL objects representing the parameters.
+ /// @param BindParams Array of PostgreSQL objects representing the parameters.
/// (Note that the number is determined by the number of parameters
/// in the statement.)
/// @param lease Pointer to the lease object whose record is being updated.
/// @throw isc::dhcp::DbOperationError An operation on the open database has
/// failed.
template <typename LeasePtr>
- void updateLeaseCommon(StatementIndex stindex, bindparams& params,
+ void updateLeaseCommon(StatementIndex stindex, BindParams& params,
const LeasePtr& lease);
/// @brief Delete lease common code
/// see how many rows were deleted.
///
/// @param stindex Index of prepared statement to be executed
- /// @param bindparams Array of PostgreSQL objects representing the parameters.
+ /// @param BindParams Array of PostgreSQL objects representing the parameters.
/// (Note that the number is determined by the number of parameters
/// in the statement.)
///
///
/// @throw isc::dhcp::DbOperationError An operation on the open database has
/// failed.
- bool deleteLeaseCommon(StatementIndex stindex, bindparams& params);
+ bool deleteLeaseCommon(StatementIndex stindex, BindParams& params);
/// The exchange objects are used for transfer of data to/from the database.
/// They are pointed-to objects as the contents may change in "const" calls,
std::vector<PgSqlStatementBind> statements_;
/// PostgreSQL connection handle
- PGconn* status;
+ PGconn* conn_;
};
}; // end of isc::dhcp namespace