// // Copyright (c) 2019-2024 Ruben Perez Hidalgo (rubenperez038 at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_MYSQL_IMPL_IS_FATAL_ERROR_IPP #define BOOST_MYSQL_IMPL_IS_FATAL_ERROR_IPP #pragma once #include #include #include #include bool boost::mysql::is_fatal_error(error_code ec) noexcept { // If there is no failure, it's not fatal if (!ec) return false; // Retrieve the error category const auto& cat = ec.category(); if (cat == get_common_server_category()) { // Server errors may or may not be fatal. MySQL defines a ton of different errors. // After some research, these are the ones I'd recommend to consider fatal auto code = static_cast(ec.value()); switch (code) { // Different flavors of communication errors. These usually indicate that the connection // has been left in an unspecified state, and the safest is to reconnect it. case common_server_errc::er_unknown_com_error: case common_server_errc::er_aborting_connection: case common_server_errc::er_net_packet_too_large: case common_server_errc::er_net_read_error_from_pipe: case common_server_errc::er_net_fcntl_error: case common_server_errc::er_net_packets_out_of_order: case common_server_errc::er_net_uncompress_error: case common_server_errc::er_net_read_error: case common_server_errc::er_net_read_interrupted: case common_server_errc::er_net_error_on_write: case common_server_errc::er_net_write_interrupted: case common_server_errc::er_malformed_packet: case common_server_errc::er_zlib_z_buf_error: case common_server_errc::er_zlib_z_data_error: case common_server_errc::er_zlib_z_mem_error: return true; default: return false; } } else if (cat == get_mysql_server_category() || cat == get_mariadb_server_category()) { // DB-specific codes are all non fatal return false; } else if (cat == get_client_category()) { auto code = static_cast(ec.value()); switch (code) { // These indicate malformed frames or packet mismatches case client_errc::incomplete_message: case client_errc::protocol_value_error: case client_errc::extra_bytes: case client_errc::sequence_number_mismatch: // Exceeding the max buffer size is not recoverable case client_errc::max_buffer_size_exceeded: // These are produced by the static interface, and currently cause parsing // to stop, leaving unread packets in the network buffer. // See https://github.com/boostorg/mysql/issues/212 case client_errc::metadata_check_failed: case client_errc::num_resultsets_mismatch: case client_errc::row_type_mismatch: case client_errc::static_row_parsing_error: // While these are currently produced only by the connection pool, // any timed out or cancelled operation would leave the connection in an undefined state case client_errc::timeout: case client_errc::cancelled: // These are only produced by handshake. We categorize them as fatal because they need reconnection, // although anything affecting handshake effectively does. case client_errc::server_doesnt_support_ssl: case client_errc::unknown_auth_plugin: case client_errc::server_unsupported: case client_errc::auth_plugin_requires_ssl: return true; default: return false; } } else { // Other categories are fatal - these include network and SSL errors return true; } } #endif