diff --git a/include/sqlpp11/boolean.h b/include/sqlpp11/boolean.h index 56b081b4..4eb6d7a8 100644 --- a/include/sqlpp11/boolean.h +++ b/include/sqlpp11/boolean.h @@ -102,21 +102,38 @@ namespace sqlpp template struct field_methods_t { + static constexpr bool _null_is_trivial = true; operator _cpp_value_type() const { return static_cast(*this).value(); } }; template struct field_methods_t< _result_field_t, - typename std::enable_if::value + typename std::enable_if::value and column_spec_can_be_null_t::value and not null_is_trivial_value_t::value>::type> { + static constexpr bool _null_is_trivial = false; }; template struct _result_field_t: public field_methods_t<_result_field_t> { + using _field_methods_t = field_methods_t<_result_field_t>; + + using _traits = make_traits::type>; + + struct _recursive_traits + { + using _parameters = std::tuple<>; + using _provided_tables = detail::type_set<>; + using _provided_outer_tables = detail::type_set<>; + using _required_tables = detail::type_set<>; + using _extra_tables = detail::type_set<>; + using _can_be_null = column_spec_can_be_null_t; + }; + _result_field_t(): _is_valid(false), _is_null(true), @@ -149,7 +166,7 @@ namespace sqlpp if (_is_null) { - if (connector_enforce_result_validity_t::value and not null_is_trivial_value_t::value) + if (connector_enforce_null_result_treatment_t::value and not null_is_trivial_value_t::value) { throw exception("accessing value of NULL field"); } diff --git a/include/sqlpp11/floating_point.h b/include/sqlpp11/floating_point.h index d1b26750..8cb9eca2 100644 --- a/include/sqlpp11/floating_point.h +++ b/include/sqlpp11/floating_point.h @@ -101,22 +101,37 @@ namespace sqlpp template struct field_methods_t { + static constexpr bool _null_is_trivial = true; operator _cpp_value_type() const { return static_cast(*this).value(); } }; template struct field_methods_t< _result_field_t, - typename std::enable_if::value + typename std::enable_if::value and column_spec_can_be_null_t::value and not null_is_trivial_value_t::value>::type> { + static constexpr bool _null_is_trivial = false; }; template struct _result_field_t: public field_methods_t<_result_field_t> { - using _value_type = integral; + using _field_methods_t = field_methods_t<_result_field_t>; + + using _traits = make_traits::type>; + + struct _recursive_traits + { + using _parameters = std::tuple<>; + using _provided_tables = detail::type_set<>; + using _provided_outer_tables = detail::type_set<>; + using _required_tables = detail::type_set<>; + using _extra_tables = detail::type_set<>; + using _can_be_null = column_spec_can_be_null_t; + }; _result_field_t(): _is_valid(false), @@ -150,7 +165,7 @@ namespace sqlpp if (_is_null) { - if (connector_enforce_result_validity_t::value and not null_is_trivial_value_t::value) + if (connector_enforce_null_result_treatment_t::value and not null_is_trivial_value_t::value) { throw exception("accessing value of NULL field"); } diff --git a/include/sqlpp11/integral.h b/include/sqlpp11/integral.h index 65205fa4..df5a5b0f 100644 --- a/include/sqlpp11/integral.h +++ b/include/sqlpp11/integral.h @@ -103,22 +103,37 @@ namespace sqlpp template struct field_methods_t { + static constexpr bool _null_is_trivial = true; operator _cpp_value_type() const { return static_cast(*this).value(); } }; template struct field_methods_t< _result_field_t, - typename std::enable_if::value + typename std::enable_if::value and column_spec_can_be_null_t::value and not null_is_trivial_value_t::value>::type> { + static constexpr bool _null_is_trivial = false; }; template struct _result_field_t: public field_methods_t<_result_field_t> { - using _value_type = integral; + using _field_methods_t = field_methods_t<_result_field_t>; + + using _traits = make_traits::type>; + + struct _recursive_traits + { + using _parameters = std::tuple<>; + using _provided_tables = detail::type_set<>; + using _provided_outer_tables = detail::type_set<>; + using _required_tables = detail::type_set<>; + using _extra_tables = detail::type_set<>; + using _can_be_null = column_spec_can_be_null_t; + }; _result_field_t(): _is_valid(false), @@ -152,7 +167,7 @@ namespace sqlpp if (_is_null) { - if (connector_enforce_result_validity_t::value and not null_is_trivial_value_t::value) + if (connector_enforce_null_result_treatment_t::value and not null_is_trivial_value_t::value) { throw exception("accessing value of NULL field"); } diff --git a/include/sqlpp11/text.h b/include/sqlpp11/text.h index 7810ca50..534dd098 100644 --- a/include/sqlpp11/text.h +++ b/include/sqlpp11/text.h @@ -101,21 +101,38 @@ namespace sqlpp template struct field_methods_t { + static constexpr bool _null_is_trivial = true; operator _cpp_value_type() const { return static_cast(*this).value(); } }; template struct field_methods_t< _result_field_t, - typename std::enable_if::value + typename std::enable_if::value and column_spec_can_be_null_t::value and not null_is_trivial_value_t::value>::type> { + static constexpr bool _null_is_trivial = false; }; template struct _result_field_t: public field_methods_t<_result_field_t> { + using _field_methods_t = field_methods_t<_result_field_t>; + + using _traits = make_traits::type>; + + struct _recursive_traits + { + using _parameters = std::tuple<>; + using _provided_tables = detail::type_set<>; + using _provided_outer_tables = detail::type_set<>; + using _required_tables = detail::type_set<>; + using _extra_tables = detail::type_set<>; + using _can_be_null = column_spec_can_be_null_t; + }; + _result_field_t(): _is_valid(false), _value_ptr(nullptr), @@ -151,7 +168,7 @@ namespace sqlpp if (not _value_ptr) { - if (connector_enforce_result_validity_t::value and not null_is_trivial_value_t::value) + if (connector_enforce_null_result_treatment_t::value and not null_is_trivial_value_t::value) { throw exception("accessing value of NULL field"); } diff --git a/include/sqlpp11/type_traits.h b/include/sqlpp11/type_traits.h index ddf3bf58..3c4a2c29 100644 --- a/include/sqlpp11/type_traits.h +++ b/include/sqlpp11/type_traits.h @@ -174,7 +174,7 @@ namespace sqlpp SQLPP_TYPE_TRAIT_GENERATOR(requires_braces); - SQLPP_CONNECTOR_TRAIT_GENERATOR(enforce_result_validity); + SQLPP_CONNECTOR_TRAIT_GENERATOR(enforce_null_result_treatment); template using is_database = typename std::conditional::value, std::false_type, std::true_type>::type; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 13942a11..ed2c041d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -15,6 +15,7 @@ build_and_run(SelectTypeTest) build_and_run(FunctionTest) build_and_run(PreparedTest) build_and_run(Minimalistic) +build_and_run(ResultTest) # if you want to use the generator, you can do something like this: #find_package(PythonInterp REQUIRED) diff --git a/tests/InterpretTest.cpp b/tests/InterpretTest.cpp index 528bf21f..02f00dd5 100644 --- a/tests/InterpretTest.cpp +++ b/tests/InterpretTest.cpp @@ -36,7 +36,6 @@ MockDb db = {}; MockDb::_serializer_context_t printer; -SQLPP_ALIAS_PROVIDER(kaesekuchen); int main() { @@ -125,6 +124,10 @@ int main() // join serialize(t.inner_join(t.as(t.alpha)).on(t.beta == t.as(t.alpha).beta), printer).str(); + { + auto inner = t.inner_join(t.as(t.alpha)).on(t.beta == t.as(t.alpha).beta); + serialize(select(t.alpha).from(inner), printer).str(); + } // multi_column serialize(multi_column(t.alpha, (t.beta + "cake").as(t.gamma)).as(t.alpha), printer).str(); diff --git a/tests/MockDb.h b/tests/MockDb.h index 9c4dafd9..7c19f920 100644 --- a/tests/MockDb.h +++ b/tests/MockDb.h @@ -30,8 +30,14 @@ #include #include -struct MockDb: public sqlpp::connection +template +struct MockDbT: public sqlpp::connection { + struct _tags + { + using _enforce_null_result_treatment = std::integral_constant; + }; + struct _serializer_context_t { std::ostringstream _os; @@ -156,5 +162,8 @@ struct MockDb: public sqlpp::connection }; +using MockDb = MockDbT; +using EnforceDb = MockDbT; + #endif diff --git a/tests/SelectTest.cpp b/tests/SelectTest.cpp index 9a94694b..7bdf43a5 100644 --- a/tests/SelectTest.cpp +++ b/tests/SelectTest.cpp @@ -36,14 +36,6 @@ MockDb db = {}; MockDb::_serializer_context_t printer; -namespace alias -{ - SQLPP_ALIAS_PROVIDER(a); - SQLPP_ALIAS_PROVIDER(b); - SQLPP_ALIAS_PROVIDER(left); - SQLPP_ALIAS_PROVIDER(right); -} - int main() { test::TabFoo f;