mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-16 04:47:18 +08:00
Introduce optional, string_view, and span
sqlpp::optional is an alias for std::optional for C++17 and beyond. Otherwise, it is a simple and incomplete backport. For older versions of C++, the library offers simple back Similar for string_view and span.
This commit is contained in:
parent
f6cb4d311a
commit
bda77c620b
247
include/sqlpp11/compat/optional.h
Normal file
247
include/sqlpp11/compat/optional.h
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
* other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef _MSVC_LANG
|
||||||
|
#define CXX_STD_VER _MSVC_LANG
|
||||||
|
#else
|
||||||
|
#define CXX_STD_VER __cplusplus
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CXX_STD_VER >= 201703L
|
||||||
|
#include <optional>
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
template <class T>
|
||||||
|
using optional = std::optional<T>;
|
||||||
|
|
||||||
|
using std::nullopt_t;
|
||||||
|
using std::nullopt;
|
||||||
|
|
||||||
|
using std::bad_optional_access;
|
||||||
|
} // namespace sqlpp
|
||||||
|
|
||||||
|
#else // incomplete backport of std::optional
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
class nullopt_t
|
||||||
|
{
|
||||||
|
};
|
||||||
|
constexpr nullopt_t nullopt;
|
||||||
|
|
||||||
|
class bad_optional_access : public std::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~bad_optional_access() override = default;
|
||||||
|
const char* what() const noexcept override
|
||||||
|
{
|
||||||
|
return "bad optional access";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class optional
|
||||||
|
{
|
||||||
|
// Unnamed union, injecting members into scope.
|
||||||
|
union
|
||||||
|
{
|
||||||
|
char _nothing;
|
||||||
|
T _value;
|
||||||
|
};
|
||||||
|
bool _active = false;
|
||||||
|
|
||||||
|
// Placement new
|
||||||
|
template<typename... Args>
|
||||||
|
void create(Args&&... args)
|
||||||
|
{
|
||||||
|
new ((void*)std::addressof(_value)) T(std::forward<Args>(args)...);
|
||||||
|
_active = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy()
|
||||||
|
{
|
||||||
|
if (_active)
|
||||||
|
{
|
||||||
|
_value.~T();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
optional() noexcept : _nothing(), _active(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
optional(T t) : _active(true)
|
||||||
|
{
|
||||||
|
create(std::move(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
optional(const optional&) = default;
|
||||||
|
optional(optional&&) = default;
|
||||||
|
optional(const nullopt_t&) noexcept
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
optional& operator=(const optional&) = default;
|
||||||
|
optional& operator=(optional&&) = default;
|
||||||
|
optional& operator=(const nullopt_t&) noexcept
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
~optional() {
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_value() const
|
||||||
|
{
|
||||||
|
return _active;
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit operator bool() const
|
||||||
|
{
|
||||||
|
return _active;
|
||||||
|
}
|
||||||
|
|
||||||
|
T& operator*()
|
||||||
|
{
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& operator*() const
|
||||||
|
{
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& operator->() const
|
||||||
|
{
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
optional& emplace(Args&&... args) {
|
||||||
|
create(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
T& value()
|
||||||
|
{
|
||||||
|
if (_active)
|
||||||
|
return _value;
|
||||||
|
throw bad_optional_access();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
T value_or(U&& u)
|
||||||
|
{
|
||||||
|
if (_active)
|
||||||
|
return _value;
|
||||||
|
return std::forward<U>(u);
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& value() const
|
||||||
|
{
|
||||||
|
if (_active)
|
||||||
|
return _value;
|
||||||
|
throw bad_optional_access();
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class L, class R>
|
||||||
|
bool operator==(const optional<L>& left, const optional<R>& right)
|
||||||
|
{
|
||||||
|
if (static_cast<bool>(left) != static_cast<bool>(right))
|
||||||
|
return false;
|
||||||
|
if (!static_cast<bool>(left))
|
||||||
|
return true;
|
||||||
|
return *left == *right;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class L, class R>
|
||||||
|
bool operator==(const optional<L>& left, const R& right)
|
||||||
|
{
|
||||||
|
if (!static_cast<bool>(left))
|
||||||
|
return false;
|
||||||
|
return *left == right;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class L, class R>
|
||||||
|
bool operator==(const L& left, const optional<R>& right)
|
||||||
|
{
|
||||||
|
if (!static_cast<bool>(right))
|
||||||
|
return false;
|
||||||
|
return left == *right;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class L, class R>
|
||||||
|
bool operator!=(const optional<L>& left, const optional<R>& right)
|
||||||
|
{
|
||||||
|
if (static_cast<bool>(left) != static_cast<bool>(right))
|
||||||
|
return true;
|
||||||
|
if (!static_cast<bool>(left))
|
||||||
|
return false;
|
||||||
|
return *left != *right;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class L, class R>
|
||||||
|
bool operator!=(const optional<L>& left, const R& right)
|
||||||
|
{
|
||||||
|
if (!static_cast<bool>(left))
|
||||||
|
return true;
|
||||||
|
return *left != right;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class L, class R>
|
||||||
|
bool operator!=(const L& left, const optional<R>& right)
|
||||||
|
{
|
||||||
|
if (!static_cast<bool>(right))
|
||||||
|
return true;
|
||||||
|
return left != *right;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
bool operator==(const optional<T>& left, const nullopt_t&)
|
||||||
|
{
|
||||||
|
return !left;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
bool operator==(const nullopt_t& n, const optional<T>& right)
|
||||||
|
{
|
||||||
|
return !right;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace sqlpp
|
||||||
|
|
||||||
|
#endif
|
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2024, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -26,28 +26,52 @@
|
|||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sqlpp11/basic_expression_operators.h>
|
#ifdef _MSVC_LANG
|
||||||
#include <sqlpp11/result_field.h>
|
#define CXX_STD_VER _MSVC_LANG
|
||||||
#include <sqlpp11/result_field_base.h>
|
#else
|
||||||
#include <sqlpp11/data_types/integral/data_type.h>
|
#define CXX_STD_VER __cplusplus
|
||||||
#include <sqlpp11/field_spec.h>
|
#endif
|
||||||
|
|
||||||
|
#if CXX_STD_VER >= 202002L
|
||||||
|
#include <span>
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
using span = std::span<T>;
|
||||||
|
} // namespace sqlpp
|
||||||
|
|
||||||
|
#else // incomplete backport of std::span
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template <typename Db, typename NameType, bool CanBeNull>
|
template <typename T>
|
||||||
struct result_field_t<Db, field_spec_t<NameType, integral, CanBeNull>>
|
class span
|
||||||
: public result_field_base<Db, field_spec_t<NameType, integral, CanBeNull>>
|
|
||||||
{
|
{
|
||||||
template <typename Target>
|
const T* _data = nullptr;
|
||||||
void _bind(Target& target, size_t index)
|
size_t _size = 0u;
|
||||||
|
public:
|
||||||
|
constexpr span() = default;
|
||||||
|
constexpr span(const T* data, size_t size) : _data(data), _size(size)
|
||||||
{
|
{
|
||||||
target._bind_integral_result(index, &this->_value, &this->_is_null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Target>
|
const char* data() const
|
||||||
void _post_bind(Target& target, size_t index)
|
|
||||||
{
|
{
|
||||||
target._post_bind_integral_result(index, &this->_value, &this->_is_null);
|
return _data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t size() const
|
||||||
|
{
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& operator[](size_t i) const
|
||||||
|
{
|
||||||
|
return *(_data + i);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace sqlpp
|
} // namespace sqlpp
|
||||||
|
|
||||||
|
#endif
|
106
include/sqlpp11/compat/string_view.h
Normal file
106
include/sqlpp11/compat/string_view.h
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
* other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef _MSVC_LANG
|
||||||
|
#define CXX_STD_VER _MSVC_LANG
|
||||||
|
#else
|
||||||
|
#define CXX_STD_VER __cplusplus
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CXX_STD_VER >= 201703L
|
||||||
|
#include <string_view>
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
using string_view = std::string_view;
|
||||||
|
} // namespace sqlpp
|
||||||
|
|
||||||
|
#else // incomplete backport of std::string_view
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include <string>
|
||||||
|
#include <iosfwd>
|
||||||
|
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
class string_view
|
||||||
|
{
|
||||||
|
const char* _data = nullptr;
|
||||||
|
size_t _size = 0u;
|
||||||
|
public:
|
||||||
|
constexpr string_view() = default;
|
||||||
|
string_view(const std::string& source) : _data(source.data()), _size(source.size())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr string_view(const char* data, size_t size) : _data(data), _size(size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
string_view(const char* data) : _data(data), _size(std::char_traits<char>::length(data))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* data() const
|
||||||
|
{
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const
|
||||||
|
{
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator std::string() const
|
||||||
|
{
|
||||||
|
return std::string(_data, _size);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool operator==(const string_view& left, const string_view& right)
|
||||||
|
{
|
||||||
|
if (left.size() != right.size())
|
||||||
|
return false;
|
||||||
|
return std::char_traits<char>::compare(left.data(), right.data(), left.size()) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator!=(const string_view& left, const string_view& right)
|
||||||
|
{
|
||||||
|
if (left.size() != right.size())
|
||||||
|
return true;
|
||||||
|
return std::char_traits<char>::compare(left.data(), right.data(), left.size()) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::ostream& operator<<(std::ostream& os, const string_view& sv)
|
||||||
|
{
|
||||||
|
return os << std::string(sv);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace sqlpp
|
||||||
|
|
||||||
|
#endif
|
@ -32,7 +32,6 @@
|
|||||||
#include <sqlpp11/data_types/blob/expression_operators.h>
|
#include <sqlpp11/data_types/blob/expression_operators.h>
|
||||||
#include <sqlpp11/data_types/blob/column_operators.h>
|
#include <sqlpp11/data_types/blob/column_operators.h>
|
||||||
#include <sqlpp11/data_types/blob/parameter_value.h>
|
#include <sqlpp11/data_types/blob/parameter_value.h>
|
||||||
#include <sqlpp11/data_types/blob/result_field.h>
|
|
||||||
|
|
||||||
// blob specific functions
|
// blob specific functions
|
||||||
#include <sqlpp11/data_types/text/like.h>
|
#include <sqlpp11/data_types/text/like.h>
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include <sqlpp11/type_traits.h>
|
#include <sqlpp11/type_traits.h>
|
||||||
|
#include <sqlpp11/compat/span.h>
|
||||||
#include <sqlpp11/logic.h>
|
#include <sqlpp11/logic.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
@ -38,6 +39,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
using _traits = make_traits<blob, tag::is_value_type>;
|
using _traits = make_traits<blob, tag::is_value_type>;
|
||||||
using _cpp_value_type = std::vector<std::uint8_t>;
|
using _cpp_value_type = std::vector<std::uint8_t>;
|
||||||
|
using _result_type = sqlpp::span<std::uint8_t>;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using _is_valid_operand = ::sqlpp::logic::any_t<is_blob_t<T>::value, is_text_t<T>::value>;
|
using _is_valid_operand = ::sqlpp::logic::any_t<is_blob_t<T>::value, is_text_t<T>::value>;
|
||||||
|
@ -1,84 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2013-2017, Roland Bock
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
* other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sqlpp11/basic_expression_operators.h>
|
|
||||||
#include <sqlpp11/result_field.h>
|
|
||||||
#include <sqlpp11/result_field_base.h>
|
|
||||||
#include <sqlpp11/data_types/blob/data_type.h>
|
|
||||||
#include <sqlpp11/field_spec.h>
|
|
||||||
#include <ostream>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
template <typename Db, typename NameType, bool CanBeNull>
|
|
||||||
struct result_field_t<Db, field_spec_t<NameType, blob, CanBeNull>>
|
|
||||||
: public result_field_base<Db, field_spec_t<NameType, blob, CanBeNull>>
|
|
||||||
{
|
|
||||||
const uint8_t* blob{nullptr}; // Non-owning
|
|
||||||
size_t len{};
|
|
||||||
|
|
||||||
template <typename Target>
|
|
||||||
void _bind(Target& target, size_t index)
|
|
||||||
{
|
|
||||||
target._bind_blob_result(index, &blob, &len);
|
|
||||||
if (blob)
|
|
||||||
this->_value.assign(blob, blob + len);
|
|
||||||
else
|
|
||||||
this->_value.clear();
|
|
||||||
this->_is_null = (blob == nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Target>
|
|
||||||
void _post_bind(Target& target, size_t index)
|
|
||||||
{
|
|
||||||
target._post_bind_blob_result(index, &blob, &len);
|
|
||||||
if (blob)
|
|
||||||
this->_value.assign(blob, blob + len);
|
|
||||||
else
|
|
||||||
this->_value.clear();
|
|
||||||
this->_is_null = (blob == nullptr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Db, typename NameType, bool CanBeNull>
|
|
||||||
inline std::ostream& operator<<(
|
|
||||||
std::ostream& os, const result_field_t<Db, field_spec_t<NameType, blob, CanBeNull>>& e)
|
|
||||||
{
|
|
||||||
if (e.is_null())
|
|
||||||
{
|
|
||||||
return os << "NULL";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::vector<uint8_t> value = e.value();
|
|
||||||
std::string value_str(value.begin(), value.end());
|
|
||||||
return os << value_str;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace sqlpp
|
|
@ -32,4 +32,3 @@
|
|||||||
#include <sqlpp11/data_types/boolean/expression_operators.h>
|
#include <sqlpp11/data_types/boolean/expression_operators.h>
|
||||||
#include <sqlpp11/data_types/boolean/column_operators.h>
|
#include <sqlpp11/data_types/boolean/column_operators.h>
|
||||||
#include <sqlpp11/data_types/boolean/parameter_value.h>
|
#include <sqlpp11/data_types/boolean/parameter_value.h>
|
||||||
#include <sqlpp11/data_types/boolean/result_field.h>
|
|
||||||
|
@ -34,6 +34,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
using _traits = make_traits<boolean, tag::is_value_type>;
|
using _traits = make_traits<boolean, tag::is_value_type>;
|
||||||
using _cpp_value_type = bool;
|
using _cpp_value_type = bool;
|
||||||
|
using _result_type = bool;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using _is_valid_operand = is_boolean_t<T>;
|
using _is_valid_operand = is_boolean_t<T>;
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
* other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sqlpp11/basic_expression_operators.h>
|
|
||||||
#include <sqlpp11/result_field.h>
|
|
||||||
#include <sqlpp11/result_field_base.h>
|
|
||||||
#include <sqlpp11/data_types/boolean/data_type.h>
|
|
||||||
#include <sqlpp11/field_spec.h>
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
template <typename Db, typename NameType, bool CanBeNull>
|
|
||||||
struct result_field_t<Db, field_spec_t<NameType, boolean, CanBeNull>>
|
|
||||||
: public result_field_base<Db, field_spec_t<NameType, boolean, CanBeNull>, signed char>
|
|
||||||
{
|
|
||||||
template <typename Target>
|
|
||||||
void _bind(Target& target, size_t index)
|
|
||||||
{
|
|
||||||
target._bind_boolean_result(index, &this->_value, &this->_is_null);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Target>
|
|
||||||
void _post_bind(Target& target, size_t index)
|
|
||||||
{
|
|
||||||
target._post_bind_boolean_result(index, &this->_value, &this->_is_null);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace sqlpp
|
|
@ -32,4 +32,3 @@
|
|||||||
#include <sqlpp11/data_types/day_point/expression_operators.h>
|
#include <sqlpp11/data_types/day_point/expression_operators.h>
|
||||||
#include <sqlpp11/data_types/day_point/column_operators.h>
|
#include <sqlpp11/data_types/day_point/column_operators.h>
|
||||||
#include <sqlpp11/data_types/day_point/parameter_value.h>
|
#include <sqlpp11/data_types/day_point/parameter_value.h>
|
||||||
#include <sqlpp11/data_types/day_point/result_field.h>
|
|
||||||
|
@ -35,6 +35,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
using _traits = make_traits<day_point, tag::is_value_type>;
|
using _traits = make_traits<day_point, tag::is_value_type>;
|
||||||
using _cpp_value_type = ::sqlpp::chrono::day_point;
|
using _cpp_value_type = ::sqlpp::chrono::day_point;
|
||||||
|
using _result_type = ::sqlpp::chrono::day_point;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using _is_valid_operand = is_day_or_time_point_t<T>;
|
using _is_valid_operand = is_day_or_time_point_t<T>;
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2015-2015, Roland Bock
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
* other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sqlpp11/basic_expression_operators.h>
|
|
||||||
#include <sqlpp11/result_field.h>
|
|
||||||
#include <sqlpp11/result_field_base.h>
|
|
||||||
#include <sqlpp11/data_types/day_point/data_type.h>
|
|
||||||
#include <sqlpp11/field_spec.h>
|
|
||||||
#include <ostream>
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
template <typename Db, typename NameType, bool CanBeNull>
|
|
||||||
struct result_field_t<Db, field_spec_t<NameType, day_point, CanBeNull>>
|
|
||||||
: public result_field_base<Db, field_spec_t<NameType, day_point, CanBeNull>>
|
|
||||||
{
|
|
||||||
template <typename Target>
|
|
||||||
void _bind(Target& target, size_t index)
|
|
||||||
{
|
|
||||||
target._bind_date_result(index, &this->_value, &this->_is_null);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Target>
|
|
||||||
void _post_bind(Target& target, size_t index)
|
|
||||||
{
|
|
||||||
target._post_bind_date_result(index, &this->_value, &this->_is_null);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Db, typename NameType, bool CanBeNull>
|
|
||||||
inline std::ostream& operator<<(
|
|
||||||
std::ostream& os, const result_field_t<Db, field_spec_t<NameType, day_point, CanBeNull>>& e)
|
|
||||||
{
|
|
||||||
if (e.is_null())
|
|
||||||
{
|
|
||||||
os << "NULL";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const auto ymd = ::date::year_month_day{e.value()};
|
|
||||||
os << ymd;
|
|
||||||
}
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
} // namespace sqlpp
|
|
@ -32,4 +32,3 @@
|
|||||||
#include <sqlpp11/data_types/floating_point/expression_operators.h>
|
#include <sqlpp11/data_types/floating_point/expression_operators.h>
|
||||||
#include <sqlpp11/data_types/floating_point/column_operators.h>
|
#include <sqlpp11/data_types/floating_point/column_operators.h>
|
||||||
#include <sqlpp11/data_types/floating_point/parameter_value.h>
|
#include <sqlpp11/data_types/floating_point/parameter_value.h>
|
||||||
#include <sqlpp11/data_types/floating_point/result_field.h>
|
|
||||||
|
@ -34,6 +34,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
using _traits = make_traits<floating_point, tag::is_value_type>;
|
using _traits = make_traits<floating_point, tag::is_value_type>;
|
||||||
using _cpp_value_type = double;
|
using _cpp_value_type = double;
|
||||||
|
using _result_type = double;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using _is_valid_operand = is_numeric_t<T>;
|
using _is_valid_operand = is_numeric_t<T>;
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
* other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sqlpp11/exception.h>
|
|
||||||
#include <sqlpp11/result_field.h>
|
|
||||||
#include <sqlpp11/result_field_base.h>
|
|
||||||
#include <sqlpp11/type_traits.h>
|
|
||||||
#include <sqlpp11/data_types/floating_point/data_type.h>
|
|
||||||
#include <sqlpp11/field_spec.h>
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
template <typename Db, typename NameType, bool CanBeNull>
|
|
||||||
struct result_field_t<Db, field_spec_t<NameType, floating_point, CanBeNull>>
|
|
||||||
: public result_field_base<Db, field_spec_t<NameType, floating_point, CanBeNull>>
|
|
||||||
{
|
|
||||||
template <typename Target>
|
|
||||||
void _bind(Target& target, size_t index)
|
|
||||||
{
|
|
||||||
target._bind_floating_point_result(index, &this->_value, &this->_is_null);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Target>
|
|
||||||
void _post_bind(Target& target, size_t index)
|
|
||||||
{
|
|
||||||
target._post_bind_floating_point_result(index, &this->_value, &this->_is_null);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace sqlpp
|
|
@ -32,4 +32,3 @@
|
|||||||
#include <sqlpp11/data_types/integral/expression_operators.h>
|
#include <sqlpp11/data_types/integral/expression_operators.h>
|
||||||
#include <sqlpp11/data_types/integral/column_operators.h>
|
#include <sqlpp11/data_types/integral/column_operators.h>
|
||||||
#include <sqlpp11/data_types/integral/parameter_value.h>
|
#include <sqlpp11/data_types/integral/parameter_value.h>
|
||||||
#include <sqlpp11/data_types/integral/result_field.h>
|
|
||||||
|
@ -34,6 +34,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
using _traits = make_traits<integral, tag::is_value_type>;
|
using _traits = make_traits<integral, tag::is_value_type>;
|
||||||
using _cpp_value_type = int64_t;
|
using _cpp_value_type = int64_t;
|
||||||
|
using _result_type = int64_t;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using _is_valid_operand = is_numeric_t<T>;
|
using _is_valid_operand = is_numeric_t<T>;
|
||||||
|
@ -32,4 +32,3 @@
|
|||||||
#include <sqlpp11/data_types/no_value/expression_operators.h>
|
#include <sqlpp11/data_types/no_value/expression_operators.h>
|
||||||
#include <sqlpp11/data_types/no_value/column_operators.h>
|
#include <sqlpp11/data_types/no_value/column_operators.h>
|
||||||
#include <sqlpp11/data_types/no_value/parameter_value.h>
|
#include <sqlpp11/data_types/no_value/parameter_value.h>
|
||||||
#include <sqlpp11/data_types/no_value/result_field.h>
|
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
* other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sqlpp11/result_field.h>
|
|
||||||
#include <sqlpp11/data_types/no_value/data_type.h>
|
|
||||||
#include <sqlpp11/field_spec.h>
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
template <typename Db, typename NameType, bool CanBeNull>
|
|
||||||
struct result_field_t<Db, field_spec_t<NameType, no_value_t, CanBeNull>>
|
|
||||||
{
|
|
||||||
template <typename Target>
|
|
||||||
void _bind(Target& /*unused*/, size_t /*unused*/)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Target>
|
|
||||||
void _post_bind(Target& /*unused*/, size_t /*unused*/)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void _validate() const
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void _invalidate() const
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool is_null() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Db, typename NameType, bool CanBeNull>
|
|
||||||
inline std::ostream& operator<<(
|
|
||||||
std::ostream& os,
|
|
||||||
const result_field_t<Db, field_spec_t<NameType, no_value_t, CanBeNull>>& /*unused*/)
|
|
||||||
{
|
|
||||||
os << "NULL";
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
} // namespace sqlpp
|
|
@ -32,7 +32,6 @@
|
|||||||
#include <sqlpp11/data_types/text/expression_operators.h>
|
#include <sqlpp11/data_types/text/expression_operators.h>
|
||||||
#include <sqlpp11/data_types/text/column_operators.h>
|
#include <sqlpp11/data_types/text/column_operators.h>
|
||||||
#include <sqlpp11/data_types/text/parameter_value.h>
|
#include <sqlpp11/data_types/text/parameter_value.h>
|
||||||
#include <sqlpp11/data_types/text/result_field.h>
|
|
||||||
|
|
||||||
// text specific functions
|
// text specific functions
|
||||||
#include <sqlpp11/data_types/text/like.h>
|
#include <sqlpp11/data_types/text/like.h>
|
||||||
|
@ -28,12 +28,17 @@
|
|||||||
|
|
||||||
#include <sqlpp11/type_traits.h>
|
#include <sqlpp11/type_traits.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <sqlpp11/compat/string_view.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
struct text
|
struct text
|
||||||
{
|
{
|
||||||
using _traits = make_traits<text, tag::is_value_type>;
|
using _traits = make_traits<text, tag::is_value_type>;
|
||||||
using _cpp_value_type = std::string;
|
using _cpp_value_type = std::string;
|
||||||
|
using _result_type = sqlpp::string_view;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using _is_valid_operand = is_text_t<T>;
|
using _is_valid_operand = is_text_t<T>;
|
||||||
|
@ -28,9 +28,7 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#if __cplusplus >= 201703L
|
#include <sqlpp11/compat/string_view.h>
|
||||||
#include <string_view>
|
|
||||||
#endif
|
|
||||||
#include <sqlpp11/type_traits.h>
|
#include <sqlpp11/type_traits.h>
|
||||||
#include <sqlpp11/alias_operators.h>
|
#include <sqlpp11/alias_operators.h>
|
||||||
|
|
||||||
@ -51,16 +49,14 @@ namespace sqlpp
|
|||||||
text_operand(_value_t t) : _t(std::move(t))
|
text_operand(_value_t t) : _t(std::move(t))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
#if __cplusplus >= 201703L
|
// allow construction from an sqlpp::string_view
|
||||||
// allow construction from an std::string_view
|
text_operand(sqlpp::string_view t) : _t(t)
|
||||||
text_operand(std::string_view t) : _t(t)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
// additional const char* overload, required to disambiguate
|
// additional const char* overload, required to disambiguate
|
||||||
text_operand(const char* t) : _t(t)
|
text_operand(const char* t) : _t(t)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
text_operand(const text_operand&) = default;
|
text_operand(const text_operand&) = default;
|
||||||
text_operand(text_operand&&) = default;
|
text_operand(text_operand&&) = default;
|
||||||
|
@ -32,9 +32,7 @@
|
|||||||
#include <sqlpp11/data_types/text/wrap_operand.h>
|
#include <sqlpp11/data_types/text/wrap_operand.h>
|
||||||
#include <sqlpp11/data_types/text/operand.h>
|
#include <sqlpp11/data_types/text/operand.h>
|
||||||
|
|
||||||
#if __cplusplus >= 201703L
|
#include <sqlpp11/compat/string_view.h>
|
||||||
#include <string_view>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
@ -51,8 +49,7 @@ namespace sqlpp
|
|||||||
target._bind_text_parameter(index, &_value, _is_null);
|
target._bind_text_parameter(index, &_value, _is_null);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if __cplusplus >= 201703L
|
parameter_value_base& operator=(const sqlpp::string_view& val)
|
||||||
parameter_value_base& operator=(const std::string_view& val)
|
|
||||||
{
|
{
|
||||||
_value = val;
|
_value = val;
|
||||||
_is_null = false;
|
_is_null = false;
|
||||||
@ -65,6 +62,5 @@ namespace sqlpp
|
|||||||
_is_null = false;
|
_is_null = false;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
} // namespace sqlpp
|
} // namespace sqlpp
|
||||||
|
@ -1,87 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
* other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sqlpp11/basic_expression_operators.h>
|
|
||||||
#include <sqlpp11/result_field.h>
|
|
||||||
#include <sqlpp11/result_field_base.h>
|
|
||||||
#include <sqlpp11/data_types/text/data_type.h>
|
|
||||||
#include <sqlpp11/field_spec.h>
|
|
||||||
#include <ostream>
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
template <typename Db, typename NameType, bool CanBeNull>
|
|
||||||
struct result_field_t<Db, field_spec_t<NameType, text, CanBeNull>>
|
|
||||||
: public result_field_base<Db, field_spec_t<NameType, text, CanBeNull>>
|
|
||||||
{
|
|
||||||
const char* text{nullptr}; // Non-owning
|
|
||||||
size_t len{};
|
|
||||||
|
|
||||||
template <typename Target>
|
|
||||||
void _bind(Target& target, size_t index)
|
|
||||||
{
|
|
||||||
target._bind_text_result(index, &text, &len);
|
|
||||||
if (text)
|
|
||||||
{
|
|
||||||
this->_value.assign(text, len);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->_value.assign("");
|
|
||||||
}
|
|
||||||
this->_is_null = (text == nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Target>
|
|
||||||
void _post_bind(Target& target, size_t index)
|
|
||||||
{
|
|
||||||
target._post_bind_text_result(index, &text, &len);
|
|
||||||
if (text)
|
|
||||||
{
|
|
||||||
this->_value.assign(text, len);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->_value.assign("");
|
|
||||||
}
|
|
||||||
this->_is_null = (text == nullptr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Db, typename NameType, bool CanBeNull>
|
|
||||||
inline std::ostream& operator<<(
|
|
||||||
std::ostream& os, const result_field_t<Db, field_spec_t<NameType, text, CanBeNull>>& e)
|
|
||||||
{
|
|
||||||
if (e.is_null())
|
|
||||||
{
|
|
||||||
return os << "NULL";
|
|
||||||
}
|
|
||||||
|
|
||||||
return os << e.value();
|
|
||||||
}
|
|
||||||
} // namespace sqlpp
|
|
@ -27,21 +27,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#if __cplusplus >= 201703L
|
#include <sqlpp11/compat/string_view.h>
|
||||||
#include <string_view>
|
|
||||||
#endif
|
|
||||||
#include <sqlpp11/type_traits.h>
|
#include <sqlpp11/type_traits.h>
|
||||||
#include <sqlpp11/wrap_operand.h>
|
#include <sqlpp11/wrap_operand.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
struct text_operand;
|
struct text_operand;
|
||||||
|
using checked_type = sqlpp::string_view;
|
||||||
#if __cplusplus >= 201703L
|
|
||||||
using checked_type = std::string_view;
|
|
||||||
#else
|
|
||||||
using checked_type = std::string;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct wrap_operand<
|
struct wrap_operand<
|
||||||
|
@ -32,4 +32,3 @@
|
|||||||
#include <sqlpp11/data_types/time_of_day/expression_operators.h>
|
#include <sqlpp11/data_types/time_of_day/expression_operators.h>
|
||||||
#include <sqlpp11/data_types/time_of_day/column_operators.h>
|
#include <sqlpp11/data_types/time_of_day/column_operators.h>
|
||||||
#include <sqlpp11/data_types/time_of_day/parameter_value.h>
|
#include <sqlpp11/data_types/time_of_day/parameter_value.h>
|
||||||
#include <sqlpp11/data_types/time_of_day/result_field.h>
|
|
||||||
|
@ -35,6 +35,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
using _traits = make_traits<time_of_day, tag::is_value_type>;
|
using _traits = make_traits<time_of_day, tag::is_value_type>;
|
||||||
using _cpp_value_type = std::chrono::microseconds;
|
using _cpp_value_type = std::chrono::microseconds;
|
||||||
|
using _result_type = std::chrono::microseconds;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using _is_valid_operand = is_time_of_day_t<T>;
|
using _is_valid_operand = is_time_of_day_t<T>;
|
||||||
|
@ -1,70 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2015-2015, Roland Bock
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
* other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sqlpp11/chrono.h>
|
|
||||||
#include <sqlpp11/basic_expression_operators.h>
|
|
||||||
#include <sqlpp11/result_field.h>
|
|
||||||
#include <sqlpp11/result_field_base.h>
|
|
||||||
#include <sqlpp11/data_types/time_of_day/data_type.h>
|
|
||||||
#include <sqlpp11/field_spec.h>
|
|
||||||
#include <ostream>
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
template <typename Db, typename NameType, bool CanBeNull>
|
|
||||||
struct result_field_t<Db, field_spec_t<NameType, time_of_day, CanBeNull>>
|
|
||||||
: public result_field_base<Db, field_spec_t<NameType, time_of_day, CanBeNull>>
|
|
||||||
{
|
|
||||||
template <typename Target>
|
|
||||||
void _bind(Target& target, size_t i)
|
|
||||||
{
|
|
||||||
target._bind_time_of_day_result(i, &this->_value, &this->_is_null);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Target>
|
|
||||||
void _post_bind(Target& target, size_t i)
|
|
||||||
{
|
|
||||||
target._post_bind_time_of_day_result(i, &this->_value, &this->_is_null);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Db, typename NameType, bool CanBeNull>
|
|
||||||
inline std::ostream& operator<<(
|
|
||||||
std::ostream& os, const result_field_t<Db, field_spec_t<NameType, time_of_day, CanBeNull>>& e)
|
|
||||||
{
|
|
||||||
if (e.is_null())
|
|
||||||
{
|
|
||||||
os << "NULL";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
os << ::date::make_time(e.value());
|
|
||||||
}
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
} // namespace sqlpp
|
|
@ -32,4 +32,3 @@
|
|||||||
#include <sqlpp11/data_types/time_point/expression_operators.h>
|
#include <sqlpp11/data_types/time_point/expression_operators.h>
|
||||||
#include <sqlpp11/data_types/time_point/column_operators.h>
|
#include <sqlpp11/data_types/time_point/column_operators.h>
|
||||||
#include <sqlpp11/data_types/time_point/parameter_value.h>
|
#include <sqlpp11/data_types/time_point/parameter_value.h>
|
||||||
#include <sqlpp11/data_types/time_point/result_field.h>
|
|
||||||
|
@ -35,6 +35,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
using _traits = make_traits<time_point, tag::is_value_type>;
|
using _traits = make_traits<time_point, tag::is_value_type>;
|
||||||
using _cpp_value_type = ::sqlpp::chrono::microsecond_point;
|
using _cpp_value_type = ::sqlpp::chrono::microsecond_point;
|
||||||
|
using _result_type = ::sqlpp::chrono::microsecond_point;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using _is_valid_operand = is_day_or_time_point_t<T>;
|
using _is_valid_operand = is_day_or_time_point_t<T>;
|
||||||
|
@ -1,73 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2015-2015, Roland Bock
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
* other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sqlpp11/chrono.h>
|
|
||||||
#include <sqlpp11/basic_expression_operators.h>
|
|
||||||
#include <sqlpp11/result_field.h>
|
|
||||||
#include <sqlpp11/result_field_base.h>
|
|
||||||
#include <sqlpp11/data_types/time_point/data_type.h>
|
|
||||||
#include <sqlpp11/field_spec.h>
|
|
||||||
#include <ostream>
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
template <typename Db, typename NameType, bool CanBeNull>
|
|
||||||
struct result_field_t<Db, field_spec_t<NameType, time_point, CanBeNull>>
|
|
||||||
: public result_field_base<Db, field_spec_t<NameType, time_point, CanBeNull>>
|
|
||||||
{
|
|
||||||
template <typename Target>
|
|
||||||
void _bind(Target& target, size_t i)
|
|
||||||
{
|
|
||||||
target._bind_date_time_result(i, &this->_value, &this->_is_null);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Target>
|
|
||||||
void _post_bind(Target& target, size_t i)
|
|
||||||
{
|
|
||||||
target._post_bind_date_time_result(i, &this->_value, &this->_is_null);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Db, typename NameType, bool CanBeNull>
|
|
||||||
inline std::ostream& operator<<(
|
|
||||||
std::ostream& os, const result_field_t<Db, field_spec_t<NameType, time_point, CanBeNull>>& e)
|
|
||||||
{
|
|
||||||
if (e.is_null())
|
|
||||||
{
|
|
||||||
os << "NULL";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const auto dp = ::sqlpp::chrono::floor<::date::days>(e.value());
|
|
||||||
const auto time = ::date::make_time(e.value() - dp);
|
|
||||||
const auto ymd = ::date::year_month_day{dp};
|
|
||||||
os << ymd << 'T' << time;
|
|
||||||
}
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
} // namespace sqlpp
|
|
@ -32,4 +32,3 @@
|
|||||||
#include <sqlpp11/data_types/unsigned_integral/expression_operators.h>
|
#include <sqlpp11/data_types/unsigned_integral/expression_operators.h>
|
||||||
#include <sqlpp11/data_types/unsigned_integral/column_operators.h>
|
#include <sqlpp11/data_types/unsigned_integral/column_operators.h>
|
||||||
#include <sqlpp11/data_types/unsigned_integral/parameter_value.h>
|
#include <sqlpp11/data_types/unsigned_integral/parameter_value.h>
|
||||||
#include <sqlpp11/data_types/unsigned_integral/result_field.h>
|
|
||||||
|
@ -34,6 +34,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
using _traits = make_traits<unsigned_integral, tag::is_value_type>;
|
using _traits = make_traits<unsigned_integral, tag::is_value_type>;
|
||||||
using _cpp_value_type = uint64_t;
|
using _cpp_value_type = uint64_t;
|
||||||
|
using _result_type = uint64_t;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using _is_valid_operand = is_numeric_t<T>;
|
using _is_valid_operand = is_numeric_t<T>;
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2013-2016, Roland Bock, Aaron Bishop
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
* other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sqlpp11/basic_expression_operators.h>
|
|
||||||
#include <sqlpp11/result_field.h>
|
|
||||||
#include <sqlpp11/result_field_base.h>
|
|
||||||
#include <sqlpp11/data_types/unsigned_integral/data_type.h>
|
|
||||||
#include <sqlpp11/field_spec.h>
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
template <typename Db, typename NameType, bool CanBeNull>
|
|
||||||
struct result_field_t<Db, field_spec_t<NameType, unsigned_integral, CanBeNull>>
|
|
||||||
: public result_field_base<Db, field_spec_t<NameType, unsigned_integral, CanBeNull>>
|
|
||||||
{
|
|
||||||
template <typename Target>
|
|
||||||
void _bind(Target& target, size_t index)
|
|
||||||
{
|
|
||||||
target._bind_unsigned_integral_result(index, &this->_value, &this->_is_null);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Target>
|
|
||||||
void _post_bind(Target& target, size_t index)
|
|
||||||
{
|
|
||||||
target._post_bind_unsigned_integral_result(index, &this->_value, &this->_is_null);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace sqlpp
|
|
@ -44,7 +44,7 @@ namespace sqlpp
|
|||||||
using _name_type = alias::a_t::_alias_t;
|
using _name_type = alias::a_t::_alias_t;
|
||||||
using _value_type = value_type_of<Expr>;
|
using _value_type = value_type_of<Expr>;
|
||||||
using _field_spec = field_spec_t<_name_type, _value_type, true>;
|
using _field_spec = field_spec_t<_name_type, _value_type, true>;
|
||||||
using type = result_field_t<Db, _field_spec>;
|
using type = typename _field_spec::cpp_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Db,
|
template <typename Db,
|
||||||
|
@ -28,6 +28,10 @@
|
|||||||
|
|
||||||
#include <sqlpp11/type_traits.h>
|
#include <sqlpp11/type_traits.h>
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
#include <sqlpp11/compat/optional.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template <typename NameType, typename ValueType, bool CanBeNull>
|
template <typename NameType, typename ValueType, bool CanBeNull>
|
||||||
@ -39,6 +43,10 @@ namespace sqlpp
|
|||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
|
|
||||||
using _alias_t = NameType;
|
using _alias_t = NameType;
|
||||||
|
|
||||||
|
using cpp_type = typename std::conditional<CanBeNull,
|
||||||
|
sqlpp::optional<typename ValueType::_result_type>,
|
||||||
|
typename ValueType::_result_type>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Left, typename Right, typename Enable = void>
|
template <typename Left, typename Right, typename Enable = void>
|
||||||
|
@ -28,6 +28,9 @@
|
|||||||
|
|
||||||
#include <sqlpp11/chrono.h>
|
#include <sqlpp11/chrono.h>
|
||||||
#include <sqlpp11/exception.h>
|
#include <sqlpp11/exception.h>
|
||||||
|
#include <sqlpp11/compat/optional.h>
|
||||||
|
#include <sqlpp11/compat/string_view.h>
|
||||||
|
#include <sqlpp11/compat/span.h>
|
||||||
#include <sqlpp11/mysql/detail/prepared_statement_handle.h>
|
#include <sqlpp11/mysql/detail/prepared_statement_handle.h>
|
||||||
#include <sqlpp11/mysql/sqlpp_mysql.h>
|
#include <sqlpp11/mysql/sqlpp_mysql.h>
|
||||||
|
|
||||||
@ -45,6 +48,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
std::shared_ptr<detail::prepared_statement_handle_t> _handle;
|
std::shared_ptr<detail::prepared_statement_handle_t> _handle;
|
||||||
void* _result_row_address{nullptr};
|
void* _result_row_address{nullptr};
|
||||||
|
bool _require_bind = true;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bind_result_t() = default;
|
bind_result_t() = default;
|
||||||
@ -79,17 +83,23 @@ namespace sqlpp
|
|||||||
|
|
||||||
if (&result_row != _result_row_address)
|
if (&result_row != _result_row_address)
|
||||||
{
|
{
|
||||||
result_row._bind(*this); // sets row data to mysql bind data
|
result_row._bind_fields(*this); // sets row data to mysql bind data
|
||||||
bind_impl(); // binds mysql statement to data
|
|
||||||
_result_row_address = &result_row;
|
_result_row_address = &result_row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_require_bind)
|
||||||
|
{
|
||||||
|
bind_impl(); // binds mysql statement to data
|
||||||
|
_require_bind = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (next_impl())
|
if (next_impl())
|
||||||
{
|
{
|
||||||
if (not result_row)
|
if (not result_row)
|
||||||
{
|
{
|
||||||
result_row._validate();
|
result_row._validate();
|
||||||
}
|
}
|
||||||
result_row._post_bind(*this); // translates bind_data to row data where required
|
result_row._read_fields(*this); // translates bind_data to row data where required
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -103,270 +113,289 @@ namespace sqlpp
|
|||||||
return !_handle or !*_handle;
|
return !_handle or !*_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_boolean_result(size_t index, signed char* value, bool* is_null)
|
void bind_field(size_t index, bool& /*value*/)
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "MySQL debug: binding boolean result " << static_cast<void*>(value) << " at index: " << index
|
std::cerr << "MySQL debug: binding boolean result at index: " << index
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
detail::result_meta_data_t& meta_data{_handle->result_param_meta_data[index]};
|
auto& buffer{_handle->result_buffers[index]};
|
||||||
meta_data.index = index;
|
new (&buffer._bool) bool{};
|
||||||
meta_data.len = nullptr;
|
|
||||||
meta_data.is_null = is_null;
|
|
||||||
|
|
||||||
MYSQL_BIND& param{_handle->result_params[index]};
|
MYSQL_BIND& param{_handle->result_params[index]};
|
||||||
param.buffer_type = MYSQL_TYPE_TINY;
|
param.buffer_type = MYSQL_TYPE_TINY;
|
||||||
param.buffer = value;
|
param.buffer = &buffer._bool;
|
||||||
param.buffer_length = sizeof(*value);
|
param.buffer_length = sizeof(buffer._bool);
|
||||||
param.length = &meta_data.bound_len;
|
param.length = &buffer.length;
|
||||||
param.is_null = &meta_data.bound_is_null;
|
param.is_null = &buffer.is_null;
|
||||||
param.is_unsigned = false;
|
param.is_unsigned = false;
|
||||||
param.error = &meta_data.bound_error;
|
param.error = &buffer.error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_integral_result(size_t index, int64_t* value, bool* is_null)
|
void bind_field(size_t index, int64_t& /*value*/)
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "MySQL debug: binding integral result " << static_cast<void*>(value) << " at index: " << index
|
std::cerr << "MySQL debug: binding integral result at index: " << index
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
detail::result_meta_data_t& meta_data{_handle->result_param_meta_data[index]};
|
auto& buffer{_handle->result_buffers[index]};
|
||||||
meta_data.index = index;
|
new (&buffer._int64) int64_t{};
|
||||||
meta_data.len = nullptr;
|
|
||||||
meta_data.is_null = is_null;
|
|
||||||
|
|
||||||
MYSQL_BIND& param{_handle->result_params[index]};
|
MYSQL_BIND& param{_handle->result_params[index]};
|
||||||
param.buffer_type = MYSQL_TYPE_LONGLONG;
|
param.buffer_type = MYSQL_TYPE_LONGLONG;
|
||||||
param.buffer = value;
|
param.buffer = &buffer._int64;
|
||||||
param.buffer_length = sizeof(*value);
|
param.buffer_length = sizeof(buffer._int64);
|
||||||
param.length = &meta_data.bound_len;
|
param.length = &buffer.length;
|
||||||
param.is_null = &meta_data.bound_is_null;
|
param.is_null = &buffer.is_null;
|
||||||
param.is_unsigned = false;
|
param.is_unsigned = false;
|
||||||
param.error = &meta_data.bound_error;
|
param.error = &buffer.error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_unsigned_integral_result(size_t index, uint64_t* value, bool* is_null)
|
void bind_field(size_t index, uint64_t& /*value*/)
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "MySQL debug: binding unsigned integral result " << static_cast<void*>(value)
|
std::cerr << "MySQL debug: binding unsigned integral result at index: " << index << std::endl;
|
||||||
<< " at index: " << index << std::endl;
|
|
||||||
|
|
||||||
detail::result_meta_data_t& meta_data{_handle->result_param_meta_data[index]};
|
auto& buffer{_handle->result_buffers[index]};
|
||||||
meta_data.index = index;
|
new (&buffer._uint64) uint64_t{};
|
||||||
meta_data.len = nullptr;
|
|
||||||
meta_data.is_null = is_null;
|
|
||||||
|
|
||||||
MYSQL_BIND& param{_handle->result_params[index]};
|
MYSQL_BIND& param{_handle->result_params[index]};
|
||||||
param.buffer_type = MYSQL_TYPE_LONGLONG;
|
param.buffer_type = MYSQL_TYPE_LONGLONG;
|
||||||
param.buffer = value;
|
param.buffer = &buffer._uint64;
|
||||||
param.buffer_length = sizeof(*value);
|
param.buffer_length = sizeof(buffer._uint64);
|
||||||
param.length = &meta_data.bound_len;
|
param.length = &buffer.length;
|
||||||
param.is_null = &meta_data.bound_is_null;
|
param.is_null = &buffer.is_null;
|
||||||
param.is_unsigned = true;
|
param.is_unsigned = true;
|
||||||
param.error = &meta_data.bound_error;
|
param.error = &buffer.error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_floating_point_result(size_t index, double* value, bool* is_null)
|
void bind_field(size_t index, double& /*value*/)
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "MySQL debug: binding floating point result " << static_cast<void*>(value)
|
std::cerr << "MySQL debug: binding floating point result at index: " << index << std::endl;
|
||||||
<< " at index: " << index << std::endl;
|
|
||||||
|
|
||||||
detail::result_meta_data_t& meta_data{_handle->result_param_meta_data[index]};
|
auto& buffer{_handle->result_buffers[index]};
|
||||||
meta_data.index = index;
|
new (&buffer._double) double{};
|
||||||
meta_data.len = nullptr;
|
|
||||||
meta_data.is_null = is_null;
|
|
||||||
|
|
||||||
MYSQL_BIND& param{_handle->result_params[index]};
|
MYSQL_BIND& param{_handle->result_params[index]};
|
||||||
param.buffer_type = MYSQL_TYPE_DOUBLE;
|
param.buffer_type = MYSQL_TYPE_DOUBLE;
|
||||||
param.buffer = value;
|
param.buffer = &buffer._double;
|
||||||
param.buffer_length = sizeof(*value);
|
param.buffer_length = sizeof(buffer._double);
|
||||||
param.length = &meta_data.bound_len;
|
param.length = &buffer.length;
|
||||||
param.is_null = &meta_data.bound_is_null;
|
param.is_null = &buffer.is_null;
|
||||||
param.is_unsigned = false;
|
param.is_unsigned = false;
|
||||||
param.error = &meta_data.bound_error;
|
param.error = &buffer.error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_text_result(size_t index, const char** value, size_t* len)
|
void bind_field(size_t index, sqlpp::string_view& /*value*/)
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "MySQL debug: binding text result " << static_cast<const void*>(*value) << " at index: " << index
|
std::cerr << "MySQL debug: binding text result at index: " << index
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
detail::result_meta_data_t& meta_data{_handle->result_param_meta_data[index]};
|
auto& buffer{_handle->result_buffers[index]};
|
||||||
meta_data.index = index;
|
|
||||||
meta_data.len = len;
|
|
||||||
meta_data.is_null = nullptr;
|
|
||||||
meta_data.text_buffer = value;
|
|
||||||
if (meta_data.bound_text_buffer.empty())
|
|
||||||
meta_data.bound_text_buffer.resize(8);
|
|
||||||
|
|
||||||
MYSQL_BIND& param{_handle->result_params[index]};
|
MYSQL_BIND& param{_handle->result_params[index]};
|
||||||
param.buffer_type = MYSQL_TYPE_STRING;
|
param.buffer_type = MYSQL_TYPE_STRING;
|
||||||
param.buffer = meta_data.bound_text_buffer.data();
|
param.buffer = buffer.var_buffer.data();
|
||||||
param.buffer_length = meta_data.bound_text_buffer.size();
|
param.buffer_length = buffer.var_buffer.size();
|
||||||
param.length = &meta_data.bound_len;
|
param.length = &buffer.length;
|
||||||
param.is_null = &meta_data.bound_is_null;
|
param.is_null = &buffer.is_null;
|
||||||
param.is_unsigned = false;
|
param.is_unsigned = false;
|
||||||
param.error = &meta_data.bound_error;
|
param.error = &buffer.error;
|
||||||
}
|
}
|
||||||
void _bind_blob_result(size_t index, const char** value, size_t* len)
|
|
||||||
|
void bind_field(size_t index, sqlpp::span<uint8_t>& /*value*/)
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "MySQL debug: binding text result " << static_cast<const void*>(*value) << " at index: " << index
|
std::cerr << "MySQL debug: binding blob result at index: " << index
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
detail::result_meta_data_t& meta_data{_handle->result_param_meta_data[index]};
|
auto& buffer{_handle->result_buffers[index]};
|
||||||
meta_data.index = index;
|
|
||||||
meta_data.len = len;
|
|
||||||
meta_data.is_null = nullptr;
|
|
||||||
meta_data.text_buffer = value;
|
|
||||||
if (meta_data.bound_text_buffer.empty())
|
|
||||||
meta_data.bound_text_buffer.resize(8);
|
|
||||||
|
|
||||||
MYSQL_BIND& param{_handle->result_params[index]};
|
MYSQL_BIND& param{_handle->result_params[index]};
|
||||||
param.buffer_type = MYSQL_TYPE_BLOB;
|
param.buffer_type = MYSQL_TYPE_BLOB;
|
||||||
param.buffer = meta_data.bound_text_buffer.data();
|
param.buffer = buffer.var_buffer.data();
|
||||||
param.buffer_length = meta_data.bound_text_buffer.size();
|
param.buffer_length = buffer.var_buffer.size();
|
||||||
param.length = &meta_data.bound_len;
|
param.length = &buffer.length;
|
||||||
param.is_null = &meta_data.bound_is_null;
|
param.is_null = &buffer.is_null;
|
||||||
param.is_unsigned = false;
|
param.is_unsigned = false;
|
||||||
param.error = &meta_data.bound_error;
|
param.error = &buffer.error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_date_result(size_t index, ::sqlpp::chrono::day_point* value, bool* is_null)
|
void bind_chrono_field(size_t index, enum_field_types buffer_type)
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
auto& buffer{_handle->result_buffers[index]};
|
||||||
std::cerr << "MySQL debug: binding date result " << static_cast<void*>(value) << " at index: " << index
|
new (&buffer._mysql_time) MYSQL_TIME{};
|
||||||
<< std::endl;
|
|
||||||
|
|
||||||
detail::result_meta_data_t& meta_data{_handle->result_param_meta_data[index]};
|
|
||||||
meta_data.index = index;
|
|
||||||
meta_data.len = nullptr;
|
|
||||||
meta_data.is_null = is_null;
|
|
||||||
meta_data.text_buffer = nullptr;
|
|
||||||
meta_data.bound_text_buffer.resize(sizeof(MYSQL_TIME));
|
|
||||||
|
|
||||||
MYSQL_BIND& param{_handle->result_params[index]};
|
MYSQL_BIND& param{_handle->result_params[index]};
|
||||||
param.buffer_type = MYSQL_TYPE_DATE;
|
param.buffer_type = buffer_type;
|
||||||
param.buffer = meta_data.bound_text_buffer.data();
|
param.buffer = &buffer._mysql_time;
|
||||||
param.buffer_length = meta_data.bound_text_buffer.size();
|
param.buffer_length = sizeof(buffer._mysql_time);
|
||||||
param.length = &meta_data.bound_len;
|
param.length = &buffer.length;
|
||||||
param.is_null = &meta_data.bound_is_null;
|
param.is_null = &buffer.is_null;
|
||||||
param.is_unsigned = false;
|
param.is_unsigned = false;
|
||||||
param.error = &meta_data.bound_error;
|
param.error = &buffer.error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_date_time_result(size_t index, ::sqlpp::chrono::microsecond_point* value, bool* is_null)
|
void bind_field(size_t index, ::sqlpp::chrono::day_point& /*value*/)
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "MySQL debug: binding date time result " << static_cast<void*>(value) << " at index: " << index
|
std::cerr << "MySQL debug: binding date result at index: " << index
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
detail::result_meta_data_t& meta_data{_handle->result_param_meta_data[index]};
|
bind_chrono_field(index, MYSQL_TYPE_DATE);
|
||||||
meta_data.index = index;
|
|
||||||
meta_data.len = nullptr;
|
|
||||||
meta_data.is_null = is_null;
|
|
||||||
meta_data.text_buffer = nullptr;
|
|
||||||
meta_data.bound_text_buffer.resize(sizeof(MYSQL_TIME));
|
|
||||||
|
|
||||||
MYSQL_BIND& param{_handle->result_params[index]};
|
|
||||||
param.buffer_type = MYSQL_TYPE_DATETIME;
|
|
||||||
param.buffer = meta_data.bound_text_buffer.data();
|
|
||||||
param.buffer_length = meta_data.bound_text_buffer.size();
|
|
||||||
param.length = &meta_data.bound_len;
|
|
||||||
param.is_null = &meta_data.bound_is_null;
|
|
||||||
param.is_unsigned = false;
|
|
||||||
param.error = &meta_data.bound_error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_time_of_day_result(size_t index, ::std::chrono::microseconds* value, bool* is_null)
|
void bind_field(size_t index, ::sqlpp::chrono::microsecond_point& /*value*/)
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "MySQL debug: binding time of day result " << static_cast<void*>(value) << " at index: " << index
|
std::cerr << "MySQL debug: binding date time result at index: " << index
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
detail::result_meta_data_t& meta_data{_handle->result_param_meta_data[index]};
|
bind_chrono_field(index, MYSQL_TYPE_DATETIME);
|
||||||
meta_data.index = index;
|
|
||||||
meta_data.len = nullptr;
|
|
||||||
meta_data.is_null = is_null;
|
|
||||||
meta_data.text_buffer = nullptr;
|
|
||||||
meta_data.bound_text_buffer.resize(sizeof(MYSQL_TIME));
|
|
||||||
|
|
||||||
MYSQL_BIND& param{_handle->result_params[index]};
|
|
||||||
param.buffer_type = MYSQL_TYPE_TIME;
|
|
||||||
param.buffer = meta_data.bound_text_buffer.data();
|
|
||||||
param.buffer_length = meta_data.bound_text_buffer.size();
|
|
||||||
param.length = &meta_data.bound_len;
|
|
||||||
param.is_null = &meta_data.bound_is_null;
|
|
||||||
param.is_unsigned = false;
|
|
||||||
param.error = &meta_data.bound_error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _post_bind_boolean_result(size_t /* index */, signed char* /* value */, bool* /* is_null */)
|
void bind_field(size_t index, ::std::chrono::microseconds& /*value*/)
|
||||||
{
|
|
||||||
}
|
|
||||||
void _post_bind_floating_point_result(size_t /* index */, double* /* value */, bool* /* is_null */)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
void _post_bind_integral_result(size_t /* index */, int64_t* /* value */, bool* /* is_null */)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
void _post_bind_unsigned_integral_result(size_t /* index */, uint64_t* /* value */, bool* /* is_null */)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
void _post_bind_text_result(size_t /* index */, const char** /* text */, size_t* /* len */)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
void _post_bind_date_result(size_t index, ::sqlpp::chrono::day_point* value, bool* is_null)
|
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "MySQL debug: post binding date result " << static_cast<void*>(value) << " at index: " << index
|
std::cerr << "MySQL debug: binding time of day result at index: " << index
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
if (not *is_null)
|
bind_chrono_field(index, MYSQL_TYPE_TIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void bind_field(size_t index, sqlpp::optional<T>& value)
|
||||||
{
|
{
|
||||||
const auto& dt =
|
value = T{};
|
||||||
*reinterpret_cast<const MYSQL_TIME*>(_handle->result_param_meta_data[index].bound_text_buffer.data());
|
bind_field(index, *value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_field(size_t index, bool& value)
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "MySQL debug: reading bool result at index: " << index
|
||||||
|
<< std::endl;
|
||||||
|
value = _handle->result_buffers[index]._bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_field(size_t index, int64_t& value)
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "MySQL debug: reading integral result at index: " << index
|
||||||
|
<< std::endl;
|
||||||
|
value = _handle->result_buffers[index]._int64;
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_field(size_t index, uint64_t& value)
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "MySQL debug: reading unsigned integral result at index: " << index
|
||||||
|
<< std::endl;
|
||||||
|
value = _handle->result_buffers[index]._uint64;
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_field(size_t index, double& value)
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "MySQL debug: reading floating point result at index: " << index
|
||||||
|
<< std::endl;
|
||||||
|
value = _handle->result_buffers[index]._double;
|
||||||
|
}
|
||||||
|
|
||||||
|
void refetch_if_required(size_t index)
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "MySQL debug: Checking result size at index: " << index
|
||||||
|
<< std::endl;
|
||||||
|
auto& buffer = _handle->result_buffers[index];
|
||||||
|
auto& params = _handle->result_params[index];
|
||||||
|
if (*params.length > params.buffer_length)
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "MySQL debug: increasing buffer at: " << index << " to " << *params.length << std::endl;
|
||||||
|
buffer.var_buffer.resize(*params.length);
|
||||||
|
params.buffer = buffer.var_buffer.data();
|
||||||
|
params.buffer_length = buffer.var_buffer.size();
|
||||||
|
const auto err = mysql_stmt_fetch_column(_handle->mysql_stmt, ¶ms, index, 0);
|
||||||
|
if (err)
|
||||||
|
throw sqlpp::exception{std::string{"MySQL: Fetch column after reallocate failed: "} + "error-code: " +
|
||||||
|
std::to_string(err) + ", stmt-error: " + mysql_stmt_error(_handle->mysql_stmt) +
|
||||||
|
", stmt-errno: " + std::to_string(mysql_stmt_errno(_handle->mysql_stmt))};
|
||||||
|
_require_bind = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_field(size_t index, sqlpp::string_view& value)
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "MySQL debug: reading text result at index: " << index
|
||||||
|
<< std::endl;
|
||||||
|
refetch_if_required(index);
|
||||||
|
const auto& buffer = _handle->result_buffers[index];
|
||||||
|
const auto& params = _handle->result_params[index];
|
||||||
|
value = sqlpp::string_view(buffer.var_buffer.data(), *params.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_field(size_t index, sqlpp::span<uint8_t>& value)
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "MySQL debug: reading blob result at index: " << index
|
||||||
|
<< std::endl;
|
||||||
|
refetch_if_required(index);
|
||||||
|
const auto& buffer = _handle->result_buffers[index];
|
||||||
|
const auto& params = _handle->result_params[index];
|
||||||
|
value = sqlpp::span<uint8_t>(reinterpret_cast<const uint8_t*>(buffer.var_buffer.data()), *params.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_field(size_t index, ::sqlpp::chrono::day_point& value)
|
||||||
|
{
|
||||||
|
if (_handle->debug)
|
||||||
|
std::cerr << "MySQL debug: reading date result at index: " << index
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
const auto& dt = _handle->result_buffers[index]._mysql_time;
|
||||||
if (dt.year > std::numeric_limits<int>::max())
|
if (dt.year > std::numeric_limits<int>::max())
|
||||||
throw sqlpp::exception{"cannot read year from db: " + std::to_string(dt.year)};
|
throw sqlpp::exception{"cannot read year from db: " + std::to_string(dt.year)};
|
||||||
*is_null = false;
|
value = ::date::year(static_cast<int>(dt.year)) / ::date::month(dt.month) / ::date::day(dt.day);
|
||||||
*value = ::date::year(static_cast<int>(dt.year)) / ::date::month(dt.month) / ::date::day(dt.day);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _post_bind_date_time_result(size_t index, ::sqlpp::chrono::microsecond_point* value, bool* is_null)
|
void read_field(size_t index, ::sqlpp::chrono::microsecond_point& value)
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "MySQL debug: post binding date time result " << static_cast<void*>(value) << " at index: " << index
|
std::cerr << "MySQL debug: reading date time result at index: " << index << std::endl;
|
||||||
<< std::endl;
|
|
||||||
|
|
||||||
if (not *is_null)
|
const auto& dt = _handle->result_buffers[index]._mysql_time;
|
||||||
{
|
|
||||||
const auto& dt =
|
|
||||||
*reinterpret_cast<const MYSQL_TIME*>(_handle->result_param_meta_data[index].bound_text_buffer.data());
|
|
||||||
if (dt.year > std::numeric_limits<int>::max())
|
if (dt.year > std::numeric_limits<int>::max())
|
||||||
throw sqlpp::exception{"cannot read year from db: " + std::to_string(dt.year)};
|
throw sqlpp::exception{"cannot read year from db: " + std::to_string(dt.year)};
|
||||||
*is_null = false;
|
value = ::sqlpp::chrono::day_point(::date::year(static_cast<int>(dt.year)) / ::date::month(dt.month) /
|
||||||
*value = ::sqlpp::chrono::day_point(::date::year(static_cast<int>(dt.year)) / ::date::month(dt.month) / ::date::day(dt.day)) +
|
::date::day(dt.day)) +
|
||||||
std::chrono::hours(dt.hour) + std::chrono::minutes(dt.minute) + std::chrono::seconds(dt.second) +
|
std::chrono::hours(dt.hour) + std::chrono::minutes(dt.minute) + std::chrono::seconds(dt.second) +
|
||||||
std::chrono::microseconds(dt.second_part);
|
std::chrono::microseconds(dt.second_part);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void _post_bind_time_of_day_result(size_t index, ::std::chrono::microseconds* value, bool* is_null)
|
void read_field(size_t index, ::std::chrono::microseconds& value)
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "MySQL debug: post binding date time result " << static_cast<void*>(value) << " at index: " << index
|
std::cerr << "MySQL debug: reading date time result at index: " << index << std::endl;
|
||||||
<< std::endl;
|
|
||||||
|
|
||||||
if (not *is_null)
|
const auto& dt = _handle->result_buffers[index]._mysql_time;
|
||||||
{
|
value = std::chrono::hours(dt.hour) + std::chrono::minutes(dt.minute) + std::chrono::seconds(dt.second) +
|
||||||
const auto& dt =
|
|
||||||
*reinterpret_cast<const MYSQL_TIME*>(_handle->result_param_meta_data[index].bound_text_buffer.data());
|
|
||||||
*value = std::chrono::hours(dt.hour) + std::chrono::minutes(dt.minute) + std::chrono::seconds(dt.second) +
|
|
||||||
std::chrono::microseconds(dt.second_part);
|
std::chrono::microseconds(dt.second_part);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void read_field(size_t index, sqlpp::optional<T>& value)
|
||||||
|
{
|
||||||
|
if (_handle->result_buffers[index].is_null)
|
||||||
|
{
|
||||||
|
value.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!value)
|
||||||
|
value = T{};
|
||||||
|
read_field(index, *value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -387,58 +416,12 @@ namespace sqlpp
|
|||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "MySQL debug: Accessing next row of handle at " << _handle.get() << std::endl;
|
std::cerr << "MySQL debug: Accessing next row of handle at " << _handle.get() << std::endl;
|
||||||
|
|
||||||
auto flag = mysql_stmt_fetch(_handle->mysql_stmt);
|
const auto flag = mysql_stmt_fetch(_handle->mysql_stmt);
|
||||||
|
|
||||||
switch (flag)
|
switch (flag)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
case MYSQL_DATA_TRUNCATED:
|
case MYSQL_DATA_TRUNCATED:
|
||||||
{
|
|
||||||
bool need_to_rebind{false};
|
|
||||||
for (auto& r : _handle->result_param_meta_data)
|
|
||||||
{
|
|
||||||
if (r.len)
|
|
||||||
{
|
|
||||||
if (r.bound_is_null)
|
|
||||||
{
|
|
||||||
*r.text_buffer = nullptr;
|
|
||||||
*r.len = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (r.bound_len > r.bound_text_buffer.size())
|
|
||||||
{
|
|
||||||
if (_handle->debug)
|
|
||||||
std::cerr << "MySQL debug: Need to reallocate buffer " << static_cast<const void*>(*r.text_buffer)
|
|
||||||
<< " at index " << r.index << " for handle at " << _handle.get() << std::endl;
|
|
||||||
need_to_rebind = true;
|
|
||||||
r.bound_text_buffer.resize(r.bound_len);
|
|
||||||
MYSQL_BIND& param{_handle->result_params[r.index]};
|
|
||||||
param.buffer = r.bound_text_buffer.data();
|
|
||||||
param.buffer_length = r.bound_text_buffer.size();
|
|
||||||
|
|
||||||
auto err =
|
|
||||||
mysql_stmt_fetch_column(_handle->mysql_stmt, ¶m, static_cast<unsigned int>(r.index), 0);
|
|
||||||
if (err)
|
|
||||||
throw sqlpp::exception{std::string{"MySQL: Fetch column after reallocate failed: "} +
|
|
||||||
"error-code: " + std::to_string(err) +
|
|
||||||
", stmt-error: " + mysql_stmt_error(_handle->mysql_stmt) +
|
|
||||||
", stmt-errno: " + std::to_string(mysql_stmt_errno(_handle->mysql_stmt))};
|
|
||||||
}
|
|
||||||
*r.text_buffer = r.bound_text_buffer.data();
|
|
||||||
if (_handle->debug)
|
|
||||||
std::cerr << "MySQL debug: New buffer " << static_cast<const void*>(*r.text_buffer) << " at index "
|
|
||||||
<< r.index << " for handle at " << _handle.get() << std::endl;
|
|
||||||
|
|
||||||
*r.len = r.bound_len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (r.is_null)
|
|
||||||
*r.is_null = r.bound_is_null;
|
|
||||||
}
|
|
||||||
if (need_to_rebind)
|
|
||||||
bind_impl();
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
case 1:
|
case 1:
|
||||||
throw sqlpp::exception{std::string{"MySQL: Could not fetch next result: "} +
|
throw sqlpp::exception{std::string{"MySQL: Could not fetch next result: "} +
|
||||||
|
@ -36,6 +36,9 @@
|
|||||||
#include <sqlpp11/mysql/detail/result_handle.h>
|
#include <sqlpp11/mysql/detail/result_handle.h>
|
||||||
#include <sqlpp11/mysql/sqlpp_mysql.h>
|
#include <sqlpp11/mysql/sqlpp_mysql.h>
|
||||||
#include <sqlpp11/mysql/char_result_row.h>
|
#include <sqlpp11/mysql/char_result_row.h>
|
||||||
|
#include <sqlpp11/compat/optional.h>
|
||||||
|
#include <sqlpp11/compat/string_view.h>
|
||||||
|
#include <sqlpp11/compat/span.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
@ -88,7 +91,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
result_row._validate();
|
result_row._validate();
|
||||||
}
|
}
|
||||||
result_row._bind(*this);
|
result_row._read_fields(*this);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -102,114 +105,102 @@ namespace sqlpp
|
|||||||
return !_handle or !*_handle;
|
return !_handle or !*_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_boolean_result(size_t index, signed char* value, bool* is_null)
|
void read_field(size_t index, bool& value)
|
||||||
{
|
{
|
||||||
*is_null = (_char_result_row.data == nullptr or _char_result_row.data[index] == nullptr);
|
value = (_char_result_row.data[index][0] == 't' or _char_result_row.data[index][0] == '1');
|
||||||
*value =
|
|
||||||
(*is_null ? false : (_char_result_row.data[index][0] == 't' or _char_result_row.data[index][0] == '1'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_floating_point_result(size_t index, double* value, bool* is_null)
|
void read_field(size_t index, double& value)
|
||||||
{
|
{
|
||||||
*is_null = (_char_result_row.data == nullptr or _char_result_row.data[index] == nullptr);
|
value = std::strtod(_char_result_row.data[index], nullptr);
|
||||||
*value = (*is_null ? 0 : std::strtod(_char_result_row.data[index], nullptr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_integral_result(size_t index, int64_t* value, bool* is_null)
|
void read_field(size_t index, int64_t& value)
|
||||||
{
|
{
|
||||||
*is_null = (_char_result_row.data == nullptr or _char_result_row.data[index] == nullptr);
|
value = std::strtoll(_char_result_row.data[index], nullptr, 10);
|
||||||
*value = (*is_null ? 0 : std::strtoll(_char_result_row.data[index], nullptr, 10));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_unsigned_integral_result(size_t index, uint64_t* value, bool* is_null)
|
void read_field(size_t index, uint64_t& value)
|
||||||
{
|
{
|
||||||
*is_null = (_char_result_row.data == nullptr or _char_result_row.data[index] == nullptr);
|
value = std::strtoull(_char_result_row.data[index], nullptr, 10);
|
||||||
*value = (*is_null ? 0 : std::strtoull(_char_result_row.data[index], nullptr, 10));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_blob_result(size_t index, const uint8_t** value, size_t* len)
|
void read_field(size_t index, sqlpp::span<uint8_t>& value)
|
||||||
{
|
{
|
||||||
bool is_null{_char_result_row.data == nullptr or _char_result_row.data[index] == nullptr};
|
value = sqlpp::span<uint8_t>(reinterpret_cast<const uint8_t*>(_char_result_row.data[index]), _char_result_row.len[index]);
|
||||||
*value = (uint8_t*)(is_null ? nullptr : _char_result_row.data[index]);
|
|
||||||
*len = (is_null ? 0 : _char_result_row.len[index]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_text_result(size_t index, const char** value, size_t* len)
|
void read_field(size_t index, sqlpp::string_view& value)
|
||||||
{
|
{
|
||||||
bool is_null{_char_result_row.data == nullptr or _char_result_row.data[index] == nullptr};
|
value = sqlpp::string_view(_char_result_row.data[index], _char_result_row.len[index]);
|
||||||
*value = (is_null ? nullptr : _char_result_row.data[index]);
|
|
||||||
*len = (is_null ? 0 : _char_result_row.len[index]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_date_result(size_t index, ::sqlpp::chrono::day_point* value, bool* is_null)
|
void read_field(size_t index, ::sqlpp::chrono::day_point& value)
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "MySQL debug: parsing date result at index: " << index << std::endl;
|
std::cerr << "MySQL debug: parsing date result at index: " << index << std::endl;
|
||||||
|
|
||||||
*value = {};
|
|
||||||
*is_null = (_char_result_row.data == nullptr or _char_result_row.data[index] == nullptr);
|
|
||||||
if (*is_null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto date_string = _char_result_row.data[index];
|
const auto date_string = _char_result_row.data[index];
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "MySQL debug: date string: " << date_string << std::endl;
|
std::cerr << "MySQL debug: date string: " << date_string << std::endl;
|
||||||
|
|
||||||
if (::sqlpp::detail::parse_date(*value, date_string) == false)
|
if (::sqlpp::detail::parse_date(value, date_string) == false)
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "MySQL debug: invalid date result: " << date_string << std::endl;
|
std::cerr << "MySQL debug: invalid date result: " << date_string << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_date_time_result(size_t index, ::sqlpp::chrono::microsecond_point* value, bool* is_null)
|
void read_field(size_t index, ::sqlpp::chrono::microsecond_point& value)
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "MySQL debug: parsing date result at index: " << index << std::endl;
|
std::cerr << "MySQL debug: parsing date result at index: " << index << std::endl;
|
||||||
|
|
||||||
*value = {};
|
|
||||||
*is_null = (_char_result_row.data == nullptr or _char_result_row.data[index] == nullptr);
|
|
||||||
if (*is_null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto date_time_string = _char_result_row.data[index];
|
const auto date_time_string = _char_result_row.data[index];
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "MySQL debug: date_time string: " << date_time_string << std::endl;
|
std::cerr << "MySQL debug: date_time string: " << date_time_string << std::endl;
|
||||||
|
|
||||||
if (::sqlpp::detail::parse_timestamp(*value, date_time_string) == false)
|
if (::sqlpp::detail::parse_timestamp(value, date_time_string) == false)
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "MySQL debug: invalid date_time result: " << date_time_string << std::endl;
|
std::cerr << "MySQL debug: invalid date_time result: " << date_time_string << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_time_of_day_result(size_t index, ::std::chrono::microseconds* value, bool* is_null)
|
void read_field(size_t index, ::std::chrono::microseconds& value)
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "MySQL debug: parsing time of day result at index: " << index << std::endl;
|
std::cerr << "MySQL debug: parsing time of day result at index: " << index << std::endl;
|
||||||
|
|
||||||
*value = {};
|
|
||||||
*is_null = (_char_result_row.data == nullptr or _char_result_row.data[index] == nullptr);
|
|
||||||
if (*is_null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto time_string = _char_result_row.data[index];
|
const auto time_string = _char_result_row.data[index];
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "MySQL debug: time of day string: " << time_string << std::endl;
|
std::cerr << "MySQL debug: time of day string: " << time_string << std::endl;
|
||||||
|
|
||||||
if (::sqlpp::detail::parse_time_of_day(*value, time_string) == false)
|
if (::sqlpp::detail::parse_time_of_day(value, time_string) == false)
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "MySQL debug: invalid time result: " << time_string << std::endl;
|
std::cerr << "MySQL debug: invalid time result: " << time_string << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto read_field(size_t index, sqlpp::optional<T>& value) -> void
|
||||||
|
{
|
||||||
|
const bool is_null = _char_result_row.data[index] == nullptr;
|
||||||
|
if (is_null)
|
||||||
|
{
|
||||||
|
value.reset();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (not value)
|
||||||
|
{
|
||||||
|
value = T{};
|
||||||
|
}
|
||||||
|
read_field(index, *value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool next_impl()
|
bool next_impl()
|
||||||
{
|
{
|
||||||
|
@ -36,16 +36,20 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
struct result_meta_data_t
|
struct bind_result_buffer
|
||||||
{
|
{
|
||||||
size_t index;
|
unsigned long length;
|
||||||
unsigned long bound_len;
|
my_bool is_null;
|
||||||
my_bool bound_is_null;
|
my_bool error;
|
||||||
my_bool bound_error;
|
union // unnamed union injects members into scope
|
||||||
std::vector<char> bound_text_buffer; // also for blobs
|
{
|
||||||
const char** text_buffer;
|
bool _bool;
|
||||||
size_t* len;
|
int64_t _int64;
|
||||||
bool* is_null;
|
uint64_t _uint64;
|
||||||
|
double _double;
|
||||||
|
MYSQL_TIME _mysql_time;
|
||||||
|
};
|
||||||
|
std::vector<char> var_buffer; // text and blobs
|
||||||
};
|
};
|
||||||
|
|
||||||
struct prepared_statement_handle_t
|
struct prepared_statement_handle_t
|
||||||
@ -72,7 +76,7 @@ namespace sqlpp
|
|||||||
std::vector<MYSQL_TIME> stmt_date_time_param_buffer;
|
std::vector<MYSQL_TIME> stmt_date_time_param_buffer;
|
||||||
std::vector<wrapped_bool> stmt_param_is_null; // my_bool is bool after 8.0, and vector<bool> is bad
|
std::vector<wrapped_bool> stmt_param_is_null; // my_bool is bool after 8.0, and vector<bool> is bad
|
||||||
std::vector<MYSQL_BIND> result_params;
|
std::vector<MYSQL_BIND> result_params;
|
||||||
std::vector<result_meta_data_t> result_param_meta_data;
|
std::vector<bind_result_buffer> result_buffers;
|
||||||
bool debug;
|
bool debug;
|
||||||
|
|
||||||
prepared_statement_handle_t(MYSQL_STMT* stmt, size_t no_of_parameters, size_t no_of_columns, bool debug_)
|
prepared_statement_handle_t(MYSQL_STMT* stmt, size_t no_of_parameters, size_t no_of_columns, bool debug_)
|
||||||
@ -81,7 +85,7 @@ namespace sqlpp
|
|||||||
stmt_date_time_param_buffer(no_of_parameters, MYSQL_TIME{}), // ()-init for correct constructor
|
stmt_date_time_param_buffer(no_of_parameters, MYSQL_TIME{}), // ()-init for correct constructor
|
||||||
stmt_param_is_null(no_of_parameters, false), // ()-init for correct constructor
|
stmt_param_is_null(no_of_parameters, false), // ()-init for correct constructor
|
||||||
result_params(no_of_columns, MYSQL_BIND{}), // ()-init for correct constructor
|
result_params(no_of_columns, MYSQL_BIND{}), // ()-init for correct constructor
|
||||||
result_param_meta_data(no_of_columns, result_meta_data_t{}), // ()-init for correct constructor
|
result_buffers(no_of_columns, bind_result_buffer{}), // ()-init for correct constructor
|
||||||
debug{debug_}
|
debug{debug_}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,9 @@
|
|||||||
#include <sqlpp11/chrono.h>
|
#include <sqlpp11/chrono.h>
|
||||||
#include <sqlpp11/data_types.h>
|
#include <sqlpp11/data_types.h>
|
||||||
#include <sqlpp11/detail/parse_date_time.h>
|
#include <sqlpp11/detail/parse_date_time.h>
|
||||||
|
#include <sqlpp11/compat/optional.h>
|
||||||
|
#include <sqlpp11/compat/string_view.h>
|
||||||
|
#include <sqlpp11/compat/span.h>
|
||||||
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -49,10 +52,63 @@ namespace sqlpp
|
|||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
struct statement_handle_t;
|
struct statement_handle_t;
|
||||||
|
|
||||||
|
inline unsigned char unhex(unsigned char c)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case '0':
|
||||||
|
case '1':
|
||||||
|
case '2':
|
||||||
|
case '3':
|
||||||
|
case '4':
|
||||||
|
case '5':
|
||||||
|
case '6':
|
||||||
|
case '7':
|
||||||
|
case '8':
|
||||||
|
case '9':
|
||||||
|
return c - '0';
|
||||||
|
case 'a':
|
||||||
|
case 'b':
|
||||||
|
case 'c':
|
||||||
|
case 'd':
|
||||||
|
case 'e':
|
||||||
|
case 'f':
|
||||||
|
return c + 10 - 'a';
|
||||||
|
case 'A':
|
||||||
|
case 'B':
|
||||||
|
case 'C':
|
||||||
|
case 'D':
|
||||||
|
case 'E':
|
||||||
|
case 'F':
|
||||||
|
return c + 10 - 'A';
|
||||||
}
|
}
|
||||||
|
throw sqlpp::exception{std::string{"Unexpected hex char: "} + static_cast<char>(c)};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t hex_assign(std::vector<uint8_t>& value, const uint8_t* blob, size_t len)
|
||||||
|
{
|
||||||
|
const auto result_size = len / 2 - 1; // unhex - leading chars
|
||||||
|
if (value.size() < result_size)
|
||||||
|
{
|
||||||
|
value.resize(result_size); // unhex - leading chars
|
||||||
|
}
|
||||||
|
size_t val_index = 0;
|
||||||
|
size_t blob_index = 2;
|
||||||
|
while (blob_index < len)
|
||||||
|
{
|
||||||
|
value[val_index] = static_cast<unsigned char>(unhex(blob[blob_index]) << 4) + unhex(blob[blob_index + 1]);
|
||||||
|
++val_index;
|
||||||
|
blob_index += 2;
|
||||||
|
}
|
||||||
|
return result_size;
|
||||||
|
}
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
class bind_result_t
|
class bind_result_t
|
||||||
{
|
{
|
||||||
|
// Need to buffer blobs (or switch to PQexecParams with binary results)
|
||||||
|
std::vector<std::vector<uint8_t>> _var_buffers;
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<detail::statement_handle_t> _handle;
|
std::shared_ptr<detail::statement_handle_t> _handle;
|
||||||
|
|
||||||
@ -97,9 +153,9 @@ namespace sqlpp
|
|||||||
|
|
||||||
bind_result_t(const std::shared_ptr<detail::statement_handle_t>& handle) : _handle(handle)
|
bind_result_t(const std::shared_ptr<detail::statement_handle_t>& handle) : _handle(handle)
|
||||||
{
|
{
|
||||||
|
_var_buffers.resize(_handle->result.field_count());
|
||||||
if (this->_handle && this->_handle->debug())
|
if (this->_handle && this->_handle->debug())
|
||||||
{
|
{
|
||||||
// cerr
|
|
||||||
std::cerr << "PostgreSQL debug: constructing bind result, using handle at: " << this->_handle.get()
|
std::cerr << "PostgreSQL debug: constructing bind result, using handle at: " << this->_handle.get()
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
@ -131,7 +187,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
result_row._validate();
|
result_row._validate();
|
||||||
}
|
}
|
||||||
result_row._bind(*this);
|
result_row._read_fields(*this);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -142,72 +198,60 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_boolean_result(size_t _index, signed char* value, bool* is_null)
|
void read_field(size_t _index, bool& value)
|
||||||
{
|
{
|
||||||
auto index = static_cast<int>(_index);
|
const auto index = static_cast<int>(_index);
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
std::cerr << "PostgreSQL debug: binding boolean result at index: " << index << std::endl;
|
std::cerr << "PostgreSQL debug: reading boolean result at index: " << index << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
*is_null = _handle->result.is_null(_handle->count, index);
|
value = _handle->result.get_bool_value(_handle->count, index);
|
||||||
*value = _handle->result.get_bool_value(_handle->count, index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_floating_point_result(size_t _index, double* value, bool* is_null)
|
void read_field(size_t _index, double& value)
|
||||||
{
|
{
|
||||||
auto index = static_cast<int>(_index);
|
const auto index = static_cast<int>(_index);
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
std::cerr << "PostgreSQL debug: binding floating_point result at index: " << index << std::endl;
|
std::cerr << "PostgreSQL debug: reading floating_point result at index: " << index << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
*is_null = _handle->result.is_null(_handle->count, index);
|
value = _handle->result.get_double_value(_handle->count, index);
|
||||||
*value = _handle->result.get_double_value(_handle->count, index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_integral_result(size_t _index, int64_t* value, bool* is_null)
|
void read_field(size_t _index, int64_t& value)
|
||||||
{
|
{
|
||||||
auto index = static_cast<int>(_index);
|
const auto index = static_cast<int>(_index);
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
std::cerr << "PostgreSQL debug: binding integral result at index: " << index << std::endl;
|
std::cerr << "PostgreSQL debug: reading integral result at index: " << index << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
*is_null = _handle->result.is_null(_handle->count, index);
|
value = _handle->result.get_int64_value(_handle->count, index);
|
||||||
*value = _handle->result.get_int64_value(_handle->count, index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_unsigned_integral_result(size_t _index, uint64_t* value, bool* is_null)
|
void read_field(size_t _index, uint64_t& value)
|
||||||
{
|
{
|
||||||
auto index = static_cast<int>(_index);
|
const auto index = static_cast<int>(_index);
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
std::cerr << "PostgreSQL debug: binding unsigned integral result at index: " << index << std::endl;
|
std::cerr << "PostgreSQL debug: reading unsigned integral result at index: " << index << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
*is_null = _handle->result.is_null(_handle->count, index);
|
value = _handle->result.get_uint64_value(_handle->count, index);
|
||||||
*value = _handle->result.get_uint64_value(_handle->count, index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_text_result(size_t _index, const char** value, size_t* len)
|
void read_field(size_t _index, sqlpp::string_view& value)
|
||||||
{
|
{
|
||||||
auto index = static_cast<int>(_index);
|
const auto index = static_cast<int>(_index);
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
std::cerr << "PostgreSQL debug: binding text result at index: " << index << std::endl;
|
std::cerr << "PostgreSQL debug: reading text result at index: " << index << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_handle->result.is_null(_handle->count, index))
|
value = sqlpp::string_view(_handle->result.get_char_ptr_value(_handle->count, index),
|
||||||
{
|
static_cast<size_t>(_handle->result.length(_handle->count, index)));
|
||||||
*value = nullptr;
|
|
||||||
*len = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*value = _handle->result.get_char_ptr_value(_handle->count, index);
|
|
||||||
*len = static_cast<size_t>(_handle->result.length(_handle->count, index));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PostgreSQL will return one of those (using the default ISO client):
|
// PostgreSQL will return one of those (using the default ISO client):
|
||||||
@ -218,20 +262,13 @@ namespace sqlpp
|
|||||||
// 1992-10-10 01:02:03-06:30 - for some timezones with non-hour offset
|
// 1992-10-10 01:02:03-06:30 - for some timezones with non-hour offset
|
||||||
// 1900-01-01 - date only
|
// 1900-01-01 - date only
|
||||||
// we do not support time-only values !
|
// we do not support time-only values !
|
||||||
void _bind_date_result(size_t _index, ::sqlpp::chrono::day_point* value, bool* is_null)
|
void read_field(size_t _index, ::sqlpp::chrono::day_point& value)
|
||||||
{
|
{
|
||||||
auto index = static_cast<int>(_index);
|
const auto index = static_cast<int>(_index);
|
||||||
|
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
std::cerr << "PostgreSQL debug: binding date result at index: " << index << std::endl;
|
std::cerr << "PostgreSQL debug: reading date result at index: " << index << std::endl;
|
||||||
}
|
|
||||||
|
|
||||||
*value = {};
|
|
||||||
*is_null = _handle->result.is_null(_handle->count, index);
|
|
||||||
if (*is_null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto date_string = _handle->result.get_char_ptr_value(_handle->count, index);
|
const auto date_string = _handle->result.get_char_ptr_value(_handle->count, index);
|
||||||
@ -239,7 +276,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
std::cerr << "PostgreSQL debug: date string: " << date_string << std::endl;
|
std::cerr << "PostgreSQL debug: date string: " << date_string << std::endl;
|
||||||
}
|
}
|
||||||
if (::sqlpp::detail::parse_date(*value, date_string) == false)
|
if (::sqlpp::detail::parse_date(value, date_string) == false)
|
||||||
{
|
{
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
@ -249,19 +286,12 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
// always returns UTC time for timestamp with time zone
|
// always returns UTC time for timestamp with time zone
|
||||||
void _bind_date_time_result(size_t _index, ::sqlpp::chrono::microsecond_point* value, bool* is_null)
|
void read_field(size_t _index, ::sqlpp::chrono::microsecond_point& value)
|
||||||
{
|
{
|
||||||
auto index = static_cast<int>(_index);
|
const auto index = static_cast<int>(_index);
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
std::cerr << "PostgreSQL debug: binding date_time result at index: " << index << std::endl;
|
std::cerr << "PostgreSQL debug: reading date_time result at index: " << index << std::endl;
|
||||||
}
|
|
||||||
|
|
||||||
*value = {};
|
|
||||||
*is_null = _handle->result.is_null(_handle->count, index);
|
|
||||||
if (*is_null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto date_string = _handle->result.get_char_ptr_value(_handle->count, index);
|
const auto date_string = _handle->result.get_char_ptr_value(_handle->count, index);
|
||||||
@ -269,7 +299,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
std::cerr << "PostgreSQL debug: got date_time string: " << date_string << std::endl;
|
std::cerr << "PostgreSQL debug: got date_time string: " << date_string << std::endl;
|
||||||
}
|
}
|
||||||
if (::sqlpp::detail::parse_timestamp(*value, date_string) == false)
|
if (::sqlpp::detail::parse_timestamp(value, date_string) == false)
|
||||||
{
|
{
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
@ -279,19 +309,12 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
// always returns UTC time for time with time zone
|
// always returns UTC time for time with time zone
|
||||||
void _bind_time_of_day_result(size_t _index, ::std::chrono::microseconds* value, bool* is_null)
|
void read_field(size_t _index, ::std::chrono::microseconds& value)
|
||||||
{
|
{
|
||||||
auto index = static_cast<int>(_index);
|
const auto index = static_cast<int>(_index);
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
std::cerr << "PostgreSQL debug: binding time result at index: " << index << std::endl;
|
std::cerr << "PostgreSQL debug: reading time result at index: " << index << std::endl;
|
||||||
}
|
|
||||||
|
|
||||||
*value = {};
|
|
||||||
*is_null = _handle->result.is_null(_handle->count, index);
|
|
||||||
if (*is_null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto time_string = _handle->result.get_char_ptr_value(_handle->count, index);
|
const auto time_string = _handle->result.get_char_ptr_value(_handle->count, index);
|
||||||
@ -301,7 +324,7 @@ namespace sqlpp
|
|||||||
std::cerr << "PostgreSQL debug: got time string: " << time_string << std::endl;
|
std::cerr << "PostgreSQL debug: got time string: " << time_string << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (::sqlpp::detail::parse_time_of_day(*value, time_string) == false)
|
if (::sqlpp::detail::parse_time_of_day(value, time_string) == false)
|
||||||
{
|
{
|
||||||
if (_handle->debug()) {
|
if (_handle->debug()) {
|
||||||
std::cerr << "PostgreSQL debug: got invalid time '" << time_string << "'" << std::endl;
|
std::cerr << "PostgreSQL debug: got invalid time '" << time_string << "'" << std::endl;
|
||||||
@ -309,23 +332,39 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_blob_result(size_t _index, const uint8_t** value, size_t* len)
|
void read_field(size_t _index, sqlpp::span<uint8_t>& value)
|
||||||
{
|
{
|
||||||
auto index = static_cast<int>(_index);
|
const auto index = static_cast<int>(_index);
|
||||||
if (_handle->debug())
|
if (_handle->debug())
|
||||||
{
|
{
|
||||||
std::cerr << "PostgreSQL debug: binding blob result at index: " << index << std::endl;
|
std::cerr << "PostgreSQL debug: reading blob result at index: " << index << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Need to decode the hex data.
|
||||||
|
// Using PQexecParams would allow to use binary data.
|
||||||
|
// That's certainly faster, but some effort to determine the correct column types.
|
||||||
|
const auto size =
|
||||||
|
detail::hex_assign(_var_buffers[_index], _handle->result.get_blob_value(_handle->count, index),
|
||||||
|
static_cast<size_t>(_handle->result.length(_handle->count, index)));
|
||||||
|
|
||||||
|
value = sqlpp::span<uint8_t>(_var_buffers[_index].data(), size);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto read_field(size_t _index, sqlpp::optional<T>& value) -> void
|
||||||
|
{
|
||||||
|
const auto index = static_cast<int>(_index);
|
||||||
if (_handle->result.is_null(_handle->count, index))
|
if (_handle->result.is_null(_handle->count, index))
|
||||||
{
|
{
|
||||||
*value = nullptr;
|
value.reset();
|
||||||
*len = 0;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*value = _handle->result.get_blob_value(_handle->count, index);
|
if (not value)
|
||||||
*len = static_cast<size_t>(_handle->result.length(_handle->count, index));
|
{
|
||||||
|
value = T{};
|
||||||
|
}
|
||||||
|
read_field(_index, *value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,6 @@
|
|||||||
#include <sqlpp11/connection.h>
|
#include <sqlpp11/connection.h>
|
||||||
#include <sqlpp11/detail/float_safe_ostringstream.h>
|
#include <sqlpp11/detail/float_safe_ostringstream.h>
|
||||||
#include <sqlpp11/postgresql/bind_result.h>
|
#include <sqlpp11/postgresql/bind_result.h>
|
||||||
#include <sqlpp11/postgresql/result_field.h>
|
|
||||||
#include <sqlpp11/postgresql/connection_config.h>
|
#include <sqlpp11/postgresql/connection_config.h>
|
||||||
#include <sqlpp11/postgresql/prepared_statement.h>
|
#include <sqlpp11/postgresql/prepared_statement.h>
|
||||||
#include <sqlpp11/postgresql/exception.h>
|
#include <sqlpp11/postgresql/exception.h>
|
||||||
|
@ -141,7 +141,9 @@ namespace sqlpp
|
|||||||
valid = false;
|
valid = false;
|
||||||
count = 0;
|
count = 0;
|
||||||
total_count = 0;
|
total_count = 0;
|
||||||
result = PQexecPrepared(connection.native_handle(), _name.data(), static_cast<int>(size), values.data(), nullptr, nullptr, 0);
|
result = PQexecPrepared(connection.native_handle(), /*stmtName*/ _name.data(),
|
||||||
|
/*nParams*/ static_cast<int>(size), /*paramValues*/ values.data(),
|
||||||
|
/*paramLengths*/ nullptr, /*paramFormats*/ nullptr, /*resultFormat*/ 0);
|
||||||
/// @todo validate result? is it really valid
|
/// @todo validate result? is it really valid
|
||||||
valid = true;
|
valid = true;
|
||||||
}
|
}
|
||||||
@ -171,7 +173,8 @@ namespace sqlpp
|
|||||||
void prepare(const std::string& stmt)
|
void prepare(const std::string& stmt)
|
||||||
{
|
{
|
||||||
// Create the prepared statement
|
// Create the prepared statement
|
||||||
result = PQprepare(connection.native_handle(), _name.c_str(), stmt.c_str(), 0, nullptr);
|
result = PQprepare(connection.native_handle(), _name.c_str(), stmt.c_str(),
|
||||||
|
/*nParams*/ 0, /*paramTypes*/ nullptr);
|
||||||
valid = true;
|
valid = true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -118,6 +118,7 @@ namespace sqlpp
|
|||||||
check_index(record, field);
|
check_index(record, field);
|
||||||
auto t = int64_t{};
|
auto t = int64_t{};
|
||||||
const auto txt = std::string{get_pq_value(m_result, record, field)};
|
const auto txt = std::string{get_pq_value(m_result, record, field)};
|
||||||
|
std::cerr << "txt: " << txt << ", record: " << record << ", field: " << field << std::endl;
|
||||||
if(txt != "")
|
if(txt != "")
|
||||||
{
|
{
|
||||||
t = std::stoll(txt);
|
t = std::stoll(txt);
|
||||||
|
@ -1,120 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2021-2021, Roland Bock
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
* other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sqlpp11/basic_expression_operators.h>
|
|
||||||
#include <sqlpp11/exception.h>
|
|
||||||
#include <sqlpp11/result_field.h>
|
|
||||||
#include <sqlpp11/result_field_base.h>
|
|
||||||
#include <sqlpp11/data_types/blob/data_type.h>
|
|
||||||
#include <sqlpp11/field_spec.h>
|
|
||||||
#include <ostream>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
namespace postgresql
|
|
||||||
{
|
|
||||||
// Forward declaration
|
|
||||||
class connection_base;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
inline unsigned char unhex(unsigned char c)
|
|
||||||
{
|
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case '0':
|
|
||||||
case '1':
|
|
||||||
case '2':
|
|
||||||
case '3':
|
|
||||||
case '4':
|
|
||||||
case '5':
|
|
||||||
case '6':
|
|
||||||
case '7':
|
|
||||||
case '8':
|
|
||||||
case '9':
|
|
||||||
return c - '0';
|
|
||||||
case 'a':
|
|
||||||
case 'b':
|
|
||||||
case 'c':
|
|
||||||
case 'd':
|
|
||||||
case 'e':
|
|
||||||
case 'f':
|
|
||||||
return c + 10 - 'a';
|
|
||||||
case 'A':
|
|
||||||
case 'B':
|
|
||||||
case 'C':
|
|
||||||
case 'D':
|
|
||||||
case 'E':
|
|
||||||
case 'F':
|
|
||||||
return c + 10 - 'A';
|
|
||||||
}
|
|
||||||
throw sqlpp::exception{std::string{"Unexpected hex char: "} + static_cast<char>(c)};
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void hex_assign(std::vector<unsigned char>& value, const uint8_t* blob, size_t len)
|
|
||||||
{
|
|
||||||
value.resize(len / 2 - 1); // unhex - leading chars
|
|
||||||
size_t val_index = 0;
|
|
||||||
size_t blob_index = 2;
|
|
||||||
while (blob_index < len)
|
|
||||||
{
|
|
||||||
value[val_index] = static_cast<unsigned char>(unhex(blob[blob_index]) << 4) + unhex(blob[blob_index + 1]);
|
|
||||||
++val_index;
|
|
||||||
blob_index += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
template <typename NameType, bool CanBeNull>
|
|
||||||
struct result_field_t<postgresql::connection_base, field_spec_t<NameType, blob, CanBeNull>>
|
|
||||||
: public result_field_base<postgresql::connection_base, field_spec_t<NameType, blob, CanBeNull>>
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
const uint8_t* _blob{nullptr}; // Non-owning
|
|
||||||
|
|
||||||
public:
|
|
||||||
size_t len{};
|
|
||||||
|
|
||||||
template <typename Target>
|
|
||||||
void _bind(Target& target, size_t index)
|
|
||||||
{
|
|
||||||
target._bind_blob_result(index, &_blob, &len);
|
|
||||||
if (_blob)
|
|
||||||
{
|
|
||||||
detail::hex_assign(this->_value, _blob, len);
|
|
||||||
len = this->_value.size();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
this->_value.clear();
|
|
||||||
this->_is_null = (_blob == nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
} // namespace sqlpp
|
|
@ -1,62 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
* other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <ostream>
|
|
||||||
#include <sqlpp11/wrong.h>
|
|
||||||
#include <sqlpp11/wrap_operand.h>
|
|
||||||
#include <sqlpp11/type_traits.h>
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
template <typename Db, typename FieldSpec>
|
|
||||||
struct result_field_t
|
|
||||||
{
|
|
||||||
using X = typename FieldSpec::incorrect;
|
|
||||||
static_assert(wrong_t<result_field_t>::value, "Missing specialization for result_field_t");
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Context, typename Db, typename FieldSpec>
|
|
||||||
Context& serialize(const result_field_t<Db, FieldSpec>& t, Context& context)
|
|
||||||
{
|
|
||||||
if (t.is_null())
|
|
||||||
{
|
|
||||||
context << "NULL";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
serialize(wrap_operand_t<cpp_value_type_of<FieldSpec>>(t.value()), context);
|
|
||||||
}
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Db, typename FieldSpec>
|
|
||||||
inline std::ostream& operator<<(std::ostream& os, const result_field_t<Db, FieldSpec>& rf)
|
|
||||||
{
|
|
||||||
return serialize(rf, os);
|
|
||||||
}
|
|
||||||
} // namespace sqlpp
|
|
@ -1,111 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2013-2016, Roland Bock
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
* other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sqlpp11/alias_operators.h>
|
|
||||||
#include <sqlpp11/basic_expression_operators.h>
|
|
||||||
#include <sqlpp11/exception.h>
|
|
||||||
#include <sqlpp11/result_field.h>
|
|
||||||
#include <sqlpp11/type_traits.h>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
template <typename Db, typename FieldSpec, typename StorageType = typename value_type_of<FieldSpec>::_cpp_value_type>
|
|
||||||
struct result_field_base
|
|
||||||
{
|
|
||||||
using _field_spec_t = FieldSpec;
|
|
||||||
using _alias_t = typename FieldSpec::_alias_t;
|
|
||||||
using _cpp_value_type = typename value_type_of<FieldSpec>::_cpp_value_type;
|
|
||||||
using _cpp_storage_type = StorageType;
|
|
||||||
|
|
||||||
using _traits = make_traits<value_type_of<_field_spec_t>,
|
|
||||||
tag::is_result_field,
|
|
||||||
tag::is_expression>;
|
|
||||||
|
|
||||||
using _nodes = detail::type_vector<>;
|
|
||||||
using _can_be_null = column_spec_can_be_null_t<_field_spec_t>;
|
|
||||||
|
|
||||||
result_field_base() : _is_valid{false}, _is_null{true}, _value{}
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const _cpp_value_type& rhs) const
|
|
||||||
{
|
|
||||||
return value() == rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const _cpp_value_type& rhs) const
|
|
||||||
{
|
|
||||||
return not operator==(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _validate()
|
|
||||||
{
|
|
||||||
_is_valid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _invalidate()
|
|
||||||
{
|
|
||||||
_is_valid = false;
|
|
||||||
_is_null = true;
|
|
||||||
_value = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_null() const
|
|
||||||
{
|
|
||||||
if (not _is_valid)
|
|
||||||
{
|
|
||||||
throw exception("accessing is_null in non-existing row");
|
|
||||||
}
|
|
||||||
return _is_null;
|
|
||||||
}
|
|
||||||
|
|
||||||
_cpp_value_type value() const
|
|
||||||
{
|
|
||||||
if (not _is_valid)
|
|
||||||
{
|
|
||||||
throw exception("accessing value in non-existing row");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_is_null)
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return _value;
|
|
||||||
}
|
|
||||||
|
|
||||||
operator _cpp_value_type() const
|
|
||||||
{
|
|
||||||
return value();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _is_valid;
|
|
||||||
bool _is_null;
|
|
||||||
_cpp_storage_type _value;
|
|
||||||
};
|
|
||||||
} // namespace sqlpp
|
|
@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <sqlpp11/compat/string_view.h>
|
||||||
#include <sqlpp11/data_types/text.h>
|
#include <sqlpp11/data_types/text.h>
|
||||||
#include <sqlpp11/detail/index_sequence.h>
|
#include <sqlpp11/detail/index_sequence.h>
|
||||||
#include <sqlpp11/dynamic_select_column_list.h>
|
#include <sqlpp11/dynamic_select_column_list.h>
|
||||||
@ -43,32 +44,22 @@ namespace sqlpp
|
|||||||
struct result_row_impl;
|
struct result_row_impl;
|
||||||
|
|
||||||
template <typename Db, std::size_t index, typename FieldSpec>
|
template <typename Db, std::size_t index, typename FieldSpec>
|
||||||
struct result_field : public member_t<FieldSpec, result_field_t<Db, FieldSpec>>
|
struct result_field : public member_t<FieldSpec, typename FieldSpec::cpp_type>
|
||||||
{
|
{
|
||||||
using _field = member_t<FieldSpec, result_field_t<Db, FieldSpec>>;
|
using _field = member_t<FieldSpec, typename FieldSpec::cpp_type>;
|
||||||
|
|
||||||
result_field() = default;
|
result_field() = default;
|
||||||
|
|
||||||
void _validate()
|
template <typename Target>
|
||||||
|
void _bind_field(Target& target)
|
||||||
{
|
{
|
||||||
_field::operator()()._validate();
|
target.bind_field(index, _field::operator()());
|
||||||
}
|
|
||||||
|
|
||||||
void _invalidate()
|
|
||||||
{
|
|
||||||
_field::operator()()._invalidate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Target>
|
template <typename Target>
|
||||||
void _bind(Target& target)
|
void _read_field(Target& target)
|
||||||
{
|
{
|
||||||
_field::operator()()._bind(target, index);
|
target.read_field(index, _field::operator()());
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Target>
|
|
||||||
void _post_bind(Target& target)
|
|
||||||
{
|
|
||||||
_field::operator()()._post_bind(target, index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Callable>
|
template <typename Callable>
|
||||||
@ -90,30 +81,18 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
result_row_impl() = default;
|
result_row_impl() = default;
|
||||||
|
|
||||||
void _validate()
|
template <typename Target>
|
||||||
|
void _bind_fields(Target& target)
|
||||||
{
|
{
|
||||||
using swallow = int[];
|
using swallow = int[];
|
||||||
(void)swallow{(result_field<Db, Is, FieldSpecs>::_validate(), 0)...};
|
(void)swallow{(result_field<Db, Is, FieldSpecs>::_bind_field(target), 0)...};
|
||||||
}
|
|
||||||
|
|
||||||
void _invalidate()
|
|
||||||
{
|
|
||||||
using swallow = int[];
|
|
||||||
(void)swallow{(result_field<Db, Is, FieldSpecs>::_invalidate(), 0)...};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Target>
|
template <typename Target>
|
||||||
void _bind(Target& target)
|
void _read_fields(Target& target)
|
||||||
{
|
{
|
||||||
using swallow = int[];
|
using swallow = int[];
|
||||||
(void)swallow{(result_field<Db, Is, FieldSpecs>::_bind(target), 0)...};
|
(void)swallow{(result_field<Db, Is, FieldSpecs>::_read_field(target), 0)...};
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Target>
|
|
||||||
void _post_bind(Target& target)
|
|
||||||
{
|
|
||||||
using swallow = int[];
|
|
||||||
(void)swallow{(result_field<Db, Is, FieldSpecs>::_post_bind(target), 0)...};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Callable>
|
template <typename Callable>
|
||||||
@ -154,13 +133,11 @@ namespace sqlpp
|
|||||||
|
|
||||||
void _validate()
|
void _validate()
|
||||||
{
|
{
|
||||||
_impl::_validate();
|
|
||||||
_is_valid = true;
|
_is_valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _invalidate()
|
void _invalidate()
|
||||||
{
|
{
|
||||||
_impl::_invalidate();
|
|
||||||
_is_valid = false;
|
_is_valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,15 +157,15 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Target>
|
template <typename Target>
|
||||||
void _bind(Target& target)
|
void _bind_fields(Target& target)
|
||||||
{
|
{
|
||||||
_impl::_bind(target);
|
_impl::_bind_fields(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Target>
|
template <typename Target>
|
||||||
void _post_bind(Target& target)
|
void _read_fields(Target& target)
|
||||||
{
|
{
|
||||||
_impl::_post_bind(target);
|
_impl::_read_fields(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Callable>
|
template <typename Callable>
|
||||||
@ -223,7 +200,7 @@ namespace sqlpp
|
|||||||
: public detail::result_row_impl<Db, detail::make_index_sequence<sizeof...(FieldSpecs)>, FieldSpecs...>
|
: public detail::result_row_impl<Db, detail::make_index_sequence<sizeof...(FieldSpecs)>, FieldSpecs...>
|
||||||
{
|
{
|
||||||
using _impl = detail::result_row_impl<Db, detail::make_index_sequence<sizeof...(FieldSpecs)>, FieldSpecs...>;
|
using _impl = detail::result_row_impl<Db, detail::make_index_sequence<sizeof...(FieldSpecs)>, FieldSpecs...>;
|
||||||
using _field_type = result_field_t<Db, field_spec_t<no_name_t, text, true>>;
|
using _field_type = sqlpp::string_view;
|
||||||
|
|
||||||
bool _is_valid{false};
|
bool _is_valid{false};
|
||||||
std::vector<std::string> _dynamic_field_names;
|
std::vector<std::string> _dynamic_field_names;
|
||||||
@ -249,22 +226,12 @@ namespace sqlpp
|
|||||||
|
|
||||||
void _validate()
|
void _validate()
|
||||||
{
|
{
|
||||||
_impl::_validate();
|
|
||||||
_is_valid = true;
|
_is_valid = true;
|
||||||
for (auto& field : _dynamic_fields)
|
|
||||||
{
|
|
||||||
field.second._validate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _invalidate()
|
void _invalidate()
|
||||||
{
|
{
|
||||||
_impl::_invalidate();
|
|
||||||
_is_valid = false;
|
_is_valid = false;
|
||||||
for (auto& field : _dynamic_fields)
|
|
||||||
{
|
|
||||||
field.second._invalidate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const dynamic_result_row_t& rhs) const
|
bool operator==(const dynamic_result_row_t& rhs) const
|
||||||
@ -290,7 +257,7 @@ namespace sqlpp
|
|||||||
std::size_t index = sizeof...(FieldSpecs);
|
std::size_t index = sizeof...(FieldSpecs);
|
||||||
for (const auto& field_name : _dynamic_field_names)
|
for (const auto& field_name : _dynamic_field_names)
|
||||||
{
|
{
|
||||||
_dynamic_fields.at(field_name)._bind(target, index);
|
target.read_field(index, _dynamic_fields.at(field_name));
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -303,7 +270,7 @@ namespace sqlpp
|
|||||||
std::size_t index = sizeof...(FieldSpecs);
|
std::size_t index = sizeof...(FieldSpecs);
|
||||||
for (const auto& field_name : _dynamic_field_names)
|
for (const auto& field_name : _dynamic_field_names)
|
||||||
{
|
{
|
||||||
_dynamic_fields.at(field_name)._post_bind(target, index);
|
target.post_read(index, _dynamic_fields.at(field_name));
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -313,11 +280,9 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
_impl::_apply(callable);
|
_impl::_apply(callable);
|
||||||
|
|
||||||
std::size_t index = sizeof...(FieldSpecs);
|
|
||||||
for (const auto& field_name : _dynamic_field_names)
|
for (const auto& field_name : _dynamic_field_names)
|
||||||
{
|
{
|
||||||
_dynamic_fields.at(field_name)._apply(callable);
|
callable(_dynamic_fields.at(field_name));
|
||||||
++index;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,11 +291,9 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
_impl::_apply(callable);
|
_impl::_apply(callable);
|
||||||
|
|
||||||
std::size_t index = sizeof...(FieldSpecs);
|
|
||||||
for (const auto& field_name : _dynamic_field_names)
|
for (const auto& field_name : _dynamic_field_names)
|
||||||
{
|
{
|
||||||
_dynamic_fields.at(field_name)._apply(callable);
|
callable(_dynamic_fields.at(field_name));
|
||||||
++index;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -31,6 +31,9 @@
|
|||||||
#include <sqlpp11/exception.h>
|
#include <sqlpp11/exception.h>
|
||||||
#include <sqlpp11/sqlite3/detail/prepared_statement_handle.h>
|
#include <sqlpp11/sqlite3/detail/prepared_statement_handle.h>
|
||||||
#include <sqlpp11/sqlite3/export.h>
|
#include <sqlpp11/sqlite3/export.h>
|
||||||
|
#include <sqlpp11/compat/optional.h>
|
||||||
|
#include <sqlpp11/compat/string_view.h>
|
||||||
|
#include <sqlpp11/compat/span.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@ -83,7 +86,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
result_row._validate();
|
result_row._validate();
|
||||||
}
|
}
|
||||||
result_row._bind(*this);
|
result_row._read_fields(*this);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -92,118 +95,119 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_boolean_result(size_t index, signed char* value, bool* is_null)
|
void read_field(size_t index, bool& value)
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "Sqlite3 debug: binding boolean result " << *value << " at index: " << index << std::endl;
|
std::cerr << "Sqlite3 debug: binding boolean result at index: " << index << std::endl;
|
||||||
|
|
||||||
*value = static_cast<signed char>(sqlite3_column_int(_handle->sqlite_statement, static_cast<int>(index)));
|
value = static_cast<signed char>(sqlite3_column_int(_handle->sqlite_statement, static_cast<int>(index)));
|
||||||
*is_null = sqlite3_column_type(_handle->sqlite_statement, static_cast<int>(index)) == SQLITE_NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_floating_point_result(size_t index, double* value, bool* is_null)
|
void read_field(size_t index, double& value)
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "Sqlite3 debug: binding floating_point result " << *value << " at index: " << index << std::endl;
|
std::cerr << "Sqlite3 debug: binding floating_point result at index: " << index << std::endl;
|
||||||
|
|
||||||
switch (sqlite3_column_type(_handle->sqlite_statement, static_cast<int>(index)))
|
switch (sqlite3_column_type(_handle->sqlite_statement, static_cast<int>(index)))
|
||||||
{
|
{
|
||||||
case (SQLITE3_TEXT):
|
case (SQLITE3_TEXT):
|
||||||
*value = atof(
|
value = atof(
|
||||||
reinterpret_cast<const char*>(sqlite3_column_text(_handle->sqlite_statement, static_cast<int>(index))));
|
reinterpret_cast<const char*>(sqlite3_column_text(_handle->sqlite_statement, static_cast<int>(index))));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
*value = sqlite3_column_double(_handle->sqlite_statement, static_cast<int>(index));
|
value = sqlite3_column_double(_handle->sqlite_statement, static_cast<int>(index));
|
||||||
}
|
}
|
||||||
*is_null = sqlite3_column_type(_handle->sqlite_statement, static_cast<int>(index)) == SQLITE_NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_integral_result(size_t index, int64_t* value, bool* is_null)
|
void read_field(size_t index, int64_t& value)
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "Sqlite3 debug: binding integral result " << *value << " at index: " << index << std::endl;
|
std::cerr << "Sqlite3 debug: reading integral result at index: " << index << std::endl;
|
||||||
|
|
||||||
*value = sqlite3_column_int64(_handle->sqlite_statement, static_cast<int>(index));
|
value = sqlite3_column_int64(_handle->sqlite_statement, static_cast<int>(index));
|
||||||
*is_null = sqlite3_column_type(_handle->sqlite_statement, static_cast<int>(index)) == SQLITE_NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_unsigned_integral_result(size_t index, uint64_t* value, bool* is_null)
|
void read_field(size_t index, uint64_t& value)
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "Sqlite3 debug: binding unsigned integral result " << *value << " at index: " << index
|
std::cerr << "Sqlite3 debug: binding unsigned integral result at index: " << index << std::endl;
|
||||||
<< std::endl;
|
|
||||||
|
|
||||||
*value = static_cast<uint64_t>(sqlite3_column_int64(_handle->sqlite_statement, static_cast<int>(index)));
|
value = static_cast<uint64_t>(sqlite3_column_int64(_handle->sqlite_statement, static_cast<int>(index)));
|
||||||
*is_null = sqlite3_column_type(_handle->sqlite_statement, static_cast<int>(index)) == SQLITE_NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_text_result(size_t index, const char** value, size_t* len)
|
void read_field(size_t index, sqlpp::string_view& value)
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "Sqlite3 debug: binding text result at index: " << index << std::endl;
|
std::cerr << "Sqlite3 debug: binding text result at index: " << index << std::endl;
|
||||||
|
|
||||||
*value =
|
value = sqlpp::string_view(
|
||||||
(reinterpret_cast<const char*>(sqlite3_column_text(_handle->sqlite_statement, static_cast<int>(index))));
|
reinterpret_cast<const char*>(sqlite3_column_text(_handle->sqlite_statement, static_cast<int>(index))),
|
||||||
*len = static_cast<size_t>(sqlite3_column_bytes(_handle->sqlite_statement, static_cast<int>(index)));
|
static_cast<size_t>(sqlite3_column_bytes(_handle->sqlite_statement, static_cast<int>(index))));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_blob_result(size_t index, const uint8_t** value, size_t* len)
|
void read_field(size_t index, sqlpp::span<uint8_t>& value)
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "Sqlite3 debug: binding text result at index: " << index << std::endl;
|
std::cerr << "Sqlite3 debug: binding blob result at index: " << index << std::endl;
|
||||||
|
|
||||||
*value =
|
value = sqlpp::span<uint8_t>(
|
||||||
(reinterpret_cast<const uint8_t*>(sqlite3_column_blob(_handle->sqlite_statement, static_cast<int>(index))));
|
reinterpret_cast<const uint8_t*>(sqlite3_column_blob(_handle->sqlite_statement, static_cast<int>(index))),
|
||||||
*len = static_cast<size_t>(sqlite3_column_bytes(_handle->sqlite_statement, static_cast<int>(index)));
|
static_cast<size_t>(sqlite3_column_bytes(_handle->sqlite_statement, static_cast<int>(index))));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_date_result(size_t index, ::sqlpp::chrono::day_point* value, bool* is_null)
|
void read_field(size_t index, ::sqlpp::chrono::day_point& value)
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "Sqlite3 debug: binding date result at index: " << index << std::endl;
|
std::cerr << "Sqlite3 debug: binding date result at index: " << index << std::endl;
|
||||||
|
|
||||||
*value = {};
|
|
||||||
*is_null = sqlite3_column_type(_handle->sqlite_statement, static_cast<int>(index)) == SQLITE_NULL;
|
|
||||||
if (*is_null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto date_string =
|
const auto date_string =
|
||||||
reinterpret_cast<const char*>(sqlite3_column_text(_handle->sqlite_statement, static_cast<int>(index)));
|
reinterpret_cast<const char*>(sqlite3_column_text(_handle->sqlite_statement, static_cast<int>(index)));
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "Sqlite3 debug: date string: " << date_string << std::endl;
|
std::cerr << "Sqlite3 debug: date string: " << date_string << std::endl;
|
||||||
if (::sqlpp::detail::parse_date(*value, date_string) == false)
|
if (::sqlpp::detail::parse_date(value, date_string) == false)
|
||||||
{
|
{
|
||||||
|
value = {};
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "Sqlite3 debug: invalid date result: " << date_string << std::endl;
|
std::cerr << "Sqlite3 debug: invalid date result: " << date_string << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _bind_date_time_result(size_t index, ::sqlpp::chrono::microsecond_point* value, bool* is_null)
|
void read_field(size_t index, ::sqlpp::chrono::microsecond_point& value)
|
||||||
{
|
{
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "Sqlite3 debug: binding date result at index: " << index << std::endl;
|
std::cerr << "Sqlite3 debug: binding date result at index: " << index << std::endl;
|
||||||
|
|
||||||
*value = {};
|
|
||||||
*is_null = sqlite3_column_type(_handle->sqlite_statement, static_cast<int>(index)) == SQLITE_NULL;
|
|
||||||
if (*is_null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto date_time_string =
|
const auto date_time_string =
|
||||||
reinterpret_cast<const char*>(sqlite3_column_text(_handle->sqlite_statement, static_cast<int>(index)));
|
reinterpret_cast<const char*>(sqlite3_column_text(_handle->sqlite_statement, static_cast<int>(index)));
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "Sqlite3 debug: date_time string: " << date_time_string << std::endl;
|
std::cerr << "Sqlite3 debug: date_time string: " << date_time_string << std::endl;
|
||||||
// We treat DATETIME fields as containing either date+time or just date.
|
// We treat DATETIME fields as containing either date+time or just date.
|
||||||
if (::sqlpp::detail::parse_date_or_timestamp(*value, date_time_string) == false)
|
if (::sqlpp::detail::parse_date_or_timestamp(value, date_time_string) == false)
|
||||||
{
|
{
|
||||||
|
value = {};
|
||||||
if (_handle->debug)
|
if (_handle->debug)
|
||||||
std::cerr << "Sqlite3 debug: invalid date_time result: " << date_time_string << std::endl;
|
std::cerr << "Sqlite3 debug: invalid date_time result: " << date_time_string << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto read_field(size_t index, sqlpp::optional<T>& value) -> void
|
||||||
|
{
|
||||||
|
const bool is_null = sqlite3_column_type(_handle->sqlite_statement, static_cast<int>(index)) == SQLITE_NULL;
|
||||||
|
if (is_null)
|
||||||
|
{
|
||||||
|
value.reset();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (not value)
|
||||||
|
{
|
||||||
|
value = T{};
|
||||||
|
}
|
||||||
|
read_field(index, *value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool next_impl()
|
bool next_impl()
|
||||||
{
|
{
|
||||||
|
@ -47,12 +47,11 @@ int Insert(int, char* [])
|
|||||||
"INSERT INTO tab_bar (beta,gamma) VALUES('cheesecake'," + getTrue() + ")");
|
"INSERT INTO tab_bar (beta,gamma) VALUES('cheesecake'," + getTrue() + ")");
|
||||||
compare(__LINE__, insert_into(bar).set(bar.beta = ::sqlpp::null, bar.gamma = true),
|
compare(__LINE__, insert_into(bar).set(bar.beta = ::sqlpp::null, bar.gamma = true),
|
||||||
"INSERT INTO tab_bar (beta,gamma) VALUES(NULL," + getTrue() + ")");
|
"INSERT INTO tab_bar (beta,gamma) VALUES(NULL," + getTrue() + ")");
|
||||||
#if __cplusplus >= 201703L
|
sqlpp::string_view cheeseCake = "cheesecake";
|
||||||
// string_view argument
|
compare(__LINE__, insert_into(bar).set(bar.beta = std::string(cheeseCake), bar.gamma = true),
|
||||||
std::string_view cheeseCake = "cheesecake";
|
"INSERT INTO tab_bar (beta,gamma) VALUES('cheesecake'," + getTrue() + ")");
|
||||||
compare(__LINE__, insert_into(bar).set(bar.beta = cheeseCake, bar.gamma = true),
|
compare(__LINE__, insert_into(bar).set(bar.beta = sqlpp::string_view(cheeseCake), bar.gamma = true),
|
||||||
"INSERT INTO tab_bar (beta,gamma) VALUES('cheesecake'," + getTrue() + ")");
|
"INSERT INTO tab_bar (beta,gamma) VALUES('cheesecake'," + getTrue() + ")");
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -68,11 +68,12 @@ int Where(int, char*[])
|
|||||||
compare(__LINE__, where(is_equal_to_or_null(bar.beta, ::sqlpp::value_or_null("SQL"))), " WHERE (tab_bar.beta='SQL')");
|
compare(__LINE__, where(is_equal_to_or_null(bar.beta, ::sqlpp::value_or_null("SQL"))), " WHERE (tab_bar.beta='SQL')");
|
||||||
compare(__LINE__, where(is_equal_to_or_null(bar.beta, ::sqlpp::value_or_null<sqlpp::text>(::sqlpp::null))),
|
compare(__LINE__, where(is_equal_to_or_null(bar.beta, ::sqlpp::value_or_null<sqlpp::text>(::sqlpp::null))),
|
||||||
" WHERE tab_bar.beta IS NULL");
|
" WHERE tab_bar.beta IS NULL");
|
||||||
#if __cplusplus >= 201703L
|
|
||||||
|
// string argument
|
||||||
|
compare(__LINE__, where(bar.beta == std::string("SQL")), " WHERE (tab_bar.beta='SQL')");
|
||||||
|
|
||||||
// string_view argument
|
// string_view argument
|
||||||
std::string_view sqlString = "SQL";
|
compare(__LINE__, where(bar.beta == sqlpp::string_view("SQL")), " WHERE (tab_bar.beta='SQL')");
|
||||||
compare(__LINE__, where(bar.beta == sqlString), " WHERE (tab_bar.beta='SQL')");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
#include "Sample.h"
|
#include "Sample.h"
|
||||||
#include <sqlpp11/sqlpp11.h>
|
#include <sqlpp11/sqlpp11.h>
|
||||||
|
|
||||||
|
#include "../../include/test_helpers.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
constexpr auto bar = test::TabBar{};
|
constexpr auto bar = test::TabBar{};
|
||||||
@ -47,9 +49,9 @@ namespace
|
|||||||
// result fields are as nullable as the expressions they represent
|
// result fields are as nullable as the expressions they represent
|
||||||
const auto rows = db(select(bar.alpha, bar.gamma, seven).from(bar).unconditionally());
|
const auto rows = db(select(bar.alpha, bar.gamma, seven).from(bar).unconditionally());
|
||||||
auto& x = rows.front();
|
auto& x = rows.front();
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "");
|
static_assert(is_optional<decltype(x.alpha)>::value, "");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value, "");
|
static_assert(not is_optional<decltype(x.gamma)>::value, "");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "");
|
static_assert(not is_optional<decltype(x.s)>::value, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,20 +63,20 @@ namespace
|
|||||||
.from(foo.join(bar).on(foo.omega > bar.alpha))
|
.from(foo.join(bar).on(foo.omega > bar.alpha))
|
||||||
.unconditionally());
|
.unconditionally());
|
||||||
auto& x = rows.front();
|
auto& x = rows.front();
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
static_assert(is_optional<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.delta)>::value, "left side of (inner) join cannot be null");
|
static_assert(not is_optional<decltype(x.delta)>::value, "left side of (inner) join cannot be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value, "right side of (inner) join cannot be null");
|
static_assert(not is_optional<decltype(x.gamma)>::value, "right side of (inner) join cannot be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
static_assert(not is_optional<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const auto& rows = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
const auto& rows = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
||||||
.from(bar.join(foo).on(foo.omega > bar.alpha))
|
.from(bar.join(foo).on(foo.omega > bar.alpha))
|
||||||
.unconditionally());
|
.unconditionally());
|
||||||
auto& x = rows.front();
|
auto& x = rows.front();
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
static_assert(is_optional<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value, "left side of (inner) join cannot be null");
|
static_assert(not is_optional<decltype(x.gamma)>::value, "left side of (inner) join cannot be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.delta)>::value, "right side of (inner) join cannot be null");
|
static_assert(not is_optional<decltype(x.delta)>::value, "right side of (inner) join cannot be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
static_assert(not is_optional<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
MockSizeDb db2;
|
MockSizeDb db2;
|
||||||
@ -91,20 +93,20 @@ namespace
|
|||||||
.from(foo.inner_join(bar).on(foo.omega > bar.alpha))
|
.from(foo.inner_join(bar).on(foo.omega > bar.alpha))
|
||||||
.unconditionally());
|
.unconditionally());
|
||||||
auto& x = rows.front();
|
auto& x = rows.front();
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
static_assert(is_optional<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.delta)>::value, "left side of inner join cannot be null");
|
static_assert(not is_optional<decltype(x.delta)>::value, "left side of inner join cannot be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value, "right side of inner join cannot be null");
|
static_assert(not is_optional<decltype(x.gamma)>::value, "right side of inner join cannot be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
static_assert(not is_optional<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const auto rows = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
const auto rows = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
||||||
.from(bar.inner_join(foo).on(foo.omega > bar.alpha))
|
.from(bar.inner_join(foo).on(foo.omega > bar.alpha))
|
||||||
.unconditionally());
|
.unconditionally());
|
||||||
auto& x = rows.front();
|
auto& x = rows.front();
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
static_assert(is_optional<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value, "left side of inner join cannot be null");
|
static_assert(not is_optional<decltype(x.gamma)>::value, "left side of inner join cannot be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.delta)>::value, "right side of inner join cannot be null");
|
static_assert(not is_optional<decltype(x.delta)>::value, "right side of inner join cannot be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
static_assert(not is_optional<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Left outer join
|
// Left outer join
|
||||||
@ -113,20 +115,20 @@ namespace
|
|||||||
.from(foo.left_outer_join(bar).on(foo.omega > bar.alpha))
|
.from(foo.left_outer_join(bar).on(foo.omega > bar.alpha))
|
||||||
.unconditionally());
|
.unconditionally());
|
||||||
auto& x = rows.front();
|
auto& x = rows.front();
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
static_assert(is_optional<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.delta)>::value, "left side of left outer join cannot be null");
|
static_assert(not is_optional<decltype(x.delta)>::value, "left side of left outer join cannot be null");
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.gamma)>::value, "right side of left outer join can be null");
|
static_assert(is_optional<decltype(x.gamma)>::value, "right side of left outer join can be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
static_assert(not is_optional<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const auto rows = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
const auto rows = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
||||||
.from(bar.left_outer_join(foo).on(foo.omega > bar.alpha))
|
.from(bar.left_outer_join(foo).on(foo.omega > bar.alpha))
|
||||||
.unconditionally());
|
.unconditionally());
|
||||||
auto& x = rows.front();
|
auto& x = rows.front();
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
static_assert(is_optional<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value, "left side of left outer join cannot be null");
|
static_assert(not is_optional<decltype(x.gamma)>::value, "left side of left outer join cannot be null");
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.delta)>::value, "right side of left outer join can be null");
|
static_assert(is_optional<decltype(x.delta)>::value, "right side of left outer join can be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
static_assert(not is_optional<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Right outer join
|
// Right outer join
|
||||||
@ -135,22 +137,22 @@ namespace
|
|||||||
.from(foo.right_outer_join(bar).on(foo.omega > bar.alpha))
|
.from(foo.right_outer_join(bar).on(foo.omega > bar.alpha))
|
||||||
.unconditionally());
|
.unconditionally());
|
||||||
auto& x = rows.front();
|
auto& x = rows.front();
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
static_assert(is_optional<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.delta)>::value, "left side of right outer join can be null");
|
static_assert(is_optional<decltype(x.delta)>::value, "left side of right outer join can be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value,
|
static_assert(not is_optional<decltype(x.gamma)>::value,
|
||||||
"right side of right outer join cannot be null");
|
"right side of right outer join cannot be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
static_assert(not is_optional<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const auto rows = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
const auto rows = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
||||||
.from(bar.right_outer_join(foo).on(foo.omega > bar.alpha))
|
.from(bar.right_outer_join(foo).on(foo.omega > bar.alpha))
|
||||||
.unconditionally());
|
.unconditionally());
|
||||||
auto& x = rows.front();
|
auto& x = rows.front();
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
static_assert(is_optional<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.gamma)>::value, "left side of right outer join can be null");
|
static_assert(is_optional<decltype(x.gamma)>::value, "left side of right outer join can be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.delta)>::value,
|
static_assert(not is_optional<decltype(x.delta)>::value,
|
||||||
"right side of right outer join cannot be null");
|
"right side of right outer join cannot be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
static_assert(not is_optional<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Outer join
|
// Outer join
|
||||||
@ -159,20 +161,20 @@ namespace
|
|||||||
.from(foo.outer_join(bar).on(foo.omega > bar.alpha))
|
.from(foo.outer_join(bar).on(foo.omega > bar.alpha))
|
||||||
.unconditionally());
|
.unconditionally());
|
||||||
auto& x = rows.front();
|
auto& x = rows.front();
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
static_assert(is_optional<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.delta)>::value, "left side of outer join can be null");
|
static_assert(is_optional<decltype(x.delta)>::value, "left side of outer join can be null");
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.gamma)>::value, "right side of outer join can be null");
|
static_assert(is_optional<decltype(x.gamma)>::value, "right side of outer join can be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
static_assert(not is_optional<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const auto rows = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
const auto rows = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
||||||
.from(bar.outer_join(foo).on(foo.omega > bar.alpha))
|
.from(bar.outer_join(foo).on(foo.omega > bar.alpha))
|
||||||
.unconditionally());
|
.unconditionally());
|
||||||
auto& x = rows.front();
|
auto& x = rows.front();
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
static_assert(is_optional<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.gamma)>::value, "left side of outer join can be null");
|
static_assert(is_optional<decltype(x.gamma)>::value, "left side of outer join can be null");
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.delta)>::value, "right side of outer join can be null");
|
static_assert(is_optional<decltype(x.delta)>::value, "right side of outer join can be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
static_assert(not is_optional<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cross join
|
// Cross join
|
||||||
@ -180,19 +182,19 @@ namespace
|
|||||||
const auto rows =
|
const auto rows =
|
||||||
db(select(bar.alpha, foo.delta, bar.gamma, seven).from(foo.cross_join(bar)).unconditionally());
|
db(select(bar.alpha, foo.delta, bar.gamma, seven).from(foo.cross_join(bar)).unconditionally());
|
||||||
auto& x = rows.front();
|
auto& x = rows.front();
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
static_assert(is_optional<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.delta)>::value, "left side of cross join cannot be null");
|
static_assert(not is_optional<decltype(x.delta)>::value, "left side of cross join cannot be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value, "right side of cross join cannot be null");
|
static_assert(not is_optional<decltype(x.gamma)>::value, "right side of cross join cannot be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
static_assert(not is_optional<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const auto rows =
|
const auto rows =
|
||||||
db(select(bar.alpha, foo.delta, bar.gamma, seven).from(bar.cross_join(foo)).unconditionally());
|
db(select(bar.alpha, foo.delta, bar.gamma, seven).from(bar.cross_join(foo)).unconditionally());
|
||||||
auto& x = rows.front();
|
auto& x = rows.front();
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
static_assert(is_optional<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value, "left side of cross join cannot be null");
|
static_assert(not is_optional<decltype(x.gamma)>::value, "left side of cross join cannot be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.delta)>::value, "right side of cross join cannot be null");
|
static_assert(not is_optional<decltype(x.delta)>::value, "right side of cross join cannot be null");
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
static_assert(not is_optional<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,11 +207,11 @@ namespace
|
|||||||
static_assert(sqlpp::can_be_null_t<decltype(a)>::value, "");
|
static_assert(sqlpp::can_be_null_t<decltype(a)>::value, "");
|
||||||
const auto rows = db(select(count(a), avg(a), max(a), min(a), sum(a)).from(bar).unconditionally());
|
const auto rows = db(select(count(a), avg(a), max(a), min(a), sum(a)).from(bar).unconditionally());
|
||||||
auto& x = rows.front();
|
auto& x = rows.front();
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.count)>::value, "");
|
static_assert(not is_optional<decltype(x.count)>::value, "");
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.avg)>::value, "");
|
static_assert(is_optional<decltype(x.avg)>::value, "");
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.sum)>::value, "");
|
static_assert(is_optional<decltype(x.sum)>::value, "");
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.max)>::value, "");
|
static_assert(is_optional<decltype(x.max)>::value, "");
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.min)>::value, "");
|
static_assert(is_optional<decltype(x.min)>::value, "");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// aggregates of nullable values
|
// aggregates of nullable values
|
||||||
@ -218,11 +220,11 @@ namespace
|
|||||||
static_assert(sqlpp::can_be_null_t<decltype(o)>::value, "");
|
static_assert(sqlpp::can_be_null_t<decltype(o)>::value, "");
|
||||||
const auto rows = db(select(count(o), avg(o), max(o), min(o), sum(o)).from(foo).unconditionally());
|
const auto rows = db(select(count(o), avg(o), max(o), min(o), sum(o)).from(foo).unconditionally());
|
||||||
auto& x = rows.front();
|
auto& x = rows.front();
|
||||||
static_assert(not sqlpp::can_be_null_t<decltype(x.count)>::value, "");
|
static_assert(not is_optional<decltype(x.count)>::value, "");
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.avg)>::value, "");
|
static_assert(is_optional<decltype(x.avg)>::value, "");
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.sum)>::value, "");
|
static_assert(is_optional<decltype(x.sum)>::value, "");
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.max)>::value, "");
|
static_assert(is_optional<decltype(x.max)>::value, "");
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(x.min)>::value, "");
|
static_assert(is_optional<decltype(x.min)>::value, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "MockDb.h"
|
#include "MockDb.h"
|
||||||
#include <sqlpp11/sqlpp11.h>
|
#include <sqlpp11/sqlpp11.h>
|
||||||
#include <sqlpp11/custom_query.h>
|
#include <sqlpp11/custom_query.h>
|
||||||
|
#include "../../include/test_helpers.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -28,6 +28,8 @@
|
|||||||
#include "MockDb.h"
|
#include "MockDb.h"
|
||||||
#include <sqlpp11/sqlpp11.h>
|
#include <sqlpp11/sqlpp11.h>
|
||||||
|
|
||||||
|
#include "../../include/test_helpers.h"
|
||||||
|
|
||||||
SQLPP_ALIAS_PROVIDER(now)
|
SQLPP_ALIAS_PROVIDER(now)
|
||||||
|
|
||||||
#if _MSC_FULL_VER >= 190023918
|
#if _MSC_FULL_VER >= 190023918
|
||||||
|
@ -27,9 +27,7 @@
|
|||||||
#include "Sample.h"
|
#include "Sample.h"
|
||||||
#include "is_regular.h"
|
#include "is_regular.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#if __cplusplus >= 201703L
|
#include <sqlpp11/compat/string_view.h>
|
||||||
#include <string_view>
|
|
||||||
#endif
|
|
||||||
#include <sqlpp11/functions.h>
|
#include <sqlpp11/functions.h>
|
||||||
#include <sqlpp11/insert.h>
|
#include <sqlpp11/insert.h>
|
||||||
#include <sqlpp11/select.h>
|
#include <sqlpp11/select.h>
|
||||||
@ -109,14 +107,11 @@ int Insert(int, char*[])
|
|||||||
prepared_insert.params.delta = sqlpp::value_or_null(17);
|
prepared_insert.params.delta = sqlpp::value_or_null(17);
|
||||||
db(prepared_insert);
|
db(prepared_insert);
|
||||||
|
|
||||||
#if __cplusplus >= 201703L
|
|
||||||
auto prepared_insert_sv = db.prepare(insert_into(t).set(t.gamma = parameter(t.gamma), t.delta = parameter(t.delta), t.beta = parameter(t.beta)));
|
auto prepared_insert_sv = db.prepare(insert_into(t).set(t.gamma = parameter(t.gamma), t.delta = parameter(t.delta), t.beta = parameter(t.beta)));
|
||||||
prepared_insert_sv.params.gamma = true;
|
prepared_insert_sv.params.gamma = true;
|
||||||
prepared_insert_sv.params.delta = 17;
|
prepared_insert_sv.params.delta = 17;
|
||||||
std::string_view sv = "string_view";
|
prepared_insert_sv.params.beta = sqlpp::string_view("string_view");;
|
||||||
prepared_insert_sv.params.beta = sv;
|
|
||||||
db(prepared_insert_sv);
|
db(prepared_insert_sv);
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
#include "Sample.h"
|
#include "Sample.h"
|
||||||
#include <sqlpp11/sqlpp11.h>
|
#include <sqlpp11/sqlpp11.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include "../../include/test_helpers.h"
|
||||||
|
|
||||||
int Interpret(int, char* [])
|
int Interpret(int, char* [])
|
||||||
{
|
{
|
||||||
@ -171,9 +171,9 @@ int Interpret(int, char* [])
|
|||||||
|
|
||||||
for (const auto& row : db(select(all_of(t)).from(t).unconditionally()))
|
for (const auto& row : db(select(all_of(t)).from(t).unconditionally()))
|
||||||
{
|
{
|
||||||
serialize(row.alpha, printer);
|
serialize(t.alpha == row.alpha.value(), printer);
|
||||||
serialize(row.beta, printer);
|
serialize(t.beta == row.beta.value(), printer);
|
||||||
serialize(row.gamma, printer);
|
serialize(t.gamma == row.gamma, printer);
|
||||||
}
|
}
|
||||||
|
|
||||||
get_sql_name(t);
|
get_sql_name(t);
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "is_regular.h"
|
#include "is_regular.h"
|
||||||
#include <sqlpp11/functions.h>
|
#include <sqlpp11/functions.h>
|
||||||
#include <sqlpp11/select.h>
|
#include <sqlpp11/select.h>
|
||||||
|
#include "../../include/test_helpers.h"
|
||||||
|
|
||||||
int Prepared(int, char* [])
|
int Prepared(int, char* [])
|
||||||
{
|
{
|
||||||
@ -132,7 +133,10 @@ int Prepared(int, char* [])
|
|||||||
// Can we prepare a query without parameters?
|
// Can we prepare a query without parameters?
|
||||||
{
|
{
|
||||||
auto ps = db.prepare(select(all_of(t)).from(t).where((t.beta.like("%"))));
|
auto ps = db.prepare(select(all_of(t)).from(t).where((t.beta.like("%"))));
|
||||||
auto res = db(ps);
|
for (const auto& row : db(ps))
|
||||||
|
{
|
||||||
|
std::cerr << row.alpha << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that a prepared select is default-constructable
|
// Check that a prepared select is default-constructable
|
||||||
|
@ -28,6 +28,9 @@
|
|||||||
#include "MockDb.h"
|
#include "MockDb.h"
|
||||||
#include <sqlpp11/sqlpp11.h>
|
#include <sqlpp11/sqlpp11.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "../../include/test_helpers.h"
|
||||||
|
|
||||||
int Result(int, char* [])
|
int Result(int, char* [])
|
||||||
{
|
{
|
||||||
MockDb db = {};
|
MockDb db = {};
|
||||||
@ -39,28 +42,24 @@ int Result(int, char* [])
|
|||||||
// Using a non-enforcing db
|
// Using a non-enforcing db
|
||||||
for (const auto& row : db(select(all_of(t), t.beta.like("")).from(t).unconditionally()))
|
for (const auto& row : db(select(all_of(t), t.beta.like("")).from(t).unconditionally()))
|
||||||
{
|
{
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null");
|
static_assert(is_optional<decltype(row.alpha)>::value, "row.alpha can be null");
|
||||||
static_assert(std::is_same<bool, decltype(row.alpha.is_null())>::value, "Yikes");
|
|
||||||
using T = sqlpp::wrap_operand_t<decltype(row.alpha)>;
|
|
||||||
static_assert(sqlpp::can_be_null_t<T>::value, "row.alpha can be null");
|
|
||||||
static_assert(sqlpp::is_result_field_t<T>::value, "result_fields are not wrapped");
|
|
||||||
|
|
||||||
for (const auto& sub : db(select(all_of(t)).from(t).where(t.alpha == row.alpha)))
|
for (const auto& sub : db(select(all_of(t)).from(t).where(t.alpha == row.alpha.value())))
|
||||||
{
|
{
|
||||||
std::cerr << sub.alpha << std::endl;
|
std::cerr << sub.alpha << std::endl;
|
||||||
}
|
}
|
||||||
db(insert_into(t).set(t.beta = row.beta, t.gamma = false));
|
db(insert_into(t).set(t.beta = row.beta.value(), t.gamma = false));
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlpp::select((t.alpha + 1).as(t.alpha)).flags(sqlpp::all).from(t);
|
sqlpp::select((t.alpha + 1).as(t.alpha)).flags(sqlpp::all).from(t);
|
||||||
for (const auto& row : db(select(all_of(t)).from(t).unconditionally()))
|
for (const auto& row : db(select(all_of(t)).from(t).unconditionally()))
|
||||||
{
|
{
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null");
|
static_assert(is_optional<decltype(row.alpha)>::value, "row.alpha can be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& row : db(select(all_of(t)).from(t).unconditionally()))
|
for (const auto& row : db(select(all_of(t)).from(t).unconditionally()))
|
||||||
{
|
{
|
||||||
static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null");
|
static_assert(is_optional<decltype(row.alpha)>::value, "row.alpha can be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlpp::select((t.alpha + 1).as(t.alpha)).flags(sqlpp::all).from(t);
|
sqlpp::select((t.alpha + 1).as(t.alpha)).flags(sqlpp::all).from(t);
|
||||||
|
@ -33,13 +33,14 @@
|
|||||||
#include <sqlpp11/functions.h>
|
#include <sqlpp11/functions.h>
|
||||||
#include <sqlpp11/select.h>
|
#include <sqlpp11/select.h>
|
||||||
#include <sqlpp11/without_table_check.h>
|
#include <sqlpp11/without_table_check.h>
|
||||||
|
#include "../../include/test_helpers.h"
|
||||||
|
|
||||||
template <typename Db, typename Column>
|
template <typename Db, typename Column>
|
||||||
int64_t getColumn(Db&& db, const Column& column)
|
int64_t getColumn(Db&& db, const Column& column)
|
||||||
{
|
{
|
||||||
auto result = db(select(column.as(sqlpp::alias::a)).from(column.table()).unconditionally());
|
auto result = db(select(column.as(sqlpp::alias::a)).from(column.table()).unconditionally());
|
||||||
if (not result.empty())
|
if (not result.empty() and result.front().a.has_value())
|
||||||
return result.front().a;
|
return result.front().a.value();
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -49,15 +50,15 @@ struct to_cerr
|
|||||||
template <typename Field>
|
template <typename Field>
|
||||||
auto operator()(const Field& field) const -> void
|
auto operator()(const Field& field) const -> void
|
||||||
{
|
{
|
||||||
std::cerr << get_sql_name(field) << " = " << field << std::endl;
|
std::cerr << field << std::endl;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Row>
|
template <typename Row>
|
||||||
void print_row(Row const& row)
|
void print_row(Row const& row)
|
||||||
{
|
{
|
||||||
int64_t a = row.alpha;
|
const sqlpp::optional<int64_t> a = row.alpha;
|
||||||
const std::string b = row.beta;
|
const sqlpp::optional<sqlpp::string_view> b = row.beta;
|
||||||
std::cout << a << ", " << b << std::endl;
|
std::cout << a << ", " << b << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,16 +91,16 @@ int Select(int, char*[])
|
|||||||
|
|
||||||
for (const auto& row : db(select(all_of(t)).from(t).unconditionally()))
|
for (const auto& row : db(select(all_of(t)).from(t).unconditionally()))
|
||||||
{
|
{
|
||||||
int64_t a = row.alpha;
|
const sqlpp::optional<int64_t> a = row.alpha;
|
||||||
const std::string b = row.beta;
|
const sqlpp::optional<sqlpp::string_view> b = row.beta;
|
||||||
std::cout << a << ", " << b << std::endl;
|
std::cout << a << ", " << b << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& row :
|
for (const auto& row :
|
||||||
db(select(all_of(t), t.gamma.as(t)).from(t).where(t.alpha > 7 and trim(t.beta) == "test").for_update()))
|
db(select(all_of(t), t.gamma.as(t)).from(t).where(t.alpha > 7 and trim(t.beta) == "test").for_update()))
|
||||||
{
|
{
|
||||||
int64_t a = row.alpha;
|
const sqlpp::optional<int64_t> a = row.alpha;
|
||||||
const std::string b = row.beta;
|
const sqlpp::optional<sqlpp::string_view> b = row.beta;
|
||||||
const bool g = row.tabBar;
|
const bool g = row.tabBar;
|
||||||
std::cout << a << ", " << b << ", " << g << std::endl;
|
std::cout << a << ", " << b << ", " << g << std::endl;
|
||||||
}
|
}
|
||||||
@ -177,7 +178,7 @@ int Select(int, char*[])
|
|||||||
s.order_by.add(t.delta.order(sqlpp::sort_type::desc));
|
s.order_by.add(t.delta.order(sqlpp::sort_type::desc));
|
||||||
for (const auto& row : db(db.prepare(s)))
|
for (const auto& row : db(db.prepare(s)))
|
||||||
{
|
{
|
||||||
int64_t a = row.alpha;
|
const sqlpp::optional<int64_t> a = row.alpha;
|
||||||
std::cout << a << std::endl;
|
std::cout << a << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,7 +188,7 @@ int Select(int, char*[])
|
|||||||
select(sqlpp::value(7).as(t.alpha));
|
select(sqlpp::value(7).as(t.alpha));
|
||||||
|
|
||||||
for (const auto& row :
|
for (const auto& row :
|
||||||
db(select(sqlpp::case_when(true).then(sqlpp::null).else_(sqlpp::null).as(t.beta)).from(t).unconditionally()))
|
db(select(sqlpp::case_when(true).then(t.beta).else_(sqlpp::null).as(t.beta)).from(t).unconditionally()))
|
||||||
{
|
{
|
||||||
std::cerr << row.beta << std::endl;
|
std::cerr << row.beta << std::endl;
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include <sqlpp11/functions.h>
|
#include <sqlpp11/functions.h>
|
||||||
#include <sqlpp11/select.h>
|
#include <sqlpp11/select.h>
|
||||||
#include <sqlpp11/without_table_check.h>
|
#include <sqlpp11/without_table_check.h>
|
||||||
|
#include "../../include/test_helpers.h"
|
||||||
|
|
||||||
namespace alias
|
namespace alias
|
||||||
{
|
{
|
||||||
@ -345,7 +346,7 @@ int SelectType(int, char*[])
|
|||||||
|
|
||||||
for (const auto& row : db(select(all_of(t)).from(t).unconditionally()))
|
for (const auto& row : db(select(all_of(t)).from(t).unconditionally()))
|
||||||
{
|
{
|
||||||
int64_t a = row.alpha;
|
const auto a = row.alpha;
|
||||||
std::cout << a << std::endl;
|
std::cout << a << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include <sqlpp11/select.h>
|
#include <sqlpp11/select.h>
|
||||||
#include <sqlpp11/alias_provider.h>
|
#include <sqlpp11/alias_provider.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include "../../include/test_helpers.h"
|
||||||
|
|
||||||
int With(int, char*[])
|
int With(int, char*[])
|
||||||
{
|
{
|
||||||
|
104
tests/include/test_helpers.h
Normal file
104
tests/include/test_helpers.h
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <sqlpp11/sqlpp11.h>
|
||||||
|
|
||||||
|
template <typename Clock, typename Period>
|
||||||
|
std::ostream& operator<<(std::ostream& os, const std::chrono::time_point<Clock, Period>& t)
|
||||||
|
{
|
||||||
|
const auto dp = ::sqlpp::chrono::floor<::date::days>(t);
|
||||||
|
const auto ymd = ::date::year_month_day{dp};
|
||||||
|
const auto time = ::date::make_time(t - dp);
|
||||||
|
os << "TIMESTAMP '" << ymd << ' ' << time << "'";
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Rep, typename Period>
|
||||||
|
std::ostream& operator<<(std::ostream& os, const std::chrono::duration<Rep, Period>& t)
|
||||||
|
{
|
||||||
|
return os << '\'' << ::date::make_time(t) << '\'';
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::ostream& operator<<(std::ostream& os, const sqlpp::optional<T>& t)
|
||||||
|
{
|
||||||
|
if (not t)
|
||||||
|
return os << "NULL";
|
||||||
|
return os << t.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::ostream& operator<<(std::ostream& stream, const sqlpp::isolation_level& level)
|
||||||
|
{
|
||||||
|
switch (level)
|
||||||
|
{
|
||||||
|
case sqlpp::isolation_level::serializable:
|
||||||
|
{
|
||||||
|
stream << "SERIALIZABLE";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case sqlpp::isolation_level::repeatable_read:
|
||||||
|
{
|
||||||
|
stream << "REPEATABLE READ";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case sqlpp::isolation_level::read_committed:
|
||||||
|
{
|
||||||
|
stream << "READ COMMITTED";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case sqlpp::isolation_level::read_uncommitted:
|
||||||
|
{
|
||||||
|
stream << "READ UNCOMMITTED";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case sqlpp::isolation_level::undefined:
|
||||||
|
{
|
||||||
|
stream << "BEGIN";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename L, typename R>
|
||||||
|
auto require_equal(int line, const L& l, const R& r) -> void
|
||||||
|
{
|
||||||
|
if (l != r)
|
||||||
|
{
|
||||||
|
std::cerr << line << ": " << l << " != " << r << std::endl;
|
||||||
|
throw std::runtime_error("Unexpected result");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_optional : public std::false_type{};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_optional<sqlpp::optional<T>> : public std::true_type{};
|
||||||
|
|
@ -28,6 +28,8 @@
|
|||||||
#include <sqlpp11/mysql/mysql.h>
|
#include <sqlpp11/mysql/mysql.h>
|
||||||
#include <sqlpp11/sqlpp11.h>
|
#include <sqlpp11/sqlpp11.h>
|
||||||
|
|
||||||
|
#include "../../include/test_helpers.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -36,20 +38,6 @@ const auto library_raii = sqlpp::mysql::scoped_library_initializer_t{};
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
template <typename L, typename R>
|
|
||||||
auto require_equal(int line, const L& l, const R& r) -> void
|
|
||||||
{
|
|
||||||
if (l != r)
|
|
||||||
{
|
|
||||||
std::cerr << line << ": ";
|
|
||||||
serialize(::sqlpp::wrap_operand_t<L>{l}, std::cerr);
|
|
||||||
std::cerr << " != ";
|
|
||||||
serialize(::sqlpp::wrap_operand_t<R>{r}, std::cerr);
|
|
||||||
std::cerr << "\n" ;
|
|
||||||
throw std::runtime_error("Unexpected result");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename L, typename R>
|
template <typename L, typename R>
|
||||||
auto require_close(int line, const L& l, const R& r) -> void
|
auto require_close(int line, const L& l, const R& r) -> void
|
||||||
{
|
{
|
||||||
@ -90,13 +78,10 @@ int DateTime(int, char*[])
|
|||||||
db(insert_into(tab).default_values());
|
db(insert_into(tab).default_values());
|
||||||
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
||||||
{
|
{
|
||||||
require_equal(__LINE__, row.colDayPoint.is_null(), true);
|
require_equal(__LINE__, row.colDayPoint.has_value(), false);
|
||||||
require_equal(__LINE__, row.colDayPoint.value(), ::sqlpp::chrono::day_point{});
|
require_equal(__LINE__, row.colTimePoint.has_value(), false);
|
||||||
require_equal(__LINE__, row.colTimePoint.is_null(), true);
|
require_close(__LINE__, row.colDateTimePoint, now);
|
||||||
require_equal(__LINE__, row.colTimePoint.value(), ::sqlpp::chrono::microsecond_point{});
|
require_equal(__LINE__, row.colTimeOfDay.has_value(), false);
|
||||||
require_close(__LINE__, row.colDateTimePoint.value(), now);
|
|
||||||
require_equal(__LINE__, row.colTimeOfDay.is_null(), true);
|
|
||||||
require_equal(__LINE__, row.colTimeOfDay.value(), ::std::chrono::microseconds{});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
db(update(tab).set(tab.colDayPoint = today, tab.colTimePoint = now, tab.colTimeOfDay = current).unconditionally());
|
db(update(tab).set(tab.colDayPoint = today, tab.colTimePoint = now, tab.colTimeOfDay = current).unconditionally());
|
||||||
@ -111,8 +96,7 @@ int DateTime(int, char*[])
|
|||||||
auto statement = db.prepare(select(all_of(tab)).from(tab).unconditionally());
|
auto statement = db.prepare(select(all_of(tab)).from(tab).unconditionally());
|
||||||
for (const auto& row : db(statement))
|
for (const auto& row : db(statement))
|
||||||
{
|
{
|
||||||
require_equal(__LINE__, row.colDateTimePoint.is_null(), false);
|
require_close(__LINE__, row.colDateTimePoint, now);
|
||||||
require_close(__LINE__, row.colDateTimePoint.value(), now);
|
|
||||||
require_equal(__LINE__, row.colDayPoint.value(), today);
|
require_equal(__LINE__, row.colDayPoint.value(), today);
|
||||||
require_equal(__LINE__, row.colTimePoint.value(), now);
|
require_equal(__LINE__, row.colTimePoint.value(), now);
|
||||||
require_close(__LINE__, row.colTimeOfDay.value(), current);
|
require_close(__LINE__, row.colTimeOfDay.value(), current);
|
||||||
|
@ -48,9 +48,9 @@ int DynamicSelect(int, char*[])
|
|||||||
auto db = sql::make_test_connection();
|
auto db = sql::make_test_connection();
|
||||||
db.execute(R"(DROP TABLE IF EXISTS tab_sample)");
|
db.execute(R"(DROP TABLE IF EXISTS tab_sample)");
|
||||||
db.execute(R"(CREATE TABLE tab_sample (
|
db.execute(R"(CREATE TABLE tab_sample (
|
||||||
alpha bigint(20) DEFAULT NULL,
|
alpha bigint(20) AUTO_INCREMENT NOT NULL PRIMARY KEY,
|
||||||
beta varchar(255) DEFAULT NULL,
|
beta varchar(255) DEFAULT NULL,
|
||||||
gamma bool DEFAULT NULL
|
gamma bool NOT NULL DEFAULT 0
|
||||||
))");
|
))");
|
||||||
|
|
||||||
const auto tab = TabSample{};
|
const auto tab = TabSample{};
|
||||||
|
@ -78,10 +78,10 @@ int Json(int, char*[])
|
|||||||
if (result.empty())
|
if (result.empty())
|
||||||
throw std::runtime_error{"selection result is empty"};
|
throw std::runtime_error{"selection result is empty"};
|
||||||
|
|
||||||
const std::string value = result.front().value;
|
const sqlpp::optional<sqlpp::string_view> value = result.front().value;
|
||||||
|
|
||||||
if (value != "value")
|
if (value != "value")
|
||||||
throw std::runtime_error{std::string{"unexpected value: "} + value};
|
throw std::runtime_error{std::string{"unexpected value: "} + std::string(value ? value.value() : "NULL")};
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
|
@ -50,9 +50,9 @@ int MoveConstructor(int, char*[])
|
|||||||
|
|
||||||
connections.at(0).execute(R"(DROP TABLE IF EXISTS tab_sample)");
|
connections.at(0).execute(R"(DROP TABLE IF EXISTS tab_sample)");
|
||||||
connections.at(0).execute(R"(CREATE TABLE tab_sample (
|
connections.at(0).execute(R"(CREATE TABLE tab_sample (
|
||||||
alpha bigint(20) DEFAULT NULL,
|
alpha bigint(20) AUTO_INCREMENT NOT NULL PRIMARY KEY,
|
||||||
beta varchar(255) DEFAULT NULL,
|
beta varchar(255) DEFAULT NULL,
|
||||||
gamma bool DEFAULT NULL
|
gamma bool NOT NULL DEFAULT 0
|
||||||
))");
|
))");
|
||||||
|
|
||||||
assert(connections.at(0).is_transaction_active() == false);
|
assert(connections.at(0).is_transaction_active() == false);
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "TabSample.h"
|
#include "TabSample.h"
|
||||||
#include <sqlpp11/mysql/mysql.h>
|
#include <sqlpp11/mysql/mysql.h>
|
||||||
#include <sqlpp11/sqlpp11.h>
|
#include <sqlpp11/sqlpp11.h>
|
||||||
|
#include "../../include/test_helpers.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -82,9 +83,9 @@ int Sample(int, char*[])
|
|||||||
const auto y = db.prepare(x);
|
const auto y = db.prepare(x);
|
||||||
for (const auto& row : db(db.prepare(select(all_of(tab)).from(tab).unconditionally())))
|
for (const auto& row : db(db.prepare(select(all_of(tab)).from(tab).unconditionally())))
|
||||||
{
|
{
|
||||||
std::cerr << "alpha: " << row.alpha.is_null() << std::endl;
|
std::cerr << "alpha: " << row.alpha << std::endl;
|
||||||
std::cerr << "beta: " << row.beta.is_null() << std::endl;
|
std::cerr << "beta: " << row.beta << std::endl;
|
||||||
std::cerr << "gamma: " << row.gamma.is_null() << std::endl;
|
std::cerr << "gamma: " << row.gamma << std::endl;
|
||||||
}
|
}
|
||||||
db(insert_into(tab).set(tab.beta = "kaesekuchen", tab.gamma = true));
|
db(insert_into(tab).set(tab.beta = "kaesekuchen", tab.gamma = true));
|
||||||
db(insert_into(tab).default_values());
|
db(insert_into(tab).default_values());
|
||||||
@ -122,8 +123,8 @@ int Sample(int, char*[])
|
|||||||
auto result = db(select(all_of(tab), select(max(tab.alpha)).from(tab)).from(tab).unconditionally());
|
auto result = db(select(all_of(tab), select(max(tab.alpha)).from(tab)).from(tab).unconditionally());
|
||||||
if (const auto& row = *result.begin())
|
if (const auto& row = *result.begin())
|
||||||
{
|
{
|
||||||
long a = row.alpha;
|
const int64_t a = row.alpha;
|
||||||
long m = row.max;
|
const sqlpp::optional<long> m = row.max;
|
||||||
std::cerr << __LINE__ << " row.alpha: " << a << ", row.max: " << m << std::endl;
|
std::cerr << __LINE__ << " row.alpha: " << a << ", row.max: " << m << std::endl;
|
||||||
}
|
}
|
||||||
tx.commit();
|
tx.commit();
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include <sqlpp11/select.h>
|
#include <sqlpp11/select.h>
|
||||||
#include <sqlpp11/transaction.h>
|
#include <sqlpp11/transaction.h>
|
||||||
#include <sqlpp11/update.h>
|
#include <sqlpp11/update.h>
|
||||||
|
#include "../../include/test_helpers.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -91,7 +92,7 @@ int Select(int, char*[])
|
|||||||
db.execute(R"(CREATE TABLE tab_sample (
|
db.execute(R"(CREATE TABLE tab_sample (
|
||||||
alpha bigint(20) AUTO_INCREMENT,
|
alpha bigint(20) AUTO_INCREMENT,
|
||||||
beta varchar(255) DEFAULT NULL,
|
beta varchar(255) DEFAULT NULL,
|
||||||
gamma bool DEFAULT NULL,
|
gamma bool NOT NULL DEFAULT 0,
|
||||||
PRIMARY KEY (alpha)
|
PRIMARY KEY (alpha)
|
||||||
))");
|
))");
|
||||||
db.execute(R"(DROP TABLE IF EXISTS tab_foo)");
|
db.execute(R"(DROP TABLE IF EXISTS tab_foo)");
|
||||||
@ -153,8 +154,8 @@ int Select(int, char*[])
|
|||||||
auto result = db(select(all_of(tab), select(max(tab.alpha)).from(tab)).from(tab).unconditionally());
|
auto result = db(select(all_of(tab), select(max(tab.alpha)).from(tab)).from(tab).unconditionally());
|
||||||
if (const auto& row = *result.begin())
|
if (const auto& row = *result.begin())
|
||||||
{
|
{
|
||||||
long a = row.alpha;
|
sqlpp::optional<long> a = row.alpha;
|
||||||
long m = row.max;
|
sqlpp::optional<long> m = row.max;
|
||||||
std::cerr << "-----------------------------" << a << ", " << m << std::endl;
|
std::cerr << "-----------------------------" << a << ", " << m << std::endl;
|
||||||
}
|
}
|
||||||
tx.commit();
|
tx.commit();
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include <sqlpp11/select.h>
|
#include <sqlpp11/select.h>
|
||||||
#include <sqlpp11/transaction.h>
|
#include <sqlpp11/transaction.h>
|
||||||
#include <sqlpp11/update.h>
|
#include <sqlpp11/update.h>
|
||||||
|
#include "../../include/test_helpers.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -51,14 +52,13 @@ int Truncated(int, char*[])
|
|||||||
auto db = sql::make_test_connection();
|
auto db = sql::make_test_connection();
|
||||||
db.execute(R"(DROP TABLE IF EXISTS tab_sample)");
|
db.execute(R"(DROP TABLE IF EXISTS tab_sample)");
|
||||||
db.execute(R"(CREATE TABLE tab_sample (
|
db.execute(R"(CREATE TABLE tab_sample (
|
||||||
alpha bigint(20) AUTO_INCREMENT,
|
alpha bigint(20) AUTO_INCREMENT NOT NULL PRIMARY KEY,
|
||||||
beta varchar(255) DEFAULT NULL,
|
beta varchar(255) DEFAULT NULL,
|
||||||
gamma bool DEFAULT NULL,
|
gamma bool NOT NULL DEFAULT 0
|
||||||
PRIMARY KEY (alpha)
|
|
||||||
))");
|
))");
|
||||||
db.execute(R"(DROP TABLE IF EXISTS tab_foo)");
|
db.execute(R"(DROP TABLE IF EXISTS tab_foo)");
|
||||||
db.execute(R"(CREATE TABLE tab_foo (
|
db.execute(R"(CREATE TABLE tab_foo (
|
||||||
omega bigint(20) DEFAULT NULL
|
omega bigint(20) NOT NULL
|
||||||
))");
|
))");
|
||||||
|
|
||||||
db(insert_into(tab).set(tab.gamma = true, tab.beta = "cheese"));
|
db(insert_into(tab).set(tab.gamma = true, tab.beta = "cheese"));
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "TabSample.h"
|
#include "TabSample.h"
|
||||||
#include <sqlpp11/mysql/connection.h>
|
#include <sqlpp11/mysql/connection.h>
|
||||||
#include <sqlpp11/sqlpp11.h>
|
#include <sqlpp11/sqlpp11.h>
|
||||||
|
#include "../../include/test_helpers.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
@ -41,37 +41,32 @@ const auto blob = model::BlobSample{};
|
|||||||
constexpr size_t blob_size = 1000 * 1000ul;
|
constexpr size_t blob_size = 1000 * 1000ul;
|
||||||
constexpr size_t blob_small_size = 999;
|
constexpr size_t blob_small_size = 999;
|
||||||
|
|
||||||
void verify_blob(sql::connection& db, const std::vector<uint8_t>& data, uint64_t id)
|
void verify_blob(sql::connection& db, const std::vector<uint8_t>& expected, uint64_t id)
|
||||||
{
|
{
|
||||||
auto result = db(select(blob.data).from(blob).where(blob.id == id));
|
auto result = db(select(blob.data).from(blob).where(blob.id == id));
|
||||||
const auto& result_row = result.front();
|
const auto& result_row = result.front();
|
||||||
std::cerr << "id: " << id << std::endl;
|
if (!result_row.data)
|
||||||
std::cerr << "Insert size: " << data.size() << std::endl;
|
throw std::runtime_error("blob data is unpexpectedly NULL for id " + std::to_string(id));
|
||||||
std::cerr << "Select size: " << result_row.data.len << std::endl;
|
const auto received = *result_row.data;
|
||||||
if (data.size() != result_row.data.len)
|
|
||||||
|
if (expected.size() != received.size())
|
||||||
{
|
{
|
||||||
std::cerr << "Size mismatch" << std::endl;
|
std::cerr << "Size mismatch" << std::endl;
|
||||||
|
|
||||||
throw std::runtime_error("Size mismatch " + std::to_string(data.size()) +
|
throw std::runtime_error("Size mismatch " + std::to_string(expected.size()) +
|
||||||
" != " + std::to_string(result_row.data.len));
|
" != " + std::to_string(received.size()));
|
||||||
}
|
}
|
||||||
std::cerr << "Verifying content" << std::endl;
|
std::cerr << "Verifying content" << std::endl;
|
||||||
const auto result_blob = result_row.data.value();
|
for (size_t i = 0; i < expected.size(); i++)
|
||||||
if (data != result_blob)
|
|
||||||
{
|
{
|
||||||
std::cout << "Content mismatch ([row] original -> received)" << std::endl;
|
if (expected[i] != received[i])
|
||||||
|
|
||||||
for (size_t i = 0; i < data.size(); i++)
|
|
||||||
{
|
{
|
||||||
if (data[i] != result_row.data.value()[i])
|
std::cerr << "expected[" << i << "] " << static_cast<int>(expected[i]) << " != received " << static_cast<int>(received[i])
|
||||||
{
|
|
||||||
std::cerr << "[" << i << "] " << static_cast<int>(data.at(i)) << " -> " << static_cast<int>(result_blob.at(i))
|
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
|
||||||
}
|
|
||||||
throw std::runtime_error("Content mismatch");
|
throw std::runtime_error("Content mismatch");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int Blob(int, char*[])
|
int Blob(int, char*[])
|
||||||
{
|
{
|
||||||
@ -108,12 +103,10 @@ int Blob(int, char*[])
|
|||||||
{
|
{
|
||||||
auto result = db(select(blob.data).from(blob).where(blob.id == null_id));
|
auto result = db(select(blob.data).from(blob).where(blob.id == null_id));
|
||||||
const auto& result_row = result.front();
|
const auto& result_row = result.front();
|
||||||
std::cerr << "Null blob is_null:\t" << std::boolalpha << result_row.data.is_null() << std::endl;
|
std::cerr << "Null blob is_null:\t" << std::boolalpha << (result_row.data == sqlpp::nullopt) << std::endl;
|
||||||
std::cerr << "Null blob len == 0:\t" << std::boolalpha << (result_row.data.len == 0) << std::endl;
|
if (result_row.data.has_value())
|
||||||
std::cerr << "Null blob blob == nullptr:\t" << std::boolalpha << (result_row.data.is_null()) << std::endl;
|
|
||||||
if (!result_row.data.is_null() || result_row.data.len != 0)
|
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Null blob has incorrect values");
|
throw std::runtime_error("Expected NULL blob has value");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,10 +93,8 @@ int Date(int, char*[])
|
|||||||
db(insert_into(tab).default_values());
|
db(insert_into(tab).default_values());
|
||||||
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
||||||
{
|
{
|
||||||
require_equal(__LINE__, row.colDayPoint.is_null(), true);
|
require_equal(__LINE__, row.colDayPoint.has_value(), false);
|
||||||
require_equal(__LINE__, row.colDayPoint.value(), ::sqlpp::chrono::day_point{});
|
require_equal(__LINE__, row.colTimePoint.has_value(), false);
|
||||||
require_equal(__LINE__, row.colTimePoint.is_null(), true);
|
|
||||||
require_equal(__LINE__, row.colTimePoint.value(), ::sqlpp::chrono::microsecond_point{});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
db(update(tab).set(tab.colDayPoint = today, tab.colTimePoint = now).unconditionally());
|
db(update(tab).set(tab.colDayPoint = today, tab.colTimePoint = now).unconditionally());
|
||||||
|
@ -75,12 +75,9 @@ int DateTime(int, char*[])
|
|||||||
db(insert_into(tab).default_values());
|
db(insert_into(tab).default_values());
|
||||||
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
||||||
{
|
{
|
||||||
require_equal(__LINE__, row.c_day.is_null(), true);
|
require_equal(__LINE__, row.c_day.has_value(), false);
|
||||||
require_equal(__LINE__, row.c_day.value(), ::sqlpp::chrono::day_point{});
|
require_equal(__LINE__, row.c_time.has_value(), false);
|
||||||
require_equal(__LINE__, row.c_time.is_null(), true);
|
require_equal(__LINE__, row.c_timepoint.has_value(), false);
|
||||||
require_equal(__LINE__, row.c_time.value(), ::std::chrono::microseconds{});
|
|
||||||
require_equal(__LINE__, row.c_timepoint.is_null(), true);
|
|
||||||
require_equal(__LINE__, row.c_timepoint.value(), ::sqlpp::chrono::microsecond_point{});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
db(update(tab).set(tab.c_day = today, tab.c_time = current, tab.c_timepoint = now).unconditionally());
|
db(update(tab).set(tab.c_day = today, tab.c_time = current, tab.c_timepoint = now).unconditionally());
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "TabBar.h"
|
#include "TabBar.h"
|
||||||
#include "TabFoo.h"
|
#include "TabFoo.h"
|
||||||
#include "make_test_connection.h"
|
#include "make_test_connection.h"
|
||||||
|
#include "../../include/test_helpers.h"
|
||||||
|
|
||||||
namespace sql = sqlpp::postgresql;
|
namespace sql = sqlpp::postgresql;
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <sqlpp11/postgresql/postgresql.h>
|
#include <sqlpp11/postgresql/postgresql.h>
|
||||||
#include <sqlpp11/sqlpp11.h>
|
#include <sqlpp11/sqlpp11.h>
|
||||||
|
#include "../../include/test_helpers.h"
|
||||||
|
|
||||||
#include "TabFoo.h"
|
#include "TabFoo.h"
|
||||||
#include "make_test_connection.h"
|
#include "make_test_connection.h"
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
#include "TabFoo.h"
|
#include "TabFoo.h"
|
||||||
#include "make_test_connection.h"
|
#include "make_test_connection.h"
|
||||||
|
#include "../../include/test_helpers.h"
|
||||||
|
|
||||||
namespace sql = sqlpp::postgresql;
|
namespace sql = sqlpp::postgresql;
|
||||||
model::TabFoo tab = {};
|
model::TabFoo tab = {};
|
||||||
@ -69,7 +70,7 @@ int Select(int, char*[])
|
|||||||
db.execute(R"(DROP TABLE IF EXISTS tabfoo;)");
|
db.execute(R"(DROP TABLE IF EXISTS tabfoo;)");
|
||||||
db.execute(R"(CREATE TABLE tabfoo
|
db.execute(R"(CREATE TABLE tabfoo
|
||||||
(
|
(
|
||||||
alpha bigserial NOT NULL,
|
alpha bigserial,
|
||||||
beta smallint,
|
beta smallint,
|
||||||
gamma text,
|
gamma text,
|
||||||
c_bool boolean,
|
c_bool boolean,
|
||||||
@ -112,8 +113,8 @@ int Select(int, char*[])
|
|||||||
db(insert_into(tab).set(tab.c_bool = false, tab.gamma = "asdfg"));
|
db(insert_into(tab).set(tab.c_bool = false, tab.gamma = "asdfg"));
|
||||||
|
|
||||||
assert(db(select(tab.c_bool).from(tab).where(tab.gamma == "asdf")).front().c_bool);
|
assert(db(select(tab.c_bool).from(tab).where(tab.gamma == "asdf")).front().c_bool);
|
||||||
assert(not db(select(tab.c_bool).from(tab).where(tab.gamma == "asdfg")).front().c_bool);
|
assert(not db(select(tab.c_bool).from(tab).where(tab.gamma == "asdfg")).front().c_bool.value());
|
||||||
assert(not db(select(tab.c_bool).from(tab).where(tab.alpha == 1)).front().c_bool);
|
assert(not db(select(tab.c_bool).from(tab).where(tab.alpha == 1)).front().c_bool.has_value());
|
||||||
|
|
||||||
// test
|
// test
|
||||||
|
|
||||||
|
@ -32,56 +32,10 @@
|
|||||||
#include <sqlpp11/postgresql/connection.h>
|
#include <sqlpp11/postgresql/connection.h>
|
||||||
#include <sqlpp11/sqlpp11.h>
|
#include <sqlpp11/sqlpp11.h>
|
||||||
#include <sqlpp11/transaction.h>
|
#include <sqlpp11/transaction.h>
|
||||||
|
#include "../../include/test_helpers.h"
|
||||||
|
|
||||||
#include "make_test_connection.h"
|
#include "make_test_connection.h"
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
std::ostream& operator<<(std::ostream& stream, const sqlpp::isolation_level& level)
|
|
||||||
{
|
|
||||||
switch (level)
|
|
||||||
{
|
|
||||||
case sqlpp::isolation_level::serializable:
|
|
||||||
{
|
|
||||||
stream << "SERIALIZABLE";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case sqlpp::isolation_level::repeatable_read:
|
|
||||||
{
|
|
||||||
stream << "REPEATABLE READ";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case sqlpp::isolation_level::read_committed:
|
|
||||||
{
|
|
||||||
stream << "READ COMMITTED";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case sqlpp::isolation_level::read_uncommitted:
|
|
||||||
{
|
|
||||||
stream << "READ UNCOMMITTED";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case sqlpp::isolation_level::undefined:
|
|
||||||
{
|
|
||||||
stream << "BEGIN";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename L, typename R>
|
|
||||||
void require_equal(int line, const L& l, const R& r)
|
|
||||||
{
|
|
||||||
if (l != r)
|
|
||||||
{
|
|
||||||
std::cerr << line << ": " << l << " != " << r << std::endl;
|
|
||||||
throw std::runtime_error("Unexpected result");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace sql = sqlpp::postgresql;
|
namespace sql = sqlpp::postgresql;
|
||||||
|
|
||||||
SQLPP_ALIAS_PROVIDER(level);
|
SQLPP_ALIAS_PROVIDER(level);
|
||||||
@ -95,10 +49,10 @@ int Transaction(int, char*[])
|
|||||||
|
|
||||||
{
|
{
|
||||||
require_equal(__LINE__, db.is_transaction_active(), false);
|
require_equal(__LINE__, db.is_transaction_active(), false);
|
||||||
auto current_level = db(custom_query(sqlpp::verbatim("show transaction_isolation;"))
|
auto current_level = std::string(db(custom_query(sqlpp::verbatim("show transaction_isolation;"))
|
||||||
.with_result_type_of(select(sqlpp::value("").as(level))))
|
.with_result_type_of(select(sqlpp::value("").as(level))))
|
||||||
.front()
|
.front()
|
||||||
.level;
|
.level);
|
||||||
require_equal(__LINE__, current_level, "read committed");
|
require_equal(__LINE__, current_level, "read committed");
|
||||||
std::cerr << "isolation level outside transaction: " << current_level << "\n";
|
std::cerr << "isolation level outside transaction: " << current_level << "\n";
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ namespace
|
|||||||
{
|
{
|
||||||
// prepare test with timezone
|
// prepare test with timezone
|
||||||
db.execute("DROP TABLE IF EXISTS tab_sample");
|
db.execute("DROP TABLE IF EXISTS tab_sample");
|
||||||
db.execute("CREATE TABLE tab_sample (alpha bigint, beta text, gamma bool)");
|
db.execute("CREATE TABLE tab_sample (alpha bigint, beta text, gamma bool NOT NULL DEFAULT 'f')");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,24 +69,20 @@ int Type(int, char*[])
|
|||||||
db(insert_into(tab).default_values());
|
db(insert_into(tab).default_values());
|
||||||
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
||||||
{
|
{
|
||||||
require_equal(__LINE__, row.alpha.is_null(), true);
|
require_equal(__LINE__, row.alpha.has_value(), false);
|
||||||
require_equal(__LINE__, row.alpha.value(), 0);
|
require_equal(__LINE__, row.beta.has_value(), false);
|
||||||
require_equal(__LINE__, row.beta.is_null(), true);
|
require_equal(__LINE__, row.gamma, false);
|
||||||
require_equal(__LINE__, row.beta.value(), "");
|
|
||||||
require_equal(__LINE__, row.gamma.is_null(), true);
|
|
||||||
require_equal(__LINE__, row.gamma.value(), false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
db(update(tab).set(tab.alpha = 10, tab.beta = "Cookies!", tab.gamma = true).unconditionally());
|
db(update(tab).set(tab.alpha = 10, tab.beta = "Cookies!", tab.gamma = true).unconditionally());
|
||||||
|
|
||||||
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
||||||
{
|
{
|
||||||
require_equal(__LINE__, row.alpha.is_null(), false);
|
require_equal(__LINE__, row.alpha.has_value(), true);
|
||||||
require_equal(__LINE__, row.alpha.value(), 10);
|
require_equal(__LINE__, row.alpha.value(), 10);
|
||||||
require_equal(__LINE__, row.beta.is_null(), false);
|
require_equal(__LINE__, row.beta.has_value(), true);
|
||||||
require_equal(__LINE__, row.beta.value(), "Cookies!");
|
require_equal(__LINE__, row.beta.value(), "Cookies!");
|
||||||
require_equal(__LINE__, row.gamma.is_null(), false);
|
require_equal(__LINE__, row.gamma, true);
|
||||||
require_equal(__LINE__, row.gamma.value(), true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
db(update(tab).set(tab.alpha = 20, tab.beta = "Monster", tab.gamma = false).unconditionally());
|
db(update(tab).set(tab.alpha = 20, tab.beta = "Monster", tab.gamma = false).unconditionally());
|
||||||
@ -95,7 +91,7 @@ int Type(int, char*[])
|
|||||||
{
|
{
|
||||||
require_equal(__LINE__, row.alpha.value(), 20);
|
require_equal(__LINE__, row.alpha.value(), 20);
|
||||||
require_equal(__LINE__, row.beta.value(), "Monster");
|
require_equal(__LINE__, row.beta.value(), "Monster");
|
||||||
require_equal(__LINE__, row.gamma.value(), false);
|
require_equal(__LINE__, row.gamma, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto prepared_update = db.prepare(
|
auto prepared_update = db.prepare(
|
||||||
@ -113,7 +109,7 @@ int Type(int, char*[])
|
|||||||
{
|
{
|
||||||
require_equal(__LINE__, row.alpha.value(), 30);
|
require_equal(__LINE__, row.alpha.value(), 30);
|
||||||
require_equal(__LINE__, row.beta.value(), "IceCream");
|
require_equal(__LINE__, row.beta.value(), "IceCream");
|
||||||
require_equal(__LINE__, row.gamma.value(), true);
|
require_equal(__LINE__, row.gamma, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (std::exception& e)
|
catch (std::exception& e)
|
||||||
|
@ -50,7 +50,7 @@ int Attach(int, char*[])
|
|||||||
db.execute(R"(CREATE TABLE tab_sample (
|
db.execute(R"(CREATE TABLE tab_sample (
|
||||||
alpha INTEGER PRIMARY KEY,
|
alpha INTEGER PRIMARY KEY,
|
||||||
beta varchar(255) DEFAULT NULL,
|
beta varchar(255) DEFAULT NULL,
|
||||||
gamma bool DEFAULT NULL
|
gamma bool
|
||||||
))");
|
))");
|
||||||
|
|
||||||
// Attaching another in-memory database and creating the same table in it
|
// Attaching another in-memory database and creating the same table in it
|
||||||
@ -58,7 +58,7 @@ int Attach(int, char*[])
|
|||||||
db.execute(R"(CREATE TABLE other.tab_sample (
|
db.execute(R"(CREATE TABLE other.tab_sample (
|
||||||
alpha INTEGER PRIMARY KEY,
|
alpha INTEGER PRIMARY KEY,
|
||||||
beta varchar(255) DEFAULT NULL,
|
beta varchar(255) DEFAULT NULL,
|
||||||
gamma bool DEFAULT NULL
|
gamma bool
|
||||||
))");
|
))");
|
||||||
|
|
||||||
auto left = TabSample{};
|
auto left = TabSample{};
|
||||||
|
@ -60,7 +60,8 @@ int AutoIncrement(int, char*[])
|
|||||||
std::set<int64_t> results;
|
std::set<int64_t> results;
|
||||||
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
||||||
{
|
{
|
||||||
results.insert(row.alpha);
|
if (row.alpha)
|
||||||
|
results.insert(row.alpha.value());
|
||||||
};
|
};
|
||||||
const auto expected = std::set<int64_t>{1, 2, 3};
|
const auto expected = std::set<int64_t>{1, 2, 3};
|
||||||
assert(results == expected);
|
assert(results == expected);
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
#include <random>
|
#include <random>
|
||||||
|
|
||||||
namespace sql = sqlpp::sqlite3;
|
namespace sql = sqlpp::sqlite3;
|
||||||
const auto blob = BlobSample{};
|
const auto tab = BlobSample{};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* max default blob/text is 1,000,000,000
|
* max default blob/text is 1,000,000,000
|
||||||
@ -23,36 +23,32 @@ const auto blob = BlobSample{};
|
|||||||
constexpr size_t blob_size = 1000 * 1000ul;
|
constexpr size_t blob_size = 1000 * 1000ul;
|
||||||
constexpr size_t blob_small_size = 999;
|
constexpr size_t blob_small_size = 999;
|
||||||
|
|
||||||
void verify_blob(sql::connection& db, const std::vector<uint8_t>& data, uint64_t id)
|
void verify_blob(sql::connection& db, const std::vector<uint8_t>& expected, uint64_t id)
|
||||||
{
|
{
|
||||||
auto result = db(select(blob.data).from(blob).where(blob.id == id));
|
auto result = db(select(tab.data).from(tab).where(tab.id == id));
|
||||||
const auto& result_row = result.front();
|
const auto& result_row = result.front();
|
||||||
std::cerr << "Insert size: " << data.size() << std::endl;
|
if (!result_row.data)
|
||||||
std::cerr << "Select size: " << result_row.data.len << std::endl;
|
throw std::runtime_error("blob data is unpexpectedly NULL for id " + std::to_string(id));
|
||||||
if (data.size() != result_row.data.len)
|
const auto received = *result_row.data;
|
||||||
|
|
||||||
|
if (expected.size() != received.size())
|
||||||
{
|
{
|
||||||
std::cerr << "Size mismatch" << std::endl;
|
std::cerr << "Size mismatch" << std::endl;
|
||||||
|
|
||||||
throw std::runtime_error("Size mismatch " + std::to_string(data.size()) +
|
throw std::runtime_error("Size mismatch " + std::to_string(expected.size()) +
|
||||||
" != " + std::to_string(result_row.data.len));
|
" != " + std::to_string(received.size()));
|
||||||
}
|
}
|
||||||
std::cerr << "Verifying content" << std::endl;
|
std::cerr << "Verifying content" << std::endl;
|
||||||
std::vector<uint8_t> result_blob(result_row.data.blob, result_row.data.blob + result_row.data.len);
|
for (size_t i = 0; i < expected.size(); i++)
|
||||||
if (data != result_blob)
|
|
||||||
{
|
{
|
||||||
std::cout << "Content mismatch ([row] original -> received)" << std::endl;
|
if (expected[i] != received[i])
|
||||||
|
|
||||||
for (size_t i = 0; i < data.size(); i++)
|
|
||||||
{
|
{
|
||||||
if (data[i] != result_row.data.blob[i])
|
std::cerr << "expected[" << i << "] " << static_cast<int>(expected[i]) << " != received " << static_cast<int>(received[i])
|
||||||
{
|
|
||||||
std::cerr << "[" << i << "] " << static_cast<int>(data.at(i)) << " -> " << static_cast<int>(result_blob.at(i))
|
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
|
||||||
}
|
|
||||||
throw std::runtime_error("Content mismatch");
|
throw std::runtime_error("Content mismatch");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int Blob(int, char*[])
|
int Blob(int, char*[])
|
||||||
{
|
{
|
||||||
@ -77,26 +73,20 @@ int Blob(int, char*[])
|
|||||||
std::generate_n(data_smaller.begin(), blob_small_size, generator);
|
std::generate_n(data_smaller.begin(), blob_small_size, generator);
|
||||||
|
|
||||||
// If we use the bigger blob it will trigger SQLITE_TOOBIG for the query
|
// If we use the bigger blob it will trigger SQLITE_TOOBIG for the query
|
||||||
auto id = db(insert_into(blob).set(blob.data = data_smaller));
|
auto id = db(insert_into(tab).set(tab.data = data_smaller));
|
||||||
|
|
||||||
auto prepared_insert = db.prepare(insert_into(blob).set(blob.data = parameter(blob.data)));
|
auto prepared_insert = db.prepare(insert_into(tab).set(tab.data = parameter(tab.data)));
|
||||||
prepared_insert.params.data = data;
|
prepared_insert.params.data = data;
|
||||||
auto prep_id = db(prepared_insert);
|
const auto prep_id = db(prepared_insert);
|
||||||
prepared_insert.params.data.set_null();
|
prepared_insert.params.data.set_null();
|
||||||
auto null_id = db(prepared_insert);
|
const auto null_id = db(prepared_insert);
|
||||||
|
|
||||||
verify_blob(db, data_smaller, id);
|
verify_blob(db, data_smaller, id);
|
||||||
verify_blob(db, data, prep_id);
|
verify_blob(db, data, prep_id);
|
||||||
{
|
{
|
||||||
auto result = db(select(blob.data).from(blob).where(blob.id == null_id));
|
auto result = db(select(tab.data).from(tab).where(tab.id == null_id));
|
||||||
const auto& result_row = result.front();
|
const auto& result_row = result.front();
|
||||||
std::cerr << "Null blob is_null:\t" << std::boolalpha << result_row.data.is_null() << std::endl;
|
std::cerr << "Null blob is_null:\t" << std::boolalpha << (result_row.data == sqlpp::nullopt) << std::endl;
|
||||||
std::cerr << "Null blob len == 0:\t" << std::boolalpha << (result_row.data.len == 0) << std::endl;
|
|
||||||
std::cerr << "Null blob blob == nullptr:\t" << std::boolalpha << (result_row.data.blob == nullptr) << std::endl;
|
|
||||||
if (!result_row.data.is_null() || result_row.data.len != 0 || result_row.data.blob != nullptr)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("Null blob has incorrect values");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -78,10 +78,8 @@ int DateTime(int, char*[])
|
|||||||
|
|
||||||
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
for (const auto& row : db(select(all_of(tab)).from(tab).unconditionally()))
|
||||||
{
|
{
|
||||||
require_equal(__LINE__, row.colDayPoint.is_null(), true);
|
require_equal(__LINE__, row.colDayPoint == sqlpp::nullopt, true);
|
||||||
require_equal(__LINE__, row.colDayPoint.value(), ::sqlpp::chrono::day_point{});
|
require_equal(__LINE__, row.colTimePoint == sqlpp::nullopt, true);
|
||||||
require_equal(__LINE__, row.colTimePoint.is_null(), true);
|
|
||||||
require_equal(__LINE__, row.colTimePoint.value(), ::sqlpp::chrono::microsecond_point{});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
db(update(tab).set(tab.colDayPoint = today, tab.colTimePoint = now).unconditionally());
|
db(update(tab).set(tab.colDayPoint = today, tab.colTimePoint = now).unconditionally());
|
||||||
|
@ -57,7 +57,7 @@ int main()
|
|||||||
db.execute("CREATE TABLE tab_sample (\
|
db.execute("CREATE TABLE tab_sample (\
|
||||||
alpha bigint(20) DEFAULT NULL,\
|
alpha bigint(20) DEFAULT NULL,\
|
||||||
beta varchar(255) DEFAULT NULL,\
|
beta varchar(255) DEFAULT NULL,\
|
||||||
gamma bool DEFAULT NULL\
|
gamma bool\
|
||||||
)");
|
)");
|
||||||
|
|
||||||
const auto tab = TabSample{};
|
const auto tab = TabSample{};
|
||||||
|
@ -41,6 +41,13 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::ostream& operator<<(std::ostream& os, const sqlpp::optional<T>& t) {
|
||||||
|
if (not t)
|
||||||
|
return os << "NULL";
|
||||||
|
return os << t.value();
|
||||||
|
}
|
||||||
|
|
||||||
SQLPP_ALIAS_PROVIDER(left)
|
SQLPP_ALIAS_PROVIDER(left)
|
||||||
|
|
||||||
namespace sql = sqlpp::sqlite3;
|
namespace sql = sqlpp::sqlite3;
|
||||||
@ -55,7 +62,7 @@ int DynamicSelect(int, char*[])
|
|||||||
db.execute("CREATE TABLE tab_sample (\
|
db.execute("CREATE TABLE tab_sample (\
|
||||||
alpha bigint(20) DEFAULT NULL,\
|
alpha bigint(20) DEFAULT NULL,\
|
||||||
beta varchar(255) DEFAULT NULL,\
|
beta varchar(255) DEFAULT NULL,\
|
||||||
gamma bool DEFAULT NULL\
|
gamma bool\
|
||||||
)");
|
)");
|
||||||
|
|
||||||
const auto tab = TabSample{};
|
const auto tab = TabSample{};
|
||||||
|
@ -39,15 +39,22 @@ namespace sql = sqlpp::sqlite3;
|
|||||||
|
|
||||||
const auto fp = FpSample{};
|
const auto fp = FpSample{};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::ostream& operator<<(std::ostream& os, const sqlpp::optional<T>& t) {
|
||||||
|
if (not t)
|
||||||
|
return os << "NULL";
|
||||||
|
return os << t.value();
|
||||||
|
}
|
||||||
|
|
||||||
template <typename L, typename R>
|
template <typename L, typename R>
|
||||||
auto require_equal(int line, const L& l, const R& r) -> void
|
auto require_equal(int line, const L& l, const R& r) -> void
|
||||||
{
|
{
|
||||||
if (l != r)
|
if (l != r)
|
||||||
{
|
{
|
||||||
std::cerr << line << ": ";
|
std::cerr << line << ": ";
|
||||||
serialize(::sqlpp::wrap_operand_t<L>{l}, std::cerr);
|
std::cerr << l;
|
||||||
std::cerr << " != ";
|
std::cerr << " != ";
|
||||||
serialize(::sqlpp::wrap_operand_t<R>{r}, std::cerr);
|
std::cerr << r;
|
||||||
throw std::runtime_error("Unexpected result");
|
throw std::runtime_error("Unexpected result");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,13 @@
|
|||||||
SQLPP_ALIAS_PROVIDER(pragma)
|
SQLPP_ALIAS_PROVIDER(pragma)
|
||||||
SQLPP_ALIAS_PROVIDER(sub)
|
SQLPP_ALIAS_PROVIDER(sub)
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::ostream& operator<<(std::ostream& os, const sqlpp::optional<T>& t) {
|
||||||
|
if (not t)
|
||||||
|
return os << "NULL";
|
||||||
|
return os << t.value();
|
||||||
|
}
|
||||||
|
|
||||||
namespace sql = sqlpp::sqlite3;
|
namespace sql = sqlpp::sqlite3;
|
||||||
int Sample(int, char*[])
|
int Sample(int, char*[])
|
||||||
{
|
{
|
||||||
@ -52,7 +59,7 @@ int Sample(int, char*[])
|
|||||||
db.execute(R"(CREATE TABLE tab_sample (
|
db.execute(R"(CREATE TABLE tab_sample (
|
||||||
alpha INTEGER PRIMARY KEY,
|
alpha INTEGER PRIMARY KEY,
|
||||||
beta varchar(255) DEFAULT NULL,
|
beta varchar(255) DEFAULT NULL,
|
||||||
gamma bool DEFAULT NULL
|
gamma bool
|
||||||
))");
|
))");
|
||||||
db.execute(R"(CREATE TABLE tab_foo (
|
db.execute(R"(CREATE TABLE tab_foo (
|
||||||
omega bigint(20) DEFAULT NULL
|
omega bigint(20) DEFAULT NULL
|
||||||
@ -102,8 +109,8 @@ int Sample(int, char*[])
|
|||||||
.from(tab)
|
.from(tab)
|
||||||
.unconditionally()))
|
.unconditionally()))
|
||||||
{
|
{
|
||||||
int64_t x = row.alpha;
|
sqlpp::optional<int64_t> x = row.alpha;
|
||||||
int64_t a = row.max;
|
sqlpp::optional<int64_t> a = row.max;
|
||||||
std::cout << x << ", " << a << std::endl;
|
std::cout << x << ", " << a << std::endl;
|
||||||
}
|
}
|
||||||
tx.commit();
|
tx.commit();
|
||||||
@ -134,7 +141,8 @@ int Sample(int, char*[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::cerr << "--------" << std::endl;
|
std::cerr << "--------" << std::endl;
|
||||||
ps.params.alpha = sqlpp::eval<sqlpp::integer>(db, "last_insert_rowid()");
|
const auto last_id = sqlpp::eval<sqlpp::integer>(db, "last_insert_rowid()");
|
||||||
|
ps.params.alpha = last_id.value();
|
||||||
ps.params.gamma = false;
|
ps.params.gamma = false;
|
||||||
for (const auto& row : db(ps))
|
for (const auto& row : db(ps))
|
||||||
{
|
{
|
||||||
|
@ -41,6 +41,13 @@
|
|||||||
namespace sql = sqlpp::sqlite3;
|
namespace sql = sqlpp::sqlite3;
|
||||||
const auto tab = TabSample{};
|
const auto tab = TabSample{};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::ostream& operator<<(std::ostream& os, const sqlpp::optional<T>& t) {
|
||||||
|
if (not t)
|
||||||
|
return os << "NULL";
|
||||||
|
return os << t.value();
|
||||||
|
}
|
||||||
|
|
||||||
void testSelectAll(sql::connection& db, size_t expectedRowCount)
|
void testSelectAll(sql::connection& db, size_t expectedRowCount)
|
||||||
{
|
{
|
||||||
std::cerr << "--------------------------------------" << std::endl;
|
std::cerr << "--------------------------------------" << std::endl;
|
||||||
@ -50,7 +57,7 @@ void testSelectAll(sql::connection& db, size_t expectedRowCount)
|
|||||||
++i;
|
++i;
|
||||||
std::cerr << ">>> row.alpha: " << row.alpha << ", row.beta: " << row.beta << ", row.gamma: " << row.gamma
|
std::cerr << ">>> row.alpha: " << row.alpha << ", row.beta: " << row.beta << ", row.gamma: " << row.gamma
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
assert(static_cast<size_t>(row.alpha) == i);
|
assert(row.alpha == static_cast<int64_t>(i));
|
||||||
};
|
};
|
||||||
assert(i == expectedRowCount);
|
assert(i == expectedRowCount);
|
||||||
|
|
||||||
@ -61,7 +68,7 @@ void testSelectAll(sql::connection& db, size_t expectedRowCount)
|
|||||||
++i;
|
++i;
|
||||||
std::cerr << ">>> row.alpha: " << row.alpha << ", row.beta: " << row.beta << ", row.gamma: " << row.gamma
|
std::cerr << ">>> row.alpha: " << row.alpha << ", row.beta: " << row.beta << ", row.gamma: " << row.gamma
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
assert(static_cast<size_t>(row.alpha) == i);
|
assert(row.alpha == static_cast<int64_t>(i));
|
||||||
};
|
};
|
||||||
assert(i == expectedRowCount);
|
assert(i == expectedRowCount);
|
||||||
std::cerr << "--------------------------------------" << std::endl;
|
std::cerr << "--------------------------------------" << std::endl;
|
||||||
@ -93,7 +100,7 @@ int Select(int, char*[])
|
|||||||
db.execute(R"(CREATE TABLE tab_sample (
|
db.execute(R"(CREATE TABLE tab_sample (
|
||||||
alpha INTEGER PRIMARY KEY,
|
alpha INTEGER PRIMARY KEY,
|
||||||
beta varchar(255) DEFAULT NULL,
|
beta varchar(255) DEFAULT NULL,
|
||||||
gamma bool DEFAULT NULL
|
gamma bool
|
||||||
))");
|
))");
|
||||||
|
|
||||||
testSelectAll(db, 0);
|
testSelectAll(db, 0);
|
||||||
@ -141,8 +148,8 @@ int Select(int, char*[])
|
|||||||
auto tx = start_transaction(db);
|
auto tx = start_transaction(db);
|
||||||
for (const auto& row : db(select(all_of(tab), select(max(tab.alpha)).from(tab)).from(tab).unconditionally()))
|
for (const auto& row : db(select(all_of(tab), select(max(tab.alpha)).from(tab)).from(tab).unconditionally()))
|
||||||
{
|
{
|
||||||
const int64_t x = row.alpha;
|
const auto x = row.alpha;
|
||||||
const int64_t a = row.max;
|
const auto a = row.max;
|
||||||
std::cout << ">>>" << x << ", " << a << std::endl;
|
std::cout << ">>>" << x << ", " << a << std::endl;
|
||||||
}
|
}
|
||||||
for (const auto& row :
|
for (const auto& row :
|
||||||
@ -153,14 +160,14 @@ int Select(int, char*[])
|
|||||||
std::cerr << ">>> row.alpha: " << row.alpha << ", row.beta: " << row.beta << ", row.gamma: " << row.gamma
|
std::cerr << ">>> row.alpha: " << row.alpha << ", row.beta: " << row.beta << ", row.gamma: " << row.gamma
|
||||||
<< ", row.trim: '" << row.trim << "'" << std::endl;
|
<< ", row.trim: '" << row.trim << "'" << std::endl;
|
||||||
// check trim
|
// check trim
|
||||||
assert(string_util::trim(row.beta.value()) == row.trim.value());
|
assert((not row.beta and not row.trim) || string_util::trim(std::string(row.beta.value())) == row.trim.value());
|
||||||
// end
|
// end
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto& row : db(select(all_of(tab), select(trim(tab.beta)).from(tab)).from(tab).unconditionally()))
|
for (const auto& row : db(select(all_of(tab), select(trim(tab.beta)).from(tab)).from(tab).unconditionally()))
|
||||||
{
|
{
|
||||||
const int64_t x = row.alpha;
|
const sqlpp::optional<int64_t> x = row.alpha;
|
||||||
const std::string a = row.trim;
|
const sqlpp::optional<sqlpp::string_view> a = row.trim;
|
||||||
std::cout << ">>>" << x << ", " << a << std::endl;
|
std::cout << ">>>" << x << ", " << a << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
CREATE TABLE tab_sample (
|
CREATE TABLE tab_sample (
|
||||||
alpha bigint(20) DEFAULT NULL,
|
alpha bigint(20) DEFAULT NULL,
|
||||||
beta tinyint(1) DEFAULT NULL,
|
beta tinyint(1) DEFAULT NULL,
|
||||||
gamma varchar(255) DEFAULT NULL
|
gamma varchar(255)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||||
|
@ -37,6 +37,13 @@
|
|||||||
namespace sql = sqlpp::sqlite3;
|
namespace sql = sqlpp::sqlite3;
|
||||||
const auto tab = TabSample{};
|
const auto tab = TabSample{};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::ostream& operator<<(std::ostream& os, const sqlpp::optional<T>& t) {
|
||||||
|
if (not t)
|
||||||
|
return os << "NULL";
|
||||||
|
return os << t.value();
|
||||||
|
}
|
||||||
|
|
||||||
int Union(int, char*[])
|
int Union(int, char*[])
|
||||||
{
|
{
|
||||||
sql::connection_config config;
|
sql::connection_config config;
|
||||||
@ -48,7 +55,7 @@ int Union(int, char*[])
|
|||||||
db.execute(R"(CREATE TABLE tab_sample (
|
db.execute(R"(CREATE TABLE tab_sample (
|
||||||
alpha INTEGER PRIMARY KEY,
|
alpha INTEGER PRIMARY KEY,
|
||||||
beta varchar(255) DEFAULT NULL,
|
beta varchar(255) DEFAULT NULL,
|
||||||
gamma bool DEFAULT NULL
|
gamma bool
|
||||||
))");
|
))");
|
||||||
|
|
||||||
auto u = select(all_of(tab)).from(tab).unconditionally().union_all(select(all_of(tab)).from(tab).unconditionally());
|
auto u = select(all_of(tab)).from(tab).unconditionally().union_all(select(all_of(tab)).from(tab).unconditionally());
|
||||||
|
@ -39,6 +39,13 @@
|
|||||||
namespace sql = sqlpp::sqlite3;
|
namespace sql = sqlpp::sqlite3;
|
||||||
const auto tab = TabSample{};
|
const auto tab = TabSample{};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::ostream& operator<<(std::ostream& os, const sqlpp::optional<T>& t) {
|
||||||
|
if (not t)
|
||||||
|
return os << "NULL";
|
||||||
|
return os << t.value();
|
||||||
|
}
|
||||||
|
|
||||||
int With(int, char*[])
|
int With(int, char*[])
|
||||||
{
|
{
|
||||||
#if SQLITE_VERSION_NUMBER >= 3008003
|
#if SQLITE_VERSION_NUMBER >= 3008003
|
||||||
@ -51,7 +58,7 @@ int With(int, char*[])
|
|||||||
db.execute(R"(CREATE TABLE tab_sample (
|
db.execute(R"(CREATE TABLE tab_sample (
|
||||||
alpha INTEGER PRIMARY KEY,
|
alpha INTEGER PRIMARY KEY,
|
||||||
beta varchar(255) DEFAULT NULL,
|
beta varchar(255) DEFAULT NULL,
|
||||||
gamma bool DEFAULT NULL
|
gamma bool
|
||||||
))");
|
))");
|
||||||
|
|
||||||
auto a = sqlpp::cte(sqlpp::alias::a).as(select(all_of(tab)).from(tab).where(tab.alpha > 3));
|
auto a = sqlpp::cte(sqlpp::alias::a).as(select(all_of(tab)).from(tab).where(tab.alpha > 3));
|
||||||
|
Loading…
Reference in New Issue
Block a user