Repository: pingcap/tidb
File: pkg/util/ranger/detacher.go (Go)

Code before:
	}
	var bestRes *cnfItemRangeResult
	columnValues := make([]*valueInfo, len(cols))
	for i, cond := range conds {
		tmpConds := []expression.Expression{cond}
		colSets := expression.ExtractColumnSet(cond)
		if colSets.Len() == 0 {
			continue
		}
		// When we build ranges for the CNF item, we choose not to merge consecutive ranges because we hope to get point
		// ranges here. See https://github.com/pingcap/tidb/issues/41572 for more details.
		//
		// Here is an example. Assume that the index is `idx(a,b,c)` and the condition is `((a,b) in ((1,1),(1,2)) and c = 1`.
		// We build ranges for `(a,b) in ((1,1),(1,2))` and get `[1 1, 1 1] [1 2, 1 2]`, which are point ranges and we can
		// append `c = 1` to the point ranges. However, if we choose to merge consecutive ranges here, we get `[1 1, 1 2]`,
		// which are not point ranges, and we cannot append `c = 1` anymore.
		res, err := detachCondAndBuildRange(sctx, tmpConds, cols, lengths, rangeMaxSize, convertToSortKey, false)
		if err != nil {
			return nil, nil, err
		}
		if len(res.Ranges) == 0 {
			return &cnfItemRangeResult{rangeResult: res, offset: i}, nil, nil
		}
		// take the union of the two columnValues
		columnValues = unionColumnValues(columnValues, res.ColumnValues)
		if len(res.AccessConds) == 0 || len(res.RemainedConds) > 0 {
			continue
		}
		curRes := getCNFItemRangeResult(sctx, res, i)
		bestRes = mergeTwoCNFRanges(sctx, cond, bestRes, curRes)
	}

	if bestRes != nil && bestRes.rangeResult != nil {
		bestRes.rangeResult.IsDNFCond = false
	}
	return bestRes, columnValues, nil
}

func unionColumnValues(lhs, rhs []*valueInfo) []*valueInfo {
	if lhs == nil {
		return rhs
	}
	if rhs != nil {
		for i, valInfo := range lhs {
			if i >= len(rhs) {
				break
			}
			if valInfo == nil && rhs[i] != nil {
				lhs[i] = rhs[i]
			}
		}

Review comment (suggestion):
nice fix
how about add the comment here
// for a=1 or b =1 and c =1 of index(a,b), although we can only use first two of them as access conds.
		// we can also keep the range from (a=1 or b =1) into consecutive merge consideration.

Code after:
	}
	var bestRes *cnfItemRangeResult
	columnValues := make([]*valueInfo, len(cols))
	for i, cond := range conds {
		tmpConds := []expression.Expression{cond}
		colSets := expression.ExtractColumnSet(cond)
		if colSets.Len() == 0 {
			continue
		}
		// When we build ranges for the CNF item, we choose not to merge consecutive ranges because we hope to get point
		// ranges here. See https://github.com/pingcap/tidb/issues/41572 for more details.
		//
		// Here is an example. Assume that the index is `idx(a,b,c)` and the condition is `((a,b) in ((1,1),(1,2)) and c = 1`.
		// We build ranges for `(a,b) in ((1,1),(1,2))` and get `[1 1, 1 1] [1 2, 1 2]`, which are point ranges and we can
		// append `c = 1` to the point ranges. However, if we choose to merge consecutive ranges here, we get `[1 1, 1 2]`,
		// which are not point ranges, and we cannot append `c = 1` anymore.
		res, err := detachCondAndBuildRange(sctx, tmpConds, cols, lengths, rangeMaxSize, convertToSortKey, false)
		if err != nil {
			return nil, nil, err
		}
		if len(res.Ranges) == 0 {
			return &cnfItemRangeResult{rangeResult: res, offset: i}, nil, nil
		}
		// take the union of the two columnValues
		columnValues = unionColumnValues(columnValues, res.ColumnValues)
		if len(res.AccessConds) == 0 {
			continue
		}
		curRes := getCNFItemRangeResult(sctx, res, i)
		bestRes = mergeTwoCNFRanges(sctx, cond, bestRes, curRes)
	}
	if bestRes != nil && bestRes.rangeResult != nil {
		bestRes.rangeResult.IsDNFCond = false
	}
	return bestRes, columnValues, nil
}

func unionColumnValues(lhs, rhs []*valueInfo) []*valueInfo {
	if lhs == nil {
		return rhs
	}
	if rhs != nil {
		for i, valInfo := range lhs {
			if i >= len(rhs) {
				break
			}
			if valInfo == nil && rhs[i] != nil {
				lhs[i] = rhs[i]
			}
		}
	}