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