*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.236 2007/08/31 23:35:22 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.237 2007/11/07 21:00:37 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* patternsel - Generic code for pattern-match selectivity.
*/
static double
-patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype)
+patternsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
{
PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
Oid operator = PG_GETARG_OID(1);
Const *rest = NULL;
double result;
+ /*
+ * If this is for a NOT LIKE or similar operator, get the corresponding
+ * positive-match operator and work with that. Set result to the
+ * correct default estimate, too.
+ */
+ if (negate)
+ {
+ operator = get_negator(operator);
+ if (!OidIsValid(operator))
+ elog(ERROR, "patternsel called for operator without a negator");
+ result = 1.0 - DEFAULT_MATCH_SEL;
+ }
+ else
+ {
+ result = DEFAULT_MATCH_SEL;
+ }
+
/*
* If expression is not variable op constant, then punt and return a
* default estimate.
*/
if (!get_restriction_variable(root, args, varRelid,
&vardata, &other, &varonleft))
- return DEFAULT_MATCH_SEL;
+ return result;
if (!varonleft || !IsA(other, Const))
{
ReleaseVariableStats(vardata);
- return DEFAULT_MATCH_SEL;
+ return result;
}
variable = (Node *) linitial(args);
/*
* If the constant is NULL, assume operator is strict and return zero, ie,
- * operator will never return TRUE.
+ * operator will never return TRUE. (It's zero even for a negator op.)
*/
if (((Const *) other)->constisnull)
{
if (consttype != TEXTOID && consttype != BYTEAOID)
{
ReleaseVariableStats(vardata);
- return DEFAULT_MATCH_SEL;
+ return result;
}
/*
break;
default:
ReleaseVariableStats(vardata);
- return DEFAULT_MATCH_SEL;
+ return result;
}
/* divide pattern into fixed prefix and remainder */
elog(ERROR, "unrecognized consttype: %u",
prefix->consttype);
ReleaseVariableStats(vardata);
- return DEFAULT_MATCH_SEL;
+ return result;
}
prefix = string_to_const(prefixstr, vartype);
pfree(prefixstr);
ReleaseVariableStats(vardata);
- return result;
+ return negate ? (1.0 - result) : result;
}
/*
Datum
regexeqsel(PG_FUNCTION_ARGS)
{
- PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Regex));
+ PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Regex, false));
}
/*
Datum
icregexeqsel(PG_FUNCTION_ARGS)
{
- PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Regex_IC));
+ PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Regex_IC, false));
}
/*
Datum
likesel(PG_FUNCTION_ARGS)
{
- PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Like));
+ PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Like, false));
}
/*
Datum
iclikesel(PG_FUNCTION_ARGS)
{
- PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Like_IC));
+ PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Like_IC, false));
}
/*
Datum
regexnesel(PG_FUNCTION_ARGS)
{
- double result;
-
- result = patternsel(fcinfo, Pattern_Type_Regex);
- result = 1.0 - result;
- PG_RETURN_FLOAT8(result);
+ PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Regex, true));
}
/*
Datum
icregexnesel(PG_FUNCTION_ARGS)
{
- double result;
-
- result = patternsel(fcinfo, Pattern_Type_Regex_IC);
- result = 1.0 - result;
- PG_RETURN_FLOAT8(result);
+ PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Regex_IC, true));
}
/*
Datum
nlikesel(PG_FUNCTION_ARGS)
{
- double result;
-
- result = patternsel(fcinfo, Pattern_Type_Like);
- result = 1.0 - result;
- PG_RETURN_FLOAT8(result);
+ PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Like, true));
}
/*
Datum
icnlikesel(PG_FUNCTION_ARGS)
{
- double result;
-
- result = patternsel(fcinfo, Pattern_Type_Like_IC);
- result = 1.0 - result;
- PG_RETURN_FLOAT8(result);
+ PG_RETURN_FLOAT8(patternsel(fcinfo, Pattern_Type_Like_IC, true));
}
/*
PG_RETURN_FLOAT8(DEFAULT_INEQ_SEL);
}
+/*
+ * patternjoinsel - Generic code for pattern-match join selectivity.
+ */
+static double
+patternjoinsel(PG_FUNCTION_ARGS, Pattern_Type ptype, bool negate)
+{
+ /* For the moment we just punt. */
+ return negate ? (1.0 - DEFAULT_MATCH_SEL) : DEFAULT_MATCH_SEL;
+}
+
/*
* regexeqjoinsel - Join selectivity of regular-expression pattern match.
*/
Datum
regexeqjoinsel(PG_FUNCTION_ARGS)
{
- PG_RETURN_FLOAT8(DEFAULT_MATCH_SEL);
+ PG_RETURN_FLOAT8(patternjoinsel(fcinfo, Pattern_Type_Regex, false));
}
/*
Datum
icregexeqjoinsel(PG_FUNCTION_ARGS)
{
- PG_RETURN_FLOAT8(DEFAULT_MATCH_SEL);
+ PG_RETURN_FLOAT8(patternjoinsel(fcinfo, Pattern_Type_Regex_IC, false));
}
/*
Datum
likejoinsel(PG_FUNCTION_ARGS)
{
- PG_RETURN_FLOAT8(DEFAULT_MATCH_SEL);
+ PG_RETURN_FLOAT8(patternjoinsel(fcinfo, Pattern_Type_Like, false));
}
/*
Datum
iclikejoinsel(PG_FUNCTION_ARGS)
{
- PG_RETURN_FLOAT8(DEFAULT_MATCH_SEL);
+ PG_RETURN_FLOAT8(patternjoinsel(fcinfo, Pattern_Type_Like_IC, false));
}
/*
Datum
regexnejoinsel(PG_FUNCTION_ARGS)
{
- float8 result;
-
- result = DatumGetFloat8(regexeqjoinsel(fcinfo));
- result = 1.0 - result;
- PG_RETURN_FLOAT8(result);
+ PG_RETURN_FLOAT8(patternjoinsel(fcinfo, Pattern_Type_Regex, true));
}
/*
Datum
icregexnejoinsel(PG_FUNCTION_ARGS)
{
- float8 result;
-
- result = DatumGetFloat8(icregexeqjoinsel(fcinfo));
- result = 1.0 - result;
- PG_RETURN_FLOAT8(result);
+ PG_RETURN_FLOAT8(patternjoinsel(fcinfo, Pattern_Type_Regex_IC, true));
}
/*
Datum
nlikejoinsel(PG_FUNCTION_ARGS)
{
- float8 result;
-
- result = DatumGetFloat8(likejoinsel(fcinfo));
- result = 1.0 - result;
- PG_RETURN_FLOAT8(result);
+ PG_RETURN_FLOAT8(patternjoinsel(fcinfo, Pattern_Type_Like, true));
}
/*
Datum
icnlikejoinsel(PG_FUNCTION_ARGS)
{
- float8 result;
-
- result = DatumGetFloat8(iclikejoinsel(fcinfo));
- result = 1.0 - result;
- PG_RETURN_FLOAT8(result);
+ PG_RETURN_FLOAT8(patternjoinsel(fcinfo, Pattern_Type_Like_IC, true));
}
/*