File indexing completed on 2025-09-18 08:52:42
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_MYSQL_IMPL_INTERNAL_SANSIO_START_EXECUTION_HPP
0009 #define BOOST_MYSQL_IMPL_INTERNAL_SANSIO_START_EXECUTION_HPP
0010
0011 #include <boost/mysql/character_set.hpp>
0012 #include <boost/mysql/client_errc.hpp>
0013 #include <boost/mysql/constant_string_view.hpp>
0014 #include <boost/mysql/diagnostics.hpp>
0015 #include <boost/mysql/error_code.hpp>
0016 #include <boost/mysql/format_sql.hpp>
0017
0018 #include <boost/mysql/detail/algo_params.hpp>
0019 #include <boost/mysql/detail/any_execution_request.hpp>
0020 #include <boost/mysql/detail/execution_processor/execution_processor.hpp>
0021 #include <boost/mysql/detail/next_action.hpp>
0022 #include <boost/mysql/detail/output_string.hpp>
0023 #include <boost/mysql/detail/resultset_encoding.hpp>
0024
0025 #include <boost/mysql/impl/internal/coroutine.hpp>
0026 #include <boost/mysql/impl/internal/protocol/impl/serialization_context.hpp>
0027 #include <boost/mysql/impl/internal/protocol/serialization.hpp>
0028 #include <boost/mysql/impl/internal/sansio/connection_state_data.hpp>
0029 #include <boost/mysql/impl/internal/sansio/read_resultset_head.hpp>
0030
0031 #include <boost/core/span.hpp>
0032
0033 namespace boost {
0034 namespace mysql {
0035 namespace detail {
0036
0037
0038 struct query_with_params
0039 {
0040 constant_string_view query;
0041 span<const format_arg> args;
0042 format_options opts;
0043
0044 void serialize(serialization_context& ctx) const
0045 {
0046
0047 auto fmt_ctx = access::construct<format_context_base>(output_string_ref::create(ctx), opts);
0048
0049
0050 ctx.add(0x03);
0051
0052
0053 vformat_sql_to(fmt_ctx, query, args);
0054
0055
0056 ctx.add_error(fmt_ctx.error_state());
0057 }
0058 };
0059
0060 class start_execution_algo
0061 {
0062 int resume_point_{0};
0063 read_resultset_head_algo read_head_st_;
0064 any_execution_request req_;
0065 bool is_top_level_;
0066
0067 std::uint8_t& seqnum() { return processor().sequence_number(); }
0068 execution_processor& processor() { return read_head_st_.processor(); }
0069
0070 static resultset_encoding get_encoding(any_execution_request::type_t type)
0071 {
0072 switch (type)
0073 {
0074 case any_execution_request::type_t::query:
0075 case any_execution_request::type_t::query_with_params: return resultset_encoding::text;
0076 case any_execution_request::type_t::stmt: return resultset_encoding::binary;
0077 default: BOOST_ASSERT(false); return resultset_encoding::text;
0078 }
0079 }
0080
0081 next_action write_query_with_params(
0082 connection_state_data& st,
0083 any_execution_request::data_t::query_with_params_t data
0084 )
0085 {
0086
0087 if (st.current_charset.name == nullptr)
0088 {
0089 return error_code(client_errc::unknown_character_set);
0090 }
0091 format_options opts{st.current_charset, st.backslash_escapes};
0092
0093
0094 return st.write(query_with_params{data.query, data.args, opts}, seqnum());
0095 }
0096
0097 next_action write_stmt(connection_state_data& st, any_execution_request::data_t::stmt_t data)
0098 {
0099 if (data.num_params != data.params.size())
0100 return error_code(client_errc::wrong_num_params);
0101 return st.write(execute_stmt_command{data.stmt_id, data.params}, seqnum());
0102 }
0103
0104 next_action compose_request(connection_state_data& st)
0105 {
0106 switch (req_.type)
0107 {
0108 case any_execution_request::type_t::query: return st.write(query_command{req_.data.query}, seqnum());
0109 case any_execution_request::type_t::query_with_params:
0110 return write_query_with_params(st, req_.data.query_with_params);
0111 case any_execution_request::type_t::stmt: return write_stmt(st, req_.data.stmt);
0112 default: BOOST_ASSERT(false); return next_action();
0113 }
0114 }
0115
0116 public:
0117
0118
0119 start_execution_algo(start_execution_algo_params params, bool is_top_level = true) noexcept
0120 : read_head_st_({params.proc}, false), req_(params.req), is_top_level_(is_top_level)
0121 {
0122 }
0123
0124 next_action resume(connection_state_data& st, diagnostics& diag, error_code ec)
0125 {
0126 next_action act;
0127
0128 switch (resume_point_)
0129 {
0130 case 0:
0131
0132 if (is_top_level_)
0133 {
0134 ec = st.check_status_ready();
0135 if (ec)
0136 return ec;
0137 }
0138
0139
0140 processor().reset(get_encoding(req_.type), st.meta_mode);
0141
0142
0143 BOOST_MYSQL_YIELD(resume_point_, 1, compose_request(st))
0144 if (ec)
0145 return ec;
0146
0147
0148
0149
0150 if (is_top_level_)
0151 st.status = connection_status::engaged_in_multi_function;
0152
0153
0154 while (!(act = read_head_st_.resume(st, diag, ec)).is_done())
0155 BOOST_MYSQL_YIELD(resume_point_, 2, act)
0156
0157
0158 if (act.error())
0159 {
0160 if (is_top_level_)
0161 st.status = connection_status::ready;
0162 return act;
0163 }
0164
0165
0166 if (processor().is_complete() && is_top_level_)
0167 st.status = connection_status::ready;
0168 }
0169
0170 return next_action();
0171 }
0172 };
0173
0174 }
0175 }
0176 }
0177
0178 #endif