Is there any way to do wrapping operations (addition, multiplication, SUM
) on bigint columns?
By this I mean the standard method of wrapping addition in other programming languages on integer types of a fixed bit-length, e.g. in C++
#include <cstdint>
#include <iostream>
int main() {
int64_t t = 9223372036854775807;
t += 1;
std::cout << t << '\n'; // prints -9223372036854775808
}
In PostgreSQL, I get an overflow:
SELECT 9223372036854775807 + 1;
ERROR: bigint out of range
For aggregation functions in Postgres, it seems the standard behavior is to cast to variable-length numbers, and then calculate the sum, e.g.
SELECT pg_typeof(SUM(id)) FROM (VALUES(9223372036854775807), (9223372036854775807)) AS t(id);
pg_typeof
-----------
numeric
(1 row)
This also works for regular numbers:
SELECT 9223372036854775807::numeric + 1;
?column?
---------------------
9223372036854775808
(1 row)
I could of course do a modulo operation here and get the result I want, but going via variable-length numbers will be a lot slower than pure 64-bit operations.
Is there any way to force standard wrapping 64-bit integer operations?
Is there any way to do wrapping operations (addition, multiplication, SUM
) on bigint columns?
By this I mean the standard method of wrapping addition in other programming languages on integer types of a fixed bit-length, e.g. in C++
#include <cstdint>
#include <iostream>
int main() {
int64_t t = 9223372036854775807;
t += 1;
std::cout << t << '\n'; // prints -9223372036854775808
}
In PostgreSQL, I get an overflow:
SELECT 9223372036854775807 + 1;
ERROR: bigint out of range
For aggregation functions in Postgres, it seems the standard behavior is to cast to variable-length numbers, and then calculate the sum, e.g.
SELECT pg_typeof(SUM(id)) FROM (VALUES(9223372036854775807), (9223372036854775807)) AS t(id);
pg_typeof
-----------
numeric
(1 row)
This also works for regular numbers:
SELECT 9223372036854775807::numeric + 1;
?column?
---------------------
9223372036854775808
(1 row)
I could of course do a modulo operation here and get the result I want, but going via variable-length numbers will be a lot slower than pure 64-bit operations.
Is there any way to force standard wrapping 64-bit integer operations?
Share Improve this question asked Feb 4 at 23:43 MarkMark 815 bronze badges 3 |1 Answer
Reset to default 1I don't think that there is a straightforward way to have aggregate functions that aggregate bigint
s to a bigint
and wrap around numbers.
But PostgreSQL is very extensible: you could write your own aggregate function to do that. If you want good performance and make use of C's wraparound, you should write the state transition function in C.
BIGINT
as an integral value within a range: operations that would result in values outside of that range cause an exception to be raised. When dealing with quantiities, raising an overflow exceptiion is preferable to returning erroneous results. There is no way to force PostgreSQL to wrap integer operations. – JohnH Commented Feb 5 at 5:16BIGINT
is more than just a collection of 64 bits: it is a signed integral quantity.BIGINT
values don't have associated statuses so overflows are signaled by raising an exception. This is analogous to a CPU raising a segmentation fault when an address references a location outside of the permitted range. – JohnH Commented Feb 5 at 16:00