Postgres doesn't support uint64_t , the largest integer type is BIGINT which's range is equal to int64. I need to return an unit64_t var from C function, how can I convert it into numeric then I can return a numeric from my function?
-
1Will Postgres be storing numbers that could exceed a 63 bit int? – Marcus Karpoff Jan 25 '18 at 16:54
-
1In C, you could cast from uint64_t to int64_t and vica versa. I do not figure out your problem. – Tom Kuschel Jan 25 '18 at 16:57
-
1The only issue would be if it used the 64th bit because then the number would become a negative number and OP would have to use something like ```__uint128_t``` from ```stdint.h``` instead of ```uint64_t``` – Marcus Karpoff Jan 25 '18 at 16:59
2 Answers
I can't find an existing function which handles this conversion directly. Worse than that, all of the structures and functions used to build NUMERIC
values appear to be local to numeric.c
, and there's not much of any use in the accompanying header, so I'm not sure how you're expected to build them yourself (looks like we are not the first to notice this).
Seems that this basically limits you to the type's SQL-level API (i.e. the built-in type casts and arithmetic operations). I think the only other SQL type which is both castable to NUMERIC
, and wide enough to hold a uint64
, is TEXT
. In other words, the simplest approach might be to convert your value to a string, and pass it into the NUMERIC
parsing routine, e.g.:
char uint64_string [21];
sprintf(uint64_string, "%" PRIu64, uint64_val);
PG_RETURN_DATUM(DirectFunctionCall3(numeric_in, CStringGetDatum(uint64_string), 0, -1));

- 19,816
- 3
- 51
- 63
C's uint64_t
and int64_t
are castable to each other without loss of information (in twos-complement arithmetic, but I doubt you're using a UNIVAC), so you could cast all uint64_t
quantities to int64_t
before writing them to the database and back to uint64_t
on read.
There are some potential problems, though. First off, do not do this if you ever need to store actual negative numbers in the relevant database columns, because you won't be able to tell whether they were negative numbers or numbers above 263−1 when you read them back. Also, all SQL operations will treat all numbers greater than 263−1 as negative. This may or may not be a problem, depending on what you are using these large numbers for and how complicated the queries involving them tend to be.
EDIT: I just realized that by "numeric" you probably meant PostgreSQL's arbitrary-precision NUMERIC column type. Unfortunately I am not having any luck whatsoever finding documentation for how to work with this type below the level of textual SQL. The only thing I can suggest is for you to read the header files for writing server-side extensions in C and/or ask for help on the pg mailing lists.

- 135,547
- 38
- 252
- 361