0
0
mirror of https://github.com/rbock/sqlpp11.git synced 2024-11-15 20:31:16 +08:00

Adjusted remaining select parts

This commit is contained in:
rbock 2014-05-30 13:43:59 +02:00
parent 98bb9a7db7
commit b00fe51fed
9 changed files with 573 additions and 263 deletions

View File

@ -203,13 +203,13 @@ namespace sqlpp
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

@ -84,9 +84,17 @@ namespace sqlpp
template<typename Policies> template<typename Policies>
struct _member_t struct _member_t
{ {
using _data_t = extra_tables_data_t<Tables...>;
_impl_t<Policies> extra_tables; _impl_t<Policies> extra_tables;
_impl_t<Policies>& operator()() { return extra_tables; } _impl_t<Policies>& operator()() { return extra_tables; }
const _impl_t<Policies>& operator()() const { return extra_tables; } const _impl_t<Policies>& operator()() const { return extra_tables; }
template<typename T>
static auto _get_member(T t) -> decltype(t.extra_tables)
{
return t.extra_tables;
}
}; };
// Additional methods for the statement // Additional methods for the statement
@ -103,9 +111,7 @@ namespace sqlpp
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data
struct _data_t using _data_t = no_data_t;
{
};
// Member implementation with data and methods // Member implementation with data and methods
template<typename Policies> template<typename Policies>
@ -118,9 +124,17 @@ namespace sqlpp
template<typename Policies> template<typename Policies>
struct _member_t struct _member_t
{ {
_impl_t<Policies> no_extra_tables_t; using _data_t = no_data_t;
_impl_t<Policies>& operator()() { return no_extra_tables_t; }
const _impl_t<Policies>& operator()() const { return no_extra_tables_t; } _impl_t<Policies> no_extra_tables;
_impl_t<Policies>& operator()() { return no_extra_tables; }
const _impl_t<Policies>& operator()() const { return no_extra_tables; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_extra_tables)
{
return t.no_extra_tables;
}
}; };
template<typename Policies> template<typename Policies>
@ -150,17 +164,6 @@ namespace sqlpp
} }
}; };
template<typename Context>
struct serializer_t<Context, typename no_extra_tables_t::_data_t>
{
using T = typename no_extra_tables_t::_data_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
} }
} }

View File

@ -39,6 +39,24 @@ namespace sqlpp
{ {
namespace vendor namespace vendor
{ {
// GROUP BY DATA
template<typename Database, typename... Expressions>
struct group_by_data_t
{
group_by_data_t(Expressions... expressions):
_expressions(expressions...)
{}
group_by_data_t(const group_by_data_t&) = default;
group_by_data_t(group_by_data_t&&) = default;
group_by_data_t& operator=(const group_by_data_t&) = default;
group_by_data_t& operator=(group_by_data_t&&) = default;
~group_by_data_t() = default;
std::tuple<Expressions...> _expressions;
vendor::interpretable_list_t<Database> _dynamic_expressions;
};
// GROUP BY // GROUP BY
template<typename Database, typename... Expressions> template<typename Database, typename... Expressions>
struct group_by_t struct group_by_t
@ -54,60 +72,100 @@ namespace sqlpp
static_assert(::sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in group_by()"); static_assert(::sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in group_by()");
group_by_t& _group_by() { return *this; } // Data
using _data_t = select_flag_list_data_t<Database, Expressions...>;
group_by_t(Expressions... expressions):
_expressions(expressions...)
{}
group_by_t(const group_by_t&) = default;
group_by_t(group_by_t&&) = default;
group_by_t& operator=(const group_by_t&) = default;
group_by_t& operator=(group_by_t&&) = default;
~group_by_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_group_by_ntc(Expression expression) void add_ntc(Expression expression)
{ {
add_group_by<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_group_by(Expression expression) void add(Expression expression)
{ {
static_assert(_is_dynamic::value, "add_group_by must not be called for static group_by"); static_assert(_is_dynamic::value, "add() must not be called for static group_by");
static_assert(is_expression_t<Expression>::value, "invalid expression argument in add_group_by()"); static_assert(is_expression_t<Expression>::value, "invalid expression argument in group_by::add()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in add_group_by()"); static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in group_by::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_group_by_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_group_by_impl(Expression expression, const std::true_type&) void _add_impl(Expression expression, const std::true_type&)
{ {
return static_cast<typename Policies::_statement_t*>(this)->_group_by()._dynamic_expressions.emplace_back(expression); return _data._dynamic_expressions.emplace_back(expression);
} }
template<typename Expression> template<typename Expression>
void _add_group_by_impl(Expression expression, const std::false_type&); void _add_impl(Expression expression, const std::false_type&);
public:
_data_t _data;
}; };
const group_by_t& _group_by() const { return *this; } // Member template for adding the named member to a statement
std::tuple<Expressions...> _expressions; template<typename Policies>
vendor::interpretable_list_t<Database> _dynamic_expressions; struct _member_t
{
using _data_t = group_by_data_t<Database, Expressions...>;
_impl_t<Policies> group_by;
_impl_t<Policies>& operator()() { return group_by; }
const _impl_t<Policies>& operator()() const { return group_by; }
template<typename T>
static auto _get_member(T t) -> decltype(t.group_by)
{
return t.group_by;
}
};
template<typename Policies>
struct _methods_t
{
};
}; };
// NO GROUP BY YET
struct no_group_by_t struct no_group_by_t
{ {
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
using _data_t = no_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
{
using _data_t = no_data_t;
_impl_t<Policies> no_group_by;
_impl_t<Policies>& operator()() { return no_group_by; }
const _impl_t<Policies>& operator()() const { return no_group_by; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_group_by)
{
return t.no_group_by;
}
};
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
@ -119,7 +177,7 @@ namespace sqlpp
auto group_by(Args... args) auto group_by(Args... args)
-> _new_statement_t<group_by_t<void, Args...>> -> _new_statement_t<group_by_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), group_by_t<void, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), group_by_data_t<void, Args...>{args...} };
} }
template<typename... Args> template<typename... Args>
@ -127,16 +185,16 @@ namespace sqlpp
-> _new_statement_t<group_by_t<_database_t, Args...>> -> _new_statement_t<group_by_t<_database_t, Args...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_group_by must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_group_by must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), vendor::group_by_t<_database_t, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), group_by_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, group_by_t<Database, Expressions...>> struct serializer_t<Context, group_by_data_t<Database, Expressions...>>
{ {
using T = group_by_t<Database, Expressions...>; using T = group_by_data_t<Database, Expressions...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
@ -150,18 +208,6 @@ namespace sqlpp
return context; return context;
} }
}; };
template<typename Context>
struct serializer_t<Context, no_group_by_t>
{
using T = no_group_by_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
} }
} }

View File

@ -38,6 +38,24 @@ namespace sqlpp
{ {
namespace vendor namespace vendor
{ {
// HAVING DATA
template<typename Database, typename... Expressions>
struct having_data_t
{
having_data_t(Expressions... expressions):
_expressions(expressions...)
{}
having_data_t(const having_data_t&) = default;
having_data_t(having_data_t&&) = default;
having_data_t& operator=(const having_data_t&) = default;
having_data_t& operator=(having_data_t&&) = default;
~having_data_t() = default;
std::tuple<Expressions...> _expressions;
vendor::interpretable_list_t<Database> _dynamic_expressions;
};
// HAVING // HAVING
template<typename Database, typename... Expressions> template<typename Database, typename... Expressions>
struct having_t struct having_t
@ -50,59 +68,102 @@ namespace sqlpp
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in having()"); static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in having()");
static_assert(::sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in having()"); static_assert(::sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in having()");
having_t& _having() { return *this; } // Data
using _data_t = having_data_t<Database, Expressions...>;
having_t(Expressions... expressions): // Member implementation with data and methods
_expressions(expressions...) template <typename Policies>
{} struct _impl_t
having_t(const having_t&) = default;
having_t(having_t&&) = default;
having_t& operator=(const having_t&) = default;
having_t& operator=(having_t&&) = default;
~having_t() = default;
template<typename Policies>
struct _methods_t
{ {
template<typename Expression> template<typename Expression>
void add_having_ntc(Expression expression) void add_ntc(Expression expression)
{ {
add_having<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_having(Expression expression) void add(Expression expression)
{ {
static_assert(_is_dynamic::value, "add_having must not be called for static having"); static_assert(_is_dynamic::value, "having::add() can only be called for dynamic_having");
static_assert(is_expression_t<Expression>::value, "invalid expression argument in add_having()"); static_assert(is_expression_t<Expression>::value, "invalid expression argument in having::add()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in add_having()"); static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in having::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_having_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_having_impl(Expression expression, const std::true_type&) void _add_impl(Expression expression, const std::true_type&)
{ {
return static_cast<typename Policies::_statement_t*>(this)->_having()._dynamic_expressions.emplace_back(expression); return _data._dynamic_expressions.emplace_back(expression);
} }
template<typename Expression> template<typename Expression>
void _add_having_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
{
using _data_t = having_data_t<Database, Expressions...>;
_impl_t<Policies> having;
_impl_t<Policies>& operator()() { return having; }
const _impl_t<Policies>& operator()() const { return having; }
template<typename T>
static auto _get_member(T t) -> decltype(t.having)
{
return t.having;
}
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
};
}; };
// NO HAVING YET
struct no_having_t struct no_having_t
{ {
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
using _data_t = no_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
{
using _data_t = no_data_t;
_impl_t<Policies> no_having;
_impl_t<Policies>& operator()() { return no_having; }
const _impl_t<Policies>& operator()() const { return no_having; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_having)
{
return t.no_having;
}
};
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
@ -114,7 +175,7 @@ namespace sqlpp
auto having(Args... args) auto having(Args... args)
-> _new_statement_t<having_t<void, Args...>> -> _new_statement_t<having_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), having_t<void, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), having_data_t<void, Args...>{args...} };
} }
template<typename... Args> template<typename... Args>
@ -122,16 +183,16 @@ namespace sqlpp
-> _new_statement_t<having_t<_database_t, Args...>> -> _new_statement_t<having_t<_database_t, Args...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_having must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_having must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), vendor::having_t<_database_t, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), having_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, having_t<Database, Expressions...>> struct serializer_t<Context, having_data_t<Database, Expressions...>>
{ {
using T = having_t<Database, Expressions...>; using T = having_data_t<Database, Expressions...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
@ -145,18 +206,6 @@ namespace sqlpp
return context; return context;
} }
}; };
template<typename Context>
struct serializer_t<Context, no_having_t>
{
using T = no_having_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
} }
} }

View File

