File indexing completed on 2025-10-18 08:52:50
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_MYSQL_DETAIL_CONNECTION_IMPL_HPP
0009 #define BOOST_MYSQL_DETAIL_CONNECTION_IMPL_HPP
0010
0011 #include <boost/mysql/any_address.hpp>
0012 #include <boost/mysql/connect_params.hpp>
0013 #include <boost/mysql/diagnostics.hpp>
0014 #include <boost/mysql/error_code.hpp>
0015 #include <boost/mysql/execution_state.hpp>
0016 #include <boost/mysql/field_view.hpp>
0017 #include <boost/mysql/handshake_params.hpp>
0018 #include <boost/mysql/metadata_mode.hpp>
0019 #include <boost/mysql/rows_view.hpp>
0020 #include <boost/mysql/statement.hpp>
0021 #include <boost/mysql/string_view.hpp>
0022
0023 #include <boost/mysql/detail/access.hpp>
0024 #include <boost/mysql/detail/algo_params.hpp>
0025 #include <boost/mysql/detail/config.hpp>
0026 #include <boost/mysql/detail/connect_params_helpers.hpp>
0027 #include <boost/mysql/detail/engine.hpp>
0028 #include <boost/mysql/detail/execution_processor/execution_processor.hpp>
0029 #include <boost/mysql/detail/initiation_base.hpp>
0030 #include <boost/mysql/detail/intermediate_handler.hpp>
0031
0032 #include <boost/asio/any_io_executor.hpp>
0033 #include <boost/optional/optional.hpp>
0034 #include <boost/system/result.hpp>
0035
0036 #include <cstddef>
0037 #include <cstdint>
0038 #include <cstring>
0039 #include <memory>
0040 #include <type_traits>
0041 #include <utility>
0042 #include <vector>
0043
0044 namespace boost {
0045 namespace mysql {
0046
0047
0048 template <class... StaticRow>
0049 class static_execution_state;
0050
0051 struct character_set;
0052 class pipeline_request;
0053
0054 namespace detail {
0055
0056
0057
0058
0059 class connection_state;
0060
0061 struct connection_state_deleter
0062 {
0063 BOOST_MYSQL_DECL void operator()(connection_state*) const;
0064 };
0065
0066 BOOST_MYSQL_DECL std::vector<field_view>& get_shared_fields(connection_state&);
0067
0068 template <class AlgoParams>
0069 any_resumable_ref setup(connection_state&, diagnostics&, const AlgoParams&);
0070
0071
0072 template <class AlgoParams>
0073 typename AlgoParams::result_type get_result(const connection_state&);
0074
0075
0076
0077
0078 template <class AlgoParams>
0079 using has_void_result = std::is_same<typename AlgoParams::result_type, void>;
0080
0081 template <class AlgoParams, bool is_void>
0082 struct completion_signature_impl;
0083
0084 template <class AlgoParams>
0085 struct completion_signature_impl<AlgoParams, true>
0086 {
0087
0088 typedef void(type)(error_code);
0089 };
0090
0091 template <class AlgoParams>
0092 struct completion_signature_impl<AlgoParams, false>
0093 {
0094
0095 typedef void(type)(error_code, typename AlgoParams::result_type);
0096 };
0097
0098 template <class AlgoParams>
0099 using completion_signature_t = typename completion_signature_impl<
0100 AlgoParams,
0101 has_void_result<AlgoParams>::value>::type;
0102
0103
0104 template <class AlgoParams>
0105 struct generic_algo_fn
0106 {
0107 static_assert(!has_void_result<AlgoParams>::value, "Internal error: result_type should be non-void");
0108
0109 using result_t = typename AlgoParams::result_type;
0110
0111 template <class Handler>
0112 void operator()(Handler&& handler, error_code ec)
0113 {
0114 std::move(handler)(ec, ec ? result_t{} : get_result<AlgoParams>(*st));
0115 }
0116
0117 connection_state* st;
0118 };
0119
0120
0121
0122 class connection_impl
0123 {
0124 std::unique_ptr<engine> engine_;
0125 std::unique_ptr<connection_state, connection_state_deleter> st_;
0126
0127 asio::any_io_executor get_executor() const { return engine_->get_executor(); }
0128
0129
0130 template <class T>
0131 static auto make_request(T&& input, connection_state& st)
0132 -> decltype(execution_request_traits<typename std::decay<T>::type>::make_request(
0133 std::forward<T>(input),
0134 get_shared_fields(st)
0135 ))
0136 {
0137 return execution_request_traits<typename std::decay<T>::type>::make_request(
0138 std::forward<T>(input),
0139 get_shared_fields(st)
0140 );
0141 }
0142
0143
0144 template <class AlgoParams>
0145 typename AlgoParams::result_type run_impl(
0146 AlgoParams params,
0147 error_code& ec,
0148 diagnostics& diag,
0149 std::true_type
0150 )
0151 {
0152 engine_->run(setup(*st_, diag, params), ec);
0153 }
0154
0155 template <class AlgoParams>
0156 typename AlgoParams::result_type run_impl(
0157 AlgoParams params,
0158 error_code& ec,
0159 diagnostics& diag,
0160 std::false_type
0161 )
0162 {
0163 engine_->run(setup(*st_, diag, params), ec);
0164 return get_result<AlgoParams>(*st_);
0165 }
0166
0167 template <class AlgoParams, class Handler>
0168 static void async_run_impl(
0169 engine& eng,
0170 connection_state& st,
0171 AlgoParams params,
0172 diagnostics& diag,
0173 Handler&& handler,
0174 std::true_type
0175 )
0176 {
0177 eng.async_run(setup(st, diag, params), std::forward<Handler>(handler));
0178 }
0179
0180 template <class AlgoParams, class Handler>
0181 static void async_run_impl(
0182 engine& eng,
0183 connection_state& st,
0184 AlgoParams params,
0185 diagnostics& diag,
0186 Handler&& handler,
0187 std::false_type
0188 )
0189 {
0190 eng.async_run(
0191 setup(st, diag, params),
0192 make_intermediate_handler(generic_algo_fn<AlgoParams>{&st}, std::forward<Handler>(handler))
0193 );
0194 }
0195
0196 template <class AlgoParams, class Handler>
0197 static void async_run_impl(
0198 engine& eng,
0199 connection_state& st,
0200 AlgoParams params,
0201 diagnostics& diag,
0202 Handler&& handler
0203 )
0204 {
0205 async_run_impl(eng, st, params, diag, std::forward<Handler>(handler), has_void_result<AlgoParams>{});
0206 }
0207
0208 struct run_algo_initiation : initiation_base
0209 {
0210 using initiation_base::initiation_base;
0211
0212 template <class Handler, class AlgoParams>
0213 void operator()(
0214 Handler&& handler,
0215 diagnostics* diag,
0216 engine* eng,
0217 connection_state* st,
0218 AlgoParams params
0219 )
0220 {
0221 async_run_impl(*eng, *st, params, *diag, std::forward<Handler>(handler));
0222 }
0223 };
0224
0225
0226 static connect_algo_params make_params_connect(const void* server_address, const handshake_params& params)
0227 {
0228 return connect_algo_params{server_address, params, false};
0229 }
0230
0231 static connect_algo_params make_params_connect_v2(const connect_params& params)
0232 {
0233 return connect_algo_params{
0234 ¶ms.server_address,
0235 make_hparams(params),
0236 params.server_address.type() == address_type::unix_path
0237 };
0238 }
0239
0240 template <class EndpointType>
0241 struct initiate_connect : initiation_base
0242 {
0243 using initiation_base::initiation_base;
0244
0245 template <class Handler>
0246 void operator()(
0247 Handler&& handler,
0248 diagnostics* diag,
0249 engine* eng,
0250 connection_state* st,
0251 const EndpointType& endpoint,
0252 handshake_params params
0253 )
0254 {
0255 async_run_impl(
0256 *eng,
0257 *st,
0258 make_params_connect(&endpoint, params),
0259 *diag,
0260 std::forward<Handler>(handler)
0261 );
0262 }
0263 };
0264
0265 struct initiate_connect_v2 : initiation_base
0266 {
0267 using initiation_base::initiation_base;
0268
0269 template <class Handler>
0270 void operator()(
0271 Handler&& handler,
0272 diagnostics* diag,
0273 engine* eng,
0274 connection_state* st,
0275 const connect_params* params
0276 )
0277 {
0278 async_run_impl(*eng, *st, make_params_connect_v2(*params), *diag, std::forward<Handler>(handler));
0279 }
0280 };
0281
0282
0283 struct initiate_execute : initiation_base
0284 {
0285 using initiation_base::initiation_base;
0286
0287 template <class Handler, class ExecutionRequest>
0288 void operator()(
0289 Handler&& handler,
0290 diagnostics* diag,
0291 engine* eng,
0292 connection_state* st,
0293 ExecutionRequest&& req,
0294 execution_processor* proc
0295 )
0296 {
0297 async_run_impl(
0298 *eng,
0299 *st,
0300 execute_algo_params{make_request(std::forward<ExecutionRequest>(req), *st), proc},
0301 *diag,
0302 std::forward<Handler>(handler)
0303 );
0304 }
0305 };
0306
0307
0308 struct initiate_start_execution : initiation_base
0309 {
0310 using initiation_base::initiation_base;
0311
0312 template <class Handler, class ExecutionRequest>
0313 void operator()(
0314 Handler&& handler,
0315 diagnostics* diag,
0316 engine* eng,
0317 connection_state* st,
0318 ExecutionRequest&& req,
0319 execution_processor* proc
0320 )
0321 {
0322 async_run_impl(
0323 *eng,
0324 *st,
0325 start_execution_algo_params{make_request(std::forward<ExecutionRequest>(req), *st), proc},
0326 *diag,
0327 std::forward<Handler>(handler)
0328 );
0329 }
0330 };
0331
0332 public:
0333 BOOST_MYSQL_DECL connection_impl(
0334 std::size_t read_buff_size,
0335 std::size_t max_buffer_size,
0336 std::unique_ptr<engine> eng
0337 );
0338
0339 BOOST_MYSQL_DECL metadata_mode meta_mode() const;
0340 BOOST_MYSQL_DECL void set_meta_mode(metadata_mode m);
0341 BOOST_MYSQL_DECL bool ssl_active() const;
0342 BOOST_MYSQL_DECL bool backslash_escapes() const;
0343 BOOST_MYSQL_DECL system::result<character_set> current_character_set() const;
0344 BOOST_MYSQL_DECL boost::optional<std::uint32_t> connection_id() const;
0345 BOOST_MYSQL_DECL diagnostics& shared_diag();
0346
0347 engine& get_engine()
0348 {
0349 BOOST_ASSERT(engine_);
0350 return *engine_;
0351 }
0352
0353 const engine& get_engine() const
0354 {
0355 BOOST_ASSERT(engine_);
0356 return *engine_;
0357 }
0358
0359
0360 template <class AlgoParams>
0361 typename AlgoParams::result_type run(AlgoParams params, error_code& ec, diagnostics& diag)
0362 {
0363 return run_impl(params, ec, diag, has_void_result<AlgoParams>{});
0364 }
0365
0366 template <class AlgoParams, class CompletionToken>
0367 auto async_run(AlgoParams params, diagnostics& diag, CompletionToken&& token)
0368 -> decltype(asio::async_initiate<CompletionToken, completion_signature_t<AlgoParams>>(
0369 run_algo_initiation(get_executor()),
0370 token,
0371 &diag,
0372 engine_.get(),
0373 st_.get(),
0374 params
0375 ))
0376 {
0377 return asio::async_initiate<CompletionToken, completion_signature_t<AlgoParams>>(
0378 run_algo_initiation(get_executor()),
0379 token,
0380 &diag,
0381 engine_.get(),
0382 st_.get(),
0383 params
0384 );
0385 }
0386
0387
0388 template <class EndpointType>
0389 void connect(
0390 const EndpointType& endpoint,
0391 const handshake_params& params,
0392 error_code& err,
0393 diagnostics& diag
0394 )
0395 {
0396 run(make_params_connect(&endpoint, params), err, diag);
0397 }
0398
0399 void connect_v2(const connect_params& params, error_code& err, diagnostics& diag)
0400 {
0401 run(make_params_connect_v2(params), err, diag);
0402 }
0403
0404 template <class EndpointType, class CompletionToken>
0405 auto async_connect(
0406 const EndpointType& endpoint,
0407 const handshake_params& params,
0408 diagnostics& diag,
0409 CompletionToken&& token
0410 )
0411 -> decltype(asio::async_initiate<CompletionToken, void(error_code)>(
0412 initiate_connect<EndpointType>(get_executor()),
0413 token,
0414 &diag,
0415 engine_.get(),
0416 st_.get(),
0417 endpoint,
0418 params
0419 ))
0420 {
0421 return asio::async_initiate<CompletionToken, void(error_code)>(
0422 initiate_connect<EndpointType>(get_executor()),
0423 token,
0424 &diag,
0425 engine_.get(),
0426 st_.get(),
0427 endpoint,
0428 params
0429 );
0430 }
0431
0432 template <class CompletionToken>
0433 auto async_connect_v2(const connect_params& params, diagnostics& diag, CompletionToken&& token)
0434 -> decltype(asio::async_initiate<CompletionToken, void(error_code)>(
0435 initiate_connect_v2(get_executor()),
0436 token,
0437 &diag,
0438 engine_.get(),
0439 st_.get(),
0440 ¶ms
0441 ))
0442 {
0443 return asio::async_initiate<CompletionToken, void(error_code)>(
0444 initiate_connect_v2(get_executor()),
0445 token,
0446 &diag,
0447 engine_.get(),
0448 st_.get(),
0449 ¶ms
0450 );
0451 }
0452
0453
0454 handshake_algo_params make_params_handshake(const handshake_params& params) const
0455 {
0456 return {params, false};
0457 }
0458
0459
0460 template <class ExecutionRequest, class ResultsType>
0461 void execute(ExecutionRequest&& req, ResultsType& result, error_code& err, diagnostics& diag)
0462 {
0463 run(
0464 execute_algo_params{
0465 make_request(std::forward<ExecutionRequest>(req), *st_),
0466 &access::get_impl(result).get_interface()
0467 },
0468 err,
0469 diag
0470 );
0471 }
0472
0473 template <class ExecutionRequest, class ResultsType, class CompletionToken>
0474 auto async_execute(
0475 ExecutionRequest&& req,
0476 ResultsType& result,
0477 diagnostics& diag,
0478 CompletionToken&& token
0479 )
0480 -> decltype(asio::async_initiate<CompletionToken, void(error_code)>(
0481 initiate_execute(get_executor()),
0482 token,
0483 &diag,
0484 engine_.get(),
0485 st_.get(),
0486 std::forward<ExecutionRequest>(req),
0487 &access::get_impl(result).get_interface()
0488 ))
0489 {
0490 return asio::async_initiate<CompletionToken, void(error_code)>(
0491 initiate_execute(get_executor()),
0492 token,
0493 &diag,
0494 engine_.get(),
0495 st_.get(),
0496 std::forward<ExecutionRequest>(req),
0497 &access::get_impl(result).get_interface()
0498 );
0499 }
0500
0501
0502 template <class ExecutionRequest, class ExecutionStateType>
0503 void start_execution(
0504 ExecutionRequest&& req,
0505 ExecutionStateType& exec_st,
0506 error_code& err,
0507 diagnostics& diag
0508 )
0509 {
0510 run(
0511 start_execution_algo_params{
0512 make_request(std::forward<ExecutionRequest>(req), *st_),
0513 &access::get_impl(exec_st).get_interface()
0514 },
0515 err,
0516 diag
0517 );
0518 }
0519
0520 template <class ExecutionRequest, class ExecutionStateType, class CompletionToken>
0521 auto async_start_execution(
0522 ExecutionRequest&& req,
0523 ExecutionStateType& exec_st,
0524 diagnostics& diag,
0525 CompletionToken&& token
0526 )
0527 -> decltype(asio::async_initiate<CompletionToken, void(error_code)>(
0528 initiate_start_execution(get_executor()),
0529 token,
0530 &diag,
0531 engine_.get(),
0532 st_.get(),
0533 std::forward<ExecutionRequest>(req),
0534 &access::get_impl(exec_st).get_interface()
0535 ))
0536 {
0537 return asio::async_initiate<CompletionToken, void(error_code)>(
0538 initiate_start_execution(get_executor()),
0539 token,
0540 &diag,
0541 engine_.get(),
0542 st_.get(),
0543 std::forward<ExecutionRequest>(req),
0544 &access::get_impl(exec_st).get_interface()
0545 );
0546 }
0547
0548
0549 read_some_rows_dynamic_algo_params make_params_read_some_rows(execution_state& st) const
0550 {
0551 return {&access::get_impl(st).get_interface()};
0552 }
0553
0554
0555 template <class SpanElementType, class ExecutionState>
0556 read_some_rows_algo_params make_params_read_some_rows_static(
0557 ExecutionState& exec_st,
0558 span<SpanElementType> output
0559 ) const
0560 {
0561 return {
0562 &access::get_impl(exec_st).get_interface(),
0563 access::get_impl(exec_st).make_output_ref(output)
0564 };
0565 }
0566
0567
0568 template <class ExecutionStateType>
0569 read_resultset_head_algo_params make_params_read_resultset_head(ExecutionStateType& st) const
0570 {
0571 return {&detail::access::get_impl(st).get_interface()};
0572 }
0573
0574
0575 close_statement_algo_params make_params_close_statement(statement stmt) const { return {stmt.id()}; }
0576
0577
0578 BOOST_MYSQL_DECL
0579 static run_pipeline_algo_params make_params_pipeline(
0580 const pipeline_request& req,
0581 std::vector<stage_response>& response
0582 );
0583
0584
0585 connection_state& get_state() { return *st_; }
0586 };
0587
0588
0589
0590
0591 template <class AlgoParams, class CompletionToken>
0592 using async_run_t = decltype(std::declval<connection_impl&>().async_run(
0593 std::declval<AlgoParams>(),
0594 std::declval<diagnostics&>(),
0595 std::declval<CompletionToken>()
0596 ));
0597
0598 template <class EndpointType, class CompletionToken>
0599 using async_connect_t = decltype(std::declval<connection_impl&>().async_connect(
0600 std::declval<const EndpointType&>(),
0601 std::declval<const handshake_params&>(),
0602 std::declval<diagnostics&>(),
0603 std::declval<CompletionToken>()
0604 ));
0605
0606 template <class CompletionToken>
0607 using async_connect_v2_t = decltype(std::declval<connection_impl&>().async_connect_v2(
0608 std::declval<const connect_params&>(),
0609 std::declval<diagnostics&>(),
0610 std::declval<CompletionToken>()
0611 ));
0612
0613 template <class ExecutionRequest, class ResultsType, class CompletionToken>
0614 using async_execute_t = decltype(std::declval<connection_impl&>().async_execute(
0615 std::declval<ExecutionRequest>(),
0616 std::declval<ResultsType&>(),
0617 std::declval<diagnostics&>(),
0618 std::declval<CompletionToken>()
0619 ));
0620
0621 template <class ExecutionRequest, class ExecutionStateType, class CompletionToken>
0622 using async_start_execution_t = decltype(std::declval<connection_impl&>().async_start_execution(
0623 std::declval<ExecutionRequest>(),
0624 std::declval<ExecutionStateType&>(),
0625 std::declval<diagnostics&>(),
0626 std::declval<CompletionToken>()
0627 ));
0628
0629 template <class CompletionToken>
0630 using async_handshake_t = async_run_t<handshake_algo_params, CompletionToken>;
0631
0632 template <class CompletionToken>
0633 using async_read_resultset_head_t = async_run_t<read_resultset_head_algo_params, CompletionToken>;
0634
0635 template <class CompletionToken>
0636 using async_read_some_rows_dynamic_t = async_run_t<read_some_rows_dynamic_algo_params, CompletionToken>;
0637
0638 template <class CompletionToken>
0639 using async_prepare_statement_t = async_run_t<prepare_statement_algo_params, CompletionToken>;
0640
0641 template <class CompletionToken>
0642 using async_close_statement_t = async_run_t<close_statement_algo_params, CompletionToken>;
0643
0644 template <class CompletionToken>
0645 using async_set_character_set_t = async_run_t<set_character_set_algo_params, CompletionToken>;
0646
0647 template <class CompletionToken>
0648 using async_ping_t = async_run_t<ping_algo_params, CompletionToken>;
0649
0650 template <class CompletionToken>
0651 using async_reset_connection_t = async_run_t<reset_connection_algo_params, CompletionToken>;
0652
0653 template <class CompletionToken>
0654 using async_quit_connection_t = async_run_t<quit_connection_algo_params, CompletionToken>;
0655
0656 template <class CompletionToken>
0657 using async_close_connection_t = async_run_t<close_connection_algo_params, CompletionToken>;
0658
0659 template <class CompletionToken>
0660 using async_run_pipeline_t = async_run_t<run_pipeline_algo_params, CompletionToken>;
0661
0662 }
0663 }
0664 }
0665
0666 #ifdef BOOST_MYSQL_HEADER_ONLY
0667 #include <boost/mysql/impl/connection_impl.ipp>
0668 #endif
0669
0670 #endif