=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/DataQueryParams.java' --- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/DataQueryParams.java 2012-12-11 20:46:36 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/DataQueryParams.java 2012-12-12 15:29:04 +0000 @@ -172,6 +172,13 @@ return dimension; } + + @Override + public String toString() + { + return "[in: " + indicators + ", de: " + dataElements + ", pe: " + periods + + ", ou: " + organisationUnits + "]"; + } // ------------------------------------------------------------------------- // Get and set methods === modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultAnalyticsService.java' --- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultAnalyticsService.java 2012-12-11 20:46:36 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultAnalyticsService.java 2012-12-12 15:29:04 +0000 @@ -41,7 +41,7 @@ public class DefaultAnalyticsService implements AnalyticsService { - //TODO select from correct shard + //TODO select from correct partition //TODO period aggregation for multiple period types //TODO hierarchy aggregation for org units at multiple levels //TODO indicator aggregation === modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/QueryPlanner.java' --- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/QueryPlanner.java 2012-12-11 20:46:36 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/QueryPlanner.java 2012-12-12 15:29:04 +0000 @@ -39,7 +39,7 @@ public class QueryPlanner { /** - * Creates a list of DataParams. + * Creates a list of DataQueryParams. * * @param params the data query params. * @param optimalQueries the number of optimal queries for the planner to return. @@ -47,6 +47,8 @@ */ public static List planQuery( DataQueryParams params, int optimalQueries ) { + params = new DataQueryParams( params ); + List queries = new ArrayList(); ListMap tablePeriodMap = PartitionUtils.getTablePeriodMap( params.getPeriods() ); @@ -65,21 +67,23 @@ } else { - int pages = optimalQueries / tablePeriodMap.size(); - - String dimension = getPartitionDimension( params, pages ); - - List dimensionValues = params.getDimension( dimension ); - - List> valuePages = new PaginatedList( dimensionValues ).setNumberOfPages( pages ).getPages(); - + int pages = optimalQueries / tablePeriodMap.size(); // TODO individual no per table + for ( String tableName : tablePeriodMap.keySet() ) { - for ( List values : valuePages ) + params.setPeriods( tablePeriodMap.get( tableName ) ); + + String dimension = getPartitionDimension( params, pages ); + + List partitionValues = params.getDimension( dimension ); + + List> partitionValuePages = new PaginatedList( partitionValues ).setNumberOfPages( pages ).getPages(); + + for ( List valuePage : partitionValuePages ) { DataQueryParams query = new DataQueryParams( params ); query.setPeriods( tablePeriodMap.get( tableName ) ); - query.setDimension( dimension, values ); + query.setDimension( dimension, valuePage ); query.setTableName( tableName ); queries.add( query ); } @@ -89,7 +93,17 @@ return queries; } - private static String getPartitionDimension( DataQueryParams params, int optimalQueries ) + /** + * Gets the data dimension must suitable as partition key. Will first check + * if any of the dimensions have enough values to satisfy a optimal number of + * queries, and return that dimension if so. If not returns the dimension + * with the highest number of values. The order of the fixed dimensions are + * data element, organisation unit, period. + * + * @param params the data query parameters. + * @param optimalQueries the optimal number of queries to create. + */ + public static String getPartitionDimension( DataQueryParams params, int optimalQueries ) { SortedMap> map = params.getDimensionValuesMap(); === added directory 'dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/data' === added file 'dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/data/QueryPlannerTest.java' --- dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/data/QueryPlannerTest.java 1970-01-01 00:00:00 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/data/QueryPlannerTest.java 2012-12-12 15:29:04 +0000 @@ -0,0 +1,68 @@ +package org.hisp.dhis.analytics.data; + +/* + * Copyright (c) 2004-2012, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import java.util.Arrays; +import java.util.List; + +import org.hisp.dhis.analytics.DataQueryParams; +import org.junit.Test; + +import static org.hisp.dhis.analytics.DataQueryParams.*; +import static org.junit.Assert.*; + +public class QueryPlannerTest +{ + @Test + public void getPartitionDimension() + { + DataQueryParams params = new DataQueryParams(); + params.setDataElements( Arrays.asList( "a", "b", "c", "d" ) ); + params.setOrganisationUnits( Arrays.asList( "a", "b", "c", "d", "e" ) ); + params.setPeriods( Arrays.asList( "2000Q1", "2000Q2", "2000Q3", "2000Q4", "2001Q1", "2001Q2" ) ); + + assertEquals( DATAELEMENT_DIM_ID, QueryPlanner.getPartitionDimension( params, 3 ) ); + assertEquals( DATAELEMENT_DIM_ID, QueryPlanner.getPartitionDimension( params, 4 ) ); + assertEquals( ORGUNIT_DIM_ID, QueryPlanner.getPartitionDimension( params, 5 ) ); + assertEquals( PERIOD_DIM_ID, QueryPlanner.getPartitionDimension( params, 6 ) ); + assertEquals( PERIOD_DIM_ID, QueryPlanner.getPartitionDimension( params, 7 ) ); + } + + @Test + public void planQuery() + { + DataQueryParams params = new DataQueryParams(); + params.setDataElements( Arrays.asList( "a", "b", "c", "d" ) ); + params.setOrganisationUnits( Arrays.asList( "a", "b", "c", "d", "e" ) ); + params.setPeriods( Arrays.asList( "2000Q1", "2000Q2", "2000Q3", "2000Q4", "2001Q1", "2001Q2" ) ); + + List queries = QueryPlanner.planQuery( params, 4 ); + + assertEquals( 4, queries.size() ); + } +} === modified file 'dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/PartitionUtilsTest.java' --- dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/PartitionUtilsTest.java 2012-12-12 14:41:21 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/table/PartitionUtilsTest.java 2012-12-12 15:29:04 +0000 @@ -32,12 +32,14 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import java.util.Arrays; import java.util.Date; import java.util.List; import org.hisp.dhis.period.Cal; import org.hisp.dhis.period.Period; import org.hisp.dhis.period.YearlyPeriodType; +import org.hisp.dhis.system.util.ListMap; import org.junit.Test; public class PartitionUtilsTest @@ -78,4 +80,20 @@ assertEquals( p1, PartitionUtils.getPeriod( TABLE_NAME_TEMP + "_2000" ) ); assertEquals( p2, PartitionUtils.getPeriod( TABLE_NAME_TEMP + "_2001" ) ); } + + @Test + public void testGetTablePeriodMap() + { + ListMap map = PartitionUtils.getTablePeriodMap( Arrays.asList( "2000S1", "2000S2", "2001S1", "2001S2", "2002S1" ) ); + + assertEquals( 3, map.size() ); + + assertTrue( map.keySet().contains( TABLE_NAME + "_2000" ) ); + assertTrue( map.keySet().contains( TABLE_NAME + "_2001" ) ); + assertTrue( map.keySet().contains( TABLE_NAME + "_2002" ) ); + + assertEquals( 2, map.get( TABLE_NAME + "_2000" ).size() ); + assertEquals( 2, map.get( TABLE_NAME + "_2001" ).size() ); + assertEquals( 1, map.get( TABLE_NAME + "_2002" ).size() ); + } }