Added examples for ResultSetColumn
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Manual / Cookbook.pod
1 =head1 NAME 
2
3 DBIx::Class::Manual::Cookbook - Miscellaneous recipes
4
5 =head1 RECIPES
6
7 =head2 Searching
8
9 =head3 Paged results
10
11 When you expect a large number of results, you can ask L<DBIx::Class> for a
12 paged resultset, which will fetch only a small number of records at a time:
13
14   my $rs = $schema->resultset('Artist')->search(
15     undef,
16     {
17       page => 1,  # page to return (defaults to 1)
18       rows => 10, # number of results per page
19     },
20   );
21
22   return $rs->all(); # all records for page 1
23
24 The C<page> attribute does not have to be specified in your search:
25
26   my $rs = $schema->resultset('Artist')->search(
27     undef,
28     {
29       rows => 10,
30     }
31   );
32
33   return $rs->page(1); # DBIx::Class::ResultSet containing first 10 records
34
35 In either of the above cases, you can return a L<Data::Page> object for the
36 resultset (suitable for use in e.g. a template) using the C<pager> method:
37
38   return $rs->pager();
39
40 =head3 Complex WHERE clauses
41
42 Sometimes you need to formulate a query using specific operators:
43
44   my @albums = $schema->resultset('Album')->search({
45     artist => { 'like', '%Lamb%' },
46     title  => { 'like', '%Fear of Fours%' },
47   });
48
49 This results in something like the following C<WHERE> clause:
50
51   WHERE artist LIKE '%Lamb%' AND title LIKE '%Fear of Fours%'
52
53 Other queries might require slightly more complex logic:
54
55   my @albums = $schema->resultset('Album')->search({
56     -or => [
57       -and => [
58         artist => { 'like', '%Smashing Pumpkins%' },
59         title  => 'Siamese Dream',
60       ],
61       artist => 'Starchildren',
62     ],
63   });
64
65 This results in the following C<WHERE> clause:
66
67   WHERE ( artist LIKE '%Smashing Pumpkins%' AND title = 'Siamese Dream' )
68     OR artist = 'Starchildren'
69
70 For more information on generating complex queries, see
71 L<SQL::Abstract/WHERE CLAUSES>.
72
73 =head3 Using specific columns
74
75 When you only want specific columns from a table, you can use
76 C<columns> to specify which ones you need. This is useful to avoid
77 loading columns with large amounts of data that you aren't about to
78 use anyway:
79
80   my $rs = $schema->resultset('Artist')->search(
81     undef,
82     {
83       columns => [qw/ name /]
84     }
85   );
86
87   # Equivalent SQL:
88   # SELECT artist.name FROM artist
89
90 This is a shortcut for C<select> and C<as>, see below. C<columns>
91 cannot be used together with C<select> and C<as>.
92
93 =head3 Using database functions or stored procedures
94
95 The combination of C<select> and C<as> can be used to return the result of a
96 database function or stored procedure as a column value. You use C<select> to
97 specify the source for your column value (e.g. a column name, function, or
98 stored procedure name). You then use C<as> to set the column name you will use
99 to access the returned value:
100
101   my $rs = $schema->resultset('Artist')->search(
102     {},
103     {
104       select => [ 'name', { LENGTH => 'name' } ],
105       as     => [qw/ name name_length /],
106     }
107   );
108
109   # Equivalent SQL:
110   # SELECT name name, LENGTH( name ) name_length
111   # FROM artist
112
113 If your alias exists as a column in your base class (i.e. it was added
114 with C<add_columns>), you just access it as normal. Our C<Artist>
115 class has a C<name> column, so we just use the C<name> accessor:
116
117   my $artist = $rs->first();
118   my $name = $artist->name();
119
120 If on the other hand the alias does not correspond to an existing column, you
121 have to fetch the value using the C<get_column> accessor:
122
123   my $name_length = $artist->get_column('name_length');
124
125 If you don't like using C<get_column>, you can always create an accessor for
126 any of your aliases using either of these:
127
128   # Define accessor manually:
129   sub name_length { shift->get_column('name_length'); }
130     
131   # Or use DBIx::Class::AccessorGroup:
132   __PACKAGE__->mk_group_accessors('column' => 'name_length');
133
134 =head3 SELECT DISTINCT with multiple columns
135
136   my $rs = $schema->resultset('Foo')->search(
137     {},
138     {
139       select => [
140         { distinct => [ $source->columns ] }
141       ],
142       as => [ $source->columns ]
143     }
144   );
145
146   my $count = $rs->next->get_column('count');
147
148 =head3 SELECT COUNT(DISTINCT colname)
149
150   my $rs = $schema->resultset('Foo')->search(
151     {},
152     {
153       select => [
154         { count => { distinct => 'colname' } }
155       ],
156       as => [ 'count' ]
157     }
158   );
159
160 =head3 Grouping results
161
162 L<DBIx::Class> supports C<GROUP BY> as follows:
163
164   my $rs = $schema->resultset('Artist')->search(
165     {},
166     {
167       join     => [qw/ cds /],
168       select   => [ 'name', { count => 'cds.cdid' } ],
169       as       => [qw/ name cd_count /],
170       group_by => [qw/ name /]
171     }
172   );
173
174   # Equivalent SQL:
175   # SELECT name, COUNT( cds.cdid ) FROM artist me
176   # LEFT JOIN cd cds ON ( cds.artist = me.artistid )
177   # GROUP BY name
178
179 =head3 Predefined searches
180
181 You can write your own L<DBIx::Class::ResultSet> class by inheriting from it
182 and define often used searches as methods:
183
184   package My::DBIC::ResultSet::CD;
185   use strict;
186   use warnings;
187   use base 'DBIx::Class::ResultSet';
188
189   sub search_cds_ordered {
190       my ($self) = @_;
191
192       return $self->search(
193           {},
194           { order_by => 'name DESC' },
195       );
196   }
197
198   1;
199
200 To use your resultset, first tell DBIx::Class to create an instance of it
201 for you, in your My::DBIC::Schema::CD class:
202
203   __PACKAGE__->resultset_class('My::DBIC::ResultSet::CD');
204
205 Then call your new method in your code:
206
207    my $ordered_cds = $schema->resultset('CD')->search_cds_ordered();
208
209
210 =head3 Predefined searches without writing a ResultSet class
211
212 Alternatively you can automatically generate a DBIx::Class::ResultSet
213 class by using the ResultSetManager component and tagging your method
214 as ResultSet:
215
216   __PACKAGE__->load_components(qw/ ResultSetManager Core /);
217
218   sub search_cds_ordered : ResultSet {
219       my ($self) = @_;
220       return $self->search(
221           {},
222           { order_by => 'name DESC' },
223       );
224   } 
225
226 Then call your method in the same way from your code:
227
228    my $ordered_cds = $schema->resultset('CD')->search_cds_ordered();
229
230 =head2 Using joins and prefetch
231
232 You can use the C<join> attribute to allow searching on, or sorting your
233 results by, one or more columns in a related table. To return all CDs matching
234 a particular artist name:
235
236   my $rs = $schema->resultset('CD')->search(
237     {
238       'artist.name' => 'Bob Marley'    
239     },
240     {
241       join => [qw/artist/], # join the artist table
242     }
243   );
244
245   # Equivalent SQL:
246   # SELECT cd.* FROM cd
247   # JOIN artist ON cd.artist = artist.id
248   # WHERE artist.name = 'Bob Marley'
249
250 If required, you can now sort on any column in the related tables by including
251 it in your C<order_by> attribute:
252
253   my $rs = $schema->resultset('CD')->search(
254     {
255       'artist.name' => 'Bob Marley'
256     },
257     {
258       join     => [qw/ artist /],
259       order_by => [qw/ artist.name /]
260     }
261   };
262
263   # Equivalent SQL:
264   # SELECT cd.* FROM cd
265   # JOIN artist ON cd.artist = artist.id
266   # WHERE artist.name = 'Bob Marley'
267   # ORDER BY artist.name
268
269 Note that the C<join> attribute should only be used when you need to search or
270 sort using columns in a related table. Joining related tables when you only
271 need columns from the main table will make performance worse!
272
273 Now let's say you want to display a list of CDs, each with the name of the
274 artist. The following will work fine:
275
276   while (my $cd = $rs->next) {
277     print "CD: " . $cd->title . ", Artist: " . $cd->artist->name;
278   }
279
280 There is a problem however. We have searched both the C<cd> and C<artist> tables
281 in our main query, but we have only returned data from the C<cd> table. To get
282 the artist name for any of the CD objects returned, L<DBIx::Class> will go back
283 to the database:
284
285   SELECT artist.* FROM artist WHERE artist.id = ?
286
287 A statement like the one above will run for each and every CD returned by our
288 main query. Five CDs, five extra queries. A hundred CDs, one hundred extra
289 queries!
290
291 Thankfully, L<DBIx::Class> has a C<prefetch> attribute to solve this problem.
292 This allows you to fetch results from related tables in advance:
293
294   my $rs = $schema->resultset('CD')->search(
295     {
296       'artist.name' => 'Bob Marley'
297     },
298     {
299       join     => [qw/ artist /],
300       order_by => [qw/ artist.name /],
301       prefetch => [qw/ artist /] # return artist data too!
302     }
303   );
304
305   # Equivalent SQL (note SELECT from both "cd" and "artist"):
306   # SELECT cd.*, artist.* FROM cd
307   # JOIN artist ON cd.artist = artist.id
308   # WHERE artist.name = 'Bob Marley'
309   # ORDER BY artist.name
310
311 The code to print the CD list remains the same:
312
313   while (my $cd = $rs->next) {
314     print "CD: " . $cd->title . ", Artist: " . $cd->artist->name;
315   }
316
317 L<DBIx::Class> has now prefetched all matching data from the C<artist> table,
318 so no additional SQL statements are executed. You now have a much more
319 efficient query.
320
321 Note that as of L<DBIx::Class> 0.05999_01, C<prefetch> I<can> be used with
322 C<has_many> relationships.
323
324 Also note that C<prefetch> should only be used when you know you will
325 definitely use data from a related table. Pre-fetching related tables when you
326 only need columns from the main table will make performance worse!
327
328 =head3 Multi-step joins
329
330 Sometimes you want to join more than one relationship deep. In this example,
331 we want to find all C<Artist> objects who have C<CD>s whose C<LinerNotes>
332 contain a specific string:
333
334   # Relationships defined elsewhere:
335   # Artist->has_many('cds' => 'CD', 'artist');
336   # CD->has_one('liner_notes' => 'LinerNotes', 'cd');
337
338   my $rs = $schema->resultset('Artist')->search(
339     {
340       'liner_notes.notes' => { 'like', '%some text%' },
341     },
342     {
343       join => {
344         'cds' => 'liner_notes'
345       }
346     }
347   );
348
349   # Equivalent SQL:
350   # SELECT artist.* FROM artist
351   # JOIN ( cd ON artist.id = cd.artist )
352   # JOIN ( liner_notes ON cd.id = liner_notes.cd )
353   # WHERE liner_notes.notes LIKE '%some text%'
354
355 Joins can be nested to an arbitrary level. So if we decide later that we
356 want to reduce the number of Artists returned based on who wrote the liner
357 notes:
358
359   # Relationship defined elsewhere:
360   # LinerNotes->belongs_to('author' => 'Person');
361
362   my $rs = $schema->resultset('Artist')->search(
363     {
364       'liner_notes.notes' => { 'like', '%some text%' },
365       'author.name' => 'A. Writer'
366     },
367     {
368       join => {
369         'cds' => {
370           'liner_notes' => 'author'
371         }
372       }
373     }
374   );
375
376   # Equivalent SQL:
377   # SELECT artist.* FROM artist
378   # JOIN ( cd ON artist.id = cd.artist )
379   # JOIN ( liner_notes ON cd.id = liner_notes.cd )
380   # JOIN ( author ON author.id = liner_notes.author )
381   # WHERE liner_notes.notes LIKE '%some text%'
382   # AND author.name = 'A. Writer'
383
384 =head2 Multi-step prefetch
385
386 From 0.04999_05 onwards, C<prefetch> can be nested more than one relationship
387 deep using the same syntax as a multi-step join:
388
389   my $rs = $schema->resultset('Tag')->search(
390     {},
391     {
392       prefetch => {
393         cd => 'artist'
394       }
395     }
396   );
397
398   # Equivalent SQL:
399   # SELECT tag.*, cd.*, artist.* FROM tag
400   # JOIN cd ON tag.cd = cd.cdid
401   # JOIN artist ON cd.artist = artist.artistid
402
403 Now accessing our C<cd> and C<artist> relationships does not need additional
404 SQL statements:
405
406   my $tag = $rs->first;
407   print $tag->cd->artist->name;
408
409 =head2 Columns of data
410
411 If you want to find the sum of a particular column there are several
412 ways, the obvious one is to use search:
413
414   my $rs = $schema->resultset('Items')->search(
415     {},
416     { 
417        select => [ { sum => 'Cost' } ],
418        as     => [ 'total_cost' ],
419     }
420   );
421   my $tc = $rs->first->get_column('total_cost');
422
423 Or, you can use the L<DBIx::Class::ResultSetColumn>, which gets
424 returned when you ask the C<ResultSet> for a column using
425 C<get_column>:
426
427   my $cost = $schema->resultset('Items')->get_column('Cost');
428   my $tc = $cost->sum;
429
430 With this you can also do:
431
432   my $minvalue = $cost->min;
433   my $maxvalue = $cost->max;
434
435 Or just iterate through the values of this column only:
436
437   while ( my $c = $cost->next ) {
438     print $c;
439   }
440
441   foreach my $c ($cost->all) {
442     print $c;
443   }
444
445 See L<DBIx::Class::ResultSetColumn> for more documentation.
446
447 =head2 Using relationships
448
449 =head3 Create a new row in a related table
450
451   my $book->create_related('author', { name => 'Fred'});
452
453 =head3 Search in a related table
454
455 Only searches for books named 'Titanic' by the author in $author.
456
457   my $author->search_related('books', { name => 'Titanic' });
458
459 =head3 Delete data in a related table
460
461 Deletes only the book named Titanic by the author in $author.
462
463   my $author->delete_related('books', { name => 'Titanic' });
464
465 =head3 Ordering a relationship result set
466
467 If you always want a relation to be ordered, you can specify this when you 
468 create the relationship.
469
470 To order C<< $book->pages >> by descending page_number.
471
472   Book->has_many('pages' => 'Page', 'book', { order_by => \'page_number DESC'} );
473
474
475
476 =head2 Transactions
477
478 As of version 0.04001, there is improved transaction support in
479 L<DBIx::Class::Storage::DBI> and L<DBIx::Class::Schema>.  Here is an
480 example of the recommended way to use it:
481
482   my $genus = $schema->resultset('Genus')->find(12);
483
484   my $coderef2 = sub {
485     $genus->extinct(1);
486     $genus->update;
487   };
488
489   my $coderef1 = sub {
490     $genus->add_to_species({ name => 'troglodyte' });
491     $genus->wings(2);
492     $genus->update;
493     $schema->txn_do($coderef2); # Can have a nested transaction
494     return $genus->species;
495   };
496
497   my $rs;
498   eval {
499     $rs = $schema->txn_do($coderef1);
500   };
501
502   if ($@) {                             # Transaction failed
503     die "the sky is falling!"           #
504       if ($@ =~ /Rollback failed/);     # Rollback failed
505
506     deal_with_failed_transaction();
507   }
508
509 Nested transactions will work as expected. That is, only the outermost
510 transaction will actually issue a commit to the $dbh, and a rollback
511 at any level of any transaction will cause the entire nested
512 transaction to fail. Support for savepoints and for true nested
513 transactions (for databases that support them) will hopefully be added
514 in the future.
515
516 =head2 Many-to-many relationships
517
518 This is straightforward using L<DBIx::Class::Relationship::ManyToMany>:
519
520   package My::DB;
521   # ... set up connection ...
522
523   package My::User;
524   use base 'My::DB';
525   __PACKAGE__->table('user');
526   __PACKAGE__->add_columns(qw/id name/);
527   __PACKAGE__->set_primary_key('id');
528   __PACKAGE__->has_many('user_address' => 'My::UserAddress', 'user');
529   __PACKAGE__->many_to_many('addresses' => 'user_address', 'address');
530
531   package My::UserAddress;
532   use base 'My::DB';
533   __PACKAGE__->table('user_address');
534   __PACKAGE__->add_columns(qw/user address/);
535   __PACKAGE__->set_primary_key(qw/user address/);
536   __PACKAGE__->belongs_to('user' => 'My::User');
537   __PACKAGE__->belongs_to('address' => 'My::Address');
538
539   package My::Address;
540   use base 'My::DB';
541   __PACKAGE__->table('address');
542   __PACKAGE__->add_columns(qw/id street town area_code country/);
543   __PACKAGE__->set_primary_key('id');
544   __PACKAGE__->has_many('user_address' => 'My::UserAddress', 'address');
545   __PACKAGE__->many_to_many('users' => 'user_address', 'user');
546
547   $rs = $user->addresses(); # get all addresses for a user
548   $rs = $address->users(); # get all users for an address
549
550 =head2 Setting default values for a row
551
552 It's as simple as overriding the C<new> method.  Note the use of
553 C<next::method>.
554
555   sub new {
556     my ( $class, $attrs ) = @_;
557
558     $attrs->{foo} = 'bar' unless defined $attrs->{foo};
559
560     $class->next::method($attrs);
561   }
562
563 For more information about C<next::method>, look in the L<Class::C3> 
564 documentation. See also L<DBIx::Class::Manual::Component> for more
565 ways to write your own base classes to do this.
566
567 People looking for ways to do "triggers" with DBIx::Class are probably
568 just looking for this.
569
570 =head2 Stringification
571
572 Employ the standard stringification technique by using the C<overload>
573 module.
574
575 To make an object stringify itself as a single column, use something
576 like this (replace C<foo> with the column/method of your choice):
577
578   use overload '""' => 'foo', fallback => 1;
579
580 For more complex stringification, you can use an anonymous subroutine:
581
582   use overload '""' => sub { $_[0]->name . ", " .
583                              $_[0]->address }, fallback => 1;
584
585 =head3 Stringification Example
586
587 Suppose we have two tables: C<Product> and C<Category>. The table
588 specifications are:
589
590   Product(id, Description, category)
591   Category(id, Description)
592
593 C<category> is a foreign key into the Category table.
594
595 If you have a Product object C<$obj> and write something like
596
597   print $obj->category
598
599 things will not work as expected.
600
601 To obtain, for example, the category description, you should add this
602 method to the class defining the Category table:
603
604   use overload "" => sub {
605       my $self = shift;
606
607       return $self->Description;
608   }, fallback => 1;
609
610 =head2 Disconnecting cleanly
611
612 If you find yourself quitting an app with Control-C a lot during
613 development, you might like to put the following signal handler in
614 your main database class to make sure it disconnects cleanly:
615
616   $SIG{INT} = sub {
617     __PACKAGE__->storage->disconnect;
618   };
619
620 =head2 Schema import/export
621
622 This functionality requires you to have L<SQL::Translator> (also known as
623 "SQL Fairy") installed.
624
625 To create a DBIx::Class schema from an existing database:
626
627  sqlt --from DBI
628       --to DBIx::Class::File
629       --prefix "MySchema" > MySchema.pm
630
631 To create a MySQL database from an existing L<DBIx::Class> schema, convert the
632 schema to MySQL's dialect of SQL:
633
634   sqlt --from SQL::Translator::Parser::DBIx::Class 
635        --to MySQL 
636        --DBIx::Class "MySchema.pm" > Schema1.sql
637   
638 And import using the mysql client:
639
640   mysql -h "host" -D "database" -u "user" -p < Schema1.sql
641
642 =head2 Easy migration from class-based to schema-based setup
643
644 You want to start using the schema-based approach to L<DBIx::Class>
645 (see L<SchemaIntro.pod>), but have an established class-based setup with lots
646 of existing classes that you don't want to move by hand. Try this nifty script
647 instead:
648
649   use MyDB;
650   use SQL::Translator;
651   
652   my $schema = MyDB->schema_instance;
653   
654   my $translator           =  SQL::Translator->new( 
655       debug                => $debug          ||  0,
656       trace                => $trace          ||  0,
657       no_comments          => $no_comments    ||  0,
658       show_warnings        => $show_warnings  ||  0,
659       add_drop_table       => $add_drop_table ||  0,
660       validate             => $validate       ||  0,
661       parser_args          => {
662          'DBIx::Schema'    => $schema,
663                               },
664       producer_args   => {
665           'prefix'         => 'My::Schema',
666                          },
667   );
668   
669   $translator->parser('SQL::Translator::Parser::DBIx::Class');
670   $translator->producer('SQL::Translator::Producer::DBIx::Class::File');
671   
672   my $output = $translator->translate(@args) or die
673           "Error: " . $translator->error;
674   
675   print $output;
676
677 You could use L<Module::Find> to search for all subclasses in the MyDB::*
678 namespace, which is currently left as an exercise for the reader.
679
680 =head2 Schema versioning
681
682 The following example shows simplistically how you might use DBIx::Class to
683 deploy versioned schemas to your customers. The basic process is as follows:
684
685 =over 4
686
687 =item 1.
688
689 Create a DBIx::Class schema
690
691 =item 2.
692
693 Save the schema
694
695 =item 3.
696
697 Deploy to customers
698
699 =item 4.
700
701 Modify schema to change functionality
702
703 =item 5.
704
705 Deploy update to customers
706
707 =back
708
709 =head3 Create a DBIx::Class schema
710
711 This can either be done manually, or generated from an existing database as
712 described under C<Schema import/export>.
713
714 =head3 Save the schema
715
716 Use C<sqlt> to transform your schema into an SQL script suitable for your
717 customer's database. E.g. for MySQL:
718
719   sqlt --from SQL::Translator::Parser::DBIx::Class
720        --to MySQL
721        --DBIx::Class "MySchema.pm" > Schema1.mysql.sql
722
723 If you need to target databases from multiple vendors, just generate an SQL
724 script suitable for each. To support PostgreSQL too:
725
726   sqlt --from SQL::Translator::DBIx::Class
727        --to PostgreSQL
728        --DBIx::Class "MySchema.pm" > Schema1.pgsql.sql
729
730 =head3 Deploy to customers
731
732 There are several ways you could deploy your schema. These are probably
733 beyond the scope of this recipe, but might include:
734
735 =over 4
736
737 =item 1.
738
739 Require customer to apply manually using their RDBMS.
740
741 =item 2.
742
743 Package along with your app, making database dump/schema update/tests
744 all part of your install.
745
746 =back
747
748 =head3 Modify the schema to change functionality
749
750 As your application evolves, it may be necessary to modify your schema to
751 change functionality. Once the changes are made to your schema in DBIx::Class,
752 export the modified schema as before, taking care not to overwrite the original:
753
754   sqlt --from SQL::Translator::DBIx::Class
755        --to MySQL
756        --DBIx::Class "Anything.pm" > Schema2.mysql.sql
757
758 Next, use sqlt-diff to create an SQL script that will update the customer's
759 database schema:
760
761   sqlt-diff --to MySQL Schema1=MySQL Schema2=MySQL > SchemaUpdate.mysql.sql
762
763 =head3 Deploy update to customers
764
765 The schema update can be deployed to customers using the same method as before.
766
767 =head2 Setting limit dialect for SQL::Abstract::Limit
768
769 In some cases, SQL::Abstract::Limit cannot determine the dialect of
770 the remote SQL server by looking at the database handle. This is a
771 common problem when using the DBD::JDBC, since the DBD-driver only
772 know that in has a Java-driver available, not which JDBC driver the
773 Java component has loaded.  This specifically sets the limit_dialect
774 to Microsoft SQL-server (See more names in SQL::Abstract::Limit
775 -documentation.
776
777   __PACKAGE__->storage->sql_maker->limit_dialect('mssql');
778
779 The JDBC bridge is one way of getting access to a MSSQL server from a platform
780 that Microsoft doesn't deliver native client libraries for. (e.g. Linux)
781
782 =head2 Setting quoting for the generated SQL. 
783
784 If the database contains column names with spaces and/or reserved words, they
785 need to be quoted in the SQL queries. This is done using:
786
787   __PACKAGE__->storage->sql_maker->quote_char([ qw/[ ]/] );
788   __PACKAGE__->storage->sql_maker->name_sep('.');
789
790 The first sets the quote characters. Either a pair of matching
791 brackets, or a C<"> or C<'>:
792   
793   __PACKAGE__->storage->sql_maker->quote_char('"');
794
795 Check the documentation of your database for the correct quote
796 characters to use. C<name_sep> needs to be set to allow the SQL
797 generator to put the quotes the correct place.
798
799 =head2 Overloading methods
800
801 L<DBIx::Class> uses the L<Class::C3> package, which provides for redispatch of 
802 method calls.  You have to use calls to C<next::method> to overload methods.  
803 More information on using L<Class::C3> with L<DBIx::Class> can be found in 
804 L<DBIx::Class::Manual::Component>.
805
806 =head3 Changing one field whenever another changes
807
808 For example, say that you have three columns, C<id>, C<number>, and 
809 C<squared>.  You would like to make changes to C<number> and have
810 C<squared> be automagically set to the value of C<number> squared.
811 You can accomplish this by overriding C<store_column>:
812
813   sub store_column {
814     my ( $self, $name, $value ) = @_;
815     if ($name eq 'number') {
816       $self->squared($value * $value);
817     }
818     $self->next::method($name, $value);
819   }
820
821 Note that the hard work is done by the call to C<next::method>, which
822 redispatches your call to store_column in the superclass(es).
823
824 =head3 Automatically creating related objects
825
826 You might have a class C<Artist> which has many C<CD>s.  Further, if you
827 want to create a C<CD> object every time you insert an C<Artist> object.
828 You can accomplish this by overriding C<insert> on your objects:
829
830   sub insert {
831     my ( $self, @args ) = @_;
832     $self->next::method(@args);
833     $self->cds->new({})->fill_from_artist($self)->insert;
834     return $self;
835   }
836
837 where C<fill_from_artist> is a method you specify in C<CD> which sets
838 values in C<CD> based on the data in the C<Artist> object you pass in.
839
840 =head2 Debugging DBIx::Class objects with Data::Dumper
841
842 L<Data::Dumper> can be a very useful tool for debugging, but sometimes it can
843 be hard to find the pertinent data in all the data it can generate.
844 Specifically, if one naively tries to use it like so,
845
846   use Data::Dumper;
847
848   my $cd = $schema->resultset('CD')->find(1);
849   print Dumper($cd);
850
851 several pages worth of data from the CD object's schema and result source will
852 be dumped to the screen. Since usually one is only interested in a few column
853 values of the object, this is not very helpful.
854
855 Luckily, it is possible to modify the data before L<Data::Dumper> outputs
856 it. Simply define a hook that L<Data::Dumper> will call on the object before
857 dumping it. For example,
858
859   package My::DB::CD;
860
861   sub _dumper_hook {
862     $_[0] = bless {
863       %{ $_[0] },
864       result_source => undef,
865     }, ref($_[0]);
866   }
867
868   [...]
869
870   use Data::Dumper;
871
872   local $Data::Dumper::Freezer = '_dumper_hook';
873
874   my $cd = $schema->resultset('CD')->find(1);
875   print Dumper($cd);
876          # dumps $cd without its ResultSource
877
878 If the structure of your schema is such that there is a common base class for
879 all your table classes, simply put a method similar to C<_dumper_hook> in the
880 base class and set C<$Data::Dumper::Freezer> to its name and L<Data::Dumper>
881 will automagically clean up your data before printing it. See
882 L<Data::Dumper/EXAMPLES> for more information.
883
884 =head2 Retrieving a row object's Schema
885
886 It is possible to get a Schema object from a row object like so:
887
888   my $schema = $cd->result_source->schema;
889   # use the schema as normal:
890   my $artist_rs = $schema->resultset('Artist'); 
891
892 This can be useful when you don't want to pass around a Schema object to every
893 method.
894
895 =head2 Profiling
896
897 When you enable L<DBIx::Class::Storage::DBI>'s debugging it prints the SQL
898 executed as well as notifications of query completion and transaction
899 begin/commit.  If you'd like to profile the SQL you can subclass the
900 L<DBIx::Class::Storage::Statistics> class and write your own profiling
901 mechanism:
902
903   package My::Profiler;
904   use strict;
905
906   use base 'DBIx::Class::Storage::Statistics';
907
908   use Time::HiRes qw(time);
909
910   my $start;
911
912   sub query_start {
913     my $self = shift();
914     my $sql = shift();
915     my $params = @_;
916
917     print "Executing $sql: ".join(', ', @params)."\n";
918     $start = time();
919   }
920
921   sub query_end {
922     my $self = shift();
923     my $sql = shift();
924     my @params = @_;
925
926     printf("Execution took %0.4f seconds.\n", time() - $start);
927     $start = undef;
928   }
929
930   1;
931
932 You can then install that class as the debugging object:
933
934   __PACKAGE__->storage()->debugobj(new My::Profiler());
935   __PACKAGE__->storage()->debug(1);
936
937 A more complicated example might involve storing each execution of SQL in an
938 array:
939
940   sub query_end {
941     my $self = shift();
942     my $sql = shift();
943     my @params = @_;
944
945     my $elapsed = time() - $start;
946     push(@{ $calls{$sql} }, {
947         params => \@params,
948         elapsed => $elapsed
949     });
950   }
951
952 You could then create average, high and low execution times for an SQL
953 statement and dig down to see if certain parameters cause aberrant behavior.
954
955 =head2 Getting the value of the primary key for the last database insert
956
957 AKA getting last_insert_id
958
959 If you are using PK::Auto, this is straightforward:
960
961   my $foo = $rs->create(\%blah);
962   # do more stuff
963   my $id = $foo->id; # foo->my_primary_key_field will also work.
964
965 If you are not using autoincrementing primary keys, this will probably
966 not work, but then you already know the value of the last primary key anyway.
967
968 =head2 Dynamic Sub-classing DBIx::Class proxy classes 
969 (AKA multi-class object inflation from one table) 
970  
971 L<DBIx::Class> classes are proxy classes, therefore some different
972 techniques need to be employed for more than basic subclassing.  In
973 this example we have a single user table that carries a boolean bit
974 for admin.  We would like like to give the admin users
975 objects(L<DBIx::Class::Row>) the same methods as a regular user but
976 also special admin only methods.  It doesn't make sense to create two
977 seperate proxy-class files for this.  We would be copying all the user
978 methods into the Admin class.  There is a cleaner way to accomplish
979 this.
980
981 Overriding the C<inflate_results()> method within the User proxy-class
982 gives us the effect we want.  This method is called by
983 L<DBIx::Class::ResultSet> when inflating a result from storage.  So we
984 grab the object being returned, inspect the values we are looking for,
985 bless it if it's an admin object, and then return it.  See the example
986 below:
987  
988 B<Schema Definition> 
989  
990     package DB::Schema; 
991      
992     use base qw/DBIx::Class::Schema/; 
993  
994     __PACKAGE__->load_classes(qw/User/); 
995  
996  
997 B<Proxy-Class definitions> 
998  
999     package DB::Schema::User; 
1000      
1001     use strict; 
1002     use warnings; 
1003     use base qw/DBIx::Class/; 
1004      
1005     ### Defined what our admin class is for ensure_class_loaded 
1006     my $admin_class = __PACKAGE__ . '::Admin'; 
1007      
1008     __PACKAGE__->load_components(qw/Core/); 
1009      
1010     __PACKAGE__->table('users'); 
1011      
1012     __PACKAGE__->add_columns(qw/user_id   email    password  
1013                                 firstname lastname active 
1014                                 admin/); 
1015      
1016     __PACKAGE__->set_primary_key('user_id'); 
1017      
1018     sub inflate_result { 
1019         my $self = shift;  
1020         my $ret = $self->next::method(@_); 
1021         if( $ret->admin ) {### If this is an admin rebless for extra functions  
1022             $self->ensure_class_loaded( $admin_class ); 
1023             bless $ret, $admin_class; 
1024         } 
1025         return $ret; 
1026     } 
1027      
1028     sub hello { 
1029         print "I am a regular user.\n"; 
1030         return ; 
1031     } 
1032      
1033      
1034     package DB::Schema::User::Admin; 
1035      
1036     use strict; 
1037     use warnings; 
1038     use base qw/DB::Schema::User/; 
1039      
1040     sub hello 
1041     { 
1042         print "I am an admin.\n"; 
1043         return; 
1044     } 
1045      
1046     sub do_admin_stuff 
1047     { 
1048         print "I am doing admin stuff\n"; 
1049         return ; 
1050     } 
1051  
1052 B<Test File> test.pl 
1053  
1054     use warnings; 
1055     use strict; 
1056     use DB::Schema; 
1057      
1058     my $user_data = { email    => 'someguy@place.com',  
1059                       password => 'pass1',  
1060                       admin    => 0 }; 
1061                            
1062     my $admin_data = { email    => 'someadmin@adminplace.com',  
1063                        password => 'pass2',  
1064                        admin    => 1 }; 
1065                            
1066     my $schema = DB::Schema->connection('dbi:Pg:dbname=test'); 
1067      
1068     $schema->resultset('User')->create( $user_data ); 
1069     $schema->resultset('User')->create( $admin_data ); 
1070      
1071     ### Now we search for them 
1072     my $user = $schema->resultset('User')->single( $user_data ); 
1073     my $admin = $schema->resultset('User')->single( $admin_data ); 
1074      
1075     print ref $user, "\n"; 
1076     print ref $admin, "\n"; 
1077      
1078     print $user->password , "\n"; # pass1 
1079     print $admin->password , "\n";# pass2; inherited from User 
1080     print $user->hello , "\n";# I am a regular user. 
1081     print $admin->hello, "\n";# I am an admin. 
1082  
1083     ### The statement below will NOT print 
1084     print "I can do admin stuff\n" if $user->can('do_admin_stuff'); 
1085     ### The statement below will print 
1086     print "I can do admin stuff\n" if $admin->can('do_admin_stuff'); 
1087
1088 =cut