Simplify relation_has_unique_index_for()

Now that the only call to relation_has_unique_index_for() that
supplied an exprlist and oprlist has been removed, the loop handling
those lists is effectively dead code.  This patch removes that loop
and simplifies the function accordingly.

Author: Richard Guo <guofenglinux@gmail.com>
Discussion: https://postgr.es/m/CAMbWs4-EBnaRvEs7frTLbsXiweSTUXifsteF-d3rvv01FKO86w@mail.gmail.com
pull/239/head
Richard Guo 3 weeks ago
parent 24225ad9aa
commit bf9ee294e5
  1. 85
      src/backend/optimizer/path/indxpath.c
  2. 5
      src/backend/optimizer/plan/analyzejoins.c
  3. 5
      src/include/optimizer/paths.h

@ -4142,47 +4142,26 @@ ec_member_matches_indexcol(PlannerInfo *root, RelOptInfo *rel,
* a set of equality conditions, because the conditions constrain all * a set of equality conditions, because the conditions constrain all
* columns of some unique index. * columns of some unique index.
* *
* The conditions can be represented in either or both of two ways: * The conditions are provided as a list of RestrictInfo nodes, where the
* 1. A list of RestrictInfo nodes, where the caller has already determined * caller has already determined that each condition is a mergejoinable
* that each condition is a mergejoinable equality with an expression in * equality with an expression in this relation on one side, and an
* this relation on one side, and an expression not involving this relation * expression not involving this relation on the other. The transient
* on the other. The transient outer_is_left flag is used to identify which * outer_is_left flag is used to identify which side we should look at:
* side we should look at: left side if outer_is_left is false, right side * left side if outer_is_left is false, right side if it is true.
* if it is true.
* 2. A list of expressions in this relation, and a corresponding list of
* equality operators. The caller must have already checked that the operators
* represent equality. (Note: the operators could be cross-type; the
* expressions should correspond to their RHS inputs.)
* *
* The caller need only supply equality conditions arising from joins; * The caller need only supply equality conditions arising from joins;
* this routine automatically adds in any usable baserestrictinfo clauses. * this routine automatically adds in any usable baserestrictinfo clauses.
* (Note that the passed-in restrictlist will be destructively modified!) * (Note that the passed-in restrictlist will be destructively modified!)
*
* If extra_clauses isn't NULL, return baserestrictinfo clauses which were used
* to derive uniqueness.
*/ */
bool bool
relation_has_unique_index_for(PlannerInfo *root, RelOptInfo *rel, relation_has_unique_index_for(PlannerInfo *root, RelOptInfo *rel,
List *restrictlist, List *restrictlist, List **extra_clauses)
List *exprlist, List *oprlist)
{
return relation_has_unique_index_ext(root, rel, restrictlist,
exprlist, oprlist, NULL);
}
/*
* relation_has_unique_index_ext
* Same as relation_has_unique_index_for(), but supports extra_clauses
* parameter. If extra_clauses isn't NULL, return baserestrictinfo clauses
* which were used to derive uniqueness.
*/
bool
relation_has_unique_index_ext(PlannerInfo *root, RelOptInfo *rel,
List *restrictlist,
List *exprlist, List *oprlist,
List **extra_clauses)
{ {
ListCell *ic; ListCell *ic;
Assert(list_length(exprlist) == list_length(oprlist));
/* Short-circuit if no indexes... */ /* Short-circuit if no indexes... */
if (rel->indexlist == NIL) if (rel->indexlist == NIL)
return false; return false;
@ -4225,7 +4204,7 @@ relation_has_unique_index_ext(PlannerInfo *root, RelOptInfo *rel,
} }
/* Short-circuit the easy case */ /* Short-circuit the easy case */
if (restrictlist == NIL && exprlist == NIL) if (restrictlist == NIL)
return false; return false;
/* Examine each index of the relation ... */ /* Examine each index of the relation ... */
@ -4247,14 +4226,12 @@ relation_has_unique_index_ext(PlannerInfo *root, RelOptInfo *rel,
continue; continue;
/* /*
* Try to find each index column in the lists of conditions. This is * Try to find each index column in the list of conditions. This is
* O(N^2) or worse, but we expect all the lists to be short. * O(N^2) or worse, but we expect all the lists to be short.
*/ */
for (c = 0; c < ind->nkeycolumns; c++) for (c = 0; c < ind->nkeycolumns; c++)
{ {
bool matched = false;
ListCell *lc; ListCell *lc;
ListCell *lc2;
foreach(lc, restrictlist) foreach(lc, restrictlist)
{ {
@ -4284,8 +4261,6 @@ relation_has_unique_index_ext(PlannerInfo *root, RelOptInfo *rel,
if (match_index_to_operand(rexpr, c, ind)) if (match_index_to_operand(rexpr, c, ind))
{ {
matched = true; /* column is unique */
if (bms_membership(rinfo->clause_relids) == BMS_SINGLETON) if (bms_membership(rinfo->clause_relids) == BMS_SINGLETON)
{ {
MemoryContext oldMemCtx = MemoryContext oldMemCtx =
@ -4303,43 +4278,11 @@ relation_has_unique_index_ext(PlannerInfo *root, RelOptInfo *rel,
MemoryContextSwitchTo(oldMemCtx); MemoryContextSwitchTo(oldMemCtx);
} }
break; break; /* found a match; column is unique */
} }
} }
if (matched) if (lc == NULL)
continue;
forboth(lc, exprlist, lc2, oprlist)
{
Node *expr = (Node *) lfirst(lc);
Oid opr = lfirst_oid(lc2);
/* See if the expression matches the index key */
if (!match_index_to_operand(expr, c, ind))
continue;
/*
* The equality operator must be a member of the index
* opfamily, else it is not asserting the right kind of
* equality behavior for this index. We assume the caller
* determined it is an equality operator, so we don't need to
* check any more tightly than this.
*/
if (!op_in_opfamily(opr, ind->opfamily[c]))
continue;
/*
* XXX at some point we may need to check collations here too.
* For the moment we assume all collations reduce to the same
* notion of equality.
*/
matched = true; /* column is unique */
break;
}
if (!matched)
break; /* no match; this index doesn't help us */ break; /* no match; this index doesn't help us */
} }

@ -990,11 +990,10 @@ rel_is_distinct_for(PlannerInfo *root, RelOptInfo *rel, List *clause_list,
{ {
/* /*
* Examine the indexes to see if we have a matching unique index. * Examine the indexes to see if we have a matching unique index.
* relation_has_unique_index_ext automatically adds any usable * relation_has_unique_index_for automatically adds any usable
* restriction clauses for the rel, so we needn't do that here. * restriction clauses for the rel, so we needn't do that here.
*/ */
if (relation_has_unique_index_ext(root, rel, clause_list, NIL, NIL, if (relation_has_unique_index_for(root, rel, clause_list, extra_clauses))
extra_clauses))
return true; return true;
} }
else if (rel->rtekind == RTE_SUBQUERY) else if (rel->rtekind == RTE_SUBQUERY)

@ -71,10 +71,7 @@ extern void generate_partitionwise_join_paths(PlannerInfo *root,
extern void create_index_paths(PlannerInfo *root, RelOptInfo *rel); extern void create_index_paths(PlannerInfo *root, RelOptInfo *rel);
extern bool relation_has_unique_index_for(PlannerInfo *root, RelOptInfo *rel, extern bool relation_has_unique_index_for(PlannerInfo *root, RelOptInfo *rel,
List *restrictlist, List *restrictlist,
List *exprlist, List *oprlist); List **extra_clauses);
extern bool relation_has_unique_index_ext(PlannerInfo *root, RelOptInfo *rel,
List *restrictlist, List *exprlist,
List *oprlist, List **extra_clauses);
extern bool indexcol_is_bool_constant_for_query(PlannerInfo *root, extern bool indexcol_is_bool_constant_for_query(PlannerInfo *root,
IndexOptInfo *index, IndexOptInfo *index,
int indexcol); int indexcol);

Loading…
Cancel
Save