public void conditionList(SqlExprList conditions) {
    if (conditions.size() == 0) return;

    out.print("( ");

    String sep = "  AND ";

    boolean first = true;
    boolean lastAnnotated = false;

    for (SqlExpr c : conditions) {
      if (!first) {
        if (!allOnOneLine) out.println();
        out.print(sep);
      }
      boolean needsParens = !(c instanceof S_Equal);

      // TODO Interact with SqlExpr precedence printing
      if (needsParens) out.print("( ");
      out.print(c.asSQL());
      if (needsParens) out.print(" )");
      if (!allOnOneLine) lastAnnotated = annotate(c);
      first = false;
    }
    if (!allOnOneLine && lastAnnotated) out.println("");
    out.print(" )");
    first = true;

    if (allOnOneLine) {
      for (SqlExpr c : conditions) {
        if (c.hasNotes()) {
          if (!first) out.println();
          annotate(c);
          first = false;
        }
      }
    }
  }
  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;
  }