Kea  1.9.9-git
mysql_binding.h
Go to the documentation of this file.
1 // Copyright (C) 2018-2019,2021 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 <asiolink/io_address.h>
11 #include <cc/data.h>
13 #include <exceptions/exceptions.h>
14 #include <util/optional.h>
15 #include <boost/date_time/posix_time/conversion.hpp>
16 #include <boost/date_time/posix_time/posix_time.hpp>
17 #include <boost/shared_ptr.hpp>
18 #include <mysql/mysql_constants.h>
19 #include <mysql.h>
20 #include <mysqld_error.h>
21 #include <cstdint>
22 #include <iterator>
23 #include <string>
24 #include <vector>
25 
26 namespace isc {
27 namespace db {
28 
35 template<typename T>
38  static const enum_field_types column_type = MYSQL_TYPE_BLOB;
42  static const size_t length = 0;
45  static const bool am_unsigned = false;
46 };
47 
49 template<>
50 struct MySqlBindingTraits<std::string> {
51  static const enum_field_types column_type = MYSQL_TYPE_STRING;
52  static const size_t length = 0;
53  static const bool am_unsigned = false;
54 };
55 
57 template<>
58 struct MySqlBindingTraits<boost::posix_time::ptime> {
59  static const enum_field_types column_type = MYSQL_TYPE_TIMESTAMP;
60  static const size_t length = sizeof(MYSQL_TIME);
61  static const bool am_unsignged = false;
62 };
63 
65 template<>
66 struct MySqlBindingTraits<int8_t> {
67  static const enum_field_types column_type = MYSQL_TYPE_TINY;
68  static const size_t length = 1;
69  static const bool am_unsigned = false;
70 };
71 
73 template<>
74 struct MySqlBindingTraits<uint8_t> {
75  static const enum_field_types column_type = MYSQL_TYPE_TINY;
76  static const size_t length = 1;
77  static const bool am_unsigned = true;
78 };
79 
81 template<>
82 struct MySqlBindingTraits<int16_t> {
83  static const enum_field_types column_type = MYSQL_TYPE_SHORT;
84  static const size_t length = 2;
85  static const bool am_unsigned = false;
86 };
87 
89 template<>
90 struct MySqlBindingTraits<uint16_t> {
91  static const enum_field_types column_type = MYSQL_TYPE_SHORT;
92  static const size_t length = 2;
93  static const bool am_unsigned = true;
94 };
95 
97 template<>
98 struct MySqlBindingTraits<int32_t> {
99  static const enum_field_types column_type = MYSQL_TYPE_LONG;
100  static const size_t length = 4;
101  static const bool am_unsigned = false;
102 };
103 
105 template<>
106 struct MySqlBindingTraits<uint32_t> {
107  static const enum_field_types column_type = MYSQL_TYPE_LONG;
108  static const size_t length = 4;
109  static const bool am_unsigned = true;
110 };
111 
113 template<>
114 struct MySqlBindingTraits<int64_t> {
115  static const enum_field_types column_type = MYSQL_TYPE_LONGLONG;
116  static const size_t length = 8;
117  static const bool am_unsigned = false;
118 };
119 
121 template<>
122 struct MySqlBindingTraits<uint64_t> {
123  static const enum_field_types column_type = MYSQL_TYPE_LONGLONG;
124  static const size_t length = 8;
125  static const bool am_unsigned = true;
126 };
127 
128 template<>
129 struct MySqlBindingTraits<float> {
130  static const enum_field_types column_type = MYSQL_TYPE_FLOAT;
131  static const size_t length = 4;
132  static const bool am_unsigned = false;
133 };
134 
137 
139 typedef boost::shared_ptr<MySqlBinding> MySqlBindingPtr;
140 
163 public:
164 
168  enum_field_types getType() const {
169  return (bind_.buffer_type);
170  }
171 
180  MYSQL_BIND& getMySqlBinding() {
181  return (bind_);
182  }
183 
193  std::string getString() const;
194 
204  std::string getStringOrDefault(const std::string& default_value) const;
205 
215  data::ElementPtr getJSON() const;
216 
226  std::vector<uint8_t> getBlob() const;
227 
237  std::vector<uint8_t>
238  getBlobOrDefault(const std::vector<uint8_t>& default_value) const;
239 
252  template<typename T>
253  T getInteger() const {
254  // Make sure that the binding type is numeric.
255  validateAccess<T>();
256 
257  // Convert the buffer to a numeric type and then return a copy.
258  const T* value = reinterpret_cast<const T*>(&buffer_[0]);
259  return (*value);
260  }
261 
274  template<typename T>
275  T getIntegerOrDefault(T default_value) const {
276  if (amNull()) {
277  return (default_value);
278  }
279  return (getInteger<T>());
280  }
281 
291  float getFloat() const;
292 
302  bool getBool() const {
303  return (static_cast<bool>(getInteger<uint8_t>()));
304  }
305 
315  boost::posix_time::ptime getTimestamp() const;
316 
326  boost::posix_time::ptime
327  getTimestampOrDefault(const boost::posix_time::ptime& default_value) const;
328 
332  bool amNull() const {
333  return (null_value_ == MLM_TRUE);
334  }
335 
342  static MySqlBindingPtr createString(const unsigned long length);
343 
349  static MySqlBindingPtr createString(const std::string& value);
350 
357  static MySqlBindingPtr condCreateString(const util::Optional<std::string>& value);
358 
365  static MySqlBindingPtr createBlob(const unsigned long length);
366 
377  template<typename Iterator>
378  static MySqlBindingPtr createBlob(Iterator begin, Iterator end) {
379  MySqlBindingPtr binding(new MySqlBinding(MYSQL_TYPE_BLOB,
380  std::distance(begin, end)));
381  binding->setBufferValue(begin, end);
382  return (binding);
383  }
384 
391  template<typename T>
392  static MySqlBindingPtr createInteger() {
393  MySqlBindingPtr binding(new MySqlBinding(MySqlBindingTraits<T>::column_type,
395  binding->setValue<T>(0);
396  return (binding);
397  }
398 
407  template<typename T>
408  static MySqlBindingPtr createInteger(T value) {
409  MySqlBindingPtr binding(new MySqlBinding(MySqlBindingTraits<T>::column_type,
411  binding->setValue(value);
412  return (binding);
413  }
414 
424  template<typename T>
425  static MySqlBindingPtr condCreateInteger(const util::Optional<T>& value) {
426  return (value.unspecified() ? createNull() : createInteger<T>(value.get()));
427  }
428 
434  static MySqlBindingPtr createFloat(const float value);
435 
444  template<typename T>
445  static MySqlBindingPtr condCreateFloat(const util::Optional<T>& value) {
446  return (value.unspecified() ? createNull() :
447  createInteger<float> (static_cast<float>(value.get())));
448  }
449 
456  static MySqlBindingPtr createBool(const bool value);
457 
464  static MySqlBindingPtr condCreateBool(const util::Optional<bool>& value);
465 
472  static MySqlBindingPtr
474 
478  static MySqlBindingPtr createTimestamp();
479 
485  static MySqlBindingPtr createTimestamp(const boost::posix_time::ptime& timestamp);
486 
493  static MySqlBindingPtr createNull();
494 
500  static void convertToDatabaseTime(const time_t input_time,
501  MYSQL_TIME& output_time);
502 
508  static void convertToDatabaseTime(const boost::posix_time::ptime& input_time,
509  MYSQL_TIME& output_time);
510 
530  static void convertToDatabaseTime(const time_t cltt,
531  const uint32_t valid_lifetime,
532  MYSQL_TIME& expire);
533 
551  static void convertFromDatabaseTime(const MYSQL_TIME& expire,
552  uint32_t valid_lifetime,
553  time_t& cltt);
554 
561  static boost::posix_time::ptime
562  convertFromDatabaseTime(const MYSQL_TIME& database_time);
563 
564 private:
565 
573  MySqlBinding(enum_field_types buffer_type, const size_t length);
574 
583  template<typename Iterator>
584  void setBufferValue(Iterator begin, Iterator end) {
585  length_ = std::distance(begin, end);
586  buffer_.assign(begin, end);
587  // It appears that the MySQL connectors sometimes require that the
588  // buffer is specified (set to a non-zero value), even if the buffer
589  // length is 0. We have found that setting the buffer to 0 value would
590  // cause the value inserted to the database be NULL. In order to avoid
591  // it, we simply make sure that the buffer length is at least 1 byte and
592  // provide the pointer to this byte within the binding.
593  if (buffer_.empty()) {
594  buffer_.resize(1);
595  }
596  bind_.buffer = &buffer_[0];
597  bind_.buffer_length = length_;
598  }
599 
603  void setBufferLength(const unsigned long length);
604 
611  template<typename T>
612  void setValue(T value) {
613  memcpy(static_cast<void*>(&buffer_[0]), reinterpret_cast<char*>(&value),
614  sizeof(value));
615  bind_.buffer = &buffer_[0];
616  bind_.is_unsigned = (MySqlBindingTraits<T>::am_unsigned ? MLM_TRUE : MLM_FALSE);
617  }
618 
623  void setTimestampValue(const boost::posix_time::ptime& timestamp);
624 
633  template<typename T>
634  void validateAccess() const {
635  // Can't retrieve null value.
636  if (amNull()) {
637  isc_throw(InvalidOperation, "retrieved value is null");
638  }
639  // The type of the accessor must match the stored data type.
640  if (MySqlBindingTraits<T>::column_type != getType()) {
641  isc_throw(InvalidOperation, "mismatched column type");
642  }
643  }
644 
646  std::vector<uint8_t> buffer_;
647 
649  unsigned long length_;
650 
652  my_bool null_value_;
653 
655  MYSQL_BIND bind_;
656 };
657 
659 typedef std::vector<MySqlBindingPtr> MySqlBindingCollection;
660 
661 
662 } // end of namespace isc::db
663 } // end of namespace isc
664 
665 #endif
std::vector< uint8_t > getBlobOrDefault(const std::vector< uint8_t > &default_value) const
Returns value held in the binding as blob.
boost::posix_time::ptime getTimestampOrDefault(const boost::posix_time::ptime &default_value) const
Returns timestamp value held in the binding.
static MySqlBindingPtr createNull()
Creates binding encapsulating a NULL value.
static MySqlBindingPtr createInteger(T value)
Creates binding of numeric type for sending data.
bool my_bool
my_bool type in MySQL 8.x.
void unspecified(bool unspecified)
Modifies the flag that indicates whether the value is specified or unspecified.
Definition: optional.h:121
std::vector< uint8_t > getBlob() const
Returns value held in the binding as blob.
std::string getString() const
Returns value held in the binding as string.
T getIntegerOrDefault(T default_value) const
Returns numeric value held in the binding.
static MySqlBindingPtr createTimestamp()
Creates binding of timestamp type for receiving data.
bool amNull() const
Checks if the bound value is NULL.
static const enum_field_types column_type
Column type represented in MySQL C API.
Definition: mysql_binding.h:38
T getInteger() const
Returns numeric value held in the binding.
static MySqlBindingPtr createBlob(Iterator begin, Iterator end)
Creates binding of blob type for sending data.
bool getBool() const
Returns boolean value held in the binding.
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
STL namespace.
enum_field_types getType() const
Returns MySQL column type for the binding.
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 MySqlBindingPtr condCreateBool(const util::Optional< bool > &value)
Conditionally creates binding of uint8_t type representing a boolean value if provided value is speci...
static const size_t length
Length of data in this column.
Definition: mysql_binding.h:42
static MySqlBindingPtr condCreateInteger(const util::Optional< T > &value)
Conditionally creates binding of numeric type for sending data if provided value is specified...
Trait class for column types supported in MySQL.
Definition: mysql_binding.h:36
static void convertFromDatabaseTime(const MYSQL_TIME &expire, uint32_t valid_lifetime, time_t &cltt)
Converts Database Time to Lease Times.
static MySqlBindingPtr condCreateFloat(const util::Optional< T > &value)
Conditionally creates binding of float type for sending data if provided value is specified...
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:45
static MySqlBindingPtr condCreateString(const util::Optional< std::string > &value)
Conditionally creates binding of text type for sending data if provided value is unspecified.
T get() const
Retrieves the encapsulated value.
Definition: optional.h:112
boost::posix_time::ptime getTimestamp() const
Returns timestamp value held in the binding.
static MySqlBindingPtr condCreateIPv4Address(const util::Optional< asiolink::IOAddress > &value)
Conditionally creates binding of uint32_t type representing an IPv4 address if provided value is spec...
float getFloat() const
Returns float value held in the binding.
static MySqlBindingPtr createFloat(const float value)
Creates binding having a float type for sending data.
static MySqlBindingPtr createBool(const bool value)
Creates binding having a bool type for sending data.
std::string getStringOrDefault(const std::string &default_value) const
Returns value held in the binding as string.
std::vector< MySqlBindingPtr > MySqlBindingCollection
Collection of bindings.
boost::shared_ptr< MySqlBinding > MySqlBindingPtr
Shared pointer to the Binding class.
static MySqlBindingPtr createBlob(const unsigned long length)
Creates binding of blob type for receiving data.
static MySqlBindingPtr createInteger()
Creates binding of numeric type for receiving data.
MySQL binding used in prepared statements.
data::ElementPtr getJSON() const
Returns value held in the binding as JSON.
const my_bool MLM_TRUE
MySQL true value.