0
0
mirror of https://github.com/rbock/sqlpp11.git synced 2024-11-15 20:31:16 +08:00

Added columns and add_values to insert for multi row inserts

Need to change add_values method to use assignments, though.
This commit is contained in:
rbock 2014-01-26 13:24:42 +01:00
parent f802300685
commit 5ef5259988
8 changed files with 376 additions and 9 deletions

View File

@ -43,6 +43,7 @@ namespace sqlpp
template<typename Table, typename ColumnSpec> template<typename Table, typename ColumnSpec>
struct column_t: public ColumnSpec::_value_type::template operators<column_t<Table, ColumnSpec>> struct column_t: public ColumnSpec::_value_type::template operators<column_t<Table, ColumnSpec>>
{ {
using _is_column = std::true_type;
using _table = Table; using _table = Table;
using _column_type = typename ColumnSpec::_column_type; using _column_type = typename ColumnSpec::_column_type;
struct _value_type: ColumnSpec::_value_type struct _value_type: ColumnSpec::_value_type

View File

@ -28,10 +28,12 @@
#define SQLPP_INSERT_H #define SQLPP_INSERT_H
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/parameter_list.h>
#include <sqlpp11/prepared_insert.h> #include <sqlpp11/prepared_insert.h>
#include <sqlpp11/vendor/column_list.h>
#include <sqlpp11/vendor/noop.h> #include <sqlpp11/vendor/noop.h>
#include <sqlpp11/vendor/insert_list.h> #include <sqlpp11/vendor/insert_list.h>
#include <sqlpp11/parameter_list.h> #include <sqlpp11/vendor/insert_value_list.h>
namespace sqlpp namespace sqlpp
{ {
@ -39,16 +41,22 @@ namespace sqlpp
template< template<
typename Database = void, typename Database = void,
typename Table = vendor::noop, typename Table = vendor::noop,
typename InsertList = vendor::noop typename InsertList = vendor::noop,
typename ColumnList = vendor::noop,
typename ValueList = vendor::insert_value_list_t<vendor::noop>
> >
struct insert_t struct insert_t
{ {
static_assert(vendor::is_noop<Table>::value or is_table_t<Table>::value, "invalid 'Table' argument"); static_assert(vendor::is_noop<Table>::value or is_table_t<Table>::value, "invalid 'Table' argument");
static_assert(vendor::is_noop<InsertList>::value or is_insert_list_t<InsertList>::value, "invalid 'InsertList' argument"); static_assert(vendor::is_noop<InsertList>::value or is_insert_list_t<InsertList>::value, "invalid 'InsertList' argument");
static_assert(vendor::is_noop<ColumnList>::value or is_column_list_t<ColumnList>::value, "invalid 'ColumnList' argument");
static_assert(vendor::is_noop<ValueList>::value or is_insert_value_list_t<ValueList>::value, "invalid 'ValueList' argument");
using use_default_values_t = insert_t<Database, Table, vendor::insert_default_values_t>;
template<typename AssignmentT> template<typename AssignmentT>
using set_insert_list_t = insert_t<Database, Table, AssignmentT>; using set_insert_list_t = insert_t<Database, Table, AssignmentT>;
using use_default_values_t = insert_t<Database, Table, vendor::insert_default_values_t>; template<typename ColumnT, typename ValueT>
using set_column_value_list_t = insert_t<Database, Table, InsertList, ColumnT, ValueT>;
using _parameter_tuple_t = std::tuple<Table, InsertList>; using _parameter_tuple_t = std::tuple<Table, InsertList>;
using _parameter_list_t = typename make_parameter_list_t<insert_t>::type; using _parameter_list_t = typename make_parameter_list_t<insert_t>::type;
@ -57,10 +65,13 @@ namespace sqlpp
-> use_default_values_t -> use_default_values_t
{ {
static_assert(std::is_same<InsertList, vendor::noop>::value, "cannot call default_values() after set() or default_values()"); static_assert(std::is_same<InsertList, vendor::noop>::value, "cannot call default_values() after set() or default_values()");
static_assert(vendor::is_noop<ColumnList>::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"); static_assert(Table::_required_insert_columns::size::value == 0, "cannot use default_values, because some columns are configured to require values");
return { return {
_table, _table,
{}, {},
_column_list,
_value_list,
}; };
} }
@ -69,10 +80,13 @@ namespace sqlpp
-> set_insert_list_t<vendor::insert_list_t<void, typename std::decay<Assignment>::type...>> -> set_insert_list_t<vendor::insert_list_t<void, typename std::decay<Assignment>::type...>>
{ {
static_assert(std::is_same<InsertList, vendor::noop>::value, "cannot call set() after set() or default_values()"); static_assert(std::is_same<InsertList, vendor::noop>::value, "cannot call set() after set() or default_values()");
static_assert(vendor::is_noop<ColumnList>::value, "cannot call set() after columns()");
// FIXME: Need to check if all required columns are set // FIXME: Need to check if all required columns are set
return { return {
_table, _table,
vendor::insert_list_t<void, typename std::decay<Assignment>::type...>{std::forward<Assignment>(assignment)...}, vendor::insert_list_t<void, typename std::decay<Assignment>::type...>{std::forward<Assignment>(assignment)...},
_column_list,
_value_list,
}; };
} }
@ -81,9 +95,12 @@ namespace sqlpp
-> set_insert_list_t<vendor::insert_list_t<Database, typename std::decay<Assignment>::type...>> -> set_insert_list_t<vendor::insert_list_t<Database, typename std::decay<Assignment>::type...>>
{ {
static_assert(std::is_same<InsertList, vendor::noop>::value, "cannot call set() after set() or default_values()"); static_assert(std::is_same<InsertList, vendor::noop>::value, "cannot call set() after set() or default_values()");
static_assert(vendor::is_noop<ColumnList>::value, "cannot call set() after columns()");
return { return {
_table, _table,
vendor::insert_list_t<Database, typename std::decay<Assignment>::type...>{std::forward<Assignment>(assignment)...}, vendor::insert_list_t<Database, typename std::decay<Assignment>::type...>{std::forward<Assignment>(assignment)...},
_column_list,
_value_list,
}; };
} }
@ -97,6 +114,34 @@ namespace sqlpp
return *this; return *this;
} }
template<typename Column>
//using _insert_value_t = vendor::insert_value_t<typename vendor::wrap_operand<typename Column::_value_type::_cpp_value_type>::type>;
using _insert_value_t = vendor::insert_value_t<typename Column::_value_type::_cpp_value_type>;
template<typename... Column>
auto columns(Column... columns)
-> set_column_value_list_t<vendor::column_list_t<Column...>, vendor::insert_value_list_t<_insert_value_t<Column>...>>
{
static_assert(vendor::is_noop<ColumnList>::value, "cannot call columns() twice");
static_assert(vendor::is_noop<InsertList>::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<Column...>{columns...}},
vendor::insert_value_list_t<_insert_value_t<Column>...>{},
};
}
template<typename... Value>
insert_t& add_values(Value... values)
{
static_assert(is_insert_value_list_t<ValueList>::value, "cannot call add_values() before columns()");
_value_list.add(typename ValueList::_value_tuple_t{values...});
return *this;
};
static constexpr size_t _get_static_no_of_parameters() static constexpr size_t _get_static_no_of_parameters()
{ {
return _parameter_list_t::size::value; return _parameter_list_t::size::value;
@ -128,20 +173,36 @@ namespace sqlpp
Table _table; Table _table;
InsertList _insert_list; InsertList _insert_list;
ColumnList _column_list;
ValueList _value_list;
}; };
namespace vendor namespace vendor
{ {
template<typename Context, typename Database, typename Table, typename InsertList> template<typename Context, typename Database, typename Table, typename InsertList, typename ColumnList, typename ValueList>
struct interpreter_t<Context, insert_t<Database, Table, InsertList>> struct interpreter_t<Context, insert_t<Database, Table, InsertList, ColumnList, ValueList>>
{ {
using T = insert_t<Database, Table, InsertList>; using T = insert_t<Database, Table, InsertList, ColumnList, ValueList>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
context << "INSERT INTO "; if (not vendor::is_noop<decltype(t._insert_list)>::value)
interpret(t._table, context); {
interpret(t._insert_list, context); 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";
}
return context; return context;
} }
}; };

View File

@ -50,6 +50,11 @@ namespace sqlpp
tvin_t& operator=(tvin_t&&) = default; tvin_t& operator=(tvin_t&&) = default;
~tvin_t() = default; ~tvin_t() = default;
bool _is_trivial() const
{
return _value._is_trivial();
}
_operand_t _value; _operand_t _value;
}; };

View File

@ -95,6 +95,7 @@ namespace sqlpp
SQLPP_TYPE_TRAIT_GENERATOR(is_table); SQLPP_TYPE_TRAIT_GENERATOR(is_table);
SQLPP_TYPE_TRAIT_GENERATOR(is_pseudo_table); SQLPP_TYPE_TRAIT_GENERATOR(is_pseudo_table);
SQLPP_TYPE_TRAIT_GENERATOR(is_column);
SQLPP_TYPE_TRAIT_GENERATOR(is_select); SQLPP_TYPE_TRAIT_GENERATOR(is_select);
SQLPP_TYPE_TRAIT_GENERATOR(is_select_flag_list); SQLPP_TYPE_TRAIT_GENERATOR(is_select_flag_list);
SQLPP_TYPE_TRAIT_GENERATOR(is_select_column_list); SQLPP_TYPE_TRAIT_GENERATOR(is_select_column_list);
@ -114,6 +115,8 @@ namespace sqlpp
SQLPP_TYPE_TRAIT_GENERATOR(is_assignment); SQLPP_TYPE_TRAIT_GENERATOR(is_assignment);
SQLPP_TYPE_TRAIT_GENERATOR(is_update_list); SQLPP_TYPE_TRAIT_GENERATOR(is_update_list);
SQLPP_TYPE_TRAIT_GENERATOR(is_insert_list); SQLPP_TYPE_TRAIT_GENERATOR(is_insert_list);
SQLPP_TYPE_TRAIT_GENERATOR(is_insert_value);
SQLPP_TYPE_TRAIT_GENERATOR(is_insert_value_list);
SQLPP_TYPE_TRAIT_GENERATOR(is_sort_order); SQLPP_TYPE_TRAIT_GENERATOR(is_sort_order);
SQLPP_TYPE_TRAIT_GENERATOR(requires_braces); SQLPP_TYPE_TRAIT_GENERATOR(requires_braces);
SQLPP_TYPE_TRAIT_GENERATOR(is_parameter); SQLPP_TYPE_TRAIT_GENERATOR(is_parameter);

78
include/sqlpp11/vendor/column_list.h vendored Normal file
View File

@ -0,0 +1,78 @@
/*
* 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_COLUMN_LIST_H
#define SQLPP_COLUMN_LIST_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/set.h>
#include <sqlpp11/vendor/interpret_tuple.h>
namespace sqlpp
{
namespace vendor
{
template<typename... Columns>
struct column_list_t
{
using _is_column_list = std::true_type;
using _parameter_tuple_t = std::tuple<Columns...>;
// check for at least one order column
static_assert(sizeof...(Columns), "at least one column required in columns()");
// check for duplicate columns
static_assert(not ::sqlpp::detail::has_duplicates<Columns...>::value, "at least one duplicate argument detected in columns()");
// check for invalid columns
using _column_set = typename ::sqlpp::detail::make_set_if<is_column_t, Columns...>::type;
static_assert(_column_set::size::value == sizeof...(Columns), "at least one argument is not a column in columns()");
// check for prohibited columns
using _prohibited_column_set = typename ::sqlpp::detail::make_set_if<must_not_insert_t, Columns...>::type;
static_assert(_prohibited_column_set::size::value == 0, "at least one column argument has a must_not_insert flag in its definition");
_parameter_tuple_t _columns;
};
template<typename Context, typename... Columns>
struct interpreter_t<Context, column_list_t<Columns...>>
{
using T = column_list_t<Columns...>;
static Context& _(const T& t, Context& context)
{
context << " (";
interpret_tuple(t._columns, ",", context);
context << ")";
return context;
}
};
}
}
#endif

101
include/sqlpp11/vendor/insert_value.h vendored Normal file
View File

@ -0,0 +1,101 @@
/*
* 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_VALUE_H
#define SQLPP_INSERT_VALUE_H
#include <sqlpp11/default_value.h>
#include <sqlpp11/null.h>
#include <sqlpp11/tvin.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/interpreter.h>
namespace sqlpp
{
namespace vendor
{
template<typename ValueType>
struct insert_value_t
{
using _is_insert_value = std::true_type;
using _value_t = ValueType;
insert_value_t(_value_t value):
_is_null(false),
_is_default(false),
_value({value})
{}
insert_value_t(tvin_t<_value_t> tvin):
_is_null(tvin._is_trivial()),
_is_default(false),
_value({tvin._value})
{}
insert_value_t(const ::sqlpp::null_t&):
_is_null(true),
_is_default(false),
_value()
{}
insert_value_t(const ::sqlpp::default_value_t&):
_is_null(false),
_is_default(true),
_value()
{}
insert_value_t(const insert_value_t&) = default;
insert_value_t(insert_value_t&&) = default;
insert_value_t& operator=(const insert_value_t&) = default;
insert_value_t& operator=(insert_value_t&&) = default;
~insert_value_t() = default;
bool _is_null;
bool _is_default;
typename wrap_operand<_value_t>::type _value;
};
template<typename Context, typename ValueType>
struct interpreter_t<Context, insert_value_t<ValueType>>
{
using T = insert_value_t<ValueType>;
static Context& _(const T& t, Context& context)
{
if (t._is_null)
context << "NULL";
else if (t._is_default)
context << "DEFAULT";
else
interpret(t._value, context);
return context;
}
};
}
}
#endif

View File

@ -0,0 +1,113 @@
/*
* 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_VALUE_LIST_H
#define SQLPP_INSERT_VALUE_LIST_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/set.h>
#include <sqlpp11/vendor/insert_value.h>
#include <sqlpp11/vendor/interpret_tuple.h>
namespace sqlpp
{
namespace vendor
{
template<typename... InsertValues>
struct insert_value_list_t
{
using _is_insert_value_list = std::true_type;
static_assert(sizeof...(InsertValues), "at least one insert value required");
// check for invalid arguments
using _insert_values_set = typename ::sqlpp::detail::make_set_if<is_insert_value_t, InsertValues...>::type;
static_assert(_insert_values_set::size::value == sizeof...(InsertValues), "at least one argument is not an insert value");
using _value_tuple_t = std::tuple<InsertValues...>;
void add(_value_tuple_t value_tuple)
{
_insert_values.emplace_back(value_tuple);
}
bool empty() const
{
return _insert_values.empty();
}
std::vector<_value_tuple_t> _insert_values;
};
template<>
struct insert_value_list_t<noop>
{
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<typename Context, typename... InsertValues>
struct interpreter_t<Context, insert_value_list_t<InsertValues...>>
{
using T = insert_value_list_t<InsertValues...>;
static Context& _(const T& t, Context& context)
{
context << " VALUES ";
for (const auto& row : t._insert_values)
{
context << '(';
interpret_tuple(row, ",", context);
context << ')';
}
return context;
}
};
template<typename Context>
struct interpreter_t<Context, insert_value_list_t<noop>>
{
using T = insert_value_list_t<noop>;
static Context& _(const T& t, Context& context)
{
return context;
}
};
}
}
#endif

View File

@ -43,6 +43,11 @@ int main()
TabSample t; TabSample t;
TabFoo f; TabFoo f;
interpret(insert_into(t).columns(t.gamma, t.beta), printer).flush();
interpret(insert_into(t).columns(t.gamma, t.beta).add_values(true, "cheesecake"), printer).flush();
interpret(insert_into(t).columns(t.gamma, t.beta).add_values(true, "cheesecake").add_values(false, sqlpp::tvin(std::string("coffee"))).add_values(false, sqlpp::tvin(std::string())), printer).flush();
interpret(insert_into(t).columns(t.gamma, t.beta).add_values(sqlpp::default_value, sqlpp::null), printer).flush();
interpret(insert_into(t).columns(t.gamma, t.beta), printer).flush();
interpret(t.alpha = sqlpp::null, printer).flush(); interpret(t.alpha = sqlpp::null, printer).flush();
interpret(t.alpha = sqlpp::default_value, printer).flush(); interpret(t.alpha = sqlpp::default_value, printer).flush();
interpret(t.alpha, printer).flush(); interpret(t.alpha, printer).flush();