Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 

186 rader
5.4 KiB

  1. #pragma once
  2. #include "connection.h"
  3. namespace cppmariadb
  4. {
  5. /* op_store_result ***************************************************************************/
  6. struct op_store_result
  7. {
  8. using result_type = result_stored;
  9. inline MYSQL_RES* operator()(MYSQL* handle) const
  10. { return mysql_store_result(handle); }
  11. };
  12. /* op_use_result *****************************************************************************/
  13. struct op_use_result
  14. {
  15. using result_type = result_used;
  16. inline MYSQL_RES* operator()(MYSQL* handle) const
  17. { return mysql_use_result(handle); }
  18. };
  19. /* connection ********************************************************************************/
  20. connection::connection()
  21. : connection(nullptr)
  22. {
  23. auto h = mysql_init(nullptr);
  24. if (!h)
  25. throw exception("unable to initialize connection handle", error_code::Unknown);
  26. set_handle(h);
  27. }
  28. connection::connection(MYSQL* h)
  29. : handle(h)
  30. { }
  31. connection::connection(connection&& other)
  32. : handle(std::move(other))
  33. , _result (std::move(other)._result)
  34. { }
  35. connection::~connection()
  36. { close(); }
  37. connection& connection::operator =(connection&& other)
  38. {
  39. close();
  40. set_handle(other.get_handle());
  41. other.set_handle(nullptr);
  42. return *this;
  43. }
  44. void connection::connect(
  45. const std::string& host,
  46. const uint& port,
  47. const std::string& user,
  48. const std::string& password,
  49. const std::string& database,
  50. const client_flags& flags)
  51. {
  52. if (!mysql_real_connect(
  53. get_handle(),
  54. host.c_str(),
  55. user.c_str(),
  56. password.c_str(),
  57. database.empty() ? static_cast<const char*>(nullptr) : database.c_str(),
  58. port,
  59. nullptr,
  60. flags.value))
  61. throw exception(error_msg(), error_code());
  62. }
  63. void connection::close()
  64. {
  65. _result.reset();
  66. auto h = get_handle();
  67. if (h)
  68. mysql_close(h);
  69. }
  70. result* connection::result() const
  71. { return _result.get(); }
  72. uint connection::fieldcount() const
  73. { return mysql_field_count(get_handle()); }
  74. error_code connection::error_code() const
  75. {
  76. auto ret = mysql_errno(get_handle());
  77. return static_cast<enum error_code>(ret);
  78. }
  79. std::string connection::error_msg() const
  80. {
  81. auto ret = mysql_error(get_handle());
  82. return (ret ? std::string(ret) : std::string());
  83. }
  84. std::string connection::escape(const std::string& value) const
  85. {
  86. if (get_handle())
  87. {
  88. std::string ret;
  89. ret.resize(2 * value.size() + 1);
  90. auto len = mysql_real_escape_string(
  91. get_handle(),
  92. const_cast<char*>(ret.data()),
  93. value.c_str(),
  94. value.size());
  95. ret.resize(len);
  96. return ret;
  97. }
  98. return value;
  99. }
  100. template<class T>
  101. typename T::result_type* connection::execute_internal(const std::string& cmd)
  102. {
  103. cppmariadb_log(debug) << "execute cppmariadb query: " << std::endl << cmd;
  104. if (!get_handle())
  105. throw exception("invalid handle", error_code::Unknown, cmd);
  106. using result_type = typename T::result_type;
  107. _result.reset();
  108. if (mysql_real_query(*this, cmd.data(), cmd.size()) != 0)
  109. throw exception(error_msg(), error_code(), cmd);
  110. auto ret = T()(*this);
  111. if (!ret)
  112. {
  113. if (mysql_field_count(*this) > 0)
  114. throw exception(error_msg(), error_code(), cmd);
  115. return nullptr;
  116. }
  117. _result.reset(new result_type(ret));
  118. return static_cast<result_type*>(_result.get());
  119. }
  120. void connection::execute(const std::string& cmd)
  121. { execute_internal<op_store_result>(cmd); }
  122. unsigned long long connection::execute_id(const std::string& cmd)
  123. {
  124. execute_internal<op_store_result>(cmd);
  125. auto id = mysql_insert_id(*this);
  126. if (id == static_cast<unsigned long long>(-1))
  127. throw exception(error_msg(), error_code(), cmd);
  128. return id;
  129. }
  130. unsigned long long connection::execute_rows(const std::string& cmd)
  131. {
  132. execute_internal<op_store_result>(cmd);
  133. auto rows = mysql_affected_rows(*this);
  134. if (rows == static_cast<unsigned long long>(-1))
  135. throw exception(error_msg(), error_code(), cmd);
  136. return rows;
  137. }
  138. result_stored* connection::execute_stored(const std::string& cmd)
  139. { return execute_internal<op_store_result>(cmd); }
  140. result_used* connection::execute_used(const std::string& cmd)
  141. { return execute_internal<op_use_result>(cmd); }
  142. void connection::execute(const statement& s)
  143. { return execute(s.query(*this)); }
  144. unsigned long long connection::execute_id(const statement& s)
  145. { return execute_id(s.query(*this)); }
  146. unsigned long long connection::execute_rows(const statement& s)
  147. { return execute_rows(s.query(*this)); }
  148. result_stored* connection::execute_stored(const statement& s)
  149. { return execute_stored(s.query(*this)); }
  150. result_used* connection::execute_used(const statement& s)
  151. { return execute_used(s.query(*this)); }
  152. }