3 DBIx::Class::Manual::Cookbook - Miscellaneous recipes
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:
14 my $rs = $schema->resultset('Artist')->search(
17 page => 1, # page to return (defaults to 1)
18 rows => 10, # number of results per page
22 return $rs->all(); # all records for page 1
24 The C<page> attribute does not have to be specified in your search:
26 my $rs = $schema->resultset('Artist')->search(
33 return $rs->page(1); # DBIx::Class::ResultSet containing first 10 records
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:
40 =head3 Complex WHERE clauses
42 Sometimes you need to formulate a query using specific operators:
44 my @albums = $schema->resultset('Album')->search({
45 artist => { 'like', '%Lamb%' },
46 title => { 'like', '%Fear of Fours%' },
49 This results in something like the following C<WHERE> clause:
51 WHERE artist LIKE '%Lamb%' AND title LIKE '%Fear of Fours%'
53 Other queries might require slightly more complex logic:
55 my @albums = $schema->resultset('Album')->search({
58 artist => { 'like', '%Smashing Pumpkins%' },
59 title => 'Siamese Dream',
61 artist => 'Starchildren',
65 This results in the following C<WHERE> clause:
67 WHERE ( artist LIKE '%Smashing Pumpkins%' AND title = 'Siamese Dream' )
68 OR artist = 'Starchildren'
70 For more information on generating complex queries, see
71 L<SQL::Abstract/WHERE CLAUSES>.
73 =head3 Using specific columns
75 When you only want selected columns from a table, you can use C<cols> to
76 specify which ones you need:
78 my $rs = $schema->resultset('Artist')->search(
81 columns => [qw/ name /]
86 # SELECT artist.name FROM artist
88 =head3 Using database functions or stored procedures
90 The combination of C<select> and C<as> can be used to return the result of a
91 database function or stored procedure as a column value. You use C<select> to
92 specify the source for your column value (e.g. a column name, function, or
93 stored procedure name). You then use C<as> to set the column name you will use
94 to access the returned value:
96 my $rs = $schema->resultset('Artist')->search(
99 select => [ 'name', { LENGTH => 'name' } ],
100 as => [qw/ name name_length /],
105 # SELECT name name, LENGTH( name ) name_length
108 If your alias exists as a column in your base class (i.e. it was added with
109 C<add_columns>), you just access it as normal. Our C<Artist> class has a C<name>
110 column, so we just use the C<name> accessor:
112 my $artist = $rs->first();
113 my $name = $artist->name();
115 If on the other hand the alias does not correspond to an existing column, you
116 can get the value using the C<get_column> accessor:
118 my $name_length = $artist->get_column('name_length');
120 If you don't like using C<get_column>, you can always create an accessor for
121 any of your aliases using either of these:
123 # Define accessor manually:
124 sub name_length { shift->get_column('name_length'); }
126 # Or use DBIx::Class::AccessorGroup:
127 __PACKAGE__->mk_group_accessors('column' => 'name_length');
129 =head3 SELECT DISTINCT with multiple columns
131 my $rs = $schema->resultset('Foo')->search(
135 { distinct => [ $source->columns ] }
137 as => [ $source->columns ]
141 my $count = $rs->next->get_column('count');
143 =head3 SELECT COUNT(DISTINCT colname)
145 my $rs = $schema->resultset('Foo')->search(
149 { count => { distinct => 'colname' } }
155 =head3 Grouping results
157 L<DBIx::Class> supports C<GROUP BY> as follows:
159 my $rs = $schema->resultset('Artist')->search(
163 select => [ 'name', { count => 'cds.cdid' } ],
164 as => [qw/ name cd_count /],
165 group_by => [qw/ name /]
170 # SELECT name, COUNT( cds.cdid ) FROM artist me
171 # LEFT JOIN cd cds ON ( cds.artist = me.artistid )
174 =head3 Predefined searches
176 You can write your own DBIx::Class::ResultSet class by inheriting from it
177 and define often used searches as methods:
179 package My::DBIC::ResultSet::CD;
182 use base 'DBIx::Class::ResultSet';
184 sub search_cds_ordered {
187 return $self->search(
189 { order_by => 'name DESC' },
195 To use your resultset, first tell DBIx::Class to create an instance of it
196 for you, in your My::DBIC::Schema::CD class:
198 __PACKAGE__->resultset_class('My::DBIC::ResultSet::CD');
200 Then call your new method in your code:
202 my $ordered_cds = $schema->resultset('CD')->search_cds_ordered();
205 =head3 Predefined searches without writing a ResultSet class
207 Alternatively you can automatically generate a DBIx::Class::ResultSet
208 class by using the ResultSetManager component and tagging your method
211 __PACKAGE__->load_components(qw/ ResultSetManager Core /);
213 sub search_cds_ordered : ResultSet {
215 return $self->search(
217 { order_by => 'name DESC' },
221 Then call your method in the same way from your code:
223 my $ordered_cds = $schema->resultset('CD')->search_cds_ordered();
225 =head2 Using joins and prefetch
227 You can use the C<join> attribute to allow searching on, or sorting your
228 results by, one or more columns in a related table. To return all CDs matching
229 a particular artist name:
231 my $rs = $schema->resultset('CD')->search(
233 'artist.name' => 'Bob Marley'
236 join => [qw/artist/], # join the artist table
241 # SELECT cd.* FROM cd
242 # JOIN artist ON cd.artist = artist.id
243 # WHERE artist.name = 'Bob Marley'
245 If required, you can now sort on any column in the related tables by including
246 it in your C<order_by> attribute:
248 my $rs = $schema->resultset('CD')->search(
250 'artist.name' => 'Bob Marley'
253 join => [qw/ artist /],
254 order_by => [qw/ artist.name /]
259 # SELECT cd.* FROM cd
260 # JOIN artist ON cd.artist = artist.id
261 # WHERE artist.name = 'Bob Marley'
262 # ORDER BY artist.name
264 Note that the C<join> attribute should only be used when you need to search or
265 sort using columns in a related table. Joining related tables when you only
266 need columns from the main table will make performance worse!
268 Now let's say you want to display a list of CDs, each with the name of the
269 artist. The following will work fine:
271 while (my $cd = $rs->next) {
272 print "CD: " . $cd->title . ", Artist: " . $cd->artist->name;
275 There is a problem however. We have searched both the C<cd> and C<artist> tables
276 in our main query, but we have only returned data from the C<cd> table. To get
277 the artist name for any of the CD objects returned, L<DBIx::Class> will go back
280 SELECT artist.* FROM artist WHERE artist.id = ?
282 A statement like the one above will run for each and every CD returned by our
283 main query. Five CDs, five extra queries. A hundred CDs, one hundred extra
286 Thankfully, L<DBIx::Class> has a C<prefetch> attribute to solve this problem.
287 This allows you to fetch results from related tables in advance:
289 my $rs = $schema->resultset('CD')->search(
291 'artist.name' => 'Bob Marley'
294 join => [qw/ artist /],
295 order_by => [qw/ artist.name /],
296 prefetch => [qw/ artist /] # return artist data too!
300 # Equivalent SQL (note SELECT from both "cd" and "artist"):
301 # SELECT cd.*, artist.* FROM cd
302 # JOIN artist ON cd.artist = artist.id
303 # WHERE artist.name = 'Bob Marley'
304 # ORDER BY artist.name
306 The code to print the CD list remains the same:
308 while (my $cd = $rs->next) {
309 print "CD: " . $cd->title . ", Artist: " . $cd->artist->name;
312 L<DBIx::Class> has now prefetched all matching data from the C<artist> table,
313 so no additional SQL statements are executed. You now have a much more
316 Note that as of L<DBIx::Class> 0.04, C<prefetch> cannot be used with
317 C<has_many> relationships. You will get an error along the lines of "No
318 accessor for prefetched ..." if you try.
320 Also note that C<prefetch> should only be used when you know you will
321 definitely use data from a related table. Pre-fetching related tables when you
322 only need columns from the main table will make performance worse!
324 =head3 Multi-step joins
326 Sometimes you want to join more than one relationship deep. In this example,
327 we want to find all C<Artist> objects who have C<CD>s whose C<LinerNotes>
328 contain a specific string:
330 # Relationships defined elsewhere:
331 # Artist->has_many('cds' => 'CD', 'artist');
332 # CD->has_one('liner_notes' => 'LinerNotes', 'cd');
334 my $rs = $schema->resultset('Artist')->search(
336 'liner_notes.notes' => { 'like', '%some text%' },
340 'cds' => 'liner_notes'
346 # SELECT artist.* FROM artist
347 # JOIN ( cd ON artist.id = cd.artist )
348 # JOIN ( liner_notes ON cd.id = liner_notes.cd )
349 # WHERE liner_notes.notes LIKE '%some text%'
351 Joins can be nested to an arbitrary level. So if we decide later that we
352 want to reduce the number of Artists returned based on who wrote the liner
355 # Relationship defined elsewhere:
356 # LinerNotes->belongs_to('author' => 'Person');
358 my $rs = $schema->resultset('Artist')->search(
360 'liner_notes.notes' => { 'like', '%some text%' },
361 'author.name' => 'A. Writer'
366 'liner_notes' => 'author'
373 # SELECT artist.* FROM artist
374 # JOIN ( cd ON artist.id = cd.artist )
375 # JOIN ( liner_notes ON cd.id = liner_notes.cd )
376 # JOIN ( author ON author.id = liner_notes.author )
377 # WHERE liner_notes.notes LIKE '%some text%'
378 # AND author.name = 'A. Writer'
380 =head2 Multi-step prefetch
382 From 0.04999_05 onwards, C<prefetch> can be nested more than one relationship
383 deep using the same syntax as a multi-step join:
385 my $rs = $schema->resultset('Tag')->search(
395 # SELECT tag.*, cd.*, artist.* FROM tag
396 # JOIN cd ON tag.cd = cd.cdid
397 # JOIN artist ON cd.artist = artist.artistid
399 Now accessing our C<cd> and C<artist> relationships does not need additional
402 my $tag = $rs->first;
403 print $tag->cd->artist->name;
407 As of version 0.04001, there is improved transaction support in
408 L<DBIx::Class::Storage::DBI> and L<DBIx::Class::Schema>. Here is an
409 example of the recommended way to use it:
411 my $genus = $schema->resultset('Genus')->find(12);
414 my ($schema, $genus, $code) = @_;
415 $genus->add_to_species({ name => 'troglodyte' });
418 $schema->txn_do($code, $genus); # Can have a nested transaction
419 return $genus->species;
430 $rs = $schema->txn_do($coderef1, $schema, $genus, $coderef2);
433 if ($@) { # Transaction failed
434 die "the sky is falling!" #
435 if ($@ =~ /Rollback failed/); # Rollback failed
437 deal_with_failed_transaction();
440 Nested transactions will work as expected. That is, only the outermost
441 transaction will actually issue a commit to the $dbh, and a rollback
442 at any level of any transaction will cause the entire nested
443 transaction to fail. Support for savepoints and for true nested
444 transactions (for databases that support them) will hopefully be added
447 =head2 Many-to-many relationships
449 This is straightforward using L<DBIx::Class::Relationship::ManyToMany>:
452 # ... set up connection ...
456 __PACKAGE__->table('user');
457 __PACKAGE__->add_columns(qw/id name/);
458 __PACKAGE__->set_primary_key('id');
459 __PACKAGE__->has_many('user_address' => 'My::UserAddress', 'user');
460 __PACKAGE__->many_to_many('addresses' => 'user_address', 'address');
462 package My::UserAddress;
464 __PACKAGE__->table('user_address');
465 __PACKAGE__->add_columns(qw/user address/);
466 __PACKAGE__->set_primary_key(qw/user address/);
467 __PACKAGE__->belongs_to('user' => 'My::User');
468 __PACKAGE__->belongs_to('address' => 'My::Address');
472 __PACKAGE__->table('address');
473 __PACKAGE__->add_columns(qw/id street town area_code country/);
474 __PACKAGE__->set_primary_key('id');
475 __PACKAGE__->has_many('user_address' => 'My::UserAddress', 'address');
476 __PACKAGE__->many_to_many('users' => 'user_address', 'user');
478 $rs = $user->addresses(); # get all addresses for a user
479 $rs = $address->users(); # get all users for an address
481 =head2 Setting default values for a row
483 It's as simple as overriding the C<new> method. Note the use of
487 my ( $class, $attrs ) = @_;
489 $attrs->{foo} = 'bar' unless defined $attrs->{foo};
491 $class->next::method($attrs);
494 For more information about C<next::method>, look in the L<Class::C3>
495 documentation. See also L<DBIx::Class::Manual::Component> for more
496 ways to write your own base classes to do this.
498 People looking for ways to do "triggers" with DBIx::Class are probably
499 just looking for this.
501 =head2 Stringification
503 Employ the standard stringification technique by using the C<overload>
504 module. Replace C<foo> with the column/method of your choice.
506 use overload '""' => 'foo', fallback => 1;
508 =head2 Disconnecting cleanly
510 If you find yourself quitting an app with Control-C a lot during
511 development, you might like to put the following signal handler in
512 your main database class to make sure it disconnects cleanly:
515 __PACKAGE__->storage->disconnect;
518 =head2 Schema import/export
520 This functionality requires you to have L<SQL::Translator> (also known as
521 "SQL Fairy") installed.
523 To create a DBIx::Class schema from an existing database:
526 --to DBIx::Class::File
527 --prefix "MySchema" > MySchema.pm
529 To create a MySQL database from an existing L<DBIx::Class> schema, convert the
530 schema to MySQL's dialect of SQL:
532 sqlt --from DBIx::Class --to MySQL --DBIx::Class "MySchema.pm" > Schema1.sql
534 And import using the mysql client:
536 mysql -h "host" -D "database" -u "user" -p < Schema1.sql
538 =head2 Easy migration from class-based to schema-based setup
540 You want to start using the schema-based approach to L<DBIx::Class>
541 (see L<SchemaIntro.pod>), but have an established class-based setup with lots
542 of existing classes that you don't want to move by hand. Try this nifty script
548 my $schema = MyDB->schema_instance;
550 my $translator = SQL::Translator->new(
551 debug => $debug || 0,
552 trace => $trace || 0,
553 no_comments => $no_comments || 0,
554 show_warnings => $show_warnings || 0,
555 add_drop_table => $add_drop_table || 0,
556 validate => $validate || 0,
558 'DBIx::Schema' => $schema,
561 'prefix' => 'My::Schema',
565 $translator->parser('DBIx::Class');
566 $translator->producer('DBIx::Class::File');
568 my $output = $translator->translate(@args) or die
569 "Error: " . $translator->error;
573 You could use L<Module::Find> to search for all subclasses in the MyDB::*
574 namespace, which is currently left as an exercise for the reader.
576 =head2 Schema versioning
578 The following example shows simplistically how you might use DBIx::Class to
579 deploy versioned schemas to your customers. The basic process is as follows:
585 Create a DBIx::Class schema
597 Modify schema to change functionality
601 Deploy update to customers
605 =head3 Create a DBIx::Class schema
607 This can either be done manually, or generated from an existing database as
608 described under C<Schema import/export>.
610 =head3 Save the schema
612 Use C<sqlt> to transform your schema into an SQL script suitable for your
613 customer's database. E.g. for MySQL:
615 sqlt --from DBIx::Class
617 --DBIx::Class "MySchema.pm" > Schema1.mysql.sql
619 If you need to target databases from multiple vendors, just generate an SQL
620 script suitable for each. To support PostgreSQL too:
622 sqlt --from DBIx::Class
624 --DBIx::Class "MySchema.pm" > Schema1.pgsql.sql
626 =head3 Deploy to customers
628 There are several ways you could deploy your schema. These are probably
629 beyond the scope of this recipe, but might include:
635 Require customer to apply manually using their RDBMS.
639 Package along with your app, making database dump/schema update/tests
640 all part of your install.
644 =head3 Modify the schema to change functionality
646 As your application evolves, it may be necessary to modify your schema to
647 change functionality. Once the changes are made to your schema in DBIx::Class,
648 export the modified schema as before, taking care not to overwrite the original:
650 sqlt --from DBIx::Class
652 --DBIx::Class "Anything.pm" > Schema2.mysql.sql
654 Next, use sqlt-diff to create an SQL script that will update the customer's
657 sqlt-diff --to MySQL Schema1=MySQL Schema2=MySQL > SchemaUpdate.mysql.sql
659 =head3 Deploy update to customers
661 The schema update can be deployed to customers using the same method as before.
663 =head2 Setting limit dialect for SQL::Abstract::Limit
665 In some cases, SQL::Abstract::Limit cannot determine the dialect of the remote
666 SQL-server by looking at the database-handle. This is a common problem when
667 using the DBD::JDBC, since the DBD-driver only know that in has a Java-driver
668 available, not which JDBC-driver the Java component has loaded.
669 This specifically sets the limit_dialect to Microsoft SQL-server (Se more names
670 in SQL::Abstract::Limit -documentation.
672 __PACKAGE__->storage->sql_maker->limit_dialect('mssql');
674 The JDBC-bridge is one way of getting access to a MSSQL-server from a platform
675 that Microsoft doesn't deliver native client libraries for. (e.g. Linux)
677 =head2 Setting quotes for the generated SQL.
679 If the database contains columnames with spaces and/or reserved words, the
680 SQL-query needs to be quoted. This is done using:
682 __PACKAGE__->storage->sql_maker->quote_char([ qw/[ ]/] );
683 __PACKAGE__->storage->sql_maker->name_sep('.');
685 The first sets the quotesymbols. If the quote i "symmetric" as " or '
687 __PACKAGE__->storage->sql_maker->quote_char('"');
689 is enough. If the left quote differs form the right quote, the first
690 notation should be used. name_sep needs to be set to allow the
691 SQL generator to put the quotes the correct place.