From: <mrp...@us...> - 2011-02-21 17:12:15
|
Revision: 4215 http://bigdata.svn.sourceforge.net/bigdata/?rev=4215&view=rev Author: mrpersonick Date: 2011-02-21 17:12:09 +0000 (Mon, 21 Feb 2011) Log Message: ----------- better handling of unrecognized values in queries Modified Paths: -------------- branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/BigdataEvaluationStrategyImpl3.java branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/sop/SOp2BOpUtility.java branches/QUADS_QUERY_BRANCH/bigdata-sails/src/test/com/bigdata/rdf/sail/TestBigdataSailEvaluationStrategyImpl.java branches/QUADS_QUERY_BRANCH/bigdata-sails/src/test/com/bigdata/rdf/sail/TestNestedUnions.java Added Paths: ----------- branches/QUADS_QUERY_BRANCH/bigdata-sails/src/test/com/bigdata/rdf/sail/union.ttl Modified: branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/BigdataEvaluationStrategyImpl3.java =================================================================== --- branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/BigdataEvaluationStrategyImpl3.java 2011-02-21 14:30:25 UTC (rev 4214) +++ branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/BigdataEvaluationStrategyImpl3.java 2011-02-21 17:12:09 UTC (rev 4215) @@ -703,13 +703,14 @@ * If we encounter a value not in the lexicon, we can * still continue with the query if the value is in * either an optional tail or an optional join group (i.e. - * if it appears on the right side of a LeftJoin). + * if it appears on the right side of a LeftJoin). We can + * also continue if the value is in a UNION. * Otherwise we can stop evaluating right now. */ - if (sop.isRightSideLeftJoin()) { + if (sop.getGroup() == SOpTreeBuilder.ROOT_GROUP_ID) { + throw new UnrecognizedValueException(ex); + } else { groupsToPrune.add(sopTree.getGroup(sop.getGroup())); - } else { - throw new UnrecognizedValueException(ex); } } } @@ -720,6 +721,15 @@ * not in the lexicon. */ sopTree = stb.pruneGroups(sopTree, groupsToPrune); + + /* + * If after pruning groups with unrecognized values we end up with a + * UNION with no subqueries, we can safely just return an empty + * iteration. + */ + if (SOp2BOpUtility.isEmptyUnion(sopTree.getRoot())) { + return new EmptyIteration<BindingSet, QueryEvaluationException>(); + } /* * If we have a filter in the root group (one that can be safely applied @@ -2047,9 +2057,33 @@ } private IConstraint toConstraint(Or or) { - final IConstraint right = toConstraint(or.getRightArg()); - final IConstraint left = toConstraint(or.getLeftArg()); - return new OR(left, right); + IConstraint left = null, right = null; + UnrecognizedValueException uve = null; + try { + left = toConstraint(or.getLeftArg()); + } catch (UnrecognizedValueException ex) { + uve = ex; + } + try { + right = toConstraint(or.getRightArg()); + } catch (UnrecognizedValueException ex) { + uve = ex; + } + + /* + * if both sides contain unrecognized values, then we need to throw + * the exception up. but if only one does, then we can still handle it + * since we are doing an OR. + */ + if (left == null && right == null) { + throw uve; + } + + if (left != null && right != null) { + return new OR(left, right); + } else { + return left != null ? left : right; + } } private IConstraint toConstraint(And and) { Modified: branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/sop/SOp2BOpUtility.java =================================================================== --- branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/sop/SOp2BOpUtility.java 2011-02-21 14:30:25 UTC (rev 4214) +++ branches/QUADS_QUERY_BRANCH/bigdata-sails/src/java/com/bigdata/rdf/sail/sop/SOp2BOpUtility.java 2011-02-21 17:12:09 UTC (rev 4215) @@ -105,6 +105,18 @@ } + public static boolean isEmptyUnion(final SOpGroup sopGroup) { + + if (isUnion(sopGroup)) { + final SOpGroups children = sopGroup.getChildren(); + if (children == null || children.size() == 0) { + return true; + } + } + return false; + + } + /** * Because of the way we parse the Sesame operator tree, the single * optional tails get placed in their own singleton subgroup without any @@ -214,10 +226,10 @@ * First do the non-optional subqueries (UNIONs) */ for (SOpGroup child : children) { - if (!isUnion(child)) + if (!isUnion(child) || isEmptyUnion(child)) continue; - final PipelineOp subquery = convert( + final PipelineOp subquery = union( child, idFactory, db, queryEngine, queryHints); final boolean optional = isOptional(child); final int subqueryId = idFactory.incrementAndGet(); Modified: branches/QUADS_QUERY_BRANCH/bigdata-sails/src/test/com/bigdata/rdf/sail/TestBigdataSailEvaluationStrategyImpl.java =================================================================== --- branches/QUADS_QUERY_BRANCH/bigdata-sails/src/test/com/bigdata/rdf/sail/TestBigdataSailEvaluationStrategyImpl.java 2011-02-21 14:30:25 UTC (rev 4214) +++ branches/QUADS_QUERY_BRANCH/bigdata-sails/src/test/com/bigdata/rdf/sail/TestBigdataSailEvaluationStrategyImpl.java 2011-02-21 17:12:09 UTC (rev 4215) @@ -118,7 +118,7 @@ " ?p = <"+property1+">) " + "}"; - { // evalute it once so i can see it + { // evaluate it once so i can see it final StringWriter sw = new StringWriter(); final SPARQLResultsXMLWriter handler = new SPARQLResultsXMLWriter( @@ -891,6 +891,29 @@ } + public void test_join_combo_3() throws Exception { + + // define the vocabulary + + // define the graph + Graph graph = new GraphImpl(); + + // define the query + String query = + "PREFIX : <http://example/> " + + "SELECT * " + + "{ " + + " { ?x :p ?y } UNION { ?p a ?z } " + + "}"; + + // define the correct answer + Collection<BindingSet> answer = new LinkedList<BindingSet>(); + + // run the test + runQuery(graph, query, answer); + + } + public void test_two_nested_opt() throws Exception { // define the vocabulary Modified: branches/QUADS_QUERY_BRANCH/bigdata-sails/src/test/com/bigdata/rdf/sail/TestNestedUnions.java =================================================================== --- branches/QUADS_QUERY_BRANCH/bigdata-sails/src/test/com/bigdata/rdf/sail/TestNestedUnions.java 2011-02-21 14:30:25 UTC (rev 4214) +++ branches/QUADS_QUERY_BRANCH/bigdata-sails/src/test/com/bigdata/rdf/sail/TestNestedUnions.java 2011-02-21 17:12:09 UTC (rev 4215) @@ -39,12 +39,18 @@ import org.openrdf.query.BindingSet; import org.openrdf.query.QueryLanguage; import org.openrdf.query.TupleQueryResult; +import org.openrdf.query.algebra.Distinct; import org.openrdf.query.algebra.Projection; import org.openrdf.query.algebra.QueryRoot; import org.openrdf.query.algebra.TupleExpr; import org.openrdf.query.impl.BindingImpl; +import org.openrdf.repository.Repository; import org.openrdf.repository.RepositoryConnection; +import org.openrdf.repository.sail.SailRepository; import org.openrdf.repository.sail.SailTupleQuery; +import org.openrdf.rio.RDFFormat; +import org.openrdf.sail.Sail; +import org.openrdf.sail.memory.MemoryStore; import com.bigdata.rdf.axioms.NoAxioms; import com.bigdata.rdf.sail.sop.SOpTree; @@ -332,5 +338,109 @@ } } + + public void testForumBug() throws Exception { + +// final Sail sail = new MemoryStore(); + final Sail sail = getSail(); + + try { + + sail.initialize(); + final Repository repo = sail instanceof BigdataSail ? + new BigdataSailRepository((BigdataSail)sail) : + new SailRepository(sail); + final RepositoryConnection cxn = repo.getConnection(); + + try { + + final ValueFactory vf = sail.getValueFactory(); + + cxn.setAutoCommit(false); + + /* + * load the data + */ + cxn.add(getClass().getResourceAsStream("union.ttl"),"",RDFFormat.TURTLE); + + /* + * Note: The either flush() or commit() is required to flush the + * statement buffers to the database before executing any + * operations that go around the sail. + */ + cxn.commit(); + + { + + String query = + "prefix bd: <"+BD.NAMESPACE+"> " + + "prefix rdf: <"+RDF.NAMESPACE+"> " + + "prefix rdfs: <"+RDFS.NAMESPACE+"> " + + "SELECT DISTINCT ?neType ?majorType ?minorType " + + "WHERE { " + + " { " + + " ?neType <http://www.w3.org/2000/01/rdf-schema#subClassOf> <http://example/class/NamedEntity> . " + + " FILTER(?neType != <http://example/class/NamedEntity>) " + + " } " + + " UNION " + + " { ?lookup <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://example/class/Lookup> . " + + " ?lookup <http://example/prop/lookup/majorType> ?majorType . " + + " OPTIONAL { ?lookup <http://example/prop/lookup/minorType> ?minorType } " + + " } " + + "}"; + + final SailTupleQuery tupleQuery = (SailTupleQuery) + cxn.prepareTupleQuery(QueryLanguage.SPARQL, query); + tupleQuery.setIncludeInferred(false /* includeInferred */); + + if (sail instanceof BigdataSail && log.isInfoEnabled()) { + + final BigdataSailTupleQuery bdTupleQuery = + (BigdataSailTupleQuery) tupleQuery; + final QueryRoot root = (QueryRoot) bdTupleQuery.getTupleExpr(); + final Distinct d = (Distinct) root.getArg(); + final Projection p = (Projection) d.getArg(); + final TupleExpr tupleExpr = p.getArg(); + log.info(tupleExpr); + + final SOpTreeBuilder stb = new SOpTreeBuilder(); + final SOpTree tree = stb.collectSOps(tupleExpr); + + log.info(tree); + log.info(query); + + } + + if (log.isInfoEnabled()) { + final TupleQueryResult result = tupleQuery.evaluate(); + log.info("results:"); + while (result.hasNext()) { + log.info(result.next()); + } + } + + final Collection<BindingSet> answer = new LinkedList<BindingSet>(); + answer.add(createBindingSet( + new BindingImpl("neType", vf.createURI("http://example/class/Location")) + )); + answer.add(createBindingSet( + new BindingImpl("neType", vf.createURI("http://example/class/Person")) + )); + + final TupleQueryResult result = tupleQuery.evaluate(); + compare(result, answer); + + } + + } finally { + cxn.close(); + } + } finally { + if (sail instanceof BigdataSail) + ((BigdataSail)sail).__tearDownUnitTest();//shutDown(); + } + + } + } Added: branches/QUADS_QUERY_BRANCH/bigdata-sails/src/test/com/bigdata/rdf/sail/union.ttl =================================================================== --- branches/QUADS_QUERY_BRANCH/bigdata-sails/src/test/com/bigdata/rdf/sail/union.ttl (rev 0) +++ branches/QUADS_QUERY_BRANCH/bigdata-sails/src/test/com/bigdata/rdf/sail/union.ttl 2011-02-21 17:12:09 UTC (rev 4215) @@ -0,0 +1,21 @@ +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . +@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . + +<http://example/class/Location> rdfs:subClassOf <http://example/class/NamedEntity> . +<http://example/class/Location> rdfs:label "Location" . +<http://example/class/NamedEntity> rdfs:label "NamedEntity" . +<http://example/elem/loc/loc1> rdfs:label "label: Amsterdam" . +<http://example/elem/loc/loc1> rdf:type <http://example/class/Location> . +<http://example/elem/loc/loc1> <http://example/prop/lookupName> "amsterdam" . +<http://example/elem/loc/loc2> rdfs:label "label: Den Haag" . +<http://example/elem/loc/loc2> rdf:type <http://example/class/Location> . +<http://example/elem/loc/loc2> <http://example/prop/lookupName> "den haag" . +<http://example/elem/loc/loc3> rdfs:label "label: IJmuiden" . +<http://example/elem/loc/loc3> rdf:type <http://example/class/Location> . +<http://example/elem/loc/loc3> <http://example/prop/lookupName> "ijmuiden" . +<http://example/elem/loc/loc3> <http://example/prop/disabled> "true"^^<http://www.w3.org/2001/XMLSchema#boolean> . +<http://example/class/Person> rdfs:subClassOf <http://example/class/NamedEntity> . +<http://example/class/Person> rdfs:label "Person" . +<http://example/elem/person/puk> rdfs:label "label: Puk van de Petteflet" . +<http://example/elem/person/puk> rdf:type <http://example/class/Person> . +<http://example/elem/person/puk> <http://example/prop/lookupName> "puk van de petteflet" . This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |