|
- #pragma once
-
- #include "connection.h"
-
- namespace cppmariadb
- {
-
- /* op_store_result ***************************************************************************/
-
- struct op_store_result
- {
- using result_type = result_stored;
-
- inline MYSQL_RES* operator()(MYSQL* handle) const
- { return mysql_store_result(handle); }
- };
-
- /* op_use_result *****************************************************************************/
-
- struct op_use_result
- {
- using result_type = result_used;
-
- inline MYSQL_RES* operator()(MYSQL* handle) const
- { return mysql_use_result(handle); }
- };
-
- /* connection ********************************************************************************/
-
- connection::connection()
- : connection(nullptr)
- {
- auto h = mysql_init(nullptr);
- if (!h)
- throw exception("unable to initialize connection handle", error_code::Unknown);
- set_handle(h);
- }
-
- connection::connection(MYSQL* h)
- : handle(h)
- { }
-
- connection::connection(connection&& other)
- : handle(std::move(other))
- , _result (std::move(other)._result)
- { }
-
- connection::~connection()
- { close(); }
-
- connection& connection::operator =(connection&& other)
- {
- close();
- set_handle(other.get_handle());
- other.set_handle(nullptr);
- return *this;
- }
-
- void connection::connect(
- const std::string& host,
- const uint& port,
- const std::string& user,
- const std::string& password,
- const std::string& database,
- const client_flags& flags)
- {
- if (!mysql_real_connect(
- get_handle(),
- host.c_str(),
- user.c_str(),
- password.c_str(),
- database.empty() ? static_cast<const char*>(nullptr) : database.c_str(),
- port,
- nullptr,
- flags.value))
- throw exception(error_msg(), error_code());
- }
-
- void connection::close()
- {
- _result.reset();
- auto h = get_handle();
- if (h)
- mysql_close(h);
- }
-
- result* connection::result() const
- { return _result.get(); }
-
- uint connection::fieldcount() const
- { return mysql_field_count(get_handle()); }
-
- error_code connection::error_code() const
- {
- auto ret = mysql_errno(get_handle());
- return static_cast<enum error_code>(ret);
- }
-
- std::string connection::error_msg() const
- {
- auto ret = mysql_error(get_handle());
- return (ret ? std::string(ret) : std::string());
- }
-
- std::string connection::escape(const std::string& value) const
- {
- if (get_handle())
- {
- std::string ret;
- ret.resize(2 * value.size() + 1);
- auto len = mysql_real_escape_string(
- get_handle(),
- const_cast<char*>(ret.data()),
- value.c_str(),
- value.size());
- ret.resize(len);
- return ret;
- }
- return value;
- }
-
- template<class T>
- typename T::result_type* connection::execute_internal(const std::string& cmd)
- {
- cppmariadb_log(debug) << "execute cppmariadb query: " << std::endl << cmd;
- if (!get_handle())
- throw exception("invalid handle", error_code::Unknown, cmd);
- using result_type = typename T::result_type;
- _result.reset();
- if (mysql_real_query(*this, cmd.data(), cmd.size()) != 0)
- throw exception(error_msg(), error_code(), cmd);
- auto ret = T()(*this);
- if (!ret)
- {
- if (mysql_field_count(*this) > 0)
- throw exception(error_msg(), error_code(), cmd);
- return nullptr;
- }
- _result.reset(new result_type(ret));
- return static_cast<result_type*>(_result.get());
- }
-
- void connection::execute(const std::string& cmd)
- { execute_internal<op_store_result>(cmd); }
-
- unsigned long long connection::execute_id(const std::string& cmd)
- {
- execute_internal<op_store_result>(cmd);
- auto id = mysql_insert_id(*this);
- if (id == static_cast<unsigned long long>(-1))
- throw exception(error_msg(), error_code(), cmd);
- return id;
- }
-
- unsigned long long connection::execute_rows(const std::string& cmd)
- {
- execute_internal<op_store_result>(cmd);
- auto rows = mysql_affected_rows(*this);
- if (rows == static_cast<unsigned long long>(-1))
- throw exception(error_msg(), error_code(), cmd);
- return rows;
- }
-
- result_stored* connection::execute_stored(const std::string& cmd)
- { return execute_internal<op_store_result>(cmd); }
-
- result_used* connection::execute_used(const std::string& cmd)
- { return execute_internal<op_use_result>(cmd); }
-
- void connection::execute(const statement& s)
- { return execute(s.query(*this)); }
-
- unsigned long long connection::execute_id(const statement& s)
- { return execute_id(s.query(*this)); }
-
- unsigned long long connection::execute_rows(const statement& s)
- { return execute_rows(s.query(*this)); }
-
- result_stored* connection::execute_stored(const statement& s)
- { return execute_stored(s.query(*this)); }
-
- result_used* connection::execute_used(const statement& s)
- { return execute_used(s.query(*this)); }
-
- }
|