Kea 2.7.6
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
139void PsqlBindArray::addNull(const int format) {
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 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.
257}
258
259void
265
266void
268 if (!value) {
269 addNull();
270 return;
271 }
272
273 std::ostringstream ss;
274 value->toJSON(ss);
275 addTempString(ss.str());
276}
277
278void
280 if (!value) {
281 addNull();
282 return;
283 }
284
285 std::ostringstream ss;
286 value->toJSON(ss);
287 addTempString(ss.str());
288}
289
290std::string
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
324bool
325PsqlBindArray::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
336std::string
337PgSqlExchange::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
349std::string
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
364std::string
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
384time_t
385PgSqlExchange::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
397void
398PgSqlExchange::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
404const char*
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
416bool
418 const size_t col) {
419 r.rowColCheck(row,col);
420 return (PQgetisnull(r, row, col));
421}
422
423void
425 const size_t col, std::string& value) {
426 value = getRawColumnValue(r, row, col);
427}
428
429void
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
444void
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
459void
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
467void
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
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
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
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
529void
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
561void
562PgSqlExchange::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
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
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
625std::string
626PgSqlExchange::getColumnLabel(const PgSqlResult& r, const size_t column) {
627 return (r.getColumnLabel(column));
628}
629
630std::string
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
664 : r_(r), row_(row) {
665 // Validate the desired row.
666 r.rowCheck(row);
667}
668
669bool
671 return (PgSqlExchange::isColumnNull(r_, row_, col));
672}
673
674std::string
676 std::string tmp;
677 PgSqlExchange::getColumnValue(r_, row_, col, tmp);
678 return (tmp);
679}
680
681bool
683 bool tmp;
684 PgSqlExchange::getColumnValue(r_, row_, col, tmp);
685 return (tmp);
686}
687
688double
690 double tmp;
691 PgSqlExchange::getColumnValue(r_, row_, col, tmp);
692 return (tmp);
693}
694
695const char*
697 return (PgSqlExchange::getRawColumnValue(r_, row_, col));
698}
699
700uint64_t
702 uint64_t value;
703 PgSqlExchange::getColumnValue(r_, row_, col, value);
704 return (value);
705}
706
707uint32_t
709 uint32_t value;
710 PgSqlExchange::getColumnValue(r_, row_, col, value);
711 return (value);
712}
713
714uint16_t
716 uint16_t value;
717 PgSqlExchange::getColumnValue(r_, row_, col, value);
718 return (value);
719}
720
721void
722PgSqlResultRowWorker::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
736boost::posix_time::ptime
738 boost::posix_time::ptime value;
739 getColumnValue(col, value);
740 return (value);
741};
742
745 data::ElementPtr value;
746 getColumnValue(col, value);
747 return (value);
748}
749
752 return (PgSqlExchange::getTripletValue(r_, row_, col));
753}
754
756PgSqlResultRowWorker::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
761std::string
765
766} // end of isc::db namespace
767} // 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 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:798
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:36
void unspecified(bool unspecified)
Modifies the flag that indicates whether the value is specified or unspecified.
Definition optional.h:136
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:29
boost::shared_ptr< Element > ElementPtr
Definition data.h:28
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.
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.