PostgreSQL Source Code  git master
dbsize.c File Reference
#include "postgres.h"
#include <sys/stat.h>
#include "access/htup_details.h"
#include "access/relation.h"
#include "catalog/catalog.h"
#include "catalog/namespace.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_database.h"
#include "catalog/pg_tablespace.h"
#include "commands/dbcommands.h"
#include "commands/tablespace.h"
#include "miscadmin.h"
#include "storage/fd.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/numeric.h"
#include "utils/rel.h"
#include "utils/relfilenumbermap.h"
#include "utils/relmapper.h"
#include "utils/syscache.h"
Include dependency graph for dbsize.c:

Go to the source code of this file.

Data Structures

struct  size_pretty_unit
 

Macros

#define half_rounded(x)   (((x) + ((x) < 0 ? -1 : 1)) / 2)
 

Functions

static int64 db_dir_size (const char *path)
 
static int64 calculate_database_size (Oid dbOid)
 
Datum pg_database_size_oid (PG_FUNCTION_ARGS)
 
Datum pg_database_size_name (PG_FUNCTION_ARGS)
 
static int64 calculate_tablespace_size (Oid tblspcOid)
 
Datum pg_tablespace_size_oid (PG_FUNCTION_ARGS)
 
Datum pg_tablespace_size_name (PG_FUNCTION_ARGS)
 
static int64 calculate_relation_size (RelFileLocator *rfn, BackendId backend, ForkNumber forknum)
 
Datum pg_relation_size (PG_FUNCTION_ARGS)
 
static int64 calculate_toast_table_size (Oid toastrelid)
 
static int64 calculate_table_size (Relation rel)
 
static int64 calculate_indexes_size (Relation rel)
 
Datum pg_table_size (PG_FUNCTION_ARGS)
 
Datum pg_indexes_size (PG_FUNCTION_ARGS)
 
static int64 calculate_total_relation_size (Relation rel)
 
Datum pg_total_relation_size (PG_FUNCTION_ARGS)
 
Datum pg_size_pretty (PG_FUNCTION_ARGS)
 
static char * numeric_to_cstring (Numeric n)
 
static bool numeric_is_less (Numeric a, Numeric b)
 
static Numeric numeric_absolute (Numeric n)
 
static Numeric numeric_half_rounded (Numeric n)
 
static Numeric numeric_truncated_divide (Numeric n, int64 divisor)
 
Datum pg_size_pretty_numeric (PG_FUNCTION_ARGS)
 
Datum pg_size_bytes (PG_FUNCTION_ARGS)
 
Datum pg_relation_filenode (PG_FUNCTION_ARGS)
 
Datum pg_filenode_relation (PG_FUNCTION_ARGS)
 
Datum pg_relation_filepath (PG_FUNCTION_ARGS)
 

Variables

static const struct size_pretty_unit size_pretty_units []
 

Macro Definition Documentation

◆ half_rounded

#define half_rounded (   x)    (((x) + ((x) < 0 ? -1 : 1)) / 2)

Definition at line 36 of file dbsize.c.

Function Documentation

◆ calculate_database_size()

static int64 calculate_database_size ( Oid  dbOid)
static

Definition at line 106 of file dbsize.c.

107 {
108  int64 totalsize;
109  DIR *dirdesc;
110  struct dirent *direntry;
111  char dirpath[MAXPGPATH];
112  char pathname[MAXPGPATH + 21 + sizeof(TABLESPACE_VERSION_DIRECTORY)];
113  AclResult aclresult;
114 
115  /*
116  * User must have connect privilege for target database or have privileges
117  * of pg_read_all_stats
118  */
119  aclresult = object_aclcheck(DatabaseRelationId, dbOid, GetUserId(), ACL_CONNECT);
120  if (aclresult != ACLCHECK_OK &&
121  !has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS))
122  {
123  aclcheck_error(aclresult, OBJECT_DATABASE,
124  get_database_name(dbOid));
125  }
126 
127  /* Shared storage in pg_global is not counted */
128 
129  /* Include pg_default storage */
130  snprintf(pathname, sizeof(pathname), "base/%u", dbOid);
131  totalsize = db_dir_size(pathname);
132 
133  /* Scan the non-default tablespaces */
134  snprintf(dirpath, MAXPGPATH, "pg_tblspc");
135  dirdesc = AllocateDir(dirpath);
136 
137  while ((direntry = ReadDir(dirdesc, dirpath)) != NULL)
138  {
140 
141  if (strcmp(direntry->d_name, ".") == 0 ||
142  strcmp(direntry->d_name, "..") == 0)
143  continue;
144 
145  snprintf(pathname, sizeof(pathname), "pg_tblspc/%s/%s/%u",
146  direntry->d_name, TABLESPACE_VERSION_DIRECTORY, dbOid);
147  totalsize += db_dir_size(pathname);
148  }
149 
150  FreeDir(dirdesc);
151 
152  return totalsize;
153 }
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:4949
AclResult
Definition: acl.h:183
@ ACLCHECK_OK
Definition: acl.h:184
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3485
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition: aclchk.c:4598
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2981
static int64 db_dir_size(const char *path)
Definition: dbsize.c:62
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2709
int FreeDir(DIR *dir)
Definition: fd.c:2761
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2643
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:121
Oid GetUserId(void)
Definition: miscinit.c:497
@ OBJECT_DATABASE
Definition: parsenodes.h:1871
#define ACL_CONNECT
Definition: parsenodes.h:94
#define MAXPGPATH
#define snprintf
Definition: port.h:238
#define TABLESPACE_VERSION_DIRECTORY
Definition: relpath.h:33
Definition: dirent.c:26
Definition: dirent.h:10
char d_name[MAX_PATH]
Definition: dirent.h:15

