mirror of https://github.com/citusdata/citus.git
Update ruleutils_13.c with postgres ruleutils
Some manual updates are done for ruleutils_13 based on the difference between pg12 ruleutils and pg13 ruleutils.pull/3900/head
parent
30549dc0e2
commit
8ce8683ac4
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue