[Bioperl-l] postgres 8.3 will not cast text to integer any longer

Hilmar Lapp hlapp at gmx.net
Thu Mar 20 20:34:42 EDT 2008


On Mar 20, 2008, at 7:30 PM, Erik wrote:
> Here is the postgres 8.3.1 result of your sql statements:
>
> CREATE TABLE t1 (a varchar(10), b text, c integer);
>
> SELECT * from t1 WHERE a = 1;   -- fails in 8.3.1
> SELECT * from t1 WHERE b = 1;	  -- fails in 8.3.1
> SELECT * from t1 WHERE c = '1'; -- ok
>
> [...]
> The failure is always (virtually) the same:
> ERROR:  operator does not exist: character varying = integer
> LINE 1: SELECT * from t1 WHERE a = 1;
>                                  ^
> HINT:  No operator matches the given name and argument
> type(s). You might need to add explicit type casts.


So it's indeed the backend that changed behavior. It's actually  
documented as I see now:

http://www.postgresql.org/docs/8.3/static/release-8-3.html

scroll to section E.2.2. Migration to Version 8.3, E.2.2.1. General,  
and the first item there:

<quote>
Non-character data types are no longer automatically cast to TEXT  
(Peter, Tom)

Previously, if a non-character value was supplied to an operator or  
function that requires text input, it was automatically cast to text,  
for most (though not all) built-in data types. This no longer  
happens: an explicit cast to text is now required for all non- 
character-string types.
</quote>

I can see the arguments there but this will prevent upgrading to 8.3  
for many many applications, and the comments from the Pg developers  
('fix your SQL to use casts') that I've seen there on the mailing  
lists are just not helpful. Fixing SQL is for many legacy  
applications is just not an option.

In the case of Bioperl-db it's very non-trivial, because all of a  
sudden we would be changing from a hands-off and let-the-driver- 
figure-it-out approach to forcing types everywhere.

So I think at this point with this change I have to declare Bioperl- 
db officially incompatible with PostgreSQL 8.3+ until we've found a  
solution to this, which is too bad because it seems 8.3 has some  
really nice performance features added.

One possible solution might be to create a CAST in the database  
(namely the one that was taken away, restoring behavior to pre-8.3).  
Another possibility is to move the parameter binding method into the  
driver adaptor which would then delegate to the DBI method but would  
be overridden for the PostgreSQL adapter to force all bindings to  
type string.

Which leads me back to the surprise observation that the parameter  
was bound as an integer in the first place, when DBD::Pg used to bind  
everything as string unless you told it otherwise. Which DBD::Pg  
version is it that you are using? I would suspect (or hope) that  
maybe there is soon an update release of DBD::Pg that fixes this  
problem by going back to binding everything as string by default (and  
as the tests show PostgreSQL will still convert strings to integer if  
necessary).

Depending on what I (or can someone else update us on this?) find out  
for the DBD::Pg plans, I'll probably start looking into moving the  
parameter binding into the driver adapters. Though it does feel  
pathetic that this is now also not transparent between drivers.

	-hilmar
-- 
===========================================================
: Hilmar Lapp  -:-  Durham, NC  -:-  hlapp at gmx dot net :
===========================================================





More information about the Bioperl-l mailing list