From 1ceddf40c0e5f049213fff00caba683d630c5033 Mon Sep 17 00:00:00 2001
From: Donnie Pinkston <donnie@cms.caltech.edu>
Date: Wed, 30 Jan 2019 14:44:36 -0800
Subject: [PATCH] Aggregate function bugfixes

A number of bugfixes caused by some of the changes in the arithmetic
type-coercion rules, and the parser-framework changes.

COUNT(DISTINCT a) wasn't being handled correctly due to an issue in
the NanoSQLTranslator flow-control.

The SumAvg/StdDevVar aggregate implementations are now updated to
produce double-precision results when calculating their values.  The
type-converter had been changed to do integer division when the LHS
and RHS are both integers, and this was breaking tests of these
aggregate functions.
---
 .../nanodb/functions/StdDevVarAggregate.java  | 30 +++++++++----------
 .../nanodb/functions/SumAvgAggregate.java     |  3 +-
 .../nanodb/sqlparse/NanoSQLTranslator.java    |  6 ++--
 3 files changed, 20 insertions(+), 19 deletions(-)

diff --git a/src/main/java/edu/caltech/nanodb/functions/StdDevVarAggregate.java b/src/main/java/edu/caltech/nanodb/functions/StdDevVarAggregate.java
index 1f8142c..1b9efe5 100755
--- a/src/main/java/edu/caltech/nanodb/functions/StdDevVarAggregate.java
+++ b/src/main/java/edu/caltech/nanodb/functions/StdDevVarAggregate.java
@@ -49,7 +49,7 @@ public class StdDevVarAggregate extends AggregateFunction {
             // Store the new value
             values.add(value);
         }
-                
+
         if (sum == null) {
             // This is the first value.  Store it.
             sum = value;
@@ -61,17 +61,18 @@ public class StdDevVarAggregate extends AggregateFunction {
         }
     }
 
-    
+
     @Override
     public Object getResult() {
         if (sum == null || values == null)
             return null;
         else {
-            int count = values.size();
+            // TODO:  Need to generate NUMERIC result.  Using double right now.
+            double count = (double) values.size();
             // Compute average from the sum and count.
             Object avg = ArithmeticOperator.evalObjects(
-                ArithmeticOperator.Type.DIVIDE, sum, Integer.valueOf(count));
-            
+                ArithmeticOperator.Type.DIVIDE, sum, count);
+
             // Compute the sum of the square of the residuals.
             Object sumSquaresResids = squareDifference(values.get(0), avg);
             for (int i = 1; i < count; i++) {
@@ -79,12 +80,11 @@ public class StdDevVarAggregate extends AggregateFunction {
                     ArithmeticOperator.Type.ADD, sumSquaresResids,
                     squareDifference(values.get(i), avg));
             }
-            
+
             // Compute the variance.
             Object var = ArithmeticOperator.evalObjects(
-                ArithmeticOperator.Type.DIVIDE, sumSquaresResids, 
-                Integer.valueOf(count));
-            
+                ArithmeticOperator.Type.DIVIDE, sumSquaresResids, count);
+
             // Compute standard deviation if necessary.
             if (computeStdDev) {
                 return ArithmeticOperator.evalObjects(
@@ -95,8 +95,8 @@ public class StdDevVarAggregate extends AggregateFunction {
             }
         }
     }
-    
-    
+
+
     @Override
     public ColumnType getReturnType(List<Expression> args, Schema schema) {
         if (args.size() != 1) {
@@ -109,11 +109,11 @@ public class StdDevVarAggregate extends AggregateFunction {
         // same type as the values of the column.
         return args.get(0).getColumnInfo(schema).getType();
     }
-    
- 
-    /** 
+
+
+    /**
      * Helper function that computes the square of the difference between
-     * two values. 
+     * two values.
      */
     private Object squareDifference(Object value, Object avg) {
         return ArithmeticOperator.evalObjects(ArithmeticOperator.Type.POWER,
diff --git a/src/main/java/edu/caltech/nanodb/functions/SumAvgAggregate.java b/src/main/java/edu/caltech/nanodb/functions/SumAvgAggregate.java
index 5d09a91..d7bfe18 100644
--- a/src/main/java/edu/caltech/nanodb/functions/SumAvgAggregate.java
+++ b/src/main/java/edu/caltech/nanodb/functions/SumAvgAggregate.java
@@ -91,9 +91,10 @@ public class SumAvgAggregate extends AggregateFunction {
             return null;
         }
         else if (computeAverage) {
+            // TODO:  Need to generate NUMERIC result.  Using double right now.
             // Compute average from the sum and count.
             return ArithmeticOperator.evalObjects(
-                ArithmeticOperator.Type.DIVIDE, sum, Integer.valueOf(count));
+                ArithmeticOperator.Type.DIVIDE, sum, (double) count);
         }
         else {
             // Just return the sum.
diff --git a/src/main/java/edu/caltech/nanodb/sqlparse/NanoSQLTranslator.java b/src/main/java/edu/caltech/nanodb/sqlparse/NanoSQLTranslator.java
index d213621..3a7f236 100644
--- a/src/main/java/edu/caltech/nanodb/sqlparse/NanoSQLTranslator.java
+++ b/src/main/java/edu/caltech/nanodb/sqlparse/NanoSQLTranslator.java
@@ -882,11 +882,11 @@ public class NanoSQLTranslator extends NanoSQLBaseVisitor<Object> {
                 ColumnName colName = ((ColumnValue) e).getColumnName();
                 if (colName.isColumnWildcard())
                     functionName += "#STAR";
+                else if (distinct)
+                    functionName += "#DISTINCT";
             }
         }
-        else if (distinct) {
-            functionName += "#DISTINCT";
-        }
+        // TODO:  Report error if someone uses DISTINCT with multiple args.
 
         FunctionCall fnCall = new FunctionCall(functionName, distinct, args);
         if (functionDirectory != null)
-- 
GitLab