summaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/nodes/copyfuncs.c21
-rw-r--r--src/backend/nodes/outfuncs.c16
-rw-r--r--src/backend/optimizer/plan/createplan.c49
-rw-r--r--src/backend/optimizer/plan/setrefs.c27
-rw-r--r--src/backend/optimizer/plan/subselect.c21
-rw-r--r--src/backend/utils/adt/ruleutils.c70
6 files changed, 70 insertions, 134 deletions
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index e76b5b3f633..6b1bf7be19d 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -603,17 +603,24 @@ _copyForeignScan(const ForeignScan *from)
static CustomScan *
_copyCustomScan(const CustomScan *from)
{
- CustomScan *newnode;
-
- newnode = from->methods->CopyCustomScan(from);
- Assert(nodeTag(newnode) == nodeTag(from));
+ CustomScan *newnode = makeNode(CustomScan);
+ /*
+ * copy node superclass fields
+ */
CopyScanFields((const Scan *) from, (Scan *) newnode);
+
+ /*
+ * copy remainder of node
+ */
COPY_SCALAR_FIELD(flags);
+ COPY_NODE_FIELD(custom_exprs);
+ COPY_NODE_FIELD(custom_private);
+
/*
- * NOTE: The method field of CustomScan is required to be a pointer
- * to a static table of callback functions. So, we don't copy the
- * table itself, just reference the original one.
+ * NOTE: The method field of CustomScan is required to be a pointer to a
+ * static table of callback functions. So we don't copy the table itself,
+ * just reference the original one.
*/
COPY_SCALAR_FIELD(methods);
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index cdf1e7ece1f..ca9bd4f7c7f 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -569,10 +569,14 @@ _outCustomScan(StringInfo str, const CustomScan *node)
WRITE_NODE_TYPE("CUSTOMSCAN");
_outScanInfo(str, (const Scan *) node);
+
WRITE_UINT_FIELD(flags);
- appendStringInfo(str, " :methods");
+ WRITE_NODE_FIELD(custom_exprs);
+ WRITE_NODE_FIELD(custom_private);
+ appendStringInfoString(str, " :methods ");
_outToken(str, node->methods->CustomName);
- node->methods->TextOutCustomScan(str, node);
+ if (node->methods->TextOutCustomScan)
+ node->methods->TextOutCustomScan(str, node);
}
static void
@@ -1600,11 +1604,15 @@ static void
_outCustomPath(StringInfo str, const CustomPath *node)
{
WRITE_NODE_TYPE("CUSTOMPATH");
+
_outPathInfo(str, (const Path *) node);
+
WRITE_UINT_FIELD(flags);
- appendStringInfo(str, " :methods");
+ WRITE_NODE_FIELD(custom_private);
+ appendStringInfoString(str, " :methods ");
_outToken(str, node->methods->CustomName);
- node->methods->TextOutCustomPath(str, node);
+ if (node->methods->TextOutCustomPath)
+ node->methods->TextOutCustomPath(str, node);
}
static void
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index e6bd4c326ca..fa478025c1a 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -77,7 +77,7 @@ static WorkTableScan *create_worktablescan_plan(PlannerInfo *root, Path *best_pa
List *tlist, List *scan_clauses);
static ForeignScan *create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path,
List *tlist, List *scan_clauses);
-static Plan *create_customscan_plan(PlannerInfo *root,
+static CustomScan *create_customscan_plan(PlannerInfo *root,
CustomPath *best_path,
List *tlist, List *scan_clauses);
static NestLoop *create_nestloop_plan(PlannerInfo *root, NestPath *best_path,
@@ -86,6 +86,7 @@ static MergeJoin *create_mergejoin_plan(PlannerInfo *root, MergePath *best_path,
Plan *outer_plan, Plan *inner_plan);
static HashJoin *create_hashjoin_plan(PlannerInfo *root, HashPath *best_path,
Plan *outer_plan, Plan *inner_plan);
+static Node *replace_nestloop_params(PlannerInfo *root, Node *expr);
static Node *replace_nestloop_params_mutator(Node *node, PlannerInfo *root);
static void process_subquery_nestloop_params(PlannerInfo *root,
List *subplan_params);
@@ -413,10 +414,10 @@ create_scan_plan(PlannerInfo *root, Path *best_path)
break;
case T_CustomScan:
- plan = create_customscan_plan(root,
- (CustomPath *) best_path,
- tlist,
- scan_clauses);
+ plan = (Plan *) create_customscan_plan(root,
+ (CustomPath *) best_path,
+ tlist,
+ scan_clauses);
break;
default:
@@ -2022,11 +2023,11 @@ create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path,
*
* Transform a CustomPath into a Plan.
*/
-static Plan *
+static CustomScan *
create_customscan_plan(PlannerInfo *root, CustomPath *best_path,
List *tlist, List *scan_clauses)
{
- Plan *plan;
+ CustomScan *cplan;
RelOptInfo *rel = best_path->path.parent;
/*
@@ -2045,23 +2046,35 @@ create_customscan_plan(PlannerInfo *root, CustomPath *best_path,
* Invoke custom plan provider to create the Plan node represented by the
* CustomPath.
*/
- plan = best_path->methods->PlanCustomPath(root, rel, best_path, tlist,
- scan_clauses);
+ cplan = (CustomScan *) best_path->methods->PlanCustomPath(root,
+ rel,
+ best_path,
+ tlist,
+ scan_clauses);
+ Assert(IsA(cplan, CustomScan));
/*
- * NOTE: unlike create_foreignscan_plan(), it is the responsibility of the
- * custom plan provider to replace outer-relation variables with nestloop
- * params, because we cannot know what expression trees may be held in
- * private fields.
+ * Copy cost data from Path to Plan; no need to make custom-plan providers
+ * do this
*/
+ copy_path_costsize(&cplan->scan.plan, &best_path->path);
/*
- * Copy cost data from Path to Plan; no need to make custom-plan providers
- * do this
+ * Replace any outer-relation variables with nestloop params in the qual
+ * and custom_exprs expressions. We do this last so that the custom-plan
+ * provider doesn't have to be involved. (Note that parts of custom_exprs
+ * could have come from join clauses, so doing this beforehand on the
+ * scan_clauses wouldn't work.)
*/
- copy_path_costsize(plan, &best_path->path);
+ if (best_path->path.param_info)
+ {
+ cplan->scan.plan.qual = (List *)
+ replace_nestloop_params(root, (Node *) cplan->scan.plan.qual);
+ cplan->custom_exprs = (List *)
+ replace_nestloop_params(root, (Node *) cplan->custom_exprs);
+ }
- return plan;
+ return cplan;
}
@@ -2598,7 +2611,7 @@ create_hashjoin_plan(PlannerInfo *root,
* root->curOuterRels are replaced by Params, and entries are added to
* root->curOuterParams if not already present.
*/
-Node *
+static Node *
replace_nestloop_params(PlannerInfo *root, Node *expr)
{
/* No setup needed for tree walk, so away we go */
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index e42972750b9..e630d0b6d81 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -94,6 +94,7 @@ static Plan *set_subqueryscan_references(PlannerInfo *root,
SubqueryScan *plan,
int rtoffset);
static bool trivial_subqueryscan(SubqueryScan *plan);
+static Node *fix_scan_expr(PlannerInfo *root, Node *node, int rtoffset);
static Node *fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context);
static bool fix_scan_expr_walker(Node *node, fix_scan_expr_context *context);
static void set_join_references(PlannerInfo *root, Join *join, int rtoffset);
@@ -580,23 +581,15 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
case T_CustomScan:
{
- CustomScan *cscan = (CustomScan *) plan;
+ CustomScan *splan = (CustomScan *) plan;
- cscan->scan.scanrelid += rtoffset;
- cscan->scan.plan.targetlist =
- fix_scan_list(root, cscan->scan.plan.targetlist, rtoffset);
- cscan->scan.plan.qual =
- fix_scan_list(root, cscan->scan.plan.qual, rtoffset);
-
- /*
- * The core implementation applies the routine to fixup varno
- * on the target-list and scan qualifier. If custom-scan has
- * additional expression nodes on its private fields, it has
- * to apply same fixup on them. Otherwise, the custom-plan
- * provider can skip this callback.
- */
- if (cscan->methods->SetCustomScanRef)
- cscan->methods->SetCustomScanRef(root, cscan, rtoffset);
+ splan->scan.scanrelid += rtoffset;
+ splan->scan.plan.targetlist =
+ fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
+ splan->scan.plan.qual =
+ fix_scan_list(root, splan->scan.plan.qual, rtoffset);
+ splan->custom_exprs =
+ fix_scan_list(root, splan->custom_exprs, rtoffset);
}
break;
@@ -1182,7 +1175,7 @@ fix_param_node(PlannerInfo *root, Param *p)
* looking up operator opcode info for OpExpr and related nodes,
* and adding OIDs from regclass Const nodes into root->glob->relationOids.
*/
-Node *
+static Node *
fix_scan_expr(PlannerInfo *root, Node *node, int rtoffset)
{
fix_scan_expr_context context;
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index 4200ec0a5a7..9111b56e92a 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -2284,24 +2284,9 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params,
break;
case T_CustomScan:
- {
- CustomScan *custom_scan = (CustomScan *) plan;
-
- context.paramids = bms_add_members(context.paramids,
- scan_params);
- /*
- * custom-scan provider is responsible to apply
- * finalize_primnode() on the expression node of
- * its private fields, but no need to apply it
- * on the tlist and qual of Plan node because it
- * is already done above.
- */
- if (custom_scan->methods->FinalizeCustomScan)
- custom_scan->methods->FinalizeCustomScan(root,
- custom_scan,
- finalize_primnode,
- (void *)&context);
- }
+ finalize_primnode((Node *) ((CustomScan *) plan)->custom_exprs,
+ &context);
+ context.paramids = bms_add_members(context.paramids, scan_params);
break;
case T_ModifyTable:
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index bf4e81f554a..24ade6cc201 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -5493,26 +5493,6 @@ get_utility_query_def(Query *query, deparse_context *context)
}
}
-/*
- * GetSpecialCustomVar
- *
- * If a custom-scan provider uses a special varnode, this function will be
- * called when deparsing; it should return an Expr node to be reversed-listed
- * in lieu of the special Var.
- */
-static Node *
-GetSpecialCustomVar(CustomScanState *css, Var *varnode, PlanState **child_ps)
-{
- Assert(IsA(css, CustomScanState));
- Assert(IS_SPECIAL_VARNO(varnode->varno));
-
- if (!css->methods->GetSpecialCustomVar)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("%s does not support special varno reference",
- css->methods->CustomName)));
- return (Node *) css->methods->GetSpecialCustomVar(css, varnode, child_ps);
-}
/*
* Display a Var appropriately.
@@ -5542,8 +5522,6 @@ get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context)
int netlevelsup;
deparse_namespace *dpns;
deparse_columns *colinfo;
- PlanState *child_ps = NULL;
- Node *expr;
char *refname;
char *attname;
@@ -5568,29 +5546,6 @@ get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context)
colinfo = deparse_columns_fetch(var->varno, dpns);
attnum = var->varattno;
}
- else if (IS_SPECIAL_VARNO(var->varno) &&
- IsA(dpns->planstate, CustomScanState) &&
- (expr = GetSpecialCustomVar((CustomScanState *) dpns->planstate,
- var, &child_ps)) != NULL)
- {
- deparse_namespace save_dpns;
-
- if (child_ps)
- push_child_plan(dpns, child_ps, &save_dpns);
- /*
- * Force parentheses because our caller probably assumed a Var is a
- * simple expression.
- */
- if (!IsA(expr, Var))
- appendStringInfoChar(buf, '(');
- get_rule_expr((Node *) expr, context, true);
- if (!IsA(expr, Var))
- appendStringInfoChar(buf, ')');
-
- if (child_ps)
- pop_child_plan(dpns, &save_dpns);
- return NULL;
- }
else if (var->varno == OUTER_VAR && dpns->outer_tlist)
{
TargetEntry *tle;
@@ -5805,7 +5760,6 @@ get_name_for_var_field(Var *var, int fieldno,
AttrNumber attnum;
int netlevelsup;
deparse_namespace *dpns;
- PlanState *child_ps = NULL;
TupleDesc tupleDesc;
Node *expr;
@@ -5880,30 +5834,6 @@ get_name_for_var_field(Var *var, int fieldno,
rte = rt_fetch(var->varno, dpns->rtable);
attnum = var->varattno;
}
- else if (IS_SPECIAL_VARNO(var->varno) &&
- IsA(dpns->planstate, CustomScanState) &&
- (expr = GetSpecialCustomVar((CustomScanState *) dpns->planstate,
- var, &child_ps)) != NULL)
- {
- StringInfo saved = context->buf;
- StringInfoData temp;
- deparse_namespace save_dpns;
-
- initStringInfo(&temp);
- context->buf = &temp;
-
- if (child_ps)
- push_child_plan(dpns, child_ps, &save_dpns);
- if (!IsA(expr, Var))
- appendStringInfoChar(context->buf, '(');
- get_rule_expr((Node *) expr, context, true);
- if (!IsA(expr, Var))
- appendStringInfoChar(context->buf, ')');
- if (child_ps)
- pop_child_plan(dpns, &save_dpns);
- context->buf = saved;
- return temp.data;
- }
else if (var->varno == OUTER_VAR && dpns->outer_tlist)
{
TargetEntry *tle;