diff --git a/include/sqlpp11/column.h b/include/sqlpp11/column.h index a3aa6e73..495643b3 100644 --- a/include/sqlpp11/column.h +++ b/include/sqlpp11/column.h @@ -51,6 +51,13 @@ namespace sqlpp using _name_t = typename ColumnSpec::_name_t; + column_t() = default; + column_t(const column_t&) = default; + column_t(column_t&&) = default; + column_t& operator=(const column_t&) = default; + column_t& operator=(column_t&&) = default; + ~column_t() = default; + template void serialize(std::ostream& os, Db& db) const { diff --git a/include/sqlpp11/from.h b/include/sqlpp11/from.h index 91688ea5..0f604a7f 100644 --- a/include/sqlpp11/from.h +++ b/include/sqlpp11/from.h @@ -57,11 +57,11 @@ namespace sqlpp std::tuple _tables; }; - template + template struct dynamic_from_t { using _is_from = tag_yes; - using _is_dynamic_from = tag_yes; + using _is_dynamic = tag_yes; template void add(Table&& table) @@ -69,13 +69,12 @@ namespace sqlpp _dynamic_tables.push_back(std::forward(table)); } - void serialize(std::ostream& os, Db& db, bool has_static_from) const + void serialize(std::ostream& os, Db& db) const { - if (sizeof...(TableOrJoin) == 0 and _dynamic_tables.empty()) + if (_dynamic_tables.empty()) return; os << " FROM "; - detail::serialize_tuple(os, db, _tables, ','); - bool first = sizeof...(TableOrJoin) == 0; + bool first = true; for (const auto& table : _dynamic_tables) { if (not first) @@ -85,7 +84,6 @@ namespace sqlpp } } - std::tuple _tables; std::vector> _dynamic_tables; }; } diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index f2d59b53..ef7eab3f 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -93,10 +93,10 @@ namespace sqlpp using _is_select = tag_yes; using _requires_braces = tag_yes; - template - using set_from_t = select_t::type...>, Where, GroupBy, Having, OrderBy, Limit, Offset>; - template - using set_where_t = select_t::type>, GroupBy, Having, OrderBy, Limit, Offset>; + template + using set_from_t = select_t; + template + using set_where_t = select_t; template using set_group_by_t = select_t::type...>, Having, OrderBy, Limit, Offset>; template @@ -165,7 +165,8 @@ namespace sqlpp // sqlpp functions template - set_from_t from(Table&&... table) + auto from(Table&&... table) + -> 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"); @@ -182,24 +183,40 @@ namespace sqlpp }; } - /* + auto dynamic_from() + -> set_from_t> + { + 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"); + static_assert(is_noop::value, "cannot call from() twice for a single select"); + return { + _flags, + _expression_list, + {{}}, + _where, + _group_by, + _having, + _order_by, + _limit, + _offset + }; + } + template - select_t& add_from(Table&& table) - { - static_assert(not is_noop::value, "cannot call add_from() without having selected anything"); - static_assert(not std::is_same::value, "cannot call add_from() in a non-dynamic select"); + void add_from(Table&& table) + { + static_assert(not is_noop::value, "cannot call add_from() without having selected anything"); + static_assert(is_dynamic_t::value, "cannot call add_from() in a non-dynamic from"); - _dynamic._from.add(std::forward
(table)); - - return *this; - } - */ + _from.add(std::forward
(table)); + } template - set_where_t where(Expr&& expr) + auto where(Expr&& expr) + -> set_where_t::type>> { static_assert(not is_noop::value, "cannot call where() without a from()"); - static_assert(is_noop::value, "cannot call where() twice for a single select"); + static_assert(is_noop::value, "cannot call where() or dynamic_where() twice for a single select"); return { _flags, _expression_list, @@ -213,6 +230,33 @@ namespace sqlpp }; } + auto dynamic_where() + -> set_where_t> + { + static_assert(not is_noop::value, "cannot call dynamic_where() without a from()"); + static_assert(is_noop::value, "cannot call where() or dynamic_where() twice for a single select"); + return { + _flags, + _expression_list, + _from, + {{}}, + _group_by, + _having, + _order_by, + _limit, + _offset, + }; + } + + template + void add_where(Expr&& expr) + { + static_assert(not is_noop::value, "cannot call add_from() without having selected anything"); + static_assert(is_dynamic_t::value, "cannot call add_where() in a non-dynamic where"); + + _where.add(std::forward(expr)); + } + template set_group_by_t group_by(Col&&... column) { @@ -391,7 +435,6 @@ namespace sqlpp { detail::make_expression_tuple(std::forward(namedExpr)...) } }; } - /* template select_t::type, detail::make_select_flag_list_t, detail::make_select_expression_list_t> dynamic_select(const Db& db, NamedExpr&&... namedExpr) { @@ -400,6 +443,5 @@ namespace sqlpp { detail::make_expression_tuple(std::forward(namedExpr)...) } }; } - */ } #endif diff --git a/include/sqlpp11/type_traits.h b/include/sqlpp11/type_traits.h index b8d32721..cf34cb2e 100644 --- a/include/sqlpp11/type_traits.h +++ b/include/sqlpp11/type_traits.h @@ -95,6 +95,7 @@ namespace sqlpp SQLPP_TYPE_TRAIT_GENERATOR(is_select_flag_list); SQLPP_TYPE_TRAIT_GENERATOR(is_select_expression_list); SQLPP_TYPE_TRAIT_GENERATOR(is_from); + SQLPP_TYPE_TRAIT_GENERATOR(is_dynamic); SQLPP_TYPE_TRAIT_GENERATOR(is_where); SQLPP_TYPE_TRAIT_GENERATOR(is_group_by); SQLPP_TYPE_TRAIT_GENERATOR(is_having); diff --git a/include/sqlpp11/where.h b/include/sqlpp11/where.h index 2e0782e1..05349cf9 100644 --- a/include/sqlpp11/where.h +++ b/include/sqlpp11/where.h @@ -27,10 +27,13 @@ #ifndef SQLPP_WHERE_H #define SQLPP_WHERE_H +#include +#include #include #include #include #include +#include namespace sqlpp { @@ -51,6 +54,39 @@ namespace sqlpp Expr _expr; }; + template + struct dynamic_where_t + { + + using _is_where = tag_yes; + using _is_dynamic = tag_yes; + + template + void add(Expr&& expr) + { + static_assert(is_expression_t::value, "invalid expression argument in where()"); + _conditions.push_back(std::forward(expr)); + } + + void serialize(std::ostream& os, Db& db) const + { + if (_conditions.empty()) + return; + + os << " WHERE "; + 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/tests/SelectTest.cpp b/tests/SelectTest.cpp index 4a6c6c0a..4d9868fb 100644 --- a/tests/SelectTest.cpp +++ b/tests/SelectTest.cpp @@ -262,16 +262,14 @@ int main() static_assert(std::is_same::value, "select with identical columns(name/value_type) need to have identical result_types"); } -#if 0 { - auto s = dynamic_select(db, t); - s = s.add_from(t); - s = s.add_from(t); // This will not be accepted by the SQL server, but it is dynamic and this kind of test is not possible at compile time, I guess + auto s = dynamic_select(db, t).dynamic_from().dynamic_where(); + s.add_from(t); + s.add_where(t.alpha > 7); std::cerr << "------------------------\n"; s.serialize(std::cerr, db); std::cerr << "------------------------\n"; } -#endif static_assert(sqlpp::is_select_flag_t::value, "sqlpp::all has to be a select_flag");