PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
gistutil.c File Reference
#include "postgres.h"
#include <float.h>
#include <math.h>
#include "access/gist_private.h"
#include "access/htup_details.h"
#include "access/reloptions.h"
#include "catalog/pg_opclass.h"
#include "storage/indexfsm.h"
#include "storage/lmgr.h"
#include "utils/builtins.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, Datum attdata[], bool isnull[], bool isleaf)
 
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 GISTInitBuffer (Buffer b, uint32 f)
 
void gistcheckpage (Relation rel, Buffer buf)
 
Buffer gistNewBuffer (Relation r)
 
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)
 

Function Documentation

void gistcheckpage ( Relation  rel,
Buffer  buf 
)

Definition at line 723 of file gistutil.c.

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

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

724 {
725  Page page = BufferGetPage(buf);
726 
727  /*
728  * ReadBuffer verifies that every newly-read page passes
729  * PageHeaderIsValid, which means it either contains a reasonably sane
730  * page header or is all-zero. We have to defend against the all-zero
731  * case, however.
732  */
733  if (PageIsNew(page))
734  ereport(ERROR,
735  (errcode(ERRCODE_INDEX_CORRUPTED),
736  errmsg("index \"%s\" contains unexpected zero page at block %u",
739  errhint("Please REINDEX it.")));
740 
741  /*
742  * Additionally check that the special area looks sane.
743  */
744  if (PageGetSpecialSize(page) != MAXALIGN(sizeof(GISTPageOpaqueData)))
745  ereport(ERROR,
746  (errcode(ERRCODE_INDEX_CORRUPTED),
747  errmsg("index \"%s\" contains corrupted page at block %u",
750  errhint("Please REINDEX it.")));
751 }
int errhint(const char *fmt,...)
Definition: elog.c:987
int errcode(int sqlerrcode)
Definition: elog.c:575
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:66
#define RelationGetRelationName(relation)
Definition: rel.h:437
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define ereport(elevel, rest)
Definition: elog.h:122
#define MAXALIGN(LEN)
Definition: c.h:588
#define PageGetSpecialSize(page)
Definition: bufpage.h:297
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
#define PageIsNew(page)
Definition: bufpage.h:226
int errmsg(const char *fmt,...)
Definition: elog.c:797
Pointer Page
Definition: bufpage.h:74
OffsetNumber gistchoose ( Relation  r,
Page  p,
IndexTuple  it,
GISTSTATE giststate 
)

Definition at line 372 of file gistutil.c.

References Assert, FALSE, FirstOffsetNumber, gistDeCompressAtt(), gistdentryinit(), GistPageIsLeaf, gistpenalty(), i, index_getattr, INDEX_MAX_KEYS, MAX_RANDOM_VALUE, tupleDesc::natts, NULL, OffsetNumberNext, PageGetItem, PageGetItemId, PageGetMaxOffsetNumber, random(), RelationData::rd_att, result, and GISTSTATE::tupdesc.

Referenced by gistdoinsert(), and gistProcessItup().

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

Definition at line 294 of file gistutil.c.

References FALSE, gistdentryinit(), i, index_getattr, tupleDesc::natts, RelationData::rd_att, and GISTSTATE::tupdesc.

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

296 {
297  int i;
298 
299  for (i = 0; i < r->rd_att->natts; i++)
300  {
301  Datum datum;
302 
303  datum = index_getattr(tuple, i + 1, giststate->tupdesc, &isnull[i]);
304  gistdentryinit(giststate, i, &attdata[i],
305  datum, r, p, o,
306  FALSE, isnull[i]);
307  }
308 }
TupleDesc tupdesc
Definition: gist_private.h:81
int natts
Definition: tupdesc.h:73
void gistdentryinit(GISTSTATE *giststate, int nkey, GISTENTRY *e, Datum k, Relation r, Page pg, OffsetNumber o, bool l, bool isNull)
Definition: gistutil.c:544
#define FALSE
Definition: c.h:221
uintptr_t Datum
Definition: postgres.h:372
TupleDesc rd_att
Definition: rel.h:115
#define index_getattr(tup, attnum, tupleDesc, isnull)
Definition: itup.h:100
int i
void gistdentryinit ( GISTSTATE giststate,
int  nkey,
GISTENTRY e,
Datum  k,
Relation  r,
Page  pg,
OffsetNumber  o,
bool  l,
bool  isNull 
)

Definition at line 544 of file gistutil.c.

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

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

547 {
548  if (!isNull)
549  {
550  GISTENTRY *dep;
551 
552  gistentryinit(*e, k, r, pg, o, l);
553  dep = (GISTENTRY *)
555  giststate->supportCollation[nkey],
556  PointerGetDatum(e)));
557  /* decompressFn may just return the given pointer */
558  if (dep != e)
559  gistentryinit(*e, dep->key, dep->rel, dep->page, dep->offset,
560  dep->leafkey);
561  }
562  else
563  gistentryinit(*e, (Datum) 0, r, pg, o, l);
564 }
Relation rel
Definition: gist.h:124
Oid supportCollation[INDEX_MAX_KEYS]
Definition: gist_private.h:96
#define PointerGetDatum(X)
Definition: postgres.h:562
Page page
Definition: gist.h:125
Datum key
Definition: gist.h:123
FmgrInfo decompressFn[INDEX_MAX_KEYS]
Definition: gist_private.h:88
bool leafkey
Definition: gist.h:127
uintptr_t Datum
Definition: postgres.h:372
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
Definition: fmgr.c:1027
#define gistentryinit(e, k, r, pg, o, l)
Definition: gist.h:169
#define DatumGetPointer(X)
Definition: postgres.h:555
OffsetNumber offset
Definition: gist.h:126
IndexTuple* gistextractpage ( Page  page,
int *  len 
)

Definition at line 94 of file gistutil.c.

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

Referenced by gistplacetopage().

95 {
97  maxoff;
98  IndexTuple *itvec;
99 
100  maxoff = PageGetMaxOffsetNumber(page);
101  *len = maxoff;
102  itvec = palloc(sizeof(IndexTuple) * maxoff);
103  for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
104  itvec[i - FirstOffsetNumber] = (IndexTuple) PageGetItem(page, PageGetItemId(page, i));
105 
106  return itvec;
107 }
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:354
uint16 OffsetNumber
Definition: off.h:24
#define FirstOffsetNumber
Definition: off.h:27
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:232
#define OffsetNumberNext(offsetNumber)
Definition: off.h:53
void * palloc(Size size)
Definition: mcxt.c:849
int i
#define PageGetItem(page, itemId)
Definition: bufpage.h:337
static Datum gistFetchAtt ( GISTSTATE giststate,
int  nkey,
Datum  k,
Relation  r 
)
static

Definition at line 610 of file gistutil.c.

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

Referenced by gistFetchTuple().

611 {
612  GISTENTRY fentry;
613  GISTENTRY *fep;
614 
615  gistentryinit(fentry, k, r, NULL, (OffsetNumber) 0, false);
616 
617  fep = (GISTENTRY *)
618  DatumGetPointer(FunctionCall1Coll(&giststate->fetchFn[nkey],
619  giststate->supportCollation[nkey],
620  PointerGetDatum(&fentry)));
621 
622  /* fetchFn set 'key', return it to the caller */
623  return fep->key;
624 }
FmgrInfo fetchFn[INDEX_MAX_KEYS]
Definition: gist_private.h:93
Oid supportCollation[INDEX_MAX_KEYS]
Definition: gist_private.h:96
#define PointerGetDatum(X)
Definition: postgres.h:562
uint16 OffsetNumber
Definition: off.h:24
Datum key
Definition: gist.h:123
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
Definition: fmgr.c:1027
#define NULL
Definition: c.h:229
#define gistentryinit(e, k, r, pg, o, l)
Definition: gist.h:169
#define DatumGetPointer(X)
Definition: postgres.h:555
HeapTuple gistFetchTuple ( GISTSTATE giststate,
Relation  r,
IndexTuple  tuple 
)

Definition at line 631 of file gistutil.c.

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

Referenced by gistScanPage().

632 {
633  MemoryContext oldcxt = MemoryContextSwitchTo(giststate->tempCxt);
635  bool isnull[INDEX_MAX_KEYS];
636  int i;
637 
638  for (i = 0; i < r->rd_att->natts; i++)
639  {
640  Datum datum;
641 
642  datum = index_getattr(tuple, i + 1, giststate->tupdesc, &isnull[i]);
643 
644  if (giststate->fetchFn[i].fn_oid != InvalidOid)
645  {
646  if (!isnull[i])
647  fetchatt[i] = gistFetchAtt(giststate, i, datum, r);
648  else
649  fetchatt[i] = (Datum) 0;
650  }
651  else
652  {
653  /*
654  * Index-only scans not supported for this column. Since the
655  * planner chose an index-only scan anyway, it is not interested
656  * in this column, and we can replace it with a NULL.
657  */
658  isnull[i] = true;
659  fetchatt[i] = (Datum) 0;
660  }
661  }
662  MemoryContextSwitchTo(oldcxt);
663 
664  return heap_form_tuple(giststate->fetchTupdesc, fetchatt, isnull);
665 }
TupleDesc tupdesc
Definition: gist_private.h:81
static Datum gistFetchAtt(GISTSTATE *giststate, int nkey, Datum k, Relation r)
Definition: gistutil.c:610
FmgrInfo fetchFn[INDEX_MAX_KEYS]
Definition: gist_private.h:93
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
int natts
Definition: tupdesc.h:73
#define fetchatt(A, T)
Definition: tupmacs.h:37
MemoryContext tempCxt
Definition: gist_private.h:79
uintptr_t Datum
Definition: postgres.h:372
TupleDesc rd_att
Definition: rel.h:115
#define InvalidOid
Definition: postgres_ext.h:36
Oid fn_oid
Definition: fmgr.h:59
TupleDesc fetchTupdesc
Definition: gist_private.h:82
#define INDEX_MAX_KEYS
#define index_getattr(tup, attnum, tupleDesc, isnull)
Definition: itup.h:100
int i
void gistfillbuffer ( Page  page,
IndexTuple itup,
int  len,
OffsetNumber  off 
)

Definition at line 33 of file gistutil.c.

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

Referenced by gistplacetopage(), and gistRedoPageSplitRecord().

