code: func (b *builtinLocate3ArgsSig) evalInt(row chunk.Row) (int64, bool, error) {
  	subStr, isNull, err := b.args[0].EvalString(b.ctx, row)
  	if isNull || err != nil {
  		return 0, isNull, err
  	}
  	str, isNull, err := b.args[1].EvalString(b.ctx, row)
  	if isNull || err != nil {
  		return 0, isNull, err
  	}
  	pos, isNull, err := b.args[2].EvalInt(b.ctx, row)
  	// Transfer the argument which starts from 1 to real index which starts from 0.
  	pos--
  	if isNull || err != nil {
  		return 0, isNull, err
  	}
  	subStrLen := len([]rune(subStr))
  	if pos < 0 || pos > int64(len([]rune(strings.ToLower(str)))-subStrLen) {
  		return 0, false, nil
  	} else if subStrLen == 0 {
  		return pos + 1, false, nil
  	}
  	slice := string([]rune(strings.ToLower(str))[pos:])
  	idx := strings.Index(slice, strings.ToLower(subStr))
  	if idx != -1 {
  		return pos + int64(utf8.RuneCountInString(slice[:idx])) + 1, false, nil
  	}
  	return 0, false, nil
  }
docs: // evalInt evals LOCATE(substr,str,pos), non case-sensitive.
  // See https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_locate