fix enum/set detection for MySQL (RT#68717)
Rafael Kitover [Fri, 10 Jun 2011 04:55:58 +0000 (00:55 -0400)]
Changes
lib/DBIx/Class/Schema/Loader/DBI.pm
lib/DBIx/Class/Schema/Loader/DBI/mysql.pm
t/10_02mysql_common.t

diff --git a/Changes b/Changes
index baf4363..84aeffe 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,5 +1,6 @@
 Revision history for Perl extension DBIx::Class::Schema::Loader
 
+        - fix enum/set detection for MySQL (RT#68717)
         - fix is_nullable detection on MS Access
         - remove '$table has no primary key' warning
         - added uniq_to_primary option to promote unique keys to primary keys
index 0f53430..964e923 100644 (file)
@@ -381,7 +381,7 @@ sub _columns_info_for {
             $column_info->{size}    = $2;
         }
 
-        my $extra_info = $self->_extra_column_info($table, $columns[$i], $column_info) || {};
+        my $extra_info = $self->_extra_column_info($table, $columns[$i], $column_info, $sth) || {};
         $column_info = { %$column_info, %$extra_info };
 
         $result{ $self->_lc($columns[$i]) } = $column_info;
index 4712fdf..d037e98 100644 (file)
@@ -133,14 +133,15 @@ sub _columns_info_for {
     my $dbh = $self->schema->storage->dbh;
 
     while (my ($col, $info) = each %$result) {
-        delete $info->{size} if $info->{data_type} !~ /^(?: (?:var)?(?:char(?:acter)?|binary) | bit | year)\z/ix;
-
         if ($info->{data_type} eq 'int') {
             $info->{data_type} = 'integer';
         }
         elsif ($info->{data_type} eq 'double') {
             $info->{data_type} = 'double precision';
         }
+        my $data_type = $info->{data_type};
+
+        delete $info->{size} if $data_type !~ /^(?: (?:var)?(?:char(?:acter)?|binary) | bit | year)\z/ix;
 
         # information_schema is available in 5.0+
         my ($precision, $scale, $column_type, $default) = eval { $dbh->selectrow_array(<<'EOF', {}, $table, $col) };
@@ -148,14 +149,14 @@ SELECT numeric_precision, numeric_scale, column_type, column_default
 FROM information_schema.columns
 WHERE table_name = ? AND column_name = ?
 EOF
-        my $has_information_schema = not defined $@;
+        my $has_information_schema = not $@;
 
         $column_type = '' if not defined $column_type;
 
-        if ($info->{data_type} eq 'bit' && (not exists $info->{size})) {
+        if ($data_type eq 'bit' && (not exists $info->{size})) {
             $info->{size} = $precision if defined $precision;
         }
-        elsif ($info->{data_type} =~ /^(?:float|double precision|decimal)\z/i) {
+        elsif ($data_type =~ /^(?:float|double precision|decimal)\z/i) {
             if (defined $precision && defined $scale) {
                 if ($precision == 10 && $scale == 0) {
                     delete $info->{size};
@@ -165,7 +166,7 @@ EOF
                 }
             }
         }
-        elsif ($info->{data_type} eq 'year') {
+        elsif ($data_type eq 'year') {
             if ($column_type =~ /\(2\)/) {
                 $info->{size} = 2;
             }
@@ -173,11 +174,20 @@ EOF
                 delete $info->{size};
             }
         }
-        elsif ($info->{data_type} =~ /^(?:date(?:time)?|timestamp)\z/) {
+        elsif ($data_type =~ /^(?:date(?:time)?|timestamp)\z/) {
             if (not (defined $self->datetime_undef_if_invalid && $self->datetime_undef_if_invalid == 0)) {
                 $info->{datetime_undef_if_invalid} = 1;
             }
         }
+        elsif ($data_type =~ /^(?:enum|set)\z/ && $has_information_schema
+               && $column_type =~ /^(?:enum|set)\(/) {
+
+            delete $info->{extra}{list};
+
+            while ($column_type =~ /'([^']+)',?/g) {
+                push @{ $info->{extra}{list} }, $1;
+            }
+        }
 
         # Sometimes apparently there's a bug where default_value gets set to ''
         # for things that don't actually have or support that default (like ints.)
@@ -188,7 +198,7 @@ EOF
                 }
             }
             else { # just check if it's a char/text type, otherwise remove
-                delete $info->{default_value} unless $info->{data_type} =~ /char|text/i;
+                delete $info->{default_value} unless $data_type =~ /char|text/i;
             }
         }
     }
index 9f1a366..8f674a7 100644 (file)
@@ -124,6 +124,13 @@ my $tester = dbixcsl_common_tests->new(
                       => { data_type => 'enum', extra => { list => [qw/foo bar baz/] } },
         "set('foo','bar','baz')"
                       => { data_type => 'set',  extra => { list => [qw/foo bar baz/] } },
+
+        # RT#68717
+        "enum('11,10 (<500)/0 DUN','4,90 (<120)/0 EUR') NOT NULL default '11,10 (<500)/0 DUN'"
+                      => { data_type => 'enum', extra => { list => ['11,10 (<500)/0 DUN', '4,90 (<120)/0 EUR'] }, default_value => '11,10 (<500)/0 DUN' },
+        "set('11_10 (<500)/0 DUN','4_90 (<120)/0 EUR') NOT NULL default '11_10 (<500)/0 DUN'"
+                      => { data_type => 'set', extra => { list => ['11_10 (<500)/0 DUN', '4_90 (<120)/0 EUR'] }, default_value => '11_10 (<500)/0 DUN' },
+
     },
     extra => {
         create => [