DBIx-ProfileManager

 view release on metacpan or  search on metacpan

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

package DBIx::ProfileManager;

use strict;
use warnings;

our $VERSION = '0.03';

use DBI;
use DBI::Profile;
use Scalar::Util qw(weaken);

our %ORIGINAL_METHODS;

sub new {
    my ( $class, %args ) = @_;
    bless +{
        config => $args{config} || '!Statement',
        data => +{},
        path => [],
        is_started => 0,
    } => $class;
}

{
    no strict 'refs';
    for my $attr ( qw/config data path is_started/ ) {
        *{$attr} = sub {
            if ( @_ == 2 ) {
                $_[0]->{$attr} = $_[1];
            }
            else {
                return $_[0]->{$attr};
            }
        };
    }
}

sub profile_start {
    my ( $self, @db_handles ) = @_;

    my $config = $self->config;

    unless ( @db_handles > 0 ) {
        @db_handles = $self->_active_db_handles;
        $ENV{DBI_PROFILE} = $config;
    }
    
    if ( @db_handles > 0 ) {
        for my $dbh (@db_handles) {
            $dbh->{Profile} = $config;
        }
        if ( $db_handles[0] ) {
            $self->path($db_handles[0]->{Profile}{Path});
        }
    }

    $self->data(+{});
    $self->path( [ split(':', $config) ] ) if ( @{$self->path} == 0 );

    {
        no strict 'refs';
        no warnings 'redefine';

        my $pfm = $self;
        weaken( $pfm );

        my $cb = sub {
            my $dbh = shift;
            $pfm->_fetch_profile_data($dbh);
        };

        unless ( exists $DBI::db::{DESTROY} ) {
            *DBI::db::DESTROY = $cb;
        }

        $ORIGINAL_METHODS{disconnect} = \&DBI::db::disconnect;
        *DBI::db::disconnect = sub {
            my $dbh = shift;
            $cb->($dbh);
            $ORIGINAL_METHODS{disconnect}->($dbh);
        };
    };
    
    $self->is_started(1);
}

sub profile_stop {
    my $self = shift;
    return unless ($self->is_started);
    my @db_handles = $self->_active_db_handles;

    delete $ENV{DBI_PROFILE};
    delete $DBI::db::{DESTROY};
    
    for my $dbh (@db_handles) {
        $self->_fetch_profile_data( $dbh );
    }

    {
        no warnings 'redefine';
        *DBI::db::disconnect = $ORIGINAL_METHODS{disconnect};
    };
    
    $self->is_started(0);
}

sub data_formatted {
    my ($self, $format, @results) = @_;
    $format ||= '%{statement} : %{total}s / %{count} = %{avg}s avg (first %{first}s, min %{min}s, max %{max}s)';
    @results = $self->data_structured unless ( @results > 0 );
    my @formatted;

    for my $result ( @results ) {
        my $log = $format;
        $log =~ s/%\{?([\w_]+)\}?/(exists $result->{$1})?$result->{$1}:sprintf('%%{%s}',$1)/gex;
        push(@formatted, $log);
    }

    return wantarray ? @formatted : join("\n", @formatted);
}

sub data_structured {
    my $self = shift;
    my $data = $self->data;
    my @results;



( run in 0.902 second using v1.01-cache-2.11-cpan-d8267643d1d )