From e63a798a823b58c1e9fe9bda395aea7a09071d45 Mon Sep 17 00:00:00 2001 From: Roland Bock Date: Fri, 1 Nov 2013 12:23:50 +0100 Subject: [PATCH] Started to use flags to indicate database traits e.g. support for any or outer join, or how string concatenation is implemented --- include/sqlpp11/any.h | 1 + include/sqlpp11/concat.h | 16 ++++++++++++--- include/sqlpp11/detail/serialize_tuple.h | 12 ++++++------ include/sqlpp11/detail/wrap_operand.h | 2 +- include/sqlpp11/join.h | 25 ++++++++++++++++++++++++ include/sqlpp11/some.h | 1 + tests/SelectTest.cpp | 8 +++++++- 7 files changed, 54 insertions(+), 11 deletions(-) diff --git a/include/sqlpp11/any.h b/include/sqlpp11/any.h index c9d4c970..8b042297 100644 --- a/include/sqlpp11/any.h +++ b/include/sqlpp11/any.h @@ -72,6 +72,7 @@ namespace sqlpp template void serialize(std::ostream& os, Db& db) const { + static_assert(Db::_supports_any, "any() not supported by current database"); os << "ANY("; _select.serialize(os, db); os << ")"; diff --git a/include/sqlpp11/concat.h b/include/sqlpp11/concat.h index 3078dc32..842e54f3 100644 --- a/include/sqlpp11/concat.h +++ b/include/sqlpp11/concat.h @@ -74,9 +74,19 @@ namespace sqlpp template void serialize(std::ostream& os, Db& db) const { - os << "CONCAT("; - detail::serialize_tuple(os, db, _args, ','); - os << ")"; + static_assert(Db::_use_concat_operator or Db::_use_concat_function, "neither concat operator nor concat function supported by current database"); + if (Db::_use_concat_operator) + { + os << "("; + detail::serialize_tuple(os, db, _args, "||"); + os << ")"; + } + else if (Db::_use_concat_function) + { + os << "CONCAT("; + detail::serialize_tuple(os, db, _args, ','); + os << ")"; + } } private: diff --git a/include/sqlpp11/detail/serialize_tuple.h b/include/sqlpp11/detail/serialize_tuple.h index 25c33698..d73d9ba9 100644 --- a/include/sqlpp11/detail/serialize_tuple.h +++ b/include/sqlpp11/detail/serialize_tuple.h @@ -38,8 +38,8 @@ namespace sqlpp template struct tuple_serializer_impl { - template - static void serialize(std::ostream& os, Db& db, const Tuple& flags_and_columns, char separator) + template + static void serialize(std::ostream& os, Db& db, const Tuple& flags_and_columns, const Separator& separator) { if (index > begin) os << separator; @@ -56,14 +56,14 @@ namespace sqlpp template struct tuple_serializer_impl { - template - static void serialize(std::ostream& os, Db& db, const Tuple& flags_and_columns, char separator) + template + static void serialize(std::ostream& os, Db& db, const Tuple& flags_and_columns, const Separator& separator) { } }; - template - static void serialize_tuple(std::ostream& os, Db& db, const Tuple& flags_and_columns, char separator) + template + static void serialize_tuple(std::ostream& os, Db& db, const Tuple& flags_and_columns, const Separator& separator) { tuple_serializer_impl<0, 0, std::tuple_size::value>::serialize(os, db, flags_and_columns, separator); } diff --git a/include/sqlpp11/detail/wrap_operand.h b/include/sqlpp11/detail/wrap_operand.h index 74a356d2..d5ebfd94 100644 --- a/include/sqlpp11/detail/wrap_operand.h +++ b/include/sqlpp11/detail/wrap_operand.h @@ -101,7 +101,7 @@ namespace sqlpp template void serialize(std::ostream& os, Db& db) const { - os << '"' << db.escape(_t) << '"'; + os << '\'' << db.escape(_t) << '\''; } bool _is_trivial() const { return _t.empty(); } diff --git a/include/sqlpp11/join.h b/include/sqlpp11/join.h index cd4690a2..8265a0d3 100644 --- a/include/sqlpp11/join.h +++ b/include/sqlpp11/join.h @@ -34,18 +34,42 @@ namespace sqlpp { struct inner_join_t { + template + struct _is_supported + { + static constexpr bool value = Db::_supports_inner_join; + }; + static constexpr const char* _name = " INNER "; }; struct outer_join_t { + template + struct _is_supported + { + static constexpr bool value = Db::_supports_outer_join; + }; + static constexpr const char* _name = " OUTER "; }; struct left_outer_join_t { + template + struct _is_supported + { + static constexpr bool value = Db::_supports_left_outer_join; + }; + static constexpr const char* _name = " LEFT OUTER "; }; struct right_outer_join_t { + template + struct _is_supported + { + static constexpr bool value = Db::_supports_right_outer_join; + }; + static constexpr const char* _name = " RIGHT OUTER "; }; @@ -109,6 +133,7 @@ namespace sqlpp void serialize(std::ostream& os, Db& db) const { // FIXME: Need to check if db supports the join type. e.g. sqlite does not support right outer or full outer join + static_assert(JoinType::template _is_supported::value, "join type not supported by current database"); static_assert(not is_noop::value, "joined tables require on()"); _lhs.serialize(os, db); os << JoinType::_name; diff --git a/include/sqlpp11/some.h b/include/sqlpp11/some.h index e7affa14..54a1f910 100644 --- a/include/sqlpp11/some.h +++ b/include/sqlpp11/some.h @@ -72,6 +72,7 @@ namespace sqlpp template void serialize(std::ostream& os, Db& db) const { + static_assert(Db::_supports_some, "some() not supported by current database"); os << "SOME("; _select.serialize(os, db); os << ")"; diff --git a/tests/SelectTest.cpp b/tests/SelectTest.cpp index df7b9cab..8af6d64f 100644 --- a/tests/SelectTest.cpp +++ b/tests/SelectTest.cpp @@ -25,12 +25,18 @@ #include "TabSample.h" #include +#include #include #include class DbMock: public sqlpp::connection { public: + static constexpr bool _supports_any = true; + + static constexpr bool _use_concat_function = true; + static constexpr bool _use_concat_operator = false; + const std::string& escape(const std::string& text) { return text; } }; @@ -266,7 +272,7 @@ int main() { auto s = dynamic_select(db, all_of(t)).dynamic_from().dynamic_where().dynamic_limit().dynamic_offset(); s = s.add_from(t); - s = s.add_where(t.alpha > 7); + s = s.add_where(t.alpha > 7 and t.alpha == any(select(t.alpha).from(t).where(t.alpha < 3))); s = s.set_limit(30); s = s.set_limit(3); std::cerr << "------------------------\n";