|
26 | 26 | *
|
27 | 27 | *
|
28 | 28 | * IDENTIFICATION
|
29 |
| - * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.315 2008/11/06 20:51:14 tgl Exp $ |
| 29 | + * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.316 2008/11/15 19:43:45 tgl Exp $ |
30 | 30 | *
|
31 | 31 | *-------------------------------------------------------------------------
|
32 | 32 | */
|
@@ -590,18 +590,25 @@ InitPlan(QueryDesc *queryDesc, int eflags)
|
590 | 590 | foreach(l, plannedstmt->rowMarks)
|
591 | 591 | {
|
592 | 592 | RowMarkClause *rc = (RowMarkClause *) lfirst(l);
|
593 |
| - Oid relid = getrelid(rc->rti, rangeTable); |
| 593 | + Oid relid; |
594 | 594 | Relation relation;
|
595 | 595 | ExecRowMark *erm;
|
596 | 596 |
|
| 597 | + /* ignore "parent" rowmarks; they are irrelevant at runtime */ |
| 598 | + if (rc->isParent) |
| 599 | + continue; |
| 600 | + |
| 601 | + relid = getrelid(rc->rti, rangeTable); |
597 | 602 | relation = heap_open(relid, RowShareLock);
|
598 | 603 | erm = (ExecRowMark *) palloc(sizeof(ExecRowMark));
|
599 | 604 | erm->relation = relation;
|
600 | 605 | erm->rti = rc->rti;
|
| 606 | + erm->prti = rc->prti; |
601 | 607 | erm->forUpdate = rc->forUpdate;
|
602 | 608 | erm->noWait = rc->noWait;
|
603 |
| - /* We'll set up ctidAttno below */ |
| 609 | + /* We'll locate the junk attrs below */ |
604 | 610 | erm->ctidAttNo = InvalidAttrNumber;
|
| 611 | + erm->toidAttNo = InvalidAttrNumber; |
605 | 612 | estate->es_rowMarks = lappend(estate->es_rowMarks, erm);
|
606 | 613 | }
|
607 | 614 |
|
@@ -822,17 +829,29 @@ InitPlan(QueryDesc *queryDesc, int eflags)
|
822 | 829 | elog(ERROR, "could not find junk ctid column");
|
823 | 830 | }
|
824 | 831 |
|
825 |
| - /* For SELECT FOR UPDATE/SHARE, find the ctid attrs now */ |
| 832 | + /* For SELECT FOR UPDATE/SHARE, find the junk attrs now */ |
826 | 833 | foreach(l, estate->es_rowMarks)
|
827 | 834 | {
|
828 | 835 | ExecRowMark *erm = (ExecRowMark *) lfirst(l);
|
829 | 836 | char resname[32];
|
830 | 837 |
|
831 |
| - snprintf(resname, sizeof(resname), "ctid%u", erm->rti); |
| 838 | + /* always need the ctid */ |
| 839 | + snprintf(resname, sizeof(resname), "ctid%u", |
| 840 | + erm->prti); |
832 | 841 | erm->ctidAttNo = ExecFindJunkAttribute(j, resname);
|
833 | 842 | if (!AttributeNumberIsValid(erm->ctidAttNo))
|
834 | 843 | elog(ERROR, "could not find junk \"%s\" column",
|
835 | 844 | resname);
|
| 845 | + /* if child relation, need tableoid too */ |
| 846 | + if (erm->rti != erm->prti) |
| 847 | + { |
| 848 | + snprintf(resname, sizeof(resname), "tableoid%u", |
| 849 | + erm->prti); |
| 850 | + erm->toidAttNo = ExecFindJunkAttribute(j, resname); |
| 851 | + if (!AttributeNumberIsValid(erm->toidAttNo)) |
| 852 | + elog(ERROR, "could not find junk \"%s\" column", |
| 853 | + resname); |
| 854 | + } |
836 | 855 | }
|
837 | 856 | }
|
838 | 857 | }
|
@@ -1383,13 +1402,33 @@ lnext: ;
|
1383 | 1402 | LockTupleMode lockmode;
|
1384 | 1403 | HTSU_Result test;
|
1385 | 1404 |
|
| 1405 | + /* if child rel, must check whether it produced this row */ |
| 1406 | + if (erm->rti != erm->prti) |
| 1407 | + { |
| 1408 | + Oid tableoid; |
| 1409 | + |
| 1410 | + datum = ExecGetJunkAttribute(slot, |
| 1411 | + erm->toidAttNo, |
| 1412 | + &isNull); |
| 1413 | + /* shouldn't ever get a null result... */ |
| 1414 | + if (isNull) |
| 1415 | + elog(ERROR, "tableoid is NULL"); |
| 1416 | + tableoid = DatumGetObjectId(datum); |
| 1417 | + |
| 1418 | + if (tableoid != RelationGetRelid(erm->relation)) |
| 1419 | + { |
| 1420 | + /* this child is inactive right now */ |
| 1421 | + continue; |
| 1422 | + } |
| 1423 | + } |
| 1424 | + |
| 1425 | + /* okay, fetch the tuple by ctid */ |
1386 | 1426 | datum = ExecGetJunkAttribute(slot,
|
1387 | 1427 | erm->ctidAttNo,
|
1388 | 1428 | &isNull);
|
1389 | 1429 | /* shouldn't ever get a null result... */
|
1390 | 1430 | if (isNull)
|
1391 | 1431 | elog(ERROR, "ctid is NULL");
|
1392 |
| - |
1393 | 1432 | tuple.t_self = *((ItemPointer) DatumGetPointer(datum));
|
1394 | 1433 |
|
1395 | 1434 | if (erm->forUpdate)
|
@@ -2122,9 +2161,11 @@ EvalPlanQual(EState *estate, Index rti,
|
2122 | 2161 | relation = NULL;
|
2123 | 2162 | foreach(l, estate->es_rowMarks)
|
2124 | 2163 | {
|
2125 |
| - if (((ExecRowMark *) lfirst(l))->rti == rti) |
| 2164 | + ExecRowMark *erm = lfirst(l); |
| 2165 | + |
| 2166 | + if (erm->rti == rti) |
2126 | 2167 | {
|
2127 |
| - relation = ((ExecRowMark *) lfirst(l))->relation; |
| 2168 | + relation = erm->relation; |
2128 | 2169 | break;
|
2129 | 2170 | }
|
2130 | 2171 | }
|
|
0 commit comments