diff --git a/include/sqlpp11/from.h b/include/sqlpp11/from.h index ee63fdcc..7e10c0b8 100644 --- a/include/sqlpp11/from.h +++ b/include/sqlpp11/from.h @@ -28,21 +28,21 @@ #define SQLPP_FROM_H #include -#include #include #include -#include +#include #include namespace sqlpp { - template + template struct from_t { using _is_from = std::true_type; + using _is_dynamic = typename std::conditional::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::value, "at least one duplicate argument detected in from()"); @@ -54,46 +54,26 @@ namespace sqlpp // FIXME: Joins contain two tables. This is not being dealt with at the moment + template + void add(Table&& table) + { + static_assert(is_table_t::type>::value, "from arguments require to be tables or joins"); + _dynamic_tables.emplace_back(std::forward(table)); + } + template void serialize(std::ostream& os, Db& db) const { + if (sizeof...(TableOrJoin) == 0 and _dynamic_tables.empty()) + return; os << " FROM "; detail::serialize_tuple(os, db, _tables, ','); + _dynamic_tables.serialize(os, db, sizeof...(TableOrJoin) == 0); } std::tuple _tables; + detail::serializable_list _dynamic_tables; }; - - template - struct dynamic_from_t - { - using _is_from = std::true_type; - using _is_dynamic = std::true_type; - - template - void add(Table&& table) - { - static_assert(is_table_t::type>::value, "from arguments require to be tables or joins"); - _dynamic_tables.push_back(std::forward
(table)); - } - - void serialize(std::ostream& os, Db& db) const - { - if (_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; - } - } - - std::vector> _dynamic_tables; - }; } #endif diff --git a/include/sqlpp11/group_by.h b/include/sqlpp11/group_by.h index 945cb6e7..35312d0a 100644 --- a/include/sqlpp11/group_by.h +++ b/include/sqlpp11/group_by.h @@ -28,22 +28,24 @@ #define SQLPP_GROUP_BY_H #include -#include #include #include #include #include #include #include -#include +#include namespace sqlpp { - template + template struct group_by_t { + using _is_group_by = std::true_type; + using _is_dynamic = typename std::conditional::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::value, "at least one duplicate argument detected in group_by()"); @@ -52,52 +54,30 @@ namespace sqlpp using _valid_expressions = typename detail::make_set_if::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 + void add(E&& expr) + { + static_assert(is_table_t::type>::value, "from arguments require to be tables or joins"); + _dynamic_expressions.emplace_back(std::forward(expr)); + } template 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 _expressions; + detail::serializable_list _dynamic_expressions; }; - template - struct dynamic_group_by_t - { - using _is_group_by = std::true_type; - using _is_dynamic = std::true_type; - - template - void add(Expr&& expr) - { - static_assert(is_expression_t::type>::value, "group_by arguments require to be expressions"); - _expressions.push_back(std::forward(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> _expressions; - }; - } #endif diff --git a/include/sqlpp11/having.h b/include/sqlpp11/having.h index 1ae9cc21..0547a969 100644 --- a/include/sqlpp11/having.h +++ b/include/sqlpp11/having.h @@ -28,66 +28,47 @@ #define SQLPP_HAVING_H #include -#include #include #include #include -#include +#include +#include namespace sqlpp { - template + template struct having_t { - static_assert(is_expression_t::value, "invalid expression argument in having()"); - using _is_having = std::true_type; + using _is_dynamic = typename std::conditional::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::type; + static_assert(_valid_expressions::size::value == sizeof...(Expr), "at least one argument is not an expression in having()"); + + template + void add(E&& expr) + { + static_assert(is_expression_t::type>::value, "invalid expression argument in add_having()"); + _dynamic_expressions.emplace_back(std::forward(expr)); + } template void serialize(std::ostream& os, Db& db) const { static_assert(Db::_supports_having, "having() not supported by current database"); + + if (sizeof...(Expr) == 0 and _dynamic_expressions.empty()) + return; os << " HAVING "; - _expr.serialize(os, db); + detail::serialize_tuple(os, db, _expressions, " AND "); + _dynamic_expressions.serialize(os, db, " AND ", sizeof...(Expr) == 0); } - Expr _expr; + std::tuple _expressions; + detail::serializable_list _dynamic_expressions; }; - template - struct dynamic_having_t - { - - using _is_having = std::true_type; - using _is_dynamic = std::true_type; - - template - void add(Expr&& expr) - { - static_assert(is_expression_t::type>::value, "invalid expression argument in having()"); - _conditions.push_back(std::forward(expr)); - } - - void serialize(std::ostream& os, Db& db) const - { - static_assert(Db::_supports_having, "having() not supported by current database"); - if (_conditions.empty()) - return; - - os << " HAVING "; - bool first = true; - for (const auto& condition : _conditions) - { - if (not first) - os << " AND "; - condition.serialize(os, db); - first = false; - } - } - - std::vector> _conditions; - }; - } #endif diff --git a/include/sqlpp11/join.h b/include/sqlpp11/join.h index 8265a0d3..bebc0993 100644 --- a/include/sqlpp11/join.h +++ b/include/sqlpp11/join.h @@ -88,10 +88,15 @@ namespace sqlpp template using set_on_t = join_t; - template - set_on_t::type>> on(Expr&& expr) + template + auto on(Expr&&... expr) + -> set_on_t::type...>> { - return { _lhs, _rhs, {std::forward(expr)} }; + static_assert(is_noop::value, "cannot call on() twice for a single join()"); + return { _lhs, + _rhs, + {std::tuple::type...>{std::forward(expr)...}} + }; } template diff --git a/include/sqlpp11/on.h b/include/sqlpp11/on.h index a4c33bf9..bfadfa9a 100644 --- a/include/sqlpp11/on.h +++ b/include/sqlpp11/on.h @@ -28,62 +28,43 @@ #define SQLPP_ON_H #include -#include #include -#include +#include +#include namespace sqlpp { - template + template struct on_t { - static_assert(is_expression_t::value, "invalid expression argument in on()"); - using _is_on = std::true_type; + using _is_dynamic = typename std::conditional::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::type; + static_assert(_valid_expressions::size::value == sizeof...(Expr), "at least one argument is not an expression in on()"); + + template + void add(E&& expr) + { + static_assert(is_expression_t::type>::value, "invalid expression argument in add_on()"); + _dynamic_expressions.emplace_back(std::forward(expr)); + } template void serialize(std::ostream& os, Db& db) const { + if (sizeof...(Expr) == 0 and _dynamic_expressions.empty()) + return; os << " ON "; - _expr.serialize(os, db); + detail::serialize_tuple(os, db, _expressions, " AND "); + _dynamic_expressions.serialize(os, db, " AND ", sizeof...(Expr) == 0); } - Expr _expr; + std::tuple _expressions; + detail::serializable_list _dynamic_expressions; }; - template - struct dynamic_on_t - { - - using _is_on = std::true_type; - using _is_dynamic = std::true_type; - - template - void add(Expr&& expr) - { - static_assert(is_expression_t::type>::value, "invalid expression argument in on()"); - _conditions.push_back(std::forward(expr)); - } - - void serialize(std::ostream& os, Db& db) const - { - if (_conditions.empty()) - return; - - os << " ON "; - bool first = true; - for (const auto& condition : _conditions) - { - if (not first) - os << " AND "; - condition.serialize(os, db); - first = false; - } - } - - std::vector> _conditions; - }; - } #endif diff --git a/include/sqlpp11/order_by.h b/include/sqlpp11/order_by.h index 3c5cd10a..e8c5d22d 100644 --- a/include/sqlpp11/order_by.h +++ b/include/sqlpp11/order_by.h @@ -36,62 +36,43 @@ namespace sqlpp { - template + template struct order_by_t { + using _is_order_by = std::true_type; + using _is_dynamic = typename std::conditional::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::value, "at least one duplicate argument detected in order_by()"); + static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected in order_by()"); // check for invalid order expressions - using _valid_expressions = typename detail::make_set_if::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::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 + void add(E&& expr) + { + static_assert(is_sort_order_t::type>::value, "order_by arguments require to be sort-order expressions"); + _dynamic_expressions.push_back(std::forward(expr)); + } template void serialize(std::ostream& os, Db& db) const { static_assert(Db::_supports_order_by, "order by not supported by current database"); + if (sizeof...(Expr) == 0 and _dynamic_expressions.empty()) + return; + os << " ORDER BY "; - detail::serialize_tuple(os, db, _orderExpressions, ','); + detail::serialize_tuple(os, db, _expressions, ','); + _dynamic_expressions.serialize(os, db, sizeof...(Expr) == 0); } - std::tuple _orderExpressions; - }; - - template - struct dynamic_order_by_t - { - using _is_order_by = std::true_type; - using _is_dynamic = std::true_type; - - template - void add(Expr&& expr) - { - static_assert(is_sort_order_t::type>::value, "order_by arguments require to be sort-order expressions"); - _expressions.push_back(std::forward(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()) - return; - os << " ORDER BY "; - bool first = true; - for (const auto& expr : _expressions) - { - if (not first) - os << ','; - expr.serialize(os, db); - first = false; - } - } - - std::vector> _expressions; + std::tuple _expressions; + detail::serializable_list _dynamic_expressions; }; } diff --git a/include/sqlpp11/remove.h b/include/sqlpp11/remove.h index 5a88ad40..e657f87a 100644 --- a/include/sqlpp11/remove.h +++ b/include/sqlpp11/remove.h @@ -62,7 +62,7 @@ namespace sqlpp template auto using_(Tab&&... tab) - -> set_using_t::type...>> + -> set_using_t::type...>> { static_assert(std::is_same::value, "cannot call using() twice"); static_assert(std::is_same::value, "cannot call using() after where()"); @@ -73,14 +73,15 @@ namespace sqlpp }; } - auto dynamic_using_() - -> set_using_t> + template + auto dynamic_using_(Tab&&... tab) + -> set_using_t::type...>> { static_assert(std::is_same::value, "cannot call using() twice"); static_assert(std::is_same::value, "cannot call using() after where()"); return { _table, - {{}}, + {std::tuple::type...>{std::forward(tab)...}}, _where }; } diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 5f215d2d..d2b8a3d0 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -196,7 +196,7 @@ namespace sqlpp // sqlpp functions template auto from(Table&&... table) - -> set_from_t::type...>> + -> set_from_t::type...>> { static_assert(not is_noop::value, "cannot call from() without having selected anything"); static_assert(is_noop::value, "cannot call from() twice for a single select"); @@ -213,8 +213,9 @@ namespace sqlpp }; } - auto dynamic_from() - -> set_from_t> + template + auto dynamic_from(Table&&... table) + -> set_from_t::type...>> { static_assert(not std::is_same::value, "cannot call dynamic_from() in a non-dynamic select"); static_assert(not is_noop::value, "cannot call from() without having selected anything"); @@ -222,7 +223,7 @@ namespace sqlpp return { _flags, _expression_list, - {{}}, + {std::tuple::type...>{std::forward
(table)...}}, _where, _group_by, _having, @@ -293,7 +294,7 @@ namespace sqlpp template auto group_by(Col&&... column) - -> set_group_by_t::type...>> + -> set_group_by_t::type...>> { static_assert(not is_noop::value, "cannot call group_by() without a from()"); static_assert(is_noop::value, "cannot call group_by() twice for a single select"); @@ -310,8 +311,9 @@ namespace sqlpp }; } - auto group_by() - -> set_group_by_t> + template + auto dynamic_group_by(Col&&... column) + -> set_group_by_t::type...>> { static_assert(not is_noop::value, "cannot call group_by() without a from()"); static_assert(is_noop::value, "cannot call group_by() twice for a single select"); @@ -320,7 +322,7 @@ namespace sqlpp _expression_list, _from, _where, - {{}}, + {std::tuple::type...>{std::forward(column)...}}, _having, _order_by, _limit, @@ -338,9 +340,9 @@ namespace sqlpp return *this; } - template - auto having(Expr&& expr) - -> set_having_t::type>> + template + auto having(Expr&&... expr) + -> set_having_t::type...>> { static_assert(not is_noop::value, "cannot call having() without a group_by"); static_assert(is_noop::value, "cannot call having() twice for a single select"); @@ -350,15 +352,16 @@ namespace sqlpp _from, _where, _group_by, - {std::forward(expr)}, + {std::tuple::type...>{std::forward(expr)...}}, _order_by, _limit, _offset, }; } - auto dynamic_having() - -> set_having_t> + template + auto dynamic_having(Expr&&... expr) + -> set_having_t::type...>> { static_assert(not is_noop::value, "cannot call having() without a group_by"); static_assert(is_noop::value, "cannot call having() twice for a single select"); @@ -368,7 +371,7 @@ namespace sqlpp _from, _where, _group_by, - {{}}, + {std::tuple::type...>{std::forward(expr)...}}, _order_by, _limit, _offset, @@ -387,7 +390,7 @@ namespace sqlpp template auto order_by(OrderExpr&&... expr) - -> set_order_by_t::type...>> + -> set_order_by_t::type...>> { static_assert(not is_noop::value, "cannot call order_by() without a from()"); static_assert(is_noop::value, "cannot call order_by() twice for a single select"); @@ -404,8 +407,9 @@ namespace sqlpp }; } - auto dynamic_order_by() - -> set_order_by_t> + template + auto dynamic_order_by(OrderExpr&&... expr) + -> set_order_by_t::type...>> { static_assert(not is_noop::value, "cannot call order_by() without a from()"); static_assert(is_noop::value, "cannot call order_by() twice for a single select"); @@ -416,7 +420,7 @@ namespace sqlpp _where, _group_by, _having, - {{}}, + {std::tuple::type...>{std::forward(expr)...}}, _limit, _offset, }; diff --git a/include/sqlpp11/select_fwd.h b/include/sqlpp11/select_fwd.h index fa62388b..57486a06 100644 --- a/include/sqlpp11/select_fwd.h +++ b/include/sqlpp11/select_fwd.h @@ -40,15 +40,15 @@ namespace sqlpp template struct select_flag_list_t; template struct select_expression_list_t; - template struct from_t; + template struct from_t; template struct where_t; - template struct group_by_t; + template struct group_by_t; - template struct having_t; + template struct having_t; - template struct order_by_t; + template struct order_by_t; struct limit_t; diff --git a/include/sqlpp11/using.h b/include/sqlpp11/using.h index 694e056a..9af96bd2 100644 --- a/include/sqlpp11/using.h +++ b/include/sqlpp11/using.h @@ -30,17 +30,18 @@ #include #include #include +#include #include -#include namespace sqlpp { - template + template struct using_t { using _is_using = std::true_type; + using _is_dynamic = typename std::conditional::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::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 + void add(T&& table) + { + static_assert(is_table_t::type>::value, "using() arguments require to be tables"); + _dynamic_tables.emplace_back(std::forward(table)); + } + template 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 _tables; + detail::serializable_list _dynamic_tables; }; - template - struct dynamic_using_t - { - using _is_using = std::true_type; - using _is_dynamic = std::true_type; - - template - void add(Table&& table) - { - static_assert(is_table_t::type>::value, "using arguments require to be tables"); - _dynamic_tables.push_back(std::forward
(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> _dynamic_tables; - }; } #endif diff --git a/include/sqlpp11/where.h b/include/sqlpp11/where.h index 98b9d270..56d517a3 100644 --- a/include/sqlpp11/where.h +++ b/include/sqlpp11/where.h @@ -47,13 +47,12 @@ namespace sqlpp using _valid_expressions = typename detail::make_set_if::type; static_assert(_valid_expressions::size::value == sizeof...(Expr), "at least one argument is not an expression in where()"); - template - void add(E&& expr) - { - static_assert(is_expression_t::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(expr)); - } + template + void add(E&& expr) + { + static_assert(is_expression_t::type>::value, "invalid expression argument in add_where()"); + _dynamic_expressions.emplace_back(std::forward(expr)); + } template void serialize(std::ostream& os, Db& db) const @@ -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 _expressions;