Skip to content

Commit 5939a66

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 3cbacbd commit 5939a66

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
@@ -626,12 +626,18 @@ table_block_parallelscan_nextpage(Relation rel,
626626
* is stored, and if it uses them in the expected manner (e.g. the actual data
627627
* is in the main fork rather than some other), it can use this implementation
628628
* of the relation_size callback rather than implementing its own.
629+
*
630+
* Different counting methods is not supported for this function yet. It's expected
631+
* DEFAULT_SIZE in all cases.
629632
*/
630-
uint64
631-
table_block_relation_size(Relation rel, ForkNumber forkNumber)
633+
int64
634+
table_block_relation_size(Relation rel, ForkNumber forkNumber, uint8 method)
632635
{
633636
uint64 nblocks = 0;
634637

638+
if (method != DEFAULT_SIZE)
639+
return -1;
640+
635641
/* InvalidForkNumber indicates returning the size for all forks */
636642
if (forkNumber == InvalidForkNumber)
637643
{
@@ -641,7 +647,7 @@ table_block_relation_size(Relation rel, ForkNumber forkNumber)
641647
else
642648
nblocks = smgrnblocks(RelationGetSmgr(rel), forkNumber);
643649

644-
return nblocks * BLCKSZ;
650+
return (int64) nblocks * BLCKSZ;
645651
}
646652

647653
/*

src/backend/utils/adt/dbsize.c

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

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

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

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

@@ -494,6 +562,18 @@ pg_table_size(PG_FUNCTION_ARGS)
494562
if (rel == NULL)
495563
PG_RETURN_NULL();
496564

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

499579
relation_close(rel, AccessShareLock);
@@ -506,13 +586,25 @@ pg_indexes_size(PG_FUNCTION_ARGS)
506586
{
507587
Oid relOid = PG_GETARG_OID(0);
508588
Relation rel;
509-
int64 size;
589+
int64 size = 0;
510590

511591
rel = try_relation_open(relOid, AccessShareLock);
512592

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

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

518610
relation_close(rel, AccessShareLock);
@@ -555,6 +647,18 @@ pg_total_relation_size(PG_FUNCTION_ARGS)
555647
if (rel == NULL)
556648
PG_RETURN_NULL();
557649

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

560664
relation_close(rel, AccessShareLock);

src/include/access/tableam.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,15 @@ typedef struct TM_IndexDeleteOp
287287
#define TABLE_MODIFY_FETCH_OLD_TUPLE 0x0002
288288
#define TABLE_MODIFY_LOCK_UPDATED 0x0004
289289

290+
/* "method" flag bits for relation_size */
291+
/* Default behavior implemented for heap AM */
292+
#define DEFAULT_SIZE (0)
293+
/* Extended behavior that AM can provide */
294+
#define RELATION_SIZE (1)
295+
#define TABLE_SIZE (2)
296+
#define TOTAL_SIZE (3)
297+
#define TOAST_TABLE_SIZE (4)
298+
#define INDEXES_SIZE (5)
290299

291300
/* Typedef for callback function for table_index_build_scan */
292301
typedef void (*IndexBuildCallback) (Relation index,
@@ -746,7 +755,7 @@ typedef struct TableAmRoutine
746755
* probable that we'll need to revise the interface for those at some
747756
* point.
748757
*/
749-
uint64 (*relation_size) (Relation rel, ForkNumber forkNumber);
758+
int64 (*relation_size) (Relation rel, ForkNumber forkNumber, uint8 method);
750759

751760

752761
/*
@@ -1909,7 +1918,8 @@ table_index_validate_scan(Relation table_rel,
19091918
static inline uint64
19101919
table_relation_size(Relation rel, ForkNumber forkNumber)
19111920
{
1912-
return rel->rd_tableam->relation_size(rel, forkNumber);
1921+
int64 res = rel->rd_tableam->relation_size(rel, forkNumber, DEFAULT_SIZE);
1922+
return res >= 0 ? res : 0;
19131923
}
19141924

19151925
/*
@@ -2132,7 +2142,7 @@ extern void table_block_parallelscan_startblock_init(Relation rel,
21322142
* ----------------------------------------------------------------------------
21332143
*/
21342144

2135-
extern uint64 table_block_relation_size(Relation rel, ForkNumber forkNumber);
2145+
extern int64 table_block_relation_size(Relation rel, ForkNumber forkNumber, uint8 method);
21362146
extern void table_block_relation_estimate_size(Relation rel,
21372147
int32 *attr_widths,
21382148
BlockNumber *pages,

0 commit comments

Comments
 (0)