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

Merge branch 'feature/unified_statement' into develop

This commit is contained in:
rbock 2014-06-13 09:38:35 +02:00
commit 07980a72a2
52 changed files with 2281 additions and 1303 deletions

View File

@ -34,7 +34,8 @@ namespace sqlpp
namespace vendor namespace vendor
{ {
template<typename Flag, typename Expr> template<typename Flag, typename Expr>
struct avg_t: public floating_point::template expression_operators<avg_t<Flag, Expr>> struct avg_t: public floating_point::template expression_operators<avg_t<Flag, Expr>>,
public alias_operators<avg_t<Flag, Expr>>
{ {
using _traits = make_traits<floating_point, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; using _traits = make_traits<floating_point, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
using _recursive_traits = make_recursive_traits<Expr>; using _recursive_traits = make_recursive_traits<Expr>;

View File

@ -139,7 +139,11 @@ namespace sqlpp
static_assert(detail::all_t<_is_valid_comparison_operand<vendor::wrap_operand_t<T>>::value...>::value, "at least one operand of in() is not valid"); static_assert(detail::all_t<_is_valid_comparison_operand<vendor::wrap_operand_t<T>>::value...>::value, "at least one operand of in() is not valid");
return { *static_cast<const Base*>(this), vendor::wrap_operand_t<T>{t}... }; return { *static_cast<const Base*>(this), vendor::wrap_operand_t<T>{t}... };
} }
};
template<typename Base>
struct alias_operators
{
template<typename alias_provider> template<typename alias_provider>
expression_alias_t<Base, alias_provider> as(const alias_provider&) expression_alias_t<Base, alias_provider> as(const alias_provider&)
{ {

View File

@ -35,7 +35,8 @@ namespace sqlpp
namespace vendor namespace vendor
{ {
template<typename Flag, typename Expr> template<typename Flag, typename Expr>
struct count_t: public sqlpp::detail::integral::template expression_operators<count_t<Flag, Expr>> struct count_t: public sqlpp::detail::integral::template expression_operators<count_t<Flag, Expr>>,
public alias_operators<count_t<Flag, Expr>>
{ {
using _traits = make_traits<::sqlpp::detail::integral, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; using _traits = make_traits<::sqlpp::detail::integral, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
using _recursive_traits = make_recursive_traits<Expr>; using _recursive_traits = make_recursive_traits<Expr>;

View File

@ -34,22 +34,22 @@ namespace sqlpp
namespace detail namespace detail
{ {
template<typename Target, typename Statement, typename Term> template<typename Target, typename Statement, typename Term>
Target pick_arg_impl(Statement statement, Term term, const std::true_type&) typename Target::_data_t pick_arg_impl(Statement statement, Term term, const std::true_type&)
{ {
return term; return term;
}; };
template<typename Target, typename Statement, typename Term> template<typename Target, typename Statement, typename Term>
Target pick_arg_impl(Statement statement, Term term, const std::false_type&) typename Target::_data_t pick_arg_impl(Statement statement, Term term, const std::false_type&)
{ {
return static_cast<Target>(statement); return Target::_get_member(statement)._data;
}; };
// Returns a statement's term either by picking the term from the statement or using the new term // Returns a statement's term either by picking the term from the statement or using the new term
template<typename Target, typename Statement, typename Term> template<typename Target, typename Statement, typename Term>
Target pick_arg(Statement statement, Term term) typename Target::_data_t pick_arg(Statement statement, Term term)
{ {
return pick_arg_impl<Target>(statement, term, std::is_same<Target, Term>()); return pick_arg_impl<Target>(statement, term, std::is_same<typename Target::_data_t, Term>());
}; };
} }
} }

View File

@ -34,7 +34,8 @@ namespace sqlpp
namespace vendor namespace vendor
{ {
template<typename Select> template<typename Select>
struct exists_t: public boolean::template expression_operators<exists_t<Select>> struct exists_t: public boolean::template expression_operators<exists_t<Select>>,
public alias_operators<exists_t<Select>>
{ {
using _traits = make_traits<boolean, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; using _traits = make_traits<boolean, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
using _recursive_traits = make_recursive_traits<Select>; using _recursive_traits = make_recursive_traits<Select>;

View File

@ -50,12 +50,13 @@ namespace sqlpp
{ {
using _provided_tables = detail::type_set<>; using _provided_tables = detail::type_set<>;
using _required_tables = ::sqlpp::detail::type_set<>; using _required_tables = ::sqlpp::detail::type_set<>;
static_assert(not is_expression_t<T>::value, "value() is to be called with non-sql-type like int, or string"); static_assert(is_wrapped_value_t<vendor::wrap_operand_t<T>>::value, "value() is to be called with non-sql-type like int, or string");
return { t }; return { t };
} }
template<typename ValueType> // Csaba Csoma suggests: unsafe_sql instead of verbatim template<typename ValueType> // Csaba Csoma suggests: unsafe_sql instead of verbatim
struct verbatim_t: public ValueType::template expression_operators<verbatim_t<ValueType>> struct verbatim_t: public ValueType::template expression_operators<verbatim_t<ValueType>>,
public alias_operators<verbatim_t<ValueType>>
{ {
using _traits = make_traits<ValueType, ::sqlpp::tag::expression>; using _traits = make_traits<ValueType, ::sqlpp::tag::expression>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
@ -148,7 +149,7 @@ namespace sqlpp
template<typename Container> template<typename Container>
auto value_list(Container c) -> value_list_t<Container> auto value_list(Container c) -> value_list_t<Container>
{ {
static_assert(not is_expression_t<typename Container::value_type>::value, "value_list() is to be called with a container of non-sql-type like std::vector<int>, or std::list(string)"); static_assert(is_wrapped_value_t<vendor::wrap_operand_t<typename Container::value_type>>::value, "value_list() is to be called with a container of non-sql-type like std::vector<int>, or std::list(string)");
return { c }; return { c };
} }

View File

@ -27,159 +27,45 @@
#ifndef SQLPP_INSERT_H #ifndef SQLPP_INSERT_H
#define SQLPP_INSERT_H #define SQLPP_INSERT_H
#include <sqlpp11/statement.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/parameter_list.h> #include <sqlpp11/parameter_list.h>
#include <sqlpp11/prepared_insert.h> #include <sqlpp11/prepared_insert.h>
#include <sqlpp11/default_value.h> #include <sqlpp11/default_value.h>
#include <sqlpp11/vendor/noop.h> #include <sqlpp11/vendor/noop.h>
#include <sqlpp11/vendor/single_table.h> #include <sqlpp11/vendor/into.h>
#include <sqlpp11/vendor/insert_value_list.h> #include <sqlpp11/vendor/insert_value_list.h>
#include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/detail/get_last.h>
#include <sqlpp11/detail/pick_arg.h>
namespace sqlpp namespace sqlpp
{ {
template<typename Db, typename... Policies> struct insert_name_t {};
struct insert_t;
namespace detail struct insert_t: public vendor::statement_name_t<insert_name_t>
{
template<typename Db, typename... Policies>
struct insert_policies_t
{
using _database_t = Db;
using _statement_t = insert_t<Db, Policies...>;
struct _methods_t: public Policies::template _methods_t<insert_policies_t>...
{}; {};
template<typename Needle, typename Replacement>
struct _policies_update_t
{
static_assert(detail::is_element_of<Needle, make_type_set_t<Policies...>>::value, "policies update for non-policy class detected");
using type = insert_t<Db, vendor::policy_update_t<Policies, Needle, Replacement>...>;
};
template<typename Needle, typename Replacement>
using _new_statement_t = typename _policies_update_t<Needle, Replacement>::type;
using _all_required_tables = detail::make_joined_set_t<required_tables_of<Policies>...>;
using _all_provided_tables = detail::make_joined_set_t<provided_tables_of<Policies>...>;
using _all_extra_tables = detail::make_joined_set_t<extra_tables_of<Policies>...>;
using _known_tables = detail::make_joined_set_t<_all_provided_tables, _all_extra_tables>;
template<typename Expression>
using _no_unknown_tables = detail::is_subset_of<required_tables_of<Expression>, _known_tables>;
// The tables not covered by the from.
using _required_tables = detail::make_difference_set_t<
_all_required_tables,
_all_provided_tables // Hint: extra_tables are not used here because they are just a helper for dynamic .add_*()
>;
using _traits = make_traits<no_value_t>; // FIXME
struct _recursive_traits
{
using _parameters = std::tuple<>; // FIXME
using _required_tables = _required_tables;
using _provided_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>;
};
};
}
// INSERT
template<typename Db, typename... Policies>
struct insert_t:
public Policies...,
public detail::insert_policies_t<Db, Policies...>::_methods_t
{
using _policies_t = typename detail::insert_policies_t<Db, Policies...>;
using _database_t = typename _policies_t::_database_t;
using _is_dynamic = typename std::conditional<std::is_same<_database_t, void>::value, std::false_type, std::true_type>::type;
using _parameter_list_t = typename make_parameter_list_t<insert_t>::type;
// Constructors
constexpr insert_t()
{}
template<typename Statement, typename Term>
insert_t(Statement statement, Term term):
Policies(detail::pick_arg<Policies>(statement, term))...
{}
insert_t(const insert_t&) = default;
insert_t(insert_t&&) = default;
insert_t& operator=(const insert_t&) = default;
insert_t& operator=(insert_t&&) = default;
~insert_t() = default;
// run and prepare
static constexpr size_t _get_static_no_of_parameters()
{
return _parameter_list_t::size::value;
}
size_t _get_no_of_parameters() const
{
return _parameter_list_t::size::value;
}
void _check_consistency() const
{
// FIXME: Read up on what is allowed/prohibited in INSERT
}
template<typename Database>
std::size_t _run(Database& db) const
{
_check_consistency();
static_assert(_get_static_no_of_parameters() == 0, "cannot run insert directly with parameters, use prepare instead");
return db.insert(*this);
}
template<typename Database>
auto _prepare(Database& db) const
-> prepared_insert_t<Database, insert_t>
{
_check_consistency();
return {{}, db.prepare_insert(*this)};
}
};
namespace vendor namespace vendor
{ {
template<typename Context, typename Database, typename... Policies> template<typename Context>
struct serializer_t<Context, insert_t<Database, Policies...>> struct serializer_t<Context, insert_name_t>
{ {
using T = insert_t<Database, Policies...>; using T = insert_name_t;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
context << "INSERT INTO "; context << "INSERT ";
using swallow = int[];
(void) swallow{(serialize(static_cast<const Policies&>(t), context), 0)...};
return context; return context;
} }
}; };
} }
template<typename Database> template<typename Database>
using blank_insert_t = insert_t<Database, using blank_insert_t = statement_t<Database,
vendor::no_single_table_t, insert_t,
vendor::no_into_t,
vendor::no_insert_value_list_t>; vendor::no_insert_value_list_t>;
constexpr auto insert() auto insert()
-> blank_insert_t<void> -> blank_insert_t<void>
{ {
return { blank_insert_t<void>() }; return { blank_insert_t<void>() };

View File

@ -42,6 +42,7 @@ namespace sqlpp
// integral value type // integral value type
struct integral struct integral
{ {
using _traits = make_traits<integral, ::sqlpp::tag::expression>;
using _tag = ::sqlpp::tag::integral; using _tag = ::sqlpp::tag::integral;
using _cpp_value_type = int64_t; using _cpp_value_type = int64_t;

View File

@ -85,7 +85,7 @@ namespace sqlpp
static_assert(not is_join_t<Rhs>::value, "rhs argument for join must not be a join"); static_assert(not is_join_t<Rhs>::value, "rhs argument for join must not be a join");
static_assert(vendor::is_noop<On>::value or is_on_t<On>::value, "invalid on expression in join().on()"); static_assert(vendor::is_noop<On>::value or is_on_t<On>::value, "invalid on expression in join().on()");
static_assert(::sqlpp::detail::is_disjunct_from<typename Lhs::_provided_tables, typename Rhs::_provided_tables>::value, "joined tables must not be identical"); static_assert(::sqlpp::detail::is_disjunct_from<provided_tables_of<Lhs>, provided_tables_of<Rhs>>::value, "joined tables must not be identical");
static_assert(_recursive_traits::_required_tables::size::value == 0, "joined tables must not depend on other tables"); static_assert(_recursive_traits::_required_tables::size::value == 0, "joined tables must not depend on other tables");

View File

@ -34,7 +34,8 @@ namespace sqlpp
namespace vendor namespace vendor
{ {
template<typename Expr> template<typename Expr>
struct max_t: public value_type_of<Expr>::template expression_operators<max_t<Expr>> struct max_t: public value_type_of<Expr>::template expression_operators<max_t<Expr>>,
public alias_operators<max_t<Expr>>
{ {
using _traits = make_traits<value_type_of<Expr>, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; using _traits = make_traits<value_type_of<Expr>, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
using _recursive_traits = make_recursive_traits<Expr>; using _recursive_traits = make_recursive_traits<Expr>;

View File

@ -34,7 +34,8 @@ namespace sqlpp
namespace vendor namespace vendor
{ {
template<typename Expr> template<typename Expr>
struct min_t: public value_type_of<Expr>::template expression_operators<min_t<Expr>> struct min_t: public value_type_of<Expr>::template expression_operators<min_t<Expr>>,
public alias_operators<min_t<Expr>>
{ {
using _traits = make_traits<value_type_of<Expr>, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; using _traits = make_traits<value_type_of<Expr>, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
using _recursive_traits = make_recursive_traits<Expr>; using _recursive_traits = make_recursive_traits<Expr>;

View File

@ -74,7 +74,7 @@ namespace sqlpp
template<typename NamedExpr> template<typename NamedExpr>
auto parameter(const NamedExpr&) auto parameter(const NamedExpr&)
-> parameter_t<typename NamedExpr::_value_type, NamedExpr> -> parameter_t<value_type_of<NamedExpr>, NamedExpr>
{ {
static_assert(is_named_expression_t<NamedExpr>::value, "not a named expression"); static_assert(is_named_expression_t<NamedExpr>::value, "not a named expression");
return {}; return {};
@ -82,7 +82,7 @@ namespace sqlpp
template<typename ValueType, typename AliasProvider> template<typename ValueType, typename AliasProvider>
auto parameter(const ValueType&, const AliasProvider&) auto parameter(const ValueType&, const AliasProvider&)
-> parameter_t<ValueType, AliasProvider> -> parameter_t<vendor::wrap_operand_t<ValueType>, AliasProvider>
{ {
static_assert(is_expression_t<ValueType>::value, "first argument is not a value type"); static_assert(is_expression_t<ValueType>::value, "first argument is not a value type");
static_assert(is_alias_provider_t<AliasProvider>::value, "second argument is not an alias provider"); static_assert(is_alias_provider_t<AliasProvider>::value, "second argument is not an alias provider");

View File

@ -28,6 +28,7 @@
#define SQLPP_PARAMETER_LIST_H #define SQLPP_PARAMETER_LIST_H
#include <tuple> #include <tuple>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/wrong.h> #include <sqlpp11/vendor/wrong.h>
#include <sqlpp11/detail/index_sequence.h> #include <sqlpp11/detail/index_sequence.h>

View File

@ -27,188 +27,104 @@
#ifndef SQLPP_REMOVE_H #ifndef SQLPP_REMOVE_H
#define SQLPP_REMOVE_H #define SQLPP_REMOVE_H
#include <sqlpp11/statement.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/parameter_list.h> #include <sqlpp11/parameter_list.h>
#include <sqlpp11/prepared_remove.h> #include <sqlpp11/prepared_remove.h>
#include <sqlpp11/vendor/noop.h> #include <sqlpp11/vendor/noop.h>
#warning: need to use another table provider, since delete can be used with several tables #warning: need to use another table provider, since delete can be used with several tables
#include <sqlpp11/vendor/single_table.h> #include <sqlpp11/vendor/from.h>
#include <sqlpp11/vendor/extra_tables.h> #include <sqlpp11/vendor/extra_tables.h>
#include <sqlpp11/vendor/using.h> #include <sqlpp11/vendor/using.h>
#include <sqlpp11/vendor/where.h> #include <sqlpp11/vendor/where.h>
#include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/detail/get_last.h>
#include <sqlpp11/detail/pick_arg.h>
namespace sqlpp namespace sqlpp
{ {
template<typename Db, typename... Policies> struct remove_name_t {};
struct remove_t; struct remove_t: public vendor::statement_name_t<remove_name_t>
namespace detail
{ {
template<typename Db = void, typename... Policies> using _traits = make_traits<no_value_t, tag::return_value>;
struct remove_policies_t struct _name_t {};
template<typename Policies>
struct _result_methods_t
{ {
using _database_t = Db; using _statement_t = typename Policies::_statement_t;
using _statement_t = remove_t<Db, Policies...>;
struct _methods_t: public Policies::template _methods_t<remove_policies_t>... const _statement_t& _get_statement() const
{};
template<typename Needle, typename Replacement>
struct _policies_update_t
{ {
static_assert(detail::is_element_of<Needle, make_type_set_t<Policies...>>::value, "policies update for non-policy class detected"); return static_cast<const _statement_t&>(*this);
using type = remove_t<Db, vendor::policy_update_t<Policies, Needle, Replacement>...>;
};
template<typename Needle, typename Replacement>
using _new_statement_t = typename _policies_update_t<Needle, Replacement>::type;
using _all_required_tables = detail::make_joined_set_t<required_tables_of<Policies>...>;
using _all_provided_tables = detail::make_joined_set_t<provided_tables_of<Policies>...>;
using _all_extra_tables = detail::make_joined_set_t<extra_tables_of<Policies>...>;
using _known_tables = detail::make_joined_set_t<_all_provided_tables, _all_extra_tables>;
template<typename Expression>
using _no_unknown_tables = detail::is_subset_of<required_tables_of<Expression>, _known_tables>;
// The tables not covered by the from.
using _required_tables = detail::make_difference_set_t<
_all_required_tables,
_all_provided_tables // Hint: extra_tables are not used here because they are just a helper for dynamic .add_*()
>;
using _traits = make_traits<no_value_t>; // FIXME
struct _recursive_traits
{
using _parameters = std::tuple<>; // FIXME
using _required_tables = _required_tables;
using _provided_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>;
};
};
} }
// REMOVE template<typename Db>
template<typename Db, typename... Policies> auto _run(Db& db) const -> decltype(db.remove(_get_statement()))
struct remove_t:
public Policies...,
public detail::remove_policies_t<Db, Policies...>::_methods_t
{ {
using _policies_t = typename detail::remove_policies_t<Db, Policies...>; _statement_t::_check_consistency();
using _database_t = typename _policies_t::_database_t;
using _is_dynamic = typename std::conditional<std::is_same<_database_t, void>::value, std::false_type, std::true_type>::type; static_assert(_statement_t::_get_static_no_of_parameters() == 0, "cannot run remove directly with parameters, use prepare instead");
using _parameter_list_t = typename make_parameter_list_t<remove_t>::type;
// Constructors
constexpr remove_t()
{}
template<typename Statement, typename Term>
remove_t(Statement statement, Term term):
Policies(detail::pick_arg<Policies>(statement, term))...
{}
remove_t(const remove_t&) = default;
remove_t(remove_t&&) = default;
remove_t& operator=(const remove_t&) = default;
remove_t& operator=(remove_t&&) = default;
~remove_t() = default;
// run and prepare
static constexpr size_t _get_static_no_of_parameters()
{
return _parameter_list_t::size::value;
}
size_t _get_no_of_parameters() const
{
return _parameter_list_t::size::value;
}
void _check_consistency() const
{
#warning reactivate checks
#if 0
static_assert(is_where_t<_where_t>::value, "cannot run update without having a where condition, use .where(true) to update all rows");
// FIXME: Read more details about what is allowed and what not in SQL DELETE
static_assert(is_table_subset_of_table<_where_t>::value, "where requires additional tables");
#endif
}
template<typename Database>
std::size_t _run(Database& db) const
{
_check_consistency();
static_assert(_get_static_no_of_parameters() == 0, "cannot run remove directly with parameters, use prepare instead");
return db.remove(*this); return db.remove(*this);
} }
template<typename Database> /*
auto _prepare(Database& db) const template<typename Db>
-> prepared_remove_t<Database, remove_t> auto _prepare(Db& db) const
-> prepared_remove_t<Db, remove_t>
{ {
_check_consistency(); _check_consistency();
return {{}, db.prepare_remove(*this)}; return {{}, db.prepare_remove(*this)};
} }
*/
}; };
};
namespace vendor namespace vendor
{ {
template<typename Context, typename Database, typename... Policies> template<typename Context>
struct serializer_t<Context, remove_t<Database, Policies...>> struct serializer_t<Context, remove_name_t>
{ {
using T = remove_t<Database, Policies...>; using T = remove_name_t;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
context << "DELETE FROM "; context << "DELETE";
using swallow = int[];
(void) swallow{(serialize(static_cast<const Policies&>(t), context), 0)...};
return context; return context;
} }
}; };
} }
template<typename Database> template<typename Database>
using blank_remove_t = remove_t<Database, using blank_remove_t = statement_t<Database,
vendor::no_single_table_t, remove_t,
vendor::no_from_t,
vendor::no_using_t, vendor::no_using_t,
vendor::no_extra_tables_t, vendor::no_extra_tables_t,
vendor::no_where_t>; vendor::no_where_t>;
constexpr auto remove() auto remove()
-> blank_remove_t<void> -> blank_remove_t<void>
{ {
return { blank_remove_t<void>() }; return { blank_remove_t<void>() };
} }
template<typename Table> template<typename Table>
constexpr auto remove_from(Table table) auto remove_from(Table table)
-> decltype(blank_remove_t<void>().from(table)) -> decltype(blank_remove_t<void>().from(table))
{ {
return { blank_remove_t<void>().from(table) }; return { blank_remove_t<void>().from(table) };
} }
template<typename Database> template<typename Database>
constexpr auto dynamic_remove(const Database&) auto dynamic_remove(const Database&)
-> decltype(blank_remove_t<Database>()) -> decltype(blank_remove_t<Database>())
{ {
return { blank_remove_t<Database>() }; return { blank_remove_t<Database>() };
} }
template<typename Database, typename Table> template<typename Database, typename Table>
constexpr auto dynamic_remove_from(const Database&, Table table) auto dynamic_remove_from(const Database&, Table table)
-> decltype(blank_remove_t<Database>().from(table)) -> decltype(blank_remove_t<Database>().from(table))
{ {
return { blank_remove_t<Database>().from(table) }; return { blank_remove_t<Database>().from(table) };

View File

@ -27,9 +27,7 @@
#ifndef SQLPP_SELECT_H #ifndef SQLPP_SELECT_H
#define SQLPP_SELECT_H #define SQLPP_SELECT_H
#include <sqlpp11/result.h> #include <sqlpp11/statement.h>
#include <sqlpp11/parameter_list.h>
#include <sqlpp11/prepared_select.h>
#include <sqlpp11/vendor/noop.h> #include <sqlpp11/vendor/noop.h>
#include <sqlpp11/vendor/select_flag_list.h> #include <sqlpp11/vendor/select_flag_list.h>
@ -43,221 +41,35 @@
#include <sqlpp11/vendor/limit.h> #include <sqlpp11/vendor/limit.h>
#include <sqlpp11/vendor/offset.h> #include <sqlpp11/vendor/offset.h>
#include <sqlpp11/vendor/expression.h> #include <sqlpp11/vendor/expression.h>
#include <sqlpp11/vendor/serializer.h>
#include <sqlpp11/vendor/wrong.h> #include <sqlpp11/vendor/wrong.h>
#include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/detail/get_last.h>
#include <sqlpp11/detail/pick_arg.h>
namespace sqlpp namespace sqlpp
{ {
template<typename Db, typename... Policies> struct select_name_t {};
struct select_t;
#warning STEPS: struct select_t: public vendor::statement_name_t<select_name_t>
#warning deal with different return types in the connector (select could be a single value, update could be a range of rows)
namespace detail
{
template<typename Db = void, typename... Policies>
struct select_policies_t
{
using _database_t = Db;
using _statement_t = select_t<Db, Policies...>;
struct _methods_t: public Policies::template _methods_t<select_policies_t>...
{}; {};
template<typename Needle, typename Replacement>
struct _policies_update_t
{
static_assert(detail::is_element_of<Needle, make_type_set_t<Policies...>>::value, "policies update for non-policy class detected");
using type = select_t<Db, vendor::policy_update_t<Policies, Needle, Replacement>...>;
};
template<typename Needle, typename Replacement>
using _new_statement_t = typename _policies_update_t<Needle, Replacement>::type;
using _all_required_tables = detail::make_joined_set_t<required_tables_of<Policies>...>;
using _all_provided_tables = detail::make_joined_set_t<provided_tables_of<Policies>...>;
using _all_extra_tables = detail::make_joined_set_t<extra_tables_of<Policies>...>;
using _known_tables = detail::make_joined_set_t<_all_provided_tables, _all_extra_tables>;
template<typename Expression>
using _no_unknown_tables = detail::is_subset_of<required_tables_of<Expression>, _known_tables>;
// The tables not covered by the from.
using _required_tables = detail::make_difference_set_t<
_all_required_tables,
_all_provided_tables // Hint: extra_tables are not used here because they are just a helper for dynamic .add_*()
>;
using _result_type_provider = detail::get_last_if<is_return_value_t, vendor::no_select_column_list_t, Policies...>;
// A select can be used as a pseudo table if
// - at least one column is selected
// - the select is complete (leaks no tables)
using _can_be_used_as_table = typename std::conditional<
is_select_column_list_t<_result_type_provider>::value and _required_tables::size::value == 0,
std::true_type,
std::false_type
>::type;
using _value_type = typename std::conditional<
detail::none_t<is_missing_t<Policies>::value...>::value,
value_type_of<_result_type_provider>,
no_value_t // if a required statement part is missing (e.g. columns in a select), then the statement cannot be used as a value
>::type;
using _is_expression = typename std::conditional<
std::is_same<_value_type, no_value_t>::value,
std::false_type,
std::true_type>::type;
using _traits = make_traits<_value_type>;
struct _recursive_traits
{
using _parameters = std::tuple<>; // FIXME
using _required_tables = _required_tables;
using _provided_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>;
};
};
}
// SELECT
template<typename Db,
typename... Policies
>
struct select_t:
public Policies...,
public detail::select_policies_t<Db, Policies...>::_value_type::template expression_operators<select_t<Db, Policies...>>,
public detail::select_policies_t<Db, Policies...>::_methods_t
{
using _policies_t = typename detail::select_policies_t<Db, Policies...>;
using _traits = make_traits<value_type_of<_policies_t>, ::sqlpp::tag::select, tag::expression_if<typename _policies_t::_is_expression>, tag::named_expression_if<typename _policies_t::_is_expression>>;
using _recursive_traits = typename _policies_t::_recursive_traits;
using _database_t = Db;
using _is_dynamic = typename std::conditional<std::is_same<_database_t, void>::value, std::false_type, std::true_type>::type;
using _result_type_provider = typename _policies_t::_result_type_provider;
using _parameter_tuple_t = std::tuple<Policies...>;
using _parameter_list_t = typename make_parameter_list_t<select_t>::type;
template<typename Database>
using _result_row_t = typename _result_type_provider::template _result_row_t<Database>;
using _dynamic_names_t = typename _result_type_provider::_dynamic_names_t;
using _requires_braces = std::true_type;
using _name_t = typename _result_type_provider::_name_t;
// Constructors
select_t()
{}
template<typename Statement, typename Term>
select_t(Statement statement, Term term):
Policies(detail::pick_arg<Policies>(statement, term))...
{}
select_t(const select_t& r) = default;
select_t(select_t&& r) = default;
select_t& operator=(const select_t& r) = default;
select_t& operator=(select_t&& r) = default;
~select_t() = default;
// PseudoTable
template<typename AliasProvider>
struct _pseudo_table_t
{
using table = typename _result_type_provider::template _pseudo_table_t<select_t>;
using alias = typename table::template _alias_t<AliasProvider>;
};
template<typename AliasProvider>
typename _pseudo_table_t<AliasProvider>::alias as(const AliasProvider& aliasProvider) const
{
static_assert(_policies_t::_can_be_used_as_table::value, "select cannot be used as table, incomplete from()");
return typename _pseudo_table_t<AliasProvider>::table(
*this).as(aliasProvider);
}
const _dynamic_names_t& get_dynamic_names() const
{
return static_cast<const _result_type_provider&>(*this)._dynamic_columns._dynamic_expression_names;
}
static constexpr size_t _get_static_no_of_parameters()
{
return _parameter_list_t::size::value;
}
size_t _get_no_of_parameters() const
{
return _parameter_list_t::size::value;
}
size_t get_no_of_result_columns() const
{
return _result_type_provider::static_size() + get_dynamic_names().size();
}
void _check_consistency() const
{
#warning check for missing terms here, and for missing tables
static_assert(not required_tables_of<_policies_t>::size::value, "one sub expression contains tables which are not in the from()");
}
// Execute
template<typename Database>
auto _run(Database& db) const
-> result_t<decltype(db.select(*this)), _result_row_t<Database>>
{
_check_consistency();
static_assert(_get_static_no_of_parameters() == 0, "cannot run select directly with parameters, use prepare instead");
return {db.select(*this), get_dynamic_names()};
}
// Prepare
template<typename Database>
auto _prepare(Database& db) const
-> prepared_select_t<Database, select_t>
{
_check_consistency();
return {{}, get_dynamic_names(), db.prepare_select(*this)};
}
};
namespace vendor namespace vendor
{ {
template<typename Context, typename Database, typename... Policies> template<typename Context>
struct serializer_t<Context, select_t<Database, Policies...>> struct serializer_t<Context, select_name_t>
{ {
using T = select_t<Database, Policies...>; using T = select_name_t;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
context << "SELECT "; context << "SELECT ";
using swallow = int[];
(void) swallow{(serialize(static_cast<const Policies&>(t), context), 0)...};
return context; return context;
} }
}; };
} }
template<typename Database> template<typename Database>
using blank_select_t = select_t<Database, using blank_select_t = statement_t<Database,
select_t,
vendor::no_select_flag_list_t, vendor::no_select_flag_list_t,
vendor::no_select_column_list_t, vendor::no_select_column_list_t,
vendor::no_from_t, vendor::no_from_t,

246
include/sqlpp11/statement.h Normal file
View File

@ -0,0 +1,246 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_STATEMENT_H
#define SQLPP_STATEMENT_H
#include <sqlpp11/result.h>
#include <sqlpp11/parameter_list.h>
#include <sqlpp11/prepared_select.h>
#include <sqlpp11/serialize.h>
#include <sqlpp11/vendor/noop.h>
#include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/vendor/serializer.h>
#include <sqlpp11/detail/get_last.h>
#include <sqlpp11/detail/pick_arg.h>
namespace sqlpp
{
template<typename Db, typename... Policies>
struct statement_t;
#warning STEPS:
#warning deal with different return types in the connector (select could be a single value, update could be a range of rows)
namespace detail
{
template<typename Db = void, typename... Policies>
struct statement_policies_t
{
#warning need to check policies' signature, e.g. a _data_t in _member_t template
using _database_t = Db;
using _statement_t = statement_t<Db, Policies...>;
struct _methods_t: public Policies::template _methods_t<statement_policies_t>...
{};
template<typename Needle, typename Replacement>
struct _policies_update_t
{
static_assert(detail::is_element_of<Needle, make_type_set_t<Policies...>>::value, "policies update for non-policy class detected");
using type = statement_t<Db, vendor::policy_update_t<Policies, Needle, Replacement>...>;
};
template<typename Needle, typename Replacement>
using _new_statement_t = typename _policies_update_t<Needle, Replacement>::type;
using _all_required_tables = detail::make_joined_set_t<required_tables_of<Policies>...>;
using _all_provided_tables = detail::make_joined_set_t<provided_tables_of<Policies>...>;
using _all_extra_tables = detail::make_joined_set_t<extra_tables_of<Policies>...>;
using _known_tables = detail::make_joined_set_t<_all_provided_tables, _all_extra_tables>;
template<typename Expression>
using _no_unknown_tables = detail::is_subset_of<required_tables_of<Expression>, _known_tables>;
// The tables not covered by the from.
using _required_tables = detail::make_difference_set_t<
_all_required_tables,
_all_provided_tables // Hint: extra_tables are not used here because they are just a helper for dynamic .add_*()
>;
using _result_type_provider = detail::get_last_if<is_return_value_t, vendor::noop, Policies...>;
struct _result_methods_t: public _result_type_provider::template _result_methods_t<statement_policies_t>
{};
// A select can be used as a pseudo table if
// - at least one column is selected
// - the select is complete (leaks no tables)
using _can_be_used_as_table = typename std::conditional<
is_select_column_list_t<_result_type_provider>::value and _required_tables::size::value == 0,
std::true_type,
std::false_type
>::type;
using _value_type = typename std::conditional<
detail::none_t<is_missing_t<Policies>::value...>::value,
value_type_of<_result_type_provider>,
no_value_t // if a required statement part is missing (e.g. columns in a select), then the statement cannot be used as a value
>::type;
using _is_expression = typename std::conditional<
std::is_same<_value_type, no_value_t>::value,
std::false_type,
std::true_type>::type;
using _traits = make_traits<_value_type>;
struct _recursive_traits
{
using _parameters = std::tuple<>; // FIXME
using _required_tables = _required_tables;
using _provided_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>;
};
};
}
template<typename Db,
typename... Policies
>
struct statement_t:
public Policies::template _member_t<detail::statement_policies_t<Db, Policies...>>...,
public detail::statement_policies_t<Db, Policies...>::_value_type::template expression_operators<statement_t<Db, Policies...>>,
public detail::statement_policies_t<Db, Policies...>::_result_methods_t,
public detail::statement_policies_t<Db, Policies...>::_methods_t
{
using _policies_t = typename detail::statement_policies_t<Db, Policies...>;
using _traits = make_traits<value_type_of<_policies_t>, ::sqlpp::tag::select, tag::expression_if<typename _policies_t::_is_expression>, tag::named_expression_if<typename _policies_t::_is_expression>>;
using _recursive_traits = typename _policies_t::_recursive_traits;
using _result_type_provider = typename _policies_t::_result_type_provider;
using _requires_braces = std::true_type;
using _name_t = typename _result_type_provider::_name_t;
// Constructors
statement_t()
{}
template<typename Statement, typename Term>
statement_t(Statement statement, Term term):
Policies::template _member_t<_policies_t>{
typename Policies::template _impl_t<_policies_t>{
detail::pick_arg<typename Policies::template _member_t<_policies_t>>(statement, term)
}}...
//Policies::template _member_t<_policies_t>{{detail::pick_arg<typename Policies::template _member_t<_policies_t>>(statement, term)}}...
{}
statement_t(const statement_t& r) = default;
statement_t(statement_t&& r) = default;
statement_t& operator=(const statement_t& r) = default;
statement_t& operator=(statement_t&& r) = default;
~statement_t() = default;
static constexpr size_t _get_static_no_of_parameters()
{
#warning need to fix this
return 0;
//return _parameter_list_t::size::value;
}
size_t _get_no_of_parameters() const
{
return _get_static_no_of_parameters();
}
static void _check_consistency()
{
// FIXME: Check each "methods" or each member...
#warning check for missing terms here, and for missing tables
static_assert(not required_tables_of<_policies_t>::size::value, "one sub expression requires tables which are otherwise not known in the statement");
}
};
namespace vendor
{
template<typename Context, typename Database, typename... Policies>
struct serializer_t<Context, statement_t<Database, Policies...>>
{
using T = statement_t<Database, Policies...>;
using P = ::sqlpp::detail::statement_policies_t<Database, Policies...>;
static Context& _(const T& t, Context& context)
{
using swallow = int[];
(void) swallow{(serialize(static_cast<const typename Policies::template _member_t<P>&>(t)()._data, context), 0)...};
return context;
}
};
template<typename NameData>
struct statement_name_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = NameData;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = NameData;
_impl_t<Policies> statement_name;
_impl_t<Policies>& operator()() { return statement_name; }
const _impl_t<Policies>& operator()() const { return statement_name; }
template<typename T>
static auto _get_member(T t) -> decltype(t.statement_name)
{
return t.statement_name;
}
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
};
};
}
}
#endif

View File

@ -34,7 +34,8 @@ namespace sqlpp
namespace vendor namespace vendor
{ {
template<typename Flag, typename Expr> template<typename Flag, typename Expr>
struct sum_t: public value_type_of<Expr>::template expression_operators<sum_t<Flag, Expr>> struct sum_t: public value_type_of<Expr>::template expression_operators<sum_t<Flag, Expr>>,
public alias_operators<sum_t<Flag, Expr>>
{ {
using _traits = make_traits<value_type_of<Expr>, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; using _traits = make_traits<value_type_of<Expr>, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
using _recursive_traits = make_recursive_traits<Expr>; using _recursive_traits = make_recursive_traits<Expr>;

View File

@ -35,10 +35,8 @@
namespace sqlpp namespace sqlpp
{ {
struct table_alias_base_t {};
template<typename AliasProvider, typename Table, typename... ColumnSpec> template<typename AliasProvider, typename Table, typename... ColumnSpec>
struct table_alias_t: public table_alias_base_t, public ColumnSpec::_name_t::template _member_t<column_t<AliasProvider, ColumnSpec>>... struct table_alias_t: public ColumnSpec::_name_t::template _member_t<column_t<AliasProvider, ColumnSpec>>...
{ {
//FIXME: Need to add join functionality //FIXME: Need to add join functionality
using _traits = make_traits<value_type_of<Table>, tag::table, tag::alias, tag::named_expression_if<is_expression_t<Table>>>; using _traits = make_traits<value_type_of<Table>, tag::table, tag::alias, tag::named_expression_if<is_expression_t<Table>>>;
@ -65,10 +63,10 @@ namespace sqlpp
namespace vendor namespace vendor
{ {
template<typename Context, typename X> template<typename Context, typename AliasProvider, typename Table, typename... ColumnSpec>
struct serializer_t<Context, X, typename std::enable_if<std::is_base_of<table_alias_base_t, X>::value, void>::type> struct serializer_t<Context, table_alias_t<AliasProvider, Table, ColumnSpec...>>
{ {
using T = X; using T = table_alias_t<AliasProvider, Table, ColumnSpec...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {

View File

@ -42,6 +42,8 @@ namespace sqlpp
using _traits = make_traits<value_type_of<Operand>, tag::expression>; using _traits = make_traits<value_type_of<Operand>, tag::expression>;
using _recursive_traits = make_recursive_traits<Operand>; using _recursive_traits = make_recursive_traits<Operand>;
using _operand_t = Operand;
tvin_t(Operand operand): tvin_t(Operand operand):
_value(operand) _value(operand)
{} {}

View File

@ -88,6 +88,7 @@ namespace sqlpp
detail::is_element_of<tag::integral, typename T::_traits::_tags>::value, detail::is_element_of<tag::integral, typename T::_traits::_tags>::value,
detail::is_element_of<tag::floating_point, typename T::_traits::_tags>::value>; detail::is_element_of<tag::floating_point, typename T::_traits::_tags>::value>;
SQLPP_IS_VALUE_TRAIT_GENERATOR(text); SQLPP_IS_VALUE_TRAIT_GENERATOR(text);
SQLPP_IS_VALUE_TRAIT_GENERATOR(wrapped_value);
SQLPP_IS_VALUE_TRAIT_GENERATOR(expression); SQLPP_IS_VALUE_TRAIT_GENERATOR(expression);
SQLPP_IS_VALUE_TRAIT_GENERATOR(named_expression); SQLPP_IS_VALUE_TRAIT_GENERATOR(named_expression);
namespace tag namespace tag
@ -122,6 +123,7 @@ namespace sqlpp
SQLPP_IS_VALUE_TRAIT_GENERATOR(select_column_list); SQLPP_IS_VALUE_TRAIT_GENERATOR(select_column_list);
SQLPP_IS_VALUE_TRAIT_GENERATOR(from); SQLPP_IS_VALUE_TRAIT_GENERATOR(from);
SQLPP_IS_VALUE_TRAIT_GENERATOR(single_table); SQLPP_IS_VALUE_TRAIT_GENERATOR(single_table);
SQLPP_IS_VALUE_TRAIT_GENERATOR(into);
SQLPP_IS_VALUE_TRAIT_GENERATOR(extra_tables); SQLPP_IS_VALUE_TRAIT_GENERATOR(extra_tables);
SQLPP_IS_VALUE_TRAIT_GENERATOR(on); SQLPP_IS_VALUE_TRAIT_GENERATOR(on);
SQLPP_IS_VALUE_TRAIT_GENERATOR(dynamic); SQLPP_IS_VALUE_TRAIT_GENERATOR(dynamic);

View File

@ -27,6 +27,8 @@
#ifndef SQLPP_UPDATE_H #ifndef SQLPP_UPDATE_H
#define SQLPP_UPDATE_H #define SQLPP_UPDATE_H
#include <sqlpp11/statement.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/parameter_list.h> #include <sqlpp11/parameter_list.h>
#include <sqlpp11/prepared_update.h> #include <sqlpp11/prepared_update.h>
@ -34,153 +36,68 @@
#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/policy_update.h>
#include <sqlpp11/detail/get_last.h>
#include <sqlpp11/detail/pick_arg.h>
namespace sqlpp namespace sqlpp
{ {
template<typename Db, typename... Policies> struct update_name_t {};
struct update_t;
namespace detail struct update_t: public vendor::statement_name_t<update_name_t>
{ {
template<typename Db = void, typename... Policies> using _traits = make_traits<no_value_t, tag::return_value>;
struct update_policies_t struct _name_t {};
template<typename Policies>
struct _result_methods_t
{ {
using _database_t = Db; using _statement_t = typename Policies::_statement_t;
using _statement_t = update_t<Db, Policies...>; const _statement_t& _get_statement() const
struct _methods_t: public Policies::template _methods_t<update_policies_t>...
{};
template<typename Needle, typename Replacement>
struct _policies_update_t
{ {
static_assert(detail::is_element_of<Needle, make_type_set_t<Policies...>>::value, "policies update for non-policy class detected"); return static_cast<const _statement_t&>(*this);
using type = update_t<Db, vendor::policy_update_t<Policies, Needle, Replacement>...>;
};
template<typename Needle, typename Replacement>
using _new_statement_t = typename _policies_update_t<Needle, Replacement>::type;
using _all_required_tables = detail::make_joined_set_t<required_tables_of<Policies>...>;
using _all_provided_tables = detail::make_joined_set_t<provided_tables_of<Policies>...>;
using _all_extra_tables = detail::make_joined_set_t<extra_tables_of<Policies>...>;
using _known_tables = detail::make_joined_set_t<_all_provided_tables, _all_extra_tables>;
template<typename Expression>
using _no_unknown_tables = detail::is_subset_of<required_tables_of<Expression>, _known_tables>;
// The tables not covered by the from.
using _required_tables = detail::make_difference_set_t<
_all_required_tables,
_all_provided_tables // Hint: extra_tables are not used here because they are just a helper for dynamic .add_*()
>;
using _traits = make_traits<no_value_t>; // FIXME
struct _recursive_traits
{
using _parameters = std::tuple<>; // FIXME
using _required_tables = _required_tables;
using _provided_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>;
};
};
} }
// UPDATE template<typename Db>
template<typename Db, typename... Policies> auto _run(Db& db) const -> decltype(db.update(_get_statement()))
struct update_t:
public Policies...,
public detail::update_policies_t<Db, Policies...>::_methods_t
{ {
using _policies_t = typename detail::update_policies_t<Db, Policies...>; _statement_t::_check_consistency();
using _database_t = typename _policies_t::_database_t;
using _is_dynamic = typename std::conditional<std::is_same<_database_t, void>::value, std::false_type, std::true_type>::type; static_assert(_statement_t::_get_static_no_of_parameters() == 0, "cannot run update directly with parameters, use prepare instead");
using _parameter_list_t = typename make_parameter_list_t<update_t>::type;
// Constructors
constexpr update_t()
{}
template<typename Statement, typename Term>
update_t(Statement statement, Term term):
Policies(detail::pick_arg<Policies>(statement, term))...
{}
update_t(const update_t&) = default;
update_t(update_t&&) = default;
update_t& operator=(const update_t&) = default;
update_t& operator=(update_t&&) = default;
~update_t() = default;
// run and prepare
static constexpr size_t _get_static_no_of_parameters()
{
return _parameter_list_t::size::value;
}
size_t _get_no_of_parameters() const
{
return _parameter_list_t::size::value;
}
void _check_consistency() const
{
#warning reactivate tests
/*
static_assert(is_where_t<_where_t>::value, "cannot run update without having a where condition, use .where(true) to update all rows");
static_assert(is_table_subset_of_table<_update_list_t>::value, "updates require additional tables");
static_assert(is_table_subset_of_table<_where_t>::value, "where requires additional tables");
*/
}
template<typename Database>
std::size_t _run(Database& db) const
{
_check_consistency();
static_assert(_get_static_no_of_parameters() == 0, "cannot run update directly with parameters, use prepare instead");
return db.update(*this); return db.update(*this);
} }
template<typename Database> /*
auto _prepare(Database& db) const template<typename Db>
-> prepared_update_t<Database, update_t> auto _prepare(Db& db) const
-> prepared_update_t<Db, update_t>
{ {
_check_consistency(); _statement_t::_check_consistency();
return {{}, db.prepare_update(*this)}; return {{}, db.prepare_update(*this)};
} }
*/
}; };
};
namespace vendor namespace vendor
{ {
template<typename Context, typename Database, typename... Policies> template<typename Context>
struct serializer_t<Context, update_t<Database, Policies...>> struct serializer_t<Context, update_name_t>
{ {
using T = update_t<Database, Policies...>; using T = update_name_t;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
context << "UPDATE "; context << "UPDATE ";
using swallow = int[];
(void) swallow{(serialize(static_cast<const Policies&>(t), context), 0)...};
return context; return context;
} }
}; };
} }
template<typename Database> template<typename Database>
using blank_update_t = update_t<Database, using blank_update_t = statement_t<Database,
update_t,
vendor::no_single_table_t, vendor::no_single_table_t,
vendor::no_update_list_t, vendor::no_update_list_t,
vendor::no_where_t>; vendor::no_where_t>;

View File

@ -37,7 +37,8 @@ namespace sqlpp
{ {
// FIXME: Remove First, inherit from text_t // FIXME: Remove First, inherit from text_t
template<typename First, typename... Args> template<typename First, typename... Args>
struct concat_t: public value_type_of<First>::template expression_operators<concat_t<First, Args...>> struct concat_t: public value_type_of<First>::template expression_operators<concat_t<First, Args...>>,
public alias_operators<concat_t<First, Args...>>
{ {
using _traits = make_traits<value_type_of<First>, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; using _traits = make_traits<value_type_of<First>, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
using _recursive_traits = make_recursive_traits<First, Args...>; using _recursive_traits = make_recursive_traits<First, Args...>;

View File

@ -40,7 +40,8 @@ namespace sqlpp
namespace vendor namespace vendor
{ {
template<typename Lhs, typename Rhs> template<typename Lhs, typename Rhs>
struct binary_expression_t<Lhs, op::equal_to, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<equal_to_t<Lhs, Rhs>> struct binary_expression_t<Lhs, op::equal_to, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<binary_expression_t<Lhs, op::equal_to, Rhs>>,
public alias_operators<binary_expression_t<Lhs, op::equal_to, Rhs>>
{ {
using _traits = make_traits<boolean, sqlpp::tag::expression>; using _traits = make_traits<boolean, sqlpp::tag::expression>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>; using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
@ -84,7 +85,8 @@ namespace sqlpp
}; };
template<typename Lhs, typename Rhs> template<typename Lhs, typename Rhs>
struct binary_expression_t<Lhs, op::not_equal_to, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<not_equal_to_t<Lhs, Rhs>> struct binary_expression_t<Lhs, op::not_equal_to, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<binary_expression_t<Lhs, op::not_equal_to, Rhs>>,
public alias_operators<binary_expression_t<Lhs, op::not_equal_to, Rhs>>
{ {
using _traits = make_traits<boolean, sqlpp::tag::expression>; using _traits = make_traits<boolean, sqlpp::tag::expression>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>; using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
@ -128,7 +130,8 @@ namespace sqlpp
}; };
template<typename Rhs> template<typename Rhs>
struct unary_expression_t<op::logical_not, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<logical_not_t<Rhs>> struct unary_expression_t<op::logical_not, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<unary_expression_t<op::logical_not, Rhs>>,
public alias_operators<unary_expression_t<op::logical_not, Rhs>>
{ {
using _traits = make_traits<boolean, sqlpp::tag::expression>; using _traits = make_traits<boolean, sqlpp::tag::expression>;
using _recursive_traits = make_recursive_traits<Rhs>; using _recursive_traits = make_recursive_traits<Rhs>;
@ -162,7 +165,8 @@ namespace sqlpp
}; };
template<typename Lhs, typename O, typename Rhs> template<typename Lhs, typename O, typename Rhs>
struct binary_expression_t: public value_type_of<O>::template expression_operators<binary_expression_t<Lhs, O, Rhs>> struct binary_expression_t: public value_type_of<O>::template expression_operators<binary_expression_t<Lhs, O, Rhs>>,
public alias_operators<binary_expression_t<Lhs, O, Rhs>>
{ {
using _traits = make_traits<value_type_of<O>, sqlpp::tag::expression>; using _traits = make_traits<value_type_of<O>, sqlpp::tag::expression>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>; using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
@ -199,7 +203,8 @@ namespace sqlpp
}; };
template<typename O, typename Rhs> template<typename O, typename Rhs>
struct unary_expression_t: public O::_value_type::template expression_operators<unary_expression_t<O, Rhs>> struct unary_expression_t: public value_type_of<O>::template expression_operators<unary_expression_t<O, Rhs>>,
public alias_operators<unary_expression_t<O, Rhs>>
{ {
using _traits = make_traits<value_type_of<O>, sqlpp::tag::expression>; using _traits = make_traits<value_type_of<O>, sqlpp::tag::expression>;
using _recursive_traits = make_recursive_traits<Rhs>; using _recursive_traits = make_recursive_traits<Rhs>;

View File

@ -35,6 +35,20 @@ namespace sqlpp
{ {
namespace vendor namespace vendor
{ {
template<typename... Tables>
struct extra_tables_data_t
{
extra_tables_data_t()
{}
extra_tables_data_t(const extra_tables_data_t&) = default;
extra_tables_data_t(extra_tables_data_t&&) = default;
extra_tables_data_t& operator=(const extra_tables_data_t&) = default;
extra_tables_data_t& operator=(extra_tables_data_t&&) = default;
~extra_tables_data_t() = default;
};
// EXTRA_TABLES // EXTRA_TABLES
template<typename... Tables> template<typename... Tables>
struct extra_tables_t struct extra_tables_t
@ -56,26 +70,73 @@ namespace sqlpp
static_assert(not ::sqlpp::detail::has_duplicates<Tables...>::value, "at least one duplicate argument detected in extra_tables()"); static_assert(not ::sqlpp::detail::has_duplicates<Tables...>::value, "at least one duplicate argument detected in extra_tables()");
static_assert(::sqlpp::detail::all_t<is_table_t<Tables>::value...>::value, "at least one argument is not a table or join in extra_tables()"); static_assert(::sqlpp::detail::all_t<is_table_t<Tables>::value...>::value, "at least one argument is not a table or join in extra_tables()");
extra_tables_t() // Data
{} using _data_t = extra_tables_data_t<Tables...>;
extra_tables_t(const extra_tables_t&) = default; // Member implementation with data and methods
extra_tables_t(extra_tables_t&&) = default; template <typename Policies>
extra_tables_t& operator=(const extra_tables_t&) = default; struct _impl_t
extra_tables_t& operator=(extra_tables_t&&) = default; {
~extra_tables_t() = default; _data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = extra_tables_data_t<Tables...>;
_impl_t<Policies> extra_tables;
_impl_t<Policies>& operator()() { return extra_tables; }
const _impl_t<Policies>& operator()() const { return extra_tables; }
template<typename T>
static auto _get_member(T t) -> decltype(t.extra_tables)
{
return t.extra_tables;
}
};
// Additional methods for the statement
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
}; };
}; };
// NO EXTRA TABLES YET
struct no_extra_tables_t struct no_extra_tables_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_extra_tables;
_impl_t<Policies>& operator()() { return no_extra_tables; }
const _impl_t<Policies>& operator()() const { return no_extra_tables; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_extra_tables)
{
return t.no_extra_tables;
}
};
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
@ -86,27 +147,16 @@ namespace sqlpp
auto extra_tables(Args...) auto extra_tables(Args...)
-> _new_statement_t<extra_tables_t<Args...>> -> _new_statement_t<extra_tables_t<Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), extra_tables_t<Args...>{} }; return { *static_cast<typename Policies::_statement_t*>(this), extra_tables_data_t<Args...>{} };
} }
}; };
}; };
// Interpreters // Interpreters
template<typename Context, typename Database, typename... Tables> template<typename Context, typename Database, typename... Tables>
struct serializer_t<Context, extra_tables_t<Database, Tables...>> struct serializer_t<Context, extra_tables_data_t<Database, Tables...>>
{ {
using T = extra_tables_t<Database, Tables...>; using T = extra_tables_data_t<Database, Tables...>;
static Context& _(const T& t, Context& context)
{
return context;
}
};
template<typename Context>
struct serializer_t<Context, no_extra_tables_t>
{
using T = no_extra_tables_t;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {

View File

@ -37,6 +37,24 @@ namespace sqlpp
{ {
namespace vendor namespace vendor
{ {
// FROM DATA
template<typename Database, typename... Tables>
struct from_data_t
{
from_data_t(Tables... tables):
_tables(tables...)
{}
from_data_t(const from_data_t&) = default;
from_data_t(from_data_t&&) = default;
from_data_t& operator=(const from_data_t&) = default;
from_data_t& operator=(from_data_t&&) = default;
~from_data_t() = default;
std::tuple<Tables...> _tables;
vendor::interpretable_list_t<Database> _dynamic_tables;
};
// FROM // FROM
template<typename Database, typename... Tables> template<typename Database, typename... Tables>
struct from_t struct from_t
@ -55,45 +73,61 @@ namespace sqlpp
static_assert(required_tables_of<from_t>::size::value == 0, "at least one table depends on another table"); static_assert(required_tables_of<from_t>::size::value == 0, "at least one table depends on another table");
from_t& _from() { return *this; } // Data
using _data_t = from_data_t<Database, Tables...>;
from_t(Tables... tables):
_tables(tables...)
{}
from_t(const from_t&) = default;
from_t(from_t&&) = default;
from_t& operator=(const from_t&) = default;
from_t& operator=(from_t&&) = default;
~from_t() = default;
// Member implementation with data and methods
template<typename Policies> template<typename Policies>
struct _methods_t struct _impl_t
{ {
template<typename Table> template<typename Table>
void add_from(Table table) void add(Table table)
{ {
static_assert(_is_dynamic::value, "add_from must not be called for static from()"); static_assert(_is_dynamic::value, "from::add() must not be called for static from()");
static_assert(is_table_t<Table>::value, "invalid table argument in add_from()"); static_assert(is_table_t<Table>::value, "invalid table argument in from::add()");
#warning need to check if table is already known
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_table_t<Table>::value>; using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_table_t<Table>::value>;
_add_from_impl(table, ok()); // dispatch to prevent compile messages after the static_assert _add_impl(table, ok()); // dispatch to prevent compile messages after the static_assert
} }
private: private:
template<typename Table> template<typename Table>
void _add_from_impl(Table table, const std::true_type&) void _add_impl(Table table, const std::true_type&)
{ {
return static_cast<typename Policies::_statement_t*>(this)->_from()._dynamic_tables.emplace_back(table); return _data._dynamic_tables.emplace_back(table);
} }
template<typename Table> template<typename Table>
void _add_from_impl(Table table, const std::false_type&); void _add_impl(Table table, const std::false_type&);
public:
_data_t _data;
}; };
std::tuple<Tables...> _tables; // Member template for adding the named member to a statement
vendor::interpretable_list_t<Database> _dynamic_tables; template<typename Policies>
struct _member_t
{
using _data_t = from_data_t<Database, Tables...>;
_impl_t<Policies> from;
_impl_t<Policies>& operator()() { return from; }
const _impl_t<Policies>& operator()() const { return from; }
template<typename T>
static auto _get_member(T t) -> decltype(t.from)
{
return t.from;
}
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
};
}; };
struct no_from_t struct no_from_t
@ -101,6 +135,34 @@ namespace sqlpp
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_from;
_impl_t<Policies>& operator()() { return no_from; }
const _impl_t<Policies>& operator()() const { return no_from; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_from)
{
return t.no_from;
}
};
// Additional methods for the statement
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
@ -112,7 +174,7 @@ namespace sqlpp
auto from(Args... args) auto from(Args... args)
-> _new_statement_t<from_t<void, Args...>> -> _new_statement_t<from_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), from_t<void, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), from_data_t<void, Args...>{args...} };
} }
template<typename... Args> template<typename... Args>
@ -120,16 +182,16 @@ namespace sqlpp
-> _new_statement_t<from_t<_database_t, Args...>> -> _new_statement_t<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"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_from must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), vendor::from_t<_database_t, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), from_data_t<_database_t, Args...>{args...} };
} }
}; };
}; };
// Interpreters // Interpreters
template<typename Context, typename Database, typename... Tables> template<typename Context, typename Database, typename... Tables>
struct serializer_t<Context, from_t<Database, Tables...>> struct serializer_t<Context, from_data_t<Database, Tables...>>
{ {
using T = from_t<Database, Tables...>; using T = from_data_t<Database, Tables...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
@ -144,17 +206,6 @@ namespace sqlpp
} }
}; };
template<typename Context>
struct serializer_t<Context, no_from_t>
{
using T = no_from_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
} }
} }

View File

@ -39,6 +39,24 @@ namespace sqlpp
{ {
namespace vendor namespace vendor
{ {
// GROUP BY DATA
template<typename Database, typename... Expressions>
struct group_by_data_t
{
group_by_data_t(Expressions... expressions):
_expressions(expressions...)
{}
group_by_data_t(const group_by_data_t&) = default;
group_by_data_t(group_by_data_t&&) = default;
group_by_data_t& operator=(const group_by_data_t&) = default;
group_by_data_t& operator=(group_by_data_t&&) = default;
~group_by_data_t() = default;
std::tuple<Expressions...> _expressions;
vendor::interpretable_list_t<Database> _dynamic_expressions;
};
// GROUP BY // GROUP BY
template<typename Database, typename... Expressions> template<typename Database, typename... Expressions>
struct group_by_t struct group_by_t
@ -54,60 +72,100 @@ namespace sqlpp
static_assert(::sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in group_by()"); static_assert(::sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in group_by()");
group_by_t& _group_by() { return *this; } // Data
using _data_t = group_by_data_t<Database, Expressions...>;
group_by_t(Expressions... expressions):
_expressions(expressions...)
{}
group_by_t(const group_by_t&) = default;
group_by_t(group_by_t&&) = default;
group_by_t& operator=(const group_by_t&) = default;
group_by_t& operator=(group_by_t&&) = default;
~group_by_t() = default;
// Member implementation with data and methods
template<typename Policies> template<typename Policies>
struct _methods_t struct _impl_t
{ {
template<typename Expression> template<typename Expression>
void add_group_by_ntc(Expression expression) void add_ntc(Expression expression)
{ {
add_group_by<Expression, std::false_type>(expression); add<Expression, std::false_type>(expression);
} }
template<typename Expression, typename TableCheckRequired = std::true_type> template<typename Expression, typename TableCheckRequired = std::true_type>
void add_group_by(Expression expression) void add(Expression expression)
{ {
static_assert(_is_dynamic::value, "add_group_by must not be called for static group_by"); static_assert(_is_dynamic::value, "add() must not be called for static group_by");
static_assert(is_expression_t<Expression>::value, "invalid expression argument in add_group_by()"); static_assert(is_expression_t<Expression>::value, "invalid expression argument in group_by::add()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in add_group_by()"); static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in group_by::add()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t<Expression>::value>; using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t<Expression>::value>;
_add_group_by_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert _add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
} }
private: private:
template<typename Expression> template<typename Expression>
void _add_group_by_impl(Expression expression, const std::true_type&) void _add_impl(Expression expression, const std::true_type&)
{ {
return static_cast<typename Policies::_statement_t*>(this)->_group_by()._dynamic_expressions.emplace_back(expression); return _data._dynamic_expressions.emplace_back(expression);
} }
template<typename Expression> template<typename Expression>
void _add_group_by_impl(Expression expression, const std::false_type&); void _add_impl(Expression expression, const std::false_type&);
public:
_data_t _data;
}; };
const group_by_t& _group_by() const { return *this; } // Member template for adding the named member to a statement
std::tuple<Expressions...> _expressions; template<typename Policies>
vendor::interpretable_list_t<Database> _dynamic_expressions; struct _member_t
{
using _data_t = group_by_data_t<Database, Expressions...>;
_impl_t<Policies> group_by;
_impl_t<Policies>& operator()() { return group_by; }
const _impl_t<Policies>& operator()() const { return group_by; }
template<typename T>
static auto _get_member(T t) -> decltype(t.group_by)
{
return t.group_by;
}
}; };
template<typename Policies>
struct _methods_t
{
};
};
// NO GROUP BY YET
struct no_group_by_t struct no_group_by_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_group_by;
_impl_t<Policies>& operator()() { return no_group_by; }
const _impl_t<Policies>& operator()() const { return no_group_by; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_group_by)
{
return t.no_group_by;
}
};
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
@ -119,7 +177,7 @@ namespace sqlpp
auto group_by(Args... args) auto group_by(Args... args)
-> _new_statement_t<group_by_t<void, Args...>> -> _new_statement_t<group_by_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), group_by_t<void, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), group_by_data_t<void, Args...>{args...} };
} }
template<typename... Args> template<typename... Args>
@ -127,16 +185,16 @@ namespace sqlpp
-> _new_statement_t<group_by_t<_database_t, Args...>> -> _new_statement_t<group_by_t<_database_t, Args...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_group_by must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_group_by must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), vendor::group_by_t<_database_t, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), group_by_data_t<_database_t, Args...>{args...} };
} }
}; };
}; };
// Interpreters // Interpreters
template<typename Context, typename Database, typename... Expressions> template<typename Context, typename Database, typename... Expressions>
struct serializer_t<Context, group_by_t<Database, Expressions...>> struct serializer_t<Context, group_by_data_t<Database, Expressions...>>
{ {
using T = group_by_t<Database, Expressions...>; using T = group_by_data_t<Database, Expressions...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
@ -150,18 +208,6 @@ namespace sqlpp
return context; return context;
} }
}; };
template<typename Context>
struct serializer_t<Context, no_group_by_t>
{
using T = no_group_by_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
} }
} }

View File

@ -38,6 +38,24 @@ namespace sqlpp
{ {
namespace vendor namespace vendor
{ {
// HAVING DATA
template<typename Database, typename... Expressions>
struct having_data_t
{
having_data_t(Expressions... expressions):
_expressions(expressions...)
{}
having_data_t(const having_data_t&) = default;
having_data_t(having_data_t&&) = default;
having_data_t& operator=(const having_data_t&) = default;
having_data_t& operator=(having_data_t&&) = default;
~having_data_t() = default;
std::tuple<Expressions...> _expressions;
vendor::interpretable_list_t<Database> _dynamic_expressions;
};
// HAVING // HAVING
template<typename Database, typename... Expressions> template<typename Database, typename... Expressions>
struct having_t struct having_t
@ -50,59 +68,102 @@ namespace sqlpp
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in having()"); static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in having()");
static_assert(::sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in having()"); static_assert(::sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in having()");
having_t& _having() { return *this; } // Data
using _data_t = having_data_t<Database, Expressions...>;
having_t(Expressions... expressions):
_expressions(expressions...)
{}
having_t(const having_t&) = default;
having_t(having_t&&) = default;
having_t& operator=(const having_t&) = default;
having_t& operator=(having_t&&) = default;
~having_t() = default;
// Member implementation with data and methods
template <typename Policies> template <typename Policies>
struct _methods_t struct _impl_t
{ {
template<typename Expression> template<typename Expression>
void add_having_ntc(Expression expression) void add_ntc(Expression expression)
{ {
add_having<Expression, std::false_type>(expression); add<Expression, std::false_type>(expression);
} }
template<typename Expression, typename TableCheckRequired = std::true_type> template<typename Expression, typename TableCheckRequired = std::true_type>
void add_having(Expression expression) void add(Expression expression)
{ {
static_assert(_is_dynamic::value, "add_having must not be called for static having"); static_assert(_is_dynamic::value, "having::add() can only be called for dynamic_having");
static_assert(is_expression_t<Expression>::value, "invalid expression argument in add_having()"); static_assert(is_expression_t<Expression>::value, "invalid expression argument in having::add()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in add_having()"); static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in having::add()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t<Expression>::value>; using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t<Expression>::value>;
_add_having_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert _add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
} }
private: private:
template<typename Expression> template<typename Expression>
void _add_having_impl(Expression expression, const std::true_type&) void _add_impl(Expression expression, const std::true_type&)
{ {
return static_cast<typename Policies::_statement_t*>(this)->_having()._dynamic_expressions.emplace_back(expression); return _data._dynamic_expressions.emplace_back(expression);
} }
template<typename Expression> template<typename Expression>
void _add_having_impl(Expression expression, const std::false_type&); void _add_impl(Expression expression, const std::false_type&);
public:
_data_t _data;
}; };
std::tuple<Expressions...> _expressions; // Member template for adding the named member to a statement
vendor::interpretable_list_t<Database> _dynamic_expressions; template<typename Policies>
struct _member_t
{
using _data_t = having_data_t<Database, Expressions...>;
_impl_t<Policies> having;
_impl_t<Policies>& operator()() { return having; }
const _impl_t<Policies>& operator()() const { return having; }
template<typename T>
static auto _get_member(T t) -> decltype(t.having)
{
return t.having;
}
}; };
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
};
};
// NO HAVING YET
struct no_having_t struct no_having_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_having;
_impl_t<Policies>& operator()() { return no_having; }
const _impl_t<Policies>& operator()() const { return no_having; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_having)
{
return t.no_having;
}
};
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
@ -114,7 +175,7 @@ namespace sqlpp
auto having(Args... args) auto having(Args... args)
-> _new_statement_t<having_t<void, Args...>> -> _new_statement_t<having_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), having_t<void, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), having_data_t<void, Args...>{args...} };
} }
template<typename... Args> template<typename... Args>
@ -122,16 +183,16 @@ namespace sqlpp
-> _new_statement_t<having_t<_database_t, Args...>> -> _new_statement_t<having_t<_database_t, Args...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_having must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_having must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), vendor::having_t<_database_t, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), having_data_t<_database_t, Args...>{args...} };
} }
}; };
}; };
// Interpreters // Interpreters
template<typename Context, typename Database, typename... Expressions> template<typename Context, typename Database, typename... Expressions>
struct serializer_t<Context, having_t<Database, Expressions...>> struct serializer_t<Context, having_data_t<Database, Expressions...>>
{ {
using T = having_t<Database, Expressions...>; using T = having_data_t<Database, Expressions...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
@ -145,18 +206,6 @@ namespace sqlpp
return context; return context;
} }
}; };
template<typename Context>
struct serializer_t<Context, no_having_t>
{
using T = no_having_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
} }
} }

