mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-16 04:47:18 +08:00
Add basic serialize functions and start documenting differences
This commit is contained in:
parent
2b7e0ee6a5
commit
c2c5f15690
39
docs/DifferencesToVersion-1.0.md
Normal file
39
docs/DifferencesToVersion-1.0.md
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# New data types
|
||||||
|
|
||||||
|
## optional
|
||||||
|
Nullable values are represented as `std::optional` if you are using C++17 or later, `sqlpp::compat::optional` otherwise.
|
||||||
|
|
||||||
|
## string_view
|
||||||
|
Text results are represented as `std::string_view` if you are using C++17 or later, `sqlpp::compat::string_view` otherwise.
|
||||||
|
|
||||||
|
# span<uint8_t>
|
||||||
|
Blob results are represented as `std::span<uint8_t>` if you are using C++20 or later, `sqlpp::compat::span<uint8_t>` otherwise.
|
||||||
|
|
||||||
|
# Result values
|
||||||
|
Result rows are represented as structs with the respective columns represented as data members. In version 1.0, these data members used to have a type that wrapped the actual data and provided conversion operators and functions to check for NULL.
|
||||||
|
|
||||||
|
Now data members have the correct data type, e.g. `int64_t` or `optional<string_view>`.
|
||||||
|
|
||||||
|
# No read-only columns
|
||||||
|
Version 1.0 had the concept of read-only columns, e.g. you could not modify a column with auto-increment values.
|
||||||
|
|
||||||
|
This concept has been removed. In most cases, you will still not want to modify columns with auto-increment values, but you can do it now, if you want to.
|
||||||
|
|
||||||
|
# IS DISCTINCT FROM
|
||||||
|
Version 1.0 used to have `is_equal_to_or_null` which translated to either `=` or `IS NULL`. While useful, this did not work with parameters.
|
||||||
|
|
||||||
|
The library now offers `is_distinct_from` and `is_not_distinct_from` which safely compares with actual values and `NULL`.
|
||||||
|
|
||||||
|
# Selecting aggregate functions
|
||||||
|
In version 1.0, many functions automatically came with a name. This was convenient for selecting, but also rather unspecific, e.g. `select(max(tab.price)).from(tab).unconditionally()` would yield rows with data member called `count_`.
|
||||||
|
|
||||||
|
Now, functions do not come with names. While this will lead to lightly more code, the assumption is that this will lead to slightly more readable code, e.g.
|
||||||
|
|
||||||
|
```
|
||||||
|
SQLPP_ALIAS_PROVIDER(max_price);
|
||||||
|
// ...
|
||||||
|
for (const auto& row : db(select(max(tab.price)).from(tab).unconditionally()))
|
||||||
|
{
|
||||||
|
std::cout << row.max_price << '\n';
|
||||||
|
}
|
||||||
|
```
|
@ -112,6 +112,11 @@ namespace sqlpp
|
|||||||
using type = typename ColumnSpec::value_type;
|
using type = typename ColumnSpec::value_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename Table, typename ColumnSpec>
|
||||||
|
struct has_default<column_t<Table, ColumnSpec>> : public ColumnSpec::has_default
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template <typename Context, typename Table, typename ColumnSpec>
|
template <typename Context, typename Table, typename ColumnSpec>
|
||||||
Context& serialize(const column_t<Table, ColumnSpec>&, Context& context)
|
Context& serialize(const column_t<Table, ColumnSpec>&, Context& context)
|
||||||
{
|
{
|
||||||
|
@ -47,7 +47,6 @@
|
|||||||
#include <sqlpp11/verbatim_table.h>
|
#include <sqlpp11/verbatim_table.h>
|
||||||
#include <sqlpp11/value.h>
|
#include <sqlpp11/value.h>
|
||||||
#include <sqlpp11/value_or_null.h>
|
#include <sqlpp11/value_or_null.h>
|
||||||
#include <sqlpp11/is_equal_to_or_null.h>
|
|
||||||
#include <sqlpp11/eval.h>
|
#include <sqlpp11/eval.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
|
@ -1,76 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 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/value_or_null.h>
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
template <typename Expr, typename ValueType>
|
|
||||||
struct is_equal_to_or_null_t: public expression_operators<is_equal_to_or_null_t<Expr, ValueType>, boolean>,
|
|
||||||
public alias_operators<is_equal_to_or_null_t<Expr, ValueType>>
|
|
||||||
{
|
|
||||||
using _traits = make_traits<boolean, tag::is_expression>;
|
|
||||||
using _nodes = detail::type_vector<Expr, value_or_null_t<ValueType>>;
|
|
||||||
|
|
||||||
is_equal_to_or_null_t(Expr expr, value_or_null_t<ValueType> value) : _expr(expr), _value(value)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
is_equal_to_or_null_t(const is_equal_to_or_null_t&) = default;
|
|
||||||
is_equal_to_or_null_t(is_equal_to_or_null_t&&) = default;
|
|
||||||
is_equal_to_or_null_t& operator=(const is_equal_to_or_null_t&) = default;
|
|
||||||
is_equal_to_or_null_t& operator=(is_equal_to_or_null_t&&) = default;
|
|
||||||
~is_equal_to_or_null_t() = default;
|
|
||||||
|
|
||||||
|
|
||||||
Expr _expr;
|
|
||||||
value_or_null_t<ValueType> _value;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Context, typename Expr, typename ValueType>
|
|
||||||
Context& serialize(const is_equal_to_or_null_t<Expr, ValueType>& t, Context& context)
|
|
||||||
{
|
|
||||||
if (t._value._is_null)
|
|
||||||
serialize(t._expr.is_null(), context);
|
|
||||||
else
|
|
||||||
serialize(t._expr == t._value, context);
|
|
||||||
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Expr, typename ValueType>
|
|
||||||
auto is_equal_to_or_null(Expr expr, value_or_null_t<ValueType> value) -> is_equal_to_or_null_t<Expr, ValueType>
|
|
||||||
{
|
|
||||||
static_assert(is_expression_t<Expr>::value,
|
|
||||||
"is_equal_to_or_null() is to be called an expression (e.g. a column) and a value_or_null expression");
|
|
||||||
static_assert(std::is_same<value_type_of_t<Expr>, ValueType>::value,
|
|
||||||
"is_equal_to_or_null() arguments need to have the same value type");
|
|
||||||
return {expr, value};
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace sqlpp
|
|
@ -177,7 +177,7 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename L, typename R>
|
template <typename L, typename R>
|
||||||
using check_modulus_args = std::enable_if_t<has_integral_value<L>::value and has_integral_value<R>::value>;
|
using check_modulus_args = std::enable_if_t<(is_integral<L>::value or is_unsigned_integral<L>::value) and (is_integral<R>::value or is_unsigned_integral<R>::value)>;
|
||||||
|
|
||||||
template <typename L, typename R, typename = check_modulus_args<L, R>>
|
template <typename L, typename R, typename = check_modulus_args<L, R>>
|
||||||
constexpr auto operator%(L l, R r) -> arithmetic_expression<L, modulus, R>
|
constexpr auto operator%(L l, R r) -> arithmetic_expression<L, modulus, R>
|
||||||
|
@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include <sqlpp11/column_fwd.h>
|
||||||
#include <sqlpp11/type_traits.h>
|
#include <sqlpp11/type_traits.h>
|
||||||
#include <sqlpp11/default_value.h>
|
#include <sqlpp11/default_value.h>
|
||||||
|
|
||||||
@ -40,16 +41,21 @@ namespace sqlpp
|
|||||||
R value;
|
R value;
|
||||||
};
|
};
|
||||||
|
|
||||||
#warning rename is_column, is_default, values_are_comparable -> values_are_compatible
|
|
||||||
#warning document the change that there is no read-only!
|
|
||||||
#warning handle default_t, but only if the column does have a default!
|
|
||||||
template <typename L, typename R>
|
template <typename L, typename R>
|
||||||
using check_assign_args = std::enable_if_t<is_column_t<L>::value and values_are_comparable<L, R>::value and
|
using check_assign_args =
|
||||||
(can_be_null<L>::value or not is_optional<R>::value) and
|
std::enable_if_t<values_are_comparable<L, R>::value and (can_be_null<L>::value or not is_optional<R>::value)>;
|
||||||
(has_default_t<L>::value or not std::is_same<R, default_value_t>::value)>;
|
|
||||||
|
|
||||||
template <typename L, typename R, typename = check_assign_args<L, R>>
|
template <typename L>
|
||||||
constexpr auto assign(L column, R value) -> assign_expression<L, R>
|
using check_assign_default_args = std::enable_if_t<has_default<L>::value>;
|
||||||
|
|
||||||
|
template <typename Table, typename ColumnSpec, typename R, typename = check_assign_args<column_t<Table, ColumnSpec>, R>>
|
||||||
|
constexpr auto assign(column_t<Table, ColumnSpec> column, R value) -> assign_expression<column_t<Table, ColumnSpec>, R>
|
||||||
|
{
|
||||||
|
return {std::move(column), std::move(value)};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Table, typename ColumnSpec, typename = check_assign_default_args<column_t<Table, ColumnSpec>>>
|
||||||
|
constexpr auto assign(column_t<Table, ColumnSpec> column, default_value_t value) -> assign_expression<column_t<Table, ColumnSpec>, default_value_t>
|
||||||
{
|
{
|
||||||
return {std::move(column), std::move(value)};
|
return {std::move(column), std::move(value)};
|
||||||
}
|
}
|
||||||
@ -79,4 +85,13 @@ namespace sqlpp
|
|||||||
return to_sql_string(context, t.column) + " = " + to_sql_string(context, embrace(t.value));
|
return to_sql_string(context, t.column) + " = " + to_sql_string(context, embrace(t.value));
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
template <typename Context, typename L, typename R>
|
||||||
|
Context& serialize(const assign_expression<L, R>& t, Context& context)
|
||||||
|
{
|
||||||
|
serialize(simple_column(t._lhs), context);
|
||||||
|
context << "=";
|
||||||
|
serialize_operand(t._rhs, context);
|
||||||
|
return context;
|
||||||
|
}
|
||||||
} // namespace sqlpp
|
} // namespace sqlpp
|
||||||
|
@ -82,7 +82,7 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename L, typename R>
|
template <typename L, typename R>
|
||||||
using check_bit_expression_args = std::enable_if_t<has_integral_value<L>::value and has_integral_value<R>::value>;
|
using check_bit_expression_args = std::enable_if_t<is_integral<L>::value and (is_integral<R>::value or is_unsigned_integral<R>::value)>;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
template <typename L, typename Operator, typename R>
|
template <typename L, typename Operator, typename R>
|
||||||
|
@ -45,7 +45,6 @@ namespace sqlpp
|
|||||||
using type = boolean;
|
using type = boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
#warning: Document that functions dont come with their default alias any more
|
|
||||||
template <typename SubSelect, typename = check_exists_arg<SubSelect>>
|
template <typename SubSelect, typename = check_exists_arg<SubSelect>>
|
||||||
constexpr auto exists(SubSelect sub_select) -> exists_t<SubSelect>
|
constexpr auto exists(SubSelect sub_select) -> exists_t<SubSelect>
|
||||||
{
|
{
|
||||||
|
@ -61,7 +61,7 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename L, typename R>
|
template <typename L, typename R>
|
||||||
using check_logical_args = std::enable_if_t<has_boolean_value<L>::value and has_boolean_value<R>::value>;
|
using check_logical_args = std::enable_if_t<is_boolean<L>::value and is_boolean<R>::value>;
|
||||||
|
|
||||||
template <typename L, typename Operator, typename R>
|
template <typename L, typename Operator, typename R>
|
||||||
struct value_type_of<logical_expression<L, Operator, R>>
|
struct value_type_of<logical_expression<L, Operator, R>>
|
||||||
|
@ -46,4 +46,164 @@ namespace sqlpp
|
|||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Context>
|
||||||
|
auto serialize(const bool& t, Context& context) -> Context&
|
||||||
|
{
|
||||||
|
context << t;
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Context>
|
||||||
|
auto serialize(const int8_t& t, Context& context) -> Context&
|
||||||
|
{
|
||||||
|
context << t;
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Context>
|
||||||
|
auto serialize(const int16_t& t, Context& context) -> Context&
|
||||||
|
{
|
||||||
|
context << t;
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Context>
|
||||||
|
auto serialize(const int32_t& t, Context& context) -> Context&
|
||||||
|
{
|
||||||
|
context << t;
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Context>
|
||||||
|
auto serialize(const int64_t& t, Context& context) -> Context&
|
||||||
|
{
|
||||||
|
context << t;
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Context>
|
||||||
|
auto serialize(const uint8_t& t, Context& context) -> Context&
|
||||||
|
{
|
||||||
|
context << t;
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Context>
|
||||||
|
auto serialize(const uint16_t& t, Context& context) -> Context&
|
||||||
|
{
|
||||||
|
context << t;
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Context>
|
||||||
|
auto serialize(const uint32_t& t, Context& context) -> Context&
|
||||||
|
{
|
||||||
|
context << t;
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Context>
|
||||||
|
auto serialize(const uint64_t& t, Context& context) -> Context&
|
||||||
|
{
|
||||||
|
context << t;
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Context>
|
||||||
|
auto serialize(const float& t, Context& context) -> Context&
|
||||||
|
{
|
||||||
|
context << t;
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Context>
|
||||||
|
auto serialize(const double& t, Context& context) -> Context&
|
||||||
|
{
|
||||||
|
#warning: Analyze precision. There was a bug about this...
|
||||||
|
context << t;
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Context>
|
||||||
|
auto serialize(const char& t, Context& context) -> Context&
|
||||||
|
{
|
||||||
|
context << t;
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Context>
|
||||||
|
auto serialize(const char* t, Context& context) -> Context&
|
||||||
|
{
|
||||||
|
context << t;
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Context>
|
||||||
|
auto serialize(const std::string& t, Context& context) -> Context&
|
||||||
|
{
|
||||||
|
context << t;
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Context>
|
||||||
|
auto serialize(const sqlpp::compat::string_view& t, Context& context) -> Context&
|
||||||
|
{
|
||||||
|
context << t;
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Context>
|
||||||
|
Context& serialize(const std::vector<uint8_t>& t, Context& context)
|
||||||
|
{
|
||||||
|
constexpr char hexChars[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||||
|
context << "x'";
|
||||||
|
for (const auto c : t)
|
||||||
|
{
|
||||||
|
context << hexChars[c >> 4] << hexChars[c & 0x0F];
|
||||||
|
}
|
||||||
|
context << '\'';
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Context>
|
||||||
|
Context& serialize(const ::sqlpp::chrono::day_point& t, Context& context)
|
||||||
|
{
|
||||||
|
const auto ymd = ::date::year_month_day{t};
|
||||||
|
context << "DATE '" << ymd << "'";
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Context>
|
||||||
|
Context& serialize(const std::chrono::microseconds& t, Context& context)
|
||||||
|
{
|
||||||
|
context << '\'' << ::date::make_time(t) << '\'';
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Period, typename Context>
|
||||||
|
Context& serialize(const std::chrono::time_point<std::chrono::system_clock, Period>& t, Context& context)
|
||||||
|
{
|
||||||
|
const auto dp = ::sqlpp::chrono::floor<::date::days>(t);
|
||||||
|
const auto time = ::date::make_time(t - dp);
|
||||||
|
const auto ymd = ::date::year_month_day{dp};
|
||||||
|
context << "TIMESTAMP '" << ymd << ' ' << time << "'";
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename Context>
|
||||||
|
auto serialize(const sqlpp::compat::optional<T>& t, Context& context) -> Context&
|
||||||
|
{
|
||||||
|
if (not t.has_value())
|
||||||
|
{
|
||||||
|
context << "NULL";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
serialize(*t, context);
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sqlpp
|
} // namespace sqlpp
|
||||||
|
@ -115,7 +115,6 @@ namespace sqlpp
|
|||||||
|
|
||||||
struct no_value_t;
|
struct no_value_t;
|
||||||
|
|
||||||
// This requires specializations for anything that has a value, like a column or a boolean expression
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct value_type_of
|
struct value_type_of
|
||||||
{
|
{
|
||||||
@ -134,6 +133,11 @@ namespace sqlpp
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
struct has_value_type : public std::integral_constant<bool, not std::is_same<value_type_of_t<T>, no_value_t>::value> {};
|
struct has_value_type : public std::integral_constant<bool, not std::is_same<value_type_of_t<T>, no_value_t>::value> {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct has_default : public std::false_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_not_cpp_bool_t
|
struct is_not_cpp_bool_t
|
||||||
{
|
{
|
||||||
@ -181,7 +185,6 @@ namespace sqlpp
|
|||||||
template <>
|
template <>
|
||||||
struct value_type_of<sqlpp::compat::string_view> { using type = text; };
|
struct value_type_of<sqlpp::compat::string_view> { using type = text; };
|
||||||
|
|
||||||
/////////////////
|
|
||||||
struct blob;
|
struct blob;
|
||||||
template <>
|
template <>
|
||||||
struct value_type_of<std::vector<std::uint8_t>> { using type = blob; };
|
struct value_type_of<std::vector<std::uint8_t>> { using type = blob; };
|
||||||
@ -200,63 +203,39 @@ namespace sqlpp
|
|||||||
struct time_point;
|
struct time_point;
|
||||||
template <typename Period>
|
template <typename Period>
|
||||||
struct value_type_of<std::chrono::time_point<std::chrono::system_clock, Period>> { using type = time_point; };
|
struct value_type_of<std::chrono::time_point<std::chrono::system_clock, Period>> { using type = time_point; };
|
||||||
/////////////////
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_boolean : public std::is_same<T, bool>
|
struct is_boolean : public std::is_same<remove_optional_t<value_type_of_t<T>>, boolean>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
|
||||||
struct is_boolean<boolean> : public std::true_type {
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct is_boolean<sqlpp::compat::nullopt_t> : public std::true_type {
|
struct is_boolean<sqlpp::compat::nullopt_t> : public std::true_type {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct has_boolean_value : public std::integral_constant<bool,
|
struct is_integral : public std::is_same<remove_optional_t<value_type_of_t<T>>, integral>
|
||||||
is_boolean<remove_optional_t<T>>::value or
|
|
||||||
is_boolean<remove_optional_t<value_type_of_t<T>>>::value>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
struct integral;
|
|
||||||
template <typename T>
|
|
||||||
struct is_integral : public std::is_integral<T>{};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct is_integral<char> : public std::false_type // char is text
|
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct is_integral<bool> : public std::false_type // bool is boolean
|
struct is_integral<sqlpp::compat::nullopt_t> : public std::true_type {
|
||||||
{
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
|
||||||
struct is_integral<sqlpp::compat::nullopt_t> : public std::true_type{};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct is_integral<integral> : public std::true_type{};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct has_integral_value
|
struct is_unsigned_integral : public std::is_same<remove_optional_t<value_type_of_t<T>>, unsigned_integral>
|
||||||
: public std::integral_constant<bool,
|
|
||||||
is_integral<remove_optional_t<T>>::value or
|
|
||||||
is_integral<remove_optional_t<value_type_of_t<T>>>::value>
|
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct is_unsigned_integral<sqlpp::compat::nullopt_t> : public std::true_type {
|
||||||
|
};
|
||||||
|
|
||||||
// A generic numeric type which could be (unsigned) integral or floating point.
|
// A generic numeric type which could be (unsigned) integral or floating point.
|
||||||
struct numeric;
|
struct numeric;
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_numeric : public std::integral_constant<bool, is_integral<T>::value or std::is_floating_point<T>::value>{};
|
struct is_numeric : public std::integral_constant<bool, is_integral<T>::value or is_unsigned_integral<T>::value or std::is_floating_point<T>::value>{};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct is_numeric<numeric> : public std::true_type{};
|
struct is_numeric<numeric> : public std::true_type{};
|
||||||
@ -375,7 +354,7 @@ namespace sqlpp
|
|||||||
struct values_are_comparable
|
struct values_are_comparable
|
||||||
: public std::integral_constant<bool,
|
: public std::integral_constant<bool,
|
||||||
(has_blob_value<L>::value and has_blob_value<R>::value) or
|
(has_blob_value<L>::value and has_blob_value<R>::value) or
|
||||||
(has_boolean_value<L>::value and has_boolean_value<R>::value) or
|
(is_boolean<L>::value and is_boolean<R>::value) or
|
||||||
(has_day_point_value<L>::value and has_day_point_value<R>::value) or
|
(has_day_point_value<L>::value and has_day_point_value<R>::value) or
|
||||||
(has_numeric_value<L>::value and has_numeric_value<R>::value) or
|
(has_numeric_value<L>::value and has_numeric_value<R>::value) or
|
||||||
(has_text_value<L>::value and has_text_value<R>::value) or
|
(has_text_value<L>::value and has_text_value<R>::value) or
|
||||||
@ -421,6 +400,7 @@ namespace sqlpp
|
|||||||
using is_time_point_t = std::is_same<value_type_of_t<T>, time_point>;
|
using is_time_point_t = std::is_same<value_type_of_t<T>, time_point>;
|
||||||
|
|
||||||
// joined data type
|
// joined data type
|
||||||
|
#warning: These something_t data type classifiers should be removed
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using is_numeric_t =
|
using is_numeric_t =
|
||||||
logic::any_t<is_integral_t<T>::value, is_unsigned_integral_t<T>::value, is_floating_point_t<T>::value>;
|
logic::any_t<is_integral_t<T>::value, is_unsigned_integral_t<T>::value, is_floating_point_t<T>::value>;
|
||||||
@ -469,9 +449,6 @@ namespace sqlpp
|
|||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_union_flag)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_union_flag)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_result_field)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_result_field)
|
||||||
|
|
||||||
#warning Document loss of must_not_insert/update and require_insert (and new has_default)
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(has_default)
|
|
||||||
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_statement)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_statement)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_prepared_statement)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_prepared_statement)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_union)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_union)
|
||||||
|
@ -43,6 +43,7 @@ namespace sqlpp
|
|||||||
|
|
||||||
T _value;
|
T _value;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct value_type_of<value_t<T>>
|
struct value_type_of<value_t<T>>
|
||||||
{
|
{
|
||||||
@ -52,9 +53,19 @@ namespace sqlpp
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
using check_value_arg = std::enable_if_t<not std::is_same<value_type_of_t<T>, no_value_t>::value and values_are_comparable<T, T>::value>;
|
using check_value_arg = std::enable_if_t<not std::is_same<value_type_of_t<T>, no_value_t>::value and values_are_comparable<T, T>::value>;
|
||||||
|
|
||||||
|
template <typename Context, typename T>
|
||||||
|
Context& serialize(const value_t<T>& t, Context& context)
|
||||||
|
{
|
||||||
|
#warning: Untested
|
||||||
|
serialize(t._value, context);
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T, typename = check_value_arg<T>>
|
template <typename T, typename = check_value_arg<T>>
|
||||||
auto value(T t) -> value_t<T>
|
auto value(T t) -> value_t<T>
|
||||||
{
|
{
|
||||||
return {std::move(t)};
|
return {std::move(t)};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace sqlpp
|
} // namespace sqlpp
|
||||||
|
@ -743,9 +743,9 @@ def createHeader():
|
|||||||
column.hasAutoValue or \
|
column.hasAutoValue or \
|
||||||
(autoId and sqlColumnName == "id")
|
(autoId and sqlColumnName == "id")
|
||||||
if columnHasDefault:
|
if columnHasDefault:
|
||||||
print(" using has_default_value = std::true_type;", file=header)
|
print(" using has_default = std::true_type;", file=header)
|
||||||
else:
|
else:
|
||||||
print(" using has_default_value = std::false_type;", file=header)
|
print(" using has_default = std::false_type;", file=header)
|
||||||
print(" };", file=header)
|
print(" };", file=header)
|
||||||
print(" } // namespace " + tableNamespace, file=header)
|
print(" } // namespace " + tableNamespace, file=header)
|
||||||
print("", file=header)
|
print("", file=header)
|
||||||
|
@ -106,8 +106,9 @@ int main()
|
|||||||
static_assert(is_same_type<decltype(row.b), sqlpp::compat::optional<int64_t>>(), "");
|
static_assert(is_same_type<decltype(row.b), sqlpp::compat::optional<int64_t>>(), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
static_assert(sqlpp::has_boolean_value<bool>::value, "");
|
#warning: also test with optional
|
||||||
static_assert(sqlpp::has_boolean_value<decltype(bar.boolNn)>::value, "");
|
static_assert(sqlpp::is_boolean<bool>::value, "");
|
||||||
|
static_assert(sqlpp::is_boolean<decltype(bar.boolNn)>::value, "");
|
||||||
static_assert(sqlpp::has_text_value<decltype(bar.textN)>::value, "");
|
static_assert(sqlpp::has_text_value<decltype(bar.textN)>::value, "");
|
||||||
static_assert(sqlpp::has_text_value<std::string>::value, "");
|
static_assert(sqlpp::has_text_value<std::string>::value, "");
|
||||||
static_assert(sqlpp::has_numeric_value<int>::value, "");
|
static_assert(sqlpp::has_numeric_value<int>::value, "");
|
||||||
@ -257,8 +258,6 @@ int main()
|
|||||||
sqlpp::numeric>::value,
|
sqlpp::numeric>::value,
|
||||||
"");
|
"");
|
||||||
|
|
||||||
#warning: Is bit-shifting with NULL "legal"? probably.
|
|
||||||
#warning: Note that bit-shifting is defined for signed int only
|
|
||||||
// Bit shifting combining optional value with non-optional value yields optional boolean.
|
// Bit shifting combining optional value with non-optional value yields optional boolean.
|
||||||
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(sqlpp::value(sqlpp::compat::make_optional(7)) << 8)>,
|
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(sqlpp::value(sqlpp::compat::make_optional(7)) << 8)>,
|
||||||
sqlpp::compat::optional<sqlpp::integral>>::value,
|
sqlpp::compat::optional<sqlpp::integral>>::value,
|
||||||
@ -293,7 +292,7 @@ int main()
|
|||||||
|
|
||||||
// assignment is no value
|
// assignment is no value
|
||||||
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(assign(bar.intN, sqlpp::compat::nullopt))>, sqlpp::no_value_t>::value, "");
|
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(assign(bar.intN, sqlpp::compat::nullopt))>, sqlpp::no_value_t>::value, "");
|
||||||
#warning: This is not the real thing yet
|
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(assign(bar.intN, sqlpp::default_value))>, sqlpp::no_value_t>::value, "");
|
||||||
|
|
||||||
// as expressions retain the value type of the real thing
|
// as expressions retain the value type of the real thing
|
||||||
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(bar.intN.as(bar.textN))>, sqlpp::value_type_of_t<decltype(bar.intN)>>::value, "");
|
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(bar.intN.as(bar.textN))>, sqlpp::value_type_of_t<decltype(bar.intN)>>::value, "");
|
||||||
@ -304,8 +303,6 @@ int main()
|
|||||||
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(sqlpp::max(7))>, sqlpp::compat::optional<sqlpp::integral>>::value, "");
|
static_assert(std::is_same<sqlpp::value_type_of_t<decltype(sqlpp::max(7))>, sqlpp::compat::optional<sqlpp::integral>>::value, "");
|
||||||
|
|
||||||
|
|
||||||
#warning: No magic for NULL in operators, e.g. comparison. It might therefore be reasonable to disallow comparison with optoinal values? But then again, columns can also be NULL, failing to compare to anything. In any case, do not translate `a == nullopt` to `a IS NULL`. Same for parameters.
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ namespace test
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
using value_type = ::sqlpp::integer;
|
using value_type = ::sqlpp::integer;
|
||||||
using has_default_value = std::true_type;
|
using has_default = std::true_type;
|
||||||
};
|
};
|
||||||
struct TextNnD
|
struct TextNnD
|
||||||
{
|
{
|
||||||
@ -42,7 +42,7 @@ namespace test
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
using value_type = ::sqlpp::text;
|
using value_type = ::sqlpp::text;
|
||||||
using has_default_value = std::true_type;
|
using has_default = std::true_type;
|
||||||
};
|
};
|
||||||
struct IntN
|
struct IntN
|
||||||
{
|
{
|
||||||
@ -59,7 +59,7 @@ namespace test
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
using value_type = ::sqlpp::compat::optional<::sqlpp::integer>;
|
using value_type = ::sqlpp::compat::optional<::sqlpp::integer>;
|
||||||
using has_default_value = std::true_type;
|
using has_default = std::true_type;
|
||||||
};
|
};
|
||||||
struct DoubleN
|
struct DoubleN
|
||||||
{
|
{
|
||||||
@ -76,7 +76,7 @@ namespace test
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
using value_type = ::sqlpp::compat::optional<::sqlpp::floating_point>;
|
using value_type = ::sqlpp::compat::optional<::sqlpp::floating_point>;
|
||||||
using has_default_value = std::true_type;
|
using has_default = std::true_type;
|
||||||
};
|
};
|
||||||
struct UIntN
|
struct UIntN
|
||||||
{
|
{
|
||||||
@ -93,7 +93,7 @@ namespace test
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
using value_type = ::sqlpp::compat::optional<::sqlpp::integer_unsigned>;
|
using value_type = ::sqlpp::compat::optional<::sqlpp::integer_unsigned>;
|
||||||
using has_default_value = std::true_type;
|
using has_default = std::true_type;
|
||||||
};
|
};
|
||||||
struct BlobN
|
struct BlobN
|
||||||
{
|
{
|
||||||
@ -110,7 +110,7 @@ namespace test
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
using value_type = ::sqlpp::compat::optional<::sqlpp::blob>;
|
using value_type = ::sqlpp::compat::optional<::sqlpp::blob>;
|
||||||
using has_default_value = std::true_type;
|
using has_default = std::true_type;
|
||||||
};
|
};
|
||||||
} // namespace TabFoo_
|
} // namespace TabFoo_
|
||||||
|
|
||||||
@ -152,7 +152,7 @@ namespace test
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
using value_type = ::sqlpp::integer;
|
using value_type = ::sqlpp::integer;
|
||||||
using has_default_value = std::true_type;
|
using has_default = std::true_type;
|
||||||
};
|
};
|
||||||
struct TextN
|
struct TextN
|
||||||
{
|
{
|
||||||
@ -169,7 +169,7 @@ namespace test
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
using value_type = ::sqlpp::compat::optional<::sqlpp::text>;
|
using value_type = ::sqlpp::compat::optional<::sqlpp::text>;
|
||||||
using has_default_value = std::true_type;
|
using has_default = std::true_type;
|
||||||
};
|
};
|
||||||
struct BoolNn
|
struct BoolNn
|
||||||
{
|
{
|
||||||
@ -186,7 +186,7 @@ namespace test
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
using value_type = ::sqlpp::boolean;
|
using value_type = ::sqlpp::boolean;
|
||||||
using has_default_value = std::false_type;
|
using has_default = std::false_type;
|
||||||
};
|
};
|
||||||
struct IntN
|
struct IntN
|
||||||
{
|
{
|
||||||
@ -203,7 +203,7 @@ namespace test
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
using value_type = ::sqlpp::compat::optional<::sqlpp::integer>;
|
using value_type = ::sqlpp::compat::optional<::sqlpp::integer>;
|
||||||
using has_default_value = std::true_type;
|
using has_default = std::true_type;
|
||||||
};
|
};
|
||||||
} // namespace TabBar_
|
} // namespace TabBar_
|
||||||
|
|
||||||
@ -243,7 +243,7 @@ namespace test
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
using value_type = ::sqlpp::integer;
|
using value_type = ::sqlpp::integer;
|
||||||
using has_default_value = std::true_type;
|
using has_default = std::true_type;
|
||||||
};
|
};
|
||||||
struct DayPointN
|
struct DayPointN
|
||||||
{
|
{
|
||||||
@ -260,7 +260,7 @@ namespace test
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
using value_type = ::sqlpp::compat::optional<::sqlpp::day_point>;
|
using value_type = ::sqlpp::compat::optional<::sqlpp::day_point>;
|
||||||
using has_default_value = std::true_type;
|
using has_default = std::true_type;
|
||||||
};
|
};
|
||||||
struct TimePointN
|
struct TimePointN
|
||||||
{
|
{
|
||||||
@ -277,7 +277,7 @@ namespace test
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
using value_type = ::sqlpp::compat::optional<::sqlpp::time_point>;
|
using value_type = ::sqlpp::compat::optional<::sqlpp::time_point>;
|
||||||
using has_default_value = std::true_type;
|
using has_default = std::true_type;
|
||||||
};
|
};
|
||||||
struct TimeOfDayN
|
struct TimeOfDayN
|
||||||
{
|
{
|
||||||
@ -294,7 +294,7 @@ namespace test
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
using value_type = ::sqlpp::compat::optional<::sqlpp::time_of_day>;
|
using value_type = ::sqlpp::compat::optional<::sqlpp::time_of_day>;
|
||||||
using has_default_value = std::true_type;
|
using has_default = std::true_type;
|
||||||
};
|
};
|
||||||
} // namespace TabDateTime_
|
} // namespace TabDateTime_
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user