Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cherry-pick series of BRIN + AO commits until 63d916b0c3 #859

Merged
merged 7 commits into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion contrib/pageinspect/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ OBJS = \
rawpage.o

EXTENSION = pageinspect
DATA = pageinspect--1.8--1.9.sql \
DATA = pageinspect--1.8--1.9.sql \
pageinspect--1.7--1.8.sql pageinspect--1.6--1.7.sql \
pageinspect--1.5.sql pageinspect--1.5--1.6.sql \
pageinspect--1.4--1.5.sql pageinspect--1.3--1.4.sql \
Expand Down
138 changes: 92 additions & 46 deletions contrib/pageinspect/brinfuncs.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,20 @@
#include "lib/stringinfo.h"
#include "miscadmin.h"
#include "pageinspect.h"
#include "storage/bufmgr.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "miscadmin.h"

PG_FUNCTION_INFO_V1(brin_page_type);
PG_FUNCTION_INFO_V1(brin_page_items);
PG_FUNCTION_INFO_V1(brin_metapage_info);
PG_FUNCTION_INFO_V1(brin_revmap_data);
PG_FUNCTION_INFO_V1(brin_upper_data);

/* GPDB specific */
PG_FUNCTION_INFO_V1(brin_revmap_chain);

#define IS_BRIN(r) ((r)->rd_rel->relam == BRIN_AM_OID)

Expand Down Expand Up @@ -82,9 +86,6 @@ brin_page_type(PG_FUNCTION_ARGS)
case BRIN_PAGETYPE_REGULAR:
type = "regular";
break;
case BRIN_PAGETYPE_UPPER:
type = "upper";
break;
default:
type = psprintf("unknown (%02x)", BrinPageType(page));
break;
Expand Down Expand Up @@ -365,8 +366,11 @@ brin_metapage_info(PG_FUNCTION_ARGS)
Page page;
BrinMetaPageData *meta;
TupleDesc tupdesc;
Datum values[4];
bool nulls[4];
Datum values[8];
bool nulls[8];
Datum *firstrevmappages;
Datum *lastrevmappages;
Datum *lastrevmappagenums;
HeapTuple htup;

if (!superuser())
Expand All @@ -392,6 +396,41 @@ brin_metapage_info(PG_FUNCTION_ARGS)
values[2] = Int32GetDatum(meta->pagesPerRange);
values[3] = Int64GetDatum(meta->lastRevmapPage);

/* GPDB specific fields */
values[4] = Int64GetDatum(meta->isAo);
if (!meta->isAo)
{
nulls[5] = true;
nulls[6] = true;
nulls[7] = true;
}
else
{
firstrevmappages = palloc(sizeof(Datum) * MAX_AOREL_CONCURRENCY);
lastrevmappages = palloc(sizeof(Datum) * MAX_AOREL_CONCURRENCY);
lastrevmappagenums = palloc(sizeof(Datum) * MAX_AOREL_CONCURRENCY);

for (int i = 0; i < MAX_AOREL_CONCURRENCY; i++)
{
firstrevmappages[i] = UInt32GetDatum(meta->aoChainInfo[i].firstPage);
lastrevmappages[i] = UInt32GetDatum(meta->aoChainInfo[i].lastPage);
lastrevmappagenums[i] = UInt32GetDatum(meta->aoChainInfo[i].lastLogicalPageNum);
}

values[5] = PointerGetDatum(construct_array(firstrevmappages,
MAX_AOREL_CONCURRENCY,
INT8OID,
sizeof(int64), true, 'i'));
values[6] = PointerGetDatum(construct_array(lastrevmappages,
MAX_AOREL_CONCURRENCY,
INT8OID,
sizeof(int64), true, 'i'));
values[7] = PointerGetDatum(construct_array(lastrevmappagenums,
MAX_AOREL_CONCURRENCY,
INT8OID,
sizeof(int64), true, 'i'));
}

htup = heap_form_tuple(tupdesc, values, nulls);

PG_RETURN_DATUM(HeapTupleGetDatum(htup));
Expand Down Expand Up @@ -454,62 +493,69 @@ brin_revmap_data(PG_FUNCTION_ARGS)
SRF_RETURN_DONE(fctx);
}


/*
* Return the BlockNumber array stored in a BRIN upper page
* GPDB: Returns the chain of revmap block numbers for a given segno (aka block
* sequence).
*/
Datum
brin_upper_data(PG_FUNCTION_ARGS)
brin_revmap_chain(PG_FUNCTION_ARGS)
{
struct
{
BlockNumber *blks;
int idx;
} *state;
FuncCallContext *fctx;
ItemPointerData *tid;
bytea *raw_page = PG_GETARG_BYTEA_P(0);
Oid indexRelid = PG_GETARG_OID(1);
int segno = PG_GETARG_UINT32(2);
Page metapage;
BrinMetaPageData *meta;
ArrayBuildState *astate = NULL;
BlockNumber currRevmapBlk;

Relation indexRel = index_open(indexRelid, AccessShareLock);

if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
(errmsg("must be superuser to use raw page functions"))));

if (SRF_IS_FIRSTCALL())
{
bytea *raw_page = PG_GETARG_BYTEA_P(0);
MemoryContext mctx;
Page page;

/* minimally verify the page we got */
page = verify_brin_page(raw_page, BRIN_PAGETYPE_UPPER, "upper");
(errmsg("must be superuser to use raw page functions"))));

/* create a function context for cross-call persistence */
fctx = SRF_FIRSTCALL_INIT();

/* switch to memory context appropriate for multiple function calls */
mctx = MemoryContextSwitchTo(fctx->multi_call_memory_ctx);
if (!IS_BRIN(indexRel))
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" is not a %s index",
RelationGetRelationName(indexRel), "BRIN")));

state = palloc(sizeof(*state));
state->blks = ((RevmapUpperBlockContents *) PageGetContents(page))->rm_blocks;
state->idx = 0;
if (segno < 0 || segno > AOTupleId_MaxSegmentFileNum)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("\"%u\" is not a valid segno value (valid values are in [0,127])",
segno)));

fctx->user_fctx = state;
metapage = verify_brin_page(raw_page, BRIN_PAGETYPE_META, "metapage");

MemoryContextSwitchTo(mctx);
if (PageIsNew(metapage))
{
index_close(indexRel, AccessShareLock);
PG_RETURN_NULL();
}

fctx = SRF_PERCALL_SETUP();
state = fctx->user_fctx;
meta = (BrinMetaPageData *) PageGetContents(metapage);
currRevmapBlk = meta->aoChainInfo[segno].firstPage;
while (currRevmapBlk != InvalidBlockNumber)
{
/* Look at the chain link to see what the next revmap blknum is */
Buffer curr;

astate = accumArrayResult(astate, UInt32GetDatum(currRevmapBlk), false,
INT8OID, CurrentMemoryContext);

if (state->idx < REVMAP_UPPER_PAGE_MAXITEMS)
{
tid = (ItemPointerData*) palloc(sizeof(ItemPointerData));
ItemPointerSetBlockNumber(tid, (BlockNumber) state->blks[state->idx++]);
ItemPointerSetOffsetNumber(tid, (OffsetNumber) 0);
SRF_RETURN_NEXT(fctx, PointerGetDatum(tid));
curr = ReadBuffer(indexRel, currRevmapBlk);
LockBuffer(curr, BUFFER_LOCK_SHARE);
currRevmapBlk = BrinNextRevmapPage(BufferGetPage(curr));
UnlockReleaseBuffer(curr);
}

SRF_RETURN_DONE(fctx);
}
index_close(indexRel, AccessShareLock);

if (astate)
PG_RETURN_DATUM(makeArrayResult(astate,
CurrentMemoryContext));
else
PG_RETURN_NULL();
}
9 changes: 0 additions & 9 deletions contrib/pageinspect/pageinspect--1.5.sql
Original file line number Diff line number Diff line change
Expand Up @@ -213,15 +213,6 @@ RETURNS SETOF tid
AS 'MODULE_PATHNAME', 'brin_revmap_data'
LANGUAGE C STRICT PARALLEL SAFE;

