Extract plan rewriting into it's own class
Refactor unnestOptional

Since refactoring happens on already valid logical plans, we do not need to go
back to the original QueryGraph. We simply trust that the incoming plans are
valid.
Added argument ids to LogicalLeafPlan
Rewrite two consecutive Selection plans into a single one
Make OuterHashJoin able to work on multiple keys
Plan OPTIONAL MATCH using both Apply/Optional and OuterJoin
Merge pull request #3306 from systay/unnest-all-the-things

[2.2] More plan rewriting