QueryPlanRetrievalTest.java
/*******************************************************************************
* Copyright (c) 2020 Eclipse RDF4J contributors.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
package org.eclipse.rdf4j.sail.memory;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.IOUtils;
import org.eclipse.rdf4j.common.transaction.IsolationLevels;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
import org.eclipse.rdf4j.model.vocabulary.FOAF;
import org.eclipse.rdf4j.model.vocabulary.RDF;
import org.eclipse.rdf4j.model.vocabulary.RDFS;
import org.eclipse.rdf4j.query.Query;
import org.eclipse.rdf4j.query.TupleQuery;
import org.eclipse.rdf4j.query.explanation.Explanation;
import org.eclipse.rdf4j.query.explanation.GenericPlanNode;
import org.eclipse.rdf4j.repository.sail.SailRepository;
import org.eclipse.rdf4j.repository.sail.SailRepositoryConnection;
import org.eclipse.rdf4j.rio.RDFFormat;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
public class QueryPlanRetrievalTest {
public static final String MAIN_QUERY = String.join("\n", "",
"{",
" {",
" OPTIONAL {",
" ?d ?e ?f",
" }",
" } ",
" ?a a ?c, ?d. ",
" FILTER(?c != ?d && ?c != \"<\") ",
" OPTIONAL{",
" ?d ?e ?f",
" } ",
"}");
public static final String TUPLE_QUERY = "SELECT ?a WHERE " + MAIN_QUERY;
public static final String ASK_QUERY = "ASK WHERE " + MAIN_QUERY;
public static final String CONSTRUCT_QUERY = "CONSTRUCT {?a a ?c, ?d} WHERE " + MAIN_QUERY;
public static final String SUB_QUERY = "select ?a where {{select ?a where {?a a ?type}} {SELECT ?a WHERE "
+ MAIN_QUERY + "}}";
public static final String SUB_QUERY2 = "PREFIX epo: <http://data.europa.eu/a4g/ontology#>\n" +
"PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n" +
"PREFIX legal: <https://www.w3.org/ns/legal#>\n" +
"PREFIX dcterms: <http://purl.org/dc/terms#>\n" +
"PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>\n" +
"PREFIX dc: <http://purl.org/dc/elements/1.1/>\n" +
"\n" +
"SELECT DISTINCT ?countryID ?year (COUNT(DISTINCT ?lot) AS ?amountLots) (SUM(if(?bidders = 1, 1, 0)) AS ?numSingleBidders) WHERE {\n"
+
"\n" +
" ?proc a epo:Procedure .\n" +
" ?proc epo:hasProcedureType ?p .\n" +
" ?stat epo:concernsSubmissionsForLot ?lot .\n" +
" ?stat a epo:SubmissionStatisticalInformation .\n" +
" ?stat epo:hasReceivedTenders ?bidders .\n" +
" ?resultnotice a epo:ResultNotice .\n" +
" ?resultnotice epo:hasDispatchDate ?ddate .\n" +
" ?proc epo:hasProcurementScopeDividedIntoLot ?lot .\n" +
" ?resultnotice epo:refersToRole ?buyerrole .\n" +
" ?resultnotice epo:refersToProcedure ?proc .\n" +
"\n" +
" \tFILTER ( ?p != <http://publications.europa.eu/resource/authority/procurement-procedure-type/neg-wo-call>)\n"
+
"\t\tBIND(year(xsd:dateTime(?ddate)) AS ?year) .\n" +
"\n" +
"\n" +
" {\n" +
" SELECT DISTINCT ?buyerrole ?countryID WHERE {\n" +
" ?org epo:hasBuyerType ?buytype .\n" +
" FILTER (?buytype != <http://publications.europa.eu/resource/authority/buyer-legal-type/eu-int-org> )\n"
+
"\n" +
" ?buyerrole epo:playedBy ?org .\n" +
" ?org legal:registeredAddress ?orgaddress .\n" +
" ?orgaddress epo:hasCountryCode ?countrycode .\n" +
" ?countrycode dc:identifier ?countryID .\n" +
"\n" +
" }\n" +
" }\n" +
"} GROUP BY ?countryID ?year";
public static final String UNION_QUERY = "select ?a where {?a a ?type. {?a ?b ?c, ?c2. {?c2 a ?type1}UNION{?c2 a ?type2}} UNION {?type ?d ?c}}";
ValueFactory vf = SimpleValueFactory.getInstance();
private void addData(SailRepository sailRepository) {
try (SailRepositoryConnection connection = sailRepository.getConnection()) {
connection.add(RDFS.RESOURCE, RDF.TYPE, RDFS.RESOURCE);
connection.add(RDF.PROPERTY, RDF.TYPE, RDFS.RESOURCE);
connection.add(RDF.TYPE, RDF.TYPE, RDF.PROPERTY);
connection.add(RDF.TYPE, RDF.TYPE, RDFS.RESOURCE);
connection.add(vf.createBNode("01"), FOAF.KNOWS, vf.createBNode("02"));
connection.add(vf.createBNode("03"), FOAF.KNOWS, vf.createBNode("04"));
connection.add(vf.createBNode("05"), FOAF.KNOWS, vf.createBNode("06"));
connection.add(vf.createBNode("07"), FOAF.KNOWS, vf.createBNode("08"));
connection.add(vf.createBNode("09"), FOAF.KNOWS, vf.createBNode("10"));
connection.add(vf.createBNode("11"), FOAF.KNOWS, vf.createBNode("12"));
connection.add(vf.createBNode("13"), FOAF.KNOWS, vf.createBNode("14"));
connection.add(vf.createBNode("15"), FOAF.KNOWS, vf.createBNode("16"));
}
}
@Test
public void testTupleQuery() {
SailRepository sailRepository = new SailRepository(new MemoryStore());
try (SailRepositoryConnection connection = sailRepository.getConnection()) {
Query query = connection.prepareTupleQuery(TUPLE_QUERY);
String actual = query.explain(Explanation.Level.Unoptimized).toString();
String expected = "Projection\n" +
"��������� ProjectionElemList\n" +
"��� ProjectionElem \"a\"\n" +
"��������� Filter\n" +
" ��������� And\n" +
" ��� ��������� Compare (!=)\n" +
" ��� ��� Var (name=c)\n" +
" ��� ��� Var (name=d)\n" +
" ��� ��������� Compare (!=)\n" +
" ��� Var (name=c)\n" +
" ��� ValueConstant (value=\"<\")\n" +
" ��������� LeftJoin\n" +
" ��������� Join [left]\n" +
" ��� ��������� LeftJoin (new scope) [left]\n" +
" ��� ��� ��������� SingletonSet [left]\n" +
" ��� ��� ��������� StatementPattern [right]\n" +
" ��� ��� s: Var (name=d)\n" +
" ��� ��� p: Var (name=e)\n" +
" ��� ��� o: Var (name=f)\n" +
" ��� ��������� Join [right]\n" +
" ��� ��������� StatementPattern [left]\n" +
" ��� ��� s: Var (name=a)\n" +
" ��� ��� p: Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" ��� ��� o: Var (name=c)\n" +
" ��� ��������� StatementPattern [right]\n" +
" ��� s: Var (name=a)\n" +
" ��� p: Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" ��� o: Var (name=d)\n" +
" ��������� StatementPattern [right]\n" +
" s: Var (name=d)\n" +
" p: Var (name=e)\n" +
" o: Var (name=f)\n";
assertThat(actual).isEqualToNormalizingNewlines(expected);
}
sailRepository.shutDown();
}
@Test
public void testTupleQueryOptimized() {
SailRepository sailRepository = new SailRepository(new MemoryStore());
addData(sailRepository);
try (SailRepositoryConnection connection = sailRepository.getConnection()) {
TupleQuery query = connection.prepareTupleQuery(TUPLE_QUERY);
String actual = query.explain(Explanation.Level.Optimized).toString();
String expected = "Projection\n" +
"��������� ProjectionElemList\n" +
"��� ProjectionElem \"a\"\n" +
"��������� LeftJoin (LeftJoinIterator)\n" +
" ��������� Join (JoinIterator) [left]\n" +
" ��� ��������� StatementPattern (costEstimate=3.00, resultSizeEstimate=4.00) [left]\n" +
" ��� ��� s: Var (name=a)\n" +
" ��� ��� p: Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" ��� ��� o: Var (name=d)\n" +
" ��� ��������� Filter [right]\n" +
" ��� ��������� Compare (!=)\n" +
" ��� ��� Var (name=c)\n" +
" ��� ��� Var (name=d)\n" +
" ��� ��������� Join (HashJoinIteration)\n" +
" ��� ��������� Filter [left]\n" +
" ��� ��� ��������� Compare (!=)\n" +
" ��� ��� ��� Var (name=c)\n" +
" ��� ��� ��� ValueConstant (value=\"<\")\n" +
" ��� ��� ��������� StatementPattern (costEstimate=3.00, resultSizeEstimate=4.00)\n" +
" ��� ��� s: Var (name=a)\n" +
" ��� ��� p: Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" ��� ��� o: Var (name=c)\n" +
" ��� ��������� LeftJoin (new scope) (costEstimate=6.61, resultSizeEstimate=12) [right]\n" +
" ��� ��������� SingletonSet [left]\n" +
" ��� ��������� StatementPattern (resultSizeEstimate=12) [right]\n" +
" ��� s: Var (name=d)\n" +
" ��� p: Var (name=e)\n" +
" ��� o: Var (name=f)\n" +
" ��������� StatementPattern (resultSizeEstimate=12) [right]\n" +
" s: Var (name=d)\n" +
" p: Var (name=e)\n" +
" o: Var (name=f)\n";
assertThat(actual).isEqualToNormalizingNewlines(expected);
}
sailRepository.shutDown();
}
@Test
@Disabled
public void testTupleQueryTimed() {
SailRepository sailRepository = new SailRepository(new MemoryStore());
addData(sailRepository);
try (SailRepositoryConnection connection = sailRepository.getConnection()) {
TupleQuery query = connection.prepareTupleQuery(TUPLE_QUERY);
GenericPlanNode genericPlanNode = query.explain(Explanation.Level.Timed).toGenericPlanNode();
GenericPlanNode leftJoin = genericPlanNode.getPlans().get(1);
GenericPlanNode filterNode = genericPlanNode.getPlans().get(1).getPlans().get(0).getPlans().get(1);
assertEquals("LeftJoin", leftJoin.getType());
assertEquals("Filter", filterNode.getType());
assertTrue(filterNode.getSelfTimeActual() > leftJoin.getSelfTimeActual());
assertTrue(filterNode.getSelfTimeActual() < leftJoin.getTotalTimeActual());
assertThat(genericPlanNode.toString()).contains("selfTimeActual");
assertThat(genericPlanNode.toString()).contains("totalTimeActual");
}
sailRepository.shutDown();
}
@Test
public void testTupleQueryExecuted() {
SailRepository sailRepository = new SailRepository(new MemoryStore());
addData(sailRepository);
try (SailRepositoryConnection connection = sailRepository.getConnection()) {
Query query = connection.prepareTupleQuery(TUPLE_QUERY);
String actual = query.explain(Explanation.Level.Executed).toString();
String expected = "Projection (resultSizeActual=2)\n" +
"��������� ProjectionElemList\n" +
"��� ProjectionElem \"a\"\n" +
"��������� LeftJoin (LeftJoinIterator) (resultSizeActual=2)\n" +
" ��������� Join (JoinIterator) (resultSizeActual=2) [left]\n" +
" ��� ��������� StatementPattern (costEstimate=3.00, resultSizeEstimate=4.00, resultSizeActual=4) [left]\n"
+
" ��� ��� s: Var (name=a)\n" +
" ��� ��� p: Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" ��� ��� o: Var (name=d)\n" +
" ��� ��������� Filter (resultSizeActual=2) [right]\n" +
" ��� ��������� Compare (!=)\n" +
" ��� ��� Var (name=c)\n" +
" ��� ��� Var (name=d)\n" +
" ��� ��������� Join (HashJoinIteration) (resultSizeActual=6)\n" +
" ��� ��������� Filter (resultSizeActual=6) [left]\n" +
" ��� ��� ��������� Compare (!=)\n" +
" ��� ��� ��� Var (name=c)\n" +
" ��� ��� ��� ValueConstant (value=\"<\")\n" +
" ��� ��� ��������� StatementPattern (costEstimate=3.00, resultSizeEstimate=4.00, resultSizeActual=6)\n"
+
" ��� ��� s: Var (name=a)\n" +
" ��� ��� p: Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" ��� ��� o: Var (name=c)\n" +
" ��� ��������� LeftJoin (new scope) (BadlyDesignedLeftJoinIterator) (costEstimate=6.61, resultSizeEstimate=12, resultSizeActual=4) [right]\n"
+
" ��� ��������� SingletonSet (resultSizeActual=4) [left]\n" +
" ��� ��������� StatementPattern (resultSizeEstimate=12, resultSizeActual=48) [right]\n" +
" ��� s: Var (name=d)\n" +
" ��� p: Var (name=e)\n" +
" ��� o: Var (name=f)\n" +
" ��������� StatementPattern (resultSizeEstimate=12, resultSizeActual=2) [right]\n" +
" s: Var (name=d)\n" +
" p: Var (name=e)\n" +
" o: Var (name=f)\n";
assertThat(actual).isEqualToNormalizingNewlines(expected);
}
sailRepository.shutDown();
}
@Test
public void testGenericPlanNode() {
SailRepository sailRepository = new SailRepository(new MemoryStore());
addData(sailRepository);
try (SailRepositoryConnection connection = sailRepository.getConnection()) {
Query query = connection.prepareTupleQuery(TUPLE_QUERY);
String actual = query.explain(Explanation.Level.Executed).toGenericPlanNode().toString();
String expected = "Projection (resultSizeActual=2)\n" +
"��������� ProjectionElemList\n" +
"��� ProjectionElem \"a\"\n" +
"��������� LeftJoin (LeftJoinIterator) (resultSizeActual=2)\n" +
" ��������� Join (JoinIterator) (resultSizeActual=2) [left]\n" +
" ��� ��������� StatementPattern (costEstimate=3.00, resultSizeEstimate=4.00, resultSizeActual=4) [left]\n"
+
" ��� ��� s: Var (name=a)\n" +
" ��� ��� p: Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" ��� ��� o: Var (name=d)\n" +
" ��� ��������� Filter (resultSizeActual=2) [right]\n" +
" ��� ��������� Compare (!=)\n" +
" ��� ��� Var (name=c)\n" +
" ��� ��� Var (name=d)\n" +
" ��� ��������� Join (HashJoinIteration) (resultSizeActual=6)\n" +
" ��� ��������� Filter (resultSizeActual=6) [left]\n" +
" ��� ��� ��������� Compare (!=)\n" +
" ��� ��� ��� Var (name=c)\n" +
" ��� ��� ��� ValueConstant (value=\"<\")\n" +
" ��� ��� ��������� StatementPattern (costEstimate=3.00, resultSizeEstimate=4.00, resultSizeActual=6)\n"
+
" ��� ��� s: Var (name=a)\n" +
" ��� ��� p: Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" ��� ��� o: Var (name=c)\n" +
" ��� ��������� LeftJoin (new scope) (BadlyDesignedLeftJoinIterator) (costEstimate=6.61, resultSizeEstimate=12, resultSizeActual=4) [right]\n"
+
" ��� ��������� SingletonSet (resultSizeActual=4) [left]\n" +
" ��� ��������� StatementPattern (resultSizeEstimate=12, resultSizeActual=48) [right]\n" +
" ��� s: Var (name=d)\n" +
" ��� p: Var (name=e)\n" +
" ��� o: Var (name=f)\n" +
" ��������� StatementPattern (resultSizeEstimate=12, resultSizeActual=2) [right]\n" +
" s: Var (name=d)\n" +
" p: Var (name=e)\n" +
" o: Var (name=f)\n";
assertThat(actual).isEqualToNormalizingNewlines(expected);
}
sailRepository.shutDown();
}
@Test
public void testJsonPlanNode() {
SailRepository sailRepository = new SailRepository(new MemoryStore());
addData(sailRepository);
try (SailRepositoryConnection connection = sailRepository.getConnection()) {
Query query = connection.prepareTupleQuery(TUPLE_QUERY);
String actual = query.explain(Explanation.Level.Executed).toJson();
String expected = "{\n" +
" \"type\" : \"Projection\",\n" +
" \"resultSizeActual\" : 2,\n" +
" \"plans\" : [ {\n" +
" \"type\" : \"ProjectionElemList\",\n" +
" \"plans\" : [ {\n" +
" \"type\" : \"ProjectionElem \\\"a\\\"\"\n" +
" } ]\n" +
" }, {\n" +
" \"type\" : \"LeftJoin\",\n" +
" \"resultSizeActual\" : 2,\n" +
" \"algorithm\" : \"LeftJoinIterator\",\n" +
" \"plans\" : [ {\n" +
" \"type\" : \"Join\",\n" +
" \"resultSizeActual\" : 2,\n" +
" \"algorithm\" : \"JoinIterator\",\n" +
" \"plans\" : [ {\n" +
" \"type\" : \"StatementPattern\",\n" +
" \"costEstimate\" : 3.0,\n" +
" \"resultSizeEstimate\" : 4.0,\n" +
" \"resultSizeActual\" : 4,\n" +
" \"plans\" : [ {\n" +
" \"type\" : \"Var (name=a)\"\n" +
" }, {\n" +
" \"type\" : \"Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\"\n"
+
" }, {\n" +
" \"type\" : \"Var (name=d)\"\n" +
" } ]\n" +
" }, {\n" +
" \"type\" : \"Filter\",\n" +
" \"resultSizeActual\" : 2,\n" +
" \"plans\" : [ {\n" +
" \"type\" : \"Compare (!=)\",\n" +
" \"plans\" : [ {\n" +
" \"type\" : \"Var (name=c)\"\n" +
" }, {\n" +
" \"type\" : \"Var (name=d)\"\n" +
" } ]\n" +
" }, {\n" +
" \"type\" : \"Join\",\n" +
" \"resultSizeActual\" : 6,\n" +
" \"algorithm\" : \"HashJoinIteration\",\n" +
" \"plans\" : [ {\n" +
" \"type\" : \"Filter\",\n" +
" \"resultSizeActual\" : 6,\n" +
" \"plans\" : [ {\n" +
" \"type\" : \"Compare (!=)\",\n" +
" \"plans\" : [ {\n" +
" \"type\" : \"Var (name=c)\"\n" +
" }, {\n" +
" \"type\" : \"ValueConstant (value=\\\"<\\\")\"\n" +
" } ]\n" +
" }, {\n" +
" \"type\" : \"StatementPattern\",\n" +
" \"costEstimate\" : 3.0,\n" +
" \"resultSizeEstimate\" : 4.0,\n" +
" \"resultSizeActual\" : 6,\n" +
" \"plans\" : [ {\n" +
" \"type\" : \"Var (name=a)\"\n" +
" }, {\n" +
" \"type\" : \"Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\"\n"
+
" }, {\n" +
" \"type\" : \"Var (name=c)\"\n" +
" } ]\n" +
" } ]\n" +
" }, {\n" +
" \"type\" : \"LeftJoin\",\n" +
" \"costEstimate\" : 6.611489018457944,\n" +
" \"resultSizeEstimate\" : 12.0,\n" +
" \"resultSizeActual\" : 4,\n" +
" \"newScope\" : true,\n" +
" \"algorithm\" : \"BadlyDesignedLeftJoinIterator\",\n" +
" \"plans\" : [ {\n" +
" \"type\" : \"SingletonSet\",\n" +
" \"resultSizeActual\" : 4\n" +
" }, {\n" +
" \"type\" : \"StatementPattern\",\n" +
" \"resultSizeEstimate\" : 12.0,\n" +
" \"resultSizeActual\" : 48,\n" +
" \"plans\" : [ {\n" +
" \"type\" : \"Var (name=d)\"\n" +
" }, {\n" +
" \"type\" : \"Var (name=e)\"\n" +
" }, {\n" +
" \"type\" : \"Var (name=f)\"\n" +
" } ]\n" +
" } ]\n" +
" } ]\n" +
" } ]\n" +
" } ]\n" +
" }, {\n" +
" \"type\" : \"StatementPattern\",\n" +
" \"resultSizeEstimate\" : 12.0,\n" +
" \"resultSizeActual\" : 2,\n" +
" \"plans\" : [ {\n" +
" \"type\" : \"Var (name=d)\"\n" +
" }, {\n" +
" \"type\" : \"Var (name=e)\"\n" +
" }, {\n" +
" \"type\" : \"Var (name=f)\"\n" +
" } ]\n" +
" } ]\n" +
" } ]\n" +
"}";
assertThat(actual).isEqualToNormalizingNewlines(expected);
}
sailRepository.shutDown();
}
@Test
public void testAskQuery() {
SailRepository sailRepository = new SailRepository(new MemoryStore());
addData(sailRepository);
try (SailRepositoryConnection connection = sailRepository.getConnection()) {
Query query = connection.prepareBooleanQuery(ASK_QUERY);
String actual = query.explain(Explanation.Level.Executed).toString();
String expected = "Slice (limit=1) (resultSizeActual=1)\n" +
" LeftJoin (LeftJoinIterator) (resultSizeActual=1)\n" +
" ��������� Join (JoinIterator) (resultSizeActual=1) [left]\n" +
" ��� ��������� StatementPattern (costEstimate=3.00, resultSizeEstimate=4.00, resultSizeActual=3) [left]\n"
+
" ��� ��� s: Var (name=a)\n" +
" ��� ��� p: Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" ��� ��� o: Var (name=d)\n" +
" ��� ��������� Filter (resultSizeActual=1) [right]\n" +
" ��� ��������� Compare (!=)\n" +
" ��� ��� Var (name=c)\n" +
" ��� ��� Var (name=d)\n" +
" ��� ��������� Join (HashJoinIteration) (resultSizeActual=4)\n" +
" ��� ��������� Filter (resultSizeActual=4) [left]\n" +
" ��� ��� ��������� Compare (!=)\n" +
" ��� ��� ��� Var (name=c)\n" +
" ��� ��� ��� ValueConstant (value=\"<\")\n" +
" ��� ��� ��������� StatementPattern (costEstimate=3.00, resultSizeEstimate=4.00, resultSizeActual=4)\n"
+
" ��� ��� s: Var (name=a)\n" +
" ��� ��� p: Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" ��� ��� o: Var (name=c)\n" +
" ��� ��������� LeftJoin (new scope) (BadlyDesignedLeftJoinIterator) (costEstimate=6.61, resultSizeEstimate=12, resultSizeActual=3) [right]\n"
+
" ��� ��������� SingletonSet (resultSizeActual=3) [left]\n" +
" ��� ��������� StatementPattern (resultSizeEstimate=12, resultSizeActual=36) [right]\n" +
" ��� s: Var (name=d)\n" +
" ��� p: Var (name=e)\n" +
" ��� o: Var (name=f)\n" +
" ��������� StatementPattern (resultSizeEstimate=12, resultSizeActual=1) [right]\n" +
" s: Var (name=d)\n" +
" p: Var (name=e)\n" +
" o: Var (name=f)\n";
assertThat(actual).isEqualToNormalizingNewlines(expected);
}
sailRepository.shutDown();
}
@Test
public void testConstructQuery() {
SailRepository sailRepository = new SailRepository(new MemoryStore());
addData(sailRepository);
try (SailRepositoryConnection connection = sailRepository.getConnection()) {
Query query = connection.prepareGraphQuery(CONSTRUCT_QUERY);
String actual = query.explain(Explanation.Level.Executed).toString();
String expected = "Reduced (resultSizeActual=3)\n" +
" MultiProjection (resultSizeActual=4)\n" +
" ProjectionElemList\n" +
" ProjectionElem \"a\" AS \"subject\"\n" +
" ProjectionElem \"_const_f5e5585a_uri\" AS \"predicate\"\n" +
" ProjectionElem \"c\" AS \"object\"\n" +
" ProjectionElemList\n" +
" ProjectionElem \"a\" AS \"subject\"\n" +
" ProjectionElem \"_const_f5e5585a_uri\" AS \"predicate\"\n" +
" ProjectionElem \"d\" AS \"object\"\n" +
" Extension (resultSizeActual=2)\n" +
" ��������� LeftJoin (LeftJoinIterator) (resultSizeActual=2)\n" +
" ��� ��������� Join (JoinIterator) (resultSizeActual=2) [left]\n" +
" ��� ��� ��������� StatementPattern (costEstimate=3.00, resultSizeEstimate=4.00, resultSizeActual=4) [left]\n"
+
" ��� ��� ��� s: Var (name=a)\n" +
" ��� ��� ��� p: Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" ��� ��� ��� o: Var (name=d)\n" +
" ��� ��� ��������� Filter (resultSizeActual=2) [right]\n" +
" ��� ��� ��������� Compare (!=)\n" +
" ��� ��� ��� Var (name=c)\n" +
" ��� ��� ��� Var (name=d)\n" +
" ��� ��� ��������� Join (HashJoinIteration) (resultSizeActual=6)\n" +
" ��� ��� ��������� Filter (resultSizeActual=6) [left]\n" +
" ��� ��� ��� ��������� Compare (!=)\n" +
" ��� ��� ��� ��� Var (name=c)\n" +
" ��� ��� ��� ��� ValueConstant (value=\"<\")\n" +
" ��� ��� ��� ��������� StatementPattern (costEstimate=3.00, resultSizeEstimate=4.00, resultSizeActual=6)\n"
+
" ��� ��� ��� s: Var (name=a)\n" +
" ��� ��� ��� p: Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" ��� ��� ��� o: Var (name=c)\n" +
" ��� ��� ��������� LeftJoin (new scope) (BadlyDesignedLeftJoinIterator) (costEstimate=6.61, resultSizeEstimate=12, resultSizeActual=4) [right]\n"
+
" ��� ��� ��������� SingletonSet (resultSizeActual=4) [left]\n" +
" ��� ��� ��������� StatementPattern (resultSizeEstimate=12, resultSizeActual=48) [right]\n" +
" ��� ��� s: Var (name=d)\n" +
" ��� ��� p: Var (name=e)\n" +
" ��� ��� o: Var (name=f)\n" +
" ��� ��������� StatementPattern (resultSizeEstimate=12, resultSizeActual=2) [right]\n" +
" ��� s: Var (name=d)\n" +
" ��� p: Var (name=e)\n" +
" ��� o: Var (name=f)\n" +
" ��������� ExtensionElem (_const_f5e5585a_uri)\n" +
" ValueConstant (value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type)\n";
assertThat(actual).isEqualToNormalizingNewlines(expected);
}
sailRepository.shutDown();
}
@Disabled // slow test used for debugging
@Test
public void bigDataset() throws IOException {
SailRepository repository = new SailRepository(new MemoryStore());
try (SailRepositoryConnection connection = repository.getConnection()) {
connection.begin(IsolationLevels.NONE);
connection.add(QueryPlanRetrievalTest.class.getClassLoader()
.getResourceAsStream("benchmarkFiles/datagovbe-valid.ttl"), "", RDFFormat.TURTLE);
connection.commit();
}
String query1 = IOUtils.toString(
QueryPlanRetrievalTest.class.getClassLoader().getResourceAsStream("benchmarkFiles/query1.qr"),
StandardCharsets.UTF_8);
try (SailRepositoryConnection connection = repository.getConnection()) {
String s = connection.prepareTupleQuery(query1).explain(Explanation.Level.Timed).toString();
System.out.println(s);
}
repository.shutDown();
}
@Test
public void testSubQuery() {
SailRepository sailRepository = new SailRepository(new MemoryStore());
addData(sailRepository);
try (SailRepositoryConnection connection = sailRepository.getConnection()) {
Query query = connection.prepareTupleQuery(SUB_QUERY);
String actual = query.explain(Explanation.Level.Executed).toString();
String expected = "Projection (resultSizeActual=4)\n" +
"��������� ProjectionElemList\n" +
"��� ProjectionElem \"a\"\n" +
"��������� Join (HashJoinIteration) (resultSizeActual=4)\n" +
" ��������� Projection (new scope) (resultSizeActual=4) [left]\n" +
" ��� ��������� ProjectionElemList\n" +
" ��� ��� ProjectionElem \"a\"\n" +
" ��� ��������� StatementPattern (resultSizeEstimate=4.00, resultSizeActual=4)\n" +
" ��� s: Var (name=a)\n" +
" ��� p: Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" ��� o: Var (name=type)\n" +
" ��������� Projection (new scope) (resultSizeActual=2) [right]\n" +
" ��������� ProjectionElemList\n" +
" ��� ProjectionElem \"a\"\n" +
" ��������� LeftJoin (LeftJoinIterator) (resultSizeActual=2)\n" +
" ��������� Join (JoinIterator) (resultSizeActual=2) [left]\n" +
" ��� ��������� StatementPattern (costEstimate=3.00, resultSizeEstimate=4.00, resultSizeActual=4) [left]\n"
+
" ��� ��� s: Var (name=a)\n" +
" ��� ��� p: Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" ��� ��� o: Var (name=d)\n" +
" ��� ��������� Filter (resultSizeActual=2) [right]\n" +
" ��� ��������� Compare (!=)\n" +
" ��� ��� Var (name=c)\n" +
" ��� ��� Var (name=d)\n" +
" ��� ��������� Join (HashJoinIteration) (resultSizeActual=6)\n" +
" ��� ��������� Filter (resultSizeActual=6) [left]\n" +
" ��� ��� ��������� Compare (!=)\n" +
" ��� ��� ��� Var (name=c)\n" +
" ��� ��� ��� ValueConstant (value=\"<\")\n" +
" ��� ��� ��������� StatementPattern (costEstimate=3.00, resultSizeEstimate=4.00, resultSizeActual=6)\n"
+
" ��� ��� s: Var (name=a)\n" +
" ��� ��� p: Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" ��� ��� o: Var (name=c)\n" +
" ��� ��������� LeftJoin (new scope) (BadlyDesignedLeftJoinIterator) (costEstimate=6.61, resultSizeEstimate=12, resultSizeActual=4) [right]\n"
+
" ��� ��������� SingletonSet (resultSizeActual=4) [left]\n" +
" ��� ��������� StatementPattern (resultSizeEstimate=12, resultSizeActual=48) [right]\n" +
" ��� s: Var (name=d)\n" +
" ��� p: Var (name=e)\n" +
" ��� o: Var (name=f)\n" +
" ��������� StatementPattern (resultSizeEstimate=12, resultSizeActual=2) [right]\n" +
" s: Var (name=d)\n" +
" p: Var (name=e)\n" +
" o: Var (name=f)\n";
assertThat(actual).isEqualToNormalizingNewlines(expected);
}
sailRepository.shutDown();
}
@Test
public void testSubQuery2() {
SailRepository sailRepository = new SailRepository(new MemoryStore());
addData(sailRepository);
try (SailRepositoryConnection connection = sailRepository.getConnection()) {
Query query = connection.prepareTupleQuery(SUB_QUERY2);
String actual = query.explain(Explanation.Level.Optimized).toString();
String expected = "Distinct\n" +
" Projection\n" +
" ��������� ProjectionElemList\n" +
" ��� ProjectionElem \"countryID\"\n" +
" ��� ProjectionElem \"year\"\n" +
" ��� ProjectionElem \"amountLots\"\n" +
" ��� ProjectionElem \"numSingleBidders\"\n" +
" ��������� Extension\n" +
" Group (countryID, year)\n" +
" Join (HashJoinIteration)\n" +
" ��������� Extension [left]\n" +
" ��� ��������� Join (JoinIterator)\n" +
" ��� ��� ��������� StatementPattern (costEstimate=0.71, resultSizeEstimate=0) [left]\n" +
" ��� ��� ��� s: Var (name=resultnotice)\n" +
" ��� ��� ��� p: Var (name=_const_183bd06d_uri, value=http://data.europa.eu/a4g/ontology#refersToProcedure, anonymous)\n"
+
" ��� ��� ��� o: Var (name=proc)\n" +
" ��� ��� ��������� Join (JoinIterator) [right]\n" +
" ��� ��� ��������� StatementPattern (costEstimate=1.00, resultSizeEstimate=0) [left]\n" +
" ��� ��� ��� s: Var (name=proc)\n" +
" ��� ��� ��� p: Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" ��� ��� ��� o: Var (name=_const_be18ee7b_uri, value=http://data.europa.eu/a4g/ontology#Procedure, anonymous)\n"
+
" ��� ��� ��������� Join (JoinIterator) [right]\n" +
" ��� ��� ��������� StatementPattern (costEstimate=1.00, resultSizeEstimate=0) [left]\n" +
" ��� ��� ��� s: Var (name=resultnotice)\n" +
" ��� ��� ��� p: Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" ��� ��� ��� o: Var (name=_const_77e914ad_uri, value=http://data.europa.eu/a4g/ontology#ResultNotice, anonymous)\n"
+
" ��� ��� ��������� Join (JoinIterator) [right]\n" +
" ��� ��� ��������� StatementPattern (costEstimate=1.12, resultSizeEstimate=0) [left]\n"
+
" ��� ��� ��� s: Var (name=proc)\n" +
" ��� ��� ��� p: Var (name=_const_9c3f1eec_uri, value=http://data.europa.eu/a4g/ontology#hasProcurementScopeDividedIntoLot, anonymous)\n"
+
" ��� ��� ��� o: Var (name=lot)\n" +
" ��� ��� ��������� Join (JoinIterator) [right]\n" +
" ��� ��� ��������� StatementPattern (costEstimate=0.75, resultSizeEstimate=0) [left]\n"
+
" ��� ��� ��� s: Var (name=stat)\n" +
" ��� ��� ��� p: Var (name=_const_25686184_uri, value=http://data.europa.eu/a4g/ontology#concernsSubmissionsForLot, anonymous)\n"
+
" ��� ��� ��� o: Var (name=lot)\n" +
" ��� ��� ��������� Join (JoinIterator) [right]\n" +
" ��� ��� ��������� StatementPattern (costEstimate=1.00, resultSizeEstimate=0) [left]\n"
+
" ��� ��� ��� s: Var (name=stat)\n" +
" ��� ��� ��� p: Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" ��� ��� ��� o: Var (name=_const_ea79e75_uri, value=http://data.europa.eu/a4g/ontology#SubmissionStatisticalInformation, anonymous)\n"
+
" ��� ��� ��������� Join (JoinIterator) [right]\n" +
" ��� ��� ��������� Filter [left]\n" +
" ��� ��� ��� ��������� Compare (!=)\n" +
" ��� ��� ��� ��� Var (name=p)\n" +
" ��� ��� ��� ��� ValueConstant (value=http://publications.europa.eu/resource/authority/procurement-procedure-type/neg-wo-call)\n"
+
" ��� ��� ��� ��������� StatementPattern (costEstimate=2.24, resultSizeEstimate=0)\n"
+
" ��� ��� ��� s: Var (name=proc)\n" +
" ��� ��� ��� p: Var (name=_const_9c756f6b_uri, value=http://data.europa.eu/a4g/ontology#hasProcedureType, anonymous)\n"
+
" ��� ��� ��� o: Var (name=p)\n" +
" ��� ��� ��������� Join (JoinIterator) [right]\n" +
" ��� ��� ��������� StatementPattern (costEstimate=2.24, resultSizeEstimate=0) [left]\n"
+
" ��� ��� ��� s: Var (name=stat)\n" +
" ��� ��� ��� p: Var (name=_const_98c73a3c_uri, value=http://data.europa.eu/a4g/ontology#hasReceivedTenders, anonymous)\n"
+
" ��� ��� ��� o: Var (name=bidders)\n" +
" ��� ��� ��������� Join (JoinIterator) [right]\n" +
" ��� ��� ��������� StatementPattern (costEstimate=2.24, resultSizeEstimate=0) [left]\n"
+
" ��� ��� ��� s: Var (name=resultnotice)\n" +
" ��� ��� ��� p: Var (name=_const_1b0b00ca_uri, value=http://data.europa.eu/a4g/ontology#hasDispatchDate, anonymous)\n"
+
" ��� ��� ��� o: Var (name=ddate)\n" +
" ��� ��� ��������� StatementPattern (costEstimate=2.24, resultSizeEstimate=0) [right]\n"
+
" ��� ��� s: Var (name=resultnotice)\n" +
" ��� ��� p: Var (name=_const_6aa9a9c_uri, value=http://data.europa.eu/a4g/ontology#refersToRole, anonymous)\n"
+
" ��� ��� o: Var (name=buyerrole)\n" +
" ��� ��������� ExtensionElem (year)\n" +
" ��� FunctionCall (http://www.w3.org/2005/xpath-functions#year-from-dateTime)\n" +
" ��� FunctionCall (http://www.w3.org/2001/XMLSchema#dateTime)\n" +
" ��� Var (name=ddate)\n" +
" ��������� Distinct (new scope) [right]\n" +
" Projection\n" +
" ��������� ProjectionElemList\n" +
" ��� ProjectionElem \"buyerrole\"\n" +
" ��� ProjectionElem \"countryID\"\n" +
" ��������� Join (JoinIterator)\n" +
" ��������� StatementPattern (costEstimate=1.25, resultSizeEstimate=0) [left]\n" +
" ��� s: Var (name=org)\n" +
" ��� p: Var (name=_const_beb18915_uri, value=https://www.w3.org/ns/legal#registeredAddress, anonymous)\n"
+
" ��� o: Var (name=orgaddress)\n" +
" ��������� Join (JoinIterator) [right]\n" +
" ��������� StatementPattern (costEstimate=1.12, resultSizeEstimate=0) [left]\n" +
" ��� s: Var (name=orgaddress)\n" +
" ��� p: Var (name=_const_2f7de0e1_uri, value=http://data.europa.eu/a4g/ontology#hasCountryCode, anonymous)\n"
+
" ��� o: Var (name=countrycode)\n" +
" ��������� Join (JoinIterator) [right]\n" +
" ��������� Filter [left]\n" +
" ��� ��������� Compare (!=)\n" +
" ��� ��� Var (name=buytype)\n" +
" ��� ��� ValueConstant (value=http://publications.europa.eu/resource/authority/buyer-legal-type/eu-int-org)\n"
+
" ��� ��������� StatementPattern (costEstimate=2.24, resultSizeEstimate=0)\n" +
" ��� s: Var (name=org)\n" +
" ��� p: Var (name=_const_1abd8d4b_uri, value=http://data.europa.eu/a4g/ontology#hasBuyerType, anonymous)\n"
+
" ��� o: Var (name=buytype)\n" +
" ��������� Join (JoinIterator) [right]\n" +
" ��������� StatementPattern (costEstimate=2.24, resultSizeEstimate=0) [left]\n"
+
" ��� s: Var (name=buyerrole)\n" +
" ��� p: Var (name=_const_beb855c2_uri, value=http://data.europa.eu/a4g/ontology#playedBy, anonymous)\n"
+
" ��� o: Var (name=org)\n" +
" ��������� StatementPattern (costEstimate=2.24, resultSizeEstimate=0) [right]\n"
+
" s: Var (name=countrycode)\n" +
" p: Var (name=_const_a825a5f4_uri, value=http://purl.org/dc/elements/1.1/identifier, anonymous)\n"
+
" o: Var (name=countryID)\n" +
" GroupElem (amountLots)\n" +
" Count (Distinct)\n" +
" Var (name=lot)\n" +
" GroupElem (numSingleBidders)\n" +
" Sum\n" +
" If\n" +
" Compare (=)\n" +
" Var (name=bidders)\n" +
" ValueConstant (value=\"1\"^^<http://www.w3.org/2001/XMLSchema#integer>)\n"
+
" ValueConstant (value=\"1\"^^<http://www.w3.org/2001/XMLSchema#integer>)\n" +
" ValueConstant (value=\"0\"^^<http://www.w3.org/2001/XMLSchema#integer>)\n" +
" ExtensionElem (amountLots)\n" +
" Count (Distinct)\n" +
" Var (name=lot)\n" +
" ExtensionElem (numSingleBidders)\n" +
" Sum\n" +
" If\n" +
" Compare (=)\n" +
" Var (name=bidders)\n" +
" ValueConstant (value=\"1\"^^<http://www.w3.org/2001/XMLSchema#integer>)\n" +
" ValueConstant (value=\"1\"^^<http://www.w3.org/2001/XMLSchema#integer>)\n" +
" ValueConstant (value=\"0\"^^<http://www.w3.org/2001/XMLSchema#integer>)\n";
assertThat(actual).isEqualToNormalizingNewlines(expected);
}
sailRepository.shutDown();
}
@Test
public void testUnionQuery() {
SailRepository sailRepository = new SailRepository(new MemoryStore());
addData(sailRepository);
try (SailRepositoryConnection connection = sailRepository.getConnection()) {
Query query = connection.prepareTupleQuery(UNION_QUERY);
String actual = query.explain(Explanation.Level.Executed).toString();
String expected = "Projection (resultSizeActual=24)\n" +
"��������� ProjectionElemList\n" +
"��� ProjectionElem \"a\"\n" +
"��������� Join (JoinIterator) (resultSizeActual=24)\n" +
" ��������� StatementPattern (costEstimate=3.00, resultSizeEstimate=4.00, resultSizeActual=4) [left]\n"
+
" ��� s: Var (name=a)\n" +
" ��� p: Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" ��� o: Var (name=type)\n" +
" ��������� Union (resultSizeActual=24) [right]\n" +
" ��������� Join (JoinIterator) (resultSizeActual=20)\n" +
" ��� ��������� StatementPattern (costEstimate=2.20, resultSizeEstimate=12, resultSizeActual=6) [left]\n"
+
" ��� ��� s: Var (name=a)\n" +
" ��� ��� p: Var (name=b)\n" +
" ��� ��� o: Var (name=c2)\n" +
" ��� ��������� Join (JoinIterator) (resultSizeActual=20) [right]\n" +
" ��� ��������� StatementPattern (costEstimate=2.57, resultSizeEstimate=12, resultSizeActual=10) [left]\n"
+
" ��� ��� s: Var (name=a)\n" +
" ��� ��� p: Var (name=b)\n" +
" ��� ��� o: Var (name=c)\n" +
" ��� ��������� Union (resultSizeActual=20) [right]\n" +
" ��� ��������� StatementPattern (new scope) (costEstimate=3.00, resultSizeEstimate=4.00, resultSizeActual=10)\n"
+
" ��� ��� s: Var (name=c2)\n" +
" ��� ��� p: Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" ��� ��� o: Var (name=type1)\n" +
" ��� ��������� StatementPattern (new scope) (costEstimate=3.00, resultSizeEstimate=4.00, resultSizeActual=10)\n"
+
" ��� s: Var (name=c2)\n" +
" ��� p: Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" ��� o: Var (name=type2)\n" +
" ��������� StatementPattern (new scope) (costEstimate=6.61, resultSizeEstimate=12, resultSizeActual=4)\n"
+
" s: Var (name=type)\n" +
" p: Var (name=d)\n" +
" o: Var (name=c)\n";
assertThat(actual).isEqualToNormalizingNewlines(expected);
}
sailRepository.shutDown();
}
@Test
public void testTimeout() {
SailRepository sailRepository = new SailRepository(new MemoryStore());
try (SailRepositoryConnection connection = sailRepository.getConnection()) {
connection.begin();
for (int i = 0; i < 1000; i++) {
connection.add(vf.createBNode(i + ""), RDF.TYPE, vf.createBNode((i + 1) + ""));
connection.add(vf.createBNode(i + ""), RDF.TYPE, vf.createBNode((i - 1) + ""));
connection.add(vf.createBNode(i + ""), RDF.TYPE, vf.createBNode((i + 2) + ""));
connection.add(vf.createBNode(i + ""), RDF.TYPE, vf.createBNode((i - 2) + ""));
}
connection.commit();
}
try (SailRepositoryConnection connection = sailRepository.getConnection()) {
Query query = connection.prepareTupleQuery(String.join("\n", "",
"select * where {",
" ?a (a|^a)* ?type. ",
" FILTER NOT EXISTS{?a (a|^a)* ?type} ",
" FILTER NOT EXISTS{?a (a|^a)* ?type} ",
" FILTER NOT EXISTS{?a (a|^a)* ?type} ",
" FILTER NOT EXISTS{?a (a|^a)* ?type}",
" FILTER NOT EXISTS{?a (a|^a)* ?type}",
" FILTER NOT EXISTS{?a (a|^a)* ?type}",
" FILTER NOT EXISTS{?a (a|^a)* ?type}",
" FILTER NOT EXISTS{?a (a|^a)* ?type}",
"}"));
query.setMaxExecutionTime(1);
String actual = query.explain(Explanation.Level.Timed).toString();
assertThat(actual).contains("Timed out");
}
sailRepository.shutDown();
}
@Test
public void testDot() {
SailRepository sailRepository = new SailRepository(new MemoryStore());
addData(sailRepository);
try (SailRepositoryConnection connection = sailRepository.getConnection()) {
Query query = connection.prepareTupleQuery(TUPLE_QUERY);
Explanation explain = query.explain(Explanation.Level.Optimized);
String actual = explain.toDot();
actual = actual.replaceAll("UUID_\\w+", "UUID");
String expected = "digraph Explanation {\n" +
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>Projection</U></td></tr></table>> shape=plaintext];\n"
+
" UUID -> UUID [label=\"left\"] ;\n" +
" UUID -> UUID [label=\"right\"] ;\n" +
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>ProjectionElemList</U></td></tr></table>> shape=plaintext];\n"
+
" UUID -> UUID [label=\"\"] ;\n" +
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>ProjectionElem "a"</U></td></tr></table>> shape=plaintext];\n"
+
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>LeftJoin</U></td></tr> <tr><td>Algorithm</td><td>LeftJoinIterator</td></tr></table>> shape=plaintext];\n"
+
" UUID -> UUID [label=\"left\"] ;\n" +
" UUID -> UUID [label=\"right\"] ;\n" +
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>Join</U></td></tr> <tr><td>Algorithm</td><td>JoinIterator</td></tr></table>> shape=plaintext];\n"
+
" UUID -> UUID [label=\"left\"] ;\n" +
" UUID -> UUID [label=\"right\"] ;\n" +
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>StatementPattern</U></td></tr> <tr><td>Cost estimate</td><td>3.00</td></tr> <tr><td>Result size estimate</td><td>4.00</td></tr></table>> shape=plaintext];\n"
+
" UUID -> UUID [label=\"index 0\"] ;\n" +
" UUID -> UUID [label=\"index 1\"] ;\n" +
" UUID -> UUID [label=\"index 2\"] ;\n" +
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>Var (name=a)</U></td></tr></table>> shape=plaintext];\n"
+
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)</U></td></tr></table>> shape=plaintext];\n"
+
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>Var (name=d)</U></td></tr></table>> shape=plaintext];\n"
+
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>Filter</U></td></tr></table>> shape=plaintext];\n"
+
" UUID -> UUID [label=\"left\"] ;\n" +
" UUID -> UUID [label=\"right\"] ;\n" +
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>Compare (!=)</U></td></tr></table>> shape=plaintext];\n"
+
" UUID -> UUID [label=\"left\"] ;\n" +
" UUID -> UUID [label=\"right\"] ;\n" +
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>Var (name=c)</U></td></tr></table>> shape=plaintext];\n"
+
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>Var (name=d)</U></td></tr></table>> shape=plaintext];\n"
+
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>Join</U></td></tr> <tr><td>Algorithm</td><td>HashJoinIteration</td></tr></table>> shape=plaintext];\n"
+
" UUID -> UUID [label=\"left\"] ;\n" +
" UUID -> UUID [label=\"right\"] ;\n" +
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>Filter</U></td></tr></table>> shape=plaintext];\n"
+
" UUID -> UUID [label=\"left\"] ;\n" +
" UUID -> UUID [label=\"right\"] ;\n" +
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>Compare (!=)</U></td></tr></table>> shape=plaintext];\n"
+
" UUID -> UUID [label=\"left\"] ;\n" +
" UUID -> UUID [label=\"right\"] ;\n" +
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>Var (name=c)</U></td></tr></table>> shape=plaintext];\n"
+
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>ValueConstant (value="<")</U></td></tr></table>> shape=plaintext];\n"
+
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>StatementPattern</U></td></tr> <tr><td>Cost estimate</td><td>3.00</td></tr> <tr><td>Result size estimate</td><td>4.00</td></tr></table>> shape=plaintext];\n"
+
" UUID -> UUID [label=\"index 0\"] ;\n" +
" UUID -> UUID [label=\"index 1\"] ;\n" +
" UUID -> UUID [label=\"index 2\"] ;\n" +
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>Var (name=a)</U></td></tr></table>> shape=plaintext];\n"
+
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)</U></td></tr></table>> shape=plaintext];\n"
+
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>Var (name=c)</U></td></tr></table>> shape=plaintext];\n"
+
" subgraph cluster_UUID {\n" +
" color=grey\n" +
"UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>LeftJoin</U></td></tr> <tr><td><B>New scope</B></td><td><B>true</B></td></tr> <tr><td>Cost estimate</td><td>6.61</td></tr> <tr><td>Result size estimate</td><td>12</td></tr></table>> shape=plaintext];\n"
+
" UUID -> UUID [label=\"left\"] ;\n" +
" UUID -> UUID [label=\"right\"] ;\n" +
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>SingletonSet</U></td></tr></table>> shape=plaintext];\n"
+
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>StatementPattern</U></td></tr> <tr><td>Result size estimate</td><td>12</td></tr></table>> shape=plaintext];\n"
+
" UUID -> UUID [label=\"index 0\"] ;\n" +
" UUID -> UUID [label=\"index 1\"] ;\n" +
" UUID -> UUID [label=\"index 2\"] ;\n" +
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>Var (name=d)</U></td></tr></table>> shape=plaintext];\n"
+
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>Var (name=e)</U></td></tr></table>> shape=plaintext];\n"
+
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>Var (name=f)</U></td></tr></table>> shape=plaintext];\n"
+
"\n" +
"}\n" +
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>StatementPattern</U></td></tr> <tr><td>Result size estimate</td><td>12</td></tr></table>> shape=plaintext];\n"
+
" UUID -> UUID [label=\"index 0\"] ;\n" +
" UUID -> UUID [label=\"index 1\"] ;\n" +
" UUID -> UUID [label=\"index 2\"] ;\n" +
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>Var (name=d)</U></td></tr></table>> shape=plaintext];\n"
+
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>Var (name=e)</U></td></tr></table>> shape=plaintext];\n"
+
" UUID [label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"#FFFFFF\"><U>Var (name=f)</U></td></tr></table>> shape=plaintext];\n"
+
"\n" +
"}\n";
assertThat(actual).isEqualToNormalizingNewlines(expected);
}
sailRepository.shutDown();
}
@Test
public void testDotTimed() {
SailRepository sailRepository = new SailRepository(new MemoryStore());
addData(sailRepository);
try (SailRepositoryConnection connection = sailRepository.getConnection()) {
Query query = connection.prepareTupleQuery(SUB_QUERY);
Explanation explain = query.explain(Explanation.Level.Timed);
String actual = explain.toDot();
actual = actual.replaceAll("UUID_\\w+", "UUID");
assertThat(actual).startsWith("digraph Explanation {");
assertThat(actual).contains(
"[label=<<table BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\" CELLPADDING=\"3\" ><tr><td COLSPAN=\"2\" BGCOLOR=\"");
assertThat(actual).contains("Total time actual</td><td BGCOLOR=");
assertThat(actual).contains("Self time actual</td><td BGCOLOR=\"");
assertThat(actual).contains("ms</td>");
assertThat(actual).contains("<U>Projection</U>");
assertThat(actual).contains("<U>ProjectionElemList</U>");
assertThat(actual).contains("<U>Join</U>");
}
sailRepository.shutDown();
}
@Test
public void testWildcard() {
String expected = "StatementPattern (resultSizeEstimate=12)\n" +
" s: Var (name=a)\n" +
" p: Var (name=b)\n" +
" o: Var (name=c)\n";
SailRepository sailRepository = new SailRepository(new MemoryStore());
addData(sailRepository);
try (SailRepositoryConnection connection = sailRepository.getConnection()) {
TupleQuery query = connection.prepareTupleQuery("select * where {?a ?b ?c.}");
String actual = query.explain(Explanation.Level.Optimized).toString();
assertThat(actual).isEqualToNormalizingNewlines(expected);
}
sailRepository.shutDown();
}
@Test
public void testArbitraryLengthPath() {
String expected = "Projection\n" +
"��������� ProjectionElemList\n" +
"��� ProjectionElem \"a\"\n" +
"��� ProjectionElem \"b\"\n" +
"��� ProjectionElem \"c\"\n" +
"��� ProjectionElem \"d\"\n" +
"��������� Join (JoinIterator)\n" +
" ��������� StatementPattern (costEstimate=8.50, resultSizeEstimate=12) [left]\n" +
" ��� s: Var (name=a)\n" +
" ��� p: Var (name=b)\n" +
" ��� o: Var (name=c)\n" +
" ��������� ArbitraryLengthPath (costEstimate=5.39, resultSizeEstimate=24) [right]\n" +
" Var (name=c)\n" +
" StatementPattern (resultSizeEstimate=0)\n" +
" s: Var (name=c)\n" +
" p: Var (name=_const_f804988f_uri, value=http://a, anonymous)\n" +
" o: Var (name=d)\n" +
" Var (name=d)\n";
SailRepository sailRepository = new SailRepository(new MemoryStore());
addData(sailRepository);
try (SailRepositoryConnection connection = sailRepository.getConnection()) {
TupleQuery query = connection.prepareTupleQuery("select * where {?a ?b ?c. ?c <http://a>* ?d}");
String actual = query.explain(Explanation.Level.Optimized).toString();
assertThat(actual).isEqualToNormalizingNewlines(expected);
}
sailRepository.shutDown();
}
@Test
public void testHaving() {
String expected = "Order (resultSizeActual=4)\n" +
" OrderElem (ASC)\n" +
" Var (name=nbTerm)\n" +
" OrderElem (ASC)\n" +
" Var (name=nameSjb1)\n" +
" OrderElem (ASC)\n" +
" Var (name=idTerm3)\n" +
" Projection (resultSizeActual=4)\n" +
" ��������� ProjectionElemList\n" +
" ��� ProjectionElem \"nameSjb1\"\n" +
" ��� ProjectionElem \"idCN1\"\n" +
" ��� ProjectionElem \"nbTerm\"\n" +
" ��� ProjectionElem \"idTerm3\"\n" +
" ��������� Join (JoinIterator) (resultSizeActual=4)\n" +
" ��������� Projection (new scope) (resultSizeActual=2) [left]\n" +
" ��� ��������� ProjectionElemList\n" +
" ��� ��� ProjectionElem \"nameSjb1\"\n" +
" ��� ��� ProjectionElem \"idCN1\"\n" +
" ��� ��� ProjectionElem \"nbTerm\"\n" +
" ��� ��������� Extension (resultSizeActual=2)\n" +
" ��� ��������� Extension (resultSizeActual=2)\n" +
" ��� ��� Filter (resultSizeActual=2)\n" +
" ��� ��� ��������� Compare (<)\n" +
" ��� ��� ��� Var (name=nbTerm)\n" +
" ��� ��� ��� ValueConstant (value=\"3\"^^<http://www.w3.org/2001/XMLSchema#integer>)\n" +
" ��� ��� ��������� Group (nameSjb1, idCN1) (resultSizeActual=4)\n" +
" ��� ��� ��������� LeftJoin (LeftJoinIterator) (resultSizeActual=11)\n" +
" ��� ��� ��� ��������� Join (JoinIterator) (resultSizeActual=11) [left]\n" +
" ��� ��� ��� ��� ��������� StatementPattern (costEstimate=54, resultSizeEstimate=4.00, resultSizeActual=4) [left]\n"
+
" ��� ��� ��� ��� ��� s: Var (name=idTerm1)\n" +
" ��� ��� ��� ��� ��� p: Var (name=_const_c6e40399_uri, value=http://iec.ch/TC57/2013/CIM-schema-cim16#Terminal.ConductingEquipment, anonymous)\n"
+
" ��� ��� ��� ��� ��� o: Var (name=idSjb1)\n" +
" ��� ��� ��� ��� ��������� Join (JoinIterator) (resultSizeActual=11) [right]\n" +
" ��� ��� ��� ��� ��������� StatementPattern (costEstimate=1.00, resultSizeEstimate=4.00, resultSizeActual=4) [left]\n"
+
" ��� ��� ��� ��� ��� s: Var (name=idSjb1)\n" +
" ��� ��� ��� ��� ��� p: Var (name=_const_f5e5585a_uri, value=http://www.w3.org/1999/02/22-rdf-syntax-ns#type, anonymous)\n"
+
" ��� ��� ��� ��� ��� o: Var (name=_const_6965b017_uri, value=http://iec.ch/TC57/2013/CIM-schema-cim16#BusbarSection, anonymous)\n"
+
" ��� ��� ��� ��� ��������� Join (JoinIterator) (resultSizeActual=11) [right]\n" +
" ��� ��� ��� ��� ��������� StatementPattern (costEstimate=2.12, resultSizeEstimate=13, resultSizeActual=4) [left]\n"
+
" ��� ��� ��� ��� ��� s: Var (name=idTerm1)\n" +
" ��� ��� ��� ��� ��� p: Var (name=_const_4395d870_uri, value=http://iec.ch/TC57/2013/CIM-schema-cim16#Terminal.ConnectivityNode, anonymous)\n"
+
" ��� ��� ��� ��� ��� o: Var (name=idCN1)\n" +
" ��� ��� ��� ��� ��������� StatementPattern (costEstimate=4.24, resultSizeEstimate=13, resultSizeActual=11) [right]\n"
+
" ��� ��� ��� ��� s: Var (name=idTermOfCN)\n" +
" ��� ��� ��� ��� p: Var (name=_const_4395d870_uri, value=http://iec.ch/TC57/2013/CIM-schema-cim16#Terminal.ConnectivityNode, anonymous)\n"
+
" ��� ��� ��� ��� o: Var (name=idCN1)\n" +
" ��� ��� ��� ��������� StatementPattern (resultSizeEstimate=4.00, resultSizeActual=11) [right]\n"
+
" ��� ��� ��� s: Var (name=idSjb1)\n" +
" ��� ��� ��� p: Var (name=_const_857da984_uri, value=http://iec.ch/TC57/2013/CIM-schema-cim16#IdentifiedObject.name, anonymous)\n"
+
" ��� ��� ��� o: Var (name=nameSjb1)\n" +
" ��� ��� ��������� GroupElem (nbTerm)\n" +
" ��� ��� Count\n" +
" ��� ��� Var (name=idTermOfCN)\n" +
" ��� ��������� ExtensionElem (nbTerm)\n" +
" ��� Count\n" +
" ��� Var (name=idTermOfCN)\n" +
" ��������� StatementPattern (costEstimate=18, resultSizeEstimate=13, resultSizeActual=4) [right]\n" +
" s: Var (name=idTerm3)\n" +
" p: Var (name=_const_4395d870_uri, value=http://iec.ch/TC57/2013/CIM-schema-cim16#Terminal.ConnectivityNode, anonymous)\n"
+
" o: Var (name=idCN1)\n";
SailRepository sailRepository = new SailRepository(new MemoryStore());
try (SailRepositoryConnection connection = sailRepository.getConnection()) {
connection.add(new StringReader("@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n" +
"@prefix cim: <http://iec.ch/TC57/2013/CIM-schema-cim16#> .\n" +
"@prefix : <http://example.org/> .\n" +
"\n" +
"# Busbar Sections\n" +
":BusbarSection1 rdf:type cim:BusbarSection ;\n" +
" cim:IdentifiedObject.name \"Busbar1\" .\n" +
"\n" +
":BusbarSection2 rdf:type cim:BusbarSection ;\n" +
" cim:IdentifiedObject.name \"Busbar2\" .\n" +
"\n" +
":BusbarSection3 rdf:type cim:BusbarSection ;\n" +
" cim:IdentifiedObject.name \"Busbar3\" .\n" +
"\n" +
":BusbarSection4 rdf:type cim:BusbarSection ;\n" +
" cim:IdentifiedObject.name \"Busbar4\" .\n" +
"\n" +
"# Connectivity Nodes\n" +
":ConnectivityNode1 a cim:ConnectivityNode .\n" +
":ConnectivityNode2 a cim:ConnectivityNode .\n" +
":ConnectivityNode3 a cim:ConnectivityNode .\n" +
":ConnectivityNode4 a cim:ConnectivityNode .\n" +
":ConnectivityNode5 a cim:ConnectivityNode .\n" +
":ConnectivityNode6 a cim:ConnectivityNode .\n" +
"\n" +
"# Terminals connected to ConnectivityNode1 (3 terminals)\n" +
":Terminal1 cim:Terminal.ConductingEquipment :BusbarSection1 ;\n" +
" cim:Terminal.ConnectivityNode :ConnectivityNode1 .\n" +
"\n" +
":Terminal2 cim:Terminal.ConnectivityNode :ConnectivityNode1 .\n" +
":Terminal3 cim:Terminal.ConnectivityNode :ConnectivityNode1 .\n" +
"\n" +
"# Terminals connected to ConnectivityNode2 (2 terminals)\n" +
":Terminal4 cim:Terminal.ConductingEquipment :BusbarSection2 ;\n" +
" cim:Terminal.ConnectivityNode :ConnectivityNode2 .\n" +
"\n" +
":Terminal5 cim:Terminal.ConnectivityNode :ConnectivityNode2 .\n" +
"\n" +
"# Terminal connected to ConnectivityNode3 (1 terminal)\n" +
":Terminal6 cim:Terminal.ConnectivityNode :ConnectivityNode3 .\n" +
"\n" +
"# Terminals connected to ConnectivityNode4 (4 terminals)\n" +
":Terminal7 cim:Terminal.ConductingEquipment :BusbarSection3 ;\n" +
" cim:Terminal.ConnectivityNode :ConnectivityNode4 .\n" +
"\n" +
":Terminal8 cim:Terminal.ConnectivityNode :ConnectivityNode4 .\n" +
":Terminal9 cim:Terminal.ConnectivityNode :ConnectivityNode4 .\n" +
":Terminal10 cim:Terminal.ConnectivityNode :ConnectivityNode4 .\n" +
"\n" +
"# Terminals connected to ConnectivityNode5 (2 terminals)\n" +
":Terminal11 cim:Terminal.ConductingEquipment :BusbarSection4 ;\n" +
" cim:Terminal.ConnectivityNode :ConnectivityNode5 .\n" +
"\n" +
":Terminal12 cim:Terminal.ConnectivityNode :ConnectivityNode5 .\n" +
"\n" +
"# Terminal connected to ConnectivityNode6 (1 terminal)\n" +
":Terminal13 cim:Terminal.ConnectivityNode :ConnectivityNode6 ."), "", RDFFormat.TURTLE);
} catch (IOException e) {
throw new RuntimeException(e);
}
try (SailRepositoryConnection connection = sailRepository.getConnection()) {
TupleQuery query = connection.prepareTupleQuery(
"PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\n" +
"PREFIX cim: <http://iec.ch/TC57/2013/CIM-schema-cim16#>\n" +
"" +
"select ?nameSjb1 ?idCN1 ?nbTerm ?idTerm3\n" +
"where {\n" +
" {\n" +
" select ?nameSjb1 ?idCN1 (count(?idTermOfCN) as ?nbTerm)\n" +
" where {\n" +
" ?idSjb1 rdf:type cim:BusbarSection .\n" +
" ?idTerm1 cim:Terminal.ConductingEquipment ?idSjb1 .\n" +
" ?idTerm1 cim:Terminal.ConnectivityNode ?idCN1 .\n" +
" ?idTermOfCN cim:Terminal.ConnectivityNode ?idCN1\n" +
" OPTIONAL { ?idSjb1 cim:IdentifiedObject.name ?nameSjb1 . }\n" +
" }\n" +
" group by ?nameSjb1 ?idCN1\n" +
" having (?nbTerm < 3)\n" +
" }\n" +
" ?idTerm3 cim:Terminal.ConnectivityNode ?idCN1\n" +
"}\n" +
"order by ?nbTerm ?nameSjb1 ?idTerm3");
String actual = query.explain(Explanation.Level.Executed).toString();
assertThat(actual).isEqualToNormalizingNewlines(expected);
}
sailRepository.shutDown();
}
}