Release 0.07047
[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';
50b95db6 11use DBIx::Class::Schema::Loader::Utils 'array_eq';
23fd9773 12use Try::Tiny;
13use Hash::Merge 'merge';
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
306bf770 19our $VERSION = '0.07047';
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
996be9ee 190 # XXX this only works for relative storage_type, like ::DBI ...
71a6e88a 191 my $loader_class = $self->loader_class;
192 if ($loader_class) {
193 $loader_class = "DBIx::Class::Schema::Loader${loader_class}" if $loader_class =~ /^::/;
194 $args->{loader_class} = $loader_class;
195 };
196
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
235 $self->class_mappings(merge($orig_class_mappings, $self->class_mappings))
236 if $orig_class_mappings;
237
238 $self->source_registrations(merge($orig_source_registrations, $self->source_registrations))
239 if $orig_source_registrations;
240}
241
242sub _copy_state_from {
243 my $self = shift;
244 my ($from) = @_;
245
246 # older DBIC's do not have this method
247 if (try { DBIx::Class->VERSION('0.08197'); 1 }) {
248 return $self->next::method(@_);
249 }
250 else {
251 # this is a copy from DBIC git master pre 0.08197
252 $self->class_mappings({ %{$from->class_mappings} });
253 $self->source_registrations({ %{$from->source_registrations} });
254
255 foreach my $moniker ($from->sources) {
256 my $source = $from->source($moniker);
257 my $new = $source->new($source);
258 # we use extra here as we want to leave the class_mappings as they are
259 # but overwrite the source_registrations entry with the new source
260 $self->register_extra_source($moniker => $new);
261 }
262
263 if ($from->storage) {
264 $self->storage($from->storage);
265 $self->storage->set_schema($self);
266 }
267 }
996be9ee 268}
269
270=head2 connection
271
530e0bf6 272=over 4
273
274=item Arguments: @args
275
276=item Return Value: $new_schema
277
278=back
279
280See L<DBIx::Class::Schema/connection> for basic usage.
d65cda9e 281
29ddb54c 282If the final argument is a hashref, and it contains the keys C<loader_options>
283or C<loader_class>, those keys will be deleted, and their values value will be
284used for the loader options or class, respectively, just as if set via the
285L</loader_options> or L</loader_class> methods above.
d65cda9e 286
287The actual auto-loading operation (the heart of this module) will be invoked
288as soon as the connection information is defined.
996be9ee 289
290=cut
291
292sub connection {
de89deba 293 my $self = shift;
294 my $class = ref $self || $self;
d65cda9e 295
296 if($_[-1] && ref $_[-1] eq 'HASH') {
cc15b78f 297 for my $option (qw/loader_class loader_options/) {
29ddb54c 298 if(my $value = delete $_[-1]->{$option}) {
299 $self->$option($value);
300 }
d65cda9e 301 }
29ddb54c 302 pop @_ if !keys %{$_[-1]};
d65cda9e 303 }
304
cc15b78f 305 # Make sure we inherit from schema_base_class and load schema_components
306 # before connecting.
307 require DBIx::Class::Schema::Loader::Base;
308 my $temp_loader = DBIx::Class::Schema::Loader::Base->new(
a2c2cf69 309 %{ $self->_loader_args },
310 schema => $self,
b7b8c970 311 naming => 'current',
312 use_namespaces => 1,
cc15b78f 313 );
314
50b95db6 315 my $modify_isa = 0;
316 my @components;
317
cc15b78f 318 if ($temp_loader->schema_base_class || $temp_loader->schema_components) {
50b95db6 319 @components = @{ $temp_loader->schema_components }
cc15b78f 320 if $temp_loader->schema_components;
321
322 push @components, ('+'.$temp_loader->schema_base_class)
323 if $temp_loader->schema_base_class;
324
50b95db6 325 my $class_isa = do {
326 no strict 'refs';
327 \@{"${class}::ISA"};
328 };
329
330 my @component_classes = map {
331 /^\+/ ? substr($_, 1, length($_) - 1) : "DBIx::Class::$_"
332 } @components;
333
334 $modify_isa++ if not array_eq([ @$class_isa[0..(@components-1)] ], \@component_classes)
335 }
336
337 if ($modify_isa) {
de89deba 338 $class->load_components(@components);
cc15b78f 339
a1781f7f 340 # This hack is necessary because we changed @ISA of $self through
de89deba 341 # ->load_components and we are now in a different place in the mro.
cc15b78f 342 no warnings 'redefine';
343
ecf22f0a 344 local *connection = set_subname __PACKAGE__.'::connection' => sub {
cc15b78f 345 my $self = shift;
346 $self->next::method(@_);
347 };
348
de89deba 349 my @linear_isa = @{ mro::get_linear_isa($class) };
350
351 my $next_method;
352
353 foreach my $i (1..$#linear_isa) {
354 no strict 'refs';
355 $next_method = *{$linear_isa[$i].'::connection'}{CODE};
356 last if $next_method;
357 }
358
359 $self = $self->$next_method(@_);
cc15b78f 360 }
a1781f7f 361 else {
362 $self = $self->next::method(@_);
363 }
996be9ee 364
59cfa251 365 if(!$class->_loader_invoked) {
fa994d3c 366 $self->_invoke_loader
367 }
996be9ee 368
369 return $self;
370}
371
372=head2 clone
373
530e0bf6 374See L<DBIx::Class::Schema/clone>.
996be9ee 375
376=cut
377
378sub clone {
379 my $self = shift;
380
381 my $clone = $self->next::method(@_);
382
fa994d3c 383 if($clone->_loader_args) {
384 $clone->_loader_args->{schema} = $clone;
385 weaken($clone->_loader_args->{schema});
386 }
996be9ee 387
388 $clone;
389}
390
391=head2 dump_to_dir
392
530e0bf6 393=over 4
394
395=item Argument: $directory
396
397=back
996be9ee 398
399Calling this as a class method on either L<DBIx::Class::Schema::Loader>
707fb247 400or any derived schema class will cause all schemas to dump
996be9ee 401manual versions of themselves to the named directory when they are
402loaded. In order to be effective, this must be set before defining a
403connection on this schema class or any derived object (as the loading
074e81cd 404happens as soon as both a connection and loader_options are set, and
405only once per class).
996be9ee 406
407See L<DBIx::Class::Schema::Loader::Base/dump_directory> for more
408details on the dumping mechanism.
409
410This can also be set at module import time via the import option
411C<dump_to_dir:/foo/bar> to L<DBIx::Class::Schema::Loader>, where
412C</foo/bar> is the target directory.
413
414Examples:
415
416 # My::Schema isa DBIx::Class::Schema::Loader, and has connection info
417 # hardcoded in the class itself:
418 perl -MDBIx::Class::Schema::Loader=dump_to_dir:/foo/bar -MMy::Schema -e1
419
420 # Same, but no hard-coded connection, so we must provide one:
421 perl -MDBIx::Class::Schema::Loader=dump_to_dir:/foo/bar -MMy::Schema -e 'My::Schema->connection("dbi:Pg:dbname=foo", ...)'
422
423 # Or as a class method, as long as you get it done *before* defining a
424 # connection on this schema class or any derived object:
425 use My::Schema;
426 My::Schema->dump_to_dir('/foo/bar');
427 My::Schema->connection(........);
428
429 # Or as a class method on the DBIx::Class::Schema::Loader itself, which affects all
430 # derived schemas
431 use My::Schema;
432 use My::OtherSchema;
433 DBIx::Class::Schema::Loader->dump_to_dir('/foo/bar');
434 My::Schema->connection(.......);
435 My::OtherSchema->connection(.......);
436
437 # Another alternative to the above:
438 use DBIx::Class::Schema::Loader qw| dump_to_dir:/foo/bar |;
439 use My::Schema;
440 use My::OtherSchema;
441 My::Schema->connection(.......);
442 My::OtherSchema->connection(.......);
443
444=cut
445
446sub import {
447 my $self = shift;
a8d229ff 448
996be9ee 449 return if !@_;
a8d229ff 450
451 my $cpkg = (caller)[0];
452
996be9ee 453 foreach my $opt (@_) {
454 if($opt =~ m{^dump_to_dir:(.*)$}) {
455 $self->dump_to_dir($1)
456 }
457 elsif($opt eq 'make_schema_at') {
458 no strict 'refs';
996be9ee 459 *{"${cpkg}::make_schema_at"} = \&make_schema_at;
460 }
a8d229ff 461 elsif($opt eq 'naming') {
462 no strict 'refs';
463 *{"${cpkg}::naming"} = sub { $self->naming(@_) };
464 }
f22644d7 465 elsif($opt eq 'use_namespaces') {
466 no strict 'refs';
467 *{"${cpkg}::use_namespaces"} = sub { $self->use_namespaces(@_) };
468 }
996be9ee 469 }
470}
471
472=head2 make_schema_at
473
530e0bf6 474=over 4
475
707fb247 476=item Arguments: $schema_class_name, \%loader_options, \@connect_info
530e0bf6 477
707fb247 478=item Return Value: $schema_class_name
530e0bf6 479
480=back
481
707fb247 482This function creates a DBIx::Class schema from an existing RDBMS
483schema. With the C<dump_directory> option, generates a set of
484DBIx::Class classes from an existing database schema read from the
485given dsn. Without a C<dump_directory>, creates schema classes in
486memory at runtime without generating on-disk class files.
996be9ee 487
707fb247 488For a complete list of supported loader_options, see
489L<DBIx::Class::Schema::Loader::Base>
483987b9 490
35a87f06 491The last hashref in the C<\@connect_info> can specify the L</loader_class>.
492
707fb247 493This function can be imported in the usual way, as illustrated in
494these Examples:
996be9ee 495
5223f24a 496 # Simple example, creates as a new class 'New::Schema::Name' in
497 # memory in the running perl interpreter.
996be9ee 498 use DBIx::Class::Schema::Loader qw/ make_schema_at /;
499 make_schema_at(
500 'New::Schema::Name',
59cfa251 501 { debug => 1 },
35a87f06 502 [ 'dbi:Pg:dbname="foo"','postgres','',
503 { loader_class => 'MyLoader' } # optionally
504 ],
996be9ee 505 );
506
707fb247 507 # Inside a script, specifying a dump directory in which to write
508 # class files
996be9ee 509 use DBIx::Class::Schema::Loader qw/ make_schema_at /;
510 make_schema_at(
511 'New::Schema::Name',
59cfa251 512 { debug => 1, dump_directory => './lib' },
35a87f06 513 [ 'dbi:Pg:dbname="foo"','postgres','',
514 { loader_class => 'MyLoader' } # optionally
515 ],
996be9ee 516 );
517
b486b265 518The last hashref in the C<\@connect_info> is checked for loader arguments such
519as C<loader_options> and C<loader_class>, see L</connection> for more details.
520
996be9ee 521=cut
522
523sub make_schema_at {
524 my ($target, $opts, $connect_info) = @_;
525
483987b9 526 {
527 no strict 'refs';
528 @{$target . '::ISA'} = qw/DBIx::Class::Schema::Loader/;
529 }
530
23fd9773 531 $target->_loader_invoked(0);
71a6e88a 532
483987b9 533 $target->loader_options($opts);
23fd9773 534
535 my $temp_schema = $target->connect(@$connect_info);
536
537 $target->storage($temp_schema->storage);
538 $target->storage->set_schema($target);
539
540 return $target;
996be9ee 541}
542
b97c2c1e 543=head2 rescan
544
530e0bf6 545=over 4
546
547=item Return Value: @new_monikers
548
549=back
550
b97c2c1e 551Re-scans the database for newly added tables since the initial
552load, and adds them to the schema at runtime, including relationships,
553etc. Does not process drops or changes.
554
a60b5b8d 555Returns a list of the new monikers added.
556
b97c2c1e 557=cut
558
39d5612f 559sub rescan { my $self = shift; $self->loader->rescan($self) }
b97c2c1e 560
a8d229ff 561=head2 naming
562
563=over 4
564
565=item Arguments: \%opts | $ver
566
567=back
568
569Controls the naming options for backward compatibility, see
570L<DBIx::Class::Schema::Loader::Base/naming> for details.
571
572To upgrade a dynamic schema, use:
573
574 __PACKAGE__->naming('current');
575
576Can be imported into your dump script and called as a function as well:
577
578 naming('v4');
996be9ee 579
f22644d7 580=head2 use_namespaces
581
582=over 4
583
584=item Arguments: 1|0
585
586=back
587
588Controls the use_namespaces options for backward compatibility, see
589L<DBIx::Class::Schema::Loader::Base/use_namespaces> for details.
590
591To upgrade a dynamic schema, use:
592
593 __PACKAGE__->use_namespaces(1);
594
595Can be imported into your dump script and called as a function as well:
596
597 use_namespaces(1);
598
996be9ee 599=head1 KNOWN ISSUES
600
601=head2 Multiple Database Schemas
602
c4a69b87 603See L<DBIx::Class::Schema::Loader::Base/db_schema>.
89ecd854 604
be80bba7 605=head1 ACKNOWLEDGEMENTS
a78e3fed 606
be80bba7 607Matt S Trout, all of the #dbix-class folks, and everyone who's ever sent
608in a bug report or suggestion.
fbd83464 609
8a6b44ef 610Based on L<DBIx::Class::Loader> by Sebastian Riedel
a78e3fed 611
612Based upon the work of IKEBE Tomohiro
613
b87ab391 614=head1 AUTHORS
a78e3fed 615
b87ab391 616Caelum: Rafael Kitover <rkitover@cpan.org>
be80bba7 617
b87ab391 618Dag-Erling Smørgrav <des@des.no>
be80bba7 619
b87ab391 620Matias E. Fernandez <mfernandez@pisco.ch>
be80bba7 621
b87ab391 622SineSwiper: Brendan Byrd <byrd.b@insightcom.com>
be80bba7 623
b87ab391 624TSUNODA Kazuya <drk@drk7.jp>
59388920 625
b87ab391 626acmoore: Andrew Moore <amoore@cpan.org>
be80bba7 627
b87ab391 628alnewkirk: Al Newkirk <awncorp@cpan.org>
be80bba7 629
b87ab391 630andrewalker: André Walker <andre@andrewalker.net>
be80bba7 631
b87ab391 632angelixd: Paul C. Mantz <pcmantz@cpan.org>
1f625792 633
d1d56e5e 634arc: Aaron Crane <arc@cpan.org>
635
b87ab391 636arcanez: Justin Hunter <justin.d.hunter@gmail.com>
fdd8ff16 637
b87ab391 638ash: Ash Berlin <ash@cpan.org>
65e705c3 639
b87ab391 640blblack: Brandon Black <blblack@gmail.com>
07307014 641
b87ab391 642bphillips: Brian Phillips <bphillips@cpan.org>
7b505bbd 643
b87ab391 644btilly: Ben Tilly <btilly@gmail.com>
da21e0cf 645
b87ab391 646domm: Thomas Klausner <domm@plix.at>
c21bfb92 647
b87ab391 648gugu: Andrey Kostenko <a.kostenko@rambler-co.ru>
d36c8734 649
b87ab391 650hobbs: Andrew Rodland <arodland@cpan.org>
827dff19 651
b87ab391 652ilmari: Dagfinn Ilmari MannsE<aring>ker <ilmari@ilmari.org>
43b982ea 653
b87ab391 654jhannah: Jay Hannah <jay@jays.net>
96f68869 655
b87ab391 656jnap: John Napiorkowski <jjn1056@yahoo.com>
2a5dcfb3 657
b87ab391 658kane: Jos Boumans <kane@cpan.org>
8763ffda 659
b87ab391 660mattp: Matt Phillips <mattp@cpan.org>
c899395b 661
b87ab391 662mephinet: Philipp Gortan <philipp.gortan@apa.at>
9fd0726a 663
b87ab391 664moritz: Moritz Lenz <moritz@faui2k3.org>
c9cf9b4d 665
b87ab391 666mst: Matt S. Trout <mst@shadowcatsystems.co.uk>
12333562 667
b87ab391 668mstratman: Mark A. Stratman <stratman@gmail.com>
71687093 669
b87ab391 670oalders: Olaf Alders <olaf@wundersolutions.com>
07f39b47 671
b87ab391 672rbo: Robert Bohne <rbo@cpan.org>
006c8ed3 673
b87ab391 674rbuels: Robert Buels <rbuels@gmail.com>
9890b10c 675
b87ab391 676ribasushi: Peter Rabbitson <ribasushi@cpan.org>
737700f7 677
b87ab391 678schwern: Michael G. Schwern <mschwern@cpan.org>
1f212b4b 679
b87ab391 680spb: Stephen Bennett <spb@exherbo.org>
4e887836 681
b87ab391 682timbunce: Tim Bunce <timb@cpan.org>
ba12c8ac 683
b87ab391 684waawaamilk: Nigel McNie <nigel@mcnie.name>
48c1a6c5 685
be80bba7 686... and lots of other folks. If we forgot you, please write the current
687maintainer or RT.
a78e3fed 688
9cc8e7e1 689=head1 COPYRIGHT & LICENSE
690
b87ab391 691Copyright (c) 2006 - 2015 by the aforementioned
692L<DBIx::Class::Schema::Loader/AUTHORS>.
a78e3fed 693
694This library is free software; you can redistribute it and/or modify it under
695the same terms as Perl itself.
696
697=head1 SEE ALSO
698
cb6407d7 699L<DBIx::Class>, L<DBIx::Class::Manual::Intro>, L<DBIx::Class::Tutorial>,
700L<DBIx::Class::Schema::Loader::Base>
a78e3fed 701
702=cut
703
7041;
71a6e88a 705# vim:et sts=4 sw=4 tw=0: