mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-15 20:31:16 +08:00
Improved checks for selects being usable as value or table
This commit is contained in:
parent
bbae5e89e9
commit
f4ec88c83d
@ -37,9 +37,6 @@ namespace sqlpp
|
||||
template<typename Select>
|
||||
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
|
||||
{
|
||||
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>>
|
||||
{
|
||||
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 };
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,8 @@ namespace sqlpp
|
||||
template<typename T>
|
||||
using _constraint = std::false_type;
|
||||
|
||||
using _base_value_type = no_value_t;
|
||||
|
||||
template<typename T>
|
||||
struct _is_valid_operand
|
||||
{
|
||||
|
@ -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<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<
|
||||
_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,
|
||||
no_value_t // If something is selected that requires a table, then we require a from for this to be a value
|
||||
>::type;
|
||||
@ -140,18 +168,7 @@ namespace sqlpp
|
||||
|
||||
using _parameter_tuple_t = std::tuple<Policies...>;
|
||||
using _parameter_list_t = typename make_parameter_list_t<select_t>::type;
|
||||
using _table_set = detail::make_difference_set_t<
|
||||
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
|
||||
>>;
|
||||
using _table_set = typename _policies_t::_table_set;
|
||||
|
||||
template<typename Database>
|
||||
using _result_row_t = typename _column_list_t::template _result_row_t<Database>;
|
||||
@ -197,6 +214,7 @@ namespace sqlpp
|
||||
template<typename AliasProvider>
|
||||
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(
|
||||
*this).as(aliasProvider);
|
||||
}
|
||||
|
@ -37,9 +37,6 @@ namespace sqlpp
|
||||
template<typename Select>
|
||||
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
|
||||
{
|
||||
using _is_expression = std::false_type;
|
||||
@ -93,7 +90,8 @@ namespace sqlpp
|
||||
template<typename 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 };
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ namespace sqlpp
|
||||
{
|
||||
//FIXME: Need to add join functionality
|
||||
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
|
||||
{
|
||||
|
@ -185,11 +185,13 @@ int main()
|
||||
static_assert(not sqlpp::is_text_t<TT>::value, "type requirement");
|
||||
}
|
||||
|
||||
|
||||
// Test any
|
||||
{
|
||||
|
||||
using TI = decltype(any(select(t.alpha).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(sqlpp::is_multi_expression_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 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(sqlpp::is_multi_expression_t<TI>::value, "type requirement");
|
||||
static_assert(sqlpp::is_numeric_t<TI>::value, "type requirement");
|
||||
|
@ -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.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");
|
||||
|
||||
auto z = select(t.alpha).from(t) == 7;
|
||||
auto l = t.as(alias::left);
|
||||
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");
|
||||
serialize(sqlpp::select().flags(sqlpp::distinct, sqlpp::straight_join).columns(l.alpha, l.beta, select(r.a).from(r))
|
||||
.from(l, r)
|
||||
auto s = select(r.a).from(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))
|
||||
.group_by(l.gamma, r.a)
|
||||
.having(r.a != true)
|
||||
@ -370,7 +385,8 @@ int main()
|
||||
.limit(17)
|
||||
.offset(3)
|
||||
.as(alias::a)
|
||||
, printer).str();
|
||||
;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user