View File

@ -37,7 +37,8 @@ namespace sqlpp
namespace vendor namespace vendor
{ {
template<bool NotInverted, typename Operand, typename... Args> template<bool NotInverted, typename Operand, typename... Args>
struct in_t: public boolean::template expression_operators<in_t<NotInverted, Operand, Args...>> struct in_t: public boolean::template expression_operators<in_t<NotInverted, Operand, Args...>>,
public alias_operators<in_t<NotInverted, Operand, Args...>>
{ {
using _traits = make_traits<boolean, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; using _traits = make_traits<boolean, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
using _recursive_traits = make_recursive_traits<Operand, Args...>; using _recursive_traits = make_recursive_traits<Operand, Args...>;

View File

@ -39,17 +39,69 @@ namespace sqlpp
{ {
namespace vendor namespace vendor
{ {
struct insert_default_values_data_t
{};
// COLUMN AND VALUE LIST // COLUMN AND VALUE LIST
struct insert_default_values_t struct insert_default_values_t
{ {
using _traits = make_traits<no_value_t>; using _traits = make_traits<no_value_t>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = insert_default_values_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = insert_default_values_data_t;
_impl_t<Policies> default_values;
_impl_t<Policies>& operator()() { return default_values; }
const _impl_t<Policies>& operator()() const { return default_values; }
template<typename T>
static auto _get_member(T t) -> decltype(t.default_values)
{
return t.default_values;
}
};
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{}; {};
}; };
template<typename Database, typename... Assignments>
struct insert_list_data_t
{
insert_list_data_t(Assignments... assignments):
_assignments(assignments...),
_columns({assignments._lhs}...),
_values(assignments._rhs...)
{}
insert_list_data_t(const insert_list_data_t&) = default;
insert_list_data_t(insert_list_data_t&&) = default;
insert_list_data_t& operator=(const insert_list_data_t&) = default;
insert_list_data_t& operator=(insert_list_data_t&&) = default;
~insert_list_data_t() = default;
std::tuple<simple_column_t<typename Assignments::_column_t>...> _columns;
std::tuple<typename Assignments::_value_t...> _values;
std::tuple<Assignments...> _assignments; // FIXME: Need to replace _columns and _values by _assignments (connector-container requires assignments)
typename vendor::interpretable_list_t<Database> _dynamic_columns;
typename vendor::interpretable_list_t<Database> _dynamic_values;
};
template<typename Database, typename... Assignments> template<typename Database, typename... Assignments>
struct insert_list_t struct insert_list_t
{ {
@ -81,36 +133,26 @@ namespace sqlpp
static_assert(::sqlpp::detail::is_subset_of<_value_required_tables, _column_required_tables>::value, "set() contains values from foreign tables"); static_assert(::sqlpp::detail::is_subset_of<_value_required_tables, _column_required_tables>::value, "set() contains values from foreign tables");
*/ */
insert_list_t& _insert_value_list() { return *this; } // Data
using _data_t = insert_list_data_t<Database, Assignments...>;
insert_list_t(Assignments... assignment):
_assignments(assignment...),
_columns({assignment._lhs}...),
_values(assignment._rhs...)
{}
insert_list_t(const insert_list_t&) = default;
insert_list_t(insert_list_t&&) = default;
insert_list_t& operator=(const insert_list_t&) = default;
insert_list_t& operator=(insert_list_t&&) = default;
~insert_list_t() = default;
// Member implementation with data and methods
template <typename Policies> template <typename Policies>
struct _methods_t struct _impl_t
{ {
template<typename Assignment> template<typename Assignment>
void add_set_ntc(Assignment assignment) void add_ntc(Assignment assignment)
{ {
add_set<Assignment, std::false_type>(assignment); add<Assignment, std::false_type>(assignment);
} }
template<typename Assignment, typename TableCheckRequired = std::true_type> template<typename Assignment, typename TableCheckRequired = std::true_type>
void add_set(Assignment assignment) void add(Assignment assignment)
{ {
static_assert(_is_dynamic::value, "add_set must not be called for static from()"); static_assert(_is_dynamic::value, "add must not be called for static from()");
static_assert(is_assignment_t<Assignment>::value, "add_set() arguments require to be assigments"); static_assert(is_assignment_t<Assignment>::value, "add() arguments require to be assigments");
static_assert(not must_not_insert_t<typename Assignment::_column_t>::value, "add_set() argument must not be used in insert"); static_assert(not must_not_insert_t<typename Assignment::_column_t>::value, "add() argument must not be used in insert");
static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value, "add_set() contains a column from a foreign table"); static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value, "add() contains a column from a foreign table");
using ok = ::sqlpp::detail::all_t< using ok = ::sqlpp::detail::all_t<
_is_dynamic::value, _is_dynamic::value,
@ -118,28 +160,67 @@ namespace sqlpp
not must_not_insert_t<typename Assignment::_column_t>::value, not must_not_insert_t<typename Assignment::_column_t>::value,
(not TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value)>; (not TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value)>;
_add_set_impl(assignment, ok()); // dispatch to prevent compile messages after the static_assert _add_impl(assignment, ok()); // dispatch to prevent compile messages after the static_assert
} }
private: private:
template<typename Assignment> template<typename Assignment>
void _add_set_impl(Assignment assignment, const std::true_type&) void _add_impl(Assignment assignment, const std::true_type&)
{ {
static_cast<typename Policies::_statement_t*>(this)->_insert_value_list()._dynamic_columns.emplace_back(simple_column_t<typename Assignment::_column_t>{assignment._lhs}); _data._dynamic_columns.emplace_back(simple_column_t<typename Assignment::_column_t>{assignment._lhs});
static_cast<typename Policies::_statement_t*>(this)->_insert_value_list()._dynamic_values.emplace_back(assignment._rhs); _data._dynamic_values.emplace_back(assignment._rhs);
} }
template<typename Assignment> template<typename Assignment>
void _add_set_impl(Assignment assignment, const std::false_type&); void _add_impl(Assignment assignment, const std::false_type&);
public:
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = insert_list_data_t<Database, Assignments...>;
_impl_t<Policies> insert_list;
_impl_t<Policies>& operator()() { return insert_list; }
const _impl_t<Policies>& operator()() const { return insert_list; }
template<typename T>
static auto _get_member(T t) -> decltype(t.insert_list)
{
return t.insert_list;
}
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
}; };
std::tuple<simple_column_t<typename Assignments::_column_t>...> _columns; };
std::tuple<typename Assignments::_value_t...> _values;
std::tuple<Assignments...> _assignments; // FIXME: Need to replace _columns and _values by _assignments (connector-container requires assignments) template<typename... Columns>
typename vendor::interpretable_list_t<Database> _dynamic_columns; struct column_list_data_t
typename vendor::interpretable_list_t<Database> _dynamic_values; {
column_list_data_t(Columns... columns):
_columns(simple_column_t<Columns>{columns}...)
{}
column_list_data_t(const column_list_data_t&) = default;
column_list_data_t(column_list_data_t&&) = default;
column_list_data_t& operator=(const column_list_data_t&) = default;
column_list_data_t& operator=(column_list_data_t&&) = default;
~column_list_data_t() = default;
#warning need to define just one version of value_tuple_t
using _value_tuple_t = std::tuple<vendor::insert_value_t<Columns>...>;
std::tuple<simple_column_t<Columns>...> _columns;
std::vector<_value_tuple_t> _insert_values;
}; };
template<typename... Columns> template<typename... Columns>
@ -160,23 +241,15 @@ namespace sqlpp
static_assert(required_tables_of<column_list_t>::size::value == 1, "columns from multiple tables in columns()"); static_assert(required_tables_of<column_list_t>::size::value == 1, "columns from multiple tables in columns()");
column_list_t& _insert_value_list() { return *this; } // Data
using _data_t = column_list_data_t<Columns...>;
column_list_t(Columns... columns):
_columns(simple_column_t<Columns>{columns}...)
{}
column_list_t(const column_list_t&) = default;
column_list_t(column_list_t&&) = default;
column_list_t& operator=(const column_list_t&) = default;
column_list_t& operator=(column_list_t&&) = default;
~column_list_t() = default;
// Member implementation with data and methods
template <typename Policies> template <typename Policies>
struct _methods_t struct _impl_t
{ {
template<typename... Assignments> template<typename... Assignments>
void add_values(Assignments... assignments) void add(Assignments... assignments)
{ {
static_assert(::sqlpp::detail::all_t<is_assignment_t<Assignments>::value...>::value, "add_values() arguments have to be assignments"); static_assert(::sqlpp::detail::all_t<is_assignment_t<Assignments>::value...>::value, "add_values() arguments have to be assignments");
using _arg_value_tuple = std::tuple<vendor::insert_value_t<typename Assignments::_column_t>...>; using _arg_value_tuple = std::tuple<vendor::insert_value_t<typename Assignments::_column_t>...>;
@ -187,35 +260,87 @@ namespace sqlpp
::sqlpp::detail::all_t<is_assignment_t<Assignments>::value...>::value, ::sqlpp::detail::all_t<is_assignment_t<Assignments>::value...>::value,
_args_correct::value>; _args_correct::value>;
_add_values_impl(ok(), assignments...); // dispatch to prevent compile messages after the static_assert _add_impl(ok(), assignments...); // dispatch to prevent compile messages after the static_assert
} }
private: private:
template<typename... Assignments> template<typename... Assignments>
void _add_values_impl(const std::true_type&, Assignments... assignments) void _add_impl(const std::true_type&, Assignments... assignments)
{ {
return static_cast<typename Policies::_statement_t*>(this)->_insert_value_list()._insert_values.emplace_back(vendor::insert_value_t<typename Assignments::_column_t>{assignments}...); return _data._insert_values.emplace_back(vendor::insert_value_t<typename Assignments::_column_t>{assignments}...);
} }
template<typename... Assignments> template<typename... Assignments>
void _add_values_impl(const std::false_type&, Assignments... assignments); void _add_impl(const std::false_type&, Assignments... assignments);
public:
_data_t _data;
}; };
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = column_list_data_t<Columns...>;
_impl_t<Policies> values;
_impl_t<Policies>& operator()() { return values; }
const _impl_t<Policies>& operator()() const { return values; }
template<typename T>
static auto _get_member(T t) -> decltype(t.values)
{
return t.values;
}
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
};
/*
bool empty() const bool empty() const
{ {
return _insert_values.empty(); return _insert_values.empty();
} }
*/
std::tuple<simple_column_t<Columns>...> _columns;
std::vector<_value_tuple_t> _insert_values;
}; };
// NO HAVING YET
struct no_insert_value_list_t struct no_insert_value_list_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_insert_values;
_impl_t<Policies>& operator()() { return no_insert_values; }
const _impl_t<Policies>& operator()() const { return no_insert_values; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_insert_values)
{
return t.no_insert_values;
}
};
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
@ -226,21 +351,21 @@ namespace sqlpp
auto default_values() auto default_values()
-> _new_statement_t<insert_default_values_t> -> _new_statement_t<insert_default_values_t>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), insert_default_values_t{} }; return { *static_cast<typename Policies::_statement_t*>(this), insert_default_values_data_t{} };
} }
template<typename... Args> template<typename... Args>
auto columns(Args... args) auto columns(Args... args)
-> _new_statement_t<column_list_t<Args...>> -> _new_statement_t<column_list_t<Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), column_list_t<Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), column_list_data_t<Args...>{args...} };
} }
template<typename... Args> template<typename... Args>
auto set(Args... args) auto set(Args... args)
-> _new_statement_t<insert_list_t<void, Args...>> -> _new_statement_t<insert_list_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), insert_list_t<void, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), insert_list_data_t<void, Args...>{args...} };
} }
template<typename... Args> template<typename... Args>
@ -248,16 +373,16 @@ namespace sqlpp
-> _new_statement_t<insert_list_t<_database_t, Args...>> -> _new_statement_t<insert_list_t<_database_t, Args...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_set must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_set must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), vendor::insert_list_t<_database_t, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), vendor::insert_list_data_t<_database_t, Args...>{args...} };
} }
}; };
}; };
// Interpreters // Interpreters
template<typename Context> template<typename Context>
struct serializer_t<Context, insert_default_values_t> struct serializer_t<Context, insert_default_values_data_t>
{ {
using T = insert_default_values_t; using T = insert_default_values_data_t;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
@ -267,9 +392,9 @@ namespace sqlpp
}; };
template<typename Context, typename... Columns> template<typename Context, typename... Columns>
struct serializer_t<Context, column_list_t<Columns...>> struct serializer_t<Context, column_list_data_t<Columns...>>
{ {
using T = column_list_t<Columns...>; using T = column_list_data_t<Columns...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
@ -294,15 +419,15 @@ namespace sqlpp
}; };
template<typename Context, typename Database, typename... Assignments> template<typename Context, typename Database, typename... Assignments>
struct serializer_t<Context, insert_list_t<Database, Assignments...>> struct serializer_t<Context, insert_list_data_t<Database, Assignments...>>
{ {
using T = insert_list_t<Database, Assignments...>; using T = insert_list_data_t<Database, Assignments...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
if (sizeof...(Assignments) + t._dynamic_columns.size() == 0) if (sizeof...(Assignments) + t._dynamic_columns.size() == 0)
{ {
serialize(insert_default_values_t(), context); serialize(insert_default_values_data_t(), context);
} }
else else
{ {
@ -322,17 +447,6 @@ namespace sqlpp
} }
}; };
template<typename Context>
struct serializer_t<Context, no_insert_value_list_t>
{
using T = no_insert_value_list_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
} }
} }

