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 */
|
int64 shardid; /* a distributed table's shardid, if positive */
|
||||||
ParseExprKind special_exprkind; /* set only for exprkinds needing special
|
ParseExprKind special_exprkind; /* set only for exprkinds needing special
|
||||||
* handling */
|
* handling */
|
||||||
Bitmapset *appendparents;
|
Bitmapset *appendparents; /* if not null, map child Vars of these relids
|
||||||
|
* back to the parent rel */
|
||||||
} deparse_context;
|
} deparse_context;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -167,20 +168,26 @@ typedef struct
|
||||||
List *rtable; /* List of RangeTblEntry nodes */
|
List *rtable; /* List of RangeTblEntry nodes */
|
||||||
List *rtable_names; /* Parallel list of names for RTEs */
|
List *rtable_names; /* Parallel list of names for RTEs */
|
||||||
List *rtable_columns; /* Parallel list of deparse_columns structs */
|
List *rtable_columns; /* Parallel list of deparse_columns structs */
|
||||||
|
List *subplans; /* List of Plan trees for SubPlans */
|
||||||
List *ctes; /* List of CommonTableExpr nodes */
|
List *ctes; /* List of CommonTableExpr nodes */
|
||||||
|
AppendRelInfo **appendrels; /* Array of AppendRelInfo nodes, or NULL */
|
||||||
/* Workspace for column alias assignment: */
|
/* Workspace for column alias assignment: */
|
||||||
bool unique_using; /* Are we making USING names globally unique */
|
bool unique_using; /* Are we making USING names globally unique */
|
||||||
List *using_names; /* List of assigned names for USING columns */
|
List *using_names; /* List of assigned names for USING columns */
|
||||||
/* Remaining fields are used only when deparsing a Plan tree: */
|
/* 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 */
|
List *ancestors; /* ancestors of planstate */
|
||||||
PlanState *outer_planstate; /* outer subplan state, or NULL if none */
|
Plan *outer_plan; /* outer subnode, or NULL if none */
|
||||||
PlanState *inner_planstate; /* inner subplan state, or NULL if none */
|
Plan *inner_plan; /* inner subnode, or NULL if none */
|
||||||
List *outer_tlist; /* referent for OUTER_VAR Vars */
|
List *outer_tlist; /* referent for OUTER_VAR Vars */
|
||||||
List *inner_tlist; /* referent for INNER_VAR Vars */
|
List *inner_tlist; /* referent for INNER_VAR Vars */
|
||||||
List *index_tlist; /* referent for INDEX_VAR Vars */
|
List *index_tlist; /* referent for INDEX_VAR Vars */
|
||||||
} deparse_namespace;
|
} 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.
|
* 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,
|
static void flatten_join_using_qual(Node *qual,
|
||||||
List **leftvars, List **rightvars);
|
List **leftvars, List **rightvars);
|
||||||
static char *get_rtable_name(int rtindex, deparse_context *context);
|
static char *get_rtable_name(int rtindex, deparse_context *context);
|
||||||
static void set_deparse_planstate(deparse_namespace *dpns, PlanState *ps);
|
static void set_deparse_plan(deparse_namespace *dpns, Plan *plan);
|
||||||
static void push_child_plan(deparse_namespace *dpns, PlanState *ps,
|
static void push_child_plan(deparse_namespace *dpns, Plan *plan,
|
||||||
deparse_namespace *save_dpns);
|
deparse_namespace *save_dpns);
|
||||||
static void pop_child_plan(deparse_namespace *dpns,
|
static void pop_child_plan(deparse_namespace *dpns,
|
||||||
deparse_namespace *save_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,
|
static char *get_variable(Var *var, int levelsup, bool istoplevel,
|
||||||
deparse_context *context);
|
deparse_context *context);
|
||||||
static void get_special_variable(Node *node, 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,
|
static void resolve_special_varno(Node *node, deparse_context *context,
|
||||||
void *private,
|
rsv_callback callback, void *callback_arg);
|
||||||
void (*callback) (Node *, deparse_context *, void *));
|
|
||||||
static Node *find_param_referent(Param *param, deparse_context *context,
|
static Node *find_param_referent(Param *param, deparse_context *context,
|
||||||
deparse_namespace **dpns_p, ListCell **ancestor_cell_p);
|
deparse_namespace **dpns_p, ListCell **ancestor_cell_p);
|
||||||
static void get_parameter(Param *param, deparse_context *context);
|
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,
|
static void get_agg_expr(Aggref *aggref, deparse_context *context,
|
||||||
Aggref *original_aggref);
|
Aggref *original_aggref);
|
||||||
static void get_agg_combine_expr(Node *node, deparse_context *context,
|
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_windowfunc_expr(WindowFunc *wfunc, deparse_context *context);
|
||||||
static void get_coercion_expr(Node *arg, deparse_context *context,
|
static void get_coercion_expr(Node *arg, deparse_context *context,
|
||||||
Oid resulttype, int32 resulttypmod,
|
Oid resulttype, int32 resulttypmod,
|
||||||
|
@ -672,7 +678,9 @@ set_deparse_for_query(deparse_namespace *dpns, Query *query,
|
||||||
/* Initialize *dpns and fill rtable/ctes links */
|
/* Initialize *dpns and fill rtable/ctes links */
|
||||||
memset(dpns, 0, sizeof(deparse_namespace));
|
memset(dpns, 0, sizeof(deparse_namespace));
|
||||||
dpns->rtable = query->rtable;
|
dpns->rtable = query->rtable;
|
||||||
|
dpns->subplans = NIL;
|
||||||
dpns->ctes = query->cteList;
|
dpns->ctes = query->cteList;
|
||||||
|
dpns->appendrels = NULL;
|
||||||
|
|
||||||
/* Assign a unique relation alias to each RTE */
|
/* Assign a unique relation alias to each RTE */
|
||||||
set_rtable_names(dpns, parent_namespaces, NULL);
|
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
|
* set_deparse_plan: set up deparse_namespace to parse subexpressions
|
||||||
* of a given PlanState node
|
* 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
|
* inner_tlist, and index_tlist fields. Caller is responsible for adjusting
|
||||||
* the ancestors list if necessary. Note that the rtable and ctes fields do
|
* 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
|
* not need to change when shifting attention to different plan nodes in a
|
||||||
* single plan tree.
|
* single plan tree.
|
||||||
*/
|
*/
|
||||||
static void
|
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
|
* 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
|
* first child plan is the OUTER referent; this is to support RETURNING
|
||||||
* lists containing references to non-target relations.
|
* lists containing references to non-target relations.
|
||||||
*/
|
*/
|
||||||
if (IsA(ps, AppendState))
|
if (IsA(plan, Append))
|
||||||
dpns->outer_planstate = ((AppendState *) ps)->appendplans[0];
|
dpns->outer_plan = linitial(((Append *) plan)->appendplans);
|
||||||
else if (IsA(ps, MergeAppendState))
|
else if (IsA(plan, MergeAppend))
|
||||||
dpns->outer_planstate = ((MergeAppendState *) ps)->mergeplans[0];
|
dpns->outer_plan = linitial(((MergeAppend *) plan)->mergeplans);
|
||||||
else if (IsA(ps, ModifyTableState))
|
else if (IsA(plan, ModifyTable))
|
||||||
dpns->outer_planstate = ((ModifyTableState *) ps)->mt_plans[0];
|
dpns->outer_plan = linitial(((ModifyTable *) plan)->plans);
|
||||||
else
|
else
|
||||||
dpns->outer_planstate = outerPlanState(ps);
|
dpns->outer_plan = outerPlan(plan);
|
||||||
|
|
||||||
if (dpns->outer_planstate)
|
if (dpns->outer_plan)
|
||||||
dpns->outer_tlist = dpns->outer_planstate->plan->targetlist;
|
dpns->outer_tlist = dpns->outer_plan->targetlist;
|
||||||
else
|
else
|
||||||
dpns->outer_tlist = NIL;
|
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,
|
* to reuse OUTER, it's used for RETURNING in some modify table cases,
|
||||||
* although not INSERT .. CONFLICT).
|
* although not INSERT .. CONFLICT).
|
||||||
*/
|
*/
|
||||||
if (IsA(ps, SubqueryScanState))
|
if (IsA(plan, SubqueryScan))
|
||||||
dpns->inner_planstate = ((SubqueryScanState *) ps)->subplan;
|
dpns->inner_plan = ((SubqueryScan *) plan)->subplan;
|
||||||
else if (IsA(ps, CteScanState))
|
else if (IsA(plan, CteScan))
|
||||||
dpns->inner_planstate = ((CteScanState *) ps)->cteplanstate;
|
dpns->inner_plan = list_nth(dpns->subplans,
|
||||||
else if (IsA(ps, ModifyTableState))
|
((CteScan *) plan)->ctePlanId - 1);
|
||||||
dpns->inner_planstate = ps;
|
else if (IsA(plan, ModifyTable))
|
||||||
|
dpns->inner_plan = plan;
|
||||||
else
|
else
|
||||||
dpns->inner_planstate = innerPlanState(ps);
|
dpns->inner_plan = innerPlan(plan);
|
||||||
|
|
||||||
if (IsA(ps, ModifyTableState))
|
if (IsA(plan, ModifyTable))
|
||||||
dpns->inner_tlist = ((ModifyTableState *) ps)->mt_excludedtlist;
|
dpns->inner_tlist = ((ModifyTable *) plan)->exclRelTlist;
|
||||||
else if (dpns->inner_planstate)
|
else if (dpns->inner_plan)
|
||||||
dpns->inner_tlist = dpns->inner_planstate->plan->targetlist;
|
dpns->inner_tlist = dpns->inner_plan->targetlist;
|
||||||
else
|
else
|
||||||
dpns->inner_tlist = NIL;
|
dpns->inner_tlist = NIL;
|
||||||
|
|
||||||
/* Set up referent for INDEX_VAR Vars, if needed */
|
/* Set up referent for INDEX_VAR Vars, if needed */
|
||||||
if (IsA(ps->plan, IndexOnlyScan))
|
if (IsA(plan, IndexOnlyScan))
|
||||||
dpns->index_tlist = ((IndexOnlyScan *) ps->plan)->indextlist;
|
dpns->index_tlist = ((IndexOnlyScan *) plan)->indextlist;
|
||||||
else if (IsA(ps->plan, ForeignScan))
|
else if (IsA(plan, ForeignScan))
|
||||||
dpns->index_tlist = ((ForeignScan *) ps->plan)->fdw_scan_tlist;
|
dpns->index_tlist = ((ForeignScan *) plan)->fdw_scan_tlist;
|
||||||
else if (IsA(ps->plan, CustomScan))
|
else if (IsA(plan, CustomScan))
|
||||||
dpns->index_tlist = ((CustomScan *) ps->plan)->custom_scan_tlist;
|
dpns->index_tlist = ((CustomScan *) plan)->custom_scan_tlist;
|
||||||
else
|
else
|
||||||
dpns->index_tlist = NIL;
|
dpns->index_tlist = NIL;
|
||||||
}
|
}
|
||||||
|
@ -1795,17 +1804,17 @@ set_deparse_planstate(deparse_namespace *dpns, PlanState *ps)
|
||||||
* previous state for pop_child_plan.
|
* previous state for pop_child_plan.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
push_child_plan(deparse_namespace *dpns, PlanState *ps,
|
push_child_plan(deparse_namespace *dpns, Plan *plan,
|
||||||
deparse_namespace *save_dpns)
|
deparse_namespace *save_dpns)
|
||||||
{
|
{
|
||||||
/* Save state for restoration later */
|
/* Save state for restoration later */
|
||||||
*save_dpns = *dpns;
|
*save_dpns = *dpns;
|
||||||
|
|
||||||
/* Link current plan node into ancestors list */
|
/* 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 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.wrapColumn = wrapColumn;
|
||||||
context.indentLevel = startIndent;
|
context.indentLevel = startIndent;
|
||||||
context.special_exprkind = EXPR_KIND_NONE;
|
context.special_exprkind = EXPR_KIND_NONE;
|
||||||
|
context.appendparents = NULL;
|
||||||
context.distrelid = distrelid;
|
context.distrelid = distrelid;
|
||||||
context.shardid = shardid;
|
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.
|
* if so, return the VALUES RTE. Otherwise return NULL.
|
||||||
*/
|
*/
|
||||||
static RangeTblEntry *
|
static RangeTblEntry *
|
||||||
get_simple_values_rte(Query *query)
|
get_simple_values_rte(Query *query, TupleDesc resultDesc)
|
||||||
{
|
{
|
||||||
RangeTblEntry *result = NULL;
|
RangeTblEntry *result = NULL;
|
||||||
ListCell *lc;
|
ListCell *lc;
|
||||||
|
int colno;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We want to return true even if the Query also contains OLD or NEW rule
|
* 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))
|
if (list_length(query->targetList) != list_length(result->eref->colnames))
|
||||||
return NULL; /* this probably cannot happen */
|
return NULL; /* this probably cannot happen */
|
||||||
|
colno = 0;
|
||||||
forboth(lc, query->targetList, lcn, result->eref->colnames)
|
forboth(lc, query->targetList, lcn, result->eref->colnames)
|
||||||
{
|
{
|
||||||
TargetEntry *tle = (TargetEntry *) lfirst(lc);
|
TargetEntry *tle = (TargetEntry *) lfirst(lc);
|
||||||
char *cname = strVal(lfirst(lcn));
|
char *cname = strVal(lfirst(lcn));
|
||||||
|
char *colname;
|
||||||
|
|
||||||
if (tle->resjunk)
|
if (tle->resjunk)
|
||||||
return NULL; /* this probably cannot happen */
|
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 */
|
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
|
* VALUES part. This reverses what transformValuesClause() did at parse
|
||||||
* time.
|
* time.
|
||||||
*/
|
*/
|
||||||
values_rte = get_simple_values_rte(query);
|
values_rte = get_simple_values_rte(query, resultDesc);
|
||||||
if (values_rte)
|
if (values_rte)
|
||||||
{
|
{
|
||||||
get_values_def(values_rte->values_lists, context);
|
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))
|
if (var->varno >= 1 && var->varno <= list_length(dpns->rtable))
|
||||||
{
|
{
|
||||||
rte = rt_fetch(var->varno, dpns->rtable);
|
Index varno = var->varno;
|
||||||
refname = (char *) list_nth(dpns->rtable_names, var->varno - 1);
|
AttrNumber varattno = var->varattno;
|
||||||
colinfo = deparse_columns_fetch(var->varno, dpns);
|
/*
|
||||||
attnum = 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
|
else
|
||||||
{
|
{
|
||||||
resolve_special_varno((Node *) var, context, NULL,
|
resolve_special_varno((Node *) var, context, get_special_variable,
|
||||||
get_special_variable);
|
NULL);
|
||||||
return 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
|
* 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
|
* 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
|
* 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) &&
|
if ((rte->rtekind == RTE_SUBQUERY || rte->rtekind == RTE_CTE) &&
|
||||||
attnum > list_length(rte->eref->colnames) &&
|
attnum > list_length(rte->eref->colnames) &&
|
||||||
dpns->inner_planstate)
|
dpns->inner_plan)
|
||||||
{
|
{
|
||||||
TargetEntry *tle;
|
TargetEntry *tle;
|
||||||
deparse_namespace save_dpns;
|
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)
|
if (!tle)
|
||||||
elog(ERROR, "invalid attnum %d for relation \"%s\"",
|
elog(ERROR, "invalid attnum %d for relation \"%s\"",
|
||||||
var->varattno, rte->eref->aliasname);
|
attnum, rte->eref->aliasname);
|
||||||
|
|
||||||
Assert(netlevelsup == 0);
|
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
|
* 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.
|
* get_rule_expr.
|
||||||
*/
|
*/
|
||||||
static void
|
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;
|
StringInfo buf = context->buf;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Force parentheses because our caller probably assumed a Var is a simple
|
* For a non-Var referent, force parentheses because our caller probably
|
||||||
* expression.
|
* assumed a Var is a simple expression.
|
||||||
*/
|
*/
|
||||||
if (!IsA(node, Var))
|
if (!IsA(node, Var))
|
||||||
appendStringInfoChar(buf, '(');
|
appendStringInfoChar(buf, '(');
|
||||||
|
@ -3817,16 +3885,18 @@ get_special_variable(Node *node, deparse_context *context, void *private)
|
||||||
* invoke the callback provided.
|
* invoke the callback provided.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
resolve_special_varno(Node *node, deparse_context *context, void *private,
|
resolve_special_varno(Node *node, deparse_context *context, rsv_callback callback, void *callback_arg)
|
||||||
void (*callback) (Node *, deparse_context *, void *))
|
|
||||||
{
|
{
|
||||||
Var *var;
|
Var *var;
|
||||||
deparse_namespace *dpns;
|
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 it's not a Var, invoke the callback. */
|
||||||
if (!IsA(node, Var))
|
if (!IsA(node, Var))
|
||||||
{
|
{
|
||||||
callback(node, context, private);
|
(*callback) (node, context, callback_arg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3842,14 +3912,30 @@ resolve_special_varno(Node *node, deparse_context *context, void *private,
|
||||||
{
|
{
|
||||||
TargetEntry *tle;
|
TargetEntry *tle;
|
||||||
deparse_namespace save_dpns;
|
deparse_namespace save_dpns;
|
||||||
|
Bitmapset *save_appendparents;
|
||||||
|
|
||||||
tle = get_tle_by_resno(dpns->outer_tlist, var->varattno);
|
tle = get_tle_by_resno(dpns->outer_tlist, var->varattno);
|
||||||
if (!tle)
|
if (!tle)
|
||||||
elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno);
|
elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno);
|
||||||
|
|
||||||
push_child_plan(dpns, dpns->outer_planstate, &save_dpns);
|
/* If we're descending to the first child of an Append or MergeAppend,
|
||||||
resolve_special_varno((Node *) tle->expr, context, private, callback);
|
* 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);
|
pop_child_plan(dpns, &save_dpns);
|
||||||
|
context->appendparents = save_appendparents;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (var->varno == INNER_VAR && dpns->inner_tlist)
|
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)
|
if (!tle)
|
||||||
elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno);
|
elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno);
|
||||||
|
|
||||||
push_child_plan(dpns, dpns->inner_planstate, &save_dpns);
|
push_child_plan(dpns, dpns->inner_plan, &save_dpns);
|
||||||
resolve_special_varno((Node *) tle->expr, context, private, callback);
|
resolve_special_varno((Node *) tle->expr, context, callback, callback_arg);
|
||||||
pop_child_plan(dpns, &save_dpns);
|
pop_child_plan(dpns, &save_dpns);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3874,14 +3960,14 @@ resolve_special_varno(Node *node, deparse_context *context, void *private,
|
||||||
if (!tle)
|
if (!tle)
|
||||||
elog(ERROR, "bogus varattno for INDEX_VAR var: %d", var->varattno);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
else if (var->varno < 1 || var->varno > list_length(dpns->rtable))
|
else if (var->varno < 1 || var->varno > list_length(dpns->rtable))
|
||||||
elog(ERROR, "bogus varno: %d", var->varno);
|
elog(ERROR, "bogus varno: %d", var->varno);
|
||||||
|
|
||||||
/* Not special. Just invoke the callback. */
|
/* 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);
|
elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno);
|
||||||
|
|
||||||
Assert(netlevelsup == 0);
|
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,
|
result = get_name_for_var_field((Var *) tle->expr, fieldno,
|
||||||
levelsup, context);
|
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);
|
elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno);
|
||||||
|
|
||||||
Assert(netlevelsup == 0);
|
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,
|
result = get_name_for_var_field((Var *) tle->expr, fieldno,
|
||||||
levelsup, context);
|
levelsup, context);
|
||||||
|
@ -4118,7 +4204,7 @@ get_name_for_var_field(Var *var, int fieldno,
|
||||||
deparse_namespace save_dpns;
|
deparse_namespace save_dpns;
|
||||||
const char *result;
|
const char *result;
|
||||||
|
|
||||||
if (!dpns->inner_planstate)
|
if (!dpns->inner_plan)
|
||||||
elog(ERROR, "failed to find plan for subquery %s",
|
elog(ERROR, "failed to find plan for subquery %s",
|
||||||
rte->eref->aliasname);
|
rte->eref->aliasname);
|
||||||
tle = get_tle_by_resno(dpns->inner_tlist, attnum);
|
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",
|
elog(ERROR, "bogus varattno for subquery var: %d",
|
||||||
attnum);
|
attnum);
|
||||||
Assert(netlevelsup == 0);
|
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,
|
result = get_name_for_var_field((Var *) tle->expr, fieldno,
|
||||||
levelsup, context);
|
levelsup, context);
|
||||||
|
@ -4236,7 +4322,7 @@ get_name_for_var_field(Var *var, int fieldno,
|
||||||
deparse_namespace save_dpns;
|
deparse_namespace save_dpns;
|
||||||
const char *result;
|
const char *result;
|
||||||
|
|
||||||
if (!dpns->inner_planstate)
|
if (!dpns->inner_plan)
|
||||||
elog(ERROR, "failed to find plan for CTE %s",
|
elog(ERROR, "failed to find plan for CTE %s",
|
||||||
rte->eref->aliasname);
|
rte->eref->aliasname);
|
||||||
tle = get_tle_by_resno(dpns->inner_tlist, attnum);
|
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",
|
elog(ERROR, "bogus varattno for subquery var: %d",
|
||||||
attnum);
|
attnum);
|
||||||
Assert(netlevelsup == 0);
|
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,
|
result = get_name_for_var_field((Var *) tle->expr, fieldno,
|
||||||
levelsup, context);
|
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
|
* If it's a PARAM_EXEC parameter, look for a matching NestLoopParam or
|
||||||
* SubPlan argument. This will necessarily be in some ancestor of the
|
* SubPlan argument. This will necessarily be in some ancestor of the
|
||||||
* current expression's PlanState.
|
* current expression's Plan.
|
||||||
*/
|
*/
|
||||||
if (param->paramkind == PARAM_EXEC)
|
if (param->paramkind == PARAM_EXEC)
|
||||||
{
|
{
|
||||||
deparse_namespace *dpns;
|
deparse_namespace *dpns;
|
||||||
PlanState *child_ps;
|
Plan *child_plan;
|
||||||
bool in_same_plan_level;
|
bool in_same_plan_level;
|
||||||
ListCell *lc;
|
ListCell *lc;
|
||||||
|
|
||||||
dpns = (deparse_namespace *) linitial(context->namespaces);
|
dpns = (deparse_namespace *) linitial(context->namespaces);
|
||||||
child_ps = dpns->planstate;
|
child_plan = dpns->plan;
|
||||||
in_same_plan_level = true;
|
in_same_plan_level = true;
|
||||||
|
|
||||||
foreach(lc, dpns->ancestors)
|
foreach(lc, dpns->ancestors)
|
||||||
{
|
{
|
||||||
PlanState *ps = (PlanState *) lfirst(lc);
|
Node *ancestor = (Node *) lfirst(lc);
|
||||||
ListCell *lc2;
|
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
|
* we've crawled up out of a subplan, this couldn't possibly be
|
||||||
* the right match.
|
* the right match.
|
||||||
*/
|
*/
|
||||||
if (IsA(ps, NestLoopState) &&
|
if (IsA(ancestor, NestLoop) &&
|
||||||
child_ps == innerPlanState(ps) &&
|
child_plan == innerPlan(ancestor) &&
|
||||||
in_same_plan_level)
|
in_same_plan_level)
|
||||||
{
|
{
|
||||||
NestLoop *nl = (NestLoop *) ps->plan;
|
NestLoop *nl = (NestLoop *) ancestor;
|
||||||
|
|
||||||
foreach(lc2, nl->nestParams)
|
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.
|
* 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 = (SubPlan *) ancestor;
|
||||||
SubPlan *subplan = sstate->subplan;
|
|
||||||
ListCell *lc3;
|
ListCell *lc3;
|
||||||
ListCell *lc4;
|
ListCell *lc4;
|
||||||
|
|
||||||
if (child_ps != sstate->planstate)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Matched subplan, so check its arguments */
|
/* Matched subplan, so check its arguments */
|
||||||
forboth(lc3, subplan->parParam, lc4, subplan->args)
|
forboth(lc3, subplan->parParam, lc4, subplan->args)
|
||||||
{
|
{
|
||||||
|
@ -4349,41 +4431,61 @@ find_param_referent(Param *param, deparse_context *context,
|
||||||
|
|
||||||
if (paramid == param->paramid)
|
if (paramid == param->paramid)
|
||||||
{
|
{
|
||||||
/* Found a match, so return it */
|
/*
|
||||||
*dpns_p = dpns;
|
* Found a match, so return it. But, since Vars in
|
||||||
*ancestor_cell_p = lc;
|
* the arg are to be evaluated in the surrounding
|
||||||
return arg;
|
* 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;
|
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.
|
* Check to see if we're emerging from an initplan of the current
|
||||||
* Initplans never have any parParams, so no need to search that
|
* ancestor plan. Initplans never have any parParams, so no need
|
||||||
* list, but we need to know if we should reset
|
* to search that list, but we need to know if we should reset
|
||||||
* in_same_plan_level.
|
* 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;
|
continue;
|
||||||
|
|
||||||
/* No parameters to be had here. */
|
/* 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;
|
in_same_plan_level = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No luck, crawl up to next ancestor */
|
/* 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))
|
if (DO_AGGSPLIT_COMBINE(aggref->aggsplit))
|
||||||
{
|
{
|
||||||
TargetEntry *tle = linitial_node(TargetEntry, aggref->args);
|
TargetEntry *tle;
|
||||||
|
|
||||||
|
|
||||||
Assert(list_length(aggref->args) == 1);
|
Assert(list_length(aggref->args) == 1);
|
||||||
resolve_special_varno((Node *) tle->expr, context, original_aggref,
|
tle = linitial_node(TargetEntry, aggref->args);
|
||||||
get_agg_combine_expr);
|
resolve_special_varno((Node *) tle->expr, context,
|
||||||
|
get_agg_combine_expr, original_aggref);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6336,10 +6440,10 @@ get_agg_expr(Aggref *aggref, deparse_context *context,
|
||||||
* Aggref and then calls this.
|
* Aggref and then calls this.
|
||||||
*/
|
*/
|
||||||
static void
|
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 *aggref;
|
||||||
Aggref *original_aggref = private;
|
Aggref *original_aggref = callback_arg;
|
||||||
|
|
||||||
if (!IsA(node, Aggref))
|
if (!IsA(node, Aggref))
|
||||||
elog(ERROR, "combining Aggref does not point to an 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);
|
RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc);
|
||||||
List *args = ((FuncExpr *) rtfunc->funcexpr)->args;
|
List *args = ((FuncExpr *) rtfunc->funcexpr)->args;
|
||||||
|
|
||||||
allargs = list_concat(allargs, list_copy(args));
|
allargs = list_concat(allargs, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
appendStringInfoString(buf, "UNNEST(");
|
appendStringInfoString(buf, "UNNEST(");
|
||||||
|
@ -7628,7 +7732,7 @@ printSubscripts(SubscriptingRef *sbsref, deparse_context *context)
|
||||||
/* If subexpression is NULL, get_rule_expr prints nothing */
|
/* If subexpression is NULL, get_rule_expr prints nothing */
|
||||||
get_rule_expr((Node *) lfirst(lowlist_item), context, false);
|
get_rule_expr((Node *) lfirst(lowlist_item), context, false);
|
||||||
appendStringInfoChar(buf, ':');
|
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 */
|
/* If subexpression is NULL, get_rule_expr prints nothing */
|
||||||
get_rule_expr((Node *) lfirst(uplist_item), context, false);
|
get_rule_expr((Node *) lfirst(uplist_item), context, false);
|
||||||
|
|
Loading…
Reference in New Issue