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

Using _member_t to have variadic named members in statements

This commit is contained in:
rbock 2014-05-30 10:40:46 +02:00
parent 76fc2fb397
commit 408e96af4a
7 changed files with 370 additions and 228 deletions

View File

@ -34,22 +34,22 @@ namespace sqlpp
namespace detail namespace detail
{ {
template<typename Target, typename Statement, typename Term> template<typename Target, typename Statement, typename Term>
Target pick_arg_impl(Statement statement, Term term, const std::true_type&) typename Target::_data_t pick_arg_impl(Statement statement, Term term, const std::true_type&)
{ {
return term; return term;
}; };
template<typename Target, typename Statement, typename Term> template<typename Target, typename Statement, typename Term>
Target pick_arg_impl(Statement statement, Term term, const std::false_type&) typename Target::_data_t pick_arg_impl(Statement statement, Term term, const std::false_type&)
{ {
return static_cast<Target>(statement); return static_cast<typename Target::template _member_t<Target>>(statement)()._data;
}; };
// Returns a statement's term either by picking the term from the statement or using the new term // Returns a statement's term either by picking the term from the statement or using the new term
template<typename Target, typename Statement, typename Term> template<typename Target, typename Statement, typename Term>
Target pick_arg(Statement statement, Term term) typename Target::_data_t pick_arg(Statement statement, Term term)
{ {
return pick_arg_impl<Target>(statement, term, std::is_same<Target, Term>()); return pick_arg_impl<Target>(statement, term, std::is_same<typename Target::_data_t, Term>());
}; };
} }
} }

View File

@ -93,7 +93,7 @@ namespace sqlpp
_all_provided_tables // Hint: extra_tables are not used here because they are just a helper for dynamic .add_*() _all_provided_tables // Hint: extra_tables are not used here because they are just a helper for dynamic .add_*()
>; >;
using _result_type_provider = detail::get_last_if<is_return_value_t, vendor::no_select_column_list_t, Policies...>; using _result_type_provider = detail::get_last_if<is_return_value_t, vendor::noop, Policies...>;
struct _result_methods_t: public _result_type_provider::template _result_methods_t<select_policies_t> struct _result_methods_t: public _result_type_provider::template _result_methods_t<select_policies_t>
{}; {};
@ -143,7 +143,7 @@ namespace sqlpp
typename... Policies typename... Policies
> >
struct select_t: struct select_t:
public Policies..., public Policies::template _member_t<Policies>...,
public detail::select_policies_t<Db, Policies...>::_value_type::template expression_operators<select_t<Db, Policies...>>, public detail::select_policies_t<Db, Policies...>::_value_type::template expression_operators<select_t<Db, Policies...>>,
public detail::select_policies_t<Db, Policies...>::_result_methods_t, public detail::select_policies_t<Db, Policies...>::_result_methods_t,
public detail::select_policies_t<Db, Policies...>::_methods_t public detail::select_policies_t<Db, Policies...>::_methods_t
@ -165,7 +165,7 @@ namespace sqlpp
template<typename Statement, typename Term> template<typename Statement, typename Term>
select_t(Statement statement, Term term): select_t(Statement statement, Term term):
Policies(detail::pick_arg<Policies>(statement, term))... Policies::template _member_t<Policies>{{detail::pick_arg<Policies>(statement, term)}}...
{} {}
select_t(const select_t& r) = default; select_t(const select_t& r) = default;
@ -173,7 +173,6 @@ namespace sqlpp
select_t& operator=(const select_t& r) = default; select_t& operator=(const select_t& r) = default;
select_t& operator=(select_t&& r) = default; select_t& operator=(select_t&& r) = default;
~select_t() = default; ~select_t() = default;
}; };
namespace vendor namespace vendor
@ -188,7 +187,7 @@ namespace sqlpp
context << "SELECT "; context << "SELECT ";
using swallow = int[]; using swallow = int[];
(void) swallow{(serialize(static_cast<const Policies&>(t), context), 0)...}; (void) swallow{(serialize(static_cast<const Policies&>(t)._data, context), 0)...};
return context; return context;
} }
@ -197,16 +196,16 @@ namespace sqlpp
template<typename Database> template<typename Database>
using blank_select_t = select_t<Database, using blank_select_t = select_t<Database,
vendor::no_select_flag_list_t, //vendor::no_select_flag_list_t,
vendor::no_select_column_list_t, vendor::no_select_column_list_t,
vendor::no_from_t, vendor::no_from_t/*,
vendor::no_extra_tables_t, vendor::no_extra_tables_t*/,
vendor::no_where_t, vendor::no_where_t/*,
vendor::no_group_by_t, vendor::no_group_by_t,
vendor::no_having_t, vendor::no_having_t,
vendor::no_order_by_t, vendor::no_order_by_t,
vendor::no_limit_t, vendor::no_limit_t,
vendor::no_offset_t>; vendor::no_offset_t*/>;
blank_select_t<void> select() // FIXME: These should be constexpr blank_select_t<void> select() // FIXME: These should be constexpr

View File

@ -37,6 +37,24 @@ namespace sqlpp
{ {
namespace vendor namespace vendor
{ {
// FROM DATA
template<typename Database, typename... Tables>
struct from_data_t
{
from_data_t(Tables... tables):
_tables(tables...)
{}
from_data_t(const from_data_t&) = default;
from_data_t(from_data_t&&) = default;
from_data_t& operator=(const from_data_t&) = default;
from_data_t& operator=(from_data_t&&) = default;
~from_data_t() = default;
std::tuple<Tables...> _tables;
vendor::interpretable_list_t<Database> _dynamic_tables;
};
// FROM // FROM
template<typename Database, typename... Tables> template<typename Database, typename... Tables>
struct from_t struct from_t
@ -55,45 +73,52 @@ namespace sqlpp
static_assert(required_tables_of<from_t>::size::value == 0, "at least one table depends on another table"); static_assert(required_tables_of<from_t>::size::value == 0, "at least one table depends on another table");
from_t& _from() { return *this; } // Data
using _data_t = from_data_t<Database, Tables...>;
from_t(Tables... tables):
_tables(tables...)
{}
from_t(const from_t&) = default;
from_t(from_t&&) = default;
from_t& operator=(const from_t&) = default;
from_t& operator=(from_t&&) = default;
~from_t() = default;
// Member implementation with data and methods
template<typename Policies> template<typename Policies>
struct _methods_t struct _impl_t
{ {
template<typename Table> template<typename Table>
void add_from(Table table) void _add_t(Table table)
{ {
static_assert(_is_dynamic::value, "add_from must not be called for static from()"); static_assert(_is_dynamic::value, "from::add() must not be called for static from()");
static_assert(is_table_t<Table>::value, "invalid table argument in add_from()"); static_assert(is_table_t<Table>::value, "invalid table argument in from::add()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_table_t<Table>::value>; using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_table_t<Table>::value>;
_add_from_impl(table, ok()); // dispatch to prevent compile messages after the static_assert _add_impl(table, ok()); // dispatch to prevent compile messages after the static_assert
} }
private: private:
template<typename Table> template<typename Table>
void _add_from_impl(Table table, const std::true_type&) void _add_impl(Table table, const std::true_type&)
{ {
return static_cast<typename Policies::_statement_t*>(this)->_from()._dynamic_tables.emplace_back(table); return _data._dynamic_tables.emplace_back(table);
} }
template<typename Table> template<typename Table>
void _add_from_impl(Table table, const std::false_type&); void _add_impl(Table table, const std::false_type&);
public:
_data_t _data;
}; };
std::tuple<Tables...> _tables; // Member template for adding the named member to a statement
vendor::interpretable_list_t<Database> _dynamic_tables; template<typename Policies>
struct _member_t
{
_impl_t<Policies> no_from;
_impl_t<Policies>& operator()() { return no_from; }
const _impl_t<Policies>& operator()() const { return no_from; }
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
};
}; };
struct no_from_t struct no_from_t
@ -101,6 +126,28 @@ namespace sqlpp
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data
struct _data_t
{
};
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
_impl_t<Policies> no_from;
_impl_t<Policies>& operator()() { return no_from; }
const _impl_t<Policies>& operator()() const { return no_from; }
};
// Additional methods for the statement
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
@ -112,7 +159,7 @@ namespace sqlpp
auto from(Args... args) auto from(Args... args)
-> _new_statement_t<from_t<void, Args...>> -> _new_statement_t<from_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), from_t<void, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), from_data_t<void, Args...>{args...} };
} }
template<typename... Args> template<typename... Args>
@ -120,14 +167,14 @@ namespace sqlpp
-> _new_statement_t<from_t<_database_t, Args...>> -> _new_statement_t<from_t<_database_t, Args...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_from must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_from must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), vendor::from_t<_database_t, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), from_data_t<_database_t, Args...>{args...} };
} }
}; };
}; };
// Interpreters // Interpreters
template<typename Context, typename Database, typename... Tables> template<typename Context, typename Database, typename... Tables>
struct serializer_t<Context, from_t<Database, Tables...>> struct serializer_t<Context, from_data_t<Database, Tables...>>
{ {
using T = from_t<Database, Tables...>; using T = from_t<Database, Tables...>;
@ -145,9 +192,9 @@ namespace sqlpp
}; };
template<typename Context> template<typename Context>
struct serializer_t<Context, no_from_t> struct serializer_t<Context, no_from_t::_data_t>
{ {
using T = no_from_t; using T = no_from_t::_data_t;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {

View File

@ -39,6 +39,12 @@ namespace sqlpp
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
struct _name_t {};
template<typename Policies>
struct _result_methods_t
{};
}; };
template<typename Context> template<typename Context>

View File

@ -44,18 +44,18 @@ namespace sqlpp
{ {
namespace detail namespace detail
{ {
template<typename... Rest> template<typename... Columns>
struct get_first_argument_if_unique struct select_traits
{ {
using _traits = make_traits<no_value_t, tag::select_column_list, tag::return_value>; using _traits = make_traits<no_value_t, tag::select_column_list, tag::return_value>;
struct _name_t {}; struct _name_t {};
}; };
template<typename T> template<typename Column>
struct get_first_argument_if_unique<T> struct select_traits<Column>
{ {
using _traits = make_traits<value_type_of<T>, tag::select_column_list, tag::return_value, tag::expression, tag::named_expression>; using _traits = make_traits<value_type_of<Column>, tag::select_column_list, tag::return_value, tag::expression, tag::named_expression>;
using _name_t = typename T::_name_t; using _name_t = typename Column::_name_t;
}; };
} }
@ -127,67 +127,54 @@ namespace sqlpp
} }
}; };
// SELECTED COLUMNS DATA
template<typename Database, typename... Columns>
struct select_column_list_data_t
{
select_column_list_data_t(Columns... columns):
_columns(columns...)
{}
// SELECT COLUMNS select_column_list_data_t(std::tuple<Columns...> columns):
_columns(columns)
{}
select_column_list_data_t(const select_column_list_data_t&) = default;
select_column_list_data_t(select_column_list_data_t&&) = default;
select_column_list_data_t& operator=(const select_column_list_data_t&) = default;
select_column_list_data_t& operator=(select_column_list_data_t&&) = default;
~select_column_list_data_t() = default;
std::tuple<Columns...> _columns;
dynamic_select_column_list<Database> _dynamic_columns;
};
// SELECTED COLUMNS
template<typename Database, typename... Columns> template<typename Database, typename... Columns>
struct select_column_list_t struct select_column_list_t
{ {
// get_first_argument_if_unique is kind of ugly using _traits = typename ::sqlpp::detail::select_traits<Columns...>::_traits;
using _traits = typename ::sqlpp::detail::get_first_argument_if_unique<Columns...>::_traits;
using _recursive_traits = make_recursive_traits<Columns...>; using _recursive_traits = make_recursive_traits<Columns...>;
using _name_t = typename ::sqlpp::detail::get_first_argument_if_unique<Columns...>::_name_t; using _name_t = typename ::sqlpp::detail::select_traits<Columns...>::_name_t;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type; using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
static_assert(not ::sqlpp::detail::has_duplicates<Columns...>::value, "at least one duplicate argument detected"); static_assert(not ::sqlpp::detail::has_duplicates<Columns...>::value, "at least one duplicate argument detected");
template<typename T> static_assert(::sqlpp::detail::all_t<(is_named_expression_t<Columns>::value or is_multi_column_t<Columns>::value)...>::value, "at least one argument is not a named expression");
using is_valid_expression_t = std::integral_constant<bool, is_named_expression_t<T>::value or is_multi_column_t<T>::value>;
static_assert(::sqlpp::detail::all_t<is_valid_expression_t<Columns>::value...>::value, "at least one argument is not a named expression");
static_assert(not ::sqlpp::detail::has_duplicates<typename Columns::_name_t...>::value, "at least one duplicate name detected"); static_assert(not ::sqlpp::detail::has_duplicates<typename Columns::_name_t...>::value, "at least one duplicate name detected");
struct _column_type {}; struct _column_type {};
// Data
using _data_t = select_column_list_data_t<Database, Columns...>;
template<typename Db> // Member implementation with data and methods
using _result_row_t = typename std::conditional<_is_dynamic::value,
dynamic_result_row_t<Db, make_field_t<Columns>...>,
result_row_t<Db, make_field_t<Columns>...>>::type;
using _dynamic_names_t = typename dynamic_select_column_list<Database>::_names_t;
template <typename Select>
using _pseudo_table_t = select_pseudo_table_t<Select, Columns...>;
template <typename Db>
using _dynamic_t = select_column_list_t<Db, std::tuple<Columns...>>;
select_column_list_t& _select_column_list() { return *this; }
const select_column_list_t& _select_column_list() const { return *this; }
select_column_list_t(std::tuple<Columns...> columns):
_columns(columns)
{}
select_column_list_t(Columns... columns):
_columns(columns...)
{}
select_column_list_t(const select_column_list_t&) = default;
select_column_list_t(select_column_list_t&&) = default;
select_column_list_t& operator=(const select_column_list_t&) = default;
select_column_list_t& operator=(select_column_list_t&&) = default;
~select_column_list_t() = default;
static constexpr size_t static_size()
{
return sizeof...(Columns);
}
template<typename Policies> template<typename Policies>
struct _methods_t struct _impl_t
{ {
template<typename NamedExpression> template<typename NamedExpression>
void add_column_ntc(NamedExpression namedExpression) void add_column_ntc(NamedExpression namedExpression)
@ -212,27 +199,58 @@ namespace sqlpp
_add_column_impl(namedExpression, ok()); // dispatch to prevent compile messages after the static_assert _add_column_impl(namedExpression, ok()); // dispatch to prevent compile messages after the static_assert
} }
private: //private:
template<typename NamedExpression> template<typename NamedExpression>
void _add_column_impl(NamedExpression namedExpression, const std::true_type&) void _add_column_impl(NamedExpression namedExpression, const std::true_type&)
{ {
return static_cast<typename Policies::_statement_t*>(this)->_select_column_list()._dynamic_columns.emplace_back(namedExpression); return _data._dynamic_columns.emplace_back(namedExpression);
} }
template<typename NamedExpression> template<typename NamedExpression>
void _add_column_impl(NamedExpression namedExpression, const std::false_type&); void _add_column_impl(NamedExpression namedExpression, const std::false_type&);
public:
_data_t _data;
}; };
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
_impl_t<Policies> selected_columns;
_impl_t<Policies>& operator()() { return selected_columns; }
const _impl_t<Policies>& operator()() const { return selected_columns; }
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
};
// Result methods
template<typename Policies> template<typename Policies>
struct _result_methods_t struct _result_methods_t
{ {
using _statement_t = typename Policies::_statement_t; using _statement_t = typename Policies::_statement_t;
const _statement_t& _get_statement() const
{
return static_cast<const _statement_t&>(*this);
}
template<typename Db>
using _result_row_t = typename std::conditional<_is_dynamic::value,
dynamic_result_row_t<Db, make_field_t<Columns>...>,
result_row_t<Db, make_field_t<Columns>...>>::type;
using _dynamic_names_t = typename dynamic_select_column_list<Database>::_names_t;
template<typename AliasProvider> template<typename AliasProvider>
struct _deferred_table_t struct _deferred_table_t
{ {
using table = _pseudo_table_t<_statement_t>; using table = select_pseudo_table_t<_statement_t, Columns...>;
using alias = typename _pseudo_table_t<_statement_t>::template _alias_t<AliasProvider>; using alias = typename table::template _alias_t<AliasProvider>;
}; };
template<typename AliasProvider> template<typename AliasProvider>
@ -245,11 +263,12 @@ namespace sqlpp
_alias_t<AliasProvider> as(const AliasProvider& aliasProvider) const _alias_t<AliasProvider> as(const AliasProvider& aliasProvider) const
{ {
static_assert(Policies::_can_be_used_as_table::value, "statement cannot be used as table, e.g. due to missing tables"); static_assert(Policies::_can_be_used_as_table::value, "statement cannot be used as table, e.g. due to missing tables");
return _table_t<AliasProvider>(static_cast<const _statement_t&>(*this)).as(aliasProvider); return _table_t<AliasProvider>(_get_statement()).as(aliasProvider);
} }
const _dynamic_names_t& get_dynamic_names() const const _dynamic_names_t& get_dynamic_names() const
{ {
return static_cast<const typename Policies::_statement_t*>(this)->_select_column_list()._dynamic_columns._dynamic_expression_names; return _get_statement().selected_columns._data._dynamic_columns._dynamic_expression_names;
} }
static constexpr size_t _get_static_no_of_parameters() static constexpr size_t _get_static_no_of_parameters()
@ -266,18 +285,18 @@ namespace sqlpp
size_t get_no_of_result_columns() const size_t get_no_of_result_columns() const
{ {
return static_size() + get_dynamic_names().size(); return sizeof...(Columns) + get_dynamic_names().size();
} }
// Execute // Execute
template<typename Db> template<typename Db>
auto _run(Db& db) const auto _run(Db& db) const
-> result_t<decltype(db.select(std::declval<const _statement_t>())), _result_row_t<Db>> -> result_t<decltype(db.select(_get_statement())), _result_row_t<Db>>
{ {
Policies::_check_consistency(); Policies::_check_consistency();
static_assert(_get_static_no_of_parameters() == 0, "cannot run select directly with parameters, use prepare instead"); static_assert(_get_static_no_of_parameters() == 0, "cannot run select directly with parameters, use prepare instead");
return {db.select(static_cast<const _statement_t&>(*this)), get_dynamic_names()}; return {db.select(_get_statement()), get_dynamic_names()};
} }
#if 0 #if 0
@ -293,10 +312,6 @@ namespace sqlpp
#endif #endif
}; };
const select_column_list_t& _column_list() const { return *this; }
std::tuple<Columns...> _columns;
dynamic_select_column_list<Database> _dynamic_columns;
}; };
} }
@ -315,17 +330,30 @@ namespace sqlpp
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop, ::sqlpp::tag::missing>; using _traits = make_traits<no_value_t, ::sqlpp::tag::noop, ::sqlpp::tag::missing>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
template<typename Db>
using _result_row_t = ::sqlpp::result_row_t<Db>;
using _dynamic_names_t = typename dynamic_select_column_list<void>::_names_t;
struct _name_t {}; struct _name_t {};
template<typename T> // Data
struct _pseudo_table_t struct _data_t
{ {
static_assert(wrong_t<T>::value, "Cannot use a select as a table when no columns have been selected yet");
}; };
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
_impl_t<Policies> no_selected_columns;
_impl_t<Policies>& operator()() { return no_selected_columns; }
const _impl_t<Policies>& operator()() const { return no_selected_columns; }
};
// Additional methods for the statement
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
@ -337,7 +365,7 @@ namespace sqlpp
auto columns(Args... args) auto columns(Args... args)
-> _new_statement_t<::sqlpp::detail::make_select_column_list_t<void, Args...>> -> _new_statement_t<::sqlpp::detail::make_select_column_list_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), ::sqlpp::detail::make_select_column_list_t<void, Args...>{std::tuple_cat(::sqlpp::detail::as_tuple<Args>::_(args)...)} }; return { *static_cast<typename Policies::_statement_t*>(this), typename ::sqlpp::detail::make_select_column_list_t<void, Args...>::_data_t{std::tuple_cat(::sqlpp::detail::as_tuple<Args>::_(args)...)} };
} }
template<typename... Args> template<typename... Args>
@ -345,20 +373,16 @@ namespace sqlpp
-> _new_statement_t<::sqlpp::detail::make_select_column_list_t<_database_t, Args...>> -> _new_statement_t<::sqlpp::detail::make_select_column_list_t<_database_t, Args...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_columns must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_columns must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), ::sqlpp::detail::make_select_column_list_t<_database_t, Args...>{std::tuple_cat(::sqlpp::detail::as_tuple<Args>::_(args)...)} }; return { *static_cast<typename Policies::_statement_t*>(this), typename ::sqlpp::detail::make_select_column_list_t<_database_t, Args...>::_data_t{std::tuple_cat(::sqlpp::detail::as_tuple<Args>::_(args)...)} };
} }
}; };
template<typename Policies>
struct _result_methods_t
{};
}; };
// Interpreters // Interpreters
template<typename Context, typename Database, typename... Columns> template<typename Context, typename Database, typename... Columns>
struct serializer_t<Context, select_column_list_t<Database, Columns...>> struct serializer_t<Context, select_column_list_data_t<Database, Columns...>>
{ {
using T = select_column_list_t<Database, Columns...>; using T = select_column_list_data_t<Database, Columns...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
@ -374,9 +398,9 @@ namespace sqlpp
}; };
template<typename Context> template<typename Context>
struct serializer_t<Context, no_select_column_list_t> struct serializer_t<Context, typename no_select_column_list_t::_data_t>
{ {
using T = no_select_column_list_t; using T = typename no_select_column_list_t::_data_t;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {

View File

@ -38,96 +38,160 @@ namespace sqlpp
{ {
namespace vendor namespace vendor
{ {
// WHERE template<typename Database, typename... Expressions>
struct where_data_t
{
where_data_t(Expressions... expressions):
_expressions(expressions...)
{}
where_data_t(const where_data_t&) = default;
where_data_t(where_data_t&&) = default;
where_data_t& operator=(const where_data_t&) = default;
where_data_t& operator=(where_data_t&&) = default;
~where_data_t() = default;
std::tuple<Expressions...> _expressions;
vendor::interpretable_list_t<Database> _dynamic_expressions;
};
// WHERE(EXPR)
template<typename Database, typename... Expressions> template<typename Database, typename... Expressions>
struct where_t struct where_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::where>; using _traits = make_traits<no_value_t, ::sqlpp::tag::where>;
using _recursive_traits = make_recursive_traits<Expressions...>; using _recursive_traits = make_recursive_traits<Expressions...>;
#warning: is_dynamic should be using a template alias (making it easier to replace the logic)
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type; using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in where()"); static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in where()");
static_assert(sqlpp::detail::none_t<is_assignment_t<Expressions>::value...>::value, "at least one argument is an assignment in where()"); static_assert(sqlpp::detail::none_t<is_assignment_t<Expressions>::value...>::value, "at least one argument is an assignment in where()");
static_assert(sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not valid expression in where()"); static_assert(sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not valid expression in where()");
where_t& _where() { return *this; } // Data
using _data_t = where_data_t<Database, Expressions...>;
where_t(Expressions... expressions): // Member implementation with data and methods
_expressions(expressions...) template <typename Policies>
{} struct _impl_t
where_t(const where_t&) = default;
where_t(where_t&&) = default;
where_t& operator=(const where_t&) = default;
where_t& operator=(where_t&&) = default;
~where_t() = default;
template<typename Policies>
struct _methods_t
{ {
template<typename Expression> template<typename Expression>
void add_where_ntc(Expression expression) void add_ntc(Expression expression)
{ {
add_where<Expression, std::false_type>(expression); add<Expression, std::false_type>(expression);
} }
template<typename Expression, typename TableCheckRequired = std::true_type> template<typename Expression, typename TableCheckRequired = std::true_type>
void add_where(Expression expression) void add(Expression expression)
{ {
static_assert(_is_dynamic::value, "add_where can only be called for dynamic_where"); static_assert(_is_dynamic::value, "where::add() can only be called for dynamic_where");
static_assert(is_expression_t<Expression>::value, "invalid expression argument in add_where()"); static_assert(is_expression_t<Expression>::value, "invalid expression argument in where::add()");
static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in add_where()"); static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in where::add()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t<Expression>::value>; using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t<Expression>::value>;
_add_where_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert _add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
} }
private: private:
template<typename Expression> template<typename Expression>
void _add_where_impl(Expression expression, const std::true_type&) void _add_impl(Expression expression, const std::true_type&)
{ {
return static_cast<typename Policies::_statement_t*>(this)->_where()._dynamic_expressions.emplace_back(expression); return _data._dynamic_expressions.emplace_back(expression);
} }
template<typename Expression> template<typename Expression>
void _add_where_impl(Expression expression, const std::false_type&); void _add_impl(Expression expression, const std::false_type&);
public:
_data_t _data;
}; };
std::tuple<Expressions...> _expressions; // Member template for adding the named member to a statement
vendor::interpretable_list_t<Database> _dynamic_expressions; template<typename Policies>
struct _member_t
{
_impl_t<Policies> where;
_impl_t<Policies>& operator()() { return where; }
const _impl_t<Policies>& operator()() const { return where; }
}; };
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
};
};
template<>
struct where_data_t<void, bool>
{
bool _condition;
};
// WHERE(BOOL)
template<> template<>
struct where_t<void, bool> struct where_t<void, bool>
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::where>; using _traits = make_traits<no_value_t, ::sqlpp::tag::where>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
where_t(bool condition): // Data
_condition(condition) using _data_t = where_data_t<void, bool>;
{}
where_t(const where_t&) = default; // Member implementation with data and methods
where_t(where_t&&) = default; template<typename Policies>
where_t& operator=(const where_t&) = default; struct _impl_t
where_t& operator=(where_t&&) = default; {
~where_t() = default; _data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
_impl_t<Policies> where;
_impl_t<Policies>& operator()() { return where; }
const _impl_t<Policies>& operator()() const { return where; }
};
// Additional methods for the statement
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
}; };
bool _condition;
}; };
// NO WHERE YET
struct no_where_t struct no_where_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::where>; using _traits = make_traits<no_value_t, ::sqlpp::tag::where>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data
struct _data_t
{
};
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
_impl_t<Policies> no_where;
_impl_t<Policies>& operator()() { return no_where; }
const _impl_t<Policies>& operator()() const { return no_where; }
};
// Additional methods for the statement
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
@ -139,7 +203,7 @@ namespace sqlpp
auto where(Args... args) auto where(Args... args)
-> _new_statement_t<where_t<void, Args...>> -> _new_statement_t<where_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), where_t<void, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), where_data_t<void, Args...>{args...} };
} }
template<typename... Args> template<typename... Args>
@ -147,16 +211,16 @@ namespace sqlpp
-> _new_statement_t<where_t<_database_t, Args...>> -> _new_statement_t<where_t<_database_t, Args...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_where must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_where must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), vendor::where_t<_database_t, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), where_data_t<_database_t, Args...>{args...} };
} }
}; };
}; };
// Interpreters // Interpreters
template<typename Context, typename Database, typename... Expressions> template<typename Context, typename Database, typename... Expressions>
struct serializer_t<Context, where_t<Database, Expressions...>> struct serializer_t<Context, where_data_t<Database, Expressions...>>
{ {
using T = where_t<Database, Expressions...>; using T = where_data_t<Database, Expressions...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
@ -172,9 +236,9 @@ namespace sqlpp
}; };
template<typename Context> template<typename Context>
struct serializer_t<Context, where_t<void, bool>> struct serializer_t<Context, where_data_t<void, bool>>
{ {
using T = where_t<void, bool>; using T = where_data_t<void, bool>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
@ -185,9 +249,9 @@ namespace sqlpp
}; };
template<typename Context> template<typename Context>
struct serializer_t<Context, no_where_t> struct serializer_t<Context, typename no_where_t::_data_t>
{ {
using T = no_where_t; using T = typename no_where_t::_data_t;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {

View File

@ -55,6 +55,7 @@ int main()
const std::string b = row.beta; const std::string b = row.beta;
} }
#if 0
for (const auto& row : db(select(all_of(t).as(t)).from(t).where(true))) for (const auto& row : db(select(all_of(t).as(t)).from(t).where(true)))
{ {
int64_t a = row.tabBar.alpha; int64_t a = row.tabBar.alpha;
@ -85,6 +86,7 @@ int main()
auto X = select(all_of(t)).from(t).as(t.alpha); auto X = select(all_of(t)).from(t).as(t.alpha);
#endif
return 0; return 0;
} }