3333#include "utils/lsyscache.h"
3434
3535/*
36- * The struct containing self-join candidate. Used to find duplicate reloids.
36+ * Utility structure. It is needed to perform a sorting procedure and simplify
37+ * the search of SJE-candidate baserels referencing the same database relation.
38+ * Having collected all baserels from the query jointree, the planner sorts them
39+ * according to the reloid value, groups them with the next pass and attempts to
40+ * remove self-joins.
41+ * Preliminary sorting prevents quadratic behaviour that can be harmful in the
42+ * case of numerous joins.
3743 */
3844typedef struct
3945{
@@ -1584,6 +1590,9 @@ replace_varno(Node *node, int from, int to)
15841590 * We must make a copy of the original Bitmapset before making any
15851591 * modifications, because the same pointer to it might be shared among
15861592 * different places.
1593+ * Also, this function can be used in 'delete only' mode (newId < 0).
1594+ * It allows us to utilise the same code in the remove_useless_joins and the
1595+ * remove_self_joins features.
15871596 */
15881597static Bitmapset *
15891598replace_relid (Relids relids , int oldId , int newId )
@@ -2463,7 +2472,7 @@ self_join_candidates_cmp(const void *a, const void *b)
24632472 * of the removed relation become either restriction or join clauses, based on
24642473 * whether they reference any relations not participating in the removed join.
24652474 *
2466- * 'targetlist ' is the top-level targetlist of the query. If it has any
2475+ * 'joinlist ' is the top-level joinlist of the query. If it has any
24672476 * references to the removed relations, we update them to point to the
24682477 * remaining ones.
24692478 */
@@ -2485,11 +2494,15 @@ remove_useless_self_joins(PlannerInfo *root, List *joinlist)
24852494
24862495 if (unlikely (toRemove != NULL ))
24872496 {
2488- int nremoved = 0 ;
2489-
24902497 /* At the end, remove orphaned relation links */
24912498 while ((relid = bms_next_member (toRemove , relid )) >= 0 )
2499+ {
2500+ int nremoved = 0 ;
2501+
24922502 joinlist = remove_rel_from_joinlist (joinlist , relid , & nremoved );
2503+ if (nremoved != 1 )
2504+ elog (ERROR , "SJE failed to find relation %d in joinlist" , relid );
2505+ }
24932506 }
24942507
24952508 return joinlist ;
0 commit comments