*** pgsql/src/backend/access/gin/ginscan.c 2009/01/10 21:08:36 1.21 --- pgsql/src/backend/access/gin/ginscan.c 2009/03/25 22:19:01 1.22 *************** *** 8,14 **** * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION ! * $PostgreSQL: pgsql/src/backend/access/gin/ginscan.c,v 1.20 2009/01/01 17:23:34 momjian Exp $ *------------------------------------------------------------------------- */ --- 8,14 ---- * 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 $ *------------------------------------------------------------------------- */ *************** ginbeginscan(PG_FUNCTION_ARGS) *** 38,44 **** static void fillScanKey(GinState *ginstate, GinScanKey key, OffsetNumber attnum, Datum query, Datum *entryValues, bool *partial_matches, uint32 nEntryValues, ! StrategyNumber strategy) { uint32 i, j; --- 38,44 ---- static void fillScanKey(GinState *ginstate, GinScanKey key, OffsetNumber attnum, Datum query, Datum *entryValues, bool *partial_matches, uint32 nEntryValues, ! StrategyNumber strategy, Pointer *extra_data) { uint32 i, j; *************** fillScanKey(GinState *ginstate, GinScanK *** 48,53 **** --- 48,54 ---- 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); *************** fillScanKey(GinState *ginstate, GinScanK *** 57,62 **** --- 58,64 ---- 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; *************** newScanKey(IndexScanDesc scan) *** 156,215 **** 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->isVoidRes = false; for (i = 0; i < scan->numberOfKeys; i++) { Datum *entryValues; ! int32 nEntryValues; bool *partial_matches = 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 (nEntryValues < 0) { /* ! * extractQueryFn signals that nothing will be found, so we can ! * just set isVoidRes flag... */ so->isVoidRes = true; break; } - /* - * extractQueryFn signals that everything matches - */ if (entryValues == NULL || nEntryValues == 0) ! /* full scan... */ continue; ! fillScanKey(&so->ginstate, &(so->keys[nkeys]), scankey[i].sk_attno, scankey[i].sk_argument, ! entryValues, partial_matches, nEntryValues, scankey[i].sk_strategy); nkeys++; } ! so->nkeys = nkeys; ! ! if (so->nkeys == 0 && !so->isVoidRes) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ! errmsg("GIN index does not support search with void query"))); pgstat_count_index_scan(scan->indexRelation); } --- 158,229 ---- int i; uint32 nkeys = 0; 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 = 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 (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 can match, so we can ! * just set isVoidRes flag. No need to examine any more keys. */ so->isVoidRes = true; break; } if (entryValues == NULL || nEntryValues == 0) ! { ! /* ! * 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]), ! skey->sk_attno, skey->sk_argument, ! entryValues, partial_matches, nEntryValues, ! skey->sk_strategy, extra_data); nkeys++; } ! if (nkeys == 0 && !so->isVoidRes) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), ! errmsg("GIN indexes do not support whole-index scans"))); ! ! so->nkeys = nkeys; pgstat_count_index_scan(scan->indexRelation); }