diff --git a/src/backend/optimizer/plan/analyzejoins.c b/src/backend/optimizer/plan/analyzejoins.c index 66474b18c60..060118da4ec 100644 --- a/src/backend/optimizer/plan/analyzejoins.c +++ b/src/backend/optimizer/plan/analyzejoins.c @@ -2018,7 +2018,7 @@ remove_self_joins_recurse(PlannerInfo *root, List *joinlist) int j; int numRels; - /* Collect indexes of base relations of the join tree */ + /* Collect indexes of possibly-mergeable relations from the joinlist */ foreach(jl, joinlist) { Node *jlnode = (Node *) lfirst(jl); @@ -2029,15 +2029,31 @@ remove_self_joins_recurse(PlannerInfo *root, List *joinlist) RangeTblEntry *rte = root->simple_rte_array[varno]; /* - * We only consider ordinary relations as candidates to be - * removed, and these relations should not have TABLESAMPLE - * clauses specified. Removing a relation with TABLESAMPLE clause - * could potentially change the semantics of the query. Because of - * UPDATE/DELETE EPQ mechanism, currently Query->resultRelation or - * Query->mergeTargetRelation associated rel cannot be eliminated. + * To be considered for self-join removal, the RTE must: + * + * 1. Be an ordinary relation. (Someday we might support SJE on + * partitioned tables, but not yet.) + * + * 2. Not have inh set, ie it has no inheritance children (or the + * user wrote ONLY to ignore them). Under traditional inheritance + * a unique index on a parent table does not establish uniqueness + * across its children. This rule also keeps us from trying to + * merge an inheritance scan with an ONLY scan, which would be + * wrong. (preprocess_relation_rtes already cleared the inh flag + * for tables known not to have inheritance children.) + * + * 3. Not have a TABLESAMPLE clause. Removing a relation with a + * TABLESAMPLE clause would change the semantics of the query, + * even if we merged it with another RTE with an identical + * TABLESAMPLE clause. (Two such RTEs should represent + * independent samplings of the base table.) + * + * 4. Not be the query's result relation or MERGE target. Merging + * would cause misbehavior during EPQ. */ if (rte->rtekind == RTE_RELATION && rte->relkind == RELKIND_RELATION && + !rte->inh && rte->tablesample == NULL && varno != root->parse->resultRelation && varno != root->parse->mergeTargetRelation)