From: Shigeru Hanada Date: Wed, 6 Oct 2010 10:10:42 +0000 (+0900) Subject: Revert ANALYZE support for foreign tables. X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=7945e24e0164d07fc0b1bf1ca5e61205c48b1235;p=users%2Fhanada%2Fpostgres.git Revert ANALYZE support for foreign tables. Also rename EstimateCost() in FdwRoutine because almost same function has been defined as GetStatistics() in SQL/MED standard. --- diff --git a/contrib/postgresql_fdw/postgresql_fdw.c b/contrib/postgresql_fdw/postgresql_fdw.c index 7193e756f7..6c80152fc8 100644 --- a/contrib/postgresql_fdw/postgresql_fdw.c +++ b/contrib/postgresql_fdw/postgresql_fdw.c @@ -54,9 +54,7 @@ static void pgOpen(ForeignScanState *scanstate); static void pgIterate(ForeignScanState *scanstate); static void pgClose(ForeignScanState *scanstate); static void pgReOpen(ForeignScanState *scanstate); -static void pgAnalyze(Relation rel, VacuumStmt *vacstmt, bool update_reltuples, - bool inh); -static void pgEstimateCost(Path *path, PlannerInfo *root, RelOptInfo *baserel); +static void pgGetStatistics(Path *path, PlannerInfo *root, RelOptInfo *baserel); /* deparse SQL from the request */ static bool is_immutable_func(Oid funcid); @@ -84,12 +82,11 @@ FdwRoutine postgresql_fdw_routine = { pgConnectServer, pgFreeFSConnection, + pgGetStatistics, pgOpen, pgIterate, pgClose, pgReOpen, - pgAnalyze, - pgEstimateCost, }; /* @@ -758,25 +755,13 @@ storeResult(Tuplestorestate *tupstore, pfree(values); } -/* - * Collect statistics about contents of remote table and update pg_statistics. - * If update_reltuples was true, update pg_class.reltuples/relpages too. - */ -static void -pgAnalyze(Relation rel, VacuumStmt *vacstmt, bool update_reltuples, bool inh) -{ - ereport(WARNING, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("analyze of remote PostgreSQL table not implemented"))); -} - /* * Estimate costs of scanning on a foreign table. * * baserel->baserestrictinfo can be used to examine quals on the relation. */ static void -pgEstimateCost(Path *path, PlannerInfo *root, RelOptInfo *baserel) +pgGetStatistics(Path *path, PlannerInfo *root, RelOptInfo *baserel) { RangeTblEntry *rte; ForeignTable *table; diff --git a/doc/src/sgml/ref/analyze.sgml b/doc/src/sgml/ref/analyze.sgml index ff80cfbb9e..d5f2528eb9 100644 --- a/doc/src/sgml/ref/analyze.sgml +++ b/doc/src/sgml/ref/analyze.sgml @@ -43,13 +43,6 @@ ANALYZE [ VERBOSE ] [ table [ ( - - - If the table was a foreign table, ANALYZE transfers the - responsibility to collect statistics to foreign-data wrapper's handler. If - the handler of the foreign-data wrapper didn't support Analyze() API, - analyze of the table is skipped. - diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index d8a48f7b80..14b66dd35b 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -182,13 +182,12 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt, * Check that it's a plain table; we used to do this in get_rel_oids() but * seems safer to check after we've locked the relation. */ - if (onerel->rd_rel->relkind != RELKIND_RELATION && - onerel->rd_rel->relkind != RELKIND_FOREIGN_TABLE) + if (onerel->rd_rel->relkind != RELKIND_RELATION) { /* No need for a WARNING if we already complained during VACUUM */ if (!(vacstmt->options & VACOPT_VACUUM)) ereport(WARNING, - (errmsg("skipping \"%s\" --- cannot analyze indexes, views or special system tables", + (errmsg("skipping \"%s\" --- cannot analyze indexes, views, foreign tables or special system tables", RelationGetRelationName(onerel)))); relation_close(onerel, ShareUpdateExclusiveLock); return; @@ -225,26 +224,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt, /* * Do the normal non-recursive ANALYZE. */ - if (onerel->rd_rel->relkind == RELKIND_FOREIGN_TABLE) - { - ForeignTable *table; - ForeignServer *server; - ForeignDataWrapper *wrapper; - FdwRoutine *routine; - - table = GetForeignTable(onerel->rd_id); - server = GetForeignServer(table->serverid); - wrapper = GetForeignDataWrapper(server->fdwid); - routine = GetFdwRoutine(wrapper->fdwhandler); - if (routine->Analyze) - routine->Analyze(onerel, vacstmt, update_reltuples, false); - else - ereport(WARNING, - (errmsg("skipping \"%s\" --- fdwhandler doesn't support analyze", - RelationGetRelationName(onerel)))); - } - else - do_analyze_rel(onerel, vacstmt, update_reltuples, false); + do_analyze_rel(onerel, vacstmt, update_reltuples, false); /* * If there are child tables, do recursive ANALYZE. diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 5492d0f50e..51bd3e1ae7 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -329,38 +329,30 @@ get_rel_oids(Oid relid, const RangeVar *vacrel, const char *stmttype) } else { - /* Process all plain relations and foreign tables listed in pg_class */ + /* Process all plain relations listed in pg_class */ Relation pgclass; HeapScanDesc scan; HeapTuple tuple; - ScanKeyData key[2]; - int i; + ScanKeyData key; - ScanKeyInit(&key[0], + ScanKeyInit(&key, Anum_pg_class_relkind, BTEqualStrategyNumber, F_CHAREQ, CharGetDatum(RELKIND_RELATION)); - ScanKeyInit(&key[1], - Anum_pg_class_relkind, - BTEqualStrategyNumber, F_CHAREQ, - CharGetDatum(RELKIND_FOREIGN_TABLE)); - pgclass = heap_open(RelationRelationId, AccessShareLock); - for (i = 0; i < 2; i++) + scan = heap_beginscan(pgclass, SnapshotNow, 1, &key); + + while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) { - scan = heap_beginscan(pgclass, SnapshotNow, 1, &key[i]); - while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) - { - /* Make a relation list entry for this guy */ - oldcontext = MemoryContextSwitchTo(vac_context); - oid_list = lappend_oid(oid_list, HeapTupleGetOid(tuple)); - MemoryContextSwitchTo(oldcontext); - } - heap_endscan(scan); + /* Make a relation list entry for this guy */ + oldcontext = MemoryContextSwitchTo(vac_context); + oid_list = lappend_oid(oid_list, HeapTupleGetOid(tuple)); + MemoryContextSwitchTo(oldcontext); } + heap_endscan(scan); heap_close(pgclass, AccessShareLock); } diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index 924ce621b7..a4080cc559 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -1039,18 +1039,14 @@ cost_foreignscan(Path *path, PlannerInfo *root, Assert(baserel->relid > 0); Assert(baserel->rtekind == RTE_RELATION); - /* Have the wrapper handler estimate the cost of this scan. */ + /* Leave estimation of the costs to the wrapper handler */ rte = planner_rt_fetch(baserel->relid, root); table = GetForeignTable(rte->relid); server = GetForeignServer(table->serverid); wrapper = GetForeignDataWrapper(server->fdwid); routine = GetFdwRoutine(wrapper->fdwhandler); - /* Use cost_seqscan() instead if the wrapper did't support this API. */ - if (routine->EstimateCost != NULL) - routine->EstimateCost(path, root, baserel); - else - cost_seqscan(path, root, baserel); + routine->GetStatistics(path, root, baserel); } /* diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index 01e47a2939..14f2369a0f 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -348,21 +348,6 @@ static const SchemaQuery Query_for_list_of_tsvf = { NULL }; -static const SchemaQuery Query_for_list_of_tf = { - /* catname */ - "pg_catalog.pg_class c", - /* selcondition */ - "c.relkind IN ('r', 'f')", - /* viscondition */ - "pg_catalog.pg_table_is_visible(c.oid)", - /* namespace */ - "c.relnamespace", - /* result */ - "pg_catalog.quote_ident(c.relname)", - /* qualresult */ - NULL -}; - static const SchemaQuery Query_for_list_of_views = { /* catname */ "pg_catalog.pg_class c", @@ -2559,7 +2544,7 @@ psql_completion(char *text, int start, int end) pg_strcasecmp(prev_wd, "ANALYZE") == 0 && (pg_strcasecmp(prev2_wd, "FULL") == 0 || pg_strcasecmp(prev2_wd, "FREEZE") == 0)) - COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tf, + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, " UNION SELECT 'VERBOSE'"); else if (pg_strcasecmp(prev3_wd, "VACUUM") == 0 && pg_strcasecmp(prev_wd, "VERBOSE") == 0 && @@ -2573,13 +2558,13 @@ psql_completion(char *text, int start, int end) " UNION SELECT 'ANALYZE'"); else if (pg_strcasecmp(prev2_wd, "VACUUM") == 0 && pg_strcasecmp(prev_wd, "ANALYZE") == 0) - COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tf, + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, " UNION SELECT 'VERBOSE'"); else if ((pg_strcasecmp(prev_wd, "ANALYZE") == 0 && pg_strcasecmp(prev2_wd, "VERBOSE") == 0) || (pg_strcasecmp(prev_wd, "VERBOSE") == 0 && pg_strcasecmp(prev2_wd, "ANALYZE") == 0)) - COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tf, NULL); + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL); /* WITH [RECURSIVE] */ else if (pg_strcasecmp(prev_wd, "WITH") == 0) @@ -2588,7 +2573,7 @@ psql_completion(char *text, int start, int end) /* ANALYZE */ /* If the previous word is ANALYZE, produce list of tables */ else if (pg_strcasecmp(prev_wd, "ANALYZE") == 0) - COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tf, NULL); + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL); /* WHERE */ /* Simple case of the word before the where being the table name */ diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 3c580d70a7..329dd321f9 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -1396,6 +1396,12 @@ struct FdwRoutine */ void (*FreeFSConnection)(FSConnection *conn); + /* + * Estimate costs of a foreign path. + * FDW should update startup_cost and total_cost in the Path. + */ + void (*GetStatistics)(Path *path, PlannerInfo *root, RelOptInfo *baserel); + /* * Deparse query request and open a cursor for the foreign scan. */ @@ -1416,26 +1422,6 @@ struct FdwRoutine * executed again. */ void (*ReOpen)(ForeignScanState *scanstate); - - /* - * Emulate ANALYZE on a table and create/update the statistics for the - * foreign table. Statistics to be updated are: - * - all columns of pg_statistics - * - reltuples, relpages of pg_class (only if update_reltuples was true) - * - * If this API was not implemented (== NULL), ANALYZE skips that relation. - */ - void (*Analyze)(Relation rel, VacuumStmt *vacstmt, bool update_reltuples, - bool inh); - - /* - * Estimate costs of scanning on the foreign table. - * FDW should update startup_cost and total_cost in the Path. - * - * If this API was not implemented (== NULL), cost_seqscan() will be used - * instead. - */ - void (*EstimateCost)(Path *path, PlannerInfo *root, RelOptInfo *baserel); }; /* ----------------------------------------------------------------