@Override
  public Expr visitBinaryOperator(ExprNormalizedResult ctx, Stack<Expr> stack, BinaryOperator expr)
      throws PlanningException {
    super.visitBinaryOperator(ctx, stack, expr);

    ////////////////////////
    // For Left Term
    ////////////////////////

    if (isAggregationFunction(expr.getLeft())) {
      String leftRefName = ctx.block.namedExprsMgr.addExpr(expr.getLeft());
      ctx.aggExprs.add(new NamedExpr(expr.getLeft(), leftRefName));
      expr.setLeft(new ColumnReferenceExpr(leftRefName));
    }

    ////////////////////////
    // For Right Term
    ////////////////////////
    if (isAggregationFunction(expr.getRight())) {
      String rightRefName = ctx.block.namedExprsMgr.addExpr(expr.getRight());
      ctx.aggExprs.add(new NamedExpr(expr.getRight(), rightRefName));
      expr.setRight(new ColumnReferenceExpr(rightRefName));
    }

    return expr;
  }
 @Override
 public Expr visitCastExpr(ExprNormalizedResult ctx, Stack<Expr> stack, CastExpr expr)
     throws PlanningException {
   super.visitCastExpr(ctx, stack, expr);
   if (expr.getChild().getType() == OpType.GeneralSetFunction
       || expr.getChild().getType() == OpType.CountRowsFunction) {
     String referenceName = ctx.block.namedExprsMgr.addExpr(expr.getChild());
     ctx.aggExprs.add(new NamedExpr(expr.getChild(), referenceName));
     expr.setChild(new ColumnReferenceExpr(referenceName));
   }
   return expr;
 }
  @Override
  public Expr visitUnaryOperator(ExprNormalizedResult ctx, Stack<Expr> stack, UnaryOperator expr)
      throws PlanningException {
    super.visitUnaryOperator(ctx, stack, expr);
    if (isAggregationFunction(expr.getChild())) {
      // Get an anonymous column name and replace the aggregation function by the column name
      String refName = ctx.block.namedExprsMgr.addExpr(expr.getChild());
      ctx.aggExprs.add(new NamedExpr(expr.getChild(), refName));
      expr.setChild(new ColumnReferenceExpr(refName));
    }

    return expr;
  }