PostgreSQL Source Code git master
gistutil.c File Reference
#include "postgres.h"
#include <math.h>
#include "access/gist_private.h"
#include "access/htup_details.h"
#include "access/reloptions.h"
#include "common/pg_prng.h"
#include "storage/indexfsm.h"
#include "utils/float.h"
#include "utils/fmgrprotos.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
Include dependency graph for gistutil.c:

Go to the source code of this file.

Functions

void gistfillbuffer (Page page, IndexTuple *itup, int len, OffsetNumber off)
 
bool gistnospace (Page page, IndexTuple *itvec, int len, OffsetNumber todelete, Size freespace)
 
bool gistfitpage (IndexTuple *itvec, int len)
 
IndexTuplegistextractpage (Page page, int *len)
 
IndexTuplegistjoinvector (IndexTuple *itvec, int *len, IndexTuple *additvec, int addlen)
 
IndexTupleDatagistfillitupvec (IndexTuple *vec, int veclen, int *memlen)
 
void gistMakeUnionItVec (GISTSTATE *giststate, IndexTuple *itvec, int len, Datum *attr, bool *isnull)
 
IndexTuple gistunion (Relation r, IndexTuple *itvec, int len, GISTSTATE *giststate)
 
void gistMakeUnionKey (GISTSTATE *giststate, int attno, GISTENTRY *entry1, bool isnull1, GISTENTRY *entry2, bool isnull2, Datum *dst, bool *dstisnull)
 
bool gistKeyIsEQ (GISTSTATE *giststate, int attno, Datum a, Datum b)
 
void gistDeCompressAtt (GISTSTATE *giststate, Relation r, IndexTuple tuple, Page p, OffsetNumber o, GISTENTRY *attdata, bool *isnull)
 
IndexTuple gistgetadjusted (Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *giststate)
 
OffsetNumber gistchoose (Relation r, Page p, IndexTuple it, GISTSTATE *giststate)
 
void gistdentryinit (GISTSTATE *giststate, int nkey, GISTENTRY *e, Datum k, Relation r, Page pg, OffsetNumber o, bool l, bool isNull)
 
IndexTuple gistFormTuple (GISTSTATE *giststate, Relation r, const Datum *attdata, const bool *isnull, bool isleaf)
 
void gistCompressValues (GISTSTATE *giststate, Relation r, const Datum *attdata, const bool *isnull, bool isleaf, Datum *compatt)
 
static Datum gistFetchAtt (GISTSTATE *giststate, int nkey, Datum k, Relation r)
 
HeapTuple gistFetchTuple (GISTSTATE *giststate, Relation r, IndexTuple tuple)
 
float gistpenalty (GISTSTATE *giststate, int attno, GISTENTRY *orig, bool isNullOrig, GISTENTRY *add, bool isNullAdd)
 
void gistinitpage (Page page, uint32 f)
 
void GISTInitBuffer (Buffer b, uint32 f)
 
void gistcheckpage (Relation rel, Buffer buf)
 
Buffer gistNewBuffer (Relation r, Relation heaprel)
 
bool gistPageRecyclable (Page page)
 
byteagistoptions (Datum reloptions, bool validate)
 
bool gistproperty (Oid index_oid, int attno, IndexAMProperty prop, const char *propname, bool *res, bool *isnull)
 
XLogRecPtr gistGetFakeLSN (Relation rel)
 
Datum gist_stratnum_common (PG_FUNCTION_ARGS)
 
StrategyNumber gisttranslatecmptype (CompareType cmptype, Oid opfamily, Oid opcintype)
 

Function Documentation

◆ gist_stratnum_common()

Datum gist_stratnum_common ( PG_FUNCTION_ARGS  )

Definition at line 1065 of file gistutil.c.

1066{
1067 CompareType cmptype = PG_GETARG_INT32(0);
1068
1069 switch (cmptype)
1070 {
1071 case COMPARE_EQ:
1073 case COMPARE_LT:
1075 case COMPARE_LE:
1077 case COMPARE_GT:
1079 case COMPARE_GE:
1081 case COMPARE_OVERLAP:
1085 default:
1087 }
1088}
CompareType
Definition: cmptype.h:32
@ COMPARE_LE
Definition: cmptype.h:35
@ COMPARE_OVERLAP
Definition: cmptype.h:40
@ COMPARE_GT
Definition: cmptype.h:38
@ COMPARE_EQ
Definition: cmptype.h:36
@ COMPARE_CONTAINED_BY
Definition: cmptype.h:41
@ COMPARE_GE
Definition: cmptype.h:37
@ COMPARE_LT
Definition: cmptype.h:34
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_RETURN_UINT16(x)
Definition: fmgr.h:357
#define RTOverlapStrategyNumber
Definition: stratnum.h:53
#define RTEqualStrategyNumber
Definition: stratnum.h:68
#define InvalidStrategy
Definition: stratnum.h:24
#define RTLessEqualStrategyNumber
Definition: stratnum.h:71
#define RTGreaterEqualStrategyNumber
Definition: stratnum.h:73
#define RTGreaterStrategyNumber
Definition: stratnum.h:72
#define RTContainedByStrategyNumber
Definition: stratnum.h:58
#define RTLessStrategyNumber
Definition: stratnum.h:70

References COMPARE_CONTAINED_BY, COMPARE_EQ, COMPARE_GE, COMPARE_GT, COMPARE_LE, COMPARE_LT, COMPARE_OVERLAP, InvalidStrategy, PG_GETARG_INT32, PG_RETURN_UINT16, RTContainedByStrategyNumber, RTEqualStrategyNumber, RTGreaterEqualStrategyNumber, RTGreaterStrategyNumber, RTLessEqualStrategyNumber, RTLessStrategyNumber, and RTOverlapStrategyNumber.

◆ gistcheckpage()

void gistcheckpage ( Relation  rel,
Buffer  buf 
)

Definition at line 785 of file gistutil.c.

786{
787 Page page = BufferGetPage(buf);
788
789 /*
790 * ReadBuffer verifies that every newly-read page passes
791 * PageHeaderIsValid, which means it either contains a reasonably sane
792 * page header or is all-zero. We have to defend against the all-zero
793 * case, however.
794 */
795 if (PageIsNew(page))
797 (errcode(ERRCODE_INDEX_CORRUPTED),
798 errmsg("index \"%s\" contains unexpected zero page at block %u",
801 errhint("Please REINDEX it.")));
802
803 /*
804 * Additionally check that the special area looks sane.
805 */
806 if (PageGetSpecialSize(page) != MAXALIGN(sizeof(GISTPageOpaqueData)))
808 (errcode(ERRCODE_INDEX_CORRUPTED),
809 errmsg("index \"%s\" contains corrupted page at block %u",
812 errhint("Please REINDEX it.")));
813}
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:3724
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:396
static uint16 PageGetSpecialSize(const PageData *page)
Definition: bufpage.h:317
static bool PageIsNew(const PageData *page)
Definition: bufpage.h:234
PageData * Page
Definition: bufpage.h:82
#define MAXALIGN(LEN)
Definition: c.h:768
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
static char * buf
Definition: pg_test_fsync.c:72
#define RelationGetRelationName(relation)
Definition: rel.h:546

References buf, BufferGetBlockNumber(), BufferGetPage(), ereport, errcode(), errhint(), errmsg(), ERROR, MAXALIGN, PageGetSpecialSize(), PageIsNew(), and RelationGetRelationName.

Referenced by gistBufferingFindCorrectParent(), gistdoinsert(), gistFindCorrectParent(), gistFindPath(), gistkillitems(), gistNewBuffer(), gistScanPage(), gistvacuum_delete_empty_pages(), and pgstat_gist_page().

◆ gistchoose()

OffsetNumber gistchoose ( Relation  r,
Page  p,
IndexTuple  it,
GISTSTATE giststate 
)

Definition at line 374 of file gistutil.c.

376{
377 OffsetNumber result;
378 OffsetNumber maxoff;
380 float best_penalty[INDEX_MAX_KEYS];
381 GISTENTRY entry,
382 identry[INDEX_MAX_KEYS];
383 bool isnull[INDEX_MAX_KEYS];
384 int keep_current_best;
385
387
388 gistDeCompressAtt(giststate, r,
389 it, NULL, (OffsetNumber) 0,
390 identry, isnull);
391
392 /* we'll return FirstOffsetNumber if page is empty (shouldn't happen) */
393 result = FirstOffsetNumber;
394
395 /*
396 * The index may have multiple columns, and there's a penalty value for
397 * each column. The penalty associated with a column that appears earlier
398 * in the index definition is strictly more important than the penalty of
399 * a column that appears later in the index definition.
400 *
401 * best_penalty[j] is the best penalty we have seen so far for column j,
402 * or -1 when we haven't yet examined column j. Array entries to the
403 * right of the first -1 are undefined.
404 */
405 best_penalty[0] = -1;
406
407 /*
408 * If we find a tuple that's exactly as good as the currently best one, we
409 * could use either one. When inserting a lot of tuples with the same or
410 * similar keys, it's preferable to descend down the same path when
411 * possible, as that's more cache-friendly. On the other hand, if all
412 * inserts land on the same leaf page after a split, we're never going to
413 * insert anything to the other half of the split, and will end up using
414 * only 50% of the available space. Distributing the inserts evenly would
415 * lead to better space usage, but that hurts cache-locality during
416 * insertion. To get the best of both worlds, when we find a tuple that's
417 * exactly as good as the previous best, choose randomly whether to stick
418 * to the old best, or use the new one. Once we decide to stick to the
419 * old best, we keep sticking to it for any subsequent equally good tuples
420 * we might find. This favors tuples with low offsets, but still allows
421 * some inserts to go to other equally-good subtrees.
422 *
423 * keep_current_best is -1 if we haven't yet had to make a random choice
424 * whether to keep the current best tuple. If we have done so, and
425 * decided to keep it, keep_current_best is 1; if we've decided to
426 * replace, keep_current_best is 0. (This state will be reset to -1 as
427 * soon as we've made the replacement, but sometimes we make the choice in
428 * advance of actually finding a replacement best tuple.)
429 */
430 keep_current_best = -1;
431
432 /*
433 * Loop over tuples on page.
434 */
435 maxoff = PageGetMaxOffsetNumber(p);
436 Assert(maxoff >= FirstOffsetNumber);
437
438 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
439 {
441 bool zero_penalty;
442 int j;
443
444 zero_penalty = true;
445
446 /* Loop over index attributes. */
447 for (j = 0; j < IndexRelationGetNumberOfKeyAttributes(r); j++)
448 {
449 Datum datum;
450 float usize;
451 bool IsNull;
452
453 /* Compute penalty for this column. */
454 datum = index_getattr(itup, j + 1, giststate->leafTupdesc,
455 &IsNull);
456 gistdentryinit(giststate, j, &entry, datum, r, p, i,
457 false, IsNull);
458 usize = gistpenalty(giststate, j, &entry, IsNull,
459 &identry[j], isnull[j]);
460 if (usize > 0)
461 zero_penalty = false;
462
463 if (best_penalty[j] < 0 || usize < best_penalty[j])
464 {
465 /*
466 * New best penalty for column. Tentatively select this tuple
467 * as the target, and record the best penalty. Then reset the
468 * next column's penalty to "unknown" (and indirectly, the
469 * same for all the ones to its right). This will force us to
470 * adopt this tuple's penalty values as the best for all the
471 * remaining columns during subsequent loop iterations.
472 */
473 result = i;
474 best_penalty[j] = usize;
475
477 best_penalty[j + 1] = -1;
478
479 /* we have new best, so reset keep-it decision */
480 keep_current_best = -1;
481 }
482 else if (best_penalty[j] == usize)
483 {
484 /*
485 * The current tuple is exactly as good for this column as the
486 * best tuple seen so far. The next iteration of this loop
487 * will compare the next column.
488 */
489 }
490 else
491 {
492 /*
493 * The current tuple is worse for this column than the best
494 * tuple seen so far. Skip the remaining columns and move on
495 * to the next tuple, if any.
496 */
497 zero_penalty = false; /* so outer loop won't exit */
498 break;
499 }
500 }
501
502 /*
503 * If we looped past the last column, and did not update "result",
504 * then this tuple is exactly as good as the prior best tuple.
505 */
506 if (j == IndexRelationGetNumberOfKeyAttributes(r) && result != i)
507 {
508 if (keep_current_best == -1)
509 {
510 /* we didn't make the random choice yet for this old best */
511 keep_current_best = pg_prng_bool(&pg_global_prng_state) ? 1 : 0;
512 }
513 if (keep_current_best == 0)
514 {
515 /* we choose to use the new tuple */
516 result = i;
517 /* choose again if there are even more exactly-as-good ones */
518 keep_current_best = -1;
519 }
520 }
521
522 /*
523 * If we find a tuple with zero penalty for all columns, and we've
524 * decided we don't want to search for another tuple with equal
525 * penalty, there's no need to examine remaining tuples; just break
526 * out of the loop and return it.
527 */
528 if (zero_penalty)
529 {
530 if (keep_current_best == -1)
531 {
532 /* we didn't make the random choice yet for this old best */
533 keep_current_best = pg_prng_bool(&pg_global_prng_state) ? 1 : 0;
534 }
535 if (keep_current_best == 1)
536 break;
537 }
538 }
539
540 return result;
541}
static Item PageGetItem(const PageData *page, const ItemIdData *itemId)
Definition: bufpage.h:354
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
Definition: bufpage.h:244
static OffsetNumber PageGetMaxOffsetNumber(const PageData *page)
Definition: bufpage.h:372
#define Assert(condition)
Definition: c.h:815
#define GistPageIsLeaf(page)
Definition: gist.h:170
void gistDeCompressAtt(GISTSTATE *giststate, Relation r, IndexTuple tuple, Page p, OffsetNumber o, GISTENTRY *attdata, bool *isnull)
Definition: gistutil.c:296
void gistdentryinit(GISTSTATE *giststate, int nkey, GISTENTRY *e, Datum k, Relation r, Page pg, OffsetNumber o, bool l, bool isNull)
Definition: gistutil.c:547
float gistpenalty(GISTSTATE *giststate, int attno, GISTENTRY *orig, bool isNullOrig, GISTENTRY *add, bool isNullAdd)
Definition: gistutil.c:724
int j
Definition: isn.c:73
int i
Definition: isn.c:72
IndexTupleData * IndexTuple
Definition: itup.h:53
static Datum index_getattr(IndexTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: itup.h:131
#define OffsetNumberNext(offsetNumber)
Definition: off.h:52
uint16 OffsetNumber
Definition: off.h:24
#define FirstOffsetNumber
Definition: off.h:27
#define INDEX_MAX_KEYS
pg_prng_state pg_global_prng_state
Definition: pg_prng.c:34
bool pg_prng_bool(pg_prng_state *state)
Definition: pg_prng.c:313
uintptr_t Datum
Definition: postgres.h:69
#define IndexRelationGetNumberOfKeyAttributes(relation)
Definition: rel.h:531
TupleDesc leafTupdesc
Definition: gist_private.h:80

References Assert, FirstOffsetNumber, gistDeCompressAtt(), gistdentryinit(), GistPageIsLeaf, gistpenalty(), i, index_getattr(), INDEX_MAX_KEYS, IndexRelationGetNumberOfKeyAttributes, j, GISTSTATE::leafTupdesc, OffsetNumberNext, PageGetItem(), PageGetItemId(), PageGetMaxOffsetNumber(), pg_global_prng_state, and pg_prng_bool().

Referenced by gistdoinsert(), and gistProcessItup().

◆ gistCompressValues()

void gistCompressValues ( GISTSTATE giststate,
Relation  r,
const Datum attdata,
const bool *  isnull,
bool  isleaf,
Datum compatt 
)

Definition at line 596 of file gistutil.c.

598{
599 int i;
600
601 /*
602 * Call the compress method on each attribute.
603 */
604 for (i = 0; i < IndexRelationGetNumberOfKeyAttributes(r); i++)
605 {
606 if (isnull[i])
607 compatt[i] = (Datum) 0;
608 else
609 {
610 GISTENTRY centry;
611 GISTENTRY *cep;
612
613 gistentryinit(centry, attdata[i], r, NULL, (OffsetNumber) 0,
614 isleaf);
615 /* there may not be a compress function in opclass */
616 if (OidIsValid(giststate->compressFn[i].fn_oid))
617 cep = (GISTENTRY *)
619 giststate->supportCollation[i],
620 PointerGetDatum(&centry)));
621 else
622 cep = &centry;
623 compatt[i] = cep->key;
624 }
625 }
626
627 if (isleaf)
628 {
629 /*
630 * Emplace each included attribute if any.
631 */
632 for (; i < r->rd_att->natts; i++)
633 {
634 if (isnull[i])
635 compatt[i] = (Datum) 0;
636 else
637 compatt[i] = attdata[i];
638 }
639 }
640}
#define OidIsValid(objectId)
Definition: c.h:732
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
Definition: fmgr.c:1129
#define gistentryinit(e, k, r, pg, o, l)
Definition: gist.h:245
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:317
Oid fn_oid
Definition: fmgr.h:59
Datum key
Definition: gist.h:161
Oid supportCollation[INDEX_MAX_KEYS]
Definition: gist_private.h:97
FmgrInfo compressFn[INDEX_MAX_KEYS]
Definition: gist_private.h:88
TupleDesc rd_att
Definition: rel.h:112

References GISTSTATE::compressFn, DatumGetPointer(), FmgrInfo::fn_oid, FunctionCall1Coll(), gistentryinit, i, IndexRelationGetNumberOfKeyAttributes, GISTENTRY::key, TupleDescData::natts, OidIsValid, PointerGetDatum(), RelationData::rd_att, and GISTSTATE::supportCollation.

Referenced by gistFormTuple(), and gistSortedBuildCallback().

◆ gistDeCompressAtt()

void gistDeCompressAtt ( GISTSTATE giststate,
Relation  r,
IndexTuple  tuple,
Page  p,
OffsetNumber  o,
GISTENTRY attdata,
bool *  isnull 
)

Definition at line 296 of file gistutil.c.

298{
299 int i;
300
301 for (i = 0; i < IndexRelationGetNumberOfKeyAttributes(r); i++)
302 {
303 Datum datum;
304
305 datum = index_getattr(tuple, i + 1, giststate->leafTupdesc, &isnull[i]);
306 gistdentryinit(giststate, i, &attdata[i],
307 datum, r, p, o,
308 false, isnull[i]);
309 }
310}

References gistdentryinit(), i, index_getattr(), IndexRelationGetNumberOfKeyAttributes, and GISTSTATE::leafTupdesc.

Referenced by gistchoose(), gistgetadjusted(), gistRelocateBuildBuffersOnSplit(), and placeOne().

◆ gistdentryinit()

void gistdentryinit ( GISTSTATE giststate,
int  nkey,
GISTENTRY e,
Datum  k,
Relation  r,
Page  pg,
OffsetNumber  o,
bool  l,
bool  isNull 
)

Definition at line 547 of file gistutil.c.

550{
551 if (!isNull)
552 {
553 GISTENTRY *dep;
554
555 gistentryinit(*e, k, r, pg, o, l);
556
557 /* there may not be a decompress function in opclass */
558 if (!OidIsValid(giststate->decompressFn[nkey].fn_oid))
559 return;
560
561 dep = (GISTENTRY *)
563 giststate->supportCollation[nkey],
565 /* decompressFn may just return the given pointer */
566 if (dep != e)
567 gistentryinit(*e, dep->key, dep->rel, dep->page, dep->offset,
568 dep->leafkey);
569 }
570 else
571 gistentryinit(*e, (Datum) 0, r, pg, o, l);
572}
e
Definition: preproc-init.c:82
OffsetNumber offset
Definition: gist.h:164
Page page
Definition: gist.h:163
Relation rel
Definition: gist.h:162
bool leafkey
Definition: gist.h:165
FmgrInfo decompressFn[INDEX_MAX_KEYS]
Definition: gist_private.h:89

References DatumGetPointer(), GISTSTATE::decompressFn, FmgrInfo::fn_oid, FunctionCall1Coll(), gistentryinit, GISTENTRY::key, GISTENTRY::leafkey, GISTENTRY::offset, OidIsValid, GISTENTRY::page, PointerGetDatum(), GISTENTRY::rel, and GISTSTATE::supportCollation.

Referenced by gistchoose(), gistDeCompressAtt(), gistindex_keytest(), gistMakeUnionItVec(), and gistSplitByKey().

◆ gistextractpage()

IndexTuple * gistextractpage ( Page  page,
int *  len 
)

Definition at line 95 of file gistutil.c.

96{
98 maxoff;
99 IndexTuple *itvec;
100
101 maxoff = PageGetMaxOffsetNumber(page);
102 *len = maxoff;
103 itvec = palloc(sizeof(IndexTuple) * maxoff);
104 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
105 itvec[i - FirstOffsetNumber] = (IndexTuple) PageGetItem(page, PageGetItemId(page, i));
106
107 return itvec;
108}
void * palloc(Size size)
Definition: mcxt.c:1317
const void size_t len

References FirstOffsetNumber, i, len, OffsetNumberNext, PageGetItem(), PageGetItemId(), PageGetMaxOffsetNumber(), and palloc().

Referenced by gist_indexsortbuild_levelstate_flush(), and gistplacetopage().

