PostgreSQL Source Code  git master
pgstattuple.c File Reference
#include "postgres.h"
#include "access/gist_private.h"
#include "access/hash.h"
#include "access/heapam.h"
#include "access/nbtree.h"
#include "access/relscan.h"
#include "access/tableam.h"
#include "catalog/namespace.h"
#include "catalog/pg_am_d.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "storage/bufmgr.h"
#include "storage/lmgr.h"
#include "utils/varlena.h"
Include dependency graph for pgstattuple.c:

Go to the source code of this file.

Data Structures

struct  pgstattuple_type
 

Macros

#define NCOLUMNS   9
 
#define NCHARS   314
 

Typedefs

typedef struct pgstattuple_type pgstattuple_type
 
typedef void(* pgstat_page) (pgstattuple_type *, Relation, BlockNumber, BufferAccessStrategy)
 

Functions

 PG_FUNCTION_INFO_V1 (pgstattuple)
 
 PG_FUNCTION_INFO_V1 (pgstattuple_v1_5)
 
 PG_FUNCTION_INFO_V1 (pgstattuplebyid)
 
 PG_FUNCTION_INFO_V1 (pgstattuplebyid_v1_5)
 
static Datum build_pgstattuple_type (pgstattuple_type *stat, FunctionCallInfo fcinfo)
 
static Datum pgstat_relation (Relation rel, FunctionCallInfo fcinfo)
 
static Datum pgstat_heap (Relation rel, FunctionCallInfo fcinfo)
 
static void pgstat_btree_page (pgstattuple_type *stat, Relation rel, BlockNumber blkno, BufferAccessStrategy bstrategy)
 
static void pgstat_hash_page (pgstattuple_type *stat, Relation rel, BlockNumber blkno, BufferAccessStrategy bstrategy)
 
static void pgstat_gist_page (pgstattuple_type *stat, Relation rel, BlockNumber blkno, BufferAccessStrategy bstrategy)
 
static Datum pgstat_index (Relation rel, BlockNumber start, pgstat_page pagefn, FunctionCallInfo fcinfo)
 
static void pgstat_index_page (pgstattuple_type *stat, Page page, OffsetNumber minoff, OffsetNumber maxoff)
 
Datum pgstattuple (PG_FUNCTION_ARGS)
 
Datum pgstattuple_v1_5 (PG_FUNCTION_ARGS)
 
Datum pgstattuplebyid (PG_FUNCTION_ARGS)
 
Datum pgstattuplebyid_v1_5 (PG_FUNCTION_ARGS)
 

Variables

 PG_MODULE_MAGIC
 

Macro Definition Documentation

◆ NCHARS

#define NCHARS   314

◆ NCOLUMNS

#define NCOLUMNS   9

Typedef Documentation

◆ pgstat_page

typedef void(* pgstat_page) (pgstattuple_type *, Relation, BlockNumber, BufferAccessStrategy)

Definition at line 64 of file pgstattuple.c.

◆ pgstattuple_type

Function Documentation

◆ build_pgstattuple_type()

static Datum build_pgstattuple_type ( pgstattuple_type stat,
FunctionCallInfo  fcinfo 
)
static

Definition at line 89 of file pgstattuple.c.

90 {
91 #define NCOLUMNS 9
92 #define NCHARS 314
93 
94  HeapTuple tuple;
95  char *values[NCOLUMNS];
96  char values_buf[NCOLUMNS][NCHARS];
97  int i;
98  double tuple_percent;
99  double dead_tuple_percent;
100  double free_percent; /* free/reusable space in % */
101  TupleDesc tupdesc;
102  AttInMetadata *attinmeta;
103 
104  /* Build a tuple descriptor for our result type */
105  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
106  elog(ERROR, "return type must be a row type");
107 
108  /*
109  * Generate attribute metadata needed later to produce tuples from raw C
110  * strings
111  */
112  attinmeta = TupleDescGetAttInMetadata(tupdesc);
113 
114  if (stat->table_len == 0)
115  {
116  tuple_percent = 0.0;
117  dead_tuple_percent = 0.0;
118  free_percent = 0.0;
119  }
120  else
121  {
122  tuple_percent = 100.0 * stat->tuple_len / stat->table_len;
123  dead_tuple_percent = 100.0 * stat->dead_tuple_len / stat->table_len;
124  free_percent = 100.0 * stat->free_space / stat->table_len;
125  }
126 
127  /*
128  * Prepare a values array for constructing the tuple. This should be an
129  * array of C strings which will be processed later by the appropriate
130  * "in" functions.
131  */
132  for (i = 0; i < NCOLUMNS; i++)
133  values[i] = values_buf[i];
134  i = 0;
135  snprintf(values[i++], NCHARS, INT64_FORMAT, stat->table_len);
136  snprintf(values[i++], NCHARS, INT64_FORMAT, stat->tuple_count);
137  snprintf(values[i++], NCHARS, INT64_FORMAT, stat->tuple_len);
138  snprintf(values[i++], NCHARS, "%.2f", tuple_percent);
139  snprintf(values[i++], NCHARS, INT64_FORMAT, stat->dead_tuple_count);
140  snprintf(values[i++], NCHARS, INT64_FORMAT, stat->dead_tuple_len);
141  snprintf(values[i++], NCHARS, "%.2f", dead_tuple_percent);
142  snprintf(values[i++], NCHARS, INT64_FORMAT, stat->free_space);
143  snprintf(values[i++], NCHARS, "%.2f", free_percent);
144 
145  /* build a tuple */
146  tuple = BuildTupleFromCStrings(attinmeta, values);
147 
148  /* make the tuple into a datum */
149  return HeapTupleGetDatum(tuple);
150 }
static Datum values[MAXATTR]
Definition: bootstrap.c:151
#define INT64_FORMAT
Definition: c.h:503
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
Definition: execTuples.c:2222
AttInMetadata * TupleDescGetAttInMetadata(TupleDesc tupdesc)
Definition: execTuples.c:2173
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
int i
Definition: isn.c:72
#define NCHARS
#define NCOLUMNS
#define snprintf
Definition: port.h:238

References BuildTupleFromCStrings(), elog, ERROR, get_call_result_type(), HeapTupleGetDatum(), i, INT64_FORMAT, NCHARS, NCOLUMNS, snprintf, TupleDescGetAttInMetadata(), TYPEFUNC_COMPOSITE, and values.

Referenced by pgstat_heap(), and pgstat_index().

◆ PG_FUNCTION_INFO_V1() [1/4]

PG_FUNCTION_INFO_V1 ( pgstattuple  )

◆ PG_FUNCTION_INFO_V1() [2/4]

PG_FUNCTION_INFO_V1 ( pgstattuple_v1_5  )

◆ PG_FUNCTION_INFO_V1() [3/4]

PG_FUNCTION_INFO_V1 ( pgstattuplebyid  )

◆ PG_FUNCTION_INFO_V1() [4/4]

PG_FUNCTION_INFO_V1 ( pgstattuplebyid_v1_5  )

◆ pgstat_btree_page()

static void pgstat_btree_page ( pgstattuple_type stat,
Relation  rel,
BlockNumber  blkno,
BufferAccessStrategy  bstrategy 
)
static

Definition at line 408 of file pgstattuple.c.

410 {
411  Buffer buf;
412  Page page;
413 
414  buf = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, bstrategy);
416  page = BufferGetPage(buf);
417 
418  /* Page is valid, see what to do with it */
419  if (PageIsNew(page))
420  {
421  /* fully empty page */
422  stat->free_space += BLCKSZ;
423  }
424  else
425  {
426  BTPageOpaque opaque;
427 
428  opaque = BTPageGetOpaque(page);
429  if (P_IGNORE(opaque))
430  {
431  /* deleted or half-dead page */
432  stat->free_space += BLCKSZ;
433  }
434  else if (P_ISLEAF(opaque))
435  {
436  pgstat_index_page(stat, page, P_FIRSTDATAKEY(opaque),
437  PageGetMaxOffsetNumber(page));
438  }
439  else
440  {
441  /* internal page */
442  }
443  }
444 
445  _bt_relbuf(rel, buf);
446 }
int Buffer
Definition: buf.h:23
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:5158
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:793
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:400
@ RBM_NORMAL
Definition: bufmgr.h:45
Pointer Page
Definition: bufpage.h:81
static bool PageIsNew(Page page)
Definition: bufpage.h:233
static OffsetNumber PageGetMaxOffsetNumber(Page page)
Definition: bufpage.h:372
void _bt_relbuf(Relation rel, Buffer buf)
Definition: nbtpage.c:1023
#define P_ISLEAF(opaque)
Definition: nbtree.h:220
#define BTPageGetOpaque(page)
Definition: nbtree.h:73
#define P_FIRSTDATAKEY(opaque)
Definition: nbtree.h:369
#define BT_READ
Definition: nbtree.h:719
#define P_IGNORE(opaque)
Definition: nbtree.h:225
static char * buf
Definition: pg_test_fsync.c:72
static void pgstat_index_page(pgstattuple_type *stat, Page page, OffsetNumber minoff, OffsetNumber maxoff)
Definition: pgstattuple.c:566
@ MAIN_FORKNUM
Definition: relpath.h:58

References _bt_relbuf(), BT_READ, BTPageGetOpaque, buf, BufferGetPage(), LockBuffer(), MAIN_FORKNUM, P_FIRSTDATAKEY, P_IGNORE, P_ISLEAF, PageGetMaxOffsetNumber(), PageIsNew(), pgstat_index_page(), RBM_NORMAL, and ReadBufferExtended().

Referenced by pgstat_relation().

◆ pgstat_gist_page()

static void pgstat_gist_page ( pgstattuple_type stat,
Relation  rel,
BlockNumber  blkno,
BufferAccessStrategy  bstrategy 
)
static

Definition at line 494 of file pgstattuple.c.

496 {
497  Buffer buf;
498  Page page;
499 
500  buf = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, bstrategy);
502  gistcheckpage(rel, buf);
503  page = BufferGetPage(buf);
504 
505  if (GistPageIsLeaf(page))
506  {
508  PageGetMaxOffsetNumber(page));
509  }
510  else
511  {
512  /* root or node */
513  }
514 
516 }
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:4941
#define GistPageIsLeaf(page)
Definition: gist.h:169
#define GIST_SHARE
Definition: gist_private.h:42
void gistcheckpage(Relation rel, Buffer buf)
Definition: gistutil.c:785
#define FirstOffsetNumber
Definition: off.h:27

References buf, BufferGetPage(), FirstOffsetNumber, GIST_SHARE, gistcheckpage(), GistPageIsLeaf, LockBuffer(), MAIN_FORKNUM, PageGetMaxOffsetNumber(), pgstat_index_page(), RBM_NORMAL, ReadBufferExtended(), and UnlockReleaseBuffer().

Referenced by pgstat_relation().

◆ pgstat_hash_page()

static void pgstat_hash_page ( pgstattuple_type stat,
Relation  rel,
BlockNumber  blkno,
BufferAccessStrategy  bstrategy 
)
static

Definition at line 452 of file pgstattuple.c.

454 {
455  Buffer buf;
456  Page page;
457 
458  buf = _hash_getbuf_with_strategy(rel, blkno, HASH_READ, 0, bstrategy);
459  page = BufferGetPage(buf);
460 
461  if (PageGetSpecialSize(page) == MAXALIGN(sizeof(HashPageOpaqueData)))
462  {
463  HashPageOpaque opaque;
464 
465  opaque = HashPageGetOpaque(page);
466  switch (opaque->hasho_flag & LH_PAGE_TYPE)
467  {
468  case LH_UNUSED_PAGE:
469  stat->free_space += BLCKSZ;
470  break;
471  case LH_BUCKET_PAGE:
472  case LH_OVERFLOW_PAGE:
474  PageGetMaxOffsetNumber(page));
475  break;
476  case LH_BITMAP_PAGE:
477  case LH_META_PAGE:
478  default:
479  break;
480  }
481  }
482  else
483  {
484  /* maybe corrupted */
485  }
486 
487  _hash_relbuf(rel, buf);
488 }
static uint16 PageGetSpecialSize(Page page)
Definition: bufpage.h:316
#define MAXALIGN(LEN)
Definition: c.h:765
#define HashPageGetOpaque(page)
Definition: hash.h:88
#define LH_BUCKET_PAGE
Definition: hash.h:55
#define LH_UNUSED_PAGE
Definition: hash.h:53
#define LH_META_PAGE
Definition: hash.h:57
#define HASH_READ
Definition: hash.h:339
#define LH_PAGE_TYPE
Definition: hash.h:63
#define LH_BITMAP_PAGE
Definition: hash.h:56
#define LH_OVERFLOW_PAGE
Definition: hash.h:54
void _hash_relbuf(Relation rel, Buffer buf)
Definition: hashpage.c:266
Buffer _hash_getbuf_with_strategy(Relation rel, BlockNumber blkno, int access, int flags, BufferAccessStrategy bstrategy)
Definition: hashpage.c:239
uint16 hasho_flag
Definition: hash.h:82

References _hash_getbuf_with_strategy(), _hash_relbuf(), buf, BufferGetPage(), FirstOffsetNumber, HASH_READ, HashPageOpaqueData::hasho_flag, HashPageGetOpaque, LH_BITMAP_PAGE, LH_BUCKET_PAGE, LH_META_PAGE, LH_OVERFLOW_PAGE, LH_PAGE_TYPE, LH_UNUSED_PAGE, MAXALIGN, PageGetMaxOffsetNumber(), PageGetSpecialSize(), and pgstat_index_page().

Referenced by pgstat_relation().

◆ pgstat_heap()

static Datum pgstat_heap ( Relation  rel,
FunctionCallInfo  fcinfo 
)
static

Definition at line 313 of file pgstattuple.c.

314 {
315  TableScanDesc scan;
316  HeapScanDesc hscan;
317  HeapTuple tuple;
318  BlockNumber nblocks;
319  BlockNumber block = 0; /* next block to count free space in */
320  BlockNumber tupblock;
321  Buffer buffer;
322  pgstattuple_type stat = {0};
323  SnapshotData SnapshotDirty;
324 
325  /*
326  * Sequences always use heap AM, but they don't show that in the catalogs.
327  */
328  if (rel->rd_rel->relkind != RELKIND_SEQUENCE &&
329  rel->rd_rel->relam != HEAP_TABLE_AM_OID)
330  ereport(ERROR,
331  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
332  errmsg("only heap AM is supported")));
333 
334  /* Disable syncscan because we assume we scan from block zero upwards */
335  scan = table_beginscan_strat(rel, SnapshotAny, 0, NULL, true, false);
336  hscan = (HeapScanDesc) scan;
337 
338  InitDirtySnapshot(SnapshotDirty);
339 
340  nblocks = hscan->rs_nblocks; /* # blocks to be scanned */
341 
342  /* scan the relation */
343  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
344  {
346 
347  /* must hold a buffer lock to call HeapTupleSatisfiesVisibility */
349 
350  if (HeapTupleSatisfiesVisibility(tuple, &SnapshotDirty, hscan->rs_cbuf))
351  {
352  stat.tuple_len += tuple->t_len;
353  stat.tuple_count++;
354  }
355  else
356  {
357  stat.dead_tuple_len += tuple->t_len;
358  stat.dead_tuple_count++;
359  }
360 
362 
363  /*
364  * To avoid physically reading the table twice, try to do the
365  * free-space scan in parallel with the heap scan. However,
366  * heap_getnext may find no tuples on a given page, so we cannot
367  * simply examine the pages returned by the heap scan.
368  */
369  tupblock = ItemPointerGetBlockNumber(&tuple->t_self);
370 
371  while (block <= tupblock)
372  {
374 
375  buffer = ReadBufferExtended(rel, MAIN_FORKNUM, block,
376  RBM_NORMAL, hscan->rs_strategy);
377  LockBuffer(buffer, BUFFER_LOCK_SHARE);
378  stat.free_space += PageGetExactFreeSpace((Page) BufferGetPage(buffer));
379  UnlockReleaseBuffer(buffer);
380  block++;
381  }
382  }
383 
384  while (block < nblocks)
385  {
387 
388  buffer = ReadBufferExtended(rel, MAIN_FORKNUM, block,
389  RBM_NORMAL, hscan->rs_strategy);
390  LockBuffer(buffer, BUFFER_LOCK_SHARE);
391  stat.free_space += PageGetExactFreeSpace((Page) BufferGetPage(buffer));
392  UnlockReleaseBuffer(buffer);
393  block++;
394  }
395 
396  table_endscan(scan);
398 
399  stat.table_len = (uint64) nblocks * BLCKSZ;
400 
401  return build_pgstattuple_type(&stat, fcinfo);
402 }
uint32 BlockNumber
Definition: block.h:31
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:189
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:190
Size PageGetExactFreeSpace(Page page)
Definition: bufpage.c:947
uint64_t uint64
Definition: c.h:486
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ereport(elevel,...)
Definition: elog.h:149
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
Definition: heapam.c:1243
struct HeapScanDescData * HeapScanDesc
Definition: heapam.h:110
bool HeapTupleSatisfiesVisibility(HeapTuple htup, Snapshot snapshot, Buffer buffer)
static BlockNumber ItemPointerGetBlockNumber(const ItemPointerData *pointer)
Definition: itemptr.h:103
#define AccessShareLock
Definition: lockdefs.h:36
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
static Datum build_pgstattuple_type(pgstattuple_type *stat, FunctionCallInfo fcinfo)
Definition: pgstattuple.c:89
@ ForwardScanDirection
Definition: sdir.h:28
#define SnapshotAny
Definition: snapmgr.h:33
#define InitDirtySnapshot(snapshotdata)
Definition: snapmgr.h:40
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:205
BufferAccessStrategy rs_strategy
Definition: heapam.h:71
Buffer rs_cbuf
Definition: heapam.h:68
BlockNumber rs_nblocks
Definition: heapam.h:59
ItemPointerData t_self
Definition: htup.h:65
uint32 t_len
Definition: htup.h:64
Form_pg_class rd_rel
Definition: rel.h:111
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:1028
static TableScanDesc table_beginscan_strat(Relation rel, Snapshot snapshot, int nkeys, struct ScanKeyData *key, bool allow_strat, bool allow_sync)
Definition: tableam.h:936

References AccessShareLock, BUFFER_LOCK_SHARE, BUFFER_LOCK_UNLOCK, BufferGetPage(), build_pgstattuple_type(), CHECK_FOR_INTERRUPTS, ereport, errcode(), errmsg(), ERROR, ForwardScanDirection, heap_getnext(), HeapTupleSatisfiesVisibility(), InitDirtySnapshot, ItemPointerGetBlockNumber(), LockBuffer(), MAIN_FORKNUM, PageGetExactFreeSpace(), RBM_NORMAL, RelationData::rd_rel, ReadBufferExtended(), relation_close(), HeapScanDescData::rs_cbuf, HeapScanDescData::rs_nblocks, HeapScanDescData::rs_strategy, SnapshotAny, HeapTupleData::t_len, HeapTupleData::t_self, table_beginscan_strat(), table_endscan(), and UnlockReleaseBuffer().

Referenced by pgstat_relation().

◆ pgstat_index()

static Datum pgstat_index ( Relation  rel,
BlockNumber  start,
pgstat_page  pagefn,
FunctionCallInfo  fcinfo 
)
static

Definition at line 522 of file pgstattuple.c.

524 {
525  BlockNumber nblocks;
526  BlockNumber blkno;
527  BufferAccessStrategy bstrategy;
528  pgstattuple_type stat = {0};
529 
530  /* prepare access strategy for this index */
531  bstrategy = GetAccessStrategy(BAS_BULKREAD);
532 
533  blkno = start;
534  for (;;)
535  {
536  /* Get the current relation length */
538  nblocks = RelationGetNumberOfBlocks(rel);
540 
541  /* Quit if we've scanned the whole relation */
542  if (blkno >= nblocks)
543  {
544  stat.table_len = (uint64) nblocks * BLCKSZ;
545 
546  break;
547  }
548 
549  for (; blkno < nblocks; blkno++)
550  {
552 
553  pagefn(&stat, rel, blkno, bstrategy);
554  }
555  }
556 
558 
559  return build_pgstattuple_type(&stat, fcinfo);
560 }
@ BAS_BULKREAD
Definition: bufmgr.h:36
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:273
BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype)
Definition: freelist.c:541
return str start
void LockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:419
void UnlockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:469
#define ExclusiveLock
Definition: lockdefs.h:42

References AccessShareLock, BAS_BULKREAD, build_pgstattuple_type(), CHECK_FOR_INTERRUPTS, ExclusiveLock, GetAccessStrategy(), LockRelationForExtension(), relation_close(), RelationGetNumberOfBlocks, start, and UnlockRelationForExtension().

Referenced by pgstat_relation().

◆ pgstat_index_page()

static void pgstat_index_page ( pgstattuple_type stat,
Page  page,
OffsetNumber  minoff,
OffsetNumber  maxoff 
)
static

Definition at line 566 of file pgstattuple.c.

568 {
569  OffsetNumber i;
570 
571  stat->free_space += PageGetExactFreeSpace(page);
572 
573  for (i = minoff; i <= maxoff; i = OffsetNumberNext(i))
574  {
575  ItemId itemid = PageGetItemId(page, i);
576 
577  if (ItemIdIsDead(itemid))
578  {
579  stat->dead_tuple_count++;
580  stat->dead_tuple_len += ItemIdGetLength(itemid);
581  }
582  else
583  {
584  stat->tuple_count++;
585  stat->tuple_len += ItemIdGetLength(itemid);
586  }
587  }
588 }
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
Definition: bufpage.h:243
#define ItemIdGetLength(itemId)
Definition: itemid.h:59
#define ItemIdIsDead(itemId)
Definition: itemid.h:113
#define OffsetNumberNext(offsetNumber)
Definition: off.h:52
uint16 OffsetNumber
Definition: off.h:24

References i, ItemIdGetLength, ItemIdIsDead, OffsetNumberNext, PageGetExactFreeSpace(), and PageGetItemId().

Referenced by pgstat_btree_page(), pgstat_gist_page(), and pgstat_hash_page().

◆ pgstat_relation()

static Datum pgstat_relation ( Relation  rel,
FunctionCallInfo  fcinfo 
)
static

Definition at line 240 of file pgstattuple.c.

241 {
242  const char *err;
243 
244  /*
245  * Reject attempts to read non-local temporary relations; we would be
246  * likely to get wrong data since we have no visibility into the owning
247  * session's local buffers.
248  */
249  if (RELATION_IS_OTHER_TEMP(rel))
250  ereport(ERROR,
251  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
252  errmsg("cannot access temporary tables of other sessions")));
253 
254  if (RELKIND_HAS_TABLE_AM(rel->rd_rel->relkind) ||
255  rel->rd_rel->relkind == RELKIND_SEQUENCE)
256  {
257  return pgstat_heap(rel, fcinfo);
258  }
259  else if (rel->rd_rel->relkind == RELKIND_INDEX)
260  {
261  /* see pgstatindex_impl */
262  if (!rel->rd_index->indisvalid)
263  ereport(ERROR,
264  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
265  errmsg("index \"%s\" is not valid",
266  RelationGetRelationName(rel))));
267 
268  switch (rel->rd_rel->relam)
269  {
270  case BTREE_AM_OID:
271  return pgstat_index(rel, BTREE_METAPAGE + 1,
272  pgstat_btree_page, fcinfo);
273  case HASH_AM_OID:
274  return pgstat_index(rel, HASH_METAPAGE + 1,
275  pgstat_hash_page, fcinfo);
276  case GIST_AM_OID:
277  return pgstat_index(rel, GIST_ROOT_BLKNO + 1,
278  pgstat_gist_page, fcinfo);
279  case GIN_AM_OID:
280  err = "gin index";
281  break;
282  case SPGIST_AM_OID:
283  err = "spgist index";
284  break;
285  case BRIN_AM_OID:
286  err = "brin index";
287  break;
288  default:
289  err = "unknown index";
290  break;
291  }
292  ereport(ERROR,
293  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
294  errmsg("index \"%s\" (%s) is not supported",
295  RelationGetRelationName(rel), err)));
296  }
297  else
298  {
299  ereport(ERROR,
300  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
301  errmsg("cannot get tuple-level statistics for relation \"%s\"",
303  errdetail_relkind_not_supported(rel->rd_rel->relkind)));
304  }
305 
306  return 0; /* should not happen */
307 }
void err(int eval, const char *fmt,...)
Definition: err.c:43
#define GIST_ROOT_BLKNO
Definition: gist_private.h:262
#define HASH_METAPAGE
Definition: hash.h:198
#define BTREE_METAPAGE
Definition: nbtree.h:148
int errdetail_relkind_not_supported(char relkind)
Definition: pg_class.c:24
static Datum pgstat_index(Relation rel, BlockNumber start, pgstat_page pagefn, FunctionCallInfo fcinfo)
Definition: pgstattuple.c:522
static void pgstat_gist_page(pgstattuple_type *stat, Relation rel, BlockNumber blkno, BufferAccessStrategy bstrategy)
Definition: pgstattuple.c:494
static void pgstat_btree_page(pgstattuple_type *stat, Relation rel, BlockNumber blkno, BufferAccessStrategy bstrategy)
Definition: pgstattuple.c:408
static Datum pgstat_heap(Relation rel, FunctionCallInfo fcinfo)
Definition: pgstattuple.c:313
static void pgstat_hash_page(pgstattuple_type *stat, Relation rel, BlockNumber blkno, BufferAccessStrategy bstrategy)
Definition: pgstattuple.c:452
#define RelationGetRelationName(relation)
Definition: rel.h:539
#define RELATION_IS_OTHER_TEMP(relation)
Definition: rel.h:658
Form_pg_index rd_index
Definition: rel.h:192

References BTREE_METAPAGE, ereport, err(), errcode(), errdetail_relkind_not_supported(), errmsg(), ERROR, GIST_ROOT_BLKNO, HASH_METAPAGE, pgstat_btree_page(), pgstat_gist_page(), pgstat_hash_page(), pgstat_heap(), pgstat_index(), RelationData::rd_index, RelationData::rd_rel, RELATION_IS_OTHER_TEMP, and RelationGetRelationName.

Referenced by pgstattuple(), pgstattuple_v1_5(), pgstattuplebyid(), and pgstattuplebyid_v1_5().

◆ pgstattuple()

Datum pgstattuple ( PG_FUNCTION_ARGS  )

Definition at line 166 of file pgstattuple.c.

167 {
169  RangeVar *relrv;
170  Relation rel;
171 
172  if (!superuser())
173  ereport(ERROR,
174  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
175  errmsg("must be superuser to use pgstattuple functions")));
176 
177  /* open relation */
179  rel = relation_openrv(relrv, AccessShareLock);
180 
181  PG_RETURN_DATUM(pgstat_relation(rel, fcinfo));
182 }
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
RangeVar * makeRangeVarFromNameList(const List *names)
Definition: namespace.c:3554
NameData relname
Definition: pg_class.h:38
static Datum pgstat_relation(Relation rel, FunctionCallInfo fcinfo)
Definition: pgstattuple.c:240
Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: relation.c:137
Definition: c.h:641
bool superuser(void)
Definition: superuser.c:46
List * textToQualifiedNameList(text *textval)
Definition: varlena.c:3374

References AccessShareLock, ereport, errcode(), errmsg(), ERROR, makeRangeVarFromNameList(), PG_GETARG_TEXT_PP, PG_RETURN_DATUM, pgstat_relation(), relation_openrv(), relname, superuser(), and textToQualifiedNameList().

◆ pgstattuple_v1_5()

Datum pgstattuple_v1_5 ( PG_FUNCTION_ARGS  )

Definition at line 192 of file pgstattuple.c.

193 {
195  RangeVar *relrv;
196  Relation rel;
197 
198  /* open relation */
200  rel = relation_openrv(relrv, AccessShareLock);
201 
202  PG_RETURN_DATUM(pgstat_relation(rel, fcinfo));
203 }

References AccessShareLock, makeRangeVarFromNameList(), PG_GETARG_TEXT_PP, PG_RETURN_DATUM, pgstat_relation(), relation_openrv(), relname, and textToQualifiedNameList().

◆ pgstattuplebyid()

Datum pgstattuplebyid ( PG_FUNCTION_ARGS  )

Definition at line 207 of file pgstattuple.c.

208 {
209  Oid relid = PG_GETARG_OID(0);
210  Relation rel;
211 
212  if (!superuser())
213  ereport(ERROR,
214  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
215  errmsg("must be superuser to use pgstattuple functions")));
216 
217  /* open relation */
218  rel = relation_open(relid, AccessShareLock);
219 
220  PG_RETURN_DATUM(pgstat_relation(rel, fcinfo));
221 }
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
unsigned int Oid
Definition: postgres_ext.h:31
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:47

References AccessShareLock, ereport, errcode(), errmsg(), ERROR, PG_GETARG_OID, PG_RETURN_DATUM, pgstat_relation(), relation_open(), and superuser().

◆ pgstattuplebyid_v1_5()

Datum pgstattuplebyid_v1_5 ( PG_FUNCTION_ARGS  )

Definition at line 225 of file pgstattuple.c.

226 {
227  Oid relid = PG_GETARG_OID(0);
228  Relation rel;
229 
230  /* open relation */
231  rel = relation_open(relid, AccessShareLock);
232 
233  PG_RETURN_DATUM(pgstat_relation(rel, fcinfo));
234 }

References AccessShareLock, PG_GETARG_OID, PG_RETURN_DATUM, pgstat_relation(), and relation_open().

Variable Documentation

◆ PG_MODULE_MAGIC

PG_MODULE_MAGIC

Definition at line 41 of file pgstattuple.c.