Kea  2.3.5-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  if (timestamp < epoch) {
243  isc_throw(isc::BadValue, "Time value is before the epoch");
244  }
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) {
249  isc_throw(isc::BadValue, "Time value is too large: " <<
250  (input_time < 0 ?
251  static_cast<int64_t>(static_cast<uint32_t>(input_time)) :
252  input_time));
253  }
254 
255  // Converts to timestamp to local date/time string.
256  addTempString(PgSqlExchange::convertLocalToDatabaseTime(input_time));
257 }
258 
259 void
260 PsqlBindArray::addTimestamp() {
261  time_t now;
262  time(&now);
263  addTempString(PgSqlExchange::convertLocalToDatabaseTime(now));
264 }
265 
266 void
267 PsqlBindArray::add(const ElementPtr& value) {
268  if (!value) {
269  addNull();
270  return;
271  }
272 
273  std::ostringstream ss;
274  value->toJSON(ss);
275  addTempString(ss.str());
276 }
277 
278 void
279 PsqlBindArray::add(const ConstElementPtr& value) {
280  if (!value) {
281  addNull();
282  return;
283  }
284 
285  std::ostringstream ss;
286  value->toJSON(ss);
287  addTempString(ss.str());
288 }
289 
290 std::string
291 PsqlBindArray::toText() const {
292  std::ostringstream stream;
293 
294  if (values_.size() == 0) {
295  return ("bindarray is empty");
296  }
297 
298  for (int i = 0; i < values_.size(); ++i) {
299  stream << i << " : ";
300 
301  if (lengths_[i] == 0) {
302  stream << "empty" << std::endl;
303  continue;
304  }
305 
306  if (formats_[i] == TEXT_FMT) {
307  stream << "\"" << values_[i] << "\"" << std::endl;
308  } else {
309  const char *data = values_[i];
310  stream << "0x";
311  for (int x = 0; x < lengths_[i]; ++x) {
312  stream << std::setfill('0') << std::setw(2)
313  << std::setbase(16)
314  << static_cast<unsigned int>(data[x]);
315  }
316 
317  stream << std::endl << std::setbase(10);
318  }
319  }
320 
321  return (stream.str());
322 }
323 
324 bool
325 PsqlBindArray::amNull(size_t index) const {
326  if (values_.size() < index + 1) {
327  isc_throw(OutOfRange, "The index " << index << " is larger than the "
328  " array size " << values_.size());
329  }
330 
331  // We assume lengths_.size() always equals values_.size(). If not, the
332  // at() operator will throw.
333  return ( (values_.at(index) == NULL) && (lengths_.at(index) == 0) );
334 }
335 
336 std::string
337 PgSqlExchange::convertToDatabaseTime(const time_t input_time) {
338  struct tm tinfo;
339  char buffer[20];
340 
341  localtime_r(&input_time, &tinfo);
342 
343  // PostgreSQL will assume the value is already in local time since we
344  // do not specify timezone in the string.
345  strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tinfo);
346  return (std::string(buffer));
347 }
348 
349 std::string
350 PgSqlExchange::convertLocalToDatabaseTime(const time_t input_time) {
351  struct tm tinfo;
352  char buffer[20];
353 
354  // We use gmtime_r to avoid adjustment as time_t is already local.
355  gmtime_r(&input_time, &tinfo);
356 
357  // PostgreSQL will assume the value is already in local time since we
358  // do not specify timezone in the string.
359  strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tinfo);
360  return (std::string(buffer));
361 }
362 
363 
364 std::string
365 PgSqlExchange::convertToDatabaseTime(const time_t cltt,
366  const uint32_t valid_lifetime) {
367  // Calculate expiry time. Store it in the 64-bit value so as we can
368  // detect overflows.
369  int64_t expire_time_64 = static_cast<int64_t>(cltt)
370  + static_cast<int64_t>(valid_lifetime);
371 
372  // It has been observed that the PostgreSQL doesn't deal well with the
373  // timestamp values beyond the DataSource::MAX_DB_TIME seconds since the
374  // beginning of the epoch (around year 2038). The value is often
375  // stored in the database but it is invalid when read back (overflow?).
376  // Hence, the maximum timestamp value is restricted here.
377  if (expire_time_64 > DatabaseConnection::MAX_DB_TIME) {
378  isc_throw(isc::BadValue, "Time value is too large: " << expire_time_64);
379  }
380 
381  return (convertToDatabaseTime(static_cast<time_t>(expire_time_64)));
382 }
383 
384 time_t
385 PgSqlExchange::convertFromDatabaseTime(const std::string& db_time_val) {
386  // Convert string time value to time_t
387  time_t new_time;
388  try {
389  new_time = (boost::lexical_cast<time_t>(db_time_val));
390  } catch (const std::exception& ex) {
391  isc_throw(BadValue, "Database time value is invalid: " << db_time_val);
392  }
393 
394  return (new_time);
395 }
396 
397 void
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);
402 }
403 
404 const char*
405 PgSqlExchange::getRawColumnValue(const PgSqlResult& r, const int row,
406  const size_t col) {
407  r.rowColCheck(row,col);
408  const char* value = PQgetvalue(r, row, col);
409  if (!value) {
410  isc_throw(DbOperationError, "getRawColumnValue no data for :"
411  << getColumnLabel(r, col) << " row:" << row);
412  }
413  return (value);
414 }
415 
416 bool
417 PgSqlExchange::isColumnNull(const PgSqlResult& r, const int row,
418  const size_t col) {
419  r.rowColCheck(row,col);
420  return (PQgetisnull(r, row, col));
421 }
422 
423 void
424 PgSqlExchange::getColumnValue(const PgSqlResult& r, const int row,
425  const size_t col, std::string& value) {
426  value = getRawColumnValue(r, row, col);
427 }
428 
429 void
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') {
434  value = false;
435  } else if (*data == 't') {
436  value = true;
437  } else {
438  isc_throw(DbOperationError, "Invalid boolean data: " << data
439  << " for: " << getColumnLabel(r, col) << " row:" << row
440  << " : must be 't' or 'f'");
441  }
442 }
443 
444 void
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);
448  try {
449  // lexically casting as uint8_t doesn't convert from char
450  // so we use uint16_t and implicitly convert.
451  value = boost::lexical_cast<uint16_t>(data);
452  } catch (const std::exception& ex) {
453  isc_throw(DbOperationError, "Invalid uint8_t data: " << data
454  << " for: " << getColumnLabel(r, col) << " row:" << row
455  << " : " << ex.what());
456  }
457 }
458 
459 void
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);
465 }
466 
467 void
468 PgSqlExchange::getColumnValue(const PgSqlResult& r, const int row,
469  const size_t col, ElementPtr& value) {
470  const char* data = getRawColumnValue(r, row, col);
471  try {
472  value = Element::fromJSON(data);
473  } catch (const std::exception& ex) {
474  isc_throw(DbOperationError, "Cannot convert data: " << data
475  << " for: " << getColumnLabel(r, col) << " row:" << row
476  << " : " << ex.what());
477  }
478 }
479 
481 PgSqlExchange::getInetValue4(const PgSqlResult& r, const int row,
482  const size_t col) {
483  const char* data = getRawColumnValue(r, row, col);
484  try {
485  asiolink::IOAddress addr(data);
486  if (!addr.isV4()) {
487  isc_throw(BadValue, "not a v4 address");
488  }
489 
490  return (addr);
491  } catch (const std::exception& ex) {
492  isc_throw(DbOperationError, "Cannot convert data: " << data
493  << " for: " << getColumnLabel(r, col) << " row:" << row
494  << " : " << ex.what());
495  }
496 }
497 
499 PgSqlExchange::getInetValue6(const PgSqlResult& r, const int row,
500  const size_t col) {
501  const char* data = getRawColumnValue(r, row, col);
502  try {
503  asiolink::IOAddress addr(data);
504  if (!addr.isV6()) {
505  isc_throw(BadValue, "not a v6 address");
506  }
507 
508  return (addr);
509  } catch (const std::exception& ex) {
510  isc_throw(DbOperationError, "Cannot convert data: " << data
511  << " for: " << getColumnLabel(r, col) << " row:" << row
512  << " : " << ex.what());
513  }
514 }
515 
517 PgSqlExchange::getIPv6Value(const PgSqlResult& r, const int row,
518  const size_t col) {
519  const char* data = getRawColumnValue(r, row, col);
520  try {
521  return (isc::asiolink::IOAddress(data));
522  } catch (const std::exception& ex) {
523  isc_throw(DbOperationError, "Cannot convert data: " << data
524  << " for: " << getColumnLabel(r, col) << " row:" << row
525  << " : " << ex.what());
526  }
527 }
528 
529 void
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) {
534  // Returns converted bytes in a dynamically allocated buffer, and
535  // sets bytes_converted.
536  unsigned char* bytes = PQunescapeBytea((const unsigned char*)
537  (getRawColumnValue(r, row, col)),
538  &bytes_converted);
539 
540  // Unlikely it couldn't allocate it but you never know.
541  if (!bytes) {
542  isc_throw (DbOperationError, "PQunescapeBytea failed for:"
543  << getColumnLabel(r, col) << " row:" << row);
544  }
545 
546  // Make sure it's not larger than expected.
547  if (bytes_converted > buffer_size) {
548  // Free the allocated buffer first!
549  PQfreemem(bytes);
550  isc_throw (DbOperationError, "Converted data size: "
551  << bytes_converted << " is too large for: "
552  << getColumnLabel(r, col) << " row:" << row);
553  }
554 
555  // Copy from the allocated buffer to caller's buffer then free
556  // the allocated buffer.
557  memcpy(buffer, bytes, bytes_converted);
558  PQfreemem(bytes);
559 }
560 
561 void
562 PgSqlExchange::convertFromBytea(const PgSqlResult& r, const int row, const size_t col,
563  std::vector<uint8_t>& value) {
564  // Returns converted bytes in a dynamically allocated buffer, and
565  // sets bytes_converted.
566  size_t bytes_converted = 0;
567  unsigned char* bytes = PQunescapeBytea((const unsigned char*)
568  (getRawColumnValue(r, row, col)),
569  &bytes_converted);
570 
571  // Unlikely it couldn't allocate it but you never know.
572  if (!bytes) {
573  isc_throw (DbOperationError, "PQunescapeBytea failed for:"
574  << getColumnLabel(r, col) << " row:" << row);
575  }
576 
577  // Copy from the allocated buffer to caller's buffer then free
578  // the allocated buffer.
579  if (bytes_converted) {
580  value.assign(bytes, bytes + bytes_converted);
581  } else {
582  value.clear();
583  }
584 
585  // Free the PostgreSQL buffer.
586  PQfreemem(bytes);
587 }
588 
590 PgSqlExchange::getTripletValue(const PgSqlResult& r, const int row,
591  const size_t col) {
592  uint32_t col_value;
593  if (isColumnNull(r, row, col)) {
594  return (Triplet<uint32_t>());
595  }
596 
597  getColumnValue(r, row, col, col_value);
598  return (Triplet<uint32_t>(col_value));
599 }
600 
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)) {
606  return (Triplet<uint32_t>());
607  }
608 
609  uint32_t value;
610  getColumnValue(r, row, def_col, value);
611 
612  uint32_t min_value = value;
613  if (!isColumnNull(r, row, min_col)) {
614  getColumnValue(r, row, min_col, min_value);
615  }
616 
617  uint32_t max_value = value;
618  if (!isColumnNull(r, row, max_col)) {
619  getColumnValue(r, row, max_col, max_value);
620  }
621 
622  return (Triplet<uint32_t>(min_value, value, max_value));
623 }
624 
625 std::string
626 PgSqlExchange::getColumnLabel(const PgSqlResult& r, const size_t column) {
627  return (r.getColumnLabel(column));
628 }
629 
630 std::string
631 PgSqlExchange::dumpRow(const PgSqlResult& r, int row) {
632  r.rowCheck(row);
633  std::ostringstream stream;
634  int columns = r.getCols();
635  for (int col = 0; col < columns; ++col) {
636  const char* val = getRawColumnValue(r, row, col);
637  std::string name = r.getColumnLabel(col);
638  int format = PQfformat(r, col);
639 
640  stream << col << " " << name << " : " ;
641  if (format == PsqlBindArray::TEXT_FMT) {
642  stream << "\"" << val << "\"" << std::endl;
643  } else {
644  const char *data = val;
645  int length = PQfsize(r, col);
646  if (length == 0) {
647  stream << "empty" << std::endl;
648  } else {
649  stream << "0x";
650  for (int i = 0; i < length; ++i) {
651  stream << std::setfill('0') << std::setw(2)
652  << std::setbase(16)
653  << static_cast<unsigned int>(data[i]);
654  }
655  stream << std::endl;
656  }
657  }
658  }
659 
660  return (stream.str());
661 }
662 
663 PgSqlResultRowWorker::PgSqlResultRowWorker(const PgSqlResult& r, const int row)
664  : r_(r), row_(row) {
665  // Validate the desired row.
666  r.rowCheck(row);
667 }
668 
669 bool
671  return (PgSqlExchange::isColumnNull(r_, row_, col));
672 }
673 
674 std::string
676  std::string tmp;
677  PgSqlExchange::getColumnValue(r_, row_, col, tmp);
678  return (tmp);
679 }
680 
681 bool
682 PgSqlResultRowWorker::getBool(const size_t col) {
683  bool tmp;
684  PgSqlExchange::getColumnValue(r_, row_, col, tmp);
685  return (tmp);
686 }
687 
688 double
690  double tmp;
691  PgSqlExchange::getColumnValue(r_, row_, col, tmp);
692  return (tmp);
693 }
694 
695 const char*
697  return (PgSqlExchange::getRawColumnValue(r_, row_, col));
698 }
699 
700 uint64_t
702  uint64_t value;
703  PgSqlExchange::getColumnValue(r_, row_, col, value);
704  return (value);
705 }
706 
707 uint32_t
708 PgSqlResultRowWorker::getInt(const size_t col) {
709  uint32_t value;
710  PgSqlExchange::getColumnValue(r_, row_, col, value);
711  return (value);
712 }
713 
714 uint16_t
716  uint16_t value;
717  PgSqlExchange::getColumnValue(r_, row_, col, value);
718  return (value);
719 }
720 
721 void
722 PgSqlResultRowWorker::getBytes(const size_t col, std::vector<uint8_t>& value) {
723  PgSqlExchange::convertFromBytea(r_, row_, col, value);
724 }
725 
728  return (PgSqlExchange::getInetValue4(r_, row_, col));
729 }
730 
733  return (PgSqlExchange::getInetValue6(r_, row_, col));
734 }
735 
736 boost::posix_time::ptime
738  boost::posix_time::ptime value;
739  getColumnValue(col, value);
740  return (value);
741 };
742 
744 PgSqlResultRowWorker::getJSON(const size_t col) {
745  data::ElementPtr value;
746  getColumnValue(col, value);
747  return (value);
748 }
749 
752  return (PgSqlExchange::getTripletValue(r_, row_, col));
753 }
754 
756 PgSqlResultRowWorker::getTriplet(const size_t def_col, const size_t min_col,
757  const size_t max_col) {
758  return (PgSqlExchange::getTripletValue(r_, row_, def_col, min_col, max_col));
759 }
760 
761 std::string
763  return (PgSqlExchange::dumpRow(r_, row_));
764 }
765 
766 } // end of isc::db namespace
767 } // 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.