[Dbix-class] Joins with circular relations
Bernhard Weisshuhn
bkw at weisshuhn.de
Wed Oct 3 17:17:54 GMT 2007
Hello everbody,
I'm pulling my hair on this one. I'm trying to specify a query where the join
criteria of one nested table refers to a table already joined. No problem in
SQL, but I can't seem to do it in DBIC-Syntax.
It's kind of hard to explain for, so please take a look at this example (which
is not the actual model, just something a made up to illustrate the problem):
CREATE TABLE englishwords (
englishword TEXT PRIMARY KEY
);
CREATE TABLE languages (
language TEXT PRIMARY KEY
);
CREATE TABLE translatedwords ( englishword TEXT NOT NULL REFERENCES englishwords(englishword), language TEXT NOT NULL REFERENCES languages(language), translatedword TEXT NOT NULL,
PRIMARY KEY (englishword,language)
);
CREATE TABLE users ( user TEXT PRIMARY KEY,
language TEXT NOT NULL REFERENCES languages(language)
);
CREATE TABLE userwords ( user TEXT NOT NULL REFERENCES users(user), englishword TEXT NOT NULL REFERENCES englishwords(englishword), PRIMARY KEY (user,englishword)
);
We have a list of words and correspoinding translations in several
languages. Users have a preferred language and a list of words they need for
whatever it is that they use the application for.
Silly, but easier to understand than the actual model.
I now want to retrieve all words of a certain user from his 'userwords'
list translated to his preferred language. In plain SQL I would write sth
like this:
SELECT
translatedwords.translatedword
FROM
userwords
JOIN users ON (users.user = userwords.user)
JOIN translatedwords ON (
translatedwords.language = users.language AND
translatedwords.englishword = userwords.englishword
)
WHERE
userwords.user='someuser';
Is there a way to specify this in DBIC with regular join or prefetch syntax?
All my experiments ended up with the language table being selected twice.
I naively tried stuff like:
$schema->resultset('Translatedwords')->search(
{'users.user' => 'someuser' },
{
join => [
{ englishword => { userwords => { user => 'language' } } },
{ language => 'users'}
]
}
);
... which does what the fine manual says, but not what I want.
Is there a way to do this that I have overlooked?
Or is this way of joining simply not supported?
Do I maybe have to add some clever manual relation to the schema?
For reference, these are the relations from the autogenerated schema:
Translations::Englishwords->has_many(
"translatedwords",
"Translations::Translatedwords",
{ "foreign.englishword" => "self.englishword" },
);
Translations::Languages->has_many(
"translatedwords",
"Translations::Translatedwords",
{ "foreign.language" => "self.language" },
);
Translations::Translatedwords->belongs_to(
"englishword",
"Translations::Englishwords",
{ englishword => "englishword" },
);
Translations::Translatedwords->belongs_to(
"language",
"Translations::Languages",
{ language => "language" },
);
Translations::Languages->has_many(
"users",
"Translations::Users",
{ "foreign.language" => "self.language" },
);
Translations::Users->belongs_to(
"language",
"Translations::Languages",
{ language => "language" },
);
Translations::Englishwords->has_many(
"userwords",
"Translations::Userwords",
{ "foreign.englishword" => "self.englishword" },
);
Translations::Users->has_many(
"userwords",
"Translations::Userwords",
{ "foreign.user" => "self.user" },
);
Translations::Userwords->belongs_to(
"user", "Translations::Users", { user => "user" }
);
Translations::Userwords->belongs_to(
"englishword",
"Translations::Englishwords",
{ englishword => "englishword" },
);
Any help would be greatly appreciated.
regards,
bkw
More information about the DBIx-Class
mailing list