// implement CallConvertlet public void convert(RexCall call) { // REVIEW jvs 18-Mar-2006: The test for variableSeen // here and elsewhere precludes predicates like where // (boolean_col AND (int_col > 10)). Should probably // support bare boolean columns as predicates with // coordinate TRUE. if (variableSeen || (coordinate != null)) { failed = true; } if (failed) { return; } int nOperands = call.getOperands().size(); assert (exprStack.size() >= nOperands); SargSetExpr expr = factory.newSetExpr(boundInputRef.getType(), setOp); // Pop the correct number of operands off the stack // and transfer them to the new set expression. ListIterator<SargExpr> iter = exprStack.listIterator(exprStack.size() - nOperands); while (iter.hasNext()) { expr.addChild(iter.next()); iter.remove(); } exprStack.add(expr); }
/** Reconstructs a rex predicate from a list of SargExprs which will be AND'ed together. */ private void recomposeConjunction() { for (int i = 0; i < sargBindingList.size(); i++) { final SargBinding currBinding = sargBindingList.get(i); final RexInputRef currRef = currBinding.getInputRef(); SargExpr currSargExpr = currBinding.getExpr(); RexNode currAndNode = sarg2RexMap.get(currSargExpr); // don't need this anymore // will be have new mapping put back if currSargExpr remain // unchanged. sarg2RexMap.remove(currSargExpr); boolean recomp = false; // search the rest of the list to find SargExpr on the same col. ListIterator<SargBinding> iter = sargBindingList.listIterator(i + 1); while (iter.hasNext()) { final SargBinding nextBinding = iter.next(); final RexInputRef nextRef = nextBinding.getInputRef(); final SargExpr nextSargExpr = nextBinding.getExpr(); if (nextRef.getIndex() == currRef.getIndex()) { // build new SargExpr SargSetExpr expr = factory.newSetExpr(currSargExpr.getDataType(), SargSetOperator.INTERSECTION); expr.addChild(currSargExpr); expr.addChild(nextSargExpr); // build new RexNode currAndNode = factory .getRexBuilder() .makeCall( SqlStdOperatorTable.andOperator, currAndNode, sarg2RexMap.get(nextSargExpr)); currSargExpr = expr; sarg2RexMap.remove(nextSargExpr); iter.remove(); recomp = true; } } if (recomp) { assert !simpleMode; if (!testDynamicParamSupport(currSargExpr)) { // Oops, we can't actually support the conjunction we // recomposed. Toss it. (We could do a better job by at // least using part of it, but the effort might be better // spent on implementing deferred expression evaluation.) nonSargFilterList.add(currAndNode); sargBindingList.remove(i); continue; } } if (recomp) { SargBinding newBinding = new SargBinding(currSargExpr, currRef); sargBindingList.remove(i); sargBindingList.add(i, newBinding); } sarg2RexMap.put(currSargExpr, currAndNode); } }
private void intersectSequences(SargIntervalSequence targetSeq, SargIntervalSequence sourceSeq) { ListIterator<SargInterval> targetIter = targetSeq.list.listIterator(); if (!targetIter.hasNext()) { // No target intervals at all, so quit. return; } ListIterator<SargInterval> sourceIter = sourceSeq.list.listIterator(); if (!sourceIter.hasNext()) { // No source intervals at all, so result is empty targetSeq.list.clear(); return; } // Start working on first source and target intervals SargInterval target = targetIter.next(); SargInterval source = sourceIter.next(); // loop invariant: both source and target are non-null on entry for (; ; ) { if (source.getUpperBound().compareTo(target.getLowerBound()) < 0) { // Source is completely below target; discard it and // move on to next one. if (!sourceIter.hasNext()) { // No more sources. break; } source = sourceIter.next(); continue; } if (target.getUpperBound().compareTo(source.getLowerBound()) < 0) { // Target is completely below source; discard it and // move on to next one. targetIter.remove(); if (!targetIter.hasNext()) { // All done. return; } target = targetIter.next(); continue; } // Overlap case: perform intersection of the two intervals. if (source.getLowerBound().compareTo(target.getLowerBound()) > 0) { // Source starts after target starts, so trim the target. target.setLower( source.getLowerBound().getCoordinate(), source.getLowerBound().getStrictness()); } int c = source.getUpperBound().compareTo(target.getUpperBound()); if (c < 0) { // The source ends before the target ends, so split the target // into two parts. The first part will be kept for sure; the // second part will be compared against further source ranges. SargInterval newTarget = new SargInterval(factory, dataType); newTarget.setLower( source.getUpperBound().getCoordinate(), source.getUpperBound().getStrictnessComplement()); if (target.getUpperBound().isFinite()) { newTarget.setUpper( target.getUpperBound().getCoordinate(), target.getUpperBound().getStrictness()); } // Trim current target to exclude the part of the range // which will move to newTarget. target.setUpper( source.getUpperBound().getCoordinate(), source.getUpperBound().getStrictness()); // Insert newTarget after target. This makes newTarget // into previous(). targetIter.add(newTarget); // Next time through, work on newTarget. // targetIter.previous() is pointing at the newTarget. target = targetIter.previous(); // Now targetIter.next() is also pointing at the newTarget; // need to do this redundant step to get targetIter in sync // with target. target = targetIter.next(); // Advance source. if (!sourceIter.hasNext()) { break; } source = sourceIter.next(); } else if (c == 0) { // Source and target ends coincide, so advance both source and // target. if (!targetIter.hasNext()) { return; } target = targetIter.next(); if (!sourceIter.hasNext()) { break; } source = sourceIter.next(); } else { // Source ends after target ends, so advance target. assert (c > 0); if (!targetIter.hasNext()) { return; } target = targetIter.next(); } } // Discard any remaining targets since they didn't have corresponding // sources. for (; ; ) { targetIter.remove(); if (!targetIter.hasNext()) { break; } targetIter.next(); } }