26
26
*
27
27
*
28
28
* 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 $
30
30
*
31
31
*-------------------------------------------------------------------------
32
32
*/
@@ -754,6 +754,16 @@ InitPlan(QueryDesc *queryDesc, int eflags)
754
754
*/
755
755
estate -> es_junkFilter =
756
756
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" )));
757
767
}
758
768
else
759
769
{
@@ -771,18 +781,6 @@ InitPlan(QueryDesc *queryDesc, int eflags)
771
781
{
772
782
/* For SELECT, want to return the cleaned tuple type */
773
783
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
- char resname [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
- }
786
784
}
787
785
else if (operation == CMD_UPDATE || operation == CMD_DELETE )
788
786
{
@@ -791,10 +789,27 @@ InitPlan(QueryDesc *queryDesc, int eflags)
791
789
if (!AttributeNumberIsValid (j -> jf_junkAttNo ))
792
790
elog (ERROR , "could not find junk ctid column" );
793
791
}
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
+ char resname [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
+ }
794
805
}
795
806
}
796
807
else
808
+ {
797
809
estate -> es_junkFilter = NULL ;
810
+ if (estate -> es_rowMarks )
811
+ elog (ERROR , "SELECT FOR UPDATE/SHARE, but no junk columns" );
812
+ }
798
813
}
799
814
800
815
/*
@@ -1240,47 +1255,30 @@ lnext: ;
1240
1255
slot = planSlot ;
1241
1256
1242
1257
/*
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
1244
1259
* removed.
1245
1260
*
1246
1261
* Store this new "clean" tuple in the junkfilter's resultSlot.
1247
1262
* (Formerly, we stored it back over the "dirty" tuple, which is WRONG
1248
1263
* because that tuple slot has the wrong descriptor.)
1249
1264
*
1250
- * Also , extract all the junk information we need.
1265
+ * But first , extract all the junk information we need.
1251
1266
*/
1252
1267
if ((junkfilter = estate -> es_junkFilter ) != NULL )
1253
1268
{
1254
- Datum datum ;
1255
- bool isNull ;
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
-
1273
1269
/*
1274
1270
* Process any FOR UPDATE or FOR SHARE locking requested.
1275
1271
*/
1276
- else if (estate -> es_rowMarks != NIL )
1272
+ if (estate -> es_rowMarks != NIL )
1277
1273
{
1278
1274
ListCell * l ;
1279
1275
1280
1276
lmark : ;
1281
1277
foreach (l , estate -> es_rowMarks )
1282
1278
{
1283
1279
ExecRowMark * erm = lfirst (l );
1280
+ Datum datum ;
1281
+ bool isNull ;
1284
1282
HeapTupleData tuple ;
1285
1283
Buffer buffer ;
1286
1284
ItemPointerData update_ctid ;
@@ -1352,6 +1350,25 @@ lnext: ;
1352
1350
}
1353
1351
}
1354
1352
1353
+ /*
1354
+ * extract the 'ctid' junk attribute.
1355
+ */
1356
+ if (operation == CMD_UPDATE || operation == CMD_DELETE )
1357
+ {
1358
+ Datum datum ;
1359
+ bool isNull ;
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
+
1355
1372
/*
1356
1373
* Create a new "clean" tuple with all junk attributes removed. We
1357
1374
* don't need to do this for DELETE, however (there will in fact
0 commit comments