0
0
mirror of https://github.com/rbock/sqlpp11.git synced 2024-11-16 04:47:18 +08:00

Merge branch 'feature/crtp-to-composition-for-statements' into develop

This commit is contained in:
rbock 2014-02-13 08:45:14 +01:00
commit 3e9eab8773
45 changed files with 937 additions and 811 deletions

View File

@ -27,8 +27,8 @@
#ifndef SQLPP_ANY_H #ifndef SQLPP_ANY_H
#define SQLPP_ANY_H #define SQLPP_ANY_H
#include <sstream>
#include <sqlpp11/boolean.h> #include <sqlpp11/boolean.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp 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): any_t(Select select):
_select(select) _select(select)
{} {}

View File

@ -84,6 +84,14 @@ namespace sqlpp
return { *this, {t} }; return { *this, {t} };
} }
template<typename T>
auto operator =(T t) const
-> typename std::enable_if<not(_value_type::template _constraint<typename vendor::wrap_operand<T>::type>::value and not std::is_same<column_t, T>::value),
vendor::assignment_t<column_t, typename vendor::wrap_operand<T>::type>>::type
{
static_assert(sqlpp::vendor::wrong_t<T>::value, "invalid assignment operand");
}
auto operator =(sqlpp::null_t) const auto operator =(sqlpp::null_t) const
->vendor::assignment_t<column_t, sqlpp::null_t> ->vendor::assignment_t<column_t, sqlpp::null_t>
{ {

View File

@ -35,6 +35,7 @@ namespace sqlpp
{ {
static constexpr bool _is_expression = true; static constexpr bool _is_expression = true;
using _value_type = no_value_t; using _value_type = no_value_t;
using _table_set = ::sqlpp::detail::type_set<>;
static constexpr bool _is_trivial() { return false; } static constexpr bool _is_trivial() { return false; }
}; };

View File

@ -47,6 +47,7 @@ namespace sqlpp
template<typename T> template<typename T>
auto value(T t) -> typename operand_t<T, is_value_t>::type auto value(T t) -> typename operand_t<T, is_value_t>::type
{ {
using _table_set = ::sqlpp::detail::type_set<>;
static_assert(not is_value_t<T>::value, "value() is to be called with non-sql-type like int, or string"); static_assert(not is_value_t<T>::value, "value() is to be called with non-sql-type like int, or string");
return { t }; return { t };
} }
@ -55,6 +56,7 @@ namespace sqlpp
struct verbatim_t: public ValueType::template operators<verbatim_t<ValueType>> struct verbatim_t: public ValueType::template operators<verbatim_t<ValueType>>
{ {
using _value_type = ValueType; using _value_type = ValueType;
using _table_set = ::sqlpp::detail::type_set<>;
verbatim_t(std::string verbatim): _verbatim(verbatim) {} verbatim_t(std::string verbatim): _verbatim(verbatim) {}
verbatim_t(const verbatim_t&) = default; verbatim_t(const verbatim_t&) = default;
@ -100,6 +102,7 @@ namespace sqlpp
struct value_list_t // to be used in .in() method struct value_list_t // to be used in .in() method
{ {
using _container_t = Container; using _container_t = Container;
using _table_set = ::sqlpp::detail::type_set<>;// FIXME: Could it be something else?
using _value_type = typename operand_t<typename _container_t::value_type, is_value_t>::type::_value_type; using _value_type = typename operand_t<typename _container_t::value_type, is_value_t>::type::_value_type;
value_list_t(_container_t container): value_list_t(_container_t container):

View File

@ -34,49 +34,49 @@
#include <sqlpp11/vendor/noop.h> #include <sqlpp11/vendor/noop.h>
#include <sqlpp11/vendor/single_table.h> #include <sqlpp11/vendor/single_table.h>
#include <sqlpp11/vendor/insert_value_list.h> #include <sqlpp11/vendor/insert_value_list.h>
#include <sqlpp11/vendor/crtp_wrapper.h>
#include <sqlpp11/vendor/policy.h>
#include <sqlpp11/vendor/policy_update.h> #include <sqlpp11/vendor/policy_update.h>
namespace sqlpp namespace sqlpp
{ {
namespace detail // INSERT
{ template<typename Database = void,
template< typename Table = vendor::no_single_table_t,
typename Table, typename InsertValueList = vendor::no_insert_value_list_t
typename InsertValueList
> >
struct check_insert_t struct insert_t
{ {
static_assert(Table::_table_set::template is_superset_of<typename InsertValueList::_table_set>::value, "inserted columns do not match the table in insert_into"); static_assert(Table::_table_set::template is_superset_of<typename InsertValueList::_table_set>::value, "columns do not match the table they are to be inserted into");
//static_assert(not (vendor::is_noop<InsertList>::value and vendor::is_noop<ColumnList>::value) , "calling set() or default_values()");
static constexpr bool value = true;
};
}
template<typename Database, typename... Policies>
struct insert_t: public vendor::policy_t<Policies>..., public vendor::crtp_wrapper_t<insert_t<Database, Policies...>, Policies>...
{
template<typename Needle, typename Replacement>
using _policy_update_t = insert_t<Database, vendor::policy_update_t<Policies, Needle, Replacement>...>;
using _database_t = Database; using _database_t = Database;
using _parameter_tuple_t = std::tuple<Policies...>; using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
using _table_set = typename Table::_table_set;
template<typename Needle, typename Replacement, typename... Policies>
struct _policies_update_impl
{
using type = insert_t<Database, vendor::policy_update_t<Policies, Needle, Replacement>...>;
};
template<typename Needle, typename Replacement>
using _policies_update_t = typename _policies_update_impl<Needle, Replacement, Table, InsertValueList>::type;
using _parameter_tuple_t = std::tuple<Table, InsertValueList>;
using _parameter_list_t = typename make_parameter_list_t<insert_t>::type; using _parameter_list_t = typename make_parameter_list_t<insert_t>::type;
// Constructors
insert_t() insert_t()
{} {}
static_assert(detail::check_insert_t<Policies...>::value, "invalid insert_into"); template<typename X>
insert_t(X x, Table table):
template<typename Whatever> _table(table),
insert_t(insert_t i, Whatever whatever): _insert_value_list(x._insert_value_list)
vendor::policy_t<Policies>(i, whatever)...
{} {}
template<typename Insert, typename Whatever> template<typename X>
insert_t(Insert i, Whatever whatever): insert_t(X x, InsertValueList insert_value_list):
vendor::policy_t<Policies>(i, whatever)... _table(x._table),
_insert_value_list(insert_value_list)
{} {}
insert_t(const insert_t&) = default; insert_t(const insert_t&) = default;
@ -85,6 +85,56 @@ namespace sqlpp
insert_t& operator=(insert_t&&) = default; insert_t& operator=(insert_t&&) = default;
~insert_t() = default; ~insert_t() = default;
// type update functions
auto default_values()
-> _policies_update_t<vendor::no_insert_value_list_t, vendor::insert_default_values_t>
{
static_assert(is_noop_t<InsertValueList>::value, "cannot combine default_values() with other methods");
return { *this, vendor::insert_default_values_t{} };
}
template<typename... Args>
auto columns(Args... args)
-> _policies_update_t<vendor::no_insert_value_list_t, vendor::column_list_t<Args...>>
{
static_assert(is_noop_t<InsertValueList>::value, "cannot combine columns() with other methods");
return { *this, vendor::column_list_t<Args...>{args...} };
}
template<typename... Args>
auto set(Args... args)
-> _policies_update_t<vendor::no_insert_value_list_t, vendor::insert_list_t<void, Args...>>
{
static_assert(is_noop_t<InsertValueList>::value, "cannot combine set() with other methods");
return { *this, vendor::insert_list_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_set(Args... args)
-> _policies_update_t<vendor::no_insert_value_list_t, vendor::insert_list_t<_database_t, Args...>>
{
static_assert(is_noop_t<InsertValueList>::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<typename... Args>
void add_set(Args... args)
{
static_assert(is_insert_list_t<InsertValueList>::value, "cannot call add_set() before dynamic_set()");
static_assert(is_dynamic_t<InsertValueList>::value, "cannot call add_set() before dynamic_set()");
return _insert_value_list.add_set(*this, args...);
}
template<typename... Args>
void add_values(Args... args)
{
static_assert(is_column_list_t<InsertValueList>::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() static constexpr size_t _get_static_no_of_parameters()
{ {
return _parameter_list_t::size::value; return _parameter_list_t::size::value;
@ -99,7 +149,6 @@ namespace sqlpp
std::size_t _run(Db& db) const 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(_get_static_no_of_parameters() == 0, "cannot run insert directly with parameters, use prepare instead");
static_assert(detail::check_insert_t<Policies...>::value, "Cannot run this insert expression");
return db.insert(*this); return db.insert(*this);
} }
@ -107,9 +156,11 @@ namespace sqlpp
auto _prepare(Db& db) const auto _prepare(Db& db) const
-> prepared_insert_t<Db, insert_t> -> prepared_insert_t<Db, insert_t>
{ {
static_assert(detail::check_insert_t<Policies...>::value, "Cannot prepare this insert expression");
return {{}, db.prepare_insert(*this)}; return {{}, db.prepare_insert(*this)};
} }
InsertValueList _insert_value_list;
Table _table;
}; };
namespace vendor namespace vendor
@ -122,28 +173,25 @@ namespace sqlpp
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
context << "INSERT INTO "; context << "INSERT INTO ";
interpret(t._single_table(), context); interpret(t._table, context);
interpret(t._insert_value_list(), context); interpret(t._insert_value_list, context);
return context; return context;
} }
}; };
} }
template<typename Database>
using blank_insert_t = insert_t<Database, vendor::no_single_table_t, vendor::no_insert_value_list_t>;
template<typename Table> template<typename Table>
constexpr auto insert_into(Table table) constexpr auto insert_into(Table table)
-> insert_t<void, vendor::single_table_t<void, Table>, vendor::no_insert_value_list_t> -> insert_t<void, vendor::single_table_t<void, Table>>
{ {
return { blank_insert_t<void>(), vendor::single_table_t<void, Table>{table} }; return { insert_t<void>(), vendor::single_table_t<void, Table>{table} };
} }
template<typename Database, typename Table> template<typename Database, typename Table>
constexpr auto dynamic_insert_into(const Database&, Table table) constexpr auto dynamic_insert_into(const Database&, Table table)
-> insert_t<Database, vendor::single_table_t<void, Table>, vendor::no_insert_value_list_t> -> insert_t<Database, vendor::single_table_t<void, Table>>
{ {
return { blank_insert_t<Database>(), vendor::single_table_t<void, Table>{table} }; return { insert_t<Database>(), vendor::single_table_t<void, Table>{table} };
} }
} }

View File

@ -35,6 +35,7 @@ namespace sqlpp
{ {
static constexpr bool _is_expression = true; static constexpr bool _is_expression = true;
using _value_type = no_value_t; using _value_type = no_value_t;
using _table_set = ::sqlpp::detail::type_set<>;
static constexpr bool _is_trivial() { return false; } static constexpr bool _is_trivial() { return false; }
}; };

View File

@ -28,6 +28,7 @@
#define SQLPP_PARAMETER_H #define SQLPP_PARAMETER_H
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp namespace sqlpp
{ {
@ -38,6 +39,7 @@ namespace sqlpp
using _is_parameter = std::true_type; using _is_parameter = std::true_type;
using _is_expression_t = std::true_type; using _is_expression_t = std::true_type;
using _instance_t = typename NameType::_name_t::template _member_t<typename ValueType::_parameter_t>; using _instance_t = typename NameType::_name_t::template _member_t<typename ValueType::_parameter_t>;
using _table_set = sqlpp::detail::type_set<>;
parameter_t() parameter_t()
{} {}

View File

@ -34,8 +34,6 @@
#include <sqlpp11/vendor/single_table.h> #include <sqlpp11/vendor/single_table.h>
#include <sqlpp11/vendor/using.h> #include <sqlpp11/vendor/using.h>
#include <sqlpp11/vendor/where.h> #include <sqlpp11/vendor/where.h>
#include <sqlpp11/vendor/crtp_wrapper.h>
#include <sqlpp11/vendor/policy.h>
#include <sqlpp11/vendor/policy_update.h> #include <sqlpp11/vendor/policy_update.h>
namespace sqlpp namespace sqlpp
@ -50,27 +48,52 @@ namespace sqlpp
}; };
} }
template<typename Database, typename... Policies> // REMOVE
struct remove_t: public vendor::policy_t<Policies>..., public vendor::crtp_wrapper_t<remove_t<Database, Policies...>, Policies>... template<typename Database,
typename Table = vendor::no_single_table_t,
typename Using = vendor::no_using_t,
typename Where = vendor::no_where_t
>
struct remove_t
{ {
template<typename Needle, typename Replacement>
using _policy_update_t = remove_t<Database, vendor::policy_update_t<Policies, Needle, Replacement>...>;
using _database_t = Database; using _database_t = Database;
using _parameter_tuple_t = std::tuple<Policies...>; using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
template<typename Needle, typename Replacement, typename... Policies>
struct _policies_update_impl
{
using type = remove_t<Database, vendor::policy_update_t<Policies, Needle, Replacement>...>;
};
template<typename Needle, typename Replacement>
using _policies_update_t = typename _policies_update_impl<Needle, Replacement, Table, Using, Where>::type;
using _parameter_tuple_t = std::tuple<Table, Using, Where>;
using _parameter_list_t = typename make_parameter_list_t<remove_t>::type; using _parameter_list_t = typename make_parameter_list_t<remove_t>::type;
// Constructors
remove_t() remove_t()
{} {}
template<typename Whatever> template<typename X>
remove_t(remove_t r, Whatever whatever): remove_t(X x, Table table):
vendor::policy_t<Policies>(r, whatever)... _table(table),
_using(x._using),
_where(x._where)
{} {}
template<typename Remove, typename Whatever> template<typename X>
remove_t(Remove r, Whatever whatever): remove_t(X x, Using using_):
vendor::policy_t<Policies>(r, whatever)... _table(x._table),
_using(using_),
_where(x._where)
{}
template<typename X>
remove_t(X x, Where where):
_table(x._table),
_using(x._using),
_where(where)
{} {}
remove_t(const remove_t&) = default; remove_t(const remove_t&) = default;
@ -79,6 +102,59 @@ namespace sqlpp
remove_t& operator=(remove_t&&) = default; remove_t& operator=(remove_t&&) = default;
~remove_t() = default; ~remove_t() = default;
// type update functions
template<typename... Args>
auto using_(Args... args)
-> _policies_update_t<vendor::no_using_t, vendor::using_t<void, Args...>>
{
static_assert(is_noop_t<Using>::value, "cannot call using_()/dynamic_using() twice");
return { *this, vendor::using_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_using(Args... args)
-> _policies_update_t<vendor::no_using_t, vendor::using_t<_database_t, Args...>>
{
static_assert(is_noop_t<Using>::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<typename... Args>
auto where(Args... args)
-> _policies_update_t<vendor::no_where_t, vendor::where_t<void, Args...>>
{
static_assert(is_noop_t<Where>::value, "cannot call where()/dynamic_where() twice");
return { *this, vendor::where_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_where(Args... args)
-> _policies_update_t<vendor::no_where_t, vendor::where_t<_database_t, Args...>>
{
static_assert(is_noop_t<Where>::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<typename... Args>
void add_using(Args... args)
{
static_assert(is_using_t<Using>::value, "cannot call add_using() before dynamic_using()");
static_assert(is_dynamic_t<Using>::value, "cannot call add_using() before dynamic_using()");
return _using.add_using(args...);
}
template<typename... Args>
void add_where(Args... args)
{
static_assert(is_where_t<Where>::value, "cannot call add_where() before dynamic_where()");
static_assert(is_dynamic_t<Where>::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() static constexpr size_t _get_static_no_of_parameters()
{ {
return _parameter_list_t::size::value; return _parameter_list_t::size::value;
@ -93,7 +169,7 @@ namespace sqlpp
std::size_t _run(Db& db) const 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(_get_static_no_of_parameters() == 0, "cannot run remove directly with parameters, use prepare instead");
static_assert(detail::check_remove_t<Policies...>::value, "Cannot run this remove expression"); //static_assert(detail::check_remove_t<Policies...>::value, "Cannot run this remove expression");
return db.remove(*this); return db.remove(*this);
} }
@ -101,9 +177,13 @@ namespace sqlpp
auto _prepare(Db& db) const auto _prepare(Db& db) const
-> prepared_remove_t<Database, remove_t> -> prepared_remove_t<Database, remove_t>
{ {
static_assert(detail::check_remove_t<Policies...>::value, "Cannot run this remove expression"); //static_assert(detail::check_remove_t<Policies...>::value, "Cannot run this remove expression");
return {{}, db.prepare_remove(*this)}; return {{}, db.prepare_remove(*this)};
} }
Table _table;
Using _using;
Where _where;
}; };
namespace vendor namespace vendor
@ -116,29 +196,26 @@ namespace sqlpp
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
context << "DELETE FROM"; context << "DELETE FROM";
interpret(t._single_table(), context); interpret(t._table, context);
interpret(t._using(), context); interpret(t._using, context);
interpret(t._where(), context); interpret(t._where, context);
return context; return context;
} }
}; };
} }
template<typename Database>
using blank_remove_t = remove_t<Database, vendor::no_single_table_t, vendor::no_using_t, vendor::no_where_t>;
template<typename Table> template<typename Table>
constexpr auto remove_from(Table table) constexpr auto remove_from(Table table)
-> remove_t<void, vendor::single_table_t<void, Table>, vendor::no_using_t, vendor::no_where_t> -> remove_t<void, vendor::single_table_t<void, Table>>
{ {
return { blank_remove_t<void>(), vendor::single_table_t<void, Table>{table} }; return { remove_t<void>(), vendor::single_table_t<void, Table>{table} };
} }
template<typename Database, typename Table> template<typename Database, typename Table>
constexpr auto dynamic_remove_from(const Database&, Table table) constexpr auto dynamic_remove_from(const Database&, Table table)
-> remove_t<Database, vendor::single_table_t<void, Table>, vendor::no_using_t, vendor::no_where_t> -> remove_t<Database, vendor::single_table_t<void, Table>>
{ {
return { blank_remove_t<Database>(), vendor::single_table_t<void, Table>{table} }; return { remove_t<Database>(), vendor::single_table_t<void, Table>{table} };
} }
} }

View File

@ -44,8 +44,6 @@
#include <sqlpp11/vendor/expression.h> #include <sqlpp11/vendor/expression.h>
#include <sqlpp11/vendor/interpreter.h> #include <sqlpp11/vendor/interpreter.h>
#include <sqlpp11/vendor/wrong.h> #include <sqlpp11/vendor/wrong.h>
#include <sqlpp11/vendor/crtp_wrapper.h>
#include <sqlpp11/vendor/policy.h>
#include <sqlpp11/vendor/policy_update.h> #include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/detail/copy_tuple_args.h> #include <sqlpp11/detail/copy_tuple_args.h>
@ -55,74 +53,180 @@ namespace sqlpp
namespace detail namespace detail
{ {
template< template<
typename FlagList,
typename ColumnList, typename ColumnList,
typename From, typename From
typename Where,
typename GroupBy,
typename Having,
typename OrderBy,
typename Limit,
typename Offset
> >
struct select_helper_t struct select_helper_t
{ {
using _column_list_t = ColumnList; static_assert(is_noop_t<ColumnList>::value or sqlpp::is_select_column_list_t<ColumnList>::value, "Yikes");
using _from_t = ColumnList; static_assert(is_noop_t<From>::value or sqlpp::is_from_t<From>::value, "Yikes");
using _value_type = typename std::conditional< using _value_type = typename std::conditional<
sqlpp::is_from_t<From>::value, sqlpp::is_from_t<From>::value,
typename ColumnList::_value_type, 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 there is no from, the select is not complete (this logic is a bit simple, but better than nothing)
>::type; >::type;
template<typename Database>
struct can_run_t
{
//static_assert(is_where_t<Where>::value, "cannot select remove without having a where condition, use .where(true) to remove all rows");
//static_assert(not vendor::is_noop<ColumnList>::value, "cannot run select without having selected anything");
//static_assert(is_from_t<From>::value, "cannot run select without a from()");
//static_assert(is_where_t<Where>::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 // SELECT
template<typename Database, typename... Policies> template<typename Database = void,
struct select_t: public vendor::policy_t<Policies>..., public vendor::crtp_wrapper_t<select_t<Database, Policies...>, Policies>..., typename FlagList = vendor::no_select_flag_list_t,
public detail::select_helper_t<Policies...>::_value_type::template operators<select_t<Database, Policies...>> typename ColumnList = vendor::no_select_column_list_t,
typename From = vendor::no_from_t,
typename Where = vendor::no_where_t,
typename GroupBy = vendor::no_group_by_t,
typename Having = vendor::no_having_t,
typename OrderBy = vendor::no_order_by_t,
typename Limit = vendor::no_limit_t,
typename Offset = vendor::no_offset_t
>
struct select_t: public detail::select_helper_t<ColumnList, From>::_value_type::template operators<select_t<Database, FlagList, ColumnList, From, Where, GroupBy, Having, OrderBy, Limit, Offset>>
{ {
template<typename Needle, typename Replacement>
using _policy_update_t = select_t<Database, vendor::policy_update_t<Policies, Needle, Replacement>...>;
using _database_t = Database; using _database_t = Database;
using _parameter_tuple_t = std::tuple<Policies...>; using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
using _parameter_list_t = typename make_parameter_list_t<select_t>::type;
using _column_list_t = typename detail::select_helper_t<Policies...>::_column_list_t; template<typename Needle, typename Replacement, typename... Policies>
struct _policies_update_impl
{
using type = select_t<Database, vendor::policy_update_t<Policies, Needle, Replacement>...>;
};
template<typename Needle, typename Replacement>
using _policies_update_t = typename _policies_update_impl<Needle, Replacement, FlagList, ColumnList, From, Where, GroupBy, Having, OrderBy, Limit, Offset>::type;
using _parameter_tuple_t = std::tuple<FlagList, ColumnList, From, Where, GroupBy, Having, OrderBy, Limit, Offset>;
using _parameter_list_t = typename make_parameter_list_t<select_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; using _result_row_t = typename _column_list_t::_result_row_t;
using _dynamic_names_t = typename _column_list_t::_dynamic_names_t; using _dynamic_names_t = typename _column_list_t::_dynamic_names_t;
using _is_select = std::true_type; using _is_select = std::true_type;
using _requires_braces = std::true_type; using _requires_braces = std::true_type;
using _value_type = typename detail::select_helper_t<Policies...>::_value_type; using _value_type = typename detail::select_helper_t<ColumnList, From>::_value_type;
using _name_t = typename _column_list_t::_name_t; using _name_t = typename _column_list_t::_name_t;
// Constructors
select_t() select_t()
{} {}
template<typename Whatever> template<typename X>
select_t(select_t r, Whatever whatever): select_t(X x, FlagList flag_list):
vendor::policy_t<Policies>(r, whatever)... _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<typename Remove, typename Whatever> template<typename X>
select_t(Remove r, Whatever whatever): select_t(X x, ColumnList column_list):
vendor::policy_t<Policies>(r, whatever)... _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<typename X>
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<typename X>
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<typename X>
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<typename X>
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<typename X>
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<typename X>
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<typename X>
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; select_t(const select_t& r) = default;
@ -131,7 +235,230 @@ namespace sqlpp
select_t& operator=(select_t&& r) = default; select_t& operator=(select_t&& r) = default;
~select_t() = default; ~select_t() = default;
// Indicators // type update functions
template<typename... Args>
auto flags(Args... args)
-> _policies_update_t<vendor::no_select_flag_list_t, vendor::select_flag_list_t<void, Args...>>
{
static_assert(is_noop_t<FlagList>::value, "flags()/dynamic_flags() must not be called twice");
return { *this, vendor::select_flag_list_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_flags(Args... args)
-> _policies_update_t<vendor::no_select_flag_list_t, vendor::select_flag_list_t<_database_t, Args...>>
{
static_assert(is_noop_t<FlagList>::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<typename... Args>
auto columns(Args... args)
-> _policies_update_t<vendor::no_select_column_list_t, vendor::select_column_list_t<void, Args...>>
{
static_assert(is_noop_t<ColumnList>::value, "columns()/dynamic_columns() must not be called twice");
return { *this, vendor::select_column_list_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_columns(Args... args)
-> _policies_update_t<vendor::no_select_column_list_t, vendor::select_column_list_t<_database_t, Args...>>
{
static_assert(is_noop_t<ColumnList>::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<typename... Args>
auto from(Args... args)
-> _policies_update_t<vendor::no_from_t, vendor::from_t<void, Args...>>
{
return { *this, vendor::from_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_from(Args... args)
-> _policies_update_t<vendor::no_from_t, vendor::from_t<_database_t, Args...>>
{
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<typename... Args>
auto where(Args... args)
-> _policies_update_t<vendor::no_where_t, vendor::where_t<void, Args...>>
{
static_assert(is_noop_t<Where>::value, "cannot call where()/dynamic_where() twice");
return { *this, vendor::where_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_where(Args... args)
-> _policies_update_t<vendor::no_where_t, vendor::where_t<_database_t, Args...>>
{
static_assert(is_noop_t<Where>::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<typename... Args>
auto group_by(Args... args)
-> _policies_update_t<vendor::no_group_by_t, vendor::group_by_t<void, Args...>>
{
static_assert(is_noop_t<GroupBy>::value, "cannot call group_by()/dynamic_group_by() twice");
return { *this, vendor::group_by_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_group_by(Args... args)
-> _policies_update_t<vendor::no_group_by_t, vendor::group_by_t<_database_t, Args...>>
{
static_assert(is_noop_t<GroupBy>::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<typename... Args>
auto having(Args... args)
-> _policies_update_t<vendor::no_having_t, vendor::having_t<void, Args...>>
{
static_assert(is_noop_t<Having>::value, "cannot call having()/dynamic_having() twice");
return { *this, vendor::having_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_having(Args... args)
-> _policies_update_t<vendor::no_having_t, vendor::having_t<_database_t, Args...>>
{
static_assert(is_noop_t<Having>::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<typename... Args>
auto order_by(Args... args)
-> _policies_update_t<vendor::no_order_by_t, vendor::order_by_t<void, Args...>>
{
static_assert(is_noop_t<OrderBy>::value, "cannot call order_by()/dynamic_order_by() twice");
return { *this, vendor::order_by_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_order_by(Args... args)
-> _policies_update_t<vendor::no_order_by_t, vendor::order_by_t<_database_t, Args...>>
{
static_assert(is_noop_t<OrderBy>::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<typename Arg>
auto limit(Arg arg)
-> _policies_update_t<vendor::no_limit_t, vendor::limit_t<typename vendor::wrap_operand<Arg>::type>>
{
static_assert(is_noop_t<Limit>::value, "cannot call limit()/dynamic_limit() twice");
return { *this, vendor::limit_t<typename vendor::wrap_operand<Arg>::type>{{arg}} };
}
auto dynamic_limit()
-> _policies_update_t<vendor::no_limit_t, vendor::dynamic_limit_t<_database_t>>
{
static_assert(is_noop_t<Limit>::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<typename Arg>
auto offset(Arg arg)
-> _policies_update_t<vendor::no_offset_t, vendor::offset_t<typename vendor::wrap_operand<Arg>::type>>
{
static_assert(is_noop_t<Offset>::value, "cannot call offset()/dynamic_offset() twice");
return { *this, vendor::offset_t<typename vendor::wrap_operand<Arg>::type>{{arg}} };
}
auto dynamic_offset()
-> _policies_update_t<vendor::no_offset_t, vendor::dynamic_offset_t<_database_t>>
{
static_assert(is_noop_t<Offset>::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<typename... Args>
void add_flag(Args... args)
{
static_assert(is_select_flag_list_t<FlagList>::value, "cannot call add_flag() before dynamic_flags()");
static_assert(is_dynamic_t<FlagList>::value, "cannot call add_flag() before dynamic_flags()");
return _flag_list.add_flag(*this, args...);
}
template<typename... Args>
void add_column(Args... args)
{
static_assert(is_select_column_list_t<ColumnList>::value, "cannot call add_column() before dynamic_columns()");
static_assert(is_dynamic_t<ColumnList>::value, "cannot call add_column() before dynamic_columns()");
return _column_list.add_column(*this, args...);
}
template<typename... Args>
void add_from(Args... args)
{
static_assert(is_from_t<From>::value, "cannot call add_from() before dynamic_from()");
static_assert(is_dynamic_t<From>::value, "cannot call add_using() before dynamic_from()");
return _from.add_from(*this, args...);
}
template<typename... Args>
void add_where(Args... args)
{
static_assert(is_where_t<Where>::value, "cannot call add_where() before dynamic_where()");
static_assert(is_dynamic_t<Where>::value, "cannot call add_where() before dynamic_where()");
return _where.add_where(*this, args...);
}
template<typename... Args>
void add_group_by(Args... args)
{
static_assert(is_group_by_t<GroupBy>::value, "cannot call add_group_by() before dynamic_group_by()");
static_assert(is_dynamic_t<GroupBy>::value, "cannot call add_group_by() before dynamic_group_by()");
return _group_by.add_group_by(*this, args...);
}
template<typename... Args>
void add_having(Args... args)
{
static_assert(is_having_t<Having>::value, "cannot call add_having() before dynamic_having()");
static_assert(is_dynamic_t<Having>::value, "cannot call add_having() before dynamic_having()");
return _having.add_having(*this, args...);
}
template<typename... Args>
void add_order_by(Args... args)
{
static_assert(is_order_by_t<OrderBy>::value, "cannot call add_order_by() before dynamic_order_by()");
static_assert(is_dynamic_t<OrderBy>::value, "cannot call add_order_by() before dynamic_order_by()");
return _order_by.add_order_by(*this, args...);
}
template<typename Arg>
void set_limit(Arg arg)
{
static_assert(is_limit_t<Limit>::value, "cannot call add_limit() before dynamic_limit()");
static_assert(is_dynamic_t<Limit>::value, "cannot call add_limit() before dynamic_limit()");
return _limit.set_limit(arg);
}
template<typename Arg>
void set_offset(Arg arg)
{
static_assert(is_offset_t<Offset>::value, "cannot call add_offset() before dynamic_offset()");
static_assert(is_dynamic_t<Offset>::value, "cannot call add_offset() before dynamic_offset()");
return _offset.set_offset(arg);
}
// PseudoTable
template<typename AliasProvider> template<typename AliasProvider>
struct _pseudo_table_t struct _pseudo_table_t
{ {
@ -148,7 +475,7 @@ namespace sqlpp
const _dynamic_names_t& get_dynamic_names() const 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() static constexpr size_t _get_static_no_of_parameters()
@ -166,12 +493,25 @@ namespace sqlpp
return _result_row_t::static_size() + get_dynamic_names().size(); return _result_row_t::static_size() + get_dynamic_names().size();
} }
template<typename Db>
struct can_run_t
{
//static_assert(is_where_t<Where>::value, "cannot select remove without having a where condition, use .where(true) to remove all rows");
//static_assert(not vendor::is_noop<ColumnList>::value, "cannot run select without having selected anything");
//static_assert(is_from_t<From>::value, "cannot run select without a from()");
//static_assert(is_where_t<Where>::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 // Execute
template<typename Db> template<typename Db>
auto _run(Db& db) const auto _run(Db& db) const
-> result_t<decltype(db.select(*this)), _result_row_t> -> result_t<decltype(db.select(*this)), _result_row_t>
{ {
static_assert(detail::select_helper_t<Policies...>::template can_run_t<Db>::value, "Cannot execute select statement"); static_assert(can_run_t<Db>::value, "Cannot execute select statement");
static_assert(_get_static_no_of_parameters() == 0, "cannot run select directly with parameters, use prepare instead"); static_assert(_get_static_no_of_parameters() == 0, "cannot run select directly with parameters, use prepare instead");
return {db.select(*this), get_dynamic_names()}; return {db.select(*this), get_dynamic_names()};
} }
@ -181,10 +521,20 @@ namespace sqlpp
auto _prepare(Db& db) const auto _prepare(Db& db) const
-> prepared_select_t<Db, select_t> -> prepared_select_t<Db, select_t>
{ {
static_assert(detail::select_helper_t<Policies...>::template can_run_t<Db>::value, "Cannot prepare select statement"); static_assert(can_run_t<Db>::value, "Cannot prepare select statement");
return {{}, get_dynamic_names(), db.prepare_select(*this)}; 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 namespace vendor
@ -198,15 +548,15 @@ namespace sqlpp
{ {
context << "SELECT "; context << "SELECT ";
interpret(t._flag_list(), context); interpret(t._flag_list, context);
interpret(t._column_list(), context); interpret(t._column_list, context);
interpret(t._from(), context); interpret(t._from, context);
interpret(t._where(), context); interpret(t._where, context);
interpret(t._group_by(), context); interpret(t._group_by, context);
interpret(t._having(), context); interpret(t._having, context);
interpret(t._order_by(), context); interpret(t._order_by, context);
interpret(t._limit(), context); interpret(t._limit, context);
interpret(t._offset(), context); interpret(t._offset, context);
return context; return context;
} }
@ -233,32 +583,29 @@ namespace sqlpp
decltype(std::tuple_cat(as_tuple<Columns>::_(std::declval<Columns>())...))>; decltype(std::tuple_cat(as_tuple<Columns>::_(std::declval<Columns>())...))>;
} }
select_t<void> select() // FIXME: These should be constexpr
blank_select_t<void> select() // FIXME: These should be constexpr
{ {
return { blank_select_t<void>() }; return { select_t<void>() };
} }
template<typename... Columns> template<typename... Columns>
auto select(Columns... columns) auto select(Columns... columns)
-> vendor::update_policies_t<blank_select_t<void>, -> select_t<void, vendor::no_select_flag_list_t, detail::make_select_column_list_t<void, Columns...>>
vendor::no_select_column_list_t,
detail::make_select_column_list_t<void, Columns...>>
{ {
return { blank_select_t<void>(), detail::make_select_column_list_t<void, Columns...>(std::tuple_cat(detail::as_tuple<Columns>::_(columns)...)) }; return { select_t<void>(), detail::make_select_column_list_t<void, Columns...>(std::tuple_cat(detail::as_tuple<Columns>::_(columns)...)) };
} }
template<typename Database> template<typename Database>
blank_select_t<Database> dynamic_select(const Database&) select_t<Database> dynamic_select(const Database&)
{ {
return { blank_select_t<Database>() }; return { select_t<Database>() };
} }
template<typename Database, typename... Columns> template<typename Database, typename... Columns>
auto dynamic_select(const Database&, Columns... columns) auto dynamic_select(const Database&, Columns... columns)
-> vendor::update_policies_t<blank_select_t<Database>, vendor::no_select_column_list_t, detail::make_select_column_list_t<void, Columns...>> -> select_t<Database, vendor::no_select_flag_list_t, detail::make_select_column_list_t<void, Columns...>>
{ {
return { blank_select_t<Database>(), detail::make_select_column_list_t<void, Columns...>(std::tuple_cat(detail::as_tuple<Columns>::_(columns)...)) }; return { select_t<Database>(), detail::make_select_column_list_t<void, Columns...>(std::tuple_cat(detail::as_tuple<Columns>::_(columns)...)) };
} }
} }

View File

@ -27,7 +27,6 @@
#ifndef SQLPP_SELECT_FLAGS_H #ifndef SQLPP_SELECT_FLAGS_H
#define SQLPP_SELECT_FLAGS_H #define SQLPP_SELECT_FLAGS_H
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/type_set.h> #include <sqlpp11/detail/type_set.h>
#include <sqlpp11/vendor/interpret_tuple.h> #include <sqlpp11/vendor/interpret_tuple.h>

View File

@ -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 <type_traits>
namespace sqlpp
{
template<typename Database, typename... Policies>
struct select_t;
}
#endif

View File

@ -179,6 +179,12 @@ namespace sqlpp
return { *static_cast<const Base*>(this), {t} }; return { *static_cast<const Base*>(this), {t} };
} }
template<typename T>
auto operator +=(T t) const -> decltype(std::declval<Base>() = std::declval<Base>() + t)
{
return *static_cast<const Base*>(this) = operator +(t);
}
template<typename T> template<typename T>
vendor::like_t<Base, typename _operand_t<T>::type> like(T t) const vendor::like_t<Base, typename _operand_t<T>::type> like(T t) const
{ {

View File

@ -39,6 +39,7 @@ namespace sqlpp
{ {
using _operand_t = Operand; using _operand_t = Operand;
using _value_type = typename _operand_t::_value_type; using _value_type = typename _operand_t::_value_type;
using _table_set = typename _operand_t::_table_set;
tvin_t(Operand operand): tvin_t(Operand operand):
_value(operand) _value(operand)
@ -74,6 +75,7 @@ namespace sqlpp
template<typename T> template<typename T>
struct tvin_wrap_t struct tvin_wrap_t
{ {
using _table_set = typename T::_table_set;
static constexpr bool _is_trivial() static constexpr bool _is_trivial()
{ {
return false; return false;
@ -94,6 +96,7 @@ namespace sqlpp
template<typename T> template<typename T>
struct tvin_wrap_t<tvin_t<T>> struct tvin_wrap_t<tvin_t<T>>
{ {
using _table_set = typename T::_table_set;
bool _is_trivial() const bool _is_trivial() const
{ {
return _value._is_trivial(); return _value._is_trivial();

View File

@ -93,6 +93,7 @@ namespace sqlpp
SQLPP_IS_COLUMN_TRAIT_GENERATOR(require_insert); SQLPP_IS_COLUMN_TRAIT_GENERATOR(require_insert);
SQLPP_IS_COLUMN_TRAIT_GENERATOR(can_be_null); 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_table);
SQLPP_TYPE_TRAIT_GENERATOR(is_join); SQLPP_TYPE_TRAIT_GENERATOR(is_join);
SQLPP_TYPE_TRAIT_GENERATOR(is_pseudo_table); SQLPP_TYPE_TRAIT_GENERATOR(is_pseudo_table);

View File

@ -34,8 +34,6 @@
#include <sqlpp11/vendor/update_list.h> #include <sqlpp11/vendor/update_list.h>
#include <sqlpp11/vendor/noop.h> #include <sqlpp11/vendor/noop.h>
#include <sqlpp11/vendor/where.h> #include <sqlpp11/vendor/where.h>
#include <sqlpp11/vendor/crtp_wrapper.h>
#include <sqlpp11/vendor/policy.h>
#include <sqlpp11/vendor/policy_update.h> #include <sqlpp11/vendor/policy_update.h>
namespace sqlpp namespace sqlpp
@ -44,7 +42,7 @@ namespace sqlpp
{ {
template< template<
typename Table, typename Table,
typename Assignments, typename UpdateList,
typename Where typename Where
> >
struct check_update_t struct check_update_t
@ -53,27 +51,53 @@ namespace sqlpp
}; };
} }
template<typename Database, typename... Policies> template<typename Database = void,
struct update_t: public vendor::policy_t<Policies>..., public vendor::crtp_wrapper_t<update_t<Database, Policies...>, Policies>... typename Table = vendor::no_single_table_t,
typename UpdateList = vendor::no_update_list_t,
typename Where = vendor::no_where_t>
struct update_t
{ {
template<typename Needle, typename Replacement> static_assert(Table::_table_set::template is_superset_of<typename UpdateList::_table_set>::value, "updated columns do not match the table");
using _policy_update_t = update_t<Database, vendor::policy_update_t<Policies, Needle, Replacement>...>; static_assert(Table::_table_set::template is_superset_of<typename Where::_table_set>::value, "where condition does not match updated table");
using _database_t = Database; using _database_t = Database;
using _parameter_tuple_t = std::tuple<Policies...>; using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
template<typename Needle, typename Replacement, typename... Policies>
struct _policies_update_impl
{
using type = update_t<Database, vendor::policy_update_t<Policies, Needle, Replacement>...>;
};
template<typename Needle, typename Replacement>
using _policies_update_t = typename _policies_update_impl<Needle, Replacement, Table, UpdateList, Where>::type;
using _parameter_tuple_t = std::tuple<Table, UpdateList, Where>;
using _parameter_list_t = typename make_parameter_list_t<update_t>::type; using _parameter_list_t = typename make_parameter_list_t<update_t>::type;
update_t() update_t()
{} {}
template<typename Whatever> // Constructors
update_t(update_t r, Whatever whatever): template<typename X>
vendor::policy_t<Policies>(r, whatever)... update_t(X x, Table table):
_table(table),
_update_list(x._update_list),
_where(x._where)
{} {}
template<typename Remove, typename Whatever> template<typename X>
update_t(Remove r, Whatever whatever): update_t(X x, UpdateList update_list):
vendor::policy_t<Policies>(r, whatever)... _table(x._table),
_update_list(update_list),
_where(x._where)
{}
template<typename X>
update_t(X x, Where where):
_table(x._table),
_update_list(x._update_list),
_where(where)
{} {}
update_t(const update_t&) = default; update_t(const update_t&) = default;
@ -82,6 +106,59 @@ namespace sqlpp
update_t& operator=(update_t&&) = default; update_t& operator=(update_t&&) = default;
~update_t() = default; ~update_t() = default;
// type update functions
template<typename... Args>
auto set(Args... args)
-> _policies_update_t<vendor::no_update_list_t, vendor::update_list_t<void, Args...>>
{
static_assert(is_noop_t<UpdateList>::value, "cannot call set()/dynamic_set() twice");
return { *this, vendor::update_list_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_set(Args... args)
-> _policies_update_t<vendor::no_update_list_t, vendor::update_list_t<_database_t, Args...>>
{
static_assert(is_noop_t<UpdateList>::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<typename... Args>
auto where(Args... args)
-> _policies_update_t<vendor::no_where_t, vendor::where_t<void, Args...>>
{
static_assert(is_noop_t<Where>::value, "cannot call where()/dynamic_where() twice");
return { *this, vendor::where_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_where(Args... args)
-> _policies_update_t<vendor::no_where_t, vendor::where_t<_database_t, Args...>>
{
static_assert(is_noop_t<Where>::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<typename... Args>
void add_set(Args... args)
{
static_assert(is_update_list_t<UpdateList>::value, "cannot call add_set() before dynamic_set()");
static_assert(is_dynamic_t<UpdateList>::value, "cannot call add_set() before dynamic_set()");
return _update_list.add_set(*this, args...);
}
template<typename... Args>
void add_where(Args... args)
{
static_assert(is_where_t<Where>::value, "cannot call add_where() before dynamic_where()");
static_assert(is_dynamic_t<Where>::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() static constexpr size_t _get_static_no_of_parameters()
{ {
return _parameter_list_t::size::value; return _parameter_list_t::size::value;
@ -96,7 +173,6 @@ namespace sqlpp
std::size_t _run(Db& db) const 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(_get_static_no_of_parameters() == 0, "cannot run update directly with parameters, use prepare instead");
static_assert(detail::check_update_t<Policies...>::value, "Cannot run this update expression");
return db.update(*this); return db.update(*this);
} }
@ -104,9 +180,12 @@ namespace sqlpp
auto _prepare(Db& db) const auto _prepare(Db& db) const
-> prepared_update_t<Database, update_t> -> prepared_update_t<Database, update_t>
{ {
static_assert(detail::check_update_t<Policies...>::value, "Cannot run this update expression");
return {{}, db.prepare_update(*this)}; return {{}, db.prepare_update(*this)};
} }
Table _table;
UpdateList _update_list;
Where _where;
}; };
namespace vendor namespace vendor
@ -119,29 +198,26 @@ namespace sqlpp
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
context << "UPDATE "; context << "UPDATE ";
interpret(t._single_table(), context); interpret(t._table, context);
interpret(t._update_list(), context); interpret(t._update_list, context);
interpret(t._where(), context); interpret(t._where, context);
return context; return context;
} }
}; };
} }
template<typename Database>
using blank_update_t = update_t<Database, vendor::no_single_table_t, vendor::no_update_list_t, vendor::no_where_t>;
template<typename Table> template<typename Table>
constexpr auto update(Table table) constexpr auto update(Table table)
-> update_t<void, vendor::single_table_t<void, Table>, vendor::no_update_list_t, vendor::no_where_t> -> update_t<void, vendor::single_table_t<void, Table>>
{ {
return { blank_update_t<void>(), vendor::single_table_t<void, Table>{table} }; return { update_t<void>(), vendor::single_table_t<void, Table>{table} };
} }
template<typename Database, typename Table> template<typename Database, typename Table>
constexpr auto dynamic_update(const Database&, Table table) constexpr auto dynamic_update(const Database&, Table table)
-> update_t<Database, vendor::single_table_t<void, Table>, vendor::no_update_list_t, vendor::no_where_t> -> update_t<Database, vendor::single_table_t<void, Table>>
{ {
return { blank_update_t<Database>(), vendor::single_table_t<void, Table>{table} }; return { update_t<Database>(), vendor::single_table_t<void, Table>{table} };
} }
} }

View File

@ -44,6 +44,7 @@ namespace sqlpp
using _column_t = Lhs; using _column_t = Lhs;
using value_type = Rhs; using value_type = Rhs;
using _parameter_tuple_t = std::tuple<_column_t, Rhs>; using _parameter_tuple_t = std::tuple<_column_t, Rhs>;
using _table_set = typename Lhs::_table_set::template join<typename Rhs::_table_set>::type;
static_assert(not std::is_same<Rhs, null_t>::value or can_be_null_t<_column_t>::value, "column cannot be null"); static_assert(not std::is_same<Rhs, null_t>::value or can_be_null_t<_column_t>::value, "column cannot be null");

View File

@ -40,6 +40,7 @@ namespace sqlpp
{ {
static_assert(sizeof...(Args) > 0, "concat requires two arguments at least"); static_assert(sizeof...(Args) > 0, "concat requires two arguments at least");
static_assert(sqlpp::detail::and_t<is_text_t, First, Args...>::value, "at least one non-text argument detected in concat()"); static_assert(sqlpp::detail::and_t<is_text_t, First, Args...>::value, "at least one non-text argument detected in concat()");
using _table_set = typename ::sqlpp::detail::make_joined_set<typename First::_table_set, typename Args::_table_set...>::type;
struct _value_type: public First::_value_type::_base_value_type struct _value_type: public First::_value_type::_base_value_type
{ {

View File

@ -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 <sqlpp11/vendor/wrong.h>
namespace sqlpp
{
namespace vendor
{
template<typename T>
struct get_database_impl;
template<template<typename, typename...> class Statement, typename Database, typename... Policies>
struct get_database_impl<Statement<Database, Policies...>>
{
using type = Database;
};
template<typename T>
using get_database_t = typename get_database_impl<T>::type;
template<typename Derived, typename Policy>
struct crtp_wrapper_t
{
static_assert(wrong_t<Derived, Policy>::value, "missing crtp policy specialization");
};
}
}
#endif

View File

@ -44,6 +44,7 @@ namespace sqlpp
{ {
using _value_type = ::sqlpp::detail::boolean; using _value_type = ::sqlpp::detail::boolean;
using _parameter_tuple_t = std::tuple<Lhs, Rhs>; using _parameter_tuple_t = std::tuple<Lhs, Rhs>;
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Lhs::_table_set, typename Rhs::_table_set>::type;
equal_t(Lhs lhs, Rhs rhs): equal_t(Lhs lhs, Rhs rhs):
_lhs(lhs), _lhs(lhs),
@ -88,6 +89,7 @@ namespace sqlpp
{ {
using _value_type = ::sqlpp::detail::boolean; using _value_type = ::sqlpp::detail::boolean;
using _parameter_tuple_t = std::tuple<Lhs, Rhs>; using _parameter_tuple_t = std::tuple<Lhs, Rhs>;
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Lhs::_table_set, typename Rhs::_table_set>::type;
not_equal_t(Lhs lhs, Rhs rhs): not_equal_t(Lhs lhs, Rhs rhs):
_lhs(lhs), _lhs(lhs),
@ -132,6 +134,7 @@ namespace sqlpp
{ {
using _value_type = ::sqlpp::detail::boolean; using _value_type = ::sqlpp::detail::boolean;
using _parameter_tuple_t = std::tuple<Lhs>; using _parameter_tuple_t = std::tuple<Lhs>;
using _table_set = typename Lhs::_table_set;
logical_not_t(Lhs l): logical_not_t(Lhs l):
_lhs(l) _lhs(l)
@ -168,6 +171,7 @@ namespace sqlpp
using _rhs_t = Rhs; using _rhs_t = Rhs;
using _value_type = typename O::_value_type; using _value_type = typename O::_value_type;
using _parameter_tuple_t = std::tuple<_lhs_t, _rhs_t>; using _parameter_tuple_t = std::tuple<_lhs_t, _rhs_t>;
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Lhs::_table_set, typename Rhs::_table_set>::type;
binary_expression_t(_lhs_t lhs, _rhs_t rhs): binary_expression_t(_lhs_t lhs, _rhs_t rhs):
_lhs(lhs), _lhs(lhs),

View File

@ -27,13 +27,11 @@
#ifndef SQLPP_FROM_H #ifndef SQLPP_FROM_H
#define SQLPP_FROM_H #define SQLPP_FROM_H
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/interpretable_list.h> #include <sqlpp11/vendor/interpretable_list.h>
#include <sqlpp11/vendor/interpret_tuple.h> #include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/detail/logic.h> #include <sqlpp11/detail/logic.h>
#include <sqlpp11/vendor/policy_update.h> #include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/vendor/crtp_wrapper.h>
namespace sqlpp namespace sqlpp
{ {
@ -66,47 +64,21 @@ namespace sqlpp
from_t& operator=(from_t&&) = default; from_t& operator=(from_t&&) = default;
~from_t() = default; ~from_t() = default;
template<typename Table> template<typename Select, typename Table>
void add_from(Table table) void add_from(const Select&, Table table)
{ {
static_assert(_is_dynamic::value, "add_from can only be called for dynamic_from"); static_assert(_is_dynamic::value, "add_from can only be called for dynamic_from");
static_assert(is_table_t<Table>::value, "from arguments require to be tables or joins"); static_assert(is_table_t<Table>::value, "from arguments require to be tables or joins");
_dynamic_tables.emplace_back(table); _dynamic_tables.emplace_back(table);
} }
const from_t& _from() const { return *this; }
std::tuple<Tables...> _tables; std::tuple<Tables...> _tables;
vendor::interpretable_list_t<Database> _dynamic_tables; vendor::interpretable_list_t<Database> _dynamic_tables;
}; };
struct no_from_t struct no_from_t
{ {
const no_from_t& _from() const { return *this; } using _is_noop = std::true_type;
};
// CRTP Wrappers
template<typename Derived, typename Database, typename... Args>
struct crtp_wrapper_t<Derived, from_t<Database, Args...>>
{
};
template<typename Derived>
struct crtp_wrapper_t<Derived, no_from_t>
{
template<typename... Args>
auto from(Args... args)
-> vendor::update_policies_t<Derived, no_from_t, from_t<void, Args...>>
{
return { static_cast<Derived&>(*this), from_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_from(Args... args)
-> vendor::update_policies_t<Derived, no_from_t, from_t<get_database_t<Derived>, Args...>>
{
static_assert(not std::is_same<get_database_t<Derived>, void>::value, "dynamic_from must not be called in a static statement");
return { static_cast<Derived&>(*this), from_t<get_database_t<Derived>, Args...>(args...) };
}
}; };
// Interpreters // Interpreters

View File

@ -33,7 +33,6 @@
#include <sqlpp11/vendor/interpret_tuple.h> #include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/vendor/interpretable_list.h> #include <sqlpp11/vendor/interpretable_list.h>
#include <sqlpp11/vendor/policy_update.h> #include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/vendor/crtp_wrapper.h>
#include <sqlpp11/detail/logic.h> #include <sqlpp11/detail/logic.h>
namespace sqlpp namespace sqlpp
@ -64,8 +63,8 @@ namespace sqlpp
group_by_t& operator=(group_by_t&&) = default; group_by_t& operator=(group_by_t&&) = default;
~group_by_t() = default; ~group_by_t() = default;
template<typename Expression> template<typename Statement, typename Expression>
void add_group_by(Expression expression) void add_group_by(const Statement&, Expression expression)
{ {
static_assert(is_table_t<Expression>::value, "from arguments require to be tables or joins"); static_assert(is_table_t<Expression>::value, "from arguments require to be tables or joins");
_dynamic_expressions.emplace_back(expression); _dynamic_expressions.emplace_back(expression);
@ -78,33 +77,7 @@ namespace sqlpp
struct no_group_by_t struct no_group_by_t
{ {
using _is_group_by = std::true_type; using _is_noop = std::true_type;
const no_group_by_t& _group_by() const { return *this; }
};
// CRTP Wrappers
template<typename Derived, typename Database, typename... Args>
struct crtp_wrapper_t<Derived, group_by_t<Database, Args...>>
{
};
template<typename Derived>
struct crtp_wrapper_t<Derived, no_group_by_t>
{
template<typename... Args>
auto group_by(Args... args)
-> vendor::update_policies_t<Derived, no_group_by_t, group_by_t<void, Args...>>
{
return { static_cast<Derived&>(*this), group_by_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_group_by(Args... args)
-> vendor::update_policies_t<Derived, no_group_by_t, group_by_t<get_database_t<Derived>, Args...>>
{
static_assert(not std::is_same<get_database_t<Derived>, void>::value, "dynamic_group_by must not be called in a static statement");
return { static_cast<Derived&>(*this), group_by_t<get_database_t<Derived>, Args...>(args...) };
}
}; };
// Interpreters // Interpreters

View File

@ -32,7 +32,6 @@
#include <sqlpp11/vendor/interpret_tuple.h> #include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/vendor/interpretable_list.h> #include <sqlpp11/vendor/interpretable_list.h>
#include <sqlpp11/vendor/policy_update.h> #include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/vendor/crtp_wrapper.h>
#include <sqlpp11/detail/logic.h> #include <sqlpp11/detail/logic.h>
namespace sqlpp namespace sqlpp
@ -69,40 +68,13 @@ namespace sqlpp
_dynamic_expressions.emplace_back(expr); _dynamic_expressions.emplace_back(expr);
} }
const having_t& _having() const { return *this; }
_parameter_tuple_t _expressions; _parameter_tuple_t _expressions;
vendor::interpretable_list_t<Database> _dynamic_expressions; vendor::interpretable_list_t<Database> _dynamic_expressions;
}; };
struct no_having_t struct no_having_t
{ {
using _is_having = std::true_type; using _is_noop = std::true_type;
const no_having_t& _having() const { return *this; }
};
// CRTP Wrappers
template<typename Derived, typename Database, typename... Args>
struct crtp_wrapper_t<Derived, having_t<Database, Args...>>
{
};
template<typename Derived>
struct crtp_wrapper_t<Derived, no_having_t>
{
template<typename... Args>
auto having(Args... args)
-> vendor::update_policies_t<Derived, no_having_t, having_t<void, Args...>>
{
return { static_cast<Derived&>(*this), having_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_having(Args... args)
-> vendor::update_policies_t<Derived, no_having_t, having_t<get_database_t<Derived>, Args...>>
{
static_assert(not std::is_same<get_database_t<Derived>, void>::value, "dynamic_having must not be called in a static statement");
return { static_cast<Derived&>(*this), having_t<get_database_t<Derived>, Args...>(args...) };
}
}; };
// Interpreters // Interpreters

View File

@ -56,6 +56,7 @@ namespace sqlpp
T in; T in;
}; };
}; };
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Operand::_table_set, typename Args::_table_set...>::type;
in_t(Operand operand, Args... args): in_t(Operand operand, Args... args):
_operand(operand), _operand(operand),

View File

@ -32,6 +32,7 @@
#include <sqlpp11/tvin.h> #include <sqlpp11/tvin.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/interpreter.h> #include <sqlpp11/vendor/interpreter.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp namespace sqlpp
{ {
@ -43,6 +44,7 @@ namespace sqlpp
struct type_if struct type_if
{ {
using type = Type; using type = Type;
using _table_set = typename Type::_table_set;
}; };
template<typename Type> template<typename Type>
@ -50,6 +52,7 @@ namespace sqlpp
{ {
struct type struct type
{ {
using _table_set = sqlpp::detail::type_set<>;
}; };
}; };
} }

View File

@ -32,8 +32,6 @@
#include <sqlpp11/vendor/interpret_tuple.h> #include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/vendor/insert_value.h> #include <sqlpp11/vendor/insert_value.h>
#include <sqlpp11/vendor/simple_column.h> #include <sqlpp11/vendor/simple_column.h>
#include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/vendor/crtp_wrapper.h>
namespace sqlpp namespace sqlpp
{ {
@ -42,10 +40,8 @@ namespace sqlpp
// COLUMN AND VALUE LIST // COLUMN AND VALUE LIST
struct insert_default_values_t struct insert_default_values_t
{ {
using _is_insert_list = std::true_type;
using _table_set = ::sqlpp::detail::type_set<>; using _table_set = ::sqlpp::detail::type_set<>;
using _is_dynamic = std::false_type; using _is_dynamic = std::false_type;
const insert_default_values_t& _insert_value_list() const { return *this; }
}; };
template<typename Database, typename... Assignments> template<typename Database, typename... Assignments>
@ -67,8 +63,11 @@ namespace sqlpp
static_assert(not sqlpp::detail::or_t<must_not_insert_t, typename Assignments::_column_t...>::value, "at least one assignment is prohibited by its column definition in set()"); static_assert(not sqlpp::detail::or_t<must_not_insert_t, typename Assignments::_column_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...>::type; using _column_table_set = typename ::sqlpp::detail::make_joined_set<typename Assignments::_column_t::_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 _value_table_set = typename ::sqlpp::detail::make_joined_set<typename Assignments::value_type::_table_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): insert_list_t(Assignments... assignment):
_assignments(assignment...), _assignments(assignment...),
@ -82,17 +81,20 @@ namespace sqlpp
insert_list_t& operator=(insert_list_t&&) = default; insert_list_t& operator=(insert_list_t&&) = default;
~insert_list_t() = default; ~insert_list_t() = default;
template<typename Assignment> template<typename Insert, typename Assignment>
void add_set(Assignment assignment) void add_set(const Insert&, Assignment assignment)
{ {
static_assert(is_assignment_t<Assignment>::value, "set() arguments require to be assigments"); static_assert(is_assignment_t<Assignment>::value, "add_set() arguments require to be assigments");
static_assert(not must_not_insert_t<Assignment>::value, "set() argument must not be used in insert"); static_assert(not must_not_insert_t<Assignment>::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<typename Insert::_table_set>::value, "add_set() contains a column from a foreign table");
static_assert(_column_table_set::template is_subset_of<typename Insert::_table_set>::value, "add_set() contains a value from a foreign table");
_dynamic_columns.emplace_back(simple_column_t<typename Assignment::_column_t>{assignment._lhs}); _dynamic_columns.emplace_back(simple_column_t<typename Assignment::_column_t>{assignment._lhs});
_dynamic_values.emplace_back(assignment._rhs); _dynamic_values.emplace_back(assignment._rhs);
} }
const insert_list_t& _insert_value_list() const { return *this; }
std::tuple<simple_column_t<typename Assignments::_column_t>...> _columns; std::tuple<simple_column_t<typename Assignments::_column_t>...> _columns;
std::tuple<typename Assignments::value_type...> _values; std::tuple<typename Assignments::value_type...> _values;
std::tuple<Assignments...> _assignments; // FIXME: Need to replace _columns and _values by _assignments (connector-container requires assignments) std::tuple<Assignments...> _assignments; // FIXME: Need to replace _columns and _values by _assignments (connector-container requires assignments)
@ -129,9 +131,14 @@ namespace sqlpp
column_list_t& operator=(column_list_t&&) = default; column_list_t& operator=(column_list_t&&) = default;
~column_list_t() = default; ~column_list_t() = default;
void add_values(vendor::insert_value_t<Columns>... values) template<typename... Assignments>
void add_values(Assignments... assignments)
{ {
_insert_values.emplace_back(values...); static_assert(::sqlpp::detail::and_t<is_assignment_t, Assignments...>::value, "add_values() arguments have to be assignments");
using _arg_value_tuple = std::tuple<vendor::insert_value_t<typename Assignments::_column_t>...>;
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 bool empty() const
@ -139,70 +146,25 @@ namespace sqlpp
return _insert_values.empty(); return _insert_values.empty();
} }
const column_list_t& _insert_value_list() const { return *this; }
std::tuple<simple_column_t<Columns>...> _columns; std::tuple<simple_column_t<Columns>...> _columns;
std::vector<_value_tuple_t> _insert_values; std::vector<_value_tuple_t> _insert_values;
private:
template<typename... Assignments>
void add_values_impl(const std::true_type&, Assignments... assignments)
{
_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);
}; };
struct no_insert_value_list_t struct no_insert_value_list_t
{ {
using _is_noop = std::true_type;
using _table_set = ::sqlpp::detail::type_set<>; using _table_set = ::sqlpp::detail::type_set<>;
const no_insert_value_list_t& _insert_value_list() const { return *this; }
};
// CRTP Wrappers
template<typename Derived>
struct crtp_wrapper_t<Derived, insert_default_values_t>
{
};
template<typename Derived, typename Database, typename... Args>
struct crtp_wrapper_t<Derived, column_list_t<Database, Args...>>
{
};
template<typename Derived, typename Database, typename... Args>
struct crtp_wrapper_t<Derived, insert_list_t<Database, Args...>>
{
};
template<typename Derived>
struct crtp_wrapper_t<Derived, no_insert_value_list_t>
{
template<typename... Args>
struct delayed_t
{
using type = Derived;
};
template<typename Arg = void>
auto default_values()
-> vendor::update_policies_t<typename delayed_t<Arg>::type, no_insert_value_list_t, insert_default_values_t>
{
return { static_cast<Derived&>(*this), insert_default_values_t{} };
}
template<typename... Args>
auto columns(Args... args)
-> vendor::update_policies_t<Derived, no_insert_value_list_t, column_list_t<Args...>>
{
return { static_cast<Derived&>(*this), column_list_t<Args...>(args...) };
}
template<typename... Args>
auto set(Args... args)
-> vendor::update_policies_t<Derived, no_insert_value_list_t, insert_list_t<void, Args...>>
{
return { static_cast<Derived&>(*this), insert_list_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_set(Args... args)
-> vendor::update_policies_t<Derived, no_insert_value_list_t, insert_list_t<get_database_t<Derived>, Args...>>
{
static_assert(not std::is_same<get_database_t<Derived>, void>::value, "dynamic_insert_list must not be called in a static statement");
return { static_cast<Derived&>(*this), insert_list_t<get_database_t<Derived>, Args...>(args...) };
}
}; };
// Interpreters // Interpreters

View File

@ -41,6 +41,7 @@ namespace sqlpp
static_assert(is_text_t<Operand>::value, "Operand for like() has to be a text"); static_assert(is_text_t<Operand>::value, "Operand for like() has to be a text");
static_assert(is_text_t<Pattern>::value, "Pattern for like() has to be a text"); static_assert(is_text_t<Pattern>::value, "Pattern for like() has to be a text");
using _parameter_tuple_t = std::tuple<Operand, Pattern>; using _parameter_tuple_t = std::tuple<Operand, Pattern>;
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Operand::_table_set, typename Pattern::_table_set>::type;
struct _value_type: public boolean struct _value_type: public boolean
{ {

View File

@ -29,7 +29,6 @@
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/policy_update.h> #include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/vendor/crtp_wrapper.h>
namespace sqlpp namespace sqlpp
{ {
@ -52,7 +51,6 @@ namespace sqlpp
limit_t& operator=(limit_t&&) = default; limit_t& operator=(limit_t&&) = default;
~limit_t() = default; ~limit_t() = default;
const limit_t& _limit() const { return *this; }
Limit _value; Limit _value;
}; };
@ -88,54 +86,13 @@ namespace sqlpp
_initialized = true; _initialized = true;
} }
const dynamic_limit_t& _limit() const { return *this; }
bool _initialized = false; bool _initialized = false;
interpretable_t<Database> _value; interpretable_t<Database> _value;
}; };
struct no_limit_t struct no_limit_t
{ {
using _is_limit = std::true_type; using _is_noop = std::true_type;
const no_limit_t& _limit() const { return *this; }
};
// CRTP Wrappers
template<typename Derived, typename Limit>
struct crtp_wrapper_t<Derived, limit_t<Limit>>
{
};
template<typename Derived, typename Database>
struct crtp_wrapper_t<Derived, dynamic_limit_t<Database>>
{
};
template<typename Derived>
struct crtp_wrapper_t<Derived, no_limit_t>
{
template<typename... Args>
struct delayed_get_database_t
{
using type = get_database_t<Derived>;
};
template<typename Arg>
auto limit(Arg arg)
-> vendor::update_policies_t<Derived, no_limit_t, limit_t<typename wrap_operand<Arg>::type>>
{
typename wrap_operand<Arg>::type value = {arg};
return { static_cast<Derived&>(*this), limit_t<typename wrap_operand<Arg>::type>(value) };
}
template<typename... Args>
auto dynamic_limit(Args... args)
-> vendor::update_policies_t<Derived, no_limit_t, dynamic_limit_t<typename delayed_get_database_t<Args...>::type>>
{
static_assert(sizeof...(Args) < 2, "dynamic_limit must be called with zero or one arguments");
static_assert(not std::is_same<get_database_t<Derived>, void>::value, "dynamic_limit must not be called in a static statement");
return { static_cast<Derived&>(*this), dynamic_limit_t<typename delayed_get_database_t<Args...>::type>(args...) };
}
}; };
// Interpreters // Interpreters

View File

@ -35,6 +35,7 @@ namespace sqlpp
{ {
struct noop struct noop
{ {
using is_noop = std::true_type;
}; };
template<typename Context> template<typename Context>

View File

@ -29,7 +29,6 @@
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/policy_update.h> #include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/vendor/crtp_wrapper.h>
namespace sqlpp namespace sqlpp
{ {
@ -52,8 +51,6 @@ namespace sqlpp
offset_t& operator=(offset_t&&) = default; offset_t& operator=(offset_t&&) = default;
~offset_t() = default; ~offset_t() = default;
const offset_t& _offset() const { return *this; }
Offset _value; Offset _value;
}; };
@ -89,53 +86,13 @@ namespace sqlpp
_initialized = true; _initialized = true;
} }
const dynamic_offset_t& _offset() const { return *this; }
bool _initialized = false; bool _initialized = false;
interpretable_t<Database> _value; interpretable_t<Database> _value;
}; };
struct no_offset_t struct no_offset_t
{ {
using _is_offset = std::true_type; using _is_noop = std::true_type;
const no_offset_t& _offset() const { return *this; }
};
// CRTP Wrappers
template<typename Derived, typename Offset>
struct crtp_wrapper_t<Derived, offset_t<Offset>>
{
};
template<typename Derived, typename Database>
struct crtp_wrapper_t<Derived, dynamic_offset_t<Database>>
{
};
template<typename Derived>
struct crtp_wrapper_t<Derived, no_offset_t>
{
template<typename... Args>
struct delayed_get_database_t
{
using type = get_database_t<Derived>;
};
template<typename Arg>
auto offset(Arg arg)
-> vendor::update_policies_t<Derived, no_offset_t, offset_t<typename wrap_operand<Arg>::type>>
{
typename wrap_operand<Arg>::type value = {arg};
return { static_cast<Derived&>(*this), offset_t<typename wrap_operand<Arg>::type>(value) };
}
template<typename... Args>
auto dynamic_offset(Args... args)
-> vendor::update_policies_t<Derived, no_offset_t, dynamic_offset_t<typename delayed_get_database_t<Args...>::type>>
{
static_assert(sizeof...(Args) < 2, "dynamic_offset must be called with zero or one arguments");
static_assert(not std::is_same<get_database_t<Derived>, void>::value, "dynamic_offset must not be called in a static statement");
return { static_cast<Derived&>(*this), dynamic_offset_t<typename delayed_get_database_t<Args...>::type>(args...) };
}
}; };
// Interpreters // Interpreters

View File

@ -28,12 +28,10 @@
#define SQLPP_ORDER_BY_H #define SQLPP_ORDER_BY_H
#include <tuple> #include <tuple>
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/interpret_tuple.h> #include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/vendor/interpretable.h> #include <sqlpp11/vendor/interpretable.h>
#include <sqlpp11/vendor/policy_update.h> #include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/vendor/crtp_wrapper.h>
#include <sqlpp11/detail/logic.h> #include <sqlpp11/detail/logic.h>
namespace sqlpp namespace sqlpp
@ -63,47 +61,20 @@ namespace sqlpp
order_by_t& operator=(order_by_t&&) = default; order_by_t& operator=(order_by_t&&) = default;
~order_by_t() = default; ~order_by_t() = default;
template<typename Expression> template<typename Statement, typename Expression>
void add_order_by(Expression expressions) void add_order_by(const Statement&, Expression expressions)
{ {
static_assert(is_sort_order_t<Expression>::value, "order_by arguments require to be sort-order expressions"); static_assert(is_sort_order_t<Expression>::value, "order_by arguments require to be sort-order expressions");
_dynamic_expressions.push_back(expressions); _dynamic_expressions.push_back(expressions);
} }
const order_by_t& _order_by() const { return *this; }
_parameter_tuple_t _expressions; _parameter_tuple_t _expressions;
vendor::interpretable_list_t<Database> _dynamic_expressions; vendor::interpretable_list_t<Database> _dynamic_expressions;
}; };
struct no_order_by_t struct no_order_by_t
{ {
using _is_order_by = std::true_type; using _is_noop = std::true_type;
const no_order_by_t& _order_by() const { return *this; }
};
// CRTP Wrappers
template<typename Derived, typename Database, typename... Args>
struct crtp_wrapper_t<Derived, order_by_t<Database, Args...>>
{
};
template<typename Derived>
struct crtp_wrapper_t<Derived, no_order_by_t>
{
template<typename... Args>
auto order_by(Args... args)
-> vendor::update_policies_t<Derived, no_order_by_t, order_by_t<void, Args...>>
{
return { static_cast<Derived&>(*this), order_by_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_order_by(Args... args)
-> vendor::update_policies_t<Derived, no_order_by_t, order_by_t<get_database_t<Derived>, Args...>>
{
static_assert(not std::is_same<get_database_t<Derived>, void>::value, "dynamic_order_by must not be called in a static statement");
return { static_cast<Derived&>(*this), order_by_t<get_database_t<Derived>, Args...>(args...) };
}
}; };
// Interpreters // Interpreters

View File

@ -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 <sqlpp11/vendor/wrong.h>
namespace sqlpp
{
namespace vendor
{
template<typename PolicyImpl>
struct policy_t: public PolicyImpl
{
policy_t()
{}
template<typename Whatever>
policy_t(const Whatever&, policy_t policy):
PolicyImpl(policy)
{}
template<typename Whatever>
policy_t(const Whatever&, PolicyImpl impl):
PolicyImpl(impl)
{}
template<typename Derived, typename Whatever>
policy_t(Derived derived, const Whatever&):
PolicyImpl(derived)
{}
};
}
}
#endif

View File

@ -29,7 +29,6 @@
#include <tuple> #include <tuple>
#include <sqlpp11/result_row.h> #include <sqlpp11/result_row.h>
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/table.h> #include <sqlpp11/table.h>
#include <sqlpp11/no_value.h> #include <sqlpp11/no_value.h>
#include <sqlpp11/vendor/field.h> #include <sqlpp11/vendor/field.h>
@ -38,7 +37,6 @@
#include <sqlpp11/vendor/named_interpretable.h> #include <sqlpp11/vendor/named_interpretable.h>
#include <sqlpp11/vendor/interpret_tuple.h> #include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/vendor/policy_update.h> #include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/vendor/crtp_wrapper.h>
#include <sqlpp11/detail/type_set.h> #include <sqlpp11/detail/type_set.h>
namespace sqlpp namespace sqlpp
@ -184,8 +182,8 @@ namespace sqlpp
select_column_list_t& operator=(select_column_list_t&&) = default; select_column_list_t& operator=(select_column_list_t&&) = default;
~select_column_list_t() = default; ~select_column_list_t() = default;
template<typename Expr> template<typename Select, typename Expr>
void add_column(Expr namedExpr) void add_column(const Select&, Expr namedExpr)
{ {
static_assert(is_named_expression_t<Expr>::value, "select() arguments require to be named expressions"); static_assert(is_named_expression_t<Expr>::value, "select() arguments require to be named expressions");
static_assert(_is_dynamic::value, "cannot add columns to a non-dynamic column list"); static_assert(_is_dynamic::value, "cannot add columns to a non-dynamic column list");
@ -199,7 +197,7 @@ namespace sqlpp
struct no_select_column_list_t 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 _result_row_t = ::sqlpp::result_row_t<>;
using _dynamic_names_t = typename dynamic_select_column_list<void>::_names_t; using _dynamic_names_t = typename dynamic_select_column_list<void>::_names_t;
using _value_type = no_value_t; using _value_type = no_value_t;
@ -210,33 +208,6 @@ namespace sqlpp
{ {
static_assert(wrong_t<T>::value, "Cannot use a select as a table when no columns have been selected yet"); static_assert(wrong_t<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<typename Derived, typename Database, typename... Args>
struct crtp_wrapper_t<Derived, select_column_list_t<Database, Args...>>
{
};
template<typename Derived>
struct crtp_wrapper_t<Derived, no_select_column_list_t>
{
template<typename... Args>
auto columns(Args... args)
-> vendor::update_policies_t<Derived, no_select_column_list_t, select_column_list_t<void, Args...>>
{
return { static_cast<Derived&>(*this), select_column_list_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_columns(Args... args)
-> vendor::update_policies_t<Derived, no_select_column_list_t, select_column_list_t<get_database_t<Derived>, Args...>>
{
static_assert(not std::is_same<get_database_t<Derived>, void>::value, "dynamic_columns must not be called in a static statement");
return { static_cast<Derived&>(*this), select_column_list_t<get_database_t<Derived>, Args...>(args...) };
}
}; };
// Interpreters // Interpreters

View File

@ -28,13 +28,11 @@
#define SQLPP_VENDOR_SELECT_FLAG_LIST_H #define SQLPP_VENDOR_SELECT_FLAG_LIST_H
#include <tuple> #include <tuple>
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/select_flags.h> #include <sqlpp11/select_flags.h>
#include <sqlpp11/detail/type_set.h> #include <sqlpp11/detail/type_set.h>
#include <sqlpp11/vendor/interpret_tuple.h> #include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/vendor/policy_update.h> #include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/vendor/crtp_wrapper.h>
namespace sqlpp namespace sqlpp
{ {
@ -63,8 +61,8 @@ namespace sqlpp
select_flag_list_t& operator=(select_flag_list_t&&) = default; select_flag_list_t& operator=(select_flag_list_t&&) = default;
~select_flag_list_t() = default; ~select_flag_list_t() = default;
template<typename Flag> template<typename Select, typename Flag>
void add_flag(Flag flag) void add_flag(const Select&, Flag flag)
{ {
static_assert(is_select_flag_t<Flag>::value, "flag arguments require to be select flags"); static_assert(is_select_flag_t<Flag>::value, "flag arguments require to be select flags");
_dynamic_flags.emplace_back(flag); _dynamic_flags.emplace_back(flag);
@ -77,34 +75,9 @@ namespace sqlpp
struct no_select_flag_list_t struct no_select_flag_list_t
{ {
using _is_select_flag_list = std::true_type; using _is_noop = std::true_type;
const no_select_flag_list_t& _flag_list() const { return *this; }
}; };
// CRTP Wrappers
template<typename Derived, typename Database, typename... Args>
struct crtp_wrapper_t<Derived, select_flag_list_t<Database, Args...>>
{
};
template<typename Derived>
struct crtp_wrapper_t<Derived, no_select_flag_list_t>
{
template<typename... Args>
auto flags(Args... args)
-> vendor::update_policies_t<Derived, no_select_flag_list_t, select_flag_list_t<void, Args...>>
{
return { static_cast<Derived&>(*this), select_flag_list_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_flags(Args... args)
-> vendor::update_policies_t<Derived, no_select_flag_list_t, select_flag_list_t<get_database_t<Derived>, Args...>>
{
static_assert(not std::is_same<get_database_t<Derived>, void>::value, "dynamic_flags must not be called in a static statement");
return { static_cast<Derived&>(*this), select_flag_list_t<get_database_t<Derived>, Args...>(args...) };
}
};
// Interpreters // Interpreters
template<typename Context, typename Database, typename... Flags> template<typename Context, typename Database, typename... Flags>

View File

@ -28,8 +28,6 @@
#define SQLPP_VENDOR_SINGLE_TABLE_H #define SQLPP_VENDOR_SINGLE_TABLE_H
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/vendor/crtp_wrapper.h>
#include <sqlpp11/detail/type_set.h> #include <sqlpp11/detail/type_set.h>
namespace sqlpp namespace sqlpp
@ -54,7 +52,6 @@ namespace sqlpp
single_table_t& operator=(single_table_t&&) = default; single_table_t& operator=(single_table_t&&) = default;
~single_table_t() = default; ~single_table_t() = default;
const single_table_t& _single_table() const { return *this; }
using _table_set = typename Table::_table_set; using _table_set = typename Table::_table_set;
Table _table; Table _table;
}; };
@ -62,18 +59,6 @@ namespace sqlpp
struct no_single_table_t struct no_single_table_t
{ {
using _table_set = ::sqlpp::detail::type_set<>; using _table_set = ::sqlpp::detail::type_set<>;
const no_single_table_t& _single_table() const { return *this; }
};
// CRTP Wrappers
template<typename Derived, typename Database, typename Table>
struct crtp_wrapper_t<Derived, single_table_t<Database, Table>>
{
};
template<typename Derived>
struct crtp_wrapper_t<Derived, no_single_table_t>
{
}; };
// Interpreters // Interpreters

View File

@ -52,6 +52,12 @@ namespace sqlpp
static_assert(not ::sqlpp::detail::or_t<must_not_update_t, typename Assignments::_column_t...>::value, "at least one assignment is prohibited by its column definition in set()"); static_assert(not ::sqlpp::detail::or_t<must_not_update_t, typename Assignments::_column_t...>::value, "at least one assignment is prohibited by its column definition in set()");
using _column_table_set = typename ::sqlpp::detail::make_joined_set<typename Assignments::_column_t::_table_set...>::type;
using _value_table_set = typename ::sqlpp::detail::make_joined_set<typename Assignments::value_type::_table_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): update_list_t(Assignments... assignments):
_assignments(assignments...) _assignments(assignments...)
{} {}
@ -62,48 +68,22 @@ namespace sqlpp
update_list_t& operator=(update_list_t&&) = default; update_list_t& operator=(update_list_t&&) = default;
~update_list_t() = default; ~update_list_t() = default;
template<typename Assignment> template<typename Update, typename Assignment>
void add_set(Assignment assignment) void add_set(const Update&, Assignment assignment)
{ {
static_assert(is_assignment_t<Assignment>::value, "set() arguments require to be assigments"); static_assert(is_assignment_t<Assignment>::value, "set() arguments require to be assigments");
static_assert(not must_not_update_t<typename Assignment::_column_t>::value, "set() argument must not be updated"); static_assert(not must_not_update_t<typename Assignment::_column_t>::value, "set() argument must not be updated");
_dynamic_assignments.emplace_back(assignment); _dynamic_assignments.emplace_back(assignment);
} }
const update_list_t& _update_list() const { return *this; }
_parameter_tuple_t _assignments; _parameter_tuple_t _assignments;
typename vendor::interpretable_list_t<Database> _dynamic_assignments; typename vendor::interpretable_list_t<Database> _dynamic_assignments;
}; };
struct no_update_list_t 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; } using _table_set = ::sqlpp::detail::type_set<>;
};
// CRTP Wrappers
template<typename Derived, typename Database, typename... Args>
struct crtp_wrapper_t<Derived, update_list_t<Database, Args...>>
{
};
template<typename Derived>
struct crtp_wrapper_t<Derived, no_update_list_t>
{
template<typename... Args>
auto set(Args... args)
-> vendor::update_policies_t<Derived, no_update_list_t, update_list_t<void, Args...>>
{
return { static_cast<Derived&>(*this), update_list_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_set(Args... args)
-> vendor::update_policies_t<Derived, no_update_list_t, update_list_t<get_database_t<Derived>, Args...>>
{
static_assert(not std::is_same<get_database_t<Derived>, void>::value, "dynamic_update_list must not be called in a static statement");
return { static_cast<Derived&>(*this), update_list_t<get_database_t<Derived>, Args...>(args...) };
}
}; };
// Interpreters // Interpreters

View File

@ -32,7 +32,6 @@
#include <sqlpp11/vendor/interpret_tuple.h> #include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/detail/type_set.h> #include <sqlpp11/detail/type_set.h>
#include <sqlpp11/vendor/policy_update.h> #include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/vendor/crtp_wrapper.h>
namespace sqlpp namespace sqlpp
{ {
@ -71,39 +70,13 @@ namespace sqlpp
_dynamic_tables.emplace_back(table); _dynamic_tables.emplace_back(table);
} }
const using_t& _using() const { return *this; }
_parameter_tuple_t _tables; _parameter_tuple_t _tables;
vendor::interpretable_list_t<Database> _dynamic_tables; vendor::interpretable_list_t<Database> _dynamic_tables;
}; };
struct no_using_t struct no_using_t
{ {
const no_using_t& _using() const { return *this; } using _is_noop = std::true_type;
};
// CRTP Wrapper
template<typename Derived, typename Database, typename... Args>
struct crtp_wrapper_t<Derived, using_t<Database, Args...>>
{
};
template<typename Derived>
struct crtp_wrapper_t<Derived, no_using_t>
{
template<typename... Args>
auto using_(Args... args)
-> vendor::update_policies_t<Derived, no_using_t, using_t<void, Args...>>
{
return { static_cast<Derived&>(*this), using_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_using(Args... args)
-> vendor::update_policies_t<Derived, no_using_t, using_t<get_database_t<Derived>, Args...>>
{
static_assert(not std::is_same<get_database_t<Derived>, void>::value, "dynamic_using must not be called in a static statement");
return { static_cast<Derived&>(*this), using_t<get_database_t<Derived>, Args...>(args...) };
}
}; };
// Interpreters // Interpreters

View File

@ -32,8 +32,6 @@
#include <sqlpp11/vendor/expression.h> #include <sqlpp11/vendor/expression.h>
#include <sqlpp11/vendor/interpret_tuple.h> #include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/vendor/interpretable_list.h> #include <sqlpp11/vendor/interpretable_list.h>
#include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/vendor/crtp_wrapper.h>
#include <sqlpp11/detail/logic.h> #include <sqlpp11/detail/logic.h>
namespace sqlpp namespace sqlpp
@ -49,10 +47,13 @@ namespace sqlpp
using _parameter_tuple_t = std::tuple<Expressions...>; using _parameter_tuple_t = std::tuple<Expressions...>;
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in where()"); static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in where()");
static_assert(sqlpp::detail::and_t<is_expression_t, Expressions...>::value, "at least one argument is not an expression in where()"); static_assert(not sqlpp::detail::or_t<is_assignment_t, Expressions...>::value, "at least one argument is an assignment in where()");
static_assert(sqlpp::detail::and_t<is_expression_t, Expressions...>::value, "at least one argument is not valid expression in where()");
using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type; using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type;
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Expressions::_table_set...>::type;
where_t(Expressions... expressions): where_t(Expressions... expressions):
_expressions(expressions...) _expressions(expressions...)
{} {}
@ -63,15 +64,14 @@ namespace sqlpp
where_t& operator=(where_t&&) = default; where_t& operator=(where_t&&) = default;
~where_t() = default; ~where_t() = default;
template<typename E> template<typename Statement, typename Expression>
void add_where(E expr) void add_where(const Statement&, Expression expression)
{ {
static_assert(_is_dynamic::value, "add_where can only be called for dynamic_where"); static_assert(_is_dynamic::value, "add_where can only be called for dynamic_where");
static_assert(is_expression_t<E>::value, "invalid expression argument in add_where()"); static_assert(is_expression_t<Expression>::value, "invalid expression argument in add_where()");
_dynamic_expressions.emplace_back(expr); _dynamic_expressions.emplace_back(expression);
} }
const where_t& _where() const { return *this; }
_parameter_tuple_t _expressions; _parameter_tuple_t _expressions;
vendor::interpretable_list_t<Database> _dynamic_expressions; vendor::interpretable_list_t<Database> _dynamic_expressions;
}; };
@ -81,6 +81,7 @@ namespace sqlpp
{ {
using _is_where = std::true_type; using _is_where = std::true_type;
using _is_dynamic = std::false_type; using _is_dynamic = std::false_type;
using _table_set = ::sqlpp::detail::type_set<>;
where_t(bool condition): where_t(bool condition):
_condition(condition) _condition(condition)
@ -92,39 +93,13 @@ namespace sqlpp
where_t& operator=(where_t&&) = default; where_t& operator=(where_t&&) = default;
~where_t() = default; ~where_t() = default;
const where_t& _where() const { return *this; }
bool _condition; bool _condition;
}; };
struct no_where_t struct no_where_t
{ {
using _is_where = std::true_type; using _is_noop = std::true_type;
const no_where_t& _where() const { return *this; } using _table_set = ::sqlpp::detail::type_set<>;
};
// CRTP Wrappers
template<typename Derived, typename Database, typename... Args>
struct crtp_wrapper_t<Derived, where_t<Database, Args...>>
{
};
template<typename Derived>
struct crtp_wrapper_t<Derived, no_where_t>
{
template<typename... Args>
auto where(Args... args)
-> vendor::update_policies_t<Derived, no_where_t, where_t<void, Args...>>
{
return { static_cast<Derived&>(*this), where_t<void, Args...>(args...) };
}
template<typename... Args>
auto dynamic_where(Args... args)
-> vendor::update_policies_t<Derived, no_where_t, where_t<get_database_t<Derived>, Args...>>
{
static_assert(not std::is_same<get_database_t<Derived>, void>::value, "dynamic_where must not be called in a static statement");
return { static_cast<Derived&>(*this), where_t<get_database_t<Derived>, Args...>(args...) };
}
}; };
// Interpreters // Interpreters

View File

@ -29,6 +29,7 @@
#include <string> #include <string>
#include <sqlpp11/vendor/interpreter.h> #include <sqlpp11/vendor/interpreter.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp namespace sqlpp
{ {
@ -47,6 +48,21 @@ namespace sqlpp
static constexpr bool _is_expression = true; static constexpr bool _is_expression = true;
using _value_type = sqlpp::detail::boolean; using _value_type = sqlpp::detail::boolean;
using _value_t = bool; 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; } bool _is_trivial() const { return _t == false; }
@ -65,22 +81,36 @@ namespace sqlpp
} }
}; };
template<typename T>
struct integral_operand struct integral_operand
{ {
static constexpr bool _is_expression = true; static constexpr bool _is_expression = true;
using _value_type = ::sqlpp::detail::integral; using _value_type = ::sqlpp::detail::integral;
using _value_t = T; 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; } bool _is_trivial() const { return _t == 0; }
_value_t _t; _value_t _t;
}; };
template<typename Context, typename T> template<typename Context>
struct interpreter_t<Context, integral_operand<T>> struct interpreter_t<Context, integral_operand>
{ {
using Operand = integral_operand<T>; using Operand = integral_operand;
static Context& _(const Operand& t, Context& context) static Context& _(const Operand& t, Context& context)
{ {
@ -90,22 +120,36 @@ namespace sqlpp
}; };
template<typename T>
struct floating_point_operand struct floating_point_operand
{ {
static constexpr bool _is_expression = true; static constexpr bool _is_expression = true;
using _value_type = ::sqlpp::detail::floating_point; using _value_type = ::sqlpp::detail::floating_point;
using _value_t = T; 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; } bool _is_trivial() const { return _t == 0; }
_value_t _t; _value_t _t;
}; };
template<typename Context, typename T> template<typename Context>
struct interpreter_t<Context, floating_point_operand<T>> struct interpreter_t<Context, floating_point_operand>
{ {
using Operand = floating_point_operand<T>; using Operand = floating_point_operand;
static Context& _(const Operand& t, Context& context) static Context& _(const Operand& t, Context& context)
{ {
@ -119,6 +163,21 @@ namespace sqlpp
static constexpr bool _is_expression = true; static constexpr bool _is_expression = true;
using _value_type = ::sqlpp::detail::text; using _value_type = ::sqlpp::detail::text;
using _value_t = std::string; 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(); } bool _is_trivial() const { return _t.empty(); }
@ -152,13 +211,13 @@ namespace sqlpp
template<typename T> template<typename T>
struct wrap_operand<T, typename std::enable_if<std::is_integral<T>::value>::type> struct wrap_operand<T, typename std::enable_if<std::is_integral<T>::value>::type>
{ {
using type = integral_operand<T>; using type = integral_operand;
}; };
template<typename T> template<typename T>
struct wrap_operand<T, typename std::enable_if<std::is_floating_point<T>::value>::type> struct wrap_operand<T, typename std::enable_if<std::is_floating_point<T>::value>::type>
{ {
using type = floating_point_operand<T>; using type = floating_point_operand;
}; };
template<typename T> template<typename T>

View File

@ -32,15 +32,20 @@
namespace sqlpp namespace sqlpp
{ {
namespace vendor namespace vendor
{
namespace detail
{ {
// A template that always returns false // A template that always returns false
// To be used with static assert, for instance, to ensure it // To be used with static assert, for instance, to ensure it
// fires only when the template is instantiated. // fires only when the template is instantiated.
template<class ...T> template<typename... T>
struct wrong_t struct wrong
{ {
static constexpr bool value = false; using type = std::false_type;
}; };
} }
template<typename... T>
using wrong_t = typename detail::wrong<T...>::type;
}
} }
#endif #endif

View File

@ -19,5 +19,6 @@ find_package(PythonInterp REQUIRED)
add_custom_command( add_custom_command(
OUTPUT ${CMAKE_CURRENT_LIST_DIR}/Sample.h OUTPUT ${CMAKE_CURRENT_LIST_DIR}/Sample.h
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/ddl2cpp ${CMAKE_CURRENT_LIST_DIR}/sample.sql Sample test COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/ddl2cpp ${CMAKE_CURRENT_LIST_DIR}/sample.sql Sample test
DEPENDS ${CMAKE_CURRENT_LIST_DIR}/sample.sql
) )

View File

@ -35,6 +35,7 @@ DbMock::_context_t printer(std::cerr);
int main() int main()
{ {
test::TabBar t; test::TabBar t;
test::TabFoo f;
auto x = t.alpha = 7; auto x = t.alpha = 7;
auto y = t.beta = "kaesekuchen"; auto y = t.beta = "kaesekuchen";
@ -57,8 +58,13 @@ int main()
static_assert(sqlpp::is_regular<T>::value, "type requirement"); static_assert(sqlpp::is_regular<T>::value, "type requirement");
} }
interpret(insert_into(t).default_values(), printer).flush();
interpret(insert_into(t), printer).flush(); interpret(insert_into(t), printer).flush();
interpret(insert_into(t).set(t.beta = "kirschauflauf"), 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, 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(); auto i = dynamic_insert_into(db, t).dynamic_set();
i.add_set(t.beta = "kirschauflauf"); i.add_set(t.beta = "kirschauflauf");
interpret(i, printer).flush(); interpret(i, printer).flush();

View File

@ -25,7 +25,6 @@
#include <iostream> #include <iostream>
#include <sqlpp11/remove.h> #include <sqlpp11/remove.h>
#include <sqlpp11/select.h>
#include "Sample.h" #include "Sample.h"
#include "MockDb.h" #include "MockDb.h"
#include "is_regular.h" #include "is_regular.h"

View File

@ -23,6 +23,7 @@
* OF THE POSSIBILITY OF SUCH DAMAGE. * OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <iostream>
#include "Sample.h" #include "Sample.h"
#include "MockDb.h" #include "MockDb.h"
#include "is_regular.h" #include "is_regular.h"
@ -31,7 +32,6 @@
#include <sqlpp11/functions.h> #include <sqlpp11/functions.h>
#include <sqlpp11/connection.h> #include <sqlpp11/connection.h>
#include <iostream>
DbMock db = {}; DbMock db = {};
DbMock::_context_t printer(std::cerr); DbMock::_context_t printer(std::cerr);
@ -175,6 +175,8 @@ int main()
// Test a select of a single numeric table column // Test a select of a single numeric table column
{ {
using T = decltype(select(t.alpha).from(t)); using T = decltype(select(t.alpha).from(t));
static_assert(sqlpp::is_select_column_list_t<decltype(T::_column_list)>::value, "Must not be noop");
static_assert(sqlpp::is_from_t<decltype(T::_from)>::value, "Must not be noop");
static_assert(sqlpp::is_numeric_t<T>::value, "type requirement"); static_assert(sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(sqlpp::is_expression_t<T>::value, "type requirement"); static_assert(sqlpp::is_expression_t<T>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<T>::value, "type requirement"); static_assert(sqlpp::is_named_expression_t<T>::value, "type requirement");
@ -271,7 +273,7 @@ int main()
// Test that select(all_of(tab)) is expanded in select // Test that select(all_of(tab)) is expanded in select
{ {
auto a = select(all_of(t)); 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); //auto c = select(t);
static_assert(std::is_same<decltype(a), decltype(b)>::value, "all_of(t) has to be expanded by select()"); static_assert(std::is_same<decltype(a), decltype(b)>::value, "all_of(t) has to be expanded by select()");
//static_assert(std::is_same<decltype(b), decltype(c)>::value, "t has to be expanded by select()"); //static_assert(std::is_same<decltype(b), decltype(c)>::value, "t has to be expanded by select()");
@ -280,14 +282,14 @@ int main()
// Test that select(all_of(tab)) is expanded in multi_column // Test that select(all_of(tab)) is expanded in multi_column
{ {
auto a = multi_column(alias::a, all_of(t)); 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<decltype(a), decltype(b)>::value, "all_of(t) has to be expanded by multi_column"); static_assert(std::is_same<decltype(a), decltype(b)>::value, "all_of(t) has to be expanded by multi_column");
} }
// Test that select(tab) is expanded in multi_column // Test that select(tab) is expanded in multi_column
{ {
auto a = multi_column(alias::a, all_of(t)); 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<decltype(a), decltype(b)>::value, "t has to be expanded by multi_column"); static_assert(std::is_same<decltype(a), decltype(b)>::value, "t has to be expanded by multi_column");
} }

View File

@ -35,6 +35,7 @@ DbMock::_context_t printer(std::cerr);
int main() int main()
{ {
test::TabBar t; test::TabBar t;
test::TabFoo f;
auto x = t.alpha = 7; auto x = t.alpha = 7;
auto y = t.beta = "kaesekuchen"; auto y = t.beta = "kaesekuchen";
@ -58,6 +59,7 @@ int main()
interpret(update(t), printer).flush(); interpret(update(t), printer).flush();
interpret(update(t).set(t.gamma = false), printer).flush(); interpret(update(t).set(t.gamma = false), printer).flush();
interpret(update(t).set(t.gamma = false).where(t.beta != "transparent"), printer).flush(); interpret(update(t).set(t.gamma = false).where(t.beta != "transparent"), 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(); auto u = dynamic_update(db, t).dynamic_set(t.gamma = false).dynamic_where();
u.add_set(t.gamma = false); u.add_set(t.gamma = false);
interpret(u, printer).flush(); interpret(u, printer).flush();

View File

@ -35,6 +35,7 @@ CREATE TABLE tab_bar
( (
alpha bigint AUTO_INCREMENT, alpha bigint AUTO_INCREMENT,
beta varchar(255) NULL DEFAULT "", beta varchar(255) NULL DEFAULT "",
gamma bool NOT NULL gamma bool NOT NULL,
delta int
); );