flesh out doc for 'from', 'select', 'as' and 'group_by'
Will Hawes [Mon, 23 Jan 2006 17:48:39 +0000 (17:48 +0000)]
lib/DBIx/Class/ResultSet.pm

index ff876b1..4df3d58 100644 (file)
@@ -657,11 +657,57 @@ from that, then auto-populates C<as> from C<select> as normal.
 
 =head2 select (arrayref)
 
-Indicates which columns should be selected from the storage.
+Indicates which columns should be selected from the storage. You can use
+column names, or in the case of RDBMS back ends, function or stored procedure
+names:
+
+  $rs = $schema->resultset('Foo')->search(
+    {},
+    {
+      select => {
+        'column_name',
+        { count => 'column_to_count' },
+        { sum => 'column_to_sum' }
+      }
+    }
+  );
+
+When you use function/stored procedure names and do not supply an C<as>
+attribute, the column names returned are storage-dependent. E.g. MySQL would
+return a column named C<count(column_to_count)> in the above example.
 
 =head2 as (arrayref)
 
-Indicates column names for object inflation.
+Indicates column names for object inflation. This is used in conjunction with
+C<select>, usually when C<select> contains one or more function or stored
+procedure names:
+
+  $rs = $schema->resultset('Foo')->search(
+    {},
+    {
+      select => {
+        'column1',
+        { count => 'column2' }
+      },
+      as => [qw/ column1 column2_count /]
+    }
+  );
+
+  my $foo = $rs->first(); # get the first Foo
+
+If the object against which the search is performed already has an accessor
+matching a column name specified in C<as>, the value can be retrieved using
+the accessor as normal:
+
+  my $column1 = $foo->column1();
+
+If on the other hand an accessor does not exist in the object, you need to
+use C<get_column> instead:
+
+  my $column2_count = $foo->get_column('column2_count');
+
+You can create your own accessors if required - see
+L<DBIx::Class::Manual::Cookbook> for details.
 
 =head2 join
 
@@ -705,13 +751,92 @@ query (when they are accessed afterwards they will have already been
 objects, because it saves a query.  Currently limited to prefetching
 one relationship deep, so unlike C<join>, prefetch must be an arrayref.
 
-=head2 from 
+=head2 from (arrayref)
 
-This attribute can contain a arrayref of elements.  Each element can be another
-arrayref, to nest joins, or it can be a hash which represents the two sides
-of the join. 
+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>.
+
+In simple terms, C<from> works as follows:
+
+    [
+        { <alias> => <table>, -join-type => 'inner|left|right' }
+        [] # nested JOIN (optional)
+        { <table.column> = <foreign_table.foreign_key> }
+    ]
+
+    JOIN
+        <alias> <table>
+        [JOIN ...]
+    ON <table.column> = <foreign_table.foreign_key>
+
+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(
+      {},
+      {
+          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(
+        {},
+        {
+            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
 
 =head2 page
 
@@ -720,13 +845,16 @@ for an unpaged resultset.
 
 =head2 rows
 
-For a paged resultset, how many rows per page.  Can also be used to simulate an
-SQL C<LIMIT>.
+For a paged resultset, how many rows per page:
+
+  rows => 10
+
+Can also be used to simulate an SQL C<LIMIT>.
 
 =head2 group_by (arrayref)
 
-A arrayref of columns to group by (note that L</count> doesn't work on grouped
-resultsets).
+A arrayref of columns to group by. Can include columns of joined tables. Note
+note that L</count> doesn't work on grouped resultsets.
 
   group_by => [qw/ column1 column2 ... /]