postgresql/src/test/modules/test_ginpostinglist/test_ginpostinglist.c

97 lines
3.0 KiB
C

/*--------------------------------------------------------------------------
*
* test_ginpostinglist.c
* Test varbyte-encoding in ginpostinglist.c
*
* Copyright (c) 2019, PostgreSQL Global Development Group
*
* IDENTIFICATION
* src/test/modules/test_ginpostinglist/test_ginpostinglist.c
*
* -------------------------------------------------------------------------
*/
#include "postgres.h"
#include "access/ginblock.h"
#include "access/gin_private.h"
#include "access/htup_details.h"
#include "fmgr.h"
PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(test_ginpostinglist);
/*
* Encodes a pair of TIDs, and decodes it back. The first TID is always
* (0, 1), the second one is formed from the blk/off arguments. The 'maxsize'
* argument is passed to ginCompressPostingList(); it can be used to test the
* overflow checks.
*
* The reason that we test a pair, instead of just a single TID, is that
* the GinPostingList stores the first TID as is, and the varbyte-encoding
* is only used for the deltas between TIDs. So testing a single TID would
* not exercise the varbyte encoding at all.
*
* This function prints NOTICEs to describe what is tested, and how large the
* resulting GinPostingList is. Any incorrect results, e.g. if the encode +
* decode round trip doesn't return the original input, are reported as
* ERRORs.
*/
static void
test_itemptr_pair(BlockNumber blk, OffsetNumber off, int maxsize)
{
ItemPointerData orig_itemptrs[2];
ItemPointer decoded_itemptrs;
GinPostingList *pl;
int nwritten;
int ndecoded;
elog(NOTICE, "testing with (%u, %d), (%u, %d), max %d bytes",
0, 1, blk, off, maxsize);
ItemPointerSet(&orig_itemptrs[0], 0, 1);
ItemPointerSet(&orig_itemptrs[1], blk, off);
/* Encode, and decode it back */
pl = ginCompressPostingList(orig_itemptrs, 2, maxsize, &nwritten);
elog(NOTICE, "encoded %d item pointers to %zu bytes",
nwritten, SizeOfGinPostingList(pl));
if (SizeOfGinPostingList(pl) > maxsize)
elog(ERROR, "overflow: result was %zu bytes, max %d",
SizeOfGinPostingList(pl), maxsize);
decoded_itemptrs = ginPostingListDecode(pl, &ndecoded);
if (nwritten != ndecoded)
elog(NOTICE, "encoded %d itemptrs, %d came back", nwritten, ndecoded);
/* Check the result */
if (!ItemPointerEquals(&orig_itemptrs[0], &decoded_itemptrs[0]))
elog(ERROR, "mismatch on first itemptr: (%u, %d) vs (%u, %d)",
0, 1,
ItemPointerGetBlockNumber(&decoded_itemptrs[0]),
ItemPointerGetOffsetNumber(&decoded_itemptrs[0]));
if (ndecoded == 2 &&
!ItemPointerEquals(&orig_itemptrs[0], &decoded_itemptrs[0]))
{
elog(ERROR, "mismatch on second itemptr: (%u, %d) vs (%u, %d)",
0, 1,
ItemPointerGetBlockNumber(&decoded_itemptrs[0]),
ItemPointerGetOffsetNumber(&decoded_itemptrs[0]));
}
}
/*
* SQL-callable entry point to perform all tests.
*/
Datum
test_ginpostinglist(PG_FUNCTION_ARGS)
{
test_itemptr_pair(0, 2, 14);
test_itemptr_pair(0, MaxHeapTuplesPerPage, 14);
test_itemptr_pair(MaxBlockNumber, MaxHeapTuplesPerPage, 14);
test_itemptr_pair(MaxBlockNumber, MaxHeapTuplesPerPage, 16);
PG_RETURN_VOID();
}