diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index 5e2a7a8234e..ec0ccf15362 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -113,6 +113,8 @@ analyze_rel(Oid relid, RangeVar *relation, int elevel; AcquireSampleRowsFunc acquirefunc = NULL; BlockNumber relpages = 0; + FdwRoutine *fdwroutine = NULL; + bool import_stats = false; /* Select logging level */ if (params.options & VACOPT_VERBOSE) @@ -195,26 +197,32 @@ analyze_rel(Oid relid, RangeVar *relation, else if (onerel->rd_rel->relkind == RELKIND_FOREIGN_TABLE) { /* - * For a foreign table, call the FDW's hook function to see whether it - * supports analysis. + * For a foreign table, call the FDW's hook functions to see whether + * it supports statistics import or analysis. */ - FdwRoutine *fdwroutine; - bool ok = false; - fdwroutine = GetFdwRoutineForRelation(onerel, false); - if (fdwroutine->AnalyzeForeignTable != NULL) - ok = fdwroutine->AnalyzeForeignTable(onerel, - &acquirefunc, - &relpages); - - if (!ok) + if (fdwroutine->ImportStatistics != NULL && + fdwroutine->StatisticsAreImportable != NULL && + fdwroutine->StatisticsAreImportable(onerel)) + import_stats = true; + else { - ereport(WARNING, - (errmsg("skipping \"%s\" --- cannot analyze this foreign table", - RelationGetRelationName(onerel)))); - relation_close(onerel, ShareUpdateExclusiveLock); - return; + bool ok = false; + + if (fdwroutine->AnalyzeForeignTable != NULL) + ok = fdwroutine->AnalyzeForeignTable(onerel, + &acquirefunc, + &relpages); + + if (!ok) + { + ereport(WARNING, + (errmsg("skipping \"%s\" --- cannot analyze this foreign table", + RelationGetRelationName(onerel)))); + relation_close(onerel, ShareUpdateExclusiveLock); + return; + } } } else if (onerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) @@ -248,9 +256,18 @@ analyze_rel(Oid relid, RangeVar *relation, /* * Do the normal non-recursive ANALYZE. We can skip this for partitioned - * tables, which don't contain any rows. + * tables, which don't contain any rows. For foreign tables, if they + * support importing statistics, do that instead of the non-recursive + * ANALYZE. */ - if (onerel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE) + if (import_stats) + { + Assert(onerel->rd_rel->relkind == RELKIND_FOREIGN_TABLE); + Assert(fdwroutine != NULL); + Assert(fdwroutine->ImportStatistics != NULL); + fdwroutine->ImportStatistics(onerel, va_cols, elevel); + } + else if (onerel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE) do_analyze_rel(onerel, params, va_cols, acquirefunc, relpages, false, in_outer_xact, elevel); diff --git a/src/include/foreign/fdwapi.h b/src/include/foreign/fdwapi.h index fcd7e7027f3..c4453f306fa 100644 --- a/src/include/foreign/fdwapi.h +++ b/src/include/foreign/fdwapi.h @@ -157,6 +157,12 @@ typedef bool (*AnalyzeForeignTable_function) (Relation relation, AcquireSampleRowsFunc *func, BlockNumber *totalpages); +typedef bool (*StatisticsAreImportable_function) (Relation relation); + +typedef void (*ImportStatistics_function) (Relation relation, + List *va_cols, + int elevel); + typedef List *(*ImportForeignSchema_function) (ImportForeignSchemaStmt *stmt, Oid serverOid); @@ -255,6 +261,8 @@ typedef struct FdwRoutine /* Support functions for ANALYZE */ AnalyzeForeignTable_function AnalyzeForeignTable; + StatisticsAreImportable_function StatisticsAreImportable; + ImportStatistics_function ImportStatistics; /* Support functions for IMPORT FOREIGN SCHEMA */ ImportForeignSchema_function ImportForeignSchema;