mirror of
https://github.com/postgres/postgres.git
synced 2025-04-22 23:02:54 +03:00
Make pg_relation_size() and friends return NULL if the object doesn't exist.
That avoids errors when the functions are used in queries like "SELECT pg_relation_size(oid) FROM pg_class", and a table is dropped concurrently. Phil Sorber
This commit is contained in:
parent
6f6b46c9c0
commit
fa352d662e
@ -14979,6 +14979,11 @@ postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
|
|||||||
the table name.
|
the table name.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
If an OID that does not represent an existing object is passed as
|
||||||
|
argument to one of the above functions, NULL is returned.
|
||||||
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The functions shown in <xref linkend="functions-admin-dblocation"> assist
|
The functions shown in <xref linkend="functions-admin-dblocation"> assist
|
||||||
in identifying the specific disk files associated with database objects.
|
in identifying the specific disk files associated with database objects.
|
||||||
|
@ -120,12 +120,6 @@ calculate_database_size(Oid dbOid)
|
|||||||
|
|
||||||
FreeDir(dirdesc);
|
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;
|
return totalsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,8 +127,14 @@ Datum
|
|||||||
pg_database_size_oid(PG_FUNCTION_ARGS)
|
pg_database_size_oid(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
Oid dbOid = PG_GETARG_OID(0);
|
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
|
Datum
|
||||||
@ -142,13 +142,20 @@ pg_database_size_name(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
Name dbName = PG_GETARG_NAME(0);
|
Name dbName = PG_GETARG_NAME(0);
|
||||||
Oid dbOid = get_database_oid(NameStr(*dbName), false);
|
Oid dbOid = get_database_oid(NameStr(*dbName), false);
|
||||||
|
int64 size;
|
||||||
|
|
||||||
PG_RETURN_INT64(calculate_database_size(dbOid));
|
size = 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
|
static int64
|
||||||
calculate_tablespace_size(Oid tblspcOid)
|
calculate_tablespace_size(Oid tblspcOid)
|
||||||
@ -184,10 +191,7 @@ calculate_tablespace_size(Oid tblspcOid)
|
|||||||
dirdesc = AllocateDir(tblspcPath);
|
dirdesc = AllocateDir(tblspcPath);
|
||||||
|
|
||||||
if (!dirdesc)
|
if (!dirdesc)
|
||||||
ereport(ERROR,
|
return -1;
|
||||||
(errcode_for_file_access(),
|
|
||||||
errmsg("could not open tablespace directory \"%s\": %m",
|
|
||||||
tblspcPath)));
|
|
||||||
|
|
||||||
while ((direntry = ReadDir(dirdesc, tblspcPath)) != NULL)
|
while ((direntry = ReadDir(dirdesc, tblspcPath)) != NULL)
|
||||||
{
|
{
|
||||||
@ -226,8 +230,14 @@ Datum
|
|||||||
pg_tablespace_size_oid(PG_FUNCTION_ARGS)
|
pg_tablespace_size_oid(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
Oid tblspcOid = PG_GETARG_OID(0);
|
Oid tblspcOid = PG_GETARG_OID(0);
|
||||||
|
int64 size;
|
||||||
|
|
||||||
PG_RETURN_INT64(calculate_tablespace_size(tblspcOid));
|
size = calculate_tablespace_size(tblspcOid);
|
||||||
|
|
||||||
|
if (size < 0)
|
||||||
|
PG_RETURN_NULL();
|
||||||
|
|
||||||
|
PG_RETURN_INT64(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
@ -235,8 +245,14 @@ pg_tablespace_size_name(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
Name tblspcName = PG_GETARG_NAME(0);
|
Name tblspcName = PG_GETARG_NAME(0);
|
||||||
Oid tblspcOid = get_tablespace_oid(NameStr(*tblspcName), false);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -289,7 +305,17 @@ pg_relation_size(PG_FUNCTION_ARGS)
|
|||||||
Relation rel;
|
Relation rel;
|
||||||
int64 size;
|
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,
|
size = calculate_relation_size(&(rel->rd_node), rel->rd_backend,
|
||||||
forkname_to_number(text_to_cstring(forkName)));
|
forkname_to_number(text_to_cstring(forkName)));
|
||||||
@ -339,14 +365,11 @@ calculate_toast_table_size(Oid toastrelid)
|
|||||||
* those won't have attached toast tables, but they can have multiple forks.
|
* those won't have attached toast tables, but they can have multiple forks.
|
||||||
*/
|
*/
|
||||||
static int64
|
static int64
|
||||||
calculate_table_size(Oid relOid)
|
calculate_table_size(Relation rel)
|
||||||
{
|
{
|
||||||
int64 size = 0;
|
int64 size = 0;
|
||||||
Relation rel;
|
|
||||||
ForkNumber forkNum;
|
ForkNumber forkNum;
|
||||||
|
|
||||||
rel = relation_open(relOid, AccessShareLock);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* heap size, including FSM and VM
|
* heap size, including FSM and VM
|
||||||
*/
|
*/
|
||||||
@ -360,8 +383,6 @@ calculate_table_size(Oid relOid)
|
|||||||
if (OidIsValid(rel->rd_rel->reltoastrelid))
|
if (OidIsValid(rel->rd_rel->reltoastrelid))
|
||||||
size += calculate_toast_table_size(rel->rd_rel->reltoastrelid);
|
size += calculate_toast_table_size(rel->rd_rel->reltoastrelid);
|
||||||
|
|
||||||
relation_close(rel, AccessShareLock);
|
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,12 +392,9 @@ calculate_table_size(Oid relOid)
|
|||||||
* Can be applied safely to an index, but you'll just get zero.
|
* Can be applied safely to an index, but you'll just get zero.
|
||||||
*/
|
*/
|
||||||
static int64
|
static int64
|
||||||
calculate_indexes_size(Oid relOid)
|
calculate_indexes_size(Relation rel)
|
||||||
{
|
{
|
||||||
int64 size = 0;
|
int64 size = 0;
|
||||||
Relation rel;
|
|
||||||
|
|
||||||
rel = relation_open(relOid, AccessShareLock);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Aggregate all indexes on the given relation
|
* Aggregate all indexes on the given relation
|
||||||
@ -405,8 +423,6 @@ calculate_indexes_size(Oid relOid)
|
|||||||
list_free(index_oids);
|
list_free(index_oids);
|
||||||
}
|
}
|
||||||
|
|
||||||
relation_close(rel, AccessShareLock);
|
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,16 +430,38 @@ Datum
|
|||||||
pg_table_size(PG_FUNCTION_ARGS)
|
pg_table_size(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
Oid relOid = PG_GETARG_OID(0);
|
Oid relOid = PG_GETARG_OID(0);
|
||||||
|
Relation rel;
|
||||||
|
int64 size;
|
||||||
|
|
||||||
PG_RETURN_INT64(calculate_table_size(relOid));
|
rel = try_relation_open(relOid, AccessShareLock);
|
||||||
|
|
||||||
|
if (rel == NULL)
|
||||||
|
PG_RETURN_NULL();
|
||||||
|
|
||||||
|
size = calculate_table_size(rel);
|
||||||
|
|
||||||
|
relation_close(rel, AccessShareLock);
|
||||||
|
|
||||||
|
PG_RETURN_INT64(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
pg_indexes_size(PG_FUNCTION_ARGS)
|
pg_indexes_size(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
Oid relOid = PG_GETARG_OID(0);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -431,7 +469,7 @@ pg_indexes_size(PG_FUNCTION_ARGS)
|
|||||||
* including heap data, index data, toast data, FSM, VM.
|
* including heap data, index data, toast data, FSM, VM.
|
||||||
*/
|
*/
|
||||||
static int64
|
static int64
|
||||||
calculate_total_relation_size(Oid Relid)
|
calculate_total_relation_size(Relation rel)
|
||||||
{
|
{
|
||||||
int64 size;
|
int64 size;
|
||||||
|
|
||||||
@ -439,12 +477,12 @@ calculate_total_relation_size(Oid Relid)
|
|||||||
* Aggregate the table size, this includes size of the heap, toast and
|
* Aggregate the table size, this includes size of the heap, toast and
|
||||||
* toast index with free space and visibility map
|
* 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
|
* Add size of all attached indexes as well
|
||||||
*/
|
*/
|
||||||
size += calculate_indexes_size(Relid);
|
size += calculate_indexes_size(rel);
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
@ -452,9 +490,20 @@ calculate_total_relation_size(Oid Relid)
|
|||||||
Datum
|
Datum
|
||||||
pg_total_relation_size(PG_FUNCTION_ARGS)
|
pg_total_relation_size(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
Oid relid = PG_GETARG_OID(0);
|
Oid relOid = PG_GETARG_OID(0);
|
||||||
|
Relation rel;
|
||||||
|
int64 size;
|
||||||
|
|
||||||
PG_RETURN_INT64(calculate_total_relation_size(relid));
|
rel = try_relation_open(relOid, AccessShareLock);
|
||||||
|
|
||||||
|
if (rel == NULL)
|
||||||
|
PG_RETURN_NULL();
|
||||||
|
|
||||||
|
size = calculate_total_relation_size(rel);
|
||||||
|
|
||||||
|
relation_close(rel, AccessShareLock);
|
||||||
|
|
||||||
|
PG_RETURN_INT64(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user