From a61c2088be6a6f32e3ce6829e860bf2a431d5e05 Mon Sep 17 00:00:00 2001 From: teodor Date: Tue, 12 May 2009 14:11:01 +0000 Subject: [PATCH] Fix 8.4 support of GIN (basically, multicolumn indexes) --- README.gevel | 3 +++ gevel.c | 67 ++++++++++++++++++++++++++++++++++++++-------------- gevel.sql.in | 6 +++++ 3 files changed, 58 insertions(+), 18 deletions(-) diff --git a/README.gevel b/README.gevel index 21230c1..4d7c2a5 100644 --- a/README.gevel +++ b/README.gevel @@ -124,6 +124,9 @@ regression=# select gist_tree('pix'); (29 rows) * gin_stat(INDEXNAME) prints estimated counts for each indexed values + Note: since 8.4 gin_stat function has gin_stat(INDEXNAME, COLNUMBER) + prototype, single-argument function will return result for a first + column of index # SELECT * FROM gin_stat('gin_idx') as t(value int, nrow int) where nrow > 250; value | nrow diff --git a/gevel.c b/gevel.c index d9d8397..16e18d3 100644 --- a/gevel.c +++ b/gevel.c @@ -489,6 +489,7 @@ gist_print(PG_FUNCTION_ARGS) { typedef struct GinStatState { Relation index; GinState ginstate; + OffsetNumber attnum; Buffer buffer; OffsetNumber offset; @@ -553,7 +554,9 @@ refindPosition(GinStatState *st) for(;;) { int cmp; +#if PG_VERSION_NUM < 80400 bool isnull; +#endif Datum datum; IndexTuple itup; @@ -561,16 +564,25 @@ refindPosition(GinStatState *st) return false; itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, st->offset)); +#if PG_VERSION_NUM >= 80400 + datum = gin_index_getattr(&st->ginstate, itup); + + cmp = compareAttEntries(&st->ginstate, + st->attnum + 1, st->curval, + gintuple_get_attrnum(&st->ginstate, itup), datum); +#else datum = index_getattr(itup, FirstOffsetNumber, st->ginstate.tupdesc, &isnull); + cmp = DatumGetInt32( FunctionCall2( &st->ginstate.compareFn, st->curval, datum )); +#endif if ( cmp == 0 ) { - if ( !st->ginstate.tupdesc->attrs[0]->attbyval ) + if ( !st->index->rd_att->attrs[st->attnum]->attbyval ) pfree( (void*) st->curval ); return true; } @@ -582,7 +594,7 @@ refindPosition(GinStatState *st) } static void -gin_setup_firstcall(FuncCallContext *funcctx, text *name) { +gin_setup_firstcall(FuncCallContext *funcctx, text *name, int attnum) { MemoryContext oldcontext; GinStatState *st; char *relname=t2c(name); @@ -596,13 +608,21 @@ gin_setup_firstcall(FuncCallContext *funcctx, text *name) { makeRangeVarFromNameList(stringToQualifiedNameList(relname, "gin_stat"))); initGinState( &st->ginstate, st->index ); +#if PG_VERSION_NUM >= 80400 + if (attnum < 0 || attnum >= st->index->rd_att->natts) + elog(ERROR,"Wrong column's number"); + st->attnum = attnum; +#else + st->attnum = 0; +#endif + funcctx->user_fctx = (void*)st; tupdesc = CreateTemplateTupleDesc(2, false); TupleDescInitEntry(tupdesc, 1, "value", - st->index->rd_att->attrs[0]->atttypid, - st->index->rd_att->attrs[0]->atttypmod, - st->index->rd_att->attrs[0]->attndims); + st->index->rd_att->attrs[st->attnum]->atttypid, + st->index->rd_att->attrs[st->attnum]->atttypmod, + st->index->rd_att->attrs[st->attnum]->attndims); TupleDescInitEntry(tupdesc, 2, "nrow", INT4OID, -1, 0); memset( st->nulls, ' ', 2*sizeof(char) ); @@ -620,15 +640,19 @@ gin_setup_firstcall(FuncCallContext *funcctx, text *name) { static void processTuple( FuncCallContext *funcctx, GinStatState *st, IndexTuple itup ) { MemoryContext oldcontext; - Datum datum; +#if PG_VERSION_NUM < 80400 bool isnull; +#endif - datum = index_getattr(itup, FirstOffsetNumber, st->ginstate.tupdesc, &isnull); oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); st->curval = datumCopy( +#if PG_VERSION_NUM >= 80400 + gin_index_getattr(&st->ginstate, itup), +#else index_getattr(itup, FirstOffsetNumber, st->ginstate.tupdesc, &isnull), - st->ginstate.tupdesc->attrs[0]->attbyval, - st->ginstate.tupdesc->attrs[0]->attlen ); +#endif + st->index->rd_att->attrs[st->attnum]->attbyval, + st->index->rd_att->attrs[st->attnum]->attlen ); MemoryContextSwitchTo(oldcontext); st->dvalues[0] = st->curval; @@ -669,7 +693,7 @@ gin_stat(PG_FUNCTION_ARGS) { if (SRF_IS_FIRSTCALL()) { text *name=PG_GETARG_TEXT_P(0); funcctx = SRF_FIRSTCALL_INIT(); - gin_setup_firstcall(funcctx, name); + gin_setup_firstcall(funcctx, name, (PG_NARGS()==2) ? PG_GETARG_INT32(1) : 0 ); PG_FREE_IF_COPY(name,0); } @@ -683,17 +707,24 @@ gin_stat(PG_FUNCTION_ARGS) { SRF_RETURN_DONE(funcctx); } - st->offset++; + for(;;) { + st->offset++; - if (moveRightIfItNeeded(st)==false) { - UnlockReleaseBuffer( st->buffer ); - gin_index_close(st->index); + if (moveRightIfItNeeded(st)==false) { + UnlockReleaseBuffer( st->buffer ); + gin_index_close(st->index); - SRF_RETURN_DONE(funcctx); - } + SRF_RETURN_DONE(funcctx); + } + + page = BufferGetPage(st->buffer); + ituple = (IndexTuple) PageGetItem(page, PageGetItemId(page, st->offset)); - page = BufferGetPage(st->buffer); - ituple = (IndexTuple) PageGetItem(page, PageGetItemId(page, st->offset)); +#if PG_VERSION_NUM >= 80400 + if (st->attnum + 1 == gintuple_get_attrnum(&st->ginstate, ituple)) +#endif + break; + } processTuple( funcctx, st, ituple ); diff --git a/gevel.sql.in b/gevel.sql.in index 5294f81..4a71188 100644 --- a/gevel.sql.in +++ b/gevel.sql.in @@ -31,6 +31,12 @@ create or replace function gin_stat(text) language 'C' with (isstrict); +create or replace function gin_stat(text, int) + returns setof record + as 'MODULE_PATHNAME' + language 'C' + with (isstrict); + create or replace function gin_count_estimate(text, tsquery) returns bigint as 'MODULE_PATHNAME' -- 2.37.3