0
0
mirror of https://github.com/rbock/sqlpp11.git synced 2024-11-15 20:31:16 +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
{
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;
};
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
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_*()
>;
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>
{};
@ -143,7 +143,7 @@ namespace sqlpp
typename... Policies
>
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...>::_result_methods_t,
public detail::select_policies_t<Db, Policies...>::_methods_t
@ -165,7 +165,7 @@ namespace sqlpp
template<typename Statement, typename 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;
@ -173,7 +173,6 @@ namespace sqlpp
select_t& operator=(const select_t& r) = default;
select_t& operator=(select_t&& r) = default;
~select_t() = default;
};
namespace vendor
@ -188,7 +187,7 @@ namespace sqlpp
context << "SELECT ";
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;
}
@ -197,16 +196,16 @@ namespace sqlpp
template<typename 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_from_t,
vendor::no_extra_tables_t,
vendor::no_where_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>;
vendor::no_offset_t*/>;
blank_select_t<void> select() // FIXME: These should be constexpr

View File

@ -37,6 +37,24 @@ namespace sqlpp
{
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
template<typename Database, typename... Tables>
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");
from_t& _from() { return *this; }
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;
// Data
using _data_t = from_data_t<Database, Tables...>;
// Member implementation with data and methods
template<typename Policies>
struct _methods_t
struct _impl_t
{
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_table_t<Table>::value, "invalid table argument in add_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 from::add()");
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:
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>
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;
vendor::interpretable_list_t<Database> _dynamic_tables;
// 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>
struct _methods_t
{
};
};
struct no_from_t
@ -101,18 +126,40 @@ namespace sqlpp
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
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>
struct _methods_t
{
using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_from_t, T>;
using _new_statement_t = typename Policies::template _new_statement_t<no_from_t, T>;
template<typename... Args>
auto from(Args... 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>
@ -120,14 +167,14 @@ namespace sqlpp
-> _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");
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
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...>;
@ -145,9 +192,9 @@ namespace sqlpp
};
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)
{

View File

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

View File

@ -44,18 +44,18 @@ namespace sqlpp
{
namespace detail
{
template<typename... Rest>
struct get_first_argument_if_unique
template<typename... Columns>
struct select_traits
{
using _traits = make_traits<no_value_t, tag::select_column_list, tag::return_value>;
struct _name_t {};
};
template<typename T>
struct get_first_argument_if_unique<T>
template<typename Column>
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 _name_t = typename T::_name_t;
using _traits = make_traits<value_type_of<Column>, tag::select_column_list, tag::return_value, tag::expression, tag::named_expression>;
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>
struct select_column_list_t
{
// get_first_argument_if_unique is kind of ugly
using _traits = typename ::sqlpp::detail::get_first_argument_if_unique<Columns...>::_traits;
using _traits = typename ::sqlpp::detail::select_traits<Columns...>::_traits;
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;
static_assert(not ::sqlpp::detail::has_duplicates<Columns...>::value, "at least one duplicate argument detected");
template<typename T>
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(::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");
static_assert(not ::sqlpp::detail::has_duplicates<typename Columns::_name_t...>::value, "at least one duplicate name detected");
struct _column_type {};
// Data
using _data_t = select_column_list_data_t<Database, Columns...>;
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 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);
}
// Member implementation with data and methods
template<typename Policies>
struct _methods_t
struct _impl_t
{
template<typename NamedExpression>
void add_column_ntc(NamedExpression namedExpression)
@ -205,98 +192,126 @@ namespace sqlpp
static_assert(not ::sqlpp::detail::is_element_of<typename NamedExpression::_name_t, column_names>::value, "a column of this name is present in the select already");
using ok = ::sqlpp::detail::all_t<
_is_dynamic::value,
is_named_expression_t<NamedExpression>::value
>;
_is_dynamic::value,
is_named_expression_t<NamedExpression>::value
>;
_add_column_impl(namedExpression, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
//private:
template<typename NamedExpression>
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>
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 _result_methods_t
{
using _statement_t = typename Policies::_statement_t;
struct _member_t
{
_impl_t<Policies> selected_columns;
_impl_t<Policies>& operator()() { return selected_columns; }
const _impl_t<Policies>& operator()() const { return selected_columns; }
};
template<typename AliasProvider>
struct _deferred_table_t
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
};
// Result methods
template<typename Policies>
struct _result_methods_t
{
using _statement_t = typename Policies::_statement_t;
const _statement_t& _get_statement() const
{
using table = _pseudo_table_t<_statement_t>;
using alias = typename _pseudo_table_t<_statement_t>::template _alias_t<AliasProvider>;
};
template<typename AliasProvider>
using _table_t = typename _deferred_table_t<AliasProvider>::table;
template<typename AliasProvider>
using _alias_t = typename _deferred_table_t<AliasProvider>::alias;
template<typename AliasProvider>
_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");
return _table_t<AliasProvider>(static_cast<const _statement_t&>(*this)).as(aliasProvider);
return static_cast<const _statement_t&>(*this);
}
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;
}
static constexpr size_t _get_static_no_of_parameters()
{
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>
struct _deferred_table_t
{
using table = select_pseudo_table_t<_statement_t, Columns...>;
using alias = typename table::template _alias_t<AliasProvider>;
};
template<typename AliasProvider>
using _table_t = typename _deferred_table_t<AliasProvider>::table;
template<typename AliasProvider>
using _alias_t = typename _deferred_table_t<AliasProvider>::alias;
template<typename AliasProvider>
_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");
return _table_t<AliasProvider>(_get_statement()).as(aliasProvider);
}
const _dynamic_names_t& get_dynamic_names() const
{
return _get_statement().selected_columns._data._dynamic_columns._dynamic_expression_names;
}
static constexpr size_t _get_static_no_of_parameters()
{
#warning need to fix this
return 0;
}
return 0;
}
size_t _get_no_of_parameters() const
{
size_t _get_no_of_parameters() const
{
#warning need to fix this
return 0;
}
return 0;
}
size_t get_no_of_result_columns() const
{
return static_size() + get_dynamic_names().size();
}
size_t get_no_of_result_columns() const
{
return sizeof...(Columns) + get_dynamic_names().size();
}
// Execute
template<typename Db>
auto _run(Db& db) const
-> result_t<decltype(db.select(std::declval<const _statement_t>())), _result_row_t<Db>>
{
Policies::_check_consistency();
static_assert(_get_static_no_of_parameters() == 0, "cannot run select directly with parameters, use prepare instead");
// Execute
template<typename Db>
auto _run(Db& db) const
-> result_t<decltype(db.select(_get_statement())), _result_row_t<Db>>
{
Policies::_check_consistency();
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
// Prepare
template<typename Db>
auto _prepare(Db& db) const
-> prepared_select_t<Db, select_t>
{
Policies::_check_consistency();
// Prepare
template<typename Db>
auto _prepare(Db& db) const
-> prepared_select_t<Db, select_t>
{
Policies::_check_consistency();
return {{}, get_dynamic_names(), db.prepare_select(*this)};
}
return {{}, get_dynamic_names(), db.prepare_select(*this)};
}
#endif
};
};
const select_column_list_t& _column_list() const { return *this; }
std::tuple<Columns...> _columns;
dynamic_select_column_list<Database> _dynamic_columns;
};
}
@ -315,29 +330,42 @@ namespace sqlpp
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop, ::sqlpp::tag::missing>;
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 {};
template<typename T>
struct _pseudo_table_t
// Data
struct _data_t
{
};
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
static_assert(wrong_t<T>::value, "Cannot use a select as a table when no columns have been selected yet");
_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>
struct _methods_t
{
using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_select_column_list_t, T>;
using _new_statement_t = typename Policies::template _new_statement_t<no_select_column_list_t, T>;
template<typename... Args>
auto columns(Args... 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>
@ -345,20 +373,16 @@ namespace sqlpp
-> _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");
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
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)
{
@ -374,9 +398,9 @@ namespace sqlpp
};
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)
{

View File

@ -38,96 +38,160 @@ namespace sqlpp
{
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>
struct where_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::where>;
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;
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::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):
_expressions(expressions...)
{}
// Member implementation with data and methods
template <typename Policies>
struct _impl_t
{
template<typename Expression>
void add_ntc(Expression expression)
{
add<Expression, std::false_type>(expression);
}
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 Expression, typename TableCheckRequired = std::true_type>
void add(Expression expression)
{
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 where::add()");
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>;
_add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename Expression>
void _add_impl(Expression expression, const std::true_type&)
{
return _data._dynamic_expressions.emplace_back(expression);
}
template<typename Expression>
void _add_impl(Expression expression, 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> 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<typename Expression>
void add_where_ntc(Expression expression)
{
add_where<Expression, std::false_type>(expression);
}
template<typename Expression, typename TableCheckRequired = std::true_type>
void add_where(Expression expression)
{
static_assert(_is_dynamic::value, "add_where can only be called for dynamic_where");
static_assert(is_expression_t<Expression>::value, "invalid expression argument in add_where()");
static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in add_where()");
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
}
private:
template<typename Expression>
void _add_where_impl(Expression expression, const std::true_type&)
{
return static_cast<typename Policies::_statement_t*>(this)->_where()._dynamic_expressions.emplace_back(expression);
}
template<typename Expression>
void _add_where_impl(Expression expression, const std::false_type&);
};
std::tuple<Expressions...> _expressions;
vendor::interpretable_list_t<Database> _dynamic_expressions;
};
template<>
struct where_data_t<void, bool>
{
bool _condition;
};
// WHERE(BOOL)
template<>
struct where_t<void, bool>
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::where>;
using _recursive_traits = make_recursive_traits<>;
where_t(bool condition):
_condition(condition)
{}
// Data
using _data_t = where_data_t<void, bool>;
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;
// 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> 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
{
};
bool _condition;
};
// NO WHERE YET
struct no_where_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::where>;
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>
struct _methods_t
{
@ -139,7 +203,7 @@ namespace sqlpp
auto where(Args... 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>
@ -147,16 +211,16 @@ namespace sqlpp
-> _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");
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
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)
{
@ -172,9 +236,9 @@ namespace sqlpp
};
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)
{
@ -185,9 +249,9 @@ namespace sqlpp
};
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)
{

View File

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