Additional columns may need to be added to a Project

In the new test, consider the Select that implements the join condition c3.name == c2.name whose input is a Project. Without the Project, the Select would have access to c2 and c3, one from the outer loop and the other from the IndexScan. The Project is added to supply columns needed by the innermost loop, that is, the one implementing the semi-join and the top-level query projection. For this it needs c1.name, c1.cid. Prior to this branch, that is all it would have. But then the Select will not assemble (column not found: c2.name).

The idea is that having committed to keeping the Project, it must handle any columns used by nodes between the Project and the nested loops proper. This requires a little tricky use of the visitor pattern, since it does not want to include columns from other branches of the loops than the one path in question. For this, it visits the nodes one-by-one with a flag that ignores expressions not immediately from such an explicit node. Most of the time, the Project is immediately on the inside and no such visiting is required.