mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-15 20:31:16 +08:00
Streamlined usage of dynamic and non-dynamic method versions
from, where, having, group_py, order_by, using. Prepared on() as well
This commit is contained in:
parent
4b4048bd11
commit
5304e77f4a
@ -28,21 +28,21 @@
|
||||
#define SQLPP_FROM_H
|
||||
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
#include <sqlpp11/select_fwd.h>
|
||||
#include <sqlpp11/type_traits.h>
|
||||
#include <sqlpp11/detail/serializable.h>
|
||||
#include <sqlpp11/detail/serializable_list.h>
|
||||
#include <sqlpp11/detail/serialize_tuple.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
template<typename... TableOrJoin>
|
||||
template<typename Database, typename... TableOrJoin>
|
||||
struct from_t
|
||||
{
|
||||
using _is_from = std::true_type;
|
||||
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
||||
|
||||
// ensure one argument at least
|
||||
static_assert(sizeof...(TableOrJoin), "at least one table or join argument required in from()");
|
||||
static_assert(_is_dynamic::value or sizeof...(TableOrJoin), "at least one table or join argument required in from()");
|
||||
|
||||
// check for duplicate arguments
|
||||
static_assert(not detail::has_duplicates<TableOrJoin...>::value, "at least one duplicate argument detected in from()");
|
||||
@ -54,45 +54,25 @@ namespace sqlpp
|
||||
// FIXME: Joins contain two tables. This is not being dealt with at the moment
|
||||
|
||||
|
||||
template<typename Db>
|
||||
void serialize(std::ostream& os, Db& db) const
|
||||
{
|
||||
os << " FROM ";
|
||||
detail::serialize_tuple(os, db, _tables, ',');
|
||||
}
|
||||
|
||||
std::tuple<TableOrJoin...> _tables;
|
||||
};
|
||||
|
||||
template<typename Db>
|
||||
struct dynamic_from_t
|
||||
{
|
||||
using _is_from = std::true_type;
|
||||
using _is_dynamic = std::true_type;
|
||||
|
||||
template<typename Table>
|
||||
void add(Table&& table)
|
||||
{
|
||||
static_assert(is_table_t<typename std::decay<Table>::type>::value, "from arguments require to be tables or joins");
|
||||
_dynamic_tables.push_back(std::forward<Table>(table));
|
||||
_dynamic_tables.emplace_back(std::forward<Table>(table));
|
||||
}
|
||||
|
||||
template<typename Db>
|
||||
void serialize(std::ostream& os, Db& db) const
|
||||
{
|
||||
if (_dynamic_tables.empty())
|
||||
if (sizeof...(TableOrJoin) == 0 and _dynamic_tables.empty())
|
||||
return;
|
||||
os << " FROM ";
|
||||
bool first = true;
|
||||
for (const auto& table : _dynamic_tables)
|
||||
{
|
||||
if (not first)
|
||||
os << ',';
|
||||
table.serialize(os, db);
|
||||
first = false;
|
||||
}
|
||||
detail::serialize_tuple(os, db, _tables, ',');
|
||||
_dynamic_tables.serialize(os, db, sizeof...(TableOrJoin) == 0);
|
||||
}
|
||||
|
||||
std::vector<detail::serializable_t<Db>> _dynamic_tables;
|
||||
std::tuple<TableOrJoin...> _tables;
|
||||
detail::serializable_list<Database> _dynamic_tables;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -28,22 +28,24 @@
|
||||
#define SQLPP_GROUP_BY_H
|
||||
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
#include <tuple>
|
||||
#include <sqlpp11/select_fwd.h>
|
||||
#include <sqlpp11/expression.h>
|
||||
#include <sqlpp11/type_traits.h>
|
||||
#include <sqlpp11/detail/set.h>
|
||||
#include <sqlpp11/detail/serialize_tuple.h>
|
||||
#include <sqlpp11/detail/serializable.h>
|
||||
#include <sqlpp11/detail/serializable_list.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
template<typename... Expr>
|
||||
template<typename Database, typename... Expr>
|
||||
struct group_by_t
|
||||
{
|
||||
using _is_group_by = std::true_type;
|
||||
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
||||
|
||||
// ensure one argument at least
|
||||
static_assert(sizeof...(Expr), "at least one expression (e.g. a column) required in group_by()");
|
||||
static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression (e.g. a column) required in group_by()");
|
||||
|
||||
// check for duplicate expressions
|
||||
static_assert(not detail::has_duplicates<Expr...>::value, "at least one duplicate argument detected in group_by()");
|
||||
@ -52,52 +54,30 @@ namespace sqlpp
|
||||
using _valid_expressions = typename detail::make_set_if<is_expression_t, Expr...>::type;
|
||||
static_assert(_valid_expressions::size::value == sizeof...(Expr), "at least one argument is not an expression in group_by()");
|
||||
|
||||
using _is_group_by = std::true_type;
|
||||
template<typename E>
|
||||
void add(E&& expr)
|
||||
{
|
||||
static_assert(is_table_t<typename std::decay<E>::type>::value, "from arguments require to be tables or joins");
|
||||
_dynamic_expressions.emplace_back(std::forward<E>(expr));
|
||||
}
|
||||
|
||||
template<typename Db>
|
||||
void serialize(std::ostream& os, Db& db) const
|
||||
{
|
||||
static_assert(Db::_supports_group_by, "group_by() not supported by current database");
|
||||
if (sizeof...(Expr) == 0 and _dynamic_expressions.empty())
|
||||
return;
|
||||
|
||||
os << " GROUP BY ";
|
||||
detail::serialize_tuple(os, db, _expressions, ',');
|
||||
_dynamic_expressions.serialize(os, db, sizeof...(Expr) == 0);
|
||||
}
|
||||
|
||||
std::tuple<Expr...> _expressions;
|
||||
detail::serializable_list<Database> _dynamic_expressions;
|
||||
|
||||
};
|
||||
|
||||
template<typename Db>
|
||||
struct dynamic_group_by_t
|
||||
{
|
||||
using _is_group_by = std::true_type;
|
||||
using _is_dynamic = std::true_type;
|
||||
|
||||
template<typename Expr>
|
||||
void add(Expr&& expr)
|
||||
{
|
||||
static_assert(is_expression_t<typename std::decay<Expr>::type>::value, "group_by arguments require to be expressions");
|
||||
_expressions.push_back(std::forward<Expr>(expr));
|
||||
}
|
||||
|
||||
void serialize(std::ostream& os, Db& db) const
|
||||
{
|
||||
static_assert(Db::_supports_group_by, "group_by() not supported by current database");
|
||||
if (_expressions.empty())
|
||||
return;
|
||||
os << " GROUP BY ";
|
||||
bool first = true;
|
||||
for (const auto& expr : _expressions)
|
||||
{
|
||||
if (not first)
|
||||
os << ',';
|
||||
expr.serialize(os, db);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<detail::serializable_t<Db>> _expressions;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -28,64 +28,45 @@
|
||||
#define SQLPP_HAVING_H
|
||||
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
#include <sqlpp11/type_traits.h>
|
||||
#include <sqlpp11/expression.h>
|
||||
#include <sqlpp11/detail/set.h>
|
||||
#include <sqlpp11/detail/serializable.h>
|
||||
#include <sqlpp11/detail/serialize_tuple.h>
|
||||
#include <sqlpp11/detail/serializable_list.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
template<typename Expr>
|
||||
template<typename Database, typename... Expr>
|
||||
struct having_t
|
||||
{
|
||||
static_assert(is_expression_t<Expr>::value, "invalid expression argument in having()");
|
||||
|
||||
using _is_having = std::true_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...(Expr), "at least one expression argument required in having()");
|
||||
using _valid_expressions = typename detail::make_set_if<is_expression_t, Expr...>::type;
|
||||
static_assert(_valid_expressions::size::value == sizeof...(Expr), "at least one argument is not an expression in having()");
|
||||
|
||||
template<typename E>
|
||||
void add(E&& expr)
|
||||
{
|
||||
static_assert(is_expression_t<typename std::decay<E>::type>::value, "invalid expression argument in add_having()");
|
||||
_dynamic_expressions.emplace_back(std::forward<E>(expr));
|
||||
}
|
||||
|
||||
template<typename Db>
|
||||
void serialize(std::ostream& os, Db& db) const
|
||||
{
|
||||
static_assert(Db::_supports_having, "having() not supported by current database");
|
||||
os << " HAVING ";
|
||||
_expr.serialize(os, db);
|
||||
}
|
||||
|
||||
Expr _expr;
|
||||
};
|
||||
|
||||
template<typename Db>
|
||||
struct dynamic_having_t
|
||||
{
|
||||
|
||||
using _is_having = std::true_type;
|
||||
using _is_dynamic = std::true_type;
|
||||
|
||||
template<typename Expr>
|
||||
void add(Expr&& expr)
|
||||
{
|
||||
static_assert(is_expression_t<typename std::decay<Expr>::type>::value, "invalid expression argument in having()");
|
||||
_conditions.push_back(std::forward<Expr>(expr));
|
||||
}
|
||||
|
||||
void serialize(std::ostream& os, Db& db) const
|
||||
{
|
||||
static_assert(Db::_supports_having, "having() not supported by current database");
|
||||
if (_conditions.empty())
|
||||
if (sizeof...(Expr) == 0 and _dynamic_expressions.empty())
|
||||
return;
|
||||
|
||||
os << " HAVING ";
|
||||
bool first = true;
|
||||
for (const auto& condition : _conditions)
|
||||
{
|
||||
if (not first)
|
||||
os << " AND ";
|
||||
condition.serialize(os, db);
|
||||
first = false;
|
||||
}
|
||||
detail::serialize_tuple(os, db, _expressions, " AND ");
|
||||
_dynamic_expressions.serialize(os, db, " AND ", sizeof...(Expr) == 0);
|
||||
}
|
||||
|
||||
std::vector<detail::serializable_t<Db>> _conditions;
|
||||
std::tuple<Expr...> _expressions;
|
||||
detail::serializable_list<Database> _dynamic_expressions;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -88,10 +88,15 @@ namespace sqlpp
|
||||
template<typename OnT>
|
||||
using set_on_t = join_t<JoinType, Lhs, Rhs, OnT>;
|
||||
|
||||
template<typename Expr>
|
||||
set_on_t<on_t<typename std::decay<Expr>::type>> on(Expr&& expr)
|
||||
template<typename... Expr>
|
||||
auto on(Expr&&... expr)
|
||||
-> set_on_t<on_t<void, typename std::decay<Expr>::type...>>
|
||||
{
|
||||
return { _lhs, _rhs, {std::forward<Expr>(expr)} };
|
||||
static_assert(is_noop<On>::value, "cannot call on() twice for a single join()");
|
||||
return { _lhs,
|
||||
_rhs,
|
||||
{std::tuple<typename std::decay<Expr>::type...>{std::forward<Expr>(expr)...}}
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
@ -28,60 +28,41 @@
|
||||
#define SQLPP_ON_H
|
||||
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
#include <sqlpp11/type_traits.h>
|
||||
#include <sqlpp11/detail/serializable.h>
|
||||
#include <sqlpp11/detail/serialize_tuple.h>
|
||||
#include <sqlpp11/detail/serializable_list.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
template<typename Expr>
|
||||
template<typename Database, typename... Expr>
|
||||
struct on_t
|
||||
{
|
||||
static_assert(is_expression_t<Expr>::value, "invalid expression argument in on()");
|
||||
|
||||
using _is_on = std::true_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...(Expr), "at least one expression argument required in on()");
|
||||
using _valid_expressions = typename detail::make_set_if<is_expression_t, Expr...>::type;
|
||||
static_assert(_valid_expressions::size::value == sizeof...(Expr), "at least one argument is not an expression in on()");
|
||||
|
||||
template<typename E>
|
||||
void add(E&& expr)
|
||||
{
|
||||
static_assert(is_expression_t<typename std::decay<E>::type>::value, "invalid expression argument in add_on()");
|
||||
_dynamic_expressions.emplace_back(std::forward<E>(expr));
|
||||
}
|
||||
|
||||
template<typename Db>
|
||||
void serialize(std::ostream& os, Db& db) const
|
||||
{
|
||||
os << " ON ";
|
||||
_expr.serialize(os, db);
|
||||
}
|
||||
|
||||
Expr _expr;
|
||||
};
|
||||
|
||||
template<typename Db>
|
||||
struct dynamic_on_t
|
||||
{
|
||||
|
||||
using _is_on = std::true_type;
|
||||
using _is_dynamic = std::true_type;
|
||||
|
||||
template<typename Expr>
|
||||
void add(Expr&& expr)
|
||||
{
|
||||
static_assert(is_expression_t<typename std::decay<Expr>::type>::value, "invalid expression argument in on()");
|
||||
_conditions.push_back(std::forward<Expr>(expr));
|
||||
}
|
||||
|
||||
void serialize(std::ostream& os, Db& db) const
|
||||
{
|
||||
if (_conditions.empty())
|
||||
if (sizeof...(Expr) == 0 and _dynamic_expressions.empty())
|
||||
return;
|
||||
|
||||
os << " ON ";
|
||||
bool first = true;
|
||||
for (const auto& condition : _conditions)
|
||||
{
|
||||
if (not first)
|
||||
os << " AND ";
|
||||
condition.serialize(os, db);
|
||||
first = false;
|
||||
}
|
||||
detail::serialize_tuple(os, db, _expressions, " AND ");
|
||||
_dynamic_expressions.serialize(os, db, " AND ", sizeof...(Expr) == 0);
|
||||
}
|
||||
|
||||
std::vector<detail::serializable_t<Db>> _conditions;
|
||||
std::tuple<Expr...> _expressions;
|
||||
detail::serializable_list<Database> _dynamic_expressions;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -36,62 +36,43 @@
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
template<typename... OrderExpr>
|
||||
template<typename Database,typename... Expr>
|
||||
struct order_by_t
|
||||
{
|
||||
using _is_order_by = std::true_type;
|
||||
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
||||
|
||||
// check for at least one order expression
|
||||
static_assert(sizeof...(OrderExpr), "at least one sort-order expression required in order_by()");
|
||||
static_assert(_is_dynamic::value or sizeof...(Expr), "at least one sort-order expression required in order_by()");
|
||||
|
||||
// check for duplicate order expressions
|
||||
static_assert(not detail::has_duplicates<OrderExpr...>::value, "at least one duplicate argument detected in order_by()");
|
||||
static_assert(not detail::has_duplicates<Expr...>::value, "at least one duplicate argument detected in order_by()");
|
||||
|
||||
// check for invalid order expressions
|
||||
using _valid_expressions = typename detail::make_set_if<is_sort_order_t, OrderExpr...>::type;
|
||||
static_assert(_valid_expressions::size::value == sizeof...(OrderExpr), "at least one argument is not a sort order expression in order_by()");
|
||||
using _valid_expressions = typename detail::make_set_if<is_sort_order_t, Expr...>::type;
|
||||
static_assert(_valid_expressions::size::value == sizeof...(Expr), "at least one argument is not a sort order expression in order_by()");
|
||||
|
||||
using _is_order_by = std::true_type;
|
||||
template<typename E>
|
||||
void add(E&& expr)
|
||||
{
|
||||
static_assert(is_sort_order_t<typename std::decay<E>::type>::value, "order_by arguments require to be sort-order expressions");
|
||||
_dynamic_expressions.push_back(std::forward<E>(expr));
|
||||
}
|
||||
|
||||
template<typename Db>
|
||||
void serialize(std::ostream& os, Db& db) const
|
||||
{
|
||||
static_assert(Db::_supports_order_by, "order by not supported by current database");
|
||||
os << " ORDER BY ";
|
||||
detail::serialize_tuple(os, db, _orderExpressions, ',');
|
||||
}
|
||||
|
||||
std::tuple<OrderExpr...> _orderExpressions;
|
||||
};
|
||||
|
||||
template<typename Db>
|
||||
struct dynamic_order_by_t
|
||||
{
|
||||
using _is_order_by = std::true_type;
|
||||
using _is_dynamic = std::true_type;
|
||||
|
||||
template<typename Expr>
|
||||
void add(Expr&& expr)
|
||||
{
|
||||
static_assert(is_sort_order_t<typename std::decay<Expr>::type>::value, "order_by arguments require to be sort-order expressions");
|
||||
_expressions.push_back(std::forward<Expr>(expr));
|
||||
}
|
||||
|
||||
void serialize(std::ostream& os, Db& db) const
|
||||
{
|
||||
static_assert(Db::_supports_order_by, "order by not supported by current database");
|
||||
if (_expressions.empty())
|
||||
if (sizeof...(Expr) == 0 and _dynamic_expressions.empty())
|
||||
return;
|
||||
|
||||
os << " ORDER BY ";
|
||||
bool first = true;
|
||||
for (const auto& expr : _expressions)
|
||||
{
|
||||
if (not first)
|
||||
os << ',';
|
||||
expr.serialize(os, db);
|
||||
first = false;
|
||||
}
|
||||
detail::serialize_tuple(os, db, _expressions, ',');
|
||||
_dynamic_expressions.serialize(os, db, sizeof...(Expr) == 0);
|
||||
}
|
||||
|
||||
std::vector<detail::serializable_t<Db>> _expressions;
|
||||
std::tuple<Expr...> _expressions;
|
||||
detail::serializable_list<Database> _dynamic_expressions;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ namespace sqlpp
|
||||
|
||||
template<typename... Tab>
|
||||
auto using_(Tab&&... tab)
|
||||
-> set_using_t<using_t<typename std::decay<Tab>::type...>>
|
||||
-> set_using_t<using_t<void, typename std::decay<Tab>::type...>>
|
||||
{
|
||||
static_assert(std::is_same<Using, noop>::value, "cannot call using() twice");
|
||||
static_assert(std::is_same<Where, noop>::value, "cannot call using() after where()");
|
||||
@ -73,14 +73,15 @@ namespace sqlpp
|
||||
};
|
||||
}
|
||||
|
||||
auto dynamic_using_()
|
||||
-> set_using_t<dynamic_using_t<Database>>
|
||||
template<typename... Tab>
|
||||
auto dynamic_using_(Tab&&... tab)
|
||||
-> set_using_t<using_t<Database, typename std::decay<Tab>::type...>>
|
||||
{
|
||||
static_assert(std::is_same<Using, noop>::value, "cannot call using() twice");
|
||||
static_assert(std::is_same<Where, noop>::value, "cannot call using() after where()");
|
||||
return {
|
||||
_table,
|
||||
{{}},
|
||||
{std::tuple<typename std::decay<Tab>::type...>{std::forward<Tab>(tab)...}},
|
||||
_where
|
||||
};
|
||||
}
|
||||
|
@ -196,7 +196,7 @@ namespace sqlpp
|
||||
// sqlpp functions
|
||||
template<typename... Table>
|
||||
auto from(Table&&... table)
|
||||
-> set_from_t<from_t<typename std::decay<Table>::type...>>
|
||||
-> set_from_t<from_t<void, typename std::decay<Table>::type...>>
|
||||
{
|
||||
static_assert(not is_noop<ExpressionList>::value, "cannot call from() without having selected anything");
|
||||
static_assert(is_noop<From>::value, "cannot call from() twice for a single select");
|
||||
@ -213,8 +213,9 @@ namespace sqlpp
|
||||
};
|
||||
}
|
||||
|
||||
auto dynamic_from()
|
||||
-> set_from_t<dynamic_from_t<Database>>
|
||||
template<typename... Table>
|
||||
auto dynamic_from(Table&&... table)
|
||||
-> set_from_t<from_t<Database, typename std::decay<Table>::type...>>
|
||||
{
|
||||
static_assert(not std::is_same<Database, void>::value, "cannot call dynamic_from() in a non-dynamic select");
|
||||
static_assert(not is_noop<ExpressionList>::value, "cannot call from() without having selected anything");
|
||||
@ -222,7 +223,7 @@ namespace sqlpp
|
||||
return {
|
||||
_flags,
|
||||
_expression_list,
|
||||
{{}},
|
||||
{std::tuple<typename std::decay<Table>::type...>{std::forward<Table>(table)...}},
|
||||
_where,
|
||||
_group_by,
|
||||
_having,
|
||||
@ -293,7 +294,7 @@ namespace sqlpp
|
||||
|
||||
template<typename... Col>
|
||||
auto group_by(Col&&... column)
|
||||
-> set_group_by_t<group_by_t<typename std::decay<Col>::type...>>
|
||||
-> set_group_by_t<group_by_t<void, typename std::decay<Col>::type...>>
|
||||
{
|
||||
static_assert(not is_noop<From>::value, "cannot call group_by() without a from()");
|
||||
static_assert(is_noop<GroupBy>::value, "cannot call group_by() twice for a single select");
|
||||
@ -310,8 +311,9 @@ namespace sqlpp
|
||||
};
|
||||
}
|
||||
|
||||
auto group_by()
|
||||
-> set_group_by_t<group_by_t<Database>>
|
||||
template<typename... Col>
|
||||
auto dynamic_group_by(Col&&... column)
|
||||
-> set_group_by_t<group_by_t<Database, typename std::decay<Col>::type...>>
|
||||
{
|
||||
static_assert(not is_noop<From>::value, "cannot call group_by() without a from()");
|
||||
static_assert(is_noop<GroupBy>::value, "cannot call group_by() twice for a single select");
|
||||
@ -320,7 +322,7 @@ namespace sqlpp
|
||||
_expression_list,
|
||||
_from,
|
||||
_where,
|
||||
{{}},
|
||||
{std::tuple<typename std::decay<Col>::type...>{std::forward<Col>(column)...}},
|
||||
_having,
|
||||
_order_by,
|
||||
_limit,
|
||||
@ -338,9 +340,9 @@ namespace sqlpp
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Expr>
|
||||
auto having(Expr&& expr)
|
||||
-> set_having_t<having_t<typename std::decay<Expr>::type>>
|
||||
template<typename... Expr>
|
||||
auto having(Expr&&... expr)
|
||||
-> set_having_t<having_t<void, typename std::decay<Expr>::type...>>
|
||||
{
|
||||
static_assert(not is_noop<GroupBy>::value, "cannot call having() without a group_by");
|
||||
static_assert(is_noop<Having>::value, "cannot call having() twice for a single select");
|
||||
@ -350,15 +352,16 @@ namespace sqlpp
|
||||
_from,
|
||||
_where,
|
||||
_group_by,
|
||||
{std::forward<Expr>(expr)},
|
||||
{std::tuple<typename std::decay<Expr>::type...>{std::forward<Expr>(expr)...}},
|
||||
_order_by,
|
||||
_limit,
|
||||
_offset,
|
||||
};
|
||||
}
|
||||
|
||||
auto dynamic_having()
|
||||
-> set_having_t<dynamic_having_t<Database>>
|
||||
template<typename... Expr>
|
||||
auto dynamic_having(Expr&&... expr)
|
||||
-> set_having_t<having_t<Database, typename std::decay<Expr>::type...>>
|
||||
{
|
||||
static_assert(not is_noop<GroupBy>::value, "cannot call having() without a group_by");
|
||||
static_assert(is_noop<Having>::value, "cannot call having() twice for a single select");
|
||||
@ -368,7 +371,7 @@ namespace sqlpp
|
||||
_from,
|
||||
_where,
|
||||
_group_by,
|
||||
{{}},
|
||||
{std::tuple<typename std::decay<Expr>::type...>{std::forward<Expr>(expr)...}},
|
||||
_order_by,
|
||||
_limit,
|
||||
_offset,
|
||||
@ -387,7 +390,7 @@ namespace sqlpp
|
||||
|
||||
template<typename... OrderExpr>
|
||||
auto order_by(OrderExpr&&... expr)
|
||||
-> set_order_by_t<order_by_t<typename std::decay<OrderExpr>::type...>>
|
||||
-> set_order_by_t<order_by_t<void, typename std::decay<OrderExpr>::type...>>
|
||||
{
|
||||
static_assert(not is_noop<From>::value, "cannot call order_by() without a from()");
|
||||
static_assert(is_noop<OrderBy>::value, "cannot call order_by() twice for a single select");
|
||||
@ -404,8 +407,9 @@ namespace sqlpp
|
||||
};
|
||||
}
|
||||
|
||||
auto dynamic_order_by()
|
||||
-> set_order_by_t<dynamic_order_by_t<Database>>
|
||||
template<typename... OrderExpr>
|
||||
auto dynamic_order_by(OrderExpr&&... expr)
|
||||
-> set_order_by_t<order_by_t<Database, typename std::decay<OrderExpr>::type...>>
|
||||
{
|
||||
static_assert(not is_noop<From>::value, "cannot call order_by() without a from()");
|
||||
static_assert(is_noop<OrderBy>::value, "cannot call order_by() twice for a single select");
|
||||
@ -416,7 +420,7 @@ namespace sqlpp
|
||||
_where,
|
||||
_group_by,
|
||||
_having,
|
||||
{{}},
|
||||
{std::tuple<typename std::decay<OrderExpr>::type...>{std::forward<OrderExpr>(expr)...}},
|
||||
_limit,
|
||||
_offset,
|
||||
};
|
||||
|
@ -40,15 +40,15 @@ namespace sqlpp
|
||||
template<typename FlagTuple> struct select_flag_list_t;
|
||||
template<typename Database, typename NamedExprTuple> struct select_expression_list_t;
|
||||
|
||||
template<typename... TableOrJoin> struct from_t;
|
||||
template<typename Database, typename... TableOrJoin> struct from_t;
|
||||
|
||||
template<typename Database, typename... Expr> struct where_t;
|
||||
|
||||
template<typename... Expr> struct group_by_t;
|
||||
template<typename Database, typename... Expr> struct group_by_t;
|
||||
|
||||
template<typename Expr> struct having_t;
|
||||
template<typename Database, typename... Expr> struct having_t;
|
||||
|
||||
template<typename... Expr> struct order_by_t;
|
||||
template<typename Database, typename... Expr> struct order_by_t;
|
||||
|
||||
struct limit_t;
|
||||
|
||||
|
@ -30,17 +30,18 @@
|
||||
#include <ostream>
|
||||
#include <sqlpp11/type_traits.h>
|
||||
#include <sqlpp11/detail/set.h>
|
||||
#include <sqlpp11/detail/serializable_list.h>
|
||||
#include <sqlpp11/detail/serialize_tuple.h>
|
||||
#include <sqlpp11/detail/serializable.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
template<typename... Table>
|
||||
template<typename Database, typename... Table>
|
||||
struct using_t
|
||||
{
|
||||
using _is_using = std::true_type;
|
||||
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
||||
|
||||
static_assert(sizeof...(Table), "at least one table argument required in using()");
|
||||
static_assert(_is_dynamic::value or sizeof...(Table), "at least one table argument required in using()");
|
||||
|
||||
// check for duplicate arguments
|
||||
static_assert(not detail::has_duplicates<Table...>::value, "at least one duplicate argument detected in using()");
|
||||
@ -50,46 +51,27 @@ namespace sqlpp
|
||||
static_assert(_valid_expressions::size::value == sizeof...(Table), "at least one argument is not an table in using()");
|
||||
|
||||
|
||||
template<typename T>
|
||||
void add(T&& table)
|
||||
{
|
||||
static_assert(is_table_t<typename std::decay<T>::type>::value, "using() arguments require to be tables");
|
||||
_dynamic_tables.emplace_back(std::forward<T>(table));
|
||||
}
|
||||
|
||||
template<typename Db>
|
||||
void serialize(std::ostream& os, Db& db) const
|
||||
{
|
||||
if (sizeof...(Table) == 0 and _dynamic_tables.empty())
|
||||
return;
|
||||
os << " USING ";
|
||||
detail::serialize_tuple(os, db, _tables, ',');
|
||||
_dynamic_tables.serialize(os, db, sizeof...(Table) == 0);
|
||||
}
|
||||
|
||||
std::tuple<Table...> _tables;
|
||||
detail::serializable_list<Database> _dynamic_tables;
|
||||
};
|
||||
|
||||
template<typename Db>
|
||||
struct dynamic_using_t
|
||||
{
|
||||
using _is_using = std::true_type;
|
||||
using _is_dynamic = std::true_type;
|
||||
|
||||
template<typename Table>
|
||||
void add(Table&& table)
|
||||
{
|
||||
static_assert(is_table_t<typename std::decay<Table>::type>::value, "using arguments require to be tables");
|
||||
_dynamic_tables.push_back(std::forward<Table>(table));
|
||||
}
|
||||
|
||||
void serialize(std::ostream& os, Db& db) const
|
||||
{
|
||||
if (_dynamic_tables.empty())
|
||||
return;
|
||||
os << " USING ";
|
||||
bool first = true;
|
||||
for (const auto& table : _dynamic_tables)
|
||||
{
|
||||
if (not first)
|
||||
os << ',';
|
||||
table.serialize(os, db);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<detail::serializable_t<Db>> _dynamic_tables;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -51,7 +51,6 @@ namespace sqlpp
|
||||
void add(E&& expr)
|
||||
{
|
||||
static_assert(is_expression_t<typename std::decay<E>::type>::value, "invalid expression argument in add_where()");
|
||||
static_assert(_is_dynamic::value, "cannot add expressions to a non-dynamic where()");
|
||||
_dynamic_expressions.emplace_back(std::forward<E>(expr));
|
||||
}
|
||||
|
||||
@ -62,7 +61,7 @@ namespace sqlpp
|
||||
return;
|
||||
os << " WHERE ";
|
||||
detail::serialize_tuple(os, db, _expressions, " AND ");
|
||||
_dynamic_expressions.serialize(os, db, " AND ", true);
|
||||
_dynamic_expressions.serialize(os, db, " AND ", sizeof...(Expr) == 0);
|
||||
}
|
||||
|
||||
std::tuple<Expr...> _expressions;
|
||||
|
Loading…
Reference in New Issue
Block a user