Now supporting scalar refs as default values! (rjbs)
Jess Robinson [Thu, 9 Oct 2008 22:27:41 +0000 (22:27 +0000)]
Changes
lib/SQL/Translator/Producer.pm
lib/SQL/Translator/Producer/MySQL.pm
lib/SQL/Translator/Producer/Oracle.pm
lib/SQL/Translator/Producer/PostgreSQL.pm
lib/SQL/Translator/Producer/SQLServer.pm
lib/SQL/Translator/Producer/SQLite.pm
t/47postgres-producer.t

diff --git a/Changes b/Changes
index 6144f16..188832a 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,6 +1,7 @@
 # ----------------------------------------------------------
 # 
 # ----------------------------------------------------------
+* Applied patch from rjbs with minor changes, now we support scalar refs in default values!
 * Fixed SQLite producer to end index statements in newlines, in scalar context
 * Decreed that all list context statements shall not end in ; or ;\n
 * Fixed SQLite, Diff and MySQL producers to agree with Decree.
index 1b2baf2..3366dc1 100644 (file)
@@ -26,6 +26,37 @@ $VERSION = sprintf "%d.%02d", q$Revision: 1.8 $ =~ /(\d+)\.(\d+)/;
 
 sub produce { "" }
 
+# Do not rely on this if you are not bundled with SQL::Translator.
+# -- rjbs, 2008-09-30
+## $exceptions contains an arrayref of paired values
+## Each pair contains a pattern match or string, and a value to be used as
+## the default if matched.
+## They are special per Producer, and provide support for the old 'now()'
+## default value exceptions
+sub _apply_default_value {
+  my (undef, $field_ref, $default, $exceptions) = @_;
+
+  if ($exceptions and ! ref $default) {
+    for (my $i = 0; $i < @$exceptions; $i += 2) {
+      my ($pat, $val) = @$exceptions[ $i, $i + 1 ];
+      if (ref $pat and $default =~ $pat) {
+          $default = $val;
+          last;
+      } elsif (lc $default eq lc $pat) {
+          $default = $val;
+          last
+      }
+    }
+  }
+
+  if (ref $default) {
+      $$field_ref .= " DEFAULT $$default";
+  } else {
+      $$field_ref .= " DEFAULT '$default'";
+  }
+
+}
+
 1;
 
 # -------------------------------------------------------------------
