From 9110f6653a0295876902a0f2f112d6067bbdd52b Mon Sep 17 00:00:00 2001 From: rbock Date: Sat, 29 Nov 2014 14:02:24 +0100 Subject: [PATCH] Reduced error messages for several clauses --- include/sqlpp11/extra_tables.h | 44 +++++++++++++++++++--------- include/sqlpp11/from.h | 2 +- include/sqlpp11/into.h | 38 +++++++++++++++++------- include/sqlpp11/limit.h | 29 ++++++++++++++----- include/sqlpp11/offset.h | 27 ++++++++++++++--- include/sqlpp11/single_table.h | 28 ++++++++++++++---- include/sqlpp11/update.h | 8 ++--- include/sqlpp11/where.h | 53 ++++++++++++++++++++++++---------- 8 files changed, 169 insertions(+), 60 deletions(-) diff --git a/include/sqlpp11/extra_tables.h b/include/sqlpp11/extra_tables.h index 28d17f5b..18d74a9b 100644 --- a/include/sqlpp11/extra_tables.h +++ b/include/sqlpp11/extra_tables.h @@ -62,12 +62,6 @@ namespace sqlpp using _tags = detail::type_set<>; }; - // FIXME: extra_tables must not require tables! - - static_assert(sizeof...(Tables), "at least one table or join argument required in extra_tables()"); - static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected in extra_tables()"); - static_assert(detail::all_t::value...>::value, "at least one argument is not a table or join in extra_tables()"); - // Data using _data_t = extra_tables_data_t; @@ -130,17 +124,41 @@ namespace sqlpp return t.no_extra_tables; } - template - using _new_statement_t = new_statement; + template + using _new_statement_t = new_statement_t; + + template + using _check = detail::all_t::value...>; using _consistency_check = consistent_t; - template - auto extra_tables(Args...) const - -> _new_statement_t> + template + auto extra_tables(Tables... tables) const + -> _new_statement_t<_check, extra_tables_t> { -#warning: need to move static asserts - return { static_cast&>(*this), extra_tables_data_t{} }; + static_assert(_check::value, "at least one argument is not a table or join in extra_tables()"); + + return _extra_tables_impl(_check{}, tables...); + } + + private: + template + auto _extra_tables_impl(const std::false_type&, Tables... tables) const + -> bad_statement; + + template + auto _extra_tables_impl(const std::true_type&, Tables...) const + -> _new_statement_t> + { + static_assert(required_tables_of>::size::value == 0, "at least one table depends on another table in extra_tables()"); + + static constexpr std::size_t _number_of_tables = detail::sum(provided_tables_of::size::value...); + using _unique_tables = detail::make_joined_set_t...>; + using _unique_table_names = detail::transform_set_t; + static_assert(_number_of_tables == _unique_tables::size::value, "at least one duplicate table detected in extra_tables()"); + static_assert(_number_of_tables == _unique_table_names::size::value, "at least one duplicate table name detected in extra_tables()"); + + return { static_cast&>(*this), extra_tables_data_t{} }; } }; }; diff --git a/include/sqlpp11/from.h b/include/sqlpp11/from.h index a821c001..f5a11ded 100644 --- a/include/sqlpp11/from.h +++ b/include/sqlpp11/from.h @@ -189,7 +189,7 @@ namespace sqlpp auto _from_impl(const std::true_type&, Tables... tables) const -> _new_statement_t> { - static_assert(required_tables_of>::size::value == 0, "at least one table depends on another table"); + static_assert(required_tables_of>::size::value == 0, "at least one table depends on another table in from()"); static constexpr std::size_t _number_of_tables = detail::sum(provided_tables_of::size::value...); using _unique_tables = detail::make_joined_set_t...>; diff --git a/include/sqlpp11/into.h b/include/sqlpp11/into.h index d4a19928..57fe4710 100644 --- a/include/sqlpp11/into.h +++ b/include/sqlpp11/into.h @@ -61,9 +61,6 @@ namespace sqlpp using _traits = make_traits; using _recursive_traits = make_recursive_traits; - static_assert(is_table_t
::value, "argument has to be a table"); - static_assert(required_tables_of
::size::value == 0, "table depends on another table"); - using _data_t = into_data_t; struct _name_t {}; @@ -140,16 +137,35 @@ namespace sqlpp } using _database_t = typename Policies::_database_t; + template - using _new_statement_t = new_statement; + using _check = detail::all_t::value>; + + template + using _new_statement_t = new_statement_t; using _consistency_check = assert_into_t; - template - auto into(Args... args) const - -> _new_statement_t> + template + auto into(Table table) const + -> _new_statement_t<_check
, into_t> { - return { static_cast&>(*this), into_data_t{args...} }; + static_assert(_check
::value, "argument is not a table in into()"); + return _into_impl(_check
{}, table); + } + + private: + template + auto _into_impl(const std::false_type&, Table table) const + -> bad_statement; + + template + auto _into_impl(const std::true_type&, Table table) const + -> _new_statement_t> + { + static_assert(required_tables_of>::size::value == 0, "argument depends on another table in into()"); + + return { static_cast&>(*this), into_data_t{table} }; } }; }; @@ -169,10 +185,10 @@ namespace sqlpp } }; - template - auto into(T&&... t) -> decltype(statement_t().into(std::forward(t)...)) + template + auto into(T&& t) -> decltype(statement_t().into(std::forward(t))) { - return statement_t().into(std::forward(t)...); + return statement_t().into(std::forward(t)); } } diff --git a/include/sqlpp11/limit.h b/include/sqlpp11/limit.h index 33fa840f..050da15c 100644 --- a/include/sqlpp11/limit.h +++ b/include/sqlpp11/limit.h @@ -57,8 +57,6 @@ namespace sqlpp using _traits = make_traits; using _recursive_traits = make_recursive_traits; - static_assert(is_integral_t::value, "limit requires an integral value or integral parameter"); - // Data using _data_t = limit_data_t; @@ -134,6 +132,7 @@ namespace sqlpp { // FIXME: Make sure that Limit does not require external tables? Need to read up on SQL using arg_t = wrap_operand_t; + static_assert(is_integral_t::value, "limit requires an integral value or integral parameter"); _data._value = arg_t{value}; _data._initialized = true; } @@ -195,23 +194,39 @@ namespace sqlpp using _database_t = typename Policies::_database_t; template - using _new_statement_t = new_statement; + using _check = is_integral_t>; + + template + using _new_statement_t = new_statement_t; using _consistency_check = consistent_t; template auto limit(Arg arg) const - -> _new_statement_t>> + -> _new_statement_t<_check, limit_t>> { - return { static_cast&>(*this), limit_data_t>{{arg}} }; + static_assert(_check::value, "limit requires an integral value or integral parameter"); + return _limit_impl(_check{}, wrap_operand_t{arg}); } auto dynamic_limit() const - -> _new_statement_t> + -> _new_statement_t> { - static_assert(not std::is_same<_database_t, void>::value, "dynamic_limit must not be called in a static statement"); return { static_cast&>(*this), dynamic_limit_data_t<_database_t>{} }; } + + private: + template + auto _limit_impl(const std::false_type&, Arg arg) const + -> bad_statement; + + template + auto _limit_impl(const std::true_type&, Arg arg) const + -> _new_statement_t> + { + return { static_cast&>(*this), limit_data_t{arg} }; + } + }; }; diff --git a/include/sqlpp11/offset.h b/include/sqlpp11/offset.h index 44ddc69d..0b3253a2 100644 --- a/include/sqlpp11/offset.h +++ b/include/sqlpp11/offset.h @@ -134,6 +134,7 @@ namespace sqlpp { // FIXME: Make sure that Offset does not require external tables? Need to read up on SQL using arg_t = wrap_operand_t; + static_assert(is_integral_t::value, "offset requires an integral value or integral parameter"); _data._value = arg_t{value}; _data._initialized = true; } @@ -205,24 +206,42 @@ namespace sqlpp } using _database_t = typename Policies::_database_t; + template - using _new_statement_t = new_statement; + using _check = is_integral_t>; + + template + using _new_statement_t = new_statement_t; using _consistency_check = consistent_t; template auto offset(Arg arg) const - -> _new_statement_t>> + -> _new_statement_t<_check, offset_t>> { - return { static_cast&>(*this), offset_data_t>{{arg}} }; + static_assert(_check::value, "offset requires an integral value or integral parameter"); + return _offset_impl(_check{}, wrap_operand_t{arg}); } auto dynamic_offset() const - -> _new_statement_t> + -> _new_statement_t> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_offset must not be called in a static statement"); return { static_cast&>(*this), dynamic_offset_data_t<_database_t>{} }; } + + private: + template + auto _offset_impl(const std::false_type&, Arg arg) const + -> bad_statement; + + template + auto _offset_impl(const std::true_type&, Arg arg) const + -> _new_statement_t> + { + return { static_cast&>(*this), offset_data_t{arg} }; + } + }; }; diff --git a/include/sqlpp11/single_table.h b/include/sqlpp11/single_table.h index 824ed892..867f1ed3 100644 --- a/include/sqlpp11/single_table.h +++ b/include/sqlpp11/single_table.h @@ -129,15 +129,33 @@ namespace sqlpp using _database_t = typename Policies::_database_t; template - using _new_statement_t = new_statement; + using _check = detail::all_t::value>; + + template + using _new_statement_t = new_statement_t; using _consistency_check = consistent_t; - template - auto from(Args... args) const - -> _new_statement_t> + template + auto single_table(Table table) const + -> _new_statement_t<_check
, single_table_t> { - return { static_cast&>(*this), single_table_data_t{args...} }; + static_assert(_check
::value, "argument is not a table in single_table()"); + return _single_table_impl(_check
{}, table); + } + + private: + template + auto _single_table_impl(const std::false_type&, Table table) const + -> bad_statement; + + template + auto _single_table_impl(const std::true_type&, Table table) const + -> _new_statement_t> + { + static_assert(required_tables_of>::size::value == 0, "argument depends on another table in single_table()"); + + return { static_cast&>(*this), single_table_data_t{table} }; } }; }; diff --git a/include/sqlpp11/update.h b/include/sqlpp11/update.h index 09ee8a5d..7e1058f6 100644 --- a/include/sqlpp11/update.h +++ b/include/sqlpp11/update.h @@ -112,17 +112,17 @@ namespace sqlpp template constexpr auto update(Table table) - -> decltype(blank_update_t().from(table)) + -> decltype(blank_update_t().single_table(table)) { - return { blank_update_t().from(table) }; + return { blank_update_t().single_table(table) }; } template constexpr auto dynamic_update(const Database&, Table table) - -> decltype(blank_update_t().from(table)) + -> decltype(blank_update_t().single_table(table)) { static_assert(std::is_base_of::value, "Invalid database parameter"); - return { blank_update_t().from(table) }; + return { blank_update_t().single_table(table) }; } } diff --git a/include/sqlpp11/where.h b/include/sqlpp11/where.h index a0afdfdb..6b4f8490 100644 --- a/include/sqlpp11/where.h +++ b/include/sqlpp11/where.h @@ -75,10 +75,6 @@ namespace sqlpp using _is_dynamic = is_database; - static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in where()"); - static_assert(detail::none_t::value...>::value, "at least one argument is an assignment in where()"); - static_assert(detail::all_t::value...>::value, "at least one argument is not valid expression in where()"); - // Data using _data_t = where_data_t; @@ -231,28 +227,55 @@ namespace sqlpp } using _database_t = typename Policies::_database_t; - template - using _new_statement_t = new_statement; + + template + using _check = detail::all_t::value...>; + + template + using _new_statement_t = new_statement_t; 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 - -> _new_statement_t> + auto where(bool b) const + -> _new_statement_t> { - return { static_cast&>(*this), where_data_t{args...} }; + return { static_cast&>(*this), where_data_t{b} }; } - template - auto dynamic_where(Args... args) const - -> _new_statement_t> + template + auto where(Expressions... expressions) const + -> _new_statement_t<_check, where_t> { - static_assert(not std::is_same<_database_t, void>::value, "dynamic_where must not be called in a static statement"); - return { static_cast&>(*this), where_data_t<_database_t, Args...>{args...} }; + static_assert(_check::value, "at least one argument is not an expression in where()"); + static_assert(sizeof...(Expressions), "at least one expression argument required in where()"); + + return _where_impl(_check{}, expressions...); } + + template + auto dynamic_where(Expressions... expressions) const + -> _new_statement_t<_check, where_t<_database_t, Expressions...>> + { + static_assert(_check::value, "at least one argument is not an expression in where()"); + static_assert(not std::is_same<_database_t, void>::value, "dynamic_where must not be called in a static statement"); + return _where_impl<_database_t>(_check{}, expressions...); + } + + private: + template + auto _where_impl(const std::false_type&, Expressions... expressions) const + -> bad_statement; + + template + auto _where_impl(const std::true_type&, Expressions... expressions) const + -> _new_statement_t> + { + return { static_cast&>(*this), where_data_t<_database_t, Expressions...>{expressions...} }; + } + }; };