aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/optimizer/path/indxpath.c14
-rw-r--r--src/backend/utils/adt/selfuncs.c52
-rw-r--r--src/include/utils/selfuncs.h4
3 files changed, 43 insertions, 27 deletions
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index b9439e60a8b..47dd3ec55b0 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.222 2007/05/22 01:40:33 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.223 2007/11/07 22:37:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -2668,6 +2668,7 @@ prefix_quals(Node *leftop, Oid opfamily,
Oid datatype;
Oid oproid;
Expr *expr;
+ FmgrInfo ltproc;
Const *greaterstr;
Assert(pstatus != Pattern_Prefix_None);
@@ -2759,13 +2760,14 @@ prefix_quals(Node *leftop, Oid opfamily,
* "x < greaterstr".
*-------
*/
- greaterstr = make_greater_string(prefix_const);
+ oproid = get_opfamily_member(opfamily, datatype, datatype,
+ BTLessStrategyNumber);
+ if (oproid == InvalidOid)
+ elog(ERROR, "no < operator for opfamily %u", opfamily);
+ fmgr_info(get_opcode(oproid), &ltproc);
+ greaterstr = make_greater_string(prefix_const, &ltproc);
if (greaterstr)
{
- oproid = get_opfamily_member(opfamily, datatype, datatype,
- BTLessStrategyNumber);
- if (oproid == InvalidOid)
- elog(ERROR, "no < operator for opfamily %u", opfamily);
expr = make_opclause(oproid, BOOLOID, false,
(Expr *) leftop, (Expr *) greaterstr);
result = lappend(result,
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index 5bf04d052a6..095b389eb12 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.237 2007/11/07 21:00:37 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.238 2007/11/07 22:37:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -4302,17 +4302,17 @@ prefix_selectivity(VariableStatData *vardata,
* "x < greaterstr".
*-------
*/
- greaterstrcon = make_greater_string(prefixcon);
+ cmpopr = get_opfamily_member(opfamily, vartype, vartype,
+ BTLessStrategyNumber);
+ if (cmpopr == InvalidOid)
+ elog(ERROR, "no < operator for opfamily %u", opfamily);
+ fmgr_info(get_opcode(cmpopr), &opproc);
+
+ greaterstrcon = make_greater_string(prefixcon, &opproc);
if (greaterstrcon)
{
Selectivity topsel;
- cmpopr = get_opfamily_member(opfamily, vartype, vartype,
- BTLessStrategyNumber);
- if (cmpopr == InvalidOid)
- elog(ERROR, "no < operator for opfamily %u", opfamily);
- fmgr_info(get_opcode(cmpopr), &opproc);
-
topsel = ineq_histogram_selectivity(vardata, &opproc, false,
greaterstrcon->constvalue,
greaterstrcon->consttype);
@@ -4589,8 +4589,17 @@ pattern_selectivity(Const *patt, Pattern_Type ptype)
* in the form of a Const pointer; else return NULL.
*
* The key requirement here is that given a prefix string, say "foo",
- * we must be able to generate another string "fop" that is greater
- * than all strings "foobar" starting with "foo".
+ * we must be able to generate another string "fop" that is greater than
+ * all strings "foobar" starting with "foo". We can test that we have
+ * generated a string greater than the prefix string, but in non-C locales
+ * that is not a bulletproof guarantee that an extension of the string might
+ * not sort after it; an example is that "foo " is less than "foo!", but it
+ * is not clear that a "dictionary" sort ordering will consider "foo!" less
+ * than "foo bar". Therefore, this function should be used only for
+ * estimation purposes when working in a non-C locale.
+ *
+ * The caller must provide the appropriate "less than" comparison function
+ * for testing the strings.
*
* If we max out the righthand byte, truncate off the last character
* and start incrementing the next. For example, if "z" were the last
@@ -4599,20 +4608,15 @@ pattern_selectivity(Const *patt, Pattern_Type ptype)
*
* This could be rather slow in the worst case, but in most cases we
* won't have to try more than one or two strings before succeeding.
- *
- * NOTE: at present this assumes we are in the C locale, so that simple
- * bytewise comparison applies. However, we might be in a multibyte
- * encoding such as UTF8, so we do have to watch out for generating
- * invalid encoding sequences.
*/
Const *
-make_greater_string(const Const *str_const)
+make_greater_string(const Const *str_const, FmgrInfo *ltproc)
{
Oid datatype = str_const->consttype;
char *workstr;
int len;
- /* Get the string and a modifiable copy */
+ /* Get a modifiable copy of the string in C-string format */
if (datatype == NAMEOID)
{
workstr = DatumGetCString(DirectFunctionCall1(nameout,
@@ -4660,8 +4664,18 @@ make_greater_string(const Const *str_const)
else
workstr_const = string_to_bytea_const(workstr, len);
- pfree(workstr);
- return workstr_const;
+ if (DatumGetBool(FunctionCall2(ltproc,
+ str_const->constvalue,
+ workstr_const->constvalue)))
+ {
+ /* Successfully made a string larger than the input */
+ pfree(workstr);
+ return workstr_const;
+ }
+
+ /* No good, release unusable value and try again */
+ pfree(DatumGetPointer(workstr_const->constvalue));
+ pfree(workstr_const);
}
/* restore last byte so we don't confuse pg_mbcliplen */
diff --git a/src/include/utils/selfuncs.h b/src/include/utils/selfuncs.h
index fc409d9bddd..f92bb16d079 100644
--- a/src/include/utils/selfuncs.h
+++ b/src/include/utils/selfuncs.h
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/utils/selfuncs.h,v 1.40 2007/08/31 23:35:22 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/selfuncs.h,v 1.41 2007/11/07 22:37:24 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -118,7 +118,7 @@ extern Pattern_Prefix_Status pattern_fixed_prefix(Const *patt,
Pattern_Type ptype,
Const **prefix,
Const **rest);
-extern Const *make_greater_string(const Const *str_const);
+extern Const *make_greater_string(const Const *str_const, FmgrInfo *ltproc);
extern Datum eqsel(PG_FUNCTION_ARGS);
extern Datum neqsel(PG_FUNCTION_ARGS);