code: func (b *builtinSubstringBinary3ArgsSig) evalString(row chunk.Row) (string, bool, error) {
  	str, isNull, err := b.args[0].EvalString(b.ctx, row)
  	if isNull || err != nil {
  		return "", true, err
  	}
  	pos, isNull, err := b.args[1].EvalInt(b.ctx, row)
  	if isNull || err != nil {
  		return "", true, err
  	}
  	length, isNull, err := b.args[2].EvalInt(b.ctx, row)
  	if isNull || err != nil {
  		return "", true, err
  	}
  	byteLen := int64(len(str))
  	if pos < 0 {
  		pos += byteLen
  	} else {
  		pos--
  	}
  	if pos > byteLen || pos < 0 {
  		pos = byteLen
  	}
  	end := pos + length
  	if end < pos {
  		return "", false, nil
  	} else if end < byteLen {
  		return str[pos:end], false, nil
  	}
  	return str[pos:], false, nil
  }
docs: // evalString evals SUBSTR(str,pos,len), SUBSTR(str FROM pos FOR len), SUBSTR() is a synonym for SUBSTRING().
  // See https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_substr