From: Rafael Kitover Date: Mon, 24 May 2010 11:17:25 +0000 (-0400) Subject: better type info for DB2 X-Git-Tag: 0.07001~36 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=7640ef4b86af6164f7883bc71cffa9c0e26e69af;p=dbsrgits%2FDBIx-Class-Schema-Loader.git better type info for DB2 --- diff --git a/Changes b/Changes index 6c286b3..2cd8ff4 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,7 @@ Revision history for Perl extension DBIx::Class::Schema::Loader + - better type info for DB2 + 0.07000 2010-05-22 23:40:15 - added qualify_objects option to prepend db_schema to table names - fix for negative numeric default values diff --git a/TODO b/TODO index bd120ef..ff70b87 100644 --- a/TODO +++ b/TODO @@ -33,7 +33,7 @@ - add an option to add extra code to Result classes (maybe...) - redo in-memory schema as an @INC coderef rather than temp files - add option to filter out views - - support columns with names like "ro'd p/n" + - support columns with names like "ro'd p/n" in MSSQL - Relationships - Re-scan relations/tables after initial relation setup to find diff --git a/lib/DBIx/Class/Schema/Loader/DBI/DB2.pm b/lib/DBIx/Class/Schema/Loader/DBI/DB2.pm index b996dab..3c4afb2 100644 --- a/lib/DBIx/Class/Schema/Loader/DBI/DB2.pm +++ b/lib/DBIx/Class/Schema/Loader/DBI/DB2.pm @@ -134,11 +134,60 @@ sub _columns_info_for { $info->{is_auto_increment} = 1; } - if ((eval { lc ${ $info->{default_value} } }||'') eq 'current timestamp') { - ${ $info->{default_value} } = 'current_timestamp'; + my $data_type = $info->{data_type}; + + if ($data_type !~ /^(?:(?:var)?(?:char|graphic)|decimal)\z/i) { delete $info->{size}; + } + + if ($data_type eq 'double') { + $info->{data_type} = 'double precision'; + } + elsif ($data_type eq 'decimal') { + no warnings 'uninitialized'; + + $info->{data_type} = 'numeric'; + + my @size = @{ $info->{size} || [] }; + + if ($size[0] == 5 && $size[1] == 0) { + delete $info->{size}; + } + } + elsif ($data_type =~ /^(?:((?:var)?char) \(\) for bit data|(long varchar) for bit data)\z/i) { + my $base_type = lc($1 || $2); + + (my $original_type = $data_type) =~ s/[()]+ //; + + $info->{original}{data_type} = $original_type; + + if ($base_type eq 'long varchar') { + $info->{data_type} = 'blob'; + } + else { + if ($base_type eq 'char') { + $info->{data_type} = 'binary'; + } + elsif ($base_type eq 'varchar') { + $info->{data_type} = 'varbinary'; + } + + my ($size) = $dbh->selectrow_array(<<'EOF', {}, $self->db_schema, $self->_uc($table), $self->_uc($col)); +SELECT length +FROM syscat.columns +WHERE tabschema = ? AND tabname = ? AND colname = ? +EOF + + $info->{size} = $size if $size; + } + } + + if ((eval { lc ${ $info->{default_value} } }||'') =~ /^current (date|time(?:stamp)?)\z/i) { + my $type = lc($1); + + ${ $info->{default_value} } = 'current_timestamp'; - my $orig_deflt = 'current timestamp'; + my $orig_deflt = "current $type"; $info->{original}{default_value} = \$orig_deflt; } } diff --git a/lib/DBIx/Class/Schema/Loader/DBI/Pg.pm b/lib/DBIx/Class/Schema/Loader/DBI/Pg.pm index ccf6690..9ec8dee 100644 --- a/lib/DBIx/Class/Schema/Loader/DBI/Pg.pm +++ b/lib/DBIx/Class/Schema/Loader/DBI/Pg.pm @@ -145,6 +145,7 @@ sub _columns_info_for { my $data_type = $info->{data_type}; # these types are fixed size + # XXX should this be a negative match? if ($data_type =~ /^(?:bigint|int8|bigserial|serial8|boolean|bool|box|bytea|cidr|circle|date|double precision|float8|inet|integer|int|int4|line|lseg|macaddr|money|path|point|polygon|real|float4|smallint|int2|serial|serial4|text)\z/i) { delete $info->{size}; diff --git a/t/13db2_common.t b/t/13db2_common.t index f5f1475..4823d7e 100644 --- a/t/13db2_common.t +++ b/t/13db2_common.t @@ -16,8 +16,65 @@ my $tester = dbixcsl_common_tests->new( preserve_case_mode_is_exclusive => 1, quote_char => '"', data_types => { - 'timestamp DEFAULT CURRENT TIMESTAMP' => { data_type => 'timestamp', default_value => \'current_timestamp', - original => { default_value => \'current timestamp' } }, + # http://publib.boulder.ibm.com/infocenter/db2luw/v8/index.jsp?topic=/com.ibm.db2.udb.doc/admin/r0008483.htm + # + # Numeric Types + smallint => { data_type => 'smallint' }, + integer => { data_type => 'integer' }, + 'int' => { data_type => 'integer' }, + real => { data_type => 'real' }, + 'double precision' => { data_type => 'double precision' }, + double => { data_type => 'double precision' }, + float => { data_type => 'double precision' }, + 'float(24)' => { data_type => 'real' }, + 'float(25)' => { data_type => 'double precision' }, + 'float(53)' => { data_type => 'double precision' }, + numeric => { data_type => 'numeric' }, + decimal => { data_type => 'numeric' }, + 'numeric(6,3)' => { data_type => 'numeric', size => [6,3] }, + 'decimal(6,3)' => { data_type => 'numeric', size => [6,3] }, + + # Character String Types + char => { data_type => 'char', size => 1 }, + 'char(3)' => { data_type => 'char', size => 3 }, + 'varchar(3)' => { data_type => 'varchar', size => 3 }, + 'long varchar' => { data_type => 'long varchar' }, + 'clob' => { data_type => 'clob' }, + + # Graphic String Types (double-byte strings) + graphic => { data_type => 'graphic', size => 1 }, + 'graphic(3)' => { data_type => 'graphic', size => 3 }, + 'vargraphic(3)' => { data_type => 'vargraphic', size => 3 }, + 'long vargraphic' => { data_type => 'long vargraphic' }, + 'dbclob' => { data_type => 'dbclob' }, + + # Binary String Types + 'char for bit data'=> { data_type => 'binary', size => 1, original => { data_type => 'char for bit data' } }, + 'char(3) for bit data' + => { data_type => 'binary', size => 3, original => { data_type => 'char for bit data' } }, + 'varchar(3) for bit data' + => { data_type => 'varbinary', size => 3, original => { data_type => 'varchar for bit data' } }, + 'long varchar for bit data' + => { data_type => 'blob', original => { data_type => 'long varchar for bit data' } }, + blob => { data_type => 'blob' }, + + # DateTime Types + 'date' => { data_type => 'date' }, + 'date default current date' + => { data_type => 'date', default_value => \'current_timestamp', + original => { default_value => \'current date' } }, + 'time' => { data_type => 'time' }, + 'time default current time' + => { data_type => 'time', default_value => \'current_timestamp', + original => { default_value => \'current time' } }, + timestamp => { data_type => 'timestamp' }, + 'timestamp default current timestamp' + => { data_type => 'timestamp', default_value => \'current_timestamp', + original => { default_value => \'current timestamp' } }, + + # DATALINK Type + # XXX I don't know how to make these +# datalink => { data_type => 'datalink' }, }, ); diff --git a/t/14ora_common.t b/t/14ora_common.t index 1232939..294b1e5 100644 --- a/t/14ora_common.t +++ b/t/14ora_common.t @@ -136,7 +136,7 @@ my $tester = dbixcsl_common_tests->new( 'Oracle sequence detection'; } else { - skip 1, 'not running common tests'; + skip 'not running common tests', 1; } } }, diff --git a/t/lib/dbixcsl_common_tests.pm b/t/lib/dbixcsl_common_tests.pm index af46977..2d76ee0 100644 --- a/t/lib/dbixcsl_common_tests.pm +++ b/t/lib/dbixcsl_common_tests.pm @@ -1770,8 +1770,8 @@ sub _custom_column_info { } my %DATA_TYPE_MULTI_TABLE_OVERRIDES = ( - oracle => qr/\blong\b/, - mssql => qr/\b(?:timestamp|rowversion)\b/, + oracle => qr/\blong\b/i, + mssql => qr/\b(?:timestamp|rowversion)\b/i, ); sub setup_data_type_tests { @@ -1784,11 +1784,11 @@ sub setup_data_type_tests { # split types into tables based on overrides my (@types, @split_off_types, @first_table_types); { - no warnings 'uninitialized'; + my $split_off_re = $DATA_TYPE_MULTI_TABLE_OVERRIDES{lc($self->{vendor})} || qr/(?!)/; @types = keys %$types; - @split_off_types = grep /$DATA_TYPE_MULTI_TABLE_OVERRIDES{lc($self->{vendor})}/i, @types; - @first_table_types = grep !/$DATA_TYPE_MULTI_TABLE_OVERRIDES{lc($self->{vendor})}/i, @types; + @split_off_types = grep /$split_off_re/, @types; + @first_table_types = grep !/$split_off_re/, @types; } @types = +{ map +($_, $types->{$_}), @first_table_types },