Kea 3.3.1
pgsql_exchange.cc
Go to the documentation of this file.
1// Copyright (C) 2016-2026 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
10#include <util/str.h>
12
13#include <boost/date_time/posix_time/posix_time.hpp>
14#include <boost/lexical_cast.hpp>
15
16#include <iomanip>
17#include <sstream>
18#include <vector>
19
20using namespace isc::util;
21using namespace isc::util::str;
22using namespace isc::data;
23using namespace boost::posix_time;
24
25namespace isc {
26namespace db {
27
28const int PsqlBindArray::TEXT_FMT = 0;
29const int PsqlBindArray::BINARY_FMT = 1;
30const char* PsqlBindArray::TRUE_STR = "TRUE";
31const char* PsqlBindArray::FALSE_STR = "FALSE";
32
33void PsqlBindArray::add(const char* value) {
34 if (!value) {
35 isc_throw(BadValue, "PsqlBindArray::add - char* value cannot be NULL");
36 }
37
38 values_.push_back(value);
39 lengths_.push_back(strlen(value));
40 formats_.push_back(TEXT_FMT);
41}
42
43void PsqlBindArray::add(const std::string& value) {
44 values_.push_back(value.c_str());
45 lengths_.push_back(value.size());
46 formats_.push_back(TEXT_FMT);
47}
48
49void PsqlBindArray::insert(const char* value, size_t index) {
50 if (index && index >= values_.size()) {
51 isc_throw(OutOfRange, "PsqlBindArray::insert - index: " << index
52 << ", is larger than the array size: " << values_.size());
53 }
54
55 values_.insert(values_.begin() + index, value);
56 lengths_.insert(lengths_.begin() + index, strlen(value));
57 formats_.insert(formats_.begin() + index, TEXT_FMT);
58}
59
60void PsqlBindArray::insert(const std::string& value, size_t index) {
61 if (index && index >= values_.size()) {
62 isc_throw(OutOfRange, "PsqlBindArray::insert - index: " << index
63 << ", is larger than the array size: " << values_.size());
64 }
65
66 bound_strs_.push_back(ConstStringPtr(new std::string(value)));
67
68 values_.insert(values_.begin() + index, bound_strs_.back()->c_str());
69 lengths_.insert(lengths_.begin() + index, value.size());
70 formats_.insert(formats_.begin() + index, TEXT_FMT);
71}
72
74 if (values_.size() == 0) {
75 isc_throw(OutOfRange, "PsqlBindArray::pop_back - array empty");
76 }
77
78 values_.erase(values_.end() - 1);
79 lengths_.erase(lengths_.end() - 1);
80 formats_.erase(formats_.end() - 1);
81}
82
83void PsqlBindArray::add(const std::vector<uint8_t>& data) {
84 values_.push_back(reinterpret_cast<const char*>(&(data[0])));
85 lengths_.push_back(data.size());
86 formats_.push_back(BINARY_FMT);
87}
88
89void PsqlBindArray::addTempBinary(const std::vector<uint8_t>& data) {
90 bound_strs_.push_back(ConstStringPtr(new std::string(
91 reinterpret_cast<const char*>(data.data()), data.size())));
92
93 values_.push_back(reinterpret_cast<const char*>(bound_strs_.back()->data()));
94 lengths_.push_back(data.size());
95 formats_.push_back(BINARY_FMT);
96}
97
98void PsqlBindArray::add(const uint8_t* data, const size_t len) {
99 if (!data) {
100 isc_throw(BadValue, "PsqlBindArray::add - uint8_t data cannot be NULL");
101 }
102
103 values_.push_back(reinterpret_cast<const char*>(&(data[0])));
104 lengths_.push_back(len);
105 formats_.push_back(BINARY_FMT);
106}
107
108void PsqlBindArray::addTempBuffer(const uint8_t* data, const size_t len) {
109 if (!data) {
110 isc_throw(BadValue, "PsqlBindArray::addTempBuffer - uint8_t data cannot be NULL");
111 }
112
113 bound_strs_.push_back(ConstStringPtr(new std::string(
114 reinterpret_cast<const char*>(data), len)));
115
116 values_.push_back(bound_strs_.back()->data());
117 lengths_.push_back(len);
118 formats_.push_back(BINARY_FMT);
119}
120
121void PsqlBindArray::add(const bool& value) {
122 add(value ? TRUE_STR : FALSE_STR);
123}
124
125void PsqlBindArray::add(const uint8_t& byte) {
126 // We static_cast to an unsigned int, otherwise lexical_cast may to
127 // treat byte as a character, which yields "" for unprintable values
128 addTempString(boost::lexical_cast<std::string>
129 (static_cast<unsigned int>(byte)));
130}
131
133 if (addr.isV4()) {
134 addTempString(boost::lexical_cast<std::string>
135 (addr.toUint32()));
136 } else {
137 addTempString(addr.toText());
138 }
139}
140
141void PsqlBindArray::addNull(const int format) {
142 values_.push_back(NULL);
143 lengths_.push_back(0);
144 formats_.push_back(format);
145}
146
147void
149 if (triplet.unspecified()) {
150 addNull();
151 } else {
152 add<uint32_t>(triplet.get());
153 }
154}
155
156void
158 if (triplet.unspecified() || (triplet.getMin() == triplet.get())) {
159 addNull();
160 } else {
161 add<uint32_t>(triplet.getMin());
162 }
163}
164
165void
167 if (triplet.unspecified() || (triplet.getMax() == triplet.get())) {
168 addNull();
169 } else {
170 add<uint32_t>(triplet.getMax());
171 }
172}
173
179void PsqlBindArray::addTempString(const std::string& str) {
180 bound_strs_.push_back(ConstStringPtr(new std::string(str)));
181
182 PsqlBindArray::add((bound_strs_.back())->c_str());
183}
184
185void
187 if (value.unspecified()) {
188 addNull();
189 } else {
190 addTempString(value);
191 }
192}
193
194void
196 if (!value.isV4()) {
197 isc_throw(BadValue, "unable to add address to PsqlBindAray '"
198 << value.toText() << "' is not an IPv4 address");
199 }
200
201 // inet columns are inserted as string addresses.
202 addTempString(value.toText());
203}
204
205void
207 // If the value is unspecified it doesn't matter what the value is.
208 if (value.unspecified()) {
209 addNull();
210 } else {
211 addInet4(value);
212 }
213}
214
215void
217 if (!value.isV6()) {
218 isc_throw(BadValue, "unable to add address to PsqlBindAray '"
219 << value.toText() << "' is not an IPv6 address");
220 }
221
222 // inet columns are inserted as string addresses.
223 addTempString(value.toText());
224}
225
226void
228 // If the value is unspecified it doesn't matter what the value is.
229 if (value.unspecified()) {
230 addNull();
231 } else {
232 addInet6(value);
233 }
234}
235
236void
237PsqlBindArray::addTimestamp(const boost::posix_time::ptime& timestamp) {
238 // Convert the ptime to time_t, then use the existing conversion
239 // function to make db time.
240 //
241 // Sadly boost::posix_time::to_time_t() was not added until 1.58,
242 // so do it ourselves.
243 ptime epoch(boost::gregorian::date(1970, 1, 1));
244 if (timestamp < epoch) {
245 isc_throw(isc::BadValue, "Time value is before the epoch");
246 }
247 ptime max_db_time = boost::posix_time::from_time_t(DatabaseConnection::MAX_DB_TIME);
248 time_duration::sec_type since_epoch = (timestamp - epoch).total_seconds();
249 time_t input_time(since_epoch);
250 if (timestamp > max_db_time) {
251 isc_throw(isc::BadValue, "Time value is too large: " <<
252 (input_time < 0 ?
253 static_cast<int64_t>(static_cast<uint32_t>(input_time)) :
254 input_time));
255 }
256
257 // Converts to timestamp to local date/time string.
259}
260
261void
267
268void
270 if (!value) {
271 addNull();
272 return;
273 }
274
275 std::ostringstream ss;
276 value->toJSON(ss);
277 addTempString(ss.str());
278}
279
280void
282 if (!value) {
283 addNull();
284 return;
285 }
286
287 std::ostringstream ss;
288 value->toJSON(ss);
289 addTempString(ss.str());
290}
291
292std::string
294 std::ostringstream stream;
295
296 if (values_.size() == 0) {
297 return ("bindarray is empty");
298 }
299
300 for (size_t i = 0; i < values_.size(); ++i) {
301 stream << i << " : ";
302
303 if (lengths_[i] == 0) {
304 stream << "empty" << std::endl;
305 continue;
306 }
307
308 if (formats_[i] == TEXT_FMT) {
309 stream << "\"" << values_[i] << "\"" << std::endl;
310 } else {
311 const char *data = values_[i];
312 stream << "0x";
313 for (int x = 0; x < lengths_[i]; ++x) {
314 stream << byteToHex(data[x]);
315 }
316 stream << std::endl;
317 }
318 }
319
320 return (stream.str());
321}
322
323bool
324PsqlBindArray::amNull(size_t index) const {
325 if (values_.size() < index + 1) {
326 isc_throw(OutOfRange, "The index " << index << " is larger than the "
327 " array size " << values_.size());
328 }
329
330 // We assume lengths_.size() always equals values_.size(). If not, the
331 // at() operator will throw.
332 return ( (values_.at(index) == NULL) && (lengths_.at(index) == 0) );
333}
334
335std::string
336PgSqlExchange::convertToDatabaseTime(const time_t input_time) {
337 struct tm tinfo;
338 char buffer[20];
339
340 localtime_r(&input_time, &tinfo);
341
342 // PostgreSQL will assume the value is already in local time since we
343 // do not specify timezone in the string.
344 strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tinfo);
345 return (std::string(buffer));
346}
347
348std::string
350 struct tm tinfo;
351 char buffer[20];
352
353 // We use gmtime_r to avoid adjustment as time_t is already local.
354 gmtime_r(&input_time, &tinfo);
355
356 // PostgreSQL will assume the value is already in local time since we
357 // do not specify timezone in the string.
358 strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tinfo);
359 return (std::string(buffer));
360}
361
362
363std::string
365 const uint32_t valid_lifetime) {
366 // Calculate expiry time. Store it in the 64-bit value so as we can
367 // detect overflows.
368 int64_t expire_time_64 = static_cast<int64_t>(cltt)
369 + static_cast<int64_t>(valid_lifetime);
370
371 // It has been observed that the PostgreSQL doesn't deal well with the
372 // timestamp values beyond the DataSource::MAX_DB_TIME seconds since the
373 // beginning of the epoch (around year 2038). The value is often
374 // stored in the database but it is invalid when read back (overflow?).
375 // Hence, the maximum timestamp value is restricted here.
376 if (expire_time_64 > DatabaseConnection::MAX_DB_TIME) {
377 isc_throw(isc::BadValue, "Time value is too large: " << expire_time_64);
378 }
379
380 return (convertToDatabaseTime(static_cast<time_t>(expire_time_64)));
381}
382
383time_t
384PgSqlExchange::convertFromDatabaseTime(const std::string& db_time_val) {
385 // Convert string time value to time_t
386 time_t new_time;
387 try {
388 new_time = (boost::lexical_cast<time_t>(db_time_val));
389 } catch (const std::exception& ex) {
390 isc_throw(BadValue, "Database time value is invalid: " << db_time_val);
391 }
392
393 return (new_time);
394}
395
396void
397PgSqlExchange::convertFromDatabaseTime(const std::string& db_time_val,
398 boost::posix_time::ptime& conv_time) {
399 time_t tmp_time = convertFromDatabaseTime(db_time_val);
400 conv_time = boost::posix_time::from_time_t(tmp_time);
401}
402
403const char*
405 const size_t col) {
406 r.rowColCheck(row,col);
407 const char* value = PQgetvalue(r, row, col);
408 if (!value) {
409 isc_throw(DbOperationError, "getRawColumnValue no data for :"
410 << getColumnLabel(r, col) << " row:" << row);
411 }
412 return (value);
413}
414
415bool
417 const size_t col) {
418 r.rowColCheck(row,col);
419 return (PQgetisnull(r, row, col));
420}
421
422void
424 const size_t col, std::string& value) {
425 value = getRawColumnValue(r, row, col);
426}
427
428void
430 const size_t col, bool &value) {
431 const char* data = getRawColumnValue(r, row, col);
432 if (!strlen(data) || *data == 'f') {
433 value = false;
434 } else if (*data == 't') {
435 value = true;
436 } else {
437 isc_throw(DbOperationError, "Invalid boolean data: " << data
438 << " for: " << getColumnLabel(r, col) << " row:" << row
439 << " : must be 't' or 'f'");
440 }
441}
442
443void
445 const size_t col, uint8_t &value) {
446 const char* data = getRawColumnValue(r, row, col);
447 try {
448 // lexically casting as uint8_t doesn't convert from char
449 // so we use uint16_t and implicitly convert.
450 value = boost::lexical_cast<uint16_t>(data);
451 } catch (const std::exception& ex) {
452 isc_throw(DbOperationError, "Invalid uint8_t data: " << data
453 << " for: " << getColumnLabel(r, col) << " row:" << row
454 << " : " << ex.what());
455 }
456}
457
458void
460 const size_t col, boost::posix_time::ptime& value) {
461 std::string db_time_val;
462 PgSqlExchange::getColumnValue(r, row, col, db_time_val );
463 PgSqlExchange::convertFromDatabaseTime(db_time_val, value);
464}
465
466void
468 const size_t col, ElementPtr& value) {
469 const char* data = getRawColumnValue(r, row, col);
470 try {
471 value = Element::fromJSON(data);
472 } catch (const std::exception& ex) {
473 isc_throw(DbOperationError, "Cannot convert data: " << data
474 << " for: " << getColumnLabel(r, col) << " row:" << row
475 << " : " << ex.what());
476 }
477}
478
481 const size_t col) {
482 const char* data = getRawColumnValue(r, row, col);
483 try {
485 if (!addr.isV4()) {
486 isc_throw(BadValue, "not a v4 address");
487 }
488
489 return (addr);
490 } catch (const std::exception& ex) {
491 isc_throw(DbOperationError, "Cannot convert data: " << data
492 << " for: " << getColumnLabel(r, col) << " row:" << row
493 << " : " << ex.what());
494 }
495}
496
499 const size_t col) {
500 const char* data = getRawColumnValue(r, row, col);
501 try {
503 if (!addr.isV6()) {
504 isc_throw(BadValue, "not a v6 address");
505 }
506
507 return (addr);
508 } catch (const std::exception& ex) {
509 isc_throw(DbOperationError, "Cannot convert data: " << data
510 << " for: " << getColumnLabel(r, col) << " row:" << row
511 << " : " << ex.what());
512 }
513}
514
517 const size_t col) {
518 const char* data = getRawColumnValue(r, row, col);
519 try {
521 } catch (const std::exception& ex) {
522 isc_throw(DbOperationError, "Cannot convert data: " << data
523 << " for: " << getColumnLabel(r, col) << " row:" << row
524 << " : " << ex.what());
525 }
526}
527
528void
530 const size_t col, uint8_t* buffer,
531 const size_t buffer_size,
532 size_t &bytes_converted) {
533 // Returns converted bytes in a dynamically allocated buffer, and
534 // sets bytes_converted.
535 unsigned char* bytes = PQunescapeBytea((const unsigned char*)
536 (getRawColumnValue(r, row, col)),
537 &bytes_converted);
538
539 // Unlikely it couldn't allocate it but you never know.
540 if (!bytes) {
541 isc_throw (DbOperationError, "PQunescapeBytea failed for:"
542 << getColumnLabel(r, col) << " row:" << row);
543 }
544
545 // Make sure it's not larger than expected.
546 if (bytes_converted > buffer_size) {
547 // Free the allocated buffer first!
548 PQfreemem(bytes);
549 isc_throw (DbOperationError, "Converted data size: "
550 << bytes_converted << " is too large for: "
551 << getColumnLabel(r, col) << " row:" << row);
552 }
553
554 // Copy from the allocated buffer to caller's buffer then free
555 // the allocated buffer.
556 memcpy(buffer, bytes, bytes_converted);
557 PQfreemem(bytes);
558}
559
560void
561PgSqlExchange::convertFromBytea(const PgSqlResult& r, const int row, const size_t col,
562 std::vector<uint8_t>& value) {
563 // Returns converted bytes in a dynamically allocated buffer, and
564 // sets bytes_converted.
565 size_t bytes_converted = 0;
566 unsigned char* bytes = PQunescapeBytea((const unsigned char*)
567 (getRawColumnValue(r, row, col)),
568 &bytes_converted);
569
570 // Unlikely it couldn't allocate it but you never know.
571 if (!bytes) {
572 isc_throw (DbOperationError, "PQunescapeBytea failed for:"
573 << getColumnLabel(r, col) << " row:" << row);
574 }
575
576 // Copy from the allocated buffer to caller's buffer then free
577 // the allocated buffer.
578 if (bytes_converted) {
579 value.assign(bytes, bytes + bytes_converted);
580 } else {
581 value.clear();
582 }
583
584 // Free the PostgreSQL buffer.
585 PQfreemem(bytes);
586}
587
590 const size_t col) {
591 uint32_t col_value;
592 if (isColumnNull(r, row, col)) {
593 return (Triplet<uint32_t>());
594 }
595
596 getColumnValue(r, row, col, col_value);
597 return (Triplet<uint32_t>(col_value));
598}
599
602 const size_t def_col, const size_t min_col,
603 const size_t max_col) {
604 if (isColumnNull(r, row, def_col)) {
605 return (Triplet<uint32_t>());
606 }
607
608 uint32_t value;
609 getColumnValue(r, row, def_col, value);
610
611 uint32_t min_value = value;
612 if (!isColumnNull(r, row, min_col)) {
613 getColumnValue(r, row, min_col, min_value);
614 }
615
616 uint32_t max_value = value;
617 if (!isColumnNull(r, row, max_col)) {
618 getColumnValue(r, row, max_col, max_value);
619 }
620
621 return (Triplet<uint32_t>(min_value, value, max_value));
622}
623
624std::string
625PgSqlExchange::getColumnLabel(const PgSqlResult& r, const size_t column) {
626 return (r.getColumnLabel(column));
627}
628
629std::string
631 r.rowCheck(row);
632 std::ostringstream stream;
633 int columns = r.getCols();
634 for (int col = 0; col < columns; ++col) {
635 const char* val = getRawColumnValue(r, row, col);
636 std::string name = r.getColumnLabel(col);
637 int format = PQfformat(r, col);
638
639 stream << col << " " << name << " : " ;
640 if (format == PsqlBindArray::TEXT_FMT) {
641 stream << "\"" << val << "\"" << std::endl;
642 } else {
643 const char *data = val;
644 int length = PQfsize(r, col);
645 if (length == 0) {
646 stream << "empty" << std::endl;
647 } else {
648 stream << "0x";
649 for (int i = 0; i < length; ++i) {
650 stream << byteToHex(data[i]);
651 }
652 stream << std::endl;
653 }
654 }
655 }
656
657 return (stream.str());
658}
659
661 : r_(r), row_(row) {
662 // Validate the desired row.
663 r.rowCheck(row);
664}
665
666bool
668 return (PgSqlExchange::isColumnNull(r_, row_, col));
669}
670
671std::string
673 std::string tmp;
674 PgSqlExchange::getColumnValue(r_, row_, col, tmp);
675 return (tmp);
676}
677
678bool
680 bool tmp;
681 PgSqlExchange::getColumnValue(r_, row_, col, tmp);
682 return (tmp);
683}
684
685double
687 double tmp;
688 PgSqlExchange::getColumnValue(r_, row_, col, tmp);
689 return (tmp);
690}
691
692const char*
694 return (PgSqlExchange::getRawColumnValue(r_, row_, col));
695}
696
697uint64_t
699 uint64_t value;
700 PgSqlExchange::getColumnValue(r_, row_, col, value);
701 return (value);
702}
703
704uint32_t
706 uint32_t value;
707 PgSqlExchange::getColumnValue(r_, row_, col, value);
708 return (value);
709}
710
711uint16_t
713 uint16_t value;
714 PgSqlExchange::getColumnValue(r_, row_, col, value);
715 return (value);
716}
717
718void
719PgSqlResultRowWorker::getBytes(const size_t col, std::vector<uint8_t>& value) {
720 PgSqlExchange::convertFromBytea(r_, row_, col, value);
721}
722
725 return (PgSqlExchange::getInetValue4(r_, row_, col));
726}
727
730 return (PgSqlExchange::getInetValue6(r_, row_, col));
731}
732
733boost::posix_time::ptime
735 boost::posix_time::ptime value;
736 getColumnValue(col, value);
737 return (value);
738};
739
742 data::ElementPtr value;
743 getColumnValue(col, value);
744 return (value);
745}
746
749 return (PgSqlExchange::getTripletValue(r_, row_, col));
750}
751
753PgSqlResultRowWorker::getTriplet(const size_t def_col, const size_t min_col,
754 const size_t max_col) {
755 return (PgSqlExchange::getTripletValue(r_, row_, def_col, min_col, max_col));
756}
757
758std::string
762
763} // end of isc::db namespace
764} // end of isc namespace
static ElementPtr fromJSON(const std::string &in, bool preproc=false)
These functions will parse the given string (JSON) representation of a compound element.
Definition data.cc:865
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
A generic exception that is thrown if a parameter given to a method would refer to or modify out-of-r...
static const time_t MAX_DB_TIME
Defines maximum value for time that can be reliably stored.
Exception thrown on failure to execute a database function.
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.
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.
static std::string convertToDatabaseTime(const time_t input_time)
Converts UTC time_t value to a text representation in local time.
static std::string dumpRow(const PgSqlResult &r, int row)
Diagnostic tool which dumps the Result row contents as a string.
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.
static std::string getColumnLabel(const PgSqlResult &r, const size_t col)
Fetches the name of the column in a result set.
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.
static std::string convertLocalToDatabaseTime(const time_t input_time)
Converts local time_t value to a text representation in local time.
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 getColumnValue(const PgSqlResult &r, const int row, const size_t col, std::string &value)
Fetches text column value as a string.
static time_t convertFromDatabaseTime(const std::string &db_time_val)
Converts time stamp from the database to a time_t.
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.
static isc::asiolink::IOAddress getIPv6Value(const PgSqlResult &r, const int row, const size_t col)
Converts a column in a row in a result set into IPv6 address.
void getBytes(const size_t col, std::vector< uint8_t > &value)
Fetches binary data at the given column into a vector.
std::string getString(const size_t col)
Fetches the column value as a string.
void getColumnValue(const size_t col, T &value)
Fetches a text column as the given value type.
boost::posix_time::ptime getTimestamp(const size_t col)
Fetches a timestamp column as a ptime.
bool getBool(const size_t col)
Fetches the boolean value at the given column.
PgSqlResultRowWorker(const PgSqlResult &r, const int row)
Constructor.
const char * getRawColumnValue(const size_t col)
Gets a pointer to the raw column value in a result set row.
data::ElementPtr getJSON(const size_t col)
Fetches a JSON column as an ElementPtr.
isc::util::Triplet< uint32_t > getTriplet(const size_t col)
Fetches a uint32_t value into a Triplet using a single column value.
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.
double getDouble(const size_t col)
Fetches the floating point value at the given column.
uint64_t getBigInt(const size_t col)
Fetches the uint64_t value at the given column.
isc::asiolink::IOAddress getInet4(const size_t col)
Fetches the v4 IP address at the given column.
std::string dumpRow()
Diagnostic tool which dumps the Result row contents as a string.
isc::asiolink::IOAddress getInet6(const size_t col)
Fetches the v6 IP address at the given column.
bool isColumnNull(const size_t col)
Indicates whether or not the given column value is null.
RAII wrapper for PostgreSQL Result sets.
void rowCheck(int row) const
Determines if a row index is valid.
void rowColCheck(int row, int col) const
Determines if both a row and column index are valid.
std::string getColumnLabel(const int col) const
Fetches the name of the column in a result set.
int getCols() const
Returns the number of columns in the result set.
A template representing an optional value.
Definition optional.h:37
void unspecified(bool unspecified)
Modifies the flag that indicates whether the value is specified or unspecified.
Definition optional.h:145
This template specifies a parameter value.
Definition triplet.h:37
T get(T hint) const
Returns value with a hint.
Definition triplet.h:99
T getMax() const
Returns a maximum allowed value.
Definition triplet.h:112
T getMin() const
Returns a minimum allowed value.
Definition triplet.h:85
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:30
boost::shared_ptr< Element > ElementPtr
Definition data.h:29
boost::shared_ptr< const std::string > ConstStringPtr
Structure used to bind C++ input values to dynamic SQL parameters The structure contains three vector...
const std::string & byteToHex(uint8_t byte)
Converts a byte to a two hex digit string.
Definition str.cc:403
Defines the logger used by the top-level component of kea-lfc.
void insert(const char *value, size_t index)
Inserts a string value to the bind array before the given index.
void addOptionalInet4(const util::Optional< isc::asiolink::IOAddress > &value)
Adds an Optional IPv4 address to the bind array.
void addTempString(const std::string &str)
Binds the given string to the bind array.
void addInet4(const isc::asiolink::IOAddress &value)
Adds an IPv4 address to the bind array.
void addInet6(const isc::asiolink::IOAddress &value)
Adds an IPv6 address to the bind array.
std::vector< const char * > values_
Vector of pointers to the data values.
void addTempBuffer(const uint8_t *data, const size_t len)
Adds a temporary buffer of binary data to the bind array.
void addOptional(const util::Optional< std::string > &value)
Adds an Optional string to the bind array.
std::vector< int > formats_
Vector of "format" for each value.
void add(const char *value)
Adds a char array to bind array based.
void addNull(const int format=PsqlBindArray::TEXT_FMT)
Adds a NULL value to the bind array.
void addMax(const isc::util::Triplet< uint32_t > &triplet)
Adds an integer Triplet's maximum value to the bind array.
static const char * TRUE_STR
Constant string passed to DB for boolean true values.
std::string toText() const
Dumps the contents of the array to a string.
static const char * FALSE_STR
Constant string passed to DB for boolean false values.
static const int BINARY_FMT
Format value for binary data.
void addTempBinary(const std::vector< uint8_t > &data)
Adds a vector of binary data to the bind array.
bool amNull(size_t index=0) const
Determines if specified value is null.
static const int TEXT_FMT
Format value for text data.
void addTimestamp()
Adds a timestamp of the current time to the bind array.
void popBack()
Removes the last entry in the bind array.
void addOptionalInet6(const util::Optional< isc::asiolink::IOAddress > &value)
Adds an Optional IPv6 address to the bind array.
std::vector< int > lengths_
Vector of data lengths for each value.
void addMin(const isc::util::Triplet< uint32_t > &triplet)
Adds an integer Triplet's minimum value to the bind array.