code: func WrapWithCastAsString(ctx sessionctx.Context, expr Expression) Expression {
  	exprTp := expr.GetType()
  	if exprTp.EvalType() == types.ETString {
  		return expr
  	}
  	argLen := exprTp.Flen
  	// If expr is decimal, we should take the decimal point and negative sign
  	// into consideration, so we set `expr.GetType().Flen + 2` as the `argLen`.
  	// Since the length of float and double is not accurate, we do not handle
  	// them.
  	if exprTp.Tp == mysql.TypeNewDecimal && argLen != types.UnspecifiedFsp {
  		argLen += 2
  	}
  	if exprTp.EvalType() == types.ETInt {
  		argLen = mysql.MaxIntWidth
  	}
  	tp := types.NewFieldType(mysql.TypeVarString)
  	tp.Charset, tp.Collate = charset.GetDefaultCharsetAndCollate()
  	tp.Flen, tp.Decimal = argLen, types.UnspecifiedLength
  	return BuildCastFunction(ctx, expr, tp)
  }
docs: // WrapWithCastAsString wraps `expr` with `cast` if the return type of expr is
  // not type string, otherwise, returns `expr` directly.