blob: 3d9baae39ceef3b39676b73e15cfacfc62618a06 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package org.apache.geode.cache.query.internal.aggregate;
import static org.apache.geode.cache.query.internal.aggregate.AbstractAggregator.downCast;
import static org.apache.geode.test.awaitility.GeodeAwaitility.await;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.ToIntFunction;
import java.util.stream.Collectors;
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import junitparams.naming.TestCaseName;
import org.junit.After;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.query.Query;
import org.apache.geode.cache.query.QueryService;
import org.apache.geode.cache.query.SelectResults;
import org.apache.geode.cache.query.Struct;
import org.apache.geode.cache.query.data.Portfolio;
import org.apache.geode.cache.query.data.PortfolioPdx;
import org.apache.geode.cache.query.data.Position;
import org.apache.geode.cache.query.data.PositionPdx;
import org.apache.geode.cache.query.internal.CompiledSelect;
import org.apache.geode.cache.query.internal.DefaultQuery;
import org.apache.geode.test.dunit.rules.ClusterStartupRule;
import org.apache.geode.test.dunit.rules.MemberVM;
import org.apache.geode.test.junit.rules.GfshCommandRule;
import org.apache.geode.test.junit.rules.VMProvider;
@RunWith(JUnitParamsRunner.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class AggregateFunctionsQueryDUnitTest implements Serializable {
private static final String regionName = "portfolio";
private static MemberVM locator, server1, server2, server3, server4;
@ClassRule
public static GfshCommandRule gfsh = new GfshCommandRule();
@ClassRule
public static ClusterStartupRule cluster = new ClusterStartupRule();
@BeforeClass
public static void beforeClass() throws Exception {
locator = cluster.startLocatorVM(0);
server1 = cluster.startServerVM(1, locator.getPort());
server2 = cluster.startServerVM(2, locator.getPort());
server3 = cluster.startServerVM(3, locator.getPort());
server4 = cluster.startServerVM(4, locator.getPort());
gfsh.connectAndVerify(locator);
}
private void createRegion(String regionType) {
gfsh.executeAndAssertThat("create region --name=" + regionName + " --type=" + regionType)
.statusIsSuccess();
locator.waitUntilRegionIsReadyOnExactlyThisManyServers("/" + regionName, 4);
}
private void createIndexes() {
gfsh.executeAndAssertThat(
"define index --name=shortIndex --expression=shortID --region=" + regionName)
.statusIsSuccess();
gfsh.executeAndAssertThat(
"define index --name=statusIndex --expression=status --region=" + regionName)
.statusIsSuccess();
gfsh.executeAndAssertThat(
"define index --name=idIndex --expression=ID --type=key --region=" + regionName)
.statusIsSuccess();
gfsh.executeAndAssertThat(
"define index --name=secIdIndex --expression=\"pos.secId\" --region=\"/" + regionName
+ " p, p.positions.values pos\"")
.statusIsSuccess();
gfsh.executeAndAssertThat("create defined indexes").statusIsSuccess();
// Wait Until Indexes are Fully Created.
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
Cache memberCache = ClusterStartupRule.getCache();
await().untilAsserted(
() -> assertThat(memberCache.getQueryService().getIndexes().size()).isEqualTo(4));
}, server1, server2, server3, server4);
}
private void populateRegion(boolean usePdx, int entriesAmount) {
assertThat(ClusterStartupRule.getCache()).isNotNull();
Region<Integer, Object> portfolioRegion = ClusterStartupRule.getCache().getRegion(regionName);
assertThat(portfolioRegion).isNotNull();
for (int i = 1; i < entriesAmount + 1; ++i) {
Object value;
if (usePdx) {
PortfolioPdx pfPdx = new PortfolioPdx(i);
pfPdx.shortID = (short) ((short) i / 5);
value = pfPdx;
} else {
Portfolio pf = new Portfolio(i);
pf.shortID = (short) ((short) i / 5);
value = pf;
}
portfolioRegion.put(i, value);
}
// Wait Until Region is Fully Populated.
await().untilAsserted(() -> assertThat(portfolioRegion.size()).isEqualTo(entriesAmount));
}
private Predicate<Object> hasStatus(boolean usePdx, boolean status) {
return object -> {
if (!usePdx) {
return (status == ((Portfolio) object).isActive());
} else {
return (status == ((PortfolioPdx) object).isActive());
}
};
}
private ToIntFunction<Object> toPortfolioID(boolean usePdx) {
return value -> {
if (!usePdx) {
return ((Portfolio) value).getID();
} else {
return ((PortfolioPdx) value).getID();
}
};
}
private ToIntFunction<Object> toPortfolioShortID(boolean usePdx) {
return value -> {
if (!usePdx) {
return ((Portfolio) value).shortID;
} else {
return ((PortfolioPdx) value).shortID;
}
};
}
private <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Set<Object> seen = ConcurrentHashMap.newKeySet();
return t -> seen.add(keyExtractor.apply(t));
}
private long countByStatus(boolean status, boolean usePdx) {
assertThat(ClusterStartupRule.getCache()).isNotNull();
Region<String, Object> region = ClusterStartupRule.getCache().getRegion(regionName);
return region.values()
.stream()
.filter(hasStatus(usePdx, status))
.count();
}
private long countDistinctShortIDsByStatus(boolean status, boolean usePdx) {
assertThat(ClusterStartupRule.getCache()).isNotNull();
Region<String, Object> region = ClusterStartupRule.getCache().getRegion(regionName);
return region.values()
.stream()
.filter(hasStatus(usePdx, status))
.filter(distinctByKey(value -> {
if (!usePdx) {
return ((Portfolio) value).shortID;
} else {
return ((PortfolioPdx) value).shortID;
}
}))
.count();
}
private double sumIDsByStatus(boolean status, boolean usePdx) {
assertThat(ClusterStartupRule.getCache()).isNotNull();
Region<String, Object> region = ClusterStartupRule.getCache().getRegion(regionName);
return region.values()
.stream()
.filter(hasStatus(usePdx, status))
.mapToInt(toPortfolioID(usePdx))
.sum();
}
private double sumDistinctShortIDsByStatus(boolean status, boolean usePdx) {
assertThat(ClusterStartupRule.getCache()).isNotNull();
Region<String, Object> region = ClusterStartupRule.getCache().getRegion(regionName);
return region.values()
.stream()
.filter(hasStatus(usePdx, status))
.filter(distinctByKey(value -> {
if (!usePdx) {
return ((Portfolio) value).shortID;
} else {
return ((PortfolioPdx) value).shortID;
}
}))
.mapToInt(toPortfolioShortID(usePdx))
.sum();
}
private int maxIDByStatus(boolean status, boolean usePdx) {
assertThat(ClusterStartupRule.getCache()).isNotNull();
Region<String, Object> region = ClusterStartupRule.getCache().getRegion(regionName);
return region.values()
.stream()
.filter(hasStatus(usePdx, status))
.mapToInt(toPortfolioID(usePdx))
.max().orElseThrow(IllegalArgumentException::new);
}
private int minIDByStatus(boolean status, boolean usePdx) {
assertThat(ClusterStartupRule.getCache()).isNotNull();
Region<String, Object> region = ClusterStartupRule.getCache().getRegion(regionName);
return region.values()
.stream()
.filter(hasStatus(usePdx, status))
.mapToInt(toPortfolioID(usePdx))
.min().orElseThrow(IllegalArgumentException::new);
}
@SuppressWarnings("unused")
private Object[] regionTypeAndOneBoolean() {
// Pdx, Alias , Nested Queries
return new Object[] {
new Object[] {"REPLICATE", true},
new Object[] {"REPLICATE", false},
new Object[] {"PARTITION", true},
new Object[] {"PARTITION", false},
};
}
@SuppressWarnings("unused")
private Object[] regionTypeAndTwoBooleans() {
// Pdx, Alias , Nested Queries
return new Object[] {
new Object[] {"REPLICATE", true, true},
new Object[] {"REPLICATE", true, false},
new Object[] {"REPLICATE", false, true},
new Object[] {"REPLICATE", false, false},
new Object[] {"PARTITION", true, true},
new Object[] {"PARTITION", true, false},
new Object[] {"PARTITION", false, true},
new Object[] {"PARTITION", false, false},
};
}
@SuppressWarnings("unused")
private Object[] regionTypeAndThreeBooleans() {
// Pdx, Alias , Nested Queries
return new Object[] {
new Object[] {"REPLICATE", true, true, true},
new Object[] {"REPLICATE", true, true, false},
new Object[] {"REPLICATE", true, false, true},
new Object[] {"REPLICATE", true, false, false},
new Object[] {"REPLICATE", false, true, true},
new Object[] {"REPLICATE", false, true, false},
new Object[] {"REPLICATE", false, false, true},
new Object[] {"REPLICATE", false, false, false},
new Object[] {"PARTITION", true, true, true},
new Object[] {"PARTITION", true, true, false},
new Object[] {"PARTITION", true, false, true},
new Object[] {"PARTITION", true, false, false},
new Object[] {"PARTITION", false, true, true},
new Object[] {"PARTITION", false, true, false},
new Object[] {"PARTITION", false, false, true},
new Object[] {"PARTITION", false, false, false},
};
}
@Test
@Parameters(method = "regionTypeAndTwoBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2})")
public void groupBySingleFieldShouldBeTransformableToDistinctOrderByAndReturnCorrectly(
String regionType, boolean usePdx, boolean useAlias) {
createRegion(regionType);
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 200), server1, server2, server3,
server4);
String queryString;
if (!useAlias) {
queryString =
"SELECT p.shortID FROM /" + regionName + " p WHERE p.ID >= 0 GROUP BY p.shortID ";
} else {
queryString = "SELECT p.shortID AS short_id FROM /" + regionName
+ " p WHERE p.ID >= 0 GROUP BY short_id ";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
CompiledSelect cs = ((DefaultQuery) query).getSelect();
assertThat(cs.isDistinct()).isTrue();
assertThat(cs.isOrderBy()).isTrue();
assertThat(cs.isGroupBy()).isFalse();
Region<String, Object> region = ClusterStartupRule.getCache().getRegion(regionName);
Map<Short, List<Object>> temp = region.values().stream().collect(
Collectors.groupingBy(value -> (short) toPortfolioShortID(usePdx).applyAsInt(value)));
Set<Short> expectedResults = temp.keySet();
@SuppressWarnings("unchecked")
SelectResults<Object> results = (SelectResults<Object>) query.execute();
assertThat(results.asList().size()).isEqualTo(expectedResults.size());
for (Object result : results.asList()) {
if (!useAlias) {
assertThat(result).isInstanceOf(Short.class);
assertThat(expectedResults.contains(result)).isTrue();
} else {
Struct struct = (Struct) result;
assertThat(struct.get("short_id")).isInstanceOf(Short.class);
assertThat(expectedResults.contains(struct.get("short_id"))).isTrue();
}
}
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndOneBoolean")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1})")
public void groupByMultipleFieldsShouldBeTransformableToDistinctOrderByAndReturnCorrectly(
String regionType, boolean usePdx) {
createRegion(regionType);
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 150), server1, server2, server3,
server4);
String queryString = "SELECT p.status AS status, p.ID FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY status, p.ID ";
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
CompiledSelect cs = ((DefaultQuery) query).getSelect();
assertThat(cs.isDistinct()).isTrue();
assertThat(cs.isOrderBy()).isTrue();
assertThat(cs.isGroupBy()).isFalse();
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(150);
for (Struct struct : results.asList()) {
Integer id = (Integer) struct.get("ID");
assertThat(((String) struct.get("status"))).isEqualTo(id % 2 == 0 ? "active" : "inactive");
}
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndThreeBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2},NestedQuery:{3})")
public void countStartWithGroupByShouldWorkCorrectly(String regionType, boolean usePdx,
boolean useAlias, boolean useNestedQuery) {
createRegion(regionType);
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 200), server1, server2, server3,
server4);
String expression = useNestedQuery
? "ELEMENT(SELECT * FROM /" + regionName + " iter WHERE iter.ID = p.ID)" : "*";
String queryString;
if (!useAlias) {
queryString = "SELECT p.status, COUNT(" + expression + ") FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY p.status";
} else {
queryString = "SELECT p.status AS st, COUNT(" + expression + ") AS ct FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY st";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
double activeCount = countByStatus(true, usePdx);
double inactiveCount = countByStatus(false, usePdx);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(2);
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
Optional<Struct> activeStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("active")).findAny();
assertThat(activeStruct.isPresent()).isTrue();
assertThat(activeStruct.get().getFieldValues()[1]).isEqualTo(downCast(activeCount));
Optional<Struct> inactiveStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("inactive")).findAny();
assertThat(inactiveStruct.isPresent()).isTrue();
assertThat(inactiveStruct.get().getFieldValues()[1]).isEqualTo(downCast(inactiveCount));
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndThreeBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2},NestedQuery:{3})")
public void countStartWithGroupByShouldWorkCorrectlyWithIndexes(String regionType, boolean usePdx,
boolean useAlias, boolean useNestedQuery) {
createRegion(regionType);
createIndexes();
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 200), server1, server2, server3,
server4);
String expression = useNestedQuery
? "ELEMENT(SELECT * FROM /" + regionName + " iter WHERE iter.ID = p.ID)" : "*";
String queryString;
if (!useAlias) {
queryString = "SELECT p.status, COUNT(" + expression + ") FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY p.status";
} else {
queryString = "SELECT p.status AS st, COUNT(" + expression + ") AS ct FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY st";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
double activeCount = countByStatus(true, usePdx);
double inactiveCount = countByStatus(false, usePdx);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(2);
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
Optional<Struct> activeStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("active")).findAny();
assertThat(activeStruct.isPresent()).isTrue();
assertThat(activeStruct.get().getFieldValues()[1]).isEqualTo(downCast(activeCount));
Optional<Struct> inactiveStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("inactive")).findAny();
assertThat(inactiveStruct.isPresent()).isTrue();
assertThat(inactiveStruct.get().getFieldValues()[1]).isEqualTo(downCast(inactiveCount));
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndThreeBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2},NestedQuery:{3})")
public void countDistinctWithGroupByShouldWorkCorrectly(String regionType, boolean usePdx,
boolean useAlias, boolean useNestedQuery) {
createRegion(regionType);
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 200), server1, server2, server3,
server4);
String expression = useNestedQuery
? "ELEMENT(SELECT iter.shortID FROM /" + regionName + " iter WHERE iter.ID = p.ID)"
: "p.shortID";
String queryString;
if (!useAlias) {
queryString = "SELECT p.status, COUNT(DISTINCT " + expression + ") FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY status";
} else {
queryString = "SELECT p.status AS st, COUNT(DISTINCT " + expression + ") AS ct FROM /"
+ regionName + " p WHERE p.ID > 0 GROUP BY st";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
double activeCount = countDistinctShortIDsByStatus(true, usePdx);
double inactiveCount = countDistinctShortIDsByStatus(false, usePdx);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(2);
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
Optional<Struct> activeStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("active")).findAny();
assertThat(activeStruct.isPresent()).isTrue();
assertThat(activeStruct.get().getFieldValues()[1]).isEqualTo(downCast(activeCount));
Optional<Struct> inactiveStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("inactive")).findAny();
assertThat(inactiveStruct.isPresent()).isTrue();
assertThat(inactiveStruct.get().getFieldValues()[1]).isEqualTo(downCast(inactiveCount));
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndThreeBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2},NestedQuery:{3})")
public void countDistinctWithGroupByShouldWorkCorrectlyWithIndexes(String regionType,
boolean usePdx, boolean useAlias, boolean useNestedQuery) {
createRegion(regionType);
createIndexes();
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 200), server1, server2, server3,
server4);
String expression = useNestedQuery
? "ELEMENT(SELECT iter.shortID FROM /" + regionName + " iter WHERE iter.ID = p.ID)"
: "p.shortID";
String queryString;
if (!useAlias) {
queryString = "SELECT p.status, COUNT(DISTINCT " + expression + ") FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY status";
} else {
queryString = "SELECT p.status AS st, COUNT(DISTINCT " + expression + ") AS ct FROM /"
+ regionName + " p WHERE p.ID > 0 GROUP BY st";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
double activeCount = countDistinctShortIDsByStatus(true, usePdx);
double inactiveCount = countDistinctShortIDsByStatus(false, usePdx);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(2);
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
Optional<Struct> activeStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("active")).findAny();
assertThat(activeStruct.isPresent()).isTrue();
assertThat(activeStruct.get().getFieldValues()[1]).isEqualTo(downCast(activeCount));
Optional<Struct> inactiveStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("inactive")).findAny();
assertThat(inactiveStruct.isPresent()).isTrue();
assertThat(inactiveStruct.get().getFieldValues()[1]).isEqualTo(downCast(inactiveCount));
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndTwoBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2})")
public void countWithGroupByShouldBeUsableWithinOrderByAndWorkCorrectly(String regionType,
boolean usePdx, boolean useAlias) {
createRegion(regionType);
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 600), server1, server2, server3,
server4);
String queryString;
if (!useAlias) {
queryString = "SELECT p.shortID, COUNT(*) FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY p.shortID ORDER BY COUNT(*) DESC";
} else {
queryString = "SELECT p.shortID AS shid, COUNT(*) AS ct FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY shid ORDER BY ct DESC";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
// Compute Expected Results
List<Object[]> expectedOrderedResults = new ArrayList<>();
Region<String, Object> region = ClusterStartupRule.getCache().getRegion(regionName);
Map<Short, Long> temp = region.values().stream().collect(Collectors.groupingBy(
value -> (short) toPortfolioShortID(usePdx).applyAsInt(value), Collectors.counting()));
temp.entrySet().stream().sorted(Map.Entry.<Short, Long>comparingByValue().reversed())
.forEachOrdered(e -> expectedOrderedResults
.add(new Object[] {e.getKey(), e.getValue().doubleValue()}));
// Execute Query
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(expectedOrderedResults.size());
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
// Assertions
List<Struct> queryResults = results.asList();
for (int i = 0; i < queryResults.size(); i++) {
Struct structResult = queryResults.get(i);
Object[] expectedResult = expectedOrderedResults.get(i);
assertThat(structResult.getFieldValues()[0]).isEqualTo(expectedResult[0]);
assertThat(structResult.getFieldValues()[1])
.isEqualTo(downCast((double) expectedResult[1]));
}
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndTwoBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2})")
public void countWithGroupByShouldBeUsableWithinOrderByAndWorkCorrectlyWithIndexes(
String regionType, boolean usePdx, boolean useAlias) {
createRegion(regionType);
createIndexes();
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 600), server1, server2, server3,
server4);
String queryString;
if (!useAlias) {
queryString = "SELECT p.shortID, COUNT(*) FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY p.shortID ORDER BY COUNT(*) DESC";
} else {
queryString = "SELECT p.shortID AS shid, COUNT(*) AS ct FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY shid ORDER BY ct DESC";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
// Compute Expected Results
List<Object[]> expectedOrderedResults = new ArrayList<>();
Region<String, Object> region = ClusterStartupRule.getCache().getRegion(regionName);
Map<Short, Long> temp = region.values().stream().collect(Collectors.groupingBy(
value -> (short) toPortfolioShortID(usePdx).applyAsInt(value), Collectors.counting()));
temp.entrySet().stream().sorted(Map.Entry.<Short, Long>comparingByValue().reversed())
.forEachOrdered(e -> expectedOrderedResults
.add(new Object[] {e.getKey(), e.getValue().doubleValue()}));
// Execute Query
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(expectedOrderedResults.size());
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
// Assertions
List<Struct> queryResults = results.asList();
for (int i = 0; i < queryResults.size(); i++) {
Struct structResult = queryResults.get(i);
Object[] expectedResult = expectedOrderedResults.get(i);
assertThat(structResult.getFieldValues()[0]).isEqualTo(expectedResult[0]);
assertThat(structResult.getFieldValues()[1])
.isEqualTo(downCast((double) expectedResult[1]));
}
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndThreeBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2},NestedQuery:{3})")
public void sumWithGroupByShouldWorkCorrectly(String regionType, boolean usePdx, boolean useAlias,
boolean useNestedQuery) {
createRegion(regionType);
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 600), server1, server2, server3,
server4);
String expression = useNestedQuery
? "ELEMENT(SELECT iter.ID FROM /" + regionName + " iter WHERE iter.ID = p.ID)" : "p.ID";
String queryString;
if (!useAlias) {
queryString = "SELECT p.status, SUM(" + expression + ") FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY status";
} else {
queryString = "SELECT p.status AS st, SUM(" + expression + ") AS sm FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY st";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
double activeSum = sumIDsByStatus(true, usePdx);
double inactiveSum = sumIDsByStatus(false, usePdx);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(2);
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
Optional<Struct> activeStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("active")).findAny();
assertThat(activeStruct.isPresent()).isTrue();
assertThat(activeStruct.get().getFieldValues()[1]).isEqualTo(downCast(activeSum));
Optional<Struct> inactiveStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("inactive")).findAny();
assertThat(inactiveStruct.isPresent()).isTrue();
assertThat(inactiveStruct.get().getFieldValues()[1]).isEqualTo(downCast(inactiveSum));
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndThreeBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2},NestedQuery:{3})")
public void sumWithGroupByShouldWorkCorrectlyWithIndexes(String regionType, boolean usePdx,
boolean useAlias, boolean useNestedQuery) {
createRegion(regionType);
createIndexes();
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 600), server1, server2, server3,
server4);
String expression = useNestedQuery
? "ELEMENT(SELECT iter.ID FROM /" + regionName + " iter WHERE iter.ID = p.ID)" : "p.ID";
String queryString;
if (!useAlias) {
queryString = "SELECT p.status, SUM(" + expression + ") FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY status";
} else {
queryString = "SELECT p.status AS st, SUM(" + expression + ") AS sm FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY st";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
double activeSum = sumIDsByStatus(true, usePdx);
double inactiveSum = sumIDsByStatus(false, usePdx);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(2);
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
Optional<Struct> activeStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("active")).findAny();
assertThat(activeStruct.isPresent()).isTrue();
assertThat(activeStruct.get().getFieldValues()[1]).isEqualTo(downCast(activeSum));
Optional<Struct> inactiveStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("inactive")).findAny();
assertThat(inactiveStruct.isPresent()).isTrue();
assertThat(inactiveStruct.get().getFieldValues()[1]).isEqualTo(downCast(inactiveSum));
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndThreeBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2},NestedQuery:{3})")
public void sumDistinctWithGroupByShouldWorkCorrectly(String regionType, boolean usePdx,
boolean useAlias, boolean useNestedQuery) {
createRegion(regionType);
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 600), server1, server2, server3,
server4);
String expression = useNestedQuery
? "ELEMENT(SELECT iter.shortID FROM /" + regionName + " iter WHERE iter.ID = p.ID)"
: "p.shortID";
String queryString;
if (!useAlias) {
queryString = "SELECT p.status, SUM(DISTINCT " + expression + ") FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY status";
} else {
queryString = "SELECT p.status AS st, SUM(DISTINCT " + expression + ") AS sm FROM /"
+ regionName + " p WHERE p.ID > 0 GROUP BY st";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
double activeDistinctShortIDsSum = sumDistinctShortIDsByStatus(true, usePdx);
double inactiveDistinctShortIDsSum = sumDistinctShortIDsByStatus(false, usePdx);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(2);
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
Optional<Struct> activeStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("active")).findAny();
assertThat(activeStruct.isPresent()).isTrue();
assertThat(activeStruct.get().getFieldValues()[1])
.isEqualTo(downCast(activeDistinctShortIDsSum));
Optional<Struct> inactiveStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("inactive")).findAny();
assertThat(inactiveStruct.isPresent()).isTrue();
assertThat(inactiveStruct.get().getFieldValues()[1])
.isEqualTo(downCast(inactiveDistinctShortIDsSum));
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndThreeBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2},NestedQuery:{3})")
public void sumDistinctWithGroupByShouldWorkCorrectlyWithIndexes(String regionType,
boolean usePdx, boolean useAlias, boolean useNestedQuery) {
createRegion(regionType);
createIndexes();
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 600), server1, server2, server3,
server4);
String expression = useNestedQuery
? "ELEMENT(SELECT iter.shortID FROM /" + regionName + " iter WHERE iter.ID = p.ID)"
: "p.shortID";
String queryString;
if (!useAlias) {
queryString = "SELECT p.status, SUM(DISTINCT " + expression + ") FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY status";
} else {
queryString = "SELECT p.status AS st, SUM(DISTINCT " + expression + ") AS sm FROM /"
+ regionName + " p WHERE p.ID > 0 GROUP BY st";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
double activeDistinctShortIDsSum = sumDistinctShortIDsByStatus(true, usePdx);
double inactiveDistinctShortIDsSum = sumDistinctShortIDsByStatus(false, usePdx);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(2);
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
Optional<Struct> activeStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("active")).findAny();
assertThat(activeStruct.isPresent()).isTrue();
assertThat(activeStruct.get().getFieldValues()[1])
.isEqualTo(downCast(activeDistinctShortIDsSum));
Optional<Struct> inactiveStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("inactive")).findAny();
assertThat(inactiveStruct.isPresent()).isTrue();
assertThat(inactiveStruct.get().getFieldValues()[1])
.isEqualTo(downCast(inactiveDistinctShortIDsSum));
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndTwoBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2})")
public void sumWithGroupByShouldBeUsableWithinOrderByAndWorkCorrectly(String regionType,
boolean usePdx, boolean useAlias) {
createRegion(regionType);
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 300), server1, server2, server3,
server4);
String queryString;
if (!useAlias) {
queryString = "SELECT p.shortID, SUM(p.ID) FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY p.shortID ORDER BY SUM(p.ID) ASC";
} else {
queryString = "SELECT p.shortID AS shid, SUM(p.ID) AS sm FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY shid ORDER BY sm ASC";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
// Compute Expected Results
List<Object[]> expectedOrderedResults = new ArrayList<>();
Region<String, Object> region = ClusterStartupRule.getCache().getRegion(regionName);
Map<Short, Integer> temp = region.values().stream().collect(
Collectors.groupingBy(value -> (short) toPortfolioShortID(usePdx).applyAsInt(value),
Collectors.summingInt(toPortfolioID(usePdx))));
temp.entrySet().stream().sorted(Map.Entry.comparingByValue())
.forEachOrdered(e -> expectedOrderedResults.add(new Object[] {e.getKey(), e.getValue()}));
// Execute Query
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(expectedOrderedResults.size());
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
// Assertions
List<Struct> queryResults = results.asList();
for (int i = 0; i < queryResults.size(); i++) {
Struct structResult = queryResults.get(i);
Object[] expectedResult = expectedOrderedResults.get(i);
assertThat(structResult.getFieldValues()[0]).isEqualTo(expectedResult[0]);
assertThat(structResult.getFieldValues()[1]).isEqualTo(expectedResult[1]);
}
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndTwoBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2})")
public void sumWithGroupByShouldBeUsableWithinOrderByAndWorkCorrectlyWithIndexes(
String regionType, boolean usePdx, boolean useAlias) {
createRegion(regionType);
createIndexes();
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 300), server1, server2, server3,
server4);
String queryString;
if (!useAlias) {
queryString = "SELECT p.shortID, SUM(p.ID) FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY p.shortID ORDER BY SUM(p.ID) ASC";
} else {
queryString = "SELECT p.shortID AS shid, SUM(p.ID) AS sm FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY shid ORDER BY sm ASC";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
// Compute Expected Results
List<Object[]> expectedOrderedResults = new ArrayList<>();
Region<String, Object> region = ClusterStartupRule.getCache().getRegion(regionName);
Map<Short, Integer> temp = region.values().stream().collect(
Collectors.groupingBy(value -> (short) toPortfolioShortID(usePdx).applyAsInt(value),
Collectors.summingInt(toPortfolioID(usePdx))));
temp.entrySet().stream().sorted(Map.Entry.comparingByValue())
.forEachOrdered(e -> expectedOrderedResults.add(new Object[] {e.getKey(), e.getValue()}));
// Execute Query
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(expectedOrderedResults.size());
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
// Assertions
List<Struct> queryResults = results.asList();
for (int i = 0; i < queryResults.size(); i++) {
Struct structResult = queryResults.get(i);
Object[] expectedResult = expectedOrderedResults.get(i);
assertThat(structResult.getFieldValues()[0]).isEqualTo(expectedResult[0]);
assertThat(structResult.getFieldValues()[1]).isEqualTo(expectedResult[1]);
}
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndThreeBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2},NestedQuery:{3})")
public void avgWithGroupByShouldWorkCorrectly(String regionType, boolean usePdx, boolean useAlias,
boolean useNestedQuery) {
createRegion(regionType);
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 300), server1, server2, server3,
server4);
String expression = useNestedQuery
? "ELEMENT(SELECT iter.ID FROM /" + regionName + " iter WHERE iter.ID = p.ID)" : "p.ID";
String queryString;
if (!useAlias) {
queryString = "SELECT p.status, AVG(" + expression + ") FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY status";
} else {
queryString = "SELECT p.status AS st, AVG(" + expression + ") AS av FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY st";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
double activeAvg = sumIDsByStatus(true, usePdx) / countByStatus(true, usePdx);
double inactiveAvg = sumIDsByStatus(false, usePdx) / countByStatus(false, usePdx);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(2);
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
Optional<Struct> activeStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("active")).findAny();
assertThat(activeStruct.isPresent()).isTrue();
assertThat(activeStruct.get().getFieldValues()[1]).isEqualTo(downCast(activeAvg));
Optional<Struct> inactiveStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("inactive")).findAny();
assertThat(inactiveStruct.isPresent()).isTrue();
assertThat(inactiveStruct.get().getFieldValues()[1]).isEqualTo(downCast(inactiveAvg));
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndThreeBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2},NestedQuery:{3})")
public void avgWithGroupByShouldWorkCorrectlyWithIndexes(String regionType, boolean usePdx,
boolean useAlias, boolean useNestedQuery) {
createRegion(regionType);
createIndexes();
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 300), server1, server2, server3,
server4);
String expression = useNestedQuery
? "ELEMENT(SELECT iter.ID FROM /" + regionName + " iter WHERE iter.ID = p.ID)" : "p.ID";
String queryString;
if (!useAlias) {
queryString = "SELECT p.status, AVG(" + expression + ") FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY status";
} else {
queryString = "SELECT p.status AS st, AVG(" + expression + ") AS av FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY st";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
double activeAvg = sumIDsByStatus(true, usePdx) / countByStatus(true, usePdx);
double inactiveAvg = sumIDsByStatus(false, usePdx) / countByStatus(false, usePdx);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(2);
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
Optional<Struct> activeStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("active")).findAny();
assertThat(activeStruct.isPresent()).isTrue();
assertThat(activeStruct.get().getFieldValues()[1]).isEqualTo(downCast(activeAvg));
Optional<Struct> inactiveStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("inactive")).findAny();
assertThat(inactiveStruct.isPresent()).isTrue();
assertThat(inactiveStruct.get().getFieldValues()[1]).isEqualTo(downCast(inactiveAvg));
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndThreeBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2},NestedQuery:{3})")
public void avgDistinctWithGroupByShouldWorkCorrectly(String regionType, boolean usePdx,
boolean useAlias, boolean useNestedQuery) {
createRegion(regionType);
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 300), server1, server2, server3,
server4);
String expression = useNestedQuery
? "ELEMENT(SELECT iter.shortID FROM /" + regionName + " iter WHERE iter.ID = p.ID)"
: "p.shortID";
String queryString;
if (!useAlias) {
queryString = "SELECT p.status, AVG(DISTINCT " + expression + ") FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY status";
} else {
queryString = "SELECT p.status AS st, AVG(DISTINCT p.shortID) AS av FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY st";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
double activeDistinctShortIDsAvg =
sumDistinctShortIDsByStatus(true, usePdx) / countDistinctShortIDsByStatus(true, usePdx);
double inactiveDistinctShortIDsAvg =
sumDistinctShortIDsByStatus(false, usePdx) / countDistinctShortIDsByStatus(false, usePdx);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(2);
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
Optional<Struct> activeStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("active")).findAny();
assertThat(activeStruct.isPresent()).isTrue();
assertThat(activeStruct.get().getFieldValues()[1])
.isEqualTo(downCast(activeDistinctShortIDsAvg));
Optional<Struct> inactiveStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("inactive")).findAny();
assertThat(inactiveStruct.isPresent()).isTrue();
assertThat(inactiveStruct.get().getFieldValues()[1])
.isEqualTo(downCast(inactiveDistinctShortIDsAvg));
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndThreeBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2},NestedQuery:{3})")
public void avgDistinctWithGroupByShouldWorkCorrectlyWithIndexes(String regionType,
boolean usePdx, boolean useAlias, boolean useNestedQuery) {
createRegion(regionType);
createIndexes();
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 300), server1, server2, server3,
server4);
String expression = useNestedQuery
? "ELEMENT(SELECT iter.shortID FROM /" + regionName + " iter WHERE iter.ID = p.ID)"
: "p.shortID";
String queryString;
if (!useAlias) {
queryString = "SELECT p.status, AVG(DISTINCT " + expression + ") FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY status";
} else {
queryString = "SELECT p.status AS st, AVG(DISTINCT p.shortID) AS av FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY st";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
double activeDistinctShortIDsAvg =
sumDistinctShortIDsByStatus(true, usePdx) / countDistinctShortIDsByStatus(true, usePdx);
double inactiveDistinctShortIDsAvg =
sumDistinctShortIDsByStatus(false, usePdx) / countDistinctShortIDsByStatus(false, usePdx);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(2);
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
Optional<Struct> activeStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("active")).findAny();
assertThat(activeStruct.isPresent()).isTrue();
assertThat(activeStruct.get().getFieldValues()[1])
.isEqualTo(downCast(activeDistinctShortIDsAvg));
Optional<Struct> inactiveStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("inactive")).findAny();
assertThat(inactiveStruct.isPresent()).isTrue();
assertThat(inactiveStruct.get().getFieldValues()[1])
.isEqualTo(downCast(inactiveDistinctShortIDsAvg));
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndTwoBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2})")
public void avgWithGroupByShouldBeUsableWithinOrderByAndWorkCorrectly(String regionType,
boolean usePdx, boolean useAlias) {
createRegion(regionType);
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 300), server1, server2, server3,
server4);
String queryString;
if (!useAlias) {
queryString = "SELECT p.shortID, AVG(p.ID) FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY p.shortID ORDER BY AVG(p.ID) DESC";
} else {
queryString = "SELECT p.shortID AS shid, AVG(p.ID) AS ag FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY shid ORDER BY ag DESC";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
// Compute Expected Results
List<Object[]> expectedOrderedResults = new ArrayList<>();
Region<String, Object> region = ClusterStartupRule.getCache().getRegion(regionName);
Map<Short, Double> temp = region.values().stream().collect(
Collectors.groupingBy(value -> (short) toPortfolioShortID(usePdx).applyAsInt(value),
Collectors.averagingInt(toPortfolioID(usePdx))));
temp.entrySet().stream().sorted(Map.Entry.<Short, Double>comparingByValue().reversed())
.forEachOrdered(e -> expectedOrderedResults.add(new Object[] {e.getKey(), e.getValue()}));
// Execute Query
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(expectedOrderedResults.size());
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
// Assertions
List<Struct> queryResults = results.asList();
for (int i = 0; i < queryResults.size(); i++) {
Struct structResult = queryResults.get(i);
Object[] expectedResult = expectedOrderedResults.get(i);
assertThat(structResult.getFieldValues()[0]).isEqualTo(expectedResult[0]);
assertThat(structResult.getFieldValues()[1])
.isEqualTo(downCast((double) expectedResult[1]));
}
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndTwoBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2})")
public void avgWithGroupByShouldBeUsableWithinOrderByAndWorkCorrectlyWithIndexes(
String regionType, boolean usePdx, boolean useAlias) {
createRegion(regionType);
createIndexes();
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 300), server1, server2, server3,
server4);
String queryString;
if (!useAlias) {
queryString = "SELECT p.shortID, AVG(p.ID) FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY p.shortID ORDER BY AVG(p.ID) DESC";
} else {
queryString = "SELECT p.shortID AS shid, AVG(p.ID) AS ag FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY shid ORDER BY ag DESC";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
// Compute Expected Results
List<Object[]> expectedOrderedResults = new ArrayList<>();
Region<String, Object> region = ClusterStartupRule.getCache().getRegion(regionName);
Map<Short, Double> temp = region.values().stream().collect(
Collectors.groupingBy(value -> (short) toPortfolioShortID(usePdx).applyAsInt(value),
Collectors.averagingInt(toPortfolioID(usePdx))));
temp.entrySet().stream().sorted(Map.Entry.<Short, Double>comparingByValue().reversed())
.forEachOrdered(e -> expectedOrderedResults.add(new Object[] {e.getKey(), e.getValue()}));
// Execute Query
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(expectedOrderedResults.size());
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
// Assertions
List<Struct> queryResults = results.asList();
for (int i = 0; i < queryResults.size(); i++) {
Struct structResult = queryResults.get(i);
Object[] expectedResult = expectedOrderedResults.get(i);
assertThat(structResult.getFieldValues()[0]).isEqualTo(expectedResult[0]);
assertThat(structResult.getFieldValues()[1])
.isEqualTo(downCast((double) expectedResult[1]));
}
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndThreeBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2},NestedQuery:{3})")
public void maxWithGroupByShouldWorkCorrectly(String regionType, boolean usePdx, boolean useAlias,
boolean useNestedQuery) {
createRegion(regionType);
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 300), server1, server2, server3,
server4);
String expression = useNestedQuery
? "ELEMENT(SELECT iter.ID FROM /" + regionName + " iter WHERE iter.ID = p.ID)" : "p.ID";
String queryString;
if (!useAlias) {
queryString = "SELECT p.status, MAX(" + expression + ") FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY status";
} else {
queryString = "SELECT p.status AS st, MAX(" + expression + ") as mx FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY st";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
int maxActiveID = maxIDByStatus(true, usePdx);
int maxInactiveID = maxIDByStatus(false, usePdx);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(2);
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
Optional<Struct> activeStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("active")).findAny();
assertThat(activeStruct.isPresent()).isTrue();
assertThat(activeStruct.get().getFieldValues()[1]).isEqualTo(maxActiveID);
Optional<Struct> inactiveStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("inactive")).findAny();
assertThat(inactiveStruct.isPresent()).isTrue();
assertThat(inactiveStruct.get().getFieldValues()[1]).isEqualTo(maxInactiveID);
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndThreeBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2},NestedQuery:{3})")
public void maxWithGroupByShouldWorkCorrectlyWithIndexes(String regionType, boolean usePdx,
boolean useAlias, boolean useNestedQuery) {
createRegion(regionType);
createIndexes();
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 300), server1, server2, server3,
server4);
String expression = useNestedQuery
? "ELEMENT(SELECT iter.ID FROM /" + regionName + " iter WHERE iter.ID = p.ID)" : "p.ID";
String queryString;
if (!useAlias) {
queryString = "SELECT p.status, MAX(" + expression + ") FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY status";
} else {
queryString = "SELECT p.status AS st, MAX(" + expression + ") as mx FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY st";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
int maxActiveID = maxIDByStatus(true, usePdx);
int maxInactiveID = maxIDByStatus(false, usePdx);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(2);
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
Optional<Struct> activeStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("active")).findAny();
assertThat(activeStruct.isPresent()).isTrue();
assertThat(activeStruct.get().getFieldValues()[1]).isEqualTo(maxActiveID);
Optional<Struct> inactiveStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("inactive")).findAny();
assertThat(inactiveStruct.isPresent()).isTrue();
assertThat(inactiveStruct.get().getFieldValues()[1]).isEqualTo(maxInactiveID);
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndThreeBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2},NestedQuery:{3})")
public void minWithGroupByShouldWorkCorrectly(String regionType, boolean usePdx, boolean useAlias,
boolean useNestedQuery) {
createRegion(regionType);
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 300), server1, server2, server3,
server4);
String expression = useNestedQuery
? "ELEMENT(SELECT iter.ID FROM /" + regionName + " iter WHERE iter.ID = p.ID)" : "p.ID";
String queryString;
if (!useAlias) {
queryString = "SELECT p.status, MIN(" + expression + ") FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY status";
} else {
queryString = "SELECT p.status AS st, MIN(" + expression + ") as mx FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY st";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
int minActiveID = minIDByStatus(true, usePdx);
int minInactiveID = minIDByStatus(false, usePdx);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(2);
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
Optional<Struct> activeStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("active")).findAny();
assertThat(activeStruct.isPresent()).isTrue();
assertThat(activeStruct.get().getFieldValues()[1]).isEqualTo(minActiveID);
Optional<Struct> inactiveStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("inactive")).findAny();
assertThat(inactiveStruct.isPresent()).isTrue();
assertThat(inactiveStruct.get().getFieldValues()[1]).isEqualTo(minInactiveID);
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndThreeBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2},NestedQuery:{3})")
public void minWithGroupByShouldWorkCorrectlyWithIndexes(String regionType, boolean usePdx,
boolean useAlias, boolean useNestedQuery) {
createRegion(regionType);
createIndexes();
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 300), server1, server2, server3,
server4);
String expression = useNestedQuery
? "ELEMENT(SELECT iter.ID FROM /" + regionName + " iter WHERE iter.ID = p.ID)" : "p.ID";
String queryString;
if (!useAlias) {
queryString = "SELECT p.status, MIN(" + expression + ") FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY status";
} else {
queryString = "SELECT p.status AS st, MIN(" + expression + ") as mx FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY st";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
int minActiveID = minIDByStatus(true, usePdx);
int minInactiveID = minIDByStatus(false, usePdx);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(2);
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
Optional<Struct> activeStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("active")).findAny();
assertThat(activeStruct.isPresent()).isTrue();
assertThat(activeStruct.get().getFieldValues()[1]).isEqualTo(minActiveID);
Optional<Struct> inactiveStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("inactive")).findAny();
assertThat(inactiveStruct.isPresent()).isTrue();
assertThat(inactiveStruct.get().getFieldValues()[1]).isEqualTo(minInactiveID);
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndThreeBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2},NestedQuery:{3})")
public void groupByMultipleFieldsWithAggregateFunctionsShouldWorkCorrectly(String regionType,
boolean usePdx, boolean useAlias, boolean useNestedQuery) {
createRegion(regionType);
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 300), server1, server2, server3,
server4);
String expression = useNestedQuery
? "ELEMENT(SELECT iter.ID FROM /" + regionName + " iter WHERE iter.ID = p.ID)" : "p.ID";
String queryString;
if (!useAlias) {
queryString = "SELECT p.status, p.description, SUM(" + expression + "), COUNT(" + expression
+ "), AVG(" + expression + ") FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY status, description";
} else {
queryString = "SELECT p.status AS st, p.description as ds, SUM(" + expression
+ ") as sm, COUNT(" + expression + ") as ag, AVG(" + expression + ") as ct FROM /"
+ regionName + " p WHERE p.ID > 0 GROUP BY st, ds";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
double activeCount = countByStatus(true, usePdx);
double inactiveCount = countByStatus(false, usePdx);
double activeSum = sumIDsByStatus(true, usePdx);
double inactiveSum = sumIDsByStatus(false, usePdx);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(2);
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
Optional<Struct> activeStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("active")).findAny();
assertThat(activeStruct.isPresent()).isTrue();
assertThat(activeStruct.get().getFieldValues()[1]).isNull();
assertThat(activeStruct.get().getFieldValues()[2]).isEqualTo(downCast(activeSum));
assertThat(activeStruct.get().getFieldValues()[3]).isEqualTo(downCast(activeCount));
assertThat(activeStruct.get().getFieldValues()[4])
.isEqualTo(downCast(activeSum / activeCount));
Optional<Struct> inactiveStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("inactive")).findAny();
assertThat(inactiveStruct.isPresent()).isTrue();
assertThat(inactiveStruct.get().getFieldValues()[1]).isEqualTo("XXXX");
assertThat(inactiveStruct.get().getFieldValues()[2]).isEqualTo(downCast(inactiveSum));
assertThat(inactiveStruct.get().getFieldValues()[3]).isEqualTo(downCast(inactiveCount));
assertThat(inactiveStruct.get().getFieldValues()[4])
.isEqualTo(downCast(inactiveSum / inactiveCount));
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndThreeBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2},NestedQuery:{3})")
public void groupByMultipleFieldsWithAggregateFunctionsShouldWorkCorrectlyWithIndexes(
String regionType, boolean usePdx, boolean useAlias, boolean useNestedQuery) {
createRegion(regionType);
createIndexes();
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 300), server1, server2, server3,
server4);
String expression = useNestedQuery
? "ELEMENT(SELECT iter.ID FROM /" + regionName + " iter WHERE iter.ID = p.ID)" : "p.ID";
String queryString;
if (!useAlias) {
queryString = "SELECT p.status, p.description, SUM(" + expression + "), COUNT(" + expression
+ "), AVG(" + expression + ") FROM /" + regionName
+ " p WHERE p.ID > 0 GROUP BY status, description";
} else {
queryString = "SELECT p.status AS st, p.description as ds, SUM(" + expression
+ ") as sm, COUNT(" + expression + ") as ag, AVG(" + expression + ") as ct FROM /"
+ regionName + " p WHERE p.ID > 0 GROUP BY st, ds";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
double activeCount = countByStatus(true, usePdx);
double inactiveCount = countByStatus(false, usePdx);
double activeSum = sumIDsByStatus(true, usePdx);
double inactiveSum = sumIDsByStatus(false, usePdx);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(2);
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
Optional<Struct> activeStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("active")).findAny();
assertThat(activeStruct.isPresent()).isTrue();
assertThat(activeStruct.get().getFieldValues()[1]).isNull();
assertThat(activeStruct.get().getFieldValues()[2]).isEqualTo(downCast(activeSum));
assertThat(activeStruct.get().getFieldValues()[3]).isEqualTo(downCast(activeCount));
assertThat(activeStruct.get().getFieldValues()[4])
.isEqualTo(downCast(activeSum / activeCount));
Optional<Struct> inactiveStruct = results.asList().stream()
.filter(struct -> struct.getFieldValues()[0].equals("inactive")).findAny();
assertThat(inactiveStruct.isPresent()).isTrue();
assertThat(inactiveStruct.get().getFieldValues()[1]).isEqualTo("XXXX");
assertThat(inactiveStruct.get().getFieldValues()[2]).isEqualTo(downCast(inactiveSum));
assertThat(inactiveStruct.get().getFieldValues()[3]).isEqualTo(downCast(inactiveCount));
assertThat(inactiveStruct.get().getFieldValues()[4])
.isEqualTo(downCast(inactiveSum / inactiveCount));
}, server1, server2, server3, server4);
}
@Test
@SuppressWarnings("unchecked")
@Parameters(method = "regionTypeAndTwoBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2})")
public void groupByWithMultipleAggregateFunctionAndsLimitClauseShouldWorkCorrectly(
String regionType, boolean usePdx, boolean useAlias) {
createRegion(regionType);
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 200), server1, server2, server3,
server4);
String queryString;
if (!useAlias) {
queryString =
"SELECT pos.secId, COUNT(pos.mktValue), MAX(pos.mktValue), MIN(pos.mktValue), SUM(pos.mktValue), AVG(pos.mktValue) FROM /"
+ regionName + " p, p.positions.values pos GROUP BY pos.secId LIMIT 7";
} else {
queryString =
"SELECT pos.secId AS posSec, COUNT(pos.mktValue) as ct, MAX(pos.mktValue) as mx, MIN(pos.mktValue) as mn, SUM(pos.mktValue) as sm, AVG(pos.mktValue) as ag FROM /"
+ regionName + " p, p.positions.values pos GROUP BY posSec LIMIT 7";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
Region<String, Object> region = ClusterStartupRule.getCache().getRegion(regionName);
// Pre-Populate Map of Expected Values
Map<String, List<Double>> mktValuesPerSecId = new HashMap<>();
Arrays.stream(Portfolio.secIds)
.forEach(secId -> mktValuesPerSecId.put(secId, new ArrayList<>()));
region.values().forEach(value -> {
if (!usePdx) {
Portfolio portfolio = ((Portfolio) value);
((Map<String, Position>) portfolio.positions).values()
.forEach(position -> mktValuesPerSecId.get(position.secId).add(position.mktValue));
} else {
PortfolioPdx portfolioPdx = ((PortfolioPdx) value);
((Map<String, PositionPdx>) portfolioPdx.positions).values().forEach(
position -> mktValuesPerSecId.get(position.secId).add(position.getMktValue()));
}
});
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(7);
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
results.forEach(struct -> {
String posSecId = (String) struct.getFieldValues()[0];
assertThat(mktValuesPerSecId.containsKey(posSecId)).isTrue();
List<Double> valuesPerSecId = mktValuesPerSecId.get(posSecId);
assertThat(struct.getFieldValues()[1]).isEqualTo(valuesPerSecId.size());
assertThat(struct.getFieldValues()[2]).isEqualTo(Collections.max(valuesPerSecId));
assertThat(struct.getFieldValues()[3]).isEqualTo(Collections.min(valuesPerSecId));
assertThat(struct.getFieldValues()[4])
.isEqualTo(downCast(valuesPerSecId.stream().mapToDouble(Double::doubleValue).sum()));
assertThat(struct.getFieldValues()[5]).isEqualTo(downCast(
valuesPerSecId.stream().mapToDouble(Double::doubleValue).average().orElse(0d)));
});
}, server1, server2, server3, server4);
}
@Test
@SuppressWarnings("unchecked")
@Parameters(method = "regionTypeAndTwoBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2})")
public void groupByWithMultipleAggregateFunctionAndsLimitClauseShouldWorkCorrectlyWithIndexes(
String regionType, boolean usePdx, boolean useAlias) {
createRegion(regionType);
createIndexes();
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 200), server1, server2, server3,
server4);
String queryString;
if (!useAlias) {
queryString =
"SELECT pos.secId, COUNT(pos.mktValue), MAX(pos.mktValue), MIN(pos.mktValue), SUM(pos.mktValue), AVG(pos.mktValue) FROM /"
+ regionName + " p, p.positions.values pos GROUP BY pos.secId LIMIT 7";
} else {
queryString =
"SELECT pos.secId AS posSec, COUNT(pos.mktValue) as ct, MAX(pos.mktValue) as mx, MIN(pos.mktValue) as mn, SUM(pos.mktValue) as sm, AVG(pos.mktValue) as ag FROM /"
+ regionName + " p, p.positions.values pos GROUP BY posSec LIMIT 7";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
Region<String, Object> region = ClusterStartupRule.getCache().getRegion(regionName);
// Pre-Populate Map of Expected Values
Map<String, List<Double>> mktValuesPerSecId = new HashMap<>();
Arrays.stream(Portfolio.secIds)
.forEach(secId -> mktValuesPerSecId.put(secId, new ArrayList<>()));
region.values().forEach(value -> {
if (!usePdx) {
Portfolio portfolio = ((Portfolio) value);
((Map<String, Position>) portfolio.positions).values()
.forEach(position -> mktValuesPerSecId.get(position.secId).add(position.mktValue));
} else {
PortfolioPdx portfolioPdx = ((PortfolioPdx) value);
((Map<String, PositionPdx>) portfolioPdx.positions).values().forEach(
position -> mktValuesPerSecId.get(position.secId).add(position.getMktValue()));
}
});
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(7);
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
results.forEach(struct -> {
String posSecId = (String) struct.getFieldValues()[0];
assertThat(mktValuesPerSecId.containsKey(posSecId)).isTrue();
List<Double> valuesPerSecId = mktValuesPerSecId.get(posSecId);
assertThat(struct.getFieldValues()[1]).isEqualTo(valuesPerSecId.size());
assertThat(struct.getFieldValues()[2]).isEqualTo(Collections.max(valuesPerSecId));
assertThat(struct.getFieldValues()[3]).isEqualTo(Collections.min(valuesPerSecId));
assertThat(struct.getFieldValues()[4])
.isEqualTo(downCast(valuesPerSecId.stream().mapToDouble(Double::doubleValue).sum()));
assertThat(struct.getFieldValues()[5]).isEqualTo(downCast(
valuesPerSecId.stream().mapToDouble(Double::doubleValue).average().orElse(0d)));
});
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndThreeBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2},NestedQuery:{3})")
public void aggregateFunctionsWithoutGroupByShouldWorkCorrectly(String regionType, boolean usePdx,
boolean useAlias, boolean useNestedQuery) {
createRegion(regionType);
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 300), server1, server2, server3,
server4);
String expression = useNestedQuery
? "ELEMENT(SELECT iter.ID FROM /" + regionName + " iter WHERE iter.ID = p.ID)" : "p.ID";
String queryString;
if (!useAlias) {
queryString = "SELECT AVG(" + expression + "), SUM(" + expression + "), MIN(" + expression
+ "), MAX(" + expression + "), COUNT(" + expression + ") FROM /" + regionName
+ " p WHERE p.ID > 0";
} else {
queryString = "SELECT AVG(" + expression + ") as ag, SUM(" + expression + ") as sm, MIN("
+ expression + ") as mn, MAX(" + expression + ") as mx, COUNT(" + expression
+ ") as ct FROM /" + regionName + " p WHERE p.ID > 0";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
Region<String, Object> region = ClusterStartupRule.getCache().getRegion(regionName);
int sumIDs = region.values().stream().mapToInt(toPortfolioID(usePdx)).sum();
int minID = region.values().stream().mapToInt(toPortfolioID(usePdx)).min().orElse(-1);
int maxID = region.values().stream().mapToInt(toPortfolioID(usePdx)).max().orElse(-1);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(1);
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
Struct structResult = results.asList().get(0);
assertThat(structResult).isNotNull();
assertThat(structResult.getFieldValues()[0])
.isEqualTo(downCast(((double) sumIDs / region.size())));
assertThat(structResult.getFieldValues()[1]).isEqualTo(sumIDs);
assertThat(structResult.getFieldValues()[2]).isEqualTo(minID);
assertThat(structResult.getFieldValues()[3]).isEqualTo(maxID);
assertThat(structResult.getFieldValues()[4]).isEqualTo(300);
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndThreeBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2},NestedQuery:{3})")
public void aggregateFunctionsWithoutGroupByShouldWorkCorrectlyWithIndexes(String regionType,
boolean usePdx, boolean useAlias, boolean useNestedQuery) {
createRegion(regionType);
createIndexes();
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 300), server1, server2, server3,
server4);
String expression = useNestedQuery
? "ELEMENT(SELECT iter.ID FROM /" + regionName + " iter WHERE iter.ID = p.ID)" : "p.ID";
String queryString;
if (!useAlias) {
queryString = "SELECT AVG(" + expression + "), SUM(" + expression + "), MIN(" + expression
+ "), MAX(" + expression + "), COUNT(" + expression + ") FROM /" + regionName
+ " p WHERE p.ID > 0";
} else {
queryString = "SELECT AVG(" + expression + ") as ag, SUM(" + expression + ") as sm, MIN("
+ expression + ") as mn, MAX(" + expression + ") as mx, COUNT(" + expression
+ ") as ct FROM /" + regionName + " p WHERE p.ID > 0";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
Region<String, Object> region = ClusterStartupRule.getCache().getRegion(regionName);
int sumIDs = region.values().stream().mapToInt(toPortfolioID(usePdx)).sum();
int minID = region.values().stream().mapToInt(toPortfolioID(usePdx)).min().orElse(-1);
int maxID = region.values().stream().mapToInt(toPortfolioID(usePdx)).max().orElse(-1);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(1);
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
Struct structResult = results.asList().get(0);
assertThat(structResult).isNotNull();
assertThat(structResult.getFieldValues()[0])
.isEqualTo(downCast(((double) sumIDs / region.size())));
assertThat(structResult.getFieldValues()[1]).isEqualTo(sumIDs);
assertThat(structResult.getFieldValues()[2]).isEqualTo(minID);
assertThat(structResult.getFieldValues()[3]).isEqualTo(maxID);
assertThat(structResult.getFieldValues()[4]).isEqualTo(300);
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndThreeBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2},NestedQuery:{3})")
public void aggregateFunctionsWithDistinctAndWithoutGroupByShouldWorkCorrectly(String regionType,
boolean usePdx, boolean useAlias, boolean useNestedQuery) {
createRegion(regionType);
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 300), server1, server2, server3,
server4);
String expression = useNestedQuery
? "ELEMENT(SELECT iter.shortID FROM /" + regionName + " iter WHERE iter.ID = p.ID)"
: "p.shortID";
String queryString;
if (!useAlias) {
queryString = "SELECT AVG(DISTINCT " + expression + "), SUM(DISTINCT " + expression
+ "), COUNT(DISTINCT " + expression + ") FROM /" + regionName
+ " p WHERE p.ID > 0 AND p.isActive() = true";
} else {
queryString = "SELECT AVG(DISTINCT " + expression + ") as ag, SUM(DISTINCT " + expression
+ ") as sm, COUNT(DISTINCT " + expression + ") as ct FROM /" + regionName
+ " p WHERE p.ID > 0 AND p.isActive() = true";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
double activeDistinctShortIDsSum = sumDistinctShortIDsByStatus(true, usePdx);
double activeDistinctShortIDsAvg =
activeDistinctShortIDsSum / countDistinctShortIDsByStatus(true, usePdx);
double activeDistinctShortIDsCount = countDistinctShortIDsByStatus(true, usePdx);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(1);
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
Struct structResult = results.asList().get(0);
assertThat(structResult).isNotNull();
assertThat(structResult.getFieldValues()[0]).isEqualTo(downCast(activeDistinctShortIDsAvg));
assertThat(structResult.getFieldValues()[1]).isEqualTo(downCast(activeDistinctShortIDsSum));
assertThat(structResult.getFieldValues()[2]).isEqualTo(downCast(activeDistinctShortIDsCount));
}, server1, server2, server3, server4);
}
@Test
@Parameters(method = "regionTypeAndThreeBooleans")
@TestCaseName("[{index}] {method}(RegionType:{0},PDX:{1},Alias:{2},NestedQuery:{3})")
public void aggregateFunctionsWithDistinctAndWithoutGroupByShouldWorkCorrectlyWithIndexes(
String regionType, boolean usePdx, boolean useAlias, boolean useNestedQuery) {
createRegion(regionType);
createIndexes();
VMProvider.invokeInRandomMember(() -> populateRegion(usePdx, 300), server1, server2, server3,
server4);
String expression = useNestedQuery
? "ELEMENT(SELECT iter.shortID FROM /" + regionName + " iter WHERE iter.ID = p.ID)"
: "p.shortID";
String queryString;
if (!useAlias) {
queryString = "SELECT AVG(DISTINCT " + expression + "), SUM(DISTINCT " + expression
+ "), COUNT(DISTINCT " + expression + ") FROM /" + regionName
+ " p WHERE p.ID > 0 AND p.isActive() = true";
} else {
queryString = "SELECT AVG(DISTINCT " + expression + ") as ag, SUM(DISTINCT " + expression
+ ") as sm, COUNT(DISTINCT " + expression + ") as ct FROM /" + regionName
+ " p WHERE p.ID > 0 AND p.isActive() = true";
}
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
QueryService queryService = ClusterStartupRule.getCache().getQueryService();
Query query = queryService.newQuery(queryString);
double activeDistinctShortIDsSum = sumDistinctShortIDsByStatus(true, usePdx);
double activeDistinctShortIDsAvg =
activeDistinctShortIDsSum / countDistinctShortIDsByStatus(true, usePdx);
double activeDistinctShortIDsCount = countDistinctShortIDsByStatus(true, usePdx);
@SuppressWarnings("unchecked")
SelectResults<Struct> results = (SelectResults<Struct>) query.execute();
assertThat(results.size()).isEqualTo(1);
assertThat(results.getCollectionType().getElementType().isStructType()).isTrue();
Struct structResult = results.asList().get(0);
assertThat(structResult).isNotNull();
assertThat(structResult.getFieldValues()[0]).isEqualTo(downCast(activeDistinctShortIDsAvg));
assertThat(structResult.getFieldValues()[1]).isEqualTo(downCast(activeDistinctShortIDsSum));
assertThat(structResult.getFieldValues()[2]).isEqualTo(downCast(activeDistinctShortIDsCount));
}, server1, server2, server3, server4);
}
@After
public void tearDown() {
// Always destroy everything to avoid race conditions with subsequent tests.
gfsh.executeAndAssertThat("clear defined indexes").statusIsSuccess();
gfsh.executeAndAssertThat("destroy region --name=" + regionName).statusIsSuccess();
gfsh.executeAndAssertThat("destroy index --name=shortIndex --if-exists").statusIsSuccess();
gfsh.executeAndAssertThat("destroy index --name=statusIndex --if-exists").statusIsSuccess();
gfsh.executeAndAssertThat("destroy index --name=idIndex --if-exists").statusIsSuccess();
gfsh.executeAndAssertThat("destroy index --name=secIdIndex --if-exists").statusIsSuccess();
VMProvider.invokeInEveryMember(() -> {
assertThat(ClusterStartupRule.getCache()).isNotNull();
Cache memberCache = ClusterStartupRule.getCache();
await().untilAsserted(() -> assertThat(memberCache.getRegion(regionName)).isNull());
await().untilAsserted(
() -> assertThat(memberCache.getQueryService().getIndexes().isEmpty()).isTrue());
}, server1, server2, server3, server4);
}
}