X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FSchema.pm;h=5ec6020b427d90465413b822b054feaf156f80e3;hb=d4daee7b54e38e4b3d3d0a77759bddc1a4ede6e5;hp=63bff4661781f69bad64858ee3c66e353d1fbad5;hpb=341d5edefa34c7cdfee74be00eba9cd44ad2b7c4;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Schema.pm b/lib/DBIx/Class/Schema.pm index 63bff46..5ec6020 100644 --- a/lib/DBIx/Class/Schema.pm +++ b/lib/DBIx/Class/Schema.pm @@ -8,7 +8,7 @@ use Carp::Clan qw/^DBIx::Class/; use Scalar::Util qw/weaken/; use File::Spec; use Sub::Name (); -require Module::Find; +use Module::Find(); use base qw/DBIx::Class/; @@ -173,8 +173,8 @@ sub _findallmod { } # returns a hash of $shortname => $fullname for every package -# found in the given namespaces ($shortname is with the $fullname's -# namespace stripped off) +# found in the given namespaces ($shortname is with the $fullname's +# namespace stripped off) sub _map_namespaces { my ($class, @namespaces) = @_; @@ -190,6 +190,22 @@ sub _map_namespaces { @results_hash; } +# returns the result_source_instance for the passed class/object, +# or dies with an informative message (used by load_namespaces) +sub _ns_get_rsrc_instance { + my $class = shift; + my $rs = ref ($_[0]) || $_[0]; + + if ($rs->can ('result_source_instance') ) { + return $rs->result_source_instance; + } + else { + $class->throw_exception ( + "Attempt to load_namespaces() class $rs failed - are you sure this is a real Result Class?" + ); + } +} + sub load_namespaces { my ($class, %args) = @_; @@ -223,16 +239,29 @@ sub load_namespaces { local *Class::C3::reinitialize = sub { }; use warnings 'redefine'; - # ensure classes are loaded and fetch properly sorted classes + # ensure classes are loaded and attached in inheritance order $class->ensure_class_loaded($_) foreach(values %results); - my @subclass_last = sort { $results{$a}->isa($results{$b}) } keys(%results); - + my %inh_idx; + my @subclass_last = sort { + + ($inh_idx{$a} ||= + scalar @{mro::get_linear_isa( $results{$a} )} + ) + + <=> + + ($inh_idx{$b} ||= + scalar @{mro::get_linear_isa( $results{$b} )} + ) + + } keys(%results); + foreach my $result (@subclass_last) { my $result_class = $results{$result}; my $rs_class = delete $resultsets{$result}; - my $rs_set = $result_class->resultset_class; - + my $rs_set = $class->_ns_get_rsrc_instance ($result_class)->resultset_class; + if($rs_set && $rs_set ne 'DBIx::Class::ResultSet') { if($rs_class && $rs_class ne $rs_set) { carp "We found ResultSet class '$rs_class' for '$result', but it seems " @@ -241,10 +270,10 @@ sub load_namespaces { } elsif($rs_class ||= $default_resultset_class) { $class->ensure_class_loaded($rs_class); - $result_class->resultset_class($rs_class); + $class->_ns_get_rsrc_instance ($result_class)->resultset_class($rs_class); } - my $source_name = $result_class->source_name || $result; + my $source_name = $class->_ns_get_rsrc_instance ($result_class)->source_name || $result; push(@to_register, [ $source_name, $result_class ]); } @@ -269,8 +298,10 @@ sub load_namespaces { =back -Alternative method to L which you should look at -using if you can. +L is an alternative method to L, both of +which serve similar purposes, each with different advantages and disadvantages. +In the general case you should use L, unless you need to +be able to specify that only specific classes are loaded at runtime. With no arguments, this method uses L to find all classes under the schema's namespace. Otherwise, this method loads the classes you specify @@ -724,7 +755,7 @@ i.e., [ 2, 'Indie Band' ], ... ]); - + Since wantarray context is basically the same as looping over $rs->create(...) you won't see any performance benefits and in this case the method is more for convenience. Void context sends the column information directly to storage @@ -775,10 +806,10 @@ Overload C to change the behaviour of C. sub connection { my ($self, @info) = @_; return $self if !@info && $self->storage; - + my ($storage_class, $args) = ref $self->storage_type ? ($self->_normalize_storage_type($self->storage_type),{}) : ($self->storage_type, {}); - + $storage_class = 'DBIx::Class::Storage'.$storage_class if $storage_class =~ m/^::/; eval "require ${storage_class};"; @@ -999,16 +1030,16 @@ sub throw_exception { =over 4 -=item Arguments: $sqlt_args, $dir +=item Arguments: \%sqlt_args, $dir =back Attempts to deploy the schema to the current storage using L. -See L for a list of values for C<$sqlt_args>. The most -common value for this would be C<< { add_drop_table => 1, } >> to have the SQL -produced include a DROP TABLE statement for each table created. For quoting -purposes use C value with C and +See L for a list of values for C<\%sqlt_args>. +The most common value for this would be C<< { add_drop_table => 1 } >> +to have the SQL produced include a C statement for each table +created. For quoting purposes supply C and C. Additionally, the DBIx::Class parser accepts a C parameter as a hash @@ -1029,19 +1060,16 @@ sub deploy { =over 4 -=item Arguments: $rdbms_type, $sqlt_args, $dir +=item Arguments: See L =item Return value: $listofstatements =back -A convenient shortcut to storage->deployment_statements(). Returns the -SQL statements used by L and -L. C<$rdbms_type> provides the -(optional) SQLT (not DBI) database driver name for which the SQL -statements are produced. If not supplied, the type is determined by -interrogating the current connection. The other two arguments are -identical to those of L. +A convenient shortcut to +C<< $self->storage->deployment_statements($self, @args) >>. +Returns the SQL statements used by L and +L. =cut @@ -1058,42 +1086,15 @@ sub deployment_statements { =over 4 -=item Arguments: \@databases, $version, $directory, $preversion, $sqlt_args - -=back - -Creates an SQL file based on the Schema, for each of the specified -database types, in the given directory. Given a previous version number, -this will also create a file containing the ALTER TABLE statements to -transform the previous schema into the current one. Note that these -statements may contain DROP TABLE or DROP COLUMN statements that can -potentially destroy data. - -The file names are created using the C method below, please -override this method in your schema if you would like a different file -name format. For the ALTER file, the same format is used, replacing -$version in the name with "$preversion-$version". - -See L for details of $sqlt_args. - -If no arguments are passed, then the following default values are used: - -=over 4 - -=item databases - ['MySQL', 'SQLite', 'PostgreSQL'] - -=item version - $schema->schema_version - -=item directory - './' - -=item preversion - +=item Arguments: See L =back -Note that this feature is currently EXPERIMENTAL and may not work correctly -across all databases, or fully handle complex relationships. +A convenient shortcut to +C<< $self->storage->create_ddl_dir($self, @args) >>. -WARNING: Please check all SQL files created, before applying them. +Creates an SQL file based on the Schema, for each of the specified +database types, in the given directory. =cut @@ -1123,6 +1124,19 @@ name format is: C<$dir$schema-$version-$type.sql>. You may override this method in your schema if you wish to use a different format. + WARNING + + Prior to DBIx::Class version 0.08100 this method had a different signature: + + my $filename = $table->ddl_filename($type, $dir, $version, $preversion) + + In recent versions variables $dir and $version were reversed in order to + bring the signature in line with other Schema/Storage methods. If you + really need to maintain backward compatibility, you can do the following + in any overriding methods: + + ($dir, $version) = ($version, $dir) if ($DBIx::Class::VERSION < 0.08100); + =cut sub ddl_filename { @@ -1132,7 +1146,7 @@ sub ddl_filename { $filename =~ s/::/-/g; $filename = File::Spec->catfile($dir, "$filename-$version-$type.sql"); $filename =~ s/$version/$preversion-$version/ if($preversion); - + return $filename; } @@ -1358,7 +1372,7 @@ more information. $self->throw_exception ("No arguments to load_classes and couldn't load ${base} ($@)") if $@; - + if ($self eq $target) { # Pathological case, largely caused by the docs on early C::M::DBIC::Plain foreach my $moniker ($self->sources) { @@ -1371,14 +1385,14 @@ more information. $self->connection(@info); return $self; } - + my $schema = $self->compose_namespace($target, $base); { no strict 'refs'; my $name = join '::', $target, 'schema'; *$name = Sub::Name::subname $name, sub { $schema }; } - + $schema->connection(@info); foreach my $moniker ($schema->sources) { my $source = $schema->source($moniker);