(2012/03/09 14:00), Tom Lane wrote:
I wrote:
There are a couple of other points that make me think we need to revisit
the PlanForeignScan API definition some more, too.  ...
So we need to break down what PlanForeignScan currently does into three
separate steps.  The first idea that comes to mind is to call them
GetForeignRelSize, GetForeignPaths, GetForeignPlan; but maybe somebody
has a better idea for names?

Attached is a draft patch for that.

1. FilefdwPlanState.pages and FileFdwPlanState.ntuples seems redundant. Why not use RelOptInfo.pages and RelOptInfo.tuples?

2. IMHO RelOptInfo.fdw_private seems confusing. How about renaming it to e.g., RelOptInfo.fdw_state?

Attached is a patch for the draft patch.

Best regards,
Etsuro Fujita
*** a/contrib/file_fdw/file_fdw.c
--- b/contrib/file_fdw/file_fdw.c
***************
*** 74,87 **** static const struct FileFdwOption valid_options[] = {
  };
  
  /*
!  * FDW-specific information for RelOptInfo.fdw_private.
   */
  typedef struct FileFdwPlanState
  {
        char       *filename;           /* file to read */
        List       *options;            /* merged COPY options, excluding 
filename */
-       BlockNumber pages;                      /* estimate of file's physical 
size */
-       double          ntuples;                /* estimate of number of rows 
in file */
  } FileFdwPlanState;
  
  /*
--- 74,85 ----
  };
  
  /*
!  * FDW-specific information for RelOptInfo.fdw_state.
   */
  typedef struct FileFdwPlanState
  {
        char       *filename;           /* file to read */
        List       *options;            /* merged COPY options, excluding 
filename */
  } FileFdwPlanState;
  
  /*
***************
*** 132,140 **** static void fileGetOptions(Oid foreigntableid,
                           char **filename, List **other_options);
  static List *get_file_fdw_attribute_options(Oid relid);
  static void estimate_size(PlannerInfo *root, RelOptInfo *baserel,
!                         FileFdwPlanState *fdw_private);
  static void estimate_costs(PlannerInfo *root, RelOptInfo *baserel,
-                          FileFdwPlanState *fdw_private,
                           Cost *startup_cost, Cost *total_cost);
  
  
--- 130,137 ----
                           char **filename, List **other_options);
  static List *get_file_fdw_attribute_options(Oid relid);
  static void estimate_size(PlannerInfo *root, RelOptInfo *baserel,
!                         FileFdwPlanState *fpstate);
  static void estimate_costs(PlannerInfo *root, RelOptInfo *baserel,
                           Cost *startup_cost, Cost *total_cost);
  
  
***************
*** 415,433 **** fileGetForeignRelSize(PlannerInfo *root,
                                          RelOptInfo *baserel,
                                          Oid foreigntableid)
  {
!       FileFdwPlanState *fdw_private;
  
        /*
         * Fetch options.  We only need filename at this point, but we might
         * as well get everything and not need to re-fetch it later in planning.
         */
!       fdw_private = (FileFdwPlanState *) palloc(sizeof(FileFdwPlanState));
!       fileGetOptions(foreigntableid,
!                                  &fdw_private->filename, 
&fdw_private->options);
!       baserel->fdw_private = (void *) fdw_private;
  
        /* Estimate relation size */
!       estimate_size(root, baserel, fdw_private);
  }
  
  /*
--- 412,429 ----
                                          RelOptInfo *baserel,
                                          Oid foreigntableid)
  {
!       FileFdwPlanState *fpstate;
  
        /*
         * Fetch options.  We only need filename at this point, but we might
         * as well get everything and not need to re-fetch it later in planning.
         */
!       fpstate = (FileFdwPlanState *) palloc(sizeof(FileFdwPlanState));
!       fileGetOptions(foreigntableid, &fpstate->filename, &fpstate->options);
!       baserel->fdw_state = (void *) fpstate;
  
        /* Estimate relation size */
