Skip to content

Commit

Permalink
Undocument the from attribute (the description was mostly outdated an…
Browse files Browse the repository at this point in the history
…yway)
  • Loading branch information
ribasushi committed Sep 21, 2009
1 parent 1bedffa commit f4342a8
Showing 1 changed file with 0 additions and 171 deletions.
171 changes: 0 additions & 171 deletions lib/DBIx/Class/ResultSet.pm
Original file line number Diff line number Diff line change
Expand Up @@ -3575,177 +3575,6 @@ By default, searches are not cached.
For more examples of using these attributes, see
L<DBIx::Class::Manual::Cookbook>.
=head2 from
=over 4
=item Value: \@from_clause
=back
The C<from> attribute gives you manual control over the C<FROM> clause of SQL
statements generated by L<DBIx::Class>, allowing you to express custom C<JOIN>
clauses.
NOTE: Use this on your own risk. This allows you to shoot off your foot!
C<join> will usually do what you need and it is strongly recommended that you
avoid using C<from> unless you cannot achieve the desired result using C<join>.
And we really do mean "cannot", not just tried and failed. Attempting to use
this because you're having problems with C<join> is like trying to use x86
ASM because you've got a syntax error in your C. Trust us on this.
Now, if you're still really, really sure you need to use this (and if you're
not 100% sure, ask the mailing list first), here's an explanation of how this
works.
The syntax is as follows -
[
{ <alias1> => <table1> },
[
{ <alias2> => <table2>, -join_type => 'inner|left|right' },
[], # nested JOIN (optional)
{ <table1.column1> => <table2.column2>, ... (more conditions) },
],
# More of the above [ ] may follow for additional joins
]
<table1> <alias1>
JOIN
<table2> <alias2>
[JOIN ...]
ON <table1.column1> = <table2.column2>
<more joins may follow>
An easy way to follow the examples below is to remember the following:
Anything inside "[]" is a JOIN
Anything inside "{}" is a condition for the enclosing JOIN
The following examples utilize a "person" table in a family tree application.
In order to express parent->child relationships, this table is self-joined:
# Person->belongs_to('father' => 'Person');
# Person->belongs_to('mother' => 'Person');
C<from> can be used to nest joins. Here we return all children with a father,
then search against all mothers of those children:
$rs = $schema->resultset('Person')->search(
undef,
{
alias => 'mother', # alias columns in accordance with "from"
from => [
{ mother => 'person' },
[
[
{ child => 'person' },
[
{ father => 'person' },
{ 'father.person_id' => 'child.father_id' }
]
],
{ 'mother.person_id' => 'child.mother_id' }
],
]
},
);
# Equivalent SQL:
# SELECT mother.* FROM person mother
# JOIN (
# person child
# JOIN person father
# ON ( father.person_id = child.father_id )
# )
# ON ( mother.person_id = child.mother_id )
The type of any join can be controlled manually. To search against only people
with a father in the person table, we could explicitly use C<INNER JOIN>:
$rs = $schema->resultset('Person')->search(
undef,
{
alias => 'child', # alias columns in accordance with "from"
from => [
{ child => 'person' },
[
{ father => 'person', -join_type => 'inner' },
{ 'father.id' => 'child.father_id' }
],
]
},
);
# Equivalent SQL:
# SELECT child.* FROM person child
# INNER JOIN person father ON child.father_id = father.id
You can select from a subquery by passing a resultset to from as follows.
$schema->resultset('Artist')->search(
undef,
{ alias => 'artist2',
from => [ { artist2 => $artist_rs->as_query } ],
} );
# and you'll get sql like this..
# SELECT artist2.artistid, artist2.name, artist2.rank, artist2.charfield FROM
# ( SELECT me.artistid, me.name, me.rank, me.charfield FROM artists me ) artist2
If you need to express really complex joins, you
can supply literal SQL to C<from> via a scalar reference. In this case
the contents of the scalar will replace the table name associated with the
resultsource.
WARNING: This technique might very well not work as expected on chained
searches - you have been warned.
# Assuming the Event resultsource is defined as:
MySchema::Event->add_columns (
sequence => {
data_type => 'INT',
is_auto_increment => 1,
},
location => {
data_type => 'INT',
},
type => {
data_type => 'INT',
},
);
MySchema::Event->set_primary_key ('sequence');
# This will get back the latest event for every location. The column
# selector is still provided by DBIC, all we do is add a JOIN/WHERE
# combo to limit the resultset
$rs = $schema->resultset('Event');
$table = $rs->result_source->name;
$latest = $rs->search (
undef,
{ from => \ "
(SELECT e1.* FROM $table e1
JOIN $table e2
ON e1.location = e2.location
AND e1.sequence < e2.sequence
WHERE e2.sequence is NULL
) me",
},
);
# Equivalent SQL (with the DBIC chunks added):
SELECT me.sequence, me.location, me.type FROM
(SELECT e1.* FROM events e1
JOIN events e2
ON e1.location = e2.location
AND e1.sequence < e2.sequence
WHERE e2.sequence is NULL
) me;
=head2 for
=over 4
Expand Down

0 comments on commit f4342a8

Please sign in to comment.