removed the mistaken debug code
[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
bade79c4 22The C<page> attribute does not have to be specified in your search:
23
24 my $rs = $schema->resultset('Artist')->search(
5e8b1b2a 25 undef,
bade79c4 26 {
27 rows => 10,
28 }
29 );
faf62551 30
bade79c4 31 return $rs->page(1); # DBIx::Class::ResultSet containing first 10 records
faf62551 32
264f1571 33In either of the above cases, you can get a L<Data::Page> object for the
bade79c4 34resultset (suitable for use in e.g. a template) using the C<pager> method:
faf62551 35
bade79c4 36 return $rs->pager();
faf62551 37
d2f3e87b 38=head2 Complex WHERE clauses
2913b2d3 39
40dbc108 40Sometimes you need to formulate a query using specific operators:
41
ea6309e2 42 my @albums = $schema->resultset('Album')->search({
35d4fe78 43 artist => { 'like', '%Lamb%' },
44 title => { 'like', '%Fear of Fours%' },
45 });
40dbc108 46
47This results in something like the following C<WHERE> clause:
48
35d4fe78 49 WHERE artist LIKE '%Lamb%' AND title LIKE '%Fear of Fours%'
40dbc108 50
51Other queries might require slightly more complex logic:
52
ea6309e2 53 my @albums = $schema->resultset('Album')->search({
35d4fe78 54 -or => [
55 -and => [
56 artist => { 'like', '%Smashing Pumpkins%' },
57 title => 'Siamese Dream',
58 ],
59 artist => 'Starchildren',
60 ],
61 });
40dbc108 62
63This results in the following C<WHERE> clause:
64
35d4fe78 65 WHERE ( artist LIKE '%Smashing Pumpkins%' AND title = 'Siamese Dream' )
66 OR artist = 'Starchildren'
40dbc108 67
68For more information on generating complex queries, see
69L<SQL::Abstract/WHERE CLAUSES>.
ee38fa40 70
d2f3e87b 71=head2 Arbitrary SQL through a custom ResultSource
321d9634 72
73Sometimes you have to run arbitrary SQL because your query is too complex
74(e.g. it contains Unions, Sub-Selects, Stored Procedures, etc.) or has to
75be optimized for your database in a special way, but you still want to
76get the results as a L<DBIx::Class::ResultSet>.
77The recommended way to accomplish this is by defining a separate ResultSource
78for your query. You can then inject complete SQL statements using a scalar
79reference (this is a feature of L<SQL::Abstract>).
80
81Say you want to run a complex custom query on your user data, here's what
82you have to add to your User class:
83
84 package My::Schema::User;
85
86 use base qw/DBIx::Class/;
87
88 # ->load_components, ->table, ->add_columns, etc.
89
90 # Make a new ResultSource based on the User class
91 my $source = __PACKAGE__->result_source_instance();
92 my $new_source = $source->new( $source );
93 $new_source->source_name( 'UserFriendsComplex' );
94
95 # Hand in your query as a scalar reference
96 # It will be added as a sub-select after FROM,
97 # so pay attention to the surrounding brackets!
98 $new_source->name( \<<SQL );
99 ( SELECT u.* FROM user u
100 INNER JOIN user_friends f ON u.id = f.user_id
101 WHERE f.friend_user_id = ?
102 UNION
103 SELECT u.* FROM user u
104 INNER JOIN user_friends f ON u.id = f.friend_user_id
105 WHERE f.user_id = ? )
106 SQL
107
108 # Finally, register your new ResultSource with your Schema
109 My::Schema->register_source( 'UserFriendsComplex' => $new_source );
110
111Next, you can execute your complex query using bind parameters like this:
112
113 my $friends = [ $schema->resultset( 'UserFriendsComplex' )->search( {},
114 {
115 bind => [ 12345, 12345 ]
116 }
117 ) ];
118
119... and you'll get back a perfect L<DBIx::Class::ResultSet>.
120
d2f3e87b 121=head2 Using specific columns
faf62551 122
324572ca 123When you only want specific columns from a table, you can use
124C<columns> to specify which ones you need. This is useful to avoid
125loading columns with large amounts of data that you aren't about to
126use anyway:
faf62551 127
bade79c4 128 my $rs = $schema->resultset('Artist')->search(
5e8b1b2a 129 undef,
bade79c4 130 {
5e8b1b2a 131 columns => [qw/ name /]
bade79c4 132 }
133 );
faf62551 134
bade79c4 135 # Equivalent SQL:
136 # SELECT artist.name FROM artist
faf62551 137
324572ca 138This is a shortcut for C<select> and C<as>, see below. C<columns>
139cannot be used together with C<select> and C<as>.
140
d2f3e87b 141=head2 Using database functions or stored procedures
faf62551 142
bade79c4 143The combination of C<select> and C<as> can be used to return the result of a
144database function or stored procedure as a column value. You use C<select> to
145specify the source for your column value (e.g. a column name, function, or
146stored procedure name). You then use C<as> to set the column name you will use
147to access the returned value:
faf62551 148
bade79c4 149 my $rs = $schema->resultset('Artist')->search(
324572ca 150 {},
bade79c4 151 {
152 select => [ 'name', { LENGTH => 'name' } ],
153 as => [qw/ name name_length /],
154 }
155 );
faf62551 156
bade79c4 157 # Equivalent SQL:
98b65433 158 # SELECT name name, LENGTH( name )
bade79c4 159 # FROM artist
faf62551 160
d676881f 161Note that the C< as > attribute has absolutely nothing to with the sql
162syntax C< SELECT foo AS bar > (see the documentation in
163L<DBIx::Class::ResultSet/ATTRIBUTES>). If your alias exists as a
164column in your base class (i.e. it was added with C<add_columns>), you
165just access it as normal. Our C<Artist> class has a C<name> column, so
166we just use the C<name> accessor:
faf62551 167
bade79c4 168 my $artist = $rs->first();
169 my $name = $artist->name();
faf62551 170
171If on the other hand the alias does not correspond to an existing column, you
324572ca 172have to fetch the value using the C<get_column> accessor:
faf62551 173
bade79c4 174 my $name_length = $artist->get_column('name_length');
faf62551 175
bade79c4 176If you don't like using C<get_column>, you can always create an accessor for
faf62551 177any of your aliases using either of these:
178
bade79c4 179 # Define accessor manually:
180 sub name_length { shift->get_column('name_length'); }
faf62551 181
bade79c4 182 # Or use DBIx::Class::AccessorGroup:
183 __PACKAGE__->mk_group_accessors('column' => 'name_length');
faf62551 184
d2f3e87b 185=head2 SELECT DISTINCT with multiple columns
faf62551 186
bade79c4 187 my $rs = $schema->resultset('Foo')->search(
324572ca 188 {},
bade79c4 189 {
190 select => [
191 { distinct => [ $source->columns ] }
192 ],
d676881f 193 as => [ $source->columns ] # remember 'as' is not the same as SQL AS :-)
bade79c4 194 }
195 );
faf62551 196
d2f3e87b 197=head2 SELECT COUNT(DISTINCT colname)
6607ee1b 198
bade79c4 199 my $rs = $schema->resultset('Foo')->search(
324572ca 200 {},
bade79c4 201 {
202 select => [
203 { count => { distinct => 'colname' } }
204 ],
205 as => [ 'count' ]
206 }
207 );
6607ee1b 208
3d565896 209 my $count = $rs->next->get_column('count');
210
d2f3e87b 211=head2 Grouping results
bade79c4 212
213L<DBIx::Class> supports C<GROUP BY> as follows:
214
215 my $rs = $schema->resultset('Artist')->search(
324572ca 216 {},
bade79c4 217 {
218 join => [qw/ cds /],
219 select => [ 'name', { count => 'cds.cdid' } ],
220 as => [qw/ name cd_count /],
221 group_by => [qw/ name /]
222 }
223 );
6607ee1b 224
bade79c4 225 # Equivalent SQL:
226 # SELECT name, COUNT( cds.cdid ) FROM artist me
227 # LEFT JOIN cd cds ON ( cds.artist = me.artistid )
228 # GROUP BY name
6607ee1b 229
d676881f 230Please see L<DBIx::Class::ResultSet/ATTRIBUTES> documentation if you
231are in any way unsure about the use of the attributes above (C< join
232>, C< select >, C< as > and C< group_by >).
233
d2f3e87b 234=head2 Predefined searches
74dc2edc 235
324572ca 236You can write your own L<DBIx::Class::ResultSet> class by inheriting from it
74dc2edc 237and define often used searches as methods:
238
239 package My::DBIC::ResultSet::CD;
240 use strict;
241 use warnings;
242 use base 'DBIx::Class::ResultSet';
243
244 sub search_cds_ordered {
245 my ($self) = @_;
246
247 return $self->search(
248 {},
249 { order_by => 'name DESC' },
250 );
251 }
252
253 1;
254
255To use your resultset, first tell DBIx::Class to create an instance of it
256for you, in your My::DBIC::Schema::CD class:
257
9dc1bfce 258 # class definition as normal
259 __PACKAGE__->load_components(qw/ Core /);
260 __PACKAGE__->table('cd');
261
262 # tell DBIC to use the custom ResultSet class
74dc2edc 263 __PACKAGE__->resultset_class('My::DBIC::ResultSet::CD');
264
9dc1bfce 265Note that C<resultset_class> must be called after C<load_components> and C<table>, or you will get errors about missing methods.
266
74dc2edc 267Then call your new method in your code:
268
269 my $ordered_cds = $schema->resultset('CD')->search_cds_ordered();
270
d2f3e87b 271=head2 Using SQL functions on the left hand side of a comparison
1c133e22 272
273Using SQL functions on the left hand side of a comparison is generally
274not a good idea since it requires a scan of the entire table. However,
275it can be accomplished with C<DBIx::Class> when necessary.
276
277If you do not have quoting on, simply include the function in your search
278specification as you would any column:
279
280 $rs->search({ 'YEAR(date_of_birth)' => 1979 });
281
282With quoting on, or for a more portable solution, use the C<where>
283attribute:
284
285 $rs->search({}, { where => \'YEAR(date_of_birth) = 1979' });
286
287=begin hidden
288
289(When the bind args ordering bug is fixed, this technique will be better
290and can replace the one above.)
291
292With quoting on, or for a more portable solution, use the C<where> and
293C<bind> attributes:
294
295 $rs->search({}, {
296 where => \'YEAR(date_of_birth) = ?',
297 bind => [ 1979 ]
298 });
299
300=end hidden
301
d2f3e87b 302=head1 JOINS AND PREFETCHING
303
87980de7 304=head2 Using joins and prefetch
305
bade79c4 306You can use the C<join> attribute to allow searching on, or sorting your
307results by, one or more columns in a related table. To return all CDs matching
308a particular artist name:
ea6309e2 309
bade79c4 310 my $rs = $schema->resultset('CD')->search(
311 {
312 'artist.name' => 'Bob Marley'
313 },
314 {
315 join => [qw/artist/], # join the artist table
316 }
317 );
318
319 # Equivalent SQL:
320 # SELECT cd.* FROM cd
321 # JOIN artist ON cd.artist = artist.id
322 # WHERE artist.name = 'Bob Marley'
323
324If required, you can now sort on any column in the related tables by including
325it in your C<order_by> attribute:
326
327 my $rs = $schema->resultset('CD')->search(
328 {
329 'artist.name' => 'Bob Marley'
330 },
331 {
332 join => [qw/ artist /],
333 order_by => [qw/ artist.name /]
334 }
2f81ed0f 335 );
ea6309e2 336
bade79c4 337 # Equivalent SQL:
338 # SELECT cd.* FROM cd
339 # JOIN artist ON cd.artist = artist.id
340 # WHERE artist.name = 'Bob Marley'
341 # ORDER BY artist.name
ea6309e2 342
bade79c4 343Note that the C<join> attribute should only be used when you need to search or
344sort using columns in a related table. Joining related tables when you only
345need columns from the main table will make performance worse!
ea6309e2 346
bade79c4 347Now let's say you want to display a list of CDs, each with the name of the
348artist. The following will work fine:
ea6309e2 349
bade79c4 350 while (my $cd = $rs->next) {
351 print "CD: " . $cd->title . ", Artist: " . $cd->artist->name;
352 }
ea6309e2 353
bade79c4 354There is a problem however. We have searched both the C<cd> and C<artist> tables
355in our main query, but we have only returned data from the C<cd> table. To get
356the artist name for any of the CD objects returned, L<DBIx::Class> will go back
357to the database:
ea6309e2 358
bade79c4 359 SELECT artist.* FROM artist WHERE artist.id = ?
ea6309e2 360
361A statement like the one above will run for each and every CD returned by our
362main query. Five CDs, five extra queries. A hundred CDs, one hundred extra
363queries!
364
bade79c4 365Thankfully, L<DBIx::Class> has a C<prefetch> attribute to solve this problem.
897342e4 366This allows you to fetch results from related tables in advance:
ea6309e2 367
bade79c4 368 my $rs = $schema->resultset('CD')->search(
369 {
370 'artist.name' => 'Bob Marley'
371 },
372 {
373 join => [qw/ artist /],
374 order_by => [qw/ artist.name /],
375 prefetch => [qw/ artist /] # return artist data too!
376 }
377 );
ea6309e2 378
bade79c4 379 # Equivalent SQL (note SELECT from both "cd" and "artist"):
380 # SELECT cd.*, artist.* FROM cd
381 # JOIN artist ON cd.artist = artist.id
382 # WHERE artist.name = 'Bob Marley'
383 # ORDER BY artist.name
ea6309e2 384
385The code to print the CD list remains the same:
386
bade79c4 387 while (my $cd = $rs->next) {
388 print "CD: " . $cd->title . ", Artist: " . $cd->artist->name;
389 }
ea6309e2 390
bade79c4 391L<DBIx::Class> has now prefetched all matching data from the C<artist> table,
ea6309e2 392so no additional SQL statements are executed. You now have a much more
393efficient query.
394
77d6b403 395Note that as of L<DBIx::Class> 0.05999_01, C<prefetch> I<can> be used with
396C<has_many> relationships.
ea6309e2 397
bade79c4 398Also note that C<prefetch> should only be used when you know you will
ea6309e2 399definitely use data from a related table. Pre-fetching related tables when you
400only need columns from the main table will make performance worse!
401
d2f3e87b 402=head2 Multi-step joins
ea6309e2 403
404Sometimes you want to join more than one relationship deep. In this example,
bade79c4 405we want to find all C<Artist> objects who have C<CD>s whose C<LinerNotes>
406contain a specific string:
407
408 # Relationships defined elsewhere:
409 # Artist->has_many('cds' => 'CD', 'artist');
410 # CD->has_one('liner_notes' => 'LinerNotes', 'cd');
411
412 my $rs = $schema->resultset('Artist')->search(
413 {
414 'liner_notes.notes' => { 'like', '%some text%' },
415 },
416 {
417 join => {
418 'cds' => 'liner_notes'
419 }
420 }
421 );
ea6309e2 422
bade79c4 423 # Equivalent SQL:
424 # SELECT artist.* FROM artist
425 # JOIN ( cd ON artist.id = cd.artist )
426 # JOIN ( liner_notes ON cd.id = liner_notes.cd )
427 # WHERE liner_notes.notes LIKE '%some text%'
ea6309e2 428
429Joins can be nested to an arbitrary level. So if we decide later that we
430want to reduce the number of Artists returned based on who wrote the liner
431notes:
432
bade79c4 433 # Relationship defined elsewhere:
434 # LinerNotes->belongs_to('author' => 'Person');
435
436 my $rs = $schema->resultset('Artist')->search(
437 {
438 'liner_notes.notes' => { 'like', '%some text%' },
439 'author.name' => 'A. Writer'
440 },
441 {
442 join => {
443 'cds' => {
444 'liner_notes' => 'author'
ea6309e2 445 }
bade79c4 446 }
447 }
448 );
ea6309e2 449
bade79c4 450 # Equivalent SQL:
451 # SELECT artist.* FROM artist
452 # JOIN ( cd ON artist.id = cd.artist )
453 # JOIN ( liner_notes ON cd.id = liner_notes.cd )
454 # JOIN ( author ON author.id = liner_notes.author )
455 # WHERE liner_notes.notes LIKE '%some text%'
456 # AND author.name = 'A. Writer'
87980de7 457
897342e4 458=head2 Multi-step prefetch
459
460From 0.04999_05 onwards, C<prefetch> can be nested more than one relationship
461deep using the same syntax as a multi-step join:
462
463 my $rs = $schema->resultset('Tag')->search(
ac2803ef 464 {},
897342e4 465 {
466 prefetch => {
467 cd => 'artist'
468 }
469 }
470 );
471
472 # Equivalent SQL:
473 # SELECT tag.*, cd.*, artist.* FROM tag
474 # JOIN cd ON tag.cd = cd.cdid
475 # JOIN artist ON cd.artist = artist.artistid
476
477Now accessing our C<cd> and C<artist> relationships does not need additional
478SQL statements:
479
480 my $tag = $rs->first;
481 print $tag->cd->artist->name;
482
d2f3e87b 483=head1 ROW-LEVEL OPERATIONS
484
485=head2 Retrieving a row object's Schema
486
487It is possible to get a Schema object from a row object like so:
488
489 my $schema = $cd->result_source->schema;
490 # use the schema as normal:
491 my $artist_rs = $schema->resultset('Artist');
492
493This can be useful when you don't want to pass around a Schema object to every
494method.
495
496=head2 Getting the value of the primary key for the last database insert
497
498AKA getting last_insert_id
499
500If you are using PK::Auto (which is a core component as of 0.07), this is
501straightforward:
502
503 my $foo = $rs->create(\%blah);
504 # do more stuff
505 my $id = $foo->id; # foo->my_primary_key_field will also work.
506
507If you are not using autoincrementing primary keys, this will probably
508not work, but then you already know the value of the last primary key anyway.
509
510=head2 Stringification
511
512Employ the standard stringification technique by using the C<overload>
513module.
514
515To make an object stringify itself as a single column, use something
516like this (replace C<foo> with the column/method of your choice):
517
518 use overload '""' => sub { shift->name}, fallback => 1;
519
520For more complex stringification, you can use an anonymous subroutine:
521
522 use overload '""' => sub { $_[0]->name . ", " .
523 $_[0]->address }, fallback => 1;
524
525=head3 Stringification Example
526
527Suppose we have two tables: C<Product> and C<Category>. The table
528specifications are:
529
530 Product(id, Description, category)
531 Category(id, Description)
532
533C<category> is a foreign key into the Category table.
534
535If you have a Product object C<$obj> and write something like
536
537 print $obj->category
538
539things will not work as expected.
540
541To obtain, for example, the category description, you should add this
542method to the class defining the Category table:
543
544 use overload "" => sub {
545 my $self = shift;
546
547 return $self->Description;
548 }, fallback => 1;
549
550=head2 Want to know if find_or_create found or created a row?
551
552Just use C<find_or_new> instead, then check C<in_storage>:
553
554 my $obj = $rs->find_or_new({ blah => 'blarg' });
555 unless ($obj->in_storage) {
556 $obj->insert;
557 # do whatever else you wanted if it was a new row
558 }
559
560=head2 Dynamic Sub-classing DBIx::Class proxy classes
561
562AKA multi-class object inflation from one table
563
564L<DBIx::Class> classes are proxy classes, therefore some different
565techniques need to be employed for more than basic subclassing. In
566this example we have a single user table that carries a boolean bit
567for admin. We would like like to give the admin users
568objects(L<DBIx::Class::Row>) the same methods as a regular user but
569also special admin only methods. It doesn't make sense to create two
570seperate proxy-class files for this. We would be copying all the user
571methods into the Admin class. There is a cleaner way to accomplish
572this.
573
574Overriding the C<inflate_result> method within the User proxy-class
575gives us the effect we want. This method is called by
576L<DBIx::Class::ResultSet> when inflating a result from storage. So we
577grab the object being returned, inspect the values we are looking for,
578bless it if it's an admin object, and then return it. See the example
579below:
580
581B<Schema Definition>
582
583 package DB::Schema;
584
585 use base qw/DBIx::Class::Schema/;
586
587 __PACKAGE__->load_classes(qw/User/);
588
589
590B<Proxy-Class definitions>
591
592 package DB::Schema::User;
593
594 use strict;
595 use warnings;
596 use base qw/DBIx::Class/;
597
598 ### Defined what our admin class is for ensure_class_loaded
599 my $admin_class = __PACKAGE__ . '::Admin';
600
601 __PACKAGE__->load_components(qw/Core/);
602
603 __PACKAGE__->table('users');
604
605 __PACKAGE__->add_columns(qw/user_id email password
606 firstname lastname active
607 admin/);
608
609 __PACKAGE__->set_primary_key('user_id');
610
611 sub inflate_result {
612 my $self = shift;
613 my $ret = $self->next::method(@_);
614 if( $ret->admin ) {### If this is an admin rebless for extra functions
615 $self->ensure_class_loaded( $admin_class );
616 bless $ret, $admin_class;
617 }
618 return $ret;
619 }
620
621 sub hello {
622 print "I am a regular user.\n";
623 return ;
624 }
625
626
627 package DB::Schema::User::Admin;
628
629 use strict;
630 use warnings;
631 use base qw/DB::Schema::User/;
632
633 sub hello
634 {
635 print "I am an admin.\n";
636 return;
637 }
638
639 sub do_admin_stuff
640 {
641 print "I am doing admin stuff\n";
642 return ;
643 }
644
645B<Test File> test.pl
646
647 use warnings;
648 use strict;
649 use DB::Schema;
650
651 my $user_data = { email => 'someguy@place.com',
652 password => 'pass1',
653 admin => 0 };
654
655 my $admin_data = { email => 'someadmin@adminplace.com',
656 password => 'pass2',
657 admin => 1 };
658
659 my $schema = DB::Schema->connection('dbi:Pg:dbname=test');
660
661 $schema->resultset('User')->create( $user_data );
662 $schema->resultset('User')->create( $admin_data );
663
664 ### Now we search for them
665 my $user = $schema->resultset('User')->single( $user_data );
666 my $admin = $schema->resultset('User')->single( $admin_data );
667
668 print ref $user, "\n";
669 print ref $admin, "\n";
670
671 print $user->password , "\n"; # pass1
672 print $admin->password , "\n";# pass2; inherited from User
673 print $user->hello , "\n";# I am a regular user.
674 print $admin->hello, "\n";# I am an admin.
675
676 ### The statement below will NOT print
677 print "I can do admin stuff\n" if $user->can('do_admin_stuff');
678 ### The statement below will print
679 print "I can do admin stuff\n" if $admin->can('do_admin_stuff');
680
681=head2 Skip object creation for faster results
682
683DBIx::Class is not built for speed, it's built for convenience and
684ease of use, but sometimes you just need to get the data, and skip the
685fancy objects.
686
687To do this simply use L<DBIx::Class::ResultClass::HashRefInflator>.
688
689 my $rs = $schema->resultset('CD');
690
691 $rs->result_class('DBIx::Class::ResultClass::HashRefInflator');
692
693 my $hash_ref = $rs->find(1);
694
695Wasn't that easy?
696
697=head2 Get raw data for blindingly fast results
698
699If the L<HashRefInflator|DBIx::Class::ResultClass::HashRefInflator> solution
700above is not fast enough for you, you can use a DBIx::Class to return values
701exactly as they come out of the data base with none of the convenience methods
702wrapped round them.
703
704This is used like so:-
705
706 my $cursor = $rs->cursor
707 while (my @vals = $cursor->next) {
708 # use $val[0..n] here
709 }
710
711You will need to map the array offsets to particular columns (you can
712use the I<select> attribute of C<search()> to force ordering).
713
714=head1 RESULTSET OPERATIONS
715
716=head2 Getting Schema from a ResultSet
717
718To get the schema object from a result set, do the following:
719
720 $rs->result_source->schema
721
722=head2 Getting Columns Of Data
723
724AKA Aggregating Data
ac2803ef 725
726If you want to find the sum of a particular column there are several
727ways, the obvious one is to use search:
728
729 my $rs = $schema->resultset('Items')->search(
730 {},
731 {
732 select => [ { sum => 'Cost' } ],
d676881f 733 as => [ 'total_cost' ], # remember this 'as' is for DBIx::Class::ResultSet not SQL
ac2803ef 734 }
735 );
736 my $tc = $rs->first->get_column('total_cost');
737
738Or, you can use the L<DBIx::Class::ResultSetColumn>, which gets
739returned when you ask the C<ResultSet> for a column using
740C<get_column>:
741
742 my $cost = $schema->resultset('Items')->get_column('Cost');
743 my $tc = $cost->sum;
744
745With this you can also do:
746
747 my $minvalue = $cost->min;
748 my $maxvalue = $cost->max;
749
750Or just iterate through the values of this column only:
751
752 while ( my $c = $cost->next ) {
753 print $c;
754 }
755
756 foreach my $c ($cost->all) {
757 print $c;
758 }
759
709353af 760C<ResultSetColumn> only has a limited number of built-in functions, if
761you need one that it doesn't have, then you can use the C<func> method
762instead:
763
764 my $avg = $cost->func('AVERAGE');
765
766This will cause the following SQL statement to be run:
767
768 SELECT AVERAGE(Cost) FROM Items me
769
770Which will of course only work if your database supports this function.
ac2803ef 771See L<DBIx::Class::ResultSetColumn> for more documentation.
772
204e5c03 773=head2 Creating a result set from a set of rows
774
775Sometimes you have a (set of) row objects that you want to put into a
776resultset without the need to hit the DB again. You can do that by using the
777L<set_cache|DBIx::Class::Resultset/set_cache> method:
778
2d7a4e46 779 my @uploadable_groups;
204e5c03 780 while (my $group = $groups->next) {
781 if ($group->can_upload($self)) {
782 push @uploadable_groups, $group;
783 }
784 }
785 my $new_rs = $self->result_source->resultset;
786 $new_rs->set_cache(\@uploadable_groups);
787 return $new_rs;
788
789
d2f3e87b 790=head1 USING RELATIONSHIPS
acee4e4d 791
d2f3e87b 792=head2 Create a new row in a related table
acee4e4d 793
6f1434fd 794 my $author = $book->create_related('author', { name => 'Fred'});
acee4e4d 795
d2f3e87b 796=head2 Search in a related table
acee4e4d 797
798Only searches for books named 'Titanic' by the author in $author.
799
6f1434fd 800 my $books_rs = $author->search_related('books', { name => 'Titanic' });
acee4e4d 801
d2f3e87b 802=head2 Delete data in a related table
acee4e4d 803
804Deletes only the book named Titanic by the author in $author.
805
6f1434fd 806 $author->delete_related('books', { name => 'Titanic' });
acee4e4d 807
d2f3e87b 808=head2 Ordering a relationship result set
f8bad769 809
810If you always want a relation to be ordered, you can specify this when you
811create the relationship.
812
6f1434fd 813To order C<< $book->pages >> by descending page_number, create the relation
814as follows:
f8bad769 815
6f1434fd 816 __PACKAGE__->has_many('pages' => 'Page', 'book', { order_by => \'page_number DESC'} );
f8bad769 817
d2f3e87b 818=head2 Many-to-many relationships
f8bad769 819
d2f3e87b 820This is straightforward using L<ManyToMany|DBIx::Class::Relationship/many_to_many>:
f8bad769 821
d2f3e87b 822 package My::User;
6f1434fd 823 use base 'DBIx::Class';
824 __PACKAGE__->load_components('Core');
d2f3e87b 825 __PACKAGE__->table('user');
826 __PACKAGE__->add_columns(qw/id name/);
827 __PACKAGE__->set_primary_key('id');
828 __PACKAGE__->has_many('user_address' => 'My::UserAddress', 'user');
829 __PACKAGE__->many_to_many('addresses' => 'user_address', 'address');
87980de7 830
d2f3e87b 831 package My::UserAddress;
6f1434fd 832 use base 'DBIx::Class';
833 __PACKAGE__->load_components('Core');
d2f3e87b 834 __PACKAGE__->table('user_address');
835 __PACKAGE__->add_columns(qw/user address/);
836 __PACKAGE__->set_primary_key(qw/user address/);
837 __PACKAGE__->belongs_to('user' => 'My::User');
838 __PACKAGE__->belongs_to('address' => 'My::Address');
181a28f4 839
d2f3e87b 840 package My::Address;
6f1434fd 841 use base 'DBIx::Class';
842 __PACKAGE__->load_components('Core');
d2f3e87b 843 __PACKAGE__->table('address');
844 __PACKAGE__->add_columns(qw/id street town area_code country/);
845 __PACKAGE__->set_primary_key('id');
846 __PACKAGE__->has_many('user_address' => 'My::UserAddress', 'address');
847 __PACKAGE__->many_to_many('users' => 'user_address', 'user');
848
849 $rs = $user->addresses(); # get all addresses for a user
850 $rs = $address->users(); # get all users for an address
851
852=head1 TRANSACTIONS
853
854As of version 0.04001, there is improved transaction support in
855L<DBIx::Class::Storage> and L<DBIx::Class::Schema>. Here is an
856example of the recommended way to use it:
857
858 my $genus = $schema->resultset('Genus')->find(12);
859
860 my $coderef2 = sub {
861 $genus->extinct(1);
862 $genus->update;
863 };
70634260 864
181a28f4 865 my $coderef1 = sub {
35d4fe78 866 $genus->add_to_species({ name => 'troglodyte' });
867 $genus->wings(2);
868 $genus->update;
6f1434fd 869 $schema->txn_do($coderef2); # Can have a nested transaction. Only the outer will actualy commit
181a28f4 870 return $genus->species;
871 };
872
181a28f4 873 my $rs;
874 eval {
70634260 875 $rs = $schema->txn_do($coderef1);
181a28f4 876 };
877
878 if ($@) { # Transaction failed
879 die "the sky is falling!" #
880 if ($@ =~ /Rollback failed/); # Rollback failed
881
882 deal_with_failed_transaction();
35d4fe78 883 }
87980de7 884
181a28f4 885Nested transactions will work as expected. That is, only the outermost
886transaction will actually issue a commit to the $dbh, and a rollback
887at any level of any transaction will cause the entire nested
888transaction to fail. Support for savepoints and for true nested
40dbc108 889transactions (for databases that support them) will hopefully be added
890in the future.
ee38fa40 891
d2f3e87b 892=head1 SQL
ee38fa40 893
d2f3e87b 894=head2 Creating Schemas From An Existing Database
ea6309e2 895
d2f3e87b 896L<DBIx::Class::Schema::Loader> will connect to a database and create a
897L<DBIx::Class::Schema> and associated sources by examining the database.
bade79c4 898
d2f3e87b 899The recommend way of achieving this is to use the
900L<make_schema_at|DBIx::Class::Schema::Loader/make_schema_at> method:
bade79c4 901
6f1434fd 902 perl -MDBIx::Class::Schema::Loader=make_schema_at,dump_to_dir:./lib \
903 -e 'make_schema_at("My::Schema", { debug => 1 }, [ "dbi:Pg:dbname=foo","postgres" ])'
362500af 904
d2f3e87b 905This will create a tree of files rooted at C<./lib/My/Schema/> containing
906source definitions for all the tables found in the C<foo> database.
362500af 907
d2f3e87b 908=head2 Creating DDL SQL
362500af 909
264f1571 910The following functionality requires you to have L<SQL::Translator>
911(also known as "SQL Fairy") installed.
362500af 912
264f1571 913To create a set of database-specific .sql files for the above schema:
362500af 914
264f1571 915 my $schema = My::Schema->connect($dsn);
916 $schema->create_ddl_dir(['MySQL', 'SQLite', 'PostgreSQL'],
917 '0.1',
d2f3e87b 918 './dbscriptdir/'
264f1571 919 );
920
921By default this will create schema files in the current directory, for
922MySQL, SQLite and PostgreSQL, using the $VERSION from your Schema.pm.
923
924To create a new database using the schema:
925
926 my $schema = My::Schema->connect($dsn);
927 $schema->deploy({ add_drop_tables => 1});
928
929To import created .sql files using the mysql client:
930
931 mysql -h "host" -D "database" -u "user" -p < My_Schema_1.0_MySQL.sql
932
933To create C<ALTER TABLE> conversion scripts to update a database to a
934newer version of your schema at a later point, first set a new
d2f3e87b 935C<$VERSION> in your Schema file, then:
264f1571 936
937 my $schema = My::Schema->connect($dsn);
938 $schema->create_ddl_dir(['MySQL', 'SQLite', 'PostgreSQL'],
939 '0.2',
940 '/dbscriptdir/',
941 '0.1'
942 );
943
944This will produce new database-specific .sql files for the new version
945of the schema, plus scripts to convert from version 0.1 to 0.2. This
946requires that the files for 0.1 as created above are available in the
947given directory to diff against.
362500af 948
6f1434fd 949=head2 Select from dual
16cd5b28 950
951Dummy tables are needed by some databases to allow calling functions
952or expressions that aren't based on table content, for examples of how
953this applies to various database types, see:
954L<http://troels.arvin.dk/db/rdbms/#other-dummy_table>.
955
956Note: If you're using Oracles dual table don't B<ever> do anything
957other than a select, if you CRUD on your dual table you *will* break
958your database.
959
960Make a table class as you would for any other table
961
962 package MyAppDB::Dual;
963 use strict;
964 use warnings;
965 use base 'DBIx::Class';
966 __PACKAGE__->load_components("Core");
967 __PACKAGE__->table("Dual");
968 __PACKAGE__->add_columns(
969 "dummy",
970 { data_type => "VARCHAR2", is_nullable => 0, size => 1 },
971 );
972
973Once you've loaded your table class select from it using C<select>
974and C<as> instead of C<columns>
975
976 my $rs = $schema->resultset('Dual')->search(undef,
977 { select => [ 'sydate' ],
978 as => [ 'now' ]
979 },
980 );
981
982All you have to do now is be careful how you access your resultset, the below
983will not work because there is no column called 'now' in the Dual table class
984
985 while (my $dual = $rs->next) {
986 print $dual->now."\n";
987 }
6f1434fd 988 # Can't locate object method "now" via package "MyAppDB::Dual" at headshot.pl line 23.
16cd5b28 989
990You could of course use 'dummy' in C<as> instead of 'now', or C<add_columns> to
991your Dual class for whatever you wanted to select from dual, but that's just
992silly, instead use C<get_column>
993
994 while (my $dual = $rs->next) {
995 print $dual->get_column('now')."\n";
996 }
997
998Or use C<cursor>
999
1000 my $cursor = $rs->cursor;
1001 while (my @vals = $cursor->next) {
1002 print $vals[0]."\n";
1003 }
1004
1005Or use L<DBIx::Class::ResultClass::HashRefInflator>
1006
1007 $rs->result_class('DBIx::Class::ResultClass::HashRefInflator');
1008 while ( my $dual = $rs->next ) {
1009 print $dual->{now}."\n";
1010 }
1011
1012Here are some example C<select> conditions to illustrate the different syntax
1013you could use for doing stuff like
1014C<oracles.heavily(nested(functions_can('take', 'lots'), OF), 'args')>
1015
1016 # get a sequence value
1017 select => [ 'A_SEQ.nextval' ],
1018
1019 # get create table sql
1020 select => [ { 'dbms_metadata.get_ddl' => [ "'TABLE'", "'ARTIST'" ]} ],
1021
1022 # get a random num between 0 and 100
1023 select => [ { "trunc" => [ { "dbms_random.value" => [0,100] } ]} ],
1024
1025 # what year is it?
1026 select => [ { 'extract' => [ \'year from sysdate' ] } ],
1027
1028 # do some math
1029 select => [ {'round' => [{'cos' => [ \'180 * 3.14159265359/180' ]}]}],
1030
1031 # which day of the week were you born on?
6f1434fd 1032 select => [{'to_char' => [{'to_date' => [ "'25-DEC-1980'", "'dd-mon-yyyy'" ]}, "'day'"]}],
16cd5b28 1033
1034 # select 16 rows from dual
1035 select => [ "'hello'" ],
1036 as => [ 'world' ],
1037 group_by => [ 'cube( 1, 2, 3, 4 )' ],
1038
1039
1040
d2f3e87b 1041=head2 Adding Indexes And Functions To Your SQL
362500af 1042
d2f3e87b 1043Often you will want indexes on columns on your table to speed up searching. To
1044do this, create a method called C<sqlt_deploy_hook> in the relevant source
1045class:
b0a20454 1046
d2f3e87b 1047 package My::Schema::Artist;
b0a20454 1048
d2f3e87b 1049 __PACKAGE__->table('artist');
1050 __PACKAGE__->add_columns(id => { ... }, name => { ... })
b0a20454 1051
d2f3e87b 1052 sub sqlt_deploy_hook {
1053 my ($self, $sqlt_table) = @_;
1054
1055 $sqlt_table->add_index(name => 'idx_name', fields => ['name']);
1056 }
1057
1058 1;
1059
1060Sometimes you might want to change the index depending on the type of the
1061database for which SQL is being generated:
1062
1063 my ($db_type = $sqlt_table->schema->translator->producer_type)
1064 =~ s/^SQL::Translator::Producer:://;
1065
1066You can also add hooks to the schema level to stop certain tables being
1067created:
1068
1069 package My::Schema;
1070
1071 ...
1072
1073 sub sqlt_deploy_hook {
1074 my ($self, $sqlt_schema) = @_;
1075
1076 $sqlt_schema->drop_table('table_name');
1077 }
1078
1079You could also add views or procedures to the output using
1080L<SQL::Translator::Schema/add_view> or
1081L<SQL::Translator::Schema/add_procedure>.
b0a20454 1082
362500af 1083=head2 Schema versioning
1084
1085The following example shows simplistically how you might use DBIx::Class to
1086deploy versioned schemas to your customers. The basic process is as follows:
1087
da4779ad 1088=over 4
1089
1090=item 1.
1091
1092Create a DBIx::Class schema
1093
1094=item 2.
1095
1096Save the schema
1097
1098=item 3.
1099
1100Deploy to customers
1101
1102=item 4.
1103
1104Modify schema to change functionality
1105
1106=item 5.
1107
1108Deploy update to customers
1109
1110=back
362500af 1111
d2f3e87b 1112B<Create a DBIx::Class schema>
362500af 1113
1114This can either be done manually, or generated from an existing database as
d2f3e87b 1115described under L</Creating Schemas From An Existing Database>
362500af 1116
d2f3e87b 1117B<Save the schema>
362500af 1118
d2f3e87b 1119Call L<DBIx::Class::Schema/create_ddl_dir> as above under L</Creating DDL SQL>.
362500af 1120
d2f3e87b 1121B<Deploy to customers>
362500af 1122
1123There are several ways you could deploy your schema. These are probably
1124beyond the scope of this recipe, but might include:
1125
da4779ad 1126=over 4
1127
1128=item 1.
1129
1130Require customer to apply manually using their RDBMS.
1131
1132=item 2.
1133
1134Package along with your app, making database dump/schema update/tests
362500af 1135all part of your install.
1136
da4779ad 1137=back
1138
d2f3e87b 1139B<Modify the schema to change functionality>
362500af 1140
264f1571 1141As your application evolves, it may be necessary to modify your schema
1142to change functionality. Once the changes are made to your schema in
1143DBIx::Class, export the modified schema and the conversion scripts as
d2f3e87b 1144in L</Creating DDL SQL>.
362500af 1145
d2f3e87b 1146B<Deploy update to customers>
362500af 1147
264f1571 1148Add the L<DBIx::Class::Schema::Versioned> schema component to your
1149Schema class. This will add a new table to your database called
ecea7937 1150C<dbix_class_schema_vesion> which will keep track of which version is installed
264f1571 1151and warn if the user trys to run a newer schema version than the
1152database thinks it has.
1153
1154Alternatively, you can send the conversion sql scripts to your
1155customers as above.
362500af 1156
d2f3e87b 1157=head2 Setting quoting for the generated SQL.
1158
1159If the database contains column names with spaces and/or reserved words, they
1160need to be quoted in the SQL queries. This is done using:
1161
1162 __PACKAGE__->storage->sql_maker->quote_char([ qw/[ ]/] );
1163 __PACKAGE__->storage->sql_maker->name_sep('.');
1164
1165The first sets the quote characters. Either a pair of matching
1166brackets, or a C<"> or C<'>:
1167
1168 __PACKAGE__->storage->sql_maker->quote_char('"');
1169
1170Check the documentation of your database for the correct quote
1171characters to use. C<name_sep> needs to be set to allow the SQL
1172generator to put the quotes the correct place.
1173
1174In most cases you should set these as part of the arguments passed to
1175L<DBIx::Class::Schema/conect>:
1176
1177 my $schema = My::Schema->connect(
1178 'dbi:mysql:my_db',
1179 'db_user',
1180 'db_password',
1181 {
1182 quote_char => '"',
1183 name_sep => '.'
1184 }
1185 )
1186
7be93b07 1187=head2 Setting limit dialect for SQL::Abstract::Limit
1188
324572ca 1189In some cases, SQL::Abstract::Limit cannot determine the dialect of
1190the remote SQL server by looking at the database handle. This is a
1191common problem when using the DBD::JDBC, since the DBD-driver only
1192know that in has a Java-driver available, not which JDBC driver the
1193Java component has loaded. This specifically sets the limit_dialect
1194to Microsoft SQL-server (See more names in SQL::Abstract::Limit
1195-documentation.
7be93b07 1196
1197 __PACKAGE__->storage->sql_maker->limit_dialect('mssql');
1198
324572ca 1199The JDBC bridge is one way of getting access to a MSSQL server from a platform
7be93b07 1200that Microsoft doesn't deliver native client libraries for. (e.g. Linux)
1201
d2f3e87b 1202The limit dialect can also be set at connect time by specifying a
1203C<limit_dialect> key in the final hash as shown above.
2437a1e3 1204
d2f3e87b 1205=head1 BOOTSTRAPPING/MIGRATING
2437a1e3 1206
d2f3e87b 1207=head2 Easy migration from class-based to schema-based setup
2437a1e3 1208
d2f3e87b 1209You want to start using the schema-based approach to L<DBIx::Class>
1210(see L<SchemaIntro.pod>), but have an established class-based setup with lots
1211of existing classes that you don't want to move by hand. Try this nifty script
1212instead:
1213
1214 use MyDB;
1215 use SQL::Translator;
1216
1217 my $schema = MyDB->schema_instance;
2437a1e3 1218
d2f3e87b 1219 my $translator = SQL::Translator->new(
1220 debug => $debug || 0,
1221 trace => $trace || 0,
1222 no_comments => $no_comments || 0,
1223 show_warnings => $show_warnings || 0,
1224 add_drop_table => $add_drop_table || 0,
1225 validate => $validate || 0,
1226 parser_args => {
1227 'DBIx::Schema' => $schema,
1228 },
1229 producer_args => {
1230 'prefix' => 'My::Schema',
1231 },
1232 );
1233
1234 $translator->parser('SQL::Translator::Parser::DBIx::Class');
1235 $translator->producer('SQL::Translator::Producer::DBIx::Class::File');
1236
1237 my $output = $translator->translate(@args) or die
1238 "Error: " . $translator->error;
1239
1240 print $output;
2437a1e3 1241
d2f3e87b 1242You could use L<Module::Find> to search for all subclasses in the MyDB::*
1243namespace, which is currently left as an exercise for the reader.
2437a1e3 1244
d2f3e87b 1245=head1 OVERLOADING METHODS
086b93a2 1246
ab872312 1247L<DBIx::Class> uses the L<Class::C3> package, which provides for redispatch of
1248method calls, useful for things like default values and triggers. You have to
1249use calls to C<next::method> to overload methods. More information on using
1250L<Class::C3> with L<DBIx::Class> can be found in
086b93a2 1251L<DBIx::Class::Manual::Component>.
1252
d2f3e87b 1253=head2 Setting default values for a row
1254
1255It's as simple as overriding the C<new> method. Note the use of
1256C<next::method>.
1257
1258 sub new {
1259 my ( $class, $attrs ) = @_;
1260
1261 $attrs->{foo} = 'bar' unless defined $attrs->{foo};
1262
1263 my $new = $class->next::method($attrs);
1264
1265 return $new;
1266 }
1267
1268For more information about C<next::method>, look in the L<Class::C3>
1269documentation. See also L<DBIx::Class::Manual::Component> for more
1270ways to write your own base classes to do this.
1271
1272People looking for ways to do "triggers" with DBIx::Class are probably
1273just looking for this.
1274
1275=head2 Changing one field whenever another changes
086b93a2 1276
1277For example, say that you have three columns, C<id>, C<number>, and
1278C<squared>. You would like to make changes to C<number> and have
1279C<squared> be automagically set to the value of C<number> squared.
1280You can accomplish this by overriding C<store_column>:
1281
1282 sub store_column {
1283 my ( $self, $name, $value ) = @_;
1284 if ($name eq 'number') {
1285 $self->squared($value * $value);
1286 }
1287 $self->next::method($name, $value);
1288 }
1289
1290Note that the hard work is done by the call to C<next::method>, which
324572ca 1291redispatches your call to store_column in the superclass(es).
086b93a2 1292
d2f3e87b 1293=head2 Automatically creating related objects
086b93a2 1294
324572ca 1295You might have a class C<Artist> which has many C<CD>s. Further, if you
086b93a2 1296want to create a C<CD> object every time you insert an C<Artist> object.
ccbebdbc 1297You can accomplish this by overriding C<insert> on your objects:
086b93a2 1298
1299 sub insert {
ccbebdbc 1300 my ( $self, @args ) = @_;
1301 $self->next::method(@args);
086b93a2 1302 $self->cds->new({})->fill_from_artist($self)->insert;
1303 return $self;
1304 }
1305
1306where C<fill_from_artist> is a method you specify in C<CD> which sets
1307values in C<CD> based on the data in the C<Artist> object you pass in.
1308
d2f3e87b 1309=head2 Wrapping/overloading a column accessor
1310
1311B<Problem:>
1312
1313Say you have a table "Camera" and want to associate a description
1314with each camera. For most cameras, you'll be able to generate the description from
1315the other columns. However, in a few special cases you may want to associate a
1316custom description with a camera.
1317
1318B<Solution:>
1319
1320In your database schema, define a description field in the "Camera" table that
1321can contain text and null values.
1322
1323In DBIC, we'll overload the column accessor to provide a sane default if no
1324custom description is defined. The accessor will either return or generate the
1325description, depending on whether the field is null or not.
1326
1327First, in your "Camera" schema class, define the description field as follows:
1328
1329 __PACKAGE__->add_columns(description => { accessor => '_description' });
1330
1331Next, we'll define the accessor-wrapper subroutine:
1332
1333 sub description {
1334 my $self = shift;
1335
1336 # If there is an update to the column, we'll let the original accessor
1337 # deal with it.
1338 return $self->_description(@_) if @_;
1339
1340 # Fetch the column value.
1341 my $description = $self->_description;
1342
1343 # If there's something in the description field, then just return that.
1344 return $description if defined $description && length $descripton;
1345
1346 # Otherwise, generate a description.
1347 return $self->generate_description;
1348 }
1349
1350=head1 DEBUGGING AND PROFILING
1351
1352=head2 DBIx::Class objects with Data::Dumper
1def3451 1353
1354L<Data::Dumper> can be a very useful tool for debugging, but sometimes it can
1355be hard to find the pertinent data in all the data it can generate.
1356Specifically, if one naively tries to use it like so,
1357
1358 use Data::Dumper;
1359
1360 my $cd = $schema->resultset('CD')->find(1);
1361 print Dumper($cd);
1362
1363several pages worth of data from the CD object's schema and result source will
1364be dumped to the screen. Since usually one is only interested in a few column
1365values of the object, this is not very helpful.
1366
1367Luckily, it is possible to modify the data before L<Data::Dumper> outputs
1368it. Simply define a hook that L<Data::Dumper> will call on the object before
1369dumping it. For example,
1370
1371 package My::DB::CD;
1372
1373 sub _dumper_hook {
99fb1058 1374 $_[0] = bless {
1375 %{ $_[0] },
1def3451 1376 result_source => undef,
99fb1058 1377 }, ref($_[0]);
1def3451 1378 }
1379
1380 [...]
1381
1382 use Data::Dumper;
1383
22139027 1384 local $Data::Dumper::Freezer = '_dumper_hook';
1def3451 1385
1386 my $cd = $schema->resultset('CD')->find(1);
1387 print Dumper($cd);
1388 # dumps $cd without its ResultSource
1389
1390If the structure of your schema is such that there is a common base class for
1391all your table classes, simply put a method similar to C<_dumper_hook> in the
1392base class and set C<$Data::Dumper::Freezer> to its name and L<Data::Dumper>
1393will automagically clean up your data before printing it. See
1394L<Data::Dumper/EXAMPLES> for more information.
1395
4c248161 1396=head2 Profiling
1397
85f78622 1398When you enable L<DBIx::Class::Storage>'s debugging it prints the SQL
4c248161 1399executed as well as notifications of query completion and transaction
1400begin/commit. If you'd like to profile the SQL you can subclass the
1401L<DBIx::Class::Storage::Statistics> class and write your own profiling
1402mechanism:
1403
1404 package My::Profiler;
1405 use strict;
1406
1407 use base 'DBIx::Class::Storage::Statistics';
1408
1409 use Time::HiRes qw(time);
1410
1411 my $start;
1412
1413 sub query_start {
1414 my $self = shift();
1415 my $sql = shift();
1416 my $params = @_;
1417
70f39278 1418 $self->print("Executing $sql: ".join(', ', @params)."\n");
4c248161 1419 $start = time();
1420 }
1421
1422 sub query_end {
1423 my $self = shift();
1424 my $sql = shift();
1425 my @params = @_;
1426
70f39278 1427 my $elapsed = sprintf("%0.4f", time() - $start);
1428 $self->print("Execution took $elapsed seconds.\n");
4c248161 1429 $start = undef;
1430 }
1431
1432 1;
1433
1434You can then install that class as the debugging object:
1435
70f39278 1436 __PACKAGE__->storage->debugobj(new My::Profiler());
1437 __PACKAGE__->storage->debug(1);
4c248161 1438
1439A more complicated example might involve storing each execution of SQL in an
1440array:
1441
1442 sub query_end {
1443 my $self = shift();
1444 my $sql = shift();
1445 my @params = @_;
1446
1447 my $elapsed = time() - $start;
1448 push(@{ $calls{$sql} }, {
1449 params => \@params,
1450 elapsed => $elapsed
1451 });
1452 }
1453
1454You could then create average, high and low execution times for an SQL
1455statement and dig down to see if certain parameters cause aberrant behavior.
70f39278 1456You might want to check out L<DBIx::Class::QueryLog> as well.
4c248161 1457
7aaec96c 1458
40dbc108 1459=cut