Is it possible to get the binary (or hexadecimal) representation of a value stored as double precision in a PostgreSQL database?

StackOverflow https://stackoverflow.com/questions/23263986

Question

Is it possible to get the binary (or hexadecimal) representation of a value stored as double precision in a PostgreSQL database?

I already tried to use a cast to bit(64) (double precision is stored with a size of 8 bytes) but I get the following error:

SELECT (1.031::double precision)::bit(64)
>> ERROR:  cannot cast type double precision to bit

SELECT (1024::double precision)::bit(64)
>> ERROR:  cannot cast type double precision to bit

For integers it works :

select (1024::integer)::bit(32)
>> 00000000000000000000010000000000

select (-1024::integer)::bit(32)
>> 11111111111111111111110000000000

select (1024::bigint)::bit(64)
>> 0000000000000000000000000000000000000000000000000000010000000000

select ((17179869184+8589934592)::bigint)::bit(64)
>> 0000000000000000000000000000011000000000000000000000000000000000

The official documentation doesn't seem to provide a way of doing it for double precision values over SQL queries.

However

SELECT -0::double precision AS minuszero, 0::double precision AS pluszero

gives in pgAdmin III the following result:

"minuszero";"pluszero"
-0;0

which seems to indicate that pgAdmin is aware of the difference between the 2 values returned by Postgres (which differs only by the sign bit of the binary representation (IEEE Standard 754) of 0 and -0).

Somehow I assume that pgAdmin gets internally the binary representation of the double precision value from the reply of the database, and shows it accordingly in a decimal representation on the screen.

Was it helpful?

Solution

Somehow I assume that pgAdmin gets internally the binary representation of the double precision value from the reply of the database, and shows it accordingly in a decimal representation on the screen.

No, actually it doesn't grok binary at all. This -0 and 0 are text representations that come verbatim from the server. If pgAdmin understood binary, it could be able to display the result of this SQL sequence:

DECLARE c BINARY CURSOR WITH HOLD FOR
  SELECT -0::double precision AS minuszero, 0::double precision AS pluszero;

FETCH 1 FROM c;

and in fact, it displays an empty string as output in each column.

The psql command line tool is also unable to deal with binary because it doesn't support null bytes in raw query results.

This is not a limitation of the C libpq library however, even with its simplest function PQexec(). Raw bytes could be obtained and displayed in hex with this code:

  PGresult* res = PQexec(conn, "DECLARE c BINARY CURSOR WITH HOLD FOR "
    "SELECT -0::double precision AS minuszero, 0::double precision AS pluszero;"
    "FETCH 1 FROM c");
  if (res && PQresultStatus(res)==PGRES_TUPLES_OK) {
    for (int i=0; i<PQnfields(res); i++) {
      printf("column %s: ", PQfname(res, i));
      for (int j=0; j<PQfsize(res,0); j++)
        printf("%02x", ((unsigned char*)PQgetvalue(res, 0, i))[j]);
      printf("\n");
    }
  }

result:

column minuszero: 8000000000000000
column pluszero: 0000000000000000

You can finally see this sign bit as the first (and only) bit set in the first column. It's in network byte order, MSB first, which is reversed compared to the disk representation for little endian architecture, as used in the x86 family.

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