34
34
#include "optimizer/tlist.h"
35
35
#include "utils/lsyscache.h"
36
36
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
-
46
37
/*
47
38
* The struct containing self-join candidate. Used to find duplicate reloids.
48
39
*/
@@ -75,13 +66,11 @@ static bool is_innerrel_unique_for(PlannerInfo *root,
75
66
JoinType jointype ,
76
67
List * restrictlist ,
77
68
List * * extra_clauses );
78
- static Bitmapset * replace_relid (Relids relids , int oldId , int newId );
79
69
static 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 );
81
71
static int self_join_candidates_cmp (const void * a , const void * b );
82
72
83
73
84
-
85
74
/*
86
75
* remove_useless_joins
87
76
* 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,
367
356
ListCell * l ;
368
357
369
358
/*
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.
371
361
*/
372
362
for (rti = 1 ; rti < root -> simple_rel_array_size ; rti ++ )
373
363
{
@@ -394,35 +384,8 @@ remove_rel_from_query(PlannerInfo *root, RelOptInfo *rel,
394
384
replace_relid (otherrel -> attr_needed [attroff ], ojrelid , subst );
395
385
}
396
386
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 );
426
389
}
427
390
428
391
/*
@@ -1462,35 +1425,32 @@ is_innerrel_unique_for(PlannerInfo *root,
1462
1425
}
1463
1426
1464
1427
/*
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.
1466
1434
*/
1467
- static void
1468
- replace_varno (Node * node , int from , int to )
1469
- {
1470
- ReplaceVarnoContext ctx ;
1471
-
1472
- if (to <= 0 )
1473
- return ;
1474
1435
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 ;
1479
1442
1480
- /*
1481
- * Walker function for replace_varno()
1482
- */
1483
1443
static bool
1484
1444
replace_varno_walker (Node * node , ReplaceVarnoContext * ctx )
1485
1445
{
1486
1446
if (node == NULL )
1487
1447
return false;
1488
-
1489
1448
if (IsA (node , Var ))
1490
1449
{
1491
1450
Var * var = (Var * ) node ;
1492
1451
1493
- if (var -> varno == ctx -> from )
1452
+ if (var -> varno == ctx -> from &&
1453
+ var -> varlevelsup == ctx -> sublevels_up )
1494
1454
{
1495
1455
var -> varno = ctx -> to ;
1496
1456
var -> varnosyn = ctx -> to ;
@@ -1501,11 +1461,29 @@ replace_varno_walker(Node *node, ReplaceVarnoContext *ctx)
1501
1461
{
1502
1462
PlaceHolderVar * phv = (PlaceHolderVar * ) node ;
1503
1463
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
+ }
1506
1471
1507
1472
/* fall through to recurse into the placeholder's expression */
1508
1473
}
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
+ }
1509
1487
else if (IsA (node , RestrictInfo ))
1510
1488
{
1511
1489
RestrictInfo * rinfo = (RestrictInfo * ) node ;
@@ -1517,18 +1495,24 @@ replace_varno_walker(Node *node, ReplaceVarnoContext *ctx)
1517
1495
{
1518
1496
replace_varno ((Node * ) rinfo -> clause , ctx -> from , ctx -> to );
1519
1497
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 );
1523
1504
}
1524
1505
1525
1506
if (is_req_equal )
1526
1507
rinfo -> required_relids = rinfo -> clause_relids ;
1527
1508
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 );
1529
1511
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 );
1532
1516
1533
1517
if (rinfo -> mergeopfamilies &&
1534
1518
bms_get_singleton_member (rinfo -> clause_relids , & relid ) &&
@@ -1556,7 +1540,30 @@ replace_varno_walker(Node *node, ReplaceVarnoContext *ctx)
1556
1540
1557
1541
return false;
1558
1542
}
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 );
1560
1567
}
1561
1568
1562
1569
/*
@@ -1748,7 +1755,6 @@ remove_self_join_rel(PlannerInfo *root, PlanRowMark *kmark, PlanRowMark *rmark,
1748
1755
int i ;
1749
1756
List * jinfo_candidates = NIL ;
1750
1757
List * binfo_candidates = NIL ;
1751
- ReplaceVarnoContext ctx = {.from = toRemove -> relid ,.to = toKeep -> relid };
1752
1758
1753
1759
Assert (toKeep -> relid != -1 );
1754
1760
@@ -1925,8 +1931,7 @@ remove_self_join_rel(PlannerInfo *root, PlanRowMark *kmark, PlanRowMark *rmark,
1925
1931
}
1926
1932
1927
1933
/* 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 );
1930
1935
1931
1936
/* See remove_self_joins_one_group() */
1932
1937
Assert (root -> parse -> resultRelation != toRemove -> relid );
0 commit comments