/** * Registers method if it: a. is public, and b. is named "convertXxx", and c. has a return type of * "RexNode" or a subtype d. has a 2 parameters with types ConvertletContext and SqlNode (or a * subtype) respectively. */ private void registerNodeTypeMethod(final Method method) { if (!Modifier.isPublic(method.getModifiers())) { return; } if (!method.getName().startsWith("convert")) { return; } if (!RexNode.class.isAssignableFrom(method.getReturnType())) { return; } final Class[] parameterTypes = method.getParameterTypes(); if (parameterTypes.length != 2) { return; } if (parameterTypes[0] != SqlRexContext.class) { return; } final Class parameterType = parameterTypes[1]; if (!SqlNode.class.isAssignableFrom(parameterType)) { return; } map.put( parameterType, new SqlRexConvertlet() { public RexNode convertCall(SqlRexContext cx, SqlCall call) { try { return (RexNode) method.invoke(ReflectiveConvertletTable.this, cx, call); } catch (IllegalAccessException e) { throw Util.newInternal(e, "while converting " + call); } catch (InvocationTargetException e) { throw Util.newInternal(e, "while converting " + call); } } }); }
protected RexNode register(RexNode expr) { final String key = expr.toString(); final RexNode previous = mapDigestToExpr.put(key, expr); if (!allowDups && (previous != null)) { throw new SubExprExistsException(expr); } return expr; }
/** * Registers that one operator is an alias for another. * * @param alias Operator which is alias * @param target Operator to translate calls to */ protected void addAlias(final SqlOperator alias, final SqlOperator target) { map.put( alias, new SqlRexConvertlet() { public RexNode convertCall(SqlRexContext cx, SqlCall call) { Util.permAssert(call.getOperator() == alias, "call to wrong operator"); final SqlCall newCall = target.createCall(SqlParserPos.ZERO, call.getOperandList()); return cx.convertExpression(newCall); } }); }
/** * 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; }
protected void registerSchema(MockSchema schema) { schemas.put(schema.name, schema); }
/** 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 registerConvertlet(SqlOperator op, CallConvertlet convertlet) { convertletMap.put(op, convertlet); }
/** * Registers a convertlet for a given operator instance * * @param op Operator instance, say {@link org.eigenbase.sql.fun.SqlStdOperatorTable#MINUS} * @param convertlet Convertlet */ protected void registerOp(SqlOperator op, SqlRexConvertlet convertlet) { map.put(op, convertlet); }