@@ -744,9 +744,6 @@ InitPlan(QueryDesc *queryDesc, int eflags)
744
744
erm -> prti = rc -> prti ;
745
745
erm -> markType = rc -> markType ;
746
746
erm -> noWait = rc -> noWait ;
747
- erm -> ctidAttNo = rc -> ctidAttNo ;
748
- erm -> toidAttNo = rc -> toidAttNo ;
749
- erm -> wholeAttNo = rc -> wholeAttNo ;
750
747
ItemPointerSetInvalid (& (erm -> curCtid ));
751
748
estate -> es_rowMarks = lappend (estate -> es_rowMarks , erm );
752
749
}
@@ -1386,6 +1383,71 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
1386
1383
}
1387
1384
1388
1385
1386
+ /*
1387
+ * ExecFindRowMark -- find the ExecRowMark struct for given rangetable index
1388
+ */
1389
+ ExecRowMark *
1390
+ ExecFindRowMark (EState * estate , Index rti )
1391
+ {
1392
+ ListCell * lc ;
1393
+
1394
+ foreach (lc , estate -> es_rowMarks )
1395
+ {
1396
+ ExecRowMark * erm = (ExecRowMark * ) lfirst (lc );
1397
+
1398
+ if (erm -> rti == rti )
1399
+ return erm ;
1400
+ }
1401
+ elog (ERROR , "failed to find ExecRowMark for rangetable index %u" , rti );
1402
+ return NULL ; /* keep compiler quiet */
1403
+ }
1404
+
1405
+ /*
1406
+ * ExecBuildAuxRowMark -- create an ExecAuxRowMark struct
1407
+ *
1408
+ * Inputs are the underlying ExecRowMark struct and the targetlist of the
1409
+ * input plan node (not planstate node!). We need the latter to find out
1410
+ * the column numbers of the resjunk columns.
1411
+ */
1412
+ ExecAuxRowMark *
1413
+ ExecBuildAuxRowMark (ExecRowMark * erm , List * targetlist )
1414
+ {
1415
+ ExecAuxRowMark * aerm = (ExecAuxRowMark * ) palloc0 (sizeof (ExecAuxRowMark ));
1416
+ char resname [32 ];
1417
+
1418
+ aerm -> rowmark = erm ;
1419
+
1420
+ /* Look up the resjunk columns associated with this rowmark */
1421
+ if (erm -> relation )
1422
+ {
1423
+ Assert (erm -> markType != ROW_MARK_COPY );
1424
+
1425
+ /* if child rel, need tableoid */
1426
+ if (erm -> rti != erm -> prti )
1427
+ {
1428
+ snprintf (resname , sizeof (resname ), "tableoid%u" , erm -> prti );
1429
+ aerm -> toidAttNo = ExecFindJunkAttributeInTlist (targetlist ,
1430
+ resname );
1431
+ }
1432
+
1433
+ /* always need ctid for real relations */
1434
+ snprintf (resname , sizeof (resname ), "ctid%u" , erm -> prti );
1435
+ aerm -> ctidAttNo = ExecFindJunkAttributeInTlist (targetlist ,
1436
+ resname );
1437
+ }
1438
+ else
1439
+ {
1440
+ Assert (erm -> markType == ROW_MARK_COPY );
1441
+
1442
+ snprintf (resname , sizeof (resname ), "wholerow%u" , erm -> prti );
1443
+ aerm -> wholeAttNo = ExecFindJunkAttributeInTlist (targetlist ,
1444
+ resname );
1445
+ }
1446
+
1447
+ return aerm ;
1448
+ }
1449
+
1450
+
1389
1451
/*
1390
1452
* EvalPlanQual logic --- recheck modified tuple(s) to see if we want to
1391
1453
* process the updated version under READ COMMITTED rules.
@@ -1676,19 +1738,21 @@ EvalPlanQualFetch(EState *estate, Relation relation, int lockmode,
1676
1738
/*
1677
1739
* EvalPlanQualInit -- initialize during creation of a plan state node
1678
1740
* that might need to invoke EPQ processing.
1679
- * Note: subplan can be NULL if it will be set later with EvalPlanQualSetPlan.
1741
+ *
1742
+ * Note: subplan/auxrowmarks can be NULL/NIL if they will be set later
1743
+ * with EvalPlanQualSetPlan.
1680
1744
*/
1681
1745
void
1682
1746
EvalPlanQualInit (EPQState * epqstate , EState * estate ,
1683
- Plan * subplan , int epqParam )
1747
+ Plan * subplan , List * auxrowmarks , int epqParam )
1684
1748
{
1685
1749
/* Mark the EPQ state inactive */
1686
1750
epqstate -> estate = NULL ;
1687
1751
epqstate -> planstate = NULL ;
1688
1752
epqstate -> origslot = NULL ;
1689
1753
/* ... and remember data that EvalPlanQualBegin will need */
1690
1754
epqstate -> plan = subplan ;
1691
- epqstate -> rowMarks = NIL ;
1755
+ epqstate -> arowMarks = auxrowmarks ;
1692
1756
epqstate -> epqParam = epqParam ;
1693
1757
}
1694
1758
@@ -1698,25 +1762,14 @@ EvalPlanQualInit(EPQState *epqstate, EState *estate,
1698
1762
* We need this so that ModifyTuple can deal with multiple subplans.
1699
1763
*/
1700
1764
void
1701
- EvalPlanQualSetPlan (EPQState * epqstate , Plan * subplan )
1765
+ EvalPlanQualSetPlan (EPQState * epqstate , Plan * subplan , List * auxrowmarks )
1702
1766
{
1703
1767
/* If we have a live EPQ query, shut it down */
1704
1768
EvalPlanQualEnd (epqstate );
1705
1769
/* And set/change the plan pointer */
1706
1770
epqstate -> plan = subplan ;
1707
- }
1708
-
1709
- /*
1710
- * EvalPlanQualAddRowMark -- add an ExecRowMark that EPQ needs to handle.
1711
- *
1712
- * Currently, only non-locking RowMarks are supported.
1713
- */
1714
- void
1715
- EvalPlanQualAddRowMark (EPQState * epqstate , ExecRowMark * erm )
1716
- {
1717
- if (RowMarkRequiresRowShareLock (erm -> markType ))
1718
- elog (ERROR , "EvalPlanQual doesn't support locking rowmarks" );
1719
- epqstate -> rowMarks = lappend (epqstate -> rowMarks , erm );
1771
+ /* The rowmarks depend on the plan, too */
1772
+ epqstate -> arowMarks = auxrowmarks ;
1720
1773
}
1721
1774
1722
1775
/*
@@ -1766,13 +1819,17 @@ EvalPlanQualFetchRowMarks(EPQState *epqstate)
1766
1819
1767
1820
Assert (epqstate -> origslot != NULL );
1768
1821
1769
- foreach (l , epqstate -> rowMarks )
1822
+ foreach (l , epqstate -> arowMarks )
1770
1823
{
1771
- ExecRowMark * erm = (ExecRowMark * ) lfirst (l );
1824
+ ExecAuxRowMark * aerm = (ExecAuxRowMark * ) lfirst (l );
1825
+ ExecRowMark * erm = aerm -> rowmark ;
1772
1826
Datum datum ;
1773
1827
bool isNull ;
1774
1828
HeapTupleData tuple ;
1775
1829
1830
+ if (RowMarkRequiresRowShareLock (erm -> markType ))
1831
+ elog (ERROR , "EvalPlanQual doesn't support locking rowmarks" );
1832
+
1776
1833
/* clear any leftover test tuple for this rel */
1777
1834
EvalPlanQualSetTuple (epqstate , erm -> rti , NULL );
1778
1835
@@ -1788,7 +1845,7 @@ EvalPlanQualFetchRowMarks(EPQState *epqstate)
1788
1845
Oid tableoid ;
1789
1846
1790
1847
datum = ExecGetJunkAttribute (epqstate -> origslot ,
1791
- erm -> toidAttNo ,
1848
+ aerm -> toidAttNo ,
1792
1849
& isNull );
1793
1850
/* non-locked rels could be on the inside of outer joins */
1794
1851
if (isNull )
@@ -1804,7 +1861,7 @@ EvalPlanQualFetchRowMarks(EPQState *epqstate)
1804
1861
1805
1862
/* fetch the tuple's ctid */
1806
1863
datum = ExecGetJunkAttribute (epqstate -> origslot ,
1807
- erm -> ctidAttNo ,
1864
+ aerm -> ctidAttNo ,
1808
1865
& isNull );
1809
1866
/* non-locked rels could be on the inside of outer joins */
1810
1867
if (isNull )
@@ -1829,7 +1886,7 @@ EvalPlanQualFetchRowMarks(EPQState *epqstate)
1829
1886
1830
1887
/* fetch the whole-row Var for the relation */
1831
1888
datum = ExecGetJunkAttribute (epqstate -> origslot ,
1832
- erm -> wholeAttNo ,
1889
+ aerm -> wholeAttNo ,
1833
1890
& isNull );
1834
1891
/* non-locked rels could be on the inside of outer joins */
1835
1892
if (isNull )
0 commit comments