Understand Postgres enumerated types
Stephen Bennett [Sun, 7 Nov 2010 21:51:40 +0000 (21:51 +0000)]
Changes
lib/DBIx/Class/Schema/Loader.pm
lib/DBIx/Class/Schema/Loader/DBI/Pg.pm
t/12pg_common.t
t/lib/dbixcsl_common_tests.pm

diff --git a/Changes b/Changes
index ba5f445..1c12d4a 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,5 +1,6 @@
 Revision history for Perl extension DBIx::Class::Schema::Loader
 
+        - Added support for PostgreSQL enum types
         - Added table/column comment support for Oracle
         - Fix missing require (RT#62072)
 
index 2f886ee..f4692ec 100644 (file)
@@ -518,6 +518,8 @@ hobbs: Andrew Rodland <arodland@cpan.org>
 
 domm: Thomas Klausner <domm@plix.at>
 
+spb: Stephen Bennett <spb@exherbo.org>
+
 ... and lots of other folks. If we forgot you, please write the current
 maintainer or RT.
 
index 8e4d7c1..1b922f1 100644 (file)
@@ -224,6 +224,18 @@ EOF
         elsif (lc($data_type) eq 'character') {
             $info->{data_type} = 'char';
         }
+        else {
+            my ($typetype) = $self->schema->storage->dbh
+                ->selectrow_array(<<EOF, {}, $data_type);
+SELECT typtype
+FROM pg_catalog.pg_type
+WHERE typname = ?
+EOF
+            if ($typetype eq 'e') {
+                $info->{data_type} = 'enum';
+            }
+        }
+
 
 # process SERIAL columns
         if (ref($info->{default_value}) eq 'SCALAR' && ${ $info->{default_value} } =~ /\bnextval\(['"]([.\w]+)/i) {
@@ -245,6 +257,28 @@ EOF
     return $result;
 }
 
+sub _extra_column_info {
+    my ($self, $table, $col, $info, $dbi_info) = @_;
+    my %extra_info;
+
+    # The following will extract a list of allowed values if this
+    # is an enumerated type. Otherwise, no results and we do nothing.
+    my $typevalues = $self->schema->storage->dbh
+        ->selectall_arrayref(<<EOF, {}, $info->{data_type});
+SELECT e.enumlabel
+FROM pg_catalog.pg_enum e
+JOIN pg_catalog.pg_type t ON t.oid = e.enumtypid
+WHERE t.typname = ?
+EOF
+
+    if (@$typevalues) {
+        $extra_info{extra}{list} = [ map { $_->[0] } @$typevalues ];
+    }
+
+    return \%extra_info;
+}
+
+
 =head1 SEE ALSO
 
 L<DBIx::Class::Schema::Loader>, L<DBIx::Class::Schema::Loader::Base>,
index 3b7baa8..bdac57a 100644 (file)
@@ -112,7 +112,17 @@ my $tester = dbixcsl_common_tests->new(
 
         # Blob Types
        bytea => { data_type => 'bytea' },
+
+        # Enum Types
+        pg_loader_test_enum => { data_type => 'enum', extra => { list => [ qw/foo bar baz/] }, size => 4 },
     },
+    pre_create => [
+        q{
+            CREATE TYPE pg_loader_test_enum AS ENUM (
+                'foo', 'bar', 'baz'
+            )
+        },
+    ],
     extra       => {
         create => [
             q{
@@ -145,6 +155,7 @@ my $tester = dbixcsl_common_tests->new(
         ],
         pre_drop_ddl => [
             'DROP SCHEMA dbicsl_test CASCADE',
+            'DROP TYPE pg_loader_test_enum',
         ],
         drop  => [ qw/ pg_loader_test1 pg_loader_test2 / ],
         count => 4,
index 41bfdd3..7922a30 100644 (file)
@@ -1585,6 +1585,8 @@ sub create {
 
     my $dbh = $self->dbconnect(1);
 
+    $dbh->do($_) for @{ $self->{pre_create} || [] };
+
     $dbh->do($_) foreach (@statements);
 
     $dbh->do($_) foreach (@{ $self->{data_type_tests}{ddl} || [] });