private void handleFilter(FilterTuple filterTuple, FilterExpr expr) { /* * CompareEQ expressions are inserted as bindings if possible * * if the filtertuple contains all vars of the filterexpr, we * can evaluate the filter expr safely on the filterTuple * * if there is no intersection of variables, the filter is * irrelevant for this expr * * if there is some intersection, we cannot remove the filter * and have to keep it in the query plan for postfiltering */ int intersected = 0; for (String filterVar : expr.getVars()) { if (filterTuple.getFreeVars().contains(filterVar)) intersected++; } // filter expression is irrelevant if (intersected == 0) return; // push eq comparison into stmt as bindings if (expr.isCompareEq()) { if (handleCompare(filterTuple, (Compare) expr.getExpression())) return; } // filter contains all variables => push filter if (intersected == expr.getVars().size()) filterTuple.addFilterExpr(expr); // filter is still needed for post filtering else { canRemove = false; } }
@Override public void meet(Filter filter) { if (filter.getArg() instanceof EmptyResult) { log.debug( "Argument of filter expression does not yield results at the provided sources, replacing Filter node."); filter.replaceWith(filter.getArg()); return; } /* * TODO idea: * if we have a FILTER such as ?s='a' OR ?s='b' OR ?s='c' handle this appropriately */ ValueExpr valueExpr = filter.getCondition(); /* * TODO transform condition into some normal form, e.g. CNF */ // determine conjunctive expressions List<ValueExpr> conjunctiveExpressions = new ArrayList<ValueExpr>(); getConjunctiveExpressions(valueExpr, conjunctiveExpressions); FilterExprInsertVisitor filterExprVst = new FilterExprInsertVisitor(); List<ValueExpr> remainingExpr = new ArrayList<ValueExpr>(conjunctiveExpressions.size()); for (ValueExpr cond : conjunctiveExpressions) { /* * Determine if this filter is applicable for optimization. * Currently only leaf expressions are applicable, i.e. * not combined expressions. */ if (isCompatibleExpr(cond)) { HashSet<String> exprVars = new VarFinder().findVars(cond); FilterExpr filterExpr = new FilterExpr(cond, exprVars); filterExprVst.initialize(filterExpr); filter.getArg().visit(filterExprVst); // if the filter expr. is handled in the stmt we do not have to keep it if (filterExprVst.canRemove()) continue; remainingExpr.add(filterExpr.getExpression()); } else { remainingExpr.add(cond); } } if (remainingExpr.size() == 0) { filter.replaceWith(filter.getArg()); // remove the filter } else if (remainingExpr.size() == 1) { filter.setCondition(remainingExpr.get(0)); // just apply the remaining condition } else { // construct conjunctive value expr And root = new And(); root.setLeftArg(remainingExpr.get(0)); And tmp = root; for (int i = 1; i < remainingExpr.size() - 1; i++) { And _a = new And(); _a.setLeftArg(remainingExpr.get(i)); tmp.setRightArg(_a); tmp = _a; } tmp.setRightArg(remainingExpr.get(remainingExpr.size() - 1)); filter.setCondition(root); } }