code: func (c *ifFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (sig builtinFunc, err error) {
  	if err = c.verifyArgs(args); err != nil {
  		return nil, err
  	}
  	retTp := InferType4ControlFuncs(args[1].GetType(), args[2].GetType())
  	evalTps := retTp.EvalType()
  	bf := newBaseBuiltinFuncWithTp(ctx, args, evalTps, types.ETInt, evalTps, evalTps)
  	retTp.Flag |= bf.tp.Flag
  	bf.tp = retTp
  	switch evalTps {
  	case types.ETInt:
  		sig = &builtinIfIntSig{bf}
  		sig.setPbCode(tipb.ScalarFuncSig_IfInt)
  	case types.ETReal:
  		sig = &builtinIfRealSig{bf}
  		sig.setPbCode(tipb.ScalarFuncSig_IfReal)
  	case types.ETDecimal:
  		sig = &builtinIfDecimalSig{bf}
  		sig.setPbCode(tipb.ScalarFuncSig_IfDecimal)
  	case types.ETString:
  		sig = &builtinIfStringSig{bf}
  		sig.setPbCode(tipb.ScalarFuncSig_IfString)
  	case types.ETDatetime, types.ETTimestamp:
  		sig = &builtinIfTimeSig{bf}
  		sig.setPbCode(tipb.ScalarFuncSig_IfTime)
  	case types.ETDuration:
  		sig = &builtinIfDurationSig{bf}
  		sig.setPbCode(tipb.ScalarFuncSig_IfDuration)
  	case types.ETJson:
  		sig = &builtinIfJSONSig{bf}
  		sig.setPbCode(tipb.ScalarFuncSig_IfJson)
  	}
  	return sig, nil
  }
docs: // getFunction see https://dev.mysql.com/doc/refman/5.7/en/control-flow-functions.html#function_if