From: Rafael Kitover Date: Tue, 25 May 2010 20:00:17 +0000 (-0400) Subject: some work on Informix data_types, datetimes and intervals left to do X-Git-Tag: 0.07001~34 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=c7e6dc1fd51af6feea5b585a691a80f904fb4d11;p=dbsrgits%2FDBIx-Class-Schema-Loader.git some work on Informix data_types, datetimes and intervals left to do --- diff --git a/lib/DBIx/Class/Schema/Loader/DBI/Informix.pm b/lib/DBIx/Class/Schema/Loader/DBI/Informix.pm index e4f8f2e..b389917 100644 --- a/lib/DBIx/Class/Schema/Loader/DBI/Informix.pm +++ b/lib/DBIx/Class/Schema/Loader/DBI/Informix.pm @@ -164,7 +164,7 @@ sub _columns_info_for { local $dbh->{FetchHashKeyName} = 'NAME_lc'; my $sth = $dbh->prepare(<<'EOF'); -select c.colname, c.coltype, d.type deflt_type, d.default deflt +select c.colname, c.coltype, c.collength, c.colmin, d.type deflt_type, d.default deflt from syscolumns c join systables t on c.tabid = t.tabid left join sysdefaults d on t.tabid = d.tabid and c.colno = d.colno @@ -175,31 +175,78 @@ EOF $sth->finish; while (my ($col, $info) = each %$cols) { + $col = $self->_lc($col); + my $type = $info->{coltype} % 256; if ($type == 6) { # SERIAL $result->{$col}{is_auto_increment} = 1; } - if (looks_like_number $result->{$col}{data_type}) { + my $data_type = $result->{$col}{data_type}; + + if (looks_like_number $data_type) { if ($type == 7) { $result->{$col}{data_type} = 'date'; } elsif ($type == 10) { $result->{$col}{data_type} = 'datetime year to fraction(5)'; } + elsif ($type == 17 || $type == 52) { + $result->{$col}{data_type} = 'bigint'; + } + elsif ($type == 40) { + $result->{$col}{data_type} = 'lvarchar'; + $result->{$col}{size} = $info->{collength}; + } + elsif ($type == 12) { + $result->{$col}{data_type} = 'text'; + } + elsif ($type == 11) { + $result->{$col}{data_type} = 'bytea'; + $result->{$col}{original}{data_type} = 'byte'; + } + elsif ($type == 41) { + # XXX no way to distinguish opaque types boolean, blob and clob + $result->{$col}{data_type} = 'blob'; + } + elsif ($type == 21) { + $result->{$col}{data_type} = 'list'; + } + elsif ($type == 20) { + $result->{$col}{data_type} = 'multiset'; + } + elsif ($type == 19) { + $result->{$col}{data_type} = 'set'; + } + } + + if ($type == 15) { + $result->{$col}{data_type} = 'nchar'; + } + elsif ($type == 16) { + $result->{$col}{data_type} = 'nvarchar'; + } + # XXX untested! + elsif ($info->{coltype} == 2061) { + $result->{$col}{data_type} = 'idssecuritylabel'; } + # XXX colmin doesn't work for min size of varchar columns, it's NULL +# if (lc($data_type) eq 'varchar') { +# $result->{$col}{size}[1] = $info->{colmin}; +# } + my ($default_type, $default) = @{$info}{qw/deflt_type deflt/}; next unless $default_type; if ($default_type eq 'C') { - my $current = 'CURRENT YEAR TO FRACTION(5)'; + my $current = 'current year to fraction(5)'; $result->{$col}{default_value} = \$current; } elsif ($default_type eq 'T') { - my $today = 'TODAY'; + my $today = 'today'; $result->{$col}{default_value} = \$today; } else { @@ -215,6 +262,40 @@ EOF } } + # fix up data_types some more + while (my ($col, $info) = each %$result) { + my $data_type = $info->{data_type}; + + if ($data_type !~ /^(?:[nl]?(?:var)?char|decimal)\z/i) { + delete $info->{size}; + } + + if (lc($data_type) eq 'decimal') { + no warnings 'uninitialized'; + + $info->{data_type} = 'numeric'; + + my @size = @{ $info->{size} || [] }; + + if ($size[0] == 16 && $size[1] == -4) { + delete $info->{size}; + } + elsif ($size[0] == 16 && $size[1] == 2) { + $info->{data_type} = 'money'; + delete $info->{size}; + } + } + elsif (lc($data_type) eq 'smallfloat') { + $info->{data_type} = 'real'; + } + elsif (lc($data_type) eq 'float') { + $info->{data_type} = 'double precision'; + } + elsif ($data_type =~ /^n?(?:var)?char\z/i) { + $info->{size} = $info->{size}[0]; + } + } + return $result; } diff --git a/t/16mssql_common.t b/t/16mssql_common.t index 7737441..3a8f35d 100644 --- a/t/16mssql_common.t +++ b/t/16mssql_common.t @@ -105,6 +105,8 @@ my $tester = dbixcsl_common_tests->new( # string types char => { data_type => 'char', size => 1 }, 'char(2)' => { data_type => 'char', size => 2 }, + character => { data_type => 'char', size => 1 }, + 'character(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 }, diff --git a/t/19informix_common.t b/t/19informix_common.t index f3deeed..07b0523 100644 --- a/t/19informix_common.t +++ b/t/19informix_common.t @@ -13,15 +13,106 @@ my $password = $ENV{DBICTEST_INFORMIX_PASS} || ''; my $tester = dbixcsl_common_tests->new( vendor => 'Informix', - auto_inc_pk => 'SERIAL PRIMARY KEY', + auto_inc_pk => 'serial primary key', null => '', - default_function => 'CURRENT YEAR TO FRACTION(5)', - default_function_def => 'DATETIME YEAR TO FRACTION(5) DEFAULT CURRENT YEAR TO FRACTION(5)', + default_function => 'current year to fraction(5)', + default_function_def => 'datetime year to fraction(5) default current year to fraction(5)', dsn => $dsn, user => $user, password => $password, loader_options => { preserve_case => 1 }, quote_char => '"', + data_types => { + # http://publib.boulder.ibm.com/infocenter/idshelp/v115/index.jsp?topic=/com.ibm.sqlr.doc/ids_sqr_094.htm + + # Numeric Types + 'int' => { data_type => 'integer' }, + integer => { data_type => 'integer' }, + int8 => { data_type => 'bigint' }, + bigint => { data_type => 'bigint' }, + serial => { data_type => 'integer', is_auto_increment => 1 }, + bigserial => { data_type => 'bigint', is_auto_increment => 1 }, + serial8 => { data_type => 'bigint', is_auto_increment => 1 }, + smallint => { data_type => 'smallint' }, + real => { data_type => 'real' }, + smallfloat => { data_type => 'real' }, + # just 'double' is a syntax error + 'double precision' => { data_type => 'double precision' }, + float => { data_type => 'double precision' }, + 'float(1)' => { data_type => 'double precision' }, + 'float(5)' => { data_type => 'double precision' }, + 'float(10)' => { data_type => 'double precision' }, + 'float(15)' => { data_type => 'double precision' }, + 'float(16)' => { data_type => 'double precision' }, + numeric => { data_type => 'numeric' }, + decimal => { data_type => 'numeric' }, + dec => { data_type => 'numeric' }, + 'numeric(6,3)' => { data_type => 'numeric', size => [6,3] }, + 'decimal(6,3)' => { data_type => 'numeric', size => [6,3] }, + 'dec(6,3)' => { data_type => 'numeric', size => [6,3] }, + + # Boolean Type + # XXX this should map to 'boolean' + boolean => { data_type => 'smallint' }, + + # Money Type + money => { data_type => 'money' }, + 'money(3,3)' => { data_type => 'numeric', size => [3,3] }, + + # Byte Type + byte => { data_type => 'bytea', original => { data_type => 'byte' } }, + + # Character String Types + char => { data_type => 'char', size => 1 }, + 'char(3)' => { data_type => 'char', size => 3 }, + character => { data_type => 'char', size => 1 }, + 'character(3)' => { data_type => 'char', size => 3 }, + 'varchar(3)' => { data_type => 'varchar', size => 3 }, + 'character varying(3)' + => { data_type => 'varchar', size => 3 }, + # XXX min size not supported, colmin from syscolumns is NULL + 'varchar(3,2)' => { data_type => 'varchar', size => 3 }, + 'character varying(3,2)' + => { data_type => 'varchar', size => 3 }, + nchar => { data_type => 'nchar', size => 1 }, + 'nchar(3)' => { data_type => 'nchar', size => 3 }, + 'nvarchar(3)' => { data_type => 'nvarchar', size => 3 }, + 'nvarchar(3,2)' => { data_type => 'nvarchar', size => 3 }, + 'lvarchar(3)' => { data_type => 'lvarchar', size => 3 }, + 'lvarchar(33)' => { data_type => 'lvarchar', size => 33 }, + text => { data_type => 'text' }, + + # DateTime Types + date => { data_type => 'date' }, + 'date default today' + => { data_type => 'date', default_value => \'today' }, + # XXX support all precisions + 'datetime year to fraction(5)', + => { data_type => 'datetime year to fraction(5)' }, + 'datetime year to fraction(5) default current year to fraction(5)', + => { data_type => 'datetime year to fraction(5)', default_value => \'current year to fraction(5)' }, + # XXX do interval + + # Blob Types + # XXX no way to distinguish opaque types boolean, blob and clob + blob => { data_type => 'blob' }, + clob => { data_type => 'blob' }, + + # IDSSECURITYLABEL Type + # + # This requires the DBSECADM privilege and a security policy on the + # table, things I know nothing about. +# idssecuritylabel => { data_type => 'idssecuritylabel' }, + + # List Types + # XXX need to introspect element type too + 'list(varchar(20) not null)' + => { data_type => 'list' }, + 'multiset(varchar(20) not null)' + => { data_type => 'multiset' }, + 'set(varchar(20) not null)' + => { data_type => 'set' }, + }, ); if( !$dsn ) { diff --git a/t/lib/dbixcsl_common_tests.pm b/t/lib/dbixcsl_common_tests.pm index 2d76ee0..ae299b9 100644 --- a/t/lib/dbixcsl_common_tests.pm +++ b/t/lib/dbixcsl_common_tests.pm @@ -1772,6 +1772,7 @@ sub _custom_column_info { my %DATA_TYPE_MULTI_TABLE_OVERRIDES = ( oracle => qr/\blong\b/i, mssql => qr/\b(?:timestamp|rowversion)\b/i, + informix => qr/\b(?:bigserial|serial8)\b/i, ); sub setup_data_type_tests {