Class::PObject::Driver::mysql - MySQL Pobject Driver


Class-PObject documentation Contained in the Class-PObject distribution.

Index


Code Index:

NAME

Top

Class::PObject::Driver::mysql - MySQL Pobject Driver

SYNOPSIS

Top

    use Class::PObject;
    pobject Person => {
        columns => ['id', 'name', 'email'],
        driver  => 'mysql',
        datasource => {
            DSN => 'dbi:mysql:db_name',
            User => 'sherzodr',
            Password => 'marley01'
        }
    };




DESCRIPTION

Top

Class::PObject::Driver::mysql is a direct subclass of Class::PObjecet::Driver::DBI. It inherits all the base functionality needed for all the DBI-related classes. For details of these methods and their specifications refer to Class::PObject::Driver and Class::PObject::Driver::DBI.

DATASOURCE

datasource attribute should be in the form of a hashref. The following keys are supported

METHODS

Top

Class::PObject::Driver::mysql (re-)defines following methods of its own

NOTES

Top

If the table is detected to be missing in the database, it will attempt to create proper table for you. To have more control over how it creates this table, you can fill-in column types using tmap argument.

SEE ALSO

Top

Class::PObject, Class::PObject::Driver::csv, Class::PObject::Driver::file

COPYRIGHT AND LICENSE

Top


Class-PObject documentation Contained in the Class-PObject distribution.

package Class::PObject::Driver::mysql;

# mysql.pm,v 1.25 2003/12/12 05:17:37 sherzodr Exp

use strict;
#use diagnostics;
use Log::Agent;
use vars ('@ISA', '$VERSION');
require Class::PObject::Driver::DBI;

@ISA = ('Class::PObject::Driver::DBI');
$VERSION = '2.01';

# 
# overriding _prepare_insert() with the version that uses REPLACE
# statement of MySQL instead of usual INSERT
#
sub _prepare_insert {
    my ($self, $table_name, $columns) = @_;

    my ($sql, @fields, @bind_params);
    $sql = "REPLACE INTO $table_name SET ";
    while ( my ($k, $v) = each %$columns ) {
        push @fields, "`$k`=?";
        push @bind_params, $v
    }
    $sql .= join(", ", @fields);
    return ($sql, \@bind_params)
}





sub save {
    my ($self, $object_name, $props, $columns) = @_;
    
    my $dbh                 = $self->dbh($object_name, $props)        or return;
    my $table               = $self->_tablename($object_name, $props, $dbh) or return;
    my ($sql, $bind_params) = $self->_prepare_insert($table, $columns);

    $self->_write_lock($dbh, $table) or return undef;
    my $sth                 = $dbh->prepare( $sql );
    unless ( $sth->execute(@$bind_params) ) {
        $self->errstr("couldn't save/update the record: " . $sth->errstr);
        logerr $self->errstr;
        return undef
    }
    $self->_unlock($dbh) or return undef;
    return $dbh->{mysql_insertid} || $dbh->{insertid}
}









sub dbh {
    my ($self, $object_name, $props) = @_;

    # checking if datasource provides adequate information to us
    my $datasource = $props->{datasource};
    unless ( ref($datasource) eq 'HASH' ) {    
        $self->errstr("'datasource' is invalid");
        return undef
    }
    if ( defined $props->{datasource}->{Handle} ) {
        return $props->{datasource}->{Handle}
    }
    my $stashed_name = $props->{datasource}->{DSN};
    if ( defined $self->stash($stashed_name) ) {
        return $self->stash($stashed_name)
    }
    if ( $datasource->{Handle} ) {
        $self->stash($stashed_name, $datasource->{Handle});
        return $datasource->{Handle}
    }
    my $dsn       = $datasource->{DSN};
    my $db_user   = $datasource->{User} || $datasource->{UserName};
    my $db_pass   = $datasource->{Password};
    unless ( $dsn ) {
        $self->errstr("'DSN' is missing in 'datasource'");
        return undef
    }
    require DBI;
    my $dbh = DBI->connect($dsn, $db_user, $db_pass, {RaiseError=>1, PrintError=>0});
    unless ( defined $dbh ) {
        $self->errstr("couldn't connect to 'DSN': " . $DBI::errstr);
        return undef
    }
    $dbh->{FetchHashKeyName} = 'NAME_lc';
    $self->stash($stashed_name, $dbh);
    $self->stash('close', 1);
    return $dbh
}



sub _tablename {
    my $self = shift;
    my ($object_name, $props, $dbh) = @_;

    unless ( defined $dbh ) {
        $dbh = $self->dbh( $object_name, $props )
    }
    my $tablename   = $self->SUPER::_tablename(@_);
    my $exists= 0;
    # if table by this name already exists in the database,
    # no reason to go any further.Return the name
    my $stashed = sprintf "exists:%s-%s", $dbh->{Name}, $tablename;
    if ( $self->stash($stashed) ) {
        logtrc 3, "'$stashed' was present. Table exists";
        return $tablename
    }
    
    # if we come this far, we're still not sure if the database 
    # exists or not. so we peek into the catalog.
    my %tables  = map { s/\W//g; $_, 1 } $dbh->tables;
    logtrc 3, "Retrieved %d tables from the database", scalar keys %tables;
    if ( $tables{ $tablename } ) {
        logtrc 3, "Table '%s' exists", $tablename;
        $self->stash($stashed, 1);
        return $tablename
    }

    my $sql = $self->_prepare_create_table($object_name, $tablename);
    unless ( $dbh->do( $sql ) ) {
        $self->errstr( $dbh->errstr );
        return undef
    }
    $self->stash($stashed, 1);
    return $tablename
}



sub _prepare_create_table {
    my ($self, $object_name, $tablename) = @_;

    my $sql = $self->SUPER::_prepare_create_table($object_name, $tablename);
    $sql =~ s/(id +INTEGER +PRIMARY +KEY)/$1 AUTO_INCREMENT/i;
    return $sql
}





1;
__END__;