mirror of
https://github.com/postgres/postgres.git
synced 2025-05-20 00:03:14 -04:00
Change Agg and Group nodes so that Vars contained in their targetlists
and quals have varno OUTER, rather than zero, to indicate a reference to an output of their lefttree subplan. This is consistent with the way that every other upper-level node type does it, and allows some simplifications in setrefs.c and EXPLAIN.
This commit is contained in:
parent
3c5985b473
commit
cc77005df7
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1994-5, Regents of the University of California
|
* Portions Copyright (c) 1994-5, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.157 2007/02/22 22:00:22 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.158 2007/02/22 23:44:24 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -52,8 +52,8 @@ static void show_scan_qual(List *qual, const char *qlabel,
|
|||||||
int scanrelid, Plan *outer_plan,
|
int scanrelid, Plan *outer_plan,
|
||||||
StringInfo str, int indent, ExplainState *es);
|
StringInfo str, int indent, ExplainState *es);
|
||||||
static void show_upper_qual(List *qual, const char *qlabel,
|
static void show_upper_qual(List *qual, const char *qlabel,
|
||||||
const char *outer_name, int outer_varno, Plan *outer_plan,
|
const char *outer_name, Plan *outer_plan,
|
||||||
const char *inner_name, int inner_varno, Plan *inner_plan,
|
const char *inner_name, Plan *inner_plan,
|
||||||
StringInfo str, int indent, ExplainState *es);
|
StringInfo str, int indent, ExplainState *es);
|
||||||
static void show_sort_keys(Plan *sortplan, int nkeys, AttrNumber *keycols,
|
static void show_sort_keys(Plan *sortplan, int nkeys, AttrNumber *keycols,
|
||||||
const char *qlabel,
|
const char *qlabel,
|
||||||
@ -783,55 +783,55 @@ explain_outNode(StringInfo str,
|
|||||||
case T_NestLoop:
|
case T_NestLoop:
|
||||||
show_upper_qual(((NestLoop *) plan)->join.joinqual,
|
show_upper_qual(((NestLoop *) plan)->join.joinqual,
|
||||||
"Join Filter",
|
"Join Filter",
|
||||||
"outer", OUTER, outerPlan(plan),
|
"outer", outerPlan(plan),
|
||||||
"inner", INNER, innerPlan(plan),
|
"inner", innerPlan(plan),
|
||||||
str, indent, es);
|
str, indent, es);
|
||||||
show_upper_qual(plan->qual,
|
show_upper_qual(plan->qual,
|
||||||
"Filter",
|
"Filter",
|
||||||
"outer", OUTER, outerPlan(plan),
|
"outer", outerPlan(plan),
|
||||||
"inner", INNER, innerPlan(plan),
|
"inner", innerPlan(plan),
|
||||||
str, indent, es);
|
str, indent, es);
|
||||||
break;
|
break;
|
||||||
case T_MergeJoin:
|
case T_MergeJoin:
|
||||||
show_upper_qual(((MergeJoin *) plan)->mergeclauses,
|
show_upper_qual(((MergeJoin *) plan)->mergeclauses,
|
||||||
"Merge Cond",
|
"Merge Cond",
|
||||||
"outer", OUTER, outerPlan(plan),
|
"outer", outerPlan(plan),
|
||||||
"inner", INNER, innerPlan(plan),
|
"inner", innerPlan(plan),
|
||||||
str, indent, es);
|
str, indent, es);
|
||||||
show_upper_qual(((MergeJoin *) plan)->join.joinqual,
|
show_upper_qual(((MergeJoin *) plan)->join.joinqual,
|
||||||
"Join Filter",
|
"Join Filter",
|
||||||
"outer", OUTER, outerPlan(plan),
|
"outer", outerPlan(plan),
|
||||||
"inner", INNER, innerPlan(plan),
|
"inner", innerPlan(plan),
|
||||||
str, indent, es);
|
str, indent, es);
|
||||||
show_upper_qual(plan->qual,
|
show_upper_qual(plan->qual,
|
||||||
"Filter",
|
"Filter",
|
||||||
"outer", OUTER, outerPlan(plan),
|
"outer", outerPlan(plan),
|
||||||
"inner", INNER, innerPlan(plan),
|
"inner", innerPlan(plan),
|
||||||
str, indent, es);
|
str, indent, es);
|
||||||
break;
|
break;
|
||||||
case T_HashJoin:
|
case T_HashJoin:
|
||||||
show_upper_qual(((HashJoin *) plan)->hashclauses,
|
show_upper_qual(((HashJoin *) plan)->hashclauses,
|
||||||
"Hash Cond",
|
"Hash Cond",
|
||||||
"outer", OUTER, outerPlan(plan),
|
"outer", outerPlan(plan),
|
||||||
"inner", INNER, innerPlan(plan),
|
"inner", innerPlan(plan),
|
||||||
str, indent, es);
|
str, indent, es);
|
||||||
show_upper_qual(((HashJoin *) plan)->join.joinqual,
|
show_upper_qual(((HashJoin *) plan)->join.joinqual,
|
||||||
"Join Filter",
|
"Join Filter",
|
||||||
"outer", OUTER, outerPlan(plan),
|
"outer", outerPlan(plan),
|
||||||
"inner", INNER, innerPlan(plan),
|
"inner", innerPlan(plan),
|
||||||
str, indent, es);
|
str, indent, es);
|
||||||
show_upper_qual(plan->qual,
|
show_upper_qual(plan->qual,
|
||||||
"Filter",
|
"Filter",
|
||||||
"outer", OUTER, outerPlan(plan),
|
"outer", outerPlan(plan),
|
||||||
"inner", INNER, innerPlan(plan),
|
"inner", innerPlan(plan),
|
||||||
str, indent, es);
|
str, indent, es);
|
||||||
break;
|
break;
|
||||||
case T_Agg:
|
case T_Agg:
|
||||||
case T_Group:
|
case T_Group:
|
||||||
show_upper_qual(plan->qual,
|
show_upper_qual(plan->qual,
|
||||||
"Filter",
|
"Filter",
|
||||||
"subplan", 0, outerPlan(plan),
|
"subplan", outerPlan(plan),
|
||||||
"", 0, NULL,
|
"", NULL,
|
||||||
str, indent, es);
|
str, indent, es);
|
||||||
break;
|
break;
|
||||||
case T_Sort:
|
case T_Sort:
|
||||||
@ -844,13 +844,13 @@ explain_outNode(StringInfo str,
|
|||||||
case T_Result:
|
case T_Result:
|
||||||
show_upper_qual((List *) ((Result *) plan)->resconstantqual,
|
show_upper_qual((List *) ((Result *) plan)->resconstantqual,
|
||||||
"One-Time Filter",
|
"One-Time Filter",
|
||||||
"subplan", OUTER, outerPlan(plan),
|
"subplan", outerPlan(plan),
|
||||||
"", 0, NULL,
|
"", NULL,
|
||||||
str, indent, es);
|
str, indent, es);
|
||||||
show_upper_qual(plan->qual,
|
show_upper_qual(plan->qual,
|
||||||
"Filter",
|
"Filter",
|
||||||
"subplan", OUTER, outerPlan(plan),
|
"subplan", outerPlan(plan),
|
||||||
"", 0, NULL,
|
"", NULL,
|
||||||
str, indent, es);
|
str, indent, es);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -1088,13 +1088,15 @@ show_scan_qual(List *qual, const char *qlabel,
|
|||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
show_upper_qual(List *qual, const char *qlabel,
|
show_upper_qual(List *qual, const char *qlabel,
|
||||||
const char *outer_name, int outer_varno, Plan *outer_plan,
|
const char *outer_name, Plan *outer_plan,
|
||||||
const char *inner_name, int inner_varno, Plan *inner_plan,
|
const char *inner_name, Plan *inner_plan,
|
||||||
StringInfo str, int indent, ExplainState *es)
|
StringInfo str, int indent, ExplainState *es)
|
||||||
{
|
{
|
||||||
List *context;
|
List *context;
|
||||||
Node *outercontext;
|
Node *outercontext;
|
||||||
Node *innercontext;
|
Node *innercontext;
|
||||||
|
int outer_varno;
|
||||||
|
int inner_varno;
|
||||||
Node *node;
|
Node *node;
|
||||||
char *exprstr;
|
char *exprstr;
|
||||||
int i;
|
int i;
|
||||||
@ -1105,15 +1107,27 @@ show_upper_qual(List *qual, const char *qlabel,
|
|||||||
|
|
||||||
/* Generate deparse context */
|
/* Generate deparse context */
|
||||||
if (outer_plan)
|
if (outer_plan)
|
||||||
|
{
|
||||||
outercontext = deparse_context_for_subplan(outer_name,
|
outercontext = deparse_context_for_subplan(outer_name,
|
||||||
(Node *) outer_plan);
|
(Node *) outer_plan);
|
||||||
|
outer_varno = OUTER;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
outercontext = NULL;
|
outercontext = NULL;
|
||||||
|
outer_varno = 0;
|
||||||
|
}
|
||||||
if (inner_plan)
|
if (inner_plan)
|
||||||
|
{
|
||||||
innercontext = deparse_context_for_subplan(inner_name,
|
innercontext = deparse_context_for_subplan(inner_name,
|
||||||
(Node *) inner_plan);
|
(Node *) inner_plan);
|
||||||
|
inner_varno = INNER;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
innercontext = NULL;
|
innercontext = NULL;
|
||||||
|
inner_varno = 0;
|
||||||
|
}
|
||||||
context = deparse_context_for_plan(outer_varno, outercontext,
|
context = deparse_context_for_plan(outer_varno, outercontext,
|
||||||
inner_varno, innercontext,
|
inner_varno, innercontext,
|
||||||
es->rtable);
|
es->rtable);
|
||||||
|
@ -61,7 +61,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.150 2007/02/02 00:07:03 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.151 2007/02/22 23:44:24 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -420,7 +420,7 @@ advance_transition_function(AggState *aggstate,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Advance all the aggregates for one input tuple. The input tuple
|
* Advance all the aggregates for one input tuple. The input tuple
|
||||||
* has been stored in tmpcontext->ecxt_scantuple, so that it is accessible
|
* has been stored in tmpcontext->ecxt_outertuple, so that it is accessible
|
||||||
* to ExecEvalExpr. pergroup is the array of per-group structs to use
|
* to ExecEvalExpr. pergroup is the array of per-group structs to use
|
||||||
* (this might be in a hashtable entry).
|
* (this might be in a hashtable entry).
|
||||||
*
|
*
|
||||||
@ -643,8 +643,8 @@ find_unaggregated_cols_walker(Node *node, Bitmapset **colnos)
|
|||||||
{
|
{
|
||||||
Var *var = (Var *) node;
|
Var *var = (Var *) node;
|
||||||
|
|
||||||
/* setrefs.c should have set the varno to 0 */
|
/* setrefs.c should have set the varno to OUTER */
|
||||||
Assert(var->varno == 0);
|
Assert(var->varno == OUTER);
|
||||||
Assert(var->varlevelsup == 0);
|
Assert(var->varlevelsup == 0);
|
||||||
*colnos = bms_add_member(*colnos, var->varattno);
|
*colnos = bms_add_member(*colnos, var->varattno);
|
||||||
return false;
|
return false;
|
||||||
@ -905,7 +905,7 @@ agg_retrieve_direct(AggState *aggstate)
|
|||||||
aggstate->grp_firstTuple = NULL; /* don't keep two pointers */
|
aggstate->grp_firstTuple = NULL; /* don't keep two pointers */
|
||||||
|
|
||||||
/* set up for first advance_aggregates call */
|
/* set up for first advance_aggregates call */
|
||||||
tmpcontext->ecxt_scantuple = firstSlot;
|
tmpcontext->ecxt_outertuple = firstSlot;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Process each outer-plan tuple, and then fetch the next one,
|
* Process each outer-plan tuple, and then fetch the next one,
|
||||||
@ -926,7 +926,7 @@ agg_retrieve_direct(AggState *aggstate)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* set up for next advance_aggregates call */
|
/* set up for next advance_aggregates call */
|
||||||
tmpcontext->ecxt_scantuple = outerslot;
|
tmpcontext->ecxt_outertuple = outerslot;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we are grouping, check whether we've crossed a group
|
* If we are grouping, check whether we've crossed a group
|
||||||
@ -973,7 +973,7 @@ agg_retrieve_direct(AggState *aggstate)
|
|||||||
* with an empty firstSlot ... but if not grouping, there can't be any
|
* with an empty firstSlot ... but if not grouping, there can't be any
|
||||||
* references to non-aggregated input columns, so no problem.)
|
* references to non-aggregated input columns, so no problem.)
|
||||||
*/
|
*/
|
||||||
econtext->ecxt_scantuple = firstSlot;
|
econtext->ecxt_outertuple = firstSlot;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check the qual (HAVING clause); if the group does not match, ignore
|
* Check the qual (HAVING clause); if the group does not match, ignore
|
||||||
@ -1022,7 +1022,7 @@ agg_fill_hash_table(AggState *aggstate)
|
|||||||
if (TupIsNull(outerslot))
|
if (TupIsNull(outerslot))
|
||||||
break;
|
break;
|
||||||
/* set up for advance_aggregates call */
|
/* set up for advance_aggregates call */
|
||||||
tmpcontext->ecxt_scantuple = outerslot;
|
tmpcontext->ecxt_outertuple = outerslot;
|
||||||
|
|
||||||
/* Find or build hashtable entry for this tuple's group */
|
/* Find or build hashtable entry for this tuple's group */
|
||||||
entry = lookup_hash_entry(aggstate, outerslot);
|
entry = lookup_hash_entry(aggstate, outerslot);
|
||||||
@ -1116,7 +1116,7 @@ agg_retrieve_hash_table(AggState *aggstate)
|
|||||||
* Use the representative input tuple for any references to
|
* Use the representative input tuple for any references to
|
||||||
* non-aggregated input columns in the qual and tlist.
|
* non-aggregated input columns in the qual and tlist.
|
||||||
*/
|
*/
|
||||||
econtext->ecxt_scantuple = firstSlot;
|
econtext->ecxt_outertuple = firstSlot;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check the qual (HAVING clause); if the group does not match, ignore
|
* Check the qual (HAVING clause); if the group does not match, ignore
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* locate group boundaries.
|
* locate group boundaries.
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/executor/nodeGroup.c,v 1.68 2007/02/02 00:07:03 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/executor/nodeGroup.c,v 1.69 2007/02/22 23:44:24 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -72,9 +72,14 @@ ExecGroup(GroupState *node)
|
|||||||
node->grp_done = TRUE;
|
node->grp_done = TRUE;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* Copy tuple, set up as input for qual test and projection */
|
/* Copy tuple into firsttupleslot */
|
||||||
ExecCopySlot(firsttupleslot, outerslot);
|
ExecCopySlot(firsttupleslot, outerslot);
|
||||||
econtext->ecxt_scantuple = firsttupleslot;
|
|
||||||
|
/*
|
||||||
|
* Set it up as input for qual test and projection. The expressions
|
||||||
|
* will access the input tuple as varno OUTER.
|
||||||
|
*/
|
||||||
|
econtext->ecxt_outertuple = firsttupleslot;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check the qual (HAVING clause); if the group does not match, ignore
|
* Check the qual (HAVING clause); if the group does not match, ignore
|
||||||
@ -126,7 +131,7 @@ ExecGroup(GroupState *node)
|
|||||||
*/
|
*/
|
||||||
/* Copy tuple, set up as input for qual test and projection */
|
/* Copy tuple, set up as input for qual test and projection */
|
||||||
ExecCopySlot(firsttupleslot, outerslot);
|
ExecCopySlot(firsttupleslot, outerslot);
|
||||||
econtext->ecxt_scantuple = firsttupleslot;
|
econtext->ecxt_outertuple = firsttupleslot;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check the qual (HAVING clause); if the group does not match, ignore
|
* Check the qual (HAVING clause); if the group does not match, ignore
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/executor/nodeResult.c,v 1.39 2007/02/16 03:49:04 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/executor/nodeResult.c,v 1.40 2007/02/22 23:44:25 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -132,13 +132,11 @@ ExecResult(ResultState *node)
|
|||||||
if (TupIsNull(outerTupleSlot))
|
if (TupIsNull(outerTupleSlot))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
node->ps.ps_OuterTupleSlot = outerTupleSlot;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX gross hack. use outer tuple as scan tuple for projection
|
* prepare to compute projection expressions, which will expect
|
||||||
|
* to access the input tuples as varno OUTER.
|
||||||
*/
|
*/
|
||||||
econtext->ecxt_outertuple = outerTupleSlot;
|
econtext->ecxt_outertuple = outerTupleSlot;
|
||||||
econtext->ecxt_scantuple = outerTupleSlot;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.131 2007/02/22 22:00:24 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.132 2007/02/22 23:44:25 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -56,7 +56,6 @@ typedef struct
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
indexed_tlist *subplan_itlist;
|
indexed_tlist *subplan_itlist;
|
||||||
Index subvarno;
|
|
||||||
int rtoffset;
|
int rtoffset;
|
||||||
} fix_upper_expr_context;
|
} fix_upper_expr_context;
|
||||||
|
|
||||||
@ -73,7 +72,7 @@ static Node *fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context);
|
|||||||
static void set_join_references(Join *join, int rtoffset);
|
static void set_join_references(Join *join, int rtoffset);
|
||||||
static void set_inner_join_references(Plan *inner_plan,
|
static void set_inner_join_references(Plan *inner_plan,
|
||||||
indexed_tlist *outer_itlist);
|
indexed_tlist *outer_itlist);
|
||||||
static void set_upper_references(Plan *plan, Index subvarno, int rtoffset);
|
static void set_upper_references(Plan *plan, int rtoffset);
|
||||||
static indexed_tlist *build_tlist_index(List *tlist);
|
static indexed_tlist *build_tlist_index(List *tlist);
|
||||||
static Var *search_indexed_tlist_for_var(Var *var,
|
static Var *search_indexed_tlist_for_var(Var *var,
|
||||||
indexed_tlist *itlist,
|
indexed_tlist *itlist,
|
||||||
@ -90,7 +89,6 @@ static Node *fix_join_expr_mutator(Node *node,
|
|||||||
fix_join_expr_context *context);
|
fix_join_expr_context *context);
|
||||||
static Node *fix_upper_expr(Node *node,
|
static Node *fix_upper_expr(Node *node,
|
||||||
indexed_tlist *subplan_itlist,
|
indexed_tlist *subplan_itlist,
|
||||||
Index subvarno,
|
|
||||||
int rtoffset);
|
int rtoffset);
|
||||||
static Node *fix_upper_expr_mutator(Node *node,
|
static Node *fix_upper_expr_mutator(Node *node,
|
||||||
fix_upper_expr_context *context);
|
fix_upper_expr_context *context);
|
||||||
@ -345,7 +343,7 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
|
|||||||
break;
|
break;
|
||||||
case T_Agg:
|
case T_Agg:
|
||||||
case T_Group:
|
case T_Group:
|
||||||
set_upper_references(plan, (Index) 0, rtoffset);
|
set_upper_references(plan, rtoffset);
|
||||||
break;
|
break;
|
||||||
case T_Result:
|
case T_Result:
|
||||||
{
|
{
|
||||||
@ -354,11 +352,9 @@ set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
|
|||||||
/*
|
/*
|
||||||
* Result may or may not have a subplan; if not, it's more
|
* Result may or may not have a subplan; if not, it's more
|
||||||
* like a scan node than an upper node.
|
* like a scan node than an upper node.
|
||||||
*
|
|
||||||
* XXX why does Result use a different subvarno from Agg/Group?
|
|
||||||
*/
|
*/
|
||||||
if (splan->plan.lefttree != NULL)
|
if (splan->plan.lefttree != NULL)
|
||||||
set_upper_references(plan, (Index) OUTER, rtoffset);
|
set_upper_references(plan, rtoffset);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
splan->plan.targetlist =
|
splan->plan.targetlist =
|
||||||
@ -889,7 +885,7 @@ set_inner_join_references(Plan *inner_plan, indexed_tlist *outer_itlist)
|
|||||||
* the expression.
|
* the expression.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
set_upper_references(Plan *plan, Index subvarno, int rtoffset)
|
set_upper_references(Plan *plan, int rtoffset)
|
||||||
{
|
{
|
||||||
Plan *subplan = plan->lefttree;
|
Plan *subplan = plan->lefttree;
|
||||||
indexed_tlist *subplan_itlist;
|
indexed_tlist *subplan_itlist;
|
||||||
@ -909,7 +905,6 @@ set_upper_references(Plan *plan, Index subvarno, int rtoffset)
|
|||||||
|
|
||||||
newexpr = fix_upper_expr((Node *) tle->expr,
|
newexpr = fix_upper_expr((Node *) tle->expr,
|
||||||
subplan_itlist,
|
subplan_itlist,
|
||||||
subvarno,
|
|
||||||
rtoffset);
|
rtoffset);
|
||||||
tle = flatCopyTargetEntry(tle);
|
tle = flatCopyTargetEntry(tle);
|
||||||
tle->expr = (Expr *) newexpr;
|
tle->expr = (Expr *) newexpr;
|
||||||
@ -920,7 +915,6 @@ set_upper_references(Plan *plan, Index subvarno, int rtoffset)
|
|||||||
plan->qual = (List *)
|
plan->qual = (List *)
|
||||||
fix_upper_expr((Node *) plan->qual,
|
fix_upper_expr((Node *) plan->qual,
|
||||||
subplan_itlist,
|
subplan_itlist,
|
||||||
subvarno,
|
|
||||||
rtoffset);
|
rtoffset);
|
||||||
|
|
||||||
pfree(subplan_itlist);
|
pfree(subplan_itlist);
|
||||||
@ -1233,23 +1227,20 @@ fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
|
|||||||
*
|
*
|
||||||
* 'node': the tree to be fixed (a target item or qual)
|
* 'node': the tree to be fixed (a target item or qual)
|
||||||
* 'subplan_itlist': indexed target list for subplan
|
* 'subplan_itlist': indexed target list for subplan
|
||||||
* 'subvarno': varno to be assigned to all Vars
|
|
||||||
* 'rtoffset': how much to increment varnoold by
|
* 'rtoffset': how much to increment varnoold by
|
||||||
*
|
*
|
||||||
* The resulting tree is a copy of the original in which all Var nodes have
|
* The resulting tree is a copy of the original in which all Var nodes have
|
||||||
* varno = subvarno, varattno = resno of corresponding subplan target.
|
* varno = OUTER, varattno = resno of corresponding subplan target.
|
||||||
* The original tree is not modified.
|
* The original tree is not modified.
|
||||||
*/
|
*/
|
||||||
static Node *
|
static Node *
|
||||||
fix_upper_expr(Node *node,
|
fix_upper_expr(Node *node,
|
||||||
indexed_tlist *subplan_itlist,
|
indexed_tlist *subplan_itlist,
|
||||||
Index subvarno,
|
|
||||||
int rtoffset)
|
int rtoffset)
|
||||||
{
|
{
|
||||||
fix_upper_expr_context context;
|
fix_upper_expr_context context;
|
||||||
|
|
||||||
context.subplan_itlist = subplan_itlist;
|
context.subplan_itlist = subplan_itlist;
|
||||||
context.subvarno = subvarno;
|
|
||||||
context.rtoffset = rtoffset;
|
context.rtoffset = rtoffset;
|
||||||
return fix_upper_expr_mutator(node, &context);
|
return fix_upper_expr_mutator(node, &context);
|
||||||
}
|
}
|
||||||
@ -1267,7 +1258,7 @@ fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
|
|||||||
|
|
||||||
newvar = search_indexed_tlist_for_var(var,
|
newvar = search_indexed_tlist_for_var(var,
|
||||||
context->subplan_itlist,
|
context->subplan_itlist,
|
||||||
context->subvarno,
|
OUTER,
|
||||||
context->rtoffset);
|
context->rtoffset);
|
||||||
if (!newvar)
|
if (!newvar)
|
||||||
elog(ERROR, "variable not found in subplan target list");
|
elog(ERROR, "variable not found in subplan target list");
|
||||||
@ -1278,7 +1269,7 @@ fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
|
|||||||
{
|
{
|
||||||
newvar = search_indexed_tlist_for_non_var(node,
|
newvar = search_indexed_tlist_for_non_var(node,
|
||||||
context->subplan_itlist,
|
context->subplan_itlist,
|
||||||
context->subvarno);
|
OUTER);
|
||||||
if (newvar)
|
if (newvar)
|
||||||
return (Node *) newvar;
|
return (Node *) newvar;
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.249 2007/02/14 01:58:57 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.250 2007/02/22 23:44:25 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -2626,7 +2626,7 @@ get_rte_for_var(Var *var, int levelsup, deparse_context *context,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to find the relevant RTE in this rtable. In a plan tree, it's
|
* Try to find the relevant RTE in this rtable. In a plan tree, it's
|
||||||
* likely that varno is OUTER, INNER, or 0, in which case we try to use
|
* likely that varno is OUTER or INNER, in which case we try to use
|
||||||
* varnoold instead. If the Var references an expression computed by a
|
* varnoold instead. If the Var references an expression computed by a
|
||||||
* subplan, varnoold will be 0, and we fall back to looking at the special
|
* subplan, varnoold will be 0, and we fall back to looking at the special
|
||||||
* subplan RTEs.
|
* subplan RTEs.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user