You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2015/09/08 19:10:35 UTC

[03/20] jena git commit: Move join test package to aling to main. Start leftjoin tests.

Move join test package to aling to main.  Start leftjoin tests.


Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/d4da1a5a
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/d4da1a5a
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/d4da1a5a

Branch: refs/heads/master
Commit: d4da1a5a890073d2bd8114e8e611ddaf88eae8fd
Parents: 0b060c8
Author: Andy Seaborne <an...@apache.org>
Authored: Tue Sep 8 10:22:57 2015 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Tue Sep 8 18:08:11 2015 +0100

----------------------------------------------------------------------
 .../java/org/apache/jena/sparql/TC_General.java |   2 +-
 .../apache/jena/sparql/engine/TS_Engine.java    |   3 +-
 .../apache/jena/sparql/engine/TestTableLib.java | 119 ----------
 .../engine/join/AbstractTestInnerJoin.java      | 170 +++++++++++++
 .../sparql/engine/join/AbstractTestJoin.java    | 101 ++++++++
 .../engine/join/AbstractTestLeftJoin.java       | 170 +++++++++++++
 .../apache/jena/sparql/engine/join/TS_Join.java |  34 +++
 .../jena/sparql/engine/join/TestHashJoin.java   |  38 +++
 .../sparql/engine/join/TestJoinNestedLoop.java  |  34 +++
 .../engine/join/TestJoinNestedLoopSimple.java   |  34 +++
 .../jena/sparql/engine/join/TestJoinSimple.java |  34 +++
 .../sparql/engine/join/TestLeftJoinSimple.java  |  34 +++
 .../jena/sparql/join/AbstractTestJoin.java      | 236 -------------------
 .../org/apache/jena/sparql/join/TS_Join.java    |  34 ---
 .../apache/jena/sparql/join/TestHashJoin.java   |  38 ---
 .../jena/sparql/join/TestJoinNestedLoop.java    |  34 ---
 .../sparql/join/TestJoinNestedLoopSimple.java   |  34 ---
 .../apache/jena/sparql/join/TestJoinSimple.java |  34 ---
 18 files changed, 652 insertions(+), 531 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/d4da1a5a/jena-arq/src/test/java/org/apache/jena/sparql/TC_General.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/TC_General.java b/jena-arq/src/test/java/org/apache/jena/sparql/TC_General.java
index 7c67a5d..429387e 100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/TC_General.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/TC_General.java
@@ -25,12 +25,12 @@ import org.apache.jena.sparql.algebra.optimize.TS_Optimization ;
 import org.apache.jena.sparql.api.TS_API ;
 import org.apache.jena.sparql.core.TS_Core ;
 import org.apache.jena.sparql.engine.TS_Engine ;
+import org.apache.jena.sparql.engine.join.TS_Join ;
 import org.apache.jena.sparql.expr.E_Function ;
 import org.apache.jena.sparql.expr.NodeValue ;
 import org.apache.jena.sparql.expr.TS_Expr ;
 import org.apache.jena.sparql.function.user.TS_UserFunctions ;
 import org.apache.jena.sparql.graph.TS_Graph ;
-import org.apache.jena.sparql.join.TS_Join ;
 import org.apache.jena.sparql.lang.TS_Lang ;
 import org.apache.jena.sparql.modify.TS_Update ;
 import org.apache.jena.sparql.negation.TS_Negation ;

http://git-wip-us.apache.org/repos/asf/jena/blob/d4da1a5a/jena-arq/src/test/java/org/apache/jena/sparql/engine/TS_Engine.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/engine/TS_Engine.java b/jena-arq/src/test/java/org/apache/jena/sparql/engine/TS_Engine.java
index 889acf9..d7b386c 100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/engine/TS_Engine.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/engine/TS_Engine.java
@@ -22,13 +22,14 @@ import org.apache.jena.sparql.engine.binding.TestBindingStreams ;
 import org.apache.jena.sparql.engine.http.TestQueryEngineHTTP ;
 import org.apache.jena.sparql.engine.http.TestService ;
 import org.apache.jena.sparql.engine.iterator.TS_QueryIterators ;
