package org.aksw.jena_sparql_api.cache.tests; import org.apache.jena.query.Query; import org.apache.jena.query.QueryFactory; import org.apache.jena.sparql.algebra.Algebra; import org.apache.jena.sparql.algebra.Op; import org.apache.jena.sparql.algebra.OpVisitor; import org.apache.jena.sparql.algebra.op.OpAssign; import org.apache.jena.sparql.algebra.op.OpBGP; import org.apache.jena.sparql.algebra.op.OpConditional; import org.apache.jena.sparql.algebra.op.OpDatasetNames; import org.apache.jena.sparql.algebra.op.OpDiff; import org.apache.jena.sparql.algebra.op.OpDisjunction; import org.apache.jena.sparql.algebra.op.OpDistinct; import org.apache.jena.sparql.algebra.op.OpExtend; import org.apache.jena.sparql.algebra.op.OpFilter; import org.apache.jena.sparql.algebra.op.OpGraph; import org.apache.jena.sparql.algebra.op.OpGroup; import org.apache.jena.sparql.algebra.op.OpJoin; import org.apache.jena.sparql.algebra.op.OpLabel; import org.apache.jena.sparql.algebra.op.OpLeftJoin; import org.apache.jena.sparql.algebra.op.OpList; import org.apache.jena.sparql.algebra.op.OpMinus; import org.apache.jena.sparql.algebra.op.OpNull; import org.apache.jena.sparql.algebra.op.OpOrder; import org.apache.jena.sparql.algebra.op.OpPath; import org.apache.jena.sparql.algebra.op.OpProcedure; import org.apache.jena.sparql.algebra.op.OpProject; import org.apache.jena.sparql.algebra.op.OpPropFunc; import org.apache.jena.sparql.algebra.op.OpQuad; import org.apache.jena.sparql.algebra.op.OpQuadBlock; import org.apache.jena.sparql.algebra.op.OpQuadPattern; import org.apache.jena.sparql.algebra.op.OpReduced; import org.apache.jena.sparql.algebra.op.OpSequence; import org.apache.jena.sparql.algebra.op.OpService; import org.apache.jena.sparql.algebra.op.OpSlice; import org.apache.jena.sparql.algebra.op.OpTable; import org.apache.jena.sparql.algebra.op.OpTopN; import org.apache.jena.sparql.algebra.op.OpTriple; import org.apache.jena.sparql.algebra.op.OpUnion; import com.google.common.collect.Range; /** * Perform a depth first traversal, where nodes are visited before descending * in order to create OpQueryLevel objects. * * * Outdated: Perform a depth first traversal. If a leaf is found, navigate to the parents and * collect the query level data. If an op is encountered that cannot be added to the current query level, create a new * one and it the prior level as a child of the new one. * If the parent is e.g. a join or a union, create the corresponding op and * attach all constructed query levels so far as children. * * @author raven * */ class OpToQueryLevel implements OpVisitor { public static final int PRECEDENCE_QUADS_OR_FILTERS = 0; public static final int PRECEDENCE_PROJECT = 3; public static final int PRECEDENCE_AGGREGATE = 3; public static final int PRECEDENCE_GROUPBY = 3; public static final int PRECEDENCE_ORDERBY = 3; public static final int PRECEDENCE_DISTINCT = 4; public static final int PRECEDENCE_SLICE = 5; public static final int PRECEDENCE_NESTED = 1000; public static OpQueryLevel toQueryLevel(Op op) { OpToQueryLevel visitor = new OpToQueryLevel(); op.visit(visitor); OpQueryLevel result = visitor.getResult(); return result; } protected OpQueryLevel currentLevel; protected int currentPrecedence = 0; public OpQueryLevel getResult() { return currentLevel; } @Override public void visit(OpBGP opBGP) { // TODO Auto-generated method stub } @Override public void visit(OpQuadPattern quadPattern) { // TODO Auto-generated method stub } @Override public void visit(OpQuadBlock quadBlock) { // TODO Auto-generated method stub } @Override public void visit(OpTriple opTriple) { // TODO Auto-generated method stub } @Override public void visit(OpQuad opQuad) { // TODO Auto-generated method stub } @Override public void visit(OpPath opPath) { // TODO Auto-generated method stub } @Override public void visit(OpTable opTable) { // TODO Auto-generated method stub } @Override public void visit(OpNull opNull) { // TODO Auto-generated method stub } @Override public void visit(OpProcedure opProc) { // TODO Auto-generated method stub } @Override public void visit(OpPropFunc opPropFunc) { // TODO Auto-generated method stub } @Override public void visit(OpFilter opFilter) { // TODO Auto-generated method stub } @Override public void visit(OpGraph opGraph) { // TODO Auto-generated method stub } @Override public void visit(OpService opService) { // TODO Auto-generated method stub } @Override public void visit(OpDatasetNames dsNames) { // TODO Auto-generated method stub } @Override public void visit(OpLabel opLabel) { // TODO Auto-generated method stub } @Override public void visit(OpAssign opAssign) { // TODO Auto-generated method stub } @Override public void visit(OpExtend opExtend) { // TODO Auto-generated method stub } @Override public void visit(OpJoin opJoin) { // TODO Auto-generated method stub } @Override public void visit(OpLeftJoin opLeftJoin) { // TODO Auto-generated method stub } @Override public void visit(OpUnion opUnion) { // TODO Auto-generated method stub } @Override public void visit(OpDiff opDiff) { // TODO Auto-generated method stub } @Override public void visit(OpMinus opMinus) { // TODO Auto-generated method stub } @Override public void visit(OpConditional opCondition) { // TODO Auto-generated method stub } @Override public void visit(OpSequence opSequence) { // TODO Auto-generated method stub } @Override public void visit(OpDisjunction opDisjunction) { //OpQueryLevel ql = ensure(PRECEDENCE_NESTED); OpDisjunction parentOp = OpDisjunction.create(); for(Op subOp : opDisjunction.getElements()) { OpToQueryLevel visitor = new OpToQueryLevel(); subOp.visit(visitor); Op childOp = visitor.getResult(); parentOp.add(childOp); } //ql. currentLevel = new OpQueryLevel(parentOp); } @Override public void visit(OpList opList) { throw new UnsupportedOperationException("not implemented yet"); } @Override public void visit(OpOrder opOrder) { opOrder.getSubOp().visit(this); OpQueryLevel ql = ensure(PRECEDENCE_ORDERBY); ql.getData().getSolutionModifiers().setSortConditions(opOrder.getConditions()); } public OpQueryLevel ensure(int precedenceLevel) { OpQueryLevel result = ensure(precedenceLevel, false); return result; } public OpQueryLevel ensure(int precedenceLevel, boolean acceptEqual) { boolean isAccepted = acceptEqual ? precedenceLevel <= currentPrecedence : precedenceLevel < currentPrecedence; OpQueryLevel result = isAccepted ? currentLevel : new OpQueryLevel(currentLevel); currentPrecedence = precedenceLevel; return result; } // public OpQueryLevel ensure(Op subOp, int precedenceLevel, boolean acceptEqual) { // boolean isAccepted = acceptEqual // ? precedenceLevel <= currentPrecedence // : precedenceLevel < currentPrecedence; // // OpQueryLevel result = isAccepted // ? currentLevel // : new OpQueryLevel(subOp); // // currentPrecedence = precedenceLevel; // return result; // } @Override public void visit(OpProject op) { op.getSubOp().visit(this); OpQueryLevel ql = ensure(PRECEDENCE_PROJECT); ql.getData().getSolutionModifiers().setProjection(op.getVars()); } @Override public void visit(OpReduced op) { op.getSubOp().visit(this); OpQueryLevel ql = ensure(PRECEDENCE_DISTINCT); ql.getData().getSolutionModifiers().setDeduplicationLevel(1); } @Override public void visit(OpDistinct op) { op.getSubOp().visit(this); OpQueryLevel ql = ensure(PRECEDENCE_DISTINCT); ql.getData().getSolutionModifiers().setDeduplicationLevel(2); } @Override public void visit(OpSlice op) { op.getSubOp().visit(this); OpQueryLevel ql = ensure(PRECEDENCE_SLICE); long start = op.getStart(); long end = start + op.getLength(); ql.getData().getSolutionModifiers().setSlice(Range.closed(op.getStart(), end)); } @Override public void visit(OpGroup op) { op.getSubOp().visit(this); OpQueryLevel ql = ensure(PRECEDENCE_GROUPBY); ql.getData().setAggregators(op.getAggregators()); ql.getData().setGroupVars(op.getGroupVars()); } @Override public void visit(OpTopN op) { throw new UnsupportedOperationException("not implemented yet"); } public static void main(String[] args) { Query query = QueryFactory.create("SELECT DISTINCT ?s { { ?s a ?t } UNION { ?s a ?u } }"); Op op = Algebra.toQuadForm(Algebra.compile(query)); OpQueryLevel ql = OpToQueryLevel.toQueryLevel(op); System.out.println(ql); } }