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

Commite76af54

Browse files
committed
Fix some issues with LATERAL(SELECT UNION ALL SELECT).
The LATERAL marking has to be propagated down to the UNION leaf querieswhen we pull them up. Also, fix the formerly stubbed-offset_append_rel_pathlist(). It does already have enough smarts to cope withmaking a parameterized Append path at need; it just has to not assume thatthere *must* be an unparameterized path.
1 parent83af58f commite76af54

File tree

4 files changed

+94
-30
lines changed

4 files changed

+94
-30
lines changed

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

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,7 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
661661
intparentRTindex=rti;
662662
List*live_childrels=NIL;
663663
List*subpaths=NIL;
664+
boolsubpaths_valid= true;
664665
List*all_child_pathkeys=NIL;
665666
List*all_child_outers=NIL;
666667
ListCell*l;
@@ -699,19 +700,21 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
699700
if (IS_DUMMY_REL(childrel))
700701
continue;
701702

702-
/* XXX need to figure out what to do for LATERAL */
703-
if (childrel->cheapest_total_path==NULL)
704-
elog(ERROR,"LATERAL within an append relation is not supported yet");
703+
/*
704+
* Child is live, so add it to the live_childrels list for use below.
705+
*/
706+
live_childrels=lappend(live_childrels,childrel);
705707

706708
/*
707-
* Child is live, so add its cheapest access path to the Append path
708-
* we are constructing for the parent.
709+
* If child has an unparameterized cheapest-total path, add that to
710+
* the unparameterized Append path we are constructing for the parent.
711+
* If not, there's no workable unparameterized path.
709712
*/
710-
subpaths=accumulate_append_subpath(subpaths,
713+
if (childrel->cheapest_total_path)
714+
subpaths=accumulate_append_subpath(subpaths,
711715
childrel->cheapest_total_path);
712-
713-
/* Remember which childrels are live, for logic below */
714-
live_childrels=lappend(live_childrels,childrel);
716+
else
717+
subpaths_valid= false;
715718

716719
/*
717720
* Collect lists of all the available path orderings and
@@ -779,17 +782,20 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
779782
}
780783

781784
/*
782-
*Next, build an unordered,unparameterizedAppend pathforthe rel.
783-
*(Note: this is correct even if we have zero or one live subpath due to
784-
* constraint exclusion.)
785+
*If we foundunparameterizedpathsforall children, build an unordered,
786+
*unparameterized Append path for the rel. (Note: this is correct even
787+
*if we have zero or one live subpath due toconstraint exclusion.)
785788
*/
786-
add_path(rel, (Path*)create_append_path(rel,subpaths,NULL));
789+
if (subpaths_valid)
790+
add_path(rel, (Path*)create_append_path(rel,subpaths,NULL));
787791

788792
/*
789-
*Buildunparameterized MergeAppend paths based on the collected list of
790-
* child pathkeys.
793+
*Also buildunparameterized MergeAppend paths based on the collected
794+
*list ofchild pathkeys.
791795
*/
792-
generate_mergeappend_paths(root,rel,live_childrels,all_child_pathkeys);
796+
if (subpaths_valid)
797+
generate_mergeappend_paths(root,rel,live_childrels,
798+
all_child_pathkeys);
793799

794800
/*
795801
* Build Append paths for each parameterization seen among the child rels.
@@ -807,11 +813,11 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
807813
foreach(l,all_child_outers)
808814
{
809815
Relidsrequired_outer= (Relids)lfirst(l);
810-
boolok= true;
811816
ListCell*lcr;
812817

813818
/* Select the child paths for an Append with this parameterization */
814819
subpaths=NIL;
820+
subpaths_valid= true;
815821
foreach(lcr,live_childrels)
816822
{
817823
RelOptInfo*childrel= (RelOptInfo*)lfirst(lcr);
@@ -831,15 +837,15 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
831837
required_outer,1.0);
832838
if (cheapest_total==NULL)
833839
{
834-
ok= false;
840+
subpaths_valid= false;
835841
break;
836842
}
837843
}
838844

839845
subpaths=accumulate_append_subpath(subpaths,cheapest_total);
840846
}
841847

