2
0
mirror of https://github.com/boostorg/mysql.git synced 2026-02-13 12:32:18 +00:00

clang-format for headers

This commit is contained in:
Ruben Perez
2022-10-11 14:45:38 +02:00
parent 996172dc3a
commit 905eadb5ba
118 changed files with 2522 additions and 2731 deletions

169
.clang-format Normal file
View File

@@ -0,0 +1,169 @@
---
Language: Cpp
ColumnLimit: 100
IndentWidth: 4
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: true
AfterClass: true
AfterControlStatement: true
AfterEnum: true
AfterFunction: true
AfterNamespace: false
AfterStruct: true
AfterUnion: true
AfterExternBlock: false
BeforeCatch: true
BeforeElse: true
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
AccessModifierOffset: -4
BinPackArguments: false
BinPackParameters: false
AlignAfterOpenBracket: BlockIndent
PointerAlignment: Left
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^<boost/mysql/.*\.hpp>'
Priority: -8
SortPriority: 0
- Regex: '^<boost/.*\.hpp>'
Priority: -7
SortPriority: 0
- Regex: "^<.*"
Priority: -6
SortPriority: 0
- Regex: ".*"
Priority: -5
SortPriority: 0
IndentCaseLabels: false
AllowShortCaseLabelsOnASingleLine: true
AllowAllArgumentsOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlignArrayOfStructures: Left
DerivePointerAlignment: false
PenaltyBreakAssignment: 2000000
PenaltyBreakBeforeFirstCallParameter: 0
PenaltyBreakOpenParenthesis: 0
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200000000
# Defaults (based on Google)
AlignConsecutiveMacros: false
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllConstructorInitializersOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortFunctionsOnASingleLine: All
AllowShortLambdasOnASingleLine: All
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BreakBeforeBinaryOperators: None
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
CommentPragmas: "^ IWYU pragma:"
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: true
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeIsMainRegex: "([-_](test|unittest))?$"
IncludeIsMainSourceRegex: ""
IndentGotoLabels: true
IndentPPDirectives: None
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ""
MacroBlockEnd: ""
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Never
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
RawStringFormats:
- Language: Cpp
Delimiters:
- cc
- CC
- cpp
- Cpp
- CPP
- "c++"
- "C++"
CanonicalDelimiter: ""
BasedOnStyle: google
- Language: TextProto
Delimiters:
- pb
- PB
- proto
- PROTO
EnclosingFunctions:
- EqualsProto
- EquivToProto
- PARSE_PARTIAL_TEXT_PROTO
- PARSE_TEST_PROTO
- PARSE_TEXT_PROTO
- ParseTextOrDie
- ParseTextProtoOrDie
CanonicalDelimiter: ""
BasedOnStyle: google
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
Standard: Auto
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 8
UseCRLF: false
UseTab: Never
---

View File

@@ -55,6 +55,7 @@ target_link_libraries(
)
target_include_directories(
boost_mysql
SYSTEM # TODO: review this
INTERFACE
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"

View File

@@ -20,8 +20,7 @@ public:
const char* what() const noexcept override { return "bad_value_access"; }
};
} // mysql
} // boost
} // namespace mysql
} // namespace boost
#endif

View File

@@ -245,9 +245,7 @@ enum class collation : std::uint16_t
gb18030_unicode_520_ci = 250
};
} // mysql
} // boost
} // namespace mysql
} // namespace boost
#endif

View File

@@ -10,14 +10,16 @@
#include <boost/asio/ssl/context.hpp>
#ifndef BOOST_MYSQL_DOXYGEN // For some arcane reason, Doxygen fails to expand Asio macros without this
#ifndef BOOST_MYSQL_DOXYGEN // For some arcane reason, Doxygen fails to expand Asio macros without
// this
#include <boost/mysql/detail/channel/channel.hpp>
#include <boost/mysql/detail/protocol/protocol_types.hpp>
#include <boost/mysql/error.hpp>
#include <boost/mysql/handshake_params.hpp>
#include <boost/mysql/resultset.hpp>
#include <boost/mysql/statement.hpp>
#include <boost/mysql/handshake_params.hpp>
#include <type_traits>
#endif
@@ -54,9 +56,7 @@ namespace mysql {
* In particular, it is __not__ allowed to call [refmem connection handshake]
* on a moved-from connection in order to re-open it.
*/
template <
class Stream
>
template <class Stream>
class connection
{
std::unique_ptr<detail::channel<Stream>> channel_;
@@ -72,36 +72,36 @@ class connection
return *channel_;
}
error_info& shared_info() noexcept { return get_channel().shared_info(); }
public:
/**
* \brief Initializing constructor.
* \details
* As part of the initialization, a Stream object is created
* by forwarding any passed in arguments to its constructor.
*
*
* The constructed connection will have [refmem connection valid]
* return `true`.
*/
template<
template <
class... Args,
class EnableIf = typename std::enable_if<std::is_constructible<Stream, Args...>::value>::type
>
connection(Args&&... args) :
channel_(new detail::channel<Stream>(std::forward<Args>(args)...))
class EnableIf =
typename std::enable_if<std::is_constructible<Stream, Args...>::value>::type>
connection(Args&&... args) : channel_(new detail::channel<Stream>(std::forward<Args>(args)...))
{
}
/**
* \brief Move constructor.
* \details The constructed connection will be valid if `other` is valid.
* After this operation, `other` is guaranteed to be invalid.
*/
* \brief Move constructor.
* \details The constructed connection will be valid if `other` is valid.
* After this operation, `other` is guaranteed to be invalid.
*/
connection(connection&& other) = default;
/**
* \brief Move assignment.
* \details The assigned-to connection will be valid if `other` is valid.
*/
* \brief Move assignment.
* \details The assigned-to connection will be valid if `other` is valid.
*/
connection& operator=(connection&& rhs) = default;
#ifndef BOOST_MYSQL_DOXYGEN
@@ -138,7 +138,7 @@ public:
/**
* \brief Returns whether the connection uses SSL or not.
* \details This function always returns `false` if the underlying
* stream does not support SSL. This function always returns `false`
* stream does not support SSL. This function always returns `false`
* for connections that haven't been
* established yet (handshake not run yet). If the handshake fails,
* the return value is undefined.
@@ -149,7 +149,6 @@ public:
*/
bool uses_ssl() const noexcept { return get_channel().ssl_active(); }
/**
* \brief Performs a connection to the MySQL server (sync with error code version).
* \details This function is only available if `Stream` satisfies the
@@ -166,7 +165,7 @@ public:
void connect(
const EndpointType& endpoint,
const handshake_params& params,
error_code& ec,
error_code& ec,
error_info& info
);
@@ -183,10 +182,7 @@ public:
* See [link mysql.ssl.handshake this section] for more info.
*/
template <typename EndpointType>
void connect(
const EndpointType& endpoint,
const handshake_params& params
);
void connect(const EndpointType& endpoint, const handshake_params& params);
/**
* \brief Performs a connection to the MySQL server
@@ -210,9 +206,7 @@ public:
template <
typename EndpointType,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
CompletionToken
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)
>
CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
async_connect(
const EndpointType& endpoint,
@@ -220,7 +214,12 @@ public:
CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
)
{
return async_connect(endpoint, params, this->shared_info(), std::forward<CompletionToken>(token));
return async_connect(
endpoint,
params,
this->shared_info(),
std::forward<CompletionToken>(token)
);
}
/**
@@ -245,9 +244,7 @@ public:
template <
typename EndpointType,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
CompletionToken
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)
>
CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
async_connect(
const EndpointType& endpoint,
@@ -258,7 +255,7 @@ public:
/**
* \brief Performs the MySQL-level handshake (sync with error code version).
* \details Does not connect the underlying stream.
* \details Does not connect the underlying stream.
* If the `Stream` template parameter fulfills the __SocketConnection__
* requirements, use [refmem connection connect] instead of this function.
*
@@ -292,11 +289,8 @@ public:
*
* The handler signature for this operation is `void(boost::mysql::error_code)`.
*/
template <
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
CompletionToken
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)
>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
async_handshake(
const handshake_params& params,
@@ -320,11 +314,8 @@ public:
*
* The handler signature for this operation is `void(boost::mysql::error_code)`.
*/
template <
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
CompletionToken
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)
>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
async_handshake(
const handshake_params& params,
@@ -340,7 +331,8 @@ public:
* before calling any function that involves communication with the server over this
* connection. Otherwise, the results are undefined.
*/
void query(boost::string_view query_string, resultset<Stream>& result, error_code&, error_info&);
void
query(boost::string_view query_string, resultset<Stream>& result, error_code&, error_info&);
/**
* \brief Executes a SQL text query (sync with exceptions version).
@@ -363,11 +355,8 @@ public:
* The handler signature for this operation is
* `void(boost::mysql::error_code, boost::mysql::resultset_base<Stream>)`.
*/
template <
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
CompletionToken
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)
>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
async_query(
boost::string_view query_string,
@@ -375,7 +364,12 @@ public:
CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
)
{
return async_query(query_string, result, shared_info(), std::forward<CompletionToken>(token));
return async_query(
query_string,
result,
shared_info(),
std::forward<CompletionToken>(token)
);
}
/**
@@ -389,11 +383,8 @@ public:
* The handler signature for this operation is
* `void(boost::mysql::error_code, boost::mysql::resultset_base<Stream>)`.
*/
template <
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
CompletionToken
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)
>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
async_query(
boost::string_view query_string,
@@ -408,7 +399,8 @@ public:
* Prepared statements are only valid while the connection object on which
* this function was called is alive and open.
*/
void prepare_statement(boost::string_view stmt, statement<Stream>& result, error_code&, error_info&);
void
prepare_statement(boost::string_view stmt, statement<Stream>& result, error_code&, error_info&);
/**
* \brief Prepares a statement (sync with exceptions version).
@@ -427,11 +419,8 @@ public:
* The handler signature for this operation is
* `void(boost::mysql::error_code, boost::mysql::statement_base<Stream>)`
*/
template <
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
CompletionToken
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)
>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
async_prepare_statement(
boost::string_view stmt,
@@ -439,7 +428,12 @@ public:
CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
)
{
return async_prepare_statement(stmt, result, shared_info(), std::forward<CompletionToken>(token));
return async_prepare_statement(
stmt,
result,
shared_info(),
std::forward<CompletionToken>(token)
);
}
/**
@@ -451,11 +445,8 @@ public:
* The handler signature for this operation is
* `void(boost::mysql::error_code, boost::mysql::statement_base<Stream>)`
*/
template <
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
CompletionToken
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)
>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
async_prepare_statement(
boost::string_view stmt,
@@ -464,10 +455,9 @@ public:
CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
);
/**
* \brief Closes the connection (sync with error code version).
* \details
* \details
* This function is only available if `Stream` satisfies the
* [reflink SocketStream] requirements.
*
@@ -478,7 +468,7 @@ public:
/**
* \brief Closes the connection (sync with exceptions version).
* \details
* \details
* This function is only available if `Stream` satisfies the
* [reflink SocketStream] requirements.
*
@@ -489,7 +479,7 @@ public:
/**
* \brief Closes the connection (async without [reflink error_info] version).
* \details
* \details
* This function is only available if `Stream` satisfies the
* [reflink SocketStream] requirements.
*
@@ -498,11 +488,8 @@ public:
*
* The handler signature for this operation is `void(boost::mysql::error_code)`.
*/
template <
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
CompletionToken
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)
>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
async_close(CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
{
@@ -511,7 +498,7 @@ public:
/**
* \brief Closes the connection (async with [reflink error_info] version).
* \details
* \details
* This function is only available if `Stream` satisfies the
* [reflink SocketStream] requirements.
*
@@ -520,24 +507,20 @@ public:
*
* The handler signature for this operation is `void(boost::mysql::error_code)`.
*/
template <
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
CompletionToken
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)
>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
async_close(
error_info& output_info,
CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)
);
/**
* \brief Notifies the MySQL server that the client wants to end the session
* (sync with error code version).
*
* \details Sends a quit request to the MySQL server. If the connection is using SSL,
* this function will also perform the SSL shutdown. You should
* this function will also perform the SSL shutdown. You should
* close the underlying physical connection after calling this function.
*
* If the `Stream` template parameter fulfills the __SocketConnection__
@@ -552,7 +535,7 @@ public:
* (sync with exceptions version).
*
* \details Sends a quit request to the MySQL server. If the connection is using SSL,
* this function will also perform the SSL shutdown. You should
* this function will also perform the SSL shutdown. You should
* close the underlying physical connection after calling this function.
*
* If the `Stream` template parameter fulfills the __SocketConnection__
@@ -566,7 +549,7 @@ public:
* (async without [reflink error_info] version).
*
* \details Sends a quit request to the MySQL server. If the connection is using SSL,
* this function will also perform the SSL shutdown. You should
* this function will also perform the SSL shutdown. You should
* close the underlying physical connection after calling this function.
*
* If the `Stream` template parameter fulfills the __SocketConnection__
@@ -575,11 +558,8 @@ public:
*
* The handler signature for this operation is `void(boost::mysql::error_code)`.
*/
template <
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
CompletionToken
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)
>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
async_quit(CompletionToken&& token BOOST_ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))
{
@@ -591,7 +571,7 @@ public:
* (async with [reflink error_info] version).
*
* \details Sends a quit request to the MySQL server. If the connection is using SSL,
* this function will also perform the SSL shutdown. You should
* this function will also perform the SSL shutdown. You should
* close the underlying physical connection after calling this function.
*
* If the `Stream` template parameter fulfills the __SocketConnection__
@@ -600,11 +580,8 @@ public:
*
* The handler signature for this operation is `void(boost::mysql::error_code)`.
*/
template <
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
CompletionToken
BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)
>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code))
CompletionToken BOOST_ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
async_quit(
error_info& output_info,
@@ -618,8 +595,8 @@ constexpr unsigned short default_port = 3306;
/// The default TCP port for the MySQL protocol, as a string. Useful for hostname resolution.
constexpr const char* default_port_string = "3306";
} // mysql
} // boost
} // namespace mysql
} // namespace boost
#include <boost/mysql/impl/connection.hpp>

View File

@@ -8,9 +8,10 @@
#ifndef BOOST_MYSQL_DATETIME_TYPES_HPP
#define BOOST_MYSQL_DATETIME_TYPES_HPP
#include <chrono>
#include <boost/config.hpp>
#include <chrono>
namespace boost {
namespace mysql {
@@ -31,16 +32,17 @@ using datetime = std::chrono::time_point<std::chrono::system_clock, std::chrono:
using time = std::chrono::microseconds;
/// The minimum allowed value for [reflink date] (0000-01-01).
BOOST_CXX14_CONSTEXPR const date min_date { days(-719528) };
BOOST_CXX14_CONSTEXPR const date min_date{days(-719528)};
/// The maximum allowed value for [reflink date] (9999-12-31).
BOOST_CXX14_CONSTEXPR const date max_date { days(2932896) };
BOOST_CXX14_CONSTEXPR const date max_date{days(2932896)};
/// The minimum allowed value for [reflink datetime].
BOOST_CXX14_CONSTEXPR const datetime min_datetime = min_date;
/// The maximum allowed value for [reflink datetime].
BOOST_CXX14_CONSTEXPR const datetime max_datetime = max_date + std::chrono::hours(24) - std::chrono::microseconds(1);
BOOST_CXX14_CONSTEXPR const datetime max_datetime =
max_date + std::chrono::hours(24) - std::chrono::microseconds(1);
/// The minimum allowed value for [reflink time].
constexpr time min_time = -std::chrono::hours(839);
@@ -48,7 +50,7 @@ constexpr time min_time = -std::chrono::hours(839);
/// The maximum allowed value for [reflink time].
constexpr time max_time = std::chrono::hours(839);
} // mysql
} // boost
} // namespace mysql
} // namespace boost
#endif

View File

@@ -8,11 +8,13 @@
#ifndef BOOST_MYSQL_DETAIL_AUTH_AUTH_CALCULATOR_HPP
#define BOOST_MYSQL_DETAIL_AUTH_AUTH_CALCULATOR_HPP
#include <boost/mysql/error.hpp>
#include <boost/mysql/detail/auxiliar/bytestring.hpp>
#include <boost/mysql/error.hpp>
#include <boost/utility/string_view.hpp>
#include <array>
#include <vector>
#include <boost/utility/string_view.hpp>
namespace boost {
namespace mysql {
@@ -33,10 +35,11 @@ struct authentication_plugin
class auth_calculator
{
const authentication_plugin* plugin_ {nullptr};
const authentication_plugin* plugin_{nullptr};
bytestring response_;
inline static const authentication_plugin* find_plugin(boost::string_view name);
public:
inline error_code calculate(
boost::string_view plugin_name,
@@ -46,7 +49,10 @@ public:
);
boost::string_view response() const noexcept
{
return boost::string_view(reinterpret_cast<const char*>(response_.data()), response_.size());
return boost::string_view(
reinterpret_cast<const char*>(response_.data()),
response_.size()
);
}
boost::string_view plugin_name() const noexcept
{
@@ -55,9 +61,9 @@ public:
}
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/auth/impl/auth_calculator.ipp>

View File

@@ -8,11 +8,13 @@
#ifndef BOOST_MYSQL_DETAIL_AUTH_CACHING_SHA2_PASSWORD_HPP
#define BOOST_MYSQL_DETAIL_AUTH_CACHING_SHA2_PASSWORD_HPP
#include <cstddef>
#include <boost/mysql/detail/auxiliar/bytestring.hpp>
#include <boost/utility/string_view.hpp>
#include <boost/mysql/error.hpp>
#include <boost/utility/string_view.hpp>
#include <cstddef>
namespace boost {
namespace mysql {
namespace detail {
@@ -34,10 +36,10 @@ inline error_code compute_response(
bytestring& output
);
} // caching_sha2_password
} // detail
} // mysql
} // boost
} // namespace caching_sha2_password
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/auth/impl/caching_sha2_password.ipp>

View File

@@ -11,55 +11,48 @@
#pragma once
#include <boost/mysql/detail/auth/auth_calculator.hpp>
#include <boost/mysql/detail/auth/mysql_native_password.hpp>
#include <boost/mysql/detail/auth/caching_sha2_password.hpp>
#include <boost/mysql/detail/auth/mysql_native_password.hpp>
#include <boost/mysql/detail/auxiliar/make_string_view.hpp>
namespace boost {
namespace mysql {
namespace detail {
constexpr authentication_plugin mysql_native_password_plugin {
constexpr authentication_plugin mysql_native_password_plugin{
make_string_view("mysql_native_password"),
&mysql_native_password::compute_response
};
&mysql_native_password::compute_response};
constexpr authentication_plugin caching_sha2_password_plugin {
constexpr authentication_plugin caching_sha2_password_plugin{
make_string_view("caching_sha2_password"),
&caching_sha2_password::compute_response
};
&caching_sha2_password::compute_response};
constexpr std::array<const authentication_plugin*, 2> all_authentication_plugins {{
constexpr const authentication_plugin* all_authentication_plugins[] = {
&mysql_native_password_plugin,
&caching_sha2_password_plugin
}};
&caching_sha2_password_plugin};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
inline const boost::mysql::detail::authentication_plugin*
boost::mysql::detail::auth_calculator::find_plugin(
boost::string_view name
)
boost::mysql::detail::auth_calculator::find_plugin(boost::string_view name)
{
auto it = std::find_if(
all_authentication_plugins.begin(),
all_authentication_plugins.end(),
std::begin(all_authentication_plugins),
std::end(all_authentication_plugins),
[name](const authentication_plugin* plugin) { return plugin->name == name; }
);
return it == std::end(all_authentication_plugins) ? nullptr : *it;
}
inline boost::mysql::error_code
boost::mysql::detail::auth_calculator::calculate(
inline boost::mysql::error_code boost::mysql::detail::auth_calculator::calculate(
boost::string_view plugin_name,
boost::string_view password,
boost::string_view challenge,
bool use_ssl
)
{
plugin_ = find_plugin(plugin_name);
if (plugin_)
{
@@ -80,6 +73,4 @@ boost::mysql::detail::auth_calculator::calculate(
}
}
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_AUTH_IMPL_AUTH_CALCULATOR_IPP_ */

View File

@@ -10,11 +10,12 @@
#pragma once
#include <openssl/sha.h>
#include <cstring>
#include <boost/mysql/detail/auxiliar/make_string_view.hpp>
#include <boost/mysql/detail/auth/caching_sha2_password.hpp>
#include <boost/mysql/detail/auxiliar/bytestring.hpp>
#include <boost/mysql/detail/auxiliar/make_string_view.hpp>
#include <cstring>
#include <openssl/sha.h>
namespace boost {
namespace mysql {
@@ -27,22 +28,18 @@ constexpr boost::string_view perform_full_auth = make_string_view("\4");
// challenge must point to challenge_length bytes of data
// output must point to response_length bytes of data
inline void compute_auth_string(
boost::string_view password,
const void* challenge,
void* output
)
inline void compute_auth_string(boost::string_view password, const void* challenge, void* output)
{
static_assert(response_length == SHA256_DIGEST_LENGTH, "Buffer size mismatch");
// SHA(SHA(password_sha) concat challenge) XOR password_sha
// hash1 = SHA(pass)
using sha_buffer = std::uint8_t [response_length];
using sha_buffer = std::uint8_t[response_length];
sha_buffer password_sha;
SHA256(reinterpret_cast<const unsigned char*>(password.data()), password.size(), password_sha);
// SHA(password_sha) concat challenge = buffer
std::uint8_t buffer [response_length + challenge_length];
std::uint8_t buffer[response_length + challenge_length];
SHA256(password_sha, response_length, buffer);
std::memcpy(buffer + response_length, challenge, challenge_length);
@@ -57,15 +54,12 @@ inline void compute_auth_string(
}
}
} // caching_sha2_password
} // detail
} // mysql
} // boost
} // namespace caching_sha2_password
} // namespace detail
} // namespace mysql
} // namespace boost
inline boost::mysql::error_code
boost::mysql::detail::caching_sha2_password::compute_response(
inline boost::mysql::error_code boost::mysql::detail::caching_sha2_password::compute_response(
boost::string_view password,
boost::string_view challenge,
bool use_ssl,
@@ -92,14 +86,9 @@ boost::mysql::detail::caching_sha2_password::compute_response(
// Do the calculation
output.resize(response_length);
compute_auth_string(
password,
challenge.data(),
output.data()
);
compute_auth_string(password, challenge.data(), output.data());
return error_code();
}
}
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_AUTH_IMPL_CACHING_SHA2_PASSWORD_IPP_ */

View File

@@ -10,10 +10,11 @@
#pragma once
#include <openssl/sha.h>
#include <cstring>
#include <boost/mysql/detail/auth/mysql_native_password.hpp>
#include <cstring>
#include <openssl/sha.h>
namespace boost {
namespace mysql {
namespace detail {
@@ -25,19 +26,15 @@ constexpr std::size_t response_length = 20;
// challenge must point to challenge_length bytes of data
// output must point to response_length bytes of data
// SHA1( password ) XOR SHA1( "20-bytes random data from server" <concat> SHA1( SHA1( password ) ) )
inline void compute_auth_string(
boost::string_view password,
const void* challenge,
void* output
)
inline void compute_auth_string(boost::string_view password, const void* challenge, void* output)
{
// SHA1 (password)
using sha1_buffer = unsigned char [SHA_DIGEST_LENGTH];
using sha1_buffer = unsigned char[SHA_DIGEST_LENGTH];
sha1_buffer password_sha1;
SHA1(reinterpret_cast<const unsigned char*>(password.data()), password.size(), password_sha1);
// Add server challenge (salt)
unsigned char salted_buffer [challenge_length + SHA_DIGEST_LENGTH];
unsigned char salted_buffer[challenge_length + SHA_DIGEST_LENGTH];
memcpy(salted_buffer, challenge, challenge_length);
SHA1(password_sha1, sizeof(password_sha1), salted_buffer + 20);
sha1_buffer salted_sha1;
@@ -51,17 +48,15 @@ inline void compute_auth_string(
}
}
} // mysql_native_password
} // detail
} // mysql
} // boost
} // namespace mysql_native_password
} // namespace detail
} // namespace mysql
} // namespace boost
inline boost::mysql::error_code
boost::mysql::detail::mysql_native_password::compute_response(
inline boost::mysql::error_code boost::mysql::detail::mysql_native_password::compute_response(
boost::string_view password,
boost::string_view challenge,
bool, // use_ssl
bool, // use_ssl
bytestring& output
)
{
@@ -73,14 +68,8 @@ boost::mysql::detail::mysql_native_password::compute_response(
// Do the calculation
output.resize(response_length);
compute_auth_string(
password,
challenge.data(),
output.data()
);
compute_auth_string(password, challenge.data(), output.data());
return error_code();
}
#endif

View File

@@ -8,11 +8,13 @@
#ifndef BOOST_MYSQL_DETAIL_AUTH_MYSQL_NATIVE_PASSWORD_HPP
#define BOOST_MYSQL_DETAIL_AUTH_MYSQL_NATIVE_PASSWORD_HPP
#include <cstdint>
#include <boost/utility/string_view.hpp>
#include <boost/mysql/detail/auxiliar/bytestring.hpp>
#include <boost/mysql/error.hpp>
#include <boost/utility/string_view.hpp>
#include <cstdint>
namespace boost {
namespace mysql {
namespace detail {
@@ -27,11 +29,10 @@ inline error_code compute_response(
bytestring& output
);
} // mysql_native_password
} // detail
} // mysql
} // boost
} // namespace mysql_native_password
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/auth/impl/mysql_native_password.ipp>

View File

@@ -8,8 +8,8 @@
#ifndef BOOST_MYSQL_DETAIL_AUXILIAR_BYTESTRING_HPP
#define BOOST_MYSQL_DETAIL_AUXILIAR_BYTESTRING_HPP
#include <vector>
#include <cstdint>
#include <vector>
namespace boost {
namespace mysql {
@@ -20,10 +20,8 @@ using basic_bytestring = std::vector<std::uint8_t, Allocator>;
using bytestring = std::vector<std::uint8_t>;
}
}
}
} // namespace detail
} // namespace mysql
} // namespace boost
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_AUXILIAR_BYTESTRING_HPP_ */

View File

@@ -8,11 +8,13 @@
#ifndef BOOST_MYSQL_DETAIL_AUXILIAR_FIELD_IMPL_HPP
#define BOOST_MYSQL_DETAIL_AUXILIAR_FIELD_IMPL_HPP
#include <boost/mysql/field_kind.hpp>
#include <boost/mysql/datetime_types.hpp>
#include <boost/mysql/bad_field_access.hpp>
#include <boost/variant2/variant.hpp>
#include <boost/mysql/datetime_types.hpp>
#include <boost/mysql/field_kind.hpp>
#include <boost/mp11.hpp>
#include <boost/variant2/variant.hpp>
#include <string>
#include <type_traits>
@@ -24,26 +26,29 @@ namespace detail {
struct field_impl
{
using null_t = boost::variant2::monostate;
using variant_type = boost::variant2::variant<
null_t, // Any of the below when the value is NULL
std::int64_t, // signed TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT
std::uint64_t, // unsigned TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT, YEAR, BIT
std::string, // CHAR, VARCHAR, BINARY, VARBINARY, TEXT (all sizes), BLOB (all sizes), ENUM, SET, DECIMAL, GEOMTRY
float, // FLOAT
double, // DOUBLE
date, // DATE
datetime, // DATETIME, TIMESTAMP
time // TIME
>;
null_t, // Any of the below when the value is NULL
std::int64_t, // signed TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT
std::uint64_t, // unsigned TINYINT, SMALLINT, MEDIUMINT, INT, BIGINT, YEAR, BIT
std::string, // CHAR, VARCHAR, BINARY, VARBINARY, TEXT (all sizes), BLOB (all sizes), ENUM,
// SET, DECIMAL, GEOMTRY
float, // FLOAT
double, // DOUBLE
date, // DATE
datetime, // DATETIME, TIMESTAMP
time // TIME
>;
variant_type data;
field_impl() = default;
template <typename... Args>
field_impl(Args&&... args) noexcept(std::is_nothrow_constructible<variant_type, Args...>::value) :
data (std::forward<Args>(args)...) {}
field_impl(Args&&... args) noexcept(std::is_nothrow_constructible<variant_type, Args...>::value)
: data(std::forward<Args>(args)...)
{
}
field_kind kind() const noexcept { return static_cast<field_kind>(data.index()); }
@@ -80,8 +85,8 @@ struct field_impl
}
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#endif

View File

@@ -8,8 +8,9 @@
#ifndef BOOST_MYSQL_DETAIL_AUXILIAR_FIELD_TYPE_TRAITS_HPP
#define BOOST_MYSQL_DETAIL_AUXILIAR_FIELD_TYPE_TRAITS_HPP
#include <boost/mysql/field_view.hpp>
#include <boost/mysql/detail/auxiliar/void_t.hpp>
#include <boost/mysql/field_view.hpp>
#include <cstddef>
#include <iterator>
#include <type_traits>
@@ -19,8 +20,11 @@ namespace mysql {
namespace detail {
template <typename T, typename = void>
struct is_field_view_forward_iterator : std::false_type { };
struct is_field_view_forward_iterator : std::false_type
{
};
// clang-format off
template <typename T>
struct is_field_view_forward_iterator<T, void_t<
typename std::enable_if<
@@ -36,10 +40,14 @@ struct is_field_view_forward_iterator<T, void_t<
>::value
>::type
>> : std::true_type { };
// clang-format on
template <typename T, typename = void>
struct is_field_view_collection : std::false_type {};
struct is_field_view_collection : std::false_type
{
};
// clang-format off
template <typename T>
struct is_field_view_collection<T, void_t<
typename std::enable_if<
@@ -49,19 +57,19 @@ struct is_field_view_collection<T, void_t<
is_field_view_forward_iterator<decltype(std::end(std::declval<const T&>()))>::value
>::type
>> : std::true_type {};
// clang-format on
// Helpers
template <typename T>
using enable_if_field_view_forward_iterator = typename std::enable_if<is_field_view_forward_iterator<T>::value>::type;
using enable_if_field_view_forward_iterator =
typename std::enable_if<is_field_view_forward_iterator<T>::value>::type;
template <typename T>
using enable_if_field_view_collection = typename std::enable_if<is_field_view_collection<T>::value>::type;
}
}
}
using enable_if_field_view_collection =
typename std::enable_if<is_field_view_collection<T>::value>::type;
} // namespace detail
} // namespace mysql
} // namespace boost
#endif

View File

