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

Commit9f95417

Browse files
committed
Correctly identify which EC members are computable at a plan node.
find_computable_ec_member() had the wrong mental model of whatits primary caller prepare_sort_from_pathkeys() would do withthe selected EquivalenceClass member expression. We will notcompute the EC expression in a plan node atop the one returningthe passed-in targetlist; rather, the EC expression will becomputed as an additional column of that targetlist. So anyVar or quasi-Var used in the given tlist is also available to theEC expression. In simple cases this makes no difference becausethe given tlist is just a list of Vars or quasi-Vars --- but ifwe are considering an appendrel member produced by flatteninga UNION ALL, the tlist may contain expressions, resulting infailure to match and a "could not find pathkey item to sort"error.To fix, we can flatten both the tlist and the EC members withpull_var_clause(), and then just check for subset-ness, sothat the code is actually shorter than before.While this bug is quite old, the present patch only works back tov13. We could possibly make it work in v12 by back-patching partsof3753982. On the whole though I don't like the risk/rewardratio of that idea. v12's final release is next month, meaningthere would be no chance to correct matters if the patch causes aregression. Since this failure has escaped notice for 14 years,it's likely nobody will hit it in the field with v12.Per bug #18652 from Alexander Lakhin.Andrei Lepikhov and Tom LaneDiscussion:https://postgr.es/m/18652-deaa782ebcca85d1@postgresql.org
1 parent98c5b19 commit9f95417

File tree

3 files changed

+71
-38
lines changed

3 files changed

+71
-38
lines changed

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

Lines changed: 33 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ static EquivalenceMember *add_eq_member(EquivalenceClass *ec,
3838
JoinDomain*jdomain,
3939
EquivalenceMember*parent,
4040
Oiddatatype);
41-
staticboolis_exprlist_member(Expr*node,List*exprs);
4241
staticvoidgenerate_base_implied_equalities_const(PlannerInfo*root,
4342
EquivalenceClass*ec);
4443
staticvoidgenerate_base_implied_equalities_no_const(PlannerInfo*root,
@@ -810,9 +809,18 @@ find_ec_member_matching_expr(EquivalenceClass *ec,
810809
*expressions appearing in "exprs"; return NULL if no match.
811810
*
812811
* "exprs" can be either a list of bare expression trees, or a list of
813-
* TargetEntry nodes. Either way, it should contain Vars and possibly
814-
* Aggrefs and WindowFuncs, which are matched to the corresponding elements
815-
* of the EquivalenceClass's expressions.
812+
* TargetEntry nodes. Typically it will contain Vars and possibly Aggrefs
813+
* and WindowFuncs; however, when considering an appendrel member the list
814+
* could contain arbitrary expressions. We consider an EC member to be
815+
* computable if all the Vars, PlaceHolderVars, Aggrefs, and WindowFuncs
816+
* it needs are present in "exprs".
817+
*
818+
* There is some subtlety in that definition: for example, if an EC member is
819+
* Var_A + 1 while what is in "exprs" is Var_A + 2, it's still computable.
820+
* This works because in the final plan tree, the EC member's expression will
821+
* be computed as part of the same plan node targetlist that is currently
822+
* represented by "exprs". So if we have Var_A available for the existing
823+
* tlist member, it must be OK to use it in the EC expression too.
816824
*
817825
* Unlike find_ec_member_matching_expr, there's no special provision here
818826
* for binary-compatible relabeling. This is intentional: if we have to
@@ -832,12 +840,24 @@ find_computable_ec_member(PlannerInfo *root,
832840
Relidsrelids,
833841
boolrequire_parallel_safe)
834842
{
843+
List*exprvars;
835844
ListCell*lc;
836845

846+
/*
847+
* Pull out the Vars and quasi-Vars present in "exprs". In the typical
848+
* non-appendrel case, this is just another representation of the same
849+
* list. However, it does remove the distinction between the case of a
850+
* list of plain expressions and a list of TargetEntrys.
851+
*/
852+
exprvars=pull_var_clause((Node*)exprs,
853+
PVC_INCLUDE_AGGREGATES |
854+
PVC_INCLUDE_WINDOWFUNCS |
855+
PVC_INCLUDE_PLACEHOLDERS);
856+
837857
foreach(lc,ec->ec_members)
838858
{
839859
EquivalenceMember*em= (EquivalenceMember*)lfirst(lc);
840-
List*exprvars;
860+
List*emvars;
841861
ListCell*lc2;
842862

843863
/*
@@ -855,18 +875,18 @@ find_computable_ec_member(PlannerInfo *root,
855875
continue;
856876

857877
/*
858-
* Match if all Vars and quasi-Vars areavailable in "exprs".
878+
* Match if all Vars and quasi-Vars arepresent in "exprs".
859879
*/
860-
exprvars=pull_var_clause((Node*)em->em_expr,
861-
PVC_INCLUDE_AGGREGATES |
862-
PVC_INCLUDE_WINDOWFUNCS |
863-
PVC_INCLUDE_PLACEHOLDERS);
864-
foreach(lc2,exprvars)
880+
emvars=pull_var_clause((Node*)em->em_expr,
881+
PVC_INCLUDE_AGGREGATES |
882+
PVC_INCLUDE_WINDOWFUNCS |
883+
PVC_INCLUDE_PLACEHOLDERS);
884+
foreach(lc2,emvars)
865885
{
866-
if (!is_exprlist_member(lfirst(lc2),exprs))
886+
if (!list_member(exprvars,lfirst(lc2)))
867887
break;
868888
}
869-
list_free(exprvars);
889+
list_free(emvars);
870890
if (lc2)
871891
continue;/* we hit a non-available Var */
872892

@@ -884,31 +904,6 @@ find_computable_ec_member(PlannerInfo *root,
884904
returnNULL;
885905
}
886906

887-
/*
888-
* is_exprlist_member
889-
* Subroutine for find_computable_ec_member: is "node" in "exprs"?
890-
*
891-
* Per the requirements of that function, "exprs" might or might not have
892-
* TargetEntry superstructure.
893-
*/
894-
staticbool
895-
is_exprlist_member(Expr*node,List*exprs)
896-
{
897-
ListCell*lc;
898-
899-
foreach(lc,exprs)
900-
{
901-
Expr*expr= (Expr*)lfirst(lc);
902-
903-
if (expr&&IsA(expr,TargetEntry))
904-
expr= ((TargetEntry*)expr)->expr;
905-
906-
if (equal(node,expr))
907-
return true;
908-
}
909-
return false;
910-
}
911-
912907
/*
913908
* relation_can_be_sorted_early
914909
*Can this relation be sorted on this EC before the final output step?

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1678,6 +1678,36 @@ select min(1-id) from matest0;
16781678

16791679
reset enable_seqscan;
16801680
reset enable_parallel_append;
1681+
explain (verbose, costs off) -- bug #18652
1682+
select 1 - id as c from
1683+
(select id from matest3 t1 union all select id * 2 from matest3 t2) ss
1684+
order by c;
1685+
QUERY PLAN
1686+
------------------------------------------------------------
1687+
Result
1688+
Output: ((1 - t1.id))
1689+
-> Merge Append
1690+
Sort Key: ((1 - t1.id))
1691+
-> Index Scan using matest3i on public.matest3 t1
1692+
Output: t1.id, (1 - t1.id)
1693+
-> Sort
1694+
Output: ((t2.id * 2)), ((1 - (t2.id * 2)))
1695+
Sort Key: ((1 - (t2.id * 2)))
1696+
-> Seq Scan on public.matest3 t2
1697+
Output: (t2.id * 2), (1 - (t2.id * 2))
1698+
(11 rows)
1699+
1700+
select 1 - id as c from
1701+
(select id from matest3 t1 union all select id * 2 from matest3 t2) ss
1702+
order by c;
1703+
c
1704+
-----
1705+
-11
1706+
-9
1707+
-5
1708+
-4
1709+
(4 rows)
1710+
16811711
drop table matest0 cascade;
16821712
NOTICE: drop cascades to 3 other objects
16831713
DETAIL: drop cascades to table matest1

‎src/test/regress/sql/inherit.sql‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,14 @@ select min(1-id) from matest0;
601601
reset enable_seqscan;
602602
reset enable_parallel_append;
603603

604+
explain (verbose, costs off)-- bug #18652
605+
select1- idas cfrom
606+
(select idfrom matest3 t1union allselect id*2from matest3 t2) ss
607+
order by c;
608+
select1- idas cfrom
609+
(select idfrom matest3 t1union allselect id*2from matest3 t2) ss
610+
order by c;
611+
604612
droptable matest0 cascade;
605613

606614
--

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp