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

Prevent unconditional joins, and naked bool in where() or boolean expressions

- `.from(t1, t2)` produces an unconditional join if you forget to add a condition in the .where()
  sqlpp11 therefore now deprecates unconditional joins.
- more often than not, writing  something like `where(name == "doe")`, you
  meant to write `where(t.name == "doe")`. It is hard to find bugs when
  the former expression compiles because you happen to have a variable
  `name` in the current scope as well.
  sqlpp11 therefore now deprecates `.where(bool)` and disallows
  raw bool values boolean expression like `something and bool`
  wrap bools in sqlpp::value(), if you REALLY want a bool value here
This commit is contained in:
rbock 2016-02-25 07:57:28 +01:00
parent 6e60dc6630
commit 5e96551f83
27 changed files with 617 additions and 132 deletions

View File

@ -31,6 +31,8 @@ namespace sqlpp
{ {
struct bad_statement struct bad_statement
{ {
static constexpr bool value = false;
template <typename... T> template <typename... T>
bad_statement(T&&...) bad_statement(T&&...)
{ {

View File

@ -40,21 +40,21 @@ namespace sqlpp
}; };
template <typename L, typename R> template <typename L, typename R>
struct return_type_and<L, R, binary_operand_check_t<L, is_boolean_t, R, is_boolean_t>> struct return_type_and<L, R, unwrapped_binary_operand_check_t<L, is_boolean_t, R, is_boolean_t>>
{ {
using check = consistent_t; using check = consistent_t;
using type = logical_and_t<wrap_operand_t<L>, wrap_operand_t<R>>; using type = logical_and_t<wrap_operand_t<L>, wrap_operand_t<R>>;
}; };
template <typename L, typename R> template <typename L, typename R>
struct return_type_or<L, R, binary_operand_check_t<L, is_boolean_t, R, is_boolean_t>> struct return_type_or<L, R, unwrapped_binary_operand_check_t<L, is_boolean_t, R, is_boolean_t>>
{ {
using check = consistent_t; using check = consistent_t;
using type = logical_or_t<wrap_operand_t<L>, wrap_operand_t<R>>; using type = logical_or_t<wrap_operand_t<L>, wrap_operand_t<R>>;
}; };
template <typename T, typename Defer> template <typename T, typename Defer>
struct return_type_not<T, Defer, unary_operand_check_t<T, is_boolean_t>> struct return_type_not<T, Defer, unwrapped_unary_operand_check_t<T, is_boolean_t>>
{ {
using check = consistent_t; using check = consistent_t;
using type = logical_not_t<wrap_operand_t<T>>; using type = logical_not_t<wrap_operand_t<T>>;

View File

@ -0,0 +1,120 @@
/*
* Copyright (c) 2013-2015, 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_DYNAMIC_JOIN_H
#define SQLPP_DYNAMIC_JOIN_H
#include <sqlpp11/join_types.h>
#include <sqlpp11/on.h>
#include <sqlpp11/noop.h>
namespace sqlpp
{
template <typename JoinType, typename Rhs, typename On = noop>
struct dynamic_join_t
{
using _traits = make_traits<no_value_t, tag::is_table, tag::is_dynamic_join>;
using _nodes = detail::type_vector<Rhs>;
using _can_be_null = std::false_type;
static_assert(is_table_t<Rhs>::value, "rhs argument for join() has to be a table");
static_assert(not is_join_t<Rhs>::value, "rhs argument for join must not be a join");
static_assert(is_noop<On>::value or is_on_t<On>::value, "invalid on expression in join().on()");
static_assert(required_tables_of<dynamic_join_t>::size::value == 0,
"joined tables must not depend on other tables");
template <typename OnT>
using set_on_t = dynamic_join_t<JoinType, Rhs, OnT>;
template <typename... Expr>
auto on(Expr... expr) -> set_on_t<on_t<void, Expr...>>
{
static_assert(is_noop<On>::value, "cannot call on() twice for a single join()");
static_assert(logic::all_t<is_expression_t<Expr>::value...>::value,
"at least one argument is not an expression in on()");
return {_rhs, {std::tuple<Expr...>{expr...}, {}}};
}
auto unconditionally() -> set_on_t<on_t<void, unconditional_t>>
{
static_assert(is_noop<On>::value, "cannot call on() twice for a single join()");
return {_rhs, {}};
}
Rhs _rhs;
On _on;
};
template <typename Context, typename JoinType, typename Rhs, typename On>
struct serializer_t<Context, dynamic_join_t<JoinType, Rhs, On>>
{
using _serialize_check = serialize_check_of<Context, Rhs, On>;
using T = dynamic_join_t<JoinType, Rhs, On>;
static Context& _(const T& t, Context& context)
{
static_assert(not is_noop<On>::value, "joined tables require on()");
context << " JOIN ";
serialize(t._rhs, context);
serialize(t._on, context);
return context;
}
};
template <typename Table>
dynamic_join_t<inner_join_t, Table> dynamic_join(Table table)
{
return {table, {}};
}
template <typename Table>
dynamic_join_t<inner_join_t, Table> dynamic_inner_join(Table table)
{
return {table, {}};
}
template <typename Table>
dynamic_join_t<outer_join_t, Table> outer_join(Table table)
{
return {table, {}};
}
template <typename Table>
dynamic_join_t<left_outer_join_t, Table> left_outer_join(Table table)
{
return {table, {}};
}
template <typename Table>
dynamic_join_t<right_outer_join_t, Table> right_outer_join(Table table)
{
return {table, {}};
}
}
#endif

View File

@ -35,9 +35,16 @@
#include <sqlpp11/logic.h> #include <sqlpp11/logic.h>
#include <sqlpp11/detail/sum.h> #include <sqlpp11/detail/sum.h>
#include <sqlpp11/policy_update.h> #include <sqlpp11/policy_update.h>
#include <sqlpp11/dynamic_join.h>
namespace sqlpp namespace sqlpp
{ {
#ifdef SQLPP_ALLOW_UNCONDITIONAL_JOIN
constexpr bool allow_unconditional_from = 1;
#else
constexpr bool allow_unconditional_from = 0;
#endif
// FROM DATA // FROM DATA
template <typename Database, typename... Tables> template <typename Database, typename... Tables>
struct from_data_t struct from_data_t
@ -77,35 +84,40 @@ namespace sqlpp
{ {
} }
template <typename Table> template <typename DynamicJoin>
void add(Table table) void add(DynamicJoin dynamicJoin)
{ {
static_assert(_is_dynamic::value, "from::add() 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 from::add()"); static_assert(
is_dynamic_join_t<DynamicJoin>::value or (allow_unconditional_from and is_table_t<DynamicJoin>::value),
"invalid argument in from::add(), or #define ALLOW_UNCONDITIONAL_JOIN "
"for a grace period of using tables here");
using _known_tables = using _known_tables =
detail::make_joined_set_t<provided_tables_of<Tables>...>; // Hint: Joins contain more than one table detail::make_joined_set_t<provided_tables_of<Tables>...>; // Hint: Joins contain more than one table
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/feedback/details/2173198 // workaround for msvc bug https://connect.microsoft.com/VisualStudio/feedback/details/2173198
// using _known_table_names = detail::transform_set_t<name_of, _known_tables>; // using _known_table_names = detail::transform_set_t<name_of, _known_tables>;
using _known_table_names = detail::make_name_of_set_t<_known_tables>; using _known_table_names = detail::make_name_of_set_t<_known_tables>;
static_assert(not detail::is_element_of<typename Table::_alias_t, _known_table_names>::value, using _joined_tables = provided_tables_of<DynamicJoin>;
using _joined_table_names = detail::make_name_of_set_t<_joined_tables>;
static_assert(detail::is_disjunct_from<_joined_table_names, _known_table_names>::value,
"Must not use the same table name twice in from()"); "Must not use the same table name twice in from()");
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Table>; using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, DynamicJoin>;
_serialize_check::_(); _serialize_check::_();
using ok = logic::all_t<_is_dynamic::value, is_table_t<Table>::value, _serialize_check::type::value>; using ok = logic::all_t<_is_dynamic::value, is_table_t<DynamicJoin>::value, _serialize_check::type::value>;
_add_impl(table, ok()); // dispatch to prevent compile messages after the static_assert _add_impl(dynamicJoin, ok()); // dispatch to prevent compile messages after the static_assert
} }
private: private:
template <typename Table> template <typename DynamicJoin>
void _add_impl(Table table, const std::true_type&) void _add_impl(DynamicJoin dynamicJoin, const std::true_type&)
{ {
return _data._dynamic_tables.emplace_back(from_table(table)); return _data._dynamic_tables.emplace_back(from_table(dynamicJoin));
} }
template <typename Table> template <typename DynamicJoin>
void _add_impl(Table table, const std::false_type&); void _add_impl(DynamicJoin dynamicJoin, const std::false_type&);
public: public:
_data_t _data; _data_t _data;
@ -210,12 +222,15 @@ namespace sqlpp
using _consistency_check = consistent_t; using _consistency_check = consistent_t;
template <typename... Tables> template <typename Table, typename... Tables>
auto from(Tables... tables) const -> _new_statement_t<_check<Tables...>, from_t<void, from_table_t<Tables>...>> auto from(Table table, Tables... tables) const
-> _new_statement_t<_check<Table, Tables...>, from_t<void, from_table_t<Table>, from_table_t<Tables>...>>
{ {
static_assert(_check<Tables...>::value, "at least one argument is not a table or join in from()"); static_assert(_check<Table, Tables...>::value, "at least one argument is not a table or join in from()");
static_assert(sizeof...(Tables), "at least one table or join argument required in from()"); static_assert(sizeof...(Tables) == 0 or ::sqlpp::allow_unconditional_from,
return _from_impl<void>(_check<Tables...>{}, tables...); "unconditional join is deprecated, please use explicit joins or #define ALLOW_UNCONDITIONAL_JOIN "
"for a grace period");
return _from_impl<void>(_check<Table, Tables...>{}, table, tables...);
} }
template <typename... Tables> template <typename... Tables>
@ -225,6 +240,10 @@ namespace sqlpp
static_assert(not std::is_same<_database_t, void>::value, static_assert(not std::is_same<_database_t, void>::value,
"dynamic_from must not be called in a static statement"); "dynamic_from must not be called in a static statement");
static_assert(_check<Tables...>::value, "at least one argument is not a table or join in from()"); static_assert(_check<Tables...>::value, "at least one argument is not a table or join in from()");
static_assert(
sizeof...(Tables) == 1 or ::sqlpp::allow_unconditional_from,
"unconditional join is deprecated, please use explicit joins or #define SQLPP_ALLOW_UNCONDITIONAL_JOIN "
"for a grace period");
return _from_impl<_database_t>(_check<Tables...>{}, tables...); return _from_impl<_database_t>(_check<Tables...>{}, tables...);
} }

View File

@ -27,42 +27,12 @@
#ifndef SQLPP_JOIN_H #ifndef SQLPP_JOIN_H
#define SQLPP_JOIN_H #define SQLPP_JOIN_H
#include <sqlpp11/type_traits.h> #include <sqlpp11/join_types.h>
#include <sqlpp11/on.h> #include <sqlpp11/on.h>
#include <sqlpp11/noop.h> #include <sqlpp11/noop.h>
namespace sqlpp namespace sqlpp
{ {
struct inner_join_t
{
template <typename Lhs, typename Rhs>
using _provided_outer_tables =
detail::make_joined_set_t<provided_outer_tables_of<Lhs>, provided_outer_tables_of<Rhs>>;
static constexpr const char* _name = " INNER ";
};
struct outer_join_t
{
template <typename Lhs, typename Rhs>
using _provided_outer_tables = detail::make_joined_set_t<provided_tables_of<Lhs>, provided_tables_of<Rhs>>;
static constexpr const char* _name = " OUTER ";
};
struct left_outer_join_t
{
template <typename Lhs, typename Rhs>
using _provided_outer_tables = detail::make_joined_set_t<provided_tables_of<Lhs>, provided_outer_tables_of<Rhs>>;
static constexpr const char* _name = " LEFT OUTER ";
};
struct right_outer_join_t
{
template <typename Lhs, typename Rhs>
using _provided_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Lhs>, provided_tables_of<Rhs>>;
static constexpr const char* _name = " RIGHT OUTER ";
};
template <typename JoinType, typename Lhs, typename Rhs, typename On = noop> template <typename JoinType, typename Lhs, typename Rhs, typename On = noop>
struct join_t struct join_t
{ {
@ -93,6 +63,11 @@ namespace sqlpp
return {_lhs, _rhs, {std::tuple<Expr...>{expr...}, {}}}; return {_lhs, _rhs, {std::tuple<Expr...>{expr...}, {}}};
} }
auto unconditionally() -> set_on_t<on_t<void, unconditional_t>>
{
return {_lhs, _rhs, {}};
}
template <typename T> template <typename T>
join_t<inner_join_t, join_t, T> join(T t) join_t<inner_join_t, join_t, T> join(T t)
{ {

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2013-2015, 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_JOIN_TYPES_H
#define SQLPP_JOIN_TYPES_H
#include <sqlpp11/type_traits.h>
namespace sqlpp
{
struct inner_join_t
{
template <typename Lhs, typename Rhs>
using _provided_outer_tables =
detail::make_joined_set_t<provided_outer_tables_of<Lhs>, provided_outer_tables_of<Rhs>>;
static constexpr const char* _name = " INNER ";
};
struct outer_join_t
{
template <typename Lhs, typename Rhs>
using _provided_outer_tables = detail::make_joined_set_t<provided_tables_of<Lhs>, provided_tables_of<Rhs>>;
static constexpr const char* _name = " OUTER ";
};
struct left_outer_join_t
{
template <typename Lhs, typename Rhs>
using _provided_outer_tables = detail::make_joined_set_t<provided_tables_of<Lhs>, provided_outer_tables_of<Rhs>>;
static constexpr const char* _name = " LEFT OUTER ";
};
struct right_outer_join_t
{
template <typename Lhs, typename Rhs>
using _provided_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Lhs>, provided_tables_of<Rhs>>;
static constexpr const char* _name = " RIGHT OUTER ";
};
}
#endif

View File

@ -30,6 +30,7 @@
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/interpret_tuple.h> #include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/interpretable_list.h> #include <sqlpp11/interpretable_list.h>
#include <sqlpp11/unconditional.h>
#include <sqlpp11/logic.h> #include <sqlpp11/logic.h>
namespace sqlpp namespace sqlpp
@ -72,6 +73,25 @@ namespace sqlpp
interpretable_list_t<Database> _dynamic_expressions; interpretable_list_t<Database> _dynamic_expressions;
}; };
template <>
struct on_t<void, unconditional_t>
{
using _traits = make_traits<no_value_t, tag::is_on>;
using _nodes = detail::type_vector<>;
};
template <typename Context>
struct serializer_t<Context, on_t<void, unconditional_t>>
{
using _serialize_check = consistent_t;
using T = on_t<void, unconditional_t>;
static Context& _(const T&, Context& context)
{
return context;
}
};
template <typename Context, typename Database, typename... Expressions> template <typename Context, typename Database, typename... Expressions>
struct serializer_t<Context, on_t<Database, Expressions...>> struct serializer_t<Context, on_t<Database, Expressions...>>
{ {
@ -82,11 +102,12 @@ namespace sqlpp
{ {
if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty()) if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty())
return context; return context;
context << " ON "; context << " ON (";
interpret_tuple(t._expressions, " AND ", context); interpret_tuple(t._expressions, " AND ", context);
if (sizeof...(Expressions) and not t._dynamic_expressions.empty()) if (sizeof...(Expressions) and not t._dynamic_expressions.empty())
context << " AND "; context << " AND ";
interpret_list(t._dynamic_expressions, " AND ", context); interpret_list(t._dynamic_expressions, " AND ", context);
context << " )";
return context; return context;
} }
}; };

View File

@ -38,13 +38,16 @@ namespace sqlpp
}; };
template <typename T, template <typename> class Pred> template <typename T, template <typename> class Pred>
struct unary_operand_check<T, Pred, detail::enable_if_t<Pred<wrap_operand_t<T>>::value>> struct unary_operand_check<T, Pred, detail::enable_if_t<Pred<T>::value>>
{ {
using type = void; using type = void;
}; };
template <typename T, template <typename> class Pred> template <typename T, template <typename> class Pred>
using unary_operand_check_t = typename unary_operand_check<T, Pred>::type; using unary_operand_check_t = typename unary_operand_check<wrap_operand_t<T>, Pred>::type;
template <typename T, template <typename> class Pred>
using unwrapped_unary_operand_check_t = typename unary_operand_check<T, Pred>::type;
template <typename L, template <typename L,
template <typename> class LPred, template <typename> class LPred,
@ -56,17 +59,17 @@ namespace sqlpp
}; };
template <typename L, template <typename> class LPred, typename R, template <typename> class RPred> template <typename L, template <typename> class LPred, typename R, template <typename> class RPred>
struct binary_operand_check<L, struct binary_operand_check<L, LPred, R, RPred, detail::enable_if_t<LPred<L>::value and RPred<R>::value>>
LPred,
R,
RPred,
detail::enable_if_t<LPred<wrap_operand_t<L>>::value and RPred<wrap_operand_t<R>>::value>>
{ {
using type = void; using type = void;
}; };
template <typename L, template <typename> class LPred, typename R, template <typename> class RPred> template <typename L, template <typename> class LPred, typename R, template <typename> class RPred>
using binary_operand_check_t = typename binary_operand_check<L, LPred, R, RPred>::type; using binary_operand_check_t =
typename binary_operand_check<wrap_operand_t<L>, LPred, wrap_operand_t<L>, RPred>::type;
template <typename L, template <typename> class LPred, typename R, template <typename> class RPred>
using unwrapped_binary_operand_check_t = typename binary_operand_check<L, LPred, R, RPred>::type;
} }
#endif #endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2015, Roland Bock * Copyright (c) 2013-2016, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -30,6 +30,7 @@
#include <sqlpp11/column_fwd.h> #include <sqlpp11/column_fwd.h>
#include <sqlpp11/interpret.h> #include <sqlpp11/interpret.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/join.h>
#include <sqlpp11/alias.h> #include <sqlpp11/alias.h>
#include <sqlpp11/detail/type_set.h> #include <sqlpp11/detail/type_set.h>
@ -41,7 +42,6 @@ namespace sqlpp
template <typename AliasProvider, typename Table, typename... ColumnSpec> template <typename AliasProvider, typename Table, typename... ColumnSpec>
struct table_alias_t : public ColumnSpec::_alias_t::template _member_t<column_t<AliasProvider, ColumnSpec>>... struct table_alias_t : public ColumnSpec::_alias_t::template _member_t<column_t<AliasProvider, ColumnSpec>>...
{ {
// FIXME: Need to add join functionality
using _traits = make_traits<value_type_of<Table>, using _traits = make_traits<value_type_of<Table>,
tag::is_table, tag::is_table,
tag::is_alias, tag::is_alias,
@ -60,6 +60,36 @@ namespace sqlpp
{ {
} }
template <typename T>
join_t<inner_join_t, table_alias_t, T> join(T t) const
{
return {*this, t, {}};
}
template <typename T>
join_t<inner_join_t, table_alias_t, T> inner_join(T t) const
{
return {*this, t, {}};
}
template <typename T>
join_t<outer_join_t, table_alias_t, T> outer_join(T t) const
{
return {*this, t, {}};
}
template <typename T>
join_t<left_outer_join_t, table_alias_t, T> left_outer_join(T t) const
{
return {*this, t, {}};
}
template <typename T>
join_t<right_outer_join_t, table_alias_t, T> right_outer_join(T t) const
{
return {*this, t, {}};
}
Table _table; Table _table;
}; };

View File

@ -164,6 +164,7 @@ namespace sqlpp
SQLPP_VALUE_TRAIT_GENERATOR(is_table) SQLPP_VALUE_TRAIT_GENERATOR(is_table)
SQLPP_VALUE_TRAIT_GENERATOR(is_raw_table) SQLPP_VALUE_TRAIT_GENERATOR(is_raw_table)
SQLPP_VALUE_TRAIT_GENERATOR(is_join) SQLPP_VALUE_TRAIT_GENERATOR(is_join)
SQLPP_VALUE_TRAIT_GENERATOR(is_dynamic_join)
SQLPP_VALUE_TRAIT_GENERATOR(is_pseudo_table) SQLPP_VALUE_TRAIT_GENERATOR(is_pseudo_table)
SQLPP_VALUE_TRAIT_GENERATOR(is_column) SQLPP_VALUE_TRAIT_GENERATOR(is_column)
SQLPP_VALUE_TRAIT_GENERATOR(is_select) SQLPP_VALUE_TRAIT_GENERATOR(is_select)

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2013-2015, 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_UNCONDITIONAL_H
#define SQLPP_UNCONDITIONAL_H
namespace sqlpp
{
struct unconditional_t
{
};
}
#endif

View File

@ -33,6 +33,7 @@
#include <sqlpp11/expression.h> #include <sqlpp11/expression.h>
#include <sqlpp11/interpret_tuple.h> #include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/interpretable_list.h> #include <sqlpp11/interpretable_list.h>
#include <sqlpp11/unconditional.h>
#include <sqlpp11/logic.h> #include <sqlpp11/logic.h>
namespace sqlpp namespace sqlpp
@ -153,6 +154,7 @@ namespace sqlpp
}; };
}; };
#ifdef SQLPP_ALLOW_NAKED_BOOL_EXPRESSION
template <> template <>
struct where_data_t<void, bool> struct where_data_t<void, bool>
{ {
@ -214,8 +216,70 @@ namespace sqlpp
using _consistency_check = consistent_t; using _consistency_check = consistent_t;
}; };
}; };
#endif
SQLPP_PORTABLE_STATIC_ASSERT(assert_where_t, "where expression required, e.g. where(true)"); template <>
struct where_data_t<void, unconditional_t>
{
};
// WHERE() UNCONDITIONALLY
template <>
struct where_t<void, unconditional_t>
{
using _traits = make_traits<no_value_t, tag::is_where>;
using _nodes = detail::type_vector<>;
// Data
using _data_t = where_data_t<void, unconditional_t>;
// Member implementation with data and methods
template <typename Policies>
struct _impl_t
{
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2173269
_impl_t() = default;
_impl_t(const _data_t& data) : _data(data)
{
}
_data_t _data;
};
// Base template to be inherited by the statement
template <typename Policies>
struct _base_t
{
using _data_t = where_data_t<void, unconditional_t>;
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2173269
template <typename... Args>
_base_t(Args&&... args)
: where{std::forward<Args>(args)...}
{
}
_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;
}
using _consistency_check = consistent_t;
};
};
SQLPP_PORTABLE_STATIC_ASSERT(assert_where_t, "calling where() or uncontionally() required");
SQLPP_PORTABLE_STATIC_ASSERT(assert_where_expressions_t, SQLPP_PORTABLE_STATIC_ASSERT(assert_where_expressions_t,
"at least one argument is not a boolean expression in where()"); "at least one argument is not a boolean expression in where()");
@ -328,10 +392,28 @@ namespace sqlpp
assert_where_t, assert_where_t,
consistent_t>::type; consistent_t>::type;
#ifdef SQLPP_ALLOW_NAKED_BOOL_EXPRESSION
template <typename T = void>
auto where(bool b) const -> _new_statement_t<std::true_type, where_t<void, bool>> auto where(bool b) const -> _new_statement_t<std::true_type, where_t<void, bool>>
{ {
return {static_cast<const derived_statement_t<Policies>&>(*this), where_data_t<void, bool>{b}}; return {static_cast<const derived_statement_t<Policies>&>(*this), where_data_t<void, bool>{b}};
} }
#else
template <typename T = void>
auto where(bool b) const -> bad_statement
{
static_assert(
wrong_t<T>::value,
"where(bool) is deprecated, please use unconditionally() or #define SQLPP_ALLOW_NAKED_BOOL_EXPRESSION "
"for a grace period");
return {static_cast<const derived_statement_t<Policies>&>(*this), where_data_t<void, bool>{b}};
}
#endif
auto unconditionally() const -> _new_statement_t<std::true_type, where_t<void, unconditional_t>>
{
return {static_cast<const derived_statement_t<Policies>&>(*this), where_data_t<void, unconditional_t>{}};
}
template <typename... Expressions> template <typename... Expressions>
auto where(Expressions... expressions) const auto where(Expressions... expressions) const
@ -387,6 +469,7 @@ namespace sqlpp
} }
}; };
#ifdef SQLPP_ALLOW_NAKED_BOOL_EXPRESSION
template <typename Context> template <typename Context>
struct serializer_t<Context, where_data_t<void, bool>> struct serializer_t<Context, where_data_t<void, bool>>
{ {
@ -400,6 +483,19 @@ namespace sqlpp
return context; return context;
} }
}; };
#endif
template <typename Context>
struct serializer_t<Context, where_data_t<void, unconditional_t>>
{
using _serialize_check = consistent_t;
using T = where_data_t<void, unconditional_t>;
static Context& _(const T&, Context& context)
{
return context;
}
};
template <typename... T> template <typename... T>
auto where(T&&... t) -> decltype(statement_t<void, no_where_t<false>>().where(std::forward<T>(t)...)) auto where(T&&... t) -> decltype(statement_t<void, no_where_t<false>>().where(std::forward<T>(t)...))

View File

@ -36,7 +36,7 @@ int main()
static_assert(sqlpp::can_be_null_t<decltype(t.alpha)>::value, "t.alpha can be null"); static_assert(sqlpp::can_be_null_t<decltype(t.alpha)>::value, "t.alpha can be null");
static_assert(not sqlpp::null_is_trivial_value_t<decltype(t.alpha)>::value, "t.alpha does not say null_is_trivial"); static_assert(not sqlpp::null_is_trivial_value_t<decltype(t.alpha)>::value, "t.alpha does not say null_is_trivial");
for (const auto& row : edb(select(all_of(t)).from(t).where(true))) for (const auto& row : edb(select(all_of(t)).from(t).unconditionally()))
{ {
static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null"); static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null");
static_assert(not sqlpp::null_is_trivial_value_t<decltype(row.alpha)>::value, static_assert(not sqlpp::null_is_trivial_value_t<decltype(row.alpha)>::value,

View File

@ -34,4 +34,5 @@ test_compile(where)
test_compile(insert) test_compile(insert)
test_compile(date) test_compile(date)
test_compile(date_time) test_compile(date_time)
test_compile(unwrapped_bool)

View File

@ -75,51 +75,53 @@ namespace
// If there is no group_by, we can select whatever we want // If there is no group_by, we can select whatever we want
void no_group_by() void no_group_by()
{ {
run_check(select(all_of(t)).from(t).where(true)); run_check(select(all_of(t)).from(t).unconditionally());
run_check(select(t.alpha).from(t).where(true)); run_check(select(t.alpha).from(t).unconditionally());
run_check(select(count(t.alpha)).from(t).where(true)); run_check(select(count(t.alpha)).from(t).unconditionally());
} }
// If there is a dynamic group_by, we can still select whatever we want // If there is a dynamic group_by, we can still select whatever we want
// because there is no way of knowing which expressions might have been added dynamically // because there is no way of knowing which expressions might have been added dynamically
void dynamic_group_by() void dynamic_group_by()
{ {
run_check(select(all_of(t)).from(t).where(true)); run_check(select(all_of(t)).from(t).unconditionally());
run_check(select(t.alpha).from(t).where(true)); run_check(select(t.alpha).from(t).unconditionally());
run_check(select(count(t.alpha)).from(t).where(true)); run_check(select(count(t.alpha)).from(t).unconditionally());
} }
// If there is a static group_by, selected columns must be made of group_by expressions, or aggregate expression (e.g. // If there is a static group_by, selected columns must be made of group_by expressions, or aggregate expression (e.g.
// count(t.id)) or values to be valid // count(t.id)) or values to be valid
void static_group_by_ok() void static_group_by_ok()
{ {
run_check(select(t.alpha).from(t).where(true).group_by(t.alpha)); run_check(select(t.alpha).from(t).unconditionally().group_by(t.alpha));
run_check(select((t.alpha + 42).as(whatever)).from(t).where(true).group_by(t.alpha)); run_check(select((t.alpha + 42).as(whatever)).from(t).unconditionally().group_by(t.alpha));
run_check(select((t.alpha + 42).as(whatever)).from(t).where(true).group_by(t.alpha, t.alpha + t.delta * 17)); run_check(select((t.alpha + 42).as(whatever)).from(t).unconditionally().group_by(t.alpha, t.alpha + t.delta * 17));
run_check( run_check(select((t.alpha + t.delta * 17).as(whatever))
select((t.alpha + t.delta * 17).as(whatever)).from(t).where(true).group_by(t.alpha, t.alpha + t.delta * 17)); .from(t)
run_check(select((t.beta + "fortytwo").as(whatever)).from(t).where(true).group_by(t.beta)); .unconditionally()
.group_by(t.alpha, t.alpha + t.delta * 17));
run_check(select((t.beta + "fortytwo").as(whatever)).from(t).unconditionally().group_by(t.beta));
run_check(select(avg(t.alpha)).from(t).where(true).group_by(t.beta)); run_check(select(avg(t.alpha)).from(t).unconditionally().group_by(t.beta));
run_check(select(count(t.alpha)).from(t).where(true).group_by(t.beta)); run_check(select(count(t.alpha)).from(t).unconditionally().group_by(t.beta));
run_check(select(max(t.alpha)).from(t).where(true).group_by(t.beta)); run_check(select(max(t.alpha)).from(t).unconditionally().group_by(t.beta));
run_check(select(min(t.alpha)).from(t).where(true).group_by(t.beta)); run_check(select(min(t.alpha)).from(t).unconditionally().group_by(t.beta));
run_check(select(sum(t.alpha)).from(t).where(true).group_by(t.beta)); run_check(select(sum(t.alpha)).from(t).unconditionally().group_by(t.beta));
run_check(select((t.alpha + count(t.delta)).as(whatever)).from(t).where(true).group_by(t.alpha)); run_check(select((t.alpha + count(t.delta)).as(whatever)).from(t).unconditionally().group_by(t.alpha));
run_check(select(sqlpp::value(1).as(whatever)).from(t).where(true).group_by(t.alpha)); run_check(select(sqlpp::value(1).as(whatever)).from(t).unconditionally().group_by(t.alpha));
run_check(select(sqlpp::value("whatever").as(whatever)).from(t).where(true).group_by(t.alpha)); run_check(select(sqlpp::value("whatever").as(whatever)).from(t).unconditionally().group_by(t.alpha));
} }
// Failures with static group_by and selected non-aggregates or incorrect aggregates // Failures with static group_by and selected non-aggregates or incorrect aggregates
void static_group_by_nok() void static_group_by_nok()
{ {
run_check<sqlpp::assert_aggregates_t>(select(t.beta).from(t).where(true).group_by(t.alpha)); run_check<sqlpp::assert_aggregates_t>(select(t.beta).from(t).unconditionally().group_by(t.alpha));
run_check<sqlpp::assert_aggregates_t>( run_check<sqlpp::assert_aggregates_t>(
select((t.alpha + t.delta).as(whatever)).from(t).where(true).group_by(t.alpha)); select((t.alpha + t.delta).as(whatever)).from(t).unconditionally().group_by(t.alpha));
run_check<sqlpp::assert_aggregates_t>( run_check<sqlpp::assert_aggregates_t>(
select((t.alpha + t.delta).as(whatever)).from(t).where(true).group_by(t.alpha, t.alpha + t.delta * 17)); select((t.alpha + t.delta).as(whatever)).from(t).unconditionally().group_by(t.alpha, t.alpha + t.delta * 17));
} }
} }

View File

@ -0,0 +1,115 @@
/*
* Copyright (c) 2015-2016, 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.
*/
#include <iostream>
#include "MockDb.h"
#include "Sample.h"
#include <sqlpp11/sqlpp11.h>
namespace
{
constexpr auto t = test::TabBar{};
template <typename T>
struct wrap
{
};
template <typename T>
void print_type_on_error(std::true_type)
{
}
template <typename T>
void print_type_on_error(std::false_type)
{
wrap<T>::_print_me_;
}
template <typename Assert, typename Lhs, typename Rhs>
void and_check(const Lhs& lhs, const Rhs& rhs)
{
using ReturnType = decltype(lhs and rhs);
using ExpectedReturnType =
sqlpp::logic::all_t<Assert::value xor std::is_same<ReturnType, sqlpp::bad_expression<sqlpp::boolean>>::value>;
print_type_on_error<ReturnType>(ExpectedReturnType{});
static_assert(ExpectedReturnType::value, "Unexpected return type");
}
template <typename Assert, typename Lhs, typename Rhs>
void or_check(const Lhs& lhs, const Rhs& rhs)
{
using ReturnType = decltype(lhs or rhs);
using ExpectedReturnType =
sqlpp::logic::all_t<Assert::value xor std::is_same<ReturnType, sqlpp::bad_expression<sqlpp::boolean>>::value>;
print_type_on_error<ReturnType>(ExpectedReturnType{});
static_assert(ExpectedReturnType::value, "Unexpected return type");
}
template <typename Assert, typename Lhs>
void not_check(const Lhs& lhs)
{
using ReturnType = decltype(not lhs);
using ExpectedReturnType =
sqlpp::logic::all_t<Assert::value xor std::is_same<ReturnType, sqlpp::bad_expression<sqlpp::boolean>>::value>;
print_type_on_error<ReturnType>(ExpectedReturnType{});
static_assert(ExpectedReturnType::value, "Unexpected return type");
}
template <typename Assert, typename Condition>
void where_check(const Condition& condition)
{
using ReturnType = decltype(sqlpp::where(condition));
using ExpectedReturnType =
sqlpp::logic::all_t<Assert::value xor std::is_same<ReturnType, sqlpp::bad_statement>::value>;
print_type_on_error<ReturnType>(ExpectedReturnType{});
static_assert(ExpectedReturnType::value, "Unexpected return type");
}
void boolean()
{
and_check<sqlpp::consistent_t>(t.gamma, t.gamma);
and_check<sqlpp::assert_valid_operands>(t.gamma, true);
// and_check<sqlpp::assert_valid_operands>(true, t.gamma); // Cannot currently do that
or_check<sqlpp::consistent_t>(t.gamma, t.gamma);
or_check<sqlpp::assert_valid_operands>(t.gamma, true);
// or_check<sqlpp::assert_valid_operands>(true, t.gamma); // Cannot currently do that
not_check<sqlpp::consistent_t>(t.gamma);
}
void where()
{
where_check<sqlpp::consistent_t>(t.gamma);
where_check<sqlpp::bad_statement>(true);
}
}
int main(int, char* [])
{
boolean();
where();
}

View File

@ -31,7 +31,6 @@
namespace namespace
{ {
constexpr auto t = test::TabBar{}; constexpr auto t = test::TabBar{};
constexpr auto f = test::TabFoo{};
template <typename T> template <typename T>
void print_type_on_error(std::true_type) void print_type_on_error(std::true_type)

View File

@ -40,7 +40,7 @@ int DateTime(int, char* [])
{ {
std::cout << row.now; std::cout << row.now;
} }
for (const auto& row : db(select(all_of(t)).from(t).where(true))) for (const auto& row : db(select(all_of(t)).from(t).unconditionally()))
{ {
std::cout << row.colDayPoint; std::cout << row.colDayPoint;
std::cout << row.colTimePoint; std::cout << row.colTimePoint;

View File

@ -197,7 +197,7 @@ int Function(int, char* [])
static_assert(not sqlpp::is_numeric_t<TT>::value, "type requirement"); static_assert(not sqlpp::is_numeric_t<TT>::value, "type requirement");
static_assert(not sqlpp::is_text_t<TT>::value, "type requirement"); static_assert(not sqlpp::is_text_t<TT>::value, "type requirement");
if (false and db(select(exists(select(t.alpha).from(t).where(true)))).front().exists) if (false and db(select(exists(select(t.alpha).from(t).unconditionally()))).front().exists)
{ /* do something */ { /* do something */
} }
} }
@ -286,7 +286,7 @@ int Function(int, char* [])
static_assert(sqlpp::is_integral_t<TT>::value, "type requirement"); static_assert(sqlpp::is_integral_t<TT>::value, "type requirement");
static_assert(not sqlpp::is_floating_point_t<TT>::value, "type requirement"); static_assert(not sqlpp::is_floating_point_t<TT>::value, "type requirement");
if (false and db(select(count(t.alpha)).from(t).where(true)).front().count > 0) if (false and db(select(count(t.alpha)).from(t).unconditionally()).front().count > 0)
{ /* do something */ { /* do something */
} }
} }
@ -444,7 +444,7 @@ int Function(int, char* [])
static_assert(std::is_same<decltype(sqlpp::tvin("test")), sqlpp::tvin_arg_t<sqlpp::text_operand>>::value, static_assert(std::is_same<decltype(sqlpp::tvin("test")), sqlpp::tvin_arg_t<sqlpp::text_operand>>::value,
"text values are accepted and wrapped"); "text values are accepted and wrapped");
for (const auto& row : db(select(all_of(t)).from(t).where(true))) for (const auto& row : db(select(all_of(t)).from(t).unconditionally()))
{ {
static_assert(std::is_same<decltype(sqlpp::tvin(row.alpha)), static_assert(std::is_same<decltype(sqlpp::tvin(row.alpha)),
sqlpp::tvin_arg_t<typename std::remove_const<decltype(row.alpha)>::type>>::value, sqlpp::tvin_arg_t<typename std::remove_const<decltype(row.alpha)>::type>>::value,

View File

@ -178,10 +178,9 @@ int Interpret(int, char* [])
serialize(avg(sqlpp::distinct, t.alpha - 7), printer).str(); serialize(avg(sqlpp::distinct, t.alpha - 7), printer).str();
serialize(sum(sqlpp::distinct, t.alpha + 7), printer).str(); serialize(sum(sqlpp::distinct, t.alpha + 7), printer).str();
serialize(select(all_of(t)).from(t).where(true), printer).str(); serialize(select(all_of(t)).from(t).unconditionally(), printer).str();
serialize(select(all_of(t)).from(t).where(false), printer).str();
for (const auto& row : db(select(all_of(t)).from(t).where(true))) for (const auto& row : db(select(all_of(t)).from(t).unconditionally()))
{ {
serialize(row.alpha, printer); serialize(row.alpha, printer);
serialize(row.beta, printer); serialize(row.beta, printer);
@ -201,8 +200,8 @@ int Interpret(int, char* [])
std::cerr << serialize(x, printer).str() << std::endl; std::cerr << serialize(x, printer).str() << std::endl;
printer.reset(); printer.reset();
std::cerr << serialize(select(all_of(t)).from(t).where(t.alpha.in(select(f.epsilon).from(f).where(true))), printer) std::cerr << serialize(select(all_of(t)).from(t).where(t.alpha.in(select(f.epsilon).from(f).unconditionally())),
.str() << std::endl; printer).str() << std::endl;
printer.reset(); printer.reset();
std::cerr << serialize(select(all_of(t)).from(t).where(t.alpha.in()), printer).str() << std::endl; std::cerr << serialize(select(all_of(t)).from(t).where(t.alpha.in()), printer).str() << std::endl;
@ -214,7 +213,7 @@ int Interpret(int, char* [])
auto s = schema_qualified_table(schema, t).as(sqlpp::alias::x); auto s = schema_qualified_table(schema, t).as(sqlpp::alias::x);
printer.reset(); printer.reset();
std::cerr << serialize(select(all_of(s)).from(s).where(true), printer).str() << std::endl; std::cerr << serialize(select(all_of(s)).from(s).unconditionally(), printer).str() << std::endl;
printer.reset(); printer.reset();
std::cerr << serialize(sqlpp::case_when(true).then(t.alpha).else_(t.alpha + 1).as(t.beta), printer).str() std::cerr << serialize(sqlpp::case_when(true).then(t.alpha).else_(t.alpha + 1).as(t.beta), printer).str()

View File

@ -60,7 +60,7 @@ int Remove(int, char* [])
printer.reset(); printer.reset();
std::cerr << serialize(r, printer).str() << std::endl; std::cerr << serialize(r, printer).str() << std::endl;
printer.reset(); printer.reset();
std::cerr << serialize(remove_from(t).where(true), printer).str() << std::endl; std::cerr << serialize(remove_from(t).unconditionally(), printer).str() << std::endl;
db(r); db(r);

View File

@ -42,7 +42,7 @@ int Result(int, char* [])
static_assert(not sqlpp::null_is_trivial_value_t<decltype(t.alpha)>::value, "t.alpha does not say null_is_trivial"); static_assert(not sqlpp::null_is_trivial_value_t<decltype(t.alpha)>::value, "t.alpha does not say null_is_trivial");
// Using a non-enforcing db // Using a non-enforcing db
for (const auto& row : db(select(all_of(t), t.beta.like("")).from(t).where(true))) for (const auto& row : db(select(all_of(t), t.beta.like("")).from(t).unconditionally()))
{ {
static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null"); static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null");
static_assert(sqlpp::null_is_trivial_value_t<decltype(row.alpha)>::value, "row.alpha interprets null_is_trivial"); static_assert(sqlpp::null_is_trivial_value_t<decltype(row.alpha)>::value, "row.alpha interprets null_is_trivial");
@ -64,14 +64,14 @@ int Result(int, char* [])
} }
sqlpp::select((t.alpha + 1).as(t.alpha)).flags(sqlpp::all).from(t); sqlpp::select((t.alpha + 1).as(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).unconditionally()))
{ {
static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null"); static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null");
static_assert(sqlpp::null_is_trivial_value_t<decltype(row.alpha)>::value, "row.alpha interprets null_is_trivial"); static_assert(sqlpp::null_is_trivial_value_t<decltype(row.alpha)>::value, "row.alpha interprets null_is_trivial");
} }
// Using a non-enforcing db // Using a non-enforcing db
for (const auto& row : edb(select(all_of(t)).from(t).where(true))) for (const auto& row : edb(select(all_of(t)).from(t).unconditionally()))
{ {
static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null"); static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null");
static_assert(not sqlpp::null_is_trivial_value_t<decltype(row.alpha)>::value, static_assert(not sqlpp::null_is_trivial_value_t<decltype(row.alpha)>::value,
@ -79,7 +79,7 @@ int Result(int, char* [])
} }
sqlpp::select((t.alpha + 1).as(t.alpha)).flags(sqlpp::all).from(t); sqlpp::select((t.alpha + 1).as(t.alpha)).flags(sqlpp::all).from(t);
for (const auto& row : edb(select(all_of(t)).from(t).where(true))) for (const auto& row : edb(select(all_of(t)).from(t).unconditionally()))
{ {
static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null"); static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null");
static_assert(not sqlpp::null_is_trivial_value_t<decltype(row.alpha)>::value, static_assert(not sqlpp::null_is_trivial_value_t<decltype(row.alpha)>::value,

View File

@ -35,7 +35,7 @@
template <typename Db, typename Column> template <typename Db, typename Column>
int64_t getColumn(Db&& db, const Column& column) int64_t getColumn(Db&& db, const Column& column)
{ {
auto result = db(select(column.as(sqlpp::alias::a)).from(column.table()).where(true)); auto result = db(select(column.as(sqlpp::alias::a)).from(column.table()).unconditionally());
if (not result.empty()) if (not result.empty())
return result.front().a; return result.front().a;
else else
@ -59,14 +59,14 @@ int Select(int, char* [])
std::cout << row.a << std::endl; std::cout << row.a << std::endl;
} }
for (const auto& row : db(select(all_of(t)).from(t).where(true))) for (const auto& row : db(select(all_of(t)).from(t).unconditionally()))
{ {
int64_t a = row.alpha; int64_t a = row.alpha;
const std::string b = row.beta; const std::string b = row.beta;
std::cout << a << ", " << b << std::endl; std::cout << a << ", " << b << std::endl;
} }
for (const auto& row : db(select(all_of(t).as(t)).from(t).where(true))) for (const auto& row : db(select(all_of(t).as(t)).from(t).unconditionally()))
{ {
int64_t a = row.tabBar.alpha; int64_t a = row.tabBar.alpha;
const std::string b = row.tabBar.beta; const std::string b = row.tabBar.beta;
@ -82,19 +82,19 @@ int Select(int, char* [])
} }
for (const auto& row : for (const auto& row :
db(select(all_of(t), all_of(f)).from(t.join(f).on(t.alpha > f.omega and not t.gamma)).where(true))) db(select(all_of(t), all_of(f)).from(t.join(f).on(t.alpha > f.omega and not t.gamma)).unconditionally()))
{ {
std::cout << row.alpha << std::endl; std::cout << row.alpha << std::endl;
} }
for (const auto& row : db(select(all_of(t), all_of(f)) for (const auto& row : db(select(all_of(t), all_of(f))
.from(t.join(f).on(t.alpha > f.omega).join(tab_a).on(t.alpha == tab_a.omega)) .from(t.join(f).on(t.alpha > f.omega).join(tab_a).on(t.alpha == tab_a.omega))
.where(true))) .unconditionally()))
{ {
std::cout << row.alpha << std::endl; std::cout << row.alpha << std::endl;
} }
for (const auto& row : db(select(count(t.alpha), avg(t.alpha)).from(t).where(true))) for (const auto& row : db(select(count(t.alpha), avg(t.alpha)).from(t).unconditionally()))
{ {
std::cout << row.count << std::endl; std::cout << row.count << std::endl;
} }
@ -146,7 +146,7 @@ int Select(int, char* [])
.dynamic_offset(); .dynamic_offset();
s.select_flags.add(sqlpp::distinct); s.select_flags.add(sqlpp::distinct);
s.selected_columns.add(f.omega); s.selected_columns.add(f.omega);
s.from.add(f); s.from.add(dynamic_join(f).unconditionally());
s.where.add(t.alpha > 7); s.where.add(t.alpha > 7);
s.having.add(t.alpha > 7); s.having.add(t.alpha > 7);
s.limit.set(3); s.limit.set(3);
@ -165,7 +165,7 @@ int Select(int, char* [])
select(sqlpp::value(7).as(t.alpha)); select(sqlpp::value(7).as(t.alpha));
for (const auto& row : for (const auto& row :
db(select(sqlpp::case_when(true).then(sqlpp::null).else_(sqlpp::null).as(t.beta)).from(t).where(true))) db(select(sqlpp::case_when(true).then(sqlpp::null).else_(sqlpp::null).as(t.beta)).from(t).unconditionally()))
{ {
std::cerr << row.beta << std::endl; std::cerr << row.beta << std::endl;
} }

View File

@ -298,7 +298,7 @@ int SelectType(int, char* [])
t.alpha.as(alias::a) // index 12 t.alpha.as(alias::a) // index 12
) )
.from(t) .from(t)
.where(true)); // next index is 13 .unconditionally()); // next index is 13
using ResultRow = typename Select::_result_methods_t<Select>::template _result_row_t<MockDb>; using ResultRow = typename Select::_result_methods_t<Select>::template _result_row_t<MockDb>;
using IndexSequence = ResultRow::_field_index_sequence; using IndexSequence = ResultRow::_field_index_sequence;
static_assert(std::is_same<IndexSequence, sqlpp::detail::field_index_sequence<13, 0, 1, 2, 3, 4, 8, 12>>::value, static_assert(std::is_same<IndexSequence, sqlpp::detail::field_index_sequence<13, 0, 1, 2, 3, 4, 8, 12>>::value,
@ -318,15 +318,16 @@ int SelectType(int, char* [])
"select with identical columns(name/value_type) need to have identical result_types"); "select with identical columns(name/value_type) need to have identical result_types");
} }
for (const auto& row : db(select(all_of(t)).from(t).where(true))) for (const auto& row : db(select(all_of(t)).from(t).unconditionally()))
{ {
int64_t a = row.alpha; int64_t a = row.alpha;
std::cout << a << std::endl; std::cout << a << std::endl;
} }
{ {
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(t).dynamic_where().dynamic_limit().dynamic_offset();
s.from.add(t); #warning : Need to test the deprecated stuff
s.from.add(dynamic_join(f).on(f.omega > t.alpha));
s.where.add_ntc(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.limit.set(30); s.limit.set(30);
s.limit.set(3); s.limit.set(3);
@ -376,7 +377,7 @@ int SelectType(int, char* [])
auto s1 = sqlpp::select() auto s1 = sqlpp::select()
.flags(sqlpp::distinct, sqlpp::straight_join) .flags(sqlpp::distinct, sqlpp::straight_join)
.columns(l.gamma, r.a) .columns(l.gamma, r.a)
.from(r, t, l) .from(r.join(t).unconditionally().join(l).unconditionally())
.where(t.beta == "hello world" and select(t.gamma).from(t)) // .as(alias::right)) .where(t.beta == "hello world" and select(t.gamma).from(t)) // .as(alias::right))
.group_by(l.gamma, r.a) .group_by(l.gamma, r.a)
.having(r.a != true) .having(r.a != true)

View File

@ -37,23 +37,23 @@ int Union(int, char* [])
const auto t = test::TabBar{}; const auto t = test::TabBar{};
const auto f = test::TabFoo{}; const auto f = test::TabFoo{};
db(select(t.alpha).from(t).where(true).union_distinct(select(f.epsilon.as(t.alpha)).from(f).where(true))); db(select(t.alpha).from(t).unconditionally().union_distinct(select(f.epsilon.as(t.alpha)).from(f).unconditionally()));
db(select(t.alpha).from(t).where(true).union_all(select(f.epsilon.as(t.alpha)).from(f).where(true))); db(select(t.alpha).from(t).unconditionally().union_all(select(f.epsilon.as(t.alpha)).from(f).unconditionally()));
auto u = select(t.alpha) auto u = select(t.alpha)
.from(t) .from(t)
.where(true) .unconditionally()
.union_all(select(f.epsilon.as(t.alpha)).from(f).where(true)) .union_all(select(f.epsilon.as(t.alpha)).from(f).unconditionally())
.as(sqlpp::alias::u); .as(sqlpp::alias::u);
db(select(all_of(u)).from(u).where(true).union_all(select(t.delta.as(t.alpha)).from(t).where(true))); db(select(all_of(u)).from(u).unconditionally().union_all(select(t.delta.as(t.alpha)).from(t).unconditionally()));
db(select(u.alpha).from(u).where(true).union_all(select(t.delta.as(t.alpha)).from(t).where(true))); db(select(u.alpha).from(u).unconditionally().union_all(select(t.delta.as(t.alpha)).from(t).unconditionally()));
db(select(t.alpha) db(select(t.alpha)
.from(t) .from(t)
.where(true) .unconditionally()
.union_all(select(t.alpha).from(t).where(true)) .union_all(select(t.alpha).from(t).unconditionally())
.union_all(select(t.alpha).from(t).where(true))); .union_all(select(t.alpha).from(t).unconditionally()));
return 0; return 0;
} }

View File

@ -63,11 +63,11 @@ int Update(int, char* [])
db(u); db(u);
db(update(t).set(t.delta = sqlpp::verbatim<sqlpp::integer>("17+4")).where(true)); db(update(t).set(t.delta = sqlpp::verbatim<sqlpp::integer>("17+4")).unconditionally());
db(update(t).set(t.delta = sqlpp::null).where(true)); db(update(t).set(t.delta = sqlpp::null).unconditionally());
db(update(t).set(t.delta = sqlpp::default_value).where(true)); db(update(t).set(t.delta = sqlpp::default_value).unconditionally());
db(update(t).set(t.delta += t.alpha * 2, t.beta += " and cake").where(true)); db(update(t).set(t.delta += t.alpha * 2, t.beta += " and cake").unconditionally());
return 0; return 0;
} }

View File

@ -38,16 +38,16 @@ int With(int, char* [])
auto x = sqlpp::cte(sqlpp::alias::x).as(select(all_of(t)).from(t)); auto x = sqlpp::cte(sqlpp::alias::x).as(select(all_of(t)).from(t));
db(with(x)(select(x.alpha).from(x).where(true))); db(with(x)(select(x.alpha).from(x).unconditionally()));
auto y0 = sqlpp::cte(sqlpp::alias::y).as(select(all_of(t)).from(t)); auto y0 = sqlpp::cte(sqlpp::alias::y).as(select(all_of(t)).from(t));
auto y = y0.union_all(select(all_of(y0)).from(y0).where(false)); auto y = y0.union_all(select(all_of(y0)).from(y0).unconditionally());
std::cout << serialize(y, printer).str() << std::endl; std::cout << serialize(y, printer).str() << std::endl;
printer.reset(); printer.reset();
std::cout << serialize(from_table(y), printer).str() << std::endl; std::cout << serialize(from_table(y), printer).str() << std::endl;
db(with(y)(select(y.alpha).from(y).where(true))); db(with(y)(select(y.alpha).from(y).unconditionally()));
return 0; return 0;
} }