summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/executor/execMain.c13
-rw-r--r--src/backend/nodes/copyfuncs.c1
-rw-r--r--src/backend/nodes/outfuncs.c2
-rw-r--r--src/backend/optimizer/plan/planner.c3
-rw-r--r--src/backend/optimizer/plan/setrefs.c2
-rw-r--r--src/backend/optimizer/prep/preptlist.c6
-rw-r--r--src/backend/optimizer/prep/prepunion.c1
-rw-r--r--src/include/nodes/execnodes.h1
-rw-r--r--src/include/nodes/plannodes.h7
-rw-r--r--src/include/nodes/relation.h2
10 files changed, 30 insertions, 8 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 6d4a77328a4..c477314efa3 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -726,6 +726,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
erm->relation = relation;
erm->rti = rc->rti;
erm->prti = rc->prti;
+ erm->rowmarkId = rc->rowmarkId;
erm->markType = rc->markType;
erm->noWait = rc->noWait;
ItemPointerSetInvalid(&(erm->curCtid));
@@ -1373,23 +1374,29 @@ ExecBuildAuxRowMark(ExecRowMark *erm, List *targetlist)
/* if child rel, need tableoid */
if (erm->rti != erm->prti)
{
- snprintf(resname, sizeof(resname), "tableoid%u", erm->prti);
+ snprintf(resname, sizeof(resname), "tableoid%u", erm->rowmarkId);
aerm->toidAttNo = ExecFindJunkAttributeInTlist(targetlist,
resname);
+ if (!AttributeNumberIsValid(aerm->toidAttNo))
+ elog(ERROR, "could not find junk %s column", resname);
}
/* always need ctid for real relations */
- snprintf(resname, sizeof(resname), "ctid%u", erm->prti);
+ snprintf(resname, sizeof(resname), "ctid%u", erm->rowmarkId);
aerm->ctidAttNo = ExecFindJunkAttributeInTlist(targetlist,
resname);
+ if (!AttributeNumberIsValid(aerm->ctidAttNo))
+ elog(ERROR, "could not find junk %s column", resname);
}
else
{
Assert(erm->markType == ROW_MARK_COPY);
- snprintf(resname, sizeof(resname), "wholerow%u", erm->prti);
+ snprintf(resname, sizeof(resname), "wholerow%u", erm->rowmarkId);
aerm->wholeAttNo = ExecFindJunkAttributeInTlist(targetlist,
resname);
+ if (!AttributeNumberIsValid(aerm->wholeAttNo))
+ elog(ERROR, "could not find junk %s column", resname);
}
return aerm;
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 0b2aa3dfff8..778c53063ec 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -856,6 +856,7 @@ _copyPlanRowMark(PlanRowMark *from)
COPY_SCALAR_FIELD(rti);
COPY_SCALAR_FIELD(prti);
+ COPY_SCALAR_FIELD(rowmarkId);
COPY_SCALAR_FIELD(markType);
COPY_SCALAR_FIELD(noWait);
COPY_SCALAR_FIELD(isParent);
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 032150e1bb7..15a9aa2f939 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -756,6 +756,7 @@ _outPlanRowMark(StringInfo str, PlanRowMark *node)
WRITE_UINT_FIELD(rti);
WRITE_UINT_FIELD(prti);
+ WRITE_UINT_FIELD(rowmarkId);
WRITE_ENUM_FIELD(markType, RowMarkType);
WRITE_BOOL_FIELD(noWait);
WRITE_BOOL_FIELD(isParent);
@@ -1524,6 +1525,7 @@ _outPlannerGlobal(StringInfo str, PlannerGlobal *node)
WRITE_NODE_FIELD(relationOids);
WRITE_NODE_FIELD(invalItems);
WRITE_UINT_FIELD(lastPHId);
+ WRITE_UINT_FIELD(lastRowMarkId);
WRITE_BOOL_FIELD(transientPlan);
}
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 45ba902fbab..55206573c72 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -165,6 +165,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
glob->relationOids = NIL;
glob->invalItems = NIL;
glob->lastPHId = 0;
+ glob->lastRowMarkId = 0;
glob->transientPlan = false;
/* Determine what fraction of the plan is likely to be scanned */
@@ -1852,6 +1853,7 @@ preprocess_rowmarks(PlannerInfo *root)
newrc = makeNode(PlanRowMark);
newrc->rti = newrc->prti = rc->rti;
+ newrc->rowmarkId = ++(root->glob->lastRowMarkId);
if (rc->forUpdate)
newrc->markType = ROW_MARK_EXCLUSIVE;
else
@@ -1877,6 +1879,7 @@ preprocess_rowmarks(PlannerInfo *root)
newrc = makeNode(PlanRowMark);
newrc->rti = newrc->prti = i;
+ newrc->rowmarkId = ++(root->glob->lastRowMarkId);
/* real tables support REFERENCE, anything else needs COPY */
if (rte->rtekind == RTE_RELATION)
newrc->markType = ROW_MARK_REFERENCE;
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 70be2e66f2d..2618ef14a83 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -252,7 +252,7 @@ set_plan_references(PlannerGlobal *glob, Plan *plan,
newrc = (PlanRowMark *) palloc(sizeof(PlanRowMark));
memcpy(newrc, rc, sizeof(PlanRowMark));
- /* adjust indexes */
+ /* adjust indexes ... but *not* the rowmarkId */
newrc->rti += rtoffset;
newrc->prti += rtoffset;
diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c
index 7a09d1f8309..425d80c6244 100644
--- a/src/backend/optimizer/prep/preptlist.c
+++ b/src/backend/optimizer/prep/preptlist.c
@@ -132,7 +132,7 @@ preprocess_targetlist(PlannerInfo *root, List *tlist)
TIDOID,
-1,
0);
- snprintf(resname, sizeof(resname), "ctid%u", rc->rti);
+ snprintf(resname, sizeof(resname), "ctid%u", rc->rowmarkId);
tle = makeTargetEntry((Expr *) var,
list_length(tlist) + 1,
pstrdup(resname),
@@ -147,7 +147,7 @@ preprocess_targetlist(PlannerInfo *root, List *tlist)
OIDOID,
-1,
0);
- snprintf(resname, sizeof(resname), "tableoid%u", rc->rti);
+ snprintf(resname, sizeof(resname), "tableoid%u", rc->rowmarkId);
tle = makeTargetEntry((Expr *) var,
list_length(tlist) + 1,
pstrdup(resname),
@@ -161,7 +161,7 @@ preprocess_targetlist(PlannerInfo *root, List *tlist)
var = makeWholeRowVar(rt_fetch(rc->rti, range_table),
rc->rti,
0);
- snprintf(resname, sizeof(resname), "wholerow%u", rc->rti);
+ snprintf(resname, sizeof(resname), "wholerow%u", rc->rowmarkId);
tle = makeTargetEntry((Expr *) var,
list_length(tlist) + 1,
pstrdup(resname),
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index 35f9f980e90..cabc93d5df9 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -1288,6 +1288,7 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
newrc->rti = childRTindex;
newrc->prti = rti;
+ newrc->rowmarkId = oldrc->rowmarkId;
newrc->markType = oldrc->markType;
newrc->noWait = oldrc->noWait;
newrc->isParent = false;
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index fda44255b08..ac0de093f16 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -417,6 +417,7 @@ typedef struct ExecRowMark
Relation relation; /* opened and suitably locked relation */
Index rti; /* its range table index */
Index prti; /* parent range table index, if child */
+ Index rowmarkId; /* unique identifier for resjunk columns */
RowMarkType markType; /* see enum in nodes/plannodes.h */
bool noWait; /* NOWAIT option */
ItemPointerData curCtid; /* ctid of currently locked tuple, if any */
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index e14257932e6..729e35557d8 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -701,7 +701,11 @@ typedef enum RowMarkType
* The tableoid column is only present for an inheritance hierarchy.
* When markType == ROW_MARK_COPY, there is instead a single column named
* wholerow%u whole-row value of relation
- * In all three cases, %u represents the parent rangetable index (prti).
+ * In all three cases, %u represents the rowmark ID number (rowmarkId).
+ * This number is unique within a plan tree, except that child relation
+ * entries copy their parent's rowmarkId. (Assigning unique numbers
+ * means we needn't renumber rowmarkIds when flattening subqueries, which
+ * would require finding and renaming the resjunk columns as well.)
* Note this means that all tables in an inheritance hierarchy share the
* same resjunk column names. However, in an inherited UPDATE/DELETE the
* columns could have different physical column numbers in each subplan.
@@ -711,6 +715,7 @@ typedef struct PlanRowMark
NodeTag type;
Index rti; /* range table index of markable relation */
Index prti; /* range table index of parent relation */
+ Index rowmarkId; /* unique identifier for resjunk columns */
RowMarkType markType; /* see enum above */
bool noWait; /* NOWAIT option */
bool isParent; /* true if this is a "dummy" parent entry */
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index a3678a5b58d..f109a1de520 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -82,6 +82,8 @@ typedef struct PlannerGlobal
Index lastPHId; /* highest PlaceHolderVar ID assigned */
+ Index lastRowMarkId; /* highest PlanRowMark ID assigned */
+
bool transientPlan; /* redo plan when TransactionXmin changes? */
} PlannerGlobal;