DBIx-Abstract

 view release on metacpan or  search on metacpan

lib/DBIx/Abstract.pm  view on Meta::CPAN

# ABSTRACT: DBI SQL abstraction
package DBIx::Abstract;
$DBIx::Abstract::VERSION = '1.04';
use DBI;
use Scalar::Util 'weaken';
use Check::ISA qw( obj_does );
use strict;
use warnings;

our $AUTOLOAD;

sub ___drivers {
    my ( $driver, $config ) = @_;
    my %drivers = (

        # Feel free to add new drivers... note that some DBD data_sources
        # do not translate well (eg Oracle).
        mysql => "dbi:mysql:$config->{dbname}:$config->{host}:$config->{port}",
        msql  => "dbi:msql:$config->{dbname}:$config->{host}:$config->{port}",

        # According to DBI, drivers should use the below if they have no
        # other preference.  It is ODBC style.
        DEFAULT => "dbi:$driver:"
    );

    # Make Oracle look a little bit like other DBs.
    # Right now we only have one hack, but I can imagine there being
    # more...
    if ( $driver eq 'Oracle' ) {
        $config->{'sid'} ||= delete( $config->{'dbname'} );
    }

    my @keys;
    foreach ( sort keys %$config ) {
        next if /^user$/;
        next if /^password$/;
        next if /^driver$/;
        push( @keys, "$_=$config->{$_}" );
    }
    $drivers{'DEFAULT'} .= join( ';', @keys );
    if ( $drivers{$driver} ) {
        return $drivers{$driver};
    }
    else {
        return $drivers{'DEFAULT'};
    }
}

sub connect {
    my $class = shift;
    my ( $config, $options ) = @_;
    my ( $dbh, $data_source, $user, $pass, $driver, $dbname, $host, $port );
    my $self = {};

    if ( !defined($config) ) {
        require Carp;
        Carp::croak( "DBIx::Abstract->connect A connection configuration must be provided." );
    }
    elsif ( ref($config) eq 'HASH' ) {
        if ( $config->{'dbh'} ) {
            $dbh = $config->{'dbh'};
        }
        else {
            $user = $config->{'user'}     || $config->{'username'};
            $pass = $config->{'password'} || $config->{'pass'};

lib/DBIx/Abstract.pm  view on Meta::CPAN

            foreach ( @{ $self->{'CLONES'} } ) {
                if ( ref($_) ) {
                    if ( $_->DESTROY == -1 ) {
                        warn
"Error: DBIx::Abstract tried to recurse into $_ from $self during DESTROY \n";
                    }
                }
                else {

                # Shouldn't be possible to get here... but Perl's destruction is
                # a bit weird.  I guess I wouldn't expect less from the
                # apocalypse.
                #          warn "Error: DBIx::Abstract clone not object\n";
                }
                $_ = undef;
            }
        }
        $self->{'sth'}->finish if ref( $self->{'sth'} );

        # Close our handle if we opened it and its still around
        if ( !$self->{'connect'}{'dbh'} and defined( $self->{'dbh'} ) ) {
            $self->{'dbh'}->disconnect;
        }
    }
    else {
        my $new = [];
        foreach ( @{ $self->{'ORIG'}->{'CLONES'} } ) {
            if ( defined($_) and ref($_) and $self ne $_ ) {
                push( @$new, $_ );
            }
        }
        $self->{'ORIG'}->{'CLONES'} = $new;
    }
    $self->{'sth'}->finish if ref( $self->{'sth'} );
## Apparently this can cause $self->{'dbh'} to be deleted prior to
## disconnect being called.  Bleah.
    #  delete($self->{'dbh'});
    delete( $self->{'sth'} );

    #  delete($self->{'connect'});
    delete( $self->{'options'} );
    delete( $self->{'MODQUERY'} );
    delete( $self->{'ORIG'} );
    delete( $self->{'CLONES'} );
    return 0;
}

sub clone {
    my $self    = shift;
    my $class   = ref($self);
    my $newself = {%$self};
    delete( $newself->{'CLONES'} );
    delete( $newself->{'ORIG'} );
    bless $newself, $class;
    if ( !$self->{'ORIG'} ) {
        $newself->{'ORIG'} = $self;
    }
    else {
        $newself->{'ORIG'} = $self->{'ORIG'};
    }
    weaken( $newself->{'ORIG'} );

    push( @{ $newself->{'ORIG'}->{'CLONES'} }, $newself );
    weaken(
        $newself->{'ORIG'}->{'CLONES'}[ $#{ $newself->{'ORIG'}->{'CLONES'} } ]
    );

    $self->__logwrite( 5, 'Cloned' );
    return $newself;
}

my %valid_opts = map( { $_ => 1 } qw(
      loglevel logfile saveSQL useCached delaymods
      ) );

sub opt {
    my $self = shift;
    my ( $key, $value ) = @_;
    if ( ref($key) ) {
        $value = $key->{'value'};
        $key   = $key->{'key'};
    }
    my $ret;
    if ( $valid_opts{$key} ) {
        $ret = $self->{'options'}{$key};
    }
    elsif ( exists( $self->{'dbh'}{$key} ) ) {
        $ret = $self->{'dbh'}{$key};
    }
    else {
        die "DBIx::Abstract->opt Unknown option $key\n";
    }
    if ( defined($value) ) {
        if ( $valid_opts{$key} ) {
            $self->{'options'}{$key} = $value;
        }
        else {
            eval { $self->{'dbh'}->{$key} = $value };
            if ($@) {
                warn $@;
                return $ret;
            }
        }
        $self->__logwrite(
            5,
            'Option change',
            $key   ? $key   : '',
            $ret   ? $ret   : '',
            $value ? $value : ''
        );
    }
    return $ret;
}

sub __literal_query {
    my $self = shift;
    # This actually makes a query
    # All of the other related query functions (eventually) call this
    my ( $sql, @bind_values ) = @_;
    my $sth;
    if ( $self->opt('saveSQL') ) {
        my @bind_copy = @bind_values;
        $self->{'lastsql'} = $sql;
        $self->{'lastsql'} =~ s/\?/$self->quote(shift(@bind_copy))/eg;



( run in 1.161 second using v1.01-cache-2.11-cpan-39bf76dae61 )