Skip Menu |

This queue is for tickets about the DBIx-Class CPAN distribution.

Report information
The Basics
Id: 52812
Status: resolved
Priority: 0/
Queue: DBIx-Class

People
Owner: Nobody in particular
Requestors: grousse [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 0.08115
Fixed in: 0.08117



Subject: dependency solver bug in SQL::Translator::Parser prevent deployement
Hello. My application triggers this kind of error messages: DBIx::Class::Schema::deploy(): Unable to produce deployment statements: translate: Error with parser 'SQL::Translator::Parser::DBIx::Class': Can't call method "_invoke_sqlt_deploy_hook" on an undefined value at /usr/lib/perl5/vendor_perl/5.10.1/SQL/Translator/Parser/DBIx/Class.pm line 258. This happens when attempting partial deployment of a single piece of the schema: $schema->deploy({ add_drop_table => 1, parser_args => { sources => [ $moniker ] } }); When investigating the parse() function of SQL::Translator::Parser::DBIx::Class, I found than the %tables hash contains only one entry for the just added source at the end of the main loop (line 81 -> 243), but got unfortunatly added a wrong additional entry by _resolve_deps function call. This last one is called recursively with the following args: call1: $table = 'unmaintained' $tables = { unmaintained => { ... } } %seen = () call2: $table = 'package' $tables = { unmaintained => { ... } } %seen = () Then $tables hashref get a new entry by autovification at line 322, as shown by this debug session DB<11> n ... 322: for my $dep (keys %{$tables->{$table}{foreign_table_deps}} ) { DB<12> x keys %$tables 0 'unmaintained' DB<13> n DB<14> x keys %$tables 0 'packages' 1 'unmaintained' Unfortunatly, the second entry is not a valid entry, and the fatal error occurs when attempting to access $tables{package}{source} object in the next loop. Here is the class corresponding to this piece of Schema: package Youri::Check::Schema::Unmaintained; use base qw/DBIx::Class/; __PACKAGE__->load_components(qw/Core/); __PACKAGE__->table('unmaintained'); __PACKAGE__->add_columns( id => { data_type => 'integer', is_auto_increment => 1, }, error => { data_type => 'varchar', is_auto_increment => 0, }, package_id => { data_type => 'integer', is_auto_increment => 0, }, ); __PACKAGE__->set_primary_key('id'); __PACKAGE__->belongs_to( 'package_id' => 'Youri::Check::Schema::Package' ); There is indeed a relationship with the other table (packages), which is already deployed at that time, and should get considered for deployement. The same code was previously working, with previous versions of DBIx::Class, but I can't give exact version number.
Here is a sample testcase, as well as a patch fixing the issue.
--- /usr/lib/perl5/vendor_perl/5.10.1/SQL/Translator/Parser/DBIx/Class.pm 2009-12-16 17:37:45.000000000 +0100 +++ Class.pm 2009-12-16 17:38:44.000000000 +0100 @@ -319,6 +319,8 @@ my %seen = map { $_ => $seen->{$_} + 1 } (keys %$seen); $seen{$table} = 1; + # avoid auto-vivification of hash entries + return unless exists $tables->{$table}; for my $dep (keys %{$tables->{$table}{foreign_table_deps}} ) { if ($seen->{$dep}) {
package My::Schema::A; use base qw/DBIx::Class/; __PACKAGE__->load_components(qw/Core/); __PACKAGE__->table('a'); __PACKAGE__->add_columns( id => { data_type => 'integer', is_auto_increment => 1, }, ); __PACKAGE__->set_primary_key('id'); package My::Schema::B; use base qw/DBIx::Class/; __PACKAGE__->load_components(qw/Core/); __PACKAGE__->table('b'); __PACKAGE__->add_columns( id => { data_type => 'integer', is_auto_increment => 1, }, a_id => { data_type => 'integer', is_auto_increment => 0, }, ); __PACKAGE__->set_primary_key('id'); __PACKAGE__->belongs_to( 'a_id' => 'My::Schema::A' ); package My::Schema; use base qw/DBIx::Class::Schema/; __PACKAGE__->load_classes(qw/ A /); package My::App; my $schema = My::Schema->connect("DBI:SQLite:dbname=db"); my $dbh = $schema->storage()->dbh(); My::Schema->load_classes('B'); my $new_schema = My::Schema->clone(); $new_schema->storage($schema->storage()); $schema = $new_schema; $schema->deploy({ add_drop_table => 1, parser_args => { sources => [ 'B' ] } }); 1;
Thank you for the report. Regression fixed by means different than the proposed patch (exclusion happens much earlier): http://dev.catalyst.perl.org/svnweb/bast/revision?rev=8158 Cheers