Class::DBI::MySQL + Time::Piece::MySQL problems

[prev] [thread] [next] [Date index for 2004/12/28]

From: batou
Subject: Class::DBI::MySQL + Time::Piece::MySQL problems
Date: 22:34 on 28 Dec 2004
I am trying to use Class::DBI::MySQL(v0.95) in
conjunction with the Time::Piece::MySQL(v0.05) module
with ActiveState Perl 5.8.6 for MSWin32 build 811. 
The problem I am running into is this:

after_set_logintime trigger error: Can't inflate
logintime to Time::Piece::MySQL using
'1->_attr(logintime)': Time::Piece is not a
Time::Piece::MySQL at
C:/Perl/site/lib/Class/Trigger.pm line 51
 at C:\CVS\CafePoints\CafeDatabase.pm line 882
CafeDB::Users CafeDB::Users=HASH(0x2739078) destroyed
without saving changes to logintime at
C:\CVS\CafePoints\CafeDatabase.pm line 0

The code that causes the error is the following:

	use Time::Piece::MySQL;
	my $t = Time::Piece->from_mysql_datetime('1970-01-01
00:00:00');
	$user1->logintime($t);

The DBI object declares the following for inflation
and deflation of the object:

CafeDB::Users->has_a(logintime =>
"Time::Piece::MySQL",
		inflate => sub {my $t = shift;
			Time::Piece->from_mysql_datetime(
				($t) == 0 ? '1970-01-01 00:00:00' : $t) },
		deflate => 'mysql_datetime' );


NOTE:  I added the ? : clause because MySQL 4.1 can
return a date of '0000-00-00 00:00:00' which causes
Time::Piece->strptime to blow up in bad ways since
it's not a valid date for that object.  Because of
thisTime::Piece::DBI causes it to return an undef for
such a date.  This undef causes Class::DBI to blow up
because because it was not a reference to an object
that was returned.  This was a second issue I ran
into, not related to the bug I'm dealing with now, but
this seemed to be the right place to report it.

I traced into the package and the problem seems to be
in the following subroutine:

sub _inflate_to_object {
	my $col = shift;
	return sub {
		my $self = shift;
		return if not defined $self->_attr($col);
		my ($a_class, %meths) = @{
$self->__hasa_rels->{$col} };
		if (my $obj = ref $self->_attr($col)) {
			return if UNIVERSAL::isa($obj, $a_class);
			return $self->_croak(
				"Can't inflate $col to $a_class using
'$self->_attr($col)': $obj is not a $a_class"
			);
		}
		my $get = $meths{'inflate'}
			|| ($a_class->isa('Class::DBI') ? "_simple_bless" :
"new");
		my $obj =
			(ref $get eq "CODE")
			? $get->($self->_attr($col))
			: $a_class->$get($self->_attr($col));
		return $self->_croak(
			"Can't inflate $col to $a_class via $get using
'$self->_attr($col)'")
			unless ref $obj;  # use ref as $obj may be
overloaded and appear 'false'
		$self->_attribute_set($col => $obj);
	};
}

It is dieing because you have to tell it to use the
class "Time::Piece::MySQL" in order to access the
'from_mysql_datetime' method.  However, when it gets
to the check for the class of the object created by
Time::Piece::MySQL is in the package of "Time::Piece"
so it blows up on the UNIVERSAL::isa check.

I tried adding the following line in my base class of
the object (not the actual Class::DBI file):

			return if ($a_class =~ /Time::Piece/ &&
UNIVERSAL::isa($obj, "Time::Piece"));

This didn't work however, as it allways traced into
the actual Class::DBI file.  Does anyone know how to
fix this?  

Class::DBI::MySQL + Time::Piece::MySQL problems
batou 22:34 on 28 Dec 2004

Re: Class::DBI::MySQL + Time::Piece::MySQL problems
Perrin Harkins 22:44 on 28 Dec 2004

Generated at 12:15 on 16 Jan 2005 by mariachi v0.52