34 {
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]);
45 
46  l = PageAddItem(page, (Item) itup[i], sz, off, false, false);
47  if (l == InvalidOffsetNumber)
48  elog(ERROR, "failed to add item to GiST index page, item %d out of %d, size %d bytes",
49  i, len, (int) sz);
50  off++;
51  }
52 }
#define PageIsEmpty(page)
Definition: bufpage.h:219
Pointer Item
Definition: item.h:17
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:413
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:354
uint16 OffsetNumber
Definition: off.h:24
#define ERROR
Definition: elog.h:43
#define FirstOffsetNumber
Definition: off.h:27
#define InvalidOffsetNumber
Definition: off.h:26
#define OffsetNumberNext(offsetNumber)
Definition: off.h:53
size_t Size
Definition: c.h:356
int i
#define elog
Definition: elog.h:219
#define IndexTupleSize(itup)
Definition: itup.h:70
IndexTupleData* gistfillitupvec ( IndexTuple vec,
int  veclen,
int *  memlen 
)

Definition at line 126 of file gistutil.c.

References i, IndexTupleSize, and palloc().

Referenced by gistplacetopage(), and gistSplit().

127 {
128  char *ptr,
129  *ret;
130  int i;
131 
132  *memlen = 0;
133 
134  for (i = 0; i < veclen; i++)
135  *memlen += IndexTupleSize(vec[i]);
136 
137  ptr = ret = palloc(*memlen);
138 
139  for (i = 0; i < veclen; i++)
140  {
141  memcpy(ptr, vec[i], IndexTupleSize(vec[i]));
142  ptr += IndexTupleSize(vec[i]);
143  }
144 
145  return (IndexTupleData *) ret;
146 }
void * palloc(Size size)
Definition: mcxt.c:849
int i
#define IndexTupleSize(itup)
Definition: itup.h:70
bool gistfitpage ( IndexTuple itvec,
int  len 
)

Definition at line 78 of file gistutil.c.

References GiSTPageSize, i, and IndexTupleSize.

Referenced by gistSplit().

79 {
80  int i;
81  Size size = 0;
82 
83  for (i = 0; i < len; i++)
84  size += IndexTupleSize(itvec[i]) + sizeof(ItemIdData);
85 
86  /* TODO: Consider fillfactor */
87  return (size <= GiSTPageSize);
88 }
struct ItemIdData ItemIdData
#define GiSTPageSize
Definition: gist_private.h:432
size_t Size
Definition: c.h:356
int i
#define IndexTupleSize(itup)
Definition: itup.h:70
IndexTuple gistFormTuple ( GISTSTATE giststate,
Relation  r,
Datum  attdata[],
bool  isnull[],
bool  isleaf 
)

Definition at line 567 of file gistutil.c.

References GISTSTATE::compressFn, DatumGetPointer, FunctionCall1Coll(), gistentryinit, i, index_form_tuple(), INDEX_MAX_KEYS, ItemPointerSetOffsetNumber, GISTENTRY::key, tupleDesc::natts, NULL, PointerGetDatum, RelationData::rd_att, GISTSTATE::supportCollation, IndexTupleData::t_tid, and GISTSTATE::tupdesc.

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

569 {
570  Datum compatt[INDEX_MAX_KEYS];
571  int i;
572  IndexTuple res;
573 
574  /*
575  * Call the compress method on each attribute.
576  */
577  for (i = 0; i < r->rd_att->natts; i++)
578  {
579  if (isnull[i])
580  compatt[i] = (Datum) 0;
581  else
582  {
583  GISTENTRY centry;
584  GISTENTRY *cep;
585 
586  gistentryinit(centry, attdata[i], r, NULL, (OffsetNumber) 0,
587  isleaf);
588  cep = (GISTENTRY *)
590  giststate->supportCollation[i],
591  PointerGetDatum(&centry)));
592  compatt[i] = cep->key;
593  }
594  }
595 
596  res = index_form_tuple(giststate->tupdesc, compatt, isnull);
597 
598  /*
599  * The offset number on tuples on internal pages is unused. For historical
600  * reasons, it is set to 0xffff.
601  */
602  ItemPointerSetOffsetNumber(&(res->t_tid), 0xffff);
603  return res;
604 }
TupleDesc tupdesc
Definition: gist_private.h:81
Oid supportCollation[INDEX_MAX_KEYS]
Definition: gist_private.h:96
#define PointerGetDatum(X)
Definition: postgres.h:562
FmgrInfo compressFn[INDEX_MAX_KEYS]
Definition: gist_private.h:87
ItemPointerData t_tid
Definition: itup.h:37
int natts
Definition: tupdesc.h:73
uint16 OffsetNumber
Definition: off.h:24
IndexTuple index_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: indextuple.c:37
Datum key
Definition: gist.h:123
uintptr_t Datum
Definition: postgres.h:372
Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
Definition: fmgr.c:1027
TupleDesc rd_att
Definition: rel.h:115
#define NULL
Definition: c.h:229
#define gistentryinit(e, k, r, pg, o, l)
Definition: gist.h:169
#define INDEX_MAX_KEYS
#define DatumGetPointer(X)
Definition: postgres.h:555
#define ItemPointerSetOffsetNumber(pointer, offsetNumber)
Definition: itemptr.h:125
int i
IndexTuple gistgetadjusted ( Relation  r,
IndexTuple  oldtup,
IndexTuple  addtup,
GISTSTATE giststate 
)

