1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-02 09:02:37 +03:00

Improve the performance of LIKE/regex estimation in non-C locales, by making

make_greater_string() try harder to generate a string that's actually greater
than its input string.  Before we just assumed that making a string that was
memcmp-greater was enough, but it is easy to generate examples where this is
not so when the locale is not C.  Instead, loop until the relevant comparison
function agrees that the generated string is greater than the input.

Unfortunately this is probably not enough to guarantee that the generated
string is greater than all extensions of the input, so we cannot relax the
restriction to C locale for the LIKE/regex index optimization.  But it should
at least improve the odds of getting a useful selectivity estimate in
prefix_selectivity().  Per example from Guillaume Smet.

Backpatch to 8.1, mainly because that's what the complainant is using...
This commit is contained in:
Tom Lane
2007-11-07 22:37:24 +00:00
parent 9542287123
commit 2de946be6a
3 changed files with 43 additions and 27 deletions

View File

@ -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,