198
include/sqlpp11/vendor/into.h vendored Normal file
View File

@ -0,0 +1,198 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_VENDOR_INTO_H
#define SQLPP_VENDOR_INTO_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/no_value.h>
#include <sqlpp11/vendor/serializer.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
{
namespace vendor
{
// A SINGLE TABLE DATA
template<typename Database, typename Table>
struct into_data_t
{
into_data_t(Table table):
_table(table)
{}
into_data_t(const into_data_t&) = default;
into_data_t(into_data_t&&) = default;
into_data_t& operator=(const into_data_t&) = default;
into_data_t& operator=(into_data_t&&) = default;
~into_data_t() = default;
Table _table;
};
// A SINGLE TABLE
template<typename Database, typename Table>
struct into_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::into, tag::return_value>;
using _recursive_traits = make_recursive_traits<Table>;
static_assert(is_table_t<Table>::value, "argument has to be a table");
static_assert(required_tables_of<Table>::size::value == 0, "table depends on another table");
using _data_t = into_data_t<Database, Table>;
struct _name_t {};
// Member implementation with data and methods
template <typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = into_data_t<Database, Table>;
_impl_t<Policies> into;
_impl_t<Policies>& operator()() { return into; }
const _impl_t<Policies>& operator()() const { return into; }
template<typename T>
static auto _get_member(T t) -> decltype(t.into)
{
return t.into;
}
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
};
template<typename Policies>
struct _result_methods_t
{
using _statement_t = typename Policies::_statement_t;
const _statement_t& _get_statement() const
{
return static_cast<const _statement_t&>(*this);
}
template<typename Db>
auto _run(Db& db) const -> decltype(db.insert(_get_statement()))
{
_statement_t::_check_consistency();
static_assert(_statement_t::_get_static_no_of_parameters() == 0, "cannot run insert directly with parameters, use prepare instead");
return db.insert(*this);
}
/*
template<typename Db>
auto _prepare(Db& db) const
-> prepared_insert_t<Db, insert_t>
{
_statement_t::_check_consistency();
return {{}, db.prepare_insert(*this)};
}
*/
};
};
// NO INTO YET
struct no_into_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_into;
_impl_t<Policies>& operator()() { return no_into; }
const _impl_t<Policies>& operator()() const { return no_into; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_into)
{
return t.no_into;
}
};
template<typename Policies>
struct _methods_t
{
using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_into_t, T>;
template<typename... Args>
auto into(Args... args)
-> _new_statement_t<into_t<void, Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), into_data_t<void, Args...>{args...} };
}
};
};
// Interpreters
template<typename Context, typename Database, typename Table>
struct serializer_t<Context, into_data_t<Database, Table>>
{
using T = into_data_t<Database, Table>;
static Context& _(const T& t, Context& context)
{
context << " INTO ";
serialize(t._table, context);
return context;
}
};
}
}
#endif

View File

@ -36,7 +36,8 @@ namespace sqlpp
namespace vendor namespace vendor
{ {
template<bool NotInverted, typename Operand> template<bool NotInverted, typename Operand>
struct is_null_t: public boolean::template expression_operators<is_null_t<NotInverted, Operand>> struct is_null_t: public boolean::template expression_operators<is_null_t<NotInverted, Operand>>,
public alias_operators<is_null_t<NotInverted, Operand>>
{ {
using _traits = make_traits<boolean, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; using _traits = make_traits<boolean, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
using _recursive_traits = make_recursive_traits<Operand>; using _recursive_traits = make_recursive_traits<Operand>;

View File

@ -36,7 +36,8 @@ namespace sqlpp
namespace vendor namespace vendor
{ {
template<typename Operand, typename Pattern> template<typename Operand, typename Pattern>
struct like_t: public boolean::template expression_operators<like_t<Operand, Pattern>> struct like_t: public boolean::template expression_operators<like_t<Operand, Pattern>>,
public alias_operators<like_t<Operand, Pattern>>
{ {
using _traits = make_traits<boolean, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>; using _traits = make_traits<boolean, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
using _recursive_traits = make_recursive_traits<Operand, Pattern>; using _recursive_traits = make_recursive_traits<Operand, Pattern>;

View File

@ -35,6 +35,23 @@ namespace sqlpp
{ {
namespace vendor namespace vendor
{ {
// LIMIT DATA
template<typename Limit>
struct limit_data_t
{
limit_data_t(Limit value):
_value(value)
{}
limit_data_t(const limit_data_t&) = default;
limit_data_t(limit_data_t&&) = default;
limit_data_t& operator=(const limit_data_t&) = default;
limit_data_t& operator=(limit_data_t&&) = default;
~limit_data_t() = default;
Limit _value;
};
// LIMIT // LIMIT
template<typename Limit> template<typename Limit>
struct limit_t struct limit_t
@ -44,65 +61,113 @@ namespace sqlpp
static_assert(is_integral_t<Limit>::value, "limit requires an integral value or integral parameter"); static_assert(is_integral_t<Limit>::value, "limit requires an integral value or integral parameter");
limit_t(Limit value): // Data
_value(value) using _data_t = limit_data_t<Limit>;
{}
limit_t(const limit_t&) = default; // Member implementation with data and methods
limit_t(limit_t&&) = default; template <typename Policies>
limit_t& operator=(const limit_t&) = default; struct _impl_t
limit_t& operator=(limit_t&&) = default; {
~limit_t() = default; _data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = limit_data_t<Limit>;
_impl_t<Policies> limit;
_impl_t<Policies>& operator()() { return limit; }
const _impl_t<Policies>& operator()() const { return limit; }
template<typename T>
static auto _get_member(T t) -> decltype(t.limit)
{
return t.limit;
}
};
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
}; };
Limit _value;
}; };
// DYNAMIC LIMIT DATA
template<typename Database>
struct dynamic_limit_data_t
{
dynamic_limit_data_t():
_value(noop())
{
}
template<typename Limit>
dynamic_limit_data_t(Limit value):
_initialized(true),
_value(typename wrap_operand<Limit>::type(value))
{
}
dynamic_limit_data_t(const dynamic_limit_data_t&) = default;
dynamic_limit_data_t(dynamic_limit_data_t&&) = default;
dynamic_limit_data_t& operator=(const dynamic_limit_data_t&) = default;
dynamic_limit_data_t& operator=(dynamic_limit_data_t&&) = default;
~dynamic_limit_data_t() = default;
bool _initialized = false;
interpretable_t<Database> _value;
};
// DYNAMIC LIMIT
template<typename Database> template<typename Database>
struct dynamic_limit_t struct dynamic_limit_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::limit>; using _traits = make_traits<no_value_t, ::sqlpp::tag::limit>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
dynamic_limit_t& _limit() { return *this; } // Data
using _data_t = dynamic_limit_data_t<Database>;
dynamic_limit_t():
_value(noop())
{
}
template<typename Limit>
dynamic_limit_t(Limit value):
_initialized(true),
_value(typename wrap_operand<Limit>::type(value))
{
}
dynamic_limit_t(const dynamic_limit_t&) = default;
dynamic_limit_t(dynamic_limit_t&&) = default;
dynamic_limit_t& operator=(const dynamic_limit_t&) = default;
dynamic_limit_t& operator=(dynamic_limit_t&&) = default;
~dynamic_limit_t() = default;
// Member implementation with data and methods
template <typename Policies> template <typename Policies>
struct _methods_t struct _impl_t
{ {
template<typename Limit> template<typename Limit>
void set_limit(Limit value) void set(Limit value)
{ {
// FIXME: Make sure that Limit does not require external tables? Need to read up on SQL // FIXME: Make sure that Limit does not require external tables? Need to read up on SQL
using arg_t = typename wrap_operand<Limit>::type; using arg_t = typename wrap_operand<Limit>::type;
static_cast<typename Policies::_statement_t*>(this)->_limit()._value = arg_t{value}; _data._value = arg_t{value};
static_cast<typename Policies::_statement_t*>(this)->_limit()._initialized = true; _data._initialized = true;
}
public:
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = dynamic_limit_data_t<Database>;
_impl_t<Policies> limit;
_impl_t<Policies>& operator()() { return limit; }
const _impl_t<Policies>& operator()() const { return limit; }
template<typename T>
static auto _get_member(T t) -> decltype(t.limit)
{
return t.limit;
} }
}; };
bool _initialized = false; // Additional methods for the statement
interpretable_t<Database> _value; template<typename Policies>
struct _methods_t
{
};
}; };
struct no_limit_t struct no_limit_t
@ -110,6 +175,33 @@ namespace sqlpp
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_limit;
_impl_t<Policies>& operator()() { return no_limit; }
const _impl_t<Policies>& operator()() const { return no_limit; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_limit)
{
return t.no_limit;
}
};
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
@ -121,23 +213,23 @@ namespace sqlpp
auto limit(Arg arg) auto limit(Arg arg)
-> _new_statement_t<limit_t<typename wrap_operand<Arg>::type>> -> _new_statement_t<limit_t<typename wrap_operand<Arg>::type>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), limit_t<typename wrap_operand<Arg>::type>{{arg}} }; return { *static_cast<typename Policies::_statement_t*>(this), limit_data_t<typename wrap_operand<Arg>::type>{{arg}} };
} }
auto dynamic_limit() auto dynamic_limit()
-> _new_statement_t<dynamic_limit_t<_database_t>> -> _new_statement_t<dynamic_limit_t<_database_t>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_limit must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_limit must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), dynamic_limit_t<_database_t>{} }; return { *static_cast<typename Policies::_statement_t*>(this), dynamic_limit_data_t<_database_t>{} };
} }
}; };
}; };
// Interpreters // Interpreters
template<typename Context, typename Database> template<typename Context, typename Database>
struct serializer_t<Context, dynamic_limit_t<Database>> struct serializer_t<Context, dynamic_limit_data_t<Database>>
{ {
using T = dynamic_limit_t<Database>; using T = dynamic_limit_data_t<Database>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
@ -151,9 +243,9 @@ namespace sqlpp
}; };
template<typename Context, typename Limit> template<typename Context, typename Limit>
struct serializer_t<Context, limit_t<Limit>> struct serializer_t<Context, limit_data_t<Limit>>
{ {
using T = limit_t<Limit>; using T = limit_data_t<Limit>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
@ -162,18 +254,6 @@ namespace sqlpp
return context; return context;
} }
}; };
template<typename Context>
struct serializer_t<Context, no_limit_t>
{
using T = no_limit_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
} }
} }

View File

@ -35,10 +35,30 @@ namespace sqlpp
{ {
namespace vendor namespace vendor
{ {
#warning: Need extra include file for no_data
struct no_data_t {};
template<typename Context>
struct serializer_t<Context, no_data_t>
{
using T = no_data_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
struct noop struct noop
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
struct _name_t {};
template<typename Policies>
struct _result_methods_t
{};
}; };
template<typename Context> template<typename Context>

View File

@ -35,6 +35,23 @@ namespace sqlpp
{ {
namespace vendor namespace vendor
{ {
// OFFSET DATA
template<typename Offset>
struct offset_data_t
{
offset_data_t(Offset value):
_value(value)
{}
offset_data_t(const offset_data_t&) = default;
offset_data_t(offset_data_t&&) = default;
offset_data_t& operator=(const offset_data_t&) = default;
offset_data_t& operator=(offset_data_t&&) = default;
~offset_data_t() = default;
Offset _value;
};
// OFFSET // OFFSET
template<typename Offset> template<typename Offset>
struct offset_t struct offset_t
@ -44,49 +61,107 @@ namespace sqlpp
static_assert(is_integral_t<Offset>::value, "offset requires an integral value or integral parameter"); static_assert(is_integral_t<Offset>::value, "offset requires an integral value or integral parameter");
offset_t(Offset value): // Data
_value(value) using _data_t = offset_data_t<Offset>;
{}
offset_t(const offset_t&) = default; // Member implementation with data and methods
offset_t(offset_t&&) = default; template <typename Policies>
offset_t& operator=(const offset_t&) = default; struct _impl_t
offset_t& operator=(offset_t&&) = default; {
~offset_t() = default; _data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = offset_data_t<Offset>;
_impl_t<Policies> offset;
_impl_t<Policies>& operator()() { return offset; }
const _impl_t<Policies>& operator()() const { return offset; }
template<typename T>
static auto _get_member(T t) -> decltype(t.offset)
{
return t.offset;
}
};
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
}; };
Offset _value;
}; };
// DYNAMIC OFFSET DATA
template<typename Database>
struct dynamic_offset_data_t
{
dynamic_offset_data_t():
_value(noop())
{
}
template<typename Offset>
dynamic_offset_data_t(Offset value):
_initialized(true),
_value(typename wrap_operand<Offset>::type(value))
{
}
dynamic_offset_data_t(const dynamic_offset_data_t&) = default;
dynamic_offset_data_t(dynamic_offset_data_t&&) = default;
dynamic_offset_data_t& operator=(const dynamic_offset_data_t&) = default;
dynamic_offset_data_t& operator=(dynamic_offset_data_t&&) = default;
~dynamic_offset_data_t() = default;
bool _initialized = false;
interpretable_t<Database> _value;
};
// DYNAMIC OFFSET
template<typename Database> template<typename Database>
struct dynamic_offset_t struct dynamic_offset_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::offset>; using _traits = make_traits<no_value_t, ::sqlpp::tag::offset>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
dynamic_offset_t& _offset() { return *this; } // Data
using _data_t = dynamic_offset_data_t<Database>;
dynamic_offset_t(): // Member implementation with data and methods
_value(noop()) template <typename Policies>
struct _impl_t
{ {
}
template<typename Offset> template<typename Offset>
dynamic_offset_t(Offset value): void set(Offset value)
_initialized(true),
_value(typename wrap_operand<Offset>::type(value))
{ {
// FIXME: Make sure that Offset does not require external tables? Need to read up on SQL
using arg_t = typename wrap_operand<Offset>::type;
_data._value = arg_t{value};
_data._initialized = true;
} }
public:
_data_t _data;
};
dynamic_offset_t(const dynamic_offset_t&) = default; // Member template for adding the named member to a statement
dynamic_offset_t(dynamic_offset_t&&) = default; template<typename Policies>
dynamic_offset_t& operator=(const dynamic_offset_t&) = default; struct _member_t
dynamic_offset_t& operator=(dynamic_offset_t&&) = default; {
~dynamic_offset_t() = default; using _data_t = dynamic_offset_data_t<Database>;
_impl_t<Policies> offset;
_impl_t<Policies>& operator()() { return offset; }
const _impl_t<Policies>& operator()() const { return offset; }
template<typename T>
static auto _get_member(T t) -> decltype(t.offset)
{
return t.offset;
}
};
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
@ -110,6 +185,33 @@ namespace sqlpp
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_offset;
_impl_t<Policies>& operator()() { return no_offset; }
const _impl_t<Policies>& operator()() const { return no_offset; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_offset)
{
return t.no_offset;
}
};
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
@ -121,23 +223,23 @@ namespace sqlpp
auto offset(Arg arg) auto offset(Arg arg)
-> _new_statement_t<offset_t<typename wrap_operand<Arg>::type>> -> _new_statement_t<offset_t<typename wrap_operand<Arg>::type>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), offset_t<typename wrap_operand<Arg>::type>{{arg}} }; return { *static_cast<typename Policies::_statement_t*>(this), offset_data_t<typename wrap_operand<Arg>::type>{{arg}} };
} }
auto dynamic_offset() auto dynamic_offset()
-> _new_statement_t<dynamic_offset_t<_database_t>> -> _new_statement_t<dynamic_offset_t<_database_t>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_offset must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_offset must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), dynamic_offset_t<_database_t>{} }; return { *static_cast<typename Policies::_statement_t*>(this), dynamic_offset_data_t<_database_t>{} };
} }
}; };
}; };
// Interpreters // Interpreters
template<typename Context, typename Offset> template<typename Context, typename Offset>
struct serializer_t<Context, offset_t<Offset>> struct serializer_t<Context, offset_data_t<Offset>>
{ {
using T = offset_t<Offset>; using T = offset_data_t<Offset>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
@ -148,9 +250,9 @@ namespace sqlpp
}; };
template<typename Context, typename Database> template<typename Context, typename Database>
struct serializer_t<Context, dynamic_offset_t<Database>> struct serializer_t<Context, dynamic_offset_data_t<Database>>
{ {
using T = dynamic_offset_t<Database>; using T = dynamic_offset_data_t<Database>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
@ -162,17 +264,6 @@ namespace sqlpp
return context; return context;
} }
}; };
template<typename Context>
struct serializer_t<Context, no_offset_t>
{
using T = no_offset_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
} }
} }

