diff options
Diffstat (limited to 'src/backend/access')
-rw-r--r-- | src/backend/access/gin/ginarrayproc.c | 6 | ||||
-rw-r--r-- | src/backend/access/gin/ginget.c | 52 | ||||
-rw-r--r-- | src/backend/access/gin/ginscan.c | 66 |
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); } |