Thread: manipulating NUMERIC values in C extension
Hi I'd like to be able to perform some manipulation on NUMERIC values in a C function; however the exposed functionality in numeric.h is pretty restrictive. I can see numeric_normalize will return a pointer to a string representation, which is workable, and if there were an equivalent string-to-numeric function that would be enough (although not the most efficient) but I can't see a way to get a string back in to a numeric value to return. numeric_in looks like it might do what I want but to do that I would have to build a FunctionCallInfo struct to do that, and I'm not 100% clear how to do that either :( I _could_ return the result as a varchar and cast it back to numeric in the SQL, but that's not very clean. Accessing the numeric structure directly would work too but I'm assuming that's not recommended since it's not exposed in numeric.h. Any thoughts would be appreciated, Geoff
On Fri, Jun 8, 2018 at 7:27 AM Geoff Winkless <pgsqladmin@geoff.dj> wrote:
Hi
I'd like to be able to perform some manipulation on NUMERIC values in
a C function; however the exposed functionality in numeric.h is pretty
restrictive.
I can see numeric_normalize will return a pointer to a string
representation, which is workable, and if there were an equivalent
string-to-numeric function that would be enough (although not the most
efficient) but I can't see a way to get a string back in to a numeric
value to return.
numeric_in looks like it might do what I want but to do that I would
have to build a FunctionCallInfo struct to do that, and I'm not 100%
clear how to do that either :(
I _could_ return the result as a varchar and cast it back to numeric
in the SQL, but that's not very clean.
Accessing the numeric structure directly would work too but I'm
assuming that's not recommended since it's not exposed in numeric.h.
Any thoughts would be appreciated,
Have you considered the standard C library functions: "atoi()", "atof()", "atol()", and "atoll()" ?
Geoff
Rap music is performed by those that can not sing so others can not think.
Maranatha! <><
John McKown
John McKown
On Fri, 8 Jun 2018 at 13:27, Geoff Winkless <pgsqladmin@geoff.dj> wrote: > numeric_in looks like it might do what I want but to do that I would > have to build a FunctionCallInfo struct to do that, and I'm not 100% > clear how to do that either :( Answering my own question, looks like res = DatumGetNumeric(DirectFunctionCall3(numeric_in, CStringGetDatum(buf), 0, -1)); should do it, judging from https://api.pgxn.org/src/orafce/orafce-3.6.1/convert.c Geoff
On Fri, 8 Jun 2018 at 13:47, Geoff Winkless <pgsqladmin@geoff.dj> wrote: > Answering my own question, looks like And just in case anyone googling the question comes across this, this example code works. #include "postgres.h" #include <string.h> #include "fmgr.h" #include "utils/geo_decls.h" #include "funcapi.h" #include "utils/array.h" #include "utils/builtins.h" #include "utils/numeric.h" #include "catalog/pg_type.h" PG_MODULE_MAGIC; PG_FUNCTION_INFO_V1(pgnumeric_x10); Datum pgnumeric_x10(PG_FUNCTION_ARGS) { Numeric v; char *r; char mybuff[1000]; double f; v=PG_GETARG_NUMERIC(0); r=numeric_normalize(v); f=atof(r)*10; sprintf(mybuff, "%f", f); v = DatumGetNumeric(DirectFunctionCall3(numeric_in, CStringGetDatum(mybuff), 0, -1)); pfree(r); PG_RETURN_NUMERIC(v); } Example of it running: =# CREATE OR REPLACE FUNCTION pgnumeric_x10(NUMERIC) RETURNS NUMERIC AS 'testpgnumchange.so', 'pgnumeric_x10' LANGUAGE C STRICT IMMUTABLE; CREATE FUNCTION Time: 0.811 ms =# select pgnumeric_x10(132387.4823487::NUMERIC); pgnumeric_x10 ---------------- 1323874.823487 (1 row) Time: 0.593 ms =# For obvious reasons I wouldn't suggest using atof on a numeric, we have our own functions for manipulating _Decimal128 which is what I'll actually be using in the end version, but this is easier to compile as an example :) Geoff
On Fri, 8 Jun 2018 at 13:44, John McKown <john.archie.mckown@gmail.com> wrote: > Have you considered the standard C library functions: "atoi()", "atof()", "atol()", and "atoll()" ? Hi John My issue wasn't so much how to get a number out of the string, rather how to get that value back into a NUMERIC object to return back to the server. Thanks for taking the time to reply though, it's appreciated. Geoff