Skip dumping unique indexes with expressions (RT#93613)
Dagfinn Ilmari Mannsåker [Fri, 4 Apr 2014 15:27:22 +0000 (16:27 +0100)]
DBD::Pg 3.0.0 returns expression indexes from ->statistics_info, with
COLUMN_NAME => undef and pg_expression => $expression.  Because
->_table_uniq_info just skipped individual rows without COLUMN_NAME,
an index contains a mix of plain columns and expressions would
generate erroneous ->add_unique_constraint() calls.

Changes
lib/DBIx/Class/Schema/Loader/DBI.pm
t/10_03pg_common.t

diff --git a/Changes b/Changes
index 39c3788..7b47e7f 100644 (file)
--- a/Changes
+++ b/Changes
@@ -2,6 +2,7 @@ Revision history for Perl extension DBIx::Class::Schema::Loader
 
         - Add options to omit the version and timestamp from the
           generated code (RT#92300)
+        - Skip dumping unique indexes with expressions (RT#93613)
 
 0.07039  2014-01-06
         - Fix table listing with DBD::DB2 >= 1.85 (RT#91764)
index 35efed8..2c23e4c 100644 (file)
@@ -340,17 +340,18 @@ sub _table_uniq_info {
         next if $row->{TYPE} eq 'table'
             || defined $row->{FILTER_CONDITION}
             || !$row->{INDEX_NAME}
-            || !defined $row->{ORDINAL_POSITION}
-            || !$row->{COLUMN_NAME};
+            || !defined $row->{ORDINAL_POSITION};
 
-        $indices{$row->{INDEX_NAME}}[$row->{ORDINAL_POSITION}] = $self->_lc($row->{COLUMN_NAME});
+        $indices{$row->{INDEX_NAME}}[$row->{ORDINAL_POSITION}] = $self->_lc($row->{COLUMN_NAME} || '');
     }
     $sth->finish;
 
     my @retval;
     foreach my $index_name (keys %indices) {
-        my $index = $indices{$index_name};
-        push(@retval, [ $index_name => [ @$index[1..$#$index] ] ]);
+        my (undef, @cols) = @{$indices{$index_name}};
+        # skip indexes with missing column names (e.g. expression indexes)
+        next unless @cols == grep $_, @cols;
+        push(@retval, [ $index_name => \@cols ]);
     }
 
     return \@retval;
index 477ff0a..1da712b 100644 (file)
@@ -246,6 +246,22 @@ my $tester = dbixcsl_common_tests->new(
                 create view pg_loader_test11 as
                     select * from pg_loader_test1
             },
+            q{
+                create table pg_loader_test12 (
+                    id integer not null,
+                    name text
+                )
+            },
+            q{
+                create unique index uniq_id_lc_name on pg_loader_test12 (
+                    id, lower(name)
+                )
+            },
+            q{
+                create unique index uniq_uc_name_id on pg_loader_test12 (
+                    upper(name), id
+                )
+            },
         ],
         pre_drop_ddl => [
             'DROP SCHEMA dbicsl_test CASCADE',
@@ -254,8 +270,8 @@ my $tester = dbixcsl_common_tests->new(
             'DROP TYPE pg_loader_test_enum',
             'DROP VIEW pg_loader_test11',
         ],
-        drop  => [ qw/pg_loader_test1 pg_loader_test2 pg_loader_test9 pg_loader_test10/ ],
-        count => 9 + 30 * 2,
+        drop  => [ qw/pg_loader_test1 pg_loader_test2 pg_loader_test9 pg_loader_test10 pg_loader_test12/ ],
+        count => 10 + 30 * 2,
         run   => sub {
             my ($schema, $monikers, $classes) = @_;
 
@@ -449,6 +465,9 @@ my $tester = dbixcsl_common_tests->new(
             # test that views are marked as such
             isa_ok $schema->resultset($monikers->{pg_loader_test11})->result_source, 'DBIx::Class::ResultSource::View',
                 'views have table_class set correctly';
+
+            is_deeply { $schema->source($monikers->{pg_loader_test12})->unique_constraints },
+                {}, 'unique indexes with expressions are not dumped';
         },
     },
 );