Definition at line 314 of file gistutil.c.

References FALSE, gistDeCompressAtt(), gistFormTuple(), gistKeyIsEQ(), gistMakeUnionKey(), i, INDEX_MAX_KEYS, tupleDesc::natts, NULL, RelationData::rd_att, and IndexTupleData::t_tid.

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

315 {
316  bool neednew = FALSE;
317  GISTENTRY oldentries[INDEX_MAX_KEYS],
318  addentries[INDEX_MAX_KEYS];
319  bool oldisnull[INDEX_MAX_KEYS],
320  addisnull[INDEX_MAX_KEYS];
321  Datum attr[INDEX_MAX_KEYS];
322  bool isnull[INDEX_MAX_KEYS];
323  IndexTuple newtup = NULL;
324  int i;
325 
326  gistDeCompressAtt(giststate, r, oldtup, NULL,
327  (OffsetNumber) 0, oldentries, oldisnull);
328 
329  gistDeCompressAtt(giststate, r, addtup, NULL,
330  (OffsetNumber) 0, addentries, addisnull);
331 
332  for (i = 0; i < r->rd_att->natts; i++)
333  {
334  gistMakeUnionKey(giststate, i,
335  oldentries + i, oldisnull[i],
336  addentries + i, addisnull[i],
337  attr + i, isnull + i);
338 
339  if (neednew)
340  /* we already need new key, so we can skip check */
341  continue;
342 
343  if (isnull[i])
344  /* union of key may be NULL if and only if both keys are NULL */
345  continue;
346 
347  if (!addisnull[i])
348  {
349  if (oldisnull[i] ||
350  !gistKeyIsEQ(giststate, i, oldentries[i].key, attr[i]))
351  neednew = true;
352  }
353  }
354 
355  if (neednew)
356  {
357  /* need to update key */
358  newtup = gistFormTuple(giststate, r, attr, isnull, false);
359  newtup->t_tid = oldtup->t_tid;
360  }
361 
362  return newtup;
363 }
void gistDeCompressAtt(GISTSTATE *giststate, Relation r, IndexTuple tuple, Page p, OffsetNumber o, GISTENTRY *attdata, bool *isnull)
Definition: gistutil.c:294
ItemPointerData t_tid
Definition: itup.h:37
int natts
Definition: tupdesc.h:73
bool gistKeyIsEQ(GISTSTATE *giststate, int attno, Datum a, Datum b)
Definition: gistutil.c:279
uint16 OffsetNumber
Definition: off.h:24
#define FALSE
Definition: c.h:221
uintptr_t Datum
Definition: postgres.h:372
TupleDesc rd_att
Definition: rel.h:115
#define NULL
Definition: c.h:229
void gistMakeUnionKey(GISTSTATE *giststate, int attno, GISTENTRY *entry1, bool isnull1, GISTENTRY *entry2, bool isnull2, Datum *dst, bool *dstisnull)
Definition: gistutil.c:231
#define INDEX_MAX_KEYS
int i
IndexTuple gistFormTuple(GISTSTATE *giststate, Relation r, Datum attdata[], bool isnull[], bool isleaf)
Definition: gistutil.c:567
XLogRecPtr gistGetFakeLSN ( Relation  rel)

Definition at line 946 of file gistutil.c.

References Assert, GetFakeLSNForUnloggedRel(), RelationData::rd_rel, RELPERSISTENCE_TEMP, and RELPERSISTENCE_UNLOGGED.

Referenced by gistbuild(), gistbulkdelete(), gistplacetopage(), and gistvacuumpage().

947 {
948  static XLogRecPtr counter = 1;
949 
950  if (rel->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
951  {
952  /*
953  * Temporary relations are only accessible in our session, so a simple
954  * backend-local counter will do.
955  */
956  return counter++;
957  }
958  else
959  {
960  /*
961  * Unlogged relations are accessible from other backends, and survive
962  * (clean) restarts. GetFakeLSNForUnloggedRel() handles that for us.
963  */
964  Assert(rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED);
965  return GetFakeLSNForUnloggedRel();
966  }
967 }
#define RELPERSISTENCE_UNLOGGED
Definition: pg_class.h:171
Form_pg_class rd_rel
Definition: rel.h:114
XLogRecPtr GetFakeLSNForUnloggedRel(void)
Definition: xlog.c:4727
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:675
#define RELPERSISTENCE_TEMP
Definition: pg_class.h:172
void GISTInitBuffer ( Buffer  b,
uint32  f 
)

Definition at line 701 of file gistutil.c.

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

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

702 {
703  GISTPageOpaque opaque;
704  Page page;
705  Size pageSize;
706 
707  pageSize = BufferGetPageSize(b);
708  page = BufferGetPage(b);
709  PageInit(page, pageSize, sizeof(GISTPageOpaqueData));
710 
711  opaque = GistPageGetOpaque(page);
712  /* page was already zeroed by PageInit, so this is not needed: */
713  /* memset(&(opaque->nsn), 0, sizeof(GistNSN)); */
714  opaque->rightlink = InvalidBlockNumber;
715  opaque->flags = f;
716  opaque->gist_page_id = GIST_PAGE_ID;
717 }
uint16 gist_page_id
Definition: gist.h:63
uint16 flags
Definition: gist.h:62
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define BufferGetPageSize(buffer)
Definition: bufmgr.h:147
#define GistPageGetOpaque(page)
Definition: gist.h:130
size_t Size
Definition: c.h:356
#define InvalidBlockNumber
Definition: block.h:33
BlockNumber rightlink
Definition: gist.h:61
#define GIST_PAGE_ID
Definition: gist.h:74
Pointer Page
Definition: bufpage.h:74
void PageInit(Page page, Size pageSize, Size specialSize)
Definition: bufpage.c:41
IndexTuple* gistjoinvector ( IndexTuple itvec,
int *  len,
IndexTuple additvec,
int  addlen 
)

Definition at line 113 of file gistutil.c.

References memmove, and repalloc().

Referenced by gistplacetopage().

114 {
115  itvec = (IndexTuple *) repalloc((void *) itvec, sizeof(IndexTuple) * ((*len) + addlen));
116  memmove(&itvec[*len], additvec, sizeof(IndexTuple) * addlen);
117  *len += addlen;
118  return itvec;
119 }
#define memmove(d, s, c)
Definition: c.h:1058
IndexTupleData * IndexTuple
Definition: itup.h:53
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:963
bool gistKeyIsEQ ( GISTSTATE giststate,
int  attno,
Datum  a,
Datum  b 
)

Definition at line 279 of file gistutil.c.

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

Referenced by gistgetadjusted(), and gistUserPicksplit().

280 {
281  bool result;
282 
283  FunctionCall3Coll(&giststate->equalFn[attno],
284  giststate->supportCollation[attno],
285  a, b,
286  PointerGetDatum(&result));
287  return result;
288 }
Oid supportCollation[INDEX_MAX_KEYS]
Definition: gist_private.h:96
#define PointerGetDatum(X)
Definition: postgres.h:562
FmgrInfo equalFn[INDEX_MAX_KEYS]
Definition: gist_private.h:91
return result
Definition: formatting.c:1618
Datum FunctionCall3Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3)
Definition: fmgr.c:1069
void gistMakeUnionItVec ( GISTSTATE giststate,
IndexTuple itvec,
int  len,
Datum attr,
bool isnull 
)

Definition at line 154 of file gistutil.c.

References FALSE, FunctionCall2Coll(), GEVHDRSZ, gistdentryinit(), i, index_getattr, GistEntryVector::n, tupleDesc::natts, NULL, palloc(), PointerGetDatum, GISTSTATE::supportCollation, TRUE, GISTSTATE::tupdesc, GISTSTATE::unionFn, and GistEntryVector::vector.

Referenced by gistunion(), and gistunionsubkeyvec().

156 {
157  int i;
158  GistEntryVector *evec;
159  int attrsize;
160 
161  evec = (GistEntryVector *) palloc((len + 2) * sizeof(GISTENTRY) + GEVHDRSZ);
162 
163  for (i = 0; i < giststate->tupdesc->natts; i++)
164  {
165  int j;
166 
167  /* Collect non-null datums for this column */
168  evec->n = 0;
169  for (j = 0; j < len; j++)
170  {
171  Datum datum;
172  bool IsNull;
173 
174  datum = index_getattr(itvec[j], i + 1, giststate->tupdesc, &IsNull);
175  if (IsNull)
176  continue;
177 
178  gistdentryinit(giststate, i,
179  evec->vector + evec->n,
180  datum,
181  NULL, NULL, (OffsetNumber) 0,
182  FALSE, IsNull);
183  evec->n++;
184  }
185 
186  /* If this column was all NULLs, the union is NULL */
187  if (evec->n == 0)
188  {
189  attr[i] = (Datum) 0;
190  isnull[i] = TRUE;
191  }
192  else
193  {
194  if (evec->n == 1)
195  {
196  /* unionFn may expect at least two inputs */
197  evec->n = 2;
198  evec->vector[1] = evec->vector[0];
199  }
200 
201  /* Make union and store in attr array */
202  attr[i] = FunctionCall2Coll(&giststate->unionFn[i],
203  giststate->supportCollation[i],
204  PointerGetDatum(evec),
205  PointerGetDatum(&attrsize));
206 
207  isnull[i] = FALSE;
208  }
209  }
210 }
TupleDesc tupdesc
Definition: gist_private.h:81
Oid supportCollation[INDEX_MAX_KEYS]
Definition: gist_private.h:96
#define PointerGetDatum(X)
Definition: postgres.h:562
int32 n
Definition: gist.h:160
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1047
int natts
Definition: tupdesc.h:73
uint16 OffsetNumber
Definition: off.h:24
GISTENTRY vector[FLEXIBLE_ARRAY_MEMBER]
Definition: gist.h:161
#define GEVHDRSZ
Definition: gist.h:164
void gistdentryinit(GISTSTATE *giststate, int nkey, GISTENTRY *e, Datum k, Relation r, Page pg, OffsetNumber o, bool l, bool isNull)
Definition: gistutil.c:544
struct GISTENTRY GISTENTRY
#define FALSE
Definition: c.h:221
uintptr_t Datum
Definition: postgres.h:372
#define NULL
Definition: c.h:229
#define index_getattr(tup, attnum, tupleDesc, isnull)
Definition: itup.h:100
void * palloc(Size size)
Definition: mcxt.c:849
int i
#define TRUE
Definition: c.h:217
FmgrInfo unionFn[INDEX_MAX_KEYS]
Definition: gist_private.h:86
void gistMakeUnionKey ( GISTSTATE giststate,
int  attno,
GISTENTRY entry1,
bool  isnull1,
GISTENTRY entry2,
bool  isnull2,
Datum dst,
bool dstisnull 
)

