← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 20638: Event analytics, Fixed bug related to program indicators and multiple partitions.

 

------------------------------------------------------------
revno: 20638
committer: Lars Helge Overland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Mon 2015-10-12 17:02:17 +0200
message:
  Event analytics, Fixed bug related to program indicators and multiple partitions.
modified:
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEventAnalyticsManager.java
  dhis-2/dhis-support/dhis-support-commons/src/main/java/org/hisp/dhis/commons/collection/ListUtils.java


--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEventAnalyticsManager.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEventAnalyticsManager.java	2015-10-12 11:46:32 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEventAnalyticsManager.java	2015-10-12 15:02:17 +0000
@@ -56,6 +56,7 @@
 import org.hisp.dhis.common.NameableObject;
 import org.hisp.dhis.common.QueryFilter;
 import org.hisp.dhis.common.QueryItem;
+import org.hisp.dhis.commons.collection.ListUtils;
 import org.hisp.dhis.commons.util.ExpressionUtils;
 import org.hisp.dhis.commons.util.TextUtils;
 import org.hisp.dhis.jdbc.StatementBuilder;
@@ -104,7 +105,7 @@
     {
         String countClause = getAggregateClause( params );
         
-        String sql = "select " + countClause + " as value," + getSelectColumns( params ) + " ";
+        String sql = "select " + countClause + " as value," + StringUtils.join( getSelectColumns( params ), "," ) + " ";
 
         // ---------------------------------------------------------------------
         // Criteria
@@ -116,7 +117,7 @@
         // Group by
         // ---------------------------------------------------------------------
 
-        sql += "group by " + getSelectColumns( params ) + " ";
+        sql += "group by " + StringUtils.join( getSelectColumns( params ), "," ) + " ";
 
         // ---------------------------------------------------------------------
         // Sort order
@@ -217,7 +218,9 @@
     {
         List<String> fixedCols = Lists.newArrayList( "psi", "ps", "executiondate", "longitude", "latitude", "ouname", "oucode" );
         
-        String sql = "select " + getSelectString( fixedCols ) + getSelectColumns( params ) + " ";
+        List<String> selectCols = ListUtils.distinctUnion( fixedCols, getSelectColumns( params ) );
+        
+        String sql = "select " + StringUtils.join( selectCols, "," ) + " ";
 
         // ---------------------------------------------------------------------
         // Criteria
@@ -405,11 +408,11 @@
         {
             if ( EventOutputType.TRACKED_ENTITY_INSTANCE.equals( outputType ) && params.isProgramRegistration() )
             {
-                return Lists.newArrayList( "tei" );
+                return Lists.newArrayList( statementBuilder.columnQuote( "tei" ) );
             }
             else if ( EventOutputType.ENROLLMENT.equals( outputType ) )
             {
-                return Lists.newArrayList( "pi" );
+                return Lists.newArrayList( statementBuilder.columnQuote( "pi" ) );
             }
         }
         
@@ -418,15 +421,15 @@
     
     /**
      * Returns the dynamic select columns. Dimensions come first and query items
-     * second.
+     * second. Program indicator expressions are converted to SQL expressions.
      */
-    private String getSelectColumns( EventQueryParams params )
+    private List<String> getSelectColumns( EventQueryParams params )
     {
-        String sql = "";
+        List<String> columns = Lists.newArrayList();
         
         for ( DimensionalObject dimension : params.getDimensions() )
         {
-            sql += statementBuilder.columnQuote( dimension.getDimensionName() ) + ",";
+            columns.add( statementBuilder.columnQuote( dimension.getDimensionName() ) );
         }
         
         for ( QueryItem queryItem : params.getItems() )
@@ -435,17 +438,53 @@
             {
                 ProgramIndicator in = (ProgramIndicator) queryItem.getItem();
                 
-                sql += "(" + programIndicatorService.getAnalyticsSQl( in.getExpression() ) + "),";
+                columns.add( "(" + programIndicatorService.getAnalyticsSQl( in.getExpression() ) + ")" );
             }
             else
             {
-                sql += statementBuilder.columnQuote( queryItem.getItemName() ) + ",";
+                columns.add( statementBuilder.columnQuote( queryItem.getItemName() ) );
             }
         }
         
-        return removeLastComma( sql );
+        return columns;
     }
 
+    /**
+     * Returns the dynamic select columns. Dimensions come first and query items
+     * second. Program indicator expressions are exploded into attributes and
+     * data element identifiers.
+     */
+    private List<String> getPartitionSelectColumns( EventQueryParams params )
+    {
+        List<String> columns = Lists.newArrayList();
+        
+        for ( DimensionalObject dimension : params.getDimensions() )
+        {
+            columns.add( statementBuilder.columnQuote( dimension.getDimensionName() ) );
+        }
+        
+        for ( QueryItem queryItem : params.getItems() )
+        {
+            if ( queryItem.isProgramIndicator() )
+            {
+                ProgramIndicator in = (ProgramIndicator) queryItem.getItem();
+                
+                Set<String> uids = ProgramIndicator.getDataElementAndAttributeIdentifiers( in.getExpression() );
+                
+                for ( String uid : uids )
+                {
+                    columns.add( statementBuilder.columnQuote( uid ) );
+                }
+            }
+            else
+            {
+                columns.add( statementBuilder.columnQuote( queryItem.getItemName() ) );
+            }
+        }
+        
+        return columns;
+    }
+    
     private String getFromWhereClause( EventQueryParams params, List<String> fixedColumns )
     {
         if ( params.spansMultiplePartitions() )
@@ -460,15 +499,17 @@
     
     private String getFromWhereMultiplePartitionsClause( EventQueryParams params, List<String> fixedColumns )
     {
-        List<String> aggregateCols = getAggregateColumns( params );
+        List<String> cols = ListUtils.distinctUnion( fixedColumns, getAggregateColumns( params ), getPartitionSelectColumns( params ) );
+        
+        String selectCols = StringUtils.join( cols, "," );
         
         String sql = "from (";
         
         for ( String partition : params.getPartitions().getPartitions() )
         {
-            sql += "select " + getSelectString( fixedColumns ) + getSelectString( aggregateCols ) + getSelectColumns( params );
+            sql += "select " + selectCols + " ";
             
-            sql += " " + getFromWhereSinglePartitionClause( params, partition );
+            sql += getFromWhereSinglePartitionClause( params, partition );
             
             sql += "union all ";
         }
@@ -630,22 +671,6 @@
     }
 
     /**
-     * Creates a comma separated string based on the items in the given lists.
-     * Appends a comma at the end of the string if not empty.
-     */
-    private String getSelectString( List<String> columns )
-    {
-        if ( columns == null || columns.isEmpty() )
-        {
-            return StringUtils.EMPTY;
-        }
-        
-        String fixedCols = StringUtils.join( columns, ", " );
-        
-        return StringUtils.defaultIfEmpty( fixedCols + ", ", fixedCols );
-    }
-
-    /**
      * Returns an item value for the given query, query item and value. Assumes that
      * data dimensions are collapsed for the given query. Returns the short name
      * of the given query item followed by the item value. If the given query item

=== modified file 'dhis-2/dhis-support/dhis-support-commons/src/main/java/org/hisp/dhis/commons/collection/ListUtils.java'
--- dhis-2/dhis-support/dhis-support-commons/src/main/java/org/hisp/dhis/commons/collection/ListUtils.java	2015-10-01 13:57:42 +0000
+++ dhis-2/dhis-support/dhis-support-commons/src/main/java/org/hisp/dhis/commons/collection/ListUtils.java	2015-10-12 15:02:17 +0000
@@ -253,6 +253,26 @@
         
         return union;
     }
+
+    /**
+     * Unions the given array of lists into a single list with distinct items.
+     * 
+     * @param <T> type.
+     * @param lists the array of lists.
+     * @return a union of the given lists.
+     */
+    @SafeVarargs
+    public static final <T> List<T> distinctUnion( final List<T>... lists )
+    {
+        final List<T> union = new UniqueArrayList<>();
+        
+        for ( List<T> list : lists )
+        {
+            union.addAll( list );
+        }
+        
+        return union;
+    }
     
     /**
      * Returns a contiguous list of Integers starting on and including a, ending