From 41709f38ec0fd99f3b045d5d5f4e6d97527461bf Mon Sep 17 00:00:00 2001 From: rbock Date: Wed, 7 Oct 2015 21:43:19 +0200 Subject: [PATCH 1/9] Added date data type. --- include/sqlpp11/column_types.h | 1 + include/sqlpp11/date.h | 248 +++++++++++++++++++++++++++++++++ include/sqlpp11/date_fwd.h | 41 ++++++ include/sqlpp11/type_traits.h | 2 + include/sqlpp11/wrap_operand.h | 37 +++++ 5 files changed, 329 insertions(+) create mode 100644 include/sqlpp11/date.h create mode 100644 include/sqlpp11/date_fwd.h diff --git a/include/sqlpp11/column_types.h b/include/sqlpp11/column_types.h index d79d01f4..a6db384c 100644 --- a/include/sqlpp11/column_types.h +++ b/include/sqlpp11/column_types.h @@ -28,6 +28,7 @@ #define SQLPP_COLUMN_TYPES_H #include +#include #include #include #include diff --git a/include/sqlpp11/date.h b/include/sqlpp11/date.h new file mode 100644 index 00000000..4fcfbefe --- /dev/null +++ b/include/sqlpp11/date.h @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2015-2015, Roland Bock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SQLPP_DATE_H +#define SQLPP_DATE_H + +#include +#include +#include +#include +#include +#include +#include + +namespace sqlpp +{ + // date value type + struct date + { + using _traits = make_traits; + using _tag = tag::is_date; + using _cpp_value_type = day_point; + + template + using _is_valid_operand = is_date_t; + }; + + // date parameter value + template <> + struct parameter_value_t + { + using _value_type = date; + using _cpp_value_type = typename _value_type::_cpp_value_type; + + parameter_value_t() : _value{}, _is_null(true) + { + } + + explicit parameter_value_t(const _cpp_value_type& val) : _value(val), _is_null(false) + { + } + + parameter_value_t& operator=(const _cpp_value_type& val) + { + _value = val; + _is_null = false; + return *this; + } + + parameter_value_t& operator=(const tvin_t>& t) + { + if (t._is_trivial()) + { + _value = day_point{}; + _is_null = true; + } + else + { + _value = t._value._t; + _is_null = false; + } + return *this; + } + + void set_null() + { + _value = day_point{}; + _is_null = true; + } + + bool is_null() const + { + return _is_null; + } + + const _cpp_value_type& value() const + { + return _value; + } + + operator _cpp_value_type() const + { + return _value; + } + + template + void _bind(Target& target, size_t index) const + { + target._bind_date_parameter(index, &_value, _is_null); + } + + private: + _cpp_value_type _value; + bool _is_null; + }; + + // date expression operators + template + struct expression_operators : public basic_expression_operators + { + template + using _is_valid_operand = is_valid_operand; + }; + + // date column operators + template + struct column_operators + { + template + using _is_valid_operand = is_valid_operand; + + template + auto operator+=(T t) const -> assignment_t, wrap_operand_t>> + { + using rhs = wrap_operand_t; + static_assert(_is_valid_operand::value, "invalid rhs assignment operand"); + + return {*static_cast(this), {{*static_cast(this), rhs{t}}}}; + } + + template + auto operator-=(T t) const -> assignment_t, wrap_operand_t>> + { + using rhs = wrap_operand_t; + static_assert(_is_valid_operand::value, "invalid rhs assignment operand"); + + return {*static_cast(this), {{*static_cast(this), rhs{t}}}}; + } + + template + auto operator/=(T t) const -> assignment_t>> + { + using rhs = wrap_operand_t; + static_assert(_is_valid_operand::value, "invalid rhs assignment operand"); + + return {*static_cast(this), {{*static_cast(this), rhs{t}}}}; + } + + template + auto operator*=(T t) const -> assignment_t, wrap_operand_t>> + { + using rhs = wrap_operand_t; + static_assert(_is_valid_operand::value, "invalid rhs assignment operand"); + + return {*static_cast(this), {{*static_cast(this), rhs{t}}}}; + } + }; + + // date result field + template + struct result_field_t : public result_field_methods_t> + { + static_assert(std::is_same, date>::value, "field type mismatch"); + using _cpp_value_type = typename date::_cpp_value_type; + + result_field_t() : _is_valid(false), _is_null(true), _value{} + { + } + + void _invalidate() + { + _is_valid = false; + _is_null = true; + _value = day_point{}; + } + + void _validate() + { + _is_valid = true; + } + + bool is_null() const + { + if (not _is_valid) + throw exception("accessing is_null in non-existing row"); + return _is_null; + } + + bool _is_trivial() const + { + if (not _is_valid) + throw exception("accessing is_null in non-existing row"); + + return value() == day_point{}; + } + + _cpp_value_type value() const + { + if (not _is_valid) + throw exception("accessing value in non-existing row"); + + if (_is_null) + { + if (enforce_null_result_treatment_t::value and not null_is_trivial_value_t::value) + { + throw exception("accessing value of NULL field"); + } + else + { + return day_point{}; + } + } + return _value; + } + + template + void _bind(Target& target, size_t i) + { + target._bind_date_result(i, &_value, &_is_null); + } + + private: + bool _is_valid; + bool _is_null; + _cpp_value_type _value; + }; + + // ostream operator for date result field + template + inline std::ostream& operator<<(std::ostream& os, const result_field_t& e) + { + return serialize(e, os); + } +} +#endif diff --git a/include/sqlpp11/date_fwd.h b/include/sqlpp11/date_fwd.h new file mode 100644 index 00000000..7404c297 --- /dev/null +++ b/include/sqlpp11/date_fwd.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2015-2015, Roland Bock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SQLPP_DATE_FWD_H +#define SQLPP_DATE_FWD_H + +#include + +namespace sqlpp +{ + using days = std::chrono::duration, std::chrono::hours::period>>; + + using day_point = std::chrono::time_point; + + struct date; +}; + +#endif diff --git a/include/sqlpp11/type_traits.h b/include/sqlpp11/type_traits.h index 01265b61..e67904a9 100644 --- a/include/sqlpp11/type_traits.h +++ b/include/sqlpp11/type_traits.h @@ -89,6 +89,8 @@ namespace sqlpp SQLPP_VALUE_TRAIT_GENERATOR(is_value_type) SQLPP_VALUE_TRAIT_GENERATOR(is_sql_null) SQLPP_VALUE_TRAIT_GENERATOR(is_boolean) + SQLPP_VALUE_TRAIT_GENERATOR(is_date) + SQLPP_VALUE_TRAIT_GENERATOR(is_datetime) SQLPP_VALUE_TRAIT_GENERATOR(is_integral) SQLPP_VALUE_TRAIT_GENERATOR(is_floating_point) template diff --git a/include/sqlpp11/wrap_operand.h b/include/sqlpp11/wrap_operand.h index 3470e7d9..0c3b1720 100644 --- a/include/sqlpp11/wrap_operand.h +++ b/include/sqlpp11/wrap_operand.h @@ -28,6 +28,7 @@ #define SQLPP_DETAIL_WRAP_OPERAND_H #include +#include #include #include #include @@ -70,6 +71,36 @@ namespace sqlpp _value_t _t; }; + struct date_operand : public alias_operators + { + using _traits = make_traits; + using _nodes = detail::type_vector<>; + using _is_aggregate_expression = std::true_type; + + using _value_t = day_point; + + date_operand() : _t{} + { + } + + date_operand(_value_t t) : _t(t) + { + } + + date_operand(const date_operand&) = default; + date_operand(date_operand&&) = default; + date_operand& operator=(const date_operand&) = default; + date_operand& operator=(date_operand&&) = default; + ~date_operand() = default; + + bool _is_trivial() const + { + return _t == day_point{}; + } + + _value_t _t; + }; + template struct serializer_t { @@ -224,6 +255,12 @@ namespace sqlpp using type = boolean_operand; }; + template <> + struct wrap_operand + { + using type = date_operand; + }; + template struct wrap_operand::value>::type> { From 407136c44e4dafb2241d0491f1aea25bf33cfdcf Mon Sep 17 00:00:00 2001 From: rbock Date: Thu, 8 Oct 2015 16:08:04 +0200 Subject: [PATCH 2/9] Added a date_time column type --- include/sqlpp11/column_types.h | 1 + include/sqlpp11/date.h | 40 +--- include/sqlpp11/date_time.h | 213 ++++++++++++++++++ .../sqlpp11/{date_fwd.h => date_time_fwd.h} | 2 + include/sqlpp11/type_traits.h | 6 +- include/sqlpp11/wrap_operand.h | 27 +-- 6 files changed, 237 insertions(+), 52 deletions(-) create mode 100644 include/sqlpp11/date_time.h rename include/sqlpp11/{date_fwd.h => date_time_fwd.h} (93%) diff --git a/include/sqlpp11/column_types.h b/include/sqlpp11/column_types.h index a6db384c..662d4179 100644 --- a/include/sqlpp11/column_types.h +++ b/include/sqlpp11/column_types.h @@ -29,6 +29,7 @@ #include #include +#include #include #include #include diff --git a/include/sqlpp11/date.h b/include/sqlpp11/date.h index 4fcfbefe..2ebf784d 100644 --- a/include/sqlpp11/date.h +++ b/include/sqlpp11/date.h @@ -27,7 +27,7 @@ #ifndef SQLPP_DATE_H #define SQLPP_DATE_H -#include +#include #include #include #include @@ -45,7 +45,7 @@ namespace sqlpp using _cpp_value_type = day_point; template - using _is_valid_operand = is_date_t; + using _is_valid_operand = is_time_point_t; }; // date parameter value @@ -131,42 +131,6 @@ namespace sqlpp { template using _is_valid_operand = is_valid_operand; - - template - auto operator+=(T t) const -> assignment_t, wrap_operand_t>> - { - using rhs = wrap_operand_t; - static_assert(_is_valid_operand::value, "invalid rhs assignment operand"); - - return {*static_cast(this), {{*static_cast(this), rhs{t}}}}; - } - - template - auto operator-=(T t) const -> assignment_t, wrap_operand_t>> - { - using rhs = wrap_operand_t; - static_assert(_is_valid_operand::value, "invalid rhs assignment operand"); - - return {*static_cast(this), {{*static_cast(this), rhs{t}}}}; - } - - template - auto operator/=(T t) const -> assignment_t>> - { - using rhs = wrap_operand_t; - static_assert(_is_valid_operand::value, "invalid rhs assignment operand"); - - return {*static_cast(this), {{*static_cast(this), rhs{t}}}}; - } - - template - auto operator*=(T t) const -> assignment_t, wrap_operand_t>> - { - using rhs = wrap_operand_t; - static_assert(_is_valid_operand::value, "invalid rhs assignment operand"); - - return {*static_cast(this), {{*static_cast(this), rhs{t}}}}; - } }; // date result field diff --git a/include/sqlpp11/date_time.h b/include/sqlpp11/date_time.h new file mode 100644 index 00000000..f8a11831 --- /dev/null +++ b/include/sqlpp11/date_time.h @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2015-2015, Roland Bock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SQLPP_DATE_TIME_H +#define SQLPP_DATE_TIME_H + +#include +#include +#include +#include +#include +#include +#include + +namespace sqlpp +{ + // date_time value type + struct date_time + { + using _traits = make_traits; + using _tag = tag::is_date_time; + using _cpp_value_type = ms_point; + + template + using _is_valid_operand = is_time_point_t; + }; + + // date_time parameter value + template <> + struct parameter_value_t + { + using _value_type = date_time; + using _cpp_value_type = typename _value_type::_cpp_value_type; + + parameter_value_t() : _value{}, _is_null(true) + { + } + + explicit parameter_value_t(const _cpp_value_type& val) : _value(val), _is_null(false) + { + } + + parameter_value_t& operator=(const _cpp_value_type& val) + { + _value = val; + _is_null = false; + return *this; + } + + parameter_value_t& operator=(const tvin_t>& t) + { + if (t._is_trivial()) + { + _value = day_point{}; + _is_null = true; + } + else + { + _value = t._value._t; + _is_null = false; + } + return *this; + } + + void set_null() + { + _value = day_point{}; + _is_null = true; + } + + bool is_null() const + { + return _is_null; + } + + const _cpp_value_type& value() const + { + return _value; + } + + operator _cpp_value_type() const + { + return _value; + } + + template + void _bind(Target& target, size_t index) const + { + target._bind_date_parameter(index, &_value, _is_null); + } + + private: + _cpp_value_type _value; + bool _is_null; + }; + + // date_time expression operators + template + struct expression_operators : public basic_expression_operators + { + template + using _is_valid_operand = is_valid_operand; + }; + + // date_time column operators + template + struct column_operators + { + template + using _is_valid_operand = is_valid_operand; + }; + + // date_time result field + template + struct result_field_t + : public result_field_methods_t> + { + static_assert(std::is_same, date_time>::value, "field type mismatch"); + using _cpp_value_type = typename date_time::_cpp_value_type; + + result_field_t() : _is_valid(false), _is_null(true), _value{} + { + } + + void _invalidate() + { + _is_valid = false; + _is_null = true; + _value = day_point{}; + } + + void _validate() + { + _is_valid = true; + } + + bool is_null() const + { + if (not _is_valid) + throw exception("accessing is_null in non-existing row"); + return _is_null; + } + + bool _is_trivial() const + { + if (not _is_valid) + throw exception("accessing is_null in non-existing row"); + + return value() == day_point{}; + } + + _cpp_value_type value() const + { + if (not _is_valid) + throw exception("accessing value in non-existing row"); + + if (_is_null) + { + if (enforce_null_result_treatment_t::value and not null_is_trivial_value_t::value) + { + throw exception("accessing value of NULL field"); + } + else + { + return day_point{}; + } + } + return _value; + } + + template + void _bind(Target& target, size_t i) + { + target._bind_date_result(i, &_value, &_is_null); + } + + private: + bool _is_valid; + bool _is_null; + _cpp_value_type _value; + }; + + // ostream operator for date_time result field + template + inline std::ostream& operator<<(std::ostream& os, const result_field_t& e) + { + return serialize(e, os); + } +} +#endif diff --git a/include/sqlpp11/date_fwd.h b/include/sqlpp11/date_time_fwd.h similarity index 93% rename from include/sqlpp11/date_fwd.h rename to include/sqlpp11/date_time_fwd.h index 7404c297..80c960db 100644 --- a/include/sqlpp11/date_fwd.h +++ b/include/sqlpp11/date_time_fwd.h @@ -34,8 +34,10 @@ namespace sqlpp using days = std::chrono::duration, std::chrono::hours::period>>; using day_point = std::chrono::time_point; + using ms_point = std::chrono::time_point; struct date; + struct date_time; }; #endif diff --git a/include/sqlpp11/type_traits.h b/include/sqlpp11/type_traits.h index e67904a9..06f1ee40 100644 --- a/include/sqlpp11/type_traits.h +++ b/include/sqlpp11/type_traits.h @@ -90,13 +90,17 @@ namespace sqlpp SQLPP_VALUE_TRAIT_GENERATOR(is_sql_null) SQLPP_VALUE_TRAIT_GENERATOR(is_boolean) SQLPP_VALUE_TRAIT_GENERATOR(is_date) - SQLPP_VALUE_TRAIT_GENERATOR(is_datetime) + SQLPP_VALUE_TRAIT_GENERATOR(is_date_time) SQLPP_VALUE_TRAIT_GENERATOR(is_integral) SQLPP_VALUE_TRAIT_GENERATOR(is_floating_point) template using is_numeric_t = logic::any_t::value, detail::is_element_of::value>; + template + using is_time_point_t = logic::any_t::value, + detail::is_element_of::value>; + SQLPP_VALUE_TRAIT_GENERATOR(is_text) SQLPP_VALUE_TRAIT_GENERATOR(is_wrapped_value) SQLPP_VALUE_TRAIT_GENERATOR(is_selectable) diff --git a/include/sqlpp11/wrap_operand.h b/include/sqlpp11/wrap_operand.h index 0c3b1720..b829e255 100644 --- a/include/sqlpp11/wrap_operand.h +++ b/include/sqlpp11/wrap_operand.h @@ -28,7 +28,7 @@ #define SQLPP_DETAIL_WRAP_OPERAND_H #include -#include +#include #include #include #include @@ -71,27 +71,28 @@ namespace sqlpp _value_t _t; }; - struct date_operand : public alias_operators + template + struct date_time_operand : public alias_operators> { using _traits = make_traits; using _nodes = detail::type_vector<>; using _is_aggregate_expression = std::true_type; - using _value_t = day_point; + using _value_t = std::chrono::time_point; - date_operand() : _t{} + date_time_operand() : _t{} { } - date_operand(_value_t t) : _t(t) + date_time_operand(_value_t t) : _t(t) { } - date_operand(const date_operand&) = default; - date_operand(date_operand&&) = default; - date_operand& operator=(const date_operand&) = default; - date_operand& operator=(date_operand&&) = default; - ~date_operand() = default; + date_time_operand(const date_time_operand&) = default; + date_time_operand(date_time_operand&&) = default; + date_time_operand& operator=(const date_time_operand&) = default; + date_time_operand& operator=(date_time_operand&&) = default; + ~date_time_operand() = default; bool _is_trivial() const { @@ -255,10 +256,10 @@ namespace sqlpp using type = boolean_operand; }; - template <> - struct wrap_operand + template + struct wrap_operand, void> { - using type = date_operand; + using type = date_time_operand; }; template From 553dc5b016283b8f6d53e5a9cfa2d4bf0fa6c604 Mon Sep 17 00:00:00 2001 From: rbock Date: Fri, 9 Oct 2015 07:24:05 +0200 Subject: [PATCH 3/9] Using portable static asserts for the basic expression operators now The return type yet needs to be adjusted --- include/sqlpp11/basic_expression_operators.h | 50 ++++++----- include/sqlpp11/consistent.h | 43 +++++++++ include/sqlpp11/insert_value_list.h | 59 +------------ include/sqlpp11/portable_static_assert.h | 91 ++++++++++++++++++++ include/sqlpp11/type_traits.h | 9 +- 5 files changed, 164 insertions(+), 88 deletions(-) create mode 100644 include/sqlpp11/consistent.h create mode 100644 include/sqlpp11/portable_static_assert.h diff --git a/include/sqlpp11/basic_expression_operators.h b/include/sqlpp11/basic_expression_operators.h index 032ecd34..eea5a364 100644 --- a/include/sqlpp11/basic_expression_operators.h +++ b/include/sqlpp11/basic_expression_operators.h @@ -28,6 +28,8 @@ #define SQLPP_DETAIL_BASIC_EXPRESSION_OPERATORS_H #include +#include +#include #include #include #include @@ -38,27 +40,33 @@ namespace sqlpp { + SQLPP_PORTABLE_STATIC_ASSERT(assert_valid_rhs_comparison_operand_t, "invalid rhs operand in comparison"); + + template + using check_rhs_comparison_operand_t = static_check_t< + (is_expression_t::value // expressions are OK + or + is_multi_expression_t::value) // multi-expressions like ANY are OK for comparisons, too + and + LhsValueType::template _is_valid_operand::value, // the correct value type is required, of course + assert_valid_rhs_comparison_operand_t>; + + SQLPP_PORTABLE_STATIC_ASSERT(assert_valid_in_arguments_t, "at least one operand of in() is not valid"); + + template + using check_rhs_in_arguments_t = + static_check_t::value...>::value, + assert_valid_in_arguments_t>; + // basic operators template struct basic_expression_operators { - template - struct _is_valid_comparison_operand - { - static constexpr bool value = - (is_expression_t::value // expressions are OK - or - is_multi_expression_t::value) // multi-expressions like ANY are OK for comparisons, too - and - ValueType::template _is_valid_operand::value // the correct value type is required, of course - ; - }; - template equal_to_t> operator==(T t) const { using rhs = wrap_operand_t; - static_assert(_is_valid_comparison_operand::value, "invalid rhs operand in comparison"); + check_rhs_comparison_operand_t{}._(); return {*static_cast(this), {rhs{t}}}; } @@ -67,7 +75,7 @@ namespace sqlpp not_equal_to_t> operator!=(T t) const { using rhs = wrap_operand_t; - static_assert(_is_valid_comparison_operand::value, "invalid rhs operand in comparison"); + check_rhs_comparison_operand_t{}._(); return {*static_cast(this), {rhs{t}}}; } @@ -76,7 +84,7 @@ namespace sqlpp less_than_t> operator<(T t) const { using rhs = wrap_operand_t; - static_assert(_is_valid_comparison_operand::value, "invalid rhs operand in comparison"); + check_rhs_comparison_operand_t{}._(); return {*static_cast(this), rhs{t}}; } @@ -85,7 +93,7 @@ namespace sqlpp less_equal_t> operator<=(T t) const { using rhs = wrap_operand_t; - static_assert(_is_valid_comparison_operand::value, "invalid rhs operand in comparison"); + check_rhs_comparison_operand_t{}._(); return {*static_cast(this), rhs{t}}; } @@ -94,7 +102,7 @@ namespace sqlpp greater_than_t> operator>(T t) const { using rhs = wrap_operand_t; - static_assert(_is_valid_comparison_operand::value, "invalid rhs operand in comparison"); + check_rhs_comparison_operand_t{}._(); return {*static_cast(this), rhs{t}}; } @@ -103,7 +111,7 @@ namespace sqlpp greater_equal_t> operator>=(T t) const { using rhs = wrap_operand_t; - static_assert(_is_valid_comparison_operand::value, "invalid rhs operand in comparison"); + check_rhs_comparison_operand_t{}._(); return {*static_cast(this), rhs{t}}; } @@ -132,16 +140,14 @@ namespace sqlpp template in_t...> in(T... t) const { - static_assert(logic::all_t<_is_valid_comparison_operand>::value...>::value, - "at least one operand of in() is not valid"); + check_rhs_in_arguments_t...>::_(); return {*static_cast(this), wrap_operand_t{t}...}; } template not_in_t...> not_in(T... t) const { - static_assert(logic::all_t<_is_valid_comparison_operand>::value...>::value, - "at least one operand of in() is not valid"); + check_rhs_in_arguments_t...>::_(); return {*static_cast(this), wrap_operand_t{t}...}; } }; diff --git a/include/sqlpp11/consistent.h b/include/sqlpp11/consistent.h new file mode 100644 index 00000000..7f6e765c --- /dev/null +++ b/include/sqlpp11/consistent.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2013-2015, Roland Bock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SQLPP_CONSISTENT_H +#define SQLPP_CONSISTENT_H + +#include + +namespace sqlpp +{ + struct consistent_t + { + static constexpr bool value = true; + using type = std::true_type; + + static void _(){}; + }; +} + +#endif diff --git a/include/sqlpp11/insert_value_list.h b/include/sqlpp11/insert_value_list.h index f366bafa..ae7be67f 100644 --- a/include/sqlpp11/insert_value_list.h +++ b/include/sqlpp11/insert_value_list.h @@ -28,6 +28,7 @@ #define SQLPP_INSERT_VALUE_LIST_H #include +#include #include #include #include @@ -127,64 +128,6 @@ namespace sqlpp interpretable_list_t _dynamic_values; }; -#define SQLPP_PORTABLE_STATIC_ASSERT(name, message) \ - struct name \ - { \ - static constexpr bool value = false; \ - using type = std::false_type; \ - \ - template \ - static void _() \ - { \ - static_assert(wrong_t::value, message); \ - } \ - } - - namespace detail - { - template - struct static_check_impl - { - using type = Assert; - }; - - template - struct static_check_impl - { - using type = consistent_t; - }; - } - - template - using static_check_t = typename detail::static_check_impl::type; - - namespace detail - { - template - struct static_combined_check_impl; - - template - struct static_combined_check_impl - { - using type = Assert; - }; - - template - struct static_combined_check_impl - { - using type = typename static_combined_check_impl::type; - }; - - template <> - struct static_combined_check_impl<> - { - using type = consistent_t; - }; - } - - template - using static_combined_check_t = typename detail::static_combined_check_impl::type; - SQLPP_PORTABLE_STATIC_ASSERT(assert_insert_set_assignments_t, "at least one argument is not an assignment in set()"); SQLPP_PORTABLE_STATIC_ASSERT(assert_insert_set_no_duplicates_t, "at least one duplicate column detected in set()"); SQLPP_PORTABLE_STATIC_ASSERT(assert_insert_set_prohibited_t, diff --git a/include/sqlpp11/portable_static_assert.h b/include/sqlpp11/portable_static_assert.h new file mode 100644 index 00000000..06732f10 --- /dev/null +++ b/include/sqlpp11/portable_static_assert.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2015-2015, Roland Bock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SQLPP_PORTABLE_STATIC_ASSERT_H +#define SQLPP_PORTABLE_STATIC_ASSERT_H + +namespace sqlpp +{ +#define SQLPP_PORTABLE_STATIC_ASSERT(name, message) \ + struct name \ + { \ + static constexpr bool value = false; \ + using type = std::false_type; \ + \ + template \ + static void _() \ + { \ + static_assert(wrong_t::value, message); \ + } \ + } + + namespace detail + { + template + struct static_check_impl + { + using type = Assert; + }; + + template + struct static_check_impl + { + using type = consistent_t; + }; + } + + template + using static_check_t = typename detail::static_check_impl::type; + + namespace detail + { + template + struct static_combined_check_impl; + + template + struct static_combined_check_impl + { + using type = Assert; + }; + + template + struct static_combined_check_impl + { + using type = typename static_combined_check_impl::type; + }; + + template <> + struct static_combined_check_impl<> + { + using type = consistent_t; + }; + } + + template + using static_combined_check_t = typename detail::static_combined_check_impl::type; +} + +#endif diff --git a/include/sqlpp11/type_traits.h b/include/sqlpp11/type_traits.h index 06f1ee40..98bc1b35 100644 --- a/include/sqlpp11/type_traits.h +++ b/include/sqlpp11/type_traits.h @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -306,14 +307,6 @@ namespace sqlpp template using derived_statement_t = typename Policies::_statement_t; - struct consistent_t - { - static constexpr bool value = true; - using type = std::true_type; - - static void _(){}; - }; - template using is_inconsistent_t = typename std::conditional::value, std::false_type, std::true_type>::type; From d1a3ab596a58018e5b9d4afb54658eef79bfbb55 Mon Sep 17 00:00:00 2001 From: rbock Date: Fri, 9 Oct 2015 21:12:23 +0200 Subject: [PATCH 4/9] Prepared basic expression operators for compile time tests --- include/sqlpp11/basic_expression_operators.h | 94 +++++++++++++++++--- 1 file changed, 80 insertions(+), 14 deletions(-) diff --git a/include/sqlpp11/basic_expression_operators.h b/include/sqlpp11/basic_expression_operators.h index eea5a364..abad7cfb 100644 --- a/include/sqlpp11/basic_expression_operators.h +++ b/include/sqlpp11/basic_expression_operators.h @@ -28,6 +28,7 @@ #define SQLPP_DETAIL_BASIC_EXPRESSION_OPERATORS_H #include +#include #include #include #include @@ -58,60 +59,125 @@ namespace sqlpp static_check_t::value...>::value, assert_valid_in_arguments_t>; + namespace detail + { + template class Expr, typename Lhs> + struct new_unary_expression_impl + { + using type = bad_statement; + }; + + template