From: teodor Date: Tue, 8 Jul 2008 13:08:39 +0000 (+0000) Subject: Sync X-Git-Url: http://sigaev.ru/git/gitweb.cgi?a=commitdiff_plain;h=b32b0f2fb3386df8ca64b7339b64fd319c752b82;p=wildspeed.git Sync --- diff --git a/wildspeed.c b/wildspeed.c index 389dff8..7aa0f96 100644 --- a/wildspeed.c +++ b/wildspeed.c @@ -133,14 +133,9 @@ gin_extract_permuted(PG_FUNCTION_ARGS) PG_RETURN_POINTER(entries); } -PG_FUNCTION_INFO_V1(wildcmp); -Datum wildcmp(PG_FUNCTION_ARGS); -Datum -wildcmp(PG_FUNCTION_ARGS) +static int +wildcmp_internal(text *a, text *b, bool partialMatch) { - text *a = PG_GETARG_TEXT_P(0); - text *b = PG_GETARG_TEXT_P(1); - bool partialMatch = PG_GETARG_BOOL(2); int32 cmp; int lena, lenb; @@ -244,6 +239,39 @@ wildcmp(PG_FUNCTION_ARGS) } } + return cmp; +} + +PG_FUNCTION_INFO_V1(wildcmp); +Datum wildcmp(PG_FUNCTION_ARGS); +Datum +wildcmp(PG_FUNCTION_ARGS) +{ + text *a = PG_GETARG_TEXT_P(0); + text *b = PG_GETARG_TEXT_P(1); + int32 cmp; + + cmp = wildcmp_internal(a, b, false); + + PG_FREE_IF_COPY(a,0); + PG_FREE_IF_COPY(b,1); + PG_RETURN_INT32( cmp ); +} + +PG_FUNCTION_INFO_V1(wildcmp_prefix); +Datum wildcmp_prefix(PG_FUNCTION_ARGS); +Datum +wildcmp_prefix(PG_FUNCTION_ARGS) +{ + text *a = PG_GETARG_TEXT_P(0); + text *b = PG_GETARG_TEXT_P(1); +#ifdef NOT_USED + StrategyNumber strategy = PG_GETARG_UINT16(2); +#endif + int32 cmp; + + cmp = wildcmp_internal(a, b, true); + PG_FREE_IF_COPY(a,0); PG_FREE_IF_COPY(b,1); PG_RETURN_INT32( cmp ); @@ -356,6 +384,7 @@ gin_extract_wildcard(PG_FUNCTION_ARGS) #endif bool *partialmatch, **ptr_partialmatch = (bool**) PG_GETARG_POINTER(3); + bool *needRecheck = (bool*) ((PG_NARGS() == 5) ? PG_GETARG_POINTER(4) : NULL); Datum *entries = NULL; char *qptr = VARDATA(q); int clen, @@ -365,6 +394,8 @@ gin_extract_wildcard(PG_FUNCTION_ARGS) text *entry; *nentries = 0; + if ( needRecheck ) + *needRecheck = false; if ( lenq == 0 ) { @@ -454,6 +485,9 @@ gin_extract_wildcard(PG_FUNCTION_ARGS) entries[ *nentries ] = PointerGetDatum( entry ); (*nentries)++; } + + if ( needRecheck && splitqlen > 3 /* X1 may be inside X OR Y */ ) + *needRecheck = true; } else { @@ -476,6 +510,8 @@ gin_extract_wildcard(PG_FUNCTION_ARGS) entries[ *nentries ] = PointerGetDatum( entry ); (*nentries)++; } + if ( needRecheck && splitqlen > 2 /* we don't remeber an order of Xn */ ) + *needRecheck = true; } } else @@ -510,6 +546,8 @@ gin_extract_wildcard(PG_FUNCTION_ARGS) entries[ *nentries ] = PointerGetDatum( entry ); (*nentries)++; } + if ( needRecheck && splitqlen > 2 /* X1 may be inside X */ ) + *needRecheck = true; } else { @@ -534,6 +572,9 @@ gin_extract_wildcard(PG_FUNCTION_ARGS) partialmatch[ *nentries ] = true; entries[ *nentries ] = PointerGetDatum( entry ); (*nentries)++; + + if ( needRecheck && splitqlen > 3 /* we don't remeber an order of Xn */ ) + *needRecheck = true; } } } @@ -542,12 +583,27 @@ gin_extract_wildcard(PG_FUNCTION_ARGS) #ifdef OPTIMIZE_WILDCARD_QUERY if ( *nentries > 1 ) + { + int saven = *nentries; + optimize_wildcard_search( entries, nentries ); + + if ( needRecheck && saven != *nentries ) + *needRecheck = true; + } #endif PG_RETURN_POINTER(entries); } +typedef struct PerCallConsistentStorage { + int nentries; + bool needRecheck; + int datasz; + char data[1]; /* query */ +} PerCallConsistentStorage; + +#define PCCSHDR_SZ offsetof(PerCallConsistentStorage, data) PG_FUNCTION_INFO_V1(gin_consistent_wildcard); Datum gin_consistent_wildcard(PG_FUNCTION_ARGS); @@ -555,37 +611,48 @@ Datum gin_consistent_wildcard(PG_FUNCTION_ARGS) { bool *check = (bool *) PG_GETARG_POINTER(0); + text *query = PG_GETARG_TEXT_P(2); bool res = true; int i; - int32 nentries; + PerCallConsistentStorage *pccs = NULL; + bool *recheck = (bool *) PG_GETARG_POINTER(3); - if ( fcinfo->flinfo->fn_extra == NULL ) + *recheck = true; + + pccs = (PerCallConsistentStorage*) fcinfo->flinfo->fn_extra; + + if ( pccs == NULL || pccs->datasz != VARSIZE(query) || memcmp( pccs->data, query, pccs->datasz) !=0 ) { - bool *pmatch; + bool *pmatch = NULL; /* - * we need to get nentries, we'll get it by regular way + * we need to fill our cache, we'll get it by regular way * and store it in function context */ - fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, - sizeof(int32)); + pccs = (PerCallConsistentStorage*) MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, + PCCSHDR_SZ + VARSIZE(query) ); + pccs->datasz = VARSIZE(query); + memcpy( pccs->data, query, pccs->datasz); - DirectFunctionCall4( + DirectFunctionCall5( gin_extract_wildcard, - PG_GETARG_DATUM(2), /* query */ - PointerGetDatum( fcinfo->flinfo->fn_extra ), /* &nentries */ + PointerGetDatum(query), + PointerGetDatum( &pccs->nentries ), /* &nentries */ PG_GETARG_DATUM(1), /* strategy */ - PointerGetDatum( &pmatch ) + PointerGetDatum( &pmatch ), + PointerGetDatum( &pccs->needRecheck ) ); - } - nentries = *(int32*) fcinfo->flinfo->fn_extra; + fcinfo->flinfo->fn_extra = (void*)pccs; + } - for (i = 0; res && i < nentries; i++) + for (i = 0; res && i < pccs->nentries; i++) if (check[i] == false) res = false; + *recheck = pccs->needRecheck; + PG_RETURN_BOOL(res); } diff --git a/wildspeed.sql.in b/wildspeed.sql.in index a8c5cdb..4cbaa5a 100644 --- a/wildspeed.sql.in +++ b/wildspeed.sql.in @@ -6,7 +6,12 @@ RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE; -CREATE OR REPLACE FUNCTION wildcmp(text, text, bool) +CREATE OR REPLACE FUNCTION wildcmp(text, text) +RETURNS int32 +AS 'MODULE_PATHNAME' +LANGUAGE C IMMUTABLE; + +CREATE OR REPLACE FUNCTION wildcmp_prefix(text, text, int2) RETURNS int32 AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE; @@ -24,11 +29,12 @@ LANGUAGE C IMMUTABLE; CREATE OPERATOR CLASS wildcard_ops FOR TYPE text USING gin AS - OPERATOR 1 ~~ RECHECK, - FUNCTION 1 wildcmp(text,text,bool), + OPERATOR 1 ~~, + FUNCTION 1 wildcmp(text,text), FUNCTION 2 gin_extract_permuted(text, internal), FUNCTION 3 gin_extract_wildcard(text, internal, int2, internal), FUNCTION 4 gin_consistent_wildcard(internal, int2, text), + FUNCTION 5 wildcmp_prefix(text,text,int2), STORAGE text;