I try to convert data queried via libpq in binary format into Arrow format in C. For that, I queried the data type Oids for the corresponding columns via PQftype() and match them with Arrow datatypes. But I am not sure how to handle numerics.
The query SELECT oid, typname FROM pg_type;
returns 1700 for numeric, but how do I get precision and scale?
I am not able to find helpful information in the documentation. Am I searching at the wrong spot? https://www.postgresql.org/docs/13/datatype-numeric.html#DATATYPE-NUMERIC-DECIMAL
What can I expect to get in my PGresult from a binary numeric?
Thanks in advance :)
EDIT
So with the help of Laurenz I managed to put a function together, which converts a Numeric in binary form from libpq into a basic String representation. Of course binary results only make sense, if you do not intend to convert the Numerics to Strings, but it helps to understand the format of Numerics.
The binary form basically is a list of 2 byte integers with different meanings and the digit integers are just concatenated in their String form. Here is 49273.64 with precision 20 and scale 2 in binary and in fields:
ndigits | 00000000 | 00000011 | weight | 00000000 | 00000001 | sign | 00000000 | 00000000 | dscale | 00000000 | 00000010 | digits | 00000000 | 00000100 | 00100100 | 00111001 | 00011001 | 00000000
ndigits: 3, weight: 1, sign: 0, dscale: 2, digits: 4 | 9273 | 6400
char *getStrFromNumeric(u_int16_t *numvar){
u_int16_t ndigits = ntohs(numvar[0]); // how many u_int16_t at numvar[4]
int16_t dscale = ntohs(numvar[3]); // how many char digits after decimal point
int16_t weight = ntohs(numvar[1])+1; // weight+1 is how many u_int16_t from numvar[4] are before decimal point. here weight already gets +1 at initialization.
char *result = (char *)malloc(sizeof(char)*(weight+dscale)+1+1+2); // +1+1 -> '\0' and '.'
char *copyStr = (char *) malloc(sizeof (char)*5);
int strindex = 0;
int numvarindex = 0;
while(weight>0){
sprintf(copyStr, "%d", ntohs(numvar[numvarindex+4]));
sprintf(&(result[strindex]), "%s", copyStr);
strindex += strlen(copyStr);
numvarindex++;
weight--;
}
sprintf(&(result[strindex]), ".");
strindex++;
while(dscale>0){
sprintf(copyStr, "%d", ntohs(numvar[numvarindex+4]));
dscale -= strlen(copyStr);
sprintf(&(result[strindex]), "%s", copyStr);
strindex += strlen(copyStr);
numvarindex++;
}
sprintf(&(result[strindex]), "\0");
return result;
}