From: Brandon Black Date: Tue, 24 Jan 2006 09:41:34 +0000 (+0000) Subject: ported db2, pg schema, and test updates from non-schema loader to schema loader X-Git-Tag: 0.03000~47 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=af96f52e62b7fd03380a5f53a1b4263a71bd3589;p=dbsrgits%2FDBIx-Class-Schema-Loader.git ported db2, pg schema, and test updates from non-schema loader to schema loader --- diff --git a/lib/DBIx/Class/Schema/Loader/DB2.pm b/lib/DBIx/Class/Schema/Loader/DB2.pm index 49153a9..d0859a9 100644 --- a/lib/DBIx/Class/Schema/Loader/DB2.pm +++ b/lib/DBIx/Class/Schema/Loader/DB2.pm @@ -2,7 +2,6 @@ package DBIx::Class::Schema::Loader::DB2; use strict; use base 'DBIx::Class::Schema::Loader::Generic'; -use DBI; use Carp; =head1 NAME @@ -30,13 +29,13 @@ See L. =cut sub _db_classes { - return (); + return qw/DBIx::Class::PK::Auto::DB2/; } sub _tables { my $class = shift; my %args = @_; - my $db_schema = uc ($args{db_schema} || ''); + my $db_schema = uc $class->loader_data->{_db_schema}; my $dbh = $class->storage->dbh; # this is split out to avoid version parsing errors... @@ -70,7 +69,9 @@ WHERE c.TABSCHEMA = ? and c.TABNAME = ? SQL $sth->execute($db_schema, $tabname) or die; - my @cols = map { @$_ } @{$sth->fetchall_arrayref}; + my @cols = map { lc } map { @$_ } @{$sth->fetchall_arrayref}; + + $sth->finish; $sth = $dbh->prepare(<<'SQL') or die; SELECT kcu.COLNAME @@ -81,11 +82,42 @@ SQL $sth->execute($db_schema, $tabname) or die; - my @pri = map { @$_ } @{$sth->fetchall_arrayref}; + my @pri = map { lc } map { @$_ } @{$sth->fetchall_arrayref}; + + $sth->finish; return ( \@cols, \@pri ); } +# Find and setup relationships +sub _relationships { + my $class = shift; + + my $dbh = $class->storage->dbh; + + my $sth = $dbh->prepare(<<'SQL') or die; +SELECT SR.COLCOUNT, SR.REFTBNAME, SR.PKCOLNAMES, SR.FKCOLNAMES +FROM SYSIBM.SYSRELS SR WHERE SR.TBNAME = ? +SQL + + foreach my $table ( $class->tables ) { + if ($sth->execute(uc $table)) { + while(my $res = $sth->fetchrow_arrayref()) { + my ($colcount, $other, $other_column, $column) = + map { $_=lc; s/^\s+//; s/\s+$//; $_; } @$res; + next if $colcount != 1; # XXX no multi-col FK support yet + eval { $class->_belongs_to_many( $table, $column, $other, + $other_column ) }; + warn qq/\# belongs_to_many failed "$@"\n\n/ + if $@ && $class->debug_loader; + } + } + } + + $sth->finish; + $dbh->disconnect; +} + =head1 SEE ALSO L diff --git a/lib/DBIx/Class/Schema/Loader/Generic.pm b/lib/DBIx/Class/Schema/Loader/Generic.pm index 28d05bb..896e2fe 100644 --- a/lib/DBIx/Class/Schema/Loader/Generic.pm +++ b/lib/DBIx/Class/Schema/Loader/Generic.pm @@ -110,7 +110,7 @@ sub _load_from_connection { _exclude => $args{exclude}, _relationships => $args{relationships}, _inflect => $args{inflect}, - _db_schema => $args{db_schema}, + _db_schema => $args{db_schema} || '', _drop_db_schema => $args{drop_db_schema}, TABLE_CLASSES => {}, MONIKERS => {}, @@ -237,35 +237,29 @@ sub _load_classes { next unless $table =~ /$constraint/; next if ( defined $exclude && $table =~ /$exclude/ ); - my $table = lc $table; - my $table_name_db_schema = $table; - my $table_name_only = $table_name_db_schema; my ($db_schema, $tbl) = split /\./, $table; + my $tablename = lc $table; if($tbl) { - $table_name_db_schema = $tbl if $class->loader_data->{_drop_db_schema}; - $table_name_only = $tbl; - } - else { - undef $db_schema; + $tablename = $class->loader_data->{_drop_db_schema} ? $tbl : lc $table; } - my $table_subclass = $class->_table2subclass($db_schema, $table_name_only); - my $table_class = $namespace . '::' . $table_subclass; + my $table_subclass = $class->_table2subclass($db_schema, $tbl); + my $table_class = "$namespace\::$table_subclass"; $class->inject_base( $table_class, 'DBIx::Class::Core' ); $_->require for @db_classes; $class->inject_base( $table_class, $_ ) for @db_classes; - warn qq/\# Initializing table "$table_name_db_schema" as "$table_class"\n/ if $class->debug_loader; - $table_class->table(lc $table_name_db_schema); + warn qq/\# Initializing table "$tablename" as "$table_class"\n/ if $class->debug_loader; + $table_class->table(lc $tablename); - my ( $cols, $pks ) = $class->_table_info($table_name_db_schema); + my ( $cols, $pks ) = $class->_table_info($table); carp("$table has no primary key") unless @$pks; $table_class->add_columns(@$cols); $table_class->set_primary_key(@$pks) if @$pks; my $code = "package $table_class;\n$additional_base$additional$left_base"; warn qq/$code/ if $class->debug_loader; - warn qq/$table_class->table('$table_name_db_schema');\n/ if $class->debug_loader; + warn qq/$table_class->table('$tablename');\n/ if $class->debug_loader; my $columns = join "', '", @$cols; warn qq/$table_class->add_columns('$columns')\n/ if $class->debug_loader; my $primaries = join "', '", @$pks; @@ -275,8 +269,8 @@ sub _load_classes { unshift @{"$table_class\::ISA"}, $_ foreach ( @{ $class->loader_data->{_left_base} } ); $class->register_class($table_subclass, $table_class); - $class->loader_data->{TABLE_CLASSES}->{$table_name_db_schema} = $table_class; - $class->loader_data->{MONIKERS}->{$table_name_db_schema} = $table_subclass; + $class->loader_data->{TABLE_CLASSES}->{lc $tablename} = $table_class; + $class->loader_data->{MONIKERS}->{lc $tablename} = $table_subclass; } } @@ -286,11 +280,11 @@ sub _relationships { my $dbh = $class->storage->dbh; foreach my $table ( $class->tables ) { my $quoter = $dbh->get_info(29) || q{"}; - if ( my $sth = $dbh->foreign_key_info( '', '', '', '', '', $table ) ) { + if ( my $sth = $dbh->foreign_key_info( '', $class->loader_data->{_db_schema}, '', '', '', $table ) ) { for my $res ( @{ $sth->fetchall_arrayref( {} ) } ) { - my $column = $res->{FK_COLUMN_NAME}; - my $other = $res->{UK_TABLE_NAME}; - my $other_column = $res->{UK_COLUMN_NAME}; + my $column = lc $res->{FK_COLUMN_NAME}; + my $other = lc $res->{UK_TABLE_NAME}; + my $other_column = lc $res->{UK_COLUMN_NAME}; $column =~ s/$quoter//g; $other =~ s/$quoter//g; $other_column =~ s/$quoter//g; @@ -307,13 +301,19 @@ sub _relationships { sub _table2subclass { my ( $class, $db_schema, $table ) = @_; - my $table_subclass = join '', map ucfirst, split /[\W_]+/, $table; + my $db_schema_ns; - if($db_schema && !$class->loader_data->{_drop_db_schema}) { - $table_subclass = (ucfirst lc $db_schema) . '-' . $table_subclass; + if($table) { + $db_schema = ucfirst lc $db_schema; + $db_schema_ns = "::$db_schema" if(!$class->loader_data->{_drop_db_schema}); + } else { + $table = $db_schema; } - $table_subclass; + my $subclass = join '', map ucfirst, split /[\W_]+/, lc $table; + $subclass = $db_schema_ns ? "$db_schema_ns\::" . $subclass : $subclass; + + return $subclass; } # Overload in driver class diff --git a/t/13db2_common.t b/t/13db2_common.t index cee99b2..862f2fd 100644 --- a/t/13db2_common.t +++ b/t/13db2_common.t @@ -7,11 +7,13 @@ my $user = $ENV{DB2_USER} || ''; my $password = $ENV{DB2_PASS} || ''; my $tester = dbixcsl_common_tests->new( - vendor => 'DB2', - auto_inc_pk => 'INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY', - dsn => "dbi:DB2:$database", - user => $user, - password => $password, + vendor => 'DB2', + auto_inc_pk => 'INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY', + dsn => "dbi:DB2:$database", + user => $user, + password => $password, + db_schema => $user, + drop_db_schema => 1, ); if( !$database || !$user ) { diff --git a/t/dbixcsl_common_tests.pm b/t/dbixcsl_common_tests.pm index 70507fc..b56eb82 100644 --- a/t/dbixcsl_common_tests.pm +++ b/t/dbixcsl_common_tests.pm @@ -46,23 +46,28 @@ sub run_tests { my $schema_pkg = "$namespace\::Schema"; + my %loader_opts = ( + dsn => $self->{dsn}, + user => $self->{user}, + password => $self->{password}, + namespace => $namespace, + constraint => '^(?:\S+\.)?(?i:loader_test)[0-9]+$', + relationships => 1, + debug => $debug, + ); + + $loader_opts{db_schema} = $self->{db_schema} if $self->{db_schema}; + $loader_opts{drop_db_schema} = $self->{drop_db_schema} if $self->{drop_db_schema}; + eval qq{ package $schema_pkg; - use base qw/DBIx::Class::Schema::Loader/; - - __PACKAGE__->load_from_connection( - dsn => "$self->{dsn}", - user => "$self->{user}", - password => "$self->{password}", - namespace => "$namespace", - constraint => '^loader_test.*', - relationships => 1, - debug => "$debug", - ); + use base qw/DBIx::Class::Schema::Loader/; + + __PACKAGE__->load_from_connection(\%loader_opts); }; ok(!$@, "Loader initialization failed: $@"); - my $conn = $schema_pkg->connect($self->{dsn},$self->{user},$self->{passwd}); + my $conn = $schema_pkg->connect($self->{dsn},$self->{user},$self->{password}); my $moniker1 = $conn->moniker('loader_test1'); my $rsobj1 = $conn->resultset($moniker1); @@ -177,7 +182,7 @@ sub run_tests { sub dbconnect { my ($self, $complain) = @_; - DBI->connect( + my $dbh = DBI->connect( $self->{dsn}, $self->{user}, $self->{password}, { @@ -186,6 +191,10 @@ sub dbconnect { AutoCommit => 1, } ); + + die "Failed to connect to database: $DBI::errstr" if !$dbh; + + return $dbh; } sub create { @@ -310,7 +319,7 @@ sub create { CREATE TABLE loader_test11 ( id11 $self->{auto_inc_pk}, message VARCHAR(8) DEFAULT 'foo', - loader_test10 INTEGER NOT NULL, + loader_test10 INTEGER, FOREIGN KEY (loader_test10) REFERENCES loader_test10 (id10) ) $self->{innodb}; }, @@ -320,11 +329,19 @@ sub create { q{ REFERENCES loader_test11 (id11); }), ); + $self->drop_tables; + $self->{created} = 1; my $dbh = $self->dbconnect(1); $dbh->do($_) for (@statements); unless($self->{skip_rels}) { + # hack for now, since DB2 doesn't like inline comments, and we need + # to test one for mysql, which works on everyone else... + # this all needs to be refactored anyways. + if($self->{vendor} =~ /DB2/i) { + @statements_reltests = map { s/--.*\n//; $_ } @statements_reltests; + } $dbh->do($_) for (@statements_reltests); unless($self->{vendor} =~ /sqlite/i) { $dbh->do($_) for (@statements_advanced); @@ -333,7 +350,7 @@ sub create { $dbh->disconnect(); } -sub DESTROY { +sub drop_tables { my $self = shift; return unless $self->{created}; @@ -379,7 +396,9 @@ sub DESTROY { } } $dbh->do("DROP TABLE $_") for (@tables); - $dbh->disconnect(); + $dbh->disconnect; } +sub DESTROY { shift->drop_tables; } + 1;