Kea  1.5.0
mysql_binding.h
Go to the documentation of this file.
1 // Copyright (C) 2018 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 MYSQL_BINDING_H
8 #define MYSQL_BINDING_H
9 
10 #include <cc/data.h>
12 #include <exceptions/exceptions.h>
13 #include <boost/date_time/posix_time/conversion.hpp>
14 #include <boost/date_time/posix_time/posix_time.hpp>
15 #include <boost/shared_ptr.hpp>
16 #include <mysql/mysql_constants.h>
17 #include <mysql.h>
18 #include <mysqld_error.h>
19 #include <cstdint>
20 #include <iterator>
21 #include <string>
22 #include <vector>
23 
24 namespace isc {
25 namespace db {
26 
33 template<typename T>
36  static const enum_field_types column_type = MYSQL_TYPE_BLOB;
40  static const size_t length = 0;
43  static const bool am_unsigned = false;
44 };
45 
47 template<>
48 struct MySqlBindingTraits<std::string> {
49  static const enum_field_types column_type = MYSQL_TYPE_STRING;
50  static const size_t length = 0;
51  static const bool am_unsigned = false;
52 };
53 
55 template<>
56 struct MySqlBindingTraits<boost::posix_time::ptime> {
57  static const enum_field_types column_type = MYSQL_TYPE_TIMESTAMP;
58  static const size_t length = sizeof(MYSQL_TIME);
59  static const bool am_unsignged = false;
60 };
61 
63 template<>
64 struct MySqlBindingTraits<int8_t> {
65  static const enum_field_types column_type = MYSQL_TYPE_TINY;
66  static const size_t length = 1;
67  static const bool am_unsigned = false;
68 };
69 
71 template<>
72 struct MySqlBindingTraits<uint8_t> {
73  static const enum_field_types column_type = MYSQL_TYPE_TINY;
74  static const size_t length = 1;
75  static const bool am_unsigned = true;
76 };
77 
79 template<>
80 struct MySqlBindingTraits<int16_t> {
81  static const enum_field_types column_type = MYSQL_TYPE_SHORT;
82  static const size_t length = 2;
83  static const bool am_unsigned = false;
84 };
85 
87 template<>
88 struct MySqlBindingTraits<uint16_t> {
89  static const enum_field_types column_type = MYSQL_TYPE_SHORT;
90  static const size_t length = 2;
91  static const bool am_unsigned = true;
92 };
93 
95 template<>
96 struct MySqlBindingTraits<int32_t> {
97  static const enum_field_types column_type = MYSQL_TYPE_LONG;
98  static const size_t length = 4;
99  static const bool am_unsigned = false;
100 };
101 
103 template<>
104 struct MySqlBindingTraits<uint32_t> {
105  static const enum_field_types column_type = MYSQL_TYPE_LONG;
106  static const size_t length = 4;
107  static const bool am_unsigned = true;
108 };
109 
111 template<>
112 struct MySqlBindingTraits<int64_t> {
113  static const enum_field_types column_type = MYSQL_TYPE_LONGLONG;
114  static const size_t length = 8;
115  static const bool am_unsigned = false;
116 };
117 
119 template<>
120 struct MySqlBindingTraits<uint64_t> {
121  static const enum_field_types column_type = MYSQL_TYPE_LONGLONG;
122  static const size_t length = 8;
123  static const bool am_unsigned = true;
124 };
125 
128 
130 typedef boost::shared_ptr<MySqlBinding> MySqlBindingPtr;
131 
154 public:
155 
159  enum_field_types getType() const {
160  return (bind_.buffer_type);
161  }
162 
171  MYSQL_BIND& getMySqlBinding() {
172  return (bind_);
173  }
174 
184  std::string getString() const;
185 
195  std::string getStringOrDefault(const std::string& default_value) const;
196 
206  data::ElementPtr getJSON() const;
207 
217  std::vector<uint8_t> getBlob() const;
218 
228  std::vector<uint8_t>
229  getBlobOrDefault(const std::vector<uint8_t>& default_value) const;
230 
243  template<typename T>
244  T getInteger() const {
245  // Make sure that the binding type is numeric.
246  validateAccess<T>();
247 
248  // Convert the buffer to a numeric type and then return a copy.
249  const T* value = reinterpret_cast<const T*>(&buffer_[0]);
250  return (*value);
251  }
252 
265  template<typename T>
266  T getIntegerOrDefault(T default_value) const {
267  if (amNull()) {
268  return (default_value);
269  }
270  return (getInteger<T>());
271  }
272 
282  boost::posix_time::ptime getTimestamp() const;
283 
293  boost::posix_time::ptime
294  getTimestampOrDefault(const boost::posix_time::ptime& default_value) const;
295 
299  bool amNull() const {
300  return (null_value_ == MLM_TRUE);
301  }
302 
309  static MySqlBindingPtr createString(const unsigned long length);
310 
316  static MySqlBindingPtr createString(const std::string& value);
317 
324  static MySqlBindingPtr condCreateString(const std::string& value);
325 
332  static MySqlBindingPtr createBlob(const unsigned long length);
333 
344  template<typename Iterator>
345  static MySqlBindingPtr createBlob(Iterator begin, Iterator end) {
346  MySqlBindingPtr binding(new MySqlBinding(MYSQL_TYPE_BLOB,
347  std::distance(begin, end)));
348  binding->setBufferValue(begin, end);
349  return (binding);
350  }
351 
358  template<typename T>
362  binding->setValue<T>(0);
363  return (binding);
364  }
365 
374  template<typename T>
375  static MySqlBindingPtr createInteger(T value) {
378  binding->setValue(value);
379  return (binding);
380  }
381 
391  template<typename T>
393  return (value == 0 ? createNull() : createInteger(value));
394  }
395 
400 
406  static MySqlBindingPtr createTimestamp(const boost::posix_time::ptime& timestamp);
407 
414  static MySqlBindingPtr createNull();
415 
421  static void convertToDatabaseTime(const time_t input_time,
422  MYSQL_TIME& output_time);
423 
443  static void convertToDatabaseTime(const time_t cltt,
444  const uint32_t valid_lifetime,
445  MYSQL_TIME& expire);
446 
464  static void convertFromDatabaseTime(const MYSQL_TIME& expire,
465  uint32_t valid_lifetime,
466  time_t& cltt);
467 
474  static boost::posix_time::ptime
475  convertFromDatabaseTime(const MYSQL_TIME& database_time);
476 
477 private:
478 
486  MySqlBinding(enum_field_types buffer_type, const size_t length);
487 
496  template<typename Iterator>
497  void setBufferValue(Iterator begin, Iterator end) {
498  length_ = std::distance(begin, end);
499  buffer_.assign(begin, end);
500  // It appears that the MySQL connectors sometimes require that the
501  // buffer is specified (set to a non-zero value), even if the buffer
502  // length is 0. We have found that setting the buffer to 0 value would
503  // cause the value inserted to the database be NULL. In order to avoid
504  // it, we simply make sure that the buffer length is at least 1 byte and
505  // provide the pointer to this byte within the binding.
506  if (buffer_.empty()) {
507  buffer_.resize(1);
508  }
509  bind_.buffer = &buffer_[0];
510  bind_.buffer_length = length_;
511  }
512 
516  void setBufferLength(const unsigned long length);
517 
524  template<typename T>
525  void setValue(T value) {
526  memcpy(static_cast<void*>(&buffer_[0]), reinterpret_cast<char*>(&value),
527  sizeof(value));
528  bind_.buffer = &buffer_[0];
529  bind_.is_unsigned = (MySqlBindingTraits<T>::am_unsigned ? MLM_TRUE : MLM_FALSE);
530  }
531 
536  void setTimestampValue(const boost::posix_time::ptime& timestamp);
537 
546  template<typename T>
547  void validateAccess() const {
548  // Can't retrieve null value.
549  if (amNull()) {
550  isc_throw(InvalidOperation, "retrieved value is null");
551  }
552  // The type of the accessor must match the stored data type.
554  isc_throw(InvalidOperation, "mismatched column type");
555  }
556  }
557 
559  std::vector<uint8_t> buffer_;
560 
562  unsigned long length_;
563 
565  my_bool null_value_;
566 
568  MYSQL_BIND bind_;
569 };
570 
572 typedef std::vector<MySqlBindingPtr> MySqlBindingCollection;
573 
574 
575 } // end of namespace isc::db
576 } // end of namespace isc
577 
578 #endif
static MySqlBindingPtr createNull()
Creates binding encapsulating a NULL value.
static MySqlBindingPtr createInteger(T value)
Creates binding of numeric type for sending data.
static MySqlBindingPtr createTimestamp()
Creates binding of timestamp type for receiving data.
static const enum_field_types column_type
Column type represented in MySQL C API.
Definition: mysql_binding.h:36
enum_field_types getType() const
Returns MySQL column type for the binding.
static MySqlBindingPtr createBlob(Iterator begin, Iterator end)
Creates binding of blob type for sending data.
static MySqlBindingPtr condCreateString(const std::string &value)
Conditionally creates binding of text type for sending data if provided value is not empty.
static void convertToDatabaseTime(const time_t input_time, MYSQL_TIME &output_time)
Converts time_t value to database time.
boost::shared_ptr< Element > ElementPtr
Definition: data.h:20
MYSQL_BIND & getMySqlBinding()
Returns reference to the native binding.
static MySqlBindingPtr createString(const unsigned long length)
Creates binding of text type for receiving data.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
const my_bool MLM_FALSE
MySQL false value.
static const size_t length
Length of data in this column.
Definition: mysql_binding.h:40
Trait class for column types supported in MySQL.
Definition: mysql_binding.h:34
T getInteger() const
Returns numeric value held in the binding.
std::string getStringOrDefault(const std::string &default_value) const
Returns value held in the binding as string.
boost::posix_time::ptime getTimestampOrDefault(const boost::posix_time::ptime &default_value) const
Returns timestamp value held in the binding.
static void convertFromDatabaseTime(const MYSQL_TIME &expire, uint32_t valid_lifetime, time_t &cltt)
Converts Database Time to Lease Times.
std::vector< uint8_t > getBlobOrDefault(const std::vector< uint8_t > &default_value) const
Returns value held in the binding as blob.
std::string getString() const
Returns value held in the binding as string.
Defines the logger used by the top-level component of kea-dhcp-ddns.
static const bool am_unsigned
Boolean value indicating if the numeric value is unsigned.
Definition: mysql_binding.h:43
std::vector< uint8_t > getBlob() const
Returns value held in the binding as blob.
static MySqlBindingPtr condCreateInteger(T value)
Conditionally creates binding of numeric type for sending data if provided value is not 0.
boost::posix_time::ptime getTimestamp() const
Returns timestamp value held in the binding.
std::vector< MySqlBindingPtr > MySqlBindingCollection
Collection of bindings.
boost::shared_ptr< MySqlBinding > MySqlBindingPtr
Shared pointer to the Binding class.
T getIntegerOrDefault(T default_value) const
Returns numeric value held in the binding.
data::ElementPtr getJSON() const
Returns value held in the binding as JSON.
static MySqlBindingPtr createBlob(const unsigned long length)
Creates binding of blob type for receiving data.
bool amNull() const
Checks if the bound value is NULL.
static MySqlBindingPtr createInteger()
Creates binding of numeric type for receiving data.
MySQL binding used in prepared statements.
const my_bool MLM_TRUE
MySQL true value.