fixed multi-fk checking for postgres (misdetection of multiple single-fks on one...
Brandon Black [Fri, 27 Jan 2006 16:54:19 +0000 (16:54 +0000)]
lib/DBIx/Class/Schema/Loader/Generic.pm
lib/DBIx/Class/Schema/Loader/SQLite.pm
lib/DBIx/Class/Schema/Loader/mysql.pm
t/11mysql_common.t
t/dbixcsl_common_tests.pm

index 9445084..52f8fc3 100644 (file)
@@ -192,36 +192,51 @@ sub _loader_make_relations {
         $table_relname = Lingua::EN::Inflect::PL($table_relname);
     }
 
-    # for single-column case, set the relname to the column name,
-    # to make filter accessors work
-    if(scalar keys %$cond == 1) {
-        my ($col) = keys %$cond;
-        $other_relname = $cond->{$col};
-    }
+    if(ref($cond) eq 'HASH') {
+        # for single-column case, set the relname to the column name,
+        # to make filter accessors work
+        if(scalar keys %$cond == 1) {
+            my ($col) = keys %$cond;
+            $other_relname = $cond->{$col};
+        }
 
-    my $rev_cond = { reverse %$cond };
+        my $rev_cond = { reverse %$cond };
 
-    my $cond_printable = _loader_stringify_hash($cond)
-        if $class->_loader_debug;
-    my $rev_cond_printable = _loader_stringify_hash($rev_cond)
-        if $class->_loader_debug;
+        my $cond_printable = _loader_stringify_hash($cond)
+            if $class->_loader_debug;
+        my $rev_cond_printable = _loader_stringify_hash($rev_cond)
+            if $class->_loader_debug;
 
-    warn qq/\# Belongs_to relationship\n/ if $class->_loader_debug;
+        warn qq/\# Belongs_to relationship\n/ if $class->_loader_debug;
 
-    warn qq/$table_class->belongs_to( '$other_relname' => '$other_class',/
-      .  qq/$cond_printable);\n\n/
-      if $class->_loader_debug;
+        warn qq/$table_class->belongs_to( '$other_relname' => '$other_class',/
+          .  qq/$cond_printable);\n\n/
+          if $class->_loader_debug;
 
-    $table_class->belongs_to( $other_relname => $other_class, $cond);
+        $table_class->belongs_to( $other_relname => $other_class, $cond);
 
-    warn qq/\# Has_many relationship\n/ if $class->_loader_debug;
+        warn qq/\# Has_many relationship\n/ if $class->_loader_debug;
 
-    warn qq/$other_class->has_many( '$table_relname' => '$table_class',/
-      .  qq/$rev_cond_printable);\n\n/
-      .  qq/);\n\n/
-      if $class->_loader_debug;
+        warn qq/$other_class->has_many( '$table_relname' => '$table_class',/
+          .  qq/$rev_cond_printable);\n\n/
+          .  qq/);\n\n/
+          if $class->_loader_debug;
 
-    $other_class->has_many( $table_relname => $table_class, $rev_cond);
+        $other_class->has_many( $table_relname => $table_class, $rev_cond);
+    }
+    else { # implicit stuff, just a col name
+        warn qq/\# Belongs_to relationship\n/ if $class->_loader_debug;
+        warn qq/$table_class->belongs_to( '$cond' => '$other_class' );\n\n/
+          if $class->_loader_debug;
+        $table_class->belongs_to( $cond => $other_class );
+
+        warn qq/\# Has_many relationship\n/ if $class->_loader_debug;
+        warn qq/$other_class->has_many( '$table_relname' => '$table_class',/
+          .  qq/$cond);\n\n/
+          if $class->_loader_debug;
+
+        $other_class->has_many( $table_relname => $table_class, $cond);
+    }
 }
 
 # Load and setup classes
@@ -290,14 +305,18 @@ sub _loader_relationships {
             my $uk_tbl  = lc $raw_rel->{UK_TABLE_NAME};
             my $uk_col  = lc $raw_rel->{UK_COLUMN_NAME};
             my $fk_col  = lc $raw_rel->{FK_COLUMN_NAME};
+            my $relid   = lc $raw_rel->{UK_NAME};
             $uk_tbl =~ s/$quoter//g;
             $uk_col =~ s/$quoter//g;
             $fk_col =~ s/$quoter//g;
-            $rels->{$uk_tbl}->{$uk_col} = $fk_col;
+            $relid  =~ s/$quoter//g;
+            $rels->{$relid}->{tbl} = $uk_tbl;
+            $rels->{$relid}->{cols}->{$uk_col} = $fk_col;
         }
 
