Thread: binary data

binary data

From
David Lizano
Date:
Is there any method to insert binary data in a PostgreSQL row?

What data type must I use to insert an image?

Thanks in advance.



Re: binary data

From
hughmandeville@hotmail.com (Hugh Mandeville)
Date:
> Is there any method to insert binary data in a PostgreSQL row?

i'm curious too.

Chapter 3. of the PostgreSQL 7.1 User's Guide has a description of the
data types.

http://www.postgresql.org/idocs/index.php?datatype.html

i couldn't find any official binary data type listed.  you might try
using the text data type and uuencode the data on the way in and
uudecode it on the way out.

the doc note section does mention the "bytea" data type, which works,
but i don't know if it is supported or its limitations.


Re: Re: binary data

From
Alex Pilosov
Date:
Yes, there is a binary datatype, called 'bytea', which can handle anything
you can throw at it, including nulls.

The rules for escaping things you want to throw at it are tricky though.
(and same for unescaping things you get back from database).

If you are using perl, use DBD::Pg version 1.00 or higher, it encapsulates
it all transparently.

On 13 Jun 2001, Hugh Mandeville wrote:

> > Is there any method to insert binary data in a PostgreSQL row?
> 
> i'm curious too.
> 
> Chapter 3. of the PostgreSQL 7.1 User's Guide has a description of the
> data types.
> 
> http://www.postgresql.org/idocs/index.php?datatype.html
> 
> i couldn't find any official binary data type listed.  you might try
> using the text data type and uuencode the data on the way in and
> uudecode it on the way out.
> 
> the doc note section does mention the "bytea" data type, which works,
> but i don't know if it is supported or its limitations.
> 
> ---------------------------(end of broadcast)---------------------------
> TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org
> 
> 



Re: binary data

From
"Hugh Mandeville"
Date:
postgresql's large object functions can be used to store and retrieve binary
data.

http://www.ca.postgresql.org/devel-corner/docs/postgres/lo-interfaces.html

here is some sample code:
   inv_oid = lo_creat(dbconn, INV_READ | INV_WRITE);   if (inv_oid == InvalidOid) {       fprintf (stderr, "lo_creat
failed:%s\n", PQerrorMessage(dbconn));       return (1);   }
 
   res = PQexec(dbconn, "BEGIN WORK");   if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) {       fprintf(stderr,
"PQexe(\"BEGINWORK\") failed: %s\n",
 
PQresultErrorMessage(res));       return (1);   }   PQclear(res);
   obj_fd = lo_open(dbconn, inv_oid, INV_READ | INV_WRITE);   if (obj_fd == -1) {       fprintf (stderr, "lo_open
failed:%s\n", PQerrorMessage(dbconn));       return (1);   }
 
   ret = lo_write (dbconn, obj_fd, buf, buflen);   if (ret == -1) {       fprintf (stderr, "lo_write failed: %s\n",
PQerrorMessage(dbconn));      return (1);   }
 
   ret = lo_lseek(dbconn, obj_fd, 0, SEEK_SET);   if (ret == -1) {       fprintf (stderr, "lo_seek failed: %s\n",
PQerrorMessage(dbconn));      return (1);   }
 
   ret = lo_read (dbconn, obj_fd, buf, buflen);   if (ret == -1) {       fprintf (stderr, "lo_read failed: %s\n",
PQerrorMessage(dbconn));      return (1);   }
 
   lo_close(dbconn, obj_fd);
   res = PQexec(dbconn, "COMMIT");   PQclear(res);






Re: Re: binary data

From
"Hugh Mandeville"
Date:
"Alex Pilosov" <alex@pilosoft.com> wrote in message
news:Pine.BSO.4.10.10106201342060.20262-100000@spider.pilosoft.com...
> Yes, there is a binary datatype, called 'bytea', which can handle anything
> you can throw at it, including nulls.
>
> The rules for escaping things you want to throw at it are tricky though.
> (and same for unescaping things you get back from database).

i ended up having to use the C large object functions to write binary data.
i wasn't able to insert nulls using the INSERT command with psql, C or Perl.
what is the correct way to escape 0?  \000 doesn't work for me.

i created a table with a 'bytea' column. i inserted data escaping out
special characters with their 3 digit octet.
everything inserts correctly except null (\000). data with null characters
inserted with no errors but doing a select for the value or for its size
came back incorrectly.  it returns everything before the null character.
i tried inserting and selecting the data with psql and the C interface
(PQexec, PQgetvalue, PQgetlength).

here is a log from my psql session.  the last insert i did 'null \000 null'
comes back as octet length 5 which is wrong, it should be 11.

test=# CREATE TABLE log (data    bytea);
CREATE
test=# INSERT INTO log (data) VALUES ('plain text');
INSERT 61650 1
test=# INSERT INTO log (data) VALUES ('special chars \n \001 \002');
INSERT 61651 1
test=# INSERT INTO log (data) VALUES ('null \000 null');
INSERT 61652 1
test=# SELECT octet_length(data), data FROM log;octet_length |             data
--------------+------------------------------          10 | plain text          19 | special chars \012 \001 \002
   5 | null
 
(3 rows)


> If you are using perl, use DBD::Pg version 1.00 or higher, it encapsulates
> it all transparently.

i also tried doing an insert and using quote() with perl (DBD::Pg v1.0)

$sql = "INSERT INTO log (data) VALUES (" . $dbh->quote($bindata) . ")";

it has the same problem when the data contains a null, perl returns
"DBD::Pg::st execute failed: ERROR:  Unterminated quoted string at ..."







Re: Re: binary data

From
"Hugh Mandeville"
Date:
this works
"Alex Pilosov" <alex@pilosoft.com> wrote in message
>> what is the correct way to escape 0?  \000 doesn't work for me.
>The correct way is \\\\000 (yes really).
>
>If you are using DBD::Pg after 0.98, it will happen for you automatically
>if you bind the variable as SQL_BINARY.

>> i also tried doing an insert and using quote() with perl (DBD::Pg v1.0)
>You must use $dbh->quote($bindata,DBI::SQL_BINARY) (and DBD::Pg after 1.0)




Re: Re: Re: binary data

From
Tom Lane
Date:
"Hugh Mandeville" <hughmandeville@hotmail.com> writes:
> "Alex Pilosov" <alex@pilosoft.com> wrote in message
>> The rules for escaping things you want to throw at it are tricky though.
>> (and same for unescaping things you get back from database).

> test=# INSERT INTO log (data) VALUES ('special chars \n \001 \002');
> INSERT 61651 1
> test=# INSERT INTO log (data) VALUES ('null \000 null');
> INSERT 61652 1
> test=# SELECT octet_length(data), data FROM log;
>  octet_length |             data
> --------------+------------------------------
>            10 | plain text
>            19 | special chars \012 \001 \002
>             5 | null
> (3 rows)

He did say the rules for escaping things are tricky ;-).  You need to
double the backslashes, because interpretation of the string literal
takes off one level of backslashing before bytea ever sees it:

regression=# INSERT INTO log (data) VALUES ('null \\000 null');
INSERT 273181 1
regression=# SELECT octet_length(data), data FROM log;octet_length |             data
--------------+------------------------------          10 | plain text          19 | special chars \012 \001 \002
   5 | null          11 | null \000 null
 
(4 rows)

        regards, tom lane


Re: Re: Re: binary data

From
Karel Zak
Date:
On Fri, Jun 22, 2001 at 10:22:32AM -0400, Tom Lane wrote:

> He did say the rules for escaping things are tricky ;-).  You need to
> double the backslashes, because interpretation of the string literal
> takes off one level of backslashing before bytea ever sees it:
> 
> regression=# INSERT INTO log (data) VALUES ('null \\000 null');
> INSERT 273181 1
> regression=# SELECT octet_length(data), data FROM log;
>  octet_length |             data
> --------------+------------------------------
>            10 | plain text
>            19 | special chars \012 \001 \002
>             5 | null
>            11 | null \000 null
> (4 rows)
And what use some better encoding if you have a lot of binary chars 
in data. For example base64, that code 2 chars to 3 instead \\000 
that encode 1 char to 4. 
            Karel

-- Karel Zak  <zakkr@zf.jcu.cz>http://home.zf.jcu.cz/~zakkr/C, PostgreSQL, PHP, WWW, http://docs.linux.cz,
http://mape.jcu.cz


Re: Re: Re: binary data

From
Tom Lane
Date:
Karel Zak <zakkr@zf.jcu.cz> writes:
> On Fri, Jun 22, 2001 at 10:22:32AM -0400, Tom Lane wrote:
>> He did say the rules for escaping things are tricky ;-).

>  And what use some better encoding if you have a lot of binary chars 
> in data. For example base64, that code 2 chars to 3 instead \\000 
> that encode 1 char to 4. 

Yeah, it's pretty messy.  Perhaps we could offer a couple of conversion
functions that convert bytea to or from base64 or other popular
encodings.  bytea is pretty impoverished --- it hasn't received the
attention it deserves.
        regards, tom lane


Re: Re: Re: binary data

From
Bruce Momjian
Date:
> Karel Zak <zakkr@zf.jcu.cz> writes:
> > On Fri, Jun 22, 2001 at 10:22:32AM -0400, Tom Lane wrote:
> >> He did say the rules for escaping things are tricky ;-).
> 
> >  And what use some better encoding if you have a lot of binary chars 
> > in data. For example base64, that code 2 chars to 3 instead \\000 
> > that encode 1 char to 4. 
> 
> Yeah, it's pretty messy.  Perhaps we could offer a couple of conversion
> functions that convert bytea to or from base64 or other popular
> encodings.  bytea is pretty impoverished --- it hasn't received the
> attention it deserves.

