PostgreSQL Source Code  git master
gistfuncs.c File Reference
#include "postgres.h"
#include "access/gist.h"
#include "access/htup.h"
#include "access/relation.h"
#include "catalog/pg_am_d.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "pageinspect.h"
#include "storage/itemptr.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/pg_lsn.h"
#include "utils/rel.h"
#include "utils/ruleutils.h"
Include dependency graph for gistfuncs.c:

Go to the source code of this file.

Macros

#define IS_GIST(r)   ((r)->rd_rel->relam == GIST_AM_OID)
 

Functions

 PG_FUNCTION_INFO_V1 (gist_page_opaque_info)
 
 PG_FUNCTION_INFO_V1 (gist_page_items)
 
 PG_FUNCTION_INFO_V1 (gist_page_items_bytea)
 
static Page verify_gist_page (bytea *raw_page)
 
Datum gist_page_opaque_info (PG_FUNCTION_ARGS)
 
Datum gist_page_items_bytea (PG_FUNCTION_ARGS)
 
Datum gist_page_items (PG_FUNCTION_ARGS)
 

Macro Definition Documentation

◆ IS_GIST

#define IS_GIST (   r)    ((r)->rd_rel->relam == GIST_AM_OID)

Definition at line 31 of file gistfuncs.c.

Function Documentation

◆ gist_page_items()

Datum gist_page_items ( PG_FUNCTION_ARGS  )

Definition at line 194 of file gistfuncs.c.

