25#include "utils/fmgrprotos.h"
38 bool unlockbuf,
bool unlockleftchild);
45#define ROTATEDIST(d) do { \
46 SplitPageLayout *tmp = (SplitPageLayout *) palloc0(sizeof(SplitPageLayout)); \
47 tmp->block.blkno = InvalidBlockNumber; \
48 tmp->buffer = InvalidBuffer; \
131 "GiST temporary context",
176 if (giststate == NULL)
188 itup->t_tid = *ht_ctid;
236 bool markfollowright,
256 elog(
ERROR,
"concurrent GiST page split was incomplete");
273 is_split =
gistnospace(page, itup, ntup, oldoffnum, freespace);
282 is_split =
gistnospace(page, itup, ntup, oldoffnum, freespace);
312 memmove(itvec + pos, itvec + pos + 1,
sizeof(
IndexTuple) * (tlen - pos));
315 dist =
gistSplit(rel, page, itvec, tlen, giststate);
321 for (ptr = dist; ptr; ptr = ptr->
next)
327 elog(
ERROR,
"GiST page split into too many halves (%d, maximum %d)",
355 for (; ptr; ptr = ptr->next)
371 for (ptr = dist; ptr; ptr = ptr->
next)
393 for (ptr = dist; ptr; ptr = ptr->
next)
396 for (
i = 0, ptr = dist; ptr; ptr = ptr->
next)
397 downlinks[
i++] = ptr->itup;
411 for (ptr = dist; ptr; ptr = ptr->
next)
415 si->
buf = ptr->buffer;
417 *splitinfo =
lappend(*splitinfo, si);
425 for (ptr = dist; ptr; ptr = ptr->
next)
427 char *
data = (
char *) (ptr->list);
429 for (
int i = 0;
i < ptr->block.num;
i++)
441 *newblkno = ptr->block.blkno;
449 ptr->next->block.blkno;
461 if (ptr->next && !is_rootsplit && markfollowright)
488 for (ptr = dist; ptr; ptr = ptr->
next)
516 dist, oldrlink, oldnsn, leftchildbuf,
522 for (ptr = dist; ptr; ptr = ptr->
next)
534 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)
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)
void LockBuffer(Buffer buffer, int mode)
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, Item newtup, Size newsize)
void PageIndexTupleDelete(Page page, OffsetNumber offnum)
Page PageGetTempPageCopySpecial(const PageData *page)
static Item PageGetItem(const PageData *page, const ItemIdData *itemId)
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
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,...)
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(ItemPointer pointer1, ItemPointer 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)
void * palloc0(Size size)
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)
void PredicateLockPageSplit(Relation relation, BlockNumber oldblkno, BlockNumber newblkno)
void CheckForSerializableConflictIn(Relation relation, ItemPointer 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]
ambuildphasename_function ambuildphasename
ambuildempty_function ambuildempty
amvacuumcleanup_function amvacuumcleanup
amoptions_function amoptions
amestimateparallelscan_function amestimateparallelscan
amrestrpos_function amrestrpos
aminsert_function aminsert
amendscan_function amendscan
amtranslate_strategy_function amtranslatestrategy
amparallelrescan_function amparallelrescan
bool amconsistentordering
amtranslate_cmptype_function amtranslatecmptype
amcostestimate_function amcostestimate
amadjustmembers_function amadjustmembers
amgettuple_function amgettuple
amcanreturn_function amcanreturn
amgetbitmap_function amgetbitmap
amproperty_function amproperty
ambulkdelete_function ambulkdelete
amvalidate_function amvalidate
ammarkpos_function ammarkpos
bool amusemaintenanceworkmem
ambeginscan_function ambeginscan
amrescan_function amrescan
aminitparallelscan_function aminitparallelscan
uint8 amparallelvacuumoptions
aminsertcleanup_function aminsertcleanup
amgettreeheight_function amgettreeheight
bool amconsistentequality
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 XLogRecPtrIsInvalid(r)
XLogRecPtr log_newpage_buffer(Buffer buffer, bool page_std)
void XLogEnsureRecordSpace(int max_block_id, int ndatas)