Kea 2.7.5
pgsql_exchange.h
Go to the documentation of this file.
1// Copyright (C) 2016-2024 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#ifndef PGSQL_EXCHANGE_H
8#define PGSQL_EXCHANGE_H
9
10#include <asiolink/io_address.h>
12#include <cc/data.h>
13#include <util/triplet.h>
16
17#include <boost/lexical_cast.hpp>
18#include <boost/noncopyable.hpp>
19#include <boost/shared_ptr.hpp>
20#include <libpq-fe.h>
21
22#include <stdint.h>
23#include <vector>
24#include <iostream>
25
26namespace isc {
27namespace db {
28
45
46class PgSqlResult : public boost::noncopyable {
47public:
57 PgSqlResult(PGresult *result);
58
63
65 int getRows() const {
66 return (rows_);
67 }
68
70 int getCols() const {
71 return (cols_);
72 }
73
79 void rowCheck(int row) const;
80
86 void colCheck(int col) const;
87
95 void rowColCheck(int row, int col) const;
96
106 std::string getColumnLabel(const int col) const;
107
112 operator PGresult*() const {
113 return (result_);
114 }
115
119 operator bool() const {
120 return (result_);
121 }
122
123private:
124 PGresult* result_;
125 int rows_;
126 int cols_;
127};
128
129typedef boost::shared_ptr<PgSqlResult> PgSqlResultPtr;
130
149typedef boost::shared_ptr<const std::string> ConstStringPtr;
150
154
156 std::vector<const char*> values_;
157
159 std::vector<int> lengths_;
160
163 std::vector<int> formats_;
164
166 static const int TEXT_FMT;
167
169 static const int BINARY_FMT;
170
172 static const char* TRUE_STR;
173
175 static const char* FALSE_STR;
176
179 size_t size() const {
180 return (values_.size());
181 }
182
186 bool empty() const {
187 return (values_.empty());
188 }
189
199 void add(const char* value);
200
209 void add(const std::string& value);
210
224 void insert(const char* value, size_t index);
225
238 void insert(const std::string& value, size_t index);
239
243 void popBack();
244
253 void add(const std::vector<uint8_t>& data);
254
262 void addTempBinary(const std::vector<uint8_t>& data);
263
274 void add(const uint8_t* data, const size_t len);
275
288 void addTempBuffer(const uint8_t* data, const size_t len);
289
297 void add(const bool& value);
298
306 void add(const uint8_t& byte);
307
316 void add(const isc::asiolink::IOAddress& addr);
317
326 template<typename T>
327 void add(const T& value) {
328 addTempString(boost::lexical_cast<std::string>(value));
329 }
330
339 void addTempString(const std::string& str);
340
345 void addNull(const int format = PsqlBindArray::TEXT_FMT);
346
353 void add(const isc::util::Triplet<uint32_t>& triplet);
354
361 void addMin(const isc::util::Triplet<uint32_t>& triplet);
362
369 void addMax(const isc::util::Triplet<uint32_t>& triplet);
370
377 void addOptional(const util::Optional<std::string>& value);
378
384 template<typename T>
385 void addOptional(const util::Optional<T>& value) {
386 if (value.unspecified()) {
387 addNull();
388 } else {
389 add(value.get());
390 }
391 }
392
399 void addInet4(const isc::asiolink::IOAddress& value);
400
407 void addInet6(const isc::asiolink::IOAddress& value);
408
416
426
427
434 void addTimestamp(const boost::posix_time::ptime& timestamp);
435
439 void addTimestamp();
440
448 void add(const data::ElementPtr& value);
449
457 void add(const data::ConstElementPtr& value);
458
461 std::string toText() const;
462
463 // --- the following methods are mostly useful for testing -----
464
469 bool amNull(size_t index = 0) const;
470
478 template<typename T>
479 T getInteger(size_t index = 0) {
480 if (values_.size() < index + 1) {
481 isc_throw(OutOfRange, "Invalid index " << index << ", the values array has "
482 << values_.size() << " element(s)");
483 }
484 auto x = values_.at(index);
485 if (!x) {
486 isc_throw(BadValue, "the data in column " << index << " is null");
487 }
488 return (boost::lexical_cast<T>(x));
489 }
490
496 int getType(size_t index = 0 ) {
497 if (formats_.size() < index + 1) {
498 isc_throw(OutOfRange, "Invalid index " << index << ", the formats_ array has "
499 << formats_.size() << " element(s)");
500 }
501 return (formats_.at(index));
502 }
503
504private:
506 std::vector<ConstStringPtr> bound_strs_;
507};
508
510typedef boost::shared_ptr<PsqlBindArray> PsqlBindArrayPtr;
511
518public:
520 PgSqlExchange(const size_t num_columns = 0) : columns_(num_columns) {}
521
523 virtual ~PgSqlExchange() {}
524
529 static std::string convertToDatabaseTime(const time_t input_time);
530
535 static std::string convertLocalToDatabaseTime(const time_t input_time);
536
559 static std::string convertToDatabaseTime(const time_t cltt,
560 const uint32_t valid_lifetime);
561
571 static time_t convertFromDatabaseTime(const std::string& db_time_val);
572
582 static void convertFromDatabaseTime(const std::string& db_time_val,
583 boost::posix_time::ptime& conv_time);
584
599 static const char* getRawColumnValue(const PgSqlResult& r, const int row,
600 const size_t col);
601
613 static std::string getColumnLabel(const PgSqlResult& r, const size_t col);
614
624 static void getColumnValue(const PgSqlResult& r, const int row,
625 const size_t col, std::string& value);
626
636 static void getColumnValue(const PgSqlResult& r, const int row,
637 const size_t col, bool &value);
638
648 static void getColumnValue(const PgSqlResult& r, const int row,
649 const size_t col, uint8_t &value);
650
663 const int row,
664 const size_t col);
665
678 const int row,
679 const size_t col);
680
693 const int row,
694 const size_t col);
695
703 static bool isColumnNull(const PgSqlResult& r, const int row,
704 const size_t col);
705
718 template<typename T>
719 static void getColumnValue(const PgSqlResult& r, const int row,
720 const size_t col, T& value) {
721 const char* data = getRawColumnValue(r, row, col);
722 try {
723 value = boost::lexical_cast<T>(data);
724 } catch (const std::exception& ex) {
725 isc_throw(db::DbOperationError, "Invalid data:[" << data
726 << "] for row: " << row << " col: " << col << ","
727 << getColumnLabel(r, col) << " : " << ex.what());
728 }
729 }
730
740 static void getColumnValue(const PgSqlResult& r, const int row,
741 const size_t col, boost::posix_time::ptime& value);
742
752 static void getColumnValue(const PgSqlResult& r, const int row,
753 const size_t col, data::ElementPtr& value);
754
770 static void convertFromBytea(const PgSqlResult& r, const int row,
771 const size_t col, uint8_t* buffer,
772 const size_t buffer_size,
773 size_t &bytes_converted);
774
788 static void convertFromBytea(const PgSqlResult& r, const int row,
789 const size_t col, std::vector<uint8_t>& value);
790
803 const int row,
804 const size_t col);
805
823 const int row,
824 const size_t def_col,
825 const size_t min_col,
826 const size_t max_col);
827
834 static std::string dumpRow(const PgSqlResult& r, int row);
835
836protected:
839 std::vector<std::string> columns_;
840};
841
845public:
852 PgSqlResultRowWorker(const PgSqlResult& r, const int row);
853
859 bool isColumnNull(const size_t col);
860
866 std::string getString(const size_t col);
867
873 bool getBool(const size_t col);
874
880 double getDouble(const size_t col);
881
893 const char* getRawColumnValue(const size_t col);
894
900 uint64_t getBigInt(const size_t col);
901
907 uint32_t getInt(const size_t col);
908
914 uint16_t getSmallInt(const size_t col);
915
920 void getBytes(const size_t col, std::vector<uint8_t>& value);
921
928 isc::asiolink::IOAddress getInet4(const size_t col);
929
936 isc::asiolink::IOAddress getInet6(const size_t col);
937
945 template<typename T>
946 void getColumnValue(const size_t col, T& value) {
947 PgSqlExchange::getColumnValue(r_, row_, col, value);
948 }
949
954 boost::posix_time::ptime getTimestamp(const size_t col);
955
960 data::ElementPtr getJSON(const size_t col);
961
969
981 isc::util::Triplet<uint32_t> getTriplet(const size_t def_col,
982 const size_t min_col,
983 const size_t max_col);
984
988 std::string dumpRow();
989
990private:
992 const PgSqlResult& r_;
993
995 size_t row_;
996};
997
999typedef boost::shared_ptr<PgSqlResultRowWorker> PgSqlResultRowWorkerPtr;
1000
1001} // end of isc::db namespace
1002} // end of isc namespace
1003
1004#endif // PGSQL_EXCHANGE_H
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...
Exception thrown on failure to execute a database function.
Base class for marshalling data to and from PostgreSQL.
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.
virtual ~PgSqlExchange()
Destructor.
PgSqlExchange(const size_t num_columns=0)
Constructor.
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, T &value)
Fetches a text column as the given value type.
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.
std::vector< std::string > columns_
Stores text labels for columns, currently only used for logging and errors.
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.
Convenience class which facilitates fetching column values from a result set row.
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 colCheck(int col) const
Determines if a column index is valid.
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 getRows() const
Returns the number of rows in the result set.
int getCols() const
Returns the number of columns in the result set.
PgSqlResult(PGresult *result)
Constructor.
A template representing an optional value.
Definition optional.h:36
T get() const
Retrieves the encapsulated value.
Definition optional.h:114
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
#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< PgSqlResult > PgSqlResultPtr
boost::shared_ptr< PgSqlResultRowWorker > PgSqlResultRowWorkerPtr
Pointer to a result row worker.
boost::shared_ptr< PsqlBindArray > PsqlBindArrayPtr
Defines a smart pointer to PsqlBindArray.
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.
T getInteger(size_t index=0)
Returns the value as an integer.
int getType(size_t index=0)
Returns the column type.
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.
size_t size() const
Fetches the number of entries in the array.
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.
PsqlBindArray()
Constructor.
void addTempBinary(const std::vector< uint8_t > &data)
Adds a vector of binary data to the bind array.
void add(const T &value)
Adds the given value 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 addOptional(const util::Optional< T > &value)
Adds an Optional<type> value to the bind array.
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.
bool empty() const
Indicates it the array is empty.
void addMin(const isc::util::Triplet< uint32_t > &triplet)
Adds an integer Triplet's minimum value to the bind array.