Use TableAm API in pg_table_size
Hi,
I noticed that there are several file layout assumptions in dbsize.c which might not hold true for non heap relations attached with the TableAm API. It seems logical that in order to retrieve the disk size of a relation, the existing size method to be used instead.
A small patch is included to demonstrate how such an implementation can look like. Also, the existing method for heap, table_block_relation_size, should be able to address the valid cases where a fork number does not exist.
If this is considered valid, then the same can be applied for indexes too. The more generic calculate_relation_size can be adapted to call into the TableAm for those kinds of relations that makes sense. If agreed, a more complete patch can be provided.
Cheers,
//Georgios
Attachments:
0001-Use-tableam-for-pg_table_size.patchapplication/octet-stream; name=0001-Use-tableam-for-pg_table_size.patchDownload
diff --git a/src/backend/access/table/tableam.c b/src/backend/access/table/tableam.c
index c814733b22..9cce6c3f34 100644
--- a/src/backend/access/table/tableam.c
+++ b/src/backend/access/table/tableam.c
@@ -516,10 +516,14 @@ table_block_relation_size(Relation rel, ForkNumber forkNumber)
if (forkNumber == InvalidForkNumber)
{
for (int i = 0; i < MAX_FORKNUM; i++)
- nblocks += smgrnblocks(rel->rd_smgr, i);
+ nblocks += smgrexists(rel->rd_smgr, i)
+ ? smgrnblocks(rel->rd_smgr, i)
+ : 0;
}
else
- nblocks = smgrnblocks(rel->rd_smgr, forkNumber);
+ nblocks += smgrexists(rel->rd_smgr, forkNumber)
+ ? smgrnblocks(rel->rd_smgr, forkNumber)
+ : 0;
return nblocks * BLCKSZ;
}
diff --git a/src/backend/utils/adt/dbsize.c b/src/backend/utils/adt/dbsize.c
index 840664429e..ce51726bc7 100644
--- a/src/backend/utils/adt/dbsize.c
+++ b/src/backend/utils/adt/dbsize.c
@@ -15,6 +15,7 @@
#include "access/htup_details.h"
#include "access/relation.h"
+#include "access/tableam.h"
#include "catalog/catalog.h"
#include "catalog/namespace.h"
#include "catalog/pg_authid.h"
@@ -342,7 +343,7 @@ pg_relation_size(PG_FUNCTION_ARGS)
static int64
calculate_toast_table_size(Oid toastrelid)
{
- int64 size = 0;
+ uint64 size = 0;
Relation toastRel;
ForkNumber forkNum;
ListCell *lc;
@@ -352,8 +353,7 @@ calculate_toast_table_size(Oid toastrelid)
/* toast heap size, including FSM and VM size */
for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
- size += calculate_relation_size(&(toastRel->rd_node),
- toastRel->rd_backend, forkNum);
+ size += table_relation_size(toastRel, forkNum);
/* toast index size, including FSM and VM size */
indexlist = RelationGetIndexList(toastRel);
@@ -374,29 +374,30 @@ calculate_toast_table_size(Oid toastrelid)
list_free(indexlist);
relation_close(toastRel, AccessShareLock);
- return size;
+ Assert(size < PG_INT64_MAX);
+
+ return (int64)size;
}
/*
* Calculate total on-disk size of a given table,
- * including FSM and VM, plus TOAST table if any.
+ * plus TOAST table if any.
* Indexes other than the TOAST table's index are not included.
*
- * Note that this also behaves sanely if applied to an index or toast table;
+ * Note that this also behaves sanely if applied to a toast table;
* those won't have attached toast tables, but they can have multiple forks.
*/
static int64
calculate_table_size(Relation rel)
{
- int64 size = 0;
+ uint64 size = 0;
ForkNumber forkNum;
/*
- * heap size, including FSM and VM
+ * table size, including FSM and VM
*/
for (forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
- size += calculate_relation_size(&(rel->rd_node), rel->rd_backend,
- forkNum);
+ size += table_relation_size(rel, forkNum);
/*
* Size of toast relation
@@ -404,7 +405,9 @@ calculate_table_size(Relation rel)
if (OidIsValid(rel->rd_rel->reltoastrelid))
size += calculate_toast_table_size(rel->rd_rel->reltoastrelid);
- return size;
+ Assert(size < PG_INT64_MAX);
+
+ return (int64)size;
}
/*
@@ -452,14 +455,17 @@ pg_table_size(PG_FUNCTION_ARGS)
{
Oid relOid = PG_GETARG_OID(0);
Relation rel;
- int64 size;
+ int64 size = 0;
rel = try_relation_open(relOid, AccessShareLock);
if (rel == NULL)
PG_RETURN_NULL();
- size = calculate_table_size(rel);
+ if (RELKIND_HAS_STORAGE(rel->rd_rel->relkind) &&
+ rel->rd_rel->relkind != RELKIND_INDEX &&
+ rel->rd_rel->relkind != RELKIND_SEQUENCE)
+ size = calculate_table_size(rel);
relation_close(rel, AccessShareLock);
@@ -487,7 +493,7 @@ pg_indexes_size(PG_FUNCTION_ARGS)
/*
* Compute the on-disk size of all files for the relation,
- * including heap data, index data, toast data, FSM, VM.
+ * including table data, index data, toast data.
*/
static int64
calculate_total_relation_size(Relation rel)