Line data Source code
1 : /*--------------------------------------------------------------------------
2 : *
3 : * test_ginpostinglist.c
4 : * Test varbyte-encoding in ginpostinglist.c
5 : *
6 : * Copyright (c) 2019-2024, PostgreSQL Global Development Group
7 : *
8 : * IDENTIFICATION
9 : * src/test/modules/test_ginpostinglist/test_ginpostinglist.c
10 : *
11 : * -------------------------------------------------------------------------
12 : */
13 : #include "postgres.h"
14 :
15 : #include "access/gin_private.h"
16 : #include "access/ginblock.h"
17 : #include "access/htup_details.h"
18 : #include "fmgr.h"
19 :
20 2 : PG_MODULE_MAGIC;
21 :
22 4 : PG_FUNCTION_INFO_V1(test_ginpostinglist);
23 :
24 : /*
25 : * Encodes a pair of TIDs, and decodes it back. The first TID is always
26 : * (0, 1), the second one is formed from the blk/off arguments. The 'maxsize'
27 : * argument is passed to ginCompressPostingList(); it can be used to test the
28 : * overflow checks.
29 : *
30 : * The reason that we test a pair, instead of just a single TID, is that
31 : * the GinPostingList stores the first TID as is, and the varbyte-encoding
32 : * is only used for the deltas between TIDs. So testing a single TID would
33 : * not exercise the varbyte encoding at all.
34 : *
35 : * This function prints NOTICEs to describe what is tested, and how large the
36 : * resulting GinPostingList is. Any incorrect results, e.g. if the encode +
37 : * decode round trip doesn't return the original input, are reported as
38 : * ERRORs.
39 : */
40 : static void
41 8 : test_itemptr_pair(BlockNumber blk, OffsetNumber off, int maxsize)
42 : {
43 : ItemPointerData orig_itemptrs[2];
44 : ItemPointer decoded_itemptrs;
45 : GinPostingList *pl;
46 : int nwritten;
47 : int ndecoded;
48 :
49 8 : elog(NOTICE, "testing with (%u, %d), (%u, %d), max %d bytes",
50 : 0, 1, blk, off, maxsize);
51 8 : ItemPointerSet(&orig_itemptrs[0], 0, 1);
52 8 : ItemPointerSet(&orig_itemptrs[1], blk, off);
53 :
54 : /* Encode, and decode it back */
55 8 : pl = ginCompressPostingList(orig_itemptrs, 2, maxsize, &nwritten);
56 8 : elog(NOTICE, "encoded %d item pointers to %zu bytes",
57 : nwritten, SizeOfGinPostingList(pl));
58 :
59 8 : if (SizeOfGinPostingList(pl) > maxsize)
60 0 : elog(ERROR, "overflow: result was %zu bytes, max %d",
61 : SizeOfGinPostingList(pl), maxsize);
62 :
63 8 : decoded_itemptrs = ginPostingListDecode(pl, &ndecoded);
64 8 : if (nwritten != ndecoded)
65 0 : elog(NOTICE, "encoded %d itemptrs, %d came back", nwritten, ndecoded);
66 :
67 : /* Check the result */
68 8 : if (!ItemPointerEquals(&orig_itemptrs[0], &decoded_itemptrs[0]))
69 0 : elog(ERROR, "mismatch on first itemptr: (%u, %d) vs (%u, %d)",
70 : 0, 1,
71 : ItemPointerGetBlockNumber(&decoded_itemptrs[0]),
72 : ItemPointerGetOffsetNumber(&decoded_itemptrs[0]));
73 :
74 8 : if (ndecoded == 2 &&
75 6 : !ItemPointerEquals(&orig_itemptrs[0], &decoded_itemptrs[0]))
76 : {
77 0 : elog(ERROR, "mismatch on second itemptr: (%u, %d) vs (%u, %d)",
78 : 0, 1,
79 : ItemPointerGetBlockNumber(&decoded_itemptrs[0]),
80 : ItemPointerGetOffsetNumber(&decoded_itemptrs[0]));
81 : }
82 8 : }
83 :
84 : /*
85 : * SQL-callable entry point to perform all tests.
86 : */
87 : Datum
88 2 : test_ginpostinglist(PG_FUNCTION_ARGS)
89 : {
90 2 : test_itemptr_pair(0, 2, 14);
91 2 : test_itemptr_pair(0, MaxHeapTuplesPerPage, 14);
92 2 : test_itemptr_pair(MaxBlockNumber, MaxHeapTuplesPerPage, 14);
93 2 : test_itemptr_pair(MaxBlockNumber, MaxHeapTuplesPerPage, 16);
94 :
95 2 : PG_RETURN_VOID();
96 : }
|