rewrite datetime defaults as CURRENT_TIMESTAMP to ease cross-deployment
Rafael Kitover [Tue, 20 Apr 2010 05:30:47 +0000 (01:30 -0400)]
Changes
lib/DBIx/Class/Schema/Loader/DBI/DB2.pm
lib/DBIx/Class/Schema/Loader/DBI/MSSQL.pm
lib/DBIx/Class/Schema/Loader/DBI/Pg.pm
lib/DBIx/Class/Schema/Loader/DBI/SQLAnywhere.pm
t/13db2_common.t
t/16mssql_common.t
t/17sybase_asa_common.t

diff --git a/Changes b/Changes
index e95d077..9c53032 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,6 +1,7 @@
 Revision history for Perl extension DBIx::Class::Schema::Loader
 
-        - rewrite default_value \'now()' as \'CURRENT_TIMESTAMP' for Pg
+        - rewrite datetime default functions as \'CURRENT_TIMESTAMP' where
+          possible (except for Sybase ASE) to ease cross-deployment
         - use column_info instead of select to get Oracle column list (RT#42281)
         - match quotes in MySQL parser in more places (RT#42101)
         - fix unique detection in DB2 for multiple schemas (RT#39622)
index 7567d16..b6963be 100644 (file)
@@ -104,29 +104,35 @@ sub _table_fk_info {
 }
 
 sub _columns_info_for {
-    my ($self, $table) = @_;
-    return $self->next::method(uc $table);
-}
+    my $self = shift;
+    my ($table) = @_;
 
-sub _extra_column_info {
-    my ($self, $table, $column, $info, $dbi_info) = @_;
-    my %extra_info;
+    my $result = $self->next::method(uc $table);
 
     my $dbh = $self->schema->storage->dbh;
-    my $sth = $dbh->prepare_cached(
-        q{
-            SELECT COUNT(*)
-            FROM syscat.columns
-            WHERE tabschema = ? AND tabname = ? AND colname = ?
-            AND identity = 'Y' AND generated != ''
-        },
-        {}, 1);
-    $sth->execute($self->db_schema, $table, $column);
-    if ($sth->fetchrow_array) {
-        $extra_info{is_auto_increment} = 1;
+
+    while (my ($col, $info) = each %$result) {
+        # check for identities
+        my $sth = $dbh->prepare_cached(
+            q{
+                SELECT COUNT(*)
+                FROM syscat.columns
+                WHERE tabschema = ? AND tabname = ? AND colname = ?
+                AND identity = 'Y' AND generated != ''
+            },
+            {}, 1);
+        $sth->execute($self->db_schema, uc $table, uc $col);
+        if ($sth->fetchrow_array) {
+            $info->{is_auto_increment} = 1;
+        }
+
+        if (eval { lc ${ $info->{default_value} } }||'' eq 'CURRENT TIMESTAMP') {
+            ${ $info->{default_value} } = 'CURRENT_TIMESTAMP';
+            delete $info->{size};
+        }
     }
 
-    return \%extra_info;
+    return $result;
 }
 
 =head1 SEE ALSO
@@ -146,3 +152,4 @@ the same terms as Perl itself.
 =cut
 
 1;
+# vim:et sts=4 sw=4 tw=0:
index f3e5777..ee04770 100644 (file)
@@ -288,6 +288,10 @@ wHERE lower(table_name) = @{[ $dbh->quote(lc $table) ]} AND lower(column_name) =
             $info->{default_value} =
                 $default =~ /^['(] (.*) [)']\z/x ? $1 :
                     $default =~ /^\d/ ? $default : \$default;
+
+            if (eval { lc ${ $info->{default_value} } }||'' eq 'getdate()') {
+                ${ $info->{default_value} } = 'CURRENT_TIMESTAMP';
+            }
         }
     }
 
index b089a04..b89fe95 100644 (file)
@@ -201,8 +201,9 @@ EOF
             delete $result->{$col}{default_value};
         }
 
-# alias now() to current_timestamp for deploying to other DBs
-        if (eval { lc ${ $result->{$col}{default_value} } eq 'now()' }) {
+# alias now() to CURRENT_TIMESTAMP for deploying to other DBs
+        if (eval { lc ${ $result->{$col}{default_value} }||'' eq 'now()' }) {
+            # do not use a ref to a constant, that breaks Data::Dump output
             ${$result->{$col}{default_value}} = 'CURRENT_TIMESTAMP';
         }
     }
index 0205f02..2e16e96 100644 (file)
@@ -99,6 +99,10 @@ EOF
         }
 
         delete $info->{default_value} if ref($info->{default_value}) eq 'SCALAR' && ${ $info->{default_value} } eq 'NULL';
