0
0
mirror of https://github.com/rbock/sqlpp11.git synced 2024-11-16 04:47:18 +08:00

Improved checks for selects being usable as value or table

This commit is contained in:
rbock 2014-04-18 19:59:35 +02:00
parent bbae5e89e9
commit f4ec88c83d
7 changed files with 60 additions and 26 deletions

View File

@ -37,9 +37,6 @@ namespace sqlpp
template<typename Select> template<typename Select>
struct any_t struct any_t
{ {
static_assert(is_select_t<Select>::value, "any() requires a single column select expression as argument");
static_assert(is_value_t<Select>::value, "any() requires a single column select expression as argument");
struct _value_type: public Select::_value_type::_base_value_type struct _value_type: public Select::_value_type::_base_value_type
{ {
using _is_expression = std::false_type; using _is_expression = std::false_type;
@ -94,6 +91,7 @@ namespace sqlpp
auto any(T t) -> typename vendor::any_t<vendor::wrap_operand_t<T>> auto any(T t) -> typename vendor::any_t<vendor::wrap_operand_t<T>>
{ {
static_assert(is_select_t<vendor::wrap_operand_t<T>>::value, "any() requires a select expression as argument"); static_assert(is_select_t<vendor::wrap_operand_t<T>>::value, "any() requires a select expression as argument");
static_assert(is_value_t<vendor::wrap_operand_t<T>>::value, "any() requires a single column select expression as argument");
return { t }; return { t };
} }

View File

@ -36,6 +36,8 @@ namespace sqlpp
template<typename T> template<typename T>
using _constraint = std::false_type; using _constraint = std::false_type;
using _base_value_type = no_value_t;
template<typename T> template<typename T>
struct _is_valid_operand struct _is_valid_operand
{ {

View File

@ -108,8 +108,36 @@ namespace sqlpp
static_assert(is_noop_t<ColumnList>::value or sqlpp::is_select_column_list_t<ColumnList>::value, "column list of select is neither naught nor a valid column list"); static_assert(is_noop_t<ColumnList>::value or sqlpp::is_select_column_list_t<ColumnList>::value, "column list of select is neither naught nor a valid column list");
static_assert(is_noop_t<From>::value or sqlpp::is_from_t<From>::value, "from() part of select is neither naught nor a valid from()"); static_assert(is_noop_t<From>::value or sqlpp::is_from_t<From>::value, "from() part of select is neither naught nor a valid from()");
using _required_tables =
detail::make_joined_set_t<
typename _flag_list_t::_table_set,
typename _column_list_t::_table_set,
typename _where_t::_table_set,
typename _group_by_t::_table_set,
typename _having_t::_table_set,
typename _order_by_t::_table_set,
typename _limit_t::_table_set,
typename _offset_t::_table_set
>;
// The tables not covered by the from.
using _table_set = detail::make_difference_set_t<
_required_tables,
typename _from_t::_table_set // Hint: extra_tables are not used here because they are just helpers for dynamic .add_*() methods
>;
// A select can be used as a pseudo table if
// - at least one column is selected
// - the select is complete (leaks no tables)
using _can_be_used_as_table = typename std::conditional<
is_select_column_list_t<_column_list_t>::value and _table_set::size::value == 0,
std::true_type,
std::false_type
>::type;
using _value_type = typename std::conditional< using _value_type = typename std::conditional<
_column_list_t::_table_set::size::value ? sqlpp::is_from_t<From>::value : true, is_select_column_list_t<_column_list_t>::value and is_subset_of<typename _column_list_t::_table_set, typename _from_t::_table_set>::value,
typename ColumnList::_value_type, typename ColumnList::_value_type,
no_value_t // If something is selected that requires a table, then we require a from for this to be a value no_value_t // If something is selected that requires a table, then we require a from for this to be a value
>::type; >::type;
@ -140,18 +168,7 @@ namespace sqlpp
using _parameter_tuple_t = std::tuple<Policies...>; using _parameter_tuple_t = std::tuple<Policies...>;
using _parameter_list_t = typename make_parameter_list_t<select_t>::type; using _parameter_list_t = typename make_parameter_list_t<select_t>::type;
using _table_set = detail::make_difference_set_t< using _table_set = typename _policies_t::_table_set;
typename _from_t::_table_set,
detail::make_joined_set_t< // Hint: extra_tables are not used here because they are just helpers for dynamic .add_*() methods
typename _flag_list_t::_table_set,
typename _column_list_t::_table_set,
typename _where_t::_table_set,
typename _group_by_t::_table_set,
typename _having_t::_table_set,
typename _order_by_t::_table_set,
typename _limit_t::_table_set,
typename _offset_t::_table_set
>>;
template<typename Database> template<typename Database>
using _result_row_t = typename _column_list_t::template _result_row_t<Database>; using _result_row_t = typename _column_list_t::template _result_row_t<Database>;
@ -197,6 +214,7 @@ namespace sqlpp
template<typename AliasProvider> template<typename AliasProvider>
typename _pseudo_table_t<AliasProvider>::alias as(const AliasProvider& aliasProvider) const typename _pseudo_table_t<AliasProvider>::alias as(const AliasProvider& aliasProvider) const
{ {
static_assert(_policies_t::_can_be_used_as_table::value, "select cannot be used as table, incomplete from()");
return typename _pseudo_table_t<AliasProvider>::table( return typename _pseudo_table_t<AliasProvider>::table(
*this).as(aliasProvider); *this).as(aliasProvider);
} }

View File

@ -37,9 +37,6 @@ namespace sqlpp
template<typename Select> template<typename Select>
struct some_t struct some_t
{ {
static_assert(is_select_t<Select>::value, "some() requires a single column select expression as argument");
static_assert(is_value_t<Select>::value, "some() requires a single column select expression as argument");
struct _value_type: public Select::_value_type::_base_value_type struct _value_type: public Select::_value_type::_base_value_type
{ {
using _is_expression = std::false_type; using _is_expression = std::false_type;
@ -93,7 +90,8 @@ namespace sqlpp
template<typename T> template<typename T>
auto some(T t) -> typename vendor::some_t<vendor::wrap_operand_t<T>> auto some(T t) -> typename vendor::some_t<vendor::wrap_operand_t<T>>
{ {
static_assert(is_select_t<vendor::wrap_operand_t<T>>::value, "some() requires a select expression as argument"); static_assert(is_select_t<vendor::wrap_operand_t<T>>::value, "some() requires a single column select expression as argument");
static_assert(is_value_t<vendor::wrap_operand_t<T>>::value, "some() requires a single column select expression as argument");
return { t }; return { t };
} }

View File

@ -42,7 +42,7 @@ namespace sqlpp
{ {
//FIXME: Need to add join functionality //FIXME: Need to add join functionality
using _is_table = std::true_type; using _is_table = std::true_type;
using _table_set = detail::type_set<table_alias_t>; using _table_set = detail::type_set<AliasProvider>;
struct _value_type: Table::_value_type struct _value_type: Table::_value_type
{ {

View File

@ -185,11 +185,13 @@ int main()
static_assert(not sqlpp::is_text_t<TT>::value, "type requirement"); static_assert(not sqlpp::is_text_t<TT>::value, "type requirement");
} }
// Test any // Test any
{ {
using TI = decltype(any(select(t.alpha).from(t))); using TI = decltype(any(select(t.alpha).from(t)));
using TT = decltype(any(select(t.beta).from(t))); using TT = decltype(any(select(t.beta).from(t)));
using TF = decltype(any(select(f.omega).from(t))); using TF = decltype(any(select(f.omega).from(f)));
static_assert(not sqlpp::is_named_expression_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_named_expression_t<TI>::value, "type requirement");
static_assert(sqlpp::is_multi_expression_t<TI>::value, "type requirement"); static_assert(sqlpp::is_multi_expression_t<TI>::value, "type requirement");
static_assert(sqlpp::is_numeric_t<TI>::value, "type requirement"); static_assert(sqlpp::is_numeric_t<TI>::value, "type requirement");
@ -212,7 +214,7 @@ int main()
{ {
using TI = decltype(some(select(t.alpha).from(t))); using TI = decltype(some(select(t.alpha).from(t)));
using TT = decltype(some(select(t.beta).from(t))); using TT = decltype(some(select(t.beta).from(t)));
using TF = decltype(some(select(f.omega).from(t))); using TF = decltype(some(select(f.omega).from(f)));
static_assert(not sqlpp::is_named_expression_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_named_expression_t<TI>::value, "type requirement");
static_assert(sqlpp::is_multi_expression_t<TI>::value, "type requirement"); static_assert(sqlpp::is_multi_expression_t<TI>::value, "type requirement");
static_assert(sqlpp::is_numeric_t<TI>::value, "type requirement"); static_assert(sqlpp::is_numeric_t<TI>::value, "type requirement");

View File

@ -357,12 +357,27 @@ int main()
static_assert(sqlpp::is_named_expression_t<decltype(t.alpha)>::value, "alpha should be a named expression"); static_assert(sqlpp::is_named_expression_t<decltype(t.alpha)>::value, "alpha should be a named expression");
static_assert(sqlpp::is_named_expression_t<decltype(t.alpha.as(alias::a))>::value, "an alias of alpha should be a named expression"); static_assert(sqlpp::is_named_expression_t<decltype(t.alpha.as(alias::a))>::value, "an alias of alpha should be a named expression");
static_assert(sqlpp::is_alias_t<decltype(t.alpha.as(alias::a))>::value, "an alias of alpha should be an alias"); static_assert(sqlpp::is_alias_t<decltype(t.alpha.as(alias::a))>::value, "an alias of alpha should be an alias");
auto z = select(t.alpha).from(t) == 7; auto z = select(t.alpha).from(t) == 7;
auto l = t.as(alias::left); auto l = t.as(alias::left);
auto r = select(t.gamma.as(alias::a)).from(t).where(t.gamma == true).as(alias::right); auto r = select(t.gamma.as(alias::a)).from(t).where(t.gamma == true).as(alias::right);
using R = decltype(r);
static_assert(sqlpp::is_boolean_t<decltype(select(t.gamma).from(t))>::value, "select(bool) has to be a bool"); static_assert(sqlpp::is_boolean_t<decltype(select(t.gamma).from(t))>::value, "select(bool) has to be a bool");
serialize(sqlpp::select().flags(sqlpp::distinct, sqlpp::straight_join).columns(l.alpha, l.beta, select(r.a).from(r)) auto s = select(r.a).from(r);
.from(l, r) using RA = decltype(r.a);
using S = decltype(s);
using SCL = typename S::_column_list_t;
using SF = typename S::_from_t;
static_assert(sqlpp::is_select_column_list_t<SCL>::value, "no column list");
static_assert(sqlpp::is_from_t<SF>::value, "no from list");
using SCL_T = typename SCL::_table_set;
using SF_T = typename SF::_table_set;
static_assert(SCL_T::size::value == 1, "unexpected table_set in column_list");
static_assert(SF_T::size::value == 1, "unexpected table_set in from");
static_assert(std::is_same<SCL_T, SF_T>::value, "should be the same");
static_assert(sqlpp::is_boolean_t<decltype(select(r.a).from(r))>::value, "select(bool) has to be a bool");
auto s1 = sqlpp::select().flags(sqlpp::distinct, sqlpp::straight_join).columns(l.alpha, l.beta, select(r.a).from(r))
.from(r,t,l)
.where(t.beta == "hello world" and select(t.gamma).from(t))// .as(alias::right)) .where(t.beta == "hello world" and select(t.gamma).from(t))// .as(alias::right))
.group_by(l.gamma, r.a) .group_by(l.gamma, r.a)
.having(r.a != true) .having(r.a != true)
@ -370,7 +385,8 @@ int main()
.limit(17) .limit(17)
.offset(3) .offset(3)
.as(alias::a) .as(alias::a)
, printer).str(); ;
return 0; return 0;
} }