code: private static void simplifyOuterJoin(BranchNode joinTree) {
          assert(joinTree != null);
          List<AbstractExpression> exprs = new ArrayList<>();
          JoinNode leftNode = joinTree.getLeftNode();
          JoinNode rightNode = joinTree.getRightNode();
          // For the top level node only,
          // WHERE expressions need to be evaluated for NULL-rejection
          if (leftNode.getWhereExpression() != null) {
              exprs.add(leftNode.getWhereExpression());
          }
          if (rightNode.getWhereExpression() != null) {
              exprs.add(rightNode.getWhereExpression());
          }
          simplifyOuterJoinRecursively(joinTree, exprs);
      }
docs: Outer join simplification using null rejection.
  http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.43.2531
  Outerjoin Simplification and Reordering for Query Optimization
  by Cesar A. Galindo-Legaria , Arnon Rosenthal
  Algorithm:
  Traverse the join tree top-down:
  For each join node n1 do:
  For each expression expr (join and where) at the node n1
  For each join node n2 descended from n1 do:
  If expr rejects nulls introduced by n2 inner table, then
  - convert LEFT OUTER n2 to an INNER join.
  - convert FULL OUTER n2 to RIGHT OUTER join
  If expr rejects nulls introduced by n2 outer table, then
  - convert RIGHT OUTER n2 to an INNER join.
  - convert FULL OUTER n2 to LEFT OUTER join