예제 #1
0
  private SargIntervalSequence evaluateIntersection(List<SargIntervalSequence> list) {
    SargIntervalSequence seq = null;

    if (list.isEmpty()) {
      // Counterintuitive but true: intersection of no sets is the
      // universal set (kinda like 2^0=1).  One way to prove this to
      // yourself is to apply DeMorgan's law.  The union of no sets is
      // certainly the empty set.  So the complement of that union is the
      // universal set.  That's equivalent to the intersection of the
      // complements of no sets, which is the intersection of no sets.
      // QED.
      seq = new SargIntervalSequence();
      seq.addInterval(new SargInterval(factory, getDataType()));
      return seq;
    }

    // The way we evaluate the intersection is to start with the first
    // entry as a baseline, and then keep deleting stuff from it by
    // intersecting the other entrie in turn.  Whatever makes it through
    // this filtering remains as the final result.
    for (SargIntervalSequence newSeq : list) {
      if (seq == null) {
        // first child
        seq = newSeq;
        continue;
      }
      intersectSequences(seq, newSeq);
    }

    return seq;
  }
예제 #2
0
  /**
   * Analyzes a rex predicate.
   *
   * @param rexPredicate predicate to be analyzed
   * @return a list of SargBindings contained in the input rex predicate
   */
  public List<SargBinding> analyzeAll(RexNode rexPredicate) {
    sargBindingList = new ArrayList<SargBinding>();
    sarg2RexMap = new HashMap<SargExpr, RexNode>();
    nonSargFilterList = new ArrayList<RexNode>();

    // Flatten out the RexNode tree into a list of terms that
    // are AND'ed together
    final List<RexNode> rexCFList = RelOptUtil.conjunctions(rexPredicate);

    // In simple mode, each input ref can only be referenced once, so
    // keep a list of them.  We also only allow one non-point expression.
    List<Integer> boundRefList = new ArrayList<Integer>();
    boolean rangeFound = false;

    for (RexNode rexPred : rexCFList) {
      final SargBinding sargBinding = analyze(rexPred);
      if (sargBinding != null) {
        if (simpleMode) {
          RexInputRef inputRef = sargBinding.getInputRef();
          if (boundRefList.contains(inputRef.getIndex())) {
            nonSargFilterList.add(rexPred);
            continue;
          } else {
            boundRefList.add(inputRef.getIndex());
          }
          SargIntervalSequence sargSeq = sargBinding.getExpr().evaluate();
          if (sargSeq.isRange()) {
            if (rangeFound) {
              nonSargFilterList.add(rexPred);
              continue;
            } else {
              rangeFound = true;
            }
          }
        }
        sargBindingList.add(sargBinding);
        sarg2RexMap.put(sargBinding.getExpr(), rexPred);
      } else {
        nonSargFilterList.add(rexPred);
      }
    }

    // Reset the state variables used during analyze, just for sanity sake.
    failed = false;
    boundInputRef = null;
    clearLeaf();

    // Combine the AND terms back together.
    recomposeConjunction();

    return sargBindingList;
  }
예제 #3
0
  private SargIntervalSequence evaluateUnion(List<SargIntervalSequence> list) {
    SargIntervalSequence seq = new SargIntervalSequence();

    // Toss all entries from each sequence in the list into one big sorted
    // set.
    SortedSet<SargInterval> intervals = new TreeSet<SargInterval>(new IntervalComparator());
    for (SargIntervalSequence childSeq : list) {
      intervals.addAll(childSeq.getList());
    }

    // Now, overlapping ranges are consecutive in the set.  Merge them by
    // increasing the upper bound of the first; discard the others.  In the
    // example, [4, 6] and [5, 7) are combined to form [4, 7).  (7, 8] is
    // not merged with the new range because neither range contains the
    // value 7.
    //
    // Input:
    //          1  2  3  4  5  6  7  8  9
    // 1 [1, 3] [-----]
    // 2 [4, 6]          [-----]
    // 3 [5, 7)             [-----)
    // 4 (7, 8]                   (--]
    //
    // Output:
    // 1 [1, 3] [-----]
    // 2 [4, 7)          [--------)
    // 3 (7, 8]                   (--]
    SargInterval accumulator = null;
    for (SargInterval interval : intervals) {
      // Empty intervals should have been previously filtered out.
      assert (!interval.isEmpty());

      if (accumulator == null) {
        // The very first interval:  start accumulating.
        accumulator = new SargInterval(factory, getDataType());
        accumulator.copyFrom(interval);
        seq.addInterval(accumulator);
        continue;
      }

      if (accumulator.contains(interval)) {
        // Just drop new interval because it's already covered
        // by accumulator.
        continue;
      }

      // Test for overlap.
      int c = interval.getLowerBound().compareTo(accumulator.getUpperBound());

      // If no overlap, test for touching instead.
      if (c > 0) {
        if (interval.getLowerBound().isTouching(accumulator.getUpperBound())) {
          // Force test below to pass.
          c = -1;
        }
      }

      if (c <= 0) {
        // Either touching or overlap:  grow the accumulator.
        accumulator.upperBound.copyFrom(interval.getUpperBound());
      } else {
        // Disjoint:  start accumulating a new interval
        accumulator = new SargInterval(factory, getDataType());
        accumulator.copyFrom(interval);
        seq.addInterval(accumulator);
      }
    }

    return seq;
  }