Definition at line 231 of file gistutil.c.

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

Referenced by gistgetadjusted(), and supportSecondarySplit().

235 {
236  /* we need a GistEntryVector with room for exactly 2 elements */
237  union
238  {
239  GistEntryVector gev;
240  char padding[2 * sizeof(GISTENTRY) + GEVHDRSZ];
241  } storage;
242  GistEntryVector *evec = &storage.gev;
243  int dstsize;
244 
245  evec->n = 2;
246 
247  if (isnull1 && isnull2)
248  {
249  *dstisnull = TRUE;
250  *dst = (Datum) 0;
251  }
252  else
253  {
254  if (isnull1 == FALSE && isnull2 == FALSE)
255  {
256  evec->vector[0] = *entry1;
257  evec->vector[1] = *entry2;
258  }
259  else if (isnull1 == FALSE)
260  {
261  evec->vector[0] = *entry1;
262  evec->vector[1] = *entry1;
263  }
264  else
265  {
266  evec->vector[0] = *entry2;
267  evec->vector[1] = *entry2;
268  }
269 
270  *dstisnull = FALSE;
271  *dst = FunctionCall2Coll(&giststate->unionFn[attno],
272  giststate->supportCollation[attno],
273  PointerGetDatum(evec),
274  PointerGetDatum(&dstsize));
275  }
276 }
Oid supportCollation[INDEX_MAX_KEYS]
Definition: gist_private.h:96
#define PointerGetDatum(X)
Definition: postgres.h:562
int32 n
Definition: gist.h:160
Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
Definition: fmgr.c:1047
GISTENTRY vector[FLEXIBLE_ARRAY_MEMBER]
Definition: gist.h:161
#define GEVHDRSZ
Definition: gist.h:164
struct GISTENTRY GISTENTRY
#define FALSE
Definition: c.h:221
uintptr_t Datum
Definition: postgres.h:372
#define TRUE
Definition: c.h:217
FmgrInfo unionFn[INDEX_MAX_KEYS]
Definition: gist_private.h:86
Buffer gistNewBuffer ( Relation  r)

Definition at line 762 of file gistutil.c.

References DataPageDeleteStack::blkno, buffer, BufferGetPage, ConditionalLockBuffer(), ExclusiveLock, GetFreeIndexPage(), GIST_EXCLUSIVE, GIST_UNLOCK, gistcheckpage(), GistPageIsDeleted, InvalidBlockNumber, LockBuffer(), LockRelationForExtension(), P_NEW, PageIsNew, ReadBuffer(), RELATION_IS_LOCAL, ReleaseBuffer(), and UnlockRelationForExtension().

Referenced by gistbuild(), and gistplacetopage().

763 {
764  Buffer buffer;
765  bool needLock;
766 
767  /* First, try to get a page from FSM */
768  for (;;)
769  {
770  BlockNumber blkno = GetFreeIndexPage(r);
771 
772  if (blkno == InvalidBlockNumber)
773  break; /* nothing left in FSM */
774 
775  buffer = ReadBuffer(r, blkno);
776 
777  /*
778  * We have to guard against the possibility that someone else already
779  * recycled this page; the buffer may be locked if so.
780  */
781  if (ConditionalLockBuffer(buffer))
782  {
783  Page page = BufferGetPage(buffer);
784 
785  if (PageIsNew(page))
786  return buffer; /* OK to use, if never initialized */
787 
788  gistcheckpage(r, buffer);
789 
790  if (GistPageIsDeleted(page))
791  return buffer; /* OK to use */
792 
793  LockBuffer(buffer, GIST_UNLOCK);
794  }
795 
796  /* Can't use it, so release buffer and try again */
797  ReleaseBuffer(buffer);
798  }
799 
800  /* Must extend the file */
801  needLock = !RELATION_IS_LOCAL(r);
802 
803  if (needLock)
805 
806  buffer = ReadBuffer(r, P_NEW);
807  LockBuffer(buffer, GIST_EXCLUSIVE);
808 
809  if (needLock)
811 
812  return buffer;
813 }
#define GistPageIsDeleted(page)
Definition: gist.h:135
#define ExclusiveLock
Definition: lockdefs.h:44
#define RELATION_IS_LOCAL(relation)
Definition: rel.h:524
#define GIST_UNLOCK
Definition: gist_private.h:45
uint32 BlockNumber
Definition: block.h:31
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3309
#define P_NEW
Definition: bufmgr.h:82
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
bool ConditionalLockBuffer(Buffer buffer)
Definition: bufmgr.c:3572
void LockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:332
void UnlockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:382
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
BlockNumber GetFreeIndexPage(Relation rel)
Definition: indexfsm.c:38
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:207
void gistcheckpage(Relation rel, Buffer buf)
Definition: gistutil.c:723
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:594
#define InvalidBlockNumber
Definition: block.h:33
#define PageIsNew(page)
Definition: bufpage.h:226
#define GIST_EXCLUSIVE
Definition: gist_private.h:44
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:74
bool gistnospace ( Page  page,
IndexTuple itvec,
int  len,
OffsetNumber  todelete,
Size  freespace 
)

