mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-15 20:31:16 +08:00
Added static_assert tests for dynamic from.add()
This commit is contained in:
parent
dec3f5b3df
commit
712c79cb8a
@ -58,6 +58,7 @@ namespace sqlpp
|
||||
};
|
||||
|
||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_from_add_dynamic, "from::add() requires a dynamic_from");
|
||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_from_add_not_dynamic_pre_join, "join condition missing");
|
||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_from_add_dynamic_join, "from::add(X) requires X to be a dynamic join");
|
||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_from_add_unique_names,
|
||||
"from::add() must not add table names already used in from");
|
||||
@ -66,44 +67,48 @@ namespace sqlpp
|
||||
"tables not statically known, use "
|
||||
"without_table_check() to express the intent");
|
||||
|
||||
template <typename From, typename DynamicJoin>
|
||||
struct check_from_add
|
||||
{
|
||||
using _known_tables = provided_tables_of<typename From::_table_t>; // Hint: Joins contain more than one table
|
||||
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/feedback/details/2173198
|
||||
// using _known_table_names = detail::transform_set_t<name_of, _known_tables>;
|
||||
using _known_table_names = detail::make_name_of_set_t<_known_tables>;
|
||||
using _joined_tables = provided_tables_of<DynamicJoin>;
|
||||
using _joined_table_names = detail::make_name_of_set_t<_joined_tables>;
|
||||
using _required_tables = required_tables_of<DynamicJoin>;
|
||||
using type = static_combined_check_t<
|
||||
static_check_t<From::_is_dynamic::value, assert_from_add_dynamic>,
|
||||
static_check_t<not is_dynamic_pre_join_t<DynamicJoin>::value, assert_from_add_not_dynamic_pre_join>,
|
||||
static_check_t<is_dynamic_join_t<DynamicJoin>::value, assert_from_add_dynamic_join>,
|
||||
static_check_t<detail::is_disjunct_from<_joined_table_names, _known_table_names>::value,
|
||||
assert_from_add_unique_names>,
|
||||
static_check_t<detail::is_subset_of<_required_tables, _known_tables>::value,
|
||||
assert_from_add_no_required_tables>,
|
||||
sqlpp::serialize_check_t<serializer_context_of<typename From::_database_t>, DynamicJoin>>;
|
||||
};
|
||||
|
||||
template <typename From, typename DynamicJoin>
|
||||
using check_from_add_t = typename check_from_add<From, DynamicJoin>::type;
|
||||
|
||||
// FROM
|
||||
template <typename Database, typename Table>
|
||||
struct from_t
|
||||
{
|
||||
using _traits = make_traits<no_value_t, tag::is_from>;
|
||||
using _nodes = detail::type_vector<Table>;
|
||||
using _is_dynamic = is_database<Database>;
|
||||
|
||||
// Data
|
||||
using _data_t = from_data_t<Database, Table>;
|
||||
|
||||
template <typename DynamicJoin>
|
||||
struct check_add
|
||||
{
|
||||
using _known_tables = provided_tables_of<Table>; // Hint: Joins contain more than one table
|
||||
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/feedback/details/2173198
|
||||
// using _known_table_names = detail::transform_set_t<name_of, _known_tables>;
|
||||
using _known_table_names = detail::make_name_of_set_t<_known_tables>;
|
||||
using _joined_tables = provided_tables_of<DynamicJoin>;
|
||||
using _joined_table_names = detail::make_name_of_set_t<_joined_tables>;
|
||||
using _required_tables = required_tables_of<DynamicJoin>;
|
||||
using type = static_combined_check_t<
|
||||
static_check_t<_is_dynamic::value, assert_from_add_dynamic>,
|
||||
static_check_t<is_dynamic_join_t<DynamicJoin>::value, assert_from_add_dynamic_join>,
|
||||
static_check_t<detail::is_disjunct_from<_joined_table_names, _known_table_names>::value,
|
||||
assert_from_add_unique_names>,
|
||||
static_check_t<detail::is_subset_of<_required_tables, _known_tables>::value,
|
||||
assert_from_add_no_required_tables>,
|
||||
sqlpp::serialize_check_t<typename Database::_serializer_context_t, DynamicJoin>>;
|
||||
};
|
||||
|
||||
template <typename DynamicJoin>
|
||||
using check_add_t = typename check_add<DynamicJoin>::type;
|
||||
|
||||
// Member implementation with data and methods
|
||||
template <typename Policies>
|
||||
struct _impl_t
|
||||
{
|
||||
using _database_t = Database;
|
||||
using _is_dynamic = is_database<_database_t>;
|
||||
using _table_t = Table;
|
||||
|
||||
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069
|
||||
_impl_t() = default;
|
||||
_impl_t(const _data_t& data) : _data(data)
|
||||
@ -112,9 +117,9 @@ namespace sqlpp
|
||||
|
||||
template <typename DynamicJoin>
|
||||
auto add(DynamicJoin dynamicJoin) ->
|
||||
typename std::conditional<check_add_t<DynamicJoin>::value, void, bad_statement>::type
|
||||
typename std::conditional<check_from_add_t<_impl_t, DynamicJoin>::value, void, bad_statement>::type
|
||||
{
|
||||
using Check = check_add_t<DynamicJoin>;
|
||||
using Check = check_from_add_t<_impl_t, DynamicJoin>;
|
||||
Check::_();
|
||||
return _add_impl(dynamicJoin, Check{});
|
||||
}
|
||||
|
@ -502,6 +502,24 @@ namespace sqlpp
|
||||
|
||||
template <typename Statement, template <typename> class Predicate>
|
||||
using has_policy_t = typename has_policy_impl<Statement, Predicate>::type;
|
||||
|
||||
struct no_context_t
|
||||
{
|
||||
};
|
||||
template <typename Db, typename = void>
|
||||
struct serializer_context_of_impl
|
||||
{
|
||||
using type = no_context_t;
|
||||
};
|
||||
|
||||
template <typename Db>
|
||||
struct serializer_context_of_impl<Db, detail::void_t<typename Db::_serializer_context_t>>
|
||||
{
|
||||
using type = typename Db::_serializer_context_t;
|
||||
};
|
||||
|
||||
template <typename Db>
|
||||
using serializer_context_of = typename serializer_context_of_impl<Db>::type;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -111,9 +111,56 @@ namespace
|
||||
from_dynamic_check<sqlpp::assert_from_not_pre_join_t>(t.join(f));
|
||||
}
|
||||
|
||||
template <typename Assert, typename FromImpl, typename Expression>
|
||||
void dynamic_from_add_check(FromImpl from, const Expression& expression)
|
||||
{
|
||||
using CheckResult = sqlpp::check_from_add_t<FromImpl, Expression>;
|
||||
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
|
||||
print_type_on_error<CheckResult>(ExpectedCheckResult{});
|
||||
static_assert(ExpectedCheckResult::value, "Unexpected check result");
|
||||
|
||||
using ReturnType = decltype(from.add(expression));
|
||||
using ExpectedReturnType =
|
||||
sqlpp::logic::all_t<Assert::value xor std::is_same<ReturnType, sqlpp::bad_statement>::value>;
|
||||
print_type_on_error<ReturnType>(ExpectedReturnType{});
|
||||
static_assert(ExpectedReturnType::value, "Unexpected return type");
|
||||
}
|
||||
|
||||
void dynamic_from_add()
|
||||
{
|
||||
#warning : need to add tests for dynamic_from(xxx).add(yyy)
|
||||
static auto db = MockDb{};
|
||||
auto fromT = dynamic_select(db, t.alpha).dynamic_from(t).from;
|
||||
auto staticFrom = dynamic_select(db, t.alpha).from(t).from;
|
||||
const auto fa = f.as(sqlpp::alias::a);
|
||||
|
||||
// OK
|
||||
dynamic_from_add_check<sqlpp::consistent_t>(fromT, dynamic_join(f).on(t.alpha > f.omega));
|
||||
dynamic_from_add_check<sqlpp::consistent_t>(fromT, dynamic_inner_join(f).on(t.alpha > f.omega));
|
||||
dynamic_from_add_check<sqlpp::consistent_t>(fromT, dynamic_left_outer_join(f).on(t.alpha > f.omega));
|
||||
dynamic_from_add_check<sqlpp::consistent_t>(fromT, dynamic_right_outer_join(f).on(t.alpha > f.omega));
|
||||
dynamic_from_add_check<sqlpp::consistent_t>(fromT, dynamic_outer_join(f).on(t.alpha > f.omega));
|
||||
dynamic_from_add_check<sqlpp::consistent_t>(fromT, dynamic_cross_join(f));
|
||||
|
||||
// Try a bunch of non dynamic joins
|
||||
dynamic_from_add_check<sqlpp::assert_from_add_dynamic>(staticFrom, 7);
|
||||
|
||||
// Try a bunch of non dynamic joins
|
||||
dynamic_from_add_check<sqlpp::assert_from_add_dynamic_join>(fromT, 7);
|
||||
dynamic_from_add_check<sqlpp::assert_from_add_dynamic_join>(fromT, t.gamma);
|
||||
dynamic_from_add_check<sqlpp::assert_from_add_dynamic_join>(fromT, join(f, f.as(sqlpp::alias::a)));
|
||||
|
||||
// Try incomplete dynamic join
|
||||
dynamic_from_add_check<sqlpp::assert_from_add_not_dynamic_pre_join>(fromT, dynamic_join(f));
|
||||
|
||||
// Try joining the same table name
|
||||
dynamic_from_add_check<sqlpp::assert_from_add_unique_names>(fromT, dynamic_cross_join(t));
|
||||
dynamic_from_add_check<sqlpp::assert_from_add_unique_names>(fromT, dynamic_cross_join(f.as(t)));
|
||||
|
||||
// Try joining with a condition that requires other tables
|
||||
dynamic_from_add_check<sqlpp::assert_from_add_no_required_tables>(fromT, dynamic_join(f).on(t.alpha > fa.omega));
|
||||
|
||||
// If you really think you know what you are doing, use without_table_check
|
||||
dynamic_from_add_check<sqlpp::consistent_t>(fromT, dynamic_join(f).on(t.alpha > without_table_check(fa.omega)));
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user