◆ gistFetchAtt()

static Datum gistFetchAtt ( GISTSTATE giststate,
int  nkey,
Datum  k,
Relation  r 
)
static

Definition at line 646 of file gistutil.c.

647{
648 GISTENTRY fentry;
649 GISTENTRY *fep;
650
651 gistentryinit(fentry, k, r, NULL, (OffsetNumber) 0, false);
652
653 fep = (GISTENTRY *)
654 DatumGetPointer(FunctionCall1Coll(&giststate->fetchFn[nkey],
655 giststate->supportCollation[nkey],
656 PointerGetDatum(&fentry)));
657
658 /* fetchFn set 'key', return it to the caller */
659 return fep->key;
660}
FmgrInfo fetchFn[INDEX_MAX_KEYS]
Definition: gist_private.h:94

References DatumGetPointer(), GISTSTATE::fetchFn, FunctionCall1Coll(), gistentryinit, GISTENTRY::key, PointerGetDatum(), and GISTSTATE::supportCollation.

Referenced by gistFetchTuple().

◆ gistFetchTuple()

HeapTuple gistFetchTuple ( GISTSTATE giststate,
Relation  r,
IndexTuple  tuple 
)

Definition at line 667 of file gistutil.c.

668{
669 MemoryContext oldcxt = MemoryContextSwitchTo(giststate->tempCxt);
671 bool isnull[INDEX_MAX_KEYS];
672 int i;
673
674 for (i = 0; i < IndexRelationGetNumberOfKeyAttributes(r); i++)
675 {
676 Datum datum;
677
678 datum = index_getattr(tuple, i + 1, giststate->leafTupdesc, &isnull[i]);
679
680 if (giststate->fetchFn[i].fn_oid != InvalidOid)
681 {
682 if (!isnull[i])
683 fetchatt[i] = gistFetchAtt(giststate, i, datum, r);
684 else
685 fetchatt[i] = (Datum) 0;
686 }
687 else if (giststate->compressFn[i].fn_oid == InvalidOid)
688 {
689 /*
690 * If opclass does not provide compress method that could change
691 * original value, att is necessarily stored in original form.
692 */
693 if (!isnull[i])
694 fetchatt[i] = datum;
695 else
696 fetchatt[i] = (Datum) 0;
697 }
698 else
699 {
700 /*
701 * Index-only scans not supported for this column. Since the
702 * planner chose an index-only scan anyway, it is not interested
703 * in this column, and we can replace it with a NULL.
704 */
705 isnull[i] = true;
706 fetchatt[i] = (Datum) 0;
707 }
708 }
709
710 /*
711 * Get each included attribute.
712 */
713 for (; i < r->rd_att->natts; i++)
714 {
715 fetchatt[i] = index_getattr(tuple, i + 1, giststate->leafTupdesc,
716 &isnull[i]);
717 }
718 MemoryContextSwitchTo(oldcxt);
719
720 return heap_form_tuple(giststate->fetchTupdesc, fetchatt, isnull);
721}
static Datum gistFetchAtt(GISTSTATE *giststate, int nkey, Datum k, Relation r)
Definition: gistutil.c:646
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1117
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
#define InvalidOid
Definition: postgres_ext.h:37
TupleDesc fetchTupdesc
Definition: gist_private.h:83
MemoryContext tempCxt
Definition: gist_private.h:78
#define fetchatt(A, T)
Definition: tupmacs.h:47

References GISTSTATE::compressFn, fetchatt, GISTSTATE::fetchFn, GISTSTATE::fetchTupdesc, FmgrInfo::fn_oid, gistFetchAtt(), heap_form_tuple(), i, index_getattr(), INDEX_MAX_KEYS, IndexRelationGetNumberOfKeyAttributes, InvalidOid, GISTSTATE::leafTupdesc, MemoryContextSwitchTo(), TupleDescData::natts, RelationData::rd_att, and GISTSTATE::tempCxt.

Referenced by gistScanPage().

◆ gistfillbuffer()

void gistfillbuffer ( Page  page,
IndexTuple itup,
int  len,
OffsetNumber  off 
)

Definition at line 34 of file gistutil.c.

35{
36 int i;
37
38 if (off == InvalidOffsetNumber)
39 off = (PageIsEmpty(page)) ? FirstOffsetNumber :
41
42 for (i = 0; i < len; i++)
43 {
44 Size sz = IndexTupleSize(itup[i]);
46
47 l = PageAddItem(page, (Item) itup[i], sz, off, false, false);
48 if (l == InvalidOffsetNumber)
49 elog(ERROR, "failed to add item to GiST index page, item %d out of %d, size %d bytes",
50 i, len, (int) sz);
51 off++;
52 }
53}
static bool PageIsEmpty(const PageData *page)
Definition: bufpage.h:224
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:471
size_t Size
Definition: c.h:562
#define elog(elevel,...)
Definition: elog.h:225
Pointer Item
Definition: item.h:17
static Size IndexTupleSize(const IndexTupleData *itup)
Definition: itup.h:71
#define InvalidOffsetNumber
Definition: off.h:26

References elog, ERROR, FirstOffsetNumber, i, IndexTupleSize(), InvalidOffsetNumber, len, OffsetNumberNext, PageAddItem, PageGetMaxOffsetNumber(), and PageIsEmpty().

Referenced by gist_indexsortbuild_levelstate_add(), gistplacetopage(), and gistRedoPageSplitRecord().

◆ gistfillitupvec()

IndexTupleData * gistfillitupvec ( IndexTuple vec,
int  veclen,
int *  memlen 
)

Definition at line 127 of file gistutil.c.

128{
129 char *ptr,
130 *ret;
131 int i;
132
133 *memlen = 0;
134
135 for (i = 0; i < veclen; i++)
136 *memlen += IndexTupleSize(vec[i]);
137
138 ptr = ret = palloc(*memlen);
139
140 for (i = 0; i < veclen; i++)
141 {
142 memcpy(ptr, vec[i], IndexTupleSize(vec[i]));
143 ptr += IndexTupleSize(vec[i]);
144 }
145
146 return (IndexTupleData *) ret;
147}

References i, IndexTupleSize(), and palloc().

Referenced by gist_indexsortbuild_levelstate_flush(), gistplacetopage(), and gistSplit().

◆ gistfitpage()

bool gistfitpage ( IndexTuple itvec,
int  len 
)

Definition at line 79 of file gistutil.c.

80{
81 int i;
82 Size size = 0;
83
84 for (i = 0; i < len; i++)
85 size += IndexTupleSize(itvec[i]) + sizeof(ItemIdData);
86
87 /* TODO: Consider fillfactor */
88 return (size <= GiSTPageSize);
89}
#define GiSTPageSize
Definition: gist_private.h:476
struct ItemIdData ItemIdData
static pg_noinline void Size size
Definition: slab.c:607

References GiSTPageSize, i, IndexTupleSize(), len, and size.

Referenced by gistSplit().

◆ gistFormTuple()

IndexTuple gistFormTuple ( GISTSTATE giststate,
Relation  r,
const Datum attdata,
const bool *  isnull,
bool  isleaf 
)

Definition at line 575 of file gistutil.c.

