1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-05 07:21:24 +03:00

Add prefix operator for TEXT type.

The prefix operator along with SP-GiST indexes can be used as an alternative
for LIKE 'word%' commands  and it doesn't have a limitation of string/prefix
length as B-Tree has.

Bump catalog version

Author: Ildus Kurbangaliev with some editorization by me
Review by: Arthur Zakirov, Alexander Korotkov, and me
Discussion: https://www.postgresql.org/message-id/flat/20180202180327.222b04b3@wp.localdomain
This commit is contained in:
Teodor Sigaev
2018-04-03 19:46:45 +03:00
parent 4ab2999815
commit 710d90da1f
14 changed files with 189 additions and 9 deletions

View File

@ -67,6 +67,20 @@
*/
#define SPGIST_MAX_PREFIX_LENGTH Max((int) (BLCKSZ - 258 * 16 - 100), 32)
/*
* Strategy for collation aware operator on text is equal to btree strategy
* plus value of 10.
*
* Current collation aware strategies and their corresponding btree strategies:
* 11 BTLessStrategyNumber
* 12 BTLessEqualStrategyNumber
* 14 BTGreaterEqualStrategyNumber
* 15 BTGreaterStrategyNumber
*/
#define SPG_STRATEGY_ADDITION (10)
#define SPG_IS_COLLATION_AWARE_STRATEGY(s) ((s) > SPG_STRATEGY_ADDITION \
&& (s) != RTPrefixStrategyNumber)
/* Struct for sorting values in picksplit */
typedef struct spgNodePtr
{
@ -496,10 +510,10 @@ spg_text_inner_consistent(PG_FUNCTION_ARGS)
* well end with a partial multibyte character, so that applying
* any encoding-sensitive test to it would be risky anyhow.)
*/
if (strategy > 10)
if (SPG_IS_COLLATION_AWARE_STRATEGY(strategy))
{
if (collate_is_c)
strategy -= 10;
strategy -= SPG_STRATEGY_ADDITION;
else
continue;
}
@ -526,6 +540,10 @@ spg_text_inner_consistent(PG_FUNCTION_ARGS)
if (r < 0)
res = false;
break;
case RTPrefixStrategyNumber:
if (r != 0)
res = false;
break;
default:
elog(ERROR, "unrecognized strategy number: %d",
in->scankeys[j].sk_strategy);
@ -605,10 +623,27 @@ spg_text_leaf_consistent(PG_FUNCTION_ARGS)
int queryLen = VARSIZE_ANY_EXHDR(query);
int r;
if (strategy > 10)
if (strategy == RTPrefixStrategyNumber)
{
/*
* if level >= length of query then reconstrValue is began with
* query (prefix) string and we don't need to check it again.
*/
res = (level >= queryLen) ||
DatumGetBool(DirectFunctionCall2(text_starts_with,
out->leafValue, PointerGetDatum(query)));
if (!res) /* no need to consider remaining conditions */
break;
continue;
}
if (SPG_IS_COLLATION_AWARE_STRATEGY(strategy))
{
/* Collation-aware comparison */
strategy -= 10;
strategy -= SPG_STRATEGY_ADDITION;
/* If asserts enabled, verify encoding of reconstructed string */
Assert(pg_verifymbstr(fullValue, fullLen, false));