diff options
Diffstat (limited to 'src/backend/utils/adt/dbsize.c')
-rw-r--r-- | src/backend/utils/adt/dbsize.c | 922 |
1 files changed, 461 insertions, 461 deletions
diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c index 158d2cf4026..57b72fe15cc 100644 --- a/src/backend/utils/adt/dbsize.c +++ b/src/backend/utils/adt/dbsize.c @@ -1,461 +1,461 @@ -/*
- * dbsize.c
- * object size functions
- *
- * Copyright (c) 2002-2005, PostgreSQL Global Development Group
- *
- * IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/dbsize.c,v 1.1 2005/07/29 14:46:57 momjian Exp $
- *
- */
-
-#include "postgres.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include "access/heapam.h"
-#include "catalog/namespace.h"
-#include "catalog/pg_tablespace.h"
-#include "commands/dbcommands.h"
-#include "commands/tablespace.h"
-#include "miscadmin.h"
-#include "storage/fd.h"
-#include "utils/builtins.h"
-#include "utils/syscache.h"
-#include "utils/relcache.h"
-
-
-/* Return physical size of directory contents, or 0 if dir doesn't exist */
-static int64
-db_dir_size(const char *path)
-{
- int64 dirsize = 0;
- struct dirent *direntry;
- DIR *dirdesc;
- char filename[MAXPGPATH];
-
- dirdesc = AllocateDir(path);
-
- if (!dirdesc)
- return 0;
-
- while ((direntry = readdir(dirdesc)) != NULL)
- {
- struct stat fst;
-
- if (strcmp(direntry->d_name, ".") == 0 ||
- strcmp(direntry->d_name, "..") == 0)
- continue;
-
- snprintf(filename, MAXPGPATH, "%s/%s", path, direntry->d_name);
-
- if (stat(filename, &fst) < 0)
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not stat \"%s\": %m", filename)));
-
- dirsize += fst.st_size;
- }
-
- FreeDir(dirdesc);
- return dirsize;
-}
-
-/*
- * calculate size of database in all tablespaces
- */
-static int64
-calculate_database_size(Oid dbOid)
-{
- int64 totalsize = 0;
- DIR *dirdesc;
- struct dirent *direntry;
- char pathname[MAXPGPATH];
-
- /* Shared storage in pg_global is not counted */
-
- /* Include pg_default storage */
- snprintf(pathname, MAXPGPATH, "%s/base/%u", DataDir, dbOid);
- totalsize += db_dir_size(pathname);
-
- /* Scan the non-default tablespaces */
- snprintf(pathname, MAXPGPATH, "%s/pg_tblspc", DataDir);
- dirdesc = AllocateDir(pathname);
- if (!dirdesc)
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not open tablespace directory \"%s\": %m",
- pathname)));
-
- while ((direntry = readdir(dirdesc)) != NULL)
- {
- if (strcmp(direntry->d_name, ".") == 0 ||
- strcmp(direntry->d_name, "..") == 0)
- continue;
-
- snprintf(pathname, MAXPGPATH, "%s/pg_tblspc/%s/%u",
- DataDir, direntry->d_name, dbOid);
- totalsize += db_dir_size(pathname);
- }
-
- FreeDir(dirdesc);
-
- /* Complain if we found no trace of the DB at all */
- if (!totalsize)
- ereport(ERROR,
- (ERRCODE_UNDEFINED_DATABASE,
- errmsg("database with OID %u does not exist", dbOid)));
-
- return totalsize;
-}
-
-Datum
-pg_database_size_oid(PG_FUNCTION_ARGS)
-{
- Oid dbOid = PG_GETARG_OID(0);
-
- PG_RETURN_INT64(calculate_database_size(dbOid));
-}
-
-Datum
-pg_database_size_name(PG_FUNCTION_ARGS)
-{
- Name dbName = PG_GETARG_NAME(0);
- Oid dbOid = get_database_oid(NameStr(*dbName));
-
- if (!OidIsValid(dbOid))
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_DATABASE),
- errmsg("database \"%s\" does not exist",
- NameStr(*dbName))));
-
- PG_RETURN_INT64(calculate_database_size(dbOid));
-}
-
-
-/*
- * calculate total size of tablespace
- */
-static int64
-calculate_tablespace_size(Oid tblspcOid)
-{
- char tblspcPath[MAXPGPATH];
- char pathname[MAXPGPATH];
- int64 totalsize=0;
- DIR *dirdesc;
- struct dirent *direntry;
-
- if (tblspcOid == DEFAULTTABLESPACE_OID)
- snprintf(tblspcPath, MAXPGPATH, "%s/base", DataDir);
- else if (tblspcOid == GLOBALTABLESPACE_OID)
- snprintf(tblspcPath, MAXPGPATH, "%s/global", DataDir);
- else
- snprintf(tblspcPath, MAXPGPATH, "%s/pg_tblspc/%u", DataDir, tblspcOid);
-
- dirdesc = AllocateDir(tblspcPath);
-
- if (!dirdesc)
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not open tablespace directory \"%s\": %m",
- tblspcPath)));
-
- while ((direntry = readdir(dirdesc)) != NULL)
- {
- struct stat fst;
-
- if (strcmp(direntry->d_name, ".") == 0 ||
- strcmp(direntry->d_name, "..") == 0)
- continue;
-
- snprintf(pathname, MAXPGPATH, "%s/%s", tblspcPath, direntry->d_name);
-
- if (stat(pathname, &fst) < 0)
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not stat \"%s\": %m", pathname)));
-
- if (fst.st_mode & S_IFDIR)
- totalsize += db_dir_size(pathname);
-
- totalsize += fst.st_size;
- }
-
- FreeDir(dirdesc);
-
- return totalsize;
-}
-
-Datum
-pg_tablespace_size_oid(PG_FUNCTION_ARGS)
-{
- Oid tblspcOid = PG_GETARG_OID(0);
-
- PG_RETURN_INT64(calculate_tablespace_size(tblspcOid));
-}
-
-Datum
-pg_tablespace_size_name(PG_FUNCTION_ARGS)
-{
- Name tblspcName = PG_GETARG_NAME(0);
- Oid tblspcOid = get_tablespace_oid(NameStr(*tblspcName));
-
- if (!OidIsValid(tblspcOid))
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("tablespace \"%s\" does not exist",
- NameStr(*tblspcName))));
-
- PG_RETURN_INT64(calculate_tablespace_size(tblspcOid));
-}
-
-
-/*
- * calculate size of a relation
- */
-static int64
-calculate_relation_size(Oid tblspcOid, Oid relnodeOid)
-{
- int64 totalsize=0;
- unsigned int segcount=0;
- char dirpath[MAXPGPATH];
- char pathname[MAXPGPATH];
-
- if (!tblspcOid)
- tblspcOid = MyDatabaseTableSpace;
-
- if (tblspcOid == DEFAULTTABLESPACE_OID)
- snprintf(dirpath, MAXPGPATH, "%s/base/%u", DataDir, MyDatabaseId);
- else if (tblspcOid == GLOBALTABLESPACE_OID)
- snprintf(dirpath, MAXPGPATH, "%s/global", DataDir);
- else
- snprintf(dirpath, MAXPGPATH, "%s/pg_tblspc/%u/%u",
- DataDir, tblspcOid, MyDatabaseId);
-
- for (segcount = 0 ;; segcount++)
- {
- struct stat fst;
-
- if (segcount == 0)
- snprintf(pathname, MAXPGPATH, "%s/%u",
- dirpath, relnodeOid);
- else
- snprintf(pathname, MAXPGPATH, "%s/%u.%u",
- dirpath, relnodeOid, segcount);
-
- if (stat(pathname, &fst) < 0)
- {
- if (errno == ENOENT)
- break;
- else
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not stat \"%s\": %m", pathname)));
- }
- totalsize += fst.st_size;
- }
-
- return totalsize;
-}
-
-Datum
-pg_relation_size_oid(PG_FUNCTION_ARGS)
-{
- Oid relOid=PG_GETARG_OID(0);
- HeapTuple tuple;
- Form_pg_class pg_class;
- Oid relnodeOid;
- Oid tblspcOid;
-
- tuple = SearchSysCache(RELOID,
- ObjectIdGetDatum(relOid),
- 0, 0, 0);
- if (!HeapTupleIsValid(tuple))
- ereport(ERROR,
- (ERRCODE_UNDEFINED_TABLE,
- errmsg("relation with OID %u does not exist", relOid)));
-
- pg_class = (Form_pg_class) GETSTRUCT(tuple);
- relnodeOid = pg_class->relfilenode;
- tblspcOid = pg_class->reltablespace;
-
- ReleaseSysCache(tuple);
-
- PG_RETURN_INT64(calculate_relation_size(tblspcOid, relnodeOid));
-}
-
-Datum
-pg_relation_size_name(PG_FUNCTION_ARGS)
-{
- text *relname = PG_GETARG_TEXT_P(0);
- RangeVar *relrv;
- Relation relation;
- Oid relnodeOid;
- Oid tblspcOid;
-
- relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
- relation = relation_openrv(relrv, AccessShareLock);
-
- tblspcOid = relation->rd_rel->reltablespace;
- relnodeOid = relation->rd_rel->relfilenode;
-
- relation_close(relation, AccessShareLock);
-
- PG_RETURN_INT64(calculate_relation_size(tblspcOid, relnodeOid));
-}
-
-
-/*
- * Compute on-disk size of files for 'relation' according to the stat function,
- * optionally including heap data, index data, and/or toast data.
- */
-static int64
-calculate_complete_relation_size(Oid tblspcOid, Oid relnodeOid)
-{
- Relation heapRelation;
- Relation idxRelation;
- Relation toastRelation;
- Oid idxOid;
- Oid idxTblspcOid;
- Oid toastOid;
- Oid toastTblspcOid;
- bool hasIndices;
- int64 size = 0;
- List *indexoidlist;
- ListCell *idx;
-
- heapRelation = relation_open(relnodeOid, AccessShareLock);
- toastOid = heapRelation->rd_rel->reltoastrelid;
- hasIndices = heapRelation->rd_rel->relhasindex;
-
- /* Get the heap size */
- size += calculate_relation_size(tblspcOid, relnodeOid);
-
- /* Get Index size */
- if ( hasIndices ) {
- /* recursively include any dependent indexes ... */
- indexoidlist = RelationGetIndexList(heapRelation);
-
- foreach(idx, indexoidlist) {
- idxOid = lfirst_oid(idx);
- idxRelation = relation_open(idxOid, AccessShareLock);
- idxTblspcOid = idxRelation->rd_rel->reltablespace;
- size += calculate_relation_size(idxTblspcOid, idxOid);
- relation_close(idxRelation, AccessShareLock);
- }
- list_free(indexoidlist);
- }
-
- /* Close heapReleation now we no longer need it */
- relation_close(heapRelation, AccessShareLock);
-
- /* Get toast table size */
- if ( toastOid != 0 ) {
-
- /* recursively include any toast relations ... */
- toastRelation = relation_open(toastOid, AccessShareLock);
- toastTblspcOid = toastRelation->rd_rel->reltablespace;
- size += calculate_relation_size(toastTblspcOid, toastOid);
- relation_close(toastRelation, AccessShareLock);
- }
-
- return size;
-}
-
-/*
- * Compute on-disk size of files for 'relation' including
- * heap data, index data, and toasted data.
- */
-Datum
-pg_complete_relation_size_oid(PG_FUNCTION_ARGS)
-{
- Oid relOid=PG_GETARG_OID(0);
- HeapTuple tuple;
- Form_pg_class pg_class;
- Oid relnodeOid;
- Oid tblspcOid;
-
- tuple = SearchSysCache(RELOID,
- ObjectIdGetDatum(relOid),
- 0, 0, 0);
- if (!HeapTupleIsValid(tuple))
- ereport(ERROR,
- (ERRCODE_UNDEFINED_TABLE,
- errmsg("relation with OID %u does not exist", relOid)));
-
- pg_class = (Form_pg_class) GETSTRUCT(tuple);
- relnodeOid = pg_class->relfilenode;
- tblspcOid = pg_class->reltablespace;
-
- ReleaseSysCache(tuple);
-
- PG_RETURN_INT64(calculate_complete_relation_size(tblspcOid, relnodeOid));
-}
-
-Datum
-pg_complete_relation_size_name(PG_FUNCTION_ARGS)
-{
- text *relname = PG_GETARG_TEXT_P(0);
- RangeVar *relrv;
- Relation relation;
- Oid relnodeOid;
- Oid tblspcOid;
-
- relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
- relation = relation_openrv(relrv, AccessShareLock);
-
- tblspcOid = relation->rd_rel->reltablespace;
- relnodeOid = relation->rd_rel->relfilenode;
-
- relation_close(relation, AccessShareLock);
-
- PG_RETURN_INT64(calculate_complete_relation_size(tblspcOid, relnodeOid));
-}
-
-/*
- * formatting with size units
- */
-Datum
-pg_size_pretty(PG_FUNCTION_ARGS)
-{
- int64 size=PG_GETARG_INT64(0);
- char *result=palloc(50+VARHDRSZ);
- int64 limit = 10*1024;
- int64 mult=1;
-
- if (size < limit*mult)
- snprintf(VARDATA(result), 50, INT64_FORMAT" bytes",
- size);
- else
- {
- mult *= 1024;
- if (size < limit*mult)
- snprintf(VARDATA(result), 50, INT64_FORMAT " kB",
- (size+mult/2) / mult);
- else
- {
- mult *= 1024;
- if (size < limit*mult)
- snprintf(VARDATA(result), 50, INT64_FORMAT " MB",
- (size+mult/2) / mult);
- else
- {
- mult *= 1024;
- if (size < limit*mult)
- snprintf(VARDATA(result), 50, INT64_FORMAT " GB",
- (size+mult/2) / mult);
- else
- {
- mult *= 1024;
- snprintf(VARDATA(result), 50, INT64_FORMAT " TB",
- (size+mult/2) / mult);
- }
- }
- }
- }
-
- VARATT_SIZEP(result) = strlen(VARDATA(result)) + VARHDRSZ;
-
- PG_RETURN_TEXT_P(result);
-}
+/* + * dbsize.c + * object size functions + * + * Copyright (c) 2002-2005, PostgreSQL Global Development Group + * + * IDENTIFICATION + * $PostgreSQL: pgsql/src/backend/utils/adt/dbsize.c,v 1.2 2005/08/02 14:07:27 tgl Exp $ + * + */ + +#include "postgres.h" + +#include <sys/types.h> +#include <sys/stat.h> + +#include "access/heapam.h" +#include "catalog/namespace.h" +#include "catalog/pg_tablespace.h" +#include "commands/dbcommands.h" +#include "commands/tablespace.h" +#include "miscadmin.h" +#include "storage/fd.h" +#include "utils/builtins.h" +#include "utils/syscache.h" +#include "utils/relcache.h" + + +/* Return physical size of directory contents, or 0 if dir doesn't exist */ +static int64 +db_dir_size(const char *path) +{ + int64 dirsize = 0; + struct dirent *direntry; + DIR *dirdesc; + char filename[MAXPGPATH]; + + dirdesc = AllocateDir(path); + + if (!dirdesc) + return 0; + + while ((direntry = readdir(dirdesc)) != NULL) + { + struct stat fst; + + if (strcmp(direntry->d_name, ".") == 0 || + strcmp(direntry->d_name, "..") == 0) + continue; + + snprintf(filename, MAXPGPATH, "%s/%s", path, direntry->d_name); + + if (stat(filename, &fst) < 0) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not stat \"%s\": %m", filename))); + + dirsize += fst.st_size; + } + + FreeDir(dirdesc); + return dirsize; +} + +/* + * calculate size of database in all tablespaces + */ +static int64 +calculate_database_size(Oid dbOid) +{ + int64 totalsize = 0; + DIR *dirdesc; + struct dirent *direntry; + char pathname[MAXPGPATH]; + + /* Shared storage in pg_global is not counted */ + + /* Include pg_default storage */ + snprintf(pathname, MAXPGPATH, "%s/base/%u", DataDir, dbOid); + totalsize += db_dir_size(pathname); + + /* Scan the non-default tablespaces */ + snprintf(pathname, MAXPGPATH, "%s/pg_tblspc", DataDir); + dirdesc = AllocateDir(pathname); + if (!dirdesc) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not open tablespace directory \"%s\": %m", + pathname))); + + while ((direntry = readdir(dirdesc)) != NULL) + { + if (strcmp(direntry->d_name, ".") == 0 || + strcmp(direntry->d_name, "..") == 0) + continue; + + snprintf(pathname, MAXPGPATH, "%s/pg_tblspc/%s/%u", + DataDir, direntry->d_name, dbOid); + totalsize += db_dir_size(pathname); + } + + FreeDir(dirdesc); + + /* Complain if we found no trace of the DB at all */ + if (!totalsize) + ereport(ERROR, + (ERRCODE_UNDEFINED_DATABASE, + errmsg("database with OID %u does not exist", dbOid))); + + return totalsize; +} + +Datum +pg_database_size_oid(PG_FUNCTION_ARGS) +{ + Oid dbOid = PG_GETARG_OID(0); + + PG_RETURN_INT64(calculate_database_size(dbOid)); +} + +Datum +pg_database_size_name(PG_FUNCTION_ARGS) +{ + Name dbName = PG_GETARG_NAME(0); + Oid dbOid = get_database_oid(NameStr(*dbName)); + + if (!OidIsValid(dbOid)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_DATABASE), + errmsg("database \"%s\" does not exist", + NameStr(*dbName)))); + + PG_RETURN_INT64(calculate_database_size(dbOid)); +} + + +/* + * calculate total size of tablespace + */ +static int64 +calculate_tablespace_size(Oid tblspcOid) +{ + char tblspcPath[MAXPGPATH]; + char pathname[MAXPGPATH]; + int64 totalsize=0; + DIR *dirdesc; + struct dirent *direntry; + + if (tblspcOid == DEFAULTTABLESPACE_OID) + snprintf(tblspcPath, MAXPGPATH, "%s/base", DataDir); + else if (tblspcOid == GLOBALTABLESPACE_OID) + snprintf(tblspcPath, MAXPGPATH, "%s/global", DataDir); + else + snprintf(tblspcPath, MAXPGPATH, "%s/pg_tblspc/%u", DataDir, tblspcOid); + + dirdesc = AllocateDir(tblspcPath); + + if (!dirdesc) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not open tablespace directory \"%s\": %m", + tblspcPath))); + + while ((direntry = readdir(dirdesc)) != NULL) + { + struct stat fst; + + if (strcmp(direntry->d_name, ".") == 0 || + strcmp(direntry->d_name, "..") == 0) + continue; + + snprintf(pathname, MAXPGPATH, "%s/%s", tblspcPath, direntry->d_name); + + if (stat(pathname, &fst) < 0) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not stat \"%s\": %m", pathname))); + + if (fst.st_mode & S_IFDIR) + totalsize += db_dir_size(pathname); + + totalsize += fst.st_size; + } + + FreeDir(dirdesc); + + return totalsize; +} + +Datum +pg_tablespace_size_oid(PG_FUNCTION_ARGS) +{ + Oid tblspcOid = PG_GETARG_OID(0); + + PG_RETURN_INT64(calculate_tablespace_size(tblspcOid)); +} + +Datum +pg_tablespace_size_name(PG_FUNCTION_ARGS) +{ + Name tblspcName = PG_GETARG_NAME(0); + Oid tblspcOid = get_tablespace_oid(NameStr(*tblspcName)); + + if (!OidIsValid(tblspcOid)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("tablespace \"%s\" does not exist", + NameStr(*tblspcName)))); + + PG_RETURN_INT64(calculate_tablespace_size(tblspcOid)); +} + + +/* + * calculate size of a relation + */ +static int64 +calculate_relation_size(Oid tblspcOid, Oid relnodeOid) +{ + int64 totalsize=0; + unsigned int segcount=0; + char dirpath[MAXPGPATH]; + char pathname[MAXPGPATH]; + + if (!tblspcOid) + tblspcOid = MyDatabaseTableSpace; + + if (tblspcOid == DEFAULTTABLESPACE_OID) + snprintf(dirpath, MAXPGPATH, "%s/base/%u", DataDir, MyDatabaseId); + else if (tblspcOid == GLOBALTABLESPACE_OID) + snprintf(dirpath, MAXPGPATH, "%s/global", DataDir); + else + snprintf(dirpath, MAXPGPATH, "%s/pg_tblspc/%u/%u", + DataDir, tblspcOid, MyDatabaseId); + + for (segcount = 0 ;; segcount++) + { + struct stat fst; + + if (segcount == 0) + snprintf(pathname, MAXPGPATH, "%s/%u", + dirpath, relnodeOid); + else + snprintf(pathname, MAXPGPATH, "%s/%u.%u", + dirpath, relnodeOid, segcount); + + if (stat(pathname, &fst) < 0) + { + if (errno == ENOENT) + break; + else + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not stat \"%s\": %m", pathname))); + } + totalsize += fst.st_size; + } + + return totalsize; +} + +Datum +pg_relation_size_oid(PG_FUNCTION_ARGS) +{ + Oid relOid=PG_GETARG_OID(0); + HeapTuple tuple; + Form_pg_class pg_class; + Oid relnodeOid; + Oid tblspcOid; + + tuple = SearchSysCache(RELOID, + ObjectIdGetDatum(relOid), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + ereport(ERROR, + (ERRCODE_UNDEFINED_TABLE, + errmsg("relation with OID %u does not exist", relOid))); + + pg_class = (Form_pg_class) GETSTRUCT(tuple); + relnodeOid = pg_class->relfilenode; + tblspcOid = pg_class->reltablespace; + + ReleaseSysCache(tuple); + + PG_RETURN_INT64(calculate_relation_size(tblspcOid, relnodeOid)); +} + +Datum +pg_relation_size_name(PG_FUNCTION_ARGS) +{ + text *relname = PG_GETARG_TEXT_P(0); + RangeVar *relrv; + Relation relation; + Oid relnodeOid; + Oid tblspcOid; + + relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname)); + relation = relation_openrv(relrv, AccessShareLock); + + tblspcOid = relation->rd_rel->reltablespace; + relnodeOid = relation->rd_rel->relfilenode; + + relation_close(relation, AccessShareLock); + + PG_RETURN_INT64(calculate_relation_size(tblspcOid, relnodeOid)); +} + + +/* + * Compute on-disk size of files for 'relation' according to the stat function, + * optionally including heap data, index data, and/or toast data. + */ +static int64 +calculate_complete_relation_size(Oid tblspcOid, Oid relnodeOid) +{ + Relation heapRelation; + Relation idxRelation; + Relation toastRelation; + Oid idxOid; + Oid idxTblspcOid; + Oid toastOid; + Oid toastTblspcOid; + bool hasIndices; + int64 size = 0; + List *indexoidlist; + ListCell *idx; + + heapRelation = relation_open(relnodeOid, AccessShareLock); + toastOid = heapRelation->rd_rel->reltoastrelid; + hasIndices = heapRelation->rd_rel->relhasindex; + + /* Get the heap size */ + size += calculate_relation_size(tblspcOid, relnodeOid); + + /* Get Index size */ + if ( hasIndices ) { + /* recursively include any dependent indexes ... */ + indexoidlist = RelationGetIndexList(heapRelation); + + foreach(idx, indexoidlist) { + idxOid = lfirst_oid(idx); + idxRelation = relation_open(idxOid, AccessShareLock); + idxTblspcOid = idxRelation->rd_rel->reltablespace; + size += calculate_relation_size(idxTblspcOid, idxOid); + relation_close(idxRelation, AccessShareLock); + } + list_free(indexoidlist); + } + + /* Close heapReleation now we no longer need it */ + relation_close(heapRelation, AccessShareLock); + + /* Get toast table size */ + if ( toastOid != 0 ) { + + /* recursively include any toast relations ... */ + toastRelation = relation_open(toastOid, AccessShareLock); + toastTblspcOid = toastRelation->rd_rel->reltablespace; + size += calculate_relation_size(toastTblspcOid, toastOid); + relation_close(toastRelation, AccessShareLock); + } + + return size; +} + +/* + * Compute on-disk size of files for 'relation' including + * heap data, index data, and toasted data. + */ +Datum +pg_complete_relation_size_oid(PG_FUNCTION_ARGS) +{ + Oid relOid=PG_GETARG_OID(0); + HeapTuple tuple; + Form_pg_class pg_class; + Oid relnodeOid; + Oid tblspcOid; + + tuple = SearchSysCache(RELOID, + ObjectIdGetDatum(relOid), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + ereport(ERROR, + (ERRCODE_UNDEFINED_TABLE, + errmsg("relation with OID %u does not exist", relOid))); + + pg_class = (Form_pg_class) GETSTRUCT(tuple); + relnodeOid = pg_class->relfilenode; + tblspcOid = pg_class->reltablespace; + + ReleaseSysCache(tuple); + + PG_RETURN_INT64(calculate_complete_relation_size(tblspcOid, relnodeOid)); +} + +Datum +pg_complete_relation_size_name(PG_FUNCTION_ARGS) +{ + text *relname = PG_GETARG_TEXT_P(0); + RangeVar *relrv; + Relation relation; + Oid relnodeOid; + Oid tblspcOid; + + relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname)); + relation = relation_openrv(relrv, AccessShareLock); + + tblspcOid = relation->rd_rel->reltablespace; + relnodeOid = relation->rd_rel->relfilenode; + + relation_close(relation, AccessShareLock); + + PG_RETURN_INT64(calculate_complete_relation_size(tblspcOid, relnodeOid)); +} + +/* + * formatting with size units + */ +Datum +pg_size_pretty(PG_FUNCTION_ARGS) +{ + int64 size=PG_GETARG_INT64(0); + char *result=palloc(50+VARHDRSZ); + int64 limit = 10*1024; + int64 mult=1; + + if (size < limit*mult) + snprintf(VARDATA(result), 50, INT64_FORMAT" bytes", + size); + else + { + mult *= 1024; + if (size < limit*mult) + snprintf(VARDATA(result), 50, INT64_FORMAT " kB", + (size+mult/2) / mult); + else + { + mult *= 1024; + if (size < limit*mult) + snprintf(VARDATA(result), 50, INT64_FORMAT " MB", + (size+mult/2) / mult); + else + { + mult *= 1024; + if (size < limit*mult) + snprintf(VARDATA(result), 50, INT64_FORMAT " GB", + (size+mult/2) / mult); + else + { + mult *= 1024; + snprintf(VARDATA(result), 50, INT64_FORMAT " TB", + (size+mult/2) / mult); + } + } + } + } + + VARATT_SIZEP(result) = strlen(VARDATA(result)) + VARHDRSZ; + + PG_RETURN_TEXT_P(result); +} |