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.
master
Klaus Post 5 years ago committed by Harshavardhana
parent 1c5b05c130
commit c1a17c2561
  1. 13
      pkg/s3select/sql/aggregation.go

@ -49,7 +49,7 @@ type aggVal struct {
func newAggVal(fn FuncName) *aggVal { func newAggVal(fn FuncName) *aggVal {
switch fn { switch fn {
case aggFnAvg, aggFnSum: case aggFnAvg, aggFnSum:
return &aggVal{runningSum: FromInt(0)} return &aggVal{runningSum: FromFloat(0)}
case aggFnMin: case aggFnMin:
return &aggVal{runningMin: FromInt(0)} return &aggVal{runningMin: FromInt(0)}
case aggFnMax: case aggFnMax:
@ -126,8 +126,14 @@ func (e *FuncExpr) evalAggregationNode(r Record) error {
// For all non-null values, the count is incremented. // For all non-null values, the count is incremented.
e.aggregate.runningCount++ e.aggregate.runningCount++
case aggFnAvg: case aggFnAvg, aggFnSum:
e.aggregate.runningCount++ 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) err = e.aggregate.runningSum.arithOp(opPlus, argVal)
case aggFnMin: case aggFnMin:
@ -136,9 +142,6 @@ func (e *FuncExpr) evalAggregationNode(r Record) error {
case aggFnMax: case aggFnMax:
err = e.aggregate.runningMax.minmax(argVal, true, isFirstRow) err = e.aggregate.runningMax.minmax(argVal, true, isFirstRow)
case aggFnSum:
err = e.aggregate.runningSum.arithOp(opPlus, argVal)
default: default:
err = errInvalidAggregation err = errInvalidAggregation
} }

Loading…
Cancel
Save