You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rya.apache.org by pu...@apache.org on 2016/09/27 14:58:53 UTC
incubator-rya git commit: RYA-153 Fixed JoinPCJMatcher bug. Closes
#82 meiercaleb/RYA-153.
Repository: incubator-rya
Updated Branches:
refs/heads/master 9bdecc9ed -> db281030c
RYA-153 Fixed JoinPCJMatcher bug. Closes #82 meiercaleb/RYA-153.
Project: http://git-wip-us.apache.org/repos/asf/incubator-rya/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-rya/commit/db281030
Tree: http://git-wip-us.apache.org/repos/asf/incubator-rya/tree/db281030
Diff: http://git-wip-us.apache.org/repos/asf/incubator-rya/diff/db281030
Branch: refs/heads/master
Commit: db281030c08294aa08720f30d5b7d3ddbbe1f580
Parents: 9bdecc9
Author: Caleb Meier <me...@gmail.com>
Authored: Mon Aug 15 13:05:47 2016 -0400
Committer: pujav65 <pu...@gmail.com>
Committed: Tue Sep 27 10:56:58 2016 -0400
----------------------------------------------------------------------
.../pcj/matching/JoinSegmentPCJMatcher.java | 5 +
.../pcj/matching/PCJOptimizerUtilities.java | 31 +
.../indexing/pcj/matching/PCJOptimizerTest.java | 950 ++++++++++---------
3 files changed, 540 insertions(+), 446 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/db281030/extras/indexing/src/main/java/mvm/rya/indexing/pcj/matching/JoinSegmentPCJMatcher.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/mvm/rya/indexing/pcj/matching/JoinSegmentPCJMatcher.java b/extras/indexing/src/main/java/mvm/rya/indexing/pcj/matching/JoinSegmentPCJMatcher.java
index 29c4188..a74abec 100644
--- a/extras/indexing/src/main/java/mvm/rya/indexing/pcj/matching/JoinSegmentPCJMatcher.java
+++ b/extras/indexing/src/main/java/mvm/rya/indexing/pcj/matching/JoinSegmentPCJMatcher.java
@@ -60,6 +60,11 @@ public class JoinSegmentPCJMatcher extends AbstractPCJMatcher {
*/
@Override
public boolean matchPCJ(QuerySegment pcjNodes, ExternalTupleSet pcj) {
+
+ if(PCJOptimizerUtilities.pcjContainsLeftJoins(pcj)) {
+ return false;
+ }
+
boolean nodesReplaced = segment.replaceWithPcj(pcjNodes, pcj);
if (nodesReplaced) {
tupleAndNodesUpToDate = false;
http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/db281030/extras/indexing/src/main/java/mvm/rya/indexing/pcj/matching/PCJOptimizerUtilities.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/main/java/mvm/rya/indexing/pcj/matching/PCJOptimizerUtilities.java b/extras/indexing/src/main/java/mvm/rya/indexing/pcj/matching/PCJOptimizerUtilities.java
index 485e466..757fb40 100644
--- a/extras/indexing/src/main/java/mvm/rya/indexing/pcj/matching/PCJOptimizerUtilities.java
+++ b/extras/indexing/src/main/java/mvm/rya/indexing/pcj/matching/PCJOptimizerUtilities.java
@@ -343,4 +343,35 @@ public class PCJOptimizerUtilities {
}
}
+
+
+ public static boolean pcjContainsLeftJoins(ExternalTupleSet pcj) {
+ LeftJoinVisitor lj = new LeftJoinVisitor();
+ pcj.getTupleExpr().visit(lj);
+ return lj.containsLeftJoin;
+ }
+
+ protected static class LeftJoinVisitor extends QueryModelVisitorBase<RuntimeException> {
+
+ boolean containsLeftJoin = false;
+
+ public boolean containsLeftJoin() {
+ return containsLeftJoin;
+ }
+
+ @Override
+ public void meet(LeftJoin node) {
+ containsLeftJoin = true;
+ }
+ }
+
+
+
+
+
+
+
+
+
+
}
http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/db281030/extras/indexing/src/test/java/mvm/rya/indexing/pcj/matching/PCJOptimizerTest.java
----------------------------------------------------------------------
diff --git a/extras/indexing/src/test/java/mvm/rya/indexing/pcj/matching/PCJOptimizerTest.java b/extras/indexing/src/test/java/mvm/rya/indexing/pcj/matching/PCJOptimizerTest.java
index b1c0d0d..90c54d3 100644
--- a/extras/indexing/src/test/java/mvm/rya/indexing/pcj/matching/PCJOptimizerTest.java
+++ b/extras/indexing/src/test/java/mvm/rya/indexing/pcj/matching/PCJOptimizerTest.java
@@ -1,4 +1,5 @@
package mvm.rya.indexing.pcj.matching;
+
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -7,9 +8,9 @@ package mvm.rya.indexing.pcj.matching;
* 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
@@ -18,463 +19,520 @@ package mvm.rya.indexing.pcj.matching;
* under the License.
*/
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
+import mvm.rya.indexing.IndexPlanValidator.IndexedExecutionPlanGenerator;
import mvm.rya.indexing.external.tupleSet.ExternalTupleSet;
import mvm.rya.indexing.external.tupleSet.SimpleExternalTupleSet;
+import org.junit.Assert;
import org.junit.Test;
import org.openrdf.query.MalformedQueryException;
import org.openrdf.query.algebra.Projection;
+import org.openrdf.query.algebra.QueryModelNode;
+import org.openrdf.query.algebra.StatementPattern;
import org.openrdf.query.algebra.TupleExpr;
+import org.openrdf.query.algebra.helpers.QueryModelVisitorBase;
import org.openrdf.query.parser.ParsedQuery;
import org.openrdf.query.parser.sparql.SPARQLParser;
+import com.google.common.collect.Sets;
+
public class PCJOptimizerTest {
- @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 ?a ?b ?m" //
- + "{" //
- + " ?a a ?b . "//
- + " OPTIONAL {?a <uri:talksTo> ?m} . "//
- + "}";//
-
- SPARQLParser parser = new SPARQLParser();
- ParsedQuery pq1 = parser.parseQuery(query1, null);
- ParsedQuery pq2 = parser.parseQuery(query2, null);
- TupleExpr te1 = pq1.getTupleExpr();
- TupleExpr te2 = pq2.getTupleExpr();
-
- SimpleExternalTupleSet pcj = new SimpleExternalTupleSet(
- (Projection) te2);
- List<ExternalTupleSet> externalList = new ArrayList<>();
- externalList.add(pcj);
-
- PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
- optimizer.optimize(te1, null, null);
- System.out.println(te1);
-
- // Assert.assertEquals(true, jsm.matchPCJ(pcj));
- // TupleExpr te = jsm.getQuery();
- // Assert.assertEquals(new HashSet<QueryModelNode>(),
- // jsm.getUnmatchedArgs());
- //
- // 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 testSegmentWithUnion() throws MalformedQueryException {
-
- String query1 = ""//
- + "SELECT ?e ?c ?l" //
- + "{" //
- + " {?e <uri:p1> <uri:o1>. } UNION { ?e a ?c. OPTIONAL {?e <uri:talksTo> ?l}. ?e <uri:p5> <uri:o4>. ?e <uri:p4> <uri:o3> } . "//
- + " ?e <uri:p2> ?c . "//
- + " ?e <uri:p3> <uri:o2> . "//
- + "}";//
-
- String query2 = ""//
- + "SELECT ?a ?b ?m" //
- + "{" //
- + " ?a <uri:p5> <uri:o4> ." //
- + " ?a <uri:p4> <uri:o3> ." //
- + " OPTIONAL {?a <uri:talksTo> ?m} . "//
- + " ?a a ?b . "//
- + "}";//
-
- String query3 = ""//
- + "SELECT ?h ?i" //
- + "{" //
- + " ?h <uri:p2> ?i . "//
- + " ?h <uri:p3> <uri:o2> . "//
- + "}";//
-
- SPARQLParser parser = new SPARQLParser();
- ParsedQuery pq1 = parser.parseQuery(query1, null);
- ParsedQuery pq2 = parser.parseQuery(query2, null);
- ParsedQuery pq3 = parser.parseQuery(query3, null);
- TupleExpr te1 = pq1.getTupleExpr();
- TupleExpr te2 = pq2.getTupleExpr();
- TupleExpr te3 = pq3.getTupleExpr();
-
- SimpleExternalTupleSet pcj1 = new SimpleExternalTupleSet(
- (Projection) te2);
- SimpleExternalTupleSet pcj2 = new SimpleExternalTupleSet(
- (Projection) te3);
- List<ExternalTupleSet> externalList = new ArrayList<>();
- externalList.add(pcj1);
- externalList.add(pcj2);
-
- PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
- optimizer.optimize(te1, null, null);
- System.out.println(te1);
-
- // Assert.assertEquals(true, jsm.matchPCJ(pcj));
- // TupleExpr te = jsm.getQuery();
- // Assert.assertEquals(new HashSet<QueryModelNode>(),
- // jsm.getUnmatchedArgs());
- //
- // 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 testExactMatchLargeReOrdered() throws Exception {
-
- String query1 = ""//
- + "SELECT ?a ?b ?c ?d ?e ?f ?g ?h" //
- + "{" //
- + " ?a <uri:p0> ?b ." //
- + " OPTIONAL{?b <uri:p2> ?c. ?c <uri:p1> ?d} . " //
- + " OPTIONAL{?b <uri:p3> ?e. ?e <uri:p1> ?f} . "//
- + " OPTIONAL{?b <uri:p4> ?g. ?g <uri:p1> ?h} . "//
- + " OPTIONAL{?b <uri:p4> ?i. ?i <uri:p1> ?j} . "//
- + " OPTIONAL{?b <uri:p4> ?k. ?k <uri:p1> ?l} . "//
- + " OPTIONAL{?b <uri:p4> ?m. ?m <uri:p1> ?n} . "//
- + " OPTIONAL{?b <uri:p4> ?o. ?o <uri:p1> ?p} . "//
- + "}";//
-
- String query2 = ""//
- + "SELECT ?a ?b ?c ?d ?e ?f ?g ?h" //
- + "{" //
- + " ?a <uri:p0> ?b ." //
- + " OPTIONAL{?b <uri:p4> ?o. ?o <uri:p1> ?p} . "//
- + " OPTIONAL{?b <uri:p4> ?g. ?g <uri:p1> ?h} . "//
- + " OPTIONAL{?b <uri:p2> ?c. ?c <uri:p1> ?d} . " //
- + " OPTIONAL{?b <uri:p4> ?i. ?i <uri:p1> ?j} . "//
- + " OPTIONAL{?b <uri:p4> ?m. ?m <uri:p1> ?n} . "//
- + " OPTIONAL{?b <uri:p4> ?k. ?k <uri:p1> ?l} . "//
- + " OPTIONAL{?b <uri:p3> ?e. ?e <uri:p1> ?f} . "//
- + "}";//
-
- SPARQLParser parser = new SPARQLParser();
- ParsedQuery pq1 = parser.parseQuery(query1, null);
- ParsedQuery pq2 = parser.parseQuery(query2, null);
- TupleExpr te1 = pq1.getTupleExpr();
- TupleExpr te2 = pq2.getTupleExpr();
-
- SimpleExternalTupleSet pcj = new SimpleExternalTupleSet(
- (Projection) te2);
- List<ExternalTupleSet> externalList = new ArrayList<>();
- externalList.add(pcj);
-
- PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
- optimizer.optimize(te1, null, null);
- System.out.println(te1);
- }
-
- @Test
- public void testSubsetMatchLargeReOrdered() throws Exception {
-
- String query1 = ""//
- + "SELECT ?a ?b ?c ?d ?e ?f ?g ?h" //
- + "{" //
- + " ?a <uri:p0> ?b ." //
- + " OPTIONAL{?b <uri:p2> ?c. ?c <uri:p1> ?d} . " //
- + " OPTIONAL{?b <uri:p3> ?e. ?e <uri:p1> ?f} . "//
- + " OPTIONAL{?b <uri:p4> ?g. ?g <uri:p1> ?h} . "//
- + " OPTIONAL{?b <uri:p4> ?i. ?i <uri:p1> ?j} . "//
- + " OPTIONAL{?b <uri:p4> ?k. ?k <uri:p1> ?l} . "//
- + " OPTIONAL{?b <uri:p4> ?m. ?m <uri:p1> ?n} . "//
- + " OPTIONAL{?b <uri:p4> ?o. ?o <uri:p1> ?p} . "//
- + "}";//
-
- String query2 = ""//
- + "SELECT ?a ?b ?c ?d ?e ?f ?g ?h" //
- + "{" //
- + " ?a <uri:p0> ?b ." //
- + " OPTIONAL{?b <uri:p4> ?o. ?o <uri:p1> ?p} . "//
- + " OPTIONAL{?b <uri:p4> ?g. ?g <uri:p1> ?h} . "//
- + " OPTIONAL{?b <uri:p2> ?c. ?c <uri:p1> ?d} . " //
- + " OPTIONAL{?b <uri:p3> ?e. ?e <uri:p1> ?f} . "//
- + "}";//
-
- SPARQLParser parser = new SPARQLParser();
- ParsedQuery pq1 = parser.parseQuery(query1, null);
- ParsedQuery pq2 = parser.parseQuery(query2, null);
- TupleExpr te1 = pq1.getTupleExpr();
- TupleExpr te2 = pq2.getTupleExpr();
-
- SimpleExternalTupleSet pcj = new SimpleExternalTupleSet(
- (Projection) te2);
- List<ExternalTupleSet> externalList = new ArrayList<>();
- externalList.add(pcj);
-
- PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
- optimizer.optimize(te1, null, null);
- System.out.println(te1);
- }
-
- @Test
- public void testSwitchTwoBoundVars() throws Exception {
-
- String query1 = ""//
- + "SELECT ?a ?b ?c " //
- + "{" //
- + " ?a <uri:p0> ?c ." //
- + " ?c <uri:p5> <uri:o5> ." //
- + " OPTIONAL{?c <uri:p4> <uri:o4>} ." + " ?b<uri:p1> ?c ." //
- + " OPTIONAL{ ?a <uri:p1> ?b } ." //
- + " ?a <uri:p2> <uri:o2>. " //
- + " ?b <uri:p3> <uri:o3> " //
- + "}";//
-
- String query2 = ""//
- + "SELECT ?a ?b ?c " //
- + "{" //
- + " ?a <uri:p2> <uri:o2>. " //
- + " ?b <uri:p3> <uri:o3>. " //
- + " OPTIONAL{ ?a <uri:p1> ?b } ." //
- + " ?a <uri:p0> ?c ." //
- + " ?b<uri:p1> ?c " //
- + "}";//
-
- SPARQLParser parser = new SPARQLParser();
- ParsedQuery pq1 = parser.parseQuery(query1, null);
- ParsedQuery pq2 = parser.parseQuery(query2, null);
- TupleExpr te1 = pq1.getTupleExpr();
- TupleExpr te2 = pq2.getTupleExpr();
- SimpleExternalTupleSet pcj = new SimpleExternalTupleSet(
- (Projection) te2);
- List<ExternalTupleSet> externalList = new ArrayList<>();
- externalList.add(pcj);
-
- PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
- optimizer.optimize(te1, null, null);
- System.out.println(te1);
- }
-
- @Test
- public void testSegmentWithLargeUnion() throws MalformedQueryException {
-
- String query1 = ""//
- + "SELECT ?e ?c ?l" //
- + "{" //
- + " {?e <uri:p1> <uri:o1>. } UNION { " //
- + " ?e <uri:p0> ?l ." //
- + " ?l <uri:p5> <uri:o5> ." //
- + " OPTIONAL{?l <uri:p4> <uri:o4>} ." + " ?c<uri:p1> ?l ." //
- + " OPTIONAL{ ?e <uri:p1> ?c } ." //
- + " ?e <uri:p2> <uri:o2>. " //
- + " ?c <uri:p3> <uri:o3> " //
- + " } . "//
- + " ?e <uri:p2> ?c . "//
- + " ?e <uri:p3> <uri:o2> . "//
- + "}";//
-
- String query2 = ""//
- + "SELECT ?a ?b ?c " //
- + "{" //
- + " ?a <uri:p2> <uri:o2>. " //
- + " ?b <uri:p3> <uri:o3>. " //
- + " OPTIONAL{ ?a <uri:p1> ?b } ." //
- + " ?a <uri:p0> ?c ." //
- + " ?b<uri:p1> ?c " //
- + "}";//
-
- String query3 = ""//
- + "SELECT ?h ?i" //
- + "{" //
- + " ?h <uri:p2> ?i . "//
- + " ?h <uri:p3> <uri:o2> . "//
- + "}";//
-
- SPARQLParser parser = new SPARQLParser();
- ParsedQuery pq1 = parser.parseQuery(query1, null);
- ParsedQuery pq2 = parser.parseQuery(query2, null);
- ParsedQuery pq3 = parser.parseQuery(query3, null);
- TupleExpr te1 = pq1.getTupleExpr();
- TupleExpr te2 = pq2.getTupleExpr();
- TupleExpr te3 = pq3.getTupleExpr();
-
- SimpleExternalTupleSet pcj1 = new SimpleExternalTupleSet(
- (Projection) te2);
- SimpleExternalTupleSet pcj2 = new SimpleExternalTupleSet(
- (Projection) te3);
- List<ExternalTupleSet> externalList = new ArrayList<>();
- externalList.add(pcj1);
- externalList.add(pcj2);
-
- PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
- optimizer.optimize(te1, null, null);
- System.out.println(te1);
-
- // Assert.assertEquals(true, jsm.matchPCJ(pcj));
- // TupleExpr te = jsm.getQuery();
- // Assert.assertEquals(new HashSet<QueryModelNode>(),
- // jsm.getUnmatchedArgs());
- //
- // 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 testSegmentWithUnionAndFilters() throws MalformedQueryException {
-
- String query1 = ""//
- + "SELECT ?e ?c ?l" //
- + "{" //
- + " Filter(?e = <uri:s1>) " //
- + " Filter(?c = <uri:s2>) " //
- + " {?e <uri:p1> <uri:o1>. } UNION { ?e a ?c. OPTIONAL {?e <uri:talksTo> ?l}. ?e <uri:p5> <uri:o4>. ?e <uri:p4> <uri:o3> } . "//
- + " ?e <uri:p2> ?c . "//
- + " ?e <uri:p3> <uri:o2> . "//
- + "}";//
-
- String query2 = ""//
- + "SELECT ?a ?b ?m" //
- + "{" //
- + " Filter(?b = <uri:s2>) " //
- + " ?a <uri:p5> <uri:o4> ." //
- + " ?a <uri:p4> <uri:o3> ." //
- + " OPTIONAL {?a <uri:talksTo> ?m} . "//
- + " ?a a ?b . "//
- + "}";//
-
- String query3 = ""//
- + "SELECT ?h ?i" //
- + "{" //
- + " Filter(?h = <uri:s1>) " //
- + " ?h <uri:p2> ?i . "//
- + " ?h <uri:p3> <uri:o2> . "//
- + "}";//
-
- SPARQLParser parser = new SPARQLParser();
- ParsedQuery pq1 = parser.parseQuery(query1, null);
- ParsedQuery pq2 = parser.parseQuery(query2, null);
- ParsedQuery pq3 = parser.parseQuery(query3, null);
- TupleExpr te1 = pq1.getTupleExpr();
- TupleExpr te2 = pq2.getTupleExpr();
- TupleExpr te3 = pq3.getTupleExpr();
-
- SimpleExternalTupleSet pcj1 = new SimpleExternalTupleSet(
- (Projection) te2);
- SimpleExternalTupleSet pcj2 = new SimpleExternalTupleSet(
- (Projection) te3);
- List<ExternalTupleSet> externalList = new ArrayList<>();
- externalList.add(pcj1);
- externalList.add(pcj2);
-
- PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
- optimizer.optimize(te1, null, null);
- System.out.println(te1);
-
- // Assert.assertEquals(true, jsm.matchPCJ(pcj));
- // TupleExpr te = jsm.getQuery();
- // Assert.assertEquals(new HashSet<QueryModelNode>(),
- // jsm.getUnmatchedArgs());
- //
- // 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 testSegmentWithLeftJoinsAndFilters()
- throws MalformedQueryException {
-
- String query1 = ""//
- + "SELECT ?e ?c ?l" //
- + "{" //
- + " Filter(?e = <uri:s1>) " //
- + " Filter(?c = <uri:s2>) " //
- + " ?e <uri:p1> <uri:o1>. "
- + " OPTIONAL {?e <uri:p2> ?l}. "
- + " ?c <uri:p3> <uri:o3> . "//
- + " ?c <uri:p4> ?e . "//
- + " OPTIONAL {?e <uri:p2> ?c } . "//
- + "}";//
-
- String query2 = ""//
- + "SELECT ?e ?c ?l" //
- + "{" //
- + " Filter(?c = <uri:s2>) " //
- + " ?e <uri:p1> <uri:o1>. "
- + " OPTIONAL {?e <uri:p2> ?l}. "
- + " ?c <uri:p3> <uri:o3> . "//
- + "}";//
-
- String query3 = ""//
- + "SELECT ?e ?c" //
- + "{" //
- + " Filter(?e = <uri:s1>) " //
- + " ?c <uri:p4> ?e . "//
- + " OPTIONAL {?e <uri:p2> ?c } . "//
- + "}";//
-
- SPARQLParser parser = new SPARQLParser();
- ParsedQuery pq1 = parser.parseQuery(query1, null);
- ParsedQuery pq2 = parser.parseQuery(query2, null);
- ParsedQuery pq3 = parser.parseQuery(query3, null);
- TupleExpr te1 = pq1.getTupleExpr();
- TupleExpr te2 = pq2.getTupleExpr();
- TupleExpr te3 = pq3.getTupleExpr();
-
- SimpleExternalTupleSet pcj1 = new SimpleExternalTupleSet(
- (Projection) te2);
- SimpleExternalTupleSet pcj2 = new SimpleExternalTupleSet(
- (Projection) te3);
- List<ExternalTupleSet> externalList = new ArrayList<>();
- externalList.add(pcj1);
- externalList.add(pcj2);
-
- PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
- optimizer.optimize(te1, null, null);
- System.out.println(te1);
-
- // Assert.assertEquals(true, jsm.matchPCJ(pcj));
- // TupleExpr te = jsm.getQuery();
- // Assert.assertEquals(new HashSet<QueryModelNode>(),
- // jsm.getUnmatchedArgs());
- //
- // 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 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 ?a ?b ?m" //
+ + "{" //
+ + " ?a a ?b . "//
+ + " OPTIONAL {?a <uri:talksTo> ?m} . "//
+ + "}";//
+
+ SPARQLParser parser = new SPARQLParser();
+ ParsedQuery pq1 = parser.parseQuery(query1, null);
+ ParsedQuery pq2 = parser.parseQuery(query2, null);
+ TupleExpr te1 = pq1.getTupleExpr();
+ TupleExpr te2 = pq2.getTupleExpr();
+
+ TupleExpr unOpt = te1.clone();
+ List<QueryModelNode> remainingNodes = getNodes(te1);
+ Set<QueryModelNode> unMatchedNodes = new HashSet<>();
+ unMatchedNodes.add(remainingNodes.get(2));
+
+ SimpleExternalTupleSet pcj = new SimpleExternalTupleSet((Projection) te2);
+ List<ExternalTupleSet> externalList = new ArrayList<>();
+ externalList.add(pcj);
+
+ PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
+ optimizer.optimize(te1, null, null);
+
+ Assert.assertEquals(true, validatePcj(te1, unOpt, externalList, unMatchedNodes));
+
+
+ }
+
+ @Test
+ public void testSegmentWithUnion() throws MalformedQueryException {
+
+ String query1 = ""//
+ + "SELECT ?e ?c ?l" //
+ + "{" //
+ + " {?e <uri:p1> <uri:o1>. } UNION { ?e a ?c. OPTIONAL {?e <uri:talksTo> ?l}. ?e <uri:p5> <uri:o4>. ?e <uri:p4> <uri:o3> } . "//
+ + " ?e <uri:p2> ?c . "//
+ + " ?e <uri:p3> <uri:o2> . "//
+ + "}";//
+
+ String query2 = ""//
+ + "SELECT ?a ?b ?m" //
+ + "{" //
+ + " ?a <uri:p5> <uri:o4> ." //
+ + " ?a <uri:p4> <uri:o3> ." //
+ + " OPTIONAL {?a <uri:talksTo> ?m} . "//
+ + " ?a a ?b . "//
+ + "}";//
+
+ String query3 = ""//
+ + "SELECT ?h ?i" //
+ + "{" //
+ + " ?h <uri:p2> ?i . "//
+ + " ?h <uri:p3> <uri:o2> . "//
+ + "}";//
+
+ SPARQLParser parser = new SPARQLParser();
+ ParsedQuery pq1 = parser.parseQuery(query1, null);
+ ParsedQuery pq2 = parser.parseQuery(query2, null);
+ ParsedQuery pq3 = parser.parseQuery(query3, null);
+ TupleExpr te1 = pq1.getTupleExpr();
+ TupleExpr te2 = pq2.getTupleExpr();
+ TupleExpr te3 = pq3.getTupleExpr();
+
+ TupleExpr unOpt = te1.clone();
+ List<QueryModelNode> remainingNodes = getNodes(te1);
+ Set<QueryModelNode> unMatchedNodes = new HashSet<>();
+ unMatchedNodes.add(remainingNodes.get(0));
+
+ SimpleExternalTupleSet pcj1 = new SimpleExternalTupleSet((Projection) te2);
+ SimpleExternalTupleSet pcj2 = new SimpleExternalTupleSet((Projection) te3);
+ List<ExternalTupleSet> externalList = new ArrayList<>();
+ externalList.add(pcj1);
+ externalList.add(pcj2);
+
+ PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
+ optimizer.optimize(te1, null, null);
+
+ Assert.assertEquals(true, validatePcj(te1, unOpt, externalList, unMatchedNodes));
+
+
+
+ }
+
+ @Test
+ public void testExactMatchLargeReOrdered() throws Exception {
+
+
+ String query1 = ""//
+ + "SELECT ?a ?b ?c ?d ?e ?f ?g ?h" //
+ + "{" //
+ + " ?a <uri:p0> ?b ." //
+ + " OPTIONAL{?b <uri:p2> ?c. ?c <uri:p1> ?d} . " //
+ + " OPTIONAL{?b <uri:p3> ?e. ?e <uri:p1> ?f} . "//
+ + " OPTIONAL{?b <uri:p4> ?g. ?g <uri:p1> ?h} . "//
+ + " OPTIONAL{?b <uri:p4> ?i. ?i <uri:p1> ?j} . "//
+ + " OPTIONAL{?b <uri:p4> ?k. ?k <uri:p1> ?l} . "//
+ + " OPTIONAL{?b <uri:p4> ?m. ?m <uri:p1> ?n} . "//
+ + " OPTIONAL{?b <uri:p4> ?o. ?o <uri:p1> ?p} . "//
+ + "}";//
+
+ String query2 = ""//
+ + "SELECT ?a ?b ?c ?d ?e ?f ?g ?h" //
+ + "{" //
+ + " ?a <uri:p0> ?b ." //
+ + " OPTIONAL{?b <uri:p4> ?o. ?o <uri:p1> ?p} . "//
+ + " OPTIONAL{?b <uri:p4> ?g. ?g <uri:p1> ?h} . "//
+ + " OPTIONAL{?b <uri:p2> ?c. ?c <uri:p1> ?d} . " //
+ + " OPTIONAL{?b <uri:p4> ?i. ?i <uri:p1> ?j} . "//
+ + " OPTIONAL{?b <uri:p4> ?m. ?m <uri:p1> ?n} . "//
+ + " OPTIONAL{?b <uri:p4> ?k. ?k <uri:p1> ?l} . "//
+ + " OPTIONAL{?b <uri:p3> ?e. ?e <uri:p1> ?f} . "//
+ + "}";//
+
+ SPARQLParser parser = new SPARQLParser();
+ ParsedQuery pq1 = parser.parseQuery(query1, null);
+ ParsedQuery pq2 = parser.parseQuery(query2, null);
+ TupleExpr te1 = pq1.getTupleExpr();
+ TupleExpr te2 = pq2.getTupleExpr();
+
+ TupleExpr unOpt = te1.clone();
+
+ SimpleExternalTupleSet pcj = new SimpleExternalTupleSet((Projection) te2);
+ List<ExternalTupleSet> externalList = new ArrayList<>();
+ externalList.add(pcj);
+
+
+ PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
+ optimizer.optimize(te1, null, null);
+
+ Assert.assertEquals(true, validatePcj(te1, unOpt, externalList, new HashSet<QueryModelNode>()));
+ }
+
+ @Test
+ public void testSubsetMatchLargeReOrdered() throws Exception {
+
+ String query1 = ""//
+ + "SELECT ?a ?b ?c ?d ?e ?f ?g ?h" //
+ + "{" //
+ + " ?a <uri:p0> ?b ." //
+ + " OPTIONAL{?b <uri:p2> ?c. ?c <uri:p1> ?d} . " //
+ + " OPTIONAL{?b <uri:p3> ?e. ?e <uri:p1> ?f} . "//
+ + " OPTIONAL{?b <uri:p4> ?g. ?g <uri:p1> ?h} . "//
+ + " OPTIONAL{?b <uri:p5> ?i. ?i <uri:p6> ?j} . "//
+ + " OPTIONAL{?b <uri:p5> ?k. ?k <uri:p6> ?l} . "//
+ + " OPTIONAL{?b <uri:p5> ?m. ?m <uri:p6> ?n} . "//
+ + " OPTIONAL{?b <uri:p4> ?o. ?o <uri:p1> ?p} . "//
+ + "}";//
+
+ String query2 = ""//
+ + "SELECT ?a ?b ?c ?d ?e ?f ?g ?h" //
+ + "{" //
+ + " ?a <uri:p0> ?b ." //
+ + " OPTIONAL{?b <uri:p4> ?o. ?o <uri:p1> ?p} . "//
+ + " OPTIONAL{?b <uri:p4> ?g. ?g <uri:p1> ?h} . "//
+ + " OPTIONAL{?b <uri:p2> ?c. ?c <uri:p1> ?d} . " //
+ + " OPTIONAL{?b <uri:p3> ?e. ?e <uri:p1> ?f} . "//
+ + "}";//
+
+ SPARQLParser parser = new SPARQLParser();
+ ParsedQuery pq1 = parser.parseQuery(query1, null);
+ ParsedQuery pq2 = parser.parseQuery(query2, null);
+ TupleExpr te1 = pq1.getTupleExpr();
+ TupleExpr te2 = pq2.getTupleExpr();
+
+ TupleExpr unOpt = te1.clone();
+ List<QueryModelNode> remainingNodes = getNodes(te1);
+ Set<QueryModelNode> unMatchedNodes = new HashSet<>();
+ unMatchedNodes.add(remainingNodes.get(8));
+ unMatchedNodes.add(remainingNodes.get(9));
+ unMatchedNodes.add(remainingNodes.get(10));
+ unMatchedNodes.add(remainingNodes.get(11));
+ unMatchedNodes.add(remainingNodes.get(12));
+ unMatchedNodes.add(remainingNodes.get(7));
+
+ SimpleExternalTupleSet pcj = new SimpleExternalTupleSet((Projection) te2);
+ List<ExternalTupleSet> externalList = new ArrayList<>();
+ externalList.add(pcj);
+
+ PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
+ optimizer.optimize(te1, null, null);
+
+ Assert.assertEquals(true, validatePcj(te1, unOpt, externalList, unMatchedNodes));
+ }
+
+ @Test
+ public void testSwitchTwoBoundVars() throws Exception {
+
+ String query1 = ""//
+ + "SELECT ?a ?b ?c " //
+ + "{" //
+ + " ?a <uri:p0> ?c ." //
+ + " ?c <uri:p5> <uri:o5> ." //
+ + " OPTIONAL{?c <uri:p4> <uri:o4>} ."
+ + " ?b<uri:p1> ?c ." //
+ + " OPTIONAL{ ?a <uri:p1> ?b } ." //
+ + " ?a <uri:p2> <uri:o2>. " //
+ + " ?b <uri:p3> <uri:o3> " //
+ + "}";//
+
+ String query2 = ""//
+ + "SELECT ?a ?b ?c " //
+ + "{" //
+ + " ?a <uri:p2> <uri:o2>. " //
+ + " ?b <uri:p3> <uri:o3>. " //
+ + " OPTIONAL{ ?a <uri:p1> ?b } ." //
+ + " ?a <uri:p0> ?c ." //
+ + " ?b<uri:p1> ?c " //
+ + "}";//
+
+ SPARQLParser parser = new SPARQLParser();
+ ParsedQuery pq1 = parser.parseQuery(query1, null);
+ ParsedQuery pq2 = parser.parseQuery(query2, null);
+ TupleExpr te1 = pq1.getTupleExpr();
+ TupleExpr te2 = pq2.getTupleExpr();
+
+ TupleExpr unOpt = te1.clone();
+ List<QueryModelNode> remainingNodes = getNodes(te1);
+ Set<QueryModelNode> unMatchedNodes = new HashSet<>();
+ unMatchedNodes.add(remainingNodes.get(1));
+ unMatchedNodes.add(remainingNodes.get(2));
+
+ SimpleExternalTupleSet pcj = new SimpleExternalTupleSet((Projection) te2);
+ List<ExternalTupleSet> externalList = new ArrayList<>();
+ externalList.add(pcj);
+
+ PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
+ optimizer.optimize(te1, null, null);
+
+ Assert.assertEquals(true, validatePcj(te1, unOpt, externalList, unMatchedNodes));
+ }
+
+ @Test
+ public void testSegmentWithLargeUnion() throws MalformedQueryException {
+
+ String query1 = ""//
+ + "SELECT ?e ?c ?l" //
+ + "{" //
+ + " {?e <uri:p1> <uri:o1>. } UNION { " //
+ + " ?e <uri:p0> ?l ." //
+ + " ?l <uri:p5> <uri:o5> ." //
+ + " OPTIONAL{?l <uri:p4> <uri:o4>} ." + " ?c<uri:p1> ?l ." //
+ + " OPTIONAL{ ?e <uri:p1> ?c } ." //
+ + " ?e <uri:p2> <uri:o2>. " //
+ + " ?c <uri:p3> <uri:o3> " //
+ + " } . "//
+ + " ?e <uri:p2> ?c . "//
+ + " ?e <uri:p3> <uri:o2> . "//
+ + "}";//
+
+ String query2 = ""//
+ + "SELECT ?a ?b ?c " //
+ + "{" //
+ + " ?a <uri:p2> <uri:o2>. " //
+ + " ?b <uri:p3> <uri:o3>. " //
+ + " OPTIONAL{ ?a <uri:p1> ?b } ." //
+ + " ?a <uri:p0> ?c ." //
+ + " ?b<uri:p1> ?c " //
+ + "}";//
+
+ String query3 = ""//
+ + "SELECT ?h ?i" //
+ + "{" //
+ + " ?h <uri:p2> ?i . "//
+ + " ?h <uri:p3> <uri:o2> . "//
+ + "}";//
+
+ SPARQLParser parser = new SPARQLParser();
+ ParsedQuery pq1 = parser.parseQuery(query1, null);
+ ParsedQuery pq2 = parser.parseQuery(query2, null);
+ ParsedQuery pq3 = parser.parseQuery(query3, null);
+ TupleExpr te1 = pq1.getTupleExpr();
+ TupleExpr te2 = pq2.getTupleExpr();
+ TupleExpr te3 = pq3.getTupleExpr();
+
+ TupleExpr unOpt = te1.clone();
+ List<QueryModelNode> remainingNodes = getNodes(te1);
+ Set<QueryModelNode> unMatchedNodes = new HashSet<>();
+ unMatchedNodes.add(remainingNodes.get(0));
+ unMatchedNodes.add(remainingNodes.get(2));
+ unMatchedNodes.add(remainingNodes.get(3));
+
+ SimpleExternalTupleSet pcj1 = new SimpleExternalTupleSet((Projection) te2);
+ SimpleExternalTupleSet pcj2 = new SimpleExternalTupleSet((Projection) te3);
+ List<ExternalTupleSet> externalList = new ArrayList<>();
+ externalList.add(pcj1);
+ externalList.add(pcj2);
+
+ PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
+ optimizer.optimize(te1, null, null);
+
+ Assert.assertEquals(true, validatePcj(te1, unOpt, externalList, unMatchedNodes));
+
+ }
+
+ @Test
+ public void testSegmentWithUnionAndFilters() throws MalformedQueryException {
+
+ String query1 = ""//
+ + "SELECT ?e ?c ?l" //
+ + "{" //
+ + " Filter(?e = <uri:s1>) " //
+ + " Filter(?c = <uri:s2>) " //
+ + " {?e <uri:p1> <uri:o1>. } UNION { ?e a ?c. OPTIONAL {?e <uri:talksTo> ?l}. ?e <uri:p5> <uri:o4>. ?e <uri:p4> <uri:o3> } . "//
+ + " ?e <uri:p2> ?c . "//
+ + " ?e <uri:p3> <uri:o2> . "//
+ + "}";//
+
+ String query2 = ""//
+ + "SELECT ?a ?b ?m" //
+ + "{" //
+ + " Filter(?b = <uri:s2>) " //
+ + " ?a <uri:p5> <uri:o4> ." //
+ + " ?a <uri:p4> <uri:o3> ." //
+ + " OPTIONAL {?a <uri:talksTo> ?m} . "//
+ + " ?a a ?b . "//
+ + "}";//
+
+ String query3 = ""//
+ + "SELECT ?h ?i" //
+ + "{" //
+ + " Filter(?h = <uri:s1>) " //
+ + " ?h <uri:p2> ?i . "//
+ + " ?h <uri:p3> <uri:o2> . "//
+ + "}";//
+
+ SPARQLParser parser = new SPARQLParser();
+ ParsedQuery pq1 = parser.parseQuery(query1, null);
+ ParsedQuery pq2 = parser.parseQuery(query2, null);
+ ParsedQuery pq3 = parser.parseQuery(query3, null);
+ TupleExpr te1 = pq1.getTupleExpr();
+ TupleExpr te2 = pq2.getTupleExpr();
+ TupleExpr te3 = pq3.getTupleExpr();
+
+ TupleExpr unOpt = te1.clone();
+ List<QueryModelNode> remainingNodes = getNodes(te1);
+ Set<QueryModelNode> unMatchedNodes = new HashSet<>();
+ unMatchedNodes.add(remainingNodes.get(0));
+
+ SimpleExternalTupleSet pcj1 = new SimpleExternalTupleSet((Projection) te2);
+ SimpleExternalTupleSet pcj2 = new SimpleExternalTupleSet((Projection) te3);
+ List<ExternalTupleSet> externalList = new ArrayList<>();
+ externalList.add(pcj1);
+ externalList.add(pcj2);
+
+ PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
+ optimizer.optimize(te1, null, null);
+
+ Assert.assertEquals(true, validatePcj(te1, unOpt, externalList, unMatchedNodes));
+
+ }
+
+ @Test
+ public void testSegmentWithLeftJoinsAndFilters() throws MalformedQueryException {
+
+ String query1 = ""//
+ + "SELECT ?e ?c ?l" //
+ + "{" //
+ + " Filter(?e = <uri:s1>) " //
+ + " Filter(?c = <uri:s2>) " //
+ + " ?e <uri:p1> <uri:o1>. " + " OPTIONAL {?e <uri:p2> ?l}. " + " ?c <uri:p3> <uri:o3> . "//
+ + " ?c <uri:p4> ?e . "//
+ + " OPTIONAL {?e <uri:p2> ?c } . "//
+ + "}";//
+
+ String query2 = ""//
+ + "SELECT ?e ?c ?l" //
+ + "{" //
+ + " Filter(?c = <uri:s2>) " //
+ + " ?e <uri:p1> <uri:o1>. " + " OPTIONAL {?e <uri:p2> ?l}. " + " ?c <uri:p3> <uri:o3> . "//
+ + "}";//
+
+ String query3 = ""//
+ + "SELECT ?e ?c" //
+ + "{" //
+ + " Filter(?e = <uri:s1>) " //
+ + " ?c <uri:p4> ?e . "//
+ + " OPTIONAL {?e <uri:p2> ?c } . "//
+ + "}";//
+
+ SPARQLParser parser = new SPARQLParser();
+ ParsedQuery pq1 = parser.parseQuery(query1, null);
+ ParsedQuery pq2 = parser.parseQuery(query2, null);
+ ParsedQuery pq3 = parser.parseQuery(query3, null);
+ TupleExpr te1 = pq1.getTupleExpr();
+ TupleExpr te2 = pq2.getTupleExpr();
+ TupleExpr te3 = pq3.getTupleExpr();
+
+ TupleExpr unOpt = te1.clone();
+
+ SimpleExternalTupleSet pcj1 = new SimpleExternalTupleSet((Projection) te2);
+ SimpleExternalTupleSet pcj2 = new SimpleExternalTupleSet((Projection) te3);
+ List<ExternalTupleSet> externalList = new ArrayList<>();
+ externalList.add(pcj1);
+ externalList.add(pcj2);
+
+ PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
+ optimizer.optimize(te1, null, null);
+
+ Assert.assertEquals(true, validatePcj(te1, unOpt, externalList, new HashSet<QueryModelNode>()));
+ }
+
+ @Test
+ public void testJoinMatcherRejectsLeftJoinPcj() throws MalformedQueryException {
+
+ String query1 = ""//
+ + "SELECT ?e ?c ?l" //
+ + "{" //
+ + " ?e a ?c . "//
+ + " ?e <uri:talksTo> ?l . "//
+ + " ?e <http://www.w3.org/2000/01/rdf-schema#label> ?l "//
+ + "}";//
+
+ String query2 = ""//
+ + "SELECT ?a ?b ?m" //
+ + "{" //
+ + " ?a a ?b . "//
+ + " ?a <uri:talksTo> ?m . "//
+ + " OPTIONAL {?a <http://www.w3.org/2000/01/rdf-schema#label> ?m} . "//
+ + "}";//
+
+ SPARQLParser parser = new SPARQLParser();
+ ParsedQuery pq1 = parser.parseQuery(query1, null);
+ ParsedQuery pq2 = parser.parseQuery(query2, null);
+ TupleExpr te1 = pq1.getTupleExpr();
+ TupleExpr te2 = pq2.getTupleExpr();
+ TupleExpr expected = te1.clone();
+
+ SimpleExternalTupleSet pcj = new SimpleExternalTupleSet((Projection) te2);
+ List<ExternalTupleSet> externalList = new ArrayList<>();
+ externalList.add(pcj);
+
+ PCJOptimizer optimizer = new PCJOptimizer(externalList, false);
+ optimizer.optimize(te1, null, null);
+ Assert.assertEquals(expected, te1);
+
+ }
+
+
+ private List<QueryModelNode> getNodes(TupleExpr te) {
+ NodeCollector collector = new NodeCollector();
+ te.visit(collector);
+ return collector.getNodes();
+ }
+
+ private boolean validatePcj(TupleExpr optTupleExp, TupleExpr unOptTup, List<ExternalTupleSet> pcjs, Set<QueryModelNode> expUnmatchedNodes) {
+
+ IndexedExecutionPlanGenerator iep = new IndexedExecutionPlanGenerator(
+ unOptTup, pcjs);
+ List<ExternalTupleSet> indexList = iep.getNormalizedIndices();
+ Set<QueryModelNode> indexSet = new HashSet<>();
+ for(ExternalTupleSet etup: indexList) {
+ indexSet.add(etup);
+ }
+
+ Set<QueryModelNode> tupNodes = Sets.newHashSet(getNodes(optTupleExp));
+
+ Set<QueryModelNode> diff = Sets.difference(tupNodes, indexSet);
+ return diff.equals(expUnmatchedNodes);
+ }
+
+
+ public static class NodeCollector extends QueryModelVisitorBase<RuntimeException> {
+
+ List<QueryModelNode> qNodes = new ArrayList<>();
+
+ @Override
+ public void meetNode(final QueryModelNode node) {
+ if (node instanceof StatementPattern || node instanceof ExternalTupleSet) {
+ qNodes.add(node);
+ }
+ super.meetNode(node);
+
+ }
+
+ public List<QueryModelNode> getNodes() {
+ return qNodes;
+ }
+
+ }
}