/**
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 Sep 2, 2010
*/
package com.bigdata.bop.controller;
import java.util.Properties;
import junit.framework.TestCase2;
import com.bigdata.bop.BOp;
import com.bigdata.bop.BOpEvaluationContext;
import com.bigdata.bop.Constant;
import com.bigdata.bop.IBindingSet;
import com.bigdata.bop.IConstant;
import com.bigdata.bop.IVariable;
import com.bigdata.bop.NV;
import com.bigdata.bop.PipelineOp;
import com.bigdata.bop.Var;
import com.bigdata.bop.ap.E;
import com.bigdata.bop.ap.R;
import com.bigdata.bop.bindingSet.EmptyBindingSet;
import com.bigdata.bop.bindingSet.ListBindingSet;
import com.bigdata.bop.bset.StartOp;
import com.bigdata.bop.engine.AbstractQueryEngineTestCase;
import com.bigdata.bop.engine.IRunningQuery;
import com.bigdata.bop.engine.QueryEngine;
import com.bigdata.bop.engine.StandaloneChunkHandler;
import com.bigdata.bop.solutions.SliceOp;
import com.bigdata.journal.BufferMode;
import com.bigdata.journal.ITx;
import com.bigdata.journal.Journal;
import com.bigdata.striterator.ChunkedArrayIterator;
/**
* Test suite for {@link Union}.
*
* @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a>
* @version $Id: TestUnionBindingSets.java 3500 2010-09-03 00:27:45Z thompsonbry
* $
*/
public class TestUnion extends TestCase2 {
/**
*
*/
public TestUnion() {
}
/**
* @param name
*/
public TestUnion(String name) {
super(name);
}
@Override
public Properties getProperties() {
final Properties p = new Properties(super.getProperties());
p.setProperty(Journal.Options.BUFFER_MODE, BufferMode.Transient
.toString());
return p;
}
private Journal jnl;
private QueryEngine queryEngine;
@Override
protected void setUp() throws Exception {
jnl = new Journal(getProperties());
loadData(jnl);
queryEngine = new QueryEngine(jnl);
queryEngine.init();
}
/**
* Create and populate relation in the {@link #namespace}.
*/
private void loadData(final Journal store) {
final String namespace = "ns";
// create the relation.
final R rel = new R(store, namespace, ITx.UNISOLATED, new Properties());
rel.create();
// data to insert (in key order for convenience).
final E[] a = {//
new E("John", "Mary"),// [0]
new E("Leon", "Paul"),// [1]
new E("Mary", "Paul"),// [2]
new E("Paul", "Leon"),// [3]
};
// insert data (the records are not pre-sorted).
rel
.insert(new ChunkedArrayIterator<E>(a.length, a, null/* keyOrder */));
// Do commit since not scale-out.
store.commit();
}
@Override
protected void tearDown() throws Exception {
if (queryEngine != null) {
queryEngine.shutdownNow();
queryEngine = null;
}
if (jnl != null) {
jnl.destroy();
jnl = null;
}
}
/**
* Verifies that the UNION of two operators is computed. The operators do
* not route around the UNION, so their solutions are copied to the UNION
* and from the UNION to onto the top-level query buffer. For this test
* variant, both subqueries run using their default inputs, which is a
* single empty binding set each. This gives us two empty binding sets as
* the output of the union.
*
* @throws Exception
*/
public void test_union_defaultInputs() throws Exception {
final int startId1 = 1;
final int startId2 = 2;
final int unionId = 3;
final BOp startOp1 = new StartOp(new BOp[] {}, NV.asMap(new NV[] {//
new NV(StartOp.Annotations.BOP_ID, startId1),//
new NV(StartOp.Annotations.EVALUATION_CONTEXT,
BOpEvaluationContext.CONTROLLER),//
}));
final BOp startOp2 = new StartOp(new BOp[] {}, NV.asMap(new NV[] {//
new NV(StartOp.Annotations.BOP_ID, startId2),//
new NV(StartOp.Annotations.EVALUATION_CONTEXT,
BOpEvaluationContext.CONTROLLER),//
}));
final BOp unionOp = new Union(new BOp[0], NV
.asMap(new NV[] {//
new NV(Union.Annotations.BOP_ID, unionId),//
new NV(Union.Annotations.SUBQUERIES, new BOp[] {
startOp1, startOp2 }),//
new NV(QueryEngine.Annotations.CHUNK_HANDLER,
StandaloneChunkHandler.TEST_INSTANCE),//
// new NV(Union.Annotations.EVALUATION_CONTEXT,
// BOpEvaluationContext.CONTROLLER),//
// new NV(Union.Annotations.CONTROLLER, true),//
}));
final BOp query = unionOp;
// the expected solutions.
final IBindingSet[] expected = new IBindingSet[] {//
EmptyBindingSet.INSTANCE,
EmptyBindingSet.INSTANCE,
};
final IRunningQuery runningQuery = queryEngine.eval(query);
// verify solutions.
AbstractQueryEngineTestCase.assertSameSolutionsAnyOrder(expected,
runningQuery);
}
public void test_union_consumesSource() throws Exception {
final int startId1 = 1;
final int startId2 = 2;
final int unionId = 3;
final BOp startOp1 = new StartOp(new BOp[] {}, NV.asMap(new NV[] {//
new NV(StartOp.Annotations.BOP_ID, startId1),//
new NV(StartOp.Annotations.EVALUATION_CONTEXT,
BOpEvaluationContext.CONTROLLER),//
}));
final BOp startOp2 = new StartOp(new BOp[] {}, NV.asMap(new NV[] {//
new NV(StartOp.Annotations.BOP_ID, startId2),//
new NV(StartOp.Annotations.EVALUATION_CONTEXT,
BOpEvaluationContext.CONTROLLER),//
}));
final BOp unionOp = new Union(new BOp[]{}, NV
.asMap(new NV[] {//
new NV(Union.Annotations.BOP_ID, unionId),//
new NV(Union.Annotations.SUBQUERIES, new BOp[] {
startOp1, startOp2 }), //
new NV(QueryEngine.Annotations.CHUNK_HANDLER,
StandaloneChunkHandler.TEST_INSTANCE),//
// new NV(Union.Annotations.EVALUATION_CONTEXT,
// BOpEvaluationContext.CONTROLLER),//
// new NV(Union.Annotations.CONTROLLER, true),//
}));
final BOp query = unionOp;
/*
* Create an initial non-empty binding set.
*/
final IBindingSet bset = new ListBindingSet();
bset.set(Var.var("x"), new Constant<String>("John"));
bset.set(Var.var("y"), new Constant<String>("Mary"));
// the expected solutions.
final IBindingSet[] expected = new IBindingSet[] {//
bset, // one copy from the left side of the union.
bset, // one copy from the right side of the union.
};
final IRunningQuery runningQuery = queryEngine.eval(query, bset);
// verify solutions.
AbstractQueryEngineTestCase.assertSameSolutionsAnyOrder(expected,
runningQuery);
}
/**
* Verifies that the UNION of two operators is computed.
*
* @throws Exception
*/
public void test_union() throws Exception {
final int startId1 = 1;
final int startId2 = 2;
final int unionId = 3;
final int sliceId = 4;
final IVariable<?> x = Var.var("x");
final IVariable<?> y = Var.var("y");
final IBindingSet[] bindingSets1 = new IBindingSet[1];
{
final IBindingSet tmp = new ListBindingSet();
tmp.set(x, new Constant<String>("Leon"));
bindingSets1[0] = tmp;
}
final IBindingSet[] bindingSets2 = new IBindingSet[1];
{
final IBindingSet tmp = new ListBindingSet();
tmp.set(x, new Constant<String>("Mary"));
tmp.set(y, new Constant<String>("John"));
bindingSets2[0] = tmp;
}
final BOp startOp1 = new StartOp(new BOp[] {}, NV.asMap(new NV[] {//
new NV(StartOp.Annotations.BOP_ID, startId1),//
new NV(StartOp.Annotations.EVALUATION_CONTEXT,
BOpEvaluationContext.CONTROLLER),//
new NV(StartOp.Annotations.BINDING_SETS,bindingSets1)
}));
final BOp startOp2 = new StartOp(new BOp[] {}, NV.asMap(new NV[] {//
new NV(StartOp.Annotations.BOP_ID, startId2),//
new NV(StartOp.Annotations.EVALUATION_CONTEXT,
BOpEvaluationContext.CONTROLLER),//
new NV(StartOp.Annotations.BINDING_SETS,bindingSets2)
}));
final BOp unionOp = new Union(new BOp[] {}, NV
.asMap(new NV[] {//
new NV(Union.Annotations.BOP_ID, unionId),//
new NV(Union.Annotations.SUBQUERIES, new BOp[] {
startOp1, startOp2 }) //
// new NV(Union.Annotations.EVALUATION_CONTEXT,
// BOpEvaluationContext.CONTROLLER),//
// new NV(Union.Annotations.CONTROLLER, true),//
}));
final BOp sliceOp = new SliceOp(new BOp[]{unionOp},NV.asMap(
new NV(Union.Annotations.BOP_ID, sliceId),//
new NV(Union.Annotations.EVALUATION_CONTEXT,
BOpEvaluationContext.CONTROLLER),//
new NV(PipelineOp.Annotations.SHARED_STATE,true),//
new NV(PipelineOp.Annotations.REORDER_SOLUTIONS,false),//
new NV(QueryEngine.Annotations.CHUNK_HANDLER,
StandaloneChunkHandler.TEST_INSTANCE)//
));
final BOp query = sliceOp;
// the expected solutions.
final IBindingSet[] expected = new IBindingSet[] {//
new ListBindingSet(//
new IVariable[] { x },//
new IConstant[] { new Constant<String>("Leon") }//
), //
new ListBindingSet(//
new IVariable[] { x, y },//
new IConstant[] { new Constant<String>("Mary"),
new Constant<String>("John") }//
),//
};
final IRunningQuery runningQuery = queryEngine.eval(query);
// verify solutions.
AbstractQueryEngineTestCase.assertSameSolutionsAnyOrder(expected,
runningQuery);
}
}