Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import scala.collection.mutable

import org.apache.spark.sql.AnalysisException
import org.apache.spark.sql.catalyst.expressions.SubqueryExpression
import org.apache.spark.sql.catalyst.plans.{Inner, LeftAnti, LeftOuter, LeftSemi, RightOuter}
import org.apache.spark.sql.catalyst.plans.{Cross, Inner, LeftAnti, LeftOuter, LeftSemi, RightOuter}
import org.apache.spark.sql.catalyst.plans.logical._
import org.apache.spark.sql.catalyst.rules.Rule
import org.apache.spark.sql.catalyst.trees.TreePattern.{CTE, PLAN_EXPRESSION}
Expand Down Expand Up @@ -220,6 +220,9 @@ object ResolveWithCTE extends Rule[LogicalPlan] {
case Join(left, right, Inner, _, _) =>
checkIfSelfReferenceIsPlacedCorrectly(left, cteId, allowRecursiveRef)
checkIfSelfReferenceIsPlacedCorrectly(right, cteId, allowRecursiveRef)
case Join(left, right, Cross, _, _) =>
checkIfSelfReferenceIsPlacedCorrectly(left, cteId, allowRecursiveRef)
checkIfSelfReferenceIsPlacedCorrectly(right, cteId, allowRecursiveRef)
case Join(left, right, LeftOuter, _, _) =>
checkIfSelfReferenceIsPlacedCorrectly(left, cteId, allowRecursiveRef)
checkIfSelfReferenceIsPlacedCorrectly(right, cteId, allowRecursiveRef = false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1167,3 +1167,92 @@ WithCTE
+- Project [a#x]
+- SubqueryAlias t1
+- CTERelationRef xxxx, true, [a#x, b#x, c#x], false, false


-- !query
CREATE TABLE tb (next INT)
-- !query analysis
CreateDataSourceTableCommand `spark_catalog`.`default`.`tb`, false


-- !query
INSERT INTO tb VALUES (0), (1)
-- !query analysis
InsertIntoHadoopFsRelationCommand file:[not included in comparison]/{warehouse_dir}/tb, false, Parquet, [path=file:[not included in comparison]/{warehouse_dir}/tb], Append, `spark_catalog`.`default`.`tb`, org.apache.spark.sql.execution.datasources.InMemoryFileIndex(file:[not included in comparison]/{warehouse_dir}/tb), [next]
+- Project [cast(col1#x as int) AS next#x]
+- LocalRelation [col1#x]


-- !query
WITH RECURSIVE t(n) AS (
SELECT 1
UNION ALL
SELECT next FROM t CROSS JOIN tb
)
SELECT * FROM t LIMIT 63
-- !query analysis
WithCTE
:- CTERelationDef xxxx, false
: +- SubqueryAlias t
: +- Project [1#x AS n#x]
: +- UnionLoop xxxx
: :- Project [1 AS 1#x]
: : +- OneRowRelation
: +- Project [next#x]
: +- Join Cross
: :- SubqueryAlias t
: : +- Project [1#x AS n#x]
: : +- UnionLoopRef xxxx, [1#x], false
: +- SubqueryAlias spark_catalog.default.tb
: +- Relation spark_catalog.default.tb[next#x] parquet
+- GlobalLimit 63
+- LocalLimit 63
+- Project [n#x]
+- SubqueryAlias t
+- CTERelationRef xxxx, true, [n#x], false, false


-- !query
DROP TABLE tb
-- !query analysis
DropTable false, false
+- ResolvedIdentifier V2SessionCatalog(spark_catalog), default.tb


-- !query
WITH RECURSIVE
x(id) AS (SELECT 1 UNION SELECT 2),
t(id, xid) AS (
SELECT 0 AS id, 0 AS xid
UNION ALL
SELECT t.id + 1, xid * 10 + x.id FROM t CROSS JOIN x WHERE t.id < 3
)
SELECT * FROM t
-- !query analysis
WithCTE
:- CTERelationDef xxxx, false
: +- SubqueryAlias x
: +- Project [1#x AS id#x]
: +- Distinct
: +- Union false, false
: :- Project [1 AS 1#x]
: : +- OneRowRelation
: +- Project [2 AS 2#x]
: +- OneRowRelation
:- CTERelationDef xxxx, false
: +- SubqueryAlias t
: +- Project [id#x AS id#x, xid#x AS xid#x]
: +- UnionLoop xxxx
: :- Project [0 AS id#x, 0 AS xid#x]
: : +- OneRowRelation
: +- Project [(id#x + 1) AS (id + 1)#x, ((xid#x * 10) + id#x) AS ((xid * 10) + id)#x]
: +- Filter (id#x < 3)
: +- Join Cross
: :- SubqueryAlias t
: : +- Project [id#x AS id#x, xid#x AS xid#x]
: : +- UnionLoopRef xxxx, [id#x, xid#x], false
: +- SubqueryAlias x
: +- CTERelationRef xxxx, true, [id#x], false, false, 2
+- Project [id#x, xid#x]
+- SubqueryAlias t
+- CTERelationRef xxxx, true, [id#x, xid#x], false, false
26 changes: 25 additions & 1 deletion sql/core/src/test/resources/sql-tests/inputs/cte-recursion.sql
Original file line number Diff line number Diff line change
Expand Up @@ -462,4 +462,28 @@ WITH RECURSIVE t1(a,b,c) AS (
SELECT 1,1,1
UNION ALL
SELECT a+1,a+1,a+1 FROM t1)
SELECT a FROM t1 LIMIT 5;
SELECT a FROM t1 LIMIT 5;

-- CROSS JOIN example
CREATE TABLE tb (next INT);

INSERT INTO tb VALUES (0), (1);

WITH RECURSIVE t(n) AS (
SELECT 1
UNION ALL
SELECT next FROM t CROSS JOIN tb
)
SELECT * FROM t LIMIT 63;

DROP TABLE tb;
-- CROSS JOIN example 2

WITH RECURSIVE
x(id) AS (SELECT 1 UNION SELECT 2),
t(id, xid) AS (
SELECT 0 AS id, 0 AS xid
UNION ALL
SELECT t.id + 1, xid * 10 + x.id FROM t CROSS JOIN x WHERE t.id < 3
)
SELECT * FROM t
128 changes: 128 additions & 0 deletions sql/core/src/test/resources/sql-tests/results/cte-recursion.sql.out
Original file line number Diff line number Diff line change
Expand Up @@ -1050,3 +1050,131 @@ struct<a:int>
3
4
5


-- !query
CREATE TABLE tb (next INT)
-- !query schema
struct<>
-- !query output



-- !query
INSERT INTO tb VALUES (0), (1)
-- !query schema
struct<>
-- !query output



-- !query
WITH RECURSIVE t(n) AS (
SELECT 1
UNION ALL
SELECT next FROM t CROSS JOIN tb
)
SELECT * FROM t LIMIT 63
-- !query schema
struct<n:int>
-- !query output
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1


-- !query
DROP TABLE tb
-- !query schema
struct<>
-- !query output



-- !query
WITH RECURSIVE
x(id) AS (SELECT 1 UNION SELECT 2),
t(id, xid) AS (
SELECT 0 AS id, 0 AS xid
UNION ALL
SELECT t.id + 1, xid * 10 + x.id FROM t CROSS JOIN x WHERE t.id < 3
)
SELECT * FROM t
-- !query schema
struct<id:int,xid:int>
-- !query output
0 0
1 1
1 2
2 11
2 12
2 21
2 22
3 111
3 112
3 121
3 122
3 211
3 212
3 221
3 222