Kea 2.2.0
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
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
19using namespace isc::util;
20using namespace isc::data;
21using namespace boost::posix_time;
22
23namespace isc {
24namespace db {
25
26const int PsqlBindArray::TEXT_FMT = 0;
27const int PsqlBindArray::BINARY_FMT = 1;
28const char* PsqlBindArray::TRUE_STR = "TRUE";
29const char* PsqlBindArray::FALSE_STR = "FALSE";
30
31void 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
41void 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
47void 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
58void 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
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
81void 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
87void 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
96void 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
106void 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
119void PsqlBindArray::add(const bool& value) {
120 add(value ? TRUE_STR : FALSE_STR);
121}
122
123void 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
131 if (addr.isV4()) {
132 addTempString(boost::lexical_cast<std::string>
133 (addr.toUint32()));
134 } else {
135 addTempString(addr.toText());
136 }
137}
138
140 values_.push_back(NULL);
141 lengths_.push_back(0);
142 formats_.push_back(format);
143}
144
145void
147 if (triplet.unspecified()) {
148 addNull();
149 } else {
150 add<uint32_t>(triplet.get());
151 }
152}
153
154void
156 if (triplet.unspecified() || (triplet.getMin() == triplet.get())) {
157 addNull();
158 } else {
159 add<uint32_t>(triplet.getMin());
160 }
161}
162
163void
165 if (triplet.unspecified() || (triplet.getMax() == triplet.get())) {
166 addNull();
167 } else {
168 add<uint32_t>(triplet.getMax());
169 }
170}
171
177void 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
183void
185 if (value.unspecified()) {
186 addNull();
187 } else {
188 addTempString(value);
189 }
190}
191
192void
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
203void
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
213void
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
224void
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
234void
235PsqlBindArray::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.
251}
252
253void
255 time_t now;
256 time(&now);
258}
259
260void
262 if (!value) {
263 addNull();
264 return;
265 }
266
267 std::ostringstream ss;
268 value->toJSON(ss);
269 addTempString(ss.str());
270}
271
272void
274 if (!value) {
275 addNull();
276 return;
277 }
278
279 std::ostringstream ss;
280 value->toJSON(ss);
281 addTempString(ss.str());
282}
283
284std::string
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
318bool
319PsqlBindArray::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
330std::string
331PgSqlExchange::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
343std::string
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
358std::string
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
378time_t
379PgSqlExchange::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
391void
392PgSqlExchange::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
398const char*
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
410bool
412 const size_t col) {
413 r.rowColCheck(row,col);
414 return (PQgetisnull(r, row, col));
415}
416
417void
419 const size_t col, std::string& value) {
420 value = getRawColumnValue(r, row, col);
421}
422
423void
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
438void
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
453void
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
461void
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
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
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
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
523void
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
555void
556PgSqlExchange::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
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
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
619std::string
620PgSqlExchange::getColumnLabel(const PgSqlResult& r, const size_t column) {
621 return (r.getColumnLabel(column));
622}
623
624std::string
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 << " : " ;
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
658 : r_(r), row_(row) {
659 // Validate the desired row.
660 r.rowCheck(row);
661}
662
663bool
665 return (PgSqlExchange::isColumnNull(r_, row_, col));
666}
667
668std::string
670 std::string tmp;
671 PgSqlExchange::getColumnValue(r_, row_, col, tmp);
672 return (tmp);
673}
674
675bool
677 bool tmp;
678 PgSqlExchange::getColumnValue(r_, row_, col, tmp);
679 return (tmp);
680}
681
682double
684 double tmp;
685 PgSqlExchange::getColumnValue(r_, row_, col, tmp);
686 return (tmp);
687}
688
689const char*
691 return (PgSqlExchange::getRawColumnValue(r_, row_, col));
692}
693
694uint64_t
696 uint64_t value;
697 PgSqlExchange::getColumnValue(r_, row_, col, value);
698 return (value);
699}
700
701uint32_t
703 uint32_t value;
704 PgSqlExchange::getColumnValue(r_, row_, col, value);
705 return (value);
706}
707
708uint16_t
710 uint16_t value;
711 PgSqlExchange::getColumnValue(r_, row_, col, value);
712 return (value);
713}
714
715void
716PgSqlResultRowWorker::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
730boost::posix_time::ptime
732 boost::posix_time::ptime value;
733 getColumnValue(col, value);
734 return (value);
735};
736
739 data::ElementPtr value;
740 getColumnValue(col, value);
741 return (value);
742}
743
746 return (PgSqlExchange::getTripletValue(r_, row_, col));
747}
748
750PgSqlResultRowWorker::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
755std::string
757 return (PgSqlExchange::dumpRow(r_, row_));
758}
759
760} // end of isc::db namespace
761} // end of isc namespace
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.
void unspecified(bool unspecified)
Modifies the flag that indicates whether the value is specified or unspecified.
Definition: optional.h:136
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:27
boost::shared_ptr< Element > ElementPtr
Definition: data.h:24
boost::shared_ptr< const std::string > ConstStringPtr
Structure used to bind C++ input values to dynamic SQL parameters The structure contains three vector...
std::string format(const std::string &format, const std::vector< std::string > &args)
Apply Formatting.
Definition: strutil.cc:157
Definition: edns.h:19
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.