Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Re^8: DBI placeholders for spatial data

by afoken (Chancellor)
on Jun 27, 2021 at 01:50 UTC ( [id://11134360]=note: print w/replies, xml ) Need Help??


in reply to Re^7: DBI placeholders for spatial data
in thread DBI placeholders for spatial data

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". ;-)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11134360]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (5)
As of 2024-03-28 21:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found