/**
* diqube: Distributed Query Base.
*
* Copyright (C) 2015 Bastian Gloeckle
*
* This file is part of diqube.
*
* diqube is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.diqube.server.execution;
import java.util.Arrays;
import java.util.HashSet;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import org.diqube.data.column.ColumnType;
import org.diqube.execution.ExecutablePlan;
import org.testng.Assert;
import org.testng.annotations.Test;
/**
* Validates result of diql queries with GROUP BY.
*
* @author Bastian Gloeckle
*/
public abstract class GroupDiqlExecutionTest<T> extends AbstractCacheDoubleDiqlExecutionTest<T> {
public GroupDiqlExecutionTest(ColumnType colType, TestDataProvider<T> dp) {
super(colType, dp);
}
@Test
public void simpleSelectGroupTest() throws InterruptedException, ExecutionException {
Object[] colAValues = dp.emptyArray((int) VALUE_LENGTH);
for (int i = 0; i < colAValues.length; i++)
colAValues[i] = dp.v(i % 99);
initializeSimpleTable(colAValues, COL_B_DEFAULT_VALUES);
// GIVEN
// a simple select stmt
ExecutablePlan executablePlan = buildExecutablePlan("Select " + COL_A + " from " + TABLE + " group by " + COL_A);
ExecutorService executor = executors.newTestExecutor(executablePlan.preferredExecutorServiceSize());
try {
// WHEN
// executing it on the sample table
Future<Void> future = executablePlan.executeAsynchronously(executor);
future.get(); // wait until done.
// THEN
Assert.assertTrue(columnValueConsumerIsDone, "Source should have reported 'done'");
Assert.assertTrue(future.isDone(), "Future should report done");
Assert.assertFalse(future.isCancelled(), "Future should not report cancelled");
Assert.assertTrue(resultValues.containsKey(COL_A), "Result values should be available for column A");
Assert.assertEquals(resultValues.size(), 1, "Result values should be available for one column only");
Object[] expectedValues = dp.emptyArray(99);
for (int i = 0; i < 99; i++)
expectedValues[i] = dp.v(i);
Assert.assertEquals(new HashSet<>(resultValues.get(COL_A).values()), new HashSet<>(Arrays.asList(expectedValues)),
"Expected to receive values of 99 groups");
} finally {
executor.shutdownNow();
}
}
@Test
public void simpleSelectGroupWhereTest() throws InterruptedException, ExecutionException {
Object[] colAValues = dp.emptyArray((int) VALUE_LENGTH);
int lastIndexWithValueZero = -1;
for (int i = 0; i < colAValues.length; i++) {
colAValues[i] = dp.v(i % 99);
if (i % 99 == 0L)
lastIndexWithValueZero = i;
}
initializeSimpleTable(colAValues, COL_B_DEFAULT_VALUES);
// GIVEN
// a simple select stmt
ExecutablePlan executablePlan = buildExecutablePlan("Select " + COL_A + " from " + TABLE + " where " + //
COL_B + " = " + COL_B_DEFAULT_VALUES_DIQL[0] + " or " + //
COL_B + " = " + COL_B_DEFAULT_VALUES_DIQL[1] + " or " + //
COL_B + " = " + COL_B_DEFAULT_VALUES_DIQL[lastIndexWithValueZero] + //
" group by " + COL_A);
ExecutorService executor = executors.newTestExecutor(executablePlan.preferredExecutorServiceSize());
try {
// WHEN
// executing it on the sample table
Future<Void> future = executablePlan.executeAsynchronously(executor);
future.get(); // wait until done.
// THEN
Assert.assertTrue(columnValueConsumerIsDone, "Source should have reported 'done'");
Assert.assertTrue(future.isDone(), "Future should report done");
Assert.assertFalse(future.isCancelled(), "Future should not report cancelled");
Assert.assertTrue(resultValues.containsKey(COL_A), "Result values should be available for column A");
Assert.assertEquals(resultValues.size(), 1, "Result values should be available for one column only");
Object[] expectedValues = dp.a(0, 1); // for the first group value 0L, for the second group
// value 1L.
Assert.assertEquals(new HashSet<>(resultValues.get(COL_A).values()), new HashSet<>(Arrays.asList(expectedValues)),
"Expected to receive values of 2 groups");
} finally {
executor.shutdownNow();
}
}
@Test
public void simpleGroupAggregationTest() throws InterruptedException, ExecutionException {
Object[] colAValues = dp.a(1, 5, 100, 1, 99, 1);
Object[] colBValues = dp.a(0, 0, 0, 0, 0, 0);
initializeSimpleTable(colAValues, colBValues);
// GIVEN
// a simple select stmt
ExecutablePlan executablePlan = buildExecutablePlan(
"Select " + COL_A + ", count() from " + TABLE + " where " + COL_A + " = " + dp.vDiql(1) + " group by " + COL_A);
ExecutorService executor = executors.newTestExecutor(executablePlan.preferredExecutorServiceSize());
try {
// WHEN
// executing it on the sample table
Future<Void> future = executablePlan.executeAsynchronously(executor);
future.get(); // wait until done.
// THEN
Assert.assertTrue(columnValueConsumerIsDone, "Source should have reported 'done'");
Assert.assertTrue(future.isDone(), "Future should report done");
Assert.assertFalse(future.isCancelled(), "Future should not report cancelled");
Assert.assertTrue(resultValues.containsKey(COL_A), "Result values should be available for result column a");
String resColName = functionBasedColumnNameBuilderFactory.create().withFunctionName("count").build();
Assert.assertTrue(resultValues.containsKey(COL_A), "Result values should be available for result column a");
Assert.assertTrue(resultValues.containsKey(resColName),
"Result values should be available for result count column");
Assert.assertEquals(resultValues.size(), 2, "Result values should be available for one column only");
Object[] expectedValues = dp.a(1);
Assert.assertEquals(new HashSet<>(resultValues.get(COL_A).values()), new HashSet<>(Arrays.asList(expectedValues)),
"Expected to get value 1L as result for colA");
expectedValues = new Long[] { 3L };
Assert.assertEquals(new HashSet<>(resultValues.get(resColName).values()),
new HashSet<>(Arrays.asList(expectedValues)), "Expected to get value 3L as result for count col");
} finally {
executor.shutdownNow();
}
}
}