diff options
Diffstat (limited to 'src/backend')
| -rw-r--r-- | src/backend/nodes/copyfuncs.c | 21 | ||||
| -rw-r--r-- | src/backend/nodes/outfuncs.c | 16 | ||||
| -rw-r--r-- | src/backend/optimizer/plan/createplan.c | 49 | ||||
| -rw-r--r-- | src/backend/optimizer/plan/setrefs.c | 27 | ||||
| -rw-r--r-- | src/backend/optimizer/plan/subselect.c | 21 | ||||
| -rw-r--r-- | src/backend/utils/adt/ruleutils.c | 70 |
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; |
