From: Rafael Kitover Date: Mon, 26 Apr 2010 21:21:17 +0000 (-0400) Subject: unregister dropped sources on rescan X-Git-Tag: 0.07000~50 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=0c1d5b472c4a25217e297e07c4392932061554fb;p=dbsrgits%2FDBIx-Class-Schema-Loader.git unregister dropped sources on rescan --- diff --git a/Changes b/Changes index b21aada..c6454fb 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,6 @@ Revision history for Perl extension DBIx::Class::Schema::Loader + - unregister dropped sources on rescan - added 'preserve_case' option with support for SQLite, mysql, MSSQL and Firebird/InterBase; removed the MSSQL 'case_sensitive_collation' and the Firebird/InterBase 'unquoted_ddl' options in favor of it. diff --git a/TODO b/TODO index a2ba73f..95b9bf5 100644 --- a/TODO +++ b/TODO @@ -8,8 +8,6 @@ support pk/uk/fk info on views, possibly. May or may not be a sane thing to try Fix up ResultSet Manager / Methods / etc stuff. May require some work in the main DBIx::Class first. -SQLite needs some heavy refactoring, the subroutines are becoming too complex to understand easily. - Refactor RelBuilder so that it doesn't require a live mostly-built DBIx::Class::Schema, so that other modules (SQLT) can use it easier. And then when/if we get there, break it out as a seperate distribution with a new name. @@ -18,5 +16,3 @@ Relationship stuff: Re-scan relations/tables after initial relation setup to find ->many_to_many() relations to be set up? While scanning for many-to-many, scan for implied rels as well? (if foo->belongs_to('bar') and baz->belongs_to('bar'), does that impliy foo->might_have('baz') and the reverse?) ... - -unregister sources for dropped tables on rescan diff --git a/lib/DBIx/Class/Schema/Loader/Base.pm b/lib/DBIx/Class/Schema/Loader/Base.pm index 997b7e0..d5e70a8 100644 --- a/lib/DBIx/Class/Schema/Loader/Base.pm +++ b/lib/DBIx/Class/Schema/Loader/Base.pm @@ -177,12 +177,8 @@ In general, there is very little difference between v5 and v6 schemas. This mode is identical to C mode, except that monikerization of CamelCase table names is also done correctly. -CamelCase column names in case-sensitive mode will also be handled correctly -for relationship name inflection. - -Currently, only Sybase ASE, MSSQL with CS/BIN collation and Firebird without -the L -option are in case-sensitive mode. +CamelCase column names in case-preserving mode will also be handled correctly +for relationship name inflection. See L. If you don't have any CamelCase table or column names, you can upgrade without breaking any of your code. @@ -924,12 +920,21 @@ sub rescan { my @created; my @current = $self->_tables_list({ constraint => $self->constraint, exclude => $self->exclude }); + foreach my $table (@current) { if(!exists $self->{_tables}->{$table}) { push(@created, $table); } } + my %current; + @current{@current} = (); + foreach my $table (keys %{ $self->{_tables} }) { + if (not exists $current{$table}) { + $self->_unregister_source_for_table($table); + } + } + my $loaded = $self->_load_tables(@created); return map { $self->monikers->{$_} } @$loaded; @@ -1801,6 +1806,22 @@ sub _uc { return $self->preserve_case ? $name : uc($name); } +sub _unregister_source_for_table { + my ($self, $table) = @_; + + eval { + local $@; + my $schema = $self->schema; + # in older DBIC it's a private method + my $unregister = $schema->can('unregister_source') || $schema->can('_unregister_source'); + $schema->$unregister($self->_table2moniker($table)); + delete $self->monikers->{$table}; + delete $self->classes->{$table}; + delete $self->_upgrading_classes->{$table}; + delete $self->{_tables}{$table}; + }; +} + # remove the dump dir from @INC on destruction sub DESTROY { my $self = shift; diff --git a/lib/DBIx/Class/Schema/Loader/DBI.pm b/lib/DBIx/Class/Schema/Loader/DBI.pm index 33a274e..7e9a7a7 100644 --- a/lib/DBIx/Class/Schema/Loader/DBI.pm +++ b/lib/DBIx/Class/Schema/Loader/DBI.pm @@ -132,14 +132,7 @@ sub _filter_tables { } else { warn "Bad table or view '$table', ignoring: $@\n"; - local $@; - eval { - my $schema = $self->schema; - # in older DBIC it's a private method - my $unregister = $schema->can('unregister_source') - || $schema->can('_unregister_source'); - $schema->$unregister($self->_table2moniker($table)); - }; + $self->_unregister_source_for_table($table); } } diff --git a/t/lib/dbixcsl_common_tests.pm b/t/lib/dbixcsl_common_tests.pm index 6557e07..0ecbda0 100644 --- a/t/lib/dbixcsl_common_tests.pm +++ b/t/lib/dbixcsl_common_tests.pm @@ -4,6 +4,7 @@ use strict; use warnings; use Test::More; +use Test::Exception; use DBIx::Class::Schema::Loader; use Class::Unload; use File::Path; @@ -87,7 +88,7 @@ sub run_tests { my $extra_count = $self->{extra}{count} || 0; - plan tests => @connect_info * (176 + $extra_count + ($self->{data_type_tests}{test_count} || 0)); + plan tests => @connect_info * (178 + $extra_count + ($self->{data_type_tests}{test_count} || 0)); foreach my $info_idx (0..$#connect_info) { my $info = $connect_info[$info_idx]; @@ -861,7 +862,7 @@ sub test_schema { } # rescan and norewrite test - SKIP: { + { my @statements_rescan = ( qq{ CREATE TABLE loader_test30 ( @@ -924,13 +925,28 @@ sub test_schema { my $rsobj30 = $conn->resultset('LoaderTest30'); isa_ok($rsobj30, 'DBIx::Class::ResultSet'); - skip 'no rels', 2 if $self->{skip_rels}; + SKIP: { + skip 'no rels', 2 if $self->{skip_rels}; + + my $obj30 = $rsobj30->find(123); + isa_ok( $obj30->loader_test2, $class2); + + ok($rsobj30->result_source->column_info('loader_test2')->{is_foreign_key}, + 'Foreign key detected'); + } + + $conn->storage->disconnect; # for Firebird + $conn->storage->dbh->do("DROP TABLE loader_test30"); - my $obj30 = $rsobj30->find(123); - isa_ok( $obj30->loader_test2, $class2); + @new = do { + local $SIG{__WARN__} = sub {}; + $conn->rescan; + }; + is_deeply(\@new, [], 'no new tables on rescan'); - ok($rsobj30->result_source->column_info('loader_test2')->{is_foreign_key}, - 'Foreign key detected'); + throws_ok { $conn->resultset('LoaderTest30') } + qr/Can't find source/, + 'source unregistered for dropped table after rescan'; } $self->test_data_types($conn);