Definition at line 58 of file gistutil.c.

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

Referenced by gistplacetopage().

59 {
60  unsigned int size = freespace,
61  deleted = 0;
62  int i;
63 
64  for (i = 0; i < len; i++)
65  size += IndexTupleSize(itvec[i]) + sizeof(ItemIdData);
66 
67  if (todelete != InvalidOffsetNumber)
68  {
69  IndexTuple itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, todelete));
70 
71  deleted = IndexTupleSize(itup) + sizeof(ItemIdData);
72  }
73 
74  return (PageGetFreeSpace(page) + deleted < size);
75 }
Size PageGetFreeSpace(Page page)
Definition: bufpage.c:582
IndexTupleData * IndexTuple
Definition: itup.h:53
struct ItemIdData ItemIdData
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:232
#define InvalidOffsetNumber
Definition: off.h:26
int i
#define PageGetItem(page, itemId)
Definition: bufpage.h:337
#define IndexTupleSize(itup)
Definition: itup.h:70
bytea* gistoptions ( Datum  reloptions,
bool  validate 
)

Definition at line 816 of file gistutil.c.

References allocateReloptStruct(), fillfactor, fillRelOptions(), lengthof, NULL, offsetof, options, parseRelOptions(), pfree(), RELOPT_KIND_GIST, RELOPT_TYPE_INT, and RELOPT_TYPE_STRING.

Referenced by gisthandler().

817 {
819  GiSTOptions *rdopts;
820  int numoptions;
821  static const relopt_parse_elt tab[] = {
822  {"fillfactor", RELOPT_TYPE_INT, offsetof(GiSTOptions, fillfactor)},
823  {"buffering", RELOPT_TYPE_STRING, offsetof(GiSTOptions, bufferingModeOffset)}
824  };
825 
826  options = parseRelOptions(reloptions, validate, RELOPT_KIND_GIST,
827  &numoptions);
828 
829  /* if none set, we're done */
830  if (numoptions == 0)
831  return NULL;
832 
833  rdopts = allocateReloptStruct(sizeof(GiSTOptions), options, numoptions);
834 
835  fillRelOptions((void *) rdopts, sizeof(GiSTOptions), options, numoptions,
836  validate, tab, lengthof(tab));
837 
838  pfree(options);
839 
840  return (bytea *) rdopts;
841 }
#define lengthof(array)
Definition: c.h:562
void pfree(void *pointer)
Definition: mcxt.c:950
int fillfactor
Definition: pgbench.c:112
void * allocateReloptStruct(Size base, relopt_value *options, int numoptions)
Definition: reloptions.c:1215
static char ** options
void fillRelOptions(void *rdopts, Size basesize, relopt_value *options, int numoptions, bool validate, const relopt_parse_elt *elems, int numelems)
Definition: reloptions.c:1239
#define NULL
Definition: c.h:229
Definition: c.h:439
relopt_value * parseRelOptions(Datum options, bool validate, relopt_kind kind, int *numrelopts)
Definition: reloptions.c:1020
#define offsetof(type, field)
Definition: c.h:555
float gistpenalty ( GISTSTATE giststate,
int  attno,
GISTENTRY orig,
bool  isNullOrig,
GISTENTRY add,
bool  isNullAdd 
)

Definition at line 668 of file gistutil.c.

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

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

671 {
672  float penalty = 0.0;
673 
674  if (giststate->penaltyFn[attno].fn_strict == FALSE ||
675  (isNullOrig == FALSE && isNullAdd == FALSE))
676  {
677  FunctionCall3Coll(&giststate->penaltyFn[attno],
678  giststate->supportCollation[attno],
679  PointerGetDatum(orig),
680  PointerGetDatum(add),
681  PointerGetDatum(&penalty));
682  /* disallow negative or NaN penalty */
683  if (isnan(penalty) || penalty < 0.0)
684  penalty = 0.0;
685  }
686  else if (isNullOrig && isNullAdd)
687  penalty = 0.0;
688  else
689  {
690  /* try to prevent mixing null and non-null values */
691  penalty = get_float4_infinity();
692  }
693 
694  return penalty;
695 }
Oid supportCollation[INDEX_MAX_KEYS]
Definition: gist_private.h:96
#define PointerGetDatum(X)
Definition: postgres.h:562
float get_float4_infinity(void)
Definition: float.c:146
bool fn_strict
Definition: fmgr.h:61
#define FALSE
Definition: c.h:221
FmgrInfo penaltyFn[INDEX_MAX_KEYS]
Definition: gist_private.h:89
Datum FunctionCall3Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2, Datum arg3)
Definition: fmgr.c:1069
bool gistproperty ( Oid  index_oid,
int  attno,
IndexAMProperty  prop,
const char *  propname,
bool res,
bool isnull 
)

