blob: 577baed5cc521857be5bf8861d9e1c7c29d2c16f [file] [log] [blame]
package org.apache.rya.indexing.pcj.matching;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.rya.indexing.external.matching.ExternalSetMatcher;
import org.apache.rya.indexing.external.matching.FlattenedOptional;
import org.apache.rya.indexing.external.matching.QuerySegmentFactory;
import org.apache.rya.indexing.external.tupleSet.ExternalTupleSet;
import org.apache.rya.indexing.external.tupleSet.SimpleExternalTupleSet;
import org.eclipse.rdf4j.query.MalformedQueryException;
import org.eclipse.rdf4j.query.algebra.Filter;
import org.eclipse.rdf4j.query.algebra.Join;
import org.eclipse.rdf4j.query.algebra.LeftJoin;
import org.eclipse.rdf4j.query.algebra.Projection;
import org.eclipse.rdf4j.query.algebra.QueryModelNode;
import org.eclipse.rdf4j.query.algebra.StatementPattern;
import org.eclipse.rdf4j.query.algebra.TupleExpr;
import org.eclipse.rdf4j.query.algebra.Union;
import org.eclipse.rdf4j.query.algebra.helpers.AbstractQueryModelVisitor;
import org.eclipse.rdf4j.query.parser.ParsedQuery;
import org.eclipse.rdf4j.query.parser.sparql.SPARQLParser;
import org.junit.Assert;
import org.junit.Test;
public class OptionalJoinSegmentPCJMatcherTest {
private final PCJExternalSetMatcherFactory pcjFactory = new PCJExternalSetMatcherFactory();
private final QuerySegmentFactory<ExternalTupleSet> qFactory = new QuerySegmentFactory<ExternalTupleSet>();
@Test
public void testBasicSegment() throws MalformedQueryException {
String query1 = ""//
+ "SELECT ?e ?c ?l" //
+ "{" //
+ " ?e a ?c . "//
+ " OPTIONAL {?e <uri:talksTo> ?l} . "//
+ " ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
+ "}";//
String query2 = ""//
+ "SELECT ?e ?c ?l" //
+ "{" //
+ " ?e a ?c . "//
+ " OPTIONAL {?e <uri:talksTo> ?l} . "//
+ "}";//
SPARQLParser parser = new SPARQLParser();
ParsedQuery pq1 = parser.parseQuery(query1, null);
ParsedQuery pq2 = parser.parseQuery(query2, null);
TupleExpr te1 = pq1.getTupleExpr();
TupleExpr te2 = pq2.getTupleExpr();
Projection proj = (Projection) te1;
Join join = (Join) proj.getArg();
ExternalSetMatcher<ExternalTupleSet> jsm = pcjFactory.getMatcher(qFactory.getQuerySegment(join));
SimpleExternalTupleSet pcj = new SimpleExternalTupleSet((Projection)te2);
Assert.assertEquals(true, jsm.match(pcj));
TupleExpr te = jsm.getQuery();
Assert.assertEquals(new HashSet<QueryModelNode>(), jsm.getUnmatchedArgNodes());
Set<QueryModelNode> qNodes = LeftJoinQueryNodeGatherer.getNodes(te);
List<QueryModelNode> nodes = jsm.getOrderedNodes();
Set<QueryModelNode> nodeSet = new HashSet<>();
nodeSet.add(nodes.get(0));
nodeSet.add(pcj);
Assert.assertEquals(nodeSet, new HashSet<QueryModelNode>(nodes));
Assert.assertEquals(nodeSet, qNodes);
}
@Test
public void testBasicMatchWithFilter() throws Exception {
String query1 = ""//
+ "SELECT ?e ?c ?l" //
+ "{" //
+ " Filter(?e = <uri:Bob>)" //
+ " Filter(?c = <uri:Lawyer>)" //
+ " ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l . "//
+ " ?e a ?c . "//
+ " OPTIONAL {?e <uri:talksTo> ?l} . "//
+ "}";//
String query2 = ""//
+ "SELECT ?e ?c ?l" //
+ "{" //
+ " Filter(?e = <uri:Bob>)" //
+ " ?e a ?c . "//
+ " OPTIONAL {?e <uri:talksTo> ?l} . "//
+ "}";//
SPARQLParser parser = new SPARQLParser();
ParsedQuery pq1 = parser.parseQuery(query1, null);
ParsedQuery pq2 = parser.parseQuery(query2, null);
TupleExpr te1 = pq1.getTupleExpr();
TupleExpr te2 = pq2.getTupleExpr();
Projection proj = (Projection) te1;
Filter filter = (Filter) proj.getArg();
ExternalSetMatcher<ExternalTupleSet> jsm = pcjFactory.getMatcher(qFactory.getQuerySegment(filter));
SimpleExternalTupleSet pcj = new SimpleExternalTupleSet((Projection)te2);
Assert.assertEquals(true, jsm.match(pcj));
TupleExpr te = jsm.getQuery();
Assert.assertEquals(new HashSet<QueryModelNode>(), jsm.getUnmatchedArgNodes());
Set<QueryModelNode> qNodes = LeftJoinQueryNodeGatherer.getNodes(te);
List<QueryModelNode> nodes = jsm.getOrderedNodes();
Set<QueryModelNode> nodeSet = new HashSet<>();
nodeSet.add(nodes.get(0));
nodeSet.add(pcj);
nodeSet.add(nodes.get(2));
Assert.assertEquals(nodeSet, new HashSet<QueryModelNode>(nodes));
Assert.assertEquals(nodeSet, qNodes);
}
@Test
public void testMultipleFilters() throws Exception {
String query1 = ""//
+ "SELECT ?e ?c ?l" //
+ "{" //
+ " Filter(?e = <uri:Bob>)" //
+ " Filter(?c = <uri:Lawyer>)" //
+ " ?l <uri:workAt> <uri:Company1> ."
+ " OPTIONAL { ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l } . "//
+ " ?e a ?c . "//
+ " ?e <uri:talksTo> ?l . "//
+ "}";//
String query2 = ""//
+ "SELECT ?e ?c ?l" //
+ "{" //
+ " Filter(?e = <uri:Bob>)" //
+ " ?e a ?c . "//
+ " ?e <uri:talksTo> ?l . "//
+ "}";//
SPARQLParser parser = new SPARQLParser();
ParsedQuery pq1 = parser.parseQuery(query1, null);
ParsedQuery pq2 = parser.parseQuery(query2, null);
TupleExpr te1 = pq1.getTupleExpr();
TupleExpr te2 = pq2.getTupleExpr();
Projection proj = (Projection) te1;
Join join = (Join) proj.getArg();
ExternalSetMatcher<ExternalTupleSet> jsm = pcjFactory.getMatcher(qFactory.getQuerySegment(join));
SimpleExternalTupleSet pcj = new SimpleExternalTupleSet((Projection)te2);
Assert.assertEquals(true, jsm.match(pcj));
TupleExpr te = jsm.getQuery();
Assert.assertEquals(new HashSet<QueryModelNode>(), jsm.getUnmatchedArgNodes());
Set<QueryModelNode> qNodes = LeftJoinQueryNodeGatherer.getNodes(te);
List<QueryModelNode> nodes = jsm.getOrderedNodes();
Set<QueryModelNode> nodeSet = new HashSet<>();
nodeSet.add(nodes.get(0));
nodeSet.add(nodes.get(2));
nodeSet.add(nodes.get(3));
nodeSet.add(pcj);
Assert.assertEquals(nodeSet, new HashSet<QueryModelNode>(nodes));
Assert.assertEquals(nodeSet, qNodes);
}
@Test
public void testWithUnmatchedNodes() throws Exception {
String query1 = ""//
+ "SELECT ?a ?b ?c ?d ?e" //
+ "{" //
+ " Filter(?a = <uri:s1>)" //
+ " Filter(?b = <uri:s2>)" //
+ " {?e <uri:p3> <uri:o2> } UNION {?d <uri:p4> <uri:o3>} ."
+ " ?a <uri:workAt> <uri:Company1> ."
+ " ?b <uri:talksTo> ?c . "//
+ " OPTIONAL { ?b <uri:p1> ?c } . "//
+ " ?b <uri:p2> <uri:o1> . "//
+ "}";//
String query2 = ""//
+ "SELECT ?e ?c ?l" //
+ "{" //
+ " ?b <uri:talksTo> ?c . "//
+ " OPTIONAL { ?b <uri:p1> ?c } . "//
+ " ?b <uri:p2> <uri:o1> . "//
+ " Filter(?b = <uri:s2>)" //
+ "}";//
SPARQLParser parser = new SPARQLParser();
ParsedQuery pq1 = parser.parseQuery(query1, null);
ParsedQuery pq2 = parser.parseQuery(query2, null);
TupleExpr te1 = pq1.getTupleExpr();
TupleExpr te2 = pq2.getTupleExpr();
Projection proj = (Projection) te1;
Join join = (Join) proj.getArg();
ExternalSetMatcher<ExternalTupleSet> jsm = pcjFactory.getMatcher(qFactory.getQuerySegment(join));
SimpleExternalTupleSet pcj = new SimpleExternalTupleSet((Projection)te2);
Assert.assertEquals(true, jsm.match(pcj));
TupleExpr te = jsm.getQuery();
Set<QueryModelNode> qNodes = LeftJoinQueryNodeGatherer.getNodes(te);
List<QueryModelNode> nodes = jsm.getOrderedNodes();
Assert.assertEquals(1, jsm.getUnmatchedArgNodes().size());
Assert.assertEquals(true, jsm.getUnmatchedArgNodes().contains(nodes.get(3)));
Set<QueryModelNode> nodeSet = new HashSet<>();
nodeSet.add(nodes.get(0));
nodeSet.add(nodes.get(2));
nodeSet.add(nodes.get(3));
nodeSet.add(pcj);
Assert.assertEquals(nodeSet, new HashSet<QueryModelNode>(nodes));
Assert.assertEquals(nodeSet, qNodes);
}
static class LeftJoinQueryNodeGatherer extends AbstractQueryModelVisitor<RuntimeException> {
private static Set<QueryModelNode> nodes;
public static Set<QueryModelNode> getNodes(TupleExpr te) {
nodes = new HashSet<>();
te.visit(new LeftJoinQueryNodeGatherer());
return nodes;
}
@Override
public void meetNode(QueryModelNode node) {
if(node instanceof ExternalTupleSet) {
nodes.add(node);
}
super.meetNode(node);
}
@Override
public void meet(StatementPattern node) {
nodes.add(node);
}
@Override
public void meet(Filter node) {
nodes.add(node.getCondition());
super.meet(node);
}
@Override
public void meet(LeftJoin node) {
nodes.add(new FlattenedOptional(node));
node.getLeftArg().visit(this);
}
@Override
public void meet(Union node) {
nodes.add(node);
}
}
}