842-
if (ok)
848+
if (subpaths_valid)
843849
add_path(rel, (Path*)
844850
create_append_path(rel,subpaths,required_outer));
845851
}
@@ -911,13 +917,11 @@ generate_mergeappend_paths(PlannerInfo *root, RelOptInfo *rel,
911917
*/
912918
if (cheapest_startup==NULL||cheapest_total==NULL)
913919
{
914-
/* XXX need to figure out what to do for LATERAL */
915-
if (childrel->cheapest_total_path==NULL)
916-
elog(ERROR,"LATERAL within an append relation is not supported yet");
917-
918920
cheapest_startup=cheapest_total=
919921
childrel->cheapest_total_path;
922+
/* Assert we do have an unparameterized path for this child */
920923
Assert(cheapest_total!=NULL);
924+
Assert(cheapest_total->param_info==NULL);
921925
}
922926

923927
/*

‎src/backend/optimizer/prep/prepjointree.c

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -995,20 +995,45 @@ pull_up_simple_union_all(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte)
995995
{
996996
intvarno= ((RangeTblRef*)jtnode)->rtindex;
997997
Query*subquery=rte->subquery;
998-
intrtoffset;
998+
intrtoffset=list_length(root->parse->rtable);
999999
List*rtable;
10001000

10011001
/*
1002-
* Append child RTEs to parent rtable.
1003-
*
1002+
* Make a modifiable copy of the subquery's rtable, so we can adjust
1003+
* upper-level Vars in it. There are no such Vars in the setOperations
1004+
* tree proper, so fixing the rtable should be sufficient.
1005+
*/
1006+
rtable=copyObject(subquery->rtable);
1007+
1008+
/*
10041009
* Upper-level vars in subquery are now one level closer to their parent
10051010
* than before. We don't have to worry about offsetting varnos, though,
1006-
* because any such vars must refer to stuff above the level of the query
1007-
* we are pulling into.
1011+
* because the UNION leaf queries can't cross-reference each other.
10081012
*/
1009-
rtoffset=list_length(root->parse->rtable);
1010-
rtable=copyObject(subquery->rtable);
10111013
IncrementVarSublevelsUp_rtable(rtable,-1,1);
1014+
1015+
/*
1016+
* If the UNION ALL subquery had a LATERAL marker, propagate that to all
1017+
* its children. The individual children might or might not contain any
1018+
* actual lateral cross-references, but we have to mark the pulled-up
1019+
* child RTEs so that later planner stages will check for such.
1020+
*/
1021+
if (rte->lateral)
1022+
{
1023+
ListCell*rt;
1024+
1025+
foreach(rt,rtable)
1026+
{
1027+
RangeTblEntry*child_rte= (RangeTblEntry*)lfirst(rt);
1028+
1029+
Assert(child_rte->rtekind==RTE_SUBQUERY);
1030+
child_rte->lateral= true;
1031+
}
1032+
}
1033+
1034+
/*
1035+
* Append child RTEs to parent rtable.
1036+
*/
10121037
root->parse->rtable=list_concat(root->parse->rtable,rtable);
10131038

10141039
/*

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3109,6 +3109,32 @@ explain (costs off)
31093109
-> Function Scan on generate_series g
31103110
(4 rows)
31113111

3112+
-- lateral with UNION ALL subselect
3113+
explain (costs off)
3114+
select * from generate_series(100,200) g,
3115+
lateral (select * from int8_tbl a where g = q1 union all
3116+
select * from int8_tbl b where g = q2) ss;
3117+
QUERY PLAN
3118+
------------------------------------------
3119+
Nested Loop
3120+
-> Function Scan on generate_series g
3121+
-> Append
3122+
-> Seq Scan on int8_tbl a
3123+
Filter: (g.g = q1)
3124+
-> Seq Scan on int8_tbl b
3125+
Filter: (g.g = q2)
3126+
(7 rows)
3127+
3128+
select * from generate_series(100,200) g,
3129+
lateral (select * from int8_tbl a where g = q1 union all
3130+
select * from int8_tbl b where g = q2) ss;
3131+
g | q1 | q2
3132+
-----+------------------+------------------
3133+
123 | 123 | 456
3134+
123 | 123 | 4567890123456789
3135+
123 | 4567890123456789 | 123
3136+
(3 rows)
3137+
31123138
-- test some error cases where LATERAL should have been used but wasn't
31133139
select f1,g from int4_tbl a, generate_series(0, f1) g;
31143140
ERROR: column "f1" does not exist

‎src/test/regress/sql/join.sql

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,15 @@ explain (costs off)
876876
explain (costs off)
877877
selectcount(*)from tenk1 across join lateral generate_series(1,two) g;
878878

879+
-- lateral with UNION ALL subselect
880+
explain (costs off)
881+
select*from generate_series(100,200) g,
882+
lateral (select*from int8_tbl awhere g= q1union all
883+
select*from int8_tbl bwhere g= q2) ss;
884+
select*from generate_series(100,200) g,
885+
lateral (select*from int8_tbl awhere g= q1union all
886+
select*from int8_tbl bwhere g= q2) ss;
887+
879888
-- test some error cases where LATERAL should have been used but wasn't
880889
select f1,gfrom int4_tbl a, generate_series(0, f1) g;
881890
select f1,gfrom int4_tbl a, generate_series(0,a.f1) g;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp