Cookbook cleanup
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Manual / Cookbook.pod
CommitLineData
3b44ccc6 1=head1 NAME
9c82c181 2
40dbc108 3DBIx::Class::Manual::Cookbook - Miscellaneous recipes
ee38fa40 4
d2f3e87b 5=head1 SEARCHING
2913b2d3 6
d2f3e87b 7=head2 Paged results
faf62551 8
bade79c4 9When you expect a large number of results, you can ask L<DBIx::Class> for a
264f1571 10paged resultset, which will fetch only a defined number of records at a time:
faf62551 11
bade79c4 12 my $rs = $schema->resultset('Artist')->search(
5e8b1b2a 13 undef,
bade79c4 14 {
15 page => 1, # page to return (defaults to 1)
16 rows => 10, # number of results per page
17 },
18 );
faf62551 19
bade79c4 20 return $rs->all(); # all records for page 1
faf62551 21
ec30560d 22You can get a L<Data::Page> object for the resultset (suitable for use
23in e.g. a template) using the C<pager> method:
faf62551 24
bade79c4 25 return $rs->pager();
faf62551 26
d2f3e87b 27=head2 Complex WHERE clauses
2913b2d3 28
40dbc108 29Sometimes you need to formulate a query using specific operators:
30
ea6309e2 31 my @albums = $schema->resultset('Album')->search({
35d4fe78 32 artist => { 'like', '%Lamb%' },
33 title => { 'like', '%Fear of Fours%' },
34 });
40dbc108 35
36This results in something like the following C<WHERE> clause:
37
35d4fe78 38 WHERE artist LIKE '%Lamb%' AND title LIKE '%Fear of Fours%'
40dbc108 39
40Other queries might require slightly more complex logic:
41
ea6309e2 42 my @albums = $schema->resultset('Album')->search({
35d4fe78 43 -or => [
44 -and => [
45 artist => { 'like', '%Smashing Pumpkins%' },
46 title => 'Siamese Dream',
47 ],
48 artist => 'Starchildren',
49 ],
50 });
40dbc108 51
52This results in the following C<WHERE> clause:
53
35d4fe78 54 WHERE ( artist LIKE '%Smashing Pumpkins%' AND title = 'Siamese Dream' )
55 OR artist = 'Starchildren'
40dbc108 56
57For more information on generating complex queries, see
58L<SQL::Abstract/WHERE CLAUSES>.
ee38fa40 59
b9823354 60=head2 Retrieve one and only one row from a resultset
61
62Sometimes you need only the first "top" row of a resultset. While this can be
63easily done with L<< $rs->first|DBIx::Class::ResultSet/first >>, it is suboptimal,
64as a full blown cursor for the resultset will be created and then immediately
65destroyed after fetching the first row object.
66L<< $rs->single|DBIx::Class::ResultSet/single >> is
67designed specifically for this case - it will grab the first returned result
68without even instantiating a cursor.
69
70Before replacing all your calls to C<first()> with C<single()> please observe the
71following CAVEATS:
72
73=over
74
75=item *
76While single() takes a search condition just like search() does, it does
77_not_ accept search attributes. However one can always chain a single() to
78a search():
79
80 my $top_cd = $cd_rs -> search({}, { order_by => 'rating' }) -> single;
81
82
83=item *
84Since single() is the engine behind find(), it is designed to fetch a
85single row per database query. Thus a warning will be issued when the
86underlying SELECT returns more than one row. Sometimes however this usage
87is valid: i.e. we have an arbitrary number of cd's but only one of them is
88at the top of the charts at any given time. If you know what you are doing,
89you can silence the warning by explicitly limiting the resultset size:
90
91 my $top_cd = $cd_rs -> search ({}, { order_by => 'rating', rows => 1 }) -> single;
92
93=back
94
d2f3e87b 95=head2 Arbitrary SQL through a custom ResultSource
321d9634 96
97Sometimes you have to run arbitrary SQL because your query is too complex
98(e.g. it contains Unions, Sub-Selects, Stored Procedures, etc.) or has to
99be optimized for your database in a special way, but you still want to
100get the results as a L<DBIx::Class::ResultSet>.
101The recommended way to accomplish this is by defining a separate ResultSource
102for your query. You can then inject complete SQL statements using a scalar
103reference (this is a feature of L<SQL::Abstract>).
104
105Say you want to run a complex custom query on your user data, here's what
106you have to add to your User class:
107
23471103 108 package My::Schema::Result::User;
321d9634 109
110 use base qw/DBIx::Class/;
111
112 # ->load_components, ->table, ->add_columns, etc.
113
114 # Make a new ResultSource based on the User class
115 my $source = __PACKAGE__->result_source_instance();
116 my $new_source = $source->new( $source );
117 $new_source->source_name( 'UserFriendsComplex' );
118
119 # Hand in your query as a scalar reference
120 # It will be added as a sub-select after FROM,
121 # so pay attention to the surrounding brackets!
122 $new_source->name( \<<SQL );
123 ( SELECT u.* FROM user u
124 INNER JOIN user_friends f ON u.id = f.user_id
125 WHERE f.friend_user_id = ?
126 UNION
127 SELECT u.* FROM user u
128 INNER JOIN user_friends f ON u.id = f.friend_user_id
129 WHERE f.user_id = ? )
130 SQL
131
132 # Finally, register your new ResultSource with your Schema
dbe79da9 133 My::Schema->register_extra_source( 'UserFriendsComplex' => $new_source );
321d9634 134
135Next, you can execute your complex query using bind parameters like this:
136
137 my $friends = [ $schema->resultset( 'UserFriendsComplex' )->search( {},
138 {
139 bind => [ 12345, 12345 ]
140 }
141 ) ];
142
d00a5c68 143... and you'll get back a perfect L<DBIx::Class::ResultSet> (except, of course,
144that you cannot modify the rows it contains, ie. cannot call L</update>,
145L</delete>, ... on it).
146
147If you prefer to have the definitions of these custom ResultSources in separate
148files (instead of stuffing all of them into the same resultset class), you can
149achieve the same with subclassing the resultset class and defining the
150ResultSource there:
151
23471103 152 package My::Schema::Result::UserFriendsComplex;
d00a5c68 153
23471103 154 use My::Schema::Result::User;
155 use base qw/My::Schema::Result::User/;
d00a5c68 156
157 __PACKAGE__->table('dummy'); # currently must be called before anything else
158
159 # Hand in your query as a scalar reference
160 # It will be added as a sub-select after FROM,
161 # so pay attention to the surrounding brackets!
162 __PACKAGE__->name( \<<SQL );
163 ( SELECT u.* FROM user u
164 INNER JOIN user_friends f ON u.id = f.user_id
165 WHERE f.friend_user_id = ?
166 UNION
167 SELECT u.* FROM user u
168 INNER JOIN user_friends f ON u.id = f.friend_user_id
169 WHERE f.user_id = ? )
170 SQL
171
172TIMTOWDI.
321d9634 173
d2f3e87b 174=head2 Using specific columns
faf62551 175
324572ca 176When you only want specific columns from a table, you can use
177C<columns> to specify which ones you need. This is useful to avoid
178loading columns with large amounts of data that you aren't about to
179use anyway:
faf62551 180
bade79c4 181 my $rs = $schema->resultset('Artist')->search(
5e8b1b2a 182 undef,
bade79c4 183 {
5e8b1b2a 184 columns => [qw/ name /]
bade79c4 185 }
186 );
faf62551 187
bade79c4 188 # Equivalent SQL:
189 # SELECT artist.name FROM artist
faf62551 190
324572ca 191This is a shortcut for C<select> and C<as>, see below. C<columns>
192cannot be used together with C<select> and C<as>.
193
d2f3e87b 194=head2 Using database functions or stored procedures
faf62551 195
bade79c4 196The combination of C<select> and C<as> can be used to return the result of a
197database function or stored procedure as a column value. You use C<select> to
198specify the source for your column value (e.g. a column name, function, or
199stored procedure name). You then use C<as> to set the column name you will use
200to access the returned value:
faf62551 201
bade79c4 202 my $rs = $schema->resultset('Artist')->search(
324572ca 203 {},
bade79c4 204 {
205 select => [ 'name', { LENGTH => 'name' } ],
206 as => [qw/ name name_length /],
207 }
208 );
faf62551 209
bade79c4 210 # Equivalent SQL:
98b65433 211 # SELECT name name, LENGTH( name )
bade79c4 212 # FROM artist
faf62551 213
d676881f 214Note that the C< as > attribute has absolutely nothing to with the sql
215syntax C< SELECT foo AS bar > (see the documentation in
216L<DBIx::Class::ResultSet/ATTRIBUTES>). If your alias exists as a
217column in your base class (i.e. it was added with C<add_columns>), you
218just access it as normal. Our C<Artist> class has a C<name> column, so
219we just use the C<name> accessor:
faf62551 220
bade79c4 221 my $artist = $rs->first();
222 my $name = $artist->name();
faf62551 223
224If on the other hand the alias does not correspond to an existing column, you
324572ca 225have to fetch the value using the C<get_column> accessor:
faf62551 226
bade79c4 227 my $name_length = $artist->get_column('name_length');
faf62551 228
bade79c4 229If you don't like using C<get_column>, you can always create an accessor for
faf62551 230any of your aliases using either of these:
231
bade79c4 232 # Define accessor manually:
233 sub name_length { shift->get_column('name_length'); }
faf62551 234
bade79c4 235 # Or use DBIx::Class::AccessorGroup:
236 __PACKAGE__->mk_group_accessors('column' => 'name_length');
faf62551 237
d2f3e87b 238=head2 SELECT DISTINCT with multiple columns
faf62551 239
bade79c4 240 my $rs = $schema->resultset('Foo')->search(
324572ca 241 {},
bade79c4 242 {
243 select => [
244 { distinct => [ $source->columns ] }
245 ],
d676881f 246 as => [ $source->columns ] # remember 'as' is not the same as SQL AS :-)
bade79c4 247 }
248 );
faf62551 249
d2f3e87b 250=head2 SELECT COUNT(DISTINCT colname)
6607ee1b 251
bade79c4 252 my $rs = $schema->resultset('Foo')->search(
324572ca 253 {},
bade79c4 254 {
255 select => [
256 { count => { distinct => 'colname' } }
257 ],
258 as => [ 'count' ]
259 }
260 );
6607ee1b 261
3d565896 262 my $count = $rs->next->get_column('count');
263
d2f3e87b 264=head2 Grouping results
bade79c4 265
266L<DBIx::Class> supports C<GROUP BY> as follows:
267
268 my $rs = $schema->resultset('Artist')->search(
324572ca 269 {},
bade79c4 270 {
271 join => [qw/ cds /],
51458a6a 272 select => [ 'name', { count => 'cds.id' } ],
bade79c4 273 as => [qw/ name cd_count /],
274 group_by => [qw/ name /]
275 }
276 );
6607ee1b 277
bade79c4 278 # Equivalent SQL:
51458a6a 279 # SELECT name, COUNT( cd.id ) FROM artist
280 # LEFT JOIN cd ON artist.id = cd.artist
bade79c4 281 # GROUP BY name
6607ee1b 282
d676881f 283Please see L<DBIx::Class::ResultSet/ATTRIBUTES> documentation if you
284are in any way unsure about the use of the attributes above (C< join
285>, C< select >, C< as > and C< group_by >).
286
70bb942d 287=head2 Subqueries (EXPERIMENTAL)
03834f77 288
289You can write subqueries relatively easily in DBIC.
290
291 my $inside_rs = $schema->resultset('Artist')->search({
292 name => [ 'Billy Joel', 'Brittany Spears' ],
293 });
294
68a797c1 295 my $rs = $schema->resultset('CD')->search({
03834f77 296 artist_id => { 'IN' => $inside_rs->get_column('id')->as_query },
297 });
298
299The usual operators ( =, !=, IN, NOT IN, etc) are supported.
300
301B<NOTE>: You have to explicitly use '=' when doing an equality comparison.
302The following will B<not> work:
303
68a797c1 304 my $rs = $schema->resultset('CD')->search({
03834f77 305 artist_id => $inside_rs->get_column('id')->as_query,
306 });
307
0a62f675 308=head3 Support
309
310Subqueries are supported in the where clause (first hashref), and in the
311from, select, and +select attributes.
312
68a797c1 313=head3 Correlated subqueries
314
315 my $cdrs = $schema->resultset('CD');
316 my $rs = $cdrs->search({
317 year => {
318 '=' => $cdrs->search(
319 { artistid => { '=' => \'me.artistid' } },
320 { alias => 'inner' }
321 )->get_column('year')->max_rs->as_query,
322 },
323 });
324
325That creates the following SQL:
326
327 SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track
328 FROM cd me
329 WHERE year = (
330 SELECT MAX(inner.year)
331 FROM cd inner
332 WHERE artistid = me.artistid
333 )
334
6a9530d1 335=head3 EXPERIMENTAL
336
337Please note that subqueries are considered an experimental feature.
338
d2f3e87b 339=head2 Predefined searches
74dc2edc 340
324572ca 341You can write your own L<DBIx::Class::ResultSet> class by inheriting from it
74dc2edc 342and define often used searches as methods:
343
344 package My::DBIC::ResultSet::CD;
345 use strict;
346 use warnings;
347 use base 'DBIx::Class::ResultSet';
348
349 sub search_cds_ordered {
350 my ($self) = @_;
351
352 return $self->search(
353 {},
354 { order_by => 'name DESC' },
355 );
356 }
357
358 1;
359
360To use your resultset, first tell DBIx::Class to create an instance of it
361for you, in your My::DBIC::Schema::CD class:
362
9dc1bfce 363 # class definition as normal
364 __PACKAGE__->load_components(qw/ Core /);
365 __PACKAGE__->table('cd');
366
367 # tell DBIC to use the custom ResultSet class
74dc2edc 368 __PACKAGE__->resultset_class('My::DBIC::ResultSet::CD');
369
9dc1bfce 370Note that C<resultset_class> must be called after C<load_components> and C<table>, or you will get errors about missing methods.
371
74dc2edc 372Then call your new method in your code:
373
374 my $ordered_cds = $schema->resultset('CD')->search_cds_ordered();
375
d2f3e87b 376=head2 Using SQL functions on the left hand side of a comparison
1c133e22 377
378Using SQL functions on the left hand side of a comparison is generally
379not a good idea since it requires a scan of the entire table. However,
380it can be accomplished with C<DBIx::Class> when necessary.
381
382If you do not have quoting on, simply include the function in your search
383specification as you would any column:
384
385 $rs->search({ 'YEAR(date_of_birth)' => 1979 });
386
387With quoting on, or for a more portable solution, use the C<where>
388attribute:
389
390 $rs->search({}, { where => \'YEAR(date_of_birth) = 1979' });
391
392=begin hidden
393
394(When the bind args ordering bug is fixed, this technique will be better
395and can replace the one above.)
396
397With quoting on, or for a more portable solution, use the C<where> and
398C<bind> attributes:
399
400 $rs->search({}, {
401 where => \'YEAR(date_of_birth) = ?',
402 bind => [ 1979 ]
403 });
404
405=end hidden
406
d2f3e87b 407=head1 JOINS AND PREFETCHING
408
87980de7 409=head2 Using joins and prefetch
410
bade79c4 411You can use the C<join> attribute to allow searching on, or sorting your
412results by, one or more columns in a related table. To return all CDs matching
413a particular artist name:
ea6309e2 414
bade79c4 415 my $rs = $schema->resultset('CD')->search(
416 {
417 'artist.name' => 'Bob Marley'
418 },
419 {
51458a6a 420 join => 'artist', # join the artist table
bade79c4 421 }
422 );
423
424 # Equivalent SQL:
425 # SELECT cd.* FROM cd
426 # JOIN artist ON cd.artist = artist.id
427 # WHERE artist.name = 'Bob Marley'
428
429If required, you can now sort on any column in the related tables by including
430it in your C<order_by> attribute:
431
432 my $rs = $schema->resultset('CD')->search(
433 {
434 'artist.name' => 'Bob Marley'
435 },
436 {
51458a6a 437 join => 'artist',
bade79c4 438 order_by => [qw/ artist.name /]
439 }
2f81ed0f 440 );
ea6309e2 441
bade79c4 442 # Equivalent SQL:
443 # SELECT cd.* FROM cd
444 # JOIN artist ON cd.artist = artist.id
445 # WHERE artist.name = 'Bob Marley'
446 # ORDER BY artist.name
ea6309e2 447
bade79c4 448Note that the C<join> attribute should only be used when you need to search or
449sort using columns in a related table. Joining related tables when you only
450need columns from the main table will make performance worse!
ea6309e2 451
bade79c4 452Now let's say you want to display a list of CDs, each with the name of the
453artist. The following will work fine:
ea6309e2 454
bade79c4 455 while (my $cd = $rs->next) {
456 print "CD: " . $cd->title . ", Artist: " . $cd->artist->name;
457 }
ea6309e2 458
bade79c4 459There is a problem however. We have searched both the C<cd> and C<artist> tables
460in our main query, but we have only returned data from the C<cd> table. To get
461the artist name for any of the CD objects returned, L<DBIx::Class> will go back
462to the database:
ea6309e2 463
bade79c4 464 SELECT artist.* FROM artist WHERE artist.id = ?
ea6309e2 465
466A statement like the one above will run for each and every CD returned by our
467main query. Five CDs, five extra queries. A hundred CDs, one hundred extra
468queries!
469
bade79c4 470Thankfully, L<DBIx::Class> has a C<prefetch> attribute to solve this problem.
897342e4 471This allows you to fetch results from related tables in advance:
ea6309e2 472
bade79c4 473 my $rs = $schema->resultset('CD')->search(
474 {
475 'artist.name' => 'Bob Marley'
476 },
477 {
51458a6a 478 join => 'artist',
bade79c4 479 order_by => [qw/ artist.name /],
51458a6a 480 prefetch => 'artist' # return artist data too!
bade79c4 481 }
482 );
ea6309e2 483
bade79c4 484 # Equivalent SQL (note SELECT from both "cd" and "artist"):
485 # SELECT cd.*, artist.* FROM cd
486 # JOIN artist ON cd.artist = artist.id
487 # WHERE artist.name = 'Bob Marley'
488 # ORDER BY artist.name
ea6309e2 489
490The code to print the CD list remains the same:
491
bade79c4 492 while (my $cd = $rs->next) {
493 print "CD: " . $cd->title . ", Artist: " . $cd->artist->name;
494 }
ea6309e2 495
bade79c4 496L<DBIx::Class> has now prefetched all matching data from the C<artist> table,
ea6309e2 497so no additional SQL statements are executed. You now have a much more
498efficient query.
499
bade79c4 500Also note that C<prefetch> should only be used when you know you will
ea6309e2 501definitely use data from a related table. Pre-fetching related tables when you
502only need columns from the main table will make performance worse!
503
51458a6a 504=head2 Multiple joins
505
506In the examples above, the C<join> attribute was a scalar. If you
507pass an array reference instead, you can join to multiple tables. In
508this example, we want to limit the search further, using
509C<LinerNotes>:
510
511 # Relationships defined elsewhere:
512 # CD->belongs_to('artist' => 'Artist');
513 # CD->has_one('liner_notes' => 'LinerNotes', 'cd');
514 my $rs = $schema->resultset('CD')->search(
515 {
516 'artist.name' => 'Bob Marley'
517 'liner_notes.notes' => { 'like', '%some text%' },
518 },
519 {
520 join => [qw/ artist liner_notes /],
521 order_by => [qw/ artist.name /],
522 }
523 );
524
525 # Equivalent SQL:
526 # SELECT cd.*, artist.*, liner_notes.* FROM cd
527 # JOIN artist ON cd.artist = artist.id
528 # JOIN liner_notes ON cd.id = liner_notes.cd
529 # WHERE artist.name = 'Bob Marley'
530 # ORDER BY artist.name
531
d2f3e87b 532=head2 Multi-step joins
ea6309e2 533
534Sometimes you want to join more than one relationship deep. In this example,
bade79c4 535we want to find all C<Artist> objects who have C<CD>s whose C<LinerNotes>
536contain a specific string:
537
538 # Relationships defined elsewhere:
539 # Artist->has_many('cds' => 'CD', 'artist');
540 # CD->has_one('liner_notes' => 'LinerNotes', 'cd');
541
542 my $rs = $schema->resultset('Artist')->search(
543 {
544 'liner_notes.notes' => { 'like', '%some text%' },
545 },
546 {
547 join => {
548 'cds' => 'liner_notes'
549 }
550 }
551 );
ea6309e2 552
bade79c4 553 # Equivalent SQL:
554 # SELECT artist.* FROM artist
51458a6a 555 # LEFT JOIN cd ON artist.id = cd.artist
556 # LEFT JOIN liner_notes ON cd.id = liner_notes.cd
bade79c4 557 # WHERE liner_notes.notes LIKE '%some text%'
ea6309e2 558
559Joins can be nested to an arbitrary level. So if we decide later that we
560want to reduce the number of Artists returned based on who wrote the liner
561notes:
562
bade79c4 563 # Relationship defined elsewhere:
564 # LinerNotes->belongs_to('author' => 'Person');
565
566 my $rs = $schema->resultset('Artist')->search(
567 {
568 'liner_notes.notes' => { 'like', '%some text%' },
569 'author.name' => 'A. Writer'
570 },
571 {
572 join => {
573 'cds' => {
574 'liner_notes' => 'author'
ea6309e2 575 }
bade79c4 576 }
577 }
578 );
ea6309e2 579
bade79c4 580 # Equivalent SQL:
581 # SELECT artist.* FROM artist
51458a6a 582 # LEFT JOIN cd ON artist.id = cd.artist
583 # LEFT JOIN liner_notes ON cd.id = liner_notes.cd
584 # LEFT JOIN author ON author.id = liner_notes.author
bade79c4 585 # WHERE liner_notes.notes LIKE '%some text%'
586 # AND author.name = 'A. Writer'
87980de7 587
51458a6a 588=head2 Multi-step and multiple joins
589
590With various combinations of array and hash references, you can join
591tables in any combination you desire. For example, to join Artist to
592CD and Concert, and join CD to LinerNotes:
593
594 # Relationships defined elsewhere:
595 # Artist->has_many('concerts' => 'Concert', 'artist');
596
597 my $rs = $schema->resultset('Artist')->search(
598 { },
599 {
600 join => [
601 {
602 cds => 'liner_notes'
603 },
604 'concerts'
605 ],
606 }
607 );
608
609 # Equivalent SQL:
610 # SELECT artist.* FROM artist
611 # LEFT JOIN cd ON artist.id = cd.artist
612 # LEFT JOIN liner_notes ON cd.id = liner_notes.cd
613 # LEFT JOIN concert ON artist.id = concert.artist
614
897342e4 615=head2 Multi-step prefetch
616
d76788de 617C<prefetch> can be nested more than one relationship
897342e4 618deep using the same syntax as a multi-step join:
619
620 my $rs = $schema->resultset('Tag')->search(
ac2803ef 621 {},
897342e4 622 {
623 prefetch => {
624 cd => 'artist'
625 }
626 }
627 );
628
629 # Equivalent SQL:
630 # SELECT tag.*, cd.*, artist.* FROM tag
51458a6a 631 # JOIN cd ON tag.cd = cd.id
632 # JOIN artist ON cd.artist = artist.id
897342e4 633
634Now accessing our C<cd> and C<artist> relationships does not need additional
635SQL statements:
636
637 my $tag = $rs->first;
638 print $tag->cd->artist->name;
639
d2f3e87b 640=head1 ROW-LEVEL OPERATIONS
641
642=head2 Retrieving a row object's Schema
643
644It is possible to get a Schema object from a row object like so:
645
646 my $schema = $cd->result_source->schema;
647 # use the schema as normal:
648 my $artist_rs = $schema->resultset('Artist');
649
650This can be useful when you don't want to pass around a Schema object to every
651method.
652
653=head2 Getting the value of the primary key for the last database insert
654
655AKA getting last_insert_id
656
d76788de 657Thanks to the core component PK::Auto, this is straightforward:
d2f3e87b 658
659 my $foo = $rs->create(\%blah);
660 # do more stuff
661 my $id = $foo->id; # foo->my_primary_key_field will also work.
662
663If you are not using autoincrementing primary keys, this will probably
664not work, but then you already know the value of the last primary key anyway.
665
666=head2 Stringification
667
668Employ the standard stringification technique by using the C<overload>
669module.
670
671To make an object stringify itself as a single column, use something
b24d86a1 672like this (replace C<name> with the column/method of your choice):
d2f3e87b 673
674 use overload '""' => sub { shift->name}, fallback => 1;
675
676For more complex stringification, you can use an anonymous subroutine:
677
678 use overload '""' => sub { $_[0]->name . ", " .
679 $_[0]->address }, fallback => 1;
680
681=head3 Stringification Example
682
683Suppose we have two tables: C<Product> and C<Category>. The table
684specifications are:
685
686 Product(id, Description, category)
687 Category(id, Description)
688
689C<category> is a foreign key into the Category table.
690
691If you have a Product object C<$obj> and write something like
692
693 print $obj->category
694
695things will not work as expected.
696
697To obtain, for example, the category description, you should add this
698method to the class defining the Category table:
699
700 use overload "" => sub {
701 my $self = shift;
702
703 return $self->Description;
704 }, fallback => 1;
705
706=head2 Want to know if find_or_create found or created a row?
707
708Just use C<find_or_new> instead, then check C<in_storage>:
709
710 my $obj = $rs->find_or_new({ blah => 'blarg' });
711 unless ($obj->in_storage) {
712 $obj->insert;
713 # do whatever else you wanted if it was a new row
714 }
715
716=head2 Dynamic Sub-classing DBIx::Class proxy classes
717
718AKA multi-class object inflation from one table
719
720L<DBIx::Class> classes are proxy classes, therefore some different
721techniques need to be employed for more than basic subclassing. In
722this example we have a single user table that carries a boolean bit
723for admin. We would like like to give the admin users
724objects(L<DBIx::Class::Row>) the same methods as a regular user but
725also special admin only methods. It doesn't make sense to create two
726seperate proxy-class files for this. We would be copying all the user
727methods into the Admin class. There is a cleaner way to accomplish
728this.
729
730Overriding the C<inflate_result> method within the User proxy-class
731gives us the effect we want. This method is called by
732L<DBIx::Class::ResultSet> when inflating a result from storage. So we
733grab the object being returned, inspect the values we are looking for,
734bless it if it's an admin object, and then return it. See the example
735below:
736
737B<Schema Definition>
738
23471103 739 package My::Schema;
d2f3e87b 740
741 use base qw/DBIx::Class::Schema/;
742
23471103 743 __PACKAGE__->load_namespaces;
d2f3e87b 744
745
746B<Proxy-Class definitions>
747
23471103 748 package My::Schema::Result::User;
d2f3e87b 749
750 use strict;
751 use warnings;
752 use base qw/DBIx::Class/;
753
754 ### Defined what our admin class is for ensure_class_loaded
755 my $admin_class = __PACKAGE__ . '::Admin';
756
757 __PACKAGE__->load_components(qw/Core/);
758
759 __PACKAGE__->table('users');
760
761 __PACKAGE__->add_columns(qw/user_id email password
762 firstname lastname active
763 admin/);
764
765 __PACKAGE__->set_primary_key('user_id');
766
767 sub inflate_result {
768 my $self = shift;
769 my $ret = $self->next::method(@_);
770 if( $ret->admin ) {### If this is an admin rebless for extra functions
771 $self->ensure_class_loaded( $admin_class );
772 bless $ret, $admin_class;
773 }
774 return $ret;
775 }
776
777 sub hello {
778 print "I am a regular user.\n";
779 return ;
780 }
781
782
23471103 783 package My::Schema::Result::User::Admin;
d2f3e87b 784
785 use strict;
786 use warnings;
23471103 787 use base qw/My::Schema::Result::User/;
d2f3e87b 788
789 sub hello
790 {
791 print "I am an admin.\n";
792 return;
793 }
794
795 sub do_admin_stuff
796 {
797 print "I am doing admin stuff\n";
798 return ;
799 }
800
801B<Test File> test.pl
802
803 use warnings;
804 use strict;
23471103 805 use My::Schema;
d2f3e87b 806
807 my $user_data = { email => 'someguy@place.com',
808 password => 'pass1',
809 admin => 0 };
810
811 my $admin_data = { email => 'someadmin@adminplace.com',
812 password => 'pass2',
813 admin => 1 };
814
23471103 815 my $schema = My::Schema->connection('dbi:Pg:dbname=test');
d2f3e87b 816
817 $schema->resultset('User')->create( $user_data );
818 $schema->resultset('User')->create( $admin_data );
819
820 ### Now we search for them
821 my $user = $schema->resultset('User')->single( $user_data );
822 my $admin = $schema->resultset('User')->single( $admin_data );
823
824 print ref $user, "\n";
825 print ref $admin, "\n";
826
827 print $user->password , "\n"; # pass1
828 print $admin->password , "\n";# pass2; inherited from User
829 print $user->hello , "\n";# I am a regular user.
830 print $admin->hello, "\n";# I am an admin.
831
832 ### The statement below will NOT print
833 print "I can do admin stuff\n" if $user->can('do_admin_stuff');
834 ### The statement below will print
835 print "I can do admin stuff\n" if $admin->can('do_admin_stuff');
836
a5b29361 837=head2 Skip row object creation for faster results
d2f3e87b 838
839DBIx::Class is not built for speed, it's built for convenience and
840ease of use, but sometimes you just need to get the data, and skip the
841fancy objects.
842
843To do this simply use L<DBIx::Class::ResultClass::HashRefInflator>.
844
845 my $rs = $schema->resultset('CD');
846
847 $rs->result_class('DBIx::Class::ResultClass::HashRefInflator');
848
849 my $hash_ref = $rs->find(1);
a5b29361 850
d2f3e87b 851Wasn't that easy?
bc96f260 852
db2b2eb6 853Beware, changing the Result class using
854L<DBIx::Class::ResultSet/result_class> will replace any existing class
855completely including any special components loaded using
856load_components, eg L<DBIx::Class::InflateColumn::DateTime>.
857
d2f3e87b 858=head2 Get raw data for blindingly fast results
859
860If the L<HashRefInflator|DBIx::Class::ResultClass::HashRefInflator> solution
861above is not fast enough for you, you can use a DBIx::Class to return values
db2b2eb6 862exactly as they come out of the database with none of the convenience methods
d2f3e87b 863wrapped round them.
864
2d7d8459 865This is used like so:
d2f3e87b 866
867 my $cursor = $rs->cursor
868 while (my @vals = $cursor->next) {
869 # use $val[0..n] here
870 }
871
872You will need to map the array offsets to particular columns (you can
db2b2eb6 873use the L<DBIx::Class::ResultSet/select> attribute of L<DBIx::Class::ResultSet/search> to force ordering).
d2f3e87b 874
875=head1 RESULTSET OPERATIONS
876
877=head2 Getting Schema from a ResultSet
878
db2b2eb6 879To get the L<DBIx::Class::Schema> object from a ResultSet, do the following:
d2f3e87b 880
881 $rs->result_source->schema
882
883=head2 Getting Columns Of Data
884
885AKA Aggregating Data
ac2803ef 886
887If you want to find the sum of a particular column there are several
888ways, the obvious one is to use search:
889
890 my $rs = $schema->resultset('Items')->search(
891 {},
892 {
893 select => [ { sum => 'Cost' } ],
d676881f 894 as => [ 'total_cost' ], # remember this 'as' is for DBIx::Class::ResultSet not SQL
ac2803ef 895 }
896 );
897 my $tc = $rs->first->get_column('total_cost');
898
899Or, you can use the L<DBIx::Class::ResultSetColumn>, which gets
900returned when you ask the C<ResultSet> for a column using
901C<get_column>:
902
903 my $cost = $schema->resultset('Items')->get_column('Cost');
904 my $tc = $cost->sum;
905
906With this you can also do:
907
908 my $minvalue = $cost->min;
909 my $maxvalue = $cost->max;
910
911Or just iterate through the values of this column only:
912
913 while ( my $c = $cost->next ) {
914 print $c;
915 }
916
917 foreach my $c ($cost->all) {
918 print $c;
919 }
920
709353af 921C<ResultSetColumn> only has a limited number of built-in functions, if
922you need one that it doesn't have, then you can use the C<func> method
923instead:
924
925 my $avg = $cost->func('AVERAGE');
926
927This will cause the following SQL statement to be run:
928
929 SELECT AVERAGE(Cost) FROM Items me
930
931Which will of course only work if your database supports this function.
ac2803ef 932See L<DBIx::Class::ResultSetColumn> for more documentation.
933
204e5c03 934=head2 Creating a result set from a set of rows
935
936Sometimes you have a (set of) row objects that you want to put into a
937resultset without the need to hit the DB again. You can do that by using the
938L<set_cache|DBIx::Class::Resultset/set_cache> method:
939
2d7a4e46 940 my @uploadable_groups;
204e5c03 941 while (my $group = $groups->next) {
942 if ($group->can_upload($self)) {
943 push @uploadable_groups, $group;
944 }
945 }
946 my $new_rs = $self->result_source->resultset;
947 $new_rs->set_cache(\@uploadable_groups);
948 return $new_rs;
949
950
d2f3e87b 951=head1 USING RELATIONSHIPS
acee4e4d 952
d2f3e87b 953=head2 Create a new row in a related table
acee4e4d 954
6f1434fd 955 my $author = $book->create_related('author', { name => 'Fred'});
acee4e4d 956
d2f3e87b 957=head2 Search in a related table
acee4e4d 958
959Only searches for books named 'Titanic' by the author in $author.
960
6f1434fd 961 my $books_rs = $author->search_related('books', { name => 'Titanic' });
acee4e4d 962
d2f3e87b 963=head2 Delete data in a related table
acee4e4d 964
965Deletes only the book named Titanic by the author in $author.
966
6f1434fd 967 $author->delete_related('books', { name => 'Titanic' });
acee4e4d 968
d2f3e87b 969=head2 Ordering a relationship result set
f8bad769 970
971If you always want a relation to be ordered, you can specify this when you
972create the relationship.
973
6f1434fd 974To order C<< $book->pages >> by descending page_number, create the relation
975as follows:
f8bad769 976
6f1434fd 977 __PACKAGE__->has_many('pages' => 'Page', 'book', { order_by => \'page_number DESC'} );
f8bad769 978
7c0825ab 979=head2 Filtering a relationship result set
980
981If you want to get a filtered result set, you can just add add to $attr as follows:
982
983 __PACKAGE__->has_many('pages' => 'Page', 'book', { where => { scrap => 0 } } );
984
d2f3e87b 985=head2 Many-to-many relationships
f8bad769 986
d2f3e87b 987This is straightforward using L<ManyToMany|DBIx::Class::Relationship/many_to_many>:
f8bad769 988
d2f3e87b 989 package My::User;
6f1434fd 990 use base 'DBIx::Class';
991 __PACKAGE__->load_components('Core');
d2f3e87b 992 __PACKAGE__->table('user');
993 __PACKAGE__->add_columns(qw/id name/);
994 __PACKAGE__->set_primary_key('id');
995 __PACKAGE__->has_many('user_address' => 'My::UserAddress', 'user');
996 __PACKAGE__->many_to_many('addresses' => 'user_address', 'address');
87980de7 997
d2f3e87b 998 package My::UserAddress;
6f1434fd 999 use base 'DBIx::Class';
1000 __PACKAGE__->load_components('Core');
d2f3e87b 1001 __PACKAGE__->table('user_address');
1002 __PACKAGE__->add_columns(qw/user address/);
1003 __PACKAGE__->set_primary_key(qw/user address/);
1004 __PACKAGE__->belongs_to('user' => 'My::User');
1005 __PACKAGE__->belongs_to('address' => 'My::Address');
181a28f4 1006
d2f3e87b 1007 package My::Address;
6f1434fd 1008 use base 'DBIx::Class';
1009 __PACKAGE__->load_components('Core');
d2f3e87b 1010 __PACKAGE__->table('address');
1011 __PACKAGE__->add_columns(qw/id street town area_code country/);
1012 __PACKAGE__->set_primary_key('id');
1013 __PACKAGE__->has_many('user_address' => 'My::UserAddress', 'address');
1014 __PACKAGE__->many_to_many('users' => 'user_address', 'user');
1015
1016 $rs = $user->addresses(); # get all addresses for a user
1017 $rs = $address->users(); # get all users for an address
1018
db2b2eb6 1019=head2 Relationships across DB schemas
1020
1021Mapping relationships across L<DB schemas|DBIx::Class::Manual::Glossary/DB schema>
1022is easy as long as the schemas themselves are all accessible via the same DBI
1023connection. In most cases, this means that they are on the same database host
1024as each other and your connecting database user has the proper permissions to them.
1025
1026To accomplish this one only needs to specify the DB schema name in the table
1027declaration, like so...
1028
1029 package MyDatabase::Main::Artist;
1030 use base qw/DBIx::Class/;
1031 __PACKAGE__->load_components(qw/PK::Auto Core/);
1032
1033 __PACKAGE__->table('database1.artist'); # will use "database1.artist" in FROM clause
1034
1035 __PACKAGE__->add_columns(qw/ artistid name /);
1036 __PACKAGE__->set_primary_key('artistid');
1037 __PACKAGE__->has_many('cds' => 'MyDatabase::Main::Cd');
1038
1039 1;
1040
1041Whatever string you specify there will be used to build the "FROM" clause in SQL
1042queries.
1043
1044The big drawback to this is you now have DB schema names hardcoded in your
1045class files. This becomes especially troublesome if you have multiple instances
1046of your application to support a change lifecycle (e.g. DEV, TEST, PROD) and
1047the DB schemas are named based on the environment (e.g. database1_dev).
1048
1049However, one can dynamically "map" to the proper DB schema by overriding the
1050L<connection|DBIx::Class::Schama/connection> method in your Schema class and
1051building a renaming facility, like so:
1052
1053 package MyDatabase::Schema;
1054 use Moose;
1055
1056 extends 'DBIx::Class::Schema';
1057
1058 around connection => sub {
1059 my ( $inner, $self, $dsn, $username, $pass, $attr ) = ( shift, @_ );
1060
1061 my $postfix = delete $attr->{schema_name_postfix};
1062
1063 $inner->(@_);
1064
1065 if ( $postfix ) {
1066 $self->append_db_name($postfix);
1067 }
1068 };
1069
1070 sub append_db_name {
1071 my ( $self, $postfix ) = @_;
1072
1073 my @sources_with_db
1074 = grep
1075 { $_->name =~ /^\w+\./mx }
1076 map
1077 { $self->source($_) }
1078 $self->sources;
1079
1080 foreach my $source (@sources_with_db) {
1081 my $name = $source->name;
1082 $name =~ s{^(\w+)\.}{${1}${postfix}\.}mx;
1083
1084 $source->name($name);
1085 }
1086 }
1087
1088 1;
1089
1090By overridding the L<connection|DBIx::Class::Schama/connection>
1091method and extracting a custom option from the provided \%attr hashref one can
1092then simply iterate over all the Schema's ResultSources, renaming them as
1093needed.
1094
1095To use this facility, simply add or modify the \%attr hashref that is passed to
1096L<connection|DBIx::Class::Schama/connect>, as follows:
1097
1098 my $schema
1099 = MyDatabase::Schema->connect(
1100 $dsn,
1101 $user,
1102 $pass,
1103 {
1104 schema_name_postfix => '_dev'
1105 # ... Other options as desired ...
1106 })
1107
1108Obviously, one could accomplish even more advanced mapping via a hash map or a
1109callback routine.
1110
d2f3e87b 1111=head1 TRANSACTIONS
1112
1113As of version 0.04001, there is improved transaction support in
1114L<DBIx::Class::Storage> and L<DBIx::Class::Schema>. Here is an
1115example of the recommended way to use it:
1116
1117 my $genus = $schema->resultset('Genus')->find(12);
1118
1119 my $coderef2 = sub {
1120 $genus->extinct(1);
1121 $genus->update;
1122 };
70634260 1123
181a28f4 1124 my $coderef1 = sub {
35d4fe78 1125 $genus->add_to_species({ name => 'troglodyte' });
1126 $genus->wings(2);
1127 $genus->update;
6f1434fd 1128 $schema->txn_do($coderef2); # Can have a nested transaction. Only the outer will actualy commit
181a28f4 1129 return $genus->species;
1130 };
1131
181a28f4 1132 my $rs;
1133 eval {
70634260 1134 $rs = $schema->txn_do($coderef1);
181a28f4 1135 };
1136
1137 if ($@) { # Transaction failed
1138 die "the sky is falling!" #
1139 if ($@ =~ /Rollback failed/); # Rollback failed
1140
1141 deal_with_failed_transaction();
35d4fe78 1142 }
87980de7 1143
181a28f4 1144Nested transactions will work as expected. That is, only the outermost
1145transaction will actually issue a commit to the $dbh, and a rollback
1146at any level of any transaction will cause the entire nested
1147transaction to fail. Support for savepoints and for true nested
40dbc108 1148transactions (for databases that support them) will hopefully be added
1149in the future.
ee38fa40 1150
d2f3e87b 1151=head1 SQL
ee38fa40 1152
d2f3e87b 1153=head2 Creating Schemas From An Existing Database
ea6309e2 1154
d2f3e87b 1155L<DBIx::Class::Schema::Loader> will connect to a database and create a
1156L<DBIx::Class::Schema> and associated sources by examining the database.
bade79c4 1157
d2f3e87b 1158The recommend way of achieving this is to use the
1159L<make_schema_at|DBIx::Class::Schema::Loader/make_schema_at> method:
bade79c4 1160
6f1434fd 1161 perl -MDBIx::Class::Schema::Loader=make_schema_at,dump_to_dir:./lib \
1162 -e 'make_schema_at("My::Schema", { debug => 1 }, [ "dbi:Pg:dbname=foo","postgres" ])'
362500af 1163
d2f3e87b 1164This will create a tree of files rooted at C<./lib/My/Schema/> containing
1165source definitions for all the tables found in the C<foo> database.
362500af 1166
d2f3e87b 1167=head2 Creating DDL SQL
362500af 1168
264f1571 1169The following functionality requires you to have L<SQL::Translator>
1170(also known as "SQL Fairy") installed.
362500af 1171
264f1571 1172To create a set of database-specific .sql files for the above schema:
362500af 1173
264f1571 1174 my $schema = My::Schema->connect($dsn);
1175 $schema->create_ddl_dir(['MySQL', 'SQLite', 'PostgreSQL'],
1176 '0.1',
d2f3e87b 1177 './dbscriptdir/'
264f1571 1178 );
1179
1180By default this will create schema files in the current directory, for
1181MySQL, SQLite and PostgreSQL, using the $VERSION from your Schema.pm.
1182
1183To create a new database using the schema:
1184
1185 my $schema = My::Schema->connect($dsn);
1186 $schema->deploy({ add_drop_tables => 1});
1187
1188To import created .sql files using the mysql client:
1189
1190 mysql -h "host" -D "database" -u "user" -p < My_Schema_1.0_MySQL.sql
1191
1192To create C<ALTER TABLE> conversion scripts to update a database to a
1193newer version of your schema at a later point, first set a new
d2f3e87b 1194C<$VERSION> in your Schema file, then:
264f1571 1195
1196 my $schema = My::Schema->connect($dsn);
1197 $schema->create_ddl_dir(['MySQL', 'SQLite', 'PostgreSQL'],
1198 '0.2',
1199 '/dbscriptdir/',
1200 '0.1'
1201 );
1202
1203This will produce new database-specific .sql files for the new version
1204of the schema, plus scripts to convert from version 0.1 to 0.2. This
1205requires that the files for 0.1 as created above are available in the
1206given directory to diff against.
362500af 1207
6f1434fd 1208=head2 Select from dual
16cd5b28 1209
1210Dummy tables are needed by some databases to allow calling functions
1211or expressions that aren't based on table content, for examples of how
1212this applies to various database types, see:
1213L<http://troels.arvin.dk/db/rdbms/#other-dummy_table>.
1214
1215Note: If you're using Oracles dual table don't B<ever> do anything
1216other than a select, if you CRUD on your dual table you *will* break
1217your database.
1218
1219Make a table class as you would for any other table
1220
1221 package MyAppDB::Dual;
1222 use strict;
1223 use warnings;
1224 use base 'DBIx::Class';
1225 __PACKAGE__->load_components("Core");
1226 __PACKAGE__->table("Dual");
1227 __PACKAGE__->add_columns(
1228 "dummy",
1229 { data_type => "VARCHAR2", is_nullable => 0, size => 1 },
1230 );
1231
1232Once you've loaded your table class select from it using C<select>
1233and C<as> instead of C<columns>
1234
1235 my $rs = $schema->resultset('Dual')->search(undef,
1236 { select => [ 'sydate' ],
1237 as => [ 'now' ]
1238 },
1239 );
1240
1241All you have to do now is be careful how you access your resultset, the below
1242will not work because there is no column called 'now' in the Dual table class
1243
1244 while (my $dual = $rs->next) {
1245 print $dual->now."\n";
1246 }
6f1434fd 1247 # Can't locate object method "now" via package "MyAppDB::Dual" at headshot.pl line 23.
16cd5b28 1248
1249You could of course use 'dummy' in C<as> instead of 'now', or C<add_columns> to
1250your Dual class for whatever you wanted to select from dual, but that's just
1251silly, instead use C<get_column>
1252
1253 while (my $dual = $rs->next) {
1254 print $dual->get_column('now')."\n";
1255 }
1256
1257Or use C<cursor>
1258
1259 my $cursor = $rs->cursor;
1260 while (my @vals = $cursor->next) {
1261 print $vals[0]."\n";
1262 }
336256bc 1263
1264In case you're going to use this "trick" together with L<DBIx::Class::Schema/deploy> or
1265L<DBIx::Class::Schema/create_ddl_dir> a table called "dual" will be created in your
1266current schema. This would overlap "sys.dual" and you could not fetch "sysdate" or
1267"sequence.nextval" anymore from dual. To avoid this problem, just tell
1268L<SQL::Translator> to not create table dual:
1269
1270 my $sqlt_args = {
1271 add_drop_table => 1,
1272 parser_args => { sources => [ grep $_ ne 'Dual', schema->sources ] },
1273 };
1274 $schema->create_ddl_dir( [qw/Oracle/], undef, './sql', undef, $sqlt_args );
16cd5b28 1275
1276Or use L<DBIx::Class::ResultClass::HashRefInflator>
1277
1278 $rs->result_class('DBIx::Class::ResultClass::HashRefInflator');
1279 while ( my $dual = $rs->next ) {
1280 print $dual->{now}."\n";
1281 }
1282
1283Here are some example C<select> conditions to illustrate the different syntax
1284you could use for doing stuff like
1285C<oracles.heavily(nested(functions_can('take', 'lots'), OF), 'args')>
1286
1287 # get a sequence value
1288 select => [ 'A_SEQ.nextval' ],
1289
1290 # get create table sql
1291 select => [ { 'dbms_metadata.get_ddl' => [ "'TABLE'", "'ARTIST'" ]} ],
1292
1293 # get a random num between 0 and 100
1294 select => [ { "trunc" => [ { "dbms_random.value" => [0,100] } ]} ],
1295
1296 # what year is it?
1297 select => [ { 'extract' => [ \'year from sysdate' ] } ],
1298
1299 # do some math
1300 select => [ {'round' => [{'cos' => [ \'180 * 3.14159265359/180' ]}]}],
1301
1302 # which day of the week were you born on?
6f1434fd 1303 select => [{'to_char' => [{'to_date' => [ "'25-DEC-1980'", "'dd-mon-yyyy'" ]}, "'day'"]}],
16cd5b28 1304
1305 # select 16 rows from dual
1306 select => [ "'hello'" ],
1307 as => [ 'world' ],
1308 group_by => [ 'cube( 1, 2, 3, 4 )' ],
1309
1310
1311
d2f3e87b 1312=head2 Adding Indexes And Functions To Your SQL
362500af 1313
d2f3e87b 1314Often you will want indexes on columns on your table to speed up searching. To
1315do this, create a method called C<sqlt_deploy_hook> in the relevant source
2d7d8459 1316class (refer to the advanced
1317L<callback system|DBIx::Class::ResultSource/sqlt_deploy_callback> if you wish
1318to share a hook between multiple sources):
b0a20454 1319
23471103 1320 package My::Schema::Result::Artist;
b0a20454 1321
d2f3e87b 1322 __PACKAGE__->table('artist');
1323 __PACKAGE__->add_columns(id => { ... }, name => { ... })
b0a20454 1324
d2f3e87b 1325 sub sqlt_deploy_hook {
1326 my ($self, $sqlt_table) = @_;
1327
1328 $sqlt_table->add_index(name => 'idx_name', fields => ['name']);
1329 }
1330
1331 1;
1332
1333Sometimes you might want to change the index depending on the type of the
1334database for which SQL is being generated:
1335
1336 my ($db_type = $sqlt_table->schema->translator->producer_type)
1337 =~ s/^SQL::Translator::Producer:://;
1338
1339You can also add hooks to the schema level to stop certain tables being
1340created:
1341
1342 package My::Schema;
1343
1344 ...
1345
1346 sub sqlt_deploy_hook {
1347 my ($self, $sqlt_schema) = @_;
1348
1349 $sqlt_schema->drop_table('table_name');
1350 }
1351
2d7d8459 1352You could also add views, procedures or triggers to the output using
1353L<SQL::Translator::Schema/add_view>,
1354L<SQL::Translator::Schema/add_procedure> or
1355L<SQL::Translator::Schema/add_trigger>.
1356
b0a20454 1357
362500af 1358=head2 Schema versioning
1359
1360The following example shows simplistically how you might use DBIx::Class to
1361deploy versioned schemas to your customers. The basic process is as follows:
1362
da4779ad 1363=over 4
1364
1365=item 1.
1366
1367Create a DBIx::Class schema
1368
1369=item 2.
1370
1371Save the schema
1372
1373=item 3.
1374
1375Deploy to customers
1376
1377=item 4.
1378
1379Modify schema to change functionality
1380
1381=item 5.
1382
1383Deploy update to customers
1384
1385=back
362500af 1386
d2f3e87b 1387B<Create a DBIx::Class schema>
362500af 1388
1389This can either be done manually, or generated from an existing database as
d2f3e87b 1390described under L</Creating Schemas From An Existing Database>
362500af 1391
d2f3e87b 1392B<Save the schema>
362500af 1393
d2f3e87b 1394Call L<DBIx::Class::Schema/create_ddl_dir> as above under L</Creating DDL SQL>.
362500af 1395
d2f3e87b 1396B<Deploy to customers>
362500af 1397
1398There are several ways you could deploy your schema. These are probably
1399beyond the scope of this recipe, but might include:
1400
da4779ad 1401=over 4
1402
1403=item 1.
1404
1405Require customer to apply manually using their RDBMS.
1406
1407=item 2.
1408
1409Package along with your app, making database dump/schema update/tests
362500af 1410all part of your install.
1411
da4779ad 1412=back
1413
d2f3e87b 1414B<Modify the schema to change functionality>
362500af 1415
264f1571 1416As your application evolves, it may be necessary to modify your schema
1417to change functionality. Once the changes are made to your schema in
1418DBIx::Class, export the modified schema and the conversion scripts as
d2f3e87b 1419in L</Creating DDL SQL>.
362500af 1420
d2f3e87b 1421B<Deploy update to customers>
362500af 1422
264f1571 1423Add the L<DBIx::Class::Schema::Versioned> schema component to your
1424Schema class. This will add a new table to your database called
ecea7937 1425C<dbix_class_schema_vesion> which will keep track of which version is installed
264f1571 1426and warn if the user trys to run a newer schema version than the
1427database thinks it has.
1428
1429Alternatively, you can send the conversion sql scripts to your
1430customers as above.
362500af 1431
d2f3e87b 1432=head2 Setting quoting for the generated SQL.
1433
1434If the database contains column names with spaces and/or reserved words, they
1435need to be quoted in the SQL queries. This is done using:
1436
1437 __PACKAGE__->storage->sql_maker->quote_char([ qw/[ ]/] );
1438 __PACKAGE__->storage->sql_maker->name_sep('.');
1439
1440The first sets the quote characters. Either a pair of matching
1441brackets, or a C<"> or C<'>:
1442
1443 __PACKAGE__->storage->sql_maker->quote_char('"');
1444
1445Check the documentation of your database for the correct quote
1446characters to use. C<name_sep> needs to be set to allow the SQL
1447generator to put the quotes the correct place.
1448
1449In most cases you should set these as part of the arguments passed to
d68b0c69 1450L<DBIx::Class::Schema/connect>:
d2f3e87b 1451
1452 my $schema = My::Schema->connect(
1453 'dbi:mysql:my_db',
1454 'db_user',
1455 'db_password',
1456 {
1457 quote_char => '"',
1458 name_sep => '.'
1459 }
1460 )
1461
7be93b07 1462=head2 Setting limit dialect for SQL::Abstract::Limit
1463
324572ca 1464In some cases, SQL::Abstract::Limit cannot determine the dialect of
1465the remote SQL server by looking at the database handle. This is a
1466common problem when using the DBD::JDBC, since the DBD-driver only
1467know that in has a Java-driver available, not which JDBC driver the
1468Java component has loaded. This specifically sets the limit_dialect
1469to Microsoft SQL-server (See more names in SQL::Abstract::Limit
1470-documentation.
7be93b07 1471
1472 __PACKAGE__->storage->sql_maker->limit_dialect('mssql');
1473
324572ca 1474The JDBC bridge is one way of getting access to a MSSQL server from a platform
7be93b07 1475that Microsoft doesn't deliver native client libraries for. (e.g. Linux)
1476
d2f3e87b 1477The limit dialect can also be set at connect time by specifying a
1478C<limit_dialect> key in the final hash as shown above.
2437a1e3 1479
05697a49 1480=head2 Working with PostgreSQL array types
1481
20ea616f 1482You can also assign values to PostgreSQL array columns by passing array
1483references in the C<\%columns> (C<\%vals>) hashref of the
1484L<DBIx::Class::ResultSet/create> and L<DBIx::Class::Row/update> family of
1485methods:
05697a49 1486
1487 $resultset->create({
1488 numbers => [1, 2, 3]
1489 });
1490
1491 $row->update(
1492 {
1493 numbers => [1, 2, 3]
1494 },
1495 {
1496 day => '2008-11-24'
1497 }
1498 );
1499
1500In conditions (eg. C<\%cond> in the L<DBIx::Class::ResultSet/search> family of
1501methods) you cannot directly use array references (since this is interpreted as
1502a list of values to be C<OR>ed), but you can use the following syntax to force
1503passing them as bind values:
1504
1505 $resultset->search(
1506 {
31eb3263 1507 numbers => \[ '= ?', [numbers => [1, 2, 3]] ]
05697a49 1508 }
1509 );
1510
1511See L<SQL::Abstract/array_datatypes> and L<SQL::Abstract/Literal SQL with
31eb3263 1512placeholders and bind values (subqueries)> for more explanation. Note that
1513L<DBIx::Class> sets L<SQL::Abstract/bindtype> to C<columns>, so you must pass
1514the bind values (the C<[1, 2, 3]> arrayref in the above example) wrapped in
1515arrayrefs together with the column name, like this: C<< [column_name => value]
1516>>.
05697a49 1517
d2f3e87b 1518=head1 BOOTSTRAPPING/MIGRATING
2437a1e3 1519
d2f3e87b 1520=head2 Easy migration from class-based to schema-based setup
2437a1e3 1521
d2f3e87b 1522You want to start using the schema-based approach to L<DBIx::Class>
1523(see L<SchemaIntro.pod>), but have an established class-based setup with lots
1524of existing classes that you don't want to move by hand. Try this nifty script
1525instead:
1526
1527 use MyDB;
1528 use SQL::Translator;
1529
1530 my $schema = MyDB->schema_instance;
2437a1e3 1531
d2f3e87b 1532 my $translator = SQL::Translator->new(
1533 debug => $debug || 0,
1534 trace => $trace || 0,
1535 no_comments => $no_comments || 0,
1536 show_warnings => $show_warnings || 0,
1537 add_drop_table => $add_drop_table || 0,
1538 validate => $validate || 0,
1539 parser_args => {
1540 'DBIx::Schema' => $schema,
1541 },
1542 producer_args => {
1543 'prefix' => 'My::Schema',
1544 },
1545 );
1546
1547 $translator->parser('SQL::Translator::Parser::DBIx::Class');
1548 $translator->producer('SQL::Translator::Producer::DBIx::Class::File');
1549
1550 my $output = $translator->translate(@args) or die
1551 "Error: " . $translator->error;
1552
1553 print $output;
2437a1e3 1554
d2f3e87b 1555You could use L<Module::Find> to search for all subclasses in the MyDB::*
1556namespace, which is currently left as an exercise for the reader.
2437a1e3 1557
d2f3e87b 1558=head1 OVERLOADING METHODS
086b93a2 1559
ab872312 1560L<DBIx::Class> uses the L<Class::C3> package, which provides for redispatch of
1561method calls, useful for things like default values and triggers. You have to
1562use calls to C<next::method> to overload methods. More information on using
1563L<Class::C3> with L<DBIx::Class> can be found in
086b93a2 1564L<DBIx::Class::Manual::Component>.
1565
d2f3e87b 1566=head2 Setting default values for a row
1567
1568It's as simple as overriding the C<new> method. Note the use of
1569C<next::method>.
1570
1571 sub new {
1572 my ( $class, $attrs ) = @_;
1573
1574 $attrs->{foo} = 'bar' unless defined $attrs->{foo};
1575
1576 my $new = $class->next::method($attrs);
1577
1578 return $new;
1579 }
1580
1581For more information about C<next::method>, look in the L<Class::C3>
1582documentation. See also L<DBIx::Class::Manual::Component> for more
1583ways to write your own base classes to do this.
1584
1585People looking for ways to do "triggers" with DBIx::Class are probably
1586just looking for this.
1587
1588=head2 Changing one field whenever another changes
086b93a2 1589
1590For example, say that you have three columns, C<id>, C<number>, and
1591C<squared>. You would like to make changes to C<number> and have
1592C<squared> be automagically set to the value of C<number> squared.
1593You can accomplish this by overriding C<store_column>:
1594
1595 sub store_column {
1596 my ( $self, $name, $value ) = @_;
1597 if ($name eq 'number') {
1598 $self->squared($value * $value);
1599 }
1600 $self->next::method($name, $value);
1601 }
1602
1603Note that the hard work is done by the call to C<next::method>, which
324572ca 1604redispatches your call to store_column in the superclass(es).
086b93a2 1605
d2f3e87b 1606=head2 Automatically creating related objects
086b93a2 1607
324572ca 1608You might have a class C<Artist> which has many C<CD>s. Further, if you
086b93a2 1609want to create a C<CD> object every time you insert an C<Artist> object.
ccbebdbc 1610You can accomplish this by overriding C<insert> on your objects:
086b93a2 1611
1612 sub insert {
ccbebdbc 1613 my ( $self, @args ) = @_;
1614 $self->next::method(@args);
086b93a2 1615 $self->cds->new({})->fill_from_artist($self)->insert;
1616 return $self;
1617 }
1618
1619where C<fill_from_artist> is a method you specify in C<CD> which sets
1620values in C<CD> based on the data in the C<Artist> object you pass in.
1621
d2f3e87b 1622=head2 Wrapping/overloading a column accessor
1623
1624B<Problem:>
1625
1626Say you have a table "Camera" and want to associate a description
1627with each camera. For most cameras, you'll be able to generate the description from
1628the other columns. However, in a few special cases you may want to associate a
1629custom description with a camera.
1630
1631B<Solution:>
1632
1633In your database schema, define a description field in the "Camera" table that
1634can contain text and null values.
1635
1636In DBIC, we'll overload the column accessor to provide a sane default if no
1637custom description is defined. The accessor will either return or generate the
1638description, depending on whether the field is null or not.
1639
1640First, in your "Camera" schema class, define the description field as follows:
1641
1642 __PACKAGE__->add_columns(description => { accessor => '_description' });
1643
1644Next, we'll define the accessor-wrapper subroutine:
1645
1646 sub description {
1647 my $self = shift;
1648
1649 # If there is an update to the column, we'll let the original accessor
1650 # deal with it.
1651 return $self->_description(@_) if @_;
1652
1653 # Fetch the column value.
1654 my $description = $self->_description;
1655
1656 # If there's something in the description field, then just return that.
1657 return $description if defined $description && length $descripton;
1658
1659 # Otherwise, generate a description.
1660 return $self->generate_description;
1661 }
1662
1663=head1 DEBUGGING AND PROFILING
1664
1665=head2 DBIx::Class objects with Data::Dumper
1def3451 1666
1667L<Data::Dumper> can be a very useful tool for debugging, but sometimes it can
1668be hard to find the pertinent data in all the data it can generate.
1669Specifically, if one naively tries to use it like so,
1670
1671 use Data::Dumper;
1672
1673 my $cd = $schema->resultset('CD')->find(1);
1674 print Dumper($cd);
1675
1676several pages worth of data from the CD object's schema and result source will
1677be dumped to the screen. Since usually one is only interested in a few column
1678values of the object, this is not very helpful.
1679
1680Luckily, it is possible to modify the data before L<Data::Dumper> outputs
1681it. Simply define a hook that L<Data::Dumper> will call on the object before
1682dumping it. For example,
1683
1684 package My::DB::CD;
1685
1686 sub _dumper_hook {
99fb1058 1687 $_[0] = bless {
1688 %{ $_[0] },
1def3451 1689 result_source => undef,
99fb1058 1690 }, ref($_[0]);
1def3451 1691 }
1692
1693 [...]
1694
1695 use Data::Dumper;
1696
22139027 1697 local $Data::Dumper::Freezer = '_dumper_hook';
1def3451 1698
1699 my $cd = $schema->resultset('CD')->find(1);
1700 print Dumper($cd);
1701 # dumps $cd without its ResultSource
1702
1703If the structure of your schema is such that there is a common base class for
1704all your table classes, simply put a method similar to C<_dumper_hook> in the
1705base class and set C<$Data::Dumper::Freezer> to its name and L<Data::Dumper>
1706will automagically clean up your data before printing it. See
1707L<Data::Dumper/EXAMPLES> for more information.
1708
4c248161 1709=head2 Profiling
1710
85f78622 1711When you enable L<DBIx::Class::Storage>'s debugging it prints the SQL
4c248161 1712executed as well as notifications of query completion and transaction
1713begin/commit. If you'd like to profile the SQL you can subclass the
1714L<DBIx::Class::Storage::Statistics> class and write your own profiling
1715mechanism:
1716
1717 package My::Profiler;
1718 use strict;
1719
1720 use base 'DBIx::Class::Storage::Statistics';
1721
1722 use Time::HiRes qw(time);
1723
1724 my $start;
1725
1726 sub query_start {
1727 my $self = shift();
1728 my $sql = shift();
1729 my $params = @_;
1730
70f39278 1731 $self->print("Executing $sql: ".join(', ', @params)."\n");
4c248161 1732 $start = time();
1733 }
1734
1735 sub query_end {
1736 my $self = shift();
1737 my $sql = shift();
1738 my @params = @_;
1739
70f39278 1740 my $elapsed = sprintf("%0.4f", time() - $start);
1741 $self->print("Execution took $elapsed seconds.\n");
4c248161 1742 $start = undef;
1743 }
1744
1745 1;
1746
1747You can then install that class as the debugging object:
1748
70f39278 1749 __PACKAGE__->storage->debugobj(new My::Profiler());
1750 __PACKAGE__->storage->debug(1);
4c248161 1751
1752A more complicated example might involve storing each execution of SQL in an
1753array:
1754
1755 sub query_end {
1756 my $self = shift();
1757 my $sql = shift();
1758 my @params = @_;
1759
1760 my $elapsed = time() - $start;
1761 push(@{ $calls{$sql} }, {
1762 params => \@params,
1763 elapsed => $elapsed
1764 });
1765 }
1766
1767You could then create average, high and low execution times for an SQL
1768statement and dig down to see if certain parameters cause aberrant behavior.
70f39278 1769You might want to check out L<DBIx::Class::QueryLog> as well.
4c248161 1770
bc96f260 1771=head1 STARTUP SPEED
1772
1773L<DBIx::Class|DBIx::Class> programs can have a significant startup delay
1774as the ORM loads all the relevant classes. This section examines
1775techniques for reducing the startup delay.
1776
1777These tips are are listed in order of decreasing effectiveness - so the
1778first tip, if applicable, should have the greatest effect on your
1779application.
1780
1781=head2 Statically Define Your Schema
1782
1783If you are using
1784L<DBIx::Class::Schema::Loader|DBIx::Class::Schema::Loader> to build the
1785classes dynamically based on the database schema then there will be a
1786significant startup delay.
1787
1788For production use a statically defined schema (which can be generated
1789using L<DBIx::Class::Schema::Loader|DBIx::Class::Schema::Loader> to dump
1790the database schema once - see
1791L<make_schema_at|DBIx::Class::Schema::Loader/make_schema_at> and
1792L<dump_directory|DBIx::Class::Schema::Loader/dump_directory> for more
1793details on creating static schemas from a database).
1794
1795=head2 Move Common Startup into a Base Class
1796
1797Typically L<DBIx::Class> result classes start off with
1798
1799 use base qw/DBIx::Class/;
1800 __PACKAGE__->load_components(qw/InflateColumn::DateTime Core/);
1801
1802If this preamble is moved into a common base class:-
1803
1804 package MyDBICbase;
1805
1806 use base qw/DBIx::Class/;
1807 __PACKAGE__->load_components(qw/InflateColumn::DateTime Core/);
1808 1;
1809
1810and each result class then uses this as a base:-
1811
1812 use base qw/MyDBICbase/;
1813
1814then the load_components is only performed once, which can result in a
1815considerable startup speedup for schemas with many classes.
1816
1817=head2 Explicitly List Schema Result Classes
1818
1819The schema class will normally contain
1820
1821 __PACKAGE__->load_classes();
1822
1823to load the result classes. This will use L<Module::Find|Module::Find>
1824to find and load the appropriate modules. Explicitly defining the
1825classes you wish to load will remove the overhead of
1826L<Module::Find|Module::Find> and the related directory operations:-
1827
1828 __PACKAGE__->load_classes(qw/ CD Artist Track /);
1829
1830If you are instead using the L<load_namespaces|DBIx::Class::Schema/load_namespaces>
1831syntax to load the appropriate classes there is not a direct alternative
1832avoiding L<Module::Find|Module::Find>.
7aaec96c 1833
f4db5947 1834=head1 MEMORY USAGE
1835
1836=head2 Cached statements
1837
1838L<DBIx::Class> normally caches all statements with L<< prepare_cached()|DBI/prepare_cached >>.
1839This is normally a good idea, but if too many statements are cached, the database may use too much
1840memory and may eventually run out and fail entirely. If you suspect this may be the case, you may want
1841to examine DBI's L<< CachedKids|DBI/CachedKidsCachedKids_(hash_ref) >> hash:
1842
1843 # print all currently cached prepared statements
1844 print for keys %{$schema->storage->dbh->{CachedKids}};
1845 # get a count of currently cached prepared statements
1846 my $count = scalar keys %{$schema->storage->dbh->{CachedKids}};
1847
1848If it's appropriate, you can simply clear these statements, automatically deallocating them in the
1849database:
1850
1851 my $kids = $schema->storage->dbh->{CachedKids};
1852 delete @{$kids}{keys %$kids} if scalar keys %$kids > 100;
1853
1854But what you probably want is to expire unused statements and not those that are used frequently.
1855You can accomplish this with L<Tie::Cache> or L<Tie::Cache::LRU>:
1856
1857 use Tie::Cache;
1858 use DB::Main;
1859 my $schema = DB::Main->connect($dbi_dsn, $user, $pass, {
1860 on_connect_do => sub { tie %{shift->_dbh->{CachedKids}}, 'Tie::Cache', 100 },
1861 });
1862
40dbc108 1863=cut