From: teodor Date: Fri, 4 Jul 2008 17:15:16 +0000 (+0000) Subject: add gin_count_estimate() for tsvector index X-Git-Url: http://www.sigaev.ru/git/gitweb.cgi?p=gevel.git;a=commitdiff_plain;h=56c12cb8cb8a966738e78f784f2c55e955f36830 add gin_count_estimate() for tsvector index --- diff --git a/README.gevel b/README.gevel index c3fbf2a..21230c1 100644 --- a/README.gevel +++ b/README.gevel @@ -134,3 +134,12 @@ regression=# select gist_tree('pix'); 59 | 259 (4 rows) + * bigint gin_count_estimate(INDEXNAME, TSQUERY) outputs number of indexed + rows matched query. It doesn't touch heap at all. + +# select gin_count_estimate('qq', 'star'); + gin_count_estimate +-------------------- + 790 +(1 row) + diff --git a/gevel.c b/gevel.c index 69115d5..2886c3d 100644 --- a/gevel.c +++ b/gevel.c @@ -10,13 +10,20 @@ #include "miscadmin.h" #include "storage/lmgr.h" #include "catalog/namespace.h" +#if PG_VERSION_NUM >= 80300 +#include +#endif +#include #include "utils/builtins.h" #include "utils/lsyscache.h" #include "utils/datum.h" +#include "utils/fmgroids.h" #include #include #include #include +#include + #define PAGESIZE (BLCKSZ - MAXALIGN(sizeof(PageHeaderData) + sizeof(ItemIdData))) @@ -586,7 +593,7 @@ gin_setup_firstcall(FuncCallContext *funcctx, text *name) { st=(GinStatState*)palloc( sizeof(GinStatState) ); memset(st,0,sizeof(GinStatState)); st->index = gin_index_open( - makeRangeVarFromNameList(stringToQualifiedNameList(relname, "gist_tree"))); + makeRangeVarFromNameList(stringToQualifiedNameList(relname, "gin_stat"))); initGinState( &st->ginstate, st->index ); funcctx->user_fctx = (void*)st; @@ -696,3 +703,51 @@ gin_stat(PG_FUNCTION_ARGS) { SRF_RETURN_NEXT(funcctx, result); } +PG_FUNCTION_INFO_V1(gin_count_estimate); +Datum gin_count_estimate(PG_FUNCTION_ARGS); +#if PG_VERSION_NUM >= 80300 +Datum +gin_count_estimate(PG_FUNCTION_ARGS) { + text *name=PG_GETARG_TEXT_P(0); + Relation index; + TIDBitmap *bitmap = tbm_create(work_mem * 1024L); + IndexScanDesc scan; + int64 count; + char *relname=t2c(name); + ScanKeyData key; + + index = gin_index_open( + makeRangeVarFromNameList(stringToQualifiedNameList(relname, "gin_count_estimate"))); + + if ( index->rd_opcintype[0] != TSVECTOROID ) { + gin_index_close(index); + elog(ERROR, "Column type is not a tsvector"); + } + + key.sk_flags = 0; + key.sk_attno = 1; + key.sk_strategy = TSearchStrategyNumber; + key.sk_subtype = 0; + key.sk_argument = PG_GETARG_DATUM(1); + + fmgr_info( F_TS_MATCH_VQ , &key.sk_func ); + + scan = index_beginscan_bitmap(index, SnapshotNow, 1, &key); + + count = index_getbitmap(scan, bitmap); + tbm_free(bitmap); + + index_endscan( scan ); + gin_index_close(index); + + + PG_RETURN_INT64(count); +} +#else +Datum +gin_count_estimate(PG_FUNCTION_ARGS) { + elog(NOTICE, "Function is not working under PgSQL < 8.3"); + + PG_RETURN_INT64(0); +} +#endif diff --git a/gevel.sql.in b/gevel.sql.in index 6bfa5e8..5294f81 100644 --- a/gevel.sql.in +++ b/gevel.sql.in @@ -31,4 +31,11 @@ create or replace function gin_stat(text) language 'C' with (isstrict); +create or replace function gin_count_estimate(text, tsquery) + returns bigint + as 'MODULE_PATHNAME' + language 'C' + with (isstrict); + + END;