File indexing completed on 2025-07-05 08:39:51
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_MYSQL_DETAIL_EXECUTION_PROCESSOR_STATIC_RESULTS_IMPL_HPP
0009 #define BOOST_MYSQL_DETAIL_EXECUTION_PROCESSOR_STATIC_RESULTS_IMPL_HPP
0010
0011 #include <boost/mysql/detail/config.hpp>
0012
0013 #ifdef BOOST_MYSQL_CXX14
0014
0015 #include <boost/mysql/diagnostics.hpp>
0016 #include <boost/mysql/field_view.hpp>
0017 #include <boost/mysql/metadata.hpp>
0018 #include <boost/mysql/metadata_collection_view.hpp>
0019 #include <boost/mysql/string_view.hpp>
0020
0021 #include <boost/mysql/detail/execution_processor/execution_processor.hpp>
0022 #include <boost/mysql/detail/typing/readable_field_traits.hpp>
0023 #include <boost/mysql/detail/typing/row_traits.hpp>
0024
0025 #include <boost/assert.hpp>
0026 #include <boost/mp11/algorithm.hpp>
0027 #include <boost/mp11/integer_sequence.hpp>
0028
0029 #include <array>
0030 #include <cstddef>
0031
0032 namespace boost {
0033 namespace mysql {
0034 namespace detail {
0035
0036 using results_reset_fn_t = void (*)(void*);
0037 using results_parse_fn_t =
0038 error_code (*)(span<const std::size_t> pos_map, span<const field_view> from, void* to);
0039
0040 struct results_resultset_descriptor
0041 {
0042 std::size_t num_columns;
0043 name_table_t name_table;
0044 meta_check_fn_t meta_check;
0045 results_parse_fn_t parse_fn;
0046 };
0047
0048 struct static_per_resultset_data
0049 {
0050 std::size_t meta_offset{};
0051 std::size_t meta_size{};
0052 std::size_t info_offset{};
0053 std::size_t info_size{};
0054 bool has_ok_packet_data{false};
0055 std::uint64_t affected_rows{};
0056 std::uint64_t last_insert_id{};
0057 std::uint16_t warnings{};
0058 bool is_out_params{false};
0059 };
0060
0061 class results_external_data
0062 {
0063 public:
0064 struct ptr_data
0065 {
0066 void* rows;
0067 std::size_t* pos_map;
0068 static_per_resultset_data* per_resultset;
0069 };
0070
0071 results_external_data(
0072 span<const results_resultset_descriptor> desc,
0073 results_reset_fn_t reset,
0074 ptr_data ptr
0075 ) noexcept
0076 : desc_(desc), reset_(reset), ptr_(ptr)
0077 {
0078 }
0079
0080 void set_pointers(ptr_data ptr) noexcept { ptr_ = ptr; }
0081
0082 std::size_t num_resultsets() const noexcept { return desc_.size(); }
0083 std::size_t num_columns(std::size_t idx) const noexcept
0084 {
0085 BOOST_ASSERT(idx < num_resultsets());
0086 return desc_[idx].num_columns;
0087 }
0088 name_table_t name_table(std::size_t idx) const noexcept
0089 {
0090 BOOST_ASSERT(idx < num_resultsets());
0091 return desc_[idx].name_table;
0092 }
0093 meta_check_fn_t meta_check_fn(std::size_t idx) const noexcept
0094 {
0095 BOOST_ASSERT(idx < num_resultsets());
0096 return desc_[idx].meta_check;
0097 }
0098 results_parse_fn_t parse_fn(std::size_t idx) const noexcept
0099 {
0100 BOOST_ASSERT(idx < num_resultsets());
0101 return desc_[idx].parse_fn;
0102 }
0103 results_reset_fn_t reset_fn() const noexcept { return reset_; }
0104 void* rows() const noexcept { return ptr_.rows; }
0105 span<std::size_t> pos_map(std::size_t idx) const noexcept
0106 {
0107 return span<std::size_t>(ptr_.pos_map, num_columns(idx));
0108 }
0109 static_per_resultset_data& per_result(std::size_t idx) const noexcept
0110 {
0111 BOOST_ASSERT(idx < num_resultsets());
0112 return ptr_.per_resultset[idx];
0113 }
0114
0115 private:
0116 span<const results_resultset_descriptor> desc_;
0117 results_reset_fn_t reset_;
0118 ptr_data ptr_;
0119 };
0120
0121 class static_results_erased_impl final : public execution_processor
0122 {
0123 public:
0124 static_results_erased_impl(results_external_data ext) noexcept : ext_(ext) {}
0125
0126 results_external_data& ext_data() noexcept { return ext_; }
0127
0128 metadata_collection_view get_meta(std::size_t index) const noexcept
0129 {
0130 const auto& resultset_data = ext_.per_result(index);
0131 return metadata_collection_view(meta_.data() + resultset_data.meta_offset, resultset_data.meta_size);
0132 }
0133
0134 std::uint64_t get_affected_rows(std::size_t index) const noexcept
0135 {
0136 return ext_.per_result(index).affected_rows;
0137 }
0138
0139 std::uint64_t get_last_insert_id(std::size_t index) const noexcept
0140 {
0141 return ext_.per_result(index).last_insert_id;
0142 }
0143
0144 unsigned get_warning_count(std::size_t index) const noexcept { return ext_.per_result(index).warnings; }
0145
0146 string_view get_info(std::size_t index) const noexcept
0147 {
0148 const auto& resultset_data = ext_.per_result(index);
0149 return string_view(info_.data() + resultset_data.info_offset, resultset_data.info_size);
0150 }
0151
0152 bool get_is_out_params(std::size_t index) const noexcept { return ext_.per_result(index).is_out_params; }
0153
0154 private:
0155
0156 BOOST_MYSQL_DECL
0157 void reset_impl() noexcept override final;
0158
0159 BOOST_MYSQL_DECL
0160 error_code on_head_ok_packet_impl(const ok_view& pack, diagnostics& diag) override final;
0161
0162 BOOST_MYSQL_DECL
0163 void on_num_meta_impl(std::size_t num_columns) override final;
0164
0165 BOOST_MYSQL_DECL
0166 error_code on_meta_impl(const coldef_view& coldef, bool is_last, diagnostics& diag) override final;
0167
0168 BOOST_MYSQL_DECL
0169 error_code on_row_impl(span<const std::uint8_t> msg, const output_ref&, std::vector<field_view>& fields)
0170 override final;
0171
0172 BOOST_MYSQL_DECL
0173 error_code on_row_ok_packet_impl(const ok_view& pack) override final;
0174
0175 void on_row_batch_start_impl() override final {}
0176 void on_row_batch_finish_impl() override final {}
0177
0178
0179 results_external_data ext_;
0180 std::vector<metadata> meta_;
0181 std::vector<char> info_;
0182 std::size_t resultset_index_{0};
0183
0184
0185 span<std::size_t> current_pos_map() noexcept { return ext_.pos_map(resultset_index_ - 1); }
0186 span<const std::size_t> current_pos_map() const noexcept { return ext_.pos_map(resultset_index_ - 1); }
0187 name_table_t current_name_table() const noexcept { return ext_.name_table(resultset_index_ - 1); }
0188 static_per_resultset_data& current_resultset() noexcept { return ext_.per_result(resultset_index_ - 1); }
0189 metadata_collection_view current_resultset_meta() const noexcept
0190 {
0191 return get_meta(resultset_index_ - 1);
0192 }
0193
0194 BOOST_MYSQL_DECL
0195 static_per_resultset_data& add_resultset();
0196
0197 BOOST_MYSQL_DECL
0198 error_code on_ok_packet_impl(const ok_view& pack);
0199
0200 error_code meta_check(diagnostics& diag) const
0201 {
0202 return ext_.meta_check_fn(resultset_index_ - 1)(current_pos_map(), current_resultset_meta(), diag);
0203 }
0204 };
0205
0206 template <class... StaticRow>
0207 using results_rows_t = std::tuple<std::vector<underlying_row_t<StaticRow>>...>;
0208
0209 template <class... StaticRow>
0210 struct results_fns
0211 {
0212 using rows_t = results_rows_t<StaticRow...>;
0213
0214 struct reset_fn
0215 {
0216 rows_t& obj;
0217
0218 template <std::size_t I>
0219 void operator()(boost::mp11::mp_size_t<I>) const noexcept
0220 {
0221 std::get<I>(obj).clear();
0222 }
0223 };
0224
0225 static void reset(void* rows_ptr) noexcept
0226 {
0227 auto& rows = *static_cast<rows_t*>(rows_ptr);
0228 boost::mp11::mp_for_each<boost::mp11::mp_iota_c<sizeof...(StaticRow)>>(reset_fn{rows});
0229 }
0230
0231 template <std::size_t I>
0232 static error_code do_parse(span<const std::size_t> pos_map, span<const field_view> from, void* to)
0233 {
0234 using StaticRowT = mp11::mp_at_c<mp11::mp_list<StaticRow...>, I>;
0235 auto& v = std::get<I>(*static_cast<rows_t*>(to));
0236 v.emplace_back();
0237 return parse<StaticRowT>(pos_map, from, v.back());
0238 }
0239
0240 template <std::size_t I>
0241 static constexpr results_resultset_descriptor create_descriptor()
0242 {
0243 using StaticRowT = mp11::mp_at_c<mp11::mp_list<StaticRow...>, I>;
0244 return {
0245 get_row_size<StaticRowT>(),
0246 get_row_name_table<StaticRowT>(),
0247 &meta_check<StaticRowT>,
0248 &do_parse<I>,
0249 };
0250 }
0251
0252 template <std::size_t... I>
0253 static constexpr std::array<results_resultset_descriptor, sizeof...(StaticRow)> create_descriptors(mp11::index_sequence<
0254 I...>)
0255 {
0256 return {{create_descriptor<I>()...}};
0257 }
0258 };
0259
0260 template <class... StaticRow>
0261 BOOST_INLINE_CONSTEXPR std::array<results_resultset_descriptor, sizeof...(StaticRow)>
0262 results_resultset_descriptor_table = results_fns<StaticRow...>::create_descriptors(
0263 mp11::make_index_sequence<sizeof...(StaticRow)>()
0264 );
0265
0266 template <std::size_t I, class... StaticRow>
0267 using rows_span_t = boost::span<
0268 const typename std::tuple_element<I, std::tuple<underlying_row_t<StaticRow>...>>::type>;
0269
0270 template <BOOST_MYSQL_STATIC_ROW... StaticRow>
0271 class static_results_impl
0272 {
0273
0274 struct
0275 {
0276 results_rows_t<StaticRow...> rows;
0277 std::array<std::size_t, max_num_columns<StaticRow...>> pos_map{};
0278 std::array<static_per_resultset_data, sizeof...(StaticRow)> per_resultset{};
0279 } data_;
0280
0281
0282 static_results_erased_impl impl_;
0283
0284 results_external_data::ptr_data ptr_data() noexcept
0285 {
0286 return {
0287 &data_.rows,
0288 data_.pos_map.data(),
0289 data_.per_resultset.data(),
0290 };
0291 }
0292
0293 void set_pointers() noexcept { impl_.ext_data().set_pointers(ptr_data()); }
0294
0295 public:
0296 static_results_impl() noexcept
0297 : impl_(results_external_data(
0298 results_resultset_descriptor_table<StaticRow...>,
0299 &results_fns<StaticRow...>::reset,
0300 ptr_data()
0301 ))
0302 {
0303 }
0304
0305 static_results_impl(const static_results_impl& rhs) : data_(rhs.data_), impl_(rhs.impl_)
0306 {
0307 set_pointers();
0308 }
0309
0310 static_results_impl(static_results_impl&& rhs) noexcept
0311 : data_(std::move(rhs.data_)), impl_(std::move(rhs.impl_))
0312 {
0313 set_pointers();
0314 }
0315
0316 static_results_impl& operator=(const static_results_impl& rhs)
0317 {
0318 data_ = rhs.data_;
0319 impl_ = rhs.impl_;
0320 set_pointers();
0321 return *this;
0322 }
0323
0324 static_results_impl& operator=(static_results_impl&& rhs)
0325 {
0326 data_ = std::move(rhs.data_);
0327 impl_ = std::move(rhs.impl_);
0328 set_pointers();
0329 return *this;
0330 }
0331
0332
0333 template <std::size_t I>
0334 rows_span_t<I, StaticRow...> get_rows() const noexcept
0335 {
0336 return std::get<I>(data_.rows);
0337 }
0338
0339 const static_results_erased_impl& get_interface() const noexcept { return impl_; }
0340 static_results_erased_impl& get_interface() noexcept { return impl_; }
0341 };
0342
0343 }
0344 }
0345 }
0346
0347 #ifdef BOOST_MYSQL_HEADER_ONLY
0348 #include <boost/mysql/impl/static_results_impl.ipp>
0349 #endif
0350
0351 #endif
0352
0353 #endif