diff options
| author | Robert Haas <rhaas@postgresql.org> | 2015-05-01 08:50:35 -0400 |
|---|---|---|
| committer | Robert Haas <rhaas@postgresql.org> | 2015-05-01 08:50:35 -0400 |
| commit | e7cb7ee14555cc9c5773e2c102efd6371f6f2005 (patch) | |
| tree | fc1d7ab49a9f9eee6027a6ace17c37963e514cc9 /src/include | |
| parent | 2b22795b32576fa7173b501b646581a17de35902 (diff) | |
| download | postgresql-e7cb7ee14555cc9c5773e2c102efd6371f6f2005.tar.gz | |
Allow FDWs and custom scan providers to replace joins with scans.
Foreign data wrappers can use this capability for so-called "join
pushdown"; that is, instead of executing two separate foreign scans
and then joining the results locally, they can generate a path which
performs the join on the remote server and then is scanned locally.
This commit does not extend postgres_fdw to take advantage of this
capability; it just provides the infrastructure.
Custom scan providers can use this in a similar way. Previously,
it was only possible for a custom scan provider to scan a single
relation. Now, it can scan an entire join tree, provided of course
that it knows how to produce the same results that the join would
have produced if executed normally.
KaiGai Kohei, reviewed by Shigeru Hanada, Ashutosh Bapat, and me.
Diffstat (limited to 'src/include')
| -rw-r--r-- | src/include/foreign/fdwapi.h | 15 | ||||
| -rw-r--r-- | src/include/nodes/plannodes.h | 20 | ||||
| -rw-r--r-- | src/include/nodes/relation.h | 2 | ||||
| -rw-r--r-- | src/include/optimizer/paths.h | 13 | ||||
| -rw-r--r-- | src/include/optimizer/planmain.h | 1 |
5 files changed, 46 insertions, 5 deletions
diff --git a/src/include/foreign/fdwapi.h b/src/include/foreign/fdwapi.h index 1d768412af..c683d9259e 100644 --- a/src/include/foreign/fdwapi.h +++ b/src/include/foreign/fdwapi.h @@ -82,6 +82,17 @@ typedef void (*EndForeignModify_function) (EState *estate, typedef int (*IsForeignRelUpdatable_function) (Relation rel); +typedef void (*GetForeignJoinPaths_function) (PlannerInfo *root, + RelOptInfo *joinrel, + RelOptInfo *outerrel, + RelOptInfo *innerrel, + List *restrictlist, + JoinType jointype, + SpecialJoinInfo *sjinfo, + SemiAntiJoinFactors *semifactors, + Relids param_source_rels, + Relids extra_lateral_rels); + typedef void (*ExplainForeignScan_function) (ForeignScanState *node, struct ExplainState *es); @@ -150,10 +161,14 @@ typedef struct FdwRoutine /* Support functions for IMPORT FOREIGN SCHEMA */ ImportForeignSchema_function ImportForeignSchema; + + /* Support functions for join push-down */ + GetForeignJoinPaths_function GetForeignJoinPaths; } FdwRoutine; /* Functions in foreign/foreign.c */ +extern Oid GetFdwHandlerByRelId(Oid relid); extern FdwRoutine *GetFdwRoutine(Oid fdwhandler); extern FdwRoutine *GetFdwRoutineByRelId(Oid relid); extern FdwRoutine *GetFdwRoutineForRelation(Relation relation, bool makecopy); diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 21cbfa8cf0..baeba2d330 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -471,7 +471,11 @@ typedef struct WorkTableScan * fdw_exprs and fdw_private are both under the control of the foreign-data * wrapper, but fdw_exprs is presumed to contain expression trees and will * be post-processed accordingly by the planner; fdw_private won't be. - * Note that everything in both lists must be copiable by copyObject(). + * An optional fdw_ps_tlist is used to map a reference to an attribute of + * underlying relation(s) onto a pair of INDEX_VAR and alternative varattno. + * When fdw_ps_tlist is used, this represents a remote join, and the FDW + * is responsible for setting this field to an appropriate value. + * Note that everything in above lists must be copiable by copyObject(). * One way to store an arbitrary blob of bytes is to represent it as a bytea * Const. Usually, though, you'll be better off choosing a representation * that can be dumped usefully by nodeToString(). @@ -480,18 +484,22 @@ typedef struct WorkTableScan typedef struct ForeignScan { Scan scan; + Oid fdw_handler; /* OID of FDW handler */ List *fdw_exprs; /* expressions that FDW may evaluate */ + List *fdw_ps_tlist; /* tlist, if replacing a join */ List *fdw_private; /* private data for FDW */ + Bitmapset *fdw_relids; /* RTIs generated by this scan */ bool fsSystemCol; /* true if any "system column" is needed */ } ForeignScan; /* ---------------- * CustomScan node * - * The comments for ForeignScan's fdw_exprs and fdw_private fields apply - * equally to custom_exprs and custom_private. Note that since Plan trees - * can be copied, custom scan providers *must* fit all plan data they need - * into those fields; embedding CustomScan in a larger struct will not work. + * The comments for ForeignScan's fdw_exprs, fdw_varmap and fdw_private fields + * apply equally to custom_exprs, custom_ps_tlist and custom_private. + * Note that since Plan trees can be copied, custom scan providers *must* + * fit all plan data they need into those fields; embedding CustomScan in + * a larger struct will not work. * ---------------- */ struct CustomScan; @@ -512,7 +520,9 @@ typedef struct CustomScan Scan scan; uint32 flags; /* mask of CUSTOMPATH_* flags, see relation.h */ List *custom_exprs; /* expressions that custom code may evaluate */ + List *custom_ps_tlist;/* tlist, if replacing a join */ List *custom_private; /* private data for custom code */ + Bitmapset *custom_relids; /* RTIs generated by this scan */ const CustomScanMethods *methods; } CustomScan; diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index 401a686664..1713d298de 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -366,6 +366,7 @@ typedef struct PlannerInfo * subroot - PlannerInfo for subquery (NULL if it's not a subquery) * subplan_params - list of PlannerParamItems to be passed to subquery * fdwroutine - function hooks for FDW, if foreign table (else NULL) + * fdw_handler - OID of FDW handler, if foreign table (else InvalidOid) * fdw_private - private state for FDW, if foreign table (else NULL) * * Note: for a subquery, tuples, subplan, subroot are not set immediately @@ -461,6 +462,7 @@ typedef struct RelOptInfo List *subplan_params; /* if subquery */ /* use "struct FdwRoutine" to avoid including fdwapi.h here */ struct FdwRoutine *fdwroutine; /* if foreign table */ + Oid fdw_handler; /* if foreign table */ void *fdw_private; /* if foreign table */ /* used by various scans and joins: */ diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h index 6cad92e443..c42c69d746 100644 --- a/src/include/optimizer/paths.h +++ b/src/include/optimizer/paths.h @@ -30,6 +30,19 @@ typedef void (*set_rel_pathlist_hook_type) (PlannerInfo *root, RangeTblEntry *rte); extern PGDLLIMPORT set_rel_pathlist_hook_type set_rel_pathlist_hook; +/* Hook for plugins to get control in add_paths_to_joinrel() */ +typedef void (*set_join_pathlist_hook_type) (PlannerInfo *root, + RelOptInfo *joinrel, + RelOptInfo *outerrel, + RelOptInfo *innerrel, + List *restrictlist, + JoinType jointype, + SpecialJoinInfo *sjinfo, + SemiAntiJoinFactors *semifactors, + Relids param_source_rels, + Relids extra_lateral_rels); +extern PGDLLIMPORT set_join_pathlist_hook_type set_join_pathlist_hook; + /* Hook for plugins to replace standard_join_search() */ typedef RelOptInfo *(*join_search_hook_type) (PlannerInfo *root, int levels_needed, diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h index fa72918d1b..0c8cbcded9 100644 --- a/src/include/optimizer/planmain.h +++ b/src/include/optimizer/planmain.h @@ -41,6 +41,7 @@ extern Plan *optimize_minmax_aggregates(PlannerInfo *root, List *tlist, * prototypes for plan/createplan.c */ extern Plan *create_plan(PlannerInfo *root, Path *best_path); +extern Plan *create_plan_recurse(PlannerInfo *root, Path *best_path); extern SubqueryScan *make_subqueryscan(List *qptlist, List *qpqual, Index scanrelid, Plan *subplan); extern ForeignScan *make_foreignscan(List *qptlist, List *qpqual, |
