Revert ANALYZE support for foreign tables.
authorShigeru Hanada <[email protected]>
Wed, 6 Oct 2010 10:10:42 +0000 (19:10 +0900)
committerShigeru Hanada <[email protected]>
Wed, 6 Oct 2010 10:10:42 +0000 (19:10 +0900)
Also rename EstimateCost() in FdwRoutine because almost same function
has been defined as GetStatistics() in SQL/MED standard.

contrib/postgresql_fdw/postgresql_fdw.c
doc/src/sgml/ref/analyze.sgml
src/backend/commands/analyze.c
src/backend/commands/vacuum.c
src/backend/optimizer/path/costsize.c
src/bin/psql/tab-complete.c
src/include/nodes/execnodes.h

index 7193e756f7b71a7c3b782a97a2f979f4c82840cc..6c80152fc85f10a74ce0d24e521e3676d5e1b56c 100644 (file)
@@ -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;
index ff80cfbb9e4d2bf90038cc93b27527a618d8fa5a..d5f2528eb96ad349cabee4d30aca5079d64380ac 100644 (file)
@@ -43,13 +43,6 @@ ANALYZE [ VERBOSE ] [ <replaceable class="PARAMETER">table</replaceable> [ ( <re
    only that table.  It is further possible to give a list of column names,
    in which case only the statistics for those columns are collected.
   </para>
-
-  <para>
-   If the table was a foreign table, <command>ANALYZE</command> 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.
-  </para>
  </refsect1>
 
  <refsect1>
index d8a48f7b806daee06bb3538c3277b7359d59eafd..14b66dd35b99986458b95b51511373aa0f0cfaca 100644 (file)
@@ -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.
index 5492d0f50e129faf2b76b3693031c331f99232e2..51bd3e1ae734fabecb4d19c59f2190f965b055ab 100644 (file)
@@ -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);
    }
 
index 924ce621b7a6f3770648f752fc861a18b9aeddcb..a4080cc559266a8abd74a9df2cad8588222cdc64 100644 (file)
@@ -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);
 }
 
 /*
index 01e47a2939d1922d696ef47b27ba22b9d9748afd..14f2369a0f7ab118891c9d1a515c0cf3f2bb9a0e 100644 (file)
@@ -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 */
index 3c580d70a722ec2670ca270fea27aa8bc07c239d..329dd321f9eee88e1b8b37105c75c830afea9b19 100644 (file)
@@ -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);
 };
 
 /* ----------------------------------------------------------------