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_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/relfilenodemap.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 (RelFileNode *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 35 of file dbsize.c.

Referenced by pg_size_pretty().

Function Documentation

◆ calculate_database_size()

static int64 calculate_database_size ( Oid  dbOid)
static

Definition at line 105 of file dbsize.c.

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

Referenced by pg_database_size_name(), and pg_database_size_oid().

106 {
107  int64 totalsize;
108  DIR *dirdesc;
109  struct dirent *direntry;
110  char dirpath[MAXPGPATH];
111  char pathname[MAXPGPATH + 21 + sizeof(TABLESPACE_VERSION_DIRECTORY)];
112  AclResult aclresult;
113 
114  /*
115  * User must have connect privilege for target database or be a member of
116  * pg_read_all_stats
117  */
118  aclresult = pg_database_aclcheck(dbOid, GetUserId(), ACL_CONNECT);
119  if (aclresult != ACLCHECK_OK &&
120  !is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS))
121  {
122  aclcheck_error(aclresult, OBJECT_DATABASE,
123  get_database_name(dbOid));
124  }
125 
126  /* Shared storage in pg_global is not counted */
127 
128  /* Include pg_default storage */
129  snprintf(pathname, sizeof(pathname), "base/%u", dbOid);
130  totalsize = db_dir_size(pathname);
131 
132  /* Scan the non-default tablespaces */
133  snprintf(dirpath, MAXPGPATH, "pg_tblspc");
134  dirdesc = AllocateDir(dirpath);
135 
136  while ((direntry = ReadDir(dirdesc, dirpath)) != NULL)
137  {
139 
140  if (strcmp(direntry->d_name, ".") == 0 ||
141  strcmp(direntry->d_name, "..") == 0)
142  continue;
143 
144  snprintf(pathname, sizeof(pathname), "pg_tblspc/%s/%s/%u",
145  direntry->d_name, TABLESPACE_VERSION_DIRECTORY, dbOid);
146  totalsize += db_dir_size(pathname);
147  }
148 
149  FreeDir(dirdesc);
150 
151  return totalsize;
152 }
Oid GetUserId(void)
Definition: miscinit.c:478
Definition: dirent.h:9
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3308
Definition: dirent.c:25
#define MAXPGPATH
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2113
#define TABLESPACE_VERSION_DIRECTORY
Definition: relpath.h:26
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2678
#define ACL_CONNECT
Definition: parsenodes.h:94
AclResult
Definition: acl.h:177
bool is_member_of_role(Oid member, Oid role)
Definition: acl.c:4869
AclResult pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4706
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2744
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:120
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:216
int FreeDir(DIR *dir)
Definition: fd.c:2796
static int64 db_dir_size(const char *path)
Definition: dbsize.c:61

◆ calculate_indexes_size()

static int64 calculate_indexes_size ( Relation  rel)
static

Definition at line 438 of file dbsize.c.

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

Referenced by calculate_total_relation_size(), and pg_indexes_size().

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

◆ calculate_relation_size()

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

Definition at line 295 of file dbsize.c.

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().

296 {
297  int64 totalsize = 0;
298  char *relationpath;
299  char pathname[MAXPGPATH];
300  unsigned int segcount = 0;
301 
302  relationpath = relpathbackend(*rfn, backend, forknum);
303 
304  for (segcount = 0;; segcount++)
305  {
306  struct stat fst;
307 
309 
310  if (segcount == 0)
311  snprintf(pathname, MAXPGPATH, "%s",
312  relationpath);
313  else
314  snprintf(pathname, MAXPGPATH, "%s.%u",
315  relationpath, segcount);
316 
317  if (stat(pathname, &fst) < 0)
318  {
319  if (errno == ENOENT)
320  break;
321  else
322  ereport(ERROR,
324  errmsg("could not stat file \"%s\": %m", pathname)));
325  }
326  totalsize += fst.st_size;
327  }
328 
329  return totalsize;
330 }
#define ERROR
Definition: elog.h:46
#define MAXPGPATH
int errcode_for_file_access(void)
Definition: elog.c:721
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:120
#define relpathbackend(rnode, backend, forknum)
Definition: relpath.h:78
#define snprintf
Definition: port.h:216
#define stat
Definition: win32_port.h:275

◆ calculate_table_size()

static int64 calculate_table_size ( Relation  rel)
static

