views:

282

answers:

1

I'm trying to move a simple Sinatra app over to Heroku. Migration of the Ruby app code and existing MySQL database using Taps went smoothly, but I'm getting the following Postgres error:

PostgresError - ERROR: operator does not exist: text = integer LINE 1: ...d_at", "post_id" FROM "comments" WHERE ("post_id" IN (4, 17,... ^ HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.

It's evident that the problem is related to a type mismatch in the query, but this is being issued from a Haml template by the DataMapper ORM at a very high level of abstraction, so I'm not sure how I'd go about controlling this...

Specifically, this seems to be throwing up on a call of p.comments from my Haml template, where p represents a given post.

The Datamapper models are related as follows:

class Post
    property :id, Serial
    ...
    has n, :comments
end

class Comment
    property :id, Serial
    ...
    belongs_to :post
end

This works fine on my local and current hosted environment using MySQL, but Postgres is clearly more strict.

There must be hundreds of Datamapper & Haml apps running on Postgres DBs, and this model relationship is super-conventional, so hopefully someone has seen (and determined how to fix) this. Thanks!

UPDATE: See http://stackoverflow.com/questions/2943693/heroku-postgres-type-operator-error-after-migrating-db-from-mysql for resolution.

+1  A: 

It looks like post_id is of type TEXT instead of INTEGER. To fix this, you have to change the datatype. This has been changed in version 8.3, older version have an implicit cast. You can tell PostgreSQL to do so:

CREATE FUNCTION pg_catalog.text(integer) RETURNS text STRICT IMMUTABLE LANGUAGE SQL AS 'SELECT textin(int4out($1));';
CREATE CAST (integer AS text) WITH FUNCTION pg_catalog.text(integer) AS IMPLICIT;

CREATE FUNCTION pg_catalog.text(smallint) RETURNS text STRICT IMMUTABLE LANGUAGE SQL AS 'SELECT textin(int2out($1));';
CREATE CAST (smallint AS text) WITH FUNCTION pg_catalog.text(smallint) AS IMPLICIT;

CREATE FUNCTION pg_catalog.text(bigint) RETURNS text STRICT IMMUTABLE LANGUAGE SQL AS 'SELECT textin(int8out($1));';
CREATE CAST (bigint AS text) WITH FUNCTION pg_catalog.text(bigint) AS IMPLICIT;

See also http://wiki.postgresql.org/wiki/Image:Pg83-implicit-casts.sql

Frank Heikens
Thanks, Frank. I'm aware that the problem is that the ID columns have been set as TEXT; the question is *why*? On the original MySQL back-end, these columns are stored as INT and the app runs fine, but for some reason these are getting converted in the DB transfer.Unfortunately, Heroku doesn't give direct SQL access to the database, so I don't think I can create these functions. This problem would go away if I could store the IDs as INT in the first place ;)This actually seems to be a Taps bug and not related to Sinatra/Haml, so I'll try to reword... Thanks again.
sevennineteen