identproj_v2_20121112.patch
text/x-patch
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
Series: patch v2
| File | + | − |
|---|---|---|
| src/backend/executor/nodeGroup.c | 12 | 3 |
| src/backend/executor/nodeResult.c | 8 | 2 |
| src/backend/executor/nodeWindowAgg.c | 8 | 2 |
| src/backend/optimizer/plan/setrefs.c | 15 | 1 |
| src/include/nodes/plannodes.h | 1 | 0 |
diff --git a/src/backend/executor/nodeGroup.c b/src/backend/executor/nodeGroup.c
index a8a1fe6..38037f9 100644
--- a/src/backend/executor/nodeGroup.c
+++ b/src/backend/executor/nodeGroup.c
@@ -110,7 +110,10 @@ ExecGroup(GroupState *node)
TupleTableSlot *result;
ExprDoneCond isDone;
- result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
+ if (node->ss.ps.ps_ProjInfo)
+ result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
+ else /* Assign outertuple for identity projection */
+ result = econtext->ecxt_outertuple;
if (isDone != ExprEndResult)
{
@@ -173,7 +176,10 @@ ExecGroup(GroupState *node)
TupleTableSlot *result;
ExprDoneCond isDone;
- result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
+ if (node->ss.ps.ps_ProjInfo)
+ result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
+ else /* Assign outertuple for identity projection */
+ result = econtext->ecxt_outertuple;
if (isDone != ExprEndResult)
{
@@ -244,7 +250,10 @@ ExecInitGroup(Group *node, EState *estate, int eflags)
* Initialize result tuple type and projection info.
*/
ExecAssignResultTypeFromTL(&grpstate->ss.ps);
- ExecAssignProjectionInfo(&grpstate->ss.ps, NULL);
+ if (node->plan.tlist_lower_congruent)
+ grpstate->ss.ps.ps_ProjInfo = NULL;
+ else
+ ExecAssignProjectionInfo(&grpstate->ss.ps, NULL);
grpstate->ss.ps.ps_TupFromTlist = false;
diff --git a/src/backend/executor/nodeResult.c b/src/backend/executor/nodeResult.c
index b51efd8..4a129d6 100644
--- a/src/backend/executor/nodeResult.c
+++ b/src/backend/executor/nodeResult.c
@@ -152,7 +152,10 @@ ExecResult(ResultState *node)
* the projection produces an empty set, in which case we must loop
* back to see if there are more outerPlan tuples.
*/
- resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
+ if (node->ps.ps_ProjInfo)
+ resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
+ else /* Assign outertuple for identity projection */
+ resultSlot = econtext->ecxt_outertuple;
if (isDone != ExprEndResult)
{
@@ -261,7 +264,10 @@ ExecInitResult(Result *node, EState *estate, int eflags)
* initialize tuple type and projection info
*/
ExecAssignResultTypeFromTL(&resstate->ps);
- ExecAssignProjectionInfo(&resstate->ps, NULL);
+ if (node->plan.tlist_lower_congruent)
+ resstate->ps.ps_ProjInfo = NULL;
+ else
+ ExecAssignProjectionInfo(&resstate->ps, NULL);
return resstate;
}
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index ade9b57..d34c45a 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -1373,7 +1373,10 @@ restart:
* evaluated with respect to that row.
*/
econtext->ecxt_outertuple = winstate->ss.ss_ScanTupleSlot;
- result = ExecProject(winstate->ss.ps.ps_ProjInfo, &isDone);
+ if (winstate->ss.ps.ps_ProjInfo)
+ result = ExecProject(winstate->ss.ps.ps_ProjInfo, &isDone);
+ else /* Assign outertuple for identity projection */
+ result = econtext->ecxt_outertuple;
if (isDone == ExprEndResult)
{
@@ -1490,7 +1493,10 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
* Initialize result tuple type and projection info.
*/
ExecAssignResultTypeFromTL(&winstate->ss.ps);
- ExecAssignProjectionInfo(&winstate->ss.ps, NULL);
+ if (node->plan.tlist_lower_congruent)
+ winstate->ss.ps.ps_ProjInfo = NULL;
+ else
+ ExecAssignProjectionInfo(&winstate->ss.ps, NULL);
winstate->ss.ps.ps_TupFromTlist = false;
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index ccd69fc..39d54ce 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -1184,6 +1184,7 @@ set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
indexed_tlist *subplan_itlist;
List *output_targetlist;
ListCell *l;
+ int nmatch = 0;
subplan_itlist = build_tlist_index(subplan->targetlist);
@@ -1214,12 +1215,25 @@ set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
subplan_itlist,
OUTER_VAR,
rtoffset);
+
+ if (IsA(newexpr, Var) && ((Var*)newexpr)->varattno == nmatch + 1)
+ nmatch++;
+
tle = flatCopyTargetEntry(tle);
tle->expr = (Expr *) newexpr;
output_targetlist = lappend(output_targetlist, tle);
}
- plan->targetlist = output_targetlist;
+ /*
+ * Directly refer to the lower tuple slot on projection if the all elements
+ * in target list exactly correspond to the ones in the lower tlist.
+ */
+ plan->tlist_lower_congruent =
+ (nmatch == list_length(plan->targetlist) &&
+ nmatch == list_length(subplan->targetlist));
+
+ plan->targetlist = output_targetlist;
+
plan->qual = (List *)
fix_upper_expr(root,
(Node *) plan->qual,
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index fb9a863..9e7729c 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -106,6 +106,7 @@ typedef struct Plan
* Common structural data for all Plan types.
*/
List *targetlist; /* target list to be computed at this node */
+ bool tlist_lower_congruent; /* target list is lower-congruent */
List *qual; /* implicitly-ANDed qual conditions */
struct Plan *lefttree; /* input plan tree(s) */
struct Plan *righttree;