fix doubling of find_related condition
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class.pm
CommitLineData
ea2e61bf 1package DBIx::Class;
2
5d283305 3use strict;
4use warnings;
5
f9cc85ce 6our $VERSION;
7# Always remember to do all digits for the version even if they're 0
8# i.e. first release of 0.XX *must* be 0.XX000. This avoids fBSD ports
9# brain damage and presumably various other packaging systems too
10
11# $VERSION declaration must stay up here, ahead of any other package
12# declarations, as to not confuse various modules attempting to determine
13# this ones version, whether that be s.c.o. or Module::Metadata, etc
4cc6b752 14$VERSION = '0.08192';
f9cc85ce 15
16$VERSION = eval $VERSION if $VERSION =~ /_/; # numify for warning-free dev releases
17
87bf71d5 18BEGIN {
e0b2dc74 19 package DBIx::Class::_ENV_;
20
87bf71d5 21 if ($] < 5.009_005) {
22 require MRO::Compat;
e0b2dc74 23 *OLD_MRO = sub () { 1 };
87bf71d5 24 }
25 else {
26 require mro;
e0b2dc74 27 *OLD_MRO = sub () { 0 };
87bf71d5 28 }
4bea1fe7 29
30 # ::Runmode would only be loaded by DBICTest, which in turn implies t/
e0b2dc74 31 *DBICTEST = eval { DBICTest::RunMode->is_author }
4bea1fe7 32 ? sub () { 1 }
33 : sub () { 0 }
34 ;
e0b2dc74 35
b4ad8a74 36 # There was a brief period of p5p insanity when $@ was invisible in a DESTROY
37 *INVISIBLE_DOLLAR_AT = ($] >= 5.013001 and $] <= 5.013007)
38 ? sub () { 1 }
39 : sub () { 0 }
40 ;
41
e0b2dc74 42 # During 5.13 dev cycle HELEMs started to leak on copy
43 *PEEPEENESS = (defined $ENV{DBICTEST_ALL_LEAKS}
44 # request for all tests would force "non-leaky" illusion and vice-versa
45 ? ! $ENV{DBICTEST_ALL_LEAKS}
46
47 # otherwise confess that this perl is busted ONLY on smokers
48 : do {
49 if (eval { DBICTest::RunMode->is_smoker }) {
50
51 # leaky 5.13.6 (fixed in blead/cefd5c7c)
52 if ($] == '5.013006') { 1 }
53
54 # not sure why this one leaks, but disable anyway - ANDK seems to make it weep
55 elsif ($] == '5.013005') { 1 }
56
57 else { 0 }
58 }
59 else { 0 }
60 }
61 ) ? sub () { 1 } : sub () { 0 };
b4ad8a74 62
87bf71d5 63}
64
d38cd95c 65use mro 'c3';
329d7385 66
2527233b 67use DBIx::Class::Optional::Dependencies;
68
db29433c 69use base qw/DBIx::Class::Componentised DBIx::Class::AccessorGroup/;
11736b4c 70use DBIx::Class::StartupCheck;
3e110410 71
70c28808 72__PACKAGE__->mk_group_accessors(inherited => '_skip_namespace_frames');
73__PACKAGE__->_skip_namespace_frames('^DBIx::Class|^SQL::Abstract|^Try::Tiny');
74
ade0fe3b 75sub mk_classdata {
77d518d1 76 shift->mk_classaccessor(@_);
77}
78
79sub mk_classaccessor {
80 my $self = shift;
ade0fe3b 81 $self->mk_group_accessors('inherited', $_[0]);
77d518d1 82 $self->set_inherited(@_) if @_ > 1;
3e110410 83}
3c0068c1 84
7411204b 85sub component_base_class { 'DBIx::Class' }
227d4dee 86
f0750722 87sub MODIFY_CODE_ATTRIBUTES {
b5d2c57f 88 my ($class,$code,@attrs) = @_;
89 $class->mk_classdata('__attr_cache' => {})
90 unless $class->can('__attr_cache');
91 $class->__attr_cache->{$code} = [@attrs];
92 return ();
f0750722 93}
94
da95b45f 95sub _attr_cache {
b5d2c57f 96 my $self = shift;
97 my $cache = $self->can('__attr_cache') ? $self->__attr_cache : {};
9780718f 98
99 return {
100 %$cache,
101 %{ $self->maybe::next::method || {} },
20674fcd 102 };
da95b45f 103}
104
ea2e61bf 1051;
34d52be2 106
75d07914 107=head1 NAME
34d52be2 108
7e4b2f59 109DBIx::Class - Extensible and flexible object <-> relational mapper.
34d52be2 110
3b1c2bbd 111=head1 GETTING HELP/SUPPORT
112
113The community can be found via:
114
a06e1181 115=over
3b1c2bbd 116
054235c6 117=item * Web Site: L<http://www.dbix-class.org/>
118
c6fdaf2a 119=item * IRC: irc.perl.org#dbix-class
120
121=for html
e3194e31 122<a href="http://chat.mibbit.com/#dbix-class@irc.perl.org">(click for instant chatroom login)</a>
3b1c2bbd 123
a06e1181 124=item * Mailing list: L<http://lists.scsys.co.uk/mailman/listinfo/dbix-class>
3b1c2bbd 125
a06e1181 126=item * RT Bug Tracker: L<https://rt.cpan.org/Dist/Display.html?Queue=DBIx-Class>
127
aeb669b8 128=item * gitweb: L<http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=dbsrgits/DBIx-Class.git>
a06e1181 129
aeb669b8 130=item * git: L<git://git.shadowcat.co.uk/dbsrgits/DBIx-Class.git>
a06e1181 131
43517a60 132=item * twitter L<http://www.twitter.com/dbix_class>
133
a06e1181 134=back
3b1c2bbd 135
34d52be2 136=head1 SYNOPSIS
137
03460bef 138Create a schema class called MyApp/Schema.pm:
34d52be2 139
03460bef 140 package MyApp::Schema;
a0638a7b 141 use base qw/DBIx::Class::Schema/;
34d52be2 142
f0bb26f3 143 __PACKAGE__->load_namespaces();
daec44b8 144
a0638a7b 145 1;
daec44b8 146
30e1753a 147Create a result class to represent artists, who have many CDs, in
03460bef 148MyApp/Schema/Result/Artist.pm:
daec44b8 149
30e1753a 150See L<DBIx::Class::ResultSource> for docs on defining result classes.
151
03460bef 152 package MyApp::Schema::Result::Artist;
d88ecca6 153 use base qw/DBIx::Class::Core/;
daec44b8 154
a0638a7b 155 __PACKAGE__->table('artist');
156 __PACKAGE__->add_columns(qw/ artistid name /);
157 __PACKAGE__->set_primary_key('artistid');
03460bef 158 __PACKAGE__->has_many(cds => 'MyApp::Schema::Result::CD');
daec44b8 159
a0638a7b 160 1;
daec44b8 161
30e1753a 162A result class to represent a CD, which belongs to an artist, in
03460bef 163MyApp/Schema/Result/CD.pm:
39fe0e65 164
03460bef 165 package MyApp::Schema::Result::CD;
d88ecca6 166 use base qw/DBIx::Class::Core/;
39fe0e65 167
d88ecca6 168 __PACKAGE__->load_components(qw/InflateColumn::DateTime/);
a0638a7b 169 __PACKAGE__->table('cd');
bd077b47 170 __PACKAGE__->add_columns(qw/ cdid artistid title year /);
a0638a7b 171 __PACKAGE__->set_primary_key('cdid');
03460bef 172 __PACKAGE__->belongs_to(artist => 'MyApp::Schema::Result::Artist', 'artistid');
39fe0e65 173
a0638a7b 174 1;
39fe0e65 175
a0638a7b 176Then you can use these classes in your application's code:
39fe0e65 177
a0638a7b 178 # Connect to your database.
03460bef 179 use MyApp::Schema;
180 my $schema = MyApp::Schema->connect($dbi_dsn, $user, $pass, \%dbi_params);
a0638a7b 181
182 # Query for all artists and put them in an array,
183 # or retrieve them as a result set object.
30e1753a 184 # $schema->resultset returns a DBIx::Class::ResultSet
2053ab2a 185 my @all_artists = $schema->resultset('Artist')->all;
186 my $all_artists_rs = $schema->resultset('Artist');
126042ee 187
30e1753a 188 # Output all artists names
4e8ffded 189 # $artist here is a DBIx::Class::Row, which has accessors
16ccb4fe 190 # for all its columns. Rows are also subclasses of your Result class.
85067746 191 foreach $artist (@all_artists) {
30e1753a 192 print $artist->name, "\n";
193 }
194
a0638a7b 195 # Create a result set to search for artists.
86beca1d 196 # This does not query the DB.
2053ab2a 197 my $johns_rs = $schema->resultset('Artist')->search(
6576ef54 198 # Build your WHERE using an SQL::Abstract structure:
2053ab2a 199 { name => { like => 'John%' } }
a0638a7b 200 );
39fe0e65 201
2053ab2a 202 # Execute a joined query to get the cds.
a0638a7b 203 my @all_john_cds = $johns_rs->search_related('cds')->all;
448c8424 204
f0bb26f3 205 # Fetch the next available row.
a0638a7b 206 my $first_john = $johns_rs->next;
448c8424 207
2053ab2a 208 # Specify ORDER BY on the query.
a0638a7b 209 my $first_john_cds_by_title_rs = $first_john->cds(
210 undef,
211 { order_by => 'title' }
212 );
448c8424 213
bd077b47 214 # Create a result set that will fetch the artist data
2053ab2a 215 # at the same time as it fetches CDs, using only one query.
884559b1 216 my $millennium_cds_rs = $schema->resultset('CD')->search(
a0638a7b 217 { year => 2000 },
218 { prefetch => 'artist' }
219 );
448c8424 220
880a1a0c 221 my $cd = $millennium_cds_rs->next; # SELECT ... FROM cds JOIN artists ...
bd077b47 222 my $cd_artist_name = $cd->artist->name; # Already has the data so no 2nd query
076652e8 223
264f1571 224 # new() makes a DBIx::Class::Row object but doesnt insert it into the DB.
225 # create() is the same as new() then insert().
884559b1 226 my $new_cd = $schema->resultset('CD')->new({ title => 'Spoon' });
f183eccd 227 $new_cd->artist($cd->artist);
f183eccd 228 $new_cd->insert; # Auto-increment primary key filled in after INSERT
f183eccd 229 $new_cd->title('Fork');
230
884559b1 231 $schema->txn_do(sub { $new_cd->update }); # Runs the update in a transaction
f183eccd 232
bd077b47 233 # change the year of all the millennium CDs at once
234 $millennium_cds_rs->update({ year => 2002 });
f183eccd 235
236=head1 DESCRIPTION
237
238This is an SQL to OO mapper with an object API inspired by L<Class::DBI>
bd077b47 239(with a compatibility layer as a springboard for porting) and a resultset API
f183eccd 240that allows abstract encapsulation of database operations. It aims to make
241representing queries in your code as perl-ish as possible while still
a0638a7b 242providing access to as many of the capabilities of the database as possible,
f183eccd 243including retrieving related records from multiple tables in a single query,
bd077b47 244JOIN, LEFT JOIN, COUNT, DISTINCT, GROUP BY, ORDER BY and HAVING support.
f183eccd 245
246DBIx::Class can handle multi-column primary and foreign keys, complex
247queries and database-level paging, and does its best to only query the
75d07914 248database in order to return something you've directly asked for. If a
249resultset is used as an iterator it only fetches rows off the statement
250handle as requested in order to minimise memory usage. It has auto-increment
2053ab2a 251support for SQLite, MySQL, PostgreSQL, Oracle, SQL Server and DB2 and is
252known to be used in production on at least the first four, and is fork-
ec6415a9 253and thread-safe out of the box (although
254L<your DBD may not be|DBI/Threads_and_Thread_Safety>).
f183eccd 255
dfccde48 256This project is still under rapid development, so large new features may be
257marked EXPERIMENTAL - such APIs are still usable but may have edge bugs.
258Failing test cases are *always* welcome and point releases are put out rapidly
259as bugs are found and fixed.
260
261We do our best to maintain full backwards compatibility for published
262APIs, since DBIx::Class is used in production in many organisations,
263and even backwards incompatible changes to non-published APIs will be fixed
264if they're reported and doing so doesn't cost the codebase anything.
265
264f1571 266The test suite is quite substantial, and several developer releases
267are generally made to CPAN before the branch for the next release is
268merged back to trunk for a major release.
f183eccd 269
f183eccd 270=head1 WHERE TO GO NEXT
271
2ca930b4 272L<DBIx::Class::Manual::DocMap> lists each task you might want help on, and
273the modules where you will find documentation.
076652e8 274
3942ab4d 275=head1 AUTHOR
34d52be2 276
266bdcc3 277mst: Matt S. Trout <mst@shadowcatsystems.co.uk>
34d52be2 278
dfccde48 279(I mostly consider myself "project founder" these days but the AUTHOR heading
280is traditional :)
281
3942ab4d 282=head1 CONTRIBUTORS
283
907ed671 284abraxxa: Alexander Hartmaier <abraxxa@cpan.org>
84e3c114 285
fd4b0742 286acca: Alexander Kuznetsov <acca@cpan.org>
287
6d84db2c 288aherzog: Adam Herzog <adam@herzogdesigns.com>
289
daeb1865 290Alexander Keusch <cpan@keusch.at>
291
630ba6e5 292alnewkirk: Al Newkirk <we@ana.im>
293
6ebf5cbb 294amiri: Amiri Barksdale <amiri@metalabel.com>
295
b703fec7 296amoore: Andrew Moore <amoore@cpan.org>
297
266bdcc3 298andyg: Andy Grundman <andy@hybridized.org>
3942ab4d 299
266bdcc3 300ank: Andres Kievsky
3942ab4d 301
59ac6523 302arc: Aaron Crane <arc@cpan.org>
303
624764ae 304arcanez: Justin Hunter <justin.d.hunter@gmail.com>
305
ce4c07df 306ash: Ash Berlin <ash@cpan.org>
307
3d5bd2af 308bert: Norbert Csongradi <bert@cpan.org>
309
967a4c40 310blblack: Brandon L. Black <blblack@gmail.com>
3942ab4d 311
62eb8fe8 312bluefeet: Aran Deltac <bluefeet@cpan.org>
313
d6170b26 314bphillips: Brian Phillips <bphillips@cpan.org>
315
f856fe01 316boghead: Bryan Beeley <cpan@beeley.org>
317
bcb8f3ed 318bricas: Brian Cassidy <bricas@cpan.org>
319
3d7e3e05 320brunov: Bruno Vecchi <vecchi.b@gmail.com>
321
281719d2 322caelum: Rafael Kitover <rkitover@cpan.org>
323
f5f2af8f 324caldrin: Maik Hentsche <maik.hentsche@amd.com>
325
d3b0e369 326castaway: Jess Robinson
3942ab4d 327
266bdcc3 328claco: Christopher H. Laco
ccb9c9b1 329
266bdcc3 330clkao: CL Kao
3942ab4d 331
e21dfd6a 332da5id: David Jack Olrik <djo@cpan.org>
18360aed 333
13de943d 334debolaz: Anders Nor Berle <berle@cpan.org>
335
d1f542db 336dew: Dan Thomas <dan@godders.org>
337
266bdcc3 338dkubb: Dan Kubb <dan.kubb-cpan@onautopilot.com>
ccb9c9b1 339
9382ad07 340dnm: Justin Wheeler <jwheeler@datademons.com>
341
0818c9a7 342dpetrov: Dimitar Petrov <mitakaa@gmail.com>
343
266bdcc3 344dwc: Daniel Westermann-Clark <danieltwc@cpan.org>
4685e006 345
5cffe785 346dyfrgi: Michael Leuchtenburg <michael@slashhome.org>
8fe164b9 347
307f1265 348felliott: Fitz Elliott <fitz.elliott@gmail.com>
349
0ffada27 350freetime: Bill Moseley <moseley@hank.org>
351
ade0fe3b 352frew: Arthur Axel "fREW" Schmidt <frioux@gmail.com>
353
b4987ed0 354goraxe: Gordon Irving <goraxe@cpan.org>
355
d3b0e369 356gphat: Cory G Watson <gphat@cpan.org>
ad3d2d7c 357
61f031bf 358Grant Street Group L<http://www.grantstreet.com/>
359
e758ffe6 360groditi: Guillermo Roditi <groditi@cpan.org>
361
6dad89f5 362Haarg: Graham Knop <haarg@haarg.org>
363
157ce0cf 364hobbs: Andrew Rodland <arodland@cpan.org>
365
5d779578 366ilmari: Dagfinn Ilmari MannsE<aring>ker <ilmari@ilmari.org>
367
0ac0af6c 368initself: Mike Baas <mike@initselftech.com>
369
2bb4c37b 370ironcamel: Naveed Massjouni <naveedm9@gmail.com>
371
f165eda8 372jawnsy: Jonathan Yu <jawnsy@cpan.org>
373
bee21976 374jasonmay: Jason May <jason.a.may@gmail.com>
375
d3b0e369 376jesper: Jesper Krogh
5fb0c64c 377
4a743a00 378jgoulah: John Goulah <jgoulah@cpan.org>
379
102a2984 380jguenther: Justin Guenther <jguenther@cpan.org>
d7c4c15c 381
a14a46e2 382jhannah: Jay Hannah <jay@jays.net>
383
8b93a938 384jnapiorkowski: John Napiorkowski <jjn1056@yahoo.com>
385
11736b4c 386jon: Jon Schutz <jjschutz@cpan.org>
387
1aec4bac 388jshirley: J. Shirley <jshirley@gmail.com>
389
41519379 390kaare: Kaare Rasmussen
391
d3b0e369 392konobi: Scott McWhirter
535fc2ee 393
4e0a89e4 394littlesavage: Alexey Illarionov <littlesavage@orionet.ru>
395
4367679a 396lukes: Luke Saunders <luke.saunders@gmail.com>
397
709ea492 398marcus: Marcus Ramberg <mramberg@cpan.org>
399
114780ee 400mattlaw: Matt Lawrence
401
45bffdf0 402mattp: Matt Phillips <mattp@cpan.org>
403
58755bba 404michaelr: Michael Reddick <michael.reddick@gmail.com>
405
91d0c99f 406milki: Jonathan Chu <milki@rescomp.berkeley.edu>
407
77e7e47d 408ned: Neil de Carteret
409
266bdcc3 410nigel: Nigel Metheringham <nigelm@cpan.org>
6565b410 411
d3b0e369 412ningu: David Kamholz <dkamholz@cpan.org>
413
66cf3a84 414Nniuq: Ron "Quinn" Straight" <quinnfazigu@gmail.org>
415
20b4c148 416norbi: Norbert Buchmuller <norbi@nix.hu>
417
48580715 418nuba: Nuba Princigalli <nuba@cpan.org>
419
d3b0e369 420Numa: Dan Sully <daniel@cpan.org>
421
dc571b76 422ovid: Curtis "Ovid" Poe <ovid@cpan.org>
423
bf356c54 424oyse: Øystein Torget <oystein.torget@dnv.com>
425
266bdcc3 426paulm: Paul Makepeace
4763f4b7 427
d3b0e369 428penguin: K J Cheetham
429
8cfef6f5 430perigrin: Chris Prather <chris@prather.org>
431
14899528 432peter: Peter Collingbourne <peter@pcc.me.uk>
caac1708 433
266bdcc3 434phaylon: Robert Sedlacek <phaylon@dunkelheit.at>
a53b95f1 435
56fadd8f 436plu: Johannes Plunien <plu@cpan.org>
437
0c1a4a15 438Possum: Daniel LeWarne <possum@cpan.org>
439
d3b0e369 440quicksilver: Jules Bean
022e0893 441
4ed01b34 442rafl: Florian Ragwitz <rafl@debian.org>
443
0c1a4a15 444rainboxx: Matthias Dietrich <perl@rb.ly>
445
868a7b26 446rbo: Robert Bohne <rbo@cpan.org>
447
7ff0dace 448rbuels: Robert Buels <rmb32@cornell.edu>
449
0da8b7da 450rdj: Ryan D Johnson <ryan@innerfence.com>
451
66b1e361 452ribasushi: Peter Rabbitson <ribasushi@cpan.org>
d76e282a 453
b487918c 454rjbs: Ricardo Signes <rjbs@cpan.org>
455
6ffb5be5 456robkinyon: Rob Kinyon <rkinyon@cpan.org>
457
726c8f65 458Robert Olson <bob@rdolson.org>
459
e4c9f3f0 460Roman: Roman Filippov <romanf@cpan.org>
461
dc81dba3 462Sadrak: Felix Antonius Wilhelm Ostmann <sadrak@cpan.org>
463
d3b0e369 464sc_: Just Another Perl Hacker
ba606e58 465
266bdcc3 466scotty: Scotty Allen <scotty@scottyallen.com>
181a28f4 467
1c133e22 468semifor: Marc Mims <marc@questright.com>
469
20b4c148 470solomon: Jared Johnson <jaredj@nmgi.com>
471
88f937fb 472spb: Stephen Bennett <stephen@freenode.net>
473
59187a3b 474Squeeks <squeek@cpan.org>
475
637ca936 476sszabo: Stephan Szabo <sszabo@bigpanda.com>
477
a9e8284f 478talexb: Alex Beamish <talexb@gmail.com>
479
7bf0d0d6 480tamias: Ronald J Kimball <rjk@tamias.net>
f92a9d79 481
386c2272 482teejay : Aaron Trevena <teejay@cpan.org>
483
84e3c114 484Todd Lipcon
e063fe2c 485
6eb6264e 486Tom Hukins
487
2e4b6d78 488tonvoon: Ton Voon <tonvoon@cpan.org>
489
d15e3fc5 490triode: Pete Gamache <gamache@cpan.org>
491
d3b0e369 492typester: Daisuke Murase <typester@cpan.org>
c0e7b4e5 493
4740bdb7 494victori: Victor Igumnov <victori@cpan.org>
495
d3b0e369 496wdh: Will Hawes
4c248161 497
00c03ced 498willert: Sebastian Willert <willert@cpan.org>
499
66d2a14e 500wreis: Wallace Reis <wreis@cpan.org>
501
d52d4d6e 502yrlnry: Mark Jason Dominus <mjd@plover.com>
503
d3b0e369 504zamolxes: Bogdan Lucaciu <bogdan@wiz.ro>
78060df8 505
b38e10bd 506=head1 COPYRIGHT
507
48580715 508Copyright (c) 2005 - 2010 the DBIx::Class L</AUTHOR> and L</CONTRIBUTORS>
b38e10bd 509as listed above.
510
96154ef7 511=head1 LICENSE
512
513This library is free software and may be distributed under the same terms
514as perl itself.
515
34d52be2 516=cut