577{
578 Datum compatt[INDEX_MAX_KEYS];
580
581 gistCompressValues(giststate, r, attdata, isnull, isleaf, compatt);
582
583 res = index_form_tuple(isleaf ? giststate->leafTupdesc :
584 giststate->nonLeafTupdesc,
585 compatt, isnull);
586
587 /*
588 * The offset number on tuples on internal pages is unused. For historical
589 * reasons, it is set to 0xffff.
590 */
591 ItemPointerSetOffsetNumber(&(res->t_tid), 0xffff);
592 return res;
593}
void gistCompressValues(GISTSTATE *giststate, Relation r, const Datum *attdata, const bool *isnull, bool isleaf, Datum *compatt)
Definition: gistutil.c:596
IndexTuple index_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: indextuple.c:44
static void ItemPointerSetOffsetNumber(ItemPointerData *pointer, OffsetNumber offsetNumber)
Definition: itemptr.h:158
TupleDesc nonLeafTupdesc
Definition: gist_private.h:81

References gistCompressValues(), index_form_tuple(), INDEX_MAX_KEYS, ItemPointerSetOffsetNumber(), GISTSTATE::leafTupdesc, GISTSTATE::nonLeafTupdesc, and res.

Referenced by gistBuildCallback(), gistgetadjusted(), gistinsert(), gistSplit(), and gistunion().

◆ gistgetadjusted()

IndexTuple gistgetadjusted ( Relation  r,
IndexTuple  oldtup,
IndexTuple  addtup,
GISTSTATE giststate 
)

Definition at line 316 of file gistutil.c.

317{
318 bool neednew = false;
319 GISTENTRY oldentries[INDEX_MAX_KEYS],
320 addentries[INDEX_MAX_KEYS];
321 bool oldisnull[INDEX_MAX_KEYS],
322 addisnull[INDEX_MAX_KEYS];
323 Datum attr[INDEX_MAX_KEYS];
324 bool isnull[INDEX_MAX_KEYS];
325 IndexTuple newtup = NULL;
326 int i;
327
328 gistDeCompressAtt(giststate, r, oldtup, NULL,
329 (OffsetNumber) 0, oldentries, oldisnull);
330
331 gistDeCompressAtt(giststate, r, addtup, NULL,
332 (OffsetNumber) 0, addentries, addisnull);
333
334 for (i = 0; i < IndexRelationGetNumberOfKeyAttributes(r); i++)
335 {
336 gistMakeUnionKey(giststate, i,
337 oldentries + i, oldisnull[i],
338 addentries + i, addisnull[i],
339 attr + i, isnull + i);
340
341 if (neednew)
342 /* we already need new key, so we can skip check */
343 continue;
344
345 if (isnull[i])
346 /* union of key may be NULL if and only if both keys are NULL */
347 continue;
348
349 if (!addisnull[i])
350 {
351 if (oldisnull[i] ||
352 !gistKeyIsEQ(giststate, i, oldentries[i].key, attr[i]))
353 neednew = true;
354 }
355 }
356
357 if (neednew)
358 {
359 /* need to update key */
360 newtup = gistFormTuple(giststate, r, attr, isnull, false);
361 newtup->t_tid = oldtup->t_tid;
362 }
363
364 return newtup;
365}
void gistMakeUnionKey(GISTSTATE *giststate, int attno, GISTENTRY *entry1, bool isnull1, GISTENTRY *entry2, bool isnull2, Datum *dst, bool *dstisnull)
Definition: gistutil.c:233
bool gistKeyIsEQ(GISTSTATE *giststate, int attno, Datum a, Datum b)
Definition: gistutil.c:281
IndexTuple gistFormTuple(GISTSTATE *giststate, Relation r, const Datum *attdata, const bool *isnull, bool isleaf)
Definition: gistutil.c:575
ItemPointerData t_tid
Definition: itup.h:37

References gistDeCompressAtt(), gistFormTuple(), gistKeyIsEQ(), gistMakeUnionKey(), i, INDEX_MAX_KEYS, IndexRelationGetNumberOfKeyAttributes, sort-test::key, and IndexTupleData::t_tid.

Referenced by gistdoinsert(), gistformdownlink(), gistProcessItup(), and gistRelocateBuildBuffersOnSplit().

◆ gistGetFakeLSN()

XLogRecPtr gistGetFakeLSN ( Relation  rel)

Definition at line 1016 of file gistutil.c.

1017{
1018 if (rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
1019 {
1020 /*
1021 * Temporary relations are only accessible in our session, so a simple
1022 * backend-local counter will do.
1023 */
1024 static XLogRecPtr counter = FirstNormalUnloggedLSN;
1025
1026 return counter++;
1027 }
1028 else if (RelationIsPermanent(rel))
1029 {
1030 /*
1031 * WAL-logging on this relation will start after commit, so its LSNs
1032 * must be distinct numbers smaller than the LSN at the next commit.
1033 * Emit a dummy WAL record if insert-LSN hasn't advanced after the
1034 * last call.
1035 */
1036 static XLogRecPtr lastlsn = InvalidXLogRecPtr;
1037 XLogRecPtr currlsn = GetXLogInsertRecPtr();
1038
1039 /* Shouldn't be called for WAL-logging relations */
1040 Assert(!RelationNeedsWAL(rel));
1041
1042 /* No need for an actual record if we already have a distinct LSN */
1043 if (!XLogRecPtrIsInvalid(lastlsn) && lastlsn == currlsn)
1044 currlsn = gistXLogAssignLSN();
1045
1046 lastlsn = currlsn;
1047 return currlsn;
1048 }
1049 else
1050 {
1051 /*
1052 * Unlogged relations are accessible from other backends, and survive
1053 * (clean) restarts. GetFakeLSNForUnloggedRel() handles that for us.
1054 */
1055 Assert(rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED);
1056 return GetFakeLSNForUnloggedRel();
1057 }
1058}
XLogRecPtr gistXLogAssignLSN(void)
Definition: gistxlog.c:576
#define RelationNeedsWAL(relation)
Definition: rel.h:635
#define RelationIsPermanent(relation)
Definition: rel.h:624
Form_pg_class rd_rel
Definition: rel.h:111
XLogRecPtr GetXLogInsertRecPtr(void)
Definition: xlog.c:9459
XLogRecPtr GetFakeLSNForUnloggedRel(void)
Definition: xlog.c:4625
#define FirstNormalUnloggedLSN
Definition: xlogdefs.h:36
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28

References Assert, FirstNormalUnloggedLSN, GetFakeLSNForUnloggedRel(), GetXLogInsertRecPtr(), gistXLogAssignLSN(), InvalidXLogRecPtr, RelationData::rd_rel, RelationIsPermanent, RelationNeedsWAL, and XLogRecPtrIsInvalid.

Referenced by gistdeletepage(), gistplacetopage(), gistprunepage(), gistvacuumpage(), and gistvacuumscan().

◆ GISTInitBuffer()

void GISTInitBuffer ( Buffer  b,
uint32  f 
)

Definition at line 773 of file gistutil.c.

774{
775 Page page;
776
777 page = BufferGetPage(b);
778 gistinitpage(page, f);
779}
void gistinitpage(Page page, uint32 f)
Definition: gistutil.c:757
int b
Definition: isn.c:69

References b, BufferGetPage(), and gistinitpage().

Referenced by gistbuild(), gistbuildempty(), gistplacetopage(), and gistRedoPageSplitRecord().

◆ gistinitpage()

void gistinitpage ( Page  page,
uint32  f 
)

Definition at line 757 of file gistutil.c.

758{
759 GISTPageOpaque opaque;
760
761 PageInit(page, BLCKSZ, sizeof(GISTPageOpaqueData));
762
763 opaque = GistPageGetOpaque(page);
765 opaque->flags = f;
766 opaque->gist_page_id = GIST_PAGE_ID;
767}
#define InvalidBlockNumber
Definition: block.h:33
void PageInit(Page page, Size pageSize, Size specialSize)
Definition: bufpage.c:42
#define GIST_PAGE_ID
Definition: gist.h:112
#define GistPageGetOpaque(page)
Definition: gist.h:168
uint16 gist_page_id
Definition: gist.h:83
BlockNumber rightlink
Definition: gist.h:81
uint16 flags
Definition: gist.h:82

References GISTPageOpaqueData::flags, GISTPageOpaqueData::gist_page_id, GIST_PAGE_ID, GistPageGetOpaque, InvalidBlockNumber, PageInit(), and GISTPageOpaqueData::rightlink.

Referenced by gist_indexsortbuild(), gist_indexsortbuild_levelstate_add(), gist_indexsortbuild_levelstate_flush(), and GISTInitBuffer().

◆ gistjoinvector()

IndexTuple * gistjoinvector ( IndexTuple itvec,
int *  len,
IndexTuple additvec,
int  addlen 
)

Definition at line 114 of file gistutil.c.

115{
116 itvec = (IndexTuple *) repalloc(itvec, sizeof(IndexTuple) * ((*len) + addlen));
117 memmove(&itvec[*len], additvec, sizeof(IndexTuple) * addlen);
118 *len += addlen;
119 return itvec;
120}
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1541

References len, and repalloc().

Referenced by gist_indexsortbuild_levelstate_flush(), and gistplacetopage().

◆ gistKeyIsEQ()

bool gistKeyIsEQ ( GISTSTATE giststate,
int  attno,
Datum  a,
Datum  b 
)

Definition at line 281 of file gistutil.c.

282{
283 bool result = false; /* silence compiler warning */
284
285 FunctionCall3Coll(&giststate->equalFn[attno],
286 giststate->supportCollation[attno],
287 a, b,
288 PointerGetDatum(&result));
289 return result;
290}
Datum FunctionCall3Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3)
Definition: fmgr.c:1171
int a
Definition: isn.c:68
FmgrInfo equalFn[INDEX_MAX_KEYS]
Definition: gist_private.h:92

