mirror of
https://github.com/boostorg/mysql.git
synced 2025-05-12 14:11:41 +00:00
parent
cbe9270253
commit
27e417dc2d
@ -8,122 +8,114 @@
|
||||
#ifndef BOOST_MYSQL_IMPL_INTERNAL_PROTOCOL_CAPABILITIES_HPP
|
||||
#define BOOST_MYSQL_IMPL_INTERNAL_PROTOCOL_CAPABILITIES_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace boost {
|
||||
namespace mysql {
|
||||
namespace detail {
|
||||
|
||||
// Server/client capabilities
|
||||
// clang-format off
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_LONG_PASSWORD = 1; // Use the improved version of Old Password Authentication
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_FOUND_ROWS = 2; // Send found rows instead of affected rows in EOF_Packet
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_LONG_FLAG = 4; // Get all column flags
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_CONNECT_WITH_DB = 8; // Database (schema) name can be specified on connect in Handshake Response Packet
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_NO_SCHEMA = 16; // Don't allow database.table.column
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_COMPRESS = 32; // Compression protocol supported
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_ODBC = 64; // Special handling of ODBC behavior
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_LOCAL_FILES = 128; // Can use LOAD DATA LOCAL
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_IGNORE_SPACE = 256; // Ignore spaces before '('
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_PROTOCOL_41 = 512; // New 4.1 protocol
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_INTERACTIVE = 1024; // This is an interactive client
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_SSL = 2048; // Use SSL encryption for the session
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_IGNORE_SIGPIPE = 4096; // Client only flag
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_TRANSACTIONS = 8192; // Client knows about transactions
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_RESERVED = 16384; // DEPRECATED: Old flag for 4.1 protocol
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_SECURE_CONNECTION = 32768; // DEPRECATED: Old flag for 4.1 authentication, required by MariaDB
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_MULTI_STATEMENTS = (1UL << 16); // Enable/disable multi-stmt support
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_MULTI_RESULTS = (1UL << 17); // Enable/disable multi-results
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_PS_MULTI_RESULTS = (1UL << 18); // Multi-results and OUT parameters in PS-protocol
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_PLUGIN_AUTH = (1UL << 19); // Client supports plugin authentication
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_CONNECT_ATTRS = (1UL << 20); // Client supports connection attributes
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA = (1UL << 21); // Enable authentication response packet to be larger than 255 bytes
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS = (1UL << 22); // Don't close the connection for a user account with expired password
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_SESSION_TRACK = (1UL << 23); // Capable of handling server state change information
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_DEPRECATE_EOF = (1UL << 24); // Client no longer needs EOF_Packet and will use OK_Packet instead
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_SSL_VERIFY_SERVER_CERT = (1UL << 30); // Verify server certificate
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_OPTIONAL_RESULTSET_METADATA = (1UL << 25); // The client can handle optional metadata information in the resultset
|
||||
BOOST_INLINE_CONSTEXPR std::uint32_t CLIENT_REMEMBER_OPTIONS = (1UL << 31); // Don't reset the options after an unsuccessful connect
|
||||
// clang-format on
|
||||
|
||||
class capabilities
|
||||
enum class capabilities : std::uint32_t
|
||||
{
|
||||
std::uint32_t value_;
|
||||
// CLIENT_LONG_PASSWORD: Use the improved version of Old Password Authentication
|
||||
long_password = 1,
|
||||
|
||||
public:
|
||||
constexpr explicit capabilities(std::uint32_t value = 0) noexcept : value_(value){};
|
||||
constexpr std::uint32_t get() const noexcept { return value_; }
|
||||
void set(std::uint32_t value) noexcept { value_ = value; }
|
||||
constexpr bool has(std::uint32_t cap) const noexcept { return value_ & cap; }
|
||||
constexpr bool has_all(capabilities other) const noexcept
|
||||
{
|
||||
return (value_ & other.get()) == other.get();
|
||||
}
|
||||
constexpr capabilities operator|(capabilities rhs) const noexcept
|
||||
{
|
||||
return capabilities(value_ | rhs.value_);
|
||||
}
|
||||
constexpr capabilities operator&(capabilities rhs) const noexcept
|
||||
{
|
||||
return capabilities(value_ & rhs.value_);
|
||||
}
|
||||
constexpr bool operator==(const capabilities& rhs) const noexcept { return value_ == rhs.value_; }
|
||||
constexpr bool operator!=(const capabilities& rhs) const noexcept { return value_ != rhs.value_; }
|
||||
// CLIENT_FOUND_ROWS: Send found rows instead of affected rows in EOF_Packet
|
||||
found_rows = 2,
|
||||
|
||||
// CLIENT_LONG_FLAG: Get all column flags
|
||||
long_flag = 4,
|
||||
|
||||
// CLIENT_CONNECT_WITH_DB: Database (schema) name can be specified on connect in Handshake Response Packet
|
||||
connect_with_db = 8,
|
||||
|
||||
// CLIENT_NO_SCHEMA: Don't allow database.table.column
|
||||
no_schema = 16,
|
||||
|
||||
// CLIENT_COMPRESS: Compression protocol supported
|
||||
compress = 32,
|
||||
|
||||
// CLIENT_ODBC: Special handling of ODBC behavior
|
||||
odbc = 64,
|
||||
|
||||
// CLIENT_LOCAL_FILES: Can use LOAD DATA LOCAL
|
||||
local_files = 128,
|
||||
|
||||
// CLIENT_IGNORE_SPACE: Ignore spaces before '('
|
||||
ignore_space = 256,
|
||||
|
||||
// CLIENT_PROTOCOL_41: New 4.1 protocol
|
||||
protocol_41 = 512,
|
||||
|
||||
// CLIENT_INTERACTIVE: This is an interactive client
|
||||
interactive = 1024,
|
||||
|
||||
// CLIENT_SSL: Use SSL encryption for the session
|
||||
ssl = 2048,
|
||||
|
||||
// CLIENT_IGNORE_SIGPIPE: Client only flag
|
||||
ignore_sigpipe = 4096,
|
||||
|
||||
// CLIENT_TRANSACTIONS: Client knows about transactions
|
||||
transactions = 8192,
|
||||
|
||||
// CLIENT_RESERVED: DEPRECATED: Old flag for 4.1 protocol
|
||||
reserved = 16384,
|
||||
|
||||
// CLIENT_SECURE_CONNECTION: DEPRECATED: Old flag for 4.1 authentication, required by MariaDB
|
||||
secure_connection = 32768,
|
||||
|
||||
// CLIENT_MULTI_STATEMENTS: Enable/disable multi-stmt support
|
||||
multi_statements = (1UL << 16),
|
||||
|
||||
// CLIENT_MULTI_RESULTS: Enable/disable multi-results
|
||||
multi_results = (1UL << 17),
|
||||
|
||||
// CLIENT_PS_MULTI_RESULTS: Multi-results and OUT parameters in PS-protocol
|
||||
ps_multi_results = (1UL << 18),
|
||||
|
||||
// CLIENT_PLUGIN_AUTH: Client supports plugin authentication
|
||||
plugin_auth = (1UL << 19),
|
||||
|
||||
// CLIENT_CONNECT_ATTRS: Client supports connection attributes
|
||||
connect_attrs = (1UL << 20),
|
||||
|
||||
// CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA: Enable authentication response packet to be larger than 255
|
||||
// bytes
|
||||
plugin_auth_lenenc_data = (1UL << 21),
|
||||
|
||||
// CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS: Don't close the connection for a user account with expired
|
||||
// password
|
||||
can_handle_expired_passwords = (1UL << 22),
|
||||
|
||||
// CLIENT_SESSION_TRACK: Capable of handling server state change information
|
||||
session_track = (1UL << 23),
|
||||
|
||||
// CLIENT_DEPRECATE_EOF: Client no longer needs EOF_Packet and will use OK_Packet instead
|
||||
deprecate_eof = (1UL << 24),
|
||||
|
||||
// CLIENT_SSL_VERIFY_SERVER_CERT: Verify server certificate
|
||||
ssl_verify_server_cert = (1UL << 30),
|
||||
|
||||
// CLIENT_OPTIONAL_RESULTSET_METADATA: The client can handle optional metadata information in the
|
||||
// resultset
|
||||
optional_resultset_metadata = (1UL << 25),
|
||||
|
||||
// CLIENT_REMEMBER_OPTIONS: Don't reset the options after an unsuccessful connect
|
||||
remember_options = (1UL << 31),
|
||||
};
|
||||
|
||||
/*
|
||||
* CLIENT_LONG_PASSWORD: unset // Use the improved version of Old Password Authentication
|
||||
* CLIENT_FOUND_ROWS: unset // Send found rows instead of affected rows in EOF_Packet
|
||||
* CLIENT_LONG_FLAG: unset // Get all column flags
|
||||
* CLIENT_CONNECT_WITH_DB: optional // Database (schema) name can be specified on connect in
|
||||
* Handshake Response Packet CLIENT_NO_SCHEMA: unset // Don't allow database.table.column
|
||||
* CLIENT_COMPRESS: unset // Compression protocol supported
|
||||
* CLIENT_ODBC: unset // Special handling of ODBC behavior
|
||||
* CLIENT_LOCAL_FILES: unset // Can use LOAD DATA LOCAL
|
||||
* CLIENT_IGNORE_SPACE: unset // Ignore spaces before '('
|
||||
* CLIENT_PROTOCOL_41: mandatory // New 4.1 protocol
|
||||
* CLIENT_INTERACTIVE: unset // This is an interactive client
|
||||
* CLIENT_SSL: unset // Use SSL encryption for the session
|
||||
* CLIENT_IGNORE_SIGPIPE: unset // Client only flag
|
||||
* CLIENT_TRANSACTIONS: unset // Client knows about transactions
|
||||
* CLIENT_RESERVED: unset // DEPRECATED: Old flag for 4.1 protocol
|
||||
* CLIENT_RESERVED2: unset // DEPRECATED: Old flag for 4.1 authentication
|
||||
* \ CLIENT_SECURE_CONNECTION CLIENT_MULTI_STATEMENTS: unset // Enable/disable multi-stmt support
|
||||
* CLIENT_MULTI_RESULTS: unset // Enable/disable multi-results
|
||||
* CLIENT_PS_MULTI_RESULTS: unset // Multi-results and OUT parameters in PS-protocol
|
||||
* CLIENT_PLUGIN_AUTH: mandatory // Client supports plugin authentication
|
||||
* CLIENT_CONNECT_ATTRS: unset // Client supports connection attributes
|
||||
* CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA: mandatory // Enable authentication response packet to be
|
||||
* larger than 255 bytes CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS: unset // Don't close the connection
|
||||
* for a user account with expired password CLIENT_SESSION_TRACK: unset // Capable of handling
|
||||
* server state change information CLIENT_DEPRECATE_EOF: mandatory // Client no longer needs
|
||||
* EOF_Packet and will use OK_Packet instead CLIENT_SSL_VERIFY_SERVER_CERT: unset // Verify server
|
||||
* certificate CLIENT_OPTIONAL_RESULTSET_METADATA: unset // The client can handle optional metadata
|
||||
* information in the resultset CLIENT_REMEMBER_OPTIONS: unset // Don't reset the options after an
|
||||
* unsuccessful connect
|
||||
*
|
||||
* We pay attention to:
|
||||
* CLIENT_CONNECT_WITH_DB: optional // Database (schema) name can be specified on connect in
|
||||
* Handshake Response Packet CLIENT_PROTOCOL_41: mandatory // New 4.1 protocol CLIENT_PLUGIN_AUTH:
|
||||
* mandatory // Client supports plugin authentication CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA:
|
||||
* mandatory // Enable authentication response packet to be larger than 255 bytes
|
||||
* CLIENT_DEPRECATE_EOF: mandatory // Client no longer needs EOF_Packet and will use OK_Packet
|
||||
* instead
|
||||
*/
|
||||
constexpr capabilities operator&(capabilities lhs, capabilities rhs)
|
||||
{
|
||||
return static_cast<capabilities>(static_cast<std::uint32_t>(lhs) & static_cast<std::uint32_t>(rhs));
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
BOOST_INLINE_CONSTEXPR capabilities mandatory_capabilities{
|
||||
CLIENT_PROTOCOL_41 |
|
||||
CLIENT_PLUGIN_AUTH |
|
||||
CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA |
|
||||
CLIENT_DEPRECATE_EOF |
|
||||
CLIENT_SECURE_CONNECTION
|
||||
};
|
||||
// clang-format on
|
||||
constexpr capabilities operator|(capabilities lhs, capabilities rhs)
|
||||
{
|
||||
return static_cast<capabilities>(static_cast<std::uint32_t>(lhs) | static_cast<std::uint32_t>(rhs));
|
||||
}
|
||||
|
||||
BOOST_INLINE_CONSTEXPR capabilities optional_capabilities{CLIENT_MULTI_RESULTS | CLIENT_PS_MULTI_RESULTS};
|
||||
// Are all capabilities in subset in caps?
|
||||
constexpr bool has_capabilities(capabilities caps, capabilities subset) { return (caps & subset) == subset; }
|
||||
|
||||
} // namespace detail
|
||||
} // namespace mysql
|
||||
|
@ -758,7 +758,7 @@ inline capabilities compose_capabilities(string_fixed<2> low, string_fixed<2> hi
|
||||
auto capabilities_begin = reinterpret_cast<std::uint8_t*>(&res);
|
||||
memcpy(capabilities_begin, low.value.data(), 2);
|
||||
memcpy(capabilities_begin + 2, high.value.data(), 2);
|
||||
return capabilities(boost::endian::little_to_native(res));
|
||||
return static_cast<capabilities>(boost::endian::little_to_native(res));
|
||||
}
|
||||
|
||||
inline db_flavor parse_db_version(string_view version_string)
|
||||
@ -811,7 +811,7 @@ boost::mysql::error_code boost::mysql::detail::deserialize_server_hello_impl(
|
||||
auto cap = compose_capabilities(pack.capability_flags_low, pack.capability_flags_high);
|
||||
|
||||
// Check minimum server capabilities to deserialize this frame
|
||||
if (!cap.has(CLIENT_PLUGIN_AUTH))
|
||||
if (!has_capabilities(cap, capabilities::plugin_auth))
|
||||
return client_errc::server_unsupported;
|
||||
|
||||
// Deserialize next fields
|
||||
|
@ -260,7 +260,7 @@ void boost::mysql::detail::execute_stmt_command::serialize(serialization_context
|
||||
void boost::mysql::detail::login_request::serialize(serialization_context& ctx) const
|
||||
{
|
||||
ctx.serialize_fixed(
|
||||
int4{negotiated_capabilities.get()}, // client_flag
|
||||
int4{static_cast<std::uint32_t>(negotiated_capabilities)}, // client_flag
|
||||
int4{max_packet_size}, // max_packet_size
|
||||
int1{get_collation_first_byte(collation_id)}, // character_set
|
||||
string_fixed<23>{} // filler (all zeros)
|
||||
@ -269,7 +269,7 @@ void boost::mysql::detail::login_request::serialize(serialization_context& ctx)
|
||||
string_null{username},
|
||||
string_lenenc{to_string(auth_response)} // we require CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA
|
||||
);
|
||||
if (negotiated_capabilities.has(CLIENT_CONNECT_WITH_DB))
|
||||
if (has_capabilities(negotiated_capabilities, capabilities::connect_with_db))
|
||||
{
|
||||
string_null{database}.serialize(ctx); // database
|
||||
}
|
||||
@ -279,7 +279,7 @@ void boost::mysql::detail::login_request::serialize(serialization_context& ctx)
|
||||
void boost::mysql::detail::ssl_request::serialize(serialization_context& ctx) const
|
||||
{
|
||||
ctx.serialize_fixed(
|
||||
int4{negotiated_capabilities.get()}, // client_flag
|
||||
int4{static_cast<std::uint32_t>(negotiated_capabilities)}, // client_flag
|
||||
int4{max_packet_size}, // max_packet_size
|
||||
int1{get_collation_first_byte(collation_id)}, // character_set,
|
||||
string_fixed<23>{} // filler, all zeros
|
||||
|
@ -59,7 +59,7 @@ struct connection_state_data
|
||||
db_flavor flavor{db_flavor::mysql};
|
||||
|
||||
// What are the connection's capabilities?
|
||||
capabilities current_capabilities;
|
||||
capabilities current_capabilities{};
|
||||
|
||||
// The current connection ID. Supplied by handshake, can be used in KILL statements
|
||||
std::uint32_t connection_id{};
|
||||
@ -110,7 +110,7 @@ struct connection_state_data
|
||||
{
|
||||
status = connection_status::not_connected;
|
||||
flavor = db_flavor::mysql;
|
||||
current_capabilities = capabilities();
|
||||
current_capabilities = capabilities{};
|
||||
// Metadata mode does not get reset on handshake
|
||||
reader.reset();
|
||||
// Writer does not need reset, since every write clears previous state
|
||||
|
@ -32,9 +32,9 @@ namespace boost {
|
||||
namespace mysql {
|
||||
namespace detail {
|
||||
|
||||
inline capabilities conditional_capability(bool condition, std::uint32_t cap)
|
||||
inline capabilities conditional_capability(bool condition, capabilities cap)
|
||||
{
|
||||
return capabilities(condition ? cap : 0);
|
||||
return condition ? cap : capabilities{};
|
||||
}
|
||||
|
||||
inline error_code process_capabilities(
|
||||
@ -44,24 +44,47 @@ inline error_code process_capabilities(
|
||||
bool transport_supports_ssl
|
||||
)
|
||||
{
|
||||
// The capabilities that we absolutely require. These are always set except in extremely old servers
|
||||
constexpr capabilities mandatory_capabilities =
|
||||
// We don't speak the older protocol
|
||||
capabilities::protocol_41 |
|
||||
|
||||
// We only know how to deserialize the hello frame if this is set
|
||||
capabilities::plugin_auth |
|
||||
|
||||
// Same as above
|
||||
capabilities::plugin_auth_lenenc_data |
|
||||
|
||||
// This makes processing execute responses easier
|
||||
capabilities::deprecate_eof |
|
||||
|
||||
// Used in MariaDB to signal 4.1 protocol. Always set in MySQL, too
|
||||
capabilities::secure_connection;
|
||||
|
||||
// The capabilities that we support but don't require
|
||||
constexpr capabilities optional_capabilities = capabilities::multi_results |
|
||||
capabilities::ps_multi_results;
|
||||
|
||||
auto ssl = transport_supports_ssl ? params.ssl() : ssl_mode::disable;
|
||||
capabilities server_caps = hello.server_capabilities;
|
||||
capabilities required_caps = mandatory_capabilities |
|
||||
conditional_capability(!params.database().empty(), CLIENT_CONNECT_WITH_DB) |
|
||||
conditional_capability(params.multi_queries(), CLIENT_MULTI_STATEMENTS) |
|
||||
conditional_capability(ssl == ssl_mode::require, CLIENT_SSL);
|
||||
if (required_caps.has(CLIENT_SSL) && !server_caps.has(CLIENT_SSL))
|
||||
capabilities
|
||||
required_caps = mandatory_capabilities |
|
||||
conditional_capability(!params.database().empty(), capabilities::connect_with_db) |
|
||||
conditional_capability(params.multi_queries(), capabilities::multi_statements) |
|
||||
conditional_capability(ssl == ssl_mode::require, capabilities::ssl);
|
||||
if (has_capabilities(required_caps, capabilities::ssl) &&
|
||||
!has_capabilities(server_caps, capabilities::ssl))
|
||||
{
|
||||
// This happens if the server doesn't have SSL configured. This special
|
||||
// error code helps users diagnosing their problem a lot (server_unsupported doesn't).
|
||||
return make_error_code(client_errc::server_doesnt_support_ssl);
|
||||
}
|
||||
else if (!server_caps.has_all(required_caps))
|
||||
else if (!has_capabilities(server_caps, required_caps))
|
||||
{
|
||||
return make_error_code(client_errc::server_unsupported);
|
||||
}
|
||||
negotiated_caps = server_caps & (required_caps | optional_capabilities |
|
||||
conditional_capability(ssl == ssl_mode::enable, CLIENT_SSL));
|
||||
conditional_capability(ssl == ssl_mode::enable, capabilities::ssl));
|
||||
return error_code();
|
||||
}
|
||||
|
||||
@ -89,7 +112,10 @@ class handshake_algo
|
||||
}
|
||||
|
||||
// Once the handshake is processed, the capabilities are stored in the connection state
|
||||
bool use_ssl(const connection_state_data& st) const { return st.current_capabilities.has(CLIENT_SSL); }
|
||||
bool use_ssl(const connection_state_data& st) const
|
||||
{
|
||||
return has_capabilities(st.current_capabilities, capabilities::ssl);
|
||||
}
|
||||
|
||||
error_code process_handshake(
|
||||
connection_state_data& st,
|
||||
@ -104,7 +130,7 @@ class handshake_algo
|
||||
return err;
|
||||
|
||||
// Check capabilities
|
||||
capabilities negotiated_caps;
|
||||
capabilities negotiated_caps{};
|
||||
err = process_capabilities(hparams_, hello, negotiated_caps, st.tls_supported);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -8,6 +8,7 @@
|
||||
#ifndef BOOST_MYSQL_TEST_UNIT_INCLUDE_TEST_UNIT_PRINTING_HPP
|
||||
#define BOOST_MYSQL_TEST_UNIT_INCLUDE_TEST_UNIT_PRINTING_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include <iosfwd>
|
||||
|
||||
namespace boost {
|
||||
@ -20,8 +21,8 @@ std::ostream& operator<<(std::ostream& os, address_type value);
|
||||
namespace detail {
|
||||
|
||||
// capabilities
|
||||
class capabilities;
|
||||
std::ostream& operator<<(std::ostream& os, const capabilities& caps);
|
||||
enum class capabilities : std::uint32_t;
|
||||
std::ostream& operator<<(std::ostream& os, capabilities caps);
|
||||
|
||||
// db_flavor
|
||||
enum class db_flavor;
|
||||
|
@ -611,9 +611,9 @@ static const char* to_string(address_type v)
|
||||
std::ostream& boost::mysql::operator<<(std::ostream& os, address_type v) { return os << ::to_string(v); }
|
||||
|
||||
// capabilities
|
||||
std::ostream& boost::mysql::detail::operator<<(std::ostream& os, const capabilities& v)
|
||||
std::ostream& boost::mysql::detail::operator<<(std::ostream& os, capabilities v)
|
||||
{
|
||||
return os << "capabilities{" << v.get() << "}";
|
||||
return os << "capabilities{" << static_cast<std::uint32_t>(v) << "}";
|
||||
}
|
||||
|
||||
// db_flavor
|
||||
|
@ -9,64 +9,86 @@
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
using namespace boost::mysql::detail;
|
||||
#include "test_unit/printing.hpp"
|
||||
|
||||
using namespace boost::mysql;
|
||||
using detail::capabilities;
|
||||
using detail::has_capabilities;
|
||||
|
||||
namespace {
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(test_capabilities)
|
||||
|
||||
constexpr capabilities rhs{CLIENT_CONNECT_WITH_DB | CLIENT_SSL | CLIENT_COMPRESS};
|
||||
|
||||
BOOST_AUTO_TEST_CASE(has_bit_set)
|
||||
BOOST_AUTO_TEST_CASE(operator_or)
|
||||
{
|
||||
capabilities caps(CLIENT_COMPRESS);
|
||||
BOOST_TEST(caps.has(CLIENT_COMPRESS));
|
||||
// Two != flags
|
||||
BOOST_TEST((capabilities::long_password | capabilities::long_flag) == static_cast<capabilities>(5));
|
||||
|
||||
// Same flag
|
||||
BOOST_TEST((capabilities::long_flag | capabilities::long_flag) == capabilities::long_flag);
|
||||
|
||||
// Big values
|
||||
BOOST_TEST(
|
||||
(capabilities::long_password | capabilities::remember_options) ==
|
||||
static_cast<capabilities>(1 | (1 << 31))
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(has_bit_not_set)
|
||||
BOOST_AUTO_TEST_CASE(operator_and)
|
||||
{
|
||||
capabilities caps(CLIENT_COMPRESS);
|
||||
BOOST_TEST(!caps.has(CLIENT_SSL));
|
||||
// Single flag present
|
||||
BOOST_TEST((static_cast<capabilities>(5) & capabilities::long_password) == capabilities::long_password);
|
||||
|
||||
// Single flag absent
|
||||
BOOST_TEST((static_cast<capabilities>(5) & capabilities::odbc) == capabilities{});
|
||||
|
||||
// Multiple flags
|
||||
BOOST_TEST(
|
||||
(static_cast<capabilities>(11) & static_cast<capabilities>(67)) == static_cast<capabilities>(3)
|
||||
);
|
||||
|
||||
// Big values
|
||||
BOOST_TEST(
|
||||
(static_cast<capabilities>(0xffffffff) & capabilities::remember_options) ==
|
||||
capabilities::remember_options
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(has_multiple_bits_set)
|
||||
BOOST_AUTO_TEST_CASE(has_capabilities_)
|
||||
{
|
||||
capabilities caps(CLIENT_CONNECT_WITH_DB | CLIENT_SSL | CLIENT_COMPRESS);
|
||||
for (int i = 0; i < 32; ++i)
|
||||
{
|
||||
std::uint32_t cap_bit = 1 << i;
|
||||
bool is_set = cap_bit == CLIENT_CONNECT_WITH_DB || cap_bit == CLIENT_SSL ||
|
||||
cap_bit == CLIENT_COMPRESS;
|
||||
BOOST_TEST(caps.has(cap_bit) == is_set);
|
||||
}
|
||||
}
|
||||
constexpr auto search = capabilities::connect_with_db | capabilities::ssl | capabilities::compress;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(has_all_has_none)
|
||||
{
|
||||
capabilities lhs(0);
|
||||
BOOST_TEST(!lhs.has_all(rhs));
|
||||
}
|
||||
// No capabilities present
|
||||
BOOST_TEST(!has_capabilities(capabilities{}, search));
|
||||
|
||||
BOOST_AUTO_TEST_CASE(has_all_has_some_but_not_all)
|
||||
{
|
||||
capabilities lhs(CLIENT_CONNECT_WITH_DB | CLIENT_COMPRESS);
|
||||
BOOST_TEST(!lhs.has_all(rhs));
|
||||
}
|
||||
// Some present, but not all
|
||||
BOOST_TEST(!has_capabilities(capabilities::connect_with_db | capabilities::compress, search));
|
||||
|
||||
BOOST_AUTO_TEST_CASE(has_all_has_some_but_not_all_plus_unrelated)
|
||||
{
|
||||
capabilities lhs(CLIENT_CONNECT_WITH_DB | CLIENT_COMPRESS | CLIENT_TRANSACTIONS);
|
||||
BOOST_TEST(!lhs.has_all(rhs));
|
||||
}
|
||||
// Some present, but not all. Some unrelated are present
|
||||
BOOST_TEST(!has_capabilities(
|
||||
capabilities::connect_with_db | capabilities::compress | capabilities::long_flag,
|
||||
search
|
||||
));
|
||||
|
||||
BOOST_AUTO_TEST_CASE(has_all_has_only_the_requested_ones)
|
||||
{
|
||||
capabilities lhs(rhs);
|
||||
BOOST_TEST(lhs.has_all(rhs));
|
||||
}
|
||||
// Only the requested ones are present
|
||||
BOOST_TEST(has_capabilities(search, search));
|
||||
|
||||
BOOST_AUTO_TEST_CASE(has_all_has_the_requested_ones_and_others)
|
||||
{
|
||||
capabilities lhs = rhs | capabilities(CLIENT_TRANSACTIONS);
|
||||
BOOST_TEST(lhs.has_all(rhs));
|
||||
// Has the requested ones, plus extra ones
|
||||
BOOST_TEST(has_capabilities(static_cast<capabilities>(0xffffffff), search));
|
||||
|
||||
// Searching for only one capability works
|
||||
BOOST_TEST(
|
||||
has_capabilities(capabilities::connect_with_db | capabilities::compress, capabilities::compress)
|
||||
);
|
||||
BOOST_TEST(
|
||||
!has_capabilities(capabilities::connect_with_db | capabilities::compress, capabilities::long_flag)
|
||||
);
|
||||
|
||||
// Searching for the empty set always returns true
|
||||
BOOST_TEST(has_capabilities(capabilities::connect_with_db | capabilities::compress, capabilities{}));
|
||||
BOOST_TEST(has_capabilities(static_cast<capabilities>(0xffffffff), capabilities{}));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END() // test_capabilities
|
||||
|
||||
} // namespace
|
@ -1245,17 +1245,18 @@ BOOST_AUTO_TEST_CASE(deserialize_server_hello_impl_success)
|
||||
constexpr std::uint8_t auth_plugin_data[] = {0x52, 0x1a, 0x50, 0x3a, 0x4b, 0x12, 0x70, 0x2f, 0x03, 0x5a,
|
||||
0x74, 0x05, 0x28, 0x2b, 0x7f, 0x21, 0x43, 0x4a, 0x21, 0x62};
|
||||
|
||||
constexpr std::uint32_t caps = CLIENT_LONG_PASSWORD | CLIENT_FOUND_ROWS | CLIENT_LONG_FLAG |
|
||||
CLIENT_CONNECT_WITH_DB | CLIENT_NO_SCHEMA | CLIENT_COMPRESS | CLIENT_ODBC |
|
||||
CLIENT_LOCAL_FILES | CLIENT_IGNORE_SPACE | CLIENT_PROTOCOL_41 |
|
||||
CLIENT_INTERACTIVE | CLIENT_IGNORE_SIGPIPE | CLIENT_TRANSACTIONS |
|
||||
CLIENT_RESERVED | // old flag, but set in this frame
|
||||
CLIENT_SECURE_CONNECTION | // old flag, but set in this frame
|
||||
CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS | CLIENT_PS_MULTI_RESULTS |
|
||||
CLIENT_PLUGIN_AUTH | CLIENT_CONNECT_ATTRS |
|
||||
CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA |
|
||||
CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS | CLIENT_SESSION_TRACK |
|
||||
CLIENT_DEPRECATE_EOF | CLIENT_REMEMBER_OPTIONS;
|
||||
constexpr auto caps = capabilities::long_password | capabilities::found_rows | capabilities::long_flag |
|
||||
capabilities::connect_with_db | capabilities::no_schema | capabilities::compress |
|
||||
capabilities::odbc | capabilities::local_files | capabilities::ignore_space |
|
||||
capabilities::protocol_41 | capabilities::interactive |
|
||||
capabilities::ignore_sigpipe | capabilities::transactions |
|
||||
capabilities::reserved | // old flag, but set in this frame
|
||||
capabilities::secure_connection | // old flag, but set in this frame
|
||||
capabilities::multi_statements | capabilities::multi_results |
|
||||
capabilities::ps_multi_results | capabilities::plugin_auth |
|
||||
capabilities::connect_attrs | capabilities::plugin_auth_lenenc_data |
|
||||
capabilities::can_handle_expired_passwords | capabilities::session_track |
|
||||
capabilities::deprecate_eof | capabilities::remember_options;
|
||||
|
||||
deserialization_buffer serialized{0x35, 0x2e, 0x37, 0x2e, 0x32, 0x37, 0x2d, 0x30, 0x75, 0x62, 0x75, 0x6e,
|
||||
0x74, 0x75, 0x30, 0x2e, 0x31, 0x39, 0x2e, 0x30, 0x34, 0x2e, 0x31, 0x00,
|
||||
@ -1276,7 +1277,7 @@ BOOST_AUTO_TEST_CASE(deserialize_server_hello_impl_success)
|
||||
// Actual value
|
||||
BOOST_TEST(actual.server == db_flavor::mysql);
|
||||
BOOST_MYSQL_ASSERT_BUFFER_EQUALS(actual.auth_plugin_data.to_span(), auth_plugin_data);
|
||||
BOOST_TEST(actual.server_capabilities == capabilities(caps));
|
||||
BOOST_TEST(actual.server_capabilities == caps);
|
||||
BOOST_TEST(actual.connection_id == 2u);
|
||||
BOOST_TEST(actual.auth_plugin_name == "mysql_native_password");
|
||||
|
||||
@ -1457,17 +1458,18 @@ BOOST_AUTO_TEST_CASE(deserialize_server_hello_success)
|
||||
constexpr std::uint8_t auth_plugin_data[] = {0x52, 0x1a, 0x50, 0x3a, 0x4b, 0x12, 0x70, 0x2f, 0x03, 0x5a,
|
||||
0x74, 0x05, 0x28, 0x2b, 0x7f, 0x21, 0x43, 0x4a, 0x21, 0x62};
|
||||
|
||||
constexpr std::uint32_t caps = CLIENT_LONG_PASSWORD | CLIENT_FOUND_ROWS | CLIENT_LONG_FLAG |
|
||||
CLIENT_CONNECT_WITH_DB | CLIENT_NO_SCHEMA | CLIENT_COMPRESS | CLIENT_ODBC |
|
||||
CLIENT_LOCAL_FILES | CLIENT_IGNORE_SPACE | CLIENT_PROTOCOL_41 |
|
||||
CLIENT_INTERACTIVE | CLIENT_IGNORE_SIGPIPE | CLIENT_TRANSACTIONS |
|
||||
CLIENT_RESERVED | // old flag, but set in this frame
|
||||
CLIENT_SECURE_CONNECTION | // old flag, but set in this frame
|
||||
CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS | CLIENT_PS_MULTI_RESULTS |
|
||||
CLIENT_PLUGIN_AUTH | CLIENT_CONNECT_ATTRS |
|
||||
CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA |
|
||||
CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS | CLIENT_SESSION_TRACK |
|
||||
CLIENT_DEPRECATE_EOF | CLIENT_REMEMBER_OPTIONS;
|
||||
constexpr auto caps = capabilities::long_password | capabilities::found_rows | capabilities::long_flag |
|
||||
capabilities::connect_with_db | capabilities::no_schema | capabilities::compress |
|
||||
capabilities::odbc | capabilities::local_files | capabilities::ignore_space |
|
||||
capabilities::protocol_41 | capabilities::interactive |
|
||||
capabilities::ignore_sigpipe | capabilities::transactions |
|
||||
capabilities::reserved | // old flag, but set in this frame
|
||||
capabilities::secure_connection | // old flag, but set in this frame
|
||||
capabilities::multi_statements | capabilities::multi_results |
|
||||
capabilities::ps_multi_results | capabilities::plugin_auth |
|
||||
capabilities::connect_attrs | capabilities::plugin_auth_lenenc_data |
|
||||
capabilities::can_handle_expired_passwords | capabilities::session_track |
|
||||
capabilities::deprecate_eof | capabilities::remember_options;
|
||||
|
||||
deserialization_buffer serialized{0x0a, 0x35, 0x2e, 0x37, 0x2e, 0x32, 0x37, 0x2d, 0x30, 0x75, 0x62, 0x75,
|
||||
0x6e, 0x74, 0x75, 0x30, 0x2e, 0x31, 0x39, 0x2e, 0x30, 0x34, 0x2e, 0x31,
|
||||
@ -1490,7 +1492,7 @@ BOOST_AUTO_TEST_CASE(deserialize_server_hello_success)
|
||||
// Actual value
|
||||
BOOST_TEST(actual.server == db_flavor::mysql);
|
||||
BOOST_MYSQL_ASSERT_BUFFER_EQUALS(actual.auth_plugin_data.to_span(), auth_plugin_data);
|
||||
BOOST_TEST(actual.server_capabilities == capabilities(caps));
|
||||
BOOST_TEST(actual.server_capabilities == caps);
|
||||
BOOST_TEST(actual.connection_id == 2u);
|
||||
BOOST_TEST(actual.auth_plugin_name == "mysql_native_password");
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <boost/mysql/mysql_collations.hpp>
|
||||
#include <boost/mysql/string_view.hpp>
|
||||
|
||||
#include <boost/mysql/impl/internal/protocol/capabilities.hpp>
|
||||
#include <boost/mysql/impl/internal/protocol/serialization.hpp>
|
||||
|
||||
#include <boost/core/span.hpp>
|
||||
@ -246,13 +247,13 @@ BOOST_AUTO_TEST_CASE(login_request_)
|
||||
0x35, 0xa5, 0xff, 0xdb, 0x3f, 0x48, 0xe6, 0xfc, 0x34, 0xc9}
|
||||
};
|
||||
|
||||
constexpr std::uint32_t caps = CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_LOCAL_FILES |
|
||||
CLIENT_PROTOCOL_41 | CLIENT_INTERACTIVE | CLIENT_TRANSACTIONS |
|
||||
CLIENT_SECURE_CONNECTION | CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS |
|
||||
CLIENT_PS_MULTI_RESULTS | CLIENT_PLUGIN_AUTH | CLIENT_CONNECT_ATTRS |
|
||||
CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA |
|
||||
CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS | CLIENT_SESSION_TRACK |
|
||||
CLIENT_DEPRECATE_EOF;
|
||||
constexpr auto caps = capabilities::long_password | capabilities::long_flag | capabilities::local_files |
|
||||
capabilities::protocol_41 | capabilities::interactive | capabilities::transactions |
|
||||
capabilities::secure_connection | capabilities::multi_statements |
|
||||
capabilities::multi_results | capabilities::ps_multi_results |
|
||||
capabilities::plugin_auth | capabilities::connect_attrs |
|
||||
capabilities::plugin_auth_lenenc_data | capabilities::can_handle_expired_passwords |
|
||||
capabilities::session_track | capabilities::deprecate_eof;
|
||||
|
||||
struct
|
||||
{
|
||||
@ -262,7 +263,7 @@ BOOST_AUTO_TEST_CASE(login_request_)
|
||||
} test_cases[] = {
|
||||
{
|
||||
"without_db", {
|
||||
capabilities(caps),
|
||||
caps,
|
||||
16777216, // max packet size
|
||||
collations::utf8_general_ci,
|
||||
"root", // username
|
||||
@ -277,7 +278,7 @@ BOOST_AUTO_TEST_CASE(login_request_)
|
||||
},
|
||||
{
|
||||
"with_db", {
|
||||
capabilities(caps | CLIENT_CONNECT_WITH_DB),
|
||||
caps | capabilities::connect_with_db,
|
||||
16777216, // max packet size
|
||||
collations::utf8_general_ci,
|
||||
"root", // username
|
||||
@ -302,11 +303,12 @@ BOOST_AUTO_TEST_CASE(login_request_)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ssl_request_)
|
||||
{
|
||||
constexpr std::uint32_t caps = CLIENT_LONG_FLAG | CLIENT_LOCAL_FILES | CLIENT_PROTOCOL_41 |
|
||||
CLIENT_INTERACTIVE | CLIENT_SSL | CLIENT_TRANSACTIONS |
|
||||
CLIENT_SECURE_CONNECTION | CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS |
|
||||
CLIENT_PS_MULTI_RESULTS | CLIENT_PLUGIN_AUTH | CLIENT_CONNECT_ATTRS |
|
||||
CLIENT_SESSION_TRACK | (1UL << 29);
|
||||
constexpr auto caps = capabilities::long_flag | capabilities::local_files | capabilities::protocol_41 |
|
||||
capabilities::interactive | capabilities::ssl | capabilities::transactions |
|
||||
capabilities::secure_connection | capabilities::multi_statements |
|
||||
capabilities::multi_results | capabilities::ps_multi_results |
|
||||
capabilities::plugin_auth | capabilities::connect_attrs |
|
||||
capabilities::session_track | static_cast<capabilities>(1UL << 29);
|
||||
|
||||
// Data
|
||||
ssl_request value{
|
||||
|
@ -58,12 +58,11 @@ namespace {
|
||||
BOOST_AUTO_TEST_SUITE(test_handshake)
|
||||
|
||||
// Capabilities
|
||||
constexpr capabilities min_caps{
|
||||
detail::CLIENT_PLUGIN_AUTH | detail::CLIENT_PROTOCOL_41 | detail::CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA |
|
||||
detail::CLIENT_DEPRECATE_EOF | detail::CLIENT_SECURE_CONNECTION
|
||||
};
|
||||
constexpr auto min_caps = capabilities::plugin_auth | capabilities::protocol_41 |
|
||||
capabilities::plugin_auth_lenenc_data | capabilities::deprecate_eof |
|
||||
capabilities::secure_connection;
|
||||
|
||||
constexpr capabilities tls_caps{min_caps.get() | detail::CLIENT_SSL};
|
||||
constexpr auto tls_caps = min_caps | capabilities::ssl;
|
||||
|
||||
// Helpers to create the relevant packets
|
||||
class server_hello_builder
|
||||
@ -119,7 +118,9 @@ public:
|
||||
// Capabilities is also divided in 2 parts
|
||||
string_fixed<2> caps_low{};
|
||||
string_fixed<2> caps_high{};
|
||||
std::uint32_t caps_little = boost::endian::native_to_little(server_caps_.get());
|
||||
std::uint32_t caps_little = boost::endian::native_to_little(
|
||||
static_cast<std::uint32_t>(server_caps_)
|
||||
);
|
||||
auto* caps_begin = reinterpret_cast<const char*>(&caps_little);
|
||||
std::copy(caps_begin, caps_begin + 2, caps_low.value.data());
|
||||
std::copy(caps_begin + 2, caps_begin + 4, caps_high.value.data());
|
||||
@ -783,7 +784,7 @@ BOOST_AUTO_TEST_CASE(csha2p_securetransport_fullauth_ok)
|
||||
// capabilities: connect with db
|
||||
//
|
||||
|
||||
constexpr capabilities db_caps = min_caps | capabilities(detail::CLIENT_CONNECT_WITH_DB);
|
||||
constexpr auto db_caps = min_caps | capabilities::connect_with_db;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(db_nonempty_supported)
|
||||
{
|
||||
@ -853,7 +854,7 @@ BOOST_AUTO_TEST_CASE(db_empty_unsupported)
|
||||
// capabilities: multi_queries
|
||||
//
|
||||
|
||||
constexpr capabilities multiq_caps = min_caps | capabilities(detail::CLIENT_MULTI_STATEMENTS);
|
||||
constexpr auto multiq_caps = min_caps | capabilities::multi_statements;
|
||||
|
||||
// We request it and the server supports it
|
||||
BOOST_AUTO_TEST_CASE(multiq_true_supported)
|
||||
@ -1061,7 +1062,6 @@ BOOST_AUTO_TEST_CASE(tls_error_unsupported)
|
||||
//
|
||||
// Base capabilities
|
||||
//
|
||||
// TODO: having the capabilities in all uppercase likely conflicts with official headers
|
||||
|
||||
// If the server doesn't have these, we can't talk to it
|
||||
BOOST_AUTO_TEST_CASE(caps_mandatory)
|
||||
@ -1071,15 +1071,23 @@ BOOST_AUTO_TEST_CASE(caps_mandatory)
|
||||
const char* name;
|
||||
capabilities caps;
|
||||
} test_cases[] = {
|
||||
{"no_protocol_41", capabilities(min_caps.get() & ~detail::CLIENT_PROTOCOL_41) },
|
||||
{"no_plugin_auth", capabilities(min_caps.get() & ~detail::CLIENT_PLUGIN_AUTH) },
|
||||
{"no_plugin_auth",
|
||||
capabilities::protocol_41 | capabilities::plugin_auth_lenenc_data | capabilities::deprecate_eof |
|
||||
capabilities::secure_connection },
|
||||
{"no_protocol_41",
|
||||
capabilities::plugin_auth | capabilities::plugin_auth_lenenc_data | capabilities::deprecate_eof |
|
||||
capabilities::secure_connection },
|
||||
{"no_plugin_auth_lenenc_data",
|
||||
capabilities(min_caps.get() & ~detail::CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA) },
|
||||
{"no_deprecate_eof", capabilities(min_caps.get() & ~detail::CLIENT_DEPRECATE_EOF) },
|
||||
{"no_secure_connection", capabilities(min_caps.get() & ~detail::CLIENT_SECURE_CONNECTION)},
|
||||
{"several_missing",
|
||||
capabilities(detail::CLIENT_PLUGIN_AUTH | detail::CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA) },
|
||||
{"none", capabilities() },
|
||||
capabilities::plugin_auth | capabilities::protocol_41 | capabilities::deprecate_eof |
|
||||
capabilities::secure_connection },
|
||||
{"no_deprecate_eof",
|
||||
capabilities::plugin_auth | capabilities::protocol_41 | capabilities::plugin_auth_lenenc_data |
|
||||
capabilities::secure_connection },
|
||||
{"no_secure_connection",
|
||||
capabilities::plugin_auth | capabilities::protocol_41 | capabilities::plugin_auth_lenenc_data |
|
||||
capabilities::deprecate_eof },
|
||||
{"several_missing", capabilities::plugin_auth | capabilities::plugin_auth_lenenc_data},
|
||||
{"none", capabilities{} },
|
||||
};
|
||||
|
||||
for (const auto& tc : test_cases)
|
||||
@ -1105,8 +1113,8 @@ BOOST_AUTO_TEST_CASE(caps_optional)
|
||||
const char* name;
|
||||
capabilities caps;
|
||||
} test_cases[] = {
|
||||
{"multi_results", capabilities(detail::CLIENT_MULTI_RESULTS) },
|
||||
{"ps_multi_results", capabilities(detail::CLIENT_PS_MULTI_RESULTS)},
|
||||
{"multi_results", capabilities::multi_results },
|
||||
{"ps_multi_results", capabilities::ps_multi_results},
|
||||
};
|
||||
|
||||
for (const auto& tc : test_cases)
|
||||
@ -1142,24 +1150,24 @@ BOOST_AUTO_TEST_CASE(caps_ignored)
|
||||
const char* name;
|
||||
capabilities caps;
|
||||
} test_cases[] = {
|
||||
{"long_password", capabilities(detail::CLIENT_LONG_PASSWORD) },
|
||||
{"found_rows", capabilities(detail::CLIENT_FOUND_ROWS) },
|
||||
{"long_flag", capabilities(detail::CLIENT_LONG_FLAG) },
|
||||
{"no_schema", capabilities(detail::CLIENT_NO_SCHEMA) },
|
||||
{"compress", capabilities(detail::CLIENT_COMPRESS) },
|
||||
{"odbc", capabilities(detail::CLIENT_ODBC) },
|
||||
{"local_files", capabilities(detail::CLIENT_LOCAL_FILES) },
|
||||
{"ignore_space", capabilities(detail::CLIENT_IGNORE_SPACE) },
|
||||
{"interactive", capabilities(detail::CLIENT_INTERACTIVE) },
|
||||
{"ignore_sigpipe", capabilities(detail::CLIENT_IGNORE_SIGPIPE) },
|
||||
{"transactions", capabilities(detail::CLIENT_TRANSACTIONS) },
|
||||
{"reserved", capabilities(detail::CLIENT_RESERVED) },
|
||||
{"connect_attrs", capabilities(detail::CLIENT_CONNECT_ATTRS) },
|
||||
{"can_handle_expired_passwords", capabilities(detail::CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS)},
|
||||
{"session_track", capabilities(detail::CLIENT_SESSION_TRACK) },
|
||||
{"ssl_verify_server_cert", capabilities(detail::CLIENT_SSL_VERIFY_SERVER_CERT) },
|
||||
{"optional_resultset_metadata", capabilities(detail::CLIENT_OPTIONAL_RESULTSET_METADATA) },
|
||||
{"remember_options", capabilities(detail::CLIENT_REMEMBER_OPTIONS) },
|
||||
{"long_password", capabilities::long_password },
|
||||
{"found_rows", capabilities::found_rows },
|
||||
{"long_flag", capabilities::long_flag },
|
||||
{"no_schema", capabilities::no_schema },
|
||||
{"compress", capabilities::compress },
|
||||
{"odbc", capabilities::odbc },
|
||||
{"local_files", capabilities::local_files },
|
||||
{"ignore_space", capabilities::ignore_space },
|
||||
{"interactive", capabilities::interactive },
|
||||
{"ignore_sigpipe", capabilities::ignore_sigpipe },
|
||||
{"transactions", capabilities::transactions },
|
||||
{"reserved", capabilities::reserved },
|
||||
{"connect_attrs", capabilities::connect_attrs },
|
||||
{"can_handle_expired_passwords", capabilities::can_handle_expired_passwords},
|
||||
{"session_track", capabilities::session_track },
|
||||
{"ssl_verify_server_cert", capabilities::ssl_verify_server_cert },
|
||||
{"optional_resultset_metadata", capabilities::optional_resultset_metadata },
|
||||
{"remember_options", capabilities::remember_options },
|
||||
};
|
||||
|
||||
for (const auto& tc : test_cases)
|
||||
|
Loading…
x
Reference in New Issue
Block a user