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:
parent
76fc2fb397
commit
408e96af4a
@ -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>());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
99
include/sqlpp11/vendor/from.h
vendored
99
include/sqlpp11/vendor/from.h
vendored
@ -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)
|
||||||
{
|
{
|
||||||
|
6
include/sqlpp11/vendor/noop.h
vendored
6
include/sqlpp11/vendor/noop.h
vendored
@ -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>
|
||||||
|
180
include/sqlpp11/vendor/select_column_list.h
vendored
180
include/sqlpp11/vendor/select_column_list.h
vendored
@ -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)
|
||||||
{
|
{
|
||||||
|
148
include/sqlpp11/vendor/where.h
vendored
148
include/sqlpp11/vendor/where.h
vendored
@ -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):
|
|
||||||
_expressions(expressions...)
|
|
||||||
{}
|
|
||||||
|
|
||||||
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>
|
template <typename Policies>
|
||||||
struct _methods_t
|
struct _impl_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)
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user