mirror of
https://github.com/pikami/cosmium.git
synced 2026-10-10 03:56:11 +01:00
Return the numeric extreme when a group contains any number, fall back to alphabetic string comparison when it does not, and keep nil when neither type is present. Co-authored-by: Cursor Agent <[email protected]>
137 lines
2.9 KiB
Go
137 lines
2.9 KiB
Go
package memoryexecutor
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/pikami/cosmium/parsers"
|
|
)
|
|
|
|
func (r rowContext) aggregate_Avg(arguments []interface{}) interface{} {
|
|
selectExpression := arguments[0].(parsers.SelectItem)
|
|
sum := 0.0
|
|
count := 0
|
|
|
|
for _, item := range r.grouppedRows {
|
|
value := item.resolveSelectItem(selectExpression)
|
|
if numericValue, ok := value.(float64); ok {
|
|
sum += numericValue
|
|
count++
|
|
} else if numericValue, ok := value.(int); ok {
|
|
sum += float64(numericValue)
|
|
count++
|
|
}
|
|
}
|
|
|
|
if count > 0 {
|
|
return sum / float64(count)
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func (r rowContext) aggregate_Count(arguments []interface{}) interface{} {
|
|
selectExpression := arguments[0].(parsers.SelectItem)
|
|
count := 0
|
|
|
|
for _, item := range r.grouppedRows {
|
|
value := item.resolveSelectItem(selectExpression)
|
|
if value != nil {
|
|
count++
|
|
}
|
|
}
|
|
|
|
return count
|
|
}
|
|
|
|
func (r rowContext) aggregate_Max(arguments []interface{}) interface{} {
|
|
return r.aggregateMinMax(arguments, true)
|
|
}
|
|
|
|
func (r rowContext) aggregate_Min(arguments []interface{}) interface{} {
|
|
return r.aggregateMinMax(arguments, false)
|
|
}
|
|
|
|
func (r rowContext) aggregateMinMax(arguments []interface{}, isMax bool) interface{} {
|
|
selectExpression := arguments[0].(parsers.SelectItem)
|
|
var extremeNumber float64
|
|
hasNumber := false
|
|
var extremeString string
|
|
hasString := false
|
|
|
|
for _, item := range r.grouppedRows {
|
|
value := item.resolveSelectItem(selectExpression)
|
|
|
|
if numericValue, ok := aggregateNumber(value); ok {
|
|
if !hasNumber || numberIsExtreme(numericValue, extremeNumber, isMax) {
|
|
extremeNumber = numericValue
|
|
hasNumber = true
|
|
}
|
|
continue
|
|
}
|
|
|
|
if strValue, ok := value.(string); ok {
|
|
if !hasString || stringIsExtreme(strValue, extremeString, isMax) {
|
|
extremeString = strValue
|
|
hasString = true
|
|
}
|
|
}
|
|
}
|
|
|
|
if hasNumber {
|
|
return extremeNumber
|
|
}
|
|
if hasString {
|
|
return extremeString
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func aggregateNumber(value interface{}) (float64, bool) {
|
|
switch numericValue := value.(type) {
|
|
case float64:
|
|
return numericValue, true
|
|
case int:
|
|
return float64(numericValue), true
|
|
default:
|
|
return 0, false
|
|
}
|
|
}
|
|
|
|
func numberIsExtreme(candidate, current float64, isMax bool) bool {
|
|
if isMax {
|
|
return candidate > current
|
|
}
|
|
return candidate < current
|
|
}
|
|
|
|
func stringIsExtreme(candidate, current string, isMax bool) bool {
|
|
comparison := strings.Compare(candidate, current)
|
|
if isMax {
|
|
return comparison > 0
|
|
}
|
|
return comparison < 0
|
|
}
|
|
|
|
func (r rowContext) aggregate_Sum(arguments []interface{}) interface{} {
|
|
selectExpression := arguments[0].(parsers.SelectItem)
|
|
sum := 0.0
|
|
count := 0
|
|
|
|
for _, item := range r.grouppedRows {
|
|
value := item.resolveSelectItem(selectExpression)
|
|
if numericValue, ok := value.(float64); ok {
|
|
sum += numericValue
|
|
count++
|
|
} else if numericValue, ok := value.(int); ok {
|
|
sum += float64(numericValue)
|
|
count++
|
|
}
|
|
}
|
|
|
|
if count > 0 {
|
|
return sum
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|