Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:42:38

0001 //
0002 // Copyright (c) 2019-2023 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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};  // The OK packet information is default constructed, or actual data?
0055     std::uint64_t affected_rows{};   // OK packet data
0056     std::uint64_t last_insert_id{};  // OK packet data
0057     std::uint16_t warnings{};        // OK packet data
0058     bool is_out_params{false};       // Does this resultset contain OUT param information?
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     // Virtual implementations
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     // Data
0179     results_external_data ext_;
0180     std::vector<metadata> meta_;
0181     std::vector<char> info_;
0182     std::size_t resultset_index_{0};
0183 
0184     // Helpers
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<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         auto& v = std::get<I>(*static_cast<rows_t*>(to));
0235         v.emplace_back();
0236         return parse(pos_map, from, v.back());
0237     }
0238 
0239     template <std::size_t I>
0240     static constexpr results_resultset_descriptor create_descriptor()
0241     {
0242         using T = mp11::mp_at_c<mp11::mp_list<StaticRow...>, I>;
0243         return {
0244             get_row_size<T>(),
0245             get_row_name_table<T>(),
0246             &meta_check<T>,
0247             &do_parse<I>,
0248         };
0249     }
0250 
0251     template <std::size_t... I>
0252     static constexpr std::array<results_resultset_descriptor, sizeof...(StaticRow)> create_descriptors(mp11::index_sequence<
0253                                                                                                        I...>)
0254     {
0255         return {{create_descriptor<I>()...}};
0256     }
0257 };
0258 
0259 template <class... StaticRow>
0260 constexpr std::array<results_resultset_descriptor, sizeof...(StaticRow)>
0261     results_resultset_descriptor_table = results_fns<StaticRow...>::create_descriptors(
0262         mp11::make_index_sequence<sizeof...(StaticRow)>()
0263     );
0264 
0265 template <BOOST_MYSQL_STATIC_ROW... StaticRow>
0266 class static_results_impl
0267 {
0268     // Data that requires knowing template params
0269     struct
0270     {
0271         results_rows_t<StaticRow...> rows;
0272         std::array<std::size_t, max_num_columns<StaticRow...>> pos_map{};
0273         std::array<static_per_resultset_data, sizeof...(StaticRow)> per_resultset{};
0274     } data_;
0275 
0276     // The type-erased impl, that will use pointers to the above storage
0277     static_results_erased_impl impl_;
0278 
0279     results_external_data::ptr_data ptr_data() noexcept
0280     {
0281         return {
0282             &data_.rows,
0283             data_.pos_map.data(),
0284             data_.per_resultset.data(),
0285         };
0286     }
0287 
0288     void set_pointers() noexcept { impl_.ext_data().set_pointers(ptr_data()); }
0289 
0290 public:
0291     static_results_impl() noexcept
0292         : impl_(results_external_data(
0293               results_resultset_descriptor_table<StaticRow...>,
0294               &results_fns<StaticRow...>::reset,
0295               ptr_data()
0296           ))
0297     {
0298     }
0299 
0300     static_results_impl(const static_results_impl& rhs) : data_(rhs.data_), impl_(rhs.impl_)
0301     {
0302         set_pointers();
0303     }
0304 
0305     static_results_impl(static_results_impl&& rhs) noexcept
0306         : data_(std::move(rhs.data_)), impl_(std::move(rhs.impl_))
0307     {
0308         set_pointers();
0309     }
0310 
0311     static_results_impl& operator=(const static_results_impl& rhs)
0312     {
0313         data_ = rhs.data_;
0314         impl_ = rhs.impl_;
0315         set_pointers();
0316         return *this;
0317     }
0318 
0319     static_results_impl& operator=(static_results_impl&& rhs)
0320     {
0321         data_ = std::move(rhs.data_);
0322         impl_ = std::move(rhs.impl_);
0323         set_pointers();
0324         return *this;
0325     }
0326 
0327     // User facing
0328     template <std::size_t I>
0329     boost::span<const typename std::tuple_element<I, std::tuple<StaticRow...>>::type> get_rows(
0330     ) const noexcept
0331     {
0332         return std::get<I>(data_.rows);
0333     }
0334 
0335     const static_results_erased_impl& get_interface() const noexcept { return impl_; }
0336     static_results_erased_impl& get_interface() noexcept { return impl_; }
0337 };
0338 
0339 }  // namespace detail
0340 }  // namespace mysql
0341 }  // namespace boost
0342 
0343 #ifdef BOOST_MYSQL_HEADER_ONLY
0344 #include <boost/mysql/impl/static_results_impl.ipp>
0345 #endif
0346 
0347 #endif  // BOOST_MYSQL_CXX14
0348 
0349 #endif