PostgreSQL Source Code git master
Loading...
Searching...
No Matches
brinfuncs.c File Reference
#include "postgres.h"
#include "access/brin_internal.h"
#include "access/brin_page.h"
#include "access/brin_tuple.h"
#include "access/htup_details.h"
#include "catalog/pg_am_d.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "lib/stringinfo.h"
#include "miscadmin.h"
#include "pageinspect.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/tuplestore.h"
Include dependency graph for brinfuncs.c:

Go to the source code of this file.

Data Structures

struct  brin_column_state
 

Macros

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

Typedefs

typedef struct brin_column_state brin_column_state
 

Functions

 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)
 
static Page verify_brin_page (bytea *raw_page, uint16 type, const char *strtype)
 
Datum brin_page_type (PG_FUNCTION_ARGS)
 
Datum brin_page_items (PG_FUNCTION_ARGS)
 
Datum brin_metapage_info (PG_FUNCTION_ARGS)
 
Datum brin_revmap_data (PG_FUNCTION_ARGS)
 

Macro Definition Documentation

◆ BRIN_PAGE_ITEMS_V1_12

#define BRIN_PAGE_ITEMS_V1_12   8

Definition at line 122 of file brinfuncs.c.

◆ IS_BRIN

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

Definition at line 32 of file brinfuncs.c.

Typedef Documentation

◆ brin_column_state

Function Documentation

◆ brin_metapage_info()

Datum brin_metapage_info ( PG_FUNCTION_ARGS  )

Definition at line 344 of file brinfuncs.c.

345{
347 Page page;
348 BrinMetaPageData *meta;
349 TupleDesc tupdesc;
350 Datum values[4];
351 bool nulls[4] = {0};
352 HeapTuple htup;
353
354 if (!superuser())
357 errmsg("must be superuser to use raw page functions")));
358
359 page = verify_brin_page(raw_page, BRIN_PAGETYPE_META, "metapage");
360
361 if (PageIsNew(page))
363
364 /* Build a tuple descriptor for our result type */
365 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
366 elog(ERROR, "return type must be a row type");
367 tupdesc = BlessTupleDesc(tupdesc);
368
369 /* Extract values from the metapage */
370 meta = (BrinMetaPageData *) PageGetContents(page);
371 values[0] = CStringGetTextDatum(psprintf("0x%08X", meta->brinMagic));
372 values[1] = Int32GetDatum(meta->brinVersion);
375
376 htup = heap_form_tuple(tupdesc, values, nulls);
377
379}
static Datum values[MAXATTR]
Definition bootstrap.c:188
#define BRIN_PAGETYPE_META
Definition brin_page.h:51
static Page verify_brin_page(bytea *raw_page, uint16 type, const char *strtype)
Definition brinfuncs.c:94
static bool PageIsNew(const PageData *page)
Definition bufpage.h:259
static char * PageGetContents(Page page)
Definition bufpage.h:283
PageData * Page
Definition bufpage.h:81
#define CStringGetTextDatum(s)
Definition builtins.h:98
int errcode(int sqlerrcode)
Definition elog.c:874
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define ereport(elevel,...)
Definition elog.h:150
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
#define PG_RETURN_NULL()
Definition fmgr.h:346
#define PG_RETURN_DATUM(x)
Definition fmgr.h:354
#define PG_GETARG_BYTEA_P(n)
Definition fmgr.h:336
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition funcapi.c:276
@ TYPEFUNC_COMPOSITE
Definition funcapi.h:149
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
Definition funcapi.h:230
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1037
static char * errmsg
static Datum Int64GetDatum(int64 X)
Definition postgres.h:413
uint64_t Datum
Definition postgres.h:70
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212
static int fb(int x)
char * psprintf(const char *fmt,...)
Definition psprintf.c:43
uint32 brinVersion
Definition brin_page.h:67
BlockNumber lastRevmapPage
Definition brin_page.h:69
BlockNumber pagesPerRange
Definition brin_page.h:68
Definition c.h:778
bool superuser(void)
Definition superuser.c:47

