code: func (cc *clientConn) writeResultset(ctx context.Context, rs ResultSet, binary bool, serverStatus uint16, fetchSize int) (runErr error) {
  	defer func() {
  		// close ResultSet when cursor doesn't exist
  		if !mysql.HasCursorExistsFlag(serverStatus) {
  			terror.Call(rs.Close)
  		}
  		r := recover()
  		if r == nil {
  			return
  		}
  		if str, ok := r.(string); !ok || !strings.HasPrefix(str, memory.PanicMemoryExceed) {
  			panic(r)
  		}
  		// TODO(jianzhang.zj: add metrics here)
  		runErr = errors.Errorf("%v", r)
  		buf := make([]byte, 4096)
  		stackSize := runtime.Stack(buf, false)
  		buf = buf[:stackSize]
  		logutil.Logger(ctx).Error("write query result panic", zap.String("lastCmd", cc.lastCmd), zap.String("stack", string(buf)))
  	}()
  	var err error
  	if mysql.HasCursorExistsFlag(serverStatus) {
  		err = cc.writeChunksWithFetchSize(ctx, rs, serverStatus, fetchSize)
  	} else {
  		err = cc.writeChunks(ctx, rs, binary, serverStatus)
  	}
  	if err != nil {
  		return err
  	}
  	return cc.flush()
  }
docs: // writeResultset writes data into a resultset and uses rs.Next to get row data back.
  // If binary is true, the data would be encoded in BINARY format.
  // serverStatus, a flag bit represents server information.
  // fetchSize, the desired number of rows to be fetched each time when client uses cursor.
  // resultsets, it's used to support the MULTI_RESULTS capability in mysql protocol.