* Fetch the current row value for a non-locked relation, identified by rti, * that needs to be scanned by an EvalPlanQual operation. origslot must have * been set to contain the current result row (top-level row) that we need to * recheck. Returns true if a substitution tuple was found, false if not. */
| 3757 | * recheck. Returns true if a substitution tuple was found, false if not. |
| 3758 | */ |
| 3759 | bool |
| 3760 | EvalPlanQualFetchRowMark(EPQState *epqstate, Index rti, TupleTableSlot *slot) |
| 3761 | { |
| 3762 | ExecAuxRowMark *earm = epqstate->relsubs_rowmark[rti - 1]; |
| 3763 | ExecRowMark *erm = earm->rowmark; |
| 3764 | Datum datum; |
| 3765 | bool isNull; |
| 3766 | |
| 3767 | Assert(earm != NULL); |
| 3768 | Assert(epqstate->origslot != NULL); |
| 3769 | |
| 3770 | if (RowMarkRequiresRowShareLock(erm->markType)) |
| 3771 | elog(ERROR, "EvalPlanQual doesn't support locking rowmarks"); |
| 3772 | |
| 3773 | /* if child rel, must check whether it produced this row */ |
| 3774 | if (erm->rti != erm->prti) |
| 3775 | { |
| 3776 | Oid tableoid; |
| 3777 | |
| 3778 | datum = ExecGetJunkAttribute(epqstate->origslot, |
| 3779 | earm->toidAttNo, |
| 3780 | &isNull); |
| 3781 | /* non-locked rels could be on the inside of outer joins */ |
| 3782 | if (isNull) |
| 3783 | return false; |
| 3784 | |
| 3785 | tableoid = DatumGetObjectId(datum); |
| 3786 | |
| 3787 | Assert(OidIsValid(erm->relid)); |
| 3788 | if (tableoid != erm->relid) |
| 3789 | { |
| 3790 | /* this child is inactive right now */ |
| 3791 | return false; |
| 3792 | } |
| 3793 | } |
| 3794 | |
| 3795 | if (erm->markType == ROW_MARK_REFERENCE) |
| 3796 | { |
| 3797 | Assert(erm->relation != NULL); |
| 3798 | |
| 3799 | /* fetch the tuple's ctid */ |
| 3800 | datum = ExecGetJunkAttribute(epqstate->origslot, |
| 3801 | earm->ctidAttNo, |
| 3802 | &isNull); |
| 3803 | /* non-locked rels could be on the inside of outer joins */ |
| 3804 | if (isNull) |
| 3805 | return false; |
| 3806 | |
| 3807 | /* fetch requests on foreign tables must be passed to their FDW */ |
| 3808 | if (erm->relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE) |
| 3809 | { |
| 3810 | FdwRoutine *fdwroutine; |
| 3811 | bool updated = false; |
| 3812 | |
| 3813 | fdwroutine = GetFdwRoutineForRelation(erm->relation, false); |
| 3814 | /* this should have been checked already, but let's be safe */ |
| 3815 | if (fdwroutine->RefetchForeignRow == NULL) |
| 3816 | ereport(ERROR, |
no test coverage detected