index f09d5d7..9121160 100644 (file)
@@ -554,11 +554,13 @@ sub create_field
     # Default?  XXX Need better quoting!
     my $default = $field->default_value;
     if ( defined $default ) {
-        if ( uc $default eq 'NULL') {
-            $field_def .= ' DEFAULT NULL';
-        } else {
-            $field_def .= " DEFAULT '$default'";
-        }
+        SQL::Translator::Producer->_apply_default_value(
+          \$field_def,
+          $default, 
+          [
+            'NULL'       => \'NULL',
+          ],
+        );
     }
 
     if ( my $comments = $field->comments ) {
index e603124..b43ef99 100644 (file)
@@ -548,7 +548,11 @@ sub create_field {
         # then sub "1/0," otherwise just test the truthity of the
         # argument and use that (naive?).
         #
-        if ( 
+        if (ref $default and defined $$default) {
+          $default = $$default;
+        } elsif (ref $default) {
+          $default = 'NULL';
+        } elsif ( 
             $data_type =~ /^number$/i && 
             $default   !~ /^-?\d+$/     &&
             $default   !~ m/null/i
index ac68634..495f529 100644 (file)
@@ -485,7 +485,6 @@ sub create_view {
         my $list      = $extra{'list'} || [];
         # todo deal with embedded quotes
         my $commalist = join( ', ', map { qq['$_'] } @$list );
-        my $seq_name;
 
         if ($postgres_version >= 8.3 && $field->data_type eq 'enum') {
             my $type_name = $field->table->name . '_' . $field->name . '_type';
@@ -497,20 +496,19 @@ sub create_view {
         }
 
         #
-        # Default value -- disallow for timestamps
+        # Default value 
         #
-#        my $default = $data_type =~ /(timestamp|date)/i
-#            ? undef : $field->default_value;
         my $default = $field->default_value;
         if ( defined $default ) {
-            my $qd = "'";
-            $qd = '' if ($default eq 'now()' || 
-                         $default eq 'CURRENT_TIMESTAMP');
-            $field_def .= sprintf( ' DEFAULT %s',
-                                   ( $field->is_auto_increment && $seq_name )
-                                   ? qq[nextval('"$seq_name"'::text)] :
-                                   ( $default =~ m/null/i ) ? 'NULL' : "$qd$default$qd"
-                                   );
+            SQL::Translator::Producer->_apply_default_value(
+              \$field_def,
+              $default,
+              [
+                'NULL'              => \'NULL',
+                'now()'             => 'now()',
+                'CURRENT_TIMESTAMP' => 'CURRENT_TIMESTAMP',
+              ],
+            );
         }
 
         #
index 1a0c294..a65cf30 100644 (file)
@@ -189,7 +189,6 @@ sub produce {
             my $list           = $extra{'list'} || [];
             # \todo deal with embedded quotes
             my $commalist      = join( ', ', map { qq['$_'] } @$list );
-            my $seq_name;
 
             if ( $data_type eq 'enum' ) {
                 my $check_name = mk_name(
@@ -256,13 +255,15 @@ sub produce {
             #
             my $default = $field->default_value;
             if ( defined $default ) {
-                $field_def .= sprintf( ' DEFAULT %s',
-                    ( $field->is_auto_increment && $seq_name )
-                    ? qq[nextval('"$seq_name"'::text)] :
-                    ( $default =~ m/null/i ) ? 'NULL' : "'$default'"
+                SQL::Translator::Producer->_apply_default_value(
+                  \$field_def,
+                  $default, 
+                  [
+                    'NULL'       => \'NULL',
+                  ],
                 );
             }
-            
+
             push @field_defs, $field_def;            
         }
 
index 4526951..99fc885 100644 (file)
@@ -287,17 +287,16 @@ sub create_field
 
     # Default?  XXX Need better quoting!
     my $default = $field->default_value;
-    if ( defined $default ) {
-        if ( uc $default eq 'NULL') {
-            $field_def .= ' DEFAULT NULL';
-        } elsif ( $default eq 'now()' ||
-                  $default eq 'CURRENT_TIMESTAMP' ) {
-            $field_def .= ' DEFAULT CURRENT_TIMESTAMP';
-        } elsif ( $default =~ /val\(/ ) {
-            next;
-        } else {
-            $field_def .= " DEFAULT '$default'";
-        }
+    if (defined $default) {
+        SQL::Translator::Producer->_apply_default_value(
+            \$field_def,
+            $default, 
+            [
+             'NULL'              => \'NULL',
+             'now()'             => 'now()',
+             'CURRENT_TIMESTAMP' => 'CURRENT_TIMESTAMP',
+            ],
+        );
     }
 
     return $field_def;
index 5dc7ccc..8203602 100644 (file)
@@ -14,7 +14,7 @@ use FindBin qw/$Bin/;
 #=============================================================================
 
 BEGIN {
-    maybe_plan(9,
+    maybe_plan(13,
         'SQL::Translator::Producer::PostgreSQL',
         'Test::Differences',
     )
@@ -22,7 +22,7 @@ BEGIN {
 use Test::Differences;
 use SQL::Translator;
 
-
+my $PRODUCER = \&SQL::Translator::Producer::PostgreSQL::create_field;
 
 my $table = SQL::Translator::Schema::Table->new( name => 'mytable');
 
@@ -104,6 +104,76 @@ my $field5_sql = SQL::Translator::Producer::PostgreSQL::create_field($field5,{ p
 
 is($field5_sql, 'enum_field mytable_enum_field_type NOT NULL', 'Create real enum field works');
 
+{
+    # let's test default values! -- rjbs, 2008-09-30
+    my %field = (
+        table => $table,
+        data_type => 'VARCHAR',
+        size => 10,
+        is_auto_increment => 0,
+        is_nullable => 1,
+        is_foreign_key => 0,
+        is_unique => 0,
+    );
+
+    {
+        my $simple_default = SQL::Translator::Schema::Field->new(
+            %field,
+            name => 'str_default',
+            default_value => 'foo',
+        );
+
+        is(
+            $PRODUCER->($simple_default),
+            q{str_default character varying(10) DEFAULT 'foo'},
+            'default str',
+        );
+    }
+
+    {
+        my $null_default = SQL::Translator::Schema::Field->new(
+            %field,
+            name => 'null_default',
+            default_value => \'NULL',
+        );
+
+        is(
+            $PRODUCER->($null_default),
+            q{null_default character varying(10) DEFAULT NULL},
+            'default null',
+        );
+    }
+
+    {
+        my $null_default = SQL::Translator::Schema::Field->new(
+            %field,
+            name => 'null_default_2',
+            default_value => 'NULL', # XXX: this should go away
+        );
+
+        is(
+            $PRODUCER->($null_default),
+            q{null_default_2 character varying(10) DEFAULT NULL},
+            'default null from special cased string',
+        );
+    }
+
+    {
+        my $func_default = SQL::Translator::Schema::Field->new(
+            %field,
+            name => 'func_default',
+            default_value => \'func(funky)',
+        );
+
+        is(
+            $PRODUCER->($func_default),
+            q{func_default character varying(10) DEFAULT func(funky)},
+            'unquoted default from scalar ref',
+        );
+    }
+}
+
+
 my $view1 = SQL::Translator::Schema::View->new(
     name   => 'view_foo',
     fields => [qw/id name/],