0
0
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:
Roland Bock 2013-11-16 18:36:05 +01:00
parent 4b4048bd11
commit 5304e77f4a
11 changed files with 158 additions and 264 deletions

View File

@ -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;
};
}

View File

@ -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

View File

@ -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;
};
}

View File

@ -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>

View File

@ -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;
};
}

View File

@ -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;
};
}

View File

@ -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
};
}

View File

@ -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,
};

View File

@ -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;

View File

@ -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

View File

@ -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;