Subject: | Parser::DBI fails to load appropriate driver |
Date: | Fri, 3 Oct 2008 18:00:09 +0200 |
To: | bug-SQL-Translator [...] rt.cpan.org |
From: | Jean-Baptiste Mazon <jmazon [...] amadeus.com> |
SQL::Translator v0.09001
This is perl, v5.10.0 built for x86_64-linux-thread-multi
Symptoms
========
$ sqlt -f DBI --dsn dbi:Oracle:db --db-user scott --db-password tiger -t
Oracle -d --trace --show-warnings
[SQL::Translator] Got parser: code ref
[SQL::Translator] Got producer: code ref
[SQL::Translator] Got parser: SQL::Translator::Parser::DBI::parse
[SQL::Translator] Got producer: SQL::Translator::Producer::Oracle::produce
Error: translate: Error with parser 'SQL::Translator::Parser::DBI':
Undefined subroutine &SQL::Translator::Parser::DBI::Oracle::parse called
at /home/jmazon/lib/perl5/site_perl/5.10.0/SQL/Translator/Parser/DBI.pm
line 180.
Problem 1
=========
It looks as though &SQL::Translator::Parser::DBI::parse attempts to load
the driver by invoking &SQL::Translator::load as if it were a method:
sub parse {
my ( $tr, $data ) = @_;
# (...) (convert parameters to $pkg =
'SQL::Translator::Parser::DBI::Oracle')
$tr->load( $pkg );
# (...)
}
Well, it's not. The other place it's invoked uses it as a plain old sub:
Translator.pm:697: load("SQL::Translator::$uctype") or return ();
I got around it using can, because I'm not sure whether it's intended to
be subclassed or something. Maybe a direct call could be enough.
Problem 2
=========
&SQL::Translator::load doesn't even report it failed to load its argument.
It fails to detect the problem because it checks for errors with the
following regex: /Can't locate $file in \@INC/. Unfortunately, with the
wrong calling convention, $file gets assigned a stringified object ref,
'SQL/Translator=HASH(0x14f5680).pm', which contains regex metacharacters.
DB<52> x $@ =~ /Can't locate $file in \@INC/
empty array
DB<53> x $@ =~ /Can't locate \Q$file\E in \@INC/
0 1
Admittedly, it's not really supposed to happen. Not sure what a robust
require fail detection scheme would look like, anyway.
Problem 3
=========
&SQL::Translator::Parser::DBI::parse doesn't check load's return value. I
appended an "or die $tr->error"
Patch
=====
(it doesn't buy me a successful translation yet, but it pushes the error
out of the init phase for me, so I figure it could be of use)
--- SQL/Translator/Parser/DBI.pm.orig 2008-10-03 17:48:59.001451000
+0200
+++ SQL/Translator/Parser/DBI.pm 2008-10-03 17:48:25.000190000 +0200
@@ -172,7 +172,7 @@
my $pkg = "SQL::Translator::Parser::DBI::$driver";
my $sub = $pkg.'::parse';
- $tr->load( $pkg );
+ $tr->can('load')->( $pkg ) or die $tr->error;
eval {
no strict 'refs';