+++ /dev/null
-CREATE FUNCTION database_size (name) RETURNS bigint
- AS 'MODULE_PATHNAME', 'database_size'
- LANGUAGE C STRICT;
-
-CREATE FUNCTION relation_size (text) RETURNS bigint
- AS 'MODULE_PATHNAME', 'relation_size'
- LANGUAGE C STRICT;
-
-CREATE FUNCTION pg_tablespace_size(oid) RETURNS bigint
- AS 'MODULE_PATHNAME', 'pg_tablespace_size'
- LANGUAGE C STRICT;
-
-CREATE FUNCTION pg_database_size(oid) RETURNS bigint
- AS 'MODULE_PATHNAME', 'pg_database_size'
- LANGUAGE C STRICT;
-
-CREATE FUNCTION pg_relation_size(oid) RETURNS bigint
- AS 'MODULE_PATHNAME', 'pg_relation_size'
- LANGUAGE C STRICT;
-
-CREATE FUNCTION pg_size_pretty(bigint) RETURNS text
- AS 'MODULE_PATHNAME', 'pg_size_pretty'
- LANGUAGE C STRICT;
-
-CREATE FUNCTION total_relation_size (text) RETURNS bigint AS '
-SELECT pg_relation_size(r.oid)
- + COALESCE(pg_relation_size(t.oid), 0)::bigint
- + COALESCE(pg_relation_size(ti.oid), 0)::bigint
- + COALESCE(SUM(pg_relation_size(i.indexrelid)), 0)::bigint
- + COALESCE(SUM(pg_relation_size(it.oid)), 0)::bigint
- + COALESCE(SUM(pg_relation_size(iti.oid)), 0)::bigint AS bytes
-FROM pg_class r
- LEFT JOIN pg_class t ON (r.reltoastrelid = t.oid)
- LEFT JOIN pg_class ti ON (t.reltoastidxid = ti.oid)
- LEFT JOIN pg_index i ON (r.oid = i.indrelid)
- LEFT JOIN pg_class ir ON (ir.oid = i.indexrelid)
- LEFT JOIN pg_class it ON (ir.reltoastrelid = it.oid)
- LEFT JOIN pg_class iti ON (it.reltoastidxid = iti.oid)
-WHERE r.relname = \$1
-GROUP BY r.oid, t.oid, ti.oid
-' LANGUAGE SQL;
-
-CREATE FUNCTION indexes_size (text) RETURNS bigint
- AS '
-SELECT COALESCE(SUM(pg_relation_size(ir.oid)), 0)::bigint
- + COALESCE(SUM(pg_relation_size(it.oid)), 0)::bigint
- + COALESCE(SUM(pg_relation_size(iti.oid)), 0)::bigint AS bytes
-FROM pg_class r
- LEFT JOIN pg_index i ON (r.oid = i.indrelid)
- LEFT JOIN pg_class ir ON (ir.oid = i.indexrelid)
- LEFT JOIN pg_class it ON (ir.reltoastrelid = it.oid)
- LEFT JOIN pg_class iti ON (it.reltoastidxid = iti.oid)
-WHERE r.relname = \$1
-' LANGUAGE SQL;
-
-CREATE FUNCTION relation_size_components (text) RETURNS SETOF RECORD
- AS '
--- relation size
-SELECT indexes_size(r.relname) AS indexes_size,
- relation_size(r.relname) AS data_size,
- total_relation_size(r.relname) AS total_size,
- r.relname, r.relkind, r.oid AS relid, r.relfilenode
-FROM pg_class r
-WHERE r.relname = \$1
-
-UNION ALL
-
--- relation toast size
-SELECT indexes_size(toast.relname) AS indexes_size,
- relation_size(''pg_toast.''||toast.relname) AS data_size,
- total_relation_size(toast.relname) AS total_size,
- toast.relname, toast.relkind, toast.oid AS relid, toast.relfilenode
-FROM pg_class r, pg_class toast
-WHERE r.reltoastrelid = toast.oid
- AND r.relname = \$1
-
-UNION ALL
-
--- relation toast index size
-SELECT indexes_size(toastidxr.relname) AS indexes_size,
- relation_size(''pg_toast.''||toastidxr.relname) AS data_size,
- total_relation_size(toastidxr.relname) AS total_size,
- toastidxr.relname, toastidxr.relkind,
- toastidxr.oid AS relid, toastidxr.relfilenode
-FROM pg_class r, pg_index toastidx, pg_class toastidxr
-WHERE r.relname = \$1
- AND r.reltoastrelid = toastidx.indrelid
- AND toastidx.indexrelid = toastidxr.oid
-
-UNION ALL
-
--- relation indices size
-SELECT indexes_size(idxr.relname) AS indexes_size,
- relation_size(idxr.relname) AS data_size,
- total_relation_size(idxr.relname) AS total_size,
- idxr.relname, idxr.relkind, idxr.oid AS relid, idxr.relfilenode
-FROM pg_class r, pg_class idxr, pg_index idx
-WHERE r.relname = \$1
- AND r.oid = idx.indrelid
- AND idx.indexrelid = idxr.oid
-
-UNION ALL
-
--- relation indices toast size
-SELECT indexes_size(idxtoastr.relname) AS indexes_size,
- relation_size(''pg_toast.''||idxtoastr.relname) AS data_size,
- total_relation_size(idxtoastr.relname) AS total_size,
- idxtoastr.relname, idxtoastr.relkind, idxtoastr.oid AS relid,
- idxtoastr.relfilenode
-FROM pg_class r, pg_class idxr, pg_index idx, pg_class idxtoastr
-WHERE r.relname = \$1
- AND r.oid = idx.indrelid
- AND idx.indexrelid = idxr.oid
- AND idxr.reltoastrelid = idxtoastr.oid
-
-UNION ALL
-
--- relation indices toast index size
-SELECT indexes_size(idxtoastidxr.relname) AS indexes_size,
- relation_size(''pg_toast.''||idxtoastidxr.relname) AS data_size,
- total_relation_size(idxtoastidxr.relname) AS total_size,
- idxtoastidxr.relname, idxtoastidxr.relkind,
- idxtoastidxr.oid AS relid, idxtoastidxr.relfilenode
-FROM pg_class r, pg_class idxr, pg_index idx, pg_class idxtoast,
- pg_class idxtoastidxr
-WHERE r.relname = \$1
- AND r.oid = idx.indrelid
- AND idx.indexrelid = idxr.oid
- AND idxr.reltoastrelid = idxtoast.oid
- AND idxtoast.reltoastrelid = idxtoastidxr.oid
-' LANGUAGE SQL;
-
-/*
- * dbsize.c
- * object size functions
- *
- * Copyright (c) 2002-2005, PostgreSQL Global Development Group
- *
- * IDENTIFICATION
- * $PostgreSQL: pgsql/contrib/dbsize/dbsize.c,v 1.19 2005/07/04 04:51:43 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 "miscadmin.h"
-#include "storage/fd.h"
-#include "utils/builtins.h"
-#include "utils/syscache.h"
-
-
-Datum pg_tablespace_size(PG_FUNCTION_ARGS);
-Datum pg_database_size(PG_FUNCTION_ARGS);
-Datum pg_relation_size(PG_FUNCTION_ARGS);
-Datum pg_size_pretty(PG_FUNCTION_ARGS);
-
-Datum database_size(PG_FUNCTION_ARGS);
-Datum relation_size(PG_FUNCTION_ARGS);
-
-PG_FUNCTION_INFO_V1(pg_tablespace_size);
-PG_FUNCTION_INFO_V1(pg_database_size);
-PG_FUNCTION_INFO_V1(pg_relation_size);
-PG_FUNCTION_INFO_V1(pg_size_pretty);
-
-PG_FUNCTION_INFO_V1(database_size);
-PG_FUNCTION_INFO_V1(relation_size);
-
-
-/* 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, path)) != 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;
-}
-
-
-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, "base/%u", dbOid);
- totalsize += db_dir_size(pathname);
-
- /* Scan the non-default tablespaces */
- snprintf(pathname, MAXPGPATH, "pg_tblspc");
- dirdesc = AllocateDir(pathname);
-
- while ((direntry = ReadDir(dirdesc, pathname)) != NULL)
- {
- if (strcmp(direntry->d_name, ".") == 0 ||
- strcmp(direntry->d_name, "..") == 0)
- continue;
-
- snprintf(pathname, MAXPGPATH, "pg_tblspc/%s/%u",
- 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;
-}
-
-/*
- * calculate total size of tablespace
- */
-Datum
-pg_tablespace_size(PG_FUNCTION_ARGS)
-{
- Oid tblspcOid = PG_GETARG_OID(0);
- char tblspcPath[MAXPGPATH];
- char pathname[MAXPGPATH];
- int64 totalsize=0;
- DIR *dirdesc;
- struct dirent *direntry;
-
- if (tblspcOid == DEFAULTTABLESPACE_OID)
- snprintf(tblspcPath, MAXPGPATH, "base");
- else if (tblspcOid == GLOBALTABLESPACE_OID)
- snprintf(tblspcPath, MAXPGPATH, "global");
- else
- snprintf(tblspcPath, MAXPGPATH, "pg_tblspc/%u", tblspcOid);
-
- dirdesc = AllocateDir(tblspcPath);
-
- while ((direntry = ReadDir(dirdesc, tblspcPath)) != 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)));
- totalsize += fst.st_size;
-
- if (fst.st_mode & S_IFDIR)
- totalsize += db_dir_size(pathname);
- }
-
- FreeDir(dirdesc);
-
- PG_RETURN_INT64(totalsize);
-}
-
-
-/*
- * calculate size of database in all tablespaces
- */
-Datum
-pg_database_size(PG_FUNCTION_ARGS)
-{
- Oid dbOid = PG_GETARG_OID(0);
-
- PG_RETURN_INT64(calculate_database_size(dbOid));
-}
-
-Datum
-database_size(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 relation size given tablespace and relation OIDs */
-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, "base/%u", MyDatabaseId);
- else if (tblspcOid == GLOBALTABLESPACE_OID)
- snprintf(dirpath, MAXPGPATH, "global");
- else
- snprintf(dirpath, MAXPGPATH, "pg_tblspc/%u/%u",
- 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;
-}
-
-/*
- * calculate size of relation
- */
-Datum
-pg_relation_size(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
-relation_size(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));
-}
-
-/*
- * 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);
-}
+/*\r
+ * dbsize.c\r
+ * object size functions\r
+ *\r
+ * Copyright (c) 2002-2005, PostgreSQL Global Development Group\r
+ *\r
+ * IDENTIFICATION\r
+ * $PostgreSQL: pgsql/src/backend/utils/adt/dbsize.c,v 1.1 2005/07/29 14:46:57 momjian Exp $\r
+ *\r
+ */\r
+\r
+#include "postgres.h"\r
+\r
+#include <sys/types.h>\r
+#include <sys/stat.h>\r
+\r
+#include "access/heapam.h"\r
+#include "catalog/namespace.h"\r
+#include "catalog/pg_tablespace.h"\r
+#include "commands/dbcommands.h"\r
+#include "commands/tablespace.h"\r
+#include "miscadmin.h"\r
+#include "storage/fd.h"\r
+#include "utils/builtins.h"\r
+#include "utils/syscache.h"\r
+#include "utils/relcache.h"\r
+\r
+\r
+/* Return physical size of directory contents, or 0 if dir doesn't exist */\r
+static int64\r
+db_dir_size(const char *path)\r
+{\r
+ int64 dirsize = 0;\r
+ struct dirent *direntry;\r
+ DIR *dirdesc;\r
+ char filename[MAXPGPATH];\r
+\r
+ dirdesc = AllocateDir(path);\r
+\r
+ if (!dirdesc)\r
+ return 0;\r
+\r
+ while ((direntry = readdir(dirdesc)) != NULL)\r
+ {\r
+ struct stat fst;\r
+\r
+ if (strcmp(direntry->d_name, ".") == 0 ||\r
+ strcmp(direntry->d_name, "..") == 0)\r
+ continue;\r
+\r
+ snprintf(filename, MAXPGPATH, "%s/%s", path, direntry->d_name);\r
+\r
+ if (stat(filename, &fst) < 0)\r
+ ereport(ERROR,\r
+ (errcode_for_file_access(),\r
+ errmsg("could not stat \"%s\": %m", filename)));\r
+ \r
+ dirsize += fst.st_size;\r
+ }\r
+\r
+ FreeDir(dirdesc);\r
+ return dirsize;\r
+}\r
+\r
+/*\r
+ * calculate size of database in all tablespaces\r
+ */\r
+static int64\r
+calculate_database_size(Oid dbOid)\r
+{\r
+ int64 totalsize = 0;\r
+ DIR *dirdesc;\r
+ struct dirent *direntry;\r
+ char pathname[MAXPGPATH];\r
+\r
+ /* Shared storage in pg_global is not counted */\r
+\r
+ /* Include pg_default storage */\r
+ snprintf(pathname, MAXPGPATH, "%s/base/%u", DataDir, dbOid);\r
+ totalsize += db_dir_size(pathname);\r
+\r
+ /* Scan the non-default tablespaces */\r
+ snprintf(pathname, MAXPGPATH, "%s/pg_tblspc", DataDir);\r
+ dirdesc = AllocateDir(pathname);\r
+ if (!dirdesc)\r
+ ereport(ERROR,\r
+ (errcode_for_file_access(),\r
+ errmsg("could not open tablespace directory \"%s\": %m",\r
+ pathname)));\r
+\r
+ while ((direntry = readdir(dirdesc)) != NULL)\r
+ {\r
+ if (strcmp(direntry->d_name, ".") == 0 ||\r
+ strcmp(direntry->d_name, "..") == 0)\r
+ continue;\r
+\r
+ snprintf(pathname, MAXPGPATH, "%s/pg_tblspc/%s/%u",\r
+ DataDir, direntry->d_name, dbOid);\r
+ totalsize += db_dir_size(pathname);\r
+ }\r
+\r
+ FreeDir(dirdesc);\r
+\r
+ /* Complain if we found no trace of the DB at all */\r
+ if (!totalsize)\r
+ ereport(ERROR,\r
+ (ERRCODE_UNDEFINED_DATABASE,\r
+ errmsg("database with OID %u does not exist", dbOid)));\r
+\r
+ return totalsize;\r
+}\r
+\r
+Datum\r
+pg_database_size_oid(PG_FUNCTION_ARGS)\r
+{\r
+ Oid dbOid = PG_GETARG_OID(0);\r
+\r
+ PG_RETURN_INT64(calculate_database_size(dbOid));\r
+}\r
+\r
+Datum\r
+pg_database_size_name(PG_FUNCTION_ARGS)\r
+{\r
+ Name dbName = PG_GETARG_NAME(0);\r
+ Oid dbOid = get_database_oid(NameStr(*dbName));\r
+\r
+ if (!OidIsValid(dbOid))\r
+ ereport(ERROR,\r
+ (errcode(ERRCODE_UNDEFINED_DATABASE),\r
+ errmsg("database \"%s\" does not exist",\r
+ NameStr(*dbName))));\r
+\r
+ PG_RETURN_INT64(calculate_database_size(dbOid));\r
+}\r
+\r
+\r
+/*\r
+ * calculate total size of tablespace\r
+ */\r
+static int64\r
+calculate_tablespace_size(Oid tblspcOid)\r
+{\r
+ char tblspcPath[MAXPGPATH];\r
+ char pathname[MAXPGPATH];\r
+ int64 totalsize=0;\r
+ DIR *dirdesc;\r
+ struct dirent *direntry;\r
+\r
+ if (tblspcOid == DEFAULTTABLESPACE_OID)\r
+ snprintf(tblspcPath, MAXPGPATH, "%s/base", DataDir);\r
+ else if (tblspcOid == GLOBALTABLESPACE_OID)\r
+ snprintf(tblspcPath, MAXPGPATH, "%s/global", DataDir);\r
+ else\r
+ snprintf(tblspcPath, MAXPGPATH, "%s/pg_tblspc/%u", DataDir, tblspcOid);\r
+\r
+ dirdesc = AllocateDir(tblspcPath);\r
+\r
+ if (!dirdesc)\r
+ ereport(ERROR,\r
+ (errcode_for_file_access(),\r
+ errmsg("could not open tablespace directory \"%s\": %m",\r
+ tblspcPath)));\r
+\r
+ while ((direntry = readdir(dirdesc)) != NULL)\r
+ {\r
+ struct stat fst;\r
+\r
+ if (strcmp(direntry->d_name, ".") == 0 ||\r
+ strcmp(direntry->d_name, "..") == 0)\r
+ continue;\r
+\r
+ snprintf(pathname, MAXPGPATH, "%s/%s", tblspcPath, direntry->d_name);\r
+\r
+ if (stat(pathname, &fst) < 0)\r
+ ereport(ERROR,\r
+ (errcode_for_file_access(),\r
+ errmsg("could not stat \"%s\": %m", pathname)));\r
+\r
+ if (fst.st_mode & S_IFDIR)\r
+ totalsize += db_dir_size(pathname);\r
+ \r
+ totalsize += fst.st_size;\r
+ }\r
+\r
+ FreeDir(dirdesc);\r
+ \r
+ return totalsize;\r
+}\r
+\r
+Datum\r
+pg_tablespace_size_oid(PG_FUNCTION_ARGS)\r
+{\r
+ Oid tblspcOid = PG_GETARG_OID(0);\r
+ \r
+ PG_RETURN_INT64(calculate_tablespace_size(tblspcOid));\r
+}\r
+\r
+Datum\r
+pg_tablespace_size_name(PG_FUNCTION_ARGS)\r
+{\r
+ Name tblspcName = PG_GETARG_NAME(0);\r
+ Oid tblspcOid = get_tablespace_oid(NameStr(*tblspcName));\r
+\r
+ if (!OidIsValid(tblspcOid))\r
+ ereport(ERROR,\r
+ (errcode(ERRCODE_UNDEFINED_OBJECT),\r
+ errmsg("tablespace \"%s\" does not exist",\r
+ NameStr(*tblspcName))));\r
+\r
+ PG_RETURN_INT64(calculate_tablespace_size(tblspcOid));\r
+}\r
+\r
+\r
+/*\r
+ * calculate size of a relation\r
+ */\r
+static int64\r
+calculate_relation_size(Oid tblspcOid, Oid relnodeOid)\r
+{\r
+ int64 totalsize=0;\r
+ unsigned int segcount=0;\r
+ char dirpath[MAXPGPATH];\r
+ char pathname[MAXPGPATH];\r
+\r
+ if (!tblspcOid)\r
+ tblspcOid = MyDatabaseTableSpace;\r
+\r
+ if (tblspcOid == DEFAULTTABLESPACE_OID)\r
+ snprintf(dirpath, MAXPGPATH, "%s/base/%u", DataDir, MyDatabaseId);\r
+ else if (tblspcOid == GLOBALTABLESPACE_OID)\r
+ snprintf(dirpath, MAXPGPATH, "%s/global", DataDir);\r
+ else\r
+ snprintf(dirpath, MAXPGPATH, "%s/pg_tblspc/%u/%u",\r
+ DataDir, tblspcOid, MyDatabaseId);\r
+\r
+ for (segcount = 0 ;; segcount++)\r
+ {\r
+ struct stat fst;\r
+\r
+ if (segcount == 0)\r
+ snprintf(pathname, MAXPGPATH, "%s/%u",\r
+ dirpath, relnodeOid);\r
+ else\r
+ snprintf(pathname, MAXPGPATH, "%s/%u.%u",\r
+ dirpath, relnodeOid, segcount);\r
+\r
+ if (stat(pathname, &fst) < 0)\r
+ {\r
+ if (errno == ENOENT)\r
+ break;\r
+ else\r
+ ereport(ERROR,\r
+ (errcode_for_file_access(),\r
+ errmsg("could not stat \"%s\": %m", pathname)));\r
+ }\r
+ totalsize += fst.st_size;\r
+ }\r
+\r
+ return totalsize;\r
+}\r
+\r
+Datum\r
+pg_relation_size_oid(PG_FUNCTION_ARGS)\r
+{\r
+ Oid relOid=PG_GETARG_OID(0);\r
+ HeapTuple tuple;\r
+ Form_pg_class pg_class;\r
+ Oid relnodeOid;\r
+ Oid tblspcOid;\r
+\r
+ tuple = SearchSysCache(RELOID,\r
+ ObjectIdGetDatum(relOid),\r
+ 0, 0, 0);\r
+ if (!HeapTupleIsValid(tuple))\r
+ ereport(ERROR,\r
+ (ERRCODE_UNDEFINED_TABLE,\r
+ errmsg("relation with OID %u does not exist", relOid)));\r
+\r
+ pg_class = (Form_pg_class) GETSTRUCT(tuple);\r
+ relnodeOid = pg_class->relfilenode;\r
+ tblspcOid = pg_class->reltablespace;\r
+\r
+ ReleaseSysCache(tuple);\r
+\r
+ PG_RETURN_INT64(calculate_relation_size(tblspcOid, relnodeOid));\r
+}\r
+\r
+Datum\r
+pg_relation_size_name(PG_FUNCTION_ARGS)\r
+{\r
+ text *relname = PG_GETARG_TEXT_P(0);\r
+ RangeVar *relrv;\r
+ Relation relation;\r
+ Oid relnodeOid;\r
+ Oid tblspcOid;\r
+ \r
+ relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname)); \r
+ relation = relation_openrv(relrv, AccessShareLock);\r
+ \r
+ tblspcOid = relation->rd_rel->reltablespace; \r
+ relnodeOid = relation->rd_rel->relfilenode;\r
+ \r
+ relation_close(relation, AccessShareLock);\r
+\r
+ PG_RETURN_INT64(calculate_relation_size(tblspcOid, relnodeOid));\r
+}\r
+\r
+\r
+/*\r
+ * Compute on-disk size of files for 'relation' according to the stat function, \r
+ * optionally including heap data, index data, and/or toast data.\r
+ */\r
+static int64\r
+calculate_complete_relation_size(Oid tblspcOid, Oid relnodeOid)\r
+{\r
+ Relation heapRelation;\r
+ Relation idxRelation;\r
+ Relation toastRelation;\r
+ Oid idxOid;\r
+ Oid idxTblspcOid;\r
+ Oid toastOid;\r
+ Oid toastTblspcOid;\r
+ bool hasIndices;\r
+ int64 size = 0;\r
+ List *indexoidlist;\r
+ ListCell *idx;\r
+\r
+ heapRelation = relation_open(relnodeOid, AccessShareLock);\r
+ toastOid = heapRelation->rd_rel->reltoastrelid;\r
+ hasIndices = heapRelation->rd_rel->relhasindex;\r
+\r
+ /* Get the heap size */\r
+ size += calculate_relation_size(tblspcOid, relnodeOid);\r
+\r
+ /* Get Index size */\r
+ if ( hasIndices ) {\r
+ /* recursively include any dependent indexes ... */\r
+ indexoidlist = RelationGetIndexList(heapRelation);\r
+ \r
+ foreach(idx, indexoidlist) {\r
+ idxOid = lfirst_oid(idx);\r
+ idxRelation = relation_open(idxOid, AccessShareLock);\r
+ idxTblspcOid = idxRelation->rd_rel->reltablespace;\r
+ size += calculate_relation_size(idxTblspcOid, idxOid);\r
+ relation_close(idxRelation, AccessShareLock);\r
+ }\r
+ list_free(indexoidlist);\r
+ }\r
+ \r
+ /* Close heapReleation now we no longer need it */\r
+ relation_close(heapRelation, AccessShareLock);\r
+\r
+ /* Get toast table size */\r
+ if ( toastOid != 0 ) {\r
+\r
+ /* recursively include any toast relations ... */\r
+ toastRelation = relation_open(toastOid, AccessShareLock);\r
+ toastTblspcOid = toastRelation->rd_rel->reltablespace;\r
+ size += calculate_relation_size(toastTblspcOid, toastOid);\r
+ relation_close(toastRelation, AccessShareLock);\r
+ }\r
+\r
+ return size;\r
+}\r
+\r
+/*\r
+ * Compute on-disk size of files for 'relation' including \r
+ * heap data, index data, and toasted data.\r
+ */\r
+Datum\r
+pg_complete_relation_size_oid(PG_FUNCTION_ARGS)\r
+{\r
+ Oid relOid=PG_GETARG_OID(0);\r
+ HeapTuple tuple;\r
+ Form_pg_class pg_class;\r
+ Oid relnodeOid;\r
+ Oid tblspcOid;\r
+\r
+ tuple = SearchSysCache(RELOID,\r
+ ObjectIdGetDatum(relOid),\r
+ 0, 0, 0);\r
+ if (!HeapTupleIsValid(tuple))\r
+ ereport(ERROR,\r
+ (ERRCODE_UNDEFINED_TABLE,\r
+ errmsg("relation with OID %u does not exist", relOid)));\r
+\r
+ pg_class = (Form_pg_class) GETSTRUCT(tuple);\r
+ relnodeOid = pg_class->relfilenode;\r
+ tblspcOid = pg_class->reltablespace;\r
+\r
+ ReleaseSysCache(tuple);\r
+\r
+ PG_RETURN_INT64(calculate_complete_relation_size(tblspcOid, relnodeOid));\r
+}\r
+\r
+Datum\r
+pg_complete_relation_size_name(PG_FUNCTION_ARGS)\r
+{\r
+ text *relname = PG_GETARG_TEXT_P(0);\r
+ RangeVar *relrv;\r
+ Relation relation;\r
+ Oid relnodeOid;\r
+ Oid tblspcOid;\r
+ \r
+ relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname)); \r
+ relation = relation_openrv(relrv, AccessShareLock);\r
+ \r
+ tblspcOid = relation->rd_rel->reltablespace; \r
+ relnodeOid = relation->rd_rel->relfilenode;\r
+ \r
+ relation_close(relation, AccessShareLock);\r
+\r
+ PG_RETURN_INT64(calculate_complete_relation_size(tblspcOid, relnodeOid));\r
+}\r
+\r
+/*\r
+ * formatting with size units\r
+ */\r
+Datum\r
+pg_size_pretty(PG_FUNCTION_ARGS)\r
+{\r
+ int64 size=PG_GETARG_INT64(0);\r
+ char *result=palloc(50+VARHDRSZ);\r
+ int64 limit = 10*1024;\r
+ int64 mult=1;\r
+\r
+ if (size < limit*mult)\r
+ snprintf(VARDATA(result), 50, INT64_FORMAT" bytes",\r
+ size);\r
+ else\r
+ {\r
+ mult *= 1024;\r
+ if (size < limit*mult)\r
+ snprintf(VARDATA(result), 50, INT64_FORMAT " kB",\r
+ (size+mult/2) / mult);\r
+ else\r
+ {\r
+ mult *= 1024;\r
+ if (size < limit*mult)\r
+ snprintf(VARDATA(result), 50, INT64_FORMAT " MB",\r
+ (size+mult/2) / mult);\r
+ else\r
+ {\r
+ mult *= 1024;\r
+ if (size < limit*mult)\r
+ snprintf(VARDATA(result), 50, INT64_FORMAT " GB",\r
+ (size+mult/2) / mult);\r
+ else\r
+ {\r
+ mult *= 1024;\r
+ snprintf(VARDATA(result), 50, INT64_FORMAT " TB",\r
+ (size+mult/2) / mult);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ VARATT_SIZEP(result) = strlen(VARDATA(result)) + VARHDRSZ;\r
+\r
+ PG_RETURN_TEXT_P(result);\r
+}\r