identproj_v1_20120913.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 v1
| File | + | − |
|---|---|---|
| src/backend/executor/execQual.c | 5 | 0 |
| src/backend/executor/execUtils.c | 11 | 0 |
| src/backend/executor/nodeAgg.c | 2 | 0 |
| src/backend/executor/nodeGroup.c | 1 | 0 |
| src/backend/executor/nodeModifyTable.c | 1 | 1 |
| src/backend/executor/nodeResult.c | 1 | 0 |
| src/backend/executor/nodeSubplan.c | 2 | 0 |
| src/backend/executor/nodeWindowAgg.c | 1 | 0 |
| src/backend/optimizer/plan/setrefs.c | 15 | 2 |
| src/include/executor/executor.h | 1 | 0 |
| src/include/nodes/execnodes.h | 3 | 0 |
| src/include/nodes/plannodes.h | 1 | 0 |
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 56b106a..da1113f 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -5360,6 +5360,11 @@ ExecProject(ProjectionInfo *projInfo, ExprDoneCond *isDone)
if (isDone)
*isDone = ExprSingleResult;
+ /* Simply return outer tuple for identity projection */
+ if (projInfo->pi_identity)
+ return econtext->ecxt_outertuple;
+
+
/*
* Clear any former contents of the result slot. This makes it safe for
* us to use the slot's Datum/isnull arrays as workspace. (Also, we can
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 0bbd0d4..38d259a 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -485,6 +485,9 @@ ExecGetResultType(PlanState *planstate)
* ensured that tuple slot has a descriptor matching the tlist!) Note that
* the given tlist should be a list of ExprState nodes, not Expr nodes.
*
+ * This ProjectionInfo is marked as identity projection and passes through the
+ * outer tupleslot in ExecProject() when lower_congruent is true.
+ *
* inputDesc can be NULL, but if it is not, we check to see whether simple
* Vars in the tlist match the descriptor. It is important to provide
* inputDesc for relation-scan plan nodes, as a cross check that the relation
@@ -494,6 +497,7 @@ ExecGetResultType(PlanState *planstate)
*/
ProjectionInfo *
ExecBuildProjectionInfo(List *targetList,
+ bool lower_congruent,
ExprContext *econtext,
TupleTableSlot *slot,
TupleDesc inputDesc)
@@ -511,6 +515,12 @@ ExecBuildProjectionInfo(List *targetList,
projInfo->pi_exprContext = econtext;
projInfo->pi_slot = slot;
+ projInfo->pi_identity = lower_congruent;
+
+ /* identity projection does not need further fields */
+ if (lower_congruent)
+ return projInfo;
+
/* since these are all int arrays, we need do just one palloc */
workspace = (int *) palloc(len * 3 * sizeof(int));
projInfo->pi_varSlotOffsets = varSlotOffsets = workspace;
@@ -676,6 +686,7 @@ ExecAssignProjectionInfo(PlanState *planstate,
{
planstate->ps_ProjInfo =
ExecBuildProjectionInfo(planstate->targetlist,
+ planstate->tlist_lower_congruent,
planstate->ps_ExprContext,
planstate->ps_ResultTupleSlot,
inputDesc);
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 38c7141..6e84aa7 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -1449,6 +1449,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
aggstate->ss.ps.qual = (List *)
ExecInitExpr((Expr *) node->plan.qual,
(PlanState *) aggstate);
+ aggstate->ss.ps.tlist_lower_congruent = node->plan.tlist_lower_congruent;
/*
* initialize child nodes
@@ -1748,6 +1749,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
/* Set up projection info for evaluation */
peraggstate->evalproj = ExecBuildProjectionInfo(aggrefstate->args,
+ false,
aggstate->tmpcontext,
peraggstate->evalslot,
NULL);
diff --git a/src/backend/executor/nodeGroup.c b/src/backend/executor/nodeGroup.c
index a8a1fe6..048c265 100644
--- a/src/backend/executor/nodeGroup.c
+++ b/src/backend/executor/nodeGroup.c
@@ -229,6 +229,7 @@ ExecInitGroup(Group *node, EState *estate, int eflags)
grpstate->ss.ps.qual = (List *)
ExecInitExpr((Expr *) node->plan.qual,
(PlanState *) grpstate);
+ grpstate->ss.ps.tlist_lower_congruent = node->plan.tlist_lower_congruent;
/*
* initialize child nodes
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 26a59d0..aa95004 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -1006,7 +1006,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
rliststate = (List *) ExecInitExpr((Expr *) rlist, &mtstate->ps);
resultRelInfo->ri_projectReturning =
- ExecBuildProjectionInfo(rliststate, econtext, slot,
+ ExecBuildProjectionInfo(rliststate, false, econtext, slot,
resultRelInfo->ri_RelationDesc->rd_att);
resultRelInfo++;
}
diff --git a/src/backend/executor/nodeResult.c b/src/backend/executor/nodeResult.c
index b51efd8..cd6c8f2 100644
--- a/src/backend/executor/nodeResult.c
+++ b/src/backend/executor/nodeResult.c
@@ -246,6 +246,7 @@ ExecInitResult(Result *node, EState *estate, int eflags)
(PlanState *) resstate);
resstate->resconstantqual = ExecInitExpr((Expr *) node->resconstantqual,
(PlanState *) resstate);
+ resstate->ps.tlist_lower_congruent = node->plan.tlist_lower_congruent;
/*
* initialize child nodes
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index d615b78..5612e93 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -866,6 +866,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
slot = ExecInitExtraTupleSlot(estate);
ExecSetSlotDescriptor(slot, tupDesc);
sstate->projLeft = ExecBuildProjectionInfo(lefttlist,
+ false,
NULL,
slot,
NULL);
@@ -874,6 +875,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
slot = ExecInitExtraTupleSlot(estate);
ExecSetSlotDescriptor(slot, tupDesc);
sstate->projRight = ExecBuildProjectionInfo(righttlist,
+ false,
sstate->innerecontext,
slot,
NULL);
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index ade9b57..dd557a8 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -1457,6 +1457,7 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
winstate->ss.ps.targetlist = (List *)
ExecInitExpr((Expr *) node->plan.targetlist,
(PlanState *) winstate);
+ winstate->ss.ps.tlist_lower_congruent = node->plan.tlist_lower_congruent;
/*
* WindowAgg nodes never have quals, since they can only occur at the
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index ccd69fc..776ce64 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -26,7 +26,6 @@
#include "utils/lsyscache.h"
#include "utils/syscache.h"
-
typedef struct
{
Index varno; /* RT index of Var */
@@ -1184,6 +1183,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 +1214,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/executor/executor.h b/src/include/executor/executor.h
index 075bbe8..f705262 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -328,6 +328,7 @@ extern void ExecAssignResultType(PlanState *planstate, TupleDesc tupDesc);
extern void ExecAssignResultTypeFromTL(PlanState *planstate);
extern TupleDesc ExecGetResultType(PlanState *planstate);
extern ProjectionInfo *ExecBuildProjectionInfo(List *targetList,
+ bool tlist_lower_congruent,
ExprContext *econtext,
TupleTableSlot *slot,
TupleDesc inputDesc);
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index fec07b8..d3b0bc6 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -220,6 +220,7 @@ typedef struct ReturnSetInfo
* slot slot to place projection result in
* itemIsDone workspace array for ExecProject
* directMap true if varOutputCols[] is an identity map
+ * identity true if this is an identity projection
* numSimpleVars number of simple Vars found in original tlist
* varSlotOffsets array indicating which slot each simple Var is from
* varNumbers array containing input attr numbers of simple Vars
@@ -237,6 +238,7 @@ typedef struct ProjectionInfo
TupleTableSlot *pi_slot;
ExprDoneCond *pi_itemIsDone;
bool pi_directMap;
+ bool pi_identity;
int pi_numSimpleVars;
int *pi_varSlotOffsets;
int *pi_varNumbers;
@@ -987,6 +989,7 @@ typedef struct PlanState
* subPlan list, which does not exist in the plan tree).
*/
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 PlanState *lefttree; /* input plan tree(s) */
struct PlanState *righttree;
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;