Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing CAST(foo AS type) as a relationship condition in DBIx::Class

For historical reasons, we have a table at work that has integer values in a text field that correspond to the ID's in another table. Example:

CREATE TABLE things (
    id     INTEGER,
    name   VARCHAR,
    thingy VARCHAR
);

CREATE TABLE other_things (
    id     INTEGER,
    name   VARCHAR,
);

So a "thing" has-one "other thing", but rather than being set up sensibly, the join field is a varchar, and called "thingy".

So in Postgres, I can do this to join the two tables:

SELECT t.id, t.name, ot.name FROM things t 
  JOIN other_things ot ON CAST(t.thingy AS int) = ot.id

How can I represent this relationship in DBIx::Class? Here's an example of one thing I've tried:

package MySchema::Thing;

__PACKAGE__->has_one(
    'other_thing',
    'MySchema::OtherThing',
    { 'foreign.id' => 'CAST(self.thingy AS int)' },
); 
like image 225
Kit Peters Avatar asked Sep 19 '13 21:09

Kit Peters


2 Answers

nwellnhof was close, but to get the literal SQL to SQL::Abstract, I had to do a coderef like so:

__PACKAGE__->has_one(
    'other_thing',
    'MySchema::OtherThing',
    sub {
        my $args = shift;
        return {
            qq{$args->{'foreign_alias'}.id} => { q{=} => \qq{CAST($args->{'self_alias'}.dept AS int)} },
        };  
    },
); 
like image 72
Kit Peters Avatar answered Oct 19 '22 16:10

Kit Peters


Using Literal SQL should do the trick:

__PACKAGE__->has_one(
    'other_thing',
    'MySchema::OtherThing',
    { 'foreign.id' => { '=', \'CAST(self.thingy AS int)' } },
);
like image 37
nwellnhof Avatar answered Oct 19 '22 15:10

nwellnhof