mirror of
https://github.com/rbock/sqlpp11.git
synced 2026-01-08 14:10:51 -06:00
Added "real" cross join
This commit is contained in:
@@ -27,36 +27,36 @@
|
||||
#ifndef SQLPP_DYNAMIC_JOIN_H
|
||||
#define SQLPP_DYNAMIC_JOIN_H
|
||||
|
||||
#include <sqlpp11/dynamic_cross_join.h>
|
||||
#include <sqlpp11/dynamic_pre_join.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
template <typename CrossJoin, typename On>
|
||||
template <typename PreJoin, typename On>
|
||||
struct dynamic_join_t
|
||||
{
|
||||
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 _provided_tables = provided_tables_of<CrossJoin>;
|
||||
using _provided_tables = provided_tables_of<PreJoin>;
|
||||
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(required_tables_of<CrossJoin>::size::value == 0, "joined tables must not depend on other tables");
|
||||
static_assert(is_dynamic_pre_join_t<PreJoin>::value, "lhs argument for on() has to be a pre join");
|
||||
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()");
|
||||
|
||||
CrossJoin _cross_join;
|
||||
PreJoin _pre_join;
|
||||
On _on;
|
||||
};
|
||||
|
||||
template <typename Context, typename CrossJoin, typename On>
|
||||
struct serializer_t<Context, dynamic_join_t<CrossJoin, On>>
|
||||
template <typename Context, typename PreJoin, typename On>
|
||||
struct serializer_t<Context, dynamic_join_t<PreJoin, On>>
|
||||
{
|
||||
using _serialize_check = serialize_check_of<Context, CrossJoin, On>;
|
||||
using T = dynamic_join_t<CrossJoin, On>;
|
||||
using _serialize_check = serialize_check_of<Context, PreJoin, On>;
|
||||
using T = dynamic_join_t<PreJoin, On>;
|
||||
|
||||
static Context& _(const T& t, Context& context)
|
||||
{
|
||||
serialize(t._cross_join, context);
|
||||
serialize(t._pre_join, context);
|
||||
serialize(t._on, context);
|
||||
return context;
|
||||
}
|
||||
|
||||
@@ -24,93 +24,88 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SQLPP_DYNAMIC_CROSS_JOIN_H
|
||||
#define SQLPP_DYNAMIC_CROSS_JOIN_H
|
||||
#ifndef SQLPP_DYNAMIC_PRE_JOIN_H
|
||||
#define SQLPP_DYNAMIC_PRE_JOIN_H
|
||||
|
||||
#include <sqlpp11/join_types.h>
|
||||
#include <sqlpp11/on.h>
|
||||
|
||||
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_cross_join_no_join_t, "argument of dynamic_join() must not 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_pre_join_no_join_t, "argument of dynamic_join() must not be a table");
|
||||
|
||||
template <typename Table>
|
||||
struct check_dynamic_cross_join
|
||||
struct check_dynamic_pre_join
|
||||
{
|
||||
using type =
|
||||
static_combined_check_t<static_check_t<is_table_t<Table>::value, assert_dynamic_cross_join_table_t>,
|
||||
static_check_t<not is_join_t<Table>::value, assert_dynamic_cross_join_no_join_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_pre_join_no_join_t>>;
|
||||
};
|
||||
|
||||
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,
|
||||
"dynamic join has to consist of a dynamic cross_join and a join condition");
|
||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_dynamic_join_consist_of_pre_join_and_on_t,
|
||||
"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,
|
||||
"dynamically joined tables must not depend on other tables");
|
||||
|
||||
template <typename CrossJoin, typename On>
|
||||
template <typename PreJoin, typename On>
|
||||
struct check_dynamic_join
|
||||
{
|
||||
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_on_t<On>::value, assert_dynamic_join_consist_of_cross_join_and_on_t>,
|
||||
static_check_t<required_tables_of<CrossJoin>::size::value == 0, assert_dynamic_join_no_table_dependencies_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_pre_join_and_on_t>,
|
||||
static_check_t<required_tables_of<PreJoin>::size::value == 0, assert_dynamic_join_no_table_dependencies_t>>;
|
||||
};
|
||||
|
||||
template <typename CrossJoin, typename On>
|
||||
using check_dynamic_join_t = typename check_dynamic_join<CrossJoin, On>::type;
|
||||
template <typename PreJoin, typename On>
|
||||
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
|
||||
{
|
||||
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>
|
||||
using check_dynamic_join_on_t = typename check_dynamic_join_on<CrossJoin, Expr>::type;
|
||||
template <typename PreJoin, typename Expr>
|
||||
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;
|
||||
|
||||
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 _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(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");
|
||||
|
||||
template <typename Expr>
|
||||
auto on(Expr expr) const -> typename std::conditional<check_dynamic_join_on_t<dynamic_cross_join_t, Expr>::value,
|
||||
dynamic_join_t<dynamic_cross_join_t, on_t<Expr>>,
|
||||
auto on(Expr expr) const -> typename std::conditional<check_dynamic_join_on_t<dynamic_pre_join_t, Expr>::value,
|
||||
dynamic_join_t<dynamic_pre_join_t, on_t<Expr>>,
|
||||
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}};
|
||||
}
|
||||
|
||||
auto unconditionally() -> dynamic_join_t<dynamic_cross_join_t, on_t<unconditional_t>>
|
||||
{
|
||||
return {*this, {}};
|
||||
}
|
||||
|
||||
Rhs _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 T = dynamic_cross_join_t<JoinType, Rhs>;
|
||||
using T = dynamic_pre_join_t<JoinType, Rhs>;
|
||||
|
||||
static Context& _(const T& t, Context& context)
|
||||
{
|
||||
@@ -121,44 +116,54 @@ namespace sqlpp
|
||||
};
|
||||
|
||||
template <typename JoinType, typename Table>
|
||||
using make_dynamic_cross_join_t = typename std::conditional<check_dynamic_cross_join_t<Table>::value,
|
||||
dynamic_cross_join_t<JoinType, Table>,
|
||||
bad_statement>::type;
|
||||
using make_dynamic_pre_join_t = typename std::conditional<check_dynamic_pre_join_t<Table>::value,
|
||||
dynamic_pre_join_t<JoinType, Table>,
|
||||
bad_statement>::type;
|
||||
|
||||
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};
|
||||
}
|
||||
|
||||
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};
|
||||
}
|
||||
|
||||
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};
|
||||
}
|
||||
|
||||
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};
|
||||
}
|
||||
|
||||
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};
|
||||
}
|
||||
|
||||
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
|
||||
@@ -148,8 +148,8 @@ namespace sqlpp
|
||||
};
|
||||
|
||||
SQLPP_PORTABLE_STATIC_ASSERT(
|
||||
assert_from_not_cross_join_t,
|
||||
"from() argument is a cross join, please use an explicit on() condition or unconditionally()");
|
||||
assert_from_not_pre_join_t,
|
||||
"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_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()");
|
||||
@@ -161,7 +161,7 @@ namespace sqlpp
|
||||
struct check_from
|
||||
{
|
||||
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<required_tables_of<Table>::size::value == 0, assert_from_dependency_free_t>,
|
||||
static_check_t<provided_tables_of<Table>::size::value ==
|
||||
|
||||
@@ -28,18 +28,18 @@
|
||||
#define SQLPP_JOIN_H
|
||||
|
||||
#include <sqlpp11/join_types.h>
|
||||
#include <sqlpp11/cross_join.h>
|
||||
#include <sqlpp11/pre_join.h>
|
||||
#include <sqlpp11/on.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
template <typename CrossJoin, typename On>
|
||||
template <typename PreJoin, typename On>
|
||||
struct join_t
|
||||
{
|
||||
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 _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>;
|
||||
|
||||
template <typename T>
|
||||
@@ -72,19 +72,25 @@ namespace sqlpp
|
||||
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;
|
||||
};
|
||||
|
||||
template <typename Context, typename CrossJoin, typename On>
|
||||
struct serializer_t<Context, join_t<CrossJoin, On>>
|
||||
template <typename Context, typename PreJoin, typename On>
|
||||
struct serializer_t<Context, join_t<PreJoin, On>>
|
||||
{
|
||||
using _serialize_check = serialize_check_of<Context, CrossJoin, On>;
|
||||
using T = join_t<CrossJoin, On>;
|
||||
using _serialize_check = serialize_check_of<Context, PreJoin, On>;
|
||||
using T = join_t<PreJoin, On>;
|
||||
|
||||
static Context& _(const T& t, Context& context)
|
||||
{
|
||||
serialize(t._cross_join, context);
|
||||
serialize(t._pre_join, context);
|
||||
serialize(t._on, context);
|
||||
return context;
|
||||
}
|
||||
|
||||
@@ -60,6 +60,14 @@ namespace sqlpp
|
||||
|
||||
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
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef SQLPP_CROSS_JOIN_H
|
||||
#define SQLPP_CROSS_JOIN_H
|
||||
#ifndef SQLPP_PRE_JOIN_H
|
||||
#define SQLPP_PRE_JOIN_H
|
||||
|
||||
#include <sqlpp11/join_types.h>
|
||||
#include <sqlpp11/on.h>
|
||||
@@ -33,62 +33,62 @@
|
||||
|
||||
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_cross_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_cross_join_unique_names_t, "joined table names have to be unique");
|
||||
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_pre_join_rhs_table_t, "rhs argument of join() has to be a table");
|
||||
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_pre_join_unique_names_t, "joined table names have to be unique");
|
||||
|
||||
template <typename Lhs, typename Rhs>
|
||||
struct check_cross_join
|
||||
struct check_pre_join
|
||||
{
|
||||
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<Rhs>::value, assert_cross_join_rhs_table_t>,
|
||||
static_check_t<not is_join_t<Rhs>::value, assert_cross_join_rhs_no_join_t>,
|
||||
static_check_t<is_table_t<Lhs>::value, assert_pre_join_lhs_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_pre_join_rhs_no_join_t>,
|
||||
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,
|
||||
assert_cross_join_unique_names_t>>;
|
||||
assert_pre_join_unique_names_t>>;
|
||||
};
|
||||
|
||||
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,
|
||||
"join has to consist of a cross_join and a join condition");
|
||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_join_consist_of_pre_join_and_on_t,
|
||||
"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_on_no_foreign_table_dependencies_t,
|
||||
"on() condition must not depend on other tables");
|
||||
|
||||
template <typename CrossJoin, typename On>
|
||||
template <typename PreJoin, typename On>
|
||||
struct check_join
|
||||
{
|
||||
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_on_t<On>::value, assert_join_consist_of_cross_join_and_on_t>,
|
||||
static_check_t<required_tables_of<CrossJoin>::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<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_pre_join_and_on_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<PreJoin>>::value,
|
||||
assert_join_on_no_foreign_table_dependencies_t>>;
|
||||
};
|
||||
|
||||
template <typename CrossJoin, typename On>
|
||||
using check_join_t = typename check_join<CrossJoin, On>::type;
|
||||
template <typename PreJoin, typename On>
|
||||
using check_join_t = typename check_join<PreJoin, On>::type;
|
||||
|
||||
template <typename CrossJoin, typename Expr>
|
||||
template <typename PreJoin, typename Expr>
|
||||
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>
|
||||
using check_join_on_t = typename check_join_on<CrossJoin, Expr>::type;
|
||||
template <typename PreJoin, typename Expr>
|
||||
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;
|
||||
|
||||
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 _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,
|
||||
"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>
|
||||
auto on(Expr expr) const -> typename std::conditional<check_join_on_t<cross_join_t, Expr>::value,
|
||||
join_t<cross_join_t, on_t<Expr>>,
|
||||
auto on(Expr expr) const -> typename std::conditional<check_join_on_t<pre_join_t, Expr>::value,
|
||||
join_t<pre_join_t, on_t<Expr>>,
|
||||
bad_statement>::type
|
||||
{
|
||||
check_join_on_t<cross_join_t, Expr>::_();
|
||||
check_join_on_t<pre_join_t, Expr>::_();
|
||||
|
||||
return {*this, {expr}};
|
||||
}
|
||||
|
||||
auto unconditionally() -> join_t<cross_join_t, on_t<unconditional_t>>
|
||||
{
|
||||
return {*this, {}};
|
||||
}
|
||||
|
||||
Lhs _lhs;
|
||||
Rhs _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 T = cross_join_t<JoinType, Lhs, Rhs>;
|
||||
using T = pre_join_t<JoinType, Lhs, Rhs>;
|
||||
|
||||
static Context& _(const T& t, Context& context)
|
||||
{
|
||||
@@ -137,54 +132,65 @@ namespace sqlpp
|
||||
};
|
||||
|
||||
template <typename Lhs, typename Rhs>
|
||||
auto join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_cross_join_t<Lhs, Rhs>::value,
|
||||
cross_join_t<inner_join_t, Lhs, Rhs>,
|
||||
auto join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_pre_join_t<Lhs, Rhs>::value,
|
||||
pre_join_t<inner_join_t, Lhs, Rhs>,
|
||||
bad_statement>::type
|
||||
{
|
||||
check_cross_join_t<Lhs, Rhs>::_();
|
||||
check_pre_join_t<Lhs, Rhs>::_();
|
||||
|
||||
return {lhs, rhs};
|
||||
}
|
||||
|
||||
template <typename Lhs, typename Rhs>
|
||||
auto inner_join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_cross_join_t<Lhs, Rhs>::value,
|
||||
cross_join_t<inner_join_t, Lhs, Rhs>,
|
||||
auto inner_join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_pre_join_t<Lhs, Rhs>::value,
|
||||
pre_join_t<inner_join_t, Lhs, Rhs>,
|
||||
bad_statement>::type
|
||||
{
|
||||
check_cross_join_t<Lhs, Rhs>::_();
|
||||
check_pre_join_t<Lhs, Rhs>::_();
|
||||
|
||||
return {lhs, rhs};
|
||||
}
|
||||
|
||||
template <typename Lhs, typename Rhs>
|
||||
auto left_outer_join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_cross_join_t<Lhs, Rhs>::value,
|
||||
cross_join_t<left_outer_join_t, Lhs, Rhs>,
|
||||
auto left_outer_join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_pre_join_t<Lhs, Rhs>::value,
|
||||
pre_join_t<left_outer_join_t, Lhs, Rhs>,
|
||||
bad_statement>::type
|
||||
{
|
||||
check_cross_join_t<Lhs, Rhs>::_();
|
||||
check_pre_join_t<Lhs, Rhs>::_();
|
||||
|
||||
return {lhs, rhs};
|
||||
}
|
||||
|
||||
template <typename Lhs, typename Rhs>
|
||||
auto right_outer_join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_cross_join_t<Lhs, Rhs>::value,
|
||||
cross_join_t<right_outer_join_t, Lhs, Rhs>,
|
||||
auto right_outer_join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_pre_join_t<Lhs, Rhs>::value,
|
||||
pre_join_t<right_outer_join_t, Lhs, Rhs>,
|
||||
bad_statement>::type
|
||||
{
|
||||
check_cross_join_t<Lhs, Rhs>::_();
|
||||
check_pre_join_t<Lhs, Rhs>::_();
|
||||
|
||||
return {lhs, rhs};
|
||||
}
|
||||
|
||||
template <typename Lhs, typename Rhs>
|
||||
auto outer_join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_cross_join_t<Lhs, Rhs>::value,
|
||||
cross_join_t<right_outer_join_t, Lhs, Rhs>,
|
||||
auto outer_join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_pre_join_t<Lhs, Rhs>::value,
|
||||
pre_join_t<right_outer_join_t, Lhs, Rhs>,
|
||||
bad_statement>::type
|
||||
{
|
||||
check_cross_join_t<Lhs, Rhs>::_();
|
||||
check_pre_join_t<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
|
||||
@@ -97,6 +97,12 @@ namespace sqlpp
|
||||
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
|
||||
{
|
||||
return *static_cast<const Table*>(this);
|
||||
|
||||
@@ -90,6 +90,12 @@ namespace sqlpp
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
@@ -169,9 +169,9 @@ namespace sqlpp
|
||||
SQLPP_VALUE_TRAIT_GENERATOR(is_return_value)
|
||||
SQLPP_VALUE_TRAIT_GENERATOR(is_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_dynamic_cross_join)
|
||||
SQLPP_VALUE_TRAIT_GENERATOR(is_dynamic_pre_join)
|
||||
SQLPP_VALUE_TRAIT_GENERATOR(is_dynamic_join)
|
||||
SQLPP_VALUE_TRAIT_GENERATOR(is_pseudo_table)
|
||||
SQLPP_VALUE_TRAIT_GENERATOR(is_column)
|
||||
|
||||
Reference in New Issue
Block a user