From c1a17c2561758523840bf4cc38ba5f6192d97f98 Mon Sep 17 00:00:00 2001 From: Klaus Post Date: Fri, 27 Sep 2019 16:12:03 -0700 Subject: [PATCH] S3 Select: Aggregate AVG/SUM as float (#8326) Force sum/average to be calculated as a float. As noted in #8221 > run SELECT AVG(CAST (Score as int)) FROM S3Object on ``` Name,Score alice,80 bob,81 ``` > AWS S3 gives 80.5 and MinIO gives 80. This also makes overflows much more unlikely. --- pkg/s3select/sql/aggregation.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/pkg/s3select/sql/aggregation.go b/pkg/s3select/sql/aggregation.go index 930672096..11b36c340 100644 --- a/pkg/s3select/sql/aggregation.go +++ b/pkg/s3select/sql/aggregation.go @@ -49,7 +49,7 @@ type aggVal struct { func newAggVal(fn FuncName) *aggVal { switch fn { case aggFnAvg, aggFnSum: - return &aggVal{runningSum: FromInt(0)} + return &aggVal{runningSum: FromFloat(0)} case aggFnMin: return &aggVal{runningMin: FromInt(0)} case aggFnMax: @@ -126,8 +126,14 @@ func (e *FuncExpr) evalAggregationNode(r Record) error { // For all non-null values, the count is incremented. e.aggregate.runningCount++ - case aggFnAvg: + case aggFnAvg, aggFnSum: e.aggregate.runningCount++ + // Convert to float. + f, ok := argVal.ToFloat() + if !ok { + return fmt.Errorf("Could not convert value %v (%s) to a number", argVal.value, argVal.GetTypeString()) + } + argVal.setFloat(f) err = e.aggregate.runningSum.arithOp(opPlus, argVal) case aggFnMin: @@ -136,9 +142,6 @@ func (e *FuncExpr) evalAggregationNode(r Record) error { case aggFnMax: err = e.aggregate.runningMax.minmax(argVal, true, isFirstRow) - case aggFnSum: - err = e.aggregate.runningSum.arithOp(opPlus, argVal) - default: err = errInvalidAggregation }