http://qs1969.pair.com?node_id=11134357


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

But... did you notice that your original dsn example had:

DBD:MariaDB:

instead of

dbi:MariaDB:

?

Replies are listed 'Best First'.
Re^8: DBI placeholders for spatial data
by afoken (Chancellor) on Jun 27, 2021 at 01:50 UTC

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