]> granicus.if.org Git - postgresql/blobdiff - src/backend/optimizer/path/allpaths.c
Implement an API to let foreign-data wrappers actually be functional.
[postgresql] / src / backend / optimizer / path / allpaths.c
index aa9a90cbfa2e67ef572b683f9b8938725ff271b8..c835a954ed97b29e87adb933af5078f27fc9971b 100644 (file)
@@ -3,7 +3,7 @@
  * allpaths.c
  *       Routines to find possible search paths for processing a query
  *
- * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
@@ -17,6 +17,7 @@
 
 #include <math.h>
 
+#include "catalog/pg_class.h"
 #include "nodes/nodeFuncs.h"
 #ifdef OPTIMIZER_DEBUG
 #include "nodes/print.h"
@@ -34,6 +35,7 @@
 #include "parser/parse_clause.h"
 #include "parser/parsetree.h"
 #include "rewrite/rewriteManip.h"
+#include "utils/lsyscache.h"
 
 
 /* These parameters are set by GUC */
@@ -63,6 +65,8 @@ static void set_cte_pathlist(PlannerInfo *root, RelOptInfo *rel,
                                 RangeTblEntry *rte);
 static void set_worktable_pathlist(PlannerInfo *root, RelOptInfo *rel,
                                           RangeTblEntry *rte);
+static void set_foreign_pathlist(PlannerInfo *root, RelOptInfo *rel,
+                                          RangeTblEntry *rte);
 static RelOptInfo *make_rel_from_joinlist(PlannerInfo *root, List *joinlist);
 static bool subquery_is_pushdown_safe(Query *subquery, Query *topquery,
                                                  bool *differentTypes);
@@ -197,9 +201,17 @@ set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
        }
        else
        {
-               /* Plain relation */
                Assert(rel->rtekind == RTE_RELATION);
-               set_plain_rel_pathlist(root, rel, rte);
+               if (get_rel_relkind(rte->relid) == RELKIND_FOREIGN_TABLE)
+               {
+                       /* Foreign table */
+                       set_foreign_pathlist(root, rel, rte);
+               }
+               else
+               {
+                       /* Plain relation */
+                       set_plain_rel_pathlist(root, rel, rte);
+               }
        }
 
 #ifdef OPTIMIZER_DEBUG
@@ -758,11 +770,8 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
        rel->subrtable = subroot->parse->rtable;
        rel->subrowmark = subroot->rowMarks;
 
-       /* Copy number of output rows from subplan */
-       rel->tuples = rel->subplan->plan_rows;
-
        /* Mark rel with estimated output rows, width, etc */
-       set_baserel_size_estimates(root, rel);
+       set_subquery_size_estimates(root, rel, subroot);
 
        /* Convert subquery pathkeys to outer representation */
        pathkeys = convert_subquery_pathkeys(root, rel, subroot->query_pathkeys);
@@ -907,6 +916,23 @@ set_worktable_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
        set_cheapest(rel);
 }
 
+/*
+ * set_foreign_pathlist
+ *             Build the (single) access path for a foreign table RTE
+ */
+static void
+set_foreign_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
+{
+       /* Mark rel with estimated output rows, width, etc */
+       set_foreign_size_estimates(root, rel);
+
+       /* Generate appropriate path */
+       add_path(rel, (Path *) create_foreignscan_path(root, rel));
+
+       /* Select cheapest path (pretty easy in this case...) */
+       set_cheapest(rel);
+}
+
 /*
  * make_rel_from_joinlist
  *       Build access paths using a "joinlist" to guide the join path search.
@@ -1506,6 +1532,9 @@ print_path(PlannerInfo *root, Path *path, int indent)
                case T_TidPath:
                        ptype = "TidScan";
                        break;
+               case T_ForeignPath:
+                       ptype = "ForeignScan";
+                       break;
                case T_AppendPath:
                        ptype = "Append";
                        break;