Kea  2.1.7-git
pgsql_exchange.h
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 #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>
14 #include <util/boost_time_utils.h>
15 #include <exceptions/exceptions.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 
26 namespace isc {
27 namespace db {
28 
45 
46 class PgSqlResult : public boost::noncopyable {
47 public:
57  PgSqlResult(PGresult *result);
58 
62  ~PgSqlResult();
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 
123 private:
124  PGresult* result_;
125  int rows_;
126  int cols_;
127 };
128 
129 typedef boost::shared_ptr<PgSqlResult> PgSqlResultPtr;
130 
149 typedef boost::shared_ptr<const std::string> ConstStringPtr;
150 
153  PsqlBindArray() : values_(0), lengths_(0), formats_(0) {}
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);
390  }
391  }
392 
399  void addInet4(const isc::asiolink::IOAddress& value);
400 
407  void addInet6(const isc::asiolink::IOAddress& value);
408 
415  void addOptionalInet4(const util::Optional<isc::asiolink::IOAddress>& value);
416 
425  void addOptionalInet6(const util::Optional<isc::asiolink::IOAddress>& value);
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 
504 private:
506  std::vector<ConstStringPtr> bound_strs_;
507 };
508 
510 typedef boost::shared_ptr<PsqlBindArray> PsqlBindArrayPtr;
511 
518 public:
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 
662  static isc::asiolink::IOAddress getInetValue4(const PgSqlResult& r,
663  const int row,
664  const size_t col);
665 
677  static isc::asiolink::IOAddress getInetValue6(const PgSqlResult& r,
678  const int row,
679  const size_t col);
680 
692  static isc::asiolink::IOAddress getIPv6Value(const PgSqlResult& r,
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 
771  static void convertFromBytea(const PgSqlResult& r, const int row,
772  const size_t col, uint8_t* buffer,
773  const size_t buffer_size,
774  size_t &bytes_converted);
775 
789  static void convertFromBytea(const PgSqlResult& r, const int row,
790  const size_t col, std::vector<uint8_t>& value);
791 
803  static isc::util::Triplet<uint32_t> getTripletValue(const PgSqlResult& r,
804  const int row,
805  const size_t col);
806 
823  static isc::util::Triplet<uint32_t> getTripletValue(const PgSqlResult& r,
824  const int row,
825  const size_t def_col,
826  const size_t min_col,
827  const size_t max_col);
828 
835  static std::string dumpRow(const PgSqlResult& r, int row);
836 
837 protected:
840  std::vector<std::string> columns_;
841 };
842 
846 public:
853  PgSqlResultRowWorker(const PgSqlResult& r, const int row);
854 
860  bool isColumnNull(const size_t col);
861 
867  std::string getString(const size_t col);
868 
874  bool getBool(const size_t col);
875 
881  double getDouble(const size_t col);
882 
894  const char* getRawColumnValue(const size_t col);
895 
901  uint64_t getBigInt(const size_t col);
902 
908  uint32_t getInt(const size_t col);
909 
915  uint16_t getSmallInt(const size_t col);
916 
921  void getBytes(const size_t col, std::vector<uint8_t>& value);
922 
929  isc::asiolink::IOAddress getInet4(const size_t col);
930 
937  isc::asiolink::IOAddress getInet6(const size_t col);
938 
946  template<typename T>
947  void getColumnValue(const size_t col, T& value) {
948  PgSqlExchange::getColumnValue(r_, row_, col, value);
949  }
950 
955  boost::posix_time::ptime getTimestamp(const size_t col);
956 
961  data::ElementPtr getJSON(const size_t col);
962 
969  isc::util::Triplet<uint32_t> getTriplet(const size_t col);
970 
982  isc::util::Triplet<uint32_t> getTriplet(const size_t def_col,
983  const size_t min_col,
984  const size_t max_col);
985 
989  std::string dumpRow();
990 
991 private:
993  const PgSqlResult& r_;
994 
996  size_t row_;
997 };
998 
1000 typedef boost::shared_ptr<PgSqlResultRowWorker> PgSqlResultRowWorkerPtr;
1001 
1002 } // end of isc::db namespace
1003 } // end of isc namespace
1004 
1005 #endif // PGSQL_EXCHANGE_H
RAII wrapper for PostgreSQL Result sets.
void unspecified(bool unspecified)
Modifies the flag that indicates whether the value is specified or unspecified.
Definition: optional.h:136
std::vector< int > formats_
Vector of "format" for each value.
void addOptional(const util::Optional< T > &value)
Adds an Optional<type> value to the bind array.
static const int BINARY_FMT
Format value for binary data.
static const char * FALSE_STR
Constant string passed to DB for boolean false values.
boost::shared_ptr< PgSqlResult > PgSqlResultPtr
std::vector< int > lengths_
Vector of data lengths for each value.
PgSqlResult(PGresult *result)
Constructor.
PgSqlExchange(const size_t num_columns=0)
Constructor.
boost::shared_ptr< Element > ElementPtr
Definition: data.h:24
Base class for marshalling data to and from PostgreSQL.
int getRows() const
Returns the number of rows in the result set.
void rowCheck(int row) const
Determines if a row index is valid.
bool empty() const
Indicates it the array is empty.
std::string getColumnLabel(const int col) const
Fetches the name of the column in a result set.
int getType(size_t index=0)
Returns the column type.
std::vector< const char * > values_
Vector of pointers to the data values.
Convenience class which facilitates fetching column values from a result set row. ...
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
boost::shared_ptr< PsqlBindArray > PsqlBindArrayPtr
Defines a smart pointer to PsqlBindArray.
virtual ~PgSqlExchange()
Destructor.
static const int TEXT_FMT
Format value for text data.
boost::shared_ptr< const Element > ConstElementPtr
Definition: data.h:27
boost::shared_ptr< PgSqlResultRowWorker > PgSqlResultRowWorkerPtr
Pointer to a result row worker.
static void getColumnValue(const PgSqlResult &r, const int row, const size_t col, std::string &value)
Fetches text column value as a string.
static void getColumnValue(const PgSqlResult &r, const int row, const size_t col, T &value)
Fetches a text column as the given value type.
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.
size_t size() const
Fetches the number of entries in the array.
std::vector< std::string > columns_
Stores text labels for columns, currently only used for logging and errors.
T getInteger(size_t index=0)
Returns the value as an integer.
void rowColCheck(int row, int col) const
Determines if both a row and column index are valid.
PsqlBindArray()
Constructor.
void colCheck(int col) const
Determines if a column index is valid.
~PgSqlResult()
Destructor.
int getCols() const
Returns the number of columns in the result set.
void add(const T &value)
Adds the given value to the bind array.
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.
static const char * TRUE_STR
Constant string passed to DB for boolean true values.
std::string format(const std::string &format, const std::vector< std::string > &args)
Apply Formatting.
Definition: strutil.cc:157
void getColumnValue(const size_t col, T &value)
Fetches a text column as the given value type.