PostgreSQL Source Code  git master
pgstattuple.c
Go to the documentation of this file.
1 /*
2  * contrib/pgstattuple/pgstattuple.c
3  *
4  * Copyright (c) 2001,2002 Tatsuo Ishii
5  *
6  * Permission to use, copy, modify, and distribute this software and
7  * its documentation for any purpose, without fee, and without a
8  * written agreement is hereby granted, provided that the above
9  * copyright notice and this paragraph and the following two
10  * paragraphs appear in all copies.
11  *
12  * IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,
13  * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
14  * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
15  * DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED
16  * OF THE POSSIBILITY OF SUCH DAMAGE.
17  *
18  * THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20  * A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS
21  * IS" BASIS, AND THE AUTHOR HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE,
22  * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23  */
24 
25 #include "postgres.h"
26 
27 #include "access/gist_private.h"
28 #include "access/hash.h"
29 #include "access/heapam.h"
30 #include "access/nbtree.h"
31 #include "access/relscan.h"
32 #include "access/tableam.h"
33 #include "catalog/namespace.h"
34 #include "catalog/pg_am_d.h"
35 #include "funcapi.h"
36 #include "miscadmin.h"
37 #include "storage/bufmgr.h"
38 #include "storage/lmgr.h"
39 #include "utils/builtins.h"
40 #include "utils/varlena.h"
41 
43 
48 
49 /*
50  * struct pgstattuple_type
51  *
52  * tuple_percent, dead_tuple_percent and free_percent are computable,
53  * so not defined here.
54  */
55 typedef struct pgstattuple_type
56 {
57  uint64 table_len;
58  uint64 tuple_count;
59  uint64 tuple_len;
62  uint64 free_space; /* free/reusable space in bytes */
64 
67 
69  FunctionCallInfo fcinfo);
71 static Datum pgstat_heap(Relation rel, FunctionCallInfo fcinfo);
73  Relation rel, BlockNumber blkno,
74  BufferAccessStrategy bstrategy);
76  Relation rel, BlockNumber blkno,
77  BufferAccessStrategy bstrategy);
79  Relation rel, BlockNumber blkno,
80  BufferAccessStrategy bstrategy);
82  pgstat_page pagefn, FunctionCallInfo fcinfo);
83 static void pgstat_index_page(pgstattuple_type *stat, Page page,
84  OffsetNumber minoff, OffsetNumber maxoff);
85 
86 /*
87  * build_pgstattuple_type -- build a pgstattuple_type tuple
88  */
89 static Datum
91 {
92 #define NCOLUMNS 9
93 #define NCHARS 314
94 
95  HeapTuple tuple;
96  char *values[NCOLUMNS];
97  char values_buf[NCOLUMNS][NCHARS];
98  int i;
99  double tuple_percent;
100  double dead_tuple_percent;
101  double free_percent; /* free/reusable space in % */
102  TupleDesc tupdesc;
103  AttInMetadata *attinmeta;
104 
105  /* Build a tuple descriptor for our result type */
106  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
107  elog(ERROR, "return type must be a row type");
108 
109  /*
110  * Generate attribute metadata needed later to produce tuples from raw C
111  * strings
112  */
113  attinmeta = TupleDescGetAttInMetadata(tupdesc);
114 
115  if (stat->table_len == 0)
116  {
117  tuple_percent = 0.0;
118  dead_tuple_percent = 0.0;
119  free_percent = 0.0;
120  }
121  else
122  {
123  tuple_percent = 100.0 * stat->tuple_len / stat->table_len;
124  dead_tuple_percent = 100.0 * stat->dead_tuple_len / stat->table_len;
125  free_percent = 100.0 * stat->free_space / stat->table_len;
126  }
127 
128  /*
129  * Prepare a values array for constructing the tuple. This should be an
130  * array of C strings which will be processed later by the appropriate
131  * "in" functions.
132  */
133  for (i = 0; i < NCOLUMNS; i++)
134  values[i] = values_buf[i];
135  i = 0;
136  snprintf(values[i++], NCHARS, INT64_FORMAT, stat->table_len);
137  snprintf(values[i++], NCHARS, INT64_FORMAT, stat->tuple_count);
138  snprintf(values[i++], NCHARS, INT64_FORMAT, stat->tuple_len);
139  snprintf(values[i++], NCHARS, "%.2f", tuple_percent);
140  snprintf(values[i++], NCHARS, INT64_FORMAT, stat->dead_tuple_count);
141  snprintf(values[i++], NCHARS, INT64_FORMAT, stat->dead_tuple_len);
142  snprintf(values[i++], NCHARS, "%.2f", dead_tuple_percent);
143  snprintf(values[i++], NCHARS, INT64_FORMAT, stat->free_space);
144  snprintf(values[i++], NCHARS, "%.2f", free_percent);
145 
146  /* build a tuple */
147  tuple = BuildTupleFromCStrings(attinmeta, values);
148 
149  /* make the tuple into a datum */
150  return HeapTupleGetDatum(tuple);
151 }
152 
153 /* ----------
154  * pgstattuple:
155  * returns live/dead tuples info
156  *
157  * C FUNCTION definition
158  * pgstattuple(text) returns pgstattuple_type
159  *
160  * The superuser() check here must be kept as the library might be upgraded
161  * without the extension being upgraded, meaning that in pre-1.5 installations
162  * these functions could be called by any user.
163  * ----------
164  */
165 
166 Datum
168 {
170  RangeVar *relrv;
171  Relation rel;
172 
173  if (!superuser())
174  ereport(ERROR,
175  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
176  errmsg("must be superuser to use pgstattuple functions")));
177 
178  /* open relation */
180  rel = relation_openrv(relrv, AccessShareLock);
181 
182  PG_RETURN_DATUM(pgstat_relation(rel, fcinfo));
183 }
184 
185 /*
186  * As of pgstattuple version 1.5, we no longer need to check if the user
187  * is a superuser because we REVOKE EXECUTE on the function from PUBLIC.
188  * Users can then grant access to it based on their policies.
189  *
190  * Otherwise identical to pgstattuple (above).
191  */
192 Datum
194 {
196  RangeVar *relrv;
197  Relation rel;
198 
199  /* open relation */
201  rel = relation_openrv(relrv, AccessShareLock);
202 
203  PG_RETURN_DATUM(pgstat_relation(rel, fcinfo));
204 }
205 
206 /* Must keep superuser() check, see above. */
207 Datum
209 {
210  Oid relid = PG_GETARG_OID(0);
211  Relation rel;
212 
213  if (!superuser())
214  ereport(ERROR,
215  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
216  errmsg("must be superuser to use pgstattuple functions")));
217 
218  /* open relation */
219  rel = relation_open(relid, AccessShareLock);
220 
221  PG_RETURN_DATUM(pgstat_relation(rel, fcinfo));
222 }
223 
224 /* Remove superuser() check for 1.5 version, see above */
225 Datum
227 {
228  Oid relid = PG_GETARG_OID(0);
229  Relation rel;
230 
231  /* open relation */
232  rel = relation_open(relid, AccessShareLock);
233 
234  PG_RETURN_DATUM(pgstat_relation(rel, fcinfo));
235 }
236 
237 /*
238  * pgstat_relation
239  */
240 static Datum
242 {
243  const char *err;
244 
245  /*
246  * Reject attempts to read non-local temporary relations; we would be
247  * likely to get wrong data since we have no visibility into the owning
248  * session's local buffers.
249  */
250  if (RELATION_IS_OTHER_TEMP(rel))
251  ereport(ERROR,
252  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
253  errmsg("cannot access temporary tables of other sessions")));
254 
255  if (RELKIND_HAS_TABLE_AM(rel->rd_rel->relkind) ||
256  rel->rd_rel->relkind == RELKIND_SEQUENCE)
257  {
258  return pgstat_heap(rel, fcinfo);
259  }
260  else if (rel->rd_rel->relkind == RELKIND_INDEX)
261  {
262  /* see pgstatindex_impl */
263  if (!rel->rd_index->indisvalid)
264  ereport(ERROR,
265  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
266  errmsg("index \"%s\" is not valid",
267  RelationGetRelationName(rel))));
268 
269  switch (rel->rd_rel->relam)
270  {
271  case BTREE_AM_OID:
272  return pgstat_index(rel, BTREE_METAPAGE + 1,
273  pgstat_btree_page, fcinfo);
274  case HASH_AM_OID:
275  return pgstat_index(rel, HASH_METAPAGE + 1,
276  pgstat_hash_page, fcinfo);
277  case GIST_AM_OID:
278  return pgstat_index(rel, GIST_ROOT_BLKNO + 1,
279  pgstat_gist_page, fcinfo);
280  case GIN_AM_OID:
281  err = "gin index";
282  break;
283  case SPGIST_AM_OID:
284  err = "spgist index";
285  break;
286  case BRIN_AM_OID:
287  err = "brin index";
288  break;
289  default:
290  err = "unknown index";
291  break;
292  }
293  ereport(ERROR,
294  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
295  errmsg("index \"%s\" (%s) is not supported",
296  RelationGetRelationName(rel), err)));
297  }
298  else
299  {
300  ereport(ERROR,
301  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
302  errmsg("cannot get tuple-level statistics for relation \"%s\"",
304  errdetail_relkind_not_supported(rel->rd_rel->relkind)));
305  }
306 
307  return 0; /* should not happen */
308 }
309 
310 /*
311  * pgstat_heap -- returns live/dead tuples info in a heap
312  */
313 static Datum
315 {
316  TableScanDesc scan;
317  HeapScanDesc hscan;
318  HeapTuple tuple;
319  BlockNumber nblocks;
320  BlockNumber block = 0; /* next block to count free space in */
321  BlockNumber tupblock;
322  Buffer buffer;
323  pgstattuple_type stat = {0};
324  SnapshotData SnapshotDirty;
325 
326  /*
327  * Sequences always use heap AM, but they don't show that in the catalogs.
328  */
329  if (rel->rd_rel->relkind != RELKIND_SEQUENCE &&
330  rel->rd_rel->relam != HEAP_TABLE_AM_OID)
331  ereport(ERROR,
332  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
333  errmsg("only heap AM is supported")));
334 
335  /* Disable syncscan because we assume we scan from block zero upwards */
336  scan = table_beginscan_strat(rel, SnapshotAny, 0, NULL, true, false);
337  hscan = (HeapScanDesc) scan;
338 
339  InitDirtySnapshot(SnapshotDirty);
340 
341  nblocks = hscan->rs_nblocks; /* # blocks to be scanned */
342 
343  /* scan the relation */
344  while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
345  {
347 
348  /* must hold a buffer lock to call HeapTupleSatisfiesVisibility */
350 
351  if (HeapTupleSatisfiesVisibility(tuple, &SnapshotDirty, hscan->rs_cbuf))
352  {
353  stat.tuple_len += tuple->t_len;
354  stat.tuple_count++;
355  }
356  else
357  {
358  stat.dead_tuple_len += tuple->t_len;
359  stat.dead_tuple_count++;
360  }
361 
363 
364  /*
365  * To avoid physically reading the table twice, try to do the
366  * free-space scan in parallel with the heap scan. However,
367  * heap_getnext may find no tuples on a given page, so we cannot
368  * simply examine the pages returned by the heap scan.
369  */
370  tupblock = ItemPointerGetBlockNumber(&tuple->t_self);
371 
372  while (block <= tupblock)
373  {
375 
376  buffer = ReadBufferExtended(rel, MAIN_FORKNUM, block,
377  RBM_NORMAL, hscan->rs_strategy);
378  LockBuffer(buffer, BUFFER_LOCK_SHARE);
379  stat.free_space += PageGetExactFreeSpace((Page) BufferGetPage(buffer));
380  UnlockReleaseBuffer(buffer);
381  block++;
382  }
383  }
384 
385  while (block < nblocks)
386  {
388 
389  buffer = ReadBufferExtended(rel, MAIN_FORKNUM, block,
390  RBM_NORMAL, hscan->rs_strategy);
391  LockBuffer(buffer, BUFFER_LOCK_SHARE);
392  stat.free_space += PageGetExactFreeSpace((Page) BufferGetPage(buffer));
393  UnlockReleaseBuffer(buffer);
394  block++;
395  }
396 
397  table_endscan(scan);
399 
400  stat.table_len = (uint64) nblocks * BLCKSZ;
401 
402  return build_pgstattuple_type(&stat, fcinfo);
403 }
404 
405 /*
406  * pgstat_btree_page -- check tuples in a btree page
407  */
408 static void
410  BufferAccessStrategy bstrategy)
411 {
412  Buffer buf;
413  Page page;
414 
415  buf = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, bstrategy);
417  page = BufferGetPage(buf);
418 
419  /* Page is valid, see what to do with it */
420  if (PageIsNew(page))
421  {
422  /* fully empty page */
423  stat->free_space += BLCKSZ;
424  }
425  else
426  {
427  BTPageOpaque opaque;
428 
429  opaque = BTPageGetOpaque(page);
430  if (P_IGNORE(opaque))
431  {
432  /* deleted or half-dead page */
433  stat->free_space += BLCKSZ;
434  }
435  else if (P_ISLEAF(opaque))
436  {
437  pgstat_index_page(stat, page, P_FIRSTDATAKEY(opaque),
438  PageGetMaxOffsetNumber(page));
439  }
440  else
441  {
442  /* internal page */
443  }
444  }
445 
446  _bt_relbuf(rel, buf);
447 }
448 
449 /*
450  * pgstat_hash_page -- check tuples in a hash page
451  */
452 static void
454  BufferAccessStrategy bstrategy)
455 {
456  Buffer buf;
457  Page page;
458 
459  buf = _hash_getbuf_with_strategy(rel, blkno, HASH_READ, 0, bstrategy);
460  page = BufferGetPage(buf);
461 
462  if (PageGetSpecialSize(page) == MAXALIGN(sizeof(HashPageOpaqueData)))
463  {
464  HashPageOpaque opaque;
465 
466  opaque = HashPageGetOpaque(page);
467  switch (opaque->hasho_flag & LH_PAGE_TYPE)
468  {
469  case LH_UNUSED_PAGE:
470  stat->free_space += BLCKSZ;
471  break;
472  case LH_BUCKET_PAGE:
473  case LH_OVERFLOW_PAGE:
475  PageGetMaxOffsetNumber(page));
476  break;
477  case LH_BITMAP_PAGE:
478  case LH_META_PAGE:
479  default:
480  break;
481  }
482  }
483  else
484  {
485  /* maybe corrupted */
486  }
487 
488  _hash_relbuf(rel, buf);
489 }
490 
491 /*
492  * pgstat_gist_page -- check tuples in a gist page
493  */
494 static void
496  BufferAccessStrategy bstrategy)
497 {
498  Buffer buf;
499  Page page;
500 
501  buf = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, bstrategy);
503  gistcheckpage(rel, buf);
504  page = BufferGetPage(buf);
505 
506  if (GistPageIsLeaf(page))
507  {
509  PageGetMaxOffsetNumber(page));
510  }
511  else
512  {
513  /* root or node */
514  }
515 
517 }
518 
519 /*
520  * pgstat_index -- returns live/dead tuples info in a generic index
521  */
522 static Datum
524  FunctionCallInfo fcinfo)
525 {
526  BlockNumber nblocks;
527  BlockNumber blkno;
528  BufferAccessStrategy bstrategy;
529  pgstattuple_type stat = {0};
530 
531  /* prepare access strategy for this index */
532  bstrategy = GetAccessStrategy(BAS_BULKREAD);
533 
534  blkno = start;
535  for (;;)
536  {
537  /* Get the current relation length */
539  nblocks = RelationGetNumberOfBlocks(rel);
541 
542  /* Quit if we've scanned the whole relation */
543  if (blkno >= nblocks)
544  {
545  stat.table_len = (uint64) nblocks * BLCKSZ;
546 
547  break;
548  }
549 
550  for (; blkno < nblocks; blkno++)
551  {
553 
554  pagefn(&stat, rel, blkno, bstrategy);
555  }
556  }
557 
559 
560  return build_pgstattuple_type(&stat, fcinfo);
561 }
562 
563 /*
564  * pgstat_index_page -- for generic index page
565  */
566 static void
568  OffsetNumber minoff, OffsetNumber maxoff)
569 {
570  OffsetNumber i;
571 
572  stat->free_space += PageGetExactFreeSpace(page);
573 
574  for (i = minoff; i <= maxoff; i = OffsetNumberNext(i))
575  {
576  ItemId itemid = PageGetItemId(page, i);
577 
578  if (ItemIdIsDead(itemid))
579  {
580  stat->dead_tuple_count++;
581  stat->dead_tuple_len += ItemIdGetLength(itemid);
582  }
583  else
584  {
585  stat->tuple_count++;
586  stat->tuple_len += ItemIdGetLength(itemid);
587  }
588  }
589 }
uint32 BlockNumber
Definition: block.h:31
static Datum values[MAXATTR]
Definition: bootstrap.c:150
int Buffer
Definition: buf.h:23
struct BufferAccessStrategyData * BufferAccessStrategy
Definition: buf.h:44
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:4923
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:5140
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:793
@ BAS_BULKREAD
Definition: bufmgr.h:36
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:189
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:190
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:273
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:400
@ RBM_NORMAL
Definition: bufmgr.h:45
Size PageGetExactFreeSpace(Page page)
Definition: bufpage.c:958
Pointer Page
Definition: bufpage.h:81
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
static uint16 PageGetSpecialSize(Page page)
Definition: bufpage.h:316
#define MAXALIGN(LEN)
Definition: c.h:814
#define INT64_FORMAT
Definition: c.h:551
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 ereport(elevel,...)
Definition: elog.h:149
void err(int eval, const char *fmt,...)
Definition: err.c:43
HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)
Definition: execTuples.c:2222
AttInMetadata * TupleDescGetAttInMetadata(TupleDesc tupdesc)
Definition: execTuples.c:2173
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
BufferAccessStrategy GetAccessStrategy(BufferAccessStrategyType btype)
Definition: freelist.c:541
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 GistPageIsLeaf(page)
Definition: gist.h:169
#define GIST_ROOT_BLKNO
Definition: gist_private.h:262
#define GIST_SHARE
Definition: gist_private.h:42
void gistcheckpage(Relation rel, Buffer buf)
Definition: gistutil.c:785
#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 HASH_METAPAGE
Definition: hash.h:198
#define LH_PAGE_TYPE
Definition: hash.h:63
#define LH_BITMAP_PAGE
Definition: hash.h:56
#define LH_OVERFLOW_PAGE
Definition: hash.h:54
return str start
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
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)
int i
Definition: isn.c:73
#define ItemIdGetLength(itemId)
Definition: itemid.h:59
#define ItemIdIsDead(itemId)
Definition: itemid.h:113
static BlockNumber ItemPointerGetBlockNumber(const ItemPointerData *pointer)
Definition: itemptr.h:103
void LockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:420
void UnlockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:470
#define AccessShareLock
Definition: lockdefs.h:36
#define ExclusiveLock
Definition: lockdefs.h:42
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
RangeVar * makeRangeVarFromNameList(const List *names)
Definition: namespace.c:3539
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 BTREE_METAPAGE
Definition: nbtree.h:148
#define BT_READ
Definition: nbtree.h:719
#define P_IGNORE(opaque)
Definition: nbtree.h:225
#define OffsetNumberNext(offsetNumber)
Definition: off.h:52
uint16 OffsetNumber
Definition: off.h:24
#define FirstOffsetNumber
Definition: off.h:27
int errdetail_relkind_not_supported(char relkind)
Definition: pg_class.c:24
NameData relname
Definition: pg_class.h:38
static char * buf
Definition: pg_test_fsync.c:73
Datum pgstattuplebyid(PG_FUNCTION_ARGS)
Definition: pgstattuple.c:208
static Datum pgstat_relation(Relation rel, FunctionCallInfo fcinfo)
Definition: pgstattuple.c:241
#define NCHARS
static Datum pgstat_index(Relation rel, BlockNumber start, pgstat_page pagefn, FunctionCallInfo fcinfo)
Definition: pgstattuple.c:523
PG_MODULE_MAGIC
Definition: pgstattuple.c:42
static void pgstat_index_page(pgstattuple_type *stat, Page page, OffsetNumber minoff, OffsetNumber maxoff)
Definition: pgstattuple.c:567
Datum pgstattuple_v1_5(PG_FUNCTION_ARGS)
Definition: pgstattuple.c:193
PG_FUNCTION_INFO_V1(pgstattuple)
static void pgstat_gist_page(pgstattuple_type *stat, Relation rel, BlockNumber blkno, BufferAccessStrategy bstrategy)
Definition: pgstattuple.c:495
struct pgstattuple_type pgstattuple_type
void(* pgstat_page)(pgstattuple_type *, Relation, BlockNumber, BufferAccessStrategy)
Definition: pgstattuple.c:65
static Datum build_pgstattuple_type(pgstattuple_type *stat, FunctionCallInfo fcinfo)
Definition: pgstattuple.c:90
#define NCOLUMNS
static void pgstat_btree_page(pgstattuple_type *stat, Relation rel, BlockNumber blkno, BufferAccessStrategy bstrategy)
Definition: pgstattuple.c:409
Datum pgstattuplebyid_v1_5(PG_FUNCTION_ARGS)
Definition: pgstattuple.c:226
static Datum pgstat_heap(Relation rel, FunctionCallInfo fcinfo)
Definition: pgstattuple.c:314
Datum pgstattuple(PG_FUNCTION_ARGS)
Definition: pgstattuple.c:167
static void pgstat_hash_page(pgstattuple_type *stat, Relation rel, BlockNumber blkno, BufferAccessStrategy bstrategy)
Definition: pgstattuple.c:453
#define snprintf
Definition: port.h:238
uintptr_t Datum
Definition: postgres.h:64
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationGetRelationName(relation)
Definition: rel.h:539
#define RELATION_IS_OTHER_TEMP(relation)
Definition: rel.h:658
struct RelationData * Relation
Definition: relcache.h:27
@ MAIN_FORKNUM
Definition: relpath.h:58
@ 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
Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: relation.c:137
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:47
uint16 hasho_flag
Definition: hash.h:82
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_index rd_index
Definition: rel.h:192
Form_pg_class rd_rel
Definition: rel.h:111
uint64 tuple_count
Definition: pgstattuple.c:58
uint64 dead_tuple_len
Definition: pgstattuple.c:61
uint64 dead_tuple_count
Definition: pgstattuple.c:60
Definition: c.h:690
bool superuser(void)
Definition: superuser.c:46
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:1019
static TableScanDesc table_beginscan_strat(Relation rel, Snapshot snapshot, int nkeys, struct ScanKeyData *key, bool allow_strat, bool allow_sync)
Definition: tableam.h:932
List * textToQualifiedNameList(text *textval)
Definition: varlena.c:3374