Skip to content

Loading…

Supporting Migration from old-school DBI #27

Open
bluefeet opened this Issue · 2 comments

2 participants

@bluefeet

I tend to work in environments with a large legacy code base. These environments tend to have funky setups for their DBI connections such as AutoCommit=>0 and RaiseError=>0 (and a lot worse such as custom timeout handling with alarm() and such...). I'd like to use DBIx::Connector in these environments and incrementally port the code to use it.

But, the problem with that is DBIx::Connector is pretty heavy handed. In particular what is causing me issues right now is:

  • txn() and svp() do not work if AutoCommit is off.
  • fixup doesn't work if RaiseError is off.

So, the following DBI attributes just won't work with DBIx::Connector even tho my legacy code depends on it:

my $connector = Foo->new( $dsn, $user, $pass, { RaiseError=>0, AutoCommit=>0 });

I tried coming up with a solution that uses local() to encapsulate the setting of RaiseError and AutoCommit so that they are set what DBIx::Connector wants when it needs them that way but reverts to their original value when the DBI handle is being used directly:

package Foo;

use base 'DBIx::Connector';

sub _exec {
    my $self = shift;
    my $dbh = shift;

    local $dbh->{RaiseError} = 1;

    return $self->SUPER::_exec( $dbh, @_ );
}

sub in_txn {
    my $self = shift;
    return $self->{_in_txn} ? 1 : 0;
}

sub txn {
    my $self = shift;
    local $self->{_in_txn} = 1;
    return $self->SUPER::txn( @_ );
}

sub svp {
    my $self = shift;
    local $self->{_in_txn} = 1;
    return $self->SUPER::svp( @_ );
}

1;

And got pretty much stuck at that point as I couldn't figure out a good way to inject AutoCommit=>1 at the points it needs it like I am able to to with RaiseError=>1. And, I'm aware that RaiseError=>1 needs to be set in more places than for _exec(), such as when $driver->ping() is being called.

Now, I could just copy and paste the functions (_txn_run, _txn_fixup_run, etc) where I need to local()ize these attributes but then my code is going to break when DBIx::Connector changes something internal. Bad.

I see two valid solutions:

  • Abstract out various bits of the logic in DBIx::Connector so that a subclass can wrap around more fine-grained parts and.
  • Change DBIx::Connector to not be so heavy handed and just build-in the local()ization of RaiseError and AutoCommit.

Thoughts? Thanks! :)

@bluefeet

Oh, and this is in a web environment so I can't just use DBIx::Connector for new code and DBI for old code - that would cause double-DBI connections which would make the DBAs oh-so-not-happy.

@theory
Owner
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.