aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorAndres Freund <andres@anarazel.de>2019-05-17 18:06:18 -0700
committerAndres Freund <andres@anarazel.de>2019-05-17 18:56:47 -0700
commit7f44ede5941499c4cee13b812dd93335f4005095 (patch)
tree7c3705c22e1d6f94644c3f05a20f8f8f8a699533 /src/backend
parent6630ccad7a25cad32e2d1a6833fb971602cb67fe (diff)
downloadpostgresql-7f44ede5941499c4cee13b812dd93335f4005095.tar.gz
postgresql-7f44ede5941499c4cee13b812dd93335f4005095.zip
tableam: Don't assume that every AM uses md.c style storage.
Previously various parts of the code routed size requests through RelationGetNumberOfBlocks[InFork]. That works if md.c is used by the AM, but not otherwise. Add a tableam callback to return the size of the table. As not every AM will use postgres' BLCKSZ, have it return bytes, and have RelationGetNumberOfBlocksInFork() round the byte size up into blocks. To allow code outside of the AM to determine the actual relation size map InvalidForkNumber the total size of a relation, as not every AM might just need the postgres defined forks. A few users of RelationGetNumberOfBlocks() ought to be converted away from that. One case, the use of it to determine whether a tid is valid, will be fixed in a follow up commit. Others will have to wait for v13. Author: Andres Freund Discussion: https://postgr.es/m/20190423225201.3bbv6tbqzkb5w7cw@alap3.anarazel.de
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/access/heap/heapam_handler.c27
-rw-r--r--src/backend/access/table/tableamapi.c3
-rw-r--r--src/backend/storage/buffer/bufmgr.c43
3 files changed, 70 insertions, 3 deletions
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
index 00505ec3f4d..9aa468295ae 100644
--- a/src/backend/access/heap/heapam_handler.c
+++ b/src/backend/access/heap/heapam_handler.c
@@ -1975,6 +1975,31 @@ heapam_scan_get_blocks_done(HeapScanDesc hscan)
}
+/* ------------------------------------------------------------------------
+ * Miscellaneous callbacks for the heap AM
+ * ------------------------------------------------------------------------
+ */
+
+static uint64
+heapam_relation_size(Relation rel, ForkNumber forkNumber)
+{
+ uint64 nblocks = 0;
+
+ /* Open it at the smgr level if not already done */
+ RelationOpenSmgr(rel);
+
+ /* InvalidForkNumber indicates returning the size for all forks */
+ if (forkNumber == InvalidForkNumber)
+ {
+ for (int i = 0; i < MAX_FORKNUM; i++)
+ nblocks += smgrnblocks(rel->rd_smgr, i);
+ }
+ else
+ nblocks = smgrnblocks(rel->rd_smgr, forkNumber);
+
+ return nblocks * BLCKSZ;
+}
+
/* ------------------------------------------------------------------------
* Planner related callbacks for the heap AM
@@ -2556,6 +2581,8 @@ static const TableAmRoutine heapam_methods = {
.index_build_range_scan = heapam_index_build_range_scan,
.index_validate_scan = heapam_index_validate_scan,
+ .relation_size = heapam_relation_size,
+
.relation_estimate_size = heapam_estimate_rel_size,
.scan_bitmap_next_block = heapam_scan_bitmap_next_block,
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
index 0053dc95cab..32877e7674f 100644
--- a/src/backend/access/table/tableamapi.c
+++ b/src/backend/access/table/tableamapi.c
@@ -86,6 +86,9 @@ GetTableAmRoutine(Oid amhandler)
Assert(routine->scan_analyze_next_tuple != NULL);
Assert(routine->index_build_range_scan != NULL);
Assert(routine->index_validate_scan != NULL);
+
+ Assert(routine->relation_size != NULL);
+
Assert(routine->relation_estimate_size != NULL);
/* optional, but one callback implies presence of hte other */
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index 887023fc8a5..33d7941a405 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -33,6 +33,7 @@
#include <sys/file.h>
#include <unistd.h>
+#include "access/tableam.h"
#include "access/xlog.h"
#include "catalog/catalog.h"
#include "catalog/storage.h"
@@ -2789,14 +2790,50 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln)
/*
* RelationGetNumberOfBlocksInFork
* Determines the current number of pages in the specified relation fork.
+ *
+ * Note that the accuracy of the result will depend on the details of the
+ * relation's storage. For builtin AMs it'll be accurate, but for external AMs
+ * it might not be.
*/
BlockNumber
RelationGetNumberOfBlocksInFork(Relation relation, ForkNumber forkNum)
{
- /* Open it at the smgr level if not already done */
- RelationOpenSmgr(relation);
+ switch (relation->rd_rel->relkind)
+ {
+ case RELKIND_SEQUENCE:
+ case RELKIND_INDEX:
+ case RELKIND_PARTITIONED_INDEX:
+ /* Open it at the smgr level if not already done */
+ RelationOpenSmgr(relation);
+
+ return smgrnblocks(relation->rd_smgr, forkNum);
+
+ case RELKIND_RELATION:
+ case RELKIND_TOASTVALUE:
+ case RELKIND_MATVIEW:
+ {
+ /*
+ * Not every table AM uses BLCKSZ wide fixed size
+ * blocks. Therefore tableam returns the size in bytes - but
+ * for the purpose of this routine, we want the number of
+ * blocks. Therefore divide, rounding up.
+ */
+ uint64 szbytes;
+
+ szbytes = table_relation_size(relation, forkNum);
+
+ return (szbytes + (BLCKSZ - 1)) / BLCKSZ;
+ }
+ case RELKIND_VIEW:
+ case RELKIND_COMPOSITE_TYPE:
+ case RELKIND_FOREIGN_TABLE:
+ case RELKIND_PARTITIONED_TABLE:
+ default:
+ Assert(false);
+ break;
+ }
- return smgrnblocks(relation->rd_smgr, forkNum);
+ return 0; /* keep compiler quiet */
}
/*