should be it

This commit is contained in:
2025-10-24 19:21:19 -05:00
parent a4b23fc57c
commit f09560c7b1
14047 changed files with 3161551 additions and 1 deletions

View File

@@ -0,0 +1,35 @@
# name: test/sql/cte/cte_bc.test
# description: Test BC of reading CTEs
# group: [cte]
# The database is written with a vector size of 2048.
require vector_size 2048
unzip data/storage/cte_v1.db.gz __TEST_DIR__/cte_v1.db
unzip data/storage/cte_v1_4.db.gz __TEST_DIR__/cte_v1_4.db
statement ok
ATTACH '__TEST_DIR__/cte_v1.db' (READ_ONLY)
statement ok
ATTACH '__TEST_DIR__/cte_v1_4.db' (READ_ONLY)
foreach cte_db cte_v1 cte_v1_4
query I
FROM ${cte_db}.v1
----
42
query I
FROM ${cte_db}.v2
----
42
query I
FROM ${cte_db}.v3
----
42
endloop

View File

@@ -0,0 +1,16 @@
# name: test/sql/cte/cte_colname_issue_10074.test
# description: Issue #10074 - CTE returns wrong column name
# group: [cte]
statement ok
pragma enable_verification
statement ok
create table t as with q(id,s) as (values(1,42)),
a(s)as materialized(select 42)
select id from q join a on q.s=a.s
query I
select id from t
----
1

View File

@@ -0,0 +1,34 @@
# name: test/sql/cte/cte_describe.test
# description: Test CTE describe
# group: [cte]
statement ok
PRAGMA enable_verification
query I nosort describe
DESCRIBE select 42 AS a
query I nosort describe
with cte as (select 42 AS a) FROM (DESCRIBE TABLE cte)
query I nosort describe
with cte as (select 42 AS a) FROM (DESCRIBE TABLE cte)
query I nosort summarize
SUMMARIZE select 42 AS a
query I nosort summarize
with cte as (select 42 AS a) FROM (SUMMARIZE TABLE cte)
query I nosort summarize
with cte as (select 42 AS a) FROM (SUMMARIZE TABLE cte)
statement error
with cte as (select 42 AS a) (DESCRIBE TABLE cte)
----
Parser Error: exprLocation NOT IMPLEMENTED
statement error
(DESCRIBE TABLE cte) ORDER BY 1
----
Parser Error: exprLocation NOT IMPLEMENTED

View File

@@ -0,0 +1,21 @@
# name: test/sql/cte/cte_issue_17311.test
# description: Test for CTE issue #17311
# group: [cte]
statement ok
PRAGMA enable_verification
statement ok
CREATE RECURSIVE VIEW nums (n) AS
VALUES (1)
UNION ALL
SELECT n+1 FROM nums WHERE n < 5;
query I
FROM nums
----
1
2
3
4
5

View File

@@ -0,0 +1,18 @@
# name: test/sql/cte/cte_schema.test
# description: Test conflict between CTE and table in different schema
# group: [cte]
statement ok
create schema s1;
statement ok
create table s1.tbl(a varchar);
statement ok
insert into s1.tbl values ('hello');
query II
with tbl as (select 'world' b)
select * from s1.tbl, tbl;
----
hello world

View File

@@ -0,0 +1,19 @@
# name: test/sql/cte/cte_with_replacement_scan.test
# description: Test CTE with same name as file
# group: [cte]
require parquet
statement ok
PRAGMA enable_verification
statement ok
copy (select 42 as answer) to '__TEST_DIR__/df.parquet';
query I
WITH '__TEST_DIR__/df.parquet' AS (
SELECT answer FROM '__TEST_DIR__/df.parquet'
)
SELECT * FROM '__TEST_DIR__/df.parquet';
----
42

View File

@@ -0,0 +1,65 @@
# name: test/sql/cte/game_of_life.test_slow
# description: Run conways game of life as a CTE (https://gist.github.com/janickr/58fab629ee3ea7e5638a)
# group: [cte]
statement ok
create table series as select * from generate_series(-1,1) x(n);
# conway
query III
with recursive generation1(x,y) as ( --the initial board setup
select 2, 3
union
select 3, 3
union
select 4, 3
),
game(n, x, y) as (
select 1 AS n, x, y from generation1 -- generation 1 is initial board setup
union all
select n+1, new_x, new_y from -- generation n+1
(
select n, x+offset_x new_x, y+offset_y new_y, max(self) over (partition by n+1, x+offset_x, y+offset_y) cell_was_already_alive
from game, (
select x.n offset_x, y.n offset_y, case when x.n = 0 and y.n = 0 then 1 else 0 end self
from series x(n), series y(n) --join 2 row generators to get 9 pairs
) offsets_to_neighbours_and_self(offset_x, offset_y, self)
where n < 100
) all_impacts
group by n+1, new_x, new_y, cell_was_already_alive -- from all impacts back to cells
having (cell_was_already_alive=1 and count(*) < 5 and count(*) > 2) or count(*) = 3 --decide if cell is alive
)
select * from game where n=4 order by n, x, y; --select generation 4
----
4 3 2
4 3 3
4 3 4
query III
with recursive generation1(x,y) as ( --the initial board setup
select 2, 3
union
select 3, 3
union
select 4, 3
),
game(n, x, y) as (
select 1 AS n, x, y from generation1 -- generation 1 is initial board setup
union all
select n+1, new_x, new_y from -- generation n+1
(
select n, x+offset_x new_x, y+offset_y new_y, max(self) over (partition by n+1, x+offset_x, y+offset_y) cell_was_already_alive
from game, (
select x.n offset_x, y.n offset_y, case when x.n = 0 and y.n = 0 then 1 else 0 end self
from generate_series(-1,1) x(n), generate_series(-1,1) y(n) --join 2 row generators to get 9 pairs
) offsets_to_neighbours_and_self(offset_x, offset_y, self)
where n < 100
) all_impacts
group by n+1, new_x, new_y, cell_was_already_alive -- from all impacts back to cells
having (cell_was_already_alive=1 and count(*) < 5 and count(*) > 2) or count(*) = 3 --decide if cell is alive
)
select * from game where n=4 order by n, x, y; --select generation 4
----
4 3 2
4 3 3
4 3 4

View File

@@ -0,0 +1,18 @@
# name: test/sql/cte/incorrect_recursive_cte.test
# description: Incorrect recursive ctes
# group: [cte]
# recursive CTE without UNION is just a normal CTE
query I
WITH RECURSIVE cte AS (SELECT 42) SELECT * FROM cte;
----
42
# we only support recursive ctes with union or union all
statement error
with recursive t as (select 1 as x intersect select x+1 from t where x < 3) select * from t order by x
----
statement error
with recursive t as (select 1 as x except select x+1 from t where x < 3) select * from t order by x
----

View File

@@ -0,0 +1,17 @@
# name: test/sql/cte/insert_cte_bug_3417.test
# description: Test for a crash reported in issue #3417
# group: [cte]
statement ok
PRAGMA enable_verification
statement ok
CREATE TABLE table1 (id INTEGER, a INTEGER);
statement ok
CREATE TABLE table2 (table1_id INTEGER);
statement error
INSERT INTO table2 WITH cte AS (INSERT INTO table1 SELECT 1, 2 RETURNING id) SELECT id FROM cte;
----
<REGEX>:.*Parser Error.*A CTE needs a SELECT.*

View File

@@ -0,0 +1,12 @@
# name: test/sql/cte/lazy_cte_bind.test
# description: Test that CTE binding is lazy
# group: [cte]
statement ok
PRAGMA enable_verification
query I
with cte as (select * from read_parquet('does/not/exist/file.parquet'))
select 42
----
42

View File

@@ -0,0 +1,39 @@
# name: test/sql/cte/materialized/annotated_and_auto_materialized.test
# description: Issue 13850 - Binder error when manually materializing a CTE
# group: [materialized]
statement ok
create table batch (
entity text,
start_ts timestamp,
duration interval
);
statement ok
create table active_events (
entity text,
start_ts timestamp,
end_ts timestamp
);
statement ok
explain create table new_active_events as
with
new_events as materialized ( -- Does not make much sense in this example, but my original query was a union of a bunch of things
select * from batch
), combined_deduplicated_events as (
select
entity,
min(start_ts) as start_ts,
max(end_ts) as end_ts
from
active_events
group by
entity
), all_events as (
select * from combined_deduplicated_events
)
select
*
from
new_events;

View File

@@ -0,0 +1,407 @@
# name: test/sql/cte/materialized/automatic_cte_materialization.test_slow
# description: Test that CTEs are automatically materialized
# group: [materialized]
require tpch
statement ok
PRAGMA enable_verification
statement ok
PRAGMA explain_output='OPTIMIZED_ONLY'
statement ok
SET disabled_optimizers TO 'common_subplan'
statement ok
CALL dbgen(sf=0.01);
# TPC-H Q15
query II
EXPLAIN WITH revenue AS (
SELECT
l_suppkey AS supplier_no,
sum(l_extendedprice * (1 - l_discount)) AS total_revenue
FROM
lineitem
WHERE
l_shipdate >= CAST('1996-01-01' AS date)
AND l_shipdate < CAST('1996-04-01' AS date)
GROUP BY
supplier_no
)
SELECT
s_suppkey,
s_name,
s_address,
s_phone,
total_revenue
FROM
supplier,
revenue
WHERE
s_suppkey = supplier_no
AND total_revenue = (
SELECT
max(total_revenue)
FROM revenue)
ORDER BY
s_suppkey;
----
logical_opt <REGEX>:.*CTE_SCAN.*
query II
EXPLAIN WITH revenue AS NOT MATERIALIZED (
SELECT
l_suppkey AS supplier_no,
sum(l_extendedprice * (1 - l_discount)) AS total_revenue
FROM
lineitem
WHERE
l_shipdate >= CAST('1996-01-01' AS date)
AND l_shipdate < CAST('1996-04-01' AS date)
GROUP BY
supplier_no
)
SELECT
s_suppkey,
s_name,
s_address,
s_phone,
total_revenue
FROM
supplier,
revenue
WHERE
s_suppkey = supplier_no
AND total_revenue = (
SELECT
max(total_revenue)
FROM revenue)
ORDER BY
s_suppkey;
----
logical_opt <!REGEX>:.*CTE_SCAN.*
# duplicate table name
statement ok
DROP TABLE customer
require tpcds
statement ok
call dsdgen(sf=0.01)
# TPC-DS Q23
query II
EXPLAIN WITH frequent_ss_items AS
(SELECT itemdesc,
i_item_sk item_sk,
d_date solddate,
count(*) cnt
FROM store_sales,
date_dim,
(SELECT SUBSTRING(i_item_desc, 1, 30) itemdesc,
*
FROM item) sq1
WHERE ss_sold_date_sk = d_date_sk
AND ss_item_sk = i_item_sk
AND d_year IN (2000,
2000+1,
2000+2,
2000+3)
GROUP BY itemdesc,
i_item_sk,
d_date
HAVING count(*) >4),
max_store_sales AS
(SELECT max(csales) tpcds_cmax
FROM
(SELECT c_customer_sk,
sum(ss_quantity*ss_sales_price) csales
FROM store_sales,
customer,
date_dim
WHERE ss_customer_sk = c_customer_sk
AND ss_sold_date_sk = d_date_sk
AND d_year IN (2000,
2000+1,
2000+2,
2000+3)
GROUP BY c_customer_sk) sq2),
best_ss_customer AS
(SELECT c_customer_sk,
sum(ss_quantity*ss_sales_price) ssales
FROM store_sales,
customer,
max_store_sales
WHERE ss_customer_sk = c_customer_sk
GROUP BY c_customer_sk
HAVING sum(ss_quantity*ss_sales_price) > (50/100.0) * max(tpcds_cmax))
SELECT c_last_name,
c_first_name,
sales
FROM
(SELECT c_last_name,
c_first_name,
sum(cs_quantity*cs_list_price) sales
FROM catalog_sales,
customer,
date_dim,
frequent_ss_items,
best_ss_customer
WHERE d_year = 2000
AND d_moy = 2
AND cs_sold_date_sk = d_date_sk
AND cs_item_sk = item_sk
AND cs_bill_customer_sk = best_ss_customer.c_customer_sk
AND cs_bill_customer_sk = customer.c_customer_sk
GROUP BY c_last_name,
c_first_name
UNION ALL SELECT c_last_name,
c_first_name,
sum(ws_quantity*ws_list_price) sales
FROM web_sales,
customer,
date_dim,
frequent_ss_items,
best_ss_customer
WHERE d_year = 2000
AND d_moy = 2
AND ws_sold_date_sk = d_date_sk
AND ws_item_sk = item_sk
AND ws_bill_customer_sk = best_ss_customer.c_customer_sk
AND ws_bill_customer_sk = customer.c_customer_sk
GROUP BY c_last_name,
c_first_name) sq3
ORDER BY c_last_name NULLS FIRST,
c_first_name NULLS FIRST,
sales NULLS FIRST
LIMIT 100;
----
logical_opt <REGEX>:.*CTE_SCAN.*
query II
EXPLAIN WITH frequent_ss_items AS NOT MATERIALIZED
(SELECT itemdesc,
i_item_sk item_sk,
d_date solddate,
count(*) cnt
FROM store_sales,
date_dim,
(SELECT SUBSTRING(i_item_desc, 1, 30) itemdesc,
*
FROM item) sq1
WHERE ss_sold_date_sk = d_date_sk
AND ss_item_sk = i_item_sk
AND d_year IN (2000,
2000+1,
2000+2,
2000+3)
GROUP BY itemdesc,
i_item_sk,
d_date
HAVING count(*) >4),
max_store_sales AS NOT MATERIALIZED
(SELECT max(csales) tpcds_cmax
FROM
(SELECT c_customer_sk,
sum(ss_quantity*ss_sales_price) csales
FROM store_sales,
customer,
date_dim
WHERE ss_customer_sk = c_customer_sk
AND ss_sold_date_sk = d_date_sk
AND d_year IN (2000,
2000+1,
2000+2,
2000+3)
GROUP BY c_customer_sk) sq2),
best_ss_customer AS NOT MATERIALIZED
(SELECT c_customer_sk,
sum(ss_quantity*ss_sales_price) ssales
FROM store_sales,
customer,
max_store_sales
WHERE ss_customer_sk = c_customer_sk
GROUP BY c_customer_sk
HAVING sum(ss_quantity*ss_sales_price) > (50/100.0) * max(tpcds_cmax))
SELECT c_last_name,
c_first_name,
sales
FROM
(SELECT c_last_name,
c_first_name,
sum(cs_quantity*cs_list_price) sales
FROM catalog_sales,
customer,
date_dim,
frequent_ss_items,
best_ss_customer
WHERE d_year = 2000
AND d_moy = 2
AND cs_sold_date_sk = d_date_sk
AND cs_item_sk = item_sk
AND cs_bill_customer_sk = best_ss_customer.c_customer_sk
AND cs_bill_customer_sk = customer.c_customer_sk
GROUP BY c_last_name,
c_first_name
UNION ALL SELECT c_last_name,
c_first_name,
sum(ws_quantity*ws_list_price) sales
FROM web_sales,
customer,
date_dim,
frequent_ss_items,
best_ss_customer
WHERE d_year = 2000
AND d_moy = 2
AND ws_sold_date_sk = d_date_sk
AND ws_item_sk = item_sk
AND ws_bill_customer_sk = best_ss_customer.c_customer_sk
AND ws_bill_customer_sk = customer.c_customer_sk
GROUP BY c_last_name,
c_first_name) sq3
ORDER BY c_last_name NULLS FIRST,
c_first_name NULLS FIRST,
sales NULLS FIRST
LIMIT 100;
----
logical_opt <!REGEX>:.*CTE_SCAN.*
# TPC-DS Q57
query II
EXPLAIN WITH v1 AS
(SELECT i_category,
i_brand,
cc_name,
d_year,
d_moy,
sum(cs_sales_price) sum_sales,
avg(sum(cs_sales_price)) OVER (PARTITION BY i_category,
i_brand,
cc_name,
d_year) avg_monthly_sales,
rank() OVER (PARTITION BY i_category,
i_brand,
cc_name
ORDER BY d_year,
d_moy) rn
FROM item,
catalog_sales,
date_dim,
call_center
WHERE cs_item_sk = i_item_sk
AND cs_sold_date_sk = d_date_sk
AND cc_call_center_sk= cs_call_center_sk
AND (d_year = 1999
OR (d_year = 1999-1
AND d_moy =12)
OR (d_year = 1999+1
AND d_moy =1))
GROUP BY i_category,
i_brand,
cc_name,
d_year,
d_moy),
v2 AS
(SELECT v1.i_category,
v1.i_brand,
v1.cc_name,
v1.d_year,
v1.d_moy,
v1.avg_monthly_sales,
v1.sum_sales,
v1_lag.sum_sales psum,
v1_lead.sum_sales nsum
FROM v1,
v1 v1_lag,
v1 v1_lead
WHERE v1.i_category = v1_lag.i_category
AND v1.i_category = v1_lead.i_category
AND v1.i_brand = v1_lag.i_brand
AND v1.i_brand = v1_lead.i_brand
AND v1. cc_name = v1_lag. cc_name
AND v1. cc_name = v1_lead. cc_name
AND v1.rn = v1_lag.rn + 1
AND v1.rn = v1_lead.rn - 1)
SELECT *
FROM v2
WHERE d_year = 1999
AND avg_monthly_sales > 0
AND CASE
WHEN avg_monthly_sales > 0 THEN abs(sum_sales - avg_monthly_sales) / avg_monthly_sales
ELSE NULL
END > 0.1
ORDER BY sum_sales - avg_monthly_sales NULLS FIRST, 1, 2, 3, 4, 5, 6, 7, 8, 9
LIMIT 100;
----
logical_opt <REGEX>:.*CTE_SCAN.*
query II
EXPLAIN WITH v1 AS NOT MATERIALIZED
(SELECT i_category,
i_brand,
cc_name,
d_year,
d_moy,
sum(cs_sales_price) sum_sales,
avg(sum(cs_sales_price)) OVER (PARTITION BY i_category,
i_brand,
cc_name,
d_year) avg_monthly_sales,
rank() OVER (PARTITION BY i_category,
i_brand,
cc_name
ORDER BY d_year,
d_moy) rn
FROM item,
catalog_sales,
date_dim,
call_center
WHERE cs_item_sk = i_item_sk
AND cs_sold_date_sk = d_date_sk
AND cc_call_center_sk= cs_call_center_sk
AND (d_year = 1999
OR (d_year = 1999-1
AND d_moy =12)
OR (d_year = 1999+1
AND d_moy =1))
GROUP BY i_category,
i_brand,
cc_name,
d_year,
d_moy),
v2 AS
(SELECT v1.i_category,
v1.i_brand,
v1.cc_name,
v1.d_year,
v1.d_moy,
v1.avg_monthly_sales,
v1.sum_sales,
v1_lag.sum_sales psum,
v1_lead.sum_sales nsum
FROM v1,
v1 v1_lag,
v1 v1_lead
WHERE v1.i_category = v1_lag.i_category
AND v1.i_category = v1_lead.i_category
AND v1.i_brand = v1_lag.i_brand
AND v1.i_brand = v1_lead.i_brand
AND v1. cc_name = v1_lag. cc_name
AND v1. cc_name = v1_lead. cc_name
AND v1.rn = v1_lag.rn + 1
AND v1.rn = v1_lead.rn - 1)
SELECT *
FROM v2
WHERE d_year = 1999
AND avg_monthly_sales > 0
AND CASE
WHEN avg_monthly_sales > 0 THEN abs(sum_sales - avg_monthly_sales) / avg_monthly_sales
ELSE NULL
END > 0.1
ORDER BY sum_sales - avg_monthly_sales NULLS FIRST, 1, 2, 3, 4, 5, 6, 7, 8, 9
LIMIT 100;
----
logical_opt <!REGEX>:.*CTE_SCAN.*

View File

@@ -0,0 +1,23 @@
# name: test/sql/cte/materialized/cte_filter_pusher.test
# description: Test that the cte_filter_pusher optimizer works
# group: [materialized]
query I
WITH
a(x) AS MATERIALIZED (
SELECT *
FROM generate_series(1, 10)
),
b(x) AS MATERIALIZED (
SELECT *
FROM a
WHERE x < 8
)
SELECT *
FROM b
WHERE x % 3 = 1
ORDER BY x;
----
1
4
7

View File

@@ -0,0 +1,111 @@
# name: test/sql/cte/materialized/dml_materialized_cte.test
# description: Test DML statements with materialized Common Table Expressions (CTE)
# group: [materialized]
statement ok
PRAGMA enable_verification
require no_alternative_verify
statement ok
create table a(i integer);
statement ok
insert into a values (42);
query I
WITH t(x) AS MATERIALIZED (VALUES (42))
INSERT INTO a (SELECT * FROM t);
----
1
query I
WITH t(x) AS MATERIALIZED (VALUES (42))
DELETE FROM a WHERE a.i IN (SELECT * FROM t);
----
2
statement ok
insert into a values (42);
query I
WITH t(x) AS MATERIALIZED (VALUES (42))
UPDATE a SET i = 0 WHERE a.i IN (SELECT * FROM t);
----
1
query I
FROM a
----
0
statement ok
insert into a values (2);
query I
WITH t(x) AS MATERIALIZED (SELECT 1),
u(x) AS MATERIALIZED (SELECT 2 UNION ALL SELECT * FROM t)
DELETE FROM a WHERE a.i IN (SELECT * FROM u);
----
1
statement ok
insert into a values (2);
query I
WITH t(x) AS MATERIALIZED (SELECT 1),
u(x) AS MATERIALIZED (SELECT 2 UNION ALL SELECT * FROM t)
UPDATE a SET i = 99 WHERE a.i IN (SELECT * FROM u);
----
1
query I
FROM a ORDER BY 1
----
0
99
query I
WITH t(x) AS MATERIALIZED (SELECT 1),
u(x) AS MATERIALIZED (SELECT 2 UNION ALL SELECT * FROM t)
INSERT INTO a (SELECT * FROM u);
----
2
query I
FROM a ORDER BY 1
----
0
1
2
99
statement ok
insert into a values (42);
query I
WITH t(x) AS MATERIALIZED (SELECT 1)
DELETE FROM a WHERE i IN (WITH s(x) AS MATERIALIZED (SELECT x + 41 FROM t) SELECT * FROM t);
----
1
query I
FROM a ORDER BY 1
----
0
2
42
99
query I
WITH t(x) AS MATERIALIZED (SELECT 1)
DELETE FROM a WHERE i IN (WITH s(x) AS MATERIALIZED (SELECT x + 41 FROM t) SELECT * FROM s);
----
1
query I
FROM a ORDER BY 1
----
0
2
99

View File

@@ -0,0 +1,65 @@
# name: test/sql/cte/materialized/game_of_life_materialized.test_slow
# description: Run conways game of life as a CTE (https://gist.github.com/janickr/58fab629ee3ea7e5638a)
# group: [materialized]
statement ok
create table series as select * from generate_series(-1,1) x(n);
# conway
query III
with recursive generation1(x,y) as materialized ( --the initial board setup
select 2, 3
union
select 3, 3
union
select 4, 3
),
game(n, x, y) as materialized (
select 1 AS n, x, y from generation1 -- generation 1 is initial board setup
union all
select n+1, new_x, new_y from -- generation n+1
(
select n, x+offset_x new_x, y+offset_y new_y, max(self) over (partition by n+1, x+offset_x, y+offset_y) cell_was_already_alive
from game, (
select x.n offset_x, y.n offset_y, case when x.n = 0 and y.n = 0 then 1 else 0 end self
from series x(n), series y(n) --join 2 row generators to get 9 pairs
) offsets_to_neighbours_and_self(offset_x, offset_y, self)
where n < 100
) all_impacts
group by n+1, new_x, new_y, cell_was_already_alive -- from all impacts back to cells
having (cell_was_already_alive=1 and count(*) < 5 and count(*) > 2) or count(*) = 3 --decide if cell is alive
)
select * from game where n=4 order by n, x, y; --select generation 4
----
4 3 2
4 3 3
4 3 4
query III
with recursive generation1(x,y) as materialized ( --the initial board setup
select 2, 3
union
select 3, 3
union
select 4, 3
),
game(n, x, y) as materialized (
select 1 AS n, x, y from generation1 -- generation 1 is initial board setup
union all
select n+1, new_x, new_y from -- generation n+1
(
select n, x+offset_x new_x, y+offset_y new_y, max(self) over (partition by n+1, x+offset_x, y+offset_y) cell_was_already_alive
from game, (
select x.n offset_x, y.n offset_y, case when x.n = 0 and y.n = 0 then 1 else 0 end self
from generate_series(-1,1) x(n), generate_series(-1,1) y(n) --join 2 row generators to get 9 pairs
) offsets_to_neighbours_and_self(offset_x, offset_y, self)
where n < 100
) all_impacts
group by n+1, new_x, new_y, cell_was_already_alive -- from all impacts back to cells
having (cell_was_already_alive=1 and count(*) < 5 and count(*) > 2) or count(*) = 3 --decide if cell is alive
)
select * from game where n=4 order by n, x, y; --select generation 4
----
4 3 2
4 3 3
4 3 4

View File

@@ -0,0 +1,18 @@
# name: test/sql/cte/materialized/incorrect_recursive_cte_materialized.test
# description: Incorrect recursive ctes
# group: [materialized]
# recursive CTE without UNION is just a normal CTE
query I
WITH RECURSIVE cte AS MATERIALIZED (SELECT 42) SELECT * FROM cte;
----
42
# we only support recursive ctes with union or union all
statement error
with recursive t as MATERIALIZED (select 1 as x intersect select x+1 from t where x < 3) select * from t order by x
----
statement error
with recursive t as MATERIALIZED (select 1 as x except select x+1 from t where x < 3) select * from t order by x
----

View File

@@ -0,0 +1,31 @@
# name: test/sql/cte/materialized/internal_3004.test
# description: INTERNAL Error: Attempted to access index 1 within vector of size 1 -> harlequin internal code, CTE related
# group: [materialized]
statement ok
with
system_types as (
select distinct
type_name as label,
'type' as type_label,
1000 as priority,
null as context
from duckdb_types()
where database_name = 'system'
),
custom_types as (
select distinct
type_name as label,
'type' as type_label,
1000 as priority,
schema_name as context
from duckdb_types()
where
database_name not in ('system', 'temp')
and type_name not in (select label from system_types)
)
select *
from system_types
union all
select *
from custom_types

View File

@@ -0,0 +1,37 @@
# name: test/sql/cte/materialized/materialized_cte_modifiers.test
# description: TopN should still work with materialized CTE (internal issue 2569)
# group: [materialized]
require tpcds
statement ok
call dsdgen(sf=0)
# q01
query II
explain
WITH customer_total_return AS
(SELECT sr_customer_sk AS ctr_customer_sk,
sr_store_sk AS ctr_store_sk,
sum(sr_return_amt) AS ctr_total_return
FROM store_returns,
date_dim
WHERE sr_returned_date_sk = d_date_sk
AND d_year = 2000
GROUP BY sr_customer_sk,
sr_store_sk)
SELECT c_customer_id
FROM customer_total_return ctr1,
store,
customer
WHERE ctr1.ctr_total_return >
(SELECT avg(ctr_total_return)*1.2
FROM customer_total_return ctr2
WHERE ctr1.ctr_store_sk = ctr2.ctr_store_sk)
AND s_store_sk = ctr1.ctr_store_sk
AND s_state = 'TN'
AND ctr1.ctr_customer_sk = c_customer_sk
ORDER BY c_customer_id
LIMIT 100;
----
physical_plan <REGEX>:.*TOP_N.*

View File

@@ -0,0 +1,51 @@
# name: test/sql/cte/materialized/materialized_cte_prepared.test
# description: Test DML statements with materialized Common Table Expressions (CTE)
# group: [materialized]
statement ok
PRAGMA enable_verification
require no_alternative_verify
statement ok
create table a(i integer);
statement ok
insert into a values (1), (2), (3), (NULL), (42), (84);
# prepare in materialized cte
statement ok
PREPARE v1 AS WITH t(x) AS MATERIALIZED (VALUES ($1))
DELETE FROM a WHERE i IN (FROM t);
query I
EXECUTE v1(42)
----
1
query I
FROM a ORDER BY 1
----
1
2
3
84
NULL
# prepare in both materialized cte and delete
statement ok
PREPARE v2 AS WITH t(x) AS MATERIALIZED (VALUES ($1))
DELETE FROM a WHERE (i + $2) IN (FROM t);
query I
EXECUTE v2(5, 2)
----
1
query I
FROM a ORDER BY 1
----
1
2
84
NULL

View File

@@ -0,0 +1,76 @@
# name: test/sql/cte/materialized/recursive_array_slice_materialized.test
# description: Issue #3005: array_slice prevents row values to be used more than once
# group: [materialized]
statement ok
PRAGMA enable_verification
statement ok
CREATE TABLE p(loc int8);
statement ok
INSERT INTO p VALUES (1);
query II
WITH RECURSIVE t(y, arr) AS MATERIALIZED
(
SELECT 1, array[1,2,3,4,5,6]
UNION ALL
SELECT y+1, arr[:loc]
FROM t, p
WHERE y < 10
) SELECT * FROM t;
----
1 [1, 2, 3, 4, 5, 6]
2 [1]
3 [1]
4 [1]
5 [1]
6 [1]
7 [1]
8 [1]
9 [1]
10 [1]
query II
WITH RECURSIVE t(y, arr) AS MATERIALIZED
(
SELECT 1, array[1,2,3,4,5,6]
UNION ALL
SELECT y+1, arr
FROM t, p
WHERE y < 10
AND y = loc
) SELECT * FROM t;
----
1 [1, 2, 3, 4, 5, 6]
2 [1, 2, 3, 4, 5, 6]
query II
WITH RECURSIVE t(y, arr) AS MATERIALIZED
(
SELECT 1, array[1,2,3,4,5,6]
UNION ALL
SELECT y+1, arr[:loc]
FROM t, p
WHERE y < 10
AND y = loc
) SELECT * FROM t;
----
1 [1, 2, 3, 4, 5, 6]
2 [1]
query I
WITH RECURSIVE t(arr) AS MATERIALIZED
(
SELECT array[1,2,3,4,5,6]
UNION ALL
SELECT arr[arr[1]+1:6]
FROM t
WHERE arr[1] < 6
) SELECT * FROM t;
----
[1, 2, 3, 4, 5, 6]
[2, 3, 4, 5, 6]
[4, 5, 6]
[]

View File

@@ -0,0 +1,133 @@
# name: test/sql/cte/materialized/recursive_cte_complex_pipelines.test
# description: Recursive CTEs with complex pipelines
# group: [materialized]
statement ok
PRAGMA enable_verification
# recursive CTE with various cross products
query I
WITH RECURSIVE t AS MATERIALIZED
(
SELECT 1 AS x
UNION
SELECT t1.x + t2.x + t3.x AS x
FROM t t1, t t2, t t3
WHERE t1.x < 100
)
SELECT * FROM t ORDER BY 1;
----
1
3
9
27
81
243
# what if we have different types?
query I
WITH RECURSIVE t AS MATERIALIZED
(
SELECT 1 AS x
UNION
SELECT (t1.x + t2.x + t3.x)::HUGEINT AS x
FROM t t1, t t2, t t3
WHERE t1.x < 100
)
SELECT * FROM t ORDER BY 1;
----
1
3
9
27
81
243
statement ok
CREATE TABLE a AS SELECT * FROM range(100) t1(i)
# recursive CTE with aggregates
query I
WITH RECURSIVE t AS MATERIALIZED
(
SELECT 1 AS x
UNION
SELECT SUM(x) AS x
FROM t, a
WHERE x < 1000000
)
SELECT * FROM t ORDER BY 1 NULLS LAST;
----
1
100
10000
1000000
NULL
# the same but with a hash join
query I
WITH RECURSIVE t AS MATERIALIZED
(
SELECT 1 AS x
UNION
SELECT SUM(x) AS x
FROM t, a
WHERE x < 1000000 AND t.x=a.i
)
SELECT * FROM t ORDER BY 1 NULLS LAST;
----
1
# nested aggregates
query I
WITH RECURSIVE t AS MATERIALIZED
(
SELECT 1 AS x
UNION
SELECT SUM(x)
FROM
(SELECT SUM(x) FROM t) t1(x), a
WHERE x < 1000
)
SELECT * FROM t ORDER BY 1 NULLS LAST;
----
1
100
10000
NULL
# non-correlated subqueries
query I
WITH RECURSIVE t AS MATERIALIZED
(
SELECT 1 AS x
UNION
SELECT (SELECT x + 1 FROM t) AS x
FROM t
WHERE x < 5
)
SELECT * FROM t ORDER BY 1 NULLS LAST;
----
1
2
3
4
5
# correlated subqueries
query I
WITH RECURSIVE t AS MATERIALIZED
(
SELECT 1 AS x
UNION
SELECT (SELECT t.x+t2.x FROM t t2 LIMIT 1) AS x
FROM t
WHERE x < 10
)
SELECT * FROM t ORDER BY 1 NULLS LAST;
----
1
2
4
8
16

View File

