mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-16 04:47:18 +08:00
Prepared for advanced table checks
This commit is contained in:
parent
6e7d05d6db
commit
9349f56d68
@ -34,7 +34,7 @@
|
||||
#include <sqlpp11/core/default_value.h>
|
||||
#include <sqlpp11/core/type_traits.h>
|
||||
#include <sqlpp11/core/wrong.h>
|
||||
#include <sqlpp11/core/detail/type_set.h>
|
||||
#include <sqlpp11/core/detail/type_vector.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
@ -104,13 +104,18 @@ namespace sqlpp
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Table>
|
||||
struct table_t;
|
||||
template <typename Table>
|
||||
struct table_t;
|
||||
|
||||
template<typename Table, typename ColumnSpec>
|
||||
struct required_tables_of<column_t<Table, ColumnSpec>>
|
||||
{
|
||||
using type = detail::type_set<table_t<Table>>;
|
||||
using type = detail::type_vector<table_t<Table>>;
|
||||
};
|
||||
|
||||
template <typename Table, typename ColumnSpec>
|
||||
struct required_static_tables_of<column_t<Table, ColumnSpec>> : public required_tables_of<column_t<Table, ColumnSpec>>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Context, typename Table, typename ColumnSpec>
|
||||
|
@ -67,18 +67,36 @@ namespace sqlpp
|
||||
#warning: We should mix dynamic and optional into the provided_tables_of (instead of having separate traits for each).
|
||||
#warning: it might be great to search for missing tables and return something like `missing_table_for<column_t<SomeSpec>>`.
|
||||
|
||||
template<typename T>
|
||||
struct is_dynamic : public std::false_type {};
|
||||
template<typename T>
|
||||
struct is_dynamic<dynamic_t<T>> : public std::true_type {};
|
||||
|
||||
template <typename Lhs, typename JoinType, typename Rhs, typename Condition>
|
||||
struct provided_tables_of<join_t<Lhs, JoinType, Rhs, Condition>>
|
||||
{
|
||||
using type = detail::type_vector_cat_t<provided_tables_of_t<Lhs>, provided_tables_of_t<Rhs>>;
|
||||
};
|
||||
|
||||
template <typename Lhs, typename JoinType, typename Rhs, typename Condition>
|
||||
struct provided_static_tables_of<join_t<Lhs, JoinType, Rhs, Condition>>
|
||||
{
|
||||
using type = typename std::conditional<
|
||||
is_dynamic<Rhs>::value,
|
||||
provided_static_tables_of<Lhs>,
|
||||
detail::type_vector_cat_t<provided_static_tables_of<Lhs>, provided_static_tables_of<Rhs>>>::type;
|
||||
};
|
||||
|
||||
template <typename Lhs, typename JoinType, typename Rhs, typename Condition>
|
||||
struct provided_optional_tables_of<join_t<Lhs, JoinType, Rhs, Condition>>
|
||||
{
|
||||
using type = typename std::conditional<
|
||||
std::is_same<JoinType, left_outer_join_t>::value,
|
||||
sqlpp::detail::type_set<Rhs>,
|
||||
typename std::conditional<
|
||||
std::is_same<JoinType, right_outer_join_t>::value,
|
||||
sqlpp::detail::type_set<Lhs>,
|
||||
typename std::conditional<std::is_same<JoinType, full_outer_join_t>::value,
|
||||
detail::make_joined_set_t<provided_tables_of_t<Lhs>, provided_tables_of_t<Rhs>>,
|
||||
detail::type_set<>>::type>::type>::type;
|
||||
using type = detail::type_vector_cat_t<
|
||||
typename std::conditional<detail::type_vector<right_outer_join_t, full_outer_join_t>::contains<JoinType>(),
|
||||
provided_tables_of_t<Lhs>,
|
||||
detail::type_vector<>>::type,
|
||||
typename std::conditional<detail::type_vector<left_outer_join_t, full_outer_join_t>::contains<JoinType>(),
|
||||
provided_tables_of_t<Rhs>,
|
||||
detail::type_vector<>>::type>;
|
||||
};
|
||||
|
||||
template <typename Lhs, typename JoinType, typename Rhs, typename Condition>
|
||||
@ -124,8 +142,36 @@ namespace sqlpp
|
||||
|
||||
#warning: Verify that the Expr does not require tables other than Lhs, Rhs
|
||||
//and detail::make_joined_set_t<provided_tables_of_t<Lhs>, provided_tables_of_t<Rhs>>::is_superset_of<required_tables_of_t<Expr>::value
|
||||
template <typename Expr, typename StaticTableTypeVector, typename AllTableTypeVector>
|
||||
struct are_table_requirements_satisfied
|
||||
: std::integral_constant<bool,
|
||||
StaticTableTypeVector::contains_all(required_static_tables_of_t<Expr>{}) and
|
||||
AllTableTypeVector::contains_all(required_tables_of_t<Expr>{})>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Lhs, typename Rhs, typename Expr>
|
||||
using check_on_args = sqlpp::enable_if_t<sqlpp::is_boolean<Expr>::value>;
|
||||
struct are_join_table_requirements_satisfied
|
||||
: public std::integral_constant<
|
||||
bool,
|
||||
is_dynamic<Rhs>::value ?
|
||||
// In case of a dynamic join, we can use all tables in the ON expr.
|
||||
are_table_requirements_satisfied<
|
||||
Expr,
|
||||
provided_tables_of_t<join_t<Lhs, cross_join_t, Rhs, unconditional_t>>,
|
||||
provided_tables_of_t<join_t<Lhs, cross_join_t, Rhs, unconditional_t>>>::value
|
||||
:
|
||||
// In case of a static join, we can use static tables in the static part of the ON
|
||||
// expression and dynamic tables in any potential dynamic part of the expression.
|
||||
are_table_requirements_satisfied<
|
||||
Expr,
|
||||
provided_static_tables_of_t<join_t<Lhs, cross_join_t, Rhs, unconditional_t>>,
|
||||
provided_tables_of_t<join_t<Lhs, cross_join_t, Rhs, unconditional_t>>>::value>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Lhs, typename Rhs, typename Expr>
|
||||
using check_on_args = sqlpp::enable_if_t<sqlpp::is_boolean<Expr>::value and are_join_table_requirements_satisfied<Lhs, Rhs, Expr>::value>;
|
||||
|
||||
template <typename Lhs, typename JoinType, typename Rhs>
|
||||
struct pre_join_t
|
||||
@ -133,7 +179,7 @@ namespace sqlpp
|
||||
template <typename Expr, typename = check_on_args<Lhs, Rhs, Expr>>
|
||||
auto on(Expr expr) const -> join_t<Lhs, JoinType, Rhs, Expr>
|
||||
{
|
||||
return {_lhs, _rhs, std::move(expr)};
|
||||
return {_lhs, _rhs, std::move(expr)};
|
||||
}
|
||||
|
||||
Lhs _lhs;
|
||||
|
@ -69,6 +69,16 @@ namespace sqlpp
|
||||
using type = sqlpp::detail::type_set<table_t<TableSpec>>;
|
||||
};
|
||||
|
||||
template <typename TableSpec>
|
||||
struct provided_static_tables_of<table_t<TableSpec>> : public provided_tables_of<table_t<TableSpec>>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename TableSpec>
|
||||
struct provided_optional_tables_of<table_t<TableSpec>> : public provided_tables_of<table_t<TableSpec>>
|
||||
{
|
||||
};
|
||||
|
||||
template <typename Context, typename TableSpec>
|
||||
auto to_sql_string(Context& context, const table_t<TableSpec>& /*unused*/) -> std::string
|
||||
{
|
||||
|
@ -159,7 +159,7 @@ namespace sqlpp
|
||||
using _new_statement_t = new_statement_t<Check, Policies, no_where_t, T>;
|
||||
|
||||
using _consistency_check =
|
||||
typename std::conditional<WhereRequired and (Policies::_all_provided_tables::size::value > 0),
|
||||
typename std::conditional<WhereRequired and (Policies::_all_provided_tables::size() > 0),
|
||||
assert_where_or_unconditionally_called_t,
|
||||
consistent_t>::type;
|
||||
|
||||
|
@ -36,16 +36,26 @@ namespace sqlpp
|
||||
template <typename... T>
|
||||
struct type_vector
|
||||
{
|
||||
template<typename X>
|
||||
using contains = std::integral_constant<bool, ::sqlpp::logic::any<std::is_same<T, X>::value...>::value>;
|
||||
template <typename X>
|
||||
static constexpr bool contains()
|
||||
{
|
||||
return ::sqlpp::logic::any<std::is_same<T, X>::value...>::value;
|
||||
}
|
||||
|
||||
template <template <typename> class Transform>
|
||||
using transform = type_vector<typename Transform<T>::type...>;
|
||||
template <typename... X>
|
||||
static constexpr bool contains_all(type_vector<X...>)
|
||||
{
|
||||
return ::sqlpp::logic::all<contains<X>()...>::value;
|
||||
}
|
||||
|
||||
static constexpr bool size = sizeof...(T);
|
||||
static constexpr size_t size()
|
||||
{
|
||||
return sizeof...(T);
|
||||
}
|
||||
|
||||
static constexpr bool empty() {
|
||||
return size == 0;
|
||||
static constexpr bool empty()
|
||||
{
|
||||
return size() == 0;
|
||||
}
|
||||
};
|
||||
|
||||
@ -82,5 +92,17 @@ namespace sqlpp
|
||||
template <typename... T>
|
||||
using type_vector_cat_t = typename type_vector_cat_impl<T...>::type;
|
||||
|
||||
template <typename TypeVector, template <typename> class Transform>
|
||||
struct transform;
|
||||
|
||||
template <template <typename> class Transform, typename... T>
|
||||
struct transform<type_vector<T...>, Transform>
|
||||
{
|
||||
using type = type_vector<typename Transform<T>::type...>;
|
||||
};
|
||||
|
||||
template <typename TypeVector, template <typename> class Transform>
|
||||
using transform_t = typename transform<TypeVector, Transform>::type;
|
||||
|
||||
} // namespace detail
|
||||
} // namespace sqlpp
|
||||
|
@ -78,12 +78,15 @@ namespace sqlpp
|
||||
using _all_required_ctes = detail::make_joined_set_t<required_ctes_of<Policies>...>;
|
||||
using _all_provided_ctes = detail::make_joined_set_t<provided_ctes_of<Policies>...>;
|
||||
using _all_required_tables = detail::make_joined_set_t<required_tables_of_t<Policies>...>;
|
||||
using _all_provided_tables = detail::make_joined_set_t<provided_tables_of_t<Policies>...>;
|
||||
using _all_provided_outer_tables = detail::make_joined_set_t<provided_optional_tables_of_t<Policies>...>;
|
||||
using _all_provided_tables = detail::type_vector_cat_t<provided_tables_of_t<Policies>...>;
|
||||
//using _all_provided_outer_tables = detail::make_joined_set_t<provided_optional_tables_of_t<Policies>...>;
|
||||
using _all_provided_aggregates = detail::make_joined_set_t<provided_aggregates_of<Policies>...>;
|
||||
|
||||
#warning reactivate
|
||||
/*
|
||||
template <typename Expression>
|
||||
using _no_unknown_tables = detail::is_subset_of<required_tables_of_t<Expression>, _all_provided_tables>;
|
||||
*/
|
||||
|
||||
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2086629
|
||||
// template <typename... Expressions>
|
||||
@ -109,7 +112,7 @@ namespace sqlpp
|
||||
using any_t = logic::any<Predicate<Policies>::value...>;
|
||||
|
||||
// The tables not covered by the from.
|
||||
using _required_tables = detail::make_difference_set_t<_all_required_tables, _all_provided_tables>;
|
||||
//using _required_tables = detail::make_difference_set_t<_all_required_tables, _all_provided_tables>;
|
||||
|
||||
// The common table expressions not covered by the with.
|
||||
using _required_ctes = detail::make_difference_set_t<_all_required_ctes, _all_provided_ctes>;
|
||||
@ -125,7 +128,8 @@ namespace sqlpp
|
||||
// - the select is complete (leaks no table requirements or cte requirements)
|
||||
static constexpr bool _can_be_used_as_table()
|
||||
{
|
||||
return has_result_row_t<_statement_t>::value and _required_tables::size::value == 0 and
|
||||
#warning: reactivate
|
||||
return has_result_row_t<_statement_t>::value and /*_required_tables::size::value == 0 and*/
|
||||
_required_ctes::size::value == 0;
|
||||
}
|
||||
|
||||
@ -147,8 +151,9 @@ namespace sqlpp
|
||||
|
||||
using _cte_check =
|
||||
typename std::conditional<_required_ctes::size::value == 0, consistent_t, assert_no_unknown_ctes_t>::type;
|
||||
using _table_check =
|
||||
typename std::conditional<_required_tables::size::value == 0, consistent_t, assert_no_unknown_tables_t>::type;
|
||||
#warning: reactivate
|
||||
using _table_check = std::true_type;
|
||||
//typename std::conditional<_required_tables::size::value == 0, consistent_t, assert_no_unknown_tables_t>::type;
|
||||
using _parameter_check = typename std::
|
||||
conditional<_parameters::empty(), consistent_t, assert_no_parameters_t>::type;
|
||||
};
|
||||
@ -206,7 +211,7 @@ namespace sqlpp
|
||||
>;
|
||||
using _name_tag_of = name_tag_of<_result_type_provider>;
|
||||
using _nodes = detail::type_vector<_policies_t>;
|
||||
using _used_outer_tables = typename _policies_t::_all_provided_outer_tables;
|
||||
//using _used_outer_tables = typename _policies_t::_all_provided_outer_tables;
|
||||
|
||||
// Constructors
|
||||
statement_t() = default;
|
||||
|
@ -45,12 +45,27 @@ namespace sqlpp
|
||||
template<typename... T>
|
||||
struct required_tables_of<detail::type_vector<T...>>
|
||||
{
|
||||
using type = detail::make_joined_set_t<typename required_tables_of<T>::type...>;
|
||||
using type = detail::type_vector_cat_t<typename required_tables_of<T>::type...>;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using required_tables_of_t = typename required_tables_of<T>::type;
|
||||
|
||||
template<typename T>
|
||||
struct required_static_tables_of
|
||||
{
|
||||
using type = typename required_static_tables_of<nodes_of_t<T>>::type;
|
||||
};
|
||||
|
||||
template<typename... T>
|
||||
struct required_static_tables_of<detail::type_vector<T...>>
|
||||
{
|
||||
using type = detail::type_vector_cat_t<typename required_static_tables_of<T>::type...>;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using required_static_tables_of_t = typename required_static_tables_of<T>::type;
|
||||
|
||||
#warning: need type tests...
|
||||
//static_assert(required_tables_of_t<int>::size::value == 0, "");
|
||||
|
||||
@ -66,16 +81,27 @@ namespace sqlpp
|
||||
template <typename... T>
|
||||
struct provided_tables_of<detail::type_vector<T...>>
|
||||
{
|
||||
using type = detail::make_joined_set_t<typename provided_tables_of<T>::type...>;
|
||||
using type = detail::type_vector_cat_t<typename provided_tables_of<T>::type...>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using provided_tables_of_t = typename provided_tables_of<T>::type;
|
||||
|
||||
static_assert(provided_tables_of_t<int>::size::value == 0, "");
|
||||
template <typename T>
|
||||
struct provided_static_tables_of
|
||||
{
|
||||
using type = typename provided_static_tables_of<nodes_of_t<T>>::type;
|
||||
};
|
||||
|
||||
template <typename... T>
|
||||
struct provided_static_tables_of<detail::type_vector<T...>>
|
||||
{
|
||||
using type = detail::type_vector_cat_t<typename provided_static_tables_of<T>::type...>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using provided_static_tables_of_t = typename provided_static_tables_of<T>::type;
|
||||
|
||||
// provided_optional_tables_of is similar to provided_tables_of but only references the tables that have optional
|
||||
// rows in outer joins (e.g. the right hand side table in a LEFT OUTER JOIN).
|
||||
template <typename T>
|
||||
struct provided_optional_tables_of
|
||||
{
|
||||
@ -85,11 +111,13 @@ namespace sqlpp
|
||||
template <typename... T>
|
||||
struct provided_optional_tables_of<detail::type_vector<T...>>
|
||||
{
|
||||
using type = detail::make_joined_set_t<typename provided_optional_tables_of<T>::type...>;
|
||||
using type = detail::type_vector_cat_t<typename provided_optional_tables_of<T>::type...>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using provided_optional_tables_of_t = typename provided_optional_tables_of<T>::type;
|
||||
|
||||
static_assert(provided_tables_of_t<int>::empty(), "");
|
||||
|
||||
} // namespace sqlpp
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user