statement.hpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. //
  2. // Copyright (c) 2019-2024 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. #ifndef BOOST_MYSQL_STATEMENT_HPP
  8. #define BOOST_MYSQL_STATEMENT_HPP
  9. #include <boost/mysql/detail/access.hpp>
  10. #include <boost/mysql/detail/writable_field_traits.hpp>
  11. #include <boost/assert.hpp>
  12. #include <cstdint>
  13. #include <tuple>
  14. #include <type_traits>
  15. namespace boost {
  16. namespace mysql {
  17. /**
  18. * \brief A statement with bound parameters, represented as a `std::tuple`.
  19. * \details
  20. * This class satisfies `ExecutionRequest`. You can pass instances of this class to \ref connection::execute,
  21. * \ref connection::start_execution or their async counterparts.
  22. */
  23. template <BOOST_MYSQL_WRITABLE_FIELD_TUPLE WritableFieldTuple>
  24. class bound_statement_tuple;
  25. /**
  26. * \brief A statement with bound parameters, represented as an iterator range.
  27. * \details
  28. * This class satisfies `ExecutionRequest`. You can pass instances of this class to \ref connection::execute,
  29. * \ref connection::start_execution or their async counterparts.
  30. */
  31. template <BOOST_MYSQL_FIELD_VIEW_FORWARD_ITERATOR FieldViewFwdIterator>
  32. class bound_statement_iterator_range;
  33. /**
  34. * \brief Represents a server-side prepared statement.
  35. * \details
  36. * This is a lightweight class, holding a handle to a server-side prepared statement.
  37. * \n
  38. * Note that statement's destructor doesn't deallocate the statement from the
  39. * server, as this implies a network transfer that may fail.
  40. *
  41. * \par Thread safety
  42. * Distinct objects: safe. \n
  43. * Shared objects: unsafe. \n
  44. */
  45. class statement
  46. {
  47. public:
  48. /**
  49. * \brief Default constructor.
  50. * \details Default constructed statements have `this->valid() == false`.
  51. *
  52. * \par Exception safety
  53. * No-throw guarantee.
  54. */
  55. statement() = default;
  56. /**
  57. * \brief Returns `true` if the object represents an actual server statement.
  58. * \details Calling any function other than assignment on a statement for which
  59. * this function returns `false` results in undefined behavior.
  60. * \n
  61. * Returns `false` for default-constructed statements.
  62. *
  63. * \par Exception safety
  64. * No-throw guarantee.
  65. */
  66. bool valid() const noexcept { return valid_; }
  67. /**
  68. * \brief Returns a server-side identifier for the statement (unique in a per-connection basis).
  69. * \details Note that, once a statement is closed, the server may recycle its ID.
  70. *
  71. * \par Preconditions
  72. * `this->valid() == true`
  73. *
  74. * \par Exception safety
  75. * No-throw guarantee.
  76. */
  77. std::uint32_t id() const noexcept
  78. {
  79. BOOST_ASSERT(valid());
  80. return id_;
  81. }
  82. /**
  83. * \brief Returns the number of parameters that should be provided when executing the statement.
  84. * \par Preconditions
  85. * `this->valid() == true`
  86. *
  87. * \par Exception safety
  88. * No-throw guarantee.
  89. */
  90. unsigned num_params() const noexcept
  91. {
  92. BOOST_ASSERT(valid());
  93. return num_params_;
  94. }
  95. /**
  96. * \brief Binds parameters to a statement.
  97. * \details
  98. * Creates an object that packages `*this` and the statement actual parameters `params`.
  99. * This object can be passed to \ref connection::execute, \ref connection::start_execution
  100. * and their async counterparts.
  101. * \n
  102. * The parameters are copied into a `std::tuple` by using `std::make_tuple`. This function
  103. * only participates in overload resolution if `std::make_tuple(FWD(args)...)` yields a
  104. * `WritableFieldTuple`. Equivalent to `this->bind(std::make_tuple(std::forward<T>(params)...))`.
  105. * \n
  106. * This function doesn't involve communication with the server.
  107. *
  108. * \par Preconditions
  109. * `this->valid() == true`
  110. * \n
  111. * \par Exception safety
  112. * Strong guarantee. Only throws if constructing any of the internal tuple elements throws.
  113. */
  114. template <class... T>
  115. #ifdef BOOST_MYSQL_DOXYGEN
  116. bound_statement_tuple<std::tuple<__see_below__>>
  117. #else
  118. auto
  119. #endif
  120. bind(T&&... params) const->typename std::enable_if<
  121. detail::is_writable_field_tuple<decltype(std::make_tuple(std::forward<T>(params)...))>::value,
  122. bound_statement_tuple<decltype(std::make_tuple(std::forward<T>(params)...))>>::type
  123. {
  124. return bind(std::make_tuple(std::forward<T>(params)...));
  125. }
  126. /**
  127. * \brief Binds parameters to a statement.
  128. * \details
  129. * Creates an object that packages `*this` and the statement actual parameters `params`.
  130. * This object can be passed to \ref connection::execute, \ref connection::start_execution
  131. * or their async counterparts.
  132. * \n
  133. * The `params` tuple is decay-copied into the returned object.
  134. * \n
  135. * This function doesn't involve communication with the server.
  136. *
  137. * \par Preconditions
  138. * `this->valid() == true`
  139. * \n
  140. * \par Exception safety
  141. * Strong guarantee. Only throws if the decay-copy of the tuple throws.
  142. */
  143. template <
  144. BOOST_MYSQL_WRITABLE_FIELD_TUPLE WritableFieldTuple,
  145. typename EnableIf =
  146. typename std::enable_if<detail::is_writable_field_tuple<WritableFieldTuple>::value>::type>
  147. bound_statement_tuple<typename std::decay<WritableFieldTuple>::type> bind(WritableFieldTuple&& params
  148. ) const;
  149. /**
  150. * \brief Binds parameters to a statement (iterator range overload).
  151. * \details
  152. * Creates an object that packages `*this` and the statement actual parameters, represented
  153. * as the iterator range `[params_first, params_last)`.
  154. * This object can be passed to \ref connection::execute, \ref connection::start_execution
  155. * or their async counterparts.
  156. * \n
  157. * This function doesn't involve communication with the server.
  158. *
  159. * \par Preconditions
  160. * `this->valid() == true`
  161. * \n
  162. * \par Exception safety
  163. * Strong guarantee. Only throws if copy-constructing iterators throws.
  164. */
  165. template <
  166. BOOST_MYSQL_FIELD_VIEW_FORWARD_ITERATOR FieldViewFwdIterator,
  167. typename EnableIf = typename std::enable_if<
  168. detail::is_field_view_forward_iterator<FieldViewFwdIterator>::value>::type>
  169. bound_statement_iterator_range<FieldViewFwdIterator> bind(
  170. FieldViewFwdIterator params_first,
  171. FieldViewFwdIterator params_last
  172. ) const;
  173. private:
  174. bool valid_{false};
  175. std::uint32_t id_{0};
  176. std::uint16_t num_params_{0};
  177. statement(std::uint32_t id, std::uint16_t num_params) noexcept
  178. : valid_(true), id_(id), num_params_(num_params)
  179. {
  180. }
  181. #ifndef BOOST_MYSQL_DOXYGEN
  182. friend struct detail::access;
  183. #endif
  184. };
  185. } // namespace mysql
  186. } // namespace boost
  187. #include <boost/mysql/impl/statement.hpp>
  188. #endif