// // Copyright (c) 2019-2024 Ruben Perez Hidalgo (rubenperez038 at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_MYSQL_FIELD_HPP #define BOOST_MYSQL_FIELD_HPP #include #include #include #include #include #include #include #include #include #include #ifdef __cpp_lib_string_view #include #endif namespace boost { namespace mysql { /** * \brief Variant-like class that can represent of any of the allowed database types. * \details * This is a regular variant-like class that can represent any of the types that MySQL allows. It * has value semantics (as opposed to \ref field_view). Instances of this class are not created * by the library. They should be created by the user, when the reference semantics of * \ref field_view are not appropriate. * \n * Like a variant, at any point, a `field` always contains a value of * certain type. You can query the type using \ref kind and the `is_xxx` functions * like \ref is_int64. Use `as_xxx` and `get_xxx` for checked and unchecked value * access, respectively. You can mutate a `field` by calling the assignment operator, * or using the lvalue references returned by `as_xxx` and `get_xxx`. */ class field { public: /** * \brief Constructs a `field` holding NULL. * \par Exception safety * No-throw guarantee. */ field() = default; /** * \brief Copy constructor. * \par Exception safety * Strong guarantee. Internal allocations may throw. */ field(const field&) = default; /** * \brief Move constructor. * \par Exception safety * No-throw guarantee. * * \par Object lifetimes * All references into `other` are invalidated, including the ones obtained by calling * get_xxx, as_xxx and \ref field::operator field_view(). */ field(field&& other) = default; /** * \brief Copy assignment. * \par Exception safety * Basic guarantee. Internal allocations may throw. * * \par Object lifetimes * Invalidates references obtained by as_xxx and get_xxx functions, * but not the ones obtained by \ref field::operator field_view(). */ field& operator=(const field&) = default; /** * \brief Move assignment. * \par Exception safety * No-throw guarantee. * * \par Object lifetimes * Invalidates references to `*this` obtained by as_xxx and get_xxx functions, * but not the ones obtained by \ref field::operator field_view(). All references into `other` * are invalidated, including the ones obtained by calling get_xxx, as_xxx and * \ref field::operator field_view(). */ field& operator=(field&& other) = default; /// Destructor. ~field() = default; /** * \brief Constructs a `field` holding NULL. * \details * Caution: `field(NULL)` will __NOT__ match this overload. It will try to construct * a `string_view` from a NULL C string, causing undefined behavior. * * \par Exception safety * No-throw guarantee. */ explicit field(std::nullptr_t) noexcept {} /** * \brief Constructs a `field` holding an `int64`. * \par Exception safety * No-throw guarantee. */ explicit field(signed char v) noexcept : repr_(std::int64_t(v)) {} /// \copydoc field(signed char) explicit field(short v) noexcept : repr_(std::int64_t(v)) {} /// \copydoc field(signed char) explicit field(int v) noexcept : repr_(std::int64_t(v)) {} /// \copydoc field(signed char) explicit field(long v) noexcept : repr_(std::int64_t(v)) {} /// \copydoc field(signed char) explicit field(long long v) noexcept : repr_(std::int64_t(v)) {} /** * \brief Constructs a `field` holding an `uint64`. * \par Exception safety * No-throw guarantee. */ explicit field(unsigned char v) noexcept : repr_(std::uint64_t(v)) {} /// \copydoc field(unsigned char) explicit field(unsigned short v) noexcept : repr_(std::uint64_t(v)) {} /// \copydoc field(unsigned char) explicit field(unsigned int v) noexcept : repr_(std::uint64_t(v)) {} /// \copydoc field(unsigned char) explicit field(unsigned long v) noexcept : repr_(std::uint64_t(v)) {} /// \copydoc field(unsigned char) explicit field(unsigned long long v) noexcept : repr_(std::uint64_t(v)) {} /** * \brief Constructors from character types would incorrectly construct a `field` holding an integer, * so they are not allowed. */ explicit field(char) = delete; /// \copydoc field(char) explicit field(wchar_t) = delete; /// \copydoc field(char) explicit field(char16_t) = delete; /// \copydoc field(char) explicit field(char32_t) = delete; #ifdef __cpp_char8_t /// \copydoc field(char) explicit field(char8_t) = delete; #endif /** * \brief Constructs a `field` holding a string. * \par Exception safety * Strong guarantee. Internal allocations may throw. */ explicit field(const std::string& v) : repr_(v) {} /** * \brief Constructs a `field` holding a string. * \details v is moved into an internal `std::string` object. * \par Exception safety * No-throw guarantee. */ explicit field(std::string&& v) noexcept : repr_(std::move(v)) {} /// \copydoc field(const std::string&) explicit field(const char* v) : repr_(boost::variant2::in_place_type_t(), v) {} /// \copydoc field(const std::string&) explicit field(string_view v) : repr_(boost::variant2::in_place_type_t(), v) {} #if defined(__cpp_lib_string_view) /// \copydoc field(const std::string&) explicit field(std::string_view v) noexcept : repr_(boost::variant2::in_place_type_t(), v) {} #endif /** * \brief Constructs a `field` holding a `blob`. * \details v is moved into an internal `blob` object. * \par Exception safety * No-throw guarantee. */ explicit field(blob v) noexcept : repr_(std::move(v)) {} /** * \brief Constructs a `field` holding a `float`. * \par Exception safety * No-throw guarantee. */ explicit field(float v) noexcept : repr_(v) {} /** * \brief Constructs a `field` holding a `double`. * \par Exception safety * No-throw guarantee. */ explicit field(double v) noexcept : repr_(v) {} /** * \brief Constructs a `field` holding a `date`. * \par Exception safety * No-throw guarantee. */ explicit field(const date& v) noexcept : repr_(v) {} /** * \brief Constructs a `field` holding a `datetime`. * \par Exception safety * No-throw guarantee. */ explicit field(const datetime& v) noexcept : repr_(v) {} /** * \brief Constructs a `field` holding a `time`. * \par Exception safety * No-throw guarantee. */ explicit field(const time& v) noexcept : repr_(v) {} /** * \brief Constructs a `field` from a \ref field_view. * \details The resulting `field` has the same kind and value as the original `field_view`. * * \par Exception safety * Strong guarantee. Internal allocations may throw. * * \par Object lifetimes * The resulting `field` is guaranteed to be valid even after `v` becomes invalid. */ field(const field_view& v) { from_view(v); } /** * \brief Replaces `*this` with a `NULL`, changing the kind to `null` and destroying any * previous contents. * * \par Exception safety * No-throw guarantee. * * \par Object lifetimes * Invalidates references obtained by as_xxx and get_xxx functions, * but not the ones obtained by \ref field::operator field_view(). */ field& operator=(std::nullptr_t) noexcept { repr_.data.emplace(); return *this; } /** * \brief Replaces `*this` with `v`, changing the kind to `int64` and destroying any * previous contents. * * \par Exception safety * No-throw guarantee. * * \par Object lifetimes * Invalidates references obtained by as_xxx and get_xxx functions, * but not the ones obtained by \ref field::operator field_view(). */ field& operator=(signed char v) noexcept { repr_.data.emplace(v); return *this; } /// \copydoc operator=(signed char) field& operator=(short v) noexcept { repr_.data.emplace(v); return *this; } /// \copydoc operator=(signed char) field& operator=(int v) noexcept { repr_.data.emplace(v); return *this; } /// \copydoc operator=(signed char) field& operator=(long v) noexcept { repr_.data.emplace(v); return *this; } /// \copydoc operator=(signed char) field& operator=(long long v) noexcept { repr_.data.emplace(v); return *this; } /** * \brief Replaces `*this` with `v`, changing the kind to `uint64` and destroying any * previous contents. * * \par Exception safety * No-throw guarantee. * * \par Object lifetimes * Invalidates references obtained by as_xxx and get_xxx functions, * but not the ones obtained by \ref field::operator field_view(). */ field& operator=(unsigned char v) noexcept { repr_.data.emplace(v); return *this; } /// \copydoc operator=(unsigned char) field& operator=(unsigned short v) noexcept { repr_.data.emplace(v); return *this; } /// \copydoc operator=(unsigned char) field& operator=(unsigned int v) noexcept { repr_.data.emplace(v); return *this; } /// \copydoc operator=(unsigned char) field& operator=(unsigned long v) noexcept { repr_.data.emplace(v); return *this; } /// \copydoc operator=(unsigned char) field& operator=(unsigned long long v) noexcept { repr_.data.emplace(v); return *this; } /** * \brief Assignments from character types would incorrectly assign an integer, * so they are not allowed. */ field& operator=(char) = delete; /// \copydoc operator=(char) field& operator=(wchar_t) = delete; /// \copydoc operator=(char) field& operator=(char16_t) = delete; /// \copydoc operator=(char) field& operator=(char32_t) = delete; #ifdef __cpp_char8_t /// \copydoc operator=(char) field& operator=(char8_t) = delete; #endif /** * \brief Replaces `*this` with `v`, changing the kind to `string` and destroying any previous * contents. * * \par Exception safety * Basic guarantee. Internal allocations may throw. * * \par Object lifetimes * Invalidates references obtained by as_xxx and get_xxx functions, * but not the ones obtained by \ref field::operator field_view(). */ field& operator=(const std::string& v) { repr_.data.emplace(v); return *this; } /// \copydoc operator=(const std::string&) field& operator=(std::string&& v) { repr_.data.emplace(std::move(v)); return *this; } /// \copydoc operator=(const std::string&) field& operator=(const char* v) { repr_.data.emplace(v); return *this; } /// \copydoc operator=(const std::string&) field& operator=(string_view v) { repr_.data.emplace(v); return *this; } #if defined(__cpp_lib_string_view) /// \copydoc operator=(const std::string&) field& operator=(std::string_view v) { repr_.data.emplace(v); return *this; } #endif /** * \brief Replaces `*this` with `v`, changing the kind to `blob` and destroying any * previous contents. * * \par Exception safety * Basic guarantee. Internal allocations may throw. * * \par Object lifetimes * Invalidates references obtained by as_xxx and get_xxx functions, * but not the ones obtained by \ref field::operator field_view(). */ field& operator=(blob v) { repr_.data.emplace(std::move(v)); return *this; } /** * \brief Replaces `*this` with `v`, changing the kind to `float_` and destroying any * previous contents. * * \par Exception safety * No-throw guarantee. * * \par Object lifetimes * Invalidates references obtained by as_xxx and get_xxx functions, * but not the ones obtained by \ref field::operator field_view(). */ field& operator=(float v) noexcept { repr_.data.emplace(v); return *this; } /** * \brief Replaces `*this` with `v`, changing the kind to `double` and destroying any * previous contents. * * \par Exception safety * No-throw guarantee. * * \par Object lifetimes * Invalidates references obtained by as_xxx and get_xxx functions, * but not the ones obtained by \ref field::operator field_view(). */ field& operator=(double v) noexcept { repr_.data.emplace(v); return *this; } /** * \brief Replaces `*this` with `v`, changing the kind to `date` and destroying any * previous contents. * * \par Exception safety * No-throw guarantee. * * \par Object lifetimes * Invalidates references obtained by as_xxx and get_xxx functions, * but not the ones obtained by \ref field::operator field_view(). */ field& operator=(const date& v) noexcept { repr_.data.emplace(v); return *this; } /** * \brief Replaces `*this` with `v`, changing the kind to `datetime` and destroying any * previous contents. * * \par Exception safety * No-throw guarantee. * * \par Object lifetimes * Invalidates references obtained by as_xxx and get_xxx functions, * but not the ones obtained by \ref field::operator field_view(). */ field& operator=(const datetime& v) noexcept { repr_.data.emplace(v); return *this; } /** * \brief Replaces `*this` with `v`, changing the kind to `time` and destroying any * previous contents. * * \par Exception safety * No-throw guarantee. * * \par Object lifetimes * Invalidates references obtained by as_xxx and get_xxx functions, but not */ field& operator=(const time& v) noexcept { repr_.data.emplace