Kea  2.1.7-git
pgsql_exchange.cc
Go to the documentation of this file.
1 // Copyright (C) 2016-2022 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #include <config.h>
8 
9 #include <pgsql/pgsql_exchange.h>
10 #include <exceptions/exceptions.h>
11 
12 #include <boost/date_time/posix_time/posix_time.hpp>
13 #include <boost/lexical_cast.hpp>
14 
15 #include <iomanip>
16 #include <sstream>
17 #include <vector>
18 
19 using namespace isc::util;
20 using namespace isc::data;
21 using namespace boost::posix_time;
22 
23 namespace isc {
24 namespace db {
25 
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";
30 
31 void PsqlBindArray::add(const char* value) {
32  if (!value) {
33  isc_throw(BadValue, "PsqlBindArray::add - char* value cannot be NULL");
34  }
35 
36  values_.push_back(value);
37  lengths_.push_back(strlen(value));
38  formats_.push_back(TEXT_FMT);
39 }
40 
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);
45 }
46 
47 void PsqlBindArray::insert(const char* value, size_t index) {
48  if (index && index >= values_.size()) {
49  isc_throw(OutOfRange, "PsqlBindArray::insert - index: " << index
50  << ", is larger than the array size: " << values_.size());
51  }
52 
53  values_.insert(values_.begin() + index, value);
54  lengths_.insert(lengths_.begin() + index, strlen(value));
55  formats_.insert(formats_.begin() + index, TEXT_FMT);
56 }
57 
58 void PsqlBindArray::insert(const std::string& value, size_t index) {
59  if (index && index >= values_.size()) {
60  isc_throw(OutOfRange, "PsqlBindArray::insert - index: " << index
61  << ", is larger than the array size: " << values_.size());
62  }
63 
64  bound_strs_.push_back(ConstStringPtr(new std::string(value)));
65 
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);
69 }
70 
71 void PsqlBindArray::popBack() {
72  if (values_.size() == 0) {
73  isc_throw(OutOfRange, "PsqlBindArray::pop_back - array empty");
74  }
75 
76  values_.erase(values_.end() - 1);
77  lengths_.erase(lengths_.end() - 1);
78  formats_.erase(formats_.end() - 1);
79 }
80 
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);
85 }
86 
87 void PsqlBindArray::addTempBinary(const std::vector<uint8_t>& data) {
88  bound_strs_.push_back(ConstStringPtr(new std::string(
89  reinterpret_cast<const char*>(data.data()), data.size())));
90 
91  values_.push_back(reinterpret_cast<const char*>(bound_strs_.back()->data()));
92  lengths_.push_back(data.size());
93  formats_.push_back(BINARY_FMT);
94 }
95 
96 void PsqlBindArray::add(const uint8_t* data, const size_t len) {
97  if (!data) {
98  isc_throw(BadValue, "PsqlBindArray::add - uint8_t data cannot be NULL");
99  }
100 
101  values_.push_back(reinterpret_cast<const char*>(&(data[0])));
102  lengths_.push_back(len);
103  formats_.push_back(BINARY_FMT);
104 }
105 
106 void PsqlBindArray::addTempBuffer(const uint8_t* data, const size_t len) {
107  if (!data) {
108  isc_throw(BadValue, "PsqlBindArray::addTempBuffer - uint8_t data cannot be NULL");
109  }
110 
111  bound_strs_.push_back(ConstStringPtr(new std::string(
112  reinterpret_cast<const char*>(data), len)));
113 
114  values_.push_back(bound_strs_.back()->data());
115  lengths_.push_back(len);
116  formats_.push_back(BINARY_FMT);
117 }
118 
119 void PsqlBindArray::add(const bool& value) {
120  add(value ? TRUE_STR : FALSE_STR);
121 }
122 
123 void PsqlBindArray::add(const uint8_t& byte) {
124  // We static_cast to an unsigned int, otherwise lexical_cast may to
125  // treat byte as a character, which yields "" for unprintable values
126  addTempString(boost::lexical_cast<std::string>
127  (static_cast<unsigned int>(byte)));
128 }
129 
130 void PsqlBindArray::add(const isc::asiolink::IOAddress& addr) {
131  if (addr.isV4()) {
132  addTempString(boost::lexical_cast<std::string>
133  (addr.toUint32()));
134  } else {
135  addTempString(addr.toText());
136  }
137 }
138 
139 void PsqlBindArray::addNull(const int format) {
140  values_.push_back(NULL);
141  lengths_.push_back(0);
142  formats_.push_back(format);
143 }
144 
145 void
146 PsqlBindArray::add(const Triplet<uint32_t>& triplet) {
147  if (triplet.unspecified()) {
148  addNull();
149  } else {
150  add<uint32_t>(triplet.get());
151  }
152 }
153 
154 void
155 PsqlBindArray::addMin(const Triplet<uint32_t>& triplet) {
156  if (triplet.unspecified() || (triplet.getMin() == triplet.get())) {
157  addNull();
158  } else {
159  add<uint32_t>(triplet.getMin());
160  }
161 }
162 
163 void
164 PsqlBindArray::addMax(const Triplet<uint32_t>& triplet) {
165  if (triplet.unspecified() || (triplet.getMax() == triplet.get())) {
166  addNull();
167  } else {
168  add<uint32_t>(triplet.getMax());
169  }
170 }
171 
177 void PsqlBindArray::addTempString(const std::string& str) {
178  bound_strs_.push_back(ConstStringPtr(new std::string(str)));
179 
180  PsqlBindArray::add((bound_strs_.back())->c_str());
181 }
182 
183 void
184 PsqlBindArray::addOptional(const util::Optional<std::string>& value) {
185  if (value.unspecified()) {
186  addNull();
187  } else {
188  addTempString(value);
189  }
190 }
191 
192 void
193 PsqlBindArray::addInet4(const isc::asiolink::IOAddress& value) {
194  if (!value.isV4()) {
195  isc_throw(BadValue, "unable to add address to PsqlBindAray '"
196  << value.toText() << "' is not an IPv4 address");
197  }
198 
199  // inet columns are inserted as string addresses.
200  addTempString(value.toText());
201 }
202 
203 void
204 PsqlBindArray::addOptionalInet4(const util::Optional<isc::asiolink::IOAddress>& value) {
205  // If the value is unspecified it doesn't matter what the value is.
206  if (value.unspecified()) {
207  addNull();
208  } else {
209  addInet4(value);
210  }
211 }
212 
213 void
214 PsqlBindArray::addInet6(const isc::asiolink::IOAddress& value) {
215  if (!value.isV6()) {
216  isc_throw(BadValue, "unable to add address to PsqlBindAray '"
217  << value.toText() << "' is not an IPv6 address");
218  }
219 
220  // inet columns are inserted as string addresses.
221  addTempString(value.toText());
222 }
223 
224 void
225 PsqlBindArray::addOptionalInet6(const util::Optional<isc::asiolink::IOAddress>& value) {
226  // If the value is unspecified it doesn't matter what the value is.
227  if (value.unspecified()) {
228  addNull();
229  } else {
230  addInet6(value);
231  }
232 }
233 
234 void
235 PsqlBindArray::addTimestamp(const boost::posix_time::ptime& timestamp) {
236  // Convert the ptime to time_t, then use the existing conversion
237  // function to make db time.
238  //
239  // Sadly boost::posix_time::to_time_t() was not added until 1.58,
240  // so do it ourselves.
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);
244 
245  if (input_time > DatabaseConnection::MAX_DB_TIME) {
246  isc_throw(isc::BadValue, "Time value is too large: " << input_time);
247  }
248 
249  // Converts to timestamp to local date/time string.
250  addTempString(PgSqlExchange::convertLocalToDatabaseTime(input_time));
251 }
252 
253 void
254 PsqlBindArray::addTimestamp() {
255  time_t now;
256  time(&now);
257  addTempString(PgSqlExchange::convertLocalToDatabaseTime(now));
258 }
259 
260 void
261 PsqlBindArray::add(const ElementPtr& value) {
262  if (!value) {
263  addNull();
264  return;
265  }
266 
267  std::ostringstream ss;
268  value->toJSON(ss);
269  addTempString(ss.str());
270 }
271 
272 void
273 PsqlBindArray::add(const ConstElementPtr& value) {
274  if (!value) {
275  addNull();
276  return;
277  }
278 
279  std::ostringstream ss;
280  value->toJSON(ss);
281  addTempString(ss.str());
282 }
283 
284 std::string
285 PsqlBindArray::toText() const {
286  std::ostringstream stream;
287 
288  if (values_.size() == 0) {
289  return ("bindarray is empty");
290  }
291 
292  for (int i = 0; i < values_.size(); ++i) {
293  stream << i << " : ";
294 
295  if (lengths_[i] == 0) {
296  stream << "empty" << std::endl;
297  continue;
298  }
299 
300  if (formats_[i] == TEXT_FMT) {
301  stream << "\"" << values_[i] << "\"" << std::endl;
302  } else {
303  const char *data = values_[i];
304  stream << "0x";
305  for (int x = 0; x < lengths_[i]; ++x) {
306  stream << std::setfill('0') << std::setw(2)
307  << std::setbase(16)
308  << static_cast<unsigned int>(data[x]);
309  }
310 
311  stream << std::endl << std::setbase(10);
312  }
313  }
314 
315  return (stream.str());
316 }
317 
318 bool
319 PsqlBindArray::amNull(size_t index) const {
320  if (values_.size() < index + 1) {
321  isc_throw(OutOfRange, "The index " << index << " is larger than the "
322  " array size " << values_.size());
323  }
324 
325  // We assume lengths_.size() always equals values_.size(). If not, the
326  // at() operator will throw.
327  return ( (values_.at(index) == NULL) && (lengths_.at(index) == 0) );
328 }
329 
330 std::string
331 PgSqlExchange::convertToDatabaseTime(const time_t input_time) {
332  struct tm tinfo;
333  char buffer[20];
334 
335  localtime_r(&input_time, &tinfo);
336 
337  // PostgreSQL will assume the value is already in local time since we
338  // do not specify timezone in the string.
339  strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tinfo);
340  return (std::string(buffer));
341 }
342 
343 std::string
344 PgSqlExchange::convertLocalToDatabaseTime(const time_t input_time) {
345  struct tm tinfo;
346  char buffer[20];
347 
348  // We use gmtime_r to avoid adjustment as time_t is already local.
349  gmtime_r(&input_time, &tinfo);
350 
351  // PostgreSQL will assume the value is already in local time since we
352  // do not specify timezone in the string.
353  strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tinfo);
354  return (std::string(buffer));
355 }
356 
357 
358 std::string
359 PgSqlExchange::convertToDatabaseTime(const time_t cltt,
360  const uint32_t valid_lifetime) {
361  // Calculate expiry time. Store it in the 64-bit value so as we can
362  // detect overflows.
363  int64_t expire_time_64 = static_cast<int64_t>(cltt)
364  + static_cast<int64_t>(valid_lifetime);
365 
366  // It has been observed that the PostgreSQL doesn't deal well with the
367  // timestamp values beyond the DataSource::MAX_DB_TIME seconds since the
368  // beginning of the epoch (around year 2038). The value is often
369  // stored in the database but it is invalid when read back (overflow?).
370  // Hence, the maximum timestamp value is restricted here.
371  if (expire_time_64 > DatabaseConnection::MAX_DB_TIME) {
372  isc_throw(isc::BadValue, "Time value is too large: " << expire_time_64);
373  }
374 
375  return (convertToDatabaseTime(static_cast<time_t>(expire_time_64)));
376 }
377 
378 time_t
379 PgSqlExchange::convertFromDatabaseTime(const std::string& db_time_val) {
380  // Convert string time value to time_t
381  time_t new_time;
382  try {
383  new_time = (boost::lexical_cast<time_t>(db_time_val));
384  } catch (const std::exception& ex) {
385  isc_throw(BadValue, "Database time value is invalid: " << db_time_val);
386  }
387 
388  return (new_time);
389 }
390 
391 void
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);
396 }
397 
398 const char*
399 PgSqlExchange::getRawColumnValue(const PgSqlResult& r, const int row,
400  const size_t col) {
401  r.rowColCheck(row,col);
402  const char* value = PQgetvalue(r, row, col);
403  if (!value) {
404  isc_throw(DbOperationError, "getRawColumnValue no data for :"
405  << getColumnLabel(r, col) << " row:" << row);
406  }
407  return (value);
408 }
409 
410 bool
411 PgSqlExchange::isColumnNull(const PgSqlResult& r, const int row,
412  const size_t col) {
413  r.rowColCheck(row,col);
414  return (PQgetisnull(r, row, col));
415 }
416 
417 void
418 PgSqlExchange::getColumnValue(const PgSqlResult& r, const int row,
419  const size_t col, std::string& value) {
420  value = getRawColumnValue(r, row, col);
421 }
422 
423 void
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') {
428  value = false;
429  } else if (*data == 't') {
430  value = true;
431  } else {
432  isc_throw(DbOperationError, "Invalid boolean data: " << data
433  << " for: " << getColumnLabel(r, col) << " row:" << row
434  << " : must be 't' or 'f'");
435  }
436 }
437 
438 void
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);
442  try {
443  // lexically casting as uint8_t doesn't convert from char
444  // so we use uint16_t and implicitly convert.
445  value = boost::lexical_cast<uint16_t>(data);
446  } catch (const std::exception& ex) {
447  isc_throw(DbOperationError, "Invalid uint8_t data: " << data
448  << " for: " << getColumnLabel(r, col) << " row:" << row
449  << " : " << ex.what());
450  }
451 }
452 
453 void
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);
459 }
460 
461 void
462 PgSqlExchange::getColumnValue(const PgSqlResult& r, const int row,
463  const size_t col, ElementPtr& value) {
464  const char* data = getRawColumnValue(r, row, col);
465  try {
466  value = Element::fromJSON(data);
467  } catch (const std::exception& ex) {
468  isc_throw(DbOperationError, "Cannot convert data: " << data
469  << " for: " << getColumnLabel(r, col) << " row:" << row
470  << " : " << ex.what());
471  }
472 }
473 
475 PgSqlExchange::getInetValue4(const PgSqlResult& r, const int row,
476  const size_t col) {
477  const char* data = getRawColumnValue(r, row, col);
478  try {
479  asiolink::IOAddress addr(data);
480  if (!addr.isV4()) {
481  isc_throw(BadValue, "not a v4 address");
482  }
483 
484  return (addr);
485  } catch (const std::exception& ex) {
486  isc_throw(DbOperationError, "Cannot convert data: " << data
487  << " for: " << getColumnLabel(r, col) << " row:" << row
488  << " : " << ex.what());
489  }
490 }
491 
493 PgSqlExchange::getInetValue6(const PgSqlResult& r, const int row,
494  const size_t col) {
495  const char* data = getRawColumnValue(r, row, col);
496  try {
497  asiolink::IOAddress addr(data);
498  if (!addr.isV6()) {
499  isc_throw(BadValue, "not a v6 address");
500  }
501 
502  return (addr);
503  } catch (const std::exception& ex) {
504  isc_throw(DbOperationError, "Cannot convert data: " << data
505  << " for: " << getColumnLabel(r, col) << " row:" << row
506  << " : " << ex.what());
507  }
508 }
509 
511 PgSqlExchange::getIPv6Value(const PgSqlResult& r, const int row,
512  const size_t col) {
513  const char* data = getRawColumnValue(r, row, col);
514  try {
515  return (isc::asiolink::IOAddress(data));
516  } catch (const std::exception& ex) {
517  isc_throw(DbOperationError, "Cannot convert data: " << data
518  << " for: " << getColumnLabel(r, col) << " row:" << row
519  << " : " << ex.what());
520  }
521 }
522 
523 void
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) {
528  // Returns converted bytes in a dynamically allocated buffer, and
529  // sets bytes_converted.
530  unsigned char* bytes = PQunescapeBytea((const unsigned char*)
531  (getRawColumnValue(r, row, col)),
532  &bytes_converted);
533 
534  // Unlikely it couldn't allocate it but you never know.
535  if (!bytes) {
536  isc_throw (DbOperationError, "PQunescapeBytea failed for:"
537  << getColumnLabel(r, col) << " row:" << row);
538  }
539 
540  // Make sure it's not larger than expected.
541  if (bytes_converted > buffer_size) {
542  // Free the allocated buffer first!
543  PQfreemem(bytes);
544  isc_throw (DbOperationError, "Converted data size: "
545  << bytes_converted << " is too large for: "
546  << getColumnLabel(r, col) << " row:" << row);
547  }
548 
549  // Copy from the allocated buffer to caller's buffer then free
550  // the allocated buffer.
551  memcpy(buffer, bytes, bytes_converted);
552  PQfreemem(bytes);
553 }
554 
555 void
556 PgSqlExchange::convertFromBytea(const PgSqlResult& r, const int row, const size_t col,
557  std::vector<uint8_t>& value) {
558  // Returns converted bytes in a dynamically allocated buffer, and
559  // sets bytes_converted.
560  size_t bytes_converted = 0;
561  unsigned char* bytes = PQunescapeBytea((const unsigned char*)
562  (getRawColumnValue(r, row, col)),
563  &bytes_converted);
564 
565  // Unlikely it couldn't allocate it but you never know.
566  if (!bytes) {
567  isc_throw (DbOperationError, "PQunescapeBytea failed for:"
568  << getColumnLabel(r, col) << " row:" << row);
569  }
570 
571  // Copy from the allocated buffer to caller's buffer then free
572  // the allocated buffer.
573  if (bytes_converted) {
574  value.assign(bytes, bytes + bytes_converted);
575  } else {
576  value.clear();
577  }
578 
579  // Free the PostgreSQL buffer.
580  PQfreemem(bytes);
581 }
582 
584 PgSqlExchange::getTripletValue(const PgSqlResult& r, const int row,
585  const size_t col) {
586  uint32_t col_value;
587  if (isColumnNull(r, row, col)) {
588  return (Triplet<uint32_t>());
589  }
590 
591  getColumnValue(r, row, col, col_value);
592  return (Triplet<uint32_t>(col_value));
593 }
594 
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)) {
600  return (Triplet<uint32_t>());
601  }
602 
603  uint32_t value;
604  getColumnValue(r, row, def_col, value);
605 
606  uint32_t min_value = value;
607  if (!isColumnNull(r, row, min_col)) {
608  getColumnValue(r, row, min_col, min_value);
609  }
610 
611  uint32_t max_value = value;
612  if (!isColumnNull(r, row, max_col)) {
613  getColumnValue(r, row, max_col, max_value);
614  }
615 
616  return (Triplet<uint32_t>(min_value, value, max_value));
617 }
618 
619 std::string
620 PgSqlExchange::getColumnLabel(const PgSqlResult& r, const size_t column) {
621  return (r.getColumnLabel(column));
622 }
623 
624 std::string
625 PgSqlExchange::dumpRow(const PgSqlResult& r, int row) {
626  r.rowCheck(row);
627  std::ostringstream stream;
628  int columns = r.getCols();
629  for (int col = 0; col < columns; ++col) {
630  const char* val = getRawColumnValue(r, row, col);
631  std::string name = r.getColumnLabel(col);
632  int format = PQfformat(r, col);
633 
634  stream << col << " " << name << " : " ;
635  if (format == PsqlBindArray::TEXT_FMT) {
636  stream << "\"" << val << "\"" << std::endl;
637  } else {
638  const char *data = val;
639  int length = PQfsize(r, col);
640  if (length == 0) {
641  stream << "empty" << std::endl;
642  } else {
643  stream << "0x";
644  for (int i = 0; i < length; ++i) {
645  stream << std::setfill('0') << std::setw(2)
646  << std::setbase(16)
647  << static_cast<unsigned int>(data[i]);
648  }
649  stream << std::endl;
650  }
651  }
652  }
653 
654  return (stream.str());
655 }
656 
657 PgSqlResultRowWorker::PgSqlResultRowWorker(const PgSqlResult& r, const int row)
658  : r_(r), row_(row) {
659  // Validate the desired row.
660  r.rowCheck(row);
661 }
662 
663 bool
665  return (PgSqlExchange::isColumnNull(r_, row_, col));
666 }
667 
668 std::string
670  std::string tmp;
671  PgSqlExchange::getColumnValue(r_, row_, col, tmp);
672  return (tmp);
673 }
674 
675 bool
676 PgSqlResultRowWorker::getBool(const size_t col) {
677  bool tmp;
678  PgSqlExchange::getColumnValue(r_, row_, col, tmp);
679  return (tmp);
680 }
681 
682 double
684  double tmp;
685  PgSqlExchange::getColumnValue(r_, row_, col, tmp);
686  return (tmp);
687 }
688 
689 const char*
691  return (PgSqlExchange::getRawColumnValue(r_, row_, col));
692 }
693 
694 uint64_t
696  uint64_t value;
697  PgSqlExchange::getColumnValue(r_, row_, col, value);
698  return (value);
699 }
700 
701 uint32_t
702 PgSqlResultRowWorker::getInt(const size_t col) {
703  uint32_t value;
704  PgSqlExchange::getColumnValue(r_, row_, col, value);
705  return (value);
706 }
707 
708 uint16_t
710  uint16_t value;
711  PgSqlExchange::getColumnValue(r_, row_, col, value);
712  return (value);
713 }
714 
715 void
716 PgSqlResultRowWorker::getBytes(const size_t col, std::vector<uint8_t>& value) {
717  PgSqlExchange::convertFromBytea(r_, row_, col, value);
718 }
719 
722  return (PgSqlExchange::getInetValue4(r_, row_, col));
723 }
724 
727  return (PgSqlExchange::getInetValue6(r_, row_, col));
728 }
729 
730 boost::posix_time::ptime
732  boost::posix_time::ptime value;
733  getColumnValue(col, value);
734  return (value);
735 };
736 
738 PgSqlResultRowWorker::getJSON(const size_t col) {
739  data::ElementPtr value;
740  getColumnValue(col, value);
741  return (value);
742 }
743 
746  return (PgSqlExchange::getTripletValue(r_, row_, col));
747 }
748 
750 PgSqlResultRowWorker::getTriplet(const size_t def_col, const size_t min_col,
751  const size_t max_col) {
752  return (PgSqlExchange::getTripletValue(r_, row_, def_col, min_col, max_col));
753 }
754 
755 std::string
757  return (PgSqlExchange::dumpRow(r_, row_));
758 }
759 
760 } // end of isc::db namespace
761 } // end of isc namespace
RAII wrapper for PostgreSQL Result sets.
void unspecified(bool unspecified)
Modifies the flag that indicates whether the value is specified or unspecified.
Definition: optional.h:136
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.
Definition: triplet.h:85
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
Definition: data.h:24
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.
Definition: triplet.h:112
#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.
Definition: edns.h:19
bool getBool(const size_t col)
Fetches the boolean value at the given column.
T get(T hint) const
Returns value with a hint.
Definition: triplet.h:99
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:27
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.
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.
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...
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.
Definition: strutil.cc:157
void getColumnValue(const size_t col, T &value)
Fetches a text column as the given value type.