code: func TableRangesToKVRanges(tid int64, ranges []*ranger.Range, fb *statistics.QueryFeedback) []kv.KeyRange {
  	if fb == nil || fb.Hist == nil {
  		return tableRangesToKVRangesWithoutSplit(tid, ranges)
  	}
  	krs := make([]kv.KeyRange, 0, len(ranges))
  	feedbackRanges := make([]*ranger.Range, 0, len(ranges))
  	for _, ran := range ranges {
  		low := codec.EncodeInt(nil, ran.LowVal[0].GetInt64())
  		high := codec.EncodeInt(nil, ran.HighVal[0].GetInt64())
  		if ran.LowExclude {
  			low = []byte(kv.Key(low).PrefixNext())
  		}
  		// If this range is split by histogram, then the high val will equal to one bucket's upper bound,
  		// since we need to guarantee each range falls inside the exactly one bucket, `PerfixNext` will make the
  		// high value greater than upper bound, so we store the range here.
  		r := &ranger.Range{LowVal: []types.Datum{types.NewBytesDatum(low)},
  			HighVal: []types.Datum{types.NewBytesDatum(high)}}
  		feedbackRanges = append(feedbackRanges, r)
  
  		if !ran.HighExclude {
  			high = []byte(kv.Key(high).PrefixNext())
  		}
  		startKey := tablecodec.EncodeRowKey(tid, low)
  		endKey := tablecodec.EncodeRowKey(tid, high)
  		krs = append(krs, kv.KeyRange{StartKey: startKey, EndKey: endKey})
  	}
  	fb.StoreRanges(feedbackRanges)
  	return krs
  }
docs: // TableRangesToKVRanges converts table ranges to "KeyRange".