https://rt.cpan.org/Ticket/Display.html?id=100188
DBD::File has an issue that might cause backward compat:
sub FETCH
{
:
$attr eq "TYPE" and
return [ map { $sth->{f_overall_defs}{$_}{data_type} || "CHAR" }
@colnames ];
at which point, f_overall_defs is something like
{ c_test => {
data_length => undef,
data_type => 'INTEGER'
},
test => {
data_length => 10,
data_type => 'CHAR'
}
}
so $sth->{TYPE}[0] will return "INTEGER" instead of 4
TYPE is defined in DBI:
--8<---
"TYPE"
Type: array-ref, read-only
Returns a reference to an array of integer values for each column. The
^^^^^^^^^^^^^^
value indicates the data type of the corresponding column.
The values correspond to the international standards (ANSI X3.135 and
ISO/IEC 9075) which, in general terms, means ODBC. Driver-specific
types that don't exactly match standard types should generally return
the same values as an ODBC driver supplied by the makers of the
database. That might include private type numbers in ranges the vendor
has officially registered with the ISO working group:
ftp://sqlstandards.org/SC32/SQL_Registry/
Where there's no vendor-supplied ODBC driver to be compatible with, the
DBI driver can use type numbers in the range that is now officially
reserved for use by the DBI: -9999 to -9000.
All possible values for "TYPE" should have at least one entry in the
output of the "type_info_all" method (see "type_info_all").
-->8---
The solution would be a code change to this:
--8<---
# fill overall_defs unless we know
unless (exists $sth->{f_overall_defs} && ref
$sth->{f_overall_defs}) {
my $types = $sth->{Database}{Types};
unless ($types) { # Feth types only once per database
if (my $t = $sth->{Database}->type_info_all ()) {
foreach my $i (1 .. $#$t) {
$types->{uc $t->[$i][0]} = $t->[$i][1];
$types->{$t->[$i][1]} ||= uc $t->[$i][0];
}
}
$types->{""} = 0;
$types->{0} = "";
$sth->{Database}{Types} = $types;
}
my $all_meta =
$sth->{Database}->func ("*", "table_defs",
"get_sql_engine_meta");
while (my ($tbl, $meta) = each %$all_meta) {
exists $meta->{table_defs} && ref $meta->{table_defs} or
next;
foreach (keys %{$meta->{table_defs}{columns}}) {
my $field_info = $meta->{table_defs}{columns}{$_};
if (defined $field_info->{data_type} &&
$field_info->{data_type} !~ m/^[0-9]+$/) {
$field_info->{type_name} = uc
$field_info->{data_type};
$field_info->{data_type} =
$types->{$field_info->{type_name}} || 0;
}
$field_info->{type_name} ||=
$types->{$field_info->{data_type}} || "CHAR";
$sth->{f_overall_defs}{$_} = $field_info;
}
}
}
my @colnames = $sth->sql_get_colnames ();
$attr eq "TYPE" and
return [ map { $sth->{f_overall_defs}{$_}{data_type} || 12 }
@colnames ];
$attr eq "TYPE_NAME" and
return [ map { $sth->{f_overall_defs}{$_}{type_name} ||
"CHAR" }
@colnames ];
-->8---
Now we have both a numeric TYPE attribute and a matching TYPE_NAME
attribute, but how much DBD::File uses might this break?
MY opinion is that we should meet the DBI docs: return NUMERIC for the
TYPE attribute. All DBD::File consumers that ever depended on STRING
behavior depended on implementation (error) instead of docs
--
H.Merijn Brand http://tux.nl Perl Monger http://amsterdam.pm.org/
using perl5.00307 .. 5.21 porting perl5 on HP-UX, AIX, and openSUSE
http://mirrors.develooper.com/hpux/ http://www.test-smoke.org/
http://qa.perl.org http://www.goldmark.org/jeff/stupid-disclaimers/
pgp7kUh3jR5Ij.pgp
Description: OpenPGP digital signature