References BlessTupleDesc(), BRIN_PAGETYPE_META, BrinMetaPageData::brinMagic, BrinMetaPageData::brinVersion, CStringGetTextDatum, elog, ereport, errcode(), errmsg, ERROR, fb(), get_call_result_type(), heap_form_tuple(), HeapTupleGetDatum(), Int32GetDatum(), Int64GetDatum(), BrinMetaPageData::lastRevmapPage, PageGetContents(), PageIsNew(), BrinMetaPageData::pagesPerRange, PG_GETARG_BYTEA_P, PG_RETURN_DATUM, PG_RETURN_NULL, psprintf(), superuser(), TYPEFUNC_COMPOSITE, values, and verify_brin_page().

◆ brin_page_items()

Datum brin_page_items ( PG_FUNCTION_ARGS  )

Definition at line 130 of file brinfuncs.c.

131{
134 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
135 Relation indexRel;
136 brin_column_state **columns;
139 Page page;
140 OffsetNumber offset;
141 AttrNumber attno;
142 bool unusedItem;
143
144 if (!superuser())
147 errmsg("must be superuser to use raw page functions")));
148
149 InitMaterializedSRF(fcinfo, 0);
150
151 /*
152 * Version 1.12 added a new output column for the empty range flag. But as
153 * it was added in the middle, it may cause crashes with function
154 * definitions from older versions of the extension.
155 *
156 * There is no way to reliably avoid the problems created by the old
157 * function definition at this point, so insist that the user update the
158 * extension.
159 */
160 if (rsinfo->setDesc->natts < BRIN_PAGE_ITEMS_V1_12)
163 errmsg("function has wrong number of declared columns"),
164 errhint("To resolve the problem, update the \"pageinspect\" extension to the latest version.")));
165
167
168 if (!IS_BRIN(indexRel))
171 errmsg("\"%s\" is not a %s index",
172 RelationGetRelationName(indexRel), "BRIN")));
173
174 bdesc = brin_build_desc(indexRel);
175
176 /* minimally verify the page we got */
178
179 if (PageIsNew(page))
180 {
182 index_close(indexRel, AccessShareLock);
184 }
185
186 /*
187 * Initialize output functions for all indexed datatypes; simplifies
188 * calling them later.
189 */
190 columns = palloc_array(brin_column_state *, RelationGetDescr(indexRel)->natts);
191 for (attno = 1; attno <= bdesc->bd_tupdesc->natts; attno++)
192 {
193 Oid output;
194 bool isVarlena;
196 int i;
198
199 opcinfo = bdesc->bd_info[attno - 1];
201 sizeof(FmgrInfo) * opcinfo->oi_nstored);
202
203 column->nstored = opcinfo->oi_nstored;
204 for (i = 0; i < opcinfo->oi_nstored; i++)
205 {
206 getTypeOutputInfo(opcinfo->oi_typcache[i]->type_id, &output, &isVarlena);
207 fmgr_info(output, &column->outputFn[i]);
208 }
209
210 columns[attno - 1] = column;
211 }
212
213 offset = FirstOffsetNumber;
214 unusedItem = false;
215 dtup = NULL;
216 for (;;)
217 {
218 Datum values[8];
219 bool nulls[8] = {0};
220
221 /*
222 * This loop is called once for every attribute of every tuple in the
223 * page. At the start of a tuple, we get a NULL dtup; that's our
224 * signal for obtaining and decoding the next one. If that's not the
225 * case, we output the next attribute.
226 */
227 if (dtup == NULL)
228 {
230
231 /* verify item status: if there's no data, we can't decode */
232 itemId = PageGetItemId(page, offset);
233 if (ItemIdIsUsed(itemId))
234 {
236 (BrinTuple *) PageGetItem(page, itemId),
237 NULL);
238 attno = 1;
239 unusedItem = false;
240 }
241 else
242 unusedItem = true;
243 }
244 else
245 attno++;
246
247 if (unusedItem)
248 {
249 values[0] = UInt16GetDatum(offset);
250 nulls[1] = true;
251 nulls[2] = true;
252 nulls[3] = true;
253 nulls[4] = true;
254 nulls[5] = true;
255 nulls[6] = true;
256 nulls[7] = true;
257 }
258 else
259 {
260 int att = attno - 1;
261
262 values[0] = UInt16GetDatum(offset);
263 switch (TupleDescAttr(rsinfo->setDesc, 1)->atttypid)
264 {
265 case INT8OID:
266 values[1] = Int64GetDatum((int64) dtup->bt_blkno);
267 break;
268 case INT4OID:
269 /* support for old extension version */
270 values[1] = UInt32GetDatum(dtup->bt_blkno);
271 break;
272 default:
273 elog(ERROR, "incorrect output types");
274 }
275 values[2] = UInt16GetDatum(attno);
276 values[3] = BoolGetDatum(dtup->bt_columns[att].bv_allnulls);
277 values[4] = BoolGetDatum(dtup->bt_columns[att].bv_hasnulls);
278 values[5] = BoolGetDatum(dtup->bt_placeholder);
279 values[6] = BoolGetDatum(dtup->bt_empty_range);
280 if (!dtup->bt_columns[att].bv_allnulls)
281 {
282 BrinValues *bvalues = &dtup->bt_columns[att];
284 bool first;
285 int i;
286
287 initStringInfo(&s);
288 appendStringInfoChar(&s, '{');
289
290 first = true;
291 for (i = 0; i < columns[att]->nstored; i++)
292 {
293 char *val;
294
295 if (!first)
296 appendStringInfoString(&s, " .. ");
297 first = false;
298 val = OutputFunctionCall(&columns[att]->outputFn[i],
299 bvalues->bv_values[i]);
301 pfree(val);
302 }
303 appendStringInfoChar(&s, '}');
304
306 pfree(s.data);
307 }
308 else
309 {
310 nulls[7] = true;
311 }
312 }
313
314 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
315
316 /*
317 * If the item was unused, jump straight to the next one; otherwise,
318 * the only cleanup needed here is to set our signal to go to the next
319 * tuple in the following iteration, by freeing the current one.
320 */
321 if (unusedItem)
322 offset = OffsetNumberNext(offset);
323 else if (attno >= bdesc->bd_tupdesc->natts)
324 {
325 pfree(dtup);
326 dtup = NULL;
327 offset = OffsetNumberNext(offset);
328 }
329
330 /*
331 * If we're beyond the end of the page, we're done.
332 */
333 if (offset > PageGetMaxOffsetNumber(page))
334 break;
335 }
336
338 index_close(indexRel, AccessShareLock);
339
340 return (Datum) 0;
341}
int16 AttrNumber
Definition attnum.h:21
void brin_free_desc(BrinDesc *bdesc)
Definition brin.c:1641
BrinDesc * brin_build_desc(Relation rel)
Definition brin.c:1586
#define BRIN_PAGETYPE_REGULAR
Definition brin_page.h:53
BrinMemTuple * brin_deform_tuple(BrinDesc *brdesc, BrinTuple *tuple, BrinMemTuple *dMemtuple)
Definition brin_tuple.c:553
#define BRIN_PAGE_ITEMS_V1_12
Definition brinfuncs.c:122
#define IS_BRIN(r)
Definition brinfuncs.c:32
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
Definition bufpage.h:269
static void * PageGetItem(PageData *page, const ItemIdData *itemId)
Definition bufpage.h:379
static OffsetNumber PageGetMaxOffsetNumber(const PageData *page)
Definition bufpage.h:397
int64_t int64
Definition c.h:615
int errhint(const char *fmt,...) pg_attribute_printf(1
#define palloc_array(type, count)
Definition fe_memutils.h:76
void fmgr_info(Oid functionId, FmgrInfo *finfo)
Definition fmgr.c:129
char * OutputFunctionCall(FmgrInfo *flinfo, Datum val)
Definition fmgr.c:1684
#define PG_GETARG_OID(n)
Definition fmgr.h:275
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
Definition funcapi.c:76
FILE * output
void index_close(Relation relation, LOCKMODE lockmode)
Definition indexam.c:177
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition indexam.c:133
long val
Definition informix.c:689
int i
Definition isn.c:77
#define ItemIdIsUsed(itemId)
Definition itemid.h:92
#define AccessShareLock
Definition lockdefs.h:36
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition lsyscache.c:3129
void pfree(void *pointer)
Definition mcxt.c:1616
void * palloc(Size size)
Definition mcxt.c:1387
#define OffsetNumberNext(offsetNumber)
Definition off.h:52
uint16 OffsetNumber
Definition off.h:24
#define FirstOffsetNumber
Definition off.h:27
static Datum UInt16GetDatum(uint16 X)
Definition postgres.h:192
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
static Datum UInt32GetDatum(uint32 X)
Definition postgres.h:232
unsigned int Oid
#define RelationGetDescr(relation)
Definition rel.h:540
#define RelationGetRelationName(relation)
Definition rel.h:548
void appendStringInfoString(StringInfo str, const char *s)
Definition stringinfo.c:230
void appendStringInfoChar(StringInfo str, char ch)
Definition stringinfo.c:242
void initStringInfo(StringInfo str)
Definition stringinfo.c:97
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:178
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition tuplestore.c:785

References AccessShareLock, appendStringInfoChar(), appendStringInfoString(), BoolGetDatum(), brin_build_desc(), brin_deform_tuple(), brin_free_desc(), BRIN_PAGE_ITEMS_V1_12, BRIN_PAGETYPE_REGULAR, CStringGetTextDatum, StringInfoData::data, elog, ereport, errcode(), errhint(), errmsg, ERROR, fb(), FirstOffsetNumber, fmgr_info(), getTypeOutputInfo(), i, index_close(), index_open(), InitMaterializedSRF(), initStringInfo(), Int64GetDatum(), IS_BRIN, ItemIdIsUsed, brin_column_state::nstored, OffsetNumberNext, output, OutputFunctionCall(), PageGetItem(), PageGetItemId(), PageGetMaxOffsetNumber(), PageIsNew(), palloc(), palloc_array, pfree(), PG_GETARG_BYTEA_P, PG_GETARG_OID, PG_RETURN_NULL, RelationGetDescr, RelationGetRelationName, superuser(), TupleDescAttr(), tuplestore_putvalues(), UInt16GetDatum(), UInt32GetDatum(), val, values, and verify_brin_page().

◆ brin_page_type()

Datum brin_page_type ( PG_FUNCTION_ARGS  )

Definition at line 45 of file brinfuncs.c.

46{
48 Page page;
49 char *type;
50
51 if (!superuser())
54 errmsg("must be superuser to use raw page functions")));
55
57
58 if (PageIsNew(page))
60
61 /* verify the special space has the expected size */
62 if (PageGetSpecialSize(page) != MAXALIGN(sizeof(BrinSpecialSpace)))
65 errmsg("input page is not a valid %s page", "BRIN"),
66 errdetail("Expected special size %d, got %d.",
67 (int) MAXALIGN(sizeof(BrinSpecialSpace)),
68 (int) PageGetSpecialSize(page))));
69
70 switch (BrinPageType(page))
71 {
73 type = "meta";
74 break;
76 type = "revmap";
77 break;
79 type = "regular";
80 break;
81 default:
82 type = psprintf("unknown (%02x)", BrinPageType(page));
83 break;
84 }
85
87}
#define BRIN_PAGETYPE_REVMAP
Definition brin_page.h:52
#define BrinPageType(page)
Definition brin_page.h:42
static uint16 PageGetSpecialSize(const PageData *page)
Definition bufpage.h:342
#define MAXALIGN(LEN)
Definition c.h:898
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define PG_RETURN_TEXT_P(x)
Definition fmgr.h:374
Page get_page_from_raw(bytea *raw_page)
Definition rawpage.c:216
text * cstring_to_text(const char *s)
Definition varlena.c:184
const char * type

References BRIN_PAGETYPE_META, BRIN_PAGETYPE_REGULAR, BRIN_PAGETYPE_REVMAP, BrinPageType, cstring_to_text(), ereport, errcode(), errdetail(), errmsg, ERROR, fb(), get_page_from_raw(), MAXALIGN, PageGetSpecialSize(), PageIsNew(), PG_GETARG_BYTEA_P, PG_RETURN_NULL, PG_RETURN_TEXT_P, psprintf(), superuser(), and type.

◆ brin_revmap_data()

Datum brin_revmap_data ( PG_FUNCTION_ARGS  )

Definition at line 385 of file brinfuncs.c.

386{
387 struct
388 {
389 ItemPointerData *tids;
390 int idx;
391 } *state;
393
394 if (!superuser())
397 errmsg("must be superuser to use raw page functions")));
398
399 if (SRF_IS_FIRSTCALL())
400 {
403 Page page;
404
405 /* create a function context for cross-call persistence */
407
408 /* switch to memory context appropriate for multiple function calls */
409 mctx = MemoryContextSwitchTo(fctx->multi_call_memory_ctx);
410
411 /* minimally verify the page we got */
413
414 if (PageIsNew(page))
415 {
418 }
419
420 state = palloc(sizeof(*state));
421 state->tids = ((RevmapContents *) PageGetContents(page))->rm_tids;
422 state->idx = 0;
423
424 fctx->user_fctx = state;
425
427 }
428
430 state = fctx->user_fctx;
431
432 if (state->idx < REVMAP_PAGE_MAXITEMS)
434
436}
Datum idx(PG_FUNCTION_ARGS)
Definition _int_op.c:262
#define REVMAP_PAGE_MAXITEMS
Definition brin_page.h:93
#define SRF_IS_FIRSTCALL()
Definition funcapi.h:304
#define SRF_PERCALL_SETUP()
Definition funcapi.h:308
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition funcapi.h:310
#define SRF_FIRSTCALL_INIT()
Definition funcapi.h:306
#define SRF_RETURN_DONE(_funcctx)
Definition funcapi.h:328
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342

References BRIN_PAGETYPE_REVMAP, ereport, errcode(), errmsg, ERROR, fb(), idx(), MemoryContextSwitchTo(), PageGetContents(), PageIsNew(), palloc(), PG_GETARG_BYTEA_P, PG_RETURN_NULL, PointerGetDatum(), REVMAP_PAGE_MAXITEMS, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, superuser(), and verify_brin_page().

◆ PG_FUNCTION_INFO_V1() [1/4]

PG_FUNCTION_INFO_V1 ( brin_metapage_info  )

◆ PG_FUNCTION_INFO_V1() [2/4]

PG_FUNCTION_INFO_V1 ( brin_page_items  )

◆ PG_FUNCTION_INFO_V1() [3/4]

PG_FUNCTION_INFO_V1 ( brin_page_type  )

◆ PG_FUNCTION_INFO_V1() [4/4]

PG_FUNCTION_INFO_V1 ( brin_revmap_data  )

◆ verify_brin_page()

static Page verify_brin_page ( bytea raw_page,
uint16  type,
const char strtype 
)
static

Definition at line 94 of file brinfuncs.c.

95{
97
98 if (PageIsNew(page))
99 return page;
100
101 /* verify the special space has the expected size */
102 if (PageGetSpecialSize(page) != MAXALIGN(sizeof(BrinSpecialSpace)))
105 errmsg("input page is not a valid %s page", "BRIN"),
106 errdetail("Expected special size %d, got %d.",
107 (int) MAXALIGN(sizeof(BrinSpecialSpace)),
108 (int) PageGetSpecialSize(page))));
109
110 /* verify the special space says this page is what we want */
111 if (BrinPageType(page) != type)
114 errmsg("page is not a BRIN page of type \"%s\"", strtype),
115 errdetail("Expected special type %08x, got %08x.",
116 type, BrinPageType(page))));
117
118 return page;
119}

References BrinPageType, ereport, errcode(), errdetail(), errmsg, ERROR, fb(), get_page_from_raw(), MAXALIGN, PageGetSpecialSize(), PageIsNew(), and type.

Referenced by brin_metapage_info(), brin_page_items(), and brin_revmap_data().