diff --git a/include/sqlpp11/insert.h b/include/sqlpp11/insert.h index f55b092f..e1ee5593 100644 --- a/include/sqlpp11/insert.h +++ b/include/sqlpp11/insert.h @@ -45,10 +45,11 @@ namespace sqlpp > struct insert_t { - static_assert(Table::_table_set::template is_superset_of::value, "inserted columns do not match the table in insert_into"); + static_assert(Table::_table_set::template is_superset_of::value, "columns do not match the table they are to be inserted into"); using _database_t = Database; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; + using _table_set = typename Table::_table_set; template struct _policies_update_impl @@ -97,7 +98,7 @@ namespace sqlpp -> _policies_update_t> { static_assert(is_noop_t::value, "cannot combine columns() with other methods"); - return { *this, vendor::column_list_t(args...) }; + return { *this, vendor::column_list_t{args...} }; } template @@ -105,7 +106,7 @@ namespace sqlpp -> _policies_update_t> { static_assert(is_noop_t::value, "cannot combine set() with other methods"); - return { *this, vendor::insert_list_t(args...) }; + return { *this, vendor::insert_list_t{args...} }; } template @@ -114,7 +115,7 @@ namespace sqlpp { static_assert(is_noop_t::value, "cannot combine dynamic_set() with other methods"); static_assert(_is_dynamic::value, "dynamic_set must not be called in a static statement"); - return { *this, vendor::insert_list_t<_database_t, Args...>(args...) }; + return { *this, vendor::insert_list_t<_database_t, Args...>{args...} }; } // value adding methods @@ -129,7 +130,7 @@ namespace sqlpp template void add_values(Args... args) { - static_assert(is_column_list_t::value, "cannot call add_set() before columns()"); + static_assert(is_column_list_t::value, "cannot call add_values() before columns()"); return _insert_value_list.add_values(args...); } diff --git a/include/sqlpp11/remove.h b/include/sqlpp11/remove.h index b74983b6..a0673934 100644 --- a/include/sqlpp11/remove.h +++ b/include/sqlpp11/remove.h @@ -108,7 +108,7 @@ namespace sqlpp -> _policies_update_t> { static_assert(is_noop_t::value, "cannot call using_()/dynamic_using() twice"); - return { *this, vendor::using_t(args...) }; + return { *this, vendor::using_t{args...} }; } template @@ -117,7 +117,7 @@ namespace sqlpp { static_assert(is_noop_t::value, "cannot call using_()/dynamic_using() twice"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_using must not be called in a static statement"); - return { *this, vendor::using_t<_database_t, Args...>(args...) }; + return { *this, vendor::using_t<_database_t, Args...>{args...} }; } template @@ -125,7 +125,7 @@ namespace sqlpp -> _policies_update_t> { static_assert(is_noop_t::value, "cannot call where()/dynamic_where() twice"); - return { *this, vendor::where_t(args...) }; + return { *this, vendor::where_t{args...} }; } template @@ -134,7 +134,7 @@ namespace sqlpp { static_assert(is_noop_t::value, "cannot call where()/dynamic_where() twice"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_where must not be called in a static statement"); - return { *this, vendor::where_t<_database_t, Args...>(args...) }; + return { *this, vendor::where_t<_database_t, Args...>{args...} }; } // value adding methods diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index cf1db690..2f01e1d9 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -240,7 +240,7 @@ namespace sqlpp -> _policies_update_t> { static_assert(is_noop_t::value, "flags()/dynamic_flags() must not be called twice"); - return { *this, vendor::select_flag_list_t(args...) }; + return { *this, vendor::select_flag_list_t{args...} }; } template @@ -249,7 +249,7 @@ namespace sqlpp { static_assert(is_noop_t::value, "flags()/dynamic_flags() must not be called twice"); static_assert(_is_dynamic::value, "dynamic_flags must not be called in a static statement"); - return { *this, vendor::select_flag_list_t<_database_t, Args...>(args...) }; + return { *this, vendor::select_flag_list_t<_database_t, Args...>{args...} }; } template @@ -257,7 +257,7 @@ namespace sqlpp -> _policies_update_t> { static_assert(is_noop_t::value, "columns()/dynamic_columns() must not be called twice"); - return { *this, vendor::select_column_list_t(args...) }; + return { *this, vendor::select_column_list_t{args...} }; } template @@ -266,14 +266,14 @@ namespace sqlpp { static_assert(is_noop_t::value, "columns()/dynamic_columns() must not be called twice"); static_assert(_is_dynamic::value, "dynamic_columns must not be called in a static statement"); - return { *this, vendor::select_column_list_t<_database_t, Args...>(args...) }; + return { *this, vendor::select_column_list_t<_database_t, Args...>{args...} }; } template auto from(Args... args) -> _policies_update_t> { - return { *this, vendor::from_t(args...) }; + return { *this, vendor::from_t{args...} }; } template @@ -281,7 +281,7 @@ namespace sqlpp -> _policies_update_t> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_from must not be called in a static statement"); - return { *this, vendor::from_t<_database_t, Args...>(args...) }; + return { *this, vendor::from_t<_database_t, Args...>{args...} }; } template @@ -289,7 +289,7 @@ namespace sqlpp -> _policies_update_t> { static_assert(is_noop_t::value, "cannot call where()/dynamic_where() twice"); - return { *this, vendor::where_t(args...) }; + return { *this, vendor::where_t{args...} }; } template @@ -298,7 +298,7 @@ namespace sqlpp { static_assert(is_noop_t::value, "cannot call where()/dynamic_where() twice"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_where must not be called in a static statement"); - return { *this, vendor::where_t<_database_t, Args...>(args...) }; + return { *this, vendor::where_t<_database_t, Args...>{args...} }; } template @@ -306,7 +306,7 @@ namespace sqlpp -> _policies_update_t> { static_assert(is_noop_t::value, "cannot call group_by()/dynamic_group_by() twice"); - return { *this, vendor::group_by_t(args...) }; + return { *this, vendor::group_by_t{args...} }; } template @@ -315,7 +315,7 @@ namespace sqlpp { static_assert(is_noop_t::value, "cannot call group_by()/dynamic_group_by() twice"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_group_by must not be called in a static statement"); - return { *this, vendor::group_by_t<_database_t, Args...>(args...) }; + return { *this, vendor::group_by_t<_database_t, Args...>{args...} }; } template @@ -323,7 +323,7 @@ namespace sqlpp -> _policies_update_t> { static_assert(is_noop_t::value, "cannot call having()/dynamic_having() twice"); - return { *this, vendor::having_t(args...) }; + return { *this, vendor::having_t{args...} }; } template @@ -332,7 +332,7 @@ namespace sqlpp { static_assert(is_noop_t::value, "cannot call having()/dynamic_having() twice"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_having must not be called in a static statement"); - return { *this, vendor::having_t<_database_t, Args...>(args...) }; + return { *this, vendor::having_t<_database_t, Args...>{args...} }; } template @@ -340,7 +340,7 @@ namespace sqlpp -> _policies_update_t> { static_assert(is_noop_t::value, "cannot call order_by()/dynamic_order_by() twice"); - return { *this, vendor::order_by_t(args...) }; + return { *this, vendor::order_by_t{args...} }; } template @@ -349,7 +349,7 @@ namespace sqlpp { static_assert(is_noop_t::value, "cannot call order_by()/dynamic_order_by() twice"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_order_by must not be called in a static statement"); - return { *this, vendor::order_by_t<_database_t, Args...>(args...) }; + return { *this, vendor::order_by_t<_database_t, Args...>{args...} }; } template @@ -357,7 +357,7 @@ namespace sqlpp -> _policies_update_t::type>> { static_assert(is_noop_t::value, "cannot call limit()/dynamic_limit() twice"); - return { *this, vendor::limit_t::type>({arg}) }; + return { *this, vendor::limit_t::type>{{arg}} }; } auto dynamic_limit() @@ -365,7 +365,7 @@ namespace sqlpp { static_assert(is_noop_t::value, "cannot call limit()/dynamic_limit() twice"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_limit must not be called in a static statement"); - return { *this, vendor::dynamic_limit_t<_database_t>() }; + return { *this, vendor::dynamic_limit_t<_database_t>{} }; } template @@ -373,7 +373,7 @@ namespace sqlpp -> _policies_update_t::type>> { static_assert(is_noop_t::value, "cannot call offset()/dynamic_offset() twice"); - return { *this, vendor::offset_t::type>({arg}) }; + return { *this, vendor::offset_t::type>{{arg}} }; } auto dynamic_offset() @@ -381,7 +381,7 @@ namespace sqlpp { static_assert(is_noop_t::value, "cannot call offset()/dynamic_offset() twice"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_offset must not be called in a static statement"); - return { *this, vendor::dynamic_offset_t<_database_t>() }; + return { *this, vendor::dynamic_offset_t<_database_t>{} }; } // value adding methods diff --git a/include/sqlpp11/update.h b/include/sqlpp11/update.h index 63ba4cd5..e92ba792 100644 --- a/include/sqlpp11/update.h +++ b/include/sqlpp11/update.h @@ -57,6 +57,8 @@ namespace sqlpp typename Where = vendor::no_where_t> struct update_t { + static_assert(Table::_table_set::template is_superset_of::value, "updated columns do not match the table"); + using _database_t = Database; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; @@ -109,7 +111,7 @@ namespace sqlpp -> _policies_update_t> { static_assert(is_noop_t::value, "cannot call set()/dynamic_set() twice"); - return { *this, vendor::update_list_t(args...) }; + return { *this, vendor::update_list_t{args...} }; } template @@ -118,7 +120,7 @@ namespace sqlpp { static_assert(is_noop_t::value, "cannot call set()/dynamic_set() twice"); static_assert(_is_dynamic::value, "dynamic_set must not be called in a static statement"); - return { *this, vendor::update_list_t<_database_t, Args...>(args...) }; + return { *this, vendor::update_list_t<_database_t, Args...>{args...} }; } template @@ -126,7 +128,7 @@ namespace sqlpp -> _policies_update_t> { static_assert(is_noop_t::value, "cannot call where()/dynamic_where() twice"); - return { *this, vendor::where_t(args...) }; + return { *this, vendor::where_t{args...} }; } template @@ -135,7 +137,7 @@ namespace sqlpp { static_assert(is_noop_t::value, "cannot call where()/dynamic_where() twice"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_where must not be called in a static statement"); - return { *this, vendor::where_t<_database_t, Args...>(args...) }; + return { *this, vendor::where_t<_database_t, Args...>{args...} }; } // value adding methods diff --git a/include/sqlpp11/vendor/insert_value_list.h b/include/sqlpp11/vendor/insert_value_list.h index 31ea1db6..5fb1239c 100644 --- a/include/sqlpp11/vendor/insert_value_list.h +++ b/include/sqlpp11/vendor/insert_value_list.h @@ -63,11 +63,11 @@ namespace sqlpp static_assert(not sqlpp::detail::or_t::value, "at least one assignment is prohibited by its column definition in set()"); - using _table_set = typename ::sqlpp::detail::make_joined_set< - typename Assignments::_column_t::_table_set..., - typename Assignments::value_type::_table_set... - >::type; - static_assert(_is_dynamic::value ? (_table_set::size::value < 2) : (_table_set::size::value == 1), "set() contains assignments for tables from several columns"); + using _column_table_set = typename ::sqlpp::detail::make_joined_set::type; + using _value_table_set = typename ::sqlpp::detail::make_joined_set::type; + using _table_set = typename ::sqlpp::detail::make_joined_set<_column_table_set, _value_table_set>::type; + static_assert(sizeof...(Assignments) ? (_column_table_set::size::value == 1) : true, "set() contains assignments for tables from several columns"); + static_assert(_value_table_set::template is_subset_of<_column_table_set>::value, "set() contains values from foreign tables"); insert_list_t(Assignments... assignment): _assignments(assignment...), @@ -84,8 +84,12 @@ namespace sqlpp template void add_set(const Insert&, Assignment assignment) { - static_assert(is_assignment_t::value, "set() arguments require to be assigments"); - static_assert(not must_not_insert_t::value, "set() argument must not be used in insert"); + static_assert(is_assignment_t::value, "add_set() arguments require to be assigments"); + static_assert(not must_not_insert_t::value, "add_set() argument must not be used in insert"); + using _column_table_set = typename Assignment::_column_t::_table_set; + using _value_table_set = typename Assignment::value_type::_table_set; + static_assert(_value_table_set::template is_subset_of::value, "add_set() contains a column from a foreign table"); + static_assert(_column_table_set::template is_subset_of::value, "add_set() contains a value from a foreign table"); _dynamic_columns.emplace_back(simple_column_t{assignment._lhs}); _dynamic_values.emplace_back(assignment._rhs); } @@ -127,9 +131,14 @@ namespace sqlpp column_list_t& operator=(column_list_t&&) = default; ~column_list_t() = default; - void add_values(vendor::insert_value_t... values) + template + void add_values(Assignments... assignments) { - _insert_values.emplace_back(values...); + static_assert(::sqlpp::detail::and_t::value, "add_values() arguments have to be assignments"); + using _arg_value_tuple = std::tuple...>; + using _args_correct = std::is_same<_arg_value_tuple, _value_tuple_t>; + static_assert(_args_correct::value, "add_values() arguments do not match columns() arguments"); + add_values_impl(_args_correct{}, assignments...); // dispatch to prevent error messages due to incorrect arguments } bool empty() const @@ -139,19 +148,25 @@ namespace sqlpp std::tuple...> _columns; std::vector<_value_tuple_t> _insert_values; + + private: + template + void add_values_impl(const std::true_type&, Assignments... assignments) + { + _insert_values.emplace_back(vendor::insert_value_t{assignments}...); + } + + template + void add_values_impl(const std::false_type&, Assignments... assignments) + { + } + }; struct no_insert_value_list_t { using _is_noop = std::true_type; using _table_set = ::sqlpp::detail::type_set<>; - - template - void add_values(Base base, Args...) - { - static_assert(wrong_t::value, "cannot call add_values() without calling columns() first"); - } - }; // Interpreters diff --git a/include/sqlpp11/vendor/update_list.h b/include/sqlpp11/vendor/update_list.h index 3637f3c5..eab8b785 100644 --- a/include/sqlpp11/vendor/update_list.h +++ b/include/sqlpp11/vendor/update_list.h @@ -52,6 +52,12 @@ namespace sqlpp static_assert(not ::sqlpp::detail::or_t::value, "at least one assignment is prohibited by its column definition in set()"); + using _column_table_set = typename ::sqlpp::detail::make_joined_set::type; + using _value_table_set = typename ::sqlpp::detail::make_joined_set::type; + using _table_set = typename ::sqlpp::detail::make_joined_set<_column_table_set, _value_table_set>::type; + static_assert(sizeof...(Assignments) ? (_column_table_set::size::value == 1) : true, "set() contains assignments for tables from several columns"); + static_assert(_value_table_set::template is_subset_of<_column_table_set>::value, "set() contains values from foreign tables"); + update_list_t(Assignments... assignments): _assignments(assignments...) {} @@ -70,7 +76,6 @@ namespace sqlpp _dynamic_assignments.emplace_back(assignment); } - const update_list_t& _update_list() const { return *this; } _parameter_tuple_t _assignments; typename vendor::interpretable_list_t _dynamic_assignments; }; @@ -78,7 +83,7 @@ namespace sqlpp struct no_update_list_t { using _is_noop = std::true_type; - const no_update_list_t& _update_list() const { return *this; } + using _table_set = ::sqlpp::detail::type_set<>; }; // Interpreters diff --git a/tests/InsertTest.cpp b/tests/InsertTest.cpp index 93d7e6c7..9a343a0c 100644 --- a/tests/InsertTest.cpp +++ b/tests/InsertTest.cpp @@ -61,6 +61,9 @@ int main() interpret(insert_into(t).default_values(), printer).flush(); interpret(insert_into(t), printer).flush(); interpret(insert_into(t).set(t.beta = "kirschauflauf"), printer).flush(); + interpret(insert_into(t).columns(t.beta), printer).flush(); + auto multi_insert = insert_into(t).columns(t.beta); + multi_insert.add_values(t.beta = "cheesecake"); auto i = dynamic_insert_into(db, t).dynamic_set(); i.add_set(t.beta = "kirschauflauf"); interpret(i, printer).flush(); diff --git a/tests/UpdateTest.cpp b/tests/UpdateTest.cpp index 93dbf7f0..cdc35a6f 100644 --- a/tests/UpdateTest.cpp +++ b/tests/UpdateTest.cpp @@ -59,8 +59,8 @@ int main() interpret(update(t), printer).flush(); interpret(update(t).set(t.gamma = false), printer).flush(); interpret(update(t).set(t.gamma = false).where(t.beta != "transparent"), printer).flush(); -#warning make this fail! - interpret(update(t).set(t.beta = f.delta).where(t.beta != "transparent"), printer).flush(); +#warning make this fail + interpret(update(t).set(t.beta = "opaque").where(t.beta != f.delta), printer).flush(); auto u = dynamic_update(db, t).dynamic_set(t.gamma = false).dynamic_where(); u.add_set(t.gamma = false); interpret(u, printer).flush();