mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-15 20:31:16 +08:00
Migrated insert to generic statement
This commit is contained in:
parent
7e32a0a3ea
commit
8d16b6ab2d
@ -27,6 +27,7 @@
|
||||
#ifndef SQLPP_INSERT_H
|
||||
#define SQLPP_INSERT_H
|
||||
|
||||
#include <sqlpp11/statement.h>
|
||||
#include <sqlpp11/type_traits.h>
|
||||
#include <sqlpp11/parameter_list.h>
|
||||
#include <sqlpp11/prepared_insert.h>
|
||||
@ -34,13 +35,10 @@
|
||||
#include <sqlpp11/vendor/noop.h>
|
||||
#include <sqlpp11/vendor/single_table.h>
|
||||
#include <sqlpp11/vendor/insert_value_list.h>
|
||||
#include <sqlpp11/vendor/policy_update.h>
|
||||
|
||||
#include <sqlpp11/detail/get_last.h>
|
||||
#include <sqlpp11/detail/pick_arg.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
#if 0
|
||||
template<typename Db, typename... Policies>
|
||||
struct insert_t;
|
||||
|
||||
@ -121,39 +119,6 @@ namespace sqlpp
|
||||
insert_t& operator=(insert_t&&) = default;
|
||||
~insert_t() = default;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
void _check_consistency() const
|
||||
{
|
||||
// FIXME: Read up on what is allowed/prohibited in INSERT
|
||||
}
|
||||
|
||||
template<typename Database>
|
||||
std::size_t _run(Database& db) const
|
||||
{
|
||||
_check_consistency();
|
||||
|
||||
static_assert(_get_static_no_of_parameters() == 0, "cannot run insert directly with parameters, use prepare instead");
|
||||
return db.insert(*this);
|
||||
}
|
||||
|
||||
template<typename Database>
|
||||
auto _prepare(Database& db) const
|
||||
-> prepared_insert_t<Database, insert_t>
|
||||
{
|
||||
_check_consistency();
|
||||
|
||||
return {{}, db.prepare_insert(*this)};
|
||||
}
|
||||
};
|
||||
|
||||
namespace vendor
|
||||
@ -173,13 +138,14 @@ namespace sqlpp
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename Database>
|
||||
using blank_insert_t = insert_t<Database,
|
||||
using blank_insert_t = statement_t<Database,
|
||||
vendor::no_single_table_t,
|
||||
vendor::no_insert_value_list_t>;
|
||||
|
||||
constexpr auto insert()
|
||||
auto insert()
|
||||
-> blank_insert_t<void>
|
||||
{
|
||||
return { blank_insert_t<void>() };
|
||||
|
@ -27,9 +27,7 @@
|
||||
#ifndef SQLPP_SELECT_H
|
||||
#define SQLPP_SELECT_H
|
||||
|
||||
#include <sqlpp11/result.h>
|
||||
#include <sqlpp11/parameter_list.h>
|
||||
#include <sqlpp11/prepared_select.h>
|
||||
#include <sqlpp11/statement.h>
|
||||
|
||||
#include <sqlpp11/vendor/noop.h>
|
||||
#include <sqlpp11/vendor/select_flag_list.h>
|
||||
@ -43,165 +41,13 @@
|
||||
#include <sqlpp11/vendor/limit.h>
|
||||
#include <sqlpp11/vendor/offset.h>
|
||||
#include <sqlpp11/vendor/expression.h>
|
||||
#include <sqlpp11/vendor/serializer.h>
|
||||
#include <sqlpp11/vendor/wrong.h>
|
||||
#include <sqlpp11/vendor/policy_update.h>
|
||||
|
||||
#include <sqlpp11/detail/get_last.h>
|
||||
#include <sqlpp11/detail/pick_arg.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
template<typename Db, typename... Policies>
|
||||
struct select_t;
|
||||
|
||||
#warning STEPS:
|
||||
#warning deal with different return types in the connector (select could be a single value, update could be a range of rows)
|
||||
namespace detail
|
||||
{
|
||||
template<typename Db = void, typename... Policies>
|
||||
struct select_policies_t
|
||||
{
|
||||
#warning need to check policies' signature, e.g. a _data_t in _member_t template
|
||||
using _database_t = Db;
|
||||
using _statement_t = select_t<Db, Policies...>;
|
||||
|
||||
struct _methods_t: public Policies::template _methods_t<select_policies_t>...
|
||||
{};
|
||||
|
||||
template<typename Needle, typename Replacement>
|
||||
struct _policies_update_t
|
||||
{
|
||||
static_assert(detail::is_element_of<Needle, make_type_set_t<Policies...>>::value, "policies update for non-policy class detected");
|
||||
using type = select_t<Db, vendor::policy_update_t<Policies, Needle, Replacement>...>;
|
||||
};
|
||||
|
||||
template<typename Needle, typename Replacement>
|
||||
using _new_statement_t = typename _policies_update_t<Needle, Replacement>::type;
|
||||
|
||||
using _all_required_tables = detail::make_joined_set_t<required_tables_of<Policies>...>;
|
||||
using _all_provided_tables = detail::make_joined_set_t<provided_tables_of<Policies>...>;
|
||||
using _all_extra_tables = detail::make_joined_set_t<extra_tables_of<Policies>...>;
|
||||
|
||||
using _known_tables = detail::make_joined_set_t<_all_provided_tables, _all_extra_tables>;
|
||||
|
||||
template<typename Expression>
|
||||
using _no_unknown_tables = detail::is_subset_of<required_tables_of<Expression>, _known_tables>;
|
||||
|
||||
// The tables not covered by the from.
|
||||
using _required_tables = detail::make_difference_set_t<
|
||||
_all_required_tables,
|
||||
_all_provided_tables // Hint: extra_tables are not used here because they are just a helper for dynamic .add_*()
|
||||
>;
|
||||
|
||||
using _result_type_provider = detail::get_last_if<is_return_value_t, vendor::noop, Policies...>;
|
||||
|
||||
struct _result_methods_t: public _result_type_provider::template _result_methods_t<select_policies_t>
|
||||
{};
|
||||
|
||||
|
||||
// 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<_result_type_provider>::value and _required_tables::size::value == 0,
|
||||
std::true_type,
|
||||
std::false_type
|
||||
>::type;
|
||||
|
||||
using _value_type = typename std::conditional<
|
||||
detail::none_t<is_missing_t<Policies>::value...>::value,
|
||||
value_type_of<_result_type_provider>,
|
||||
no_value_t // if a required statement part is missing (e.g. columns in a select), then the statement cannot be used as a value
|
||||
>::type;
|
||||
|
||||
using _is_expression = typename std::conditional<
|
||||
std::is_same<_value_type, no_value_t>::value,
|
||||
std::false_type,
|
||||
std::true_type>::type;
|
||||
|
||||
using _traits = make_traits<_value_type>;
|
||||
|
||||
struct _recursive_traits
|
||||
{
|
||||
using _parameters = std::tuple<>; // FIXME
|
||||
using _required_tables = _required_tables;
|
||||
using _provided_tables = detail::type_set<>;
|
||||
using _extra_tables = detail::type_set<>;
|
||||
};
|
||||
|
||||
static void _check_consistency()
|
||||
{
|
||||
#warning check for missing terms here, and for missing tables
|
||||
static_assert(not required_tables_of<select_policies_t>::size::value, "one sub expression requires tables which are otherwise not known in the statement");
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
// SELECT
|
||||
template<typename Db,
|
||||
typename... Policies
|
||||
>
|
||||
struct select_t:
|
||||
public Policies::template _member_t<detail::select_policies_t<Db, Policies...>>...,
|
||||
public detail::select_policies_t<Db, Policies...>::_value_type::template expression_operators<select_t<Db, Policies...>>,
|
||||
public detail::select_policies_t<Db, Policies...>::_result_methods_t,
|
||||
public detail::select_policies_t<Db, Policies...>::_methods_t
|
||||
{
|
||||
using _policies_t = typename detail::select_policies_t<Db, Policies...>;
|
||||
|
||||
using _traits = make_traits<value_type_of<_policies_t>, ::sqlpp::tag::select, tag::expression_if<typename _policies_t::_is_expression>, tag::named_expression_if<typename _policies_t::_is_expression>>;
|
||||
using _recursive_traits = typename _policies_t::_recursive_traits;
|
||||
|
||||
using _result_type_provider = typename _policies_t::_result_type_provider;
|
||||
|
||||
using _requires_braces = std::true_type;
|
||||
|
||||
using _name_t = typename _result_type_provider::_name_t;
|
||||
|
||||
// Constructors
|
||||
select_t()
|
||||
{}
|
||||
|
||||
template<typename Statement, typename Term>
|
||||
select_t(Statement statement, Term term):
|
||||
Policies::template _member_t<_policies_t>{
|
||||
typename Policies::template _impl_t<_policies_t>{
|
||||
detail::pick_arg<typename Policies::template _member_t<_policies_t>>(statement, term)
|
||||
}}...
|
||||
//Policies::template _member_t<_policies_t>{{detail::pick_arg<typename Policies::template _member_t<_policies_t>>(statement, term)}}...
|
||||
{}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
namespace vendor
|
||||
{
|
||||
template<typename Context, typename Database, typename... Policies>
|
||||
struct serializer_t<Context, select_t<Database, Policies...>>
|
||||
{
|
||||
using T = select_t<Database, Policies...>;
|
||||
using P = ::sqlpp::detail::select_policies_t<Database, Policies...>;
|
||||
|
||||
static Context& _(const T& t, Context& context)
|
||||
{
|
||||
context << "SELECT ";
|
||||
|
||||
using swallow = int[];
|
||||
(void) swallow{(serialize(static_cast<const typename Policies::template _member_t<P>&>(t)()._data, context), 0)...};
|
||||
|
||||
return context;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template<typename Database>
|
||||
using blank_select_t = select_t<Database,
|
||||
using blank_select_t = statement_t<Database,
|
||||
vendor::no_select_flag_list_t,
|
||||
vendor::no_select_column_list_t,
|
||||
vendor::no_from_t,
|
||||
|
193
include/sqlpp11/statement.h
Normal file
193
include/sqlpp11/statement.h
Normal file
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* 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_STATEMENT_H
|
||||
#define SQLPP_STATEMENT_H
|
||||
|
||||
#include <sqlpp11/result.h>
|
||||
#include <sqlpp11/parameter_list.h>
|
||||
#include <sqlpp11/prepared_select.h>
|
||||
#include <sqlpp11/vendor/policy_update.h>
|
||||
#include <sqlpp11/vendor/serializer.h>
|
||||
|
||||
#include <sqlpp11/detail/get_last.h>
|
||||
#include <sqlpp11/detail/pick_arg.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
template<typename Db, typename... Policies>
|
||||
struct statement_t;
|
||||
|
||||
#warning STEPS:
|
||||
#warning deal with different return types in the connector (select could be a single value, update could be a range of rows)
|
||||
namespace detail
|
||||
{
|
||||
template<typename Db = void, typename... Policies>
|
||||
struct statement_policies_t
|
||||
{
|
||||
#warning need to check policies' signature, e.g. a _data_t in _member_t template
|
||||
using _database_t = Db;
|
||||
using _statement_t = statement_t<Db, Policies...>;
|
||||
|
||||
struct _methods_t: public Policies::template _methods_t<statement_policies_t>...
|
||||
{};
|
||||
|
||||
template<typename Needle, typename Replacement>
|
||||
struct _policies_update_t
|
||||
{
|
||||
static_assert(detail::is_element_of<Needle, make_type_set_t<Policies...>>::value, "policies update for non-policy class detected");
|
||||
using type = statement_t<Db, vendor::policy_update_t<Policies, Needle, Replacement>...>;
|
||||
};
|
||||
|
||||
template<typename Needle, typename Replacement>
|
||||
using _new_statement_t = typename _policies_update_t<Needle, Replacement>::type;
|
||||
|
||||
using _all_required_tables = detail::make_joined_set_t<required_tables_of<Policies>...>;
|
||||
using _all_provided_tables = detail::make_joined_set_t<provided_tables_of<Policies>...>;
|
||||
using _all_extra_tables = detail::make_joined_set_t<extra_tables_of<Policies>...>;
|
||||
|
||||
using _known_tables = detail::make_joined_set_t<_all_provided_tables, _all_extra_tables>;
|
||||
|
||||
template<typename Expression>
|
||||
using _no_unknown_tables = detail::is_subset_of<required_tables_of<Expression>, _known_tables>;
|
||||
|
||||
// The tables not covered by the from.
|
||||
using _required_tables = detail::make_difference_set_t<
|
||||
_all_required_tables,
|
||||
_all_provided_tables // Hint: extra_tables are not used here because they are just a helper for dynamic .add_*()
|
||||
>;
|
||||
|
||||
using _result_type_provider = detail::get_last_if<is_return_value_t, vendor::noop, Policies...>;
|
||||
|
||||
struct _result_methods_t: public _result_type_provider::template _result_methods_t<statement_policies_t>
|
||||
{};
|
||||
|
||||
|
||||
// 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<_result_type_provider>::value and _required_tables::size::value == 0,
|
||||
std::true_type,
|
||||
std::false_type
|
||||
>::type;
|
||||
|
||||
using _value_type = typename std::conditional<
|
||||
detail::none_t<is_missing_t<Policies>::value...>::value,
|
||||
value_type_of<_result_type_provider>,
|
||||
no_value_t // if a required statement part is missing (e.g. columns in a select), then the statement cannot be used as a value
|
||||
>::type;
|
||||
|
||||
using _is_expression = typename std::conditional<
|
||||
std::is_same<_value_type, no_value_t>::value,
|
||||
std::false_type,
|
||||
std::true_type>::type;
|
||||
|
||||
using _traits = make_traits<_value_type>;
|
||||
|
||||
struct _recursive_traits
|
||||
{
|
||||
using _parameters = std::tuple<>; // FIXME
|
||||
using _required_tables = _required_tables;
|
||||
using _provided_tables = detail::type_set<>;
|
||||
using _extra_tables = detail::type_set<>;
|
||||
};
|
||||
|
||||
static void _check_consistency()
|
||||
{
|
||||
#warning check for missing terms here, and for missing tables
|
||||
static_assert(not required_tables_of<statement_policies_t>::size::value, "one sub expression requires tables which are otherwise not known in the statement");
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
// SELECT
|
||||
template<typename Db,
|
||||
typename... Policies
|
||||
>
|
||||
struct statement_t:
|
||||
public Policies::template _member_t<detail::statement_policies_t<Db, Policies...>>...,
|
||||
public detail::statement_policies_t<Db, Policies...>::_value_type::template expression_operators<statement_t<Db, Policies...>>,
|
||||
public detail::statement_policies_t<Db, Policies...>::_result_methods_t,
|
||||
public detail::statement_policies_t<Db, Policies...>::_methods_t
|
||||
{
|
||||
using _policies_t = typename detail::statement_policies_t<Db, Policies...>;
|
||||
|
||||
using _traits = make_traits<value_type_of<_policies_t>, ::sqlpp::tag::select, tag::expression_if<typename _policies_t::_is_expression>, tag::named_expression_if<typename _policies_t::_is_expression>>;
|
||||
using _recursive_traits = typename _policies_t::_recursive_traits;
|
||||
|
||||
using _result_type_provider = typename _policies_t::_result_type_provider;
|
||||
|
||||
using _requires_braces = std::true_type;
|
||||
|
||||
using _name_t = typename _result_type_provider::_name_t;
|
||||
|
||||
// Constructors
|
||||
statement_t()
|
||||
{}
|
||||
|
||||
template<typename Statement, typename Term>
|
||||
statement_t(Statement statement, Term term):
|
||||
Policies::template _member_t<_policies_t>{
|
||||
typename Policies::template _impl_t<_policies_t>{
|
||||
detail::pick_arg<typename Policies::template _member_t<_policies_t>>(statement, term)
|
||||
}}...
|
||||
//Policies::template _member_t<_policies_t>{{detail::pick_arg<typename Policies::template _member_t<_policies_t>>(statement, term)}}...
|
||||
{}
|
||||
|
||||
statement_t(const statement_t& r) = default;
|
||||
statement_t(statement_t&& r) = default;
|
||||
statement_t& operator=(const statement_t& r) = default;
|
||||
statement_t& operator=(statement_t&& r) = default;
|
||||
~statement_t() = default;
|
||||
};
|
||||
|
||||
namespace vendor
|
||||
{
|
||||
template<typename Context, typename Database, typename... Policies>
|
||||
struct serializer_t<Context, statement_t<Database, Policies...>>
|
||||
{
|
||||
using T = statement_t<Database, Policies...>;
|
||||
using P = ::sqlpp::detail::statement_policies_t<Database, Policies...>;
|
||||
|
||||
static Context& _(const T& t, Context& context)
|
||||
{
|
||||
#warning: Need to have a class that provides the "SELECT" or "INSERT", etc
|
||||
context << "SELECT ";
|
||||
|
||||
using swallow = int[];
|
||||
(void) swallow{(serialize(static_cast<const typename Policies::template _member_t<P>&>(t)()._data, context), 0)...};
|
||||
|
||||
return context;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
264
include/sqlpp11/vendor/insert_value_list.h
vendored
264
include/sqlpp11/vendor/insert_value_list.h
vendored
@ -39,17 +39,69 @@ namespace sqlpp
|
||||
{
|
||||
namespace vendor
|
||||
{
|
||||
struct insert_default_values_data_t
|
||||
{};
|
||||
|
||||
// COLUMN AND VALUE LIST
|
||||
struct insert_default_values_t
|
||||
{
|
||||
using _traits = make_traits<no_value_t>;
|
||||
using _recursive_traits = make_recursive_traits<>;
|
||||
|
||||
// Data
|
||||
using _data_t = insert_default_values_data_t;
|
||||
|
||||
// Member implementation with data and methods
|
||||
template<typename Policies>
|
||||
struct _impl_t
|
||||
{
|
||||
_data_t _data;
|
||||
};
|
||||
|
||||
// Member template for adding the named member to a statement
|
||||
template<typename Policies>
|
||||
struct _member_t
|
||||
{
|
||||
using _data_t = insert_default_values_data_t;
|
||||
|
||||
_impl_t<Policies> default_values;
|
||||
_impl_t<Policies>& operator()() { return default_values; }
|
||||
const _impl_t<Policies>& operator()() const { return default_values; }
|
||||
|
||||
template<typename T>
|
||||
static auto _get_member(T t) -> decltype(t.default_values)
|
||||
{
|
||||
return t.default_values;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Policies>
|
||||
struct _methods_t
|
||||
{};
|
||||
};
|
||||
|
||||
template<typename Database, typename... Assignments>
|
||||
struct insert_list_data_t
|
||||
{
|
||||
insert_list_data_t(Assignments... assignments):
|
||||
_assignments(assignments...),
|
||||
_columns({assignments._lhs}...),
|
||||
_values(assignments._rhs...)
|
||||
{}
|
||||
|
||||
insert_list_data_t(const insert_list_data_t&) = default;
|
||||
insert_list_data_t(insert_list_data_t&&) = default;
|
||||
insert_list_data_t& operator=(const insert_list_data_t&) = default;
|
||||
insert_list_data_t& operator=(insert_list_data_t&&) = default;
|
||||
~insert_list_data_t() = default;
|
||||
|
||||
std::tuple<simple_column_t<typename Assignments::_column_t>...> _columns;
|
||||
std::tuple<typename Assignments::_value_t...> _values;
|
||||
std::tuple<Assignments...> _assignments; // FIXME: Need to replace _columns and _values by _assignments (connector-container requires assignments)
|
||||
typename vendor::interpretable_list_t<Database> _dynamic_columns;
|
||||
typename vendor::interpretable_list_t<Database> _dynamic_values;
|
||||
};
|
||||
|
||||
template<typename Database, typename... Assignments>
|
||||
struct insert_list_t
|
||||
{
|
||||
@ -81,36 +133,26 @@ namespace sqlpp
|
||||
static_assert(::sqlpp::detail::is_subset_of<_value_required_tables, _column_required_tables>::value, "set() contains values from foreign tables");
|
||||
*/
|
||||
|
||||
insert_list_t& _insert_value_list() { return *this; }
|
||||
// Data
|
||||
using _data_t = insert_list_data_t<Database, Assignments...>;
|
||||
|
||||
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<typename Policies>
|
||||
struct _methods_t
|
||||
// Member implementation with data and methods
|
||||
template <typename Policies>
|
||||
struct _impl_t
|
||||
{
|
||||
template<typename Assignment>
|
||||
void add_set_ntc(Assignment assignment)
|
||||
void add_ntc(Assignment assignment)
|
||||
{
|
||||
add_set<Assignment, std::false_type>(assignment);
|
||||
add<Assignment, std::false_type>(assignment);
|
||||
}
|
||||
|
||||
template<typename Assignment, typename TableCheckRequired = std::true_type>
|
||||
void add_set(Assignment assignment)
|
||||
void add(Assignment assignment)
|
||||
{
|
||||
static_assert(_is_dynamic::value, "add_set must not be called for static from()");
|
||||
static_assert(is_assignment_t<Assignment>::value, "add_set() arguments require to be assigments");
|
||||
static_assert(not must_not_insert_t<typename Assignment::_column_t>::value, "add_set() argument must not be used in insert");
|
||||
static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value, "add_set() contains a column from a foreign table");
|
||||
static_assert(_is_dynamic::value, "add must not be called for static from()");
|
||||
static_assert(is_assignment_t<Assignment>::value, "add() arguments require to be assigments");
|
||||
static_assert(not must_not_insert_t<typename Assignment::_column_t>::value, "add() argument must not be used in insert");
|
||||
static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value, "add() contains a column from a foreign table");
|
||||
|
||||
using ok = ::sqlpp::detail::all_t<
|
||||
_is_dynamic::value,
|
||||
@ -118,28 +160,67 @@ namespace sqlpp
|
||||
not must_not_insert_t<typename Assignment::_column_t>::value,
|
||||
(not TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value)>;
|
||||
|
||||
_add_set_impl(assignment, ok()); // dispatch to prevent compile messages after the static_assert
|
||||
_add_impl(assignment, ok()); // dispatch to prevent compile messages after the static_assert
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename Assignment>
|
||||
void _add_set_impl(Assignment assignment, const std::true_type&)
|
||||
void _add_impl(Assignment assignment, const std::true_type&)
|
||||
{
|
||||
static_cast<typename Policies::_statement_t*>(this)->_insert_value_list()._dynamic_columns.emplace_back(simple_column_t<typename Assignment::_column_t>{assignment._lhs});
|
||||
static_cast<typename Policies::_statement_t*>(this)->_insert_value_list()._dynamic_values.emplace_back(assignment._rhs);
|
||||
_data._dynamic_columns.emplace_back(simple_column_t<typename Assignment::_column_t>{assignment._lhs});
|
||||
_data._dynamic_values.emplace_back(assignment._rhs);
|
||||
}
|
||||
|
||||
template<typename Assignment>
|
||||
void _add_set_impl(Assignment assignment, const std::false_type&);
|
||||
void _add_impl(Assignment assignment, const std::false_type&);
|
||||
public:
|
||||
_data_t _data;
|
||||
};
|
||||
|
||||
// Member template for adding the named member to a statement
|
||||
template<typename Policies>
|
||||
struct _member_t
|
||||
{
|
||||
using _data_t = insert_list_data_t<Database, Assignments...>;
|
||||
|
||||
_impl_t<Policies> insert_list;
|
||||
_impl_t<Policies>& operator()() { return insert_list; }
|
||||
const _impl_t<Policies>& operator()() const { return insert_list; }
|
||||
|
||||
template<typename T>
|
||||
static auto _get_member(T t) -> decltype(t.insert_list)
|
||||
{
|
||||
return t.insert_list;
|
||||
}
|
||||
};
|
||||
|
||||
// Additional methods for the statement
|
||||
template<typename Policies>
|
||||
struct _methods_t
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
|
||||
std::tuple<simple_column_t<typename Assignments::_column_t>...> _columns;
|
||||
std::tuple<typename Assignments::_value_t...> _values;
|
||||
std::tuple<Assignments...> _assignments; // FIXME: Need to replace _columns and _values by _assignments (connector-container requires assignments)
|
||||
typename vendor::interpretable_list_t<Database> _dynamic_columns;
|
||||
typename vendor::interpretable_list_t<Database> _dynamic_values;
|
||||
};
|
||||
|
||||
template<typename... Columns>
|
||||
struct column_list_data_t
|
||||
{
|
||||
column_list_data_t(Columns... columns):
|
||||
_columns(simple_column_t<Columns>{columns}...)
|
||||
{}
|
||||
|
||||
column_list_data_t(const column_list_data_t&) = default;
|
||||
column_list_data_t(column_list_data_t&&) = default;
|
||||
column_list_data_t& operator=(const column_list_data_t&) = default;
|
||||
column_list_data_t& operator=(column_list_data_t&&) = default;
|
||||
~column_list_data_t() = default;
|
||||
|
||||
#warning need to define just one version of value_tuple_t
|
||||
using _value_tuple_t = std::tuple<vendor::insert_value_t<Columns>...>;
|
||||
std::tuple<simple_column_t<Columns>...> _columns;
|
||||
std::vector<_value_tuple_t> _insert_values;
|
||||
};
|
||||
|
||||
template<typename... Columns>
|
||||
@ -160,23 +241,15 @@ namespace sqlpp
|
||||
|
||||
static_assert(required_tables_of<column_list_t>::size::value == 1, "columns from multiple tables in columns()");
|
||||
|
||||
column_list_t& _insert_value_list() { return *this; }
|
||||
// Data
|
||||
using _data_t = column_list_data_t<Columns...>;
|
||||
|
||||
column_list_t(Columns... columns):
|
||||
_columns(simple_column_t<Columns>{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;
|
||||
|
||||
template<typename Policies>
|
||||
struct _methods_t
|
||||
// Member implementation with data and methods
|
||||
template <typename Policies>
|
||||
struct _impl_t
|
||||
{
|
||||
template<typename... Assignments>
|
||||
void add_values(Assignments... assignments)
|
||||
void add(Assignments... assignments)
|
||||
{
|
||||
static_assert(::sqlpp::detail::all_t<is_assignment_t<Assignments>::value...>::value, "add_values() arguments have to be assignments");
|
||||
using _arg_value_tuple = std::tuple<vendor::insert_value_t<typename Assignments::_column_t>...>;
|
||||
@ -187,35 +260,87 @@ namespace sqlpp
|
||||
::sqlpp::detail::all_t<is_assignment_t<Assignments>::value...>::value,
|
||||
_args_correct::value>;
|
||||
|
||||
_add_values_impl(ok(), assignments...); // dispatch to prevent compile messages after the static_assert
|
||||
_add_impl(ok(), assignments...); // dispatch to prevent compile messages after the static_assert
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename... Assignments>
|
||||
void _add_values_impl(const std::true_type&, Assignments... assignments)
|
||||
void _add_impl(const std::true_type&, Assignments... assignments)
|
||||
{
|
||||
return static_cast<typename Policies::_statement_t*>(this)->_insert_value_list()._insert_values.emplace_back(vendor::insert_value_t<typename Assignments::_column_t>{assignments}...);
|
||||
return _data._insert_values.emplace_back(vendor::insert_value_t<typename Assignments::_column_t>{assignments}...);
|
||||
}
|
||||
|
||||
template<typename... Assignments>
|
||||
void _add_values_impl(const std::false_type&, Assignments... assignments);
|
||||
void _add_impl(const std::false_type&, Assignments... assignments);
|
||||
public:
|
||||
_data_t _data;
|
||||
};
|
||||
|
||||
// Member template for adding the named member to a statement
|
||||
template<typename Policies>
|
||||
struct _member_t
|
||||
{
|
||||
using _data_t = column_list_data_t<Columns...>;
|
||||
|
||||
_impl_t<Policies> column_list;
|
||||
_impl_t<Policies>& operator()() { return column_list; }
|
||||
const _impl_t<Policies>& operator()() const { return column_list; }
|
||||
|
||||
template<typename T>
|
||||
static auto _get_member(T t) -> decltype(t.column_list)
|
||||
{
|
||||
return t.column_list;
|
||||
}
|
||||
};
|
||||
|
||||
// Additional methods for the statement
|
||||
template<typename Policies>
|
||||
struct _methods_t
|
||||
{
|
||||
};
|
||||
|
||||
/*
|
||||
bool empty() const
|
||||
{
|
||||
return _insert_values.empty();
|
||||
}
|
||||
|
||||
std::tuple<simple_column_t<Columns>...> _columns;
|
||||
std::vector<_value_tuple_t> _insert_values;
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
// NO HAVING YET
|
||||
struct no_insert_value_list_t
|
||||
{
|
||||
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
|
||||
using _recursive_traits = make_recursive_traits<>;
|
||||
|
||||
// Data
|
||||
using _data_t = no_data_t;
|
||||
|
||||
// Member implementation with data and methods
|
||||
template<typename Policies>
|
||||
struct _impl_t
|
||||
{
|
||||
_data_t _data;
|
||||
};
|
||||
|
||||
// Member template for adding the named member to a statement
|
||||
template<typename Policies>
|
||||
struct _member_t
|
||||
{
|
||||
using _data_t = no_data_t;
|
||||
|
||||
_impl_t<Policies> no_insert_values;
|
||||
_impl_t<Policies>& operator()() { return no_insert_values; }
|
||||
const _impl_t<Policies>& operator()() const { return no_insert_values; }
|
||||
|
||||
template<typename T>
|
||||
static auto _get_member(T t) -> decltype(t.no_insert_values)
|
||||
{
|
||||
return t.no_insert_values;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Policies>
|
||||
struct _methods_t
|
||||
{
|
||||
@ -226,21 +351,21 @@ namespace sqlpp
|
||||
auto default_values()
|
||||
-> _new_statement_t<insert_default_values_t>
|
||||
{
|
||||
return { *static_cast<typename Policies::_statement_t*>(this), insert_default_values_t{} };
|
||||
return { *static_cast<typename Policies::_statement_t*>(this), insert_default_values_data_t{} };
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
auto columns(Args... args)
|
||||
-> _new_statement_t<column_list_t<Args...>>
|
||||
{
|
||||
return { *static_cast<typename Policies::_statement_t*>(this), column_list_t<Args...>{args...} };
|
||||
return { *static_cast<typename Policies::_statement_t*>(this), column_list_data_t<Args...>{args...} };
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
auto set(Args... args)
|
||||
-> _new_statement_t<insert_list_t<void, Args...>>
|
||||
{
|
||||
return { *static_cast<typename Policies::_statement_t*>(this), insert_list_t<void, Args...>{args...} };
|
||||
return { *static_cast<typename Policies::_statement_t*>(this), insert_list_data_t<void, Args...>{args...} };
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
@ -248,16 +373,16 @@ namespace sqlpp
|
||||
-> _new_statement_t<insert_list_t<_database_t, Args...>>
|
||||
{
|
||||
static_assert(not std::is_same<_database_t, void>::value, "dynamic_set must not be called in a static statement");
|
||||
return { *static_cast<typename Policies::_statement_t*>(this), vendor::insert_list_t<_database_t, Args...>{args...} };
|
||||
return { *static_cast<typename Policies::_statement_t*>(this), vendor::insert_list_data_t<_database_t, Args...>{args...} };
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Interpreters
|
||||
template<typename Context>
|
||||
struct serializer_t<Context, insert_default_values_t>
|
||||
struct serializer_t<Context, insert_default_values_data_t>
|
||||
{
|
||||
using T = insert_default_values_t;
|
||||
using T = insert_default_values_data_t;
|
||||
|
||||
static Context& _(const T& t, Context& context)
|
||||
{
|
||||
@ -267,9 +392,9 @@ namespace sqlpp
|
||||
};
|
||||
|
||||
template<typename Context, typename... Columns>
|
||||
struct serializer_t<Context, column_list_t<Columns...>>
|
||||
struct serializer_t<Context, column_list_data_t<Columns...>>
|
||||
{
|
||||
using T = column_list_t<Columns...>;
|
||||
using T = column_list_data_t<Columns...>;
|
||||
|
||||
static Context& _(const T& t, Context& context)
|
||||
{
|
||||
@ -294,15 +419,15 @@ namespace sqlpp
|
||||
};
|
||||
|
||||
template<typename Context, typename Database, typename... Assignments>
|
||||
struct serializer_t<Context, insert_list_t<Database, Assignments...>>
|
||||
struct serializer_t<Context, insert_list_data_t<Database, Assignments...>>
|
||||
{
|
||||
using T = insert_list_t<Database, Assignments...>;
|
||||
using T = insert_list_data_t<Database, Assignments...>;
|
||||
|
||||
static Context& _(const T& t, Context& context)
|
||||
{
|
||||
if (sizeof...(Assignments) + t._dynamic_columns.size() == 0)
|
||||
{
|
||||
serialize(insert_default_values_t(), context);
|
||||
serialize(insert_default_values_data_t(), context);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -322,17 +447,6 @@ namespace sqlpp
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Context>
|
||||
struct serializer_t<Context, no_insert_value_list_t>
|
||||
{
|
||||
using T = no_insert_value_list_t;
|
||||
|
||||
static Context& _(const T& t, Context& context)
|
||||
{
|
||||
return context;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
140
include/sqlpp11/vendor/single_table.h
vendored
140
include/sqlpp11/vendor/single_table.h
vendored
@ -36,39 +36,151 @@ namespace sqlpp
|
||||
{
|
||||
namespace vendor
|
||||
{
|
||||
// A SINGLE TABLE DATA
|
||||
template<typename Database, typename Table>
|
||||
struct single_table_data_t
|
||||
{
|
||||
single_table_data_t(Table table):
|
||||
_table(table)
|
||||
{}
|
||||
|
||||
single_table_data_t(const single_table_data_t&) = default;
|
||||
single_table_data_t(single_table_data_t&&) = default;
|
||||
single_table_data_t& operator=(const single_table_data_t&) = default;
|
||||
single_table_data_t& operator=(single_table_data_t&&) = default;
|
||||
~single_table_data_t() = default;
|
||||
|
||||
Table _table;
|
||||
};
|
||||
|
||||
// A SINGLE TABLE
|
||||
template<typename Database, typename Table>
|
||||
struct single_table_t
|
||||
{
|
||||
using _traits = make_traits<no_value_t, ::sqlpp::tag::single_table>;
|
||||
using _traits = make_traits<no_value_t, ::sqlpp::tag::single_table, tag::return_value>;
|
||||
using _recursive_traits = make_recursive_traits<Table>;
|
||||
|
||||
static_assert(is_table_t<Table>::value, "argument has to be a table");
|
||||
static_assert(required_tables_of<Table>::size::value == 0, "table depends on another table");
|
||||
|
||||
single_table_t(Table table):
|
||||
_table(table)
|
||||
{}
|
||||
using _data_t = single_table_data_t<Database, Table>;
|
||||
|
||||
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;
|
||||
struct _name_t {};
|
||||
|
||||
// Member implementation with data and methods
|
||||
template <typename Policies>
|
||||
struct _impl_t
|
||||
{
|
||||
_data_t _data;
|
||||
};
|
||||
|
||||
// Member template for adding the named member to a statement
|
||||
template<typename Policies>
|
||||
struct _member_t
|
||||
{
|
||||
using _data_t = single_table_data_t<Database, Table>;
|
||||
|
||||
_impl_t<Policies> into;
|
||||
_impl_t<Policies>& operator()() { return into; }
|
||||
const _impl_t<Policies>& operator()() const { return into; }
|
||||
|
||||
template<typename T>
|
||||
static auto _get_member(T t) -> decltype(t.into)
|
||||
{
|
||||
return t.into;
|
||||
}
|
||||
};
|
||||
|
||||
// Additional methods for the statement
|
||||
template<typename Policies>
|
||||
struct _methods_t
|
||||
{
|
||||
};
|
||||
|
||||
Table _table;
|
||||
template<typename Policies>
|
||||
struct _result_methods_t
|
||||
{
|
||||
using _statement_t = typename Policies::_statement_t;
|
||||
|
||||
const _statement_t& _get_statement() const
|
||||
{
|
||||
return static_cast<const _statement_t&>(*this);
|
||||
}
|
||||
|
||||
static constexpr size_t _get_static_no_of_parameters()
|
||||
{
|
||||
#warning need to fix this
|
||||
return 0;
|
||||
//return _parameter_list_t::size::value;
|
||||
}
|
||||
|
||||
size_t _get_no_of_parameters() const
|
||||
{
|
||||
#warning need to fix this
|
||||
return 0;
|
||||
//return _parameter_list_t::size::value;
|
||||
}
|
||||
|
||||
void _check_consistency() const
|
||||
{
|
||||
// FIXME: Read up on what is allowed/prohibited in INSERT
|
||||
}
|
||||
|
||||
template<typename Db>
|
||||
auto _run(Db& db) const -> decltype(db.insert(_get_statement()))
|
||||
{
|
||||
_check_consistency();
|
||||
|
||||
static_assert(_get_static_no_of_parameters() == 0, "cannot run insert directly with parameters, use prepare instead");
|
||||
return db.insert(*this);
|
||||
}
|
||||
|
||||
/*
|
||||
template<typename Db>
|
||||
auto _prepare(Db& db) const
|
||||
-> prepared_insert_t<Db, insert_t>
|
||||
{
|
||||
_check_consistency();
|
||||
|
||||
return {{}, db.prepare_insert(*this)};
|
||||
}
|
||||
*/
|
||||
};
|
||||
};
|
||||
|
||||
// NO INTO YET
|
||||
struct no_single_table_t
|
||||
{
|
||||
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
|
||||
using _recursive_traits = make_recursive_traits<>;
|
||||
|
||||
// Data
|
||||
using _data_t = no_data_t;
|
||||
|
||||
// Member implementation with data and methods
|
||||
template<typename Policies>
|
||||
struct _impl_t
|
||||
{
|
||||
_data_t _data;
|
||||
};
|
||||
|
||||
// Member template for adding the named member to a statement
|
||||
template<typename Policies>
|
||||
struct _member_t
|
||||
{
|
||||
using _data_t = no_data_t;
|
||||
|
||||
_impl_t<Policies> no_into;
|
||||
_impl_t<Policies>& operator()() { return no_into; }
|
||||
const _impl_t<Policies>& operator()() const { return no_into; }
|
||||
|
||||
template<typename T>
|
||||
static auto _get_member(T t) -> decltype(t.no_into)
|
||||
{
|
||||
return t.no_into;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Policies>
|
||||
struct _methods_t
|
||||
{
|
||||
@ -80,7 +192,7 @@ namespace sqlpp
|
||||
auto into(Args... args)
|
||||
-> _new_statement_t<single_table_t<void, Args...>>
|
||||
{
|
||||
return { *static_cast<typename Policies::_statement_t*>(this), single_table_t<void, Args...>{args...} };
|
||||
return { *static_cast<typename Policies::_statement_t*>(this), single_table_data_t<void, Args...>{args...} };
|
||||
}
|
||||
|
||||
#warning: remove can operate on several tables at once, so it should not use single_table anyway
|
||||
@ -88,16 +200,16 @@ namespace sqlpp
|
||||
auto from(Args... args)
|
||||
-> _new_statement_t<single_table_t<void, Args...>>
|
||||
{
|
||||
return { *static_cast<typename Policies::_statement_t*>(this), single_table_t<void, Args...>{args...} };
|
||||
return { *static_cast<typename Policies::_statement_t*>(this), single_table_data_t<void, Args...>{args...} };
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Interpreters
|
||||
template<typename Context, typename Database, typename Table>
|
||||
struct serializer_t<Context, single_table_t<Database, Table>>
|
||||
struct serializer_t<Context, single_table_data_t<Database, Table>>
|
||||
{
|
||||
using T = single_table_t<Database, Table>;
|
||||
using T = single_table_data_t<Database, Table>;
|
||||
|
||||
static Context& _(const T& t, Context& context)
|
||||
{
|
||||
|
@ -7,11 +7,11 @@ macro (build_and_run arg)
|
||||
endmacro ()
|
||||
|
||||
#build_and_run(InterpretTest)
|
||||
#build_and_run(InsertTest)
|
||||
build_and_run(InsertTest)
|
||||
#build_and_run(RemoveTest)
|
||||
#build_and_run(UpdateTest)
|
||||
#build_and_run(SelectTest)
|
||||
build_and_run(SelectTypeTest)
|
||||
#build_and_run(SelectTypeTest)
|
||||
#build_and_run(FunctionTest)
|
||||
#build_and_run(PreparedTest)
|
||||
|
||||
|
@ -67,10 +67,10 @@ int main()
|
||||
serialize(insert_into(t).set(t.beta = "kirschauflauf"), printer).str();
|
||||
serialize(insert_into(t).columns(t.beta), printer).str();
|
||||
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);
|
||||
multi_insert.column_list.add(t.beta = "cheesecake", t.delta = 1);
|
||||
multi_insert.column_list.add(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");
|
||||
i.insert_list.add(t.beta = "kirschauflauf");
|
||||
serialize(i, printer).str();
|
||||
|
||||
db(multi_insert);
|
||||
|
Loading…
Reference in New Issue
Block a user