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- typedef struct
41- {
42- int from ;
43- int to ;
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 JoinType jointype ,
7667 List * restrictlist ,
7768 List * * extra_clauses );
78- static Bitmapset * replace_relid (Relids relids , int oldId , int newId );
7969static void replace_varno (Node * node , int from , int to );
80- static bool replace_varno_walker ( Node * node , ReplaceVarnoContext * ctx );
70+ static Bitmapset * replace_relid ( Relids relids , int oldId , int newId );
8171static int self_join_candidates_cmp (const void * a , const void * 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- ReplaceVarnoContext ctx = {.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- #ifdef USE_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- static void
1468- replace_varno (Node * node , int from , int to )
1469- {
1470- ReplaceVarnoContext ctx ;
1471-
1472- if (to <= 0 )
1473- return ;
14741435
1475- ctx .from = from ;
1476- ctx .to = to ;
1477- replace_varno_walker (node , & ctx );
1478- }
1436+ typedef struct
1437+ {
1438+ int from ;
1439+ int to ;
1440+ int sublevels_up ;
1441+ } ReplaceVarnoContext ;
14791442
1480- /*
1481- * Walker function for replace_varno()
1482- */
14831443static bool
14841444replace_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+ else if (IsA (node , Query ))
1475+ {
1476+ /* Recurse into subselects */
1477+ bool result ;
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+ return result ;
1486+ }
15091487 else if (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- return expression_tree_walker (node , replace_varno_walker , (void * ) ctx );
1543+
1544+ return expression_tree_walker (node , replace_varno_walker ,
1545+ (void * ) ctx );
1546+ }
1547+
1548+ static void
1549+ replace_varno (Node * node , int from , int to )
1550+ {
1551+ ReplaceVarnoContext ctx ;
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 int i ;
17491756 List * jinfo_candidates = NIL ;
17501757 List * binfo_candidates = NIL ;
1751- ReplaceVarnoContext ctx = {.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