use strict;
use warnings;
-use base qw/DBIx::Class::Schema/;
-use base qw/Class::Data::Accessor/;
-use Carp;
+use base qw/DBIx::Class::Schema Class::Data::Accessor/;
+use Carp::Clan qw/^DBIx::Class/;
use UNIVERSAL::require;
use Class::C3;
-use Data::Dump qw/ dump /;
use Scalar::Util qw/ weaken /;
# Always remember to do all digits for the version even if they're 0
# i.e. first release of 0.XX *must* be 0.XX000. This avoids fBSD ports
# brain damage and presumably various other packaging systems too
-our $VERSION = '0.03002';
+our $VERSION = '0.04006';
-__PACKAGE__->mk_classaccessor('dump_to_dir');
-__PACKAGE__->mk_classaccessor('loader');
-__PACKAGE__->mk_classaccessor('_loader_args');
+__PACKAGE__->mk_classaccessor('_loader_args' => {});
+__PACKAGE__->mk_classaccessors(qw/dump_to_dir _loader_invoked _loader/);
=head1 NAME
use base qw/DBIx::Class::Schema::Loader/;
__PACKAGE__->loader_options(
- relationships => 1,
constraint => '^foo.*',
# debug => 1,
);
DBIx::Class::Schema::Loader automates the definition of a
L<DBIx::Class::Schema> by scanning database table definitions and
-setting up the columns and primary keys.
+setting up the columns, primary keys, and relationships.
-DBIx::Class::Schema::Loader currently supports DBI for MySQL,
-PostgreSQL, SQLite and DB2.
+DBIx::Class::Schema::Loader currently supports only the DBI storage type.
+It has explicit support for L<DBD::Pg>, L<DBD::mysql>, L<DBD::DB2>,
+L<DBD::SQLite>, and L<DBD::Oracle>. Other DBI drivers may function to
+a greater or lesser degree with this loader, depending on how much of the
+DBI spec they implement, and how standard their implementation is.
+
+Patches to make other DBDs work correctly welcome.
See L<DBIx::Class::Schema::Loader::DBI::Writing> for notes on writing
your own vendor-specific subclass for an unsupported DBD driver.
-This module requires L<DBIx::Class> 0.06 or later, and obsoletes
+This module requires L<DBIx::Class> 0.07006 or later, and obsoletes
the older L<DBIx::Class::Loader>.
This module is designed more to get you up and running quickly against
That being said, transitioning your code from a Schema generated by this
module to one that doesn't use this module should be straightforward and
-painless (as long as you're not using any methods that are now deprecated
-in this document), so don't shy away from it just for fears of the
-transition down the road.
+painless, so don't shy away from it just for fears of the transition down
+the road.
=head1 METHODS
only useful in fairly complex scenarios, see the
L<DBIx::Class::Schema::Loader::Base> documentation.
-This method is *required*, for backwards compatibility reasons. If
-you do not wish to change any options, just call it with an empty
-argument list during schema class initialization.
+If you intend to use C<loader_options>, you must call
+C<loader_options> before any connection is made, or embed the
+C<loader_options> in the connection information itself as shown
+below. Setting C<loader_options> after the connection has
+already been made is useless.
=cut
sub loader_options {
my $self = shift;
- my %args;
- if(ref $_[0] eq 'HASH') {
- %args = %{$_[0]};
- }
- else {
- %args = @_;
- }
-
- my $class = ref $self || $self;
- $args{schema} = $self;
- $args{schema_class} = $class;
- weaken($args{schema}) if ref $self;
-
+ my %args = (ref $_[0] eq 'HASH') ? %{$_[0]} : @_;
$self->_loader_args(\%args);
- $self->_invoke_loader if $self->storage && !$class->loader;
$self;
}
my $self = shift;
my $class = ref $self || $self;
- $self->_loader_args->{dump_directory} ||= $self->dump_to_dir;
+ my $args = $self->_loader_args;
+
+ # set up the schema/schema_class arguments
+ $args->{schema} = $self;
+ $args->{schema_class} = $class;
+ weaken($args->{schema}) if ref $self;
+ $args->{dump_directory} ||= $self->dump_to_dir;
# XXX this only works for relative storage_type, like ::DBI ...
my $impl = "DBIx::Class::Schema::Loader" . $self->storage_type;
croak qq/Could not load storage_type loader "$impl": / .
qq/"$UNIVERSAL::require::ERROR"/;
- # XXX in the future when we get rid of ->loader, the next two
- # lines can be replaced by "$impl->new(%{$self->_loader_args})->load;"
- $class->loader($impl->new(%{$self->_loader_args}));
- $class->loader->load;
+ $self->_loader($impl->new(%$args));
+ $self->_loader->load;
+ $self->_loader_invoked(1);
$self;
}
=head2 connection
-See L<DBIx::Class::Schema>.
+See L<DBIx::Class::Schema> for basic usage.
+
+If the final argument is a hashref, and it contains a key C<loader_options>,
+that key will be deleted, and its value will be used for the loader options,
+just as if set via the L</loader_options> method above.
+
+The actual auto-loading operation (the heart of this module) will be invoked
+as soon as the connection information is defined.
=cut
sub connection {
- my $self = shift->next::method(@_);
+ my $self = shift;
+
+ if($_[-1] && ref $_[-1] eq 'HASH') {
+ if(my $loader_opts = delete $_[-1]->{loader_options}) {
+ $self->loader_options($loader_opts);
+ pop @_ if !keys %{$_[-1]};
+ }
+ }
+
+ $self = $self->next::method(@_);
my $class = ref $self || $self;
- $self->_invoke_loader if $self->_loader_args && !$class->loader;
+ if(!$class->_loader_invoked) {
+ $self->_invoke_loader
+ }
return $self;
}
my $clone = $self->next::method(@_);
- $clone->_loader_args($self->_loader_args);
- $clone->_loader_args->{schema} = $clone;
- weaken($clone->_loader_args->{schema});
+ if($clone->_loader_args) {
+ $clone->_loader_args->{schema} = $clone;
+ weaken($clone->_loader_args->{schema});
+ }
$clone;
}
without the intermediate step of creating a physical Loader-based
schema class.
+The return value is the input class name.
+
This function can be exported/imported by the normal means, as
illustrated in these Examples:
use DBIx::Class::Schema::Loader qw/ make_schema_at /;
make_schema_at(
'New::Schema::Name',
- { relationships => 1, debug => 1 },
+ { debug => 1 },
[ 'dbi:Pg:dbname="foo"','postgres' ],
);
# Complex: dump loaded schema to disk, all from the commandline:
- perl -MDBIx::Class::Schema::Loader=make_schema_at,dump_to_dir:./lib -e 'make_schema_at("New::Schema::Name", { relationships => 1 }, [ "dbi:Pg:dbname=foo","postgres" ])'
+ perl -MDBIx::Class::Schema::Loader=make_schema_at,dump_to_dir:./lib -e 'make_schema_at("New::Schema::Name", { debug => 1 }, [ "dbi:Pg:dbname=foo","postgres" ])'
# Same, but inside a script, and using a different way to specify the
# dump directory:
use DBIx::Class::Schema::Loader qw/ make_schema_at /;
make_schema_at(
'New::Schema::Name',
- { relationships => 1, debug => 1, dump_directory => './lib' },
+ { debug => 1, dump_directory => './lib' },
[ 'dbi:Pg:dbname="foo"','postgres' ],
);
sub make_schema_at {
my ($target, $opts, $connect_info) = @_;
- my $opts_dumped = dump($opts);
- my $cinfo_dumped = dump(@$connect_info);
- eval qq|
- package $target;
- use base qw/DBIx::Class::Schema::Loader/;
- __PACKAGE__->loader_options($opts_dumped);
- __PACKAGE__->connection($cinfo_dumped);
- |;
- croak "make_schema_at failed: $@" if $@;
+ {
+ no strict 'refs';
+ @{$target . '::ISA'} = qw/DBIx::Class::Schema::Loader/;
+ }
+
+ $target->loader_options($opts);
+ $target->connection(@$connect_info);
}
+=head2 rescan
+
+Re-scans the database for newly added tables since the initial
+load, and adds them to the schema at runtime, including relationships,
+etc. Does not process drops or changes.
+
+Returns a list of the new monikers added.
+
+=cut
+
+sub rescan { my $self = shift; $self->_loader->rescan($self) }
+
=head1 EXAMPLE
Using the example in L<DBIx::Class::Manual::ExampleSchema> as a basis
use base qw/DBIx::Class::Schema::Loader/;
__PACKAGE__->loader_options(
- relationships => 1,
debug => 1,
);
__PACKAGE__->connection('dbi:SQLite:example.db');
and remove the Main directory tree (optional). Every thing else
should work the same
-=head1 DEPRECATED METHODS
-
-You don't need to read anything in this section unless you're upgrading
-code that was written against pre-0.03 versions of this module. This
-version is intended to be backwards-compatible with pre-0.03 code, but
-will issue warnings about your usage of deprecated features/methods.
-
-=head2 load_from_connection
-
-This deprecated method is now roughly an alias for L</loader_options>.
-
-This method *will* disappear in a future version.
-
-For now, using this method will invoke the legacy behavior for
-backwards compatibility, and merely emit a warning about upgrading
-your code.
-
-It also reverts the default inflection scheme to
-use L<Lingua::EN::Inflect> just like pre-0.03 versions of this
-module did.
-
-You can force these legacy inflections with the
-option C<legacy_default_inflections>, even after switch over
-to the preferred L</loader_options> way of doing things.
-
-See the source of this method for more details.
-
-=cut
-
-sub load_from_connection {
- my ($self, %args) = @_;
-
- my $cmds_ver = $Catalyst::Model::DBIC::Schema::VERSION;
- if($cmds_ver) {
- if($cmds_ver < 0.14) {
- warn 'You should upgrade your installation of'
- . ' Catalyst::Model::DBIC::Schema to 0.14 or higher, then:';
- }
- warn 'You should regenerate your Model files, which may eliminate'
- . ' the following deprecation warning:';
- }
- warn 'load_from_connection deprecated, please [re-]read the'
- . ' [new] DBIx::Class::Schema::Loader documentation';
-
- # Support the old connect_info / dsn / etc args...
- $args{connect_info} = [
- delete $args{dsn},
- delete $args{user},
- delete $args{password},
- delete $args{options},
- ] if $args{dsn};
-
- $self->connection(@{delete $args{connect_info}})
- if $args{connect_info};
-
- $self->loader_options('legacy_default_inflections' => 1, %args);
-}
-
-=head2 loader
-
-This is an accessor in the generated Schema class for accessing
-the L<DBIx::Class::Schema::Loader::Base> -based loader object
-that was used during construction. See the
-L<DBIx::Class::Schema::Loader::Base> docs for more information
-on the available loader methods there.
-
-This accessor is deprecated. Do not use it. Anything you can
-get from C<loader>, you can get via the normal L<DBIx::Class::Schema>
-methods, and your code will be more robust and forward-thinking
-for doing so.
-
-If you're already using C<loader> in your code, make an effort
-to get rid of it. If you think you've found a situation where it
-is necessary, let me know and we'll see what we can do to remedy
-that situation.
-
-In some future version, this accessor *will* disappear. It was
-apparently quite a design/API mistake to ever have exposed it to
-user-land in the first place, all things considered.
-
=head1 KNOWN ISSUES
=head2 Multiple Database Schemas
At some point in the future, an intelligent way around this might be
devised, probably by allowing the C<db_schema> option to be an
-arrayref of schemas to load, or perhaps even offering schema
-constraint/exclusion options just like the table ones.
+arrayref of schemas to load.
In "normal" L<DBIx::Class::Schema> usage, manually-defined
source classes and relationships have no problems crossing vendor schemas.
=head1 THANK YOU
-Adam Anderson, Andy Grundman, Autrijus Tang, Dan Kubb, David Naughton,
-Randal Schwartz, Simon Flack, Matt S Trout, everyone on #dbix-class, and
-all the others who've helped.
+Matt S Trout, all of the #dbix-class folks, and everyone who's ever sent
+in a bug report or suggestion.
=head1 LICENSE