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 if (timestamp < epoch) {
245 ptime max_db_time = boost::posix_time::from_time_t(DatabaseConnection::MAX_DB_TIME);
246 time_duration::sec_type since_epoch = (timestamp - epoch).total_seconds();
247 time_t input_time(since_epoch);
248 if (timestamp > max_db_time) {
251 static_cast<int64_t>(static_cast<uint32_t>(input_time)) :
256 addTempString(PgSqlExchange::convertLocalToDatabaseTime(input_time));
260 PsqlBindArray::addTimestamp() {
263 addTempString(PgSqlExchange::convertLocalToDatabaseTime(now));
273 std::ostringstream ss;
275 addTempString(ss.str());
285 std::ostringstream ss;
287 addTempString(ss.str());
291 PsqlBindArray::toText()
const {
292 std::ostringstream stream;
294 if (values_.size() == 0) {
295 return (
"bindarray is empty");
298 for (
int i = 0; i < values_.size(); ++i) {
299 stream << i <<
" : ";
301 if (lengths_[i] == 0) {
302 stream <<
"empty" << std::endl;
306 if (formats_[i] == TEXT_FMT) {
307 stream <<
"\"" << values_[i] <<
"\"" << std::endl;
309 const char *data = values_[i];
311 for (
int x = 0; x < lengths_[i]; ++x) {
312 stream << std::setfill(
'0') << std::setw(2)
314 <<
static_cast<unsigned int>(data[x]);
317 stream << std::endl << std::setbase(10);
321 return (stream.str());
325 PsqlBindArray::amNull(
size_t index)
const {
326 if (values_.size() < index + 1) {
328 " array size " << values_.size());
333 return ( (values_.at(index) == NULL) && (lengths_.at(index) == 0) );
337 PgSqlExchange::convertToDatabaseTime(
const time_t input_time) {
341 localtime_r(&input_time, &tinfo);
345 strftime(buffer,
sizeof(buffer),
"%Y-%m-%d %H:%M:%S", &tinfo);
346 return (std::string(buffer));
350 PgSqlExchange::convertLocalToDatabaseTime(
const time_t input_time) {
355 gmtime_r(&input_time, &tinfo);
359 strftime(buffer,
sizeof(buffer),
"%Y-%m-%d %H:%M:%S", &tinfo);
360 return (std::string(buffer));
365 PgSqlExchange::convertToDatabaseTime(
const time_t cltt,
366 const uint32_t valid_lifetime) {
369 int64_t expire_time_64 =
static_cast<int64_t
>(cltt)
370 + static_cast<int64_t>(valid_lifetime);
377 if (expire_time_64 > DatabaseConnection::MAX_DB_TIME) {
381 return (convertToDatabaseTime(static_cast<time_t>(expire_time_64)));
385 PgSqlExchange::convertFromDatabaseTime(
const std::string& db_time_val) {
389 new_time = (boost::lexical_cast<time_t>(db_time_val));
390 }
catch (
const std::exception& ex) {
398 PgSqlExchange::convertFromDatabaseTime(
const std::string& db_time_val,
399 boost::posix_time::ptime& conv_time) {
400 time_t tmp_time = convertFromDatabaseTime(db_time_val);
401 conv_time = boost::posix_time::from_time_t(tmp_time);
405 PgSqlExchange::getRawColumnValue(
const PgSqlResult& r,
const int row,
408 const char* value = PQgetvalue(r, row, col);
411 << getColumnLabel(r, col) <<
" row:" << row);
420 return (PQgetisnull(r, row, col));
424 PgSqlExchange::getColumnValue(
const PgSqlResult& r,
const int row,
425 const size_t col, std::string& value) {
426 value = getRawColumnValue(r, row, col);
430 PgSqlExchange::getColumnValue(
const PgSqlResult& r,
const int row,
431 const size_t col,
bool &value) {
432 const char* data = getRawColumnValue(r, row, col);
433 if (!strlen(data) || *data ==
'f') {
435 }
else if (*data ==
't') {
439 <<
" for: " << getColumnLabel(r, col) <<
" row:" << row
440 <<
" : must be 't' or 'f'");
445 PgSqlExchange::getColumnValue(
const PgSqlResult& r,
const int row,
446 const size_t col, uint8_t &value) {
447 const char* data = getRawColumnValue(r, row, col);
451 value = boost::lexical_cast<uint16_t>(data);
452 }
catch (
const std::exception& ex) {
454 <<
" for: " << getColumnLabel(r, col) <<
" row:" << row
455 <<
" : " << ex.
what());
460 PgSqlExchange::getColumnValue(
const PgSqlResult& r,
const int row,
461 const size_t col, boost::posix_time::ptime& value) {
462 std::string db_time_val;
463 PgSqlExchange::getColumnValue(r, row, col, db_time_val );
464 PgSqlExchange::convertFromDatabaseTime(db_time_val, value);
468 PgSqlExchange::getColumnValue(
const PgSqlResult& r,
const int row,
470 const char* data = getRawColumnValue(r, row, col);
472 value = Element::fromJSON(data);
473 }
catch (
const std::exception& ex) {
475 <<
" for: " << getColumnLabel(r, col) <<
" row:" << row
476 <<
" : " << ex.
what());
483 const char* data = getRawColumnValue(r, row, col);
491 }
catch (
const std::exception& ex) {
493 <<
" for: " << getColumnLabel(r, col) <<
" row:" << row
494 <<
" : " << ex.
what());
501 const char* data = getRawColumnValue(r, row, col);
509 }
catch (
const std::exception& ex) {
511 <<
" for: " << getColumnLabel(r, col) <<
" row:" << row
512 <<
" : " << ex.
what());
519 const char* data = getRawColumnValue(r, row, col);
522 }
catch (
const std::exception& ex) {
524 <<
" for: " << getColumnLabel(r, col) <<
" row:" << row
525 <<
" : " << ex.
what());
530 PgSqlExchange::convertFromBytea(
const PgSqlResult& r,
const int row,
531 const size_t col, uint8_t* buffer,
532 const size_t buffer_size,
533 size_t &bytes_converted) {
536 unsigned char* bytes = PQunescapeBytea((
const unsigned char*)
537 (getRawColumnValue(r, row, col)),
543 << getColumnLabel(r, col) <<
" row:" << row);
547 if (bytes_converted > buffer_size) {
551 << bytes_converted <<
" is too large for: " 552 << getColumnLabel(r, col) <<
" row:" << row);
557 memcpy(buffer, bytes, bytes_converted);
562 PgSqlExchange::convertFromBytea(
const PgSqlResult& r,
const int row,
const size_t col,
563 std::vector<uint8_t>& value) {
566 size_t bytes_converted = 0;
567 unsigned char* bytes = PQunescapeBytea((
const unsigned char*)
568 (getRawColumnValue(r, row, col)),
574 << getColumnLabel(r, col) <<
" row:" << row);
579 if (bytes_converted) {
580 value.assign(bytes, bytes + bytes_converted);
590 PgSqlExchange::getTripletValue(
const PgSqlResult& r,
const int row,
593 if (isColumnNull(r, row, col)) {
597 getColumnValue(r, row, col, col_value);
602 PgSqlExchange::getTripletValue(
const PgSqlResult& r,
const int row,
603 const size_t def_col,
const size_t min_col,
604 const size_t max_col) {
605 if (isColumnNull(r, row, def_col)) {
610 getColumnValue(r, row, def_col, value);
612 uint32_t min_value = value;
613 if (!isColumnNull(r, row, min_col)) {
614 getColumnValue(r, row, min_col, min_value);
617 uint32_t max_value = value;
618 if (!isColumnNull(r, row, max_col)) {
619 getColumnValue(r, row, max_col, max_value);
626 PgSqlExchange::getColumnLabel(
const PgSqlResult& r,
const size_t column) {
633 std::ostringstream stream;
635 for (
int col = 0; col < columns; ++col) {
636 const char* val = getRawColumnValue(r, row, col);
638 int format = PQfformat(r, col);
640 stream << col <<
" " << name <<
" : " ;
641 if (format == PsqlBindArray::TEXT_FMT) {
642 stream <<
"\"" << val <<
"\"" << std::endl;
644 const char *data = val;
645 int length = PQfsize(r, col);
647 stream <<
"empty" << std::endl;
650 for (
int i = 0; i < length; ++i) {
651 stream << std::setfill(
'0') << std::setw(2)
653 <<
static_cast<unsigned int>(data[i]);
660 return (stream.str());
663 PgSqlResultRowWorker::PgSqlResultRowWorker(
const PgSqlResult& r,
const int row)
736 boost::posix_time::ptime
738 boost::posix_time::ptime value;
757 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.