*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.191.2.12 2007/07/31 19:54:00 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.191.2.13 2007/11/07 22:37:43 tgl Exp $
*
*-------------------------------------------------------------------------
*/
Oid datatype;
Oid oproid;
Expr *expr;
+ FmgrInfo ltproc;
Const *greaterstr;
Assert(pstatus != Pattern_Prefix_None);
* "x < greaterstr".
*-------
*/
- greaterstr = make_greater_string(prefix_const);
+ oproid = get_opclass_member(opclass, InvalidOid,
+ BTLessStrategyNumber);
+ if (oproid == InvalidOid)
+ elog(ERROR, "no < operator for opclass %u", opclass);
+ fmgr_info(get_opcode(oproid), <proc);
+ greaterstr = make_greater_string(prefix_const, <proc);
if (greaterstr)
{
- oproid = get_opclass_member(opclass, InvalidOid,
- BTLessStrategyNumber);
- if (oproid == InvalidOid)
- elog(ERROR, "no < operator for opclass %u", opclass);
expr = make_opclause(oproid, BOOLOID, false,
(Expr *) leftop, (Expr *) greaterstr);
result = lappend(result, make_restrictinfo(expr, true, false, NULL));
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.191.2.3 2007/01/03 22:39:42 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.191.2.4 2007/11/07 22:37:43 tgl Exp $
*
*-------------------------------------------------------------------------
*/
Selectivity prefixsel;
Oid cmpopr;
List *cmpargs;
+ FmgrInfo ltproc;
Const *greaterstrcon;
cmpopr = get_opclass_member(opclass, InvalidOid,
* "x < greaterstr".
*-------
*/
- greaterstrcon = make_greater_string(prefixcon);
+ cmpopr = get_opclass_member(opclass, InvalidOid,
+ BTLessStrategyNumber);
+ if (cmpopr == InvalidOid)
+ elog(ERROR, "no < operator for opclass %u", opclass);
+ fmgr_info(get_opcode(cmpopr), <proc);
+
+ greaterstrcon = make_greater_string(prefixcon, <proc);
if (greaterstrcon)
{
Selectivity topsel;
- cmpopr = get_opclass_member(opclass, InvalidOid,
- BTLessStrategyNumber);
- if (cmpopr == InvalidOid)
- elog(ERROR, "no < operator for opclass %u", opclass);
cmpargs = list_make2(variable, greaterstrcon);
/* Assume scalarltsel is appropriate for all supported types */
topsel = DatumGetFloat8(DirectFunctionCall4(scalarltsel,
* 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
*
* 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,
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 */