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

Commit3753df8

Browse files
committed
Cope with lateral references in the quals of a subquery RTE.
The qual pushdown logic assumed that all Vars in a restriction clausemust be Vars referencing subquery outputs; but since we introducedLATERAL, it's possible for such a Var to be a lateral reference instead.This led to an assertion failure in debug builds. In a non-debugbuild, there might be no ill effects (if qual_is_pushdown_safe decidedthe qual was unsafe anyway), or we could get failures later due toconstruction of an invalid plan. I've not gone to much length tocharacterize the possible failures, but at least segfaults in theexecutor have been observed.Given that this has been busted since 9.3 and it took this long foranybody to notice, I judge that the case isn't worth going to greatlengths to optimize. Hence, fix by just teaching qual_is_pushdown_safethat such quals are unsafe to push down, matching the previous behaviorwhen it accidentally didn't fail.Per report from Tom Ellis. Back-patch to all supported branches.Discussion:https://postgr.es/m/20200713175124.GQ8220@cloudinit-builder
1 parent4fdc559 commit3753df8

File tree

3 files changed

+96
-3
lines changed

3 files changed

+96
-3
lines changed

‎src/backend/optimizer/path/allpaths.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3154,8 +3154,10 @@ qual_is_pushdown_safe(Query *subquery, Index rti, Node *qual,
31543154
Assert(!contain_window_function(qual));
31553155

31563156
/*
3157-
* Examine all Vars used in clause; since it's a restriction clause, all
3158-
* such Vars must refer to subselect output columns.
3157+
* Examine all Vars used in clause. Since it's a restriction clause, all
3158+
* such Vars must refer to subselect output columns ... unless this is
3159+
* part of a LATERAL subquery, in which case there could be lateral
3160+
* references.
31593161
*/
31603162
vars=pull_var_clause(qual,PVC_INCLUDE_PLACEHOLDERS);
31613163
foreach(vl,vars)
@@ -3175,7 +3177,19 @@ qual_is_pushdown_safe(Query *subquery, Index rti, Node *qual,
31753177
break;
31763178
}
31773179

3178-
Assert(var->varno==rti);
3180+
/*
3181+
* Punt if we find any lateral references. It would be safe to push
3182+
* these down, but we'd have to convert them into outer references,
3183+
* which subquery_push_qual lacks the infrastructure to do. The case
3184+
* arises so seldom that it doesn't seem worth working hard on.
3185+
*/
3186+
if (var->varno!=rti)
3187+
{
3188+
safe= false;
3189+
break;
3190+
}
3191+
3192+
/* Subqueries have no system columns */
31793193
Assert(var->varattno >=0);
31803194

31813195
/* Check point 4 */

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

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,6 +1127,59 @@ from int4_tbl;
11271127
(4,5,6.0)
11281128
(5 rows)
11291129

1130+
--
1131+
-- Check for sane handling of a lateral reference in a subquery's quals
1132+
-- (most of the complication here is to prevent the test case from being
1133+
-- flattened too much)
1134+
--
1135+
explain (verbose, costs off)
1136+
select * from
1137+
int4_tbl i4,
1138+
lateral (
1139+
select i4.f1 > 1 as b, 1 as id
1140+
from (select random() order by 1) as t1
1141+
union all
1142+
select true as b, 2 as id
1143+
) as t2
1144+
where b and f1 >= 0;
1145+
QUERY PLAN
1146+
--------------------------------------------
1147+
Nested Loop
1148+
Output: i4.f1, ((i4.f1 > 1)), (1)
1149+
-> Seq Scan on public.int4_tbl i4
1150+
Output: i4.f1
1151+
Filter: (i4.f1 >= 0)
1152+
-> Append
1153+
-> Subquery Scan on t1
1154+
Output: (i4.f1 > 1), 1
1155+
Filter: (i4.f1 > 1)
1156+
-> Sort
1157+
Output: (random())
1158+
Sort Key: (random())
1159+
-> Result
1160+
Output: random()
1161+
-> Result
1162+
Output: true, 2
1163+
(16 rows)
1164+
1165+
select * from
1166+
int4_tbl i4,
1167+
lateral (
1168+
select i4.f1 > 1 as b, 1 as id
1169+
from (select random() order by 1) as t1
1170+
union all
1171+
select true as b, 2 as id
1172+
) as t2
1173+
where b and f1 >= 0;
1174+
f1 | b | id
1175+
------------+---+----
1176+
0 | t | 2
1177+
123456 | t | 1
1178+
123456 | t | 2
1179+
2147483647 | t | 1
1180+
2147483647 | t | 2
1181+
(5 rows)
1182+
11301183
--
11311184
-- Check that volatile quals aren't pushed down past a DISTINCT:
11321185
-- nextval() should not be called more than the nominal number of times

‎src/test/regress/sql/subselect.sql

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,32 @@ select (select q from
601601
) q )
602602
from int4_tbl;
603603

604+
--
605+
-- Check for sane handling of a lateral reference in a subquery's quals
606+
-- (most of the complication here is to prevent the test case from being
607+
-- flattened too much)
608+
--
609+
explain (verbose, costs off)
610+
select*from
611+
int4_tbl i4,
612+
lateral (
613+
selecti4.f1>1as b,1as id
614+
from (select random()order by1)as t1
615+
union all
616+
select trueas b,2as id
617+
)as t2
618+
where band f1>=0;
619+
620+
select*from
621+
int4_tbl i4,
622+
lateral (
623+
selecti4.f1>1as b,1as id
624+
from (select random()order by1)as t1
625+
union all
626+
select trueas b,2as id
627+
)as t2
628+
where band f1>=0;
629+
604630
--
605631
-- Check that volatile quals aren't pushed down past a DISTINCT:
606632
-- nextval() should not be called more than the nominal number of times

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp