Skip to content

Commit 7994443

Browse files
committed
Extend tableam->relation_size() functionality to use different calculation methods.
This allows to output size metrics for relations and indexes provided by OrioleDB extension using existing PG functions. If extension function doesn't support the requested method it should output negative value and thus asking to fall back to using PG internal calculation e.g. - Orioledb relation_size outputs -1 for bridged indexes to fallback to counting them as PG indexes - PG table_block_relation_size outputs -1 for any method except the only DEFAULT_SIZE that it supports. This API relies on table AM extensibility and doesn't use index AM extensibility yet, which could look more logical, but also more complicated.
1 parent bc16f95 commit 7994443

File tree

3 files changed

+127
-7
lines changed

3 files changed

+127
-7
lines changed

src/backend/access/table/tableam.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -635,12 +635,18 @@ table_block_parallelscan_nextpage(Relation rel,
635635
* is stored, and if it uses them in the expected manner (e.g. the actual data
636636
* is in the main fork rather than some other), it can use this implementation
637637
* of the relation_size callback rather than implementing its own.
638+
*
639+
* Different counting methods is not supported for this function yet. It's expected
640+
* DEFAULT_SIZE in all cases.
638641
*/
639-
uint64
640-
table_block_relation_size(Relation rel, ForkNumber forkNumber)
642+
int64
643+
table_block_relation_size(Relation rel, ForkNumber forkNumber, uint8 method)
641644
{
642645
uint64 nblocks = 0;
643646

647+
if (method != DEFAULT_SIZE)
648+
return -1;
649+
644650
/* InvalidForkNumber indicates returning the size for all forks */
645651
if (forkNumber == InvalidForkNumber)
646652
{
@@ -650,7 +656,7 @@ table_block_relation_size(Relation rel, ForkNumber forkNumber)
650656
else
651657
nblocks = smgrnblocks(RelationGetSmgr(rel), forkNumber);
652658

653-
return nblocks * BLCKSZ;
659+
return (int64) nblocks * BLCKSZ;
654660
}
655661

656662
/*

src/backend/utils/adt/dbsize.c

Lines changed: 105 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "utils/relfilenumbermap.h"
3232
#include "utils/relmapper.h"
3333
#include "utils/syscache.h"
34+
#include "access/tableam.h"
3435

3536
/* Divide by two and round away from zero */
3637
#define half_rounded(x) (((x) + ((x) < 0 ? -1 : 1)) / 2)
@@ -343,6 +344,61 @@ calculate_relation_size(RelFileLocator *rfn, BackendId backend, ForkNumber forkn
343344
return totalsize;
344345
}
345346

347+
/*
348+
* Try to get size using proper relation_size method in table am. Fallback to previous method
349+
* if rd_tableam->relation_size doesn't support requested counting method or otherwise refuses
350+
* to count (with negative output)
351+
*/
352+
static
353+
int64 try_tableam_relation_size(Relation rel, ForkNumber forkNum, bool allforks, uint8 method)
354+
{
355+
int64 size = 0;
356+
357+
if (rel->rd_rel->relkind == RELKIND_INDEX)
358+
{
359+
/* For index check rd_tableam for parent relation */
360+
Relation tbl;
361+
362+
tbl = relation_open(rel->rd_index->indrelid, AccessShareLock);
363+
if(tbl->rd_tableam && tbl->rd_tableam->relation_size)
364+
{
365+
/* We call relation_size method for parent relation but provide index relation as an argument.
366+
* Method for index is always RELATION_SIZE
367+
*/
368+
if (allforks)
369+
{
370+
for (ForkNumber i = 0; i <= MAX_FORKNUM; i++)
371+
{
372+
size += tbl->rd_tableam->relation_size(rel, i, RELATION_SIZE);
373+
}
374+
}
375+
else
376+
size = tbl->rd_tableam->relation_size(rel, forkNum, RELATION_SIZE);
377+
378+
if (size >= 0)
379+
{
380+
relation_close(tbl, AccessShareLock);
381+
return size;
382+
}
383+
}
384+
relation_close(tbl, AccessShareLock);
385+
}
386+
else if (rel->rd_tableam && rel->rd_tableam->relation_size)
387+
{
388+
if (allforks)
389+
{
390+
for (ForkNumber i = 0; i <= MAX_FORKNUM; i++)
391+
size += rel->rd_tableam->relation_size(rel, i, method);
392+
}
393+
else
394+
size = rel->rd_tableam->relation_size(rel, forkNum, method);
395+
396+
if (size >= 0)
397+
return size;
398+
}
399+
return -1;
400+
}
401+
346402
Datum
347403
pg_relation_size(PG_FUNCTION_ARGS)
348404
{
@@ -363,6 +419,18 @@ pg_relation_size(PG_FUNCTION_ARGS)
363419
if (rel == NULL)
364420
PG_RETURN_NULL();
365421

422+
/*
423+
* Try to get size using proper relation_size method in table am. Fallback to previous method
424+
* if rd_tableam->relation_size doesn't support requested counting method or otherwise refuses
425+
* to count (with negative output)
426+
*/
427+
size = try_tableam_relation_size(rel, forkname_to_number(text_to_cstring(forkName)), false, RELATION_SIZE);
428+
if (size >= 0)
429+
{
430+
relation_close(rel, AccessShareLock);
431+
PG_RETURN_INT64(size);
432+
}
433+
366434
size = calculate_relation_size(&(rel->rd_locator), rel->rd_backend,
367435
forkname_to_number(text_to_cstring(forkName)));
368436

@@ -495,6 +563,18 @@ pg_table_size(PG_FUNCTION_ARGS)
495563
if (rel == NULL)
496564
PG_RETURN_NULL();
497565

566+
/*
567+
* Try to get size using proper relation_size method in table am. Fallback to previous method
568+
* if rd_tableam->relation_size doesn't support requested counting method or otherwise refuses
569+
* to count (with negative output)
570+
*/
571+
size = try_tableam_relation_size(rel, InvalidForkNumber, true, TABLE_SIZE);
572+
if (size >= 0)
573+
{
574+
relation_close(rel, AccessShareLock);
575+
PG_RETURN_INT64(size);
576+
}
577+
498578
size = calculate_table_size(rel);
499579

500580
relation_close(rel, AccessShareLock);
@@ -507,13 +587,25 @@ pg_indexes_size(PG_FUNCTION_ARGS)
507587
{
508588
Oid relOid = PG_GETARG_OID(0);
509589
Relation rel;
510-
int64 size;
590+
int64 size = 0;
511591

512592
rel = try_relation_open(relOid, AccessShareLock);
513593

514594
if (rel == NULL)
515595
PG_RETURN_NULL();
516596

597+
if (rel->rd_tableam && rel->rd_tableam->relation_size)
598+
{
599+
for (ForkNumber forkNum = 0; forkNum <= MAX_FORKNUM; forkNum++)
600+
size += rel->rd_tableam->relation_size(rel, forkNum , INDEXES_SIZE);
601+
602+
if(size >= 0)
603+
{
604+
relation_close(rel, AccessShareLock);
605+
PG_RETURN_INT64(size);
606+
}
607+
}
608+
517609
size = calculate_indexes_size(rel);
518610

519611
relation_close(rel, AccessShareLock);
@@ -556,6 +648,18 @@ pg_total_relation_size(PG_FUNCTION_ARGS)
556648
if (rel == NULL)
557649
PG_RETURN_NULL();
558650

651+
/*
652+
* Try to get size using proper relation_size method in table am. Fallback to previous method
653+
* if rd_tableam->relation_size doesn't support requested counting method or otherwise refuses
654+
* to count (with negative output)
655+
*/
656+
size = try_tableam_relation_size(rel, InvalidForkNumber, true, TOTAL_SIZE);
657+
if (size >= 0)
658+
{
659+
relation_close(rel, AccessShareLock);
660+
PG_RETURN_INT64(size);
661+
}
662+
559663
size = calculate_total_relation_size(rel);
560664

561665
relation_close(rel, AccessShareLock);

src/include/access/tableam.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,15 @@ typedef struct TM_IndexDeleteOp
279279
#define TABLE_MODIFY_FETCH_OLD_TUPLE 0x0002
280280
#define TABLE_MODIFY_LOCK_UPDATED 0x0004
281281

282+
/* "method" flag bits for relation_size */
283+
/* Default behavior implemented for heap AM */
284+
#define DEFAULT_SIZE (0)
285+
/* Extended behavior that AM can provide */
286+
#define RELATION_SIZE (1)
287+
#define TABLE_SIZE (2)
288+
#define TOTAL_SIZE (3)
289+
#define TOAST_TABLE_SIZE (4)
290+
#define INDEXES_SIZE (5)
282291

283292
/* Typedef for callback function for table_index_build_scan */
284293
typedef void (*IndexBuildCallback) (Relation index,
@@ -739,7 +748,7 @@ typedef struct TableAmRoutine
739748
* probable that we'll need to revise the interface for those at some
740749
* point.
741750
*/
742-
uint64 (*relation_size) (Relation rel, ForkNumber forkNumber);
751+
int64 (*relation_size) (Relation rel, ForkNumber forkNumber, uint8 method);
743752

744753

745754
/*
@@ -1906,7 +1915,8 @@ table_index_validate_scan(Relation table_rel,
19061915
static inline uint64
19071916
table_relation_size(Relation rel, ForkNumber forkNumber)
19081917
{
1909-
return rel->rd_tableam->relation_size(rel, forkNumber);
1918+
int64 res = rel->rd_tableam->relation_size(rel, forkNumber, DEFAULT_SIZE);
1919+
return res >= 0 ? res : 0;
19101920
}
19111921

19121922
/*
@@ -2129,7 +2139,7 @@ extern void table_block_parallelscan_startblock_init(Relation rel,
21292139
* ----------------------------------------------------------------------------
21302140
*/
21312141

2132-
extern uint64 table_block_relation_size(Relation rel, ForkNumber forkNumber);
2142+
extern int64 table_block_relation_size(Relation rel, ForkNumber forkNumber, uint8 method);
21332143
extern void table_block_relation_estimate_size(Relation rel,
21342144
int32 *attr_widths,
21352145
BlockNumber *pages,

0 commit comments

Comments
 (0)