add gin_count_estimate() for tsvector index
authorteodor <teodor>
Fri, 4 Jul 2008 17:15:16 +0000 (17:15 +0000)
committerteodor <teodor>
Fri, 4 Jul 2008 17:15:16 +0000 (17:15 +0000)
README.gevel
gevel.c
gevel.sql.in

index c3fbf2a..21230c1 100644 (file)
@@ -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 (file)
--- a/gevel.c
+++ b/gevel.c
 #include "miscadmin.h"
 #include "storage/lmgr.h"
 #include "catalog/namespace.h"
+#if PG_VERSION_NUM >= 80300
+#include <tsearch/ts_utils.h>
+#endif
+#include <utils/tqual.h>
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
 #include "utils/datum.h"
+#include "utils/fmgroids.h"
 #include <fmgr.h>
 #include <funcapi.h>
 #include <access/heapam.h>
 #include <catalog/pg_type.h>
+#include <access/relscan.h>
+
 
 #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
index 6bfa5e8..5294f81 100644 (file)
@@ -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;