25#include "utils/fmgrprotos.h"
38 bool unlockbuf,
bool unlockleftchild);
45#define ROTATEDIST(d) do { \
46 SplitPageLayout *tmp = palloc0_object(SplitPageLayout); \
47 tmp->block.blkno = InvalidBlockNumber; \
48 tmp->buffer = InvalidBuffer; \
62 .
type = T_IndexAmRoutine,
67 .amcanorderbyop =
true,
69 .amconsistentequality =
false,
70 .amconsistentordering =
false,
71 .amcanbackward =
false,
73 .amcanmulticol =
true,
74 .amoptionalkey =
true,
75 .amsearcharray =
false,
76 .amsearchnulls =
true,
78 .amclusterable =
true,
80 .amcanparallel =
false,
81 .amcanbuildparallel =
false,
83 .amusemaintenanceworkmem =
false,
84 .amsummarizing =
false,
85 .amparallelvacuumoptions =
92 .aminsertcleanup = NULL,
97 .amgettreeheight = NULL,
100 .ambuildphasename = NULL,
110 .amestimateparallelscan = NULL,
111 .aminitparallelscan = NULL,
112 .amparallelrescan = NULL,
113 .amtranslatestrategy = NULL,
132 "GiST temporary context",
177 if (giststate == NULL)
189 itup->t_tid = *ht_ctid;
237 bool markfollowright,
257 elog(
ERROR,
"concurrent GiST page split was incomplete");
274 is_split =
gistnospace(page, itup, ntup, oldoffnum, freespace);
283 is_split =
gistnospace(page, itup, ntup, oldoffnum, freespace);
313 memmove(itvec + pos, itvec + pos + 1,
sizeof(
IndexTuple) * (tlen - pos));
316 dist =
gistSplit(rel, page, itvec, tlen, giststate);
322 for (ptr = dist; ptr; ptr = ptr->
next)
328 elog(
ERROR,
"GiST page split into too many halves (%d, maximum %d)",
356 for (; ptr; ptr = ptr->next)
372 for (ptr = dist; ptr; ptr = ptr->
next)
394 for (ptr = dist; ptr; ptr = ptr->
next)
397 for (
i = 0, ptr = dist; ptr; ptr = ptr->
next)
398 downlinks[
i++] = ptr->itup;
412 for (ptr = dist; ptr; ptr = ptr->
next)
416 si->
buf = ptr->buffer;
418 *splitinfo =
lappend(*splitinfo, si);
426 for (ptr = dist; ptr; ptr = ptr->
next)
428 char *
data = (
char *) (ptr->list);
430 for (
int i = 0;
i < ptr->block.num;
i++)
442 *newblkno = ptr->block.blkno;
450 ptr->next->block.blkno;
462 if (ptr->next && !is_rootsplit && markfollowright)
489 for (ptr = dist; ptr; ptr = ptr->
next)
517 dist, oldrlink, oldnsn, leftchildbuf,
523 for (ptr = dist; ptr; ptr = ptr->
next)
535 for (ptr = dist->
next; ptr; ptr = ptr->
next)
556 elog(
ERROR,
"failed to add item to index page in \"%s\"",
588 deloffs[0] = oldoffnum;
593 deloffs, ndeloffs, itup, ntup,
647 bool xlocked =
false;
650 state.freespace = freespace;
652 state.heapRel = heapRel;
653 state.is_build = is_build;
661 state.stack = stack = &firststack;
700 stack->
lsn = xlocked ?
765 (
errmsg(
"index \"%s\" contains an inner tuple marked as invalid",
767 errdetail(
"This is caused by an incomplete page split at crash recovery before upgrading to PostgreSQL 9.1."),
768 errhint(
"Please REINDEX it.")));
828 item->
blkno = childblkno;
831 state.stack = stack = item;
897 for (; stack; stack = stack->
parent)
963 elog(
ERROR,
"concurrent GiST page split was incomplete");
984 fifo =
lcons(ptr, fifo);
1016 elog(
ERROR,
"failed to re-find parent of a page in index \"%s\", block %u",
1154 if (downlink == NULL)
1163 downlink = newdownlink;
1208 (
errmsg(
"fixing incomplete split in index \"%s\", block %u",
1233 splitinfo =
lappend(splitinfo, si);
1298 bool unlockbuf,
bool unlockleftchild)
1377 for (
int pos =
list_length(splitinfo) - 1; pos > 1; pos--)
1386 left->
buf, right->
buf,
false,
false))
1474 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1475 errmsg(
"index row size %zu exceeds maximum %zu for index \"%s\"",
1516 while (resptr->
next)
1517 resptr = resptr->
next;
1546 elog(
ERROR,
"numberOfAttributes %d > %d",
1551 "GiST scan context",
1644 for (;
i <
index->rd_att->natts;
i++)
1696 deletable[ndeletable++] = offnum;
1704 snapshotConflictHorizon =
1706 deletable, ndeletable);
1729 deletable, ndeletable,
1730 snapshotConflictHorizon,
#define InvalidBlockNumber
static Datum values[MAXATTR]
BlockNumber BufferGetBlockNumber(Buffer buffer)
void LockBuffer(Buffer buffer, BufferLockMode mode)
Buffer ExtendBufferedRel(BufferManagerRelation bmr, ForkNumber forkNum, BufferAccessStrategy strategy, uint32 flags)
void ReleaseBuffer(Buffer buffer)
XLogRecPtr BufferGetLSNAtomic(Buffer buffer)
void UnlockReleaseBuffer(Buffer buffer)
void MarkBufferDirty(Buffer buffer)
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
static Page BufferGetPage(Buffer buffer)
static bool BufferIsValid(Buffer bufnum)
void PageRestoreTempPage(Page tempPage, Page oldPage)
void PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
bool PageIndexTupleOverwrite(Page page, OffsetNumber offnum, const void *newtup, Size newsize)
void PageIndexTupleDelete(Page page, OffsetNumber offnum)
Page PageGetTempPageCopySpecial(const PageData *page)
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
static void * PageGetItem(PageData *page, const ItemIdData *itemId)
static void PageSetLSN(Page page, XLogRecPtr lsn)
static XLogRecPtr PageGetLSN(const PageData *page)
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
static OffsetNumber PageGetMaxOffsetNumber(const PageData *page)
#define OidIsValid(objectId)
int errdetail(const char *fmt,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
#define palloc_object(type)
#define palloc_array(type, count)
#define palloc0_object(type)
void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, MemoryContext destcxt)
#define PG_RETURN_POINTER(x)
TransactionId index_compute_xid_horizon_for_tuples(Relation irel, Relation hrel, Buffer ibuf, OffsetNumber *itemnos, int nitems)
SplitPageLayout * gistSplit(Relation r, Page page, IndexTuple *itup, int len, GISTSTATE *giststate)
GISTSTATE * initGISTstate(Relation index)
static GISTInsertStack * gistFindPath(Relation r, BlockNumber child, OffsetNumber *downlinkoffnum)
void gistdoinsert(Relation r, IndexTuple itup, Size freespace, GISTSTATE *giststate, Relation heapRel, bool is_build)
static void gistfixsplit(GISTInsertState *state, GISTSTATE *giststate)
static void gistprunepage(Relation rel, Page page, Buffer buffer, Relation heapRel)
bool gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate, Buffer buffer, IndexTuple *itup, int ntup, OffsetNumber oldoffnum, BlockNumber *newblkno, Buffer leftchildbuf, List **splitinfo, bool markfollowright, Relation heapRel, bool is_build)
bool gistinsert(Relation r, Datum *values, bool *isnull, ItemPointer ht_ctid, Relation heapRel, IndexUniqueCheck checkUnique, bool indexUnchanged, IndexInfo *indexInfo)
void gistbuildempty(Relation index)
static bool gistinserttuples(GISTInsertState *state, GISTInsertStack *stack, GISTSTATE *giststate, IndexTuple *tuples, int ntup, OffsetNumber oldoffnum, Buffer leftchild, Buffer rightchild, bool unlockbuf, bool unlockleftchild)
MemoryContext createTempGistContext(void)
void freeGISTstate(GISTSTATE *giststate)
static bool gistinserttuple(GISTInsertState *state, GISTInsertStack *stack, GISTSTATE *giststate, IndexTuple tuple, OffsetNumber oldoffnum)
static void gistfinishsplit(GISTInsertState *state, GISTInsertStack *stack, GISTSTATE *giststate, List *splitinfo, bool unlockbuf)
static void gistFindCorrectParent(Relation r, GISTInsertStack *child, bool is_build)
static IndexTuple gistformdownlink(Relation rel, Buffer buf, GISTSTATE *giststate, GISTInsertStack *stack, bool is_build)
Datum gisthandler(PG_FUNCTION_ARGS)
#define GIST_DECOMPRESS_PROC
#define GIST_PICKSPLIT_PROC
#define GistMarkFollowRight(page)
#define GIST_CONSISTENT_PROC
#define GistClearFollowRight(page)
#define GIST_COMPRESS_PROC
#define GistClearPageHasGarbage(page)
#define GIST_PENALTY_PROC
#define GistPageIsLeaf(page)
#define GistFollowRight(page)
#define GIST_OPTIONS_PROC
#define GIST_DISTANCE_PROC
#define GistPageSetNSN(page, val)
#define GistPageIsDeleted(page)
#define GistPageGetOpaque(page)
#define GistPageHasGarbage(page)
#define GistPageGetNSN(page)
#define GIST_MAX_SPLIT_PAGES
#define GistTupleSetValid(itup)
#define GistTupleIsInvalid(itup)
IndexBuildResult * gistbuild(Relation heap, Relation index, IndexInfo *indexInfo)
bool gistgettuple(IndexScanDesc scan, ScanDirection dir)
int64 gistgetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
bool gistcanreturn(Relation index, int attno)
IndexScanDesc gistbeginscan(Relation r, int nkeys, int norderbys)
void gistendscan(IndexScanDesc scan)
void gistrescan(IndexScanDesc scan, ScanKey key, int nkeys, ScanKey orderbys, int norderbys)
void gistSplitByKey(Relation r, Page page, IndexTuple *itup, int len, GISTSTATE *giststate, GistSplitVector *v, int attno)
bytea * gistoptions(Datum reloptions, bool validate)
Buffer gistNewBuffer(Relation r, Relation heaprel)
bool gistproperty(Oid index_oid, int attno, IndexAMProperty prop, const char *propname, bool *res, bool *isnull)
bool gistnospace(Page page, IndexTuple *itvec, int len, OffsetNumber todelete, Size freespace)
void gistfillbuffer(Page page, IndexTuple *itup, int len, OffsetNumber off)
IndexTuple gistFormTuple(GISTSTATE *giststate, Relation r, const Datum *attdata, const bool *isnull, bool isleaf)
IndexTuple * gistextractpage(Page page, int *len)
bool gistfitpage(IndexTuple *itvec, int len)
IndexTuple gistgetadjusted(Relation r, IndexTuple oldtup, IndexTuple addtup, GISTSTATE *giststate)
OffsetNumber gistchoose(Relation r, Page p, IndexTuple it, GISTSTATE *giststate)
XLogRecPtr gistGetFakeLSN(Relation rel)
IndexTuple * gistjoinvector(IndexTuple *itvec, int *len, IndexTuple *additvec, int addlen)
void GISTInitBuffer(Buffer b, uint32 f)
StrategyNumber gisttranslatecmptype(CompareType cmptype, Oid opfamily)
void gistcheckpage(Relation rel, Buffer buf)
IndexTupleData * gistfillitupvec(IndexTuple *vec, int veclen, int *memlen)
IndexBulkDeleteResult * gistvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
IndexBulkDeleteResult * gistbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, IndexBulkDeleteCallback callback, void *callback_state)
void gistadjustmembers(Oid opfamilyoid, Oid opclassoid, List *operators, List *functions)
bool gistvalidate(Oid opclassoid)
XLogRecPtr gistXLogSplit(bool page_is_leaf, SplitPageLayout *dist, BlockNumber origrlink, GistNSN orignsn, Buffer leftchildbuf, bool markfollowright)
XLogRecPtr gistXLogDelete(Buffer buffer, OffsetNumber *todelete, int ntodelete, TransactionId snapshotConflictHorizon, Relation heaprel)
XLogRecPtr gistXLogUpdate(Buffer buffer, OffsetNumber *todelete, int ntodelete, IndexTuple *itup, int ituplen, Buffer leftchildbuf)
Assert(PointerIsAligned(start, uint64))
FmgrInfo * index_getprocinfo(Relation irel, AttrNumber attnum, uint16 procnum)
RegProcedure index_getprocid(Relation irel, AttrNumber attnum, uint16 procnum)
IndexTuple CopyIndexTuple(IndexTuple source)
if(TABLE==NULL||TABLE_index==NULL)
#define ItemIdIsDead(itemId)
bool ItemPointerEquals(const ItemPointerData *pointer1, const ItemPointerData *pointer2)
static void ItemPointerSetBlockNumber(ItemPointerData *pointer, BlockNumber blockNumber)
static BlockNumber ItemPointerGetBlockNumber(const ItemPointerData *pointer)
IndexTupleData * IndexTuple
static Size IndexTupleSize(const IndexTupleData *itup)
#define MaxIndexTuplesPerPage
List * lappend(List *list, void *datum)
List * list_delete_first(List *list)
List * lcons(void *datum, List *list)
void MemoryContextReset(MemoryContext context)
MemoryContext CurrentMemoryContext
void MemoryContextDelete(MemoryContext context)
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
#define START_CRIT_SECTION()
#define END_CRIT_SECTION()
#define InvalidOffsetNumber
#define OffsetNumberIsValid(offsetNumber)
#define OffsetNumberNext(offsetNumber)
#define FirstOffsetNumber
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
static int list_length(const List *l)
static void * list_nth(const List *list, int n)
static char buf[DEFAULT_XLOG_SEG_SIZE]
void PredicateLockPageSplit(Relation relation, BlockNumber oldblkno, BlockNumber newblkno)
void CheckForSerializableConflictIn(Relation relation, const ItemPointerData *tid, BlockNumber blkno)
#define RelationGetRelationName(relation)
#define RelationNeedsWAL(relation)
#define IndexRelationGetNumberOfKeyAttributes(relation)
void gistcostestimate(PlannerInfo *root, IndexPath *path, double loop_count, Cost *indexStartupCost, Cost *indexTotalCost, Selectivity *indexSelectivity, double *indexCorrelation, double *indexPages)
void check_stack_depth(void)
OffsetNumber downlinkoffnum
struct GISTInsertStack * parent
FmgrInfo fetchFn[INDEX_MAX_KEYS]
FmgrInfo penaltyFn[INDEX_MAX_KEYS]
Oid supportCollation[INDEX_MAX_KEYS]
FmgrInfo distanceFn[INDEX_MAX_KEYS]
FmgrInfo consistentFn[INDEX_MAX_KEYS]
FmgrInfo decompressFn[INDEX_MAX_KEYS]
FmgrInfo compressFn[INDEX_MAX_KEYS]
FmgrInfo equalFn[INDEX_MAX_KEYS]
FmgrInfo unionFn[INDEX_MAX_KEYS]
FmgrInfo picksplitFn[INDEX_MAX_KEYS]
GIST_SPLITVEC splitVector
Datum spl_lattr[INDEX_MAX_KEYS]
bool spl_lisnull[INDEX_MAX_KEYS]
Datum spl_rattr[INDEX_MAX_KEYS]
bool spl_risnull[INDEX_MAX_KEYS]
struct SplitPageLayout * next
#define InvalidTransactionId
TupleDesc CreateTupleDescTruncatedCopy(TupleDesc tupdesc, int natts)
#define VACUUM_OPTION_PARALLEL_BULKDEL
#define VACUUM_OPTION_PARALLEL_COND_CLEANUP
#define XLogStandbyInfoActive()
#define XLogRecPtrIsValid(r)
XLogRecPtr log_newpage_buffer(Buffer buffer, bool page_std)
void XLogEnsureRecordSpace(int max_block_id, int ndatas)