3 * Functions to investigate BRIN indexes
5 * Copyright (c) 2014-2025, PostgreSQL Global Development Group
8 * contrib/pageinspect/brinfuncs.c
16#include "catalog/pg_am_d.h"
31 #define IS_BRIN(r) ((r)->rd_rel->relam == BRIN_AM_OID)
52 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
53 errmsg(
"must be superuser to use raw page functions")));
60 /* verify the special space has the expected size */
63 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
64 errmsg(
"input page is not a valid %s page",
"BRIN"),
65 errdetail(
"Expected special size %d, got %d.",
89 * Verify that the given bytea contains a BRIN page of the indicated page
90 * type, or die in the attempt. A pointer to the page is returned.
100 /* verify the special space has the expected size */
103 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
104 errmsg(
"input page is not a valid %s page",
"BRIN"),
105 errdetail(
"Expected special size %d, got %d.",
109 /* verify the special space says this page is what we want */
112 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
113 errmsg(
"page is not a BRIN page of type \"%s\"", strtype),
114 errdetail(
"Expected special type %08x, got %08x.",
120/* Number of output arguments (columns) for brin_page_items() */
121 #define BRIN_PAGE_ITEMS_V1_12 8
124 * Extract all item values from a BRIN index page
126 * Usage: SELECT * FROM brin_page_items(get_raw_page('idx', 1), 'idx'::regclass);
145 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
146 errmsg(
"must be superuser to use raw page functions")));
151 * Version 1.12 added a new output column for the empty range flag. But as
152 * it was added in the middle, it may cause crashes with function
153 * definitions from older versions of the extension.
155 * There is no way to reliably avoid the problems created by the old
156 * function definition at this point, so insist that the user update the
161 (
errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
162 errmsg(
"function has wrong number of declared columns"),
163 errhint(
"To resolve the problem, update the \"pageinspect\" extension to the latest version.")));
169 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
170 errmsg(
"\"%s\" is not a %s index",
175 /* minimally verify the page we got */
186 * Initialize output functions for all indexed datatypes; simplifies
187 * calling them later.
190 for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
198 opcinfo = bdesc->bd_info[attno - 1];
209 columns[attno - 1] = column;
221 * This loop is called once for every attribute of every tuple in the
222 * page. At the start of a tuple, we get a NULL dtup; that's our
223 * signal for obtaining and decoding the next one. If that's not the
224 * case, we output the next attribute.
230 /* verify item status: if there's no data, we can't decode */
268 /* support for old extension version */
279 if (!dtup->bt_columns[att].bv_allnulls)
290 for (
i = 0;
i < columns[att]->nstored;
i++)
316 * If the item was unused, jump straight to the next one; otherwise,
317 * the only cleanup needed here is to set our signal to go to the next
318 * tuple in the following iteration, by freeing the current one.
322 else if (attno >= bdesc->bd_tupdesc->natts)
330 * If we're beyond the end of the page, we're done.
355 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
356 errmsg(
"must be superuser to use raw page functions")));
363 /* Build a tuple descriptor for our result type */
365 elog(
ERROR,
"return type must be a row type");
368 /* Extract values from the metapage */
381 * Return the TID array stored in a BRIN revmap page
395 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
396 errmsg(
"must be superuser to use raw page functions")));
404 /* create a function context for cross-call persistence */
407 /* switch to memory context appropriate for multiple function calls */
410 /* minimally verify the page we got */
Datum idx(PG_FUNCTION_ARGS)
static Datum values[MAXATTR]
void brin_free_desc(BrinDesc *bdesc)
BrinDesc * brin_build_desc(Relation rel)
#define BRIN_PAGETYPE_REVMAP
#define BRIN_PAGETYPE_REGULAR
#define BRIN_PAGETYPE_META
#define BrinPageType(page)
#define REVMAP_PAGE_MAXITEMS
BrinMemTuple * brin_deform_tuple(BrinDesc *brdesc, BrinTuple *tuple, BrinMemTuple *dMemtuple)
Datum brin_revmap_data(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(brin_page_type)
struct brin_column_state brin_column_state
Datum brin_metapage_info(PG_FUNCTION_ARGS)
#define BRIN_PAGE_ITEMS_V1_12
Datum brin_page_type(PG_FUNCTION_ARGS)
static Page verify_brin_page(bytea *raw_page, uint16 type, const char *strtype)
Datum brin_page_items(PG_FUNCTION_ARGS)
static uint16 PageGetSpecialSize(const PageData *page)
static Item PageGetItem(const PageData *page, const ItemIdData *itemId)
static bool PageIsNew(const PageData *page)
static char * PageGetContents(Page page)
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
static OffsetNumber PageGetMaxOffsetNumber(const PageData *page)
#define CStringGetTextDatum(s)
#define FLEXIBLE_ARRAY_MEMBER
int errdetail(const char *fmt,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
void fmgr_info(Oid functionId, FmgrInfo *finfo)
char * OutputFunctionCall(FmgrInfo *flinfo, Datum val)
#define PG_RETURN_TEXT_P(x)
#define PG_RETURN_DATUM(x)
#define PG_GETARG_BYTEA_P(n)
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
#define SRF_IS_FIRSTCALL()
#define SRF_PERCALL_SETUP()
#define SRF_RETURN_NEXT(_funcctx, _result)
#define SRF_FIRSTCALL_INIT()
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
#define SRF_RETURN_DONE(_funcctx)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
void index_close(Relation relation, LOCKMODE lockmode)
Relation index_open(Oid relationId, LOCKMODE lockmode)
if(TABLE==NULL||TABLE_index==NULL)
#define ItemIdIsUsed(itemId)
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
void pfree(void *pointer)
#define OffsetNumberNext(offsetNumber)
#define FirstOffsetNumber
Page get_page_from_raw(bytea *raw_page)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
static Datum Int64GetDatum(int64 X)
static Datum PointerGetDatum(const void *X)
static Datum UInt16GetDatum(uint16 X)
static Datum BoolGetDatum(bool X)
static Datum Int32GetDatum(int32 X)
static Datum UInt32GetDatum(uint32 X)
char * psprintf(const char *fmt,...)
#define RelationGetDescr(relation)
#define RelationGetRelationName(relation)
void appendStringInfoString(StringInfo str, const char *s)
void appendStringInfoChar(StringInfo str, char ch)
void initStringInfo(StringInfo str)
BlockNumber lastRevmapPage
BlockNumber pagesPerRange
TypeCacheEntry * oi_typcache[FLEXIBLE_ARRAY_MEMBER]
MemoryContext multi_call_memory_ctx
Tuplestorestate * setResult
FmgrInfo outputFn[FLEXIBLE_ARRAY_MEMBER]
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
text * cstring_to_text(const char *s)