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
$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 {
}
}
+ # 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;
}
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 ) {