View File

@ -39,73 +39,133 @@ namespace sqlpp
{ {
namespace vendor namespace vendor
{ {
// ORDER BY DATA
template<typename Database, typename... Expressions> template<typename Database, typename... Expressions>
struct order_by_t struct order_by_data_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::group_by>; order_by_data_t(Expressions... expressions):
using _recursive_traits = make_recursive_traits<Expressions...>;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one sort-order expression required in order_by()");
static_assert(not ::sqlpp::detail::has_duplicates<Expressions...>::value, "at least one duplicate argument detected in order_by()");
static_assert(::sqlpp::detail::all_t<is_sort_order_t<Expressions>::value...>::value, "at least one argument is not a sort order expression in order_by()");
order_by_t& _order_by() { return *this; }
order_by_t(Expressions... expressions):
_expressions(expressions...) _expressions(expressions...)
{} {}
order_by_t(const order_by_t&) = default; order_by_data_t(const order_by_data_t&) = default;
order_by_t(order_by_t&&) = default; order_by_data_t(order_by_data_t&&) = default;
order_by_t& operator=(const order_by_t&) = default; order_by_data_t& operator=(const order_by_data_t&) = default;
order_by_t& operator=(order_by_t&&) = default; order_by_data_t& operator=(order_by_data_t&&) = default;
~order_by_t() = default; ~order_by_data_t() = default;
template<typename Policies>
struct _methods_t
{
template<typename Expression>
void add_order_by_ntc(Expression expression)
{
add_order_by<Expression, std::false_type>(expression);
}
template<typename Expression, typename TableCheckRequired = std::true_type>
void add_order_by(Expression expression)
{
static_assert(_is_dynamic::value, "add_order_by must not be called for static order_by");
static_assert(is_sort_order_t<Expression>::value, "invalid expression argument in add_order_by()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in add_order_by()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_sort_order_t<Expression>::value>;
_add_order_by_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename Expression>
void _add_order_by_impl(Expression expression, const std::true_type&)
{
return static_cast<typename Policies::_statement_t*>(this)->_order_by()._dynamic_expressions.emplace_back(expression);
}
template<typename Expression>
void _add_order_by_impl(Expression expression, const std::false_type&);
};
std::tuple<Expressions...> _expressions; std::tuple<Expressions...> _expressions;
vendor::interpretable_list_t<Database> _dynamic_expressions; vendor::interpretable_list_t<Database> _dynamic_expressions;
}; };
// ORDER BY
template<typename Database, typename... Expressions>
struct order_by_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::order_by>;
using _recursive_traits = make_recursive_traits<Expressions...>;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression (e.g. a column) required in order_by()");
static_assert(not ::sqlpp::detail::has_duplicates<Expressions...>::value, "at least one duplicate argument detected in order_by()");
static_assert(::sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in order_by()");
// Data
using _data_t = order_by_data_t<Database, Expressions...>;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
template<typename Expression>
void add_ntc(Expression expression)
{
add<Expression, std::false_type>(expression);
}
template<typename Expression, typename TableCheckRequired = std::true_type>
void add(Expression expression)
{
static_assert(_is_dynamic::value, "add() must not be called for static order_by");
static_assert(is_expression_t<Expression>::value, "invalid expression argument in order_by::add()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in order_by::add()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t<Expression>::value>;
_add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename Expression>
void _add_impl(Expression expression, const std::true_type&)
{
return _data._dynamic_expressions.emplace_back(expression);
}
template<typename Expression>
void _add_impl(Expression expression, const std::false_type&);
public:
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = order_by_data_t<Database, Expressions...>;
_impl_t<Policies> order_by;
_impl_t<Policies>& operator()() { return order_by; }
const _impl_t<Policies>& operator()() const { return order_by; }
template<typename T>
static auto _get_member(T t) -> decltype(t.order_by)
{
return t.order_by;
}
};
template<typename Policies>
struct _methods_t
{
};
};
// NO ORDER BY YET
struct no_order_by_t struct no_order_by_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_order_by;
_impl_t<Policies>& operator()() { return no_order_by; }
const _impl_t<Policies>& operator()() const { return no_order_by; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_order_by)
{
return t.no_order_by;
}
};
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
@ -117,7 +177,7 @@ namespace sqlpp
auto order_by(Args... args) auto order_by(Args... args)
-> _new_statement_t<order_by_t<void, Args...>> -> _new_statement_t<order_by_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), order_by_t<void, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), order_by_data_t<void, Args...>{args...} };
} }
template<typename... Args> template<typename... Args>
@ -125,16 +185,16 @@ namespace sqlpp
-> _new_statement_t<order_by_t<_database_t, Args...>> -> _new_statement_t<order_by_t<_database_t, Args...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_order_by must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_order_by must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), vendor::order_by_t<_database_t, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), order_by_data_t<_database_t, Args...>{args...} };
} }
}; };
}; };
// Interpreters // Interpreters
template<typename Context, typename Database, typename... Expressions> template<typename Context, typename Database, typename... Expressions>
struct serializer_t<Context, order_by_t<Database, Expressions...>> struct serializer_t<Context, order_by_data_t<Database, Expressions...>>
{ {
using T = order_by_t<Database, Expressions...>; using T = order_by_data_t<Database, Expressions...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
@ -148,18 +208,6 @@ namespace sqlpp
return context; return context;
} }
}; };
template<typename Context>
struct serializer_t<Context, no_order_by_t>
{
using T = no_order_by_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
} }
} }

View File

@ -44,18 +44,18 @@ namespace sqlpp
{ {
namespace detail namespace detail
{ {
template<typename... Rest> template<typename... Columns>
struct get_first_argument_if_unique struct select_traits
{ {
using _traits = make_traits<no_value_t, tag::select_column_list, tag::return_value>; using _traits = make_traits<no_value_t, tag::select_column_list, tag::return_value>;
struct _name_t {}; struct _name_t {};
}; };
template<typename T> template<typename Column>
struct get_first_argument_if_unique<T> struct select_traits<Column>
{ {
using _traits = make_traits<value_type_of<T>, tag::select_column_list, tag::return_value, tag::expression, tag::named_expression>; using _traits = make_traits<value_type_of<Column>, tag::select_column_list, tag::return_value, tag::expression, tag::named_expression>;
using _name_t = typename T::_name_t; using _name_t = typename Column::_name_t;
}; };
} }
@ -127,79 +127,69 @@ namespace sqlpp
} }
}; };
// SELECTED COLUMNS DATA
template<typename Database, typename... Columns>
struct select_column_list_data_t
{
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
// SELECT COLUMNS select_column_list_data_t(Columns... columns):
_columns(columns...)
{}
select_column_list_data_t(std::tuple<Columns...> columns):
_columns(columns)
{}
select_column_list_data_t(const select_column_list_data_t&) = default;
select_column_list_data_t(select_column_list_data_t&&) = default;
select_column_list_data_t& operator=(const select_column_list_data_t&) = default;
select_column_list_data_t& operator=(select_column_list_data_t&&) = default;
~select_column_list_data_t() = default;
std::tuple<Columns...> _columns;
dynamic_select_column_list<Database> _dynamic_columns;
};
// SELECTED COLUMNS
template<typename Database, typename... Columns> template<typename Database, typename... Columns>
struct select_column_list_t struct select_column_list_t
{ {
// get_first_argument_if_unique is kind of ugly using _traits = typename ::sqlpp::detail::select_traits<Columns...>::_traits;
using _traits = typename ::sqlpp::detail::get_first_argument_if_unique<Columns...>::_traits;
using _recursive_traits = make_recursive_traits<Columns...>; using _recursive_traits = make_recursive_traits<Columns...>;
using _name_t = typename ::sqlpp::detail::get_first_argument_if_unique<Columns...>::_name_t; using _name_t = typename ::sqlpp::detail::select_traits<Columns...>::_name_t;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type; using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
static_assert(not ::sqlpp::detail::has_duplicates<Columns...>::value, "at least one duplicate argument detected"); static_assert(not ::sqlpp::detail::has_duplicates<Columns...>::value, "at least one duplicate argument detected");
template<typename T> static_assert(::sqlpp::detail::all_t<(is_named_expression_t<Columns>::value or is_multi_column_t<Columns>::value)...>::value, "at least one argument is not a named expression");
using is_valid_expression_t = std::integral_constant<bool, is_named_expression_t<T>::value or is_multi_column_t<T>::value>;
static_assert(::sqlpp::detail::all_t<is_valid_expression_t<Columns>::value...>::value, "at least one argument is not a named expression");
static_assert(not ::sqlpp::detail::has_duplicates<typename Columns::_name_t...>::value, "at least one duplicate name detected"); static_assert(not ::sqlpp::detail::has_duplicates<typename Columns::_name_t...>::value, "at least one duplicate name detected");
struct _column_type {}; struct _column_type {};
// Data
using _data_t = select_column_list_data_t<Database, Columns...>;
template<typename Db> // Member implementation with data and methods
using _result_row_t = typename std::conditional<_is_dynamic::value,
dynamic_result_row_t<Db, make_field_t<Columns>...>,
result_row_t<Db, make_field_t<Columns>...>>::type;
using _dynamic_names_t = typename dynamic_select_column_list<Database>::_names_t;
template <typename Select>
using _pseudo_table_t = select_pseudo_table_t<Select, Columns...>;
template <typename Db>
using _dynamic_t = select_column_list_t<Db, std::tuple<Columns...>>;
select_column_list_t& _select_column_list() { return *this; }
select_column_list_t(std::tuple<Columns...> columns):
_columns(columns)
{}
select_column_list_t(Columns... columns):
_columns(columns...)
{}
select_column_list_t(const select_column_list_t&) = default;
select_column_list_t(select_column_list_t&&) = default;
select_column_list_t& operator=(const select_column_list_t&) = default;
select_column_list_t& operator=(select_column_list_t&&) = default;
~select_column_list_t() = default;
static constexpr size_t static_size()
{
return sizeof...(Columns);
}
template<typename Policies> template<typename Policies>
struct _methods_t struct _impl_t
{ {
template<typename NamedExpression> template<typename NamedExpression>
void add_column_ntc(NamedExpression namedExpression) void add_ntc(NamedExpression namedExpression)
{ {
add_column<NamedExpression, std::false_type>(namedExpression); add<NamedExpression, std::false_type>(namedExpression);
} }
template<typename NamedExpression, typename TableCheckRequired = std::true_type> template<typename NamedExpression, typename TableCheckRequired = std::true_type>
void add_column(NamedExpression namedExpression) void add(NamedExpression namedExpression)
{ {
static_assert(_is_dynamic::value, "add_column can only be called for dynamic_column"); static_assert(_is_dynamic::value, "selected_columns::add() can only be called for dynamic_column");
static_assert(is_named_expression_t<NamedExpression>::value, "invalid named expression argument in add_column()"); static_assert(is_named_expression_t<NamedExpression>::value, "invalid named expression argument in selected_columns::add()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<NamedExpression>::value, "named expression uses tables unknown to this statement in add_column()"); static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<NamedExpression>::value, "named expression uses tables unknown to this statement in selected_columns::add()");
using column_names = ::sqlpp::detail::make_type_set_t<typename Columns::_name_t...>; using column_names = ::sqlpp::detail::make_type_set_t<typename Columns::_name_t...>;
static_assert(not ::sqlpp::detail::is_element_of<typename NamedExpression::_name_t, column_names>::value, "a column of this name is present in the select already"); static_assert(not ::sqlpp::detail::is_element_of<typename NamedExpression::_name_t, column_names>::value, "a column of this name is present in the select already");
@ -208,24 +198,118 @@ namespace sqlpp
is_named_expression_t<NamedExpression>::value is_named_expression_t<NamedExpression>::value
>; >;
_add_column_impl(namedExpression, ok()); // dispatch to prevent compile messages after the static_assert _add_impl(namedExpression, ok()); // dispatch to prevent compile messages after the static_assert
} }
private: //private:
template<typename NamedExpression> template<typename NamedExpression>
void _add_column_impl(NamedExpression namedExpression, const std::true_type&) void _add_impl(NamedExpression namedExpression, const std::true_type&)
{ {
return static_cast<typename Policies::_statement_t*>(this)->_select_column_list()._dynamic_columns.emplace_back(namedExpression); return _data._dynamic_columns.emplace_back(namedExpression);
} }
template<typename NamedExpression> template<typename NamedExpression>
void _add_column_impl(NamedExpression namedExpression, const std::false_type&); void _add_column_impl(NamedExpression namedExpression, const std::false_type&);
public:
_data_t _data;
}; };
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = select_column_list_data_t<Database, Columns...>;
_impl_t<Policies> selected_columns;
_impl_t<Policies>& operator()() { return selected_columns; }
const _impl_t<Policies>& operator()() const { return selected_columns; }
template<typename T>
static auto _get_member(T t) -> decltype(t.selected_columns)
{
return t.selected_columns;
}
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
};
// Result methods
template<typename Policies>
struct _result_methods_t
{
using _statement_t = typename Policies::_statement_t;
const _statement_t& _get_statement() const
{
return static_cast<const _statement_t&>(*this);
}
template<typename Db>
using _result_row_t = typename std::conditional<_is_dynamic::value,
dynamic_result_row_t<Db, make_field_t<Columns>...>,
result_row_t<Db, make_field_t<Columns>...>>::type;
using _dynamic_names_t = typename dynamic_select_column_list<Database>::_names_t;
template<typename AliasProvider>
struct _deferred_table_t
{
using table = select_pseudo_table_t<_statement_t, Columns...>;
using alias = typename table::template _alias_t<AliasProvider>;
};
template<typename AliasProvider>
using _table_t = typename _deferred_table_t<AliasProvider>::table;
template<typename AliasProvider>
using _alias_t = typename _deferred_table_t<AliasProvider>::alias;
template<typename AliasProvider>
_alias_t<AliasProvider> as(const AliasProvider& aliasProvider) const
{
static_assert(Policies::_can_be_used_as_table::value, "statement cannot be used as table, e.g. due to missing tables");
return _table_t<AliasProvider>(_get_statement()).as(aliasProvider);
}
const _dynamic_names_t& get_dynamic_names() const
{
return _get_statement().selected_columns._data._dynamic_columns._dynamic_expression_names;
}
size_t get_no_of_result_columns() const
{
return sizeof...(Columns) + get_dynamic_names().size();
}
// Execute
template<typename Db>
auto _run(Db& db) const
-> result_t<decltype(db.select(_get_statement())), _result_row_t<Db>>
{
_statement_t::_check_consistency();
static_assert(_statement_t::_get_static_no_of_parameters() == 0, "cannot run select directly with parameters, use prepare instead");
return {db.select(_get_statement()), get_dynamic_names()};
}
#if 0
// Prepare
template<typename Db>
auto _prepare(Db& db) const
-> prepared_select_t<Db, select_t>
{
_statement_t::_check_consistency();
return {{}, get_dynamic_names(), db.prepare_select(*this)};
}
#endif
};
const select_column_list_t& _column_list() const { return *this; }
std::tuple<Columns...> _columns;
dynamic_select_column_list<Database> _dynamic_columns;
}; };
} }
@ -244,17 +328,36 @@ namespace sqlpp
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop, ::sqlpp::tag::missing>; using _traits = make_traits<no_value_t, ::sqlpp::tag::noop, ::sqlpp::tag::missing>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
template<typename Db>
using _result_row_t = ::sqlpp::result_row_t<Db>;
using _dynamic_names_t = typename dynamic_select_column_list<void>::_names_t;
struct _name_t {}; struct _name_t {};
template<typename T> // Data
struct _pseudo_table_t using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{ {
static_assert(wrong_t<T>::value, "Cannot use a select as a table when no columns have been selected yet"); _data_t _data;
}; };
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_selected_columns;
_impl_t<Policies>& operator()() { return no_selected_columns; }
const _impl_t<Policies>& operator()() const { return no_selected_columns; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_selected_columns)
{
return t.no_selected_columns;
}
};
// Additional methods for the statement
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
@ -266,7 +369,7 @@ namespace sqlpp
auto columns(Args... args) auto columns(Args... args)
-> _new_statement_t<::sqlpp::detail::make_select_column_list_t<void, Args...>> -> _new_statement_t<::sqlpp::detail::make_select_column_list_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), ::sqlpp::detail::make_select_column_list_t<void, Args...>{std::tuple_cat(::sqlpp::detail::as_tuple<Args>::_(args)...)} }; return { *static_cast<typename Policies::_statement_t*>(this), typename ::sqlpp::detail::make_select_column_list_t<void, Args...>::_data_t{std::tuple_cat(::sqlpp::detail::as_tuple<Args>::_(args)...)} };
} }
template<typename... Args> template<typename... Args>
@ -274,16 +377,16 @@ namespace sqlpp
-> _new_statement_t<::sqlpp::detail::make_select_column_list_t<_database_t, Args...>> -> _new_statement_t<::sqlpp::detail::make_select_column_list_t<_database_t, Args...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_columns must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_columns must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), ::sqlpp::detail::make_select_column_list_t<_database_t, Args...>{std::tuple_cat(::sqlpp::detail::as_tuple<Args>::_(args)...)} }; return { *static_cast<typename Policies::_statement_t*>(this), typename ::sqlpp::detail::make_select_column_list_t<_database_t, Args...>::_data_t{std::tuple_cat(::sqlpp::detail::as_tuple<Args>::_(args)...)} };
} }
}; };
}; };
// Interpreters // Interpreters
template<typename Context, typename Database, typename... Columns> template<typename Context, typename Database, typename... Columns>
struct serializer_t<Context, select_column_list_t<Database, Columns...>> struct serializer_t<Context, select_column_list_data_t<Database, Columns...>>
{ {
using T = select_column_list_t<Database, Columns...>; using T = select_column_list_data_t<Database, Columns...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
@ -298,16 +401,6 @@ namespace sqlpp
} }
}; };
template<typename Context>
struct serializer_t<Context, no_select_column_list_t>
{
using T = no_select_column_list_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
} }
} }

View File

