read_resultset_head.hpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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_IMPL_INTERNAL_SANSIO_READ_RESULTSET_HEAD_HPP
  8. #define BOOST_MYSQL_IMPL_INTERNAL_SANSIO_READ_RESULTSET_HEAD_HPP
  9. #include <boost/mysql/diagnostics.hpp>
  10. #include <boost/mysql/error_code.hpp>
  11. #include <boost/mysql/detail/algo_params.hpp>
  12. #include <boost/mysql/detail/execution_processor/execution_processor.hpp>
  13. #include <boost/mysql/impl/internal/coroutine.hpp>
  14. #include <boost/mysql/impl/internal/sansio/connection_state_data.hpp>
  15. namespace boost {
  16. namespace mysql {
  17. namespace detail {
  18. inline error_code process_execution_response(
  19. connection_state_data& st,
  20. execution_processor& proc,
  21. span<const std::uint8_t> msg,
  22. diagnostics& diag
  23. )
  24. {
  25. auto response = deserialize_execute_response(msg, st.flavor, diag);
  26. error_code err;
  27. switch (response.type)
  28. {
  29. case execute_response::type_t::error: err = response.data.err; break;
  30. case execute_response::type_t::ok_packet:
  31. st.backslash_escapes = response.data.ok_pack.backslash_escapes();
  32. err = proc.on_head_ok_packet(response.data.ok_pack, diag);
  33. break;
  34. case execute_response::type_t::num_fields: proc.on_num_meta(response.data.num_fields); break;
  35. }
  36. return err;
  37. }
  38. inline error_code process_field_definition(
  39. execution_processor& proc,
  40. span<const std::uint8_t> msg,
  41. diagnostics& diag
  42. )
  43. {
  44. // Deserialize the message
  45. coldef_view coldef{};
  46. auto err = deserialize_column_definition(msg, coldef);
  47. if (err)
  48. return err;
  49. // Notify the processor
  50. return proc.on_meta(coldef, diag);
  51. }
  52. class read_resultset_head_algo
  53. {
  54. diagnostics* diag_;
  55. execution_processor* proc_;
  56. struct state_t
  57. {
  58. int resume_point{0};
  59. } state_;
  60. public:
  61. read_resultset_head_algo(read_resultset_head_algo_params params) noexcept
  62. : diag_(params.diag), proc_(params.proc)
  63. {
  64. }
  65. void reset() { state_ = state_t{}; }
  66. diagnostics& diag() { return *diag_; }
  67. execution_processor& processor() { return *proc_; }
  68. next_action resume(connection_state_data& st, error_code ec)
  69. {
  70. if (ec)
  71. return ec;
  72. switch (state_.resume_point)
  73. {
  74. case 0:
  75. // Clear diagnostics
  76. diag_->clear();
  77. // If we're not reading head, return
  78. if (!proc_->is_reading_head())
  79. return next_action();
  80. // Read the response
  81. BOOST_MYSQL_YIELD(state_.resume_point, 1, st.read(proc_->sequence_number()))
  82. // Response may be: ok_packet, err_packet, local infile request
  83. // (not implemented), or response with fields
  84. ec = process_execution_response(st, *proc_, st.reader.message(), *diag_);
  85. if (ec)
  86. return ec;
  87. // Read all of the field definitions
  88. while (proc_->is_reading_meta())
  89. {
  90. // Read a message
  91. BOOST_MYSQL_YIELD(state_.resume_point, 2, st.read(proc_->sequence_number()))
  92. // Process the metadata packet
  93. ec = process_field_definition(*proc_, st.reader.message(), *diag_);
  94. if (ec)
  95. return ec;
  96. }
  97. // No EOF packet is expected here, as we require deprecate EOF capabilities
  98. }
  99. return next_action();
  100. }
  101. };
  102. } // namespace detail
  103. } // namespace mysql
  104. } // namespace boost
  105. #endif