References a, b, GISTSTATE::equalFn, FunctionCall3Coll(), PointerGetDatum(), and GISTSTATE::supportCollation.

Referenced by gistgetadjusted(), and gistUserPicksplit().

◆ gistMakeUnionItVec()

void gistMakeUnionItVec ( GISTSTATE giststate,
IndexTuple itvec,
int  len,
Datum attr,
bool *  isnull 
)

Definition at line 155 of file gistutil.c.

157{
158 int i;
159 GistEntryVector *evec;
160 int attrsize;
161
162 evec = (GistEntryVector *) palloc((len + 2) * sizeof(GISTENTRY) + GEVHDRSZ);
163
164 for (i = 0; i < giststate->nonLeafTupdesc->natts; i++)
165 {
166 int j;
167
168 /* Collect non-null datums for this column */
169 evec->n = 0;
170 for (j = 0; j < len; j++)
171 {
172 Datum datum;
173 bool IsNull;
174
175 datum = index_getattr(itvec[j], i + 1, giststate->leafTupdesc,
176 &IsNull);
177 if (IsNull)
178 continue;
179
180 gistdentryinit(giststate, i,
181 evec->vector + evec->n,
182 datum,
183 NULL, NULL, (OffsetNumber) 0,
184 false, IsNull);
185 evec->n++;
186 }
187
188 /* If this column was all NULLs, the union is NULL */
189 if (evec->n == 0)
190 {
191 attr[i] = (Datum) 0;
192 isnull[i] = true;
193 }
194 else
195 {
196 if (evec->n == 1)
197 {
198 /* unionFn may expect at least two inputs */
199 evec->n = 2;
200 evec->vector[1] = evec->vector[0];
201 }
202
203 /* Make union and store in attr array */
204 attr[i] = FunctionCall2Coll(&giststate->unionFn[i],
205 giststate->supportCollation[i],
206 PointerGetDatum(evec),
207 PointerGetDatum(&attrsize));
208
209 isnull[i] = false;
210 }
211 }
212}
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1149
struct GISTENTRY GISTENTRY
#define GEVHDRSZ
Definition: gist.h:240
FmgrInfo unionFn[INDEX_MAX_KEYS]
Definition: gist_private.h:87
GISTENTRY vector[FLEXIBLE_ARRAY_MEMBER]
Definition: gist.h:237
int32 n
Definition: gist.h:236

References FunctionCall2Coll(), GEVHDRSZ, gistdentryinit(), i, index_getattr(), j, GISTSTATE::leafTupdesc, len, GistEntryVector::n, TupleDescData::natts, GISTSTATE::nonLeafTupdesc, palloc(), PointerGetDatum(), GISTSTATE::supportCollation, GISTSTATE::unionFn, and GistEntryVector::vector.

Referenced by gistunion(), and gistunionsubkeyvec().

◆ gistMakeUnionKey()

void gistMakeUnionKey ( GISTSTATE giststate,
int  attno,
GISTENTRY entry1,
bool  isnull1,
GISTENTRY entry2,
bool  isnull2,
Datum dst,
bool *  dstisnull 
)

Definition at line 233 of file gistutil.c.

237{
238 /* we need a GistEntryVector with room for exactly 2 elements */
239 union
240 {
241 GistEntryVector gev;
242 char padding[2 * sizeof(GISTENTRY) + GEVHDRSZ];
243 } storage;
244 GistEntryVector *evec = &storage.gev;
245 int dstsize;
246
247 evec->n = 2;
248
249 if (isnull1 && isnull2)
250 {
251 *dstisnull = true;
252 *dst = (Datum) 0;
253 }
254 else
255 {
256 if (isnull1 == false && isnull2 == false)
257 {
258 evec->vector[0] = *entry1;
259 evec->vector[1] = *entry2;
260 }
261 else if (isnull1 == false)
262 {
263 evec->vector[0] = *entry1;
264 evec->vector[1] = *entry1;
265 }
266 else
267 {
268 evec->vector[0] = *entry2;
269 evec->vector[1] = *entry2;
270 }
271
272 *dstisnull = false;
273 *dst = FunctionCall2Coll(&giststate->unionFn[attno],
274 giststate->supportCollation[attno],
275 PointerGetDatum(evec),
276 PointerGetDatum(&dstsize));
277 }
278}
#define storage
Definition: indent_codes.h:68

References FunctionCall2Coll(), GEVHDRSZ, GistEntryVector::n, PointerGetDatum(), storage, GISTSTATE::supportCollation, GISTSTATE::unionFn, and GistEntryVector::vector.

Referenced by gistgetadjusted(), and supportSecondarySplit().

◆ gistNewBuffer()

Buffer gistNewBuffer ( Relation  r,
Relation  heaprel 
)

Definition at line 824 of file gistutil.c.

825{
826 Buffer buffer;
827
828 /* First, try to get a page from FSM */
829 for (;;)
830 {
831 BlockNumber blkno = GetFreeIndexPage(r);
832
833 if (blkno == InvalidBlockNumber)
834 break; /* nothing left in FSM */
835
836 buffer = ReadBuffer(r, blkno);
837
838 /*
839 * We have to guard against the possibility that someone else already
840 * recycled this page; the buffer may be locked if so.
841 */
842 if (ConditionalLockBuffer(buffer))
843 {
844 Page page = BufferGetPage(buffer);
845
846 /*
847 * If the page was never initialized, it's OK to use.
848 */
849 if (PageIsNew(page))
850 return buffer;
851
852 gistcheckpage(r, buffer);
853
854 /*
855 * Otherwise, recycle it if deleted, and too old to have any
856 * processes interested in it.
857 */
858 if (gistPageRecyclable(page))
859 {
860 /*
861 * If we are generating WAL for Hot Standby then create a WAL
862 * record that will allow us to conflict with queries running
863 * on standby, in case they have snapshots older than the
864 * page's deleteXid.
865 */
867 gistXLogPageReuse(r, heaprel, blkno, GistPageGetDeleteXid(page));
868
869 return buffer;
870 }
871
872 LockBuffer(buffer, GIST_UNLOCK);
873 }
874
875 /* Can't use it, so release buffer and try again */
876 ReleaseBuffer(buffer);
877 }
878
879 /* Must extend the file */
880 buffer = ExtendBufferedRel(BMR_REL(r), MAIN_FORKNUM, NULL,
882
883 return buffer;
884}
uint32 BlockNumber
Definition: block.h:31
int Buffer
Definition: buf.h:23
Buffer ExtendBufferedRel(BufferManagerRelation bmr, ForkNumber forkNum, BufferAccessStrategy strategy, uint32 flags)
Definition: bufmgr.c:846
bool ConditionalLockBuffer(Buffer buffer)
Definition: bufmgr.c:5126
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:4866
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:5100
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:746
@ EB_LOCK_FIRST
Definition: bufmgr.h:86
#define BMR_REL(p_rel)
Definition: bufmgr.h:107
static FullTransactionId GistPageGetDeleteXid(Page page)
Definition: gist.h:216
#define GIST_UNLOCK
Definition: gist_private.h:44
bool gistPageRecyclable(Page page)
Definition: gistutil.c:888
void gistcheckpage(Relation rel, Buffer buf)
Definition: gistutil.c:785
void gistXLogPageReuse(Relation rel, Relation heaprel, BlockNumber blkno, FullTransactionId deleteXid)
Definition: gistxlog.c:594
BlockNumber GetFreeIndexPage(Relation rel)
Definition: indexfsm.c:38
@ MAIN_FORKNUM
Definition: relpath.h:58
#define XLogStandbyInfoActive()
Definition: xlog.h:123

References BMR_REL, BufferGetPage(), ConditionalLockBuffer(), EB_LOCK_FIRST, ExtendBufferedRel(), GetFreeIndexPage(), GIST_UNLOCK, gistcheckpage(), GistPageGetDeleteXid(), gistPageRecyclable(), gistXLogPageReuse(), InvalidBlockNumber, LockBuffer(), MAIN_FORKNUM, PageIsNew(), ReadBuffer(), RelationNeedsWAL, ReleaseBuffer(), and XLogStandbyInfoActive.

Referenced by gistbuild(), and gistplacetopage().

◆ gistnospace()

bool gistnospace ( Page  page,
IndexTuple itvec,
int  len,
OffsetNumber  todelete,
Size  freespace 
)

Definition at line 59 of file gistutil.c.

60{
61 unsigned int size = freespace,
62 deleted = 0;
63 int i;
64
65 for (i = 0; i < len; i++)
66 size += IndexTupleSize(itvec[i]) + sizeof(ItemIdData);
67
68 if (todelete != InvalidOffsetNumber)
69 {
70 IndexTuple itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, todelete));
71
72 deleted = IndexTupleSize(itup) + sizeof(ItemIdData);
73 }
74
75 return (PageGetFreeSpace(page) + deleted < size);
76}
Size PageGetFreeSpace(const PageData *page)
Definition: bufpage.c:896

References i, IndexTupleSize(), InvalidOffsetNumber, len, PageGetFreeSpace(), PageGetItem(), PageGetItemId(), and size.

Referenced by gistplacetopage().

◆ gistoptions()

bytea * gistoptions ( Datum  reloptions,
bool  validate 
)

Definition at line 912 of file gistutil.c.

913{
914 static const relopt_parse_elt tab[] = {
915 {"fillfactor", RELOPT_TYPE_INT, offsetof(GiSTOptions, fillfactor)},
916 {"buffering", RELOPT_TYPE_ENUM, offsetof(GiSTOptions, buffering_mode)}
917 };
918
919 return (bytea *) build_reloptions(reloptions, validate,
921 sizeof(GiSTOptions),
922 tab, lengthof(tab));
923}
#define lengthof(array)
Definition: c.h:745
static int fillfactor
Definition: pgbench.c:188
void * build_reloptions(Datum reloptions, bool validate, relopt_kind kind, Size relopt_struct_size, const relopt_parse_elt *relopt_elems, int num_relopt_elems)
Definition: reloptions.c:1931
@ RELOPT_KIND_GIST
Definition: reloptions.h:47
@ RELOPT_TYPE_ENUM
Definition: reloptions.h:34
@ RELOPT_TYPE_INT
Definition: reloptions.h:32
Definition: c.h:644

References build_reloptions(), fillfactor, lengthof, RELOPT_KIND_GIST, RELOPT_TYPE_ENUM, and RELOPT_TYPE_INT.

Referenced by gisthandler().

◆ gistPageRecyclable()

bool gistPageRecyclable ( Page  page)

Definition at line 888 of file gistutil.c.

889{
890 if (PageIsNew(page))
891 return true;
892 if (GistPageIsDeleted(page))
893 {
894 /*
895 * The page was deleted, but when? If it was just deleted, a scan
896 * might have seen the downlink to it, and will read the page later.
897 * As long as that can happen, we must keep the deleted page around as
898 * a tombstone.
899 *
900 * For that check if the deletion XID could still be visible to
901 * anyone. If not, then no scan that's still in progress could have
902 * seen its downlink, and we can recycle it.
903 */
904 FullTransactionId deletexid_full = GistPageGetDeleteXid(page);
905
906 return GlobalVisCheckRemovableFullXid(NULL, deletexid_full);
907 }
908 return false;
909}
#define GistPageIsDeleted(page)
Definition: gist.h:173
bool GlobalVisCheckRemovableFullXid(Relation rel, FullTransactionId fxid)
Definition: procarray.c:4286

References GistPageGetDeleteXid(), GistPageIsDeleted, GlobalVisCheckRemovableFullXid(), and PageIsNew().

Referenced by gistNewBuffer(), and gistvacuumpage().

◆ gistpenalty()

float gistpenalty ( GISTSTATE giststate,
int  attno,
GISTENTRY orig,
bool  isNullOrig,
GISTENTRY add,
bool  isNullAdd 
)

Definition at line 724 of file gistutil.c.

727{
728 float penalty = 0.0;
729
730 if (giststate->penaltyFn[attno].fn_strict == false ||
731 (isNullOrig == false && isNullAdd == false))
732 {
733 FunctionCall3Coll(&giststate->penaltyFn[attno],
734 giststate->supportCollation[attno],
735 PointerGetDatum(orig),
736 PointerGetDatum(add),
737 PointerGetDatum(&penalty));
738 /* disallow negative or NaN penalty */
739 if (isnan(penalty) || penalty < 0.0)
740 penalty = 0.0;
741 }
742 else if (isNullOrig && isNullAdd)
743 penalty = 0.0;
744 else
745 {
746 /* try to prevent mixing null and non-null values */
747 penalty = get_float4_infinity();
748 }
749
750 return penalty;
751}
static float4 get_float4_infinity(void)
Definition: float.h:74
bool fn_strict
Definition: fmgr.h:61
FmgrInfo penaltyFn[INDEX_MAX_KEYS]
Definition: gist_private.h:90

References FmgrInfo::fn_strict, FunctionCall3Coll(), get_float4_infinity(), GISTSTATE::penaltyFn, PointerGetDatum(), and GISTSTATE::supportCollation.

Referenced by findDontCares(), gistchoose(), gistRelocateBuildBuffersOnSplit(), placeOne(), and supportSecondarySplit().

◆ gistproperty()

bool gistproperty ( Oid  index_oid,
int  attno,
IndexAMProperty  prop,
const char *  propname,
bool *  res,
bool *  isnull 
)

Definition at line 933 of file gistutil.c.

936{
937 Oid opclass,
938 opfamily,
939 opcintype;
940 int16 procno;
941
942 /* Only answer column-level inquiries */
943 if (attno == 0)
944 return false;
945
946 /*
947 * Currently, GiST distance-ordered scans require that there be a distance
948 * function in the opclass with the default types (i.e. the one loaded
949 * into the relcache entry, see initGISTstate). So we assume that if such
950 * a function exists, then there's a reason for it (rather than grubbing
951 * through all the opfamily's operators to find an ordered one).
952 *
953 * Essentially the same code can test whether we support returning the
954 * column data, since that's true if the opclass provides a fetch proc.
955 */
956
957 switch (prop)
958 {
960 procno = GIST_DISTANCE_PROC;
961 break;
963 procno = GIST_FETCH_PROC;
964 break;
965 default:
966 return false;
967 }
968
969 /* First we need to know the column's opclass. */
970 opclass = get_index_column_opclass(index_oid, attno);
971 if (!OidIsValid(opclass))
972 {
973 *isnull = true;
974 return true;
975 }
976
977 /* Now look up the opclass family and input datatype. */
978 if (!get_opclass_opfamily_and_input_type(opclass, &opfamily, &opcintype))
979 {
980 *isnull = true;
981 return true;
982 }
983
984 /* And now we can check whether the function is provided. */
985
986 *res = SearchSysCacheExists4(AMPROCNUM,
987 ObjectIdGetDatum(opfamily),
988 ObjectIdGetDatum(opcintype),
989 ObjectIdGetDatum(opcintype),
990 Int16GetDatum(procno));
991
992 /*
993 * Special case: even without a fetch function, AMPROP_RETURNABLE is true
994 * if the opclass has no compress function.
995 */
996 if (prop == AMPROP_RETURNABLE && !*res)
997 {
998 *res = !SearchSysCacheExists4(AMPROCNUM,
999 ObjectIdGetDatum(opfamily),
1000 ObjectIdGetDatum(opcintype),
1001 ObjectIdGetDatum(opcintype),
1003 }
1004
1005 *isnull = false;
1006
1007 return true;
1008}
@ AMPROP_DISTANCE_ORDERABLE
Definition: amapi.h:44
@ AMPROP_RETURNABLE
Definition: amapi.h:45
int16_t int16
Definition: c.h:483
#define GIST_FETCH_PROC
Definition: gist.h:40
#define GIST_COMPRESS_PROC
Definition: gist.h:34
#define GIST_DISTANCE_PROC
Definition: gist.h:39
bool get_opclass_opfamily_and_input_type(Oid opclass, Oid *opfamily, Oid *opcintype)
Definition: lsyscache.c:1236
Oid get_index_column_opclass(Oid index_oid, int attno)
Definition: lsyscache.c:3539
static Datum Int16GetDatum(int16 X)
Definition: postgres.h:177
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
unsigned int Oid
Definition: postgres_ext.h:32
#define SearchSysCacheExists4(cacheId, key1, key2, key3, key4)
Definition: syscache.h:106

References AMPROP_DISTANCE_ORDERABLE, AMPROP_RETURNABLE, get_index_column_opclass(), get_opclass_opfamily_and_input_type(), GIST_COMPRESS_PROC, GIST_DISTANCE_PROC, GIST_FETCH_PROC, Int16GetDatum(), ObjectIdGetDatum(), OidIsValid, res, and SearchSysCacheExists4.

Referenced by gisthandler().

◆ gisttranslatecmptype()

StrategyNumber gisttranslatecmptype ( CompareType  cmptype,
Oid  opfamily,
Oid  opcintype 
)

Definition at line 1098 of file gistutil.c.

1099{
1100 Oid funcid;
1101 Datum result;
1102
1103 /* Check whether the function is provided. */
1104 funcid = get_opfamily_proc(opfamily, opcintype, opcintype, GIST_STRATNUM_PROC);
1105 if (!OidIsValid(funcid))
1106 return InvalidStrategy;
1107
1108 /* Ask the translation function */
1109 result = OidFunctionCall1Coll(funcid, InvalidOid, Int32GetDatum(cmptype));
1110 return DatumGetUInt16(result);
1111}
Datum OidFunctionCall1Coll(Oid functionId, Oid collation, Datum arg1)
Definition: fmgr.c:1411
#define GIST_STRATNUM_PROC
Definition: gist.h:43
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
Definition: lsyscache.c:797
static uint16 DatumGetUInt16(Datum X)
Definition: postgres.h:187
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:217

References DatumGetUInt16(), get_opfamily_proc(), GIST_STRATNUM_PROC, Int32GetDatum(), InvalidOid, InvalidStrategy, OidFunctionCall1Coll(), and OidIsValid.

Referenced by gisthandler().

◆ gistunion()

IndexTuple gistunion ( Relation  r,
IndexTuple itvec,
int  len,
GISTSTATE giststate 
)

Definition at line 219 of file gistutil.c.

220{
221 Datum attr[INDEX_MAX_KEYS];
222 bool isnull[INDEX_MAX_KEYS];
223
224 gistMakeUnionItVec(giststate, itvec, len, attr, isnull);
225
226 return gistFormTuple(giststate, r, attr, isnull, false);
227}
void gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len, Datum *attr, bool *isnull)
Definition: gistutil.c:155

References gistFormTuple(), gistMakeUnionItVec(), INDEX_MAX_KEYS, and len.

Referenced by gist_indexsortbuild_levelstate_flush().