diff --git a/src/backend/access/aocs/aocsam_handler.c b/src/backend/access/aocs/aocsam_handler.c index 7fe9c7f287c..2eb1984617d 100644 --- a/src/backend/access/aocs/aocsam_handler.c +++ b/src/backend/access/aocs/aocsam_handler.c @@ -2181,6 +2181,14 @@ aoco_scan_sample_next_tuple(TableScanDesc scan, SampleScanState *scanstate, return ret; } +static void +aoco_swap_relation_files(Oid relid1, Oid relid2, + TransactionId frozenXid pg_attribute_unused(), + MultiXactId cutoffMulti pg_attribute_unused()) +{ + SwapAppendonlyEntries(relid1, relid2); +} + /* ------------------------------------------------------------------------ * Definition of the AO_COLUMN table access method. * @@ -2258,6 +2266,7 @@ static TableAmRoutine ao_column_methods = { .scan_sample_next_tuple = aoco_scan_sample_next_tuple, .amoptions = ao_amoptions, + .swap_relation_files = aoco_swap_relation_files, }; Datum diff --git a/src/backend/access/appendonly/appendonlyam_handler.c b/src/backend/access/appendonly/appendonlyam_handler.c index 78cbf6cc436..78107d08b44 100644 --- a/src/backend/access/appendonly/appendonlyam_handler.c +++ b/src/backend/access/appendonly/appendonlyam_handler.c @@ -2314,6 +2314,14 @@ appendonly_scan_sample_next_tuple(TableScanDesc scan, SampleScanState *scanstate return ret; } +static void +appendonly_swap_relation_files(Oid relid1, Oid relid2, + TransactionId frozenXid pg_attribute_unused(), + MultiXactId cutoffMulti pg_attribute_unused()) +{ + SwapAppendonlyEntries(relid1, relid2); +} + /* ------------------------------------------------------------------------ * Definition of the appendonly table access method. * @@ -2385,6 +2393,7 @@ static const TableAmRoutine ao_row_methods = { .scan_sample_next_tuple = appendonly_scan_sample_next_tuple, .amoptions = ao_amoptions, + .swap_relation_files = appendonly_swap_relation_files, }; Datum diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index ed0762fd42b..e0f76612b34 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -1304,7 +1304,24 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class, relform2->relallvisible = swap_allvisible; } - SwapAppendonlyEntries(r1, r2); + /* + * Swap auxiliary tables if the table AM has non-standard structure. + * See the details of the callback swap_relation_files. + */ + if (relform1->relkind == RELKIND_RELATION || + relform1->relkind == RELKIND_MATVIEW) + { + const TableAmRoutine *tam; + Oid relam; + + relam = relform1->relam; + if (relam != relform2->relam) + elog(ERROR, "can't swap relation files for different AM"); + + tam = GetTableAmRoutineByAmId(relam); + if (tam->swap_relation_files) + tam->swap_relation_files(r1, r2, frozenXid, cutoffMulti); + } /* * Update the tuples in pg_class --- unless the target relation of the diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h index d4c8d6beb9c..f3a1b357a35 100644 --- a/src/include/access/tableam.h +++ b/src/include/access/tableam.h @@ -892,6 +892,17 @@ typedef struct TableAmRoutine */ bytea *(*amoptions)(Datum reloptions, char relkind, bool validate); + /* + * This callback is used to swap internal auxiliary relation if + * the table AM use different layout structure to organize tuples. + * + * Standard heap relation will swap the heap relation itself and optional + * toast relation. Custom table AM could have different data structure, + * like AO-row/AO-col tables have several auxiliary relations. + * This behavior is table AM-specific. + */ + void (*swap_relation_files) (Oid relid1, Oid relid2, TransactionId frozenXid, MultiXactId cutoffMulti); + } TableAmRoutine;