mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-16 04:47:18 +08:00
Added portable static asserts for (dynamic) join.on()
Also removed inaccessible code for adding more conditions to on() dynamically. If someone should ever want that, he/she should use dynamic_where(), I guess.
This commit is contained in:
parent
5c7d588450
commit
e5931aa4eb
@ -53,6 +53,35 @@ namespace sqlpp
|
||||
template <typename Lhs, typename Rhs>
|
||||
using check_cross_join_t = typename check_cross_join<Lhs, Rhs>::type;
|
||||
|
||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_join_consist_of_cross_join_and_on_t,
|
||||
"join has to consist of a cross_join and a join condition");
|
||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_join_no_table_dependencies_t, "joined tables must not depend on other tables");
|
||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_join_on_no_foreign_table_dependencies_t,
|
||||
"on() condition must not depend on other tables");
|
||||
|
||||
template <typename CrossJoin, typename On>
|
||||
struct check_join
|
||||
{
|
||||
using type = static_combined_check_t<
|
||||
static_check_t<is_cross_join_t<CrossJoin>::value, assert_join_consist_of_cross_join_and_on_t>,
|
||||
static_check_t<is_on_t<On>::value, assert_join_consist_of_cross_join_and_on_t>,
|
||||
static_check_t<required_tables_of<CrossJoin>::size::value == 0, assert_join_no_table_dependencies_t>,
|
||||
static_check_t<detail::is_subset_of<required_tables_of<On>, provided_tables_of<CrossJoin>>::value,
|
||||
assert_join_on_no_foreign_table_dependencies_t>>;
|
||||
};
|
||||
|
||||
template <typename CrossJoin, typename On>
|
||||
using check_join_t = typename check_join<CrossJoin, On>::type;
|
||||
|
||||
template <typename CrossJoin, typename Expr>
|
||||
struct check_join_on
|
||||
{
|
||||
using type = static_combined_check_t<check_on_t<Expr>, check_join_t<CrossJoin, on_t<Expr>>>;
|
||||
};
|
||||
|
||||
template <typename CrossJoin, typename Expr>
|
||||
using check_join_on_t = typename check_join_on<CrossJoin, Expr>::type;
|
||||
|
||||
template <typename CrossJoin, typename On>
|
||||
struct join_t;
|
||||
|
||||
@ -73,16 +102,16 @@ namespace sqlpp
|
||||
static_assert(required_tables_of<cross_join_t>::size::value == 0, "joined tables must not depend on other tables");
|
||||
|
||||
template <typename Expr>
|
||||
auto on(Expr expr) -> join_t<cross_join_t, on_t<void, Expr>>
|
||||
auto on(Expr expr) -> typename std::conditional<check_join_on_t<cross_join_t, Expr>::value,
|
||||
join_t<cross_join_t, on_t<Expr>>,
|
||||
bad_statement>::type
|
||||
{
|
||||
static_assert(is_expression_t<Expr>::value, "argument is not an expression in on()");
|
||||
check_join_on_t<cross_join_t, Expr>::_();
|
||||
|
||||
static_assert(is_boolean_t<Expr>::value, "argument is not a boolean expression in on()");
|
||||
|
||||
return {*this, {expr, {}}};
|
||||
return {*this, {expr}};
|
||||
}
|
||||
|
||||
auto unconditionally() -> join_t<cross_join_t, on_t<void, unconditional_t>>
|
||||
auto unconditionally() -> join_t<cross_join_t, on_t<unconditional_t>>
|
||||
{
|
||||
return {*this, {}};
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2016, Roland Bock
|
||||
* Copyright (c) 2016-2016, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
@ -32,6 +32,32 @@
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_dynamic_join_consist_of_cross_join_and_on_t,
|
||||
"dynamic join has to consist of a dynamic cross_join and a join condition");
|
||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_dynamic_join_no_table_dependencies_t,
|
||||
"dynamically joined tables must not depend on other tables");
|
||||
|
||||
template <typename CrossJoin, typename On>
|
||||
struct check_dynamic_join
|
||||
{
|
||||
using type = static_combined_check_t<
|
||||
static_check_t<is_dynamic_cross_join_t<CrossJoin>::value, assert_dynamic_join_consist_of_cross_join_and_on_t>,
|
||||
static_check_t<is_on_t<On>::value, assert_dynamic_join_consist_of_cross_join_and_on_t>,
|
||||
static_check_t<required_tables_of<CrossJoin>::size::value == 0, assert_dynamic_join_no_table_dependencies_t>>;
|
||||
};
|
||||
|
||||
template <typename CrossJoin, typename On>
|
||||
using check_dynamic_join_t = typename check_dynamic_join<CrossJoin, On>::type;
|
||||
|
||||
template <typename CrossJoin, typename Expr>
|
||||
struct check_dynamic_join_on
|
||||
{
|
||||
using type = static_combined_check_t<check_on_t<Expr>, check_dynamic_join_t<CrossJoin, on_t<Expr>>>;
|
||||
};
|
||||
|
||||
template <typename CrossJoin, typename Expr>
|
||||
using check_dynamic_join_on_t = typename check_dynamic_join_on<CrossJoin, Expr>::type;
|
||||
|
||||
template <typename CrossJoin, typename On>
|
||||
struct dynamic_join_t;
|
||||
|
||||
@ -49,15 +75,16 @@ namespace sqlpp
|
||||
"joined tables must not depend on other tables");
|
||||
|
||||
template <typename Expr>
|
||||
auto on(Expr expr) -> dynamic_join_t<dynamic_cross_join_t, on_t<void, Expr>>
|
||||
auto on(Expr expr) -> typename std::conditional<check_dynamic_join_on_t<dynamic_cross_join_t, Expr>::value,
|
||||
dynamic_join_t<dynamic_cross_join_t, on_t<Expr>>,
|
||||
bad_statement>::type
|
||||
{
|
||||
static_assert(is_expression_t<Expr>::value, "argument is not a boolean expression in on()");
|
||||
static_assert(is_boolean_t<Expr>::value, "argument is not a boolean expression in on()");
|
||||
check_dynamic_join_on_t<dynamic_cross_join_t, Expr>::_();
|
||||
|
||||
return {*this, {expr, {}}};
|
||||
return {*this, {expr}};
|
||||
}
|
||||
|
||||
auto unconditionally() -> dynamic_join_t<dynamic_cross_join_t, on_t<void, unconditional_t>>
|
||||
auto unconditionally() -> dynamic_join_t<dynamic_cross_join_t, on_t<unconditional_t>>
|
||||
{
|
||||
return {*this, {}};
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2015, Roland Bock
|
||||
* Copyright (c) 2016-2016, Roland Bock
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
|
@ -42,13 +42,6 @@ namespace sqlpp
|
||||
using _provided_tables = provided_tables_of<CrossJoin>;
|
||||
using _required_tables = detail::make_difference_set_t<required_tables_of<On>, _provided_tables>;
|
||||
|
||||
static_assert(is_cross_join_t<CrossJoin>::value, "lhs argument for join() has to be a table or join");
|
||||
static_assert(is_on_t<On>::value, "invalid on expression in join().on()");
|
||||
|
||||
static_assert(required_tables_of<CrossJoin>::size::value == 0, "joined tables must not depend on other tables");
|
||||
static_assert(detail::is_subset_of<required_tables_of<On>, provided_tables_of<CrossJoin>>::value,
|
||||
"on() condition must not depend on other tables");
|
||||
|
||||
template <typename T>
|
||||
auto join(T t) const -> decltype(::sqlpp::join(*this, t))
|
||||
{
|
||||
|
@ -34,54 +34,40 @@
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
template <typename Database, typename Expression>
|
||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_on_is_expression_t, "argument is not an expression in on()");
|
||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_on_is_boolean_expression_t, "argument is not a boolean expression in on()");
|
||||
|
||||
template <typename Expr>
|
||||
struct check_on
|
||||
{
|
||||
using type = static_combined_check_t<static_check_t<is_expression_t<Expr>::value, assert_on_is_expression_t>,
|
||||
static_check_t<is_boolean_t<Expr>::value, assert_on_is_boolean_expression_t>>;
|
||||
};
|
||||
|
||||
template <typename Expr>
|
||||
using check_on_t = typename check_on<Expr>::type;
|
||||
|
||||
template <typename Expression>
|
||||
struct on_t
|
||||
{
|
||||
using _traits = make_traits<no_value_t, tag::is_on>;
|
||||
using _nodes = detail::type_vector<Expression>;
|
||||
|
||||
using _is_dynamic = is_database<Database>;
|
||||
|
||||
template <typename Expr>
|
||||
void add(Expr expr)
|
||||
{
|
||||
static_assert(_is_dynamic::value, "on::add() must not be called for static on()");
|
||||
static_assert(is_expression_t<Expr>::value, "invalid expression argument in on::add()");
|
||||
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Expr>;
|
||||
_serialize_check::_();
|
||||
|
||||
using ok = logic::all_t<_is_dynamic::value, is_expression_t<Expr>::value, _serialize_check::type::value>;
|
||||
|
||||
_add_impl(expr, ok()); // dispatch to prevent compile messages after the static_assert
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Expr>
|
||||
void _add_impl(Expr expr, const std::true_type&)
|
||||
{
|
||||
return _dynamic_expressions.emplace_back(expr);
|
||||
}
|
||||
|
||||
template <typename Expr>
|
||||
void _add_impl(Expr expr, const std::false_type&);
|
||||
|
||||
public:
|
||||
Expression _expression;
|
||||
interpretable_list_t<Database> _dynamic_expressions;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct on_t<void, unconditional_t>
|
||||
struct on_t<unconditional_t>
|
||||
{
|
||||
using _traits = make_traits<no_value_t, tag::is_on>;
|
||||
using _nodes = detail::type_vector<>;
|
||||
};
|
||||
|
||||
template <typename Context>
|
||||
struct serializer_t<Context, on_t<void, unconditional_t>>
|
||||
struct serializer_t<Context, on_t<unconditional_t>>
|
||||
{
|
||||
using _serialize_check = consistent_t;
|
||||
using T = on_t<void, unconditional_t>;
|
||||
using T = on_t<unconditional_t>;
|
||||
|
||||
static Context& _(const T&, Context& context)
|
||||
{
|
||||
@ -89,21 +75,16 @@ namespace sqlpp
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Context, typename Database, typename... Expressions>
|
||||
struct serializer_t<Context, on_t<Database, Expressions...>>
|
||||
template <typename Context, typename Expression>
|
||||
struct serializer_t<Context, on_t<Expression>>
|
||||
{
|
||||
using _serialize_check = serialize_check_of<Context, Expressions...>;
|
||||
using T = on_t<Database, Expressions...>;
|
||||
using _serialize_check = serialize_check_of<Context, Expression>;
|
||||
using T = on_t<Expression>;
|
||||
|
||||
static Context& _(const T& t, Context& context)
|
||||
{
|
||||
if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty())
|
||||
return context;
|
||||
context << " ON (";
|
||||
serialize(t._expression, context);
|
||||
if (not t._dynamic_expressions.empty())
|
||||
context << " AND ";
|
||||
interpret_list(t._dynamic_expressions, " AND ", context);
|
||||
context << " )";
|
||||
return context;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user