@@ -0,0 +1,33 @@
# name: test/sql/cte/materialized/recursive_cte_correlated_subquery_materialized.test_slow
# description: Issue #2713: reports struct_extract error when run a sql
# group: [materialized]
query I
WITH RECURSIVE
input(sud) AS MATERIALIZED (
VALUES('53..7....6..195....98....6.8...6...34..8.3..17...2...6.6....28....419..5....8..79')
),
digits(z, lp) AS MATERIALIZED (
SELECT CAST(lp+1 AS TEXT), lp::int+1 FROM generate_series(0,8,1) t(lp)
),
x(s, ind) AS MATERIALIZED (
SELECT sud, instr(sud, '.') FROM input
UNION ALL
SELECT
substr(s, 1, ind::int-1) || z || substr(s, ind::int+1),
instr(substr(s, 1, ind::int-1) || z || substr(s, ind::int+1), '.' )
FROM x, digits AS z
WHERE ind::int>0
AND NOT EXISTS (
SELECT 1
FROM digits AS lp
WHERE z.z = substr(s, ((ind::int-1)//9)*9 + lp, 1)
OR z.z = substr(s, ((ind::int-1)%9) + (lp-1)*9 + 1, 1)
OR z.z = substr(s, (((ind::int-1)//3) % 3) * 3
+ ((ind::int-1)//27) * 27 + lp
+ ((lp-1) // 3) * 6, 1)
)
)
SELECT s FROM x WHERE ind::int=0;
----
534678912672195348198342567859761423426853791713924856961537284287419635345286179

View File

@@ -0,0 +1,32 @@
# name: test/sql/cte/materialized/recursive_cte_error_materialized.test
# description: Recursive CTEs with an error thrown in the pipelines
# group: [materialized]
statement ok
PRAGMA enable_verification
statement ok
CREATE TABLE tag(id int, name string, subclassof int);
statement ok
INSERT INTO tag VALUES
(7, 'Music', 9),
(8, 'Movies', 9),
(9, 'Art', NULL)
;
statement error
WITH RECURSIVE tag_hierarchy(id, source, path, target) AS materialized (
SELECT id, name, name AS path, NULL AS target -- this should be '' for correct behaviour
FROM tag
WHERE subclassof IS NULL
UNION ALL
SELECT tag.id, tag.name, tag_hierarchy.path || ' <- ' || tag.name, tag.name AS target
FROM tag, tag_hierarchy
WHERE tag.subclassof = tag_hierarchy.id
)
SELECT source, path, target
FROM tag_hierarchy
;
----
<REGEX>:.*Conversion Error: Could not convert string.*

View File

@@ -0,0 +1,120 @@
# name: test/sql/cte/materialized/recursive_hang_2745_materialized.test
# description: Issue #2745: sql with RECURSIVE keyword but does not RECURSIVE hang
# group: [materialized]
statement ok
PRAGMA enable_verification
query III
with RECURSIVE parents_tab (id , value , parent )
as MATERIALIZED (values (1, 1, 2), (2, 2, 4), (3, 1, 4), (4, 2, -1), (5, 1, 2), (6, 2, 7), (7, 1, -1)
),
parents_tab2(id , value , parent )
as MATERIALIZED (values (1, 1, 2), (2, 2, 4), (3, 1, 4), (4, 2, -1), (5, 1, 2), (6, 2, 7), (7, 1, -1)
),
parents as MATERIALIZED (
select * from parents_tab
union all
select id, value+2, parent from parents_tab2
)
select * from parents ORDER BY id, value, parent;
----
1 1 2
1 3 2
2 2 4
2 4 4
3 1 4
3 3 4
4 2 -1
4 4 -1
5 1 2
5 3 2
6 2 7
6 4 7
7 1 -1
7 3 -1
query III
with RECURSIVE parents_tab (id , value , parent )
as MATERIALIZED (values (1, 1, 2), (2, 2, 4), (3, 1, 4), (4, 2, -1), (5, 1, 2), (6, 2, 7), (7, 1, -1)
),
parents_tab2(id , value , parent )
as MATERIALIZED (values (1, 1, 2), (2, 2, 4), (3, 1, 4), (4, 2, -1), (5, 1, 2), (6, 2, 7), (7, 1, -1)
)
select * from parents_tab
union all
select id, value+2, parent from parents_tab2 ORDER BY id, value, parent;
----
1 1 2
1 3 2
2 2 4
2 4 4
3 1 4
3 3 4
4 2 -1
4 4 -1
5 1 2
5 3 2
6 2 7
6 4 7
7 1 -1
7 3 -1
query III
with parents_tab (id , value , parent )
as MATERIALIZED (values (1, 1, 2), (2, 2, 4), (3, 1, 4), (4, 2, -1), (5, 1, 2), (6, 2, 7), (7, 1, -1)
),
parents_tab2(id , value , parent )
as MATERIALIZED (values (1, 1, 2), (2, 2, 4), (3, 1, 4), (4, 2, -1), (5, 1, 2), (6, 2, 7), (7, 1, -1)
),
parents as MATERIALIZED (
select * from parents_tab
union all
select id, value+2, parent from parents_tab2
)
select * from parents ORDER BY id, value, parent;
----
1 1 2
1 3 2
2 2 4
2 4 4
3 1 4
3 3 4
4 2 -1
4 4 -1
5 1 2
5 3 2
6 2 7
6 4 7
7 1 -1
7 3 -1
statement ok
create view vparents as
with RECURSIVE parents_tab (id , value , parent )
as MATERIALIZED (values (1, 1, 2), (2, 2, 4), (3, 1, 4), (4, 2, -1), (5, 1, 2), (6, 2, 7), (7, 1, -1)
),
parents_tab2 (id , value , parent )
as MATERIALIZED (values (1, 1, 2), (2, 2, 4), (3, 1, 4), (4, 2, -1), (5, 1, 2), (6, 2, 7), (7, 1, -1)
)
select * from parents_tab
union all
select id, value+2, parent from parents_tab2;
query III
select * from vparents ORDER BY id, value, parent;
----
1 1 2
1 3 2
2 2 4
2 4 4
3 1 4
3 3 4
4 2 -1
4 4 -1
5 1 2
5 3 2
6 2 7
6 4 7
7 1 -1
7 3 -1

View File

@@ -0,0 +1,11 @@
# name: test/sql/cte/materialized/test_bug_922_materialized.test
# description: Test for a crash reported in issue #922
# group: [materialized]
statement ok
PRAGMA enable_verification
query I
WITH my_list(value) AS MATERIALIZED (VALUES (1), (2), (3))
SELECT * FROM my_list LIMIT 0 OFFSET 1
----

View File

@@ -0,0 +1,265 @@
# name: test/sql/cte/materialized/test_correlated_recursive_cte_materialized.test
# description: Test Materialized Correlated Recursive Common Table Expressions (CTE)
# group: [materialized]
statement ok
PRAGMA enable_verification
# Correlation in the initialization query
query II
SELECT x, y
FROM generate_series(1,4) AS _(x), LATERAL
(WITH RECURSIVE t(y) AS MATERIALIZED (
SELECT _.x
UNION ALL
SELECT y + 1
FROM t
WHERE y < 3
)
SELECT * FROM t) AS t
ORDER BY x, y;
----
1 1
1 2
1 3
2 2
2 3
3 3
4 4
# Correlation in the recursive query
query II
SELECT x, y
FROM generate_series(1,4) AS _(x), LATERAL
(WITH RECURSIVE t(y) AS MATERIALIZED (
SELECT 1
UNION ALL
SELECT y + _.x
FROM t
WHERE y < 3
)
SELECT * FROM t) AS t
ORDER BY x, y;
----
1 1
1 2
1 3
2 1
2 3
3 1
3 4
4 1
4 5
# Correlation in the initialization and recursive query
query II
SELECT x, y
FROM generate_series(1,4) AS _(x), LATERAL
(WITH RECURSIVE t(y) AS MATERIALIZED (
SELECT _.x
UNION ALL
SELECT y + _.x
FROM t
WHERE y < 3
)
SELECT * FROM t) AS t
ORDER BY x, y;
----
1 1
1 2
1 3
2 2
2 4
3 3
4 4
# Correlation with multiple recursive anchors
query II
SELECT x, y
FROM generate_series(1,4) AS _(x), LATERAL
(WITH RECURSIVE t(y) AS MATERIALIZED (
SELECT _.x
UNION ALL
SELECT t1.y + t2.y + _.x
FROM t AS t1, t AS t2
WHERE t1.y < 3
)
SELECT * FROM t) AS t
ORDER BY x, y;
----
1 1
1 3
2 2
2 6
3 3
4 4
# Test correlation in SELECT clause
query III rowsort
SELECT x, y, (WITH RECURSIVE t(z) AS MATERIALIZED (
SELECT x + y
UNION ALL
SELECT z + 1
FROM t
WHERE z < 3
) SELECT sum(z) FROM t) AS z
FROM generate_series(1,2) AS _(x), generate_series(1,2) AS __(y) order by all;
----
1 1 5
1 2 3
2 1 3
2 2 4
# Complex nested recursive query
query III rowsort
SELECT x, y, (WITH RECURSIVE t(z) AS MATERIALIZED (
SELECT x + y
UNION ALL
SELECT z + 1
FROM (WITH RECURSIVE g(a) AS MATERIALIZED (
SELECT t.z
FROM t
UNION ALL
SELECT g.a + (x + y) / 2
FROM g
WHERE g.a < 3)
SELECT * FROM g) AS t(z)
WHERE z < 5
) SELECT sum(z) FROM t) AS z
FROM generate_series(1,2) AS _(x), generate_series(1,2) AS __(y) order by all;
----
1 1 23
1 2 12
2 1 12
2 2 9
# UNION semantics
# Correlation in the initialization query
query II
SELECT x, y
FROM generate_series(1,4) AS _(x), LATERAL
(WITH RECURSIVE t(y) AS MATERIALIZED (
SELECT _.x
UNION
SELECT y + 1
FROM t
WHERE y < 3
)
SELECT * FROM t) AS t
ORDER BY x, y;
----
1 1
1 2
1 3
2 2
2 3
3 3
4 4
# Correlation in the recursive query
query II
SELECT x, y
FROM generate_series(1,4) AS _(x), LATERAL
(WITH RECURSIVE t(y) AS MATERIALIZED (
SELECT 1
UNION
SELECT y + _.x
FROM t
WHERE y < 3
)
SELECT * FROM t) AS t
ORDER BY x, y;
----
1 1
1 2
1 3
2 1
2 3
3 1
3 4
4 1
4 5
# Correlation in the initialization and recursive query
query II
SELECT x, y
FROM generate_series(1,4) AS _(x), LATERAL
(WITH RECURSIVE t(y) AS MATERIALIZED (
SELECT _.x
UNION
SELECT y + _.x
FROM t
WHERE y < 3
)
SELECT * FROM t) AS t
ORDER BY x, y;
----
1 1
1 2
1 3
2 2
2 4
3 3
4 4
# Correlation with multiple recursive anchors
query II
SELECT x, y
FROM generate_series(1,4) AS _(x), LATERAL
(WITH RECURSIVE t(y) AS MATERIALIZED (
SELECT _.x
UNION
SELECT t1.y + t2.y + _.x
FROM t AS t1, t AS t2
WHERE t1.y < 3
)
SELECT * FROM t) AS t
ORDER BY x, y;
----
1 1
1 3
2 2
2 6
3 3
4 4
# Test correlation in SELECT clause
query III rowsort
SELECT x, y, (WITH RECURSIVE t(z) AS MATERIALIZED (
SELECT x + y
UNION
SELECT z + 1
FROM t
WHERE z < 3
) SELECT sum(z) FROM t) AS z
FROM generate_series(1,2) AS _(x), generate_series(1,2) AS __(y) order by all;
----
1 1 5
1 2 3
2 1 3
2 2 4
# Complex nested recursive query
query III rowsort
SELECT x, y, (WITH RECURSIVE t(z) AS MATERIALIZED (
SELECT x + y
UNION
SELECT z + 1
FROM (WITH RECURSIVE g(a) AS MATERIALIZED (
SELECT t.z
FROM t
UNION
SELECT g.a + (x + y) / 2
FROM g
WHERE g.a < 3)
SELECT * FROM g) AS t(z)
WHERE z < 5
) SELECT sum(z) FROM t) AS z
FROM generate_series(1,2) AS _(x), generate_series(1,2) AS __(y) order by all;
----
1 1 14
1 2 12
2 1 12
2 2 9

View File

@@ -0,0 +1,70 @@
# name: test/sql/cte/materialized/test_cte_in_cte_materialized.test
# description: Test Nested Common Table Expressions (CTE)
# group: [materialized]
statement ok
PRAGMA enable_verification
statement ok
create table a(i integer);
statement ok
insert into a values (42);
query I
with cte1 as MATERIALIZED (Select i as j from a) select * from cte1;
----
42
query I
with cte1 as MATERIALIZED (with b as MATERIALIZED (Select i as j from a) Select j from b) select x from cte1 t1(x);
----
42
query I
with cte1(xxx) as MATERIALIZED (with ncte(yyy) as MATERIALIZED (Select i as j from a) Select yyy from ncte) select xxx from cte1;
----
42
query II
with cte1 as MATERIALIZED (with b as MATERIALIZED (Select i as j from a) select j from b), cte2 as MATERIALIZED (with c as MATERIALIZED (select ref.j+1 as k from cte1 as ref) select k from c) select * from cte1 , cte2;
----
42 43
# duplicate CTE alias
statement error
with cte1 as MATERIALIZED (select 42), cte1 as MATERIALIZED (select 42) select * FROM cte1;
----
<REGEX>:.*Parser Error: Duplicate CTE name.*
# refer to CTE in subquery tableref
query I
with cte1 as MATERIALIZED (Select i as j from a) select * from (with cte2 as MATERIALIZED (select max(j) as j from cte1) select * from cte2) f
----
42
# refer to CTE in subquery expression
query I
with cte1 as MATERIALIZED (Select i as j from a) select * from cte1 where j = (with cte2 as MATERIALIZED (select max(j) as j from cte1) select j from cte2);
----
42
require no_alternative_verify
# same name, both get materialized with ALTERNATIVE_VERIFY, so we need 'no_alternative_verify'
query I
with cte as materialized (Select i as j from a) select * from cte where j = (with cte as (select max(j) as j from cte) select j from cte);
----
42
# refer to same-named CTE in a subquery expression
query I
with cte as MATERIALIZED (Select i as j from a) select * from cte where j = (with cte as MATERIALIZED (select max(j) as j from cte) select j from cte);
----
42
# self-refer to non-existent cte
statement error
with cte as MATERIALIZED (select * from cte) select * from cte
----
<REGEX>:.*Binder Error.*Circular reference to CTE.*

View File

@@ -0,0 +1,154 @@
# name: test/sql/cte/materialized/test_cte_materialized.test
# description: Test Common Table Expressions (CTE)
# group: [materialized]
statement ok
PRAGMA enable_verification
statement ok
create table a(i integer);
statement ok
insert into a values (42);
query I
with cte1 as MATERIALIZED (Select i as j from a) select * from cte1;
----
42
query I
with cte1 as MATERIALIZED (Select i as j from a) select x from cte1 t1(x);
----
42
query I
with cte1(xxx) as MATERIALIZED (Select i as j from a) select xxx from cte1;
----
42
query I
with cte1(xxx) as MATERIALIZED (Select i as j from a) select x from cte1 t1(x);
----
42
query II
with cte1 as MATERIALIZED (Select i as j from a), cte2 as MATERIALIZED (select ref.j as k from cte1 as ref), cte3 as MATERIALIZED (select ref2.j+1 as i from cte1 as ref2) select * from cte2 , cte3;
----
42 43
query I
with cte1 as MATERIALIZED (select i as j from a), cte2 as MATERIALIZED (select ref.j as k from cte1 as ref), cte3 as MATERIALIZED (select ref2.j+1 as i from cte1 as ref2) select * from cte2 union all select * FROM cte3;
----
42
43
# duplicate CTE alias
statement error
with cte1 as MATERIALIZED (select 42), cte1 as MATERIALIZED (select 42) select * FROM cte1;
----
# reference to CTE before its actually defined
statement error
with cte3 as MATERIALIZED (select ref2.j as i from cte1 as ref2), cte1 as MATERIALIZED (Select i as j from a), cte2 as MATERIALIZED (select ref.j+1 as k from cte1 as ref) select * from cte2 union all select * FROM cte3;
----
# multiple uses of same CTE
query II
with cte1 as MATERIALIZED (Select i as j from a) select * from cte1 cte11, cte1 cte12;
----
42 42
# refer to CTE in subquery
query I
with cte1 as MATERIALIZED (Select i as j from a) select * from cte1 where j = (select max(j) from cte1 as cte2);
----
42
# multi-column name alias
query II
with cte1(x, y) as MATERIALIZED (select 42 a, 84 b) select zzz, y from cte1 t1(zzz);
----
42 84
# use a CTE in a view definition
statement ok
create view va AS (with cte as MATERIALIZED (Select i as j from a) select * from cte);
query I
select * from va
----
42
# nested CTE views that re-use CTE aliases
query I
with cte AS MATERIALIZED (SELECT * FROM va) SELECT * FROM cte;
----
42
# multiple ctes in a view definition
statement ok
create view vb AS (with cte1 as MATERIALIZED (Select i as j from a), cte2 as MATERIALIZED (select ref.j+1 as k from cte1 as ref) select * from cte2);
query I
select * from vb
----
43
# cte in set operation node
query I
SELECT 1 UNION ALL (WITH cte AS MATERIALIZED (SELECT 42) SELECT * FROM cte);
----
1
42
# cte in recursive cte
query I
WITH RECURSIVE cte(d) AS MATERIALIZED (
SELECT 1
UNION ALL
(WITH c(d) AS (SELECT * FROM cte)
SELECT d + 1
FROM c
WHERE FALSE
)
)
SELECT max(d) FROM cte;
----
1
# test CTE with nested aliases in where clause
query II
with cte (a) as MATERIALIZED (
select 1
)
select
a as alias1,
alias1 as alias2
from cte
where alias2 > 0;
----
1 1
# test materialized CTE in recursive CTE
query II
WITH RECURSIVE t(x,v) AS (
SELECT 1, ARRAY[] :: int[]
UNION ALL
(WITH u(x) AS MATERIALIZED (SELECT 1)
SELECT f.x, (SELECT array_agg(x) FROM u)
FROM t, LATERAL (SELECT t.x + 1) AS f(x)
WHERE t.x < 5
)
) SELECT * FROM t ORDER BY x;
----
1 []
2 [1]
3 [1]
4 [1]
5 [1]
query I
SELECT * FROM (WITH t(x) AS MATERIALIZED (SELECT * FROM generate_series(1,10) LIMIT 75%) SELECT * FROM t LIMIT 80%) AS _(x) ORDER BY x LIMIT 50%;
----
1
2

View File

@@ -0,0 +1,17 @@
# name: test/sql/cte/materialized/test_cte_overflow_materialized.test
# description: Ensure no stack overflow for CTE names that match existing tables
# group: [materialized]
statement ok
create table a (id integer)
statement ok
insert into a values (1729)
statement ok
create view va as (with v as MATERIALIZED (select * from a) select * from v)
query I
with a as MATERIALIZED (select * from va) select * from a
----
1729

View File

@@ -0,0 +1,28 @@
# name: test/sql/cte/materialized/test_issue_10260.test
# description: Issue #10260: MATERIALIZED causes Binder Error: table has duplicate column name
# group: [materialized]
statement ok
PRAGMA enable_verification
statement ok
CREATE TABLE T0(C1 INT);
statement ok
CREATE TABLE T1(C1 INT);
statement ok
INSERT INTO T0(C1) VALUES (1);
statement ok
INSERT INTO T1(C1) VALUES (1);
query I
WITH CTE AS MATERIALIZED (
SELECT A1, * FROM T0
LEFT JOIN (
SELECT C1 AS A1 FROM T1
) ON T0.C1 = A1
) SELECT A1 FROM CTE;
----
1

View File

@@ -0,0 +1,86 @@
# name: test/sql/cte/materialized/test_materialized_cte.test
# description: Test Materialized Common Table Expressions (CTE)
# group: [materialized]
statement ok
PRAGMA enable_verification
query I
WITH t(x) AS MATERIALIZED (SELECT 1) SELECT * FROM t;
----
1
query II
WITH t(x) AS MATERIALIZED (SELECT t FROM generate_series(1,3) AS _(t)) SELECT t1.x,1 as y FROM t AS t1 ORDER BY x;
----
1 1
2 1
3 1
query II
WITH t(x) AS MATERIALIZED (SELECT t FROM generate_series(1,3) AS _(t)) SELECT t1.x, t1.x FROM t AS t1 ORDER BY x;
----
1 1
2 2
3 3
query II
WITH t(x) AS MATERIALIZED (SELECT t FROM generate_series(1,3) AS _(t)) SELECT t1.x, t2.x FROM t AS t1, t AS t2 ORDER BY t1.x, t2.x;
----
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
query II
WITH t(x) AS MATERIALIZED (SELECT 1),
u(x) AS MATERIALIZED (SELECT 2)
SELECT *
FROM u FULL OUTER JOIN t ON TRUE;
----
2 1
query I
WITH t(x) AS MATERIALIZED (SELECT x FROM generate_series(1,10) AS _(x) limit 4) SELECT DISTINCT x FROM t order by x desc;
----
4
3
2
1
query I
WITH t(x) AS MATERIALIZED (SELECT x FROM generate_series(1,10) AS _(x) limit 4) SELECT DISTINCT x FROM t order by x desc LIMIT 2;
----
4
3
query I
WITH t(x) AS MATERIALIZED (
WITH u(x) AS MATERIALIZED (
SELECT 42
) SELECT * FROM u
) SELECT * FROM t;
----
42
query I
WITH t(x) AS MATERIALIZED (SELECT 1),
u(x) AS MATERIALIZED (SELECT x+1 FROM t)
TABLE u UNION ALL TABLE t;
----
2
1
statement error
WITH t0(x) AS MATERIALIZED (
SELECT x FROM t1
), t1(x) AS MATERIALIZED (
SELECT 1
)
SELECT * FROM t0;
----

View File

@@ -0,0 +1,59 @@
# name: test/sql/cte/materialized/test_nested_recursive_cte_materialized.test
# description: Test Nested Recursive Common Table Expressions (CTE)
# group: [materialized]
statement ok
PRAGMA enable_verification
query I
WITH RECURSIVE t(x) AS MATERIALIZED
(
SELECT 1
UNION ALL
SELECT x+1
FROM t
WHERE x < 4
),
u(x) AS MATERIALIZED
(
SELECT *
FROM t
UNION ALL
SELECT u.x * 2 + t.x
FROM u, t
WHERE u.x < 32
)
SELECT *
FROM u
ORDER BY x
LIMIT 5;
----
1
2
3
3
4
query III
WITH RECURSIVE collatz(x, t, steps) AS MATERIALIZED
(
SELECT x, x, 0
FROM (WITH RECURSIVE n(t) AS (SELECT 1 UNION ALL SELECT t+1 FROM n WHERE t < 10) SELECT * FROM n) AS _(x)
UNION ALL
(SELECT x, CASE WHEN t%2 = 1 THEN t * 3 + p ELSE t / 2 END, steps + p
FROM collatz, (WITH RECURSIVE n(t) AS (SELECT 1 UNION ALL SELECT t+1 FROM n WHERE t < 1) SELECT * FROM n) AS _(p)
WHERE t <> 1)
)
SELECT * FROM collatz WHERE t = 1
ORDER BY x;
----
1 1 0
2 1 1
3 1 7
4 1 2
5 1 5
6 1 8
7 1 16
8 1 3
9 1 19
10 1 6

View File

@@ -0,0 +1,30 @@
# name: test/sql/cte/materialized/test_outer_joins_recursive_cte_materialized.test
# description: Test Recursive Common Table Expressions (CTE) with outer joins
# group: [materialized]
statement ok
PRAGMA enable_verification
statement ok
CREATE TABLE v(x INT);
statement ok
INSERT INTO v
VALUES
(1),(2),(3);
query II
WITH RECURSIVE t(x) AS MATERIALIZED
(
SELECT 1
UNION ALL
SELECT x + 1
FROM (SELECT t.x+1 FROM v AS _(p) FULL OUTER JOIN t ON t.x = p) AS _(x)
WHERE x < 10
) SELECT * FROM v AS _(p) RIGHT OUTER JOIN t ON t.x = p ORDER BY p, x NULLS LAST;
----
1 1
3 3
NULL 5
NULL 7
NULL 9

View File

@@ -0,0 +1,141 @@
# name: test/sql/cte/materialized/test_recursive_cte_tutorial_materialized.test
# description: Test Recursive CTEs from the CyberTec tutorial: https://www.cybertec-postgresql.com/en/recursive-queries-postgresql/
# group: [materialized]
statement ok
PRAGMA enable_verification
statement ok
CREATE TABLE emp (empno INTEGER PRIMARY KEY,
ename VARCHAR,
job VARCHAR,
mgr INTEGER,
hiredate DATE,
sal DOUBLE,
comm DOUBLE,
deptno INTEGER);
statement ok
INSERT INTO emp VALUES (7839, 'KING', 'PRESIDENT', NULL, DATE '1981-11-17', 5000.00, NULL, 10);
INSERT INTO emp VALUES (7698, 'BLAKE', 'MANAGER', 7839, DATE '1981-05-01', 2850.00, NULL, 30);
INSERT INTO emp VALUES (7782, 'CLARK', 'MANAGER', 7839, DATE '1981-06-09', 2450.00, NULL, 10);
INSERT INTO emp VALUES (7566, 'JONES', 'MANAGER', 7839, DATE '1981-04-02', 2975.00, NULL, 20);
INSERT INTO emp VALUES (7902, 'FORD', 'ANALYST', 7566, DATE '1981-12-03', 3000.00, NULL, 20);
INSERT INTO emp VALUES (7369, 'SMITH', 'CLERK', 7902, DATE '1980-12-17', 800.00, NULL, 20);
INSERT INTO emp VALUES (7499, 'ALLEN', 'SALESMAN', 7698, DATE '1981-02-20', 1600.00, 300.00, 30);
INSERT INTO emp VALUES (7521, 'WARD', 'SALESMAN', 7698, DATE '1981-02-22', 1250.00, 500.00, 30);
INSERT INTO emp VALUES (7654, 'MARTIN', 'SALESMAN', 7698, DATE '1981-09-28', 1250.00, 1400.00, 30);
INSERT INTO emp VALUES (7844, 'TURNER', 'SALESMAN', 7698, DATE '1981-09-08', 1500.00, 0.00, 30);
INSERT INTO emp VALUES (7900, 'JAMES', 'CLERK', 7698, DATE '1981-12-03', 950.00, NULL, 30);
INSERT INTO emp VALUES (7934, 'MILLER', 'CLERK', 7782, DATE '1982-01-23', 1300.00, NULL, 10);
query II
WITH RECURSIVE ctename AS MATERIALIZED (
SELECT empno, ename
FROM emp
WHERE empno = 7566
UNION ALL
SELECT emp.empno, emp.ename
FROM emp
JOIN ctename ON emp.mgr = ctename.empno
)
SELECT * FROM ctename;
----
7566 JONES
7902 FORD
7369 SMITH
query III
WITH RECURSIVE ctename AS MATERIALIZED (
SELECT empno, ename,
0 AS level
FROM emp
WHERE empno = 7566
UNION ALL
SELECT emp.empno, emp.ename,
ctename.level + 1
FROM emp
JOIN ctename ON emp.mgr = ctename.empno
)
SELECT * FROM ctename;
----
7566 JONES 0
7902 FORD 1
7369 SMITH 2
query III
WITH RECURSIVE ctename AS MATERIALIZED (
SELECT empno, ename,
ename AS path
FROM emp
WHERE empno = 7566
UNION ALL
SELECT emp.empno, emp.ename,
ctename.path || ' -> ' || emp.ename
FROM emp
JOIN ctename ON emp.mgr = ctename.empno
)
SELECT * FROM ctename;
----
7566 JONES JONES
7902 FORD JONES -> FORD
7369 SMITH JONES -> FORD -> SMITH
statement ok
CREATE VIEW ctenames AS (
WITH RECURSIVE ctename AS MATERIALIZED (
SELECT empno, ename,
ename AS path
FROM emp
WHERE empno = 7566
UNION ALL
SELECT emp.empno, emp.ename,
ctename.path || ' -> ' || emp.ename
FROM emp
JOIN ctename ON emp.mgr = ctename.empno
)
SELECT * FROM ctename
);
query III
SELECT * FROM ctenames;
----
7566 JONES JONES
7902 FORD JONES -> FORD
7369 SMITH JONES -> FORD -> SMITH
query II
WITH RECURSIVE fib AS MATERIALIZED (
SELECT 1 AS n,
1::bigint AS "fibₙ",
1::bigint AS "fibₙ₊₁"
UNION ALL
SELECT n+1,
"fibₙ₊₁",
"fibₙ" + "fibₙ₊₁"
FROM fib
WHERE n <= 20
)
SELECT n, "fibₙ" FROM fib
LIMIT 20;
----
1 1
2 1
3 2
4 3
5 5
6 8
7 13
8 21
9 34
10 55
11 89
12 144
13 233
14 377
15 610
16 987
17 1597
18 2584
19 4181
20 6765

View File

@@ -0,0 +1,118 @@
# name: test/sql/cte/materialized/test_recursive_cte_union_all_materialized.test
# description: Test Recursive Common Table Expressions UNION ALL (CTE)
# group: [materialized]
statement ok
PRAGMA enable_verification
# simple recursive CTE
query I
with recursive t as MATERIALIZED (select 1 as x union all select x+1 from t where x < 3) select * from t
----
1
2
3
# simple recursive CTE with an alias
query I
with recursive t as MATERIALIZED (select 1 as x union all select x+1 from t as m where m.x < 3) select * from t
----
1
2
3
# recursive CTE with multiple references and aliases
query I
with recursive t as MATERIALIZED (select 1 as x union all select m.x+f.x from t as m, t as f where m.x < 3) select * from t
----
1
2
4
# strings and multiple columns
query IT
with recursive t as MATERIALIZED (select 1 as x, 'hello' as y union all select x+1, y || '-' || 'hello' from t where x < 3) select * from t;
----
1 hello
2 hello-hello
3 hello-hello-hello
# referencing same CTE multiple times
query I
with recursive t as MATERIALIZED (select 1 as x union all select x+1 from t where x < 3) select min(a1.x) from t a1, t a2;
----
1
# nested uncorrelated subquery
query I
with recursive t as MATERIALIZED (select 1 as x union all select x+(SELECT 1) from t where x < 3) select * from t;
----
1
2
3
# use with recursive in table creation
statement ok
create table integers as with recursive t as MATERIALIZED (select 1 as x union all select x+1 from t where x < 3) select * from t;
# more complex uncorrelated subquery
query I
with recursive t as MATERIALIZED (select (select min(x) from integers) as x union all select x+1 from t where x < 3) select * from t;
----
1
2
3
# aggregate function
query I
with recursive t as MATERIALIZED (select 1 as x union all select sum(x+1) AS x from t where x < 3 group by x) select * from t
----
1
2
3
# recursive CTE with table-producing function
query I
WITH RECURSIVE t AS MATERIALIZED (
SELECT 1 AS i
UNION ALL
SELECT j
FROM t, generate_series(0, 10, 1) series(j)
WHERE j=i+1
)
SELECT * FROM t;
----
1
2
3
4
5
6
7
8
9
10
# order by is not allowed in the recursive term of ctes
statement error
with recursive t as MATERIALIZED (select 1 as x union all select x+1 from t where x < 3 order by x) select * from t
----
<REGEX>:.*Parser Error.*recursive query is not allowed.*
# limit is not allowed in the recursive term of ctes
statement error
with recursive t as MATERIALIZED (select 1 as x union all select x+1 from t where x < 3 LIMIT 1) select * from t
----
<REGEX>:.*Parser Error.*recursive query is not allowed.*
# offset is not allowed in the recursive term of ctes
statement error
with recursive t as MATERIALIZED (select 1 as x union all select x+1 from t where x < 3 OFFSET 1) select * from t
----
<REGEX>:.*Parser Error.*recursive query is not allowed.*
# offset is not allowed in the recursive term of ctes
statement error
with recursive t as MATERIALIZED (select 1 as x union all select x+1 from t where x < 3 LIMIT 1 OFFSET 1) select * from t
----
<REGEX>:.*Parser Error.*recursive query is not allowed.*

View File

@@ -0,0 +1,140 @@
# name: test/sql/cte/materialized/test_recursive_cte_union_materialized.test
# description: Test Recursive Common Table Expressions UNION (CTE)
# group: [materialized]
statement ok
PRAGMA enable_verification
# simple recursive CTE
query I
with recursive t as MATERIALIZED (select 1 as x union select x+1 from t where x < 3) select * from t order by x
----
1
2
3
query I
with recursive t(x) as MATERIALIZED (select 1 union select x+1 from t where x < 3) select * from t order by x
----
1
2
3
# test some aliases
query I
with recursive t(x) as MATERIALIZED (select 1 union select x+1 from t where x < 3) select zz from t t1(zz) order by zz
----
1
2
3
query I
with recursive t(x) as MATERIALIZED (select 1 union select zzz+1 from t t1(zzz) where zzz < 3) select zz from t t1(zz) order by zz
----
1
2
3
# UNION semantics prevents infinite loop here
query I
with recursive t as MATERIALIZED (select 1 as x union select x from t) select * from t
----
1
# simple recursive CTE with an alias
query I
with recursive t as MATERIALIZED (select 1 as x union select x+1 from t as m where m.x < 3) select * from t order by x
----
1
2
3
# recursive CTE with multiple references and aliases
query I
with recursive t as MATERIALIZED (select 1 as x union select m.x+f.x from t as m, t as f where m.x < 3) select * from t order by x
----
1
2
4
# strings and multiple columns
query IT
with recursive t as MATERIALIZED (select 1 as x, 'hello' as y union select x+1, y || '-' || 'hello' from t where x < 3) select * from t order by x;
----
1 hello
2 hello-hello
3 hello-hello-hello
# referencing same CTE multiple times
query I
with recursive t as MATERIALIZED (select 1 as x union select x+1 from t where x < 3) select min(a1.x) from t a1, t a2;
----
1
# nested uncorrelated subquery
query I
with recursive t as MATERIALIZED (select 1 as x union select x+(SELECT 1) from t where x < 3) select * from t order by x;
----
1
2
3
# correlated subquery
query I
with recursive t as MATERIALIZED (select 1 as x union select x+(SELECT 1+t.x) from t where x < 5) select * from t order by x;
----
1
3
7
# use with recursive in table creation
statement ok
create table integers as with recursive t as MATERIALIZED (select 1 as x union select x+1 from t where x < 3) select * from t;
# more complex uncorrelated subquery
query I
with recursive t as MATERIALIZED (select (select min(x) from integers) as x union select x+1 from t where x < 3) select * from t order by x;
----
1
2
3
# aggregate functions
query I
with recursive t as MATERIALIZED (select 1 as x union select sum(x+1) from t where x < 3) select * from t order by 1 nulls last
----
1
2
3
NULL
# order by is not allowed in the recursive term of ctes
statement error
with recursive t as MATERIALIZED (select 1 as x union select sum(x+1) from t where x < 3 order by x) select * from t
----
# limit is not allowed in the recursive term of ctes
statement error
with recursive t as MATERIALIZED (select 1 as x union select sum(x+1) from t where x < 3 LIMIT 1) select * from t
----
# offset is not allowed in the recursive term of ctes
statement error
with recursive t as MATERIALIZED (select 1 as x union select sum(x+1) from t where x < 3 OFFSET 1) select * from t
----
# offset is not allowed in the recursive term of ctes
statement error
with recursive t as MATERIALIZED (select 1 as x union select sum(x+1) from t where x < 3 LIMIT 1 OFFSET 1) select * from t
----
# create a view from a recursive cte
statement ok
create view vr as (with recursive t(x) as MATERIALIZED (select 1 union select x+1 from t where x < 3) select * from t order by x)
query I
select * from vr
----
1
2
3

View File

@@ -0,0 +1,76 @@
# name: test/sql/cte/recursive_array_slice.test
# description: Issue #3005: array_slice prevents row values to be used more than once
# group: [cte]
statement ok
PRAGMA enable_verification
statement ok
CREATE TABLE p(loc int8);
statement ok
INSERT INTO p VALUES (1);
query II
WITH RECURSIVE t(y, arr) AS
(
SELECT 1, array[1,2,3,4,5,6]
UNION ALL
SELECT y+1, arr[:loc]
FROM t, p
WHERE y < 10
) SELECT * FROM t;
----
1 [1, 2, 3, 4, 5, 6]
2 [1]
3 [1]
4 [1]
5 [1]
6 [1]
7 [1]
8 [1]
9 [1]
10 [1]
query II
WITH RECURSIVE t(y, arr) AS
(
SELECT 1, array[1,2,3,4,5,6]
UNION ALL
SELECT y+1, arr
FROM t, p
WHERE y < 10
AND y = loc
) SELECT * FROM t;
----
1 [1, 2, 3, 4, 5, 6]
2 [1, 2, 3, 4, 5, 6]
query II
WITH RECURSIVE t(y, arr) AS
(
SELECT 1, array[1,2,3,4,5,6]
UNION ALL
SELECT y+1, arr[:loc]
FROM t, p
WHERE y < 10
AND y = loc
) SELECT * FROM t;
----
1 [1, 2, 3, 4, 5, 6]
2 [1]
query I
WITH RECURSIVE t(arr) AS
(
SELECT array[1,2,3,4,5,6]
UNION ALL
SELECT arr[arr[1]+1:6]
FROM t
WHERE arr[1] < 6
) SELECT * FROM t;
----
[1, 2, 3, 4, 5, 6]
[2, 3, 4, 5, 6]
[4, 5, 6]
[]

View File

@@ -0,0 +1,133 @@
# name: test/sql/cte/recursive_cte_complex_pipelines.test
# description: Recursive CTEs with complex pipelines
# group: [cte]
statement ok
PRAGMA enable_verification
# recursive CTE with various cross products
query I
WITH RECURSIVE t AS
(
SELECT 1 AS x
UNION
SELECT t1.x + t2.x + t3.x AS x
FROM t t1, t t2, t t3
WHERE t1.x < 100
)
SELECT * FROM t ORDER BY 1;
----
1
3
9
27
81
243
# what if we have different types?
query I
WITH RECURSIVE t AS
(
SELECT 1 AS x
UNION
SELECT (t1.x + t2.x + t3.x)::HUGEINT AS x
FROM t t1, t t2, t t3
WHERE t1.x < 100
)
SELECT * FROM t ORDER BY 1;
----
1
3
9
27
81
243
statement ok
CREATE TABLE a AS SELECT * FROM range(100) t1(i)
# recursive CTE with aggregates
query I
WITH RECURSIVE t AS
(
SELECT 1 AS x
UNION
SELECT SUM(x) AS x
FROM t, a
WHERE x < 1000000
)
SELECT * FROM t ORDER BY 1 NULLS LAST;
----
1
100
10000
1000000
NULL
# the same but with a hash join
query I
WITH RECURSIVE t AS
(
SELECT 1 AS x
UNION
SELECT SUM(x) AS x
FROM t, a
WHERE x < 1000000 AND t.x=a.i
)
SELECT * FROM t ORDER BY 1 NULLS LAST;
----
1
# nested aggregates
query I
WITH RECURSIVE t AS
(
SELECT 1 AS x
UNION
SELECT SUM(x)
FROM
(SELECT SUM(x) FROM t) t1(x), a
WHERE x < 1000
)
SELECT * FROM t ORDER BY 1 NULLS LAST;
----
1
100
10000
NULL
# non-correlated subqueries
query I
WITH RECURSIVE t AS
(
SELECT 1 AS x
UNION
SELECT (SELECT x + 1 FROM t) AS x
FROM t
WHERE x < 5
)
SELECT * FROM t ORDER BY 1 NULLS LAST;
----
1
2
3
4
5
# correlated subqueries
query I
WITH RECURSIVE t AS
(
SELECT 1 AS x
UNION
SELECT (SELECT t.x+t2.x FROM t t2 LIMIT 1) AS x
FROM t
WHERE x < 10
)
SELECT * FROM t ORDER BY 1 NULLS LAST;
----
1
2
4
8
16

View File

@@ -0,0 +1,33 @@
# name: test/sql/cte/recursive_cte_correlated_subquery.test_slow
# description: Issue #2713: reports struct_extract error when run a sql
# group: [cte]
query I
WITH RECURSIVE
input(sud) AS (
VALUES('53..7....6..195....98....6.8...6...34..8.3..17...2...6.6....28....419..5....8..79')
),
digits(z, lp) AS (
SELECT CAST(lp+1 AS TEXT), lp::int+1 FROM generate_series(0,8,1) t(lp)
),
x(s, ind) AS (
SELECT sud, instr(sud, '.') FROM input
UNION ALL
SELECT
substr(s, 1, ind::int-1) || z || substr(s, ind::int+1),
instr(substr(s, 1, ind::int-1) || z || substr(s, ind::int+1), '.' )
FROM x, digits AS z
WHERE ind::int>0
AND NOT EXISTS (
SELECT 1
FROM digits AS lp
WHERE z.z = substr(s, ((ind::int-1)//9)*9 + lp, 1)
OR z.z = substr(s, ((ind::int-1)%9) + (lp-1)*9 + 1, 1)
OR z.z = substr(s, (((ind::int-1)//3) % 3) * 3
+ ((ind::int-1)//27) * 27 + lp
+ ((lp-1) // 3) * 6, 1)
)
)
SELECT s FROM x WHERE ind::int=0;
----
534678912672195348198342567859761423426853791713924856961537284287419635345286179

View File

@@ -0,0 +1,32 @@
# name: test/sql/cte/recursive_cte_error.test
# description: Recursive CTEs with an error thrown in the pipelines
# group: [cte]
statement ok
PRAGMA enable_verification
statement ok
CREATE TABLE tag(id int, name string, subclassof int);
statement ok
INSERT INTO tag VALUES
(7, 'Music', 9),
(8, 'Movies', 9),
(9, 'Art', NULL)
;
statement error
WITH RECURSIVE tag_hierarchy(id, source, path, target) AS (
SELECT id, name, name AS path, NULL AS target -- this should be '' for correct behaviour
FROM tag
WHERE subclassof IS NULL
UNION ALL
SELECT tag.id, tag.name, tag_hierarchy.path || ' <- ' || tag.name, tag.name AS target
FROM tag, tag_hierarchy
WHERE tag.subclassof = tag_hierarchy.id
)
SELECT source, path, target
FROM tag_hierarchy
;
----
<REGEX>:.*Conversion Error: Could not convert string.*

View File

@@ -0,0 +1,409 @@
# name: test/sql/cte/recursive_cte_key_variant.test
# description: Recursive CTEs with an error thrown in the pipelines
# group: [cte]
statement ok
PRAGMA enable_verification;
statement ok
CREATE TABLE tbl(a int);
query I
WITH RECURSIVE tbl(a) USING KEY (a) AS (SELECT 1 UNION SELECT a.a+1 FROM tbl AS a, (SELECT * FROM recurring.tbl AS d WHERE d.a = 1) AS b WHERE a.a < 2) SELECT * FROM tbl;
----
1
2
# reference only the recurring table
query II
WITH RECURSIVE tbl2(a, b) USING KEY (a) AS (SELECT 5, 1 UNION SELECT a, b + 1 FROM recurring.tbl2 WHERE b < a) SELECT * FROM tbl2;
----
5 5
statement error
WITH RECURSIVE tbl(a) USING KEY (b) AS (SELECT 1 UNION SELECT a.a+1 FROM tbl AS a, (SELECT * FROM recurring.tbl AS d WHERE d.a = 1) AS b WHERE a.a < 2) SELECT * FROM tbl;
----
Binder Error: Referenced column "b" not found in FROM clause!
statement error
WITH RECURSIVE tbl(a) USING KEY (a) AS (SELECT 1 UNION ALL SELECT a+1 FROM tbl) SELECT * FROM tbl;
----
Binder Error: UNION ALL cannot be used with USING KEY in recursive CTE.
query II
WITH RECURSIVE tbl2(a,b) USING KEY (a) AS (SELECT 1, NULL UNION SELECT a.a+1, a.b FROM tbl2 AS a, (SELECT * FROM recurring.tbl2) AS b WHERE a.a < 2) SELECT * FROM tbl2;
----
1 NULL
2 NULL
query III
WITH RECURSIVE tbl(a,b,c) USING KEY (a) AS (SELECT * FROM (VALUES (1, 2, 3), (2,2,5)) UNION SELECT a+1, b+1, c FROM tbl WHERE b < 4) SELECT * FROM tbl;
----
1 2 3
2 3 3
3 4 3
4 4 5
query III
WITH RECURSIVE tbl(a,b,c) USING KEY (b) AS (SELECT * FROM (VALUES (1, 2, 3), (2,3,2)) UNION SELECT a, b+1, c FROM tbl WHERE b < 4) SELECT * FROM tbl;
----
1 2 3
1 3 3
1 4 3
query III
WITH RECURSIVE tbl(a,b,c) USING KEY (a) AS (SELECT * FROM (VALUES (1, 2, 3), (2,3,2)) UNION SELECT a, b+1, c FROM tbl WHERE b < 4) SELECT * FROM tbl;
----
1 4 3
2 4 2
query III
WITH RECURSIVE tbl(a,b,c) USING KEY (b,c) AS (SELECT * FROM (VALUES (1, 2, 3), (2,3,3)) UNION SELECT a, b+1, c FROM tbl WHERE b < 4) SELECT * FROM tbl;
----
1 2 3
1 3 3
1 4 3
query III
WITH RECURSIVE tbl(a,b,c) USING KEY (a,b,c) AS (SELECT * FROM (VALUES (1, 2, 3), (2,3,3)) UNION SELECT a, b+1, c FROM tbl WHERE b < 4) SELECT * FROM tbl;
----
1 2 3
2 3 3
1 3 3
2 4 3
1 4 3
query III
WITH RECURSIVE tbl(a,b,c) USING KEY (a) AS (SELECT * FROM (VALUES (1, 2, 3), (1,3,3)) UNION SELECT a, b+1, c FROM tbl WHERE b < 4) SELECT * FROM tbl;
----
1 4 3
query III
WITH RECURSIVE tbl(a,b,c) USING KEY (a,b,c) AS (SELECT * FROM (VALUES (1, 2, 3), (1,3,3)) UNION SELECT a, b+1, c FROM tbl WHERE b < 4) SELECT * FROM tbl;
----
1 2 3
1 3 3
1 4 3
# Reference the recurring table more than once
query III
WITH RECURSIVE tbl(a,b,c) USING KEY (a) AS (
SELECT 1, NULL, NULL
UNION
(SELECT DISTINCT ON (tbl.a) tbl.a+1, rec1.a, rec2.b
FROM tbl, recurring.tbl AS rec1, recurring.tbl AS rec2
WHERE tbl.a < 5
ORDER BY tbl.a ASC, rec1.a DESC NULLS LAST, rec2.b DESC NULLS LAST
)
) SELECT * FROM tbl;
----
1 NULL NULL
2 1 NULL
3 2 1
4 3 2
5 4 3
############################################
# reference recurring table in wrong places
############################################
statement error
SELECT * FROM recurring.tbl;
----
Catalog Error: Table with name tbl does not exist!
# no using key
statement error
WITH RECURSIVE tbl2(a) AS (SELECT 1 UNION SELECT a.a + 1 FROM tbl2 AS a, recurring.tbl2 AS b WHERE a.a < 2) SELECT * FROM tbl2;
----
does not exist
statement error
WITH RECURSIVE tbl2(a,b) AS (SELECT 1, NULL UNION SELECT a.a+1, a.b FROM tbl2 AS a, (SELECT * FROM recurring.tbl2) AS b WHERE a.a < 2) SELECT * FROM tbl2;
----
does not exist
# second cte references recurring table of first cte while first cte does not
statement error
WITH RECURSIVE tbl(a, b) USING KEY (a) AS (SELECT 5, 1 UNION SELECT a, b + 1 FROM tbl WHERE b < a),
tbl1(a,b) AS (SELECT * FROM recurring.tbl) SELECT * FROM tbl1;
----
does not exist
# second cte references recurring table of first like the first cte
statement error
WITH RECURSIVE tbl(a, b) USING KEY (a) AS (SELECT * FROM ((VALUES (5, 1), (6,1)) UNION SELECT a, b + 1 FROM recurring.tbl WHERE b < a) WHERE a = 5),
tbl1(a,b) AS (SELECT * FROM recurring.tbl) SELECT * FROM tbl1;
----
does not exist
statement error
WITH RECURSIVE tbl2(a) AS (SELECT 1 UNION SELECT a.a+1 FROM tbl2 AS a, (SELECT * FROM recurring.tbl2) AS b WHERE a.a < 2) SELECT * FROM tbl2;
----
does not exist
statement error
WITH RECURSIVE tbl(a, b) USING KEY (a) AS (SELECT 5, 1 UNION SELECT a, b + 1 FROM tbl WHERE b < a),tbl1(a,b) AS (SELECT * FROM recurring.tbl) SELECT * FROM tbl1;
----
does not exist
statement error
WITH RECURSIVE tbl(a, b) USING KEY (a) AS MATERIALIZED (SELECT 5, 1 UNION SELECT a, b + 1 FROM tbl WHERE b < a),tbl1(a,b) AS (SELECT * FROM recurring.tbl) SELECT * FROM tbl1;
----
does not exist
#######################
# Connected components
#######################
statement ok
CREATE OR REPLACE TABLE nodes (node int);
statement ok
INSERT INTO nodes VALUES (0), (1), (2), (3), (4), (5), (6);
statement ok
CREATE OR REPLACE TABLE edges (here int, there int);
statement ok
INSERT INTO edges VALUES (0,4), (4,0),
(0,3), (3,0),
(1,4), (4,1),
(3,4), (4,3),
(2,5), (5,2);
query II
WITH RECURSIVE cc(node, comp) USING KEY (node) AS (
SELECT n.node, n.node AS comp
FROM nodes AS n
UNION
(SELECT DISTINCT ON (u.node) u.node, v.comp
FROM recurring.cc AS u, cc AS v, edges AS e
WHERE (e.here, e.there) = (u.node, v.node)
AND v.comp < u.comp
ORDER BY u.node asc, v.comp asc)
)
TABLE cc ORDER BY node;
----
0 0
1 0
2 2
3 0
4 0
5 2
6 6
#######################
# bellman-ford
#######################
statement ok
CREATE OR REPLACE TABLE edges (here char(2), -- source node
there char(2), -- target node
length int, -- edge weight
PRIMARY KEY (here, there));
statement ok
INSERT INTO edges(here, there, length) VALUES
('v0', 'v1', 9),
('v0', 'v2', 3),
('v1', 'v2', 6),
('v1', 'v4', 2),
('v2', 'v1', 2),
('v2', 'v3', 1),
('v3', 'v2', 2),
('v3', 'v4', 2);
statement ok
DROP TABLE nodes;
statement ok
CREATE OR REPLACE VIEW nodes(node) AS
SELECT e.here
FROM edges AS e
UNION
SELECT e.there
FROM edges AS e;
query II
WITH RECURSIVE bellman(knode, distance) USING KEY (knode) AS (
-- distance is 0 from source, ∞ from any other node
SELECT n.node AS knode,
CASE WHEN n.node = 'v0' THEN 0 ELSE 50000000 END AS distance
FROM nodes AS n
UNION
(SELECT DISTINCT ON (knode) rec.knode AS knode, n.distance + e.length AS distance
FROM bellman AS n, edges AS e, recurring.bellman AS rec
WHERE (e.here, e.there) = (n.knode, rec.knode)
AND rec.distance > n.distance + e.length
ORDER BY distance)
)
SELECT n.knode || CASE WHEN n.knode = 'v0' THEN ' (source)' ELSE '' END AS node,
n.distance
FROM bellman AS n
ORDER BY n.knode;
----
v0 (source) 0
v1 5
v2 3
v3 4
v4 6
# more rows than STANDARD_CHUNK_SIZE
query I
WITH RECURSIVE tbl(n) USING KEY (n) AS (SELECT 1 UNION SELECT n+1 FROM tbl WHERE n < 3000) SELECT SUM(n) FROM tbl
----
4501500
# You can use recursive CTE with and without a key in a query.
query II
WITH RECURSIVE tbl (a, b) USING KEY (a) AS (SELECT 1 , 1 UNION SELECT a, b+1 FROM tbl WHERE b < 3), tbl2(a,b) AS (SELECT 1, 1 UNION SELECT a, b+1 FROM tbl2 WHERE b < 3) SELECT * FROM tbl;
----
1 3
query II
WITH RECURSIVE tbl (a, b) USING KEY (a) AS (SELECT 1 , 1 UNION SELECT a, b+1 FROM tbl WHERE b < 3), tbl2(a,b) AS (SELECT 1, 1 UNION SELECT a, b+1 FROM tbl2 WHERE b < 3) SELECT * FROM tbl2;
----
1 1
1 2
1 3
query II
WITH RECURSIVE tbl2(a,b) AS (SELECT 1, 1 UNION SELECT a, b+1 FROM tbl2 WHERE b < 3), tbl (a, b) USING KEY (a) AS (SELECT 1 , 1 UNION SELECT a, b+1 FROM tbl WHERE b < 3) SELECT * FROM tbl2;
----
1 1
1 2
1 3
query II
WITH RECURSIVE tbl2(a,b) AS (SELECT 1, 1 UNION SELECT a, b+1 FROM tbl2 WHERE b < 3), tbl (a, b) USING KEY (a) AS (SELECT 1 , 1 UNION SELECT a, b+1 FROM tbl WHERE b < 3) SELECT * FROM tbl;
----
1 3
query II
WITH RECURSIVE tbl(a, b) AS (
SELECT 1, 1
UNION
(WITH RECURSIVE tbl2(a, b) USING KEY (b) AS (
SELECT a, b+1 FROM tbl WHERE b < 5
UNION
SELECT a + 1, b
FROM tbl2
WHERE a < 5) SELECT * FROM tbl2))
SELECT * FROM tbl
----
1 1
5 2
5 3
5 4
5 5
query II
WITH RECURSIVE tbl(a, b) USING KEY (b) AS (
SELECT 1, 1
UNION
(WITH RECURSIVE tbl2(a, b) AS (
SELECT a, b+1 FROM tbl WHERE b < 5
UNION
SELECT a + 1, b
FROM tbl2
WHERE a < 5) SELECT * FROM tbl2 ORDER BY a))
SELECT * FROM tbl
----
1 1
5 2
5 3
5 4
5 5
query II
WITH RECURSIVE tbl(a, b) USING KEY (b) AS (
SELECT 1, 1
UNION
(SELECT * FROM (WITH RECURSIVE tbl2(a, b) AS (
SELECT a, b+1 FROM tbl WHERE b < 5
UNION
SELECT a + 1, b
FROM tbl2
WHERE a < 5) SELECT * FROM tbl2 ORDER BY a, b)))
SELECT * FROM tbl
----
1 1
5 2
5 3
5 4
5 5
query II
WITH RECURSIVE tbl(a,b) USING KEY (a) AS (SELECT 1, 1 UNION SELECT a, b+1 FROM tbl WHERE b < 5),
tbl2(a,b) AS (SELECT 1, 1 UNION SELECT a, b+1 FROM tbl2 WHERE b < 5)
SELECT *
FROM tbl2
----
1 1
1 2
1 3
1 4
1 5
query II
WITH RECURSIVE tbl(a,b) USING KEY (a) AS (SELECT 1, 1 UNION SELECT a, b+1 FROM tbl WHERE b < 5),
tbl2(a,b) AS (SELECT 1, 1 UNION SELECT a, b+1 FROM tbl2 WHERE b < 5)
SELECT *
FROM tbl
----
1 5
query II
WITH RECURSIVE tbl(a,b) AS (SELECT 1, 1 UNION SELECT a, b+1 FROM tbl WHERE b < 5),
tbl2(a,b) USING KEY (a) AS (SELECT 1, 1 UNION SELECT a, b+1 FROM tbl2 WHERE b < 5)
SELECT *
FROM tbl2
----
1 5
query II
WITH RECURSIVE tbl(a,b) AS (SELECT 1, 1 UNION SELECT a, b+1 FROM tbl WHERE b < 5),
tbl2(a,b) USING KEY (a) AS (SELECT 1, 1 UNION SELECT a, b+1 FROM tbl2 WHERE b < 5)
SELECT *
FROM tbl
----
1 1
1 2
1 3
1 4
1 5
query III
WITH RECURSIVE tbl(a, b, c) USING KEY (a) AS ((SELECT [], 1, 3 UNION SELECT [1], 2, 4) UNION SELECT a || [b], b + 1, c FROM tbl WHERE b < 5) SELECT * FROM tbl ORDER BY len(a)
----
[] 1 3
[1] 2 3
[1, 2] 3 3
[1, 2, 3] 4 3
[1, 2, 3, 4] 5 3
query II
WITH RECURSIVE tbl(a, b) USING KEY (a) AS (SELECT 'string', 1 UNION SELECT a, b + 1 FROM tbl WHERE b < 5) SELECT * FROM tbl
----
string 5
query III
select *
from range(1, 4) as _(l),
lateral (
with recursive cte(a, b) using key (a) as (
select 1, 0
union
select a, b + 1
from recurring.cte
where b < l
)
table cte
) ORDER BY l
----
1 1 1
2 1 2
3 1 3

View File

@@ -0,0 +1,120 @@
# name: test/sql/cte/recursive_hang_2745.test
# description: Issue #2745: sql with RECURSIVE keyword but does not RECURSIVE hang
# group: [cte]
statement ok
PRAGMA enable_verification
query III
with RECURSIVE parents_tab (id , value , parent )
as (values (1, 1, 2), (2, 2, 4), (3, 1, 4), (4, 2, -1), (5, 1, 2), (6, 2, 7), (7, 1, -1)
),
parents_tab2(id , value , parent )
as (values (1, 1, 2), (2, 2, 4), (3, 1, 4), (4, 2, -1), (5, 1, 2), (6, 2, 7), (7, 1, -1)
),
parents as (
select * from parents_tab
union all
select id, value+2, parent from parents_tab2
)
select * from parents order by id, value, parent;
----
1 1 2
1 3 2
2 2 4
2 4 4
3 1 4
3 3 4
4 2 -1
4 4 -1
5 1 2
5 3 2
6 2 7
6 4 7
7 1 -1
7 3 -1
query III
with RECURSIVE parents_tab (id , value , parent )
as (values (1, 1, 2), (2, 2, 4), (3, 1, 4), (4, 2, -1), (5, 1, 2), (6, 2, 7), (7, 1, -1)
),
parents_tab2(id , value , parent )
as (values (1, 1, 2), (2, 2, 4), (3, 1, 4), (4, 2, -1), (5, 1, 2), (6, 2, 7), (7, 1, -1)
)
select * from parents_tab
union all
select id, value+2, parent from parents_tab2 ORDER BY id, value, parent;
----
1 1 2
1 3 2
2 2 4
2 4 4
3 1 4
3 3 4
4 2 -1
4 4 -1
5 1 2
5 3 2
6 2 7
6 4 7
7 1 -1
7 3 -1
query III
with parents_tab (id , value , parent )
as (values (1, 1, 2), (2, 2, 4), (3, 1, 4), (4, 2, -1), (5, 1, 2), (6, 2, 7), (7, 1, -1)
),
parents_tab2(id , value , parent )
as (values (1, 1, 2), (2, 2, 4), (3, 1, 4), (4, 2, -1), (5, 1, 2), (6, 2, 7), (7, 1, -1)
),
parents as (
select * from parents_tab
union all
select id, value+2, parent from parents_tab2
)
select * from parents ORDER BY id, value, parent;
----
1 1 2
1 3 2
2 2 4
2 4 4
3 1 4
3 3 4
4 2 -1
4 4 -1
5 1 2
5 3 2
6 2 7
6 4 7
7 1 -1
7 3 -1
statement ok
create view vparents as
with RECURSIVE parents_tab (id , value , parent )
as (values (1, 1, 2), (2, 2, 4), (3, 1, 4), (4, 2, -1), (5, 1, 2), (6, 2, 7), (7, 1, -1)
),
parents_tab2(id , value , parent )
as (values (1, 1, 2), (2, 2, 4), (3, 1, 4), (4, 2, -1), (5, 1, 2), (6, 2, 7), (7, 1, -1)
)
select * from parents_tab
union all
select id, value+2, parent from parents_tab2;
query III rowsort
select * from vparents;
----
1 1 2
1 3 2
2 2 4
2 4 4
3 1 4
3 3 4
4 2 -1
4 4 -1
5 1 2
5 3 2
6 2 7
6 4 7
7 1 -1
7 3 -1

View File

@@ -0,0 +1,11 @@
# name: test/sql/cte/test_bug_922.test
# description: Test for a crash reported in issue #922
# group: [cte]
statement ok
PRAGMA enable_verification
query I
WITH my_list(value) AS (VALUES (1), (2), (3))
SELECT * FROM my_list LIMIT 0 OFFSET 1
----

View File

@@ -0,0 +1,432 @@
# name: test/sql/cte/test_correlated_recursive_cte.test_slow
# description: Test Correlated Recursive Common Table Expressions (CTE)
# group: [cte]
statement ok
PRAGMA enable_verification
# Correlation in the initialization query
query II
SELECT x, y
FROM generate_series(1,4) AS _(x), LATERAL
(WITH RECURSIVE t(y) AS (
SELECT _.x
UNION ALL
SELECT y + 1
FROM t
WHERE y < 3
)
SELECT * FROM t) AS t
ORDER BY x, y;
----
1 1
1 2
1 3
2 2
2 3
3 3
4 4
# Correlation in the recursive query
query II
SELECT x, y
FROM generate_series(1,4) AS _(x), LATERAL
(WITH RECURSIVE t(y) AS (
SELECT 1
UNION ALL
SELECT y + _.x
FROM t
WHERE y < 3
)
SELECT * FROM t) AS t
ORDER BY x, y;
----
1 1
1 2
1 3
2 1
2 3
3 1
3 4
4 1
4 5
# Correlation in the initialization and recursive query
query II
SELECT x, y
FROM generate_series(1,4) AS _(x), LATERAL
(WITH RECURSIVE t(y) AS (
SELECT _.x
UNION ALL
SELECT y + _.x
FROM t
WHERE y < 3
)
SELECT * FROM t) AS t
ORDER BY x, y;
----
1 1
1 2
1 3
2 2
2 4
3 3
4 4
# Correlation with multiple recursive anchors
query II
SELECT x, y
FROM generate_series(1,4) AS _(x), LATERAL
(WITH RECURSIVE t(y) AS (
SELECT _.x
UNION ALL
SELECT t1.y + t2.y + _.x
FROM t AS t1, t AS t2
WHERE t1.y < 3
)
SELECT * FROM t) AS t
ORDER BY x, y;
----
1 1
1 3
2 2
2 6
3 3
4 4
# Test correlation in SELECT clause
query III rowsort
SELECT x, y, (WITH RECURSIVE t(z) AS (
SELECT x + y
UNION ALL
SELECT z + 1
FROM t
WHERE z < 3
) SELECT sum(z) FROM t) AS z
FROM generate_series(1,2) AS _(x), generate_series(1,2) AS __(y) order by all;
----
1 1 5
1 2 3
2 1 3
2 2 4
# Complex nested recursive query
query III rowsort
SELECT x, y, (WITH RECURSIVE t(z) AS (
SELECT x + y
UNION ALL
SELECT z + 1
FROM (WITH RECURSIVE g(a) AS (
SELECT t.z
FROM t
UNION ALL
SELECT g.a + (x + y) / 2
FROM g
WHERE g.a < 3)
SELECT * FROM g) AS t(z)
WHERE z < 5
) SELECT sum(z) FROM t) AS z
FROM generate_series(1,2) AS _(x), generate_series(1,2) AS __(y) order by all;
----
1 1 23
1 2 12
2 1 12
2 2 9
statement ok
CREATE TABLE a AS SELECT * FROM range(100) t1(i);
query I
SELECT t2.*
FROM (VALUES (1000000)) t(_corr), LATERAL (
WITH RECURSIVE t AS
(
SELECT 1 AS x
UNION
SELECT SUM(x) AS x
FROM t, a
WHERE x < _corr
)
SELECT * FROM t) t2
ORDER BY 1 NULLS LAST;
----
1
100
10000
1000000
NULL
query I
SELECT t2.*
FROM (VALUES (10)) t(_corr), LATERAL (
WITH RECURSIVE t AS
(
SELECT 1 AS x
UNION
SELECT (SELECT t.x+t2.x FROM t t2 LIMIT 1) AS x
FROM t
WHERE x < _corr
)
SELECT * FROM t) t2
ORDER BY 1 NULLS LAST;
----
1
2
4
8
16
query III
SELECT t2.*
FROM (VALUES (1)) t(_corr), LATERAL (
WITH RECURSIVE collatz(x, t, steps) AS
(
SELECT x, x, 0
FROM (WITH RECURSIVE n(t) AS (SELECT _corr UNION ALL SELECT t+_corr FROM n WHERE t < 10) SELECT * FROM n) AS _(x)
UNION ALL
(SELECT x, CASE WHEN t%2 = _corr THEN t * 3 + p ELSE t / 2 END, steps + p
FROM collatz, (WITH RECURSIVE n(t) AS (SELECT _corr UNION ALL SELECT t+_corr FROM n WHERE t < _corr) SELECT * FROM n) AS _(p)
WHERE t <> _corr)
)
SELECT * FROM collatz WHERE t = _corr
) t2
ORDER BY x;
----
1 1 0
2 1 1
3 1 7
4 1 2
5 1 5
6 1 8
7 1 16
8 1 3
9 1 19
10 1 6
# UNION semantics
# Correlation in the initialization query
query II
SELECT x, y
FROM generate_series(1,4) AS _(x), LATERAL
(WITH RECURSIVE t(y) AS (
SELECT _.x
UNION
SELECT y + 1
FROM t
WHERE y < 3
)
SELECT * FROM t) AS t
ORDER BY x, y;
----
1 1
1 2
1 3
2 2
2 3
3 3
4 4
# Correlation in the recursive query
query II
SELECT x, y
FROM generate_series(1,4) AS _(x), LATERAL
(WITH RECURSIVE t(y) AS (
SELECT 1
UNION
SELECT y + _.x
FROM t
WHERE y < 3
)
SELECT * FROM t) AS t
ORDER BY x, y;
----
1 1
1 2
1 3
2 1
2 3
3 1
3 4
4 1
4 5
# Correlation in the initialization and recursive query
query II
SELECT x, y
FROM generate_series(1,4) AS _(x), LATERAL
(WITH RECURSIVE t(y) AS (
SELECT _.x
UNION
SELECT y + _.x
FROM t
WHERE y < 3
)
SELECT * FROM t) AS t
ORDER BY x, y;
----
1 1
1 2
1 3
2 2
2 4
3 3
4 4
# Correlation with multiple recursive anchors
query II
SELECT x, y
FROM generate_series(1,4) AS _(x), LATERAL
(WITH RECURSIVE t(y) AS (
SELECT _.x
UNION
SELECT t1.y + t2.y + _.x
FROM t AS t1, t AS t2
WHERE t1.y < 3
)
SELECT * FROM t) AS t
ORDER BY x, y;
----
1 1
1 3
2 2
2 6
3 3
4 4
# Test correlation in SELECT clause
query III rowsort
SELECT x, y, (WITH RECURSIVE t(z) AS (
SELECT x + y
UNION
SELECT z + 1
FROM t
WHERE z < 3
) SELECT sum(z) FROM t) AS z
FROM generate_series(1,2) AS _(x), generate_series(1,2) AS __(y) order by all;
----
1 1 5
1 2 3
2 1 3
2 2 4
# Complex nested recursive query
query III rowsort
SELECT x, y, (WITH RECURSIVE t(z) AS (
SELECT x + y
UNION
SELECT z + 1
FROM (WITH RECURSIVE g(a) AS (
SELECT t.z
FROM t
UNION
SELECT g.a + (x + y) / 2
FROM g
WHERE g.a < 3)
SELECT * FROM g) AS t(z)
WHERE z < 5
) SELECT sum(z) FROM t) AS z
FROM generate_series(1,2) AS _(x), generate_series(1,2) AS __(y) order by all;
----
1 1 14
1 2 12
2 1 12
2 2 9
# Deep subquery nesting
query III
SELECT *
FROM generate_series(1,3) AS "input"("n"),
LATERAL
(WITH RECURSIVE "subquery1"("x") AS (
(SELECT "n", true AS "exists")
UNION ALL
(WITH "subquery" AS (SELECT * FROM "subquery1")
SELECT "x" - 1, (SELECT NOT EXISTS (SELECT 1 FROM "subquery" AS "input"("a") WHERE "a" > _."x"))
FROM "subquery" AS _("x") WHERE "x" > 0)
) table "subquery1")
ORDER BY "n", "x";
----
1 0 true
1 1 true
2 0 true
2 1 true
2 2 true
3 0 true
3 1 true
3 2 true
3 3 true
query III
SELECT *
FROM generate_series(1,3) AS "input"("n"),
LATERAL
(WITH RECURSIVE "subquery"("x") AS (
(SELECT "n", true AS "exists")
UNION ALL
SELECT "x" - 1, y
FROM "subquery" AS _("x"), LATERAL (SELECT NOT EXISTS (SELECT 1 FROM "subquery" AS "input"("a") WHERE "a" > _."x")) AS __(y)
WHERE "x" > 0
) table "subquery")
ORDER BY "n", "x"
;
----
1 0 true
1 1 true
2 0 true
2 1 true
2 2 true
3 0 true
3 1 true
3 2 true
3 3 true
query III
SELECT *
FROM generate_series(1,3) AS "input"("n"),
LATERAL
(WITH RECURSIVE "subquery"("x") AS (
(SELECT "n", true AS "exists")
UNION ALL
SELECT "x" - 1, y
FROM "subquery" AS _("x"), LATERAL (SELECT (SELECT (SELECT NOT EXISTS (SELECT 1 FROM "subquery" AS "input"("a") WHERE "a" > _."x")))) AS __(y)
WHERE "x" > 0
) table "subquery")
ORDER BY "n", "x"
;
----
1 0 true
1 1 true
2 0 true
2 1 true
2 2 true
3 0 true
3 1 true
3 2 true
3 3 true
query III
SELECT *
FROM generate_series(1,3) AS "input"("n"),
LATERAL
(WITH RECURSIVE "subquery"("x", "exists") AS (
(SELECT "n", true AS "exists")
UNION ALL
SELECT "a" - 1, (SELECT NOT bool_or("input"."x1" > _."a") FROM "subquery" AS "input"("x1"))
FROM "subquery" AS _("a")
WHERE "a" > 0
)
table "subquery")
ORDER BY "n", "x"
;
----
1 0 true
1 1 true
2 0 true
2 1 true
2 2 true
3 0 true
3 1 true
3 2 true
3 3 true

View File

@@ -0,0 +1,234 @@
# name: test/sql/cte/test_cte.test
# description: Test Common Table Expressions (CTE)
# group: [cte]
statement ok
PRAGMA enable_verification
statement ok
create table a(i integer);
statement ok
insert into a values (42);
query I
with cte1 as (Select i as j from a) select * from cte1;
----
42
query I
with cte1 as (Select i as j from a) select x from cte1 t1(x);
----
42
query I
with cte1(xxx) as (Select i as j from a) select xxx from cte1;
----
42
query I
with cte1(xxx) as (Select i as j from a) select x from cte1 t1(x);
----
42
query II
with cte1 as (Select i as j from a), cte2 as (select ref.j as k from cte1 as ref), cte3 as (select ref2.j+1 as i from cte1 as ref2) select * from cte2 , cte3;
----
42 43
query I
with cte1 as (select i as j from a), cte2 as (select ref.j as k from cte1 as ref), cte3 as (select ref2.j+1 as i from cte1 as ref2) select * from cte2 union all select * FROM cte3;
----
42
43
# duplicate CTE alias
statement error
with cte1 as (select 42), cte1 as (select 42) select * FROM cte1;
----
# multiple uses of same CTE
query II
with cte1 as (Select i as j from a) select * from cte1 cte11, cte1 cte12;
----
42 42
# refer to CTE in subquery
query I
with cte1 as (Select i as j from a) select * from cte1 where j = (select max(j) from cte1 as cte2);
----
42
# multi-column name alias
query II
with cte1(x, y) as (select 42 a, 84 b) select zzz, y from cte1 t1(zzz);
----
42 84
# use a CTE in a view definition
statement ok
create view va AS (with cte as (Select i as j from a) select * from cte);
query I
select * from va
----
42
# nested CTE views that re-use CTE aliases
query I
with cte AS (SELECT * FROM va) SELECT * FROM cte;
----
42
# multiple ctes in a view definition
statement ok
create view vb AS (with cte1 as (Select i as j from a), cte2 as (select ref.j+1 as k from cte1 as ref) select * from cte2);
query I
select * from vb
----
43
# cte in set operation node
query I
SELECT 1 UNION ALL (WITH cte AS (SELECT 42) SELECT * FROM cte);
----
1
42
# cte in nested set operation node
query I
SELECT 1 UNION ALL (WITH cte AS (SELECT 42) SELECT * FROM cte UNION ALL SELECT * FROM cte);
----
1
42
42
# cte in recursive cte
query I
WITH RECURSIVE cte(d) AS (
SELECT 1
UNION ALL
(WITH c(d) AS (SELECT * FROM cte)
SELECT d + 1
FROM c
WHERE FALSE
)
)
SELECT max(d) FROM cte;
----
1
# test CTE with nested aliases in where clause
query II
with cte (a) as (
select 1
)
select
a as alias1,
alias1 as alias2
from cte
where alias2 > 0;
----
1 1
# recursive CTE and a non-recursive CTE with except
query I
WITH RECURSIVE t AS (
SELECT 1 AS a
UNION ALL
SELECT a+1
FROM t
WHERE a < 10
), s AS (
(VALUES (5), (6), (7), (8), (9), (10), (11), (12), (13), (42))
EXCEPT
TABLE t
)
SELECT * FROM s AS _(x) ORDER BY x;
----
11
12
13
42
# recursive CTE with except in recursive part (but not as a recursive anchor)
query I
WITH RECURSIVE t AS (
select 1 as a
union all
(select a+1
from t
where a < 10
except
SELECT 4)
), s AS (
(values (5), (6), (7))
except
table t
)
SELECT * FROM s AS _(x) ORDER BY x;
----
5
6
7
query I
WITH RECURSIVE
t(b) AS MATERIALIZED (
(WITH helper(c) AS (
SELECT 5
), h1 AS
(SELECT * FROM helper h
UNION
SELECT 7 FROM helper h)
SELECT * FROM h1)
)
SELECT * FROM t ORDER BY b;
----
5
7
require no_alternative_verify
# FIXME: this one should work with ALTERNATIVE_VERIFY, but doesn't yet
# something wrong with binding a CTE inside a recursive CTE
query I
WITH RECURSIVE
t(b) AS MATERIALIZED (
(WITH helper(c) AS (
SELECT 5
)
SELECT * FROM helper h
UNION
SELECT 7
)
)
SELECT * FROM t ORDER BY b;
----
5
7
# reference to CTE before its actually defined, can't with ALTERNATIVE_VERIFY because everything gets materialized
statement error
with cte3 as (select ref2.j as i from cte1 as ref2), cte1 as (Select i as j from a), cte2 as (select ref.j+1 as k from cte1 as ref) select * from cte2 union all select * FROM cte3;
----
Catalog Error: Table with name cte1 does not exist!
statement error
WITH t(x) AS (SELECT x)
SELECT *
FROM range(10) AS _(x), LATERAL (SELECT * FROM t);
----
statement error
WITH cte AS (SELECT x)
SELECT b.x
FROM (SELECT 1) _(x), LATERAL (SELECT * FROM cte) b(x)
----
query III
WITH RECURSIVE rec(a, b, c) AS (select a,b,c from (values(1,2,3),(1,2,3)) s(a,b,c) union select 1,2,3) select * from rec;
----
1 2 3

View File

@@ -0,0 +1,64 @@
# name: test/sql/cte/test_cte_in_cte.test
# description: Test Nested Common Table Expressions (CTE)
# group: [cte]
statement ok
PRAGMA enable_verification
statement ok
create table a(i integer);
statement ok
insert into a values (42);
query I
with cte1 as (Select i as j from a) select * from cte1;
----
42
query I
with cte1 as (with b as (Select i as j from a) Select j from b) select x from cte1 t1(x);
----
42
query I
with cte1(xxx) as (with ncte(yyy) as (Select i as j from a) Select yyy from ncte) select xxx from cte1;
----
42
query II
with cte1 as (with b as (Select i as j from a) select j from b), cte2 as (with c as (select ref.j+1 as k from cte1 as ref) select k from c) select * from cte1 , cte2;
----
42 43
# duplicate CTE alias
statement error
with cte1 as (select 42), cte1 as (select 42) select * FROM cte1;
----
<REGEX>:.*Parser Error: Duplicate CTE name.*
# refer to CTE in subquery tableref
query I
with cte1 as (Select i as j from a) select * from (with cte2 as (select max(j) as j from cte1) select * from cte2) f
----
42
# refer to CTE in subquery expression
query I
with cte1 as (Select i as j from a) select * from cte1 where j = (with cte2 as (select max(j) as j from cte1) select j from cte2);
----
42
require no_alternative_verify
# refer to same-named CTE in a subquery expression
query I
with cte as (Select i as j from a) select * from cte where j = (with cte as (select max(j) as j from cte) select j from cte);
----
42
# self-refer to non-existent cte
statement error
with cte as (select * from cte) select * from cte
----
<REGEX>:.*Binder Error.*Circular reference to CTE.*

View File

@@ -0,0 +1,17 @@
# name: test/sql/cte/test_cte_overflow.test
# description: Ensure no stack overflow for CTE names that match existing tables
# group: [cte]
statement ok
create table a (id integer)
statement ok
insert into a values (1729)
statement ok
create view va as (with v as (select * from a) select * from v)
query I
with a as (select * from va) select * from a
----
1729

View File

@@ -0,0 +1,230 @@
# name: test/sql/cte/test_fib_complex.test_slow
# description: Very complex recursive CTE with several corner cases
# group: [cte]
statement ok
PRAGMA enable_verification;
query IIIIIIIII
SELECT "input".*,
"result".*
FROM (SELECT i FROM generate_series(2,3) AS _(i)) AS "input"("n"),
LATERAL (WITH RECURSIVE
"loop"(".iteration", ".mark", ".thread.this", ".label.this", ".thread.parent", ".label.parent", "fib.n", "fib.result.0") AS (
(SELECT CAST((0) AS INT) AS ".iteration",
CAST((0) AS INT) AS ".mark",
CAST((0) AS INT) AS ".thread.this",
'fib' AS ".label.this",
CAST((NULL) AS INT) AS ".thread.parent",
CAST((NULL) AS TEXT) AS ".label.parent",
CAST(("input"."n") AS int) AS "fib.n",
CAST((NULL) AS int) AS "fib.result.0"
)
UNION ALL
(WITH
"fib.assignment.1"(".iteration", ".mark", ".thread.this", ".label.parent", "k", "n") AS (
SELECT "input".".iteration",
"input".".mark",
"input".".thread.this",
"input".".label.parent",
CAST(("input"."fib.n" <= 1) AS bool) AS "k",
"input"."fib.n"
FROM "loop" AS "input"
WHERE "input".".label.this" IS NOT DISTINCT FROM 'fib'
),
"fib.call.1.prepare"(".iteration", ".mark", ".thread.this", ".label.this", ".thread.parent", ".label.parent", "argument.0") AS (
SELECT "input".".iteration",
"input".".mark",
(SELECT COALESCE(MAX("loop".".thread.this"), 0)
FROM "loop"
WHERE ("loop".".label.parent" IS NOT DISTINCT FROM "input".".label.parent" OR
"loop".".label.this" IS NOT DISTINCT FROM 'fib.call.1')) + ROW_NUMBER() OVER (ORDER BY "fork"."n" DESC) AS ".thread.this",
'fib.call.1' AS ".label.this",
"input".".thread.this" AS ".thread.parent",
"input".".label.parent",
CAST(("fork"."n") AS int) AS "argument.0"
FROM "loop" AS "input",
LATERAL (SELECT "input"."fib.n" - i FROM generate_series(1,2) AS _(i)) AS "fork"("n")
WHERE "input".".label.this" IS NOT DISTINCT FROM 'fib.mark.1'
),
"fib.wait.1.decide"(".iteration", ".mark", ".thread.this", ".label.parent", ".done", "n") AS (
SELECT "input".".iteration",
MIN("input".".mark") OVER (
PARTITION BY "input".".iteration",
"input".".thread.this"
ROWS BETWEEN UNBOUNDED PRECEDING
AND UNBOUNDED FOLLOWING
) AS ".mark",
"input".".thread.this",
"input".".label.parent",
NOT EXISTS(SELECT 1 AS "dummy"
FROM "loop"
WHERE "loop".".mark" > "input".".mark"
AND ("loop".".thread.this" IS NOT DISTINCT FROM "input".".thread.this" OR
"loop".".thread.parent" IS NOT DISTINCT FROM "input".".thread.this"))
AS ".done",
"input"."n"
FROM ((SELECT "input".".iteration",
"input".".mark" - 1 AS ".mark",
"input".".thread.parent",
"input".".label.parent",
"return"."fib.result.0"
FROM "loop" AS "input", "loop" AS "return"
WHERE "input".".label.this" IS NOT DISTINCT FROM 'fib.call.1'
AND "return".".label.this" IS NULL
AND "return".".label.parent" IS NOT DISTINCT FROM 'fib.call.1'
AND "return".".thread.this" IS NOT DISTINCT FROM "input".".thread.this")
UNION ALL
(SELECT "input".".iteration",
"input".".mark",
"input".".thread.this",
"input".".label.parent",
"input"."fib.n"
FROM "loop" AS "input"
WHERE "input".".label.this" IS NOT DISTINCT FROM 'fib.wait.1')) AS "input"(".iteration", ".mark", ".thread.this", ".label.parent", "n")
)
(SELECT "input".".iteration" + 1,
"input".".mark" + 1,
"input".".thread.this",
'fib.mark.1' AS ".label.this",
CAST((NULL) AS int),
"input".".label.parent",
"input"."n" AS "fib.n",
CAST((NULL) AS int) AS "fib.result.0"
FROM "fib.assignment.1" AS "input"
WHERE NOT "input"."k")
UNION ALL
(SELECT "sink".".iteration" + 1,
"sink".".mark",
"sink".".thread.this",
"sink".".label.this",
"sink".".thread.parent",
"sink".".label.parent",
CAST((NULL) AS int) AS "fib.n",
CAST((NULL) AS int) AS "fib.result.0"
FROM "fib.call.1.prepare" AS "sink")
UNION ALL
(SELECT "input".".iteration" + 1,
"input".".mark",
"input".".thread.this",
"input".".label.this",
"input".".thread.parent",
"input".".label.parent",
CAST((NULL) AS int) AS "fib.n",
CAST((NULL) AS int) AS "fib.result.0"
FROM "loop" AS "input"
WHERE "input".".label.this" IS NOT DISTINCT FROM 'fib.call.1'
AND EXISTS(SELECT 1 AS "dummy"
FROM "loop"
WHERE "loop".".label.this" IS NOT NULL
AND "loop".".label.parent" IS NOT DISTINCT FROM 'fib.call.1'
AND ("loop".".thread.this" IS NOT DISTINCT FROM "input".".thread.this" AND
"loop".".thread.parent" IS NULL OR
"loop".".thread.parent" IS NOT DISTINCT FROM "input".".thread.this")))
UNION ALL
(SELECT "input".".iteration" + 1,
"input".".mark",
"input".".thread.this",
'fib.wait.1' AS ".label.this",
CAST((NULL) AS int),
"input".".label.parent",
"input"."n" AS "fib.n",
CAST((NULL) AS int) AS "fib.result.0"
FROM "fib.wait.1.decide" AS "input"
WHERE NOT "input".".done")
UNION ALL
(SELECT "input".".iteration" + 1,
"input".".mark",
"input".".thread.this",
CAST((NULL) AS TEXT) AS ".label.this",
CAST((NULL) AS INT) AS ".thread.parent",
"input".".label.parent",
CAST((NULL) AS int) AS "fib.n",
CAST(("input"."n") AS int)
FROM "fib.assignment.1" AS "input"
WHERE "input"."k")
UNION ALL
(SELECT "key".".iteration" + 1,
"key".".mark",
"key".".thread.this",
CAST((NULL) AS TEXT) AS ".label.this",
CAST((NULL) AS INT) AS ".thread.parent",
"key".".label.parent",
CAST((NULL) AS int) AS "fib.n",
CAST(("aggregate"."n") AS int)
FROM (SELECT MIN("key".".mark") AS ".mark",
"key".".iteration",
"key".".thread.this",
"key".".label.parent"
FROM "fib.wait.1.decide" AS "key"
WHERE "key".".done"
GROUP BY "key".".iteration",
"key".".thread.this",
"key".".label.parent"
) AS "key"(".mark", ".iteration", ".thread.this", ".label.parent"),
LATERAL (SELECT SUM(CAST(("input"."n") AS INT))
FROM "fib.wait.1.decide" AS "input"
WHERE "input".".done"
AND "key".".iteration" IS NOT DISTINCT FROM "input".".iteration"
AND "key".".thread.this" IS NOT DISTINCT FROM "input".".thread.this"
AND "key".".label.parent" IS NOT DISTINCT FROM "input".".label.parent") AS "aggregate"("n")
WHERE "key".".mark" IS NOT NULL)
UNION ALL
(SELECT "input".".iteration" + 1,
"input".".mark",
"input".".thread.this",
'fib' AS ".label.this",
"input".".thread.this" AS ".thread.parent",
'fib.call.1' AS ".label.parent",
"input"."argument.0" AS "fib.n",
CAST((NULL) AS int) AS "fib.result.0"
FROM "fib.call.1.prepare" AS "input"))
)
TABLE loop) AS "result"
ORDER BY ALL
----
2 0 0 0 fib NULL NULL 2 NULL
2 1 1 0 fib.mark.1 NULL NULL 2 NULL
2 2 1 1 fib 1 fib.call.1 1 NULL
2 2 1 1 fib.call.1 0 NULL NULL NULL
2 2 1 2 fib 2 fib.call.1 0 NULL
2 2 1 2 fib.call.1 0 NULL NULL NULL
2 3 1 1 fib.call.1 0 NULL NULL NULL
2 3 1 1 NULL NULL fib.call.1 NULL 1
2 3 1 2 fib.call.1 0 NULL NULL NULL
2 3 1 2 NULL NULL fib.call.1 NULL 0
2 4 0 0 fib.wait.1 NULL NULL 0 NULL
2 4 0 0 fib.wait.1 NULL NULL 1 NULL
2 5 0 0 NULL NULL NULL NULL 1
3 0 0 0 fib NULL NULL 3 NULL
3 1 1 0 fib.mark.1 NULL NULL 3 NULL
3 2 1 1 fib 1 fib.call.1 2 NULL
3 2 1 1 fib.call.1 0 NULL NULL NULL
3 2 1 2 fib 2 fib.call.1 1 NULL
3 2 1 2 fib.call.1 0 NULL NULL NULL
3 3 1 1 fib.call.1 0 NULL NULL NULL
3 3 1 2 fib.call.1 0 NULL NULL NULL
3 3 1 2 NULL NULL fib.call.1 NULL 1
3 3 2 1 fib.mark.1 NULL fib.call.1 2 NULL
3 4 0 0 fib.wait.1 NULL NULL 1 NULL
3 4 1 1 fib.call.1 0 NULL NULL NULL
3 4 2 3 fib 3 fib.call.1 1 NULL
3 4 2 3 fib.call.1 1 fib.call.1 NULL NULL
3 4 2 4 fib 4 fib.call.1 0 NULL
3 4 2 4 fib.call.1 1 fib.call.1 NULL NULL
3 5 0 0 fib.wait.1 NULL NULL 1 NULL
3 5 1 1 fib.call.1 0 NULL NULL NULL
3 5 2 3 fib.call.1 1 fib.call.1 NULL NULL
3 5 2 3 NULL NULL fib.call.1 NULL 1
3 5 2 4 fib.call.1 1 fib.call.1 NULL NULL
3 5 2 4 NULL NULL fib.call.1 NULL 0
3 6 0 0 fib.wait.1 NULL NULL 1 NULL
3 6 1 1 fib.call.1 0 NULL NULL NULL
3 6 1 1 fib.wait.1 NULL fib.call.1 0 NULL
3 6 1 1 fib.wait.1 NULL fib.call.1 1 NULL
3 7 0 0 fib.wait.1 NULL NULL 1 NULL
3 7 1 1 fib.call.1 0 NULL NULL NULL
3 7 1 1 NULL NULL fib.call.1 NULL 1
3 8 0 0 fib.wait.1 NULL NULL 1 NULL
3 8 0 0 fib.wait.1 NULL NULL 1 NULL
3 9 0 0 NULL NULL NULL NULL 2

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,32 @@
# name: test/sql/cte/test_issue_5673.test
# description: Issue #5673 and #4987: CTE and Table name are name shadowing
# group: [cte]
statement ok
PRAGMA enable_verification
statement ok
create or replace table orders(ordered_at int);
statement ok
create or replace table stg_orders(ordered_at int);
statement ok
insert into orders values (1);
statement ok
insert into stg_orders values (1);
query I
with
orders as (
select * from main.stg_orders
where ordered_at >= (select max(ordered_at) from main.orders)
),
some_more_logic as (
select *
from orders
)
select * from some_more_logic;
----
1

View File

@@ -0,0 +1,110 @@
# name: test/sql/cte/test_moderate_union_all.test
# description: Test moderate chain of UNION ALL statements
# group: [cte]
statement ok
CREATE VIEW union_view AS
SELECT 0 i
UNION ALL
SELECT 1
UNION ALL
SELECT 2
UNION ALL
SELECT 3
UNION ALL
SELECT 4
UNION ALL
SELECT 5
UNION ALL
SELECT 6
UNION ALL
SELECT 7
UNION ALL
SELECT 8
UNION ALL
SELECT 9
UNION ALL
SELECT 10
UNION ALL
SELECT 11
UNION ALL
SELECT 12
UNION ALL
SELECT 13
UNION ALL
SELECT 14
UNION ALL
SELECT 15
UNION ALL
SELECT 16
UNION ALL
SELECT 17
UNION ALL
SELECT 18
UNION ALL
SELECT 19
UNION ALL
SELECT 20
UNION ALL
SELECT 21
UNION ALL
SELECT 22
UNION ALL
SELECT 23
UNION ALL
SELECT 24
UNION ALL
SELECT 25
UNION ALL
SELECT 26
UNION ALL
SELECT 27
UNION ALL
SELECT 28
UNION ALL
SELECT 29
UNION ALL
SELECT 30
UNION ALL
SELECT 31
UNION ALL
SELECT 32
UNION ALL
SELECT 33
UNION ALL
SELECT 34
UNION ALL
SELECT 35
UNION ALL
SELECT 36
UNION ALL
SELECT 37
UNION ALL
SELECT 38
UNION ALL
SELECT 39
UNION ALL
SELECT 40
UNION ALL
SELECT 41
UNION ALL
SELECT 42
UNION ALL
SELECT 43
UNION ALL
SELECT 44
UNION ALL
SELECT 45
UNION ALL
SELECT 46
UNION ALL
SELECT 47
UNION ALL
SELECT 48
UNION ALL
SELECT 49
query IIII
SELECT COUNT(*), MIN(i), MAX(i), AVG(i) FROM union_view
----
50 0 49 24.5

View File

@@ -0,0 +1,59 @@
# name: test/sql/cte/test_nested_recursive_cte.test
# description: Test Nested Recursive Common Table Expressions (CTE)
# group: [cte]
statement ok
PRAGMA enable_verification
query I
WITH RECURSIVE t(x) AS
(
SELECT 1
UNION ALL
SELECT x+1
FROM t
WHERE x < 4
),
u(x) AS
(
SELECT *
FROM t
UNION ALL
SELECT u.x * 2 + t.x
FROM u, t
WHERE u.x < 32
)
SELECT *
FROM u
ORDER BY x
LIMIT 5;
----
1
2
3
3
4
query III
WITH RECURSIVE collatz(x, t, steps) AS
(
SELECT x, x, 0
FROM (WITH RECURSIVE n(t) AS (SELECT 1 UNION ALL SELECT t+1 FROM n WHERE t < 10) SELECT * FROM n) AS _(x)
UNION ALL
(SELECT x, CASE WHEN t%2 = 1 THEN t * 3 + p ELSE t / 2 END, steps + p
FROM collatz, (WITH RECURSIVE n(t) AS (SELECT 1 UNION ALL SELECT t+1 FROM n WHERE t < 1) SELECT * FROM n) AS _(p)
WHERE t <> 1)
)
SELECT * FROM collatz WHERE t = 1
ORDER BY x;
----
1 1 0
2 1 1
3 1 7
4 1 2
5 1 5
6 1 8
7 1 16
8 1 3
9 1 19
10 1 6

View File

@@ -0,0 +1,30 @@
# name: test/sql/cte/test_outer_joins_recursive_cte.test
# description: Test Recursive Common Table Expressions (CTE) with outer joins
# group: [cte]
statement ok
PRAGMA enable_verification
statement ok
CREATE TABLE v(x INT);
statement ok
INSERT INTO v
VALUES
(1),(2),(3);
query II
WITH RECURSIVE t(x) AS
(
SELECT 1
UNION ALL
SELECT x + 1
FROM (SELECT t.x+1 FROM v AS _(p) FULL OUTER JOIN t ON t.x = p) AS _(x)
WHERE x < 10
) SELECT * FROM v AS _(p) RIGHT OUTER JOIN t ON t.x = p ORDER BY p, t NULLS LAST;
----
1 1
3 3
NULL 5
NULL 7
NULL 9

View File

@@ -0,0 +1,145 @@
# name: test/sql/cte/test_recursive_cte_tutorial.test
# description: Test Recursive CTEs from the CyberTec tutorial: https://www.cybertec-postgresql.com/en/recursive-queries-postgresql/
# group: [cte]
statement ok
PRAGMA enable_verification
statement ok
CREATE TABLE emp (empno INTEGER PRIMARY KEY,
ename VARCHAR,
job VARCHAR,
mgr INTEGER,
hiredate DATE,
sal DOUBLE,
comm DOUBLE,
deptno INTEGER);
statement ok
INSERT INTO emp VALUES (7839, 'KING', 'PRESIDENT', NULL, DATE '1981-11-17', 5000.00, NULL, 10);
INSERT INTO emp VALUES (7698, 'BLAKE', 'MANAGER', 7839, DATE '1981-05-01', 2850.00, NULL, 30);
INSERT INTO emp VALUES (7782, 'CLARK', 'MANAGER', 7839, DATE '1981-06-09', 2450.00, NULL, 10);
INSERT INTO emp VALUES (7566, 'JONES', 'MANAGER', 7839, DATE '1981-04-02', 2975.00, NULL, 20);
INSERT INTO emp VALUES (7902, 'FORD', 'ANALYST', 7566, DATE '1981-12-03', 3000.00, NULL, 20);
INSERT INTO emp VALUES (7369, 'SMITH', 'CLERK', 7902, DATE '1980-12-17', 800.00, NULL, 20);
INSERT INTO emp VALUES (7499, 'ALLEN', 'SALESMAN', 7698, DATE '1981-02-20', 1600.00, 300.00, 30);
INSERT INTO emp VALUES (7521, 'WARD', 'SALESMAN', 7698, DATE '1981-02-22', 1250.00, 500.00, 30);
INSERT INTO emp VALUES (7654, 'MARTIN', 'SALESMAN', 7698, DATE '1981-09-28', 1250.00, 1400.00, 30);
INSERT INTO emp VALUES (7844, 'TURNER', 'SALESMAN', 7698, DATE '1981-09-08', 1500.00, 0.00, 30);
INSERT INTO emp VALUES (7900, 'JAMES', 'CLERK', 7698, DATE '1981-12-03', 950.00, NULL, 30);
INSERT INTO emp VALUES (7934, 'MILLER', 'CLERK', 7782, DATE '1982-01-23', 1300.00, NULL, 10);
query II
WITH RECURSIVE ctename AS (
SELECT empno, ename
FROM emp
WHERE empno = 7566
UNION ALL
SELECT emp.empno, emp.ename
FROM emp
JOIN ctename ON emp.mgr = ctename.empno
)
SELECT * FROM ctename;
----
7566 JONES
7902 FORD
7369 SMITH
query III
WITH RECURSIVE ctename AS (
SELECT empno, ename,
0 AS level
FROM emp
WHERE empno = 7566
UNION ALL
SELECT emp.empno, emp.ename,
ctename.level + 1
FROM emp
JOIN ctename ON emp.mgr = ctename.empno
)
SELECT * FROM ctename;
----
7566 JONES 0
7902 FORD 1
7369 SMITH 2
query III
WITH RECURSIVE ctename AS (
SELECT empno, ename,
ename AS path
FROM emp
WHERE empno = 7566
UNION ALL
SELECT emp.empno, emp.ename,
ctename.path || ' -> ' || emp.ename
FROM emp
JOIN ctename ON emp.mgr = ctename.empno
)
SELECT * FROM ctename;
----
7566 JONES JONES
7902 FORD JONES -> FORD
7369 SMITH JONES -> FORD -> SMITH
statement ok
CREATE VIEW ctenames AS (
WITH RECURSIVE ctename AS (
SELECT empno, ename,
ename AS path
FROM emp
WHERE empno = 7566
UNION ALL
SELECT emp.empno, emp.ename,
ctename.path || ' -> ' || emp.ename
FROM emp
JOIN ctename ON emp.mgr = ctename.empno
)
SELECT * FROM ctename
);
query III
SELECT * FROM ctenames;
----
7566 JONES JONES
7902 FORD JONES -> FORD
7369 SMITH JONES -> FORD -> SMITH
require no_alternative_verify
statement ok
PRAGMA disable_verification
query II
WITH RECURSIVE fib AS (
SELECT 1 AS n,
1::bigint AS "fibₙ",
1::bigint AS "fibₙ₊₁"
UNION ALL
SELECT n+1,
"fibₙ₊₁",
"fibₙ" + "fibₙ₊₁"
FROM fib
)
SELECT n, "fibₙ" FROM fib
LIMIT 20;
----
1 1
2 1
3 2
4 3
5 5
6 8
7 13
8 21
9 34
10 55
11 89
12 144
13 233
14 377
15 610
16 987
17 1597
18 2584
19 4181
20 6765

View File

@@ -0,0 +1,179 @@
# name: test/sql/cte/test_recursive_cte_union.test
# description: Test Recursive Common Table Expressions UNION (CTE)
# group: [cte]
statement ok
PRAGMA enable_verification
# simple recursive CTE
query I
with recursive t as (select 1 as x union select x+1 from t where x < 3) select * from t order by x
----
1
2
3
query I
with recursive t(x) as (select 1 union select x+1 from t where x < 3) select * from t order by x
----
1
2
3
# test some aliases
query I
with recursive t(x) as (select 1 union select x+1 from t where x < 3) select zz from t t1(zz) order by zz
----
1
2
3
query I
with recursive t(x) as (select 1 union select zzz+1 from t t1(zzz) where zzz < 3) select zz from t t1(zz) order by zz
----
1
2
3
# UNION semantics prevents infinite loop here
query I
with recursive t as (select 1 as x union select x from t) select * from t
----
1
# simple recursive CTE with an alias
query I
with recursive t as (select 1 as x union select x+1 from t as m where m.x < 3) select * from t order by x
----
1
2
3
# recursive CTE with multiple references and aliases
query I
with recursive t as (select 1 as x union select m.x+f.x from t as m, t as f where m.x < 3) select * from t order by x
----
1
2
4
# strings and multiple columns
query IT
with recursive t as (select 1 as x, 'hello' as y union select x+1, y || '-' || 'hello' from t where x < 3) select * from t order by x;
----
1 hello
2 hello-hello
3 hello-hello-hello
# referencing same CTE multiple times
query I
with recursive t as (select 1 as x union select x+1 from t where x < 3) select min(a1.x) from t a1, t a2;
----
1
# nested uncorrelated subquery
query I
with recursive t as (select 1 as x union select x+(SELECT 1) from t where x < 3) select * from t order by x;
----
1
2
3
# some of the following recursive queries are terminated by the LIMIT clause
# this requires CTE inlining, which enable_verification disables
require no_alternative_verify
statement ok
PRAGMA disable_verification
# hash join
query I
with recursive t as (select 1 as x union all select * from (select x from t where x < 5) tbl(i) join (select 1) tbl2(i) using (i)) select * from t limit 3;
----
1
1
1
query I
with recursive t as (select 1 as x union all select * from (select 1) tbl2(i) join (select x from t where x < 5) tbl(i) using (i)) select * from t limit 3;
----
1
1
1
query I
with recursive t as (select 1 as x union all select * from (select x from t where x < 5) tbl(i) join (select first(i) from (values (1)) tbl3(i) limit 1) tbl2(i) using (i)) select * from t limit 3;
----
1
1
1
query I
with recursive t as (select 1 as x union all select * from (select first(i) from (values (1)) tbl3(i) limit 1) tbl2(i) join (select x from t where x < 5) tbl(i) using (i)) select * from t limit 3;
----
1
1
1
statement ok
PRAGMA enable_verification
# correlated subquery
query I
with recursive t as (select 1 as x union select x+(SELECT 1+t.x) from t where x < 5) select * from t order by x;
----
1
3
7
# use with recursive in table creation
statement ok
create table integers as with recursive t as (select 1 as x union select x+1 from t where x < 3) select * from t;
# more complex uncorrelated subquery
query I
with recursive t as (select (select min(x) from integers) as x union select x+1 from t where x < 3) select * from t order by x;
----
1
2
3
# aggregate functions
query I
with recursive t as (select 1 as x union select sum(x+1) from t where x < 3) select * from t order by 1 nulls last
----
1
2
3
NULL
# order by is not allowed in the recursive term of ctes
statement error
with recursive t as (select 1 as x union select sum(x+1) from t where x < 3 order by x) select * from t
----
# limit is not allowed in the recursive term of ctes
statement error
with recursive t as (select 1 as x union select sum(x+1) from t where x < 3 LIMIT 1) select * from t
----
# offset is not allowed in the recursive term of ctes
statement error
with recursive t as (select 1 as x union select sum(x+1) from t where x < 3 OFFSET 1) select * from t
----
# offset is not allowed in the recursive term of ctes
statement error
with recursive t as (select 1 as x union select sum(x+1) from t where x < 3 LIMIT 1 OFFSET 1) select * from t
----
# create a view from a recursive cte
statement ok
create view vr as (with recursive t(x) as (select 1 union select x+1 from t where x < 3) select * from t order by x)
query I
select * from vr
----
1
2
3

View File

@@ -0,0 +1,144 @@
# name: test/sql/cte/test_recursive_cte_union_all.test
# description: Test Recursive Common Table Expressions UNION ALL (CTE)
# group: [cte]
statement ok
PRAGMA enable_verification
# simple recursive CTE
query I
with recursive t as (select 1 as x union all select x+1 from t where x < 3) select * from t
----
1
2
3
# simple recursive CTE with an alias
query I
with recursive t as (select 1 as x union all select x+1 from t as m where m.x < 3) select * from t
----
1
2
3
# recursive CTE with multiple references and aliases
query I
with recursive t as (select 1 as x union all select m.x+f.x from t as m, t as f where m.x < 3) select * from t
----
1
2
4
# strings and multiple columns
query IT
with recursive t as (select 1 as x, 'hello' as y union all select x+1, y || '-' || 'hello' from t where x < 3) select * from t;
----
1 hello
2 hello-hello
3 hello-hello-hello
# referencing same CTE multiple times
query I
with recursive t as (select 1 as x union all select x+1 from t where x < 3) select min(a1.x) from t a1, t a2;
----
1
# nested uncorrelated subquery
query I
with recursive t as (select 1 as x union all select x+(SELECT 1) from t where x < 3) select * from t;
----
1
2
3
# use with recursive in table creation
statement ok
create table integers as with recursive t as (select 1 as x union all select x+1 from t where x < 3) select * from t;
# more complex uncorrelated subquery
query I
with recursive t as (select (select min(x) from integers) as x union all select x+1 from t where x < 3) select * from t;
----
1
2
3
# aggregate function
query I
with recursive t as (select 1 as x union all select sum(x+1) AS x from t where x < 3 group by x) select * from t
----
1
2
3
# some of the following recursive queries are terminated by the LIMIT clause
# this requires CTE inlining, which enable_verification disables
require no_alternative_verify
statement ok
PRAGMA disable_verification
# infinite aggregate function: will result in timeout if pipelining is not implemented
query I
with recursive t as (select 1 as x union all select sum(x+1) AS x from t where x < 3)
select * from (select * from t limit 10) t1(x) order by x nulls last
----
1
2
3
NULL
NULL
NULL
NULL
NULL
NULL
NULL
statement ok
PRAGMA enable_verification
# recursive CTE with table-producing function
query I
WITH RECURSIVE t AS (
SELECT 1 AS i
UNION ALL
SELECT j
FROM t, generate_series(0, 10, 1) series(j)
WHERE j=i+1
)
SELECT * FROM t;
----
1
2
3
4
5
6
7
8
9
10
# order by is not allowed in the recursive term of ctes
statement error
with recursive t as (select 1 as x union all select x+1 from t where x < 3 order by x) select * from t
----
<REGEX>:.*Parser Error.*recursive query is not allowed.*
# limit is not allowed in the recursive term of ctes
statement error
with recursive t as (select 1 as x union all select x+1 from t where x < 3 LIMIT 1) select * from t
----
<REGEX>:.*Parser Error.*recursive query is not allowed.*
# offset is not allowed in the recursive term of ctes
statement error
with recursive t as (select 1 as x union all select x+1 from t where x < 3 OFFSET 1) select * from t
----
<REGEX>:.*Parser Error.*recursive query is not allowed.*
# offset is not allowed in the recursive term of ctes
statement error
with recursive t as (select 1 as x union all select x+1 from t where x < 3 LIMIT 1 OFFSET 1) select * from t
----
<REGEX>:.*Parser Error.*recursive query is not allowed.*