Re: psql and bytea - Mailing list pgsql-general

From Féliciano Matias
Subject Re: psql and bytea
Date
Msg-id 1052994560.18364.6.camel@one.myworld
Whole thread Raw
Responses Re: psql and bytea
List pgsql-general
Sorry for my poor English.

First, postgresql is a beautiful DBMS !

I try to use bytea type with psql to store some files (i know, there are
\lo_*).

There are some informations in the man page of psql :

------------------------------------
Another possible use of this mechanism is to copy the contents of a file
into a field. First load the file into a variable and then proceed as
above.

       testdb=> \set content ’\’’ ‘cat my_file.txt‘ ’\’’
       testdb=> INSERT INTO my_table VALUES (:content);

One possible problem with this approach is that my_file.txt might
contain single quotes. These need to be escaped so that they don’t cause
a syntax error when the third line is processed. This could be done
with the program sed:

       testdb=> \set content ’\’’ ‘sed -e "s/’/\\\\\\’/g" < my_file.txt‘ ’\’’

But this does not work with binary string (bytea) since i want to store
any kind of files.
------------------------------------

I check the documentation (really fantastic documentation ! Great job):
http://www.postgresql.org/docs/view.php?version=7.3&idoc=0&file=datatype-binary.html

I build two very simple tools to convert a binary stream to a bytea
stream.

------------------------------------
tobytea_sql.c :
/*
* convert a stream to bytea.
* The '\' is escaped, so it can be used in a SQL statement.
*/
#include <stdio.h>
int main(void) {
    int c ;
    while ((c = getchar()) != EOF) {
        if ( c == '\'' || c == '\\' ||
             c < 32 || c > 126 ) {
            printf("\\\\%d%d%d",
                   (c % (8*8*8)) / (8*8),
                   (c % (8*8)) / 8,
                   c % 8) ;
        }
        else {
            putchar(c) ;
        }
    }
    return 0 ;
}
------------------------------------
/*
 * convert a bytea stream
 * This is not compatible with the output of tobytea_sql !
 * tobytea_sql put two \ . frombytea espect only one !
 */
#include <stdio.h>
int main(void) {
    int c ;
    int car ;
    while ((c = getchar()) != EOF) {
        if ( c < 32 || c > 126) {
            fprintf(stderr, "Char ignored\n") ;
            break ;
        }
        if ( c == '\\' ) {
            if ((c = getchar()) == EOF) return 0 ;
            car = (c - '0') * 8 * 8 ;
            if ((c = getchar()) == EOF) return 0 ;
            car += (c - '0') * 8 ;
            if ((c = getchar()) == EOF) return 0 ;
            car += c - '0' ;
            putchar(car) ;
        }
        else {
            putchar(c) ;
        }
    }
    return 0 ;
}
------------------------------------

How to use it ?
insert into a table :
$ psql
[...]
one=> create temp table tmp (data bytea) ;
CREATE TABLE
one=> -- push some data in a psql variable
one=> \set content '\''`tobytea_sql < data`'\''
one=> \echo :content
'o\\030\\251\\273C7\\266K\\331 ... [snip] ... \323W\\027\\256D'
one=> -- insert
one=> insert into tmp (data) values (:content) ;
INSERT 35042356 1
one=> -- vrite the content of temp.data to a file
one=> \a
Output format is unaligned.
one=> \t
Showing only tuples.
one=> \o | frombytea > data
one=> select data from tmp ;
one=> Char ignored            -- psql send a CR at the end of the row
(frombytea drop it since CR = 10 and it is not a "normal" char for a
bytea stream).



Is there a bug in psql ? Check this :

WARNING : this example take a lot of memory !

Create a big file with some random data :
$ dd if=/dev/urandom bs=1M count=20 of=data
$ #the bytea stream is about 74 Mo !)
$ tobytea < data | wc
0   81574 74379444
$ psql
[...]
one=> \set content '\''`tobytea_sql < data`'\''
one=> insert into tmp (data) values(:content) ;
one'> -- Problem !
one'> ' -- try to continue
one(> ) ;
INSERT 35042373 1
one=> select length(data) from tmp ;
  length
--
18924736
(1 row)

one=> -- this is not the original size (20M : 20971520).

I don't have any problems with smaller files (10Mo is always fine).

All of this is used with postgresql 7.3.2 shipped with Red Hat Linux 9 .

--
Féliciano Matias <feliciano.matias@free.fr>

Attachment

pgsql-general by date:

Previous
From: Ewald Geschwinde
Date:
Subject: problem
Next
From: Ewald Geschwinde
Date:
Subject: Re: problem