From 27649b3af2af0da6b5247c5111a60b9888ab3120 Mon Sep 17 00:00:00 2001 From: rbock Date: Mon, 11 Aug 2014 19:17:42 +0200 Subject: [PATCH] Added support for default values and result fields for insert --- include/sqlpp11/assignment.h | 8 +++- include/sqlpp11/insert_value.h | 34 ++++++++++------ include/sqlpp11/insert_value_list.h | 6 +-- include/sqlpp11/rhs_is_default.h | 60 +++++++++++++++++++++++++++++ include/sqlpp11/rhs_is_null.h | 10 +++++ tests/InterpretTest.cpp | 5 +++ tests/MockDb.h | 5 +++ tests/PreparedTest.cpp | 7 ++++ tests/ResultTest.cpp | 1 + 9 files changed, 119 insertions(+), 17 deletions(-) create mode 100644 include/sqlpp11/rhs_is_default.h diff --git a/include/sqlpp11/assignment.h b/include/sqlpp11/assignment.h index 4594f663..db8dc9e3 100644 --- a/include/sqlpp11/assignment.h +++ b/include/sqlpp11/assignment.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -71,15 +72,18 @@ namespace sqlpp static Context& _(const T& t, Context& context) { + serialize(simple_column(t._lhs), context); if ((trivial_value_is_null_t::value and rhs_is_trivial(t)) or rhs_is_null(t)) { - serialize(simple_column(t._lhs), context); context << "=NULL"; } + else if (rhs_is_default(t)) + { + context << "=DEFAULT"; + } else { - serialize(simple_column(t._lhs), context); context << "="; serialize(t._rhs, context); } diff --git a/include/sqlpp11/insert_value.h b/include/sqlpp11/insert_value.h index e65a8167..73c30a2f 100644 --- a/include/sqlpp11/insert_value.h +++ b/include/sqlpp11/insert_value.h @@ -59,35 +59,42 @@ namespace sqlpp struct insert_value_t { using _is_insert_value = std::true_type; + using _column_t = Column; using _pure_value_t = typename value_type_of::_cpp_value_type; using _wrapped_value_t = typename wrap_operand<_pure_value_t>::type; - using _tvin_t = typename detail::type_if, can_be_null_t::value>::type; // static asserts and SFINAE do not work together - using _null_t = typename detail::type_if::value>::type; // static asserts and SFINAE do not work together + using _tvin_t = tvin_t<_wrapped_value_t>; - insert_value_t(assignment_t assignment): + insert_value_t(_wrapped_value_t rhs): _is_null(false), _is_default(false), - _value(assignment._rhs) + _value(rhs) {} - insert_value_t(assignment_t assignment): - _is_null(assignment._rhs._is_trivial()), + insert_value_t(_tvin_t rhs): + _is_null(rhs._is_trivial()), _is_default(false), - _value(assignment._rhs._value) + _value(rhs._value) {} - insert_value_t(const assignment_t&): + insert_value_t(const null_t&): _is_null(true), _is_default(false), - _value() + _value{} {} - insert_value_t(const assignment_t&): + insert_value_t(const default_value_t&): _is_null(false), _is_default(true), - _value() + _value{} {} + template + insert_value_t(const result_field_t, Db, FieldSpec>& rhs): + _is_null(rhs.is_null()), + _is_default(false), + _value(rhs.is_null() ? _wrapped_value_t{} : rhs.value()) + {} + insert_value_t(const insert_value_t&) = default; insert_value_t(insert_value_t&&) = default; insert_value_t& operator=(const insert_value_t&) = default; @@ -106,8 +113,11 @@ namespace sqlpp static Context& _(const T& t, Context& context) { - if (t._is_null) + if ((trivial_value_is_null_t::value and t._value._is_trivial()) + or t._is_null) + { context << "NULL"; + } else if (t._is_default) context << "DEFAULT"; else diff --git a/include/sqlpp11/insert_value_list.h b/include/sqlpp11/insert_value_list.h index fa471d3b..bb20ee69 100644 --- a/include/sqlpp11/insert_value_list.h +++ b/include/sqlpp11/insert_value_list.h @@ -87,7 +87,7 @@ namespace sqlpp insert_list_data_t(Assignments... assignments): _assignments(assignments...), _columns({assignments._lhs}...), - _values(assignments._rhs...) + _values(insert_value_t{assignments._rhs}...) {} insert_list_data_t(const insert_list_data_t&) = default; @@ -98,7 +98,7 @@ namespace sqlpp std::tuple _assignments; // FIXME: Need to replace _columns and _values by _assignments (connector-container requires assignments) std::tuple...> _columns; - std::tuple _values; + std::tuple...> _values; interpretable_list_t _dynamic_columns; interpretable_list_t _dynamic_values; }; @@ -248,7 +248,7 @@ namespace sqlpp template void _add_impl(const std::true_type&, Assignments... assignments) { - return _data._insert_values.emplace_back(insert_value_t{assignments}...); + return _data._insert_values.emplace_back(insert_value_t{assignments._rhs}...); } template diff --git a/include/sqlpp11/rhs_is_default.h b/include/sqlpp11/rhs_is_default.h new file mode 100644 index 00000000..23dafe4c --- /dev/null +++ b/include/sqlpp11/rhs_is_default.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013-2014, 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_RHS_IS_DEFAULT_H +#define SQLPP_RHS_IS_DEFAULT_H + +#include + +namespace sqlpp +{ + template + struct rhs_is_default_t + { + static constexpr bool _(const T&) + { + return false; + } + }; + + template + struct rhs_is_default_t::value, void>::type> + { + static constexpr bool _(const T& t) + { + return true; + } + }; + + template + constexpr bool rhs_is_default(const Expression& e) + { + return rhs_is_default_t::type::_rhs_t>::_(e._rhs); + } + +} + +#endif diff --git a/include/sqlpp11/rhs_is_null.h b/include/sqlpp11/rhs_is_null.h index aa6d8ed0..c77e7a30 100644 --- a/include/sqlpp11/rhs_is_null.h +++ b/include/sqlpp11/rhs_is_null.h @@ -28,6 +28,7 @@ #define SQLPP_RHS_IS_NULL_H #include +#include namespace sqlpp { @@ -40,6 +41,15 @@ namespace sqlpp } }; + template + struct rhs_is_null_t::value, void>::type> + { + static constexpr bool _(const T& t) + { + return true; + } + }; + template struct rhs_is_null_t::value, void>::type> { diff --git a/tests/InterpretTest.cpp b/tests/InterpretTest.cpp index b927e239..13209e46 100644 --- a/tests/InterpretTest.cpp +++ b/tests/InterpretTest.cpp @@ -172,5 +172,10 @@ int main() serialize(row.gamma, printer); } + get_sql_name(t); + get_sql_name(t.alpha); + + flatten(t.alpha == 7, db); + return 0; } diff --git a/tests/MockDb.h b/tests/MockDb.h index 64cbb883..d6a55365 100644 --- a/tests/MockDb.h +++ b/tests/MockDb.h @@ -65,6 +65,11 @@ struct MockDbT: public sqlpp::connection using _interpreter_context_t = _serializer_context_t; + _serializer_context_t get_serializer_context() + { + return {}; + } + template static _serializer_context_t& _serialize_interpretable(const T& t, _serializer_context_t& context) { diff --git a/tests/PreparedTest.cpp b/tests/PreparedTest.cpp index ae4cc16e..2607cd39 100644 --- a/tests/PreparedTest.cpp +++ b/tests/PreparedTest.cpp @@ -106,5 +106,12 @@ int main() std::cerr << x.alpha << std::endl; } + // Check that a prepared select is default-constructible + { + auto s = select(all_of(t)).from(t).where((t.beta.like(parameter(t.beta)) and t.alpha == parameter(t.alpha)) or t.gamma != parameter(t.gamma)); + using P = decltype(db.prepare(s)); + P p; + } + return 0; } diff --git a/tests/ResultTest.cpp b/tests/ResultTest.cpp index bc01bd1b..cfdffe3e 100644 --- a/tests/ResultTest.cpp +++ b/tests/ResultTest.cpp @@ -61,6 +61,7 @@ int main() { std::cerr << sub.alpha << std::endl; } + db(insert_into(t).set(t.beta = row.beta)); } sqlpp::select((t.alpha + 1).as(t.alpha)).flags(sqlpp::all).from(t);