References ACL_CONNECT, aclcheck_error(), ACLCHECK_OK, AllocateDir(), CHECK_FOR_INTERRUPTS, dirent::d_name, db_dir_size(), FreeDir(), get_database_name(), GetUserId(), has_privs_of_role(), MAXPGPATH, object_aclcheck(), OBJECT_DATABASE, ReadDir(), snprintf, and TABLESPACE_VERSION_DIRECTORY.

Referenced by pg_database_size_name(), and pg_database_size_oid().

◆ calculate_indexes_size()

static int64 calculate_indexes_size ( Relation  rel)
static

Definition at line 439 of file dbsize.c.

440 {
441  int64 size = 0;
442 
443  /*
444  * Aggregate all indexes on the given relation
445  */
446  if (rel->rd_rel->relhasindex)
447  {
448  List *index_oids = RelationGetIndexList(rel);
449  ListCell *cell;
450 
451  foreach(cell, index_oids)
452  {
453  Oid idxOid = lfirst_oid(cell);
454  Relation idxRel;
455  ForkNumber forkNum;
456 
457  idxRel = relation_open(idxOid, AccessShareLock);
458 
459  for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
460  size += calculate_relation_size(&(idxRel->rd_locator),
461  idxRel->rd_backend,
462  forkNum);
463 
465  }
466 
467  list_free(index_oids);
468  }
469 
470  return size;
471 }
static int64 calculate_relation_size(RelFileLocator *rfn, BackendId backend, ForkNumber forknum)
Definition: dbsize.c:296
void list_free(List *list)
Definition: list.c:1545
#define AccessShareLock
Definition: lockdefs.h:36
#define lfirst_oid(lc)
Definition: pg_list.h:172
unsigned int Oid
Definition: postgres_ext.h:31
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4738
ForkNumber
Definition: relpath.h:48
#define MAX_FORKNUM
Definition: relpath.h:62
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
Definition: pg_list.h:52
BackendId rd_backend
Definition: rel.h:59
RelFileLocator rd_locator
Definition: rel.h:56
Form_pg_class rd_rel
Definition: rel.h:110

References AccessShareLock, calculate_relation_size(), lfirst_oid, list_free(), MAX_FORKNUM, RelationData::rd_backend, RelationData::rd_locator, RelationData::rd_rel, relation_close(), relation_open(), and RelationGetIndexList().

Referenced by calculate_total_relation_size(), and pg_indexes_size().

◆ calculate_relation_size()

static int64 calculate_relation_size ( RelFileLocator rfn,
BackendId  backend,
ForkNumber  forknum 
)
static

Definition at line 296 of file dbsize.c.

297 {
298  int64 totalsize = 0;
299  char *relationpath;
300  char pathname[MAXPGPATH];
301  unsigned int segcount = 0;
302 
303  relationpath = relpathbackend(*rfn, backend, forknum);
304 
305  for (segcount = 0;; segcount++)
306  {
307  struct stat fst;
308 
310 
311  if (segcount == 0)
312  snprintf(pathname, MAXPGPATH, "%s",
313  relationpath);
314  else
315  snprintf(pathname, MAXPGPATH, "%s.%u",
316  relationpath, segcount);
317 
318  if (stat(pathname, &fst) < 0)
319  {
320  if (errno == ENOENT)
321  break;
322  else
323  ereport(ERROR,
325  errmsg("could not stat file \"%s\": %m", pathname)));
326  }
327  totalsize += fst.st_size;
328  }
329 
330  return totalsize;
331 }
int errcode_for_file_access(void)
Definition: elog.c:718
int errmsg(const char *fmt,...)
Definition: elog.c:906
#define ERROR
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:145
#define relpathbackend(rlocator, backend, forknum)
Definition: relpath.h:85
#define stat
Definition: win32_port.h:286

References CHECK_FOR_INTERRUPTS, ereport, errcode_for_file_access(), errmsg(), ERROR, MAXPGPATH, relpathbackend, snprintf, stat::st_size, and stat.

Referenced by calculate_indexes_size(), calculate_table_size(), calculate_toast_table_size(), and pg_relation_size().

◆ calculate_table_size()

static int64 calculate_table_size ( Relation  rel)
static

Definition at line 412 of file dbsize.c.

413 {
414  int64 size = 0;
415  ForkNumber forkNum;
416 
417  /*
418  * heap size, including FSM and VM
419  */
420  for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
421  size += calculate_relation_size(&(rel->rd_locator), rel->rd_backend,
422  forkNum);
423 
424  /*
425  * Size of toast relation
426  */
427  if (OidIsValid(rel->rd_rel->reltoastrelid))
428  size += calculate_toast_table_size(rel->rd_rel->reltoastrelid);
429 
430  return size;
431 }
#define OidIsValid(objectId)
Definition: c.h:711
static int64 calculate_toast_table_size(Oid toastrelid)
Definition: dbsize.c:366

References calculate_relation_size(), calculate_toast_table_size(), MAX_FORKNUM, OidIsValid, RelationData::rd_backend, RelationData::rd_locator, and RelationData::rd_rel.

Referenced by calculate_total_relation_size(), and pg_table_size().

◆ calculate_tablespace_size()

static int64 calculate_tablespace_size ( Oid  tblspcOid)
static

Definition at line 190 of file dbsize.c.

