Пример #1
0
 private LanguageNode fold(LanguageNode in, EngineToken variety) {
   FunctionCall fc = (FunctionCall) in;
   ArrayList<ExpressionNode> grouped = new ArrayList<ExpressionNode>();
   ArrayList<ExpressionNode> same = new ArrayList<ExpressionNode>();
   ArrayList<ExpressionNode> others = new ArrayList<ExpressionNode>();
   for (ExpressionNode p : fc.getParameters()) {
     if (EngineConstant.FUNCTION.has(p, variety)) {
       if (p.isGrouped()) grouped.add(p);
       else same.add(p);
     } else {
       others.add(p);
     }
   }
   if (same.isEmpty() || !grouped.isEmpty()) return in;
   // if others is empty, this is op(op(a,b),op(c,d)), build op(a,b,c,d)
   // if others is not empty, this is op(a,op(b,c)) or op(op(a,b),c), build op(a,b,c)
   ArrayList<ExpressionNode> allsubs = new ArrayList<ExpressionNode>();
   for (ExpressionNode p : same) {
     FunctionCall pfc = (FunctionCall) p;
     allsubs.addAll(pfc.getParameters());
   }
   allsubs.addAll(others);
   // we're going to group this as well
   FunctionCall ofc = new FunctionCall(fc.getFunctionName(), allsubs);
   ofc.setGrouped();
   return ofc;
 }
Пример #2
0
 private LanguageNode handleInFunction(FunctionCall fc) {
   ExpressionNode lhs = fc.getParameters().get(0);
   if (EngineConstant.COLUMN.has(lhs) && parent.isQualifyingColumn((ColumnInstance) lhs)) {
     // only matches if all the rhs are constant
     for (ExpressionNode en : fc.getParameters(1)) {
       if (!EngineConstant.CONSTANT.has(en)) return fc;
     }
     ColumnInstance ci = (ColumnInstance) lhs;
     if (!parent.isQualifyingColumn(ci.getPEColumn())) return fc;
     ArrayList<ExpressionNode> subexprs = new ArrayList<ExpressionNode>();
     ArrayList<Part> parts = new ArrayList<Part>();
     for (ExpressionNode en : fc.getParameters(1)) {
       ColumnInstance tci = (ColumnInstance) ci.copy(null);
       ConstantExpression litex = (ConstantExpression) en;
       ExpressionNode subeq = new FunctionCall(FunctionName.makeEquals(), tci, litex);
       Part p = buildPart(subeq, tci, litex);
       parts.add(p);
       subexprs.add((ExpressionNode) p.getParent());
     }
     if (subexprs.size() > 1) {
       FunctionCall orcall = new FunctionCall(FunctionName.makeOr(), subexprs);
       OredParts pc = parent.buildOredParts(orcall, parts);
       if (pc.isComplete()) setComplete(pc);
       orcall.setGrouped();
       state.put(orcall, pc);
       return orcall;
     } else {
       Part p = parts.get(0);
       return p.getParent();
     }
   }
   return fc;
 }
Пример #3
0
    private LanguageNode handleOrFunction(FunctionCall fc) {
      ArrayList<Part> subparts = new ArrayList<Part>();
      for (ExpressionNode en : fc.getParameters()) {
        Part p = state.get(en);
        if (p == null) {
          broadening();
          return fc;
        }
        subparts.add(p);
      }
      // now to figure out what we have.  we may have a a bunch of incomplete subexprs,
      // in which case we took a = 1 or a = 2 or a = 3 => a part collection of incompletes
      // or we may have (a = 1 and b = 2) or (a =3 and b =4) ... - likewise
      // or they maybe complete.  regardless, just build a partcollection and move on.
      // sort subparts by table key; if there's more than one let's just set broadening for now
      TableKey tk = null;
      for (Part p : subparts) {
        if (tk == null) tk = p.getTableKey();
        else if (!tk.equals(p.getTableKey())) {
          broadening();
          return fc;
        }
      }
      OredParts op = parent.buildOredParts(fc, subparts);
      if (op.isComplete()) setComplete(op);

      state.put(fc, op);
      return fc;
    }
