diff --git a/include/sqlpp11/custom_query.h b/include/sqlpp11/custom_query.h index 9c77bc72..87826ec0 100644 --- a/include/sqlpp11/custom_query.h +++ b/include/sqlpp11/custom_query.h @@ -56,6 +56,12 @@ namespace sqlpp using _traits = make_traits; using _recursive_traits = make_recursive_traits; + using _parameter_check = typename std::conditional::value == 0, + consistent_t, assert_no_parameters_t>::type; + using _run_check = detail::get_first_if; + using _prepare_check = consistent_t; + custom_query_t(Parts... parts): _parts(parts...) {} @@ -70,17 +76,17 @@ namespace sqlpp custom_query_t& operator=(custom_query_t&&) = default; ~custom_query_t() = default; - static void _check_consistency() {}; - template auto _run(Db& db) const -> decltype(std::declval<_methods_t>()._run(db, *this)) { + _run_check::_(); return _methods_t::_run(db, *this); } template auto _prepare(Db& db) const -> decltype(std::declval<_methods_t>()._prepare(db, *this)) { + _prepare_check::_(); return _methods_t::_prepare(db, *this); } diff --git a/include/sqlpp11/extra_tables.h b/include/sqlpp11/extra_tables.h index d2fe8a73..473479b5 100644 --- a/include/sqlpp11/extra_tables.h +++ b/include/sqlpp11/extra_tables.h @@ -99,7 +99,7 @@ namespace sqlpp template struct _methods_t { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; @@ -142,7 +142,7 @@ namespace sqlpp template using _new_statement_t = new_statement; - static void _check_consistency() {} + using _consistency_check = consistent_t; template auto extra_tables(Args...) const diff --git a/include/sqlpp11/from.h b/include/sqlpp11/from.h index b6c9b4e6..84d107c9 100644 --- a/include/sqlpp11/from.h +++ b/include/sqlpp11/from.h @@ -119,7 +119,7 @@ namespace sqlpp template struct _methods_t { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; @@ -163,7 +163,7 @@ namespace sqlpp template using _new_statement_t = new_statement; - static void _check_consistency() {} + using _consistency_check = consistent_t; template auto from(Tables... tables) const diff --git a/include/sqlpp11/group_by.h b/include/sqlpp11/group_by.h index 89792311..e9bd0e9d 100644 --- a/include/sqlpp11/group_by.h +++ b/include/sqlpp11/group_by.h @@ -128,7 +128,7 @@ namespace sqlpp template struct _methods_t { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; @@ -172,7 +172,7 @@ namespace sqlpp template using _new_statement_t = new_statement; - static void _check_consistency() {} + using _consistency_check = consistent_t; template auto group_by(Args... args) const diff --git a/include/sqlpp11/having.h b/include/sqlpp11/having.h index cd412c7c..b43f73e9 100644 --- a/include/sqlpp11/having.h +++ b/include/sqlpp11/having.h @@ -126,7 +126,7 @@ namespace sqlpp template struct _methods_t { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; @@ -170,7 +170,7 @@ namespace sqlpp template using _new_statement_t = new_statement; - static void _check_consistency() {} + using _consistency_check = consistent_t; template auto having(Args... args) const diff --git a/include/sqlpp11/insert.h b/include/sqlpp11/insert.h index 59091a04..52f1e749 100644 --- a/include/sqlpp11/insert.h +++ b/include/sqlpp11/insert.h @@ -61,18 +61,12 @@ namespace sqlpp auto _run(Db& db, const Composite& composite) const -> decltype(db.insert(composite)) { - Composite::_check_consistency(); - static_assert(Composite::_get_static_no_of_parameters() == 0, "cannot run insert directly with parameters, use prepare instead"); - return db.insert(composite); } template auto _run(Db& db) const -> decltype(db.insert(this->_get_statement())) { - _statement_t::_check_consistency(); - - static_assert(_statement_t::_get_static_no_of_parameters() == 0, "cannot run insert directly with parameters, use prepare instead"); return db.insert(_get_statement()); } @@ -81,8 +75,6 @@ namespace sqlpp auto _prepare(Db& db, const Composite& composite) const -> prepared_insert_t { - Composite::_check_consistency(); - return {{}, db.prepare_insert(composite)}; } @@ -90,8 +82,6 @@ namespace sqlpp auto _prepare(Db& db) const -> prepared_insert_t { - _statement_t::_check_consistency(); - return {{}, db.prepare_insert(_get_statement())}; } }; diff --git a/include/sqlpp11/insert_value_list.h b/include/sqlpp11/insert_value_list.h index 8f07b51e..d7355b0a 100644 --- a/include/sqlpp11/insert_value_list.h +++ b/include/sqlpp11/insert_value_list.h @@ -96,7 +96,7 @@ namespace sqlpp template struct _methods_t { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; @@ -200,7 +200,7 @@ namespace sqlpp template struct _methods_t { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; @@ -288,10 +288,21 @@ namespace sqlpp template struct _methods_t { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; + struct assert_insert_values_t + { + using type = std::false_type; + + template + static void _() + { + static_assert(wrong_t::value, "insert values required, e.g. set(...) or default_values()"); + }; + }; + // NO INSERT COLUMNS/VALUES YET struct no_insert_value_list_t { @@ -332,10 +343,7 @@ namespace sqlpp template using _new_statement_t = new_statement; - static void _check_consistency() - { - static_assert(wrong_t<_methods_t>::value, "insert values required, e.g. set(...) or default_values()"); - } + using _consistency_check = assert_insert_values_t; auto default_values() const -> _new_statement_t diff --git a/include/sqlpp11/into.h b/include/sqlpp11/into.h index e1d2ddd5..71bb48cf 100644 --- a/include/sqlpp11/into.h +++ b/include/sqlpp11/into.h @@ -96,11 +96,22 @@ namespace sqlpp template struct _methods_t { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; + struct assert_into_t + { + using type = std::false_type; + + template + static void _() + { + static_assert(wrong_t::value, "into() required"); + }; + }; + // NO INTO YET struct no_into_t { @@ -141,10 +152,7 @@ namespace sqlpp template using _new_statement_t = new_statement; - static void _check_consistency() - { - static_assert(wrong_t<_methods_t>::value, "into() required"); - } + using _consistency_check = assert_into_t; template auto into(Args... args) const diff --git a/include/sqlpp11/limit.h b/include/sqlpp11/limit.h index 40b756ce..49266fb8 100644 --- a/include/sqlpp11/limit.h +++ b/include/sqlpp11/limit.h @@ -89,7 +89,7 @@ namespace sqlpp template struct _methods_t { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; @@ -166,7 +166,7 @@ namespace sqlpp template struct _methods_t { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; @@ -209,7 +209,7 @@ namespace sqlpp template using _new_statement_t = new_statement; - static void _check_consistency() {} + using _consistency_check = consistent_t; template auto limit(Arg arg) const diff --git a/include/sqlpp11/noop.h b/include/sqlpp11/noop.h index 1c1b4d61..d2341f1c 100644 --- a/include/sqlpp11/noop.h +++ b/include/sqlpp11/noop.h @@ -55,18 +55,12 @@ namespace sqlpp template auto _run(Db& db, const Composite& composite) const -> void { - Composite::_check_consistency(); - static_assert(Composite::_get_static_no_of_parameters() == 0, "cannot run execute directly with parameters, use prepare instead"); - return db.execute(composite); } template auto _run(Db& db) const -> void { - _statement_t::_check_consistency(); - - static_assert(_statement_t::_get_static_no_of_parameters() == 0, "cannot run insert directly with parameters, use prepare instead"); return db.execute(_get_statement()); } @@ -75,8 +69,6 @@ namespace sqlpp auto _prepare(Db& db, const Composite& composite) const -> prepared_execute_t { - Composite::_check_consistency(); - return {{}, db.prepare_execute(composite)}; } @@ -84,8 +76,6 @@ namespace sqlpp auto _prepare(Db& db) const -> prepared_execute_t { - _statement_t::_check_consistency(); - return {{}, db.prepare_execute(_get_statement())}; } }; diff --git a/include/sqlpp11/offset.h b/include/sqlpp11/offset.h index 5d0b4b3b..bc8d6769 100644 --- a/include/sqlpp11/offset.h +++ b/include/sqlpp11/offset.h @@ -89,7 +89,7 @@ namespace sqlpp template struct _methods_t { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; @@ -165,7 +165,7 @@ namespace sqlpp template struct _methods_t { - static void _check_consistency() {} + using _consistency_check = consistent_t; template void set_offset(Offset value) @@ -220,7 +220,7 @@ namespace sqlpp template using _new_statement_t = new_statement; - static void _check_consistency() {} + using _consistency_check = consistent_t; template auto offset(Arg arg) const diff --git a/include/sqlpp11/order_by.h b/include/sqlpp11/order_by.h index 8d761989..c27cf92b 100644 --- a/include/sqlpp11/order_by.h +++ b/include/sqlpp11/order_by.h @@ -128,7 +128,7 @@ namespace sqlpp template struct _methods_t { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; @@ -172,7 +172,7 @@ namespace sqlpp template using _new_statement_t = new_statement; - static void _check_consistency() {} + using _consistency_check = consistent_t; template auto order_by(Args... args) const diff --git a/include/sqlpp11/prepared_execute.h b/include/sqlpp11/prepared_execute.h index e181d37c..e9c27c9d 100644 --- a/include/sqlpp11/prepared_execute.h +++ b/include/sqlpp11/prepared_execute.h @@ -38,6 +38,8 @@ namespace sqlpp using _parameter_list_t = make_parameter_list_t; using _prepared_statement_t = typename Db::_prepared_statement_t; + using _run_check = consistent_t; + auto _run(Db& db) const -> void { diff --git a/include/sqlpp11/prepared_insert.h b/include/sqlpp11/prepared_insert.h index e32c73c8..51c759fe 100644 --- a/include/sqlpp11/prepared_insert.h +++ b/include/sqlpp11/prepared_insert.h @@ -38,6 +38,8 @@ namespace sqlpp using _parameter_list_t = make_parameter_list_t; using _prepared_statement_t = typename Db::_prepared_statement_t; + using _run_check = consistent_t; + auto _run(Db& db) const -> size_t { diff --git a/include/sqlpp11/prepared_remove.h b/include/sqlpp11/prepared_remove.h index 672ab5a6..3203ee1b 100644 --- a/include/sqlpp11/prepared_remove.h +++ b/include/sqlpp11/prepared_remove.h @@ -38,6 +38,8 @@ namespace sqlpp using _parameter_list_t = make_parameter_list_t; using _prepared_statement_t = typename Db::_prepared_statement_t; + using _run_check = consistent_t; + auto _run(Db& db) const -> size_t { diff --git a/include/sqlpp11/prepared_select.h b/include/sqlpp11/prepared_select.h index 2701e17e..40553931 100644 --- a/include/sqlpp11/prepared_select.h +++ b/include/sqlpp11/prepared_select.h @@ -40,6 +40,8 @@ namespace sqlpp using _dynamic_names_t = typename Statement::_dynamic_names_t; using _prepared_statement_t = typename Database::_prepared_statement_t; + using _run_check = consistent_t; + auto _run(Database& db) const -> result_t { diff --git a/include/sqlpp11/prepared_update.h b/include/sqlpp11/prepared_update.h index 8d51b32d..b7f94b86 100644 --- a/include/sqlpp11/prepared_update.h +++ b/include/sqlpp11/prepared_update.h @@ -38,6 +38,8 @@ namespace sqlpp using _parameter_list_t = make_parameter_list_t; using _prepared_statement_t = typename Db::_prepared_statement_t; + using _run_check = consistent_t; + auto _run(Db& db) const -> size_t { diff --git a/include/sqlpp11/remove.h b/include/sqlpp11/remove.h index 00890eaf..a74cc710 100644 --- a/include/sqlpp11/remove.h +++ b/include/sqlpp11/remove.h @@ -61,18 +61,12 @@ namespace sqlpp auto _run(Db& db, const Composite& composite) const -> decltype(db.remove(composite)) { - Composite::_check_consistency(); - static_assert(Composite::_get_static_no_of_parameters() == 0, "cannot run remove directly with parameters, use prepare instead"); - return db.remove(composite); } template auto _run(Db& db) const -> decltype(db.remove(this->_get_statement())) { - _statement_t::_check_consistency(); - - static_assert(_statement_t::_get_static_no_of_parameters() == 0, "cannot run remove directly with parameters, use prepare instead"); return db.remove(_get_statement()); } @@ -81,8 +75,6 @@ namespace sqlpp auto _prepare(Db& db, const Composite& composite) const -> prepared_remove_t { - Composite::_check_consistency(); - return {{}, db.prepare_remove(composite)}; } @@ -90,8 +82,6 @@ namespace sqlpp auto _prepare(Db& db) const -> prepared_remove_t { - _statement_t::_check_consistency(); - return {{}, db.prepare_remove(_get_statement())}; } }; diff --git a/include/sqlpp11/select_column_list.h b/include/sqlpp11/select_column_list.h index 4dc12f1b..627c37ff 100644 --- a/include/sqlpp11/select_column_list.h +++ b/include/sqlpp11/select_column_list.h @@ -231,7 +231,7 @@ namespace sqlpp template struct _methods_t { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; // Result methods @@ -297,9 +297,6 @@ namespace sqlpp auto _run(Db& db, const Composite& composite) const -> result_t> { - Composite::_check_consistency(); - static_assert(Composite::_get_static_no_of_parameters() == 0, "cannot run select directly with parameters, use prepare instead"); - return {db.select(composite), get_dynamic_names()}; } @@ -307,9 +304,6 @@ namespace sqlpp auto _run(Db& db) const -> result_t())), _result_row_t> { - _statement_t::_check_consistency(); - static_assert(_statement_t::_get_static_no_of_parameters() == 0, "cannot run select directly with parameters, use prepare instead"); - return {db.select(_get_statement()), get_dynamic_names()}; } @@ -318,8 +312,6 @@ namespace sqlpp auto _prepare(Db& db, const Composite& composite) const -> prepared_select_t { - Composite::_check_consistency(); - return {make_parameter_list_t{}, get_dynamic_names(), db.prepare_select(composite)}; } @@ -327,8 +319,6 @@ namespace sqlpp auto _prepare(Db& db) const -> prepared_select_t { - _statement_t::_check_consistency(); - return {make_parameter_list_t<_statement_t>{}, get_dynamic_names(), db.prepare_select(_get_statement())}; } }; @@ -385,7 +375,7 @@ namespace sqlpp template using _new_statement_t = new_statement; - static void _check_consistency() {} + using _consistency_check = consistent_t; template auto columns(Args... args) const diff --git a/include/sqlpp11/select_flag_list.h b/include/sqlpp11/select_flag_list.h index 5864816d..afeaa9d4 100644 --- a/include/sqlpp11/select_flag_list.h +++ b/include/sqlpp11/select_flag_list.h @@ -127,7 +127,7 @@ namespace sqlpp template struct _methods_t { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; @@ -171,7 +171,7 @@ namespace sqlpp template using _new_statement_t = new_statement; - static void _check_consistency() {} + using _consistency_check = consistent_t; template auto flags(Args... args) const diff --git a/include/sqlpp11/single_table.h b/include/sqlpp11/single_table.h index ca6566cb..f30a06c8 100644 --- a/include/sqlpp11/single_table.h +++ b/include/sqlpp11/single_table.h @@ -95,7 +95,7 @@ namespace sqlpp template struct _methods_t { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; @@ -140,7 +140,7 @@ namespace sqlpp template using _new_statement_t = new_statement; - static void _check_consistency() {} + using _consistency_check = consistent_t; template auto from(Args... args) const diff --git a/include/sqlpp11/statement.h b/include/sqlpp11/statement.h index e0d48437..26e3fa96 100644 --- a/include/sqlpp11/statement.h +++ b/include/sqlpp11/statement.h @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -43,6 +44,28 @@ namespace sqlpp template struct statement_t; + struct assert_no_unknown_tables_t + { + using type = std::false_type; + + template + static void _() + { + static_assert(wrong_t::value, "one clause requires tables which are otherwise not known in the statement"); + } + }; + + struct assert_no_parameters_t + { + using type = std::false_type; + + template + static void _() + { + static_assert(wrong_t::value, "cannot run statements with parameters directly, use prepare instead"); + } + }; + namespace detail { template @@ -110,7 +133,7 @@ namespace sqlpp struct _recursive_traits { - using _required_tables = statement_policies_t::_required_tables; + using _required_tables = _required_tables; using _provided_tables = detail::type_set<>; using _provided_outer_tables = detail::type_set<>; using _extra_tables = detail::type_set<>; @@ -119,6 +142,16 @@ namespace sqlpp detail::type_set, detail::type_set<>>::type; }; + + using _table_check = typename std::conditional<_required_tables::size::value == 0, + consistent_t, assert_no_unknown_tables_t>::type; + using _parameter_check = typename std::conditional::value == 0, + consistent_t, assert_no_parameters_t>::type; + + using _run_check = detail::get_first_if::_consistency_check...>; + using _prepare_check = detail::get_first_if::_consistency_check...>; }; } @@ -132,6 +165,9 @@ namespace sqlpp public Policies::template _methods_t>... { using _policies_t = typename detail::statement_policies_t; + using _run_check = typename _policies_t::_run_check; + using _prepare_check = typename _policies_t::_prepare_check; + using _result_type_provider = typename _policies_t::_result_type_provider; template using _result_methods_t = typename _result_type_provider::template _result_methods_t; @@ -181,14 +217,19 @@ namespace sqlpp return _policies_t::_can_be_used_as_table(); } - static void _check_consistency() + template + auto _run(Database& db) const -> decltype(std::declval<_result_methods_t>()._run(db)) { - static_assert(not required_tables_of<_policies_t>::size::value, "one sub expression requires tables which are otherwise not known in the statement"); - - using swallow = int[]; - (void) swallow{(Policies::template _methods_t>::_check_consistency(), 0)...}; + _run_check::_(); + return _result_methods_t::_run(db); } + template + auto _prepare(Database& db) const -> decltype(std::declval<_result_methods_t>()._prepare(db)) + { + _prepare_check::_(); + return _result_methods_t::_prepare(db); + } }; @@ -244,7 +285,7 @@ namespace sqlpp template struct _methods_t { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; diff --git a/include/sqlpp11/type_traits.h b/include/sqlpp11/type_traits.h index 25686dcc..d83b8ab1 100644 --- a/include/sqlpp11/type_traits.h +++ b/include/sqlpp11/type_traits.h @@ -239,6 +239,16 @@ namespace sqlpp template using derived_statement_t = typename Policies::_statement_t; + + struct consistent_t + { + using type = std::true_type; + + static void _() {}; + }; + + template + using is_inconsistent_t = typename std::conditional::value, std::false_type, std::true_type>::type; } #endif diff --git a/include/sqlpp11/update.h b/include/sqlpp11/update.h index f940fdab..49f4ee85 100644 --- a/include/sqlpp11/update.h +++ b/include/sqlpp11/update.h @@ -61,18 +61,12 @@ namespace sqlpp auto _run(Db& db, const Composite& composite) const -> decltype(db.update(composite)) { - Composite::_check_consistency(); - static_assert(Composite::_get_static_no_of_parameters() == 0, "cannot run update directly with parameters, use prepare instead"); - return db.update(composite); } template auto _run(Db& db) const -> decltype(db.update(this->_get_statement())) { - _statement_t::_check_consistency(); - - static_assert(_statement_t::_get_static_no_of_parameters() == 0, "cannot run update directly with parameters, use prepare instead"); return db.update(_get_statement()); } @@ -81,8 +75,6 @@ namespace sqlpp auto _prepare(Db& db, const Composite& composite) const -> prepared_update_t { - Composite::_check_consistency(); - return {{}, db.prepare_update(composite)}; } @@ -90,8 +82,6 @@ namespace sqlpp auto _prepare(Db& db) const -> prepared_update_t { - _statement_t::_check_consistency(); - return {{}, db.prepare_update(_get_statement())}; } }; diff --git a/include/sqlpp11/update_list.h b/include/sqlpp11/update_list.h index 425b8b8f..2b2edcd3 100644 --- a/include/sqlpp11/update_list.h +++ b/include/sqlpp11/update_list.h @@ -124,10 +124,21 @@ namespace sqlpp template struct _methods_t { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; + struct assert_update_assignments_t + { + using type = std::false_type; + + template + static void _() + { + static_assert(wrong_t::value, "update assignments required, i.e. set(...)"); + }; + }; + struct no_update_list_t { using _traits = make_traits; @@ -167,10 +178,7 @@ namespace sqlpp template using _new_statement_t = new_statement; - static void _check_consistency() - { - static_assert(wrong_t<_methods_t>::value, "update assignments required, i.e. set(...)"); - } + using _consistency_check = assert_update_assignments_t; template auto set(Assignments... assignments) const diff --git a/include/sqlpp11/using.h b/include/sqlpp11/using.h index c704dfc4..1c67cfa6 100644 --- a/include/sqlpp11/using.h +++ b/include/sqlpp11/using.h @@ -121,7 +121,7 @@ namespace sqlpp template struct _methods_t { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; @@ -165,7 +165,7 @@ namespace sqlpp template using _new_statement_t = new_statement; - static void _check_consistency() {} + using _consistency_check = consistent_t; template auto using_(Args... args) const diff --git a/include/sqlpp11/where.h b/include/sqlpp11/where.h index 01384545..667fa7f7 100644 --- a/include/sqlpp11/where.h +++ b/include/sqlpp11/where.h @@ -128,7 +128,7 @@ namespace sqlpp template struct _methods_t { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; @@ -176,11 +176,22 @@ namespace sqlpp template struct _methods_t { - static void _check_consistency() {} + using _consistency_check = consistent_t; }; }; + struct assert_where_t + { + using type = std::false_type; + + template + static void _() + { + static_assert(wrong_t::value, "where expression required, e.g. where(true)"); + }; + }; + // NO WHERE YET template struct no_where_t @@ -223,12 +234,10 @@ namespace sqlpp template using _new_statement_t = new_statement; - static void _check_consistency() - { - static constexpr bool _tables_provided = (Policies::_all_provided_tables::size::value > 0); - static constexpr bool _required = WhereRequired and _tables_provided; - static_assert(not _required, "where expression required, e.g. where(true)"); - } + using _consistency_check = typename std::conditional< + WhereRequired and (Policies::_all_provided_tables::size::value > 0), + assert_where_t, + consistent_t>::type; template auto where(Args... args) const diff --git a/tests/MockDb.h b/tests/MockDb.h index 85bf5630..6b929cfe 100644 --- a/tests/MockDb.h +++ b/tests/MockDb.h @@ -107,11 +107,25 @@ struct MockDbT: public sqlpp::connection // Directly executed statements start here template - auto operator() (const T& t) -> decltype(t._run(*this)) + auto _run(const T& t, const std::true_type&) -> decltype(t._run(*this)) { return t._run(*this); } + template + auto _run(const T& t, const std::false_type&) -> decltype(t._run(*this)) + { + return decltype(t._run(*this)){}; + } + + template + auto operator() (const T& t) -> decltype(t._run(*this)) + { + T::_run_check::_(); + using _ok = typename T::_run_check::type; + return _run(t, _ok{}); + } + void execute(const std::string& command); template