Hi,
The money type has overflow handling in its input function:
Datum
cash_in(PG_FUNCTION_ARGS)
...
Cash newvalue = (value * 10) - (*s - '0');
if (newvalue / 10 != value)
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("value \"%s\" is out of range for type %s",
str, "money")));
but not in a lot of other relevant places:
Datum
cash_pl(PG_FUNCTION_ARGS)
{
Cash c1 = PG_GETARG_CASH(0);
Cash c2 = PG_GETARG_CASH(1);
Cash result;
result = c1 + c2;
PG_RETURN_CASH(result);
}
Same with cash_mi, int8_mul_cash, cash_div_int8, etc.
cash_out doesn't have a plain overflow, but:
if (value < 0)
{
/* make the amount positive for digit-reconstruction loop */
value = -value;
doesn't reliably work if value is PG_INT64_MIN.
This leads to fun like:
postgres[2002][1]=# SELECT '92233720368547758.07'::money+'0.1';
┌─────────────────────────────┐
│ ?column? │
├─────────────────────────────┤
│ -$92,233,720,368,547,757.99 │
└─────────────────────────────┘
Greetings,
Andres Freund