diff options
Diffstat (limited to 'src/backend/utils/adt/selfuncs.c')
-rw-r--r-- | src/backend/utils/adt/selfuncs.c | 309 |
1 files changed, 142 insertions, 167 deletions
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index 3e6cabf7e74..cfc7dae55b6 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -5970,9 +5970,7 @@ string_to_bytea_const(const char *str, size_t str_len) static void genericcostestimate(PlannerInfo *root, - IndexOptInfo *index, - List *indexQuals, - List *indexOrderBys, + IndexPath *path, RelOptInfo *outer_rel, double numIndexTuples, Cost *indexStartupCost, @@ -5980,6 +5978,9 @@ genericcostestimate(PlannerInfo *root, Selectivity *indexSelectivity, double *indexCorrelation) { + IndexOptInfo *index = path->indexinfo; + List *indexQuals = path->indexquals; + List *indexOrderBys = path->indexorderbys; double numIndexPages; double num_sa_scans; double num_outer_scans; @@ -5991,14 +5992,6 @@ genericcostestimate(PlannerInfo *root, List *selectivityQuals; ListCell *l; - /* - * For our purposes here, it doesn't matter which index columns the - * individual quals and order-by expressions go with, so flatten the - * lists for convenience. - */ - indexQuals = flatten_clausegroups_list(indexQuals); - indexOrderBys = flatten_indexorderbys_list(indexOrderBys); - /*---------- * If the index is partial, AND the index predicate with the explicitly * given indexquals to produce a more accurate idea of the index @@ -6030,7 +6023,7 @@ genericcostestimate(PlannerInfo *root, if (!predicate_implied_by(oneQual, indexQuals)) predExtraQuals = list_concat(predExtraQuals, oneQual); } - /* list_concat avoids modifying the indexQuals list */ + /* list_concat avoids modifying the passed-in indexQuals list */ selectivityQuals = list_concat(predExtraQuals, indexQuals); } else @@ -6240,14 +6233,13 @@ Datum btcostestimate(PG_FUNCTION_ARGS) { PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0); - IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(1); - List *indexQuals = (List *) PG_GETARG_POINTER(2); - List *indexOrderBys = (List *) PG_GETARG_POINTER(3); - RelOptInfo *outer_rel = (RelOptInfo *) PG_GETARG_POINTER(4); - Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(5); - Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(6); - Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(7); - double *indexCorrelation = (double *) PG_GETARG_POINTER(8); + IndexPath *path = (IndexPath *) PG_GETARG_POINTER(1); + RelOptInfo *outer_rel = (RelOptInfo *) PG_GETARG_POINTER(2); + Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(3); + Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(4); + Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(5); + double *indexCorrelation = (double *) PG_GETARG_POINTER(6); + IndexOptInfo *index = path->indexinfo; Oid relid; AttrNumber colnum; VariableStatData vardata; @@ -6258,7 +6250,8 @@ btcostestimate(PG_FUNCTION_ARGS) bool found_saop; bool found_is_null_op; double num_sa_scans; - ListCell *lc1; + ListCell *lcc, + *lci; /* * For a btree scan, only leading '=' quals plus inequality quals for the @@ -6266,8 +6259,9 @@ btcostestimate(PG_FUNCTION_ARGS) * the "boundary quals" that determine the starting and stopping points of * the index scan). Additional quals can suppress visits to the heap, so * it's OK to count them in indexSelectivity, but they should not count - * for estimating numIndexTuples. So we must examine the given indexQuals - * to find out which ones count as boundary quals. + * for estimating numIndexTuples. So we must examine the given indexquals + * to find out which ones count as boundary quals. We rely on the + * knowledge that they are given in index column order. * * For a RowCompareExpr, we consider only the first column, just as * rowcomparesel() does. @@ -6277,119 +6271,113 @@ btcostestimate(PG_FUNCTION_ARGS) * considered to act the same as it normally does. */ indexBoundQuals = NIL; + indexcol = 0; eqQualHere = false; found_saop = false; found_is_null_op = false; num_sa_scans = 1; - - /* clausegroups must correspond to index columns */ - Assert(list_length(indexQuals) <= index->ncolumns); - - indexcol = 0; - foreach(lc1, indexQuals) + forboth(lcc, path->indexquals, lci, path->indexqualcols) { - List *clausegroup = (List *) lfirst(lc1); - ListCell *lc2; + RestrictInfo *rinfo = (RestrictInfo *) lfirst(lcc); + Expr *clause; + Node *leftop, + *rightop; + Oid clause_op; + int op_strategy; + bool is_null_op = false; - eqQualHere = false; + if (indexcol != lfirst_int(lci)) + { + /* Beginning of a new column's quals */ + if (!eqQualHere) + break; /* done if no '=' qual for indexcol */ + eqQualHere = false; + indexcol++; + if (indexcol != lfirst_int(lci)) + break; /* no quals at all for indexcol */ + } + + Assert(IsA(rinfo, RestrictInfo)); + clause = rinfo->clause; - foreach(lc2, clausegroup) + if (IsA(clause, OpExpr)) { - RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc2); - Expr *clause; - Node *leftop, - *rightop; - Oid clause_op; - int op_strategy; - bool is_null_op = false; - - Assert(IsA(rinfo, RestrictInfo)); - clause = rinfo->clause; - if (IsA(clause, OpExpr)) - { - leftop = get_leftop(clause); - rightop = get_rightop(clause); - clause_op = ((OpExpr *) clause)->opno; - } - else if (IsA(clause, RowCompareExpr)) - { - RowCompareExpr *rc = (RowCompareExpr *) clause; + leftop = get_leftop(clause); + rightop = get_rightop(clause); + clause_op = ((OpExpr *) clause)->opno; + } + else if (IsA(clause, RowCompareExpr)) + { + RowCompareExpr *rc = (RowCompareExpr *) clause; - leftop = (Node *) linitial(rc->largs); - rightop = (Node *) linitial(rc->rargs); - clause_op = linitial_oid(rc->opnos); - } - else if (IsA(clause, ScalarArrayOpExpr)) - { - ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause; + leftop = (Node *) linitial(rc->largs); + rightop = (Node *) linitial(rc->rargs); + clause_op = linitial_oid(rc->opnos); + } + else if (IsA(clause, ScalarArrayOpExpr)) + { + ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause; - leftop = (Node *) linitial(saop->args); - rightop = (Node *) lsecond(saop->args); - clause_op = saop->opno; - found_saop = true; - } - else if (IsA(clause, NullTest)) - { - NullTest *nt = (NullTest *) clause; + leftop = (Node *) linitial(saop->args); + rightop = (Node *) lsecond(saop->args); + clause_op = saop->opno; + found_saop = true; + } + else if (IsA(clause, NullTest)) + { + NullTest *nt = (NullTest *) clause; - leftop = (Node *) nt->arg; - rightop = NULL; - clause_op = InvalidOid; - if (nt->nulltesttype == IS_NULL) - { - found_is_null_op = true; - is_null_op = true; - } - } - else + leftop = (Node *) nt->arg; + rightop = NULL; + clause_op = InvalidOid; + if (nt->nulltesttype == IS_NULL) { - elog(ERROR, "unsupported indexqual type: %d", - (int) nodeTag(clause)); - continue; /* keep compiler quiet */ + found_is_null_op = true; + is_null_op = true; } + } + else + { + elog(ERROR, "unsupported indexqual type: %d", + (int) nodeTag(clause)); + continue; /* keep compiler quiet */ + } - if (match_index_to_operand(leftop, indexcol, index)) - { - /* clause_op is correct */ - } - else - { - Assert(match_index_to_operand(rightop, indexcol, index)); - /* Must flip operator to get the opfamily member */ - clause_op = get_commutator(clause_op); - } + if (match_index_to_operand(leftop, indexcol, index)) + { + /* clause_op is correct */ + } + else + { + Assert(match_index_to_operand(rightop, indexcol, index)); + /* Must flip operator to get the opfamily member */ + clause_op = get_commutator(clause_op); + } - /* check for equality operator */ - if (OidIsValid(clause_op)) - { - op_strategy = get_op_opfamily_strategy(clause_op, + /* check for equality operator */ + if (OidIsValid(clause_op)) + { + op_strategy = get_op_opfamily_strategy(clause_op, index->opfamily[indexcol]); - Assert(op_strategy != 0); /* not a member of opfamily?? */ - if (op_strategy == BTEqualStrategyNumber) - eqQualHere = true; - } - else if (is_null_op) - { - /* IS NULL is like = for selectivity determination */ + Assert(op_strategy != 0); /* not a member of opfamily?? */ + if (op_strategy == BTEqualStrategyNumber) eqQualHere = true; - } - /* count up number of SA scans induced by indexBoundQuals only */ - if (IsA(clause, ScalarArrayOpExpr)) - { - ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause; - int alength = estimate_array_length(lsecond(saop->args)); - - if (alength > 1) - num_sa_scans *= alength; - } - indexBoundQuals = lappend(indexBoundQuals, rinfo); } + else if (is_null_op) + { + /* IS NULL is like = for purposes of selectivity determination */ + eqQualHere = true; + } + /* count up number of SA scans induced by indexBoundQuals only */ + if (IsA(clause, ScalarArrayOpExpr)) + { + ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause; + int alength = estimate_array_length(lsecond(saop->args)); - /* Done with this indexcol, continue to next only if it had = qual */ - if (!eqQualHere) - break; - - indexcol++; + if (alength > 1) + num_sa_scans *= alength; + } + indexBoundQuals = lappend(indexBoundQuals, rinfo); } /* @@ -6399,7 +6387,7 @@ btcostestimate(PG_FUNCTION_ARGS) * NullTest invalidates that theory, even though it sets eqQualHere. */ if (index->unique && - indexcol == index->ncolumns && + indexcol == index->ncolumns - 1 && eqQualHere && !found_saop && !found_is_null_op) @@ -6422,8 +6410,8 @@ btcostestimate(PG_FUNCTION_ARGS) numIndexTuples = rint(numIndexTuples / num_sa_scans); } - genericcostestimate(root, index, indexQuals, indexOrderBys, - outer_rel, numIndexTuples, + genericcostestimate(root, path, outer_rel, + numIndexTuples, indexStartupCost, indexTotalCost, indexSelectivity, indexCorrelation); @@ -6538,16 +6526,14 @@ Datum hashcostestimate(PG_FUNCTION_ARGS) { PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0); - IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(1); - List *indexQuals = (List *) PG_GETARG_POINTER(2); - List *indexOrderBys = (List *) PG_GETARG_POINTER(3); - RelOptInfo *outer_rel = (RelOptInfo *) PG_GETARG_POINTER(4); - Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(5); - Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(6); - Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(7); - double *indexCorrelation = (double *) PG_GETARG_POINTER(8); - - genericcostestimate(root, index, indexQuals, indexOrderBys, outer_rel, 0.0, + IndexPath *path = (IndexPath *) PG_GETARG_POINTER(1); + RelOptInfo *outer_rel = (RelOptInfo *) PG_GETARG_POINTER(2); + Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(3); + Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(4); + Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(5); + double *indexCorrelation = (double *) PG_GETARG_POINTER(6); + + genericcostestimate(root, path, outer_rel, 0.0, indexStartupCost, indexTotalCost, indexSelectivity, indexCorrelation); @@ -6558,16 +6544,14 @@ Datum gistcostestimate(PG_FUNCTION_ARGS) { PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0); - IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(1); - List *indexQuals = (List *) PG_GETARG_POINTER(2); - List *indexOrderBys = (List *) PG_GETARG_POINTER(3); - RelOptInfo *outer_rel = (RelOptInfo *) PG_GETARG_POINTER(4); - Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(5); - Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(6); - Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(7); - double *indexCorrelation = (double *) PG_GETARG_POINTER(8); - - genericcostestimate(root, index, indexQuals, indexOrderBys, outer_rel, 0.0, + IndexPath *path = (IndexPath *) PG_GETARG_POINTER(1); + RelOptInfo *outer_rel = (RelOptInfo *) PG_GETARG_POINTER(2); + Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(3); + Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(4); + Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(5); + double *indexCorrelation = (double *) PG_GETARG_POINTER(6); + + genericcostestimate(root, path, outer_rel, 0.0, indexStartupCost, indexTotalCost, indexSelectivity, indexCorrelation); @@ -6578,16 +6562,14 @@ Datum spgcostestimate(PG_FUNCTION_ARGS) { PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0); - IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(1); - List *indexQuals = (List *) PG_GETARG_POINTER(2); - List *indexOrderBys = (List *) PG_GETARG_POINTER(3); - RelOptInfo *outer_rel = (RelOptInfo *) PG_GETARG_POINTER(4); - Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(5); - Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(6); - Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(7); - double *indexCorrelation = (double *) PG_GETARG_POINTER(8); - - genericcostestimate(root, index, indexQuals, indexOrderBys, outer_rel, 0.0, + IndexPath *path = (IndexPath *) PG_GETARG_POINTER(1); + RelOptInfo *outer_rel = (RelOptInfo *) PG_GETARG_POINTER(2); + Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(3); + Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(4); + Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(5); + double *indexCorrelation = (double *) PG_GETARG_POINTER(6); + + genericcostestimate(root, path, outer_rel, 0.0, indexStartupCost, indexTotalCost, indexSelectivity, indexCorrelation); @@ -6901,14 +6883,15 @@ Datum gincostestimate(PG_FUNCTION_ARGS) { PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0); - IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(1); - List *indexQuals = (List *) PG_GETARG_POINTER(2); - List *indexOrderBys = (List *) PG_GETARG_POINTER(3); - RelOptInfo *outer_rel = (RelOptInfo *) PG_GETARG_POINTER(4); - Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(5); - Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(6); - Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(7); - double *indexCorrelation = (double *) PG_GETARG_POINTER(8); + IndexPath *path = (IndexPath *) PG_GETARG_POINTER(1); + RelOptInfo *outer_rel = (RelOptInfo *) PG_GETARG_POINTER(2); + Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(3); + Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(4); + Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(5); + double *indexCorrelation = (double *) PG_GETARG_POINTER(6); + IndexOptInfo *index = path->indexinfo; + List *indexQuals = path->indexquals; + List *indexOrderBys = path->indexorderbys; ListCell *l; List *selectivityQuals; double numPages = index->pages, @@ -6931,14 +6914,6 @@ gincostestimate(PG_FUNCTION_ARGS) GinStatsData ginStats; /* - * For our purposes here, it doesn't matter which index columns the - * individual quals and order-by expressions go with, so flatten the - * lists for convenience. - */ - indexQuals = flatten_clausegroups_list(indexQuals); - indexOrderBys = flatten_indexorderbys_list(indexOrderBys); - - /* * Obtain statistic information from the meta page */ indexRel = index_open(index->indexoid, AccessShareLock); @@ -6994,7 +6969,7 @@ gincostestimate(PG_FUNCTION_ARGS) if (!predicate_implied_by(oneQual, indexQuals)) predExtraQuals = list_concat(predExtraQuals, oneQual); } - /* list_concat avoids modifying the indexQuals list */ + /* list_concat avoids modifying the passed-in indexQuals list */ selectivityQuals = list_concat(predExtraQuals, indexQuals); } else |