use of org.apache.jena.sparql.expr.ExprList in project jena by apache.
the class TransformFilterDisjunction method transform.
@Override
public Op transform(OpFilter opFilter, final Op subOp) {
ExprList exprList = opFilter.getExprs();
// First pass - any disjunctions at all?
boolean processDisjunction = false;
for (Expr expr : exprList) {
if (isDisjunction(expr)) {
processDisjunction = true;
break;
}
}
// Still may be a disjunction in a form we don't optimize.
if (!processDisjunction)
return super.transform(opFilter, subOp);
ExprList exprList2 = new ExprList();
Op newOp = subOp;
// remember what's been seen so that FILTER(?x = <x> || ?x = <x> ) does not result in two transforms.
Set<Expr> doneSoFar = new HashSet<>();
for (Expr expr : exprList) {
if (!isDisjunction(expr)) {
// Assignment there?
exprList2.add(expr);
continue;
}
// // Relies on expression equality.
// if ( doneSoFar.contains(expr) )
// continue ;
// // Must be canonical: ?x = <x> is the same as <x> = ?x
// doneSoFar.add(expr) ;
Op op2 = expandDisjunction(expr, newOp);
if (op2 != null)
newOp = op2;
}
if (exprList2.isEmpty())
return newOp;
// There should have been at least on disjunction.
if (newOp == subOp) {
Log.warn(this, "FilterDisjunction assumption failure: didn't find a disjunction after all");
return super.transform(opFilter, subOp);
}
// Failed. These a was one or more expressions we couldn't handle.
// So the full pattern is going to be executed anyway.
//return super.transform(super.transform(opFilter, subOp)) ;
// Put the non-disjunctions outside the disjunction and the pattern rewrite.
Op opOther = OpFilter.filterBy(exprList2, newOp);
if (opOther instanceof OpFilter) {
return opOther;
}
// opOther is not a filter any more - should not happen but to isolate from future changes ...
Log.warn(this, "FilterDisjunction assumption failure: not a filter after processing disjunction/other mix");
return super.transform(opFilter, subOp);
}
use of org.apache.jena.sparql.expr.ExprList in project jena by apache.
the class TransformFilterPlacement method placeJoin.
private Placement placeJoin(ExprList exprs, OpJoin opJoin) {
Op left = opJoin.getLeft();
Op right = opJoin.getRight();
Collection<Var> leftVars = fixedVars(left);
Collection<Var> rightVars = fixedVars(right);
// More sophisticated - consider optionl variables as well.
// This code check the two ways to get fixed vars yields the same
// and it does for the test suite.
// //---
// VarFinder vfLeft = VarFinder.process(left) ;
// VarFinder vfRight = VarFinder.process(right) ;
// if ( ! CollectionUtils.sameElts(leftVars, vfLeft.getFixed() ) )
// System.err.println("Left: "+leftVars+" : "+vfLeft.getFixed() ) ;
// if ( ! CollectionUtils.sameElts(rightVars, vfRight.getFixed() ) )
// System.err.println("Right: "+rightVars+" : "+vfRight.getFixed() ) ;
// //---
ExprList unpushed = new ExprList();
ExprList pushLeft = new ExprList();
ExprList pushRight = new ExprList();
for (Expr expr : exprs) {
Set<Var> vars = expr.getVarsMentioned();
boolean pushed = false;
if (leftVars.containsAll(vars)) {
pushLeft.add(expr);
pushed = true;
}
if (pushed && !pushRightAsWellAsLeft)
continue;
// If left only, make this "else if" of left test, remove "continue"
if (rightVars.containsAll(vars)) {
// Push right
pushRight.add(expr);
pushed = true;
}
if (!pushed)
unpushed.add(expr);
}
if (pushLeft.isEmpty() && pushRight.isEmpty())
return null;
Op opLeftNew = left;
if (!pushLeft.isEmpty())
opLeftNew = transformOpAlways(pushLeft, opLeftNew);
Op opRightNew = right;
if (!pushRight.isEmpty())
opRightNew = transformOpAlways(pushRight, opRightNew);
Op op = OpJoin.create(opLeftNew, opRightNew);
return result(op, unpushed);
}
use of org.apache.jena.sparql.expr.ExprList in project jena by apache.
the class TransformFilterPlacement method placeSequence.
/*
* A Sequence is a number of joins where scoping means the LHS can be
* substituted into the right, i.e. there are no scoping issues. Assuming a
* substitution join is going to be done, filtering once as soon as the
* accumulated variables cover the filter is a good thing to do. It is
* effectively pusing on the left side only - the right side, by
* substitution, will never see the variables. The variable can not be
* reintroduced (it will have been renamed away if it's the same name,
* different scope, which is a different variable with the same name in the
* orginal query).
*/
private Placement placeSequence(ExprList exprsIn, OpSequence opSequence) {
ExprList exprs = ExprList.copy(exprsIn);
Set<Var> varScope = new HashSet<>();
List<Op> ops = opSequence.getElements();
Op op = null;
for (Op op1 : ops) {
op = insertAnyFilter$(exprs, varScope, op);
Op seqElt = op1;
Placement p = transform(exprs, seqElt);
if (isChange(p)) {
exprs = p.unplaced;
seqElt = p.op;
}
varScope.addAll(fixedVars(seqElt));
op = OpSequence.create(op, seqElt);
}
return result(op, exprs);
}
use of org.apache.jena.sparql.expr.ExprList in project jena by apache.
the class TransformFilterPlacement method transform.
@Override
public Op transform(OpFilter opFilter, Op x) {
ExprList exprs = opFilter.getExprs();
// Extract any expressions with "nasty" cases (RAND, UUID, STRUUID and BNODE)
// which are not true functions (they return a different value every call so
// number of calls matters. NOW is safe (returns a fixed time point for the whole
// query.
// Phase one - check to see if work needed.
ExprList exprs2 = null;
for (Expr expr : exprs) {
if (!ExprLib.isStable(expr)) {
if (exprs2 == null)
exprs2 = new ExprList();
exprs2.add(expr);
}
}
// Phase 2 - if needed, split.
if (exprs2 != null) {
ExprList exprs1 = new ExprList();
for (Expr expr : exprs) {
// We are assuming fixup is rare.
if (ExprLib.isStable(expr))
exprs1.add(expr);
}
exprs = exprs1;
}
Placement placement = transform(exprs, x);
if (isNoChange(placement))
// Didn't do anything.
return super.transform(opFilter, x);
Op op = buildFilter(placement);
if (exprs2 != null)
// Add back the non-deterministic expressions
op = OpFilter.filterBy(exprs2, op);
return op;
}
use of org.apache.jena.sparql.expr.ExprList in project jena by apache.
the class TransformFilterPlacement method placeBGP.
// See also placeQuadPattern.
//
// An improvement might be to put any filters that apply to exactly one triple
// directly on the triple pattern. At the moment, the filter is put over
// the block leading up to the triple pattern.
private static Placement placeBGP(ExprList exprsIn, BasicPattern pattern) {
ExprList exprs = ExprList.copy(exprsIn);
Set<Var> patternVarsScope = new HashSet<>();
// Any filters that depend on no variables.
Op op = insertAnyFilter$(exprs, patternVarsScope, null);
for (Triple triple : pattern) {
OpBGP opBGP = getBGP(op);
if (opBGP == null) {
// Last thing was not a BGP (so it likely to be a filter)
// Need to pass the results from that into the next triple.
opBGP = new OpBGP();
op = OpSequence.create(op, opBGP);
}
opBGP.getPattern().add(triple);
// Update variables in scope.
VarUtils.addVarsFromTriple(patternVarsScope, triple);
op = insertAnyFilter$(exprs, patternVarsScope, op);
}
return result(op, exprs);
}
Aggregations