Пример #4
0
    private LanguageNode handleAndFunction(FunctionCall fc) {
      // and functions take incomplete simple parts and turn them into complete parts, if so desired
      ArrayList<Part> incompletes = new ArrayList<Part>();
      ArrayList<ExpressionNode> ok = new ArrayList<ExpressionNode>();
      ArrayList<Part> subparts = new ArrayList<Part>();
      for (ExpressionNode en : fc.getParameters()) {
        Part p = state.get(en);
        if (p == null || p.isComplete()) {
          ok.add(en);
          if (p != null) subparts.add(p);
          continue;
        }
        incompletes.add(p);
      }
      if (incompletes.isEmpty()) return fc;

      // now we have the problem of a mishmash of incompletes.  some may be complex, some may be
      // simple
      // some may be collections.  we need to handle cases like the following:
      // (a = 1) and (b = 2) {a,b} (1 key)
      // (a = 1) and (b = 2 or b = 3) {a,b} (2 keys)
      // (a = 1 or a = 2) and (b = 3) {a,b} (2 keys)
      // (a = 1 or a = 2) and (b = 3 or b = 4) {a,b} (4 keys here)
      // all of the above, where the result is still not complete due to missing tenant column

      MultiMap<Part, ColumnKey> needed = new MultiMap<Part, ColumnKey>();
      MultiMap<ColumnKey, Part> classified = new MultiMap<ColumnKey, Part>();
      for (Part p : incompletes) {
        ListSet<ColumnKey> has = new ListSet<ColumnKey>();
        has.addAll(p.getColumns());
        needed.putAll(p, parent.getNeeded(has));
        for (ColumnKey ck : has) {
          classified.put(ck, p);
        }
      }
      // so let's say we have a part that is (a = 1 and b = 2), needs c and tenant, and we have a
      // part
      // that is c in (1,2,3).  The needed for (a = 1 and b = 2) is {c,tenant}.  we'll pull (c in
      // (1,2,3))
      // so we'll get at least (a = 1 and b = 2 and c = 3) or (a = 1 and b =2 and c = 3) ...
      // these we can then individually try to complete.

      while (!needed.isEmpty()) {
        combineParts(needed, classified, ok, subparts);
      }
      for (Part p : subparts) state.put(p.getParent(), p);
      if (ok.size() == 1) return ok.get(0);
      else {
        // what's left is a mix of unrelated and complete or incomplete subexprs.  unrelated nodes
        // would come in from above, as would previously complete.
        return new FunctionCall(FunctionName.makeAnd(), ok);
      }
    }
Пример #5
0
 private LanguageNode handleEqualsFunction(FunctionCall fc) {
   ExpressionNode lhs = fc.getParameters().get(0);
   ExpressionNode rhs = fc.getParameters().get(1);
   if (EngineConstant.CONSTANT.has(rhs)
       && EngineConstant.COLUMN.has(lhs)
       && parent.isQualifyingColumn((ColumnInstance) lhs)) {
     ColumnInstance ci = (ColumnInstance) lhs;
     ConstantExpression litex = (ConstantExpression) rhs;
     PEColumn c = ci.getPEColumn();
     if (parent.isQualifyingColumn(c)) {
       Part p = buildPart(fc, ci, litex);
       return p.getParent();
     }
   }
   return fc;
 }
Пример #6
0
  /** @param useRhs Collect RHS columns if TRUE, and LHS columns otherwise. */
  private Set<ColumnKey> collectColumnsFromJoinConditions(
      final ListSet<ExpressionNode> joinConditions, final boolean useRhs) {
    final int sideIndex = (useRhs) ? 1 : 0;
    final Set<ColumnKey> columnKeys =
        new TreeSet<ColumnKey>(
            new Comparator<ColumnKey>() {
              @Override
              public int compare(ColumnKey c1, ColumnKey c2) {
                final int p1 = c1.getPEColumn().getPosition();
                final int p2 = c2.getPEColumn().getPosition();
                return p1 - p2;
              }
            });

    for (final ExpressionNode condition : joinConditions) {
      final FunctionCall columnEquality = (FunctionCall) condition;
      final ColumnInstance ci = (ColumnInstance) columnEquality.getParameters().get(sideIndex);
      columnKeys.add(ci.getColumnKey());
    }

    return columnKeys;
  }