diff options
| -rw-r--r-- | src/backend/optimizer/plan/createplan.c | 2 | ||||
| -rw-r--r-- | src/backend/pgxc/plan/planner.c | 2 | ||||
| -rw-r--r-- | src/backend/pgxc/pool/postgresql_fdw.c | 2 | ||||
| -rw-r--r-- | src/backend/utils/adt/ruleutils.c | 104 | ||||
| -rw-r--r-- | src/include/utils/builtins.h | 4 |
5 files changed, 111 insertions, 3 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 04b07457a0..3abcd6cfe5 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -1266,7 +1266,7 @@ create_remote_expr(PlannerInfo *root, Plan *parent, StringInfo expr, bms_free(tmprelids); /* Set up deparsing context */ - context = deparse_context_for_planstate((Node *) parent, + context = deparse_context_for_plan((Node *) parent, NULL, root->parse->rtable); diff --git a/src/backend/pgxc/plan/planner.c b/src/backend/pgxc/plan/planner.c index 9971d4a94b..28521cb8e6 100644 --- a/src/backend/pgxc/plan/planner.c +++ b/src/backend/pgxc/plan/planner.c @@ -2213,7 +2213,7 @@ reconstruct_step_query(List *rtable, bool has_order_by, List *extra_sort, char *sql_from; int count_from = 1; - context = deparse_context_for_planstate((Node *) step, NULL, rtable); + context = deparse_context_for_plan((Node *) step, NULL, rtable); useprefix = list_length(rtable) > 1; foreach(l, sub_tlist) diff --git a/src/backend/pgxc/pool/postgresql_fdw.c b/src/backend/pgxc/pool/postgresql_fdw.c index b63690e4e4..dc302a3232 100644 --- a/src/backend/pgxc/pool/postgresql_fdw.c +++ b/src/backend/pgxc/pool/postgresql_fdw.c @@ -248,7 +248,7 @@ elog(DEBUG2, "%s(%u) called", __FUNCTION__, __LINE__); /* prepare to deparse plan */ initStringInfo(&sql); - context = deparse_context_for_planstate((Node *)scan, NULL, + context = deparse_context_for_plan((Node *)scan, NULL, estate->es_range_table); /* diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index bc41c14c31..b581474ae8 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -36,6 +36,9 @@ #include "commands/tablespace.h" #include "executor/spi.h" #include "funcapi.h" +#ifdef PGXC +#include "nodes/execnodes.h" +#endif #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" #include "optimizer/clauses.h" @@ -171,6 +174,9 @@ static int print_function_arguments(StringInfo buf, HeapTuple proctup, bool print_table_args, bool print_defaults); static void print_function_rettype(StringInfo buf, HeapTuple proctup); static void set_deparse_planstate(deparse_namespace *dpns, PlanState *ps); +#ifdef PGXC +static void set_deparse_plan(deparse_namespace *dpns, Plan *plan); +#endif static void push_child_plan(deparse_namespace *dpns, PlanState *ps, deparse_namespace *save_dpns); static void pop_child_plan(deparse_namespace *dpns, @@ -2289,6 +2295,104 @@ set_deparse_planstate(deparse_namespace *dpns, PlanState *ps) dpns->inner_plan = NULL; } +#ifdef PGXC +/* + * This is a special case deparse context to be used at the planning time to + * generate query strings and expressions for remote shipping. + * + * XXX We should be careful while using this since the support is quite + * limited. The only supported use case at this point is for remote join + * reduction and some simple plan trees rooted by Agg node having a single + * RemoteQuery node as leftree. + */ +List * +deparse_context_for_plan(Node *plan, List *ancestors, + List *rtable) +{ + deparse_namespace *dpns; + + dpns = (deparse_namespace *) palloc0(sizeof(deparse_namespace)); + + /* Initialize fields that stay the same across the whole plan tree */ + dpns->rtable = rtable; + dpns->ctes = NIL; +#ifdef PGXC + dpns->remotequery = false; +#endif + + /* Set our attention on the specific plan node passed in */ + set_deparse_plan(dpns, (Plan *) plan); + dpns->ancestors = ancestors; + + /* Return a one-deep namespace stack */ + return list_make1(dpns); +} + +/* + * Set deparse context for Plan. Only those plan nodes which are immediate (or + * through simple nodes) parents of RemoteQuery nodes are supported right now. + * + * This is a kind of work-around since the new deparse interface (since 9.1) + * expects a PlanState node. But planstates are instantiated only at execution + * time when InitPlan is called. But we are required to deparse the query + * during planning time, so we hand-cook these dummy PlanState nodes instead of + * init-ing the plan. Another approach could have been to delay the query + * generation to the execution time, but we are not yet sure if this can be + * safely done, especially for remote join reduction. + */ +static void +set_deparse_plan(deparse_namespace *dpns, Plan *plan) +{ + + if (IsA(plan, NestLoop)) + { + NestLoop *nestloop = (NestLoop *) plan; + + dpns->planstate = (PlanState *) makeNode(NestLoopState); + dpns->planstate->plan = plan; + + dpns->outer_planstate = (PlanState *) makeNode(PlanState); + dpns->outer_plan = dpns->outer_planstate->plan = nestloop->join.plan.lefttree; + + dpns->inner_planstate = (PlanState *) makeNode(PlanState); + dpns->inner_plan = dpns->inner_planstate->plan = nestloop->join.plan.righttree; + } + else if (IsA(plan, RemoteQuery)) + { + dpns->planstate = (PlanState *) makeNode(PlanState); + dpns->planstate->plan = plan; + } + else if (IsA(plan, Agg) || IsA(plan, Group)) + { + /* + * We expect plan tree as Group/Agg->Sort->Result->Material->RemoteQuery, + * Result, Material nodes are optional. Sort is compulsory for Group but not + * for Agg. + * anything else is not handled right now. + */ + Plan *temp_plan = plan->lefttree; + Plan *remote_scan = NULL; + + if (temp_plan && IsA(temp_plan, Sort)) + temp_plan = temp_plan->lefttree; + if (temp_plan && IsA(temp_plan, Result)) + temp_plan = temp_plan->lefttree; + if (temp_plan && IsA(temp_plan, Material)) + temp_plan = temp_plan->lefttree; + if (temp_plan && IsA(temp_plan, RemoteQuery)) + remote_scan = temp_plan; + + if (!remote_scan) + elog(ERROR, "Deparse of this query at planning is not supported yet"); + + dpns->planstate = (PlanState *) makeNode(PlanState); + dpns->planstate->plan = plan; + } + else + elog(ERROR, "Deparse of this query at planning not supported yet"); +} + +#endif /* * push_child_plan: temporarily transfer deparsing attention to a child plan * diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 0926c34d3d..b11db63ace 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -640,6 +640,10 @@ extern void deparse_query(Query *query, StringInfo buf, List *parentnamespace); extern List *deparse_context_for(const char *aliasname, Oid relid); extern List *deparse_context_for_planstate(Node *planstate, List *ancestors, List *rtable); +#ifdef PGXC +extern List *deparse_context_for_plan(Node *plan, List *ancestors, + List *rtable); +#endif extern const char *quote_identifier(const char *ident); extern char *quote_qualified_identifier(const char *qualifier, const char *ident); |
