For another point of reference, here's microsoft's docs for SQL server on resulting precision and scale for different operators including its overflow rules: https://docs.microsoft.com/en-us/sql/t-sql/data-types/precision-scale-and-length-transact-sql?view=sql-server-ver15
-Keith On Thu, Sep 30, 2021 at 9:42 AM David Li <lidav...@apache.org> wrote: > Hello all, > > While looking at decimal arithmetic kernels in ARROW-13130, the question > of what to do about overflow came up. > > Currently, our rules are based on Redshift [1], except we raise an error > if we exceed the maximum precision (Redshift's docs implies it saturates > instead). Hence, we can always add/subtract/etc. without checking for > overflow, but we can't do things like add two decimal256(76, 0) since > there's no more precision available. > > If we were to support this last case, what would people expect the > unchecked arithmetic kernels to do on overflow? For integers, we wrap > around, but this doesn't really make sense for decimals; we could also > return nulls, or just always raise an error (this seems the most reasonable > to me). Any thoughts? > > For reference, for an unchecked add, currently we have: > "1" (decimal256(75, 0)) + "1" (decimal256(75, 0)) = "2" (decimal256(76, 0)) > "1" (decimal128(38, 0)) + "1" (decimal128(38, 0)) = error (not enough > precision) > "1" (decimal256(76, 0)) + "1" (decimal256(76, 0)) = error (not enough > precision) > "99...9 (76 digits)" (decimal256(76, 0)) + "1" (decimal256(76, 0)) = error > (not enough precision) > > Arguably these last three cases should be: > "1" (decimal128(38, 0)) + "1" (decimal128(38, 0)) = "2" (decimal256(39, > 0)) (promote to decimal256) > "1" (decimal256(76, 0)) + "1" (decimal256(76, 0)) = "2" (decimal256(76, > 0)) (saturate at max precision) > "99...9 (76 digits)" (decimal256(76, 0)) + "1" (decimal256(76, 0)) = error > (overflow) > > On a related note, you could also argue that we shouldn't increase the > precision like this, though DBs other than Redshift also do this. Playing > with DuckDB a bit, though, it doesn't match Redshift: addition/subtraction > increase precision by 1 like Redshift does, but division results in a > float, and multiplication only adds the input precisions together, while > Redshift adds 1 to the sum of the precisions. (That is, decimal128(3, 0) * > decimal128(3, 0) is decimal128(7, 0) in Redshift/Arrow but decimal128(6, 0) > in DuckDB.) > > [1]: > https://docs.aws.amazon.com/redshift/latest/dg/r_numeric_computations201.html > > -David