public SqlJoinInner rewrite(SqlJoinInner join) {
    if (!join.getRight().isInnerJoin()) return join;

    // if ( join(A, join(B, C)) ) rewrite as join(join(A,B),C)
    // this then is written without brackets (and so scope changing)
    // TODO abstract as organiseJoin(List<join elements>)
    // and remember to do top down to find maximal join trees

    SqlJoinInner right = join.getRight().asInnerJoin();

    String alias1 = join.getAliasName();
    String alias2 = right.getAliasName();

    SqlNode sn_a = join.getLeft();
    SqlNode sn_b = right.getLeft();
    SqlNode sn_c = right.getRight();

    SqlExprList conditions = new SqlExprList(join.getConditions());
    conditions.addAll(right.getConditions());

    Set<SqlTable> tables_ab = sn_a.tablesInvolved();
    tables_ab.addAll(sn_b.tablesInvolved());

    SqlExprList newCond_ab = new SqlExprList(); // Goes to new join(A,B)
    SqlExprList newCond_c = new SqlExprList(); // Goes to new join(,C)
    // Place conditions
    for (SqlExpr e : conditions) {
      Set<SqlColumn> cols = e.getColumnsNeeded();
      // columns to tables.
      Set<SqlTable> tables = tables(cols);
      // Are the tables contained in tables_ab?
      tables.removeAll(tables_ab);

      if (tables.size() == 0) newCond_ab.add(e);
      else newCond_c.add(e);
    }
    if (newCond_ab.size() + newCond_c.size() != conditions.size())
      log.error(
          String.format(
              "Conditions mismatch: (%d,%d,%d)",
              newCond_ab.size(), newCond_c.size(), conditions.size()));

    SqlJoinInner join2 = new SqlJoinInner(sn_a, sn_b);
    join2.addConditions(newCond_ab);
    join2 = new SqlJoinInner(join2, sn_c);
    join2.addConditions(newCond_c);
    return join2;
  }