bytea is binary compatible with text/varchar()/char(), right?  It stores
the same format.

--  Bruce Momjian                        |  http://candle.pha.pa.us pgman@candle.pha.pa.us               |  (610)
853-3000+  If your life is a hard drive,     |  830 Blythe Avenue +  Christ can be your backup.        |  Drexel Hill,
Pennsylvania19026
 


Re: Re: Re: binary data

From
"Hugh Mandeville"
Date:
how binary data is stored, escaped and unescaped seems to vary slightly
between the text and bytea datatypes.

are the following observations correct?

1. Escaping the special characters in the binary data
bytea: the bytea data type needs the backslash character '\' escaped to
'\\\\'
text: the text data type needs '\' escaped to '\\'.
bytea and text handle all escaping all other special characters the same.
 test=# insert into bintest (col_varchar) values ('\\'); INSERT 69443 1 test=# insert into bintest (col_bytea) values
('\\');ERROR:  Bad input string for type bytea test=# insert into bintest (col_bytea) values ('\\\\');
 

2. How the data is actually stored in the database.
bytea: stores the data as binary
text: stores all characters as binary expect 0 which it stores as \000

test=# SELECT octet_length(col_bytea) AS col, col_bytea,
octet_length(col_text) AS tol, char_length(col_text) AS tcl, col_text FROM
bintest WHERE oid = 69458;col |       col_bytea       | tol | tcl |   col_text
-----+-----------------------+-----+-----+--------------  9 | \000\001\002\003hello |  12 |  12 | \000^A^B^Chello

3. Unescaping the special characters
bytea: PQgetvalue() returns a string with all the special characters escaped
out.
text: PQgetvalue returns a string with only the 0 character escaped out.
 PQgetlength() on bytea column returns 21 PQgetvalue() returns 00000000: 5c30 3030 5c30 3031 5c30 3032 5c30 3033
\000\001\002\00300000010: 6865 6c6c 6f                             hello
 
 PQgetlength() on char column returns 12 PQgetvlaue() on char column returns 00000000: 5c30 3030 0102 0368 656c 6c6f
       \000...hello
 


are there any functions for escaping and unescaping binary data?

thanks




Re: Re: Re: Re: binary data

From
Alex Pilosov
Date:
On Wed, 27 Jun 2001, Hugh Mandeville wrote:

> how binary data is stored, escaped and unescaped seems to vary slightly
> between the text and bytea datatypes.
> 
> are the following observations correct?
> 
> 1. Escaping the special characters in the binary data
> bytea: the bytea data type needs the backslash character '\' escaped to
> '\\\\'
Correct. 

> text: the text data type needs '\' escaped to '\\'.
Correct.

> bytea and text handle all escaping all other special characters the same.
text cannot handle null character, for bytea you can use it, with '\\000'


>   test=# insert into bintest (col_varchar) values ('\\');
>   INSERT 69443 1
>   test=# insert into bintest (col_bytea) values ('\\');
>   ERROR:  Bad input string for type bytea
>   test=# insert into bintest (col_bytea) values ('\\\\');
> 
> 2. How the data is actually stored in the database.
> bytea: stores the data as binary
> text: stores all characters as binary expect 0 which it stores as \000
No, text does not and cannot store a null byte. What you see as \000 is
actually a backslash followed by three zeroes, hence you see 12 tol/tcl.

> test=# SELECT octet_length(col_bytea) AS col, col_bytea,
> octet_length(col_text) AS tol, char_length(col_text) AS tcl, col_text FROM
> bintest WHERE oid = 69458;
>  col |       col_bytea       | tol | tcl |   col_text
> -----+-----------------------+-----+-----+--------------
>    9 | \000\001\002\003hello |  12 |  12 | \000^A^B^Chello
> 
> 3. Unescaping the special characters
> bytea: PQgetvalue() returns a string with all the special characters escaped
> out.
> text: PQgetvalue returns a string with only the 0 character escaped out.
> 
>   PQgetlength() on bytea column returns 21
>   PQgetvalue() returns
>   00000000: 5c30 3030 5c30 3031 5c30 3032 5c30 3033  \000\001\002\003
>   00000010: 6865 6c6c 6f                             hello
Correct
> 
>   PQgetlength() on char column returns 12
>   PQgetvlaue() on char column returns
>   00000000: 5c30 3030 0102 0368 656c 6c6f            \000...hello
Incorrect because you didn't insert a null character there, it never
escapes anything. You have a backslash followed by zeros.


> are there any functions for escaping and unescaping binary data?
If you are using Perl DBD::Pg, its done for you automatically.

If you are using libpq, currently there are none.

-alex