Bumping version to 0.07048_01
[dbsrgits/DBIx-Class-Schema-Loader.git] / lib / DBIx / Class / Schema / Loader.pm
CommitLineData
18fca96a 1package DBIx::Class::Schema::Loader;
a78e3fed 2
3use strict;
a4a19f3c 4use warnings;
65e705c3 5use base qw/DBIx::Class::Schema Class::Accessor::Grouped/;
cc15b78f 6use MRO::Compat;
942bd5e0 7use mro 'c3';
39d5612f 8use Carp::Clan qw/^DBIx::Class/;
9use Scalar::Util 'weaken';
ecf22f0a 10use Sub::Util 'set_subname';
7ba9582a 11use DBIx::Class::Schema::Loader::Utils qw/array_eq sigwarn_silencer/;
23fd9773 12use Try::Tiny;
f3bed1f1 13use curry;
39d5612f 14use namespace::clean;
3980d69c 15
a4a19f3c 16# Always remember to do all digits for the version even if they're 0
17# i.e. first release of 0.XX *must* be 0.XX000. This avoids fBSD ports
18# brain damage and presumably various other packaging systems too
46564a42 19our $VERSION = '0.07048_01';
457eb8a6 20
65e705c3 21__PACKAGE__->mk_group_accessors('inherited', qw/
22 _loader_args
23 dump_to_dir
24 _loader_invoked
25 _loader
26 loader_class
27 naming
f22644d7 28 use_namespaces
a8d229ff 29/);
65e705c3 30__PACKAGE__->_loader_args({});
a78e3fed 31
50799170 32=encoding UTF-8
41bc1375 33
a78e3fed 34=head1 NAME
35
227cea92 36DBIx::Class::Schema::Loader - Create a DBIx::Class::Schema based on a database
a78e3fed 37
38=head1 SYNOPSIS
39
83bce685 40 ### use this module to generate a set of class files
41
42 # in a script
43 use DBIx::Class::Schema::Loader qw/ make_schema_at /;
44 make_schema_at(
45 'My::Schema',
46 { debug => 1,
47 dump_directory => './lib',
48 },
49 [ 'dbi:Pg:dbname="foo"', 'myuser', 'mypassword',
50 { loader_class => 'MyLoader' } # optionally
51 ],
52 );
53
54 # from the command line or a shell script with dbicdump (distributed
55 # with this module). Do `perldoc dbicdump` for usage.
56 dbicdump -o dump_directory=./lib \
57 -o components='["InflateColumn::DateTime"]' \
58 -o debug=1 \
59 My::Schema \
60 'dbi:Pg:dbname=foo' \
61 myuser \
62 mypassword
63
64 ### or generate and load classes at runtime
65 # note: this technique is not recommended
66 # for use in production code
67
68 package My::Schema;
69 use base qw/DBIx::Class::Schema::Loader/;
70
71 __PACKAGE__->loader_options(
72 constraint => '^foo.*',
73 # debug => 1,
74 );
75
76 #### in application code elsewhere:
77
78 use My::Schema;
79
80 my $schema1 = My::Schema->connect( $dsn, $user, $password, $attrs);
81 # -or-
82 my $schema1 = "My::Schema"; $schema1->connection(as above);
074e81cd 83
41bc1375 84=head1 DESCRIPTION
074e81cd 85
fbd83464 86DBIx::Class::Schema::Loader automates the definition of a
227cea92 87L<DBIx::Class::Schema> by scanning database table definitions and setting up
88the columns, primary keys, unique constraints and relationships.
a78e3fed 89
700658a5 90See L<dbicdump> for the C<dbicdump> utility.
91
227cea92 92DBIx::Class::Schema::Loader currently supports only the DBI storage type. It
1065db64 93has explicit support for L<DBD::Pg>, L<DBD::mysql>, L<DBD::DB2>,
227cea92 94L<DBD::Firebird>, L<DBD::InterBase>, L<DBD::Informix>, L<DBD::SQLAnywhere>,
6b0e47fc 95L<DBD::SQLite>, L<DBD::Sybase> (for Sybase ASE and MSSSQL), L<DBD::ODBC> (for
227cea92 96MSSQL, MSAccess, Firebird and SQL Anywhere) L<DBD::ADO> (for MSSQL and
97MSAccess) and L<DBD::Oracle>. Other DBI drivers may function to a greater or
6b0e47fc 98lesser degree with this loader, depending on how much of the DBI spec they
99implement, and how standard their implementation is.
3fe9c5d9 100
101Patches to make other DBDs work correctly welcome.
a78e3fed 102
996be9ee 103See L<DBIx::Class::Schema::Loader::DBI::Writing> for notes on writing
104your own vendor-specific subclass for an unsupported DBD driver.
a78e3fed 105
227cea92 106This module requires L<DBIx::Class> 0.08127 or later, and obsoletes the older
107L<DBIx::Class::Loader>.
89ecd854 108
227cea92 109See L<DBIx::Class::Schema::Loader::Base> for available options.
89ecd854 110
a78e3fed 111=head1 METHODS
112
39d5612f 113=head2 loader
114
227cea92 115The loader object, as class data on your Schema. For methods available see
116L<DBIx::Class::Schema::Loader::Base> and L<DBIx::Class::Schema::Loader::DBI>.
39d5612f 117
118=cut
119
120sub loader {
121 my $self = shift;
122 $self->_loader(@_);
123}
124
29ddb54c 125=head2 loader_class
126
530e0bf6 127=over 4
128
129=item Argument: $loader_class
130
131=back
132
29ddb54c 133Set the loader class to be instantiated when L</connection> is called.
134If the classname starts with "::", "DBIx::Class::Schema::Loader" is
135prepended. Defaults to L<DBIx::Class::Schema/storage_type> (which must
136start with "::" when using L<DBIx::Class::Schema::Loader>).
137
138This is mostly useful for subclassing existing loaders or in conjunction
139with L</dump_to_dir>.
140
996be9ee 141=head2 loader_options
a78e3fed 142
530e0bf6 143=over 4
144
145=item Argument: \%loader_options
146
147=back
148
996be9ee 149Example in Synopsis above demonstrates a few common arguments. For
150detailed information on all of the arguments, most of which are
151only useful in fairly complex scenarios, see the
152L<DBIx::Class::Schema::Loader::Base> documentation.
a78e3fed 153
3fe9c5d9 154If you intend to use C<loader_options>, you must call
155C<loader_options> before any connection is made, or embed the
156C<loader_options> in the connection information itself as shown
157below. Setting C<loader_options> after the connection has
59cfa251 158already been made is useless.
a78e3fed 159
996be9ee 160=cut
1031d4f6 161
996be9ee 162sub loader_options {
163 my $self = shift;
65e705c3 164
d65cda9e 165 my %args = (ref $_[0] eq 'HASH') ? %{$_[0]} : @_;
996be9ee 166 $self->_loader_args(\%args);
996be9ee 167
168 $self;
169}
170
171sub _invoke_loader {
172 my $self = shift;
173 my $class = ref $self || $self;
174
59cfa251 175 my $args = $self->_loader_args;
176
23fd9773 177 # temporarily copy $self's storage to class
178 my $class_storage = $class->storage;
179 if (ref $self) {
180 $class->storage($self->storage);
181 $class->storage->set_schema($class);
182 }
183
184 $args->{schema} = $class;
59cfa251 185 $args->{schema_class} = $class;
59cfa251 186 $args->{dump_directory} ||= $self->dump_to_dir;
a0e0a56a 187 $args->{naming} = $self->naming if $self->naming;
42ea7b88 188 $args->{use_namespaces} = $self->use_namespaces if defined $self->use_namespaces;
af6c2665 189
71a6e88a 190 my $loader_class = $self->loader_class;
191 if ($loader_class) {
192 $loader_class = "DBIx::Class::Schema::Loader${loader_class}" if $loader_class =~ /^::/;
193 $args->{loader_class} = $loader_class;
194 };
195
5939bf08 196 # XXX this only works for relative storage_type, like ::DBI ...
71a6e88a 197 my $impl = $loader_class || "DBIx::Class::Schema::Loader" . $self->storage_type;
23fd9773 198 try {
199 $self->ensure_class_loaded($impl)
200 }
201 catch {
202 croak qq/Could not load loader_class "$impl": "$_"/;
203 };
af6c2665 204
23fd9773 205 $class->loader($impl->new(%$args));
206 $class->loader->load;
207 $class->_loader_invoked(1);
996be9ee 208
23fd9773 209 # copy to $self
210 if (ref $self) {
211 $self->loader($class->loader);
212 $self->_loader_invoked(1);
213
214 $self->_merge_state_from($class);
215 }
216
217 # restore $class's storage
218 $class->storage($class_storage);
219
220 return $self;
221}
222
223# FIXME This needs to be moved into DBIC at some point, otherwise we are
224# maintaining things to do with DBIC guts, which we have no business of
225# maintaining. But at the moment it would be just dead code in DBIC, so we'll
226# maintain it here.
227sub _merge_state_from {
228 my ($self, $from) = @_;
229
230 my $orig_class_mappings = $self->class_mappings;
231 my $orig_source_registrations = $self->source_registrations;
232
233 $self->_copy_state_from($from);
234
7ba9582a 235 $self->class_mappings(__merge($orig_class_mappings, $self->class_mappings))
23fd9773 236 if $orig_class_mappings;
237
7ba9582a 238 $self->source_registrations(__merge($orig_source_registrations, $self->source_registrations))
23fd9773 239 if $orig_source_registrations;
240}
241
7ba9582a 242my $merger;
243sub __merge {
244
245 local $SIG{__WARN__} = sigwarn_silencer(qr/Arguments for _merge_hashes must be hash references/);
246
247 ( $merger ||= do {
248 require Hash::Merge;
249 my $m = Hash::Merge->new('LEFT_PRECEDENT');
250 $m->set_clone_behavior(0);
251 $m;
252 } )->merge(
253 $_[0], $_[1]
254 );
255}
256
23fd9773 257sub _copy_state_from {
258 my $self = shift;
259 my ($from) = @_;
260
261 # older DBIC's do not have this method
262 if (try { DBIx::Class->VERSION('0.08197'); 1 }) {
263 return $self->next::method(@_);
264 }
265 else {
266 # this is a copy from DBIC git master pre 0.08197
267 $self->class_mappings({ %{$from->class_mappings} });
268 $self->source_registrations({ %{$from->source_registrations} });
269
270 foreach my $moniker ($from->sources) {
271 my $source = $from->source($moniker);
272 my $new = $source->new($source);
273 # we use extra here as we want to leave the class_mappings as they are
274 # but overwrite the source_registrations entry with the new source
275 $self->register_extra_source($moniker => $new);
276 }
277
278 if ($from->storage) {
279 $self->storage($from->storage);
280 $self->storage->set_schema($self);
281 }
282 }
996be9ee 283}
284
285=head2 connection
286
530e0bf6 287=over 4
288
289=item Arguments: @args
290
291=item Return Value: $new_schema
292
293=back
294
295See L<DBIx::Class::Schema/connection> for basic usage.
d65cda9e 296
29ddb54c 297If the final argument is a hashref, and it contains the keys C<loader_options>
298or C<loader_class>, those keys will be deleted, and their values value will be
299used for the loader options or class, respectively, just as if set via the
300L</loader_options> or L</loader_class> methods above.
d65cda9e 301
302The actual auto-loading operation (the heart of this module) will be invoked
303as soon as the connection information is defined.
996be9ee 304
305=cut
306
307sub connection {
de89deba 308 my $self = shift;
309 my $class = ref $self || $self;
d65cda9e 310
311 if($_[-1] && ref $_[-1] eq 'HASH') {
cc15b78f 312 for my $option (qw/loader_class loader_options/) {
29ddb54c 313 if(my $value = delete $_[-1]->{$option}) {
314 $self->$option($value);
315 }
d65cda9e 316 }
29ddb54c 317 pop @_ if !keys %{$_[-1]};
d65cda9e 318 }
319
cc15b78f 320 # Make sure we inherit from schema_base_class and load schema_components
321 # before connecting.
322 require DBIx::Class::Schema::Loader::Base;
323 my $temp_loader = DBIx::Class::Schema::Loader::Base->new(
a2c2cf69 324 %{ $self->_loader_args },
325 schema => $self,
b7b8c970 326 naming => 'current',
327 use_namespaces => 1,
cc15b78f 328 );
329
50b95db6 330 my $modify_isa = 0;
331 my @components;
332
cc15b78f 333 if ($temp_loader->schema_base_class || $temp_loader->schema_components) {
50b95db6 334 @components = @{ $temp_loader->schema_components }
cc15b78f 335 if $temp_loader->schema_components;
336
337 push @components, ('+'.$temp_loader->schema_base_class)
338 if $temp_loader->schema_base_class;
339
50b95db6 340 my $class_isa = do {
341 no strict 'refs';
342 \@{"${class}::ISA"};
343 };
344
345 my @component_classes = map {
346 /^\+/ ? substr($_, 1, length($_) - 1) : "DBIx::Class::$_"
347 } @components;
348
349 $modify_isa++ if not array_eq([ @$class_isa[0..(@components-1)] ], \@component_classes)
350 }
351
352 if ($modify_isa) {
de89deba 353 $class->load_components(@components);
cc15b78f 354
a1781f7f 355 # This hack is necessary because we changed @ISA of $self through
de89deba 356 # ->load_components and we are now in a different place in the mro.
cc15b78f 357 no warnings 'redefine';
358
ecf22f0a 359 local *connection = set_subname __PACKAGE__.'::connection' => sub {
cc15b78f 360 my $self = shift;
361 $self->next::method(@_);
362 };
363
de89deba 364 my @linear_isa = @{ mro::get_linear_isa($class) };
365
366 my $next_method;
367
368 foreach my $i (1..$#linear_isa) {
369 no strict 'refs';
370 $next_method = *{$linear_isa[$i].'::connection'}{CODE};
371 last if $next_method;
372 }
373
374 $self = $self->$next_method(@_);
cc15b78f 375 }
a1781f7f 376 else {
377 $self = $self->next::method(@_);
378 }
996be9ee 379
59cfa251 380 if(!$class->_loader_invoked) {
fa994d3c 381 $self->_invoke_loader
382 }
996be9ee 383
384 return $self;
385}
386
387=head2 clone
388
530e0bf6 389See L<DBIx::Class::Schema/clone>.
996be9ee 390
391=cut
392
393sub clone {
394 my $self = shift;
395
396 my $clone = $self->next::method(@_);
397
fa994d3c 398 if($clone->_loader_args) {
399 $clone->_loader_args->{schema} = $clone;
400 weaken($clone->_loader_args->{schema});
401 }
996be9ee 402
403 $clone;
404}
405
406=head2 dump_to_dir
407
530e0bf6 408=over 4
409
410=item Argument: $directory
411
412=back
996be9ee 413
414Calling this as a class method on either L<DBIx::Class::Schema::Loader>
707fb247 415or any derived schema class will cause all schemas to dump
996be9ee 416manual versions of themselves to the named directory when they are
417loaded. In order to be effective, this must be set before defining a
418connection on this schema class or any derived object (as the loading
074e81cd 419happens as soon as both a connection and loader_options are set, and
420only once per class).
996be9ee 421
422See L<DBIx::Class::Schema::Loader::Base/dump_directory> for more
423details on the dumping mechanism.
424
425This can also be set at module import time via the import option
426C<dump_to_dir:/foo/bar> to L<DBIx::Class::Schema::Loader>, where
427C</foo/bar> is the target directory.
428
429Examples:
430
431 # My::Schema isa DBIx::Class::Schema::Loader, and has connection info
432 # hardcoded in the class itself:
433 perl -MDBIx::Class::Schema::Loader=dump_to_dir:/foo/bar -MMy::Schema -e1
434
435 # Same, but no hard-coded connection, so we must provide one:
436 perl -MDBIx::Class::Schema::Loader=dump_to_dir:/foo/bar -MMy::Schema -e 'My::Schema->connection("dbi:Pg:dbname=foo", ...)'
437
438 # Or as a class method, as long as you get it done *before* defining a
439 # connection on this schema class or any derived object:
440 use My::Schema;
441 My::Schema->dump_to_dir('/foo/bar');
442 My::Schema->connection(........);
443
444 # Or as a class method on the DBIx::Class::Schema::Loader itself, which affects all
445 # derived schemas
446 use My::Schema;
447 use My::OtherSchema;
448 DBIx::Class::Schema::Loader->dump_to_dir('/foo/bar');
449 My::Schema->connection(.......);
450 My::OtherSchema->connection(.......);
451
452 # Another alternative to the above:
453 use DBIx::Class::Schema::Loader qw| dump_to_dir:/foo/bar |;
454 use My::Schema;
455 use My::OtherSchema;
456 My::Schema->connection(.......);
457 My::OtherSchema->connection(.......);
458
459=cut
460
461sub import {
462 my $self = shift;
a8d229ff 463
996be9ee 464 return if !@_;
a8d229ff 465
466 my $cpkg = (caller)[0];
467
996be9ee 468 foreach my $opt (@_) {
469 if($opt =~ m{^dump_to_dir:(.*)$}) {
470 $self->dump_to_dir($1)
471 }
472 elsif($opt eq 'make_schema_at') {
473 no strict 'refs';
996be9ee 474 *{"${cpkg}::make_schema_at"} = \&make_schema_at;
475 }
a8d229ff 476 elsif($opt eq 'naming') {
477 no strict 'refs';
f3bed1f1 478 *{"${cpkg}::naming"} = $self->curry::naming;
a8d229ff 479 }
f22644d7 480 elsif($opt eq 'use_namespaces') {
481 no strict 'refs';
f3bed1f1 482 *{"${cpkg}::use_namespaces"} = $self->curry::use_namespaces,
f22644d7 483 }
996be9ee 484 }
485}
486
487=head2 make_schema_at
488
530e0bf6 489=over 4
490
707fb247 491=item Arguments: $schema_class_name, \%loader_options, \@connect_info
530e0bf6 492
707fb247 493=item Return Value: $schema_class_name
530e0bf6 494
495=back
496
707fb247 497This function creates a DBIx::Class schema from an existing RDBMS
498schema. With the C<dump_directory> option, generates a set of
499DBIx::Class classes from an existing database schema read from the
500given dsn. Without a C<dump_directory>, creates schema classes in
501memory at runtime without generating on-disk class files.
996be9ee 502
707fb247 503For a complete list of supported loader_options, see
504L<DBIx::Class::Schema::Loader::Base>
483987b9 505
35a87f06 506The last hashref in the C<\@connect_info> can specify the L</loader_class>.
507
707fb247 508This function can be imported in the usual way, as illustrated in
509these Examples:
996be9ee 510
5223f24a 511 # Simple example, creates as a new class 'New::Schema::Name' in
512 # memory in the running perl interpreter.
996be9ee 513 use DBIx::Class::Schema::Loader qw/ make_schema_at /;
514 make_schema_at(
515 'New::Schema::Name',
59cfa251 516 { debug => 1 },
35a87f06 517 [ 'dbi:Pg:dbname="foo"','postgres','',
518 { loader_class => 'MyLoader' } # optionally
519 ],
996be9ee 520 );
521
707fb247 522 # Inside a script, specifying a dump directory in which to write
523 # class files
996be9ee 524 use DBIx::Class::Schema::Loader qw/ make_schema_at /;
525 make_schema_at(
526 'New::Schema::Name',
59cfa251 527 { debug => 1, dump_directory => './lib' },
35a87f06 528 [ 'dbi:Pg:dbname="foo"','postgres','',
529 { loader_class => 'MyLoader' } # optionally
530 ],
996be9ee 531 );
532
b486b265 533The last hashref in the C<\@connect_info> is checked for loader arguments such
534as C<loader_options> and C<loader_class>, see L</connection> for more details.
535
996be9ee 536=cut
537
538sub make_schema_at {
539 my ($target, $opts, $connect_info) = @_;
540
483987b9 541 {
542 no strict 'refs';
543 @{$target . '::ISA'} = qw/DBIx::Class::Schema::Loader/;
544 }
545
23fd9773 546 $target->_loader_invoked(0);
71a6e88a 547
483987b9 548 $target->loader_options($opts);
23fd9773 549
550 my $temp_schema = $target->connect(@$connect_info);
551
552 $target->storage($temp_schema->storage);
553 $target->storage->set_schema($target);
554
555 return $target;
996be9ee 556}
557
b97c2c1e 558=head2 rescan
559
530e0bf6 560=over 4
561
562=item Return Value: @new_monikers
563
564=back
565
b97c2c1e 566Re-scans the database for newly added tables since the initial
567load, and adds them to the schema at runtime, including relationships,
568etc. Does not process drops or changes.
569
a60b5b8d 570Returns a list of the new monikers added.
571
b97c2c1e 572=cut
573
39d5612f 574sub rescan { my $self = shift; $self->loader->rescan($self) }
b97c2c1e 575
a8d229ff 576=head2 naming
577
578=over 4
579
580=item Arguments: \%opts | $ver
581
582=back
583
584Controls the naming options for backward compatibility, see
585L<DBIx::Class::Schema::Loader::Base/naming> for details.
586
587To upgrade a dynamic schema, use:
588
589 __PACKAGE__->naming('current');
590
591Can be imported into your dump script and called as a function as well:
592
593 naming('v4');
996be9ee 594
f22644d7 595=head2 use_namespaces
596
597=over 4
598
599=item Arguments: 1|0
600
601=back
602
603Controls the use_namespaces options for backward compatibility, see
604L<DBIx::Class::Schema::Loader::Base/use_namespaces> for details.
605
606To upgrade a dynamic schema, use:
607
608 __PACKAGE__->use_namespaces(1);
609
610Can be imported into your dump script and called as a function as well:
611
612 use_namespaces(1);
613
996be9ee 614=head1 KNOWN ISSUES
615
616=head2 Multiple Database Schemas
617
c4a69b87 618See L<DBIx::Class::Schema::Loader::Base/db_schema>.
89ecd854 619
be80bba7 620=head1 ACKNOWLEDGEMENTS
a78e3fed 621
be80bba7 622Matt S Trout, all of the #dbix-class folks, and everyone who's ever sent
623in a bug report or suggestion.
fbd83464 624
8a6b44ef 625Based on L<DBIx::Class::Loader> by Sebastian Riedel
a78e3fed 626
627Based upon the work of IKEBE Tomohiro
628
b87ab391 629=head1 AUTHORS
a78e3fed 630
b87ab391 631Caelum: Rafael Kitover <rkitover@cpan.org>
be80bba7 632
b87ab391 633Dag-Erling Smørgrav <des@des.no>
be80bba7 634
b87ab391 635Matias E. Fernandez <mfernandez@pisco.ch>
be80bba7 636
b87ab391 637SineSwiper: Brendan Byrd <byrd.b@insightcom.com>
be80bba7 638
b87ab391 639TSUNODA Kazuya <drk@drk7.jp>
59388920 640
b87ab391 641acmoore: Andrew Moore <amoore@cpan.org>
be80bba7 642
b87ab391 643alnewkirk: Al Newkirk <awncorp@cpan.org>
be80bba7 644
b87ab391 645andrewalker: André Walker <andre@andrewalker.net>
be80bba7 646
b87ab391 647angelixd: Paul C. Mantz <pcmantz@cpan.org>
1f625792 648
d1d56e5e 649arc: Aaron Crane <arc@cpan.org>
650
b87ab391 651arcanez: Justin Hunter <justin.d.hunter@gmail.com>
fdd8ff16 652
b87ab391 653ash: Ash Berlin <ash@cpan.org>
65e705c3 654
b87ab391 655blblack: Brandon Black <blblack@gmail.com>
07307014 656
b87ab391 657bphillips: Brian Phillips <bphillips@cpan.org>
7b505bbd 658
b87ab391 659btilly: Ben Tilly <btilly@gmail.com>
da21e0cf 660
b87ab391 661domm: Thomas Klausner <domm@plix.at>
c21bfb92 662
b87ab391 663gugu: Andrey Kostenko <a.kostenko@rambler-co.ru>
d36c8734 664
b87ab391 665hobbs: Andrew Rodland <arodland@cpan.org>
827dff19 666
b87ab391 667ilmari: Dagfinn Ilmari MannsE<aring>ker <ilmari@ilmari.org>
43b982ea 668
b87ab391 669jhannah: Jay Hannah <jay@jays.net>
96f68869 670
b87ab391 671jnap: John Napiorkowski <jjn1056@yahoo.com>
2a5dcfb3 672
b87ab391 673kane: Jos Boumans <kane@cpan.org>
8763ffda 674
b87ab391 675mattp: Matt Phillips <mattp@cpan.org>
c899395b 676
b87ab391 677mephinet: Philipp Gortan <philipp.gortan@apa.at>
9fd0726a 678
b87ab391 679moritz: Moritz Lenz <moritz@faui2k3.org>
c9cf9b4d 680
b87ab391 681mst: Matt S. Trout <mst@shadowcatsystems.co.uk>
12333562 682
b87ab391 683mstratman: Mark A. Stratman <stratman@gmail.com>
71687093 684
b87ab391 685oalders: Olaf Alders <olaf@wundersolutions.com>
07f39b47 686
b87ab391 687rbo: Robert Bohne <rbo@cpan.org>
006c8ed3 688
b87ab391 689rbuels: Robert Buels <rbuels@gmail.com>
9890b10c 690
b87ab391 691ribasushi: Peter Rabbitson <ribasushi@cpan.org>
737700f7 692
b87ab391 693schwern: Michael G. Schwern <mschwern@cpan.org>
1f212b4b 694
b87ab391 695spb: Stephen Bennett <spb@exherbo.org>
4e887836 696
b87ab391 697timbunce: Tim Bunce <timb@cpan.org>
ba12c8ac 698
b87ab391 699waawaamilk: Nigel McNie <nigel@mcnie.name>
48c1a6c5 700
be80bba7 701... and lots of other folks. If we forgot you, please write the current
702maintainer or RT.
a78e3fed 703
9cc8e7e1 704=head1 COPYRIGHT & LICENSE
705
b87ab391 706Copyright (c) 2006 - 2015 by the aforementioned
707L<DBIx::Class::Schema::Loader/AUTHORS>.
a78e3fed 708
709This library is free software; you can redistribute it and/or modify it under
710the same terms as Perl itself.
711
712=head1 SEE ALSO
713
cb6407d7 714L<DBIx::Class>, L<DBIx::Class::Manual::Intro>, L<DBIx::Class::Tutorial>,
715L<DBIx::Class::Schema::Loader::Base>
a78e3fed 716
717=cut
718
7191;
71a6e88a 720# vim:et sts=4 sw=4 tw=0: