Передача CAST(тип foo AS) в качестве условия отношения в DBIx::Class

По историческим причинам у нас есть рабочая таблица с целочисленными значениями в текстовом поле, которые соответствуют идентификаторам в другой таблице. Пример:

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

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

Таким образом, "вещь" имеет - одна "другая вещь", но вместо того, чтобы быть настроенной разумно, поле соединения - это varchar, и называется "вещь".

Так что в Postgres я могу сделать это, чтобы объединить две таблицы:

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

Как я могу представить эти отношения в DBIx::Class? Вот пример одной вещи, которую я пробовал:

package MySchema::Thing;

__PACKAGE__->has_one(
    'other_thing',
    'MySchema::OtherThing',
    { 'foreign.id' => 'CAST(self.thingy AS int)' },
); 

3 ответа

Решение

nwellnhof был близок, но чтобы получить буквальный SQL к SQL::Abstract, мне пришлось сделать coderef примерно так:

__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)} },
        };  
    },
); 

Использование Literal SQL должно помочь:

__PACKAGE__->has_one(
    'other_thing',
    'MySchema::OtherThing',
    { 'foreign.id' => { '=', \'CAST(self.thingy AS int)' } },
);

Я бы изменил тип данных поля.

Если это невозможно, вы можете добавить другое поле типа int и триггер, который преобразует varchar в int и сохраняет его в поле int, которое затем используется для объединений для повышения производительности.

Другие вопросы по тегам