@ -35,6 +35,23 @@ namespace sqlpp
{ {
namespace vendor namespace vendor
{ {
// LIMIT DATA
template<typename Limit>
struct limit_data_t
{
limit_data_t(Limit value):
_value(value)
{}
limit_data_t(const limit_data_t&) = default;
limit_data_t(limit_data_t&&) = default;
limit_data_t& operator=(const limit_data_t&) = default;
limit_data_t& operator=(limit_data_t&&) = default;
~limit_data_t() = default;
Limit _value;
};
// LIMIT // LIMIT
template<typename Limit> template<typename Limit>
struct limit_t struct limit_t
@ -44,65 +61,109 @@ namespace sqlpp
static_assert(is_integral_t<Limit>::value, "limit requires an integral value or integral parameter"); static_assert(is_integral_t<Limit>::value, "limit requires an integral value or integral parameter");
limit_t(Limit value): // Data
_value(value) using _data_t = limit_data_t<Limit>;
{}
limit_t(const limit_t&) = default; // Member implementation with data and methods
limit_t(limit_t&&) = default; template <typename Policies>
limit_t& operator=(const limit_t&) = default; struct _impl_t
limit_t& operator=(limit_t&&) = default; {
~limit_t() = default; _data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
_impl_t<Policies> limit;
_impl_t<Policies>& operator()() { return limit; }
const _impl_t<Policies>& operator()() const { return limit; }
template<typename T>
static auto _get_member(T t) -> decltype(t.limit)
{
return t.limit;
}
};
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
}; };
Limit _value;
}; };
// DYNAMIC LIMIT DATA
template<typename Database>
struct dynamic_limit_data_t
{
dynamic_limit_data_t():
_value(noop())
{
}
template<typename Limit>
dynamic_limit_data_t(Limit value):
_initialized(true),
_value(typename wrap_operand<Limit>::type(value))
{
}
dynamic_limit_data_t(const dynamic_limit_data_t&) = default;
dynamic_limit_data_t(dynamic_limit_data_t&&) = default;
dynamic_limit_data_t& operator=(const dynamic_limit_data_t&) = default;
dynamic_limit_data_t& operator=(dynamic_limit_data_t&&) = default;
~dynamic_limit_data_t() = default;
bool _initialized = false;
interpretable_t<Database> _value;
};
// DYNAMIC LIMIT
template<typename Database> template<typename Database>
struct dynamic_limit_t struct dynamic_limit_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::limit>; using _traits = make_traits<no_value_t, ::sqlpp::tag::limit>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
dynamic_limit_t& _limit() { return *this; } // Data
using _data_t = limit_data_t<Database>;
dynamic_limit_t(): // Member implementation with data and methods
_value(noop()) template <typename Policies>
{ struct _impl_t
}
template<typename Limit>
dynamic_limit_t(Limit value):
_initialized(true),
_value(typename wrap_operand<Limit>::type(value))
{
}
dynamic_limit_t(const dynamic_limit_t&) = default;
dynamic_limit_t(dynamic_limit_t&&) = default;
dynamic_limit_t& operator=(const dynamic_limit_t&) = default;
dynamic_limit_t& operator=(dynamic_limit_t&&) = default;
~dynamic_limit_t() = default;
template<typename Policies>
struct _methods_t
{ {
template<typename Limit> template<typename Limit>
void set_limit(Limit value) void set(Limit value)
{ {
// FIXME: Make sure that Limit does not require external tables? Need to read up on SQL // FIXME: Make sure that Limit does not require external tables? Need to read up on SQL
using arg_t = typename wrap_operand<Limit>::type; using arg_t = typename wrap_operand<Limit>::type;
static_cast<typename Policies::_statement_t*>(this)->_limit()._value = arg_t{value}; _data._value = arg_t{value};
static_cast<typename Policies::_statement_t*>(this)->_limit()._initialized = true; _data._initialized = true;
}
public:
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
_impl_t<Policies> limit;
_impl_t<Policies>& operator()() { return limit; }
const _impl_t<Policies>& operator()() const { return limit; }
template<typename T>
static auto _get_member(T t) -> decltype(t.limit)
{
return t.limit;
} }
}; };
bool _initialized = false; // Additional methods for the statement
interpretable_t<Database> _value; template<typename Policies>
struct _methods_t
{
};
}; };
struct no_limit_t struct no_limit_t
@ -110,6 +171,33 @@ 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
using _data_t = no_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
{
using _data_t = no_data_t;
_impl_t<Policies> no_limit;
_impl_t<Policies>& operator()() { return no_limit; }
const _impl_t<Policies>& operator()() const { return no_limit; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_limit)
{
return t.no_limit;
}
};
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
@ -121,23 +209,23 @@ namespace sqlpp
auto limit(Arg arg) auto limit(Arg arg)
-> _new_statement_t<limit_t<typename wrap_operand<Arg>::type>> -> _new_statement_t<limit_t<typename wrap_operand<Arg>::type>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), limit_t<typename wrap_operand<Arg>::type>{{arg}} }; return { *static_cast<typename Policies::_statement_t*>(this), limit_data_t<typename wrap_operand<Arg>::type>{{arg}} };
} }
auto dynamic_limit() auto dynamic_limit()
-> _new_statement_t<dynamic_limit_t<_database_t>> -> _new_statement_t<dynamic_limit_t<_database_t>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_limit must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_limit must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), dynamic_limit_t<_database_t>{} }; return { *static_cast<typename Policies::_statement_t*>(this), dynamic_limit_data_t<_database_t>{} };
} }
}; };
}; };
// Interpreters // Interpreters
template<typename Context, typename Database> template<typename Context, typename Database>
struct serializer_t<Context, dynamic_limit_t<Database>> struct serializer_t<Context, dynamic_limit_data_t<Database>>
{ {
using T = dynamic_limit_t<Database>; using T = dynamic_limit_data_t<Database>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
@ -162,18 +250,6 @@ namespace sqlpp
return context; return context;
} }
}; };
template<typename Context>
struct serializer_t<Context, no_limit_t>
{
using T = no_limit_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
} }
} }

