@Override
  public void visit(SqlCoalesce sqlNode) {
    out.print("SELECT ");

    boolean first = true;
    SqlJoin join = sqlNode.getJoinNode();
    // Rough draft code.
    for (Var v : sqlNode.getCoalesceVars()) {
      if (!first) out.print(", ");
      SqlColumn col = sqlNode.getIdScope().findScopeForVar(v).getColumn();
      SqlColumn leftCol = join.getLeft().getIdScope().findScopeForVar(v).getColumn();
      SqlColumn rightCol = join.getRight().getIdScope().findScopeForVar(v).getColumn();

      out.print("COALESCE(");
      out.print(leftCol.getFullColumnName());
      out.print(", ");
      out.print(rightCol.getFullColumnName());

      out.print(")");
      out.print(aliasToken());
      out.print(col.getColumnName());
      first = false;
    }

    // And other vars we want.

    for (Var v : sqlNode.getNonCoalesceVars()) {
      if (!first) out.print(", ");
      first = false;

      // Need generated names.
      SqlColumn colSub = join.getIdScope().findScopeForVar(v).getColumn();
      SqlColumn col = sqlNode.getIdScope().findScopeForVar(v).getColumn();

      out.print(colSub.getFullColumnName());
      out.print(aliasToken());
      out.print(col.getColumnName());
    }
    out.ensureStartOfLine();

    out.incIndent(); // INC
    out.println("FROM");
    join.visit(this);
    out.ensureStartOfLine();
    // Alias and annotations handled by outputNode
  }
  @Override
  public void visit(SqlSelectBlock sqlSelectBlock) {
    // Need a rename and alias if:
    //   Not top
    //   Not merely a table inside.

    levelSelectBlock++;

    if (levelSelectBlock > 1) {
      // Alias needed.
      //            SqlRename rename = SqlRename.view("X", sqlSelectBlock) ;
      //            rename.visit(this) ;
      //            levelSelectBlock-- ;
      //            return ;
    }

    genPrefix(sqlSelectBlock);
    out.print("SELECT ");
    if (sqlSelectBlock.getDistinct()) out.print("DISTINCT ");
    if (annotate(sqlSelectBlock)) out.ensureStartOfLine();
    out.incIndent();
    genColumnPrefix(sqlSelectBlock);
    print(sqlSelectBlock.getCols());
    out.decIndent();
    out.ensureStartOfLine();

    // FROM
    out.print("FROM");
    if (!sqlSelectBlock.getSubNode().isTable()) out.println();
    else out.print(" ");
    out.incIndent();
    outputNode(sqlSelectBlock.getSubNode(), true);
    // sqlSelectBlock.getSubNode().visit(this) ;
    out.decIndent();
    out.ensureStartOfLine();

    // WHERE
    if (sqlSelectBlock.getConditions().size() > 0) genWHERE(sqlSelectBlock.getConditions());

    // LIMIT/OFFSET
    out.ensureStartOfLine();
    genLimitOffset(sqlSelectBlock);
    genSuffix(sqlSelectBlock);
    levelSelectBlock--;
  }
  private void outputNode(SqlNode sqlNode, boolean mayNeedBrackets) {
    if (sqlNode.isTable()) {
      sqlNode.visit(this);
      return;
    }
    // boolean brackets = ( mayNeedBrackets && ( sqlNode.isSelectBlock() || sqlNode.isCoalesce() ) )
    // ;

    boolean brackets = false;
    brackets = brackets || (mayNeedBrackets && sqlNode.isCoalesce());

    // Work harder? ready for a better test.
    brackets = brackets || (mayNeedBrackets && sqlNode.isSelectBlock());

    // Need brackets if the subpart is a SELECT

    if (brackets) {
      out.print("( ");
      out.incIndent();
    }
    sqlNode.visit(this);
    if (brackets) {
      out.decIndent();
      out.ensureStartOfLine();
      out.print(")");
    }
    // Every derived table (SELECT ...) must have an alias.
    // Is there a more principled way to do this? .isDerived?
    //            if ( sqlNode.isRestrict() || sqlNode.isProject())
    //                out.print(+sqlNode.getAliasName()) ;
    if (sqlNode.getAliasName() != null) {
      out.print(aliasToken());
      out.print(sqlNode.getAliasName());
    }
    annotate(sqlNode);
  }