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

select is now really a variadic template

It is getting ready for customization to reflect vendor specific
statement parts, e.g. order by in update and delete for mysql.
This commit is contained in:
rbock 2014-05-19 23:24:41 +02:00
parent 15e8ca742c
commit 6d91cf2163

View File

@ -52,60 +52,24 @@
namespace sqlpp namespace sqlpp
{ {
template<typename Db, template<typename Db, typename... Policies>
typename... Policies
>
struct select_t; struct select_t;
#warning STEPS: #warning STEPS:
#warning replace _select_column_t by _result_provider
#warning turn select into a variadic template (and have a empty_select which contains the default settings
#warning do the same with insert, update and remove #warning do the same with insert, update and remove
#warning deal with different return types in the connector (select could be a single value, update could be a range of rows) #warning deal with different return types in the connector (select could be a single value, update could be a range of rows)
namespace detail namespace detail
{ {
template<typename Db = void, template<typename Db = void, typename... Policies>
typename FlagList = vendor::no_select_flag_list_t,
typename ColumnList = vendor::no_select_column_list_t,
typename From = vendor::no_from_t,
typename ExtraTables = vendor::no_extra_tables_t,
typename Where = vendor::no_where_t,
typename GroupBy = vendor::no_group_by_t,
typename Having = vendor::no_having_t,
typename OrderBy = vendor::no_order_by_t,
typename Limit = vendor::no_limit_t,
typename Offset = vendor::no_offset_t
>
struct select_policies_t struct select_policies_t
{ {
using _database_t = Db; using _database_t = Db;
using _flag_list_t = FlagList; using _statement_t = select_t<Db, Policies...>;
using _column_list_t = ColumnList;
using _from_t = From;
using _extra_tables_t = ExtraTables;
using _where_t = Where;
using _group_by_t = GroupBy;
using _having_t = Having;
using _order_by_t = OrderBy;
using _limit_t = Limit;
using _offset_t = Offset;
using _statement_t = select_t<Db, FlagList, ColumnList, From, ExtraTables, Where, GroupBy, Having, OrderBy, Limit, Offset>; struct _methods_t: public Policies::template _methods_t<select_policies_t>...
struct _methods_t:
public _flag_list_t::template _methods_t<select_policies_t>,
public _column_list_t::template _methods_t<select_policies_t>,
public _from_t::template _methods_t<select_policies_t>,
public _extra_tables_t::template _methods_t<select_policies_t>,
public _where_t::template _methods_t<select_policies_t>,
public _group_by_t::template _methods_t<select_policies_t>,
public _having_t::template _methods_t<select_policies_t>,
public _order_by_t::template _methods_t<select_policies_t>,
public _limit_t::template _methods_t<select_policies_t>,
public _offset_t::template _methods_t<select_policies_t>
{}; {};
template<typename Needle, typename Replacement, typename... Policies> template<typename Needle, typename Replacement>
struct _policies_update_t struct _policies_update_t
{ {
static_assert(detail::is_element_of<Needle, make_type_set_t<Policies...>>::value, "policies update for non-policy class detected"); static_assert(detail::is_element_of<Needle, make_type_set_t<Policies...>>::value, "policies update for non-policy class detected");
@ -113,32 +77,24 @@ namespace sqlpp
}; };
template<typename Needle, typename Replacement> template<typename Needle, typename Replacement>
using _new_statement_t = typename _policies_update_t<Needle, Replacement, FlagList, ColumnList, From, ExtraTables, Where, GroupBy, Having, OrderBy, Limit, Offset>::type; using _new_statement_t = typename _policies_update_t<Needle, Replacement>::type;
using _known_tables = detail::make_joined_set_t<provided_tables_of<_from_t>, extra_tables_of<_extra_tables_t>>; using _all_required_tables = detail::make_joined_set_t<required_tables_of<Policies>...>;
using _all_provided_tables = detail::make_joined_set_t<provided_tables_of<Policies>...>;
using _all_extra_tables = detail::make_joined_set_t<extra_tables_of<Policies>...>;
using _known_tables = detail::make_joined_set_t<_all_provided_tables, _all_extra_tables>;
template<typename Expression> template<typename Expression>
using _no_unknown_tables = detail::is_subset_of<required_tables_of<Expression>, _known_tables>; using _no_unknown_tables = detail::is_subset_of<required_tables_of<Expression>, _known_tables>;
using _all_required_tables =
detail::make_joined_set_t<
required_tables_of<_flag_list_t>,
required_tables_of<_column_list_t>,
required_tables_of<_where_t>,
required_tables_of<_group_by_t>,
required_tables_of<_having_t>,
required_tables_of<_order_by_t>,
required_tables_of<_limit_t>,
required_tables_of<_offset_t>
>;
// The tables not covered by the from. // The tables not covered by the from.
using _required_tables = detail::make_difference_set_t< using _required_tables = detail::make_difference_set_t<
_all_required_tables, _all_required_tables,
provided_tables_of<_from_t> // Hint: extra_tables_t is not used here because it is just a helper for dynamic .add_*() methods and should not change the structural integrity _all_provided_tables // Hint: extra_tables are not used here because they are just a helper for dynamic .add_*()
>; >;
using _result_provider = detail::get_last_if<is_return_value_t, vendor::no_select_column_list_t, FlagList, ColumnList, From, ExtraTables, Where, GroupBy, Having, OrderBy, Limit, Offset>; using _result_provider = detail::get_last_if<is_return_value_t, vendor::no_select_column_list_t, Policies...>;
// A select can be used as a pseudo table if // A select can be used as a pseudo table if
// - at least one column is selected // - at least one column is selected
@ -150,7 +106,7 @@ namespace sqlpp
>::type; >::type;
using _value_type = typename std::conditional< using _value_type = typename std::conditional<
detail::make_type_set_if_t<is_missing_t, FlagList, ColumnList, From, ExtraTables, Where, GroupBy, Having, OrderBy, Limit, Offset>::size::value == 0, detail::none_t<is_missing_t<Policies>::value...>::value,
value_type_of<_result_provider>, value_type_of<_result_provider>,
no_value_t // if a required statement part is missing (columns in a select), then the statement cannot be used as a value no_value_t // if a required statement part is missing (columns in a select), then the statement cannot be used as a value
>::type; >::type;
@ -300,8 +256,6 @@ namespace sqlpp
return {{}, get_dynamic_names(), db.prepare_select(*this)}; return {{}, get_dynamic_names(), db.prepare_select(*this)};
} }
std::tuple<Policies...> _terms;
}; };
namespace vendor namespace vendor
@ -315,39 +269,51 @@ namespace sqlpp
{ {
context << "SELECT "; context << "SELECT ";
interpret_tuple(t._terms, ' ', context); using swallow = int[];
(void) swallow{(serialize(static_cast<const Policies&>(t), context), 0)...};
return context; return context;
} }
}; };
} }
template<typename Database, typename... Policies> template<typename Database>
using make_select_t = typename detail::select_policies_t<Database, Policies...>::_statement_t; using blank_select_t = select_t<Database,
vendor::no_select_flag_list_t,
vendor::no_select_column_list_t,
vendor::no_from_t,
vendor::no_extra_tables_t,
vendor::no_where_t,
vendor::no_group_by_t,
vendor::no_having_t,
vendor::no_order_by_t,
vendor::no_limit_t,
vendor::no_offset_t>;
make_select_t<void> select() // FIXME: These should be constexpr
blank_select_t<void> select() // FIXME: These should be constexpr
{ {
return { }; return { };
} }
template<typename... Columns> template<typename... Columns>
auto select(Columns... columns) auto select(Columns... columns)
-> make_select_t<void, vendor::no_select_flag_list_t, detail::make_select_column_list_t<void, Columns...>> -> decltype(blank_select_t<void>().columns(detail::make_select_column_list_t<void, Columns...>(columns...)))
{ {
return { make_select_t<void>(), detail::make_select_column_list_t<void, Columns...>{std::tuple_cat(detail::as_tuple<Columns>::_(columns)...)} }; return blank_select_t<void>().columns(detail::make_select_column_list_t<void, Columns...>(columns...));
} }
template<typename Database> template<typename Database>
make_select_t<Database> dynamic_select(const Database&) blank_select_t<Database> dynamic_select(const Database&)
{ {
return { make_select_t<Database>() }; return { };
} }
template<typename Database, typename... Columns> template<typename Database, typename... Columns>
auto dynamic_select(const Database&, Columns... columns) auto dynamic_select(const Database&, Columns... columns)
-> make_select_t<Database, vendor::no_select_flag_list_t, detail::make_select_column_list_t<void, Columns...>> -> decltype(blank_select_t<Database>().columns(detail::make_select_column_list_t<void, Columns...>(columns...)))
{ {
return { make_select_t<Database>(), detail::make_select_column_list_t<void, Columns...>(std::tuple_cat(detail::as_tuple<Columns>::_(columns)...)) }; return blank_select_t<Database>().columns(detail::make_select_column_list_t<void, Columns...>(columns...));
} }
} }