7 #include "access/heapam.h"
8 #include "catalog/catalog.h"
9 #include "catalog/catname.h"
10 #include "catalog/namespace.h"
11 #include "catalog/pg_tablespace.h"
12 #include "commands/dbcommands.h"
14 #include "storage/fd.h"
15 #include "utils/builtins.h"
19 get_tablespace_size(Oid dbid, Oid spcid, bool baddirOK);
22 psnprintf(size_t len, const char *fmt,...)
30 vsnprintf(buf, len, fmt, ap);
39 * SQL function: database_size(name) returns bigint
42 PG_FUNCTION_INFO_V1(database_size);
44 Datum database_size(PG_FUNCTION_ARGS);
47 database_size(PG_FUNCTION_ARGS)
49 Name dbname = PG_GETARG_NAME(0);
59 dbid = get_database_oid(NameStr(*dbname));
60 if (!OidIsValid(dbid))
62 (errcode(ERRCODE_UNDEFINED_DATABASE),
63 errmsg("database \"%s\" does not exist", NameStr(*dbname))));
67 dbrel = heap_openr(TableSpaceRelationName, AccessShareLock);
68 scan = heap_beginscan(dbrel, SnapshotNow, 0, (ScanKey) NULL);
72 while((tuple = heap_getnext(scan, ForwardScanDirection)))
74 Oid spcid = HeapTupleGetOid(tuple);
75 if(spcid != GLOBALTABLESPACE_OID)
76 totalsize += get_tablespace_size(dbid, spcid, true);
79 heap_close(dbrel, AccessShareLock);
82 totalsize = get_tablespace_size(dbid, DEFAULTTABLESPACE_OID, false);
86 * We need to keep in mind that we may not be called from the database
87 * whose size we're reporting so, we need to look in every tablespace
88 * to see if our database has data in there
91 PG_RETURN_INT64(totalsize);
95 get_tablespace_size(Oid dbid, Oid spcid, bool baddirOK)
99 struct dirent *direntry;
102 dbpath = GetDatabasePath(dbid, spcid);
104 dirdesc = AllocateDir(dbpath);
111 (errcode_for_file_access(),
112 errmsg("could not open directory \"%s\": %m", dbpath)));
121 direntry = readdir(dirdesc);
126 (errcode_for_file_access(),
127 errmsg("error reading directory: %m")));
132 fullname = psnprintf(strlen(dbpath) + 1 + strlen(direntry->d_name) + 1,
133 "%s/%s", dbpath, direntry->d_name);
134 if (stat(fullname, &statbuf) == -1)
136 (errcode_for_file_access(),
137 errmsg("could not stat \"%s\": %m", fullname)));
138 totalsize += statbuf.st_size;
147 * SQL function: relation_size(text) returns bigint
150 PG_FUNCTION_INFO_V1(relation_size);
152 Datum relation_size(PG_FUNCTION_ARGS);
155 relation_size(PG_FUNCTION_ARGS)
157 text *relname = PG_GETARG_TEXT_P(0);
163 unsigned int segcount;
165 relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname,
167 relation = heap_openrv(relrv, AccessShareLock);
169 relnode = relation->rd_rel->relfilenode;
179 fullname = psnprintf(25, "%u", (unsigned) relnode);
181 fullname = psnprintf(50, "%u.%u", (unsigned) relnode, segcount);
183 if (stat(fullname, &statbuf) == -1)
189 (errcode_for_file_access(),
190 errmsg("could not stat \"%s\": %m", fullname)));
192 totalsize += statbuf.st_size;
197 heap_close(relation, AccessShareLock);
199 PG_RETURN_INT64(totalsize);