12 #include <boost/date_time/posix_time/posix_time.hpp> 13 #include <boost/lexical_cast.hpp> 26 const int PsqlBindArray::TEXT_FMT = 0;
27 const int PsqlBindArray::BINARY_FMT = 1;
28 const char* PsqlBindArray::TRUE_STR =
"TRUE";
29 const char* PsqlBindArray::FALSE_STR =
"FALSE";
31 void PsqlBindArray::add(
const char* value) {
36 values_.push_back(value);
37 lengths_.push_back(strlen(value));
38 formats_.push_back(TEXT_FMT);
41 void PsqlBindArray::add(
const std::string& value) {
42 values_.push_back(value.c_str());
43 lengths_.push_back(value.size());
44 formats_.push_back(TEXT_FMT);
47 void PsqlBindArray::insert(
const char* value,
size_t index) {
48 if (index && index >= values_.size()) {
50 <<
", is larger than the array size: " << values_.size());
53 values_.insert(values_.begin() + index, value);
54 lengths_.insert(lengths_.begin() + index, strlen(value));
55 formats_.insert(formats_.begin() + index, TEXT_FMT);
58 void PsqlBindArray::insert(
const std::string& value,
size_t index) {
59 if (index && index >= values_.size()) {
61 <<
", is larger than the array size: " << values_.size());
66 values_.insert(values_.begin() + index, bound_strs_.back()->c_str());
67 lengths_.insert(lengths_.begin() + index, value.size());
68 formats_.insert(formats_.begin() + index, TEXT_FMT);
71 void PsqlBindArray::popBack() {
72 if (values_.size() == 0) {
76 values_.erase(values_.end() - 1);
77 lengths_.erase(lengths_.end() - 1);
78 formats_.erase(formats_.end() - 1);
81 void PsqlBindArray::add(
const std::vector<uint8_t>& data) {
82 values_.push_back(reinterpret_cast<const char*>(&(data[0])));
83 lengths_.push_back(data.size());
84 formats_.push_back(BINARY_FMT);
87 void PsqlBindArray::addTempBinary(
const std::vector<uint8_t>& data) {
89 reinterpret_cast<const char*>(data.data()), data.size())));
91 values_.push_back(reinterpret_cast<const char*>(bound_strs_.back()->data()));
92 lengths_.push_back(data.size());
93 formats_.push_back(BINARY_FMT);
96 void PsqlBindArray::add(
const uint8_t* data,
const size_t len) {
101 values_.push_back(reinterpret_cast<const char*>(&(data[0])));
102 lengths_.push_back(len);
103 formats_.push_back(BINARY_FMT);
106 void PsqlBindArray::addTempBuffer(
const uint8_t* data,
const size_t len) {
108 isc_throw(
BadValue,
"PsqlBindArray::addTempBuffer - uint8_t data cannot be NULL");
112 reinterpret_cast<const char*>(data), len)));
114 values_.push_back(bound_strs_.back()->data());
115 lengths_.push_back(len);
116 formats_.push_back(BINARY_FMT);
119 void PsqlBindArray::add(
const bool& value) {
120 add(value ? TRUE_STR : FALSE_STR);
123 void PsqlBindArray::add(
const uint8_t& byte) {
126 addTempString(boost::lexical_cast<std::string>
127 (static_cast<unsigned int>(byte)));
132 addTempString(boost::lexical_cast<std::string>
135 addTempString(addr.
toText());
139 void PsqlBindArray::addNull(
const int format) {
140 values_.push_back(NULL);
141 lengths_.push_back(0);
142 formats_.push_back(format);
150 add<uint32_t>(triplet.
get());
159 add<uint32_t>(triplet.
getMin());
168 add<uint32_t>(triplet.
getMax());
177 void PsqlBindArray::addTempString(
const std::string& str) {
180 PsqlBindArray::add((bound_strs_.back())->c_str());
188 addTempString(value);
196 << value.
toText() <<
"' is not an IPv4 address");
200 addTempString(value.
toText());
217 << value.
toText() <<
"' is not an IPv6 address");
221 addTempString(value.
toText());
235 PsqlBindArray::addTimestamp(
const boost::posix_time::ptime& timestamp) {
241 ptime epoch(boost::gregorian::date(1970, 1, 1));
242 time_duration::sec_type since_epoch = (timestamp - epoch).total_seconds();
243 time_t input_time(since_epoch);
245 if (input_time > DatabaseConnection::MAX_DB_TIME) {
250 addTempString(PgSqlExchange::convertLocalToDatabaseTime(input_time));
254 PsqlBindArray::addTimestamp() {
257 addTempString(PgSqlExchange::convertLocalToDatabaseTime(now));
267 std::ostringstream ss;
269 addTempString(ss.str());
279 std::ostringstream ss;
281 addTempString(ss.str());
285 PsqlBindArray::toText()
const {
286 std::ostringstream stream;
288 if (values_.size() == 0) {
289 return (
"bindarray is empty");
292 for (
int i = 0; i < values_.size(); ++i) {
293 stream << i <<
" : ";
295 if (lengths_[i] == 0) {
296 stream <<
"empty" << std::endl;
300 if (formats_[i] == TEXT_FMT) {
301 stream <<
"\"" << values_[i] <<
"\"" << std::endl;
303 const char *data = values_[i];
305 for (
int x = 0; x < lengths_[i]; ++x) {
306 stream << std::setfill(
'0') << std::setw(2)
308 <<
static_cast<unsigned int>(data[x]);
311 stream << std::endl << std::setbase(10);
315 return (stream.str());
319 PsqlBindArray::amNull(
size_t index)
const {
320 if (values_.size() < index + 1) {
322 " array size " << values_.size());
327 return ( (values_.at(index) == NULL) && (lengths_.at(index) == 0) );
331 PgSqlExchange::convertToDatabaseTime(
const time_t input_time) {
335 localtime_r(&input_time, &tinfo);
339 strftime(buffer,
sizeof(buffer),
"%Y-%m-%d %H:%M:%S", &tinfo);
340 return (std::string(buffer));
344 PgSqlExchange::convertLocalToDatabaseTime(
const time_t input_time) {
349 gmtime_r(&input_time, &tinfo);
353 strftime(buffer,
sizeof(buffer),
"%Y-%m-%d %H:%M:%S", &tinfo);
354 return (std::string(buffer));
359 PgSqlExchange::convertToDatabaseTime(
const time_t cltt,
360 const uint32_t valid_lifetime) {
363 int64_t expire_time_64 =
static_cast<int64_t
>(cltt)
364 + static_cast<int64_t>(valid_lifetime);
371 if (expire_time_64 > DatabaseConnection::MAX_DB_TIME) {
375 return (convertToDatabaseTime(static_cast<time_t>(expire_time_64)));
379 PgSqlExchange::convertFromDatabaseTime(
const std::string& db_time_val) {
383 new_time = (boost::lexical_cast<time_t>(db_time_val));
384 }
catch (
const std::exception& ex) {
392 PgSqlExchange::convertFromDatabaseTime(
const std::string& db_time_val,
393 boost::posix_time::ptime& conv_time) {
394 time_t tmp_time = convertFromDatabaseTime(db_time_val);
395 conv_time = boost::posix_time::from_time_t(tmp_time);
399 PgSqlExchange::getRawColumnValue(
const PgSqlResult& r,
const int row,
402 const char* value = PQgetvalue(r, row, col);
405 << getColumnLabel(r, col) <<
" row:" << row);
414 return (PQgetisnull(r, row, col));
418 PgSqlExchange::getColumnValue(
const PgSqlResult& r,
const int row,
419 const size_t col, std::string& value) {
420 value = getRawColumnValue(r, row, col);
424 PgSqlExchange::getColumnValue(
const PgSqlResult& r,
const int row,
425 const size_t col,
bool &value) {
426 const char* data = getRawColumnValue(r, row, col);
427 if (!strlen(data) || *data ==
'f') {
429 }
else if (*data ==
't') {
433 <<
" for: " << getColumnLabel(r, col) <<
" row:" << row
434 <<
" : must be 't' or 'f'");
439 PgSqlExchange::getColumnValue(
const PgSqlResult& r,
const int row,
440 const size_t col, uint8_t &value) {
441 const char* data = getRawColumnValue(r, row, col);
445 value = boost::lexical_cast<uint16_t>(data);
446 }
catch (
const std::exception& ex) {
448 <<
" for: " << getColumnLabel(r, col) <<
" row:" << row
449 <<
" : " << ex.
what());
454 PgSqlExchange::getColumnValue(
const PgSqlResult& r,
const int row,
455 const size_t col, boost::posix_time::ptime& value) {
456 std::string db_time_val;
457 PgSqlExchange::getColumnValue(r, row, col, db_time_val );
458 PgSqlExchange::convertFromDatabaseTime(db_time_val, value);
462 PgSqlExchange::getColumnValue(
const PgSqlResult& r,
const int row,
464 const char* data = getRawColumnValue(r, row, col);
466 value = Element::fromJSON(data);
467 }
catch (
const std::exception& ex) {
469 <<
" for: " << getColumnLabel(r, col) <<
" row:" << row
470 <<
" : " << ex.
what());
477 const char* data = getRawColumnValue(r, row, col);
485 }
catch (
const std::exception& ex) {
487 <<
" for: " << getColumnLabel(r, col) <<
" row:" << row
488 <<
" : " << ex.
what());
495 const char* data = getRawColumnValue(r, row, col);
503 }
catch (
const std::exception& ex) {
505 <<
" for: " << getColumnLabel(r, col) <<
" row:" << row
506 <<
" : " << ex.
what());
513 const char* data = getRawColumnValue(r, row, col);
516 }
catch (
const std::exception& ex) {
518 <<
" for: " << getColumnLabel(r, col) <<
" row:" << row
519 <<
" : " << ex.
what());
524 PgSqlExchange::convertFromBytea(
const PgSqlResult& r,
const int row,
525 const size_t col, uint8_t* buffer,
526 const size_t buffer_size,
527 size_t &bytes_converted) {
530 unsigned char* bytes = PQunescapeBytea((
const unsigned char*)
531 (getRawColumnValue(r, row, col)),
537 << getColumnLabel(r, col) <<
" row:" << row);
541 if (bytes_converted > buffer_size) {
545 << bytes_converted <<
" is too large for: " 546 << getColumnLabel(r, col) <<
" row:" << row);
551 memcpy(buffer, bytes, bytes_converted);
556 PgSqlExchange::convertFromBytea(
const PgSqlResult& r,
const int row,
const size_t col,
557 std::vector<uint8_t>& value) {
560 size_t bytes_converted = 0;
561 unsigned char* bytes = PQunescapeBytea((
const unsigned char*)
562 (getRawColumnValue(r, row, col)),
568 << getColumnLabel(r, col) <<
" row:" << row);
573 if (bytes_converted) {
574 value.assign(bytes, bytes + bytes_converted);
584 PgSqlExchange::getTripletValue(
const PgSqlResult& r,
const int row,
587 if (isColumnNull(r, row, col)) {
591 getColumnValue(r, row, col, col_value);
596 PgSqlExchange::getTripletValue(
const PgSqlResult& r,
const int row,
597 const size_t def_col,
const size_t min_col,
598 const size_t max_col) {
599 if (isColumnNull(r, row, def_col)) {
604 getColumnValue(r, row, def_col, value);
606 uint32_t min_value = value;
607 if (!isColumnNull(r, row, min_col)) {
608 getColumnValue(r, row, min_col, min_value);
611 uint32_t max_value = value;
612 if (!isColumnNull(r, row, max_col)) {
613 getColumnValue(r, row, max_col, max_value);
620 PgSqlExchange::getColumnLabel(
const PgSqlResult& r,
const size_t column) {
627 std::ostringstream stream;
629 for (
int col = 0; col < columns; ++col) {
630 const char* val = getRawColumnValue(r, row, col);
632 int format = PQfformat(r, col);
634 stream << col <<
" " << name <<
" : " ;
635 if (format == PsqlBindArray::TEXT_FMT) {
636 stream <<
"\"" << val <<
"\"" << std::endl;
638 const char *data = val;
639 int length = PQfsize(r, col);
641 stream <<
"empty" << std::endl;
644 for (
int i = 0; i < length; ++i) {
645 stream << std::setfill(
'0') << std::setw(2)
647 <<
static_cast<unsigned int>(data[i]);
654 return (stream.str());
657 PgSqlResultRowWorker::PgSqlResultRowWorker(
const PgSqlResult& r,
const int row)
730 boost::posix_time::ptime
732 boost::posix_time::ptime value;
751 const size_t max_col) {
RAII wrapper for PostgreSQL Result sets.
void unspecified(bool unspecified)
Modifies the flag that indicates whether the value is specified or unspecified.
isc::asiolink::IOAddress getInet4(const size_t col)
Fetches the v4 IP address at the given column.
static isc::asiolink::IOAddress getInetValue4(const PgSqlResult &r, const int row, const size_t col)
Converts a column in a row in a result set into IPv4 address.
std::string getString(const size_t col)
Fetches the column value as a string.
uint16_t getSmallInt(const size_t col)
Fetches the uint16_t value at the given column.
uint32_t getInt(const size_t col)
Fetches the uint32_t value at the given column.
boost::posix_time::ptime getTimestamp(const size_t col)
Fetches a timestamp column as a ptime.
T getMin() const
Returns a minimum allowed value.
static std::string dumpRow(const PgSqlResult &r, int row)
Diagnostic tool which dumps the Result row contents as a string.
isc::util::Triplet< uint32_t > getTriplet(const size_t col)
Fetches a uint32_t value into a Triplet using a single column value.
boost::shared_ptr< Element > ElementPtr
void rowCheck(int row) const
Determines if a row index is valid.
std::string getColumnLabel(const int col) const
Fetches the name of the column in a result set.
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
uint64_t getBigInt(const size_t col)
Fetches the uint64_t value at the given column.
T getMax() const
Returns a maximum allowed value.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
std::string dumpRow()
Diagnostic tool which dumps the Result row contents as a string.
bool getBool(const size_t col)
Fetches the boolean value at the given column.
uint32_t toUint32() const
Converts IPv4 address to uint32_t.
T get(T hint) const
Returns value with a hint.
boost::shared_ptr< const Element > ConstElementPtr
void getBytes(const size_t col, std::vector< uint8_t > &value)
Fetches binary data at the given column into a vector.
static void getColumnValue(const PgSqlResult &r, const int row, const size_t col, std::string &value)
Fetches text column value as a string.
static bool isColumnNull(const PgSqlResult &r, const int row, const size_t col)
Returns true if a column within a row is null.
bool isV6() const
Convenience function to check for an IPv6 address.
bool isV4() const
Convenience function to check for an IPv4 address.
static void convertFromBytea(const PgSqlResult &r, const int row, const size_t col, uint8_t *buffer, const size_t buffer_size, size_t &bytes_converted)
Converts a column in a row in a result set to a binary bytes.
data::ElementPtr getJSON(const size_t col)
Fetches a JSON column as an ElementPtr.
boost::shared_ptr< const std::string > ConstStringPtr
Structure used to bind C++ input values to dynamic SQL parameters The structure contains three vector...
Defines the logger used by the top-level component of kea-lfc.
bool isColumnNull(const size_t col)
Indicates whether or not the given column value is null.
std::string toText() const
Convert the address to a string.
const char * getRawColumnValue(const size_t col)
Gets a pointer to the raw column value in a result set row.
void rowColCheck(int row, int col) const
Determines if both a row and column index are valid.
static isc::asiolink::IOAddress getInetValue6(const PgSqlResult &r, const int row, const size_t col)
Converts a column in a row in a result set into IPv6 address.
int getCols() const
Returns the number of columns in the result set.
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
The IOAddress class represents an IP addresses (version agnostic)
static const char * getRawColumnValue(const PgSqlResult &r, const int row, const size_t col)
Gets a pointer to the raw column value in a result set row.
double getDouble(const size_t col)
Fetches the floating point value at the given column.
static isc::util::Triplet< uint32_t > getTripletValue(const PgSqlResult &r, const int row, const size_t col)
Fetches a uint32_t value into a Triplet using a single column value.
isc::asiolink::IOAddress getInet6(const size_t col)
Fetches the v6 IP address at the given column.
Exception thrown on failure to execute a database function.
std::string format(const std::string &format, const std::vector< std::string > &args)
Apply Formatting.
void getColumnValue(const size_t col, T &value)
Fetches a text column as the given value type.