Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite617f0d

Browse files
committed
Fix improper matching of resjunk column names for FOR UPDATE in subselect.
Flattening of subquery range tables during setrefs.c could lead to therangetable indexes in PlanRowMark nodes not matching up with the columnnames previously assigned to the corresponding resjunk ctid (resp. tableoidor wholerow) columns. Typical symptom would be either a "cannot extractsystem attribute from virtual tuple" error or an Assert failure. Thiswasn't a problem before 9.0 because we didn't support FOR UPDATE below thetop query level, and so the final flattening could never renumber an RTEthat was relevant to FOR UPDATE. Fix by using a plan-tree-wide uniquenumber for each PlanRowMark to label the associated resjunk columns, sothat the number need not change during flattening.Per report from David Johnston (though I'm darned if I can see how this gotpast initial testing of the relevant code). Back-patch to 9.0.
1 parent5478f99 commite617f0d

File tree

10 files changed

+30
-8
lines changed

10 files changed

+30
-8
lines changed

‎src/backend/executor/execMain.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
742742
erm->relation=relation;
743743
erm->rti=rc->rti;
744744
erm->prti=rc->prti;
745+
erm->rowmarkId=rc->rowmarkId;
745746
erm->markType=rc->markType;
746747
erm->noWait=rc->noWait;
747748
ItemPointerSetInvalid(&(erm->curCtid));
@@ -1425,23 +1426,29 @@ ExecBuildAuxRowMark(ExecRowMark *erm, List *targetlist)
14251426
/* if child rel, need tableoid */
14261427
if (erm->rti!=erm->prti)
14271428
{
1428-
snprintf(resname,sizeof(resname),"tableoid%u",erm->prti);
1429+
snprintf(resname,sizeof(resname),"tableoid%u",erm->rowmarkId);
14291430
aerm->toidAttNo=ExecFindJunkAttributeInTlist(targetlist,
14301431
resname);
1432+
if (!AttributeNumberIsValid(aerm->toidAttNo))
1433+
elog(ERROR,"could not find junk %s column",resname);
14311434
}
14321435

14331436
/* always need ctid for real relations */
1434-
snprintf(resname,sizeof(resname),"ctid%u",erm->prti);
1437+
snprintf(resname,sizeof(resname),"ctid%u",erm->rowmarkId);
14351438
aerm->ctidAttNo=ExecFindJunkAttributeInTlist(targetlist,
14361439
resname);
1440+
if (!AttributeNumberIsValid(aerm->ctidAttNo))
1441+
elog(ERROR,"could not find junk %s column",resname);
14371442
}
14381443
else
14391444
{
14401445
Assert(erm->markType==ROW_MARK_COPY);
14411446

1442-
snprintf(resname,sizeof(resname),"wholerow%u",erm->prti);
1447+
snprintf(resname,sizeof(resname),"wholerow%u",erm->rowmarkId);
14431448
aerm->wholeAttNo=ExecFindJunkAttributeInTlist(targetlist,
14441449
resname);
1450+
if (!AttributeNumberIsValid(aerm->wholeAttNo))
1451+
elog(ERROR,"could not find junk %s column",resname);
14451452
}
14461453

14471454
returnaerm;

‎src/backend/nodes/copyfuncs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -906,6 +906,7 @@ _copyPlanRowMark(PlanRowMark *from)
906906

907907
COPY_SCALAR_FIELD(rti);
908908
COPY_SCALAR_FIELD(prti);
909+
COPY_SCALAR_FIELD(rowmarkId);
909910
COPY_SCALAR_FIELD(markType);
910911
COPY_SCALAR_FIELD(noWait);
911912
COPY_SCALAR_FIELD(isParent);

‎src/backend/nodes/outfuncs.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,7 @@ _outPlanRowMark(StringInfo str, PlanRowMark *node)
808808

809809
WRITE_UINT_FIELD(rti);
810810
WRITE_UINT_FIELD(prti);
811+
WRITE_UINT_FIELD(rowmarkId);
811812
WRITE_ENUM_FIELD(markType,RowMarkType);
812813
WRITE_BOOL_FIELD(noWait);
813814
WRITE_BOOL_FIELD(isParent);
@@ -1609,6 +1610,7 @@ _outPlannerGlobal(StringInfo str, PlannerGlobal *node)
16091610
WRITE_NODE_FIELD(relationOids);
16101611
WRITE_NODE_FIELD(invalItems);
16111612
WRITE_UINT_FIELD(lastPHId);
1613+
WRITE_UINT_FIELD(lastRowMarkId);
16121614
WRITE_BOOL_FIELD(transientPlan);
16131615
}
16141616

‎src/backend/optimizer/plan/planner.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
166166
glob->relationOids=NIL;
167167
glob->invalItems=NIL;
168168
glob->lastPHId=0;
169+
glob->lastRowMarkId=0;
169170
glob->transientPlan= false;
170171

171172
/* Determine what fraction of the plan is likely to be scanned */
@@ -1885,6 +1886,7 @@ preprocess_rowmarks(PlannerInfo *root)
18851886

18861887
newrc=makeNode(PlanRowMark);
18871888
newrc->rti=newrc->prti=rc->rti;
1889+
newrc->rowmarkId=++(root->glob->lastRowMarkId);
18881890
if (rc->forUpdate)
18891891
newrc->markType=ROW_MARK_EXCLUSIVE;
18901892
else
@@ -1910,6 +1912,7 @@ preprocess_rowmarks(PlannerInfo *root)
19101912

19111913
newrc=makeNode(PlanRowMark);
19121914
newrc->rti=newrc->prti=i;
1915+
newrc->rowmarkId=++(root->glob->lastRowMarkId);
19131916
/* real tables support REFERENCE, anything else needs COPY */
19141917
if (rte->rtekind==RTE_RELATION)
19151918
newrc->markType=ROW_MARK_REFERENCE;

‎src/backend/optimizer/plan/setrefs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ set_plan_references(PlannerGlobal *glob, Plan *plan,
252252
newrc= (PlanRowMark*)palloc(sizeof(PlanRowMark));
253253
memcpy(newrc,rc,sizeof(PlanRowMark));
254254

255-
/* adjust indexes */
255+
/* adjust indexes... but *not* the rowmarkId*/
256256
newrc->rti+=rtoffset;
257257
newrc->prti+=rtoffset;
258258

‎src/backend/optimizer/prep/preptlist.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ preprocess_targetlist(PlannerInfo *root, List *tlist)
102102
-1,
103103
InvalidOid,
104104
0);
105-
snprintf(resname,sizeof(resname),"ctid%u",rc->rti);
105+
snprintf(resname,sizeof(resname),"ctid%u",rc->rowmarkId);
106106
tle=makeTargetEntry((Expr*)var,
107107
list_length(tlist)+1,
108108
pstrdup(resname),
@@ -118,7 +118,7 @@ preprocess_targetlist(PlannerInfo *root, List *tlist)
118118
-1,
119119
InvalidOid,
120120
0);
121-
snprintf(resname,sizeof(resname),"tableoid%u",rc->rti);
121+
snprintf(resname,sizeof(resname),"tableoid%u",rc->rowmarkId);
122122
tle=makeTargetEntry((Expr*)var,
123123
list_length(tlist)+1,
124124
pstrdup(resname),
@@ -132,7 +132,7 @@ preprocess_targetlist(PlannerInfo *root, List *tlist)
132132
var=makeWholeRowVar(rt_fetch(rc->rti,range_table),
133133
rc->rti,
134134
0);
135-
snprintf(resname,sizeof(resname),"wholerow%u",rc->rti);
135+
snprintf(resname,sizeof(resname),"wholerow%u",rc->rowmarkId);
136136
tle=makeTargetEntry((Expr*)var,
137137
list_length(tlist)+1,
138138
pstrdup(resname),

‎src/backend/optimizer/prep/prepunion.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,6 +1294,7 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
12941294

12951295
newrc->rti=childRTindex;
12961296
newrc->prti=rti;
1297+
newrc->rowmarkId=oldrc->rowmarkId;
12971298
newrc->markType=oldrc->markType;
12981299
newrc->noWait=oldrc->noWait;
12991300
newrc->isParent= false;

‎src/include/nodes/execnodes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ typedef struct ExecRowMark
417417
Relationrelation;/* opened and suitably locked relation */
418418
Indexrti;/* its range table index */
419419
Indexprti;/* parent range table index, if child */
420+
IndexrowmarkId;/* unique identifier for resjunk columns */
420421
RowMarkTypemarkType;/* see enum in nodes/plannodes.h */
421422
boolnoWait;/* NOWAIT option */
422423
ItemPointerDatacurCtid;/* ctid of currently locked tuple, if any */

‎src/include/nodes/plannodes.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,11 @@ typedef enum RowMarkType
749749
* The tableoid column is only present for an inheritance hierarchy.
750750
* When markType == ROW_MARK_COPY, there is instead a single column named
751751
*wholerow%uwhole-row value of relation
752-
* In all three cases, %u represents the parent rangetable index (prti).
752+
* In all three cases, %u represents the rowmark ID number (rowmarkId).
753+
* This number is unique within a plan tree, except that child relation
754+
* entries copy their parent's rowmarkId. (Assigning unique numbers
755+
* means we needn't renumber rowmarkIds when flattening subqueries, which
756+
* would require finding and renaming the resjunk columns as well.)
753757
* Note this means that all tables in an inheritance hierarchy share the
754758
* same resjunk column names. However, in an inherited UPDATE/DELETE the
755759
* columns could have different physical column numbers in each subplan.
@@ -759,6 +763,7 @@ typedef struct PlanRowMark
759763
NodeTagtype;
760764
Indexrti;/* range table index of markable relation */
761765
Indexprti;/* range table index of parent relation */
766+
IndexrowmarkId;/* unique identifier for resjunk columns */
762767
RowMarkTypemarkType;/* see enum above */
763768
boolnoWait;/* NOWAIT option */
764769
boolisParent;/* true if this is a "dummy" parent entry */

‎src/include/nodes/relation.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ typedef struct PlannerGlobal
8282

8383
IndexlastPHId;/* highest PlaceHolderVar ID assigned */
8484

85+
IndexlastRowMarkId;/* highest PlanRowMark ID assigned */
86+
8587
booltransientPlan;/* redo plan when TransactionXmin changes? */
8688
}PlannerGlobal;
8789

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp