From 9c4832df0fac7e632a6ed01203a1a0c9bc50c0c4 Mon Sep 17 00:00:00 2001 From: rbock Date: Fri, 7 Feb 2014 21:25:23 +0100 Subject: [PATCH 01/74] Switched remove to policy based design. A lot of sweating to figure out how to do it, but now it looks MUCH cleaner and it is probably a lot easier to extend :-) --- include/sqlpp11/remove.h | 154 ++++++++----------------- include/sqlpp11/vendor/crtp_wrapper.h | 57 +++++++++ include/sqlpp11/vendor/from.h | 85 +++++++++++--- include/sqlpp11/vendor/interpreter.h | 4 +- include/sqlpp11/vendor/policy.h | 62 ++++++++++ include/sqlpp11/vendor/policy_update.h | 59 ++++++++++ include/sqlpp11/vendor/using.h | 85 +++++++++++--- include/sqlpp11/vendor/where.h | 75 ++++++++++-- tests/CMakeLists.txt | 12 +- tests/InterpretTest.cpp | 6 +- 10 files changed, 447 insertions(+), 152 deletions(-) create mode 100644 include/sqlpp11/vendor/crtp_wrapper.h create mode 100644 include/sqlpp11/vendor/policy.h create mode 100644 include/sqlpp11/vendor/policy_update.h diff --git a/include/sqlpp11/remove.h b/include/sqlpp11/remove.h index 270ef9d9..68c2397d 100644 --- a/include/sqlpp11/remove.h +++ b/include/sqlpp11/remove.h @@ -31,107 +31,53 @@ #include #include #include +#include #include #include +#include +#include +#include namespace sqlpp { - template< - typename Database, - typename Table, - typename Using = vendor::noop, - typename Where = vendor::noop - > - struct remove_t; + namespace detail + { + template + struct check_remove_t + { + static_assert(is_where_t::value, "cannot run remove without having a where condition, use .where(true) to remove all rows"); + static constexpr bool value = true; + }; + } - template< - typename Database, - typename Table, - typename Using, - typename Where - > - struct remove_t + template + struct remove_t: public vendor::policy_t..., public vendor::crtp_wrapper_t, Policies>... { - static_assert(vendor::is_noop::value or is_table_t
::value, "invalid 'Table' argument"); - static_assert(vendor::is_noop::value or is_using_t::value, "invalid 'Using' argument"); - static_assert(vendor::is_noop::value or is_where_t::value, "invalid 'Where' argument"); + template + using _policy_update_t = remove_t...>; - template - using set_using_t = remove_t; - template - using set_where_t = remove_t; - - using _parameter_tuple_t = std::tuple; + using _database_t = Database; + using _parameter_tuple_t = std::tuple; using _parameter_list_t = typename make_parameter_list_t::type; - template - auto using_(Tab... tab) - -> set_using_t> - { - static_assert(vendor::is_noop::value, "cannot call using() twice"); - static_assert(vendor::is_noop::value, "cannot call using() after where()"); - return { - _table, - {std::tuple{tab...}}, - _where - }; - } + remove_t() + {} - template - auto dynamic_using_(Tab... tab) - -> set_using_t> - { - static_assert(vendor::is_noop::value, "cannot call using() twice"); - static_assert(vendor::is_noop::value, "cannot call using() after where()"); - return { - _table, - {std::tuple{tab...}}, - _where - }; - } + template + remove_t(remove_t r, Whatever whatever): + vendor::policy_t(r, whatever)... + {} - template - remove_t& add_using_(Tab table) - { - static_assert(is_dynamic_t::value, "cannot call add_using() in a non-dynamic using"); - _using.add(table); + template + remove_t(Remove r, Whatever whatever): + vendor::policy_t(r, whatever)... + {} - return *this; - } - - template - auto where(Expr... expr) - -> set_where_t> - { - static_assert(vendor::is_noop::value, "cannot call where() twice"); - return { - _table, - _using, - {std::tuple{expr...}}, - }; - } - - template - auto dynamic_where(Expr... expr) - -> set_where_t> - { - static_assert(vendor::is_noop::value, "cannot call where() twice"); - return { - _table, - _using, - {std::tuple{expr...}}, - }; - } - - template - remove_t& add_where(Expr expr) - { - static_assert(is_dynamic_t::value, "cannot call add_where() in a non-dynamic where"); - - _where.add(expr); - - return *this; - } + remove_t(const remove_t& r) = default; + remove_t(remove_t&& r) = default; + remove_t& operator=(const remove_t& r) = default; + remove_t& operator=(remove_t&& r) = default; + ~remove_t() = default; static constexpr size_t _get_static_no_of_parameters() { @@ -147,33 +93,30 @@ namespace sqlpp std::size_t _run(Db& db) const { static_assert(_get_static_no_of_parameters() == 0, "cannot run remove directly with parameters, use prepare instead"); - static_assert(is_where_t::value, "cannot run update without having a where condition, use .where(true) to remove all rows"); + static_assert(detail::check_remove_t::value, "Cannot run this expression"); return db.remove(*this); } template auto _prepare(Db& db) const - -> prepared_remove_t + -> prepared_remove_t { + static_assert(detail::check_remove_t::value, "Cannot run this expression"); return {{}, db.prepare_remove(*this)}; } - - Table _table; - Using _using; - Where _where; }; namespace vendor { - template - struct interpreter_t> + template + struct interpreter_t> { - using T = remove_t; + using T = remove_t; static Context& _(const T& t, Context& context) { - context << "DELETE FROM "; - interpret(t._table, context); + context << "DELETE"; + interpret(t._from, context); interpret(t._using, context); interpret(t._where, context); return context; @@ -181,16 +124,19 @@ namespace sqlpp }; } + template + using blank_remove_t = remove_t; + template - constexpr remove_t remove_from(Table table) + constexpr remove_t, vendor::no_using_t, vendor::no_where_t> remove_from(Table table) { - return {table}; + return { blank_remove_t(), vendor::from_t{table} }; } - template - constexpr remove_t dynamic_remove_from(const Db&, Table table) + template + constexpr remove_t, vendor::no_using_t, vendor::no_where_t> dynamic_remove_from(const Database&, Table table) { - return {table}; + return { blank_remove_t(), vendor::from_t{table} }; } } diff --git a/include/sqlpp11/vendor/crtp_wrapper.h b/include/sqlpp11/vendor/crtp_wrapper.h new file mode 100644 index 00000000..47ef265a --- /dev/null +++ b/include/sqlpp11/vendor/crtp_wrapper.h @@ -0,0 +1,57 @@ +/* + * 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_VENDOR_CRTP_WRAPPER_H +#define SQLPP_VENDOR_CRTP_WRAPPER_H + +#include + +namespace sqlpp +{ + namespace vendor + { + template + struct get_database_impl; + + template class Statement, typename Database, typename... Policies> + struct get_database_impl> + { + using type = Database; + }; + + template + using get_database_t = typename get_database_impl::type; + + template + struct crtp_wrapper_t + { + static_assert(wrong_t::value, "missing crtp policy specialization"); + }; + } + +} + +#endif diff --git a/include/sqlpp11/vendor/from.h b/include/sqlpp11/vendor/from.h index 11e8c999..0de1e217 100644 --- a/include/sqlpp11/vendor/from.h +++ b/include/sqlpp11/vendor/from.h @@ -32,56 +32,113 @@ #include #include #include +#include +#include namespace sqlpp { namespace vendor { - template + // FROM + template struct from_t { using _is_from = std::true_type; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - // ensure one argument at least - static_assert(_is_dynamic::value or sizeof...(TableOrJoin), "at least one table or join argument required in from()"); + static_assert(_is_dynamic::value or sizeof...(Tables), "at least one table or join argument required in from()"); - // check for duplicate arguments - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in from()"); + static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in from()"); - // check for invalid arguments - static_assert(::sqlpp::detail::and_t::value, "at least one argument is not a table or join in from()"); + static_assert(::sqlpp::detail::and_t::value, "at least one argument is not a table or join in from()"); // FIXME: Joins contain two tables. This is not being dealt with at the moment when looking at duplicates, for instance + from_t(Tables... tables): + _tables(tables...) + {} + + from_t(const from_t&) = default; + from_t(from_t&&) = default; + from_t& operator=(const from_t&) = default; + from_t& operator=(from_t&&) = default; + ~from_t() = default; + template - void add(Table table) + void add_from(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); } - std::tuple _tables; + from_t& _from = *this; + std::tuple _tables; vendor::interpretable_list_t _dynamic_tables; }; - template - struct interpreter_t> + struct no_from_t + { + using _is_from = std::true_type; + no_from_t& _from = *this; + }; + + + // CRTP Wrappers + template + struct crtp_wrapper_t> { - using T = from_t; + }; + + 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> + { + using T = from_t; static Context& _(const T& t, Context& context) { - if (sizeof...(TableOrJoin) == 0 and t._dynamic_tables.empty()) + if (sizeof...(Tables) == 0 and t._dynamic_tables.empty()) return context; context << " FROM "; interpret_tuple(t._tables, ',', context); - if (sizeof...(TableOrJoin) and not t._dynamic_tables.empty()) + if (sizeof...(Tables) and not t._dynamic_tables.empty()) context << ','; interpret_list(t._dynamic_tables, ',', context); return context; } }; + + template + struct interpreter_t + { + using T = no_from_t; + + static Context& _(const T& t, Context& context) + { + return context; + } + }; } } diff --git a/include/sqlpp11/vendor/interpreter.h b/include/sqlpp11/vendor/interpreter.h index 547d7ebd..43b4b625 100644 --- a/include/sqlpp11/vendor/interpreter.h +++ b/include/sqlpp11/vendor/interpreter.h @@ -24,8 +24,8 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SQLPP_VENDOR_INTERPRET_H -#define SQLPP_VENDOR_INTERPRET_H +#ifndef SQLPP_VENDOR_INTERPRETER_H +#define SQLPP_VENDOR_INTERPRETER_H #include diff --git a/include/sqlpp11/vendor/policy.h b/include/sqlpp11/vendor/policy.h new file mode 100644 index 00000000..45edeeac --- /dev/null +++ b/include/sqlpp11/vendor/policy.h @@ -0,0 +1,62 @@ +/* + * 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_VENDOR_POLICY_H +#define SQLPP_VENDOR_POLICY_H + +#include + +namespace sqlpp +{ + namespace vendor + { + template + struct policy_t: public PolicyImpl + { + policy_t() + {} + + template + policy_t(const Whatever&, policy_t policy): + PolicyImpl(policy) + {} + + template + policy_t(const Whatever&, PolicyImpl impl): + PolicyImpl(impl) + {} + + template + policy_t(Derived derived, const Whatever&): + PolicyImpl(derived) + {} + }; + + } + +} + +#endif diff --git a/include/sqlpp11/vendor/policy_update.h b/include/sqlpp11/vendor/policy_update.h new file mode 100644 index 00000000..62f8fbcc --- /dev/null +++ b/include/sqlpp11/vendor/policy_update.h @@ -0,0 +1,59 @@ +/* + * 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_VENDOR_POLICY_UPDATE_H +#define SQLPP_VENDOR_POLICY_UPDATE_H + +#include + +namespace sqlpp +{ + namespace vendor + { + template + struct policy_update_impl + { + template + using _policy_t = typename std::conditional::value, Replacement, T>::type; + }; + + template + using policy_update_t = typename policy_update_impl::template _policy_t; + + template + struct update_policies_impl + { + using type = typename Original::template _policy_update_t; + }; + + template + using update_policies_t = typename update_policies_impl::type; + + } + +} + +#endif diff --git a/include/sqlpp11/vendor/using.h b/include/sqlpp11/vendor/using.h index 7f98b821..0cd2222f 100644 --- a/include/sqlpp11/vendor/using.h +++ b/include/sqlpp11/vendor/using.h @@ -31,55 +31,110 @@ #include #include #include +#include +#include namespace sqlpp { namespace vendor { - template + // USING + template struct using_t { using _is_using = std::true_type; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; + using _parameter_tuple_t = std::tuple; - static_assert(_is_dynamic::value or sizeof...(Table), "at least one table argument required in using()"); + static_assert(_is_dynamic::value or sizeof...(Tables), "at least one table argument required in using()"); - // check for duplicate arguments - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in using()"); + static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in using()"); - // check for invalid arguments - static_assert(::sqlpp::detail::and_t::value, "at least one argument is not an table in using()"); + static_assert(::sqlpp::detail::and_t::value, "at least one argument is not an table in using()"); + + using_t(Tables... tables): + _tables(tables...) + {} + + using_t(const using_t&) = default; + using_t(using_t&&) = default; + using_t& operator=(const using_t&) = default; + using_t& operator=(using_t&&) = default; + ~using_t() = default; - template - void add(T table) + template + void add_using(Table table) { - static_assert(is_table_t::value, "using() arguments require to be tables"); + static_assert(_is_dynamic::value, "add_using can only be called for dynamic_using"); + static_assert(is_table_t
::value, "using() arguments require to be tables"); _dynamic_tables.emplace_back(table); } + using_t& _using = *this; _parameter_tuple_t _tables; vendor::interpretable_list_t _dynamic_tables; }; - template - struct interpreter_t> + struct no_using_t + { + no_using_t& _using = *this; + }; + + // CRTP Wrapper + template + struct crtp_wrapper_t> { - using T = using_t; + }; + + template + struct crtp_wrapper_t + { + template + auto using_(Args... args) + -> vendor::update_policies_t> + { + return { static_cast(*this), using_t(args...) }; + } + + template + auto dynamic_using(Args... args) + -> vendor::update_policies_t, Args...>> + { + static_assert(not std::is_same, void>::value, "dynamic_using must not be called in a static statement"); + return { static_cast(*this), using_t, Args...>(args...) }; + } + }; + + // Interpreters + template + struct interpreter_t> + { + using T = using_t; static Context& _(const T& t, Context& context) { - if (sizeof...(Table) == 0 and t._dynamic_tables.empty()) + if (sizeof...(Tables) == 0 and t._dynamic_tables.empty()) return context; context << " USING "; interpret_tuple(t._tables, ',', context); - if (sizeof...(Table) and not t._dynamic_tables.empty()) + if (sizeof...(Tables) and not t._dynamic_tables.empty()) context << ','; interpret_list(t._dynamic_tables, ',', context); return context; } }; + + template + struct interpreter_t + { + using T = no_using_t; + + static Context& _(const T& t, Context& context) + { + return context; + } + }; } } diff --git a/include/sqlpp11/vendor/where.h b/include/sqlpp11/vendor/where.h index 72de65fa..bba16b33 100644 --- a/include/sqlpp11/vendor/where.h +++ b/include/sqlpp11/vendor/where.h @@ -40,41 +40,85 @@ namespace sqlpp { namespace vendor { - template + // WHERE + template struct where_t { using _is_where = std::true_type; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; + using _parameter_tuple_t = std::tuple; - static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression argument required in where()"); - static_assert(sqlpp::detail::and_t::value, "at least one argument is not an expression in where()"); + static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in where()"); + static_assert(sqlpp::detail::and_t::value, "at least one argument is not an expression in where()"); using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type; + where_t(Expressions... expressions): + _expressions(expressions...) + {} + + where_t(const where_t&) = default; + where_t(where_t&&) = default; + where_t& operator=(const where_t&) = default; + where_t& operator=(where_t&&) = default; + ~where_t() = default; + template - void add(E expr) + void add_where(E expr) { + 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()"); _dynamic_expressions.emplace_back(expr); } + where_t& _where = *this; _parameter_tuple_t _expressions; vendor::interpretable_list_t _dynamic_expressions; }; - template - struct interpreter_t> + struct no_where_t + { + no_where_t& _where = *this; + }; + + // CRTP Wrappers + template + struct crtp_wrapper_t> { - using T = where_t; + }; + + template + struct crtp_wrapper_t + { + template + auto where(Args... args) + -> vendor::update_policies_t> + { + return { static_cast(*this), where_t(args...) }; + } + + template + auto dynamic_where(Args... args) + -> vendor::update_policies_t, Args...>> + { + static_assert(not std::is_same, void>::value, "dynamic_where must not be called in a static statement"); + return { static_cast(*this), where_t, Args...>(args...) }; + } + }; + + // Interpreters + template + struct interpreter_t> + { + using T = where_t; static Context& _(const T& t, Context& context) { - if (sizeof...(Expr) == 0 and t._dynamic_expressions.empty()) + if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty()) return context; context << " WHERE "; interpret_tuple(t._expressions, " AND ", context); - if (sizeof...(Expr) and not t._dynamic_expressions.empty()) + if (sizeof...(Expressions) and not t._dynamic_expressions.empty()) context << " AND "; interpret_list(t._dynamic_expressions, " AND ", context); return context; @@ -104,6 +148,17 @@ namespace sqlpp } }; + template + struct interpreter_t + { + using T = no_where_t; + + static Context& _(const T& t, Context& context) + { + return context; + } + }; + } } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b2a56c15..ef9f5c96 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -7,12 +7,12 @@ macro (build_and_run arg) endmacro () 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(InsertTest) +#build_and_run(RemoveTest) +#build_and_run(UpdateTest) +#build_and_run(SelectTest) +#build_and_run(FunctionTest) +#build_and_run(PreparedTest) find_package(PythonInterp REQUIRED) diff --git a/tests/InterpretTest.cpp b/tests/InterpretTest.cpp index 8f523298..58efc51a 100644 --- a/tests/InterpretTest.cpp +++ b/tests/InterpretTest.cpp @@ -43,6 +43,7 @@ int main() test::TabFoo f; test::TabBar t; + /* interpret(insert_into(t).columns(t.gamma, t.beta), printer).flush(); interpret(insert_into(t).columns(t.gamma, t.beta).add_values(t.gamma = true, t.beta = "cheesecake"), printer).flush(); interpret(insert_into(t).columns(t.gamma, t.beta) @@ -90,10 +91,13 @@ int main() interpret(update(t), printer).flush(); interpret(update(t).set(t.gamma = true), printer).flush(); interpret(update(t).set(t.gamma = true).where(t.beta.in("kaesekuchen", "cheesecake")), printer).flush(); + */ interpret(remove_from(t), printer).flush(); + interpret(remove_from(t).using_(t), printer).flush(); interpret(remove_from(t).where(t.alpha == sqlpp::tvin(0)), printer).flush(); interpret(remove_from(t).using_(t).where(t.alpha == sqlpp::tvin(0)), printer).flush(); + /* // functions sqlpp::interpret(sqlpp::value(7), printer).flush(); // FIXME: Why is the namespace specifier required? @@ -136,6 +140,6 @@ int main() interpret(select(all_of(t)).from(t).where(true), printer).flush(); interpret(select(all_of(t)).from(t).where(false), printer).flush(); - +*/ return 0; } From 62b828ef8f675a1c9f3df73f2e772290d7870837 Mon Sep 17 00:00:00 2001 From: rbock Date: Fri, 7 Feb 2014 22:52:02 +0100 Subject: [PATCH 02/74] Migrated select components to support policy based select --- include/sqlpp11/select.h | 161 ++++++++------------ include/sqlpp11/select_fwd.h | 22 +-- include/sqlpp11/vendor/from.h | 4 +- include/sqlpp11/vendor/group_by.h | 90 ++++++++--- include/sqlpp11/vendor/having.h | 72 +++++++-- include/sqlpp11/vendor/limit.h | 114 +++++++++++--- include/sqlpp11/vendor/offset.h | 101 ++++++++++-- include/sqlpp11/vendor/order_by.h | 89 ++++++++--- include/sqlpp11/vendor/select_column_list.h | 101 ++++++++---- include/sqlpp11/vendor/select_flag_list.h | 92 ++++++++--- include/sqlpp11/vendor/where.h | 30 ++-- 11 files changed, 604 insertions(+), 272 deletions(-) diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index cd68ec59..fb22fe58 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -28,7 +28,6 @@ #define SQLPP_SELECT_H #include -#include #include #include @@ -45,74 +44,69 @@ #include #include #include +#include +#include +#include + #include #include -#include - namespace sqlpp { - template< - typename Database, - typename FlagList, - typename ColumnList, - typename From, - typename Where, - typename GroupBy, - typename Having, - typename OrderBy, - typename Limit, - typename Offset - > - struct select_t - : public ColumnList::_value_type::template operators> - { - using _Database = Database; - using _From = From; + namespace detail + { + template< + typename FlagList, + typename ColumnList, + typename From, + typename Where, + typename GroupBy, + typename Having, + typename OrderBy, + typename Limit, + typename Offset + > + struct check_select_t + { + //static_assert(is_where_t::value, "cannot select remove without having a where condition, use .where(true) to remove all rows"); + static constexpr bool value = true; + }; + } - static_assert(is_select_flag_list_t::value, "invalid list of select flags"); - static_assert(is_select_column_list_t::value, "invalid list of select expressions"); - static_assert(vendor::is_noop::value or is_from_t::value, "invalid 'from' argument"); - static_assert(vendor::is_noop::value or is_where_t::value, "invalid 'where' argument"); - static_assert(vendor::is_noop::value or is_group_by_t::value, "invalid 'group by' arguments"); - static_assert(vendor::is_noop::value or is_having_t::value, "invalid 'having' arguments"); - static_assert(vendor::is_noop::value or is_order_by_t::value, "invalid 'order by' arguments"); - static_assert(vendor::is_noop::value or is_limit_t::value, "invalid 'limit' arguments"); - static_assert(vendor::is_noop::value or is_offset_t::value, "invalid 'offset' arguments"); + template + struct select_t: public vendor::policy_t..., public vendor::crtp_wrapper_t, Policies>... + { + template + using _policy_update_t = select_t...>; + + using _database_t = Database; + using _parameter_tuple_t = std::tuple; + using _parameter_list_t = typename make_parameter_list_t::type; + + select_t() + {} + + template + select_t(select_t r, Whatever whatever): + vendor::policy_t(r, whatever)... + {} + + template + select_t(Remove r, Whatever whatever): + vendor::policy_t(r, whatever)... + {} + + select_t(const select_t& r) = default; + select_t(select_t&& r) = default; + select_t& operator=(const select_t& r) = default; + select_t& operator=(select_t&& r) = default; + ~select_t() = default; using _is_select = std::true_type; using _requires_braces = std::true_type; - template - using set_flag_list_t = select_t; - template - using set_column_list_t = select_t; - template - using set_from_t = select_t; - template - using set_where_t = select_t; - template - using set_group_by_t = select_t; - template - using set_having_t = select_t; - template - using set_order_by_t = select_t; - template - using set_limit_t = select_t; - template - using set_offset_t = select_t; - + /* using _result_row_t = typename ColumnList::_result_row_t; using _dynamic_names_t = typename ColumnList::_dynamic_names_t; using _parameter_tuple_t = std::tuple; @@ -640,58 +634,21 @@ namespace sqlpp return {{}, get_dynamic_names(), db.prepare_select(*this)}; } - - FlagList _flags; - ColumnList _columns; - From _from; - Where _where; - GroupBy _group_by; - Having _having; - OrderBy _order_by; - Limit _limit; - Offset _offset; +*/ }; namespace vendor { - template - struct interpreter_t> + template + struct interpreter_t> { - using T = select_t; + using T = select_t; static Context& _(const T& t, Context& context) { context << "SELECT "; + /* interpret(t._flags, context); interpret(t._columns, context); interpret(t._from, context); @@ -701,6 +658,7 @@ namespace sqlpp interpret(t._order_by, context); interpret(t._limit, context); interpret(t._offset, context); + */ return context; } @@ -708,6 +666,8 @@ namespace sqlpp } + /* + // construct select flag list namespace detail { @@ -751,6 +711,7 @@ namespace sqlpp {}, {}, {}, {}, {}, {}, {} }; } + */ } #endif diff --git a/include/sqlpp11/select_fwd.h b/include/sqlpp11/select_fwd.h index dc432e57..a9a5c9dd 100644 --- a/include/sqlpp11/select_fwd.h +++ b/include/sqlpp11/select_fwd.h @@ -31,27 +31,7 @@ namespace sqlpp { - namespace vendor - { - struct noop; - } - // select flags - struct all_t; - struct distinct_t; - struct straight_join_t; - - template< - typename Db, - typename Flags = vendor::noop, - typename ExpressionList = vendor::noop, - typename From = vendor::noop, - typename Where = vendor::noop, - typename GroupBy = vendor::noop, - typename Having = vendor::noop, - typename OrderBy = vendor::noop, - typename Limit = vendor::noop, - typename Offset = vendor::noop - > + template struct select_t; } #endif diff --git a/include/sqlpp11/vendor/from.h b/include/sqlpp11/vendor/from.h index 0de1e217..f0a816cd 100644 --- a/include/sqlpp11/vendor/from.h +++ b/include/sqlpp11/vendor/from.h @@ -83,7 +83,6 @@ namespace sqlpp no_from_t& _from = *this; }; - // CRTP Wrappers template struct crtp_wrapper_t> @@ -109,7 +108,6 @@ namespace sqlpp } }; - // Interpreters template struct interpreter_t> @@ -139,8 +137,8 @@ namespace sqlpp return context; } }; - } + } } #endif diff --git a/include/sqlpp11/vendor/group_by.h b/include/sqlpp11/vendor/group_by.h index ca8e2e5e..bdb7b169 100644 --- a/include/sqlpp11/vendor/group_by.h +++ b/include/sqlpp11/vendor/group_by.h @@ -32,57 +32,111 @@ #include #include #include +#include +#include #include namespace sqlpp { namespace vendor { - template + // GROUP BY + template struct group_by_t { using _is_group_by = std::true_type; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; + using _parameter_tuple_t = std::tuple; - // ensure one argument at least - static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression (e.g. a column) required in group_by()"); + static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression (e.g. a column) required in group_by()"); - // check for duplicate expressions - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in group_by()"); + static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in group_by()"); - // check for invalid expressions - static_assert(::sqlpp::detail::and_t::value, "at least one argument is not an expression in group_by()"); + static_assert(::sqlpp::detail::and_t::value, "at least one argument is not an expression in group_by()"); - template - void add(E expr) + group_by_t(Expressions... expressions): + _expressions(expressions...) + {} + + group_by_t(const group_by_t&) = default; + group_by_t(group_by_t&&) = default; + group_by_t& operator=(const group_by_t&) = default; + group_by_t& operator=(group_by_t&&) = default; + ~group_by_t() = default; + + template + void add_group_by(Expression expression) { - static_assert(is_table_t::value, "from arguments require to be tables or joins"); - _dynamic_expressions.emplace_back(expr); + static_assert(is_table_t::value, "from arguments require to be tables or joins"); + _dynamic_expressions.emplace_back(expression); } + group_by_t& _group_by = *this; _parameter_tuple_t _expressions; vendor::interpretable_list_t _dynamic_expressions; - }; - template - struct interpreter_t> + struct no_group_by_t + { + using _is_group_by = std::true_type; + no_group_by_t& _group_by = *this; + }; + + // CRTP Wrappers + template + struct crtp_wrapper_t> { - using T = group_by_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> + { + using T = group_by_t; static Context& _(const T& t, Context& context) { - if (sizeof...(Expr) == 0 and t._dynamic_expressions.empty()) + if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty()) return context; context << " GROUP BY "; interpret_tuple(t._expressions, ',', context); - if (sizeof...(Expr) and not t._dynamic_expressions.empty()) + if (sizeof...(Expressions) and not t._dynamic_expressions.empty()) context << ','; interpret_list(t._dynamic_expressions, ',', context); return context; } }; + + template + struct interpreter_t + { + using T = no_group_by_t; + + static Context& _(const T& t, Context& context) + { + return context; + } + }; + } } diff --git a/include/sqlpp11/vendor/having.h b/include/sqlpp11/vendor/having.h index e9a474df..116e1e2a 100644 --- a/include/sqlpp11/vendor/having.h +++ b/include/sqlpp11/vendor/having.h @@ -31,52 +31,100 @@ #include #include #include +#include +#include #include namespace sqlpp { namespace vendor { - template + // HAVING + template struct having_t { using _is_having = std::true_type; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; + using _parameter_tuple_t = std::tuple; - static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression argument required in having()"); - static_assert(::sqlpp::detail::and_t::value, "at least one argument is not an expression in having()"); + static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in having()"); + static_assert(::sqlpp::detail::and_t::value, "at least one argument is not an expression in having()"); using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type; - template - void add(E expr) + template + void add(Expression expr) { - static_assert(is_expression_t::value, "invalid expression argument in add_having()"); + static_assert(is_expression_t::value, "invalid expression argument in add_having()"); _dynamic_expressions.emplace_back(expr); } + having_t& _having = *this; _parameter_tuple_t _expressions; vendor::interpretable_list_t _dynamic_expressions; }; - template - struct interpreter_t> + struct no_having_t + { + using _is_having = std::true_type; + no_having_t& _having = *this; + }; + + // CRTP Wrappers + template + struct crtp_wrapper_t> { - using T = having_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> + { + using T = having_t; static Context& _(const T& t, Context& context) { - if (sizeof...(Expr) == 0 and t._dynamic_expressions.empty()) + if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty()) return context; context << " HAVING "; interpret_tuple(t._expressions, " AND ", context); - if (sizeof...(Expr) and not t._dynamic_expressions.empty()) + if (sizeof...(Expressions) and not t._dynamic_expressions.empty()) context << " AND "; interpret_list(t._dynamic_expressions, " AND ", context); return context; } }; + + template + struct interpreter_t + { + using T = no_having_t; + + static Context& _(const T& t, Context& context) + { + return context; + } + }; + } } diff --git a/include/sqlpp11/vendor/limit.h b/include/sqlpp11/vendor/limit.h index fdee2700..d3b175a5 100644 --- a/include/sqlpp11/vendor/limit.h +++ b/include/sqlpp11/vendor/limit.h @@ -27,21 +27,106 @@ #ifndef SQLPP_LIMIT_H #define SQLPP_LIMIT_H -#include -#include #include +#include +#include namespace sqlpp { namespace vendor { + // LIMIT template struct limit_t { using _is_limit = std::true_type; static_assert(is_integral_t::value, "limit requires an integral value or integral parameter"); - Limit _limit; + limit_t(size_t value): + _value(value) + {} + + limit_t(const limit_t&) = default; + limit_t(limit_t&&) = default; + limit_t& operator=(const limit_t&) = default; + limit_t& operator=(limit_t&&) = default; + ~limit_t() = default; + + limit_t& _limit = *this; + Limit _value; + }; + + struct dynamic_limit_t + { + using _is_limit = std::true_type; + using _is_dynamic = std::true_type; + + dynamic_limit_t(size_t value): + _value(value) + {} + + dynamic_limit_t(const dynamic_limit_t&) = default; + dynamic_limit_t(dynamic_limit_t&&) = default; + dynamic_limit_t& operator=(const dynamic_limit_t&) = default; + dynamic_limit_t& operator=(dynamic_limit_t&&) = default; + ~dynamic_limit_t() = default; + + void set_limit(std::size_t limit) + { + _value = limit; + } + + dynamic_limit_t& _limit = *this; + std::size_t _value; // FIXME: This should be a serializable! + }; + + struct no_limit_t + { + using _is_limit = std::true_type; + no_limit_t& _limit = *this; + }; + + // CRTP Wrappers + template + struct crtp_wrapper_t> + { + }; + + template + struct crtp_wrapper_t + { + }; + + template + struct crtp_wrapper_t + { + template + auto limit(Arg arg) + -> vendor::update_policies_t> + { + return { static_cast(*this), limit_t(arg) }; + } + + auto dynamic_limit(size_t arg) + -> vendor::update_policies_t + { + 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(arg) }; + } + }; + + // Interpreters + template + struct interpreter_t + { + using T = dynamic_limit_t; + + static Context& _(const T& t, Context& context) + { + if (t._value > 0) + context << " LIMIT " << t._limit; + return context; + } }; template @@ -52,38 +137,23 @@ namespace sqlpp static Context& _(const T& t, Context& context) { context << " LIMIT "; - interpret(t._limit, context); + interpret(t._value, context); return context; } }; - struct dynamic_limit_t - { - using _is_limit = std::true_type; - using _is_dynamic = std::true_type; - - void set(std::size_t limit) - { - _limit = limit; - } - - std::size_t _limit; - }; - template - struct interpreter_t + struct interpreter_t { - using T = dynamic_limit_t; + using T = no_limit_t; static Context& _(const T& t, Context& context) { - if (t._limit > 0) - context << " LIMIT " << t._limit; return context; } }; - } + } } #endif diff --git a/include/sqlpp11/vendor/offset.h b/include/sqlpp11/vendor/offset.h index a7af759a..7f4df82b 100644 --- a/include/sqlpp11/vendor/offset.h +++ b/include/sqlpp11/vendor/offset.h @@ -28,20 +28,94 @@ #define SQLPP_OFFSET_H #include +#include +#include namespace sqlpp { namespace vendor { + // OFFSET template struct offset_t { using _is_offset = std::true_type; static_assert(is_integral_t::value, "offset requires an integral value or integral parameter"); - Offset _offset; + offset_t(size_t value): + _value(value) + {} + + offset_t(const offset_t&) = default; + offset_t(offset_t&&) = default; + offset_t& operator=(const offset_t&) = default; + offset_t& operator=(offset_t&&) = default; + ~offset_t() = default; + + offset_t& _offset = *this; + Offset _value; }; + struct dynamic_offset_t + { + using _is_offset = std::true_type; + using _is_dynamic = std::true_type; + + dynamic_offset_t(size_t value): + _value(value) + {} + + dynamic_offset_t(const dynamic_offset_t&) = default; + dynamic_offset_t(dynamic_offset_t&&) = default; + dynamic_offset_t& operator=(const dynamic_offset_t&) = default; + dynamic_offset_t& operator=(dynamic_offset_t&&) = default; + ~dynamic_offset_t() = default; + + void set_offset(std::size_t offset) + { + _value = offset; + } + + dynamic_offset_t& _offset = *this; + std::size_t _value; // FIXME: This should be a serializable! + }; + + struct no_offset_t + { + using _is_offset = std::true_type; + no_offset_t& _offset = *this; + }; + + // CRTP Wrappers + template + struct crtp_wrapper_t> + { + }; + + template + struct crtp_wrapper_t + { + }; + + template + struct crtp_wrapper_t + { + template + auto offset(Arg arg) + -> vendor::update_policies_t> + { + return { static_cast(*this), offset_t(arg) }; + } + + auto dynamic_offset(size_t arg) + -> vendor::update_policies_t + { + 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(arg) }; + } + }; + + // Interpreters template struct interpreter_t> { @@ -55,19 +129,6 @@ namespace sqlpp } }; - struct dynamic_offset_t - { - using _is_offset = std::true_type; - using _is_dynamic = std::true_type; - - void set(std::size_t offset) - { - _offset = offset; - } - - std::size_t _offset; - }; - template struct interpreter_t { @@ -75,12 +136,22 @@ namespace sqlpp static Context& _(const T& t, Context& context) { - if (t._offset > 0) + if (t._value > 0) context << " OFFSET " << t._offset; return context; } }; + template + struct interpreter_t + { + using T = no_offset_t; + + static Context& _(const T& t, Context& context) + { + return context; + } + }; } } diff --git a/include/sqlpp11/vendor/order_by.h b/include/sqlpp11/vendor/order_by.h index fd58485f..9c6f32ed 100644 --- a/include/sqlpp11/vendor/order_by.h +++ b/include/sqlpp11/vendor/order_by.h @@ -32,55 +32,110 @@ #include #include #include +#include +#include +#include namespace sqlpp { namespace vendor { - template + template struct order_by_t { using _is_order_by = std::true_type; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; + using _parameter_tuple_t = std::tuple; - // check for at least one order expression - static_assert(_is_dynamic::value or sizeof...(Expr), "at least one sort-order expression required in order_by()"); + static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one sort-order expression required in order_by()"); - // check for duplicate order expressions - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in order_by()"); + static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in order_by()"); - // check for invalid order expressions - static_assert(::sqlpp::detail::and_t::value, "at least one argument is not a sort order expression in order_by()"); + static_assert(::sqlpp::detail::and_t::value, "at least one argument is not a sort order expression in order_by()"); - template - void add(E expr) + order_by_t(Expressions... expressions): + _expressions(expressions...) + {} + + order_by_t(const order_by_t&) = default; + order_by_t(order_by_t&&) = default; + order_by_t& operator=(const order_by_t&) = default; + order_by_t& operator=(order_by_t&&) = default; + ~order_by_t() = default; + + template + void add_order_by(Expression expressions) { - static_assert(is_sort_order_t::value, "order_by arguments require to be sort-order expressions"); - _dynamic_expressions.push_back(expr); + static_assert(is_sort_order_t::value, "order_by arguments require to be sort-order expressions"); + _dynamic_expressions.push_back(expressions); } + order_by_t& _order_by = *this; _parameter_tuple_t _expressions; vendor::interpretable_list_t _dynamic_expressions; }; - template - struct interpreter_t> + struct no_order_by_t + { + using _is_order_by = std::true_type; + no_order_by_t& _order_by = *this; + }; + + // CRTP Wrappers + template + struct crtp_wrapper_t> { - using T = order_by_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> + { + using T = order_by_t; static Context& _(const T& t, Context& context) { - if (sizeof...(Expr) == 0 and t._dynamic_expressions.empty()) + if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty()) return context; context << " ORDER BY "; interpret_tuple(t._expressions, ',', context); - if (sizeof...(Expr) and not t._dynamic_expressions.empty()) + if (sizeof...(Expressions) and not t._dynamic_expressions.empty()) context << ','; interpret_list(t._dynamic_expressions, ',', context); return context; } }; + + template + struct interpreter_t + { + using T = no_order_by_t; + + static Context& _(const T& t, Context& context) + { + return context; + } + }; + } } diff --git a/include/sqlpp11/vendor/select_column_list.h b/include/sqlpp11/vendor/select_column_list.h index ce421e8f..7872ac62 100644 --- a/include/sqlpp11/vendor/select_column_list.h +++ b/include/sqlpp11/vendor/select_column_list.h @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include namespace sqlpp @@ -130,69 +132,103 @@ namespace sqlpp }; - template + // SELECT COLUMNS + template struct select_column_list_t - { - static_assert(::sqlpp::vendor::wrong_t::value, "invalid template argument for select_column_list"); - }; - - template - struct select_column_list_t> { using _is_select_column_list = std::true_type; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; + using _parameter_tuple_t = std::tuple; using size = std::tuple_size<_parameter_tuple_t>; - // check for duplicate select expressions - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected"); + static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected"); - // check for invalid select expressions template using is_valid_expression_t = std::integral_constant::value or is_multi_column_t::value>; - static_assert(::sqlpp::detail::and_t::value, "at least one argument is not a named expression"); + static_assert(::sqlpp::detail::and_t::value, "at least one argument is not a named expression"); - // check for duplicate select expression names - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate name detected"); + static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate name detected"); - // provide type information for sub-selects that are used as expressions struct _column_type {}; - struct _value_type: ::sqlpp::detail::get_first_argument_if_unique::_value_type + struct _value_type: ::sqlpp::detail::get_first_argument_if_unique::_value_type { - using _is_expression = typename std::conditional::type; - using _is_named_expression = typename std::conditional::type; + using _is_expression = typename std::conditional::type; + using _is_named_expression = typename std::conditional::type; using _is_alias = std::false_type; }; - using _name_t = typename ::sqlpp::detail::get_first_argument_if_unique::_name_t; + using _name_t = typename ::sqlpp::detail::get_first_argument_if_unique::_name_t; using _result_row_t = typename std::conditional<_is_dynamic::value, - dynamic_result_row_t...>, - result_row_t...>>::type; + dynamic_result_row_t...>, + result_row_t...>>::type; using _dynamic_names_t = typename dynamic_select_column_list::_names_t; template - using _pseudo_table_t = select_pseudo_table_t; + using _pseudo_table_t = select_pseudo_table_t; template - using _dynamic_t = select_column_list_t>; + using _dynamic_t = select_column_list_t>; + + select_column_list_t(Columns... columns): + _columns(columns...) + {} + + select_column_list_t(const select_column_list_t&) = default; + select_column_list_t(select_column_list_t&&) = default; + select_column_list_t& operator=(const select_column_list_t&) = default; + select_column_list_t& operator=(select_column_list_t&&) = default; + ~select_column_list_t() = default; template - void add(Expr namedExpr) + void add_column(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"); _dynamic_columns.push_back(namedExpr); } + select_column_list_t& _column_list = *this; _parameter_tuple_t _columns; dynamic_select_column_list _dynamic_columns; }; - template - struct interpreter_t> + struct no_select_column_list_t + { + using _is_select_column_list = std::true_type; + no_select_column_list_t& _column_list = *this; + }; + + // CRTP Wrappers + template + struct crtp_wrapper_t> { - using T = select_column_list_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> + { + using T = select_column_list_t; static Context& _(const T& t, Context& context) { @@ -206,6 +242,17 @@ namespace sqlpp return context; } }; + + template + struct interpreter_t + { + using T = no_select_column_list_t; + + static Context& _(const T& t, Context& context) + { + return context; + } + }; } } diff --git a/include/sqlpp11/vendor/select_flag_list.h b/include/sqlpp11/vendor/select_flag_list.h index a167e4fc..48860aa7 100644 --- a/include/sqlpp11/vendor/select_flag_list.h +++ b/include/sqlpp11/vendor/select_flag_list.h @@ -27,58 +27,95 @@ #ifndef SQLPP_VENDOR_SELECT_FLAG_LIST_H #define SQLPP_VENDOR_SELECT_FLAG_LIST_H +#include #include #include #include #include #include -#include +#include +#include namespace sqlpp { namespace vendor { - template + // SELECT FLAGS + template struct select_flag_list_t - { - static_assert(::sqlpp::vendor::wrong_t::value, "invalid argument for select_flag_list"); - }; - - // select_flag_list_t - template - struct select_flag_list_t> { using _is_select_flag_list = std::true_type; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; + using _parameter_tuple_t = std::tuple; using size = std::tuple_size<_parameter_tuple_t>; - // check for duplicate order expressions - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in select flag list"); + static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in select flag list"); - // check for invalid order expressions - static_assert(::sqlpp::detail::and_t::value, "at least one argument is not a select flag in select flag list"); + static_assert(::sqlpp::detail::and_t::value, "at least one argument is not a select flag in select flag list"); - template - void add(E expr) + select_flag_list_t(Flags... flags): + _flags(flags...) + {} + + select_flag_list_t(const select_flag_list_t&) = default; + select_flag_list_t(select_flag_list_t&&) = default; + select_flag_list_t& operator=(const select_flag_list_t&) = default; + select_flag_list_t& operator=(select_flag_list_t&&) = default; + ~select_flag_list_t() = default; + + template + void add_flag(Flag flag) { - static_assert(is_select_flag_t::value, "flag arguments require to be select flags"); - _dynamic_flags.emplace_back(expr); + static_assert(is_select_flag_t::value, "flag arguments require to be select flags"); + _dynamic_flags.emplace_back(flag); } + select_flag_list_t& _flag_list = *this; _parameter_tuple_t _flags; vendor::interpretable_list_t _dynamic_flags; }; - template - struct interpreter_t>> + struct no_select_flag_list_t + { + using _is_select_flag_list = std::true_type; + no_select_flag_list_t& _flag_list = *this; + }; + + // CRTP Wrappers + template + struct crtp_wrapper_t> { - using T = select_flag_list_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 + struct interpreter_t> + { + using T = select_flag_list_t; static Context& _(const T& t, Context& context) { interpret_tuple(t._flags, ' ', context); - if (sizeof...(Flag)) + if (sizeof...(Flags)) context << ' '; interpret_list(t._dynamic_flags, ',', context); if (not t._dynamic_flags.empty()) @@ -86,6 +123,17 @@ namespace sqlpp return context; } }; + + template + struct interpreter_t + { + using T = no_select_flag_list_t; + + static Context& _(const T& t, Context& context) + { + return context; + } + }; } } diff --git a/include/sqlpp11/vendor/where.h b/include/sqlpp11/vendor/where.h index bba16b33..b1805212 100644 --- a/include/sqlpp11/vendor/where.h +++ b/include/sqlpp11/vendor/where.h @@ -27,14 +27,14 @@ #ifndef SQLPP_WHERE_H #define SQLPP_WHERE_H -#include -#include -#include #include -#include +#include +#include #include #include -#include +#include +#include +#include namespace sqlpp { @@ -76,8 +76,18 @@ namespace sqlpp vendor::interpretable_list_t _dynamic_expressions; }; + template<> + struct where_t + { + using _is_where = std::true_type; + using _is_dynamic = std::false_type; + + std::tuple _condition; + }; + struct no_where_t { + using _is_where = std::true_type; no_where_t& _where = *this; }; @@ -125,16 +135,6 @@ namespace sqlpp } }; - template<> - struct where_t - { - using _is_where = std::true_type; - using _is_dynamic = std::false_type; - using _parameter_tuple_t = std::tuple<>; - - std::tuple _condition; - }; - template struct interpreter_t> { From 0a744455ecc6bd672274fe0b4d676cfa4df47788 Mon Sep 17 00:00:00 2001 From: rbock Date: Fri, 7 Feb 2014 23:43:26 +0100 Subject: [PATCH 03/74] basic select methods work again I've let go of the select(flags, columns) monster methods, these are now separated --- include/sqlpp11/select.h | 518 ++------------------------------ include/sqlpp11/vendor/having.h | 10 + include/sqlpp11/vendor/limit.h | 66 ++-- include/sqlpp11/vendor/offset.h | 66 ++-- tests/InterpretTest.cpp | 19 +- 5 files changed, 122 insertions(+), 557 deletions(-) diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index fb22fe58..af251d69 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -120,459 +120,6 @@ namespace sqlpp using _name_t = typename ColumnList::_name_t; - // The standard constructors, assigment operators and destructor - constexpr select_t(FlagList flag_list, ColumnList column_list, From from, - Where where, GroupBy group_by, Having having, - OrderBy order_by, Limit limit, Offset offset): - _flags(flag_list), - _columns(column_list), - _from(from), - _where(where), - _group_by(group_by), - _having(having), - _order_by(order_by), - _limit(limit), - _offset(offset) - { - } - - select_t(const select_t& rhs) = default; - select_t(select_t&& rhs) = default; - select_t& operator=(const select_t& rhs) = default; - select_t& operator=(select_t&& rhs) = default; - ~select_t() = default; - - // select functions - template - auto flags(Flag... flag) - -> set_flag_list_t>> - { - static_assert(not FlagList::size::value, "cannot call dynamic_flags() after specifying them the first time"); - static_assert(not ColumnList::size::value, "cannot call columns() after specifying them the first time"); - return { - {std::tuple{flag...}}, - _columns, - _from, - _where, - _group_by, - _having, - _order_by, - _limit, - _offset - }; - } - - template - auto dynamic_flags(Flag... flag) - -> set_flag_list_t>> - { - static_assert(not std::is_same::value, "cannot call dynamic_flags() in a non-dynamic select"); - static_assert(not FlagList::size::value, "cannot call dynamic_flags() after specifying them the first time"); - static_assert(not ColumnList::size::value, "cannot call columns() after specifying them the first time"); - return { - {std::tuple{flag...}}, - _columns, - _from, - _where, - _group_by, - _having, - _order_by, - _limit, - _offset - }; - } - - template - select_t& add_flag(Flag flag) - { - static_assert(is_dynamic_t::value, "cannot call add_flag() in a non-dynamic column list"); - - _flags.add(flag); - - return *this; - } - - template - auto columns(Column... column) - -> set_column_list_t>> - { - static_assert(not ColumnList::size::value, "cannot call columns() after specifying them the first time"); - return { - _flags, - {std::tuple{column...}}, - _from, - _where, - _group_by, - _having, - _order_by, - _limit, - _offset - }; - } - - template - auto dynamic_columns(Column... column) - -> set_column_list_t>> - { - static_assert(not std::is_same::value, "cannot call dynamic_columns() in a non-dynamic select"); - static_assert(not ColumnList::size::value, "cannot call dynamic_columns() after specifying them the first time"); - return { - _flags, - {std::tuple{column...}}, - _from, - _where, - _group_by, - _having, - _order_by, - _limit, - _offset - }; - } - - template - select_t& add_column(NamedExpr namedExpr) - { - static_assert(is_dynamic_t::value, "cannot call add_column() in a non-dynamic column list"); - - _columns.add(namedExpr); - - return *this; - } - - template - auto from(Table... table) - -> set_from_t> - { - static_assert(not vendor::is_noop::value, "cannot call from() without having selected anything"); - static_assert(vendor::is_noop::value, "cannot call from() twice for a single select"); - return { - _flags, - _columns, - {std::tuple{table...}}, - _where, - _group_by, - _having, - _order_by, - _limit, - _offset - }; - } - - template - auto dynamic_from(Table... table) - -> set_from_t> - { - static_assert(not std::is_same::value, "cannot call dynamic_from() in a non-dynamic select"); - static_assert(not vendor::is_noop::value, "cannot call from() without having selected anything"); - static_assert(vendor::is_noop::value, "cannot call from() twice for a single select"); - return { - _flags, - _columns, - {std::tuple{table...}}, - _where, - _group_by, - _having, - _order_by, - _limit, - _offset - }; - } - - template - select_t& add_from(Table table) - { - static_assert(not vendor::is_noop::value, "cannot call add_from() without having selected anything"); - static_assert(is_dynamic_t::value, "cannot call add_from() in a non-dynamic from"); - - _from.add(table); - - return *this; - } - - template - auto where(Expr... expr) - -> set_where_t> - { - static_assert(not vendor::is_noop::value, "cannot call where() without a from()"); - static_assert(vendor::is_noop::value, "cannot call where() or dynamic_where() twice for a single select"); - return { - _flags, - _columns, - _from, - {std::tuple{expr...}}, - _group_by, - _having, - _order_by, - _limit, - _offset, - }; - } - - template - auto dynamic_where(Expr... expr) - -> set_where_t> - { - static_assert(not vendor::is_noop::value, "cannot call dynamic_where() without a from()"); - static_assert(vendor::is_noop::value, "cannot call where() or dynamic_where() twice for a single select"); - return { - _flags, - _columns, - _from, - {std::tuple{expr...}}, - _group_by, - _having, - _order_by, - _limit, - _offset, - }; - } - - template - select_t& add_where(Expr expr) - { - static_assert(is_dynamic_t::value, "cannot call add_where() with a non-dynamic where"); - - _where.add(expr); - - return *this; - } - - template - auto group_by(Col... column) - -> set_group_by_t> - { - static_assert(not vendor::is_noop::value, "cannot call group_by() without a from()"); - static_assert(vendor::is_noop::value, "cannot call group_by() twice for a single select"); - return { - _flags, - _columns, - _from, - _where, - {std::tuple{column...}}, - _having, - _order_by, - _limit, - _offset, - }; - } - - template - auto dynamic_group_by(Col... column) - -> set_group_by_t> - { - static_assert(not vendor::is_noop::value, "cannot call group_by() without a from()"); - static_assert(vendor::is_noop::value, "cannot call group_by() twice for a single select"); - return { - _flags, - _columns, - _from, - _where, - {std::tuple{column...}}, - _having, - _order_by, - _limit, - _offset, - }; - } - - template - select_t& add_group_by(Expr expr) - { - static_assert(is_dynamic_t::value, "cannot call add_group_by() in a non-dynamic group_by"); - - _group_by.add(expr); - - return *this; - } - - template - auto having(Expr... expr) - -> set_having_t> - { - static_assert(not vendor::is_noop::value, "cannot call having() without a group_by"); - static_assert(vendor::is_noop::value, "cannot call having() twice for a single select"); - return { - _flags, - _columns, - _from, - _where, - _group_by, - {std::tuple{expr...}}, - _order_by, - _limit, - _offset, - }; - } - - template - auto dynamic_having(Expr... expr) - -> set_having_t> - { - static_assert(not vendor::is_noop::value, "cannot call having() without a group_by"); - static_assert(vendor::is_noop::value, "cannot call having() twice for a single select"); - return { - _flags, - _columns, - _from, - _where, - _group_by, - {std::tuple{expr...}}, - _order_by, - _limit, - _offset, - }; - } - - template - select_t& add_having(Expr expr) - { - static_assert(is_dynamic_t::value, "cannot call add_having() in a non-dynamic having"); - - _having.add(expr); - - return *this; - } - - template - auto order_by(OrderExpr... expr) - -> set_order_by_t> - { - static_assert(not vendor::is_noop::value, "cannot call order_by() without a from()"); - static_assert(vendor::is_noop::value, "cannot call order_by() twice for a single select"); - return { - _flags, - _columns, - _from, - _where, - _group_by, - _having, - {std::tuple{expr...}}, - _limit, - _offset, - }; - } - - template - auto dynamic_order_by(OrderExpr... expr) - -> set_order_by_t> - { - static_assert(not vendor::is_noop::value, "cannot call order_by() without a from()"); - static_assert(vendor::is_noop::value, "cannot call order_by() twice for a single select"); - return { - _flags, - _columns, - _from, - _where, - _group_by, - _having, - {std::tuple{expr...}}, - _limit, - _offset, - }; - } - - template - select_t& add_order_by(Expr expr) - { - static_assert(is_dynamic_t::value, "cannot call add_order_by() in a non-dynamic order_by"); - - _order_by.add(expr); - - return *this; - } - - template - auto limit(Expr limit) - -> set_limit_t::type>> - { - static_assert(not vendor::is_noop::value, "cannot call limit() without a from()"); - static_assert(vendor::is_noop::value, "cannot call limit() twice for a single select"); - return { - _flags, - _columns, - _from, - _where, - _group_by, - _having, - _order_by, - {limit}, - _offset, - }; - } - - auto dynamic_limit(std::size_t limit = 0) - ->set_limit_t - { - static_assert(not vendor::is_noop::value, "cannot call limit() without a from()"); - static_assert(vendor::is_noop::value, "cannot call limit() twice for a single select"); - return { - _flags, - _columns, - _from, - _where, - _group_by, - _having, - _order_by, - {limit}, - _offset, - }; - } - - select_t& set_limit(std::size_t limit) - { - static_assert(is_dynamic_t::value, "cannot call set_limit() in a non-dynamic limit"); - - _limit.set(limit); - - return *this; - } - - template - auto offset(Expr offset) - -> set_offset_t::type>> - { - static_assert(not vendor::is_noop::value, "cannot call offset() without a limit"); - static_assert(vendor::is_noop::value, "cannot call offset() twice for a single select"); - return { - _flags, - _columns, - _from, - _where, - _group_by, - _having, - _order_by, - _limit, - {offset}, - }; - } - - auto dynamic_offset(std::size_t offset = 0) - -> set_offset_t - { - static_assert(not vendor::is_noop::value, "cannot call offset() without a limit"); - static_assert(vendor::is_noop::value, "cannot call offset() twice for a single select"); - return { - _flags, - _columns, - _from, - _where, - _group_by, - _having, - _order_by, - _limit, - {offset}, - }; - } - - select_t& set_offset(std::size_t offset) - { - static_assert(is_dynamic_t::value, "cannot call set_offset() in a non-dynamic limit"); - - _offset.set(offset); - - return *this; - } - template struct _pseudo_table_t { @@ -648,9 +195,8 @@ namespace sqlpp { context << "SELECT "; - /* - interpret(t._flags, context); - interpret(t._columns, context); + interpret(t._flag_list, context); + interpret(t._column_list, context); interpret(t._from, context); interpret(t._where, context); interpret(t._group_by, context); @@ -658,60 +204,48 @@ namespace sqlpp interpret(t._order_by, context); interpret(t._limit, context); interpret(t._offset, context); - */ return context; } }; } + template + using blank_select_t = select_t; - /* - - // construct select flag list - namespace detail + blank_select_t select() // FIXME: These should be constexpr { - template - using make_select_flag_list_t = - vendor::select_flag_list_t()...))>; + return { blank_select_t() }; } - // construct select expression list - namespace detail - { - template - using make_select_column_list_t = - vendor::select_column_list_t()...))>; - } - - auto select() - -> select_t>, vendor::select_column_list_t>> + template + auto select(Columns... columns) + -> vendor::update_policies_t, vendor::no_select_column_list_t, vendor::select_column_list_t> { - return { {}, vendor::select_column_list_t>{}, {}, {}, {}, {}, {}, {}, {} }; + return { blank_select_t(), vendor::select_column_list_t(columns...) }; } - template - auto select(NamedExpr... namedExpr) - -> select_t, detail::make_select_column_list_t> + template + blank_select_t dynamic_select() { - return { - { detail::make_flag_tuple(namedExpr...) }, - { detail::make_expression_tuple(namedExpr...) }, - {}, {}, {}, {}, {}, {}, {} - }; + return { blank_select_t() }; } - template - auto dynamic_select(const Db& db, NamedExpr... namedExpr) - -> select_t, detail::make_select_column_list_t> + template + auto dynamic_select(Columns... columns) + -> vendor::update_policies_t, vendor::no_select_column_list_t, vendor::select_column_list_t> { - return { - { detail::make_flag_tuple(namedExpr...) }, - { detail::make_expression_tuple(namedExpr...) }, - {}, {}, {}, {}, {}, {}, {} - }; + return { blank_select_t(), vendor::select_column_list_t(columns...) }; } - */ } #endif diff --git a/include/sqlpp11/vendor/having.h b/include/sqlpp11/vendor/having.h index 116e1e2a..cc5de0ac 100644 --- a/include/sqlpp11/vendor/having.h +++ b/include/sqlpp11/vendor/having.h @@ -52,6 +52,16 @@ namespace sqlpp using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type; + having_t(Expressions... expressions): + _expressions(expressions...) + {} + + having_t(const having_t&) = default; + having_t(having_t&&) = default; + having_t& operator=(const having_t&) = default; + having_t& operator=(having_t&&) = default; + ~having_t() = default; + template void add(Expression expr) { diff --git a/include/sqlpp11/vendor/limit.h b/include/sqlpp11/vendor/limit.h index d3b175a5..be74b7c5 100644 --- a/include/sqlpp11/vendor/limit.h +++ b/include/sqlpp11/vendor/limit.h @@ -56,29 +56,30 @@ namespace sqlpp Limit _value; }; - struct dynamic_limit_t - { - using _is_limit = std::true_type; - using _is_dynamic = std::true_type; - - dynamic_limit_t(size_t value): - _value(value) - {} - - dynamic_limit_t(const dynamic_limit_t&) = default; - dynamic_limit_t(dynamic_limit_t&&) = default; - dynamic_limit_t& operator=(const dynamic_limit_t&) = default; - dynamic_limit_t& operator=(dynamic_limit_t&&) = default; - ~dynamic_limit_t() = default; - - void set_limit(std::size_t limit) + template + struct dynamic_limit_t { - _value = limit; - } + using _is_limit = std::true_type; + using _is_dynamic = std::true_type; - dynamic_limit_t& _limit = *this; - std::size_t _value; // FIXME: This should be a serializable! - }; + dynamic_limit_t(size_t value): + _value(value) + {} + + dynamic_limit_t(const dynamic_limit_t&) = default; + dynamic_limit_t(dynamic_limit_t&&) = default; + dynamic_limit_t& operator=(const dynamic_limit_t&) = default; + dynamic_limit_t& operator=(dynamic_limit_t&&) = default; + ~dynamic_limit_t() = default; + + void set_limit(std::size_t limit) + { + _value = limit; + } + + dynamic_limit_t& _limit = *this; + std::size_t _value; // FIXME: This should be a serializable! + }; struct no_limit_t { @@ -92,14 +93,20 @@ namespace sqlpp { }; - 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> @@ -107,19 +114,20 @@ namespace sqlpp return { static_cast(*this), limit_t(arg) }; } - auto dynamic_limit(size_t arg) - -> vendor::update_policies_t + template + auto dynamic_limit(Arg arg) + -> vendor::update_policies_t::type>> { 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(arg) }; + return { static_cast(*this), dynamic_limit_t::type>(arg) }; } }; // Interpreters - template - struct interpreter_t + template + struct interpreter_t> { - using T = dynamic_limit_t; + using T = dynamic_limit_t; static Context& _(const T& t, Context& context) { diff --git a/include/sqlpp11/vendor/offset.h b/include/sqlpp11/vendor/offset.h index 7f4df82b..5af2ee84 100644 --- a/include/sqlpp11/vendor/offset.h +++ b/include/sqlpp11/vendor/offset.h @@ -56,29 +56,30 @@ namespace sqlpp Offset _value; }; - struct dynamic_offset_t - { - using _is_offset = std::true_type; - using _is_dynamic = std::true_type; - - dynamic_offset_t(size_t value): - _value(value) - {} - - dynamic_offset_t(const dynamic_offset_t&) = default; - dynamic_offset_t(dynamic_offset_t&&) = default; - dynamic_offset_t& operator=(const dynamic_offset_t&) = default; - dynamic_offset_t& operator=(dynamic_offset_t&&) = default; - ~dynamic_offset_t() = default; - - void set_offset(std::size_t offset) + template + struct dynamic_offset_t { - _value = offset; - } + using _is_offset = std::true_type; + using _is_dynamic = std::true_type; - dynamic_offset_t& _offset = *this; - std::size_t _value; // FIXME: This should be a serializable! - }; + dynamic_offset_t(size_t value): + _value(value) + {} + + dynamic_offset_t(const dynamic_offset_t&) = default; + dynamic_offset_t(dynamic_offset_t&&) = default; + dynamic_offset_t& operator=(const dynamic_offset_t&) = default; + dynamic_offset_t& operator=(dynamic_offset_t&&) = default; + ~dynamic_offset_t() = default; + + void set_offset(std::size_t offset) + { + _value = offset; + } + + dynamic_offset_t& _offset = *this; + std::size_t _value; // FIXME: This should be a serializable! + }; struct no_offset_t { @@ -92,14 +93,20 @@ namespace sqlpp { }; - 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> @@ -107,11 +114,12 @@ namespace sqlpp return { static_cast(*this), offset_t(arg) }; } - auto dynamic_offset(size_t arg) - -> vendor::update_policies_t + template + auto dynamic_offset(Arg arg) + -> vendor::update_policies_t::type>> { 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(arg) }; + return { static_cast(*this), dynamic_offset_t>(arg) }; } }; @@ -129,10 +137,10 @@ namespace sqlpp } }; - template - struct interpreter_t + template + struct interpreter_t> { - using T = dynamic_offset_t; + using T = dynamic_offset_t; static Context& _(const T& t, Context& context) { diff --git a/tests/InterpretTest.cpp b/tests/InterpretTest.cpp index 58efc51a..3646635e 100644 --- a/tests/InterpretTest.cpp +++ b/tests/InterpretTest.cpp @@ -69,15 +69,20 @@ int main() interpret(t.gamma != sqlpp::tvin(false), printer).flush(); interpret(t.alpha == 7, printer).flush(); interpret(t.beta + "kaesekuchen", printer).flush(); + */ - interpret(select(sqlpp::distinct, t.alpha, t.beta), printer).flush(); - interpret(select(sqlpp::distinct, t.alpha, t.beta).from(t), printer).flush(); - interpret(select(sqlpp::distinct, t.alpha, t.beta).from(t).where(t.alpha == 3), printer).flush(); - interpret(select(sqlpp::distinct, t.alpha, t.beta).from(t).where(t.alpha == 3).group_by(t.gamma), printer).flush(); - interpret(select(sqlpp::distinct, t.alpha, t.beta).from(t).where(t.alpha == 3).group_by(t.gamma).having(t.beta.like("%kuchen")), printer).flush(); - interpret(select(sqlpp::distinct, t.alpha, t.beta).from(t).where(t.alpha == 3).group_by(t.gamma).having(t.beta.like("%kuchen")).order_by(t.beta.asc()), printer).flush(); - interpret(select(sqlpp::distinct, t.alpha, t.beta).from(t).where(t.alpha == 3).group_by(t.gamma).having(t.beta.like("%kuchen")).order_by(t.beta.asc()).limit(17).offset(3), printer).flush(); + interpret(sqlpp::select(), printer).flush(); + interpret(sqlpp::select().flags(sqlpp::distinct), printer).flush(); + interpret(select(t.alpha, t.beta).flags(sqlpp::distinct), printer).flush(); + interpret(select(t.alpha, t.beta), printer).flush(); + interpret(select(t.alpha, t.beta).from(t), printer).flush(); + interpret(select(t.alpha, t.beta).from(t).where(t.alpha == 3), printer).flush(); + interpret(select(t.alpha, t.beta).from(t).where(t.alpha == 3).group_by(t.gamma), printer).flush(); + interpret(select(t.alpha, t.beta).from(t).where(t.alpha == 3).group_by(t.gamma).having(t.beta.like("%kuchen")), printer).flush(); + interpret(select(t.alpha, t.beta).from(t).where(t.alpha == 3).group_by(t.gamma).having(t.beta.like("%kuchen")).order_by(t.beta.asc()), printer).flush(); + interpret(select(t.alpha, t.beta).from(t).where(t.alpha == 3).group_by(t.gamma).having(t.beta.like("%kuchen")).order_by(t.beta.asc()).limit(17).offset(3), printer).flush(); + /* interpret(parameter(sqlpp::bigint(), t.alpha), printer).flush(); interpret(parameter(t.alpha), printer).flush(); interpret(t.alpha == parameter(t.alpha), printer).flush(); From c5ef725106c6de399fc17fa8edbdb635d0c37539 Mon Sep 17 00:00:00 2001 From: rbock Date: Fri, 7 Feb 2014 23:51:21 +0100 Subject: [PATCH 04/74] Removed the dreaded make_expression_tuple and make_flag_tuple --- .../sqlpp11/detail/make_expression_tuple.h | 64 ----------------- include/sqlpp11/detail/make_flag_tuple.h | 70 ------------------- include/sqlpp11/multi_column.h | 5 +- include/sqlpp11/select.h | 4 -- 4 files changed, 2 insertions(+), 141 deletions(-) delete mode 100644 include/sqlpp11/detail/make_expression_tuple.h delete mode 100644 include/sqlpp11/detail/make_flag_tuple.h diff --git a/include/sqlpp11/detail/make_expression_tuple.h b/include/sqlpp11/detail/make_expression_tuple.h deleted file mode 100644 index ab9478fd..00000000 --- a/include/sqlpp11/detail/make_expression_tuple.h +++ /dev/null @@ -1,64 +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_DETAIL_MAKE_EXPRESSION_TUPLE_H -#define SQLPP_DETAIL_MAKE_EXPRESSION_TUPLE_H - -namespace sqlpp -{ - namespace detail - { - template - auto make_single_expression_tuple(Expr expr) - -> typename std::enable_if::value, decltype(std::make_tuple(expr))>::type - { - return std::make_tuple(expr); - }; - - template - auto make_single_expression_tuple(Expr expr) - -> typename std::enable_if::value, std::tuple<>>::type - { - return {}; - }; - - template - auto make_single_expression_tuple(std::tuple t) - -> std::tuple - { - return t; - }; - - template - auto make_expression_tuple(Expr... expr) - -> decltype(std::tuple_cat(make_single_expression_tuple(expr)...)) - { - return std::tuple_cat(make_single_expression_tuple(expr)...); - }; - - } -} -#endif diff --git a/include/sqlpp11/detail/make_flag_tuple.h b/include/sqlpp11/detail/make_flag_tuple.h deleted file mode 100644 index 7c9efad0..00000000 --- a/include/sqlpp11/detail/make_flag_tuple.h +++ /dev/null @@ -1,70 +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_DETAIL_MAKE_FLAG_TUPLE_H -#define SQLPP_DETAIL_MAKE_FLAG_TUPLE_H - -namespace sqlpp -{ - namespace detail - { - // accept select flags - template - auto make_single_flag_tuple(Expr expr) -> typename std::enable_if::value, decltype(std::make_tuple(expr))>::type - { - return std::make_tuple(expr); - }; - - // ignore named expressions - template - auto make_single_flag_tuple(Expr expr) -> typename std::enable_if::value, std::tuple<>>::type - { - return {}; - }; - - // ignore tables - template - auto make_single_flag_tuple(Tab tab) -> typename std::enable_if::value, std::tuple<>>::type - { - return {}; - }; - - // ignore tuples of expressions - template - auto make_single_flag_tuple(std::tuple t) -> std::tuple<> - { - return {}; - }; - - template - auto make_flag_tuple(Expr... expr) -> decltype(std::tuple_cat(make_single_flag_tuple(expr)...)) - { - return std::tuple_cat(make_single_flag_tuple(expr)...); - }; - - } -} -#endif diff --git a/include/sqlpp11/multi_column.h b/include/sqlpp11/multi_column.h index 8cf50469..199bcfa8 100644 --- a/include/sqlpp11/multi_column.h +++ b/include/sqlpp11/multi_column.h @@ -28,7 +28,6 @@ #define SQLPP_MULTI_COLUMN_H #include -#include #include namespace sqlpp @@ -74,13 +73,13 @@ namespace sqlpp { template using make_multi_column_t = - multi_column_t()...))>; + multi_column_t>; } template detail::make_multi_column_t multi_column(const AliasProvider& aliasProvider, NamedExpr... namedExpr) { - return { detail::make_expression_tuple(namedExpr...)}; + return { std::tuple(namedExpr...)}; } } diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index af251d69..0da74235 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -48,10 +48,6 @@ #include #include - -#include -#include - namespace sqlpp { namespace detail From 3a875e794bcab60cee80e84c21b045a8477d287f Mon Sep 17 00:00:00 2001 From: rbock Date: Sat, 8 Feb 2014 00:35:59 +0100 Subject: [PATCH 05/74] More reasonable dynamic limit and offset --- include/sqlpp11/vendor/limit.h | 52 ++++++++++++++++++++----------- include/sqlpp11/vendor/offset.h | 55 +++++++++++++++++++++------------ 2 files changed, 69 insertions(+), 38 deletions(-) diff --git a/include/sqlpp11/vendor/limit.h b/include/sqlpp11/vendor/limit.h index be74b7c5..1a8426a2 100644 --- a/include/sqlpp11/vendor/limit.h +++ b/include/sqlpp11/vendor/limit.h @@ -42,7 +42,7 @@ namespace sqlpp using _is_limit = std::true_type; static_assert(is_integral_t::value, "limit requires an integral value or integral parameter"); - limit_t(size_t value): + limit_t(Limit value): _value(value) {} @@ -62,9 +62,17 @@ namespace sqlpp using _is_limit = std::true_type; using _is_dynamic = std::true_type; - dynamic_limit_t(size_t value): - _value(value) - {} + dynamic_limit_t(): + _value(noop()) + { + } + + template + dynamic_limit_t(Limit value): + _initialized(true), + _value(typename wrap_operand::type(value)) + { + } dynamic_limit_t(const dynamic_limit_t&) = default; dynamic_limit_t(dynamic_limit_t&&) = default; @@ -72,13 +80,19 @@ namespace sqlpp dynamic_limit_t& operator=(dynamic_limit_t&&) = default; ~dynamic_limit_t() = default; - void set_limit(std::size_t limit) - { - _value = limit; - } + template + void set_limit(Limit value) + { + using arg_t = typename wrap_operand::type; + _value = arg_t(value); + _initialized = true; + } +#warning this is stupid! Will get dangling references when copying dynamic_limit_t& _limit = *this; - std::size_t _value; // FIXME: This should be a serializable! + + bool _initialized = false; + interpretable_t _value; }; struct no_limit_t @@ -101,7 +115,7 @@ namespace sqlpp template struct crtp_wrapper_t { - template + template struct delayed_get_database_t { using type = get_database_t; @@ -109,17 +123,19 @@ namespace sqlpp template auto limit(Arg arg) - -> vendor::update_policies_t> + -> vendor::update_policies_t::type>> { - return { static_cast(*this), limit_t(arg) }; + typename wrap_operand::type value = {arg}; + return { static_cast(*this), limit_t::type>(value) }; } - template - auto dynamic_limit(Arg arg) - -> vendor::update_policies_t::type>> + 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>(arg) }; + return { static_cast(*this), dynamic_limit_t::type>(args...) }; } }; @@ -131,8 +147,8 @@ namespace sqlpp static Context& _(const T& t, Context& context) { - if (t._value > 0) - context << " LIMIT " << t._limit; + if (t._initialized) + interpret(t._value, context); return context; } }; diff --git a/include/sqlpp11/vendor/offset.h b/include/sqlpp11/vendor/offset.h index 5af2ee84..c8f1f119 100644 --- a/include/sqlpp11/vendor/offset.h +++ b/include/sqlpp11/vendor/offset.h @@ -42,7 +42,7 @@ namespace sqlpp using _is_offset = std::true_type; static_assert(is_integral_t::value, "offset requires an integral value or integral parameter"); - offset_t(size_t value): + offset_t(Offset value): _value(value) {} @@ -53,6 +53,7 @@ namespace sqlpp ~offset_t() = default; offset_t& _offset = *this; + Offset _value; }; @@ -62,9 +63,17 @@ namespace sqlpp using _is_offset = std::true_type; using _is_dynamic = std::true_type; - dynamic_offset_t(size_t value): - _value(value) - {} + dynamic_offset_t(): + _value(noop()) + { + } + + template + dynamic_offset_t(Offset value): + _initialized(true), + _value(typename wrap_operand::type(value)) + { + } dynamic_offset_t(const dynamic_offset_t&) = default; dynamic_offset_t(dynamic_offset_t&&) = default; @@ -72,13 +81,17 @@ namespace sqlpp dynamic_offset_t& operator=(dynamic_offset_t&&) = default; ~dynamic_offset_t() = default; - void set_offset(std::size_t offset) - { - _value = offset; - } + template + void set_offset(Offset value) + { + using arg_t = typename wrap_operand::type; + _value = arg_t(value); + _initialized = true; + } dynamic_offset_t& _offset = *this; - std::size_t _value; // FIXME: This should be a serializable! + bool _initialized = false; + interpretable_t _value; }; struct no_offset_t @@ -88,8 +101,8 @@ namespace sqlpp }; // CRTP Wrappers - template - struct crtp_wrapper_t> + template + struct crtp_wrapper_t> { }; @@ -101,7 +114,7 @@ namespace sqlpp template struct crtp_wrapper_t { - template + template struct delayed_get_database_t { using type = get_database_t; @@ -109,17 +122,19 @@ namespace sqlpp template auto offset(Arg arg) - -> vendor::update_policies_t> + -> vendor::update_policies_t::type>> { - return { static_cast(*this), offset_t(arg) }; + typename wrap_operand::type value = {arg}; + return { static_cast(*this), offset_t::type>(value) }; } - template - auto dynamic_offset(Arg arg) - -> vendor::update_policies_t::type>> + 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>(arg) }; + return { static_cast(*this), dynamic_offset_t::type>(args...) }; } }; @@ -132,7 +147,7 @@ namespace sqlpp static Context& _(const T& t, Context& context) { context << " OFFSET "; - interpret(t._offset, context); + interpret(t._value, context); return context; } }; @@ -144,7 +159,7 @@ namespace sqlpp static Context& _(const T& t, Context& context) { - if (t._value > 0) + if (t._initialized) context << " OFFSET " << t._offset; return context; } From f7aa56b7dcb0e84a366ffdf2fb7a04b35dc2fcdb Mon Sep 17 00:00:00 2001 From: rbock Date: Sat, 8 Feb 2014 00:43:20 +0100 Subject: [PATCH 06/74] Fixed possible dangling references problem --- include/sqlpp11/remove.h | 6 +++--- include/sqlpp11/select.h | 18 +++++++++--------- include/sqlpp11/vendor/from.h | 4 ++-- include/sqlpp11/vendor/group_by.h | 4 ++-- include/sqlpp11/vendor/having.h | 4 ++-- include/sqlpp11/vendor/limit.h | 7 +++---- include/sqlpp11/vendor/offset.h | 6 +++--- include/sqlpp11/vendor/order_by.h | 4 ++-- include/sqlpp11/vendor/select_column_list.h | 4 ++-- include/sqlpp11/vendor/select_flag_list.h | 4 ++-- include/sqlpp11/vendor/using.h | 4 ++-- include/sqlpp11/vendor/where.h | 4 ++-- 12 files changed, 34 insertions(+), 35 deletions(-) diff --git a/include/sqlpp11/remove.h b/include/sqlpp11/remove.h index 68c2397d..d7601bc8 100644 --- a/include/sqlpp11/remove.h +++ b/include/sqlpp11/remove.h @@ -116,9 +116,9 @@ namespace sqlpp static Context& _(const T& t, Context& context) { context << "DELETE"; - interpret(t._from, context); - interpret(t._using, context); - interpret(t._where, context); + interpret(t._from(), context); + interpret(t._using(), context); + interpret(t._where(), context); return context; } }; diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 0da74235..07dadf0a 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -191,15 +191,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; } diff --git a/include/sqlpp11/vendor/from.h b/include/sqlpp11/vendor/from.h index f0a816cd..8cdfa710 100644 --- a/include/sqlpp11/vendor/from.h +++ b/include/sqlpp11/vendor/from.h @@ -72,7 +72,7 @@ namespace sqlpp _dynamic_tables.emplace_back(table); } - from_t& _from = *this; + const from_t& _from() const { return *this; } std::tuple _tables; vendor::interpretable_list_t _dynamic_tables; }; @@ -80,7 +80,7 @@ namespace sqlpp struct no_from_t { using _is_from = std::true_type; - no_from_t& _from = *this; + const no_from_t& _from() const { return *this; } }; // CRTP Wrappers diff --git a/include/sqlpp11/vendor/group_by.h b/include/sqlpp11/vendor/group_by.h index bdb7b169..d5e90eb8 100644 --- a/include/sqlpp11/vendor/group_by.h +++ b/include/sqlpp11/vendor/group_by.h @@ -71,7 +71,7 @@ namespace sqlpp _dynamic_expressions.emplace_back(expression); } - group_by_t& _group_by = *this; + const group_by_t& _group_by() const { return *this; } _parameter_tuple_t _expressions; vendor::interpretable_list_t _dynamic_expressions; }; @@ -79,7 +79,7 @@ namespace sqlpp struct no_group_by_t { using _is_group_by = std::true_type; - no_group_by_t& _group_by = *this; + const no_group_by_t& _group_by() const { return *this; } }; // CRTP Wrappers diff --git a/include/sqlpp11/vendor/having.h b/include/sqlpp11/vendor/having.h index cc5de0ac..63698dad 100644 --- a/include/sqlpp11/vendor/having.h +++ b/include/sqlpp11/vendor/having.h @@ -69,7 +69,7 @@ namespace sqlpp _dynamic_expressions.emplace_back(expr); } - having_t& _having = *this; + const having_t& _having() const { return *this; } _parameter_tuple_t _expressions; vendor::interpretable_list_t _dynamic_expressions; }; @@ -77,7 +77,7 @@ namespace sqlpp struct no_having_t { using _is_having = std::true_type; - no_having_t& _having = *this; + const no_having_t& _having() const { return *this; } }; // CRTP Wrappers diff --git a/include/sqlpp11/vendor/limit.h b/include/sqlpp11/vendor/limit.h index 1a8426a2..bdae95fc 100644 --- a/include/sqlpp11/vendor/limit.h +++ b/include/sqlpp11/vendor/limit.h @@ -52,7 +52,7 @@ namespace sqlpp limit_t& operator=(limit_t&&) = default; ~limit_t() = default; - limit_t& _limit = *this; + const limit_t& _limit() const { return *this; } Limit _value; }; @@ -88,8 +88,7 @@ namespace sqlpp _initialized = true; } -#warning this is stupid! Will get dangling references when copying - dynamic_limit_t& _limit = *this; + const dynamic_limit_t& _limit() const { return *this; } bool _initialized = false; interpretable_t _value; @@ -98,7 +97,7 @@ namespace sqlpp struct no_limit_t { using _is_limit = std::true_type; - no_limit_t& _limit = *this; + const no_limit_t& _limit() const { return *this; } }; // CRTP Wrappers diff --git a/include/sqlpp11/vendor/offset.h b/include/sqlpp11/vendor/offset.h index c8f1f119..1c839887 100644 --- a/include/sqlpp11/vendor/offset.h +++ b/include/sqlpp11/vendor/offset.h @@ -52,7 +52,7 @@ namespace sqlpp offset_t& operator=(offset_t&&) = default; ~offset_t() = default; - offset_t& _offset = *this; + const offset_t& _offset() const { return *this; } Offset _value; }; @@ -89,7 +89,7 @@ namespace sqlpp _initialized = true; } - dynamic_offset_t& _offset = *this; + const dynamic_offset_t& _offset() const { return *this; } bool _initialized = false; interpretable_t _value; }; @@ -97,7 +97,7 @@ namespace sqlpp struct no_offset_t { using _is_offset = std::true_type; - no_offset_t& _offset = *this; + const no_offset_t& _offset() const { return *this; } }; // CRTP Wrappers diff --git a/include/sqlpp11/vendor/order_by.h b/include/sqlpp11/vendor/order_by.h index 9c6f32ed..63ee7421 100644 --- a/include/sqlpp11/vendor/order_by.h +++ b/include/sqlpp11/vendor/order_by.h @@ -70,7 +70,7 @@ namespace sqlpp _dynamic_expressions.push_back(expressions); } - order_by_t& _order_by = *this; + const order_by_t& _order_by() const { return *this; } _parameter_tuple_t _expressions; vendor::interpretable_list_t _dynamic_expressions; }; @@ -78,7 +78,7 @@ namespace sqlpp struct no_order_by_t { using _is_order_by = std::true_type; - no_order_by_t& _order_by = *this; + const no_order_by_t& _order_by() const { return *this; } }; // CRTP Wrappers diff --git a/include/sqlpp11/vendor/select_column_list.h b/include/sqlpp11/vendor/select_column_list.h index 7872ac62..ea90f17b 100644 --- a/include/sqlpp11/vendor/select_column_list.h +++ b/include/sqlpp11/vendor/select_column_list.h @@ -188,7 +188,7 @@ namespace sqlpp _dynamic_columns.push_back(namedExpr); } - select_column_list_t& _column_list = *this; + const select_column_list_t& _column_list() const { return *this; } _parameter_tuple_t _columns; dynamic_select_column_list _dynamic_columns; }; @@ -196,7 +196,7 @@ namespace sqlpp struct no_select_column_list_t { using _is_select_column_list = std::true_type; - no_select_column_list_t& _column_list = *this; + const no_select_column_list_t& _column_list() const { return *this; } }; // CRTP Wrappers diff --git a/include/sqlpp11/vendor/select_flag_list.h b/include/sqlpp11/vendor/select_flag_list.h index 48860aa7..dc6b4b8e 100644 --- a/include/sqlpp11/vendor/select_flag_list.h +++ b/include/sqlpp11/vendor/select_flag_list.h @@ -70,7 +70,7 @@ namespace sqlpp _dynamic_flags.emplace_back(flag); } - select_flag_list_t& _flag_list = *this; + const select_flag_list_t& _flag_list() const { return *this; } _parameter_tuple_t _flags; vendor::interpretable_list_t _dynamic_flags; }; @@ -78,7 +78,7 @@ namespace sqlpp struct no_select_flag_list_t { using _is_select_flag_list = std::true_type; - no_select_flag_list_t& _flag_list = *this; + const no_select_flag_list_t& _flag_list() const { return *this; } }; // CRTP Wrappers diff --git a/include/sqlpp11/vendor/using.h b/include/sqlpp11/vendor/using.h index 0cd2222f..1ad27720 100644 --- a/include/sqlpp11/vendor/using.h +++ b/include/sqlpp11/vendor/using.h @@ -71,14 +71,14 @@ namespace sqlpp _dynamic_tables.emplace_back(table); } - using_t& _using = *this; + const using_t& _using() const { return *this; } _parameter_tuple_t _tables; vendor::interpretable_list_t _dynamic_tables; }; struct no_using_t { - no_using_t& _using = *this; + const no_using_t& _using() const { return *this; } }; // CRTP Wrapper diff --git a/include/sqlpp11/vendor/where.h b/include/sqlpp11/vendor/where.h index b1805212..89ceeece 100644 --- a/include/sqlpp11/vendor/where.h +++ b/include/sqlpp11/vendor/where.h @@ -71,7 +71,7 @@ namespace sqlpp _dynamic_expressions.emplace_back(expr); } - where_t& _where = *this; + const where_t& _where() const { return *this; } _parameter_tuple_t _expressions; vendor::interpretable_list_t _dynamic_expressions; }; @@ -88,7 +88,7 @@ namespace sqlpp struct no_where_t { using _is_where = std::true_type; - no_where_t& _where = *this; + const no_where_t& _where() const { return *this; } }; // CRTP Wrappers From b82a0295cf7c87cb8b3618b8e9c84ce1957c0266 Mon Sep 17 00:00:00 2001 From: rbock Date: Sat, 8 Feb 2014 16:29:21 +0100 Subject: [PATCH 07/74] Fixed all_of use in select --- include/sqlpp11/multi_column.h | 1 + include/sqlpp11/select.h | 114 +++++++++++++------- include/sqlpp11/vendor/select_column_list.h | 15 +++ include/sqlpp11/vendor/where.h | 15 ++- tests/InterpretTest.cpp | 28 ++++- 5 files changed, 126 insertions(+), 47 deletions(-) diff --git a/include/sqlpp11/multi_column.h b/include/sqlpp11/multi_column.h index 199bcfa8..61d1f5f2 100644 --- a/include/sqlpp11/multi_column.h +++ b/include/sqlpp11/multi_column.h @@ -71,6 +71,7 @@ namespace sqlpp namespace detail { +#warning need to handle all_of here. template using make_multi_column_t = multi_column_t>; diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 07dadf0a..98795f71 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -63,13 +63,26 @@ namespace sqlpp typename Limit, typename Offset > - struct check_select_t + struct select_helper_t { - //static_assert(is_where_t::value, "cannot select remove without having a where condition, use .where(true) to remove all rows"); - static constexpr bool value = true; + using _column_list_t = ColumnList; + using _from_t = ColumnList; + 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>... { @@ -80,6 +93,17 @@ namespace sqlpp 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 _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; + + // FIXME: introduce checks whether this select could really be used as a value + using _value_type = typename _column_list_t::_value_type; + using _name_t = typename _column_list_t::_name_t; + select_t() {} @@ -99,27 +123,11 @@ namespace sqlpp select_t& operator=(select_t&& r) = default; ~select_t() = default; - using _is_select = std::true_type; - using _requires_braces = std::true_type; - - /* - using _result_row_t = typename ColumnList::_result_row_t; - using _dynamic_names_t = typename ColumnList::_dynamic_names_t; - using _parameter_tuple_t = std::tuple; - using _parameter_list_t = typename make_parameter_list_t::type; - // Indicators - using _value_type = typename std::conditional< - vendor::is_noop::value, - no_value_t, // If there is no from, the select is not complete (this logic is a bit simple, but better than nothing) - typename ColumnList::_value_type>::type; - - using _name_t = typename ColumnList::_name_t; - template struct _pseudo_table_t { - using table = typename ColumnList::template _pseudo_table_t; + using table = typename _column_list_t::template _pseudo_table_t; using alias = typename table::template _alias_t; }; @@ -130,9 +138,9 @@ namespace sqlpp *this).as(aliasProvider); } - const typename ColumnList::_dynamic_names_t& get_dynamic_names() const + const _dynamic_names_t& get_dynamic_names() const { - return _columns._dynamic_columns._dynamic_expression_names; + return _column_list_t::_dynamic_columns._dynamic_expression_names; } static constexpr size_t _get_static_no_of_parameters() @@ -155,13 +163,8 @@ namespace sqlpp auto _run(Db& db) const -> result_t { - 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"); + static_assert(detail::select_helper_t::template 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"); - // 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. - return {db.select(*this), get_dynamic_names()}; } @@ -170,14 +173,10 @@ namespace sqlpp auto _prepare(Db& db) const -> prepared_select_t { - 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()"); - // 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_assert(detail::select_helper_t::template can_run_t::value, "Cannot prepare select statement"); return {{}, get_dynamic_names(), db.prepare_select(*this)}; } -*/ }; namespace vendor @@ -218,6 +217,39 @@ namespace sqlpp vendor::no_limit_t, vendor::no_offset_t>; + template + struct as_tuple + { + static std::tuple _(T t) { return { t }; }; + }; + + template + struct as_tuple> + { + static std::tuple _(std::tuple t) { return t; } + }; + + template class Target, typename First, typename T> + struct copy_tuple_args_impl + { + static_assert(vendor::wrong_t::value, "copy_tuple_args must be called with a tuple"); + }; + + template class Target, typename First, typename... Args> + struct copy_tuple_args_impl> + { + using type = Target; + }; + + template class Target, typename First, typename T> + using copy_tuple_args_t = typename copy_tuple_args_impl::type; + + template + using make_select_column_list_t = + copy_tuple_args_t::_(std::declval())...))>; + + blank_select_t select() // FIXME: These should be constexpr { return { blank_select_t() }; @@ -225,22 +257,24 @@ namespace sqlpp template auto select(Columns... columns) - -> vendor::update_policies_t, vendor::no_select_column_list_t, vendor::select_column_list_t> + -> vendor::update_policies_t, + vendor::no_select_column_list_t, + make_select_column_list_t> { - return { blank_select_t(), vendor::select_column_list_t(columns...) }; + return { blank_select_t(), make_select_column_list_t(std::tuple_cat(as_tuple::_(columns)...)) }; } template - blank_select_t dynamic_select() + blank_select_t dynamic_select(const Database&) { - return { blank_select_t() }; + return { blank_select_t() }; } template - auto dynamic_select(Columns... columns) - -> vendor::update_policies_t, vendor::no_select_column_list_t, vendor::select_column_list_t> + auto dynamic_select(const Database&, Columns... columns) + -> vendor::update_policies_t, vendor::no_select_column_list_t, make_select_column_list_t> { - return { blank_select_t(), vendor::select_column_list_t(columns...) }; + return { blank_select_t(), make_select_column_list_t(std::tuple_cat(as_tuple::_(columns)...)) }; } } diff --git a/include/sqlpp11/vendor/select_column_list.h b/include/sqlpp11/vendor/select_column_list.h index ea90f17b..30bf75c4 100644 --- a/include/sqlpp11/vendor/select_column_list.h +++ b/include/sqlpp11/vendor/select_column_list.h @@ -170,6 +170,10 @@ namespace sqlpp template using _dynamic_t = select_column_list_t>; + select_column_list_t(std::tuple columns): + _columns(columns) + {} + select_column_list_t(Columns... columns): _columns(columns...) {} @@ -196,6 +200,17 @@ namespace sqlpp struct no_select_column_list_t { using _is_select_column_list = 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; + struct _name_t {}; + + template + struct _pseudo_table_t + { + 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; } }; diff --git a/include/sqlpp11/vendor/where.h b/include/sqlpp11/vendor/where.h index 89ceeece..78b34db6 100644 --- a/include/sqlpp11/vendor/where.h +++ b/include/sqlpp11/vendor/where.h @@ -82,7 +82,18 @@ namespace sqlpp using _is_where = std::true_type; using _is_dynamic = std::false_type; - std::tuple _condition; + where_t(bool condition): + _condition(condition) + {} + + where_t(const where_t&) = default; + where_t(where_t&&) = default; + where_t& operator=(const where_t&) = default; + where_t& operator=(where_t&&) = default; + ~where_t() = default; + + const where_t& _where() const { return *this; } + bool _condition; }; struct no_where_t @@ -142,7 +153,7 @@ namespace sqlpp static Context& _(const T& t, Context& context) { - if (not std::get<0>(t._condition)) + if (not t._condition) context << " WHERE NULL"; return context; } diff --git a/tests/InterpretTest.cpp b/tests/InterpretTest.cpp index 3646635e..098710cc 100644 --- a/tests/InterpretTest.cpp +++ b/tests/InterpretTest.cpp @@ -131,20 +131,38 @@ int main() interpret(t.inner_join(t.as(t.alpha)).on(t.beta == t.as(t.alpha).beta), printer).flush(); // multi_column + */ interpret(multi_column(t.alpha, t.alpha, (t.beta + "cake").as(t.gamma)), printer).flush(); // dynamic select - interpret(dynamic_select(db).dynamic_flags().dynamic_columns(t.alpha).add_column(t.beta).add_column(t.gamma), printer).flush(); - interpret(dynamic_select(db).dynamic_flags().add_flag(sqlpp::distinct).dynamic_columns().add_column(t.gamma).add_column(t.beta), printer).flush(); - interpret(dynamic_select(db).dynamic_flags(sqlpp::distinct).add_flag(sqlpp::all).dynamic_columns(t.alpha).add_column(t.beta), printer).flush(); + { + auto s = dynamic_select(db).dynamic_flags().dynamic_columns(); + s.add_column(t.beta); + s.add_column(t.gamma); + interpret(s, printer).flush(); + } + { + auto s = dynamic_select(db).dynamic_flags().dynamic_columns(); + s.add_flag(sqlpp::distinct); + s.add_column(t.beta); + s.add_column(t.gamma); + interpret(s, printer).flush(); + } + { + auto s = dynamic_select(db).dynamic_flags(sqlpp::distinct).dynamic_columns(t.alpha); + s.add_flag(sqlpp::all); + s.add_column(t.beta); + s.add_column(t.gamma); + interpret(s, printer).flush(); + } + /* // distinct aggregate interpret(count(sqlpp::distinct, t.alpha % 7), printer).flush(); interpret(avg(sqlpp::distinct, t.alpha - 7), printer).flush(); interpret(sum(sqlpp::distinct, t.alpha + 7), printer).flush(); - +*/ interpret(select(all_of(t)).from(t).where(true), printer).flush(); interpret(select(all_of(t)).from(t).where(false), printer).flush(); -*/ return 0; } From 5b67061fca68fa12d77723d46078543dcf994571 Mon Sep 17 00:00:00 2001 From: rbock Date: Sat, 8 Feb 2014 17:12:40 +0100 Subject: [PATCH 08/74] Fixed multi_column to handle all_of again --- include/sqlpp11/detail/copy_tuple_args.h | 67 ++++++++++++++++++++++++ include/sqlpp11/multi_column.h | 49 ++++++++++------- include/sqlpp11/select.h | 48 +++++------------ tests/InterpretTest.cpp | 1 + 4 files changed, 112 insertions(+), 53 deletions(-) create mode 100644 include/sqlpp11/detail/copy_tuple_args.h diff --git a/include/sqlpp11/detail/copy_tuple_args.h b/include/sqlpp11/detail/copy_tuple_args.h new file mode 100644 index 00000000..caac57d8 --- /dev/null +++ b/include/sqlpp11/detail/copy_tuple_args.h @@ -0,0 +1,67 @@ +/* + * 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_DETAIL_COPY_TUPLE_ARGS_H +#define SQLPP_DETAIL_COPY_TUPLE_ARGS_H + +#include + +namespace sqlpp +{ + namespace detail + { + template + struct as_tuple + { + static std::tuple _(T t) { return { t }; }; + }; + + template + struct as_tuple> + { + static std::tuple _(std::tuple t) { return t; } + }; + + template class Target, typename First, typename T> + struct copy_tuple_args_impl + { + static_assert(vendor::wrong_t::value, "copy_tuple_args must be called with a tuple"); + }; + + template class Target, typename First, typename... Args> + struct copy_tuple_args_impl> + { + using type = Target; + }; + + template class Target, typename First, typename T> + using copy_tuple_args_t = typename copy_tuple_args_impl::type; + + } +} + + +#endif diff --git a/include/sqlpp11/multi_column.h b/include/sqlpp11/multi_column.h index 61d1f5f2..c60ee57d 100644 --- a/include/sqlpp11/multi_column.h +++ b/include/sqlpp11/multi_column.h @@ -30,36 +30,47 @@ #include #include +#include + namespace sqlpp { - template + template struct multi_column_t { - static_assert(vendor::wrong_t::value, "invalid argument for multicolumn_t"); - }; - - template - struct multi_column_t> - { - static_assert(detail::and_t::value, "multi_column parameters need to be named expressions"); + static_assert(detail::and_t::value, "multi_column parameters need to be named expressions"); using _name_t = typename AliasProvider::_name_t; + multi_column_t(std::tuple columns): + _columns(columns) + {} + + multi_column_t(Columns... columns): + _columns(columns...) + {} + + multi_column_t(const multi_column_t&) = default; + multi_column_t(multi_column_t&&) = default; + multi_column_t& operator=(const multi_column_t&) = default; + multi_column_t& operator=(multi_column_t&&) = default; + ~multi_column_t() = default; + + struct _value_type: public no_value_t { using _is_named_expression = std::true_type; }; using _is_multi_column = std::true_type; - std::tuple _columns; + std::tuple _columns; }; namespace vendor { - template - struct interpreter_t> + template + struct interpreter_t> { - using T = multi_column_t; + using T = multi_column_t; static Context& _(const T& t, Context& context) { @@ -71,18 +82,20 @@ namespace sqlpp namespace detail { -#warning need to handle all_of here. - template + template using make_multi_column_t = - multi_column_t>; + detail::copy_tuple_args_t::_(std::declval())...))>; } - template - detail::make_multi_column_t multi_column(const AliasProvider& aliasProvider, NamedExpr... namedExpr) + template + auto multi_column(const AliasProvider&, Columns... columns) + -> detail::make_multi_column_t { - return { std::tuple(namedExpr...)}; + return detail::make_multi_column_t(std::tuple_cat(detail::as_tuple::_(columns)...)); } + } #endif diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 98795f71..7c6ba00d 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -48,6 +48,8 @@ #include #include +#include + namespace sqlpp { namespace detail @@ -217,37 +219,13 @@ namespace sqlpp vendor::no_limit_t, vendor::no_offset_t>; - template - struct as_tuple - { - static std::tuple _(T t) { return { t }; }; - }; - - template - struct as_tuple> - { - static std::tuple _(std::tuple t) { return t; } - }; - - template class Target, typename First, typename T> - struct copy_tuple_args_impl - { - static_assert(vendor::wrong_t::value, "copy_tuple_args must be called with a tuple"); - }; - - template class Target, typename First, typename... Args> - struct copy_tuple_args_impl> - { - using type = Target; - }; - - template class Target, typename First, typename T> - using copy_tuple_args_t = typename copy_tuple_args_impl::type; - - template - using make_select_column_list_t = - copy_tuple_args_t::_(std::declval())...))>; + namespace detail + { + template + using make_select_column_list_t = + copy_tuple_args_t::_(std::declval())...))>; + } blank_select_t select() // FIXME: These should be constexpr @@ -259,9 +237,9 @@ namespace sqlpp auto select(Columns... columns) -> vendor::update_policies_t, vendor::no_select_column_list_t, - make_select_column_list_t> + detail::make_select_column_list_t> { - return { blank_select_t(), make_select_column_list_t(std::tuple_cat(as_tuple::_(columns)...)) }; + return { blank_select_t(), detail::make_select_column_list_t(std::tuple_cat(detail::as_tuple::_(columns)...)) }; } template @@ -272,9 +250,9 @@ namespace sqlpp template auto dynamic_select(const Database&, Columns... columns) - -> vendor::update_policies_t, vendor::no_select_column_list_t, make_select_column_list_t> + -> vendor::update_policies_t, vendor::no_select_column_list_t, detail::make_select_column_list_t> { - return { blank_select_t(), make_select_column_list_t(std::tuple_cat(as_tuple::_(columns)...)) }; + return { blank_select_t(), detail::make_select_column_list_t(std::tuple_cat(detail::as_tuple::_(columns)...)) }; } } diff --git a/tests/InterpretTest.cpp b/tests/InterpretTest.cpp index 098710cc..f8a7e208 100644 --- a/tests/InterpretTest.cpp +++ b/tests/InterpretTest.cpp @@ -133,6 +133,7 @@ int main() // multi_column */ interpret(multi_column(t.alpha, t.alpha, (t.beta + "cake").as(t.gamma)), printer).flush(); + interpret(multi_column(t, all_of(t)), printer).flush(); // dynamic select { From 68750aac80954de6a220e0730eb7565daa585ce7 Mon Sep 17 00:00:00 2001 From: rbock Date: Sat, 8 Feb 2014 21:06:23 +0100 Subject: [PATCH 09/74] Refactored insert to use policies Much cleaner now. --- include/sqlpp11/insert.h | 183 +++++--------- include/sqlpp11/remove.h | 32 +-- include/sqlpp11/vendor/insert_list.h | 141 ----------- include/sqlpp11/vendor/insert_value_list.h | 225 +++++++++++++++--- .../vendor/{column_list.h => single_table.h} | 69 ++++-- tests/InterpretTest.cpp | 23 +- 6 files changed, 323 insertions(+), 350 deletions(-) delete mode 100644 include/sqlpp11/vendor/insert_list.h rename include/sqlpp11/vendor/{column_list.h => single_table.h} (52%) diff --git a/include/sqlpp11/insert.h b/include/sqlpp11/insert.h index 918b3892..f46459be 100644 --- a/include/sqlpp11/insert.h +++ b/include/sqlpp11/insert.h @@ -31,114 +31,56 @@ #include #include #include -#include #include -#include -#include +#include #include +#include +#include +#include namespace sqlpp { + namespace detail + { + template< + typename Table, + typename InsertValueList, + > + struct check_insert_t + { + //static_assert(not (vendor::is_noop::value and vendor::is_noop::value) , "calling set() or default_values()"); + static constexpr bool value = true; + }; + } - template< - typename Database = void, - typename Table = vendor::noop, - typename InsertList = vendor::noop, - typename ColumnList = vendor::noop, - typename ValueList = vendor::insert_value_list_t - > - struct insert_t + template + struct insert_t: public vendor::policy_t..., public vendor::crtp_wrapper_t, Policies>... { - static_assert(vendor::is_noop
::value or is_table_t
::value, "invalid 'Table' argument"); - static_assert(vendor::is_noop::value or is_insert_list_t::value, "invalid 'InsertList' argument"); - static_assert(vendor::is_noop::value or is_column_list_t::value, "invalid 'ColumnList' argument"); - static_assert(vendor::is_noop::value or is_insert_value_list_t::value, "invalid 'ValueList' argument"); + template + using _policy_update_t = insert_t...>; - using use_default_values_t = insert_t; - template - using set_insert_list_t = insert_t; - template - using set_column_value_list_t = insert_t; - - using _parameter_tuple_t = std::tuple; + using _database_t = Database; + using _parameter_tuple_t = std::tuple; using _parameter_list_t = typename make_parameter_list_t::type; - auto default_values() - -> use_default_values_t - { - static_assert(std::is_same::value, "cannot call default_values() after set() or default_values()"); - static_assert(vendor::is_noop::value, "cannot call default_values() after columns()"); - static_assert(Table::_required_insert_columns::size::value == 0, "cannot use default_values, because some columns are configured to require values"); - return { - _table, - {}, - _column_list, - _value_list, - }; - } + insert_t() + {} - template - auto set(Assignment... assignment) - -> set_insert_list_t> - { - static_assert(std::is_same::value, "cannot call set() after set() or default_values()"); - static_assert(vendor::is_noop::value, "cannot call set() after columns()"); - // FIXME: Need to check if all required columns are set - return { - _table, - vendor::insert_list_t{assignment...}, - _column_list, - _value_list, - }; - } + template + insert_t(insert_t i, Whatever whatever): + vendor::policy_t(i, whatever)... + {} - template - auto dynamic_set(Assignment... assignment) - -> set_insert_list_t> - { - static_assert(std::is_same::value, "cannot call set() after set() or default_values()"); - static_assert(vendor::is_noop::value, "cannot call set() after columns()"); - return { - _table, - vendor::insert_list_t{assignment...}, - _column_list, - _value_list, - }; - } + template + insert_t(Insert i, Whatever whatever): + vendor::policy_t(i, whatever)... + {} - template - insert_t add_set(Assignment assignment) - { - static_assert(is_dynamic_t::value, "cannot call add_set() in a non-dynamic set"); - - _insert_list.add(assignment); - - return *this; - } - - template - auto columns(Column... columns) - -> set_column_value_list_t, vendor::insert_value_list_t...>> - { - static_assert(vendor::is_noop::value, "cannot call columns() twice"); - static_assert(vendor::is_noop::value, "cannot call columns() after set() or dynamic_set()"); - // FIXME: Need to check if all required columns are set - - return { - _table, - _insert_list, - {std::tuple...>{{columns}...}}, - vendor::insert_value_list_t...>{}, - }; - } - - template - insert_t& add_values(Value... values) - { - static_assert(is_insert_value_list_t::value, "cannot call add_values() before columns()"); - _value_list.add(typename ValueList::_value_tuple_t{values...}); - return *this; - }; + insert_t(const insert_t&) = default; + insert_t(insert_t&&) = default; + insert_t& operator=(const insert_t&) = default; + insert_t& operator=(insert_t&&) = default; + ~insert_t() = default; static constexpr size_t _get_static_no_of_parameters() { @@ -153,8 +95,8 @@ namespace sqlpp template std::size_t _run(Db& db) const { - static_assert(not (vendor::is_noop::value and vendor::is_noop::value) , "calling set() or default_values()"); static_assert(_get_static_no_of_parameters() == 0, "cannot run insert directly with parameters, use prepare instead"); + static_assert(detail::check_insert_t::value, "Cannot run this insert expression"); return db.insert(*this); } @@ -162,60 +104,43 @@ namespace sqlpp auto _prepare(Db& db) const -> prepared_insert_t { - constexpr bool calledSet = not vendor::is_noop::value; - constexpr bool requireSet = Table::_required_insert_columns::size::value > 0; - static_assert(calledSet or not requireSet, "calling set() required for given table"); - + static_assert(detail::check_insert_t::value, "Cannot prepare this insert expression"); return {{}, db.prepare_insert(*this)}; } - - Table _table; - InsertList _insert_list; - ColumnList _column_list; - ValueList _value_list; }; namespace vendor { - template - struct interpreter_t> + template + struct interpreter_t> { - using T = insert_t; + using T = insert_t; static Context& _(const T& t, Context& context) { - if (not vendor::is_noop::value) - { - context << "INSERT INTO "; - interpret(t._table, context); - interpret(t._insert_list, context); - } - else if (not t._value_list.empty()) - { - context << "INSERT INTO "; - interpret(t._table, context); - interpret(t._column_list, context); - interpret(t._value_list, context); - } - else - { - context << "# empty insert"; - } + context << "INSERT INTO "; + interpret(t._single_table(), context); + interpret(t._insert_value_list(), context); return context; } }; } + template + using blank_insert_t = insert_t; + template - insert_t insert_into(Table table) + constexpr auto insert_into(Table table) + -> insert_t, vendor::no_insert_value_list_t> { - return {table}; + return { blank_insert_t(), vendor::single_table_t{table} }; } template - insert_t dynamic_insert_into(const Database& db, Table table) + constexpr auto dynamic_insert_into(const Database&, Table table) + -> insert_t, vendor::no_insert_value_list_t> { - return {table}; + return { blank_insert_t(), vendor::single_table_t{table} }; } } diff --git a/include/sqlpp11/remove.h b/include/sqlpp11/remove.h index d7601bc8..5d097838 100644 --- a/include/sqlpp11/remove.h +++ b/include/sqlpp11/remove.h @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include @@ -42,7 +42,7 @@ namespace sqlpp { namespace detail { - template + template struct check_remove_t { static_assert(is_where_t::value, "cannot run remove without having a where condition, use .where(true) to remove all rows"); @@ -73,10 +73,10 @@ namespace sqlpp vendor::policy_t(r, whatever)... {} - remove_t(const remove_t& r) = default; - remove_t(remove_t&& r) = default; - remove_t& operator=(const remove_t& r) = default; - remove_t& operator=(remove_t&& r) = default; + remove_t(const remove_t&) = default; + remove_t(remove_t&&) = default; + remove_t& operator=(const remove_t&) = default; + remove_t& operator=(remove_t&&) = default; ~remove_t() = default; static constexpr size_t _get_static_no_of_parameters() @@ -93,7 +93,7 @@ namespace sqlpp std::size_t _run(Db& db) const { static_assert(_get_static_no_of_parameters() == 0, "cannot run remove directly with parameters, use prepare instead"); - static_assert(detail::check_remove_t::value, "Cannot run this expression"); + static_assert(detail::check_remove_t::value, "Cannot run this remove expression"); return db.remove(*this); } @@ -101,7 +101,7 @@ namespace sqlpp auto _prepare(Db& db) const -> prepared_remove_t { - static_assert(detail::check_remove_t::value, "Cannot run this expression"); + static_assert(detail::check_remove_t::value, "Cannot run this remove expression"); return {{}, db.prepare_remove(*this)}; } }; @@ -115,8 +115,8 @@ namespace sqlpp static Context& _(const T& t, Context& context) { - context << "DELETE"; - interpret(t._from(), context); + context << "DELETE FROM"; + interpret(t._single_table(), context); interpret(t._using(), context); interpret(t._where(), context); return context; @@ -125,18 +125,20 @@ namespace sqlpp } template - using blank_remove_t = remove_t; + using blank_remove_t = remove_t; template - constexpr remove_t, vendor::no_using_t, vendor::no_where_t> remove_from(Table table) + constexpr auto remove_from(Table table) + -> remove_t, vendor::no_using_t, vendor::no_where_t> { - return { blank_remove_t(), vendor::from_t{table} }; + return { blank_remove_t(), vendor::single_table_t{table} }; } template - constexpr remove_t, vendor::no_using_t, vendor::no_where_t> dynamic_remove_from(const Database&, Table table) + constexpr auto dynamic_remove_from(const Database&, Table table) + -> remove_t, vendor::no_using_t, vendor::no_where_t> { - return { blank_remove_t(), vendor::from_t{table} }; + return { blank_remove_t(), vendor::single_table_t{table} }; } } diff --git a/include/sqlpp11/vendor/insert_list.h b/include/sqlpp11/vendor/insert_list.h deleted file mode 100644 index 2d30390f..00000000 --- a/include/sqlpp11/vendor/insert_list.h +++ /dev/null @@ -1,141 +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_INSERT_LIST_H -#define SQLPP_INSERT_LIST_H - -#include -#include -#include -#include -#include - -namespace sqlpp -{ - namespace vendor - { - struct insert_default_values_t - { - using _is_insert_list = std::true_type; - using _is_dynamic = std::false_type; - }; - - template - struct interpreter_t - { - using T = insert_default_values_t; - - static Context& _(const T& t, Context& context) - { - context << " DEFAULT VALUES"; - return context; - } - }; - - template - struct insert_list_t - { - using _is_insert_list = std::true_type; - using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - using _parameter_tuple_t = std::tuple; - template class Target> - using copy_assignments_t = Target; // FIXME: Nice idea to copy variadic template arguments? - template class Target, template class Wrap> - using copy_wrapped_assignments_t = Target...>; - - // check for at least one order expression - static_assert(_is_dynamic::value or sizeof...(Assignments), "at least one select expression required in set()"); - - // check for duplicate assignments - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in set()"); - - // check for invalid assignments - static_assert(sqlpp::detail::and_t::value, "at least one argument is not an assignment in set()"); - - // check for prohibited assignments - static_assert(not sqlpp::detail::or_t::value, "at least one assignment is prohibited by its column definition in set()"); - - insert_list_t(Assignments... assignment): - _assignments(assignment...), - _columns({assignment._lhs}...), - _values(assignment._rhs...) - {} - - insert_list_t(const insert_list_t&) = default; - insert_list_t(insert_list_t&&) = default; - insert_list_t& operator=(const insert_list_t&) = default; - insert_list_t& operator=(insert_list_t&&) = default; - ~insert_list_t() = default; - - template - void add(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"); - _dynamic_columns.emplace_back(simple_column_t{assignment._lhs}); - _dynamic_values.emplace_back(assignment._rhs); - } - - - std::tuple...> _columns; - std::tuple _values; - std::tuple _assignments; // FIXME: Need to replace _columns and _values by _assignments (connector-container requires assignments) - typename vendor::interpretable_list_t _dynamic_columns; - typename vendor::interpretable_list_t _dynamic_values; - }; - - template - struct interpreter_t> - { - using T = insert_list_t; - - static Context& _(const T& t, Context& context) - { - if (sizeof...(Assignments) + t._dynamic_columns.size() == 0) - { - interpret(insert_default_values_t(), context); - } - else - { - context << " ("; - interpret_tuple(t._columns, ",", context); - if (sizeof...(Assignments) and not t._dynamic_columns.empty()) - context << ','; - interpret_list(t._dynamic_columns, ',', context); - context << ") VALUES("; - interpret_tuple(t._values, ",", context); - if (sizeof...(Assignments) and not t._dynamic_values.empty()) - context << ','; - interpret_list(t._dynamic_values, ',', context); - context << ")"; - } - return context; - } - }; - } -} - -#endif diff --git a/include/sqlpp11/vendor/insert_value_list.h b/include/sqlpp11/vendor/insert_value_list.h index 76fc1552..5d750be6 100644 --- a/include/sqlpp11/vendor/insert_value_list.h +++ b/include/sqlpp11/vendor/insert_value_list.h @@ -29,28 +29,102 @@ #include #include -#include #include +#include +#include +#include +#include namespace sqlpp { namespace vendor { - template - struct insert_value_list_t + // COLUMN AND VALUE LIST + struct insert_default_values_t + { + using _is_insert_list = std::true_type; + using _is_dynamic = std::false_type; + const insert_default_values_t& _insert_value_list() const { return *this; } + }; + + template + struct insert_list_t { - using _is_insert_value_list = std::true_type; + using _is_insert_list = std::true_type; + using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; + using _parameter_tuple_t = std::tuple; + template class Target> + using copy_assignments_t = Target; // FIXME: Nice idea to copy variadic template arguments? + template class Target, template class Wrap> + using copy_wrapped_assignments_t = Target...>; - static_assert(sizeof...(InsertValues), "at least one insert value required"); + static_assert(_is_dynamic::value or sizeof...(Assignments), "at least one select expression required in set()"); - // check for invalid arguments - static_assert(::sqlpp::detail::and_t::value, "at least one argument is not an insert value"); + static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in set()"); - using _value_tuple_t = std::tuple; + static_assert(sqlpp::detail::and_t::value, "at least one argument is not an assignment in set()"); - void add(_value_tuple_t value_tuple) + static_assert(not sqlpp::detail::or_t::value, "at least one assignment is prohibited by its column definition in set()"); + + insert_list_t(Assignments... assignment): + _assignments(assignment...), + _columns({assignment._lhs}...), + _values(assignment._rhs...) + {} + + insert_list_t(const insert_list_t&) = default; + insert_list_t(insert_list_t&&) = default; + insert_list_t& operator=(const insert_list_t&) = default; + insert_list_t& operator=(insert_list_t&&) = default; + ~insert_list_t() = default; + + template + void add_set(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"); + _dynamic_columns.emplace_back(simple_column_t{assignment._lhs}); + _dynamic_values.emplace_back(assignment._rhs); + } + + + const insert_list_t& _insert_value_list() const { return *this; } + std::tuple...> _columns; + std::tuple _values; + std::tuple _assignments; // FIXME: Need to replace _columns and _values by _assignments (connector-container requires assignments) + typename vendor::interpretable_list_t _dynamic_columns; + typename vendor::interpretable_list_t _dynamic_values; + }; + + template + struct column_list_t + { + using _is_column_list = std::true_type; + using _parameter_tuple_t = std::tuple; + + static_assert(sizeof...(Columns), "at least one column required in columns()"); + + static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in columns()"); + + static_assert(::sqlpp::detail::and_t::value, "at least one argument is not a column in columns()"); + + static_assert(not ::sqlpp::detail::or_t::value, "at least one column argument has a must_not_insert flag in its definition"); + + using _value_tuple_t = std::tuple...>; + + column_list_t(Columns... columns): + _columns(simple_column_t{columns}...) + {} + + column_list_t(const column_list_t&) = default; + column_list_t(column_list_t&&) = default; + column_list_t& operator=(const column_list_t&) = default; + column_list_t& operator=(column_list_t&&) = default; + ~column_list_t() = default; + + void add_values(vendor::insert_value_t... values) { - _insert_values.emplace_back(value_tuple); + _insert_values.emplace_back(values...); } bool empty() const @@ -58,33 +132,95 @@ namespace sqlpp return _insert_values.empty(); } + const column_list_t& _insert_value_list() const { return *this; } + std::tuple...> _columns; std::vector<_value_tuple_t> _insert_values; }; - template<> - struct insert_value_list_t + struct no_insert_value_list_t + { + using _is_insert_value_list = std::true_type; + const no_insert_value_list_t& _insert_value_list() const { return *this; } + }; + + // CRTP Wrappers + template + struct crtp_wrapper_t { - using _is_insert_value_list = std::true_type; - - using _value_tuple_t = std::tuple<>; - - void add(_value_tuple_t value_tuple) - { - } - - static constexpr bool empty() - { - return true; - } }; - template - struct interpreter_t> + template + struct crtp_wrapper_t> { - using T = insert_value_list_t; + }; + + template + struct crtp_wrapper_t> + { + }; + + template + struct crtp_wrapper_t + { + template + struct delayed_t + { + using type = Derived; + }; + + template + auto default_values() + -> vendor::update_policies_t::type, no_insert_value_list_t, insert_default_values_t> + { + return { static_cast(*this), insert_default_values_t{} }; + } + + template + auto columns(Args... args) + -> vendor::update_policies_t> + { + return { static_cast(*this), column_list_t(args...) }; + } + + template + auto set(Args... args) + -> vendor::update_policies_t> + { + return { static_cast(*this), insert_list_t(args...) }; + } + + template + auto dynamic_set(Args... args) + -> vendor::update_policies_t, Args...>> + { + static_assert(not std::is_same, void>::value, "dynamic_insert_list must not be called in a static statement"); + return { static_cast(*this), insert_list_t, Args...>(args...) }; + } + }; + + // Interpreters + template + struct interpreter_t + { + using T = insert_default_values_t; static Context& _(const T& t, Context& context) { + context << " DEFAULT VALUES"; + return context; + } + }; + + template + struct interpreter_t> + { + using T = column_list_t; + + static Context& _(const T& t, Context& context) + { + context << " ("; + interpret_tuple(t._columns, ",", context); + context << ")"; context << " VALUES "; bool first = true; for (const auto& row : t._insert_values) @@ -97,20 +233,51 @@ namespace sqlpp interpret_tuple(row, ",", context); context << ')'; } + + return context; + } + }; + + template + struct interpreter_t> + { + using T = insert_list_t; + + static Context& _(const T& t, Context& context) + { + if (sizeof...(Assignments) + t._dynamic_columns.size() == 0) + { + interpret(insert_default_values_t(), context); + } + else + { + context << " ("; + interpret_tuple(t._columns, ",", context); + if (sizeof...(Assignments) and not t._dynamic_columns.empty()) + context << ','; + interpret_list(t._dynamic_columns, ',', context); + context << ") VALUES("; + interpret_tuple(t._values, ",", context); + if (sizeof...(Assignments) and not t._dynamic_values.empty()) + context << ','; + interpret_list(t._dynamic_values, ',', context); + context << ")"; + } return context; } }; template - struct interpreter_t> + struct interpreter_t { - using T = insert_value_list_t; + using T = no_insert_value_list_t; static Context& _(const T& t, Context& context) { return context; } }; + } } diff --git a/include/sqlpp11/vendor/column_list.h b/include/sqlpp11/vendor/single_table.h similarity index 52% rename from include/sqlpp11/vendor/column_list.h rename to include/sqlpp11/vendor/single_table.h index e8bbdb9a..eb77b0cf 100644 --- a/include/sqlpp11/vendor/column_list.h +++ b/include/sqlpp11/vendor/single_table.h @@ -24,53 +24,70 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SQLPP_COLUMN_LIST_H -#define SQLPP_COLUMN_LIST_H +#ifndef SQLPP_VENDOR_SINGLE_TABLE_H +#define SQLPP_VENDOR_SINGLE_TABLE_H #include -#include -#include -#include +#include +#include +#include // FIXME: REMOVE namespace sqlpp { namespace vendor { - template - struct column_list_t + // A SINGLE TABLE + template + struct single_table_t { - using _is_column_list = std::true_type; - using _parameter_tuple_t = std::tuple; + using _is_single_table = std::true_type; - // check for at least one order column - static_assert(sizeof...(Columns), "at least one column required in columns()"); + static_assert(is_table_t
::value, "argument has to be a table"); - // check for duplicate columns - static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in columns()"); + single_table_t(Table table): + _table(table) + {} - // check for invalid columns - static_assert(::sqlpp::detail::and_t::value, "at least one argument is not a column in columns()"); + single_table_t(const single_table_t&) = default; + single_table_t(single_table_t&&) = default; + single_table_t& operator=(const single_table_t&) = default; + single_table_t& operator=(single_table_t&&) = default; + ~single_table_t() = default; - // check for prohibited columns - static_assert(not ::sqlpp::detail::or_t::value, "at least one column argument has a must_not_insert flag in its definition"); - - std::tuple...> _columns; + const single_table_t& _single_table() const { return *this; } + Table _table; }; - template - struct interpreter_t> + struct no_single_table_t + { + using _is_single_table = std::true_type; + const no_single_table_t& _single_table() const { return *this; } + }; + + // CRTP Wrappers + template + struct crtp_wrapper_t> { - using T = column_list_t; + }; + + template + struct crtp_wrapper_t + { + }; + + // Interpreters + template + struct interpreter_t> + { + using T = single_table_t; static Context& _(const T& t, Context& context) { - context << " ("; - interpret_tuple(t._columns, ",", context); - context << ")"; - + interpret(t._table, context); return context; } }; + } } diff --git a/tests/InterpretTest.cpp b/tests/InterpretTest.cpp index f8a7e208..d5bf6377 100644 --- a/tests/InterpretTest.cpp +++ b/tests/InterpretTest.cpp @@ -43,18 +43,19 @@ int main() test::TabFoo f; test::TabBar t; - /* interpret(insert_into(t).columns(t.gamma, t.beta), printer).flush(); - interpret(insert_into(t).columns(t.gamma, t.beta).add_values(t.gamma = true, t.beta = "cheesecake"), printer).flush(); - interpret(insert_into(t).columns(t.gamma, t.beta) - .add_values(t.gamma = true, t.beta = "cheesecake") - .add_values(t.gamma = false, t.beta = sqlpp::tvin("coffee")) - .add_values(t.gamma = false, t.beta = sqlpp::tvin(std::string())) - , printer).flush(); - interpret(insert_into(t).columns(t.gamma, t.beta) - .add_values(t.gamma = sqlpp::default_value, t.beta = sqlpp::null) - , printer).flush(); + { + auto i = insert_into(t).columns(t.gamma, t.beta); + i.add_values(t.gamma = true, t.beta = "cheesecake"); + interpret(i, printer).flush(); + i.add_values(t.gamma = false, t.beta = sqlpp::tvin("coffee")); + i.add_values(t.gamma = false, t.beta = sqlpp::tvin(std::string())); + interpret(i, printer).flush(); + i.add_values(t.gamma = sqlpp::default_value, t.beta = sqlpp::null); + interpret(i, printer).flush(); + } + /* interpret(t.alpha = sqlpp::null, printer).flush(); interpret(t.alpha = sqlpp::default_value, printer).flush(); interpret(t.alpha, printer).flush(); @@ -87,12 +88,14 @@ int main() interpret(parameter(t.alpha), printer).flush(); interpret(t.alpha == parameter(t.alpha), printer).flush(); interpret(t.alpha == parameter(t.alpha) and (t.beta + "gimmick").like(parameter(t.beta)), printer).flush(); + */ interpret(insert_into(t), printer).flush(); interpret(insert_into(f).default_values(), printer).flush(); interpret(insert_into(t).set(t.gamma = true), printer).flush(); //interpret(insert_into(t).set(t.gamma = sqlpp::tvin(false)), printer).flush(); cannot test this since gamma cannot be null and a static assert is thrown + /* interpret(update(t), printer).flush(); interpret(update(t).set(t.gamma = true), printer).flush(); interpret(update(t).set(t.gamma = true).where(t.beta.in("kaesekuchen", "cheesecake")), printer).flush(); From 3c6e7cb89a9f1b08c1abf5e85aefd2b5be182aec Mon Sep 17 00:00:00 2001 From: rbock Date: Sat, 8 Feb 2014 22:24:05 +0100 Subject: [PATCH 10/74] Fixed a bunch of smaller migration errors --- include/sqlpp11/detail/copy_tuple_args.h | 2 +- include/sqlpp11/insert.h | 4 +- include/sqlpp11/remove.h | 2 +- include/sqlpp11/update.h | 184 ++++++++--------------- include/sqlpp11/vendor/field.h | 2 +- include/sqlpp11/vendor/limit.h | 5 +- include/sqlpp11/vendor/offset.h | 5 +- include/sqlpp11/vendor/update_list.h | 62 +++++++- tests/CMakeLists.txt | 12 +- tests/InsertTest.cpp | 2 +- tests/InterpretTest.cpp | 11 +- tests/RemoveTest.cpp | 8 +- tests/SelectTest.cpp | 17 ++- tests/UpdateTest.cpp | 2 +- 14 files changed, 157 insertions(+), 161 deletions(-) diff --git a/include/sqlpp11/detail/copy_tuple_args.h b/include/sqlpp11/detail/copy_tuple_args.h index caac57d8..f41d2443 100644 --- a/include/sqlpp11/detail/copy_tuple_args.h +++ b/include/sqlpp11/detail/copy_tuple_args.h @@ -36,7 +36,7 @@ namespace sqlpp template struct as_tuple { - static std::tuple _(T t) { return { t }; }; + static std::tuple _(T t) { return std::tuple{ t }; }; }; template diff --git a/include/sqlpp11/insert.h b/include/sqlpp11/insert.h index f46459be..ccd4583b 100644 --- a/include/sqlpp11/insert.h +++ b/include/sqlpp11/insert.h @@ -44,7 +44,7 @@ namespace sqlpp { template< typename Table, - typename InsertValueList, + typename InsertValueList > struct check_insert_t { @@ -140,7 +140,7 @@ namespace sqlpp constexpr auto dynamic_insert_into(const Database&, Table table) -> insert_t, vendor::no_insert_value_list_t> { - return { blank_insert_t(), vendor::single_table_t{table} }; + return { blank_insert_t(), vendor::single_table_t{table} }; } } diff --git a/include/sqlpp11/remove.h b/include/sqlpp11/remove.h index 5d097838..d95fd883 100644 --- a/include/sqlpp11/remove.h +++ b/include/sqlpp11/remove.h @@ -138,7 +138,7 @@ namespace sqlpp constexpr auto dynamic_remove_from(const Database&, Table table) -> remove_t, vendor::no_using_t, vendor::no_where_t> { - return { blank_remove_t(), vendor::single_table_t{table} }; + return { blank_remove_t(), vendor::single_table_t{table} }; } } diff --git a/include/sqlpp11/update.h b/include/sqlpp11/update.h index bdc2860d..d50f7a9a 100644 --- a/include/sqlpp11/update.h +++ b/include/sqlpp11/update.h @@ -30,109 +30,57 @@ #include #include #include +#include #include #include #include +#include +#include +#include namespace sqlpp { - template< - typename Database = void, - typename Table = vendor::noop, - typename Assignments = vendor::noop, - typename Where = vendor::noop - > - struct update_t; - - template< - typename Database, - typename Table, - typename Assignments, - typename Where - > - struct update_t + namespace detail + { + template< + typename Table, + typename Assignments, + typename Where + > + struct check_update_t { - static_assert(vendor::is_noop
::value or is_table_t
::value, "invalid 'Table' argument"); - static_assert(vendor::is_noop::value or is_update_list_t::value, "invalid 'Assignments' arguments"); - static_assert(vendor::is_noop::value or is_where_t::value, "invalid 'Where' argument"); + static constexpr bool value = true; + }; + } - template - using set_assignments_t = update_t; - template - using set_where_t = update_t; + template + struct update_t: public vendor::policy_t..., public vendor::crtp_wrapper_t, Policies>... + { + template + using _policy_update_t = update_t...>; - using _parameter_tuple_t = std::tuple; + using _database_t = Database; + using _parameter_tuple_t = std::tuple; using _parameter_list_t = typename make_parameter_list_t::type; - template - auto set(Assignment... assignment) - -> set_assignments_t> - { - static_assert(vendor::is_noop::value, "cannot call set() twice"); - return { - _table, - {std::tuple{assignment...}}, - _where, - }; - } + update_t() + {} - template - auto dynamic_set(Assignment... assignment) - -> set_assignments_t> - { - static_assert(vendor::is_noop::value, "cannot call set() twice"); - return { - _table, - {std::tuple{assignment...}}, - _where, - }; - } + template + update_t(update_t r, Whatever whatever): + vendor::policy_t(r, whatever)... + {} - template - update_t& add_set(Assignment assignment) - { - static_assert(is_dynamic_t::value, "cannot call add_set() in a non-dynamic set"); + template + update_t(Remove r, Whatever whatever): + vendor::policy_t(r, whatever)... + {} - _assignments.add(assignment); - - return *this; - } - - template - auto where(Expr... expr) - -> set_where_t> - { - static_assert(not vendor::is_noop::value, "cannot call where() if set() hasn't been called yet"); - static_assert(vendor::is_noop::value, "cannot call where() twice"); - return { - _table, - _assignments, - {std::tuple{expr...}}, - }; - } - - template - auto dynamic_where(Expr... expr) - -> set_where_t> - { - static_assert(not vendor::is_noop::value, "cannot call where() if set() hasn't been called yet"); - static_assert(vendor::is_noop::value, "cannot call where() twice"); - return { - _table, - _assignments, - {std::tuple{expr...}}, - }; - } - - template - update_t& add_where(Expr expr) - { - static_assert(is_dynamic_t::value, "cannot call add_where() in a non-dynamic where"); - - _where.add(expr); - - return *this; - } + update_t(const update_t&) = default; + update_t(update_t&&) = default; + update_t& operator=(const update_t&) = default; + update_t& operator=(update_t&&) = default; + ~update_t() = default; static constexpr size_t _get_static_no_of_parameters() { @@ -147,59 +95,53 @@ namespace sqlpp template std::size_t _run(Db& db) const { - static_assert(not vendor::is_noop::value, "calling set() required before running update"); - static_assert(is_where_t::value, "cannot run update without having a where condition, use .where(true) to update all rows"); 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); } template auto _prepare(Db& db) const - -> prepared_update_t + -> prepared_update_t { - static_assert(not vendor::is_noop::value, "calling set() required before running update"); - + static_assert(detail::check_update_t::value, "Cannot run this update expression"); return {{}, db.prepare_update(*this)}; } - - Table _table; - Assignments _assignments; - Where _where; }; namespace vendor { - template - struct interpreter_t> - { - using T = update_t; + template + struct interpreter_t> + { + using T = update_t; - static Context& _(const T& t, Context& context) - { - context << "UPDATE "; - interpret(t._table, context); - interpret(t._assignments, context); - interpret(t._where, context); - return context; - } - }; + static Context& _(const T& t, Context& context) + { + context << "UPDATE "; + interpret(t._single_table(), context); + interpret(t._update_list(), context); + interpret(t._where(), context); + return context; + } + }; } + template + using blank_update_t = update_t; + template - constexpr update_t update(Table table) + constexpr auto update(Table table) + -> update_t, vendor::no_update_list_t, vendor::no_where_t> { - return {table}; + return { blank_update_t(), vendor::single_table_t{table} }; } - template - constexpr update_t dynamic_update(const Db&, Table table) + template + constexpr auto dynamic_update(const Database&, Table table) + -> update_t, vendor::no_update_list_t, vendor::no_where_t> { - return {table}; + return { blank_update_t(), vendor::single_table_t{table} }; } } diff --git a/include/sqlpp11/vendor/field.h b/include/sqlpp11/vendor/field.h index cf816b77..33dad90e 100644 --- a/include/sqlpp11/vendor/field.h +++ b/include/sqlpp11/vendor/field.h @@ -54,7 +54,7 @@ namespace sqlpp }; template - struct make_field_t_impl>> + struct make_field_t_impl> { using type = multi_field_t::type...>>; }; diff --git a/include/sqlpp11/vendor/limit.h b/include/sqlpp11/vendor/limit.h index bdae95fc..fbdaee20 100644 --- a/include/sqlpp11/vendor/limit.h +++ b/include/sqlpp11/vendor/limit.h @@ -84,7 +84,7 @@ namespace sqlpp void set_limit(Limit value) { using arg_t = typename wrap_operand::type; - _value = arg_t(value); + _value = arg_t{value}; _initialized = true; } @@ -147,7 +147,10 @@ namespace sqlpp static Context& _(const T& t, Context& context) { if (t._initialized) + { + context << " LIMIT "; interpret(t._value, context); + } return context; } }; diff --git a/include/sqlpp11/vendor/offset.h b/include/sqlpp11/vendor/offset.h index 1c839887..e5ca8d10 100644 --- a/include/sqlpp11/vendor/offset.h +++ b/include/sqlpp11/vendor/offset.h @@ -160,7 +160,10 @@ namespace sqlpp static Context& _(const T& t, Context& context) { if (t._initialized) - context << " OFFSET " << t._offset; + { + context << " OFFSET "; + interpret(t._value, context); + } return context; } }; diff --git a/include/sqlpp11/vendor/update_list.h b/include/sqlpp11/vendor/update_list.h index a58e92fd..8d620c27 100644 --- a/include/sqlpp11/vendor/update_list.h +++ b/include/sqlpp11/vendor/update_list.h @@ -36,6 +36,7 @@ namespace sqlpp { namespace vendor { + // UPDATE ASSIGNMENTS template struct update_list_t { @@ -43,30 +44,69 @@ namespace sqlpp using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; using _parameter_tuple_t = std::tuple; - // check for at least one order expression static_assert(_is_dynamic::value or sizeof...(Assignments), "at least one assignment expression required in set()"); - // check for duplicate assignments static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in set()"); - // check for invalid assignments static_assert(::sqlpp::detail::and_t::value, "at least one argument is not an assignment in set()"); - // check for prohibited assignments static_assert(not ::sqlpp::detail::or_t::value, "at least one assignment is prohibited by its column definition in set()"); + update_list_t(Assignments... assignments): + _assignments(assignments...) + {} + + update_list_t(const update_list_t&) = default; + update_list_t(update_list_t&&) = default; + update_list_t& operator=(const update_list_t&) = default; + update_list_t& operator=(update_list_t&&) = default; + ~update_list_t() = default; + template - void add(Assignment assignment) + void add_set(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"); _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; }; + struct no_update_list_t + { + using _is_update_list = 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> { @@ -82,6 +122,18 @@ namespace sqlpp return context; } }; + + template + struct interpreter_t + { + using T = no_update_list_t; + + static Context& _(const T& t, Context& context) + { + return context; + } + }; + } } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ef9f5c96..b2a56c15 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -7,12 +7,12 @@ macro (build_and_run arg) endmacro () 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(InsertTest) +build_and_run(RemoveTest) +build_and_run(UpdateTest) +build_and_run(SelectTest) +build_and_run(FunctionTest) +build_and_run(PreparedTest) find_package(PythonInterp REQUIRED) diff --git a/tests/InsertTest.cpp b/tests/InsertTest.cpp index a116d93c..6238d729 100644 --- a/tests/InsertTest.cpp +++ b/tests/InsertTest.cpp @@ -60,7 +60,7 @@ int main() interpret(insert_into(t), printer).flush(); interpret(insert_into(t).set(t.beta = "kirschauflauf"), printer).flush(); auto i = dynamic_insert_into(db, t).dynamic_set(); - i = i.add_set(t.beta = "kirschauflauf"); + i.add_set(t.beta = "kirschauflauf"); interpret(i, printer).flush(); return 0; diff --git a/tests/InterpretTest.cpp b/tests/InterpretTest.cpp index d5bf6377..b8f74d3d 100644 --- a/tests/InterpretTest.cpp +++ b/tests/InterpretTest.cpp @@ -55,7 +55,6 @@ int main() interpret(i, printer).flush(); } - /* interpret(t.alpha = sqlpp::null, printer).flush(); interpret(t.alpha = sqlpp::default_value, printer).flush(); interpret(t.alpha, printer).flush(); @@ -70,7 +69,6 @@ int main() interpret(t.gamma != sqlpp::tvin(false), printer).flush(); interpret(t.alpha == 7, printer).flush(); interpret(t.beta + "kaesekuchen", printer).flush(); - */ interpret(sqlpp::select(), printer).flush(); interpret(sqlpp::select().flags(sqlpp::distinct), printer).flush(); @@ -83,29 +81,24 @@ int main() interpret(select(t.alpha, t.beta).from(t).where(t.alpha == 3).group_by(t.gamma).having(t.beta.like("%kuchen")).order_by(t.beta.asc()), printer).flush(); interpret(select(t.alpha, t.beta).from(t).where(t.alpha == 3).group_by(t.gamma).having(t.beta.like("%kuchen")).order_by(t.beta.asc()).limit(17).offset(3), printer).flush(); - /* interpret(parameter(sqlpp::bigint(), t.alpha), printer).flush(); interpret(parameter(t.alpha), printer).flush(); interpret(t.alpha == parameter(t.alpha), printer).flush(); interpret(t.alpha == parameter(t.alpha) and (t.beta + "gimmick").like(parameter(t.beta)), printer).flush(); - */ interpret(insert_into(t), printer).flush(); interpret(insert_into(f).default_values(), printer).flush(); interpret(insert_into(t).set(t.gamma = true), printer).flush(); //interpret(insert_into(t).set(t.gamma = sqlpp::tvin(false)), printer).flush(); cannot test this since gamma cannot be null and a static assert is thrown - /* interpret(update(t), printer).flush(); interpret(update(t).set(t.gamma = true), printer).flush(); interpret(update(t).set(t.gamma = true).where(t.beta.in("kaesekuchen", "cheesecake")), printer).flush(); - */ interpret(remove_from(t), printer).flush(); interpret(remove_from(t).using_(t), printer).flush(); interpret(remove_from(t).where(t.alpha == sqlpp::tvin(0)), printer).flush(); interpret(remove_from(t).using_(t).where(t.alpha == sqlpp::tvin(0)), printer).flush(); - /* // functions sqlpp::interpret(sqlpp::value(7), printer).flush(); // FIXME: Why is the namespace specifier required? @@ -134,7 +127,6 @@ int main() interpret(t.inner_join(t.as(t.alpha)).on(t.beta == t.as(t.alpha).beta), printer).flush(); // multi_column - */ interpret(multi_column(t.alpha, t.alpha, (t.beta + "cake").as(t.gamma)), printer).flush(); interpret(multi_column(t, all_of(t)), printer).flush(); @@ -159,13 +151,12 @@ int main() s.add_column(t.gamma); interpret(s, printer).flush(); } - /* // distinct aggregate interpret(count(sqlpp::distinct, t.alpha % 7), printer).flush(); interpret(avg(sqlpp::distinct, t.alpha - 7), printer).flush(); interpret(sum(sqlpp::distinct, t.alpha + 7), printer).flush(); -*/ + interpret(select(all_of(t)).from(t).where(true), printer).flush(); interpret(select(all_of(t)).from(t).where(false), printer).flush(); return 0; diff --git a/tests/RemoveTest.cpp b/tests/RemoveTest.cpp index 616a2eaf..398943e6 100644 --- a/tests/RemoveTest.cpp +++ b/tests/RemoveTest.cpp @@ -53,16 +53,16 @@ int main() } { - using T = decltype(dynamic_remove_from(db, t).dynamic_using_().dynamic_where()); + using T = decltype(dynamic_remove_from(db, t).dynamic_using().dynamic_where()); static_assert(sqlpp::is_regular::value, "type requirement"); } interpret(remove_from(t), printer).flush(); interpret(remove_from(t).where(t.beta != "transparent"), printer).flush(); interpret(remove_from(t).using_(t), printer).flush(); - auto r = dynamic_remove_from(db, t).dynamic_using_().dynamic_where(); - r = r.add_using_(t); - r = r.add_where(t.beta != "transparent"); + auto r = dynamic_remove_from(db, t).dynamic_using().dynamic_where(); + r.add_using(t); + r.add_where(t.beta != "transparent"); interpret(r, printer).flush(); return 0; diff --git a/tests/SelectTest.cpp b/tests/SelectTest.cpp index 94b2b790..8ff93911 100644 --- a/tests/SelectTest.cpp +++ b/tests/SelectTest.cpp @@ -159,6 +159,8 @@ int main() // Test a select of a single column without a from { using T = decltype(select(t.alpha)); // Hint: The current rule is pretty crude (a from is required), but certainly better than nothing +#warning Need to reactivate these tests + /* static_assert(not sqlpp::is_numeric_t::value, "type requirement"); static_assert(not sqlpp::is_expression_t::value, "type requirement"); static_assert(not sqlpp::is_named_expression_t::value, "type requirement"); @@ -170,6 +172,7 @@ int main() static_assert(not sqlpp::is_alias_t::value, "type requirement"); static_assert(not sqlpp::is_table_t::value, "type requirement"); static_assert(sqlpp::is_regular::value, "type requirement"); + */ } // Test a select of a single numeric table column @@ -297,7 +300,6 @@ int main() auto a = select(m).from(t).as(alias::b).a; static_assert(not sqlpp::is_value_t::value, "a multi_column is not a value"); } - // Test that result sets with identical name/value combinations have identical types { auto a = select(t.alpha); @@ -312,10 +314,10 @@ int main() { auto s = dynamic_select(db, all_of(t)).dynamic_from().dynamic_where().dynamic_limit().dynamic_offset(); - s = s.add_from(t); - s = s.add_where(t.alpha > 7 and t.alpha == any(select(t.alpha).from(t).where(t.alpha < 3))); - s = s.set_limit(30); - s = s.set_limit(3); + s.add_from(t); + s.add_where(t.alpha > 7 and t.alpha == any(select(t.alpha).from(t).where(t.alpha < 3))); + s.set_limit(30); + s.set_limit(3); std::cerr << "------------------------\n"; interpret(s, printer).flush(); std::cerr << "------------------------\n"; @@ -325,7 +327,8 @@ int main() // Test that select can be called with zero columns if it is used with dynamic columns. { - auto s = dynamic_select(db).dynamic_columns().add_column(t.alpha); + auto s = dynamic_select(db).dynamic_columns(); + s.add_column(t.alpha); interpret(s, printer).flush(); } @@ -360,6 +363,7 @@ int main() auto z = select(t.alpha) == 7; auto l = t.as(alias::left); auto r = select(t.gamma.as(alias::a)).from(t).where(t.gamma == true).as(alias::right); +#if 0 static_assert(sqlpp::is_boolean_t::value, "select(bool) has to be a bool"); interpret(select(sqlpp::distinct, sqlpp::straight_join, l.alpha, l.beta, select(r.a).from(r)) .from(l, r) @@ -371,6 +375,7 @@ int main() .offset(3) .as(alias::a) , printer).flush(); +#endif return 0; } diff --git a/tests/UpdateTest.cpp b/tests/UpdateTest.cpp index a46c3dbd..a4f07fe4 100644 --- a/tests/UpdateTest.cpp +++ b/tests/UpdateTest.cpp @@ -59,7 +59,7 @@ int main() interpret(update(t).set(t.gamma = false), printer).flush(); interpret(update(t).set(t.gamma = false).where(t.beta != "transparent"), printer).flush(); auto u = dynamic_update(db, t).dynamic_set(t.gamma = false).dynamic_where(); - u = u.add_set(t.gamma = false); + u.add_set(t.gamma = false); interpret(u, printer).flush(); return 0; From 88fc0959b5e8fe82b38170f3b9eaad4ce3a5daf7 Mon Sep 17 00:00:00 2001 From: rbock Date: Sat, 8 Feb 2014 22:50:26 +0100 Subject: [PATCH 11/74] Added value type back to select --- include/sqlpp11/select.h | 3 ++- tests/SelectTest.cpp | 4 +--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 7c6ba00d..652c12cf 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -86,7 +86,8 @@ namespace sqlpp // SELECT template - struct select_t: public vendor::policy_t..., public vendor::crtp_wrapper_t, Policies>... + struct select_t: public vendor::policy_t..., public vendor::crtp_wrapper_t, Policies>..., + public detail::select_helper_t::_column_list_t::_value_type::template operators> { template using _policy_update_t = select_t...>; diff --git a/tests/SelectTest.cpp b/tests/SelectTest.cpp index 8ff93911..9172920c 100644 --- a/tests/SelectTest.cpp +++ b/tests/SelectTest.cpp @@ -363,9 +363,8 @@ int main() auto z = select(t.alpha) == 7; auto l = t.as(alias::left); auto r = select(t.gamma.as(alias::a)).from(t).where(t.gamma == true).as(alias::right); -#if 0 static_assert(sqlpp::is_boolean_t::value, "select(bool) has to be a bool"); - interpret(select(sqlpp::distinct, sqlpp::straight_join, l.alpha, l.beta, select(r.a).from(r)) + interpret(sqlpp::select().flags(sqlpp::distinct, sqlpp::straight_join).columns(l.alpha, l.beta, select(r.a).from(r)) .from(l, r) .where(t.beta == "hello world" and select(t.gamma).from(t))// .as(alias::right)) .group_by(l.gamma, r.a) @@ -375,7 +374,6 @@ int main() .offset(3) .as(alias::a) , printer).flush(); -#endif return 0; } From 61ed1d9f37a9938114d6053e3725349b5729cb52 Mon Sep 17 00:00:00 2001 From: rbock Date: Sat, 8 Feb 2014 23:48:35 +0100 Subject: [PATCH 12/74] Corrected inconsistency in select value_type --- include/sqlpp11/select.h | 11 ++++++++--- include/sqlpp11/vendor/from.h | 1 - tests/SelectTest.cpp | 5 +---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 652c12cf..27408cff 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -69,6 +69,12 @@ namespace sqlpp { using _column_list_t = ColumnList; using _from_t = ColumnList; + + 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 { @@ -87,7 +93,7 @@ namespace sqlpp // SELECT template struct select_t: public vendor::policy_t..., public vendor::crtp_wrapper_t, Policies>..., - public detail::select_helper_t::_column_list_t::_value_type::template operators> + public detail::select_helper_t::_value_type::template operators> { template using _policy_update_t = select_t...>; @@ -103,8 +109,7 @@ namespace sqlpp using _is_select = std::true_type; using _requires_braces = std::true_type; - // FIXME: introduce checks whether this select could really be used as a value - using _value_type = typename _column_list_t::_value_type; + using _value_type = typename detail::select_helper_t::_value_type; using _name_t = typename _column_list_t::_name_t; select_t() diff --git a/include/sqlpp11/vendor/from.h b/include/sqlpp11/vendor/from.h index 8cdfa710..e94a8c5f 100644 --- a/include/sqlpp11/vendor/from.h +++ b/include/sqlpp11/vendor/from.h @@ -79,7 +79,6 @@ namespace sqlpp struct no_from_t { - using _is_from = std::true_type; const no_from_t& _from() const { return *this; } }; diff --git a/tests/SelectTest.cpp b/tests/SelectTest.cpp index 9172920c..4f030c75 100644 --- a/tests/SelectTest.cpp +++ b/tests/SelectTest.cpp @@ -159,8 +159,6 @@ int main() // Test a select of a single column without a from { using T = decltype(select(t.alpha)); // Hint: The current rule is pretty crude (a from is required), but certainly better than nothing -#warning Need to reactivate these tests - /* static_assert(not sqlpp::is_numeric_t::value, "type requirement"); static_assert(not sqlpp::is_expression_t::value, "type requirement"); static_assert(not sqlpp::is_named_expression_t::value, "type requirement"); @@ -172,7 +170,6 @@ int main() static_assert(not sqlpp::is_alias_t::value, "type requirement"); static_assert(not sqlpp::is_table_t::value, "type requirement"); static_assert(sqlpp::is_regular::value, "type requirement"); - */ } // Test a select of a single numeric table column @@ -360,7 +357,7 @@ int main() static_assert(sqlpp::is_named_expression_t::value, "alpha should be a named expression"); static_assert(sqlpp::is_named_expression_t::value, "an alias of alpha should be a named expression"); static_assert(sqlpp::is_alias_t::value, "an alias of alpha should be an alias"); - auto z = select(t.alpha) == 7; + auto z = select(t.alpha).from(t) == 7; auto l = t.as(alias::left); auto r = select(t.gamma.as(alias::a)).from(t).where(t.gamma == true).as(alias::right); static_assert(sqlpp::is_boolean_t::value, "select(bool) has to be a bool"); From ae2f1948ac3f1c03151bfcf6583052db7745a0e8 Mon Sep 17 00:00:00 2001 From: rbock Date: Sun, 9 Feb 2014 15:06:42 +0100 Subject: [PATCH 13/74] Added checks to prevent non-matching columns from being inserted --- include/sqlpp11/column.h | 2 + include/sqlpp11/detail/type_set.h | 69 ++++++++++++++++------ include/sqlpp11/insert.h | 3 + include/sqlpp11/vendor/from.h | 4 +- include/sqlpp11/vendor/insert_value_list.h | 9 ++- include/sqlpp11/vendor/single_table.h | 5 +- include/sqlpp11/vendor/wrong.h | 20 +++---- tests/InterpretTest.cpp | 2 +- tests/sample.sql | 1 + 9 files changed, 80 insertions(+), 35 deletions(-) diff --git a/include/sqlpp11/column.h b/include/sqlpp11/column.h index 1e5de615..95c334bb 100644 --- a/include/sqlpp11/column.h +++ b/include/sqlpp11/column.h @@ -37,6 +37,7 @@ #include #include #include +#include namespace sqlpp { @@ -46,6 +47,7 @@ namespace sqlpp using _is_column = std::true_type; using _spec_t = ColumnSpec; using _table = Table; + using _table_set = detail::type_set<_table>; using _column_type = typename ColumnSpec::_column_type; struct _value_type: ColumnSpec::_value_type { diff --git a/include/sqlpp11/detail/type_set.h b/include/sqlpp11/detail/type_set.h index d367101f..e9b8d6e5 100644 --- a/include/sqlpp11/detail/type_set.h +++ b/include/sqlpp11/detail/type_set.h @@ -27,6 +27,7 @@ #ifndef SQLPP_DETAIL_TYPE_SET_H #define SQLPP_DETAIL_TYPE_SET_H +#include #include #include #include @@ -39,17 +40,21 @@ namespace sqlpp template struct make_set; - template - class type_set_element {}; - // A type set template - struct type_set: type_set_element... + struct type_set { - using size = std::integral_constant; + using _elements_t = std::tuple; + using size = std::tuple_size<_elements_t>; + using _is_type_set = std::true_type; template - using count = std::is_base_of, type_set>; + struct count + { + template + using same = std::is_same; + static constexpr bool value = or_t::value; + }; template struct is_superset_of @@ -59,7 +64,9 @@ namespace sqlpp template struct is_superset_of> - : and_t {}; + { + static constexpr bool value = and_t::value; + }; template struct join @@ -69,7 +76,9 @@ namespace sqlpp template struct join> - : make_set {}; + { + using type = typename make_set::type; + }; template struct is_subset_of @@ -79,7 +88,9 @@ namespace sqlpp template struct is_subset_of> - : type_set::template is_superset_of{}; + { + static constexpr bool value = type_set::template is_superset_of::value; + }; template struct is_disjunct_from @@ -93,16 +104,12 @@ namespace sqlpp static constexpr bool value = not(or_t::value or or_t::template count, Element...>::value); }; - template + template struct insert { - using type = type_set; - }; - - template - struct insert::value>::type> - { - using type = type_set; + using type = typename std::conditional::value, + type_set, + type_set>::type; }; template class Predicate, typename T> @@ -152,6 +159,34 @@ namespace sqlpp template using has_duplicates = std::integral_constant::type::size::value != sizeof...(T)>; + template + struct make_joined_set + { + static_assert(::sqlpp::vendor::wrong_t::value, "invalid argument for joined set"); + }; + + template<> + struct make_joined_set<> + { + using type = type_set<>; + }; + + /* + template + struct make_joined_set> + { + using type = type_set; + }; + */ + + template + struct make_joined_set, T...> + { + using _rest = typename make_joined_set::type; + + using type = typename type_set::template join<_rest>::type; + }; + } } diff --git a/include/sqlpp11/insert.h b/include/sqlpp11/insert.h index ccd4583b..e0c0f6b0 100644 --- a/include/sqlpp11/insert.h +++ b/include/sqlpp11/insert.h @@ -48,6 +48,7 @@ namespace sqlpp > struct check_insert_t { + static_assert(Table::_table_set::template is_superset_of::value, "inserted columns do not match the table in insert_into"); //static_assert(not (vendor::is_noop::value and vendor::is_noop::value) , "calling set() or default_values()"); static constexpr bool value = true; }; @@ -66,6 +67,8 @@ namespace sqlpp insert_t() {} + static_assert(detail::check_insert_t::value, "invalid insert_into"); + template insert_t(insert_t i, Whatever whatever): vendor::policy_t(i, whatever)... diff --git a/include/sqlpp11/vendor/from.h b/include/sqlpp11/vendor/from.h index e94a8c5f..c01f24e7 100644 --- a/include/sqlpp11/vendor/from.h +++ b/include/sqlpp11/vendor/from.h @@ -48,11 +48,13 @@ namespace sqlpp static_assert(_is_dynamic::value or sizeof...(Tables), "at least one table or join argument required in from()"); + // FIXME: Joins contain two tables. This is not being dealt with at the moment when looking at duplicates, for instance static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in from()"); static_assert(::sqlpp::detail::and_t::value, "at least one argument is not a table or join in from()"); - // FIXME: Joins contain two tables. This is not being dealt with at the moment when looking at duplicates, for instance + using _table_set = typename ::sqlpp::detail::make_joined_set; + from_t(Tables... tables): _tables(tables...) diff --git a/include/sqlpp11/vendor/insert_value_list.h b/include/sqlpp11/vendor/insert_value_list.h index 5d750be6..ac6586cb 100644 --- a/include/sqlpp11/vendor/insert_value_list.h +++ b/include/sqlpp11/vendor/insert_value_list.h @@ -43,6 +43,7 @@ namespace sqlpp struct insert_default_values_t { using _is_insert_list = std::true_type; + using _table_set = ::sqlpp::detail::type_set<>; using _is_dynamic = std::false_type; const insert_default_values_t& _insert_value_list() const { return *this; } }; @@ -66,6 +67,9 @@ 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::type; + static_assert(_is_dynamic::value ? (_table_set::size::value < 2) : (_table_set::size::value == 1), "set() contains assignments for tables from several columns"); + insert_list_t(Assignments... assignment): _assignments(assignment...), _columns({assignment._lhs}...), @@ -111,6 +115,9 @@ namespace sqlpp static_assert(not ::sqlpp::detail::or_t::value, "at least one column argument has a must_not_insert flag in its definition"); using _value_tuple_t = std::tuple...>; + using _table_set = typename ::sqlpp::detail::make_joined_set::type; + + static_assert(_table_set::size::value == 1, "columns from multiple tables in columns()"); column_list_t(Columns... columns): _columns(simple_column_t{columns}...) @@ -139,7 +146,7 @@ namespace sqlpp struct no_insert_value_list_t { - using _is_insert_value_list = std::true_type; + using _table_set = ::sqlpp::detail::type_set<>; const no_insert_value_list_t& _insert_value_list() const { return *this; } }; diff --git a/include/sqlpp11/vendor/single_table.h b/include/sqlpp11/vendor/single_table.h index eb77b0cf..2a728ea8 100644 --- a/include/sqlpp11/vendor/single_table.h +++ b/include/sqlpp11/vendor/single_table.h @@ -30,7 +30,7 @@ #include #include #include -#include // FIXME: REMOVE +#include namespace sqlpp { @@ -55,12 +55,13 @@ namespace sqlpp ~single_table_t() = default; const single_table_t& _single_table() const { return *this; } + using _table_set = typename Table::_table_set; Table _table; }; struct no_single_table_t { - using _is_single_table = std::true_type; + using _table_set = ::sqlpp::detail::type_set<>; const no_single_table_t& _single_table() const { return *this; } }; diff --git a/include/sqlpp11/vendor/wrong.h b/include/sqlpp11/vendor/wrong.h index a37462ba..5694fd6a 100644 --- a/include/sqlpp11/vendor/wrong.h +++ b/include/sqlpp11/vendor/wrong.h @@ -33,20 +33,14 @@ namespace sqlpp { namespace vendor { - namespace detail - { - // A template that always returns false - // To be used with static assert, for instance, to ensure it - // fires only when the template is instantiated. - template struct wrong_t - { - using type = std::false_type; - }; - } - + // A template that always returns false + // To be used with static assert, for instance, to ensure it + // fires only when the template is instantiated. template - using wrong_t = typename detail::wrong_t::type; + struct wrong_t + { + static constexpr bool value = false; + }; } - } #endif diff --git a/tests/InterpretTest.cpp b/tests/InterpretTest.cpp index b8f74d3d..9772e10f 100644 --- a/tests/InterpretTest.cpp +++ b/tests/InterpretTest.cpp @@ -43,7 +43,7 @@ int main() test::TabFoo f; test::TabBar t; - interpret(insert_into(t).columns(t.gamma, t.beta), printer).flush(); + interpret(insert_into(t).columns(t.beta, t.gamma), printer).flush(); { auto i = insert_into(t).columns(t.gamma, t.beta); i.add_values(t.gamma = true, t.beta = "cheesecake"); diff --git a/tests/sample.sql b/tests/sample.sql index 87e26c94..4fa7e01c 100644 --- a/tests/sample.sql +++ b/tests/sample.sql @@ -26,6 +26,7 @@ CREATE TABLE tab_foo ( + delta varchar(255), epsilon bigint, omega double ); From cc768208707c10bba7dae76780cbb76015e3b52c Mon Sep 17 00:00:00 2001 From: rbock Date: Sun, 9 Feb 2014 18:14:52 +0100 Subject: [PATCH 14/74] Migrated insert and remove back to composite design --- include/sqlpp11/insert.h | 127 ++++++++++++++------- include/sqlpp11/remove.h | 125 +++++++++++++++----- include/sqlpp11/type_traits.h | 1 + include/sqlpp11/vendor/insert_value_list.h | 74 ++---------- include/sqlpp11/vendor/noop.h | 1 + include/sqlpp11/vendor/single_table.h | 15 --- include/sqlpp11/vendor/using.h | 28 +---- include/sqlpp11/vendor/where.h | 40 +------ tests/CMakeLists.txt | 10 +- tests/InsertTest.cpp | 1 + tests/RemoveTest.cpp | 1 - 11 files changed, 210 insertions(+), 213 deletions(-) diff --git a/include/sqlpp11/insert.h b/include/sqlpp11/insert.h index e0c0f6b0..5aac9e34 100644 --- a/include/sqlpp11/insert.h +++ b/include/sqlpp11/insert.h @@ -34,49 +34,48 @@ #include #include #include -#include -#include #include namespace sqlpp { - namespace detail - { - template< - typename Table, - typename InsertValueList - > - struct check_insert_t - { - static_assert(Table::_table_set::template is_superset_of::value, "inserted columns do not match the table in insert_into"); - //static_assert(not (vendor::is_noop::value and vendor::is_noop::value) , "calling set() or default_values()"); - static constexpr bool value = true; - }; - } - - template - struct insert_t: public vendor::policy_t..., public vendor::crtp_wrapper_t, Policies>... + // INSERT + template + struct insert_t { - template - using _policy_update_t = insert_t...>; + static_assert(Table::_table_set::template is_superset_of::value, "inserted columns do not match the table in insert_into"); 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 = insert_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; + // Constructors insert_t() {} - static_assert(detail::check_insert_t::value, "invalid insert_into"); - - template - insert_t(insert_t i, Whatever whatever): - vendor::policy_t(i, whatever)... + template + insert_t(X x, Table table): + _table(table), + _insert_value_list(x._insert_value_list) {} - template - insert_t(Insert i, Whatever whatever): - vendor::policy_t(i, whatever)... + template + insert_t(X x, InsertValueList insert_value_list): + _table(x._table), + _insert_value_list(insert_value_list) {} insert_t(const insert_t&) = default; @@ -85,6 +84,56 @@ namespace sqlpp insert_t& operator=(insert_t&&) = default; ~insert_t() = default; + // type update functions + auto default_values() + -> _policies_update_t + { + static_assert(is_noop_t::value, "cannot combine default_values() with other methods"); + return { *this, vendor::insert_default_values_t{} }; + } + + template + auto columns(Args... args) + -> _policies_update_t> + { + static_assert(is_noop_t::value, "cannot combine columns() with other methods"); + return { *this, vendor::column_list_t(args...) }; + } + + template + auto set(Args... args) + -> _policies_update_t> + { + static_assert(is_noop_t::value, "cannot combine set() with other methods"); + return { *this, vendor::insert_list_t(args...) }; + } + + template + auto dynamic_set(Args... args) + -> _policies_update_t> + { + 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...) }; + } + + // value adding methods + template + void add_set(Args... args) + { + static_assert(is_insert_list_t::value, "cannot call add_set() before dynamic_set()"); + static_assert(is_dynamic_t::value, "cannot call add_set() before dynamic_set()"); + return _insert_value_list.add_set(*this, args...); + } + + template + 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...); + } + + // run and prepare static constexpr size_t _get_static_no_of_parameters() { return _parameter_list_t::size::value; @@ -99,7 +148,6 @@ namespace sqlpp std::size_t _run(Db& db) const { static_assert(_get_static_no_of_parameters() == 0, "cannot run insert directly with parameters, use prepare instead"); - static_assert(detail::check_insert_t::value, "Cannot run this insert expression"); return db.insert(*this); } @@ -107,9 +155,11 @@ namespace sqlpp auto _prepare(Db& db) const -> prepared_insert_t { - static_assert(detail::check_insert_t::value, "Cannot prepare this insert expression"); return {{}, db.prepare_insert(*this)}; } + + InsertValueList _insert_value_list; + Table _table; }; namespace vendor @@ -122,28 +172,25 @@ namespace sqlpp static Context& _(const T& t, Context& context) { context << "INSERT INTO "; - interpret(t._single_table(), context); - interpret(t._insert_value_list(), context); + interpret(t._table, context); + interpret(t._insert_value_list, context); return context; } }; } - template - using blank_insert_t = insert_t; - template constexpr auto insert_into(Table table) - -> insert_t, vendor::no_insert_value_list_t> + -> insert_t> { - return { blank_insert_t(), vendor::single_table_t{table} }; + return { insert_t(), vendor::single_table_t{table} }; } template constexpr auto dynamic_insert_into(const Database&, Table table) - -> insert_t, vendor::no_insert_value_list_t> + -> insert_t> { - return { blank_insert_t(), vendor::single_table_t{table} }; + return { insert_t(), vendor::single_table_t{table} }; } } diff --git a/include/sqlpp11/remove.h b/include/sqlpp11/remove.h index d95fd883..d9213f7c 100644 --- a/include/sqlpp11/remove.h +++ b/include/sqlpp11/remove.h @@ -34,8 +34,6 @@ #include #include #include -#include -#include #include namespace sqlpp @@ -50,27 +48,52 @@ namespace sqlpp }; } - template - struct remove_t: public vendor::policy_t..., public vendor::crtp_wrapper_t, Policies>... + // REMOVE + template + struct remove_t { - template - using _policy_update_t = remove_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 = remove_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; + // Constructors remove_t() {} - template - remove_t(remove_t r, Whatever whatever): - vendor::policy_t(r, whatever)... + template + remove_t(X x, Table table): + _table(table), + _using(x._using), + _where(x._where) {} - template - remove_t(Remove r, Whatever whatever): - vendor::policy_t(r, whatever)... + template + remove_t(X x, Using using_): + _table(x._table), + _using(using_), + _where(x._where) + {} + + template + remove_t(X x, Where where): + _table(x._table), + _using(x._using), + _where(where) {} remove_t(const remove_t&) = default; @@ -79,6 +102,55 @@ namespace sqlpp remove_t& operator=(remove_t&&) = default; ~remove_t() = default; + // type update functions + template + auto using_(Args... args) + -> _policies_update_t> + { + return { *this, vendor::using_t(args...) }; + } + + template + auto dynamic_using(Args... args) + -> _policies_update_t> + { + 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...) }; + } + + template + auto where(Args... args) + -> _policies_update_t> + { + return { *this, vendor::where_t(args...) }; + } + + template + auto dynamic_where(Args... args) + -> _policies_update_t> + { + 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_using(Args... args) + { + static_assert(is_using_t::value, "cannot call add_using() before dynamic_using()"); + static_assert(is_dynamic_t::value, "cannot call add_using() before dynamic_using()"); + return _using.add_using(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; @@ -93,7 +165,7 @@ namespace sqlpp std::size_t _run(Db& db) const { static_assert(_get_static_no_of_parameters() == 0, "cannot run remove directly with parameters, use prepare instead"); - static_assert(detail::check_remove_t::value, "Cannot run this remove expression"); + //static_assert(detail::check_remove_t::value, "Cannot run this remove expression"); return db.remove(*this); } @@ -101,9 +173,13 @@ namespace sqlpp auto _prepare(Db& db) const -> prepared_remove_t { - static_assert(detail::check_remove_t::value, "Cannot run this remove expression"); + //static_assert(detail::check_remove_t::value, "Cannot run this remove expression"); return {{}, db.prepare_remove(*this)}; } + + Table _table; + Using _using; + Where _where; }; namespace vendor @@ -116,29 +192,26 @@ namespace sqlpp static Context& _(const T& t, Context& context) { context << "DELETE FROM"; - interpret(t._single_table(), context); - interpret(t._using(), context); - interpret(t._where(), context); + interpret(t._table, context); + interpret(t._using, context); + interpret(t._where, context); return context; } }; } - template - using blank_remove_t = remove_t; - template constexpr auto remove_from(Table table) - -> remove_t, vendor::no_using_t, vendor::no_where_t> + -> remove_t> { - return { blank_remove_t(), vendor::single_table_t{table} }; + return { remove_t(), vendor::single_table_t{table} }; } template constexpr auto dynamic_remove_from(const Database&, Table table) - -> remove_t, vendor::no_using_t, vendor::no_where_t> + -> remove_t> { - return { blank_remove_t(), vendor::single_table_t{table} }; + return { remove_t(), vendor::single_table_t{table} }; } } diff --git a/include/sqlpp11/type_traits.h b/include/sqlpp11/type_traits.h index 83f74895..52f7f90b 100644 --- a/include/sqlpp11/type_traits.h +++ b/include/sqlpp11/type_traits.h @@ -93,6 +93,7 @@ namespace sqlpp SQLPP_IS_COLUMN_TRAIT_GENERATOR(require_insert); SQLPP_IS_COLUMN_TRAIT_GENERATOR(can_be_null); + SQLPP_TYPE_TRAIT_GENERATOR(is_noop); SQLPP_TYPE_TRAIT_GENERATOR(is_table); SQLPP_TYPE_TRAIT_GENERATOR(is_join); SQLPP_TYPE_TRAIT_GENERATOR(is_pseudo_table); diff --git a/include/sqlpp11/vendor/insert_value_list.h b/include/sqlpp11/vendor/insert_value_list.h index ac6586cb..22668b6a 100644 --- a/include/sqlpp11/vendor/insert_value_list.h +++ b/include/sqlpp11/vendor/insert_value_list.h @@ -32,8 +32,6 @@ #include #include #include -#include -#include namespace sqlpp { @@ -42,10 +40,8 @@ namespace sqlpp // COLUMN AND VALUE LIST struct insert_default_values_t { - using _is_insert_list = std::true_type; using _table_set = ::sqlpp::detail::type_set<>; using _is_dynamic = std::false_type; - const insert_default_values_t& _insert_value_list() const { return *this; } }; template @@ -82,8 +78,8 @@ namespace sqlpp insert_list_t& operator=(insert_list_t&&) = default; ~insert_list_t() = default; - template - void add_set(Assignment assignment) + 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"); @@ -92,7 +88,6 @@ namespace sqlpp } - const insert_list_t& _insert_value_list() const { return *this; } std::tuple...> _columns; std::tuple _values; std::tuple _assignments; // FIXME: Need to replace _columns and _values by _assignments (connector-container requires assignments) @@ -139,72 +134,23 @@ namespace sqlpp return _insert_values.empty(); } - const column_list_t& _insert_value_list() const { return *this; } std::tuple...> _columns; std::vector<_value_tuple_t> _insert_values; }; struct no_insert_value_list_t { + using _is_noop = std::true_type; using _table_set = ::sqlpp::detail::type_set<>; - const no_insert_value_list_t& _insert_value_list() const { return *this; } + + template + void add_values(Base base, Args...) + { + static_assert(wrong_t::value, "cannot call add_values() without calling columns() first"); + } + }; - // CRTP Wrappers - template - struct crtp_wrapper_t - { - }; - - template - struct crtp_wrapper_t> - { - }; - - template - struct crtp_wrapper_t> - { - }; - - template - struct crtp_wrapper_t - { - template - struct delayed_t - { - using type = Derived; - }; - - template - auto default_values() - -> vendor::update_policies_t::type, no_insert_value_list_t, insert_default_values_t> - { - return { static_cast(*this), insert_default_values_t{} }; - } - - template - auto columns(Args... args) - -> vendor::update_policies_t> - { - return { static_cast(*this), column_list_t(args...) }; - } - - template - auto set(Args... args) - -> vendor::update_policies_t> - { - return { static_cast(*this), insert_list_t(args...) }; - } - - template - auto dynamic_set(Args... args) - -> vendor::update_policies_t, Args...>> - { - static_assert(not std::is_same, void>::value, "dynamic_insert_list must not be called in a static statement"); - return { static_cast(*this), insert_list_t, Args...>(args...) }; - } - }; - // Interpreters template struct interpreter_t diff --git a/include/sqlpp11/vendor/noop.h b/include/sqlpp11/vendor/noop.h index fc057cef..6cd7114c 100644 --- a/include/sqlpp11/vendor/noop.h +++ b/include/sqlpp11/vendor/noop.h @@ -35,6 +35,7 @@ namespace sqlpp { struct noop { + using is_noop = std::true_type; }; template diff --git a/include/sqlpp11/vendor/single_table.h b/include/sqlpp11/vendor/single_table.h index 2a728ea8..53387b6a 100644 --- a/include/sqlpp11/vendor/single_table.h +++ b/include/sqlpp11/vendor/single_table.h @@ -28,8 +28,6 @@ #define SQLPP_VENDOR_SINGLE_TABLE_H #include -#include -#include #include namespace sqlpp @@ -54,7 +52,6 @@ namespace sqlpp single_table_t& operator=(single_table_t&&) = default; ~single_table_t() = default; - const single_table_t& _single_table() const { return *this; } using _table_set = typename Table::_table_set; Table _table; }; @@ -62,20 +59,8 @@ namespace sqlpp struct no_single_table_t { using _table_set = ::sqlpp::detail::type_set<>; - const no_single_table_t& _single_table() const { return *this; } }; - // CRTP Wrappers - template - struct crtp_wrapper_t> - { - }; - - template - struct crtp_wrapper_t - { - }; - // Interpreters template struct interpreter_t> diff --git a/include/sqlpp11/vendor/using.h b/include/sqlpp11/vendor/using.h index 1ad27720..49ab7d9d 100644 --- a/include/sqlpp11/vendor/using.h +++ b/include/sqlpp11/vendor/using.h @@ -71,41 +71,15 @@ namespace sqlpp _dynamic_tables.emplace_back(table); } - const using_t& _using() const { return *this; } _parameter_tuple_t _tables; vendor::interpretable_list_t _dynamic_tables; }; struct no_using_t { - const no_using_t& _using() const { return *this; } + using _is_noop = std::true_type; }; - // CRTP Wrapper - template - struct crtp_wrapper_t> - { - }; - - template - struct crtp_wrapper_t - { - template - auto using_(Args... args) - -> vendor::update_policies_t> - { - return { static_cast(*this), using_t(args...) }; - } - - template - auto dynamic_using(Args... args) - -> vendor::update_policies_t, Args...>> - { - static_assert(not std::is_same, void>::value, "dynamic_using must not be called in a static statement"); - return { static_cast(*this), using_t, Args...>(args...) }; - } - }; - // Interpreters template struct interpreter_t> diff --git a/include/sqlpp11/vendor/where.h b/include/sqlpp11/vendor/where.h index 78b34db6..3cac506e 100644 --- a/include/sqlpp11/vendor/where.h +++ b/include/sqlpp11/vendor/where.h @@ -32,8 +32,6 @@ #include #include #include -#include -#include #include namespace sqlpp @@ -63,15 +61,14 @@ namespace sqlpp where_t& operator=(where_t&&) = default; ~where_t() = default; - template - void add_where(E expr) + template + void add_where(const Statement&, 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()"); - _dynamic_expressions.emplace_back(expr); + static_assert(is_expression_t::value, "invalid expression argument in add_where()"); + _dynamic_expressions.emplace_back(expression); } - const where_t& _where() const { return *this; } _parameter_tuple_t _expressions; vendor::interpretable_list_t _dynamic_expressions; }; @@ -92,41 +89,14 @@ namespace sqlpp where_t& operator=(where_t&&) = default; ~where_t() = default; - const where_t& _where() const { return *this; } bool _condition; }; struct no_where_t { - using _is_where = std::true_type; - const no_where_t& _where() const { return *this; } + using _is_noop = std::true_type; }; - // CRTP Wrappers - template - struct crtp_wrapper_t> - { - }; - - template - struct crtp_wrapper_t - { - template - auto where(Args... args) - -> vendor::update_policies_t> - { - return { static_cast(*this), where_t(args...) }; - } - - template - auto dynamic_where(Args... args) - -> vendor::update_policies_t, Args...>> - { - static_assert(not std::is_same, void>::value, "dynamic_where must not be called in a static statement"); - return { static_cast(*this), where_t, Args...>(args...) }; - } - }; - // Interpreters template struct interpreter_t> diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b2a56c15..b8b3879a 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/InsertTest.cpp b/tests/InsertTest.cpp index 6238d729..29a3e7c5 100644 --- a/tests/InsertTest.cpp +++ b/tests/InsertTest.cpp @@ -57,6 +57,7 @@ int main() static_assert(sqlpp::is_regular::value, "type requirement"); } + interpret(insert_into(t).default_values(), printer).flush(); interpret(insert_into(t), printer).flush(); interpret(insert_into(t).set(t.beta = "kirschauflauf"), printer).flush(); auto i = dynamic_insert_into(db, t).dynamic_set(); diff --git a/tests/RemoveTest.cpp b/tests/RemoveTest.cpp index 398943e6..c1f221b0 100644 --- a/tests/RemoveTest.cpp +++ b/tests/RemoveTest.cpp @@ -25,7 +25,6 @@ #include #include -#include #include "Sample.h" #include "MockDb.h" #include "is_regular.h" From 22c43358f2edb7e8830c8100252bb3b8620ac01f Mon Sep 17 00:00:00 2001 From: rbock Date: Sun, 9 Feb 2014 23:30:30 +0100 Subject: [PATCH 15/74] All statements back to composite design The point is that even though the CRTP code looked nice, it was too hard to comprehend. --- include/sqlpp11/insert.h | 2 +- include/sqlpp11/remove.h | 4 + include/sqlpp11/select.h | 470 +++++++++++++++++--- include/sqlpp11/select_flags.h | 1 - include/sqlpp11/select_fwd.h | 37 -- include/sqlpp11/update.h | 125 ++++-- include/sqlpp11/vendor/from.h | 27 +- include/sqlpp11/vendor/group_by.h | 32 +- include/sqlpp11/vendor/having.h | 29 +- include/sqlpp11/vendor/limit.h | 44 +- include/sqlpp11/vendor/offset.h | 44 +- include/sqlpp11/vendor/order_by.h | 34 +- include/sqlpp11/vendor/select_column_list.h | 34 +- include/sqlpp11/vendor/select_flag_list.h | 32 +- include/sqlpp11/vendor/update_list.h | 31 +- tests/CMakeLists.txt | 10 +- tests/SelectTest.cpp | 4 +- 17 files changed, 543 insertions(+), 417 deletions(-) delete mode 100644 include/sqlpp11/select_fwd.h 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"); From 82bcd63efde287526d24566e25b0f68255588fd3 Mon Sep 17 00:00:00 2001 From: rbock Date: Sun, 9 Feb 2014 23:45:17 +0100 Subject: [PATCH 16/74] Removed the dreaded crtp_wrapper and the policy_wrapper --- include/sqlpp11/select.h | 2 - include/sqlpp11/update.h | 2 - include/sqlpp11/vendor/crtp_wrapper.h | 57 ------------------- include/sqlpp11/vendor/from.h | 7 --- include/sqlpp11/vendor/group_by.h | 1 - include/sqlpp11/vendor/having.h | 1 - include/sqlpp11/vendor/limit.h | 1 - include/sqlpp11/vendor/offset.h | 1 - include/sqlpp11/vendor/order_by.h | 1 - include/sqlpp11/vendor/policy.h | 62 --------------------- include/sqlpp11/vendor/select_column_list.h | 1 - include/sqlpp11/vendor/select_flag_list.h | 1 - include/sqlpp11/vendor/using.h | 1 - 13 files changed, 138 deletions(-) delete mode 100644 include/sqlpp11/vendor/crtp_wrapper.h delete mode 100644 include/sqlpp11/vendor/policy.h diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 22bd0f24..cf1db690 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -44,8 +44,6 @@ #include #include #include -#include -#include #include #include diff --git a/include/sqlpp11/update.h b/include/sqlpp11/update.h index 215c5006..63ba4cd5 100644 --- a/include/sqlpp11/update.h +++ b/include/sqlpp11/update.h @@ -34,8 +34,6 @@ #include #include #include -#include -#include #include namespace sqlpp diff --git a/include/sqlpp11/vendor/crtp_wrapper.h b/include/sqlpp11/vendor/crtp_wrapper.h deleted file mode 100644 index 47ef265a..00000000 --- a/include/sqlpp11/vendor/crtp_wrapper.h +++ /dev/null @@ -1,57 +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_VENDOR_CRTP_WRAPPER_H -#define SQLPP_VENDOR_CRTP_WRAPPER_H - -#include - -namespace sqlpp -{ - namespace vendor - { - template - struct get_database_impl; - - template class Statement, typename Database, typename... Policies> - struct get_database_impl> - { - using type = Database; - }; - - template - using get_database_t = typename get_database_impl::type; - - template - struct crtp_wrapper_t - { - static_assert(wrong_t::value, "missing crtp policy specialization"); - }; - } - -} - -#endif diff --git a/include/sqlpp11/vendor/from.h b/include/sqlpp11/vendor/from.h index 4211098d..7c513848 100644 --- a/include/sqlpp11/vendor/from.h +++ b/include/sqlpp11/vendor/from.h @@ -32,7 +32,6 @@ #include #include #include -#include namespace sqlpp { @@ -82,12 +81,6 @@ namespace sqlpp using _is_noop = std::true_type; }; - // CRTP Wrappers - template - struct crtp_wrapper_t> - { - }; - // Interpreters template struct interpreter_t> diff --git a/include/sqlpp11/vendor/group_by.h b/include/sqlpp11/vendor/group_by.h index 1a0de458..9e405787 100644 --- a/include/sqlpp11/vendor/group_by.h +++ b/include/sqlpp11/vendor/group_by.h @@ -33,7 +33,6 @@ #include #include #include -#include #include namespace sqlpp diff --git a/include/sqlpp11/vendor/having.h b/include/sqlpp11/vendor/having.h index e412e762..ca4e6410 100644 --- a/include/sqlpp11/vendor/having.h +++ b/include/sqlpp11/vendor/having.h @@ -32,7 +32,6 @@ #include #include #include -#include #include namespace sqlpp diff --git a/include/sqlpp11/vendor/limit.h b/include/sqlpp11/vendor/limit.h index f73b36bf..3c4e03c3 100644 --- a/include/sqlpp11/vendor/limit.h +++ b/include/sqlpp11/vendor/limit.h @@ -29,7 +29,6 @@ #include #include -#include namespace sqlpp { diff --git a/include/sqlpp11/vendor/offset.h b/include/sqlpp11/vendor/offset.h index 18a90c65..f92ff306 100644 --- a/include/sqlpp11/vendor/offset.h +++ b/include/sqlpp11/vendor/offset.h @@ -29,7 +29,6 @@ #include #include -#include namespace sqlpp { diff --git a/include/sqlpp11/vendor/order_by.h b/include/sqlpp11/vendor/order_by.h index 0233f03b..61eeb7ed 100644 --- a/include/sqlpp11/vendor/order_by.h +++ b/include/sqlpp11/vendor/order_by.h @@ -32,7 +32,6 @@ #include #include #include -#include #include namespace sqlpp diff --git a/include/sqlpp11/vendor/policy.h b/include/sqlpp11/vendor/policy.h deleted file mode 100644 index 45edeeac..00000000 --- a/include/sqlpp11/vendor/policy.h +++ /dev/null @@ -1,62 +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_VENDOR_POLICY_H -#define SQLPP_VENDOR_POLICY_H - -#include - -namespace sqlpp -{ - namespace vendor - { - template - struct policy_t: public PolicyImpl - { - policy_t() - {} - - template - policy_t(const Whatever&, policy_t policy): - PolicyImpl(policy) - {} - - template - policy_t(const Whatever&, PolicyImpl impl): - PolicyImpl(impl) - {} - - template - policy_t(Derived derived, const Whatever&): - PolicyImpl(derived) - {} - }; - - } - -} - -#endif diff --git a/include/sqlpp11/vendor/select_column_list.h b/include/sqlpp11/vendor/select_column_list.h index 255644b5..7442e313 100644 --- a/include/sqlpp11/vendor/select_column_list.h +++ b/include/sqlpp11/vendor/select_column_list.h @@ -37,7 +37,6 @@ #include #include #include -#include #include namespace sqlpp diff --git a/include/sqlpp11/vendor/select_flag_list.h b/include/sqlpp11/vendor/select_flag_list.h index fe68a9f7..c999b003 100644 --- a/include/sqlpp11/vendor/select_flag_list.h +++ b/include/sqlpp11/vendor/select_flag_list.h @@ -33,7 +33,6 @@ #include #include #include -#include namespace sqlpp { diff --git a/include/sqlpp11/vendor/using.h b/include/sqlpp11/vendor/using.h index 49ab7d9d..bb8ef152 100644 --- a/include/sqlpp11/vendor/using.h +++ b/include/sqlpp11/vendor/using.h @@ -32,7 +32,6 @@ #include #include #include -#include namespace sqlpp { From e4c7b5235fac7cca3eea456c2b37907641ac42c3 Mon Sep 17 00:00:00 2001 From: rbock Date: Mon, 10 Feb 2014 09:46:31 +0100 Subject: [PATCH 17/74] Added several checks for correct types in insert columns/values --- include/sqlpp11/any.h | 4 +++- include/sqlpp11/default_value.h | 1 + include/sqlpp11/null.h | 1 + include/sqlpp11/parameter.h | 2 ++ include/sqlpp11/tvin.h | 3 +++ include/sqlpp11/vendor/assignment.h | 1 + include/sqlpp11/vendor/insert_value.h | 3 +++ include/sqlpp11/vendor/insert_value_list.h | 5 ++++- include/sqlpp11/vendor/wrap_operand.h | 5 +++++ tests/InsertTest.cpp | 1 + tests/UpdateTest.cpp | 3 +++ 11 files changed, 27 insertions(+), 2 deletions(-) diff --git a/include/sqlpp11/any.h b/include/sqlpp11/any.h index 004a4cfd..e4c9ceef 100644 --- a/include/sqlpp11/any.h +++ b/include/sqlpp11/any.h @@ -27,8 +27,8 @@ #ifndef SQLPP_ANY_H #define SQLPP_ANY_H -#include #include +#include namespace sqlpp { @@ -57,6 +57,8 @@ namespace sqlpp }; }; + using _table_set = ::sqlpp::detail::type_set<>; // FIXME: Can selects leak tables here? + any_t(Select select): _select(select) {} diff --git a/include/sqlpp11/default_value.h b/include/sqlpp11/default_value.h index 78eb71c5..b4125efe 100644 --- a/include/sqlpp11/default_value.h +++ b/include/sqlpp11/default_value.h @@ -35,6 +35,7 @@ namespace sqlpp { static constexpr bool _is_expression = true; using _value_type = no_value_t; + using _table_set = ::sqlpp::detail::type_set<>; static constexpr bool _is_trivial() { return false; } }; diff --git a/include/sqlpp11/null.h b/include/sqlpp11/null.h index c07a3001..643511a8 100644 --- a/include/sqlpp11/null.h +++ b/include/sqlpp11/null.h @@ -35,6 +35,7 @@ namespace sqlpp { static constexpr bool _is_expression = true; using _value_type = no_value_t; + using _table_set = ::sqlpp::detail::type_set<>; static constexpr bool _is_trivial() { return false; } }; diff --git a/include/sqlpp11/parameter.h b/include/sqlpp11/parameter.h index 3f33b808..875e738a 100644 --- a/include/sqlpp11/parameter.h +++ b/include/sqlpp11/parameter.h @@ -28,6 +28,7 @@ #define SQLPP_PARAMETER_H #include +#include namespace sqlpp { @@ -38,6 +39,7 @@ namespace sqlpp using _is_parameter = std::true_type; using _is_expression_t = std::true_type; using _instance_t = typename NameType::_name_t::template _member_t; + using _table_set = sqlpp::detail::type_set<>; parameter_t() {} diff --git a/include/sqlpp11/tvin.h b/include/sqlpp11/tvin.h index a3462d08..2b98c3ef 100644 --- a/include/sqlpp11/tvin.h +++ b/include/sqlpp11/tvin.h @@ -39,6 +39,7 @@ namespace sqlpp { using _operand_t = Operand; using _value_type = typename _operand_t::_value_type; + using _table_set = typename _operand_t::_table_set; tvin_t(Operand operand): _value(operand) @@ -74,6 +75,7 @@ namespace sqlpp template struct tvin_wrap_t { + using _table_set = typename T::_table_set; static constexpr bool _is_trivial() { return false; @@ -94,6 +96,7 @@ namespace sqlpp template struct tvin_wrap_t> { + using _table_set = typename T::_table_set; bool _is_trivial() const { return _value._is_trivial(); diff --git a/include/sqlpp11/vendor/assignment.h b/include/sqlpp11/vendor/assignment.h index 5d2cfc67..d4e0f660 100644 --- a/include/sqlpp11/vendor/assignment.h +++ b/include/sqlpp11/vendor/assignment.h @@ -44,6 +44,7 @@ namespace sqlpp using _column_t = Lhs; using value_type = Rhs; using _parameter_tuple_t = std::tuple<_column_t, Rhs>; + using _table_set = typename Lhs::_table_set::template join::type; static_assert(not std::is_same::value or can_be_null_t<_column_t>::value, "column cannot be null"); diff --git a/include/sqlpp11/vendor/insert_value.h b/include/sqlpp11/vendor/insert_value.h index 88559474..440c88ec 100644 --- a/include/sqlpp11/vendor/insert_value.h +++ b/include/sqlpp11/vendor/insert_value.h @@ -32,6 +32,7 @@ #include #include #include +#include namespace sqlpp { @@ -43,6 +44,7 @@ namespace sqlpp struct type_if { using type = Type; + using _table_set = typename Type::_table_set; }; template @@ -50,6 +52,7 @@ namespace sqlpp { struct type { + using _table_set = sqlpp::detail::type_set<>; }; }; } diff --git a/include/sqlpp11/vendor/insert_value_list.h b/include/sqlpp11/vendor/insert_value_list.h index 22668b6a..31ea1db6 100644 --- a/include/sqlpp11/vendor/insert_value_list.h +++ b/include/sqlpp11/vendor/insert_value_list.h @@ -63,7 +63,10 @@ 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::type; + 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"); insert_list_t(Assignments... assignment): diff --git a/include/sqlpp11/vendor/wrap_operand.h b/include/sqlpp11/vendor/wrap_operand.h index 106a6349..97d9cd8a 100644 --- a/include/sqlpp11/vendor/wrap_operand.h +++ b/include/sqlpp11/vendor/wrap_operand.h @@ -29,6 +29,7 @@ #include #include +#include namespace sqlpp { @@ -47,6 +48,7 @@ namespace sqlpp static constexpr bool _is_expression = true; using _value_type = sqlpp::detail::boolean; using _value_t = bool; + using _table_set = ::sqlpp::detail::type_set<>; bool _is_trivial() const { return _t == false; } @@ -71,6 +73,7 @@ namespace sqlpp static constexpr bool _is_expression = true; using _value_type = ::sqlpp::detail::integral; using _value_t = T; + using _table_set = ::sqlpp::detail::type_set<>; bool _is_trivial() const { return _t == 0; } @@ -96,6 +99,7 @@ namespace sqlpp static constexpr bool _is_expression = true; using _value_type = ::sqlpp::detail::floating_point; using _value_t = T; + using _table_set = ::sqlpp::detail::type_set<>; bool _is_trivial() const { return _t == 0; } @@ -119,6 +123,7 @@ namespace sqlpp static constexpr bool _is_expression = true; using _value_type = ::sqlpp::detail::text; using _value_t = std::string; + using _table_set = ::sqlpp::detail::type_set<>; bool _is_trivial() const { return _t.empty(); } diff --git a/tests/InsertTest.cpp b/tests/InsertTest.cpp index 29a3e7c5..93d7e6c7 100644 --- a/tests/InsertTest.cpp +++ b/tests/InsertTest.cpp @@ -35,6 +35,7 @@ DbMock::_context_t printer(std::cerr); int main() { test::TabBar t; + test::TabFoo f; auto x = t.alpha = 7; auto y = t.beta = "kaesekuchen"; diff --git a/tests/UpdateTest.cpp b/tests/UpdateTest.cpp index a4f07fe4..93dbf7f0 100644 --- a/tests/UpdateTest.cpp +++ b/tests/UpdateTest.cpp @@ -35,6 +35,7 @@ DbMock::_context_t printer(std::cerr); int main() { test::TabBar t; + test::TabFoo f; auto x = t.alpha = 7; auto y = t.beta = "kaesekuchen"; @@ -58,6 +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(); auto u = dynamic_update(db, t).dynamic_set(t.gamma = false).dynamic_where(); u.add_set(t.gamma = false); interpret(u, printer).flush(); From 54687c5e69274fd80f2ce4da13b3fcff083b05e2 Mon Sep 17 00:00:00 2001 From: rbock Date: Mon, 10 Feb 2014 17:56:16 +0100 Subject: [PATCH 18/74] Added a bunch of static asserts to prevent misuse of insert and update There are quite a few more to be inserted --- include/sqlpp11/insert.h | 11 ++--- include/sqlpp11/remove.h | 8 ++-- include/sqlpp11/select.h | 36 ++++++++--------- include/sqlpp11/update.h | 10 +++-- include/sqlpp11/vendor/insert_value_list.h | 47 ++++++++++++++-------- include/sqlpp11/vendor/update_list.h | 9 ++++- tests/InsertTest.cpp | 3 ++ tests/UpdateTest.cpp | 4 +- 8 files changed, 77 insertions(+), 51 deletions(-) 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(); From 7c928ae6d0f42a16ac5209e764e843bd50197c08 Mon Sep 17 00:00:00 2001 From: rbock Date: Mon, 10 Feb 2014 19:55:48 +0100 Subject: [PATCH 19/74] Added table sets to several more expressions --- include/sqlpp11/functions.h | 3 +++ include/sqlpp11/select.h | 1 + include/sqlpp11/update.h | 1 + include/sqlpp11/vendor/concat.h | 1 + include/sqlpp11/vendor/expression.h | 4 ++++ include/sqlpp11/vendor/in.h | 1 + include/sqlpp11/vendor/like.h | 1 + include/sqlpp11/vendor/where.h | 3 +++ tests/UpdateTest.cpp | 3 +-- 9 files changed, 16 insertions(+), 2 deletions(-) diff --git a/include/sqlpp11/functions.h b/include/sqlpp11/functions.h index 43a69a98..9aabf960 100644 --- a/include/sqlpp11/functions.h +++ b/include/sqlpp11/functions.h @@ -47,6 +47,7 @@ namespace sqlpp template auto value(T t) -> typename operand_t::type { + using _table_set = ::sqlpp::detail::type_set<>; static_assert(not is_value_t::value, "value() is to be called with non-sql-type like int, or string"); return { t }; } @@ -55,6 +56,7 @@ namespace sqlpp struct verbatim_t: public ValueType::template operators> { using _value_type = ValueType; + using _table_set = ::sqlpp::detail::type_set<>; verbatim_t(std::string verbatim): _verbatim(verbatim) {} verbatim_t(const verbatim_t&) = default; @@ -100,6 +102,7 @@ namespace sqlpp struct value_list_t // to be used in .in() method { using _container_t = Container; + using _table_set = ::sqlpp::detail::type_set<>;// FIXME: Could it be something else? using _value_type = typename operand_t::type::_value_type; value_list_t(_container_t container): diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 2f01e1d9..0afcb168 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -96,6 +96,7 @@ namespace sqlpp using _parameter_tuple_t = std::tuple; using _parameter_list_t = typename make_parameter_list_t::type; + using _table_set = ::sqlpp::detail::type_set<>; using _column_list_t = ColumnList; using _result_row_t = typename _column_list_t::_result_row_t; diff --git a/include/sqlpp11/update.h b/include/sqlpp11/update.h index e92ba792..a26a34aa 100644 --- a/include/sqlpp11/update.h +++ b/include/sqlpp11/update.h @@ -58,6 +58,7 @@ namespace sqlpp struct update_t { static_assert(Table::_table_set::template is_superset_of::value, "updated columns do not match the table"); + static_assert(Table::_table_set::template is_superset_of::value, "where condition does not match updated table"); using _database_t = Database; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; diff --git a/include/sqlpp11/vendor/concat.h b/include/sqlpp11/vendor/concat.h index 232e92d2..91bb5d80 100644 --- a/include/sqlpp11/vendor/concat.h +++ b/include/sqlpp11/vendor/concat.h @@ -40,6 +40,7 @@ namespace sqlpp { static_assert(sizeof...(Args) > 0, "concat requires two arguments at least"); static_assert(sqlpp::detail::and_t::value, "at least one non-text argument detected in concat()"); + using _table_set = typename ::sqlpp::detail::make_joined_set::type; struct _value_type: public First::_value_type::_base_value_type { diff --git a/include/sqlpp11/vendor/expression.h b/include/sqlpp11/vendor/expression.h index 20de7a16..48c71c5a 100644 --- a/include/sqlpp11/vendor/expression.h +++ b/include/sqlpp11/vendor/expression.h @@ -44,6 +44,7 @@ namespace sqlpp { using _value_type = ::sqlpp::detail::boolean; using _parameter_tuple_t = std::tuple; + using _table_set = typename ::sqlpp::detail::make_joined_set::type; equal_t(Lhs lhs, Rhs rhs): _lhs(lhs), @@ -88,6 +89,7 @@ namespace sqlpp { using _value_type = ::sqlpp::detail::boolean; using _parameter_tuple_t = std::tuple; + using _table_set = typename ::sqlpp::detail::make_joined_set::type; not_equal_t(Lhs lhs, Rhs rhs): _lhs(lhs), @@ -132,6 +134,7 @@ namespace sqlpp { using _value_type = ::sqlpp::detail::boolean; using _parameter_tuple_t = std::tuple; + using _table_set = typename Lhs::_table_set; logical_not_t(Lhs l): _lhs(l) @@ -168,6 +171,7 @@ namespace sqlpp using _rhs_t = Rhs; using _value_type = typename O::_value_type; using _parameter_tuple_t = std::tuple<_lhs_t, _rhs_t>; + using _table_set = typename ::sqlpp::detail::make_joined_set::type; binary_expression_t(_lhs_t lhs, _rhs_t rhs): _lhs(lhs), diff --git a/include/sqlpp11/vendor/in.h b/include/sqlpp11/vendor/in.h index 993a3288..557de680 100644 --- a/include/sqlpp11/vendor/in.h +++ b/include/sqlpp11/vendor/in.h @@ -56,6 +56,7 @@ namespace sqlpp T in; }; }; + using _table_set = typename ::sqlpp::detail::make_joined_set::type; in_t(Operand operand, Args... args): _operand(operand), diff --git a/include/sqlpp11/vendor/like.h b/include/sqlpp11/vendor/like.h index 6ad5d9a9..b9b0f562 100644 --- a/include/sqlpp11/vendor/like.h +++ b/include/sqlpp11/vendor/like.h @@ -41,6 +41,7 @@ namespace sqlpp static_assert(is_text_t::value, "Operand for like() has to be a text"); static_assert(is_text_t::value, "Pattern for like() has to be a text"); using _parameter_tuple_t = std::tuple; + using _table_set = typename ::sqlpp::detail::make_joined_set::type; struct _value_type: public boolean { diff --git a/include/sqlpp11/vendor/where.h b/include/sqlpp11/vendor/where.h index 3cac506e..7cff9e35 100644 --- a/include/sqlpp11/vendor/where.h +++ b/include/sqlpp11/vendor/where.h @@ -51,6 +51,8 @@ namespace sqlpp using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type; + using _table_set = typename ::sqlpp::detail::make_joined_set::type; + where_t(Expressions... expressions): _expressions(expressions...) {} @@ -95,6 +97,7 @@ namespace sqlpp struct no_where_t { using _is_noop = std::true_type; + using _table_set = ::sqlpp::detail::type_set<>; }; // Interpreters diff --git a/tests/UpdateTest.cpp b/tests/UpdateTest.cpp index cdc35a6f..e77f65a9 100644 --- a/tests/UpdateTest.cpp +++ b/tests/UpdateTest.cpp @@ -59,8 +59,7 @@ 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 = "opaque").where(t.beta != f.delta), printer).flush(); + interpret(update(t).set(t.beta = "opaque").where(t.beta != t.beta), 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(); From fb092583cc20719cb92656991353ce573e120abc Mon Sep 17 00:00:00 2001 From: rbock Date: Tue, 11 Feb 2014 10:17:02 +0100 Subject: [PATCH 20/74] Made wrong_t<...> a true std::false_type again. I am sure this would shoot me in the foot some day otherwise --- include/sqlpp11/vendor/wrong.h | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/include/sqlpp11/vendor/wrong.h b/include/sqlpp11/vendor/wrong.h index 5694fd6a..896f1e46 100644 --- a/include/sqlpp11/vendor/wrong.h +++ b/include/sqlpp11/vendor/wrong.h @@ -33,14 +33,19 @@ namespace sqlpp { namespace vendor { - // A template that always returns false - // To be used with static assert, for instance, to ensure it - // fires only when the template is instantiated. - template - struct wrong_t - { - static constexpr bool value = false; - }; + namespace detail + { + // A template that always returns false + // To be used with static assert, for instance, to ensure it + // fires only when the template is instantiated. + template + struct wrong + { + using type = std::false_type; + }; + } + template + using wrong_t = typename detail::wrong::type; } } #endif From 9e8979c6f008c6909022207a2a735128f1ec49d9 Mon Sep 17 00:00:00 2001 From: rbock Date: Thu, 13 Feb 2014 08:44:09 +0100 Subject: [PATCH 21/74] Fixed a bunch of small errors and shorted compile error messages --- include/sqlpp11/column.h | 8 ++ include/sqlpp11/select.h | 2 +- include/sqlpp11/text.h | 6 + include/sqlpp11/vendor/insert_value_list.h | 4 +- include/sqlpp11/vendor/where.h | 4 +- include/sqlpp11/vendor/wrap_operand.h | 122 +++++++++++++++------ tests/CMakeLists.txt | 1 + tests/InsertTest.cpp | 5 +- tests/SelectTest.cpp | 6 +- tests/sample.sql | 3 +- 10 files changed, 116 insertions(+), 45 deletions(-) diff --git a/include/sqlpp11/column.h b/include/sqlpp11/column.h index 95c334bb..06193dab 100644 --- a/include/sqlpp11/column.h +++ b/include/sqlpp11/column.h @@ -84,6 +84,14 @@ namespace sqlpp return { *this, {t} }; } + template + auto operator =(T t) const + -> typename std::enable_if::type>::value and not std::is_same::value), + vendor::assignment_t::type>>::type + { + static_assert(sqlpp::vendor::wrong_t::value, "invalid assignment operand"); + } + auto operator =(sqlpp::null_t) const ->vendor::assignment_t { diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 0afcb168..aa5e5983 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -475,7 +475,7 @@ namespace sqlpp const _dynamic_names_t& get_dynamic_names() const { - return _column_list_t::_dynamic_columns._dynamic_expression_names; + return _column_list._dynamic_columns._dynamic_expression_names; } static constexpr size_t _get_static_no_of_parameters() diff --git a/include/sqlpp11/text.h b/include/sqlpp11/text.h index f7d535ea..33ad3f75 100644 --- a/include/sqlpp11/text.h +++ b/include/sqlpp11/text.h @@ -179,6 +179,12 @@ namespace sqlpp return { *static_cast(this), {t} }; } + template + auto operator +=(T t) const -> decltype(std::declval() = std::declval() + t) + { + return *static_cast(this) = operator +(t); + } + template vendor::like_t::type> like(T t) const { diff --git a/include/sqlpp11/vendor/insert_value_list.h b/include/sqlpp11/vendor/insert_value_list.h index 5fb1239c..9959c823 100644 --- a/include/sqlpp11/vendor/insert_value_list.h +++ b/include/sqlpp11/vendor/insert_value_list.h @@ -157,9 +157,7 @@ namespace sqlpp } template - void add_values_impl(const std::false_type&, Assignments... assignments) - { - } + void add_values_impl(const std::false_type&, Assignments... assignments); }; diff --git a/include/sqlpp11/vendor/where.h b/include/sqlpp11/vendor/where.h index 7cff9e35..e61feef5 100644 --- a/include/sqlpp11/vendor/where.h +++ b/include/sqlpp11/vendor/where.h @@ -47,7 +47,8 @@ namespace sqlpp using _parameter_tuple_t = std::tuple; static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in where()"); - static_assert(sqlpp::detail::and_t::value, "at least one argument is not an expression in where()"); + static_assert(not sqlpp::detail::or_t::value, "at least one argument is an assignment in where()"); + static_assert(sqlpp::detail::and_t::value, "at least one argument is not valid expression in where()"); using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type; @@ -80,6 +81,7 @@ namespace sqlpp { using _is_where = std::true_type; using _is_dynamic = std::false_type; + using _table_set = ::sqlpp::detail::type_set<>; where_t(bool condition): _condition(condition) diff --git a/include/sqlpp11/vendor/wrap_operand.h b/include/sqlpp11/vendor/wrap_operand.h index 97d9cd8a..1dfce4a2 100644 --- a/include/sqlpp11/vendor/wrap_operand.h +++ b/include/sqlpp11/vendor/wrap_operand.h @@ -50,6 +50,20 @@ namespace sqlpp using _value_t = bool; using _table_set = ::sqlpp::detail::type_set<>; + boolean_operand(): + _t{} + {} + + boolean_operand(_value_t t): + _t(t) + {} + + boolean_operand(const boolean_operand&) = default; + boolean_operand(boolean_operand&&) = default; + boolean_operand& operator=(const boolean_operand&) = default; + boolean_operand& operator=(boolean_operand&&) = default; + ~boolean_operand() = default; + bool _is_trivial() const { return _t == false; } _value_t _t; @@ -67,23 +81,36 @@ namespace sqlpp } }; - template - struct integral_operand + struct integral_operand + { + static constexpr bool _is_expression = true; + using _value_type = ::sqlpp::detail::integral; + using _value_t = int64_t; + using _table_set = ::sqlpp::detail::type_set<>; + + integral_operand(): + _t{} + {} + + integral_operand(_value_t t): + _t(t) + {} + + integral_operand(const integral_operand&) = default; + integral_operand(integral_operand&&) = default; + integral_operand& operator=(const integral_operand&) = default; + integral_operand& operator=(integral_operand&&) = default; + ~integral_operand() = default; + + bool _is_trivial() const { return _t == 0; } + + _value_t _t; + }; + + template + struct interpreter_t { - static constexpr bool _is_expression = true; - using _value_type = ::sqlpp::detail::integral; - using _value_t = T; - using _table_set = ::sqlpp::detail::type_set<>; - - bool _is_trivial() const { return _t == 0; } - - _value_t _t; - }; - - template - struct interpreter_t> - { - using Operand = integral_operand; + using Operand = integral_operand; static Context& _(const Operand& t, Context& context) { @@ -93,23 +120,36 @@ namespace sqlpp }; - template - struct floating_point_operand + struct floating_point_operand + { + static constexpr bool _is_expression = true; + using _value_type = ::sqlpp::detail::floating_point; + using _value_t = double; + using _table_set = ::sqlpp::detail::type_set<>; + + floating_point_operand(): + _t{} + {} + + floating_point_operand(_value_t t): + _t(t) + {} + + floating_point_operand(const floating_point_operand&) = default; + floating_point_operand(floating_point_operand&&) = default; + floating_point_operand& operator=(const floating_point_operand&) = default; + floating_point_operand& operator=(floating_point_operand&&) = default; + ~floating_point_operand() = default; + + bool _is_trivial() const { return _t == 0; } + + _value_t _t; + }; + + template + struct interpreter_t { - static constexpr bool _is_expression = true; - using _value_type = ::sqlpp::detail::floating_point; - using _value_t = T; - using _table_set = ::sqlpp::detail::type_set<>; - - bool _is_trivial() const { return _t == 0; } - - _value_t _t; - }; - - template - struct interpreter_t> - { - using Operand = floating_point_operand; + using Operand = floating_point_operand; static Context& _(const Operand& t, Context& context) { @@ -125,6 +165,20 @@ namespace sqlpp using _value_t = std::string; using _table_set = ::sqlpp::detail::type_set<>; + text_operand(): + _t{} + {} + + text_operand(_value_t t): + _t(t) + {} + + text_operand(const text_operand&) = default; + text_operand(text_operand&&) = default; + text_operand& operator=(const text_operand&) = default; + text_operand& operator=(text_operand&&) = default; + ~text_operand() = default; + bool _is_trivial() const { return _t.empty(); } _value_t _t; @@ -157,13 +211,13 @@ namespace sqlpp template struct wrap_operand::value>::type> { - using type = integral_operand; + using type = integral_operand; }; template struct wrap_operand::value>::type> { - using type = floating_point_operand; + using type = floating_point_operand; }; template diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b2a56c15..8d04a9e3 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -19,5 +19,6 @@ find_package(PythonInterp REQUIRED) add_custom_command( OUTPUT ${CMAKE_CURRENT_LIST_DIR}/Sample.h COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/ddl2cpp ${CMAKE_CURRENT_LIST_DIR}/sample.sql Sample test + DEPENDS ${CMAKE_CURRENT_LIST_DIR}/sample.sql ) diff --git a/tests/InsertTest.cpp b/tests/InsertTest.cpp index 9a343a0c..55e5bbc7 100644 --- a/tests/InsertTest.cpp +++ b/tests/InsertTest.cpp @@ -62,8 +62,9 @@ int main() 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 multi_insert = insert_into(t).columns(t.beta, t.delta); + multi_insert.add_values(t.beta = "cheesecake", t.delta = 1); + multi_insert.add_values(t.beta = sqlpp::default_value, t.delta = sqlpp::default_value); auto i = dynamic_insert_into(db, t).dynamic_set(); i.add_set(t.beta = "kirschauflauf"); interpret(i, printer).flush(); diff --git a/tests/SelectTest.cpp b/tests/SelectTest.cpp index 5c9c7b2b..c41c4d85 100644 --- a/tests/SelectTest.cpp +++ b/tests/SelectTest.cpp @@ -273,7 +273,7 @@ int main() // Test that select(all_of(tab)) is expanded in select { auto a = select(all_of(t)); - auto b = select(t.alpha, t.beta, t.gamma); + auto b = select(t.alpha, t.beta, t.gamma, t.delta); //auto c = select(t); static_assert(std::is_same::value, "all_of(t) has to be expanded by select()"); //static_assert(std::is_same::value, "t has to be expanded by select()"); @@ -282,14 +282,14 @@ int main() // Test that select(all_of(tab)) is expanded in multi_column { auto a = multi_column(alias::a, all_of(t)); - auto b = multi_column(alias::a, t.alpha, t.beta, t.gamma); + auto b = multi_column(alias::a, t.alpha, t.beta, t.gamma, t.delta); static_assert(std::is_same::value, "all_of(t) has to be expanded by multi_column"); } // Test that select(tab) is expanded in multi_column { auto a = multi_column(alias::a, all_of(t)); - auto b = multi_column(alias::a, t.alpha, t.beta, t.gamma); + auto b = multi_column(alias::a, t.alpha, t.beta, t.gamma, t.delta); static_assert(std::is_same::value, "t has to be expanded by multi_column"); } diff --git a/tests/sample.sql b/tests/sample.sql index 4fa7e01c..75f48445 100644 --- a/tests/sample.sql +++ b/tests/sample.sql @@ -35,6 +35,7 @@ CREATE TABLE tab_bar ( alpha bigint AUTO_INCREMENT, beta varchar(255) NULL DEFAULT "", - gamma bool NOT NULL + gamma bool NOT NULL, + delta int ); From 61a4797d0b0e8e5d0fbd74d1fda259534681b53f Mon Sep 17 00:00:00 2001 From: rbock Date: Thu, 13 Feb 2014 10:07:51 +0100 Subject: [PATCH 22/74] Simplified syntax for multi_columns a lot Instead of multi_column(alias, columns...) it is now multi_column(columns...).as(alias) Also, you can now write: all_of(table).as(alias) --- include/sqlpp11/all_of.h | 71 ++++++++++++++++++++++++ include/sqlpp11/detail/copy_tuple_args.h | 11 +++- include/sqlpp11/multi_column.h | 71 ++++++++++++++++++++---- include/sqlpp11/table.h | 12 +--- include/sqlpp11/table_alias.h | 2 +- include/sqlpp11/vendor/field.h | 2 +- tests/InterpretTest.cpp | 5 +- tests/SelectTest.cpp | 13 +---- 8 files changed, 152 insertions(+), 35 deletions(-) create mode 100644 include/sqlpp11/all_of.h diff --git a/include/sqlpp11/all_of.h b/include/sqlpp11/all_of.h new file mode 100644 index 00000000..fb4f50b3 --- /dev/null +++ b/include/sqlpp11/all_of.h @@ -0,0 +1,71 @@ +/* + * 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_ALL_OF_H +#define SQLPP_ALL_OF_H + +#include +#include +#include + +namespace sqlpp +{ + template + struct all_of_t + { + using _column_tuple_t = typename Table::_column_tuple_t; + + template + detail::copy_tuple_args_t as(const AliasProvider& alias) + { + return ::sqlpp::multi_column(_column_tuple_t{}).as(alias); + } + }; + + template + auto all_of(Table t) -> all_of_t
+ { + return {}; + } + + namespace vendor + { + template + struct interpreter_t> + { + using T = all_of_t
; + + static Context& _(const T& t, const Context&) + { + static_assert(wrong_t::value, "all_of(table) does not seem to be used in select"); + } + }; + } + +} + +#endif + diff --git a/include/sqlpp11/detail/copy_tuple_args.h b/include/sqlpp11/detail/copy_tuple_args.h index f41d2443..644424e6 100644 --- a/include/sqlpp11/detail/copy_tuple_args.h +++ b/include/sqlpp11/detail/copy_tuple_args.h @@ -31,12 +31,21 @@ namespace sqlpp { + template + struct all_of_t; + namespace detail { template struct as_tuple { - static std::tuple _(T t) { return std::tuple{ t }; }; + static std::tuple _(T t) { return std::tuple{ t }; } + }; + + template + struct as_tuple<::sqlpp::all_of_t> + { + static typename ::sqlpp::all_of_t::_column_tuple_t _(::sqlpp::all_of_t) { return { }; } }; template diff --git a/include/sqlpp11/multi_column.h b/include/sqlpp11/multi_column.h index c60ee57d..f75169e7 100644 --- a/include/sqlpp11/multi_column.h +++ b/include/sqlpp11/multi_column.h @@ -35,12 +35,13 @@ namespace sqlpp { template + struct multi_column_alias_t; + + template struct multi_column_t { static_assert(detail::and_t::value, "multi_column parameters need to be named expressions"); - using _name_t = typename AliasProvider::_name_t; - multi_column_t(std::tuple columns): _columns(columns) {} @@ -55,6 +56,43 @@ namespace sqlpp multi_column_t& operator=(multi_column_t&&) = default; ~multi_column_t() = default; + template + multi_column_alias_t as(const AliasProvider&) + { + return { *this }; + } + + + using _value_type = no_value_t; + using _is_multi_column = std::true_type; + + std::tuple _columns; + }; + + template + struct multi_column_alias_t + { + static_assert(detail::and_t::value, "multi_column parameters need to be named expressions"); + + using _name_t = typename AliasProvider::_name_t; + + multi_column_alias_t(multi_column_t multi_column): + _columns(multi_column._columns) + {} + + multi_column_alias_t(std::tuple columns): + _columns(columns) + {} + + multi_column_alias_t(Columns... columns): + _columns(columns...) + {} + + multi_column_alias_t(const multi_column_alias_t&) = default; + multi_column_alias_t(multi_column_alias_t&&) = default; + multi_column_alias_t& operator=(const multi_column_alias_t&) = default; + multi_column_alias_t& operator=(multi_column_alias_t&&) = default; + ~multi_column_alias_t() = default; struct _value_type: public no_value_t { @@ -67,10 +105,21 @@ namespace sqlpp namespace vendor { - template - struct interpreter_t> + template + struct interpreter_t> { - using T = multi_column_t; + using T = multi_column_t; + + static void _(const T& t, Context& context) + { + static_assert(wrong_t::value, "multi_column must be used with an alias"); + } + }; + + template + struct interpreter_t> + { + using T = multi_column_alias_t; static Context& _(const T& t, Context& context) { @@ -82,17 +131,17 @@ namespace sqlpp namespace detail { - template + template using make_multi_column_t = - detail::copy_tuple_args_t::_(std::declval())...))>; } - template - auto multi_column(const AliasProvider&, Columns... columns) - -> detail::make_multi_column_t + template + auto multi_column(Columns... columns) + -> detail::make_multi_column_t { - return detail::make_multi_column_t(std::tuple_cat(detail::as_tuple::_(columns)...)); + return detail::make_multi_column_t(std::tuple_cat(detail::as_tuple::_(columns)...)); } diff --git a/include/sqlpp11/table.h b/include/sqlpp11/table.h index afa9f95e..d8930c73 100644 --- a/include/sqlpp11/table.h +++ b/include/sqlpp11/table.h @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -42,10 +43,9 @@ namespace sqlpp struct table_t: public table_base_t, public ColumnSpec::_name_t::template _member_t>... { using _table_set = detail::type_set
; // Hint need a type_set here to be similar to a join (which always represents more than one table) - using _all_columns = typename detail::make_set...>::type; - static_assert(_all_columns::size::value, "at least one column required per table"); + static_assert(sizeof...(ColumnSpec), "at least one column required per table"); using _required_insert_columns = typename detail::make_set_if...>::type; - using _all_of_t = std::tuple...>; + using _column_tuple_t = std::tuple...>; template using _alias_t = table_alias_t; @@ -93,12 +93,6 @@ namespace sqlpp } }; - template - auto all_of(Table t) -> typename Table::_all_of_t - { - return {}; - } - namespace vendor { template diff --git a/include/sqlpp11/table_alias.h b/include/sqlpp11/table_alias.h index 269d80b1..f4760eed 100644 --- a/include/sqlpp11/table_alias.h +++ b/include/sqlpp11/table_alias.h @@ -52,7 +52,7 @@ namespace sqlpp }; using _name_t = typename AliasProvider::_name_t; - using _all_of_t = std::tuple...>; + using _column_tuple_t = std::tuple...>; table_alias_t(Table table): _table(table) diff --git a/include/sqlpp11/vendor/field.h b/include/sqlpp11/vendor/field.h index 33dad90e..ca8847ec 100644 --- a/include/sqlpp11/vendor/field.h +++ b/include/sqlpp11/vendor/field.h @@ -54,7 +54,7 @@ namespace sqlpp }; template - struct make_field_t_impl> + struct make_field_t_impl> { using type = multi_field_t::type...>>; }; diff --git a/tests/InterpretTest.cpp b/tests/InterpretTest.cpp index 9772e10f..729091e0 100644 --- a/tests/InterpretTest.cpp +++ b/tests/InterpretTest.cpp @@ -127,8 +127,9 @@ int main() interpret(t.inner_join(t.as(t.alpha)).on(t.beta == t.as(t.alpha).beta), printer).flush(); // multi_column - interpret(multi_column(t.alpha, t.alpha, (t.beta + "cake").as(t.gamma)), printer).flush(); - interpret(multi_column(t, all_of(t)), printer).flush(); + interpret(multi_column(t.alpha, (t.beta + "cake").as(t.gamma)).as(t.alpha), printer).flush(); + interpret(multi_column(all_of(t)).as(t), printer).flush(); + interpret(all_of(t).as(t), printer).flush(); // dynamic select { diff --git a/tests/SelectTest.cpp b/tests/SelectTest.cpp index c41c4d85..56c3fbd4 100644 --- a/tests/SelectTest.cpp +++ b/tests/SelectTest.cpp @@ -281,21 +281,14 @@ int main() // Test that select(all_of(tab)) is expanded in multi_column { - auto a = multi_column(alias::a, all_of(t)); - auto b = multi_column(alias::a, t.alpha, t.beta, t.gamma, t.delta); + auto a = multi_column(all_of(t)).as(alias::a); + auto b = multi_column(t.alpha, t.beta, t.gamma, t.delta).as(alias::a); static_assert(std::is_same::value, "all_of(t) has to be expanded by multi_column"); } - // Test that select(tab) is expanded in multi_column - { - auto a = multi_column(alias::a, all_of(t)); - auto b = multi_column(alias::a, t.alpha, t.beta, t.gamma, t.delta); - static_assert(std::is_same::value, "t has to be expanded by multi_column"); - } - // Test that a multicolumn is not a value { - auto m = multi_column(alias::a, t.alpha, t.beta); + auto m = multi_column(t.alpha, t.beta).as(alias::a); auto a = select(m).from(t).as(alias::b).a; static_assert(not sqlpp::is_value_t::value, "a multi_column is not a value"); } From 8b37626b89abef7d9415f7a877c84244672ed7c8 Mon Sep 17 00:00:00 2001 From: rbock Date: Sun, 16 Feb 2014 12:41:59 +0100 Subject: [PATCH 23/74] Added uniqueness constraint to type_set, plus minor cleanup --- include/sqlpp11/detail/type_set.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/include/sqlpp11/detail/type_set.h b/include/sqlpp11/detail/type_set.h index e9b8d6e5..53450cbe 100644 --- a/include/sqlpp11/detail/type_set.h +++ b/include/sqlpp11/detail/type_set.h @@ -41,19 +41,20 @@ namespace sqlpp struct make_set; // A type set - template + template struct type_set { - using _elements_t = std::tuple; - using size = std::tuple_size<_elements_t>; + using size = std::integral_constant; using _is_type_set = std::true_type; + static_assert(std::is_same::type>::value, "use make_set to construct a set"); + template struct count { template using same = std::is_same; - static constexpr bool value = or_t::value; + static constexpr bool value = or_t::value; }; template @@ -77,7 +78,7 @@ namespace sqlpp template struct join> { - using type = typename make_set::type; + using type = typename make_set::type; }; template @@ -101,7 +102,7 @@ namespace sqlpp template struct is_disjunct_from> { - static constexpr bool value = not(or_t::value or or_t::template count, Element...>::value); + static constexpr bool value = not(or_t::value or or_t::template count, Elements...>::value); }; template @@ -109,14 +110,14 @@ namespace sqlpp { using type = typename std::conditional::value, type_set, - type_set>::type; + type_set>::type; }; template class Predicate, typename T> struct insert_if { using type = typename std::conditional::value, - type_set, + type_set, type_set>::type; }; }; From 1d5ee2068d00eaac7dafdb1cc7b789d0845ea14a Mon Sep 17 00:00:00 2001 From: rbock Date: Sun, 16 Feb 2014 13:16:09 +0100 Subject: [PATCH 24/74] Fixed a bunch of bugs found while adjusting the mysql connector --- include/sqlpp11/any.h | 2 +- include/sqlpp11/remove.h | 4 ++-- include/sqlpp11/some.h | 3 ++- include/sqlpp11/update.h | 2 +- include/sqlpp11/vendor/insert_value_list.h | 2 ++ include/sqlpp11/vendor/is_null.h | 1 + 6 files changed, 9 insertions(+), 5 deletions(-) diff --git a/include/sqlpp11/any.h b/include/sqlpp11/any.h index e4c9ceef..a5955455 100644 --- a/include/sqlpp11/any.h +++ b/include/sqlpp11/any.h @@ -57,7 +57,7 @@ namespace sqlpp }; }; - using _table_set = ::sqlpp::detail::type_set<>; // FIXME: Can selects leak tables here? + using _table_set = typename Select::_table_set; any_t(Select select): _select(select) diff --git a/include/sqlpp11/remove.h b/include/sqlpp11/remove.h index a0673934..93807f8f 100644 --- a/include/sqlpp11/remove.h +++ b/include/sqlpp11/remove.h @@ -175,7 +175,7 @@ namespace sqlpp template auto _prepare(Db& db) const - -> prepared_remove_t + -> prepared_remove_t { //static_assert(detail::check_remove_t::value, "Cannot run this remove expression"); return {{}, db.prepare_remove(*this)}; @@ -195,7 +195,7 @@ namespace sqlpp static Context& _(const T& t, Context& context) { - context << "DELETE FROM"; + context << "DELETE FROM "; interpret(t._table, context); interpret(t._using, context); interpret(t._where, context); diff --git a/include/sqlpp11/some.h b/include/sqlpp11/some.h index c9f26081..268ec963 100644 --- a/include/sqlpp11/some.h +++ b/include/sqlpp11/some.h @@ -27,8 +27,8 @@ #ifndef SQLPP_SOME_H #define SQLPP_SOME_H -#include #include +#include namespace sqlpp { @@ -56,6 +56,7 @@ namespace sqlpp const T& operator()() const { return some; } }; }; + using _table_set = typename Select::_table_set; some_t(Select select): _select(select) diff --git a/include/sqlpp11/update.h b/include/sqlpp11/update.h index a26a34aa..7485a453 100644 --- a/include/sqlpp11/update.h +++ b/include/sqlpp11/update.h @@ -178,7 +178,7 @@ namespace sqlpp template auto _prepare(Db& db) const - -> prepared_update_t + -> prepared_update_t { return {{}, db.prepare_update(*this)}; } diff --git a/include/sqlpp11/vendor/insert_value_list.h b/include/sqlpp11/vendor/insert_value_list.h index 9959c823..aa16d582 100644 --- a/include/sqlpp11/vendor/insert_value_list.h +++ b/include/sqlpp11/vendor/insert_value_list.h @@ -29,6 +29,8 @@ #include #include +#include +#include #include #include #include diff --git a/include/sqlpp11/vendor/is_null.h b/include/sqlpp11/vendor/is_null.h index 7b7dab61..6095fb89 100644 --- a/include/sqlpp11/vendor/is_null.h +++ b/include/sqlpp11/vendor/is_null.h @@ -39,6 +39,7 @@ namespace sqlpp struct is_null_t: public boolean::template operators> { static constexpr bool _inverted = not NotInverted; + using _table_set = typename Operand::_table_set; struct _value_type: public boolean { From 26f322b86a3209c97a240a485f8a20da77a499f5 Mon Sep 17 00:00:00 2001 From: rbock Date: Sun, 16 Feb 2014 19:32:43 +0100 Subject: [PATCH 25/74] Expressed equal_to, not_equal_to, logical_not as binary/unary expressions --- include/sqlpp11/basic_operators.h | 4 +- include/sqlpp11/vendor/expression.h | 68 +++++++++++++------------ include/sqlpp11/vendor/expression_fwd.h | 41 ++++++++++----- 3 files changed, 65 insertions(+), 48 deletions(-) diff --git a/include/sqlpp11/basic_operators.h b/include/sqlpp11/basic_operators.h index 0c4ec513..b832ffbf 100644 --- a/include/sqlpp11/basic_operators.h +++ b/include/sqlpp11/basic_operators.h @@ -46,14 +46,14 @@ namespace sqlpp struct basic_operators { template - vendor::equal_t::type> operator==(T t) const + vendor::equal_to_t::type> operator==(T t) const { static_assert(not is_multi_expression_t::value, "multi-expression cannot be used as left hand side operand"); return { *static_cast(this), {t} }; } template - vendor::not_equal_t::type> operator!=(T t) const + vendor::not_equal_to_t::type> operator!=(T t) const { static_assert(not is_multi_expression_t::value, "multi-expression cannot be used as left hand side operand"); return { *static_cast(this), {t} }; diff --git a/include/sqlpp11/vendor/expression.h b/include/sqlpp11/vendor/expression.h index 48c71c5a..fa068dd2 100644 --- a/include/sqlpp11/vendor/expression.h +++ b/include/sqlpp11/vendor/expression.h @@ -40,31 +40,31 @@ namespace sqlpp namespace vendor { template - struct equal_t: public ::sqlpp::detail::boolean::template operators> + struct binary_expression_t: public ::sqlpp::detail::boolean::template operators> { using _value_type = ::sqlpp::detail::boolean; using _parameter_tuple_t = std::tuple; using _table_set = typename ::sqlpp::detail::make_joined_set::type; - equal_t(Lhs lhs, Rhs rhs): + binary_expression_t(Lhs lhs, Rhs rhs): _lhs(lhs), _rhs(rhs) {} - equal_t(const equal_t&) = default; - equal_t(equal_t&&) = default; - equal_t& operator=(const equal_t&) = default; - equal_t& operator=(equal_t&&) = default; - ~equal_t() = default; + binary_expression_t(const binary_expression_t&) = default; + binary_expression_t(binary_expression_t&&) = default; + binary_expression_t& operator=(const binary_expression_t&) = default; + binary_expression_t& operator=(binary_expression_t&&) = default; + ~binary_expression_t() = default; Lhs _lhs; tvin_wrap_t _rhs; }; template - struct interpreter_t> + struct interpreter_t> { - using T = equal_t; + using T = equal_to_t; static Context& _(const T& t, Context& context) { @@ -85,31 +85,32 @@ namespace sqlpp }; template - struct not_equal_t: public ::sqlpp::detail::boolean::template operators> + struct binary_expression_t: public ::sqlpp::detail::boolean::template operators> { using _value_type = ::sqlpp::detail::boolean; using _parameter_tuple_t = std::tuple; using _table_set = typename ::sqlpp::detail::make_joined_set::type; - not_equal_t(Lhs lhs, Rhs rhs): + binary_expression_t(Lhs lhs, Rhs rhs): _lhs(lhs), _rhs(rhs) {} - not_equal_t(const not_equal_t&) = default; - not_equal_t(not_equal_t&&) = default; - not_equal_t& operator=(const not_equal_t&) = default; - not_equal_t& operator=(not_equal_t&&) = default; - ~not_equal_t() = default; + binary_expression_t(const binary_expression_t&) = default; + binary_expression_t(binary_expression_t&&) = default; + binary_expression_t& operator=(const binary_expression_t&) = default; + binary_expression_t& operator=(binary_expression_t&&) = default; + ~binary_expression_t() = default; Lhs _lhs; tvin_wrap_t _rhs; }; + /* template - struct interpreter_t> + struct interpreter_t> { - using T = not_equal_t; + using T = not_equal_to_t; static Context& _(const T& t, Context& context) { @@ -128,31 +129,32 @@ namespace sqlpp return context; } }; + */ - template - struct logical_not_t: public ::sqlpp::detail::boolean::template operators> + template + struct unary_expression_t: public ::sqlpp::detail::boolean::template operators> { using _value_type = ::sqlpp::detail::boolean; - using _parameter_tuple_t = std::tuple; - using _table_set = typename Lhs::_table_set; + using _parameter_tuple_t = std::tuple; + using _table_set = typename Rhs::_table_set; - logical_not_t(Lhs l): - _lhs(l) + unary_expression_t(Rhs rhs): + _rhs(rhs) {} - logical_not_t(const logical_not_t&) = default; - logical_not_t(logical_not_t&&) = default; - logical_not_t& operator=(const logical_not_t&) = default; - logical_not_t& operator=(logical_not_t&&) = default; - ~logical_not_t() = default; + unary_expression_t(const unary_expression_t&) = default; + unary_expression_t(unary_expression_t&&) = default; + unary_expression_t& operator=(const unary_expression_t&) = default; + unary_expression_t& operator=(unary_expression_t&&) = default; + ~unary_expression_t() = default; - Lhs _lhs; + Rhs _rhs; }; - template - struct interpreter_t> + template + struct interpreter_t> { - using T = logical_not_t; + using T = logical_not_t; static Context& _(const T& t, Context& context) { diff --git a/include/sqlpp11/vendor/expression_fwd.h b/include/sqlpp11/vendor/expression_fwd.h index 0cf2cfab..86166706 100644 --- a/include/sqlpp11/vendor/expression_fwd.h +++ b/include/sqlpp11/vendor/expression_fwd.h @@ -31,18 +31,9 @@ namespace sqlpp { namespace vendor { - template - struct equal_t; - - template - struct not_equal_t; - - template - struct logical_not_t; - namespace tag { - struct less_than + struct less { using _value_type = ::sqlpp::detail::boolean; static constexpr const char* _name = "<"; @@ -54,13 +45,23 @@ namespace sqlpp static constexpr const char* _name = "<="; }; + struct equal_to + { + using _value_type = ::sqlpp::detail::boolean; + }; + + struct not_equal_to + { + using _value_type = ::sqlpp::detail::boolean; + }; + struct greater_equal { using _value_type = ::sqlpp::detail::boolean; static constexpr const char* _name = ">="; }; - struct greater_than + struct greater { using _value_type = ::sqlpp::detail::boolean; static constexpr const char* _name = ">"; @@ -78,6 +79,11 @@ namespace sqlpp static constexpr const char* _name = " AND "; }; + struct logical_not + { + using _value_type = ::sqlpp::detail::boolean; + }; + template struct plus { @@ -133,13 +139,19 @@ namespace sqlpp struct unary_expression_t; template - using less_than_t = binary_expression_t; + using less_than_t = binary_expression_t; template using less_equal_t = binary_expression_t; template - using greater_than_t = binary_expression_t; + using equal_to_t = binary_expression_t; + + template + using not_equal_to_t = binary_expression_t; + + template + using greater_than_t = binary_expression_t; template using greater_equal_t = binary_expression_t; @@ -165,6 +177,9 @@ namespace sqlpp template using modulus_t = binary_expression_t; + template + using logical_not_t = unary_expression_t; + template using unary_plus_t = unary_expression_t, Rhs>; From abf4bb8e9a9e074bd4e31999a1aad9c3235a2661 Mon Sep 17 00:00:00 2001 From: rbock Date: Tue, 18 Feb 2014 17:45:08 +0100 Subject: [PATCH 26/74] Added serializer to interpreter The serializer has partial specializations for all templates. It is a good basis if the connector/database requires strings close to the standard. The interpreter is unspecialized (and uses a static assert to say so). It is a good basis if the connector/database requires a different interpretation, e.g. re-writing the expression tree. The interpretable_t implements three methods for interpretation: serializing with the sqlpp::serializer_context, serializing with the database's serialization context and interpretation with the database's interpretation context. --- include/sqlpp11/alias.h | 4 +- include/sqlpp11/all_of.h | 2 +- include/sqlpp11/any.h | 4 +- include/sqlpp11/avg.h | 7 +- include/sqlpp11/column.h | 4 +- include/sqlpp11/count.h | 6 +- include/sqlpp11/default_value.h | 2 +- include/sqlpp11/exists.h | 4 +- include/sqlpp11/functions.h | 8 +- include/sqlpp11/insert.h | 6 +- include/sqlpp11/join.h | 8 +- include/sqlpp11/max.h | 5 +- include/sqlpp11/min.h | 5 +- include/sqlpp11/multi_column.h | 4 +- include/sqlpp11/null.h | 2 +- include/sqlpp11/on.h | 2 +- include/sqlpp11/parameter.h | 2 +- include/sqlpp11/remove.h | 8 +- include/sqlpp11/select.h | 22 +-- include/sqlpp11/select_flags.h | 6 +- include/sqlpp11/serialize.h | 43 ++++++ .../{serializer.h => serializer_context.h} | 9 +- include/sqlpp11/some.h | 4 +- include/sqlpp11/sort_order.h | 4 +- include/sqlpp11/sum.h | 7 +- include/sqlpp11/table.h | 2 +- include/sqlpp11/table_alias.h | 4 +- include/sqlpp11/tvin.h | 9 +- include/sqlpp11/update.h | 8 +- include/sqlpp11/vendor/assignment.h | 15 +- include/sqlpp11/vendor/concat.h | 2 +- include/sqlpp11/vendor/expression.h | 30 ++-- include/sqlpp11/vendor/from.h | 4 +- include/sqlpp11/vendor/group_by.h | 4 +- include/sqlpp11/vendor/having.h | 4 +- include/sqlpp11/vendor/in.h | 4 +- include/sqlpp11/vendor/insert_value.h | 6 +- include/sqlpp11/vendor/insert_value_list.h | 10 +- include/sqlpp11/vendor/interpret_tuple.h | 4 +- include/sqlpp11/vendor/interpretable.h | 40 +++-- include/sqlpp11/vendor/interpretable_list.h | 2 +- include/sqlpp11/vendor/is_null.h | 4 +- include/sqlpp11/vendor/like.h | 6 +- include/sqlpp11/vendor/limit.h | 10 +- include/sqlpp11/vendor/named_interpretable.h | 39 +++-- include/sqlpp11/vendor/noop.h | 2 +- include/sqlpp11/vendor/offset.h | 10 +- include/sqlpp11/vendor/order_by.h | 4 +- include/sqlpp11/vendor/select_column_list.h | 12 +- include/sqlpp11/vendor/select_flag_list.h | 4 +- include/sqlpp11/vendor/select_pseudo_table.h | 4 +- include/sqlpp11/vendor/serializer.h | 48 ++++++ include/sqlpp11/vendor/simple_column.h | 4 +- include/sqlpp11/vendor/single_table.h | 4 +- include/sqlpp11/vendor/update_list.h | 4 +- include/sqlpp11/vendor/using.h | 4 +- include/sqlpp11/vendor/where.h | 6 +- include/sqlpp11/vendor/wrap_operand.h | 10 +- include/sqlpp11/verbatim_table.h | 2 +- tests/InsertTest.cpp | 12 +- tests/InterpretTest.cpp | 144 +++++++++--------- tests/MockDb.h | 21 ++- tests/RemoveTest.cpp | 10 +- tests/SelectTest.cpp | 14 +- tests/UpdateTest.cpp | 12 +- 65 files changed, 423 insertions(+), 293 deletions(-) create mode 100644 include/sqlpp11/serialize.h rename include/sqlpp11/{serializer.h => serializer_context.h} (90%) create mode 100644 include/sqlpp11/vendor/serializer.h diff --git a/include/sqlpp11/alias.h b/include/sqlpp11/alias.h index 179b6c50..f9d65fc4 100644 --- a/include/sqlpp11/alias.h +++ b/include/sqlpp11/alias.h @@ -48,14 +48,14 @@ namespace sqlpp namespace vendor { template - struct interpreter_t> + struct serializer_t> { using T = expression_alias_t; static Context& _(const T& t, Context& context) { context << '('; - interpret(t._expression, context); + serialize(t._expression, context); context << ") AS "; context << T::_name_t::_get_name(); return context; diff --git a/include/sqlpp11/all_of.h b/include/sqlpp11/all_of.h index fb4f50b3..7376490b 100644 --- a/include/sqlpp11/all_of.h +++ b/include/sqlpp11/all_of.h @@ -54,7 +54,7 @@ namespace sqlpp namespace vendor { template - struct interpreter_t> + struct serializer_t> { using T = all_of_t
; diff --git a/include/sqlpp11/any.h b/include/sqlpp11/any.h index a5955455..6bacf054 100644 --- a/include/sqlpp11/any.h +++ b/include/sqlpp11/any.h @@ -76,14 +76,14 @@ namespace sqlpp namespace vendor { template - struct interpreter_t> + struct serializer_t> { using T = vendor::any_t; static Context& _(const T& t, Context& context) { context << "EXISTS("; - interpret(t._select, context); + serialize(t._select, context); context << ")"; return context; } diff --git a/include/sqlpp11/functions.h b/include/sqlpp11/functions.h index 9aabf960..cdd556fa 100644 --- a/include/sqlpp11/functions.h +++ b/include/sqlpp11/functions.h @@ -71,7 +71,7 @@ namespace sqlpp namespace vendor { template - struct interpreter_t> + struct serializer_t> { using T = verbatim_t; @@ -94,7 +94,7 @@ namespace sqlpp { static_assert(not make_parameter_list_t::type::size::value, "parameters not supported in flattened expressions"); context.clear(); - interpret(exp, context); + serialize(exp, context); return { context.str() }; } @@ -121,7 +121,7 @@ namespace sqlpp namespace vendor { template - struct interpreter_t> + struct serializer_t> { using T = value_list_t; @@ -135,7 +135,7 @@ namespace sqlpp else context << ','; - interpret(value(entry), context); + serialize(value(entry), context); } return context; } diff --git a/include/sqlpp11/insert.h b/include/sqlpp11/insert.h index e1ee5593..eb60554a 100644 --- a/include/sqlpp11/insert.h +++ b/include/sqlpp11/insert.h @@ -166,15 +166,15 @@ namespace sqlpp namespace vendor { template - struct interpreter_t> + struct serializer_t> { using T = insert_t; static Context& _(const T& t, Context& context) { context << "INSERT INTO "; - interpret(t._table, context); - interpret(t._insert_value_list, context); + serialize(t._table, context); + serialize(t._insert_value_list, context); return context; } }; diff --git a/include/sqlpp11/join.h b/include/sqlpp11/join.h index b8cffea7..23816184 100644 --- a/include/sqlpp11/join.h +++ b/include/sqlpp11/join.h @@ -145,18 +145,18 @@ namespace sqlpp namespace vendor { template - struct interpreter_t> + struct serializer_t> { using T = join_t; static Context& _(const T& t, Context& context) { static_assert(not vendor::is_noop::value, "joined tables require on()"); - interpret(t._lhs, context); + serialize(t._lhs, context); context << JoinType::_name; context << " JOIN "; - interpret(t._rhs, context); - interpret(t._on, context); + serialize(t._rhs, context); + serialize(t._on, context); return context; } }; diff --git a/include/sqlpp11/max.h b/include/sqlpp11/max.h index 9e36d2b8..241ab544 100644 --- a/include/sqlpp11/max.h +++ b/include/sqlpp11/max.h @@ -27,7 +27,6 @@ #ifndef SQLPP_MAX_H #define SQLPP_MAX_H -#include #include namespace sqlpp @@ -73,14 +72,14 @@ namespace sqlpp namespace vendor { template - struct interpreter_t> + struct serializer_t> { using T = vendor::max_t; static Context& _(const T& t, Context& context) { context << "MAX("; - interpret(t._expr, context); + serialize(t._expr, context); context << ")"; return context; } diff --git a/include/sqlpp11/min.h b/include/sqlpp11/min.h index 9e35549c..4fd7d5c8 100644 --- a/include/sqlpp11/min.h +++ b/include/sqlpp11/min.h @@ -27,7 +27,6 @@ #ifndef SQLPP_MIN_H #define SQLPP_MIN_H -#include #include namespace sqlpp @@ -73,14 +72,14 @@ namespace sqlpp namespace vendor { template - struct interpreter_t> + struct serializer_t> { using T = vendor::min_t; static Context& _(const T& t, Context& context) { context << "MIN("; - interpret(t._expr, context); + serialize(t._expr, context); context << ")"; return context; } diff --git a/include/sqlpp11/multi_column.h b/include/sqlpp11/multi_column.h index f75169e7..c6260b30 100644 --- a/include/sqlpp11/multi_column.h +++ b/include/sqlpp11/multi_column.h @@ -106,7 +106,7 @@ namespace sqlpp namespace vendor { template - struct interpreter_t> + struct serializer_t> { using T = multi_column_t; @@ -117,7 +117,7 @@ namespace sqlpp }; template - struct interpreter_t> + struct serializer_t> { using T = multi_column_alias_t; diff --git a/include/sqlpp11/null.h b/include/sqlpp11/null.h index 643511a8..af742da1 100644 --- a/include/sqlpp11/null.h +++ b/include/sqlpp11/null.h @@ -43,7 +43,7 @@ namespace sqlpp namespace vendor { template - struct interpreter_t + struct serializer_t { using Operand = null_t; diff --git a/include/sqlpp11/on.h b/include/sqlpp11/on.h index 68c1297d..96ade430 100644 --- a/include/sqlpp11/on.h +++ b/include/sqlpp11/on.h @@ -57,7 +57,7 @@ namespace sqlpp namespace vendor { template - struct interpreter_t> + struct serializer_t> { using T = on_t; diff --git a/include/sqlpp11/parameter.h b/include/sqlpp11/parameter.h index 875e738a..260dc88a 100644 --- a/include/sqlpp11/parameter.h +++ b/include/sqlpp11/parameter.h @@ -54,7 +54,7 @@ namespace sqlpp namespace vendor { template - struct interpreter_t> + struct serializer_t> { using T = parameter_t; diff --git a/include/sqlpp11/remove.h b/include/sqlpp11/remove.h index 93807f8f..557b0f6d 100644 --- a/include/sqlpp11/remove.h +++ b/include/sqlpp11/remove.h @@ -189,16 +189,16 @@ namespace sqlpp namespace vendor { template - struct interpreter_t> + struct serializer_t> { using T = remove_t; static Context& _(const T& t, Context& context) { context << "DELETE FROM "; - interpret(t._table, context); - interpret(t._using, context); - interpret(t._where, context); + serialize(t._table, context); + serialize(t._using, context); + serialize(t._where, context); return context; } }; diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index aa5e5983..9ef444cf 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include #include @@ -540,7 +540,7 @@ namespace sqlpp namespace vendor { template - struct interpreter_t> + struct serializer_t> { using T = select_t; @@ -548,15 +548,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); + serialize(t._flag_list, context); + serialize(t._column_list, context); + serialize(t._from, context); + serialize(t._where, context); + serialize(t._group_by, context); + serialize(t._having, context); + serialize(t._order_by, context); + serialize(t._limit, context); + serialize(t._offset, context); return context; } diff --git a/include/sqlpp11/select_flags.h b/include/sqlpp11/select_flags.h index f59a6ae4..8335dd75 100644 --- a/include/sqlpp11/select_flags.h +++ b/include/sqlpp11/select_flags.h @@ -47,7 +47,7 @@ namespace sqlpp namespace vendor { template - struct interpreter_t + struct serializer_t { static Context& _(const all_t&, Context& context) { @@ -69,7 +69,7 @@ namespace sqlpp namespace vendor { template - struct interpreter_t + struct serializer_t { static Context& _(const distinct_t&, Context& context) { @@ -91,7 +91,7 @@ namespace sqlpp namespace vendor { template - struct interpreter_t + struct serializer_t { static Context& _(const straight_join_t&, Context& context) { diff --git a/include/sqlpp11/serialize.h b/include/sqlpp11/serialize.h new file mode 100644 index 00000000..8ff650ef --- /dev/null +++ b/include/sqlpp11/serialize.h @@ -0,0 +1,43 @@ +/* + * 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_SERIALIZE_H +#define SQLPP_SERIALIZE_H + +#include + +namespace sqlpp +{ + template + auto serialize(const T& t, Context& context) + -> decltype(vendor::serializer_t::_(t, context)) + { + return vendor::serializer_t::_(t, context); + } + +} + +#endif diff --git a/include/sqlpp11/serializer.h b/include/sqlpp11/serializer_context.h similarity index 90% rename from include/sqlpp11/serializer.h rename to include/sqlpp11/serializer_context.h index d8bbaaee..8e3ee35d 100644 --- a/include/sqlpp11/serializer.h +++ b/include/sqlpp11/serializer_context.h @@ -23,16 +23,16 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SQLPP_SERIALIZER_H -#define SQLPP_SERIALIZER_H +#ifndef SQLPP_SERIALIZER_CONTEXT_H +#define SQLPP_SERIALIZER_CONTEXT_H #include namespace sqlpp { - struct serializer_t + struct serializer_context_t { - serializer_t(std::ostream& os): + serializer_context_t(std::ostream& os): _os(os) {} @@ -49,6 +49,7 @@ namespace sqlpp std::string escape(std::string arg) { +// FIXME: Need to do better escaping return arg; } diff --git a/include/sqlpp11/some.h b/include/sqlpp11/some.h index 268ec963..54a1fe5b 100644 --- a/include/sqlpp11/some.h +++ b/include/sqlpp11/some.h @@ -75,14 +75,14 @@ namespace sqlpp namespace vendor { template - struct interpreter_t> + struct serializer_t> { using T = vendor::some_t
; // Hint need a type_set here to be similar to a join (which always represents more than one table) static_assert(sizeof...(ColumnSpec), "at least one column required per table"); - using _required_insert_columns = typename detail::make_set_if...>::type; + using _required_insert_columns = typename detail::make_type_set_if...>::type; using _column_tuple_t = std::tuple...>; template using _alias_t = table_alias_t; diff --git a/include/sqlpp11/update.h b/include/sqlpp11/update.h index 9173a969..5c8be581 100644 --- a/include/sqlpp11/update.h +++ b/include/sqlpp11/update.h @@ -57,8 +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"); - static_assert(Table::_table_set::template is_superset_of::value, "where condition does not match updated table"); + static_assert(::sqlpp::detail::is_superset_of::value, "updated columns do not match the table"); + static_assert(::sqlpp::detail::is_superset_of::value, "where condition does not match updated table"); using _database_t = Database; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; diff --git a/include/sqlpp11/vendor/assignment.h b/include/sqlpp11/vendor/assignment.h index 5a21731b..c3e17156 100644 --- a/include/sqlpp11/vendor/assignment.h +++ b/include/sqlpp11/vendor/assignment.h @@ -69,7 +69,7 @@ namespace sqlpp using _column_t = Lhs; using value_type = Rhs; using _parameter_tuple_t = std::tuple<_column_t, Rhs>; - using _table_set = typename Lhs::_table_set::template join::type; + using _table_set = typename ::sqlpp::detail::make_joined_set::type; static_assert(can_be_null_t<_column_t>::value ? true : not std::is_same::value, "column must not be null"); @@ -119,6 +119,7 @@ namespace sqlpp using _column_t = Lhs; using value_type = tvin_t; using _parameter_tuple_t = std::tuple<_column_t, Rhs>; + using _table_set = typename ::sqlpp::detail::make_joined_set::type; static_assert(can_be_null_t<_column_t>::value, "column cannot be null"); diff --git a/include/sqlpp11/vendor/concat.h b/include/sqlpp11/vendor/concat.h index 9d851da5..fb8e97b4 100644 --- a/include/sqlpp11/vendor/concat.h +++ b/include/sqlpp11/vendor/concat.h @@ -39,7 +39,7 @@ namespace sqlpp struct concat_t: public First::_value_type::template operators> { static_assert(sizeof...(Args) > 0, "concat requires two arguments at least"); - static_assert(sqlpp::detail::and_t::value, "at least one non-text argument detected in concat()"); + static_assert(sqlpp::detail::all_t::value, "at least one non-text argument detected in concat()"); using _table_set = typename ::sqlpp::detail::make_joined_set::type; struct _value_type: public First::_value_type::_base_value_type diff --git a/include/sqlpp11/vendor/expression.h b/include/sqlpp11/vendor/expression.h index 9d2a8868..455aebb7 100644 --- a/include/sqlpp11/vendor/expression.h +++ b/include/sqlpp11/vendor/expression.h @@ -209,6 +209,7 @@ namespace sqlpp { using _value_type = typename O::_value_type; using _parameter_tuple_t = std::tuple; + using _table_set = typename Rhs::_table_set; unary_expression_t(Rhs rhs): _rhs(rhs) diff --git a/include/sqlpp11/vendor/from.h b/include/sqlpp11/vendor/from.h index ce9dc50b..87ae0c7a 100644 --- a/include/sqlpp11/vendor/from.h +++ b/include/sqlpp11/vendor/from.h @@ -49,7 +49,7 @@ namespace sqlpp // FIXME: Joins contain two tables. This is not being dealt with at the moment when looking at duplicates, for instance static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in from()"); - static_assert(::sqlpp::detail::and_t::value, "at least one argument is not a table or join in from()"); + static_assert(::sqlpp::detail::all_t::value, "at least one argument is not a table or join in from()"); using _table_set = typename ::sqlpp::detail::make_joined_set; diff --git a/include/sqlpp11/vendor/group_by.h b/include/sqlpp11/vendor/group_by.h index d67764b7..cefd2c8d 100644 --- a/include/sqlpp11/vendor/group_by.h +++ b/include/sqlpp11/vendor/group_by.h @@ -51,7 +51,7 @@ namespace sqlpp static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in group_by()"); - static_assert(::sqlpp::detail::and_t::value, "at least one argument is not an expression in group_by()"); + static_assert(::sqlpp::detail::all_t::value, "at least one argument is not an expression in group_by()"); group_by_t(Expressions... expressions): _expressions(expressions...) diff --git a/include/sqlpp11/vendor/having.h b/include/sqlpp11/vendor/having.h index 0a3fd34e..904e13d8 100644 --- a/include/sqlpp11/vendor/having.h +++ b/include/sqlpp11/vendor/having.h @@ -47,7 +47,7 @@ namespace sqlpp using _parameter_tuple_t = std::tuple; static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in having()"); - static_assert(::sqlpp::detail::and_t::value, "at least one argument is not an expression in having()"); + static_assert(::sqlpp::detail::all_t::value, "at least one argument is not an expression in having()"); using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type; diff --git a/include/sqlpp11/vendor/insert_value_list.h b/include/sqlpp11/vendor/insert_value_list.h index 74ffecdc..c04ed95a 100644 --- a/include/sqlpp11/vendor/insert_value_list.h +++ b/include/sqlpp11/vendor/insert_value_list.h @@ -61,15 +61,15 @@ namespace sqlpp static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in set()"); - static_assert(sqlpp::detail::and_t::value, "at least one argument is not an assignment in set()"); + static_assert(sqlpp::detail::all_t::value, "at least one argument is not an assignment in set()"); - static_assert(not sqlpp::detail::or_t::value, "at least one assignment is prohibited by its column definition in set()"); + static_assert(not sqlpp::detail::any_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"); + static_assert(::sqlpp::detail::is_subset_of<_value_table_set, _column_table_set>::value, "set() contains values from foreign tables"); insert_list_t(Assignments... assignment): _assignments(assignment...), @@ -90,8 +90,8 @@ namespace sqlpp 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"); + static_assert(::sqlpp::detail::is_subset_of<_value_table_set, typename Insert::_table_set>::value, "add_set() contains a column from a foreign table"); + static_assert(::sqlpp::detail::is_subset_of<_column_table_set, typename Insert::_table_set>::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); } @@ -114,9 +114,9 @@ namespace sqlpp static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in columns()"); - static_assert(::sqlpp::detail::and_t::value, "at least one argument is not a column in columns()"); + static_assert(::sqlpp::detail::all_t::value, "at least one argument is not a column in columns()"); - static_assert(not ::sqlpp::detail::or_t::value, "at least one column argument has a must_not_insert flag in its definition"); + static_assert(not ::sqlpp::detail::any_t::value, "at least one column argument has a must_not_insert flag in its definition"); using _value_tuple_t = std::tuple...>; using _table_set = typename ::sqlpp::detail::make_joined_set::type; @@ -136,7 +136,7 @@ namespace sqlpp template void add_values(Assignments... assignments) { - static_assert(::sqlpp::detail::and_t::value, "add_values() arguments have to be assignments"); + static_assert(::sqlpp::detail::all_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"); diff --git a/include/sqlpp11/vendor/order_by.h b/include/sqlpp11/vendor/order_by.h index 391bd1dc..a96813c7 100644 --- a/include/sqlpp11/vendor/order_by.h +++ b/include/sqlpp11/vendor/order_by.h @@ -49,7 +49,7 @@ namespace sqlpp static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in order_by()"); - static_assert(::sqlpp::detail::and_t::value, "at least one argument is not a sort order expression in order_by()"); + static_assert(::sqlpp::detail::all_t::value, "at least one argument is not a sort order expression in order_by()"); order_by_t(Expressions... expressions): _expressions(expressions...) diff --git a/include/sqlpp11/vendor/select_column_list.h b/include/sqlpp11/vendor/select_column_list.h index 08ac6211..d3dd2130 100644 --- a/include/sqlpp11/vendor/select_column_list.h +++ b/include/sqlpp11/vendor/select_column_list.h @@ -143,7 +143,7 @@ namespace sqlpp template using is_valid_expression_t = std::integral_constant::value or is_multi_column_t::value>; - static_assert(::sqlpp::detail::and_t::value, "at least one argument is not a named expression"); + static_assert(::sqlpp::detail::all_t::value, "at least one argument is not a named expression"); static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate name detected"); diff --git a/include/sqlpp11/vendor/select_flag_list.h b/include/sqlpp11/vendor/select_flag_list.h index ea4ce0db..54975094 100644 --- a/include/sqlpp11/vendor/select_flag_list.h +++ b/include/sqlpp11/vendor/select_flag_list.h @@ -49,7 +49,7 @@ namespace sqlpp static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in select flag list"); - static_assert(::sqlpp::detail::and_t::value, "at least one argument is not a select flag in select flag list"); + static_assert(::sqlpp::detail::all_t::value, "at least one argument is not a select flag in select flag list"); select_flag_list_t(Flags... flags): _flags(flags...) diff --git a/include/sqlpp11/vendor/update_list.h b/include/sqlpp11/vendor/update_list.h index bd4530e0..f2684628 100644 --- a/include/sqlpp11/vendor/update_list.h +++ b/include/sqlpp11/vendor/update_list.h @@ -48,15 +48,15 @@ namespace sqlpp static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in set()"); - static_assert(::sqlpp::detail::and_t::value, "at least one argument is not an assignment in set()"); + static_assert(::sqlpp::detail::all_t::value, "at least one argument is not an assignment in set()"); - static_assert(not ::sqlpp::detail::or_t::value, "at least one assignment is prohibited by its column definition in set()"); + static_assert(not ::sqlpp::detail::any_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"); + static_assert(::sqlpp::detail::is_subset_of<_value_table_set, _column_table_set>::value, "set() contains values from foreign tables"); update_list_t(Assignments... assignments): _assignments(assignments...) diff --git a/include/sqlpp11/vendor/using.h b/include/sqlpp11/vendor/using.h index 3ef79454..940cfca9 100644 --- a/include/sqlpp11/vendor/using.h +++ b/include/sqlpp11/vendor/using.h @@ -49,7 +49,7 @@ namespace sqlpp static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in using()"); - static_assert(::sqlpp::detail::and_t::value, "at least one argument is not an table in using()"); + static_assert(::sqlpp::detail::all_t::value, "at least one argument is not an table in using()"); using_t(Tables... tables): _tables(tables...) diff --git a/include/sqlpp11/vendor/where.h b/include/sqlpp11/vendor/where.h index 63cf763b..2177ec59 100644 --- a/include/sqlpp11/vendor/where.h +++ b/include/sqlpp11/vendor/where.h @@ -47,8 +47,8 @@ namespace sqlpp using _parameter_tuple_t = std::tuple; static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in where()"); - static_assert(not sqlpp::detail::or_t::value, "at least one argument is an assignment in where()"); - static_assert(sqlpp::detail::and_t::value, "at least one argument is not valid expression in where()"); + static_assert(not sqlpp::detail::any_t::value, "at least one argument is an assignment in where()"); + static_assert(sqlpp::detail::all_t::value, "at least one argument is not valid expression in where()"); using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type; From a38a9d6f65adfc7c946ef35e7d3fa47dbe07efee Mon Sep 17 00:00:00 2001 From: rbock Date: Sun, 23 Mar 2014 20:54:44 +0100 Subject: [PATCH 36/74] Made a bunch of compile errors easier to read Fixed a few bugs in the process, too. Probably also created a few, need better checks for resulting statements. --- include/sqlpp11/alias.h | 3 + include/sqlpp11/any.h | 8 +- include/sqlpp11/avg.h | 8 +- include/sqlpp11/basic_expression_operators.h | 156 +++++++++++++++++++ include/sqlpp11/basic_operators.h | 137 ---------------- include/sqlpp11/boolean.h | 36 +++-- include/sqlpp11/column.h | 20 +-- include/sqlpp11/count.h | 10 +- include/sqlpp11/exists.h | 5 +- include/sqlpp11/floating_point.h | 80 ++++++---- include/sqlpp11/functions.h | 7 +- include/sqlpp11/integral.h | 80 ++++++---- include/sqlpp11/max.h | 5 +- include/sqlpp11/min.h | 5 +- include/sqlpp11/no_value.h | 13 +- include/sqlpp11/parameter.h | 10 +- include/sqlpp11/select.h | 2 +- include/sqlpp11/some.h | 8 +- include/sqlpp11/sum.h | 8 +- include/sqlpp11/text.h | 42 +++-- include/sqlpp11/type_traits.h | 10 -- include/sqlpp11/vendor/concat.h | 2 +- include/sqlpp11/vendor/expression.h | 10 +- include/sqlpp11/vendor/in.h | 2 +- include/sqlpp11/vendor/is_null.h | 2 +- include/sqlpp11/vendor/like.h | 2 +- include/sqlpp11/vendor/select_pseudo_table.h | 6 +- include/sqlpp11/vendor/wrap_operand.h | 4 + tests/FunctionTest.cpp | 2 + tests/SelectTypeTest.cpp | 8 +- 30 files changed, 406 insertions(+), 285 deletions(-) create mode 100644 include/sqlpp11/basic_expression_operators.h delete mode 100644 include/sqlpp11/basic_operators.h diff --git a/include/sqlpp11/alias.h b/include/sqlpp11/alias.h index f9d65fc4..7b0b4883 100644 --- a/include/sqlpp11/alias.h +++ b/include/sqlpp11/alias.h @@ -33,6 +33,9 @@ namespace sqlpp template struct expression_alias_t { + static_assert(is_expression_t::value, "invalid argument for an expression alias"); + static_assert(not is_alias_t::value, "cannot create an alias of an alias"); + struct _value_type: Expression::_value_type { using _is_expression = std::false_type; diff --git a/include/sqlpp11/any.h b/include/sqlpp11/any.h index 6bacf054..fbe4a90a 100644 --- a/include/sqlpp11/any.h +++ b/include/sqlpp11/any.h @@ -35,14 +35,15 @@ namespace sqlpp namespace vendor { template - struct any_t: public boolean::template operators> + struct any_t { static_assert(is_select_t::value, "any() requires a single column select expression as argument"); struct _value_type: public Select::_value_type::_base_value_type { - using _is_multi_expression = std::true_type; // must not be named + using _is_expression = std::false_type; + using _is_multi_expression = std::true_type; // must not be named or used with +,-,*,/, etc }; struct _name_t @@ -90,8 +91,9 @@ namespace sqlpp }; template - auto any(T t) -> typename vendor::any_t::type> + auto any(T t) -> typename vendor::any_t> { + static_assert(is_select_t>::value, "any() requires a select expression as argument"); return { t }; } diff --git a/include/sqlpp11/avg.h b/include/sqlpp11/avg.h index fed9efcb..b174b5b9 100644 --- a/include/sqlpp11/avg.h +++ b/include/sqlpp11/avg.h @@ -34,7 +34,7 @@ namespace sqlpp namespace vendor { template - struct avg_t: public floating_point::template operators> + struct avg_t: public floating_point::template expression_operators> { static_assert(is_noop::value or std::is_same::value, "avg() used with flag other than 'distinct'"); static_assert(is_numeric_t::value, "avg() requires a value expression as argument"); @@ -93,14 +93,16 @@ namespace sqlpp } template - auto avg(T t) -> typename vendor::avg_t::type> + auto avg(T t) -> typename vendor::avg_t> { + static_assert(is_numeric_t>::value, "avg() requires a value expression as argument"); return { t }; } template - auto avg(const sqlpp::distinct_t&, T t) -> typename vendor::avg_t::type> + auto avg(const sqlpp::distinct_t&, T t) -> typename vendor::avg_t> { + static_assert(is_numeric_t>::value, "avg() requires a value expression as argument"); return { t }; } diff --git a/include/sqlpp11/basic_expression_operators.h b/include/sqlpp11/basic_expression_operators.h new file mode 100644 index 00000000..72954b38 --- /dev/null +++ b/include/sqlpp11/basic_expression_operators.h @@ -0,0 +1,156 @@ +/* + * 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_DETAIL_BASIC_EXPRESSION_OPERATORS_H +#define SQLPP_DETAIL_BASIC_EXPRESSION_OPERATORS_H + +#include +#include +#include +#include +#include +#include + +namespace sqlpp +{ + + namespace detail + { + struct boolean; + } + + // basic operators + template class IsCorrectValueType> + struct basic_expression_operators + { + template + struct _is_valid_comparison_operand + { + static constexpr bool value = + (is_expression_t::value // expressions are OK + or is_multi_expression_t::value) // multi-expressions like ANY are OK for comparisons, too + and IsCorrectValueType::value // the correct value type is required, of course + ; + }; + + template + vendor::equal_to_t> operator==(T t) const + { + using rhs = vendor::wrap_operand_t; + static_assert(_is_valid_comparison_operand::value, "invalid rhs operand in comparison"); + + return { *static_cast(this), rhs{t} }; + } + + template + vendor::not_equal_to_t> operator!=(T t) const + { + using rhs = vendor::wrap_operand_t; + static_assert(_is_valid_comparison_operand::value, "invalid rhs operand in comparison"); + + return { *static_cast(this), rhs{t} }; + } + + template + vendor::less_than_t> operator<(T t) const + { + using rhs = vendor::wrap_operand_t; + static_assert(_is_valid_comparison_operand::value, "invalid rhs operand in comparison"); + + return { *static_cast(this), rhs{t} }; + } + + template + vendor::less_equal_t> operator<=(T t) const + { + using rhs = vendor::wrap_operand_t; + static_assert(_is_valid_comparison_operand::value, "invalid rhs operand in comparison"); + + return { *static_cast(this), rhs{t} }; + } + + template + vendor::greater_than_t> operator>(T t) const + { + using rhs = vendor::wrap_operand_t; + static_assert(_is_valid_comparison_operand::value, "invalid rhs operand in comparison"); + + return { *static_cast(this), rhs{t} }; + } + + template + vendor::greater_equal_t> operator>=(T t) const + { + using rhs = vendor::wrap_operand_t; + static_assert(_is_valid_comparison_operand::value, "invalid rhs operand in comparison"); + + return { *static_cast(this), rhs{t} }; + } + + vendor::is_null_t is_null() const + { + return { *static_cast(this) }; + } + + vendor::is_null_t is_not_null() const + { + return { *static_cast(this) }; + } + + sort_order_t asc() + { + return { *static_cast(this) }; + } + + sort_order_t desc() + { + return { *static_cast(this) }; + } + + // Hint: use value_list wrapper for containers... + template + vendor::in_t...> in(T... t) const + { + static_assert(detail::all_t<_is_valid_comparison_operand, vendor::wrap_operand_t...>::value, "at least one operand of in() is not valid"); + return { *static_cast(this), vendor::wrap_operand_t{t}... }; + } + + template + vendor::in_t...> not_in(T... t) const + { + static_assert(detail::all_t<_is_valid_comparison_operand, vendor::wrap_operand_t...>::value, "at least one operand of in() is not valid"); + return { *static_cast(this), vendor::wrap_operand_t{t}... }; + } + + template + expression_alias_t as(const alias_provider&) + { + return { *static_cast(this) }; + } + }; + +} +#endif diff --git a/include/sqlpp11/basic_operators.h b/include/sqlpp11/basic_operators.h deleted file mode 100644 index b832ffbf..00000000 --- a/include/sqlpp11/basic_operators.h +++ /dev/null @@ -1,137 +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_DETAIL_BASIC_OPERATORS_H -#define SQLPP_DETAIL_BASIC_OPERATORS_H - -#include -#include -#include -#include -#include - -namespace sqlpp -{ - - namespace detail - { - struct boolean; - } - - // basic operators - template class Constraint> - struct basic_operators - { - template - vendor::equal_to_t::type> operator==(T t) const - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used as left hand side operand"); - return { *static_cast(this), {t} }; - } - - template - vendor::not_equal_to_t::type> operator!=(T t) const - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used as left hand side operand"); - return { *static_cast(this), {t} }; - } - template - vendor::less_than_t::type> operator<(T t) const - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used as left hand side operand"); - return { *static_cast(this), {t} }; - } - - template - vendor::less_equal_t::type> operator<=(T t) const - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used as left hand side operand"); - return { *static_cast(this), {t} }; - } - - template - vendor::greater_than_t::type> operator>(T t) const - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used as left hand side operand"); - return { *static_cast(this), {t} }; - } - - template - vendor::greater_equal_t::type> operator>=(T t) const - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used as left hand side operand"); - return { *static_cast(this), {t} }; - } - - vendor::is_null_t is_null() const - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used with is_null()"); - return { *static_cast(this) }; - } - - vendor::is_null_t is_not_null() const - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used with is_not_null()"); - return { *static_cast(this) }; - } - - sort_order_t asc() - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used for sorting"); - return { *static_cast(this) }; - } - - sort_order_t desc() - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used for sorting"); - return { *static_cast(this) }; - } - - // Hint: use value_list wrapper for containers... - template - vendor::in_t::type...> in(T... t) const - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used with in()"); - return { *static_cast(this), {t}... }; - } - - template - vendor::in_t::type...> not_in(T... t) const - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot with be used with not_in()"); - return { *static_cast(this), {t}... }; - } - - template - expression_alias_t as(const alias_provider&) - { - static_assert(not is_multi_expression_t::value, "multi-expression cannot have a name"); - return { *static_cast(this) }; - } - }; - -} -#endif diff --git a/include/sqlpp11/boolean.h b/include/sqlpp11/boolean.h index 117d75b9..27f2ed5c 100644 --- a/include/sqlpp11/boolean.h +++ b/include/sqlpp11/boolean.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include @@ -175,33 +175,45 @@ namespace sqlpp }; template - using _operand_t = operand_t; - template - using _constraint = is_boolean_t; + struct _is_valid_operand + { + static constexpr bool value = + is_expression_t::value // expressions are OK + and is_boolean_t::value // the correct value type is required, of course + ; + }; template - struct operators: public basic_operators + struct expression_operators: public basic_expression_operators { template - vendor::logical_and_t::type> operator and(T t) const + vendor::logical_and_t> operator and(T t) const { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used as left hand side operand"); - return { *static_cast(this), {t} }; + using rhs = vendor::wrap_operand_t; + static_assert(_is_valid_operand::value, "invalid rhs operand"); + + return { *static_cast(this), rhs{t} }; } template - vendor::logical_or_t::type> operator or(T t) const + vendor::logical_or_t> operator or(T t) const { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be used as left hand side operand"); - return { *static_cast(this), {t} }; + using rhs = vendor::wrap_operand_t; + static_assert(_is_valid_operand::value, "invalid rhs operand"); + + return { *static_cast(this), rhs{t} }; } vendor::logical_not_t operator not() const { - static_assert(not is_multi_expression_t::value, "multi-expression cannot be as operand for operator not"); return { *static_cast(this) }; } }; + + template + struct column_operators + { + }; }; template diff --git a/include/sqlpp11/column.h b/include/sqlpp11/column.h index 208ae1e0..5a3bd98a 100644 --- a/include/sqlpp11/column.h +++ b/include/sqlpp11/column.h @@ -42,7 +42,8 @@ namespace sqlpp { template - struct column_t: public ColumnSpec::_value_type::template operators> + struct column_t: public ColumnSpec::_value_type::template expression_operators>, + public ColumnSpec::_value_type::template column_operators> { using _is_column = std::true_type; using _spec_t = ColumnSpec; @@ -55,6 +56,8 @@ namespace sqlpp using _is_named_expression = std::true_type; using _is_alias = std::false_type; }; + template + using _is_valid_operand = typename _value_type::template _is_valid_operand; using _name_t = typename ColumnSpec::_name_t; @@ -77,19 +80,12 @@ namespace sqlpp } template - auto operator =(T t) const - -> typename std::enable_if<_value_type::template _constraint::type>::value and not std::is_same::value, - vendor::assignment_t::type>>::type + auto operator =(T t) const -> vendor::assignment_t::type> { - return { *this, {t} }; - } + using rhs = vendor::wrap_operand_t; + static_assert(_is_valid_operand::value, "invalid rhs operand assignment operand"); - template - auto operator =(T t) const - -> typename std::enable_if::type>::value and not std::is_same::value), - vendor::assignment_t::type>>::type - { - static_assert(sqlpp::vendor::wrong_t::value, "invalid assignment operand"); + return { *this, {t} }; } auto operator =(sqlpp::null_t) const diff --git a/include/sqlpp11/count.h b/include/sqlpp11/count.h index f6253ebf..3a8de5a9 100644 --- a/include/sqlpp11/count.h +++ b/include/sqlpp11/count.h @@ -35,10 +35,10 @@ namespace sqlpp namespace vendor { template - struct count_t: public sqlpp::detail::integral::template operators> + struct count_t: public sqlpp::detail::integral::template expression_operators> { static_assert(is_noop::value or std::is_same::value, "count() used with flag other than 'distinct'"); - static_assert(is_value_t::value, "count() requires a sql value as argument"); + static_assert(is_expression_t::value, "count() requires a sql expression as argument"); struct _value_type: public sqlpp::detail::integral { @@ -94,14 +94,16 @@ namespace sqlpp } template - auto count(T t) -> typename vendor::count_t::type> + auto count(T t) -> typename vendor::count_t> { + static_assert(is_expression_t>::value, "count() requires an expression as argument"); return { t }; } template - auto count(const sqlpp::distinct_t&, T t) -> typename vendor::count_t::type> + auto count(const sqlpp::distinct_t&, T t) -> typename vendor::count_t> { + static_assert(is_expression_t>::value, "count() requires an expression as argument"); return { t }; } diff --git a/include/sqlpp11/exists.h b/include/sqlpp11/exists.h index 56fb925b..a63af7f0 100644 --- a/include/sqlpp11/exists.h +++ b/include/sqlpp11/exists.h @@ -34,7 +34,7 @@ namespace sqlpp namespace vendor { template - struct exists_t: public boolean::template operators> + struct exists_t: public boolean::template expression_operators> { static_assert(is_select_t::value, "some() requires a single column select expression as argument"); static_assert(is_value_t
::_(s._table, t)), + _insert_value_list(detail::arg_selector::_(s._insert_value_list, t)) {} insert_t(const insert_t&) = default; From 1a39d31b3e512a91828fb7514ff0836544dfdcd4 Mon Sep 17 00:00:00 2001 From: rbock Date: Wed, 26 Mar 2014 21:11:40 +0100 Subject: [PATCH 40/74] Using arg_selector for select --- include/sqlpp11/insert.h | 4 +- include/sqlpp11/select.h | 128 ++++----------------------------------- 2 files changed, 15 insertions(+), 117 deletions(-) diff --git a/include/sqlpp11/insert.h b/include/sqlpp11/insert.h index 67649f3f..18041895 100644 --- a/include/sqlpp11/insert.h +++ b/include/sqlpp11/insert.h @@ -68,8 +68,8 @@ namespace sqlpp insert_t() {} - template - insert_t(Select s, T t): + template + insert_t(Statement s, T t): _table(detail::arg_selector
::_(s._table, t)), _insert_value_list(detail::arg_selector::_(s._insert_value_list, t)) {} diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 009d5202..51c9932a 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -47,6 +47,7 @@ #include #include +#include namespace sqlpp { @@ -80,6 +81,7 @@ namespace sqlpp typename Limit = vendor::no_limit_t, typename Offset = vendor::no_offset_t > +#warning: idea: require from() for anything AFTER FROM, including dynamic columns. Then just check for from() in the run methods struct select_t: public detail::select_helper_t::_value_type::template expression_operators> { using _database_t = Database; @@ -113,121 +115,17 @@ namespace sqlpp select_t() {} - 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(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) + template + select_t(Statement s, T t): + _flag_list(detail::arg_selector::_(s._flag_list, t)), + _column_list(detail::arg_selector::_(s._column_list, t)), + _from(detail::arg_selector::_(s._from, t)), + _where(detail::arg_selector::_(s._where, t)), + _group_by(detail::arg_selector::_(s._group_by, t)), + _having(detail::arg_selector::_(s._having, t)), + _order_by(detail::arg_selector::_(s._order_by, t)), + _limit(detail::arg_selector::_(s._limit, t)), + _offset(detail::arg_selector::_(s._offset, t)) {} select_t(const select_t& r) = default; From 1a347048df3ac7c4e012d70f0e60f384ce51aae1 Mon Sep 17 00:00:00 2001 From: rbock Date: Thu, 27 Mar 2014 08:37:05 +0100 Subject: [PATCH 41/74] Migrated remove and update to using arg_selector --- include/sqlpp11/detail/arg_selector.h | 2 ++ include/sqlpp11/remove.h | 25 ++++++------------------- include/sqlpp11/update.h | 27 +++++++-------------------- 3 files changed, 15 insertions(+), 39 deletions(-) diff --git a/include/sqlpp11/detail/arg_selector.h b/include/sqlpp11/detail/arg_selector.h index 5332f33f..0b54676a 100644 --- a/include/sqlpp11/detail/arg_selector.h +++ b/include/sqlpp11/detail/arg_selector.h @@ -34,6 +34,8 @@ namespace sqlpp template struct arg_selector { + static Target _(Target, Target t) { return t; } + template static Target _(X, Target t) { return t; } diff --git a/include/sqlpp11/remove.h b/include/sqlpp11/remove.h index 557b0f6d..5392885e 100644 --- a/include/sqlpp11/remove.h +++ b/include/sqlpp11/remove.h @@ -35,6 +35,7 @@ #include #include #include +#include namespace sqlpp { @@ -75,25 +76,11 @@ namespace sqlpp remove_t() {} - template - remove_t(X x, Table table): - _table(table), - _using(x._using), - _where(x._where) - {} - - template - remove_t(X x, Using using_): - _table(x._table), - _using(using_), - _where(x._where) - {} - - template - remove_t(X x, Where where): - _table(x._table), - _using(x._using), - _where(where) + template + remove_t(Statement s, T t): + _table(detail::arg_selector
::_(s._table, t)), + _using(detail::arg_selector::_(s._using, t)), + _where(detail::arg_selector::_(s._where, t)) {} remove_t(const remove_t&) = default; diff --git a/include/sqlpp11/update.h b/include/sqlpp11/update.h index 5c8be581..39733d9a 100644 --- a/include/sqlpp11/update.h +++ b/include/sqlpp11/update.h @@ -35,6 +35,7 @@ #include #include #include +#include namespace sqlpp { @@ -75,29 +76,15 @@ namespace sqlpp using _parameter_tuple_t = std::tuple; using _parameter_list_t = typename make_parameter_list_t::type; + // Constructors update_t() {} - // Constructors - template - update_t(X x, Table table): - _table(table), - _update_list(x._update_list), - _where(x._where) - {} - - 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) + template + update_t(Statement s, T t): + _table(detail::arg_selector
::_(s._table, t)), + _update_list(detail::arg_selector::_(s._update_list, t)), + _where(detail::arg_selector::_(s._where, t)) {} update_t(const update_t&) = default; From c0595aa6f28461c43ae190c31b77a872128bec7d Mon Sep 17 00:00:00 2001 From: rbock Date: Thu, 27 Mar 2014 09:25:35 +0100 Subject: [PATCH 42/74] Fixed compile-error for parameter (need to do the same for other value types, too) --- include/sqlpp11/integral.h | 4 ++++ include/sqlpp11/parameter.h | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/sqlpp11/integral.h b/include/sqlpp11/integral.h index a90bc76d..a831ef99 100644 --- a/include/sqlpp11/integral.h +++ b/include/sqlpp11/integral.h @@ -42,12 +42,16 @@ namespace sqlpp // integral value type struct integral { +#warning why do I need base_value_type? Would it be sufficient to use _value_type instead? +#warning what is the difference between _is_value and _is_expression? using _base_value_type = integral; using _is_numeric = std::true_type; using _is_integral = std::true_type; using _is_value = std::true_type; using _is_expression = std::true_type; using _cpp_value_type = int64_t; + + using _value_type = integral; struct _parameter_t { diff --git a/include/sqlpp11/parameter.h b/include/sqlpp11/parameter.h index c4f183fc..aa75b70d 100644 --- a/include/sqlpp11/parameter.h +++ b/include/sqlpp11/parameter.h @@ -28,6 +28,7 @@ #define SQLPP_PARAMETER_H #include +#include #include namespace sqlpp @@ -81,7 +82,7 @@ namespace sqlpp auto parameter(const ValueType&, const AliasProvider&) -> parameter_t { - static_assert(is_expression_t::value, "first argument is not an expression"); + static_assert(is_value_t::value, "first argument is not a value type"); static_assert(is_alias_provider_t::value, "second argument is not an alias provider"); return {}; } From bef4d0874b42eba737b142a78a85de25ba8b5a7d Mon Sep 17 00:00:00 2001 From: rbock Date: Thu, 27 Mar 2014 16:43:36 +0100 Subject: [PATCH 43/74] Updates copyright year --- CMakeLists.txt | 2 +- LICENSE | 2 +- connector_api/bind_result.h | 2 +- connector_api/char_result.h | 2 +- connector_api/connection.h | 2 +- connector_api/interpreter.h | 2 +- connector_api/prepared_statement.h | 2 +- include/sqlpp11/alias.h | 2 +- include/sqlpp11/alias_provider.h | 2 +- include/sqlpp11/all_of.h | 2 +- include/sqlpp11/any.h | 2 +- include/sqlpp11/avg.h | 2 +- include/sqlpp11/basic_expression_operators.h | 2 +- include/sqlpp11/boolean.h | 2 +- include/sqlpp11/column.h | 2 +- include/sqlpp11/column_fwd.h | 2 +- include/sqlpp11/column_types.h | 2 +- include/sqlpp11/connection.h | 2 +- include/sqlpp11/count.h | 2 +- include/sqlpp11/default_value.h | 2 +- include/sqlpp11/detail/arg_selector.h | 2 +- include/sqlpp11/detail/copy_tuple_args.h | 2 +- include/sqlpp11/detail/logic.h | 2 +- include/sqlpp11/detail/type_set.h | 2 +- include/sqlpp11/exception.h | 2 +- include/sqlpp11/exists.h | 2 +- include/sqlpp11/floating_point.h | 2 +- include/sqlpp11/functions.h | 2 +- include/sqlpp11/insert.h | 2 +- include/sqlpp11/integral.h | 2 +- include/sqlpp11/interpret.h | 2 +- include/sqlpp11/join.h | 2 +- include/sqlpp11/max.h | 2 +- include/sqlpp11/min.h | 2 +- include/sqlpp11/multi_column.h | 2 +- include/sqlpp11/no_value.h | 2 +- include/sqlpp11/null.h | 2 +- include/sqlpp11/on.h | 2 +- include/sqlpp11/parameter.h | 2 +- include/sqlpp11/parameter_list.h | 2 +- include/sqlpp11/prepared_insert.h | 2 +- include/sqlpp11/prepared_remove.h | 2 +- include/sqlpp11/prepared_select.h | 2 +- include/sqlpp11/prepared_update.h | 2 +- include/sqlpp11/remove.h | 2 +- include/sqlpp11/result.h | 2 +- include/sqlpp11/result_row.h | 2 +- include/sqlpp11/select.h | 2 +- include/sqlpp11/select_flags.h | 2 +- include/sqlpp11/serialize.h | 2 +- include/sqlpp11/serializer_context.h | 2 +- include/sqlpp11/some.h | 2 +- include/sqlpp11/sort_order.h | 2 +- include/sqlpp11/sqlpp11.h | 2 +- include/sqlpp11/sum.h | 2 +- include/sqlpp11/table.h | 2 +- include/sqlpp11/table_alias.h | 2 +- include/sqlpp11/text.h | 2 +- include/sqlpp11/transaction.h | 2 +- include/sqlpp11/tvin.h | 2 +- include/sqlpp11/type_traits.h | 2 +- include/sqlpp11/update.h | 2 +- include/sqlpp11/vendor/assignment.h | 2 +- include/sqlpp11/vendor/char_result_row.h | 2 +- include/sqlpp11/vendor/concat.h | 2 +- include/sqlpp11/vendor/expression.h | 2 +- include/sqlpp11/vendor/expression_fwd.h | 2 +- include/sqlpp11/vendor/field.h | 2 +- include/sqlpp11/vendor/from.h | 2 +- include/sqlpp11/vendor/group_by.h | 2 +- include/sqlpp11/vendor/having.h | 2 +- include/sqlpp11/vendor/in.h | 2 +- include/sqlpp11/vendor/in_fwd.h | 2 +- include/sqlpp11/vendor/insert_value.h | 2 +- include/sqlpp11/vendor/insert_value_list.h | 2 +- include/sqlpp11/vendor/interpret_tuple.h | 2 +- include/sqlpp11/vendor/interpretable.h | 2 +- include/sqlpp11/vendor/interpretable_list.h | 2 +- include/sqlpp11/vendor/interpreter.h | 2 +- include/sqlpp11/vendor/is_null.h | 2 +- include/sqlpp11/vendor/is_null_fwd.h | 2 +- include/sqlpp11/vendor/like.h | 2 +- include/sqlpp11/vendor/limit.h | 2 +- include/sqlpp11/vendor/named_interpretable.h | 2 +- include/sqlpp11/vendor/noop.h | 2 +- include/sqlpp11/vendor/noop_fwd.h | 2 +- include/sqlpp11/vendor/offset.h | 2 +- include/sqlpp11/vendor/order_by.h | 2 +- include/sqlpp11/vendor/policy_update.h | 2 +- include/sqlpp11/vendor/select_column_list.h | 2 +- include/sqlpp11/vendor/select_flag_list.h | 2 +- include/sqlpp11/vendor/select_pseudo_table.h | 2 +- include/sqlpp11/vendor/serializer.h | 2 +- include/sqlpp11/vendor/simple_column.h | 2 +- include/sqlpp11/vendor/single_table.h | 2 +- include/sqlpp11/vendor/update_list.h | 2 +- include/sqlpp11/vendor/using.h | 2 +- include/sqlpp11/vendor/value_type.h | 2 +- include/sqlpp11/vendor/where.h | 2 +- include/sqlpp11/vendor/wrap_operand.h | 2 +- include/sqlpp11/vendor/wrong.h | 2 +- include/sqlpp11/verbatim_table.h | 2 +- scripts/ddl2cpp | 2 +- tests/FunctionTest.cpp | 2 +- tests/InsertTest.cpp | 2 +- tests/InterpretTest.cpp | 2 +- tests/MockDb.h | 2 +- tests/PreparedTest.cpp | 2 +- tests/RemoveTest.cpp | 2 +- tests/SelectTest.cpp | 2 +- tests/SelectTypeTest.cpp | 2 +- tests/UpdateTest.cpp | 2 +- tests/is_regular.h | 2 +- tests/sample.sql | 2 +- 114 files changed, 114 insertions(+), 114 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5af682b1..a3d8eeaf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2013, Roland Bock +# Copyright (c) 2013-2014, Roland Bock # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, diff --git a/LICENSE b/LICENSE index c53feede..32872e75 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2013, Roland Bock +Copyright (c) 2013-2014, Roland Bock All rights reserved. Redistribution and use in source and binary forms, with or without modification, diff --git a/connector_api/bind_result.h b/connector_api/bind_result.h index 8999c357..d1405e7d 100644 --- a/connector_api/bind_result.h +++ b/connector_api/bind_result.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/connector_api/char_result.h b/connector_api/char_result.h index 355ba959..02ab2014 100644 --- a/connector_api/char_result.h +++ b/connector_api/char_result.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/connector_api/connection.h b/connector_api/connection.h index d6e98663..b6946324 100644 --- a/connector_api/connection.h +++ b/connector_api/connection.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/connector_api/interpreter.h b/connector_api/interpreter.h index 9a83c008..90295276 100644 --- a/connector_api/interpreter.h +++ b/connector_api/interpreter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/connector_api/prepared_statement.h b/connector_api/prepared_statement.h index 4a99ee03..5a3dc94a 100644 --- a/connector_api/prepared_statement.h +++ b/connector_api/prepared_statement.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/alias.h b/include/sqlpp11/alias.h index 7b0b4883..0d781a7a 100644 --- a/include/sqlpp11/alias.h +++ b/include/sqlpp11/alias.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/alias_provider.h b/include/sqlpp11/alias_provider.h index a0cd3789..6949933b 100644 --- a/include/sqlpp11/alias_provider.h +++ b/include/sqlpp11/alias_provider.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/all_of.h b/include/sqlpp11/all_of.h index 7376490b..270dea20 100644 --- a/include/sqlpp11/all_of.h +++ b/include/sqlpp11/all_of.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/any.h b/include/sqlpp11/any.h index fbe4a90a..94fb4cd7 100644 --- a/include/sqlpp11/any.h +++ b/include/sqlpp11/any.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/avg.h b/include/sqlpp11/avg.h index b174b5b9..f763a30f 100644 --- a/include/sqlpp11/avg.h +++ b/include/sqlpp11/avg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/basic_expression_operators.h b/include/sqlpp11/basic_expression_operators.h index 72954b38..b3e74d86 100644 --- a/include/sqlpp11/basic_expression_operators.h +++ b/include/sqlpp11/basic_expression_operators.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/boolean.h b/include/sqlpp11/boolean.h index 27f2ed5c..baef620e 100644 --- a/include/sqlpp11/boolean.h +++ b/include/sqlpp11/boolean.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/column.h b/include/sqlpp11/column.h index 5a3bd98a..8292f376 100644 --- a/include/sqlpp11/column.h +++ b/include/sqlpp11/column.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/column_fwd.h b/include/sqlpp11/column_fwd.h index e655bad5..d378aa6a 100644 --- a/include/sqlpp11/column_fwd.h +++ b/include/sqlpp11/column_fwd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/column_types.h b/include/sqlpp11/column_types.h index 7c358dc5..79f43f8b 100644 --- a/include/sqlpp11/column_types.h +++ b/include/sqlpp11/column_types.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/connection.h b/include/sqlpp11/connection.h index 13cd6c69..7f51fd41 100644 --- a/include/sqlpp11/connection.h +++ b/include/sqlpp11/connection.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/count.h b/include/sqlpp11/count.h index 3a8de5a9..3e6c10ce 100644 --- a/include/sqlpp11/count.h +++ b/include/sqlpp11/count.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/default_value.h b/include/sqlpp11/default_value.h index ad6f0ca1..10dde6f1 100644 --- a/include/sqlpp11/default_value.h +++ b/include/sqlpp11/default_value.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/detail/arg_selector.h b/include/sqlpp11/detail/arg_selector.h index 0b54676a..e2922920 100644 --- a/include/sqlpp11/detail/arg_selector.h +++ b/include/sqlpp11/detail/arg_selector.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/detail/copy_tuple_args.h b/include/sqlpp11/detail/copy_tuple_args.h index 644424e6..0891e6ac 100644 --- a/include/sqlpp11/detail/copy_tuple_args.h +++ b/include/sqlpp11/detail/copy_tuple_args.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/detail/logic.h b/include/sqlpp11/detail/logic.h index 152da35e..3cc8a208 100644 --- a/include/sqlpp11/detail/logic.h +++ b/include/sqlpp11/detail/logic.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/detail/type_set.h b/include/sqlpp11/detail/type_set.h index 3388748a..e8eb69dd 100644 --- a/include/sqlpp11/detail/type_set.h +++ b/include/sqlpp11/detail/type_set.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/exception.h b/include/sqlpp11/exception.h index 4cb938fd..8b2fc6a2 100644 --- a/include/sqlpp11/exception.h +++ b/include/sqlpp11/exception.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/exists.h b/include/sqlpp11/exists.h index a63af7f0..899a460b 100644 --- a/include/sqlpp11/exists.h +++ b/include/sqlpp11/exists.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/floating_point.h b/include/sqlpp11/floating_point.h index 8ea533c7..a43c4229 100644 --- a/include/sqlpp11/floating_point.h +++ b/include/sqlpp11/floating_point.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/functions.h b/include/sqlpp11/functions.h index caf8097d..6e85caaf 100644 --- a/include/sqlpp11/functions.h +++ b/include/sqlpp11/functions.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/insert.h b/include/sqlpp11/insert.h index 18041895..04d92218 100644 --- a/include/sqlpp11/insert.h +++ b/include/sqlpp11/insert.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/integral.h b/include/sqlpp11/integral.h index a831ef99..bb14761d 100644 --- a/include/sqlpp11/integral.h +++ b/include/sqlpp11/integral.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/interpret.h b/include/sqlpp11/interpret.h index 85814a2a..42cc1524 100644 --- a/include/sqlpp11/interpret.h +++ b/include/sqlpp11/interpret.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/join.h b/include/sqlpp11/join.h index 4351bf58..1c959ba3 100644 --- a/include/sqlpp11/join.h +++ b/include/sqlpp11/join.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/max.h b/include/sqlpp11/max.h index fa4bbdc4..ecba9d94 100644 --- a/include/sqlpp11/max.h +++ b/include/sqlpp11/max.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/min.h b/include/sqlpp11/min.h index 7062f778..ee7f4068 100644 --- a/include/sqlpp11/min.h +++ b/include/sqlpp11/min.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/multi_column.h b/include/sqlpp11/multi_column.h index cfe7c212..9a05f4c0 100644 --- a/include/sqlpp11/multi_column.h +++ b/include/sqlpp11/multi_column.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/no_value.h b/include/sqlpp11/no_value.h index eb95d7b9..cad3b6e9 100644 --- a/include/sqlpp11/no_value.h +++ b/include/sqlpp11/no_value.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/null.h b/include/sqlpp11/null.h index c3d864c9..d8bcd0bd 100644 --- a/include/sqlpp11/null.h +++ b/include/sqlpp11/null.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/on.h b/include/sqlpp11/on.h index 9db74885..da874957 100644 --- a/include/sqlpp11/on.h +++ b/include/sqlpp11/on.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/parameter.h b/include/sqlpp11/parameter.h index aa75b70d..de550e15 100644 --- a/include/sqlpp11/parameter.h +++ b/include/sqlpp11/parameter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/parameter_list.h b/include/sqlpp11/parameter_list.h index 9657e647..fcb0cc56 100644 --- a/include/sqlpp11/parameter_list.h +++ b/include/sqlpp11/parameter_list.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/prepared_insert.h b/include/sqlpp11/prepared_insert.h index ae68596f..63a995df 100644 --- a/include/sqlpp11/prepared_insert.h +++ b/include/sqlpp11/prepared_insert.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/prepared_remove.h b/include/sqlpp11/prepared_remove.h index b37fe8ca..21e72986 100644 --- a/include/sqlpp11/prepared_remove.h +++ b/include/sqlpp11/prepared_remove.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/prepared_select.h b/include/sqlpp11/prepared_select.h index 68aecf1e..0cdb56b4 100644 --- a/include/sqlpp11/prepared_select.h +++ b/include/sqlpp11/prepared_select.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/prepared_update.h b/include/sqlpp11/prepared_update.h index f4c1a5e6..a6206e9e 100644 --- a/include/sqlpp11/prepared_update.h +++ b/include/sqlpp11/prepared_update.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/remove.h b/include/sqlpp11/remove.h index 5392885e..04db6eb0 100644 --- a/include/sqlpp11/remove.h +++ b/include/sqlpp11/remove.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/result.h b/include/sqlpp11/result.h index 937f3cf8..314ffc26 100644 --- a/include/sqlpp11/result.h +++ b/include/sqlpp11/result.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/result_row.h b/include/sqlpp11/result_row.h index 0249737a..81015528 100644 --- a/include/sqlpp11/result_row.h +++ b/include/sqlpp11/result_row.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 51c9932a..cec71ca4 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/select_flags.h b/include/sqlpp11/select_flags.h index 8335dd75..6b059f9b 100644 --- a/include/sqlpp11/select_flags.h +++ b/include/sqlpp11/select_flags.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/serialize.h b/include/sqlpp11/serialize.h index 34561439..296ae043 100644 --- a/include/sqlpp11/serialize.h +++ b/include/sqlpp11/serialize.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/serializer_context.h b/include/sqlpp11/serializer_context.h index 3a4ed724..df872b54 100644 --- a/include/sqlpp11/serializer_context.h +++ b/include/sqlpp11/serializer_context.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/some.h b/include/sqlpp11/some.h index 250d2bac..e15683d9 100644 --- a/include/sqlpp11/some.h +++ b/include/sqlpp11/some.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/sort_order.h b/include/sqlpp11/sort_order.h index 56080824..5f3950ef 100644 --- a/include/sqlpp11/sort_order.h +++ b/include/sqlpp11/sort_order.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/sqlpp11.h b/include/sqlpp11/sqlpp11.h index 883b2eaa..e0ccca48 100644 --- a/include/sqlpp11/sqlpp11.h +++ b/include/sqlpp11/sqlpp11.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/sum.h b/include/sqlpp11/sum.h index 168cbfb5..745e48c3 100644 --- a/include/sqlpp11/sum.h +++ b/include/sqlpp11/sum.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/table.h b/include/sqlpp11/table.h index ca694c0e..7e8078ed 100644 --- a/include/sqlpp11/table.h +++ b/include/sqlpp11/table.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/table_alias.h b/include/sqlpp11/table_alias.h index 612f11f3..2f51903a 100644 --- a/include/sqlpp11/table_alias.h +++ b/include/sqlpp11/table_alias.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/text.h b/include/sqlpp11/text.h index 36d41b60..339d7dca 100644 --- a/include/sqlpp11/text.h +++ b/include/sqlpp11/text.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/transaction.h b/include/sqlpp11/transaction.h index 63b64c91..a2b1dfbc 100644 --- a/include/sqlpp11/transaction.h +++ b/include/sqlpp11/transaction.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/tvin.h b/include/sqlpp11/tvin.h index 8cb96623..be1bf137 100644 --- a/include/sqlpp11/tvin.h +++ b/include/sqlpp11/tvin.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/type_traits.h b/include/sqlpp11/type_traits.h index c0a380e7..b4d39bf8 100644 --- a/include/sqlpp11/type_traits.h +++ b/include/sqlpp11/type_traits.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/update.h b/include/sqlpp11/update.h index 39733d9a..cf0f91b1 100644 --- a/include/sqlpp11/update.h +++ b/include/sqlpp11/update.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/assignment.h b/include/sqlpp11/vendor/assignment.h index c3e17156..d8f8ac6b 100644 --- a/include/sqlpp11/vendor/assignment.h +++ b/include/sqlpp11/vendor/assignment.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/char_result_row.h b/include/sqlpp11/vendor/char_result_row.h index abfed8f7..3cf09c12 100644 --- a/include/sqlpp11/vendor/char_result_row.h +++ b/include/sqlpp11/vendor/char_result_row.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/concat.h b/include/sqlpp11/vendor/concat.h index fda3be94..c88aae93 100644 --- a/include/sqlpp11/vendor/concat.h +++ b/include/sqlpp11/vendor/concat.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/expression.h b/include/sqlpp11/vendor/expression.h index b2be6368..e156a84b 100644 --- a/include/sqlpp11/vendor/expression.h +++ b/include/sqlpp11/vendor/expression.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/expression_fwd.h b/include/sqlpp11/vendor/expression_fwd.h index 86166706..66b446c5 100644 --- a/include/sqlpp11/vendor/expression_fwd.h +++ b/include/sqlpp11/vendor/expression_fwd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/field.h b/include/sqlpp11/vendor/field.h index a931df63..7cd6ec62 100644 --- a/include/sqlpp11/vendor/field.h +++ b/include/sqlpp11/vendor/field.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/from.h b/include/sqlpp11/vendor/from.h index 87ae0c7a..0f991384 100644 --- a/include/sqlpp11/vendor/from.h +++ b/include/sqlpp11/vendor/from.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/group_by.h b/include/sqlpp11/vendor/group_by.h index cefd2c8d..a4e59bca 100644 --- a/include/sqlpp11/vendor/group_by.h +++ b/include/sqlpp11/vendor/group_by.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/having.h b/include/sqlpp11/vendor/having.h index 904e13d8..33a89044 100644 --- a/include/sqlpp11/vendor/having.h +++ b/include/sqlpp11/vendor/having.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/in.h b/include/sqlpp11/vendor/in.h index b3d37f5d..1979264b 100644 --- a/include/sqlpp11/vendor/in.h +++ b/include/sqlpp11/vendor/in.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/in_fwd.h b/include/sqlpp11/vendor/in_fwd.h index b33aee1c..809c4cc2 100644 --- a/include/sqlpp11/vendor/in_fwd.h +++ b/include/sqlpp11/vendor/in_fwd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/insert_value.h b/include/sqlpp11/vendor/insert_value.h index e73b9ce2..dfcc97ba 100644 --- a/include/sqlpp11/vendor/insert_value.h +++ b/include/sqlpp11/vendor/insert_value.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/insert_value_list.h b/include/sqlpp11/vendor/insert_value_list.h index c04ed95a..39dadc11 100644 --- a/include/sqlpp11/vendor/insert_value_list.h +++ b/include/sqlpp11/vendor/insert_value_list.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/interpret_tuple.h b/include/sqlpp11/vendor/interpret_tuple.h index 61e03102..9c067627 100644 --- a/include/sqlpp11/vendor/interpret_tuple.h +++ b/include/sqlpp11/vendor/interpret_tuple.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/interpretable.h b/include/sqlpp11/vendor/interpretable.h index 17c4676c..a190f04e 100644 --- a/include/sqlpp11/vendor/interpretable.h +++ b/include/sqlpp11/vendor/interpretable.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/interpretable_list.h b/include/sqlpp11/vendor/interpretable_list.h index c9a3f479..291b8123 100644 --- a/include/sqlpp11/vendor/interpretable_list.h +++ b/include/sqlpp11/vendor/interpretable_list.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/interpreter.h b/include/sqlpp11/vendor/interpreter.h index 43b4b625..17dd6075 100644 --- a/include/sqlpp11/vendor/interpreter.h +++ b/include/sqlpp11/vendor/interpreter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/is_null.h b/include/sqlpp11/vendor/is_null.h index 5abc096e..2b963134 100644 --- a/include/sqlpp11/vendor/is_null.h +++ b/include/sqlpp11/vendor/is_null.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/is_null_fwd.h b/include/sqlpp11/vendor/is_null_fwd.h index 8ef3e8a4..0c8e62f0 100644 --- a/include/sqlpp11/vendor/is_null_fwd.h +++ b/include/sqlpp11/vendor/is_null_fwd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/like.h b/include/sqlpp11/vendor/like.h index a2f1755e..ca756cbb 100644 --- a/include/sqlpp11/vendor/like.h +++ b/include/sqlpp11/vendor/like.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/limit.h b/include/sqlpp11/vendor/limit.h index 1c9e3112..98ff44b8 100644 --- a/include/sqlpp11/vendor/limit.h +++ b/include/sqlpp11/vendor/limit.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/named_interpretable.h b/include/sqlpp11/vendor/named_interpretable.h index f3aa2fdc..08e4ed68 100644 --- a/include/sqlpp11/vendor/named_interpretable.h +++ b/include/sqlpp11/vendor/named_interpretable.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/noop.h b/include/sqlpp11/vendor/noop.h index 2caf41f2..e0c28ef1 100644 --- a/include/sqlpp11/vendor/noop.h +++ b/include/sqlpp11/vendor/noop.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/noop_fwd.h b/include/sqlpp11/vendor/noop_fwd.h index 704cdc99..243f77a2 100644 --- a/include/sqlpp11/vendor/noop_fwd.h +++ b/include/sqlpp11/vendor/noop_fwd.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/offset.h b/include/sqlpp11/vendor/offset.h index f8492994..80a9ac36 100644 --- a/include/sqlpp11/vendor/offset.h +++ b/include/sqlpp11/vendor/offset.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/order_by.h b/include/sqlpp11/vendor/order_by.h index a96813c7..093ba2e3 100644 --- a/include/sqlpp11/vendor/order_by.h +++ b/include/sqlpp11/vendor/order_by.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/policy_update.h b/include/sqlpp11/vendor/policy_update.h index 62f8fbcc..a65c332b 100644 --- a/include/sqlpp11/vendor/policy_update.h +++ b/include/sqlpp11/vendor/policy_update.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/select_column_list.h b/include/sqlpp11/vendor/select_column_list.h index d3dd2130..6b888cb9 100644 --- a/include/sqlpp11/vendor/select_column_list.h +++ b/include/sqlpp11/vendor/select_column_list.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/select_flag_list.h b/include/sqlpp11/vendor/select_flag_list.h index 54975094..d1292da2 100644 --- a/include/sqlpp11/vendor/select_flag_list.h +++ b/include/sqlpp11/vendor/select_flag_list.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/select_pseudo_table.h b/include/sqlpp11/vendor/select_pseudo_table.h index 196b2ae5..a63c4d63 100644 --- a/include/sqlpp11/vendor/select_pseudo_table.h +++ b/include/sqlpp11/vendor/select_pseudo_table.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/serializer.h b/include/sqlpp11/vendor/serializer.h index 41db8fa7..1a5031f9 100644 --- a/include/sqlpp11/vendor/serializer.h +++ b/include/sqlpp11/vendor/serializer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/simple_column.h b/include/sqlpp11/vendor/simple_column.h index 94f1919a..56d664bc 100644 --- a/include/sqlpp11/vendor/simple_column.h +++ b/include/sqlpp11/vendor/simple_column.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/single_table.h b/include/sqlpp11/vendor/single_table.h index 8d839fbc..99cf8eea 100644 --- a/include/sqlpp11/vendor/single_table.h +++ b/include/sqlpp11/vendor/single_table.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/update_list.h b/include/sqlpp11/vendor/update_list.h index f2684628..1fa1bdd0 100644 --- a/include/sqlpp11/vendor/update_list.h +++ b/include/sqlpp11/vendor/update_list.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/using.h b/include/sqlpp11/vendor/using.h index 940cfca9..a52a479a 100644 --- a/include/sqlpp11/vendor/using.h +++ b/include/sqlpp11/vendor/using.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/value_type.h b/include/sqlpp11/vendor/value_type.h index 4c709a03..06738c36 100644 --- a/include/sqlpp11/vendor/value_type.h +++ b/include/sqlpp11/vendor/value_type.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/where.h b/include/sqlpp11/vendor/where.h index 2177ec59..10dc8692 100644 --- a/include/sqlpp11/vendor/where.h +++ b/include/sqlpp11/vendor/where.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/wrap_operand.h b/include/sqlpp11/vendor/wrap_operand.h index 7ec98785..96092e57 100644 --- a/include/sqlpp11/vendor/wrap_operand.h +++ b/include/sqlpp11/vendor/wrap_operand.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/vendor/wrong.h b/include/sqlpp11/vendor/wrong.h index 896f1e46..65a4d181 100644 --- a/include/sqlpp11/vendor/wrong.h +++ b/include/sqlpp11/vendor/wrong.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/include/sqlpp11/verbatim_table.h b/include/sqlpp11/verbatim_table.h index c18ed30b..2ad79190 100644 --- a/include/sqlpp11/verbatim_table.h +++ b/include/sqlpp11/verbatim_table.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/scripts/ddl2cpp b/scripts/ddl2cpp index cc1d78b2..13011825 100755 --- a/scripts/ddl2cpp +++ b/scripts/ddl2cpp @@ -1,7 +1,7 @@ #!/usr/bin/env python ## - # Copyright (c) 2013 - 2014, Roland Bock + # Copyright (c) 2013-2014, Roland Bock # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, diff --git a/tests/FunctionTest.cpp b/tests/FunctionTest.cpp index 98da9365..3284daa7 100644 --- a/tests/FunctionTest.cpp +++ b/tests/FunctionTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/tests/InsertTest.cpp b/tests/InsertTest.cpp index ebe64982..67e2efe7 100644 --- a/tests/InsertTest.cpp +++ b/tests/InsertTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/tests/InterpretTest.cpp b/tests/InterpretTest.cpp index 1f02f33d..c931fb5a 100644 --- a/tests/InterpretTest.cpp +++ b/tests/InterpretTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/tests/MockDb.h b/tests/MockDb.h index 4cd8b384..fd114baf 100644 --- a/tests/MockDb.h +++ b/tests/MockDb.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/tests/PreparedTest.cpp b/tests/PreparedTest.cpp index b39b037c..7e6103ae 100644 --- a/tests/PreparedTest.cpp +++ b/tests/PreparedTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/tests/RemoveTest.cpp b/tests/RemoveTest.cpp index 48485886..f4ce1302 100644 --- a/tests/RemoveTest.cpp +++ b/tests/RemoveTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/tests/SelectTest.cpp b/tests/SelectTest.cpp index 194cd800..bc636b2e 100644 --- a/tests/SelectTest.cpp +++ b/tests/SelectTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/tests/SelectTypeTest.cpp b/tests/SelectTypeTest.cpp index 748fa700..bc224e87 100644 --- a/tests/SelectTypeTest.cpp +++ b/tests/SelectTypeTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/tests/UpdateTest.cpp b/tests/UpdateTest.cpp index 113bc8c2..35078956 100644 --- a/tests/UpdateTest.cpp +++ b/tests/UpdateTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/tests/is_regular.h b/tests/is_regular.h index 6e99e0e1..190d0838 100644 --- a/tests/is_regular.h +++ b/tests/is_regular.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/tests/sample.sql b/tests/sample.sql index 75f48445..d70387e3 100644 --- a/tests/sample.sql +++ b/tests/sample.sql @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Roland Bock + * Copyright (c) 2013-2014, Roland Bock * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, From 3f1460cd2e344ae9b9540a7a9337d0c3a2a2699d Mon Sep 17 00:00:00 2001 From: rbock Date: Fri, 28 Mar 2014 18:09:21 +0100 Subject: [PATCH 44/74] Streamlined basic value types --- include/sqlpp11/boolean.h | 1 + include/sqlpp11/floating_point.h | 1 + include/sqlpp11/integral.h | 4 +--- include/sqlpp11/text.h | 1 + 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/sqlpp11/boolean.h b/include/sqlpp11/boolean.h index baef620e..66e80853 100644 --- a/include/sqlpp11/boolean.h +++ b/include/sqlpp11/boolean.h @@ -42,6 +42,7 @@ namespace sqlpp // boolean value type struct boolean { + using _value_type = boolean; using _base_value_type = boolean; using _is_boolean = std::true_type; using _is_value = std::true_type; diff --git a/include/sqlpp11/floating_point.h b/include/sqlpp11/floating_point.h index a43c4229..a5cdb5a2 100644 --- a/include/sqlpp11/floating_point.h +++ b/include/sqlpp11/floating_point.h @@ -41,6 +41,7 @@ namespace sqlpp // floating_point value type struct floating_point { + using _value_type = floating_point; using _base_value_type = floating_point; using _is_numeric = std::true_type; using _is_floating_point = std::true_type; diff --git a/include/sqlpp11/integral.h b/include/sqlpp11/integral.h index bb14761d..2e8ea407 100644 --- a/include/sqlpp11/integral.h +++ b/include/sqlpp11/integral.h @@ -42,8 +42,7 @@ namespace sqlpp // integral value type struct integral { -#warning why do I need base_value_type? Would it be sufficient to use _value_type instead? -#warning what is the difference between _is_value and _is_expression? + using _value_type = integral; using _base_value_type = integral; using _is_numeric = std::true_type; using _is_integral = std::true_type; @@ -51,7 +50,6 @@ namespace sqlpp using _is_expression = std::true_type; using _cpp_value_type = int64_t; - using _value_type = integral; struct _parameter_t { diff --git a/include/sqlpp11/text.h b/include/sqlpp11/text.h index 339d7dca..8a41fa24 100644 --- a/include/sqlpp11/text.h +++ b/include/sqlpp11/text.h @@ -41,6 +41,7 @@ namespace sqlpp // text value type struct text { + using _value_type = text; using _base_value_type = text; using _is_text = std::true_type; using _is_value = std::true_type; From dba5c992ed8e76927ef0efd175143384481f6001 Mon Sep 17 00:00:00 2001 From: rbock Date: Fri, 28 Mar 2014 18:10:58 +0100 Subject: [PATCH 45/74] Added _table_set to select_column_list.h --- include/sqlpp11/detail/type_set.h | 3 +++ include/sqlpp11/multi_column.h | 4 ++++ include/sqlpp11/select.h | 1 - include/sqlpp11/vendor/select_column_list.h | 2 ++ 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/sqlpp11/detail/type_set.h b/include/sqlpp11/detail/type_set.h index e8eb69dd..51a2df20 100644 --- a/include/sqlpp11/detail/type_set.h +++ b/include/sqlpp11/detail/type_set.h @@ -191,6 +191,9 @@ namespace sqlpp using type = typename joined_set, _rest>::type; }; + template + using make_joined_set_t = typename make_joined_set::type; + } } diff --git a/include/sqlpp11/multi_column.h b/include/sqlpp11/multi_column.h index 9a05f4c0..821cd1c2 100644 --- a/include/sqlpp11/multi_column.h +++ b/include/sqlpp11/multi_column.h @@ -29,6 +29,7 @@ #include #include +#include #include @@ -42,6 +43,8 @@ namespace sqlpp { static_assert(detail::all_t::value, "multi_column parameters need to be named expressions"); + using _table_set = sqlpp::detail::make_joined_set_t; + multi_column_t(std::tuple columns): _columns(columns) {} @@ -75,6 +78,7 @@ namespace sqlpp static_assert(detail::all_t::value, "multi_column parameters need to be named expressions"); using _name_t = typename AliasProvider::_name_t; + using _table_set = sqlpp::detail::make_joined_set_t; multi_column_alias_t(multi_column_t multi_column): _columns(multi_column._columns) diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index cec71ca4..2da1832b 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -81,7 +81,6 @@ namespace sqlpp typename Limit = vendor::no_limit_t, typename Offset = vendor::no_offset_t > -#warning: idea: require from() for anything AFTER FROM, including dynamic columns. Then just check for from() in the run methods struct select_t: public detail::select_helper_t::_value_type::template expression_operators> { using _database_t = Database; diff --git a/include/sqlpp11/vendor/select_column_list.h b/include/sqlpp11/vendor/select_column_list.h index 6b888cb9..fdb9427a 100644 --- a/include/sqlpp11/vendor/select_column_list.h +++ b/include/sqlpp11/vendor/select_column_list.h @@ -139,6 +139,8 @@ namespace sqlpp using _parameter_tuple_t = std::tuple; using size = std::tuple_size<_parameter_tuple_t>; + using _table_set = sqlpp::detail::make_joined_set_t; + static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected"); template From 6737bf901df3bbf7c8ac71f6a9c6f57d5d0107aa Mon Sep 17 00:00:00 2001 From: rbock Date: Mon, 7 Apr 2014 22:02:08 +0200 Subject: [PATCH 46/74] Added a bunch of table tests to select And some hints regarding additional tests and how to turn them of for subselects --- include/sqlpp11/alias.h | 1 + include/sqlpp11/select.h | 21 ++++++++++++++------- include/sqlpp11/vendor/from.h | 2 +- include/sqlpp11/vendor/group_by.h | 1 + include/sqlpp11/vendor/having.h | 1 + include/sqlpp11/vendor/limit.h | 3 +++ include/sqlpp11/vendor/offset.h | 2 ++ include/sqlpp11/vendor/order_by.h | 2 ++ tests/SelectTest.cpp | 4 +--- 9 files changed, 26 insertions(+), 11 deletions(-) diff --git a/include/sqlpp11/alias.h b/include/sqlpp11/alias.h index 0d781a7a..39f3bb52 100644 --- a/include/sqlpp11/alias.h +++ b/include/sqlpp11/alias.h @@ -44,6 +44,7 @@ namespace sqlpp }; using _name_t = typename AliasProvider::_name_t; + using _table_set = typename Expression::_table_set; Expression _expression; }; diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 2da1832b..6888db64 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -391,9 +391,6 @@ namespace sqlpp return _column_list_t::static_size() + get_dynamic_names().size(); } - template - struct can_run_t - { /* static_assert(column_list::_table_set::template is_subset_t<_from_t::_table_set>::value static_assert(detail::is_subset_of::value @@ -406,8 +403,10 @@ namespace sqlpp //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; + template + struct is_table_subset_of_from + { + static constexpr bool value = ::sqlpp::detail::is_subset_of::value; }; // Execute @@ -415,7 +414,16 @@ namespace sqlpp auto _run(Db& db) const -> result_t> { - static_assert(can_run_t::value, "Cannot execute select statement"); +#warning: need to check in add_xy method as well +#warning: need add_wxy_without_table_check +#warning: might want to add an .extra_tables() method to say which tables might also be used here, say via dynamic_from or because this is a subselect + static_assert(is_table_subset_of_from::value, "selected columns require additional tables in from()"); + static_assert(is_table_subset_of_from::value, "where() expression requires additional tables in from()"); + static_assert(is_table_subset_of_from::value, "group_by() expression requires additional tables in from()"); + static_assert(is_table_subset_of_from::value, "having() expression requires additional tables in from()"); + static_assert(is_table_subset_of_from::value, "order_by() expression requires additional tables in from()"); + static_assert(is_table_subset_of_from::value, "limit() expression requires additional tables in from()"); + static_assert(is_table_subset_of_from::value, "offset() expression requires additional tables in from()"); static_assert(_get_static_no_of_parameters() == 0, "cannot run select directly with parameters, use prepare instead"); return {db.select(*this), get_dynamic_names()}; } @@ -425,7 +433,6 @@ namespace sqlpp auto _prepare(Db& db) const -> prepared_select_t { - static_assert(can_run_t::value, "Cannot prepare select statement"); return {{}, get_dynamic_names(), db.prepare_select(*this)}; } diff --git a/include/sqlpp11/vendor/from.h b/include/sqlpp11/vendor/from.h index 0f991384..e703b2b3 100644 --- a/include/sqlpp11/vendor/from.h +++ b/include/sqlpp11/vendor/from.h @@ -51,7 +51,7 @@ namespace sqlpp static_assert(::sqlpp::detail::all_t::value, "at least one argument is not a table or join in from()"); - using _table_set = typename ::sqlpp::detail::make_joined_set; + using _table_set = ::sqlpp::detail::make_joined_set_t; from_t(Tables... tables): diff --git a/include/sqlpp11/vendor/group_by.h b/include/sqlpp11/vendor/group_by.h index a4e59bca..5491a6e8 100644 --- a/include/sqlpp11/vendor/group_by.h +++ b/include/sqlpp11/vendor/group_by.h @@ -78,6 +78,7 @@ namespace sqlpp struct no_group_by_t { using _is_noop = std::true_type; + using _table_set = ::sqlpp::detail::type_set<>; }; // Interpreters diff --git a/include/sqlpp11/vendor/having.h b/include/sqlpp11/vendor/having.h index 33a89044..7572b205 100644 --- a/include/sqlpp11/vendor/having.h +++ b/include/sqlpp11/vendor/having.h @@ -75,6 +75,7 @@ namespace sqlpp struct no_having_t { using _is_noop = std::true_type; + using _table_set = ::sqlpp::detail::type_set<>; }; // Interpreters diff --git a/include/sqlpp11/vendor/limit.h b/include/sqlpp11/vendor/limit.h index 98ff44b8..4e91e312 100644 --- a/include/sqlpp11/vendor/limit.h +++ b/include/sqlpp11/vendor/limit.h @@ -29,6 +29,7 @@ #include #include +#include namespace sqlpp { @@ -40,6 +41,7 @@ namespace sqlpp { using _is_limit = std::true_type; static_assert(is_integral_t::value, "limit requires an integral value or integral parameter"); + using _table_set = ::sqlpp::detail::type_set<>; limit_t(Limit value): _value(value) @@ -93,6 +95,7 @@ namespace sqlpp struct no_limit_t { using _is_noop = std::true_type; + using _table_set = ::sqlpp::detail::type_set<>; }; // Interpreters diff --git a/include/sqlpp11/vendor/offset.h b/include/sqlpp11/vendor/offset.h index 80a9ac36..35f43bfc 100644 --- a/include/sqlpp11/vendor/offset.h +++ b/include/sqlpp11/vendor/offset.h @@ -29,6 +29,7 @@ #include #include +#include namespace sqlpp { @@ -93,6 +94,7 @@ namespace sqlpp struct no_offset_t { using _is_noop = std::true_type; + using _table_set = ::sqlpp::detail::type_set<>; }; // Interpreters diff --git a/include/sqlpp11/vendor/order_by.h b/include/sqlpp11/vendor/order_by.h index 093ba2e3..4a424eaa 100644 --- a/include/sqlpp11/vendor/order_by.h +++ b/include/sqlpp11/vendor/order_by.h @@ -33,6 +33,7 @@ #include #include #include +#include namespace sqlpp { @@ -75,6 +76,7 @@ namespace sqlpp struct no_order_by_t { using _is_noop = std::true_type; + using _table_set = ::sqlpp::detail::type_set<>; }; // Interpreters diff --git a/tests/SelectTest.cpp b/tests/SelectTest.cpp index bc636b2e..423ff488 100644 --- a/tests/SelectTest.cpp +++ b/tests/SelectTest.cpp @@ -61,13 +61,11 @@ int main() const std::string b = row.tabBar.beta; } -#warning this should fail because f is not in from() - for (const auto& row : db(select(f.omega, all_of(t).as(t), t.gamma).from(t).where(true))) + for (const auto& row : db(select(all_of(t).as(t), t.gamma).from(t).where(t.alpha > 7))) { int64_t a = row.tabBar.alpha; const std::string b = row.tabBar.beta; const bool g = row.gamma; - const float o = row.omega; } return 0; From c595353286f396658c80353b0fdf4c02cf816052 Mon Sep 17 00:00:00 2001 From: rbock Date: Tue, 8 Apr 2014 20:59:45 +0200 Subject: [PATCH 47/74] Moved where-methods to where-classes. --- include/sqlpp11/select.h | 96 +++++++++++++++++++++------------- include/sqlpp11/vendor/where.h | 44 +++++++++++++--- 2 files changed, 98 insertions(+), 42 deletions(-) diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 6888db64..da7c4749 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -51,6 +51,54 @@ namespace sqlpp { + template + struct select_t; + namespace detail + { + template + struct select_policies_t + { + using _database_t = Db; + using _select_t = select_t; + template + struct _policies_update_impl + { + using type = select_t...>; + }; + + template + using _policies_update_t = typename _policies_update_impl::type; + + static_assert(is_noop_t::value or sqlpp::is_select_column_list_t::value, "column list of select is neither naught nor a valid column list"); + static_assert(is_noop_t::value or sqlpp::is_from_t::value, "from() part of select is neither naught nor a valid from()"); + 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; + }; + } + namespace detail { template< @@ -70,18 +118,19 @@ namespace sqlpp } // SELECT - template - struct select_t: public detail::select_helper_t::_value_type::template expression_operators> + struct select_t: public detail::select_helper_t::_value_type::template expression_operators>, + Where::template _methods_t> { using _database_t = Database; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; @@ -183,23 +232,6 @@ namespace sqlpp 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> @@ -308,14 +340,6 @@ namespace sqlpp 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) { diff --git a/include/sqlpp11/vendor/where.h b/include/sqlpp11/vendor/where.h index 10dc8692..aef0d5f5 100644 --- a/include/sqlpp11/vendor/where.h +++ b/include/sqlpp11/vendor/where.h @@ -64,13 +64,17 @@ namespace sqlpp where_t& operator=(where_t&&) = default; ~where_t() = default; - template - void add_where(const Statement&, Expression expression) + template + struct _methods_t { - 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()"); - _dynamic_expressions.emplace_back(expression); - } + template + void add_where(Expression expression) + { + static_assert(is_expression_t::value, "invalid expression argument in add_where()"); +#warning: Need to dispatch to actual add method to prevent error messages from being generated + return static_cast(this)->_where._dynamic_expressions.emplace_back(expression); + } + }; _parameter_tuple_t _expressions; vendor::interpretable_list_t _dynamic_expressions; @@ -93,6 +97,11 @@ namespace sqlpp where_t& operator=(where_t&&) = default; ~where_t() = default; + template + struct _methods_t + { + }; + bool _condition; }; @@ -100,6 +109,29 @@ namespace sqlpp { using _is_noop = std::true_type; using _table_set = ::sqlpp::detail::type_set<>; + + template + struct _methods_t + { + using _database_t = typename Policies::_database_t; + template + using _new_select_t = typename Policies::template _policies_update_t; + template + auto where(Args... args) + -> _new_select_t> + { + return { *static_cast(this), where_t{args...} }; + } + + template + auto dynamic_where(Args... args) + -> _new_select_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), vendor::where_t<_database_t, Args...>{args...} }; + } + + }; }; // Interpreters From 4727de831f3ec823f66af5362094d4b1dafce2f1 Mon Sep 17 00:00:00 2001 From: rbock Date: Tue, 8 Apr 2014 21:33:38 +0200 Subject: [PATCH 48/74] Moved limit-methods to limit classes --- include/sqlpp11/select.h | 19 ++-------------- include/sqlpp11/vendor/limit.h | 40 ++++++++++++++++++++++++++++++++++ include/sqlpp11/vendor/where.h | 1 + 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index da7c4749..2ed6bc3d 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -130,7 +130,8 @@ namespace sqlpp typename Offset > struct select_t: public detail::select_helper_t::_value_type::template expression_operators>, - Where::template _methods_t> + Where::template _methods_t>, + Limit::template _methods_t> { using _database_t = Database; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; @@ -283,22 +284,6 @@ namespace sqlpp 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>> diff --git a/include/sqlpp11/vendor/limit.h b/include/sqlpp11/vendor/limit.h index 4e91e312..5e6437ca 100644 --- a/include/sqlpp11/vendor/limit.h +++ b/include/sqlpp11/vendor/limit.h @@ -53,6 +53,11 @@ namespace sqlpp limit_t& operator=(limit_t&&) = default; ~limit_t() = default; + template + struct _methods_t + { + }; + Limit _value; }; @@ -61,6 +66,7 @@ namespace sqlpp { using _is_limit = std::true_type; using _is_dynamic = std::true_type; + using _table_set = ::sqlpp::detail::type_set<>; dynamic_limit_t(): _value(noop()) @@ -88,6 +94,18 @@ namespace sqlpp _initialized = true; } + template + struct _methods_t + { + template + void set_limit(Limit value) + { + using arg_t = typename wrap_operand::type; + static_cast(this)->_limit._value = arg_t{value}; + static_cast(this)->_limit._initialized = true; + } + }; + bool _initialized = false; interpretable_t _value; }; @@ -96,6 +114,28 @@ namespace sqlpp { using _is_noop = std::true_type; using _table_set = ::sqlpp::detail::type_set<>; + + template + struct _methods_t + { + using _database_t = typename Policies::_database_t; + template + using _new_select_t = typename Policies::template _policies_update_t; + + template + auto limit(Arg arg) + -> _new_select_t::type>> + { + return { *static_cast(this), limit_t::type>{{arg}} }; + } + + auto dynamic_limit() + -> _new_select_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_t<_database_t>{} }; + } + }; }; // Interpreters diff --git a/include/sqlpp11/vendor/where.h b/include/sqlpp11/vendor/where.h index aef0d5f5..8dfc8199 100644 --- a/include/sqlpp11/vendor/where.h +++ b/include/sqlpp11/vendor/where.h @@ -116,6 +116,7 @@ namespace sqlpp using _database_t = typename Policies::_database_t; template using _new_select_t = typename Policies::template _policies_update_t; + template auto where(Args... args) -> _new_select_t> From f2fc4f73f605778db4f320e876d7a98ae45d7806 Mon Sep 17 00:00:00 2001 From: rbock Date: Tue, 8 Apr 2014 21:49:37 +0200 Subject: [PATCH 49/74] Move offset methods into offset classes --- include/sqlpp11/select.h | 35 ++----------------------- include/sqlpp11/vendor/limit.h | 14 +++------- include/sqlpp11/vendor/offset.h | 45 ++++++++++++++++++++++++++++----- 3 files changed, 44 insertions(+), 50 deletions(-) diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 2ed6bc3d..3274422d 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -131,7 +131,8 @@ namespace sqlpp > struct select_t: public detail::select_helper_t::_value_type::template expression_operators>, Where::template _methods_t>, - Limit::template _methods_t> + Limit::template _methods_t>, + Offset::template _methods_t> { using _database_t = Database; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; @@ -284,22 +285,6 @@ namespace sqlpp return { *this, vendor::order_by_t<_database_t, Args...>{args...} }; } - 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) @@ -349,22 +334,6 @@ namespace sqlpp 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 diff --git a/include/sqlpp11/vendor/limit.h b/include/sqlpp11/vendor/limit.h index 5e6437ca..c6b1034a 100644 --- a/include/sqlpp11/vendor/limit.h +++ b/include/sqlpp11/vendor/limit.h @@ -86,23 +86,15 @@ namespace sqlpp dynamic_limit_t& operator=(dynamic_limit_t&&) = default; ~dynamic_limit_t() = default; - template - void set_limit(Limit value) - { - using arg_t = typename wrap_operand::type; - _value = arg_t{value}; - _initialized = true; - } - template struct _methods_t { template void set_limit(Limit value) { - using arg_t = typename wrap_operand::type; - static_cast(this)->_limit._value = arg_t{value}; - static_cast(this)->_limit._initialized = true; + 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 35f43bfc..0c3ad9e1 100644 --- a/include/sqlpp11/vendor/offset.h +++ b/include/sqlpp11/vendor/offset.h @@ -40,6 +40,7 @@ namespace sqlpp struct offset_t { using _is_offset = std::true_type; + using _table_set = ::sqlpp::detail::type_set<>; static_assert(is_integral_t::value, "offset requires an integral value or integral parameter"); offset_t(Offset value): @@ -52,6 +53,11 @@ namespace sqlpp offset_t& operator=(offset_t&&) = default; ~offset_t() = default; + template + struct _methods_t + { + }; + Offset _value; }; @@ -60,6 +66,7 @@ namespace sqlpp { using _is_offset = std::true_type; using _is_dynamic = std::true_type; + using _table_set = ::sqlpp::detail::type_set<>; dynamic_offset_t(): _value(noop()) @@ -79,13 +86,17 @@ namespace sqlpp dynamic_offset_t& operator=(dynamic_offset_t&&) = default; ~dynamic_offset_t() = default; - template - void set_offset(Offset value) + template + struct _methods_t { - using arg_t = typename wrap_operand::type; - _value = arg_t(value); - _initialized = true; - } + template + void set_offset(Offset value) + { + using arg_t = typename wrap_operand::type; + static_cast(this)->_offset._value = arg_t{value}; + static_cast(this)->_offset._initialized = true; + } + }; bool _initialized = false; interpretable_t _value; @@ -95,6 +106,28 @@ namespace sqlpp { using _is_noop = std::true_type; using _table_set = ::sqlpp::detail::type_set<>; + + template + struct _methods_t + { + using _database_t = typename Policies::_database_t; + template + using _new_select_t = typename Policies::template _policies_update_t; + + template + auto offset(Arg arg) + -> _new_select_t::type>> + { + return { *static_cast(this), offset_t::type>{{arg}} }; + } + + auto dynamic_offset() + -> _new_select_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_t<_database_t>{} }; + } + }; }; // Interpreters From eb9eab369ad14f2420d9a5504cffa2c07b00c5ec Mon Sep 17 00:00:00 2001 From: rbock Date: Tue, 8 Apr 2014 22:02:24 +0200 Subject: [PATCH 50/74] Moved order_by-methods to order_by classes --- include/sqlpp11/select.h | 26 +------------------- include/sqlpp11/sort_order.h | 3 +++ include/sqlpp11/vendor/limit.h | 1 + include/sqlpp11/vendor/order_by.h | 40 +++++++++++++++++++++++++++---- include/sqlpp11/vendor/where.h | 1 - 5 files changed, 40 insertions(+), 31 deletions(-) diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 3274422d..fd93479e 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -131,6 +131,7 @@ namespace sqlpp > struct select_t: public detail::select_helper_t::_value_type::template expression_operators>, Where::template _methods_t>, + OrderBy::template _methods_t>, Limit::template _methods_t>, Offset::template _methods_t> { @@ -268,23 +269,6 @@ namespace sqlpp 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...} }; - } - // value adding methods template void add_flag(Args... args) @@ -326,14 +310,6 @@ namespace sqlpp 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...); - } - // PseudoTable template struct _pseudo_table_t diff --git a/include/sqlpp11/sort_order.h b/include/sqlpp11/sort_order.h index 5f3950ef..d0616449 100644 --- a/include/sqlpp11/sort_order.h +++ b/include/sqlpp11/sort_order.h @@ -27,6 +27,8 @@ #ifndef SQLPP_SORT_ORDER_H #define SQLPP_SORT_ORDER_H +#include + namespace sqlpp { enum class sort_type @@ -39,6 +41,7 @@ namespace sqlpp struct sort_order_t { using _is_sort_order = std::true_type; + using _table_set = typename Expression::_table_set; Expression _expression; }; diff --git a/include/sqlpp11/vendor/limit.h b/include/sqlpp11/vendor/limit.h index c6b1034a..683e7581 100644 --- a/include/sqlpp11/vendor/limit.h +++ b/include/sqlpp11/vendor/limit.h @@ -41,6 +41,7 @@ namespace sqlpp { using _is_limit = std::true_type; static_assert(is_integral_t::value, "limit requires an integral value or integral parameter"); + // FIXME: Is this really always empty? using _table_set = ::sqlpp::detail::type_set<>; limit_t(Limit value): diff --git a/include/sqlpp11/vendor/order_by.h b/include/sqlpp11/vendor/order_by.h index 4a424eaa..a8bf3edb 100644 --- a/include/sqlpp11/vendor/order_by.h +++ b/include/sqlpp11/vendor/order_by.h @@ -46,6 +46,8 @@ namespace sqlpp using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; using _parameter_tuple_t = std::tuple; + using _table_set = typename ::sqlpp::detail::make_joined_set::type; + static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one sort-order expression required in order_by()"); static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in order_by()"); @@ -62,12 +64,17 @@ namespace sqlpp order_by_t& operator=(order_by_t&&) = default; ~order_by_t() = default; - template - void add_order_by(const Statement&, Expression expressions) + template + struct _methods_t { - static_assert(is_sort_order_t::value, "order_by arguments require to be sort-order expressions"); - _dynamic_expressions.push_back(expressions); - } + template + void add_order_by(Expression expression) + { + static_assert(is_sort_order_t::value, "invalid expression argument in add_order_by()"); +#warning: Need to dispatch to actual add method to prevent error messages from being generated + return static_cast(this)->_order_by._dynamic_expressions.emplace_back(expression); + } + }; _parameter_tuple_t _expressions; vendor::interpretable_list_t _dynamic_expressions; @@ -77,6 +84,29 @@ namespace sqlpp { using _is_noop = std::true_type; using _table_set = ::sqlpp::detail::type_set<>; + + template + struct _methods_t + { + using _database_t = typename Policies::_database_t; + template + using _new_select_t = typename Policies::template _policies_update_t; + + template + auto order_by(Args... args) + -> _new_select_t> + { + return { *static_cast(this), order_by_t{args...} }; + } + + template + auto dynamic_order_by(Args... args) + -> _new_select_t> + { + static_assert(not std::is_same<_database_t, void>::value, "dynamic_order_by must not be called in a static statement"); + return { *static_cast(this), vendor::order_by_t<_database_t, Args...>{args...} }; + } + }; }; // Interpreters diff --git a/include/sqlpp11/vendor/where.h b/include/sqlpp11/vendor/where.h index 8dfc8199..55f7a150 100644 --- a/include/sqlpp11/vendor/where.h +++ b/include/sqlpp11/vendor/where.h @@ -131,7 +131,6 @@ namespace sqlpp static_assert(not std::is_same<_database_t, void>::value, "dynamic_where must not be called in a static statement"); return { *static_cast(this), vendor::where_t<_database_t, Args...>{args...} }; } - }; }; From a541d8e1874772032d5b3442d1bc3f319d024786 Mon Sep 17 00:00:00 2001 From: rbock Date: Tue, 8 Apr 2014 22:18:28 +0200 Subject: [PATCH 51/74] Moved having-methods to having-classes --- include/sqlpp11/select.h | 26 +-------------------- include/sqlpp11/vendor/having.h | 40 ++++++++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index fd93479e..18657a47 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -131,6 +131,7 @@ namespace sqlpp > struct select_t: public detail::select_helper_t::_value_type::template expression_operators>, Where::template _methods_t>, + Having::template _methods_t>, OrderBy::template _methods_t>, Limit::template _methods_t>, Offset::template _methods_t> @@ -252,23 +253,6 @@ namespace sqlpp 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...} }; - } - // value adding methods template void add_flag(Args... args) @@ -302,14 +286,6 @@ namespace sqlpp 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...); - } - // PseudoTable template struct _pseudo_table_t diff --git a/include/sqlpp11/vendor/having.h b/include/sqlpp11/vendor/having.h index 7572b205..ad29d987 100644 --- a/include/sqlpp11/vendor/having.h +++ b/include/sqlpp11/vendor/having.h @@ -51,6 +51,8 @@ namespace sqlpp using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type; + using _table_set = typename ::sqlpp::detail::make_joined_set::type; + having_t(Expressions... expressions): _expressions(expressions...) {} @@ -61,12 +63,17 @@ namespace sqlpp having_t& operator=(having_t&&) = default; ~having_t() = default; - template - void add(Expression expr) + template + struct _methods_t { - static_assert(is_expression_t::value, "invalid expression argument in add_having()"); - _dynamic_expressions.emplace_back(expr); - } + template + void add_having(Expression expression) + { + static_assert(is_expression_t::value, "invalid expression argument in add_having()"); +#warning: Need to dispatch to actual add method to prevent error messages from being generated + return static_cast(this)->_having._dynamic_expressions.emplace_back(expression); + } + }; _parameter_tuple_t _expressions; vendor::interpretable_list_t _dynamic_expressions; @@ -76,6 +83,29 @@ namespace sqlpp { using _is_noop = std::true_type; using _table_set = ::sqlpp::detail::type_set<>; + + template + struct _methods_t + { + using _database_t = typename Policies::_database_t; + template + using _new_select_t = typename Policies::template _policies_update_t; + + template + auto having(Args... args) + -> _new_select_t> + { + return { *static_cast(this), having_t{args...} }; + } + + template + auto dynamic_having(Args... args) + -> _new_select_t> + { + static_assert(not std::is_same<_database_t, void>::value, "dynamic_having must not be called in a static statement"); + return { *static_cast(this), vendor::having_t<_database_t, Args...>{args...} }; + } + }; }; // Interpreters From 7af13937bfed37d13fd1c86bb7e9c0d53b13358a Mon Sep 17 00:00:00 2001 From: rbock Date: Tue, 8 Apr 2014 22:26:45 +0200 Subject: [PATCH 52/74] Moved group_by-methods to group_by classes --- include/sqlpp11/select.h | 26 +------------------- include/sqlpp11/vendor/group_by.h | 40 +++++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 18657a47..f102fc0b 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -131,6 +131,7 @@ namespace sqlpp > struct select_t: public detail::select_helper_t::_value_type::template expression_operators>, Where::template _methods_t>, + GroupBy::template _methods_t>, Having::template _methods_t>, OrderBy::template _methods_t>, Limit::template _methods_t>, @@ -236,23 +237,6 @@ namespace sqlpp return { *this, vendor::from_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...} }; - } - // value adding methods template void add_flag(Args... args) @@ -278,14 +262,6 @@ namespace sqlpp return _from.add_from(*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...); - } - // PseudoTable template struct _pseudo_table_t diff --git a/include/sqlpp11/vendor/group_by.h b/include/sqlpp11/vendor/group_by.h index 5491a6e8..8c6bba6f 100644 --- a/include/sqlpp11/vendor/group_by.h +++ b/include/sqlpp11/vendor/group_by.h @@ -46,6 +46,8 @@ namespace sqlpp using _is_group_by = std::true_type; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; using _parameter_tuple_t = std::tuple; +#warning Has no parameter_list? + using _table_set = typename ::sqlpp::detail::make_joined_set::type; static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression (e.g. a column) required in group_by()"); @@ -63,12 +65,17 @@ namespace sqlpp group_by_t& operator=(group_by_t&&) = default; ~group_by_t() = default; - template - void add_group_by(const Statement&, Expression expression) + template + struct _methods_t { - static_assert(is_table_t::value, "from arguments require to be tables or joins"); - _dynamic_expressions.emplace_back(expression); - } + template + void add_group_by(Expression expression) + { + static_assert(is_expression_t::value, "invalid expression argument in add_group_by()"); +#warning: Need to dispatch to actual add method to prevent error messages from being generated + return static_cast(this)->_group_by._dynamic_expressions.emplace_back(expression); + } + }; const group_by_t& _group_by() const { return *this; } _parameter_tuple_t _expressions; @@ -79,6 +86,29 @@ namespace sqlpp { using _is_noop = std::true_type; using _table_set = ::sqlpp::detail::type_set<>; + + template + struct _methods_t + { + using _database_t = typename Policies::_database_t; + template + using _new_select_t = typename Policies::template _policies_update_t; + + template + auto group_by(Args... args) + -> _new_select_t> + { + return { *static_cast(this), group_by_t{args...} }; + } + + template + auto dynamic_group_by(Args... args) + -> _new_select_t> + { + static_assert(not std::is_same<_database_t, void>::value, "dynamic_group_by must not be called in a static statement"); + return { *static_cast(this), vendor::group_by_t<_database_t, Args...>{args...} }; + } + }; }; // Interpreters From 5e0c1cff48c8e113522c88674d6bc0e8678fcebf Mon Sep 17 00:00:00 2001 From: rbock Date: Tue, 8 Apr 2014 22:45:19 +0200 Subject: [PATCH 53/74] Moved flag-methods to select_flag classes --- include/sqlpp11/select.h | 26 +-------------- include/sqlpp11/vendor/group_by.h | 1 + include/sqlpp11/vendor/having.h | 1 + include/sqlpp11/vendor/order_by.h | 1 + include/sqlpp11/vendor/select_flag_list.h | 39 ++++++++++++++++++++--- 5 files changed, 38 insertions(+), 30 deletions(-) diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index f102fc0b..e950e84f 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -130,6 +130,7 @@ namespace sqlpp typename Offset > struct select_t: public detail::select_helper_t::_value_type::template expression_operators>, + FlagList::template _methods_t>, Where::template _methods_t>, GroupBy::template _methods_t>, Having::template _methods_t>, @@ -188,23 +189,6 @@ namespace sqlpp ~select_t() = default; // 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> @@ -238,14 +222,6 @@ namespace sqlpp } // 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) { diff --git a/include/sqlpp11/vendor/group_by.h b/include/sqlpp11/vendor/group_by.h index 8c6bba6f..29b6438d 100644 --- a/include/sqlpp11/vendor/group_by.h +++ b/include/sqlpp11/vendor/group_by.h @@ -71,6 +71,7 @@ namespace sqlpp 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()"); #warning: Need to dispatch to actual add method to prevent error messages from being generated return static_cast(this)->_group_by._dynamic_expressions.emplace_back(expression); diff --git a/include/sqlpp11/vendor/having.h b/include/sqlpp11/vendor/having.h index ad29d987..c75b2a49 100644 --- a/include/sqlpp11/vendor/having.h +++ b/include/sqlpp11/vendor/having.h @@ -69,6 +69,7 @@ namespace sqlpp 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()"); #warning: Need to dispatch to actual add method to prevent error messages from being generated return static_cast(this)->_having._dynamic_expressions.emplace_back(expression); diff --git a/include/sqlpp11/vendor/order_by.h b/include/sqlpp11/vendor/order_by.h index a8bf3edb..4aff0f26 100644 --- a/include/sqlpp11/vendor/order_by.h +++ b/include/sqlpp11/vendor/order_by.h @@ -70,6 +70,7 @@ namespace sqlpp 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()"); #warning: Need to dispatch to actual add method to prevent error messages from being generated return static_cast(this)->_order_by._dynamic_expressions.emplace_back(expression); diff --git a/include/sqlpp11/vendor/select_flag_list.h b/include/sqlpp11/vendor/select_flag_list.h index d1292da2..b42440ba 100644 --- a/include/sqlpp11/vendor/select_flag_list.h +++ b/include/sqlpp11/vendor/select_flag_list.h @@ -61,12 +61,18 @@ namespace sqlpp select_flag_list_t& operator=(select_flag_list_t&&) = default; ~select_flag_list_t() = default; - template - void add_flag(const Select&, Flag flag) + template + struct _methods_t { - static_assert(is_select_flag_t::value, "flag arguments require to be select flags"); - _dynamic_flags.emplace_back(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()"); +#warning: Need to dispatch to actual add method to prevent error messages from being generated + return static_cast(this)->_flag_list._dynamic_flags.emplace_back(flag); + } + }; const select_flag_list_t& _flag_list() const { return *this; } _parameter_tuple_t _flags; @@ -76,6 +82,29 @@ namespace sqlpp struct no_select_flag_list_t { using _is_noop = std::true_type; + + template + struct _methods_t + { + using _database_t = typename Policies::_database_t; + template + using _new_select_t = typename Policies::template _policies_update_t; + + template + auto flags(Args... args) + -> _new_select_t> + { + return { *static_cast(this), select_flag_list_t{args...} }; + } + + template + auto dynamic_flags(Args... args) + -> _new_select_t> + { + static_assert(not std::is_same<_database_t, void>::value, "dynamic_flags must not be called in a static statement"); + return { *static_cast(this), vendor::select_flag_list_t<_database_t, Args...>{args...} }; + } + }; }; From 18d244dd9f26e8306f9e6563fd9a92c468758de3 Mon Sep 17 00:00:00 2001 From: rbock Date: Wed, 9 Apr 2014 07:25:24 +0200 Subject: [PATCH 54/74] Moved from-methods to from-classes --- include/sqlpp11/select.h | 24 +------------------- include/sqlpp11/vendor/from.h | 40 +++++++++++++++++++++++++++++----- include/sqlpp11/vendor/where.h | 1 + 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index e950e84f..1523bf7c 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -131,6 +131,7 @@ namespace sqlpp > struct select_t: public detail::select_helper_t::_value_type::template expression_operators>, FlagList::template _methods_t>, + From::template _methods_t>, Where::template _methods_t>, GroupBy::template _methods_t>, Having::template _methods_t>, @@ -206,21 +207,6 @@ namespace sqlpp 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...} }; - } - // value adding methods template void add_column(Args... args) @@ -230,14 +216,6 @@ namespace sqlpp 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...); - } - // PseudoTable template struct _pseudo_table_t diff --git a/include/sqlpp11/vendor/from.h b/include/sqlpp11/vendor/from.h index e703b2b3..72a66980 100644 --- a/include/sqlpp11/vendor/from.h +++ b/include/sqlpp11/vendor/from.h @@ -64,13 +64,17 @@ namespace sqlpp from_t& operator=(from_t&&) = default; ~from_t() = default; - template - void add_from(const Select&, Table table) + template + struct _methods_t { - 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); - } + template + void add_from(Table table) + { + static_assert(is_table_t
::value, "invalid expression argument in add_from()"); +#warning: Need to dispatch to actual add method to prevent error messages from being generated + return static_cast(this)->_from._dynamic_tables.emplace_back(table); + } + }; std::tuple _tables; vendor::interpretable_list_t _dynamic_tables; @@ -79,6 +83,30 @@ namespace sqlpp struct no_from_t { using _is_noop = std::true_type; + using _table_set = ::sqlpp::detail::type_set<>; + + template + struct _methods_t + { + using _database_t = typename Policies::_database_t; + template + using _new_select_t = typename Policies::template _policies_update_t; + + template + auto from(Args... args) + -> _new_select_t> + { + return { *static_cast(this), from_t{args...} }; + } + + template + auto dynamic_from(Args... args) + -> _new_select_t> + { + static_assert(not std::is_same<_database_t, void>::value, "dynamic_from must not be called in a static statement"); + return { *static_cast(this), vendor::from_t<_database_t, Args...>{args...} }; + } + }; }; // Interpreters diff --git a/include/sqlpp11/vendor/where.h b/include/sqlpp11/vendor/where.h index 55f7a150..d7ddabeb 100644 --- a/include/sqlpp11/vendor/where.h +++ b/include/sqlpp11/vendor/where.h @@ -70,6 +70,7 @@ namespace sqlpp 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()"); #warning: Need to dispatch to actual add method to prevent error messages from being generated return static_cast(this)->_where._dynamic_expressions.emplace_back(expression); From db0bbd6e3fefa939bcaeb5433fbb964f653a4f40 Mon Sep 17 00:00:00 2001 From: rbock Date: Wed, 9 Apr 2014 08:50:34 +0200 Subject: [PATCH 55/74] Moved select_colum_list methods to the respective classes --- include/sqlpp11/select.h | 28 +----------- include/sqlpp11/vendor/select_column_list.h | 47 +++++++++++++++++---- tests/SelectTest.cpp | 17 ++++++++ 3 files changed, 57 insertions(+), 35 deletions(-) diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 1523bf7c..bc27fc43 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -131,6 +131,7 @@ namespace sqlpp > struct select_t: public detail::select_helper_t::_value_type::template expression_operators>, FlagList::template _methods_t>, + ColumnList::template _methods_t>, From::template _methods_t>, Where::template _methods_t>, GroupBy::template _methods_t>, @@ -189,33 +190,6 @@ namespace sqlpp select_t& operator=(select_t&& r) = default; ~select_t() = default; - // type update functions - 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...} }; - } - - // value adding methods - 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...); - } - // PseudoTable template struct _pseudo_table_t diff --git a/include/sqlpp11/vendor/select_column_list.h b/include/sqlpp11/vendor/select_column_list.h index fdb9427a..58846181 100644 --- a/include/sqlpp11/vendor/select_column_list.h +++ b/include/sqlpp11/vendor/select_column_list.h @@ -68,7 +68,7 @@ namespace sqlpp _names_t _dynamic_expression_names; template - void push_back(Expr expr) + void emplace_back(Expr expr) { _dynamic_expression_names.push_back(Expr::_name_t::_get_name()); _dynamic_columns.emplace_back(expr); @@ -89,8 +89,9 @@ namespace sqlpp }; _names_t _dynamic_expression_names; +#warning: Put an assert here or remove implementation to make sure this never aktually gets called template - void push_back(const T&) {} + void emplace_back(const T&) {} static constexpr bool empty() { @@ -185,13 +186,19 @@ namespace sqlpp select_column_list_t& operator=(select_column_list_t&&) = default; ~select_column_list_t() = default; - template - void add_column(const Select&, Expr namedExpr) + template + struct _methods_t { - 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"); - _dynamic_columns.push_back(namedExpr); - } + 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()"); +#warning: Need to dispatch to actual add method to prevent error messages from being generated + return static_cast(this)->_column_list._dynamic_columns.emplace_back(namedExpression); + } + }; + const select_column_list_t& _column_list() const { return *this; } _parameter_tuple_t _columns; @@ -212,6 +219,30 @@ namespace sqlpp { static_assert(wrong_t::value, "Cannot use a select as a table when no columns have been selected yet"); }; + + template + struct _methods_t + { + using _database_t = typename Policies::_database_t; + template + using _new_select_t = typename Policies::template _policies_update_t; + + template + auto columns(Args... args) + -> _new_select_t> + { +#warning need to handle all_of_t here + return { *static_cast(this), select_column_list_t{args...} }; + } + + template + auto dynamic_columns(Args... args) + -> _new_select_t> + { + static_assert(not std::is_same<_database_t, void>::value, "dynamic_columns must not be called in a static statement"); + return { *static_cast(this), vendor::select_column_list_t<_database_t, Args...>{args...} }; + } + }; }; // Interpreters diff --git a/tests/SelectTest.cpp b/tests/SelectTest.cpp index 423ff488..8880da29 100644 --- a/tests/SelectTest.cpp +++ b/tests/SelectTest.cpp @@ -49,6 +49,7 @@ int main() test::TabFoo f; test::TabBar t; + /* for (const auto& row : db(select(all_of(t)).from(t).where(true))) { int64_t a = row.alpha; @@ -67,6 +68,22 @@ int main() const std::string b = row.tabBar.beta; const bool g = row.gamma; } + */ + + auto s = dynamic_select(db).dynamic_columns(t.alpha).dynamic_flags().dynamic_from(t).dynamic_where().dynamic_group_by(t.alpha).dynamic_order_by().dynamic_having(t.gamma).dynamic_limit().dynamic_offset(); + s.add_flag(sqlpp::distinct); + s.add_column(t.beta); + s.add_from(f); + s.add_where(t.alpha > 7); + s.add_having(t.alpha > 7); + s.set_limit(3); + s.set_offset(3); + s.add_group_by(t.beta); + s.add_order_by(t.beta.asc()); + for (const auto& row : db(s)) + { + int64_t a = row.alpha; + } return 0; } From ad5584e52dcb7ff1367cd1863c66c8582a8d3304 Mon Sep 17 00:00:00 2001 From: rbock Date: Wed, 9 Apr 2014 20:54:28 +0200 Subject: [PATCH 56/74] Cleaned up a bit... --- include/sqlpp11/select.h | 216 +++++++++----------- include/sqlpp11/vendor/from.h | 6 +- include/sqlpp11/vendor/group_by.h | 6 +- include/sqlpp11/vendor/having.h | 6 +- include/sqlpp11/vendor/limit.h | 8 +- include/sqlpp11/vendor/offset.h | 8 +- include/sqlpp11/vendor/order_by.h | 6 +- include/sqlpp11/vendor/select_column_list.h | 6 +- include/sqlpp11/vendor/select_flag_list.h | 6 +- include/sqlpp11/vendor/where.h | 6 +- 10 files changed, 125 insertions(+), 149 deletions(-) diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index bc27fc43..925b6186 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -51,7 +51,14 @@ namespace sqlpp { - template + struct select_t; + + namespace detail + { + template - struct select_t; - namespace detail - { - template struct select_policies_t { using _database_t = Db; - using _select_t = select_t; + using _flag_list_t = FlagList; + using _column_list_t = ColumnList; + using _from_t = From; + using _where_t = Where; + using _group_by_t = GroupBy; + using _having_t = Having; + using _order_by_t = OrderBy; + using _limit_t = Limit; + using _offset_t = Offset; + + using _statement_t = select_t; + + struct _methods_t: + public _flag_list_t::template _methods_t, + public _column_list_t::template _methods_t, + public _from_t::template _methods_t, + public _where_t::template _methods_t, + public _group_by_t::template _methods_t, + public _having_t::template _methods_t, + public _order_by_t::template _methods_t, + public _limit_t::template _methods_t, + public _offset_t::template _methods_t + {}; + template struct _policies_update_impl { +#warning: Need to make sure that Needle is in Policies! using type = select_t...>; }; template using _policies_update_t = typename _policies_update_impl::type; - static_assert(is_noop_t::value or sqlpp::is_select_column_list_t::value, "column list of select is neither naught nor a valid column list"); - static_assert(is_noop_t::value or sqlpp::is_from_t::value, "from() part of select is neither naught nor a valid from()"); - 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; - }; - } - - namespace detail - { - template< - typename ColumnList, - typename From - > - struct select_helper_t - { static_assert(is_noop_t::value or sqlpp::is_select_column_list_t::value, "column list of select is neither naught nor a valid column list"); static_assert(is_noop_t::value or sqlpp::is_from_t::value, "from() part of select is neither naught nor a valid from()"); using _value_type = typename std::conditional< @@ -118,53 +117,39 @@ namespace sqlpp } // SELECT - template - struct select_t: public detail::select_helper_t::_value_type::template expression_operators>, - FlagList::template _methods_t>, - ColumnList::template _methods_t>, - From::template _methods_t>, - Where::template _methods_t>, - GroupBy::template _methods_t>, - Having::template _methods_t>, - OrderBy::template _methods_t>, - Limit::template _methods_t>, - Offset::template _methods_t> + struct select_t: + public detail::select_policies_t::_value_type::template expression_operators>, + public detail::select_policies_t::_methods_t { - using _database_t = Database; - using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; + using _policies_t = typename detail::select_policies_t; + using _database_t = typename _policies_t::_database_t; + using _flag_list_t = typename _policies_t::_flag_list_t; + using _column_list_t = typename _policies_t::_column_list_t; + using _from_t = typename _policies_t::_from_t; + using _where_t = typename _policies_t::_where_t; + using _group_by_t = typename _policies_t::_group_by_t; + using _having_t = typename _policies_t::_having_t; + using _order_by_t = typename _policies_t::_order_by_t; + using _limit_t = typename _policies_t::_limit_t; + using _offset_t = typename _policies_t::_offset_t; - template - struct _policies_update_impl - { - using type = select_t...>; - }; + using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - template - using _policies_update_t = typename _policies_update_impl::type; - - using _parameter_tuple_t = std::tuple; + using _parameter_tuple_t = std::tuple; using _parameter_list_t = typename make_parameter_list_t::type; using _table_set = ::sqlpp::detail::type_set<>; - using _column_list_t = ColumnList; - template - using _result_row_t = typename _column_list_t::template _result_row_t; + template + using _result_row_t = typename _column_list_t::template _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_policies_t::_value_type; using _name_t = typename _column_list_t::_name_t; // Constructors @@ -173,15 +158,15 @@ namespace sqlpp template select_t(Statement s, T t): - _flag_list(detail::arg_selector::_(s._flag_list, t)), - _column_list(detail::arg_selector::_(s._column_list, t)), - _from(detail::arg_selector::_(s._from, t)), - _where(detail::arg_selector::_(s._where, t)), - _group_by(detail::arg_selector::_(s._group_by, t)), - _having(detail::arg_selector::_(s._having, t)), - _order_by(detail::arg_selector::_(s._order_by, t)), - _limit(detail::arg_selector::_(s._limit, t)), - _offset(detail::arg_selector::_(s._offset, t)) + _flag_list(detail::arg_selector<_flag_list_t>::_(s._flag_list, t)), + _column_list(detail::arg_selector<_column_list_t>::_(s._column_list, t)), + _from(detail::arg_selector<_from_t>::_(s._from, t)), + _where(detail::arg_selector<_where_t>::_(s._where, t)), + _group_by(detail::arg_selector<_group_by_t>::_(s._group_by, t)), + _having(detail::arg_selector<_having_t>::_(s._having, t)), + _order_by(detail::arg_selector<_order_by_t>::_(s._order_by, t)), + _limit(detail::arg_selector<_limit_t>::_(s._limit, t)), + _offset(detail::arg_selector<_offset_t>::_(s._offset, t)) {} select_t(const select_t& r) = default; @@ -240,46 +225,46 @@ namespace sqlpp template struct is_table_subset_of_from { - static constexpr bool value = ::sqlpp::detail::is_subset_of::value; + static constexpr bool value = ::sqlpp::detail::is_subset_of::value; }; // Execute - template - auto _run(Db& db) const - -> result_t> + 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 #warning: might want to add an .extra_tables() method to say which tables might also be used here, say via dynamic_from or because this is a subselect - static_assert(is_table_subset_of_from::value, "selected columns require additional tables in from()"); - static_assert(is_table_subset_of_from::value, "where() expression requires additional tables in from()"); - static_assert(is_table_subset_of_from::value, "group_by() expression requires additional tables in from()"); - static_assert(is_table_subset_of_from::value, "having() expression requires additional tables in from()"); - static_assert(is_table_subset_of_from::value, "order_by() expression requires additional tables in from()"); - static_assert(is_table_subset_of_from::value, "limit() expression requires additional tables in from()"); - static_assert(is_table_subset_of_from::value, "offset() expression requires 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(_get_static_no_of_parameters() == 0, "cannot run select directly with parameters, use prepare instead"); return {db.select(*this), get_dynamic_names()}; } // Prepare - template - auto _prepare(Db& db) const - -> prepared_select_t + template + auto _prepare(Database& db) const + -> prepared_select_t { 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; + _flag_list_t _flag_list; + _column_list_t _column_list; + _from_t _from; + _where_t _where; + _group_by_t _group_by; + _having_t _having; + _order_by_t _order_by; + _limit_t _limit; + _offset_t _offset; }; namespace vendor @@ -308,17 +293,8 @@ namespace sqlpp }; } - template - using blank_select_t = select_t; + template + using make_select_t = typename detail::select_policies_t::_statement_t; namespace detail { @@ -328,29 +304,29 @@ namespace sqlpp decltype(std::tuple_cat(as_tuple::_(std::declval())...))>; } - select_t select() // FIXME: These should be constexpr + make_select_t select() // FIXME: These should be constexpr { - return { select_t() }; + return { }; } template auto select(Columns... columns) - -> select_t> + -> make_select_t> { - return { select_t(), detail::make_select_column_list_t(std::tuple_cat(detail::as_tuple::_(columns)...)) }; + return { make_select_t(), detail::make_select_column_list_t(std::tuple_cat(detail::as_tuple::_(columns)...)) }; } template - select_t dynamic_select(const Database&) + make_select_t dynamic_select(const Database&) { - return { select_t() }; + return { make_select_t() }; } template auto dynamic_select(const Database&, Columns... columns) - -> select_t> + -> make_select_t> { - return { select_t(), detail::make_select_column_list_t(std::tuple_cat(detail::as_tuple::_(columns)...)) }; + return { make_select_t(), detail::make_select_column_list_t(std::tuple_cat(detail::as_tuple::_(columns)...)) }; } } diff --git a/include/sqlpp11/vendor/from.h b/include/sqlpp11/vendor/from.h index 72a66980..9a354bc8 100644 --- a/include/sqlpp11/vendor/from.h +++ b/include/sqlpp11/vendor/from.h @@ -72,7 +72,7 @@ namespace sqlpp { static_assert(is_table_t
::value, "invalid expression argument in add_from()"); #warning: Need to dispatch to actual add method to prevent error messages from being generated - return static_cast(this)->_from._dynamic_tables.emplace_back(table); + return static_cast(this)->_from._dynamic_tables.emplace_back(table); } }; @@ -96,7 +96,7 @@ namespace sqlpp auto from(Args... args) -> _new_select_t> { - return { *static_cast(this), from_t{args...} }; + return { *static_cast(this), from_t{args...} }; } template @@ -104,7 +104,7 @@ namespace sqlpp -> _new_select_t> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_from must not be called in a static statement"); - return { *static_cast(this), vendor::from_t<_database_t, Args...>{args...} }; + return { *static_cast(this), vendor::from_t<_database_t, Args...>{args...} }; } }; }; diff --git a/include/sqlpp11/vendor/group_by.h b/include/sqlpp11/vendor/group_by.h index 29b6438d..b4764179 100644 --- a/include/sqlpp11/vendor/group_by.h +++ b/include/sqlpp11/vendor/group_by.h @@ -74,7 +74,7 @@ namespace sqlpp 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()"); #warning: Need to dispatch to actual add method to prevent error messages from being generated - return static_cast(this)->_group_by._dynamic_expressions.emplace_back(expression); + return static_cast(this)->_group_by._dynamic_expressions.emplace_back(expression); } }; @@ -99,7 +99,7 @@ namespace sqlpp auto group_by(Args... args) -> _new_select_t> { - return { *static_cast(this), group_by_t{args...} }; + return { *static_cast(this), group_by_t{args...} }; } template @@ -107,7 +107,7 @@ namespace sqlpp -> _new_select_t> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_group_by must not be called in a static statement"); - return { *static_cast(this), vendor::group_by_t<_database_t, Args...>{args...} }; + return { *static_cast(this), vendor::group_by_t<_database_t, Args...>{args...} }; } }; }; diff --git a/include/sqlpp11/vendor/having.h b/include/sqlpp11/vendor/having.h index c75b2a49..921ceffa 100644 --- a/include/sqlpp11/vendor/having.h +++ b/include/sqlpp11/vendor/having.h @@ -72,7 +72,7 @@ namespace sqlpp 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()"); #warning: Need to dispatch to actual add method to prevent error messages from being generated - return static_cast(this)->_having._dynamic_expressions.emplace_back(expression); + return static_cast(this)->_having._dynamic_expressions.emplace_back(expression); } }; @@ -96,7 +96,7 @@ namespace sqlpp auto having(Args... args) -> _new_select_t> { - return { *static_cast(this), having_t{args...} }; + return { *static_cast(this), having_t{args...} }; } template @@ -104,7 +104,7 @@ namespace sqlpp -> _new_select_t> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_having must not be called in a static statement"); - return { *static_cast(this), vendor::having_t<_database_t, Args...>{args...} }; + return { *static_cast(this), vendor::having_t<_database_t, Args...>{args...} }; } }; }; diff --git a/include/sqlpp11/vendor/limit.h b/include/sqlpp11/vendor/limit.h index 683e7581..47cea9f9 100644 --- a/include/sqlpp11/vendor/limit.h +++ b/include/sqlpp11/vendor/limit.h @@ -94,8 +94,8 @@ namespace sqlpp void set_limit(Limit value) { using arg_t = typename wrap_operand::type; - static_cast(this)->_limit._value = arg_t{value}; - static_cast(this)->_limit._initialized = true; + static_cast(this)->_limit._value = arg_t{value}; + static_cast(this)->_limit._initialized = true; } }; @@ -119,14 +119,14 @@ namespace sqlpp auto limit(Arg arg) -> _new_select_t::type>> { - return { *static_cast(this), limit_t::type>{{arg}} }; + return { *static_cast(this), limit_t::type>{{arg}} }; } auto dynamic_limit() -> _new_select_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_t<_database_t>{} }; + return { *static_cast(this), dynamic_limit_t<_database_t>{} }; } }; }; diff --git a/include/sqlpp11/vendor/offset.h b/include/sqlpp11/vendor/offset.h index 0c3ad9e1..0568ef9d 100644 --- a/include/sqlpp11/vendor/offset.h +++ b/include/sqlpp11/vendor/offset.h @@ -93,8 +93,8 @@ namespace sqlpp void set_offset(Offset value) { using arg_t = typename wrap_operand::type; - static_cast(this)->_offset._value = arg_t{value}; - static_cast(this)->_offset._initialized = true; + static_cast(this)->_offset._value = arg_t{value}; + static_cast(this)->_offset._initialized = true; } }; @@ -118,14 +118,14 @@ namespace sqlpp auto offset(Arg arg) -> _new_select_t::type>> { - return { *static_cast(this), offset_t::type>{{arg}} }; + return { *static_cast(this), offset_t::type>{{arg}} }; } auto dynamic_offset() -> _new_select_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_t<_database_t>{} }; + return { *static_cast(this), dynamic_offset_t<_database_t>{} }; } }; }; diff --git a/include/sqlpp11/vendor/order_by.h b/include/sqlpp11/vendor/order_by.h index 4aff0f26..8cf3583a 100644 --- a/include/sqlpp11/vendor/order_by.h +++ b/include/sqlpp11/vendor/order_by.h @@ -73,7 +73,7 @@ namespace sqlpp 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()"); #warning: Need to dispatch to actual add method to prevent error messages from being generated - return static_cast(this)->_order_by._dynamic_expressions.emplace_back(expression); + return static_cast(this)->_order_by._dynamic_expressions.emplace_back(expression); } }; @@ -97,7 +97,7 @@ namespace sqlpp auto order_by(Args... args) -> _new_select_t> { - return { *static_cast(this), order_by_t{args...} }; + return { *static_cast(this), order_by_t{args...} }; } template @@ -105,7 +105,7 @@ namespace sqlpp -> _new_select_t> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_order_by must not be called in a static statement"); - return { *static_cast(this), vendor::order_by_t<_database_t, Args...>{args...} }; + return { *static_cast(this), vendor::order_by_t<_database_t, Args...>{args...} }; } }; }; diff --git a/include/sqlpp11/vendor/select_column_list.h b/include/sqlpp11/vendor/select_column_list.h index 58846181..9d22d10f 100644 --- a/include/sqlpp11/vendor/select_column_list.h +++ b/include/sqlpp11/vendor/select_column_list.h @@ -195,7 +195,7 @@ namespace sqlpp 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()"); #warning: Need to dispatch to actual add method to prevent error messages from being generated - return static_cast(this)->_column_list._dynamic_columns.emplace_back(namedExpression); + return static_cast(this)->_column_list._dynamic_columns.emplace_back(namedExpression); } }; @@ -232,7 +232,7 @@ namespace sqlpp -> _new_select_t> { #warning need to handle all_of_t here - return { *static_cast(this), select_column_list_t{args...} }; + return { *static_cast(this), select_column_list_t{args...} }; } template @@ -240,7 +240,7 @@ namespace sqlpp -> _new_select_t> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_columns must not be called in a static statement"); - return { *static_cast(this), vendor::select_column_list_t<_database_t, Args...>{args...} }; + return { *static_cast(this), vendor::select_column_list_t<_database_t, Args...>{args...} }; } }; }; diff --git a/include/sqlpp11/vendor/select_flag_list.h b/include/sqlpp11/vendor/select_flag_list.h index b42440ba..1c8b2c33 100644 --- a/include/sqlpp11/vendor/select_flag_list.h +++ b/include/sqlpp11/vendor/select_flag_list.h @@ -70,7 +70,7 @@ namespace sqlpp 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()"); #warning: Need to dispatch to actual add method to prevent error messages from being generated - return static_cast(this)->_flag_list._dynamic_flags.emplace_back(flag); + return static_cast(this)->_flag_list._dynamic_flags.emplace_back(flag); } }; @@ -94,7 +94,7 @@ namespace sqlpp auto flags(Args... args) -> _new_select_t> { - return { *static_cast(this), select_flag_list_t{args...} }; + return { *static_cast(this), select_flag_list_t{args...} }; } template @@ -102,7 +102,7 @@ namespace sqlpp -> _new_select_t> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_flags must not be called in a static statement"); - return { *static_cast(this), vendor::select_flag_list_t<_database_t, Args...>{args...} }; + return { *static_cast(this), vendor::select_flag_list_t<_database_t, Args...>{args...} }; } }; }; diff --git a/include/sqlpp11/vendor/where.h b/include/sqlpp11/vendor/where.h index d7ddabeb..b82f4e6e 100644 --- a/include/sqlpp11/vendor/where.h +++ b/include/sqlpp11/vendor/where.h @@ -73,7 +73,7 @@ namespace sqlpp 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()"); #warning: Need to dispatch to actual add method to prevent error messages from being generated - return static_cast(this)->_where._dynamic_expressions.emplace_back(expression); + return static_cast(this)->_where._dynamic_expressions.emplace_back(expression); } }; @@ -122,7 +122,7 @@ namespace sqlpp auto where(Args... args) -> _new_select_t> { - return { *static_cast(this), where_t{args...} }; + return { *static_cast(this), where_t{args...} }; } template @@ -130,7 +130,7 @@ namespace sqlpp -> _new_select_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), vendor::where_t<_database_t, Args...>{args...} }; + return { *static_cast(this), vendor::where_t<_database_t, Args...>{args...} }; } }; }; From bc5ffc14921e96c47ed05e53bd21f2ab5d478df7 Mon Sep 17 00:00:00 2001 From: rbock Date: Thu, 10 Apr 2014 16:09:54 +0200 Subject: [PATCH 57/74] Added several call dispatches to reduce compiler spew in case of errors --- include/sqlpp11/detail/logic.h | 19 +++++++++++-------- include/sqlpp11/detail/type_set.h | 3 +++ include/sqlpp11/select.h | 2 +- include/sqlpp11/vendor/from.h | 17 +++++++++++++++-- include/sqlpp11/vendor/group_by.h | 14 +++++++++++++- include/sqlpp11/vendor/having.h | 14 +++++++++++++- include/sqlpp11/vendor/order_by.h | 14 +++++++++++++- include/sqlpp11/vendor/select_column_list.h | 14 +++++++++++++- include/sqlpp11/vendor/select_flag_list.h | 14 +++++++++++++- include/sqlpp11/vendor/where.h | 14 +++++++++++++- 10 files changed, 108 insertions(+), 17 deletions(-) diff --git a/include/sqlpp11/detail/logic.h b/include/sqlpp11/detail/logic.h index 3cc8a208..a533a4ee 100644 --- a/include/sqlpp11/detail/logic.h +++ b/include/sqlpp11/detail/logic.h @@ -39,23 +39,23 @@ namespace sqlpp template<> struct all_impl<> { - static constexpr bool value = true; + using type = std::true_type; }; template struct all_impl { - static constexpr bool value = all_impl::value; + using type = typename all_impl::type; }; template struct all_impl { - static constexpr bool value = false; + using type = std::false_type; }; template class Predicate, typename... T> - using all_t = all_impl::value...>; + using all_t = typename all_impl::value...>::type; template struct any_impl; @@ -63,24 +63,27 @@ namespace sqlpp template<> struct any_impl<> { - static constexpr bool value = false; + using type = std::false_type; }; template struct any_impl { - static constexpr bool value = any_impl::value; + using type = typename all_impl::type; }; template struct any_impl { - static constexpr bool value = true; + using type = std::true_type; }; template class Predicate, typename... T> - using any_t = any_impl::value...>; + using any_t = typename any_impl::value...>::type; + + template + using identity_t = T; } } diff --git a/include/sqlpp11/detail/type_set.h b/include/sqlpp11/detail/type_set.h index 51a2df20..7c4d15b7 100644 --- a/include/sqlpp11/detail/type_set.h +++ b/include/sqlpp11/detail/type_set.h @@ -145,6 +145,9 @@ namespace sqlpp using type = typename make_type_set::type::template insert::type; }; + template + using make_type_set_t = typename make_type_set::type; + template class Predicate, typename... T> struct make_type_set_if; diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 925b6186..d1d194a5 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -99,7 +99,7 @@ namespace sqlpp template struct _policies_update_impl { -#warning: Need to make sure that Needle is in Policies! + static_assert(detail::is_element_of>::value, "policies update for non-policy class detected"); using type = select_t...>; }; diff --git a/include/sqlpp11/vendor/from.h b/include/sqlpp11/vendor/from.h index 9a354bc8..99bb15dd 100644 --- a/include/sqlpp11/vendor/from.h +++ b/include/sqlpp11/vendor/from.h @@ -70,10 +70,23 @@ namespace sqlpp template void add_from(Table table) { - static_assert(is_table_t
::value, "invalid expression argument in add_from()"); -#warning: Need to dispatch to actual add method to prevent error messages from being generated + static_assert(_is_dynamic::value, "add_from must not be called for static from()"); + static_assert(is_table_t
::value, "invalid table argument in add_from()"); + + using ok = ::sqlpp::detail::all_t>; + + _add_from_impl(table, ok()); // dispatch to prevent compile messages after the static_assert + } + + private: + template + void _add_from_impl(Table table, const std::true_type&) + { return static_cast(this)->_from._dynamic_tables.emplace_back(table); } + + template + void _add_from_impl(Table table, const std::false_type&); }; std::tuple _tables; diff --git a/include/sqlpp11/vendor/group_by.h b/include/sqlpp11/vendor/group_by.h index b4764179..ceb78c22 100644 --- a/include/sqlpp11/vendor/group_by.h +++ b/include/sqlpp11/vendor/group_by.h @@ -73,9 +73,21 @@ namespace sqlpp { 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()"); -#warning: Need to dispatch to actual add method to prevent error messages from being generated + + using ok = ::sqlpp::detail::all_t>; + + _add_group_by_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert + } + + private: + template + void _add_group_by_impl(Expression expression, const std::true_type&) + { return static_cast(this)->_group_by._dynamic_expressions.emplace_back(expression); } + + template + void _add_group_by_impl(Expression expression, const std::false_type&); }; const group_by_t& _group_by() const { return *this; } diff --git a/include/sqlpp11/vendor/having.h b/include/sqlpp11/vendor/having.h index 921ceffa..b88c60d0 100644 --- a/include/sqlpp11/vendor/having.h +++ b/include/sqlpp11/vendor/having.h @@ -71,9 +71,21 @@ namespace sqlpp { 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()"); -#warning: Need to dispatch to actual add method to prevent error messages from being generated + + using ok = ::sqlpp::detail::all_t>; + + _add_having_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert + } + + private: + template + void _add_having_impl(Expression expression, const std::true_type&) + { return static_cast(this)->_having._dynamic_expressions.emplace_back(expression); } + + template + void _add_having_impl(Expression expression, const std::false_type&); }; _parameter_tuple_t _expressions; diff --git a/include/sqlpp11/vendor/order_by.h b/include/sqlpp11/vendor/order_by.h index 8cf3583a..41fdb5b0 100644 --- a/include/sqlpp11/vendor/order_by.h +++ b/include/sqlpp11/vendor/order_by.h @@ -72,9 +72,21 @@ namespace sqlpp { 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()"); -#warning: Need to dispatch to actual add method to prevent error messages from being generated + + using ok = ::sqlpp::detail::all_t>; + + _add_order_by_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert + } + + private: + template + void _add_order_by_impl(Expression expression, const std::true_type&) + { return static_cast(this)->_order_by._dynamic_expressions.emplace_back(expression); } + + template + void _add_order_by_impl(Expression expression, const std::false_type&); }; _parameter_tuple_t _expressions; diff --git a/include/sqlpp11/vendor/select_column_list.h b/include/sqlpp11/vendor/select_column_list.h index 9d22d10f..34e7b9e5 100644 --- a/include/sqlpp11/vendor/select_column_list.h +++ b/include/sqlpp11/vendor/select_column_list.h @@ -194,9 +194,21 @@ namespace sqlpp { 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()"); -#warning: Need to dispatch to actual add method to prevent error messages from being generated + + using ok = ::sqlpp::detail::all_t>; + + _add_column_impl(namedExpression, ok()); // dispatch to prevent compile messages after the static_assert + } + + private: + template + void _add_column_impl(NamedExpression namedExpression, const std::true_type&) + { return static_cast(this)->_column_list._dynamic_columns.emplace_back(namedExpression); } + + template + void _add_column_impl(NamedExpression namedExpression, const std::false_type&); }; diff --git a/include/sqlpp11/vendor/select_flag_list.h b/include/sqlpp11/vendor/select_flag_list.h index 1c8b2c33..9e63819c 100644 --- a/include/sqlpp11/vendor/select_flag_list.h +++ b/include/sqlpp11/vendor/select_flag_list.h @@ -69,9 +69,21 @@ namespace sqlpp { 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()"); -#warning: Need to dispatch to actual add method to prevent error messages from being generated + + using ok = ::sqlpp::detail::all_t>; + + _add_flag_impl(flag, ok()); // dispatch to prevent compile messages after the static_assert + } + + private: + template + void _add_flag_impl(Flag flag, const std::true_type&) + { return static_cast(this)->_flag_list._dynamic_flags.emplace_back(flag); } + + template + void _add_flag_impl(Flag flag, const std::false_type&); }; const select_flag_list_t& _flag_list() const { return *this; } diff --git a/include/sqlpp11/vendor/where.h b/include/sqlpp11/vendor/where.h index b82f4e6e..1ec7622f 100644 --- a/include/sqlpp11/vendor/where.h +++ b/include/sqlpp11/vendor/where.h @@ -72,9 +72,21 @@ namespace sqlpp { 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()"); -#warning: Need to dispatch to actual add method to prevent error messages from being generated + + using ok = ::sqlpp::detail::all_t>; + + _add_where_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert + } + + private: + template + void _add_where_impl(Expression expression, const std::true_type&) + { return static_cast(this)->_where._dynamic_expressions.emplace_back(expression); } + + template + void _add_where_impl(Expression expression, const std::false_type&); }; _parameter_tuple_t _expressions; From 7f94002bec9d90c2dd85815f3bc77eabf1814848 Mon Sep 17 00:00:00 2001 From: rbock Date: Thu, 10 Apr 2014 18:59:05 +0200 Subject: [PATCH 58/74] Migrated remove to use inherited methods --- include/sqlpp11/detail/logic.h | 2 +- include/sqlpp11/remove.h | 152 ++++++++++++++------------------- include/sqlpp11/vendor/using.h | 55 ++++++++++-- 3 files changed, 112 insertions(+), 97 deletions(-) diff --git a/include/sqlpp11/detail/logic.h b/include/sqlpp11/detail/logic.h index a533a4ee..9fb26cb9 100644 --- a/include/sqlpp11/detail/logic.h +++ b/include/sqlpp11/detail/logic.h @@ -69,7 +69,7 @@ namespace sqlpp template struct any_impl { - using type = typename all_impl::type; + using type = typename any_impl::type; }; template diff --git a/include/sqlpp11/remove.h b/include/sqlpp11/remove.h index 04db6eb0..3d07eb1f 100644 --- a/include/sqlpp11/remove.h +++ b/include/sqlpp11/remove.h @@ -39,37 +39,60 @@ namespace sqlpp { + template + struct remove_t; + namespace detail { - template - struct check_remove_t + template + struct remove_policies_t { - static_assert(is_where_t::value, "cannot run remove without having a where condition, use .where(true) to remove all rows"); - static constexpr bool value = true; + using _database_t = Db; + using _table_t = Table; + using _using_t = Using; + using _where_t = Where; + + using _statement_t = remove_t; + + struct _methods_t: + public _using_t::template _methods_t, + public _where_t::template _methods_t + {}; + + template + struct _policies_update_impl + { + using type = remove_t...>; + }; + + template + using _policies_update_t = typename _policies_update_impl::type; + }; } // REMOVE - template - struct remove_t + struct remove_t: + public detail::remove_policies_t::_methods_t { - using _database_t = Database; - using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; + using _policies_t = typename detail::remove_policies_t; + 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 _where_t = typename _policies_t::_where_t; - template - struct _policies_update_impl - { - using type = remove_t...>; - }; + using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - template - using _policies_update_t = typename _policies_update_impl::type; - - using _parameter_tuple_t = std::tuple; + using _parameter_tuple_t = std::tuple; using _parameter_list_t = typename make_parameter_list_t::type; // Constructors @@ -78,9 +101,9 @@ namespace sqlpp template remove_t(Statement s, T t): - _table(detail::arg_selector
::_(s._table, t)), - _using(detail::arg_selector::_(s._using, t)), - _where(detail::arg_selector::_(s._where, t)) + _table(detail::arg_selector<_table_t>::_(s._table, t)), + _using(detail::arg_selector<_using_t>::_(s._using, t)), + _where(detail::arg_selector<_where_t>::_(s._where, t)) {} remove_t(const remove_t&) = default; @@ -89,58 +112,6 @@ namespace sqlpp remove_t& operator=(remove_t&&) = default; ~remove_t() = default; - // type update functions - template - 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...} }; - } - - template - 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...} }; - } - - 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_using(Args... args) - { - static_assert(is_using_t::value, "cannot call add_using() before dynamic_using()"); - static_assert(is_dynamic_t::value, "cannot call add_using() before dynamic_using()"); - return _using.add_using(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() { @@ -152,25 +123,25 @@ namespace sqlpp return _parameter_list_t::size::value; } - template - std::size_t _run(Db& db) const + template + std::size_t _run(Database& db) const { static_assert(_get_static_no_of_parameters() == 0, "cannot run remove directly with parameters, use prepare instead"); - //static_assert(detail::check_remove_t::value, "Cannot run this remove expression"); + static_assert(is_where_t<_where_t>::value, "cannot run remove without having a where condition, use .where(true) to remove all rows"); return db.remove(*this); } - template - auto _prepare(Db& db) const - -> prepared_remove_t + template + auto _prepare(Database& db) const + -> prepared_remove_t { - //static_assert(detail::check_remove_t::value, "Cannot run this remove expression"); + static_assert(is_where_t<_where_t>::value, "cannot run remove without having a where condition, use .where(true) to remove all rows"); return {{}, db.prepare_remove(*this)}; } - Table _table; - Using _using; - Where _where; + _table_t _table; + _using_t _using; + _where_t _where; }; namespace vendor @@ -191,18 +162,21 @@ namespace sqlpp }; } + template + using make_remove_t = typename detail::remove_policies_t::_statement_t; + template constexpr auto remove_from(Table table) - -> remove_t> + -> make_remove_t> { - return { remove_t(), vendor::single_table_t{table} }; + return { make_remove_t(), vendor::single_table_t{table} }; } template constexpr auto dynamic_remove_from(const Database&, Table table) - -> remove_t> + -> make_remove_t> { - return { remove_t(), vendor::single_table_t{table} }; + return { make_remove_t(), vendor::single_table_t{table} }; } } diff --git a/include/sqlpp11/vendor/using.h b/include/sqlpp11/vendor/using.h index a52a479a..1a73bf6a 100644 --- a/include/sqlpp11/vendor/using.h +++ b/include/sqlpp11/vendor/using.h @@ -61,14 +61,31 @@ namespace sqlpp using_t& operator=(using_t&&) = default; ~using_t() = default; - - template - void add_using(Table table) + template + struct _methods_t { - static_assert(_is_dynamic::value, "add_using can only be called for dynamic_using"); - static_assert(is_table_t
::value, "using() arguments require to be tables"); - _dynamic_tables.emplace_back(table); - } + template + void add_using(Table table) + { + static_assert(_is_dynamic::value, "add_using must not be called for static using()"); + static_assert(is_table_t
::value, "invalid table argument in add_using()"); + + using ok = ::sqlpp::detail::all_t>; + + _add_using_impl(table, ok()); // dispatch to prevent compile messages after the static_assert + } + + private: + template + void _add_using_impl(Table table, const std::true_type&) + { + return static_cast(this)->_using._dynamic_tables.emplace_back(table); + } + + template + void _add_using_impl(Table table, const std::false_type&); + }; + _parameter_tuple_t _tables; vendor::interpretable_list_t _dynamic_tables; @@ -77,6 +94,30 @@ namespace sqlpp struct no_using_t { using _is_noop = std::true_type; + using _table_set = ::sqlpp::detail::type_set<>; + + template + struct _methods_t + { + using _database_t = typename Policies::_database_t; + template + using _new_select_t = typename Policies::template _policies_update_t; + + template + auto using_(Args... args) + -> _new_select_t> + { + return { *static_cast(this), using_t{args...} }; + } + + template + auto dynamic_using(Args... args) + -> _new_select_t> + { + static_assert(not std::is_same<_database_t, void>::value, "dynamic_using must not be called in a static statement"); + return { *static_cast(this), vendor::using_t<_database_t, Args...>{args...} }; + } + }; }; // Interpreters From d2b59c0f59d9b7534b22e195dfb4d6a2043079be Mon Sep 17 00:00:00 2001 From: rbock Date: Thu, 10 Apr 2014 20:20:59 +0200 Subject: [PATCH 59/74] Some cleanup --- include/sqlpp11/insert.h | 12 ++++++------ include/sqlpp11/remove.h | 4 ++-- include/sqlpp11/select.h | 4 ++-- include/sqlpp11/update.h | 12 ++++++------ include/sqlpp11/vendor/from.h | 6 +++--- include/sqlpp11/vendor/group_by.h | 6 +++--- include/sqlpp11/vendor/having.h | 6 +++--- include/sqlpp11/vendor/limit.h | 6 +++--- include/sqlpp11/vendor/offset.h | 6 +++--- include/sqlpp11/vendor/order_by.h | 6 +++--- include/sqlpp11/vendor/select_column_list.h | 6 +++--- include/sqlpp11/vendor/select_flag_list.h | 6 +++--- include/sqlpp11/vendor/using.h | 6 +++--- include/sqlpp11/vendor/where.h | 6 +++--- 14 files changed, 46 insertions(+), 46 deletions(-) diff --git a/include/sqlpp11/insert.h b/include/sqlpp11/insert.h index 04d92218..4fa4f6f3 100644 --- a/include/sqlpp11/insert.h +++ b/include/sqlpp11/insert.h @@ -53,13 +53,13 @@ namespace sqlpp using _table_set = typename Table::_table_set; template - struct _policies_update_impl + struct _policies_update_t { using type = insert_t...>; }; template - using _policies_update_t = typename _policies_update_impl::type; + using _new_statement_t = typename _policies_update_t::type; using _parameter_tuple_t = std::tuple; using _parameter_list_t = typename make_parameter_list_t::type; @@ -82,7 +82,7 @@ namespace sqlpp // type update functions auto default_values() - -> _policies_update_t + -> _new_statement_t { static_assert(is_noop_t::value, "cannot combine default_values() with other methods"); return { *this, vendor::insert_default_values_t{} }; @@ -90,7 +90,7 @@ namespace sqlpp template auto columns(Args... args) - -> _policies_update_t> + -> _new_statement_t> { static_assert(is_noop_t::value, "cannot combine columns() with other methods"); return { *this, vendor::column_list_t{args...} }; @@ -98,7 +98,7 @@ namespace sqlpp template auto set(Args... args) - -> _policies_update_t> + -> _new_statement_t> { static_assert(is_noop_t::value, "cannot combine set() with other methods"); return { *this, vendor::insert_list_t{args...} }; @@ -106,7 +106,7 @@ namespace sqlpp template auto dynamic_set(Args... args) - -> _policies_update_t> + -> _new_statement_t> { 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"); diff --git a/include/sqlpp11/remove.h b/include/sqlpp11/remove.h index 3d07eb1f..860af2f1 100644 --- a/include/sqlpp11/remove.h +++ b/include/sqlpp11/remove.h @@ -66,13 +66,13 @@ namespace sqlpp {}; template - struct _policies_update_impl + struct _policies_update_t { using type = remove_t...>; }; template - using _policies_update_t = typename _policies_update_impl::type; + using _new_statement_t = typename _policies_update_t::type; }; } diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index d1d194a5..851fd263 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -97,14 +97,14 @@ namespace sqlpp {}; template - struct _policies_update_impl + struct _policies_update_t { static_assert(detail::is_element_of>::value, "policies update for non-policy class detected"); using type = select_t...>; }; template - using _policies_update_t = typename _policies_update_impl::type; + using _new_statement_t = typename _policies_update_t::type; static_assert(is_noop_t::value or sqlpp::is_select_column_list_t::value, "column list of select is neither naught nor a valid column list"); static_assert(is_noop_t::value or sqlpp::is_from_t::value, "from() part of select is neither naught nor a valid from()"); diff --git a/include/sqlpp11/update.h b/include/sqlpp11/update.h index cf0f91b1..32e8f040 100644 --- a/include/sqlpp11/update.h +++ b/include/sqlpp11/update.h @@ -65,13 +65,13 @@ namespace sqlpp using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; template - struct _policies_update_impl + struct _policies_update_t { using type = update_t...>; }; template - using _policies_update_t = typename _policies_update_impl::type; + using _new_statement_t = typename _policies_update_t::type; using _parameter_tuple_t = std::tuple; using _parameter_list_t = typename make_parameter_list_t::type; @@ -96,7 +96,7 @@ namespace sqlpp // type update functions template auto set(Args... args) - -> _policies_update_t> + -> _new_statement_t> { static_assert(is_noop_t::value, "cannot call set()/dynamic_set() twice"); return { *this, vendor::update_list_t{args...} }; @@ -104,7 +104,7 @@ namespace sqlpp template auto dynamic_set(Args... args) - -> _policies_update_t> + -> _new_statement_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"); @@ -113,7 +113,7 @@ namespace sqlpp template auto where(Args... args) - -> _policies_update_t> + -> _new_statement_t> { static_assert(is_noop_t::value, "cannot call where()/dynamic_where() twice"); return { *this, vendor::where_t{args...} }; @@ -121,7 +121,7 @@ namespace sqlpp template auto dynamic_where(Args... args) - -> _policies_update_t> + -> _new_statement_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"); diff --git a/include/sqlpp11/vendor/from.h b/include/sqlpp11/vendor/from.h index 99bb15dd..6949cfee 100644 --- a/include/sqlpp11/vendor/from.h +++ b/include/sqlpp11/vendor/from.h @@ -103,18 +103,18 @@ namespace sqlpp { using _database_t = typename Policies::_database_t; template - using _new_select_t = typename Policies::template _policies_update_t; + using _new_statement_t = typename Policies::template _new_statement_t; template auto from(Args... args) - -> _new_select_t> + -> _new_statement_t> { return { *static_cast(this), from_t{args...} }; } template auto dynamic_from(Args... args) - -> _new_select_t> + -> _new_statement_t> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_from must not be called in a static statement"); return { *static_cast(this), vendor::from_t<_database_t, Args...>{args...} }; diff --git a/include/sqlpp11/vendor/group_by.h b/include/sqlpp11/vendor/group_by.h index ceb78c22..f81d6644 100644 --- a/include/sqlpp11/vendor/group_by.h +++ b/include/sqlpp11/vendor/group_by.h @@ -105,18 +105,18 @@ namespace sqlpp { using _database_t = typename Policies::_database_t; template - using _new_select_t = typename Policies::template _policies_update_t; + using _new_statement_t = typename Policies::template _new_statement_t; template auto group_by(Args... args) - -> _new_select_t> + -> _new_statement_t> { return { *static_cast(this), group_by_t{args...} }; } template auto dynamic_group_by(Args... args) - -> _new_select_t> + -> _new_statement_t> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_group_by must not be called in a static statement"); return { *static_cast(this), vendor::group_by_t<_database_t, Args...>{args...} }; diff --git a/include/sqlpp11/vendor/having.h b/include/sqlpp11/vendor/having.h index b88c60d0..f76e0142 100644 --- a/include/sqlpp11/vendor/having.h +++ b/include/sqlpp11/vendor/having.h @@ -102,18 +102,18 @@ namespace sqlpp { using _database_t = typename Policies::_database_t; template - using _new_select_t = typename Policies::template _policies_update_t; + using _new_statement_t = typename Policies::template _new_statement_t; template auto having(Args... args) - -> _new_select_t> + -> _new_statement_t> { return { *static_cast(this), having_t{args...} }; } template auto dynamic_having(Args... args) - -> _new_select_t> + -> _new_statement_t> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_having must not be called in a static statement"); return { *static_cast(this), vendor::having_t<_database_t, Args...>{args...} }; diff --git a/include/sqlpp11/vendor/limit.h b/include/sqlpp11/vendor/limit.h index 47cea9f9..e0c1216f 100644 --- a/include/sqlpp11/vendor/limit.h +++ b/include/sqlpp11/vendor/limit.h @@ -113,17 +113,17 @@ namespace sqlpp { using _database_t = typename Policies::_database_t; template - using _new_select_t = typename Policies::template _policies_update_t; + using _new_statement_t = typename Policies::template _new_statement_t; template auto limit(Arg arg) - -> _new_select_t::type>> + -> _new_statement_t::type>> { return { *static_cast(this), limit_t::type>{{arg}} }; } auto dynamic_limit() - -> _new_select_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_t<_database_t>{} }; diff --git a/include/sqlpp11/vendor/offset.h b/include/sqlpp11/vendor/offset.h index 0568ef9d..647bd99b 100644 --- a/include/sqlpp11/vendor/offset.h +++ b/include/sqlpp11/vendor/offset.h @@ -112,17 +112,17 @@ namespace sqlpp { using _database_t = typename Policies::_database_t; template - using _new_select_t = typename Policies::template _policies_update_t; + using _new_statement_t = typename Policies::template _new_statement_t; template auto offset(Arg arg) - -> _new_select_t::type>> + -> _new_statement_t::type>> { return { *static_cast(this), offset_t::type>{{arg}} }; } auto dynamic_offset() - -> _new_select_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_t<_database_t>{} }; diff --git a/include/sqlpp11/vendor/order_by.h b/include/sqlpp11/vendor/order_by.h index 41fdb5b0..246731cb 100644 --- a/include/sqlpp11/vendor/order_by.h +++ b/include/sqlpp11/vendor/order_by.h @@ -103,18 +103,18 @@ namespace sqlpp { using _database_t = typename Policies::_database_t; template - using _new_select_t = typename Policies::template _policies_update_t; + using _new_statement_t = typename Policies::template _new_statement_t; template auto order_by(Args... args) - -> _new_select_t> + -> _new_statement_t> { return { *static_cast(this), order_by_t{args...} }; } template auto dynamic_order_by(Args... args) - -> _new_select_t> + -> _new_statement_t> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_order_by must not be called in a static statement"); return { *static_cast(this), vendor::order_by_t<_database_t, Args...>{args...} }; diff --git a/include/sqlpp11/vendor/select_column_list.h b/include/sqlpp11/vendor/select_column_list.h index 34e7b9e5..6478799e 100644 --- a/include/sqlpp11/vendor/select_column_list.h +++ b/include/sqlpp11/vendor/select_column_list.h @@ -237,11 +237,11 @@ namespace sqlpp { using _database_t = typename Policies::_database_t; template - using _new_select_t = typename Policies::template _policies_update_t; + using _new_statement_t = typename Policies::template _new_statement_t; template auto columns(Args... args) - -> _new_select_t> + -> _new_statement_t> { #warning need to handle all_of_t here return { *static_cast(this), select_column_list_t{args...} }; @@ -249,7 +249,7 @@ namespace sqlpp template auto dynamic_columns(Args... args) - -> _new_select_t> + -> _new_statement_t> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_columns must not be called in a static statement"); return { *static_cast(this), vendor::select_column_list_t<_database_t, Args...>{args...} }; diff --git a/include/sqlpp11/vendor/select_flag_list.h b/include/sqlpp11/vendor/select_flag_list.h index 9e63819c..6ef9c94b 100644 --- a/include/sqlpp11/vendor/select_flag_list.h +++ b/include/sqlpp11/vendor/select_flag_list.h @@ -100,18 +100,18 @@ namespace sqlpp { using _database_t = typename Policies::_database_t; template - using _new_select_t = typename Policies::template _policies_update_t; + using _new_statement_t = typename Policies::template _new_statement_t; template auto flags(Args... args) - -> _new_select_t> + -> _new_statement_t> { return { *static_cast(this), select_flag_list_t{args...} }; } template auto dynamic_flags(Args... args) - -> _new_select_t> + -> _new_statement_t> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_flags must not be called in a static statement"); return { *static_cast(this), vendor::select_flag_list_t<_database_t, Args...>{args...} }; diff --git a/include/sqlpp11/vendor/using.h b/include/sqlpp11/vendor/using.h index 1a73bf6a..3942f64c 100644 --- a/include/sqlpp11/vendor/using.h +++ b/include/sqlpp11/vendor/using.h @@ -101,18 +101,18 @@ namespace sqlpp { using _database_t = typename Policies::_database_t; template - using _new_select_t = typename Policies::template _policies_update_t; + using _new_statement_t = typename Policies::template _new_statement_t; template auto using_(Args... args) - -> _new_select_t> + -> _new_statement_t> { return { *static_cast(this), using_t{args...} }; } template auto dynamic_using(Args... args) - -> _new_select_t> + -> _new_statement_t> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_using must not be called in a static statement"); return { *static_cast(this), vendor::using_t<_database_t, Args...>{args...} }; diff --git a/include/sqlpp11/vendor/where.h b/include/sqlpp11/vendor/where.h index 1ec7622f..b31996aa 100644 --- a/include/sqlpp11/vendor/where.h +++ b/include/sqlpp11/vendor/where.h @@ -128,18 +128,18 @@ namespace sqlpp { using _database_t = typename Policies::_database_t; template - using _new_select_t = typename Policies::template _policies_update_t; + using _new_statement_t = typename Policies::template _new_statement_t; template auto where(Args... args) - -> _new_select_t> + -> _new_statement_t> { return { *static_cast(this), where_t{args...} }; } template auto dynamic_where(Args... args) - -> _new_select_t> + -> _new_statement_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), vendor::where_t<_database_t, Args...>{args...} }; From 7e78c0d878839ae05ef717d23defd3085dee2748 Mon Sep 17 00:00:00 2001 From: rbock Date: Thu, 10 Apr 2014 21:20:37 +0200 Subject: [PATCH 60/74] Migrated update to inheritance model --- include/sqlpp11/detail/logic.h | 19 ++++ include/sqlpp11/remove.h | 1 - include/sqlpp11/update.h | 157 +++++++++++---------------- include/sqlpp11/vendor/update_list.h | 53 +++++++++ 4 files changed, 136 insertions(+), 94 deletions(-) diff --git a/include/sqlpp11/detail/logic.h b/include/sqlpp11/detail/logic.h index 9fb26cb9..57e335c9 100644 --- a/include/sqlpp11/detail/logic.h +++ b/include/sqlpp11/detail/logic.h @@ -81,6 +81,25 @@ namespace sqlpp template class Predicate, typename... T> using any_t = typename any_impl::value...>::type; + template + struct not_impl; + + template<> + struct not_impl + { + using type = std::false_type; + }; + + template<> + struct not_impl + { + using type = std::true_type; + }; + + + template class Predicate, typename... T> + using not_t = typename not_impl::value...>::type; + template using identity_t = T; diff --git a/include/sqlpp11/remove.h b/include/sqlpp11/remove.h index 860af2f1..06575373 100644 --- a/include/sqlpp11/remove.h +++ b/include/sqlpp11/remove.h @@ -73,7 +73,6 @@ namespace sqlpp template using _new_statement_t = typename _policies_update_t::type; - }; } diff --git a/include/sqlpp11/update.h b/include/sqlpp11/update.h index 32e8f040..94353edd 100644 --- a/include/sqlpp11/update.h +++ b/include/sqlpp11/update.h @@ -39,52 +39,72 @@ namespace sqlpp { + template + struct update_t; + namespace detail { - template< - typename Table, - typename UpdateList, - typename Where - > - struct check_update_t - { - static constexpr bool value = true; - }; - } - - template - struct update_t + typename Where = vendor::no_where_t + > + struct update_policies_t + { + using _database_t = Db; + using _table_t = Table; + using _update_list_t = UpdateList; + using _where_t = Where; + + using _statement_t = update_t; + + struct _methods_t: + public _update_list_t::template _methods_t, + public _where_t::template _methods_t + {}; + + template + struct _policies_update_t + { + using type = update_t...>; + }; + + template + using _new_statement_t = typename _policies_update_t::type; + }; + } + + template + struct update_t: + public detail::update_policies_t::_methods_t { - static_assert(::sqlpp::detail::is_superset_of::value, "updated columns do not match the table"); - static_assert(::sqlpp::detail::is_superset_of::value, "where condition does not match updated table"); + using _policies_t = typename detail::update_policies_t; + using _database_t = typename _policies_t::_database_t; + using _table_t = typename _policies_t::_table_t; + using _update_list_t = typename _policies_t::_update_list_t; + using _where_t = typename _policies_t::_where_t; - using _database_t = Database; - using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; + using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - template - struct _policies_update_t - { - using type = update_t...>; - }; - - template - using _new_statement_t = typename _policies_update_t::type; - - using _parameter_tuple_t = std::tuple; + using _parameter_tuple_t = std::tuple; using _parameter_list_t = typename make_parameter_list_t::type; + static_assert(::sqlpp::detail::is_superset_of::value, "updated columns do not match the table"); + static_assert(::sqlpp::detail::is_superset_of::value, "where condition does not match updated table"); + // Constructors update_t() {} template update_t(Statement s, T t): - _table(detail::arg_selector
::_(s._table, t)), - _update_list(detail::arg_selector::_(s._update_list, t)), - _where(detail::arg_selector::_(s._where, t)) + _table(detail::arg_selector<_table_t>::_(s._table, t)), + _update_list(detail::arg_selector<_update_list_t>::_(s._update_list, t)), + _where(detail::arg_selector<_where_t>::_(s._where, t)) {} update_t(const update_t&) = default; @@ -93,58 +113,6 @@ namespace sqlpp update_t& operator=(update_t&&) = default; ~update_t() = default; - // type update functions - template - auto set(Args... args) - -> _new_statement_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) - -> _new_statement_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) - -> _new_statement_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) - -> _new_statement_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() { @@ -156,23 +124,23 @@ namespace sqlpp return _parameter_list_t::size::value; } - template - std::size_t _run(Db& db) const + template + std::size_t _run(Database& db) const { static_assert(_get_static_no_of_parameters() == 0, "cannot run update directly with parameters, use prepare instead"); return db.update(*this); } - template - auto _prepare(Db& db) const - -> prepared_update_t + template + auto _prepare(Database& db) const + -> prepared_update_t { return {{}, db.prepare_update(*this)}; } - Table _table; - UpdateList _update_list; - Where _where; + _table_t _table; + _update_list_t _update_list; + _where_t _where; }; namespace vendor @@ -193,16 +161,19 @@ namespace sqlpp }; } + template + using make_update_t = typename detail::update_policies_t::_statement_t; + template constexpr auto update(Table table) - -> update_t> + -> make_update_t> { return { update_t(), vendor::single_table_t{table} }; } template constexpr auto dynamic_update(const Database&, Table table) - -> update_t> + -> make_update_t> { return { update_t(), vendor::single_table_t{table} }; } diff --git a/include/sqlpp11/vendor/update_list.h b/include/sqlpp11/vendor/update_list.h index 1fa1bdd0..9cd560d9 100644 --- a/include/sqlpp11/vendor/update_list.h +++ b/include/sqlpp11/vendor/update_list.h @@ -76,6 +76,36 @@ namespace sqlpp _dynamic_assignments.emplace_back(assignment); } + template + struct _methods_t + { + 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"); + + using ok = ::sqlpp::detail::all_t, + sqlpp::detail::not_t>; + + _add_set_impl(assignment, ok()); // dispatch to prevent compile messages after the static_assert + } + + private: + template + void _add_set_impl(Assignment assignment, const std::true_type&) + { + return static_cast(this)->_update_list._dynamic_assignments.emplace_back(assignment); + } + + template + void _add_set_impl(Assignment assignment, const std::false_type&); + }; + + _parameter_tuple_t _assignments; typename vendor::interpretable_list_t _dynamic_assignments; }; @@ -84,6 +114,29 @@ namespace sqlpp { using _is_noop = std::true_type; using _table_set = ::sqlpp::detail::type_set<>; + + template + struct _methods_t + { + using _database_t = typename Policies::_database_t; + template + using _new_statement_t = typename Policies::template _new_statement_t; + + template + auto set(Args... args) + -> _new_statement_t> + { + return { *static_cast(this), update_list_t{args...} }; + } + + template + auto dynamic_set(Args... args) + -> _new_statement_t> + { + static_assert(not std::is_same<_database_t, void>::value, "dynamic_set must not be called in a static statement"); + return { *static_cast(this), vendor::update_list_t<_database_t, Args...>{args...} }; + } + }; }; // Interpreters From abb80e3a91f9e0a93fe85418da74a471abcc081f Mon Sep 17 00:00:00 2001 From: rbock Date: Thu, 10 Apr 2014 22:44:38 +0200 Subject: [PATCH 61/74] Migrated insert to inheritance model --- include/sqlpp11/insert.h | 146 +++++++++------------ include/sqlpp11/vendor/insert_value_list.h | 124 ++++++++++++++--- 2 files changed, 170 insertions(+), 100 deletions(-) diff --git a/include/sqlpp11/insert.h b/include/sqlpp11/insert.h index 4fa4f6f3..910a7acb 100644 --- a/include/sqlpp11/insert.h +++ b/include/sqlpp11/insert.h @@ -39,39 +39,69 @@ namespace sqlpp { - // INSERT - template - struct insert_t + struct insert_t; + + namespace detail + { + template + struct insert_policies_t + { + using _database_t = Db; + using _table_t = Table; + using _insert_value_list_t = InsertValueList; + + using _statement_t = insert_t; + + struct _methods_t: + public _insert_value_list_t::template _methods_t + {}; + + template + struct _policies_insert_t + { + using type = insert_t...>; + }; + + template + using _new_statement_t = typename _policies_insert_t::type; + + using _table_set = typename _table_t::_table_set; + }; + } + + // INSERT + template + struct insert_t: + public detail::insert_policies_t::_methods_t { - static_assert(::sqlpp::detail::is_superset_of::value, "columns do not match the table they are to be inserted into"); + using _policies_t = typename detail::insert_policies_t; + using _database_t = typename _policies_t::_database_t; + using _table_t = typename _policies_t::_table_t; + using _insert_value_list_t = typename _policies_t::_insert_value_list_t; - 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; + using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; - template - struct _policies_update_t - { - using type = insert_t...>; - }; - - template - using _new_statement_t = typename _policies_update_t::type; - - using _parameter_tuple_t = std::tuple; + using _parameter_tuple_t = std::tuple; using _parameter_list_t = typename make_parameter_list_t::type; + static_assert(::sqlpp::detail::is_superset_of::value, "columns do not match the table they are to be inserted into"); + // Constructors insert_t() {} template insert_t(Statement s, T t): - _table(detail::arg_selector
::_(s._table, t)), - _insert_value_list(detail::arg_selector::_(s._insert_value_list, t)) + _table(detail::arg_selector<_table_t>::_(s._table, t)), + _insert_value_list(detail::arg_selector<_insert_value_list_t>::_(s._insert_value_list, t)) {} insert_t(const insert_t&) = default; @@ -80,55 +110,6 @@ namespace sqlpp insert_t& operator=(insert_t&&) = default; ~insert_t() = default; - // type update functions - auto default_values() - -> _new_statement_t - { - static_assert(is_noop_t::value, "cannot combine default_values() with other methods"); - return { *this, vendor::insert_default_values_t{} }; - } - - template - auto columns(Args... args) - -> _new_statement_t> - { - static_assert(is_noop_t::value, "cannot combine columns() with other methods"); - return { *this, vendor::column_list_t{args...} }; - } - - template - auto set(Args... args) - -> _new_statement_t> - { - static_assert(is_noop_t::value, "cannot combine set() with other methods"); - return { *this, vendor::insert_list_t{args...} }; - } - - template - auto dynamic_set(Args... args) - -> _new_statement_t> - { - 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...} }; - } - - // value adding methods - template - void add_set(Args... args) - { - static_assert(is_insert_list_t::value, "cannot call add_set() before dynamic_set()"); - static_assert(is_dynamic_t::value, "cannot call add_set() before dynamic_set()"); - return _insert_value_list.add_set(*this, args...); - } - - template - void add_values(Args... args) - { - static_assert(is_column_list_t::value, "cannot call add_values() before columns()"); - return _insert_value_list.add_values(args...); - } - // run and prepare static constexpr size_t _get_static_no_of_parameters() { @@ -140,22 +121,22 @@ namespace sqlpp return _parameter_list_t::size::value; } - template - std::size_t _run(Db& db) const + template + std::size_t _run(Database& db) const { static_assert(_get_static_no_of_parameters() == 0, "cannot run insert directly with parameters, use prepare instead"); return db.insert(*this); } - template - auto _prepare(Db& db) const - -> prepared_insert_t + template + auto _prepare(Database& db) const + -> prepared_insert_t { return {{}, db.prepare_insert(*this)}; } - InsertValueList _insert_value_list; - Table _table; + _insert_value_list_t _insert_value_list; + _table_t _table; }; namespace vendor @@ -175,18 +156,21 @@ namespace sqlpp }; } + template + using make_insert_t = typename detail::insert_policies_t::_statement_t; + template constexpr auto insert_into(Table table) - -> insert_t> + -> make_insert_t> { - return { insert_t(), vendor::single_table_t{table} }; + return { make_insert_t(), vendor::single_table_t{table} }; } template constexpr auto dynamic_insert_into(const Database&, Table table) - -> insert_t> + -> make_insert_t> { - return { insert_t(), vendor::single_table_t{table} }; + return { make_insert_t(), vendor::single_table_t{table} }; } } diff --git a/include/sqlpp11/vendor/insert_value_list.h b/include/sqlpp11/vendor/insert_value_list.h index 39dadc11..dd77859a 100644 --- a/include/sqlpp11/vendor/insert_value_list.h +++ b/include/sqlpp11/vendor/insert_value_list.h @@ -44,6 +44,10 @@ namespace sqlpp { using _table_set = ::sqlpp::detail::type_set<>; using _is_dynamic = std::false_type; + + template + struct _methods_t + {}; }; template @@ -96,6 +100,43 @@ namespace sqlpp _dynamic_values.emplace_back(assignment._rhs); } + template + struct _methods_t + { + 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, "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(::sqlpp::detail::is_subset_of<_value_table_set, typename Policies::_table_set>::value, "add_set() contains a column from a foreign table"); + static_assert(::sqlpp::detail::is_subset_of<_column_table_set, typename Policies::_table_set>::value, "add_set() contains a value from a foreign table"); + + using ok = ::sqlpp::detail::all_t, + ::sqlpp::detail::not_t, + ::sqlpp::detail::is_subset_of<_value_table_set, typename Policies::_table_set>, + ::sqlpp::detail::is_subset_of<_column_table_set, typename Policies::_table_set>>; + + _add_set_impl(assignment, ok()); // dispatch to prevent compile messages after the static_assert + } + + private: + template + void _add_set_impl(Assignment assignment, const std::true_type&) + { + static_cast(this)->_insert_value_list._dynamic_columns.emplace_back(simple_column_t{assignment._lhs}); + static_cast(this)->_insert_value_list._dynamic_values.emplace_back(assignment._rhs); + } + + template + void _add_set_impl(Assignment assignment, const std::false_type&); + }; + + std::tuple...> _columns; std::tuple _values; @@ -133,15 +174,34 @@ namespace sqlpp column_list_t& operator=(column_list_t&&) = default; ~column_list_t() = default; - template - void add_values(Assignments... assignments) - { - static_assert(::sqlpp::detail::all_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 - } + template + struct _methods_t + { + template + void add_values(Assignments... assignments) + { + static_assert(::sqlpp::detail::all_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"); + + using ok = ::sqlpp::detail::all_t, + _args_correct>; + + _add_values_impl(ok(), assignments...); // dispatch to prevent compile messages after the static_assert + } + + private: + template + void _add_values_impl(const std::true_type&, Assignments... assignments) + { + return static_cast(this)->_insert_value_list._insert_values.emplace_back(vendor::insert_value_t{assignments}...); + } + + template + void _add_values_impl(const std::false_type&, Assignments... assignments); + }; bool empty() const { @@ -151,22 +211,48 @@ 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 + struct _methods_t + { + using _database_t = typename Policies::_database_t; + template + using _new_statement_t = typename Policies::template _new_statement_t; + + auto default_values() + -> _new_statement_t + { + return { *static_cast(this), insert_default_values_t{} }; + } + + template + auto columns(Args... args) + -> _new_statement_t> + { + return { *static_cast(this), column_list_t{args...} }; + } + + template + auto set(Args... args) + -> _new_statement_t> + { + return { *static_cast(this), insert_list_t{args...} }; + } + + template + auto dynamic_set(Args... args) + -> _new_statement_t> + { + static_assert(not std::is_same<_database_t, void>::value, "dynamic_set must not be called in a static statement"); + return { *static_cast(this), vendor::insert_list_t<_database_t, Args...>{args...} }; + } + }; }; // Interpreters From 68f929e041250279d0d952171fa762c4f4870ba2 Mon Sep 17 00:00:00 2001 From: rbock Date: Fri, 11 Apr 2014 08:58:28 +0200 Subject: [PATCH 62/74] Removed a bunch of superfluous functions. Dispatching made some emplace_back instances obsolete. --- include/sqlpp11/vendor/insert_value_list.h | 13 ------------- include/sqlpp11/vendor/interpretable_list.h | 3 --- include/sqlpp11/vendor/select_column_list.h | 4 ---- include/sqlpp11/vendor/update_list.h | 8 -------- tests/SelectTest.cpp | 2 -- 5 files changed, 30 deletions(-) diff --git a/include/sqlpp11/vendor/insert_value_list.h b/include/sqlpp11/vendor/insert_value_list.h index dd77859a..550061ce 100644 --- a/include/sqlpp11/vendor/insert_value_list.h +++ b/include/sqlpp11/vendor/insert_value_list.h @@ -87,19 +87,6 @@ namespace sqlpp insert_list_t& operator=(insert_list_t&&) = default; ~insert_list_t() = default; - template - void add_set(const Insert&, Assignment assignment) - { - 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(::sqlpp::detail::is_subset_of<_value_table_set, typename Insert::_table_set>::value, "add_set() contains a column from a foreign table"); - static_assert(::sqlpp::detail::is_subset_of<_column_table_set, typename Insert::_table_set>::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); - } - template struct _methods_t { diff --git a/include/sqlpp11/vendor/interpretable_list.h b/include/sqlpp11/vendor/interpretable_list.h index 291b8123..a6b2d27e 100644 --- a/include/sqlpp11/vendor/interpretable_list.h +++ b/include/sqlpp11/vendor/interpretable_list.h @@ -60,9 +60,6 @@ namespace sqlpp template<> struct interpretable_list_t { - template - void emplace_back(const T&) {} - static constexpr std::size_t size() { return 0; diff --git a/include/sqlpp11/vendor/select_column_list.h b/include/sqlpp11/vendor/select_column_list.h index 6478799e..a44a586e 100644 --- a/include/sqlpp11/vendor/select_column_list.h +++ b/include/sqlpp11/vendor/select_column_list.h @@ -89,10 +89,6 @@ namespace sqlpp }; _names_t _dynamic_expression_names; -#warning: Put an assert here or remove implementation to make sure this never aktually gets called - template - void emplace_back(const T&) {} - static constexpr bool empty() { return true; diff --git a/include/sqlpp11/vendor/update_list.h b/include/sqlpp11/vendor/update_list.h index 9cd560d9..a670c422 100644 --- a/include/sqlpp11/vendor/update_list.h +++ b/include/sqlpp11/vendor/update_list.h @@ -68,14 +68,6 @@ namespace sqlpp update_list_t& operator=(update_list_t&&) = default; ~update_list_t() = default; - 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"); - _dynamic_assignments.emplace_back(assignment); - } - template struct _methods_t { diff --git a/tests/SelectTest.cpp b/tests/SelectTest.cpp index 8880da29..6dd02b46 100644 --- a/tests/SelectTest.cpp +++ b/tests/SelectTest.cpp @@ -49,7 +49,6 @@ int main() test::TabFoo f; test::TabBar t; - /* for (const auto& row : db(select(all_of(t)).from(t).where(true))) { int64_t a = row.alpha; @@ -68,7 +67,6 @@ int main() const std::string b = row.tabBar.beta; const bool g = row.gamma; } - */ auto s = dynamic_select(db).dynamic_columns(t.alpha).dynamic_flags().dynamic_from(t).dynamic_where().dynamic_group_by(t.alpha).dynamic_order_by().dynamic_having(t.gamma).dynamic_limit().dynamic_offset(); s.add_flag(sqlpp::distinct); From 207310effeb5103630c3d2760928d4de1990802f Mon Sep 17 00:00:00 2001 From: rbock Date: Fri, 11 Apr 2014 18:23:20 +0200 Subject: [PATCH 63/74] Added parameter lists to group_by and order_by --- include/sqlpp11/vendor/group_by.h | 3 ++- include/sqlpp11/vendor/order_by.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/sqlpp11/vendor/group_by.h b/include/sqlpp11/vendor/group_by.h index f81d6644..d6a88c39 100644 --- a/include/sqlpp11/vendor/group_by.h +++ b/include/sqlpp11/vendor/group_by.h @@ -46,7 +46,8 @@ namespace sqlpp using _is_group_by = std::true_type; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; using _parameter_tuple_t = std::tuple; -#warning Has no parameter_list? + using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type; + using _table_set = typename ::sqlpp::detail::make_joined_set::type; static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression (e.g. a column) required in group_by()"); diff --git a/include/sqlpp11/vendor/order_by.h b/include/sqlpp11/vendor/order_by.h index 246731cb..b23330a6 100644 --- a/include/sqlpp11/vendor/order_by.h +++ b/include/sqlpp11/vendor/order_by.h @@ -45,6 +45,7 @@ namespace sqlpp using _is_order_by = std::true_type; using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; using _parameter_tuple_t = std::tuple; + using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type; using _table_set = typename ::sqlpp::detail::make_joined_set::type; From cffc85879a773ab033c945e65d1dfaefbf3e8afb Mon Sep 17 00:00:00 2001 From: rbock Date: Fri, 11 Apr 2014 21:12:39 +0200 Subject: [PATCH 64/74] Calculate the tables required by a sub-select --- include/sqlpp11/detail/type_set.h | 17 ++++++++++++++ include/sqlpp11/select.h | 26 ++++++++++----------- include/sqlpp11/select_flags.h | 3 +++ include/sqlpp11/vendor/select_column_list.h | 1 + include/sqlpp11/vendor/select_flag_list.h | 2 ++ 5 files changed, 36 insertions(+), 13 deletions(-) diff --git a/include/sqlpp11/detail/type_set.h b/include/sqlpp11/detail/type_set.h index 7c4d15b7..56ffce8a 100644 --- a/include/sqlpp11/detail/type_set.h +++ b/include/sqlpp11/detail/type_set.h @@ -197,6 +197,23 @@ namespace sqlpp template using make_joined_set_t = typename make_joined_set::type; + template + struct make_difference_set + { + static_assert(::sqlpp::vendor::wrong_t::value, "invalid argument for difference set"); + }; + + template + struct make_difference_set, type_set> + { + template + using is_subtrahend = is_element_of>; + using type = typename make_type_set_if_not::type; + }; + + template + using make_difference_set_t = typename make_difference_set::type; + } } diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 851fd263..239c5cf1 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -140,7 +140,18 @@ namespace sqlpp using _parameter_tuple_t = std::tuple; using _parameter_list_t = typename make_parameter_list_t::type; - using _table_set = ::sqlpp::detail::type_set<>; + using _table_set = detail::make_difference_set_t< + typename _from_t::_table_set, + detail::make_joined_set_t< + typename _flag_list_t::_table_set, + typename _column_list_t::_table_set, + typename _where_t::_table_set, + typename _group_by_t::_table_set, + typename _having_t::_table_set, + typename _order_by_t::_table_set, + typename _limit_t::_table_set, + typename _offset_t::_table_set + >>; template using _result_row_t = typename _column_list_t::template _result_row_t; @@ -210,18 +221,6 @@ namespace sqlpp return _column_list_t::static_size() + get_dynamic_names().size(); } - /* - static_assert(column_list::_table_set::template is_subset_t<_from_t::_table_set>::value - static_assert(detail::is_subset_of::value - subset_of_t sollte ein eigenes template sein, das macht so etwas wie obiges sicher einfacher lesbar - also: use any and all instead of and_t and or_t - */ - //static_assert(is_where_t::value, "cannot select select 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. template struct is_table_subset_of_from { @@ -244,6 +243,7 @@ namespace sqlpp 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(_get_static_no_of_parameters() == 0, "cannot run select directly with parameters, use prepare instead"); + return {db.select(*this), get_dynamic_names()}; } diff --git a/include/sqlpp11/select_flags.h b/include/sqlpp11/select_flags.h index 6b059f9b..e8ee53d5 100644 --- a/include/sqlpp11/select_flags.h +++ b/include/sqlpp11/select_flags.h @@ -41,6 +41,7 @@ namespace sqlpp { using _is_select_flag = std::true_type; }; + using _table_set = detail::type_set<>; }; static constexpr all_t all = {}; @@ -63,6 +64,7 @@ namespace sqlpp { using _is_select_flag = std::true_type; }; + using _table_set = detail::type_set<>; }; static constexpr distinct_t distinct = {}; @@ -85,6 +87,7 @@ namespace sqlpp { using _is_select_flag = std::true_type; }; + using _table_set = detail::type_set<>; }; static constexpr straight_join_t straight_join = {}; diff --git a/include/sqlpp11/vendor/select_column_list.h b/include/sqlpp11/vendor/select_column_list.h index a44a586e..7f38fad4 100644 --- a/include/sqlpp11/vendor/select_column_list.h +++ b/include/sqlpp11/vendor/select_column_list.h @@ -216,6 +216,7 @@ namespace sqlpp struct no_select_column_list_t { using _is_noop = std::true_type; + using _table_set = ::sqlpp::detail::type_set<>; template using _result_row_t = ::sqlpp::result_row_t; using _dynamic_names_t = typename dynamic_select_column_list::_names_t; diff --git a/include/sqlpp11/vendor/select_flag_list.h b/include/sqlpp11/vendor/select_flag_list.h index 6ef9c94b..80c0f850 100644 --- a/include/sqlpp11/vendor/select_flag_list.h +++ b/include/sqlpp11/vendor/select_flag_list.h @@ -46,6 +46,7 @@ namespace sqlpp using _is_dynamic = typename std::conditional::value, std::false_type, std::true_type>::type; using _parameter_tuple_t = std::tuple; using size = std::tuple_size<_parameter_tuple_t>; + using _table_set = typename ::sqlpp::detail::make_joined_set::type; static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in select flag list"); @@ -94,6 +95,7 @@ namespace sqlpp struct no_select_flag_list_t { using _is_noop = std::true_type; + using _table_set = ::sqlpp::detail::type_set<>; template struct _methods_t From bbae5e89e9a63c069225703e36e394afdf30d968 Mon Sep 17 00:00:00 2001 From: rbock Date: Sat, 12 Apr 2014 08:22:46 +0200 Subject: [PATCH 65/74] Improved decision whether a select is a value or not --- include/sqlpp11/select.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 239c5cf1..3331fdd0 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -109,9 +109,9 @@ namespace sqlpp static_assert(is_noop_t::value or sqlpp::is_select_column_list_t::value, "column list of select is neither naught nor a valid column list"); static_assert(is_noop_t::value or sqlpp::is_from_t::value, "from() part of select is neither naught nor a valid from()"); using _value_type = typename std::conditional< - sqlpp::is_from_t::value, + _column_list_t::_table_set::size::value ? sqlpp::is_from_t::value : true, 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) + no_value_t // If something is selected that requires a table, then we require a from for this to be a value >::type; }; } @@ -142,7 +142,7 @@ namespace sqlpp using _parameter_list_t = typename make_parameter_list_t::type; using _table_set = detail::make_difference_set_t< typename _from_t::_table_set, - detail::make_joined_set_t< + detail::make_joined_set_t< // Hint: extra_tables are not used here because they are just helpers for dynamic .add_*() methods typename _flag_list_t::_table_set, typename _column_list_t::_table_set, typename _where_t::_table_set, @@ -235,6 +235,7 @@ namespace sqlpp #warning: need to check in add_xy method as well #warning: need add_wxy_without_table_check #warning: might want to add an .extra_tables() method to say which tables might also be used here, say via dynamic_from or because this is a subselect + 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()"); @@ -242,6 +243,7 @@ namespace sqlpp 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()"); static_assert(_get_static_no_of_parameters() == 0, "cannot run select directly with parameters, use prepare instead"); return {db.select(*this), get_dynamic_names()}; From f4ec88c83da4fee07572dc5570030958561ea58c Mon Sep 17 00:00:00 2001 From: rbock Date: Fri, 18 Apr 2014 19:59:35 +0200 Subject: [PATCH 66/74] Improved checks for selects being usable as value or table --- include/sqlpp11/any.h | 4 +--- include/sqlpp11/no_value.h | 2 ++ include/sqlpp11/select.h | 44 ++++++++++++++++++++++++----------- include/sqlpp11/some.h | 6 ++--- include/sqlpp11/table_alias.h | 2 +- tests/FunctionTest.cpp | 6 +++-- tests/SelectTypeTest.cpp | 22 +++++++++++++++--- 7 files changed, 60 insertions(+), 26 deletions(-) diff --git a/include/sqlpp11/any.h b/include/sqlpp11/any.h index 94fb4cd7..1f8a55b5 100644 --- a/include/sqlpp11/any.h +++ b/include/sqlpp11/any.h @@ -37,9 +37,6 @@ namespace sqlpp template struct any_t { - static_assert(is_select_t::value, "any() requires a single column select expression as argument"); - struct _value_type: public Select::_value_type::_base_value_type { using _is_expression = std::false_type; @@ -94,6 +91,7 @@ namespace sqlpp auto any(T t) -> typename vendor::any_t> { static_assert(is_select_t>::value, "any() requires a select expression as argument"); + static_assert(is_value_t>::value, "any() requires a single column select expression as argument"); return { t }; } diff --git a/include/sqlpp11/no_value.h b/include/sqlpp11/no_value.h index cad3b6e9..2079c5d7 100644 --- a/include/sqlpp11/no_value.h +++ b/include/sqlpp11/no_value.h @@ -36,6 +36,8 @@ namespace sqlpp template using _constraint = std::false_type; + using _base_value_type = no_value_t; + template struct _is_valid_operand { diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 3331fdd0..d1052935 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -108,8 +108,36 @@ namespace sqlpp static_assert(is_noop_t::value or sqlpp::is_select_column_list_t::value, "column list of select is neither naught nor a valid column list"); static_assert(is_noop_t::value or sqlpp::is_from_t::value, "from() part of select is neither naught nor a valid from()"); + + using _required_tables = + detail::make_joined_set_t< + typename _flag_list_t::_table_set, + typename _column_list_t::_table_set, + typename _where_t::_table_set, + typename _group_by_t::_table_set, + typename _having_t::_table_set, + typename _order_by_t::_table_set, + typename _limit_t::_table_set, + typename _offset_t::_table_set + >; + + // The tables not covered by the from. + using _table_set = detail::make_difference_set_t< + _required_tables, + typename _from_t::_table_set // Hint: extra_tables are not used here because they are just helpers for dynamic .add_*() methods + >; + + // A select can be used as a pseudo table if + // - at least one column is selected + // - the select is complete (leaks no tables) + using _can_be_used_as_table = typename std::conditional< + is_select_column_list_t<_column_list_t>::value and _table_set::size::value == 0, + std::true_type, + std::false_type + >::type; + using _value_type = typename std::conditional< - _column_list_t::_table_set::size::value ? sqlpp::is_from_t::value : true, + is_select_column_list_t<_column_list_t>::value and is_subset_of::value, typename ColumnList::_value_type, no_value_t // If something is selected that requires a table, then we require a from for this to be a value >::type; @@ -140,18 +168,7 @@ namespace sqlpp using _parameter_tuple_t = std::tuple; using _parameter_list_t = typename make_parameter_list_t::type; - using _table_set = detail::make_difference_set_t< - typename _from_t::_table_set, - detail::make_joined_set_t< // Hint: extra_tables are not used here because they are just helpers for dynamic .add_*() methods - typename _flag_list_t::_table_set, - typename _column_list_t::_table_set, - typename _where_t::_table_set, - typename _group_by_t::_table_set, - typename _having_t::_table_set, - typename _order_by_t::_table_set, - typename _limit_t::_table_set, - typename _offset_t::_table_set - >>; + using _table_set = typename _policies_t::_table_set; template using _result_row_t = typename _column_list_t::template _result_row_t; @@ -197,6 +214,7 @@ namespace sqlpp template typename _pseudo_table_t::alias as(const AliasProvider& aliasProvider) const { + static_assert(_policies_t::_can_be_used_as_table::value, "select cannot be used as table, incomplete from()"); return typename _pseudo_table_t::table( *this).as(aliasProvider); } diff --git a/include/sqlpp11/some.h b/include/sqlpp11/some.h index e15683d9..cd5e63cc 100644 --- a/include/sqlpp11/some.h +++ b/include/sqlpp11/some.h @@ -37,9 +37,6 @@ namespace sqlpp template struct some_t { - static_assert(is_select_t::value, "some() requires a single column select expression as argument"); - struct _value_type: public Select::_value_type::_base_value_type { using _is_expression = std::false_type; @@ -93,7 +90,8 @@ namespace sqlpp template auto some(T t) -> typename vendor::some_t> { - static_assert(is_select_t>::value, "some() requires a select expression as argument"); + static_assert(is_select_t>::value, "some() requires a single column select expression as argument"); + static_assert(is_value_t>::value, "some() requires a single column select expression as argument"); return { t }; } diff --git a/include/sqlpp11/table_alias.h b/include/sqlpp11/table_alias.h index 2f51903a..273b2d90 100644 --- a/include/sqlpp11/table_alias.h +++ b/include/sqlpp11/table_alias.h @@ -42,7 +42,7 @@ namespace sqlpp { //FIXME: Need to add join functionality using _is_table = std::true_type; - using _table_set = detail::type_set; + using _table_set = detail::type_set; struct _value_type: Table::_value_type { diff --git a/tests/FunctionTest.cpp b/tests/FunctionTest.cpp index 3284daa7..04aa8f52 100644 --- a/tests/FunctionTest.cpp +++ b/tests/FunctionTest.cpp @@ -185,11 +185,13 @@ int main() static_assert(not sqlpp::is_text_t::value, "type requirement"); } + // Test any { + using TI = decltype(any(select(t.alpha).from(t))); using TT = decltype(any(select(t.beta).from(t))); - using TF = decltype(any(select(f.omega).from(t))); + using TF = decltype(any(select(f.omega).from(f))); static_assert(not sqlpp::is_named_expression_t::value, "type requirement"); static_assert(sqlpp::is_multi_expression_t::value, "type requirement"); static_assert(sqlpp::is_numeric_t::value, "type requirement"); @@ -212,7 +214,7 @@ int main() { using TI = decltype(some(select(t.alpha).from(t))); using TT = decltype(some(select(t.beta).from(t))); - using TF = decltype(some(select(f.omega).from(t))); + using TF = decltype(some(select(f.omega).from(f))); static_assert(not sqlpp::is_named_expression_t::value, "type requirement"); static_assert(sqlpp::is_multi_expression_t::value, "type requirement"); static_assert(sqlpp::is_numeric_t::value, "type requirement"); diff --git a/tests/SelectTypeTest.cpp b/tests/SelectTypeTest.cpp index bc224e87..e0a4af64 100644 --- a/tests/SelectTypeTest.cpp +++ b/tests/SelectTypeTest.cpp @@ -357,12 +357,27 @@ int main() static_assert(sqlpp::is_named_expression_t::value, "alpha should be a named expression"); static_assert(sqlpp::is_named_expression_t::value, "an alias of alpha should be a named expression"); static_assert(sqlpp::is_alias_t::value, "an alias of alpha should be an alias"); + auto z = select(t.alpha).from(t) == 7; auto l = t.as(alias::left); auto r = select(t.gamma.as(alias::a)).from(t).where(t.gamma == true).as(alias::right); + using R = decltype(r); static_assert(sqlpp::is_boolean_t::value, "select(bool) has to be a bool"); - serialize(sqlpp::select().flags(sqlpp::distinct, sqlpp::straight_join).columns(l.alpha, l.beta, select(r.a).from(r)) - .from(l, r) + auto s = select(r.a).from(r); + using RA = decltype(r.a); + using S = decltype(s); + using SCL = typename S::_column_list_t; + using SF = typename S::_from_t; + static_assert(sqlpp::is_select_column_list_t::value, "no column list"); + static_assert(sqlpp::is_from_t::value, "no from list"); + using SCL_T = typename SCL::_table_set; + using SF_T = typename SF::_table_set; + static_assert(SCL_T::size::value == 1, "unexpected table_set in column_list"); + static_assert(SF_T::size::value == 1, "unexpected table_set in from"); + static_assert(std::is_same::value, "should be the same"); + static_assert(sqlpp::is_boolean_t::value, "select(bool) has to be a bool"); + auto s1 = sqlpp::select().flags(sqlpp::distinct, sqlpp::straight_join).columns(l.alpha, l.beta, select(r.a).from(r)) + .from(r,t,l) .where(t.beta == "hello world" and select(t.gamma).from(t))// .as(alias::right)) .group_by(l.gamma, r.a) .having(r.a != true) @@ -370,7 +385,8 @@ int main() .limit(17) .offset(3) .as(alias::a) - , printer).str(); + ; + return 0; } From 815c061979b47362d7dffaba1a5c6d0fdff3e97c Mon Sep 17 00:00:00 2001 From: rbock Date: Mon, 21 Apr 2014 10:59:29 +0200 Subject: [PATCH 67/74] Added extra_tables to select. With this method you can indicate additional tables that might be added via add_from(). These tables are considered in the add_column, add where, etc methods. --- include/sqlpp11/select.h | 12 ++- include/sqlpp11/vendor/extra_tables.h | 114 ++++++++++++++++++++++++++ tests/SelectTest.cpp | 2 +- 3 files changed, 123 insertions(+), 5 deletions(-) create mode 100644 include/sqlpp11/vendor/extra_tables.h diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index d1052935..876acc3a 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -62,6 +63,7 @@ namespace sqlpp typename FlagList = vendor::no_select_flag_list_t, typename ColumnList = vendor::no_select_column_list_t, typename From = vendor::no_from_t, + typename ExtraTables = vendor::no_extra_tables_t, typename Where = vendor::no_where_t, typename GroupBy = vendor::no_group_by_t, typename Having = vendor::no_having_t, @@ -75,6 +77,7 @@ namespace sqlpp using _flag_list_t = FlagList; using _column_list_t = ColumnList; using _from_t = From; + using _extra_tables_t = ExtraTables; using _where_t = Where; using _group_by_t = GroupBy; using _having_t = Having; @@ -82,12 +85,13 @@ namespace sqlpp using _limit_t = Limit; using _offset_t = Offset; - using _statement_t = select_t; + using _statement_t = select_t; struct _methods_t: public _flag_list_t::template _methods_t, public _column_list_t::template _methods_t, public _from_t::template _methods_t, + public _extra_tables_t::template _methods_t, public _where_t::template _methods_t, public _group_by_t::template _methods_t, public _having_t::template _methods_t, @@ -104,7 +108,7 @@ namespace sqlpp }; template - using _new_statement_t = typename _policies_update_t::type; + using _new_statement_t = typename _policies_update_t::type; static_assert(is_noop_t::value or sqlpp::is_select_column_list_t::value, "column list of select is neither naught nor a valid column list"); static_assert(is_noop_t::value or sqlpp::is_from_t::value, "from() part of select is neither naught nor a valid from()"); @@ -124,7 +128,7 @@ namespace sqlpp // The tables not covered by the from. using _table_set = detail::make_difference_set_t< _required_tables, - typename _from_t::_table_set // Hint: extra_tables are not used here because they are just helpers for dynamic .add_*() methods + typename _from_t::_table_set // Hint: extra_tables_t is not used here because it is just a helper for dynamic .add_*() methods and should not change the structural integrity >; // A select can be used as a pseudo table if @@ -157,6 +161,7 @@ namespace sqlpp using _flag_list_t = typename _policies_t::_flag_list_t; using _column_list_t = typename _policies_t::_column_list_t; using _from_t = typename _policies_t::_from_t; + using _extra_tables_t = typename _policies_t::_extra_tables_t; using _where_t = typename _policies_t::_where_t; using _group_by_t = typename _policies_t::_group_by_t; using _having_t = typename _policies_t::_having_t; @@ -252,7 +257,6 @@ namespace sqlpp { #warning: need to check in add_xy method as well #warning: need add_wxy_without_table_check -#warning: might want to add an .extra_tables() method to say which tables might also be used here, say via dynamic_from or because this is a subselect 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()"); diff --git a/include/sqlpp11/vendor/extra_tables.h b/include/sqlpp11/vendor/extra_tables.h new file mode 100644 index 00000000..0b91ad7a --- /dev/null +++ b/include/sqlpp11/vendor/extra_tables.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2013-2014, 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_EXTRA_TABLES_H +#define SQLPP_EXTRA_TABLES_H + +#include +#include +#include + +namespace sqlpp +{ + namespace vendor + { + // EXTRA_TABLES + template + struct extra_tables_t + { + using _is_extra_tables = std::true_type; + + static_assert(sizeof...(Tables), "at least one table or join argument required in extra_tables()"); + + static_assert(not ::sqlpp::detail::has_duplicates::value, "at least one duplicate argument detected in extra_tables()"); + + static_assert(::sqlpp::detail::all_t::value, "at least one argument is not a table or join in extra_tables()"); + + using _table_set = ::sqlpp::detail::make_joined_set_t; + + + extra_tables_t() + {} + + extra_tables_t(const extra_tables_t&) = default; + extra_tables_t(extra_tables_t&&) = default; + extra_tables_t& operator=(const extra_tables_t&) = default; + extra_tables_t& operator=(extra_tables_t&&) = default; + ~extra_tables_t() = default; + + template + struct _methods_t + { + }; + }; + + struct no_extra_tables_t + { + using _is_noop = std::true_type; + using _table_set = ::sqlpp::detail::type_set<>; + + template + struct _methods_t + { + template + using _new_statement_t = typename Policies::template _new_statement_t; + + template + auto extra_tables(Args...) + -> _new_statement_t> + { + return { *static_cast(this), extra_tables_t{} }; + } + }; + }; + + // Interpreters + template + struct serializer_t> + { + using T = extra_tables_t; + + static Context& _(const T& t, Context& context) + { + return context; + } + }; + + template + struct serializer_t + { + using T = no_extra_tables_t; + + static Context& _(const T& t, Context& context) + { + return context; + } + }; + + } +} + +#endif diff --git a/tests/SelectTest.cpp b/tests/SelectTest.cpp index 6dd02b46..ae2edeb1 100644 --- a/tests/SelectTest.cpp +++ b/tests/SelectTest.cpp @@ -68,7 +68,7 @@ int main() const bool g = row.gamma; } - auto s = dynamic_select(db).dynamic_columns(t.alpha).dynamic_flags().dynamic_from(t).dynamic_where().dynamic_group_by(t.alpha).dynamic_order_by().dynamic_having(t.gamma).dynamic_limit().dynamic_offset(); + auto s = dynamic_select(db).dynamic_columns(t.alpha).dynamic_flags().dynamic_from(t).extra_tables(f,t).dynamic_where().dynamic_group_by(t.alpha).dynamic_order_by().dynamic_having(t.gamma).dynamic_limit().dynamic_offset(); s.add_flag(sqlpp::distinct); s.add_column(t.beta); s.add_from(f); From 1f3e611fdfb54edd5c993a76c356632c44081e03 Mon Sep 17 00:00:00 2001 From: rbock Date: Mon, 21 Apr 2014 11:49:26 +0200 Subject: [PATCH 68/74] Added table checks to add_column and added add_column_ntc --- include/sqlpp11/select.h | 5 +++++ include/sqlpp11/vendor/select_column_list.h | 7 +++++++ tests/InterpretTest.cpp | 6 +++--- tests/SelectTypeTest.cpp | 2 +- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 876acc3a..dc54621a 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -113,6 +113,11 @@ namespace sqlpp static_assert(is_noop_t::value or sqlpp::is_select_column_list_t::value, "column list of select is neither naught nor a valid column list"); static_assert(is_noop_t::value or sqlpp::is_from_t::value, "from() part of select is neither naught nor a valid from()"); + using _known_tables = detail::make_joined_set_t; + + template + using _no_unknown_tables = detail::is_subset_of; + using _required_tables = detail::make_joined_set_t< typename _flag_list_t::_table_set, diff --git a/include/sqlpp11/vendor/select_column_list.h b/include/sqlpp11/vendor/select_column_list.h index 7f38fad4..ebff2552 100644 --- a/include/sqlpp11/vendor/select_column_list.h +++ b/include/sqlpp11/vendor/select_column_list.h @@ -186,10 +186,17 @@ namespace sqlpp struct _methods_t { template + void add_column_ntc(NamedExpression namedExpression) + { + add_column(namedExpression); + } + + 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()"); using ok = ::sqlpp::detail::all_t>; diff --git a/tests/InterpretTest.cpp b/tests/InterpretTest.cpp index c931fb5a..2fd5c3a3 100644 --- a/tests/InterpretTest.cpp +++ b/tests/InterpretTest.cpp @@ -133,20 +133,20 @@ int main() // dynamic select { - auto s = dynamic_select(db).dynamic_flags().dynamic_columns(); + auto s = dynamic_select(db).dynamic_flags().dynamic_columns().from(t); s.add_column(t.beta); s.add_column(t.gamma); serialize(s, printer).str(); } { - auto s = dynamic_select(db).dynamic_flags().dynamic_columns(); + auto s = dynamic_select(db).dynamic_flags().dynamic_columns().from(t); s.add_flag(sqlpp::distinct); s.add_column(t.beta); s.add_column(t.gamma); serialize(s, printer).str(); } { - auto s = dynamic_select(db).dynamic_flags(sqlpp::distinct).dynamic_columns(t.alpha); + auto s = dynamic_select(db).dynamic_flags(sqlpp::distinct).dynamic_columns(t.alpha).extra_tables(t); // Would fail to run() s.add_flag(sqlpp::all); s.add_column(t.beta); s.add_column(t.gamma); diff --git a/tests/SelectTypeTest.cpp b/tests/SelectTypeTest.cpp index e0a4af64..12cf9c56 100644 --- a/tests/SelectTypeTest.cpp +++ b/tests/SelectTypeTest.cpp @@ -324,7 +324,7 @@ int main() // Test that select can be called with zero columns if it is used with dynamic columns. { - auto s = dynamic_select(db).dynamic_columns(); + auto s = dynamic_select(db).dynamic_columns().extra_tables(t); s.add_column(t.alpha); serialize(s, printer).str(); } From 0ffd93108b395f978dc32edbc371c1c00ceed47b Mon Sep 17 00:00:00 2001 From: rbock Date: Tue, 22 Apr 2014 20:46:32 +0200 Subject: [PATCH 69/74] 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); From 8f16ded277951e1c621524a77104202a91020d5c Mon Sep 17 00:00:00 2001 From: rbock Date: Tue, 22 Apr 2014 21:30:31 +0200 Subject: [PATCH 70/74] Allow columns() method to use all_of_t as well --- include/sqlpp11/insert.h | 1 + include/sqlpp11/select.h | 11 +---------- include/sqlpp11/vendor/select_column_list.h | 21 ++++++++++++++++----- tests/SelectTest.cpp | 3 ++- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/include/sqlpp11/insert.h b/include/sqlpp11/insert.h index 35343bf9..9d3f54ea 100644 --- a/include/sqlpp11/insert.h +++ b/include/sqlpp11/insert.h @@ -129,6 +129,7 @@ namespace sqlpp template std::size_t _run(Database& db) const { +#warning add _check_consistency here and for remove and update static_assert(_get_static_no_of_parameters() == 0, "cannot run insert directly with parameters, use prepare instead"); return db.insert(*this); } diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index 7249045f..e58a0ad8 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -47,7 +47,6 @@ #include #include -#include #include namespace sqlpp @@ -329,14 +328,6 @@ namespace sqlpp template using make_select_t = typename detail::select_policies_t::_statement_t; - namespace detail - { - template - using make_select_column_list_t = - copy_tuple_args_t::_(std::declval())...))>; - } - make_select_t select() // FIXME: These should be constexpr { return { }; @@ -346,7 +337,7 @@ namespace sqlpp auto select(Columns... columns) -> make_select_t> { - return { make_select_t(), detail::make_select_column_list_t(std::tuple_cat(detail::as_tuple::_(columns)...)) }; + return { make_select_t(), detail::make_select_column_list_t{std::tuple_cat(detail::as_tuple::_(columns)...)} }; } template diff --git a/include/sqlpp11/vendor/select_column_list.h b/include/sqlpp11/vendor/select_column_list.h index 06c57236..9760da5d 100644 --- a/include/sqlpp11/vendor/select_column_list.h +++ b/include/sqlpp11/vendor/select_column_list.h @@ -38,6 +38,7 @@ #include #include #include +#include namespace sqlpp { @@ -219,7 +220,18 @@ namespace sqlpp _parameter_tuple_t _columns; dynamic_select_column_list _dynamic_columns; }; + } + namespace detail + { + template + using make_select_column_list_t = + copy_tuple_args_t::_(std::declval())...))>; + } + + namespace vendor + { struct no_select_column_list_t { using _is_noop = std::true_type; @@ -245,18 +257,17 @@ namespace sqlpp template auto columns(Args... args) - -> _new_statement_t> + -> _new_statement_t<::sqlpp::detail::make_select_column_list_t> { -#warning need to handle all_of_t here - return { *static_cast(this), select_column_list_t{args...} }; + return { *static_cast(this), ::sqlpp::detail::make_select_column_list_t{std::tuple_cat(::sqlpp::detail::as_tuple::_(args)...)} }; } template auto dynamic_columns(Args... args) - -> _new_statement_t> + -> _new_statement_t<::sqlpp::detail::make_select_column_list_t<_database_t, Args...>> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_columns must not be called in a static statement"); - return { *static_cast(this), vendor::select_column_list_t<_database_t, Args...>{args...} }; + return { *static_cast(this), ::sqlpp::detail::make_select_column_list_t<_database_t, Args...>{std::tuple_cat(::sqlpp::detail::as_tuple::_(args)...)} }; } }; }; diff --git a/tests/SelectTest.cpp b/tests/SelectTest.cpp index ae2edeb1..c54c7c2d 100644 --- a/tests/SelectTest.cpp +++ b/tests/SelectTest.cpp @@ -68,8 +68,9 @@ int main() const bool g = row.gamma; } - auto s = dynamic_select(db).dynamic_columns(t.alpha).dynamic_flags().dynamic_from(t).extra_tables(f,t).dynamic_where().dynamic_group_by(t.alpha).dynamic_order_by().dynamic_having(t.gamma).dynamic_limit().dynamic_offset(); + auto s = dynamic_select(db).dynamic_columns(all_of(t)).dynamic_flags().dynamic_from(t).extra_tables(f,t).dynamic_where().dynamic_group_by(t.alpha).dynamic_order_by().dynamic_having(t.gamma).dynamic_limit().dynamic_offset(); s.add_flag(sqlpp::distinct); +#warning: this should fail because t.beta has been selected already s.add_column(t.beta); s.add_from(f); s.add_where(t.alpha > 7); From d342973ef40279ffc3ae5f0bbd7177e31cb46db4 Mon Sep 17 00:00:00 2001 From: rbock Date: Tue, 22 Apr 2014 21:41:53 +0200 Subject: [PATCH 71/74] Added check to prevent add_column to use a column name known in the static part --- include/sqlpp11/vendor/select_column_list.h | 7 ++++++- tests/SelectTest.cpp | 3 +-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/include/sqlpp11/vendor/select_column_list.h b/include/sqlpp11/vendor/select_column_list.h index 9760da5d..2c3d6042 100644 --- a/include/sqlpp11/vendor/select_column_list.h +++ b/include/sqlpp11/vendor/select_column_list.h @@ -198,8 +198,13 @@ namespace sqlpp 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(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "named expression uses tables unknown to this statement in add_column()"); + using column_names = ::sqlpp::detail::make_type_set_t; + static_assert(not ::sqlpp::detail::is_element_of::value, "a column of this name is present in the select already"); - using ok = ::sqlpp::detail::all_t>; + using ok = ::sqlpp::detail::all_t + >; _add_column_impl(namedExpression, ok()); // dispatch to prevent compile messages after the static_assert } diff --git a/tests/SelectTest.cpp b/tests/SelectTest.cpp index c54c7c2d..c82f1dc2 100644 --- a/tests/SelectTest.cpp +++ b/tests/SelectTest.cpp @@ -70,8 +70,7 @@ int main() auto s = dynamic_select(db).dynamic_columns(all_of(t)).dynamic_flags().dynamic_from(t).extra_tables(f,t).dynamic_where().dynamic_group_by(t.alpha).dynamic_order_by().dynamic_having(t.gamma).dynamic_limit().dynamic_offset(); s.add_flag(sqlpp::distinct); -#warning: this should fail because t.beta has been selected already - s.add_column(t.beta); + s.add_column(f.omega); s.add_from(f); s.add_where(t.alpha > 7); s.add_having(t.alpha > 7); From f47ef75c247f41e5d20999cfe5e99f425c4ca3e1 Mon Sep 17 00:00:00 2001 From: rbock Date: Tue, 22 Apr 2014 22:21:44 +0200 Subject: [PATCH 72/74] Added a few checks to insert, update and remove --- include/sqlpp11/insert.h | 16 +++++++++++++++- include/sqlpp11/remove.h | 20 ++++++++++++++++++-- include/sqlpp11/select.h | 2 ++ include/sqlpp11/update.h | 18 ++++++++++++++++++ 4 files changed, 53 insertions(+), 3 deletions(-) diff --git a/include/sqlpp11/insert.h b/include/sqlpp11/insert.h index 9d3f54ea..c24f236f 100644 --- a/include/sqlpp11/insert.h +++ b/include/sqlpp11/insert.h @@ -126,10 +126,22 @@ namespace sqlpp return _parameter_list_t::size::value; } + template + struct is_table_subset_of_table + { + static constexpr bool value = ::sqlpp::detail::is_subset_of::value; + }; + + void _check_consistency() const + { + // FIXME: Read up on what is allowed/prohibited in INSERT + } + template std::size_t _run(Database& db) const { -#warning add _check_consistency here and for remove and update + _check_consistency(); + static_assert(_get_static_no_of_parameters() == 0, "cannot run insert directly with parameters, use prepare instead"); return db.insert(*this); } @@ -138,6 +150,8 @@ namespace sqlpp auto _prepare(Database& db) const -> prepared_insert_t { + _check_consistency(); + return {{}, db.prepare_insert(*this)}; } diff --git a/include/sqlpp11/remove.h b/include/sqlpp11/remove.h index 9ea1fd6c..ed12718f 100644 --- a/include/sqlpp11/remove.h +++ b/include/sqlpp11/remove.h @@ -132,11 +132,26 @@ namespace sqlpp return _parameter_list_t::size::value; } + template + struct is_table_subset_of_table + { + static constexpr bool value = ::sqlpp::detail::is_subset_of::value; + }; + + void _check_consistency() const + { + static_assert(is_where_t<_where_t>::value, "cannot run update without having a where condition, use .where(true) to update all rows"); + + // FIXME: Read more details about what is allowed and what not in SQL DELETE + static_assert(is_table_subset_of_table<_where_t>::value, "where requires additional tables"); + } + template std::size_t _run(Database& db) const { + _check_consistency(); + static_assert(_get_static_no_of_parameters() == 0, "cannot run remove directly with parameters, use prepare instead"); - static_assert(is_where_t<_where_t>::value, "cannot run remove without having a where condition, use .where(true) to remove all rows"); return db.remove(*this); } @@ -144,7 +159,8 @@ namespace sqlpp auto _prepare(Database& db) const -> prepared_remove_t { - static_assert(is_where_t<_where_t>::value, "cannot run remove without having a where condition, use .where(true) to remove all rows"); + _check_consistency(); + return {{}, db.prepare_remove(*this)}; } diff --git a/include/sqlpp11/select.h b/include/sqlpp11/select.h index e58a0ad8..fd1b3a59 100644 --- a/include/sqlpp11/select.h +++ b/include/sqlpp11/select.h @@ -256,6 +256,8 @@ namespace sqlpp void _check_consistency() const { + static_assert(is_select_column_list_t<_column_list_t>::value, "no columns selected"); + 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()"); diff --git a/include/sqlpp11/update.h b/include/sqlpp11/update.h index 496adb14..5865651a 100644 --- a/include/sqlpp11/update.h +++ b/include/sqlpp11/update.h @@ -130,9 +130,25 @@ namespace sqlpp return _parameter_list_t::size::value; } + template + struct is_table_subset_of_table + { + static constexpr bool value = ::sqlpp::detail::is_subset_of::value; + }; + + void _check_consistency() const + { + static_assert(is_where_t<_where_t>::value, "cannot run update without having a where condition, use .where(true) to update all rows"); + + static_assert(is_table_subset_of_table<_update_list_t>::value, "updates require additional tables"); + static_assert(is_table_subset_of_table<_where_t>::value, "where requires additional tables"); + } + template std::size_t _run(Database& db) const { + _check_consistency(); + static_assert(_get_static_no_of_parameters() == 0, "cannot run update directly with parameters, use prepare instead"); return db.update(*this); } @@ -141,6 +157,8 @@ namespace sqlpp auto _prepare(Database& db) const -> prepared_update_t { + _check_consistency(); + return {{}, db.prepare_update(*this)}; } From eef974478c0aced532e98fb411a70d671d756590 Mon Sep 17 00:00:00 2001 From: rbock Date: Tue, 22 Apr 2014 22:39:25 +0200 Subject: [PATCH 73/74] Fixed a few missing types --- include/sqlpp11/avg.h | 2 ++ include/sqlpp11/count.h | 2 ++ include/sqlpp11/exists.h | 2 ++ include/sqlpp11/max.h | 2 ++ include/sqlpp11/min.h | 2 ++ include/sqlpp11/vendor/select_column_list.h | 5 +++++ 6 files changed, 15 insertions(+) diff --git a/include/sqlpp11/avg.h b/include/sqlpp11/avg.h index f763a30f..dcf821b7 100644 --- a/include/sqlpp11/avg.h +++ b/include/sqlpp11/avg.h @@ -44,6 +44,8 @@ namespace sqlpp using _is_named_expression = std::true_type; }; + using _table_set = typename Expr::_table_set; + struct _name_t { static constexpr const char* _get_name() { return "AVG"; } diff --git a/include/sqlpp11/count.h b/include/sqlpp11/count.h index 3e6c10ce..dc54437f 100644 --- a/include/sqlpp11/count.h +++ b/include/sqlpp11/count.h @@ -45,6 +45,8 @@ namespace sqlpp using _is_named_expression = std::true_type; }; + using _table_set = typename Expr::_table_set; + struct _name_t { static constexpr const char* _get_name() { return "COUNT"; } diff --git a/include/sqlpp11/exists.h b/include/sqlpp11/exists.h index 899a460b..ac69461e 100644 --- a/include/sqlpp11/exists.h +++ b/include/sqlpp11/exists.h @@ -43,6 +43,8 @@ namespace sqlpp using _is_named_expression = std::true_type; }; + using _table_set = typename Select::_table_set; + struct _name_t { static constexpr const char* _get_name() { return "EXISTS"; } diff --git a/include/sqlpp11/max.h b/include/sqlpp11/max.h index ecba9d94..a86c4b22 100644 --- a/include/sqlpp11/max.h +++ b/include/sqlpp11/max.h @@ -43,6 +43,8 @@ namespace sqlpp using _is_named_expression = std::true_type; }; + using _table_set = typename Expr::_table_set; + struct _name_t { static constexpr const char* _get_name() { return "MAX"; } diff --git a/include/sqlpp11/min.h b/include/sqlpp11/min.h index ee7f4068..c7d9f9e0 100644 --- a/include/sqlpp11/min.h +++ b/include/sqlpp11/min.h @@ -43,6 +43,8 @@ namespace sqlpp using _is_named_expression = std::true_type; }; + using _table_set = typename Expr::_table_set; + struct _name_t { static constexpr const char* _get_name() { return "MIN"; } diff --git a/include/sqlpp11/vendor/select_column_list.h b/include/sqlpp11/vendor/select_column_list.h index 2c3d6042..52a48045 100644 --- a/include/sqlpp11/vendor/select_column_list.h +++ b/include/sqlpp11/vendor/select_column_list.h @@ -183,6 +183,11 @@ namespace sqlpp select_column_list_t& operator=(select_column_list_t&&) = default; ~select_column_list_t() = default; + static constexpr size_t static_size() + { + return size::value; + } + template struct _methods_t { From adc3545ca174567190d86726a09b428eba79a8d4 Mon Sep 17 00:00:00 2001 From: rbock Date: Thu, 24 Apr 2014 14:09:33 +0200 Subject: [PATCH 74/74] Fix in insert's add_set error handling --- include/sqlpp11/vendor/insert_value_list.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sqlpp11/vendor/insert_value_list.h b/include/sqlpp11/vendor/insert_value_list.h index 550061ce..7f450792 100644 --- a/include/sqlpp11/vendor/insert_value_list.h +++ b/include/sqlpp11/vendor/insert_value_list.h @@ -95,7 +95,7 @@ namespace sqlpp { static_assert(_is_dynamic::value, "add_set must not be called for static from()"); 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"); + 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(::sqlpp::detail::is_subset_of<_value_table_set, typename Policies::_table_set>::value, "add_set() contains a column from a foreign table");