BuildDarkFlame/_deps/mysql-src/include/mysqlx/devapi/detail/settings.h
2022-01-02 18:29:32 -06:00

277 lines
7.6 KiB
C++

/*
* Copyright (c) 2017, 2020, Oracle and/or its affiliates.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2.0, as
* published by the Free Software Foundation.
*
* This program is also distributed with certain software (including
* but not limited to OpenSSL) that is licensed under separate terms,
* as designated in a particular file or component or in included license
* documentation. The authors of MySQL hereby grant you an
* additional permission to link the program and your derivative works
* with the separately licensed software that they have included with
* MySQL.
*
* Without limiting anything contained in the foregoing, this file,
* which is part of MySQL Connector/C++, is also subject to the
* Universal FOSS Exception, version 1.0, a copy of which can be found at
* http://oss.oracle.com/licenses/universal-foss-exception.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License, version 2.0, for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef MYSQLX_DETAIL_SETTINGS_H
#define MYSQLX_DETAIL_SETTINGS_H
#include "../common.h"
#include "../document.h"
#include <chrono>
#include <list>
#include <chrono>
namespace mysqlx {
MYSQLX_ABI_BEGIN(2,0)
namespace internal {
/*
Note: Options and SSLMode enumerations are given by Traits template parameter
to allow defining (and documenting) them in the main settings.h header.
*/
template <typename Traits>
class Settings_detail
: public common::Settings_impl
{
using Value = mysqlx::Value;
using Option = typename Traits::Options;
using COption = typename Traits::COptions;
using SSLMode = typename Traits::SSLMode;
using AuthMethod = typename Traits::AuthMethod;
using CompressionMode = typename Traits::CompressionMode;
public:
template <bool session_only, typename OPT, typename... Ty>
void set(OPT opt, Ty&&... rest)
{
do_set(get_options<session_only>(opt, std::forward<Ty>(rest)...));
}
protected:
/*
Declare options that require specific type of value (mostly enumerations).
For such options we do not accept setting them to arbitrary values. Instead
an overload of opt_val() with appropriate type will be used to set value
of the option.
*/
#define OPT_VAL_TYPE(X) \
X(SSL_MODE,SSLMode) \
X(AUTH,AuthMethod)
#define CHECK_OPT(Opt,Type) \
if (opt == Session_option_impl::Opt) \
throw Error(#Opt "setting requires value of type " #Type);
/*
Store option value in Value object (with basic run-time type checks)
TODO: More precise type checking using per-option types.
*/
static Value opt_val(int opt, Value &&val)
{
OPT_VAL_TYPE(CHECK_OPT)
return val;
}
/*
For types which are not convertible to Value, but can be converted to string
go through string conversion.
*/
static Value opt_val(int opt, std::nullptr_t)
{
return opt_val(opt, Value());
}
template <
typename V,
typename std::enable_if<std::is_convertible<V, string>::value>::type*
= nullptr
>
static Value opt_val(int opt, V &&val)
{
return opt_val(opt, Value(string(val)));
}
static Value opt_val(int opt, SSLMode m)
{
if (opt != Session_option_impl::SSL_MODE)
throw Error(
"SessionSettings::SSLMode value can only be used on SSL_MODE setting."
);
return unsigned(m);
}
static Value opt_val(int opt, AuthMethod m)
{
if (opt != Session_option_impl::AUTH)
throw Error(
"SessionSettings::AuthMethod value can only be used on AUTH setting."
);
return unsigned(m);
}
static Value opt_val(int opt, CompressionMode m)
{
if (opt != Session_option_impl::COMPRESSION)
throw Error(
"SessionSettings::CompressionMode value can only be used on COMPRESSION setting."
);
return unsigned(m);
}
// Note: is_range<C> is true for string types, which should not be treated
// as arrays of characters, but as single Values.
template <
typename C,
typename std::enable_if<is_range<C>::value>::type* = nullptr,
typename std::enable_if<!std::is_convertible<C,Value>::value>::type*
= nullptr
>
static Value opt_val(int opt, const C &container)
{
return Value(std::begin(container), std::end(container));
}
template<typename _Rep, typename _Period>
static Value opt_val(
int opt, const std::chrono::duration<_Rep, _Period> &duration
)
{
if (opt != Session_option_impl::CONNECT_TIMEOUT &&
opt != Client_option_impl::POOL_QUEUE_TIMEOUT &&
opt != Client_option_impl::POOL_MAX_IDLE_TIME)
{
std::stringstream err_msg;
err_msg << "Option " << option_name(opt) << " does not accept time value";
throw_error(err_msg.str().c_str());
}
return Value(std::chrono::duration_cast<std::chrono::milliseconds>(duration)
.count());
}
// Handle values that are directly convertible to Value.
template <
typename V,
typename std::enable_if<std::is_convertible<V,int>::value>::type*
= nullptr,
typename std::enable_if<std::is_convertible<V,Value>::value>::type*
= nullptr
>
static Value opt_val(int opt, V &&val)
{
return opt_val(opt, Value(val));
}
using session_opt_val_t = std::pair<int, Value>;
using session_opt_list_t = std::list<session_opt_val_t>;
/*
Set list of options with consistency checks.
This operation is atomic - settings are changed only if all options could
be set without error, otherwise settings remain unchanged.
*/
void do_set(session_opt_list_t&&);
// Note: for ABI compatibility
void PUBLIC_API do_set(std::list<std::pair<int, common::Value>>&&);
/*
Templates that collect varargs list of options into opt_list_t list
that can be passed to do_set().
*/
template<bool session_only>
static session_opt_list_t get_options()
{
return {};
}
/*
Note: if we ever support options without values, another overload is
needed: get_options(Option opt, Option opt1, R&... rest).
*/
template <
bool session_only, typename V, typename... Ty,
typename std::enable_if<session_only, int>::type* = nullptr
>
static session_opt_list_t get_options(Option opt, V&& val, Ty&&... rest)
{
int oo(static_cast<int>(opt));
session_opt_list_t opts = get_options<session_only>(std::forward<Ty>(rest)...);
opts.emplace_front(oo,
Settings_detail::opt_val(oo, std::forward<V>(val))
);
return opts;
}
template <
bool session_only, typename V, typename... Ty,
typename std::enable_if<!session_only, int>::type* = nullptr
>
static session_opt_list_t get_options(COption opt, V&& val, Ty&&... rest)
{
int oo(static_cast<int>(opt));
session_opt_list_t opts = get_options<session_only>(std::forward<Ty>(rest)...);
opts.emplace_front(
oo,
Settings_detail::opt_val(oo, std::forward<V>(val))
);
return opts;
}
/*
Note: Methods below rely on the fact that DevAPI SessionOption constants
have the same numeric values as common::Settings_impl::Option ones.
*/
bool has_option(COption opt) const
{
return Settings_impl::has_option(opt);
}
Value get(COption opt)
{
return Settings_impl::get(opt);
}
};
} // internal namespace
MYSQLX_ABI_END(2,0)
} // mysqlx namespace
#endif