schema-loader does multi-column FKs now, needs a bit of cleanup/refactor work
[dbsrgits/DBIx-Class-Schema-Loader.git] / lib / DBIx / Class / Schema / Loader / mysql.pm
1 package DBIx::Class::Schema::Loader::mysql;
2
3 use strict;
4 use base 'DBIx::Class::Schema::Loader::Generic';
5 use Carp;
6
7 =head1 NAME
8
9 DBIx::Class::Schema::Loader::mysql - DBIx::Schema::Class::Loader mysql Implementation.
10
11 =head1 SYNOPSIS
12
13   use DBIx::Class::Schema::Loader;
14
15   # $loader is a DBIx::Class::Schema::Loader::mysql
16   my $loader = DBIx::Class::Schema::Loader->new(
17     dsn       => "dbi:mysql:dbname",
18     user      => "root",
19     password  => "",
20   );
21
22 =head1 DESCRIPTION
23
24 See L<DBIx::Class::Schema::Loader>.
25
26 =cut
27
28 sub _db_classes {
29     return qw/DBIx::Class::PK::Auto::MySQL/;
30 }
31
32 sub _relationships {
33     my $class   = shift;
34     my @tables = $class->tables;
35     my $dbh    = $class->storage->dbh;
36     my $dsn    = $class->loader_data->{_datasource}[0];
37     my %conn   =
38       $dsn =~ m/\Adbi:\w+(?:\(.*?\))?:(.+)\z/i
39       && index( $1, '=' ) >= 0
40       ? split( /[=;]/, $1 )
41       : ( database => $1 );
42     my $dbname = $conn{database} || $conn{dbname} || $conn{db};
43     die("Can't figure out the table name automatically.") if !$dbname;
44
45     my $quoter = $dbh->get_info(29);
46
47     foreach my $table (@tables) {
48         my $query = "SHOW CREATE TABLE ${dbname}.${table}";
49         my $sth   = $dbh->prepare($query)
50           or die("Cannot get table definition: $table");
51         $sth->execute;
52         my $table_def = $sth->fetchrow_arrayref->[1] || '';
53         
54         my (@reldata) = ($table_def =~ /CONSTRAINT `.*` FOREIGN KEY \(`(.*)`\) REFERENCES `(.*)` \(`(.*)`\)/g);
55
56         while (scalar @reldata > 0) {
57             my $cols = shift @reldata;
58             my $f_table = shift @reldata;
59             my $f_cols = shift @reldata;
60
61             my @cols = map { s/$quoter//; $_ } split(/\s*,\s*/,$cols);
62             my @f_cols = map { s/$quoter//; $_ } split(/\s*,\s*/,$f_cols);
63             die "Mismatched column count in rel for $table => $f_table"
64               if @cols != @f_cols;
65             
66             my $cond = {};
67             for(my $i = 0 ; $i < @cols; $i++) {
68                 $cond->{$f_cols[$i]} = $cols[$i];
69             }
70
71             eval { $class->_belongs_to_many( $table, $f_table, $cond) };
72             warn qq/\# belongs_to_many failed "$@"\n\n/ if $@ && $class->debug_loader;
73         }
74         
75         $sth->finish;
76     }
77 }
78
79 sub _tables {
80     my $class = shift;
81     my $dbh    = $class->storage->dbh;
82     my @tables;
83     foreach my $table ( $dbh->tables ) {
84         my $quoter = $dbh->get_info(29);
85         $table =~ s/$quoter//g if ($quoter);
86         push @tables, $1
87           if $table =~ /\A(\w+)\z/;
88     }
89     return @tables;
90 }
91
92 sub _table_info {
93     my ( $class, $table ) = @_;
94     my $dbh    = $class->storage->dbh;
95
96     # MySQL 4.x doesn't support quoted tables
97     my $query = "DESCRIBE $table";
98     my $sth = $dbh->prepare($query) or die("Cannot get table status: $table");
99     $sth->execute;
100     my ( @cols, @pri );
101     while ( my $hash = $sth->fetchrow_hashref ) {
102         my ($col) = $hash->{Field} =~ /(\w+)/;
103         push @cols, $col;
104         push @pri, $col if $hash->{Key} eq "PRI";
105     }
106
107     return ( \@cols, \@pri );
108 }
109
110 =head1 SEE ALSO
111
112 L<DBIx::Class::Schema::Loader>
113
114 =cut
115
116 1;