// Prepare the arguments for a binary operation. The returned arguments will // have the same type. The typ parameter specifies the allowed types for the // operation. For example, bit-operations should specify intOp or uintOp to // indicate that they do not operate on floating point arguments. Float // operations may still reduce to intOp or uintOp if the operands support it. func prepareBinaryArgs(typ opType, left, right sqlwire.Datum) (opType, sqlwire.Datum, sqlwire.Datum, error) { var err error switch typ { case intOp, uintOp: if left.UintVal != nil || right.UintVal != nil { left, err = left.ToUint() if err != nil { return uintOp, null, null, err } right, err = right.ToUint() if err != nil { return uintOp, null, null, err } return uintOp, left, right, nil } left, err = left.ToInt() if err != nil { return intOp, null, null, err } right, err = right.ToInt() if err != nil { return intOp, null, null, err } return intOp, left, right, nil case floatOp: if (left.UintVal != nil && (right.IntVal != nil || right.UintVal != nil)) || (right.UintVal != nil && (left.IntVal != nil || left.UintVal != nil)) { left, err = left.ToUint() if err != nil { return uintOp, null, null, err } right, err = right.ToUint() if err != nil { return uintOp, null, null, err } return uintOp, left, right, nil } if left.IntVal != nil && right.IntVal != nil { return intOp, left, right, nil } } left, err = left.ToFloat() if err != nil { return floatOp, null, null, err } right, err = right.ToFloat() if err != nil { return floatOp, null, null, err } return floatOp, left, right, nil }