mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-16 04:47:18 +08:00
Added "real" cross join
This commit is contained in:
parent
20b74206ae
commit
d15cb2a410
@ -27,36 +27,36 @@
|
|||||||
#ifndef SQLPP_DYNAMIC_JOIN_H
|
#ifndef SQLPP_DYNAMIC_JOIN_H
|
||||||
#define SQLPP_DYNAMIC_JOIN_H
|
#define SQLPP_DYNAMIC_JOIN_H
|
||||||
|
|
||||||
#include <sqlpp11/dynamic_cross_join.h>
|
#include <sqlpp11/dynamic_pre_join.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template <typename CrossJoin, typename On>
|
template <typename PreJoin, typename On>
|
||||||
struct dynamic_join_t
|
struct dynamic_join_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_table, tag::is_dynamic_join>;
|
using _traits = make_traits<no_value_t, tag::is_table, tag::is_dynamic_join>;
|
||||||
using _nodes = detail::type_vector<CrossJoin, On>;
|
using _nodes = detail::type_vector<PreJoin, On>;
|
||||||
using _can_be_null = std::false_type;
|
using _can_be_null = std::false_type;
|
||||||
using _provided_tables = provided_tables_of<CrossJoin>;
|
using _provided_tables = provided_tables_of<PreJoin>;
|
||||||
using _required_tables = detail::type_set<>;
|
using _required_tables = detail::type_set<>;
|
||||||
|
|
||||||
static_assert(is_dynamic_cross_join_t<CrossJoin>::value, "lhs argument for on() has to be a cross join");
|
static_assert(is_dynamic_pre_join_t<PreJoin>::value, "lhs argument for on() has to be a pre join");
|
||||||
static_assert(required_tables_of<CrossJoin>::size::value == 0, "joined tables must not depend on other tables");
|
static_assert(required_tables_of<PreJoin>::size::value == 0, "joined tables must not depend on other tables");
|
||||||
static_assert(is_on_t<On>::value, "invalid on expression in join().on()");
|
static_assert(is_on_t<On>::value, "invalid on expression in join().on()");
|
||||||
|
|
||||||
CrossJoin _cross_join;
|
PreJoin _pre_join;
|
||||||
On _on;
|
On _on;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Context, typename CrossJoin, typename On>
|
template <typename Context, typename PreJoin, typename On>
|
||||||
struct serializer_t<Context, dynamic_join_t<CrossJoin, On>>
|
struct serializer_t<Context, dynamic_join_t<PreJoin, On>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, CrossJoin, On>;
|
using _serialize_check = serialize_check_of<Context, PreJoin, On>;
|
||||||
using T = dynamic_join_t<CrossJoin, On>;
|
using T = dynamic_join_t<PreJoin, On>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
serialize(t._cross_join, context);
|
serialize(t._pre_join, context);
|
||||||
serialize(t._on, context);
|
serialize(t._on, context);
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
@ -24,93 +24,88 @@
|
|||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SQLPP_DYNAMIC_CROSS_JOIN_H
|
#ifndef SQLPP_DYNAMIC_PRE_JOIN_H
|
||||||
#define SQLPP_DYNAMIC_CROSS_JOIN_H
|
#define SQLPP_DYNAMIC_PRE_JOIN_H
|
||||||
|
|
||||||
#include <sqlpp11/join_types.h>
|
#include <sqlpp11/join_types.h>
|
||||||
#include <sqlpp11/on.h>
|
#include <sqlpp11/on.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_dynamic_cross_join_table_t, "argument of dynamic_join() has to be a table");
|
SQLPP_PORTABLE_STATIC_ASSERT(assert_dynamic_pre_join_table_t, "argument of dynamic_join() has to be a table");
|
||||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_dynamic_cross_join_no_join_t, "argument of dynamic_join() must not be a table");
|
SQLPP_PORTABLE_STATIC_ASSERT(assert_dynamic_pre_join_no_join_t, "argument of dynamic_join() must not be a table");
|
||||||
|
|
||||||
template <typename Table>
|
template <typename Table>
|
||||||
struct check_dynamic_cross_join
|
struct check_dynamic_pre_join
|
||||||
{
|
{
|
||||||
using type =
|
using type =
|
||||||
static_combined_check_t<static_check_t<is_table_t<Table>::value, assert_dynamic_cross_join_table_t>,
|
static_combined_check_t<static_check_t<is_table_t<Table>::value, assert_dynamic_pre_join_table_t>,
|
||||||
static_check_t<not is_join_t<Table>::value, assert_dynamic_cross_join_no_join_t>>;
|
static_check_t<not is_join_t<Table>::value, assert_dynamic_pre_join_no_join_t>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Table>
|
template <typename Table>
|
||||||
using check_dynamic_cross_join_t = typename check_dynamic_cross_join<Table>::type;
|
using check_dynamic_pre_join_t = typename check_dynamic_pre_join<Table>::type;
|
||||||
|
|
||||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_dynamic_join_consist_of_cross_join_and_on_t,
|
SQLPP_PORTABLE_STATIC_ASSERT(assert_dynamic_join_consist_of_pre_join_and_on_t,
|
||||||
"dynamic join has to consist of a dynamic cross_join and a join condition");
|
"dynamic join has to consist of a dynamic pre_join and a join condition");
|
||||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_dynamic_join_no_table_dependencies_t,
|
SQLPP_PORTABLE_STATIC_ASSERT(assert_dynamic_join_no_table_dependencies_t,
|
||||||
"dynamically joined tables must not depend on other tables");
|
"dynamically joined tables must not depend on other tables");
|
||||||
|
|
||||||
template <typename CrossJoin, typename On>
|
template <typename PreJoin, typename On>
|
||||||
struct check_dynamic_join
|
struct check_dynamic_join
|
||||||
{
|
{
|
||||||
using type = static_combined_check_t<
|
using type = static_combined_check_t<
|
||||||
static_check_t<is_dynamic_cross_join_t<CrossJoin>::value, assert_dynamic_join_consist_of_cross_join_and_on_t>,
|
static_check_t<is_dynamic_pre_join_t<PreJoin>::value, assert_dynamic_join_consist_of_pre_join_and_on_t>,
|
||||||
static_check_t<is_on_t<On>::value, assert_dynamic_join_consist_of_cross_join_and_on_t>,
|
static_check_t<is_on_t<On>::value, assert_dynamic_join_consist_of_pre_join_and_on_t>,
|
||||||
static_check_t<required_tables_of<CrossJoin>::size::value == 0, assert_dynamic_join_no_table_dependencies_t>>;
|
static_check_t<required_tables_of<PreJoin>::size::value == 0, assert_dynamic_join_no_table_dependencies_t>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename CrossJoin, typename On>
|
template <typename PreJoin, typename On>
|
||||||
using check_dynamic_join_t = typename check_dynamic_join<CrossJoin, On>::type;
|
using check_dynamic_join_t = typename check_dynamic_join<PreJoin, On>::type;
|
||||||
|
|
||||||
template <typename CrossJoin, typename Expr>
|
template <typename PreJoin, typename Expr>
|
||||||
struct check_dynamic_join_on
|
struct check_dynamic_join_on
|
||||||
{
|
{
|
||||||
using type = static_combined_check_t<check_on_t<Expr>, check_dynamic_join_t<CrossJoin, on_t<Expr>>>;
|
using type = static_combined_check_t<check_on_t<Expr>, check_dynamic_join_t<PreJoin, on_t<Expr>>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename CrossJoin, typename Expr>
|
template <typename PreJoin, typename Expr>
|
||||||
using check_dynamic_join_on_t = typename check_dynamic_join_on<CrossJoin, Expr>::type;
|
using check_dynamic_join_on_t = typename check_dynamic_join_on<PreJoin, Expr>::type;
|
||||||
|
|
||||||
template <typename CrossJoin, typename On>
|
template <typename PreJoin, typename On>
|
||||||
struct dynamic_join_t;
|
struct dynamic_join_t;
|
||||||
|
|
||||||
template <typename JoinType, typename Rhs>
|
template <typename JoinType, typename Rhs>
|
||||||
struct dynamic_cross_join_t
|
struct dynamic_pre_join_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_table, tag::is_dynamic_cross_join>;
|
using _traits = make_traits<no_value_t, tag::is_table, tag::is_dynamic_pre_join>;
|
||||||
using _nodes = detail::type_vector<Rhs>;
|
using _nodes = detail::type_vector<Rhs>;
|
||||||
using _can_be_null = std::false_type;
|
using _can_be_null = std::false_type;
|
||||||
|
|
||||||
static_assert(is_table_t<Rhs>::value, "rhs argument for dynamic_join() has to be a table");
|
static_assert(is_table_t<Rhs>::value, "rhs argument for dynamic_join() has to be a table");
|
||||||
static_assert(not is_join_t<Rhs>::value, "rhs argument for dynamic_join must not be a join");
|
static_assert(not is_join_t<Rhs>::value, "rhs argument for dynamic_join must not be a join");
|
||||||
|
|
||||||
static_assert(required_tables_of<dynamic_cross_join_t>::size::value == 0,
|
static_assert(required_tables_of<dynamic_pre_join_t>::size::value == 0,
|
||||||
"joined tables must not depend on other tables");
|
"joined tables must not depend on other tables");
|
||||||
|
|
||||||
template <typename Expr>
|
template <typename Expr>
|
||||||
auto on(Expr expr) const -> typename std::conditional<check_dynamic_join_on_t<dynamic_cross_join_t, Expr>::value,
|
auto on(Expr expr) const -> typename std::conditional<check_dynamic_join_on_t<dynamic_pre_join_t, Expr>::value,
|
||||||
dynamic_join_t<dynamic_cross_join_t, on_t<Expr>>,
|
dynamic_join_t<dynamic_pre_join_t, on_t<Expr>>,
|
||||||
bad_statement>::type
|
bad_statement>::type
|
||||||
{
|
{
|
||||||
check_dynamic_join_on_t<dynamic_cross_join_t, Expr>::_();
|
check_dynamic_join_on_t<dynamic_pre_join_t, Expr>::_();
|
||||||
|
|
||||||
return {*this, {expr}};
|
return {*this, {expr}};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto unconditionally() -> dynamic_join_t<dynamic_cross_join_t, on_t<unconditional_t>>
|
|
||||||
{
|
|
||||||
return {*this, {}};
|
|
||||||
}
|
|
||||||
|
|
||||||
Rhs _rhs;
|
Rhs _rhs;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Context, typename JoinType, typename Rhs>
|
template <typename Context, typename JoinType, typename Rhs>
|
||||||
struct serializer_t<Context, dynamic_cross_join_t<JoinType, Rhs>>
|
struct serializer_t<Context, dynamic_pre_join_t<JoinType, Rhs>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Rhs>;
|
using _serialize_check = serialize_check_of<Context, Rhs>;
|
||||||
using T = dynamic_cross_join_t<JoinType, Rhs>;
|
using T = dynamic_pre_join_t<JoinType, Rhs>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
@ -121,44 +116,54 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename JoinType, typename Table>
|
template <typename JoinType, typename Table>
|
||||||
using make_dynamic_cross_join_t = typename std::conditional<check_dynamic_cross_join_t<Table>::value,
|
using make_dynamic_pre_join_t = typename std::conditional<check_dynamic_pre_join_t<Table>::value,
|
||||||
dynamic_cross_join_t<JoinType, Table>,
|
dynamic_pre_join_t<JoinType, Table>,
|
||||||
bad_statement>::type;
|
bad_statement>::type;
|
||||||
|
|
||||||
template <typename Table>
|
template <typename Table>
|
||||||
auto dynamic_join(Table table) -> make_dynamic_cross_join_t<inner_join_t, Table>
|
auto dynamic_join(Table table) -> make_dynamic_pre_join_t<inner_join_t, Table>
|
||||||
{
|
{
|
||||||
check_dynamic_cross_join_t<Table>::_();
|
check_dynamic_pre_join_t<Table>::_();
|
||||||
return {table};
|
return {table};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Table>
|
template <typename Table>
|
||||||
auto dynamic_inner_join(Table table) -> make_dynamic_cross_join_t<inner_join_t, Table>
|
auto dynamic_inner_join(Table table) -> make_dynamic_pre_join_t<inner_join_t, Table>
|
||||||
{
|
{
|
||||||
check_dynamic_cross_join_t<Table>::_();
|
check_dynamic_pre_join_t<Table>::_();
|
||||||
return {table};
|
return {table};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Table>
|
template <typename Table>
|
||||||
auto dynamic_left_outer_join(Table table) -> make_dynamic_cross_join_t<left_outer_join_t, Table>
|
auto dynamic_left_outer_join(Table table) -> make_dynamic_pre_join_t<left_outer_join_t, Table>
|
||||||
{
|
{
|
||||||
check_dynamic_cross_join_t<Table>::_();
|
check_dynamic_pre_join_t<Table>::_();
|
||||||
return {table};
|
return {table};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Table>
|
template <typename Table>
|
||||||
auto dynamic_right_outer_join(Table table) -> make_dynamic_cross_join_t<right_outer_join_t, Table>
|
auto dynamic_right_outer_join(Table table) -> make_dynamic_pre_join_t<right_outer_join_t, Table>
|
||||||
{
|
{
|
||||||
check_dynamic_cross_join_t<Table>::_();
|
check_dynamic_pre_join_t<Table>::_();
|
||||||
return {table};
|
return {table};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Table>
|
template <typename Table>
|
||||||
auto dynamic_outer_join(Table table) -> make_dynamic_cross_join_t<outer_join_t, Table>
|
auto dynamic_outer_join(Table table) -> make_dynamic_pre_join_t<outer_join_t, Table>
|
||||||
{
|
{
|
||||||
check_dynamic_cross_join_t<Table>::_();
|
check_dynamic_pre_join_t<Table>::_();
|
||||||
return {table};
|
return {table};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Table>
|
||||||
|
auto dynamic_cross_join(Table table) ->
|
||||||
|
typename std::conditional<check_dynamic_pre_join_t<Table>::value,
|
||||||
|
dynamic_join_t<dynamic_pre_join_t<cross_join_t, Table>, on_t<unconditional_t>>,
|
||||||
|
bad_statement>::type
|
||||||
|
{
|
||||||
|
check_dynamic_pre_join_t<Table>::_();
|
||||||
|
return {dynamic_pre_join_t<cross_join_t, Table>{table}, {}};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -148,8 +148,8 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
SQLPP_PORTABLE_STATIC_ASSERT(
|
SQLPP_PORTABLE_STATIC_ASSERT(
|
||||||
assert_from_not_cross_join_t,
|
assert_from_not_pre_join_t,
|
||||||
"from() argument is a cross join, please use an explicit on() condition or unconditionally()");
|
"from() argument is a pre join, please use an explicit on() condition or unconditionally()");
|
||||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_from_table_t, "from() argument has to be a table or join expression");
|
SQLPP_PORTABLE_STATIC_ASSERT(assert_from_table_t, "from() argument has to be a table or join expression");
|
||||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_from_dependency_free_t, "at least one table depends on another table in from()");
|
SQLPP_PORTABLE_STATIC_ASSERT(assert_from_dependency_free_t, "at least one table depends on another table in from()");
|
||||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_from_no_duplicates_t, "at least one duplicate table name detected in from()");
|
SQLPP_PORTABLE_STATIC_ASSERT(assert_from_no_duplicates_t, "at least one duplicate table name detected in from()");
|
||||||
@ -161,7 +161,7 @@ namespace sqlpp
|
|||||||
struct check_from
|
struct check_from
|
||||||
{
|
{
|
||||||
using type = static_combined_check_t<
|
using type = static_combined_check_t<
|
||||||
static_check_t<not is_cross_join_t<Table>::value, assert_from_not_cross_join_t>,
|
static_check_t<not is_pre_join_t<Table>::value, assert_from_not_pre_join_t>,
|
||||||
static_check_t<is_table_t<Table>::value, assert_from_table_t>,
|
static_check_t<is_table_t<Table>::value, assert_from_table_t>,
|
||||||
static_check_t<required_tables_of<Table>::size::value == 0, assert_from_dependency_free_t>,
|
static_check_t<required_tables_of<Table>::size::value == 0, assert_from_dependency_free_t>,
|
||||||
static_check_t<provided_tables_of<Table>::size::value ==
|
static_check_t<provided_tables_of<Table>::size::value ==
|
||||||
|
@ -28,18 +28,18 @@
|
|||||||
#define SQLPP_JOIN_H
|
#define SQLPP_JOIN_H
|
||||||
|
|
||||||
#include <sqlpp11/join_types.h>
|
#include <sqlpp11/join_types.h>
|
||||||
#include <sqlpp11/cross_join.h>
|
#include <sqlpp11/pre_join.h>
|
||||||
#include <sqlpp11/on.h>
|
#include <sqlpp11/on.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template <typename CrossJoin, typename On>
|
template <typename PreJoin, typename On>
|
||||||
struct join_t
|
struct join_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_table, tag::is_join>;
|
using _traits = make_traits<no_value_t, tag::is_table, tag::is_join>;
|
||||||
using _nodes = detail::type_vector<CrossJoin, On>;
|
using _nodes = detail::type_vector<PreJoin, On>;
|
||||||
using _can_be_null = std::false_type;
|
using _can_be_null = std::false_type;
|
||||||
using _provided_tables = provided_tables_of<CrossJoin>;
|
using _provided_tables = provided_tables_of<PreJoin>;
|
||||||
using _required_tables = detail::make_difference_set_t<required_tables_of<On>, _provided_tables>;
|
using _required_tables = detail::make_difference_set_t<required_tables_of<On>, _provided_tables>;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -72,19 +72,25 @@ namespace sqlpp
|
|||||||
return ::sqlpp::outer_join(*this, t);
|
return ::sqlpp::outer_join(*this, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
CrossJoin _cross_join;
|
template <typename T>
|
||||||
|
auto cross_join(T t) const -> decltype(::sqlpp::cross_join(*this, t))
|
||||||
|
{
|
||||||
|
return ::sqlpp::cross_join(*this, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
PreJoin _pre_join;
|
||||||
On _on;
|
On _on;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Context, typename CrossJoin, typename On>
|
template <typename Context, typename PreJoin, typename On>
|
||||||
struct serializer_t<Context, join_t<CrossJoin, On>>
|
struct serializer_t<Context, join_t<PreJoin, On>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, CrossJoin, On>;
|
using _serialize_check = serialize_check_of<Context, PreJoin, On>;
|
||||||
using T = join_t<CrossJoin, On>;
|
using T = join_t<PreJoin, On>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
serialize(t._cross_join, context);
|
serialize(t._pre_join, context);
|
||||||
serialize(t._on, context);
|
serialize(t._on, context);
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,14 @@ namespace sqlpp
|
|||||||
|
|
||||||
static constexpr const char* _name = " RIGHT OUTER ";
|
static constexpr const char* _name = " RIGHT OUTER ";
|
||||||
};
|
};
|
||||||
|
struct cross_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 = " CROSS ";
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,8 +24,8 @@
|
|||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SQLPP_CROSS_JOIN_H
|
#ifndef SQLPP_PRE_JOIN_H
|
||||||
#define SQLPP_CROSS_JOIN_H
|
#define SQLPP_PRE_JOIN_H
|
||||||
|
|
||||||
#include <sqlpp11/join_types.h>
|
#include <sqlpp11/join_types.h>
|
||||||
#include <sqlpp11/on.h>
|
#include <sqlpp11/on.h>
|
||||||
@ -33,62 +33,62 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_cross_join_lhs_table_t, "lhs argument of join() has to be a table or a join");
|
SQLPP_PORTABLE_STATIC_ASSERT(assert_pre_join_lhs_table_t, "lhs argument of join() has to be a table or a join");
|
||||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_cross_join_rhs_table_t, "rhs argument of join() has to be a table");
|
SQLPP_PORTABLE_STATIC_ASSERT(assert_pre_join_rhs_table_t, "rhs argument of join() has to be a table");
|
||||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_cross_join_rhs_no_join_t, "rhs argument of join() must not be a join");
|
SQLPP_PORTABLE_STATIC_ASSERT(assert_pre_join_rhs_no_join_t, "rhs argument of join() must not be a join");
|
||||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_cross_join_unique_names_t, "joined table names have to be unique");
|
SQLPP_PORTABLE_STATIC_ASSERT(assert_pre_join_unique_names_t, "joined table names have to be unique");
|
||||||
|
|
||||||
template <typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
struct check_cross_join
|
struct check_pre_join
|
||||||
{
|
{
|
||||||
using type = static_combined_check_t<
|
using type = static_combined_check_t<
|
||||||
static_check_t<is_table_t<Lhs>::value, assert_cross_join_lhs_table_t>,
|
static_check_t<is_table_t<Lhs>::value, assert_pre_join_lhs_table_t>,
|
||||||
static_check_t<is_table_t<Rhs>::value, assert_cross_join_rhs_table_t>,
|
static_check_t<is_table_t<Rhs>::value, assert_pre_join_rhs_table_t>,
|
||||||
static_check_t<not is_join_t<Rhs>::value, assert_cross_join_rhs_no_join_t>,
|
static_check_t<not is_join_t<Rhs>::value, assert_pre_join_rhs_no_join_t>,
|
||||||
static_check_t<detail::is_disjunct_from<detail::make_name_of_set_t<provided_tables_of<Lhs>>,
|
static_check_t<detail::is_disjunct_from<detail::make_name_of_set_t<provided_tables_of<Lhs>>,
|
||||||
detail::make_name_of_set_t<provided_tables_of<Rhs>>>::value,
|
detail::make_name_of_set_t<provided_tables_of<Rhs>>>::value,
|
||||||
assert_cross_join_unique_names_t>>;
|
assert_pre_join_unique_names_t>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
using check_cross_join_t = typename check_cross_join<Lhs, Rhs>::type;
|
using check_pre_join_t = typename check_pre_join<Lhs, Rhs>::type;
|
||||||
|
|
||||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_join_consist_of_cross_join_and_on_t,
|
SQLPP_PORTABLE_STATIC_ASSERT(assert_join_consist_of_pre_join_and_on_t,
|
||||||
"join has to consist of a cross_join and a join condition");
|
"join has to consist of a pre_join and a join condition");
|
||||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_join_no_table_dependencies_t, "joined tables must not depend on other tables");
|
SQLPP_PORTABLE_STATIC_ASSERT(assert_join_no_table_dependencies_t, "joined tables must not depend on other tables");
|
||||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_join_on_no_foreign_table_dependencies_t,
|
SQLPP_PORTABLE_STATIC_ASSERT(assert_join_on_no_foreign_table_dependencies_t,
|
||||||
"on() condition must not depend on other tables");
|
"on() condition must not depend on other tables");
|
||||||
|
|
||||||
template <typename CrossJoin, typename On>
|
template <typename PreJoin, typename On>
|
||||||
struct check_join
|
struct check_join
|
||||||
{
|
{
|
||||||
using type = static_combined_check_t<
|
using type = static_combined_check_t<
|
||||||
static_check_t<is_cross_join_t<CrossJoin>::value, assert_join_consist_of_cross_join_and_on_t>,
|
static_check_t<is_pre_join_t<PreJoin>::value, assert_join_consist_of_pre_join_and_on_t>,
|
||||||
static_check_t<is_on_t<On>::value, assert_join_consist_of_cross_join_and_on_t>,
|
static_check_t<is_on_t<On>::value, assert_join_consist_of_pre_join_and_on_t>,
|
||||||
static_check_t<required_tables_of<CrossJoin>::size::value == 0, assert_join_no_table_dependencies_t>,
|
static_check_t<required_tables_of<PreJoin>::size::value == 0, assert_join_no_table_dependencies_t>,
|
||||||
static_check_t<detail::is_subset_of<required_tables_of<On>, provided_tables_of<CrossJoin>>::value,
|
static_check_t<detail::is_subset_of<required_tables_of<On>, provided_tables_of<PreJoin>>::value,
|
||||||
assert_join_on_no_foreign_table_dependencies_t>>;
|
assert_join_on_no_foreign_table_dependencies_t>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename CrossJoin, typename On>
|
template <typename PreJoin, typename On>
|
||||||
using check_join_t = typename check_join<CrossJoin, On>::type;
|
using check_join_t = typename check_join<PreJoin, On>::type;
|
||||||
|
|
||||||
template <typename CrossJoin, typename Expr>
|
template <typename PreJoin, typename Expr>
|
||||||
struct check_join_on
|
struct check_join_on
|
||||||
{
|
{
|
||||||
using type = static_combined_check_t<check_on_t<Expr>, check_join_t<CrossJoin, on_t<Expr>>>;
|
using type = static_combined_check_t<check_on_t<Expr>, check_join_t<PreJoin, on_t<Expr>>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename CrossJoin, typename Expr>
|
template <typename PreJoin, typename Expr>
|
||||||
using check_join_on_t = typename check_join_on<CrossJoin, Expr>::type;
|
using check_join_on_t = typename check_join_on<PreJoin, Expr>::type;
|
||||||
|
|
||||||
template <typename CrossJoin, typename On>
|
template <typename PreJoin, typename On>
|
||||||
struct join_t;
|
struct join_t;
|
||||||
|
|
||||||
template <typename JoinType, typename Lhs, typename Rhs>
|
template <typename JoinType, typename Lhs, typename Rhs>
|
||||||
struct cross_join_t
|
struct pre_join_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_cross_join>;
|
using _traits = make_traits<no_value_t, tag::is_pre_join>;
|
||||||
using _nodes = detail::type_vector<Lhs, Rhs>;
|
using _nodes = detail::type_vector<Lhs, Rhs>;
|
||||||
using _can_be_null = std::false_type;
|
using _can_be_null = std::false_type;
|
||||||
|
|
||||||
@ -99,32 +99,27 @@ namespace sqlpp
|
|||||||
static_assert(detail::is_disjunct_from<provided_tables_of<Lhs>, provided_tables_of<Rhs>>::value,
|
static_assert(detail::is_disjunct_from<provided_tables_of<Lhs>, provided_tables_of<Rhs>>::value,
|
||||||
"joined tables must not be identical");
|
"joined tables must not be identical");
|
||||||
|
|
||||||
static_assert(required_tables_of<cross_join_t>::size::value == 0, "joined tables must not depend on other tables");
|
static_assert(required_tables_of<pre_join_t>::size::value == 0, "joined tables must not depend on other tables");
|
||||||
|
|
||||||
template <typename Expr>
|
template <typename Expr>
|
||||||
auto on(Expr expr) const -> typename std::conditional<check_join_on_t<cross_join_t, Expr>::value,
|
auto on(Expr expr) const -> typename std::conditional<check_join_on_t<pre_join_t, Expr>::value,
|
||||||
join_t<cross_join_t, on_t<Expr>>,
|
join_t<pre_join_t, on_t<Expr>>,
|
||||||
bad_statement>::type
|
bad_statement>::type
|
||||||
{
|
{
|
||||||
check_join_on_t<cross_join_t, Expr>::_();
|
check_join_on_t<pre_join_t, Expr>::_();
|
||||||
|
|
||||||
return {*this, {expr}};
|
return {*this, {expr}};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto unconditionally() -> join_t<cross_join_t, on_t<unconditional_t>>
|
|
||||||
{
|
|
||||||
return {*this, {}};
|
|
||||||
}
|
|
||||||
|
|
||||||
Lhs _lhs;
|
Lhs _lhs;
|
||||||
Rhs _rhs;
|
Rhs _rhs;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Context, typename JoinType, typename Lhs, typename Rhs>
|
template <typename Context, typename JoinType, typename Lhs, typename Rhs>
|
||||||
struct serializer_t<Context, cross_join_t<JoinType, Lhs, Rhs>>
|
struct serializer_t<Context, pre_join_t<JoinType, Lhs, Rhs>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Lhs, Rhs>;
|
using _serialize_check = serialize_check_of<Context, Lhs, Rhs>;
|
||||||
using T = cross_join_t<JoinType, Lhs, Rhs>;
|
using T = pre_join_t<JoinType, Lhs, Rhs>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
@ -137,54 +132,65 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
auto join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_cross_join_t<Lhs, Rhs>::value,
|
auto join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_pre_join_t<Lhs, Rhs>::value,
|
||||||
cross_join_t<inner_join_t, Lhs, Rhs>,
|
pre_join_t<inner_join_t, Lhs, Rhs>,
|
||||||
bad_statement>::type
|
bad_statement>::type
|
||||||
{
|
{
|
||||||
check_cross_join_t<Lhs, Rhs>::_();
|
check_pre_join_t<Lhs, Rhs>::_();
|
||||||
|
|
||||||
return {lhs, rhs};
|
return {lhs, rhs};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
auto inner_join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_cross_join_t<Lhs, Rhs>::value,
|
auto inner_join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_pre_join_t<Lhs, Rhs>::value,
|
||||||
cross_join_t<inner_join_t, Lhs, Rhs>,
|
pre_join_t<inner_join_t, Lhs, Rhs>,
|
||||||
bad_statement>::type
|
bad_statement>::type
|
||||||
{
|
{
|
||||||
check_cross_join_t<Lhs, Rhs>::_();
|
check_pre_join_t<Lhs, Rhs>::_();
|
||||||
|
|
||||||
return {lhs, rhs};
|
return {lhs, rhs};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
auto left_outer_join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_cross_join_t<Lhs, Rhs>::value,
|
auto left_outer_join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_pre_join_t<Lhs, Rhs>::value,
|
||||||
cross_join_t<left_outer_join_t, Lhs, Rhs>,
|
pre_join_t<left_outer_join_t, Lhs, Rhs>,
|
||||||
bad_statement>::type
|
bad_statement>::type
|
||||||
{
|
{
|
||||||
check_cross_join_t<Lhs, Rhs>::_();
|
check_pre_join_t<Lhs, Rhs>::_();
|
||||||
|
|
||||||
return {lhs, rhs};
|
return {lhs, rhs};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
auto right_outer_join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_cross_join_t<Lhs, Rhs>::value,
|
auto right_outer_join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_pre_join_t<Lhs, Rhs>::value,
|
||||||
cross_join_t<right_outer_join_t, Lhs, Rhs>,
|
pre_join_t<right_outer_join_t, Lhs, Rhs>,
|
||||||
bad_statement>::type
|
bad_statement>::type
|
||||||
{
|
{
|
||||||
check_cross_join_t<Lhs, Rhs>::_();
|
check_pre_join_t<Lhs, Rhs>::_();
|
||||||
|
|
||||||
return {lhs, rhs};
|
return {lhs, rhs};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
auto outer_join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_cross_join_t<Lhs, Rhs>::value,
|
auto outer_join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_pre_join_t<Lhs, Rhs>::value,
|
||||||
cross_join_t<right_outer_join_t, Lhs, Rhs>,
|
pre_join_t<right_outer_join_t, Lhs, Rhs>,
|
||||||
bad_statement>::type
|
bad_statement>::type
|
||||||
{
|
{
|
||||||
check_cross_join_t<Lhs, Rhs>::_();
|
check_pre_join_t<Lhs, Rhs>::_();
|
||||||
|
|
||||||
return {lhs, rhs};
|
return {lhs, rhs};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Lhs, typename Rhs>
|
||||||
|
auto cross_join(Lhs lhs, Rhs rhs) ->
|
||||||
|
typename std::conditional<check_pre_join_t<Lhs, Rhs>::value,
|
||||||
|
join_t<pre_join_t<cross_join_t, Lhs, Rhs>, on_t<unconditional_t>>,
|
||||||
|
bad_statement>::type
|
||||||
|
{
|
||||||
|
check_pre_join_t<Lhs, Rhs>::_();
|
||||||
|
|
||||||
|
return {pre_join_t<cross_join_t, Lhs, Rhs>{lhs, rhs}, {}};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -97,6 +97,12 @@ namespace sqlpp
|
|||||||
return {*static_cast<const Table*>(this)};
|
return {*static_cast<const Table*>(this)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto cross_join(T t) const -> decltype(::sqlpp::cross_join(std::declval<Table>(), t))
|
||||||
|
{
|
||||||
|
return ::sqlpp::cross_join(*static_cast<const Table*>(this), t);
|
||||||
|
}
|
||||||
|
|
||||||
const Table& ref() const
|
const Table& ref() const
|
||||||
{
|
{
|
||||||
return *static_cast<const Table*>(this);
|
return *static_cast<const Table*>(this);
|
||||||
|
@ -90,6 +90,12 @@ namespace sqlpp
|
|||||||
return ::sqlpp::outer_join(*this, t);
|
return ::sqlpp::outer_join(*this, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto cross_join(T t) const -> decltype(::sqlpp::cross_join(*this, t))
|
||||||
|
{
|
||||||
|
return ::sqlpp::cross_join(*this, t);
|
||||||
|
}
|
||||||
|
|
||||||
Table _table;
|
Table _table;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -169,9 +169,9 @@ namespace sqlpp
|
|||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_return_value)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_return_value)
|
||||||
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_cross_join)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_pre_join)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_join)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_join)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_dynamic_cross_join)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_dynamic_pre_join)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_dynamic_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)
|
||||||
|
@ -79,7 +79,7 @@ namespace
|
|||||||
{
|
{
|
||||||
// OK
|
// OK
|
||||||
from_static_check<sqlpp::consistent_t>(t);
|
from_static_check<sqlpp::consistent_t>(t);
|
||||||
from_static_check<sqlpp::consistent_t>(t.join(f).unconditionally());
|
from_static_check<sqlpp::consistent_t>(t.cross_join(f));
|
||||||
from_static_check<sqlpp::consistent_t>(t.join(f).on(t.alpha > f.omega));
|
from_static_check<sqlpp::consistent_t>(t.join(f).on(t.alpha > f.omega));
|
||||||
|
|
||||||
// Try a bunch of non-tables
|
// Try a bunch of non-tables
|
||||||
@ -90,14 +90,14 @@ namespace
|
|||||||
from_static_check<sqlpp::assert_from_table_t>(t.delta);
|
from_static_check<sqlpp::assert_from_table_t>(t.delta);
|
||||||
|
|
||||||
// Try cross joins (missing condition)
|
// Try cross joins (missing condition)
|
||||||
from_static_check<sqlpp::assert_from_not_cross_join_t>(t.join(f));
|
from_static_check<sqlpp::assert_from_not_pre_join_t>(t.join(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
void dynamic_from()
|
void dynamic_from()
|
||||||
{
|
{
|
||||||
// OK
|
// OK
|
||||||
from_dynamic_check<sqlpp::consistent_t>(t);
|
from_dynamic_check<sqlpp::consistent_t>(t);
|
||||||
from_dynamic_check<sqlpp::consistent_t>(t.join(f).unconditionally());
|
from_dynamic_check<sqlpp::consistent_t>(t.cross_join(f));
|
||||||
from_dynamic_check<sqlpp::consistent_t>(t.join(f).on(t.alpha > f.omega));
|
from_dynamic_check<sqlpp::consistent_t>(t.join(f).on(t.alpha > f.omega));
|
||||||
|
|
||||||
// Try a bunch of non-tables
|
// Try a bunch of non-tables
|
||||||
@ -108,7 +108,7 @@ namespace
|
|||||||
from_dynamic_check<sqlpp::assert_from_table_t>(t.delta);
|
from_dynamic_check<sqlpp::assert_from_table_t>(t.delta);
|
||||||
|
|
||||||
// Try cross joins (missing condition)
|
// Try cross joins (missing condition)
|
||||||
from_dynamic_check<sqlpp::assert_from_not_cross_join_t>(t.join(f));
|
from_dynamic_check<sqlpp::assert_from_not_pre_join_t>(t.join(f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ namespace
|
|||||||
template <typename Assert, typename Lhs, typename Rhs>
|
template <typename Assert, typename Lhs, typename Rhs>
|
||||||
void join_static_check(const Lhs& lhs, const Rhs& rhs)
|
void join_static_check(const Lhs& lhs, const Rhs& rhs)
|
||||||
{
|
{
|
||||||
using CheckResult = sqlpp::check_cross_join_t<Lhs, Rhs>;
|
using CheckResult = sqlpp::check_pre_join_t<Lhs, Rhs>;
|
||||||
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
|
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
|
||||||
print_type_on_error<CheckResult>(ExpectedCheckResult{});
|
print_type_on_error<CheckResult>(ExpectedCheckResult{});
|
||||||
static_assert(ExpectedCheckResult::value, "Unexpected check result");
|
static_assert(ExpectedCheckResult::value, "Unexpected check result");
|
||||||
@ -57,20 +57,23 @@ namespace
|
|||||||
using LeftOuterJoinType = decltype(sqlpp::left_outer_join(lhs, rhs));
|
using LeftOuterJoinType = decltype(sqlpp::left_outer_join(lhs, rhs));
|
||||||
using RightOuterJoinType = decltype(sqlpp::right_outer_join(lhs, rhs));
|
using RightOuterJoinType = decltype(sqlpp::right_outer_join(lhs, rhs));
|
||||||
using OuterJoinType = decltype(sqlpp::outer_join(lhs, rhs));
|
using OuterJoinType = decltype(sqlpp::outer_join(lhs, rhs));
|
||||||
|
using CrossJoinType = decltype(sqlpp::cross_join(lhs, rhs));
|
||||||
using ExpectedReturnType = sqlpp::logic::all_t<
|
using ExpectedReturnType = sqlpp::logic::all_t<
|
||||||
(Assert::value and sqlpp::is_cross_join_t<JoinType>::value and sqlpp::is_cross_join_t<InnerJoinType>::value and
|
(Assert::value and sqlpp::is_pre_join_t<JoinType>::value and sqlpp::is_pre_join_t<InnerJoinType>::value and
|
||||||
sqlpp::is_cross_join_t<LeftOuterJoinType>::value and sqlpp::is_cross_join_t<RightOuterJoinType>::value and
|
sqlpp::is_pre_join_t<LeftOuterJoinType>::value and sqlpp::is_pre_join_t<RightOuterJoinType>::value and
|
||||||
sqlpp::is_cross_join_t<OuterJoinType>::value) xor
|
sqlpp::is_pre_join_t<OuterJoinType>::value and sqlpp::is_join_t<CrossJoinType>::value) xor
|
||||||
(std::is_same<JoinType, sqlpp::bad_statement>::value and
|
(std::is_same<JoinType, sqlpp::bad_statement>::value and
|
||||||
std::is_same<InnerJoinType, sqlpp::bad_statement>::value and
|
std::is_same<InnerJoinType, sqlpp::bad_statement>::value and
|
||||||
std::is_same<LeftOuterJoinType, sqlpp::bad_statement>::value and
|
std::is_same<LeftOuterJoinType, sqlpp::bad_statement>::value and
|
||||||
std::is_same<RightOuterJoinType, sqlpp::bad_statement>::value and
|
std::is_same<RightOuterJoinType, sqlpp::bad_statement>::value and
|
||||||
std::is_same<OuterJoinType, sqlpp::bad_statement>::value)>;
|
std::is_same<OuterJoinType, sqlpp::bad_statement>::value and
|
||||||
|
std::is_same<CrossJoinType, sqlpp::bad_statement>::value)>;
|
||||||
print_type_on_error<JoinType>(ExpectedReturnType{});
|
print_type_on_error<JoinType>(ExpectedReturnType{});
|
||||||
print_type_on_error<InnerJoinType>(ExpectedReturnType{});
|
print_type_on_error<InnerJoinType>(ExpectedReturnType{});
|
||||||
print_type_on_error<LeftOuterJoinType>(ExpectedReturnType{});
|
print_type_on_error<LeftOuterJoinType>(ExpectedReturnType{});
|
||||||
print_type_on_error<RightOuterJoinType>(ExpectedReturnType{});
|
print_type_on_error<RightOuterJoinType>(ExpectedReturnType{});
|
||||||
print_type_on_error<OuterJoinType>(ExpectedReturnType{});
|
print_type_on_error<OuterJoinType>(ExpectedReturnType{});
|
||||||
|
print_type_on_error<CrossJoinType>(ExpectedReturnType{});
|
||||||
static_assert(ExpectedReturnType::value, "Unexpected return type");
|
static_assert(ExpectedReturnType::value, "Unexpected return type");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +111,7 @@ namespace
|
|||||||
join_static_check<sqlpp::consistent_t>(ta, t);
|
join_static_check<sqlpp::consistent_t>(ta, t);
|
||||||
|
|
||||||
// Prepare a join for tests:
|
// Prepare a join for tests:
|
||||||
const auto j = join(ta, tb).unconditionally();
|
const auto j = cross_join(ta, tb);
|
||||||
|
|
||||||
// OK: Add a third table
|
// OK: Add a third table
|
||||||
join_static_check<sqlpp::consistent_t>(j, f);
|
join_static_check<sqlpp::consistent_t>(j, f);
|
||||||
@ -116,35 +119,35 @@ namespace
|
|||||||
join_static_check<sqlpp::consistent_t>(j, t);
|
join_static_check<sqlpp::consistent_t>(j, t);
|
||||||
|
|
||||||
// Try a bunch of non-tables
|
// Try a bunch of non-tables
|
||||||
join_static_check<sqlpp::assert_cross_join_rhs_table_t>(t, 7);
|
join_static_check<sqlpp::assert_pre_join_rhs_table_t>(t, 7);
|
||||||
join_static_check<sqlpp::assert_cross_join_rhs_table_t>(t, t.alpha);
|
join_static_check<sqlpp::assert_pre_join_rhs_table_t>(t, t.alpha);
|
||||||
join_static_check<sqlpp::assert_cross_join_rhs_table_t>(t, t.beta);
|
join_static_check<sqlpp::assert_pre_join_rhs_table_t>(t, t.beta);
|
||||||
join_static_check<sqlpp::assert_cross_join_rhs_table_t>(t, t.gamma);
|
join_static_check<sqlpp::assert_pre_join_rhs_table_t>(t, t.gamma);
|
||||||
join_static_check<sqlpp::assert_cross_join_rhs_table_t>(t, t.delta);
|
join_static_check<sqlpp::assert_pre_join_rhs_table_t>(t, t.delta);
|
||||||
|
|
||||||
join_static_check<sqlpp::assert_cross_join_lhs_table_t>(7, t);
|
join_static_check<sqlpp::assert_pre_join_lhs_table_t>(7, t);
|
||||||
join_static_check<sqlpp::assert_cross_join_lhs_table_t>(t.alpha, t);
|
join_static_check<sqlpp::assert_pre_join_lhs_table_t>(t.alpha, t);
|
||||||
join_static_check<sqlpp::assert_cross_join_lhs_table_t>(t.beta, t);
|
join_static_check<sqlpp::assert_pre_join_lhs_table_t>(t.beta, t);
|
||||||
join_static_check<sqlpp::assert_cross_join_lhs_table_t>(t.gamma, t);
|
join_static_check<sqlpp::assert_pre_join_lhs_table_t>(t.gamma, t);
|
||||||
join_static_check<sqlpp::assert_cross_join_lhs_table_t>(t.delta, t);
|
join_static_check<sqlpp::assert_pre_join_lhs_table_t>(t.delta, t);
|
||||||
|
|
||||||
// Try to join with join (rhs)
|
// Try to join with join (rhs)
|
||||||
join_static_check<sqlpp::assert_cross_join_rhs_no_join_t>(t, j);
|
join_static_check<sqlpp::assert_pre_join_rhs_no_join_t>(t, j);
|
||||||
join_static_check<sqlpp::assert_cross_join_rhs_no_join_t>(f, j);
|
join_static_check<sqlpp::assert_pre_join_rhs_no_join_t>(f, j);
|
||||||
join_static_check<sqlpp::assert_cross_join_rhs_no_join_t>(t.as(sqlpp::alias::left), j);
|
join_static_check<sqlpp::assert_pre_join_rhs_no_join_t>(t.as(sqlpp::alias::left), j);
|
||||||
|
|
||||||
// Try to join identical table names
|
// Try to join identical table names
|
||||||
join_static_check<sqlpp::assert_cross_join_unique_names_t>(t, t);
|
join_static_check<sqlpp::assert_pre_join_unique_names_t>(t, t);
|
||||||
join_static_check<sqlpp::assert_cross_join_unique_names_t>(f, f);
|
join_static_check<sqlpp::assert_pre_join_unique_names_t>(f, f);
|
||||||
join_static_check<sqlpp::assert_cross_join_unique_names_t>(t.as(f), f);
|
join_static_check<sqlpp::assert_pre_join_unique_names_t>(t.as(f), f);
|
||||||
join_static_check<sqlpp::assert_cross_join_unique_names_t>(t, f.as(t));
|
join_static_check<sqlpp::assert_pre_join_unique_names_t>(t, f.as(t));
|
||||||
join_static_check<sqlpp::assert_cross_join_unique_names_t>(ta, fa);
|
join_static_check<sqlpp::assert_pre_join_unique_names_t>(ta, fa);
|
||||||
join_static_check<sqlpp::assert_cross_join_unique_names_t>(j, fa);
|
join_static_check<sqlpp::assert_pre_join_unique_names_t>(j, fa);
|
||||||
join_static_check<sqlpp::assert_cross_join_unique_names_t>(j, fb);
|
join_static_check<sqlpp::assert_pre_join_unique_names_t>(j, fb);
|
||||||
join_static_check<sqlpp::assert_cross_join_unique_names_t>(j, ta);
|
join_static_check<sqlpp::assert_pre_join_unique_names_t>(j, ta);
|
||||||
join_static_check<sqlpp::assert_cross_join_unique_names_t>(j, tb);
|
join_static_check<sqlpp::assert_pre_join_unique_names_t>(j, tb);
|
||||||
|
|
||||||
// Prepare a cross_joins for tests:
|
// Prepare a pre_joins for tests:
|
||||||
const auto t_f = join(t, f);
|
const auto t_f = join(t, f);
|
||||||
const auto f_t = join(f, t);
|
const auto f_t = join(f, t);
|
||||||
const auto t_t = join(ta, tb);
|
const auto t_t = join(ta, tb);
|
||||||
@ -176,7 +179,7 @@ namespace
|
|||||||
template <typename Assert, typename Table>
|
template <typename Assert, typename Table>
|
||||||
void join_dynamic_check(const Table& table)
|
void join_dynamic_check(const Table& table)
|
||||||
{
|
{
|
||||||
using CheckResult = sqlpp::check_dynamic_cross_join_t<Table>;
|
using CheckResult = sqlpp::check_dynamic_pre_join_t<Table>;
|
||||||
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
|
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
|
||||||
print_type_on_error<CheckResult>(ExpectedCheckResult{});
|
print_type_on_error<CheckResult>(ExpectedCheckResult{});
|
||||||
static_assert(ExpectedCheckResult::value, "Unexpected check result");
|
static_assert(ExpectedCheckResult::value, "Unexpected check result");
|
||||||
@ -186,22 +189,25 @@ namespace
|
|||||||
using LeftOuterJoinType = decltype(sqlpp::dynamic_left_outer_join(table));
|
using LeftOuterJoinType = decltype(sqlpp::dynamic_left_outer_join(table));
|
||||||
using RightOuterJoinType = decltype(sqlpp::dynamic_right_outer_join(table));
|
using RightOuterJoinType = decltype(sqlpp::dynamic_right_outer_join(table));
|
||||||
using OuterJoinType = decltype(sqlpp::dynamic_outer_join(table));
|
using OuterJoinType = decltype(sqlpp::dynamic_outer_join(table));
|
||||||
using ExpectedReturnType =
|
using CrossJoinType = decltype(sqlpp::dynamic_cross_join(table));
|
||||||
sqlpp::logic::all_t<(Assert::value and sqlpp::is_dynamic_cross_join_t<JoinType>::value and
|
using ExpectedReturnType = sqlpp::logic::all_t<(Assert::value and sqlpp::is_dynamic_pre_join_t<JoinType>::value and
|
||||||
sqlpp::is_dynamic_cross_join_t<InnerJoinType>::value and
|
sqlpp::is_dynamic_pre_join_t<InnerJoinType>::value and
|
||||||
sqlpp::is_dynamic_cross_join_t<LeftOuterJoinType>::value and
|
sqlpp::is_dynamic_pre_join_t<LeftOuterJoinType>::value and
|
||||||
sqlpp::is_dynamic_cross_join_t<RightOuterJoinType>::value and
|
sqlpp::is_dynamic_pre_join_t<RightOuterJoinType>::value and
|
||||||
sqlpp::is_dynamic_cross_join_t<OuterJoinType>::value) xor
|
sqlpp::is_dynamic_pre_join_t<OuterJoinType>::value and
|
||||||
|
sqlpp::is_dynamic_join_t<CrossJoinType>::value) xor
|
||||||
(std::is_same<JoinType, sqlpp::bad_statement>::value and
|
(std::is_same<JoinType, sqlpp::bad_statement>::value and
|
||||||
std::is_same<InnerJoinType, sqlpp::bad_statement>::value and
|
std::is_same<InnerJoinType, sqlpp::bad_statement>::value and
|
||||||
std::is_same<LeftOuterJoinType, sqlpp::bad_statement>::value and
|
std::is_same<LeftOuterJoinType, sqlpp::bad_statement>::value and
|
||||||
std::is_same<RightOuterJoinType, sqlpp::bad_statement>::value and
|
std::is_same<RightOuterJoinType, sqlpp::bad_statement>::value and
|
||||||
std::is_same<OuterJoinType, sqlpp::bad_statement>::value)>;
|
std::is_same<OuterJoinType, sqlpp::bad_statement>::value and
|
||||||
|
std::is_same<CrossJoinType, sqlpp::bad_statement>::value)>;
|
||||||
print_type_on_error<JoinType>(ExpectedReturnType{});
|
print_type_on_error<JoinType>(ExpectedReturnType{});
|
||||||
print_type_on_error<InnerJoinType>(ExpectedReturnType{});
|
print_type_on_error<InnerJoinType>(ExpectedReturnType{});
|
||||||
print_type_on_error<LeftOuterJoinType>(ExpectedReturnType{});
|
print_type_on_error<LeftOuterJoinType>(ExpectedReturnType{});
|
||||||
print_type_on_error<RightOuterJoinType>(ExpectedReturnType{});
|
print_type_on_error<RightOuterJoinType>(ExpectedReturnType{});
|
||||||
print_type_on_error<OuterJoinType>(ExpectedReturnType{});
|
print_type_on_error<OuterJoinType>(ExpectedReturnType{});
|
||||||
|
print_type_on_error<CrossJoinType>(ExpectedReturnType{});
|
||||||
static_assert(ExpectedReturnType::value, "Unexpected return type");
|
static_assert(ExpectedReturnType::value, "Unexpected return type");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,17 +239,17 @@ namespace
|
|||||||
join_dynamic_check<sqlpp::consistent_t>(fa);
|
join_dynamic_check<sqlpp::consistent_t>(fa);
|
||||||
|
|
||||||
// Try a bunch of non-tables
|
// Try a bunch of non-tables
|
||||||
join_dynamic_check<sqlpp::assert_dynamic_cross_join_table_t>(7);
|
join_dynamic_check<sqlpp::assert_dynamic_pre_join_table_t>(7);
|
||||||
join_dynamic_check<sqlpp::assert_dynamic_cross_join_table_t>(t.alpha);
|
join_dynamic_check<sqlpp::assert_dynamic_pre_join_table_t>(t.alpha);
|
||||||
join_dynamic_check<sqlpp::assert_dynamic_cross_join_table_t>(t.beta);
|
join_dynamic_check<sqlpp::assert_dynamic_pre_join_table_t>(t.beta);
|
||||||
join_dynamic_check<sqlpp::assert_dynamic_cross_join_table_t>(t.gamma);
|
join_dynamic_check<sqlpp::assert_dynamic_pre_join_table_t>(t.gamma);
|
||||||
join_dynamic_check<sqlpp::assert_dynamic_cross_join_table_t>(t.delta);
|
join_dynamic_check<sqlpp::assert_dynamic_pre_join_table_t>(t.delta);
|
||||||
|
|
||||||
// Try (cross) joins
|
// Try (pre) joins
|
||||||
join_dynamic_check<sqlpp::assert_dynamic_cross_join_table_t>(t.join(f));
|
join_dynamic_check<sqlpp::assert_dynamic_pre_join_table_t>(t.join(f));
|
||||||
join_dynamic_check<sqlpp::assert_dynamic_cross_join_no_join_t>(t.join(f).unconditionally());
|
join_dynamic_check<sqlpp::assert_dynamic_pre_join_no_join_t>(t.cross_join(f));
|
||||||
|
|
||||||
// Prepare a dynamic_cross_joins for tests:
|
// Prepare a dynamic_pre_joins for tests:
|
||||||
const auto tj = dynamic_join(t);
|
const auto tj = dynamic_join(t);
|
||||||
const auto fj = dynamic_join(f);
|
const auto fj = dynamic_join(f);
|
||||||
|
|
||||||
|
@ -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(dynamic_join(f).unconditionally());
|
s.from.add(dynamic_cross_join(f));
|
||||||
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);
|
||||||
|
@ -376,7 +376,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.join(t).unconditionally().join(l).unconditionally())
|
.from(r.cross_join(t).cross_join(l))
|
||||||
.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)
|
||||||
|
Loading…
Reference in New Issue
Block a user