Example #1
0
SpGistInnerTuple
spgFormInnerTuple(SpGistState *state, bool hasPrefix, Datum prefix, int nNodes, IndexTuple *nodes)
{
    SpGistInnerTuple	tup;
    unsigned int 		size;
    int 				i;
    char				*ptr;

    size = SGITHDRSZ;
    if (hasPrefix)
        size += getTypeLength(&state->attPrefixType, prefix);

    for(i=0; i<nNodes; i++)
        size += IndexTupleSize(nodes[i]);

    Assert(size < 0xffff);

    tup = palloc0(size);

    tup->hasPrefix = !!hasPrefix;
    tup->nNodes = nNodes;
    tup->size = size;

    if (tup->hasPrefix)
        memcpyDatum(SGITDATAPTR(tup), &state->attPrefixType, prefix);

    ptr= (char*)SGITNODEPTR(tup, state);

    for(i=0; i<nNodes; i++)
    {
        IndexTuple	node = nodes[i];

        memcpy(ptr, node, IndexTupleSize(node));
        ptr += IndexTupleSize(node);
    }

    return tup;
}
Example #2
0
/*
 * Construct an inner tuple containing the given prefix and node array
 */
SpGistInnerTuple
spgFormInnerTuple(SpGistState *state, bool hasPrefix, Datum prefix,
				  int nNodes, SpGistNodeTuple *nodes)
{
	SpGistInnerTuple tup;
	unsigned int size;
	unsigned int prefixSize;
	int			i;
	char	   *ptr;

	/* Compute size needed */
	if (hasPrefix)
		prefixSize = SpGistGetTypeSize(&state->attPrefixType, prefix);
	else
		prefixSize = 0;

	size = SGITHDRSZ + prefixSize;

	/* Note: we rely on node tuple sizes to be maxaligned already */
	for (i = 0; i < nNodes; i++)
		size += IndexTupleSize(nodes[i]);

	/*
	 * Ensure that we can replace the tuple with a dead tuple later.  This
	 * test is unnecessary given current tuple layouts, but let's be safe.
	 */
	if (size < SGDTSIZE)
		size = SGDTSIZE;

	/*
	 * Inner tuple should be small enough to fit on a page
	 */
	if (size > SPGIST_PAGE_CAPACITY - sizeof(ItemIdData))
		ereport(ERROR,
				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
				 errmsg("SP-GiST inner tuple size %lu exceeds maximum %lu",
						(unsigned long) size,
				(unsigned long) (SPGIST_PAGE_CAPACITY - sizeof(ItemIdData))),
			errhint("Values larger than a buffer page cannot be indexed.")));

	/*
	 * Check for overflow of header fields --- probably can't fail if the
	 * above succeeded, but let's be paranoid
	 */
	if (size > SGITMAXSIZE ||
		prefixSize > SGITMAXPREFIXSIZE ||
		nNodes > SGITMAXNNODES)
		elog(ERROR, "SPGiST inner tuple header field is too small");

	/* OK, form the tuple */
	tup = (SpGistInnerTuple) palloc0(size);

	tup->nNodes = nNodes;
	tup->prefixSize = prefixSize;
	tup->size = size;

	if (hasPrefix)
		memcpyDatum(SGITDATAPTR(tup), &state->attPrefixType, prefix);

	ptr = (char *) SGITNODEPTR(tup);

	for (i = 0; i < nNodes; i++)
	{
		SpGistNodeTuple node = nodes[i];

		memcpy(ptr, node, IndexTupleSize(node));
		ptr += IndexTupleSize(node);
	}

	return tup;
}