FDW-API-for-importing-stats.patch
application/octet-stream
Filename: FDW-API-for-importing-stats.patch
Type: application/octet-stream
Part: 0
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;