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

Commit466979e

Browse files
committed
Replace lateral references to removed rels in subqueries
This commit introduces a new field 'sublevels_up' in ReplaceVarnoContext,and enhances replace_varno_walker() to: 1) recurse into subselects with sublevels_up increased, and 2) perform the replacement only when varlevelsup is equal to sublevels_up.This commit also fixes some outdated comments. And besides adding relevanttest cases, it makes some unification over existing SJE test cases.Discussion:https://postgr.es/m/CAMbWs4-%3DPO6Mm9gNnySbx0VHyXjgnnYYwbN9dth%3DTLQweZ-M%2Bg%40mail.gmail.comAuthor: Richard GuoReviewed-by: Andrei Lepikhov, Alexander Korotkov
1 parenta6b2a51 commit466979e

File tree

3 files changed

+337
-306
lines changed

3 files changed

+337
-306
lines changed

‎src/backend/optimizer/plan/analyzejoins.c

Lines changed: 76 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,6 @@
3434
#include"optimizer/tlist.h"
3535
#include"utils/lsyscache.h"
3636

37-
/*
38-
* The context for replace_varno_walker() containing source and target relids.
39-
*/
40-
typedefstruct
41-
{
42-
intfrom;
43-
intto;
44-
}ReplaceVarnoContext;
45-
4637
/*
4738
* The struct containing self-join candidate. Used to find duplicate reloids.
4839
*/
@@ -75,13 +66,11 @@ static bool is_innerrel_unique_for(PlannerInfo *root,
7566
JoinTypejointype,
7667
List*restrictlist,
7768
List**extra_clauses);
78-
staticBitmapset*replace_relid(Relidsrelids,intoldId,intnewId);
7969
staticvoidreplace_varno(Node*node,intfrom,intto);
80-
staticboolreplace_varno_walker(Node*node,ReplaceVarnoContext*ctx);
70+
staticBitmapset*replace_relid(Relidsrelids,intoldId,intnewId);
8171
staticintself_join_candidates_cmp(constvoid*a,constvoid*b);
8272

8373

84-
8574
/*
8675
* remove_useless_joins
8776
*Check for relations that don't actually need to be joined at all,
@@ -367,7 +356,8 @@ remove_rel_from_query(PlannerInfo *root, RelOptInfo *rel,
367356
ListCell*l;
368357

369358
/*
370-
* Remove references to the rel from other baserels' attr_needed arrays.
359+
* Remove references to the rel from other baserels' attr_needed arrays
360+
* and lateral_vars lists.
371361
*/
372362
for (rti=1;rti<root->simple_rel_array_size;rti++)
373363
{
@@ -394,35 +384,8 @@ remove_rel_from_query(PlannerInfo *root, RelOptInfo *rel,
394384
replace_relid(otherrel->attr_needed[attroff],ojrelid,subst);
395385
}
396386

397-
/* Update lateral references. */
398-
if (root->hasLateralRTEs)
399-
{
400-
RangeTblEntry*rte=root->simple_rte_array[rti];
401-
ReplaceVarnoContextctx= {.from=relid,.to=subst};
402-
403-
if (rte->lateral)
404-
{
405-
replace_varno((Node*)otherrel->lateral_vars,relid,subst);
406-
407-
/*
408-
* Although we pass root->parse through cleanup procedure, but
409-
* parse->rtable and rte contains refs to different copies of
410-
* the subquery.
411-
*/
412-
if (otherrel->rtekind==RTE_SUBQUERY)
413-
query_tree_walker(rte->subquery,replace_varno_walker,&ctx,
414-
QTW_EXAMINE_SORTGROUP);
415-
#ifdefUSE_ASSERT_CHECKING
416-
/* Just check possibly hidden non-replaced relids */
417-
Assert(!bms_is_member(relid,pull_varnos(root, (Node*)rte->tablesample)));
418-
Assert(!bms_is_member(relid,pull_varnos(root, (Node*)rte->functions)));
419-
Assert(!bms_is_member(relid,pull_varnos(root, (Node*)rte->tablefunc)));
420-
Assert(!bms_is_member(relid,pull_varnos(root, (Node*)rte->values_lists)));
421-
#endif
422-
}
423-
}
424-
425-
387+
/* Update lateral_vars list. */
388+
replace_varno((Node*)otherrel->lateral_vars,relid,subst);
426389
}
427390

