f8bb0e44a0e8b5088aacbcfca87e4fda51a58504
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class.pm
1 package DBIx::Class;
2
3 use strict;
4 use warnings;
5
6 use MRO::Compat;
7 use mro 'c3';
8
9 use DBIx::Class::Optional::Dependencies;
10
11 use vars qw($VERSION);
12 use base qw/DBIx::Class::Componentised Class::Accessor::Grouped/;
13 use DBIx::Class::StartupCheck;
14 use Try::Tiny;
15
16 sub mk_classdata {
17   shift->mk_classaccessor(@_);
18 }
19
20 sub mk_classaccessor {
21   my $self = shift;
22   $self->mk_group_accessors('inherited', $_[0]);
23   $self->set_inherited(@_) if @_ > 1;
24 }
25
26 sub component_base_class { 'DBIx::Class' }
27
28 # Always remember to do all digits for the version even if they're 0
29 # i.e. first release of 0.XX *must* be 0.XX000. This avoids fBSD ports
30 # brain damage and presumably various other packaging systems too
31 $VERSION = '0.08121_01';
32
33 $VERSION = eval $VERSION if $VERSION =~ /_/; # numify for warning-free dev releases
34
35 sub MODIFY_CODE_ATTRIBUTES {
36   my ($class,$code,@attrs) = @_;
37   $class->mk_classdata('__attr_cache' => {})
38     unless $class->can('__attr_cache');
39   $class->__attr_cache->{$code} = [@attrs];
40   return ();
41 }
42
43 sub _attr_cache {
44   my $self = shift;
45   my $cache = $self->can('__attr_cache') ? $self->__attr_cache : {};
46
47   return {
48     %$cache,
49     %{ $self->maybe::next::method || {} },
50   };
51 }
52
53 1;
54
55 =head1 NAME
56
57 DBIx::Class - Extensible and flexible object <-> relational mapper.
58
59 =head1 GETTING HELP/SUPPORT
60
61 The community can be found via:
62
63 =over
64
65 =item * IRC: L<irc.perl.org#dbix-class (click for instant chatroom login)
66 |http://mibbit.com/chat/#dbix-class@irc.perl.org>
67
68 =item * Mailing list: L<http://lists.scsys.co.uk/mailman/listinfo/dbix-class>
69
70 =item * RT Bug Tracker: L<https://rt.cpan.org/Dist/Display.html?Queue=DBIx-Class>
71
72 =item * SVNWeb: L<http://dev.catalyst.perl.org/svnweb/bast/browse/DBIx-Class/0.08>
73
74 =item * SVN: L<http://dev.catalyst.perl.org/repos/bast/DBIx-Class/0.08>
75
76 =back
77
78 =head1 SYNOPSIS
79
80 Create a schema class called MyDB/Schema.pm:
81
82   package MyDB::Schema;
83   use base qw/DBIx::Class::Schema/;
84
85   __PACKAGE__->load_namespaces();
86
87   1;
88
89 Create a result class to represent artists, who have many CDs, in
90 MyDB/Schema/Result/Artist.pm:
91
92 See L<DBIx::Class::ResultSource> for docs on defining result classes.
93
94   package MyDB::Schema::Result::Artist;
95   use base qw/DBIx::Class::Core/;
96
97   __PACKAGE__->table('artist');
98   __PACKAGE__->add_columns(qw/ artistid name /);
99   __PACKAGE__->set_primary_key('artistid');
100   __PACKAGE__->has_many(cds => 'MyDB::Schema::Result::CD');
101
102   1;
103
104 A result class to represent a CD, which belongs to an artist, in
105 MyDB/Schema/Result/CD.pm:
106
107   package MyDB::Schema::Result::CD;
108   use base qw/DBIx::Class::Core/;
109
110   __PACKAGE__->load_components(qw/InflateColumn::DateTime/);
111   __PACKAGE__->table('cd');
112   __PACKAGE__->add_columns(qw/ cdid artistid title year /);
113   __PACKAGE__->set_primary_key('cdid');
114   __PACKAGE__->belongs_to(artist => 'MyDB::Schema::Artist', 'artistid');
115
116   1;
117
118 Then you can use these classes in your application's code:
119
120   # Connect to your database.
121   use MyDB::Schema;
122   my $schema = MyDB::Schema->connect($dbi_dsn, $user, $pass, \%dbi_params);
123
124   # Query for all artists and put them in an array,
125   # or retrieve them as a result set object.
126   # $schema->resultset returns a DBIx::Class::ResultSet
127   my @all_artists = $schema->resultset('Artist')->all;
128   my $all_artists_rs = $schema->resultset('Artist');
129
130   # Output all artists names
131   # $artist here is a DBIx::Class::Row, which has accessors
132   # for all its columns. Rows are also subclasses of your Result class.
133   foreach $artist (@all_artists) {
134     print $artist->name, "\n";
135   }
136
137   # Create a result set to search for artists.
138   # This does not query the DB.
139   my $johns_rs = $schema->resultset('Artist')->search(
140     # Build your WHERE using an SQL::Abstract structure:
141     { name => { like => 'John%' } }
142   );
143
144   # Execute a joined query to get the cds.
145   my @all_john_cds = $johns_rs->search_related('cds')->all;
146
147   # Fetch the next available row.
148   my $first_john = $johns_rs->next;
149
150   # Specify ORDER BY on the query.
151   my $first_john_cds_by_title_rs = $first_john->cds(
152     undef,
153     { order_by => 'title' }
154   );
155
156   # Create a result set that will fetch the artist data
157   # at the same time as it fetches CDs, using only one query.
158   my $millennium_cds_rs = $schema->resultset('CD')->search(
159     { year => 2000 },
160     { prefetch => 'artist' }
161   );
162
163   my $cd = $millennium_cds_rs->next; # SELECT ... FROM cds JOIN artists ...
164   my $cd_artist_name = $cd->artist->name; # Already has the data so no 2nd query
165
166   # new() makes a DBIx::Class::Row object but doesnt insert it into the DB.
167   # create() is the same as new() then insert().
168   my $new_cd = $schema->resultset('CD')->new({ title => 'Spoon' });
169   $new_cd->artist($cd->artist);
170   $new_cd->insert; # Auto-increment primary key filled in after INSERT
171   $new_cd->title('Fork');
172
173   $schema->txn_do(sub { $new_cd->update }); # Runs the update in a transaction
174
175   # change the year of all the millennium CDs at once
176   $millennium_cds_rs->update({ year => 2002 });
177
178 =head1 DESCRIPTION
179
180 This is an SQL to OO mapper with an object API inspired by L<Class::DBI>
181 (with a compatibility layer as a springboard for porting) and a resultset API
182 that allows abstract encapsulation of database operations. It aims to make
183 representing queries in your code as perl-ish as possible while still
184 providing access to as many of the capabilities of the database as possible,
185 including retrieving related records from multiple tables in a single query,
186 JOIN, LEFT JOIN, COUNT, DISTINCT, GROUP BY, ORDER BY and HAVING support.
187
188 DBIx::Class can handle multi-column primary and foreign keys, complex
189 queries and database-level paging, and does its best to only query the
190 database in order to return something you've directly asked for. If a
191 resultset is used as an iterator it only fetches rows off the statement
192 handle as requested in order to minimise memory usage. It has auto-increment
193 support for SQLite, MySQL, PostgreSQL, Oracle, SQL Server and DB2 and is
194 known to be used in production on at least the first four, and is fork-
195 and thread-safe out of the box (although your DBD may not be).
196
197 This project is still under rapid development, so large new features may be
198 marked EXPERIMENTAL - such APIs are still usable but may have edge bugs.
199 Failing test cases are *always* welcome and point releases are put out rapidly
200 as bugs are found and fixed.
201
202 We do our best to maintain full backwards compatibility for published
203 APIs, since DBIx::Class is used in production in many organisations,
204 and even backwards incompatible changes to non-published APIs will be fixed
205 if they're reported and doing so doesn't cost the codebase anything.
206
207 The test suite is quite substantial, and several developer releases
208 are generally made to CPAN before the branch for the next release is
209 merged back to trunk for a major release.
210
211 =head1 WHERE TO GO NEXT
212
213 L<DBIx::Class::Manual::DocMap> lists each task you might want help on, and
214 the modules where you will find documentation.
215
216 =head1 AUTHOR
217
218 mst: Matt S. Trout <mst@shadowcatsystems.co.uk>
219
220 (I mostly consider myself "project founder" these days but the AUTHOR heading
221 is traditional :)
222
223 =head1 CONTRIBUTORS
224
225 abraxxa: Alexander Hartmaier <abraxxa@cpan.org>
226
227 aherzog: Adam Herzog <adam@herzogdesigns.com>
228
229 amoore: Andrew Moore <amoore@cpan.org>
230
231 andyg: Andy Grundman <andy@hybridized.org>
232
233 ank: Andres Kievsky
234
235 arcanez: Justin Hunter <justin.d.hunter@gmail.com>
236
237 ash: Ash Berlin <ash@cpan.org>
238
239 bert: Norbert Csongradi <bert@cpan.org>
240
241 blblack: Brandon L. Black <blblack@gmail.com>
242
243 bluefeet: Aran Deltac <bluefeet@cpan.org>
244
245 boghead: Bryan Beeley <cpan@beeley.org>
246
247 bricas: Brian Cassidy <bricas@cpan.org>
248
249 brunov: Bruno Vecchi <vecchi.b@gmail.com>
250
251 caelum: Rafael Kitover <rkitover@cpan.org>
252
253 castaway: Jess Robinson
254
255 claco: Christopher H. Laco
256
257 clkao: CL Kao
258
259 da5id: David Jack Olrik <djo@cpan.org>
260
261 debolaz: Anders Nor Berle <berle@cpan.org>
262
263 dew: Dan Thomas <dan@godders.org>
264
265 dkubb: Dan Kubb <dan.kubb-cpan@onautopilot.com>
266
267 dnm: Justin Wheeler <jwheeler@datademons.com>
268
269 dpetrov: Dimitar Petrov <mitakaa@gmail.com>
270
271 dwc: Daniel Westermann-Clark <danieltwc@cpan.org>
272
273 dyfrgi: Michael Leuchtenburg <michael@slashhome.org>
274
275 frew: Arthur Axel "fREW" Schmidt <frioux@gmail.com>
276
277 goraxe: Gordon Irving <goraxe@cpan.org>
278
279 gphat: Cory G Watson <gphat@cpan.org>
280
281 groditi: Guillermo Roditi <groditi@cpan.org>
282
283 hobbs: Andrew Rodland <arodland@cpan.org>
284
285 ilmari: Dagfinn Ilmari MannsE<aring>ker <ilmari@ilmari.org>
286
287 jasonmay: Jason May <jason.a.may@gmail.com>
288
289 jesper: Jesper Krogh
290
291 jgoulah: John Goulah <jgoulah@cpan.org>
292
293 jguenther: Justin Guenther <jguenther@cpan.org>
294
295 jhannah: Jay Hannah <jay@jays.net>
296
297 jnapiorkowski: John Napiorkowski <jjn1056@yahoo.com>
298
299 jon: Jon Schutz <jjschutz@cpan.org>
300
301 jshirley: J. Shirley <jshirley@gmail.com>
302
303 konobi: Scott McWhirter
304
305 lukes: Luke Saunders <luke.saunders@gmail.com>
306
307 marcus: Marcus Ramberg <mramberg@cpan.org>
308
309 mattlaw: Matt Lawrence
310
311 michaelr: Michael Reddick <michael.reddick@gmail.com>
312
313 ned: Neil de Carteret
314
315 nigel: Nigel Metheringham <nigelm@cpan.org>
316
317 ningu: David Kamholz <dkamholz@cpan.org>
318
319 Nniuq: Ron "Quinn" Straight" <quinnfazigu@gmail.org>
320
321 norbi: Norbert Buchmuller <norbi@nix.hu>
322
323 nuba: Nuba Princigalli <nuba@cpan.org>
324
325 Numa: Dan Sully <daniel@cpan.org>
326
327 ovid: Curtis "Ovid" Poe <ovid@cpan.org>
328
329 oyse: Ã˜ystein Torget <oystein.torget@dnv.com>
330
331 paulm: Paul Makepeace
332
333 penguin: K J Cheetham
334
335 perigrin: Chris Prather <chris@prather.org>
336
337 peter: Peter Collingbourne <peter@pcc.me.uk>
338
339 phaylon: Robert Sedlacek <phaylon@dunkelheit.at>
340
341 plu: Johannes Plunien <plu@cpan.org>
342
343 quicksilver: Jules Bean
344
345 rafl: Florian Ragwitz <rafl@debian.org>
346
347 rbuels: Robert Buels <rmb32@cornell.edu>
348
349 rdj: Ryan D Johnson <ryan@innerfence.com>
350
351 ribasushi: Peter Rabbitson <ribasushi@cpan.org>
352
353 rjbs: Ricardo Signes <rjbs@cpan.org>
354
355 robkinyon: Rob Kinyon <rkinyon@cpan.org>
356
357 Roman: Roman Filippov <romanf@cpan.org>
358
359 sc_: Just Another Perl Hacker
360
361 scotty: Scotty Allen <scotty@scottyallen.com>
362
363 semifor: Marc Mims <marc@questright.com>
364
365 solomon: Jared Johnson <jaredj@nmgi.com>
366
367 spb: Stephen Bennett <stephen@freenode.net>
368
369 sszabo: Stephan Szabo <sszabo@bigpanda.com>
370
371 teejay : Aaron Trevena <teejay@cpan.org>
372
373 Todd Lipcon
374
375 Tom Hukins
376
377 tonvoon: Ton Voon <tonvoon@cpan.org>
378
379 triode: Pete Gamache <gamache@cpan.org>
380
381 typester: Daisuke Murase <typester@cpan.org>
382
383 victori: Victor Igumnov <victori@cpan.org>
384
385 wdh: Will Hawes
386
387 willert: Sebastian Willert <willert@cpan.org>
388
389 wreis: Wallace Reis <wreis@cpan.org>
390
391 zamolxes: Bogdan Lucaciu <bogdan@wiz.ro>
392
393 Possum: Daniel LeWarne <possum@cpan.org>
394
395 =head1 COPYRIGHT
396
397 Copyright (c) 2005 - 2010 the DBIx::Class L</AUTHOR> and L</CONTRIBUTORS>
398 as listed above.
399
400 =head1 LICENSE
401
402 This library is free software and may be distributed under the same terms
403 as perl itself.
404
405 =cut