diff --git a/include/sqlpp11/custom_query.h b/include/sqlpp11/custom_query.h new file mode 100644 index 00000000..662891dd --- /dev/null +++ b/include/sqlpp11/custom_query.h @@ -0,0 +1,137 @@ +/* + * 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_CUSTOM_QUERY_H +#define SQLPP_CUSTOM_QUERY_H + +#include +#include +#include +#include + +namespace sqlpp +{ + template + struct custom_query_t; + + namespace detail + { + template + struct custom_parts_t + { + using _custom_query_t = custom_query_t; + using _result_type_provider = detail::get_first_if; + using _result_methods_t = typename _result_type_provider::template _result_methods_t<_result_type_provider>; + }; + } + + template + struct custom_query_t: + private detail::custom_parts_t::_result_methods_t + { + using _methods_t = typename detail::custom_parts_t::_result_methods_t; + using _traits = make_traits; + using _recursive_traits = make_recursive_traits; + + custom_query_t(Parts... parts): + _parts(parts...) + {} + + custom_query_t(std::tuple parts): + _parts(parts) + {} + + custom_query_t(const custom_query_t&) = default; + custom_query_t(custom_query_t&&) = default; + custom_query_t& operator=(const custom_query_t&) = default; + custom_query_t& operator=(custom_query_t&&) = default; + ~custom_query_t() = default; + + static void _check_consistency() {}; + + template + auto _run(Db& db) const -> decltype(_methods_t::_run(db, *this)) + { + return _methods_t::_run(db, *this); + } + + template + auto _prepare(Db& db) const -> decltype(_methods_t::_prepare(db, *this)) + { + return _methods_t::_prepare(db, *this); + } + + static constexpr size_t _get_static_no_of_parameters() + { + return std::tuple_size>::value; + } + + size_t _get_no_of_parameters() const + { + return _get_static_no_of_parameters(); + } + + template + auto with_result_type_of(Part part) + -> custom_query_t + { + return {tuple_cat(std::make_tuple(part), _parts)}; + } + + std::tuple _parts; + }; + + template + struct serializer_t> + { + using T = custom_query_t; + + static Context& _(const T& t, Context& context) + { + interpret_tuple_without_braces(t._parts, " ", context); + return context; + } + }; + + template + auto custom_query(Parts... parts) + -> custom_query_t...> + { + static_assert(sizeof...(Parts) > 0, "custom query requires at least one argument"); + return custom_query_t...>(parts...); + } + + template + auto dynamic_custom_query(const Database&, Parts... parts) + -> custom_query_t...> + { + static_assert(sizeof...(Parts) > 0, "custom query requires at least one query argument"); + static_assert(std::is_base_of::value, "Invalid database parameter"); + + return custom_query_t...>(parts...); + } +} +#endif diff --git a/include/sqlpp11/detail/get_first.h b/include/sqlpp11/detail/get_first.h new file mode 100644 index 00000000..25a784d8 --- /dev/null +++ b/include/sqlpp11/detail/get_first.h @@ -0,0 +1,60 @@ +/* + * 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_DETAIL_GET_FIRST_H +#define SQLPP_DETAIL_GET_FIRST_H + +#include + +namespace sqlpp +{ + namespace detail + { + template class Predicate, typename Default, typename... T> + struct get_first_if_impl; + + template class Predicate, typename Default> + struct get_first_if_impl + { + using type = Default; + }; + + template class Predicate, typename Default, typename T, typename... Rest> + struct get_first_if_impl + { + using rest = typename get_first_if_impl::type; + using type = typename std::conditional::value, + T, + rest>::type; + }; + + template class Predicate, typename Default, typename... T> + using get_first_if = typename get_first_if_impl::type; + } +} + + +#endif diff --git a/include/sqlpp11/hidden.h b/include/sqlpp11/hidden.h new file mode 100644 index 00000000..e9f98cfa --- /dev/null +++ b/include/sqlpp11/hidden.h @@ -0,0 +1,65 @@ +/* + * 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_HIDDEN_H +#define SQLPP_HIDDEN_H + +namespace sqlpp +{ + template + struct hidden_t: + public Part + { + hidden_t(Part part): + Part(part) + {} + + hidden_t(const hidden_t&) = default; + hidden_t(hidden_t&&) = default; + hidden_t& operator=(const hidden_t&) = default; + hidden_t& operator=(hidden_t&&) = default; + ~hidden_t() = default; + }; + + template + struct serializer_t> + { + using T = hidden_t; + + static Context& _(const T& t, Context& context) + { + return context; + } + }; + + template + auto hidden(Part part) + -> hidden_t + { + return {part}; + } +} +#endif diff --git a/include/sqlpp11/insert.h b/include/sqlpp11/insert.h index d6e1bc3a..59091a04 100644 --- a/include/sqlpp11/insert.h +++ b/include/sqlpp11/insert.h @@ -46,16 +46,27 @@ namespace sqlpp using _traits = make_traits; struct _name_t {}; - template + template struct _result_methods_t { - using _statement_t = derived_statement_t; + using _statement_t = Statement; const _statement_t& _get_statement() const { return static_cast(*this); } + // Execute + template + auto _run(Db& db, const Composite& composite) const + -> decltype(db.insert(composite)) + { + Composite::_check_consistency(); + static_assert(Composite::_get_static_no_of_parameters() == 0, "cannot run insert directly with parameters, use prepare instead"); + + return db.insert(composite); + } + template auto _run(Db& db) const -> decltype(db.insert(this->_get_statement())) { @@ -65,14 +76,24 @@ namespace sqlpp return db.insert(_get_statement()); } - template - auto _prepare(Db& db) const - -> prepared_insert_t - { - _statement_t::_check_consistency(); + // Prepare + template + auto _prepare(Db& db, const Composite& composite) const + -> prepared_insert_t + { + Composite::_check_consistency(); - return {{}, db.prepare_insert(_get_statement())}; - } + return {{}, db.prepare_insert(composite)}; + } + + template + auto _prepare(Db& db) const + -> prepared_insert_t + { + _statement_t::_check_consistency(); + + return {{}, db.prepare_insert(_get_statement())}; + } }; }; diff --git a/include/sqlpp11/interpret_tuple.h b/include/sqlpp11/interpret_tuple.h index 4edb2631..518c607c 100644 --- a/include/sqlpp11/interpret_tuple.h +++ b/include/sqlpp11/interpret_tuple.h @@ -34,20 +34,20 @@ namespace sqlpp { - template - static void interpret_tuple_element(const Element& element, const Separator& separator, Context& context, size_t index) + template + static void interpret_tuple_element(const Element& element, const Separator& separator, Context& context, const UseBraces&, size_t index) { if (index) context << separator; - if (requires_braces_t::value) + if (UseBraces::value and requires_braces_t::value) context << "("; serialize(element, context); - if (requires_braces_t::value) + if (UseBraces::value and requires_braces_t::value) context << ")"; } - template - auto interpret_tuple_impl(const Tuple& t, const Separator& separator, Context& context, const detail::index_sequence&) + template + auto interpret_tuple_impl(const Tuple& t, const Separator& separator, Context& context, const UseBraces& useBraces, const detail::index_sequence&) -> Context& { // Note: A braced-init-list does guarantee the order of evaluation according to 12.6.1 [class.explicit.init] paragraph 2 and 8.5.4 [dcl.init.list] paragraph 4. @@ -55,7 +55,7 @@ namespace sqlpp // See also: "http://stackoverflow.com/questions/6245735/pretty-print-stdtuple/6245777#6245777" // Beware of gcc-bug: "http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51253", otherwise an empty swallow struct could be used using swallow = int[]; - (void) swallow{(interpret_tuple_element(std::get(t), separator, context, Is), 0)...}; + (void) swallow{(interpret_tuple_element(std::get(t), separator, context, useBraces, Is), 0)...}; return context; } @@ -63,7 +63,14 @@ namespace sqlpp auto interpret_tuple(const Tuple& t, const Separator& separator, Context& context) -> Context& { - return interpret_tuple_impl(t, separator, context, detail::make_index_sequence::value>{}); + return interpret_tuple_impl(t, separator, context, std::true_type{}, detail::make_index_sequence::value>{}); + } + + template + auto interpret_tuple_without_braces(const Tuple& t, const Separator& separator, Context& context) + -> Context& + { + return interpret_tuple_impl(t, separator, context, std::false_type{}, detail::make_index_sequence::value>{}); } } diff --git a/include/sqlpp11/into.h b/include/sqlpp11/into.h index cff8fb35..e1d2ddd5 100644 --- a/include/sqlpp11/into.h +++ b/include/sqlpp11/into.h @@ -27,6 +27,7 @@ #ifndef SQLPP_INTO_H #define SQLPP_INTO_H +#include #include #include #include @@ -168,6 +169,11 @@ namespace sqlpp } }; + template + auto into(T&&... t) -> decltype(statement_t().into(std::forward(t)...)) + { + return statement_t().into(std::forward(t)...); + } } #endif diff --git a/include/sqlpp11/noop.h b/include/sqlpp11/noop.h index 5d6afae2..1c1b4d61 100644 --- a/include/sqlpp11/noop.h +++ b/include/sqlpp11/noop.h @@ -30,6 +30,7 @@ #include #include #include +#include namespace sqlpp { @@ -40,9 +41,54 @@ namespace sqlpp struct _name_t {}; - template + template struct _result_methods_t - {}; + { + using _statement_t = Statement; + + const _statement_t& _get_statement() const + { + return static_cast(*this); + } + + // Execute + template + auto _run(Db& db, const Composite& composite) const -> void + { + Composite::_check_consistency(); + static_assert(Composite::_get_static_no_of_parameters() == 0, "cannot run execute directly with parameters, use prepare instead"); + + return db.execute(composite); + } + + template + auto _run(Db& db) const -> void + { + _statement_t::_check_consistency(); + + static_assert(_statement_t::_get_static_no_of_parameters() == 0, "cannot run insert directly with parameters, use prepare instead"); + return db.execute(_get_statement()); + } + + // Prepare + template + auto _prepare(Db& db, const Composite& composite) const + -> prepared_execute_t + { + Composite::_check_consistency(); + + return {{}, db.prepare_execute(composite)}; + } + + template + auto _prepare(Db& db) const + -> prepared_execute_t + { + _statement_t::_check_consistency(); + + return {{}, db.prepare_execute(_get_statement())}; + } + }; }; template diff --git a/include/sqlpp11/prepared_execute.h b/include/sqlpp11/prepared_execute.h new file mode 100644 index 00000000..e181d37c --- /dev/null +++ b/include/sqlpp11/prepared_execute.h @@ -0,0 +1,58 @@ +/* + * 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_PREPARED_EXECUTE_H +#define SQLPP_PREPARED_EXECUTE_H + +#include +#include + +namespace sqlpp +{ + template + struct prepared_execute_t + { + using _parameter_list_t = make_parameter_list_t; + using _prepared_statement_t = typename Db::_prepared_statement_t; + + auto _run(Db& db) const + -> void + { + return db.run_prepared_execute(*this); + } + + void _bind_params() const + { + params._bind(_prepared_statement); + } + + _parameter_list_t params; + mutable _prepared_statement_t _prepared_statement; + }; + +} + +#endif diff --git a/include/sqlpp11/prepared_select.h b/include/sqlpp11/prepared_select.h index 2c74e9a2..2701e17e 100644 --- a/include/sqlpp11/prepared_select.h +++ b/include/sqlpp11/prepared_select.h @@ -32,12 +32,12 @@ namespace sqlpp { - template + template struct prepared_select_t { - using _result_row_t = typename Select::template _result_row_t; - using _parameter_list_t = make_parameter_list_t::template _result_row_t; using IndexSequence = ResultRow::_field_index_sequence; static_assert(std::is_same>::value, "invalid field sequence"); }