+
+        if (eval { lc ${ $info->{default_value} } }||'' eq 'current timestamp') {
+            ${ $info->{default_value} } = 'CURRENT_TIMESTAMP';
+        }
     }
 
     return $result;
index 2eefb47..6a7f17c 100644 (file)
@@ -9,11 +9,13 @@ my $password = $ENV{DBICTEST_DB2_PASS} || '';
 my $tester = dbixcsl_common_tests->new(
     vendor         => 'DB2',
     auto_inc_pk    => 'INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL PRIMARY KEY',
-    default_function => 'CURRENT TIMESTAMP',
     dsn            => $dsn,
     user           => $user,
     password       => $password,
     null           => '',
+    data_types => {
+        'timestamp DEFAULT CURRENT TIMESTAMP' => { data_type => 'timestamp', default_value => \'CURRENT_TIMESTAMP' }
+    },
 );
 
 if( !$dsn || !$user ) {
@@ -22,3 +24,4 @@ if( !$dsn || !$user ) {
 else {
     $tester->run_tests();
 }
+# vim:et sts=4 sw=4 tw=0:
index 0791bb4..1f3823a 100644 (file)
@@ -24,7 +24,6 @@ my $odbc_password = $ENV{DBICTEST_MSSQL_ODBC_PASS} || '';
 my $tester = dbixcsl_common_tests->new(
     vendor      => 'mssql',
     auto_inc_pk => 'INTEGER IDENTITY NOT NULL PRIMARY KEY',
-    default_function     => 'getdate()',
     default_function_def => 'DATETIME DEFAULT getdate()',
     connect_info => [ ($dbd_sybase_dsn ? {
             dsn         => $dbd_sybase_dsn,
@@ -68,8 +67,9 @@ my $tester = dbixcsl_common_tests->new(
         # datetime types
         date     => { data_type => 'date' },
         datetime => { data_type => 'datetime' },
+        # test rewriting getdate() to CURRENT_TIMESTAMP
         'datetime DEFAULT getdate()'
-                 => { data_type => 'datetime', default_value => \'getdate()' },
+                 => { data_type => 'datetime', default_value => \'CURRENT_TIMESTAMP' },
         smalldatetime  => { data_type => 'smalldatetime' },
         time     => { data_type => 'time' },
         'time(0)'=> { data_type => 'time', size => 0 },
index d9bdbd0..1d3495d 100644 (file)
@@ -5,6 +5,8 @@ use dbixcsl_common_tests;
 
 # The default max_cursor_count and max_statement_count settings of 50 are too
 # low to run this test.
+#
+# Setting them to zero is preferred.
 
 my $dbd_sqlanywhere_dsn      = $ENV{DBICTEST_SYBASE_ASA_DSN} || '';
 my $dbd_sqlanywhere_user     = $ENV{DBICTEST_SYBASE_ASA_USER} || '';
@@ -17,7 +19,6 @@ my $odbc_password = $ENV{DBICTEST_SYBASE_ASA_ODBC_PASS} || '';
 my $tester = dbixcsl_common_tests->new(
     vendor      => 'SQLAnywhere',
     auto_inc_pk => 'INTEGER IDENTITY NOT NULL PRIMARY KEY',
-    default_function => 'current timestamp',
     connect_info => [ ($dbd_sqlanywhere_dsn ? {
             dsn         => $dbd_sqlanywhere_dsn,
             user        => $dbd_sqlanywhere_user,
@@ -90,8 +91,9 @@ my $tester = dbixcsl_common_tests->new(
         'smalldatetime'
                       => { data_type => 'smalldatetime' },
         'timestamp'   => { data_type => 'timestamp' },
+        # rewrite 'current timestamp' as 'CURRENT_TIMESTAMP'
         'timestamp DEFAULT current timestamp'
-                      => { data_type => 'timestamp', default_value => \"current timestamp" },
+                      => { data_type => 'timestamp', default_value => \"CURRENT_TIMESTAMP" },
         'time'        => { data_type => 'time' },
 
         # String Types