Definition at line 411 of file dbsize.c.

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

Referenced by calculate_total_relation_size(), and pg_table_size().

412 {
413  int64 size = 0;
414  ForkNumber forkNum;
415 
416  /*
417  * heap size, including FSM and VM
418  */
419  for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
420  size += calculate_relation_size(&(rel->rd_node), rel->rd_backend,
421  forkNum);
422 
423  /*
424  * Size of toast relation
425  */
426  if (OidIsValid(rel->rd_rel->reltoastrelid))
427  size += calculate_toast_table_size(rel->rd_rel->reltoastrelid);
428 
429  return size;
430 }
static int64 calculate_relation_size(RelFileNode *rfn, BackendId backend, ForkNumber forknum)
Definition: dbsize.c:295
Form_pg_class rd_rel
Definition: rel.h:109
#define OidIsValid(objectId)
Definition: c.h:710
ForkNumber
Definition: relpath.h:40
static int64 calculate_toast_table_size(Oid toastrelid)
Definition: dbsize.c:365
RelFileNode rd_node
Definition: rel.h:56
BackendId rd_backend
Definition: rel.h:59
#define MAX_FORKNUM
Definition: relpath.h:55

◆ calculate_tablespace_size()

static int64 calculate_tablespace_size ( Oid  tblspcOid)
static

Definition at line 189 of file dbsize.c.

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(), is_member_of_role(), MAXPGPATH, MyDatabaseTableSpace, OBJECT_TABLESPACE, pg_tablespace_aclcheck(), 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().

190 {
191  char tblspcPath[MAXPGPATH];
192  char pathname[MAXPGPATH * 2];
193  int64 totalsize = 0;
194  DIR *dirdesc;
195  struct dirent *direntry;
196  AclResult aclresult;
197 
198  /*
199  * User must be a member of pg_read_all_stats or have CREATE privilege for
200  * target tablespace, either explicitly granted or implicitly because it
201  * is default for current database.
202  */
203  if (tblspcOid != MyDatabaseTableSpace &&
204  !is_member_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS))
205  {
206  aclresult = pg_tablespace_aclcheck(tblspcOid, GetUserId(), ACL_CREATE);
207  if (aclresult != ACLCHECK_OK)
209  get_tablespace_name(tblspcOid));
210  }
211 
212  if (tblspcOid == DEFAULTTABLESPACE_OID)
213  snprintf(tblspcPath, MAXPGPATH, "base");
214  else if (tblspcOid == GLOBALTABLESPACE_OID)
215  snprintf(tblspcPath, MAXPGPATH, "global");
216  else
217  snprintf(tblspcPath, MAXPGPATH, "pg_tblspc/%u/%s", tblspcOid,
219 
220  dirdesc = AllocateDir(tblspcPath);
221 
222  if (!dirdesc)
223  return -1;
224 
225  while ((direntry = ReadDir(dirdesc, tblspcPath)) != NULL)
226  {
227  struct stat fst;
228 
230 
231  if (strcmp(direntry->d_name, ".") == 0 ||
232  strcmp(direntry->d_name, "..") == 0)
233  continue;
234 
235  snprintf(pathname, sizeof(pathname), "%s/%s", tblspcPath, direntry->d_name);
236 
237  if (stat(pathname, &fst) < 0)
238  {
239  if (errno == ENOENT)
240  continue;
241  else
242  ereport(ERROR,
244  errmsg("could not stat file \"%s\": %m", pathname)));
245  }
246 
247  if (S_ISDIR(fst.st_mode))
248  totalsize += db_dir_size(pathname);
249 
250  totalsize += fst.st_size;
251  }
252 
253  FreeDir(dirdesc);
254 
255  return totalsize;
256 }
AclResult pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4768
Oid GetUserId(void)
Definition: miscinit.c:478
Definition: dirent.h:9
Oid MyDatabaseTableSpace
Definition: globals.c:90
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3308
Definition: dirent.c:25
#define ERROR
Definition: elog.h:46
#define ACL_CREATE
Definition: parsenodes.h:92
#define MAXPGPATH
#define TABLESPACE_VERSION_DIRECTORY
Definition: relpath.h:26
int errcode_for_file_access(void)
Definition: elog.c:721
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2678
AclResult
Definition: acl.h:177
#define ereport(elevel,...)
Definition: elog.h:157
bool is_member_of_role(Oid member, Oid role)
Definition: acl.c:4869
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2744
#define S_ISDIR(m)
Definition: win32_port.h:316
int errmsg(const char *fmt,...)
Definition: elog.c:909
char * get_tablespace_name(Oid spc_oid)
Definition: tablespace.c:1477
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:120
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:216
int FreeDir(DIR *dir)
Definition: fd.c:2796
static int64 db_dir_size(const char *path)
Definition: dbsize.c:61
#define stat
Definition: win32_port.h:275

