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

Commitd5478c3

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 parent5dfc66b commitd5478c3

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
@@ -726,6 +726,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
726726
erm->relation=relation;
727727
erm->rti=rc->rti;
728728
erm->prti=rc->prti;
729+
erm->rowmarkId=rc->rowmarkId;
729730
erm->markType=rc->markType;
730731
erm->noWait=rc->noWait;
731732
ItemPointerSetInvalid(&(erm->curCtid));
@@ -1373,23 +1374,29 @@ ExecBuildAuxRowMark(ExecRowMark *erm, List *targetlist)
13731374
/* if child rel, need tableoid */
13741375
if (erm->rti!=erm->prti)
13751376
{
1376-
snprintf(resname,sizeof(resname),"tableoid%u",erm->prti);
1377+
snprintf(resname,sizeof(resname),"tableoid%u",erm->rowmarkId);
13771378
aerm->toidAttNo=ExecFindJunkAttributeInTlist(targetlist,
13781379
resname);
1380+
if (!AttributeNumberIsValid(aerm->toidAttNo))
1381+
elog(ERROR,"could not find junk %s column",resname);
13791382
}
13801383

13811384
/* always need ctid for real relations */
1382-
snprintf(resname,sizeof(resname),"ctid%u",erm->prti);
1385+
snprintf(resname,sizeof(resname),"ctid%u",erm->rowmarkId);
13831386
aerm->ctidAttNo=ExecFindJunkAttributeInTlist(targetlist,
13841387
resname);
1388+
if (!AttributeNumberIsValid(aerm->ctidAttNo))
1389+
elog(ERROR,"could not find junk %s column",resname);
13851390
}
13861391
else
13871392
{
13881393
Assert(erm->markType==ROW_MARK_COPY);
13891394

1390-
snprintf(resname,sizeof(resname),"wholerow%u",erm->prti);
1395+
snprintf(resname,sizeof(resname),"wholerow%u",erm->rowmarkId);
13911396
aerm->wholeAttNo=ExecFindJunkAttributeInTlist(targetlist,
13921397
resname);
1398+
if (!AttributeNumberIsValid(aerm->wholeAttNo))
1399+
elog(ERROR,"could not find junk %s column",resname);
13931400
}
13941401

13951402
returnaerm;

‎src/backend/nodes/copyfuncs.c

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

857857
COPY_SCALAR_FIELD(rti);
858858
COPY_SCALAR_FIELD(prti);
859+
COPY_SCALAR_FIELD(rowmarkId);
859860
COPY_SCALAR_FIELD(markType);
860861
COPY_SCALAR_FIELD(noWait);
861862
COPY_SCALAR_FIELD(isParent);

‎src/backend/nodes/outfuncs.c

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

757757
WRITE_UINT_FIELD(rti);
758758
WRITE_UINT_FIELD(prti);
759+
WRITE_UINT_FIELD(rowmarkId);
759760
WRITE_ENUM_FIELD(markType,RowMarkType);
760761
WRITE_BOOL_FIELD(noWait);
761762
WRITE_BOOL_FIELD(isParent);
@@ -1524,6 +1525,7 @@ _outPlannerGlobal(StringInfo str, PlannerGlobal *node)
15241525
WRITE_NODE_FIELD(relationOids);
15251526
WRITE_NODE_FIELD(invalItems);
15261527
WRITE_UINT_FIELD(lastPHId);
1528+
WRITE_UINT_FIELD(lastRowMarkId);
15271529
WRITE_BOOL_FIELD(transientPlan);
15281530
}
15291531

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

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

170171
/* Determine what fraction of the plan is likely to be scanned */
@@ -1852,6 +1853,7 @@ preprocess_rowmarks(PlannerInfo *root)
18521853

18531854
newrc=makeNode(PlanRowMark);
18541855
newrc->rti=newrc->prti=rc->rti;
1856+
newrc->rowmarkId=++(root->glob->lastRowMarkId);
18551857
if (rc->forUpdate)
18561858
newrc->markType=ROW_MARK_EXCLUSIVE;
18571859
else
@@ -1877,6 +1879,7 @@ preprocess_rowmarks(PlannerInfo *root)
18771879

18781880
newrc=makeNode(PlanRowMark);
18791881
newrc->rti=newrc->prti=i;
1882+
newrc->rowmarkId=++(root->glob->lastRowMarkId);
18801883
/* real tables support REFERENCE, anything else needs COPY */
18811884
if (rte->rtekind==RTE_RELATION)
18821885
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
@@ -132,7 +132,7 @@ preprocess_targetlist(PlannerInfo *root, List *tlist)
132132
TIDOID,
133133
-1,
134134
0);
135-
snprintf(resname,sizeof(resname),"ctid%u",rc->rti);
135+
snprintf(resname,sizeof(resname),"ctid%u",rc->rowmarkId);
136136
tle=makeTargetEntry((Expr*)var,
137137
list_length(tlist)+1,
138138
pstrdup(resname),
@@ -147,7 +147,7 @@ preprocess_targetlist(PlannerInfo *root, List *tlist)
147147
OIDOID,
148148
-1,
149149
0);
150-
snprintf(resname,sizeof(resname),"tableoid%u",rc->rti);
150+
snprintf(resname,sizeof(resname),"tableoid%u",rc->rowmarkId);
151151
tle=makeTargetEntry((Expr*)var,
152152
list_length(tlist)+1,
153153
pstrdup(resname),
@@ -161,7 +161,7 @@ preprocess_targetlist(PlannerInfo *root, List *tlist)
161161
var=makeWholeRowVar(rt_fetch(rc->rti,range_table),
162162
rc->rti,
163163
0);
164-
snprintf(resname,sizeof(resname),"wholerow%u",rc->rti);
164+
snprintf(resname,sizeof(resname),"wholerow%u",rc->rowmarkId);
165165
tle=makeTargetEntry((Expr*)var,
166166
list_length(tlist)+1,
167167
pstrdup(resname),

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

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

12891289
newrc->rti=childRTindex;
12901290
newrc->prti=rti;
1291+
newrc->rowmarkId=oldrc->rowmarkId;
12911292
newrc->markType=oldrc->markType;
12921293
newrc->noWait=oldrc->noWait;
12931294
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
@@ -701,7 +701,11 @@ typedef enum RowMarkType
701701
* The tableoid column is only present for an inheritance hierarchy.
702702
* When markType == ROW_MARK_COPY, there is instead a single column named
703703
*wholerow%uwhole-row value of relation
704-
* In all three cases, %u represents the parent rangetable index (prti).
704+
* In all three cases, %u represents the rowmark ID number (rowmarkId).
705+
* This number is unique within a plan tree, except that child relation
706+
* entries copy their parent's rowmarkId. (Assigning unique numbers
707+
* means we needn't renumber rowmarkIds when flattening subqueries, which
708+
* would require finding and renaming the resjunk columns as well.)
705709
* Note this means that all tables in an inheritance hierarchy share the
706710
* same resjunk column names. However, in an inherited UPDATE/DELETE the
707711
* columns could have different physical column numbers in each subplan.
@@ -711,6 +715,7 @@ typedef struct PlanRowMark
711715
NodeTagtype;
712716
Indexrti;/* range table index of markable relation */
713717
Indexprti;/* range table index of parent relation */
718+
IndexrowmarkId;/* unique identifier for resjunk columns */
714719
RowMarkTypemarkType;/* see enum above */
715720
boolnoWait;/* NOWAIT option */
716721
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