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,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