if (sa->isNull)
{ if (!sb->isNull) return -1;
} elseif (sb->isNull)
{ return1;
} else
{ /* Order according to distance comparison */ for (i = 0; i < so->numberOfNonNullOrderBys; i++)
{ if (isnan(sa->distances[i]) && isnan(sb->distances[i])) continue; /* NaN == NaN */ if (isnan(sa->distances[i])) return -1; /* NaN > number */ if (isnan(sb->distances[i])) return1; /* number < NaN */ if (sa->distances[i] != sb->distances[i]) return (sa->distances[i] < sb->distances[i]) ? 1 : -1;
}
}
/* Leaf items go before inner pages, to ensure a depth-first search */ if (sa->isLeaf && !sb->isLeaf) return1; if (!sa->isLeaf && sb->isLeaf) return -1;
return0;
}
staticvoid
spgFreeSearchItem(SpGistScanOpaque so, SpGistSearchItem *item)
{ /* value is of type attType if isLeaf, else of type attLeafType */ /* (no, that is not backwards; yes, it's confusing) */ if (!(item->isLeaf ? so->state.attType.attbyval :
so->state.attLeafType.attbyval) &&
DatumGetPointer(item->value) != NULL)
pfree(DatumGetPointer(item->value));
if (item->leafTuple)
pfree(item->leafTuple);
if (item->traversalValue)
pfree(item->traversalValue);
if (so->numberOfOrderBys <= 0)
so->numberOfNonNullOrderBys = 0; else
{ int j = 0;
/* *RemoveallNULLkeys,butremembertheiroffsetsintheoriginal *array.
*/ for (i = 0; i < scan->numberOfOrderBys; i++)
{
ScanKey skey = &so->orderByData[i];
if (skey->sk_flags & SK_ISNULL)
so->nonNullOrderByOffsets[i] = -1; else
{ if (i != j)
so->orderByData[j] = *skey;
so->nonNullOrderByOffsets[i] = j++;
}
}
so->numberOfNonNullOrderBys = j;
}
if (scan->numberOfKeys <= 0)
{ /* If no quals, whole-index scan is required */
so->searchNulls = true;
so->searchNonNulls = true;
so->numberOfKeys = 0; return;
}
/* Examine the given quals */
qual_ok = true;
haveIsNull = haveNotNull = false;
nkeys = 0; for (i = 0; i < scan->numberOfKeys; i++)
{
ScanKey skey = &scan->keyData[i];
if (skey->sk_flags & SK_SEARCHNULL)
haveIsNull = true; elseif (skey->sk_flags & SK_SEARCHNOTNULL)
haveNotNull = true; elseif (skey->sk_flags & SK_ISNULL)
{ /* ordinary qual with null argument - unsatisfiable */
qual_ok = false; break;
} else
{ /* ordinary qual, propagate into so->keyData */
so->keyData[nkeys++] = *skey; /* this effectively creates a not-null requirement */
haveNotNull = true;
}
}
/* IS NULL in combination with something else is unsatisfiable */ if (haveIsNull && haveNotNull)
qual_ok = false;
/* Allocate various arrays needed for order-by scans */ if (scan->numberOfOrderBys > 0)
{ /* This will be filled in spgrescan, but allocate the space here */
so->orderByTypes = (Oid *)
palloc(sizeof(Oid) * scan->numberOfOrderBys);
so->nonNullOrderByOffsets = (int *)
palloc(sizeof(int) * scan->numberOfOrderBys);
/* These arrays have constant contents, so we can fill them now */
so->zeroDistances = (double *)
palloc(sizeof(double) * scan->numberOfOrderBys);
so->infDistances = (double *)
palloc(sizeof(double) * scan->numberOfOrderBys);
for (i = 0; i < scan->numberOfOrderBys; i++)
{
so->zeroDistances[i] = 0.0;
so->infDistances[i] = get_float8_infinity();
}
/* Must copy value out of temp context */ /* (recall that reconstructed values are of type leafType) */
item->value = out->reconstructedValues
? datumCopy(out->reconstructedValues[i],
so->state.attLeafType.attbyval,
so->state.attLeafType.attlen)
: (Datum) 0;
staticvoid
spgInnerTest(SpGistScanOpaque so, SpGistSearchItem *item,
SpGistInnerTuple innerTuple, bool isnull)
{
MemoryContext oldCxt = MemoryContextSwitchTo(so->tempCxt);
spgInnerConsistentOut out; int nNodes = innerTuple->nNodes; int i;
memset(&out, 0, sizeof(out));
if (!isnull)
{
spgInnerConsistentIn in;
spgInitInnerConsistentIn(&in, so, item, innerTuple);
/* use user-defined inner consistent method */
FunctionCall2Coll(&so->innerConsistentFn,
so->indexCollation,
PointerGetDatum(&in),
PointerGetDatum(&out));
} else
{ /* force all children to be visited */
out.nNodes = nNodes;
out.nodeNumbers = (int *) palloc(sizeof(int) * nNodes); for (i = 0; i < nNodes; i++)
out.nodeNumbers[i] = i;
}
/* If allTheSame, they should all or none of them match */ if (innerTuple->allTheSame && out.nNodes != 0 && out.nNodes != nNodes)
elog(ERROR, "inconsistent inner_consistent results for allTheSame inner tuple");
innerItem = spgMakeInnerItem(so, item, node, &out, i, isnull,
distances);
spgAddSearchItemToQueue(so, innerItem);
}
}
MemoryContextSwitchTo(oldCxt);
}
/* Returns a next item in an (ordered) scan or null if the index is exhausted */ static SpGistSearchItem *
spgGetNextQueueItem(SpGistScanOpaque so)
{ if (pairingheap_is_empty(so->scanQueue)) return NULL; /* Done when both heaps are empty */
/* Return item; caller is responsible to pfree it */ return (SpGistSearchItem *) pairingheap_remove_first(so->scanQueue);
}
if (leafTuple->tupstate != SPGIST_LIVE)
{ if (!isroot) /* all tuples on root should be live */
{ if (leafTuple->tupstate == SPGIST_REDIRECT)
{ /* redirection tuple should be first in chain */
Assert(offset == ItemPointerGetOffsetNumber(&item->heapPtr)); /* transfer attention to redirect point */
item->heapPtr = ((SpGistDeadTuple) leafTuple)->pointer;
Assert(ItemPointerGetBlockNumber(&item->heapPtr) != SPGIST_METAPAGE_BLKNO); return SpGistRedirectOffsetNumber;
}
if (leafTuple->tupstate == SPGIST_DEAD)
{ /* dead tuple should be first in chain */
Assert(offset == ItemPointerGetOffsetNumber(&item->heapPtr)); /* No live entries on this page */
Assert(SGLT_GET_NEXTOFFSET(leafTuple) == InvalidOffsetNumber); return SpGistBreakOffsetNumber;
}
}
/* We should not arrive at a placeholder */
elog(ERROR, "unexpected SPGiST tuple state: %d", leafTuple->tupstate); return SpGistErrorOffsetNumber;
}
if (SpGistPageIsLeaf(page))
{ /* Page is a leaf - that is, all its tuples are heap items */
OffsetNumber max = PageGetMaxOffsetNumber(page);
if (SpGistBlockIsRoot(blkno))
{ /* When root is a leaf, examine all its tuples */ for (offset = FirstOffsetNumber; offset <= max; offset++)
(void) spgTestLeafTuple(so, item, page, offset,
isnull, true,
&reportedSome, storeRes);
} else
{ /* Normal case: just examine the chain we arrived at */ while (offset != InvalidOffsetNumber)
{
Assert(offset >= FirstOffsetNumber && offset <= max);
offset = spgTestLeafTuple(so, item, page, offset,
isnull, false,
&reportedSome, storeRes); if (offset == SpGistRedirectOffsetNumber) goto redirect;
}
}
} else/* page is inner */
{
SpGistInnerTuple innerTuple = (SpGistInnerTuple)
PageGetItem(page, PageGetItemId(page, offset));
if (innerTuple->tupstate != SPGIST_LIVE)
{ if (innerTuple->tupstate == SPGIST_REDIRECT)
{ /* transfer attention to redirect point */
item->heapPtr = ((SpGistDeadTuple) innerTuple)->pointer;
Assert(ItemPointerGetBlockNumber(&item->heapPtr) !=
SPGIST_METAPAGE_BLKNO); goto redirect;
}
elog(ERROR, "unexpected SPGiST tuple state: %d",
innerTuple->tupstate);
}
spgInnerTest(so, item, innerTuple, isnull);
}
}
/* done with this scan item */
spgFreeSearchItem(so, item); /* clear temp context before proceeding to the next one */
MemoryContextReset(so->tempCxt);
}
if (buffer != InvalidBuffer)
UnlockReleaseBuffer(buffer);
}
/* storeRes subroutine for getbitmap case */ staticvoid
storeBitmap(SpGistScanOpaque so, ItemPointer heapPtr,
Datum leafValue, bool isnull,
SpGistLeafTuple leafTuple, bool recheck, bool recheckDistances, double *distances)
{
Assert(!recheckDistances && !distances);
tbm_add_tuples(so->tbm, heapPtr, 1, recheck);
so->ntids++;
}
if (so->want_itup)
{ /* *Reconstructindexdata.Wehavetocopythedatumoutofthetemp *contextanyway,sowemayaswellcreatethetuplehere.
*/
Datum leafDatums[INDEX_MAX_KEYS]; bool leafIsnulls[INDEX_MAX_KEYS];
/* We only need to deform the old tuple if it has INCLUDE attributes */ if (so->state.leafTupDesc->natts > 1)
spgDeformLeafTuple(leafTuple, so->state.leafTupDesc,
leafDatums, leafIsnulls, isnull);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.