mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-16 04:47:18 +08:00
Fix serialize tests for WITH RECURSIVE
This commit is contained in:
parent
10eaa1f97a
commit
aa6ea6c4f0
@ -40,7 +40,6 @@ namespace sqlpp
|
|||||||
public enable_join<table_as_t<TableSpec, NameTag>>
|
public enable_join<table_as_t<TableSpec, NameTag>>
|
||||||
{
|
{
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
using _required_ctes = required_ctes_of<TableSpec>;
|
|
||||||
|
|
||||||
static_assert(required_tables_of_t<TableSpec>::empty(), "table aliases must not depend on external tables");
|
static_assert(required_tables_of_t<TableSpec>::empty(), "table aliases must not depend on external tables");
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ namespace sqlpp
|
|||||||
struct cte_union_t
|
struct cte_union_t
|
||||||
{
|
{
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
using _required_ctes = detail::make_joined_set_t<required_ctes_of<Lhs>, required_ctes_of<Rhs>>;
|
using _required_ctes = detail::type_vector_cat_t<required_ctes_of_t<Lhs>, required_ctes_of_t<Rhs>>;
|
||||||
using _parameters = detail::type_vector_cat_t<parameters_of<Lhs>, parameters_of<Rhs>>;
|
using _parameters = detail::type_vector_cat_t<parameters_of<Lhs>, parameters_of<Rhs>>;
|
||||||
|
|
||||||
cte_union_t(Lhs lhs, Rhs rhs) : _lhs(lhs), _rhs(rhs)
|
cte_union_t(Lhs lhs, Rhs rhs) : _lhs(lhs), _rhs(rhs)
|
||||||
@ -58,6 +58,21 @@ namespace sqlpp
|
|||||||
Rhs _rhs;
|
Rhs _rhs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename Flag, typename Lhs, typename Rhs>
|
||||||
|
struct required_ctes_of<cte_union_t<Flag, Lhs, Rhs>>
|
||||||
|
{
|
||||||
|
using type = detail::type_vector_cat_t<required_ctes_of_t<Lhs>, required_ctes_of_t<Rhs>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Flag, typename Lhs, typename Rhs>
|
||||||
|
struct required_static_ctes_of<cte_union_t<Flag, Lhs, Rhs>>
|
||||||
|
{
|
||||||
|
using type = typename std::conditional<
|
||||||
|
is_dynamic<Rhs>::value,
|
||||||
|
provided_static_ctes_of_t<Lhs>,
|
||||||
|
detail::type_vector_cat_t<provided_static_ctes_of_t<Lhs>, provided_static_ctes_of_t<Rhs>>>::type;
|
||||||
|
};
|
||||||
|
|
||||||
// Interpreters
|
// Interpreters
|
||||||
template <typename Context, typename Flag, typename Lhs, typename Rhs>
|
template <typename Context, typename Flag, typename Lhs, typename Rhs>
|
||||||
auto to_sql_string(Context& context, const cte_union_t<Flag, Lhs, Rhs>& t) -> std::string
|
auto to_sql_string(Context& context, const cte_union_t<Flag, Lhs, Rhs>& t) -> std::string
|
||||||
@ -169,7 +184,7 @@ namespace sqlpp
|
|||||||
public enable_join<cte_t<NameTagProvider, Statement, FieldSpecs...>>
|
public enable_join<cte_t<NameTagProvider, Statement, FieldSpecs...>>
|
||||||
{
|
{
|
||||||
#warning: Need to test this.
|
#warning: Need to test this.
|
||||||
constexpr static bool _is_recursive = required_ctes_of<Statement>::template count<cte_ref_t<NameTagProvider>>();
|
constexpr static bool _is_recursive = required_ctes_of_t<Statement>::template contains<cte_ref_t<NameTagProvider>>::value;
|
||||||
|
|
||||||
using _column_tuple_t = std::tuple<column_t<cte_ref_t<NameTagProvider>, FieldSpecs>...>;
|
using _column_tuple_t = std::tuple<column_t<cte_ref_t<NameTagProvider>, FieldSpecs>...>;
|
||||||
|
|
||||||
@ -252,6 +267,17 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename NameTagProvider, typename Statement, typename... ColumnSpecs>
|
||||||
|
struct provided_ctes_of<cte_t<NameTagProvider, Statement, ColumnSpecs...>>
|
||||||
|
{
|
||||||
|
using type = detail::type_vector<cte_ref_t<NameTagProvider>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename NameTagProvider, typename Statement, typename... ColumnSpecs>
|
||||||
|
struct provided_static_ctes_of<cte_t<NameTagProvider, Statement, ColumnSpecs...>> : public provided_ctes_of<cte_t<NameTagProvider, Statement, ColumnSpecs...>>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template <typename Context, typename NameTagProvider, typename Statement, typename... ColumnSpecs>
|
template <typename Context, typename NameTagProvider, typename Statement, typename... ColumnSpecs>
|
||||||
auto to_sql_string(Context& context, const cte_t<NameTagProvider, Statement, ColumnSpecs...>& t) -> std::string
|
auto to_sql_string(Context& context, const cte_t<NameTagProvider, Statement, ColumnSpecs...>& t) -> std::string
|
||||||
{
|
{
|
||||||
@ -269,7 +295,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
static_assert(required_tables_of_t<Statement>::empty(),
|
static_assert(required_tables_of_t<Statement>::empty(),
|
||||||
"common table expression must not use unknown tables");
|
"common table expression must not use unknown tables");
|
||||||
static_assert(not required_ctes_of<Statement>::template count<NameTagProvider>(),
|
static_assert(not required_ctes_of_t<Statement>::template contains<NameTagProvider>::value,
|
||||||
"common table expression must not self-reference in the first part, use union_all/union_distinct "
|
"common table expression must not self-reference in the first part, use union_all/union_distinct "
|
||||||
"for recursion");
|
"for recursion");
|
||||||
|
|
||||||
@ -295,6 +321,17 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename NameTagProvider>
|
||||||
|
struct required_ctes_of<cte_ref_t<NameTagProvider>>
|
||||||
|
{
|
||||||
|
using type = sqlpp::detail::type_vector<cte_ref_t<NameTagProvider>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename NameTagProvider>
|
||||||
|
struct required_static_ctes_of<cte_ref_t<NameTagProvider>> : public required_ctes_of<cte_ref_t<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
|
||||||
{
|
{
|
||||||
|
@ -75,14 +75,16 @@ namespace sqlpp
|
|||||||
template <typename Needle, typename Replacement>
|
template <typename Needle, typename Replacement>
|
||||||
using _new_statement_t = typename _policies_update_t<Needle, Replacement>::type;
|
using _new_statement_t = typename _policies_update_t<Needle, Replacement>::type;
|
||||||
|
|
||||||
using _all_required_ctes = detail::make_joined_set_t<required_ctes_of<Policies>...>;
|
using _all_required_ctes = detail::type_vector_cat_t<required_ctes_of_t<Policies>...>;
|
||||||
using _all_provided_ctes = detail::make_joined_set_t<provided_ctes_of<Policies>...>;
|
using _all_provided_ctes = detail::type_vector_cat_t<provided_ctes_of_t<Policies>...>;
|
||||||
using _all_required_tables = detail::type_vector_cat_t<required_tables_of_t<Policies>...>;
|
using _all_required_tables = detail::type_vector_cat_t<required_tables_of_t<Policies>...>;
|
||||||
using _all_provided_tables = detail::type_vector_cat_t<provided_tables_of_t<Policies>...>;
|
using _all_provided_tables = detail::type_vector_cat_t<provided_tables_of_t<Policies>...>;
|
||||||
using _all_provided_optional_tables = detail::type_vector_cat_t<provided_optional_tables_of_t<Policies>...>;
|
using _all_provided_optional_tables = detail::type_vector_cat_t<provided_optional_tables_of_t<Policies>...>;
|
||||||
|
#warning: provided_aggregates_of needs to be replaced with type_vector, too
|
||||||
using _all_provided_aggregates = detail::make_joined_set_t<provided_aggregates_of<Policies>...>;
|
using _all_provided_aggregates = detail::make_joined_set_t<provided_aggregates_of<Policies>...>;
|
||||||
|
|
||||||
using _required_tables_of = detail::copy_if_t<_all_required_tables, _all_provided_tables::template contains_not>;
|
using _required_tables_of = detail::copy_if_t<_all_required_tables, _all_provided_tables::template contains_not>;
|
||||||
|
using _required_ctes_of = detail::copy_if_t<_all_required_ctes, _all_provided_ctes::template contains_not>;
|
||||||
|
|
||||||
template <typename Expression>
|
template <typename Expression>
|
||||||
static constexpr bool _no_unknown_tables = _all_provided_tables::template contains_all<required_tables_of_t<Expression>>::value;
|
static constexpr bool _no_unknown_tables = _all_provided_tables::template contains_all<required_tables_of_t<Expression>>::value;
|
||||||
@ -110,12 +112,6 @@ namespace sqlpp
|
|||||||
template <template <typename> class Predicate>
|
template <template <typename> class Predicate>
|
||||||
using any_t = logic::any<Predicate<Policies>::value...>;
|
using any_t = logic::any<Predicate<Policies>::value...>;
|
||||||
|
|
||||||
// The tables not covered by the from.
|
|
||||||
//using _required_tables = detail::make_difference_set_t<_all_required_tables, _all_provided_tables>;
|
|
||||||
|
|
||||||
// The common table expressions not covered by the with.
|
|
||||||
using _required_ctes = detail::make_difference_set_t<_all_required_ctes, _all_provided_ctes>;
|
|
||||||
|
|
||||||
using _result_type_provider = detail::get_last_if_t<is_result_clause, noop, Policies...>;
|
using _result_type_provider = detail::get_last_if_t<is_result_clause, noop, Policies...>;
|
||||||
|
|
||||||
struct _result_methods_t : public _result_type_provider::template _result_methods_t<_statement_t>
|
struct _result_methods_t : public _result_type_provider::template _result_methods_t<_statement_t>
|
||||||
@ -127,9 +123,8 @@ namespace sqlpp
|
|||||||
// - the select is complete (leaks no table requirements or cte requirements)
|
// - the select is complete (leaks no table requirements or cte requirements)
|
||||||
static constexpr bool _can_be_used_as_table()
|
static constexpr bool _can_be_used_as_table()
|
||||||
{
|
{
|
||||||
#warning: reactivate
|
return has_result_row<_statement_t>::value and _required_tables_of::empty() == 0 and
|
||||||
return has_result_row<_statement_t>::value and /*_required_tables::size::value == 0 and*/
|
_required_ctes_of::empty();
|
||||||
_required_ctes::size::value == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
using _value_type =
|
using _value_type =
|
||||||
@ -149,10 +144,9 @@ namespace sqlpp
|
|||||||
// required_tables and _required_ctes are defined above
|
// required_tables and _required_ctes are defined above
|
||||||
|
|
||||||
using _cte_check =
|
using _cte_check =
|
||||||
typename std::conditional<_required_ctes::size::value == 0, consistent_t, assert_no_unknown_ctes_t>::type;
|
typename std::conditional<_required_ctes_of::empty() == 0, consistent_t, assert_no_unknown_ctes_t>::type;
|
||||||
#warning: reactivate
|
using _table_check =
|
||||||
using _table_check = consistent_t;
|
typename std::conditional<_required_tables_of::empty(), consistent_t, assert_no_unknown_tables_t>::type;
|
||||||
//typename std::conditional<_required_tables::size::value == 0, consistent_t, assert_no_unknown_tables_t>::type;
|
|
||||||
using _parameter_check = typename std::
|
using _parameter_check = typename std::
|
||||||
conditional<_parameters::empty(), consistent_t, assert_no_parameters_t>::type;
|
conditional<_parameters::empty(), consistent_t, assert_no_parameters_t>::type;
|
||||||
};
|
};
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
#include <sqlpp11/core/type_traits/nodes_of.h>
|
#include <sqlpp11/core/type_traits/nodes_of.h>
|
||||||
#include <sqlpp11/core/type_traits/optional.h>
|
#include <sqlpp11/core/type_traits/optional.h>
|
||||||
#include <sqlpp11/core/type_traits/value_type.h>
|
#include <sqlpp11/core/type_traits/value_type.h>
|
||||||
|
#include <sqlpp11/core/type_traits/ctes_of.h>
|
||||||
#include <sqlpp11/core/type_traits/tables_of.h>
|
#include <sqlpp11/core/type_traits/tables_of.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
@ -288,8 +289,6 @@ namespace sqlpp
|
|||||||
template <typename T> \
|
template <typename T> \
|
||||||
using trait##_of = typename detail::trait##_of_impl<T>::type;
|
using trait##_of = typename detail::trait##_of_impl<T>::type;
|
||||||
|
|
||||||
SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(required_ctes)
|
|
||||||
SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_ctes)
|
|
||||||
SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_aggregates)
|
SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_aggregates)
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
107
include/sqlpp11/core/type_traits/ctes_of.h
Normal file
107
include/sqlpp11/core/type_traits/ctes_of.h
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2024, 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 <sqlpp11/core/type_traits/nodes_of.h>
|
||||||
|
#include <sqlpp11/core/detail/type_vector.h>
|
||||||
|
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
// required_ctes_of determines the type_vector of ctes referenced by columns within within T.
|
||||||
|
// column_t or other structs that might reference a table shall specialize this template to indicate their table
|
||||||
|
// requirement.
|
||||||
|
// Dynamic parts of a query shall wrap their required ctes in dynamic_t.
|
||||||
|
template<typename T>
|
||||||
|
struct required_ctes_of
|
||||||
|
{
|
||||||
|
using type = typename required_ctes_of<nodes_of_t<T>>::type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... T>
|
||||||
|
struct required_ctes_of<detail::type_vector<T...>>
|
||||||
|
{
|
||||||
|
using type = detail::type_vector_cat_t<typename required_ctes_of<T>::type...>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using required_ctes_of_t = typename required_ctes_of<T>::type;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct required_static_ctes_of
|
||||||
|
{
|
||||||
|
using type = typename required_static_ctes_of<nodes_of_t<T>>::type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... T>
|
||||||
|
struct required_static_ctes_of<detail::type_vector<T...>>
|
||||||
|
{
|
||||||
|
using type = detail::type_vector_cat_t<typename required_static_ctes_of<T>::type...>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using required_static_ctes_of_t = typename required_static_ctes_of<T>::type;
|
||||||
|
|
||||||
|
#warning: need type tests...
|
||||||
|
//static_assert(required_ctes_of_t<int>::size::value == 0, "");
|
||||||
|
|
||||||
|
// provided_ctes_of determines the type_vector of ctes provided by the query clause, e.g. by FROM.
|
||||||
|
// Provided ctes can be wrapped in dynamic_t if they are provided through a dynamic join.
|
||||||
|
// table_t, cte_ref_t, or other structs that might provide a table in a query need to specialize this template.
|
||||||
|
template <typename T>
|
||||||
|
struct provided_ctes_of
|
||||||
|
{
|
||||||
|
using type = typename provided_ctes_of<nodes_of_t<T>>::type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename... T>
|
||||||
|
struct provided_ctes_of<detail::type_vector<T...>>
|
||||||
|
{
|
||||||
|
using type = detail::type_vector_cat_t<typename provided_ctes_of<T>::type...>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using provided_ctes_of_t = typename provided_ctes_of<T>::type;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct provided_static_ctes_of
|
||||||
|
{
|
||||||
|
using type = typename provided_static_ctes_of<nodes_of_t<T>>::type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename... T>
|
||||||
|
struct provided_static_ctes_of<detail::type_vector<T...>>
|
||||||
|
{
|
||||||
|
using type = detail::type_vector_cat_t<typename provided_static_ctes_of<T>::type...>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using provided_static_ctes_of_t = typename provided_static_ctes_of<T>::type;
|
||||||
|
|
||||||
|
static_assert(provided_ctes_of_t<int>::empty(), "");
|
||||||
|
|
||||||
|
} // namespace sqlpp
|
||||||
|
|
@ -53,8 +53,36 @@ int main(int, char* [])
|
|||||||
{
|
{
|
||||||
const auto x_base = cte(sqlpp::alias::x).as(select(sqlpp::value(0).as(sqlpp::alias::a)));
|
const auto x_base = cte(sqlpp::alias::x).as(select(sqlpp::value(0).as(sqlpp::alias::a)));
|
||||||
const auto x = x_base.union_all(select((x_base.a + 1).as(sqlpp::alias::a)).from(x_base).where(x_base.a < 10));
|
const auto x = x_base.union_all(select((x_base.a + 1).as(sqlpp::alias::a)).from(x_base).where(x_base.a < 10));
|
||||||
|
#warning: Remove debug code.
|
||||||
|
/*
|
||||||
|
using Lhs = sqlpp::statement_t<sqlpp::no_with_t, sqlpp::select_t, sqlpp::no_select_flag_list_t,
|
||||||
|
sqlpp::select_column_list_t<sqlpp::expression_as<sqlpp::value_t<int>, sqlpp::alias::a_t>>,
|
||||||
|
sqlpp::no_from_t, sqlpp::no_where_t<true>, sqlpp::no_group_by_t, sqlpp::no_having_t,
|
||||||
|
sqlpp::no_order_by_t, sqlpp::no_limit_t, sqlpp::no_offset_t, sqlpp::no_union_t,
|
||||||
|
sqlpp::no_for_update_t>;
|
||||||
|
using Rhs = sqlpp::statement_t<
|
||||||
|
sqlpp::no_with_t, sqlpp::select_t, sqlpp::no_select_flag_list_t,
|
||||||
|
sqlpp::select_column_list_t<sqlpp::expression_as<
|
||||||
|
sqlpp::arithmetic_expression<
|
||||||
|
sqlpp::column_t<sqlpp::cte_ref_t<sqlpp::alias::x_t>,
|
||||||
|
sqlpp::field_spec_t<sqlpp::alias::a_t::_sqlpp_name_tag, sqlpp::integral>>,
|
||||||
|
sqlpp::plus, int>,
|
||||||
|
sqlpp::alias::a_t>>,
|
||||||
|
sqlpp::from_t<sqlpp::cte_ref_t<sqlpp::alias::x_t>>,
|
||||||
|
sqlpp::where_t<sqlpp::comparison_expression<
|
||||||
|
sqlpp::column_t<sqlpp::cte_ref_t<sqlpp::alias::x_t>,
|
||||||
|
sqlpp::field_spec_t<sqlpp::alias::a_t::_sqlpp_name_tag, sqlpp::integral>>,
|
||||||
|
sqlpp::less, int>>,
|
||||||
|
sqlpp::no_group_by_t, sqlpp::no_having_t, sqlpp::no_order_by_t, sqlpp::no_limit_t, sqlpp::no_offset_t,
|
||||||
|
sqlpp::no_union_t, sqlpp::no_for_update_t>;
|
||||||
|
//sqlpp::required_ctes_of_t<Rhs>::hansi;
|
||||||
|
using U = sqlpp::cte_union_t<
|
||||||
|
sqlpp::all_t, Lhs, Rhs>;
|
||||||
|
|
||||||
using X = typename std::decay<decltype(x)>::type;
|
using X = typename std::decay<decltype(x)>::type;
|
||||||
|
//X::hansi;
|
||||||
static_assert(X::_is_recursive, "");
|
static_assert(X::_is_recursive, "");
|
||||||
|
*/
|
||||||
#warning: Need to test that recursive CTEs are detected as being recursive.
|
#warning: Need to test that recursive CTEs are detected as being recursive.
|
||||||
SQLPP_COMPARE(with(x), "WITH RECURSIVE x AS (SELECT 0 AS a UNION ALL SELECT (x.a + 1) AS a FROM x WHERE x.a < 10) ");
|
SQLPP_COMPARE(with(x), "WITH RECURSIVE x AS (SELECT 0 AS a UNION ALL SELECT (x.a + 1) AS a FROM x WHERE x.a < 10) ");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user