clausesel.c
来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 564 行 · 第 1/2 页
C
564 行
* We use full equal() here because the "var" might be a function * of one or more attributes of the same relation... */ if (!equal(var, rqelem->var)) continue; /* Found the right group to put this clause in */ if (is_lobound) { if (!rqelem->have_lobound) { rqelem->have_lobound = true; rqelem->lobound = s2; } else { /*------ * We have found two similar clauses, such as * x < y AND x < z. * Keep only the more restrictive one. *------ */ if (rqelem->lobound > s2) rqelem->lobound = s2; } } else { if (!rqelem->have_hibound) { rqelem->have_hibound = true; rqelem->hibound = s2; } else { /*------ * We have found two similar clauses, such as * x > y AND x > z. * Keep only the more restrictive one. *------ */ if (rqelem->hibound > s2) rqelem->hibound = s2; } } return; } /* No matching var found, so make a new clause-pair data structure */ rqelem = (RangeQueryClause *) palloc(sizeof(RangeQueryClause)); rqelem->var = var; if (is_lobound) { rqelem->have_lobound = true; rqelem->have_hibound = false; rqelem->lobound = s2; } else { rqelem->have_lobound = false; rqelem->have_hibound = true; rqelem->hibound = s2; } rqelem->next = *rqlist; *rqlist = rqelem;}/* * clause_selectivity - * Compute the selectivity of a general boolean expression clause. * * varRelid is either 0 or a rangetable index. * * When varRelid is not 0, only variables belonging to that relation are * considered in computing selectivity; other vars are treated as constants * of unknown values. This is appropriate for estimating the selectivity of * a join clause that is being used as a restriction clause in a scan of a * nestloop join's inner relation --- varRelid should then be the ID of the * inner relation. * * When varRelid is 0, all variables are treated as variables. This * is appropriate for ordinary join clauses and restriction clauses. * * jointype is the join type, if the clause is a join clause. Pass JOIN_INNER * if the clause isn't a join clause or the context is uncertain. */Selectivityclause_selectivity(Query *root, Node *clause, int varRelid, JoinType jointype){ Selectivity s1 = 1.0; /* default for any unhandled clause type */ if (clause == NULL) return s1; if (IsA(clause, Var)) { Var *var = (Var *) clause; /* * We probably shouldn't ever see an uplevel Var here, but if we * do, return the default selectivity... */ if (var->varlevelsup == 0 && (varRelid == 0 || varRelid == (int) var->varno)) { RangeTblEntry *rte = rt_fetch(var->varno, root->rtable); if (rte->rtekind == RTE_SUBQUERY) { /* * XXX not smart about subquery references... any way to * do better? */ s1 = 0.5; } else { /* * A Var at the top of a clause must be a bool Var. This * is equivalent to the clause reln.attribute = 't', so we * compute the selectivity as if that is what we have. */ s1 = restriction_selectivity(root, BooleanEqualOperator, makeList2(var, MAKEBOOLCONST(true, false)), varRelid); } } } else if (IsA(clause, Param)) { /* XXX any way to do better? */ s1 = 1.0; } else if (IsA(clause, Const)) { /* bool constant is pretty easy... */ s1 = ((bool) ((Const *) clause)->constvalue) ? 1.0 : 0.0; } else if (not_clause(clause)) { /* inverse of the selectivity of the underlying clause */ s1 = 1.0 - clause_selectivity(root, (Node *) get_notclausearg((Expr *) clause), varRelid, jointype); } else if (and_clause(clause)) { /* share code with clauselist_selectivity() */ s1 = clauselist_selectivity(root, ((BoolExpr *) clause)->args, varRelid, jointype); } else if (or_clause(clause)) { /* * Selectivities for an 'or' clause are computed as s1+s2 - s1*s2 * to account for the probable overlap of selected tuple sets. XXX * is this too conservative? */ List *arg; s1 = 0.0; foreach(arg, ((BoolExpr *) clause)->args) { Selectivity s2 = clause_selectivity(root, (Node *) lfirst(arg), varRelid, jointype); s1 = s1 + s2 - s1 * s2; } } else if (is_opclause(clause)) { Oid opno = ((OpExpr *) clause)->opno; bool is_join_clause; if (varRelid != 0) { /* * If we are considering a nestloop join then all clauses are * restriction clauses, since we are only interested in the * one relation. */ is_join_clause = false; } else { /* * Otherwise, it's a join if there's more than one relation * used. */ is_join_clause = (NumRelids(clause) > 1); } if (is_join_clause) { /* Estimate selectivity for a join clause. */ s1 = join_selectivity(root, opno, ((OpExpr *) clause)->args, jointype); } else { /* Estimate selectivity for a restriction clause. */ s1 = restriction_selectivity(root, opno, ((OpExpr *) clause)->args, varRelid); } } else if (is_funcclause(clause)) { /* * This is not an operator, so we guess at the selectivity. THIS * IS A HACK TO GET V4 OUT THE DOOR. FUNCS SHOULD BE ABLE TO HAVE * SELECTIVITIES THEMSELVES. -- JMH 7/9/92 */ s1 = (Selectivity) 0.3333333; } else if (is_subplan(clause)) { /* * Just for the moment! FIX ME! - vadim 02/04/98 */ s1 = (Selectivity) 0.5; } else if (IsA(clause, DistinctExpr) || IsA(clause, ScalarArrayOpExpr)) { /* can we do better? */ s1 = (Selectivity) 0.5; } else if (IsA(clause, NullTest)) { /* Use node specific selectivity calculation function */ s1 = nulltestsel(root, ((NullTest *) clause)->nulltesttype, (Node *) ((NullTest *) clause)->arg, varRelid); } else if (IsA(clause, BooleanTest)) { /* Use node specific selectivity calculation function */ s1 = booltestsel(root, ((BooleanTest *) clause)->booltesttype, (Node *) ((BooleanTest *) clause)->arg, varRelid, jointype); } else if (IsA(clause, RelabelType)) { /* Not sure this case is needed, but it can't hurt */ s1 = clause_selectivity(root, (Node *) ((RelabelType *) clause)->arg, varRelid, jointype); } else if (IsA(clause, CoerceToDomain)) { /* Not sure this case is needed, but it can't hurt */ s1 = clause_selectivity(root, (Node *) ((CoerceToDomain *) clause)->arg, varRelid, jointype); }#ifdef SELECTIVITY_DEBUG elog(DEBUG4, "clause_selectivity: s1 %f", s1);#endif /* SELECTIVITY_DEBUG */ return s1;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?