code: func (b *PlanBuilder) rewriteWithPreprocess(exprNode ast.ExprNode, p LogicalPlan, aggMapper map[*ast.AggregateFuncExpr]int, asScalar bool, preprocess func(ast.Node) ast.Node) (expression.Expression, LogicalPlan, error) {
  	b.rewriterCounter++
  	defer func() { b.rewriterCounter-- }()
  
  	rewriter := b.getExpressionRewriter(p)
  	// The rewriter maybe is obtained from "b.rewriterPool", "rewriter.err" is
  	// not nil means certain previous procedure has not handled this error.
  	// Here we give us one more chance to make a correct behavior by handling
  	// this missed error.
  	if rewriter.err != nil {
  		return nil, nil, rewriter.err
  	}
  
  	rewriter.aggrMap = aggMapper
  	rewriter.asScalar = asScalar
  	rewriter.preprocess = preprocess
  
  	expr, resultPlan, err := b.rewriteExprNode(rewriter, exprNode, asScalar)
  	return expr, resultPlan, err
  }
docs: // rewriteWithPreprocess is for handling the situation that we need to adjust the input ast tree
  // before really using its node in `expressionRewriter.Leave`. In that case, we first call
  // er.preprocess(expr), which returns a new expr. Then we use the new expr in `Leave`.