diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2002-10-19 02:56:16 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2002-10-19 02:56:16 +0000 |
commit | c0f7dcdac10777a270eed88613a29b8e5d38a015 (patch) | |
tree | 08c825c755e7120f55f2ad5d41f49e5eacb6b3a4 /src/backend/utils/adt/selfuncs.c | |
parent | a3cb8746d901d503f99b9aa4ab80b6782c2b1767 (diff) | |
download | postgresql-c0f7dcdac10777a270eed88613a29b8e5d38a015.tar.gz postgresql-c0f7dcdac10777a270eed88613a29b8e5d38a015.zip |
Fix range-query estimation to not double-exclude NULLs, per gripe from
Ray Ontko 28-June-02. Also, fix prefix_selectivity for NAME lefthand
variables (it was bogusly assuming binary compatibility), and adjust
make_greater_string() to not call pg_mbcliplen() with invalid multibyte
data (this last per bug report that I can't find at the moment, but it
was in July '02).
Diffstat (limited to 'src/backend/utils/adt/selfuncs.c')
-rw-r--r-- | src/backend/utils/adt/selfuncs.c | 58 |
1 files changed, 29 insertions, 29 deletions
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index 693925b7ab5..211ccbf87bd 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.118 2002/09/20 03:55:40 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.119 2002/10/19 02:56:16 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1007,10 +1007,9 @@ icnlikesel(PG_FUNCTION_ARGS) * booltestsel - Selectivity of BooleanTest Node. */ Selectivity -booltestsel(Query *root, BooleanTest *clause, int varRelid) +booltestsel(Query *root, BoolTestType booltesttype, Node *arg, int varRelid) { Var *var; - Node *arg; Oid relid; HeapTuple statsTuple; Datum *values; @@ -1019,10 +1018,6 @@ booltestsel(Query *root, BooleanTest *clause, int varRelid) int nnumbers; double selec; - Assert(clause && IsA(clause, BooleanTest)); - - arg = (Node *) clause->arg; - /* * Ignore any binary-compatible relabeling (probably unnecessary, but * can't hurt) @@ -1040,7 +1035,7 @@ booltestsel(Query *root, BooleanTest *clause, int varRelid) * the possibility of a NULL value when using clause_selectivity, * and just assume the value is either TRUE or FALSE. */ - switch (clause->booltesttype) + switch (booltesttype) { case IS_UNKNOWN: selec = DEFAULT_UNK_SEL; @@ -1058,7 +1053,7 @@ booltestsel(Query *root, BooleanTest *clause, int varRelid) break; default: elog(ERROR, "booltestsel: unexpected booltesttype %d", - (int) clause->booltesttype); + (int) booltesttype); selec = 0.0; /* Keep compiler quiet */ break; } @@ -1107,7 +1102,7 @@ booltestsel(Query *root, BooleanTest *clause, int varRelid) */ freq_false = 1.0 - freq_true - freq_null; - switch (clause->booltesttype) + switch (booltesttype) { case IS_UNKNOWN: /* select only NULL values */ @@ -1135,7 +1130,7 @@ booltestsel(Query *root, BooleanTest *clause, int varRelid) break; default: elog(ERROR, "booltestsel: unexpected booltesttype %d", - (int) clause->booltesttype); + (int) booltesttype); selec = 0.0; /* Keep compiler quiet */ break; } @@ -1151,7 +1146,7 @@ booltestsel(Query *root, BooleanTest *clause, int varRelid) * Otherwise adjust for null fraction and assume an even split * for boolean tests. */ - switch (clause->booltesttype) + switch (booltesttype) { case IS_UNKNOWN: @@ -1176,7 +1171,7 @@ booltestsel(Query *root, BooleanTest *clause, int varRelid) break; default: elog(ERROR, "booltestsel: unexpected booltesttype %d", - (int) clause->booltesttype); + (int) booltesttype); selec = 0.0; /* Keep compiler quiet */ break; } @@ -1190,7 +1185,7 @@ booltestsel(Query *root, BooleanTest *clause, int varRelid) * No VACUUM ANALYZE stats available, so use a default value. * (Note: not much point in recursing to clause_selectivity here.) */ - switch (clause->booltesttype) + switch (booltesttype) { case IS_UNKNOWN: selec = DEFAULT_UNK_SEL; @@ -1206,7 +1201,7 @@ booltestsel(Query *root, BooleanTest *clause, int varRelid) break; default: elog(ERROR, "booltestsel: unexpected booltesttype %d", - (int) clause->booltesttype); + (int) booltesttype); selec = 0.0; /* Keep compiler quiet */ break; } @@ -1222,19 +1217,16 @@ booltestsel(Query *root, BooleanTest *clause, int varRelid) * nulltestsel - Selectivity of NullTest Node. */ Selectivity -nulltestsel(Query *root, NullTest *clause, int varRelid) +nulltestsel(Query *root, NullTestType nulltesttype, Node *arg, int varRelid) { Var *var; - Node *arg; Oid relid; HeapTuple statsTuple; double selec; double defselec; double freq_null; - Assert(clause && IsA(clause, NullTest)); - - switch (clause->nulltesttype) + switch (nulltesttype) { case IS_NULL: defselec = DEFAULT_UNK_SEL; @@ -1244,25 +1236,22 @@ nulltestsel(Query *root, NullTest *clause, int varRelid) break; default: elog(ERROR, "nulltestsel: unexpected nulltesttype %d", - (int) clause->nulltesttype); + (int) nulltesttype); return (Selectivity) 0; /* keep compiler quiet */ } - arg = (Node *) clause->arg; - /* * Ignore any binary-compatible relabeling */ if (IsA(arg, RelabelType)) arg = ((RelabelType *) arg)->arg; - if (IsA(arg, Var) &&(varRelid == 0 || varRelid == ((Var *) arg)->varno)) + if (IsA(arg, Var) && + (varRelid == 0 || varRelid == ((Var *) arg)->varno)) var = (Var *) arg; else { - /* - * punt if non-Var argument - */ + /* punt if non-Var argument */ return (Selectivity) defselec; } @@ -1282,7 +1271,7 @@ nulltestsel(Query *root, NullTest *clause, int varRelid) stats = (Form_pg_statistic) GETSTRUCT(statsTuple); freq_null = stats->stanullfrac; - switch (clause->nulltesttype) + switch (nulltesttype) { case IS_NULL: @@ -1301,7 +1290,7 @@ nulltestsel(Query *root, NullTest *clause, int varRelid) break; default: elog(ERROR, "nulltestsel: unexpected nulltesttype %d", - (int) clause->nulltesttype); + (int) nulltesttype); return (Selectivity) 0; /* keep compiler quiet */ } @@ -2978,6 +2967,10 @@ prefix_selectivity(Query *root, Var *var, Const *prefixcon) else prefix = DatumGetCString(DirectFunctionCall1(byteaout, prefixcon->constvalue)); + /* If var is type NAME, must adjust type of comparison constant */ + if (var->vartype == NAMEOID) + prefixcon = string_to_const(prefix, NAMEOID); + cmpargs = makeList2(var, prefixcon); /* Assume scalargtsel is appropriate for all supported types */ prefixsel = DatumGetFloat8(DirectFunctionCall4(scalargtsel, @@ -3014,6 +3007,9 @@ prefix_selectivity(Query *root, Var *var, Const *prefixcon) */ prefixsel = topsel + prefixsel - 1.0; + /* Adjust for double-exclusion of NULLs */ + prefixsel += nulltestsel(root, IS_NULL, (Node *) var, var->varno); + /* * A zero or slightly negative prefixsel should be converted into * a small positive value; we probably are dealing with a very @@ -3351,6 +3347,7 @@ make_greater_string(const Const *str_const) while (len > 0) { unsigned char *lastchar = (unsigned char *) (workstr + len - 1); + unsigned char savelastchar = *lastchar; /* * Try to generate a larger string by incrementing the last byte. @@ -3369,6 +3366,9 @@ make_greater_string(const Const *str_const) } } + /* restore last byte so we don't confuse pg_mbcliplen */ + *lastchar = savelastchar; + /* * Truncate off the last character, which might be more than 1 * byte, depending on the character encoding. |