@@ -12,28 +12,19 @@
#include <boost/mysql/detail/auxiliar/row_base.hpp>
boost::mysql::detail::row_base::row_base(
const field_view* fields,
std::size_t size
) :
fields_(fields, fields + size)
boost::mysql::detail::row_base::row_base(const field_view* fields, std::size_t size)
: fields_(fields, fields + size)
{
copy_strings();
}
boost::mysql::detail::row_base::row_base(
const row_base& rhs
) :
fields_(rhs.fields_),
string_buffer_(rhs.string_buffer_)
boost::mysql::detail::row_base::row_base(const row_base& rhs)
: fields_(rhs.fields_), string_buffer_(rhs.string_buffer_)
{
rebase_strings(rhs.string_buffer_.data());
}
boost::mysql::detail::row_base& boost::mysql::detail::row_base::operator=(
const row_base& rhs
)
boost::mysql::detail::row_base& boost::mysql::detail::row_base::operator=(const row_base& rhs)
{
fields_ = rhs.fields_;
string_buffer_ = rhs.string_buffer_;
@@ -41,21 +32,16 @@ boost::mysql::detail::row_base& boost::mysql::detail::row_base::operator=(
return *this;
}
void boost::mysql::detail::row_base::assign(
const field_view* fields,
std::size_t size
)
void boost::mysql::detail::row_base::assign(const field_view* fields, std::size_t size)
{
fields_.assign(fields, fields + size);
copy_strings();
}
inline void boost::mysql::detail::row_base::rebase_strings(
const char* old_buffer_base
)
inline void boost::mysql::detail::row_base::rebase_strings(const char* old_buffer_base)
{
const char* new_buffer_base = string_buffer_.data();
for (auto& f: fields_)
for (auto& f : fields_)
{
if (f.is_string())
{
@@ -63,10 +49,7 @@ inline void boost::mysql::detail::row_base::rebase_strings(
if (!sv.empty())
{
std::size_t offset = sv.data() - old_buffer_base;
f = field_view(boost::string_view(
new_buffer_base + offset,
sv.size()
));
f = field_view(boost::string_view(new_buffer_base + offset, sv.size()));
}
}
}
@@ -86,10 +69,10 @@ inline void boost::mysql::detail::row_base::copy_strings()
// Make space
string_buffer_.resize(size);
// Copy the strings
std::size_t offset = 0;
for (auto& f: fields_)
for (auto& f : fields_)
{
if (f.is_string())
{
@@ -104,5 +87,4 @@ inline void boost::mysql::detail::row_base::copy_strings()
}
}
#endif

View File

@@ -15,16 +15,14 @@ namespace mysql {
namespace detail {
template <std::size_t N>
constexpr boost::string_view make_string_view(const char(&buff)[N]) noexcept
constexpr boost::string_view make_string_view(const char (&buff)[N]) noexcept
{
static_assert(N>=1, "Expected a C-array literal");
return boost::string_view(buff, N-1); // discard null terminator
static_assert(N >= 1, "Expected a C-array literal");
return boost::string_view(buff, N - 1); // discard null terminator
}
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#endif

View File

@@ -9,6 +9,7 @@
#define BOOST_MYSQL_DETAIL_AUXILIAR_ROW_BASE_HPP
#include <boost/mysql/field_view.hpp>
#include <cstddef>
#include <vector>
@@ -33,16 +34,22 @@ public:
inline void assign(const field_view* fields, std::size_t size);
inline void rebase_strings(const char* old_buffer_base);
inline void copy_strings();
inline void clear() noexcept { fields_.clear(); string_buffer_.clear(); }
inline void clear() noexcept
{
fields_.clear();
string_buffer_.clear();
}
protected:
std::vector<field_view> fields_;
private:
std::vector<char> string_buffer_;
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/auxiliar/impl/row_base.ipp>

View File

@@ -8,21 +8,22 @@
#ifndef BOOST_MYSQL_DETAIL_AUXILIAR_ROWS_ITERATOR_HPP
#define BOOST_MYSQL_DETAIL_AUXILIAR_ROWS_ITERATOR_HPP
#include <cstdint>
#include <boost/mysql/row.hpp>
#include <boost/mysql/row_view.hpp>
#include <iterator>
#include <cstdint>
#include <iterator>
namespace boost {
namespace mysql {
namespace detail {
template <class RowsType> // This can be either rows or rows_view
template <class RowsType> // This can be either rows or rows_view
class rows_iterator
{
const RowsType* obj_ {nullptr};
std::size_t row_num_ {0};
const RowsType* obj_{nullptr};
std::size_t row_num_{0};
public:
using value_type = row;
using reference = row_view;
@@ -33,14 +34,46 @@ public:
rows_iterator() = default;
rows_iterator(const RowsType* obj, std::size_t rownum) noexcept : obj_(obj), row_num_(rownum) {}
rows_iterator& operator++() noexcept { ++row_num_; return *this; }
rows_iterator operator++(int) noexcept { auto res = *this; ++(*this); return res; }
rows_iterator& operator--() noexcept { --row_num_; return *this; }
rows_iterator operator--(int) noexcept { auto res = *this; --(*this); return res; }
rows_iterator& operator+=(std::ptrdiff_t n) noexcept { row_num_ += n; return *this; }
rows_iterator& operator-=(std::ptrdiff_t n) noexcept { row_num_ -= n; return *this; }
rows_iterator operator+(std::ptrdiff_t n) const noexcept { return rows_iterator(obj_, row_num_ + n); }
rows_iterator operator-(std::ptrdiff_t n) const noexcept { return rows_iterator(obj_, row_num_ - n); }
rows_iterator& operator++() noexcept
{
++row_num_;
return *this;
}
rows_iterator operator++(int) noexcept
{
auto res = *this;
++(*this);
return res;
}
rows_iterator& operator--() noexcept
{
--row_num_;
return *this;
}
rows_iterator operator--(int) noexcept
{
auto res = *this;
--(*this);
return res;
}
rows_iterator& operator+=(std::ptrdiff_t n) noexcept
{
row_num_ += n;
return *this;
}
rows_iterator& operator-=(std::ptrdiff_t n) noexcept
{
row_num_ -= n;
return *this;
}
rows_iterator operator+(std::ptrdiff_t n) const noexcept
{
return rows_iterator(obj_, row_num_ + n);
}
rows_iterator operator-(std::ptrdiff_t n) const noexcept
{
return rows_iterator(obj_, row_num_ - n);
}
std::ptrdiff_t operator-(rows_iterator rhs) const noexcept { return row_num_ - rhs.row_num_; }
pointer operator->() const noexcept { return **this; }
@@ -61,10 +94,8 @@ rows_iterator<RowsType> operator+(std::ptrdiff_t n, rows_iterator<RowsType> it)
return it + n;
}
}
}
}
} // namespace detail
} // namespace mysql
} // namespace boost
#endif

View File

@@ -10,8 +10,9 @@
// A very simplified variable-length string with fixed max-size
#include <array>
#include <boost/utility/string_view.hpp>
#include <array>
#include <cassert>
#include <cstring>
#include <ostream>
@@ -25,8 +26,9 @@ class static_string
{
std::array<char, max_size> buffer_;
std::size_t size_;
public:
static_string() noexcept: size_(0) {}
static_string() noexcept : size_(0) {}
static_string(boost::string_view value) noexcept : size_(value.size())
{
assert(value.size() <= max_size);
@@ -59,10 +61,8 @@ std::ostream& operator<<(std::ostream& os, const static_string<max_size>& value)
return os << value.value();
}
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_AUXILIAR_STATIC_STRING_HPP_ */

View File

@@ -10,6 +10,7 @@
#include <boost/utility/string_view.hpp>
#include <boost/utility/string_view_fwd.hpp>
#include <cstddef>
#include <cstdint>
@@ -23,10 +24,13 @@ class string_view_offset
{
std::size_t offset_;
std::size_t size_;
public:
constexpr string_view_offset() noexcept : offset_(0), size_(0) {}
constexpr string_view_offset(std::size_t offset, std::size_t size) noexcept :
offset_(offset), size_(size) {}
constexpr string_view_offset(std::size_t offset, std::size_t size) noexcept
: offset_(offset), size_(size)
{
}
constexpr std::size_t offset() const noexcept { return offset_; }
constexpr std::size_t size() const noexcept { return size_; }
constexpr bool operator==(string_view_offset rhs) const noexcept
@@ -35,15 +39,18 @@ public:
}
constexpr bool operator!=(string_view_offset rhs) const noexcept { return !(*this == rhs); }
static string_view_offset from_sv(boost::string_view from, const std::uint8_t* buffer_first) noexcept
static string_view_offset
from_sv(boost::string_view from, const std::uint8_t* buffer_first) noexcept
{
return string_view_offset(from.data() - reinterpret_cast<const char*>(buffer_first), from.size());
return string_view_offset(
from.data() - reinterpret_cast<const char*>(buffer_first),
from.size()
);
}
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#endif

View File

@@ -8,8 +8,8 @@
#ifndef BOOST_MYSQL_DETAIL_AUXILIAR_STRINGIZE_HPP
#define BOOST_MYSQL_DETAIL_AUXILIAR_STRINGIZE_HPP
#include <string>
#include <sstream>
#include <string>
namespace boost {
namespace mysql {
@@ -32,10 +32,8 @@ std::string stringize(const Types&... inputs)
return ss.str();
}
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_AUXILIAR_STRINGIZE_HPP_ */

View File

@@ -20,10 +20,7 @@ namespace detail {
#ifdef BOOST_MYSQL_VALGRIND_TESTS
inline void valgrind_make_mem_defined(
const void* data,
std::size_t size
)
inline void valgrind_make_mem_defined(const void* data, std::size_t size)
{
VALGRIND_MAKE_MEM_DEFINED(data, size);
}
@@ -34,14 +31,8 @@ inline void valgrind_make_mem_defined(const void*, std::size_t) noexcept {}
#endif
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_AUXILIAR_VALGRIND_HPP_ */

View File

@@ -16,8 +16,7 @@ template <typename...>
using void_t = void;
}
}
}
} // namespace mysql
} // namespace boost
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_PROTOCOL_IMPL_SERIALIZATION_HPP_ */

View File

@@ -8,15 +8,17 @@
#ifndef BOOST_MYSQL_DETAIL_CHANNEL_CHANNEL_HPP
#define BOOST_MYSQL_DETAIL_CHANNEL_CHANNEL_HPP
#include <boost/asio/async_result.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/mysql/error.hpp>
#include <boost/mysql/field_view.hpp>
#include <boost/mysql/detail/auxiliar/bytestring.hpp>
#include <boost/mysql/detail/protocol/capabilities.hpp>
#include <boost/mysql/detail/channel/disableable_ssl_stream.hpp>
#include <boost/mysql/detail/channel/message_reader.hpp>
#include <boost/mysql/detail/channel/message_writer.hpp>
#include <boost/mysql/detail/protocol/capabilities.hpp>
#include <boost/mysql/error.hpp>
#include <boost/mysql/field_view.hpp>
#include <boost/asio/async_result.hpp>
#include <boost/asio/buffer.hpp>
#include <cstddef>
#include <utility>
#include <vector>
@@ -25,7 +27,6 @@ namespace boost {
namespace mysql {
namespace detail {
// Implements the message layer of the MySQL protocol
template <class Stream>
class channel
@@ -35,16 +36,15 @@ class channel
message_reader reader_;
message_writer writer_;
std::uint8_t shared_sequence_number_ {}; // for async ops
bytestring shared_buff_; // for async ops
error_info shared_info_; // for async ops
std::vector<field_view> shared_fields_; // for read_some ops
std::uint8_t shared_sequence_number_{}; // for async ops
bytestring shared_buff_; // for async ops
error_info shared_info_; // for async ops
std::vector<field_view> shared_fields_; // for read_some ops
public:
// TODO: use this arg
template <class... Args>
channel(std::size_t read_buffer_size, Args&&... args) :
stream_(std::forward<Args>(args)...),
reader_(read_buffer_size)
channel(std::size_t read_buffer_size, Args&&... args)
: stream_(std::forward<Args>(args)...), reader_(read_buffer_size)
{
}
@@ -65,27 +65,30 @@ public:
return reader_.read_some(stream_, code, keep_messages);
}
template<
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) CompletionToken
>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
async_read_some(CompletionToken&& token, bool keep_messages = false)
{
return reader_.async_read_some(stream_, std::forward<CompletionToken>(token), keep_messages);
return reader_
.async_read_some(stream_, std::forward<CompletionToken>(token), keep_messages);
}
boost::asio::const_buffer read_one(std::uint8_t& seqnum, error_code& ec, bool keep_messages = false)
boost::asio::const_buffer
read_one(std::uint8_t& seqnum, error_code& ec, bool keep_messages = false)
{
return reader_.read_one(stream_, seqnum, ec, keep_messages);
}
template<
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code, ::boost::asio::const_buffer)) CompletionToken
>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, ::boost::asio::const_buffer))
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code, ::boost::asio::const_buffer))
CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
CompletionToken,
void(error_code, ::boost::asio::const_buffer)
)
async_read_one(std::uint8_t& seqnum, CompletionToken&& token, bool keep_messages = false)
{
return reader_.async_read_one(stream_, seqnum, std::forward<CompletionToken>(token), keep_messages);
return reader_
.async_read_one(stream_, seqnum, std::forward<CompletionToken>(token), keep_messages);
}
// Writing
@@ -94,24 +97,19 @@ public:
writer_.write(stream_, buffer, seqnum, code);
}
template<
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) CompletionToken
>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
async_write(boost::asio::const_buffer buffer, std::uint8_t& seqnum, CompletionToken&& token)
{
return writer_.async_write(stream_, buffer, seqnum, std::forward<CompletionToken>(token));
}
void write(const bytestring& buffer, std::uint8_t& seqnum, error_code& code)
{
write(boost::asio::buffer(buffer), seqnum, code);
}
template<
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) CompletionToken
>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
async_write(const bytestring& buffer, CompletionToken&& token)
{
@@ -152,8 +150,8 @@ public:
const std::vector<field_view>& shared_fields() const noexcept { return shared_fields_; }
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#endif

View File

@@ -9,7 +9,9 @@
#define BOOST_MYSQL_DETAIL_CHANNEL_DISABLEABLE_SSL_STREAM_HPP
#include <boost/mysql/error.hpp>
#include <boost/asio/async_result.hpp>
#include <cstddef>
namespace boost {
@@ -24,19 +26,18 @@ class disableable_ssl_stream
{
public:
template <class... Args>
disableable_ssl_stream(Args&&... args) noexcept :
inner_stream_(std::forward<Args>(args)...)
disableable_ssl_stream(Args&&... args) noexcept : inner_stream_(std::forward<Args>(args)...)
{
}
void reset() noexcept { set_ssl_active(false); } // TODO: do we really need this?
void reset() noexcept { set_ssl_active(false); } // TODO: do we really need this?
bool ssl_active() const noexcept { return ssl_active_; }
void set_ssl_active(bool v) noexcept { ssl_active_ = v; }
using executor_type = typename Stream::executor_type;
using next_layer_type = Stream;
using lowest_layer_type = typename Stream::lowest_layer_type;
executor_type get_executor() noexcept { return inner_stream_.get_executor(); }
next_layer_type& next_layer() noexcept { return inner_stream_; }
const next_layer_type& next_layer() const noexcept { return inner_stream_; }
@@ -44,59 +45,43 @@ public:
void handshake(error_code& ec);
template<
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) CompletionToken
>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(error_code))
async_handshake(CompletionToken&& token);
void shutdown(error_code& ec);
template<
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) CompletionToken
>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(error_code))
async_shutdown(CompletionToken&& token);
template <class MutableBufferSequence>
std::size_t read_some(const MutableBufferSequence&, error_code& ec);
template<
template <
class MutableBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code, std::size_t)) CompletionToken
>
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code, std::size_t)) CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(error_code, std::size_t))
async_read_some(
const MutableBufferSequence& buff,
CompletionToken&& token
);
async_read_some(const MutableBufferSequence& buff, CompletionToken&& token);
template<class ConstBufferSequence>
template <class ConstBufferSequence>
std::size_t write_some(const ConstBufferSequence&, error_code& ec);
template<
template <
class ConstBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code, std::size_t)) CompletionToken
>
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code, std::size_t)) CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(error_code, std::size_t))
async_write_some(
const ConstBufferSequence& buff,
CompletionToken&& token
);
async_write_some(const ConstBufferSequence& buff, CompletionToken&& token);
private:
Stream inner_stream_;
bool ssl_active_ {false};
bool ssl_active_{false};
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/channel/impl/disableable_ssl_stream.hpp>
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_AUXILIAR_STATIC_STRING_HPP_ */

View File

@@ -12,10 +12,12 @@
#include <boost/mysql/detail/channel/disableable_ssl_stream.hpp>
#include <boost/mysql/error.hpp>
#include <boost/asio/async_result.hpp>
#include <boost/asio/compose.hpp>
#include <boost/asio/coroutine.hpp>
#include <boost/asio/async_result.hpp>
#include <boost/asio/ssl/stream_base.hpp>
#include <cstddef>
#include <utility>
@@ -26,7 +28,6 @@ namespace detail {
template <class Stream>
using is_ssl_stream = std::is_base_of<boost::asio::ssl::stream_base, Stream>;
// Helpers to get the first non-SSL stream. We can't call just next_layer()
// because raw TCP sockets don't support this function. For non-SSL connections,
// we just return the stream itself
@@ -54,7 +55,8 @@ struct get_non_ssl_stream_t<false>
};
template <typename Stream>
auto get_non_ssl_stream(Stream& s) -> decltype(get_non_ssl_stream_t<is_ssl_stream<Stream>::value>::call(s))
auto get_non_ssl_stream(Stream& s)
-> decltype(get_non_ssl_stream_t<is_ssl_stream<Stream>::value>::call(s))
{
return get_non_ssl_stream_t<is_ssl_stream<Stream>::value>::call(s);
}
@@ -64,7 +66,7 @@ struct async_compose_noop
{
async_compose_noop(...) noexcept {}
template<class... Args>
template <class... Args>
void operator()(Args&&...)
{
assert(false);
@@ -91,7 +93,7 @@ struct ssl_handshake_helper<Stream, false>
{
static void call(disableable_ssl_stream<Stream>&, error_code&)
{
assert(false); // should never be called
assert(false); // should never be called
}
};
@@ -103,16 +105,10 @@ struct ssl_handshake_op<Stream, true> : boost::asio::coroutine
{
disableable_ssl_stream<Stream>& stream_;
ssl_handshake_op(disableable_ssl_stream<Stream>& stream) noexcept :
stream_(stream)
{
}
ssl_handshake_op(disableable_ssl_stream<Stream>& stream) noexcept : stream_(stream) {}
template<class Self>
void operator()(
Self& self,
error_code err = {}
)
template <class Self>
void operator()(Self& self, error_code err = {})
{
// Error checking
if (err)
@@ -125,7 +121,7 @@ struct ssl_handshake_op<Stream, true> : boost::asio::coroutine
BOOST_ASIO_CORO_REENTER(*this)
{
BOOST_ASIO_CORO_YIELD stream_.next_layer().async_handshake(
boost::asio::ssl::stream_base::client,
boost::asio::ssl::stream_base::client,
std::move(self)
);
stream_.set_ssl_active(true);
@@ -135,8 +131,9 @@ struct ssl_handshake_op<Stream, true> : boost::asio::coroutine
};
template <class Stream>
struct ssl_handshake_op<Stream, false> : async_compose_noop {};
struct ssl_handshake_op<Stream, false> : async_compose_noop
{
};
// Helpers to implement shutdown
template <class Stream, bool supports_ssl>
@@ -150,11 +147,9 @@ struct ssl_shutdown_helper<Stream, true>
stream.next_layer().shutdown(ec);
}
template<
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) CompletionToken
>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) CompletionToken>
static BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(error_code))
call_async(disableable_ssl_stream<Stream>& stream, CompletionToken&& token)
call_async(disableable_ssl_stream<Stream>& stream, CompletionToken&& token)
{
return stream.next_layer().async_shutdown(std::forward<CompletionToken>(token));
}
@@ -165,14 +160,12 @@ struct ssl_shutdown_helper<Stream, false>
{
static void call_sync(disableable_ssl_stream<Stream>&, error_code&)
{
assert(false); // should never be called
assert(false); // should never be called
}
template<
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) CompletionToken
>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) CompletionToken>
static BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(error_code))
call_async(disableable_ssl_stream<Stream>& stream, CompletionToken&& token)
call_async(disableable_ssl_stream<Stream>& stream, CompletionToken&& token)
{
return boost::asio::async_compose<CompletionToken, void(error_code)>(
async_compose_noop(),
@@ -182,33 +175,22 @@ struct ssl_shutdown_helper<Stream, false>
}
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
template <class Stream>
void boost::mysql::detail::disableable_ssl_stream<Stream>::handshake(
error_code& ec
)
void boost::mysql::detail::disableable_ssl_stream<Stream>::handshake(error_code& ec)
{
ssl_handshake_helper<Stream, is_ssl_stream<Stream>::value>::call(*this, ec);
}
template<class Stream>
template<
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(boost::mysql::error_code)) CompletionToken
>
template <class Stream>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(boost::mysql::error_code)) CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(boost::mysql::error_code))
boost::mysql::detail::disableable_ssl_stream<Stream>::async_handshake(
CompletionToken&& token
)
boost::mysql::detail::disableable_ssl_stream<Stream>::async_handshake(CompletionToken&& token)
{
return boost::asio::async_compose<
CompletionToken,
void(error_code)
>(
return boost::asio::async_compose<CompletionToken, void(error_code)>(
ssl_handshake_op<Stream, is_ssl_stream<Stream>::value>(*this),
token,
*this
@@ -216,21 +198,15 @@ boost::mysql::detail::disableable_ssl_stream<Stream>::async_handshake(
}
template <class Stream>
void boost::mysql::detail::disableable_ssl_stream<Stream>::shutdown(
error_code& ec
)
void boost::mysql::detail::disableable_ssl_stream<Stream>::shutdown(error_code& ec)
{
ssl_shutdown_helper<Stream, is_ssl_stream<Stream>::value>::call_sync(*this, ec);
}
template<class Stream>
template<
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(boost::mysql::error_code)) CompletionToken
>
template <class Stream>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(boost::mysql::error_code)) CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(boost::mysql::error_code))
boost::mysql::detail::disableable_ssl_stream<Stream>::async_shutdown(
CompletionToken&& token
)
boost::mysql::detail::disableable_ssl_stream<Stream>::async_shutdown(CompletionToken&& token)
{
return ssl_shutdown_helper<Stream, is_ssl_stream<Stream>::value>::call_async(
*this,
@@ -238,7 +214,6 @@ boost::mysql::detail::disableable_ssl_stream<Stream>::async_shutdown(
);
}
template <class Stream>
template <class MutableBufferSequence>
std::size_t boost::mysql::detail::disableable_ssl_stream<Stream>::read_some(
@@ -256,12 +231,10 @@ std::size_t boost::mysql::detail::disableable_ssl_stream<Stream>::read_some(
}
}
template<class Stream>
template<
template <class Stream>
template <
class MutableBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(boost::mysql::error_code, std::size_t)) CompletionToken
>
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(boost::mysql::error_code, std::size_t)) CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(boost::mysql::error_code, std::size_t))
boost::mysql::detail::disableable_ssl_stream<Stream>::async_read_some(
const MutableBufferSequence& buff,
@@ -274,11 +247,11 @@ boost::mysql::detail::disableable_ssl_stream<Stream>::async_read_some(
}
else
{
return get_non_ssl_stream(inner_stream_).async_read_some(buff, std::forward<CompletionToken>(token));
return get_non_ssl_stream(inner_stream_)
.async_read_some(buff, std::forward<CompletionToken>(token));
}
}
template <class Stream>
template <class ConstBufferSequence>
std::size_t boost::mysql::detail::disableable_ssl_stream<Stream>::write_some(
@@ -296,12 +269,10 @@ std::size_t boost::mysql::detail::disableable_ssl_stream<Stream>::write_some(
}
}
template<class Stream>
template<
template <class Stream>
template <
class ConstBufferSequence,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(boost::mysql::error_code, std::size_t)) CompletionToken
>
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(boost::mysql::error_code, std::size_t)) CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(boost::mysql::error_code, std::size_t))
boost::mysql::detail::disableable_ssl_stream<Stream>::async_write_some(
const ConstBufferSequence& buff,
@@ -314,9 +285,9 @@ boost::mysql::detail::disableable_ssl_stream<Stream>::async_write_some(
}
else
{
return get_non_ssl_stream(inner_stream_).async_write_some(buff, std::forward<CompletionToken>(token));
return get_non_ssl_stream(inner_stream_)
.async_write_some(buff, std::forward<CompletionToken>(token));
}
}
#endif

View File

@@ -11,18 +11,17 @@
#pragma once
#include <boost/mysql/detail/channel/message_parser.hpp>
#include <boost/mysql/detail/protocol/constants.hpp>
#include <boost/mysql/detail/protocol/common_messages.hpp>
#include <boost/mysql/detail/protocol/constants.hpp>
#include <boost/mysql/detail/protocol/deserialization_context.hpp>
#include <boost/core/ignore_unused.hpp>
#include <cstddef>
inline void boost::mysql::detail::message_parser::parse_message(
read_buffer& buff,
result& res
) noexcept
inline void
boost::mysql::detail::message_parser::parse_message(read_buffer& buff, result& res) noexcept
{
while (true)
{
if (state_.reading_header)
@@ -39,9 +38,9 @@ inline void boost::mysql::detail::message_parser::parse_message(
// Deserialize the header
packet_header header;
deserialization_context ctx (
deserialization_context ctx(
boost::asio::buffer(buff.pending_first() - HEADER_SIZE, HEADER_SIZE),
capabilities(0) // unaffected by capabilities
capabilities(0) // unaffected by capabilities
);
errc err = deserialize(ctx, header);
boost::ignore_unused(err);

View File

@@ -10,14 +10,14 @@
#pragma once
#include <boost/mysql/detail/channel/message_reader.hpp>
#include <boost/mysql/detail/auxiliar/valgrind.hpp>
#include <boost/mysql/detail/channel/message_reader.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/compose.hpp>
#include <boost/asio/coroutine.hpp>
#include <boost/asio/post.hpp>
boost::asio::const_buffer boost::mysql::detail::message_reader::get_next_message(
std::uint8_t& seqnum,
error_code& ec
@@ -30,7 +30,10 @@ boost::asio::const_buffer boost::mysql::detail::message_reader::get_next_message
return {};
}
seqnum = result_.message.seqnum_last + 1;
boost::asio::const_buffer res (buffer_.current_message_first() - result_.message.size, result_.message.size);
boost::asio::const_buffer res(
buffer_.current_message_first() - result_.message.size,
result_.message.size
);
parse_message();
return res;
}
@@ -45,7 +48,7 @@ void boost::mysql::detail::message_reader::read_some(
// If we already have a message, complete immediately
if (has_message())
return;
// Remove processed messages if we can
if (!keep_messages)
buffer_.remove_reserved();
@@ -58,7 +61,8 @@ void boost::mysql::detail::message_reader::read_some(
// Actually read bytes
std::size_t bytes_read = stream.read_some(buffer_.free_area(), ec);
if (ec) break;
if (ec)
break;
valgrind_make_mem_defined(buffer_.free_first(), bytes_read);
// Process them
@@ -73,15 +77,13 @@ struct boost::mysql::detail::message_reader::read_some_op : boost::asio::corouti
bool keep_messages_;
Stream& stream_;
read_some_op(message_reader& reader, bool keep_messages, Stream& stream) noexcept :
reader_(reader), keep_messages_(keep_messages), stream_(stream) {}
read_some_op(message_reader& reader, bool keep_messages, Stream& stream) noexcept
: reader_(reader), keep_messages_(keep_messages), stream_(stream)
{
}
template<class Self>
void operator()(
Self& self,
error_code ec = {},
std::size_t bytes_read = 0
)
template <class Self>
void operator()(Self& self, error_code ec = {}, std::size_t bytes_read = 0)
{
// Error handling
if (ec)
@@ -90,7 +92,6 @@ struct boost::mysql::detail::message_reader::read_some_op : boost::asio::corouti
return;
}
// Non-error path
BOOST_ASIO_CORO_REENTER(*this)
{
@@ -115,7 +116,7 @@ struct boost::mysql::detail::message_reader::read_some_op : boost::asio::corouti
// Actually read bytes
BOOST_ASIO_CORO_YIELD stream_.async_read_some(
reader_.buffer_.free_area(),
std::move(self)
std::move(self)
);
valgrind_make_mem_defined(reader_.buffer_.free_first(), bytes_read);
@@ -128,10 +129,9 @@ struct boost::mysql::detail::message_reader::read_some_op : boost::asio::corouti
}
};
template<
template <
class Stream,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(boost::mysql::error_code)) CompletionToken
>
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(boost::mysql::error_code)) CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(::boost::mysql::error_code))
boost::mysql::detail::message_reader::async_read_some(
Stream& stream,
@@ -161,34 +161,21 @@ boost::asio::const_buffer boost::mysql::detail::message_reader::read_one(
return get_next_message(seqnum, ec);
}
template<class Stream>
struct boost::mysql::detail::message_reader::read_one_op
: boost::asio::coroutine
template <class Stream>
struct boost::mysql::detail::message_reader::read_one_op : boost::asio::coroutine
{
message_reader& reader_;
bool keep_messages_;
Stream& stream_;
std::uint8_t& seqnum_;
read_one_op(
message_reader& reader,
bool keep_messages,
Stream& stream,
std::uint8_t& seqnum
) :
reader_(reader),
keep_messages_(keep_messages),
stream_(stream),
seqnum_(seqnum)
read_one_op(message_reader& reader, bool keep_messages, Stream& stream, std::uint8_t& seqnum)
: reader_(reader), keep_messages_(keep_messages), stream_(stream), seqnum_(seqnum)
{
}
template<class Self>
void operator()(
Self& self,
error_code code = {}
)
template <class Self>
void operator()(Self& self, error_code code = {})
{
// Error handling
if (code)
@@ -208,10 +195,10 @@ struct boost::mysql::detail::message_reader::read_one_op
}
};
template<
template <
class Stream,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(boost::mysql::error_code, boost::asio::const_buffer)) CompletionToken
>
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(boost::mysql::error_code, boost::asio::const_buffer))
CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
CompletionToken,
void(boost::mysql::error_code, ::boost::asio::const_buffer)

View File

@@ -11,6 +11,7 @@
#pragma once
#include <boost/mysql/detail/channel/message_writer.hpp>
#include <boost/asio/compose.hpp>
#include <boost/asio/coroutine.hpp>
@@ -33,25 +34,19 @@ void boost::mysql::detail::message_writer::write(
} while (!processor_.is_complete());
}
template <class Stream>
struct boost::mysql::detail::message_writer::write_op : boost::asio::coroutine
{
Stream& stream_;
message_writer_processor& processor_;
write_op(Stream& stream, message_writer_processor& processor) noexcept :
stream_(stream),
processor_(processor)
write_op(Stream& stream, message_writer_processor& processor) noexcept
: stream_(stream), processor_(processor)
{
}
template<class Self>
void operator()(
Self& self,
error_code ec = {},
std::size_t = 0
)
template <class Self>
void operator()(Self& self, error_code ec = {}, std::size_t = 0)
{
// Error handling
if (ec)
@@ -60,7 +55,6 @@ struct boost::mysql::detail::message_writer::write_op : boost::asio::coroutine
return;
}
// Non-error path
BOOST_ASIO_CORO_REENTER(*this)
{
@@ -81,10 +75,9 @@ struct boost::mysql::detail::message_writer::write_op : boost::asio::coroutine
}
};
template<
template <
class Stream,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(boost::mysql::error_code)) CompletionToken
>
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(boost::mysql::error_code)) CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(::boost::mysql::error_code))
boost::mysql::detail::message_writer::async_write(
Stream& stream,
@@ -101,5 +94,4 @@ boost::mysql::detail::message_writer::async_write(
);
}
#endif

View File

@@ -11,52 +11,37 @@
#pragma once
#include <boost/mysql/detail/channel/read_buffer.hpp>
#include <cassert>
#include <cstring>
boost::mysql::detail::read_buffer::read_buffer(
std::size_t size
) :
buffer_(size, std::uint8_t(0))
boost::mysql::detail::read_buffer::read_buffer(std::size_t size) : buffer_(size, std::uint8_t(0))
{
buffer_.resize(buffer_.capacity());
}
void boost::mysql::detail::read_buffer::move_to_reserved(
std::size_t length
) noexcept
void boost::mysql::detail::read_buffer::move_to_reserved(std::size_t length) noexcept
{
assert(length <= current_message_size());
current_message_offset_ += length;
}
void boost::mysql::detail::read_buffer::remove_current_message_last(
std::size_t length
) noexcept
void boost::mysql::detail::read_buffer::remove_current_message_last(std::size_t length) noexcept
{
assert(length <= current_message_size());
assert(length > 0);
std::memmove(
pending_first() - length,
pending_first(),
pending_size()
);
std::memmove(pending_first() - length, pending_first(), pending_size());
pending_offset_ -= length;
free_offset_ -= length;
}
void boost::mysql::detail::read_buffer::move_to_current_message(
std::size_t n
) noexcept
void boost::mysql::detail::read_buffer::move_to_current_message(std::size_t n) noexcept
{
assert(n <= pending_size());
pending_offset_ += n;
}
void boost::mysql::detail::read_buffer::move_to_pending(
std::size_t n
) noexcept
void boost::mysql::detail::read_buffer::move_to_pending(std::size_t n) noexcept
{
assert(n <= free_size());
free_offset_ += n;
@@ -68,11 +53,7 @@ void boost::mysql::detail::read_buffer::remove_reserved() noexcept
{
std::size_t currmsg_size = current_message_size();
std::size_t pend_size = pending_size();
std::memmove(
buffer_.data(),
current_message_first(),
currmsg_size + pend_size
);
std::memmove(buffer_.data(), current_message_first(), currmsg_size + pend_size);
current_message_offset_ = 0;
pending_offset_ = currmsg_size;
free_offset_ = currmsg_size + pend_size;
@@ -88,5 +69,4 @@ void boost::mysql::detail::read_buffer::grow_to_fit(std::size_t n)
}
}
#endif

View File

