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;
}
pg_database_size_oid(PG_FUNCTION_ARGS)
{
Oid dbOid = PG_GETARG_OID(0);
+ int64 size;
- PG_RETURN_INT64(calculate_database_size(dbOid));
+ size = calculate_database_size(dbOid);
+
+ if (size == 0)
+ PG_RETURN_NULL();
+
+ PG_RETURN_INT64(size);
}
Datum
{
Name dbName = PG_GETARG_NAME(0);
Oid dbOid = get_database_oid(NameStr(*dbName), false);
+ int64 size;
+
+ size = calculate_database_size(dbOid);
- PG_RETURN_INT64(calculate_database_size(dbOid));
+ if (size == 0)
+ PG_RETURN_NULL();
+
+ PG_RETURN_INT64(size);
}
/*
- * calculate total size of tablespace
+ * Calculate total size of tablespace. Returns -1 if the tablespace directory
+ * cannot be found.
*/
static int64
calculate_tablespace_size(Oid tblspcOid)
dirdesc = AllocateDir(tblspcPath);
if (!dirdesc)
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not open tablespace directory \"%s\": %m",
- tblspcPath)));
+ return -1;
while ((direntry = ReadDir(dirdesc, tblspcPath)) != NULL)
{
pg_tablespace_size_oid(PG_FUNCTION_ARGS)
{
Oid tblspcOid = PG_GETARG_OID(0);
+ int64 size;
+
+ size = calculate_tablespace_size(tblspcOid);
- PG_RETURN_INT64(calculate_tablespace_size(tblspcOid));
+ if (size < 0)
+ PG_RETURN_NULL();
+
+ PG_RETURN_INT64(size);
}
Datum
{
Name tblspcName = PG_GETARG_NAME(0);
Oid tblspcOid = get_tablespace_oid(NameStr(*tblspcName), false);
+ int64 size;
- PG_RETURN_INT64(calculate_tablespace_size(tblspcOid));
+ size = calculate_tablespace_size(tblspcOid);
+
+ if (size < 0)
+ PG_RETURN_NULL();
+
+ PG_RETURN_INT64(size);
}
Relation rel;
int64 size;
- rel = relation_open(relOid, AccessShareLock);
+ rel = try_relation_open(relOid, AccessShareLock);
+
+ /*
+ * Before 9.2, we used to throw an error if the relation didn't exist, but
+ * that makes queries like "SELECT pg_relation_size(oid) FROM pg_class"
+ * less robust, because while we scan pg_class with an MVCC snapshot,
+ * someone else might drop the table. It's better to return NULL for
+ * alread-dropped tables than throw an error and abort the whole query.
+ */
+ if (rel == NULL)
+ PG_RETURN_NULL();
size = calculate_relation_size(&(rel->rd_node), rel->rd_backend,
forkname_to_number(text_to_cstring(forkName)));
* those won't have attached toast tables, but they can have multiple forks.
*/
static int64
-calculate_table_size(Oid relOid)
+calculate_table_size(Relation rel)
{
int64 size = 0;
- Relation rel;
ForkNumber forkNum;
- rel = relation_open(relOid, AccessShareLock);
-
/*
* heap size, including FSM and VM
*/
if (OidIsValid(rel->rd_rel->reltoastrelid))
size += calculate_toast_table_size(rel->rd_rel->reltoastrelid);
- relation_close(rel, AccessShareLock);
-
return size;
}
* Can be applied safely to an index, but you'll just get zero.
*/
static int64
-calculate_indexes_size(Oid relOid)
+calculate_indexes_size(Relation rel)
{
int64 size = 0;
- Relation rel;
-
- rel = relation_open(relOid, AccessShareLock);
/*
* Aggregate all indexes on the given relation
list_free(index_oids);
}
- relation_close(rel, AccessShareLock);
-
return size;
}
pg_table_size(PG_FUNCTION_ARGS)
{
Oid relOid = PG_GETARG_OID(0);
+ Relation rel;
+ int64 size;
+
+ rel = try_relation_open(relOid, AccessShareLock);
+
+ if (rel == NULL)
+ PG_RETURN_NULL();
- PG_RETURN_INT64(calculate_table_size(relOid));
+ size = calculate_table_size(rel);
+
+ relation_close(rel, AccessShareLock);
+
+ PG_RETURN_INT64(size);
}
Datum
pg_indexes_size(PG_FUNCTION_ARGS)
{
Oid relOid = PG_GETARG_OID(0);
+ Relation rel;
+ int64 size;
- PG_RETURN_INT64(calculate_indexes_size(relOid));
+ rel = try_relation_open(relOid, AccessShareLock);
+
+ if (rel == NULL)
+ PG_RETURN_NULL();
+
+ size = calculate_indexes_size(rel);
+
+ relation_close(rel, AccessShareLock);
+
+ PG_RETURN_INT64(size);
}
/*
* including heap data, index data, toast data, FSM, VM.
*/
static int64
-calculate_total_relation_size(Oid Relid)
+calculate_total_relation_size(Relation rel)
{
int64 size;
* Aggregate the table size, this includes size of the heap, toast and
* toast index with free space and visibility map
*/
- size = calculate_table_size(Relid);
+ size = calculate_table_size(rel);
/*
* Add size of all attached indexes as well
*/
- size += calculate_indexes_size(Relid);
+ size += calculate_indexes_size(rel);
return size;
}
Datum
pg_total_relation_size(PG_FUNCTION_ARGS)
{
- Oid relid = PG_GETARG_OID(0);
+ Oid relOid = PG_GETARG_OID(0);
+ Relation rel;
+ int64 size;
+
+ rel = try_relation_open(relOid, AccessShareLock);
+
+ if (rel == NULL)
+ PG_RETURN_NULL();
- PG_RETURN_INT64(calculate_total_relation_size(relid));
+ size = calculate_total_relation_size(rel);
+
+ relation_close(rel, AccessShareLock);
+
+ PG_RETURN_INT64(size);
}
/*