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 
127 class MySqlBinding;
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
isc::db::MySqlBinding::getJSON
data::ElementPtr getJSON() const
Returns value held in the binding as JSON.
Definition: mysql_binding.cc:35
isc::db::MySqlBinding::getString
std::string getString() const
Returns value held in the binding as string.
Definition: mysql_binding.cc:17
isc::db::MySqlBindingTraits::am_unsigned
static const bool am_unsigned
Boolean value indicating if the numeric value is unsigned.
Definition: mysql_binding.h:43
isc::db::MySqlBinding::createString
static MySqlBindingPtr createString(const unsigned long length)
Creates binding of text type for receiving data.
Definition: mysql_binding.cc:80
isc::db::MySqlBindingTraits::length
static const size_t length
Length of data in this column.
Definition: mysql_binding.h:40
isc::db::MySqlBinding::getIntegerOrDefault
T getIntegerOrDefault(T default_value) const
Returns numeric value held in the binding.
Definition: mysql_binding.h:266
isc::db::MySqlBinding
MySQL binding used in prepared statements.
Definition: mysql_binding.h:153
isc::db::MySqlBinding::createInteger
static MySqlBindingPtr createInteger()
Creates binding of numeric type for receiving data.
Definition: mysql_binding.h:359
isc::db::MySqlBindingPtr
boost::shared_ptr< MySqlBinding > MySqlBindingPtr
Shared pointer to the Binding class.
Definition: mysql_binding.h:127
isc::db::MySqlBinding::condCreateString
static MySqlBindingPtr condCreateString(const std::string &value)
Conditionally creates binding of text type for sending data if provided value is not empty.
Definition: mysql_binding.cc:95
boost
Definition: io_service.h:12
isc::db::MySqlBinding::convertToDatabaseTime
static void convertToDatabaseTime(const time_t input_time, MYSQL_TIME &output_time)
Converts time_t value to database time.
Definition: mysql_binding.cc:128
isc::db::MySqlBinding::createNull
static MySqlBindingPtr createNull()
Creates binding encapsulating a NULL value.
Definition: mysql_binding.cc:122
isc
Defines the logger used by the top-level component of kea-dhcp-ddns.
Definition: agent_parser.cc:144
isc::db::MySqlBinding::getTimestamp
boost::posix_time::ptime getTimestamp() const
Returns timestamp value held in the binding.
Definition: mysql_binding.cc:62
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition: exceptions/exceptions.h:192
isc::db::MLM_FALSE
const my_bool MLM_FALSE
MySQL false value.
Definition: mysql_constants.h:20
isc::db::MySqlBinding::condCreateInteger
static MySqlBindingPtr condCreateInteger(T value)
Conditionally creates binding of numeric type for sending data if provided value is not 0.
Definition: mysql_binding.h:392
isc::db::MySqlBinding::getInteger
T getInteger() const
Returns numeric value held in the binding.
Definition: mysql_binding.h:244
isc::db::MySqlBinding::getStringOrDefault
std::string getStringOrDefault(const std::string &default_value) const
Returns value held in the binding as string.
Definition: mysql_binding.cc:27
isc::db::MySqlBindingTraits
Trait class for column types supported in MySQL.
Definition: mysql_binding.h:34
isc::db::MySqlBinding::getTimestampOrDefault
boost::posix_time::ptime getTimestampOrDefault(const boost::posix_time::ptime &default_value) const
Returns timestamp value held in the binding.
Definition: mysql_binding.cc:72
isc::db::MySqlBindingCollection
std::vector< MySqlBindingPtr > MySqlBindingCollection
Collection of bindings.
Definition: mysql_binding.h:572
isc::db::MySqlBinding::getMySqlBinding
MYSQL_BIND & getMySqlBinding()
Returns reference to the native binding.
Definition: mysql_binding.h:171
isc::db::MLM_TRUE
const my_bool MLM_TRUE
MySQL true value.
Definition: mysql_constants.h:23
isc::db::MySqlBinding::getBlobOrDefault
std::vector< uint8_t > getBlobOrDefault(const std::vector< uint8_t > &default_value) const
Returns value held in the binding as blob.
Definition: mysql_binding.cc:54
isc::db::MySqlBinding::createBlob
static MySqlBindingPtr createBlob(Iterator begin, Iterator end)
Creates binding of blob type for sending data.
Definition: mysql_binding.h:345
mysql_constants.h
database_connection.h
isc::db::MySqlBinding::convertFromDatabaseTime
static void convertFromDatabaseTime(const MYSQL_TIME &expire, uint32_t valid_lifetime, time_t &cltt)
Converts Database Time to Lease Times.
Definition: mysql_binding.cc:180
isc::db::MySqlBinding::getBlob
std::vector< uint8_t > getBlob() const
Returns value held in the binding as blob.
Definition: mysql_binding.cc:44
data.h
isc::db::MySqlBindingTraits::column_type
static const enum_field_types column_type
Column type represented in MySQL C API.
Definition: mysql_binding.h:36
exceptions.h
isc::db::MySqlBinding::createTimestamp
static MySqlBindingPtr createTimestamp()
Creates binding of timestamp type for receiving data.
Definition: mysql_binding.cc:115
isc::db::MySqlBinding::createBlob
static MySqlBindingPtr createBlob(const unsigned long length)
Creates binding of blob type for receiving data.
Definition: mysql_binding.cc:100
isc::data::ElementPtr
boost::shared_ptr< Element > ElementPtr
Definition: data.h:20
isc::db::MySqlBinding::createInteger
static MySqlBindingPtr createInteger(T value)
Creates binding of numeric type for sending data.
Definition: mysql_binding.h:375
isc::db::MySqlBinding::amNull
bool amNull() const
Checks if the bound value is NULL.
Definition: mysql_binding.h:299
isc::db::MySqlBinding::getType
enum_field_types getType() const
Returns MySQL column type for the binding.
Definition: mysql_binding.h:159