Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Kea
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
Operations
Operations
Incidents
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Sebastian Schrader
Kea
Commits
479791d7
Commit
479791d7
authored
Sep 18, 2018
by
Marcin Siodelski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[#93,!35] Extended MySqlConnection with generic query functions.
parent
9994f64b
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
1362 additions
and
214 deletions
+1362
-214
configure.ac
configure.ac
+3
-0
src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc
src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc
+3
-126
src/lib/mysql/Makefile.am
src/lib/mysql/Makefile.am
+3
-1
src/lib/mysql/mysql_binding.cc
src/lib/mysql/mysql_binding.cc
+216
-0
src/lib/mysql/mysql_binding.h
src/lib/mysql/mysql_binding.h
+479
-0
src/lib/mysql/mysql_connection.cc
src/lib/mysql/mysql_connection.cc
+4
-63
src/lib/mysql/mysql_connection.h
src/lib/mysql/mysql_connection.h
+172
-24
src/lib/mysql/mysql_constants.h
src/lib/mysql/mysql_constants.h
+44
-0
src/lib/mysql/tests/.gitignore
src/lib/mysql/tests/.gitignore
+1
-0
src/lib/mysql/tests/Makefile.am
src/lib/mysql/tests/Makefile.am
+40
-0
src/lib/mysql/tests/mysql_connection_unittest.cc
src/lib/mysql/tests/mysql_connection_unittest.cc
+377
-0
src/lib/mysql/tests/run_unittests.cc
src/lib/mysql/tests/run_unittests.cc
+20
-0
No files found.
configure.ac
View file @
479791d7
...
...
@@ -1529,6 +1529,8 @@ AC_CONFIG_FILES([Makefile
src/hooks/dhcp/high_availability/tests/Makefile
src/hooks/dhcp/lease_cmds/Makefile
src/hooks/dhcp/lease_cmds/tests/Makefile
src/hooks/dhcp/mysql_cb/Makefile
src/hooks/dhcp/mysql_cb/tests/Makefile
src/hooks/dhcp/user_chk/Makefile
src/hooks/dhcp/user_chk/tests/Makefile
src/hooks/dhcp/user_chk/tests/test_data_files_config.h
...
...
@@ -1593,6 +1595,7 @@ AC_CONFIG_FILES([Makefile
src/lib/log/tests/tempdir.h
src/lib/mysql/Makefile
src/lib/mysql/testutils/Makefile
src/lib/mysql/tests/Makefile
src/lib/pgsql/Makefile
src/lib/pgsql/tests/Makefile
src/lib/pgsql/testutils/Makefile
...
...
src/hooks/dhcp/mysql_cb/mysql_cb_dhcp4.cc
View file @
479791d7
...
...
@@ -17,128 +17,6 @@ using namespace isc::db;
namespace
{
class
Binding
;
typedef
boost
::
shared_ptr
<
Binding
>
BindingPtr
;
class
Binding
{
public:
enum_field_types
getType
()
const
{
return
(
bind_
.
buffer_type
);
}
MYSQL_BIND
&
getMySqlBinding
()
{
return
(
bind_
);
}
void
setBufferValue
(
const
std
::
string
&
value
)
{
buffer_
.
assign
(
value
.
begin
(),
value
.
end
());
bind_
.
buffer
=
&
buffer_
[
0
];
bind_
.
buffer_length
=
value
.
size
();
}
template
<
typename
T
>
T
getValue
()
const
{
const
T
*
value
=
reinterpret_cast
<
const
T
*>
(
&
buffer_
[
0
]);
return
(
*
value
);
}
bool
amNull
()
const
{
return
(
null_value_
==
MLM_TRUE
);
}
static
BindingPtr
createString
(
const
unsigned
long
length
=
512
)
{
BindingPtr
binding
(
new
Binding
(
MYSQL_TYPE_STRING
));
binding
->
setBufferLength
(
length
);
return
(
binding
);
}
static
BindingPtr
createString
(
const
std
::
string
&
value
)
{
BindingPtr
binding
(
new
Binding
(
MYSQL_TYPE_STRING
));
binding
->
setBufferValue
(
value
);
return
(
binding
);
}
static
BindingPtr
createTimestamp
()
{
BindingPtr
binding
(
new
Binding
(
MYSQL_TYPE_TIMESTAMP
));
binding
->
setBufferLength
(
sizeof
(
MYSQL_TIME
));
return
(
binding
);
}
private:
Binding
(
enum_field_types
buffer_type
)
:
buffer_
(),
length_
(
0
),
null_value_
(
MLM_FALSE
)
{
bind_
.
buffer_type
=
buffer_type
;
bind_
.
length
=
&
length_
;
bind_
.
is_null
=
&
null_value_
;
}
void
setBufferLength
(
const
unsigned
long
length
)
{
length_
=
length
;
buffer_
.
resize
(
length_
);
bind_
.
buffer
=
&
buffer_
[
0
];
bind_
.
buffer_length
=
length_
;
}
std
::
vector
<
uint8_t
>
buffer_
;
unsigned
long
length_
;
my_bool
null_value_
;
MYSQL_BIND
bind_
;
};
typedef
std
::
vector
<
BindingPtr
>
BindingCollection
;
class
DatabaseExchange
{
public:
typedef
std
::
function
<
void
()
>
ConsumeResultFun
;
void
selectQuery
(
MYSQL_STMT
*
statement
,
const
BindingCollection
&
in_bindings
,
BindingCollection
&
out_bindings
,
ConsumeResultFun
process_result
)
{
std
::
vector
<
MYSQL_BIND
>
in_bind_vec
;
for
(
BindingPtr
in_binding
:
in_bindings
)
{
in_bind_vec
.
push_back
(
in_binding
->
getMySqlBinding
());
}
int
status
=
0
;
if
(
!
in_bind_vec
.
empty
())
{
status
=
mysql_stmt_bind_param
(
statement
,
&
in_bind_vec
[
0
]);
}
std
::
vector
<
MYSQL_BIND
>
out_bind_vec
;
for
(
BindingPtr
out_binding
:
out_bindings
)
{
out_bind_vec
.
push_back
(
out_binding
->
getMySqlBinding
());
}
if
(
!
out_bind_vec
.
empty
())
{
status
=
mysql_stmt_bind_result
(
statement
,
&
out_bind_vec
[
0
]);
}
status
=
mysql_stmt_execute
(
statement
);
status
=
mysql_stmt_store_result
(
statement
);
MySqlFreeResult
fetch_release
(
statement
);
while
((
status
=
mysql_stmt_fetch
(
statement
))
==
MLM_MYSQL_FETCH_SUCCESS
)
{
try
{
process_result
();
}
catch
(...)
{
throw
;
}
}
}
};
}
namespace
isc
{
...
...
@@ -252,10 +130,9 @@ MySqlConfigBackendDHCPv4::getSubnet4(const ServerSelector& selector,
BindingCollection
out_bindings
;
out_bindings
.
push_back
(
Binding
::
createString
());
DatabaseExchange
xchg
;
xchg
.
selectQuery
(
impl_
->
conn_
.
statements_
[
MySqlConfigBackendDHCPv4Impl
::
GET_SUBNET4_ID
],
in_bindings
,
out_bindings
,
[
&
out_bindings
]()
{
impl_
->
conn_
.
selectQuery
(
MySqlConfigBackendDHCPv4Impl
::
GET_SUBNET4_ID
,
in_bindings
,
out_bindings
,
[
&
out_bindings
]()
{
uint32_t
hostname
=
out_bindings
[
0
]
->
getValue
<
uint32_t
>
();
});
...
...
src/lib/mysql/Makefile.am
View file @
479791d7
SUBDIRS
=
.
testutils
SUBDIRS
=
.
testutils
tests
AM_CPPFLAGS
=
-I
$(top_srcdir)
/src/lib
-I
$(top_builddir)
/src/lib
AM_CPPFLAGS
+=
$(BOOST_INCLUDES)
$(MYSQL_CPPFLAGS)
...
...
@@ -9,6 +9,8 @@ CLEANFILES = *.gcno *.gcda
lib_LTLIBRARIES
=
libkea-mysql.la
libkea_mysql_la_SOURCES
=
mysql_connection.cc mysql_connection.h
libkea_mysql_la_SOURCES
+=
mysql_binding.cc mysql_binding.h
libkea_mysql_la_SOURCES
+=
mysql_constants.h
libkea_mysql_la_LIBADD
=
$(top_builddir)
/src/lib/database/libkea-database.la
libkea_mysql_la_LIBADD
+=
$(top_builddir)
/src/lib/cc/libkea-cc.la
...
...
src/lib/mysql/mysql_binding.cc
0 → 100644
View file @
479791d7
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
#include <mysql/mysql_binding.h>
namespace
isc
{
namespace
db
{
std
::
string
MySqlBinding
::
getString
()
const
{
// Make sure the binding type is text.
validateAccess
<
std
::
string
>
();
if
(
length_
==
0
)
{
return
(
std
::
string
());
}
return
(
std
::
string
(
buffer_
.
begin
(),
buffer_
.
begin
()
+
length_
));
}
std
::
vector
<
uint8_t
>
MySqlBinding
::
getBlob
()
const
{
// Make sure the binding type is blob.
validateAccess
<
std
::
vector
<
uint8_t
>
>
();
if
(
length_
==
0
)
{
return
(
std
::
vector
<
uint8_t
>
());
}
return
(
std
::
vector
<
uint8_t
>
(
buffer_
.
begin
(),
buffer_
.
begin
()
+
length_
));
}
boost
::
posix_time
::
ptime
MySqlBinding
::
getTimestamp
()
const
{
// Make sure the binding type is timestamp.
validateAccess
<
boost
::
posix_time
::
ptime
>
();
// Copy the buffer contents into native timestamp structure and
// then convert it to posix time.
const
MYSQL_TIME
*
database_time
=
reinterpret_cast
<
const
MYSQL_TIME
*>
(
&
buffer_
[
0
]);
return
(
convertFromDatabaseTime
(
*
database_time
));
}
MySqlBindingPtr
MySqlBinding
::
createString
(
const
unsigned
long
length
)
{
MySqlBindingPtr
binding
(
new
MySqlBinding
(
MySqlBindingTraits
<
std
::
string
>::
column_type
,
length
));
return
(
binding
);
}
MySqlBindingPtr
MySqlBinding
::
createString
(
const
std
::
string
&
value
)
{
MySqlBindingPtr
binding
(
new
MySqlBinding
(
MySqlBindingTraits
<
std
::
string
>::
column_type
,
value
.
size
()));
binding
->
setBufferValue
(
value
.
begin
(),
value
.
end
());
return
(
binding
);
}
MySqlBindingPtr
MySqlBinding
::
createBlob
(
const
unsigned
long
length
)
{
MySqlBindingPtr
binding
(
new
MySqlBinding
(
MySqlBindingTraits
<
std
::
vector
<
uint8_t
>
>::
column_type
,
length
));
return
(
binding
);
}
MySqlBindingPtr
MySqlBinding
::
createTimestamp
(
const
boost
::
posix_time
::
ptime
&
timestamp
)
{
MySqlBindingPtr
binding
(
new
MySqlBinding
(
MySqlBindingTraits
<
boost
::
posix_time
::
ptime
>::
column_type
,
MySqlBindingTraits
<
boost
::
posix_time
::
ptime
>::
length
));
binding
->
setTimestampValue
(
timestamp
);
return
(
binding
);
}
MySqlBindingPtr
MySqlBinding
::
createTimestamp
()
{
MySqlBindingPtr
binding
(
new
MySqlBinding
(
MySqlBindingTraits
<
boost
::
posix_time
::
ptime
>::
column_type
,
MySqlBindingTraits
<
boost
::
posix_time
::
ptime
>::
length
));
return
(
binding
);
}
MySqlBindingPtr
MySqlBinding
::
createNull
()
{
MySqlBindingPtr
binding
(
new
MySqlBinding
(
MYSQL_TYPE_NULL
,
0
));
return
(
binding
);
}
void
MySqlBinding
::
convertToDatabaseTime
(
const
time_t
input_time
,
MYSQL_TIME
&
output_time
)
{
// Convert to broken-out time
struct
tm
time_tm
;
(
void
)
localtime_r
(
&
input_time
,
&
time_tm
);
// Place in output expire structure.
output_time
.
year
=
time_tm
.
tm_year
+
1900
;
output_time
.
month
=
time_tm
.
tm_mon
+
1
;
// Note different base
output_time
.
day
=
time_tm
.
tm_mday
;
output_time
.
hour
=
time_tm
.
tm_hour
;
output_time
.
minute
=
time_tm
.
tm_min
;
output_time
.
second
=
time_tm
.
tm_sec
;
output_time
.
second_part
=
0
;
// No fractional seconds
output_time
.
neg
=
my_bool
(
0
);
// Not negative
}
void
MySqlBinding
::
convertToDatabaseTime
(
const
time_t
cltt
,
const
uint32_t
valid_lifetime
,
MYSQL_TIME
&
expire
)
{
// Calculate expiry time. Store it in the 64-bit value so as we can detect
// overflows.
int64_t
expire_time_64
=
static_cast
<
int64_t
>
(
cltt
)
+
static_cast
<
int64_t
>
(
valid_lifetime
);
// Even on 64-bit systems MySQL doesn't seem to accept the timestamps
// beyond the max value of int32_t.
if
(
expire_time_64
>
DatabaseConnection
::
MAX_DB_TIME
)
{
isc_throw
(
BadValue
,
"Time value is too large: "
<<
expire_time_64
);
}
const
time_t
expire_time
=
static_cast
<
const
time_t
>
(
expire_time_64
);
// Convert to broken-out time
struct
tm
expire_tm
;
(
void
)
localtime_r
(
&
expire_time
,
&
expire_tm
);
// Place in output expire structure.
expire
.
year
=
expire_tm
.
tm_year
+
1900
;
expire
.
month
=
expire_tm
.
tm_mon
+
1
;
// Note different base
expire
.
day
=
expire_tm
.
tm_mday
;
expire
.
hour
=
expire_tm
.
tm_hour
;
expire
.
minute
=
expire_tm
.
tm_min
;
expire
.
second
=
expire_tm
.
tm_sec
;
expire
.
second_part
=
0
;
// No fractional seconds
expire
.
neg
=
my_bool
(
0
);
// Not negative
}
void
MySqlBinding
::
convertFromDatabaseTime
(
const
MYSQL_TIME
&
expire
,
uint32_t
valid_lifetime
,
time_t
&
cltt
)
{
// Copy across fields from MYSQL_TIME structure.
struct
tm
expire_tm
;
memset
(
&
expire_tm
,
0
,
sizeof
(
expire_tm
));
expire_tm
.
tm_year
=
expire
.
year
-
1900
;
expire_tm
.
tm_mon
=
expire
.
month
-
1
;
expire_tm
.
tm_mday
=
expire
.
day
;
expire_tm
.
tm_hour
=
expire
.
hour
;
expire_tm
.
tm_min
=
expire
.
minute
;
expire_tm
.
tm_sec
=
expire
.
second
;
expire_tm
.
tm_isdst
=
-
1
;
// Let the system work out about DST
// Convert to local time
cltt
=
mktime
(
&
expire_tm
)
-
valid_lifetime
;
}
boost
::
posix_time
::
ptime
MySqlBinding
::
convertFromDatabaseTime
(
const
MYSQL_TIME
&
database_time
)
{
// Copy across fields from MYSQL_TIME structure.
struct
tm
converted_tm
;
memset
(
&
converted_tm
,
0
,
sizeof
(
converted_tm
));
converted_tm
.
tm_year
=
database_time
.
year
-
1900
;
converted_tm
.
tm_mon
=
database_time
.
month
-
1
;
converted_tm
.
tm_mday
=
database_time
.
day
;
converted_tm
.
tm_hour
=
database_time
.
hour
;
converted_tm
.
tm_min
=
database_time
.
minute
;
converted_tm
.
tm_sec
=
database_time
.
second
;
converted_tm
.
tm_isdst
=
-
1
;
// Let the system work out about DST
// Convert to local time
return
(
boost
::
posix_time
::
ptime_from_tm
(
converted_tm
));
}
MySqlBinding
::
MySqlBinding
(
enum_field_types
buffer_type
,
const
size_t
length
)
:
buffer_
(
length
),
length_
(
length
),
null_value_
(
buffer_type
==
MYSQL_TYPE_NULL
)
{
memset
(
&
bind_
,
0
,
sizeof
(
MYSQL_BIND
));
bind_
.
buffer_type
=
buffer_type
;
if
(
buffer_type
!=
MYSQL_TYPE_NULL
)
{
bind_
.
buffer
=
&
buffer_
[
0
];
bind_
.
buffer_length
=
length_
;
bind_
.
length
=
&
length_
;
bind_
.
is_null
=
&
null_value_
;
}
}
void
MySqlBinding
::
setBufferLength
(
const
unsigned
long
length
)
{
length_
=
length
;
buffer_
.
resize
(
length_
);
bind_
.
buffer
=
&
buffer_
[
0
];
bind_
.
buffer_length
=
length_
;
}
void
MySqlBinding
::
setTimestampValue
(
const
boost
::
posix_time
::
ptime
&
timestamp
)
{
// Convert timestamp to tm structure.
tm
td_tm
=
to_tm
(
timestamp
);
// Convert tm value to time_t.
time_t
tt
=
mktime
(
&
td_tm
);
// Convert time_t to database time.
MYSQL_TIME
database_time
;
convertToDatabaseTime
(
tt
,
database_time
);
// Copy database time into the buffer.
memcpy
(
static_cast
<
void
*>
(
&
buffer_
[
0
]),
reinterpret_cast
<
char
*>
(
&
database_time
),
sizeof
(
MYSQL_TIME
));
bind_
.
buffer
=
&
buffer_
[
0
];
}
}
// end of namespace isc::db
}
// end of namespace isc
src/lib/mysql/mysql_binding.h
0 → 100644
View file @
479791d7
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef MYSQL_BINDING_H
#define MYSQL_BINDING_H
#include <database/database_connection.h>
#include <exceptions/exceptions.h>
#include <boost/date_time/posix_time/conversion.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/shared_ptr.hpp>
#include <mysql/mysql_constants.h>
#include <mysql.h>
#include <mysqld_error.h>
#include <cstdint>
#include <iterator>
#include <string>
#include <vector>
namespace
isc
{
namespace
db
{
/// @brief Trait class for column types supported in MySQL.
///
/// This class is used to map C++ types to MySQL column types
/// defined in MySQL C API and their sizes. Specializations of
/// this class provide such mapping. The default is a BLOB type
/// which can be used for various input types.
template
<
typename
T
>
struct
MySqlBindingTraits
{
/// @brief Column type represented in MySQL C API.
static
const
enum_field_types
column_type
=
MYSQL_TYPE_BLOB
;
/// @brief Length of data in this column.
///
/// The value of 0 is used for variable size columns.
static
const
size_t
length
=
0
;
/// @brief Boolean value indicating if the numeric value is
/// unsigned.
static
const
bool
am_unsigned
=
false
;
};
/// @brief Specialization for MySQL TEXT type.
template
<
>
struct
MySqlBindingTraits
<
std
::
string
>
{
static
const
enum_field_types
column_type
=
MYSQL_TYPE_STRING
;
static
const
size_t
length
=
0
;
static
const
bool
am_unsigned
=
false
;
};
/// @brief Specialization for MySQL TIMESTAMP type.
template
<
>
struct
MySqlBindingTraits
<
boost
::
posix_time
::
ptime
>
{
static
const
enum_field_types
column_type
=
MYSQL_TYPE_TIMESTAMP
;
static
const
size_t
length
=
sizeof
(
MYSQL_TIME
);
static
const
bool
am_unsignged
=
false
;
};
/// @brief Specialization for MySQL TINYINT type.
template
<
>
struct
MySqlBindingTraits
<
int8_t
>
{
static
const
enum_field_types
column_type
=
MYSQL_TYPE_TINY
;
static
const
size_t
length
=
1
;
static
const
bool
am_unsigned
=
false
;
};
/// @brief Specialization for MySQL TINYINT UNSIGNED type.
template
<
>
struct
MySqlBindingTraits
<
uint8_t
>
{
static
const
enum_field_types
column_type
=
MYSQL_TYPE_TINY
;
static
const
size_t
length
=
1
;
static
const
bool
am_unsigned
=
true
;
};
/// @brief Speclialization for MySQL SMALLINT type.
template
<
>
struct
MySqlBindingTraits
<
int16_t
>
{
static
const
enum_field_types
column_type
=
MYSQL_TYPE_SHORT
;
static
const
size_t
length
=
2
;
static
const
bool
am_unsigned
=
false
;
};
/// @brief Specialization for MySQL SMALLINT UNSIGNED type.
template
<
>
struct
MySqlBindingTraits
<
uint16_t
>
{
static
const
enum_field_types
column_type
=
MYSQL_TYPE_SHORT
;
static
const
size_t
length
=
2
;
static
const
bool
am_unsigned
=
true
;
};
/// @brief Specialization for MySQL INT type.
template
<
>
struct
MySqlBindingTraits
<
int32_t
>
{
static
const
enum_field_types
column_type
=
MYSQL_TYPE_LONG
;
static
const
size_t
length
=
4
;
static
const
bool
am_unsigned
=
false
;
};
/// @brief Specialization for MySQL INT UNSIGNED type.
template
<
>
struct
MySqlBindingTraits
<
uint32_t
>
{
static
const
enum_field_types
column_type
=
MYSQL_TYPE_LONG
;
static
const
size_t
length
=
4
;
static
const
bool
am_unsigned
=
true
;
};
/// @brief Specialization for MySQL BIGINT type.
template
<
>
struct
MySqlBindingTraits
<
int64_t
>
{
static
const
enum_field_types
column_type
=
MYSQL_TYPE_LONGLONG
;
static
const
size_t
length
=
8
;
static
const
bool
am_unsigned
=
false
;
};
/// @brief Specialization for MySQL BIGINT UNSIGNED type.
template
<
>
struct
MySqlBindingTraits
<
uint64_t
>
{
static
const
enum_field_types
column_type
=
MYSQL_TYPE_LONGLONG
;
static
const
size_t
length
=
8
;
static
const
bool
am_unsigned
=
true
;
};
/// @brief Forward declaration of @c MySqlBinding class.
class
MySqlBinding
;
/// @brief Shared pointer to the @c Binding class.
typedef
boost
::
shared_ptr
<
MySqlBinding
>
MySqlBindingPtr
;
/// @brief MySQL binding used in prepared statements.
///
/// Kea uses prepared statements to execute queries in a database.
/// Prepared statements include placeholders for the input parameters.
/// These parameters are passed to the prepared statements via a
/// collection of @c MYSQL_BIND structures. The same structures are
/// used to receive the values from the database as a result of
/// SELECT statements.
///
/// The @c MYSQL_BIND structure contains information about the
/// data type and length. It also contains pointer to the buffer
/// actually holding the data to be passed to the database, a
/// flag indicating if the value is null etc.
///
/// The @c MySqlBinding is a C++ wrapper around this structure which
/// is meant to ease management of the MySQL bindings. The major
/// benefit is that the @c MySqlBinding class owns the buffer,
/// holding the data as well as other variables which are assigned
/// to the @c MYSQL_BIND structure. It also automatically detects
/// the appropriate @c enum_field_types value based on the C++
/// type used in the binding.
class
MySqlBinding
{
public:
/// @brief Returns MySQL column type for the binding.
///
/// @return column type, e.g. MYSQL_TYPE_STRING.
enum_field_types
getType
()
const
{
return
(
bind_
.
buffer_type
);
}
/// @brief Returns reference to the native binding.
///
/// The returned reference is only valid for the lifetime of the
/// object. Make sure that the object is not destroyed as long
/// as the binding is required. In particular, do not destroy this
/// object before database query is complete.
///
/// @return Reference to native MySQL binding.
MYSQL_BIND
&
getMySqlBinding
()
{
return
(
bind_
);
}
/// @brief Returns value held in the binding as string.
///
/// Call @c MySqlBinding::amNull to verify that the value is not
/// null prior to calling this method.
///
/// @throw InvalidOperation if the value is NULL or the binding
/// type is not @c MYSQL_TYPE_STRING.
///
/// @return String value.
std
::
string
getString
()
const
;
/// @brief Returns value held in the binding as blob.
///
/// Call @c MySqlBinding::amNull to verify that the value is not
/// null prior to calling this method.
///
/// @throw InvalidOperation if the value is NULL or the binding
/// type is not @c MYSQL_TYPE_BLOB.
///
/// @return Blob in a vactor.
std
::
vector
<
uint8_t
>
getBlob
()
const
;
/// @brief Returns numeric value held in the binding.
///
/// Call @c MySqlBinding::amNull to verify that the value is not
/// null prior to calling this method.
///
/// @tparam Numeric type corresponding to the binding type, e.g.
/// @c uint8_t, @c uint16_t etc.
///
/// @throw InvalidOperation if the value is NULL or the binding
/// type does not match the template parameter.
///
/// @return Numeric value of a specified type.
template
<
typename
T
>
T
getInteger
()
const
{
// Make sure that the binding type is numeric.
validateAccess
<
T
>
();
// Convert the buffer to a numeric type and then return a copy.
const
T
*
value
=
reinterpret_cast
<
const
T
*>
(
&
buffer_
[
0
]);
return
(
*
value
);
}
/// @brief Returns timestamp value held in the binding.
///
/// Call @c MySqlBinding::amNull to verify that the value is not
/// null prior to calling this method.
///
/// @throw InvalidOperation if the value is NULL or the binding
/// type is not @c MYSQL_TYPE_TIMESTAMP.
///
/// @return Timestamp converted to posix time.
boost
::
posix_time
::
ptime
getTimestamp
()
const
;
/// @brief Checks if the bound value is NULL.
///
/// @return true if the value in the binding is NULL, false otherwise.
bool
amNull
()
const
{
return
(
null_value_
==
MLM_TRUE
);
}
/// @brief Creates binding of text type for receiving data.
///
/// @param length Length of the buffer into which received data will
/// be stored.
///
/// @return Pointer to the created binding.
static
MySqlBindingPtr
createString
(
const
unsigned
long
length
);
/// @brief Creates binding of text type for sending data.
///
/// @param value String value to be sent to the database.
///