func (af *avgFunction) calculateResult(ctx *ast.AggEvaluateContext) (d types.Datum) { switch ctx.Value.Kind() { case types.KindFloat64: t := ctx.Value.GetFloat64() / float64(ctx.Count) d.SetValue(t) case types.KindMysqlDecimal: x := ctx.Value.GetMysqlDecimal() y := mysql.NewDecFromInt(ctx.Count) to := new(mysql.MyDecimal) mysql.DecimalDiv(x, y, to, mysql.DivFracIncr) to.Round(to, ctx.Value.Frac()+mysql.DivFracIncr) d.SetMysqlDecimal(to) } return }
func (e *Evaluator) evalAggAvg(v *ast.AggregateFuncExpr) { ctx := v.GetContext() switch ctx.Value.Kind() { case types.KindFloat64: t := ctx.Value.GetFloat64() / float64(ctx.Count) v.SetValue(t) case types.KindMysqlDecimal: x := ctx.Value.GetMysqlDecimal() var y, to mysql.MyDecimal y.FromUint(uint64(ctx.Count)) mysql.DecimalDiv(x, &y, &to, mysql.DivFracIncr) to.Round(&to, ctx.Value.Frac()+mysql.DivFracIncr) v.SetMysqlDecimal(&to) } ctx.Value = *v.GetDatum() }
// GetGroupResult implements AggregationFunction interface. func (af *avgFunction) GetGroupResult(groupKey []byte) (d types.Datum) { ctx := af.getContext(groupKey) switch ctx.Value.Kind() { case types.KindFloat64: t := ctx.Value.GetFloat64() / float64(ctx.Count) d.SetValue(t) case types.KindMysqlDecimal: x := ctx.Value.GetMysqlDecimal() y := mysql.NewDecFromInt(ctx.Count) to := new(mysql.MyDecimal) mysql.DecimalDiv(x, y, to, mysql.DivFracIncr) to.Round(to, ctx.Value.Frac()+mysql.DivFracIncr) d.SetMysqlDecimal(to) } return }
// ComputeDiv computes the result of a/b. func ComputeDiv(a, b Datum) (d Datum, err error) { // MySQL support integer division Div and division operator / // we use opcode.Div for division operator and will use another for integer division later. // for division operator, we will use float64 for calculation. switch a.Kind() { case KindFloat64: y, err1 := b.ToFloat64() if err1 != nil { return d, errors.Trace(err1) } if y == 0 { return d, nil } x := a.GetFloat64() d.SetFloat64(x / y) return d, nil default: // the scale of the result is the scale of the first operand plus // the value of the div_precision_increment system variable (which is 4 by default) // we will use 4 here xa, err1 := a.ToDecimal() if err != nil { return d, errors.Trace(err1) } xb, err1 := b.ToDecimal() if err1 != nil { return d, errors.Trace(err1) } // division by zero return null to := new(mysql.MyDecimal) err = mysql.DecimalDiv(xa, xb, to, mysql.DivFracIncr) if err != mysql.ErrDivByZero { d.SetMysqlDecimal(to) } else { err = nil } return d, err } }
// ComputeIntDiv computes the result of a / b, both a and b are integer. func ComputeIntDiv(a, b Datum) (d Datum, err error) { switch a.Kind() { case KindInt64: x := a.GetInt64() switch b.Kind() { case KindInt64: y := b.GetInt64() if y == 0 { return d, nil } r, err1 := DivInt64(x, y) d.SetInt64(r) return d, errors.Trace(err1) case KindUint64: y := b.GetUint64() if y == 0 { return d, nil } r, err1 := DivIntWithUint(x, y) d.SetUint64(r) return d, errors.Trace(err1) } case KindUint64: x := a.GetUint64() switch b.Kind() { case KindInt64: y := b.GetInt64() if y == 0 { return d, nil } r, err1 := DivUintWithInt(x, y) d.SetUint64(r) return d, errors.Trace(err1) case KindUint64: y := b.GetUint64() if y == 0 { return d, nil } d.SetUint64(x / y) return d, nil } } // If either is not integer, use decimal to calculate x, err := a.ToDecimal() if err != nil { return d, errors.Trace(err) } y, err := b.ToDecimal() if err != nil { return d, errors.Trace(err) } to := new(mysql.MyDecimal) err = mysql.DecimalDiv(x, y, to, mysql.DivFracIncr) if err == mysql.ErrDivByZero { return d, nil } iVal, err1 := to.ToInt() if err == nil { err = err1 } d.SetInt64(iVal) return d, nil }