package com.taobao.tddl.optimizer.utils.range; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import com.taobao.tddl.optimizer.core.expression.IBooleanFilter; import com.taobao.tddl.optimizer.core.expression.IFilter; /** * 比如条件 a>10 || a=5 ||a < 1 min=1 max=10 equalList=[5] * * @author jianghang 2013-11-13 下午4:23:29 * @since 5.0.0 */ public class OrRangeProcessor extends AbstractRangeProcessor { private boolean fullSet = false; private final List<List<IFilter>> otherFilters = new ArrayList(); private final List<Range> ranges = new LinkedList<Range>(); private final Object column; public OrRangeProcessor(Object c){ this.column = c; } public boolean isFullSet() { return fullSet; } @Override public boolean process(IFilter node) { if (isFullSet()) { return true; } Range range = getRange((IBooleanFilter) node); if (range == null) { List<IFilter> f = new ArrayList(); f.add(node); otherFilters.add(new ArrayList(f)); } for (int i = 0; i < ranges.size(); i++) { Range rangeExisted = ranges.get(i); if (rangeExisted.intersects(range)) { // 两个区间有交际,但又互不是包含关系,则为全集,比如 a < 2 or a > 1 if (!rangeExisted.contains(range) && !range.contains(rangeExisted)) { this.fullSet = true; return true; } else { // 若存在包含关系,则取并集 ranges.set(i, rangeExisted.union(range)); return true; } } else { // 如果不相交,则判断是否是=,并判断能否合并,比如 A > 5 , A = 5 if (range.isSingleValue()) { if (range.getMaxValue().equals(rangeExisted.getMinValue()) || range.getMaxValue().equals(rangeExisted.getMaxValue())) { ranges.set(i, rangeExisted.union(range)); return true; } } if (rangeExisted.isSingleValue()) { if (rangeExisted.getMaxValue().equals(range.getMinValue()) || rangeExisted.getMaxValue().equals(range.getMaxValue())) { ranges.set(i, rangeExisted.union(range)); return true; } } } } // 若跟已存在的哪个区间都没有交集,则为独立的区间,加到range列表里 if (range != null) { ranges.add(range); } return true; } public List<List<IFilter>> toFilterList() { List<List<IFilter>> DNFNodes = new LinkedList(); if (this.isFullSet()) { return new LinkedList<List<IFilter>>(); } DNFNodes.addAll(this.otherFilters); for (Range range : ranges) { DNFNodes.add(buildFilter(range, column)); } return DNFNodes; } }