Kea 1.5.0
mysql_binding.cc
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#include <config.h>
8
10
11using namespace isc::data;
12
13namespace isc {
14namespace db {
15
16std::string
18 // Make sure the binding type is text.
19 validateAccess<std::string>();
20 if (length_ == 0) {
21 return (std::string());
22 }
23 return (std::string(buffer_.begin(), buffer_.begin() + length_));
24}
25
26std::string
27MySqlBinding::getStringOrDefault(const std::string& default_value) const {
28 if (amNull()) {
29 return (default_value);
30 }
31 return (getString());
32}
33
36 if (amNull()) {
37 return (ElementPtr());
38 }
39 std::string s = getString();
40 return (Element::fromJSON(s));
41}
42
43std::vector<uint8_t>
45 // Make sure the binding type is blob.
46 validateAccess<std::vector<uint8_t> >();
47 if (length_ == 0) {
48 return (std::vector<uint8_t>());
49 }
50 return (std::vector<uint8_t>(buffer_.begin(), buffer_.begin() + length_));
51}
52
53std::vector<uint8_t>
54MySqlBinding::getBlobOrDefault(const std::vector<uint8_t>& default_value) const {
55 if (amNull()) {
56 return (default_value);
57 }
58 return (getBlob());
59}
60
61boost::posix_time::ptime
63 // Make sure the binding type is timestamp.
64 validateAccess<boost::posix_time::ptime>();
65 // Copy the buffer contents into native timestamp structure and
66 // then convert it to posix time.
67 const MYSQL_TIME* database_time = reinterpret_cast<const MYSQL_TIME*>(&buffer_[0]);
68 return (convertFromDatabaseTime(*database_time));
69}
70
71boost::posix_time::ptime
72MySqlBinding::getTimestampOrDefault(const boost::posix_time::ptime& default_value) const {
73 if (amNull()) {
74 return (default_value);
75 }
76 return (getTimestamp());
77}
78
80MySqlBinding::createString(const unsigned long length) {
82 length));
83 return (binding);
84}
85
87MySqlBinding::createString(const std::string& value) {
89 value.size()));
90 binding->setBufferValue(value.begin(), value.end());
91 return (binding);
92}
93
95MySqlBinding::condCreateString(const std::string& value) {
96 return (value.empty() ? MySqlBinding::createNull() : createString(value));
97}
98
100MySqlBinding::createBlob(const unsigned long length) {
101 MySqlBindingPtr binding(new MySqlBinding(MySqlBindingTraits<std::vector<uint8_t> >::column_type,
102 length));
103 return (binding);
104}
105
107MySqlBinding::createTimestamp(const boost::posix_time::ptime& timestamp) {
110 binding->setTimestampValue(timestamp);
111 return (binding);
112}
113
118 return (binding);
119}
120
123 MySqlBindingPtr binding(new MySqlBinding(MYSQL_TYPE_NULL, 0));
124 return (binding);
125}
126
127void
129 MYSQL_TIME& output_time) {
130
131 // Convert to broken-out time
132 struct tm time_tm;
133 (void) localtime_r(&input_time, &time_tm);
134
135 // Place in output expire structure.
136 output_time.year = time_tm.tm_year + 1900;
137 output_time.month = time_tm.tm_mon + 1; // Note different base
138 output_time.day = time_tm.tm_mday;
139 output_time.hour = time_tm.tm_hour;
140 output_time.minute = time_tm.tm_min;
141 output_time.second = time_tm.tm_sec;
142 output_time.second_part = 0; // No fractional seconds
143 output_time.neg = my_bool(0); // Not negative
144}
145
146void
148 const uint32_t valid_lifetime,
149 MYSQL_TIME& expire) {
150
151 // Calculate expiry time. Store it in the 64-bit value so as we can detect
152 // overflows.
153 int64_t expire_time_64 = static_cast<int64_t>(cltt) +
154 static_cast<int64_t>(valid_lifetime);
155
156 // Even on 64-bit systems MySQL doesn't seem to accept the timestamps
157 // beyond the max value of int32_t.
158 if (expire_time_64 > DatabaseConnection::MAX_DB_TIME) {
159 isc_throw(BadValue, "Time value is too large: " << expire_time_64);
160 }
161
162 const time_t expire_time = static_cast<const time_t>(expire_time_64);
163
164 // Convert to broken-out time
165 struct tm expire_tm;
166 (void) localtime_r(&expire_time, &expire_tm);
167
168 // Place in output expire structure.
169 expire.year = expire_tm.tm_year + 1900;
170 expire.month = expire_tm.tm_mon + 1; // Note different base
171 expire.day = expire_tm.tm_mday;
172 expire.hour = expire_tm.tm_hour;
173 expire.minute = expire_tm.tm_min;
174 expire.second = expire_tm.tm_sec;
175 expire.second_part = 0; // No fractional seconds
176 expire.neg = my_bool(0); // Not negative
177}
178
179void
181 uint32_t valid_lifetime,
182 time_t& cltt) {
183 // Copy across fields from MYSQL_TIME structure.
184 struct tm expire_tm;
185 memset(&expire_tm, 0, sizeof(expire_tm));
186
187 expire_tm.tm_year = expire.year - 1900;
188 expire_tm.tm_mon = expire.month - 1;
189 expire_tm.tm_mday = expire.day;
190 expire_tm.tm_hour = expire.hour;
191 expire_tm.tm_min = expire.minute;
192 expire_tm.tm_sec = expire.second;
193 expire_tm.tm_isdst = -1; // Let the system work out about DST
194
195 // Convert to local time
196 cltt = mktime(&expire_tm) - valid_lifetime;
197}
198
199boost::posix_time::ptime
200MySqlBinding::convertFromDatabaseTime(const MYSQL_TIME& database_time) {
201 // Copy across fields from MYSQL_TIME structure.
202 struct tm converted_tm;
203 memset(&converted_tm, 0, sizeof(converted_tm));
204
205 converted_tm.tm_year = database_time.year - 1900;
206 converted_tm.tm_mon = database_time.month - 1;
207 converted_tm.tm_mday = database_time.day;
208 converted_tm.tm_hour = database_time.hour;
209 converted_tm.tm_min = database_time.minute;
210 converted_tm.tm_sec = database_time.second;
211 converted_tm.tm_isdst = -1; // Let the system work out about DST
212
213 // Convert to local time
214 return (boost::posix_time::ptime_from_tm(converted_tm));
215}
216
217MySqlBinding::MySqlBinding(enum_field_types buffer_type,
218 const size_t length)
219 : buffer_(length), length_(length),
220 null_value_(buffer_type == MYSQL_TYPE_NULL) {
221 memset(&bind_, 0, sizeof(MYSQL_BIND));
222 bind_.buffer_type = buffer_type;
223
224 if (buffer_type != MYSQL_TYPE_NULL) {
225 bind_.buffer = &buffer_[0];
226 bind_.buffer_length = length_;
227 bind_.length = &length_;
228 bind_.is_null = &null_value_;
229 }
230}
231
232void
233MySqlBinding::setBufferLength(const unsigned long length) {
234 length_ = length;
235 // It appears that the MySQL connectors sometimes require that the
236 // buffer is specified (set to a non-zero value), even if the buffer
237 // length is 0. We have found that setting the buffer to 0 value would
238 // cause the value inserted to the database be NULL. In order to avoid
239 // it, we simply make sure that the buffer length is at least 1 byte and
240 // provide the pointer to this byte within the binding.
241 buffer_.resize(length_ > 0 ? length_ : 1);
242 bind_.buffer = &buffer_[0];
243 bind_.buffer_length = length_;
244}
245
246void
247MySqlBinding::setTimestampValue(const boost::posix_time::ptime& timestamp) {
248 // Convert timestamp to tm structure.
249 tm td_tm = to_tm(timestamp);
250 // Convert tm value to time_t.
251 time_t tt = mktime(&td_tm);
252 // Convert time_t to database time.
253 MYSQL_TIME database_time;
254 convertToDatabaseTime(tt, database_time);
255 // Copy database time into the buffer.
256 memcpy(static_cast<void*>(&buffer_[0]), reinterpret_cast<char*>(&database_time),
257 sizeof(MYSQL_TIME));
258 bind_.buffer = &buffer_[0];
259}
260
261} // end of namespace isc::db
262} // end of namespace isc
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
static ElementPtr fromJSON(const std::string &in, bool preproc=false)
These functions will parse the given string (JSON) representation of a compound element.
Definition: data.cc:750
static const time_t MAX_DB_TIME
Defines maximum value for time that can be reliably stored.
MySQL binding used in prepared statements.
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::vector< uint8_t > getBlob() const
Returns value held in the binding as blob.
static MySqlBindingPtr createString(const unsigned long length)
Creates binding of text type for receiving data.
bool amNull() const
Checks if the bound value is NULL.
std::string getString() const
Returns value held in the binding as string.
data::ElementPtr getJSON() const
Returns value held in the binding as JSON.
std::string getStringOrDefault(const std::string &default_value) const
Returns value held in the binding as string.
static MySqlBindingPtr condCreateString(const std::string &value)
Conditionally creates binding of text type for sending data if provided value is not empty.
static MySqlBindingPtr createTimestamp()
Creates binding of timestamp type for receiving data.
boost::posix_time::ptime getTimestamp() const
Returns timestamp value held in the binding.
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 createBlob(const unsigned long length)
Creates binding of blob type for receiving data.
static void convertToDatabaseTime(const time_t input_time, MYSQL_TIME &output_time)
Converts time_t value to database time.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< Element > ElementPtr
Definition: data.h:22
boost::shared_ptr< MySqlBinding > MySqlBindingPtr
Shared pointer to the Binding class.
Defines the logger used by the top-level component of kea-dhcp-ddns.
Trait class for column types supported in MySQL.
Definition: mysql_binding.h:34