@ -38,6 +38,24 @@ namespace sqlpp
{ {
namespace vendor namespace vendor
{ {
// SELECTED FLAGS DATA
template<typename Database, typename... Flags>
struct select_flag_list_data_t
{
select_flag_list_data_t(Flags... flags):
_flags(flags...)
{}
select_flag_list_data_t(const select_flag_list_data_t&) = default;
select_flag_list_data_t(select_flag_list_data_t&&) = default;
select_flag_list_data_t& operator=(const select_flag_list_data_t&) = default;
select_flag_list_data_t& operator=(select_flag_list_data_t&&) = default;
~select_flag_list_data_t() = default;
std::tuple<Flags...> _flags;
vendor::interpretable_list_t<Database> _dynamic_flags;
};
// SELECT FLAGS // SELECT FLAGS
template<typename Database, typename... Flags> template<typename Database, typename... Flags>
struct select_flag_list_t struct select_flag_list_t
@ -51,53 +69,67 @@ namespace sqlpp
static_assert(::sqlpp::detail::all_t<is_select_flag_t<Flags>::value...>::value, "at least one argument is not a select flag in select flag list"); static_assert(::sqlpp::detail::all_t<is_select_flag_t<Flags>::value...>::value, "at least one argument is not a select flag in select flag list");
select_flag_list_t& _select_flag_list() { return *this; } // Data
using _data_t = select_flag_list_data_t<Database, Flags...>;
select_flag_list_t(Flags... flags):
_flags(flags...)
{}
select_flag_list_t(const select_flag_list_t&) = default;
select_flag_list_t(select_flag_list_t&&) = default;
select_flag_list_t& operator=(const select_flag_list_t&) = default;
select_flag_list_t& operator=(select_flag_list_t&&) = default;
~select_flag_list_t() = default;
// Member implementation with data and methods
template<typename Policies> template<typename Policies>
struct _methods_t struct _impl_t
{ {
template<typename Flag> template<typename Flag>
void add_flag_ntc(Flag flag) void add_ntc(Flag flag)
{ {
add_flag<Flag, std::false_type>(flag); add<Flag, std::false_type>(flag);
} }
template<typename Flag, typename TableCheckRequired = std::true_type> template<typename Flag, typename TableCheckRequired = std::true_type>
void add_flag(Flag flag) void add(Flag flag)
{ {
static_assert(_is_dynamic::value, "add_flag must not be called for static select flags"); static_assert(_is_dynamic::value, "select_flags::add() must not be called for static select flags");
static_assert(is_select_flag_t<Flag>::value, "invalid select flag argument in add_flag()"); static_assert(is_select_flag_t<Flag>::value, "invalid select flag argument in select_flags::add()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Flag>::value, "flag uses tables unknown to this statement in add_flag()"); static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Flag>::value, "flag uses tables unknown to this statement in select_flags::add()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_select_flag_t<Flag>::value>; using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_select_flag_t<Flag>::value>;
_add_flag_impl(flag, ok()); // dispatch to prevent compile messages after the static_assert _add_impl(flag, ok()); // dispatch to prevent compile messages after the static_assert
} }
private: private:
template<typename Flag> template<typename Flag>
void _add_flag_impl(Flag flag, const std::true_type&) void _add_impl(Flag flag, const std::true_type&)
{ {
return static_cast<typename Policies::_statement_t*>(this)->_select_flag_list()._dynamic_flags.emplace_back(flag); return _data._dynamic_flags.emplace_back(flag);
} }
template<typename Flag> template<typename Flag>
void _add_flag_impl(Flag flag, const std::false_type&); void _add_impl(Flag flag, const std::false_type&);
public:
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = select_flag_list_data_t<Database, Flags...>;
_impl_t<Policies> select_flags;
_impl_t<Policies>& operator()() { return select_flags; }
const _impl_t<Policies>& operator()() const { return select_flags; }
template<typename T>
static auto _get_member(T t) -> decltype(t.select_flags)
{
return t.select_flags;
}
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
}; };
const select_flag_list_t& _flag_list() const { return *this; }
std::tuple<Flags...> _flags;
vendor::interpretable_list_t<Database> _dynamic_flags;
}; };
struct no_select_flag_list_t struct no_select_flag_list_t
@ -105,6 +137,33 @@ namespace sqlpp
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_select_flags;
_impl_t<Policies>& operator()() { return no_select_flags; }
const _impl_t<Policies>& operator()() const { return no_select_flags; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_select_flags)
{
return t.no_select_flags;
}
};
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
@ -116,7 +175,7 @@ namespace sqlpp
auto flags(Args... args) auto flags(Args... args)
-> _new_statement_t<select_flag_list_t<void, Args...>> -> _new_statement_t<select_flag_list_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), select_flag_list_t<void, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), select_flag_list_data_t<void, Args...>{args...} };
} }
template<typename... Args> template<typename... Args>
@ -124,7 +183,7 @@ namespace sqlpp
-> _new_statement_t<select_flag_list_t<_database_t, Args...>> -> _new_statement_t<select_flag_list_t<_database_t, Args...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_flags must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_flags must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), vendor::select_flag_list_t<_database_t, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), select_flag_list_data_t<_database_t, Args...>{args...} };
} }
}; };
}; };
@ -132,9 +191,9 @@ namespace sqlpp
// Interpreters // Interpreters
template<typename Context, typename Database, typename... Flags> template<typename Context, typename Database, typename... Flags>
struct serializer_t<Context, select_flag_list_t<Database, Flags...>> struct serializer_t<Context, select_flag_list_data_t<Database, Flags...>>
{ {
using T = select_flag_list_t<Database, Flags...>; using T = select_flag_list_data_t<Database, Flags...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
@ -148,16 +207,6 @@ namespace sqlpp
} }
}; };
template<typename Context>
struct serializer_t<Context, no_select_flag_list_t>
{
using T = no_select_flag_list_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
} }
} }

View File

@ -55,8 +55,8 @@ namespace sqlpp
Select, Select,
NamedExpr...>, select_column_spec_t<NamedExpr>...> NamedExpr...>, select_column_spec_t<NamedExpr>...>
{ {
using _value_type = no_value_t; using _traits = make_traits<no_value_t, tag::table, tag::pseudo_table>;
using _is_pseudo_table = std::true_type; using _recursive_traits = make_recursive_traits<>;
select_pseudo_table_t(Select select): select_pseudo_table_t(Select select):
_select(select) _select(select)

View File

@ -36,39 +36,151 @@ namespace sqlpp
{ {
namespace vendor namespace vendor
{ {
// A SINGLE TABLE DATA
template<typename Database, typename Table>
struct single_table_data_t
{
single_table_data_t(Table table):
_table(table)
{}
single_table_data_t(const single_table_data_t&) = default;
single_table_data_t(single_table_data_t&&) = default;
single_table_data_t& operator=(const single_table_data_t&) = default;
single_table_data_t& operator=(single_table_data_t&&) = default;
~single_table_data_t() = default;
Table _table;
};
// A SINGLE TABLE // A SINGLE TABLE
template<typename Database, typename Table> template<typename Database, typename Table>
struct single_table_t struct single_table_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::single_table>; using _traits = make_traits<no_value_t, ::sqlpp::tag::single_table, tag::return_value>;
using _recursive_traits = make_recursive_traits<Table>; using _recursive_traits = make_recursive_traits<Table>;
static_assert(is_table_t<Table>::value, "argument has to be a table"); static_assert(is_table_t<Table>::value, "argument has to be a table");
static_assert(required_tables_of<Table>::size::value == 0, "table depends on another table"); static_assert(required_tables_of<Table>::size::value == 0, "table depends on another table");
single_table_t(Table table): using _data_t = single_table_data_t<Database, Table>;
_table(table)
{}
single_table_t(const single_table_t&) = default; struct _name_t {};
single_table_t(single_table_t&&) = default;
single_table_t& operator=(const single_table_t&) = default;
single_table_t& operator=(single_table_t&&) = default;
~single_table_t() = default;
// Member implementation with data and methods
template <typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = single_table_data_t<Database, Table>;
_impl_t<Policies> from;
_impl_t<Policies>& operator()() { return from; }
const _impl_t<Policies>& operator()() const { return from; }
template<typename T>
static auto _get_member(T t) -> decltype(t.from)
{
return t.from;
}
};
// Additional methods for the statement
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
}; };
Table _table; template<typename Policies>
struct _result_methods_t
{
using _statement_t = typename Policies::_statement_t;
const _statement_t& _get_statement() const
{
return static_cast<const _statement_t&>(*this);
}
static constexpr size_t _get_static_no_of_parameters()
{
#warning need to fix this
return 0;
//return _parameter_list_t::size::value;
}
size_t _get_no_of_parameters() const
{
#warning need to fix this
return 0;
//return _parameter_list_t::size::value;
}
void _check_consistency() const
{
// FIXME: Read up on what is allowed/prohibited in INSERT
}
template<typename Db>
auto _run(Db& db) const -> decltype(db.insert(_get_statement()))
{
_check_consistency();
static_assert(_get_static_no_of_parameters() == 0, "cannot run insert directly with parameters, use prepare instead");
return db.insert(*this);
}
/*
template<typename Db>
auto _prepare(Db& db) const
-> prepared_insert_t<Db, insert_t>
{
_check_consistency();
return {{}, db.prepare_insert(*this)};
}
*/
};
}; };
// NO INTO YET
struct no_single_table_t struct no_single_table_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>; using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_from;
_impl_t<Policies>& operator()() { return no_from; }
const _impl_t<Policies>& operator()() const { return no_from; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_from)
{
return t.no_from;
}
};
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
@ -76,28 +188,21 @@ namespace sqlpp
template<typename T> template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_single_table_t, T>; using _new_statement_t = typename Policies::template _new_statement_t<no_single_table_t, T>;
template<typename... Args>
auto into(Args... args)
-> _new_statement_t<single_table_t<void, Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), single_table_t<void, Args...>{args...} };
}
#warning: remove can operate on several tables at once, so it should not use single_table anyway #warning: remove can operate on several tables at once, so it should not use single_table anyway
template<typename... Args> template<typename... Args>
auto from(Args... args) auto from(Args... args)
-> _new_statement_t<single_table_t<void, Args...>> -> _new_statement_t<single_table_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), single_table_t<void, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), single_table_data_t<void, Args...>{args...} };
} }
}; };
}; };
// Interpreters // Interpreters
template<typename Context, typename Database, typename Table> template<typename Context, typename Database, typename Table>
struct serializer_t<Context, single_table_t<Database, Table>> struct serializer_t<Context, single_table_data_t<Database, Table>>
{ {
using T = single_table_t<Database, Table>; using T = single_table_data_t<Database, Table>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {

View File

@ -36,6 +36,24 @@ namespace sqlpp
{ {
namespace vendor namespace vendor
{ {
// UPDATE ASSIGNMENTS DATA
template<typename Database, typename... Assignments>
struct update_list_data_t
{
update_list_data_t(Assignments... assignments):
_assignments(assignments...)
{}
update_list_data_t(const update_list_data_t&) = default;
update_list_data_t(update_list_data_t&&) = default;
update_list_data_t& operator=(const update_list_data_t&) = default;
update_list_data_t& operator=(update_list_data_t&&) = default;
~update_list_data_t() = default;
std::tuple<Assignments...> _assignments;
typename vendor::interpretable_list_t<Database> _dynamic_assignments;
};
// UPDATE ASSIGNMENTS // UPDATE ASSIGNMENTS
template<typename Database, typename... Assignments> template<typename Database, typename... Assignments>
struct update_list_t struct update_list_t
@ -61,57 +79,70 @@ namespace sqlpp
static_assert(::sqlpp::detail::is_subset_of<_value_table_set, _column_table_set>::value, "set() contains values from foreign tables"); static_assert(::sqlpp::detail::is_subset_of<_value_table_set, _column_table_set>::value, "set() contains values from foreign tables");
*/ */
update_list_t& _update_list() { return *this; } // Data
using _data_t = update_list_data_t<Database, Assignments...>;
update_list_t(Assignments... assignments):
_assignments(assignments...)
{}
update_list_t(const update_list_t&) = default;
update_list_t(update_list_t&&) = default;
update_list_t& operator=(const update_list_t&) = default;
update_list_t& operator=(update_list_t&&) = default;
~update_list_t() = default;
// Member implementation with data and methods
template <typename Policies> template <typename Policies>
struct _methods_t struct _impl_t
{ {
template<typename Assignment> template<typename Assignment>
void add_set_ntc(Assignment assignment) void add_ntc(Assignment assignment)
{ {
add_set<Assignment, std::false_type>(assignment); add<Assignment, std::false_type>(assignment);
} }
template<typename Assignment, typename TableCheckRequired = std::true_type> template<typename Assignment, typename TableCheckRequired = std::true_type>
void add_set(Assignment assignment) void add(Assignment assignment)
{ {
static_assert(_is_dynamic::value, "add_set must not be called for static from()"); static_assert(_is_dynamic::value, "add must not be called for static from()");
static_assert(is_assignment_t<Assignment>::value, "invalid assignment argument in add_set()"); static_assert(is_assignment_t<Assignment>::value, "invalid assignment argument in add()");
static_assert(sqlpp::detail::not_t<must_not_update_t, typename Assignment::_column_t>::value, "add_set() argument must not be updated"); static_assert(sqlpp::detail::not_t<must_not_update_t, typename Assignment::_column_t>::value, "add() argument must not be updated");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value, "assignment uses tables unknown to this statement in add_set()"); static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value, "assignment uses tables unknown to this statement in add()");
using ok = ::sqlpp::detail::all_t< using ok = ::sqlpp::detail::all_t<
_is_dynamic::value, _is_dynamic::value,
is_assignment_t<Assignment>::value, is_assignment_t<Assignment>::value,
not must_not_update_t<typename Assignment::_column_t>::value>; not must_not_update_t<typename Assignment::_column_t>::value>;
_add_set_impl(assignment, ok()); // dispatch to prevent compile messages after the static_assert _add_impl(assignment, ok()); // dispatch to prevent compile messages after the static_assert
} }
private: private:
template<typename Assignment> template<typename Assignment>
void _add_set_impl(Assignment assignment, const std::true_type&) void _add_impl(Assignment assignment, const std::true_type&)
{ {
return static_cast<typename Policies::_statement_t*>(this)->_update_list()._dynamic_assignments.emplace_back(assignment); return _data._dynamic_assignments.emplace_back(assignment);
} }
template<typename Assignment> template<typename Assignment>
void _add_set_impl(Assignment assignment, const std::false_type&); void _add_impl(Assignment assignment, const std::false_type&);
public:
_data_t _data;
}; };
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = update_list_data_t<Database, Assignments...>;
std::tuple<Assignments...> _assignments; _impl_t<Policies> assignments;
typename vendor::interpretable_list_t<Database> _dynamic_assignments; _impl_t<Policies>& operator()() { return assignments; }
const _impl_t<Policies>& operator()() const { return assignments; }
template<typename T>
static auto _get_member(T t) -> decltype(t.assignments)
{
return t.assignments;
}
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
};
}; };
struct no_update_list_t struct no_update_list_t
@ -119,6 +150,33 @@ namespace sqlpp
using _traits = make_traits<no_value_t, ::sqlpp::tag::where>; using _traits = make_traits<no_value_t, ::sqlpp::tag::where>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_assignments;
_impl_t<Policies>& operator()() { return no_assignments; }
const _impl_t<Policies>& operator()() const { return no_assignments; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_assignments)
{
return t.no_assignments;
}
};
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
@ -130,7 +188,7 @@ namespace sqlpp
auto set(Args... args) auto set(Args... args)
-> _new_statement_t<update_list_t<void, Args...>> -> _new_statement_t<update_list_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), update_list_t<void, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), update_list_data_t<void, Args...>{args...} };
} }
template<typename... Args> template<typename... Args>
@ -138,16 +196,16 @@ namespace sqlpp
-> _new_statement_t<update_list_t<_database_t, Args...>> -> _new_statement_t<update_list_t<_database_t, Args...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_set must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_set must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), vendor::update_list_t<_database_t, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), vendor::update_list_data_t<_database_t, Args...>{args...} };
} }
}; };
}; };
// Interpreters // Interpreters
template<typename Context, typename Database, typename... Assignments> template<typename Context, typename Database, typename... Assignments>
struct serializer_t<Context, update_list_t<Database, Assignments...>> struct serializer_t<Context, update_list_data_t<Database, Assignments...>>
{ {
using T = update_list_t<Database, Assignments...>; using T = update_list_data_t<Database, Assignments...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
@ -159,18 +217,6 @@ namespace sqlpp
return context; return context;
} }
}; };
template<typename Context>
struct serializer_t<Context, no_update_list_t>
{
using T = no_update_list_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
} }
} }

View File

@ -37,6 +37,24 @@ namespace sqlpp
{ {
namespace vendor namespace vendor
{ {
// USING DATA
template<typename Database, typename... Tables>
struct using_data_t
{
using_data_t(Tables... tables):
_tables(tables...)
{}
using_data_t(const using_data_t&) = default;
using_data_t(using_data_t&&) = default;
using_data_t& operator=(const using_data_t&) = default;
using_data_t& operator=(using_data_t&&) = default;
~using_data_t() = default;
std::tuple<Tables...> _tables;
vendor::interpretable_list_t<Database> _dynamic_tables;
};
// USING // USING
template<typename Database, typename... Tables> template<typename Database, typename... Tables>
struct using_t struct using_t
@ -52,53 +70,95 @@ namespace sqlpp
static_assert(::sqlpp::detail::all_t<is_table_t<Tables>::value...>::value, "at least one argument is not an table in using()"); static_assert(::sqlpp::detail::all_t<is_table_t<Tables>::value...>::value, "at least one argument is not an table in using()");
using_t& _using() { return *this; } // Data
using _data_t = using_data_t<Database, Tables...>;
using_t(Tables... tables):
_tables(tables...)
{}
using_t(const using_t&) = default;
using_t(using_t&&) = default;
using_t& operator=(const using_t&) = default;
using_t& operator=(using_t&&) = default;
~using_t() = default;
// Member implementation with data and methods
template <typename Policies> template <typename Policies>
struct _methods_t struct _impl_t
{ {
template<typename Table> template<typename Table>
void add_using(Table table) void add(Table table)
{ {
static_assert(_is_dynamic::value, "add_using must not be called for static using()"); static_assert(_is_dynamic::value, "add must not be called for static using()");
static_assert(is_table_t<Table>::value, "invalid table argument in add_using()"); static_assert(is_table_t<Table>::value, "invalid table argument in add()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_table_t<Table>::value>; using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_table_t<Table>::value>;
_add_using_impl(table, ok()); // dispatch to prevent compile messages after the static_assert _add_impl(table, ok()); // dispatch to prevent compile messages after the static_assert
} }
private: private:
template<typename Table> template<typename Table>
void _add_using_impl(Table table, const std::true_type&) void _add_impl(Table table, const std::true_type&)
{ {
return static_cast<typename Policies::_statement_t*>(this)->_using()._dynamic_tables.emplace_back(table); return _data._dynamic_tables.emplace_back(table);
} }
template<typename Table> template<typename Table>
void _add_using_impl(Table table, const std::false_type&); void _add_impl(Table table, const std::false_type&);
public:
_data_t _data;
}; };
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = using_data_t<Database, Tables...>;
std::tuple<Tables...> _tables; _impl_t<Policies> using_;
vendor::interpretable_list_t<Database> _dynamic_tables; _impl_t<Policies>& operator()() { return using_; }
const _impl_t<Policies>& operator()() const { return using_; }
template<typename T>
static auto _get_member(T t) -> decltype(t.using_)
{
return t.using_;
}
}; };
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
};
};
// NO USING YET
struct no_using_t struct no_using_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::where>; using _traits = make_traits<no_value_t, ::sqlpp::tag::where>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_using;
_impl_t<Policies>& operator()() { return no_using; }
const _impl_t<Policies>& operator()() const { return no_using; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_using)
{
return t.no_using;
}
};
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
@ -110,7 +170,7 @@ namespace sqlpp
auto using_(Args... args) auto using_(Args... args)
-> _new_statement_t<using_t<void, Args...>> -> _new_statement_t<using_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), using_t<void, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), using_data_t<void, Args...>{args...} };
} }
template<typename... Args> template<typename... Args>
@ -118,16 +178,16 @@ namespace sqlpp
-> _new_statement_t<using_t<_database_t, Args...>> -> _new_statement_t<using_t<_database_t, Args...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_using must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_using must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), vendor::using_t<_database_t, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), using_data_t<_database_t, Args...>{args...} };
} }
}; };
}; };
// Interpreters // Interpreters
template<typename Context, typename Database, typename... Tables> template<typename Context, typename Database, typename... Tables>
struct serializer_t<Context, using_t<Database, Tables...>> struct serializer_t<Context, using_data_t<Database, Tables...>>
{ {
using T = using_t<Database, Tables...>; using T = using_data_t<Database, Tables...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
@ -141,17 +201,6 @@ namespace sqlpp
return context; return context;
} }
}; };
template<typename Context>
struct serializer_t<Context, no_using_t>
{
using T = no_using_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
} }
} }

