mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-16 04:47:18 +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>>;
|
||||
};
|
||||
|
||||
#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>
|
||||
struct cte_t : public cte_member<NameTagProvider, FieldSpecs>::type...,
|
||||
public enable_join<cte_t<NameTagProvider, Statement, FieldSpecs...>>
|
||||
@ -151,6 +185,13 @@ namespace sqlpp
|
||||
|
||||
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>
|
||||
auto union_distinct(Rhs rhs) const
|
||||
-> union_cte_impl_t<check_cte_union_t<Rhs>,
|
||||
@ -205,7 +246,7 @@ namespace sqlpp
|
||||
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>
|
||||
struct is_table<cte_t<NameTagProvider, Statement, ColumnSpecs...>> : public std::true_type
|
||||
{
|
||||
@ -223,9 +264,8 @@ namespace sqlpp
|
||||
to_sql_string(context, t._statement) + ")";
|
||||
}
|
||||
|
||||
// The cte_t is displayed as NameTagProviderName except within the with:
|
||||
// - the with needs the
|
||||
// NameTagProviderName AS (ColumnNames) (select/union)
|
||||
// The cte_ref_t represents the cte as table in FROM.
|
||||
// The cte_t needs to be provided by WITH.
|
||||
template <typename NameTagProvider>
|
||||
struct cte_ref_t
|
||||
{
|
||||
@ -247,10 +287,13 @@ namespace sqlpp
|
||||
}
|
||||
};
|
||||
|
||||
#warning: is table? really?
|
||||
template<typename NameTagProvider>
|
||||
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>
|
||||
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>
|
||||
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 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
|
||||
SQLPP_COMPARE(from(foo), " FROM tab_foo");
|
||||
@ -53,7 +56,13 @@ int main()
|
||||
|
||||
// CTE
|
||||
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(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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user