/* *Writeitupvectortopage,hasnocontroloffreespace.
*/ void
gistfillbuffer(Page page, IndexTuple *itup, int len, OffsetNumber off)
{ int i;
if (off == InvalidOffsetNumber)
off = (PageIsEmpty(page)) ? FirstOffsetNumber :
OffsetNumberNext(PageGetMaxOffsetNumber(page));
for (i = 0; i < len; i++)
{
Size sz = IndexTupleSize(itup[i]);
OffsetNumber l;
l = PageAddItem(page, (Item) itup[i], sz, off, false, false); if (l == InvalidOffsetNumber)
elog(ERROR, "failed to add item to GiST index page, item %d out of %d, size %d bytes",
i, len, (int) sz);
off++;
}
}
/* If this column was all NULLs, the union is NULL */ if (evec->n == 0)
{
attr[i] = (Datum) 0;
isnull[i] = true;
} else
{ if (evec->n == 1)
{ /* unionFn may expect at least two inputs */
evec->n = 2;
evec->vector[1] = evec->vector[0];
}
/* Make union and store in attr array */
attr[i] = FunctionCall2Coll(&giststate->unionFn[i],
giststate->supportCollation[i],
PointerGetDatum(evec),
PointerGetDatum(&attrsize));
isnull[i] = false;
}
}
}
/* *ReturnanIndexTuplecontainingtheresultofapplyingthe"union" *methodtothespecifiedIndexTuplevector.
*/
IndexTuple
gistunion(Relation r, IndexTuple *itvec, int len, GISTSTATE *giststate)
{
Datum attr[INDEX_MAX_KEYS]; bool isnull[INDEX_MAX_KEYS];
for (i = 0; i < IndexRelationGetNumberOfKeyAttributes(r); i++)
{
Datum datum;
datum = index_getattr(tuple, i + 1, giststate->leafTupdesc, &isnull[i]);
gistdentryinit(giststate, i, &attdata[i],
datum, r, p, o, false, isnull[i]);
}
}
for (i = 0; i < IndexRelationGetNumberOfKeyAttributes(r); i++)
{
gistMakeUnionKey(giststate, i,
oldentries + i, oldisnull[i],
addentries + i, addisnull[i],
attr + i, isnull + i);
if (neednew) /* we already need new key, so we can skip check */ continue;
if (isnull[i]) /* union of key may be NULL if and only if both keys are NULL */ continue;
if (!addisnull[i])
{ if (oldisnull[i] ||
!gistKeyIsEQ(giststate, i, oldentries[i].key, attr[i]))
neednew = true;
}
}
if (neednew)
{ /* need to update key */
newtup = gistFormTuple(giststate, r, attr, isnull, false);
newtup->t_tid = oldtup->t_tid;
}
for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
{
IndexTuple itup = (IndexTuple) PageGetItem(p, PageGetItemId(p, i)); bool zero_penalty; int j;
zero_penalty = true;
/* Loop over index attributes. */ for (j = 0; j < IndexRelationGetNumberOfKeyAttributes(r); j++)
{
Datum datum; float usize; bool IsNull;
/* Compute penalty for this column. */
datum = index_getattr(itup, j + 1, giststate->leafTupdesc,
&IsNull);
gistdentryinit(giststate, j, &entry, datum, r, p, i, false, IsNull);
usize = gistpenalty(giststate, j, &entry, IsNull,
&identry[j], isnull[j]); if (usize > 0)
zero_penalty = false;
/* we have new best, so reset keep-it decision */
keep_current_best = -1;
} elseif (best_penalty[j] == usize)
{ /* *Thecurrenttupleisexactlyasgoodforthiscolumnasthe *besttupleseensofar.Thenextiterationofthisloop *willcomparethenextcolumn.
*/
} else
{ /* *Thecurrenttupleisworseforthiscolumnthanthebest *tupleseensofar.Skiptheremainingcolumnsandmoveon *tothenexttuple,ifany.
*/
zero_penalty = false; /* so outer loop won't exit */ break;
}
}
/* *Ifweloopedpastthelastcolumn,anddidnotupdate"result", *thenthistupleisexactlyasgoodasthepriorbesttuple.
*/ if (j == IndexRelationGetNumberOfKeyAttributes(r) && result != i)
{ if (keep_current_best == -1)
{ /* we didn't make the random choice yet for this old best */
keep_current_best = pg_prng_bool(&pg_global_prng_state) ? 1 : 0;
} if (keep_current_best == 0)
{ /* we choose to use the new tuple */
result = i; /* choose again if there are even more exactly-as-good ones */
keep_current_best = -1;
}
}
/* *Ifwefindatuplewithzeropenaltyforallcolumns,andwe've *decidedwedon'twanttosearchforanothertuplewithequal *penalty,there'snoneedtoexamineremainingtuples;justbreak *outoftheloopandreturnit.
*/ if (zero_penalty)
{ if (keep_current_best == -1)
{ /* we didn't make the random choice yet for this old best */
keep_current_best = pg_prng_bool(&pg_global_prng_state) ? 1 : 0;
} if (keep_current_best == 1) break;
}
}
return result;
}
/* *initializeaGiSTentrywithadecompressedversionofkey
*/ void
gistdentryinit(GISTSTATE *giststate, int nkey, GISTENTRY *e,
Datum k, Relation r, Page pg, OffsetNumber o, bool l, bool isNull)
{ if (!isNull)
{
GISTENTRY *dep;
gistentryinit(*e, k, r, pg, o, l);
/* there may not be a decompress function in opclass */ if (!OidIsValid(giststate->decompressFn[nkey].fn_oid)) return;
dep = (GISTENTRY *)
DatumGetPointer(FunctionCall1Coll(&giststate->decompressFn[nkey],
giststate->supportCollation[nkey],
PointerGetDatum(e))); /* decompressFn may just return the given pointer */ if (dep != e)
gistentryinit(*e, dep->key, dep->rel, dep->page, dep->offset,
dep->leafkey);
} else
gistentryinit(*e, (Datum) 0, r, pg, o, l);
}
IndexTuple
gistFormTuple(GISTSTATE *giststate, Relation r, const Datum *attdata, constbool *isnull, bool isleaf)
{
Datum compatt[INDEX_MAX_KEYS];
IndexTuple res;
void
gistCompressValues(GISTSTATE *giststate, Relation r, const Datum *attdata, constbool *isnull, bool isleaf, Datum *compatt)
{ int i;
/* *Callthecompressmethodoneachattribute.
*/ for (i = 0; i < IndexRelationGetNumberOfKeyAttributes(r); i++)
{ if (isnull[i])
compatt[i] = (Datum) 0; else
{
GISTENTRY centry;
GISTENTRY *cep;
gistentryinit(centry, attdata[i], r, NULL, (OffsetNumber) 0,
isleaf); /* there may not be a compress function in opclass */ if (OidIsValid(giststate->compressFn[i].fn_oid))
cep = (GISTENTRY *)
DatumGetPointer(FunctionCall1Coll(&giststate->compressFn[i],
giststate->supportCollation[i],
PointerGetDatum(¢ry))); else
cep = ¢ry;
compatt[i] = cep->key;
}
}
if (isleaf)
{ /* *Emplaceeachincludedattributeifany.
*/ for (; i < r->rd_att->natts; i++)
{ if (isnull[i])
compatt[i] = (Datum) 0; else
compatt[i] = attdata[i];
}
}
}
/* *initializeaGiSTentrywithfetchedvalueinkeyfield
*/ static Datum
gistFetchAtt(GISTSTATE *giststate, int nkey, Datum k, Relation r)
{
GISTENTRY fentry;
GISTENTRY *fep;
switch (prop)
{ case AMPROP_DISTANCE_ORDERABLE:
procno = GIST_DISTANCE_PROC; break; case AMPROP_RETURNABLE:
procno = GIST_FETCH_PROC; break; default: returnfalse;
}
/* First we need to know the column's opclass. */
opclass = get_index_column_opclass(index_oid, attno); if (!OidIsValid(opclass))
{
*isnull = true; returntrue;
}
/* Now look up the opclass family and input datatype. */ if (!get_opclass_opfamily_and_input_type(opclass, &opfamily, &opcintype))
{
*isnull = true; returntrue;
}
/* And now we can check whether the function is provided. */
/* Shouldn't be called for WAL-logging relations */
Assert(!RelationNeedsWAL(rel));
/* No need for an actual record if we already have a distinct LSN */ if (!XLogRecPtrIsInvalid(lastlsn) && lastlsn == currlsn)
currlsn = gistXLogAssignLSN();
switch (cmptype)
{ case COMPARE_EQ:
PG_RETURN_UINT16(RTEqualStrategyNumber); case COMPARE_LT:
PG_RETURN_UINT16(RTLessStrategyNumber); case COMPARE_LE:
PG_RETURN_UINT16(RTLessEqualStrategyNumber); case COMPARE_GT:
PG_RETURN_UINT16(RTGreaterStrategyNumber); case COMPARE_GE:
PG_RETURN_UINT16(RTGreaterEqualStrategyNumber); case COMPARE_OVERLAP:
PG_RETURN_UINT16(RTOverlapStrategyNumber); case COMPARE_CONTAINED_BY:
PG_RETURN_UINT16(RTContainedByStrategyNumber); default:
PG_RETURN_UINT16(InvalidStrategy);
}
}
/* *Returnstheopclass'sprivatestratnumusedforthegivencomparetype. * *Callstheopclass'sGIST_TRANSLATE_CMPTYPE_PROCsupportfunction,ifany, *andreturnstheresult.ReturnsInvalidStrategyifthefunctionisnot *defined.
*/
StrategyNumber
gisttranslatecmptype(CompareType cmptype, Oid opfamily)
{
Oid funcid;
Datum result;
/* Check whether the function is provided. */
funcid = get_opfamily_proc(opfamily, ANYOID, ANYOID, GIST_TRANSLATE_CMPTYPE_PROC); if (!OidIsValid(funcid)) return InvalidStrategy;
/* Ask the translation function */
result = OidFunctionCall1Coll(funcid, InvalidOid, Int32GetDatum(cmptype)); return DatumGetUInt16(result);
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.47 Sekunden
(vorverarbeitet am 2026-08-08)
¤
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.