Передача 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, которое затем используется для объединений для повышения производительности.