/** Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved. Contact: SYSTAP, LLC DBA Blazegraph 2501 Calvert ST NW #106 Washington, DC 20008 licenses@blazegraph.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Created on Oct 25, 2007 */ package com.bigdata.rdf.spo; import org.openrdf.model.Statement; import com.bigdata.bop.BOp; import com.bigdata.bop.Constant; import com.bigdata.bop.IPredicate; import com.bigdata.bop.NV; import com.bigdata.bop.Var; import com.bigdata.rdf.internal.IV; import com.bigdata.rdf.internal.VTE; import com.bigdata.rdf.model.BigdataURI; import com.bigdata.rdf.model.BigdataValueFactory; import com.bigdata.rdf.model.StatementEnum; import com.bigdata.rdf.rio.StatementBuffer; import com.bigdata.rdf.store.AbstractTripleStore; import com.bigdata.rdf.store.AbstractTripleStoreTestCase; import com.bigdata.rdf.store.TestTripleStore; import com.bigdata.relation.accesspath.AccessPath; import com.bigdata.relation.accesspath.IAccessPath; import com.bigdata.test.MockTermIdFactory; /** * Test suite for {@link SPOAccessPath}. * <p> * See also {@link TestTripleStore} which tests some of this stuff. * * FIXME write tests for SLICE with non-zero offset and non-zero LIMIT. * * FIXME write tests for SLICE where the maximum fully buffered limit is * exceeded so we are forced to use the asynchronous iterator on * {@link AccessPath}. * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> * @version $Id$ */ public class TestSPOAccessPath extends AbstractTripleStoreTestCase { /** * */ public TestSPOAccessPath() { super(); } /** * @param name */ public TestSPOAccessPath(String name) { super(name); } private MockTermIdFactory factory; protected void setUp() throws Exception { super.setUp(); factory = new MockTermIdFactory(); } protected void tearDown() throws Exception { super.tearDown(); factory = null; } /** * There are 8 distinct triple pattern bindings for a triple store that * select among 3 distinct access paths. */ public void test_getAccessPath() { final AbstractTripleStore store = getStore(); // constants used for s,p,o,c when bound. 0L used when unbound. final IV<?,?> S = factory.newTermId(VTE.URI, 1); final IV<?,?> P = factory.newTermId(VTE.URI, 2); final IV<?,?> O = factory.newTermId(VTE.URI, 3); final IV<?,?> C = factory.newTermId(VTE.URI, 4); final IV<?,?> _ = factory.newTermId(VTE.URI, 0); try { final SPORelation r = store.getSPORelation(); if (store.isQuads()) { /* * For a quad store there are 16 distinct binding patterns that * select among 6 distinct access paths. there are some quad * patterns which could be mapped onto more than one access * path, but the code here checks the expected mapping. These * mappings are similar to those in YARS2, but are the mappings * generated by the "Magic" tuple logic. */ // SPOC assertEquals(SPOKeyOrder.SPOC, r.getAccessPath(_, _, _, _).getKeyOrder()); assertEquals(SPOKeyOrder.SPOC, r.getAccessPath(S, _, _, _).getKeyOrder()); assertEquals(SPOKeyOrder.SPOC, r.getAccessPath(S, P, _, _).getKeyOrder()); assertEquals(SPOKeyOrder.SPOC, r.getAccessPath(S, P, O, _).getKeyOrder()); assertEquals(SPOKeyOrder.SPOC, r.getAccessPath(S, P, O, C).getKeyOrder()); // POCS assertEquals(SPOKeyOrder.POCS, r.getAccessPath(_, P, _, _).getKeyOrder()); assertEquals(SPOKeyOrder.POCS, r.getAccessPath(_, P, O, _).getKeyOrder()); assertEquals(SPOKeyOrder.POCS, r.getAccessPath(_, P, O, C).getKeyOrder()); // OCSP assertEquals(SPOKeyOrder.OCSP, r.getAccessPath(_, _, O, _).getKeyOrder()); assertEquals(SPOKeyOrder.OCSP, r.getAccessPath(_, _, O, C).getKeyOrder()); assertEquals(SPOKeyOrder.OCSP, r.getAccessPath(S, _, O, C).getKeyOrder()); // CSPO assertEquals(SPOKeyOrder.CSPO, r.getAccessPath(_, _, _, C).getKeyOrder()); assertEquals(SPOKeyOrder.CSPO, r.getAccessPath(S, _, _, C).getKeyOrder()); assertEquals(SPOKeyOrder.CSPO, r.getAccessPath(S, P, _, C).getKeyOrder()); // PCSO assertEquals(SPOKeyOrder.PCSO, r.getAccessPath(_, P, _, C).getKeyOrder()); // SOPC assertEquals(SPOKeyOrder.SOPC, r.getAccessPath(S, _, O, _).getKeyOrder()); } else { assertEquals(SPOKeyOrder.SPO, r.getAccessPath(NULL, NULL, NULL, NULL).getKeyOrder()); assertEquals(SPOKeyOrder.SPO, r.getAccessPath(S, NULL, NULL, NULL).getKeyOrder()); assertEquals(SPOKeyOrder.SPO, r.getAccessPath(S, S, NULL, NULL) .getKeyOrder()); assertEquals(SPOKeyOrder.SPO, r.getAccessPath(S, S, S, NULL) .getKeyOrder()); assertEquals(SPOKeyOrder.POS, r.getAccessPath(NULL, S, NULL, NULL).getKeyOrder()); assertEquals(SPOKeyOrder.POS, r.getAccessPath(NULL, S, S, NULL) .getKeyOrder()); assertEquals(SPOKeyOrder.OSP, r.getAccessPath(NULL, NULL, S, NULL).getKeyOrder()); assertEquals(SPOKeyOrder.OSP, r.getAccessPath(S, NULL, S, NULL) .getKeyOrder()); } } finally { store.__tearDownUnitTest(); } } /** * Unit test for predicate patterns in which the same variable appears in * more than one position of a triple pattern. The access path should * enforce a constraint to ensure that only elements having the same value * in each position for the same variable are visited by its iterator. * <p> * Note: This test applies to the triple store, provenance, and quad store * modes. */ public void test_sameVariableConstraint_triples() { final AbstractTripleStore store = getStore(); try { final BigdataValueFactory f = store.getValueFactory(); final BigdataURI s1 = f.createURI("http://www.bigdata.com/rdf#s1"); final BigdataURI s2 = f.createURI("http://www.bigdata.com/rdf#s2"); final BigdataURI p1 = f.createURI("http://www.bigdata.com/rdf#p1"); final BigdataURI o1 = f.createURI("http://www.bigdata.com/rdf#o1"); final BigdataURI p2 = f.createURI("http://www.bigdata.com/rdf#p2"); final BigdataURI o2 = f.createURI("http://www.bigdata.com/rdf#o2"); { final StatementBuffer<Statement> buffer = new StatementBuffer<Statement>( store, 10); buffer.add(s1, p1, o1); buffer.add(s1, s1, o1); buffer.add(s2, p2, o2); buffer.add(s1, p2, o2); buffer.flush(); } // no shared variable (?g, ?h, o1) { final SPOPredicate predicate = new SPOPredicate(// store.getSPORelation().getNamespace(),// Var.var("g"), // s Var.var("h"), // p new Constant<IV>(o1.getIV()) // o ); final IAccessPath<ISPO> accessPath = store.getSPORelation() .getAccessPath(predicate); assertSameSPOs(new ISPO[] { // FIXME TERMS REFACTOR FAILS HERE new SPO(s1.getIV(), p1.getIV(), o1 .getIV(), StatementEnum.Explicit),// new SPO(s1.getIV(), s1.getIV(), o1 .getIV(), StatementEnum.Explicit),// }, accessPath.iterator()); } // shared 'g' variable (?g, ?g, o1) { final SPOPredicate predicate = new SPOPredicate(// store.getSPORelation().getNamespace(),// Var.var("g"), // s Var.var("g"), // s new Constant<IV>(o1.getIV()) // o ); final IAccessPath<ISPO> accessPath = store.getSPORelation() .getAccessPath(predicate); assertSameSPOs(new ISPO[] { // new SPO(s1.getIV(), s1.getIV(), o1.getIV(), StatementEnum.Explicit),// }, accessPath.iterator()); } } finally { store.__tearDownUnitTest(); } } /** * Unit test for predicate patterns in which the same variable appears in * more than one position of a quad pattern. The access path should enforce * a constraint to ensure that only elements having the same value in each * position for the same variable are visited by its iterator. * <p> * Note: This test only applies to the quad store mode. * <p> * Note: In the provenance mode, it is impossible for a statement to use its * own statement identifier in any position other than the quad position. * Therefore any access path which was constrained such that s, p, or o used * shared a variable with c would result in an empty access path in the * data. */ public void test_sameVariableConstraint_quads() { final AbstractTripleStore store = getStore(); try { if(!store.isQuads()) { /* * @todo modify test to work for triple store also? This is easy * enough to do with an (s,p,o) predicate in which s and o are * or s and p bound to the same variable. */ log.warn("Unit test requires quads."); return; } final BigdataValueFactory f = store.getValueFactory(); final BigdataURI graphA = f.createURI("http://www.bigdata.com/graphA"); final BigdataURI graphB = f.createURI("http://www.bigdata.com/graphB"); final BigdataURI s = f.createURI("http://www.bigdata.com/rdf#s"); final BigdataURI p1 = f.createURI("http://www.bigdata.com/rdf#p1"); final BigdataURI o1 = f.createURI("http://www.bigdata.com/rdf#o1"); final BigdataURI p2 = f.createURI("http://www.bigdata.com/rdf#p2"); final BigdataURI o2 = f.createURI("http://www.bigdata.com/rdf#o2"); { final StatementBuffer<Statement> buffer = new StatementBuffer<Statement>( store, 10); buffer.add(graphA, p1, o1, graphA); buffer.add(graphA, p2, o2, graphA); buffer.add(s, p1, o1, graphA); buffer.add(s, p2, o2, graphB); buffer.flush(); } // no shared variable (?g, p1, o1, ?h) { final SPOPredicate predicate = new SPOPredicate(// new BOp[] { Var.var("g"), // s new Constant<IV>(p1.getIV()), // p new Constant<IV>(o1.getIV()), // o Var.var("h") // c }, new NV(IPredicate.Annotations.RELATION_NAME, new String[] { store.getSPORelation() .getNamespace() // })); final IAccessPath<ISPO> accessPath = store.getSPORelation() .getAccessPath(predicate); assertSameSPOs(new ISPO[] { // new SPO(graphA.getIV(), p1.getIV(), o1 .getIV(), graphA.getIV(), StatementEnum.Explicit),// new SPO(s.getIV(), p1.getIV(), o1 .getIV(), graphA.getIV(), StatementEnum.Explicit),// }, accessPath.iterator()); } // shared 'g' variable (?g, p1, o1, ?g) { final SPOPredicate predicate = new SPOPredicate(// new BOp[] { Var.var("g"), // s new Constant<IV>(p1.getIV()), // p new Constant<IV>(o1.getIV()), // o Var.var("g") // c }, new NV(IPredicate.Annotations.RELATION_NAME, new String[] { store.getSPORelation() .getNamespace() })); final IAccessPath<ISPO> accessPath = store.getSPORelation() .getAccessPath(predicate); assertSameSPOs(new ISPO[] { // new SPO(graphA.getIV(), p1.getIV(), o1 .getIV(), graphA.getIV(), StatementEnum.Explicit),// }, accessPath.iterator()); } } finally { store.__tearDownUnitTest(); } } /** * @todo write tests of slice where offset=0, offset>0. test with limit at * fence posts (0,1) and with limit GT the maximum that can be fully * buffered. verify stable result sets by using a slice to page * through the results. */ public void test_slice() { // fail("write tests"); } }