File indexing completed on 2025-01-18 09:42:38
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_MYSQL_DETAIL_EXECUTION_PROCESSOR_EXECUTION_PROCESSOR_HPP
0009 #define BOOST_MYSQL_DETAIL_EXECUTION_PROCESSOR_EXECUTION_PROCESSOR_HPP
0010
0011 #include <boost/mysql/diagnostics.hpp>
0012 #include <boost/mysql/error_code.hpp>
0013 #include <boost/mysql/field_view.hpp>
0014 #include <boost/mysql/metadata.hpp>
0015 #include <boost/mysql/metadata_mode.hpp>
0016 #include <boost/mysql/string_view.hpp>
0017
0018 #include <boost/mysql/detail/access.hpp>
0019 #include <boost/mysql/detail/coldef_view.hpp>
0020 #include <boost/mysql/detail/ok_view.hpp>
0021 #include <boost/mysql/detail/resultset_encoding.hpp>
0022
0023 #include <boost/assert.hpp>
0024 #include <boost/config.hpp>
0025 #include <boost/core/span.hpp>
0026
0027 #include <cstddef>
0028 #include <cstdint>
0029 #include <limits>
0030
0031 namespace boost {
0032 namespace mysql {
0033 namespace detail {
0034
0035
0036 class output_ref
0037 {
0038
0039 void* data_{};
0040
0041
0042 std::size_t max_size_{(std::numeric_limits<std::size_t>::max)()};
0043
0044
0045 std::size_t type_index_{};
0046
0047
0048 std::size_t offset_{};
0049
0050 public:
0051 constexpr output_ref() noexcept = default;
0052
0053 template <class T>
0054 constexpr output_ref(boost::span<T> span, std::size_t type_index, std::size_t offset = 0) noexcept
0055 : data_(span.data()), max_size_(span.size()), type_index_(type_index), offset_(offset)
0056 {
0057 }
0058
0059 std::size_t max_size() const noexcept { return max_size_; }
0060 std::size_t type_index() const noexcept { return type_index_; }
0061 std::size_t offset() const noexcept { return offset_; }
0062 void set_offset(std::size_t v) noexcept { offset_ = v; }
0063
0064 template <class T>
0065 T& span_element() const noexcept
0066 {
0067 BOOST_ASSERT(data_);
0068 return static_cast<T*>(data_)[offset_];
0069 }
0070 };
0071
0072 class execution_processor
0073 {
0074 public:
0075 virtual ~execution_processor() {}
0076
0077 void reset(resultset_encoding enc, metadata_mode mode) noexcept
0078 {
0079 state_ = state_t::reading_first;
0080 encoding_ = enc;
0081 mode_ = mode;
0082 seqnum_ = 0;
0083 remaining_meta_ = 0;
0084 reset_impl();
0085 }
0086
0087 BOOST_ATTRIBUTE_NODISCARD
0088 error_code on_head_ok_packet(const ok_view& pack, diagnostics& diag)
0089 {
0090 BOOST_ASSERT(is_reading_head());
0091 auto err = on_head_ok_packet_impl(pack, diag);
0092 set_state_for_ok(pack);
0093 return err;
0094 }
0095
0096 void on_num_meta(std::size_t num_columns)
0097 {
0098 BOOST_ASSERT(is_reading_head());
0099 on_num_meta_impl(num_columns);
0100 remaining_meta_ = num_columns;
0101 set_state(state_t::reading_metadata);
0102 }
0103
0104 BOOST_ATTRIBUTE_NODISCARD
0105 error_code on_meta(const coldef_view& pack, diagnostics& diag)
0106 {
0107 BOOST_ASSERT(is_reading_meta());
0108 bool is_last = --remaining_meta_ == 0;
0109 auto err = on_meta_impl(pack, is_last, diag);
0110 if (is_last)
0111 set_state(state_t::reading_rows);
0112 return err;
0113 }
0114
0115 void on_row_batch_start()
0116 {
0117 BOOST_ASSERT(is_reading_rows());
0118 on_row_batch_start_impl();
0119 }
0120
0121 void on_row_batch_finish() { on_row_batch_finish_impl(); }
0122
0123 BOOST_ATTRIBUTE_NODISCARD
0124 error_code on_row(span<const std::uint8_t> msg, const output_ref& ref, std::vector<field_view>& storage)
0125 {
0126 BOOST_ASSERT(is_reading_rows());
0127 return on_row_impl(msg, ref, storage);
0128 }
0129
0130 BOOST_ATTRIBUTE_NODISCARD
0131 error_code on_row_ok_packet(const ok_view& pack)
0132 {
0133 BOOST_ASSERT(is_reading_rows());
0134 auto err = on_row_ok_packet_impl(pack);
0135 set_state_for_ok(pack);
0136 return err;
0137 }
0138
0139 bool is_reading_first() const noexcept { return state_ == state_t::reading_first; }
0140 bool is_reading_first_subseq() const noexcept { return state_ == state_t::reading_first_subseq; }
0141 bool is_reading_head() const noexcept
0142 {
0143 return state_ == state_t::reading_first || state_ == state_t::reading_first_subseq;
0144 }
0145 bool is_reading_meta() const noexcept { return state_ == state_t::reading_metadata; }
0146 bool is_reading_rows() const noexcept { return state_ == state_t::reading_rows; }
0147 bool is_complete() const noexcept { return state_ == state_t::complete; }
0148
0149 resultset_encoding encoding() const noexcept { return encoding_; }
0150 std::uint8_t& sequence_number() noexcept { return seqnum_; }
0151 metadata_mode meta_mode() const noexcept { return mode_; }
0152
0153 protected:
0154 virtual void reset_impl() noexcept = 0;
0155 virtual error_code on_head_ok_packet_impl(const ok_view& pack, diagnostics& diag) = 0;
0156 virtual void on_num_meta_impl(std::size_t num_columns) = 0;
0157 virtual error_code on_meta_impl(const coldef_view& coldef, bool is_last, diagnostics& diag) = 0;
0158 virtual error_code on_row_ok_packet_impl(const ok_view& pack) = 0;
0159 virtual error_code on_row_impl(
0160 span<const std::uint8_t> msg,
0161 const output_ref& ref,
0162 std::vector<field_view>& storage
0163 ) = 0;
0164 virtual void on_row_batch_start_impl() = 0;
0165 virtual void on_row_batch_finish_impl() = 0;
0166
0167 metadata create_meta(const coldef_view& coldef) const
0168 {
0169 return access::construct<metadata>(coldef, mode_ == metadata_mode::full);
0170 }
0171
0172 private:
0173 enum class state_t
0174 {
0175
0176 reading_first,
0177
0178
0179
0180 reading_first_subseq,
0181
0182
0183 reading_metadata,
0184
0185
0186 reading_rows,
0187
0188
0189 complete
0190 };
0191
0192 state_t state_{state_t::reading_first};
0193 resultset_encoding encoding_{resultset_encoding::text};
0194 std::uint8_t seqnum_{};
0195 metadata_mode mode_{metadata_mode::minimal};
0196 std::size_t remaining_meta_{};
0197
0198 void set_state(state_t v) noexcept { state_ = v; }
0199
0200 void set_state_for_ok(const ok_view& pack) noexcept
0201 {
0202 if (pack.more_results())
0203 {
0204 set_state(state_t::reading_first_subseq);
0205 }
0206 else
0207 {
0208 set_state(state_t::complete);
0209 }
0210 }
0211 };
0212
0213 }
0214 }
0215 }
0216
0217 #endif