/* * 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_INSERT_H #define SQLPP_INSERT_H #include #include #include #include #include #include #include #include #include namespace sqlpp { // INSERT template struct insert_t { static_assert(::sqlpp::detail::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 { 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() {} 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)) {} 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; // 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_values() before columns()"); return _insert_value_list.add_values(args...); } // run and prepare static constexpr size_t _get_static_no_of_parameters() { return _parameter_list_t::size::value; } size_t _get_no_of_parameters() const { return _parameter_list_t::size::value; } template std::size_t _run(Db& 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 { return {{}, db.prepare_insert(*this)}; } InsertValueList _insert_value_list; Table _table; }; namespace vendor { template struct serializer_t> { using T = insert_t; static Context& _(const T& t, Context& context) { context << "INSERT INTO "; serialize(t._table, context); serialize(t._insert_value_list, context); return context; } }; } template constexpr auto insert_into(Table table) -> insert_t> { return { insert_t(), vendor::single_table_t{table} }; } template constexpr auto dynamic_insert_into(const Database&, Table table) -> insert_t> { return { insert_t(), vendor::single_table_t{table} }; } } #endif