plpythonu and bytea

Started by Greg Steffensenalmost 21 years ago2 messagesgeneral
Jump to latest
#1Greg Steffensen
greg.steffensen@gmail.com

Hey, I'm trying to write some plpython procedures that read binary data from
images on the disk and store it in bytea fields. I'm basically trying to
write a plpython procedure that accepts a varchar and returns a bytea, with
these procedure contents:

data = file(args[0]).read()
return data

(The actual procedure will have more in it, but that's the tricky part). But
the returned data is always severely truncated. Is returning a bytea from
plpython impossible, or is there some way I should escape the data string?
I've tried using the built in encode and decode functions, but they don't
seem to help. If worse comes to worse, I can store the base64 encoded
version, of course, but I'd rather not do that. Any ideas?

Greg

#2Michael Fuhr
mike@fuhr.org
In reply to: Greg Steffensen (#1)
Re: plpythonu and bytea

On Sat, Jul 02, 2005 at 04:49:23PM -0400, Greg Steffensen wrote:

Hey, I'm trying to write some plpython procedures that read binary data from
images on the disk and store it in bytea fields. I'm basically trying to
write a plpython procedure that accepts a varchar and returns a bytea, with
these procedure contents:

data = file(args[0]).read()
return data

(The actual procedure will have more in it, but that's the tricky part). But
the returned data is always severely truncated. Is returning a bytea from
plpython impossible, or is there some way I should escape the data string?

I think the return value is a cstring that's cast to whatever type
the function is declared to return; I'd guess it's being truncated
because it contains NUL (\000) values. Example:

CREATE FUNCTION foo() RETURNS bytea AS $$
data = '\001\002\000\003\004'
return data
$$ LANGUAGE plpythonu;

SELECT foo(), length(foo());
foo | length
----------+--------
\001\002 | 2
(1 row)

The function should work if the data is escaped. I don't know the
best Python way to do that, but the following appears to work:

CREATE FUNCTION foo() RETURNS bytea AS $$
data = '\001\002\000\003\004'
return ''.join(['\\%03o' % ord(x) for x in data])
$$ LANGUAGE plpythonu;

SELECT foo(), length(foo());
foo | length
----------------------+--------
\001\002\000\003\004 | 5
(1 row)

It seems like there ought to be a better way than the list comprehension
shown; maybe you or somebody else with better Python skills can improve
on it.

--
Michael Fuhr
http://www.fuhr.org/~mfuhr/