◆ calculate_toast_table_size()

static int64 calculate_toast_table_size ( Oid  toastrelid)
static

Definition at line 365 of file dbsize.c.

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

Referenced by calculate_table_size().

366 {
367  int64 size = 0;
368  Relation toastRel;
369  ForkNumber forkNum;
370  ListCell *lc;
371  List *indexlist;
372 
373  toastRel = relation_open(toastrelid, AccessShareLock);
374 
375  /* toast heap size, including FSM and VM size */
376  for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
377  size += calculate_relation_size(&(toastRel->rd_node),
378  toastRel->rd_backend, forkNum);
379 
380  /* toast index size, including FSM and VM size */
381  indexlist = RelationGetIndexList(toastRel);
382 
383  /* Size is calculated using all the indexes available */
384  foreach(lc, indexlist)
385  {
386  Relation toastIdxRel;
387 
388  toastIdxRel = relation_open(lfirst_oid(lc),
390  for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
391  size += calculate_relation_size(&(toastIdxRel->rd_node),
392  toastIdxRel->rd_backend, forkNum);
393 
394  relation_close(toastIdxRel, AccessShareLock);
395  }
396  list_free(indexlist);
397  relation_close(toastRel, AccessShareLock);
398 
399  return size;
400 }
static int64 calculate_relation_size(RelFileNode *rfn, BackendId backend, ForkNumber forknum)
Definition: dbsize.c:295
#define AccessShareLock
Definition: lockdefs.h:36
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
ForkNumber
Definition: relpath.h:40
RelFileNode rd_node
Definition: rel.h:56
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
BackendId rd_backend
Definition: rel.h:59
#define MAX_FORKNUM
Definition: relpath.h:55
List * RelationGetIndexList(Relation relation)
Definition: relcache.c:4573
void list_free(List *list)
Definition: list.c:1391
Definition: pg_list.h:50
#define lfirst_oid(lc)
Definition: pg_list.h:171

◆ calculate_total_relation_size()

static int64 calculate_total_relation_size ( Relation  rel)
static

Definition at line 515 of file dbsize.c.

References calculate_indexes_size(), and calculate_table_size().

Referenced by pg_total_relation_size().

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

◆ db_dir_size()

static int64 db_dir_size ( const char *  path)
static

Definition at line 61 of file dbsize.c.

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().

62 {
63  int64 dirsize = 0;
64  struct dirent *direntry;
65  DIR *dirdesc;
66  char filename[MAXPGPATH * 2];
67 
68  dirdesc = AllocateDir(path);
69 
70  if (!dirdesc)
71  return 0;
72 
73  while ((direntry = ReadDir(dirdesc, path)) != NULL)
74  {
75  struct stat fst;
76 
78 
79  if (strcmp(direntry->d_name, ".") == 0 ||
80  strcmp(direntry->d_name, "..") == 0)
81  continue;
82 
83  snprintf(filename, sizeof(filename), "%s/%s", path, direntry->d_name);
84 
85  if (stat(filename, &fst) < 0)
86  {
87  if (errno == ENOENT)
88  continue;
89  else
90  ereport(ERROR,
92  errmsg("could not stat file \"%s\": %m", filename)));
93  }
94  dirsize += fst.st_size;
95  }
96 
97  FreeDir(dirdesc);
98  return dirsize;
99 }
Definition: dirent.h:9
Definition: dirent.c:25
#define ERROR
Definition: elog.h:46
#define MAXPGPATH
int errcode_for_file_access(void)
Definition: elog.c:721
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2678
#define ereport(elevel,...)
Definition: elog.h:157
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2744
static char * filename
Definition: pg_dumpall.c:92
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:120
char d_name[MAX_PATH]
Definition: dirent.h:15
#define snprintf
Definition: port.h:216
int FreeDir(DIR *dir)
Definition: fd.c:2796
#define stat
Definition: win32_port.h:275

◆ numeric_absolute()

static Numeric numeric_absolute ( Numeric  n)
static

Definition at line 611 of file dbsize.c.

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

Referenced by pg_size_pretty_numeric().

612 {
613  Datum d = NumericGetDatum(n);
614  Datum result;
615 
616  result = DirectFunctionCall1(numeric_abs, d);
617  return DatumGetNumeric(result);
618 }
#define NumericGetDatum(X)
Definition: numeric.h:61
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:626
Datum numeric_abs(PG_FUNCTION_ARGS)
Definition: numeric.c:1320
uintptr_t Datum
Definition: postgres.h:411
#define DatumGetNumeric(X)
Definition: numeric.h:59

◆ numeric_half_rounded()

static Numeric numeric_half_rounded ( Numeric  n)
static

Definition at line 621 of file dbsize.c.

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

Referenced by pg_size_pretty_numeric().

622 {
623  Datum d = NumericGetDatum(n);
624  Datum zero;
625  Datum one;
626  Datum two;
627  Datum result;
628 
632 
634  d = DirectFunctionCall2(numeric_add, d, one);
635  else
636  d = DirectFunctionCall2(numeric_sub, d, one);
637 
638  result = DirectFunctionCall2(numeric_div_trunc, d, two);
639  return DatumGetNumeric(result);
640 }
#define NumericGetDatum(X)
Definition: numeric.h:61
Datum numeric_div_trunc(PG_FUNCTION_ARGS)
Definition: numeric.c:3184
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4145
#define DatumGetBool(X)
Definition: postgres.h:437
uintptr_t Datum
Definition: postgres.h:411
Datum numeric_sub(PG_FUNCTION_ARGS)
Definition: numeric.c:2850
#define DatumGetNumeric(X)
Definition: numeric.h:59
Datum numeric_ge(PG_FUNCTION_ARGS)
Definition: numeric.c:2385
Datum numeric_add(PG_FUNCTION_ARGS)
Definition: numeric.c:2773
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:628

◆ numeric_is_less()

static bool numeric_is_less ( Numeric  a,
Numeric  b 
)
static

Definition at line 602 of file dbsize.c.

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

Referenced by pg_size_pretty_numeric().

603 {
604  Datum da = NumericGetDatum(a);
605  Datum db = NumericGetDatum(b);
606 
608 }
#define NumericGetDatum(X)
Definition: numeric.h:61
#define DatumGetBool(X)
Definition: postgres.h:437
uintptr_t Datum
Definition: postgres.h:411
Datum numeric_lt(PG_FUNCTION_ARGS)
Definition: numeric.c:2400
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:628

◆ numeric_to_cstring()

static char* numeric_to_cstring ( Numeric  n)
static

Definition at line 594 of file dbsize.c.

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

Referenced by pg_size_pretty_numeric().

595 {
596  Datum d = NumericGetDatum(n);
597 
599 }
#define NumericGetDatum(X)
Definition: numeric.h:61
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:743
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:626
#define DatumGetCString(X)
Definition: postgres.h:610
uintptr_t Datum
Definition: postgres.h:411

◆ numeric_truncated_divide()

static Numeric numeric_truncated_divide ( Numeric  n,
int64  divisor 
)
static

Definition at line 643 of file dbsize.c.

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

Referenced by pg_size_pretty_numeric().

644 {
645  Datum d = NumericGetDatum(n);
646  Datum divisor_numeric;
647  Datum result;
648 
649  divisor_numeric = NumericGetDatum(int64_to_numeric(divisor));
650  result = DirectFunctionCall2(numeric_div_trunc, d, divisor_numeric);
651  return DatumGetNumeric(result);
652 }
#define NumericGetDatum(X)
Definition: numeric.h:61
Datum numeric_div_trunc(PG_FUNCTION_ARGS)
Definition: numeric.c:3184
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4145
uintptr_t Datum
Definition: postgres.h:411
#define DatumGetNumeric(X)
Definition: numeric.h:59
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:628

◆ pg_database_size_name()

Datum pg_database_size_name ( PG_FUNCTION_ARGS  )

Definition at line 169 of file dbsize.c.

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

170 {
172  Oid dbOid = get_database_oid(NameStr(*dbName), false);
173  int64 size;
174 
175  size = calculate_database_size(dbOid);
176 
177  if (size == 0)
178  PG_RETURN_NULL();
179 
180  PG_RETURN_INT64(size);
181 }
#define PG_RETURN_INT64(x)
Definition: fmgr.h:368
unsigned int Oid
Definition: postgres_ext.h:31
const char * dbName
Definition: pgbench.c:283
Definition: c.h:675
Oid get_database_oid(const char *dbname, bool missing_ok)
Definition: dbcommands.c:2066
static int64 calculate_database_size(Oid dbOid)
Definition: dbsize.c:105
#define NameStr(name)
Definition: c.h:681
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_GETARG_NAME(n)
Definition: fmgr.h:278

◆ pg_database_size_oid()

Datum pg_database_size_oid ( PG_FUNCTION_ARGS  )

Definition at line 155 of file dbsize.c.

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

156 {
157  Oid dbOid = PG_GETARG_OID(0);
158  int64 size;
159 
160  size = calculate_database_size(dbOid);
161 
162  if (size == 0)
163  PG_RETURN_NULL();
164 
165  PG_RETURN_INT64(size);
166 }
#define PG_RETURN_INT64(x)
Definition: fmgr.h:368
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
static int64 calculate_database_size(Oid dbOid)
Definition: dbsize.c:105
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ pg_filenode_relation()

Datum pg_filenode_relation ( PG_FUNCTION_ARGS  )

Definition at line 898 of file dbsize.c.

References OidIsValid, PG_GETARG_OID, PG_RETURN_NULL, PG_RETURN_OID, and RelidByRelfilenode().

899 {
900  Oid reltablespace = PG_GETARG_OID(0);
901  Oid relfilenode = PG_GETARG_OID(1);
902  Oid heaprel;
903 
904  /* test needed so RelidByRelfilenode doesn't misbehave */
905  if (!OidIsValid(relfilenode))
906  PG_RETURN_NULL();
907 
908  heaprel = RelidByRelfilenode(reltablespace, relfilenode);
909 
910  if (!OidIsValid(heaprel))
911  PG_RETURN_NULL();
912  else
913  PG_RETURN_OID(heaprel);
914 }
Oid RelidByRelfilenode(Oid reltablespace, Oid relfilenode)
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_RETURN_OID(x)
Definition: fmgr.h:360
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ pg_indexes_size()

Datum pg_indexes_size ( PG_FUNCTION_ARGS  )

Definition at line 492 of file dbsize.c.

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

493 {
494  Oid relOid = PG_GETARG_OID(0);
495  Relation rel;
496  int64 size;
497 
498  rel = try_relation_open(relOid, AccessShareLock);
499 
500  if (rel == NULL)
501  PG_RETURN_NULL();
502 
503  size = calculate_indexes_size(rel);
504 
506 
507  PG_RETURN_INT64(size);
508 }
#define PG_RETURN_INT64(x)
Definition: fmgr.h:368
#define AccessShareLock
Definition: lockdefs.h:36
unsigned int Oid
Definition: postgres_ext.h:31
Relation try_relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:89
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
#define PG_RETURN_NULL()
Definition: fmgr.h:345
static int64 calculate_indexes_size(Relation rel)
Definition: dbsize.c:438

◆ pg_relation_filenode()

Datum pg_relation_filenode ( PG_FUNCTION_ARGS  )

Definition at line 850 of file dbsize.c.

References GETSTRUCT, HeapTupleIsValid, InvalidOid, ObjectIdGetDatum, OidIsValid, PG_GETARG_OID, PG_RETURN_NULL, PG_RETURN_OID, RelationMapOidToFilenode(), ReleaseSysCache(), RELOID, and SearchSysCache1().

851 {
852  Oid relid = PG_GETARG_OID(0);
853  Oid result;
854  HeapTuple tuple;
855  Form_pg_class relform;
856 
857  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
858  if (!HeapTupleIsValid(tuple))
859  PG_RETURN_NULL();
860  relform = (Form_pg_class) GETSTRUCT(tuple);
861 
862  if (RELKIND_HAS_STORAGE(relform->relkind))
863  {
864  if (relform->relfilenode)
865  result = relform->relfilenode;
866  else /* Consult the relation mapper */
867  result = RelationMapOidToFilenode(relid,
868  relform->relisshared);
869  }
870  else
871  {
872  /* no storage, return NULL */
873  result = InvalidOid;
874  }
875 
876  ReleaseSysCache(tuple);
877 
878  if (!OidIsValid(result))
879  PG_RETURN_NULL();
880 
881  PG_RETURN_OID(result);
882 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
Oid RelationMapOidToFilenode(Oid relationId, bool shared)
Definition: relmapper.c:159
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define InvalidOid
Definition: postgres_ext.h:36
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define PG_RETURN_OID(x)
Definition: fmgr.h:360
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ pg_relation_filepath()

Datum pg_relation_filepath ( PG_FUNCTION_ARGS  )

Definition at line 922 of file dbsize.c.

References Assert, BackendIdForTempRelations, cstring_to_text(), RelFileNode::dbNode, elog, ERROR, GETSTRUCT, GetTempNamespaceBackendId(), HeapTupleIsValid, InvalidBackendId, InvalidOid, isTempOrTempToastNamespace(), MAIN_FORKNUM, MyDatabaseId, MyDatabaseTableSpace, ObjectIdGetDatum, OidIsValid, PG_GETARG_OID, PG_RETURN_NULL, PG_RETURN_TEXT_P, RelationMapOidToFilenode(), ReleaseSysCache(), RelFileNode::relNode, RELOID, relpathbackend, SearchSysCache1(), and RelFileNode::spcNode.

923 {
924  Oid relid = PG_GETARG_OID(0);
925  HeapTuple tuple;
926  Form_pg_class relform;
927  RelFileNode rnode;
928  BackendId backend;
929  char *path;
930 
931  tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
932  if (!HeapTupleIsValid(tuple))
933  PG_RETURN_NULL();
934  relform = (Form_pg_class) GETSTRUCT(tuple);
935 
936  if (RELKIND_HAS_STORAGE(relform->relkind))
937  {
938  /* This logic should match RelationInitPhysicalAddr */
939  if (relform->reltablespace)
940  rnode.spcNode = relform->reltablespace;
941  else
943  if (rnode.spcNode == GLOBALTABLESPACE_OID)
944  rnode.dbNode = InvalidOid;
945  else
946  rnode.dbNode = MyDatabaseId;
947  if (relform->relfilenode)
948  rnode.relNode = relform->relfilenode;
949  else /* Consult the relation mapper */
950  rnode.relNode = RelationMapOidToFilenode(relid,
951  relform->relisshared);
952  }
953  else
954  {
955  /* no storage, return NULL */
956  rnode.relNode = InvalidOid;
957  /* some compilers generate warnings without these next two lines */
958  rnode.dbNode = InvalidOid;
959  rnode.spcNode = InvalidOid;
960  }
961 
962  if (!OidIsValid(rnode.relNode))
963  {
964  ReleaseSysCache(tuple);
965  PG_RETURN_NULL();
966  }
967 
968  /* Determine owning backend. */
969  switch (relform->relpersistence)
970  {
971  case RELPERSISTENCE_UNLOGGED:
972  case RELPERSISTENCE_PERMANENT:
973  backend = InvalidBackendId;
974  break;
975  case RELPERSISTENCE_TEMP:
976  if (isTempOrTempToastNamespace(relform->relnamespace))
977  backend = BackendIdForTempRelations();
978  else
979  {
980  /* Do it the hard way. */
981  backend = GetTempNamespaceBackendId(relform->relnamespace);
982  Assert(backend != InvalidBackendId);
983  }
984  break;
985  default:
986  elog(ERROR, "invalid relpersistence: %c", relform->relpersistence);
987  backend = InvalidBackendId; /* placate compiler */
988  break;
989  }
990 
991  ReleaseSysCache(tuple);
992 
993  path = relpathbackend(rnode, backend, MAIN_FORKNUM);
994 
996 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
bool isTempOrTempToastNamespace(Oid namespaceId)
Definition: namespace.c:3226
int GetTempNamespaceBackendId(Oid namespaceId)
Definition: namespace.c:3319
unsigned int Oid
Definition: postgres_ext.h:31
#define OidIsValid(objectId)
Definition: c.h:710
Oid MyDatabaseTableSpace
Definition: globals.c:90
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
#define BackendIdForTempRelations()
Definition: backendid.h:34
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
#define InvalidBackendId
Definition: backendid.h:23
Oid RelationMapOidToFilenode(Oid relationId, bool shared)
Definition: relmapper.c:159
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
int BackendId
Definition: backendid.h:21
Oid MyDatabaseId
Definition: globals.c:88
#define InvalidOid
Definition: postgres_ext.h:36
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
text * cstring_to_text(const char *s)
Definition: varlena.c:190
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
#define elog(elevel,...)
Definition: elog.h:232
#define relpathbackend(rnode, backend, forknum)
Definition: relpath.h:78
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ pg_relation_size()

Datum pg_relation_size ( PG_FUNCTION_ARGS  )

Definition at line 333 of file dbsize.c.

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_node, relation_close(), text_to_cstring(), and try_relation_open().

334 {
335  Oid relOid = PG_GETARG_OID(0);
336  text *forkName = PG_GETARG_TEXT_PP(1);
337  Relation rel;
338  int64 size;
339 
340  rel = try_relation_open(relOid, AccessShareLock);
341 
342  /*
343  * Before 9.2, we used to throw an error if the relation didn't exist, but
344  * that makes queries like "SELECT pg_relation_size(oid) FROM pg_class"
345  * less robust, because while we scan pg_class with an MVCC snapshot,
346  * someone else might drop the table. It's better to return NULL for
347  * already-dropped tables than throw an error and abort the whole query.
348  */
349  if (rel == NULL)
350  PG_RETURN_NULL();
351 
352  size = calculate_relation_size(&(rel->rd_node), rel->rd_backend,
354 
356 
357  PG_RETURN_INT64(size);
358 }
static int64 calculate_relation_size(RelFileNode *rfn, BackendId backend, ForkNumber forknum)
Definition: dbsize.c:295
#define PG_RETURN_INT64(x)
Definition: fmgr.h:368
#define AccessShareLock
Definition: lockdefs.h:36
unsigned int Oid
Definition: postgres_ext.h:31
ForkNumber forkname_to_number(const char *forkName)
Definition: relpath.c:50
Relation try_relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:89
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
RelFileNode rd_node
Definition: rel.h:56
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
BackendId rd_backend
Definition: rel.h:59
char * text_to_cstring(const text *t)
Definition: varlena.c:223
Definition: c.h:621
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ pg_size_bytes()

Datum pg_size_bytes ( PG_FUNCTION_ARGS  )

Definition at line 696 of file dbsize.c.

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(), generate_unaccent_rules::str, text_to_cstring(), size_pretty_unit::unitbits, and VARSIZE_ANY_EXHDR.

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

◆ pg_size_pretty()

Datum pg_size_pretty ( PG_FUNCTION_ARGS  )

Definition at line 556 of file dbsize.c.

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

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

◆ pg_size_pretty_numeric()

Datum pg_size_pretty_numeric ( PG_FUNCTION_ARGS  )

Definition at line 655 of file dbsize.c.

References cstring_to_text(), int64_to_numeric(), size_pretty_unit::limit, size_pretty_unit::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, and size_pretty_unit::unitbits.

656 {
657  Numeric size = PG_GETARG_NUMERIC(0);
658  char *result = NULL;
659  const struct size_pretty_unit *unit;
660 
661  for (unit = size_pretty_units; unit->name != NULL; unit++)
662  {
663  unsigned int shiftby;
664 
665  /* use this unit if there are no more units or we're below the limit */
666  if (unit[1].name == NULL ||
668  int64_to_numeric(unit->limit)))
669  {
670  if (unit->round)
671  size = numeric_half_rounded(size);
672 
673  result = psprintf("%s %s", numeric_to_cstring(size), unit->name);
674  break;
675  }
676 
677  /*
678  * Determine the number of bits to use to build the divisor. We may
679  * need to use 1 bit less than the difference between this and the
680  * next unit if the next unit uses half rounding. Or we may need to
681  * shift an extra bit if this unit uses half rounding and the next one
682  * does not.
683  */
684  shiftby = (unit[1].unitbits - unit->unitbits - (unit[1].round == true)
685  + (unit->round == true));
686  size = numeric_truncated_divide(size, ((int64) 1) << shiftby);
687  }
688 
690 }
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
uint32 limit
Definition: dbsize.c:41
static char * numeric_to_cstring(Numeric n)
Definition: dbsize.c:594
static Numeric numeric_absolute(Numeric n)
Definition: dbsize.c:611
static Numeric numeric_half_rounded(Numeric n)
Definition: dbsize.c:621
Numeric int64_to_numeric(int64 val)
Definition: numeric.c:4145
static bool numeric_is_less(Numeric a, Numeric b)
Definition: dbsize.c:602
uint8 unitbits
Definition: dbsize.c:44
static Numeric numeric_truncated_divide(Numeric n, int64 divisor)
Definition: dbsize.c:643
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
text * cstring_to_text(const char *s)
Definition: varlena.c:190
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:62
const char * name
Definition: encode.c:515
const char * name
Definition: dbsize.c:40
static const struct size_pretty_unit size_pretty_units[]
Definition: dbsize.c:49

◆ pg_table_size()

Datum pg_table_size ( PG_FUNCTION_ARGS  )

Definition at line 473 of file dbsize.c.

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

474 {
475  Oid relOid = PG_GETARG_OID(0);
476  Relation rel;
477  int64 size;
478 
479  rel = try_relation_open(relOid, AccessShareLock);
480 
481  if (rel == NULL)
482  PG_RETURN_NULL();
483 
484  size = calculate_table_size(rel);
485 
487 
488  PG_RETURN_INT64(size);
489 }
#define PG_RETURN_INT64(x)
Definition: fmgr.h:368
#define AccessShareLock
Definition: lockdefs.h:36
unsigned int Oid
Definition: postgres_ext.h:31
Relation try_relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:89
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
static int64 calculate_table_size(Relation rel)
Definition: dbsize.c:411
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ pg_tablespace_size_name()

Datum pg_tablespace_size_name ( PG_FUNCTION_ARGS  )

Definition at line 273 of file dbsize.c.

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

274 {
275  Name tblspcName = PG_GETARG_NAME(0);
276  Oid tblspcOid = get_tablespace_oid(NameStr(*tblspcName), false);
277  int64 size;
278 
279  size = calculate_tablespace_size(tblspcOid);
280 
281  if (size < 0)
282  PG_RETURN_NULL();
283 
284  PG_RETURN_INT64(size);
285 }
Oid get_tablespace_oid(const char *tablespacename, bool missing_ok)
Definition: tablespace.c:1431
#define PG_RETURN_INT64(x)
Definition: fmgr.h:368
unsigned int Oid
Definition: postgres_ext.h:31
Definition: c.h:675
static int64 calculate_tablespace_size(Oid tblspcOid)
Definition: dbsize.c:189
#define NameStr(name)
Definition: c.h:681
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_GETARG_NAME(n)
Definition: fmgr.h:278

◆ pg_tablespace_size_oid()

Datum pg_tablespace_size_oid ( PG_FUNCTION_ARGS  )

Definition at line 259 of file dbsize.c.

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

260 {
261  Oid tblspcOid = PG_GETARG_OID(0);
262  int64 size;
263 
264  size = calculate_tablespace_size(tblspcOid);
265 
266  if (size < 0)
267  PG_RETURN_NULL();
268 
269  PG_RETURN_INT64(size);
270 }
#define PG_RETURN_INT64(x)
Definition: fmgr.h:368
unsigned int Oid
Definition: postgres_ext.h:31
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
static int64 calculate_tablespace_size(Oid tblspcOid)
Definition: dbsize.c:189
#define PG_RETURN_NULL()
Definition: fmgr.h:345

◆ pg_total_relation_size()

Datum pg_total_relation_size ( PG_FUNCTION_ARGS  )

Definition at line 534 of file dbsize.c.

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

535 {
536  Oid relOid = PG_GETARG_OID(0);
537  Relation rel;
538  int64 size;
539 
540  rel = try_relation_open(relOid, AccessShareLock);
541 
542  if (rel == NULL)
543  PG_RETURN_NULL();
544 
545  size = calculate_total_relation_size(rel);
546 
548 
549  PG_RETURN_INT64(size);
550 }
static int64 calculate_total_relation_size(Relation rel)
Definition: dbsize.c:515
#define PG_RETURN_INT64(x)
Definition: fmgr.h:368
#define AccessShareLock
Definition: lockdefs.h:36
unsigned int Oid
Definition: postgres_ext.h:31
Relation try_relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:89
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
#define PG_RETURN_NULL()
Definition: fmgr.h:345

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 49 of file dbsize.c.