Definition at line 851 of file gistutil.c.

References AMPROCNUM, AMPROP_DISTANCE_ORDERABLE, AMPROP_RETURNABLE, Anum_pg_index_indclass, Assert, CLAOID, DatumGetPointer, GETSTRUCT, GIST_DISTANCE_PROC, GIST_FETCH_PROC, HeapTupleIsValid, INDEXRELID, Int16GetDatum, ObjectIdGetDatum, PG_USED_FOR_ASSERTS_ONLY, ReleaseSysCache(), SearchSysCache1, SearchSysCacheExists4, SysCacheGetAttr(), and oidvector::values.

Referenced by gisthandler().

854 {
855  HeapTuple tuple;
857  Form_pg_opclass rd_opclass;
858  Datum datum;
859  bool disnull;
860  oidvector *indclass;
861  Oid opclass,
862  opfamily,
863  opcintype;
864  int16 procno;
865 
866  /* Only answer column-level inquiries */
867  if (attno == 0)
868  return false;
869 
870  /*
871  * Currently, GiST distance-ordered scans require that there be a distance
872  * function in the opclass with the default types (i.e. the one loaded
873  * into the relcache entry, see initGISTstate). So we assume that if such
874  * a function exists, then there's a reason for it (rather than grubbing
875  * through all the opfamily's operators to find an ordered one).
876  *
877  * Essentially the same code can test whether we support returning the
878  * column data, since that's true if the opclass provides a fetch proc.
879  */
880 
881  switch (prop)
882  {
884  procno = GIST_DISTANCE_PROC;
885  break;
886  case AMPROP_RETURNABLE:
887  procno = GIST_FETCH_PROC;
888  break;
889  default:
890  return false;
891  }
892 
893  /* First we need to know the column's opclass. */
894 
895  tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(index_oid));
896  if (!HeapTupleIsValid(tuple))
897  {
898  *isnull = true;
899  return true;
900  }
901  rd_index = (Form_pg_index) GETSTRUCT(tuple);
902 
903  /* caller is supposed to guarantee this */
904  Assert(attno > 0 && attno <= rd_index->indnatts);
905 
906  datum = SysCacheGetAttr(INDEXRELID, tuple,
907  Anum_pg_index_indclass, &disnull);
908  Assert(!disnull);
909 
910  indclass = ((oidvector *) DatumGetPointer(datum));
911  opclass = indclass->values[attno - 1];
912 
913  ReleaseSysCache(tuple);
914 
915  /* Now look up the opclass family and input datatype. */
916 
917  tuple = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass));
918  if (!HeapTupleIsValid(tuple))
919  {
920  *isnull = true;
921  return true;
922  }
923  rd_opclass = (Form_pg_opclass) GETSTRUCT(tuple);
924 
925  opfamily = rd_opclass->opcfamily;
926  opcintype = rd_opclass->opcintype;
927 
928  ReleaseSysCache(tuple);
929 
930  /* And now we can check whether the function is provided. */
931 
933  ObjectIdGetDatum(opfamily),
934  ObjectIdGetDatum(opcintype),
935  ObjectIdGetDatum(opcintype),
936  Int16GetDatum(procno));
937  return true;
938 }
signed short int16
Definition: c.h:255
Definition: c.h:478
#define GIST_FETCH_PROC
Definition: gist.h:36
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
#define Int16GetDatum(X)
Definition: postgres.h:457
#define Anum_pg_index_indclass
Definition: pg_index.h:89
#define SearchSysCacheExists4(cacheId, key1, key2, key3, key4)
Definition: syscache.h:176
unsigned int Oid
Definition: postgres_ext.h:31
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:152
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
Oid values[FLEXIBLE_ARRAY_MEMBER]
Definition: c.h:486
FormData_pg_index * Form_pg_index
Definition: pg_index.h:67
uintptr_t Datum
Definition: postgres.h:372
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1116
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1278
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define Assert(condition)
Definition: c.h:675
#define GIST_DISTANCE_PROC
Definition: gist.h:35
#define DatumGetPointer(X)
Definition: postgres.h:555
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:990
FormData_pg_opclass * Form_pg_opclass
Definition: pg_opclass.h:68
IndexTuple gistunion ( Relation  r,
IndexTuple itvec,
int  len,
GISTSTATE giststate 
)

Definition at line 217 of file gistutil.c.

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

218 {
219  Datum attr[INDEX_MAX_KEYS];
220  bool isnull[INDEX_MAX_KEYS];
221 
222  gistMakeUnionItVec(giststate, itvec, len, attr, isnull);
223 
224  return gistFormTuple(giststate, r, attr, isnull, false);
225 }
uintptr_t Datum
Definition: postgres.h:372
void gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len, Datum *attr, bool *isnull)
Definition: gistutil.c:154
#define INDEX_MAX_KEYS
IndexTuple gistFormTuple(GISTSTATE *giststate, Relation r, Datum attdata[], bool isnull[], bool isleaf)
Definition: gistutil.c:567