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> {