View File

@ -38,96 +38,183 @@ namespace sqlpp
{ {
namespace vendor namespace vendor
{ {
// WHERE // WHERE DATA
template<typename Database, typename... Expressions>
struct where_data_t
{
where_data_t(Expressions... expressions):
_expressions(expressions...)
{}
where_data_t(const where_data_t&) = default;
where_data_t(where_data_t&&) = default;
where_data_t& operator=(const where_data_t&) = default;
where_data_t& operator=(where_data_t&&) = default;
~where_data_t() = default;
std::tuple<Expressions...> _expressions;
vendor::interpretable_list_t<Database> _dynamic_expressions;
};
// WHERE(EXPR)
template<typename Database, typename... Expressions> template<typename Database, typename... Expressions>
struct where_t struct where_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::where>; using _traits = make_traits<no_value_t, ::sqlpp::tag::where>;
using _recursive_traits = make_recursive_traits<Expressions...>; using _recursive_traits = make_recursive_traits<Expressions...>;
#warning: is_dynamic should be using a template alias (making it easier to replace the logic)
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type; using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
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::none_t<is_assignment_t<Expressions>::value...>::value, "at least one argument is an assignment in where()"); static_assert(sqlpp::detail::none_t<is_assignment_t<Expressions>::value...>::value, "at least one argument is an assignment in where()");
static_assert(sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not valid expression in where()"); static_assert(sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not valid expression in where()");
where_t& _where() { return *this; } // Data
using _data_t = where_data_t<Database, Expressions...>;
where_t(Expressions... expressions):
_expressions(expressions...)
{}
where_t(const where_t&) = default;
where_t(where_t&&) = default;
where_t& operator=(const where_t&) = default;
where_t& operator=(where_t&&) = default;
~where_t() = default;
// Member implementation with data and methods
template <typename Policies> template <typename Policies>
struct _methods_t struct _impl_t
{ {
template<typename Expression> template<typename Expression>
void add_where_ntc(Expression expression) void add_ntc(Expression expression)
{ {
add_where<Expression, std::false_type>(expression); add<Expression, std::false_type>(expression);
} }
template<typename Expression, typename TableCheckRequired = std::true_type> template<typename Expression, typename TableCheckRequired = std::true_type>
void add_where(Expression expression) void add(Expression expression)
{ {
static_assert(_is_dynamic::value, "add_where can only be called for dynamic_where"); static_assert(_is_dynamic::value, "where::add() can only be called for dynamic_where");
static_assert(is_expression_t<Expression>::value, "invalid expression argument in add_where()"); static_assert(is_expression_t<Expression>::value, "invalid expression argument in where::add()");
static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in add_where()"); static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in where::add()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t<Expression>::value>; using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t<Expression>::value>;
_add_where_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert _add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
} }
private: private:
template<typename Expression> template<typename Expression>
void _add_where_impl(Expression expression, const std::true_type&) void _add_impl(Expression expression, const std::true_type&)
{ {
return static_cast<typename Policies::_statement_t*>(this)->_where()._dynamic_expressions.emplace_back(expression); return _data._dynamic_expressions.emplace_back(expression);
} }
template<typename Expression> template<typename Expression>
void _add_where_impl(Expression expression, const std::false_type&); void _add_impl(Expression expression, const std::false_type&);
public:
_data_t _data;
}; };
std::tuple<Expressions...> _expressions; // Member template for adding the named member to a statement
vendor::interpretable_list_t<Database> _dynamic_expressions; template<typename Policies>
struct _member_t
{
using _data_t = where_data_t<Database, Expressions...>;
_impl_t<Policies> where;
_impl_t<Policies>& operator()() { return where; }
const _impl_t<Policies>& operator()() const { return where; }
template<typename T>
static auto _get_member(T t) -> decltype(t.where)
{
return t.where;
}
}; };
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
};
};
template<>
struct where_data_t<void, bool>
{
bool _condition;
};
// WHERE(BOOL)
template<> template<>
struct where_t<void, bool> struct where_t<void, bool>
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::where>; using _traits = make_traits<no_value_t, ::sqlpp::tag::where>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
where_t(bool condition): // Data
_condition(condition) using _data_t = where_data_t<void, bool>;
{}
where_t(const where_t&) = default; // Member implementation with data and methods
where_t(where_t&&) = default; template<typename Policies>
where_t& operator=(const where_t&) = default; struct _impl_t
where_t& operator=(where_t&&) = default; {
~where_t() = default; _data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = where_data_t<void, bool>;
_impl_t<Policies> where;
_impl_t<Policies>& operator()() { return where; }
const _impl_t<Policies>& operator()() const { return where; }
template<typename T>
static auto _get_member(T t) -> decltype(t.where)
{
return t.where;
}
};
// Additional methods for the statement
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
}; };
bool _condition;
}; };
// NO WHERE YET
struct no_where_t struct no_where_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::where>; using _traits = make_traits<no_value_t, ::sqlpp::tag::where>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_where;
_impl_t<Policies>& operator()() { return no_where; }
const _impl_t<Policies>& operator()() const { return no_where; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_where)
{
return t.no_where;
}
};
// Additional methods for the statement
template<typename Policies> template<typename Policies>
struct _methods_t struct _methods_t
{ {
@ -139,7 +226,7 @@ namespace sqlpp
auto where(Args... args) auto where(Args... args)
-> _new_statement_t<where_t<void, Args...>> -> _new_statement_t<where_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), where_t<void, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), where_data_t<void, Args...>{args...} };
} }
template<typename... Args> template<typename... Args>
@ -147,16 +234,16 @@ namespace sqlpp
-> _new_statement_t<where_t<_database_t, Args...>> -> _new_statement_t<where_t<_database_t, Args...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_where must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_where must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), vendor::where_t<_database_t, Args...>{args...} }; return { *static_cast<typename Policies::_statement_t*>(this), where_data_t<_database_t, Args...>{args...} };
} }
}; };
}; };
// Interpreters // Interpreters
template<typename Context, typename Database, typename... Expressions> template<typename Context, typename Database, typename... Expressions>
struct serializer_t<Context, where_t<Database, Expressions...>> struct serializer_t<Context, where_data_t<Database, Expressions...>>
{ {
using T = where_t<Database, Expressions...>; using T = where_data_t<Database, Expressions...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
@ -172,9 +259,9 @@ namespace sqlpp
}; };
template<typename Context> template<typename Context>
struct serializer_t<Context, where_t<void, bool>> struct serializer_t<Context, where_data_t<void, bool>>
{ {
using T = where_t<void, bool>; using T = where_data_t<void, bool>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
@ -184,17 +271,6 @@ namespace sqlpp
} }
}; };
template<typename Context>
struct serializer_t<Context, no_where_t>
{
using T = no_where_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
} }
} }

View File

@ -45,7 +45,7 @@ namespace sqlpp
{ {
struct boolean_operand struct boolean_operand
{ {
using _traits = make_traits<::sqlpp::detail::boolean, ::sqlpp::tag::expression>; using _traits = make_traits<::sqlpp::detail::boolean, ::sqlpp::tag::expression, ::sqlpp::tag::wrapped_value>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
using _value_t = bool; using _value_t = bool;
@ -83,7 +83,7 @@ namespace sqlpp
struct integral_operand struct integral_operand
{ {
using _traits = make_traits<::sqlpp::detail::integral, ::sqlpp::tag::expression>; using _traits = make_traits<::sqlpp::detail::integral, ::sqlpp::tag::expression, ::sqlpp::tag::wrapped_value>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
using _value_t = int64_t; using _value_t = int64_t;
@ -122,7 +122,7 @@ namespace sqlpp
struct floating_point_operand struct floating_point_operand
{ {
using _traits = make_traits<::sqlpp::detail::floating_point, ::sqlpp::tag::expression>; using _traits = make_traits<::sqlpp::detail::floating_point, ::sqlpp::tag::expression, ::sqlpp::tag::wrapped_value>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
using _value_t = double; using _value_t = double;
@ -160,7 +160,7 @@ namespace sqlpp
struct text_operand struct text_operand
{ {
using _traits = make_traits<::sqlpp::detail::text, ::sqlpp::tag::expression>; using _traits = make_traits<::sqlpp::detail::text, ::sqlpp::tag::expression, ::sqlpp::tag::wrapped_value>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
using _value_t = std::string; using _value_t = std::string;

View File

@ -7,9 +7,9 @@ macro (build_and_run arg)
endmacro () endmacro ()
#build_and_run(InterpretTest) #build_and_run(InterpretTest)
#build_and_run(InsertTest) build_and_run(InsertTest)
#build_and_run(RemoveTest) #build_and_run(RemoveTest)
build_and_run(UpdateTest) #build_and_run(UpdateTest)
#build_and_run(SelectTest) #build_and_run(SelectTest)
#build_and_run(SelectTypeTest) #build_and_run(SelectTypeTest)
#build_and_run(FunctionTest) #build_and_run(FunctionTest)

View File

@ -67,11 +67,12 @@ int main()
serialize(insert_into(t).set(t.beta = "kirschauflauf"), printer).str(); serialize(insert_into(t).set(t.beta = "kirschauflauf"), printer).str();
serialize(insert_into(t).columns(t.beta), printer).str(); serialize(insert_into(t).columns(t.beta), printer).str();
auto multi_insert = insert_into(t).columns(t.beta, t.delta); auto multi_insert = insert_into(t).columns(t.beta, t.delta);
multi_insert.add_values(t.beta = "cheesecake", t.delta = 1); multi_insert.values.add(t.beta = "cheesecake", t.delta = 1);
multi_insert.add_values(t.beta = sqlpp::default_value, t.delta = sqlpp::default_value); multi_insert.values.add(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.insert_list.add(t.beta = "kirschauflauf");
serialize(i, printer).str(); printer.reset();
std::cerr << serialize(i, printer).str() << std::endl;
db(multi_insert); db(multi_insert);

View File

@ -46,12 +46,12 @@ int main()
serialize(insert_into(t).columns(t.beta, t.gamma), printer).str(); serialize(insert_into(t).columns(t.beta, t.gamma), printer).str();
{ {
auto i = insert_into(t).columns(t.gamma, t.beta); auto i = insert_into(t).columns(t.gamma, t.beta);
i.add_values(t.gamma = true, t.beta = "cheesecake"); i.values.add(t.gamma = true, t.beta = "cheesecake");
serialize(i, printer).str(); serialize(i, printer).str();
i.add_values(t.gamma = false, t.beta = sqlpp::tvin("coffee")); i.values.add(t.gamma = false, t.beta = sqlpp::tvin("coffee"));
i.add_values(t.gamma = false, t.beta = sqlpp::tvin(std::string())); i.values.add(t.gamma = false, t.beta = sqlpp::tvin(std::string()));
serialize(i, printer).str(); serialize(i, printer).str();
i.add_values(t.gamma = sqlpp::default_value, t.beta = sqlpp::null); i.values.add(t.gamma = sqlpp::default_value, t.beta = sqlpp::null);
serialize(i, printer).str(); serialize(i, printer).str();
} }
@ -134,22 +134,22 @@ int main()
// dynamic select // dynamic select
{ {
auto s = dynamic_select(db).dynamic_flags().dynamic_columns().from(t); auto s = dynamic_select(db).dynamic_flags().dynamic_columns().from(t);
s.add_column(t.beta); s.selected_columns.add(t.beta);
s.add_column(t.gamma); s.selected_columns.add(t.gamma);
serialize(s, printer).str(); serialize(s, printer).str();
} }
{ {
auto s = dynamic_select(db).dynamic_flags().dynamic_columns().from(t); auto s = dynamic_select(db).dynamic_flags().dynamic_columns().from(t);
s.add_flag(sqlpp::distinct); s.select_flags.add(sqlpp::distinct);
s.add_column(t.beta); s.selected_columns.add(t.beta);
s.add_column(t.gamma); s.selected_columns.add(t.gamma);
serialize(s, printer).str(); serialize(s, printer).str();
} }
{ {
auto s = dynamic_select(db).dynamic_flags(sqlpp::distinct).dynamic_columns(t.alpha).extra_tables(t); // Would fail to run() auto s = dynamic_select(db).dynamic_flags(sqlpp::distinct).dynamic_columns(t.alpha).extra_tables(t); // Would fail to run()
s.add_flag(sqlpp::all); s.select_flags.add(sqlpp::all);
s.add_column(t.beta); s.selected_columns.add(t.beta);
s.add_column(t.gamma); s.selected_columns.add(t.gamma);
serialize(s, printer).str(); serialize(s, printer).str();
} }

View File

@ -43,7 +43,7 @@ struct MockDb: public sqlpp::connection
void reset() void reset()
{ {
_os.clear(); _os.str("");
} }
template<typename T> template<typename T>

View File

@ -60,9 +60,12 @@ int main()
serialize(remove_from(t).where(t.beta != "transparent"), printer).str(); serialize(remove_from(t).where(t.beta != "transparent"), printer).str();
serialize(remove_from(t).using_(t), printer).str(); serialize(remove_from(t).using_(t), printer).str();
auto r = dynamic_remove_from(db, t).dynamic_using().dynamic_where(); auto r = dynamic_remove_from(db, t).dynamic_using().dynamic_where();
r.add_using(t); r.using_.add(t);
r.add_where(t.beta != "transparent"); r.where.add(t.beta != "transparent");
serialize(r, printer).str(); printer.reset();
std::cerr << serialize(r, printer).str() << std::endl;
printer.reset();
std::cerr << serialize(remove_from(t).where(true), printer).str() << std::endl;
db(r); db(r);

View File

@ -49,6 +49,7 @@ int main()
test::TabFoo f; test::TabFoo f;
test::TabBar t; test::TabBar t;
sqlpp::select(t.alpha).flags(sqlpp::all).from(t);
for (const auto& row : db(select(all_of(t)).from(t).where(true))) for (const auto& row : db(select(all_of(t)).from(t).where(true)))
{ {
int64_t a = row.alpha; int64_t a = row.alpha;
@ -68,20 +69,26 @@ int main()
const bool g = row.gamma; const bool g = row.gamma;
} }
auto stat = sqlpp::select().columns(all_of(t)).flags(sqlpp::all).from(t).extra_tables(f,t).where(t.alpha > 0).group_by(t.alpha).order_by(t.gamma.asc()).having(t.gamma).limit(7).offset(19);
auto s = dynamic_select(db).dynamic_columns(all_of(t)).dynamic_flags().dynamic_from(t).extra_tables(f,t).dynamic_where().dynamic_group_by(t.alpha).dynamic_order_by().dynamic_having(t.gamma).dynamic_limit().dynamic_offset(); auto s = dynamic_select(db).dynamic_columns(all_of(t)).dynamic_flags().dynamic_from(t).extra_tables(f,t).dynamic_where().dynamic_group_by(t.alpha).dynamic_order_by().dynamic_having(t.gamma).dynamic_limit().dynamic_offset();
s.add_flag(sqlpp::distinct); s.select_flags.add(sqlpp::distinct);
s.add_column(f.omega); s.selected_columns.add(f.omega);
s.add_from(f); s.from.add(f);
s.add_where(t.alpha > 7); s.where.add(t.alpha > 7);
s.add_having(t.alpha > 7); s.having.add(t.alpha > 7);
s.set_limit(3); s.limit.set(3);
s.set_offset(3); s.offset.set(3);
s.add_group_by(t.beta); s.group_by.add(t.beta);
s.add_order_by(t.beta.asc()); s.order_by.add(t.beta.asc());
for (const auto& row : db(s)) for (const auto& row : db(s))
{ {
int64_t a = row.alpha; int64_t a = row.alpha;
} }
printer.reset();
std::cerr << serialize(s, printer).str() << std::endl;
auto X = select(all_of(t)).from(t).as(t.alpha);
return 0; return 0;
} }

View File

@ -311,10 +311,10 @@ int main()
{ {
auto s = dynamic_select(db, all_of(t)).dynamic_from().dynamic_where().dynamic_limit().dynamic_offset(); auto s = dynamic_select(db, all_of(t)).dynamic_from().dynamic_where().dynamic_limit().dynamic_offset();
s.add_from(t); s.from.add(t);
s.add_where(t.alpha > 7 and t.alpha == any(select(t.alpha).from(t).where(t.alpha < 3))); s.where.add_ntc(t.alpha > 7 and t.alpha == any(select(t.alpha).from(t).where(t.alpha < 3)));
s.set_limit(30); s.limit.set(30);
s.set_limit(3); s.limit.set(3);
std::cerr << "------------------------\n"; std::cerr << "------------------------\n";
serialize(s, printer).str(); serialize(s, printer).str();
std::cerr << "------------------------\n"; std::cerr << "------------------------\n";
@ -325,7 +325,7 @@ int main()
// Test that select can be called with zero columns if it is used with dynamic columns. // Test that select can be called with zero columns if it is used with dynamic columns.
{ {
auto s = dynamic_select(db).dynamic_columns().extra_tables(t); auto s = dynamic_select(db).dynamic_columns().extra_tables(t);
s.add_column(t.alpha); s.selected_columns.add(t.alpha);
serialize(s, printer).str(); serialize(s, printer).str();
} }
@ -387,6 +387,5 @@ int main()
.as(alias::a) .as(alias::a)
; ;
return 0; return 0;
} }

View File

@ -61,9 +61,11 @@ int main()
serialize(update(t).set(t.gamma = false).where(t.beta != "transparent"), printer).str(); serialize(update(t).set(t.gamma = false).where(t.beta != "transparent"), printer).str();
serialize(update(t).set(t.beta = "opaque").where(t.beta != t.beta), printer).str(); serialize(update(t).set(t.beta = "opaque").where(t.beta != t.beta), printer).str();
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); #warning: This should fail since gamma is set already
u.add_where(t.gamma != false); u.assignments.add(t.gamma = false);
serialize(u, printer).str(); u.where.add(t.gamma != false);
printer.reset();
std::cerr << serialize(u, printer).str() << std::endl;
db(u); db(u);