-        foreach my $reltbl (keys %$rels) {
-            my $cond = $rels->{$reltbl};
+        foreach my $relid (keys %$rels) {
+            my $reltbl = $rels->{$relid}->{tbl};
+            my $cond   = $rels->{$relid}->{cols};
             eval { $class->_loader_make_relations( $table, $reltbl, $cond ) };
               warn qq/\# belongs_to_many failed "$@"\n\n/
                 if $@ && $class->_loader_debug;
index 5aa7d11..7139e3f 100644 (file)
@@ -75,8 +75,8 @@ SELECT sql FROM sqlite_master WHERE tbl_name = ?
             $col =~ s/^\s+//gs;
 
             # Grab reference
-            if( $col =~ /^(.*)\s+REFERENCES\s+(\w+)\s*\((.*)\)/i ) {
-                chomp $col;
+            chomp $col;
+            if( $col =~ /^(.*)\s+REFERENCES\s+(\w+) (?: \s* \( (.*) \) )? /ix ) {
 
                 my ($cols, $f_table, $f_cols) = ($1, $2, $3);
 
@@ -88,15 +88,20 @@ SELECT sql FROM sqlite_master WHERE tbl_name = ?
                     $cols =~ s/\s+.*$//;
                 }
 
-                my @cols = map { s/\s*//g; $_ } split(/\s*,\s*/,$cols);
-                my @f_cols = map { s/\s*//g; $_ } split(/\s*,\s*/,$f_cols);
-
-                die "Mismatched column count in rel for $table => $f_table"
-                  if @cols != @f_cols;
-            
-                my $cond = {};
-                for(my $i = 0 ; $i < @cols; $i++) {
-                    $cond->{$f_cols[$i]} = $cols[$i];
+                my $cond;
+
+                if($f_cols) {
+                    my @cols = map { s/\s*//g; $_ } split(/\s*,\s*/,$cols);
+                    my @f_cols = map { s/\s*//g; $_ } split(/\s*,\s*/,$f_cols);
+                    die "Mismatched column count in rel for $table => $f_table"
+                      if @cols != @f_cols;
+                    $cond = {};
+                    for(my $i = 0 ; $i < @cols; $i++) {
+                        $cond->{$f_cols[$i]} = $cols[$i];
+                    }
+                }
+                else {
+                    $cond = $cols;
                 }
 
                 eval { $class->_loader_make_relations( $table, $f_table, $cond ) };
index bb0eedd..24c3f35 100644 (file)
@@ -51,7 +51,7 @@ sub _loader_relationships {
         $sth->execute;
         my $table_def = $sth->fetchrow_arrayref->[1] || '';
         
-        my (@reldata) = ($table_def =~ /CONSTRAINT `.*` FOREIGN KEY \(`(.*)`\) REFERENCES `(.*)` \(`(.*)`\)/g);
+        my (@reldata) = ($table_def =~ /CONSTRAINT `.*` FOREIGN KEY \(`(.*)`\) REFERENCES `(.*)` \(`(.*)`\)/ig);
 
         while (scalar @reldata > 0) {
             my $cols = shift @reldata;
index 3d49663..df7b08e 100644 (file)
@@ -17,6 +17,7 @@ my $tester = dbixcsl_common_tests->new(
     user            => $user,
     password        => $password,
     skip_rels       => $test_innodb ? 0 : $skip_rels_msg,
+    no_inline_rels  => 1,
 );
 
 if( !$database || !$user ) {
index 3bf8726..93da837 100644 (file)
@@ -36,7 +36,7 @@ sub skip_tests {
 sub run_tests {
     my $self = shift;
 
-    plan tests => 27;
+    plan tests => 32;
 
     $self->create();
 
@@ -83,7 +83,7 @@ sub run_tests {
     is( $obj2->id, 2 );
 
     SKIP: {
-        skip $self->{skip_rels}, 20 if $self->{skip_rels};
+        skip $self->{skip_rels}, 25 if $self->{skip_rels};
 
         my $moniker3 = $conn->moniker('loader_test3');
         my $rsobj3 = $conn->resultset($moniker3);
@@ -116,14 +116,14 @@ sub run_tests {
         my $obj5 = $rsobj5->find( id1 => 1, id2 => 1 );
         is( ref( $obj5->id2 ), '' );
 
-        # mulit-col fk def (works for some, not others...)
+        # mulit-col fk def
         my $obj6 = $rsobj6->find(1);
-        isa_ok( $obj6->loader_test2, "$schema_class\::$moniker2" );
-        is( ref( $obj6->loader_test5 ), "$schema_class\::$moniker5");
+        isa_ok( $obj6->loader_test2, "$schema_class\::$moniker2");
+        isa_ok( $obj6->loader_test5, "$schema_class\::$moniker5");
 
         # fk that references a non-pk key (UNIQUE)
         my $obj8 = $rsobj8->find(1);
-        isa_ok( $obj8->loader_test7, "$schema_class\::$moniker7" );
+        isa_ok( $obj8->loader_test7, "$schema_class\::$moniker7");
 
         # from Chisel's tests...
         SKIP: {
@@ -169,6 +169,24 @@ sub run_tests {
                     'found same $rsobj11 object we expected' );
             }
         }
+
+        SKIP: {
+            skip 'This vendor cannot do inline relationship definitions', 5
+                if $self->{no_inline_rels};
+
+            my $moniker12 = $conn->moniker('loader_test12');
+            my $rsobj12 = $conn->resultset($moniker12);
+            my $moniker13 = $conn->moniker('loader_test13');
+            my $rsobj13 = $conn->resultset($moniker13);
+
+            isa_ok( $rsobj12, "DBIx::Class::ResultSet" ); 
+            isa_ok( $rsobj13, "DBIx::Class::ResultSet" );
+
+            my $obj13 = $rsobj13->find(1);
+            isa_ok( $obj13->id, "$schema_class\::$moniker12" );
+            isa_ok( $obj13->loader_test12, "$schema_class\::$moniker12");
+            isa_ok( $obj13->dat, "$schema_class\::$moniker12");
+        }
     }
 }
 
@@ -322,6 +340,30 @@ sub create {
          q{ REFERENCES loader_test11 (id11) }),
     );
 
+    my @statements_inline_rels = (
+        qq{
+            CREATE TABLE loader_test12 (
+                id INTEGER NOT NULL PRIMARY KEY,
+                id2 VARCHAR(8) NOT NULL UNIQUE,
+                dat VARCHAR(8) UNIQUE
+            ) $self->{innodb}
+        },
+
+        q{ INSERT INTO loader_test12 (id,id2,dat) VALUES (1,'aaa','bbb') },
+
+        qq{
+            CREATE TABLE loader_test13 (
+                id INTEGER NOT NULL PRIMARY KEY REFERENCES loader_test12,
+                loader_test12 VARCHAR(8) NOT NULL REFERENCES loader_test12 (id2),
+                dat VARCHAR(8) REFERENCES loader_test12 (dat)
+            ) $self->{innodb}
+        },
+
+        (q{ INSERT INTO loader_test13 (id,loader_test12,dat) } .
+         q{ VALUES (1,'aaa','bbb') }),
+    );
+
+
     $self->drop_tables;
 
     $self->{created} = 1;
@@ -339,6 +381,9 @@ sub create {
         unless($self->{vendor} =~ /sqlite/i) {
             $dbh->do($_) for (@statements_advanced);
         }
+        unless($self->{no_inline_rels}) {
+            $dbh->do($_) for (@statements_inline_rels);
+        }
     }
     $dbh->disconnect();
 }
@@ -368,6 +413,11 @@ sub drop_tables {
         loader_test10
     /;
 
+    my @tables_inline_rels = qw/
+        loader_test13
+        loader_test12
+    /;
+
     my $drop_fk_mysql =
         q{ALTER TABLE loader_test10 DROP FOREIGN KEY loader_test11_fk;};
 
@@ -387,6 +437,9 @@ sub drop_tables {
             }
             $dbh->do("DROP TABLE $_") for (@tables_advanced);
         }
+        unless($self->{no_inline_rels}) {
+            $dbh->do("DROP TABLE $_") for (@tables_inline_rels);
+        }
     }
     $dbh->do("DROP TABLE $_") for (@tables);
     $dbh->disconnect;