View File

@ -35,6 +35,23 @@ namespace sqlpp
{ {
namespace vendor namespace vendor
{ {
// OFFSET DATA
template<typename Offset>
struct offset_data_t
{
offset_data_t(Offset value):
_value(value)
{}
offset_data_t(const offset_data_t&) = default;
offset_data_t(offset_data_t&&) = default;
offset_data_t& operator=(const offset_data_t&) = default;
offset_data_t& operator=(offset_data_t&&) = default;
~offset_data_t() = default;
Offset _value;
};
// OFFSET // OFFSET
template<typename Offset> template<typename Offset>
struct offset_t struct offset_t
@ -44,49 +61,103 @@ namespace sqlpp
static_assert(is_integral_t<Offset>::value, "offset requires an integral value or integral parameter"); static_assert(is_integral_t<Offset>::value, "offset requires an integral value or integral parameter");
offset_t(Offset value): // Data
_value(value) using _data_t = offset_data_t<Offset>;
{}
offset_t(const offset_t&) = default; // Member implementation with data and methods
offset_t(offset_t&&) = default; template <typename Policies>
offset_t& operator=(const offset_t&) = default; struct _impl_t
offset_t& operator=(offset_t&&) = default; {
~offset_t() = default; _data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
_impl_t<Policies> offset;
_impl_t<Policies>& operator()() { return offset; }
const _impl_t<Policies>& operator()() const { return offset; }
template<typename T>
static auto _get_member(T t) -> decltype(t.offset)
{
return t.offset;
}
};
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
}; };
Offset _value;
}; };
// DYNAMIC OFFSET DATA
template<typename Database>
struct dynamic_offset_data_t
{
dynamic_offset_data_t():
_value(noop())
{
}
template<typename Offset>
dynamic_offset_data_t(Offset value):
_initialized(true),
_value(typename wrap_operand<Offset>::type(value))
{
}
dynamic_offset_data_t(const dynamic_offset_data_t&) = default;
dynamic_offset_data_t(dynamic_offset_data_t&&) = default;
dynamic_offset_data_t& operator=(const dynamic_offset_data_t&) = default;
dynamic_offset_data_t& operator=(dynamic_offset_data_t&&) = default;
~dynamic_offset_data_t() = default;
bool _initialized = false;
interpretable_t<Database> _value;
};
// DYNAMIC OFFSET
template<typename Database> template<typename Database>
struct dynamic_offset_t struct dynamic_offset_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::offset>; using _traits = make_traits<no_value_t, ::sqlpp::tag::offset>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
dynamic_offset_t& _offset() { return *this; } // Data
using _data_t = offset_data_t<Database>;
dynamic_offset_t(): // Member implementation with data and methods
_value(noop()) template <typename Policies>
{ struct _impl_t
} {
template<typename Offset>
void set(Offset value)
{
// FIXME: Make sure that Offset does not require external tables? Need to read up on SQL
using arg_t = typename wrap_operand<Offset>::type;
_data._value = arg_t{value};
_data._initialized = true;
}
public:
_data_t _data;
};
template<typename Offset> // Member template for adding the named member to a statement
dynamic_offset_t(Offset value): template<typename Policies>
_initialized(true), struct _member_t
_value(typename wrap_operand<Offset>::type(value)) {
{ _impl_t<Policies> offset;
} _impl_t<Policies>& operator()() { return offset; }
const _impl_t<Policies>& operator()() const { return offset; }
dynamic_offset_t(const dynamic_offset_t&) = default; template<typename T>
dynamic_offset_t(dynamic_offset_t&&) = default; static auto _get_member(T t) -> decltype(t.offset)
dynamic_offset_t& operator=(const dynamic_offset_t&) = default; {
dynamic_offset_t& operator=(dynamic_offset_t&&) = default; return t.offset;
~dynamic_offset_t() = default; }
};
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
@ -110,6 +181,33 @@ 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
using _data_t = no_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
{
using _data_t = no_data_t;
_impl_t<Policies> no_offset;
_impl_t<Policies>& operator()() { return no_offset; }
const _impl_t<Policies>& operator()() const { return no_offset; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_offset)
{
return t.no_offset;
}
};
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
@ -121,14 +219,14 @@ namespace sqlpp
auto offset(Arg arg) auto offset(Arg arg)
-> _new_statement_t<offset_t<typename wrap_operand<Arg>::type>> -> _new_statement_t<offset_t<typename wrap_operand<Arg>::type>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), offset_t<typename wrap_operand<Arg>::type>{{arg}} }; return { *static_cast<typename Policies::_statement_t*>(this), offset_data_t<typename wrap_operand<Arg>::type>{{arg}} };
} }
auto dynamic_offset() auto dynamic_offset()
-> _new_statement_t<dynamic_offset_t<_database_t>> -> _new_statement_t<dynamic_offset_t<_database_t>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_offset must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_offset must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), dynamic_offset_t<_database_t>{} }; return { *static_cast<typename Policies::_statement_t*>(this), dynamic_offset_data_t<_database_t>{} };
} }
}; };
}; };
@ -162,17 +260,6 @@ namespace sqlpp
return context; return context;
} }
}; };
template<typename Context>
struct serializer_t<Context, no_offset_t>
{
using T = no_offset_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
} }
} }

