/** * Determines if a filter condition is a simple one and returns the parameters corresponding to * the simple filters. * * @param calcRel original CalcRel * @param filterExprs filter expression being analyzed * @param filterList returns the list of filter ordinals in the simple expression * @param literals returns the list of literals to be used in the simple comparisons * @param op returns the operator to be used in the simple comparison * @return true if the filter condition is simple */ private boolean isConditionSimple( CalcRel calcRel, RexNode filterExprs, List<Integer> filterList, List<RexLiteral> literals, List<CompOperatorEnum> op) { SargFactory sargFactory = new SargFactory(calcRel.getCluster().getRexBuilder()); SargRexAnalyzer rexAnalyzer = sargFactory.newRexAnalyzer(true); List<SargBinding> sargBindingList = rexAnalyzer.analyzeAll(filterExprs); // Currently, it's all or nothing. So, if there are filters rejected // by the analyzer, we can't process a subset using the reshape // exec stream if (rexAnalyzer.getNonSargFilterRexNode() != null) { return false; } List<RexInputRef> filterCols = new ArrayList<RexInputRef>(); List<RexNode> filterOperands = new ArrayList<RexNode>(); if (FennelRelUtil.extractSimplePredicates(sargBindingList, filterCols, filterOperands, op)) { for (RexInputRef filterCol : filterCols) { filterList.add(filterCol.getIndex()); } for (RexNode operand : filterOperands) { literals.add((RexLiteral) operand); } return true; } else { return false; } }
/** * Reconstructs a rex predicate from a list of SargBindings which are AND'ed together. * * @param sargBindingList list of SargBindings to be converted. * @return the rex predicate reconstructed from the list of SargBindings. */ public RexNode getSargBindingListToRexNode(List<SargBinding> sargBindingList) { if (sargBindingList.isEmpty()) { return null; } RexNode newAndNode = sarg2RexMap.get(sargBindingList.get(0).getExpr()); for (int i = 1; i < sargBindingList.size(); i++) { RexNode nextNode = sarg2RexMap.get(sargBindingList.get(i).getExpr()); newAndNode = factory.getRexBuilder().makeCall(SqlStdOperatorTable.andOperator, newAndNode, nextNode); } return newAndNode; }
/** * Reconstructs a rex predicate from the non-sargable filter predicates which are AND'ed together. * * @return the rex predicate reconstructed from the non-sargable predicates. */ public RexNode getNonSargFilterRexNode() { if (nonSargFilterList.isEmpty()) { return null; } RexNode newAndNode = nonSargFilterList.get(0); for (int i = 1; i < nonSargFilterList.size(); i++) { newAndNode = factory .getRexBuilder() .makeCall(SqlStdOperatorTable.andOperator, newAndNode, nonSargFilterList.get(i)); } return newAndNode; }
/** 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); } }