code: func Select(ctx context.Context, sctx sessionctx.Context, kvReq *kv.Request, fieldTypes []*types.FieldType, fb *statistics.QueryFeedback) (SelectResult, error) {
  	// For testing purpose.
  	if hook := ctx.Value("CheckSelectRequestHook"); hook != nil {
  		hook.(func(*kv.Request))(kvReq)
  	}
  
  	if !sctx.GetSessionVars().EnableStreaming {
  		kvReq.Streaming = false
  	}
  	resp := sctx.GetClient().Send(ctx, kvReq, sctx.GetSessionVars().KVVars)
  	if resp == nil {
  		err := errors.New("client returns nil response")
  		return nil, err
  	}
  
  	// kvReq.MemTracker is used to trace and control memory usage in DistSQL layer;
  	// for streamResult, since it is a pipeline which has no buffer, it's not necessary to trace it;
  	// for selectResult, we just use the kvReq.MemTracker prepared for co-processor
  	// instead of creating a new one for simplification.
  	if kvReq.Streaming {
  		return &streamResult{
  			resp:       resp,
  			rowLen:     len(fieldTypes),
  			fieldTypes: fieldTypes,
  			ctx:        sctx,
  			feedback:   fb,
  		}, nil
  	}
  
  	label := metrics.LblGeneral
  	if sctx.GetSessionVars().InRestrictedSQL {
  		label = metrics.LblInternal
  	}
  	return &selectResult{
  		label:      "dag",
  		resp:       resp,
  		results:    make(chan resultWithErr, kvReq.Concurrency),
  		closed:     make(chan struct{}),
  		rowLen:     len(fieldTypes),
  		fieldTypes: fieldTypes,
  		ctx:        sctx,
  		feedback:   fb,
  		sqlType:    label,
  		memTracker: kvReq.MemTracker,
  	}, nil
  }
docs: // Select sends a DAG request, returns SelectResult.
  // In kvReq, KeyRanges is required, Concurrency/KeepOrder/Desc/IsolationLevel/Priority are optional.