diff --git a/include/sqlpp11/insert.h b/include/sqlpp11/insert.h index 5aac9e34..f55b092f 100644 --- a/include/sqlpp11/insert.h +++ b/include/sqlpp11/insert.h @@ -130,7 +130,7 @@ namespace sqlpp void add_values(Args... args) { static_assert(is_column_list_t::value, "cannot call add_set() before columns()"); - return _insert_value_list.add_columns(args...); + return _insert_value_list.add_values(args...); } // run and prepare diff --git a/include/sqlpp11/remove.h b/include/sqlpp11/remove.h index d9213f7c..b74983b6 100644 --- a/include/sqlpp11/remove.h +++ b/include/sqlpp11/remove.h @@ -107,6 +107,7 @@ namespace sqlpp auto using_(Args... args) -> _policies_update_t> { + static_assert(is_noop_t::value, "cannot call using_()/dynamic_using() twice"); return { *this, vendor::using_t(args...) }; } @@ -114,6 +115,7 @@ namespace sqlpp auto dynamic_using(Args... args) -> _policies_update_t> { + 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...) }; } @@ -122,6 +124,7 @@ namespace sqlpp auto where(Args... args) -> _policies_update_t> { + static_assert(is_noop_t::value, "cannot call where()/dynamic_where() twice"); return { *this, vendor::where_t(args...) }; } @@ -129,6 +132,7 @@ namespace sqlpp auto dynamic_where(Args... args) -> _policies_update_t> { + 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...) }; } diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 27408cff..22bd0f24 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -55,74 +55,179 @@ namespace sqlpp namespace detail { template< - typename FlagList, typename ColumnList, - typename From, - typename Where, - typename GroupBy, - typename Having, - typename OrderBy, - typename Limit, - typename Offset + typename From > struct select_helper_t { - using _column_list_t = ColumnList; - using _from_t = ColumnList; - + static_assert(is_noop_t::value or sqlpp::is_select_column_list_t::value, "Yikes"); + static_assert(is_noop_t::value or sqlpp::is_from_t::value, "Yikes"); using _value_type = typename std::conditional< sqlpp::is_from_t::value, typename ColumnList::_value_type, no_value_t // If there is no from, the select is not complete (this logic is a bit simple, but better than nothing) >::type; - template - struct can_run_t - { - //static_assert(is_where_t::value, "cannot select remove without having a where condition, use .where(true) to remove all rows"); - //static_assert(not vendor::is_noop::value, "cannot run select without having selected anything"); - //static_assert(is_from_t::value, "cannot run select without a from()"); - //static_assert(is_where_t::value, "cannot run select without having a where condition, use .where(true) to select all rows"); - // FIXME: Check for missing aliases (if references are used) - // FIXME: Check for missing tables, well, actually, check for missing tables at the where(), order_by(), etc. - - static constexpr bool value = true; - }; }; } // SELECT - template - struct select_t: public vendor::policy_t..., public vendor::crtp_wrapper_t, Policies>..., - public detail::select_helper_t::_value_type::template operators> + template + struct select_t: public detail::select_helper_t::_value_type::template operators> { - template - using _policy_update_t = select_t...>; - using _database_t = Database; - using _parameter_tuple_t = std::tuple; + using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; + + template + struct _policies_update_impl + { + using type = select_t...>; + }; + + template + using _policies_update_t = typename _policies_update_impl::type; + + using _parameter_tuple_t = std::tuple; using _parameter_list_t = typename make_parameter_list_t::type; - using _column_list_t = typename detail::select_helper_t::_column_list_t; + using _column_list_t = ColumnList; using _result_row_t = typename _column_list_t::_result_row_t; using _dynamic_names_t = typename _column_list_t::_dynamic_names_t; using _is_select = std::true_type; using _requires_braces = std::true_type; - using _value_type = typename detail::select_helper_t::_value_type; + using _value_type = typename detail::select_helper_t::_value_type; using _name_t = typename _column_list_t::_name_t; + // Constructors select_t() {} - template - select_t(select_t r, Whatever whatever): - vendor::policy_t(r, whatever)... + template + select_t(X x, FlagList flag_list): + _flag_list(flag_list), + _column_list(x._column_list), + _from(x._from), + _where(x._where), + _group_by(x._group_by), + _having(x._having), + _order_by(x._order_by), + _limit(x._limit), + _offset(x._offset) {} - template - select_t(Remove r, Whatever whatever): - vendor::policy_t(r, whatever)... + template + select_t(X x, ColumnList column_list): + _flag_list(x._flag_list), + _column_list(column_list), + _from(x._from), + _where(x._where), + _group_by(x._group_by), + _having(x._having), + _order_by(x._order_by), + _limit(x._limit), + _offset(x._offset) + {} + + template + select_t(X x, From from): + _flag_list(x._flag_list), + _column_list(x._column_list), + _from(from), + _where(x._where), + _group_by(x._group_by), + _having(x._having), + _order_by(x._order_by), + _limit(x._limit), + _offset(x._offset) + {} + + template + select_t(X x, Where where): + _flag_list(x._flag_list), + _column_list(x._column_list), + _from(x._from), + _where(where), + _group_by(x._group_by), + _having(x._having), + _order_by(x._order_by), + _limit(x._limit), + _offset(x._offset) + {} + + template + select_t(X x, GroupBy group_by): + _flag_list(x._flag_list), + _column_list(x._column_list), + _from(x._from), + _where(x._where), + _group_by(group_by), + _having(x._having), + _order_by(x._order_by), + _limit(x._limit), + _offset(x._offset) + {} + + template + select_t(X x, Having having): + _flag_list(x._flag_list), + _column_list(x._column_list), + _from(x._from), + _where(x._where), + _group_by(x._group_by), + _having(having), + _order_by(x._order_by), + _limit(x._limit), + _offset(x._offset) + {} + + template + select_t(X x, OrderBy order_by): + _flag_list(x._flag_list), + _column_list(x._column_list), + _from(x._from), + _where(x._where), + _group_by(x._group_by), + _having(x._having), + _order_by(order_by), + _limit(x._limit), + _offset(x._offset) + {} + + template + select_t(X x, Limit limit): + _flag_list(x._flag_list), + _column_list(x._column_list), + _from(x._from), + _where(x._where), + _group_by(x._group_by), + _having(x._having), + _order_by(x._order_by), + _limit(limit), + _offset(x._offset) + {} + + template + select_t(X x, Offset offset): + _flag_list(x._flag_list), + _column_list(x._column_list), + _from(x._from), + _where(x._where), + _group_by(x._group_by), + _having(x._having), + _order_by(x._order_by), + _limit(x._limit), + _offset(offset) {} select_t(const select_t& r) = default; @@ -131,7 +236,230 @@ namespace sqlpp select_t& operator=(select_t&& r) = default; ~select_t() = default; - // Indicators + // type update functions + template + auto flags(Args... args) + -> _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...) }; + } + + template + auto dynamic_flags(Args... args) + -> _policies_update_t> + { + 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...) }; + } + + template + auto columns(Args... args) + -> _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...) }; + } + + template + auto dynamic_columns(Args... args) + -> _policies_update_t> + { + 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...) }; + } + + template + auto from(Args... args) + -> _policies_update_t> + { + return { *this, vendor::from_t(args...) }; + } + + template + auto dynamic_from(Args... args) + -> _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...) }; + } + + template + auto where(Args... args) + -> _policies_update_t> + { + static_assert(is_noop_t::value, "cannot call where()/dynamic_where() twice"); + return { *this, vendor::where_t(args...) }; + } + + template + auto dynamic_where(Args... args) + -> _policies_update_t> + { + 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...) }; + } + + template + auto group_by(Args... args) + -> _policies_update_t> + { + static_assert(is_noop_t::value, "cannot call group_by()/dynamic_group_by() twice"); + return { *this, vendor::group_by_t(args...) }; + } + + template + auto dynamic_group_by(Args... args) + -> _policies_update_t> + { + 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...) }; + } + + template + auto having(Args... args) + -> _policies_update_t> + { + static_assert(is_noop_t::value, "cannot call having()/dynamic_having() twice"); + return { *this, vendor::having_t(args...) }; + } + + template + auto dynamic_having(Args... args) + -> _policies_update_t> + { + 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...) }; + } + + template + auto order_by(Args... args) + -> _policies_update_t> + { + static_assert(is_noop_t::value, "cannot call order_by()/dynamic_order_by() twice"); + return { *this, vendor::order_by_t(args...) }; + } + + template + auto dynamic_order_by(Args... args) + -> _policies_update_t> + { + 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...) }; + } + + template + auto limit(Arg arg) + -> _policies_update_t::type>> + { + static_assert(is_noop_t::value, "cannot call limit()/dynamic_limit() twice"); + return { *this, vendor::limit_t::type>({arg}) }; + } + + auto dynamic_limit() + -> _policies_update_t> + { + 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>() }; + } + + template + auto offset(Arg arg) + -> _policies_update_t::type>> + { + static_assert(is_noop_t::value, "cannot call offset()/dynamic_offset() twice"); + return { *this, vendor::offset_t::type>({arg}) }; + } + + auto dynamic_offset() + -> _policies_update_t> + { + 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>() }; + } + + // value adding methods + template + void add_flag(Args... args) + { + static_assert(is_select_flag_list_t::value, "cannot call add_flag() before dynamic_flags()"); + static_assert(is_dynamic_t::value, "cannot call add_flag() before dynamic_flags()"); + return _flag_list.add_flag(*this, args...); + } + + template + void add_column(Args... args) + { + static_assert(is_select_column_list_t::value, "cannot call add_column() before dynamic_columns()"); + static_assert(is_dynamic_t::value, "cannot call add_column() before dynamic_columns()"); + return _column_list.add_column(*this, args...); + } + + template + void add_from(Args... args) + { + static_assert(is_from_t::value, "cannot call add_from() before dynamic_from()"); + static_assert(is_dynamic_t::value, "cannot call add_using() before dynamic_from()"); + return _from.add_from(*this, args...); + } + + template + void add_where(Args... args) + { + static_assert(is_where_t::value, "cannot call add_where() before dynamic_where()"); + static_assert(is_dynamic_t::value, "cannot call add_where() before dynamic_where()"); + return _where.add_where(*this, args...); + } + + template + void add_group_by(Args... args) + { + static_assert(is_group_by_t::value, "cannot call add_group_by() before dynamic_group_by()"); + static_assert(is_dynamic_t::value, "cannot call add_group_by() before dynamic_group_by()"); + return _group_by.add_group_by(*this, args...); + } + + template + void add_having(Args... args) + { + static_assert(is_having_t::value, "cannot call add_having() before dynamic_having()"); + static_assert(is_dynamic_t::value, "cannot call add_having() before dynamic_having()"); + return _having.add_having(*this, args...); + } + + template + void add_order_by(Args... args) + { + static_assert(is_order_by_t::value, "cannot call add_order_by() before dynamic_order_by()"); + static_assert(is_dynamic_t::value, "cannot call add_order_by() before dynamic_order_by()"); + return _order_by.add_order_by(*this, args...); + } + + template + void set_limit(Arg arg) + { + static_assert(is_limit_t::value, "cannot call add_limit() before dynamic_limit()"); + static_assert(is_dynamic_t::value, "cannot call add_limit() before dynamic_limit()"); + return _limit.set_limit(arg); + } + + template + void set_offset(Arg arg) + { + static_assert(is_offset_t::value, "cannot call add_offset() before dynamic_offset()"); + static_assert(is_dynamic_t::value, "cannot call add_offset() before dynamic_offset()"); + return _offset.set_offset(arg); + } + + // PseudoTable template struct _pseudo_table_t { @@ -166,12 +494,25 @@ namespace sqlpp return _result_row_t::static_size() + get_dynamic_names().size(); } + template + struct can_run_t + { + //static_assert(is_where_t::value, "cannot select remove without having a where condition, use .where(true) to remove all rows"); + //static_assert(not vendor::is_noop::value, "cannot run select without having selected anything"); + //static_assert(is_from_t::value, "cannot run select without a from()"); + //static_assert(is_where_t::value, "cannot run select without having a where condition, use .where(true) to select all rows"); + // FIXME: Check for missing aliases (if references are used) + // FIXME: Check for missing tables, well, actually, check for missing tables at the where(), order_by(), etc. + + static constexpr bool value = true; + }; + // Execute template auto _run(Db& db) const -> result_t { - static_assert(detail::select_helper_t::template can_run_t::value, "Cannot execute select statement"); + static_assert(can_run_t::value, "Cannot execute select statement"); static_assert(_get_static_no_of_parameters() == 0, "cannot run select directly with parameters, use prepare instead"); return {db.select(*this), get_dynamic_names()}; } @@ -181,10 +522,20 @@ namespace sqlpp auto _prepare(Db& db) const -> prepared_select_t { - static_assert(detail::select_helper_t::template can_run_t::value, "Cannot prepare select statement"); + static_assert(can_run_t::value, "Cannot prepare select statement"); return {{}, get_dynamic_names(), db.prepare_select(*this)}; } + + FlagList _flag_list; + ColumnList _column_list; + From _from; + Where _where; + GroupBy _group_by; + Having _having; + OrderBy _order_by; + Limit _limit; + Offset _offset; }; namespace vendor @@ -198,15 +549,15 @@ namespace sqlpp { context << "SELECT "; - interpret(t._flag_list(), context); - interpret(t._column_list(), context); - interpret(t._from(), context); - interpret(t._where(), context); - interpret(t._group_by(), context); - interpret(t._having(), context); - interpret(t._order_by(), context); - interpret(t._limit(), context); - interpret(t._offset(), context); + interpret(t._flag_list, context); + interpret(t._column_list, context); + interpret(t._from, context); + interpret(t._where, context); + interpret(t._group_by, context); + interpret(t._having, context); + interpret(t._order_by, context); + interpret(t._limit, context); + interpret(t._offset, context); return context; } @@ -233,32 +584,29 @@ namespace sqlpp decltype(std::tuple_cat(as_tuple::_(std::declval())...))>; } - - blank_select_t select() // FIXME: These should be constexpr + select_t select() // FIXME: These should be constexpr { - return { blank_select_t() }; + return { select_t() }; } template auto select(Columns... columns) - -> vendor::update_policies_t, - vendor::no_select_column_list_t, - detail::make_select_column_list_t> + -> select_t> { - return { blank_select_t(), detail::make_select_column_list_t(std::tuple_cat(detail::as_tuple::_(columns)...)) }; + return { select_t(), detail::make_select_column_list_t(std::tuple_cat(detail::as_tuple::_(columns)...)) }; } template - blank_select_t dynamic_select(const Database&) + select_t dynamic_select(const Database&) { - return { blank_select_t() }; + return { select_t() }; } template auto dynamic_select(const Database&, Columns... columns) - -> vendor::update_policies_t, vendor::no_select_column_list_t, detail::make_select_column_list_t> + -> select_t> { - return { blank_select_t(), detail::make_select_column_list_t(std::tuple_cat(detail::as_tuple::_(columns)...)) }; + return { select_t(), detail::make_select_column_list_t(std::tuple_cat(detail::as_tuple::_(columns)...)) }; } } diff --git a/include/sqlpp11/select_flags.h b/include/sqlpp11/select_flags.h index 3bcce768..f59a6ae4 100644 --- a/include/sqlpp11/select_flags.h +++ b/include/sqlpp11/select_flags.h @@ -27,7 +27,6 @@ #ifndef SQLPP_SELECT_FLAGS_H #define SQLPP_SELECT_FLAGS_H -#include #include #include #include diff --git a/include/sqlpp11/select_fwd.h b/include/sqlpp11/select_fwd.h deleted file mode 100644 index a9a5c9dd..00000000 --- a/include/sqlpp11/select_fwd.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2013, 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_SELECT_FWD_H -#define SQLPP_SELECT_FWD_H - -#include - -namespace sqlpp -{ - template - struct select_t; -} -#endif diff --git a/include/sqlpp11/update.h b/include/sqlpp11/update.h index d50f7a9a..215c5006 100644 --- a/include/sqlpp11/update.h +++ b/include/sqlpp11/update.h @@ -44,7 +44,7 @@ namespace sqlpp { template< typename Table, - typename Assignments, + typename UpdateList, typename Where > struct check_update_t @@ -53,27 +53,50 @@ namespace sqlpp }; } - template - struct update_t: public vendor::policy_t..., public vendor::crtp_wrapper_t, Policies>... + template + struct update_t { - template - using _policy_update_t = update_t...>; - using _database_t = Database; - using _parameter_tuple_t = std::tuple; + using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; + + template + struct _policies_update_impl + { + using type = update_t...>; + }; + + template + using _policies_update_t = typename _policies_update_impl::type; + + using _parameter_tuple_t = std::tuple; using _parameter_list_t = typename make_parameter_list_t::type; update_t() {} - template - update_t(update_t r, Whatever whatever): - vendor::policy_t(r, whatever)... + // Constructors + template + update_t(X x, Table table): + _table(table), + _update_list(x._update_list), + _where(x._where) {} - template - update_t(Remove r, Whatever whatever): - vendor::policy_t(r, whatever)... + template + update_t(X x, UpdateList update_list): + _table(x._table), + _update_list(update_list), + _where(x._where) + {} + + template + update_t(X x, Where where): + _table(x._table), + _update_list(x._update_list), + _where(where) {} update_t(const update_t&) = default; @@ -82,6 +105,59 @@ namespace sqlpp update_t& operator=(update_t&&) = default; ~update_t() = default; + // type update functions + template + auto set(Args... args) + -> _policies_update_t> + { + static_assert(is_noop_t::value, "cannot call set()/dynamic_set() twice"); + return { *this, vendor::update_list_t(args...) }; + } + + template + auto dynamic_set(Args... args) + -> _policies_update_t> + { + 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...) }; + } + + template + auto where(Args... args) + -> _policies_update_t> + { + static_assert(is_noop_t::value, "cannot call where()/dynamic_where() twice"); + return { *this, vendor::where_t(args...) }; + } + + template + auto dynamic_where(Args... args) + -> _policies_update_t> + { + 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...) }; + } + + // value adding methods + template + void add_set(Args... args) + { + static_assert(is_update_list_t::value, "cannot call add_set() before dynamic_set()"); + static_assert(is_dynamic_t::value, "cannot call add_set() before dynamic_set()"); + return _update_list.add_set(*this, args...); + } + + template + void add_where(Args... args) + { + static_assert(is_where_t::value, "cannot call add_where() before dynamic_where()"); + static_assert(is_dynamic_t::value, "cannot call add_where() before dynamic_where()"); + return _where.add_where(*this, args...); + } + + // run and prepare static constexpr size_t _get_static_no_of_parameters() { return _parameter_list_t::size::value; @@ -96,7 +172,6 @@ namespace sqlpp std::size_t _run(Db& db) const { static_assert(_get_static_no_of_parameters() == 0, "cannot run update directly with parameters, use prepare instead"); - static_assert(detail::check_update_t::value, "Cannot run this update expression"); return db.update(*this); } @@ -104,9 +179,12 @@ namespace sqlpp auto _prepare(Db& db) const -> prepared_update_t { - static_assert(detail::check_update_t::value, "Cannot run this update expression"); return {{}, db.prepare_update(*this)}; } + + Table _table; + UpdateList _update_list; + Where _where; }; namespace vendor @@ -119,29 +197,26 @@ namespace sqlpp static Context& _(const T& t, Context& context) { context << "UPDATE "; - interpret(t._single_table(), context); - interpret(t._update_list(), context); - interpret(t._where(), context); + interpret(t._table, context); + interpret(t._update_list, context); + interpret(t._where, context); return context; } }; } - template - using blank_update_t = update_t; - template constexpr auto update(Table table) - -> update_t, vendor::no_update_list_t, vendor::no_where_t> + -> update_t> { - return { blank_update_t(), vendor::single_table_t{table} }; + return { update_t(), vendor::single_table_t{table} }; } template constexpr auto dynamic_update(const Database&, Table table) - -> update_t, vendor::no_update_list_t, vendor::no_where_t> + -> update_t> { - return { blank_update_t(), vendor::single_table_t{table} }; + return { update_t(), vendor::single_table_t{table} }; } } diff --git a/include/sqlpp11/vendor/from.h b/include/sqlpp11/vendor/from.h index c01f24e7..4211098d 100644 --- a/include/sqlpp11/vendor/from.h +++ b/include/sqlpp11/vendor/from.h @@ -27,7 +27,6 @@ #ifndef SQLPP_FROM_H #define SQLPP_FROM_H -#include #include #include #include @@ -66,22 +65,21 @@ namespace sqlpp from_t& operator=(from_t&&) = default; ~from_t() = default; - template - void add_from(Table table) + template + void add_from(const Select&, Table table) { static_assert(_is_dynamic::value, "add_from can only be called for dynamic_from"); static_assert(is_table_t::value, "from arguments require to be tables or joins"); _dynamic_tables.emplace_back(table); } - const from_t& _from() const { return *this; } std::tuple _tables; vendor::interpretable_list_t _dynamic_tables; }; struct no_from_t { - const no_from_t& _from() const { return *this; } + using _is_noop = std::true_type; }; // CRTP Wrappers @@ -90,25 +88,6 @@ namespace sqlpp { }; - template - struct crtp_wrapper_t - { - template - auto from(Args... args) - -> vendor::update_policies_t> - { - return { static_cast(*this), from_t(args...) }; - } - - template - auto dynamic_from(Args... args) - -> vendor::update_policies_t, Args...>> - { - static_assert(not std::is_same, void>::value, "dynamic_from must not be called in a static statement"); - return { static_cast(*this), from_t, Args...>(args...) }; - } - }; - // Interpreters template struct interpreter_t> diff --git a/include/sqlpp11/vendor/group_by.h b/include/sqlpp11/vendor/group_by.h index d5e90eb8..1a0de458 100644 --- a/include/sqlpp11/vendor/group_by.h +++ b/include/sqlpp11/vendor/group_by.h @@ -64,8 +64,8 @@ namespace sqlpp group_by_t& operator=(group_by_t&&) = default; ~group_by_t() = default; - template - void add_group_by(Expression expression) + template + void add_group_by(const Statement&, Expression expression) { static_assert(is_table_t::value, "from arguments require to be tables or joins"); _dynamic_expressions.emplace_back(expression); @@ -78,35 +78,9 @@ namespace sqlpp struct no_group_by_t { - using _is_group_by = std::true_type; - const no_group_by_t& _group_by() const { return *this; } + using _is_noop = std::true_type; }; - // CRTP Wrappers - template - struct crtp_wrapper_t> - { - }; - - template - struct crtp_wrapper_t - { - template - auto group_by(Args... args) - -> vendor::update_policies_t> - { - return { static_cast(*this), group_by_t(args...) }; - } - - template - auto dynamic_group_by(Args... args) - -> vendor::update_policies_t, Args...>> - { - static_assert(not std::is_same, void>::value, "dynamic_group_by must not be called in a static statement"); - return { static_cast(*this), group_by_t, Args...>(args...) }; - } - }; - // Interpreters template struct interpreter_t> diff --git a/include/sqlpp11/vendor/having.h b/include/sqlpp11/vendor/having.h index 63698dad..e412e762 100644 --- a/include/sqlpp11/vendor/having.h +++ b/include/sqlpp11/vendor/having.h @@ -69,42 +69,15 @@ namespace sqlpp _dynamic_expressions.emplace_back(expr); } - const having_t& _having() const { return *this; } _parameter_tuple_t _expressions; vendor::interpretable_list_t _dynamic_expressions; }; struct no_having_t { - using _is_having = std::true_type; - const no_having_t& _having() const { return *this; } + using _is_noop = std::true_type; }; - // CRTP Wrappers - template - struct crtp_wrapper_t> - { - }; - - template - struct crtp_wrapper_t - { - template - auto having(Args... args) - -> vendor::update_policies_t> - { - return { static_cast(*this), having_t(args...) }; - } - - template - auto dynamic_having(Args... args) - -> vendor::update_policies_t, Args...>> - { - static_assert(not std::is_same, void>::value, "dynamic_having must not be called in a static statement"); - return { static_cast(*this), having_t, Args...>(args...) }; - } - }; - // Interpreters template struct interpreter_t> diff --git a/include/sqlpp11/vendor/limit.h b/include/sqlpp11/vendor/limit.h index fbdaee20..f73b36bf 100644 --- a/include/sqlpp11/vendor/limit.h +++ b/include/sqlpp11/vendor/limit.h @@ -52,7 +52,6 @@ namespace sqlpp limit_t& operator=(limit_t&&) = default; ~limit_t() = default; - const limit_t& _limit() const { return *this; } Limit _value; }; @@ -88,56 +87,15 @@ namespace sqlpp _initialized = true; } - const dynamic_limit_t& _limit() const { return *this; } - bool _initialized = false; interpretable_t _value; }; struct no_limit_t { - using _is_limit = std::true_type; - const no_limit_t& _limit() const { return *this; } + using _is_noop = std::true_type; }; - // CRTP Wrappers - template - struct crtp_wrapper_t> - { - }; - - template - struct crtp_wrapper_t> - { - }; - - template - struct crtp_wrapper_t - { - template - struct delayed_get_database_t - { - using type = get_database_t; - }; - - template - auto limit(Arg arg) - -> vendor::update_policies_t::type>> - { - typename wrap_operand::type value = {arg}; - return { static_cast(*this), limit_t::type>(value) }; - } - - template - auto dynamic_limit(Args... args) - -> vendor::update_policies_t::type>> - { - static_assert(sizeof...(Args) < 2, "dynamic_limit must be called with zero or one arguments"); - static_assert(not std::is_same, void>::value, "dynamic_limit must not be called in a static statement"); - return { static_cast(*this), dynamic_limit_t::type>(args...) }; - } - }; - // Interpreters template struct interpreter_t> diff --git a/include/sqlpp11/vendor/offset.h b/include/sqlpp11/vendor/offset.h index e5ca8d10..18a90c65 100644 --- a/include/sqlpp11/vendor/offset.h +++ b/include/sqlpp11/vendor/offset.h @@ -52,8 +52,6 @@ namespace sqlpp offset_t& operator=(offset_t&&) = default; ~offset_t() = default; - const offset_t& _offset() const { return *this; } - Offset _value; }; @@ -89,55 +87,15 @@ namespace sqlpp _initialized = true; } - const dynamic_offset_t& _offset() const { return *this; } bool _initialized = false; interpretable_t _value; }; struct no_offset_t { - using _is_offset = std::true_type; - const no_offset_t& _offset() const { return *this; } + using _is_noop = std::true_type; }; - // CRTP Wrappers - template - struct crtp_wrapper_t> - { - }; - - template - struct crtp_wrapper_t> - { - }; - - template - struct crtp_wrapper_t - { - template - struct delayed_get_database_t - { - using type = get_database_t; - }; - - template - auto offset(Arg arg) - -> vendor::update_policies_t::type>> - { - typename wrap_operand::type value = {arg}; - return { static_cast(*this), offset_t::type>(value) }; - } - - template - auto dynamic_offset(Args... args) - -> vendor::update_policies_t::type>> - { - static_assert(sizeof...(Args) < 2, "dynamic_offset must be called with zero or one arguments"); - static_assert(not std::is_same, void>::value, "dynamic_offset must not be called in a static statement"); - return { static_cast(*this), dynamic_offset_t::type>(args...) }; - } - }; - // Interpreters template struct interpreter_t> diff --git a/include/sqlpp11/vendor/order_by.h b/include/sqlpp11/vendor/order_by.h index 63ee7421..0233f03b 100644 --- a/include/sqlpp11/vendor/order_by.h +++ b/include/sqlpp11/vendor/order_by.h @@ -28,7 +28,6 @@ #define SQLPP_ORDER_BY_H #include -#include #include #include #include @@ -63,49 +62,22 @@ namespace sqlpp order_by_t& operator=(order_by_t&&) = default; ~order_by_t() = default; - template - void add_order_by(Expression expressions) + template + void add_order_by(const Statement&, Expression expressions) { static_assert(is_sort_order_t::value, "order_by arguments require to be sort-order expressions"); _dynamic_expressions.push_back(expressions); } - const order_by_t& _order_by() const { return *this; } _parameter_tuple_t _expressions; vendor::interpretable_list_t _dynamic_expressions; }; struct no_order_by_t { - using _is_order_by = std::true_type; - const no_order_by_t& _order_by() const { return *this; } + using _is_noop = std::true_type; }; - // CRTP Wrappers - template - struct crtp_wrapper_t> - { - }; - - template - struct crtp_wrapper_t - { - template - auto order_by(Args... args) - -> vendor::update_policies_t> - { - return { static_cast(*this), order_by_t(args...) }; - } - - template - auto dynamic_order_by(Args... args) - -> vendor::update_policies_t, Args...>> - { - static_assert(not std::is_same, void>::value, "dynamic_order_by must not be called in a static statement"); - return { static_cast(*this), order_by_t, Args...>(args...) }; - } - }; - // Interpreters template struct interpreter_t> diff --git a/include/sqlpp11/vendor/select_column_list.h b/include/sqlpp11/vendor/select_column_list.h index 30bf75c4..255644b5 100644 --- a/include/sqlpp11/vendor/select_column_list.h +++ b/include/sqlpp11/vendor/select_column_list.h @@ -29,7 +29,6 @@ #include #include -#include #include #include #include @@ -184,8 +183,8 @@ namespace sqlpp select_column_list_t& operator=(select_column_list_t&&) = default; ~select_column_list_t() = default; - template - void add_column(Expr namedExpr) + template + void add_column(const Select&, Expr namedExpr) { static_assert(is_named_expression_t::value, "select() arguments require to be named expressions"); static_assert(_is_dynamic::value, "cannot add columns to a non-dynamic column list"); @@ -199,7 +198,7 @@ namespace sqlpp struct no_select_column_list_t { - using _is_select_column_list = std::true_type; + using _is_noop = std::true_type; using _result_row_t = ::sqlpp::result_row_t<>; using _dynamic_names_t = typename dynamic_select_column_list::_names_t; using _value_type = no_value_t; @@ -210,35 +209,8 @@ namespace sqlpp { static_assert(wrong_t::value, "Cannot use a select as a table when no columns have been selected yet"); }; - - const no_select_column_list_t& _column_list() const { return *this; } }; - // CRTP Wrappers - template - struct crtp_wrapper_t> - { - }; - - template - struct crtp_wrapper_t - { - template - auto columns(Args... args) - -> vendor::update_policies_t> - { - return { static_cast(*this), select_column_list_t(args...) }; - } - - template - auto dynamic_columns(Args... args) - -> vendor::update_policies_t, Args...>> - { - static_assert(not std::is_same, void>::value, "dynamic_columns must not be called in a static statement"); - return { static_cast(*this), select_column_list_t, Args...>(args...) }; - } - }; - // Interpreters template struct interpreter_t> diff --git a/include/sqlpp11/vendor/select_flag_list.h b/include/sqlpp11/vendor/select_flag_list.h index dc6b4b8e..fe68a9f7 100644 --- a/include/sqlpp11/vendor/select_flag_list.h +++ b/include/sqlpp11/vendor/select_flag_list.h @@ -28,7 +28,6 @@ #define SQLPP_VENDOR_SELECT_FLAG_LIST_H #include -#include #include #include #include @@ -63,8 +62,8 @@ namespace sqlpp select_flag_list_t& operator=(select_flag_list_t&&) = default; ~select_flag_list_t() = default; - template - void add_flag(Flag flag) + template + void add_flag(const Select&, Flag flag) { static_assert(is_select_flag_t::value, "flag arguments require to be select flags"); _dynamic_flags.emplace_back(flag); @@ -77,34 +76,9 @@ namespace sqlpp struct no_select_flag_list_t { - using _is_select_flag_list = std::true_type; - const no_select_flag_list_t& _flag_list() const { return *this; } + using _is_noop = std::true_type; }; - // CRTP Wrappers - template - struct crtp_wrapper_t> - { - }; - - template - struct crtp_wrapper_t - { - template - auto flags(Args... args) - -> vendor::update_policies_t> - { - return { static_cast(*this), select_flag_list_t(args...) }; - } - - template - auto dynamic_flags(Args... args) - -> vendor::update_policies_t, Args...>> - { - static_assert(not std::is_same, void>::value, "dynamic_flags must not be called in a static statement"); - return { static_cast(*this), select_flag_list_t, Args...>(args...) }; - } - }; // Interpreters template diff --git a/include/sqlpp11/vendor/update_list.h b/include/sqlpp11/vendor/update_list.h index 8d620c27..3637f3c5 100644 --- a/include/sqlpp11/vendor/update_list.h +++ b/include/sqlpp11/vendor/update_list.h @@ -62,8 +62,8 @@ namespace sqlpp update_list_t& operator=(update_list_t&&) = default; ~update_list_t() = default; - template - void add_set(Assignment assignment) + template + void add_set(const Update&, Assignment assignment) { static_assert(is_assignment_t::value, "set() arguments require to be assigments"); static_assert(not must_not_update_t::value, "set() argument must not be updated"); @@ -77,35 +77,10 @@ namespace sqlpp struct no_update_list_t { - using _is_update_list = std::true_type; + using _is_noop = std::true_type; const no_update_list_t& _update_list() const { return *this; } }; - // CRTP Wrappers - template - struct crtp_wrapper_t> - { - }; - - template - struct crtp_wrapper_t - { - template - auto set(Args... args) - -> vendor::update_policies_t> - { - return { static_cast(*this), update_list_t(args...) }; - } - - template - auto dynamic_set(Args... args) - -> vendor::update_policies_t, Args...>> - { - static_assert(not std::is_same, void>::value, "dynamic_update_list must not be called in a static statement"); - return { static_cast(*this), update_list_t, Args...>(args...) }; - } - }; - // Interpreters template struct interpreter_t> diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b8b3879a..b2a56c15 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -6,13 +6,13 @@ macro (build_and_run arg) add_test(${arg} ${arg}) endmacro () -#build_and_run(InterpretTest) +build_and_run(InterpretTest) build_and_run(InsertTest) build_and_run(RemoveTest) -#build_and_run(UpdateTest) -#build_and_run(SelectTest) -#build_and_run(FunctionTest) -#build_and_run(PreparedTest) +build_and_run(UpdateTest) +build_and_run(SelectTest) +build_and_run(FunctionTest) +build_and_run(PreparedTest) find_package(PythonInterp REQUIRED) diff --git a/tests/SelectTest.cpp b/tests/SelectTest.cpp index 4f030c75..5c9c7b2b 100644 --- a/tests/SelectTest.cpp +++ b/tests/SelectTest.cpp @@ -23,6 +23,7 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include "Sample.h" #include "MockDb.h" #include "is_regular.h" @@ -31,7 +32,6 @@ #include #include -#include DbMock db = {}; DbMock::_context_t printer(std::cerr); @@ -175,6 +175,8 @@ int main() // Test a select of a single numeric table column { using T = decltype(select(t.alpha).from(t)); + static_assert(sqlpp::is_select_column_list_t::value, "Must not be noop"); + static_assert(sqlpp::is_from_t::value, "Must not be noop"); static_assert(sqlpp::is_numeric_t::value, "type requirement"); static_assert(sqlpp::is_expression_t::value, "type requirement"); static_assert(sqlpp::is_named_expression_t::value, "type requirement");