--
-- brin_upper_data()
--
CREATE FUNCTION brin_upper_data(IN page bytea,
OUT pages tid)
RETURNS SETOF tid
AS 'MODULE_PATHNAME', 'brin_upper_data'
LANGUAGE C STRICT PARALLEL SAFE;

--
-- brin_page_items()
--
Expand Down
21 changes: 21 additions & 0 deletions contrib/pageinspect/pageinspect--1.8--1.9.sql
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,24 @@ CREATE FUNCTION brin_page_items(IN page bytea, IN index_oid regclass,
RETURNS SETOF record
AS 'MODULE_PATHNAME', 'brin_page_items'
LANGUAGE C STRICT PARALLEL SAFE;
-- brin_metapage_info()
--
DROP FUNCTION brin_metapage_info(IN page bytea, OUT magic text,
OUT version integer, OUT pagesperrange integer, OUT lastrevmappage bigint);
CREATE FUNCTION brin_metapage_info(IN page bytea, OUT magic text,
OUT version integer, OUT pagesperrange integer, OUT lastrevmappage bigint,
/* GPDB specific for AO/CO tables */
OUT isAo boolean,
OUT firstrevmappages bigint[],
OUT lastrevmappages bigint[],
OUT lastrevmappagenums bigint[])
AS 'MODULE_PATHNAME', 'brin_metapage_info'
LANGUAGE C STRICT PARALLEL SAFE;

--
-- brin_revmap_chain()
--
CREATE FUNCTION brin_revmap_chain(IN page bytea, IN indexrelid regclass, IN segno int)
RETURNS bigint[]
AS 'MODULE_PATHNAME', 'brin_revmap_chain'
LANGUAGE C STRICT PARALLEL SAFE;
11 changes: 5 additions & 6 deletions src/backend/access/aocs/aocsam_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -1849,14 +1849,13 @@ aoco_index_build_range_scan(Relation heapRelation,
while (aoco_getnextslot(&aocoscan->rs_base, ForwardScanDirection, slot))
{
bool tupleIsAlive;
BlockNumber blockno;
AOTupleId *aoTupleId;
BlockNumber currblockno = ItemPointerGetBlockNumber(&slot->tts_tid);

CHECK_FOR_INTERRUPTS();
blockno = ItemPointerGetBlockNumber(&slot->tts_tid);
if (blockno != lastBlock)
if (currblockno != lastBlock)
{
lastBlock = blockno;
lastBlock = currblockno;
++blockcounts;
}

Expand All @@ -1865,8 +1864,8 @@ aoco_index_build_range_scan(Relation heapRelation,
* we scan the whole table, and throw away tuples that are not in the
* range. That's clearly very inefficient.
*/
if (blockno < start_blockno ||
(numblocks != InvalidBlockNumber && blockno >= numblocks))
if (currblockno < start_blockno ||
(numblocks != InvalidBlockNumber && currblockno >= (start_blockno + numblocks)))
continue;

/* Report scan progress, if asked to. */
Expand Down
5 changes: 3 additions & 2 deletions src/backend/access/appendonly/appendonlyam_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -1692,6 +1692,7 @@ appendonly_index_build_range_scan(Relation heapRelation,
{
bool tupleIsAlive;
AOTupleId *aoTupleId;
BlockNumber currblockno = ItemPointerGetBlockNumber(&slot->tts_tid);

CHECK_FOR_INTERRUPTS();

Expand All @@ -1700,8 +1701,8 @@ appendonly_index_build_range_scan(Relation heapRelation,
* we scan the whole table, and throw away tuples that are not in the
* range. That's clearly very inefficient.
*/
if (ItemPointerGetBlockNumber(&slot->tts_tid) < start_blockno ||
(numblocks != InvalidBlockNumber && ItemPointerGetBlockNumber(&slot->tts_tid) >= numblocks))
if (currblockno < start_blockno ||
(numblocks != InvalidBlockNumber && currblockno >= (start_blockno + numblocks)))
continue;

if (progress)
Expand Down
Loading
Loading