code: func builtinLocate(args []types.Datum, ctx context.Context) (d types.Datum, err error) {
  	// The meaning of the elements of args.
  	// args[0] -> SubStr
  	// args[1] -> Str
  	// args[2] -> Pos
  	// eval str
  	if args[1].IsNull() {
  		return d, nil
  	}
  	str, err := args[1].ToString()
  	if err != nil {
  		return d, errors.Trace(err)
  	}
  	// eval substr
  	if args[0].IsNull() {
  		return d, nil
  	}
  	subStr, err := args[0].ToString()
  	if err != nil {
  		return d, errors.Trace(err)
  	}
  	// eval pos
  	pos := int64(0)
  	if len(args) == 3 {
  		p, err := args[2].ToInt64(ctx.GetSessionVars().StmtCtx)
  		if err != nil {
  			return d, errors.Trace(err)
  		}
  		pos = p - 1
  		if pos < 0 || pos > int64(len(str)) {
  			d.SetInt64(0)
  			return d, nil
  		}
  		if pos > int64(len(str)-len(subStr)) {
  			d.SetInt64(0)
  			return d, nil
  		}
  	}
  	if len(subStr) == 0 {
  		d.SetInt64(pos + 1)
  		return d, nil
  	}
  	i := strings.Index(str[pos:], subStr)
  	if i == -1 {
  		d.SetInt64(0)
  		return d, nil
  	}
  	d.SetInt64(int64(i) + pos + 1)
  	return d, nil
  }
docs: // See https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_locate