/**
  * 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);
           }
         }
       });
 }
 /**
  * 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);
         }
       });
 }
예제 #3
0
  /**
   * 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;
  }
예제 #4
0
 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;
 }
예제 #5
0
  /**
   * 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];
    }
  }
예제 #6
0
 static {
   for (Map.Entry<Method, SqlOperator> entry : JAVA_TO_SQL_METHOD_MAP.entrySet()) {
     SQL_OP_TO_JAVA_METHOD_MAP.put(entry.getValue(), entry.getKey());
   }
 }
예제 #7
0
  /** 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);
    }
  }
예제 #8
0
 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);
 }