195 {
196  bytea *raw_page = PG_GETARG_BYTEA_P(0);
197  Oid indexRelid = PG_GETARG_OID(1);
198  ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
199  Relation indexRel;
200  TupleDesc tupdesc;
201  Page page;
202  uint16 flagbits;
203  bits16 printflags = 0;
204  OffsetNumber offset;
206  char *index_columns;
207 
208  if (!superuser())
209  ereport(ERROR,
210  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
211  errmsg("must be superuser to use raw page functions")));
212 
213  InitMaterializedSRF(fcinfo, 0);
214 
215  /* Open the relation */
216  indexRel = index_open(indexRelid, AccessShareLock);
217 
218  if (!IS_GIST(indexRel))
219  ereport(ERROR,
220  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
221  errmsg("\"%s\" is not a %s index",
222  RelationGetRelationName(indexRel), "GiST")));
223 
224  page = verify_gist_page(raw_page);
225 
226  if (PageIsNew(page))
227  {
228  index_close(indexRel, AccessShareLock);
229  PG_RETURN_NULL();
230  }
231 
232  flagbits = GistPageGetOpaque(page)->flags;
233 
234  /*
235  * Included attributes are added when dealing with leaf pages, discarded
236  * for non-leaf pages as these include only data for key attributes.
237  */
238  printflags |= RULE_INDEXDEF_PRETTY;
239  if (flagbits & F_LEAF)
240  {
241  tupdesc = RelationGetDescr(indexRel);
242  }
243  else
244  {
245  tupdesc = CreateTupleDescCopy(RelationGetDescr(indexRel));
246  tupdesc->natts = IndexRelationGetNumberOfKeyAttributes(indexRel);
247  printflags |= RULE_INDEXDEF_KEYS_ONLY;
248  }
249 
250  index_columns = pg_get_indexdef_columns_extended(indexRelid,
251  printflags);
252 
253  /* Avoid bogus PageGetMaxOffsetNumber() call with deleted pages */
254  if (GistPageIsDeleted(page))
255  elog(NOTICE, "page is deleted");
256  else
257  maxoff = PageGetMaxOffsetNumber(page);
258 
259  for (offset = FirstOffsetNumber;
260  offset <= maxoff;
261  offset++)
262  {
263  Datum values[5];
264  bool nulls[5];
265  ItemId id;
266  IndexTuple itup;
267  Datum itup_values[INDEX_MAX_KEYS];
268  bool itup_isnull[INDEX_MAX_KEYS];
270  int i;
271 
272  id = PageGetItemId(page, offset);
273 
274  if (!ItemIdIsValid(id))
275  elog(ERROR, "invalid ItemId");
276 
277  itup = (IndexTuple) PageGetItem(page, id);
278 
279  index_deform_tuple(itup, tupdesc,
280  itup_values, itup_isnull);
281 
282  memset(nulls, 0, sizeof(nulls));
283 
284  values[0] = DatumGetInt16(offset);
285  values[1] = ItemPointerGetDatum(&itup->t_tid);
286  values[2] = Int32GetDatum((int) IndexTupleSize(itup));
287  values[3] = BoolGetDatum(ItemIdIsDead(id));
288 
289  if (index_columns)
290  {
292  appendStringInfo(&buf, "(%s)=(", index_columns);
293 
294  /* Most of this is copied from record_out(). */
295  for (i = 0; i < tupdesc->natts; i++)
296  {
297  char *value;
298  char *tmp;
299  bool nq = false;
300 
301  if (itup_isnull[i])
302  value = "null";
303  else
304  {
305  Oid foutoid;
306  bool typisvarlena;
307  Oid typoid;
308 
309  typoid = TupleDescAttr(tupdesc, i)->atttypid;
310  getTypeOutputInfo(typoid, &foutoid, &typisvarlena);
311  value = OidOutputFunctionCall(foutoid, itup_values[i]);
312  }
313 
314  if (i == IndexRelationGetNumberOfKeyAttributes(indexRel))
315  appendStringInfoString(&buf, ") INCLUDE (");
316  else if (i > 0)
317  appendStringInfoString(&buf, ", ");
318 
319  /* Check whether we need double quotes for this value */
320  nq = (value[0] == '\0'); /* force quotes for empty string */
321  for (tmp = value; *tmp; tmp++)
322  {
323  char ch = *tmp;
324 
325  if (ch == '"' || ch == '\\' ||
326  ch == '(' || ch == ')' || ch == ',' ||
327  isspace((unsigned char) ch))
328  {
329  nq = true;
330  break;
331  }
332  }
333 
334  /* And emit the string */
335  if (nq)
337  for (tmp = value; *tmp; tmp++)
338  {
339  char ch = *tmp;
340 
341  if (ch == '"' || ch == '\\')
344  }
345  if (nq)
347  }
348 
349  appendStringInfoChar(&buf, ')');
350 
351  values[4] = CStringGetTextDatum(buf.data);
352  nulls[4] = false;
353  }
354  else
355  {
356  values[4] = (Datum) 0;
357  nulls[4] = true;
358  }
359 
360  tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
361  }
362 
363  relation_close(indexRel, AccessShareLock);
364 
365  return (Datum) 0;
366 }
static Datum values[MAXATTR]
Definition: bootstrap.c:151
Pointer Page
Definition: bufpage.h:81
static Item PageGetItem(Page page, ItemId itemId)
Definition: bufpage.h:354
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
Definition: bufpage.h:243
static bool PageIsNew(Page page)
Definition: bufpage.h:233
static OffsetNumber PageGetMaxOffsetNumber(Page page)
Definition: bufpage.h:372
#define CStringGetTextDatum(s)
Definition: builtins.h:97
uint16 bits16
Definition: c.h:493
uint16_t uint16
Definition: c.h:484
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define NOTICE
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:149
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1763
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_GETARG_BYTEA_P(n)
Definition: fmgr.h:335
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
Definition: funcapi.c:76
#define F_LEAF
Definition: gist.h:48
#define GistPageIsDeleted(page)
Definition: gist.h:172
#define GistPageGetOpaque(page)
Definition: gist.h:167
static Page verify_gist_page(bytea *raw_page)
Definition: gistfuncs.c:41
#define IS_GIST(r)
Definition: gistfuncs.c:31
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 @160 value
int i
Definition: isn.c:72
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:76
#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
#define IndexTupleSize(itup)
Definition: itup.h:70
#define AccessShareLock
Definition: lockdefs.h:36
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2907
#define InvalidOffsetNumber
Definition: off.h:26
uint16 OffsetNumber
Definition: off.h:24
#define FirstOffsetNumber
Definition: off.h:27
#define INDEX_MAX_KEYS
static char * buf
Definition: pg_test_fsync.c:72
uintptr_t Datum
Definition: postgres.h:64
static Datum BoolGetDatum(bool X)
Definition: postgres.h:102
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
static int16 DatumGetInt16(Datum X)
Definition: postgres.h:162
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationGetDescr(relation)
Definition: rel.h:531
#define RelationGetRelationName(relation)
Definition: rel.h:539
#define IndexRelationGetNumberOfKeyAttributes(relation)
Definition: rel.h:524
char * pg_get_indexdef_columns_extended(Oid indexrelid, bits16 flags)
Definition: ruleutils.c:1243
#define RULE_INDEXDEF_PRETTY
Definition: ruleutils.h:24
#define RULE_INDEXDEF_KEYS_ONLY
Definition: ruleutils.h:25
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:205
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:94
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:179
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:191
void initStringInfo(StringInfo str)
Definition: stringinfo.c:56
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:204
ItemPointerData t_tid
Definition: itup.h:37
TupleDesc setDesc
Definition: execnodes.h:343
Tuplestorestate * setResult
Definition: execnodes.h:342
Definition: c.h:641
bool superuser(void)
Definition: superuser.c:46
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:133
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition: tuplestore.c:784

References AccessShareLock, appendStringInfo(), appendStringInfoChar(), appendStringInfoCharMacro, appendStringInfoString(), BoolGetDatum(), buf, CreateTupleDescCopy(), CStringGetTextDatum, DatumGetInt16(), elog, ereport, errcode(), errmsg(), ERROR, F_LEAF, FirstOffsetNumber, getTypeOutputInfo(), GistPageGetOpaque, GistPageIsDeleted, i, if(), index_close(), index_deform_tuple(), INDEX_MAX_KEYS, index_open(), IndexRelationGetNumberOfKeyAttributes, IndexTupleSize, InitMaterializedSRF(), initStringInfo(), Int32GetDatum(), InvalidOffsetNumber, IS_GIST, ItemIdIsDead, ItemIdIsValid, ItemPointerGetDatum(), NOTICE, OidOutputFunctionCall(), PageGetItem(), PageGetItemId(), PageGetMaxOffsetNumber(), PageIsNew(), pg_get_indexdef_columns_extended(), PG_GETARG_BYTEA_P, PG_GETARG_OID, PG_RETURN_NULL, relation_close(), RelationGetDescr, RelationGetRelationName, RULE_INDEXDEF_KEYS_ONLY, RULE_INDEXDEF_PRETTY, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, superuser(), IndexTupleData::t_tid, TupleDescAttr, tuplestore_putvalues(), value, values, and verify_gist_page().

◆ gist_page_items_bytea()

Datum gist_page_items_bytea ( PG_FUNCTION_ARGS  )

Definition at line 130 of file gistfuncs.c.

131 {
132  bytea *raw_page = PG_GETARG_BYTEA_P(0);
133  ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
134  Page page;
135  OffsetNumber offset;
137 
138  if (!superuser())
139  ereport(ERROR,
140  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
141  errmsg("must be superuser to use raw page functions")));
142 
143  InitMaterializedSRF(fcinfo, 0);
144 
145  page = verify_gist_page(raw_page);
146 
147  if (PageIsNew(page))
148  PG_RETURN_NULL();
149 
150  /* Avoid bogus PageGetMaxOffsetNumber() call with deleted pages */
151  if (GistPageIsDeleted(page))
152  elog(NOTICE, "page is deleted");
153  else
154  maxoff = PageGetMaxOffsetNumber(page);
155 
156  for (offset = FirstOffsetNumber;
157  offset <= maxoff;
158  offset++)
159  {
160  Datum values[5];
161  bool nulls[5];
162  ItemId id;
163  IndexTuple itup;
164  bytea *tuple_bytea;
165  int tuple_len;
166 
167  id = PageGetItemId(page, offset);
168 
169  if (!ItemIdIsValid(id))
170  elog(ERROR, "invalid ItemId");
171 
172  itup = (IndexTuple) PageGetItem(page, id);
173  tuple_len = IndexTupleSize(itup);
174 
175  memset(nulls, 0, sizeof(nulls));
176 
177  values[0] = DatumGetInt16(offset);
178  values[1] = ItemPointerGetDatum(&itup->t_tid);
179  values[2] = Int32GetDatum((int) IndexTupleSize(itup));
180 
181  tuple_bytea = (bytea *) palloc(tuple_len + VARHDRSZ);
182  SET_VARSIZE(tuple_bytea, tuple_len + VARHDRSZ);
183  memcpy(VARDATA(tuple_bytea), itup, tuple_len);
184  values[3] = BoolGetDatum(ItemIdIsDead(id));
185  values[4] = PointerGetDatum(tuple_bytea);
186 
187  tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
188  }
189 
190  return (Datum) 0;
191 }
#define VARHDRSZ
Definition: c.h:646
void * palloc(Size size)
Definition: mcxt.c:1317
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
#define VARDATA(PTR)
Definition: varatt.h:278
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305

References BoolGetDatum(), DatumGetInt16(), elog, ereport, errcode(), errmsg(), ERROR, FirstOffsetNumber, GistPageIsDeleted, if(), IndexTupleSize, InitMaterializedSRF(), Int32GetDatum(), InvalidOffsetNumber, ItemIdIsDead, ItemIdIsValid, ItemPointerGetDatum(), NOTICE, PageGetItem(), PageGetItemId(), PageGetMaxOffsetNumber(), PageIsNew(), palloc(), PG_GETARG_BYTEA_P, PG_RETURN_NULL, PointerGetDatum(), SET_VARSIZE, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, superuser(), IndexTupleData::t_tid, tuplestore_putvalues(), values, VARDATA, VARHDRSZ, and verify_gist_page().

◆ gist_page_opaque_info()

Datum gist_page_opaque_info ( PG_FUNCTION_ARGS  )

Definition at line 71 of file gistfuncs.c.

72 {
73  bytea *raw_page = PG_GETARG_BYTEA_P(0);
74  TupleDesc tupdesc;
75  Page page;
76  HeapTuple resultTuple;
77  Datum values[4];
78  bool nulls[4];
79  Datum flags[16];
80  int nflags = 0;
81  uint16 flagbits;
82 
83  if (!superuser())
84  ereport(ERROR,
85  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
86  errmsg("must be superuser to use raw page functions")));
87 
88  page = verify_gist_page(raw_page);
89 
90  if (PageIsNew(page))
92 
93  /* Build a tuple descriptor for our result type */
94  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
95  elog(ERROR, "return type must be a row type");
96 
97  /* Convert the flags bitmask to an array of human-readable names */
98  flagbits = GistPageGetOpaque(page)->flags;
99  if (flagbits & F_LEAF)
100  flags[nflags++] = CStringGetTextDatum("leaf");
101  if (flagbits & F_DELETED)
102  flags[nflags++] = CStringGetTextDatum("deleted");
103  if (flagbits & F_TUPLES_DELETED)
104  flags[nflags++] = CStringGetTextDatum("tuples_deleted");
105  if (flagbits & F_FOLLOW_RIGHT)
106  flags[nflags++] = CStringGetTextDatum("follow_right");
107  if (flagbits & F_HAS_GARBAGE)
108  flags[nflags++] = CStringGetTextDatum("has_garbage");
110  if (flagbits)
111  {
112  /* any flags we don't recognize are printed in hex */
113  flags[nflags++] = DirectFunctionCall1(to_hex32, Int32GetDatum(flagbits));
114  }
115 
116  memset(nulls, 0, sizeof(nulls));
117 
118  values[0] = LSNGetDatum(PageGetLSN(page));
119  values[1] = LSNGetDatum(GistPageGetNSN(page));
120  values[2] = Int64GetDatum(GistPageGetOpaque(page)->rightlink);
121  values[3] = PointerGetDatum(construct_array_builtin(flags, nflags, TEXTOID));
122 
123  /* Build and return the result tuple. */
124  resultTuple = heap_form_tuple(tupdesc, values, nulls);
125 
126  return HeapTupleGetDatum(resultTuple);
127 }
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
Definition: arrayfuncs.c:3381
static XLogRecPtr PageGetLSN(const char *page)
Definition: bufpage.h:386
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1807
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:641
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:50
#define F_FOLLOW_RIGHT
Definition: gist.h:51
#define F_HAS_GARBAGE
Definition: gist.h:52
#define F_DELETED
Definition: gist.h:49
#define GistPageGetNSN(page)
Definition: gist.h:186
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1116
static Datum LSNGetDatum(XLogRecPtr X)
Definition: pg_lsn.h:28
Datum to_hex32(PG_FUNCTION_ARGS)
Definition: varlena.c:5007

References construct_array_builtin(), CStringGetTextDatum, DirectFunctionCall1, elog, ereport, errcode(), errmsg(), ERROR, F_DELETED, F_FOLLOW_RIGHT, F_HAS_GARBAGE, F_LEAF, F_TUPLES_DELETED, get_call_result_type(), GistPageGetNSN, GistPageGetOpaque, heap_form_tuple(), HeapTupleGetDatum(), Int32GetDatum(), Int64GetDatum(), LSNGetDatum(), PageGetLSN(), PageIsNew(), PG_GETARG_BYTEA_P, PG_RETURN_NULL, PointerGetDatum(), superuser(), to_hex32(), TYPEFUNC_COMPOSITE, values, and verify_gist_page().

◆ PG_FUNCTION_INFO_V1() [1/3]

PG_FUNCTION_INFO_V1 ( gist_page_items  )

◆ PG_FUNCTION_INFO_V1() [2/3]

PG_FUNCTION_INFO_V1 ( gist_page_items_bytea  )

◆ PG_FUNCTION_INFO_V1() [3/3]

PG_FUNCTION_INFO_V1 ( gist_page_opaque_info  )

◆ verify_gist_page()

static Page verify_gist_page ( bytea raw_page)
static

Definition at line 41 of file gistfuncs.c.

42 {
43  Page page = get_page_from_raw(raw_page);
44  GISTPageOpaque opaq;
45 
46  if (PageIsNew(page))
47  return page;
48 
49  /* verify the special space has the expected size */
50  if (PageGetSpecialSize(page) != MAXALIGN(sizeof(GISTPageOpaqueData)))
51  ereport(ERROR,
52  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
53  errmsg("input page is not a valid %s page", "GiST"),
54  errdetail("Expected special size %d, got %d.",
55  (int) MAXALIGN(sizeof(GISTPageOpaqueData)),
56  (int) PageGetSpecialSize(page))));
57 
58  opaq = GistPageGetOpaque(page);
59  if (opaq->gist_page_id != GIST_PAGE_ID)
60  ereport(ERROR,
61  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
62  errmsg("input page is not a valid %s page", "GiST"),
63  errdetail("Expected %08x, got %08x.",
65  opaq->gist_page_id)));
66 
67  return page;
68 }
static uint16 PageGetSpecialSize(Page page)
Definition: bufpage.h:316
#define MAXALIGN(LEN)
Definition: c.h:765
int errdetail(const char *fmt,...)
Definition: elog.c:1203
#define GIST_PAGE_ID
Definition: gist.h:111
Page get_page_from_raw(bytea *raw_page)
Definition: rawpage.c:215
uint16 gist_page_id
Definition: gist.h:82

References ereport, errcode(), errdetail(), errmsg(), ERROR, get_page_from_raw(), GISTPageOpaqueData::gist_page_id, GIST_PAGE_ID, GistPageGetOpaque, MAXALIGN, PageGetSpecialSize(), and PageIsNew().

Referenced by gist_page_items(), gist_page_items_bytea(), and gist_page_opaque_info().