Пример #1
0
/*
 * Adds array of item pointers to tuple's posting list or
 * creates posting tree and tuple pointed to tree in a case
 * of not enough space.  Max size of tuple is defined in
 * GinFormTuple().
 */
static IndexTuple
addItemPointersToTuple(Relation index, GinState *ginstate,
					   GinBtreeStack *stack, IndexTuple old,
					   ItemPointerData *items, uint32 nitem,
					   GinStatsData *buildStats)
{
	Datum		key = gin_index_getattr(ginstate, old);
	OffsetNumber attnum = gintuple_get_attrnum(ginstate, old);
	IndexTuple	res = GinFormTuple(index, ginstate, attnum, key,
								   NULL, nitem + GinGetNPosting(old),
								   false);

	if (res)
	{
		/* good, small enough */
		uint32		newnitem;

		newnitem = ginMergeItemPointers(GinGetPosting(res),
										GinGetPosting(old),
										GinGetNPosting(old),
										items, nitem);
		/* merge might have eliminated some duplicate items */
		GinShortenTuple(res, newnitem);
	}
	else
	{
		BlockNumber postingRoot;
		GinPostingTreeScan *gdi;

		/* posting list becomes big, so we need to make posting's tree */
		res = GinFormTuple(index, ginstate, attnum, key, NULL, 0, true);
		postingRoot = createPostingTree(index, GinGetPosting(old), GinGetNPosting(old));
		GinSetPostingTree(res, postingRoot);

		gdi = ginPrepareScanPostingTree(index, postingRoot, FALSE);
		gdi->btree.isBuild = (buildStats != NULL);

		ginInsertItemPointer(gdi, items, nitem, buildStats);

		pfree(gdi);

		/* During index build, count the newly-added data page */
		if (buildStats)
			buildStats->nDataPages++;
	}

	return res;
}
Пример #2
0
/*
 * Adds array of item pointers to tuple's posting list, or
 * creates posting tree and tuple pointing to tree in case
 * of not enough space.  Max size of tuple is defined in
 * GinFormTuple().	Returns a new, modified index tuple.
 * items[] must be in sorted order with no duplicates.
 */
static IndexTuple
addItemPointersToLeafTuple(GinState *ginstate,
						   IndexTuple old,
						   ItemPointerData *items, uint32 nitem,
						   GinStatsData *buildStats)
{
	OffsetNumber attnum;
	Datum		key;
	GinNullCategory category;
	IndexTuple	res;

	Assert(!GinIsPostingTree(old));

	attnum = gintuple_get_attrnum(ginstate, old);
	key = gintuple_get_key(ginstate, old, &category);

	/* try to build tuple with room for all the items */
	res = GinFormTuple(ginstate, attnum, key, category,
					   NULL, nitem + GinGetNPosting(old),
					   false);

	if (res)
	{
		/* good, small enough */
		uint32		newnitem;

		/* fill in the posting list with union of old and new TIDs */
		newnitem = ginMergeItemPointers(GinGetPosting(res),
										GinGetPosting(old),
										GinGetNPosting(old),
										items, nitem);
		/* merge might have eliminated some duplicate items */
		GinShortenTuple(res, newnitem);
	}
	else
	{
		/* posting list would be too big, convert to posting tree */
		BlockNumber postingRoot;

		/*
		 * Initialize posting tree with the old tuple's posting list.  It's
		 * surely small enough to fit on one posting-tree page, and should
		 * already be in order with no duplicates.
		 */
		postingRoot = createPostingTree(ginstate->index,
										GinGetPosting(old),
										GinGetNPosting(old),
										buildStats);

		/* Now insert the TIDs-to-be-added into the posting tree */
		ginInsertItemPointers(ginstate->index, postingRoot,
							  items, nitem,
							  buildStats);

		/* And build a new posting-tree-only result tuple */
		res = GinFormTuple(ginstate, attnum, key, category, NULL, 0, true);
		GinSetPostingTree(res, postingRoot);
	}

	return res;
}