summaryrefslogtreecommitdiff
path: root/src/backend/access/gin
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2009-03-25 22:19:02 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2009-03-25 22:19:02 +0000
commit87b8db37740bb044cb3b6a6439e656217869fd57 (patch)
treec59eb0167c37ed34b9b24e718b2357bec48dcce1 /src/backend/access/gin
parent050a78dd3da8d3711197bda429ed7733bbf1b291 (diff)
Adjust the APIs for GIN opclass support functions to allow the extractQuery()
method to pass extra data to the consistent() and comparePartial() methods. This is the core infrastructure needed to support the soon-to-appear contrib/btree_gin module. The APIs are still upward compatible with the definitions used in 8.3 and before, although *not* with the previous 8.4devel function definitions. catversion bump for changes in pg_proc entries (although these are just cosmetic, since GIN doesn't actually look at the function signature before calling it...) Teodor Sigaev and Oleg Bartunov
Diffstat (limited to 'src/backend/access/gin')
-rw-r--r--src/backend/access/gin/ginarrayproc.c6
-rw-r--r--src/backend/access/gin/ginget.c52
-rw-r--r--src/backend/access/gin/ginscan.c66
3 files changed, 75 insertions, 49 deletions
diff --git a/src/backend/access/gin/ginarrayproc.c b/src/backend/access/gin/ginarrayproc.c
index 3b2e43318f8..717caaad8b5 100644
--- a/src/backend/access/gin/ginarrayproc.c
+++ b/src/backend/access/gin/ginarrayproc.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/gin/ginarrayproc.c,v 1.14 2009/01/01 17:23:34 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/gin/ginarrayproc.c,v 1.15 2009/03/25 22:19:01 tgl Exp $
*-------------------------------------------------------------------------
*/
#include "postgres.h"
@@ -95,7 +95,9 @@ ginarrayconsistent(PG_FUNCTION_ARGS)
bool *check = (bool *) PG_GETARG_POINTER(0);
StrategyNumber strategy = PG_GETARG_UINT16(1);
ArrayType *query = PG_GETARG_ARRAYTYPE_P(2);
- bool *recheck = (bool *) PG_GETARG_POINTER(3);
+ /* int32 nkeys = PG_GETARG_INT32(3); */
+ /* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
+ bool *recheck = (bool *) PG_GETARG_POINTER(5);
bool res;
int i,
nentries;
diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c
index 7f9f1236605..55ed9f335ae 100644
--- a/src/backend/access/gin/ginget.c
+++ b/src/backend/access/gin/ginget.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/gin/ginget.c,v 1.23 2009/03/24 20:17:10 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/gin/ginget.c,v 1.24 2009/03/25 22:19:01 tgl Exp $
*-------------------------------------------------------------------------
*/
@@ -178,10 +178,11 @@ computePartialMatchList( GinBtreeData *btree, GinBtreeStack *stack, GinScanEntry
* case cmp < 0 => not match and continue scan
*----------
*/
- cmp = DatumGetInt32(FunctionCall3(&btree->ginstate->comparePartialFn[scanEntry->attnum-1],
+ cmp = DatumGetInt32(FunctionCall4(&btree->ginstate->comparePartialFn[scanEntry->attnum-1],
scanEntry->entry,
idatum,
- UInt16GetDatum(scanEntry->strategy)));
+ UInt16GetDatum(scanEntry->strategy),
+ PointerGetDatum(scanEntry->extra_data)));
if ( cmp > 0 )
return true;
@@ -695,16 +696,18 @@ keyGetItem(Relation index, GinState *ginstate, MemoryContext tempCtx,
/*
* If one of the entry's scans returns lossy result, return it without
- * checking - we can't suggest anything helpful to consistentFn.
+ * further checking - we can't call consistentFn for lack of data.
*/
if (ItemPointerIsLossyPage(&key->curItem))
return FALSE;
oldCtx = MemoryContextSwitchTo(tempCtx);
- res = DatumGetBool(FunctionCall4(&ginstate->consistentFn[key->attnum-1],
+ res = DatumGetBool(FunctionCall6(&ginstate->consistentFn[key->attnum-1],
PointerGetDatum(key->entryRes),
UInt16GetDatum(key->strategy),
key->query,
+ UInt32GetDatum(key->nentries),
+ PointerGetDatum(key->extra_data),
PointerGetDatum(keyrecheck)));
MemoryContextSwitchTo(oldCtx);
MemoryContextReset(tempCtx);
@@ -796,10 +799,11 @@ matchPartialInPendingList(GinState *ginstate, Page page,
OffsetNumber off, OffsetNumber maxoff,
Datum value, OffsetNumber attrnum,
Datum *datum, bool *datumExtracted,
- StrategyNumber strategy)
+ StrategyNumber strategy,
+ Pointer extra_data)
{
IndexTuple itup;
- int res;
+ int32 cmp;
while ( off < maxoff )
{
@@ -813,13 +817,14 @@ matchPartialInPendingList(GinState *ginstate, Page page,
datumExtracted[ off-1 ] = true;
}
- res = DatumGetInt32(FunctionCall3(&ginstate->comparePartialFn[attrnum],
- value,
- datum[ off-1 ],
- UInt16GetDatum(strategy)));
- if ( res == 0 )
+ cmp = DatumGetInt32(FunctionCall4(&ginstate->comparePartialFn[attrnum],
+ value,
+ datum[off-1],
+ UInt16GetDatum(strategy),
+ PointerGetDatum(extra_data)));
+ if (cmp == 0)
return true;
- else if (res>0)
+ else if (cmp > 0)
return false;
}
@@ -912,7 +917,8 @@ collectDatumForItem(IndexScanDesc scan, pendingPosition *pos)
entry->attnum,
datum,
datumExtracted,
- entry->strategy);
+ entry->strategy,
+ entry->extra_data);
else
key->entryRes[j] = true;
break;
@@ -933,7 +939,8 @@ collectDatumForItem(IndexScanDesc scan, pendingPosition *pos)
entry->attnum,
datum,
datumExtracted,
- entry->strategy);
+ entry->strategy,
+ entry->extra_data);
hasMatch |= key->entryRes[j];
}
@@ -1015,19 +1022,22 @@ scanPendingInsert(IndexScanDesc scan, TIDBitmap *tbm, int64 *ntids)
recheck = false;
match = true;
- for (i = 0; match && i < so->nkeys; i++)
+ for (i = 0; i < so->nkeys; i++)
{
GinScanKey key = so->keys + i;
keyrecheck = true;
- if ( DatumGetBool(FunctionCall4(&so->ginstate.consistentFn[ key->attnum-1 ],
- PointerGetDatum(key->entryRes),
- UInt16GetDatum(key->strategy),
- key->query,
- PointerGetDatum(&keyrecheck))) == false )
+ if (!DatumGetBool(FunctionCall6(&so->ginstate.consistentFn[key->attnum-1],
+ PointerGetDatum(key->entryRes),
+ UInt16GetDatum(key->strategy),
+ key->query,
+ UInt32GetDatum(key->nentries),
+ PointerGetDatum(key->extra_data),
+ PointerGetDatum(&keyrecheck))))
{
match = false;
+ break;
}
recheck |= keyrecheck;
diff --git a/src/backend/access/gin/ginscan.c b/src/backend/access/gin/ginscan.c
index ba377419222..486adb6d7e8 100644
--- a/src/backend/access/gin/ginscan.c
+++ b/src/backend/access/gin/ginscan.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/gin/ginscan.c,v 1.21 2009/01/10 21:08:36 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/gin/ginscan.c,v 1.22 2009/03/25 22:19:01 tgl Exp $
*-------------------------------------------------------------------------
*/
@@ -38,7 +38,7 @@ ginbeginscan(PG_FUNCTION_ARGS)
static void
fillScanKey(GinState *ginstate, GinScanKey key, OffsetNumber attnum, Datum query,
Datum *entryValues, bool *partial_matches, uint32 nEntryValues,
- StrategyNumber strategy)
+ StrategyNumber strategy, Pointer *extra_data)
{
uint32 i,
j;
@@ -48,6 +48,7 @@ fillScanKey(GinState *ginstate, GinScanKey key, OffsetNumber attnum, Datum query
key->scanEntry = (GinScanEntry) palloc(sizeof(GinScanEntryData) * nEntryValues);
key->strategy = strategy;
key->attnum = attnum;
+ key->extra_data = extra_data;
key->query = query;
key->firstCall = TRUE;
ItemPointerSet(&(key->curItem), InvalidBlockNumber, InvalidOffsetNumber);
@@ -57,6 +58,7 @@ fillScanKey(GinState *ginstate, GinScanKey key, OffsetNumber attnum, Datum query
key->scanEntry[i].pval = key->entryRes + i;
key->scanEntry[i].entry = entryValues[i];
key->scanEntry[i].attnum = attnum;
+ key->scanEntry[i].extra_data = (extra_data) ? extra_data[i] : NULL;
ItemPointerSet(&(key->scanEntry[i].curItem), InvalidBlockNumber, InvalidOffsetNumber);
key->scanEntry[i].offset = InvalidOffsetNumber;
key->scanEntry[i].buffer = InvalidBuffer;
@@ -156,60 +158,72 @@ newScanKey(IndexScanDesc scan)
int i;
uint32 nkeys = 0;
- so->keys = (GinScanKey) palloc(scan->numberOfKeys * sizeof(GinScanKeyData));
-
if (scan->numberOfKeys < 1)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("GIN indexes do not support whole-index scans")));
+ so->keys = (GinScanKey) palloc(scan->numberOfKeys * sizeof(GinScanKeyData));
+
so->isVoidRes = false;
for (i = 0; i < scan->numberOfKeys; i++)
{
+ ScanKey skey = &scankey[i];
Datum *entryValues;
- int32 nEntryValues;
+ int32 nEntryValues = 0;
bool *partial_matches = NULL;
+ Pointer *extra_data = NULL;
/* XXX can't we treat nulls by just setting isVoidRes? */
/* This would amount to assuming that all GIN operators are strict */
- if (scankey[i].sk_flags & SK_ISNULL)
- elog(ERROR, "GIN doesn't support NULL as scan key");
-
- entryValues = (Datum *) DatumGetPointer(FunctionCall4(
- &so->ginstate.extractQueryFn[scankey[i].sk_attno - 1],
- scankey[i].sk_argument,
- PointerGetDatum(&nEntryValues),
- UInt16GetDatum(scankey[i].sk_strategy),
- PointerGetDatum(&partial_matches)));
+ if (skey->sk_flags & SK_ISNULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("GIN indexes do not support NULL scan keys")));
+
+ entryValues = (Datum *)
+ DatumGetPointer(FunctionCall5(&so->ginstate.extractQueryFn[skey->sk_attno - 1],
+ skey->sk_argument,
+ PointerGetDatum(&nEntryValues),
+ UInt16GetDatum(skey->sk_strategy),
+ PointerGetDatum(&partial_matches),
+ PointerGetDatum(&extra_data)));
+
if (nEntryValues < 0)
{
/*
- * extractQueryFn signals that nothing will be found, so we can
- * just set isVoidRes flag...
+ * extractQueryFn signals that nothing can match, so we can
+ * just set isVoidRes flag. No need to examine any more keys.
*/
so->isVoidRes = true;
break;
}
- /*
- * extractQueryFn signals that everything matches
- */
if (entryValues == NULL || nEntryValues == 0)
- /* full scan... */
+ {
+ /*
+ * extractQueryFn signals that everything matches. This would
+ * require a full scan, which we can't do, but perhaps there
+ * is another scankey that provides a restriction to use. So
+ * we keep going and check only at the end.
+ */
continue;
+ }
- fillScanKey(&so->ginstate, &(so->keys[nkeys]), scankey[i].sk_attno, scankey[i].sk_argument,
- entryValues, partial_matches, nEntryValues, scankey[i].sk_strategy);
+ fillScanKey(&so->ginstate, &(so->keys[nkeys]),
+ skey->sk_attno, skey->sk_argument,
+ entryValues, partial_matches, nEntryValues,
+ skey->sk_strategy, extra_data);
nkeys++;
}
- so->nkeys = nkeys;
-
- if (so->nkeys == 0 && !so->isVoidRes)
+ if (nkeys == 0 && !so->isVoidRes)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("GIN index does not support search with void query")));
+ errmsg("GIN indexes do not support whole-index scans")));
+
+ so->nkeys = nkeys;
pgstat_count_index_scan(scan->indexRelation);
}