简体   繁体   中英

Postgresql C How to convert uint64_t into numeric?

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?

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 2 63 −1 when you read them back. Also, all SQL operations will treat all numbers greater than 2 63 −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.

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 (ie 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, eg:

char uint64_string [21];
sprintf(uint64_string, "%" PRIu64, uint64_val);
PG_RETURN_DATUM(DirectFunctionCall3(numeric_in, CStringGetDatum(uint64_string), 0, -1));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM