/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2016, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library 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 * Lesser General Public License for more details. */ package org.geotools.jdbc; import org.geotools.data.Query; import org.geotools.data.Query; import org.geotools.data.store.ContentFeatureSource; import org.geotools.feature.visitor.Aggregate; import org.geotools.feature.visitor.GroupByVisitor; import org.geotools.feature.visitor.GroupByVisitorBuilder; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.filter.Filter; import org.opengis.filter.FilterFactory; import java.io.IOException; import java.util.List; public abstract class JDBCGroupByVisitorOnlineTest extends JDBCTestSupport { public void testSimpleGroupByWithMax() throws Exception { List<Object[]> value = genericGroupByTestTest(Aggregate.MAX, "building_type"); assertTrue(value.size() == 3); checkValueContains(value, "HOUSE", "6.0"); checkValueContains(value, "FABRIC", "500.0"); checkValueContains(value, "SCHOOL", "60.0"); } public void testMultipleGroupByWithMax() throws Exception { List<Object[]> value = genericGroupByTestTest(Aggregate.MAX, "building_type", "energy_type"); assertTrue(value.size() == 11); checkValueContains(value, "SCHOOL", "WIND", "20.0"); checkValueContains(value, "SCHOOL", "FUEL", "60.0"); checkValueContains(value, "HOUSE", "NUCLEAR", "4.0"); checkValueContains(value, "SCHOOL", "SOLAR", "30.0"); checkValueContains(value, "SCHOOL", "FLOWING_WATER", "50.0"); checkValueContains(value, "SCHOOL", "NUCLEAR", "10.0"); checkValueContains(value, "HOUSE", "FUEL", "6.0"); checkValueContains(value, "FABRIC", "NUCLEAR", "150.0"); checkValueContains(value, "FABRIC", "SOLAR", "30.0"); checkValueContains(value, "FABRIC", "FLOWING_WATER", "500.0"); checkValueContains(value, "FABRIC", "WIND", "20.0"); } public void testMultipleGroupByWithMaxWithFilter() throws Exception { List<Object[]> value = genericGroupByTestTest(energyConsumptionGreaterThan(50.0), Aggregate.MAX, "building_type", "energy_type"); assertTrue(value.size() == 3); checkValueContains(value, "SCHOOL", "FUEL", "60.0"); checkValueContains(value, "FABRIC", "NUCLEAR", "150.0"); checkValueContains(value, "FABRIC", "FLOWING_WATER", "500.0"); } public void testMultipleGroupByWithMaxWithLimitOffset() throws Exception { if (!dataStore.getSQLDialect().isLimitOffsetSupported()) { return; } List<Object[]> value = genericGroupByTestTest(queryWithLimits(0, 3), Aggregate.MAX, "building_type", "energy_type"); assertFalse(value.isEmpty()); assertTrue(value.size() <= 3); } public void testSimpleGroupByWithMin() throws Exception { List<Object[]> value = genericGroupByTestTest(Aggregate.MIN, "building_type"); checkValueContains(value, "HOUSE", "4.0"); checkValueContains(value, "FABRIC", "20.0"); checkValueContains(value, "SCHOOL", "10.0"); } public void testMultipleGroupByWithMin() throws Exception { List<Object[]> value = genericGroupByTestTest(Aggregate.MIN, "building_type", "energy_type"); checkValueContains(value, "SCHOOL", "WIND", "20.0"); checkValueContains(value, "SCHOOL", "FUEL", "60.0"); checkValueContains(value, "HOUSE", "NUCLEAR", "4.0"); checkValueContains(value, "SCHOOL", "SOLAR", "30.0"); checkValueContains(value, "SCHOOL", "FLOWING_WATER", "50.0"); checkValueContains(value, "SCHOOL", "NUCLEAR", "10.0"); checkValueContains(value, "HOUSE", "FUEL", "6.0"); checkValueContains(value, "FABRIC", "NUCLEAR", "150.0"); checkValueContains(value, "FABRIC", "SOLAR", "30.0"); checkValueContains(value, "FABRIC", "FLOWING_WATER", "500.0"); checkValueContains(value, "FABRIC", "WIND", "20.0"); } public void testMultipleGroupByWithMinWithFilter() throws Exception { List<Object[]> value = genericGroupByTestTest(energyConsumptionGreaterThan(50.0), Aggregate.MIN, "building_type", "energy_type"); assertTrue(value.size() == 3); checkValueContains(value, "SCHOOL", "FUEL", "60.0"); checkValueContains(value, "FABRIC", "NUCLEAR", "150.0"); checkValueContains(value, "FABRIC", "FLOWING_WATER", "500.0"); } public void testMultipleGroupByWithMinWithLimitOffset() throws Exception { if (!dataStore.getSQLDialect().isLimitOffsetSupported()) { return; } List<Object[]> value = genericGroupByTestTest(queryWithLimits(0, 3), Aggregate.MIN, "building_type", "energy_type"); assertFalse(value.isEmpty()); assertTrue(value.size() <= 3); } public void testSimpleGroupByWithCount() throws Exception { List<Object[]> value = genericGroupByTestTest(Aggregate.COUNT, "building_type"); checkValueContains(value, "HOUSE", "2"); checkValueContains(value, "FABRIC", "4"); checkValueContains(value, "SCHOOL", "6"); } public void testMultipleGroupByWithCount() throws Exception { List<Object[]> value = genericGroupByTestTest(Aggregate.COUNT, "building_type", "energy_type"); checkValueContains(value, "SCHOOL", "WIND", "1"); checkValueContains(value, "SCHOOL", "FUEL", "1"); checkValueContains(value, "HOUSE", "NUCLEAR", "1"); checkValueContains(value, "SCHOOL", "SOLAR", "1"); checkValueContains(value, "SCHOOL", "FLOWING_WATER", "1"); checkValueContains(value, "SCHOOL", "NUCLEAR", "2"); checkValueContains(value, "HOUSE", "FUEL", "1"); checkValueContains(value, "FABRIC", "NUCLEAR", "1"); checkValueContains(value, "FABRIC", "SOLAR", "1"); checkValueContains(value, "FABRIC", "FLOWING_WATER", "1"); checkValueContains(value, "FABRIC", "WIND", "1"); } public void testMultipleGroupByWithCountWithFilter() throws Exception { List<Object[]> value = genericGroupByTestTest(energyConsumptionGreaterThan(50.0), Aggregate.COUNT, "building_type", "energy_type"); assertTrue(value.size() == 3); checkValueContains(value, "SCHOOL", "FUEL", "1"); checkValueContains(value, "FABRIC", "NUCLEAR", "1"); checkValueContains(value, "FABRIC", "FLOWING_WATER", "1"); } public void testMultipleGroupByWithCountWithLimitOffset() throws Exception { if (!dataStore.getSQLDialect().isLimitOffsetSupported()) { return; } List<Object[]> value = genericGroupByTestTest(queryWithLimits(0, 3), Aggregate.COUNT, "building_type", "energy_type"); assertFalse(value.isEmpty()); assertTrue(value.size() <= 3); } public void testSimpleGroupByWithSum() throws Exception { List<Object[]> value = genericGroupByTestTest(Aggregate.SUM, "building_type"); checkValueContains(value, "HOUSE", "10.0"); checkValueContains(value, "FABRIC", "700.0"); checkValueContains(value, "SCHOOL", "180.0"); } public void testMultipleGroupByWithSum() throws Exception { List<Object[]> value = genericGroupByTestTest(Aggregate.SUM, "building_type", "energy_type"); checkValueContains(value, "FABRIC", "FLOWING_WATER", "500.0"); checkValueContains(value, "FABRIC", "NUCLEAR", "150.0"); checkValueContains(value, "FABRIC", "SOLAR", "30.0"); checkValueContains(value, "FABRIC", "WIND", "20.0"); checkValueContains(value, "HOUSE", "FUEL", "6.0"); checkValueContains(value, "HOUSE", "NUCLEAR", "4.0"); checkValueContains(value, "SCHOOL", "FLOWING_WATER", "50.0"); checkValueContains(value, "SCHOOL", "FUEL", "60.0"); checkValueContains(value, "SCHOOL", "NUCLEAR", "20.0"); checkValueContains(value, "SCHOOL", "SOLAR", "30.0"); checkValueContains(value, "SCHOOL", "WIND", "20.0"); } public void testMultipleGroupByWithSumWithFilter() throws Exception { List<Object[]> value = genericGroupByTestTest(energyConsumptionGreaterThan(50.0), Aggregate.SUM, "building_type", "energy_type"); assertTrue(value.size() == 3); checkValueContains(value, "SCHOOL", "FUEL", "60.0"); checkValueContains(value, "FABRIC", "NUCLEAR", "150.0"); checkValueContains(value, "FABRIC", "FLOWING_WATER", "500.0"); } public void testWithMinWithLimitOffset() throws Exception { if (!dataStore.getSQLDialect().isLimitOffsetSupported()) { return; } List<Object[]> value = genericGroupByTestTest(queryWithLimits(0, 3), Aggregate.SUM, "building_type", "energy_type"); assertFalse(value.isEmpty()); assertTrue(value.size() <= 3); } private Query queryWithLimits(int lower, int upper) { Query query = new Query(tname("buildings")); query.setStartIndex(lower); query.setMaxFeatures(upper); return query; } private Query energyConsumptionGreaterThan(double value) { FilterFactory filterFactory = dataStore.getFilterFactory(); Filter filter = filterFactory.greater(filterFactory.property(aname("energy_consumption")), filterFactory.literal(value)); return new Query(tname("buildings"), filter); } private List<Object[]> genericGroupByTestTest(Aggregate aggregateVisitor, String... groupByAttributes) throws IOException { return genericGroupByTestTest(Query.ALL, aggregateVisitor, groupByAttributes); } private List<Object[]> genericGroupByTestTest(Query query, Aggregate aggregateVisitor, String... groupByAttributes) throws IOException { ContentFeatureSource featureSource = dataStore.getFeatureSource(tname("buildings_group_by_tests")); SimpleFeatureType featureType = featureSource.getSchema(); GroupByVisitorBuilder visitorBuilder = new GroupByVisitorBuilder() .withAggregateAttribute("energy_consumption", featureType) .withAggregateVisitor(aggregateVisitor); for (String groupByAttribute : groupByAttributes) { visitorBuilder.withGroupByAttribute(groupByAttribute, featureType); } GroupByVisitor visitor = visitorBuilder.build(); featureSource.accepts(query, visitor, null); assertTrue(visitor.wasOptimized()); assertFalse(visitor.wasVisited()); List<Object[]> value = visitor.getResult().toList(); assertNotNull(value); return value; } private void checkValueContains(List<Object[]> value, String... expectedResult) { assertTrue(value.stream().anyMatch(result -> { if (result.length != expectedResult.length) { return false; } for (int i = 0; i < result.length; i++) { if (!result[i].toString().equals(expectedResult[i])) { return false; } } return true; })); } }