示例#1
0
/*
 * Inserts only one entry to the index, but it can add more than 1 ItemPointer.
 */
static void
ginEntryInsert(Relation index, GinState *ginstate, Datum value, ItemPointerData *items, uint32 nitem, bool isBuild)
{
	GinBtreeData btree;
	GinBtreeStack *stack;
	IndexTuple	itup;
	Page		page;

	prepareEntryScan(&btree, index, value, ginstate);

	stack = ginFindLeafPage(&btree, NULL);
	page = BufferGetPage(stack->buffer);

	if (btree.findItem(&btree, stack))
	{
		/* found entry */
		itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, stack->off));

		if (GinIsPostingTree(itup))
		{
			/* lock root of posting tree */
			GinPostingTreeScan *gdi;
			BlockNumber rootPostingTree = GinGetPostingTree(itup);

			/* release all stack */
			LockBuffer(stack->buffer, GIN_UNLOCK);
			freeGinBtreeStack(stack);

			/* insert into posting tree */
			gdi = prepareScanPostingTree(index, rootPostingTree, FALSE);
			gdi->btree.isBuild = isBuild;
			insertItemPointer(gdi, items, nitem);

			return;
		}

		itup = addItemPointersToTuple(index, ginstate, stack, itup, items, nitem, isBuild);

		btree.isDelete = TRUE;
	}
	else
	{
		/* We suppose, that tuple can store at list one itempointer */
		itup = GinFormTuple(ginstate, value, items, 1);
		if (itup == NULL || IndexTupleSize(itup) >= GinMaxItemSize)
			elog(ERROR, "huge tuple");

		if (nitem > 1)
		{
			IndexTuple	previtup = itup;

			itup = addItemPointersToTuple(index, ginstate, stack, previtup, items + 1, nitem - 1, isBuild);
			pfree(previtup);
		}
	}

	btree.entry = itup;
	ginInsertValue(&btree, stack);
	pfree(itup);
}
示例#2
0
/*
 * Inserts only one entry to the index, but it can add more than 1 ItemPointer.
 *
 * During an index build, buildStats is non-null and the counters
 * it contains should be incremented as needed.
 */
void
ginEntryInsert(Relation index, GinState *ginstate,
			   OffsetNumber attnum, Datum value,
			   ItemPointerData *items, uint32 nitem,
			   GinStatsData *buildStats)
{
	GinBtreeData btree;
	GinBtreeStack *stack;
	IndexTuple	itup;
	Page		page;

	/* During index build, count the to-be-inserted entry */
	if (buildStats)
		buildStats->nEntries++;

	ginPrepareEntryScan(&btree, index, attnum, value, ginstate);

	stack = ginFindLeafPage(&btree, NULL);
	page = BufferGetPage(stack->buffer);

	if (btree.findItem(&btree, stack))
	{
		/* found entry */
		itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, stack->off));

		if (GinIsPostingTree(itup))
		{
			/* lock root of posting tree */
			GinPostingTreeScan *gdi;
			BlockNumber rootPostingTree = GinGetPostingTree(itup);

			/* release all stack */
			LockBuffer(stack->buffer, GIN_UNLOCK);
			freeGinBtreeStack(stack);

			/* insert into posting tree */
			gdi = ginPrepareScanPostingTree(index, rootPostingTree, FALSE);
			gdi->btree.isBuild = (buildStats != NULL);
			ginInsertItemPointer(gdi, items, nitem, buildStats);
			pfree(gdi);

			return;
		}

		itup = addItemPointersToTuple(index, ginstate, stack, itup,
									  items, nitem, buildStats);

		btree.isDelete = TRUE;
	}
	else
	{
		/* We suppose that tuple can store at least one itempointer */
		itup = GinFormTuple(index, ginstate, attnum, value, items, 1, true);

		if (nitem > 1)
		{
			/* Add the rest, making a posting tree if necessary */
			IndexTuple	previtup = itup;

			itup = addItemPointersToTuple(index, ginstate, stack, previtup,
										  items + 1, nitem - 1, buildStats);
			pfree(previtup);
		}
	}

	btree.entry = itup;
	ginInsertValue(&btree, stack, buildStats);
	pfree(itup);
}