!       estimate_size(root, baserel, fpstate);
  }
  
  /*
***************
*** 443,455 **** fileGetForeignPaths(PlannerInfo *root,
                                        RelOptInfo *baserel,
                                        Oid foreigntableid)
  {
-       FileFdwPlanState *fdw_private = (FileFdwPlanState *) 
baserel->fdw_private;
        Cost            startup_cost;
        Cost            total_cost;
  
        /* Estimate costs */
!       estimate_costs(root, baserel, fdw_private,
!                                  &startup_cost, &total_cost);
  
        /* Create a ForeignPath node and add it as only possible path */
        add_path(baserel, (Path *)
--- 439,449 ----
                                        RelOptInfo *baserel,
                                        Oid foreigntableid)
  {
        Cost            startup_cost;
        Cost            total_cost;
  
        /* Estimate costs */
!       estimate_costs(root, baserel, &startup_cost, &total_cost);
  
        /* Create a ForeignPath node and add it as only possible path */
        add_path(baserel, (Path *)
***************
*** 647,659 **** fileReScanForeignScan(ForeignScanState *node)
  /*
   * Estimate size of a foreign table.
   *
!  * The main result is returned in baserel->rows.  We also set
!  * fdw_private->pages and fdw_private->ntuples for later use in the cost
!  * calculation.
   */
  static void
  estimate_size(PlannerInfo *root, RelOptInfo *baserel,
!                         FileFdwPlanState *fdw_private)
  {
        struct stat stat_buf;
        BlockNumber pages;
--- 641,652 ----
  /*
   * Estimate size of a foreign table.
   *
!  * The main result is returned in baserel->rows.  We also set baserel->pages
!  * and baserel->tuples for later use in the cost calculation.
   */
  static void
  estimate_size(PlannerInfo *root, RelOptInfo *baserel,
!                         FileFdwPlanState *fpstate)
  {
        struct stat stat_buf;
        BlockNumber pages;
***************
*** 665,671 **** estimate_size(PlannerInfo *root, RelOptInfo *baserel,
         * Get size of the file.  It might not be there at plan time, though, in
         * which case we have to use a default estimate.
         */
!       if (stat(fdw_private->filename, &stat_buf) < 0)
                stat_buf.st_size = 10 * BLCKSZ;
  
        /*
--- 658,664 ----
         * Get size of the file.  It might not be there at plan time, though, in
         * which case we have to use a default estimate.
         */
!       if (stat(fpstate->filename, &stat_buf) < 0)
                stat_buf.st_size = 10 * BLCKSZ;
  
        /*
***************
*** 675,681 **** estimate_size(PlannerInfo *root, RelOptInfo *baserel,
        if (pages < 1)
                pages = 1;
  
!       fdw_private->pages = pages;
  
        /*
         * Estimate the number of tuples in the file.  We back into this 
estimate
--- 668,674 ----
        if (pages < 1)
                pages = 1;
  
!       baserel->pages = pages;
  
        /*
         * Estimate the number of tuples in the file.  We back into this 
estimate
***************
*** 688,694 **** estimate_size(PlannerInfo *root, RelOptInfo *baserel,
  
        ntuples = clamp_row_est((double) stat_buf.st_size / (double) 
tuple_width);
  
!       fdw_private->ntuples = ntuples;
  
        /*
         * Now estimate the number of rows returned by the scan after applying 
the
--- 681,687 ----
  
        ntuples = clamp_row_est((double) stat_buf.st_size / (double) 
tuple_width);
  
!       baserel->tuples = ntuples;
  
        /*
         * Now estimate the number of rows returned by the scan after applying 
the
***************
*** 715,725 **** estimate_size(PlannerInfo *root, RelOptInfo *baserel,
   */
  static void
  estimate_costs(PlannerInfo *root, RelOptInfo *baserel,
-                          FileFdwPlanState *fdw_private,
                           Cost *startup_cost, Cost *total_cost)
  {
!       BlockNumber pages = fdw_private->pages;
!       double          ntuples = fdw_private->ntuples;
        Cost            run_cost = 0;
        Cost            cpu_per_tuple;
  
--- 708,717 ----
   */
  static void
  estimate_costs(PlannerInfo *root, RelOptInfo *baserel,
                           Cost *startup_cost, Cost *total_cost)
  {
!       BlockNumber pages = baserel->pages;
!       double          ntuples = baserel->tuples;
        Cost            run_cost = 0;
        Cost            cpu_per_tuple;
  
*** a/doc/src/sgml/fdwhandler.sgml
--- b/doc/src/sgml/fdwhandler.sgml
***************
*** 126,132 **** GetForeignRelSize (PlannerInfo *root,
      </para>
  
      <para>
!      <literal>baserel-&gt;fdw_private</> is a <type>void</> pointer that is
       available for use by FDW planning functions.  It can be used to pass
       information forward from <function>GetForeignRelSize</> to
       <function>GetForeignPaths</> and/or <function>GetForeignPaths</> to
--- 126,132 ----
      </para>
  
      <para>
!      <literal>baserel-&gt;fdw_state</> is a <type>void</> pointer that is
       available for use by FDW planning functions.  It can be used to pass
       information forward from <function>GetForeignRelSize</> to
       <function>GetForeignPaths</> and/or <function>GetForeignPaths</> to
*** a/src/backend/optimizer/util/relnode.c
--- b/src/backend/optimizer/util/relnode.c
***************
*** 114,120 **** build_simple_rel(PlannerInfo *root, int relid, RelOptKind 
reloptkind)
        rel->subplan = NULL;
        rel->subroot = NULL;
        rel->fdwroutine = NULL;
!       rel->fdw_private = NULL;
        rel->baserestrictinfo = NIL;
        rel->baserestrictcost.startup = 0;
        rel->baserestrictcost.per_tuple = 0;
--- 114,120 ----
        rel->subplan = NULL;
        rel->subroot = NULL;
        rel->fdwroutine = NULL;
!       rel->fdw_state = NULL;
        rel->baserestrictinfo = NIL;
        rel->baserestrictcost.startup = 0;
        rel->baserestrictcost.per_tuple = 0;
***************
*** 369,375 **** build_join_rel(PlannerInfo *root,
        joinrel->subplan = NULL;
        joinrel->subroot = NULL;
        joinrel->fdwroutine = NULL;
!       joinrel->fdw_private = NULL;
        joinrel->baserestrictinfo = NIL;
        joinrel->baserestrictcost.startup = 0;
        joinrel->baserestrictcost.per_tuple = 0;
--- 369,375 ----
        joinrel->subplan = NULL;
        joinrel->subroot = NULL;
        joinrel->fdwroutine = NULL;
!       joinrel->fdw_state = NULL;
        joinrel->baserestrictinfo = NIL;
        joinrel->baserestrictcost.startup = 0;
        joinrel->baserestrictcost.per_tuple = 0;
*** a/src/include/nodes/relation.h
--- b/src/include/nodes/relation.h
***************
*** 422,428 **** typedef struct RelOptInfo
        PlannerInfo *subroot;           /* if subquery */
        /* use "struct FdwRoutine" to avoid including fdwapi.h here */
        struct FdwRoutine *fdwroutine;  /* if foreign table */
!       void       *fdw_private;        /* if foreign table */
  
        /* used by various scans and joins: */
        List       *baserestrictinfo;           /* RestrictInfo structures (if 
base
--- 422,428 ----
        PlannerInfo *subroot;           /* if subquery */
        /* use "struct FdwRoutine" to avoid including fdwapi.h here */
        struct FdwRoutine *fdwroutine;  /* if foreign table */
!       void       *fdw_state;          /* if foreign table */
  
        /* used by various scans and joins: */
        List       *baserestrictinfo;           /* RestrictInfo structures (if 
base
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to