Cleanup the code of the MySQL connector (#509)

* Move the code for sqlpp::mysql::detail::connection_handle_t to include/sqlpp11/mysql/detail/connection_handle.h
* Move the code for sqlpp::mysql::detail::prepared_statement_handle_t to include/sqlpp11/mysql/detail/prepared_statement_handle.h
* Move the code for sqlpp::mysql::detail::result_handle to include/sqlpp11/mysql/detail/result_handle.h
* Rename sqlpp::mysql::detail::connection_handle_t -> sqlpp::mysql::detail::connection_handle
* Rename sqlpp::mysql::serializer_t -> sqlpp::mysql::context_t
* Add const qualifiers to sqlpp::mysql::context_t::escape() and its parameter.
* Rename class/struct types, variables and functions from CamelCase to snake_case.
* Remove a superfluous function that forwards the call to mysql_close().
This commit is contained in:
MeanSquaredError
2023-08-05 10:18:51 +03:00
committed by GitHub
parent 3c598cd0b2
commit 490259ee69
9 changed files with 321 additions and 211 deletions
+3 -73
View File
@@ -26,91 +26,21 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <iostream>
#include <memory>
#include <vector>
#include <sqlpp11/chrono.h> #include <sqlpp11/chrono.h>
#include <sqlpp11/exception.h> #include <sqlpp11/exception.h>
#include <sqlpp11/mysql/detail/prepared_statement_handle.h>
#include <sqlpp11/mysql/sqlpp_mysql.h> #include <sqlpp11/mysql/sqlpp_mysql.h>
#include <iostream>
#ifdef _MSC_VER #ifdef _MSC_VER
#include <iso646.h> #include <iso646.h>
#endif #endif
#include <memory>
namespace sqlpp namespace sqlpp
{ {
namespace mysql namespace mysql
{ {
namespace detail
{
struct result_meta_data_t
{
size_t index;
unsigned long bound_len;
my_bool bound_is_null;
my_bool bound_error;
std::vector<char> bound_text_buffer; // also for blobs
const char** text_buffer;
size_t* len;
bool* is_null;
};
struct prepared_statement_handle_t
{
struct wrapped_bool
{
my_bool value;
wrapped_bool() : value(false)
{
}
wrapped_bool(bool v) : value(v)
{
}
wrapped_bool(const wrapped_bool&) = default;
wrapped_bool(wrapped_bool&&) = default;
wrapped_bool& operator=(const wrapped_bool&) = default;
wrapped_bool& operator=(wrapped_bool&&) = default;
~wrapped_bool() = default;
};
MYSQL_STMT* mysql_stmt;
std::vector<MYSQL_BIND> stmt_params;
std::vector<MYSQL_TIME> stmt_date_time_param_buffer;
std::vector<wrapped_bool> stmt_param_is_null; // my_bool is bool after 8.0, and vector<bool> is bad
std::vector<MYSQL_BIND> result_params;
std::vector<result_meta_data_t> result_param_meta_data;
bool debug;
prepared_statement_handle_t(MYSQL_STMT* stmt, size_t no_of_parameters, size_t no_of_columns, bool debug_)
: mysql_stmt(stmt),
stmt_params(no_of_parameters, MYSQL_BIND{}),
stmt_date_time_param_buffer(no_of_parameters, MYSQL_TIME{}),
stmt_param_is_null(no_of_parameters, false),
result_params(no_of_columns, MYSQL_BIND{}),
result_param_meta_data(no_of_columns, result_meta_data_t{}),
debug(debug_)
{
}
prepared_statement_handle_t(const prepared_statement_handle_t&) = delete;
prepared_statement_handle_t(prepared_statement_handle_t&&) = default;
prepared_statement_handle_t& operator=(const prepared_statement_handle_t&) = delete;
prepared_statement_handle_t& operator=(prepared_statement_handle_t&&) = default;
~prepared_statement_handle_t()
{
if (mysql_stmt)
mysql_stmt_close(mysql_stmt);
}
bool operator!() const
{
return !mysql_stmt;
}
};
} // namespace detail
class bind_result_t class bind_result_t
{ {
std::shared_ptr<detail::prepared_statement_handle_t> _handle; std::shared_ptr<detail::prepared_statement_handle_t> _handle;
+7 -32
View File
@@ -32,6 +32,7 @@
#include <memory> #include <memory>
#include <sqlpp11/chrono.h> #include <sqlpp11/chrono.h>
#include <sqlpp11/exception.h> #include <sqlpp11/exception.h>
#include <sqlpp11/mysql/detail/result_handle.h>
#include <sqlpp11/mysql/sqlpp_mysql.h> #include <sqlpp11/mysql/sqlpp_mysql.h>
#include <sqlpp11/mysql/char_result_row.h> #include <sqlpp11/mysql/char_result_row.h>
@@ -41,35 +42,9 @@ namespace sqlpp
{ {
namespace detail namespace detail
{ {
struct result_handle inline auto check_first_digit(const char* text, bool digit_flag) -> bool
{ {
MYSQL_RES* mysql_res; if (digit_flag)
bool debug;
result_handle(MYSQL_RES* res, bool debug_) : mysql_res(res), debug(debug_)
{
}
result_handle(const result_handle&) = delete;
result_handle(result_handle&&) = default;
result_handle& operator=(const result_handle&) = delete;
result_handle& operator=(result_handle&&) = default;
~result_handle()
{
if (mysql_res)
mysql_free_result(mysql_res);
}
bool operator!() const
{
return !mysql_res;
}
};
inline auto check_first_digit(const char* text, bool digitFlag) -> bool
{
if (digitFlag)
{ {
if (not std::isdigit(*text)) if (not std::isdigit(*text))
{ {
@@ -88,9 +63,9 @@ namespace sqlpp
inline auto check_date_digits(const char* text) -> bool inline auto check_date_digits(const char* text) -> bool
{ {
for (const auto digitFlag : {true, true, true, true, false, true, true, false, true, true}) // YYYY-MM-DD for (const auto digit_flag : {true, true, true, true, false, true, true, false, true, true}) // YYYY-MM-DD
{ {
if (not check_first_digit(text, digitFlag)) if (not check_first_digit(text, digit_flag))
return false; return false;
++text; ++text;
} }
@@ -99,9 +74,9 @@ namespace sqlpp
inline auto check_time_digits(const char* text) -> bool inline auto check_time_digits(const char* text) -> bool
{ {
for (const auto digitFlag : {true, true, false, true, true, false, true, true}) // hh:mm:ss for (const auto digit_flag : {true, true, false, true, true, false, true, true}) // hh:mm:ss
{ {
if (not check_first_digit(text, digitFlag)) if (not check_first_digit(text, digit_flag))
return false; return false;
++text; ++text;
} }
+16 -96
View File
@@ -33,11 +33,11 @@
#include <sqlpp11/mysql/bind_result.h> #include <sqlpp11/mysql/bind_result.h>
#include <sqlpp11/mysql/char_result.h> #include <sqlpp11/mysql/char_result.h>
#include <sqlpp11/mysql/connection_config.h> #include <sqlpp11/mysql/connection_config.h>
#include <sqlpp11/mysql/detail/connection_handle.h>
#include <sqlpp11/mysql/prepared_statement.h> #include <sqlpp11/mysql/prepared_statement.h>
#include <sqlpp11/mysql/remove.h> #include <sqlpp11/mysql/remove.h>
#include <sqlpp11/mysql/update.h> #include <sqlpp11/mysql/update.h>
#include <sqlpp11/serialize.h> #include <sqlpp11/serialize.h>
#include <sqlpp11/mysql/sqlpp_mysql.h>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <string> #include <string>
@@ -48,9 +48,9 @@ namespace sqlpp
{ {
namespace detail namespace detail
{ {
struct MySqlThreadInitializer struct mysql_thread_initializer
{ {
MySqlThreadInitializer() mysql_thread_initializer()
{ {
if (!mysql_thread_safe()) if (!mysql_thread_safe())
{ {
@@ -59,7 +59,7 @@ namespace sqlpp
mysql_thread_init(); mysql_thread_init();
} }
~MySqlThreadInitializer() ~mysql_thread_initializer()
{ {
mysql_thread_end(); mysql_thread_end();
} }
@@ -67,90 +67,10 @@ namespace sqlpp
inline void thread_init() inline void thread_init()
{ {
thread_local MySqlThreadInitializer threadInitializer; thread_local mysql_thread_initializer thread_initializer;
} }
inline void connect(MYSQL* mysql, const connection_config& config) inline void execute_statement(std::unique_ptr<connection_handle>& handle, const std::string& statement)
{
if (config.connect_timeout_seconds != 0 &&
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &config.connect_timeout_seconds))
{
throw sqlpp::exception("MySQL: could not set option MYSQL_OPT_CONNECT_TIMEOUT");
}
if (!mysql_real_connect(mysql, config.host.empty() ? nullptr : config.host.c_str(),
config.user.empty() ? nullptr : config.user.c_str(),
config.password.empty() ? nullptr : config.password.c_str(), nullptr, config.port,
config.unix_socket.empty() ? nullptr : config.unix_socket.c_str(), config.client_flag))
{
throw sqlpp::exception("MySQL: could not connect to server: " + std::string(mysql_error(mysql)));
}
if (mysql_set_character_set(mysql, config.charset.c_str()))
{
throw sqlpp::exception("MySQL error: can't set character set " + config.charset);
}
if (not config.database.empty() and mysql_select_db(mysql, config.database.c_str()))
{
throw sqlpp::exception("MySQL error: can't select database '" + config.database + "'");
}
}
inline void handle_cleanup(MYSQL* mysql)
{
mysql_close(mysql);
}
struct connection_handle_t
{
std::shared_ptr<const connection_config> config;
std::unique_ptr<MYSQL, void (*)(MYSQL*)> mysql;
connection_handle_t(const std::shared_ptr<const connection_config>& conf) :
config(conf),
mysql(mysql_init(nullptr), handle_cleanup)
{
if (not mysql)
{
throw sqlpp::exception("MySQL: could not init mysql data structure");
}
if (config->auto_reconnect)
{
my_bool my_true = true;
if (mysql_options(native_handle(), MYSQL_OPT_RECONNECT, &my_true))
{
throw sqlpp::exception("MySQL: could not set option MYSQL_OPT_RECONNECT");
}
}
connect(native_handle(), *config);
}
connection_handle_t(const connection_handle_t&) = delete;
connection_handle_t(connection_handle_t&&) = default;
connection_handle_t& operator=(const connection_handle_t&) = delete;
connection_handle_t& operator=(connection_handle_t&&) = default;
MYSQL* native_handle() const
{
return mysql.get();
}
bool check_connection() const
{
auto nh = native_handle();
return nh && (mysql_ping(nh) == 0);
}
void reconnect()
{
connect(native_handle(), *config);
}
};
inline void execute_statement(std::unique_ptr<connection_handle_t>& handle, const std::string& statement)
{ {
thread_init(); thread_init();
@@ -185,7 +105,7 @@ namespace sqlpp
} }
} }
inline std::shared_ptr<detail::prepared_statement_handle_t> prepare_statement(std::unique_ptr<connection_handle_t>& handle, inline std::shared_ptr<detail::prepared_statement_handle_t> prepare_statement(std::unique_ptr<connection_handle>& handle,
const std::string& statement, const std::string& statement,
size_t no_of_parameters, size_t no_of_parameters,
size_t no_of_columns) size_t no_of_columns)
@@ -235,12 +155,12 @@ namespace sqlpp
// Forward declaration // Forward declaration
class connection_base; class connection_base;
struct serializer_t struct context_t
{ {
serializer_t(const connection_base& db) : _db(db) context_t(const connection_base& db) : _db(db)
{ {
} }
serializer_t(const connection_base&&) = delete; context_t(const connection_base&&) = delete;
template <typename T> template <typename T>
std::ostream& operator<<(T t) std::ostream& operator<<(T t)
@@ -248,7 +168,7 @@ namespace sqlpp
return _os << t; return _os << t;
} }
std::string escape(std::string arg); std::string escape(const std::string& arg) const;
std::string str() const std::string str() const
{ {
@@ -259,9 +179,9 @@ namespace sqlpp
sqlpp::detail::float_safe_ostringstream _os; sqlpp::detail::float_safe_ostringstream _os;
}; };
std::integral_constant<char, '`'> get_quote_left(const serializer_t&); std::integral_constant<char, '`'> get_quote_left(const context_t&);
std::integral_constant<char, '`'> get_quote_right(const serializer_t&); std::integral_constant<char, '`'> get_quote_right(const context_t&);
class connection_base : public sqlpp::connection class connection_base : public sqlpp::connection
{ {
@@ -336,11 +256,11 @@ namespace sqlpp
using _connection_base_t = connection_base; using _connection_base_t = connection_base;
using _config_t = connection_config; using _config_t = connection_config;
using _config_ptr_t = std::shared_ptr<const _config_t>; using _config_ptr_t = std::shared_ptr<const _config_t>;
using _handle_t = detail::connection_handle_t; using _handle_t = detail::connection_handle;
using _handle_ptr_t = std::unique_ptr<_handle_t>; using _handle_ptr_t = std::unique_ptr<_handle_t>;
using _prepared_statement_t = ::sqlpp::mysql::prepared_statement_t; using _prepared_statement_t = ::sqlpp::mysql::prepared_statement_t;
using _context_t = serializer_t; using _context_t = context_t;
using _serializer_context_t = _context_t; using _serializer_context_t = _context_t;
using _interpreter_context_t = _context_t; using _interpreter_context_t = _context_t;
@@ -594,7 +514,7 @@ namespace sqlpp
}; };
// Method definition moved outside of class because it needs connection_base // Method definition moved outside of class because it needs connection_base
inline std::string serializer_t::escape(std::string arg) inline std::string context_t::escape(const std::string& arg) const
{ {
return _db.escape(arg); return _db.escape(arg);
} }
@@ -0,0 +1,117 @@
#pragma once
/*
* Copyright (c) 2013 - 2017, Roland Bock
* Copyright (c) 2023, Vesselin Atanasov
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sqlpp11/mysql/connection_config.h>
#include <sqlpp11/mysql/sqlpp_mysql.h>
#include <memory>
namespace sqlpp
{
namespace mysql
{
namespace detail
{
inline void connect(MYSQL* mysql, const connection_config& config)
{
if (config.connect_timeout_seconds != 0 &&
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, &config.connect_timeout_seconds))
{
throw sqlpp::exception("MySQL: could not set option MYSQL_OPT_CONNECT_TIMEOUT");
}
if (!mysql_real_connect(mysql, config.host.empty() ? nullptr : config.host.c_str(),
config.user.empty() ? nullptr : config.user.c_str(),
config.password.empty() ? nullptr : config.password.c_str(), nullptr, config.port,
config.unix_socket.empty() ? nullptr : config.unix_socket.c_str(), config.client_flag))
{
throw sqlpp::exception("MySQL: could not connect to server: " + std::string(mysql_error(mysql)));
}
if (mysql_set_character_set(mysql, config.charset.c_str()))
{
throw sqlpp::exception("MySQL error: can't set character set " + config.charset);
}
if (not config.database.empty() and mysql_select_db(mysql, config.database.c_str()))
{
throw sqlpp::exception("MySQL error: can't select database '" + config.database + "'");
}
}
struct connection_handle
{
std::shared_ptr<const connection_config> config;
std::unique_ptr<MYSQL, void (*)(MYSQL*)> mysql;
connection_handle(const std::shared_ptr<const connection_config>& conf) :
config(conf),
mysql(mysql_init(nullptr), mysql_close)
{
if (not mysql)
{
throw sqlpp::exception("MySQL: could not init mysql data structure");
}
if (config->auto_reconnect)
{
my_bool my_true = true;
if (mysql_options(native_handle(), MYSQL_OPT_RECONNECT, &my_true))
{
throw sqlpp::exception("MySQL: could not set option MYSQL_OPT_RECONNECT");
}
}
connect(native_handle(), *config);
}
connection_handle(const connection_handle&) = delete;
connection_handle(connection_handle&&) = default;
connection_handle& operator=(const connection_handle&) = delete;
connection_handle& operator=(connection_handle&&) = default;
MYSQL* native_handle() const
{
return mysql.get();
}
bool check_connection() const
{
auto nh = native_handle();
return nh && (mysql_ping(nh) == 0);
}
void reconnect()
{
connect(native_handle(), *config);
}
};
} // namespace detail
} // namespace mysql
} // namespace sqlpp
@@ -0,0 +1,107 @@
#pragma once
/*
* Copyright (c) 2013 - 2015, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sqlpp11/mysql/sqlpp_mysql.h>
#include <vector>
namespace sqlpp
{
namespace mysql
{
namespace detail
{
struct result_meta_data_t
{
size_t index;
unsigned long bound_len;
my_bool bound_is_null;
my_bool bound_error;
std::vector<char> bound_text_buffer; // also for blobs
const char** text_buffer;
size_t* len;
bool* is_null;
};
struct prepared_statement_handle_t
{
struct wrapped_bool
{
my_bool value;
wrapped_bool() : value(false)
{
}
wrapped_bool(bool v) : value(v)
{
}
wrapped_bool(const wrapped_bool&) = default;
wrapped_bool(wrapped_bool&&) = default;
wrapped_bool& operator=(const wrapped_bool&) = default;
wrapped_bool& operator=(wrapped_bool&&) = default;
~wrapped_bool() = default;
};
MYSQL_STMT* mysql_stmt;
std::vector<MYSQL_BIND> stmt_params;
std::vector<MYSQL_TIME> stmt_date_time_param_buffer;
std::vector<wrapped_bool> stmt_param_is_null; // my_bool is bool after 8.0, and vector<bool> is bad
std::vector<MYSQL_BIND> result_params;
std::vector<result_meta_data_t> result_param_meta_data;
bool debug;
prepared_statement_handle_t(MYSQL_STMT* stmt, size_t no_of_parameters, size_t no_of_columns, bool debug_)
: mysql_stmt(stmt),
stmt_params(no_of_parameters, MYSQL_BIND{}),
stmt_date_time_param_buffer(no_of_parameters, MYSQL_TIME{}),
stmt_param_is_null(no_of_parameters, false),
result_params(no_of_columns, MYSQL_BIND{}),
result_param_meta_data(no_of_columns, result_meta_data_t{}),
debug(debug_)
{
}
prepared_statement_handle_t(const prepared_statement_handle_t&) = delete;
prepared_statement_handle_t(prepared_statement_handle_t&&) = default;
prepared_statement_handle_t& operator=(const prepared_statement_handle_t&) = delete;
prepared_statement_handle_t& operator=(prepared_statement_handle_t&&) = default;
~prepared_statement_handle_t()
{
if (mysql_stmt)
mysql_stmt_close(mysql_stmt);
}
bool operator!() const
{
return !mysql_stmt;
}
};
} // namespace detail
} // namespace mysql
} // namespace sqlpp
@@ -0,0 +1,62 @@
#pragma once
/*
* Copyright (c) 2013 - 2015, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
namespace sqlpp
{
namespace mysql
{
namespace detail
{
struct result_handle
{
MYSQL_RES* mysql_res;
bool debug;
result_handle(MYSQL_RES* res, bool debug_) : mysql_res(res), debug(debug_)
{
}
result_handle(const result_handle&) = delete;
result_handle(result_handle&&) = default;
result_handle& operator=(const result_handle&) = delete;
result_handle& operator=(result_handle&&) = default;
~result_handle()
{
if (mysql_res)
mysql_free_result(mysql_res);
}
bool operator!() const
{
return !mysql_res;
}
};
} // namespace detail
} // namespace mysql
} // namespace sqlpp
@@ -33,7 +33,6 @@
#include <memory> #include <memory>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <vector>
#include <sqlpp11/chrono.h> #include <sqlpp11/chrono.h>
namespace sqlpp namespace sqlpp
+8 -8
View File
@@ -32,17 +32,17 @@
namespace sqlpp namespace sqlpp
{ {
template <typename First, typename... Args> template <typename First, typename... Args>
mysql::serializer_t& serialize(const concat_t<First, Args...>& t, mysql::serializer_t& context) mysql::context_t& serialize(const concat_t<First, Args...>& t, mysql::context_t& ctx)
{ {
context << "CONCAT("; ctx << "CONCAT(";
interpret_tuple(t._args, ',', context); interpret_tuple(t._args, ',', ctx);
context << ')'; ctx << ')';
return context; return ctx;
} }
inline mysql::serializer_t& serialize(const insert_default_values_data_t&, mysql::serializer_t& context) inline mysql::context_t& serialize(const insert_default_values_data_t&, mysql::context_t& ctx)
{ {
context << " () VALUES()"; ctx << " () VALUES()";
return context; return ctx;
} }
} }
+1 -1
View File
@@ -60,7 +60,7 @@ namespace
} }
sqlpp::mysql::connection connection{config}; sqlpp::mysql::connection connection{config};
sqlpp::mysql::serializer_t printer{connection}; sqlpp::mysql::context_t printer{connection};
const auto result = serialize(expr, printer).str(); const auto result = serialize(expr, printer).str();