Eng 6012 inexists sp

I have to correct myself. The semi-scan node is always added by the planner at the top of the subquery plan tree with the offset is set to 0. In your example, the subquery would have the regular scan node over the R2 table with the offset 1, and the semi-scan node on top of it with the predicate R1.A = R2.B. The offset is 0 for this node. 
And yes, the hasMatchingTuple can be set outside the loop and change its value only in one direction - from false to true - in case of the semi scan node because it will be only one match at the most.
I also added two assertion to ensure that the predicate is set and the offset is not for a semi scan node.

assert((m_isSemiScan && predicate == NULL) == false);
assert((m_isSemiScan && offset != -1) == false);

I added your example to the testSubExpressions_InnerNull() case. Interestingly, the HSQL gets it wrong