LimitDecimalWidth limits d's precision (total number of digits) and scale (number of digits after the decimal point). Note that this any limiting will modify the decimal in-place.
(d *apd.Decimal, precision, scale int)
| 51 | // (number of digits after the decimal point). Note that this any limiting will |
| 52 | // modify the decimal in-place. |
| 53 | func LimitDecimalWidth(d *apd.Decimal, precision, scale int) error { |
| 54 | if d.Form != apd.Finite || precision <= 0 { |
| 55 | return nil |
| 56 | } |
| 57 | // Use +1 here because it is inverted later. |
| 58 | if scale < math.MinInt32+1 || scale > math.MaxInt32 { |
| 59 | return errScaleOutOfRange |
| 60 | } |
| 61 | if scale > precision { |
| 62 | return pgerror.Newf(pgcode.InvalidParameterValue, "scale (%d) must be between 0 and precision (%d)", scale, precision) |
| 63 | } |
| 64 | |
| 65 | // http://www.postgresql.org/docs/9.5/static/datatype-numeric.html |
| 66 | // "If the scale of a value to be stored is greater than |
| 67 | // the declared scale of the column, the system will round the |
| 68 | // value to the specified number of fractional digits. Then, |
| 69 | // if the number of digits to the left of the decimal point |
| 70 | // exceeds the declared precision minus the declared scale, an |
| 71 | // error is raised." |
| 72 | |
| 73 | c := DecimalCtx.WithPrecision(uint32(precision)) |
| 74 | c.Traps = apd.InvalidOperation |
| 75 | |
| 76 | if _, err := c.Quantize(d, d, -int32(scale)); err != nil { |
| 77 | var lt string |
| 78 | switch v := precision - scale; v { |
| 79 | case 0: |
| 80 | lt = "1" |
| 81 | default: |
| 82 | lt = fmt.Sprintf("10^%d", v) |
| 83 | } |
| 84 | return pgerror.Newf(pgcode.NumericValueOutOfRange, "value with precision %d, scale %d must round to an absolute value less than %s", precision, scale, lt) |
| 85 | } |
| 86 | return nil |
| 87 | } |
no test coverage detected
searching dependent graphs…