/** 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 Aug 19, 2010 */ package com.bigdata.bop.solutions; import java.util.Properties; import java.util.UUID; import java.util.concurrent.FutureTask; import junit.framework.TestCase2; import com.bigdata.bop.BOp; import com.bigdata.bop.BOpContext; import com.bigdata.bop.BOpEvaluationContext; import com.bigdata.bop.Bind; import com.bigdata.bop.Constant; import com.bigdata.bop.IBindingSet; import com.bigdata.bop.IConstant; import com.bigdata.bop.IQueryContext; import com.bigdata.bop.IVariable; import com.bigdata.bop.NV; import com.bigdata.bop.PipelineOp; import com.bigdata.bop.Var; import com.bigdata.bop.bindingSet.ListBindingSet; import com.bigdata.bop.engine.AbstractQueryEngineTestCase; import com.bigdata.bop.engine.BOpStats; import com.bigdata.bop.engine.BlockingBufferWithStats; import com.bigdata.bop.engine.IRunningQuery; import com.bigdata.bop.engine.MockRunningQuery; import com.bigdata.journal.BufferMode; import com.bigdata.journal.ITx; import com.bigdata.journal.Journal; import com.bigdata.rdf.internal.IV; import com.bigdata.rdf.internal.VTE; import com.bigdata.rdf.internal.constraints.MathBOp; import com.bigdata.rdf.internal.impl.TermId; import com.bigdata.rdf.internal.impl.literal.XSDNumericIV; import com.bigdata.rdf.model.BigdataLiteral; import com.bigdata.rdf.model.BigdataValueFactory; import com.bigdata.rdf.model.BigdataValueFactoryImpl; import com.bigdata.rdf.sparql.ast.GlobalAnnotations; import com.bigdata.rdf.store.AbstractTripleStore; import com.bigdata.rdf.store.LocalTripleStore; import com.bigdata.relation.accesspath.IAsynchronousIterator; import com.bigdata.relation.accesspath.IBlockingBuffer; import com.bigdata.relation.accesspath.ThickAsynchronousIterator; /** * Unit tests for the {@link MemorySortOp}. * <p> * The test suite for the {@link IVComparator} is responsible for testing the * ability to compare inline and non-inline {@link IV}s, placing them into an * order which is not inconsistent with the SPARQL ORDER BY semantics. * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> * @version $Id$ */ public class TestMemorySortOp extends TestCase2 { /** * */ public TestMemorySortOp() { } /** * @param name */ public TestMemorySortOp(String name) { super(name); } private long termId = 1; private IV<BigdataLiteral, ?> makeIV(final BigdataLiteral lit) { final IV<BigdataLiteral, ?> iv = new TermId<BigdataLiteral>( VTE.LITERAL, termId++); iv.setValue(lit); return iv; } /** * Test with materialized IVs. */ @SuppressWarnings({ "rawtypes", "unchecked" }) public void testMaterializedIVs() { final BigdataValueFactory f = BigdataValueFactoryImpl.getInstance(getName()); final IVariable<IV> x = Var.var ( "x" ) ; final IVariable<IV> y = Var.var ( "y" ) ; final IConstant<IV> a = new Constant<IV>(makeIV(f.createLiteral("a"))); final IConstant<IV> b = new Constant<IV>(makeIV(f.createLiteral("b"))); final IConstant<IV> c = new Constant<IV>(makeIV(f.createLiteral("c"))); final IConstant<IV> d = new Constant<IV>(makeIV(f.createLiteral("d"))); final IConstant<IV> e = new Constant<IV>(makeIV(f.createLiteral("e"))); final ISortOrder<?> sors[] = new ISortOrder[] { // new SortOrder(x, true/*asc*/),// new SortOrder(y, false/*asc*/)// }; final int sortOpId = 1; final SortOp query = new MemorySortOp(new BOp[] {}, NV.asMap(new NV[] {// new NV(MemorySortOp.Annotations.BOP_ID, sortOpId),// new NV(MemorySortOp.Annotations.SORT_ORDER,sors),// new NV(MemorySortOp.Annotations.VALUE_COMPARATOR, new IVComparator()),// new NV(SliceOp.Annotations.EVALUATION_CONTEXT, BOpEvaluationContext.CONTROLLER),// new NV(MemorySortOp.Annotations.MAX_PARALLEL, 1),// new NV(PipelineOp.Annotations.REORDER_SOLUTIONS,false),// // new NV(MemorySortOp.Annotations.SHARED_STATE, true),// new NV(MemorySortOp.Annotations.LAST_PASS, true),// })); // // the test data // final IBindingSet data [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { a, a } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { a, e } ) , new ListBindingSet ( new IVariable<?> [] { x }, new IConstant [] { c } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { d, a } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { d, b } ) , new ListBindingSet ( new IVariable<?> [] {}, new IConstant [] {} ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { a, c } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { b, d } ) , new ListBindingSet ( new IVariable<?> [] { y }, new IConstant [] { a } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { b, b } ) } ; // // the expected solutions // final IBindingSet expected [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { y }, new IConstant [] { a } ) , new ListBindingSet ( new IVariable<?> [] {}, new IConstant [] {} ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { a, e } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { a, c } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { a, a } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { b, d } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { b, b } ) , new ListBindingSet ( new IVariable<?> [] { x }, new IConstant [] { c } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { d, b } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { d, a } ) } ; final BOpStats stats = query.newStats(); final IAsynchronousIterator<IBindingSet[]> source = new ThickAsynchronousIterator<IBindingSet[]>( new IBindingSet[][] { data }); final IBlockingBuffer<IBindingSet[]> sink = new BlockingBufferWithStats<IBindingSet[]>( query, stats); final UUID queryId = UUID.randomUUID(); final IQueryContext queryContext = new MockQueryContext(queryId); final IRunningQuery runningQuery = new MockRunningQuery(null/* fed */ , null/* indexManager */,queryContext ); final BOpContext<IBindingSet> context = new BOpContext<IBindingSet>( runningQuery, -1/* partitionId */ , stats, query/* op */, true/* lastInvocation */, source, sink, null/* sink2 */ ); // context.setLastInvocation(); final FutureTask<Void> ft = query.eval(context); // Run the query. { final Thread t = new Thread() { public void run() { ft.run(); } }; t.setDaemon(true); t.start(); } // Check the solutions. AbstractQueryEngineTestCase.assertSameSolutions(expected, sink.iterator(), ft); assertEquals ( 1, stats.chunksIn.get () ) ; assertEquals ( 10, stats.unitsIn.get () ) ; assertEquals ( 10, stats.unitsOut.get () ) ; assertEquals ( 1, stats.chunksOut.get () ) ; } /** * Unit test with inline {@link IV}. */ @SuppressWarnings({ "rawtypes", "unchecked" }) public void testInlineIVs() { final BigdataValueFactory f = BigdataValueFactoryImpl.getInstance(getName()); final IVariable<IV> x = Var.var ( "x" ) ; final IVariable<IV> y = Var.var ( "y" ) ; final IConstant<IV> a = new Constant<IV>(new XSDNumericIV(1)); final IConstant<IV> b = new Constant<IV>(new XSDNumericIV(2)); final IConstant<IV> c = new Constant<IV>(new XSDNumericIV(3)); final IConstant<IV> d = new Constant<IV>(new XSDNumericIV(4)); final IConstant<IV> e = new Constant<IV>(new XSDNumericIV(5)); final ISortOrder<?> sors[] = new ISortOrder[] { // new SortOrder(x, true/*asc*/),// new SortOrder(y, false/*asc*/)// }; final int sortOpId = 1; final SortOp query = new MemorySortOp(new BOp[] {}, NV.asMap(new NV[] { new NV(MemorySortOp.Annotations.BOP_ID, sortOpId), new NV(MemorySortOp.Annotations.SORT_ORDER,sors),// new NV(MemorySortOp.Annotations.VALUE_COMPARATOR, new IVComparator()),// new NV(SliceOp.Annotations.EVALUATION_CONTEXT, BOpEvaluationContext.CONTROLLER),// new NV(MemorySortOp.Annotations.MAX_PARALLEL, 1),// new NV(PipelineOp.Annotations.REORDER_SOLUTIONS,false),// // new NV(MemorySortOp.Annotations.SHARED_STATE, true),// new NV(MemorySortOp.Annotations.LAST_PASS, true),// })); // // the test data // final IBindingSet data [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { a, a } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { a, e } ) , new ListBindingSet ( new IVariable<?> [] { x }, new IConstant [] { c } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { d, a } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { d, b } ) , new ListBindingSet ( new IVariable<?> [] {}, new IConstant [] {} ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { a, c } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { b, d } ) , new ListBindingSet ( new IVariable<?> [] { y }, new IConstant [] { a } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { b, b } ) } ; // // the expected solutions // final IBindingSet expected [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { y }, new IConstant [] { a } ) , new ListBindingSet ( new IVariable<?> [] {}, new IConstant [] {} ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { a, e } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { a, c } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { a, a } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { b, d } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { b, b } ) , new ListBindingSet ( new IVariable<?> [] { x }, new IConstant [] { c } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { d, b } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { d, a } ) } ; final BOpStats stats = query.newStats () ; final IAsynchronousIterator<IBindingSet[]> source = new ThickAsynchronousIterator<IBindingSet[]>( new IBindingSet[][] { data }); final IBlockingBuffer<IBindingSet[]> sink = new BlockingBufferWithStats<IBindingSet[]>( query, stats); final UUID queryId = UUID.randomUUID(); final IQueryContext queryContext = new MockQueryContext(queryId); final IRunningQuery runningQuery = new MockRunningQuery(null/* fed */ , null/* indexManager */,queryContext ); final BOpContext<IBindingSet> context = new BOpContext<IBindingSet>( runningQuery, -1/* partitionId */ , stats, query/* op */, true/* lastInvocation */, source, sink, null/* sink2 */ ); // context.setLastInvocation(); final FutureTask<Void> ft = query.eval(context); // Run the query. { final Thread t = new Thread() { public void run() { ft.run(); } }; t.setDaemon(true); t.start(); } // Check the solutions. AbstractQueryEngineTestCase.assertSameSolutions(expected, sink.iterator(), ft); assertEquals ( 1, stats.chunksIn.get () ) ; assertEquals ( 10, stats.unitsIn.get () ) ; assertEquals ( 10, stats.unitsOut.get () ) ; assertEquals ( 1, stats.chunksOut.get () ) ; } /** * Test with computed value expressions. * <p> * Note: Since there are some unbound values for the base variables, * solutions in which those variables are not bound will cause type errors. * Unless the value expressions are evaluated before we sort the solutions * those type errors will propagate out of the sort and fail the query. * Correct treatment is to treat the type errors as unbound variables * see trac-765 */ @SuppressWarnings({ "rawtypes", "unchecked" }) public void testComputedValueExpressions() { final String namespace = getName(); final String lexiconNamespace; final Properties properties = new Properties(); properties.setProperty(com.bigdata.journal.Options.BUFFER_MODE,BufferMode.MemStore.name()); final Journal store = new Journal(properties); try { { final AbstractTripleStore kb = new LocalTripleStore(store, namespace, ITx.UNISOLATED, properties); kb.create(); store.commit(); lexiconNamespace = kb.getLexiconRelation().getNamespace(); } final IVariable<IV> x = Var.var("x"); final IVariable<IV> y = Var.var("y"); final IVariable<IV> z = Var.var("z"); final IConstant<IV> _1 = new Constant<IV>(new XSDNumericIV(1)); final IConstant<IV> _2 = new Constant<IV>(new XSDNumericIV(2)); final IConstant<IV> _3 = new Constant<IV>(new XSDNumericIV(3)); final IConstant<IV> _4 = new Constant<IV>(new XSDNumericIV(4)); final IConstant<IV> _5 = new Constant<IV>(new XSDNumericIV(5)); final ISortOrder<?> sors[] = new ISortOrder[] { // new SortOrder(new Bind(z,new MathBOp(x, y, MathBOp.MathOp.PLUS,new GlobalAnnotations(lexiconNamespace, ITx.READ_COMMITTED))), false/* asc */),// new SortOrder(y, false/* asc */), // new SortOrder(x, true/* asc */), // }; final int sortOpId = 1; final SortOp query = new MemorySortOp(new BOp[] {}, NV.asMap(new NV[] { new NV(MemorySortOp.Annotations.BOP_ID, sortOpId), new NV(MemorySortOp.Annotations.SORT_ORDER,sors),// new NV(MemorySortOp.Annotations.VALUE_COMPARATOR, new IVComparator()),// new NV(SliceOp.Annotations.EVALUATION_CONTEXT, BOpEvaluationContext.CONTROLLER),// new NV(MemorySortOp.Annotations.MAX_PARALLEL, 1),// new NV(PipelineOp.Annotations.REORDER_SOLUTIONS,false),// // new NV(MemorySortOp.Annotations.SHARED_STATE, true),// new NV(MemorySortOp.Annotations.LAST_PASS, true),// })); // // the test data // final IBindingSet data [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { _1, _1 } ) // x+y=2 , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { _1, _5 } ) // x+y=6 , new ListBindingSet ( new IVariable<?> [] { x }, new IConstant [] { _3 } ) // x+y=N/A , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { _4, _1 } ) // x+y=5 , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { _4, _2 } ) // x+y=6 , new ListBindingSet ( new IVariable<?> [] {}, new IConstant [] {} ) // x+y=N/A , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { _1, _3 } ) // x+y=4 , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { _2, _4 } ) // x+y=6 , new ListBindingSet ( new IVariable<?> [] { y }, new IConstant [] { _1 } ) // x+y=N/A , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { _2, _2 } ) // x+y=4 } ; // // the expected solutions // final IBindingSet expected [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { _1, _5 } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { _2, _4 } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { _4, _2 } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { _4, _1 } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { _1, _3 } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { _2, _2 } ) , new ListBindingSet ( new IVariable<?> [] { x, y }, new IConstant [] { _1, _1 } ) , new ListBindingSet ( new IVariable<?> [] { y }, new IConstant [] { _1 } ) // type error. , new ListBindingSet ( new IVariable<?> [] {}, new IConstant [] {} ) // type error. , new ListBindingSet ( new IVariable<?> [] { x }, new IConstant [] { _3 } ) // type error. } ; final BOpStats stats = query.newStats () ; final IAsynchronousIterator<IBindingSet[]> source = new ThickAsynchronousIterator<IBindingSet[]>( new IBindingSet[][] { data }); final IBlockingBuffer<IBindingSet[]> sink = new BlockingBufferWithStats<IBindingSet[]>( query, stats); final UUID queryId = UUID.randomUUID(); final IQueryContext queryContext = new MockQueryContext(queryId); final IRunningQuery runningQuery = new MockRunningQuery(null/* fed */ , store/* indexManager */,queryContext ); final BOpContext<IBindingSet> context = new BOpContext<IBindingSet>( runningQuery, -1/* partitionId */ , stats, query/* op */, true/* lastInvocation */, source, sink, null/* sink2 */ ); // context.setLastInvocation(); final FutureTask<Void> ft = query.eval(context); // Run the query. { final Thread t = new Thread() { public void run() { ft.run(); } }; t.setDaemon(true); t.start(); } // Check the solutions. AbstractQueryEngineTestCase.assertSameSolutions(expected, sink.iterator(), ft); assertEquals ( 1, stats.chunksIn.get () ) ; assertEquals ( 10, stats.unitsIn.get () ) ; assertEquals ( 10, stats.unitsOut.get () ) ; assertEquals(1, stats.chunksOut.get()); } finally { store.destroy(); } } }