+import org.apache.jena.sparql.engine.ref.TestTableJoin ;
 import org.junit.runner.RunWith ;
 import org.junit.runners.Suite ;
 
 @RunWith(Suite.class)
 @Suite.SuiteClasses( {
         TestBindingStreams.class
-      , TestTableLib.class
+      , TestTableJoin.class
       , TS_QueryIterators.class
       , TestService.class
       , TestQueryEngineHTTP.class

http://git-wip-us.apache.org/repos/asf/jena/blob/d4da1a5a/jena-arq/src/test/java/org/apache/jena/sparql/engine/TestTableLib.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/engine/TestTableLib.java b/jena-arq/src/test/java/org/apache/jena/sparql/engine/TestTableLib.java
deleted file mode 100644
index 88f8cf0..0000000
--- a/jena-arq/src/test/java/org/apache/jena/sparql/engine/TestTableLib.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/**
- * 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.engine;
-
-import java.util.HashSet ;
-import java.util.Set ;
-
-import org.apache.jena.atlas.junit.BaseTest ;
-import org.apache.jena.query.ARQ ;
-import org.apache.jena.query.ResultSet ;
-import org.apache.jena.query.ResultSetFactory ;
-import org.apache.jena.sparql.algebra.Table ;
-import org.apache.jena.sparql.algebra.table.TableEmpty ;
-import org.apache.jena.sparql.algebra.table.TableN ;
-import org.apache.jena.sparql.algebra.table.TableUnit ;
-import org.apache.jena.sparql.engine.ExecutionContext ;
-import org.apache.jena.sparql.engine.QueryIterator ;
-import org.apache.jena.sparql.engine.TableJoin ;
-import org.apache.jena.sparql.expr.ExprList ;
-import org.apache.jena.sparql.resultset.ResultSetCompare ;
-import org.apache.jena.sparql.sse.SSE ;
-import org.junit.Test ;
-
-public class TestTableLib extends BaseTest
-{
-    Table unit = new TableUnit() ; 
-    Table zero = new TableEmpty() ;
-    Table zeroData = SSE.parseTable("(table)") ;
-    Table unitData = SSE.parseTable("(table (row))") ;
-    Table data1 = SSE.parseTable("(table (row (?a 1) (?b 2)))") ;
-    Table data2 = SSE.parseTable("(table (row (?a 1) (?c 3)) (row (?a 9) (?c 5))  )") ;
-    Table data3 = SSE.parseTable("(table (row (?a 1) (?c 3)) (row (?a 1) (?c 4)) (row (?a 9) (?c 5))  )") ;
-    
-    Table data1J2 = SSE.parseTable("(table (row (?a 1) (?b 2) (?c 3)) )") ;
-    Table data1LJ2 = SSE.parseTable("(table (row (?a 1) (?b 2) (?c 3)) (row (?a 9) (?c 5)) )") ;
-    Table data2LJ1 = SSE.parseTable("(table (row (?a 1) (?b 2) (?c 3)) )") ;
-    
-    Table data1J3 = SSE.parseTable("(table (row (?a 1) (?b 2) (?c 3)) (row (?a 1) (?b 2) (?c 4)) )") ;
-    
-    @Test public void table_01() { test(unit, zero, true, null, zero) ; }
-    @Test public void table_02() { test(zero, unit, true, null, zero) ; }
-    @Test public void table_03() { test(unit, zero, false, null, unit) ; }
-    @Test public void table_04() { test(zero, unit, false, null, zero) ; }
-    // Same again but with non-special tables.
-    @Test public void table_05() { test(unitData, zeroData, true, null, zeroData) ; }
-    @Test public void table_06() { test(zeroData, unitData, true, null, zeroData) ; }
-    @Test public void table_07() { test(unitData, zeroData, false, null, unitData) ; }
-    @Test public void table_08() { test(zeroData, unitData, false, null, zeroData) ; }
-
-    @Test public void table_10() { test(data1, zero, true, null, zero) ; }
-    @Test public void table_11() { test(zero, data1, true, null, zero) ; }
-    @Test public void table_12() { test(data1, zero, false, null, data1) ; }
-    @Test public void table_13() { test(zero, data1, false, null, zero) ; }
-    
-    @Test public void table_14() { test(data1, zeroData, true, null, zeroData) ; }
-    @Test public void table_15() { test(zeroData, data1, true, null, zeroData) ; }
-    @Test public void table_16() { test(data1, zeroData, false, null, data1) ; }
-    @Test public void table_17() { test(zeroData, data1, false, null, zeroData) ; }
-
-    @Test public void table_18() { test(data2, unitData, true, null, data2) ; }
-    @Test public void table_19() { test(unitData, data2, true, null, data2) ; }
-    
-    @Test public void table_20() { test(data1, data2, true, null, data1J2) ; }
-    @Test public void table_21() { test(data2, data1, true, null, data1J2) ; }
-    @Test public void table_22() { test(data1, data2, false, null, data1LJ2) ; }
-    @Test public void table_23() { test(data2, data1, false, null, data2LJ1) ; }
-    
-    @Test public void table_24() { test(data1, data3, true, null, data1J3) ; }
-    @Test public void table_25() { test(data3, data1, true, null, data1J3) ; }
-
-    private void test(Table left, Table right, boolean normalJoin, ExprList exprs, Table expected) {
-        ExecutionContext execCxt = new ExecutionContext(ARQ.getContext(), null, null, null) ;
-        QueryIterator leftIter = left.iterator(execCxt) ;
-        QueryIterator qIter = normalJoin 
-            ? TableJoin.join(leftIter, right, exprs, execCxt)
-            : TableJoin.leftJoin(leftIter, right, exprs, execCxt) ;
-        
-            // Order issues
-            
-        Set<String> vars1 = new HashSet<>() ;
-        vars1.addAll(left.getVarNames()) ;
-        vars1.addAll(right.getVarNames()) ;
-        
-        TableN results = new TableN(qIter) ;
-        boolean b = TableCompare.equalsByTerm(expected, results) ;
-        if ( !b ) {
-            System.out.println("** Expected") ;
-            System.out.println(expected) ;
-            System.out.println("** Actual") ;
-            System.out.println(results) ;
-        }
-        assertTrue(b) ;
-    }
-    
-    static class TableCompare {
-        public static boolean equalsByTerm(Table table1, Table table2) {
-            ResultSet rs1 = ResultSetFactory.create(table1.iterator(null), table1.getVarNames()) ;
-            ResultSet rs2 = ResultSetFactory.create(table2.iterator(null), table2.getVarNames()) ;
-            return ResultSetCompare.equalsByTerm(rs1, rs2) ;
-        }
-    }
-        
-}

http://git-wip-us.apache.org/repos/asf/jena/blob/d4da1a5a/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/AbstractTestInnerJoin.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/AbstractTestInnerJoin.java b/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/AbstractTestInnerJoin.java
new file mode 100644
index 0000000..f5a1bdc
--- /dev/null
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/AbstractTestInnerJoin.java
@@ -0,0 +1,170 @@
+/**
+ * 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.engine.join;
+
+import org.apache.jena.sparql.algebra.Table ;
+import org.apache.jena.sparql.core.Var ;
+import org.apache.jena.sparql.engine.join.JoinKey ;
+import org.junit.Test ;
+
+/** Tests for inner/equi joins */ 
+public abstract class AbstractTestInnerJoin extends AbstractTestJoin {
+    
+    @Override
+    protected void executeTest(JoinKey joinKey, Table left, Table right, Table expectedResults) {
+        executeTestJoin("1", joinKey, left, right, expectedResults) ;
+        executeTestJoin("2", joinKey, right, left, expectedResults) ;
+    }
+    
+    static Var var_a = Var.alloc("a") ; 
+    static Var var_b = Var.alloc("b") ; 
+    static Var var_c = Var.alloc("c") ; 
+    static Var var_d = Var.alloc("d") ; 
+
+    static Table table0() { return parseTableInt("(table)") ; } 
+
+    // Table of one row and no colums.
+    static Table table1() { 
+        return parseTableInt("(table (row))") ; }
+
+    static Table tableD1() { 
+        return parseTableInt("(table", 
+                             "   (row (?a 1) (?b 2))",
+                             "   (row (?a 1) (?b 3))",
+                             "   (row (?a 1) (?b 2))",
+            ")") ;
+    }
+
+    static Table tableD2() { 
+        return parseTableInt("(table", 
+                             "   (row (?a 0) (?d 8))",
+                             "   (row (?a 1) (?c 9))",
+            ")") ;
+    }
+
+    static Table tableD3() {
+        return parseTableInt("(table", 
+                             "   (row (?a 1) (?c 9) (?b 2))",
+                             "   (row (?a 1) (?c 9) (?b 3))",
+                             "   (row (?a 1) (?c 9) (?b 2))",
+            ")") ;
+    }
+
+    static Table tableD4() {
+        return parseTableInt("(table", 
+                             "   (row (?a 1) (?b 2))",
+                             "   (row (?a 1) (?b 3))",
+                             "   (row (?a 4) (?b 4))",
+                             "   (row (?a 4) (?b 5))",
+            ")") ;
+    }
+
+    static Table tableD5() {
+        return parseTableInt("(table", 
+                             "   (row (?a 4) (?c 4))",
+                             "   (row (?a 4) (?c 5))",
+                             "   (row (?a 6) (?c 5))",
+            ")") ;
+    }
+
+    static Table tableD6() {
+        return parseTableInt("(table", 
+                             "   (row (?a 1) (?c 2))",
+                             "   (row (?a 1) (?c 3))",
+                             "   (row (?a 4) (?c 4))",
+                             "   (row (?a 4) (?c 5))",
+            ")") ;
+    }
+
+    static Table tableD4x5() {
+        return parseTableInt("(table", 
+                             "   (row (?a 4) (?c 4) (?b 4))",
+                             "   (row (?a 4) (?c 4) (?b 5))",
+                             "   (row (?a 4) (?c 5) (?b 4))",
+                             "   (row (?a 4) (?c 5) (?b 5))",
+            ")") ;
+    }
+
+    static Table tableD4x6() {
+        return parseTableInt("(table", 
+                             "   (row (?a 1) (?c 2) (?b 2))",
+                             "   (row (?a 1) (?c 2) (?b 3))",
+                             "   (row (?a 1) (?c 3) (?b 2))",
+                             "   (row (?a 1) (?c 3) (?b 3))",
+                             "   (row (?a 4) (?c 4) (?b 4))",
+                             "   (row (?a 4) (?c 4) (?b 5))",
+                             "   (row (?a 4) (?c 5) (?b 4))",
+                             "   (row (?a 4) (?c 5) (?b 5))",
+            ")") ;
+    }
+
+    // Disjoint.
+    static Table tableD8() {
+        return parseTableInt("(table",
+                             "  (row (?x 10))",
+                             "  (row (?z 11))",
+            ")") ; 
+    }
+
+    // Table8 crossproduct table2
+    static Table tableD8x2() {
+        return parseTableInt("(table",
+                             "  (row (?a 0) (?d 8) (?z 11))",
+                             "  (row (?a 0) (?d 8) (?x 10))",
+                             "  (row (?a 1) (?c 9) (?z 11))",
+                             "  (row (?a 1) (?c 9) (?x 10))",
+            ")") ;
+    }
+
+    @Test public void join_00()  { testJoin("a", table0(), table0(), table0()) ; }
+    @Test public void join_00a() { testJoin("a", table1(), table0(), table0()) ; }
+    @Test public void join_00b() { testJoin("a", tableD1(), table1(), tableD1()) ; }
+    @Test public void join_00c() { testJoin("z", tableD1(), table1(), tableD1()) ; }
+
+    @Test public void join_01() { testJoin("a", table0(), tableD2(), table0()) ; }
+    @Test public void join_02() { testJoin("a", tableD1(), table0(), table0()) ; }
+    @Test public void join_03() { testJoin("a", tableD1(), tableD2(), tableD3()) ; }
+
+    // Identity.
+    @Test public void join_04() { testJoin("a", tableD2(), table1(), tableD2()) ; }
+    @Test public void join_05() { testJoin("a", table1(), tableD2(), tableD2()) ; }
+    // Identity, keymiss
+    @Test public void join_06() { testJoin("z", table1(), tableD2(), tableD2()) ; }
+    @Test public void join_07() { testJoin("z", tableD2(), table1(), tableD2()) ; }
+
+    @Test public void join_08() { testJoin("a", tableD4(), tableD5(), tableD4x5()) ; }
+    @Test public void join_09() { testJoin("a", tableD5(), tableD4(), tableD4x5()) ; }
+
+    @Test public void join_10() { testJoin("a", tableD4(), tableD6(), tableD4x6()) ; }
+    @Test public void join_11() { testJoin("a", tableD6(), tableD4(), tableD4x6()) ; }
+
+    // Not the right join key - should still work albeit less efficiently.
+    @Test public void join_12() { testJoin("z", tableD1(), tableD2(), tableD3()) ; }
+    @Test public void join_13() { testJoin("z", tableD2(), tableD1(), tableD3()) ; }
+
+    // No key.
+    @Test public void join_14() { testJoin(null, tableD1(), tableD2(), tableD3()) ; }
+
+
+    // Disjoint tables.
+    @Test public void join_disjoint_01() { testJoin("a", tableD2(), tableD8(), tableD8x2()) ; }
+    @Test public void join_disjoint_02() { testJoin("z", tableD2(), tableD8(), tableD8x2()) ; }
+}
+
+

http://git-wip-us.apache.org/repos/asf/jena/blob/d4da1a5a/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/AbstractTestJoin.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/AbstractTestJoin.java b/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/AbstractTestJoin.java
new file mode 100644
index 0000000..b48c66b
--- /dev/null
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/AbstractTestJoin.java
@@ -0,0 +1,101 @@
+/**
+ * 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.engine.join;
+
+import java.util.List ;
+
+import org.apache.jena.atlas.iterator.Iter ;
+import org.apache.jena.atlas.lib.StrUtils ;
+import org.apache.jena.query.ResultSet ;
+import org.apache.jena.query.ResultSetFactory ;
+import org.apache.jena.sparql.algebra.Table ;
+import org.apache.jena.sparql.algebra.TableFactory ;
+import org.apache.jena.sparql.core.Var ;
+import org.apache.jena.sparql.engine.QueryIterator ;
+import org.apache.jena.sparql.engine.binding.Binding ;
+import org.apache.jena.sparql.engine.join.JoinKey ;
+import org.apache.jena.sparql.resultset.ResultSetCompare ;
+import org.apache.jena.sparql.sse.SSE ;
+import org.junit.Assert ;
+
+/** Tests for inner/equi joins */ 
+public abstract class AbstractTestJoin extends Assert {
+    protected static Table parseTableInt(String... strings) {
+        String x = StrUtils.strjoinNL(strings) ;
+        return SSE.parseTable(x) ;
+    }
+
+    protected void testJoin(String var, Table left, Table right, Table tableOut) {
+        JoinKey joinKey ;
+        if ( var != null ) {
+            if ( var.startsWith("?") )
+                var = var.substring(1) ;
+            joinKey = JoinKey.create(Var.alloc(var)) ;
+        }
+        else {
+            // No vars in join key.  Legal, albeit silly.
+            joinKey = new JoinKey.Builder().build() ;
+        }
+
+        executeTest(joinKey, left, right, tableOut) ;
+    }
+
+    protected abstract void executeTest(JoinKey joinKey, Table left, Table right, Table expectedResults) ;
+    
+    
+    private List<Binding> toList(Table table) {
+        return Iter.toList(table.rows()) ;
+    }
+
+    protected void executeTestJoin(String num, JoinKey joinKey, Table left, Table right, Table expectedResults) {
+        Table x1 = joinMaterialize(joinKey, left, right) ;
+        assertNotNull("Null table from join ("+num+")", x1) ;
+        check("Results not equal ("+num+")", joinKey, left, right, expectedResults, x1) ;
+    }
+
+    private Table joinMaterialize(JoinKey joinKey, Table left, Table right) {
+        QueryIterator qIter = join(joinKey, left , right) ;
+        return TableFactory.create(qIter) ;
+    }
+
+    public abstract QueryIterator join(JoinKey joinKey , Table left , Table right) ;
+
+    private static void check(String msg, JoinKey joinKey, Table left, Table right, Table expected, Table actual) {
+        boolean b = equalTables(expected, actual) ;
+        if ( ! b ) {
+            System.out.println("Joinkey:  "+joinKey) ;
+            System.out.println("Left:     \n"+left) ;
+            System.out.println("Right:    \n"+right) ;
+            System.out.println("Expected: \n"+expected) ;
+            System.out.println("Actual:   \n"+actual) ;
+            System.out.println() ;
+        }
+
+        assertTrue(msg, b) ;
+    }
+
+    private static boolean equalTables(Table table1, Table table2) {
+        ResultSet rs1 =  ResultSetFactory.create(table1.iterator(null), table1.getVarNames()) ;
+        ResultSet rs2 =  ResultSetFactory.create(table2.iterator(null), table2.getVarNames()) ;
+        return ResultSetCompare.equalsByTerm(rs1, rs2) ;
+    }
+
+}
+
+

http://git-wip-us.apache.org/repos/asf/jena/blob/d4da1a5a/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/AbstractTestLeftJoin.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/AbstractTestLeftJoin.java b/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/AbstractTestLeftJoin.java
new file mode 100644
index 0000000..57756ff
--- /dev/null
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/AbstractTestLeftJoin.java
@@ -0,0 +1,170 @@
+/**
+ * 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.engine.join;
+
+import org.apache.jena.sparql.algebra.Table ;
+import org.apache.jena.sparql.core.Var ;
+import org.apache.jena.sparql.engine.join.JoinKey ;
+import org.junit.Test ;
+
+public abstract class AbstractTestLeftJoin extends AbstractTestJoin {
+    @Override
+    protected void executeTest(JoinKey joinKey, Table left, Table right, Table expectedResults) {
+        executeTestJoin("LJ", joinKey, left, right, expectedResults) ;
+    }
+    
+    static Var var_a = Var.alloc("a") ; 
+    static Var var_b = Var.alloc("b") ; 
+    static Var var_c = Var.alloc("c") ; 
+    static Var var_d = Var.alloc("d") ; 
+
+    static Table table0() { return parseTableInt("(table)") ; } 
+
+    // Table of one row and no colums.
+    static Table table1() { 
+        return parseTableInt("(table (row))") ; }
+
+    static Table tableD1() { 
+        return parseTableInt("(table", 
+                             "   (row (?a 1) (?b 2))",
+                             "   (row (?a 1) (?b 3))",
+                             "   (row (?a 1) (?b 2))",
+            ")") ;
+    }
+
+    static Table tableD2() { 
+        return parseTableInt("(table", 
+                             "   (row (?a 0) (?d 8))",
+                             "   (row (?a 1) (?c 9))",
+            ")") ;
+    }
+
+    static Table tableD3() {
+        return parseTableInt("(table", 
+                             "   (row (?a 1) (?c 9) (?b 2))",
+                             "   (row (?a 1) (?c 9) (?b 3))",
+                             "   (row (?a 1) (?c 9) (?b 2))",
+            ")") ;
+    }
+
+    static Table tableD4() {
+        return parseTableInt("(table", 
+                             "   (row (?a 1) (?b 2))",
+                             "   (row (?a 1) (?b 3))",
+                             "   (row (?a 4) (?b 4))",
+                             "   (row (?a 4) (?b 5))",
+            ")") ;
+    }
+
+    static Table tableD5() {
+        return parseTableInt("(table", 
+                             "   (row (?a 4) (?c 4))",
+                             "   (row (?a 4) (?c 5))",
+                             "   (row (?a 6) (?c 5))",
+            ")") ;
+    }
+
+    static Table tableD6() {
+        return parseTableInt("(table", 
+                             "   (row (?a 1) (?c 2))",
+                             "   (row (?a 1) (?c 3))",
+                             "   (row (?a 4) (?c 4))",
+                             "   (row (?a 4) (?c 5))",
+            ")") ;
+    }
+
+    static Table tableD4x5() {
+        return parseTableInt("(table", 
+                             "   (row (?a 4) (?c 4) (?b 4))",
+                             "   (row (?a 4) (?c 4) (?b 5))",
+                             "   (row (?a 4) (?c 5) (?b 4))",
+                             "   (row (?a 4) (?c 5) (?b 5))",
+            ")") ;
+    }
+
+    static Table tableD4x6() {
+        return parseTableInt("(table", 
+                             "   (row (?a 1) (?c 2) (?b 2))",
+                             "   (row (?a 1) (?c 2) (?b 3))",
+                             "   (row (?a 1) (?c 3) (?b 2))",
+                             "   (row (?a 1) (?c 3) (?b 3))",
+                             "   (row (?a 4) (?c 4) (?b 4))",
+                             "   (row (?a 4) (?c 4) (?b 5))",
+                             "   (row (?a 4) (?c 5) (?b 4))",
+                             "   (row (?a 4) (?c 5) (?b 5))",
+            ")") ;
+    }
+
+    // Disjoint.
+    static Table tableD8() {
+        return parseTableInt("(table",
+                             "  (row (?x 10))",
+                             "  (row (?z 11))",
+            ")") ; 
+    }
+
+    // Table8 crossproduct table2
+    static Table tableD8x2() {
+        return parseTableInt("(table",
+                             "  (row (?a 0) (?d 8) (?z 11))",
+                             "  (row (?a 0) (?d 8) (?x 10))",
+                             "  (row (?a 1) (?c 9) (?z 11))",
+                             "  (row (?a 1) (?c 9) (?x 10))",
+            ")") ;
+    }
+
+    // XXX And conditions.
+    
+    @Test public void leftjoin_00()  { testJoin("a", table0(), table0(), table0()) ; }
+    @Test public void leftjoin_00a() { testJoin("a", table1(), table0(), table0()) ; }
+    @Test public void leftjoin_00b() { testJoin("a", tableD1(), table1(), tableD1()) ; }
+    @Test public void leftjoin_00c() { testJoin("z", tableD1(), table1(), tableD1()) ; }
+
+    @Test public void leftjoin_01() { testJoin("a", table0(), tableD2(), table0()) ; }
+    @Test public void leftjoin_02() { testJoin("a", tableD1(), table0(), tableD1()) ; }
+    @Test public void leftjoin_03() { testJoin("a", tableD1(), tableD2(), tableD3()) ; }
+
+    // Identity.
+    @Test public void leftjoin_04() { testJoin("a", tableD2(), table1(), tableD2()) ; }
+    @Test public void leftjoin_05() { testJoin("a", table1(), tableD2(), tableD2()) ; }
+    // Identity, keymiss
+    @Test public void leftjoin_06() { testJoin("z", table1(), tableD2(), tableD2()) ; }
+    @Test public void leftjoin_07() { testJoin("z", tableD2(), table1(), tableD2()) ; }
+
+    @Test public void leftjoin_08() { testJoin("a", tableD4(), tableD5(), tableD4x5()) ; }
+    @Test public void leftjoin_09() { testJoin("a", tableD5(), tableD4(), tableD4x5()) ; }
+
+    @Test public void leftjoin_10() { testJoin("a", tableD4(), tableD6(), tableD4x6()) ; }
+    @Test public void leftjoin_11() { testJoin("a", tableD6(), tableD4(), tableD4x6()) ; }
+
+    // Not the right join key - should still work albeit less efficiently.
+    @Test public void leftjoin_12() { testJoin("z", tableD1(), tableD2(), tableD3()) ; }
+    @Test public void leftjoin_13() { testJoin("z", tableD2(), tableD1(), tableD3()) ; }
+
+    // No key.
+    @Test public void leftjoin_14() { testJoin(null, tableD1(), tableD2(), tableD3()) ; }
+
+
+    // Disjoint tables.
+    @Test public void leftjoin_disjoint_01() { testJoin("a", tableD2(), tableD8(), tableD8x2()) ; }
+    @Test public void leftjoin_disjoint_02() { testJoin("z", tableD2(), tableD8(), tableD8x2()) ; }
+
+}
+
+

http://git-wip-us.apache.org/repos/asf/jena/blob/d4da1a5a/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TS_Join.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TS_Join.java b/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TS_Join.java
new file mode 100644
index 0000000..69b5fb4
--- /dev/null
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TS_Join.java
@@ -0,0 +1,34 @@
+/**
+ * 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.engine.join;
+
+import org.junit.runner.RunWith ;
+import org.junit.runners.Suite ;
+import org.junit.runners.Suite.SuiteClasses ;
+
+@RunWith(Suite.class)
+@SuiteClasses( {
+    TestJoinSimple.class
+    , TestJoinNestedLoopSimple.class    // Real simple materializing version.
+    , TestJoinNestedLoop.class
+    , TestHashJoin.class
+})
+
+public class TS_Join { }
+

http://git-wip-us.apache.org/repos/asf/jena/blob/d4da1a5a/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TestHashJoin.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TestHashJoin.java b/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TestHashJoin.java
new file mode 100644
index 0000000..4a4bd6f
--- /dev/null
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TestHashJoin.java
@@ -0,0 +1,38 @@
+/**
+ * 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.engine.join;
+
+import java.util.Iterator ;
+
+import org.apache.jena.sparql.algebra.Table ;
+import org.apache.jena.sparql.engine.QueryIterator ;
+import org.apache.jena.sparql.engine.binding.Binding ;
+import org.apache.jena.sparql.engine.iterator.QueryIterPlainWrapper ;
+import org.apache.jena.sparql.engine.join.Join ;
+import org.apache.jena.sparql.engine.join.JoinKey ;
+
+public class TestHashJoin extends AbstractTestInnerJoin {
+
+    @Override
+    public QueryIterator join(JoinKey joinKey, Table left, Table right) {
+        Iterator<Binding> data = Join.hashJoin(joinKey, left.iterator(null), right.iterator(null), null) ;
+        QueryIterator qIter = new QueryIterPlainWrapper(data) ;
+        return qIter ;
+    }
+}

http://git-wip-us.apache.org/repos/asf/jena/blob/d4da1a5a/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TestJoinNestedLoop.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TestJoinNestedLoop.java b/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TestJoinNestedLoop.java
new file mode 100644
index 0000000..c844ea2
--- /dev/null
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TestJoinNestedLoop.java
@@ -0,0 +1,34 @@
+/**
+ * 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.engine.join;
+
+import org.apache.jena.sparql.algebra.Table ;
+import org.apache.jena.sparql.engine.QueryIterator ;
+import org.apache.jena.sparql.engine.join.Join ;
+import org.apache.jena.sparql.engine.join.JoinKey ;
+
+public class TestJoinNestedLoop extends AbstractTestInnerJoin {
+
+    @Override
+    public QueryIterator join(JoinKey joinKey, Table left, Table right) {
+        return Join.innerLoopJoin(left.iterator(null), right.iterator(null), null) ;
+    }
+
+}
+

http://git-wip-us.apache.org/repos/asf/jena/blob/d4da1a5a/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TestJoinNestedLoopSimple.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TestJoinNestedLoopSimple.java b/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TestJoinNestedLoopSimple.java
new file mode 100644
index 0000000..0d9db54
--- /dev/null
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TestJoinNestedLoopSimple.java
@@ -0,0 +1,34 @@
+/**
+ * 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.engine.join;
+
+import org.apache.jena.sparql.algebra.Table ;
+import org.apache.jena.sparql.engine.QueryIterator ;
+import org.apache.jena.sparql.engine.join.Join ;
+import org.apache.jena.sparql.engine.join.JoinKey ;
+
+public class TestJoinNestedLoopSimple extends AbstractTestInnerJoin {
+
+    @Override
+    public QueryIterator join(JoinKey joinKey, Table left, Table right) {
+        return Join.innerLoopJoinBasic(left.iterator(null), right.iterator(null), null) ;
+    }
+
+}
+

http://git-wip-us.apache.org/repos/asf/jena/blob/d4da1a5a/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TestJoinSimple.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TestJoinSimple.java b/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TestJoinSimple.java
new file mode 100644
index 0000000..d091168
--- /dev/null
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TestJoinSimple.java
@@ -0,0 +1,34 @@
+/**
+ * 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.engine.join;
+
+import org.apache.jena.sparql.algebra.Table ;
+import org.apache.jena.sparql.engine.QueryIterator ;
+import org.apache.jena.sparql.engine.join.JoinKey ;
+import org.apache.jena.sparql.engine.ref.TableJoin ;
+
+public class TestJoinSimple extends AbstractTestInnerJoin {
+
+    @Override
+    public QueryIterator join(JoinKey joinKey, Table left, Table right) {
+        return TableJoin.join(left.iterator(null), right, null, null) ;
+    }
+
+}
+

http://git-wip-us.apache.org/repos/asf/jena/blob/d4da1a5a/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TestLeftJoinSimple.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TestLeftJoinSimple.java b/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TestLeftJoinSimple.java
new file mode 100644
index 0000000..041dfe5
--- /dev/null
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/engine/join/TestLeftJoinSimple.java
@@ -0,0 +1,34 @@
+/**
+ * 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.engine.join;
+
+import org.apache.jena.sparql.algebra.Table ;
+import org.apache.jena.sparql.engine.QueryIterator ;
+import org.apache.jena.sparql.engine.join.JoinKey ;
+import org.apache.jena.sparql.engine.ref.TableJoin ;
+
+public class TestLeftJoinSimple extends AbstractTestLeftJoin {
+
+    @Override
+    public QueryIterator join(JoinKey joinKey, Table left, Table right) {
+        return TableJoin.leftJoin(left.iterator(null), right, null, null) ;
+    }
+
+}
+

http://git-wip-us.apache.org/repos/asf/jena/blob/d4da1a5a/jena-arq/src/test/java/org/apache/jena/sparql/join/AbstractTestJoin.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/join/AbstractTestJoin.java b/jena-arq/src/test/java/org/apache/jena/sparql/join/AbstractTestJoin.java
deleted file mode 100644
index a15d3e3..0000000
--- a/jena-arq/src/test/java/org/apache/jena/sparql/join/AbstractTestJoin.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/**
- * 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.join;
-
-import java.util.List ;
-
-import org.apache.jena.atlas.iterator.Iter ;
-import org.apache.jena.atlas.lib.StrUtils ;
-import org.apache.jena.query.ResultSet ;
-import org.apache.jena.query.ResultSetFactory ;
-import org.apache.jena.sparql.algebra.Table ;
-import org.apache.jena.sparql.algebra.TableFactory ;
-import org.apache.jena.sparql.core.Var ;
-import org.apache.jena.sparql.engine.QueryIterator ;
-import org.apache.jena.sparql.engine.binding.Binding ;
-import org.apache.jena.sparql.engine.join.JoinKey ;
-import org.apache.jena.sparql.resultset.ResultSetCompare ;
-import org.apache.jena.sparql.sse.SSE ;
-import org.junit.Assert ;
-import org.junit.Test ;
-
-public abstract class AbstractTestJoin extends Assert {
-    static Var var_a = Var.alloc("a") ; 
-    static Var var_b = Var.alloc("b") ; 
-    static Var var_c = Var.alloc("c") ; 
-    static Var var_d = Var.alloc("d") ; 
-
-    static Table table0() { return parseTableInt("(table)") ; } 
-
-    // For Mere, these must be in sort-joinkey order.
-
-    private static Table parseTableInt(String... strings) {
-        String x = StrUtils.strjoinNL(strings) ;
-        return SSE.parseTable(x) ;
-    }
-
-    // Table of one row and no colums.
-    static Table table1() { 
-        return parseTableInt("(table (row))") ; }
-
-    static Table tableD1() { 
-        return parseTableInt("(table", 
-                             "   (row (?a 1) (?b 2))",
-                             "   (row (?a 1) (?b 3))",
-                             "   (row (?a 1) (?b 2))",
-            ")") ;
-    }
-
-    static Table tableD2() { 
-        return parseTableInt("(table", 
-                             "   (row (?a 0) (?d 8))",
-                             "   (row (?a 1) (?c 9))",
-            ")") ;
-    }
-
-    static Table tableD3() {
-        return parseTableInt("(table", 
-                             "   (row (?a 1) (?c 9) (?b 2))",
-                             "   (row (?a 1) (?c 9) (?b 3))",
-                             "   (row (?a 1) (?c 9) (?b 2))",
-            ")") ;
-    }
-
-    static Table tableD4() {
-        return parseTableInt("(table", 
-                             "   (row (?a 1) (?b 2))",
-                             "   (row (?a 1) (?b 3))",
-                             "   (row (?a 4) (?b 4))",
-                             "   (row (?a 4) (?b 5))",
-            ")") ;
-    }
-
-    static Table tableD5() {
-        return parseTableInt("(table", 
-                             "   (row (?a 4) (?c 4))",
-                             "   (row (?a 4) (?c 5))",
-                             "   (row (?a 6) (?c 5))",
-            ")") ;
-    }
-
-    static Table tableD6() {
-        return parseTableInt("(table", 
-                             "   (row (?a 1) (?c 2))",
-                             "   (row (?a 1) (?c 3))",
-                             "   (row (?a 4) (?c 4))",
-                             "   (row (?a 4) (?c 5))",
-            ")") ;
-    }
-
-    static Table tableD4x5() {
-        return parseTableInt("(table", 
-                             "   (row (?a 4) (?c 4) (?b 4))",
-                             "   (row (?a 4) (?c 4) (?b 5))",
-                             "   (row (?a 4) (?c 5) (?b 4))",
-                             "   (row (?a 4) (?c 5) (?b 5))",
-            ")") ;
-    }
-
-    static Table tableD4x6() {
-        return parseTableInt("(table", 
-                             "   (row (?a 1) (?c 2) (?b 2))",
-                             "   (row (?a 1) (?c 2) (?b 3))",
-                             "   (row (?a 1) (?c 3) (?b 2))",
-                             "   (row (?a 1) (?c 3) (?b 3))",
-                             "   (row (?a 4) (?c 4) (?b 4))",
-                             "   (row (?a 4) (?c 4) (?b 5))",
-                             "   (row (?a 4) (?c 5) (?b 4))",
-                             "   (row (?a 4) (?c 5) (?b 5))",
-            ")") ;
-    }
-
-    // Disjoint.
-    static Table tableD8() {
-        return parseTableInt("(table",
-                             "  (row (?x 10))",
-                             "  (row (?z 11))",
-            ")") ; 
-    }
-
-    // Table8 crossproduct table2
-    static Table tableD8x2() {
-        return parseTableInt("(table",
-                             "  (row (?a 0) (?d 8) (?z 11))",
-                             "  (row (?a 0) (?d 8) (?x 10))",
-                             "  (row (?a 1) (?c 9) (?z 11))",
-                             "  (row (?a 1) (?c 9) (?x 10))",
-            ")") ;
-    }
-
-    @Test public void join_00()  { testJoin("a", table0(), table0(), table0()) ; }
-    @Test public void join_00a() { testJoin("a", table1(), table0(), table0()) ; }
-    @Test public void join_00b() { testJoin("a", tableD1(), table1(), tableD1()) ; }
-    @Test public void join_00c() { testJoin("z", tableD1(), table1(), tableD1()) ; }
-
-    @Test public void join_01() { testJoin("a", table0(), tableD2(), table0()) ; }
-    @Test public void join_02() { testJoin("a", tableD1(), table0(), table0()) ; }
-    @Test public void join_03() { testJoin("a", tableD1(), tableD2(), tableD3()) ; }
-
-    // Identity.
-    @Test public void join_04() { testJoin("a", tableD2(), table1(), tableD2()) ; }
-    @Test public void join_05() { testJoin("a", table1(), tableD2(), tableD2()) ; }
-    // Identity, keymiss
-    @Test public void join_06() { testJoin("z", table1(), tableD2(), tableD2()) ; }
-    @Test public void join_07() { testJoin("z", tableD2(), table1(), tableD2()) ; }
-
-    @Test public void join_08() { testJoin("a", tableD4(), tableD5(), tableD4x5()) ; }
-    @Test public void join_09() { testJoin("a", tableD5(), tableD4(), tableD4x5()) ; }
-
-    @Test public void join_10() { testJoin("a", tableD4(), tableD6(), tableD4x6()) ; }
-    @Test public void join_11() { testJoin("a", tableD6(), tableD4(), tableD4x6()) ; }
-
-    // Not the right join key - should still work albeit less efficiently.
-    @Test public void join_12() { testJoin("z", tableD1(), tableD2(), tableD3()) ; }
-    @Test public void join_13() { testJoin("z", tableD2(), tableD1(), tableD3()) ; }
-
-    // No key.
-    @Test public void join_14() { testJoin(null, tableD1(), tableD2(), tableD3()) ; }
-
-
-    // Disjoint tables.
-    @Test public void join_disjoint_01() { testJoin("a", tableD2(), tableD8(), tableD8x2()) ; }
-    @Test public void join_disjoint_02() { testJoin("z", tableD2(), tableD8(), tableD8x2()) ; }
-
-    private void testJoin(String var, Table left, Table right, Table tableOut) {
-        JoinKey joinKey ;
-        if ( var != null ) {
-            if ( var.startsWith("?") )
-                var = var.substring(1) ;
-            joinKey = JoinKey.create(Var.alloc(var)) ;
-        }
-        else {
-            // No vars in join key.  Legal, albeit silly.
-            joinKey = new JoinKey.Builder().build() ;
-        }
-
-        testJoin1("1", joinKey, left, right, tableOut) ;
-        // Commumute
-        testJoin1("2", joinKey, right, left, tableOut) ;
-    }
-
-    private List<Binding> toList(Table table) {
-        return Iter.toList(table.rows()) ;
-    }
-
-    private void testJoin1(String num, JoinKey joinKey, Table left, Table right, Table expectedResults) {
-        Table x1 = joinMaterialize(joinKey, left, right) ;
-        assertNotNull("Null table from join ("+num+")", x1) ;
-        check("Results not equal ("+num+")", joinKey, left, right, expectedResults, x1) ;
-    }
-
-    private Table joinMaterialize(JoinKey joinKey, Table left, Table right) {
-        QueryIterator qIter = join(joinKey , left , right) ;
-        return TableFactory.create(qIter) ;
-    }
-
-    public abstract QueryIterator join(JoinKey joinKey , Table left , Table right) ;
-
-    private static void check(String msg, JoinKey joinKey, Table left, Table right, Table expected, Table actual) {
-        boolean b = equalTables(expected, actual) ;
-        if ( ! b ) {
-            System.out.println("Joinkey:  "+joinKey) ;
-            System.out.println("Left:     "+left) ;
-            System.out.println("Right:    "+right) ;
-            System.out.println("Expected: "+expected) ;
-            System.out.println("Actual:   "+actual) ;
-            System.out.println() ;
-        }
-
-        assertTrue(msg, b) ;
-    }
-
-    private static boolean equalTables(Table table1, Table table2) {
-        ResultSet rs1 =  ResultSetFactory.create(table1.iterator(null), table1.getVarNames()) ;
-        ResultSet rs2 =  ResultSetFactory.create(table2.iterator(null), table2.getVarNames()) ;
-        return ResultSetCompare.equalsByTerm(rs1, rs2) ;
-    }
-
-}
-
-

http://git-wip-us.apache.org/repos/asf/jena/blob/d4da1a5a/jena-arq/src/test/java/org/apache/jena/sparql/join/TS_Join.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/join/TS_Join.java b/jena-arq/src/test/java/org/apache/jena/sparql/join/TS_Join.java
deleted file mode 100644
index 0a4c2a6..0000000
--- a/jena-arq/src/test/java/org/apache/jena/sparql/join/TS_Join.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * 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.join;
-
-import org.junit.runner.RunWith ;
-import org.junit.runners.Suite ;
-import org.junit.runners.Suite.SuiteClasses ;
-
-@RunWith(Suite.class)
-@SuiteClasses( {
-    TestJoinSimple.class
-    , TestJoinNestedLoopSimple.class    // Real simple materializing version.
-    , TestJoinNestedLoop.class
-    , TestHashJoin.class
-})
-
-public class TS_Join { }
-

http://git-wip-us.apache.org/repos/asf/jena/blob/d4da1a5a/jena-arq/src/test/java/org/apache/jena/sparql/join/TestHashJoin.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/join/TestHashJoin.java b/jena-arq/src/test/java/org/apache/jena/sparql/join/TestHashJoin.java
deleted file mode 100644
index 8358bc3..0000000
--- a/jena-arq/src/test/java/org/apache/jena/sparql/join/TestHashJoin.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * 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.join;
-
-import java.util.Iterator ;
-
-import org.apache.jena.sparql.algebra.Table ;
-import org.apache.jena.sparql.engine.QueryIterator ;
-import org.apache.jena.sparql.engine.binding.Binding ;
-import org.apache.jena.sparql.engine.iterator.QueryIterPlainWrapper ;
-import org.apache.jena.sparql.engine.join.Join ;
-import org.apache.jena.sparql.engine.join.JoinKey ;
-
-public class TestHashJoin extends AbstractTestJoin {
-
-    @Override
-    public QueryIterator join(JoinKey joinKey, Table left, Table right) {
-        Iterator<Binding> data = Join.hashJoin(joinKey, left.iterator(null), right.iterator(null), null) ;
-        QueryIterator qIter = new QueryIterPlainWrapper(data) ;
-        return qIter ;
-    }
-}

http://git-wip-us.apache.org/repos/asf/jena/blob/d4da1a5a/jena-arq/src/test/java/org/apache/jena/sparql/join/TestJoinNestedLoop.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/join/TestJoinNestedLoop.java b/jena-arq/src/test/java/org/apache/jena/sparql/join/TestJoinNestedLoop.java
deleted file mode 100644
index 4123c1c..0000000
--- a/jena-arq/src/test/java/org/apache/jena/sparql/join/TestJoinNestedLoop.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * 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.join;
-
-import org.apache.jena.sparql.algebra.Table ;
-import org.apache.jena.sparql.engine.QueryIterator ;
-import org.apache.jena.sparql.engine.join.Join ;
-import org.apache.jena.sparql.engine.join.JoinKey ;
-
-public class TestJoinNestedLoop extends AbstractTestJoin {
-
-    @Override
-    public QueryIterator join(JoinKey joinKey, Table left, Table right) {
-        return Join.innerLoopJoin(left.iterator(null), right.iterator(null), null) ;
-    }
-
-}
-

http://git-wip-us.apache.org/repos/asf/jena/blob/d4da1a5a/jena-arq/src/test/java/org/apache/jena/sparql/join/TestJoinNestedLoopSimple.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/join/TestJoinNestedLoopSimple.java b/jena-arq/src/test/java/org/apache/jena/sparql/join/TestJoinNestedLoopSimple.java
deleted file mode 100644
index ff56d13..0000000
--- a/jena-arq/src/test/java/org/apache/jena/sparql/join/TestJoinNestedLoopSimple.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * 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.join;
-
-import org.apache.jena.sparql.algebra.Table ;
-import org.apache.jena.sparql.engine.QueryIterator ;
-import org.apache.jena.sparql.engine.join.Join ;
-import org.apache.jena.sparql.engine.join.JoinKey ;
-
-public class TestJoinNestedLoopSimple extends AbstractTestJoin {
-
-    @Override
-    public QueryIterator join(JoinKey joinKey, Table left, Table right) {
-        return Join.innerLoopJoinBasic(left.iterator(null), right.iterator(null), null) ;
-    }
-
-}
-

http://git-wip-us.apache.org/repos/asf/jena/blob/d4da1a5a/jena-arq/src/test/java/org/apache/jena/sparql/join/TestJoinSimple.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/join/TestJoinSimple.java b/jena-arq/src/test/java/org/apache/jena/sparql/join/TestJoinSimple.java
deleted file mode 100644
index b7135cf..0000000
--- a/jena-arq/src/test/java/org/apache/jena/sparql/join/TestJoinSimple.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * 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.join;
-
-import org.apache.jena.sparql.algebra.Table ;
-import org.apache.jena.sparql.engine.QueryIterator ;
-import org.apache.jena.sparql.engine.TableJoin ;
-import org.apache.jena.sparql.engine.join.JoinKey ;
-
-public class TestJoinSimple extends AbstractTestJoin {
-
-    @Override
-    public QueryIterator join(JoinKey joinKey, Table left, Table right) {
-        return TableJoin.join(left.iterator(null), right, null, null) ;
-    }
-
-}
-