code: func detachColumnDNFConditions(sctx sessionctx.Context, conditions []expression.Expression, checker *conditionChecker) ([]expression.Expression, bool) {
  	var (
  		hasResidualConditions bool
  		accessConditions      []expression.Expression
  	)
  	for _, cond := range conditions {
  		if sf, ok := cond.(*expression.ScalarFunction); ok && sf.FuncName.L == ast.LogicAnd {
  			cnfItems := expression.FlattenCNFConditions(sf)
  			columnCNFItems, others := detachColumnCNFConditions(sctx, cnfItems, checker)
  			if len(others) > 0 {
  				hasResidualConditions = true
  			}
  			// If one part of DNF has no access condition. Then this DNF cannot get range.
  			if len(columnCNFItems) == 0 {
  				return nil, true
  			}
  			rebuildCNF := expression.ComposeCNFCondition(sctx, columnCNFItems...)
  			accessConditions = append(accessConditions, rebuildCNF)
  		} else if checker.check(cond) {
  			accessConditions = append(accessConditions, cond)
  			if checker.shouldReserve {
  				hasResidualConditions = true
  				checker.shouldReserve = checker.length != types.UnspecifiedLength
  			}
  		} else {
  			return nil, true
  		}
  	}
  	return accessConditions, hasResidualConditions
  }
docs: // detachColumnDNFConditions detaches the condition for calculating range from the other conditions.
  // Please make sure that the top level is DNF form.