Обсуждение: PQescapeBytea & PQunescapeBytea

Поиск
Список
Период
Сортировка

PQescapeBytea & PQunescapeBytea

От
"Frost, Mr. Michael (contractor)"
Дата:
Hi.  I am running 7.4.6 of postgres.  I have some data that I desire to
store as bytea in postgres.  The data is an array of floats.  I cast the
array of floats to a unsigned char and call PQescapeBytea to prepare the
data for ingest.  I insert it into the database, and then extract it
back out.  I then call PQunescapeBytea and cast it back to float to
return it to it's original.

However, I am probably doing something incorrect, since the before /
after data is not the same.

So, I eliminate the ingest into the database, and basically just called
the PQescapeBytea & PQunescapeBytea and I get different results.

In my example, I fill an array of 10 floats with values from 0.0 to 9.0.
I then cast this to unsigned char.  I then call PQescapeBytea.

for ( i = 0; i < 10; i++ )  prsData = ( float ) i;

pData = ( unsigned char * ) prsData;

pEscapedData = PQescapeBytea ( pData, 40, &newSize );

// newSize comes back to be 161.

Then I call PQunescapeBytea with pEscapedData.  This returns a newSize
that is different from the original.

pUnescapedData = PQunescapeBytea ( pEscapedData, &newSize );

//  newSize comes back to be 130, but I expected it to be 40.

Any insight as to what I am doing incorrectly.?

Thanks,
Michael Frost
Computer Sciences Corporation
Phone:  831-656-4723
Fax:  831-656-4769
Email:  frost@nrlmry.navy.mil


Re: PQescapeBytea & PQunescapeBytea

От
Tom Lane
Дата:
"Frost, Mr. Michael (contractor)" <frost@nrlmry.navy.mil> writes:
> [ PQescapeBytea & PQunescapeBytea are not inverses ]

They're not supposed to be.  PQescapeBytea creates something that can be
inserted into a SQL command as a string literal.  PQunescapeBytea
deconstructs something that has been returned as a SELECT result.
There are two different levels of backslashing involved.

This doesn't directly answer your original problem, but I think we'll
need to see more of your code to figure out what you were doing wrong.
        regards, tom lane


Re: PQescapeBytea & PQunescapeBytea

От
"Frost, Mr. Michael (contractor)"
Дата:
Thanks for the quick response Tom.

Here is some sample code that illustrates what I am trying to do.
Basically, I have an array of floating point values that I want to store
in a bytea field.  To do this, I cast the float * to unsigned char *,
run the unsigned char *'s through PQescapeBytea, and then insert the
record.  To extract it back out, I retrieve the record, run it through
PQunescapeBytea, and then cast it back to float.

The array of floats is just an example.  In practice, it would just be a
pointer some arbitrary data.

Thanks,
Michael Frost
Computer Sciences Corporation
Phone:  831-656-4723
Fax:  831-656-4769
Email:  frost@nrlmry.navy.mil

////////////////////////////////////////////////////////////////////////
//
#include "postgres.h"
#include <stdio.h>

exec sql include sqlca;

int main ( int argc, char **argv ) {  void insertData ( );  void getData ( );
  printf ( "Calling insertData\n" );  insertData ( );
  printf ( "Calling getData\n" );  getData ( );

}

void getData ( ) {  int newSize = 0;  float *prsData = 0;
exec sql begin declare section;  char myData[2000];  int nGridID = 0;  int id = 1;  char *pUnescapedData = 0;
exec sql end declare section;
  exec sql connect to mike;
  memset ( myData, 0, 2000 );  exec sql select gridid, thedata into :nGridID, :myData from grids
where gridid = :id;
  pUnescapedData = PQunescapeBytea ( myData, &newSize );
  prsData = ( float * ) pUnescapedData;
  exec sql disconnect;

}

void insertData ( ) {  float *pData = 0;  int    i = 0;  unsigned char *pTemp = 0;  int    newSize = 0;  int    size =
40;
exec sql begin declare section;  unsigned char *pEncodeData = 0, *myData = 0;  int            nGridID = 1;
exec sql end declare section;
  exec sql connect to mike;
  pData = ( float * ) calloc ( 1, 10 * sizeof ( float ) );  for ( i = 0; i < 10; i++ )     pData[i] = ( float ) i;
  pTemp = ( unsigned char * ) calloc ( 1, 10 * sizeof ( float )  + 4 );  memcpy ( &pTemp[1], pData, 10 * sizeof ( float
));  memcpy ( pTemp, &size, 4 );
 
  pEncodeData = PQescapeBytea ( pTemp, 10 * sizeof ( float ) + 4,
&newSize );
  myData = ( unsigned char * ) calloc ( 1, newSize );  memcpy ( myData, pEncodeData, newSize );
  exec sql delete from grids;  exec sql insert into grids ( gridid, thedata ) values ( :nGridID,
:myData );
  exec sql disconnect;
}

/*    Table "public.grids"Column  |  Type   | Modifiers
---------+---------+-----------gridid  | integer |thedata | bytea   |
*/
///////////////////////////////////////////////////////////////////////
-----Original Message-----
From: Tom Lane [mailto:tgl@sss.pgh.pa.us]
Sent: Wednesday, May 04, 2005 7:30 AM
To: Frost, Mr. Michael (contractor)
Cc: pgsql-interfaces@postgresql.org
Subject: Re: [INTERFACES] PQescapeBytea & PQunescapeBytea 


"Frost, Mr. Michael (contractor)" <frost@nrlmry.navy.mil> writes:
> [ PQescapeBytea & PQunescapeBytea are not inverses ]

They're not supposed to be.  PQescapeBytea creates something that can be
inserted into a SQL command as a string literal.  PQunescapeBytea
deconstructs something that has been returned as a SELECT result.
There are two different levels of backslashing involved.

This doesn't directly answer your original problem, but I think we'll
need to see more of your code to figure out what you were doing wrong.
        regards, tom lane

Re: PQescapeBytea & PQunescapeBytea

От
Tom Lane
Дата:
"Frost, Mr. Michael (contractor)" <frost@nrlmry.navy.mil> writes:
> Here is some sample code that illustrates what I am trying to do.

Oh, you're feeding it through ECPG eh?  That's probably the source of
the impedance mismatch :-(.  PQescapeBytea is going to produce things
like\\001
because it expects that its output will be inserted directly into a
literal constant in an SQL command string.  I don't know a whole lot
about ECPG, but I would suppose that when you tell it to send the value
of a C string, it expects to have to apply its own level of escaping.
So what's getting sent is probably something like\\\\001
which of course isn't going to store what you want.  There may be an
issue on the output side too, though I'm less sure about that.

I don't know what is the recommended procedure for inserting arbitrary
binary data through ECPG.  Maybe Michael Meskes can help.
        regards, tom lane


> Basically, I have an array of floating point values that I want to store
> in a bytea field.  To do this, I cast the float * to unsigned char *,
> run the unsigned char *'s through PQescapeBytea, and then insert the
> record.  To extract it back out, I retrieve the record, run it through
> PQunescapeBytea, and then cast it back to float.

> The array of floats is just an example.  In practice, it would just be a
> pointer some arbitrary data.

> Thanks,
> Michael Frost
> Computer Sciences Corporation
> Phone:  831-656-4723
> Fax:  831-656-4769
> Email:  frost@nrlmry.navy.mil

> ////////////////////////////////////////////////////////////////////////
> //
> #include "postgres.h"
> #include <stdio.h>

> exec sql include sqlca;

> int main ( int argc, char **argv ) {
>    void insertData ( );
>    void getData ( );

>    printf ( "Calling insertData\n" );
>    insertData ( );

>    printf ( "Calling getData\n" );
>    getData ( );

> }

> void getData ( ) {
>    int newSize = 0;
>    float *prsData = 0;
> exec sql begin declare section;
>    char myData[2000];
>    int nGridID = 0;
>    int id = 1;
>    char *pUnescapedData = 0;
> exec sql end declare section;

>    exec sql connect to mike;

>    memset ( myData, 0, 2000 );
>    exec sql select gridid, thedata into :nGridID, :myData from grids
> where gridid = :id;

>    pUnescapedData = PQunescapeBytea ( myData, &newSize );

>    prsData = ( float * ) pUnescapedData;

>    exec sql disconnect;

> }

> void insertData ( ) {
>    float *pData = 0;
>    int    i = 0;
>    unsigned char *pTemp = 0;
>    int    newSize = 0;
>    int    size = 40;
> exec sql begin declare section;
>    unsigned char *pEncodeData = 0, *myData = 0;
>    int            nGridID = 1;
> exec sql end declare section;

>    exec sql connect to mike;

>    pData = ( float * ) calloc ( 1, 10 * sizeof ( float ) );
>    for ( i = 0; i < 10; i++ )
>       pData[i] = ( float ) i;

>    pTemp = ( unsigned char * ) calloc ( 1, 10 * sizeof ( float )  + 4 );
>    memcpy ( &pTemp[1], pData, 10 * sizeof ( float ) );
>    memcpy ( pTemp, &size, 4 );

>    pEncodeData = PQescapeBytea ( pTemp, 10 * sizeof ( float ) + 4,
> &newSize );

>    myData = ( unsigned char * ) calloc ( 1, newSize );
>    memcpy ( myData, pEncodeData, newSize );

>    exec sql delete from grids;
>    exec sql insert into grids ( gridid, thedata ) values ( :nGridID,
> :myData );

>    exec sql disconnect;
> }

> /*
>      Table "public.grids"
>  Column  |  Type   | Modifiers
> ---------+---------+-----------
>  gridid  | integer |
>  thedata | bytea   |
> */
> ///////////////////////////////////////////////////////////////////////