View File

@ -39,73 +39,133 @@ namespace sqlpp
{ {
namespace vendor namespace vendor
{ {
template<typename Database,typename... Expressions> // ORDER BY DATA
struct order_by_t template<typename Database, typename... Expressions>
struct order_by_data_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::group_by>; order_by_data_t(Expressions... expressions):
using _recursive_traits = make_recursive_traits<Expressions...>;
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 sort-order expression required in order_by()");
static_assert(not ::sqlpp::detail::has_duplicates<Expressions...>::value, "at least one duplicate argument detected in order_by()");
static_assert(::sqlpp::detail::all_t<is_sort_order_t<Expressions>::value...>::value, "at least one argument is not a sort order expression in order_by()");
order_by_t& _order_by() { return *this; }
order_by_t(Expressions... expressions):
_expressions(expressions...) _expressions(expressions...)
{} {}
order_by_t(const order_by_t&) = default; order_by_data_t(const order_by_data_t&) = default;
order_by_t(order_by_t&&) = default; order_by_data_t(order_by_data_t&&) = default;
order_by_t& operator=(const order_by_t&) = default; order_by_data_t& operator=(const order_by_data_t&) = default;
order_by_t& operator=(order_by_t&&) = default; order_by_data_t& operator=(order_by_data_t&&) = default;
~order_by_t() = default; ~order_by_data_t() = default;
template<typename Policies>
struct _methods_t
{
template<typename Expression>
void add_order_by_ntc(Expression expression)
{
add_order_by<Expression, std::false_type>(expression);
}
template<typename Expression, typename TableCheckRequired = std::true_type>
void add_order_by(Expression expression)
{
static_assert(_is_dynamic::value, "add_order_by must not be called for static order_by");
static_assert(is_sort_order_t<Expression>::value, "invalid expression argument in add_order_by()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in add_order_by()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_sort_order_t<Expression>::value>;
_add_order_by_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename Expression>
void _add_order_by_impl(Expression expression, const std::true_type&)
{
return static_cast<typename Policies::_statement_t*>(this)->_order_by()._dynamic_expressions.emplace_back(expression);
}
template<typename Expression>
void _add_order_by_impl(Expression expression, const std::false_type&);
};
std::tuple<Expressions...> _expressions; std::tuple<Expressions...> _expressions;
vendor::interpretable_list_t<Database> _dynamic_expressions; vendor::interpretable_list_t<Database> _dynamic_expressions;
}; };
// ORDER BY
template<typename Database, typename... Expressions>
struct order_by_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::order_by>;
using _recursive_traits = make_recursive_traits<Expressions...>;
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 (e.g. a column) required in order_by()");
static_assert(not ::sqlpp::detail::has_duplicates<Expressions...>::value, "at least one duplicate argument detected in order_by()");
static_assert(::sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in order_by()");
// Data
using _data_t = select_flag_list_data_t<Database, 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);
}
template<typename Expression, typename TableCheckRequired = std::true_type>
void add(Expression expression)
{
static_assert(_is_dynamic::value, "add() must not be called for static order_by");
static_assert(is_expression_t<Expression>::value, "invalid expression argument in order_by::add()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in order_by::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
{
using _data_t = order_by_data_t<Database, Expressions...>;
_impl_t<Policies> order_by;
_impl_t<Policies>& operator()() { return order_by; }
const _impl_t<Policies>& operator()() const { return order_by; }
template<typename T>
static auto _get_member(T t) -> decltype(t.order_by)
{
return t.order_by;
}
};
template<typename Policies>
struct _methods_t
{
};
};
// NO ORDER BY YET
struct no_order_by_t struct no_order_by_t
{ {
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
using _data_t = no_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
{
using _data_t = no_data_t;
_impl_t<Policies> no_order_by;
_impl_t<Policies>& operator()() { return no_order_by; }
const _impl_t<Policies>& operator()() const { return no_order_by; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_order_by)
{
return t.no_order_by;
}
};
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
@ -117,7 +177,7 @@ namespace sqlpp
auto order_by(Args... args) auto order_by(Args... args)
-> _new_statement_t<order_by_t<void, Args...>> -> _new_statement_t<order_by_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), order_by_t<void, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), order_by_data_t<void, Args...>{args...} };
} }
template<typename... Args> template<typename... Args>
@ -125,16 +185,16 @@ namespace sqlpp
-> _new_statement_t<order_by_t<_database_t, Args...>> -> _new_statement_t<order_by_t<_database_t, Args...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_order_by must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_order_by must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), vendor::order_by_t<_database_t, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), order_by_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, order_by_t<Database, Expressions...>> struct serializer_t<Context, order_by_data_t<Database, Expressions...>>
{ {
using T = order_by_t<Database, Expressions...>; using T = order_by_data_t<Database, Expressions...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
@ -148,18 +208,6 @@ namespace sqlpp
return context; return context;
} }
}; };
template<typename Context>
struct serializer_t<Context, no_order_by_t>
{
using T = no_order_by_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
} }
} }

View File

@ -38,7 +38,7 @@ namespace sqlpp
{ {
namespace vendor namespace vendor
{ {
// SELECTED COLUMNS DATA // SELECTED FLAGS DATA
template<typename Database, typename... Flags> template<typename Database, typename... Flags>
struct select_flag_list_data_t struct select_flag_list_data_t
{ {

View File

@ -38,6 +38,7 @@ namespace sqlpp
{ {
namespace vendor namespace vendor
{ {
// WHERE DATA
template<typename Database, typename... Expressions> template<typename Database, typename... Expressions>
struct where_data_t struct where_data_t
{ {