I just wanted to demonstrate that DBI can't connect with DBI->connect('DBD:MariaDB:...',...), but it can and does, if environment variables are set. I think that should not happen.
DBI's connect method is pure perl. It contains some legacy stuff, but I don't really want to analyse every single line of it. So I just cleared the environment and ran a test:
/tmp>env - perl -MDBI -e 'DBI->connect("DBD:MariaDB","","",{PrintError
+=>1})'
Can't connect to data source 'DBD:MariaDB' because I can't work out wh
+at driver to use (it doesn't seem to contain a 'dbi:driver:' prefix a
+nd the DBI_DRIVER env var is not set) at -e line 1.
There is a hint hiding in the error message. The relevant part of the connect() documentation is this, at the very end:
For compatibility with old DBI scripts, the driver can be specified by passing its name as the fourth argument to connect (instead of \%attr):
$dbh = DBI->connect($data_source, $user, $pass, $driver);
In this "old-style" form of connect, the $data_source should not start with "dbi:driver_name:". (If it does, the embedded driver_name will be ignored). Also note that in this older form of connect, the $dbh->{AutoCommit} attribute is undefined, the $dbh->{PrintError} attribute is off, and the old DBI_DBNAME environment variable is checked if DBI_DSN is not defined. Beware that this "old-style" connect will soon be withdrawn in a future version of DBI.
connect() assumes an old-style call, despite being called with an unblessed hash reference as fourth argument, not a string. The old-style call should have a driver name as fourth argument. This smells like a bug.
What happens if $ENV{'DBI_DRIVER'} is set?
/tmp>env - DBI_DRIVER=NON::SENSE perl -MDBI -e 'DBI->connect("DBD:Mari
+aDB","","",{PrintError=>1})'
install_driver(NON::SENSE) failed: Can't locate DBD/NON/SENSE.pm in @I
+NC (you may need to install the DBD::NON::SENSE module) (@INC contain
+s: /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/ven
+dor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/per
+l5 .) at (eval 5) line 3.
Perhaps a module that DBD::NON::SENSE requires hasn't been fully insta
+lled
at -e line 1.
Again, DBI->connect() treats a new-style call with \%attr, but an invalid $data_source, as an old-style call.
What happens to the attributes?
/tmp>env - perl -MDBI -e 'print DBI->connect("dbi:SQLite:foo","","",{P
+rintError=>1})->{PrintError}'
1
/tmp>env - DBI_DRIVER=SQLite perl -MDBI -e 'print DBI->connect("DBD:Ma
+riaDB:foo","","",{PrintError=>1})->{PrintError}'
1
/tmp>env - DBI_DRIVER=SQLite perl -MDBI -e 'print DBI->connect("DBD:Ma
+riaDB:foo","","",{})->{PrintError}'
1
PrintError is on, even by default. For "old-style" connects, it should be off. See the quoted documentation above.
What happens for a real old-style call?
/tmp>env - perl -MDBI -e 'print DBI->connect("DBD:MariaDB:foo","","","
+SQLite")->{PrintError}'
DBI->connect using 'old-style' syntax is deprecated and will be an err
+or in future versions at -e line 1.
/tmp>env - perl -MDBI -e 'print defined DBI->connect("DBD:MariaDB:foo"
+,"","","SQLite")->{PrintError}'
DBI->connect using 'old-style' syntax is deprecated and will be an err
+or in future versions at -e line 1.
1
/tmp>env - perl -MDBI -e 'print DBI->connect("DBD:MariaDB:foo","","","
+SQLite")->{PrintError}+0'
DBI->connect using 'old-style' syntax is deprecated and will be an err
+or in future versions at -e line 1.
0
We get the expected deprecation warning, and PrintError is off (defined and empty).
What happens without \%attr? This:
/tmp>env - perl -MDBI -e 'print DBI->connect("DBD:MariaDB:foo","","")'
Can't connect to data source 'DBD:MariaDB:foo' because I can't work ou
+t what driver to use (it doesn't seem to contain a 'dbi:driver:' pref
+ix and the DBI_DRIVER env var is not set) at -e line 1.
This is acceptable, as there is no fourth argument containing either a driver name or \%attr. So this could be an old-style call. The first argument lacks a "dbi:" prefix, so it must be an old-style call. (Or a confused coder.)
So, an invalid modern-style $data_source confuses connect() to use the fall-back to old-style driver name handling, but at the same time to respect the \%attr parameter and to omit the deprecation warning. I think this is a bug.
Bod's system obviously behaves the same, and someone must have set up DBI environment variables that hide the problem.
My DBI version:
/tmp>perl -MDBI -e 'print $DBI::VERSION'
1.636
I'm a little bit behind (CPAN currently has 1.643), but the relevant parts in DBI.pm are connect() and installl_driver(). The former has some changes related to the password, and keeps a copy of the original $data_source for an error message, but has no other changes. The latter is unchanged. So I think this bug still exists. Unfortunately, I don't have a spare system at hand to test the current version of DBI.
Alexander
--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
|