diff --git a/src/backend/distributed/deparser/ruleutils_13.c b/src/backend/distributed/deparser/ruleutils_13.c index 3ca2da67b..18ef36b84 100644 --- a/src/backend/distributed/deparser/ruleutils_13.c +++ b/src/backend/distributed/deparser/ruleutils_13.c @@ -132,7 +132,8 @@ typedef struct int64 shardid; /* a distributed table's shardid, if positive */ ParseExprKind special_exprkind; /* set only for exprkinds needing special * handling */ - Bitmapset *appendparents; + Bitmapset *appendparents; /* if not null, map child Vars of these relids + * back to the parent rel */ } deparse_context; /* @@ -167,20 +168,26 @@ typedef struct List *rtable; /* List of RangeTblEntry nodes */ List *rtable_names; /* Parallel list of names for RTEs */ List *rtable_columns; /* Parallel list of deparse_columns structs */ + List *subplans; /* List of Plan trees for SubPlans */ List *ctes; /* List of CommonTableExpr nodes */ + AppendRelInfo **appendrels; /* Array of AppendRelInfo nodes, or NULL */ /* Workspace for column alias assignment: */ bool unique_using; /* Are we making USING names globally unique */ List *using_names; /* List of assigned names for USING columns */ /* Remaining fields are used only when deparsing a Plan tree: */ - PlanState *planstate; /* immediate parent of current expression */ + Plan *plan; /* immediate parent of current expression */ List *ancestors; /* ancestors of planstate */ - PlanState *outer_planstate; /* outer subplan state, or NULL if none */ - PlanState *inner_planstate; /* inner subplan state, or NULL if none */ + Plan *outer_plan; /* outer subnode, or NULL if none */ + Plan *inner_plan; /* inner subnode, or NULL if none */ List *outer_tlist; /* referent for OUTER_VAR Vars */ List *inner_tlist; /* referent for INNER_VAR Vars */ List *index_tlist; /* referent for INDEX_VAR Vars */ } deparse_namespace; +/* Callback signature for resolve_special_varno() */ +typedef void (*rsv_callback) (Node *node, deparse_context *context, + void *callback_arg); + /* * Per-relation data about column alias names. * @@ -333,8 +340,8 @@ static void identify_join_columns(JoinExpr *j, RangeTblEntry *jrte, static void flatten_join_using_qual(Node *qual, List **leftvars, List **rightvars); static char *get_rtable_name(int rtindex, deparse_context *context); -static void set_deparse_planstate(deparse_namespace *dpns, PlanState *ps); -static void push_child_plan(deparse_namespace *dpns, PlanState *ps, +static void set_deparse_plan(deparse_namespace *dpns, Plan *plan); +static void push_child_plan(deparse_namespace *dpns, Plan *plan, deparse_namespace *save_dpns); static void pop_child_plan(deparse_namespace *dpns, deparse_namespace *save_dpns); @@ -380,10 +387,9 @@ static void get_rule_windowspec(WindowClause *wc, List *targetList, static char *get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context); static void get_special_variable(Node *node, deparse_context *context, - void *private); + void *callback_arg); static void resolve_special_varno(Node *node, deparse_context *context, - void *private, - void (*callback) (Node *, deparse_context *, void *)); + rsv_callback callback, void *callback_arg); static Node *find_param_referent(Param *param, deparse_context *context, deparse_namespace **dpns_p, ListCell **ancestor_cell_p); static void get_parameter(Param *param, deparse_context *context); @@ -405,7 +411,7 @@ static void get_func_expr(FuncExpr *expr, deparse_context *context, static void get_agg_expr(Aggref *aggref, deparse_context *context, Aggref *original_aggref); static void get_agg_combine_expr(Node *node, deparse_context *context, - void *private); + void *callback_arg); static void get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context); static void get_coercion_expr(Node *arg, deparse_context *context, Oid resulttype, int32 resulttypmod, @@ -672,7 +678,9 @@ set_deparse_for_query(deparse_namespace *dpns, Query *query, /* Initialize *dpns and fill rtable/ctes links */ memset(dpns, 0, sizeof(deparse_namespace)); dpns->rtable = query->rtable; + dpns->subplans = NIL; dpns->ctes = query->cteList; + dpns->appendrels = NULL; /* Assign a unique relation alias to each RTE */ set_rtable_names(dpns, parent_namespaces, NULL); @@ -1710,19 +1718,19 @@ get_rtable_name(int rtindex, deparse_context *context) } /* - * set_deparse_planstate: set up deparse_namespace to parse subexpressions - * of a given PlanState node + * set_deparse_plan: set up deparse_namespace to parse subexpressions + * of a given Plan node * - * This sets the planstate, outer_planstate, inner_planstate, outer_tlist, + * This sets the plan, outer_planstate, inner_planstate, outer_tlist, * inner_tlist, and index_tlist fields. Caller is responsible for adjusting * the ancestors list if necessary. Note that the rtable and ctes fields do * not need to change when shifting attention to different plan nodes in a * single plan tree. */ static void -set_deparse_planstate(deparse_namespace *dpns, PlanState *ps) +set_deparse_plan(deparse_namespace *dpns, Plan *plan) { - dpns->planstate = ps; + dpns->plan = plan; /* * We special-case Append and MergeAppend to pretend that the first child @@ -1732,17 +1740,17 @@ set_deparse_planstate(deparse_namespace *dpns, PlanState *ps) * first child plan is the OUTER referent; this is to support RETURNING * lists containing references to non-target relations. */ - if (IsA(ps, AppendState)) - dpns->outer_planstate = ((AppendState *) ps)->appendplans[0]; - else if (IsA(ps, MergeAppendState)) - dpns->outer_planstate = ((MergeAppendState *) ps)->mergeplans[0]; - else if (IsA(ps, ModifyTableState)) - dpns->outer_planstate = ((ModifyTableState *) ps)->mt_plans[0]; + if (IsA(plan, Append)) + dpns->outer_plan = linitial(((Append *) plan)->appendplans); + else if (IsA(plan, MergeAppend)) + dpns->outer_plan = linitial(((MergeAppend *) plan)->mergeplans); + else if (IsA(plan, ModifyTable)) + dpns->outer_plan = linitial(((ModifyTable *) plan)->plans); else - dpns->outer_planstate = outerPlanState(ps); + dpns->outer_plan = outerPlan(plan); - if (dpns->outer_planstate) - dpns->outer_tlist = dpns->outer_planstate->plan->targetlist; + if (dpns->outer_plan) + dpns->outer_tlist = dpns->outer_plan->targetlist; else dpns->outer_tlist = NIL; @@ -1755,29 +1763,30 @@ set_deparse_planstate(deparse_namespace *dpns, PlanState *ps) * to reuse OUTER, it's used for RETURNING in some modify table cases, * although not INSERT .. CONFLICT). */ - if (IsA(ps, SubqueryScanState)) - dpns->inner_planstate = ((SubqueryScanState *) ps)->subplan; - else if (IsA(ps, CteScanState)) - dpns->inner_planstate = ((CteScanState *) ps)->cteplanstate; - else if (IsA(ps, ModifyTableState)) - dpns->inner_planstate = ps; + if (IsA(plan, SubqueryScan)) + dpns->inner_plan = ((SubqueryScan *) plan)->subplan; + else if (IsA(plan, CteScan)) + dpns->inner_plan = list_nth(dpns->subplans, + ((CteScan *) plan)->ctePlanId - 1); + else if (IsA(plan, ModifyTable)) + dpns->inner_plan = plan; else - dpns->inner_planstate = innerPlanState(ps); + dpns->inner_plan = innerPlan(plan); - if (IsA(ps, ModifyTableState)) - dpns->inner_tlist = ((ModifyTableState *) ps)->mt_excludedtlist; - else if (dpns->inner_planstate) - dpns->inner_tlist = dpns->inner_planstate->plan->targetlist; + if (IsA(plan, ModifyTable)) + dpns->inner_tlist = ((ModifyTable *) plan)->exclRelTlist; + else if (dpns->inner_plan) + dpns->inner_tlist = dpns->inner_plan->targetlist; else dpns->inner_tlist = NIL; /* Set up referent for INDEX_VAR Vars, if needed */ - if (IsA(ps->plan, IndexOnlyScan)) - dpns->index_tlist = ((IndexOnlyScan *) ps->plan)->indextlist; - else if (IsA(ps->plan, ForeignScan)) - dpns->index_tlist = ((ForeignScan *) ps->plan)->fdw_scan_tlist; - else if (IsA(ps->plan, CustomScan)) - dpns->index_tlist = ((CustomScan *) ps->plan)->custom_scan_tlist; + if (IsA(plan, IndexOnlyScan)) + dpns->index_tlist = ((IndexOnlyScan *) plan)->indextlist; + else if (IsA(plan, ForeignScan)) + dpns->index_tlist = ((ForeignScan *) plan)->fdw_scan_tlist; + else if (IsA(plan, CustomScan)) + dpns->index_tlist = ((CustomScan *) plan)->custom_scan_tlist; else dpns->index_tlist = NIL; } @@ -1795,17 +1804,17 @@ set_deparse_planstate(deparse_namespace *dpns, PlanState *ps) * previous state for pop_child_plan. */ static void -push_child_plan(deparse_namespace *dpns, PlanState *ps, +push_child_plan(deparse_namespace *dpns, Plan *plan, deparse_namespace *save_dpns) { /* Save state for restoration later */ *save_dpns = *dpns; /* Link current plan node into ancestors list */ - dpns->ancestors = lcons(dpns->planstate, dpns->ancestors); + dpns->ancestors = lcons(dpns->plan, dpns->ancestors); /* Set attention on selected child */ - set_deparse_planstate(dpns, ps); + set_deparse_plan(dpns, plan); } /* @@ -1960,6 +1969,7 @@ get_query_def_extended(Query *query, StringInfo buf, List *parentnamespace, context.wrapColumn = wrapColumn; context.indentLevel = startIndent; context.special_exprkind = EXPR_KIND_NONE; + context.appendparents = NULL; context.distrelid = distrelid; context.shardid = shardid; @@ -2246,10 +2256,11 @@ get_select_query_def(Query *query, deparse_context *context, * if so, return the VALUES RTE. Otherwise return NULL. */ static RangeTblEntry * -get_simple_values_rte(Query *query) +get_simple_values_rte(Query *query, TupleDesc resultDesc) { RangeTblEntry *result = NULL; ListCell *lc; + int colno; /* * We want to return true even if the Query also contains OLD or NEW rule @@ -2286,14 +2297,24 @@ get_simple_values_rte(Query *query) if (list_length(query->targetList) != list_length(result->eref->colnames)) return NULL; /* this probably cannot happen */ + colno = 0; forboth(lc, query->targetList, lcn, result->eref->colnames) { TargetEntry *tle = (TargetEntry *) lfirst(lc); char *cname = strVal(lfirst(lcn)); + char *colname; if (tle->resjunk) return NULL; /* this probably cannot happen */ - if (tle->resname == NULL || strcmp(tle->resname, cname) != 0) + /* compute name that get_target_list would use for column */ + colno++; + if (resultDesc && colno <= resultDesc->natts) + colname = NameStr(TupleDescAttr(resultDesc, colno - 1)->attname); + else + colname = tle->resname; + + /* does it match the VALUES RTE? */ + if (colname == NULL || strcmp(colname, cname) != 0) return NULL; /* column name has been changed */ } } @@ -2321,7 +2342,7 @@ get_basic_select_query(Query *query, deparse_context *context, * VALUES part. This reverses what transformValuesClause() did at parse * time. */ - values_rte = get_simple_values_rte(query); + values_rte = get_simple_values_rte(query, resultDesc); if (values_rte) { get_values_def(values_rte->values_lists, context); @@ -3644,15 +3665,62 @@ get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context) */ if (var->varno >= 1 && var->varno <= list_length(dpns->rtable)) { - rte = rt_fetch(var->varno, dpns->rtable); - refname = (char *) list_nth(dpns->rtable_names, var->varno - 1); - colinfo = deparse_columns_fetch(var->varno, dpns); - attnum = var->varattno; + Index varno = var->varno; + AttrNumber varattno = var->varattno; + /* + * We might have been asked to map child Vars to some parent relation. + */ + if (context->appendparents && dpns->appendrels) + { + + Index pvarno = varno; + AttrNumber pvarattno = varattno; + AppendRelInfo *appinfo = dpns->appendrels[pvarno]; + bool found = false; + + /* Only map up to inheritance parents, not UNION ALL appendrels */ + while (appinfo && + rt_fetch(appinfo->parent_relid, + dpns->rtable)->rtekind == RTE_RELATION) + { + found = false; + if (pvarattno > 0) /* system columns stay as-is */ + { + if (pvarattno > appinfo->num_child_cols) + break; /* safety check */ + pvarattno = appinfo->parent_colnos[pvarattno - 1]; + if (pvarattno == 0) + break; /* Var is local to child */ + } + + pvarno = appinfo->parent_relid; + found = true; + + /* If the parent is itself a child, continue up. */ + Assert(pvarno > 0 && pvarno <= list_length(dpns->rtable)); + appinfo = dpns->appendrels[pvarno]; + } + + /* + * If we found an ancestral rel, and that rel is included in + * appendparents, print that column not the original one. + */ + if (found && bms_is_member(pvarno, context->appendparents)) + { + varno = pvarno; + varattno = pvarattno; + } + } + + rte = rt_fetch(varno, dpns->rtable); + refname = (char *) list_nth(dpns->rtable_names, varno - 1); + colinfo = deparse_columns_fetch(varno, dpns); + attnum = varattno; } else { - resolve_special_varno((Node *) var, context, NULL, - get_special_variable); + resolve_special_varno((Node *) var, context, get_special_variable, + NULL); return NULL; } @@ -3665,22 +3733,22 @@ get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context) * no alias. So in that case, drill down to the subplan and print the * contents of the referenced tlist item. This works because in a plan * tree, such Vars can only occur in a SubqueryScan or CteScan node, and - * we'll have set dpns->inner_planstate to reference the child plan node. + * we'll have set dpns->inner_plan to reference the child plan node. */ if ((rte->rtekind == RTE_SUBQUERY || rte->rtekind == RTE_CTE) && attnum > list_length(rte->eref->colnames) && - dpns->inner_planstate) + dpns->inner_plan) { TargetEntry *tle; deparse_namespace save_dpns; - tle = get_tle_by_resno(dpns->inner_tlist, var->varattno); + tle = get_tle_by_resno(dpns->inner_tlist, attnum); if (!tle) elog(ERROR, "invalid attnum %d for relation \"%s\"", - var->varattno, rte->eref->aliasname); + attnum, rte->eref->aliasname); Assert(netlevelsup == 0); - push_child_plan(dpns, dpns->inner_planstate, &save_dpns); + push_child_plan(dpns, dpns->inner_plan, &save_dpns); /* * Force parentheses because our caller probably assumed a Var is a @@ -3796,13 +3864,13 @@ get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context) * get_rule_expr. */ static void -get_special_variable(Node *node, deparse_context *context, void *private) +get_special_variable(Node *node, deparse_context *context, void *callback_arg) { StringInfo buf = context->buf; /* - * Force parentheses because our caller probably assumed a Var is a simple - * expression. + * For a non-Var referent, force parentheses because our caller probably + * assumed a Var is a simple expression. */ if (!IsA(node, Var)) appendStringInfoChar(buf, '('); @@ -3817,16 +3885,18 @@ get_special_variable(Node *node, deparse_context *context, void *private) * invoke the callback provided. */ static void -resolve_special_varno(Node *node, deparse_context *context, void *private, - void (*callback) (Node *, deparse_context *, void *)) +resolve_special_varno(Node *node, deparse_context *context, rsv_callback callback, void *callback_arg) { Var *var; deparse_namespace *dpns; + /* This function is recursive, so let's be paranoid. */ + check_stack_depth(); + /* If it's not a Var, invoke the callback. */ if (!IsA(node, Var)) { - callback(node, context, private); + (*callback) (node, context, callback_arg); return; } @@ -3842,14 +3912,30 @@ resolve_special_varno(Node *node, deparse_context *context, void *private, { TargetEntry *tle; deparse_namespace save_dpns; + Bitmapset *save_appendparents; tle = get_tle_by_resno(dpns->outer_tlist, var->varattno); if (!tle) elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno); - push_child_plan(dpns, dpns->outer_planstate, &save_dpns); - resolve_special_varno((Node *) tle->expr, context, private, callback); + /* If we're descending to the first child of an Append or MergeAppend, + * update appendparents. This will affect deparsing of all Vars + * appearing within the eventually-resolved subexpression. + */ + save_appendparents = context->appendparents; + + if (IsA(dpns->plan, Append)) + context->appendparents = bms_union(context->appendparents, + ((Append *) dpns->plan)->apprelids); + else if (IsA(dpns->plan, MergeAppend)) + context->appendparents = bms_union(context->appendparents, + ((MergeAppend *) dpns->plan)->apprelids); + + push_child_plan(dpns, dpns->outer_plan, &save_dpns); + resolve_special_varno((Node *) tle->expr, context, + callback, callback_arg); pop_child_plan(dpns, &save_dpns); + context->appendparents = save_appendparents; return; } else if (var->varno == INNER_VAR && dpns->inner_tlist) @@ -3861,8 +3947,8 @@ resolve_special_varno(Node *node, deparse_context *context, void *private, if (!tle) elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno); - push_child_plan(dpns, dpns->inner_planstate, &save_dpns); - resolve_special_varno((Node *) tle->expr, context, private, callback); + push_child_plan(dpns, dpns->inner_plan, &save_dpns); + resolve_special_varno((Node *) tle->expr, context, callback, callback_arg); pop_child_plan(dpns, &save_dpns); return; } @@ -3874,14 +3960,14 @@ resolve_special_varno(Node *node, deparse_context *context, void *private, if (!tle) elog(ERROR, "bogus varattno for INDEX_VAR var: %d", var->varattno); - resolve_special_varno((Node *) tle->expr, context, private, callback); + resolve_special_varno((Node *) tle->expr, context, callback, callback_arg); return; } else if (var->varno < 1 || var->varno > list_length(dpns->rtable)) elog(ERROR, "bogus varno: %d", var->varno); /* Not special. Just invoke the callback. */ - callback(node, context, private); + (*callback) (node, context, callback_arg); } /* @@ -3989,7 +4075,7 @@ get_name_for_var_field(Var *var, int fieldno, elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno); Assert(netlevelsup == 0); - push_child_plan(dpns, dpns->outer_planstate, &save_dpns); + push_child_plan(dpns, dpns->outer_plan, &save_dpns); result = get_name_for_var_field((Var *) tle->expr, fieldno, levelsup, context); @@ -4008,7 +4094,7 @@ get_name_for_var_field(Var *var, int fieldno, elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno); Assert(netlevelsup == 0); - push_child_plan(dpns, dpns->inner_planstate, &save_dpns); + push_child_plan(dpns, dpns->inner_plan, &save_dpns); result = get_name_for_var_field((Var *) tle->expr, fieldno, levelsup, context); @@ -4118,7 +4204,7 @@ get_name_for_var_field(Var *var, int fieldno, deparse_namespace save_dpns; const char *result; - if (!dpns->inner_planstate) + if (!dpns->inner_plan) elog(ERROR, "failed to find plan for subquery %s", rte->eref->aliasname); tle = get_tle_by_resno(dpns->inner_tlist, attnum); @@ -4126,7 +4212,7 @@ get_name_for_var_field(Var *var, int fieldno, elog(ERROR, "bogus varattno for subquery var: %d", attnum); Assert(netlevelsup == 0); - push_child_plan(dpns, dpns->inner_planstate, &save_dpns); + push_child_plan(dpns, dpns->inner_plan, &save_dpns); result = get_name_for_var_field((Var *) tle->expr, fieldno, levelsup, context); @@ -4236,7 +4322,7 @@ get_name_for_var_field(Var *var, int fieldno, deparse_namespace save_dpns; const char *result; - if (!dpns->inner_planstate) + if (!dpns->inner_plan) elog(ERROR, "failed to find plan for CTE %s", rte->eref->aliasname); tle = get_tle_by_resno(dpns->inner_tlist, attnum); @@ -4244,7 +4330,7 @@ get_name_for_var_field(Var *var, int fieldno, elog(ERROR, "bogus varattno for subquery var: %d", attnum); Assert(netlevelsup == 0); - push_child_plan(dpns, dpns->inner_planstate, &save_dpns); + push_child_plan(dpns, dpns->inner_plan, &save_dpns); result = get_name_for_var_field((Var *) tle->expr, fieldno, levelsup, context); @@ -4285,22 +4371,22 @@ find_param_referent(Param *param, deparse_context *context, /* * If it's a PARAM_EXEC parameter, look for a matching NestLoopParam or * SubPlan argument. This will necessarily be in some ancestor of the - * current expression's PlanState. + * current expression's Plan. */ if (param->paramkind == PARAM_EXEC) { deparse_namespace *dpns; - PlanState *child_ps; + Plan *child_plan; bool in_same_plan_level; ListCell *lc; dpns = (deparse_namespace *) linitial(context->namespaces); - child_ps = dpns->planstate; + child_plan = dpns->plan; in_same_plan_level = true; foreach(lc, dpns->ancestors) { - PlanState *ps = (PlanState *) lfirst(lc); + Node *ancestor = (Node *) lfirst(lc); ListCell *lc2; /* @@ -4308,11 +4394,11 @@ find_param_referent(Param *param, deparse_context *context, * we've crawled up out of a subplan, this couldn't possibly be * the right match. */ - if (IsA(ps, NestLoopState) && - child_ps == innerPlanState(ps) && + if (IsA(ancestor, NestLoop) && + child_plan == innerPlan(ancestor) && in_same_plan_level) { - NestLoop *nl = (NestLoop *) ps->plan; + NestLoop *nl = (NestLoop *) ancestor; foreach(lc2, nl->nestParams) { @@ -4331,16 +4417,12 @@ find_param_referent(Param *param, deparse_context *context, /* * Check to see if we're crawling up from a subplan. */ - foreach(lc2, ps->subPlan) + if(IsA(ancestor, SubPlan)) { - SubPlanState *sstate = (SubPlanState *) lfirst(lc2); - SubPlan *subplan = sstate->subplan; + SubPlan *subplan = (SubPlan *) ancestor; ListCell *lc3; ListCell *lc4; - if (child_ps != sstate->planstate) - continue; - /* Matched subplan, so check its arguments */ forboth(lc3, subplan->parParam, lc4, subplan->args) { @@ -4349,41 +4431,61 @@ find_param_referent(Param *param, deparse_context *context, if (paramid == param->paramid) { - /* Found a match, so return it */ - *dpns_p = dpns; - *ancestor_cell_p = lc; - return arg; + /* + * Found a match, so return it. But, since Vars in + * the arg are to be evaluated in the surrounding + * context, we have to point to the next ancestor item + * that is *not* a SubPlan. + */ + ListCell *rest; + + for_each_cell(rest, dpns->ancestors, + lnext(dpns->ancestors, lc)) + { + Node *ancestor2 = (Node *) lfirst(rest); + + if (!IsA(ancestor2, SubPlan)) + { + *dpns_p = dpns; + *ancestor_cell_p = rest; + return arg; + } + } + elog(ERROR, "SubPlan cannot be outermost ancestor"); } } - /* Keep looking, but we are emerging from a subplan. */ + /* We have emerged from a subplan. */ in_same_plan_level = false; - break; + + /* SubPlan isn't a kind of Plan, so skip the rest */ + continue; } /* - * Likewise check to see if we're emerging from an initplan. - * Initplans never have any parParams, so no need to search that - * list, but we need to know if we should reset + * Check to see if we're emerging from an initplan of the current + * ancestor plan. Initplans never have any parParams, so no need + * to search that list, but we need to know if we should reset * in_same_plan_level. */ - foreach(lc2, ps->initPlan) + foreach(lc2, ((Plan *) ancestor)->initPlan) { - SubPlanState *sstate = (SubPlanState *) lfirst(lc2); + SubPlan *subplan = castNode(SubPlan, lfirst(lc2)); - if (child_ps != sstate->planstate) + if (child_plan != (Plan *) list_nth(dpns->subplans, + subplan->plan_id - 1)) continue; /* No parameters to be had here. */ - Assert(sstate->subplan->parParam == NIL); + Assert(subplan->parParam == NIL); - /* Keep looking, but we are emerging from an initplan. */ + /* We have emerged from an initplan. */ in_same_plan_level = false; break; } /* No luck, crawl up to next ancestor */ - child_ps = ps; + child_plan = (Plan *) ancestor; } } @@ -6247,11 +6349,13 @@ get_agg_expr(Aggref *aggref, deparse_context *context, */ if (DO_AGGSPLIT_COMBINE(aggref->aggsplit)) { - TargetEntry *tle = linitial_node(TargetEntry, aggref->args); + TargetEntry *tle; + Assert(list_length(aggref->args) == 1); - resolve_special_varno((Node *) tle->expr, context, original_aggref, - get_agg_combine_expr); + tle = linitial_node(TargetEntry, aggref->args); + resolve_special_varno((Node *) tle->expr, context, + get_agg_combine_expr, original_aggref); return; } @@ -6336,10 +6440,10 @@ get_agg_expr(Aggref *aggref, deparse_context *context, * Aggref and then calls this. */ static void -get_agg_combine_expr(Node *node, deparse_context *context, void *private) +get_agg_combine_expr(Node *node, deparse_context *context, void *callback_arg) { Aggref *aggref; - Aggref *original_aggref = private; + Aggref *original_aggref = callback_arg; if (!IsA(node, Aggref)) elog(ERROR, "combining Aggref does not point to an Aggref"); @@ -7102,7 +7206,7 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context) RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc); List *args = ((FuncExpr *) rtfunc->funcexpr)->args; - allargs = list_concat(allargs, list_copy(args)); + allargs = list_concat(allargs, args); } appendStringInfoString(buf, "UNNEST("); @@ -7628,7 +7732,7 @@ printSubscripts(SubscriptingRef *sbsref, deparse_context *context) /* If subexpression is NULL, get_rule_expr prints nothing */ get_rule_expr((Node *) lfirst(lowlist_item), context, false); appendStringInfoChar(buf, ':'); - lowlist_item = lnext(sbsref->refupperindexpr, lowlist_item); + lowlist_item = lnext(sbsref->reflowerindexpr, lowlist_item); } /* If subexpression is NULL, get_rule_expr prints nothing */ get_rule_expr((Node *) lfirst(uplist_item), context, false);