Re: table_info('','','','%') cannot return any types
"Martin J. Evans" <[email protected]>
| Newsgroups | gmane.comp.lang.perl.modules.dbi.sybase.devel |
|---|---|
| Message-ID | <[email protected]> |
On 24/06/15 13:24, Tim Bunce wrote:
> On Tue, Jun 23, 2015 at 09:12:16AM +0100, Martin J. Evans wrote:
>> I was recently confirming table_info special cases and discovered the case for getting table_types cannot work.
>>
>> table_info('','','','%')
>>
>> should return a list of table types but it returns a list of empty strings instead:
>>
>> my @types = $h->tables('', '', '', '%');
>> print "all types:\n", join("xxx\n", @types), "\n";
>> # should output something like:
>> # "dbo"
>> # "INFORMATION_SCHEMA"
>> # "sys"
>> # and actually outputs:
>> xxx
>> xxx
>>
>> It seems to be down to the following in DBI.pm:
>>
>> sub tables {
>> my ($dbh, @args) = @_;
>> my $sth = $dbh->table_info(@args[0,1,2,3,4]) or return;
>> my $tables = $sth->fetchall_arrayref or return;
>> my @tables;
>> if ($dbh->get_info(29)) { # SQL_IDENTIFIER_QUOTE_CHAR
>> # problem is missing 3 in the slice below
>> @tables = map { $dbh->quote_identifier( @{$_}[0,1,2] ) } @$tables;
>> }
>>
>> My test case missed this because currently it is returning 3 values but they are all ''.
>>
>> Adding 3 to the slice fixes the issue but unfortunately changes the data returned from the deprecated tables method which now returns values like this:
>>
>> "master"."dbo"."DBD_ODBC_LOB_TEST"."TABLE"
>>
>> instead of (before)
>>
>> "master"."dbo"."DBD_ODBC_LOB_TEST"
>>
>> table_info is ok because it returns a result set and not a set of values pushed through quote_identifier.
>
> Thanks for the great analysis Martin.
>
>> Any comments?
>
> The tables('', '', '', '%') call is a special case so it seems
> reasonable to handle it as a special case in the code.
>
> Tim.
>
diff --git a/DBI.pm b/DBI.pm
index a23bed8..6e0e592 100644
--- a/DBI.pm
+++ b/DBI.pm
@@ -1761,7 +1761,10 @@ sub _new_sth { # called by DBD::<drivername>::db::prepare)
my $sth = $dbh->table_info(@args[0,1,2,3,4]) or return;
my $tables = $sth->fetchall_arrayref or return;
my @tables;
- if ($dbh->get_info(29)) { # SQL_IDENTIFIER_QUOTE_CHAR
+ if (defined($args[3]) && $args[3] eq '%' && # special case for tables('','','','%')
+ grep {defined($_) && $_ eq ''} @args[0,1,2]) {
+ @tables = map {$_->[3]} @$tables;
+ } elsif ($dbh->get_info(29)) { # SQL_IDENTIFIER_QUOTE_CHAR
@tables = map { $dbh->quote_identifier( @{$_}[0,1,2] ) } @$tables;
}
else { # temporary old style hack (yeach)
adds a special case, passes DBI tests for me and passes my testing. There is no need to quote the type as the DB should accept what it passed out.
tables('','','','%') now returns (for my ODBC DB):
SYSTEM TABLE
TABLE
VIEW
and no other calls to tables should be affected.
Martin