fix type info for MSSQL
Rafael Kitover [Sat, 10 Apr 2010 01:18:30 +0000 (21:18 -0400)]
Changes
lib/DBIx/Class/Schema/Loader/DBI/MSSQL.pm
t/16mssql_common.t

diff --git a/Changes b/Changes
index da58fa4..ba34f30 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,5 +1,6 @@
 Revision history for Perl extension DBIx::Class::Schema::Loader
 
+        - fix type info for MSSQL
         - fix MSSQL collation detection on freetds tds version 8.0
 
 0.06000  2010-04-06 01:12:25
index 7a019d9..bdd3212 100644 (file)
@@ -37,9 +37,9 @@ We attempt to detect the database collation at startup, and set the column
 lowercasing behavior accordingly, as lower-cased column names do not work on
 case-sensitive databases.
 
-To manually set or unset case-sensitive mode, put:
+To manually control case-sensitive mode, put:
 
-    case_sensitive_collation => 1
+    case_sensitive_collation => 1|0
 
 in your Loader options.
 
@@ -186,6 +186,7 @@ sub _columns_info_for {
     while (my ($col, $info) = each %$result) {
         my $dbh = $self->schema->storage->dbh;
 
+# find identities
         my $sth = $dbh->prepare(qq{
 SELECT column_name 
 FROM INFORMATION_SCHEMA.COLUMNS
@@ -198,6 +199,78 @@ AND lower(table_name) = @{[ $dbh->quote(lc $table) ]} AND lower(column_name) = @
             delete $info->{size};
         }
 
+# fix types
+        if ($info->{data_type} eq 'int') {
+            $info->{data_type} = 'integer';
+        }
+        elsif ($info->{data_type} eq 'timestamp') {
+            $info->{inflate_datetime} = 0;
+        }
+        elsif ($info->{data_type} =~ /^(?:numeric|decimal)\z/) {
+            if (ref($info->{size}) && $info->{size}[0] == 18 && $info->{size}[1] == 0) {
+                delete $info->{size};
+            }
+        }
+        elsif ($info->{data_type} eq 'real') {
+            $info->{data_type} = 'float';
+            $info->{size}      = 24;
+        }
+        elsif ($info->{data_type} eq 'float') {
+            $info->{data_type} = 'double precision';
+        }
+        elsif ($info->{data_type} =~ /^(?:small)?datetime\z/) {
+            # fixup for DBD::Sybase
+            if ($info->{default_value} && $info->{default_value} eq '3') {
+                delete $info->{default_value};
+            }
+        }
+        elsif ($info->{data_type} eq 'datetimeoffset') {
+            $info->{size} = {
+                26 => 0,
+                28 => 1,
+                29 => 2,
+                30 => 3,
+                31 => 4,
+                32 => 5,
+                33 => 6,
+                34 => 7,
+            }->{$info->{size}};
+
+            delete $info->{size} if $info->{size} == 7;
+        }
+        elsif ($info->{data_type} eq 'datetime2') {
+            $info->{size} = {
+                19 => 0,
+                21 => 1,
+                22 => 2,
+                23 => 3,
+                24 => 4,
+                25 => 5,
+                26 => 6,
+                27 => 7,
+            }->{$info->{size}};
+
+            delete $info->{size} if $info->{size} == 7;
+        }
+        elsif ($info->{data_type} eq 'time') {
+            $info->{size} = {
+                 8 => 0,
+                10 => 1,
+                11 => 2,
+                12 => 3,
+                13 => 4,
+                14 => 5,
+                15 => 6,
+                16 => 7,
+            }->{$info->{size}};
+
+            delete $info->{size} if $info->{size} == 7;
+        }
+
+        if ($info->{data_type} !~ /^(?:n?char|n?varchar|binary|varbinary|numeric|decimal|float|datetime(?:2|offset)|time)\z/) {
+            delete $info->{size};
+        }
+
 # get default
         $sth = $dbh->prepare(qq{
 SELECT column_default
index 22369a0..0791bb4 100644 (file)
@@ -38,7 +38,93 @@ my $tester = dbixcsl_common_tests->new(
         } : ()),
     ],
     data_types => {
-        'int identity' => { data_type => 'int', is_auto_increment => 1 },
+        # http://msdn.microsoft.com/en-us/library/ms187752.aspx
+
+        # numeric types
+        'int identity' => { data_type => 'integer', is_auto_increment => 1 },
+        bigint   => { data_type => 'bigint' },
+        int      => { data_type => 'integer' },
+        integer  => { data_type => 'integer' },
+        smallint => { data_type => 'smallint' },
+        tinyint  => { data_type => 'tinyint' },
+        money       => { data_type => 'money' },
+        smallmoney  => { data_type => 'smallmoney' },
+        bit         => { data_type => 'bit' },
+        real           => { data_type => 'float', size => 24 },
+        'float(14)'    => { data_type => 'float', size => 24 },
+        'float(24)'    => { data_type => 'float', size => 24 },
+        'float(25)'    => { data_type => 'double precision' },
+        'float(53)'    => { data_type => 'double precision' },
+        float          => { data_type => 'double precision' },
+        'double precision'
+                       => { data_type => 'double precision' },
+        'numeric(6,3)' => { data_type => 'numeric', size => [6,3] },
+        'decimal(6,3)' => { data_type => 'decimal', size => [6,3] },
+        'dec(6,3)'     => { data_type => 'decimal', size => [6,3] },
+        numeric        => { data_type => 'numeric' },
+        decimal        => { data_type => 'decimal' },
+        dec            => { data_type => 'decimal' },
+
+        # datetime types
+        date     => { data_type => 'date' },
+        datetime => { data_type => 'datetime' },
+        'datetime DEFAULT getdate()'
+                 => { data_type => 'datetime', default_value => \'getdate()' },
+        smalldatetime  => { data_type => 'smalldatetime' },
+        time     => { data_type => 'time' },
+        'time(0)'=> { data_type => 'time', size => 0 },
+        'time(1)'=> { data_type => 'time', size => 1 },
+        'time(2)'=> { data_type => 'time', size => 2 },
+        'time(3)'=> { data_type => 'time', size => 3 },
+        'time(4)'=> { data_type => 'time', size => 4 },
+        'time(5)'=> { data_type => 'time', size => 5 },
+        'time(6)'=> { data_type => 'time', size => 6 },
+        'time(7)'=> { data_type => 'time' },
+        datetimeoffset => { data_type => 'datetimeoffset' },
+        'datetimeoffset(0)' => { data_type => 'datetimeoffset', size => 0 },
+        'datetimeoffset(1)' => { data_type => 'datetimeoffset', size => 1 },
+        'datetimeoffset(2)' => { data_type => 'datetimeoffset', size => 2 },
+        'datetimeoffset(3)' => { data_type => 'datetimeoffset', size => 3 },
+        'datetimeoffset(4)' => { data_type => 'datetimeoffset', size => 4 },
+        'datetimeoffset(5)' => { data_type => 'datetimeoffset', size => 5 },
+        'datetimeoffset(6)' => { data_type => 'datetimeoffset', size => 6 },
+        'datetimeoffset(7)' => { data_type => 'datetimeoffset' },
+        datetime2      => { data_type => 'datetime2' },
+        'datetime2(0)' => { data_type => 'datetime2', size => 0 },
+        'datetime2(1)' => { data_type => 'datetime2', size => 1 },
+        'datetime2(2)' => { data_type => 'datetime2', size => 2 },
+        'datetime2(3)' => { data_type => 'datetime2', size => 3 },
+        'datetime2(4)' => { data_type => 'datetime2', size => 4 },
+        'datetime2(5)' => { data_type => 'datetime2', size => 5 },
+        'datetime2(6)' => { data_type => 'datetime2', size => 6 },
+        'datetime2(7)' => { data_type => 'datetime2' },
+
+        # string types
+        char           => { data_type => 'char', size => 1 },
+        'char(2)'      => { data_type => 'char', size => 2 },
+        'varchar(2)'   => { data_type => 'varchar', size => 2 },
+        nchar          => { data_type => 'nchar', size => 1 },
+        'nchar(2)'     => { data_type => 'nchar', size => 2 },
+        'nvarchar(2)'  => { data_type => 'nvarchar', size => 2 },
+
+        # binary types
+        'binary(2)'      => { data_type => 'binary', size => 2 },
+        'varbinary(2)'   => { data_type => 'varbinary', size => 2 },
+
+        # blob types
+        'varchar(max)'   => { data_type => 'text' },
+        text             => { data_type => 'text' },
+        'nvarchar(max)'  => { data_type => 'ntext' },
+        ntext            => { data_type => 'ntext' },
+        'varbinary(max)' => { data_type => 'image' },
+        image            => { data_type => 'image' },
+
+        # other types
+        timestamp        => { data_type => 'timestamp', inflate_datetime => 0 },
+        uniqueidentifier => { data_type => 'uniqueidentifier' },
+        hierarchyid      => { data_type => 'hierarchyid' },
+        sql_variant      => { data_type => 'sql_variant' },
+        xml              => { data_type => 'xml' },
     },
     extra => {
         create => [