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

Commitf593f62

Browse files
committed
Fix a couple of places in execMain that erroneously assumed that SELECT FOR
UPDATE/SHARE couldn't occur as a subquery in a query with a non-SELECTtop-level operation. Symptoms included outright failure (as in report fromMark Mielke) and silently neglecting to take the requested row locks.Back-patch to 8.3, because the visible failure in the INSERT ... SELECT caseis a regression from 8.2. I'm a bit hesitant to back-patch further given thelack of field complaints.
1 parent819b49a commitf593f62

File tree

1 file changed

+52
-35
lines changed

1 file changed

+52
-35
lines changed

‎src/backend/executor/execMain.c

Lines changed: 52 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
*
2727
*
2828
* IDENTIFICATION
29-
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.305 2008/03/28 00:21:55 tgl Exp $
29+
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.306 2008/04/21 03:49:45 tgl Exp $
3030
*
3131
*-------------------------------------------------------------------------
3232
*/
@@ -754,6 +754,16 @@ InitPlan(QueryDesc *queryDesc, int eflags)
754754
*/
755755
estate->es_junkFilter=
756756
estate->es_result_relation_info->ri_junkFilter;
757+
758+
/*
759+
* We currently can't support rowmarks in this case, because
760+
* the associated junk CTIDs might have different resnos in
761+
* different subplans.
762+
*/
763+
if (estate->es_rowMarks)
764+
ereport(ERROR,
765+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
766+
errmsg("SELECT FOR UPDATE/SHARE is not supported within a query with multiple result relations")));
757767
}
758768
else
759769
{
@@ -771,18 +781,6 @@ InitPlan(QueryDesc *queryDesc, int eflags)
771781
{
772782
/* For SELECT, want to return the cleaned tuple type */
773783
tupType=j->jf_cleanTupType;
774-
/* For SELECT FOR UPDATE/SHARE, find the ctid attrs now */
775-
foreach(l,estate->es_rowMarks)
776-
{
777-
ExecRowMark*erm= (ExecRowMark*)lfirst(l);
778-
charresname[32];
779-
780-
snprintf(resname,sizeof(resname),"ctid%u",erm->rti);
781-
erm->ctidAttNo=ExecFindJunkAttribute(j,resname);
782-
if (!AttributeNumberIsValid(erm->ctidAttNo))
783-
elog(ERROR,"could not find junk \"%s\" column",
784-
resname);
785-
}
786784
}
787785
elseif (operation==CMD_UPDATE||operation==CMD_DELETE)
788786
{
@@ -791,10 +789,27 @@ InitPlan(QueryDesc *queryDesc, int eflags)
791789
if (!AttributeNumberIsValid(j->jf_junkAttNo))
792790
elog(ERROR,"could not find junk ctid column");
793791
}
792+
793+
/* For SELECT FOR UPDATE/SHARE, find the ctid attrs now */
794+
foreach(l,estate->es_rowMarks)
795+
{
796+
ExecRowMark*erm= (ExecRowMark*)lfirst(l);
797+
charresname[32];
798+
799+
snprintf(resname,sizeof(resname),"ctid%u",erm->rti);
800+
erm->ctidAttNo=ExecFindJunkAttribute(j,resname);
801+
if (!AttributeNumberIsValid(erm->ctidAttNo))
802+
elog(ERROR,"could not find junk \"%s\" column",
803+
resname);
804+
}
794805
}
795806
}
796807
else
808+
{
797809
estate->es_junkFilter=NULL;
810+
if (estate->es_rowMarks)
811+
elog(ERROR,"SELECT FOR UPDATE/SHARE, but no junk columns");
812+
}
798813
}
799814

800815
/*
@@ -1240,47 +1255,30 @@ lnext:;
12401255
slot=planSlot;
12411256

12421257
/*
1243-
*if we have a junk filter, then project a new tuple with the junk
1258+
*If we have a junk filter, then project a new tuple with the junk
12441259
* removed.
12451260
*
12461261
* Store this new "clean" tuple in the junkfilter's resultSlot.
12471262
* (Formerly, we stored it back over the "dirty" tuple, which is WRONG
12481263
* because that tuple slot has the wrong descriptor.)
12491264
*
1250-
*Also, extract all the junk information we need.
1265+
*But first, extract all the junk information we need.
12511266
*/
12521267
if ((junkfilter=estate->es_junkFilter)!=NULL)
12531268
{
1254-
Datumdatum;
1255-
boolisNull;
1256-
1257-
/*
1258-
* extract the 'ctid' junk attribute.
1259-
*/
1260-
if (operation==CMD_UPDATE||operation==CMD_DELETE)
1261-
{
1262-
datum=ExecGetJunkAttribute(slot,junkfilter->jf_junkAttNo,
1263-
&isNull);
1264-
/* shouldn't ever get a null result... */
1265-
if (isNull)
1266-
elog(ERROR,"ctid is NULL");
1267-
1268-
tupleid= (ItemPointer)DatumGetPointer(datum);
1269-
tuple_ctid=*tupleid;/* make sure we don't free the ctid!! */
1270-
tupleid=&tuple_ctid;
1271-
}
1272-
12731269
/*
12741270
* Process any FOR UPDATE or FOR SHARE locking requested.
12751271
*/
1276-
elseif (estate->es_rowMarks!=NIL)
1272+
if (estate->es_rowMarks!=NIL)
12771273
{
12781274
ListCell*l;
12791275

12801276
lmark:;
12811277
foreach(l,estate->es_rowMarks)
12821278
{
12831279
ExecRowMark*erm=lfirst(l);
1280+
Datumdatum;
1281+
boolisNull;
12841282
HeapTupleDatatuple;
12851283
Bufferbuffer;
12861284
ItemPointerDataupdate_ctid;
@@ -1352,6 +1350,25 @@ lnext:;
13521350
}
13531351
}
13541352

1353+
/*
1354+
* extract the 'ctid' junk attribute.
1355+
*/
1356+
if (operation==CMD_UPDATE||operation==CMD_DELETE)
1357+
{
1358+
Datumdatum;
1359+
boolisNull;
1360+
1361+
datum=ExecGetJunkAttribute(slot,junkfilter->jf_junkAttNo,
1362+
&isNull);
1363+
/* shouldn't ever get a null result... */
1364+
if (isNull)
1365+
elog(ERROR,"ctid is NULL");
1366+
1367+
tupleid= (ItemPointer)DatumGetPointer(datum);
1368+
tuple_ctid=*tupleid;/* make sure we don't free the ctid!! */
1369+
tupleid=&tuple_ctid;
1370+
}
1371+
13551372
/*
13561373
* Create a new "clean" tuple with all junk attributes removed. We
13571374
* don't need to do this for DELETE, however (there will in fact

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp