PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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/varlena.h"
40
42 .name = "pgstattuple",
43 .version = PG_VERSION
44);
45
50
51/*
52 * struct pgstattuple_type
53 *
54 * tuple_percent, dead_tuple_percent and free_percent are computable,
55 * so not defined here.
56 */
57typedef struct pgstattuple_type
58{
64 uint64 free_space; /* free/reusable space in bytes */
66
69
71 FunctionCallInfo fcinfo);
73static Datum pgstat_heap(Relation rel, FunctionCallInfo fcinfo);
75 Relation rel, BlockNumber blkno,
76 BufferAccessStrategy bstrategy);
78 Relation rel, BlockNumber blkno,
79 BufferAccessStrategy bstrategy);
81 Relation rel, BlockNumber blkno,
82 BufferAccessStrategy bstrategy);
84 pgstat_page pagefn, FunctionCallInfo fcinfo);
86 OffsetNumber minoff, OffsetNumber maxoff);
87
88/*
89 * build_pgstattuple_type -- build a pgstattuple_type tuple
90 */
91static Datum
93{
94#define NCOLUMNS 9
95#define NCHARS 314
96
97 HeapTuple tuple;
98 char *values[NCOLUMNS];
99 char values_buf[NCOLUMNS][NCHARS];
100 int i;
101 double tuple_percent;
102 double dead_tuple_percent;
103 double free_percent; /* free/reusable space in % */
104 TupleDesc tupdesc;
105 AttInMetadata *attinmeta;
106
107 /* Build a tuple descriptor for our result type */
108 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
109 elog(ERROR, "return type must be a row type");
110
111 /*
112 * Generate attribute metadata needed later to produce tuples from raw C
113 * strings
114 */
115 attinmeta = TupleDescGetAttInMetadata(tupdesc);
116
117 if (stat->table_len == 0)
118 {
119 tuple_percent = 0.0;
120 dead_tuple_percent = 0.0;
121 free_percent = 0.0;
122 }
123 else
124 {
125 tuple_percent = 100.0 * stat->tuple_len / stat->table_len;
126 dead_tuple_percent = 100.0 * stat->dead_tuple_len / stat->table_len;
127 free_percent = 100.0 * stat->free_space / stat->table_len;
128 }
129
130 /*
131 * Prepare a values array for constructing the tuple. This should be an
132 * array of C strings which will be processed later by the appropriate
133 * "in" functions.
134 */
135 for (i = 0; i < NCOLUMNS; i++)
136 values[i] = values_buf[i];
137 i = 0;
138 snprintf(values[i++], NCHARS, INT64_FORMAT, stat->table_len);
139 snprintf(values[i++], NCHARS, INT64_FORMAT, stat->tuple_count);
140 snprintf(values[i++], NCHARS, INT64_FORMAT, stat->tuple_len);
141 snprintf(values[i++], NCHARS, "%.2f", tuple_percent);
142 snprintf(values[i++], NCHARS, INT64_FORMAT, stat->dead_tuple_count);
143 snprintf(values[i++], NCHARS, INT64_FORMAT, stat->dead_tuple_len);
144 snprintf(values[i++], NCHARS, "%.2f", dead_tuple_percent);
145 snprintf(values[i++], NCHARS, INT64_FORMAT, stat->free_space);
146 snprintf(values[i++], NCHARS, "%.2f", free_percent);
147
148 /* build a tuple */
149 tuple = BuildTupleFromCStrings(attinmeta, values);
150
151 /* make the tuple into a datum */
152 return HeapTupleGetDatum(tuple);
153}
154
155/* ----------
156 * pgstattuple:
157 * returns live/dead tuples info
158 *
159 * C FUNCTION definition
160 * pgstattuple(text) returns pgstattuple_type
161 *
162 * The superuser() check here must be kept as the library might be upgraded
163 * without the extension being upgraded, meaning that in pre-1.5 installations
164 * these functions could be called by any user.
165 * ----------
166 */
167
168Datum
170{
172 RangeVar *relrv;
173 Relation rel;
174
175 if (!superuser())
177 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
178 errmsg("must be superuser to use pgstattuple functions")));
179
180 /* open relation */
182 rel = relation_openrv(relrv, AccessShareLock);
183
184 PG_RETURN_DATUM(pgstat_relation(rel, fcinfo));
185}
186
187/*
188 * As of pgstattuple version 1.5, we no longer need to check if the user
189 * is a superuser because we REVOKE EXECUTE on the function from PUBLIC.
190 * Users can then grant access to it based on their policies.
191 *
192 * Otherwise identical to pgstattuple (above).
193 */
194Datum
196{
198 RangeVar *relrv;
199 Relation rel;
200
201 /* open relation */
203 rel = relation_openrv(relrv, AccessShareLock);
204
205 PG_RETURN_DATUM(pgstat_relation(rel, fcinfo));
206}
207
208/* Must keep superuser() check, see above. */
209Datum
211{
212 Oid relid = PG_GETARG_OID(0);
213 Relation rel;
214
215 if (!superuser())
217 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
218 errmsg("must be superuser to use pgstattuple functions")));
219
220 /* open relation */
221 rel = relation_open(relid, AccessShareLock);
222
223 PG_RETURN_DATUM(pgstat_relation(rel, fcinfo));
224}
225
226/* Remove superuser() check for 1.5 version, see above */
227Datum
229{
230 Oid relid = PG_GETARG_OID(0);
231 Relation rel;
232
233 /* open relation */
234 rel = relation_open(relid, AccessShareLock);
235
236 PG_RETURN_DATUM(pgstat_relation(rel, fcinfo));
237}
238
239/*
240 * pgstat_relation
241 */
242static Datum
244{
245 const char *err;
246
247 /*
248 * Reject attempts to read non-local temporary relations; we would be
249 * likely to get wrong data since we have no visibility into the owning
250 * session's local buffers.
251 */
252 if (RELATION_IS_OTHER_TEMP(rel))
254 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
255 errmsg("cannot access temporary tables of other sessions")));
256
257 if (RELKIND_HAS_TABLE_AM(rel->rd_rel->relkind) ||
258 rel->rd_rel->relkind == RELKIND_SEQUENCE)
259 {
260 return pgstat_heap(rel, fcinfo);
261 }
262 else if (rel->rd_rel->relkind == RELKIND_INDEX)
263 {
264 /* see pgstatindex_impl */
265 if (!rel->rd_index->indisvalid)
267 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
268 errmsg("index \"%s\" is not valid",
270
271 switch (rel->rd_rel->relam)
272 {
273 case BTREE_AM_OID:
274 return pgstat_index(rel, BTREE_METAPAGE + 1,
275 pgstat_btree_page, fcinfo);
276 case HASH_AM_OID:
277 return pgstat_index(rel, HASH_METAPAGE + 1,
278 pgstat_hash_page, fcinfo);
279 case GIST_AM_OID:
280 return pgstat_index(rel, GIST_ROOT_BLKNO + 1,
281 pgstat_gist_page, fcinfo);
282 case GIN_AM_OID:
283 err = "gin index";
284 break;
285 case SPGIST_AM_OID:
286 err = "spgist index";
287 break;
288 case BRIN_AM_OID:
289 err = "brin index";
290 break;
291 default:
292 err = "unknown index";
293 break;
294 }
296 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
297 errmsg("index \"%s\" (%s) is not supported",
299 }
300 else
301 {
303 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
304 errmsg("cannot get tuple-level statistics for relation \"%s\"",
307 }
308
309 return 0; /* should not happen */
310}
311
312/*
313 * pgstat_heap -- returns live/dead tuples info in a heap
314 */
315static Datum
317{
318 TableScanDesc scan;
319 HeapScanDesc hscan;
320 HeapTuple tuple;
321 BlockNumber nblocks;
322 BlockNumber block = 0; /* next block to count free space in */
323 BlockNumber tupblock;
324 Buffer buffer;
326 SnapshotData SnapshotDirty;
327
328 /*
329 * Sequences always use heap AM, but they don't show that in the catalogs.
330 */
331 if (rel->rd_rel->relkind != RELKIND_SEQUENCE &&
332 rel->rd_rel->relam != HEAP_TABLE_AM_OID)
334 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
335 errmsg("only heap AM is supported")));
336
337 /* Disable syncscan because we assume we scan from block zero upwards */
338 scan = table_beginscan_strat(rel, SnapshotAny, 0, NULL, true, false);
339 hscan = (HeapScanDesc) scan;
340
341 InitDirtySnapshot(SnapshotDirty);
342
343 nblocks = hscan->rs_nblocks; /* # blocks to be scanned */
344
345 /* scan the relation */
346 while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
347 {
349
350 /* must hold a buffer lock to call HeapTupleSatisfiesVisibility */
352
353 if (HeapTupleSatisfiesVisibility(tuple, &SnapshotDirty, hscan->rs_cbuf))
354 {
355 stat.tuple_len += tuple->t_len;
356 stat.tuple_count++;
357 }
358 else
359 {
360 stat.dead_tuple_len += tuple->t_len;
361 stat.dead_tuple_count++;
362 }
363
365
366 /*
367 * To avoid physically reading the table twice, try to do the
368 * free-space scan in parallel with the heap scan. However,
369 * heap_getnext may find no tuples on a given page, so we cannot
370 * simply examine the pages returned by the heap scan.
371 */
372 tupblock = ItemPointerGetBlockNumber(&tuple->t_self);
373
374 while (block <= tupblock)
375 {
377
378 buffer = ReadBufferExtended(rel, MAIN_FORKNUM, block,
379 RBM_NORMAL, hscan->rs_strategy);
381 stat.free_space += PageGetExactFreeSpace((Page) BufferGetPage(buffer));
382 UnlockReleaseBuffer(buffer);
383 block++;
384 }
385 }
386
387 while (block < nblocks)
388 {
390
391 buffer = ReadBufferExtended(rel, MAIN_FORKNUM, block,
392 RBM_NORMAL, hscan->rs_strategy);
394 stat.free_space += PageGetExactFreeSpace((Page) BufferGetPage(buffer));
395 UnlockReleaseBuffer(buffer);
396 block++;
397 }
398
399 table_endscan(scan);
401
402 stat.table_len = (uint64) nblocks * BLCKSZ;
403
404 return build_pgstattuple_type(&stat, fcinfo);
405}
406
407/*
408 * pgstat_btree_page -- check tuples in a btree page
409 */
410static void
412 BufferAccessStrategy bstrategy)
413{
414 Buffer buf;
415 Page page;
416
417 buf = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, bstrategy);
419 page = BufferGetPage(buf);
420
421 /* Page is valid, see what to do with it */
422 if (PageIsNew(page))
423 {
424 /* fully empty page */
425 stat->free_space += BLCKSZ;
426 }
427 else
428 {
429 BTPageOpaque opaque;
430
431 opaque = BTPageGetOpaque(page);
432 if (P_IGNORE(opaque))
433 {
434 /* deleted or half-dead page */
435 stat->free_space += BLCKSZ;
436 }
437 else if (P_ISLEAF(opaque))
438 {
441 }
442 else
443 {
444 /* internal page */
445 }
446 }
447
448 _bt_relbuf(rel, buf);
449}
450
451/*
452 * pgstat_hash_page -- check tuples in a hash page
453 */
454static void
456 BufferAccessStrategy bstrategy)
457{
458 Buffer buf;
459 Page page;
460
461 buf = _hash_getbuf_with_strategy(rel, blkno, HASH_READ, 0, bstrategy);
462 page = BufferGetPage(buf);
463
464 if (PageGetSpecialSize(page) == MAXALIGN(sizeof(HashPageOpaqueData)))
465 {
466 HashPageOpaque opaque;
467
468 opaque = HashPageGetOpaque(page);
469 switch (opaque->hasho_flag & LH_PAGE_TYPE)
470 {
471 case LH_UNUSED_PAGE:
472 stat->free_space += BLCKSZ;
473 break;
474 case LH_BUCKET_PAGE:
475 case LH_OVERFLOW_PAGE:
478 break;
479 case LH_BITMAP_PAGE:
480 case LH_META_PAGE:
481 default:
482 break;
483 }
484 }
485 else
486 {
487 /* maybe corrupted */
488 }
489
490 _hash_relbuf(rel, buf);
491}
492
493/*
494 * pgstat_gist_page -- check tuples in a gist page
495 */
496static void
498 BufferAccessStrategy bstrategy)
499{
500 Buffer buf;
501 Page page;
502
503 buf = ReadBufferExtended(rel, MAIN_FORKNUM, blkno, RBM_NORMAL, bstrategy);
505 gistcheckpage(rel, buf);
506 page = BufferGetPage(buf);
507
508 if (GistPageIsLeaf(page))
509 {
512 }
513 else
514 {
515 /* root or node */
516 }
517
519}
520
521/*
522 * pgstat_index -- returns live/dead tuples info in a generic index
523 */
524static Datum
526 FunctionCallInfo fcinfo)
527{
528 BlockNumber nblocks;
529 BlockNumber blkno;
530 BufferAccessStrategy bstrategy;
532
533 /* prepare access strategy for this index */
534 bstrategy = GetAccessStrategy(BAS_BULKREAD);
535
536 blkno = start;
537 for (;;)
538 {
539 /* Get the current relation length */
541 nblocks = RelationGetNumberOfBlocks(rel);
543
544 /* Quit if we've scanned the whole relation */
545 if (blkno >= nblocks)
546 {
547 stat.table_len = (uint64) nblocks * BLCKSZ;
548
549 break;
550 }
551
552 for (; blkno < nblocks; blkno++)
553 {
555
556 pagefn(&stat, rel, blkno, bstrategy);
557 }
558 }
559
561
562 return build_pgstattuple_type(&stat, fcinfo);
563}
564
565/*
566 * pgstat_index_page -- for generic index page
567 */
568static void
570 OffsetNumber minoff, OffsetNumber maxoff)
571{
573
574 stat->free_space += PageGetExactFreeSpace(page);
575
576 for (i = minoff; i <= maxoff; i = OffsetNumberNext(i))
577 {
578 ItemId itemid = PageGetItemId(page, i);
579
580 if (ItemIdIsDead(itemid))
581 {
582 stat->dead_tuple_count++;
583 stat->dead_tuple_len += ItemIdGetLength(itemid);
584 }
585 else
586 {
587 stat->tuple_count++;
588 stat->tuple_len += ItemIdGetLength(itemid);
589 }
590 }
591}
uint32 BlockNumber
Definition: block.h:31
static Datum values[MAXATTR]
Definition: bootstrap.c:151
int Buffer
Definition: buf.h:23
struct BufferAccessStrategyData * BufferAccessStrategy
Definition: buf.h:44
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:5320
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:5537
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:798
@ BAS_BULKREAD
Definition: bufmgr.h:37
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:196
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:197
#define RelationGetNumberOfBlocks(reln)
Definition: bufmgr.h:280
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:414
@ RBM_NORMAL
Definition: bufmgr.h:46
Size PageGetExactFreeSpace(const PageData *page)
Definition: bufpage.c:957
static uint16 PageGetSpecialSize(const PageData *page)
Definition: bufpage.h:317
static bool PageIsNew(const PageData *page)
Definition: bufpage.h:234
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
Definition: bufpage.h:244
PageData * Page
Definition: bufpage.h:82
static OffsetNumber PageGetMaxOffsetNumber(const PageData *page)
Definition: bufpage.h:372
#define MAXALIGN(LEN)
Definition: c.h:782
#define INT64_FORMAT
Definition: c.h:520
uint64_t uint64
Definition: c.h:503
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
#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:2324
AttInMetadata * TupleDescGetAttInMetadata(TupleDesc tupdesc)
Definition: execTuples.c:2275
#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:170
#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:1314
struct HeapScanDescData * HeapScanDesc
Definition: heapam.h:100
bool HeapTupleSatisfiesVisibility(HeapTuple htup, Snapshot snapshot, Buffer buffer)
int i
Definition: isn.c:77
#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:424
void UnlockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:474
#define AccessShareLock
Definition: lockdefs.h:36
#define ExclusiveLock
Definition: lockdefs.h:42
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:123
RangeVar * makeRangeVarFromNameList(const List *names)
Definition: namespace.c:3554
void _bt_relbuf(Relation rel, Buffer buf)
Definition: nbtpage.c:1023
#define P_ISLEAF(opaque)
Definition: nbtree.h:221
#define BTPageGetOpaque(page)
Definition: nbtree.h:74
#define P_FIRSTDATAKEY(opaque)
Definition: nbtree.h:370
#define BTREE_METAPAGE
Definition: nbtree.h:149
#define BT_READ
Definition: nbtree.h:730
#define P_IGNORE(opaque)
Definition: nbtree.h:226
#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:72
Datum pgstattuplebyid(PG_FUNCTION_ARGS)
Definition: pgstattuple.c:210
static Datum pgstat_relation(Relation rel, FunctionCallInfo fcinfo)
Definition: pgstattuple.c:243
#define NCHARS
PG_MODULE_MAGIC_EXT(.name="pgstattuple",.version=PG_VERSION)
static Datum pgstat_index(Relation rel, BlockNumber start, pgstat_page pagefn, FunctionCallInfo fcinfo)
Definition: pgstattuple.c:525
static void pgstat_index_page(pgstattuple_type *stat, Page page, OffsetNumber minoff, OffsetNumber maxoff)
Definition: pgstattuple.c:569
Datum pgstattuple_v1_5(PG_FUNCTION_ARGS)
Definition: pgstattuple.c:195
PG_FUNCTION_INFO_V1(pgstattuple)
static void pgstat_gist_page(pgstattuple_type *stat, Relation rel, BlockNumber blkno, BufferAccessStrategy bstrategy)
Definition: pgstattuple.c:497
struct pgstattuple_type pgstattuple_type
void(* pgstat_page)(pgstattuple_type *, Relation, BlockNumber, BufferAccessStrategy)
Definition: pgstattuple.c:67
static Datum build_pgstattuple_type(pgstattuple_type *stat, FunctionCallInfo fcinfo)
Definition: pgstattuple.c:92
#define NCOLUMNS
static void pgstat_btree_page(pgstattuple_type *stat, Relation rel, BlockNumber blkno, BufferAccessStrategy bstrategy)
Definition: pgstattuple.c:411
Datum pgstattuplebyid_v1_5(PG_FUNCTION_ARGS)
Definition: pgstattuple.c:228
static Datum pgstat_heap(Relation rel, FunctionCallInfo fcinfo)
Definition: pgstattuple.c:316
Datum pgstattuple(PG_FUNCTION_ARGS)
Definition: pgstattuple.c:169
static void pgstat_hash_page(pgstattuple_type *stat, Relation rel, BlockNumber blkno, BufferAccessStrategy bstrategy)
Definition: pgstattuple.c:455
#define snprintf
Definition: port.h:239
uintptr_t Datum
Definition: postgres.h:69
unsigned int Oid
Definition: postgres_ext.h:30
#define RelationGetRelationName(relation)
Definition: rel.h:550
#define RELATION_IS_OTHER_TEMP(relation)
Definition: rel.h:669
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:42
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:60
uint64 dead_tuple_len
Definition: pgstattuple.c:63
uint64 dead_tuple_count
Definition: pgstattuple.c:62
Definition: c.h:658
bool superuser(void)
Definition: superuser.c:46
static void table_endscan(TableScanDesc scan)
Definition: tableam.h:979
static TableScanDesc table_beginscan_strat(Relation rel, Snapshot snapshot, int nkeys, struct ScanKeyData *key, bool allow_strat, bool allow_sync)
Definition: tableam.h:894
List * textToQualifiedNameList(text *textval)
Definition: varlena.c:3467
const char * name