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>
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 };
}

View File

@@ -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
{

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<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);
}

View File

@@ -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 };
}

View File

@@ -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
{