aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/parser/parse_cte.c12
-rw-r--r--src/test/regress/expected/with.out59
-rw-r--r--src/test/regress/sql/with.sql44
3 files changed, 109 insertions, 6 deletions
diff --git a/src/backend/parser/parse_cte.c b/src/backend/parser/parse_cte.c
index 1fca7485ca3..b24989e4170 100644
--- a/src/backend/parser/parse_cte.c
+++ b/src/backend/parser/parse_cte.c
@@ -537,15 +537,15 @@ makeDependencyGraphWalker(Node *node, CteState *cstate)
* In the non-RECURSIVE case, query names are visible to the
* WITH items after them and to the main query.
*/
- ListCell *cell1;
-
cstate->innerwiths = lcons(NIL, cstate->innerwiths);
- cell1 = list_head(cstate->innerwiths);
foreach(lc, stmt->withClause->ctes)
{
CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
+ ListCell *cell1;
(void) makeDependencyGraphWalker(cte->ctequery, cstate);
+ /* note that recursion could mutate innerwiths list */
+ cell1 = list_head(cstate->innerwiths);
lfirst(cell1) = lappend((List *) lfirst(cell1), cte);
}
(void) raw_expression_tree_walker(node,
@@ -813,15 +813,15 @@ checkWellFormedRecursionWalker(Node *node, CteState *cstate)
* In the non-RECURSIVE case, query names are visible to the
* WITH items after them and to the main query.
*/
- ListCell *cell1;
-
cstate->innerwiths = lcons(NIL, cstate->innerwiths);
- cell1 = list_head(cstate->innerwiths);
foreach(lc, stmt->withClause->ctes)
{
CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
+ ListCell *cell1;
(void) checkWellFormedRecursionWalker(cte->ctequery, cstate);
+ /* note that recursion could mutate innerwiths list */
+ cell1 = list_head(cstate->innerwiths);
lfirst(cell1) = lappend((List *) lfirst(cell1), cte);
}
checkWellFormedSelectStmt(stmt, cstate);
diff --git a/src/test/regress/expected/with.out b/src/test/regress/expected/with.out
index 67eaeb4f3ed..0d506348e1c 100644
--- a/src/test/regress/expected/with.out
+++ b/src/test/regress/expected/with.out
@@ -167,6 +167,65 @@ ERROR: operator does not exist: text + integer
LINE 4: SELECT n+1 FROM t WHERE n < 10
^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
+-- Deeply nested WITH caused a list-munging problem in v13
+-- Detection of cross-references and self-references
+WITH RECURSIVE w1(c1) AS
+ (WITH w2(c2) AS
+ (WITH w3(c3) AS
+ (WITH w4(c4) AS
+ (WITH w5(c5) AS
+ (WITH RECURSIVE w6(c6) AS
+ (WITH w6(c6) AS
+ (WITH w8(c8) AS
+ (SELECT 1)
+ SELECT * FROM w8)
+ SELECT * FROM w6)
+ SELECT * FROM w6)
+ SELECT * FROM w5)
+ SELECT * FROM w4)
+ SELECT * FROM w3)
+ SELECT * FROM w2)
+SELECT * FROM w1;
+ c1
+----
+ 1
+(1 row)
+
+-- Detection of invalid self-references
+WITH RECURSIVE outermost(x) AS (
+ SELECT 1
+ UNION (WITH innermost1 AS (
+ SELECT 2
+ UNION (WITH innermost2 AS (
+ SELECT 3
+ UNION (WITH innermost3 AS (
+ SELECT 4
+ UNION (WITH innermost4 AS (
+ SELECT 5
+ UNION (WITH innermost5 AS (
+ SELECT 6
+ UNION (WITH innermost6 AS
+ (SELECT 7)
+ SELECT * FROM innermost6))
+ SELECT * FROM innermost5))
+ SELECT * FROM innermost4))
+ SELECT * FROM innermost3))
+ SELECT * FROM innermost2))
+ SELECT * FROM outermost
+ UNION SELECT * FROM innermost1)
+ )
+ SELECT * FROM outermost ORDER BY 1;
+ x
+---
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+(7 rows)
+
--
-- Some examples with a tree
--
diff --git a/src/test/regress/sql/with.sql b/src/test/regress/sql/with.sql
index f85645efdee..43cd2e10af3 100644
--- a/src/test/regress/sql/with.sql
+++ b/src/test/regress/sql/with.sql
@@ -87,6 +87,50 @@ UNION ALL
)
SELECT n, n IS OF (int) AS is_int FROM t;
+-- Deeply nested WITH caused a list-munging problem in v13
+-- Detection of cross-references and self-references
+WITH RECURSIVE w1(c1) AS
+ (WITH w2(c2) AS
+ (WITH w3(c3) AS
+ (WITH w4(c4) AS
+ (WITH w5(c5) AS
+ (WITH RECURSIVE w6(c6) AS
+ (WITH w6(c6) AS
+ (WITH w8(c8) AS
+ (SELECT 1)
+ SELECT * FROM w8)
+ SELECT * FROM w6)
+ SELECT * FROM w6)
+ SELECT * FROM w5)
+ SELECT * FROM w4)
+ SELECT * FROM w3)
+ SELECT * FROM w2)
+SELECT * FROM w1;
+-- Detection of invalid self-references
+WITH RECURSIVE outermost(x) AS (
+ SELECT 1
+ UNION (WITH innermost1 AS (
+ SELECT 2
+ UNION (WITH innermost2 AS (
+ SELECT 3
+ UNION (WITH innermost3 AS (
+ SELECT 4
+ UNION (WITH innermost4 AS (
+ SELECT 5
+ UNION (WITH innermost5 AS (
+ SELECT 6
+ UNION (WITH innermost6 AS
+ (SELECT 7)
+ SELECT * FROM innermost6))
+ SELECT * FROM innermost5))
+ SELECT * FROM innermost4))
+ SELECT * FROM innermost3))
+ SELECT * FROM innermost2))
+ SELECT * FROM outermost
+ UNION SELECT * FROM innermost1)
+ )
+ SELECT * FROM outermost ORDER BY 1;
+
--
-- Some examples with a tree
--