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:
parent
15e8ca742c
commit
6d91cf2163
@ -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...));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user