selfuncs.c
来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 2,384 行 · 第 1/5 页
C
2,384 行
*/ Oid eqopr = get_opclass_member(opclass, BTEqualStrategyNumber); List *eqargs; if (eqopr == InvalidOid) elog(ERROR, "no = operator for opclass %u", opclass); eqargs = makeList2(var, prefix); result = DatumGetFloat8(DirectFunctionCall4(eqsel, PointerGetDatum(root), ObjectIdGetDatum(eqopr), PointerGetDatum(eqargs), Int32GetDatum(varRelid))); } else { /* * Not exact-match pattern. We estimate selectivity of the fixed * prefix and remainder of pattern separately, then combine the * two. */ Selectivity prefixsel; Selectivity restsel; Selectivity selec; if (pstatus == Pattern_Prefix_Partial) prefixsel = prefix_selectivity(root, var, opclass, prefix); else prefixsel = 1.0; restsel = pattern_selectivity(rest, ptype); selec = prefixsel * restsel; /* result should be in range, but make sure... */ CLAMP_PROBABILITY(selec); result = selec; } if (prefix) { pfree(DatumGetPointer(prefix->constvalue)); pfree(prefix); } return result;}/* * regexeqsel - Selectivity of regular-expression pattern match. */Datumregexeqsel(PG_FUNCTION_ARGS){ PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Regex));}/* * icregexeqsel - Selectivity of case-insensitive regex match. */Datumicregexeqsel(PG_FUNCTION_ARGS){ PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Regex_IC));}/* * likesel - Selectivity of LIKE pattern match. */Datumlikesel(PG_FUNCTION_ARGS){ PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Like));}/* * iclikesel - Selectivity of ILIKE pattern match. */Datumiclikesel(PG_FUNCTION_ARGS){ PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Like_IC));}/* * regexnesel - Selectivity of regular-expression pattern non-match. */Datumregexnesel(PG_FUNCTION_ARGS){ double result; result = patternsel(fcinfo, Pattern_Type_Regex); result = 1.0 - result; PG_RETURN_FLOAT8(result);}/* * icregexnesel - Selectivity of case-insensitive regex non-match. */Datumicregexnesel(PG_FUNCTION_ARGS){ double result; result = patternsel(fcinfo, Pattern_Type_Regex_IC); result = 1.0 - result; PG_RETURN_FLOAT8(result);}/* * nlikesel - Selectivity of LIKE pattern non-match. */Datumnlikesel(PG_FUNCTION_ARGS){ double result; result = patternsel(fcinfo, Pattern_Type_Like); result = 1.0 - result; PG_RETURN_FLOAT8(result);}/* * icnlikesel - Selectivity of ILIKE pattern non-match. */Datumicnlikesel(PG_FUNCTION_ARGS){ double result; result = patternsel(fcinfo, Pattern_Type_Like_IC); result = 1.0 - result; PG_RETURN_FLOAT8(result);}/* * booltestsel - Selectivity of BooleanTest Node. */Selectivitybooltestsel(Query *root, BoolTestType booltesttype, Node *arg, int varRelid, JoinType jointype){ Var *var; Oid relid; HeapTuple statsTuple; Datum *values; int nvalues; float4 *numbers; int nnumbers; double selec; /* * Ignore any binary-compatible relabeling (probably unnecessary, but * can't hurt) */ if (IsA(arg, RelabelType)) arg = (Node *) ((RelabelType *) arg)->arg; if (IsA(arg, Var) && (varRelid == 0 || varRelid == ((Var *) arg)->varno)) var = (Var *) arg; else { /* * If argument is not a Var, we can't get statistics for it, but * perhaps clause_selectivity can do something with it. We ignore * the possibility of a NULL value when using clause_selectivity, * and just assume the value is either TRUE or FALSE. */ switch (booltesttype) { case IS_UNKNOWN: selec = DEFAULT_UNK_SEL; break; case IS_NOT_UNKNOWN: selec = DEFAULT_NOT_UNK_SEL; break; case IS_TRUE: case IS_NOT_FALSE: selec = (double) clause_selectivity(root, arg, varRelid, jointype); break; case IS_FALSE: case IS_NOT_TRUE: selec = 1.0 - (double) clause_selectivity(root, arg, varRelid, jointype); break; default: elog(ERROR, "unrecognized booltesttype: %d", (int) booltesttype); selec = 0.0; /* Keep compiler quiet */ break; } return (Selectivity) selec; } /* get stats for the attribute, if available */ relid = getrelid(var->varno, root->rtable); if (relid == InvalidOid) statsTuple = NULL; else statsTuple = SearchSysCache(STATRELATT, ObjectIdGetDatum(relid), Int16GetDatum(var->varattno), 0, 0); if (HeapTupleIsValid(statsTuple)) { Form_pg_statistic stats; double freq_null; stats = (Form_pg_statistic) GETSTRUCT(statsTuple); freq_null = stats->stanullfrac; if (get_attstatsslot(statsTuple, var->vartype, var->vartypmod, STATISTIC_KIND_MCV, InvalidOid, &values, &nvalues, &numbers, &nnumbers) && nnumbers > 0) { double freq_true; double freq_false; /* * Get first MCV frequency and derive frequency for true. */ if (DatumGetBool(values[0])) freq_true = numbers[0]; else freq_true = 1.0 - numbers[0] - freq_null; /* * Next derive freqency for false. Then use these as * appropriate to derive frequency for each case. */ freq_false = 1.0 - freq_true - freq_null; switch (booltesttype) { case IS_UNKNOWN: /* select only NULL values */ selec = freq_null; break; case IS_NOT_UNKNOWN: /* select non-NULL values */ selec = 1.0 - freq_null; break; case IS_TRUE: /* select only TRUE values */ selec = freq_true; break; case IS_NOT_TRUE: /* select non-TRUE values */ selec = 1.0 - freq_true; break; case IS_FALSE: /* select only FALSE values */ selec = freq_false; break; case IS_NOT_FALSE: /* select non-FALSE values */ selec = 1.0 - freq_false; break; default: elog(ERROR, "unrecognized booltesttype: %d", (int) booltesttype); selec = 0.0; /* Keep compiler quiet */ break; } free_attstatsslot(var->vartype, values, nvalues, numbers, nnumbers); } else { /* * No most-common-value info available. Still have null * fraction information, so use it for IS [NOT] UNKNOWN. * Otherwise adjust for null fraction and assume an even split * for boolean tests. */ switch (booltesttype) { case IS_UNKNOWN: /* * Use freq_null directly. */ selec = freq_null; break; case IS_NOT_UNKNOWN: /* * Select not unknown (not null) values. Calculate * from freq_null. */ selec = 1.0 - freq_null; break; case IS_TRUE: case IS_NOT_TRUE: case IS_FALSE: case IS_NOT_FALSE: selec = (1.0 - freq_null) / 2.0; break; default: elog(ERROR, "unrecognized booltesttype: %d", (int) booltesttype); selec = 0.0; /* Keep compiler quiet */ break; } } ReleaseSysCache(statsTuple); } else { /* * No VACUUM ANALYZE stats available, so use a default value. * (Note: not much point in recursing to clause_selectivity here.) */ switch (booltesttype) { case IS_UNKNOWN: selec = DEFAULT_UNK_SEL; break; case IS_NOT_UNKNOWN: selec = DEFAULT_NOT_UNK_SEL; break; case IS_TRUE: case IS_NOT_TRUE: case IS_FALSE: case IS_NOT_FALSE: selec = DEFAULT_BOOL_SEL; break; default: elog(ERROR, "unrecognized booltesttype: %d", (int) booltesttype); selec = 0.0; /* Keep compiler quiet */ break; } } /* result should be in range, but make sure... */ CLAMP_PROBABILITY(selec); return (Selectivity) selec;}/* * nulltestsel - Selectivity of NullTest Node. */Selectivitynulltestsel(Query *root, NullTestType nulltesttype, Node *arg, int varRelid){ Var *var; Oid relid; HeapTuple statsTuple; double selec; double defselec; double freq_null; switch (nulltesttype) { case IS_NULL: defselec = DEFAULT_UNK_SEL; break; case IS_NOT_NULL: defselec = DEFAULT_NOT_UNK_SEL; break; default: elog(ERROR, "unrecognized nulltesttype: %d", (int) nulltesttype); return (Selectivity) 0; /* keep compiler quiet */ } /* * Ignore any binary-compatible relabeling */ if (IsA(arg, RelabelType)) arg = (Node *) ((RelabelType *) arg)->arg; if (IsA(arg, Var) && (varRelid == 0 || varRelid == ((Var *) arg)->varno)) var = (Var *) arg; else { /* punt if non-Var argument */ return (Selectivity) defselec; } relid = getrelid(var->varno, root->rtable); if (relid == InvalidOid) return (Selectivity) defselec; /* get stats for the attribute, if available */ statsTuple = SearchSysCache(STATRELATT, ObjectIdGetDatum(relid), Int16GetDatum(var->varattno), 0, 0); if (HeapTupleIsValid(statsTuple)) { Form_pg_statistic stats; stats = (Form_pg_statistic) GETSTRUCT(statsTuple); freq_null = stats->stanullfrac; switch (nulltesttype) { case IS_NULL: /* * Use freq_null directly. */ selec = freq_null; break; case IS_NOT_NULL: /* * Select not unknown (not null) values. Calculate from * freq_null. */ selec = 1.0 - freq_null; break; default: elog(ERROR, "unrecognized nulltesttype: %d", (int) nulltesttype); return (Selectivity) 0; /* keep compiler quiet */ } ReleaseSysCache(statsTuple); } else { /* * No VACUUM ANALYZE stats available, so make a guess */ selec = defselec; } /* result should be in range, but make sure... */ CLAMP_PROBABILITY(selec); return (Selectivity) selec;}/* * eqjoinsel - Join selectivity of "=" */Datumeqjoinsel(PG_FUNCTION_ARGS){ Query *root = (Query *) PG_GETARG_POINTER(0); Oid operator = PG_GETARG_OID(1); List *args = (List *) PG_GETARG_POINTER(2); JoinType jointype = (JoinType) PG_GETARG_INT16(3); Var *var1; Var *var2; double selec; get_join_vars(args, &var1, &var2); if (var1 == NULL && var2 == NULL) selec = DEFAULT_EQ_SEL; else { HeapTuple statsTuple1 = NULL; HeapTuple statsTuple2 = NULL; Form_pg_statistic stats1 = NULL; Form_pg_statistic stats2 = NULL; double nd1 = DEFAULT_NUM_DISTINCT; double nd2 = DEFAULT_NUM_DISTINCT; bool have_mcvs1 = false; Datum *values1 = NULL; int nvalues1 = 0; float4 *numbers1 = NULL; int nnumbers1 = 0; bool have_mcvs2 = false; Datum *values2 = NULL; int nvalues2 = 0;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?