Hi,

On Wed, Dec 11, 2002 at 09:26:38AM -0800, David Wheeler wrote:
> On Wednesday, December 11, 2002, at 09:18  AM, Baldur Kristinsson wrote:
> 
> > Here is an issue regarding DBD::Pg (I wouldn't exactly call it a bug,
> > but it can be irritating nonetheless):
> >
> > If you try to pass a text value containing a null character as a bind
> > value to a statement handle during execute(), you get the error
> >
> >    "parser: unterminated quoted string at or near ..."
> >
> > There seems to be no way to escape the null byte without truncating the
> > string that is being passed (I would guess this happens at the libpq
> > level rather than DBD::Pg, though).
> >
> > If you call $dbh->quote on the value and try to insert it directly into
> > the statement, the null byte is tacitly removed.
> >
> > This seems to me to be better behaviour than the above. So I think it's
> > sensible to remove null bytes from values for other types of columns
> > than BYTEA.
> 
> Interesting. However, the null byte is by definition a string 
> terminator, so it makes no sense to me to include any data in a string 
> beyond the null byte. The behavior of quote() to tacitly strip out a 
> null byte is actually a bug (left over from an earlier implementation) 
> that should be fixed.

It may normally be a string terminator in C programs, but in Perl
strings it is not. People using DBD::Pg are not writing C, they're
writing Perl - in fact, probably in most cases they know next to no C.

Besides, there is a glaring inconsistency with the way $dbh->quote
works. In my opinion nothing which "works" using $dbh->quote and direct
embedding in a SQL statement should fail to work using placeholders and
bind values. If people learn that embedding works and placeholders
don't, they adopt programming habits that are even worse than those they
already have ;-)

In DBD::Informix the behaviour differs somewhat: Strings containing
null bytes are tacitly truncated in the case of char, varchar and
lvarchar.  However, if you're using custom datatypes such as
"informix".html and "informix".ifxmrdata, the null bytes make it into
the database. In fact, I discovered this issue when migrating from
Informix to PostgreSQL - I was moving data from an ifxmrdata column in
Informix into a text column in PostgreSQL. I'm not saying that
DBD::Informix behaviour is better, but that there should be more
consistency between DBD drivers in this regard.

> 
> I think that if you have a string with a null byte in it and you want 
> to put it into a field other than BYTEA, your code should be 
> responsible for removing it before it passes it to DBI.
> 
> dbi-dev'ers, please correct me if I'm wrong. :-)

Hmmm... Certainly it's not difficult to add a "s/\0//g" whenever you're
handling data from a source which could pass the damned thing on to you.
But isn't it one of Perl's founding principles to Do What I Mean -
without always being told exactly how it should do it...?

(As an aside, I don't see why text columns in PostgreSQL should not be
allowed to contain null bytes. After all, it cannot be a question of
storage format, as there always are four bytes at the start of a
PostgreSQL TEXT field telling us how long the string is. In some of my
attempts I seemed to successfully escape the string as '\\000' so it
made it to the Pg parser where it was truncated. If it made it that far,
why not take note of the escape and just bloody well insert the whole
thing? But of course that has nothing to do with DBD::Pg...)

-- 

Regards,

-  Baldur

Reply via email to