code: func BuildCastFunction(ctx sessionctx.Context, expr Expression, tp *types.FieldType) (res Expression) {
  	if hasSpecialCast(ctx, expr, tp) {
  		return expr
  	}
  
  	var fc functionClass
  	switch tp.EvalType() {
  	case types.ETInt:
  		fc = &castAsIntFunctionClass{baseFunctionClass{ast.Cast, 1, 1}, tp}
  	case types.ETDecimal:
  		fc = &castAsDecimalFunctionClass{baseFunctionClass{ast.Cast, 1, 1}, tp}
  	case types.ETReal:
  		fc = &castAsRealFunctionClass{baseFunctionClass{ast.Cast, 1, 1}, tp}
  	case types.ETDatetime, types.ETTimestamp:
  		fc = &castAsTimeFunctionClass{baseFunctionClass{ast.Cast, 1, 1}, tp}
  	case types.ETDuration:
  		fc = &castAsDurationFunctionClass{baseFunctionClass{ast.Cast, 1, 1}, tp}
  	case types.ETJson:
  		fc = &castAsJSONFunctionClass{baseFunctionClass{ast.Cast, 1, 1}, tp}
  	case types.ETString:
  		fc = &castAsStringFunctionClass{baseFunctionClass{ast.Cast, 1, 1}, tp}
  	}
  	f, err := fc.getFunction(ctx, []Expression{expr})
  	terror.Log(err)
  	res = &ScalarFunction{
  		FuncName: model.NewCIStr(ast.Cast),
  		RetType:  tp,
  		Function: f,
  	}
  	// We do not fold CAST if the eval type of this scalar function is ETJson
  	// since we may reset the flag of the field type of CastAsJson later which
  	// would affect the evaluation of it.
  	if tp.EvalType() != types.ETJson {
  		res = FoldConstant(res)
  	}
  	return res
  }
docs: // BuildCastFunction builds a CAST ScalarFunction from the Expression.