Hi,

I'm having trouble inserting a float into pg using binary format.

Hope someone on the list can help me point out what I'm doing wrong....

float loadavg;

loadavg = htonl(1.23);

paramValues[0] = (char *) &loadavg
paramLengths[0] = sizeof(loadavg);
paramFormats[0] = 1;

res = PQexecParams(conn,
"INSERT INTO cpu (loadavg) VALUES ($1::real)",
1,
NULL,
paramValues,
paramLengths,
paramFormats,
1);

From psql, select returns the value as 1.20765e-38 instead of
1.23.....:(

Thanks

Way





- - - - - Appended by Scientific Atlanta, a Cisco company - - - - -
This e-mail and any attachments may contain information which is confidential,
proprietary, privileged or otherwise protected by law. The information is solely
intended for the named addressee (or a person responsible for delivering it to
the addressee). If you are not the intended recipient of this message, you are
not authorized to read, print, retain, copy or disseminate this message or any
part of it. If you have received this e-mail in error, please notify the sender
immediately by return e-mail and delete it from your computer.

Search Discussions

  • Tom Lane at Jun 29, 2007 at 8:27 pm

    "Sun, Way" <Way.Sun@sciatl.com> writes:
    float loadavg;
    loadavg = htonl(1.23);
    It seems entirely unlikely that that will produce a byte-reversed float
    value; what I think will happen is that the byte-reversed value of
    integer 1 will be converted into a host-format float and stored into
    loadavg.

    AFAIK you can't really do this in C without a union. Take a look at
    pq_sendfloat4 and pq_getmsgfloat4 in the backend for examples.

    regards, tom lane
  • Richard Frankland at Jul 9, 2007 at 10:46 pm
    Hi, This is my first reply/post to postgres forums. I hope I'm doing it OK.
    If not, please help.

    So, onto how I see the problem and a possible solution.
    As Tom Lane pointed out. Using a "union" is another solution to this problem.

    Here is a simple testing program and output:

    #include <stdio.h>
    /* for ntohl/htonl */
    #include <netinet/in.h>

    void show_hex (void * vptr) {
    unsigned char * xptr;
    int k;
    /* display each byte in heX */
    xptr = (unsigned char *)vptr;
    for (k=0; k<4; k++)
    {
    printf("%.2X ", *(xptr+k));
    }
    printf("\n");
    }

    int
    main(int argc, char **argv)
    {
    float starting_value = 1.23;
    float loadavg;
    unsigned long reversed_float;

    /* prove we really are starting with 1.23 */
    printf( "%f \n", starting_value);
    show_hex(&starting_value);

    /* see man page for return type of htonl() */
    reversed_float = htonl(starting_value);
    show_hex(&reversed_float);

    /* implicit conversion shown explicitly (i.e. has no effect) */
    reversed_float = htonl((long)starting_value);
    show_hex(&reversed_float);

    /* and another implicit conversion */
    loadavg = reversed_float; //htonl(starting_value);
    show_hex(&loadavg);

    /* again, shown explicitly */
    loadavg = (float)(unsigned long)16777216; //htonl(starting_value);
    show_hex(&loadavg);
    loadavg = (float)(unsigned long)htonl((long)starting_value); //htonl(starting_value);
    show_hex(&loadavg);
    /* show what was stored into loadavg */
    printf( "%f \n", loadavg);

    /* show this is the same as the original problem */
    loadavg = htonl(1.23);
    printf( "%f \n", loadavg);

    /* A (not the only one) correct solution */
    /* Casting a pointer: */
    /* address of source */
    /* | */
    /* pointer to UNSIGNED type | */
    /* | | */
    /* dereference pointer | | */
    /* | | | */
    /* | | | */
    /* | | | */
    reversed_float = htonl(*(unsigned long *)&starting_value);

    show_hex(&reversed_float);

    /*
    * paramValues[0] = (unsigned char *) &reversed_float;
    */
    }

    ------------------------------------------------------
    $ ./tst
    1.230000
    A4 70 9D 3F
    00 00 00 01
    00 00 00 01
    00 00 80 4B
    00 00 80 4B
    16777216.000000
    16777216.000000
    3F 9D 70 A4
    $




    "Sun, Way" wrote:
    Hi,
    I'm having trouble inserting a float into pg using binary format.
    Hope someone on the list can help me point out what I'm doing wrong....
    float loadavg;
    loadavg = htonl(1.23);
    paramValues[0] = (char *) &loadavg
    paramLengths[0] = sizeof(loadavg);
    paramFormats[0] = 1;
    res = PQexecParams(conn,
    "INSERT INTO cpu (loadavg) VALUES ($1::real)",
    1,
    NULL,
    paramValues,
    paramLengths,
    paramFormats,
    1);
    From psql, select returns the value as 1.20765e-38 instead of 1.23.....:(
    Thanks
    Way



    ---------------------------------

    - - - - - Appended by Scientific Atlanta, a Cisco company - - - - -
    This e-mail and any attachments may contain information which is confidential,
    proprietary, privileged or otherwise protected by law. The information is solely
    intended for the named addressee (or a person responsible for delivering it to
    the addressee). If you are not the intended recipient of this message, you are
    not authorized to read, print, retain, copy or disseminate this message or any
    part of it. If you have received this e-mail in error, please notify the sender
    immediately by return e-mail and delete it from your computer.


    ---------------------------------
    Boardwalk for $500? In 2007? Ha!
    Play Monopoly Here and Now (it's updated for today's economy) at Yahoo! Games.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppgsql-interfaces @
categoriespostgresql
postedJun 29, '07 at 7:42p
activeJul 9, '07 at 10:46p
posts3
users3
websitepostgresql.org
irc#postgresql

People

Translate

site design / logo © 2022 Grokbase