191 {
192  char tblspcPath[MAXPGPATH];
193  char pathname[MAXPGPATH * 2];
194  int64 totalsize = 0;
195  DIR *dirdesc;
196  struct dirent *direntry;
197  AclResult aclresult;
198 
199  /*
200  * User must have privileges of pg_read_all_stats or have CREATE privilege
201  * for target tablespace, either explicitly granted or implicitly because
202  * it is default for current database.
203  */
204  if (tblspcOid != MyDatabaseTableSpace &&
205  !has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS))
206  {
207  aclresult = object_aclcheck(TableSpaceRelationId, tblspcOid, GetUserId(), ACL_CREATE);
208  if (aclresult != ACLCHECK_OK)
210  get_tablespace_name(tblspcOid));
211  }
212 
213  if (tblspcOid == DEFAULTTABLESPACE_OID)
214  snprintf(tblspcPath, MAXPGPATH, "base");
215  else if (tblspcOid == GLOBALTABLESPACE_OID)
216  snprintf(tblspcPath, MAXPGPATH, "global");
217  else
218  snprintf(tblspcPath, MAXPGPATH, "pg_tblspc/%u/%s", tblspcOid,
220 
221  dirdesc = AllocateDir(tblspcPath);
222 
223  if (!dirdesc)
224  return -1;
225 
226  while ((direntry = ReadDir(dirdesc, tblspcPath)) != NULL)
227  {
228  struct stat fst;
229 
231 
232  if (strcmp(direntry->d_name, ".") == 0 ||
233  strcmp(direntry->d_name, "..") == 0)
234  continue;
235 
236  snprintf(pathname, sizeof(pathname), "%s/%s", tblspcPath, direntry->d_name);
237 
238  if (stat(pathname, &fst) < 0)
239  {
240  if (errno == ENOENT)
241  continue;
242  else
243  ereport(ERROR,
245  errmsg("could not stat file \"%s\": %m", pathname)));
246  }
247 
248  if (S_ISDIR(fst.st_mode))
249  totalsize += db_dir_size(pathname);
250 
251  totalsize += fst.st_size;
252  }
253 
254  FreeDir(dirdesc);
255 
256  return totalsize;
257 }
char * get_tablespace_name(Oid spc_oid)
Definition: tablespace.c:1478
Oid MyDatabaseTableSpace
Definition: globals.c:91
@ OBJECT_TABLESPACE
Definition: parsenodes.h:1904
#define ACL_CREATE
Definition: parsenodes.h:92
#define S_ISDIR(m)
Definition: win32_port.h:327

References ACL_CREATE, aclcheck_error(), ACLCHECK_OK, AllocateDir(), CHECK_FOR_INTERRUPTS, dirent::d_name, db_dir_size(), ereport, errcode_for_file_access(), errmsg(), ERROR, FreeDir(), get_tablespace_name(), GetUserId(), has_privs_of_role(), MAXPGPATH, MyDatabaseTableSpace, object_aclcheck(), OBJECT_TABLESPACE, ReadDir(), S_ISDIR, snprintf, stat::st_mode, stat::st_size, stat, and TABLESPACE_VERSION_DIRECTORY.

Referenced by pg_tablespace_size_name(), and pg_tablespace_size_oid().

◆ calculate_toast_table_size()

static int64 calculate_toast_table_size ( Oid  toastrelid)
static

Definition at line 366 of file dbsize.c.

367 {
368  int64 size = 0;
369  Relation toastRel;
370  ForkNumber forkNum;
371  ListCell *lc;
372  List *indexlist;
373 
374  toastRel = relation_open(toastrelid, AccessShareLock);
375 
376  /* toast heap size, including FSM and VM size */
377  for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
378  size += calculate_relation_size(&(toastRel->rd_locator),
379  toastRel->rd_backend, forkNum);
380 
381  /* toast index size, including FSM and VM size */
382  indexlist = RelationGetIndexList(toastRel);
383 
384  /* Size is calculated using all the indexes available */
385  foreach(lc, indexlist)
386  {
387  Relation toastIdxRel;
388 
389  toastIdxRel = relation_open(lfirst_oid(lc),
391  for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
392  size += calculate_relation_size(&(toastIdxRel->rd_locator),
393  toastIdxRel->rd_backend, forkNum);
394 
395  relation_close(toastIdxRel, AccessShareLock);
396  }
397  list_free(indexlist);
398  relation_close(toastRel, AccessShareLock);
399 
400  return size;
401 }

References AccessShareLock, calculate_relation_size(), lfirst_oid, list_free(), MAX_FORKNUM, RelationData::rd_backend, RelationData::rd_locator, relation_close(), relation_open(), and RelationGetIndexList().

Referenced by calculate_table_size().

◆ calculate_total_relation_size()

static int64 calculate_total_relation_size ( Relation  rel)
static

Definition at line 516 of file dbsize.c.

517 {
518  int64 size;
519 
520  /*
521  * Aggregate the table size, this includes size of the heap, toast and
522  * toast index with free space and visibility map
523  */
524  size = calculate_table_size(rel);
525 
526  /*
527  * Add size of all attached indexes as well
528  */
529  size += calculate_indexes_size(rel);
530 
531  return size;
532 }
static int64 calculate_indexes_size(Relation rel)
Definition: dbsize.c:439
static int64 calculate_table_size(Relation rel)
Definition: dbsize.c:412

References calculate_indexes_size(), and calculate_table_size().

Referenced by pg_total_relation_size().

◆ db_dir_size()

static int64 db_dir_size ( const char *  path)
static

Definition at line 62 of file dbsize.c.

63 {
64  int64 dirsize = 0;
65  struct dirent *direntry;
66  DIR *dirdesc;
67  char filename[MAXPGPATH * 2];
68 
69  dirdesc = AllocateDir(path);
70 
71  if (!dirdesc)
72  return 0;
73 
74  while ((direntry = ReadDir(dirdesc, path)) != NULL)
75  {
76  struct stat fst;
77 
79 
80  if (strcmp(direntry->d_name, ".") == 0 ||
81  strcmp(direntry->d_name, "..") == 0)
82  continue;
83 
84  snprintf(filename, sizeof(filename), "%s/%s", path, direntry->d_name);
85 
86  if (stat(filename, &fst) < 0)
87  {
88  if (errno == ENOENT)
89  continue;
90  else
91  ereport(ERROR,
93  errmsg("could not stat file \"%s\": %m", filename)));
94  }
95  dirsize += fst.st_size;
96  }
97 
98  FreeDir(dirdesc);
99  return dirsize;
100 }
static char * filename
Definition: pg_dumpall.c:119

References AllocateDir(), CHECK_FOR_INTERRUPTS, dirent::d_name, ereport, errcode_for_file_access(), errmsg(), ERROR, filename, FreeDir(), MAXPGPATH, ReadDir(), snprintf, stat::st_size, and stat.

Referenced by calculate_database_size(), and calculate_tablespace_size().

◆ numeric_absolute()

static Numeric numeric_absolute ( Numeric  n)
static

Definition at line 612 of file dbsize.c.

613 {
614  Datum d = NumericGetDatum(n);
615  Datum result;
616 
617  result = DirectFunctionCall1(numeric_abs, d);
618  return DatumGetNumeric(result);
619 }
Datum numeric_abs(PG_FUNCTION_ARGS)
Definition: numeric.c:1312
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:642
static Numeric DatumGetNumeric(Datum X)
Definition: numeric.h:60
static Datum NumericGetDatum(Numeric X)
Definition: numeric.h:72
uintptr_t Datum
Definition: postgres.h:412

References DatumGetNumeric(), DirectFunctionCall1, numeric_abs(), and NumericGetDatum().

Referenced by pg_size_pretty_numeric().

◆ numeric_half_rounded()

static Numeric numeric_half_rounded ( Numeric  n)
static

Definition at line 622 of file dbsize.c.

623 {
624  Datum d = NumericGetDatum(n);
625  Datum zero;
626  Datum one;
627  Datum two;
628  Datum result;
629 
633 
635  d = DirectFunctionCall2(numeric_add, d, one);
636  else
637  d = DirectFunctionCall2(numeric_sub, d, one);
638 
639  result = DirectFunctionCall2(numeric_div_trunc, d, two);
640  return DatumGetNumeric(result);
641 }
Datum numeric_sub(PG_FUNCTION_ARGS)
Definition: numeric.c:2842
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4137
Datum numeric_ge(PG_FUNCTION_ARGS)
Definition: numeric.c:2377
Datum numeric_div_trunc(PG_FUNCTION_ARGS)
Definition: numeric.c:3176
Datum numeric_add(PG_FUNCTION_ARGS)
Definition: numeric.c:2765
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:644
static bool DatumGetBool(Datum X)
Definition: postgres.h:438

References DatumGetBool(), DatumGetNumeric(), DirectFunctionCall2, int64_to_numeric(), numeric_add(), numeric_div_trunc(), numeric_ge(), numeric_sub(), and NumericGetDatum().

Referenced by pg_size_pretty_numeric().

◆ numeric_is_less()

static bool numeric_is_less ( Numeric  a,
Numeric  b 
)
static

Definition at line 603 of file dbsize.c.

604 {
605  Datum da = NumericGetDatum(a);
606  Datum db = NumericGetDatum(b);
607 
609 }
Datum numeric_lt(PG_FUNCTION_ARGS)
Definition: numeric.c:2392
int b
Definition: isn.c:70
int a
Definition: isn.c:69

References a, b, DatumGetBool(), DirectFunctionCall2, numeric_lt(), and NumericGetDatum().

Referenced by pg_size_pretty_numeric().

◆ numeric_to_cstring()

static char* numeric_to_cstring ( Numeric  n)
static

Definition at line 595 of file dbsize.c.

596 {
597  Datum d = NumericGetDatum(n);
598 
600 }
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:735
static char * DatumGetCString(Datum X)
Definition: postgres.h:683

References DatumGetCString(), DirectFunctionCall1, numeric_out(), and NumericGetDatum().

Referenced by pg_size_pretty_numeric().

◆ numeric_truncated_divide()

static Numeric numeric_truncated_divide ( Numeric  n,
int64  divisor 
)
static

Definition at line 644 of file dbsize.c.

645 {
646  Datum d = NumericGetDatum(n);
647  Datum divisor_numeric;
648  Datum result;
649 
650  divisor_numeric = NumericGetDatum(int64_to_numeric(divisor));
651  result = DirectFunctionCall2(numeric_div_trunc, d, divisor_numeric);
652  return DatumGetNumeric(result);
653 }

References DatumGetNumeric(), DirectFunctionCall2, int64_to_numeric(), numeric_div_trunc(), and NumericGetDatum().

Referenced by pg_size_pretty_numeric().

◆ pg_database_size_name()

Datum pg_database_size_name ( PG_FUNCTION_ARGS  )

Definition at line 170 of file dbsize.c.

171 {
173  Oid dbOid = get_database_oid(NameStr(*dbName), false);
174  int64 size;
175 
176  size = calculate_database_size(dbOid);
177 
178  if (size == 0)
179  PG_RETURN_NULL();
180 
181  PG_RETURN_INT64(size);
182 }
#define NameStr(name)
Definition: c.h:682
Oid get_database_oid(const char *dbname, bool missing_ok)
Definition: dbcommands.c:2934
static int64 calculate_database_size(Oid dbOid)
Definition: dbsize.c:106
#define PG_RETURN_INT64(x)
Definition: fmgr.h:368
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_GETARG_NAME(n)
Definition: fmgr.h:278
const char * dbName
Definition: pgbench.c:306
Definition: c.h:677

References calculate_database_size(), dbName, get_database_oid(), NameStr, PG_GETARG_NAME, PG_RETURN_INT64, and PG_RETURN_NULL.

◆ pg_database_size_oid()

Datum pg_database_size_oid ( PG_FUNCTION_ARGS  )

Definition at line 156 of file dbsize.c.

157 {
158  Oid dbOid = PG_GETARG_OID(0);
159  int64 size;
160 
161  size = calculate_database_size(dbOid);
162 
163  if (size == 0)
164  PG_RETURN_NULL();
165 
166  PG_RETURN_INT64(size);
167 }
#define PG_GETARG_OID(n)
Definition: fmgr.h:275

References calculate_database_size(), PG_GETARG_OID, PG_RETURN_INT64, and PG_RETURN_NULL.

◆ pg_filenode_relation()

Datum pg_filenode_relation ( PG_FUNCTION_ARGS  )

Definition at line 899 of file dbsize.c.

900 {
901  Oid reltablespace = PG_GETARG_OID(0);
902  RelFileNumber relfilenumber = PG_GETARG_OID(1);
903  Oid heaprel;
904 
905  /* test needed so RelidByRelfilenumber doesn't misbehave */
906  if (!RelFileNumberIsValid(relfilenumber))
907  PG_RETURN_NULL();
908 
909  heaprel = RelidByRelfilenumber(reltablespace, relfilenumber);
910 
911  if (!OidIsValid(heaprel))
912  PG_RETURN_NULL();
913  else
914  PG_RETURN_OID(heaprel);
915 }
#define PG_RETURN_OID(x)
Definition: fmgr.h:360
Oid RelidByRelfilenumber(Oid reltablespace, RelFileNumber relfilenumber)
Oid RelFileNumber
Definition: relpath.h:25
#define RelFileNumberIsValid(relnumber)
Definition: relpath.h:27

References OidIsValid, PG_GETARG_OID, PG_RETURN_NULL, PG_RETURN_OID, RelFileNumberIsValid, and RelidByRelfilenumber().

◆ pg_indexes_size()

Datum pg_indexes_size ( PG_FUNCTION_ARGS  )

Definition at line 493 of file dbsize.c.

494 {
495  Oid relOid = PG_GETARG_OID(0);
496  Relation rel;
497  int64 size;
498 
499  rel = try_relation_open(relOid, AccessShareLock);
500 
501  if (rel == NULL)
502  PG_RETURN_NULL();
503 
504  size = calculate_indexes_size(rel);
505 
507 
508  PG_RETURN_INT64(size);
509 }
Relation try_relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:89

References AccessShareLock, calculate_indexes_size(), PG_GETARG_OID, PG_RETURN_INT64, PG_RETURN_NULL, relation_close(), and try_relation_open().

◆ pg_relation_filenode()

Datum pg_relation_filenode ( PG_FUNCTION_ARGS  )

Definition at line 851 of file dbsize.c.

852 {
853  Oid relid = PG_GETARG_OID(0);
854  RelFileNumber result;
855  HeapTuple tuple;
856  Form_pg_class relform;
857 
858  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
859  if (!HeapTupleIsValid(tuple))
860  PG_RETURN_NULL();
861  relform = (Form_pg_class) GETSTRUCT(tuple);
862 
863  if (RELKIND_HAS_STORAGE(relform->relkind))
864  {
865  if (relform->relfilenode)
866  result = relform->relfilenode;
867  else /* Consult the relation mapper */
868  result = RelationMapOidToFilenumber(relid,
869  relform->relisshared);
870  }
871  else
872  {
873  /* no storage, return NULL */
874  result = InvalidRelFileNumber;
875  }
876 
877  ReleaseSysCache(tuple);
878 
879  if (!RelFileNumberIsValid(result))
880  PG_RETURN_NULL();
881 
882  PG_RETURN_OID(result);
883 }
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:649
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:600
RelFileNumber RelationMapOidToFilenumber(Oid relationId, bool shared)
Definition: relmapper.c:166
#define InvalidRelFileNumber
Definition: relpath.h:26
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1221
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1173
@ RELOID
Definition: syscache.h:89

References GETSTRUCT, HeapTupleIsValid, InvalidRelFileNumber, ObjectIdGetDatum(), PG_GETARG_OID, PG_RETURN_NULL, PG_RETURN_OID, RelationMapOidToFilenumber(), ReleaseSysCache(), RelFileNumberIsValid, RELOID, and SearchSysCache1().

◆ pg_relation_filepath()

Datum pg_relation_filepath ( PG_FUNCTION_ARGS  )

Definition at line 923 of file dbsize.c.

924 {
925  Oid relid = PG_GETARG_OID(0);
926  HeapTuple tuple;
927  Form_pg_class relform;
928  RelFileLocator rlocator;
929  BackendId backend;
930  char *path;
931 
932  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
933  if (!HeapTupleIsValid(tuple))
934  PG_RETURN_NULL();
935  relform = (Form_pg_class) GETSTRUCT(tuple);
936 
937  if (RELKIND_HAS_STORAGE(relform->relkind))
938  {
939  /* This logic should match RelationInitPhysicalAddr */
940  if (relform->reltablespace)
941  rlocator.spcOid = relform->reltablespace;
942  else
943  rlocator.spcOid = MyDatabaseTableSpace;
944  if (rlocator.spcOid == GLOBALTABLESPACE_OID)
945  rlocator.dbOid = InvalidOid;
946  else
947  rlocator.dbOid = MyDatabaseId;
948  if (relform->relfilenode)
949  rlocator.relNumber = relform->relfilenode;
950  else /* Consult the relation mapper */
951  rlocator.relNumber = RelationMapOidToFilenumber(relid,
952  relform->relisshared);
953  }
954  else
955  {
956  /* no storage, return NULL */
957  rlocator.relNumber = InvalidRelFileNumber;
958  /* some compilers generate warnings without these next two lines */
959  rlocator.dbOid = InvalidOid;
960  rlocator.spcOid = InvalidOid;
961  }
962 
963  if (!RelFileNumberIsValid(rlocator.relNumber))
964  {
965  ReleaseSysCache(tuple);
966  PG_RETURN_NULL();
967  }
968 
969  /* Determine owning backend. */
970  switch (relform->relpersistence)
971  {
972  case RELPERSISTENCE_UNLOGGED:
973  case RELPERSISTENCE_PERMANENT:
974  backend = InvalidBackendId;
975  break;
976  case RELPERSISTENCE_TEMP:
977  if (isTempOrTempToastNamespace(relform->relnamespace))
978  backend = BackendIdForTempRelations();
979  else
980  {
981  /* Do it the hard way. */
982  backend = GetTempNamespaceBackendId(relform->relnamespace);
983  Assert(backend != InvalidBackendId);
984  }
985  break;
986  default:
987  elog(ERROR, "invalid relpersistence: %c", relform->relpersistence);
988  backend = InvalidBackendId; /* placate compiler */
989  break;
990  }
991 
992  ReleaseSysCache(tuple);
993 
994  path = relpathbackend(rlocator, backend, MAIN_FORKNUM);
995 
997 }
int BackendId
Definition: backendid.h:21
#define BackendIdForTempRelations()
Definition: backendid.h:34
#define InvalidBackendId
Definition: backendid.h:23
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
Oid MyDatabaseId
Definition: globals.c:89
Assert(fmt[strlen(fmt) - 1] !='\n')
bool isTempOrTempToastNamespace(Oid namespaceId)
Definition: namespace.c:3224
int GetTempNamespaceBackendId(Oid namespaceId)
Definition: namespace.c:3317
#define InvalidOid
Definition: postgres_ext.h:36
@ MAIN_FORKNUM
Definition: relpath.h:50
RelFileNumber relNumber
text * cstring_to_text(const char *s)
Definition: varlena.c:189

References Assert(), BackendIdForTempRelations, cstring_to_text(), RelFileLocator::dbOid, elog(), ERROR, GETSTRUCT, GetTempNamespaceBackendId(), HeapTupleIsValid, InvalidBackendId, InvalidOid, InvalidRelFileNumber, isTempOrTempToastNamespace(), MAIN_FORKNUM, MyDatabaseId, MyDatabaseTableSpace, ObjectIdGetDatum(), PG_GETARG_OID, PG_RETURN_NULL, PG_RETURN_TEXT_P, RelationMapOidToFilenumber(), ReleaseSysCache(), RelFileNumberIsValid, RelFileLocator::relNumber, RELOID, relpathbackend, SearchSysCache1(), and RelFileLocator::spcOid.

◆ pg_relation_size()

Datum pg_relation_size ( PG_FUNCTION_ARGS  )

Definition at line 334 of file dbsize.c.

335 {
336  Oid relOid = PG_GETARG_OID(0);
337  text *forkName = PG_GETARG_TEXT_PP(1);
338  Relation rel;
339  int64 size;
340 
341  rel = try_relation_open(relOid, AccessShareLock);
342 
343  /*
344  * Before 9.2, we used to throw an error if the relation didn't exist, but
345  * that makes queries like "SELECT pg_relation_size(oid) FROM pg_class"
346  * less robust, because while we scan pg_class with an MVCC snapshot,
347  * someone else might drop the table. It's better to return NULL for
348  * already-dropped tables than throw an error and abort the whole query.
349  */
350  if (rel == NULL)
351  PG_RETURN_NULL();
352 
353  size = calculate_relation_size(&(rel->rd_locator), rel->rd_backend,
355 
357 
358  PG_RETURN_INT64(size);
359 }
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
ForkNumber forkname_to_number(const char *forkName)
Definition: relpath.c:50
Definition: c.h:623
char * text_to_cstring(const text *t)
Definition: varlena.c:222

References AccessShareLock, calculate_relation_size(), forkname_to_number(), PG_GETARG_OID, PG_GETARG_TEXT_PP, PG_RETURN_INT64, PG_RETURN_NULL, RelationData::rd_backend, RelationData::rd_locator, relation_close(), text_to_cstring(), and try_relation_open().

◆ pg_size_bytes()

Datum pg_size_bytes ( PG_FUNCTION_ARGS  )

Definition at line 697 of file dbsize.c.

698 {
699  text *arg = PG_GETARG_TEXT_PP(0);
700  char *str,
701  *strptr,
702  *endptr;
703  char saved_char;
704  Numeric num;
705  int64 result;
706  bool have_digits = false;
707 
709 
710  /* Skip leading whitespace */
711  strptr = str;
712  while (isspace((unsigned char) *strptr))
713  strptr++;
714 
715  /* Check that we have a valid number and determine where it ends */
716  endptr = strptr;
717 
718  /* Part (1): sign */
719  if (*endptr == '-' || *endptr == '+')
720  endptr++;
721 
722  /* Part (2): main digit string */
723  if (isdigit((unsigned char) *endptr))
724  {
725  have_digits = true;
726  do
727  endptr++;
728  while (isdigit((unsigned char) *endptr));
729  }
730 
731  /* Part (3): optional decimal point and fractional digits */
732  if (*endptr == '.')
733  {
734  endptr++;
735  if (isdigit((unsigned char) *endptr))
736  {
737  have_digits = true;
738  do
739  endptr++;
740  while (isdigit((unsigned char) *endptr));
741  }
742  }
743 
744  /* Complain if we don't have a valid number at this point */
745  if (!have_digits)
746  ereport(ERROR,
747  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
748  errmsg("invalid size: \"%s\"", str)));
749 
750  /* Part (4): optional exponent */
751  if (*endptr == 'e' || *endptr == 'E')
752  {
753  long exponent;
754  char *cp;
755 
756  /*
757  * Note we might one day support EB units, so if what follows 'E'
758  * isn't a number, just treat it all as a unit to be parsed.
759  */
760  exponent = strtol(endptr + 1, &cp, 10);
761  (void) exponent; /* Silence -Wunused-result warnings */
762  if (cp > endptr + 1)
763  endptr = cp;
764  }
765 
766  /*
767  * Parse the number, saving the next character, which may be the first
768  * character of the unit string.
769  */
770  saved_char = *endptr;
771  *endptr = '\0';
772 
774  CStringGetDatum(strptr),
776  Int32GetDatum(-1)));
777 
778  *endptr = saved_char;
779 
780  /* Skip whitespace between number and unit */
781  strptr = endptr;
782  while (isspace((unsigned char) *strptr))
783  strptr++;
784 
785  /* Handle possible unit */
786  if (*strptr != '\0')
787  {
788  const struct size_pretty_unit *unit;
789  int64 multiplier = 0;
790 
791  /* Trim any trailing whitespace */
792  endptr = str + VARSIZE_ANY_EXHDR(arg) - 1;
793 
794  while (isspace((unsigned char) *endptr))
795  endptr--;
796 
797  endptr++;
798  *endptr = '\0';
799 
800  for (unit = size_pretty_units; unit->name != NULL; unit++)
801  {
802  /* Parse the unit case-insensitively */
803  if (pg_strcasecmp(strptr, unit->name) == 0)
804  {
805  multiplier = ((int64) 1) << unit->unitbits;
806  break;
807  }
808  }
809 
810  /* Verify we found a valid unit in the loop above */
811  if (unit->name == NULL)
812  ereport(ERROR,
813  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
814  errmsg("invalid size: \"%s\"", text_to_cstring(arg)),
815  errdetail("Invalid size unit: \"%s\".", strptr),
816  errhint("Valid units are \"bytes\", \"kB\", \"MB\", \"GB\", \"TB\", and \"PB\".")));
817 
818  if (multiplier > 1)
819  {
820  Numeric mul_num;
821 
822  mul_num = int64_to_numeric(multiplier);
823 
825  NumericGetDatum(mul_num),
826  NumericGetDatum(num)));
827  }
828  }
829 
831  NumericGetDatum(num)));
832 
833  PG_RETURN_INT64(result);
834 }
Datum numeric_int8(PG_FUNCTION_ARGS)
Definition: numeric.c:4312
Datum numeric_in(PG_FUNCTION_ARGS)
Definition: numeric.c:617
Datum numeric_mul(PG_FUNCTION_ARGS)
Definition: numeric.c:2920
static const struct size_pretty_unit size_pretty_units[]
Definition: dbsize.c:50
int errdetail(const char *fmt,...)
Definition: elog.c:1039
int errhint(const char *fmt,...)
Definition: elog.c:1153
int errcode(int sqlerrcode)
Definition: elog.c:695
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:646
void * arg
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
static int64 DatumGetInt64(Datum X)
Definition: postgres.h:733
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:698
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:560
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:355
const char * name
Definition: dbsize.c:41
uint8 unitbits
Definition: dbsize.c:45

References arg, CStringGetDatum(), DatumGetInt64(), DatumGetNumeric(), DirectFunctionCall1, DirectFunctionCall2, DirectFunctionCall3, ereport, errcode(), errdetail(), errhint(), errmsg(), ERROR, Int32GetDatum(), int64_to_numeric(), InvalidOid, size_pretty_unit::name, numeric_in(), numeric_int8(), numeric_mul(), NumericGetDatum(), ObjectIdGetDatum(), PG_GETARG_TEXT_PP, PG_RETURN_INT64, pg_strcasecmp(), size_pretty_units, generate_unaccent_rules::str, text_to_cstring(), size_pretty_unit::unitbits, and VARSIZE_ANY_EXHDR.

◆ pg_size_pretty()

Datum pg_size_pretty ( PG_FUNCTION_ARGS  )

Definition at line 557 of file dbsize.c.

558 {
559  int64 size = PG_GETARG_INT64(0);
560  char buf[64];
561  const struct size_pretty_unit *unit;
562 
563  for (unit = size_pretty_units; unit->name != NULL; unit++)
564  {
565  uint8 bits;
566 
567  /* use this unit if there are no more units or we're below the limit */
568  if (unit[1].name == NULL || i64abs(size) < unit->limit)
569  {
570  if (unit->round)
571  size = half_rounded(size);
572 
573  snprintf(buf, sizeof(buf), INT64_FORMAT " %s", size, unit->name);
574  break;
575  }
576 
577  /*
578  * Determine the number of bits to use to build the divisor. We may
579  * need to use 1 bit less than the difference between this and the
580  * next unit if the next unit uses half rounding. Or we may need to
581  * shift an extra bit if this unit uses half rounding and the next one
582  * does not. We use division rather than shifting right by this
583  * number of bits to ensure positive and negative values are rounded
584  * in the same way.
585  */
586  bits = (unit[1].unitbits - unit->unitbits - (unit[1].round == true)
587  + (unit->round == true));
588  size /= ((int64) 1) << bits;
589  }
590 
592 }
#define INT64_FORMAT
Definition: c.h:484
unsigned char uint8
Definition: c.h:440
#define i64abs(i)
Definition: c.h:1243
#define half_rounded(x)
Definition: dbsize.c:36
const char * name
Definition: encode.c:561
#define PG_GETARG_INT64(n)
Definition: fmgr.h:283
static char * buf
Definition: pg_test_fsync.c:67
uint32 limit
Definition: dbsize.c:42

References buf, cstring_to_text(), half_rounded, i64abs, INT64_FORMAT, size_pretty_unit::limit, size_pretty_unit::name, name, PG_GETARG_INT64, PG_RETURN_TEXT_P, size_pretty_unit::round, size_pretty_units, snprintf, and size_pretty_unit::unitbits.

◆ pg_size_pretty_numeric()

Datum pg_size_pretty_numeric ( PG_FUNCTION_ARGS  )

Definition at line 656 of file dbsize.c.

657 {
658  Numeric size = PG_GETARG_NUMERIC(0);
659  char *result = NULL;
660  const struct size_pretty_unit *unit;
661 
662  for (unit = size_pretty_units; unit->name != NULL; unit++)
663  {
664  unsigned int shiftby;
665 
666  /* use this unit if there are no more units or we're below the limit */
667  if (unit[1].name == NULL ||
669  int64_to_numeric(unit->limit)))
670  {
671  if (unit->round)
672  size = numeric_half_rounded(size);
673 
674  result = psprintf("%s %s", numeric_to_cstring(size), unit->name);
675  break;
676  }
677 
678  /*
679  * Determine the number of bits to use to build the divisor. We may
680  * need to use 1 bit less than the difference between this and the
681  * next unit if the next unit uses half rounding. Or we may need to
682  * shift an extra bit if this unit uses half rounding and the next one
683  * does not.
684  */
685  shiftby = (unit[1].unitbits - unit->unitbits - (unit[1].round == true)
686  + (unit->round == true));
687  size = numeric_truncated_divide(size, ((int64) 1) << shiftby);
688  }
689 
691 }
static bool numeric_is_less(Numeric a, Numeric b)
Definition: dbsize.c:603
static Numeric numeric_truncated_divide(Numeric n, int64 divisor)
Definition: dbsize.c:644
static char * numeric_to_cstring(Numeric n)
Definition: dbsize.c:595
static Numeric numeric_absolute(Numeric n)
Definition: dbsize.c:612
static Numeric numeric_half_rounded(Numeric n)
Definition: dbsize.c:622
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:77
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46

References cstring_to_text(), int64_to_numeric(), size_pretty_unit::limit, size_pretty_unit::name, name, numeric_absolute(), numeric_half_rounded(), numeric_is_less(), numeric_to_cstring(), numeric_truncated_divide(), PG_GETARG_NUMERIC, PG_RETURN_TEXT_P, psprintf(), size_pretty_unit::round, size_pretty_units, and size_pretty_unit::unitbits.

◆ pg_table_size()

Datum pg_table_size ( PG_FUNCTION_ARGS  )

Definition at line 474 of file dbsize.c.

475 {
476  Oid relOid = PG_GETARG_OID(0);
477  Relation rel;
478  int64 size;
479 
480  rel = try_relation_open(relOid, AccessShareLock);
481 
482  if (rel == NULL)
483  PG_RETURN_NULL();
484 
485  size = calculate_table_size(rel);
486 
488 
489  PG_RETURN_INT64(size);
490 }

References AccessShareLock, calculate_table_size(), PG_GETARG_OID, PG_RETURN_INT64, PG_RETURN_NULL, relation_close(), and try_relation_open().

◆ pg_tablespace_size_name()

Datum pg_tablespace_size_name ( PG_FUNCTION_ARGS  )

Definition at line 274 of file dbsize.c.

275 {
276  Name tblspcName = PG_GETARG_NAME(0);
277  Oid tblspcOid = get_tablespace_oid(NameStr(*tblspcName), false);
278  int64 size;
279 
280  size = calculate_tablespace_size(tblspcOid);
281 
282  if (size < 0)
283  PG_RETURN_NULL();
284 
285  PG_RETURN_INT64(size);
286 }
Oid get_tablespace_oid(const char *tablespacename, bool missing_ok)
Definition: tablespace.c:1432
static int64 calculate_tablespace_size(Oid tblspcOid)
Definition: dbsize.c:190

References calculate_tablespace_size(), get_tablespace_oid(), NameStr, PG_GETARG_NAME, PG_RETURN_INT64, and PG_RETURN_NULL.

◆ pg_tablespace_size_oid()

Datum pg_tablespace_size_oid ( PG_FUNCTION_ARGS  )

Definition at line 260 of file dbsize.c.

261 {
262  Oid tblspcOid = PG_GETARG_OID(0);
263  int64 size;
264 
265  size = calculate_tablespace_size(tblspcOid);
266 
267  if (size < 0)
268  PG_RETURN_NULL();
269 
270  PG_RETURN_INT64(size);
271 }

References calculate_tablespace_size(), PG_GETARG_OID, PG_RETURN_INT64, and PG_RETURN_NULL.

◆ pg_total_relation_size()

Datum pg_total_relation_size ( PG_FUNCTION_ARGS  )

Definition at line 535 of file dbsize.c.

536 {
537  Oid relOid = PG_GETARG_OID(0);
538  Relation rel;
539  int64 size;
540 
541  rel = try_relation_open(relOid, AccessShareLock);
542 
543  if (rel == NULL)
544  PG_RETURN_NULL();
545 
546  size = calculate_total_relation_size(rel);
547 
549 
550  PG_RETURN_INT64(size);
551 }
static int64 calculate_total_relation_size(Relation rel)
Definition: dbsize.c:516

References AccessShareLock, calculate_total_relation_size(), PG_GETARG_OID, PG_RETURN_INT64, PG_RETURN_NULL, relation_close(), and try_relation_open().

Variable Documentation

◆ size_pretty_units

const struct size_pretty_unit size_pretty_units[]
static
Initial value:
= {
{"bytes", 10 * 1024, false, 0},
{"kB", 20 * 1024 - 1, true, 10},
{"MB", 20 * 1024 - 1, true, 20},
{"GB", 20 * 1024 - 1, true, 30},
{"TB", 20 * 1024 - 1, true, 40},
{"PB", 20 * 1024 - 1, true, 50},
{NULL, 0, false, 0}
}

Definition at line 1 of file dbsize.c.

Referenced by pg_size_bytes(), pg_size_pretty(), and pg_size_pretty_numeric().