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; }
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; }
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; }
private Part buildPart(LanguageNode parentNode, ColumnInstance ci, ConstantExpression litex) { EqualityPart sp = parent.buildEqualityPart(parentNode, ci, litex); if (parent.isComplete(sp)) { setComplete(sp); state.put(parentNode, sp); } else { AndedParts xformed = parent.maybeMakeComplete(sp); if (xformed != null) { setComplete(xformed); LanguageNode ret = xformed.getParent(); state.put(ret, xformed); return xformed; } else { state.put(sp.getParent(), sp); } } return sp; }
private Part buildNewComplexPart(Part lp, Part rp) { ListSet<Part> allParts = new ListSet<Part>(); allParts.addAll(lp.getParts()); allParts.addAll(rp.getParts()); FunctionCall andCall = new FunctionCall( FunctionName.makeAnd(), Functional.apply(allParts, Part.castToExpression)); AndedParts cp = parent.buildAndedParts(andCall, allParts); if (parent.isComplete(cp)) { setComplete(cp); } else if (!parent.isComplete(cp)) { AndedParts ncp = parent.maybeMakeComplete(cp); if (ncp != null) { setComplete(ncp); return ncp; } } return cp; }
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); } }
private Part buildNewMultiMultiPart(OredParts lp, OredParts rp) { ArrayList<Part> newParts = new ArrayList<Part>(); for (Part lpc : lp.getParts()) { for (Part rpc : rp.getParts()) { newParts.add(combineParts(lpc.copy(), rpc.copy())); } } FunctionCall orcall = new FunctionCall( FunctionName.makeOr(), Functional.apply(newParts, Part.castToExpression)); OredParts op = parent.buildOredParts(orcall, newParts); if (op.isComplete()) setComplete(op); return op; }
private Part buildNewPartCollection(OredParts lp, Part rp) { // rp could be simple or complex, lp has either simple or complex elements. // the strategy here is to build a new complex part for each item in the collection, and // return a new collection. ArrayList<Part> newParts = new ArrayList<Part>(); for (Part sp : lp.getParts()) { newParts.add(buildNewComplexPart(sp, rp.copy())); } FunctionCall orcall = new FunctionCall( FunctionName.makeOr(), Functional.apply(newParts, Part.castToExpression)); OredParts op = parent.buildOredParts(orcall, newParts); if (op.isComplete()) setComplete(op); return op; }