From 0ffd93108b395f978dc32edbc371c1c00ceed47b Mon Sep 17 00:00:00 2001 From: rbock Date: Tue, 22 Apr 2014 20:46:32 +0200 Subject: [PATCH] Added a table consistency checks to several dynamic methods --- include/sqlpp11/insert.h | 5 ++++ include/sqlpp11/remove.h | 14 +++++++++-- include/sqlpp11/select.h | 26 ++++++++++++--------- include/sqlpp11/update.h | 6 +++++ include/sqlpp11/vendor/group_by.h | 7 ++++++ include/sqlpp11/vendor/having.h | 7 ++++++ include/sqlpp11/vendor/limit.h | 1 + include/sqlpp11/vendor/offset.h | 1 + include/sqlpp11/vendor/order_by.h | 7 ++++++ include/sqlpp11/vendor/select_column_list.h | 6 ++--- include/sqlpp11/vendor/select_flag_list.h | 7 ++++++ include/sqlpp11/vendor/update_list.h | 9 ++++++- include/sqlpp11/vendor/using.h | 2 ++ include/sqlpp11/vendor/where.h | 7 ++++++ tests/UpdateTest.cpp | 1 + 15 files changed, 89 insertions(+), 17 deletions(-) diff --git a/include/sqlpp11/insert.h b/include/sqlpp11/insert.h index 910a7acb..35343bf9 100644 --- a/include/sqlpp11/insert.h +++ b/include/sqlpp11/insert.h @@ -72,6 +72,11 @@ namespace sqlpp using _new_statement_t = typename _policies_insert_t::type; using _table_set = typename _table_t::_table_set; + + using _known_tables = detail::make_joined_set_t; + + template + using _no_unknown_tables = detail::is_subset_of; }; } diff --git a/include/sqlpp11/remove.h b/include/sqlpp11/remove.h index 06575373..9ea1fd6c 100644 --- a/include/sqlpp11/remove.h +++ b/include/sqlpp11/remove.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -49,6 +50,7 @@ namespace sqlpp template struct remove_policies_t @@ -56,12 +58,14 @@ namespace sqlpp using _database_t = Db; using _table_t = Table; using _using_t = Using; + using _extra_tables_t = ExtraTables; using _where_t = Where; - using _statement_t = remove_t; + using _statement_t = remove_t; struct _methods_t: public _using_t::template _methods_t, + public _extra_tables_t::template _methods_t, public _where_t::template _methods_t {}; @@ -72,7 +76,12 @@ namespace sqlpp }; template - using _new_statement_t = typename _policies_update_t::type; + using _new_statement_t = typename _policies_update_t::type; + + using _known_tables = detail::make_joined_set_t; + + template + using _no_unknown_tables = detail::is_subset_of; }; } @@ -87,6 +96,7 @@ namespace sqlpp using _database_t = typename _policies_t::_database_t; using _table_t = typename _policies_t::_table_t; using _using_t = typename _policies_t::_using_t; + using _extra_tables_t = typename _policies_t::_extra_tables_t; using _where_t = typename _policies_t::_where_t; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index dc54621a..7249045f 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -255,22 +255,25 @@ namespace sqlpp static constexpr bool value = ::sqlpp::detail::is_subset_of::value; }; + void _check_consistency() const + { + static_assert(is_table_subset_of_from<_flag_list_t>::value, "flags require additional tables in from()"); + static_assert(is_table_subset_of_from<_column_list_t>::value, "selected columns require additional tables in from()"); + static_assert(is_table_subset_of_from<_where_t>::value, "where() expression requires additional tables in from()"); + static_assert(is_table_subset_of_from<_group_by_t>::value, "group_by() expression requires additional tables in from()"); + static_assert(is_table_subset_of_from<_having_t>::value, "having() expression requires additional tables in from()"); + static_assert(is_table_subset_of_from<_order_by_t>::value, "order_by() expression requires additional tables in from()"); + static_assert(is_table_subset_of_from<_limit_t>::value, "limit() expression requires additional tables in from()"); + static_assert(is_table_subset_of_from<_offset_t>::value, "offset() expression requires additional tables in from()"); + static_assert(not _table_set::size::value, "one sub expression contains tables which are not in the from()"); + } + // Execute template auto _run(Database& db) const -> result_t> { -#warning: need to check in add_xy method as well -#warning: need add_wxy_without_table_check - static_assert(is_table_subset_of_from<_flag_list_t>::value, "flags require additional tables in from()"); - static_assert(is_table_subset_of_from<_column_list_t>::value, "selected columns require additional tables in from()"); - static_assert(is_table_subset_of_from<_where_t>::value, "where() expression requires additional tables in from()"); - static_assert(is_table_subset_of_from<_group_by_t>::value, "group_by() expression requires additional tables in from()"); - static_assert(is_table_subset_of_from<_having_t>::value, "having() expression requires additional tables in from()"); - static_assert(is_table_subset_of_from<_order_by_t>::value, "order_by() expression requires additional tables in from()"); - static_assert(is_table_subset_of_from<_limit_t>::value, "limit() expression requires additional tables in from()"); - static_assert(is_table_subset_of_from<_offset_t>::value, "offset() expression requires additional tables in from()"); - static_assert(not _table_set::size::value, "one sub expression contains tables which are not in the from()"); + _check_consistency(); static_assert(_get_static_no_of_parameters() == 0, "cannot run select directly with parameters, use prepare instead"); return {db.select(*this), get_dynamic_names()}; @@ -281,6 +284,7 @@ namespace sqlpp auto _prepare(Database& db) const -> prepared_select_t { + _check_consistency(); return {{}, get_dynamic_names(), db.prepare_select(*this)}; } diff --git a/include/sqlpp11/update.h b/include/sqlpp11/update.h index 94353edd..496adb14 100644 --- a/include/sqlpp11/update.h +++ b/include/sqlpp11/update.h @@ -73,6 +73,12 @@ namespace sqlpp template using _new_statement_t = typename _policies_update_t::type; + + using _known_tables = detail::make_joined_set_t; + + template + using _no_unknown_tables = detail::is_subset_of; + }; } diff --git a/include/sqlpp11/vendor/group_by.h b/include/sqlpp11/vendor/group_by.h index d6a88c39..6d3dfba1 100644 --- a/include/sqlpp11/vendor/group_by.h +++ b/include/sqlpp11/vendor/group_by.h @@ -70,10 +70,17 @@ namespace sqlpp struct _methods_t { template + void add_group_by_ntc(Expression expression) + { + add_group_by(expression); + } + + template void add_group_by(Expression expression) { static_assert(_is_dynamic::value, "add_group_by must not be called for static group_by"); static_assert(is_expression_t::value, "invalid expression argument in add_group_by()"); + static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in add_group_by()"); using ok = ::sqlpp::detail::all_t>; diff --git a/include/sqlpp11/vendor/having.h b/include/sqlpp11/vendor/having.h index f76e0142..20beeb97 100644 --- a/include/sqlpp11/vendor/having.h +++ b/include/sqlpp11/vendor/having.h @@ -67,10 +67,17 @@ namespace sqlpp struct _methods_t { template + void add_having_ntc(Expression expression) + { + add_having(expression); + } + + template void add_having(Expression expression) { static_assert(_is_dynamic::value, "add_having must not be called for static having"); static_assert(is_expression_t::value, "invalid expression argument in add_having()"); + static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in add_having()"); using ok = ::sqlpp::detail::all_t>; diff --git a/include/sqlpp11/vendor/limit.h b/include/sqlpp11/vendor/limit.h index e0c1216f..2d77760a 100644 --- a/include/sqlpp11/vendor/limit.h +++ b/include/sqlpp11/vendor/limit.h @@ -93,6 +93,7 @@ namespace sqlpp template void set_limit(Limit value) { + // FIXME: Make sure that Limit does not require external tables? Need to read up on SQL using arg_t = typename wrap_operand::type; static_cast(this)->_limit._value = arg_t{value}; static_cast(this)->_limit._initialized = true; diff --git a/include/sqlpp11/vendor/offset.h b/include/sqlpp11/vendor/offset.h index 647bd99b..c8611ce0 100644 --- a/include/sqlpp11/vendor/offset.h +++ b/include/sqlpp11/vendor/offset.h @@ -92,6 +92,7 @@ namespace sqlpp template void set_offset(Offset value) { + // FIXME: Make sure that Offset does not require external tables? Need to read up on SQL using arg_t = typename wrap_operand::type; static_cast(this)->_offset._value = arg_t{value}; static_cast(this)->_offset._initialized = true; diff --git a/include/sqlpp11/vendor/order_by.h b/include/sqlpp11/vendor/order_by.h index b23330a6..9eae6c43 100644 --- a/include/sqlpp11/vendor/order_by.h +++ b/include/sqlpp11/vendor/order_by.h @@ -69,10 +69,17 @@ namespace sqlpp struct _methods_t { template + void add_order_by_ntc(Expression expression) + { + add_order_by(expression); + } + + template void add_order_by(Expression expression) { static_assert(_is_dynamic::value, "add_order_by must not be called for static order_by"); static_assert(is_sort_order_t::value, "invalid expression argument in add_order_by()"); + static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in add_order_by()"); using ok = ::sqlpp::detail::all_t>; diff --git a/include/sqlpp11/vendor/select_column_list.h b/include/sqlpp11/vendor/select_column_list.h index ebff2552..06c57236 100644 --- a/include/sqlpp11/vendor/select_column_list.h +++ b/include/sqlpp11/vendor/select_column_list.h @@ -188,15 +188,15 @@ namespace sqlpp template void add_column_ntc(NamedExpression namedExpression) { - add_column(namedExpression); + add_column(namedExpression); } - template + template void add_column(NamedExpression namedExpression) { static_assert(_is_dynamic::value, "add_column can only be called for dynamic_column"); static_assert(is_named_expression_t::value, "invalid named expression argument in add_column()"); - static_assert(Ntc::value or Policies::template _no_unknown_tables::value, "named expression uses tables unknown to this statement in add_column()"); + static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "named expression uses tables unknown to this statement in add_column()"); using ok = ::sqlpp::detail::all_t>; diff --git a/include/sqlpp11/vendor/select_flag_list.h b/include/sqlpp11/vendor/select_flag_list.h index 80c0f850..93384318 100644 --- a/include/sqlpp11/vendor/select_flag_list.h +++ b/include/sqlpp11/vendor/select_flag_list.h @@ -66,10 +66,17 @@ namespace sqlpp struct _methods_t { template + void add_flag_ntc(Flag flag) + { + add_flag(flag); + } + + template void add_flag(Flag flag) { static_assert(_is_dynamic::value, "add_flag must not be called for static select flags"); static_assert(is_select_flag_t::value, "invalid select flag argument in add_flag()"); + static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "flag uses tables unknown to this statement in add_flag()"); using ok = ::sqlpp::detail::all_t>; diff --git a/include/sqlpp11/vendor/update_list.h b/include/sqlpp11/vendor/update_list.h index a670c422..b3446857 100644 --- a/include/sqlpp11/vendor/update_list.h +++ b/include/sqlpp11/vendor/update_list.h @@ -72,11 +72,18 @@ namespace sqlpp struct _methods_t { template + void add_set_ntc(Assignment assignment) + { + add_set(assignment); + } + + template void add_set(Assignment assignment) { static_assert(_is_dynamic::value, "add_set must not be called for static from()"); static_assert(is_assignment_t::value, "invalid assignment argument in add_set()"); - static_assert(sqlpp::detail::not_t::value, "set() argument must not be updated"); + static_assert(sqlpp::detail::not_t::value, "add_set() argument must not be updated"); + static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "assignment uses tables unknown to this statement in add_set()"); using ok = ::sqlpp::detail::all_t::value, "at least one argument is not an table in using()"); + using _table_set = ::sqlpp::detail::make_joined_set_t; + using_t(Tables... tables): _tables(tables...) {} diff --git a/include/sqlpp11/vendor/where.h b/include/sqlpp11/vendor/where.h index b31996aa..a5663ec2 100644 --- a/include/sqlpp11/vendor/where.h +++ b/include/sqlpp11/vendor/where.h @@ -68,10 +68,17 @@ namespace sqlpp struct _methods_t { template + void add_where_ntc(Expression expression) + { + add_where(expression); + } + + template void add_where(Expression expression) { static_assert(_is_dynamic::value, "add_where can only be called for dynamic_where"); static_assert(is_expression_t::value, "invalid expression argument in add_where()"); + static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in add_where()"); using ok = ::sqlpp::detail::all_t>; diff --git a/tests/UpdateTest.cpp b/tests/UpdateTest.cpp index 35078956..fcf0c6d3 100644 --- a/tests/UpdateTest.cpp +++ b/tests/UpdateTest.cpp @@ -62,6 +62,7 @@ int main() serialize(update(t).set(t.beta = "opaque").where(t.beta != t.beta), printer).str(); auto u = dynamic_update(db, t).dynamic_set(t.gamma = false).dynamic_where(); u.add_set(t.gamma = false); + u.add_where(t.gamma != false); serialize(u, printer).str(); db(u);