public SqlRexConvertlet get(SqlCall call) { SqlRexConvertlet convertlet; final SqlOperator op = call.getOperator(); // Is there a convertlet for this operator // (e.g. SqlStdOperatorTable.plusOperator)? convertlet = (SqlRexConvertlet) map.get(op); if (convertlet != null) { return convertlet; } // Is there a convertlet for this class of operator // (e.g. SqlBinaryOperator)? Class<? extends Object> clazz = op.getClass(); while (clazz != null) { convertlet = (SqlRexConvertlet) map.get(clazz); if (convertlet != null) { return convertlet; } clazz = clazz.getSuperclass(); } // Is there a convertlet for this class of expression // (e.g. SqlCall)? clazz = call.getClass(); while (clazz != null) { convertlet = (SqlRexConvertlet) map.get(clazz); if (convertlet != null) { return convertlet; } clazz = clazz.getSuperclass(); } return null; }
private Expression translate0(RexNode expr) { if (expr instanceof RexInputRef) { // TODO: multiple inputs, e.g. joins final Expression input = getInput(0); final int index = ((RexInputRef) expr).getIndex(); final List<RelDataTypeField> fields = program.getInputRowType().getFieldList(); final RelDataTypeField field = fields.get(index); if (fields.size() == 1) { return input; } else if (input.getType() == Object[].class) { return Expressions.convert_( Expressions.arrayIndex(input, Expressions.constant(field.getIndex())), Types.box(JavaRules.EnumUtil.javaClass(typeFactory, field.getType()))); } else { return Expressions.field(input, field.getName()); } } if (expr instanceof RexLocalRef) { return translate(program.getExprList().get(((RexLocalRef) expr).getIndex())); } if (expr instanceof RexLiteral) { return Expressions.constant( ((RexLiteral) expr).getValue(), typeFactory.getJavaClass(expr.getType())); } if (expr instanceof RexCall) { final RexCall call = (RexCall) expr; final SqlOperator operator = call.getOperator(); final ExpressionType expressionType = SQL_TO_LINQ_OPERATOR_MAP.get(operator); if (expressionType != null) { switch (operator.getSyntax()) { case Binary: return Expressions.makeBinary( expressionType, translate(call.getOperands()[0]), translate(call.getOperands()[1])); case Postfix: case Prefix: return Expressions.makeUnary(expressionType, translate(call.getOperands()[0])); default: throw new RuntimeException("unknown syntax " + operator.getSyntax()); } } Method method = SQL_OP_TO_JAVA_METHOD_MAP.get(operator); if (method != null) { List<Expression> exprs = translateList(Arrays.asList(call.operands)); return !Modifier.isStatic(method.getModifiers()) ? Expressions.call(exprs.get(0), method, exprs.subList(1, exprs.size())) : Expressions.call(method, exprs); } switch (expr.getKind()) { default: throw new RuntimeException("cannot translate expression " + expr); } } throw new RuntimeException("cannot translate expression " + expr); }
/** * 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; }
private Expression translate(RexNode expr) { Slot slot = map.get(expr); if (slot == null) { Expression expression = translate0(expr); assert expression != null; final ParameterExpression parameter; if (!inlineRexSet.contains(expr) && !(expr instanceof RexLocalRef)) { parameter = Expressions.parameter(expression.getType(), "v" + map.size()); } else { parameter = null; } slot = new Slot(parameter, expression); if (parameter != null && list != null) { list.add(Expressions.declare(Modifier.FINAL, slot.parameterExpression, slot.expression)); } map.put(expr, slot); } slot.count++; return slot.parameterExpression != null ? slot.parameterExpression : slot.expression; }
/** * Adds on to the existing join condition reference counts the references from the new join * condition. * * @param multiJoinInputs inputs into the new MultiJoinRel * @param nTotalFields total number of fields in the MultiJoinRel * @param joinCondition the new join condition * @param origJoinFieldRefCounts existing join condition reference counts * @param newJoinFieldRefCountsMap map containing the new join condition reference counts, indexed * by input # */ private void addOnJoinFieldRefCounts( RelNode[] multiJoinInputs, int nTotalFields, RexNode joinCondition, List<int[]> origJoinFieldRefCounts, Map<Integer, int[]> newJoinFieldRefCountsMap) { // count the input references in the join condition int[] joinCondRefCounts = new int[nTotalFields]; joinCondition.accept(new InputReferenceCounter(joinCondRefCounts)); // first, make a copy of the ref counters int nInputs = multiJoinInputs.length; int currInput = 0; for (int[] origRefCounts : origJoinFieldRefCounts) { newJoinFieldRefCountsMap.put(currInput, (int[]) origRefCounts.clone()); currInput++; } // add on to the counts for each input into the MultiJoinRel the // reference counts computed for the current join condition currInput = -1; int startField = 0; int nFields = 0; for (int i = 0; i < nTotalFields; i++) { if (joinCondRefCounts[i] == 0) { continue; } while (i >= (startField + nFields)) { startField += nFields; currInput++; assert (currInput < nInputs); nFields = multiJoinInputs[currInput].getRowType().getFieldCount(); } int[] refCounts = newJoinFieldRefCountsMap.get(currInput); refCounts[i - startField] += joinCondRefCounts[i]; } }
/** 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); } }