PostgreSQL Source Code git master
Loading...
Searching...
No Matches
gistfuncs.c
Go to the documentation of this file.
1/*
2 * gistfuncs.c
3 * Functions to investigate the content of GiST indexes
4 *
5 * Copyright (c) 2014-2026, PostgreSQL Global Development Group
6 *
7 * IDENTIFICATION
8 * contrib/pageinspect/gistfuncs.c
9 */
10#include "postgres.h"
11
12#include "access/genam.h"
13#include "access/gist.h"
14#include "access/htup.h"
15#include "access/htup_details.h"
16#include "access/relation.h"
17#include "catalog/pg_am_d.h"
18#include "funcapi.h"
19#include "miscadmin.h"
20#include "pageinspect.h"
21#include "storage/itemptr.h"
22#include "utils/array.h"
23#include "utils/builtins.h"
24#include "utils/lsyscache.h"
25#include "utils/pg_lsn.h"
26#include "utils/rel.h"
27#include "utils/ruleutils.h"
28
32
33#define IS_GIST(r) ((r)->rd_rel->relam == GIST_AM_OID)
34
35
37
38/*
39 * Verify that the given bytea contains a GIST page or die in the attempt.
40 * A pointer to the page is returned.
41 */
42static Page
44{
47
48 if (PageIsNew(page))
49 return page;
50
51 /* verify the special space has the expected size */
55 errmsg("input page is not a valid %s page", "GiST"),
56 errdetail("Expected special size %d, got %d.",
57 (int) MAXALIGN(sizeof(GISTPageOpaqueData)),
58 (int) PageGetSpecialSize(page))));
59
60 opaq = GistPageGetOpaque(page);
61 if (opaq->gist_page_id != GIST_PAGE_ID)
64 errmsg("input page is not a valid %s page", "GiST"),
65 errdetail("Expected %08x, got %08x.",
67 opaq->gist_page_id)));
68
69 return page;
70}
71
74{
76 TupleDesc tupdesc;
77 Page page;
79 Datum values[4];
80 bool nulls[4];
81 Datum flags[16];
82 int nflags = 0;
84
85 if (!superuser())
88 errmsg("must be superuser to use raw page functions")));
89
91
92 if (PageIsNew(page))
94
95 /* Build a tuple descriptor for our result type */
96 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
97 elog(ERROR, "return type must be a row type");
98
99 /* Convert the flags bitmask to an array of human-readable names */
100 flagbits = GistPageGetOpaque(page)->flags;
101 if (flagbits & F_LEAF)
102 flags[nflags++] = CStringGetTextDatum("leaf");
103 if (flagbits & F_DELETED)
104 flags[nflags++] = CStringGetTextDatum("deleted");
106 flags[nflags++] = CStringGetTextDatum("tuples_deleted");
108 flags[nflags++] = CStringGetTextDatum("follow_right");
110 flags[nflags++] = CStringGetTextDatum("has_garbage");
112 if (flagbits)
113 {
114 /* any flags we don't recognize are printed in hex */
116 }
117
118 memset(nulls, 0, sizeof(nulls));
119
120 values[0] = LSNGetDatum(PageGetLSN(page));
122 values[2] = Int64GetDatum(GistPageGetOpaque(page)->rightlink);
124
125 /* Build and return the result tuple. */
126 resultTuple = heap_form_tuple(tupdesc, values, nulls);
127
129}
130
131Datum
133{
135 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
136 Page page;
137 OffsetNumber offset;
139
140 if (!superuser())
143 errmsg("must be superuser to use raw page functions")));
144
145 InitMaterializedSRF(fcinfo, 0);
146
148
149 if (PageIsNew(page))
151
152 /* Avoid bogus PageGetMaxOffsetNumber() call with deleted pages */
153 if (GistPageIsDeleted(page))
154 elog(NOTICE, "page is deleted");
155 else
156 maxoff = PageGetMaxOffsetNumber(page);
157
158 for (offset = FirstOffsetNumber;
159 offset <= maxoff;
160 offset++)
161 {
162 Datum values[5];
163 bool nulls[5];
164 ItemId id;
165 IndexTuple itup;
167 int tuple_len;
168
169 id = PageGetItemId(page, offset);
170
171 if (!ItemIdIsValid(id))
172 elog(ERROR, "invalid ItemId");
173
174 itup = (IndexTuple) PageGetItem(page, id);
175 tuple_len = IndexTupleSize(itup);
176
177 memset(nulls, 0, sizeof(nulls));
178
179 values[0] = UInt16GetDatum(offset);
180 values[1] = ItemPointerGetDatum(&itup->t_tid);
181 values[2] = Int32GetDatum((int) IndexTupleSize(itup));
182
183 tuple_bytea = (bytea *) palloc(tuple_len + VARHDRSZ);
184 SET_VARSIZE(tuple_bytea, tuple_len + VARHDRSZ);
185 memcpy(VARDATA(tuple_bytea), itup, tuple_len);
188
189 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
190 }
191
192 return (Datum) 0;
193}
194
195Datum
197{
200 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
201 Relation indexRel;
202 TupleDesc tupdesc;
203 Page page;
205 bits16 printflags = 0;
206 OffsetNumber offset;
208 char *index_columns;
209
210 if (!superuser())
213 errmsg("must be superuser to use raw page functions")));
214
215 InitMaterializedSRF(fcinfo, 0);
216
217 /* Open the relation */
219
220 if (!IS_GIST(indexRel))
223 errmsg("\"%s\" is not a %s index",
224 RelationGetRelationName(indexRel), "GiST")));
225
227
228 if (PageIsNew(page))
229 {
230 index_close(indexRel, AccessShareLock);
232 }
233
234 flagbits = GistPageGetOpaque(page)->flags;
235
236 /*
237 * Included attributes are added when dealing with leaf pages, discarded
238 * for non-leaf pages as these include only data for key attributes.
239 */
241 if (flagbits & F_LEAF)
242 {
243 tupdesc = RelationGetDescr(indexRel);
244 }
245 else
246 {
250 }
251
253 printflags);
254
255 /* Avoid bogus PageGetMaxOffsetNumber() call with deleted pages */
256 if (GistPageIsDeleted(page))
257 elog(NOTICE, "page is deleted");
258 else
259 maxoff = PageGetMaxOffsetNumber(page);
260
261 for (offset = FirstOffsetNumber;
262 offset <= maxoff;
263 offset++)
264 {
265 Datum values[5];
266 bool nulls[5];
267 ItemId id;
268 IndexTuple itup;
272 int i;
273
274 id = PageGetItemId(page, offset);
275
276 if (!ItemIdIsValid(id))
277 elog(ERROR, "invalid ItemId");
278
279 itup = (IndexTuple) PageGetItem(page, id);
280
281 index_deform_tuple(itup, tupdesc,
283
284 memset(nulls, 0, sizeof(nulls));
285
286 values[0] = UInt16GetDatum(offset);
287 values[1] = ItemPointerGetDatum(&itup->t_tid);
288 values[2] = Int32GetDatum((int) IndexTupleSize(itup));
290
291 if (index_columns)
292 {
295
296 /* Most of this is copied from record_out(). */
297 for (i = 0; i < tupdesc->natts; i++)
298 {
299 char *value;
300 char *tmp;
301 bool nq = false;
302
303 if (itup_isnull[i])
304 value = "null";
305 else
306 {
307 Oid foutoid;
308 bool typisvarlena;
309 Oid typoid;
310
311 typoid = TupleDescAttr(tupdesc, i)->atttypid;
312 getTypeOutputInfo(typoid, &foutoid, &typisvarlena);
314 }
315
317 appendStringInfoString(&buf, ") INCLUDE (");
318 else if (i > 0)
320
321 /* Check whether we need double quotes for this value */
322 nq = (value[0] == '\0'); /* force quotes for empty string */
323 for (tmp = value; *tmp; tmp++)
324 {
325 char ch = *tmp;
326
327 if (ch == '"' || ch == '\\' ||
328 ch == '(' || ch == ')' || ch == ',' ||
329 isspace((unsigned char) ch))
330 {
331 nq = true;
332 break;
333 }
334 }
335
336 /* And emit the string */
337 if (nq)
339 for (tmp = value; *tmp; tmp++)
340 {
341 char ch = *tmp;
342
343 if (ch == '"' || ch == '\\')
346 }
347 if (nq)
349 }
350
352
353 values[4] = CStringGetTextDatum(buf.data);
354 nulls[4] = false;
355 }
356 else
357 {
358 values[4] = (Datum) 0;
359 nulls[4] = true;
360 }
361
362 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
363 }
364
365 index_close(indexRel, AccessShareLock);
366
367 return (Datum) 0;
368}
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
static Datum values[MAXATTR]
Definition bootstrap.c:155
static uint16 PageGetSpecialSize(const PageData *page)
Definition bufpage.h:316
static bool PageIsNew(const PageData *page)
Definition bufpage.h:233
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
Definition bufpage.h:243
static void * PageGetItem(PageData *page, const ItemIdData *itemId)
Definition bufpage.h:353
PageData * Page
Definition bufpage.h:81
static XLogRecPtr PageGetLSN(const PageData *page)
Definition bufpage.h:385
static OffsetNumber PageGetMaxOffsetNumber(const PageData *page)
Definition bufpage.h:371
#define CStringGetTextDatum(s)
Definition builtins.h:97
uint16 bits16
Definition c.h:554
#define MAXALIGN(LEN)
Definition c.h:826
#define VARHDRSZ
Definition c.h:711
uint16_t uint16
Definition c.h:545
int errdetail(const char *fmt,...)
Definition elog.c:1216
int errcode(int sqlerrcode)
Definition elog.c:863
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define NOTICE
Definition elog.h:35
#define ereport(elevel,...)
Definition elog.h:150
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition fmgr.c:1763
#define PG_GETARG_OID(n)
Definition fmgr.h:275
#define DirectFunctionCall1(func, arg1)
Definition fmgr.h:684
#define PG_RETURN_NULL()
Definition fmgr.h:346
#define PG_FUNCTION_INFO_V1(funcname)
Definition fmgr.h:417
#define PG_GETARG_BYTEA_P(n)
Definition fmgr.h:336
#define PG_FUNCTION_ARGS
Definition fmgr.h:193
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
Definition funcapi.c:76
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
#define F_TUPLES_DELETED
Definition gist.h:51
#define GIST_PAGE_ID
Definition gist.h:112
#define F_LEAF
Definition gist.h:49
#define F_FOLLOW_RIGHT
Definition gist.h:52
#define GistPageIsDeleted(page)
Definition gist.h:173
#define GistPageGetOpaque(page)
Definition gist.h:168
#define F_HAS_GARBAGE
Definition gist.h:53
#define F_DELETED
Definition gist.h:50
#define GistPageGetNSN(page)
Definition gist.h:187
Datum gist_page_items_bytea(PG_FUNCTION_ARGS)
Definition gistfuncs.c:132
static Page verify_gist_page(bytea *raw_page)
Definition gistfuncs.c:43
#define IS_GIST(r)
Definition gistfuncs.c:33
Datum gist_page_items(PG_FUNCTION_ARGS)
Definition gistfuncs.c:196
Datum gist_page_opaque_info(PG_FUNCTION_ARGS)
Definition gistfuncs.c:73
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1117
void index_close(Relation relation, LOCKMODE lockmode)
Definition indexam.c:177
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition indexam.c:133
void index_deform_tuple(IndexTuple tup, TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition indextuple.c:456
static struct @172 value
int i
Definition isn.c:77
#define ItemIdIsDead(itemId)
Definition itemid.h:113
#define ItemIdIsValid(itemId)
Definition itemid.h:86
static Datum ItemPointerGetDatum(const ItemPointerData *X)
Definition itemptr.h:237
IndexTupleData * IndexTuple
Definition itup.h:53
static Size IndexTupleSize(const IndexTupleData *itup)
Definition itup.h:71
#define AccessShareLock
Definition lockdefs.h:36
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition lsyscache.c:3057
void * palloc(Size size)
Definition mcxt.c:1387
#define InvalidOffsetNumber
Definition off.h:26
uint16 OffsetNumber
Definition off.h:24
#define FirstOffsetNumber
Definition off.h:27
Page get_page_from_raw(bytea *raw_page)
Definition rawpage.c:218
#define INDEX_MAX_KEYS
static Datum LSNGetDatum(XLogRecPtr X)
Definition pg_lsn.h:31
static char buf[DEFAULT_XLOG_SEG_SIZE]
static Datum Int64GetDatum(int64 X)
Definition postgres.h:423
static Datum PointerGetDatum(const void *X)
Definition postgres.h:352
static Datum UInt16GetDatum(uint16 X)
Definition postgres.h:202
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
uint64_t Datum
Definition postgres.h:70
static Datum Int32GetDatum(int32 X)
Definition postgres.h:222
unsigned int Oid
static int fb(int x)
#define RelationGetDescr(relation)
Definition rel.h:540
#define RelationGetRelationName(relation)
Definition rel.h:548
#define IndexRelationGetNumberOfKeyAttributes(relation)
Definition rel.h:533
char * pg_get_indexdef_columns_extended(Oid indexrelid, bits16 flags)
Definition ruleutils.c:1249
#define RULE_INDEXDEF_PRETTY
Definition ruleutils.h:24
#define RULE_INDEXDEF_KEYS_ONLY
Definition ruleutils.h:25
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition stringinfo.c:145
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
#define appendStringInfoCharMacro(str, ch)
Definition stringinfo.h:231
ItemPointerData t_tid
Definition itup.h:37
Definition c.h:706
bool superuser(void)
Definition superuser.c:46
TupleDesc CreateTupleDescTruncatedCopy(TupleDesc tupdesc, int natts)
Definition tupdesc.c:296
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:160
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition tuplestore.c:784
static char * VARDATA(const void *PTR)
Definition varatt.h:305
static void SET_VARSIZE(void *PTR, Size len)
Definition varatt.h:432
Datum to_hex32(PG_FUNCTION_ARGS)
Definition varlena.c:4076