/* * 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. */ package org.apache.jena.sparql.algebra; import org.apache.jena.atlas.junit.BaseTest ; import org.apache.jena.atlas.lib.StrUtils ; 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.sse.SSE ; import org.junit.Test ; //Tests for conversion of algebra forms to quad form. public class TestTransformQuads extends BaseTest { // Simple @Test public void quads01() { test ("{ GRAPH ?g { ?s ?p ?o } }", "(quadpattern (quad ?g ?s ?p ?o))" ) ; } // Not nested @Test public void quads02() { test ("{ GRAPH ?g { ?s ?p ?o } GRAPH ?g1 { ?s1 ?p1 ?o1 } }", "(sequence" + " (quadpattern (quad ?g ?s ?p ?o))", " (quadpattern (quad ?g1 ?s1 ?p1 ?o1)))" ) ; } @Test public void quads03() { test ("{ GRAPH ?g { ?s ?p ?o } GRAPH ?g { ?s1 ?p1 ?o1 } }", "(sequence" + " (quadpattern (quad ?g ?s ?p ?o))" + " (quadpattern (quad ?g ?s1 ?p1 ?o1)))" ) ; } // Nested @Test public void quads04() { test ("{ GRAPH ?g { ?s ?p ?o GRAPH ?g1 { ?s1 ?p1 ?o1 } } }", "(sequence" + " (quadpattern (quad ?g ?s ?p ?o))" + " (quadpattern (quad ?g1 ?s1 ?p1 ?o1)))" ) ; } @Test public void quads05() { test ("{ GRAPH ?g { ?s ?p ?o GRAPH ?g { ?s1 ?p1 ?o1 } } }", "(assign ((?g ?*g0))" + " (sequence" + " (quadpattern (quad ?*g0 ?s ?p ?o))" + " (quadpattern (quad ?g ?s1 ?p1 ?o1))))" ) ; } // Filters @Test public void quads10() { test ("{ GRAPH ?g { ?s ?p ?o FILTER (str(?g) = 'graphURI') } }", "(assign ((?g ?*g0))" + " (filter (= (str ?g) 'graphURI')" + " (quadpattern (quad ?*g0 ?s ?p ?o))))" ) ; } @Test public void quads11() { test ("{ GRAPH ?g { ?s ?p ?o } FILTER (str(?g) = 'graphURI') }", "(filter (= (str ?g) 'graphURI')" + " (quadpattern (quad ?g ?s ?p ?o)))" ) ; } // Nested and filter // ?g is unbound in the filter. @Test public void quads20() { test ("{ GRAPH ?g { ?s ?p ?o GRAPH ?g1 { ?s1 ?p1 ?o1 FILTER (str(?g) = 'graphURI') } } }", "(assign ((?g ?*g0))" + " (join" + " (quadpattern (quad ?*g0 ?s ?p ?o))" + " (filter (= (str ?g) 'graphURI')" + " (quadpattern (quad ?g1 ?s1 ?p1 ?o1)))))" ) ; } @Test public void quads21() { test ("{ GRAPH ?g { ?s ?p ?o GRAPH ?g1 { ?s1 ?p1 ?o1 FILTER (str(?g1) = 'graphURI') } } }", "(sequence" + " (quadpattern (quad ?g ?s ?p ?o))" + " (assign ((?g1 ?*g0))" + " (filter (= (str ?g1) 'graphURI')" + " (quadpattern (quad ?*g0 ?s1 ?p1 ?o1)))))" ) ; } // Tricky pattern ... twice. @Test public void quads30() { test ( "{ GRAPH ?g { ?s ?p ?o FILTER (str(?g) = 'graphURI') } " + " GRAPH ?g { ?s ?p ?o FILTER (str(?g) = 'graphURI') } }", "(sequence" + " (assign ((?g ?*g0))" + " (filter (= (str ?g) 'graphURI')" + " (quadpattern (quad ?*g0 ?s ?p ?o))))" + " (assign ((?g ?*g1))" + " (filter (= (str ?g) 'graphURI')" + " (quadpattern (quad ?*g1 ?s ?p ?o)))))" ) ; } // NOT EXISTS @Test public void quads31() { test ( "{ GRAPH ?g { ?s ?p ?o FILTER NOT EXISTS { GRAPH ?g1 { ?s1 ?p ?o1 } } } }", "(filter (notexists", " (quadpattern (quad ?g1 ?s1 ?p ?o1)))", " (quadpattern (quad ?g ?s ?p ?o)))" ) ; } // NOT EXISTS @Test public void quads32() { test ( "{ ?s ?p ?o FILTER NOT EXISTS { GRAPH ?g1 { ?s1 ?p ?o1 } } }", "(filter (notexists", " (quadpattern (quad ?g1 ?s1 ?p ?o1)))", " (quadpattern (quad <urn:x-arq:DefaultGraphNode> ?s ?p ?o)))" ) ; } @Test public void quads33() { test ( "{ GRAPH ?g { { SELECT ?x WHERE { ?x ?p ?g } } } }", "(project (?x)", " (quadpattern (quad ?g ?x ?/p ?/g)))") ; } // JENA-535 @Test public void quads34() { test ( "{ ?s ?p ?o OPTIONAL { FILTER NOT EXISTS { ?x ?y ?z } } }", "(conditional", " (quadpattern (quad <urn:x-arq:DefaultGraphNode> ?s ?p ?o))", " (filter (notexists", " (quadpattern (quad <urn:x-arq:DefaultGraphNode> ?x ?y ?z)))", " (table unit)))") ; } // NOT EXISTS in left join expression. @Test public void quads35() { test ( "{ ?s ?p ?o OPTIONAL { FILTER NOT EXISTS { ?x ?y ?z } } }", false, "(leftjoin", " (quadpattern (quad <urn:x-arq:DefaultGraphNode> ?s ?p ?o))", " (table unit)", " (notexists", " (quadpattern (quad <urn:x-arq:DefaultGraphNode> ?x ?y ?z))))") ; } // NOT EXISTS in left join expression. @Test public void quads36() { test ( "{ ?s ?p ?o OPTIONAL { FILTER NOT EXISTS { GRAPH ?g { ?x ?y ?z } } } }", false, "(leftjoin", " (quadpattern (quad <urn:x-arq:DefaultGraphNode> ?s ?p ?o))", " (table unit)", " (notexists", " (quadpattern (?g ?x ?y ?z))))") ; } // NOT EXISTS in BIND @Test public void quads37() { test ( "{ BIND ( true && NOT EXISTS { GRAPH ?g { ?x ?y ?z } } AS ?X ) }", "(extend ((?X (&& true (notexists", " (quadpattern (quad ?g ?x ?y ?z))))))", " (table unit))") ; } // Don't touch SERVICE @Test public void quads38() { test ("{ {?s ?p ?o } UNION { SERVICE <http://host/endpoint> { GRAPH ?gr { ?sr ?pr ?or }}} }", "(union", " (quadpattern (quad <urn:x-arq:DefaultGraphNode> ?s ?p ?o))", " (service <http://host/endpoint>", " (graph ?gr", " (bgp (triple ?sr ?pr ?or))))", ")") ; } // Don't touch SERVICE @Test public void quads39() { test ("{ { GRAPH ?g { ?s ?p ?o } } UNION { SERVICE <http://host/endpoint> { GRAPH ?gr { ?sr ?pr ?or }}} }", "(union", " (quadpattern (?g ?s ?p ?o))", " (service <http://host/endpoint>", " (graph ?gr", " (bgp (triple ?sr ?pr ?or))))", ")") ; } // Don't touch SERVICE @Test public void quads40() { test ("{ GRAPH ?g { SERVICE <http://host/endpoint> { ?s ?p ?o }}}", "(service <http://host/endpoint> (bgp (triple ?s ?p ?o)))") ; } // Don't touch SERVICE @Test public void quads41() { test ("{ GRAPH ?g1 { SERVICE <http://host/endpoint> { ?s ?p ?o } ?s1 ?p1 ?o1 } }", "(sequence", " (service <http://host/endpoint> (bgp (triple ?s ?p ?o)))", " (quadpattern (?g1 ?s1 ?p1 ?o1))", ")") ; } private static void test(String patternString, String... strExpected) { test(patternString, true, strExpected) ; } private static void test(String patternString, boolean optimize, String... strExpected) { Query q = QueryFactory.create("SELECT * WHERE "+patternString) ; Op op = Algebra.compile(q) ; if ( optimize ) op = Algebra.optimize(op) ; op = Algebra.toQuadForm(op) ; Op op2 = SSE.parseOp(StrUtils.strjoinNL(strExpected)) ; assertEquals(op2, op) ; } }