Question

I am using the libpq-fe library in C to contact to a postgres database.
I am calling a stored procedure from my code using libpqfe which returns a timestamp.
I want to store this timestamp to a char array. But to do so I first have to know the size of timestamp so that I can declare the array. To get the size I am using int PQfsize(PGresult *res, int field_index);. You can found more about it here.

It returns the value 8. But actually the size of the timestamp(without zone) is 19.

Why PQfsize is returning wrong value?

I know that size of the timestamp is constant and I can directly declare an array and then retrieve the value using PQgetvalue, but how to declare arrays for the fields which don't have fixed size.

How to retrieve a field from PGresult to store it into any variable?

Was it helpful?

Solution

PQfsize isn't returning the wrong value.

If you run the query below you will also get the answer 8, because internally in your version of Postgres timestamp is stored as an 8 byte (64 bit) integer.

select typlen from pg_type where oid = 'timestamp'::regtype::oid;

As per the documentation you linked PQfsize returns the space allocated for this field in a database tuple, in other words the size of the server's binary representation of the data type.

PQgetlength Returns the length of a field (attribute) in bytes. Tuple and field indices start at 0.

This is the actual data length for the particular data value, that is the size of the object pointed to by PQgetvalue. Note that for ASCII-represented values, this size has little to do with the binary size reported by PQfsize.

In order to declare arrays that don't have fixed size, you the size of the array before creating it using PQgetlength (which should return 19) and by specifying to get the data as text by having PQexecParams having resultFormat as 0. If you are just using PQexec then data is returned in text form by default.

An example of using libpq is avaliable here.

To modify this example so that instead just printing the value, it makes a character array from the length of the data and copies the data to the array you could replace the for loop with something like

      for (i = 0; i < PQntuples(res); i++)                
      {
           int length = PQgetlength(res, i, 0);
           char result[length];
           printf("%s\n", PQgetvalue(res, i, 0));           
           strncpy (result,PQgetvalue(res, i, 0),length);
      }

You would also need to add #include <string.h> to the example.

OTHER TIPS

From the fine manual:

PQfsize returns the space allocated for this column in a database row, in other words the size of the server's internal representation of the data type.

So PQfsize returns the number of bytes in the server's internal binary representation of a timestamp.

And a timestamp has a storage size of eight bytes. Basically, you're getting the server's internal timestamp bytes, not the human readable string that you're looking for.

You might want to use PQExecParams with resultFormat set to zero to get text values in your results rather than binary ones. If you do that, you should get the string representation of a timestamp that you're expecting but you'll have to do a wee bit of string parsing to convert the contents of the PGresult to native types.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top