diff options
-rw-r--r-- | src/backend/access/heap/heapam_handler.c | 27 | ||||
-rw-r--r-- | src/backend/access/table/tableamapi.c | 3 | ||||
-rw-r--r-- | src/backend/storage/buffer/bufmgr.c | 43 | ||||
-rw-r--r-- | src/include/access/tableam.h | 40 |
4 files changed, 110 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 */ } /* diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h index ebfa0d51855..c5d64602036 100644 --- a/src/include/access/tableam.h +++ b/src/include/access/tableam.h @@ -541,6 +541,22 @@ typedef struct TableAmRoutine /* ------------------------------------------------------------------------ + * Miscellaneous functions. + * ------------------------------------------------------------------------ + */ + + /* + * See table_relation_size(). + * + * Note that currently a few callers use the MAIN_FORKNUM size to vet the + * validity of tids (e.g. nodeTidscans.c), and others use it to figure out + * the range of potentially interesting blocks (brin, analyze). The + * abstraction around this will need to be improved in the near future. + */ + uint64 (*relation_size) (Relation rel, ForkNumber forkNumber); + + + /* ------------------------------------------------------------------------ * Planner related functions. * ------------------------------------------------------------------------ */ @@ -550,6 +566,10 @@ typedef struct TableAmRoutine * * While block oriented, it shouldn't be too hard for an AM that doesn't * doesn't internally use blocks to convert into a usable representation. + * + * This differs from the relation_size callback by returning size + * estimates (both relation size and tuple count) for planning purposes, + * rather than returning a currently correct estimate. */ void (*relation_estimate_size) (Relation rel, int32 *attr_widths, BlockNumber *pages, double *tuples, @@ -1504,6 +1524,26 @@ table_index_validate_scan(Relation heap_rel, /* ---------------------------------------------------------------------------- + * Miscellaneous functionality + * ---------------------------------------------------------------------------- + */ + +/* + * Return the current size of `rel` in bytes. If `forkNumber` is + * InvalidForkNumber, return the relation's overall size, otherwise the size + * for the indicated fork. + * + * Note that the overall size might not be the equivalent of the sum of sizes + * for the individual forks for some AMs, e.g. because the AMs storage does + * not neatly map onto the builtin types of forks. + */ +static inline uint64 +table_relation_size(Relation rel, ForkNumber forkNumber) +{ + return rel->rd_tableam->relation_size(rel, forkNumber); +} + +/* ---------------------------------------------------------------------------- * Planner related functionality * ---------------------------------------------------------------------------- */ |