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