34 #include "utils/fmgrprotos.h"
41 #define GIN_PAGE_FREESIZE \
42 ( BLCKSZ - MAXALIGN(SizeOfPageHeaderData) - MAXALIGN(sizeof(GinPageOpaqueData)) )
78 for (
i = 0;
i < ntuples;
i++)
82 memcpy(ptr, tuples[
i], this_size);
89 elog(
ERROR,
"failed to add item to index page in \"%s\"",
121 data.rightlink = rightlink;
122 data.ntuples = ntuples;
160 for (
i = 0;
i < ntuples;
i++)
168 res->nPendingPages++;
179 prevBuffer = curBuffer;
204 ntuples - startTuple,
206 res->nPendingPages++;
208 res->nPendingHeapTuples = 1;
228 bool separateList =
false;
229 bool needCleanup =
false;
390 elog(
ERROR,
"failed to add item to index page in \"%s\"",
393 memcpy(ptr, collector->
tuples[
i], tupsize);
497 &nentries, &categories);
504 elog(
ERROR,
"too many entries for GIN index");
509 if (collector->
tuples == NULL)
535 for (
i = 0;
i < nentries;
i++)
541 itup->
t_tid = *ht_ctid;
563 blknoToDelete = metadata->
head;
569 int64 nDeletedHeapTuples = 0;
577 freespace[
data.ndeleted] = blknoToDelete;
603 metadata->
head = blknoToDelete;
630 for (
i = 0;
i <
data.ndeleted;
i++)
644 for (
i = 0;
i <
data.ndeleted;
i++)
655 for (
i = 0;
i <
data.ndeleted;
i++)
662 for (
i = 0;
i <
data.ndeleted;
i++)
667 for (
i = 0; fill_fsm &&
i <
data.ndeleted;
i++)
670 }
while (blknoToDelete != newHead);
737 heapptr = itup->
t_tid;
741 curattnum == attrnum))
751 heapptr = itup->
t_tid;
781 bool fill_fsm,
bool forceCleanup,
796 bool cleanupFinish =
false;
797 bool fsm_vac =
false;
847 blknoFinish = metadata->
tail;
852 blkno = metadata->
head;
863 "GIN insert cleanup temporary context",
887 if (blkno == blknoFinish && full_clean ==
false)
888 cleanupFinish =
true;
928 &
attnum, &
key, &category, &nlist)) != NULL)
958 &
attnum, &
key, &category, &nlist)) != NULL)
1019 if (fsm_vac && fill_fsm)
1039 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1040 errmsg(
"recovery is in progress"),
1041 errhint(
"GIN pending list cannot be cleaned up during recovery.")));
1044 if (indexRel->
rd_rel->relkind != RELKIND_INDEX ||
1045 indexRel->
rd_rel->relam != GIN_AM_OID)
1047 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
1048 errmsg(
"\"%s\" is not a GIN index",
1058 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1059 errmsg(
"cannot access temporary indexes of other sessions")));
1066 memset(&stats, 0,
sizeof(stats));
1075 if (indexRel->
rd_index->indisvalid)
1084 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1085 errmsg(
"index \"%s\" is not valid",
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
#define InvalidBlockNumber
BlockNumber BufferGetBlockNumber(Buffer buffer)
void ReleaseBuffer(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)
Size PageGetExactFreeSpace(Page page)
PageHeaderData * PageHeader
static bool PageIsEmpty(Page page)
static Item PageGetItem(Page page, ItemId itemId)
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
static void PageSetLSN(Page page, XLogRecPtr lsn)
static OffsetNumber PageGetMaxOffsetNumber(Page page)
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
#define Assert(condition)
static void PGresult * res
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
#define repalloc_array(pointer, type, count)
#define palloc_array(type, count)
#define PG_RETURN_INT64(x)
#define GinGetPendingListCleanupSize(relation)
#define GIN_METAPAGE_BLKNO
#define GinPageHasFullRow(page)
#define GinPageGetOpaque(page)
signed char GinNullCategory
#define GinPageGetMeta(p)
#define GinPageIsDeleted(page)
#define GinPageSetFullRow(page)
void ginBeginBAScan(BuildAccumulator *accum)
void ginInsertBAEntries(BuildAccumulator *accum, ItemPointer heapptr, OffsetNumber attnum, Datum *entries, GinNullCategory *categories, int32 nentries)
void ginInitBA(BuildAccumulator *accum)
ItemPointerData * ginGetBAEntry(BuildAccumulator *accum, OffsetNumber *attnum, Datum *key, GinNullCategory *category, uint32 *n)
IndexTuple GinFormTuple(GinState *ginstate, OffsetNumber attnum, Datum key, GinNullCategory category, Pointer data, Size dataSize, int nipd, bool errorTooBig)
#define GIN_PAGE_FREESIZE
Datum gin_clean_pending_list(PG_FUNCTION_ARGS)
void ginInsertCleanup(GinState *ginstate, bool full_clean, bool fill_fsm, bool forceCleanup, IndexBulkDeleteResult *stats)
void ginHeapTupleFastCollect(GinState *ginstate, GinTupleCollector *collector, OffsetNumber attnum, Datum value, bool isNull, ItemPointer ht_ctid)
static int32 writeListPage(Relation index, Buffer buffer, IndexTuple *tuples, int32 ntuples, BlockNumber rightlink)
int gin_pending_list_limit
static void processPendingPage(BuildAccumulator *accum, KeyArray *ka, Page page, OffsetNumber startoff)
static void initKeyArray(KeyArray *keys, int32 maxvalues)
static void makeSublist(Relation index, IndexTuple *tuples, int32 ntuples, GinMetaPageData *res)
static void shiftList(Relation index, Buffer metabuffer, BlockNumber newHead, bool fill_fsm, IndexBulkDeleteResult *stats)
static void addDatum(KeyArray *keys, Datum datum, GinNullCategory category)
void ginHeapTupleFastInsert(GinState *ginstate, GinTupleCollector *collector)
void ginEntryInsert(GinState *ginstate, OffsetNumber attnum, Datum key, GinNullCategory category, ItemPointerData *items, uint32 nitem, GinStatsData *buildStats)
Datum * ginExtractEntries(GinState *ginstate, OffsetNumber attnum, Datum value, bool isNull, int32 *nentries, GinNullCategory **categories)
OffsetNumber gintuple_get_attrnum(GinState *ginstate, IndexTuple tuple)
Buffer GinNewBuffer(Relation index)
void GinInitBuffer(Buffer b, uint32 f)
Datum gintuple_get_key(GinState *ginstate, IndexTuple tuple, GinNullCategory *category)
void initGinState(GinState *state, Relation index)
static MemoryContext opCtx
#define XLOG_GIN_UPDATE_META_PAGE
#define GIN_NDELETE_AT_ONCE
#define XLOG_GIN_INSERT_LISTPAGE
#define XLOG_GIN_DELETE_LISTPAGE
void index_close(Relation relation, LOCKMODE lockmode)
Relation index_open(Oid relationId, LOCKMODE lockmode)
void IndexFreeSpaceMapVacuum(Relation rel)
void RecordFreeIndexPage(Relation rel, BlockNumber freeBlock)
struct ItemIdData ItemIdData
bool ItemPointerEquals(ItemPointer pointer1, ItemPointer pointer2)
static void ItemPointerSetInvalid(ItemPointerData *pointer)
static bool ItemPointerIsValid(const ItemPointerData *pointer)
IndexTupleData * IndexTuple
#define IndexTupleSize(itup)
bool ConditionalLockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
void LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
void UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
void MemoryContextReset(MemoryContext context)
MemoryContext CurrentMemoryContext
void MemoryContextDelete(MemoryContext context)
#define AllocSetContextCreate
#define ALLOCSET_DEFAULT_SIZES
#define AmAutoVacuumWorkerProcess()
#define START_CRIT_SECTION()
#define END_CRIT_SECTION()
#define InvalidOffsetNumber
#define OffsetNumberNext(offsetNumber)
#define FirstOffsetNumber
static uint32 pg_nextpower2_32(uint32 num)
void CheckForSerializableConflictIn(Relation relation, ItemPointer tid, BlockNumber blkno)
MemoryContextSwitchTo(old_ctx)
#define RelationGetRelationName(relation)
#define RelationNeedsWAL(relation)
#define RELATION_IS_OTHER_TEMP(relation)
static pg_noinline void Size size
BlockNumber nPendingPages
BlockNumber pages_deleted
GinNullCategory * categories
void vacuum_delay_point(void)
bool RecoveryInProgress(void)
void XLogRegisterBufData(uint8 block_id, const char *data, uint32 len)
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
void XLogRegisterData(const char *data, uint32 len)
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
void XLogBeginInsert(void)
void XLogEnsureRecordSpace(int max_block_id, int ndatas)