Support a custom_type_name hint for Pg enum creation
Peter Rabbitson [Wed, 10 Nov 2010 22:57:56 +0000 (22:57 +0000)]
AUTHORS
Changes
lib/SQL/Translator/Producer/PostgreSQL.pm
t/47postgres-producer.t

diff --git a/AUTHORS b/AUTHORS
index 242b3ab..5ca471f 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -28,6 +28,7 @@ The following people have contributed to the SQLFairy project:
 -   Ross Smith II <rossta@users.sf.net>
 -   Ryan D Johnson <ryan@innerfence.com>
 -   Sam Angiuoli <angiuoli@users.sourceforge.net>
+-   Stephen Bennett <stephen@freenode.net>
 -   Stephen Clouse <stephenclouse@gmail.com>
 -   Wallace Reis <wreis@cpan.org>
 -   Ying Zhang <zyolive@yahoo.com>
diff --git a/Changes b/Changes
index b30bfb3..0081690 100644 (file)
--- a/Changes
+++ b/Changes
@@ -2,6 +2,7 @@
 * Add explicit Scalar::Util to the deplist for really old perls
 * Add support for PostGIS Geometry and Geography data types in the Pg producer
 * Some minor fixes to squash warnings on new perls
+* Support a custom_type_name hint when creating enum types in PostgreSQL
 
 # ----------------------------------------------------------
 # 0.11006 2010-06-03
index f8f5438..485fae4 100644 (file)
@@ -195,6 +195,7 @@ sub produce {
     push @output, header_comment unless ($no_comments);
 
     my (@table_defs, @fks);
+    my %type_defs;
     for my $table ( $schema->get_tables ) {
 
         my ($table_def, $fks) = create_table($table, { 
@@ -203,6 +204,7 @@ sub produce {
             no_comments       => $no_comments,
             postgres_version  => $postgres_version,
             add_drop_table    => $add_drop_table,
+            type_defs         => \%type_defs,
         });
 
         push @table_defs, $table_def;
@@ -218,6 +220,7 @@ sub produce {
       });
     }
 
+    push @output, map { "$_;\n\n" } values %type_defs;
     push @output, map { "$_;\n\n" } @table_defs;
     if ( @fks ) {
         push @output, "--\n-- Foreign Key Definitions\n--\n\n" unless $no_comments;
@@ -335,6 +338,7 @@ sub create_table
     my $no_comments = $options->{no_comments} || 0;
     my $add_drop_table = $options->{add_drop_table} || 0;
     my $postgres_version = $options->{postgres_version} || 0;
+    my $type_defs = $options->{type_defs} || {};
 
     my $table_name = $table->name or next;
     my ( $fql_tbl_name ) = ( $table_name =~ s/\W(.*)$// ) ? $1 : q{};
@@ -344,7 +348,7 @@ sub create_table
     $table->name($table_name_ur);
 
 # print STDERR "$table_name table_name\n";
-    my ( @comments, @field_defs, @sequence_defs, @constraint_defs, @type_defs, @type_drops, @fks );
+    my ( @comments, @field_defs, @sequence_defs, @constraint_defs, @fks );
 
     push @comments, "--\n-- Table: $table_name_ur\n--\n" unless $no_comments;
 
@@ -364,8 +368,7 @@ sub create_table
                                                  quote_field_names => $qf,
                                                  table_name => $table_name_ur,
                                                  postgres_version => $postgres_version,
-                                                 type_defs => \@type_defs,
-                                                 type_drops => \@type_drops,
+                                                 type_defs => $type_defs,
                                                  constraint_defs => \@constraint_defs,});
     }
 
@@ -412,14 +415,10 @@ sub create_table
     if ($add_drop_table) {
         if ($postgres_version >= 8.002) {
             $create_statement .= qq[DROP TABLE IF EXISTS $qt$table_name_ur$qt CASCADE;\n];
-            $create_statement .= join (";\n", @type_drops) . ";\n"
-                if $postgres_version >= 8.003 && scalar @type_drops;
         } else {
             $create_statement .= qq[DROP TABLE $qt$table_name_ur$qt CASCADE;\n];
         }
     }
-    $create_statement .= join(";\n", @type_defs) . ";\n"
-        if $postgres_version >= 8.003 && scalar @type_defs;
     $create_statement .= qq[CREATE ${temporary}TABLE $qt$table_name_ur$qt (\n].
                             join( ",\n", map { "  $_" } @field_defs, @constraint_defs ).
                             "\n)"
@@ -488,8 +487,7 @@ sub create_view {
         my $table_name = $field->table->name;
         my $constraint_defs = $options->{constraint_defs} || [];
         my $postgres_version = $options->{postgres_version} || 0;
-        my $type_defs = $options->{type_defs} || [];
-        my $type_drops = $options->{type_drops} || [];
+        my $type_defs = $options->{type_defs} || {};
 
         $field_name_scope{$table_name} ||= {};
         my $field_name    = $field->name;
@@ -512,10 +510,15 @@ sub create_view {
         my $commalist = join( ', ', map { qq['$_'] } @$list );
 
         if ($postgres_version >= 8.003 && $field->data_type eq 'enum') {
-            my $type_name = $field->table->name . '_' . $field->name . '_type';
+            my $type_name = $extra{'custom_type_name'} || $field->table->name . '_' . $field->name . '_type';
             $field_def .= ' '. $type_name;
-            push @$type_defs, "CREATE TYPE $type_name AS ENUM ($commalist)";
-            push @$type_drops, "DROP TYPE IF EXISTS $type_name";
+            my $new_type_def = "DROP TYPE IF EXISTS $type_name;\n" .
+                               "CREATE TYPE $type_name AS ENUM ($commalist)";
+            if (! exists $type_defs->{$type_name} ) {
+                $type_defs->{$type_name} = $new_type_def;
+            } elsif ( $type_defs->{$type_name} ne $new_type_def ) {
+                die "Attempted to redefine type name '$type_name' as a different type.\n";
+            }
         } else {
             $field_def .= ' '. convert_datatype($field);
         }
index ec31cd6..01969d7 100644 (file)
@@ -14,7 +14,7 @@ use FindBin qw/$Bin/;
 #=============================================================================
 
 BEGIN {
-    maybe_plan(25,
+    maybe_plan(26,
         'SQL::Translator::Producer::PostgreSQL',
         'Test::Differences',
     )
@@ -269,6 +269,20 @@ my $field12_sql = SQL::Translator::Producer::PostgreSQL::create_field($field12,{
 
 is($field12_sql, 'time_field timestamp NOT NULL', 'time with precision');
 
+my $field13 = SQL::Translator::Schema::Field->new( name => 'enum_field_with_type_name',
+                                                   table => $table,
+                                                   data_type => 'enum',
+                                                   extra => { list => [ 'Foo', 'Bar' ],
+                                                              custom_type_name => 'real_enum_type' },
+                                                   is_auto_increment => 0,
+                                                   is_nullable => 0,
+                                                   is_foreign_key => 0,
+                                                   is_unique => 0 );
+
+my $field13_sql = SQL::Translator::Producer::PostgreSQL::create_field($field13,{ postgres_version => 8.3 });
+
+is($field13_sql, 'enum_field_with_type_name real_enum_type NOT NULL', 'Create real enum field works');
+
 
 {
     # let's test default values! -- rjbs, 2008-09-30