blob: 2a0afe060608c03a27b478de19bd286bb6882f36 [file] [log] [blame]
package org.apache.rya.indexing.external.tupleSet;
/*
* 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.List;
import java.util.Set;
import org.apache.rya.indexing.pcj.matching.QueryVariableNormalizer;
import org.eclipse.rdf4j.query.algebra.Filter;
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.helpers.AbstractQueryModelVisitor;
import org.eclipse.rdf4j.query.algebra.helpers.StatementPatternCollector;
import org.eclipse.rdf4j.query.parser.ParsedQuery;
import org.eclipse.rdf4j.query.parser.sparql.SPARQLParser;
import org.junit.Assert;
import org.junit.Test;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
public class VarConstQueryVariableNormalizerTest {
private String query1 = " " //
+ "SELECT ?person ?address ?otherValue" //
+ "{" //
+ "?person a <uri:Person>. " //
+ "?person <uri:hasName> <uri:name>."//
+ "?person <uri:hasAddress> ?address." //
+ "?person <uri:blah> ?otherValue" //
+ "}"; //
private String index1 = " " //
+ "SELECT ?X ?Y ?Z ?W" //
+ "{"//
+ "?X a <uri:Person>. " //
+ "?X <uri:hasName> ?Y."//
+ "?X <uri:hasAddress> ?Z." //
+ "?X <uri:blah> ?W" //
+ "}"; //
private String q4 = ""//
+ "SELECT ?s ?t ?u " //
+ "{" //
+ " ?s a ?t . "//
+ " ?t <http://www.w3.org/2000/01/rdf-schema#label> ?u "//
+ "}";//
private String q7 = ""//
+ "SELECT ?s ?t ?u ?x ?y ?z " //
+ "{" //
+ " ?s a ?t ."//
+ " ?x a ?y ."//
+ " ?t <http://www.w3.org/2000/01/rdf-schema#label> ?u ."//
+ " ?y <http://www.w3.org/2000/01/rdf-schema#label> ?z ."//
+ "}";//
private String q8 = ""//
+ "SELECT ?f ?m ?d ?e ?l ?c ?n ?o ?p ?a ?h ?r " //
+ "{" //
+ " ?f a ?m ."//
+ " ?e a ?l ."//
+ " ?n a ?o ."//
+ " ?a a ?h ."//
+ " ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
+ " ?l <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
+ " ?o <http://www.w3.org/2000/01/rdf-schema#label> ?p ."//
+ " ?h <http://www.w3.org/2000/01/rdf-schema#label> ?r ."//
+ " ?f <uri:talksTo> ?m . "//
+ " ?m <uri:talksTo> ?a . "//
+ " ?o <uri:talksTo> ?r . "//
+ "}";//
private String q9 = ""//
+ "SELECT ?f ?d ?e ?c ?n ?p ?a ?r " //
+ "{" //
+ " ?f a <uri:dog> ."//
+ " ?e a <uri:chicken> ."//
+ " ?n a <uri:cow> ."//
+ " ?a a <uri:elephant> ."//
+ " <uri:dog> <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
+ " <uri:chicken> <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
+ " <uri:cow> <http://www.w3.org/2000/01/rdf-schema#label> ?p ."//
+ " <uri:elephant> <http://www.w3.org/2000/01/rdf-schema#label> ?r ."//
+ " ?d <uri:talksTo> ?f . "//
+ " ?c <uri:talksTo> ?e . "//
+ " ?p <uri:talksTo> ?n . "//
+ " ?r <uri:talksTo> ?a . "//
+ "}";//
private String q10 = ""//
+ "SELECT ?f ?m ?d " //
+ "{" //
+ " ?f a ?m ."//
+ " ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
+ " ?d <uri:talksTo> ?f . "//
+ "}";//
String q15 = ""//
+ "SELECT ?x ?y ?z ?w " //
+ "{" //
+ " ?x ?y ?z ."//
+ " ?y ?z ?w ."//
+ "}";//
String q16 = ""//
+ "SELECT ?a ?b ?c " //
+ "{" //
+ " ?a ?b ?c ."//
+ "}";//
String q17 = ""//
+ "SELECT ?q ?r " //
+ "{" //
+ " ?q ?r \"url:\" ."//
+ "}";//
private String q18 = ""//
+ "SELECT ?f ?m ?d ?e ?l ?c ?n ?o ?p ?a ?r " //
+ "{" //
+ " ?f a ?m ."//
+ " ?e a ?l ."//
+ " ?n a ?o ."//
+ " ?a a <uri:elephant> ."//
+ " ?m <http://www.w3.org/2000/01/rdf-schema#label> ?d ."//
+ " ?l <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
+ " ?o <http://www.w3.org/2000/01/rdf-schema#label> ?p ."//
+ " <uri:elephant> <http://www.w3.org/2000/01/rdf-schema#label> ?r ."//
+ " ?d <uri:talksTo> ?f . "//
+ " ?c <uri:talksTo> ?e . "//
+ " ?p <uri:talksTo> ?n . "//
+ " ?r <uri:talksTo> ?a . "//
+ "}";//
String q32 = "PREFIX geo: <http://www.opengis.net/ont/geosparql#> "//
+ "PREFIX geof: <http://www.opengis.net/def/function/geosparql/> "//
+ "SELECT ?feature ?point " //
+ "{" //
+ " ?feature a geo:Feature . "//
+ " ?feature geo:hasGeometry ?point . "//
+ " ?point a geo:Point . "//
+ " ?point geo:asWKT \"wkt\" . "//
+ " FILTER(geof:sfWithin(\"wkt\", \"Polygon\")) " //
+ "}";//
String q33 = "PREFIX fts: <http://rdf.useekm.com/fts#> "//
+ "SELECT ?person ?commentmatch ?labelmatch" //
+ "{" //
+ " ?person a <http://example.org/ontology/Person> . "//
+ " ?person <http://www.w3.org/2000/01/rdf-schema#comment> ?labelmatch . "//
+ " ?person <http://www.w3.org/2000/01/rdf-schema#comment> ?commentmatch . "//
+ " FILTER(fts:text(?labelmatch, \"sally\")) . " //
+ " FILTER(fts:text(?commentmatch, \"bob\")) " //
+ "}";//
String q34 = "PREFIX geo: <http://www.opengis.net/ont/geosparql#> "//
+ "PREFIX geof: <http://www.opengis.net/def/function/geosparql/> "//
+ "SELECT ?a ?b ?c ?d" //
+ "{" //
+ " ?a a geo:Feature . "//
+ " ?b a geo:Point . "//
+ " ?b geo:asWKT ?c . "//
+ " FILTER(geof:sfWithin(?c, ?d)) " //
+ "}";//
String q35 = "PREFIX fts: <http://rdf.useekm.com/fts#> "//
+ "SELECT ?a ?b ?c" //
+ "{" //
+ " ?a <http://www.w3.org/2000/01/rdf-schema#comment> ?b . "//
+ " FILTER(fts:text(?b, ?c)) " //
+ "}";//
/**
* @param tuple1
* @param tuple2
* @return
* @throws Exception
*/
public boolean tupleEquals(TupleExpr tuple1, TupleExpr tuple2) throws Exception {
Set<StatementPattern> spSet1 = Sets.newHashSet(StatementPatternCollector.process(tuple1));
Set<StatementPattern> spSet2 = Sets.newHashSet(StatementPatternCollector.process(tuple2));
return spSet1.equals(spSet2);
}
/**
* @param tuple1
* @param tuple2
* @return
* @throws Exception
*/
public boolean isTupleSubset(TupleExpr tuple1, TupleExpr tuple2) throws Exception {
Set<StatementPattern> spSet1 = Sets.newHashSet(StatementPatternCollector.process(tuple1));
Set<StatementPattern> spSet2 = Sets.newHashSet(StatementPatternCollector.process(tuple2));
return (Sets.intersection(spSet1, spSet2).equals(spSet2));
}
/**
* @throws Exception
* Tests QueryVariableNormalizerContext with two queries whose
* StatementPattern nodes contain no constant Vars.
*/
@Test
public void testNoConstants() throws Exception {
SPARQLParser parser1 = new SPARQLParser();
SPARQLParser parser2 = new SPARQLParser();
ParsedQuery pq1 = parser1.parseQuery(q15, null);
ParsedQuery pq2 = parser2.parseQuery(q16, null);
List<TupleExpr> normalize = QueryVariableNormalizer.getNormalizedIndex(pq1.getTupleExpr(),
pq2.getTupleExpr());
Assert.assertEquals(2,normalize.size());
for (TupleExpr s : normalize) {
Assert.assertTrue(isTupleSubset(pq1.getTupleExpr(), s));
}
pq1 = parser1.parseQuery(q16, null);
pq2 = parser2.parseQuery(q17, null);
normalize = QueryVariableNormalizer.getNormalizedIndex(pq1.getTupleExpr(), pq2.getTupleExpr());
Assert.assertTrue(normalize.size() == 0);
}
@Test
public void queryConstantNodeOneMatch() throws Exception {
SPARQLParser p = new SPARQLParser();
ParsedQuery pq1 = p.parseQuery(query1, null);
ParsedQuery pq2 = p.parseQuery(index1, null);
List<TupleExpr> normalize = QueryVariableNormalizer.getNormalizedIndex(pq1.getTupleExpr(),
pq2.getTupleExpr());
Assert.assertEquals(1, normalize.size());
for(TupleExpr te: normalize) {
Assert.assertTrue(isTupleSubset(pq1.getTupleExpr(), te));
}
}
/**
* @throws Exception
* Tests QueryVariableNormalizerContext on the large query q9
* with with a smaller, potential index q10 to see if the
* correct number of outputs are produced.
*/
@Test
public void querConstNodeFourMatch() throws Exception {
SPARQLParser parser1 = new SPARQLParser();
SPARQLParser parser2 = new SPARQLParser();
ParsedQuery pq1 = parser1.parseQuery(q9, null);
ParsedQuery pq2 = parser2.parseQuery(q10, null);
List<TupleExpr> normalize = QueryVariableNormalizer.getNormalizedIndex(pq1.getTupleExpr(),
pq2.getTupleExpr());
//System.out.println(normalize);
Assert.assertEquals(4, normalize.size());
for(TupleExpr te: normalize) {
Assert.assertTrue(isTupleSubset(pq1.getTupleExpr(), te));
}
}
@Test
public void queryConstNodeSixMatch() throws Exception {
SPARQLParser parser1 = new SPARQLParser();
SPARQLParser parser2 = new SPARQLParser();
ParsedQuery pq1 = parser1.parseQuery(q9, null);
ParsedQuery pq2 = parser2.parseQuery(q18, null);
List<TupleExpr> normalize = QueryVariableNormalizer.getNormalizedIndex(pq1.getTupleExpr(),
pq2.getTupleExpr());
Assert.assertEquals(6, normalize.size());
//System.out.println("tuple expr is " +pq1.getTupleExpr() + " and normalized tuples are " + normalize);
for(TupleExpr te: normalize) {
Assert.assertTrue(isTupleSubset(pq1.getTupleExpr(), te));
}
}
@Test
public void queryConstGeoFilter() throws Exception {
SPARQLParser parser1 = new SPARQLParser();
SPARQLParser parser2 = new SPARQLParser();
ParsedQuery pq1 = parser1.parseQuery(q32, null);
ParsedQuery pq2 = parser2.parseQuery(q34, null);
List<TupleExpr> normalize = QueryVariableNormalizer.getNormalizedIndex(pq1.getTupleExpr(),
pq2.getTupleExpr());
Assert.assertEquals(1, normalize.size());
for(TupleExpr te: normalize) {
Assert.assertTrue(isTupleSubset(pq1.getTupleExpr(), te));
}
FilterCollector fc1 = new FilterCollector();
pq1.getTupleExpr().visit(fc1);
List<QueryModelNode> fList1 = fc1.getFilters();
for(TupleExpr te: normalize) {
FilterCollector fc2 = new FilterCollector();
te.visit(fc2);
List<QueryModelNode> fList2 = fc2.getFilters();
for(QueryModelNode q: fList2) {
Assert.assertTrue(fList1.contains(q));
}
}
}
@Test
public void queryConstFreeTextFilter() throws Exception {
SPARQLParser parser1 = new SPARQLParser();
SPARQLParser parser2 = new SPARQLParser();
ParsedQuery pq1 = parser1.parseQuery(q33, null);
ParsedQuery pq2 = parser2.parseQuery(q35, null);
System.out.println(pq1.getTupleExpr());
List<TupleExpr> normalize = QueryVariableNormalizer.getNormalizedIndex(pq1.getTupleExpr(),
pq2.getTupleExpr());
Assert.assertEquals(2, normalize.size());
for(TupleExpr te: normalize) {
Assert.assertTrue(isTupleSubset(pq1.getTupleExpr(), te));
}
FilterCollector fc1 = new FilterCollector();
pq1.getTupleExpr().visit(fc1);
List<QueryModelNode> fList1 = fc1.getFilters();
for(TupleExpr te: normalize) {
FilterCollector fc2 = new FilterCollector();
te.visit(fc2);
List<QueryModelNode> fList2 = fc2.getFilters();
for(QueryModelNode q: fList2) {
Assert.assertTrue(fList1.contains(q));
}
}
}
@Test
public void queryConstNodeTwoMatch() throws Exception {
SPARQLParser parser1 = new SPARQLParser();
SPARQLParser parser2 = new SPARQLParser();
ParsedQuery pq1 = parser1.parseQuery(q7, null);
ParsedQuery pq2 = parser2.parseQuery(q4, null);
List<TupleExpr> normalize = QueryVariableNormalizer.getNormalizedIndex(pq1.getTupleExpr(),
pq2.getTupleExpr());
Assert.assertEquals(2, normalize.size());
for(TupleExpr te: normalize) {
Assert.assertTrue(isTupleSubset(pq1.getTupleExpr(), te));
}
}
@Test
public void queryNAryListMatch() throws Exception {
String q1 = ""//
+ "SELECT ?a ?b ?c ?d ?e ?f ?q ?g ?h " //
+ "{" //
+ " GRAPH ?x { " //
+ " ?a a ?b ."//
+ " ?b <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
+ " ?d <uri:talksTo> ?e . "//
+ " FILTER(bound(?f) && sameTerm(?a,?b)&&bound(?q)). " //
+ " FILTER ( ?e < ?f && (?a > ?b || ?c = ?d) ). " //
+ " FILTER(?g IN (1,2,3) && ?h NOT IN(5,6,7)). " //
+ " ?x <http://www.w3.org/2000/01/rdf-schema#label> ?g. "//
+ " ?b a ?q ."//
+ " }"//
+ "}";//
String q2 = ""//
+ "SELECT ?m ?n ?r ?y " //
+ "{" //
+ " GRAPH ?q { " //
+ " FILTER(?m IN (1,?y,3) && ?n NOT IN(?r,6,7)). " //
+ " ?q <http://www.w3.org/2000/01/rdf-schema#label> ?m. "//
+ " }"//
+ "}";//
SPARQLParser parser1 = new SPARQLParser();
SPARQLParser parser2 = new SPARQLParser();
ParsedQuery pq1 = parser1.parseQuery(q1, null);
ParsedQuery pq2 = parser2.parseQuery(q2, null);
List<TupleExpr> normalize = QueryVariableNormalizer.getNormalizedIndex(pq1.getTupleExpr(),
pq2.getTupleExpr());
Assert.assertEquals(1, normalize.size());
for(TupleExpr te: normalize) {
Assert.assertTrue(isTupleSubset(pq1.getTupleExpr(), te));
}
FilterCollector fc1 = new FilterCollector();
pq1.getTupleExpr().visit(fc1);
List<QueryModelNode> fList1 = fc1.getFilters();
for(TupleExpr te: normalize) {
FilterCollector fc2 = new FilterCollector();
te.visit(fc2);
List<QueryModelNode> fList2 = fc2.getFilters();
for(QueryModelNode q: fList2) {
Assert.assertTrue(fList1.contains(q));
}
}
}
@Test
public void queryCompoundFilterMatch() throws Exception {
String q17 = ""//
+ "SELECT ?j ?k ?l ?m ?n ?o " //
+ "{" //
+ " GRAPH ?z { " //
+ " ?j <uri:talksTo> ?k . "//
+ " FILTER ( ?k < ?l && (?m > ?n || ?o = ?j) ). " //
+ " }"//
+ "}";//
// String q18 = ""//
// + "SELECT ?r ?s ?t ?u " //
// + "{" //
// + " GRAPH ?q { " //
// + " FILTER(bound(?r) && sameTerm(?s,?t)&&bound(?u)). " //
// + " ?t a ?u ."//
// + " }"//
// + "}";//
String q19 = ""//
+ "SELECT ?a ?b ?c ?d ?f ?q ?g ?h " //
+ "{" //
+ " GRAPH ?x { " //
+ " ?a a ?b ."//
+ " ?b <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
+ " ?d <uri:talksTo> \"5\" . "//
+ " FILTER ( \"5\" < ?f && (?a > ?b || ?c = ?d) ). " //
+ " FILTER(bound(?f) && sameTerm(?a,?b)&&bound(?q)). " //
+ " FILTER(?g IN (1,2,3) && ?h NOT IN(5,6,7)). " //
+ " ?h <http://www.w3.org/2000/01/rdf-schema#label> ?g. "//
+ " ?b a ?q ."//
+ " }"//
+ "}";//
// String q20 = ""//
// + "SELECT ?m ?n ?o " //
// + "{" //
// + " GRAPH ?q { " //
// + " FILTER(?m IN (1,?o,3) && ?n NOT IN(5,6,7)). " //
// + " ?n <http://www.w3.org/2000/01/rdf-schema#label> ?m. "//
// + " }"//
// + "}";//
SPARQLParser parser1 = new SPARQLParser();
SPARQLParser parser2 = new SPARQLParser();
ParsedQuery pq1 = parser1.parseQuery(q19, null);
ParsedQuery pq2 = parser2.parseQuery(q17, null);
List<TupleExpr> normalize = QueryVariableNormalizer.getNormalizedIndex(pq1.getTupleExpr(),
pq2.getTupleExpr());
System.out.println(normalize);
Assert.assertEquals(1, normalize.size());
for(TupleExpr te: normalize) {
Assert.assertTrue(isTupleSubset(pq1.getTupleExpr(), te));
}
FilterCollector fc1 = new FilterCollector();
pq1.getTupleExpr().visit(fc1);
List<QueryModelNode> fList1 = fc1.getFilters();
for(TupleExpr te: normalize) {
FilterCollector fc2 = new FilterCollector();
te.visit(fc2);
List<QueryModelNode> fList2 = fc2.getFilters();
for(QueryModelNode q: fList2) {
Assert.assertTrue(fList1.contains(q));
}
}
}
// @Test
// public void queryCompoundFilterMatch2() throws Exception {
//
//
//
//
//
//
// String q19 = ""//
// + "SELECT ?a ?b ?c ?d ?f ?q ?g ?h " //
// + "{" //
// + " GRAPH ?x { " //
// + " ?a a ?b ."//
// + " ?b <http://www.w3.org/2000/01/rdf-schema#label> ?c ."//
// + " ?d <uri:talksTo> \"5\" . "//
// + " FILTER ( \"5\" < ?f && (?a > ?b || ?c = ?d) ). " //
// + " FILTER(bound(?f) && sameTerm(?a,?b)&&bound(?q)). " //
// + " FILTER(?g IN (1,5,3) && ?h NOT IN(5,6,7)). " //
// + " ?h <http://www.w3.org/2000/01/rdf-schema#label> ?g. "//
// + " ?b a ?q ."//
// + " }"//
// + "}";//
//
//
// String q20 = ""//
// + "SELECT ?m ?n ?o ?f ?a ?b ?c ?d " //
// + "{" //
// + " GRAPH ?q { " //
// + " ?d <uri:talksTo> ?o . "//
// + " FILTER ( ?o < ?f && (?a > ?b || ?c = ?d) ). " //
// + " FILTER(?m IN (1,?o,3) && ?n NOT IN(5,6,7)). " //
// + " ?n <http://www.w3.org/2000/01/rdf-schema#label> ?m. "//
// + " }"//
// + "}";//
//
//
//
//
// SPARQLParser parser1 = new SPARQLParser();
// SPARQLParser parser2 = new SPARQLParser();
//
// ParsedQuery pq1 = parser1.parseQuery(q19, null);
// ParsedQuery pq2 = parser2.parseQuery(q20, null);
//
// List<TupleExpr> normalize = QueryVariableNormalizer.getNormalizedIndex(pq1.getTupleExpr(),
// pq2.getTupleExpr());
//
//
//
// System.out.println(normalize);
//
// Assert.assertEquals(1, normalize.size());
//
// for(TupleExpr te: normalize) {
// Assert.assertTrue(isTupleSubset(pq1.getTupleExpr(), te));
// }
//
// FilterCollector fc1 = new FilterCollector();
// pq1.getTupleExpr().visit(fc1);
// List<QueryModelNode> fList1 = fc1.getFilters();
//
// for(TupleExpr te: normalize) {
// FilterCollector fc2 = new FilterCollector();
// te.visit(fc2);
// List<QueryModelNode> fList2 = fc2.getFilters();
//
// for(QueryModelNode q: fList2) {
// Assert.assertTrue(fList1.contains(q));
// }
// }
//
//
//
// }
//
//
private static class FilterCollector extends AbstractQueryModelVisitor<RuntimeException> {
private List<QueryModelNode> filterList = Lists.newArrayList();
public List<QueryModelNode> getFilters() {
return filterList;
}
@Override
public void meet(Filter node) {
filterList.add(node.getCondition());
super.meet(node);
}
}
}