/** 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 2, 2011 */ package com.bigdata.bop.solutions; import java.math.BigInteger; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; import junit.framework.TestCase2; import org.openrdf.query.algebra.Compare.CompareOp; import com.bigdata.bop.BOpContext; import com.bigdata.bop.Bind; import com.bigdata.bop.Constant; import com.bigdata.bop.IBindingSet; import com.bigdata.bop.IConstant; import com.bigdata.bop.IConstraint; import com.bigdata.bop.IQueryContext; import com.bigdata.bop.IValueExpression; import com.bigdata.bop.IVariable; import com.bigdata.bop.IVariableFactory; import com.bigdata.bop.TestMockUtility; 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.bop.rdf.aggregate.COUNT; import com.bigdata.bop.rdf.aggregate.SAMPLE; import com.bigdata.bop.rdf.aggregate.SUM; import com.bigdata.journal.ITx; import com.bigdata.rdf.internal.IV; import com.bigdata.rdf.internal.VTE; import com.bigdata.rdf.internal.constraints.CompareBOp; import com.bigdata.rdf.internal.constraints.MathBOp; import com.bigdata.rdf.internal.constraints.SPARQLConstraint; import com.bigdata.rdf.internal.impl.TermId; import com.bigdata.rdf.internal.impl.literal.XSDBooleanIV; import com.bigdata.rdf.internal.impl.literal.XSDIntegerIV; import com.bigdata.rdf.internal.impl.literal.XSDNumericIV; import com.bigdata.rdf.model.BigdataLiteral; import com.bigdata.rdf.model.BigdataValue; 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.relation.accesspath.IAsynchronousIterator; import com.bigdata.relation.accesspath.IBlockingBuffer; import com.bigdata.relation.accesspath.ThickAsynchronousIterator; import com.bigdata.rwstore.sector.IMemoryManager; import static junit.framework.TestCase.assertEquals; /** * Abstract base class for testing {@link GroupByOp} operator implementations. * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> * @version $Id$ */ abstract public class AbstractAggregationTestCase extends TestCase2 { /** * */ public AbstractAggregationTestCase() { } /** * @param name */ public AbstractAggregationTestCase(String name) { super(name); } protected void setUp() throws Exception { super.setUp(); final UUID queryId = null; queryContext = new MockQueryContext(queryId); } protected void tearDown() throws Exception { final IMemoryManager mmgr = queryContext.getMemoryManager(); if (mmgr != null) { mmgr.clear(); } super.tearDown(); } /** * Provides sequential, predictable, and easily read variable names. */ protected static class MockVariableFactory implements IVariableFactory { int i = 0; public IVariable<?> var() { return Var.var("_" + i++); } } /** * The {@link IQueryContext} - operators which require access to the * {@link IMemoryManager} MUST explicitly setup and tear down this field. */ protected IQueryContext queryContext = null; /** * Factory for {@link GroupByOp} to be tested. * * @param select * The SELECT clause. * @param groupBy * The optional GROUP BY clause. * @param having * The optional HAVING clause. * * @return The {@link GroupByOp} to be tested. */ abstract protected GroupByOp newFixture(final IValueExpression<?>[] select, final IValueExpression<?>[] groupBy, final IConstraint[] having); /** * Return <code>true</code> iff the fixture will be a pipelined aggregation * operator as defined by {@link GroupByOp#isPipelinedAggregationOp()}. This * is used to conditionally modify the behavior of certain tests to verify * correct rejection rather of aggregation requests which can not be handled * by a pipelined aggregation operator. */ abstract protected boolean isPipelinedAggregationOp(); /** * Unit test of SELECT expression which projects a variable projected by a * GROUP_BY expression. * * <pre> * SELECT ?org GROUP BY ?org * </pre> */ public void test_aggregation_select_projects_group_by_variable() { final IVariable<?> org = Var.var("org"); final IConstant<String> org1 = new Constant<String>("org1"); final IConstant<String> org2 = new Constant<String>("org2"); final GroupByOp query = newFixture(// new IValueExpression[] { org }, // select new IValueExpression[] { org }, // groupBy null // having. ); /** * The test data: * * <pre> * ?org * org1 * org1 * org1 * org2 * </pre> */ final IBindingSet data [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { org }, new IConstant [] { org1 } ) , new ListBindingSet ( new IVariable<?> [] { org }, new IConstant [] { org1 } ) , new ListBindingSet ( new IVariable<?> [] { org }, new IConstant [] { org1 } ) , new ListBindingSet ( new IVariable<?> [] { org }, new IConstant [] { org2 } ) }; /** * The expected solutions: * * <pre> * ?org * org1 * org2 * </pre> */ final IBindingSet expected [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { org }, new IConstant [] { org1 } ) , new ListBindingSet ( new IVariable<?> [] { org }, new IConstant [] { org2 } ) } ; 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 IRunningQuery runningQuery = new MockRunningQuery(null/* fed */ , null/* indexManager */, queryContext ); // Note: [lastInvocation:=true] forces the solutions to be emitted. final BOpContext<IBindingSet> context = new BOpContext<IBindingSet>( runningQuery, -1/* partitionId */ , stats, query, true/* lastInvocation */, source, sink, null/* sink2 */ ); // // Force the solutions to be emitted. // 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.assertSameSolutionsAnyOrder(expected, sink.iterator(), ft); assertEquals(1, stats.chunksIn.get()); assertEquals(4, stats.unitsIn.get()); assertEquals(2, stats.unitsOut.get()); assertEquals(1, stats.chunksOut.get()); } /** * Unit test of SELECT expression which projects a variable projected by a * GROUP_BY expression. * * <pre> * SELECT ?org as ?newVar * GROUP BY ?org * </pre> */ public void test_aggregation_select_projects_group_by_value_expression_as_variable() { final IVariable<?> org = Var.var("org"); final IVariable<?> newVar = Var.var("newVar"); final IConstant<String> org1 = new Constant<String>("org1"); final IConstant<String> org2 = new Constant<String>("org2"); final GroupByOp query = newFixture(// new IValueExpression[] { new Bind(newVar,org) }, // select new IValueExpression[] { org }, // groupBy null // having. ); /** * The test data: * * <pre> * ?org * org1 * org1 * org1 * org2 * </pre> */ final IBindingSet data [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { org }, new IConstant [] { org1 } ) , new ListBindingSet ( new IVariable<?> [] { org }, new IConstant [] { org1 } ) , new ListBindingSet ( new IVariable<?> [] { org }, new IConstant [] { org1 } ) , new ListBindingSet ( new IVariable<?> [] { org }, new IConstant [] { org2 } ) }; /** * The expected solutions: * * <pre> * ?newVar * org1 * org2 * </pre> */ final IBindingSet expected [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { newVar }, new IConstant [] { org1 } ) , new ListBindingSet ( new IVariable<?> [] { newVar }, new IConstant [] { org2 } ) } ; 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 IRunningQuery runningQuery = new MockRunningQuery(null/* fed */ , null/* indexManager */, queryContext ); // Note: [lastInvocation:=true] forces the solutions to be emitted. final BOpContext<IBindingSet> context = new BOpContext<IBindingSet>( runningQuery, -1/* partitionId */ , stats, query/* op */, true/* lastInvocation */, source, sink, null/* sink2 */ ); // // Force the solutions to be emitted. // 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.assertSameSolutionsAnyOrder(expected, sink.iterator(), ft); assertEquals(1, stats.chunksIn.get()); assertEquals(4, stats.unitsIn.get()); assertEquals(2, stats.unitsOut.get()); assertEquals(1, stats.chunksOut.get()); } /** * Based on an example in the SPARQL 1.1 Working Draft. * * <pre> * @prefix : <http://books.example/> . * * :org1 :affiliates :auth1, :auth2 . * :auth1 :writesBook :book1, :book2 . * :book1 :price 9 . * :book2 :price 5 . * :auth2 :writesBook :book3 . * :book3 :price 7 . * :org2 :affiliates :auth3 . * :auth3 :writesBook :book4 . * :book4 :price 7 . * </pre> * * <pre> * PREFIX : <http://books.example/> * SELECT ?org, (SUM(?lprice) AS ?totalPrice) * WHERE { * ?org :affiliates ?auth . * ?auth :writesBook ?book . * ?book :price ?lprice . * } * GROUP BY ?org * </pre> * * The solutions input to the GROUP_BY are: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org2 auth3 book4 7 * </pre> * * The aggregated solutions groups are: * * <pre> * ?org ?totalPrice * org1 21 * org2 7 * </pre> * * @throws ExecutionException * @throws InterruptedException */ public void test_aggregation_groupBy_with_aggregate() { final IVariable<?> org = Var.var("org"); final IVariable<?> auth = Var.var("auth"); final IVariable<?> book = Var.var("book"); final IVariable<?> lprice = Var.var("lprice"); final IVariable<?> totalPrice = Var.var("totalPrice"); final IConstant<String> org1 = new Constant<String>("org1"); final IConstant<String> org2 = new Constant<String>("org2"); final IConstant<String> auth1 = new Constant<String>("auth1"); final IConstant<String> auth2 = new Constant<String>("auth2"); final IConstant<String> auth3 = new Constant<String>("auth3"); final IConstant<String> book1 = new Constant<String>("book1"); final IConstant<String> book2 = new Constant<String>("book2"); final IConstant<String> book3 = new Constant<String>("book3"); final IConstant<String> book4 = new Constant<String>("book4"); final IConstant<XSDNumericIV<BigdataLiteral>> price5 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(5)); final IConstant<XSDNumericIV<BigdataLiteral>> price7 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(7)); final IConstant<XSDNumericIV<BigdataLiteral>> price9 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(9)); final IValueExpression<?> totalPriceExpr = new Bind(totalPrice, new SUM(false/* distinct */, (IValueExpression<IV>) lprice)); final GroupByOp query = newFixture(// new IValueExpression[] { org, totalPriceExpr }, // select new IValueExpression[] { org }, // groupBy null // having ); /** * The test data: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org2 auth3 book4 7 * </pre> */ final IBindingSet data [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book1, price9 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book2, price5 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth2, book3, price7 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org2, auth3, book4, price7 } ) }; /** * The expected solutions: * * <pre> * ?org ?totalPrice * org1 21 * org2 7 * </pre> */ // Note: The aggregates will have gone through type promotion. final IConstant<XSDIntegerIV<BigdataLiteral>> _price7 = new Constant<XSDIntegerIV<BigdataLiteral>>( new XSDIntegerIV<BigdataLiteral>(BigInteger.valueOf(7))); final IConstant<XSDIntegerIV<BigdataLiteral>> _price21 = new Constant<XSDIntegerIV<BigdataLiteral>>( new XSDIntegerIV<BigdataLiteral>(BigInteger.valueOf(21))); final IBindingSet expected[] = new IBindingSet[] { new ListBindingSet ( new IVariable<?> [] { org, totalPrice }, new IConstant [] { org1, _price21 } ) , new ListBindingSet ( new IVariable<?> [] { org, totalPrice }, new IConstant [] { org2, _price7 } ) } ; 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 IRunningQuery runningQuery = new MockRunningQuery(null/* fed */ , null/* indexManager */, queryContext ); // Note: [lastInvocation:=true] forces the solutions to be emitted. final BOpContext<IBindingSet> context = new BOpContext<IBindingSet>( runningQuery, -1/* partitionId */ , stats, query/* op */, true/* lastInvocation */, source, sink, null/* sink2 */ ); // // Force the solutions to be emitted. // 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.assertSameSolutionsAnyOrder(expected, sink.iterator(), ft); assertEquals(1, stats.chunksIn.get()); assertEquals(4, stats.unitsIn.get()); assertEquals(2, stats.unitsOut.get()); assertEquals(1, stats.chunksOut.get()); } /** * Based on an example in the SPARQL 1.1 Working Draft. * * <pre> * @prefix : <http://books.example/> . * * :org1 :affiliates :auth1, :auth2 . * :auth1 :writesBook :book1, :book2 . * :book1 :price 9 . * :book2 :price 5 . * :auth2 :writesBook :book3 . * :book3 :price 7 . * :org2 :affiliates :auth3 . * :auth3 :writesBook :book4 . * :book4 :price 7 . * </pre> * * <pre> * PREFIX : <http://books.example/> * SELECT ?org, (SUM(?lprice) AS ?totalPrice), 12 as ?z * WHERE { * ?org :affiliates ?auth . * ?auth :writesBook ?book . * ?book :price ?lprice . * } * GROUP BY ?org * </pre> * * The solutions input to the GROUP_BY are: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org2 auth3 book4 7 * </pre> * * The aggregated solutions groups are: * * <pre> * ?org ?totalPrice ?z * org1 21 12 * org2 7 12 * </pre> * * @throws ExecutionException * @throws InterruptedException */ public void test_aggregation_groupBy_with_aggregate_and_projected_constant() { final IVariable<?> org = Var.var("org"); final IVariable<?> auth = Var.var("auth"); final IVariable<?> book = Var.var("book"); final IVariable<?> lprice = Var.var("lprice"); final IVariable<?> totalPrice = Var.var("totalPrice"); final IVariable<?> z = Var.var("z"); final IConstant<String> org1 = new Constant<String>("org1"); final IConstant<String> org2 = new Constant<String>("org2"); final IConstant<String> auth1 = new Constant<String>("auth1"); final IConstant<String> auth2 = new Constant<String>("auth2"); final IConstant<String> auth3 = new Constant<String>("auth3"); final IConstant<String> book1 = new Constant<String>("book1"); final IConstant<String> book2 = new Constant<String>("book2"); final IConstant<String> book3 = new Constant<String>("book3"); final IConstant<String> book4 = new Constant<String>("book4"); final IConstant<XSDNumericIV<BigdataLiteral>> price5 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(5)); final IConstant<XSDNumericIV<BigdataLiteral>> price7 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(7)); final IConstant<XSDNumericIV<BigdataLiteral>> price9 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(9)); final IConstant<XSDNumericIV<BigdataLiteral>> price12 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(12)); final IValueExpression<?> totalPriceExpr = new Bind(totalPrice, new SUM(false/* distinct */, (IValueExpression<IV>) lprice)); final IValueExpression<?> zExpr = new Bind(z, price12); final GroupByOp query = newFixture(// new IValueExpression[] { org, totalPriceExpr, zExpr }, // select new IValueExpression[] { org }, // groupBy null // having ); /** * The test data: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org2 auth3 book4 7 * </pre> */ final IBindingSet data [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book1, price9 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book2, price5 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth2, book3, price7 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org2, auth3, book4, price7 } ) }; /** * The expected solutions: * * <pre> * ?org ?totalPrice ?z * org1 21 12 * org2 7 12 * </pre> */ // Note: The aggregates will have gone through type promotion. final IConstant<XSDIntegerIV<BigdataLiteral>> _price7 = new Constant<XSDIntegerIV<BigdataLiteral>>( new XSDIntegerIV<BigdataLiteral>(BigInteger.valueOf(7))); final IConstant<XSDIntegerIV<BigdataLiteral>> _price21 = new Constant<XSDIntegerIV<BigdataLiteral>>( new XSDIntegerIV<BigdataLiteral>(BigInteger.valueOf(21))); final IBindingSet expected[] = new IBindingSet[] { new ListBindingSet ( new IVariable<?> [] { org, totalPrice, z }, new IConstant [] { org1, _price21, price12 } ) , new ListBindingSet ( new IVariable<?> [] { org, totalPrice, z }, new IConstant [] { org2, _price7 , price12 } ) } ; 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 IRunningQuery runningQuery = new MockRunningQuery(null/* fed */ , null/* indexManager */, queryContext ); // Note: [lastInvocation:=true] forces the solutions to be emitted. final BOpContext<IBindingSet> context = new BOpContext<IBindingSet>( runningQuery, -1/* partitionId */ , stats, query/* op */, true/* lastInvocation */, source, sink, null/* sink2 */ ); // // Force the solutions to be emitted. // 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.assertSameSolutionsAnyOrder(expected, sink.iterator(), ft); assertEquals(1, stats.chunksIn.get()); assertEquals(4, stats.unitsIn.get()); assertEquals(2, stats.unitsOut.get()); assertEquals(1, stats.chunksOut.get()); } /** * Based on an example in the SPARQL 1.1 Working Draft. * * <pre> * @prefix : <http://books.example/> . * * :org1 :affiliates :auth1, :auth2 . * :auth1 :writesBook :book1, :book2 . * :book1 :price 9 . * :book2 :price 5 . * :auth2 :writesBook :book3 . * :book3 :price 7 . * :org2 :affiliates :auth3 . * :auth3 :writesBook :book4 . * :book4 :price 7 . * </pre> * * <pre> * PREFIX : <http://books.example/> * SELECT ?org, (SUM(?lprice) AS ?totalPrice) * WHERE { * ?org :affiliates ?auth . * ?auth :writesBook ?book . * ?book :price ?lprice . * } * GROUP BY ?org * HAVING (SUM(?lprice) > 10) * </pre> * * The solutions input to the GROUP_BY are: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org2 auth3 book4 7 * </pre> * * The aggregated solutions groups are: * * <pre> * ?org ?totalPrice * org1 21 * </pre> * * @throws ExecutionException * @throws InterruptedException */ public void test_aggregation_groupBy_with_aggregate_and_having() { final IVariable<IV> org = Var.var("org"); final IVariable<IV> auth = Var.var("auth"); final IVariable<IV> book = Var.var("book"); final IVariable<IV> lprice = Var.var("lprice"); final IVariable<IV> totalPrice = Var.var("totalPrice"); /* * TODO All of these should all be IVs based on TermIds with their * value's cached (the data are not being visited which is why the tests * are passing). Also fix the other tests in this class. See TestSUM. */ final IConstant<String> org1 = new Constant<String>("org1"); final IConstant<String> org2 = new Constant<String>("org2"); final IConstant<String> auth1 = new Constant<String>("auth1"); final IConstant<String> auth2 = new Constant<String>("auth2"); final IConstant<String> auth3 = new Constant<String>("auth3"); final IConstant<String> book1 = new Constant<String>("book1"); final IConstant<String> book2 = new Constant<String>("book2"); final IConstant<String> book3 = new Constant<String>("book3"); final IConstant<String> book4 = new Constant<String>("book4"); final IConstant<XSDNumericIV<BigdataLiteral>> price5 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(5)); final IConstant<XSDNumericIV<BigdataLiteral>> price7 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(7)); final IConstant<XSDNumericIV<BigdataLiteral>> price9 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(9)); final IValueExpression<IV> totalPriceExpr = new Bind(totalPrice, new SUM(false/* distinct */, (IValueExpression<IV>) lprice)); final IConstraint totalPriceConstraint = new SPARQLConstraint<XSDBooleanIV>( new CompareBOp( totalPrice, new Constant<XSDNumericIV<BigdataLiteral>>(new XSDNumericIV(10)), CompareOp.GT)); final GroupByOp query = newFixture(// new IValueExpression[] { org, totalPriceExpr }, // select new IValueExpression[] { org }, // groupBy new IConstraint[] { totalPriceConstraint } // having ); /** * The test data: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org2 auth3 book4 7 * </pre> */ final IBindingSet data [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book1, price9 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book2, price5 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth2, book3, price7 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org2, auth3, book4, price7 } ) }; /** * The expected solutions: * * <pre> * ?org ?totalPrice * org1 21 * </pre> */ // Note: The aggregates will have gone through type promotion. final IConstant<XSDIntegerIV<BigdataLiteral>> _price21 = new Constant<XSDIntegerIV<BigdataLiteral>>( new XSDIntegerIV<BigdataLiteral>(BigInteger.valueOf(21))); final IBindingSet expected[] = new IBindingSet[] { new ListBindingSet ( new IVariable<?> [] { org, totalPrice }, new IConstant [] { org1, _price21 } ) } ; 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 IRunningQuery runningQuery = new MockRunningQuery(null/* fed */ , null/* indexManager */, queryContext ); // Note: [lastInvocation:=true] forces the solutions to be emitted. final BOpContext<IBindingSet> context = new BOpContext<IBindingSet>( runningQuery, -1/* partitionId */ , stats, query/* op */, true/* lastInvocation */, source, sink, null/* sink2 */ ); // // Force the solutions to be emitted. // 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.assertSameSolutionsAnyOrder(expected, sink.iterator(), ft); assertEquals(1, stats.chunksIn.get()); assertEquals(4, stats.unitsIn.get()); assertEquals(1, stats.unitsOut.get()); assertEquals(1, stats.chunksOut.get()); } /** * Based on an example in the SPARQL 1.1 Working Draft. * * <pre> * @prefix : <http://books.example/> . * * :org1 :affiliates :auth1, :auth2 . * :auth1 :writesBook :book1, :book2 . * :book1 :price 9 . * :book2 :price 5 . * :auth2 :writesBook :book3 . * :book3 :price 7 . * :org2 :affiliates :auth3 . * :auth3 :writesBook :book4 . * :book4 :price 7 . * </pre> * * <pre> * PREFIX : <http://books.example/> * SELECT ?org, (SUM(?lprice) AS ?totalPrice) * WHERE { * ?org :affiliates ?auth . * ?auth :writesBook ?book . * ?book :price ?lprice . * } * GROUP BY ?org * HAVING (SUM(?lprice) > 5) * </pre> * * The solutions input to the GROUP_BY are: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 blue * org2 auth3 book4 7 * </pre> * * The aggregated solutions groups are: * * <pre> * ?org ?totalPrice * org2 7 * </pre> * * @throws ExecutionException * @throws InterruptedException */ public void test_aggregation_groupBy_with_aggregate_and_having_with_errors() { final IVariable<IV> org = Var.var("org"); final IVariable<IV> auth = Var.var("auth"); final IVariable<IV> book = Var.var("book"); final IVariable<IV> lprice = Var.var("lprice"); final IVariable<IV> totalPrice = Var.var("totalPrice"); final IConstant<String> org1 = new Constant<String>("org1"); final IConstant<String> org2 = new Constant<String>("org2"); final IConstant<String> auth1 = new Constant<String>("auth1"); final IConstant<String> auth2 = new Constant<String>("auth2"); final IConstant<String> auth3 = new Constant<String>("auth3"); final IConstant<String> book1 = new Constant<String>("book1"); final IConstant<String> book2 = new Constant<String>("book2"); final IConstant<String> book3 = new Constant<String>("book3"); final IConstant<String> book4 = new Constant<String>("book4"); final BigdataValueFactory f = BigdataValueFactoryImpl.getInstance(getName()); final TermId tid1 = new TermId<BigdataValue>(VTE.LITERAL, 1); tid1.setValue(f.createLiteral("blue")); final IConstant<IV> blue = new Constant<IV>(tid1); final IConstant<XSDNumericIV<BigdataLiteral>> price5 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(5)); final IConstant<XSDNumericIV<BigdataLiteral>> price7 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(7)); final IConstant<XSDNumericIV<BigdataLiteral>> price9 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(9)); final IValueExpression<IV> totalPriceExpr = new Bind(totalPrice, new SUM(false/* distinct */, (IValueExpression<IV>) lprice)); final IConstraint totalPriceConstraint = new SPARQLConstraint<XSDBooleanIV>( new CompareBOp( totalPrice, new Constant<XSDNumericIV<BigdataLiteral>>(new XSDNumericIV(5)), CompareOp.GT)); final GroupByOp query = newFixture(// new IValueExpression[] { org, totalPriceExpr }, // select new IValueExpression[] { org }, // groupBy new IConstraint[] { totalPriceConstraint } // having ); /** * The test data: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 blue * org2 auth3 book4 7 * </pre> */ final IBindingSet data [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book1, price9 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book2, price5 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth2, book3, blue } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org2, auth3, book4, price7 } ) }; /** * The expected solutions: * * <pre> * ?org ?totalPrice * org2 7 * </pre> */ // Note: The aggregates will have gone through type promotion. final IConstant<XSDIntegerIV<BigdataLiteral>> _price7 = new Constant<XSDIntegerIV<BigdataLiteral>>( new XSDIntegerIV<BigdataLiteral>(BigInteger.valueOf(7))); final IBindingSet expected[] = new IBindingSet[] { new ListBindingSet ( new IVariable<?> [] { org, totalPrice }, new IConstant [] { org2, _price7 } ) } ; 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 IRunningQuery runningQuery = new MockRunningQuery(null/* fed */ , null/* indexManager */, queryContext ); // Note: [lastInvocation:=true] forces the solutions to be emitted. final BOpContext<IBindingSet> context = new BOpContext<IBindingSet>( runningQuery, -1/* partitionId */ , stats, query/* op */, true/* lastInvocation */, source, sink, null/* sink2 */ ); // // Force the solutions to be emitted. // 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.assertSameSolutionsAnyOrder(expected, sink.iterator(), ft); assertEquals(1, stats.chunksIn.get()); assertEquals(4, stats.unitsIn.get()); assertEquals(1, stats.unitsOut.get()); assertEquals(1, stats.chunksOut.get()); } /** * Based on an example in the SPARQL 1.1 Working Draft. * * <pre> * @prefix : <http://books.example/> . * * :org1 :affiliates :auth1, :auth2 . * :auth1 :writesBook :book1, :book2 . * :book1 :price 9 . * :book2 :price 5 . * :auth2 :writesBook :book3 . * :book3 :price 7 . * :org2 :affiliates :auth3 . * :auth3 :writesBook :book4 . * :book4 :price 7 . * </pre> * * <pre> * PREFIX : <http://books.example/> * SELECT ?org, (SUM(?lprice) AS ?totalPrice) * WHERE { * ?org :affiliates ?auth . * ?auth :writesBook ?book . * ?book :price ?lprice . * } * GROUP BY ?org * </pre> * * The solutions input to the GROUP_BY are: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 blue * org2 auth3 book4 7 * </pre> * * The aggregated solutions groups are: * * <pre> * ?org ?totalPrice * org1 N/A // Note: No value bound for ?totalPrice. * org2 7 * </pre> * * @throws ExecutionException * @throws InterruptedException */ public void test_aggregation_groupBy_with_aggregate_no_having_with_errors() { final IVariable<IV> org = Var.var("org"); final IVariable<IV> auth = Var.var("auth"); final IVariable<IV> book = Var.var("book"); final IVariable<IV> lprice = Var.var("lprice"); final IVariable<IV> totalPrice = Var.var("totalPrice"); final IConstant<String> org1 = new Constant<String>("org1"); final IConstant<String> org2 = new Constant<String>("org2"); final IConstant<String> auth1 = new Constant<String>("auth1"); final IConstant<String> auth2 = new Constant<String>("auth2"); final IConstant<String> auth3 = new Constant<String>("auth3"); final IConstant<String> book1 = new Constant<String>("book1"); final IConstant<String> book2 = new Constant<String>("book2"); final IConstant<String> book3 = new Constant<String>("book3"); final IConstant<String> book4 = new Constant<String>("book4"); final BigdataValueFactory f = BigdataValueFactoryImpl.getInstance(getName()); final TermId tid1 = new TermId<BigdataValue>(VTE.LITERAL, 1); tid1.setValue(f.createLiteral("blue")); final IConstant<IV> blue = new Constant<IV>(tid1); final IConstant<XSDNumericIV<BigdataLiteral>> price5 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(5)); final IConstant<XSDNumericIV<BigdataLiteral>> price7 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(7)); final IConstant<XSDNumericIV<BigdataLiteral>> price9 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(9)); final IValueExpression<IV> totalPriceExpr = new Bind(totalPrice, new SUM(false/* distinct */, (IValueExpression<IV>) lprice)); final GroupByOp query = newFixture(// new IValueExpression[] { org, totalPriceExpr }, // select new IValueExpression[] { org }, // groupBy null // having ); /** * The test data: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 blue * org2 auth3 book4 7 * </pre> */ final IBindingSet data [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book1, price9 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book2, price5 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth2, book3, blue } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org2, auth3, book4, price7 } ) }; /** * The expected solutions: * * <pre> * ?org ?totalPrice * org1 N/A * org2 7 * </pre> */ // Note: The aggregates will have gone through type promotion. final IConstant<XSDIntegerIV<BigdataLiteral>> _price7 = new Constant<XSDIntegerIV<BigdataLiteral>>( new XSDIntegerIV<BigdataLiteral>(BigInteger.valueOf(7))); final IBindingSet expected[] = new IBindingSet[] { new ListBindingSet ( new IVariable<?> [] { org, }, new IConstant [] { org1, } ), new ListBindingSet ( new IVariable<?> [] { org, totalPrice }, new IConstant [] { org2, _price7 } ) } ; 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 IRunningQuery runningQuery = new MockRunningQuery(null/* fed */ , null/* indexManager */, queryContext ); // Note: [lastInvocation:=true] forces the solutions to be emitted. final BOpContext<IBindingSet> context = new BOpContext<IBindingSet>( runningQuery, -1/* partitionId */ , stats, query/* op */, true/* lastInvocation */, source, sink, null/* sink2 */ ); // // Force the solutions to be emitted. // 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.assertSameSolutionsAnyOrder(expected, sink.iterator(), ft); assertEquals(1, stats.chunksIn.get()); assertEquals(4, stats.unitsIn.get()); assertEquals(2, stats.unitsOut.get()); assertEquals(1, stats.chunksOut.get()); } /** * Based on an example in the SPARQL 1.1 Working Draft. * * <pre> * @prefix : <http://books.example/> . * * :org1 :affiliates :auth1, :auth2 . * :auth1 :writesBook :book1, :book2 . * :book1 :price 9 . * :book2 :price 5 . * :auth2 :writesBook :book3 . * :book3 :price 7 . * :org2 :affiliates :auth3 . * :auth3 :writesBook :book4 . * :book4 :price 7 . * </pre> * * <pre> * PREFIX : <http://books.example/> * SELECT (SUM(?lprice) AS ?totalPrice) * WHERE { * ?org :affiliates ?auth . * ?auth :writesBook ?book . * ?book :price ?lprice . * } * HAVING (SUM(?lprice) > 10) * </pre> * * The inputs are: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org2 auth3 book4 7 * </pre> * * The solutions are: * * <pre> * ?totalPrice * 28 * </pre> * * @throws ExecutionException * @throws InterruptedException */ public void test_aggregation_without_groupBy_with_aggregate_and_having() { final IVariable<IV> org = Var.var("org"); final IVariable<IV> auth = Var.var("auth"); final IVariable<IV> book = Var.var("book"); final IVariable<IV> lprice = Var.var("lprice"); final IVariable<IV> totalPrice = Var.var("totalPrice"); final IConstant<String> org1 = new Constant<String>("org1"); final IConstant<String> org2 = new Constant<String>("org2"); final IConstant<String> auth1 = new Constant<String>("auth1"); final IConstant<String> auth2 = new Constant<String>("auth2"); final IConstant<String> auth3 = new Constant<String>("auth3"); final IConstant<String> book1 = new Constant<String>("book1"); final IConstant<String> book2 = new Constant<String>("book2"); final IConstant<String> book3 = new Constant<String>("book3"); final IConstant<String> book4 = new Constant<String>("book4"); final IConstant<XSDNumericIV<BigdataLiteral>> price5 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(5)); final IConstant<XSDNumericIV<BigdataLiteral>> price7 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(7)); final IConstant<XSDNumericIV<BigdataLiteral>> price9 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(9)); final IValueExpression<IV> totalPriceExpr = new Bind(totalPrice, new SUM(false/* distinct */, (IValueExpression<IV>) lprice)); final IConstraint totalPriceConstraint = new SPARQLConstraint<XSDBooleanIV>( new CompareBOp( totalPrice, new Constant<XSDNumericIV<BigdataLiteral>>(new XSDNumericIV(10)), CompareOp.GT)); final GroupByOp query = newFixture(// new IValueExpression[] { totalPriceExpr }, // select null, // groupBy new IConstraint[] { totalPriceConstraint } // having ); /** * The test data: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org2 auth3 book4 7 * </pre> */ final IBindingSet data [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book1, price9 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book2, price5 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth2, book3, price7 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org2, auth3, book4, price7 } ) }; /** * The expected solutions: * * <pre> * ?totalPrice * 28 * </pre> */ // Note: The aggregates will have gone through type promotion. final IConstant<XSDIntegerIV<BigdataLiteral>> _price28 = new Constant<XSDIntegerIV<BigdataLiteral>>( new XSDIntegerIV<BigdataLiteral>(BigInteger.valueOf(28))); final IBindingSet expected[] = new IBindingSet[] { new ListBindingSet ( new IVariable<?> [] { totalPrice }, new IConstant [] { _price28 } ) } ; 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 IRunningQuery runningQuery = new MockRunningQuery(null/* fed */ , null/* indexManager */, queryContext ); // Note: [lastInvocation:=true] forces the solutions to be emitted. final BOpContext<IBindingSet> context = new BOpContext<IBindingSet>( runningQuery, -1/* partitionId */ , stats, query/* op */, true/* lastInvocation */, source, sink, null/* sink2 */ ); // // Force the solutions to be emitted. // 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.assertSameSolutionsAnyOrder(expected, sink.iterator(), ft); assertEquals(1, stats.chunksIn.get()); assertEquals(4, stats.unitsIn.get()); assertEquals(1, stats.unitsOut.get()); assertEquals(1, stats.chunksOut.get()); } /** * Based on an example in the SPARQL 1.1 Working Draft. * * <pre> * @prefix : <http://books.example/> . * * :org1 :affiliates :auth1, :auth2 . * :auth1 :writesBook :book1, :book2 . * :book1 :price 9 . * :book2 :price 5 . * :auth2 :writesBook :book3 . * :book3 :price 7 . * :org2 :affiliates :auth3 . * :auth3 :writesBook :book4 . * :book4 :price 7 . * </pre> * * <pre> * PREFIX : <http://books.example/> * SELECT (SUM(?lprice) AS ?totalPrice) * WHERE { * ?org :affiliates ?auth . * ?auth :writesBook ?book . * ?book :price ?lprice . * } * HAVING (SUM(?lprice) > 50) * </pre> * * The inputs are: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org2 auth3 book4 7 * </pre> * * There are NO solutions. * * @throws ExecutionException * @throws InterruptedException */ public void test_aggregation_without_groupBy_with_aggregate_and_having_no_solutions() { final IVariable<IV> org = Var.var("org"); final IVariable<IV> auth = Var.var("auth"); final IVariable<IV> book = Var.var("book"); final IVariable<IV> lprice = Var.var("lprice"); final IVariable<IV> totalPrice = Var.var("totalPrice"); final IConstant<String> org1 = new Constant<String>("org1"); final IConstant<String> org2 = new Constant<String>("org2"); final IConstant<String> auth1 = new Constant<String>("auth1"); final IConstant<String> auth2 = new Constant<String>("auth2"); final IConstant<String> auth3 = new Constant<String>("auth3"); final IConstant<String> book1 = new Constant<String>("book1"); final IConstant<String> book2 = new Constant<String>("book2"); final IConstant<String> book3 = new Constant<String>("book3"); final IConstant<String> book4 = new Constant<String>("book4"); final IConstant<XSDNumericIV<BigdataLiteral>> price5 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(5)); final IConstant<XSDNumericIV<BigdataLiteral>> price7 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(7)); final IConstant<XSDNumericIV<BigdataLiteral>> price9 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(9)); final IValueExpression<IV> totalPriceExpr = new Bind(totalPrice, new SUM(false/* distinct */, (IValueExpression<IV>) lprice)); final IConstraint totalPriceConstraint = new SPARQLConstraint<XSDBooleanIV>( new CompareBOp( totalPrice, new Constant<XSDNumericIV<BigdataLiteral>>(new XSDNumericIV(50)), CompareOp.GT)); final GroupByOp query = newFixture(// new IValueExpression[] { totalPriceExpr }, // select null, // groupBy new IConstraint[] { totalPriceConstraint } // having ); /** * The test data: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org2 auth3 book4 7 * </pre> */ final IBindingSet data [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book1, price9 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book2, price5 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth2, book3, price7 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org2, auth3, book4, price7 } ) }; /** * THERE ARE NO SOLUTIONS. */ final IBindingSet expected[] = new IBindingSet[] {}; 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 IRunningQuery runningQuery = new MockRunningQuery(null/* fed */ , null/* indexManager */ , queryContext ); // Note: [lastInvocation:=true] forces the solutions to be emitted. final BOpContext<IBindingSet> context = new BOpContext<IBindingSet>( runningQuery, -1/* partitionId */ , stats, query/* op */, true/* lastInvocation */, source, sink, null/* sink2 */ ); // // Force the solutions to be emitted. // 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.assertSameSolutionsAnyOrder(expected, sink.iterator(), ft); assertEquals(1, stats.chunksIn.get()); assertEquals(4, stats.unitsIn.get()); assertEquals(0, stats.unitsOut.get()); assertEquals(0, stats.chunksOut.get()); } /** * Based on an example in the SPARQL 1.1 Working Draft. * * <pre> * @prefix : <http://books.example/> . * * :org1 :affiliates :auth1, :auth2 . * :auth1 :writesBook :book1, :book2 . * :book1 :price 9 . * :book2 :price 5 . * :auth2 :writesBook :book3 . * :book3 :price 7 . * :org2 :affiliates :auth3 . * :auth3 :writesBook :book4 . * :book4 :price 7 . * </pre> * * <pre> * PREFIX : <http://books.example/> * SELECT ?org, (SUM(?lprice) AS ?totalPrice) * WHERE { * ?org :affiliates ?auth . * ?auth :writesBook ?book . * ?book :price ?lprice . * } * </pre> * * The solutions input to the GROUP_BY are: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org2 auth3 book4 7 * </pre> * * The aggregated solution is: * * <pre> * ?totalPrice * 28 * </pre> * * Note that you can not SELECT "?org" as there is no group by clause in * this example and "?org" is a variable at the detail rather than aggregate * level. (You could select SAMPLE(?org) or GROUP_CONCAT(?org).) * * @throws ExecutionException * @throws InterruptedException */ public void test_aggregation_aggregate_no_groups() { final IVariable<IV> org = Var.var("org"); final IVariable<IV> auth = Var.var("auth"); final IVariable<IV> book = Var.var("book"); final IVariable<IV> lprice = Var.var("lprice"); final IVariable<IV> totalPrice = Var.var("totalPrice"); final IConstant<String> org1 = new Constant<String>("org1"); final IConstant<String> org2 = new Constant<String>("org2"); final IConstant<String> auth1 = new Constant<String>("auth1"); final IConstant<String> auth2 = new Constant<String>("auth2"); final IConstant<String> auth3 = new Constant<String>("auth3"); final IConstant<String> book1 = new Constant<String>("book1"); final IConstant<String> book2 = new Constant<String>("book2"); final IConstant<String> book3 = new Constant<String>("book3"); final IConstant<String> book4 = new Constant<String>("book4"); final IConstant<XSDNumericIV<BigdataLiteral>> price5 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(5)); final IConstant<XSDNumericIV<BigdataLiteral>> price7 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(7)); final IConstant<XSDNumericIV<BigdataLiteral>> price9 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(9)); final IValueExpression<IV> totalPriceExpr = new Bind(totalPrice, new SUM(false/* distinct */, (IValueExpression<IV>) lprice)); final GroupByOp query = newFixture(// new IValueExpression[] { totalPriceExpr }, // select null, // groupBy null // having ); /** * The test data: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org2 auth3 book4 7 * </pre> */ final IBindingSet data [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book1, price9 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book2, price5 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth2, book3, price7 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org2, auth3, book4, price7 } ) }; /** * The expected solutions: * * <pre> * ?totalPrice * 28 * </pre> */ // Note: The aggregates will have gone through type promotion. final IConstant<XSDIntegerIV<BigdataLiteral>> _price28 = new Constant<XSDIntegerIV<BigdataLiteral>>( new XSDIntegerIV<BigdataLiteral>(BigInteger.valueOf(28))); final IBindingSet expected[] = new IBindingSet[] { new ListBindingSet ( new IVariable<?> [] { totalPrice }, new IConstant [] { _price28 } ) } ; 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 IRunningQuery runningQuery = new MockRunningQuery(null/* fed */ , null/* indexManager */ , queryContext ); // Note: [lastInvocation:=true] forces the solutions to be emitted. final BOpContext<IBindingSet> context = new BOpContext<IBindingSet>( runningQuery, -1/* partitionId */ , stats, query/* op */, true/* lastInvocation */, source, sink, null/* sink2 */ ); // // Force the solutions to be emitted. // 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.assertSameSolutionsAnyOrder(expected, sink.iterator(), ft); assertEquals(1, stats.chunksIn.get()); assertEquals(4, stats.unitsIn.get()); assertEquals(1, stats.unitsOut.get()); assertEquals(1, stats.chunksOut.get()); } /** * Based on an example in the SPARQL 1.1 Working Draft. * * <pre> * @prefix : <http://books.example/> . * * :org1 :affiliates :auth1, :auth2 . * :auth1 :writesBook :book1, :book2 . * :book1 :price 9 . * :book2 :price 5 . * :auth2 :writesBook :book3 . * :book3 :price 7 . * :org2 :affiliates :auth3 . * :auth3 :writesBook :book4 . * :book4 :price 7 . * </pre> * * <pre> * PREFIX : <http://books.example/> * SELECT ?org, (SUM(DISTINCT ?lprice) AS ?totalPrice) * WHERE { * ?org :affiliates ?auth . * ?auth :writesBook ?book . * ?book :price ?lprice . * } * </pre> * * The solutions input to the GROUP_BY are: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org2 auth3 book4 7 * </pre> * * The aggregated solution is: * * <pre> * ?totalPrice * 21 * </pre> * * Note that you can not SELECT "?org" as there is no group by clause in * this example and "?org" is a variable at the detail rather than aggregate * level. (You could select SAMPLE(?org) or GROUP_CONCAT(?org).) * * @throws ExecutionException * @throws InterruptedException */ public void test_aggregation_distinct_aggregate_no_groups() { final IVariable<IV> org = Var.var("org"); final IVariable<IV> auth = Var.var("auth"); final IVariable<IV> book = Var.var("book"); final IVariable<IV> lprice = Var.var("lprice"); final IVariable<IV> totalPrice = Var.var("totalPrice"); final IConstant<String> org1 = new Constant<String>("org1"); final IConstant<String> org2 = new Constant<String>("org2"); final IConstant<String> auth1 = new Constant<String>("auth1"); final IConstant<String> auth2 = new Constant<String>("auth2"); final IConstant<String> auth3 = new Constant<String>("auth3"); final IConstant<String> book1 = new Constant<String>("book1"); final IConstant<String> book2 = new Constant<String>("book2"); final IConstant<String> book3 = new Constant<String>("book3"); final IConstant<String> book4 = new Constant<String>("book4"); final IConstant<XSDNumericIV<BigdataLiteral>> price5 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(5)); final IConstant<XSDNumericIV<BigdataLiteral>> price7 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(7)); final IConstant<XSDNumericIV<BigdataLiteral>> price9 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(9)); final IValueExpression<IV> totalPriceExpr = new Bind(totalPrice, new SUM(true/* distinct */, (IValueExpression<IV>) lprice)); final GroupByOp query = newFixture(// new IValueExpression[] { totalPriceExpr }, // select null, // groupBy null // having ); /** * The test data: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org2 auth3 book4 7 * </pre> */ final IBindingSet data [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book1, price9 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book2, price5 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth2, book3, price7 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org2, auth3, book4, price7 } ) }; /** * The expected solutions: * * <pre> * ?totalPrice * 21 * </pre> */ // Note: The aggregates will have gone through type promotion. final IConstant<XSDIntegerIV<BigdataLiteral>> _price21 = new Constant<XSDIntegerIV<BigdataLiteral>>( new XSDIntegerIV<BigdataLiteral>(BigInteger.valueOf(21))); final IBindingSet expected[] = new IBindingSet[] { new ListBindingSet ( new IVariable<?> [] { totalPrice }, new IConstant [] { _price21 } ) }; if (isPipelinedAggregationOp()) { try { query.newStats(); fail("Expecting " + UnsupportedOperationException.class); } catch (UnsupportedOperationException ex) { if (isPipelinedAggregationOp()) { if (log.isInfoEnabled()) log.info("Ignoring expected exception: " + ex); return; } else { throw ex; } } } 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 IRunningQuery runningQuery = new MockRunningQuery(null/* fed */ , null/* indexManager */ , queryContext ); // Note: [lastInvocation:=true] forces the solutions to be emitted. final BOpContext<IBindingSet> context = new BOpContext<IBindingSet>( runningQuery, -1/* partitionId */ , stats, query/* op */, true/* lastInvocation */, source, sink, null/* sink2 */ ); // // Force the solutions to be emitted. // 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.assertSameSolutionsAnyOrder(expected, sink.iterator(), ft); assertEquals(1, stats.chunksIn.get()); assertEquals(4, stats.unitsIn.get()); assertEquals(1, stats.unitsOut.get()); assertEquals(1, stats.chunksOut.get()); } /** * Based on an example in the SPARQL 1.1 Working Draft. * * <pre> * @prefix : <http://books.example/> . * * :org1 :affiliates :auth1, :auth2 . * :auth1 :writesBook :book1, :book2 . * :book1 :price 9 . * :book2 :price 5 . * :auth2 :writesBook :book3 . * :book3 :price 7 . * :org2 :affiliates :auth3 . * :auth3 :writesBook :book4 . * :book4 :price 7 . * </pre> * * <pre> * PREFIX : <http://books.example/> * SELECT ?org, (COUNT(*) AS ?totalCount) * WHERE { * ?org :affiliates ?auth . * ?auth :writesBook ?book . * ?book :price ?lprice . * } * </pre> * * The solutions input to the GROUP_BY are: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org2 auth3 book4 7 * </pre> * * The aggregated solution is: * * <pre> * ?totalCount * 4 * </pre> * * @throws ExecutionException * @throws InterruptedException */ public void test_aggregation_count_star_no_groups() { final IVariable<IV> org = Var.var("org"); final IVariable<IV> auth = Var.var("auth"); final IVariable<IV> book = Var.var("book"); final IVariable<IV> lprice = Var.var("lprice"); final IVariable<IV> star = Var.var("*"); final IVariable<IV> totalCount = Var.var("totalCount"); final IConstant<String> org1 = new Constant<String>("org1"); final IConstant<String> org2 = new Constant<String>("org2"); final IConstant<String> auth1 = new Constant<String>("auth1"); final IConstant<String> auth2 = new Constant<String>("auth2"); final IConstant<String> auth3 = new Constant<String>("auth3"); final IConstant<String> book1 = new Constant<String>("book1"); final IConstant<String> book2 = new Constant<String>("book2"); final IConstant<String> book3 = new Constant<String>("book3"); final IConstant<String> book4 = new Constant<String>("book4"); final IConstant<XSDNumericIV<BigdataLiteral>> price5 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(5)); final IConstant<XSDNumericIV<BigdataLiteral>> price7 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(7)); final IConstant<XSDNumericIV<BigdataLiteral>> price9 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(9)); final IValueExpression<IV> totalCountExpr = new Bind(totalCount, new COUNT(false/* distinct */, star)); final GroupByOp query = newFixture(// new IValueExpression[] { totalCountExpr }, // select null, // groupBy null // having ); /** * The test data: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org2 auth3 book4 7 * </pre> */ final IBindingSet data [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book1, price9 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book2, price5 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth2, book3, price7 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org2, auth3, book4, price7 } ) }; /** * The expected solutions: * * <pre> * ?totalCount * 4 * </pre> */ // final IConstant<XSDNumericIV<BigdataLiteral>> _totalCount = new Constant<XSDNumericIV<BigdataLiteral>>( // new XSDNumericIV<BigdataLiteral>(4L)); final IConstant<XSDIntegerIV<BigdataLiteral>> _totalCount = new Constant<XSDIntegerIV<BigdataLiteral>>( new XSDIntegerIV<BigdataLiteral>(BigInteger.valueOf(4L))); final IBindingSet expected[] = new IBindingSet[] { new ListBindingSet ( new IVariable<?> [] { totalCount }, new IConstant [] { _totalCount } ) } ; 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 IRunningQuery runningQuery = new MockRunningQuery(null/* fed */ , null/* indexManager */ , queryContext ); // Note: [lastInvocation:=true] forces the solutions to be emitted. final BOpContext<IBindingSet> context = new BOpContext<IBindingSet>( runningQuery, -1/* partitionId */ , stats, query/* op */, true/* lastInvocation */, source, sink, null/* sink2 */ ); // // Force the solutions to be emitted. // 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.assertSameSolutionsAnyOrder(expected, sink.iterator(), ft); assertEquals(1, stats.chunksIn.get()); assertEquals(4, stats.unitsIn.get()); assertEquals(1, stats.unitsOut.get()); assertEquals(1, stats.chunksOut.get()); } /** * Based on an example in the SPARQL 1.1 Working Draft. * * <pre> * @prefix : <http://books.example/> . * * :org1 :affiliates :auth1, :auth2 . * :auth1 :writesBook :book1, :book2 . * :book1 :price 9 . * :book2 :price 5 . * :auth2 :writesBook :book3 . * :book3 :price 7 . * :org2 :affiliates :auth3 . * :auth3 :writesBook :book4 . * :book4 :price 7 . * </pre> * * <pre> * PREFIX : <http://books.example/> * SELECT ?org, (COUNT(DISTINCT *) AS ?totalCount) * WHERE { * ?org :affiliates ?auth . * ?auth :writesBook ?book . * ?book :price ?lprice . * } * </pre> * * The solutions input to the GROUP_BY are: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org1 auth2 book3 7 // duplicate record! * org2 auth3 book4 7 * </pre> * * The aggregated solution is: * * <pre> * ?totalCount * 4 * </pre> * * @throws ExecutionException * @throws InterruptedException */ public void test_aggregation_count_distinct_star_no_groups() { final IVariable<IV> org = Var.var("org"); final IVariable<IV> auth = Var.var("auth"); final IVariable<IV> book = Var.var("book"); final IVariable<IV> lprice = Var.var("lprice"); final IVariable<IV> star = Var.var("*"); final IVariable<IV> totalCount = Var.var("totalCount"); final IConstant<String> org1 = new Constant<String>("org1"); final IConstant<String> org2 = new Constant<String>("org2"); final IConstant<String> auth1 = new Constant<String>("auth1"); final IConstant<String> auth2 = new Constant<String>("auth2"); final IConstant<String> auth3 = new Constant<String>("auth3"); final IConstant<String> book1 = new Constant<String>("book1"); final IConstant<String> book2 = new Constant<String>("book2"); final IConstant<String> book3 = new Constant<String>("book3"); final IConstant<String> book4 = new Constant<String>("book4"); final IConstant<XSDNumericIV<BigdataLiteral>> price5 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(5)); final IConstant<XSDNumericIV<BigdataLiteral>> price7 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(7)); final IConstant<XSDNumericIV<BigdataLiteral>> price9 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(9)); final IValueExpression<IV> totalCountExpr = new Bind(totalCount, new COUNT(true/* distinct */, star)); final GroupByOp query = newFixture(// new IValueExpression[] { totalCountExpr }, // select null, // groupBy null // having ); /** * The test data: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org1 auth2 book3 7 // duplicate record! * org2 auth3 book4 7 * </pre> */ final IBindingSet data [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book1, price9 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book2, price5 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth2, book3, price7 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth2, book3, price7 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org2, auth3, book4, price7 } ) }; /** * The expected solutions: * * <pre> * ?totalCount * 4 * </pre> */ // final IConstant<XSDNumericIV<BigdataLiteral>> _totalCount = new Constant<XSDNumericIV<BigdataLiteral>>( // new XSDNumericIV<BigdataLiteral>(4L)); final IConstant<XSDIntegerIV<BigdataLiteral>> _totalCount = new Constant<XSDIntegerIV<BigdataLiteral>>( new XSDIntegerIV<BigdataLiteral>(BigInteger.valueOf(4L))); final IBindingSet expected[] = new IBindingSet[] { new ListBindingSet ( new IVariable<?> [] { totalCount }, new IConstant [] { _totalCount } ) } ; if (isPipelinedAggregationOp()) { try { query.newStats(); fail("Expecting " + UnsupportedOperationException.class); } catch (UnsupportedOperationException ex) { if (isPipelinedAggregationOp()) { if (log.isInfoEnabled()) log.info("Ignoring expected exception: " + ex); return; } else { throw ex; } } } 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 IRunningQuery runningQuery = new MockRunningQuery(null/* fed */ , null/* indexManager */ , queryContext ); // Note: [lastInvocation:=true] forces the solutions to be emitted. final BOpContext<IBindingSet> context = new BOpContext<IBindingSet>( runningQuery, -1/* partitionId */ , stats, query/* op */, true/* lastInvocation */, source, sink, null/* sink2 */ ); // // Force the solutions to be emitted. // 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.assertSameSolutionsAnyOrder(expected, sink.iterator(), ft); assertEquals(1, stats.chunksIn.get()); assertEquals(5, stats.unitsIn.get()); assertEquals(1, stats.unitsOut.get()); assertEquals(1, stats.chunksOut.get()); } /** * Based on an example in the SPARQL 1.1 Working Draft. * * <pre> * @prefix : <http://books.example/> . * * :org1 :affiliates :auth1, :auth2 . * :auth1 :writesBook :book1, :book2 . * :book1 :price 9 . * :book2 :price 5 . * :auth2 :writesBook :book3 . * :book3 :price 7 . * :org2 :affiliates :auth3 . * :auth3 :writesBook :book4 . * :book4 :price 7 . * </pre> * * <pre> * PREFIX : <http://books.example/> * SELECT (SUM(?lprice+SUM(?lprice)) AS ?totalPrice) * WHERE { * ?org :affiliates ?auth . * ?auth :writesBook ?book . * ?book :price ?lprice . * } * </pre> * * The inputs are: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org2 auth3 book4 7 * </pre> * * The solutions are: * * <pre> * ?totalPrice * 140 * </pre> * * @throws ExecutionException * @throws InterruptedException */ public void test_aggregation_without_groupBy_with_nestedAggregate() { AbstractTripleStore kb = TestMockUtility.mockTripleStore(getName()); try { final String lexiconNamespace = kb.getLexiconRelation().getNamespace(); final GlobalAnnotations globals = new GlobalAnnotations(lexiconNamespace, ITx.READ_COMMITTED); final IVariable<IV> org = Var.var("org"); final IVariable<IV> auth = Var.var("auth"); final IVariable<IV> book = Var.var("book"); final IVariable<IV> lprice = Var.var("lprice"); final IVariable<IV> totalPrice = Var.var("totalPrice"); final IConstant<String> org1 = new Constant<String>("org1"); final IConstant<String> org2 = new Constant<String>("org2"); final IConstant<String> auth1 = new Constant<String>("auth1"); final IConstant<String> auth2 = new Constant<String>("auth2"); final IConstant<String> auth3 = new Constant<String>("auth3"); final IConstant<String> book1 = new Constant<String>("book1"); final IConstant<String> book2 = new Constant<String>("book2"); final IConstant<String> book3 = new Constant<String>("book3"); final IConstant<String> book4 = new Constant<String>("book4"); final IConstant<XSDNumericIV<BigdataLiteral>> price5 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(5)); final IConstant<XSDNumericIV<BigdataLiteral>> price7 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(7)); final IConstant<XSDNumericIV<BigdataLiteral>> price9 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(9)); // SUM(?lprice) final IValueExpression<IV> sumLPrice = new SUM(false/* distinct */, (IValueExpression<IV>) lprice); // SUM(?lprice+SUM(?lprice)) // Note: This is a nested aggregation!!! final IValueExpression<IV> nestedExpr = new SUM(false/* distinct */, new MathBOp(lprice, sumLPrice, MathBOp.MathOp.PLUS, globals)); final IValueExpression<IV> totalPriceExpr = new Bind(totalPrice, nestedExpr); final IConstraint totalPriceConstraint = new SPARQLConstraint<XSDBooleanIV>( new CompareBOp( totalPrice, new Constant<XSDNumericIV<BigdataLiteral>>(new XSDNumericIV(10)), CompareOp.GT)); final GroupByOp query = newFixture(// new IValueExpression[] { totalPriceExpr }, // select null, // groupBy new IConstraint[] { totalPriceConstraint } // having ); /** * The test data: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org2 auth3 book4 7 * </pre> */ final IBindingSet data [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book1, price9 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book2, price5 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth2, book3, price7 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org2, auth3, book4, price7 } ) }; /** * The expected solutions: * * <pre> * ?totalPrice * 140 * </pre> */ // Note: The aggregates will have gone through type promotion. final IConstant<XSDIntegerIV<BigdataLiteral>> _price140 = new Constant<XSDIntegerIV<BigdataLiteral>>( new XSDIntegerIV<BigdataLiteral>(BigInteger.valueOf(140))); final IBindingSet expected[] = new IBindingSet[] { new ListBindingSet ( new IVariable<?> [] { totalPrice }, new IConstant [] { _price140 } ) } ; if (isPipelinedAggregationOp()) { try { query.newStats(); fail("Expecting " + UnsupportedOperationException.class); } catch (UnsupportedOperationException ex) { if (isPipelinedAggregationOp()) { if (log.isInfoEnabled()) log.info("Ignoring expected exception: " + ex); return; } else { throw ex; } } } 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 IRunningQuery runningQuery = new MockRunningQuery(null/* fed */ , kb.getIndexManager()/* indexManager */ , queryContext ); // Note: [lastInvocation:=true] forces the solutions to be emitted. final BOpContext<IBindingSet> context = new BOpContext<IBindingSet>( runningQuery, -1/* partitionId */ , stats, query/* op */, true/* lastInvocation */, source, sink, null/* sink2 */ ); // // Force the solutions to be emitted. // 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.assertSameSolutionsAnyOrder(expected, sink.iterator(), ft); assertEquals(1, stats.chunksIn.get()); assertEquals(4, stats.unitsIn.get()); assertEquals(1, stats.unitsOut.get()); assertEquals(1, stats.chunksOut.get()); } finally { kb.getIndexManager().destroy(); } } /** * Based on an example in the SPARQL 1.1 Working Draft. * * <pre> * @prefix : <http://books.example/> . * * :org1 :affiliates :auth1, :auth2 . * :auth1 :writesBook :book1, :book2 . * :book1 :price 9 . * :book2 :price 5 . * :auth2 :writesBook :book3 . * :book3 :price 7 . * :org2 :affiliates :auth3 . * :auth3 :writesBook :book4 . * :book4 :price 7 . * </pre> * * <pre> * PREFIX : <http://books.example/> * SELECT (SUM(?lprice+SUM(?lprice)) AS ?totalPrice) * WHERE { * ?org :affiliates ?auth . * ?auth :writesBook ?book . * ?book :price ?lprice . * } * GROUP BY ?org * </pre> * * The inputs are: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org2 auth3 book4 7 * </pre> * * The solutions are: * * <pre> * ?org ?totalPrice * org1 84 * org2 14 * </pre> * * @throws ExecutionException * @throws InterruptedException */ public void test_aggregation_with_groupBy_with_nestedAggregate() { AbstractTripleStore kb = TestMockUtility.mockTripleStore(getName()); try { final String lexiconNamespace = kb.getLexiconRelation().getNamespace(); final GlobalAnnotations globals = new GlobalAnnotations(lexiconNamespace, ITx.READ_COMMITTED); final IVariable<IV> org = Var.var("org"); final IVariable<IV> auth = Var.var("auth"); final IVariable<IV> book = Var.var("book"); final IVariable<IV> lprice = Var.var("lprice"); final IVariable<IV> totalPrice = Var.var("totalPrice"); final IConstant<String> org1 = new Constant<String>("org1"); final IConstant<String> org2 = new Constant<String>("org2"); final IConstant<String> auth1 = new Constant<String>("auth1"); final IConstant<String> auth2 = new Constant<String>("auth2"); final IConstant<String> auth3 = new Constant<String>("auth3"); final IConstant<String> book1 = new Constant<String>("book1"); final IConstant<String> book2 = new Constant<String>("book2"); final IConstant<String> book3 = new Constant<String>("book3"); final IConstant<String> book4 = new Constant<String>("book4"); final IConstant<XSDNumericIV<BigdataLiteral>> price5 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(5)); final IConstant<XSDNumericIV<BigdataLiteral>> price7 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(7)); final IConstant<XSDNumericIV<BigdataLiteral>> price9 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(9)); // SUM(?lprice) final IValueExpression<IV> sumLPrice = new SUM(false/* distinct */, (IValueExpression<IV>) lprice); // SUM(?lprice+SUM(?lprice)) // Note: This is a nested aggregation!!! final IValueExpression<IV> nestedExpr = new SUM(false/* distinct */, new MathBOp(lprice, sumLPrice, MathBOp.MathOp.PLUS, globals)); final IValueExpression<IV> totalPriceExpr = new Bind(totalPrice, nestedExpr); final IConstraint totalPriceConstraint = new SPARQLConstraint<XSDBooleanIV>( new CompareBOp( totalPrice, new Constant<XSDNumericIV<BigdataLiteral>>(new XSDNumericIV(10)), CompareOp.GT)); final GroupByOp query = newFixture(// new IValueExpression[] { org, totalPriceExpr }, // select new IValueExpression[] { org }, // groupBy new IConstraint[] { totalPriceConstraint } // having ); /** * The test data: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org2 auth3 book4 7 * </pre> */ final IBindingSet data [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book1, price9 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book2, price5 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth2, book3, price7 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org2, auth3, book4, price7 } ) }; /** * The expected solutions: * * <pre> * ?org ?totalPrice * org1 84 * org2 14 * </pre> */ // Note: The aggregates will have gone through type promotion. final IConstant<XSDIntegerIV<BigdataLiteral>> _price84 = new Constant<XSDIntegerIV<BigdataLiteral>>( new XSDIntegerIV<BigdataLiteral>(BigInteger.valueOf(84))); final IConstant<XSDIntegerIV<BigdataLiteral>> _price14 = new Constant<XSDIntegerIV<BigdataLiteral>>( new XSDIntegerIV<BigdataLiteral>(BigInteger.valueOf(14))); final IBindingSet expected[] = new IBindingSet[] { new ListBindingSet ( new IVariable<?> [] { org, totalPrice }, new IConstant [] { org1, _price84 } ), new ListBindingSet ( new IVariable<?> [] { org, totalPrice }, new IConstant [] { org2, _price14 } ) } ; if (isPipelinedAggregationOp()) { try { query.newStats(); fail("Expecting " + UnsupportedOperationException.class); } catch (UnsupportedOperationException ex) { if (isPipelinedAggregationOp()) { if (log.isInfoEnabled()) log.info("Ignoring expected exception: " + ex); return; } else { throw ex; } } } 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 IRunningQuery runningQuery = new MockRunningQuery(null/* fed */ , kb.getIndexManager()/* indexManager */ , queryContext ); // Note: [lastInvocation:=true] forces the solutions to be emitted. final BOpContext<IBindingSet> context = new BOpContext<IBindingSet>( runningQuery, -1/* partitionId */ , stats, query/* op */, true/* lastInvocation */, source, sink, null/* sink2 */ ); // // Force the solutions to be emitted. // 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.assertSameSolutionsAnyOrder(expected, sink.iterator(), ft); assertEquals(1, stats.chunksIn.get()); assertEquals(4, stats.unitsIn.get()); assertEquals(2, stats.unitsOut.get()); assertEquals(1, stats.chunksOut.get()); } finally { kb.getIndexManager().destroy(); } } /** * A test in which there is a select dependency without there also being * nested aggregates. This test will detect a failure to propagate bindings * from eacn computed aggregate such that they are visible to the rest of * the aggregates to be computed. [The dependency MUST NOT be created * through the nesting of aggregates, which is already tested above. For * this test case we are concerned with aggregates which CAN be evaluated * using a pipelined aggregation operator.] * <p> * Based on an example in the SPARQL 1.1 Working Draft. * * <pre> * @prefix : <http://books.example/> . * * :org1 :affiliates :auth1, :auth2 . * :auth1 :writesBook :book1, :book2 . * :book1 :price 9 . * :book2 :price 5 . * :auth2 :writesBook :book3 . * :book3 :price 7 . * :org2 :affiliates :auth3 . * :auth3 :writesBook :book4 . * :book4 :price 7 . * </pre> * * <pre> * PREFIX : <http://books.example/> * SELECT (SUM(?lprice) AS ?totalPrice), (?totalPrice*2) as ?inflatedPrice * WHERE { * ?org :affiliates ?auth . * ?auth :writesBook ?book . * ?book :price ?lprice . * } * </pre> * * The inputs are: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org2 auth3 book4 7 * </pre> * * The solutions are: * * <pre> * ?totalPrice ?inflatedPrice * 28 56 * </pre> * * @throws ExecutionException * @throws InterruptedException */ public void test_aggregation_withoutGroupBy_withSelectDependency() { AbstractTripleStore kb = TestMockUtility.mockTripleStore(getName()); try { final String lexiconNamespace = kb.getLexiconRelation().getNamespace(); final GlobalAnnotations globals = new GlobalAnnotations(lexiconNamespace, ITx.READ_COMMITTED); final IVariable<IV> org = Var.var("org"); final IVariable<IV> auth = Var.var("auth"); final IVariable<IV> book = Var.var("book"); final IVariable<IV> lprice = Var.var("lprice"); final IVariable<IV> totalPrice = Var.var("totalPrice"); final IVariable<IV> inflatedPrice = Var.var("inflatedPrice"); final IConstant<String> org1 = new Constant<String>("org1"); final IConstant<String> org2 = new Constant<String>("org2"); final IConstant<String> auth1 = new Constant<String>("auth1"); final IConstant<String> auth2 = new Constant<String>("auth2"); final IConstant<String> auth3 = new Constant<String>("auth3"); final IConstant<String> book1 = new Constant<String>("book1"); final IConstant<String> book2 = new Constant<String>("book2"); final IConstant<String> book3 = new Constant<String>("book3"); final IConstant<String> book4 = new Constant<String>("book4"); final IConstant<XSDNumericIV<BigdataLiteral>> price5 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(5)); final IConstant<XSDNumericIV<BigdataLiteral>> price7 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(7)); final IConstant<XSDNumericIV<BigdataLiteral>> price9 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(9)); // SUM(?lprice) final IValueExpression<IV> totalPriceExpr = new Bind(totalPrice, new SUM(false/* distinct */, (IValueExpression<IV>) lprice)); // Note: This has a dependency on SUM(?lprice) final IValueExpression<IV> inflatedPriceExpr = new Bind(inflatedPrice, new MathBOp(totalPrice, new Constant(new XSDNumericIV(2)), MathBOp.MathOp.MULTIPLY, globals)); final IConstraint totalPriceConstraint = new SPARQLConstraint<XSDBooleanIV>( new CompareBOp( totalPrice, new Constant<XSDNumericIV<BigdataLiteral>>(new XSDNumericIV(10)), CompareOp.GT)); final GroupByOp query = newFixture(// new IValueExpression[] { totalPriceExpr, inflatedPriceExpr }, // select null, // groupBy new IConstraint[] { totalPriceConstraint } // having ); /** * The test data: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org2 auth3 book4 7 * </pre> */ final IBindingSet data [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book1, price9 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book2, price5 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth2, book3, price7 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org2, auth3, book4, price7 } ) }; /** * The expected solutions: * * <pre> * ?totalPrice ?inflatedPrice * 28 56 * </pre> */ // Note: The aggregates will have gone through type promotion. final IConstant<XSDIntegerIV<BigdataLiteral>> _price28 = new Constant<XSDIntegerIV<BigdataLiteral>>( new XSDIntegerIV<BigdataLiteral>(BigInteger.valueOf(28))); final IConstant<XSDIntegerIV<BigdataLiteral>> _price56 = new Constant<XSDIntegerIV<BigdataLiteral>>( new XSDIntegerIV<BigdataLiteral>(BigInteger.valueOf(56))); final IBindingSet expected[] = new IBindingSet[] { new ListBindingSet ( new IVariable<?> [] { totalPrice, inflatedPrice }, new IConstant [] { _price28, _price56 } ) } ; 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 IRunningQuery runningQuery = new MockRunningQuery(null/* fed */ , kb.getIndexManager()/* indexManager */ , queryContext ); // Note: [lastInvocation:=true] forces the solutions to be emitted. final BOpContext<IBindingSet> context = new BOpContext<IBindingSet>( runningQuery, -1/* partitionId */ , stats, query/* op */, true/* lastInvocation */, source, sink, null/* sink2 */ ); // // Force the solutions to be emitted. // 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.assertSameSolutionsAnyOrder(expected, sink.iterator(), ft); assertEquals(1, stats.chunksIn.get()); assertEquals(4, stats.unitsIn.get()); assertEquals(1, stats.unitsOut.get()); assertEquals(1, stats.chunksOut.get()); } finally { kb.getIndexManager().destroy(); } } /** * A test in which there is a select dependency without there also being * nested aggregates. This test will detect a failure to propagate bindings * from eacn computed aggregate such that they are visible to the rest of * the aggregates to be computed. [The dependency MUST NOT be created * through the nesting of aggregates, which is already tested above. For * this test case we are concerned with aggregates which CAN be evaluated * using a pipelined aggregation operator.] * <p> * Based on an example in the SPARQL 1.1 Working Draft. * * <pre> * @prefix : <http://books.example/> . * * :org1 :affiliates :auth1, :auth2 . * :auth1 :writesBook :book1, :book2 . * :book1 :price 9 . * :book2 :price 5 . * :auth2 :writesBook :book3 . * :book3 :price 7 . * :org2 :affiliates :auth3 . * :auth3 :writesBook :book4 . * :book4 :price 7 . * </pre> * * <pre> * PREFIX : <http://books.example/> * SELECT ?org, (SUM(?lprice) AS ?totalPrice), (?totalPrice*2) as ?inflatedPrice * WHERE { * ?org :affiliates ?auth . * ?auth :writesBook ?book . * ?book :price ?lprice . * } * GROUP BY ?org * </pre> * * The inputs are: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org2 auth3 book4 7 * </pre> * * The solutions are: * * <pre> * ?org ?totalPrice ?inflatedPrice * org1 21 42 * org2 7 14 * </pre> * * @throws ExecutionException * @throws InterruptedException */ public void test_aggregation_withGroupBy_withSelectDependency() { AbstractTripleStore kb = TestMockUtility.mockTripleStore(getName()); try { final String lexiconNamespace = kb.getLexiconRelation().getNamespace(); final GlobalAnnotations globals = new GlobalAnnotations(lexiconNamespace, ITx.READ_COMMITTED); final IVariable<IV> org = Var.var("org"); final IVariable<IV> auth = Var.var("auth"); final IVariable<IV> book = Var.var("book"); final IVariable<IV> lprice = Var.var("lprice"); final IVariable<IV> totalPrice = Var.var("totalPrice"); final IVariable<IV> inflatedPrice = Var.var("inflatedPrice"); final IConstant<String> org1 = new Constant<String>("org1"); final IConstant<String> org2 = new Constant<String>("org2"); final IConstant<String> auth1 = new Constant<String>("auth1"); final IConstant<String> auth2 = new Constant<String>("auth2"); final IConstant<String> auth3 = new Constant<String>("auth3"); final IConstant<String> book1 = new Constant<String>("book1"); final IConstant<String> book2 = new Constant<String>("book2"); final IConstant<String> book3 = new Constant<String>("book3"); final IConstant<String> book4 = new Constant<String>("book4"); final IConstant<XSDNumericIV<BigdataLiteral>> price5 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(5)); final IConstant<XSDNumericIV<BigdataLiteral>> price7 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(7)); final IConstant<XSDNumericIV<BigdataLiteral>> price9 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(9)); // SUM(?lprice) final IValueExpression<IV> totalPriceExpr = new Bind(totalPrice, new SUM(false/* distinct */, (IValueExpression<IV>) lprice)); // Note: This has a dependency on SUM(?lprice) final IValueExpression<IV> inflatedPriceExpr = new Bind(inflatedPrice, new MathBOp(totalPrice, new Constant(new XSDNumericIV(2)), MathBOp.MathOp.MULTIPLY, globals)); // final IConstraint totalPriceConstraint = new SPARQLConstraint<XSDBooleanIV>( // new CompareBOp( // totalPrice, // new Constant<XSDNumericIV<BigdataLiteral>>(new XSDNumericIV(10)), // CompareOp.GT)); final GroupByOp query = newFixture(// new IValueExpression[] { org, totalPriceExpr, inflatedPriceExpr }, // select new IValueExpression[] { org }, // groupBy null // having ); /** * The test data: * * <pre> * ?org ?auth ?book ?lprice * org1 auth1 book1 9 * org1 auth1 book3 5 * org1 auth2 book3 7 * org2 auth3 book4 7 * </pre> */ final IBindingSet data [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book1, price9 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth1, book2, price5 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org1, auth2, book3, price7 } ) , new ListBindingSet ( new IVariable<?> [] { org, auth, book, lprice }, new IConstant [] { org2, auth3, book4, price7 } ) }; /** * The expected solutions: * * <pre> * ?org ?totalPrice ?inflatedPrice * org1 21 42 * org2 7 14 * </pre> */ // Note: The aggregates will have gone through type promotion. final IConstant<XSDIntegerIV<BigdataLiteral>> _price7 = new Constant<XSDIntegerIV<BigdataLiteral>>( new XSDIntegerIV<BigdataLiteral>(BigInteger.valueOf(7))); final IConstant<XSDIntegerIV<BigdataLiteral>> _price14 = new Constant<XSDIntegerIV<BigdataLiteral>>( new XSDIntegerIV<BigdataLiteral>(BigInteger.valueOf(14))); final IConstant<XSDIntegerIV<BigdataLiteral>> _price21 = new Constant<XSDIntegerIV<BigdataLiteral>>( new XSDIntegerIV<BigdataLiteral>(BigInteger.valueOf(21))); final IConstant<XSDIntegerIV<BigdataLiteral>> _price42 = new Constant<XSDIntegerIV<BigdataLiteral>>( new XSDIntegerIV<BigdataLiteral>(BigInteger.valueOf(42))); final IBindingSet expected[] = new IBindingSet[] { new ListBindingSet ( new IVariable<?> [] { org, totalPrice, inflatedPrice }, new IConstant [] { org1, _price21, _price42 } ), new ListBindingSet ( new IVariable<?> [] { org, totalPrice, inflatedPrice }, new IConstant [] { org2, _price7, _price14 } ) } ; 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 IRunningQuery runningQuery = new MockRunningQuery(null/* fed */ , kb.getIndexManager()/* indexManager */ , queryContext ); // Note: [lastInvocation:=true] forces the solutions to be emitted. final BOpContext<IBindingSet> context = new BOpContext<IBindingSet>( runningQuery, -1/* partitionId */ , stats, query/* op */, true/* lastInvocation */, source, sink, null/* sink2 */ ); // // Force the solutions to be emitted. // 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.assertSameSolutionsAnyOrder(expected, sink.iterator(), ft); assertEquals(1, stats.chunksIn.get()); assertEquals(4, stats.unitsIn.get()); assertEquals(2, stats.unitsOut.get()); assertEquals(1, stats.chunksOut.get()); } finally { kb.getIndexManager().destroy(); } } /** * Based on * https://www.w3.org/2009/sparql/docs/tests/data-sparql11/grouping/group03.rq * * <pre> * @prefix : <http://example/> . * * :s1 :p 1 . * :s1 :q 9 . * :s2 :p 2 . * </pre> * * <pre> * PREFIX : <http://example/> * * SELECT ?w (SAMPLE(?v) AS ?S) * { * ?s :p ?v . * OPTIONAL { ?s :q ?w } * } * GROUP BY ?w * </pre> * * The solutions input to the GROUP_BY are: * * <pre> * ?w ?s ?v * 9 s1 1 * s2 2 * </pre> * * The aggregated solutions groups are: * * <pre> * ?w ?S * 9 1 * 2 * </pre> * * @throws ExecutionException * @throws InterruptedException */ public void test_aggregation_groupBy_by_error_values1() { AbstractTripleStore kb = TestMockUtility.mockTripleStore(getName()); try { final String lexiconNamespace = kb.getLexiconRelation().getNamespace(); final GlobalAnnotations globals = new GlobalAnnotations(lexiconNamespace, ITx.READ_COMMITTED); final IVariable<IV> w = Var.var("w"); final IVariable<IV> v = Var.var("v"); final IVariable<IV> S = Var.var("S"); final IVariable<IV> s = Var.var("s"); final IConstant<String> s1 = new Constant<String>("s1"); final IConstant<String> s2 = new Constant<String>("s2"); final IConstant<XSDNumericIV<BigdataLiteral>> num1 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(1)); final IConstant<XSDNumericIV<BigdataLiteral>> num2 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(2)); final IConstant<XSDNumericIV<BigdataLiteral>> num9 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(9)); // SAMPLE(?v) AS ?S final IValueExpression<IV> sampleVAsS = new Bind(S, new SAMPLE(false/* distinct */, (IValueExpression<IV>) v)); final GroupByOp query = newFixture(// new IValueExpression[] { w, sampleVAsS }, // select new IValueExpression[] { w }, // groupBy null // having ); /** * The test data: * * <pre> * ?w ?s ?v * 9 s1 1 * s2 2 * </pre> */ final IBindingSet data [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { w, s, v }, new IConstant [] { num9, s1, num1 } ) , new ListBindingSet ( new IVariable<?> [] { s, v }, new IConstant [] { s2, num2 } ) }; /** * The expected solutions: * * <pre> * ?w ?S * 9 1 * 2 * </pre> * * </pre> */ final IBindingSet expected[] = new IBindingSet[] { new ListBindingSet ( new IVariable<?> [] { w, S }, new IConstant [] { num9, num1 } ), new ListBindingSet ( new IVariable<?> [] { S }, new IConstant [] { num2 } ) }; 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 IRunningQuery runningQuery = new MockRunningQuery(null/* fed */ , kb.getIndexManager()/* indexManager */ , queryContext ); // Note: [lastInvocation:=true] forces the solutions to be emitted. final BOpContext<IBindingSet> context = new BOpContext<IBindingSet>( runningQuery, -1/* partitionId */ , stats, query/* op */, true/* lastInvocation */, source, sink, null/* sink2 */ ); 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.assertSameSolutionsAnyOrder(expected, sink.iterator(), ft); assertEquals(1, stats.chunksIn.get()); assertEquals(2, stats.unitsIn.get()); assertEquals(2, stats.unitsOut.get()); assertEquals(1, stats.chunksOut.get()); } finally { kb.getIndexManager().destroy(); } } // test_aggregation_groupBy_by_error_values1() /** * Based on * https://www.w3.org/2009/sparql/docs/tests/data-sparql11/grouping/group05.rq * * <pre> * @prefix : <http://example/> . * * :s1 :p 1 . * :s3 :p 1 . * :s1 :q 9 . * :s2 :p 2 . * </pre> * * <pre> * PREFIX : <http://example/> * * SELECT ?s ?w * { * ?s :p ?v . * OPTIONAL { ?s :q ?w } * } * GROUP BY ?s ?w * </pre> * * The solutions input to the GROUP_BY are: * * <pre> * ?w ?s ?v * 9 s1 1 * s2 2 * s3 1 * </pre> * * The aggregated solutions groups are: * * <pre> * ?s ?w * s1 9 * s2 * s3 * </pre> * * @throws ExecutionException * @throws InterruptedException */ public void test_aggregation_groupBy_by_error_values2() { AbstractTripleStore kb = TestMockUtility.mockTripleStore(getName()); try { final String lexiconNamespace = kb.getLexiconRelation().getNamespace(); final GlobalAnnotations globals = new GlobalAnnotations(lexiconNamespace, ITx.READ_COMMITTED); final IVariable<IV> w = Var.var("w"); final IVariable<IV> v = Var.var("v"); final IVariable<IV> S = Var.var("S"); final IVariable<IV> s = Var.var("s"); final IConstant<String> s1 = new Constant<String>("s1"); final IConstant<String> s2 = new Constant<String>("s2"); final IConstant<String> s3 = new Constant<String>("s3"); final IConstant<XSDNumericIV<BigdataLiteral>> num1 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(1)); final IConstant<XSDNumericIV<BigdataLiteral>> num2 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(2)); final IConstant<XSDNumericIV<BigdataLiteral>> num9 = new Constant<XSDNumericIV<BigdataLiteral>>( new XSDNumericIV<BigdataLiteral>(9)); final GroupByOp query = newFixture(// new IValueExpression[] { s, w }, // select new IValueExpression[] { s, w }, // groupBy null // having ); /** * The test data: * * <pre> * ?w ?s ?v * 9 s1 1 * s2 2 * s3 1 * </pre> */ final IBindingSet data [] = new IBindingSet [] { new ListBindingSet ( new IVariable<?> [] { w, s, v }, new IConstant [] { num9, s1, num1 } ) , new ListBindingSet ( new IVariable<?> [] { s, v }, new IConstant [] { s2, num2 } ) , new ListBindingSet ( new IVariable<?> [] { s, v }, new IConstant [] { s3, num1 } ) }; /** * The expected solutions: * * <pre> * ?s ?w * s1 9 * s2 * s3 * </pre> * * </pre> */ final IBindingSet expected[] = new IBindingSet[] { new ListBindingSet ( new IVariable<?> [] { s, w }, new IConstant [] { s1, num9 } ), new ListBindingSet ( new IVariable<?> [] { s }, new IConstant [] { s2 } ), new ListBindingSet ( new IVariable<?> [] { s }, new IConstant [] { s3 } ) }; 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 IRunningQuery runningQuery = new MockRunningQuery(null/* fed */ , kb.getIndexManager()/* indexManager */ , queryContext ); // Note: [lastInvocation:=true] forces the solutions to be emitted. final BOpContext<IBindingSet> context = new BOpContext<IBindingSet>( runningQuery, -1/* partitionId */ , stats, query/* op */, true/* lastInvocation */, source, sink, null/* sink2 */ ); 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.assertSameSolutionsAnyOrder(expected, sink.iterator(), ft); assertEquals(1, stats.chunksIn.get()); assertEquals(3, stats.unitsIn.get()); assertEquals(3, stats.unitsOut.get()); assertEquals(1, stats.chunksOut.get()); } finally { kb.getIndexManager().destroy(); } } // test_aggregation_groupBy_by_error_values2() // See also TestMemoryGroupByOp.test_aggregation_groupBy_by_error_values3() }