mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-16 12:51:13 +08:00
Implement CTE alias (allowing self-join)
This commit is contained in:
parent
982812abcc
commit
980daac517
@ -134,6 +134,40 @@ namespace sqlpp
|
|||||||
using type = member_t<FieldSpec, column_t<cte_ref_t<NameTagProvider>, FieldSpec>>;
|
using type = member_t<FieldSpec, column_t<cte_ref_t<NameTagProvider>, FieldSpec>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#warning: Need to document that you need to be a bit careful with aliased CTEs as we use cte_ref in columns, from, and join.
|
||||||
|
template <typename NameTagProvider, typename NewNameTagProvider, typename... FieldSpecs>
|
||||||
|
struct cte_as_t : public cte_member<NewNameTagProvider, FieldSpecs>::type...,
|
||||||
|
public enable_join<cte_as_t<NameTagProvider, NewNameTagProvider, FieldSpecs...>>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename NameTagProvider, typename NewNameTagProvider, typename... ColumnSpecs>
|
||||||
|
struct is_table<cte_as_t<NameTagProvider, NewNameTagProvider, ColumnSpecs...>> : public std::true_type
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename NameTagProvider, typename NewNameTagProvider, typename... ColumnSpecs>
|
||||||
|
struct name_tag_of<cte_as_t<NameTagProvider, NewNameTagProvider, ColumnSpecs...>> : public name_tag_of<NewNameTagProvider>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename NameTagProvider, typename NewNameTagProvider, typename... ColumnSpecs>
|
||||||
|
struct provided_tables_of<cte_as_t<NameTagProvider, NewNameTagProvider, ColumnSpecs...>>
|
||||||
|
{
|
||||||
|
using type = sqlpp::detail::type_vector<cte_ref_t<NewNameTagProvider>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename NameTagProvider, typename NewNameTagProvider, typename... ColumnSpecs>
|
||||||
|
struct provided_static_tables_of<cte_as_t<NameTagProvider, NewNameTagProvider, ColumnSpecs...>> : public provided_tables_of<cte_as_t<NameTagProvider, NewNameTagProvider, ColumnSpecs...>>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Context, typename NameTagProvider, typename NewNameTagProvider, typename... ColumnSpecs>
|
||||||
|
auto to_sql_string(Context& context, const cte_as_t<NameTagProvider, NewNameTagProvider, ColumnSpecs...>&) -> std::string
|
||||||
|
{
|
||||||
|
return name_to_sql_string(context, name_tag_of_t<NameTagProvider>::name) + " AS " + name_to_sql_string(context, name_tag_of_t<NewNameTagProvider>::name);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename NameTagProvider, typename Statement, typename... FieldSpecs>
|
template <typename NameTagProvider, typename Statement, typename... FieldSpecs>
|
||||||
struct cte_t : public cte_member<NameTagProvider, FieldSpecs>::type...,
|
struct cte_t : public cte_member<NameTagProvider, FieldSpecs>::type...,
|
||||||
public enable_join<cte_t<NameTagProvider, Statement, FieldSpecs...>>
|
public enable_join<cte_t<NameTagProvider, Statement, FieldSpecs...>>
|
||||||
@ -151,6 +185,13 @@ namespace sqlpp
|
|||||||
|
|
||||||
using _result_row_t = result_row_t<void, FieldSpecs...>;
|
using _result_row_t = result_row_t<void, FieldSpecs...>;
|
||||||
|
|
||||||
|
template <typename NewNameTagProvider>
|
||||||
|
constexpr auto as(const NewNameTagProvider& /*unused*/) const
|
||||||
|
-> cte_as_t<NameTagProvider, NewNameTagProvider, FieldSpecs...>
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Rhs>
|
template <typename Rhs>
|
||||||
auto union_distinct(Rhs rhs) const
|
auto union_distinct(Rhs rhs) const
|
||||||
-> union_cte_impl_t<check_cte_union_t<Rhs>,
|
-> union_cte_impl_t<check_cte_union_t<Rhs>,
|
||||||
@ -205,7 +246,7 @@ namespace sqlpp
|
|||||||
Statement _statement;
|
Statement _statement;
|
||||||
};
|
};
|
||||||
|
|
||||||
#warning: is table? really?
|
#warning: is table? really? cte_ref needs to be a table, not sure about cte_t
|
||||||
template <typename NameTagProvider, typename Statement, typename... ColumnSpecs>
|
template <typename NameTagProvider, typename Statement, typename... ColumnSpecs>
|
||||||
struct is_table<cte_t<NameTagProvider, Statement, ColumnSpecs...>> : public std::true_type
|
struct is_table<cte_t<NameTagProvider, Statement, ColumnSpecs...>> : public std::true_type
|
||||||
{
|
{
|
||||||
@ -223,9 +264,8 @@ namespace sqlpp
|
|||||||
to_sql_string(context, t._statement) + ")";
|
to_sql_string(context, t._statement) + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
// The cte_t is displayed as NameTagProviderName except within the with:
|
// The cte_ref_t represents the cte as table in FROM.
|
||||||
// - the with needs the
|
// The cte_t needs to be provided by WITH.
|
||||||
// NameTagProviderName AS (ColumnNames) (select/union)
|
|
||||||
template <typename NameTagProvider>
|
template <typename NameTagProvider>
|
||||||
struct cte_ref_t
|
struct cte_ref_t
|
||||||
{
|
{
|
||||||
@ -247,10 +287,13 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#warning: is table? really?
|
|
||||||
template<typename NameTagProvider>
|
template<typename NameTagProvider>
|
||||||
struct is_table<cte_ref_t<NameTagProvider>> : public std::true_type{};
|
struct is_table<cte_ref_t<NameTagProvider>> : public std::true_type{};
|
||||||
|
|
||||||
|
template<typename NameTagProvider>
|
||||||
|
struct name_tag_of<cte_ref_t<NameTagProvider>> : public name_tag_of<NameTagProvider>
|
||||||
|
{};
|
||||||
|
|
||||||
template<typename NameTagProvider>
|
template<typename NameTagProvider>
|
||||||
struct provided_tables_of<cte_ref_t<NameTagProvider>>
|
struct provided_tables_of<cte_ref_t<NameTagProvider>>
|
||||||
{
|
{
|
||||||
@ -262,9 +305,6 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename NameTagProvider>
|
|
||||||
struct name_tag_of<cte_ref_t<NameTagProvider>> : public name_tag_of<NameTagProvider>{};
|
|
||||||
|
|
||||||
template <typename Context, typename NameTagProvider>
|
template <typename Context, typename NameTagProvider>
|
||||||
auto to_sql_string(Context& context, const cte_ref_t<NameTagProvider>&) -> std::string
|
auto to_sql_string(Context& context, const cte_ref_t<NameTagProvider>&) -> std::string
|
||||||
{
|
{
|
||||||
|
@ -36,6 +36,9 @@ int main()
|
|||||||
const auto cFoo = foo.as(sqlpp::alias::c);
|
const auto cFoo = foo.as(sqlpp::alias::c);
|
||||||
|
|
||||||
const auto x = cte(sqlpp::alias::x).as(select(foo.id).from(foo).unconditionally());
|
const auto x = cte(sqlpp::alias::x).as(select(foo.id).from(foo).unconditionally());
|
||||||
|
const auto xa = x.as(sqlpp::alias::a);
|
||||||
|
const auto xb = x.as(sqlpp::alias::b);
|
||||||
|
const auto y = cte(sqlpp::alias::y).as(select(foo.id).from(foo).unconditionally());
|
||||||
|
|
||||||
// Single table
|
// Single table
|
||||||
SQLPP_COMPARE(from(foo), " FROM tab_foo");
|
SQLPP_COMPARE(from(foo), " FROM tab_foo");
|
||||||
@ -53,7 +56,13 @@ int main()
|
|||||||
|
|
||||||
// CTE
|
// CTE
|
||||||
SQLPP_COMPARE(from(x), " FROM x");
|
SQLPP_COMPARE(from(x), " FROM x");
|
||||||
|
SQLPP_COMPARE(from(foo.join(x).on(x.id == foo.id)), " FROM tab_foo INNER JOIN x ON x.id = tab_foo.id");
|
||||||
SQLPP_COMPARE(from(x.join(foo).on(x.id == foo.id)), " FROM x INNER JOIN tab_foo ON x.id = tab_foo.id");
|
SQLPP_COMPARE(from(x.join(foo).on(x.id == foo.id)), " FROM x INNER JOIN tab_foo ON x.id = tab_foo.id");
|
||||||
|
SQLPP_COMPARE(from(x.join(y).on(x.id == y.id)), " FROM x INNER JOIN y ON x.id = y.id");
|
||||||
|
#warning: Some of these should go into CTE tests
|
||||||
|
SQLPP_COMPARE(xa, "x AS a");
|
||||||
|
SQLPP_COMPARE(xa.id == xb.id, "a.id = b.id");
|
||||||
|
SQLPP_COMPARE(from(xa.join(xb).on(xa.id == xb.id)), " FROM x AS a INNER JOIN x AS b ON a.id = b.id");
|
||||||
|
|
||||||
#warning add tests for dynamic joins
|
#warning add tests for dynamic joins
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user