Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf819020

Browse files
committed
Fix incautious CTE matching in rewriteSearchAndCycle().
This function looks for a reference to the recursive WITH CTE,but it checked only the CTE name not ctelevelsup, so that it couldseize on a lower CTE that happened to have the same name. Thiswould result in planner failures later, either weird errors such as"could not find attribute 2 in subquery targetlist", or crashesor assertion failures. The code also merely Assert'ed that it founda matching entry, which is not guaranteed at all by the parser.Per bugs #17320 and #17318 from Zhiyong Wu.Thanks to Kyotaro Horiguchi for investigation.Discussion:https://postgr.es/m/17320-70e37868182512ab@postgresql.orgDiscussion:https://postgr.es/m/17318-2eb65a3a611d2368@postgresql.org
1 parentc1da0ac commitf819020

File tree

3 files changed

+36
-3
lines changed

3 files changed

+36
-3
lines changed

‎src/backend/rewrite/rewriteSearchCycle.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -383,19 +383,32 @@ rewriteSearchAndCycle(CommonTableExpr *cte)
383383
newrte->eref=newrte->alias;
384384

385385
/*
386-
* Find the reference to our CTE in the range table
386+
* Find the reference to the recursive CTE in the right UNION subquery's
387+
* range table. We expect it to be two levels up from the UNION subquery
388+
* (and must check that to avoid being fooled by sub-WITHs with the same
389+
* CTE name). There will not be more than one such reference, because the
390+
* parser would have rejected that (see checkWellFormedRecursion() in
391+
* parse_cte.c). However, the parser doesn't insist that the reference
392+
* appear in the UNION subquery's topmost range table, so we might fail to
393+
* find it at all. That's an unimplemented case for the moment.
387394
*/
388395
for (intrti=1;rti <=list_length(rte2->subquery->rtable);rti++)
389396
{
390397
RangeTblEntry*e=rt_fetch(rti,rte2->subquery->rtable);
391398

392-
if (e->rtekind==RTE_CTE&&strcmp(cte->ctename,e->ctename)==0)
399+
if (e->rtekind==RTE_CTE&&
400+
strcmp(cte->ctename,e->ctename)==0&&
401+
e->ctelevelsup==2)
393402
{
394403
cte_rtindex=rti;
395404
break;
396405
}
397406
}
398-
Assert(cte_rtindex>0);
407+
if (cte_rtindex <=0)
408+
ereport(ERROR,
409+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
410+
errmsg("with a SEARCH or CYCLE clause, the recursive reference to WITH query \"%s\" must be at the top level of its right-hand SELECT",
411+
cte->ctename)));
399412

400413
newsubquery=copyObject(rte2->subquery);
401414
IncrementVarSublevelsUp((Node*)newsubquery,1,1);

‎src/test/regress/expected/with.out

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,16 @@ with recursive search_graph(f, t, label) as (
846846
) search depth first by f, t set seq
847847
select * from search_graph order by seq;
848848
ERROR: with a SEARCH or CYCLE clause, the right side of the UNION must be a SELECT
849+
-- check that we distinguish same CTE name used at different levels
850+
-- (this case could be supported, perhaps, but it isn't today)
851+
with recursive x(col) as (
852+
select 1
853+
union
854+
(with x as (select * from x)
855+
select * from x)
856+
) search depth first by col set seq
857+
select * from x;
858+
ERROR: with a SEARCH or CYCLE clause, the recursive reference to WITH query "x" must be at the top level of its right-hand SELECT
849859
-- test ruleutils and view expansion
850860
create temp view v_search as
851861
with recursive search_graph(f, t, label) as (

‎src/test/regress/sql/with.sql

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,16 @@ with recursive search_graph(f, t, label) as (
464464
) search depth first by f, tset seq
465465
select*from search_graphorder by seq;
466466

467+
-- check that we distinguish same CTE name used at different levels
468+
-- (this case could be supported, perhaps, but it isn't today)
469+
with recursive x(col)as (
470+
select1
471+
union
472+
(with xas (select*from x)
473+
select*from x)
474+
) search depth first by colset seq
475+
select*from x;
476+
467477
-- test ruleutils and view expansion
468478
create temp view v_searchas
469479
with recursive search_graph(f, t, label)as (

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp