summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/optimizer/plan/createplan.c2
-rw-r--r--src/backend/pgxc/plan/planner.c2
-rw-r--r--src/backend/pgxc/pool/postgresql_fdw.c2
-rw-r--r--src/backend/utils/adt/ruleutils.c104
-rw-r--r--src/include/utils/builtins.h4
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);