428391
/*
@@ -1462,35 +1425,32 @@ is_innerrel_unique_for(PlannerInfo *root,
14621425
}
14631426

14641427
/*
1465-
* Replace each occurrence of removing relid with the keeping one
1428+
* replace_varno - find in the given tree any Vars, PlaceHolderVar, and Relids
1429+
* that reference the removing relid, and change them to the reference to
1430+
* the replacement relid.
1431+
*
1432+
* NOTE: although this has the form of a walker, we cheat and modify the
1433+
* nodes in-place.
14661434
*/
1467-
staticvoid
1468-
replace_varno(Node*node,intfrom,intto)
1469-
{
1470-
ReplaceVarnoContextctx;
1471-
1472-
if (to <=0)
1473-
return;
14741435

1475-
ctx.from=from;
1476-
ctx.to=to;
1477-
replace_varno_walker(node,&ctx);
1478-
}
1436+
typedefstruct
1437+
{
1438+
intfrom;
1439+
intto;
1440+
intsublevels_up;
1441+
}ReplaceVarnoContext;
14791442

1480-
/*
1481-
* Walker function for replace_varno()
1482-
*/
14831443
staticbool
14841444
replace_varno_walker(Node*node,ReplaceVarnoContext*ctx)
14851445
{
14861446
if (node==NULL)
14871447
return false;
1488-
14891448
if (IsA(node,Var))
14901449
{
14911450
Var*var= (Var*)node;
14921451

1493-
if (var->varno==ctx->from)
1452+
if (var->varno==ctx->from&&
1453+
var->varlevelsup==ctx->sublevels_up)
14941454
{
14951455
var->varno=ctx->to;
14961456
var->varnosyn=ctx->to;
@@ -1501,11 +1461,29 @@ replace_varno_walker(Node *node, ReplaceVarnoContext *ctx)
15011461
{
15021462
PlaceHolderVar*phv= (PlaceHolderVar*)node;
15031463

1504-
phv->phrels=replace_relid(phv->phrels,ctx->from,ctx->to);
1505-
phv->phnullingrels=replace_relid(phv->phnullingrels,ctx->from,ctx->to);
1464+
if (phv->phlevelsup==ctx->sublevels_up)
1465+
{
1466+
phv->phrels=
1467+
replace_relid(phv->phrels,ctx->from,ctx->to);
1468+
phv->phnullingrels=
1469+
replace_relid(phv->phnullingrels,ctx->from,ctx->to);
1470+
}
15061471

15071472
/* fall through to recurse into the placeholder's expression */
15081473
}
1474+
elseif (IsA(node,Query))
1475+
{
1476+
/* Recurse into subselects */
1477+
boolresult;
1478+
1479+
ctx->sublevels_up++;
1480+
result=query_tree_walker((Query*)node,
1481+
replace_varno_walker,
1482+
(void*)ctx,
1483+
QTW_EXAMINE_SORTGROUP);
1484+
ctx->sublevels_up--;
1485+
returnresult;
1486+
}
15091487
elseif (IsA(node,RestrictInfo))
15101488
{
15111489
RestrictInfo*rinfo= (RestrictInfo*)node;
@@ -1517,18 +1495,24 @@ replace_varno_walker(Node *node, ReplaceVarnoContext *ctx)
15171495
{
15181496
replace_varno((Node*)rinfo->clause,ctx->from,ctx->to);
15191497
replace_varno((Node*)rinfo->orclause,ctx->from,ctx->to);
1520-
rinfo->clause_relids=replace_relid(rinfo->clause_relids,ctx->from,ctx->to);
1521-
rinfo->left_relids=replace_relid(rinfo->left_relids,ctx->from,ctx->to);
1522-
rinfo->right_relids=replace_relid(rinfo->right_relids,ctx->from,ctx->to);
1498+
rinfo->clause_relids=
1499+
replace_relid(rinfo->clause_relids,ctx->from,ctx->to);
1500+
rinfo->left_relids=
1501+
replace_relid(rinfo->left_relids,ctx->from,ctx->to);
1502+
rinfo->right_relids=
1503+
replace_relid(rinfo->right_relids,ctx->from,ctx->to);
15231504
}
15241505

15251506
if (is_req_equal)
15261507
rinfo->required_relids=rinfo->clause_relids;
15271508
else
1528-
rinfo->required_relids=replace_relid(rinfo->required_relids,ctx->from,ctx->to);
1509+
rinfo->required_relids=
1510+
replace_relid(rinfo->required_relids,ctx->from,ctx->to);
15291511

1530-
rinfo->outer_relids=replace_relid(rinfo->outer_relids,ctx->from,ctx->to);
1531-
rinfo->incompatible_relids=replace_relid(rinfo->incompatible_relids,ctx->from,ctx->to);
1512+
rinfo->outer_relids=
1513+
replace_relid(rinfo->outer_relids,ctx->from,ctx->to);
1514+
rinfo->incompatible_relids=
1515+
replace_relid(rinfo->incompatible_relids,ctx->from,ctx->to);
15321516

15331517
if (rinfo->mergeopfamilies&&
15341518
bms_get_singleton_member(rinfo->clause_relids,&relid)&&
@@ -1556,7 +1540,30 @@ replace_varno_walker(Node *node, ReplaceVarnoContext *ctx)
15561540

15571541
return false;
15581542
}
1559-
returnexpression_tree_walker(node,replace_varno_walker, (void*)ctx);
1543+
1544+
returnexpression_tree_walker(node,replace_varno_walker,
1545+
(void*)ctx);
1546+
}
1547+
1548+
staticvoid
1549+
replace_varno(Node*node,intfrom,intto)
1550+
{
1551+
ReplaceVarnoContextctx;
1552+
1553+
if (to <=0)
1554+
return;
1555+
1556+
ctx.from=from;
1557+
ctx.to=to;
1558+
ctx.sublevels_up=0;
1559+
1560+
/*
1561+
* Must be prepared to start with a Query or a bare expression tree.
1562+
*/
1563+
query_or_expression_tree_walker(node,
1564+
replace_varno_walker,
1565+
(void*)&ctx,
1566+
QTW_EXAMINE_SORTGROUP);
15601567
}
15611568

15621569
/*
@@ -1748,7 +1755,6 @@ remove_self_join_rel(PlannerInfo *root, PlanRowMark *kmark, PlanRowMark *rmark,
17481755
inti;
17491756
List*jinfo_candidates=NIL;
17501757
List*binfo_candidates=NIL;
1751-
ReplaceVarnoContextctx= {.from=toRemove->relid,.to=toKeep->relid};
17521758

17531759
Assert(toKeep->relid!=-1);
17541760

@@ -1925,8 +1931,7 @@ remove_self_join_rel(PlannerInfo *root, PlanRowMark *kmark, PlanRowMark *rmark,
19251931
}
19261932

19271933
/* Replace varno in all the query structures */
1928-
query_tree_walker(root->parse,replace_varno_walker,&ctx,
1929-
QTW_EXAMINE_SORTGROUP);
1934+
replace_varno((Node*)root->parse,toRemove->relid,toKeep->relid);
19301935

19311936
/* See remove_self_joins_one_group() */
19321937
Assert(root->parse->resultRelation!=toRemove->relid);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp