Skip to content

Commit ad0787b

Browse files
committed
I've written on like that a while ago:
http://webmail.postgresql.org/~petere/dbsize.html The tarball can be rolled into contrib -- now that I think of it I don't know why I never did that. Never imagined this would have anything to do with that TODO item, though. I figured oid2name accomplished that. Peter Eisentraut peter_e@gmx.net
1 parent 40bda4c commit ad0787b

File tree

6 files changed

+203
-2
lines changed

6 files changed

+203
-2
lines changed

contrib/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# $Header: /cvsroot/pgsql/contrib/Makefile,v 1.30 2001/10/12 23:19:09 tgl Exp $
1+
# $Header: /cvsroot/pgsql/contrib/Makefile,v 1.31 2002/02/22 23:05:34 momjian Exp $
22

33
subdir = contrib
44
top_builddir = ..
@@ -11,6 +11,7 @@ WANTED_DIRS = \
1111
cube \
1212
dbase \
1313
dblink \
14+
dbsize \
1415
earthdistance \
1516
findoidjoins \
1617
fulltextindex \

contrib/README

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,11 @@ dbase -
4848

4949
dblink -
5050
Allows remote query execution
51-
by Joe Conway, joe.conway@mail.com
51+
by Joe Conway <joe.conway@mail.com>
52+
53+
dbsize -
54+
Reports database and table disk space
55+
by Peter Eisentraut <peter_e@gmx.net>
5256

5357
earthdistance -
5458
Operator for computing earth distance for two points

contrib/dbsize/Makefile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
subdir = contrib/dbsize
2+
top_builddir = ../..
3+
include $(top_builddir)/src/Makefile.global
4+
5+
MODULES = dbsize
6+
DATA_built = dbsize.sql
7+
DOCS = README.dbsize
8+
9+
include $(top_srcdir)/contrib/contrib-global.mk

contrib/dbsize/README.dbsize

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
This module contains two functions that report the size of a given
2+
database or relation. E.g.,
3+
4+
SELECT database_size('template1');
5+
SELECT relation_size('pg_class');
6+
7+
These functions report the actual file system space. Thus, users can
8+
avoid digging through the details of the database directories.
9+
10+
Copy this directory to contrib/dbsize in your PostgreSQL source tree.
11+
Then just run make; make install.

contrib/dbsize/dbsize.c

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
#include "postgres.h"
2+
#include "fmgr.h"
3+
4+
#include "access/heapam.h"
5+
#include "catalog/catalog.h"
6+
#include "catalog/catname.h"
7+
#include "catalog/pg_database.h"
8+
#include "utils/fmgroids.h"
9+
10+
#include <stdlib.h>
11+
#include <sys/types.h>
12+
#include <dirent.h>
13+
#include <sys/stat.h>
14+
#include <unistd.h>
15+
#include <errno.h>
16+
17+
18+
static char *
19+
psnprintf(size_t len, const char *fmt,...)
20+
{
21+
va_list ap;
22+
char *buf;
23+
24+
buf = palloc(len);
25+
26+
va_start(ap, fmt);
27+
vsnprintf(buf, len, fmt, ap);
28+
va_end(ap);
29+
30+
return buf;
31+
}
32+
33+
34+
35+
/*
36+
* SQL function: database_size(name) returns bigint
37+
*/
38+
39+
PG_FUNCTION_INFO_V1(database_size);
40+
41+
Datum
42+
database_size(PG_FUNCTION_ARGS)
43+
{
44+
Name dbname = PG_GETARG_NAME(0);
45+
46+
HeapTuple tuple;
47+
Relation relation;
48+
ScanKeyData scanKey;
49+
HeapScanDesc scan;
50+
Oid dbid;
51+
char *dbpath;
52+
DIR *dirdesc;
53+
struct dirent *direntry;
54+
int64 totalsize;
55+
56+
relation = heap_openr(DatabaseRelationName, AccessShareLock);
57+
ScanKeyEntryInitialize(&scanKey, 0, Anum_pg_database_datname,
58+
F_NAMEEQ, NameGetDatum(dbname));
59+
scan = heap_beginscan(relation, 0, SnapshotNow, 1, &scanKey);
60+
tuple = heap_getnext(scan, 0);
61+
62+
if (!HeapTupleIsValid(tuple))
63+
elog(ERROR, "database %s does not exist", NameStr(*dbname));
64+
65+
dbid = tuple->t_data->t_oid;
66+
if (dbid == InvalidOid)
67+
elog(ERROR, "invalid database id");
68+
69+
heap_endscan(scan);
70+
heap_close(relation, NoLock);
71+
72+
dbpath = GetDatabasePath(dbid);
73+
74+
dirdesc = opendir(dbpath);
75+
if (!dirdesc)
76+
elog(ERROR, "could not open directory %s: %s", dbpath, strerror(errno));
77+
78+
totalsize = 0;
79+
for (;;)
80+
{
81+
char *fullname;
82+
struct stat statbuf;
83+
84+
errno = 0;
85+
direntry = readdir(dirdesc);
86+
if (!direntry)
87+
{
88+
if (errno)
89+
elog(ERROR, "error reading directory: %s", strerror(errno));
90+
else
91+
break;
92+
}
93+
94+
fullname = psnprintf(strlen(dbpath) + 1 + strlen(direntry->d_name) + 1,
95+
"%s/%s", dbpath, direntry->d_name);
96+
if (stat(fullname, &statbuf) == -1)
97+
elog(ERROR, "could not stat %s: %s", fullname, strerror(errno));
98+
totalsize += statbuf.st_size;
99+
pfree(fullname);
100+
}
101+
102+
closedir(dirdesc);
103+
104+
PG_RETURN_INT64(totalsize);
105+
}
106+
107+
108+
109+
/*
110+
* SQL function: relation_size(name) returns bigint
111+
*/
112+
113+
PG_FUNCTION_INFO_V1(relation_size);
114+
115+
Datum
116+
relation_size(PG_FUNCTION_ARGS)
117+
{
118+
Name relname = PG_GETARG_NAME(0);
119+
120+
HeapTuple tuple;
121+
Relation relation;
122+
ScanKeyData scanKey;
123+
HeapScanDesc scan;
124+
Oid relnode;
125+
int64 totalsize;
126+
unsigned int segcount;
127+
128+
relation = heap_openr(RelationRelationName, AccessShareLock);
129+
ScanKeyEntryInitialize(&scanKey, 0, Anum_pg_class_relname,
130+
F_NAMEEQ, NameGetDatum(relname));
131+
scan = heap_beginscan(relation, 0, SnapshotNow, 1, &scanKey);
132+
tuple = heap_getnext(scan, 0);
133+
134+
if (!HeapTupleIsValid(tuple))
135+
elog(ERROR, "relation %s does not exist", NameStr(*relname));
136+
137+
relnode = ((Form_pg_class) GETSTRUCT(tuple))->relfilenode;
138+
if (relnode == InvalidOid)
139+
elog(ERROR, "invalid relation node id");
140+
141+
heap_endscan(scan);
142+
heap_close(relation, NoLock);
143+
144+
totalsize = 0;
145+
segcount = 0;
146+
for (;;)
147+
{
148+
char *fullname;
149+
struct stat statbuf;
150+
151+
if (segcount == 0)
152+
fullname = psnprintf(25, "%u", (unsigned) relnode);
153+
else
154+
fullname = psnprintf(50, "%u.%u", (unsigned) relnode, segcount);
155+
156+
if (stat(fullname, &statbuf) == -1)
157+
{
158+
if (errno == ENOENT)
159+
break;
160+
else
161+
elog(ERROR, "could not stat %s: %s", fullname, strerror(errno));
162+
}
163+
totalsize += statbuf.st_size;
164+
pfree(fullname);
165+
segcount++;
166+
}
167+
168+
PG_RETURN_INT64(totalsize);
169+
}

contrib/dbsize/dbsize.sql.in

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CREATE FUNCTION database_size (name) RETURNS bigint
2+
AS '@MODULE_FILENAME@', 'database_size'
3+
LANGUAGE C WITH (isstrict);
4+
5+
CREATE FUNCTION relation_size (name) RETURNS bigint
6+
AS '@MODULE_FILENAME@', 'relation_size'
7+
LANGUAGE C WITH (isstrict);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy