private void analyzeCall(RexCall call, Constancy callConstancy) { parentCallTypeStack.add(call.getOperator()); // visit operands, pushing their states onto stack super.visitCall(call); // look for NON_CONSTANT operands int nOperands = call.getOperands().length; List<Constancy> operandStack = stack.subList(stack.size() - nOperands, stack.size()); for (Constancy operandConstancy : operandStack) { if (operandConstancy == Constancy.NON_CONSTANT) { callConstancy = Constancy.NON_CONSTANT; } } // Even if all operands are constant, the call itself may // be non-deterministic. if (!call.getOperator().isDeterministic()) { callConstancy = Constancy.NON_CONSTANT; } else if (call.getOperator().isDynamicFunction()) { // We can reduce the call to a constant, but we can't // cache the plan if the function is dynamic preparingStmt.disableStatementCaching(); } // Row operator itself can't be reduced to a literal, but if // the operands are constants, we still want to reduce those if ((callConstancy == Constancy.REDUCIBLE_CONSTANT) && (call.getOperator() instanceof SqlRowOperator)) { callConstancy = Constancy.NON_CONSTANT; } if (callConstancy == Constancy.NON_CONSTANT) { // any REDUCIBLE_CONSTANT children are now known to be maximal // reducible subtrees, so they can be added to the result // list for (int iOperand = 0; iOperand < nOperands; ++iOperand) { Constancy constancy = operandStack.get(iOperand); if (constancy == Constancy.REDUCIBLE_CONSTANT) { addResult(call.getOperands()[iOperand]); } } // if this cast expression can't be reduced to a literal, // then see if we can remove the cast if (call.getOperator() == SqlStdOperatorTable.castFunc) { reduceCasts(call); } } // pop operands off of the stack operandStack.clear(); // pop this parent call operator off the stack parentCallTypeStack.remove(parentCallTypeStack.size() - 1); // push constancy result for this call onto stack stack.add(callConstancy); }
/** 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); } }