Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-11-08 09:50:32

0001 //
0002 // Copyright (c) 2019-2025 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_IMPL_INTERNAL_SANSIO_READ_RESULTSET_HEAD_HPP
0009 #define BOOST_MYSQL_IMPL_INTERNAL_SANSIO_READ_RESULTSET_HEAD_HPP
0010 
0011 #include <boost/mysql/diagnostics.hpp>
0012 #include <boost/mysql/error_code.hpp>
0013 
0014 #include <boost/mysql/detail/algo_params.hpp>
0015 #include <boost/mysql/detail/execution_processor/execution_processor.hpp>
0016 #include <boost/mysql/detail/next_action.hpp>
0017 
0018 #include <boost/mysql/impl/internal/coroutine.hpp>
0019 #include <boost/mysql/impl/internal/sansio/connection_state_data.hpp>
0020 
0021 namespace boost {
0022 namespace mysql {
0023 namespace detail {
0024 
0025 inline error_code process_execution_response(
0026     connection_state_data& st,
0027     execution_processor& proc,
0028     span<const std::uint8_t> msg,
0029     diagnostics& diag
0030 )
0031 {
0032     auto response = deserialize_execute_response(msg, st.flavor, diag);
0033     error_code err;
0034     switch (response.type)
0035     {
0036     case execute_response::type_t::error: err = response.data.err; break;
0037     case execute_response::type_t::ok_packet:
0038         st.backslash_escapes = response.data.ok_pack.backslash_escapes();
0039         err = proc.on_head_ok_packet(response.data.ok_pack, diag);
0040         break;
0041     case execute_response::type_t::num_fields: proc.on_num_meta(response.data.num_fields); break;
0042     }
0043     return err;
0044 }
0045 
0046 inline error_code process_field_definition(
0047     execution_processor& proc,
0048     span<const std::uint8_t> msg,
0049     diagnostics& diag
0050 )
0051 {
0052     // Deserialize the message
0053     coldef_view coldef{};
0054     auto err = deserialize_column_definition(msg, coldef);
0055     if (err)
0056         return err;
0057 
0058     // Notify the processor
0059     return proc.on_meta(coldef, diag);
0060 }
0061 
0062 class read_resultset_head_algo
0063 {
0064     execution_processor* proc_;
0065     bool is_top_level_;
0066 
0067     struct state_t
0068     {
0069         int resume_point{0};
0070     } state_;
0071 
0072     // Status changes are only performed if we're the top-level algorithm.
0073     // After an error, multi-function operations are considered finished
0074     void maybe_set_status_ready(connection_state_data& st) const
0075     {
0076         if (is_top_level_)
0077             st.status = connection_status::ready;
0078     }
0079 
0080 public:
0081     read_resultset_head_algo(read_resultset_head_algo_params params, bool is_top_level = true) noexcept
0082         : proc_(params.proc), is_top_level_(is_top_level)
0083     {
0084     }
0085 
0086     void reset() { state_ = state_t{}; }
0087 
0088     execution_processor& processor() { return *proc_; }
0089 
0090     next_action resume(connection_state_data& st, diagnostics& diag, error_code ec)
0091     {
0092         switch (state_.resume_point)
0093         {
0094         case 0:
0095 
0096             // If we're not reading head, return (for compatibility, we don't error here).
0097             if (!proc_->is_reading_head())
0098                 return next_action();
0099 
0100             // Check connection status. The check is only correct if we're the top-level algorithm
0101             if (is_top_level_)
0102             {
0103                 ec = st.check_status_multi_function();
0104                 if (ec)
0105                     return ec;
0106             }
0107 
0108             // Read the response
0109             BOOST_MYSQL_YIELD(state_.resume_point, 1, st.read(proc_->sequence_number()))
0110             if (ec)
0111             {
0112                 maybe_set_status_ready(st);
0113                 return ec;
0114             }
0115 
0116             // Response may be: ok_packet, err_packet, local infile request
0117             // (not implemented), or response with fields
0118             ec = process_execution_response(st, *proc_, st.reader.message(), diag);
0119             if (ec)
0120             {
0121                 maybe_set_status_ready(st);
0122                 return ec;
0123             }
0124 
0125             // Read all of the field definitions
0126             while (proc_->is_reading_meta())
0127             {
0128                 // Read a message
0129                 BOOST_MYSQL_YIELD(state_.resume_point, 2, st.read(proc_->sequence_number()))
0130                 if (ec)
0131                 {
0132                     maybe_set_status_ready(st);
0133                     return ec;
0134                 }
0135 
0136                 // Process the metadata packet
0137                 ec = process_field_definition(*proc_, st.reader.message(), diag);
0138                 if (ec)
0139                 {
0140                     maybe_set_status_ready(st);
0141                     return ec;
0142                 }
0143             }
0144 
0145             // No EOF packet is expected here, as we require deprecate EOF capabilities
0146 
0147             // If the received the final OK packet, we're no longer running a multi-function op
0148             if (proc_->is_complete() && is_top_level_)
0149                 st.status = connection_status::ready;
0150         }
0151 
0152         return next_action();
0153     }
0154 };
0155 
0156 }  // namespace detail
0157 }  // namespace mysql
0158 }  // namespace boost
0159 
0160 #endif