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_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 // A type-erased reference to be used as the output range for static_execution_state
0036 class output_ref
0037 {
0038     // Pointer to the first element of the span
0039     void* data_{};
0040 
0041     // Number of elements in the span
0042     std::size_t max_size_{(std::numeric_limits<std::size_t>::max)()};
0043 
0044     // Identifier for the type of elements. Index in the resultset type list
0045     std::size_t type_index_{};
0046 
0047     // Offset into the span's data (static_execution_state). Otherwise unused
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         // waiting for 1st packet, for the 1st resultset
0176         reading_first,
0177 
0178         // same, but for subsequent resultsets (distiguised to provide a cleaner xp to
0179         // the user in (static_)execution_state)
0180         reading_first_subseq,
0181 
0182         // waiting for metadata packets
0183         reading_metadata,
0184 
0185         // waiting for rows
0186         reading_rows,
0187 
0188         // done
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 }  // namespace detail
0214 }  // namespace mysql
0215 }  // namespace boost
0216 
0217 #endif