@@ -8,43 +8,46 @@
#ifndef BOOST_MYSQL_DETAIL_CHANNEL_MESSAGE_PARSER_HPP
#define BOOST_MYSQL_DETAIL_CHANNEL_MESSAGE_PARSER_HPP
#include <cstddef>
#include <cstdint>
#include <boost/mysql/detail/channel/read_buffer.hpp>
#include <boost/mysql/detail/protocol/constants.hpp>
#include <cstddef>
#include <cstdint>
namespace boost {
namespace mysql {
namespace detail {
class message_parser
{
struct state_t
{
bool is_first_frame {true};
std::uint8_t seqnum_first {};
std::uint8_t seqnum_last {};
bool reading_header {true};
std::size_t remaining_bytes {0};
bool more_frames_follow {false};
bool has_seqnum_mismatch {false};
bool is_first_frame{true};
std::uint8_t seqnum_first{};
std::uint8_t seqnum_last{};
bool reading_header{true};
std::size_t remaining_bytes{0};
bool more_frames_follow{false};
bool has_seqnum_mismatch{false};
};
std::size_t max_frame_size_;
state_t state_;
public:
struct result
{
bool has_message {false}; // whether it has a message or not
std::size_t required_size {0}; // if !has_message, number of bytes required to parse the current message
bool has_message{false}; // whether it has a message or not
std::size_t required_size{
0}; // if !has_message, number of bytes required to parse the current message
struct message_t
{
std::uint8_t seqnum_first;
std::uint8_t seqnum_last;
std::size_t size;
bool has_seqnum_mismatch; // for multi-frame messages, set to true if an error mismatch happened
} message {}; // if has_message, the actual parsed message
bool has_seqnum_mismatch; // for multi-frame messages, set to true if an error mismatch
// happened
} message{}; // if has_message, the actual parsed message
void set_required_size(std::size_t size) noexcept
{
@@ -60,7 +63,8 @@ public:
};
// max_frame_size is configurable so tests run faster
message_parser(std::size_t max_frame_size = MAX_PACKET_SIZE) noexcept : max_frame_size_(max_frame_size) {};
message_parser(std::size_t max_frame_size = MAX_PACKET_SIZE) noexcept
: max_frame_size_(max_frame_size){};
// Attempts to process a message from buff and puts it into msg.
// If a message is read, returns true, and msg.message_first and msg.message_last
@@ -71,11 +75,9 @@ public:
inline void parse_message(read_buffer& buff, result& res) noexcept;
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/channel/impl/message_parser.ipp>

View File

@@ -8,16 +8,17 @@
#ifndef BOOST_MYSQL_DETAIL_CHANNEL_MESSAGE_READER_HPP
#define BOOST_MYSQL_DETAIL_CHANNEL_MESSAGE_READER_HPP
#include <boost/mysql/error.hpp>
#include <boost/mysql/detail/channel/read_buffer.hpp>
#include <boost/mysql/detail/channel/message_parser.hpp>
#include <boost/mysql/detail/channel/read_buffer.hpp>
#include <boost/mysql/detail/protocol/constants.hpp>
#include <boost/mysql/error.hpp>
#include <boost/asio/async_result.hpp>
#include <cassert>
#include <cstddef>
#include <cstdint>
namespace boost {
namespace mysql {
namespace detail {
@@ -25,13 +26,16 @@ namespace detail {
class message_reader
{
public:
message_reader(std::size_t initial_buffer_size, std::size_t max_frame_size = MAX_PACKET_SIZE)
: buffer_(initial_buffer_size), parser_(max_frame_size) {}
message_reader(std::size_t initial_buffer_size, std::size_t max_frame_size = MAX_PACKET_SIZE)
: buffer_(initial_buffer_size), parser_(max_frame_size)
{
}
bool has_message() const noexcept { return result_.has_message; }
const std::uint8_t* buffer_first() const noexcept { return buffer_.first(); }
inline boost::asio::const_buffer get_next_message(std::uint8_t& seqnum, error_code& ec) noexcept;
inline boost::asio::const_buffer
get_next_message(std::uint8_t& seqnum, error_code& ec) noexcept;
// Reads some messages from stream, until there is at least one
// or an error happens. On success, has_message() returns true
@@ -42,26 +46,19 @@ public:
template <class Stream>
void read_some(Stream& stream, error_code& ec, bool keep_messages = false);
template<
class Stream,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) CompletionToken
>
template <class Stream, BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
async_read_some(Stream& stream, CompletionToken&& token, bool keep_messages = false);
// Equivalent to read_some + get_next_message
template <class Stream>
boost::asio::const_buffer read_one(
Stream& stream,
std::uint8_t& seqnum,
error_code& ec,
bool keep_messages = false
);
boost::asio::const_buffer
read_one(Stream& stream, std::uint8_t& seqnum, error_code& ec, bool keep_messages = false);
template<
template <
class Stream,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code, boost::asio::const_buffer)) CompletionToken
>
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code, boost::asio::const_buffer))
CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
async_read_one(
Stream& stream,
@@ -72,10 +69,12 @@ public:
// Exposed for the sake of testing
read_buffer& buffer() noexcept { return buffer_; }
private:
template <class Stream> struct read_some_op;
template <class Stream> struct read_one_op;
private:
template <class Stream>
struct read_some_op;
template <class Stream>
struct read_one_op;
read_buffer buffer_;
message_parser parser_;
@@ -87,15 +86,10 @@ private:
inline void on_read_bytes(size_t num_bytes);
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/channel/impl/message_reader.hpp>
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_AUXILIAR_STATIC_STRING_HPP_ */

View File

@@ -8,43 +8,42 @@
#ifndef BOOST_MYSQL_DETAIL_CHANNEL_MESSAGE_WRITER_HPP
#define BOOST_MYSQL_DETAIL_CHANNEL_MESSAGE_WRITER_HPP
#include <boost/asio/buffer.hpp>
#include <boost/asio/async_result.hpp>
#include <boost/asio/write.hpp>
#include <boost/mysql/error.hpp>
#include <boost/mysql/detail/protocol/constants.hpp>
#include <boost/mysql/detail/channel/message_writer_processor.hpp>
#include <cstddef>
#include <boost/mysql/detail/protocol/constants.hpp>
#include <boost/mysql/error.hpp>
#include <boost/asio/async_result.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/write.hpp>
#include <array>
#include <cstddef>
#include <cstdint>
namespace boost {
namespace mysql {
namespace detail {
class message_writer
{
message_writer_processor processor_;
template <class Stream> struct write_op;
template <class Stream>
struct write_op;
public:
message_writer(std::size_t max_frame_size = MAX_PACKET_SIZE) noexcept : processor_(max_frame_size) {}
message_writer(std::size_t max_frame_size = MAX_PACKET_SIZE) noexcept
: processor_(max_frame_size)
{
}
// Writes an entire message to stream; partitions the message into
// chunks and adds the required headers
template <class Stream>
void write(
Stream& stream,
boost::asio::const_buffer buffer,
std::uint8_t& seqnum,
error_code& ec
);
void
write(Stream& stream, boost::asio::const_buffer buffer, std::uint8_t& seqnum, error_code& ec);
template<
class Stream,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) CompletionToken
>
template <class Stream, BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code)) CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
async_write(
Stream& stream,
@@ -54,10 +53,9 @@ public:
);
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/channel/impl/message_writer.hpp>

View File

@@ -10,7 +10,9 @@
#include <boost/mysql/detail/protocol/common_messages.hpp>
#include <boost/mysql/detail/protocol/constants.hpp>
#include <boost/asio/buffer.hpp>
#include <array>
#include <cstddef>
#include <cstdint>
@@ -19,59 +21,62 @@ namespace boost {
namespace mysql {
namespace detail {
class message_writer_processor
{
boost::asio::const_buffer buffer_to_write_;
std::uint8_t* seqnum_ {nullptr};
std::size_t bytes_written_ {0};
std::array<std::uint8_t, HEADER_SIZE> header_buffer_ {};
bool send_empty_frame_ {false}; // Should we send a last, empty frame? (for empty messages or messages of max_frame_size_)
std::uint8_t* seqnum_{nullptr};
std::size_t bytes_written_{0};
std::array<std::uint8_t, HEADER_SIZE> header_buffer_{};
bool send_empty_frame_{false}; // Should we send a last, empty frame? (for empty messages or
// messages of max_frame_size_)
std::size_t max_frame_size_;
inline std::uint32_t compute_size_to_write() const
{
return static_cast<std::uint32_t>(std::min(
max_frame_size_,
buffer_to_write_.size() - bytes_written_
));
return static_cast<std::uint32_t>(
std::min(max_frame_size_, buffer_to_write_.size() - bytes_written_)
);
}
inline void process_header_write(
std::uint32_t size_to_write,
std::uint8_t seqnum
)
inline void process_header_write(std::uint32_t size_to_write, std::uint8_t seqnum)
{
packet_header header;
header.packet_size.value = size_to_write;
header.sequence_number = seqnum;
serialization_context ctx (capabilities(0), header_buffer_.data()); // capabilities not relevant here
serialization_context ctx(
capabilities(0),
header_buffer_.data()
); // capabilities not relevant here
serialize(ctx, header);
}
public:
// We write two buffers at once: the header and the body part
using buffers_type = std::array<boost::asio::const_buffer, 2>;
message_writer_processor(std::size_t max_frame_size = MAX_PACKET_SIZE) noexcept :
max_frame_size_(max_frame_size) {}
message_writer_processor(std::size_t max_frame_size = MAX_PACKET_SIZE) noexcept
: max_frame_size_(max_frame_size)
{
}
void reset(boost::asio::const_buffer buffer, std::uint8_t& seqnum)
{
buffer_to_write_ = buffer;
seqnum_ = &seqnum;
bytes_written_ = 0;
send_empty_frame_ = (buffer.size() == 0); // If the packet is empty, we should just send the header
send_empty_frame_ =
(buffer.size() == 0); // If the packet is empty, we should just send the header
}
buffers_type prepare_next_chunk() noexcept
{
auto first = static_cast<const std::uint8_t*>(buffer_to_write_.data());
std::size_t size_to_write = compute_size_to_write();
process_header_write(size_to_write, (*seqnum_)++);
return {{
boost::asio::buffer(header_buffer_),
boost::asio::buffer(first + bytes_written_, size_to_write)
}};
return {
{boost::asio::buffer(header_buffer_),
boost::asio::buffer(first + bytes_written_, size_to_write)}
};
}
void on_bytes_written() noexcept
@@ -80,14 +85,18 @@ public:
bytes_written_ += new_bytes;
// If we sent all the bytes, but the last frame was just max_frame_size_ bytes, the protocol
// requires us to send a last, empty frame
send_empty_frame_ = (new_bytes == max_frame_size_ && bytes_written_ == buffer_to_write_.size());
send_empty_frame_ =
(new_bytes == max_frame_size_ && bytes_written_ == buffer_to_write_.size());
}
bool is_complete() const noexcept { return !send_empty_frame_ && bytes_written_ >= buffer_to_write_.size(); }
bool is_complete() const noexcept
{
return !send_empty_frame_ && bytes_written_ >= buffer_to_write_.size();
}
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#endif

View File

@@ -8,17 +8,17 @@
#ifndef BOOST_MYSQL_DETAIL_CHANNEL_READ_BUFFER_HPP
#define BOOST_MYSQL_DETAIL_CHANNEL_READ_BUFFER_HPP
#include <boost/asio/buffer.hpp>
#include <boost/mysql/detail/auxiliar/bytestring.hpp>
#include <boost/asio/buffer.hpp>
#include <cstddef>
#include <cstdint>
namespace boost {
namespace mysql {
namespace detail {
// Custom buffer type optimized for read operations performed in the MySQL protocol.
// The buffer is a single, resizable chunk of memory with four areas:
// - Reserved area: messages that have already been read but are kept alive,
@@ -29,9 +29,10 @@ namespace detail {
class read_buffer
{
bytestring buffer_;
std::size_t current_message_offset_ {0};
std::size_t pending_offset_ {0};
std::size_t free_offset_ {0};
std::size_t current_message_offset_{0};
std::size_t pending_offset_{0};
std::size_t free_offset_{0};
public:
inline read_buffer(std::size_t size);
@@ -42,22 +43,43 @@ public:
// Area accessors
std::uint8_t* reserved_first() noexcept { return buffer_.data(); }
const std::uint8_t* reserved_first() const noexcept { return buffer_.data(); }
std::uint8_t* current_message_first() noexcept { return buffer_.data() + current_message_offset_; }
const std::uint8_t* current_message_first() const noexcept { return buffer_.data() + current_message_offset_; }
std::uint8_t* current_message_first() noexcept
{
return buffer_.data() + current_message_offset_;
}
const std::uint8_t* current_message_first() const noexcept
{
return buffer_.data() + current_message_offset_;
}
std::uint8_t* pending_first() noexcept { return buffer_.data() + pending_offset_; }
const std::uint8_t* pending_first() const noexcept { return buffer_.data() + pending_offset_; }
std::uint8_t* free_first() noexcept { return buffer_.data() + free_offset_; }
const std::uint8_t* free_first() const noexcept { return buffer_.data() + free_offset_; }
std::size_t reserved_size() const noexcept { return current_message_offset_; }
std::size_t current_message_size() const noexcept { return pending_offset_ - current_message_offset_; }
std::size_t current_message_size() const noexcept
{
return pending_offset_ - current_message_offset_;
}
std::size_t pending_size() const noexcept { return free_offset_ - pending_offset_; }
std::size_t free_size() const noexcept { return buffer_.size() - free_offset_; }
boost::asio::const_buffer reserved_area() const noexcept { return boost::asio::buffer(reserved_first(), reserved_size()); }
boost::asio::const_buffer current_message() const noexcept { return boost::asio::buffer(current_message_first(), current_message_size()); }
boost::asio::const_buffer pending_area() const noexcept { return boost::asio::buffer(pending_first(), pending_size()); }
boost::asio::mutable_buffer free_area() noexcept { return boost::asio::buffer(free_first(), free_size()); }
boost::asio::const_buffer reserved_area() const noexcept
{
return boost::asio::buffer(reserved_first(), reserved_size());
}
boost::asio::const_buffer current_message() const noexcept
{
return boost::asio::buffer(current_message_first(), current_message_size());
}
boost::asio::const_buffer pending_area() const noexcept
{
return boost::asio::buffer(pending_first(), pending_size());
}
boost::asio::mutable_buffer free_area() noexcept
{
return boost::asio::buffer(free_first(), free_size());
}
// Moves n bytes from the free to the processing area (e.g. they've been read)
inline void move_to_pending(std::size_t n) noexcept;
@@ -81,17 +103,10 @@ public:
inline void grow_to_fit(std::size_t n);
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/channel/impl/read_buffer.ipp>
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_AUXILIAR_STATIC_STRING_HPP_ */

View File

@@ -8,34 +8,24 @@
#ifndef BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_CLOSE_CONNECTION_HPP
#define BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_CLOSE_CONNECTION_HPP
#include <boost/mysql/error.hpp>
#include <boost/mysql/detail/channel/channel.hpp>
#include <boost/mysql/error.hpp>
namespace boost {
namespace mysql {
namespace detail {
template <class SocketStream>
void close_connection(
channel<SocketStream>& chan,
error_code& code,
error_info& info
);
void close_connection(channel<SocketStream>& chan, error_code& code, error_info& info);
template <class SocketStream, class CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
async_close_connection(
channel<SocketStream>& chan,
CompletionToken&& token,
error_info& info
);
async_close_connection(channel<SocketStream>& chan, CompletionToken&& token, error_info& info);
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/network_algorithms/impl/close_connection.hpp>
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_CLOSE_CONNECTION_HPP_ */

View File

@@ -8,8 +8,8 @@
#ifndef BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_CLOSE_STATEMENT_HPP
#define BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_CLOSE_STATEMENT_HPP
#include <boost/mysql/error.hpp>
#include <boost/mysql/detail/channel/channel.hpp>
#include <boost/mysql/error.hpp>
#include <boost/mysql/statement_base.hpp>
namespace boost {
@@ -33,9 +33,9 @@ async_close_statement(
error_info& info
);
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/network_algorithms/impl/close_statement.hpp>

View File

@@ -8,9 +8,9 @@
#ifndef BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_CONNECT_HPP
#define BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_CONNECT_HPP
#include <boost/mysql/handshake_params.hpp>
#include <boost/mysql/error.hpp>
#include <boost/mysql/detail/channel/channel.hpp>
#include <boost/mysql/error.hpp>
#include <boost/mysql/handshake_params.hpp>
namespace boost {
namespace mysql {
@@ -35,9 +35,9 @@ async_connect(
CompletionToken&& token
);
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/network_algorithms/impl/connect.hpp>

View File

@@ -8,11 +8,10 @@
#ifndef BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_EXECUTE_GENERIC_HPP
#define BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_EXECUTE_GENERIC_HPP
#include <boost/mysql/error.hpp>
#include <boost/mysql/resultset_base.hpp>
#include <boost/mysql/detail/channel/channel.hpp>
#include <boost/mysql/detail/protocol/resultset_encoding.hpp>
#include <boost/mysql/error.hpp>
#include <boost/mysql/resultset_base.hpp>
namespace boost {
namespace mysql {
@@ -39,9 +38,9 @@ async_execute_generic(
CompletionToken&& token
);
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/network_algorithms/impl/execute_generic.hpp>

View File

@@ -8,11 +8,11 @@
#ifndef BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_EXECUTE_QUERY_HPP
#define BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_EXECUTE_QUERY_HPP
#include <boost/mysql/detail/channel/channel.hpp>
#include <boost/mysql/error.hpp>
#include <boost/mysql/resultset_base.hpp>
#include <boost/mysql/detail/channel/channel.hpp>
#include <boost/utility/string_view.hpp>
#include <boost/utility/string_view.hpp>
namespace boost {
namespace mysql {
@@ -37,9 +37,9 @@ async_execute_query(
CompletionToken&& token
);
}
}
}
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/network_algorithms/impl/execute_query.hpp>

View File

@@ -8,11 +8,11 @@
#ifndef BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_EXECUTE_STATEMENT_HPP
#define BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_EXECUTE_STATEMENT_HPP
#include <boost/mysql/error.hpp>
#include <boost/mysql/statement_base.hpp>
#include <boost/mysql/resultset_base.hpp>
#include <boost/mysql/execute_params.hpp>
#include <boost/mysql/detail/channel/channel.hpp>
#include <boost/mysql/error.hpp>
#include <boost/mysql/execute_params.hpp>
#include <boost/mysql/resultset_base.hpp>
#include <boost/mysql/statement_base.hpp>
namespace boost {
namespace mysql {
@@ -39,9 +39,9 @@ async_execute_statement(
CompletionToken&& token
);
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/network_algorithms/impl/execute_statement.hpp>

View File

@@ -8,11 +8,10 @@
#ifndef BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_HANDSHAKE_HPP
#define BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_HANDSHAKE_HPP
#include <boost/mysql/error.hpp>
#include <boost/mysql/detail/channel/channel.hpp>
#include <boost/mysql/error.hpp>
#include <boost/mysql/handshake_params.hpp>
namespace boost {
namespace mysql {
namespace detail {
@@ -34,11 +33,10 @@ async_handshake(
CompletionToken&& token
);
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/network_algorithms/impl/handshake.hpp>
#endif

View File

@@ -12,30 +12,28 @@
#include <boost/mysql/detail/network_algorithms/close_connection.hpp>
#include <boost/mysql/detail/network_algorithms/quit_connection.hpp>
#include <boost/asio/post.hpp>
#include <type_traits>
namespace boost {
namespace mysql {
namespace detail {
template<class SocketStream>
template <class SocketStream>
struct close_connection_op : boost::asio::coroutine
{
channel<SocketStream>& chan_;
error_info& output_info_;
close_connection_op(channel<SocketStream>& chan, error_info& output_info) :
chan_(chan),
output_info_(output_info)
close_connection_op(channel<SocketStream>& chan, error_info& output_info)
: chan_(chan), output_info_(output_info)
{
}
template<class Self>
void operator()(
Self& self,
error_code err = {}
)
template <class Self>
void operator()(Self& self, error_code err = {})
{
error_code close_err;
BOOST_ASIO_CORO_REENTER(*this)
@@ -47,11 +45,7 @@ struct close_connection_op : boost::asio::coroutine
BOOST_ASIO_CORO_YIELD break;
}
BOOST_ASIO_CORO_YIELD async_quit_connection(
chan_,
std::move(self),
output_info_
);
BOOST_ASIO_CORO_YIELD async_quit_connection(chan_, std::move(self), output_info_);
// We call close regardless of the quit outcome
close_err = chan_.close();
@@ -60,9 +54,9 @@ struct close_connection_op : boost::asio::coroutine
}
};
}
}
}
} // namespace detail
} // namespace mysql
} // namespace boost
template <class SocketStream>
void boost::mysql::detail::close_connection(
@@ -86,21 +80,18 @@ void boost::mysql::detail::close_connection(
}
template <class SocketStream, class CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
CompletionToken,
void(boost::mysql::error_code)
)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(boost::mysql::error_code))
boost::mysql::detail::async_close_connection(
channel<SocketStream>& chan,
CompletionToken&& token,
error_info& info
)
{
return boost::asio::async_compose<
CompletionToken,
void(boost::mysql::error_code)
>(close_connection_op<SocketStream>{chan, info}, token, chan);
return boost::asio::async_compose<CompletionToken, void(boost::mysql::error_code)>(
close_connection_op<SocketStream>{chan, info},
token,
chan
);
}
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_IMPL_CLOSE_CONNECTION_HPP_ */

View File

@@ -17,26 +17,19 @@ namespace boost {
namespace mysql {
namespace detail {
template<class Stream>
template <class Stream>
struct close_statement_op : boost::asio::coroutine
{
channel<Stream>& chan_;
statement_base& stmt_;
close_statement_op(
channel<Stream>& chan,
statement_base& stmt
) noexcept :
chan_(chan),
stmt_(stmt)
close_statement_op(channel<Stream>& chan, statement_base& stmt) noexcept
: chan_(chan), stmt_(stmt)
{
}
template<class Self>
void operator()(
Self& self,
error_code err = {}
)
template <class Self>
void operator()(Self& self, error_code err = {})
{
// Error checking
if (err)
@@ -64,20 +57,16 @@ struct close_statement_op : boost::asio::coroutine
}
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
template <class Stream>
void boost::mysql::detail::close_statement(
channel<Stream>& chan,
statement_base& stmt,
error_code& code,
error_info&
)
void boost::mysql::detail::
close_statement(channel<Stream>& chan, statement_base& stmt, error_code& code, error_info&)
{
// Compose the close message
com_stmt_close_packet packet {stmt.id()};
com_stmt_close_packet packet{stmt.id()};
// Serialize it
serialize_message(packet, chan.current_capabilities(), chan.shared_buffer());
@@ -90,19 +79,12 @@ void boost::mysql::detail::close_statement(
}
template <class Stream, class CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
CompletionToken,
void(boost::mysql::error_code)
)
boost::mysql::detail::async_close_statement(
channel<Stream>& chan,
statement_base& stmt,
CompletionToken&& token,
error_info&
)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(boost::mysql::error_code))
boost::mysql::detail::
async_close_statement(channel<Stream>& chan, statement_base& stmt, CompletionToken&& token, error_info&)
{
// Compose the close message
com_stmt_close_packet packet {stmt.id()};
com_stmt_close_packet packet{stmt.id()};
// Serialize it
serialize_message(packet, chan.current_capabilities(), chan.shared_buffer());
@@ -115,5 +97,4 @@ boost::mysql::detail::async_close_statement(
);
}
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_IMPL_CLOSE_STATEMENT_HPP_ */

View File

@@ -32,19 +32,13 @@ struct connect_op : boost::asio::coroutine
error_info& output_info,
const endpoint_type& ep,
const handshake_params& params
) :
chan_(chan),
output_info_(output_info),
ep_(ep),
params_(params)
)
: chan_(chan), output_info_(output_info), ep_(ep), params_(params)
{
}
template<class Self>
void operator()(
Self& self,
error_code code = {}
)
template <class Self>
void operator()(Self& self, error_code code = {})
{
BOOST_ASIO_CORO_REENTER(*this)
{
@@ -59,12 +53,7 @@ struct connect_op : boost::asio::coroutine
}
// Handshake
BOOST_ASIO_CORO_YIELD async_handshake(
chan_,
params_,
std::move(self),
output_info_
);
BOOST_ASIO_CORO_YIELD async_handshake(chan_, params_, std::move(self), output_info_);
if (code)
{
chan_.close();
@@ -74,9 +63,9 @@ struct connect_op : boost::asio::coroutine
}
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
template <class Stream>
void boost::mysql::detail::connect(
@@ -102,10 +91,7 @@ void boost::mysql::detail::connect(
}
template <class Stream, class CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
CompletionToken,
void(boost::mysql::error_code)
)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(boost::mysql::error_code))
boost::mysql::detail::async_connect(
channel<Stream>& chan,
const typename Stream::lowest_layer_type::endpoint_type& endpoint,
@@ -115,7 +101,10 @@ boost::mysql::detail::async_connect(
)
{
return boost::asio::async_compose<CompletionToken, void(error_code)>(
connect_op<Stream>{chan, info, endpoint, params}, token, chan);
connect_op<Stream>{chan, info, endpoint, params},
token,
chan
);
}
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_IMPL_CONNECT_HPP_ */

View File

@@ -10,14 +10,16 @@
#pragma once
#include <boost/mysql/detail/network_algorithms/execute_generic.hpp>
#include <boost/mysql/detail/auxiliar/bytestring.hpp>
#include <boost/mysql/detail/network_algorithms/execute_generic.hpp>
#include <boost/mysql/detail/protocol/capabilities.hpp>
#include <boost/mysql/detail/protocol/common_messages.hpp>
#include <boost/mysql/detail/protocol/resultset_encoding.hpp>
#include <boost/mysql/error.hpp>
#include <boost/mysql/resultset_base.hpp>
#include <boost/asio/buffer.hpp>
#include <cstddef>
#include <cstdint>
#include <limits>
@@ -32,21 +34,17 @@ class execute_processor
error_info& output_info_;
bytestring& write_buffer_;
capabilities caps_;
std::size_t num_fields_ {};
std::size_t remaining_fields_ {};
std::size_t num_fields_{};
std::size_t remaining_fields_{};
public:
execute_processor(
resultset_base& output,
error_info& output_info,
bytestring& write_buffer,
capabilities caps
) noexcept:
output_(output),
output_info_(output_info),
write_buffer_(write_buffer),
caps_(caps)
{
};
) noexcept
: output_(output), output_info_(output_info), write_buffer_(write_buffer), caps_(caps){};
template <class Serializable, class Stream>
void process_request(
@@ -59,15 +57,12 @@ public:
serialize_message(request, caps_, write_buffer_);
}
void process_response(
boost::asio::const_buffer response,
error_code& err
)
void process_response(boost::asio::const_buffer response, error_code& err)
{
// Response may be: ok_packet, err_packet, local infile request (not implemented)
// If it is none of this, then the message type itself is the beginning of
// a length-encoded int containing the field count
deserialization_context ctx (response, caps_);
deserialization_context ctx(response, caps_);
std::uint8_t msg_type = 0;
err = make_error_code(deserialize(ctx, msg_type));
if (err)
@@ -113,7 +108,7 @@ public:
return;
}
remaining_fields_ = num_fields_;
remaining_fields_ = num_fields_;
output_.prepare_meta(num_fields_);
}
}
@@ -121,7 +116,7 @@ public:
error_code process_field_definition(boost::asio::const_buffer message)
{
column_definition_packet field_definition;
deserialization_context ctx (message, caps_);
deserialization_context ctx(message, caps_);
auto err = deserialize_message(ctx, field_definition);
if (err)
return err;
@@ -137,27 +132,19 @@ public:
bool has_remaining_fields() const noexcept { return remaining_fields_ != 0; }
};
template<class Stream>
template <class Stream>
struct execute_generic_op : boost::asio::coroutine
{
channel<Stream>& chan_;
execute_processor processor_;
execute_generic_op(
channel<Stream>& chan,
const execute_processor& processor
) :
chan_(chan),
processor_(processor)
execute_generic_op(channel<Stream>& chan, const execute_processor& processor)
: chan_(chan), processor_(processor)
{
}
template<class Self>
void operator()(
Self& self,
error_code err = {},
boost::asio::const_buffer read_message = {}
)
template <class Self>
void operator()(Self& self, error_code err = {}, boost::asio::const_buffer read_message = {})
{
// Error checking
if (err)
@@ -170,10 +157,14 @@ struct execute_generic_op : boost::asio::coroutine
BOOST_ASIO_CORO_REENTER(*this)
{
// The request message has already been composed in the initiating fn. Send it
BOOST_ASIO_CORO_YIELD chan_.async_write(chan_.shared_buffer(), processor_.sequence_number(), std::move(self));
BOOST_ASIO_CORO_YIELD chan_
.async_write(chan_.shared_buffer(), processor_.sequence_number(), std::move(self));
// Read the response
BOOST_ASIO_CORO_YIELD chan_.async_read_one(processor_.sequence_number(), std::move(self));
BOOST_ASIO_CORO_YIELD chan_.async_read_one(
processor_.sequence_number(),
std::move(self)
);
// Response may be: ok_packet, err_packet, local infile request
// (not implemented), or response with fields
@@ -216,9 +207,9 @@ struct execute_generic_op : boost::asio::coroutine
}
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
template <class Stream, class Serializable>
void boost::mysql::detail::execute_generic(
@@ -231,12 +222,8 @@ void boost::mysql::detail::execute_generic(
)
{
// Compose a com_query message, reset seq num
execute_processor processor (
output,
info,
channel.shared_buffer(),
channel.current_capabilities()
);
execute_processor
processor(output, info, channel.shared_buffer(), channel.current_capabilities());
processor.process_request(request, encoding, channel);
// Send it
@@ -249,7 +236,8 @@ void boost::mysql::detail::execute_generic(
if (err)
return;
// Response may be: ok_packet, err_packet, local infile request (not implemented), or response with fields
// Response may be: ok_packet, err_packet, local infile request (not implemented), or response
// with fields
processor.process_response(read_buffer, err);
if (err)
return;
@@ -278,10 +266,7 @@ void boost::mysql::detail::execute_generic(
}
template <class Stream, class Serializable, class CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
CompletionToken,
void(boost::mysql::error_code)
)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(boost::mysql::error_code))
boost::mysql::detail::async_execute_generic(
resultset_encoding encoding,
channel<Stream>& channel,
@@ -291,12 +276,8 @@ boost::mysql::detail::async_execute_generic(
CompletionToken&& token
)
{
execute_processor processor (
output,
info,
channel.shared_buffer(),
channel.current_capabilities()
);
execute_processor
processor(output, info, channel.shared_buffer(), channel.current_capabilities());
processor.process_request(request, encoding, channel);
return boost::asio::async_compose<CompletionToken, void(error_code)>(
execute_generic_op<Stream>(channel, processor),
@@ -305,5 +286,4 @@ boost::mysql::detail::async_execute_generic(
);
}
#endif /* INCLUDE_MYSQL_IMPL_NETWORK_ALGORITHMS_READ_RESULTSET_HEAD_IPP_ */

View File

@@ -10,10 +10,10 @@
#pragma once
#include <boost/mysql/detail/network_algorithms/execute_generic.hpp>
#include <boost/mysql/detail/network_algorithms/execute_query.hpp>
#include <boost/mysql/detail/protocol/query_messages.hpp>
#include <boost/mysql/detail/protocol/resultset_encoding.hpp>
#include <boost/mysql/detail/network_algorithms/execute_generic.hpp>
template <class Stream>
void boost::mysql::detail::execute_query(
@@ -24,23 +24,12 @@ void boost::mysql::detail::execute_query(
error_info& info
)
{
com_query_packet request { string_eof(query) };
execute_generic(
resultset_encoding::text,
channel,
request,
output,
err,
info
);
com_query_packet request{string_eof(query)};
execute_generic(resultset_encoding::text, channel, request, output, err, info);
}
template <class Stream, class CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
CompletionToken,
void(boost::mysql::error_code)
)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(boost::mysql::error_code))
boost::mysql::detail::async_execute_query(
channel<Stream>& chan,
boost::string_view query,
@@ -49,7 +38,7 @@ boost::mysql::detail::async_execute_query(
CompletionToken&& token
)
{
com_query_packet request { string_eof(query) };
com_query_packet request{string_eof(query)};
return async_execute_generic(
resultset_encoding::text,
chan,
@@ -60,5 +49,4 @@ boost::mysql::detail::async_execute_query(
);
}
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_IMPL_EXECUTE_QUERY_HPP_ */

View File

@@ -10,18 +10,18 @@
#pragma once
#include <boost/mysql/detail/network_algorithms/execute_statement.hpp>
#include <boost/mysql/detail/auxiliar/stringize.hpp>
#include <boost/mysql/detail/network_algorithms/execute_generic.hpp>
#include <boost/mysql/detail/network_algorithms/execute_statement.hpp>
#include <boost/mysql/detail/protocol/prepared_statement_messages.hpp>
#include <boost/mysql/detail/protocol/resultset_encoding.hpp>
#include <boost/mysql/detail/auxiliar/stringize.hpp>
#include <boost/mysql/statement_base.hpp>
#include <boost/mysql/resultset_base.hpp>
#include <boost/mysql/execute_params.hpp>
#include <boost/mysql/error.hpp>
#include <boost/asio/post.hpp>
#include <boost/asio/compose.hpp>
#include <boost/mysql/execute_params.hpp>
#include <boost/mysql/resultset_base.hpp>
#include <boost/mysql/statement_base.hpp>
#include <boost/asio/compose.hpp>
#include <boost/asio/post.hpp>
namespace boost {
namespace mysql {
@@ -33,14 +33,13 @@ com_stmt_execute_packet<FieldViewFwdIterator> make_stmt_execute_packet(
const statement_base& stmt
)
{
return com_stmt_execute_packet<FieldViewFwdIterator> {
return com_stmt_execute_packet<FieldViewFwdIterator>{
stmt.id(),
std::uint8_t(0), // flags
std::uint32_t(1), // iteration count
std::uint8_t(1), // new params flag: set
std::uint8_t(0), // flags
std::uint32_t(1), // iteration count
std::uint8_t(1), // new params flag: set
params.first(),
params.last()
};
params.last()};
}
template <class FieldViewFwdIterator>
@@ -54,7 +53,10 @@ error_code check_num_params(
if (param_count != stmt.num_params())
{
info.set_message(detail::stringize(
"execute statement: expected ", stmt.num_params(), " params, but got ", param_count
"execute statement: expected ",
stmt.num_params(),
" params, but got ",
param_count
));
return make_error_code(errc::wrong_num_params);
}
@@ -70,7 +72,7 @@ struct fast_fail_op : boost::asio::coroutine
fast_fail_op(error_code err) noexcept : err_(err) {}
template<class Self>
template <class Self>
void operator()(Self& self)
{
BOOST_ASIO_CORO_REENTER(*this)
@@ -81,10 +83,9 @@ struct fast_fail_op : boost::asio::coroutine
}
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
template <class Stream, class FieldViewFwdIterator>
void boost::mysql::detail::execute_statement(
@@ -111,10 +112,7 @@ void boost::mysql::detail::execute_statement(
}
template <class Stream, class FieldViewFwdIterator, class CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
CompletionToken,
void(boost::mysql::error_code)
)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(boost::mysql::error_code))
boost::mysql::detail::async_execute_statement(
channel<Stream>& chan,
const statement_base& stmt,
@@ -143,6 +141,4 @@ boost::mysql::detail::async_execute_statement(
);
}
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_IMPL_EXECUTE_STATEMENT_HPP_ */

View File

@@ -10,13 +10,14 @@
#pragma once
#include <boost/mysql/detail/auth/auth_calculator.hpp>
#include <boost/mysql/detail/network_algorithms/handshake.hpp>
#include <boost/mysql/detail/protocol/capabilities.hpp>
#include <boost/mysql/detail/protocol/handshake_messages.hpp>
#include <boost/mysql/detail/auth/auth_calculator.hpp>
#include <boost/asio/buffer.hpp>
#include <type_traits>
#include <boost/asio/buffer.hpp>
#include <type_traits>
namespace boost {
namespace mysql {
@@ -38,7 +39,7 @@ inline error_code deserialize_handshake(
error_info& info
)
{
deserialization_context ctx (boost::asio::buffer(buffer), capabilities());
deserialization_context ctx(boost::asio::buffer(buffer), capabilities());
std::uint8_t msg_type = 0;
auto err = deserialize(ctx, msg_type);
if (err != errc::ok)
@@ -81,8 +82,9 @@ class handshake_processor
handshake_params params_;
capabilities negotiated_caps_;
auth_calculator auth_calc_;
public:
handshake_processor(const handshake_params& params): params_(params) {};
handshake_processor(const handshake_params& params) : params_(params){};
capabilities negotiated_capabilities() const noexcept { return negotiated_caps_; }
const handshake_params& params() const noexcept { return params_; }
bool use_ssl() const noexcept { return negotiated_caps_.has(CLIENT_SSL); }
@@ -91,20 +93,33 @@ public:
error_code process_capabilities(const handshake_packet& handshake, bool is_ssl_stream)
{
auto ssl = params_.ssl();
capabilities server_caps (handshake.capability_falgs);
capabilities server_caps(handshake.capability_falgs);
capabilities required_caps = mandatory_capabilities |
conditional_capability(!params_.database().empty(), CLIENT_CONNECT_WITH_DB) |
conditional_capability(ssl == ssl_mode::require && is_ssl_stream, CLIENT_SSL);
conditional_capability(
!params_.database().empty(),
CLIENT_CONNECT_WITH_DB
) |
conditional_capability(
ssl == ssl_mode::require && is_ssl_stream,
CLIENT_SSL
);
if (!server_caps.has_all(required_caps))
{
return make_error_code(errc::server_unsupported);
}
negotiated_caps_ = server_caps & (required_caps | optional_capabilities |
conditional_capability(ssl == ssl_mode::enable && is_ssl_stream, CLIENT_SSL));
conditional_capability(
ssl == ssl_mode::enable && is_ssl_stream,
CLIENT_SSL
));
return error_code();
}
error_code process_handshake(boost::asio::const_buffer buffer, error_info& info, bool is_ssl_stream)
error_code process_handshake(
boost::asio::const_buffer buffer,
error_info& info,
bool is_ssl_stream
)
{
// Deserialize server greeting
handshake_packet handshake;
@@ -129,12 +144,11 @@ public:
// Response to that initial greeting
void compose_ssl_request(bytestring& buffer)
{
ssl_request sslreq {
ssl_request sslreq{
negotiated_capabilities().get(),
static_cast<std::uint32_t>(MAX_PACKET_SIZE),
get_collation_first_byte(params_.connection_collation()),
{}
};
{}};
// Serialize and send
serialize_message(sslreq, negotiated_caps_, buffer);
@@ -143,15 +157,14 @@ public:
void compose_handshake_response(bytestring& buffer)
{
// Compose response
handshake_response_packet response {
handshake_response_packet response{
negotiated_caps_.get(),
static_cast<std::uint32_t>(MAX_PACKET_SIZE),
get_collation_first_byte(params_.connection_collation()),
string_null(params_.username()),
string_lenenc(auth_calc_.response()),
string_null(params_.database()),
string_null(auth_calc_.plugin_name())
};
string_null(auth_calc_.plugin_name())};
// Serialize
serialize_message(response, negotiated_caps_, buffer);
@@ -165,7 +178,7 @@ public:
error_info& info
)
{
deserialization_context ctx (server_response, negotiated_caps_);
deserialization_context ctx(server_response, negotiated_caps_);
std::uint8_t msg_type = 0;
auto err = make_error_code(deserialize(ctx, msg_type));
if (err)
@@ -234,7 +247,7 @@ public:
return err;
serialize_message(
auth_switch_response_packet {string_eof(auth_calc_.response())},
auth_switch_response_packet{string_eof(auth_calc_.response())},
negotiated_caps_,
write_buffer
);
@@ -249,31 +262,21 @@ public:
}
};
template<class Stream>
template <class Stream>
struct handshake_op : boost::asio::coroutine
{
channel<Stream>& chan_;
error_info& output_info_;
handshake_processor processor_;
auth_result auth_state_ {auth_result::invalid};
auth_result auth_state_{auth_result::invalid};
handshake_op(
channel<Stream>& channel,
error_info& output_info,
const handshake_params& params
) :
chan_(channel),
output_info_(output_info),
processor_(params)
handshake_op(channel<Stream>& channel, error_info& output_info, const handshake_params& params)
: chan_(channel), output_info_(output_info), processor_(params)
{
}
template<class Self>
void operator()(
Self& self,
error_code err = {},
boost::asio::const_buffer read_msg = {}
)
template <class Self>
void operator()(Self& self, error_code err = {}, boost::asio::const_buffer read_msg = {})
{
// Error checking
if (err)
@@ -286,10 +289,14 @@ struct handshake_op : boost::asio::coroutine
BOOST_ASIO_CORO_REENTER(*this)
{
// Read server greeting
BOOST_ASIO_CORO_YIELD chan_.async_read_one(chan_.shared_sequence_number(), std::move(self));
BOOST_ASIO_CORO_YIELD chan_.async_read_one(
chan_.shared_sequence_number(),
std::move(self)
);
// Process server greeting
err = processor_.process_handshake(read_msg, output_info_, is_ssl_stream<Stream>::value);
err = processor_
.process_handshake(read_msg, output_info_, is_ssl_stream<Stream>::value);
if (err)
{
self.complete(err);
@@ -315,12 +322,19 @@ struct handshake_op : boost::asio::coroutine
// Compose and send handshake response
processor_.compose_handshake_response(chan_.shared_buffer());
BOOST_ASIO_CORO_YIELD chan_.async_write(chan_.shared_buffer(), chan_.shared_sequence_number(), std::move(self));
BOOST_ASIO_CORO_YIELD chan_.async_write(
chan_.shared_buffer(),
chan_.shared_sequence_number(),
std::move(self)
);
while (auth_state_ != auth_result::complete)
{
// Receive response
BOOST_ASIO_CORO_YIELD chan_.async_read_one(chan_.shared_sequence_number(), std::move(self));
BOOST_ASIO_CORO_YIELD chan_.async_read_one(
chan_.shared_sequence_number(),
std::move(self)
);
// Process it
err = processor_.process_handshake_server_response(
@@ -347,9 +361,9 @@ struct handshake_op : boost::asio::coroutine
}
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
template <class Stream>
void boost::mysql::detail::handshake(
@@ -362,7 +376,7 @@ void boost::mysql::detail::handshake(
channel.next_layer().reset();
// Set up processor
handshake_processor processor (params);
handshake_processor processor(params);
// Read server greeting
auto b = channel.read_one(channel.shared_sequence_number(), err);
@@ -391,7 +405,8 @@ void boost::mysql::detail::handshake(
// Handshake response
processor.compose_handshake_response(channel.shared_buffer());
channel.write(boost::asio::buffer(channel.shared_buffer()), channel.shared_sequence_number(), err);
channel
.write(boost::asio::buffer(channel.shared_buffer()), channel.shared_sequence_number(), err);
if (err)
return;
@@ -404,14 +419,23 @@ void boost::mysql::detail::handshake(
return;
// Process it
err = processor.process_handshake_server_response(b, channel.shared_buffer(), auth_outcome, info);
err = processor.process_handshake_server_response(
b,
channel.shared_buffer(),
auth_outcome,
info
);
if (err)
return;
if (auth_outcome == auth_result::send_more_data)
{
// We received an auth switch request and we have the response ready to be sent
channel.write(boost::asio::buffer(channel.shared_buffer()), channel.shared_sequence_number(), err);
channel.write(
boost::asio::buffer(channel.shared_buffer()),
channel.shared_sequence_number(),
err
);
if (err)
return;
}
@@ -421,10 +445,7 @@ void boost::mysql::detail::handshake(
}
template <class Stream, class CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
CompletionToken,
void(boost::mysql::error_code)
)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(boost::mysql::error_code))
boost::mysql::detail::async_handshake(
channel<Stream>& chan,
const handshake_params& params,
@@ -433,15 +454,11 @@ boost::mysql::detail::async_handshake(
)
{
chan.reset();
return boost::asio::async_compose<
CompletionToken,
void(error_code)
>(
return boost::asio::async_compose<CompletionToken, void(error_code)>(
handshake_op<Stream>(chan, info, params),
token,
chan
);
}
#endif

View File

@@ -10,15 +10,16 @@
#pragma once
#include <boost/mysql/detail/network_algorithms/prepare_statement.hpp>
#include <boost/mysql/detail/auxiliar/bytestring.hpp>
#include <boost/mysql/detail/channel/channel.hpp>
#include <boost/mysql/detail/network_algorithms/prepare_statement.hpp>
#include <boost/mysql/detail/protocol/capabilities.hpp>
#include <boost/mysql/error.hpp>
#include <boost/mysql/statement_base.hpp>
#include <boost/asio/buffer.hpp>
#include <cstdint>
#include <boost/asio/buffer.hpp>
#include <cstdint>
namespace boost {
namespace mysql {
@@ -30,30 +31,31 @@ class prepare_statement_processor
bytestring& write_buffer_;
statement_base& output_;
error_info& output_info_;
unsigned remaining_meta_ {};
unsigned remaining_meta_{};
public:
template <class Stream>
prepare_statement_processor(
channel<Stream>& chan,
statement_base& output,
error_info& output_info
) noexcept :
caps_(chan.current_capabilities()),
write_buffer_(chan.shared_buffer()),
output_(output),
output_info_(output_info)
) noexcept
: caps_(chan.current_capabilities()),
write_buffer_(chan.shared_buffer()),
output_(output),
output_info_(output_info)
{
}
void process_request(boost::string_view statement)
{
com_stmt_prepare_packet packet { string_eof(statement) };
com_stmt_prepare_packet packet{string_eof(statement)};
serialize_message(packet, caps_, write_buffer_);
}
void process_response(boost::asio::const_buffer message, void* channel, error_code& err)
{
deserialization_context ctx (message, caps_);
deserialization_context ctx(message, caps_);
std::uint8_t msg_type = 0;
err = make_error_code(deserialize(ctx, msg_type));
if (err)
@@ -80,27 +82,19 @@ public:
void on_meta_received() noexcept { --remaining_meta_; }
};
template<class Stream>
template <class Stream>
struct prepare_statement_op : boost::asio::coroutine
{
channel<Stream>& chan_;
prepare_statement_processor processor_;
prepare_statement_op(
channel<Stream>& chan,
const prepare_statement_processor& processor
) :
chan_(chan),
processor_(processor)
prepare_statement_op(channel<Stream>& chan, const prepare_statement_processor& processor)
: chan_(chan), processor_(processor)
{
}
template<class Self>
void operator()(
Self& self,
error_code err = {},
boost::asio::const_buffer read_message = {}
)
template <class Self>
void operator()(Self& self, error_code err = {}, boost::asio::const_buffer read_message = {})
{
// Error checking
if (err)
@@ -113,10 +107,17 @@ struct prepare_statement_op : boost::asio::coroutine
BOOST_ASIO_CORO_REENTER(*this)
{
// Write message (already serialized at this point)
BOOST_ASIO_CORO_YIELD chan_.async_write(chan_.shared_buffer(), chan_.shared_sequence_number(), std::move(self));
BOOST_ASIO_CORO_YIELD chan_.async_write(
chan_.shared_buffer(),
chan_.shared_sequence_number(),
std::move(self)
);
// Read response
BOOST_ASIO_CORO_YIELD chan_.async_read_one(chan_.shared_sequence_number(), std::move(self));
BOOST_ASIO_CORO_YIELD chan_.async_read_one(
chan_.shared_sequence_number(),
std::move(self)
);
// Process response
processor_.process_response(read_message, &chan_, err);
@@ -154,9 +155,9 @@ struct prepare_statement_op : boost::asio::coroutine
}
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
template <class Stream>
void boost::mysql::detail::prepare_statement(
@@ -168,7 +169,7 @@ void boost::mysql::detail::prepare_statement(
)
{
// Prepare message
prepare_statement_processor processor (channel, output, info);
prepare_statement_processor processor(channel, output, info);
processor.process_request(statement);
// Write message
@@ -203,10 +204,7 @@ void boost::mysql::detail::prepare_statement(
}
template <class Stream, class CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
CompletionToken,
void(boost::mysql::error_code)
)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(boost::mysql::error_code))
boost::mysql::detail::async_prepare_statement(
channel<Stream>& chan,
boost::string_view statement,
@@ -215,7 +213,7 @@ boost::mysql::detail::async_prepare_statement(
CompletionToken&& token
)
{
prepare_statement_processor processor (chan, output, info);
prepare_statement_processor processor(chan, output, info);
processor.process_request(statement);
return boost::asio::async_compose<CompletionToken, void(error_code)>(
prepare_statement_op(chan, processor),

View File

@@ -10,40 +10,31 @@
#pragma once
#include <boost/mysql/detail/network_algorithms/quit_connection.hpp>
#include <boost/asio/coroutine.hpp>
#include <boost/mysql/detail/channel/channel.hpp>
#include <boost/mysql/detail/network_algorithms/quit_connection.hpp>
#include <boost/mysql/error.hpp>
#include <boost/asio/coroutine.hpp>
namespace boost {
namespace mysql {
namespace detail {
template <class Stream>
void compose_quit(
channel<Stream>& chan
)
void compose_quit(channel<Stream>& chan)
{
serialize_message(
quit_packet(),
chan.current_capabilities(),
chan.shared_buffer()
);
serialize_message(quit_packet(), chan.current_capabilities(), chan.shared_buffer());
}
template<class Stream>
template <class Stream>
struct quit_connection_op : boost::asio::coroutine
{
channel<Stream>& chan_;
quit_connection_op(channel<Stream>& chan) noexcept :
chan_(chan) {}
quit_connection_op(channel<Stream>& chan) noexcept : chan_(chan) {}
template<class Self>
void operator()(
Self& self,
error_code err = {}
)
template <class Self>
void operator()(Self& self, error_code err = {})
{
BOOST_ASIO_CORO_REENTER(*this)
{
@@ -66,16 +57,12 @@ struct quit_connection_op : boost::asio::coroutine
}
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
template <class Stream>
void boost::mysql::detail::quit_connection(
channel<Stream>& chan,
error_code& err,
error_info&
)
void boost::mysql::detail::quit_connection(channel<Stream>& chan, error_code& err, error_info&)
{
compose_quit(chan);
chan.write(chan.shared_buffer(), chan.shared_sequence_number(), err);
@@ -91,15 +78,9 @@ void boost::mysql::detail::quit_connection(
}
template <class Stream, class CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
CompletionToken,
void(boost::mysql::error_code)
)
boost::mysql::detail::async_quit_connection(
channel<Stream>& chan,
CompletionToken&& token,
error_info&
)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(boost::mysql::error_code))
boost::mysql::detail::
async_quit_connection(channel<Stream>& chan, CompletionToken&& token, error_info&)
{
return boost::asio::async_compose<CompletionToken, void(error_code)>(
quit_connection_op<Stream>(chan),

View File

@@ -12,14 +12,15 @@
#include <boost/mysql/detail/network_algorithms/read_all_rows.hpp>
#include <boost/mysql/detail/protocol/deserialize_row.hpp>
#include <boost/mysql/rows_view.hpp>
#include <boost/mysql/error.hpp>
#include <boost/mysql/resultset_base.hpp>
#include <boost/asio/post.hpp>
#include <boost/mysql/rows_view.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/coroutine.hpp>
#include <cstddef>
#include <boost/asio/post.hpp>
#include <cstddef>
namespace boost {
namespace mysql {
@@ -55,7 +56,7 @@ inline void process_all_rows(
);
if (err)
return;
// If we received an EOF, we're done
if (result.complete())
{
@@ -70,8 +71,7 @@ inline void process_all_rows(
}
}
template<class Stream>
template <class Stream>
struct read_all_rows_op : boost::asio::coroutine
{
channel<Stream>& chan_;
@@ -82,18 +82,13 @@ struct read_all_rows_op : boost::asio::coroutine
channel<Stream>& chan,
error_info& output_info,
resultset_base& result
) noexcept :
chan_(chan),
output_info_(output_info),
resultset_(result)
) noexcept
: chan_(chan), output_info_(output_info), resultset_(result)
{
}
template<class Self>
void operator()(
Self& self,
error_code err = {}
)
template <class Self>
void operator()(Self& self, error_code err = {})
{
// Error checking
if (err)
@@ -138,10 +133,9 @@ struct read_all_rows_op : boost::asio::coroutine
}
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
template <class Stream>
boost::mysql::rows_view boost::mysql::detail::read_all_rows(
@@ -167,7 +161,7 @@ boost::mysql::rows_view boost::mysql::detail::read_all_rows(
channel.read_some(err, true);
if (err)
return rows_view();
// Process read messages
process_all_rows(channel, result, output, err, info);
if (err)
@@ -188,12 +182,8 @@ boost::mysql::detail::async_read_all_rows(
CompletionToken&& token
)
{
return boost::asio::async_compose<CompletionToken, void(error_code, rows_view)> (
read_all_rows_op<Stream>(
channel,
output_info,
result
),
return boost::asio::async_compose<CompletionToken, void(error_code, rows_view)>(
read_all_rows_op<Stream>(channel, output_info, result),
token,
channel
);

View File

@@ -14,8 +14,10 @@
#include <boost/mysql/detail/protocol/deserialize_row.hpp>
#include <boost/mysql/resultset_base.hpp>
#include <boost/mysql/row_view.hpp>
#include <boost/asio/post.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/post.hpp>
#include <vector>
namespace boost {
@@ -56,30 +58,20 @@ inline row_view process_one_row(
}
}
template<class Stream>
template <class Stream>
struct read_one_row_op : boost::asio::coroutine
{
channel<Stream>& chan_;
error_info& output_info_;
resultset_base& resultset_;
read_one_row_op(
channel<Stream>& chan,
error_info& output_info,
resultset_base& result
) noexcept :
chan_(chan),
output_info_(output_info),
resultset_(result)
read_one_row_op(channel<Stream>& chan, error_info& output_info, resultset_base& result) noexcept
: chan_(chan), output_info_(output_info), resultset_(result)
{
}
template<class Self>
void operator()(
Self& self,
error_code err = {},
boost::asio::const_buffer read_message = {}
)
template <class Self>
void operator()(Self& self, error_code err = {}, boost::asio::const_buffer read_message = {})
{
// Error checking
if (err)
@@ -101,25 +93,21 @@ struct read_one_row_op : boost::asio::coroutine
}
// Read the message
BOOST_ASIO_CORO_YIELD chan_.async_read_one(resultset_.sequence_number(), std::move(self));
BOOST_ASIO_CORO_YIELD chan_.async_read_one(
resultset_.sequence_number(),
std::move(self)
);
// Process it
result = process_one_row(
chan_,
read_message,
resultset_,
err,
output_info_
);
result = process_one_row(chan_, read_message, resultset_, err, output_info_);
self.complete(err, result);
}
}
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
template <class Stream>
boost::mysql::row_view boost::mysql::detail::read_one_row(
@@ -140,13 +128,7 @@ boost::mysql::row_view boost::mysql::detail::read_one_row(
if (err)
return row_view();
return process_one_row(
channel,
read_message,
result,
err,
info
);
return process_one_row(channel, read_message, result, err, info);
}
template <class Stream, class CompletionToken>
@@ -161,12 +143,8 @@ boost::mysql::detail::async_read_one_row(
CompletionToken&& token
)
{
return boost::asio::async_compose<CompletionToken, void(error_code, row_view)> (
read_one_row_op<Stream>(
channel,
output_info,
result
),
return boost::asio::async_compose<CompletionToken, void(error_code, row_view)>(
read_one_row_op<Stream>(channel, output_info, result),
token,
channel
);

View File

@@ -13,12 +13,13 @@
#include <boost/mysql/detail/network_algorithms/read_some_rows.hpp>
#include <boost/mysql/detail/protocol/deserialize_row.hpp>
#include <boost/mysql/error.hpp>
#include <boost/mysql/row.hpp>
#include <boost/mysql/resultset_base.hpp>
#include <boost/asio/post.hpp>
#include <boost/asio/buffer.hpp>
#include <cstddef>
#include <boost/mysql/row.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/post.hpp>
#include <cstddef>
namespace boost {
namespace mysql {
@@ -55,7 +56,7 @@ inline rows_view process_some_rows(
);
if (err)
return rows_view();
// There is no need to copy strings values anywhere; the returned values
// will point into the channel's internal buffer
@@ -73,8 +74,7 @@ inline rows_view process_some_rows(
);
}
template<class Stream>
template <class Stream>
struct read_some_rows_op : boost::asio::coroutine
{
channel<Stream>& chan_;
@@ -85,18 +85,13 @@ struct read_some_rows_op : boost::asio::coroutine
channel<Stream>& chan,
error_info& output_info,
resultset_base& result
) noexcept :
chan_(chan),
output_info_(output_info),
resultset_(result)
) noexcept
: chan_(chan), output_info_(output_info), resultset_(result)
{
}
template<class Self>
void operator()(
Self& self,
error_code err = {}
)
template <class Self>
void operator()(Self& self, error_code err = {})
{
// Error checking
if (err)
@@ -122,16 +117,15 @@ struct read_some_rows_op : boost::asio::coroutine
// Process messages
output = process_some_rows(chan_, resultset_, err, output_info_);
self.complete(err, output);
}
}
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
template <class Stream>
boost::mysql::rows_view boost::mysql::detail::read_some_rows(
@@ -168,12 +162,8 @@ boost::mysql::detail::async_read_some_rows(
CompletionToken&& token
)
{
return boost::asio::async_compose<CompletionToken, void(error_code, rows_view)> (
read_some_rows_op<Stream>(
channel,
output_info,
result
),
return boost::asio::async_compose<CompletionToken, void(error_code, rows_view)>(
read_some_rows_op<Stream>(channel, output_info, result),
token,
channel
);

View File

@@ -8,11 +8,11 @@
#ifndef BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_PREPARE_STATEMENT_HPP
#define BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_PREPARE_STATEMENT_HPP
#include <boost/mysql/detail/channel/channel.hpp>
#include <boost/mysql/error.hpp>
#include <boost/mysql/statement_base.hpp>
#include <boost/utility/string_view.hpp>
#include <boost/mysql/detail/channel/channel.hpp>
#include <boost/utility/string_view.hpp>
namespace boost {
namespace mysql {
@@ -37,9 +37,9 @@ async_prepare_statement(
CompletionToken&& token
);
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/network_algorithms/impl/prepare_statement.hpp>

View File

@@ -8,32 +8,23 @@
#ifndef BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_QUIT_CONNECTION_HPP
#define BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_QUIT_CONNECTION_HPP
#include <boost/mysql/error.hpp>
#include <boost/mysql/detail/channel/channel.hpp>
#include <boost/mysql/error.hpp>
namespace boost {
namespace mysql {
namespace detail {
template <class Stream>
void quit_connection(
channel<Stream>& chan,
error_code& code,
error_info& info
);
void quit_connection(channel<Stream>& chan, error_code& code, error_info& info);
template <class Stream, class CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
async_quit_connection(
channel<Stream>& chan,
CompletionToken&& token,
error_info& info
);
async_quit_connection(channel<Stream>& chan, CompletionToken&& token, error_info& info);
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/network_algorithms/impl/quit_connection.hpp>

View File

@@ -8,23 +8,18 @@
#ifndef BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_READ_ALL_ROWS_HPP
#define BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_READ_ALL_ROWS_HPP
#include <boost/mysql/error.hpp>
#include <boost/mysql/detail/channel/channel.hpp>
#include <boost/mysql/error.hpp>
#include <boost/mysql/resultset_base.hpp>
#include <boost/mysql/rows_view.hpp>
namespace boost {
namespace mysql {
namespace detail {
template <class Stream>
rows_view read_all_rows(
channel<Stream>& channel,
resultset_base& result,
error_code& err,
error_info& info
);
rows_view
read_all_rows(channel<Stream>& channel, resultset_base& result, error_code& err, error_info& info);
template <class Stream, class CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, rows_view))
@@ -35,13 +30,10 @@ async_read_all_rows(
CompletionToken&& token
);
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/network_algorithms/impl/read_all_rows.hpp>
#endif /* INCLUDE_MYSQL_IMPL_NETWORK_ALGORITHMS_READ_TEXT_ROW_HPP_ */

View File

@@ -8,23 +8,18 @@
#ifndef BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_READ_ONE_ROW_HPP
#define BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_READ_ONE_ROW_HPP
#include <boost/mysql/error.hpp>
#include <boost/mysql/detail/channel/channel.hpp>
#include <boost/mysql/error.hpp>
#include <boost/mysql/resultset_base.hpp>
#include <boost/mysql/row.hpp>
namespace boost {
namespace mysql {
namespace detail {
template <class Stream>
row_view read_one_row(
channel<Stream>& channel,
resultset_base& result,
error_code& err,
error_info& info
);
row_view
read_one_row(channel<Stream>& channel, resultset_base& result, error_code& err, error_info& info);
template <class Stream, class CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, row_view))
@@ -35,13 +30,10 @@ async_read_one_row(
CompletionToken&& token
);
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/network_algorithms/impl/read_one_row.hpp>
#endif /* INCLUDE_MYSQL_IMPL_NETWORK_ALGORITHMS_READ_TEXT_ROW_HPP_ */

View File

@@ -8,23 +8,18 @@
#ifndef BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_READ_SOME_ROWS_HPP
#define BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_READ_SOME_ROWS_HPP
#include <boost/mysql/error.hpp>
#include <boost/mysql/detail/channel/channel.hpp>
#include <boost/mysql/error.hpp>
#include <boost/mysql/resultset_base.hpp>
#include <boost/mysql/rows_view.hpp>
namespace boost {
namespace mysql {
namespace detail {
template <class Stream>
rows_view read_some_rows(
channel<Stream>& channel,
resultset_base& result,
error_code& err,
error_info& info
);
rows_view
read_some_rows(channel<Stream>& channel, resultset_base& result, error_code& err, error_info& info);
template <class Stream, class CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, rows_view))
@@ -35,13 +30,10 @@ async_read_some_rows(
CompletionToken&& token
);
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/network_algorithms/impl/read_some_rows.hpp>
#endif /* INCLUDE_MYSQL_IMPL_NETWORK_ALGORITHMS_READ_TEXT_ROW_HPP_ */

View File

@@ -8,27 +8,27 @@
#ifndef BOOST_MYSQL_DETAIL_PROTOCOL_BINARY_SERIALIZATION_HPP
#define BOOST_MYSQL_DETAIL_PROTOCOL_BINARY_SERIALIZATION_HPP
#include <boost/mysql/field_view.hpp>
#include <boost/mysql/detail/protocol/serialization.hpp>
#include <boost/mysql/field_view.hpp>
namespace boost {
namespace mysql {
namespace detail {
template <>
struct serialization_traits<field_view, serialization_tag::none> :
noop_deserialize<field_view>
struct serialization_traits<field_view, serialization_tag::none> : noop_deserialize<field_view>
{
static inline std::size_t get_size_(const serialization_context& ctx,
const field_view& input) noexcept;
static inline void serialize_(serialization_context& ctx,
const field_view& input) noexcept;
static inline std::size_t get_size_(
const serialization_context& ctx,
const field_view& input
) noexcept;
static inline void serialize_(serialization_context& ctx, const field_view& input) noexcept;
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/protocol/impl/binary_serialization.ipp>

View File

@@ -10,8 +10,10 @@
#include <boost/mysql/error.hpp>
#include <boost/mysql/field_view.hpp>
#include <boost/endian/conversion.hpp>
#include <boost/utility/string_view.hpp>
#include <cstring>
namespace boost {
@@ -19,29 +21,26 @@ namespace mysql {
namespace detail {
// All BIT values come as binary values between 1 and 8 bytes length packed in string_lenenc's,
// for both the text and the binary protocols. As the text protocol already unpacks the string_lenenc layer,
// this function is in charge of just parsing the binary payload.
// The length of the BIT value depends on how the type was defined in the table (e.g. BIT(14) will send
// a 2 byte value; BIT(54) will send a 7 byte one). Values are sent as big-endian.
inline errc deserialize_bit(
boost::string_view from,
field_view& to
) noexcept
// for both the text and the binary protocols. As the text protocol already unpacks the
// string_lenenc layer, this function is in charge of just parsing the binary payload. The length of
// the BIT value depends on how the type was defined in the table (e.g. BIT(14) will send a 2 byte
// value; BIT(54) will send a 7 byte one). Values are sent as big-endian.
inline errc deserialize_bit(boost::string_view from, field_view& to) noexcept
{
std::size_t num_bytes = from.size();
if (num_bytes < 1 || num_bytes > 8)
{
return errc::protocol_value_error;
}
unsigned char temp [8] {};
unsigned char temp[8]{};
unsigned char* dest = temp + sizeof(temp) - num_bytes;
std::memcpy(dest, from.data(), num_bytes);
to = field_view(boost::endian::load_big_u64(temp));
return errc::ok;
}
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#endif

View File

@@ -15,6 +15,7 @@ namespace mysql {
namespace detail {
// Server/client capabilities
// clang-format off
constexpr std::uint32_t CLIENT_LONG_PASSWORD = 1; // Use the improved version of Old Password Authentication
constexpr std::uint32_t CLIENT_FOUND_ROWS = 2; // Send found rows instead of affected rows in EOF_Packet
constexpr std::uint32_t CLIENT_LONG_FLAG = 4; // Get all column flags
@@ -43,73 +44,93 @@ constexpr std::uint32_t CLIENT_DEPRECATE_EOF = (1UL << 24); // Client no longer
constexpr std::uint32_t CLIENT_SSL_VERIFY_SERVER_CERT = (1UL << 30); // Verify server certificate
constexpr std::uint32_t CLIENT_OPTIONAL_RESULTSET_METADATA = (1UL << 25); // The client can handle optional metadata information in the resultset
constexpr std::uint32_t CLIENT_REMEMBER_OPTIONS = (1UL << 31); // Don't reset the options after an unsuccessful connect
// clang-format on
class capabilities
{
std::uint32_t value_;
public:
constexpr explicit capabilities(std::uint32_t value=0) noexcept : value_(value) {};
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_; }
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_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
* 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 mandatory_capabilities {
// clang-format off
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 optional_capabilities {0};
} // detail
} // mysql
} // boost
constexpr capabilities optional_capabilities{0};
} // namespace detail
} // namespace mysql
} // namespace boost
#endif

View File

@@ -8,9 +8,10 @@
#ifndef BOOST_MYSQL_DETAIL_PROTOCOL_COMMON_MESSAGES_HPP
#define BOOST_MYSQL_DETAIL_PROTOCOL_COMMON_MESSAGES_HPP
#include <boost/mysql/detail/protocol/serialization.hpp>
#include <boost/mysql/detail/protocol/constants.hpp>
#include <boost/mysql/collation.hpp>
#include <boost/mysql/detail/protocol/constants.hpp>
#include <boost/mysql/detail/protocol/serialization.hpp>
#include <tuple>
namespace boost {
@@ -26,10 +27,7 @@ struct packet_header
template <class Self, class Callable>
static void apply(Self& self, Callable&& cb)
{
std::forward<Callable>(cb)(
self.packet_size,
self.sequence_number
);
std::forward<Callable>(cb)(self.packet_size, self.sequence_number);
}
};
@@ -39,7 +37,7 @@ struct ok_packet
// header: int<1> header 0x00 or 0xFE the OK packet header
int_lenenc affected_rows;
int_lenenc last_insert_id;
std::uint16_t status_flags; // server_status_flags
std::uint16_t status_flags; // server_status_flags
std::uint16_t warnings;
// CLIENT_SESSION_TRACK: not implemented
string_lenenc info;
@@ -47,6 +45,7 @@ struct ok_packet
template <class Self, class Callable>
static void apply(Self& self, Callable&& cb)
{
// clang-format off
std::forward<Callable>(cb)(
self.affected_rows,
self.last_insert_id,
@@ -54,12 +53,13 @@ struct ok_packet
self.warnings,
self.info
);
// clang-format on
}
};
template <>
struct serialization_traits<ok_packet, serialization_tag::struct_with_fields> :
noop_serialize<ok_packet>
struct serialization_traits<ok_packet, serialization_tag::struct_with_fields>
: noop_serialize<ok_packet>
{
static inline errc deserialize_(deserialization_context& ctx, ok_packet& output) noexcept;
};
@@ -76,12 +76,14 @@ struct err_packet
template <class Self, class Callable>
static void apply(Self& self, Callable&& cb)
{
// clang-format off
std::forward<Callable>(cb)(
self.error_code,
self.sql_state_marker,
self.sql_state,
self.error_message
);
// clang-format on
}
};
@@ -90,21 +92,23 @@ static_assert(is_struct_with_fields<err_packet>(), "Bad!");
// col def
struct column_definition_packet
{
string_lenenc catalog; // always "def"
string_lenenc catalog; // always "def"
string_lenenc schema;
string_lenenc table; // virtual table
string_lenenc org_table; // physical table
string_lenenc name; // virtual column name
string_lenenc org_name; // physical column name
string_lenenc table; // virtual table
string_lenenc org_table; // physical table
string_lenenc name; // virtual column name
string_lenenc org_name; // physical column name
collation character_set;
std::uint32_t column_length; // maximum length of the field
protocol_field_type type; // type of the column as defined in enum_field_types
std::uint16_t flags; // Flags as defined in Column Definition Flags
std::uint8_t decimals; // max shown decimal digits. 0x00 for int/static strings; 0x1f for dynamic strings, double, float
std::uint32_t column_length; // maximum length of the field
protocol_field_type type; // type of the column as defined in enum_field_types
std::uint16_t flags; // Flags as defined in Column Definition Flags
std::uint8_t decimals; // max shown decimal digits. 0x00 for int/static strings; 0x1f for
// dynamic strings, double, float
template <class Self, class Callable>
static void apply(Self& self, Callable&& cb)
{
// clang-format off
std::forward<Callable>(cb)(
self.catalog,
self.schema,
@@ -118,14 +122,18 @@ struct column_definition_packet
self.flags,
self.decimals
);
// clang-format on
}
};
template <>
struct serialization_traits<column_definition_packet, serialization_tag::struct_with_fields> :
noop_serialize<column_definition_packet>
struct serialization_traits<column_definition_packet, serialization_tag::struct_with_fields>
: noop_serialize<column_definition_packet>
{
static inline errc deserialize_(deserialization_context& ctx, column_definition_packet& output) noexcept;
static inline errc deserialize_(
deserialization_context& ctx,
column_definition_packet& output
) noexcept;
};
// connection quit
@@ -134,16 +142,17 @@ struct quit_packet
static constexpr std::uint8_t command_id = 0x01;
template <class Self, class Callable>
static void apply(Self&, Callable&&) noexcept {}
static void apply(Self&, Callable&&) noexcept
{
}
};
// aux
inline error_code process_error_packet(deserialization_context& ctx, error_info& info);
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/protocol/impl/common_messages.ipp>

View File

@@ -8,8 +8,9 @@
#ifndef BOOST_MYSQL_DETAIL_PROTOCOL_CONSTANTS_HPP
#define BOOST_MYSQL_DETAIL_PROTOCOL_CONSTANTS_HPP
#include <boost/mysql/detail/protocol/protocol_types.hpp>
#include <boost/mysql/detail/auxiliar/make_string_view.hpp>
#include <boost/mysql/detail/protocol/protocol_types.hpp>
#include <cstddef>
namespace boost {
@@ -18,35 +19,34 @@ namespace detail {
enum class protocol_field_type : std::uint8_t
{
decimal = 0x00, // Apparently not sent
tiny = 0x01, // TINYINT
short_ = 0x02, // SMALLINT
long_ = 0x03, // INT
float_ = 0x04, // FLOAT
double_ = 0x05, // DOUBLE
null = 0x06, // Apparently not sent
timestamp = 0x07, // TIMESTAMP
longlong = 0x08, // BIGINT
int24 = 0x09, // MEDIUMINT
date = 0x0a, // DATE
time = 0x0b, // TIME
datetime = 0x0c, // DATETIME
year = 0x0d, // YEAR
varchar = 0x0f, // Apparently not sent
bit = 0x10, // BIT
newdecimal = 0xf6, // DECIMAL
enum_ = 0xf7, // Apparently not sent
set = 0xf8, // Apperently not sent
tiny_blob = 0xf9, // Apparently not sent
medium_blob = 0xfa,// Apparently not sent
long_blob = 0xfb, // Apparently not sent
blob = 0xfc, // Used for all TEXT and BLOB types
var_string = 0xfd, // Used for VARCHAR and VARBINARY
string = 0xfe, // Used for CHAR and BINARY, ENUM (enum flag set), SET (set flag set)
geometry = 0xff // GEOMETRY
decimal = 0x00, // Apparently not sent
tiny = 0x01, // TINYINT
short_ = 0x02, // SMALLINT
long_ = 0x03, // INT
float_ = 0x04, // FLOAT
double_ = 0x05, // DOUBLE
null = 0x06, // Apparently not sent
timestamp = 0x07, // TIMESTAMP
longlong = 0x08, // BIGINT
int24 = 0x09, // MEDIUMINT
date = 0x0a, // DATE
time = 0x0b, // TIME
datetime = 0x0c, // DATETIME
year = 0x0d, // YEAR
varchar = 0x0f, // Apparently not sent
bit = 0x10, // BIT
newdecimal = 0xf6, // DECIMAL
enum_ = 0xf7, // Apparently not sent
set = 0xf8, // Apperently not sent
tiny_blob = 0xf9, // Apparently not sent
medium_blob = 0xfa, // Apparently not sent
long_blob = 0xfb, // Apparently not sent
blob = 0xfc, // Used for all TEXT and BLOB types
var_string = 0xfd, // Used for VARCHAR and VARBINARY
string = 0xfe, // Used for CHAR and BINARY, ENUM (enum flag set), SET (set flag set)
geometry = 0xff // GEOMETRY
};
constexpr std::size_t MAX_PACKET_SIZE = 0xffffff;
constexpr std::size_t HEADER_SIZE = 4;
@@ -64,7 +64,7 @@ constexpr std::uint32_t SERVER_STATUS_METADATA_CHANGED = 1024;
constexpr std::uint32_t SERVER_QUERY_WAS_SLOW = 2048;
constexpr std::uint32_t SERVER_PS_OUT_PARAMS = 4096;
constexpr std::uint32_t SERVER_STATUS_IN_TRANS_READONLY = 8192;
constexpr std::uint32_t SERVER_SESSION_STATE_CHANGED = (1UL << 14) ;
constexpr std::uint32_t SERVER_SESSION_STATE_CHANGED = (1UL << 14);
// Packet type constants
constexpr std::uint8_t handshake_protocol_version_9 = 9;
@@ -79,24 +79,24 @@ constexpr boost::string_view fast_auth_complete_challenge = make_string_view("\3
// Column flags
namespace column_flags {
constexpr std::uint16_t not_null = 1; // Field can't be NULL.
constexpr std::uint16_t pri_key = 2; // Field is part of a primary key.
constexpr std::uint16_t unique_key = 4; // Field is part of a unique key.
constexpr std::uint16_t multiple_key = 8; // Field is part of a key.
constexpr std::uint16_t blob = 16; // Field is a blob.
constexpr std::uint16_t unsigned_ = 32; // Field is unsigned.
constexpr std::uint16_t zerofill = 64; // Field is zerofill.
constexpr std::uint16_t binary = 128; // Field is binary.
constexpr std::uint16_t enum_ = 256; // field is an enum
constexpr std::uint16_t not_null = 1; // Field can't be NULL.
constexpr std::uint16_t pri_key = 2; // Field is part of a primary key.
constexpr std::uint16_t unique_key = 4; // Field is part of a unique key.
constexpr std::uint16_t multiple_key = 8; // Field is part of a key.
constexpr std::uint16_t blob = 16; // Field is a blob.
constexpr std::uint16_t unsigned_ = 32; // Field is unsigned.
constexpr std::uint16_t zerofill = 64; // Field is zerofill.
constexpr std::uint16_t binary = 128; // Field is binary.
constexpr std::uint16_t enum_ = 256; // field is an enum
constexpr std::uint16_t auto_increment = 512; // field is a autoincrement field
constexpr std::uint16_t timestamp = 1024; // Field is a timestamp.
constexpr std::uint16_t set = 2048; // field is a set
constexpr std::uint16_t no_default_value = 4096; // Field doesn't have default value.
constexpr std::uint16_t timestamp = 1024; // Field is a timestamp.
constexpr std::uint16_t set = 2048; // field is a set
constexpr std::uint16_t no_default_value = 4096; // Field doesn't have default value.
constexpr std::uint16_t on_update_now = 8192; // Field is set to NOW on UPDATE.
constexpr std::uint16_t part_key = 16384; // Intern; Part of some key.
constexpr std::uint16_t num = 32768; // Field is num (for clients)
constexpr std::uint16_t part_key = 16384; // Intern; Part of some key.
constexpr std::uint16_t num = 32768; // Field is num (for clients)
} // column_flags
} // namespace column_flags
// Prepared statements
namespace cursor_types {
@@ -106,7 +106,7 @@ constexpr std::uint8_t read_only = 1;
constexpr std::uint8_t for_update = 2;
constexpr std::uint8_t scrollable = 4;
} // cursor_types
} // namespace cursor_types
// Text protocol deserialization constants
namespace textc {
@@ -116,24 +116,25 @@ constexpr unsigned max_decimals = 6u;
constexpr std::size_t year_sz = 4;
constexpr std::size_t month_sz = 2;
constexpr std::size_t day_sz = 2;
constexpr std::size_t hours_min_sz = 2; // in TIME, it may be longer
constexpr std::size_t hours_min_sz = 2; // in TIME, it may be longer
constexpr std::size_t mins_sz = 2;
constexpr std::size_t secs_sz = 2;
constexpr std::size_t date_sz = year_sz + month_sz + day_sz + 2; // delimiters
constexpr std::size_t time_min_sz = hours_min_sz + mins_sz + secs_sz + 2; // delimiters
constexpr std::size_t time_max_sz = time_min_sz + max_decimals + 3; // sign, period, hour extra character
constexpr std::size_t datetime_min_sz = date_sz + time_min_sz + 1; // delimiter
constexpr std::size_t datetime_max_sz = datetime_min_sz + max_decimals + 1; // period
constexpr std::size_t date_sz = year_sz + month_sz + day_sz + 2; // delimiters
constexpr std::size_t time_min_sz = hours_min_sz + mins_sz + secs_sz + 2; // delimiters
constexpr std::size_t time_max_sz =
time_min_sz + max_decimals + 3; // sign, period, hour extra character
constexpr std::size_t datetime_min_sz = date_sz + time_min_sz + 1; // delimiter
constexpr std::size_t datetime_max_sz = datetime_min_sz + max_decimals + 1; // period
constexpr unsigned time_max_hour = 838;
} // textc
} // namespace textc
// Binary protocol (de)serialization constants
namespace binc {
constexpr std::size_t length_sz = 1; // length byte, for date, datetime and time
constexpr std::size_t length_sz = 1; // length byte, for date, datetime and time
constexpr std::size_t year_sz = 2;
constexpr std::size_t month_sz = 1;
constexpr std::size_t date_day_sz = 1;
@@ -144,7 +145,7 @@ constexpr std::size_t secs_sz = 1;
constexpr std::size_t micros_sz = 4;
constexpr std::size_t time_sign_sz = 1;
constexpr std::size_t date_sz = year_sz + month_sz + date_day_sz; // does not include length
constexpr std::size_t date_sz = year_sz + month_sz + date_day_sz; // does not include length
constexpr std::size_t datetime_d_sz = date_sz;
constexpr std::size_t datetime_dhms_sz = datetime_d_sz + hours_sz + mins_sz + secs_sz;
@@ -153,9 +154,9 @@ constexpr std::size_t datetime_dhmsu_sz = datetime_dhms_sz + micros_sz;
constexpr std::size_t time_dhms_sz = time_sign_sz + time_days_sz + hours_sz + mins_sz + secs_sz;
constexpr std::size_t time_dhmsu_sz = time_dhms_sz + micros_sz;
constexpr std::size_t time_max_days = 34; // equivalent to the 839 hours, in the broken format
constexpr std::size_t time_max_days = 34; // equivalent to the 839 hours, in the broken format
} // binc
} // namespace binc
// Constants common to both protocols
constexpr unsigned max_year = 9999;
@@ -166,10 +167,8 @@ constexpr unsigned max_min = 59;
constexpr unsigned max_sec = 59;
constexpr unsigned max_micro = 999999;
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#endif

View File

@@ -11,9 +11,10 @@
// All these algorithms have been taken from:
// http://howardhinnant.github.io/date_algorithms.html
#include <cstdint>
#include <boost/config.hpp>
#include <cstdint>
namespace boost {
namespace mysql {
namespace detail {
@@ -29,9 +30,9 @@ BOOST_CXX14_CONSTEXPR inline bool is_valid(const year_month_day& ymd) noexcept;
BOOST_CXX14_CONSTEXPR inline int ymd_to_days(const year_month_day& ymd) noexcept;
BOOST_CXX14_CONSTEXPR inline year_month_day days_to_ymd(int num_days) noexcept;
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/protocol/impl/date.hpp>

View File

@@ -10,10 +10,12 @@
#include <boost/mysql/detail/protocol/capabilities.hpp>
#include <boost/mysql/error.hpp>
#include <boost/asio/buffer.hpp>
#include <cassert>
#include <cstdint>
#include <cstring>
#include <cassert>
namespace boost {
namespace mysql {
@@ -24,19 +26,35 @@ class deserialization_context
const std::uint8_t* first_;
const std::uint8_t* last_;
capabilities capabilities_;
public:
deserialization_context(const std::uint8_t* first, const std::uint8_t* last, capabilities caps) noexcept:
first_(first), last_(last), capabilities_(caps) { assert(last_ >= first_); };
deserialization_context(boost::asio::const_buffer buff, capabilities caps) noexcept:
deserialization_context(
static_cast<const std::uint8_t*>(buff.data()),
static_cast<const std::uint8_t*>(buff.data()) + buff.size(),
caps
) {};
deserialization_context(
const std::uint8_t* first,
const std::uint8_t* last,
capabilities caps
) noexcept
: first_(first), last_(last), capabilities_(caps)
{
assert(last_ >= first_);
};
deserialization_context(boost::asio::const_buffer buff, capabilities caps) noexcept
: deserialization_context(
static_cast<const std::uint8_t*>(buff.data()),
static_cast<const std::uint8_t*>(buff.data()) + buff.size(),
caps
){};
const std::uint8_t* first() const noexcept { return first_; }
const std::uint8_t* last() const noexcept { return last_; }
void set_first(const std::uint8_t* new_first) noexcept { first_ = new_first; assert(last_ >= first_); }
void advance(std::size_t sz) noexcept { first_ += sz; assert(last_ >= first_); }
void set_first(const std::uint8_t* new_first) noexcept
{
first_ = new_first;
assert(last_ >= first_);
}
void advance(std::size_t sz) noexcept
{
first_ += sz;
assert(last_ >= first_);
}
void rewind(std::size_t sz) noexcept { first_ -= sz; }
std::size_t size() const noexcept { return last_ - first_; }
bool empty() const noexcept { return last_ == first_; }
@@ -52,10 +70,8 @@ public:
}
};
}
}
}
} // namespace detail
} // namespace mysql
} // namespace boost
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_PROTOCOL_DESERIALIZATION_CONTEXT_HPP_ */

View File

@@ -12,6 +12,7 @@
#include <boost/mysql/error.hpp>
#include <boost/mysql/field_view.hpp>
#include <boost/mysql/metadata.hpp>
#include <cstdint>
#include <vector>
@@ -26,9 +27,9 @@ inline errc deserialize_binary_field(
field_view& output
);
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/protocol/impl/deserialize_binary_field.ipp>

View File

@@ -8,15 +8,16 @@
#ifndef BOOST_MYSQL_DETAIL_PROTOCOL_DESERIALIZE_ROW_HPP
#define BOOST_MYSQL_DETAIL_PROTOCOL_DESERIALIZE_ROW_HPP
#include <boost/mysql/detail/protocol/resultset_encoding.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/mysql/detail/protocol/capabilities.hpp>
#include <boost/mysql/detail/protocol/resultset_encoding.hpp>
#include <boost/mysql/detail/protocol/serialization_context.hpp>
#include <boost/mysql/resultset_base.hpp>
#include <boost/mysql/error.hpp>
#include <boost/mysql/field_view.hpp>
#include <vector>
#include <boost/mysql/resultset_base.hpp>
#include <boost/asio/buffer.hpp>
#include <vector>
namespace boost {
namespace mysql {
@@ -32,13 +33,12 @@ inline void deserialize_row(
error_code& err
);
inline void deserialize_row(
boost::asio::const_buffer read_message,
capabilities current_capabilities,
const std::uint8_t* buffer_first, // to store strings as offsets and allow buffer reallocation
resultset_base& result, // should be valid() and !complete()
std::vector<field_view>& output,
const std::uint8_t* buffer_first, // to store strings as offsets and allow buffer reallocation
resultset_base& result, // should be valid() and !complete()
std::vector<field_view>& output,
error_code& err,
error_info& info
);
@@ -48,16 +48,14 @@ inline void offsets_to_string_views(
const std::uint8_t* buffer_first
) noexcept
{
for (auto& f: fields)
for (auto& f : fields)
f.offset_to_string_view(buffer_first);
}
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/protocol/impl/deserialize_row.ipp>
#endif

View File

@@ -12,6 +12,7 @@
#include <boost/mysql/error.hpp>
#include <boost/mysql/field_view.hpp>
#include <boost/mysql/metadata.hpp>
#include <cstdint>
#include <vector>
@@ -26,9 +27,9 @@ inline errc deserialize_text_field(
field_view& output
);
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/protocol/impl/deserialize_text_field.ipp>

View File

@@ -8,8 +8,8 @@
#ifndef BOOST_MYSQL_DETAIL_PROTOCOL_HANDSHAKE_MESSAGES_HPP
#define BOOST_MYSQL_DETAIL_PROTOCOL_HANDSHAKE_MESSAGES_HPP
#include <boost/mysql/detail/protocol/serialization.hpp>
#include <boost/mysql/detail/auxiliar/static_string.hpp>
#include <boost/mysql/detail/protocol/serialization.hpp>
namespace boost {
namespace mysql {
@@ -23,15 +23,16 @@ struct handshake_packet
// int<1> protocol version Always 10
string_null server_version;
std::uint32_t connection_id;
auth_buffer_type auth_plugin_data; // not an actual protocol field, the merge of two fields
std::uint32_t capability_falgs; // merge of the two parts - not an actual field
std::uint8_t character_set; // default server a_protocol_character_set, only the lower 8-bits
std::uint16_t status_flags; // server_status_flags
auth_buffer_type auth_plugin_data; // not an actual protocol field, the merge of two fields
std::uint32_t capability_falgs; // merge of the two parts - not an actual field
std::uint8_t character_set; // default server a_protocol_character_set, only the lower 8-bits
std::uint16_t status_flags; // server_status_flags
string_null auth_plugin_name;
template <class Self, class Callable>
static void apply(Self& self, Callable&& cb)
{
// clang-format off
std::forward<Callable>(cb)(
self.server_version,
self.connection_id,
@@ -41,52 +42,60 @@ struct handshake_packet
self.status_flags,
self.auth_plugin_name
);
// clang-format on
}
};
template <>
struct serialization_traits<handshake_packet, serialization_tag::struct_with_fields> :
noop_serialize<handshake_packet>
struct serialization_traits<handshake_packet, serialization_tag::struct_with_fields>
: noop_serialize<handshake_packet>
{
static inline errc deserialize_(deserialization_context& ctx, handshake_packet& output) noexcept;
static inline errc deserialize_(
deserialization_context& ctx,
handshake_packet& output
) noexcept;
};
// response
struct handshake_response_packet
{
std::uint32_t client_flag; // capabilities
std::uint32_t client_flag; // capabilities
std::uint32_t max_packet_size;
std::uint8_t character_set;
// string[23] filler filler to the size of the handhshake response packet. All 0s.
string_null username;
string_lenenc auth_response; // we require CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA
string_null database; // only to be serialized if CLIENT_CONNECT_WITH_DB
string_null client_plugin_name; // we require CLIENT_PLUGIN_AUTH
string_lenenc auth_response; // we require CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA
string_null database; // only to be serialized if CLIENT_CONNECT_WITH_DB
string_null client_plugin_name; // we require CLIENT_PLUGIN_AUTH
// CLIENT_CONNECT_ATTRS: not implemented
template <class Self, class Callable>
static void apply(Self& self, Callable&& cb)
{
std::forward<Callable>(cb)(
self.client_flag,
self.max_packet_size,
self.character_set,
self.username,
self.auth_response,
self.database,
self.client_plugin_name
);
std::forward<Callable>(cb
)(self.client_flag,
self.max_packet_size,
self.character_set,
self.username,
self.auth_response,
self.database,
self.client_plugin_name);
}
};
template <>
struct serialization_traits<handshake_response_packet, serialization_tag::struct_with_fields> :
noop_deserialize<handshake_response_packet>
struct serialization_traits<handshake_response_packet, serialization_tag::struct_with_fields>
: noop_deserialize<handshake_response_packet>
{
static inline std::size_t get_size_(const serialization_context& ctx,
const handshake_response_packet& value) noexcept;
static inline void serialize_(serialization_context& ctx,
const handshake_response_packet& value) noexcept;
static inline std::size_t get_size_(
const serialization_context& ctx,
const handshake_response_packet& value
) noexcept;
static inline void serialize_(
serialization_context& ctx,
const handshake_response_packet& value
) noexcept;
};
// SSL request
@@ -100,12 +109,14 @@ struct ssl_request
template <class Self, class Callable>
static void apply(Self& self, Callable&& cb)
{
// clang-format off
std::forward<Callable>(cb)(
self.client_flag,
self.max_packet_size,
self.character_set,
self.filler
);
// clang-format on
}
};
@@ -118,10 +129,7 @@ struct auth_switch_request_packet
template <class Self, class Callable>
static void apply(Self& self, Callable&& cb)
{
std::forward<Callable>(cb)(
self.plugin_name,
self.auth_plugin_data
);
std::forward<Callable>(cb)(self.plugin_name, self.auth_plugin_data);
}
};
@@ -133,18 +141,18 @@ struct auth_switch_response_packet
template <class Self, class Callable>
static void apply(Self& self, Callable&& cb)
{
std::forward<Callable>(cb)(
self.auth_plugin_data
);
std::forward<Callable>(cb)(self.auth_plugin_data);
}
};
template <>
struct serialization_traits<auth_switch_request_packet, serialization_tag::struct_with_fields> :
noop_serialize<auth_switch_request_packet>
struct serialization_traits<auth_switch_request_packet, serialization_tag::struct_with_fields>
: noop_serialize<auth_switch_request_packet>
{
static inline errc deserialize_(deserialization_context& ctx,
auth_switch_request_packet& output) noexcept;
static inline errc deserialize_(
deserialization_context& ctx,
auth_switch_request_packet& output
) noexcept;
};
// more data (like auth switch request, but for the same plugin)
@@ -155,15 +163,13 @@ struct auth_more_data_packet
template <class Self, class Callable>
static void apply(Self& self, Callable&& cb)
{
std::forward<Callable>(cb)(
self.auth_plugin_data
);
std::forward<Callable>(cb)(self.auth_plugin_data);
}
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/protocol/impl/handshake_messages.ipp>

View File

@@ -20,23 +20,16 @@ namespace detail {
// Floating point types
template <class T>
void serialize_binary_float(
serialization_context& ctx,
T input
)
void serialize_binary_float(serialization_context& ctx, T input)
{
boost::endian::endian_store<T, sizeof(T),
boost::endian::order::little>(ctx.first(), input);
boost::endian::endian_store<T, sizeof(T), boost::endian::order::little>(ctx.first(), input);
ctx.advance(sizeof(T));
}
// Time types
// Does not add the length prefix byte
inline void serialize_binary_ymd(
serialization_context& ctx,
const year_month_day& ymd
) noexcept
inline void serialize_binary_ymd(serialization_context& ctx, const year_month_day& ymd) noexcept
{
assert(ymd.years >= 0 && ymd.years <= 0xffff);
serialize(
@@ -47,10 +40,7 @@ inline void serialize_binary_ymd(
);
}
inline void serialize_binary_date(
serialization_context& ctx,
const date& input
)
inline void serialize_binary_date(serialization_context& ctx, const date& input)
{
assert(input >= min_date && input <= max_date);
auto ymd = days_to_ymd(input.time_since_epoch().count());
@@ -59,10 +49,7 @@ inline void serialize_binary_date(
serialize_binary_ymd(ctx, ymd);
}
inline void serialize_binary_datetime(
serialization_context& ctx,
const datetime& input
)
inline void serialize_binary_datetime(serialization_context& ctx, const datetime& input)
{
assert(input >= min_datetime && input <= max_datetime);
@@ -87,10 +74,7 @@ inline void serialize_binary_datetime(
);
}
inline void serialize_binary_time(
serialization_context& ctx,
const time& input
)
inline void serialize_binary_time(serialization_context& ctx, const time& input)
{
// Break time
using namespace std::chrono;
@@ -114,54 +98,43 @@ inline void serialize_binary_time(
);
}
} // namespace detail
} // namespace mysql
} // namespace boost
} // detail
} // mysql
} // boost
inline std::size_t
boost::mysql::detail::serialization_traits<
boost::mysql::field_view,
boost::mysql::detail::serialization_tag::none
>::get_size_(
const serialization_context& ctx,
const field_view& input
) noexcept
inline std::size_t boost::mysql::detail::
serialization_traits<boost::mysql::field_view, boost::mysql::detail::serialization_tag::none>::
get_size_(const serialization_context& ctx, const field_view& input) noexcept
{
switch (input.kind())
{
case field_kind::null: return 0;
case field_kind::int64: return 8;
case field_kind::uint64: return 8;
case field_kind::string: return get_size(ctx, string_lenenc(input.get_string()));
case field_kind::float_: return 4;
case field_kind::double_: return 8;
case field_kind::date: return binc::date_sz + binc::length_sz;
case field_kind::datetime: return binc::datetime_dhmsu_sz + binc::length_sz;
case field_kind::time: return binc::time_dhmsu_sz + binc::length_sz;
case field_kind::null: return 0;
case field_kind::int64: return 8;
case field_kind::uint64: return 8;
case field_kind::string: return get_size(ctx, string_lenenc(input.get_string()));
case field_kind::float_: return 4;
case field_kind::double_: return 8;
case field_kind::date: return binc::date_sz + binc::length_sz;
case field_kind::datetime: return binc::datetime_dhmsu_sz + binc::length_sz;
case field_kind::time: return binc::time_dhmsu_sz + binc::length_sz;
}
}
inline void
boost::mysql::detail::serialization_traits<
boost::mysql::field_view,
boost::mysql::detail::serialization_tag::none
>::serialize_(
serialization_context& ctx,
const field_view& input
) noexcept
inline void boost::mysql::detail::
serialization_traits<boost::mysql::field_view, boost::mysql::detail::serialization_tag::none>::
serialize_(serialization_context& ctx, const field_view& input) noexcept
{
switch (input.kind())
{
case field_kind::null: break;
case field_kind::int64: serialize(ctx, input.get_int64()); break;
case field_kind::uint64: serialize(ctx, input.get_uint64()); break;
case field_kind::string: serialize(ctx, string_lenenc(input.get_string())); break;
case field_kind::float_: serialize_binary_float(ctx, input.get_float()); break;
case field_kind::double_: serialize_binary_float(ctx, input.get_double()); break;
case field_kind::date: serialize_binary_date(ctx, input.get_date()); break;
case field_kind::datetime: serialize_binary_datetime(ctx, input.get_datetime()); break;
case field_kind::time: serialize_binary_time(ctx, input.get_time()); break;
case field_kind::null: break;
case field_kind::int64: serialize(ctx, input.get_int64()); break;
case field_kind::uint64: serialize(ctx, input.get_uint64()); break;
case field_kind::string: serialize(ctx, string_lenenc(input.get_string())); break;
case field_kind::float_: serialize_binary_float(ctx, input.get_float()); break;
case field_kind::double_: serialize_binary_float(ctx, input.get_double()); break;
case field_kind::date: serialize_binary_date(ctx, input.get_date()); break;
case field_kind::datetime: serialize_binary_datetime(ctx, input.get_datetime()); break;
case field_kind::time: serialize_binary_time(ctx, input.get_time()); break;
}
}

View File

@@ -12,15 +12,10 @@
#include <boost/mysql/detail/protocol/common_messages.hpp>
inline boost::mysql::errc
boost::mysql::detail::serialization_traits<
inline boost::mysql::errc boost::mysql::detail::serialization_traits<
boost::mysql::detail::ok_packet,
boost::mysql::detail::serialization_tag::struct_with_fields
>::deserialize_(
deserialization_context& ctx,
ok_packet& output
) noexcept
boost::mysql::detail::serialization_tag::struct_with_fields>::
deserialize_(deserialization_context& ctx, ok_packet& output) noexcept
{
{
auto err = deserialize(
@@ -30,7 +25,7 @@ boost::mysql::detail::serialization_traits<
output.status_flags,
output.warnings
);
if (err == errc::ok && ctx.enough_size(1)) // message is optional, may be omitted
if (err == errc::ok && ctx.enough_size(1)) // message is optional, may be omitted
{
err = deserialize(ctx, output.info);
}
@@ -38,14 +33,10 @@ boost::mysql::detail::serialization_traits<
}
}
inline boost::mysql::errc
boost::mysql::detail::serialization_traits<
inline boost::mysql::errc boost::mysql::detail::serialization_traits<
boost::mysql::detail::column_definition_packet,
boost::mysql::detail::serialization_tag::struct_with_fields
>::deserialize_(
deserialization_context& ctx,
column_definition_packet& output
) noexcept
boost::mysql::detail::serialization_tag::struct_with_fields>::
deserialize_(deserialization_context& ctx, column_definition_packet& output) noexcept
{
int_lenenc length_of_fixed_fields;
std::uint16_t final_padding = 0;
@@ -67,12 +58,10 @@ boost::mysql::detail::serialization_traits<
);
}
inline boost::mysql::error_code boost::mysql::detail::process_error_packet(
deserialization_context& ctx,
error_info& info
)
inline boost::mysql::error_code
boost::mysql::detail::process_error_packet(deserialization_context& ctx, error_info& info)
{
err_packet error_packet {};
err_packet error_packet{};
auto code = deserialize_message(ctx, error_packet);
if (code)
return code;
@@ -80,5 +69,4 @@ inline boost::mysql::error_code boost::mysql::detail::process_error_packet(
return make_error_code(static_cast<errc>(error_packet.error_code));
}
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_PROTOCOL_IMPL_COMMON_MESSAGES_IPP_ */

View File

@@ -10,45 +10,34 @@
#pragma once
#include <boost/mysql/detail/protocol/date.hpp>
#include <boost/mysql/detail/protocol/constants.hpp>
#include <boost/mysql/detail/protocol/date.hpp>
#include <cassert>
namespace boost {
namespace mysql {
namespace detail {
constexpr bool is_leap(int y) noexcept
{
return y % 4 == 0 && (y % 100 != 0 || y % 400 == 0);
}
constexpr bool is_leap(int y) noexcept { return y % 4 == 0 && (y % 100 != 0 || y % 400 == 0); }
BOOST_CXX14_CONSTEXPR inline unsigned last_month_day(int y, unsigned m) noexcept
{
constexpr unsigned char a [] =
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
return m != 2 || !is_leap(y) ? a[m-1] : 29u;
constexpr unsigned char a[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
return m != 2 || !is_leap(y) ? a[m - 1] : 29u;
}
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
BOOST_CXX14_CONSTEXPR inline bool boost::mysql::detail::is_valid(
const year_month_day& ymd
) noexcept
BOOST_CXX14_CONSTEXPR inline bool boost::mysql::detail::is_valid(const year_month_day& ymd) noexcept
{
return
ymd.years >= 0 &&
ymd.years <= static_cast<int>(max_year) &&
ymd.month > 0 &&
ymd.month <= max_month &&
ymd.day > 0 &&
ymd.day <= last_month_day(ymd.years, ymd.month);
return ymd.years >= 0 && ymd.years <= static_cast<int>(max_year) && ymd.month > 0 &&
ymd.month <= max_month && ymd.day > 0 && ymd.day <= last_month_day(ymd.years, ymd.month);
}
BOOST_CXX14_CONSTEXPR inline int boost::mysql::detail::ymd_to_days(
const year_month_day& ymd
BOOST_CXX14_CONSTEXPR inline int boost::mysql::detail::ymd_to_days(const year_month_day& ymd
) noexcept
{
assert(is_valid(ymd));
@@ -56,32 +45,27 @@ BOOST_CXX14_CONSTEXPR inline int boost::mysql::detail::ymd_to_days(
const int m = ymd.month;
const int d = ymd.day;
y -= m <= 2;
const int era = (y >= 0 ? y : y-399) / 400;
const unsigned yoe = static_cast<unsigned>(y - era * 400); // [0, 399]
const unsigned doy = (153*(m + (m > 2 ? -3 : 9)) + 2)/5 + d-1; // [0, 365]
const unsigned doe = yoe * 365 + yoe/4 - yoe/100 + doy; // [0, 146096]
const int era = (y >= 0 ? y : y - 399) / 400;
const unsigned yoe = static_cast<unsigned>(y - era * 400); // [0, 399]
const unsigned doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1; // [0, 365]
const unsigned doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; // [0, 146096]
return era * 146097 + static_cast<int>(doe) - 719468;
}
BOOST_CXX14_CONSTEXPR inline boost::mysql::detail::year_month_day
boost::mysql::detail::days_to_ymd(
BOOST_CXX14_CONSTEXPR inline boost::mysql::detail::year_month_day boost::mysql::detail::days_to_ymd(
int num_days
) noexcept
{
num_days += 719468;
const int era = (num_days >= 0 ? num_days : num_days - 146096) / 146097;
const unsigned doe = static_cast<unsigned>(num_days - era * 146097); // [0, 146096]
const unsigned yoe = (doe - doe/1460 + doe/36524 - doe/146096) / 365; // [0, 399]
const unsigned doe = static_cast<unsigned>(num_days - era * 146097); // [0, 146096]
const unsigned yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365; // [0, 399]
const int y = static_cast<int>(yoe) + era * 400;
const unsigned doy = doe - (365*yoe + yoe/4 - yoe/100); // [0, 365]
const unsigned mp = (5*doy + 2)/153; // [0, 11]
const unsigned d = doy - (153*mp+2)/5 + 1; // [1, 31]
const unsigned m = mp + (mp < 10 ? 3 : -9); // [1, 12]
const unsigned doy = doe - (365 * yoe + yoe / 4 - yoe / 100); // [0, 365]
const unsigned mp = (5 * doy + 2) / 153; // [0, 11]
const unsigned d = doy - (153 * mp + 2) / 5 + 1; // [1, 31]
const unsigned m = mp + (mp < 10 ? 3 : -9); // [1, 12]
return year_month_day{y + (m <= 2), m, d};
}
#endif

View File

@@ -11,11 +11,12 @@
#pragma once
#include <boost/mysql/detail/auxiliar/string_view_offset.hpp>
#include <boost/mysql/detail/protocol/deserialize_binary_field.hpp>
#include <boost/mysql/detail/protocol/serialization.hpp>
#include <boost/mysql/detail/protocol/bit_deserialization.hpp>
#include <boost/mysql/detail/protocol/constants.hpp>
#include <boost/mysql/detail/protocol/date.hpp>
#include <boost/mysql/detail/protocol/bit_deserialization.hpp>
#include <boost/mysql/detail/protocol/deserialize_binary_field.hpp>
#include <boost/mysql/detail/protocol/serialization.hpp>
#include <cstddef>
namespace boost {
@@ -39,10 +40,7 @@ inline errc deserialize_binary_field_string(
// ints
template <class TargetType, class DeserializableType>
errc deserialize_binary_field_int_impl(
deserialization_context& ctx,
field_view& output
) noexcept
errc deserialize_binary_field_int_impl(deserialization_context& ctx, field_view& output) noexcept
{
DeserializableType deser;
auto err = deserialize(ctx, deser);
@@ -52,50 +50,45 @@ errc deserialize_binary_field_int_impl(
return errc::ok;
}
template <
class DeserializableTypeUnsigned,
class DeserializableTypeSigned
>
template <class DeserializableTypeUnsigned, class DeserializableTypeSigned>
errc deserialize_binary_field_int(
const metadata& meta,
deserialization_context& ctx,
field_view& output
) noexcept
{
return meta.is_unsigned() ?
deserialize_binary_field_int_impl<
std::uint64_t, DeserializableTypeUnsigned>(ctx, output) :
deserialize_binary_field_int_impl<
std::int64_t, DeserializableTypeSigned>(ctx, output);
return meta.is_unsigned()
? deserialize_binary_field_int_impl<std::uint64_t, DeserializableTypeUnsigned>(
ctx,
output
)
: deserialize_binary_field_int_impl<std::int64_t, DeserializableTypeSigned>(
ctx,
output
);
}
// Bits. These come as a binary value between 1 and 8 bytes,
// packed in a string
inline errc deserialize_binary_field_bit(
deserialization_context& ctx,
field_view& output
) noexcept
inline errc deserialize_binary_field_bit(deserialization_context& ctx, field_view& output) noexcept
{
string_lenenc buffer;
auto err = deserialize(ctx, buffer);
if (err != errc::ok) return err;
if (err != errc::ok)
return err;
return deserialize_bit(buffer.value, output);
}
// Floats
template <class T>
errc deserialize_binary_field_float(
deserialization_context& ctx,
field_view& output
) noexcept
errc deserialize_binary_field_float(deserialization_context& ctx, field_view& output) noexcept
{
// Size check
if (!ctx.enough_size(sizeof(T)))
return errc::incomplete_message;
// Endianness conversion. Boost.Endian support for floats start at 1.71
T v = boost::endian::endian_load<T, sizeof(T),
boost::endian::order::little>(ctx.first());
T v = boost::endian::endian_load<T, sizeof(T), boost::endian::order::little>(ctx.first());
// Nans and infs not allowed in SQL
if (std::isnan(v) || std::isinf(v))
@@ -108,10 +101,7 @@ errc deserialize_binary_field_float(
}
// Time types
inline errc deserialize_binary_ymd(
deserialization_context& ctx,
year_month_day& output
)
inline errc deserialize_binary_ymd(deserialization_context& ctx, year_month_day& output)
{
std::uint16_t year;
std::uint8_t month;
@@ -123,22 +113,17 @@ inline errc deserialize_binary_ymd(
return err;
// Range check
if (year > max_year ||
month > max_month ||
day > max_day)
if (year > max_year || month > max_month || day > max_day)
{
return errc::protocol_value_error;
}
output = year_month_day {year, month, day};
output = year_month_day{year, month, day};
return errc::ok;
}
inline errc deserialize_binary_field_date(
deserialization_context& ctx,
field_view& output
) noexcept
inline errc deserialize_binary_field_date(deserialization_context& ctx, field_view& output) noexcept
{
// Deserialize length
std::uint8_t length;
@@ -171,10 +156,8 @@ inline errc deserialize_binary_field_date(
return errc::ok;
}
inline errc deserialize_binary_field_datetime(
deserialization_context& ctx,
field_view& output
) noexcept
inline errc
deserialize_binary_field_datetime(deserialization_context& ctx, field_view& output) noexcept
{
using namespace binc;
@@ -186,7 +169,7 @@ inline errc deserialize_binary_field_datetime(
// Deserialize date. If the DATETIME does not contain these values,
// they are supposed to be zero (invalid date)
year_month_day ymd {};
year_month_day ymd{};
if (length >= datetime_d_sz)
{
err = deserialize_binary_ymd(ctx, ymd);
@@ -219,10 +202,7 @@ inline errc deserialize_binary_field_datetime(
// Validity check. We make this check before
// the invalid date check to make invalid dates with incorrect
// hours/mins/secs/micros fail
if (hours > max_hour ||
minutes > max_min ||
seconds > max_sec ||
micros > max_micro)
if (hours > max_hour || minutes > max_min || seconds > max_sec || micros > max_micro)
{
return errc::protocol_value_error;
}
@@ -237,20 +217,14 @@ inline errc deserialize_binary_field_datetime(
}
// Compose the final datetime. Doing time of day and date separately to avoid overflow
date d (days(ymd_to_days(ymd)));
auto time_of_day =
std::chrono::hours(hours) +
std::chrono::minutes(minutes) +
std::chrono::seconds(seconds) +
std::chrono::microseconds(micros);
date d(days(ymd_to_days(ymd)));
auto time_of_day = std::chrono::hours(hours) + std::chrono::minutes(minutes) +
std::chrono::seconds(seconds) + std::chrono::microseconds(micros);
output = field_view(d + time_of_day);
return errc::ok;
}
inline errc deserialize_binary_field_time(
deserialization_context& ctx,
field_view& output
) noexcept
inline errc deserialize_binary_field_time(deserialization_context& ctx, field_view& output) noexcept
{
using namespace binc;
@@ -271,14 +245,7 @@ inline errc deserialize_binary_field_time(
// Sign, days, hours, minutes, seconds
if (length >= time_dhms_sz)
{
err = deserialize(
ctx,
is_negative,
num_days,
hours,
minutes,
seconds
);
err = deserialize(ctx, is_negative, num_days, hours, minutes, seconds);
if (err != errc::ok)
return err;
}
@@ -292,30 +259,24 @@ inline errc deserialize_binary_field_time(
}
// Range check
if (num_days > time_max_days ||
hours > max_hour ||
minutes > max_min ||
seconds > max_sec ||
if (num_days > time_max_days || hours > max_hour || minutes > max_min || seconds > max_sec ||
microseconds > max_micro)
{
return errc::protocol_value_error;
}
// Compose the final time
output = field_view(time((is_negative ? -1 : 1) * (
days(num_days) +
std::chrono::hours(hours) +
std::chrono::minutes(minutes) +
std::chrono::seconds(seconds) +
std::chrono::microseconds(microseconds)
)));
output = field_view(time(
(is_negative ? -1 : 1) *
(days(num_days) + std::chrono::hours(hours) + std::chrono::minutes(minutes) +
std::chrono::seconds(seconds) + std::chrono::microseconds(microseconds))
));
return errc::ok;
}
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
inline boost::mysql::errc boost::mysql::detail::deserialize_binary_field(
deserialization_context& ctx,
@@ -336,19 +297,13 @@ inline boost::mysql::errc boost::mysql::detail::deserialize_binary_field(
return deserialize_binary_field_int<std::uint32_t, std::int32_t>(meta, ctx, output);
case protocol_field_type::longlong:
return deserialize_binary_field_int<std::uint64_t, std::int64_t>(meta, ctx, output);
case protocol_field_type::bit:
return deserialize_binary_field_bit(ctx, output);
case protocol_field_type::float_:
return deserialize_binary_field_float<float>(ctx, output);
case protocol_field_type::double_:
return deserialize_binary_field_float<double>(ctx, output);
case protocol_field_type::bit: return deserialize_binary_field_bit(ctx, output);
case protocol_field_type::float_: return deserialize_binary_field_float<float>(ctx, output);
case protocol_field_type::double_: return deserialize_binary_field_float<double>(ctx, output);
case protocol_field_type::timestamp:
case protocol_field_type::datetime:
return deserialize_binary_field_datetime(ctx, output);
case protocol_field_type::date:
return deserialize_binary_field_date(ctx, output);
case protocol_field_type::time:
return deserialize_binary_field_time(ctx, output);
case protocol_field_type::datetime: return deserialize_binary_field_datetime(ctx, output);
case protocol_field_type::date: return deserialize_binary_field_date(ctx, output);
case protocol_field_type::time: return deserialize_binary_field_time(ctx, output);
// True string types
case protocol_field_type::varchar:
case protocol_field_type::var_string:
@@ -363,8 +318,7 @@ inline boost::mysql::errc boost::mysql::detail::deserialize_binary_field(
case protocol_field_type::decimal:
case protocol_field_type::newdecimal:
case protocol_field_type::geometry:
default:
return deserialize_binary_field_string(ctx, output, buffer_first);
default: return deserialize_binary_field_string(ctx, output, buffer_first);
}
}

View File

@@ -10,19 +10,17 @@
#pragma once
#include <boost/mysql/detail/protocol/deserialize_binary_field.hpp>
#include <boost/mysql/detail/protocol/deserialize_row.hpp>
#include <boost/mysql/detail/protocol/deserialize_text_field.hpp>
#include <boost/mysql/detail/protocol/null_bitmap_traits.hpp>
#include <boost/mysql/detail/protocol/deserialize_binary_field.hpp>
#include <boost/mysql/detail/protocol/serialization.hpp>
namespace boost {
namespace mysql {
namespace detail {
inline bool is_next_field_null(
const deserialization_context& ctx
)
inline bool is_next_field_null(const deserialization_context& ctx)
{
if (!ctx.enough_size(1))
return false;
@@ -54,7 +52,12 @@ inline error_code deserialize_text_row(
errc err = deserialize(ctx, value_str);
if (err != errc::ok)
return make_error_code(err);
err = deserialize_text_field(value_str.value, fields[i], buffer_first, output[old_size + i]);
err = deserialize_text_field(
value_str.value,
fields[i],
buffer_first,
output[old_size + i]
);
if (err != errc::ok)
return make_error_code(err);
}
@@ -64,7 +67,6 @@ inline error_code deserialize_text_row(
return error_code();
}
inline error_code deserialize_binary_row(
deserialization_context& ctx,
const std::vector<metadata>& meta,
@@ -84,7 +86,7 @@ inline error_code deserialize_binary_row(
output.resize(old_size + num_fields);
// Null bitmap
null_bitmap_traits null_bitmap (binary_row_null_bitmap_offset, num_fields);
null_bitmap_traits null_bitmap(binary_row_null_bitmap_offset, num_fields);
const std::uint8_t* null_bitmap_begin = ctx.first();
if (!ctx.enough_size(null_bitmap.byte_count()))
return make_error_code(errc::incomplete_message);
@@ -112,9 +114,9 @@ inline error_code deserialize_binary_row(
return error_code();
}
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
void boost::mysql::detail::deserialize_row(
resultset_encoding encoding,
@@ -125,17 +127,17 @@ void boost::mysql::detail::deserialize_row(
error_code& err
)
{
err = encoding == detail::resultset_encoding::text ?
deserialize_text_row(ctx, meta, buffer_first, output) :
deserialize_binary_row(ctx, meta, buffer_first, output);
err = encoding == detail::resultset_encoding::text
? deserialize_text_row(ctx, meta, buffer_first, output)
: deserialize_binary_row(ctx, meta, buffer_first, output);
}
void boost::mysql::detail::deserialize_row(
boost::asio::const_buffer read_message,
capabilities current_capabilities,
const std::uint8_t* buffer_first, // to store strings as offsets and allow buffer reallocation
const std::uint8_t* buffer_first, // to store strings as offsets and allow buffer reallocation
resultset_base& result,
std::vector<field_view>& output,
std::vector<field_view>& output,
error_code& err,
error_info& info
)
@@ -145,7 +147,7 @@ void boost::mysql::detail::deserialize_row(
// Message type: row, error or eof?
std::uint8_t msg_type = 0;
deserialization_context ctx (read_message, current_capabilities);
deserialization_context ctx(read_message, current_capabilities);
err = make_error_code(deserialize(ctx, msg_type));
if (err)
return;
@@ -166,7 +168,7 @@ void boost::mysql::detail::deserialize_row(
else
{
// An actual row
ctx.rewind(1); // keep the 'message type' byte, as it is part of the actual message
ctx.rewind(1); // keep the 'message type' byte, as it is part of the actual message
deserialize_row(result.encoding(), ctx, result.meta(), buffer_first, output, err);
}
}

View File

@@ -10,21 +10,23 @@
#pragma once
#include <boost/mysql/detail/protocol/deserialize_text_field.hpp>
#include <boost/mysql/detail/auxiliar/string_view_offset.hpp>
#include <boost/mysql/detail/protocol/bit_deserialization.hpp>
#include <boost/mysql/detail/protocol/constants.hpp>
#include <boost/mysql/detail/protocol/date.hpp>
#include <boost/mysql/detail/protocol/bit_deserialization.hpp>
#include <boost/mysql/detail/auxiliar/string_view_offset.hpp>
#include <boost/mysql/detail/protocol/deserialize_text_field.hpp>
#include <boost/config.hpp>
#include <boost/lexical_cast/try_lexical_convert.hpp>
#include <cstdlib>
#include <cstddef>
#include <cmath>
#include <cstddef>
#include <cstdlib>
#include <type_traits>
#ifdef BOOST_MSVC
#pragma warning( push )
#pragma warning( disable : 4996 ) // MSVC doesn't like my sscanf's
#pragma warning(push)
#pragma warning(disable : 4996) // MSVC doesn't like my sscanf's
#endif
namespace boost {
@@ -33,10 +35,7 @@ namespace detail {
// Integers
template <class T>
errc deserialize_text_value_int_impl(
boost::string_view from,
field_view& to
) noexcept
errc deserialize_text_value_int_impl(boost::string_view from, field_view& to) noexcept
{
T v;
bool ok = boost::conversion::try_lexical_convert(from.data(), from.size(), v);
@@ -46,27 +45,20 @@ errc deserialize_text_value_int_impl(
return errc::ok;
}
inline errc deserialize_text_value_int(
boost::string_view from,
field_view& to,
const metadata& meta
) noexcept
inline errc
deserialize_text_value_int(boost::string_view from, field_view& to, const metadata& meta) noexcept
{
return meta.is_unsigned() ?
deserialize_text_value_int_impl<std::uint64_t>(from, to) :
deserialize_text_value_int_impl<std::int64_t>(from, to);
return meta.is_unsigned() ? deserialize_text_value_int_impl<std::uint64_t>(from, to)
: deserialize_text_value_int_impl<std::int64_t>(from, to);
}
// Floating points
template <class T>
errc deserialize_text_value_float(
boost::string_view from,
field_view& to
) noexcept
errc deserialize_text_value_float(boost::string_view from, field_view& to) noexcept
{
T val;
bool ok = boost::conversion::try_lexical_convert(from.data(), from.size(), val);
if (!ok || std::isnan(val) || std::isinf(val)) // SQL std forbids these values
if (!ok || std::isnan(val) || std::isinf(val)) // SQL std forbids these values
return errc::protocol_value_error;
to = field_view(val);
return errc::ok;
@@ -96,10 +88,7 @@ inline unsigned compute_micros(unsigned parsed_micros, unsigned decimals) noexce
return parsed_micros * static_cast<unsigned>(std::pow(10, textc::max_decimals - decimals));
}
inline errc deserialize_text_ymd(
boost::string_view from,
year_month_day& to
)
inline errc deserialize_text_ymd(boost::string_view from, year_month_day& to)
{
using namespace textc;
@@ -108,7 +97,7 @@ inline errc deserialize_text_ymd(
return errc::protocol_value_error;
// Copy to a NULL-terminated buffer
char buffer [date_sz + 1] {};
char buffer[date_sz + 1]{};
std::memcpy(buffer, from.data(), from.size());
// Parse individual components
@@ -126,13 +115,10 @@ inline errc deserialize_text_ymd(
return errc::ok;
}
inline errc deserialize_text_value_date(
boost::string_view from,
field_view& to
) noexcept
inline errc deserialize_text_value_date(boost::string_view from, field_view& to) noexcept
{
// Deserialize ymd
year_month_day ymd {};
year_month_day ymd{};
auto err = deserialize_text_ymd(from, ymd);
if (err != errc::ok)
return err;
@@ -167,14 +153,14 @@ inline errc deserialize_text_value_datetime(
return errc::protocol_value_error;
// Deserialize date part
year_month_day ymd {};
year_month_day ymd{};
auto err = deserialize_text_ymd(from.substr(0, date_sz), ymd);
if (err != errc::ok)
return err;
// Copy to NULL-terminated buffer
constexpr std::size_t datetime_time_first = date_sz + 1; // date + space
char buffer [datetime_max_sz - datetime_time_first + 1] {};
constexpr std::size_t datetime_time_first = date_sz + 1; // date + space
char buffer[datetime_max_sz - datetime_time_first + 1]{};
std::memcpy(buffer, from.data() + datetime_time_first, from.size() - datetime_time_first);
// Parse
@@ -183,16 +169,15 @@ inline errc deserialize_text_value_datetime(
char extra_char;
if (decimals)
{
int parsed = sscanf(buffer, "%2u:%2u:%2u.%6u%c",
&hours, &minutes, &seconds, &micros, &extra_char);
int parsed =
sscanf(buffer, "%2u:%2u:%2u.%6u%c", &hours, &minutes, &seconds, &micros, &extra_char);
if (parsed != 4)
return errc::protocol_value_error;
micros = compute_micros(micros, decimals);
}
else
{
int parsed = sscanf(buffer, "%2u:%2u:%2u%c",
&hours, &minutes, &seconds, &extra_char);
int parsed = sscanf(buffer, "%2u:%2u:%2u%c", &hours, &minutes, &seconds, &extra_char);
if (parsed != 3)
return errc::protocol_value_error;
}
@@ -200,10 +185,7 @@ inline errc deserialize_text_value_datetime(
// Validity check. We make this check before
// the invalid date check to make invalid dates with incorrect
// hours/mins/secs/micros fail
if (hours > max_hour ||
minutes > max_min ||
seconds > max_sec ||
micros > max_micro)
if (hours > max_hour || minutes > max_min || seconds > max_sec || micros > max_micro)
{
return errc::protocol_value_error;
}
@@ -217,21 +199,15 @@ inline errc deserialize_text_value_datetime(
}
// Sum it up. Doing time of day independently to prevent overflow
date d (days(ymd_to_days(ymd)));
auto time_of_day =
std::chrono::hours(hours) +
std::chrono::minutes(minutes) +
std::chrono::seconds(seconds) +
std::chrono::microseconds(micros);
date d(days(ymd_to_days(ymd)));
auto time_of_day = std::chrono::hours(hours) + std::chrono::minutes(minutes) +
std::chrono::seconds(seconds) + std::chrono::microseconds(micros);
to = field_view(d + time_of_day);
return errc::ok;
}
inline errc deserialize_text_value_time(
boost::string_view from,
field_view& to,
const metadata& meta
) noexcept
inline errc
deserialize_text_value_time(boost::string_view from, field_view& to, const metadata& meta) noexcept
{
using namespace textc;
@@ -240,13 +216,13 @@ inline errc deserialize_text_value_time(
// size check
std::size_t actual_min_size = time_min_sz + (decimals ? decimals + 1 : 0);
std::size_t actual_max_size = actual_min_size + 1 + 1; // hour extra character and sign
std::size_t actual_max_size = actual_min_size + 1 + 1; // hour extra character and sign
assert(actual_max_size <= time_max_sz);
if (from.size() < actual_min_size || from.size() > actual_max_size)
return errc::protocol_value_error;
// Copy to NULL-terminated buffer
char buffer [time_max_sz + 1] {};
char buffer[time_max_sz + 1]{};
memcpy(buffer, from.data(), from.size());
// Sign
@@ -259,7 +235,8 @@ inline errc deserialize_text_value_time(
char extra_char;
if (decimals)
{
int parsed = sscanf(first, "%3u:%2u:%2u.%6u%c", &hours, &minutes, &seconds, &micros, &extra_char);
int parsed =
sscanf(first, "%3u:%2u:%2u.%6u%c", &hours, &minutes, &seconds, &micros, &extra_char);
if (parsed != 4)
return errc::protocol_value_error;
micros = compute_micros(micros, decimals);
@@ -272,20 +249,14 @@ inline errc deserialize_text_value_time(
}
// Range check
if (hours > time_max_hour ||
minutes > max_min ||
seconds > max_sec ||
micros > max_micro)
if (hours > time_max_hour || minutes > max_min || seconds > max_sec || micros > max_micro)
{
return errc::protocol_value_error;
}
// Sum it
auto res =
std::chrono::hours(hours) +
std::chrono::minutes(minutes) +
std::chrono::seconds(seconds) +
std::chrono::microseconds(micros);
auto res = std::chrono::hours(hours) + std::chrono::minutes(minutes) +
std::chrono::seconds(seconds) + std::chrono::microseconds(micros);
if (is_negative)
{
res = -res;
@@ -296,9 +267,9 @@ inline errc deserialize_text_value_time(
return errc::ok;
}
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
inline boost::mysql::errc boost::mysql::detail::deserialize_text_field(
boost::string_view from,
@@ -314,21 +285,14 @@ inline boost::mysql::errc boost::mysql::detail::deserialize_text_field(
case protocol_field_type::int24:
case protocol_field_type::long_:
case protocol_field_type::year:
case protocol_field_type::longlong:
return deserialize_text_value_int(from, output, meta);
case protocol_field_type::bit:
return deserialize_bit(from, output);
case protocol_field_type::float_:
return deserialize_text_value_float<float>(from, output);
case protocol_field_type::double_:
return deserialize_text_value_float<double>(from, output);
case protocol_field_type::longlong: return deserialize_text_value_int(from, output, meta);
case protocol_field_type::bit: return deserialize_bit(from, output);
case protocol_field_type::float_: return deserialize_text_value_float<float>(from, output);
case protocol_field_type::double_: return deserialize_text_value_float<double>(from, output);
case protocol_field_type::timestamp:
case protocol_field_type::datetime:
return deserialize_text_value_datetime(from, output, meta);
case protocol_field_type::date:
return deserialize_text_value_date(from, output);
case protocol_field_type::time:
return deserialize_text_value_time(from, output, meta);
case protocol_field_type::datetime: return deserialize_text_value_datetime(from, output, meta);
case protocol_field_type::date: return deserialize_text_value_date(from, output);
case protocol_field_type::time: return deserialize_text_value_time(from, output, meta);
// True string types
case protocol_field_type::varchar:
case protocol_field_type::var_string:
@@ -343,14 +307,12 @@ inline boost::mysql::errc boost::mysql::detail::deserialize_text_field(
case protocol_field_type::decimal:
case protocol_field_type::newdecimal:
case protocol_field_type::geometry:
default:
return deserialize_text_value_string(from, output, buffer_first);
default: return deserialize_text_value_string(from, output, buffer_first);
}
}
#ifdef BOOST_MSVC
#pragma warning( pop )
#pragma warning(pop)
#endif
#endif

View File

@@ -12,21 +12,16 @@
#include <boost/mysql/detail/protocol/handshake_messages.hpp>
inline boost::mysql::errc
boost::mysql::detail::serialization_traits<
inline boost::mysql::errc boost::mysql::detail::serialization_traits<
boost::mysql::detail::handshake_packet,
boost::mysql::detail::serialization_tag::struct_with_fields
>::deserialize_(
deserialization_context& ctx,
handshake_packet& output
) noexcept
boost::mysql::detail::serialization_tag::struct_with_fields>::
deserialize_(deserialization_context& ctx, handshake_packet& output) noexcept
{
constexpr std::uint8_t auth1_length = 8;
string_fixed<auth1_length> auth_plugin_data_part_1;
string_fixed<2> capability_flags_low;
string_fixed<2> capability_flags_high;
std::uint8_t filler; // should be 0
std::uint8_t filler; // should be 0
std::uint8_t auth_plugin_data_len = 0;
string_fixed<10> reserved;
@@ -51,22 +46,18 @@ boost::mysql::detail::serialization_traits<
boost::endian::little_to_native_inplace(output.capability_falgs);
// Check minimum server capabilities to deserialize this frame
capabilities cap (output.capability_falgs);
capabilities cap(output.capability_falgs);
if (!cap.has(CLIENT_PLUGIN_AUTH))
return errc::server_unsupported;
// Deserialize following fields
err = deserialize(
ctx,
auth_plugin_data_len,
reserved
);
err = deserialize(ctx, auth_plugin_data_len, reserved);
if (err != errc::ok)
return err;
// Auth plugin data, second part
auto auth2_length = static_cast<std::uint8_t>(
std::max(13, auth_plugin_data_len - auth1_length));
auto auth2_length =
static_cast<std::uint8_t>(std::max(13, auth_plugin_data_len - auth1_length));
const void* auth2_data = ctx.first();
if (!ctx.enough_size(auth2_length))
return errc::incomplete_message;
@@ -80,28 +71,28 @@ boost::mysql::detail::serialization_traits<
// Compose auth_plugin_data
output.auth_plugin_data.clear();
output.auth_plugin_data.append(auth_plugin_data_part_1.data(), auth1_length);
output.auth_plugin_data.append(auth2_data, auth2_length - 1); // discard an extra trailing NULL byte
output.auth_plugin_data.append(
auth2_data,
auth2_length - 1
); // discard an extra trailing NULL byte
return errc::ok;
}
std::size_t
boost::mysql::detail::serialization_traits<
std::size_t boost::mysql::detail::serialization_traits<
boost::mysql::detail::handshake_response_packet,
boost::mysql::detail::serialization_tag::struct_with_fields
>::get_size_(
const serialization_context& ctx,
const handshake_response_packet& value
) noexcept
boost::mysql::detail::serialization_tag::struct_with_fields>::
get_size_(const serialization_context& ctx, const handshake_response_packet& value) noexcept
{
std::size_t res = get_size(
ctx,
value.client_flag,
value.max_packet_size,
value.character_set,
value.username,
value.auth_response
) + 23; // filler
ctx,
value.client_flag,
value.max_packet_size,
value.character_set,
value.username,
value.auth_response
) +
23; // filler
if (ctx.get_capabilities().has(CLIENT_CONNECT_WITH_DB))
{
res += get_size(ctx, value.database);
@@ -110,14 +101,10 @@ boost::mysql::detail::serialization_traits<
return res;
}
inline void
boost::mysql::detail::serialization_traits<
inline void boost::mysql::detail::serialization_traits<
boost::mysql::detail::handshake_response_packet,
boost::mysql::detail::serialization_tag::struct_with_fields
>::serialize_(
serialization_context& ctx,
const handshake_response_packet& value
) noexcept
boost::mysql::detail::serialization_tag::struct_with_fields>::
serialize_(serialization_context& ctx, const handshake_response_packet& value) noexcept
{
serialize(
ctx,
@@ -136,14 +123,10 @@ boost::mysql::detail::serialization_traits<
serialize(ctx, value.client_plugin_name);
}
inline boost::mysql::errc
boost::mysql::detail::serialization_traits<
inline boost::mysql::errc boost::mysql::detail::serialization_traits<
boost::mysql::detail::auth_switch_request_packet,
boost::mysql::detail::serialization_tag::struct_with_fields
>::deserialize_(
deserialization_context& ctx,
auth_switch_request_packet& output
) noexcept
boost::mysql::detail::serialization_tag::struct_with_fields>::
deserialize_(deserialization_context& ctx, auth_switch_request_packet& output) noexcept
{
auto err = deserialize(ctx, output.plugin_name, output.auth_plugin_data);
auto& auth_data = output.auth_plugin_data.value;
@@ -156,6 +139,4 @@ boost::mysql::detail::serialization_traits<
return err;
}
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_PROTOCOL_IMPL_HANDSHAKE_MESSAGES_IPP_ */

View File

@@ -10,54 +10,43 @@
#pragma once
#include <boost/mysql/detail/protocol/prepared_statement_messages.hpp>
#include <boost/mysql/detail/protocol/null_bitmap_traits.hpp>
#include <boost/mysql/detail/protocol/binary_serialization.hpp>
#include <boost/mysql/detail/protocol/null_bitmap_traits.hpp>
#include <boost/mysql/detail/protocol/prepared_statement_messages.hpp>
namespace boost {
namespace mysql {
namespace detail {
// Maps from an actual value to a protocol_field_type. Only value's type is used
inline protocol_field_type get_protocol_field_type(
const field_view& input
) noexcept
inline protocol_field_type get_protocol_field_type(const field_view& input) noexcept
{
switch (input.kind())
{
case field_kind::null: return protocol_field_type::null;
case field_kind::int64: return protocol_field_type::longlong;
case field_kind::uint64: return protocol_field_type::longlong;
case field_kind::string: return protocol_field_type::varchar;
case field_kind::float_: return protocol_field_type::float_;
case field_kind::double_: return protocol_field_type::double_;
case field_kind::date: return protocol_field_type::date;
case field_kind::datetime: return protocol_field_type::datetime;
case field_kind::time: return protocol_field_type::time;
case field_kind::null: return protocol_field_type::null;
case field_kind::int64: return protocol_field_type::longlong;
case field_kind::uint64: return protocol_field_type::longlong;
case field_kind::string: return protocol_field_type::varchar;
case field_kind::float_: return protocol_field_type::float_;
case field_kind::double_: return protocol_field_type::double_;
case field_kind::date: return protocol_field_type::date;
case field_kind::datetime: return protocol_field_type::datetime;
case field_kind::time: return protocol_field_type::time;
}
}
// Whether to include the unsigned flag in the statement execute message
// for a given value or not. Only value's type is used
inline bool is_unsigned(
const field_view& input
) noexcept
{
return input.is_uint64();
}
inline bool is_unsigned(const field_view& input) noexcept { return input.is_uint64(); }
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
inline boost::mysql::errc
boost::mysql::detail::serialization_traits<
inline boost::mysql::errc boost::mysql::detail::serialization_traits<
boost::mysql::detail::com_stmt_prepare_ok_packet,
boost::mysql::detail::serialization_tag::struct_with_fields
>::deserialize_(
deserialization_context& ctx,
com_stmt_prepare_ok_packet& output
) noexcept
boost::mysql::detail::serialization_tag::struct_with_fields>::
deserialize_(deserialization_context& ctx, com_stmt_prepare_ok_packet& output) noexcept
{
std::uint8_t reserved;
return deserialize(
@@ -71,17 +60,16 @@ boost::mysql::detail::serialization_traits<
}
template <class FieldViewFwdIterator>
inline std::size_t
boost::mysql::detail::serialization_traits<
inline std::size_t boost::mysql::detail::serialization_traits<
boost::mysql::detail::com_stmt_execute_packet<FieldViewFwdIterator>,
boost::mysql::detail::serialization_tag::struct_with_fields
>::get_size_(
const serialization_context& ctx,
const com_stmt_execute_packet<FieldViewFwdIterator>& value
) noexcept
boost::mysql::detail::serialization_tag::struct_with_fields>::
get_size_(
const serialization_context& ctx,
const com_stmt_execute_packet<FieldViewFwdIterator>& value
) noexcept
{
std::size_t res = 1 + // command ID
get_size(ctx, value.statement_id, value.flags, value.iteration_count);
std::size_t res = 1 + // command ID
get_size(ctx, value.statement_id, value.flags, value.iteration_count);
auto num_params = std::distance(value.params_begin, value.params_end);
assert(num_params >= 0 && num_params <= 255);
res += null_bitmap_traits(stmt_execute_null_bitmap_offset, num_params).byte_count();
@@ -95,32 +83,25 @@ boost::mysql::detail::serialization_traits<
}
template <class FieldViewFwdIterator>
inline void
boost::mysql::detail::serialization_traits<
inline void boost::mysql::detail::serialization_traits<
boost::mysql::detail::com_stmt_execute_packet<FieldViewFwdIterator>,
boost::mysql::detail::serialization_tag::struct_with_fields
>::serialize_(
serialization_context& ctx,
const com_stmt_execute_packet<FieldViewFwdIterator>& input
) noexcept
boost::mysql::detail::serialization_tag::struct_with_fields>::
serialize_(
serialization_context& ctx,
const com_stmt_execute_packet<FieldViewFwdIterator>& input
) noexcept
{
constexpr std::uint8_t command_id = com_stmt_execute_packet<FieldViewFwdIterator>::command_id;
serialize(
ctx,
command_id,
input.statement_id,
input.flags,
input.iteration_count
);
serialize(ctx, command_id, input.statement_id, input.flags, input.iteration_count);
// Number of parameters
auto num_params = std::distance(input.params_begin, input.params_end);
assert(num_params >= 0 && num_params <= 255);
// NULL bitmap (already size zero if num_params == 0)
null_bitmap_traits traits (stmt_execute_null_bitmap_offset, num_params);
null_bitmap_traits traits(stmt_execute_null_bitmap_offset, num_params);
std::size_t i = 0;
std::memset(ctx.first(), 0, traits.byte_count()); // Initialize to zeroes
std::memset(ctx.first(), 0, traits.byte_count()); // Initialize to zeroes
for (auto it = input.params_begin; it != input.params_end; ++it, ++i)
{
if (it->is_null())
@@ -149,5 +130,4 @@ boost::mysql::detail::serialization_traits<
}
}
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_PROTOCOL_IMPL_PREPARED_STATEMENT_MESSAGES_HPP_ */

View File

@@ -8,9 +8,9 @@
#ifndef BOOST_MYSQL_DETAIL_PROTOCOL_NULL_BITMAP_TRAITS_HPP
#define BOOST_MYSQL_DETAIL_PROTOCOL_NULL_BITMAP_TRAITS_HPP
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cassert>
namespace boost {
namespace mysql {
@@ -21,11 +21,18 @@ class null_bitmap_traits
std::size_t offset_;
std::size_t num_fields_;
constexpr std::size_t byte_pos(std::size_t field_pos) const noexcept { return (field_pos + offset_) / 8; }
constexpr std::size_t bit_pos(std::size_t field_pos) const noexcept { return (field_pos + offset_) % 8; }
constexpr std::size_t byte_pos(std::size_t field_pos) const noexcept
{
return (field_pos + offset_) / 8;
}
constexpr std::size_t bit_pos(std::size_t field_pos) const noexcept
{
return (field_pos + offset_) % 8;
}
public:
constexpr null_bitmap_traits(std::size_t offset, std::size_t num_fields) noexcept:
offset_(offset), num_fields_ {num_fields} {};
constexpr null_bitmap_traits(std::size_t offset, std::size_t num_fields) noexcept
: offset_(offset), num_fields_{num_fields} {};
constexpr std::size_t offset() const noexcept { return offset_; }
constexpr std::size_t num_fields() const noexcept { return num_fields_; }
@@ -45,8 +52,8 @@ public:
constexpr std::size_t stmt_execute_null_bitmap_offset = 0;
constexpr std::size_t binary_row_null_bitmap_offset = 2;
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#endif /* INCLUDE_NULL_BITMAP_HPP_ */

View File

@@ -8,8 +8,8 @@
#ifndef BOOST_MYSQL_DETAIL_PROTOCOL_PREPARED_STATEMENT_MESSAGES_HPP
#define BOOST_MYSQL_DETAIL_PROTOCOL_PREPARED_STATEMENT_MESSAGES_HPP
#include <boost/mysql/detail/protocol/serialization.hpp>
#include <boost/mysql/detail/protocol/constants.hpp>
#include <boost/mysql/detail/protocol/serialization.hpp>
#include <boost/mysql/field_view.hpp>
namespace boost {
@@ -26,9 +26,7 @@ struct com_stmt_prepare_packet
template <class Self, class Callable>
static void apply(Self& self, Callable&& cb)
{
std::forward<Callable>(cb)(
self.statement
);
std::forward<Callable>(cb)(self.statement);
}
};
@@ -46,21 +44,25 @@ struct com_stmt_prepare_ok_packet
template <class Self, class Callable>
static void apply(Self& self, Callable&& cb)
{
// clang-format off
std::forward<Callable>(cb)(
self.statement_id,
self.num_columns,
self.num_params,
self.warning_count
);
// clang-format on
}
};
template <>
struct serialization_traits<com_stmt_prepare_ok_packet, serialization_tag::struct_with_fields> :
noop_serialize<com_stmt_prepare_ok_packet>
struct serialization_traits<com_stmt_prepare_ok_packet, serialization_tag::struct_with_fields>
: noop_serialize<com_stmt_prepare_ok_packet>
{
static inline errc deserialize_(deserialization_context& ctx,
com_stmt_prepare_ok_packet& output) noexcept;
static inline errc deserialize_(
deserialization_context& ctx,
com_stmt_prepare_ok_packet& output
) noexcept;
};
// execute
@@ -80,25 +82,31 @@ struct com_stmt_execute_packet
template <class Self, class Callable>
static void apply(Self& self, Callable&& cb)
{
// clang-format off
std::forward<Callable>(cb)(
self.statement_id,
self.flags,
self.iteration_count,
self.new_params_bind_flag
);
// clang-format on
}
};
template <class FieldViewFwdIterator>
struct serialization_traits<
com_stmt_execute_packet<FieldViewFwdIterator>,
serialization_tag::struct_with_fields
> : noop_deserialize<com_stmt_execute_packet<FieldViewFwdIterator>>
serialization_tag::struct_with_fields>
: noop_deserialize<com_stmt_execute_packet<FieldViewFwdIterator>>
{
static inline std::size_t get_size_(const serialization_context& ctx,
const com_stmt_execute_packet<FieldViewFwdIterator>& value) noexcept;
static inline void serialize_(serialization_context& ctx,
const com_stmt_execute_packet<FieldViewFwdIterator>& input) noexcept;
static inline std::size_t get_size_(
const serialization_context& ctx,
const com_stmt_execute_packet<FieldViewFwdIterator>& value
) noexcept;
static inline void serialize_(
serialization_context& ctx,
const com_stmt_execute_packet<FieldViewFwdIterator>& input
) noexcept;
};
struct com_stmt_execute_param_meta_packet
@@ -109,10 +117,7 @@ struct com_stmt_execute_param_meta_packet
template <class Self, class Callable>
static void apply(Self& self, Callable&& cb)
{
std::forward<Callable>(cb)(
self.type,
self.unsigned_flag
);
std::forward<Callable>(cb)(self.type, self.unsigned_flag);
}
};
@@ -126,16 +131,13 @@ struct com_stmt_close_packet
template <class Self, class Callable>
static void apply(Self& self, Callable&& cb)
{
std::forward<Callable>(cb)(
self.statement_id
);
std::forward<Callable>(cb)(self.statement_id);
}
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/protocol/impl/prepared_statement_messages.hpp>

View File

@@ -9,11 +9,12 @@
#define BOOST_MYSQL_DETAIL_PROTOCOL_PROTOCOL_TYPES_HPP
#include <boost/utility/string_view.hpp>
#include <cstdint>
#include <array>
#include <vector>
#include <cstdint>
#include <cstring>
#include <type_traits>
#include <vector>
namespace boost {
namespace mysql {
@@ -24,10 +25,14 @@ struct value_holder
{
using value_type = T;
static_assert(std::is_nothrow_default_constructible<T>::value,
"value_holder<T> should be nothrow default constructible");
static_assert(std::is_nothrow_move_constructible<T>::value,
"value_holder<T> should be nothrow move constructible");
static_assert(
std::is_nothrow_default_constructible<T>::value,
"value_holder<T> should be nothrow default constructible"
);
static_assert(
std::is_nothrow_move_constructible<T>::value,
"value_holder<T> should be nothrow move constructible"
);
value_type value;
@@ -39,19 +44,36 @@ struct value_holder
constexpr bool operator!=(const value_holder<T>& rhs) const { return value != rhs.value; }
};
struct int3 : value_holder<std::uint32_t> { using value_holder::value_holder; };
struct int_lenenc : value_holder<std::uint64_t> { using value_holder::value_holder; };
struct int3 : value_holder<std::uint32_t>
{
using value_holder::value_holder;
};
struct string_null : value_holder<boost::string_view> { using value_holder::value_holder; };
struct string_eof : value_holder<boost::string_view> { using value_holder::value_holder; };
struct string_lenenc : value_holder<boost::string_view> { using value_holder::value_holder; };
struct int_lenenc : value_holder<std::uint64_t>
{
using value_holder::value_holder;
};
struct string_null : value_holder<boost::string_view>
{
using value_holder::value_holder;
};
struct string_eof : value_holder<boost::string_view>
{
using value_holder::value_holder;
};
struct string_lenenc : value_holder<boost::string_view>
{
using value_holder::value_holder;
};
template <std::size_t size>
using string_fixed = std::array<char, size>;
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#endif

View File

@@ -9,6 +9,7 @@
#define BOOST_MYSQL_DETAIL_PROTOCOL_QUERY_MESSAGES_HPP
#include <boost/mysql/detail/protocol/serialization.hpp>
#include <tuple>
namespace boost {
@@ -24,14 +25,12 @@ struct com_query_packet
template <class Self, class Callable>
static void apply(Self& self, Callable&& cb)
{
std::forward<Callable>(cb)(
self.query
);
std::forward<Callable>(cb)(self.query);
}
};
}
}
}
} // namespace detail
} // namespace mysql
} // namespace boost
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_PROTOCOL_QUERY_MESSAGES_HPP_ */

View File

@@ -8,7 +8,6 @@
#ifndef BOOST_MYSQL_DETAIL_PROTOCOL_RESULTSET_ENCODING_HPP
#define BOOST_MYSQL_DETAIL_PROTOCOL_RESULTSET_ENCODING_HPP
namespace boost {
namespace mysql {
namespace detail {
@@ -19,9 +18,8 @@ enum class resultset_encoding
binary
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_NETWORK_ALGORITHMS_COMMON_HPP_ */

View File

@@ -8,15 +8,17 @@
#ifndef BOOST_MYSQL_DETAIL_PROTOCOL_SERIALIZATION_HPP
#define BOOST_MYSQL_DETAIL_PROTOCOL_SERIALIZATION_HPP
#include <boost/endian/conversion.hpp>
#include <type_traits>
#include <algorithm>
#include <boost/mysql/detail/auxiliar/bytestring.hpp>
#include <boost/mysql/detail/protocol/deserialization_context.hpp>
#include <boost/mysql/detail/protocol/protocol_types.hpp>
#include <boost/mysql/detail/protocol/serialization_context.hpp>
#include <boost/mysql/detail/protocol/deserialization_context.hpp>
#include <boost/mysql/detail/auxiliar/bytestring.hpp>
#include <boost/mysql/error.hpp>
#include <boost/endian/conversion.hpp>
#include <algorithm>
#include <type_traits>
namespace boost {
namespace mysql {
namespace detail {
@@ -32,7 +34,7 @@ enum class serialization_tag
template <class T>
constexpr serialization_tag get_serialization_tag();
template <class T, serialization_tag=get_serialization_tag<T>()>
template <class T, serialization_tag = get_serialization_tag<T>()>
struct serialization_traits;
template <class... Types>
@@ -50,7 +52,10 @@ struct serialization_traits<T, serialization_tag::plain_int>
{
static errc deserialize_(deserialization_context& ctx, T& output) noexcept;
static void serialize_(serialization_context& ctx, T input) noexcept;
static constexpr std::size_t get_size_(const serialization_context&, T) noexcept { return sizeof(T); }
static constexpr std::size_t get_size_(const serialization_context&, T) noexcept
{
return sizeof(T);
}
};
// int3
@@ -82,7 +87,6 @@ struct serialization_traits<int_lenenc, serialization_tag::none>
static inline std::size_t get_size_(const serialization_context&, int_lenenc input) noexcept;
};
// string_fixed
template <std::size_t N>
struct serialization_traits<string_fixed<N>, serialization_tag::none>
@@ -99,13 +103,13 @@ struct serialization_traits<string_fixed<N>, serialization_tag::none>
{
ctx.write(input.data(), N);
}
static constexpr std::size_t get_size_(const serialization_context&, const string_fixed<N>&) noexcept
static constexpr std::size_t
get_size_(const serialization_context&, const string_fixed<N>&) noexcept
{
return N;
}
};
// string_null
template <>
struct serialization_traits<string_null, serialization_tag::none>
@@ -114,7 +118,7 @@ struct serialization_traits<string_null, serialization_tag::none>
static inline void serialize_(serialization_context& ctx, string_null input) noexcept
{
ctx.write(input.value.data(), input.value.size());
ctx.write(0); // null terminator
ctx.write(0); // null terminator
}
static inline std::size_t get_size_(const serialization_context&, string_null input) noexcept
{
@@ -147,7 +151,8 @@ struct serialization_traits<string_lenenc, serialization_tag::none>
serialize(ctx, int_lenenc(input.value.size()));
ctx.write(input.value.data(), input.value.size());
}
static inline std::size_t get_size_(const serialization_context& ctx, string_lenenc input) noexcept
static inline std::size_t
get_size_(const serialization_context& ctx, string_lenenc input) noexcept
{
return get_size(ctx, int_lenenc(input.value.size())) + input.value.size();
}
@@ -170,7 +175,10 @@ struct serialization_traits<T, serialization_tag::enumeration>
{
serialize(ctx, static_cast<underlying_type>(input));
}
static std::size_t get_size_(const serialization_context&, T) noexcept { return sizeof(underlying_type); }
static std::size_t get_size_(const serialization_context&, T) noexcept
{
return sizeof(underlying_type);
}
};
// Structs and commands
@@ -199,7 +207,10 @@ struct serialization_traits<T, serialization_tag::struct_with_fields>
template <class T>
struct noop_serialize
{
static inline std::size_t get_size_(const serialization_context&, const T&) noexcept { return 0; }
static inline std::size_t get_size_(const serialization_context&, const T&) noexcept
{
return 0;
}
static inline void serialize_(serialization_context&, const T&) noexcept {}
};
@@ -218,20 +229,18 @@ void serialize_message(
);
template <class Deserializable>
error_code deserialize_message(
deserialization_context& ctx,
Deserializable& output
);
error_code deserialize_message(deserialization_context& ctx, Deserializable& output);
// Helpers for (de) serializing a set of fields
template <class... Types>
void serialize_fields(serialization_context& ctx, const Types&... fields) noexcept;
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
#include <boost/mysql/detail/protocol/impl/serialization.hpp>
#include <boost/mysql/detail/protocol/impl/serialization.ipp>
#endif

View File

@@ -9,7 +9,9 @@
#define BOOST_MYSQL_DETAIL_PROTOCOL_SERIALIZATION_CONTEXT_HPP
#include <boost/mysql/detail/protocol/capabilities.hpp>
#include <boost/asio/buffer.hpp>
#include <cstdint>
#include <cstring>
@@ -21,22 +23,32 @@ class serialization_context
{
std::uint8_t* first_;
capabilities capabilities_;
public:
serialization_context(capabilities caps, std::uint8_t* first = nullptr) noexcept:
first_(first), capabilities_(caps) {};
serialization_context(capabilities caps, std::uint8_t* first = nullptr) noexcept
: first_(first), capabilities_(caps){};
std::uint8_t* first() const noexcept { return first_; }
void set_first(std::uint8_t* new_first) noexcept { first_ = new_first; }
void set_first(boost::asio::mutable_buffer buff) noexcept { first_ = static_cast<std::uint8_t*>(buff.data()); }
void set_first(boost::asio::mutable_buffer buff) noexcept
{
first_ = static_cast<std::uint8_t*>(buff.data());
}
void advance(std::size_t size) noexcept { first_ += size; }
capabilities get_capabilities() const noexcept { return capabilities_; }
void write(const void* buffer, std::size_t size) noexcept { memcpy(first_, buffer, size); advance(size); }
void write(std::uint8_t elm) noexcept { *first_ = elm; ++first_; }
void write(const void* buffer, std::size_t size) noexcept
{
memcpy(first_, buffer, size);
advance(size);
}
void write(std::uint8_t elm) noexcept
{
*first_ = elm;
++first_;
}
};
}
}
}
} // namespace detail
} // namespace mysql
} // namespace boost
#endif /* INCLUDE_BOOST_MYSQL_DETAIL_PROTOCOL_SERIALIZATION_CONTEXT_HPP_ */

View File

@@ -8,11 +8,13 @@
#ifndef BOOST_MYSQL_ERROR_HPP
#define BOOST_MYSQL_ERROR_HPP
#include <boost/system/error_code.hpp>
#include <string>
#include <ostream>
#include <boost/mysql/errc.hpp>
#include <boost/system/error_code.hpp>
#include <ostream>
#include <string>
namespace boost {
namespace mysql {
@@ -31,12 +33,13 @@ inline error_code make_error_code(errc error);
class error_info
{
std::string msg_;
public:
/// Default constructor.
error_info() = default;
/// Initialization constructor.
error_info(std::string&& err) noexcept: msg_(std::move(err)) {}
error_info(std::string&& err) noexcept : msg_(std::move(err)) {}
/// Gets the error message.
const std::string& message() const noexcept { return msg_; }
@@ -52,13 +55,19 @@ public:
* \relates error_info
* \brief Compare two error_info objects.
*/
inline bool operator==(const error_info& lhs, const error_info& rhs) noexcept { return lhs.message() == rhs.message(); }
inline bool operator==(const error_info& lhs, const error_info& rhs) noexcept
{
return lhs.message() == rhs.message();
}
/**
* \relates error_info
* \brief Compare two error_info objects.
*/
inline bool operator!=(const error_info& lhs, const error_info& rhs) noexcept { return !(lhs==rhs); }
inline bool operator!=(const error_info& lhs, const error_info& rhs) noexcept
{
return !(lhs == rhs);
}
/**
* \relates error_info
@@ -66,8 +75,8 @@ inline bool operator!=(const error_info& lhs, const error_info& rhs) noexcept {
*/
inline std::ostream& operator<<(std::ostream& os, const error_info& v) { return os << v.message(); }
} // mysql
} // boost
} // namespace mysql
} // namespace boost
#include <boost/mysql/impl/error.hpp>

View File

@@ -9,6 +9,7 @@
#define BOOST_MYSQL_EXECUTE_PARAMS_HPP
#include <boost/mysql/detail/auxiliar/field_type_traits.hpp>
#include <iterator>
#include <type_traits>
@@ -16,63 +17,61 @@ namespace boost {
namespace mysql {
/**
* \brief Represents the parameters required to execute a [reflink statement_base].
* \details In essence, this class contains an iterator range \\[first, last), pointing
* to a sequence of [reflink value]s that will be used as parameters to execute a
* [reflink statement_base]. FieldViewFwdIterator must meet the [reflink FieldViewFwdIterator]
* type requirements.
*
* In the future, this class may define extra members providing finer control
* over prepared statement execution.
*
* The \ref make_execute_params helper functions make it easier to create
* instances of this class.
*/
* \brief Represents the parameters required to execute a [reflink statement_base].
* \details In essence, this class contains an iterator range \\[first, last), pointing
* to a sequence of [reflink value]s that will be used as parameters to execute a
* [reflink statement_base]. FieldViewFwdIterator must meet the [reflink FieldViewFwdIterator]
* type requirements.
*
* In the future, this class may define extra members providing finer control
* over prepared statement execution.
*
* The \ref make_execute_params helper functions make it easier to create
* instances of this class.
*/
template <class FieldViewFwdIterator>
class execute_params
{
FieldViewFwdIterator first_;
FieldViewFwdIterator last_;
static_assert(detail::is_field_view_forward_iterator<FieldViewFwdIterator>::value,
"FieldViewFwdIterator requirements not met");
static_assert(
detail::is_field_view_forward_iterator<FieldViewFwdIterator>::value,
"FieldViewFwdIterator requirements not met"
);
public:
/// Constructor.
constexpr execute_params(FieldViewFwdIterator first, FieldViewFwdIterator last) :
first_(first), last_(last) {}
constexpr execute_params(FieldViewFwdIterator first, FieldViewFwdIterator last)
: first_(first), last_(last)
{
}
/// Retrieves the parameter value range's begin.
/// Retrieves the parameter value range's begin.
constexpr FieldViewFwdIterator first() const { return first_; }
/// Retrieves the parameter value range's end.
/// Retrieves the parameter value range's end.
constexpr FieldViewFwdIterator last() const { return last_; }
};
template <
class FieldViewFwdIterator,
class EnableIf = detail::enable_if_field_view_forward_iterator<FieldViewFwdIterator>
>
class EnableIf = detail::enable_if_field_view_forward_iterator<FieldViewFwdIterator> >
constexpr execute_params<FieldViewFwdIterator>
make_execute_params(
FieldViewFwdIterator first,
FieldViewFwdIterator last
)
make_execute_params(FieldViewFwdIterator first, FieldViewFwdIterator last)
{
return execute_params<FieldViewFwdIterator>(first, last);
}
template <
class FieldViewCollection,
class EnableIf = detail::enable_if_field_view_collection<FieldViewCollection>
>
constexpr auto make_execute_params(
const FieldViewCollection& col
) -> execute_params<decltype(std::begin(col))>
class EnableIf = detail::enable_if_field_view_collection<FieldViewCollection> >
constexpr auto make_execute_params(const FieldViewCollection& col)
-> execute_params<decltype(std::begin(col))>
{
return make_execute_params(std::begin(col), std::end(col));
}
} // mysql
} // boost
} // namespace mysql
} // namespace boost
#endif

View File

@@ -8,12 +8,14 @@
#ifndef BOOST_MYSQL_FIELD_HPP
#define BOOST_MYSQL_FIELD_HPP
#include <boost/mysql/field_view.hpp>
#include <boost/mysql/datetime_types.hpp>
#include <boost/mysql/field_kind.hpp>
#include <boost/mysql/detail/auxiliar/field_impl.hpp>
#include <boost/mysql/field_kind.hpp>
#include <boost/mysql/field_view.hpp>
#include <boost/utility/string_view.hpp>
#include <boost/variant2/variant.hpp>
#include <cstddef>
#include <ostream>
#include <string>
@@ -49,10 +51,14 @@ public:
explicit field(const std::string& v) : repr_(v) {}
explicit field(std::string&& v) noexcept : repr_(std::move(v)) {}
explicit field(const char* v) : repr_(boost::variant2::in_place_type_t<std::string>(), v) {}
explicit field(boost::string_view v) : repr_(boost::variant2::in_place_type_t<std::string>(), v) {}
#ifdef __cpp_lib_string_view
explicit field(std::string_view v) : repr_(boost::variant2::in_place_type_t<std::string>(), v) {}
#endif
explicit field(boost::string_view v) : repr_(boost::variant2::in_place_type_t<std::string>(), v)
{
}
#ifdef __cpp_lib_string_view
explicit field(std::string_view v) : repr_(boost::variant2::in_place_type_t<std::string>(), v)
{
}
#endif
explicit field(float v) noexcept : repr_(v) {}
explicit field(double v) noexcept : repr_(v) {}
explicit field(const date& v) noexcept : repr_(v) {}
@@ -60,30 +66,118 @@ public:
explicit field(const time& v) noexcept : repr_(v) {}
field(const field_view& v) { from_view(v); }
field& operator=(std::nullptr_t) noexcept { emplace_null(); return *this; }
field& operator=(signed char v) noexcept { emplace_int64(v); return *this; }
field& operator=(short v) noexcept { emplace_int64(v); return *this; }
field& operator=(int v) noexcept { emplace_int64(v); return *this; }
field& operator=(long v) noexcept { emplace_int64(v); return *this; }
field& operator=(long long v) noexcept { emplace_int64(v); return *this; }
field& operator=(unsigned char v) noexcept { emplace_uint64(v); return *this; }
field& operator=(unsigned short v) noexcept { emplace_uint64(v); return *this; }
field& operator=(unsigned int v) noexcept { emplace_uint64(v); return *this; }
field& operator=(unsigned long v) noexcept { emplace_uint64(v); return *this; }
field& operator=(unsigned long long v) noexcept { emplace_uint64(v); return *this; }
field& operator=(const std::string& v) { emplace_string(v); return *this; }
field& operator=(std::string&& v) { emplace_string(std::move(v)); return *this; }
field& operator=(const char* v) { emplace_string(v); return *this; }
field& operator=(boost::string_view v) { emplace_string(v); return *this; }
#ifdef __cpp_lib_string_view
field& operator=(std::string_view v) { emplace_string(v); return *this; }
#endif
field& operator=(float v) noexcept { emplace_float(v); return *this; }
field& operator=(double v) noexcept { emplace_double(v); return *this; }
field& operator=(const date& v) noexcept { emplace_date(v); return *this; }
field& operator=(const datetime& v) noexcept { emplace_datetime(v); return *this; }
field& operator=(const time& v) noexcept { emplace_time(v); return *this; }
field& operator=(const field_view& v) { from_view(v); return *this; }
field& operator=(std::nullptr_t) noexcept
{
emplace_null();
return *this;
}
field& operator=(signed char v) noexcept
{
emplace_int64(v);
return *this;
}
field& operator=(short v) noexcept
{
emplace_int64(v);
return *this;
}
field& operator=(int v) noexcept
{
emplace_int64(v);
return *this;
}
field& operator=(long v) noexcept
{
emplace_int64(v);
return *this;
}
field& operator=(long long v) noexcept
{
emplace_int64(v);
return *this;
}
field& operator=(unsigned char v) noexcept
{
emplace_uint64(v);
return *this;
}
field& operator=(unsigned short v) noexcept
{
emplace_uint64(v);
return *this;
}
field& operator=(unsigned int v) noexcept
{
emplace_uint64(v);
return *this;
}
field& operator=(unsigned long v) noexcept
{
emplace_uint64(v);
return *this;
}
field& operator=(unsigned long long v) noexcept
{
emplace_uint64(v);
return *this;
}
field& operator=(const std::string& v)
{
emplace_string(v);
return *this;
}
field& operator=(std::string&& v)
{
emplace_string(std::move(v));
return *this;
}
field& operator=(const char* v)
{
emplace_string(v);
return *this;
}
field& operator=(boost::string_view v)
{
emplace_string(v);
return *this;
}
#ifdef __cpp_lib_string_view
field& operator=(std::string_view v)
{
emplace_string(v);
return *this;
}
#endif
field& operator=(float v) noexcept
{
emplace_float(v);
return *this;
}
field& operator=(double v) noexcept
{
emplace_double(v);
return *this;
}
field& operator=(const date& v) noexcept
{
emplace_date(v);
return *this;
}
field& operator=(const datetime& v) noexcept
{
emplace_datetime(v);
return *this;
}
field& operator=(const time& v) noexcept
{
emplace_time(v);
return *this;
}
field& operator=(const field_view& v)
{
from_view(v);
return *this;
}
field_kind kind() const noexcept { return repr_.kind(); }
@@ -140,9 +234,9 @@ public:
void emplace_string(std::string&& v) noexcept { repr_.data.emplace<std::string>(std::move(v)); }
void emplace_string(const char* v) noexcept { repr_.data.emplace<std::string>(v); }
void emplace_string(boost::string_view v) noexcept { repr_.data.emplace<std::string>(v); }
#ifdef __cpp_lib_string_view
#ifdef __cpp_lib_string_view
void emplace_string(std::string_view v) noexcept { repr_.data.emplace<std::string>(v); }
#endif
#endif
void emplace_float(float v) noexcept { repr_.data.emplace<float>(v); }
void emplace_double(double v) noexcept { repr_.data.emplace<double>(v); }
void emplace_date(const date& v) noexcept { repr_.data.emplace<date>(v); }
@@ -150,27 +244,36 @@ public:
void emplace_time(const time& v) noexcept { repr_.data.emplace<time>(v); }
inline operator field_view() const noexcept { return field_view(&repr_); }
private:
detail::field_impl repr_;
inline void from_view(const field_view& v);
};
inline bool operator==(const field& lhs, const field& rhs) noexcept { return field_view(lhs) == field_view(rhs); }
inline bool operator==(const field& lhs, const field& rhs) noexcept
{
return field_view(lhs) == field_view(rhs);
}
inline bool operator!=(const field& lhs, const field& rhs) noexcept { return !(lhs == rhs); }
inline bool operator==(const field_view& lhs, const field& rhs) noexcept { return lhs == field_view(rhs); }
inline bool operator==(const field_view& lhs, const field& rhs) noexcept
{
return lhs == field_view(rhs);
}
inline bool operator!=(const field_view& lhs, const field& rhs) noexcept { return !(lhs == rhs); }
inline bool operator==(const field& lhs, const field_view& rhs) noexcept { return field_view(lhs) == rhs; }
inline bool operator==(const field& lhs, const field_view& rhs) noexcept
{
return field_view(lhs) == rhs;
}
inline bool operator!=(const field& lhs, const field_view& rhs) noexcept { return !(lhs == rhs); }
inline std::ostream& operator<<(std::ostream& os, const field& v);
} // mysql
} // boost
} // namespace mysql
} // namespace boost
#include <boost/mysql/impl/field.hpp>
#endif

View File

@@ -29,8 +29,8 @@ enum class field_kind
inline std::ostream& operator<<(std::ostream& os, field_kind v);
} // mysql
} // boost
} // namespace mysql
} // namespace boost
#include <boost/mysql/impl/field_kind.ipp>

View File

@@ -23,31 +23,31 @@ namespace mysql {
*/
enum class field_type
{
tinyint, ///< `__TINYINT__` (signed and unsigned).
smallint, ///< `__SMALLINT__` (signed and unsigned).
mediumint, ///< `__MEDIUMINT__` (signed and unsigned).
int_, ///< `__INT__` (signed and unsigned).
bigint, ///< `__BIGINT__` (signed and unsigned).
float_, ///< `__FLOAT__` (warning: FLOAT(p) where p >= 24 creates a DOUBLE column).
double_, ///< `__DOUBLE__`
decimal, ///< `__DECIMAL__`
bit, ///< `__BIT__`
year, ///< `__YEAR__`
time, ///< `__TIME__`
date, ///< `__DATE__`
datetime, ///< `__DATETIME__`
timestamp, ///< `__TIMESTAMP__`
char_, ///< `__CHAR__` (any length)
varchar, ///< `__VARCHAR__` (any length)
binary, ///< `__BINARY__` (any length)
varbinary, ///< `__VARBINARY__` (any length)
text, ///< `__TEXT__` types (`TINYTEXT`, `MEDIUMTEXT`, `TEXT` and `LONGTEXT`)
blob, ///< `__BLOB__` types (`TINYBLOB`, `MEDIUMBLOB`, `BLOB` and `LONGBLOB`)
enum_, ///< `__ENUM__`
set, ///< `__SET__`
geometry, ///< `__GEOMETRY__`
tinyint, ///< `__TINYINT__` (signed and unsigned).
smallint, ///< `__SMALLINT__` (signed and unsigned).
mediumint, ///< `__MEDIUMINT__` (signed and unsigned).
int_, ///< `__INT__` (signed and unsigned).
bigint, ///< `__BIGINT__` (signed and unsigned).
float_, ///< `__FLOAT__` (warning: FLOAT(p) where p >= 24 creates a DOUBLE column).
double_, ///< `__DOUBLE__`
decimal, ///< `__DECIMAL__`
bit, ///< `__BIT__`
year, ///< `__YEAR__`
time, ///< `__TIME__`
date, ///< `__DATE__`
datetime, ///< `__DATETIME__`
timestamp, ///< `__TIMESTAMP__`
char_, ///< `__CHAR__` (any length)
varchar, ///< `__VARCHAR__` (any length)
binary, ///< `__BINARY__` (any length)
varbinary, ///< `__VARBINARY__` (any length)
text, ///< `__TEXT__` types (`TINYTEXT`, `MEDIUMTEXT`, `TEXT` and `LONGTEXT`)
blob, ///< `__BLOB__` types (`TINYBLOB`, `MEDIUMBLOB`, `BLOB` and `LONGBLOB`)
enum_, ///< `__ENUM__`
set, ///< `__SET__`
geometry, ///< `__GEOMETRY__`
unknown, ///< None of the known types; maybe a new MySQL type we have no knowledge of.
unknown, ///< None of the known types; maybe a new MySQL type we have no knowledge of.
#ifndef BOOST_MYSQL_DOXYGEN
_not_computed,
#endif
@@ -88,9 +88,7 @@ inline std::ostream& operator<<(std::ostream& os, field_type t)
}
}
} // mysql
} // boost
} // namespace mysql
} // namespace boost
#endif

View File

@@ -8,16 +8,18 @@
#ifndef BOOST_MYSQL_FIELD_VIEW_HPP
#define BOOST_MYSQL_FIELD_VIEW_HPP
#include <boost/config/detail/suffix.hpp>
#include <boost/mysql/detail/auxiliar/string_view_offset.hpp>
#include <boost/mysql/detail/auxiliar/field_impl.hpp>
#include <boost/mysql/datetime_types.hpp>
#include <boost/mysql/detail/auxiliar/field_impl.hpp>
#include <boost/mysql/detail/auxiliar/string_view_offset.hpp>
#include <boost/mysql/field_kind.hpp>
#include <boost/config/detail/suffix.hpp>
#include <boost/utility/string_view.hpp>
#include <array>
#include <cstddef>
#include <cstdint>
#include <iosfwd>
#include <array>
namespace boost {
namespace mysql {
@@ -45,11 +47,11 @@ public:
BOOST_CXX14_CONSTEXPR field_view() = default;
/**
* \brief Constructs a NULL value.
* \details
* Caution: `value(NULL)` will __NOT__ match this overload. It will try to construct
* a `boost::string_view` from a NULL C string, causing undefined behavior.
*/
* \brief Constructs a NULL value.
* \details
* Caution: `value(NULL)` will __NOT__ match this overload. It will try to construct
* a `boost::string_view` from a NULL C string, causing undefined behavior.
*/
BOOST_CXX14_CONSTEXPR explicit field_view(std::nullptr_t) noexcept {}
BOOST_CXX14_CONSTEXPR explicit inline field_view(signed char v) noexcept;
@@ -72,16 +74,17 @@ public:
BOOST_CXX14_CONSTEXPR explicit inline field_view(const time& v) noexcept;
// TODO: hide this
BOOST_CXX14_CONSTEXPR explicit field_view(detail::string_view_offset v) noexcept : ikind_(internal_kind::sv_offset)
BOOST_CXX14_CONSTEXPR explicit field_view(detail::string_view_offset v) noexcept
: ikind_(internal_kind::sv_offset)
{
repr_.sv_offset = { v.offset(), v.size() };
repr_.sv_offset = {v.offset(), v.size()};
}
BOOST_CXX14_CONSTEXPR explicit field_view(const detail::field_impl* v) noexcept : ikind_(internal_kind::field_ptr)
BOOST_CXX14_CONSTEXPR explicit field_view(const detail::field_impl* v) noexcept
: ikind_(internal_kind::field_ptr)
{
repr_.field_ptr = v;
}
BOOST_CXX14_CONSTEXPR inline field_kind kind() const noexcept;
BOOST_CXX14_CONSTEXPR bool is_null() const noexcept { return kind() == field_kind::null; }
@@ -91,7 +94,10 @@ public:
BOOST_CXX14_CONSTEXPR bool is_float() const noexcept { return kind() == field_kind::float_; }
BOOST_CXX14_CONSTEXPR bool is_double() const noexcept { return kind() == field_kind::double_; }
BOOST_CXX14_CONSTEXPR bool is_date() const noexcept { return kind() == field_kind::date; }
BOOST_CXX14_CONSTEXPR bool is_datetime() const noexcept { return kind() == field_kind::datetime; }
BOOST_CXX14_CONSTEXPR bool is_datetime() const noexcept
{
return kind() == field_kind::datetime;
}
BOOST_CXX14_CONSTEXPR bool is_time() const noexcept { return kind() == field_kind::time; }
BOOST_CXX14_CONSTEXPR inline std::int64_t as_int64() const;
@@ -112,11 +118,16 @@ public:
BOOST_CXX14_CONSTEXPR inline datetime get_datetime() const noexcept;
BOOST_CXX14_CONSTEXPR inline time get_time() const noexcept;
/// Tests for equality (type and value); see [link mysql.values.relational this section] for more info.
/// Tests for equality (type and value); see [link mysql.values.relational this section] for
/// more info.
BOOST_CXX14_CONSTEXPR bool operator==(const field_view& rhs) const noexcept;
/// Tests for inequality (type and value); see [link mysql.values.relational this section] for more info.
BOOST_CXX14_CONSTEXPR bool operator!=(const field_view& rhs) const noexcept { return !(*this==rhs); }
/// Tests for inequality (type and value); see [link mysql.values.relational this section] for
/// more info.
BOOST_CXX14_CONSTEXPR bool operator!=(const field_view& rhs) const noexcept
{
return !(*this == rhs);
}
// TODO: hide this
void offset_to_string_view(const std::uint8_t* buffer_first) noexcept
@@ -126,10 +137,10 @@ public:
ikind_ = internal_kind::string;
repr_.string = {
reinterpret_cast<const char*>(buffer_first) + repr_.sv_offset.offset,
repr_.sv_offset.size
};
repr_.sv_offset.size};
}
}
private:
enum class internal_kind
{
@@ -174,14 +185,25 @@ private:
BOOST_CXX14_CONSTEXPR repr_t(float v) noexcept : float_(v) {}
BOOST_CXX14_CONSTEXPR repr_t(double v) noexcept : double_(v) {}
BOOST_CXX14_CONSTEXPR repr_t(date v) noexcept : date_(v.time_since_epoch().count()) {}
BOOST_CXX14_CONSTEXPR repr_t(datetime v) noexcept : datetime_(v.time_since_epoch().count()) {}
BOOST_CXX14_CONSTEXPR repr_t(datetime v) noexcept : datetime_(v.time_since_epoch().count())
{
}
BOOST_CXX14_CONSTEXPR repr_t(time v) noexcept : time_(v.count()) {}
BOOST_CXX14_CONSTEXPR repr_t(detail::string_view_offset v) noexcept : sv_offset{v.offset(), v.size()} {}
BOOST_CXX14_CONSTEXPR repr_t(detail::string_view_offset v) noexcept
: sv_offset{v.offset(), v.size()}
{
}
BOOST_CXX14_CONSTEXPR repr_t(const detail::field_impl* v) noexcept : field_ptr(v) {}
BOOST_CXX14_CONSTEXPR boost::string_view get_string() const noexcept { return boost::string_view(string.ptr, string.size); }
BOOST_CXX14_CONSTEXPR date get_date() const noexcept { return date(date::duration(date_));}
BOOST_CXX14_CONSTEXPR datetime get_datetime() const noexcept { return datetime(datetime::duration(datetime_)); }
BOOST_CXX14_CONSTEXPR boost::string_view get_string() const noexcept
{
return boost::string_view(string.ptr, string.size);
}
BOOST_CXX14_CONSTEXPR date get_date() const noexcept { return date(date::duration(date_)); }
BOOST_CXX14_CONSTEXPR datetime get_datetime() const noexcept
{
return datetime(datetime::duration(datetime_));
}
BOOST_CXX14_CONSTEXPR time get_time() const noexcept { return time(time_); }
BOOST_CXX14_CONSTEXPR detail::string_view_offset get_sv_offset() const noexcept
{
@@ -189,12 +211,15 @@ private:
}
};
internal_kind ikind_ { internal_kind::null };
internal_kind ikind_{internal_kind::null};
repr_t repr_;
friend std::ostream& operator<<(std::ostream& os, const field_view& v);
BOOST_CXX14_CONSTEXPR bool is_field_ptr() const noexcept { return ikind_ == internal_kind::field_ptr; }
BOOST_CXX14_CONSTEXPR bool is_field_ptr() const noexcept
{
return ikind_ == internal_kind::field_ptr;
}
BOOST_CXX14_CONSTEXPR inline void check_kind(internal_kind expected) const;
};
@@ -211,7 +236,6 @@ private:
*/
inline std::ostream& operator<<(std::ostream& os, const field_view& v);
/**
* \relates value
* \brief Creates an array of [reflink value]s out of the passed in arguments.
@@ -221,10 +245,9 @@ inline std::ostream& operator<<(std::ostream& os, const field_view& v);
template <class... Types>
BOOST_CXX14_CONSTEXPR std::array<field_view, sizeof...(Types)> make_field_views(Types&&... args);
} // mysql
} // boost
} // namespace mysql
} // namespace boost
#include <boost/mysql/impl/field_view.hpp>
#endif

View File

@@ -8,13 +8,15 @@
#ifndef BOOST_MYSQL_HANDSHAKE_PARAMS_HPP
#define BOOST_MYSQL_HANDSHAKE_PARAMS_HPP
#include <boost/utility/string_view.hpp>
#include <boost/mysql/collation.hpp>
#include <boost/utility/string_view.hpp>
namespace boost {
namespace mysql {
/// Determines whether to use TLS for the connection or not; ignored if the underlying stream is not SSL-capable.
/// Determines whether to use TLS for the connection or not; ignored if the underlying stream is not
/// SSL-capable.
enum class ssl_mode
{
/// Never use TLS
@@ -27,7 +29,6 @@ enum class ssl_mode
require
};
/**
* \brief Parameters defining how to perform the handshake
* with a MySQL server. See [link mysql.connparams this section]
@@ -40,6 +41,7 @@ class handshake_params
boost::string_view database_;
collation connection_collation_;
ssl_mode ssl_;
public:
/**
* \brief Initializing constructor
@@ -47,8 +49,9 @@ public:
* \param password Password for that username, possibly empty.
* \param db Database name to use, or empty string for no database (this is the default).
* \param connection_col [reflink2 collation Collation] to use for the connection.
* Impacts how text queries and prepared statements are interpreted. Defaults to utf8_general_ci.
* \param mode The [reflink ssl_mode] to use with this connection; ignored if the connection does not support SSL.
* Impacts how text queries and prepared statements are interpreted. Defaults to
* utf8_general_ci. \param mode The [reflink ssl_mode] to use with this connection; ignored if
* the connection does not support SSL.
*/
handshake_params(
boost::string_view username,
@@ -56,12 +59,12 @@ public:
boost::string_view db = "",
collation connection_col = collation::utf8_general_ci,
ssl_mode mode = ssl_mode::require
) :
username_(username),
password_(password),
database_(db),
connection_collation_(connection_col),
ssl_(mode)
)
: username_(username),
password_(password),
database_(db),
connection_collation_(connection_col),
ssl_(mode)
{
}
@@ -96,9 +99,7 @@ public:
void set_ssl(ssl_mode value) noexcept { ssl_ = value; }
};
} // mysql
} // boost
} // namespace mysql
} // namespace boost
#endif /* INCLUDE_BOOST_MYSQL_CONNECTION_PARAMS_HPP_ */

View File

@@ -10,19 +10,20 @@
#pragma once
#include <boost/mysql/row.hpp>
#include <boost/mysql/connection.hpp>
#include <boost/mysql/statement_base.hpp>
#include <boost/mysql/resultset_base.hpp>
#include <boost/mysql/detail/network_algorithms/close_connection.hpp>
#include <boost/mysql/detail/network_algorithms/connect.hpp>
#include <boost/mysql/detail/network_algorithms/handshake.hpp>
#include <boost/mysql/detail/network_algorithms/execute_query.hpp>
#include <boost/mysql/detail/network_algorithms/handshake.hpp>
#include <boost/mysql/detail/network_algorithms/prepare_statement.hpp>
#include <boost/mysql/detail/network_algorithms/quit_connection.hpp>
#include <boost/mysql/detail/network_algorithms/close_connection.hpp>
#include <boost/asio/buffer.hpp>
#include <utility>
#include <boost/mysql/resultset_base.hpp>
#include <boost/mysql/row.hpp>
#include <boost/mysql/statement_base.hpp>
#include <boost/asio/buffer.hpp>
#include <utility>
// connect
template <class Stream>
@@ -53,12 +54,8 @@ void boost::mysql::connection<Stream>::connect(
template <class Stream>
template <
class EndpointType,
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) CompletionToken
>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
CompletionToken,
void(boost::mysql::error_code)
)
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(boost::mysql::error_code))
boost::mysql::connection<Stream>::async_connect(
const EndpointType& endpoint,
const handshake_params& params,
@@ -76,7 +73,6 @@ boost::mysql::connection<Stream>::async_connect(
);
}
// handshake
template <class Stream>
void boost::mysql::connection<Stream>::handshake(
@@ -90,9 +86,7 @@ void boost::mysql::connection<Stream>::handshake(
}
template <class Stream>
void boost::mysql::connection<Stream>::handshake(
const handshake_params& params
)
void boost::mysql::connection<Stream>::handshake(const handshake_params& params)
{
detail::error_block blk;
handshake(params, blk.err, blk.info);
@@ -101,10 +95,7 @@ void boost::mysql::connection<Stream>::handshake(
template <class Stream>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
CompletionToken,
void(boost::mysql::error_code)
)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(boost::mysql::error_code))
boost::mysql::connection<Stream>::async_handshake(
const handshake_params& params,
error_info& output_info,
@@ -145,13 +136,8 @@ void boost::mysql::connection<Stream>::query(
}
template <class Stream>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(
void(::boost::mysql::error_code)
) CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
CompletionToken,
void(boost::mysql::error_code)
)
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(boost::mysql::error_code))
boost::mysql::connection<Stream>::async_query(
boost::string_view query_string,
resultset<Stream>& result,
@@ -169,7 +155,6 @@ boost::mysql::connection<Stream>::async_query(
);
}
// Prepare statement
template <class Stream>
void boost::mysql::connection<Stream>::prepare_statement(
@@ -195,13 +180,8 @@ void boost::mysql::connection<Stream>::prepare_statement(
}
template <class Stream>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(
void(::boost::mysql::error_code)
) CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
CompletionToken,
void(boost::mysql::error_code)
)
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(boost::mysql::error_code))
boost::mysql::connection<Stream>::async_prepare_statement(
boost::string_view stmt,
statement<Stream>& output,
@@ -221,10 +201,7 @@ boost::mysql::connection<Stream>::async_prepare_statement(
// Close
template <class Stream>
void boost::mysql::connection<Stream>::close(
error_code& err,
error_info& info
)
void boost::mysql::connection<Stream>::close(error_code& err, error_info& info)
{
detail::clear_errors(err, info);
detail::close_connection(get_channel(), err, info);
@@ -240,14 +217,8 @@ void boost::mysql::connection<Stream>::close()
template <class Stream>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
CompletionToken,
void(boost::mysql::error_code)
)
boost::mysql::connection<Stream>::async_close(
error_info& output_info,
CompletionToken&& token
)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(boost::mysql::error_code))
boost::mysql::connection<Stream>::async_close(error_info& output_info, CompletionToken&& token)
{
output_info.clear();
return detail::async_close_connection(
@@ -258,10 +229,7 @@ boost::mysql::connection<Stream>::async_close(
}
template <class Stream>
void boost::mysql::connection<Stream>::quit(
error_code& err,
error_info& info
)
void boost::mysql::connection<Stream>::quit(error_code& err, error_info& info)
{
detail::clear_errors(err, info);
detail::quit_connection(get_channel(), err, info);
@@ -277,14 +245,8 @@ void boost::mysql::connection<Stream>::quit()
template <class Stream>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code)) CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
CompletionToken,
void(boost::mysql::error_code)
)
boost::mysql::connection<Stream>::async_quit(
error_info& output_info,
CompletionToken&& token
)
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(boost::mysql::error_code))
boost::mysql::connection<Stream>::async_quit(error_info& output_info, CompletionToken&& token)
{
output_info.clear();
return detail::async_quit_connection(

View File

@@ -12,8 +12,10 @@
#include <boost/mysql/error.hpp>
#include <boost/mysql/impl/error_descriptions.hpp>
#include <boost/system/system_error.hpp>
#include <boost/config.hpp>
#include <boost/system/system_error.hpp>
#include <algorithm>
namespace boost {
@@ -25,18 +27,16 @@ struct is_error_code_enum<mysql::errc>
static constexpr bool value = true;
};
} // system
} // namespace system
namespace mysql {
namespace detail {
inline const char* error_to_string(errc error) noexcept
{
auto it = std::find_if(
std::begin(all_errors),
std::end(all_errors),
[error] (error_entry ent) { return error == ent.value; }
);
auto it = std::find_if(std::begin(all_errors), std::end(all_errors), [error](error_entry ent) {
return error == ent.value;
});
return it == std::end(all_errors) ? "<unknown error>" : it->message;
}
@@ -62,10 +62,7 @@ inline mysql_error_category_t& get_mysql_error_category() noexcept
inline mysql_error_category_t mysql_error_category;
inline mysql_error_category_t& get_mysql_error_category() noexcept
{
return mysql_error_category;
}
inline mysql_error_category_t& get_mysql_error_category() noexcept { return mysql_error_category; }
#endif
@@ -92,24 +89,18 @@ struct error_block
void check() { detail::check_error_code(err, info); }
};
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
inline std::ostream& boost::mysql::operator<<(
std::ostream& os,
errc value
)
inline std::ostream& boost::mysql::operator<<(std::ostream& os, errc value)
{
return os << detail::error_to_string(value);
}
inline boost::mysql::error_code boost::mysql::make_error_code(
errc error
)
inline boost::mysql::error_code boost::mysql::make_error_code(errc error)
{
return boost::system::error_code(static_cast<int>(error), detail::get_mysql_error_category());
}
#endif

View File

@@ -10,34 +10,30 @@
#pragma once
#include <boost/mysql/field.hpp>
#include <boost/mysql/detail/protocol/date.hpp>
#include <boost/mysql/bad_field_access.hpp>
#include <boost/mysql/detail/protocol/date.hpp>
#include <boost/mysql/field.hpp>
#include <cstdint>
#include <string>
void boost::mysql::field::from_view(
const field_view& fv
)
void boost::mysql::field::from_view(const field_view& fv)
{
switch (fv.kind())
{
case field_kind::null: repr_.data.emplace<detail::field_impl::null_t>(); break;
case field_kind::int64: repr_.data.emplace<std::int64_t>(fv.get_int64()); break;
case field_kind::uint64: repr_.data.emplace<std::uint64_t>(fv.get_uint64()); break;
case field_kind::string: repr_.data.emplace<std::string>(fv.get_string()); break;
case field_kind::float_: repr_.data.emplace<float>(fv.get_float()); break;
case field_kind::double_: repr_.data.emplace<double>(fv.get_double()); break;
case field_kind::date: repr_.data.emplace<date>(fv.get_date()); break;
case field_kind::datetime: repr_.data.emplace<datetime>(fv.get_datetime()); break;
case field_kind::time: repr_.data.emplace<time>(fv.get_time()); break;
case field_kind::null: repr_.data.emplace<detail::field_impl::null_t>(); break;
case field_kind::int64: repr_.data.emplace<std::int64_t>(fv.get_int64()); break;
case field_kind::uint64: repr_.data.emplace<std::uint64_t>(fv.get_uint64()); break;
case field_kind::string: repr_.data.emplace<std::string>(fv.get_string()); break;
case field_kind::float_: repr_.data.emplace<float>(fv.get_float()); break;
case field_kind::double_: repr_.data.emplace<double>(fv.get_double()); break;
case field_kind::date: repr_.data.emplace<date>(fv.get_date()); break;
case field_kind::datetime: repr_.data.emplace<datetime>(fv.get_datetime()); break;
case field_kind::time: repr_.data.emplace<time>(fv.get_time()); break;
}
}
inline std::ostream& boost::mysql::operator<<(
std::ostream& os,
const field& value
)
inline std::ostream& boost::mysql::operator<<(std::ostream& os, const field& value)
{
return os << field_view(value);
}

View File

@@ -11,12 +11,10 @@
#pragma once
#include <boost/mysql/field_kind.hpp>
#include <ostream>
inline std::ostream& boost::mysql::operator<<(
std::ostream& os,
boost::mysql::field_kind v
)
inline std::ostream& boost::mysql::operator<<(std::ostream& os, boost::mysql::field_kind v)
{
switch (v)
{

View File

@@ -10,11 +10,12 @@
#pragma once
#include <boost/mysql/field_view.hpp>
#include <boost/mysql/detail/protocol/date.hpp>
#include <boost/mysql/bad_field_access.hpp>
#include <ostream>
#include <boost/mysql/detail/protocol/date.hpp>
#include <boost/mysql/field_view.hpp>
#include <limits>
#include <ostream>
namespace boost {
namespace mysql {
@@ -24,7 +25,7 @@ inline std::ostream& print_date(std::ostream& os, const date& value)
{
assert(value >= min_date && value <= max_date);
auto ymd = detail::days_to_ymd(value.time_since_epoch().count());
char buffer [32] {};
char buffer[32]{};
snprintf(buffer, sizeof(buffer), "%04d-%02u-%02u", ymd.years, ymd.month, ymd.day);
os << buffer;
return os;
@@ -34,14 +35,17 @@ inline std::ostream& print_time(std::ostream& os, const time& value)
{
using namespace std::chrono;
assert(value >= min_time && value <= max_time);
char buffer [64] {};
char buffer[64]{};
const char* sign = value < microseconds(0) ? "-" : "";
auto num_micros = value % seconds(1);
auto num_secs = duration_cast<seconds>(value % minutes(1) - num_micros);
auto num_mins = duration_cast<minutes>(value % hours(1) - num_secs);
auto num_hours = duration_cast<hours>(value - num_mins);
snprintf(buffer, sizeof(buffer), "%s%02d:%02u:%02u.%06u",
snprintf(
buffer,
sizeof(buffer),
"%s%02d:%02u:%02u.%06u",
sign,
static_cast<int>(std::abs(num_hours.count())),
static_cast<unsigned>(std::abs(num_mins.count())),
@@ -60,146 +64,98 @@ inline std::ostream& print_datetime(std::ostream& os, const datetime& value)
if (date_part > value)
date_part -= days(1);
auto tod = value - date_part;
print_date(os, date_part); // date part
os << ' '; // separator
print_time(os, duration_cast<time>(tod)); // time of day part
print_date(os, date_part); // date part
os << ' '; // separator
print_time(os, duration_cast<time>(tod)); // time of day part
return os;
}
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(
signed char v
) noexcept :
ikind_(internal_kind::int64),
repr_(std::int64_t(v))
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(signed char v) noexcept
: ikind_(internal_kind::int64), repr_(std::int64_t(v))
{
}
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(
short v
) noexcept :
ikind_(internal_kind::int64),
repr_(std::int64_t(v))
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(short v) noexcept
: ikind_(internal_kind::int64), repr_(std::int64_t(v))
{
}
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(
int v
) noexcept :
ikind_(internal_kind::int64),
repr_(std::int64_t(v))
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(int v) noexcept
: ikind_(internal_kind::int64), repr_(std::int64_t(v))
{
}
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(
long v
) noexcept :
ikind_(internal_kind::int64),
repr_(std::int64_t(v))
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(long v) noexcept
: ikind_(internal_kind::int64), repr_(std::int64_t(v))
{
}
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(
long long v
) noexcept :
ikind_(internal_kind::int64),
repr_(std::int64_t(v))
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(long long v) noexcept
: ikind_(internal_kind::int64), repr_(std::int64_t(v))
{
}
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(
unsigned char v
) noexcept :
ikind_(internal_kind::uint64),
repr_(std::uint64_t(v))
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(unsigned char v) noexcept
: ikind_(internal_kind::uint64), repr_(std::uint64_t(v))
{
}
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(
unsigned short v
) noexcept :
ikind_(internal_kind::uint64),
repr_(std::uint64_t(v))
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(unsigned short v) noexcept
: ikind_(internal_kind::uint64), repr_(std::uint64_t(v))
{
}
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(
unsigned int v
) noexcept :
ikind_(internal_kind::uint64),
repr_(std::uint64_t(v))
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(unsigned int v) noexcept
: ikind_(internal_kind::uint64), repr_(std::uint64_t(v))
{
}
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(
unsigned long v
) noexcept :
ikind_(internal_kind::uint64),
repr_(std::uint64_t(v))
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(unsigned long v) noexcept
: ikind_(internal_kind::uint64), repr_(std::uint64_t(v))
{
}
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(
unsigned long long v
) noexcept :
ikind_(internal_kind::uint64),
repr_(std::uint64_t(v))
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(unsigned long long v) noexcept
: ikind_(internal_kind::uint64), repr_(std::uint64_t(v))
{
}
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(
boost::string_view v
) noexcept :
ikind_(internal_kind::string),
repr_(v)
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(boost::string_view v) noexcept
: ikind_(internal_kind::string), repr_(v)
{
}
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(
float v
) noexcept :
ikind_(internal_kind::float_),
repr_(v)
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(float v) noexcept
: ikind_(internal_kind::float_), repr_(v)
{
}
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(
double v
) noexcept :
ikind_(internal_kind::double_),
repr_(v)
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(double v) noexcept
: ikind_(internal_kind::double_), repr_(v)
{
}
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(
const date& v
) noexcept :
ikind_(internal_kind::date),
repr_(v)
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(const date& v) noexcept
: ikind_(internal_kind::date), repr_(v)
{
}
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(
const datetime& v
) noexcept :
ikind_(internal_kind::datetime),
repr_(v)
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(const datetime& v) noexcept
: ikind_(internal_kind::datetime), repr_(v)
{
}
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(
const time& v
) noexcept :
ikind_(internal_kind::time),
repr_(v)
BOOST_CXX14_CONSTEXPR boost::mysql::field_view::field_view(const time& v) noexcept
: ikind_(internal_kind::time), repr_(v)
{
}
BOOST_CXX14_CONSTEXPR inline boost::mysql::field_kind boost::mysql::field_view::kind() const noexcept
BOOST_CXX14_CONSTEXPR inline boost::mysql::field_kind boost::mysql::field_view::kind(
) const noexcept
{
switch (ikind_)
{
@@ -214,12 +170,11 @@ BOOST_CXX14_CONSTEXPR inline boost::mysql::field_kind boost::mysql::field_view::
case internal_kind::time: return field_kind::time;
case internal_kind::field_ptr: return repr_.field_ptr->kind();
// sv_offset values must be converted via offset_to_string_view before calling any other fn
default: return field_kind::null;
default: return field_kind::null;
}
}
BOOST_CXX14_CONSTEXPR std::int64_t
boost::mysql::field_view::as_int64() const
BOOST_CXX14_CONSTEXPR std::int64_t boost::mysql::field_view::as_int64() const
{
if (is_field_ptr())
return repr_.field_ptr->as<std::int64_t>();
@@ -227,8 +182,7 @@ boost::mysql::field_view::as_int64() const
return repr_.int64;
}
BOOST_CXX14_CONSTEXPR std::uint64_t
boost::mysql::field_view::as_uint64() const
BOOST_CXX14_CONSTEXPR std::uint64_t boost::mysql::field_view::as_uint64() const
{
if (is_field_ptr())
return repr_.field_ptr->as<std::uint64_t>();
@@ -236,8 +190,7 @@ boost::mysql::field_view::as_uint64() const
return repr_.uint64;
}
BOOST_CXX14_CONSTEXPR boost::string_view
boost::mysql::field_view::as_string() const
BOOST_CXX14_CONSTEXPR boost::string_view boost::mysql::field_view::as_string() const
{
if (is_field_ptr())
return repr_.field_ptr->as<std::string>();
@@ -245,8 +198,7 @@ boost::mysql::field_view::as_string() const
return repr_.get_string();
}
BOOST_CXX14_CONSTEXPR float
boost::mysql::field_view::as_float() const
BOOST_CXX14_CONSTEXPR float boost::mysql::field_view::as_float() const
{
if (is_field_ptr())
return repr_.field_ptr->as<float>();
@@ -254,8 +206,7 @@ boost::mysql::field_view::as_float() const
return repr_.float_;
}
BOOST_CXX14_CONSTEXPR double
boost::mysql::field_view::as_double() const
BOOST_CXX14_CONSTEXPR double boost::mysql::field_view::as_double() const
{
if (is_field_ptr())
return repr_.field_ptr->as<double>();
@@ -263,8 +214,7 @@ boost::mysql::field_view::as_double() const
return repr_.double_;
}
BOOST_CXX14_CONSTEXPR boost::mysql::date
boost::mysql::field_view::as_date() const
BOOST_CXX14_CONSTEXPR boost::mysql::date boost::mysql::field_view::as_date() const
{
if (is_field_ptr())
return repr_.field_ptr->as<date>();
@@ -272,8 +222,7 @@ boost::mysql::field_view::as_date() const
return repr_.get_date();
}
BOOST_CXX14_CONSTEXPR boost::mysql::datetime
boost::mysql::field_view::as_datetime() const
BOOST_CXX14_CONSTEXPR boost::mysql::datetime boost::mysql::field_view::as_datetime() const
{
if (is_field_ptr())
return repr_.field_ptr->as<datetime>();
@@ -281,8 +230,7 @@ boost::mysql::field_view::as_datetime() const
return repr_.get_datetime();
}
BOOST_CXX14_CONSTEXPR boost::mysql::time
boost::mysql::field_view::as_time() const
BOOST_CXX14_CONSTEXPR boost::mysql::time boost::mysql::field_view::as_time() const
{
if (is_field_ptr())
return repr_.field_ptr->as<time>();
@@ -290,71 +238,61 @@ boost::mysql::field_view::as_time() const
return repr_.get_time();
}
BOOST_CXX14_CONSTEXPR std::int64_t
boost::mysql::field_view::get_int64() const noexcept
BOOST_CXX14_CONSTEXPR std::int64_t boost::mysql::field_view::get_int64() const noexcept
{
return is_field_ptr() ? repr_.field_ptr->get<std::int64_t>() : repr_.int64;
}
BOOST_CXX14_CONSTEXPR std::uint64_t
boost::mysql::field_view::get_uint64() const noexcept
BOOST_CXX14_CONSTEXPR std::uint64_t boost::mysql::field_view::get_uint64() const noexcept
{
return is_field_ptr() ? repr_.field_ptr->get<std::uint64_t>() : repr_.uint64;
}
BOOST_CXX14_CONSTEXPR boost::string_view
boost::mysql::field_view::get_string() const noexcept
BOOST_CXX14_CONSTEXPR boost::string_view boost::mysql::field_view::get_string() const noexcept
{
return is_field_ptr() ? boost::string_view(repr_.field_ptr->get<std::string>()) : repr_.get_string();
return is_field_ptr() ? boost::string_view(repr_.field_ptr->get<std::string>())
: repr_.get_string();
}
BOOST_CXX14_CONSTEXPR float
boost::mysql::field_view::get_float() const noexcept
BOOST_CXX14_CONSTEXPR float boost::mysql::field_view::get_float() const noexcept
{
return is_field_ptr() ? repr_.field_ptr->get<float>() : repr_.float_;
}
BOOST_CXX14_CONSTEXPR double
boost::mysql::field_view::get_double() const noexcept
BOOST_CXX14_CONSTEXPR double boost::mysql::field_view::get_double() const noexcept
{
return is_field_ptr() ? repr_.field_ptr->get<double>() : repr_.double_;
}
BOOST_CXX14_CONSTEXPR boost::mysql::date
boost::mysql::field_view::get_date() const noexcept
BOOST_CXX14_CONSTEXPR boost::mysql::date boost::mysql::field_view::get_date() const noexcept
{
return is_field_ptr() ? repr_.field_ptr->get<date>() : repr_.get_date();
}
BOOST_CXX14_CONSTEXPR boost::mysql::datetime
boost::mysql::field_view::get_datetime() const noexcept
BOOST_CXX14_CONSTEXPR boost::mysql::datetime boost::mysql::field_view::get_datetime() const noexcept
{
return is_field_ptr() ? repr_.field_ptr->get<datetime>() : repr_.get_datetime();
}
BOOST_CXX14_CONSTEXPR boost::mysql::time
boost::mysql::field_view::get_time() const noexcept
BOOST_CXX14_CONSTEXPR boost::mysql::time boost::mysql::field_view::get_time() const noexcept
{
return is_field_ptr() ? repr_.field_ptr->get<time>() : repr_.get_time();
}
BOOST_CXX14_CONSTEXPR void boost::mysql::field_view::check_kind(
internal_kind expected
) const
BOOST_CXX14_CONSTEXPR void boost::mysql::field_view::check_kind(internal_kind expected) const
{
if (ikind_ != expected)
throw bad_field_access();
}
BOOST_CXX14_CONSTEXPR bool boost::mysql::field_view::operator==(
const field_view& rhs
BOOST_CXX14_CONSTEXPR bool boost::mysql::field_view::operator==(const field_view& rhs
) const noexcept
{
// Make operator== work for types not representable by field_kind
if (ikind_ == internal_kind::sv_offset)
{
return rhs.ikind_ == internal_kind::sv_offset &&
repr_.get_sv_offset() == rhs.repr_.get_sv_offset();
repr_.get_sv_offset() == rhs.repr_.get_sv_offset();
}
auto k = kind(), rhs_k = rhs.kind();
@@ -387,31 +325,23 @@ BOOST_CXX14_CONSTEXPR bool boost::mysql::field_view::operator==(
}
else
return false;
case field_kind::string:
return rhs_k == field_kind::string && get_string() == rhs.get_string();
case field_kind::float_:
return rhs_k == field_kind::float_ && get_float() == rhs.get_float();
case field_kind::string: return rhs_k == field_kind::string && get_string() == rhs.get_string();
case field_kind::float_: return rhs_k == field_kind::float_ && get_float() == rhs.get_float();
case field_kind::double_:
return rhs_k == field_kind::double_ && get_double() == rhs.get_double();
case field_kind::date:
return rhs_k == field_kind::date && get_date() == rhs.get_date();
case field_kind::date: return rhs_k == field_kind::date && get_date() == rhs.get_date();
case field_kind::datetime:
return rhs_k == field_kind::datetime && get_datetime() == rhs.get_datetime();
case field_kind::time:
return rhs_k == field_kind::time && get_time() == rhs.get_time();
case field_kind::time: return rhs_k == field_kind::time && get_time() == rhs.get_time();
}
}
inline std::ostream& boost::mysql::operator<<(
std::ostream& os,
const field_view& value
)
inline std::ostream& boost::mysql::operator<<(std::ostream& os, const field_view& value)
{
// Make operator<< work for detail::string_view_offset types
if (value.ikind_ == field_view::internal_kind::sv_offset)
return os << "<sv_offset>";
switch (value.kind())
{
case field_kind::null: return os << "<NULL>";
@@ -428,13 +358,9 @@ inline std::ostream& boost::mysql::operator<<(
template <class... Types>
BOOST_CXX14_CONSTEXPR std::array<boost::mysql::field_view, sizeof...(Types)>
boost::mysql::make_field_views(
Types&&... args
)
boost::mysql::make_field_views(Types&&... args)
{
return std::array<field_view, sizeof...(Types)>{{field_view(std::forward<Types>(args))...}};
}
#endif

View File

@@ -16,9 +16,7 @@ namespace boost {
namespace mysql {
namespace detail {
inline field_type compute_field_type_string(
std::uint32_t flags
)
inline field_type compute_field_type_string(std::uint32_t flags)
{
if (flags & column_flags::set)
return field_type::set;
@@ -30,9 +28,7 @@ inline field_type compute_field_type_string(
return field_type::char_;
}
inline field_type compute_field_type_var_string(
std::uint32_t flags
)
inline field_type compute_field_type_var_string(std::uint32_t flags)
{
if (flags & column_flags::binary)
return field_type::varbinary;
@@ -40,9 +36,7 @@ inline field_type compute_field_type_var_string(
return field_type::varchar;
}
inline field_type compute_field_type_blob(
std::uint32_t flags
)
inline field_type compute_field_type_blob(std::uint32_t flags)
{
if (flags & column_flags::binary)
return field_type::blob;
@@ -50,16 +44,12 @@ inline field_type compute_field_type_blob(
return field_type::text;
}
inline field_type compute_field_type(
protocol_field_type protocol_type,
std::uint32_t flags
)
inline field_type compute_field_type(protocol_field_type protocol_type, std::uint32_t flags)
{
switch (protocol_type)
{
case protocol_field_type::decimal:
case protocol_field_type::newdecimal:
return field_type::decimal;
case protocol_field_type::newdecimal: return field_type::decimal;
case protocol_field_type::geometry: return field_type::geometry;
case protocol_field_type::tiny: return field_type::tinyint;
case protocol_field_type::short_: return field_type::smallint;
@@ -81,9 +71,9 @@ inline field_type compute_field_type(
}
}
} // detail
} // mysql
} // boost
} // namespace detail
} // namespace mysql
} // namespace boost
inline boost::mysql::field_type boost::mysql::metadata::type() const noexcept
{

View File

@@ -10,23 +10,19 @@
#pragma once
#include <boost/mysql/resultset.hpp>
#include <boost/mysql/detail/network_algorithms/read_all_rows.hpp>
#include <boost/mysql/detail/network_algorithms/read_one_row.hpp>
#include <boost/mysql/detail/network_algorithms/read_some_rows.hpp>
#include <boost/mysql/detail/network_algorithms/read_all_rows.hpp>
#include <boost/mysql/resultset.hpp>
// Read one row
template <class Stream>
boost::mysql::row_view boost::mysql::resultset<Stream>::read_one(
error_code& err,
error_info& info
)
boost::mysql::row_view boost::mysql::resultset<Stream>::read_one(error_code& err, error_info& info)
{
detail::clear_errors(err, info);
return detail::read_one_row(get_channel(), *this, err, info);
}
template <class Stream>
boost::mysql::row_view boost::mysql::resultset<Stream>::read_one()
{
@@ -37,17 +33,13 @@ boost::mysql::row_view boost::mysql::resultset<Stream>::read_one()
}
template <class Stream>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(
void(::boost::mysql::error_code, ::boost::mysql::row_view)
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, ::boost::mysql::row_view)
) CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
CompletionToken,
void(boost::mysql::error_code, boost::mysql::row_view)
)
boost::mysql::resultset<Stream>::async_read_one(
error_info& output_info,
CompletionToken&& token
)
boost::mysql::resultset<Stream>::async_read_one(error_info& output_info, CompletionToken&& token)
{
output_info.clear();
return detail::async_read_one_row(
@@ -60,16 +52,13 @@ boost::mysql::resultset<Stream>::async_read_one(
// Read some rows
template <class Stream>
boost::mysql::rows_view boost::mysql::resultset<Stream>::read_some(
error_code& err,
error_info& info
)
boost::mysql::rows_view
boost::mysql::resultset<Stream>::read_some(error_code& err, error_info& info)
{
detail::clear_errors(err, info);
return detail::read_some_rows(get_channel(), *this, err, info);
}
template <class Stream>
boost::mysql::rows_view boost::mysql::resultset<Stream>::read_some()
{
@@ -80,17 +69,14 @@ boost::mysql::rows_view boost::mysql::resultset<Stream>::read_some()
}
template <class Stream>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(
void(::boost::mysql::error_code, ::boost::mysql::rows_view)
) CompletionToken>
template <
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, ::boost::mysql::rows_view))
CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
CompletionToken,
void(boost::mysql::error_code, boost::mysql::rows_view)
)
boost::mysql::resultset<Stream>::async_read_some(
error_info& output_info,
CompletionToken&& token
)
boost::mysql::resultset<Stream>::async_read_some(error_info& output_info, CompletionToken&& token)
{
output_info.clear();
return detail::async_read_some_rows(
@@ -103,16 +89,12 @@ boost::mysql::resultset<Stream>::async_read_some(
// Read all rows
template <class Stream>
boost::mysql::rows_view boost::mysql::resultset<Stream>::read_all(
error_code& err,
error_info& info
)
boost::mysql::rows_view boost::mysql::resultset<Stream>::read_all(error_code& err, error_info& info)
{
detail::clear_errors(err, info);
return detail::read_all_rows(get_channel(), *this, err, info);
}
template <class Stream>
boost::mysql::rows_view boost::mysql::resultset<Stream>::read_all()
{
@@ -123,17 +105,14 @@ boost::mysql::rows_view boost::mysql::resultset<Stream>::read_all()
}
template <class Stream>
template <BOOST_ASIO_COMPLETION_TOKEN_FOR(
void(::boost::mysql::error_code, ::boost::mysql::rows_view)
) CompletionToken>
template <
BOOST_ASIO_COMPLETION_TOKEN_FOR(void(::boost::mysql::error_code, ::boost::mysql::rows_view))
CompletionToken>
BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
CompletionToken,
void(boost::mysql::error_code, boost::mysql::rows_view)
)
boost::mysql::resultset<Stream>::async_read_all(
error_info& output_info,
CompletionToken&& token
)
boost::mysql::resultset<Stream>::async_read_all(error_info& output_info, CompletionToken&& token)
{
output_info.clear();
return detail::async_read_all_rows(

Some files were not shown because too many files have changed in this diff Show More