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; \
126 "GiST temporary context",
171 if (giststate == NULL)
183 itup->t_tid = *ht_ctid;
231 bool markfollowright,
251 elog(
ERROR,
"concurrent GiST page split was incomplete");
268 is_split =
gistnospace(page, itup, ntup, oldoffnum, freespace);
277 is_split =
gistnospace(page, itup, ntup, oldoffnum, freespace);
307 memmove(itvec + pos, itvec + pos + 1,
sizeof(
IndexTuple) * (tlen - pos));
310 dist =
gistSplit(rel, page, itvec, tlen, giststate);
316 for (ptr = dist; ptr; ptr = ptr->
next)
322 elog(
ERROR,
"GiST page split into too many halves (%d, maximum %d)",
350 for (; ptr; ptr = ptr->next)
366 for (ptr = dist; ptr; ptr = ptr->
next)
388 for (ptr = dist; ptr; ptr = ptr->
next)
391 for (
i = 0, ptr = dist; ptr; ptr = ptr->
next)
392 downlinks[
i++] = ptr->itup;
406 for (ptr = dist; ptr; ptr = ptr->
next)
410 si->
buf = ptr->buffer;
412 *splitinfo =
lappend(*splitinfo, si);
420 for (ptr = dist; ptr; ptr = ptr->
next)
422 char *
data = (
char *) (ptr->list);
424 for (
int i = 0;
i < ptr->block.num;
i++)
436 *newblkno = ptr->block.blkno;
444 ptr->next->block.blkno;
456 if (ptr->next && !is_rootsplit && markfollowright)
483 for (ptr = dist; ptr; ptr = ptr->
next)
511 dist, oldrlink, oldnsn, leftchildbuf,
517 for (ptr = dist; ptr; ptr = ptr->
next)
529 for (ptr = dist->
next; ptr; ptr = ptr->
next)
551 elog(
ERROR,
"failed to add item to index page in \"%s\"",
583 deloffs[0] = oldoffnum;
588 deloffs, ndeloffs, itup, ntup,
642 bool xlocked =
false;
645 state.freespace = freespace;
647 state.heapRel = heapRel;
648 state.is_build = is_build;
656 state.stack = stack = &firststack;
695 stack->
lsn = xlocked ?
760 (
errmsg(
"index \"%s\" contains an inner tuple marked as invalid",
762 errdetail(
"This is caused by an incomplete page split at crash recovery before upgrading to PostgreSQL 9.1."),
763 errhint(
"Please REINDEX it.")));
823 item->
blkno = childblkno;
826 state.stack = stack = item;
892 for (; stack; stack = stack->
parent)
958 elog(
ERROR,
"concurrent GiST page split was incomplete");
979 fifo =
lcons(ptr, fifo);
1011 elog(
ERROR,
"failed to re-find parent of a page in index \"%s\", block %u",
1142 if (downlink == NULL)
1151 downlink = newdownlink;
1196 (
errmsg(
"fixing incomplete split in index \"%s\", block %u",
1221 splitinfo =
lappend(splitinfo, si);
1286 bool unlockbuf,
bool unlockleftchild)
1365 for (
int pos =
list_length(splitinfo) - 1; pos > 1; pos--)
1374 left->
buf, right->
buf,
false,
false))
1462 (
errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
1463 errmsg(
"index row size %zu exceeds maximum %zu for index \"%s\"",
1504 while (resptr->
next)
1505 resptr = resptr->
next;
1534 elog(
ERROR,
"numberOfAttributes %d > %d",
1539 "GiST scan context",
1632 for (;
i <
index->rd_att->natts;
i++)
1684 deletable[ndeletable++] = offnum;
1692 snapshotConflictHorizon =
1694 deletable, ndeletable);
1717 deletable, ndeletable,
1718 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)
Page PageGetTempPageCopySpecial(Page page)
bool PageIndexTupleOverwrite(Page page, OffsetNumber offnum, Item newtup, Size newsize)
void PageIndexTupleDelete(Page page, OffsetNumber offnum)
static Item PageGetItem(Page page, ItemId itemId)
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
static void PageSetLSN(Page page, XLogRecPtr lsn)
static XLogRecPtr PageGetLSN(const char *page)
static OffsetNumber PageGetMaxOffsetNumber(Page page)
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
#define Assert(condition)
#define OidIsValid(objectId)
static void PGresult * res
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)
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)
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
#define IndexTupleSize(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 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)
MemoryContextSwitchTo(old_ctx)
#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
amparallelrescan_function amparallelrescan
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
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)