I am trying to sort our old code that serves two purposes. It uses DBI to create the database, and then uses DBI to connect to this database. Unfortunately, he used the same code for each. This means that if you create a sales
database, and then when you reconnect, you must explicitly call $dbh->do('use sales')
. This leads to various problems, such as developers forgetting to do this, or the database descriptor reconnects and forgets which database it was in.
What we're trying to do as a first-pass fix is ββfor the DBI::connect()
HandleError
to use HandleError
to reconnect to MySQL if the database does not exist, which allows us to create the database. For various inherited reasons (yes, we were all there) it is much harder to try to catch the "Unknown database" error outside of the connect()
method.
So my first pass when solving this is as follows:
use strict; use warnings; use DBI; use PadWalker 'peek_my'; my $dbh = DBI->connect( $dsn, $user, $pass, { RaiseError => 1, PrintError => 0, HandleError => \&reconnect_if_unknown_database, }, ); sub reconnect_if_unknown_database { my ($msg, $drh, $dbh) = @_; return unless $msg =~ /Unknown database/; my ($dsn, $user, $pass, $attr) = @{peek_my(1)}{qw/$dsn $user $pass $attr/}; unless ($dsn && $user && $pass && $attr) { return;
This works, and it is currently transparent to the end user, but it also feels like a steaming bunch of ones and zeros. Is there a better way to reconnect to another database if the connection fails?
source share