Re: before_create trigger problems
[prev]
[thread]
[next]
[Date index for 2004/12/21]
--On Tuesday, December 21, 2004 10:35:50 AM EST -0800 Emile Aben
<emileaben@xxxxx.xxx> wrote:
>
> --- Emile Aben <emileaben@xxxxx.xxx> wrote:
>
>>
>> --- Tony Bowden <tony-cdbitalk@xxxxx.xxx> wrote:
>>
>> > On Mon, Dec 20, 2004 at 05:39:11PM -0800, Emile
>> Aben
>> > wrote:
>
> Cheered too early. Now I'm genuinly confused. In my
> triggered routine I fetch information from the
> database, and I seem to have to use the low-level
> access sometimes, but not at other times:
>
> sub _fixup_exclusive {
> my ($this) = @_;
> # need to use low-level accessors(_attrs) and not
> set/get here because we're in a trigger!
> # shouldn't be too many @attrs that match
> my @mondata_list = __PACKAGE__->search (
> {
> monitor => $this->_attrs("monitor"),
> attribute => $this->_attrs("attribute"),
> }
> );
>
> my $new_start = $this->_attrs("start_date");
> my $new_end = $this->_attrs("end_date");
> foreach my $old (@mondata_list) {
> next if ( $this->_attrs("id")
> && $this->_attrs("id") eq $old->_attrs("id") );
> my $old_start = $old->start_date();
> my $old_end = $old->end_date();
>
> next if ($old_end && ( $old_end < $new_start ));
> print STDERR "NEW: $new_start -> $new_end \n";
> print STDERR "OLD: $old_start -> $old_end \n";
> use Data::Dumper; print Dumper($old);
>
>
> $old is an object created from a search in the
> database, but to be able to access anything other than
> the primary key, I have to use the accessor
> 'start_date', otherwise the data for this object won't
> actually be fetched from the database (checked that
> with Data::Dumper).
That's as designed, though I agree it seems a surprise sometimes. The
philosophy is this (with the hope that more informed readers will correct
any errors I may make):
- "low-level" accessors retrieve or modify the relevant property of the
object in core, without triggering any side effects, including
inflation/deflation, lazy loading, or other triggers. The intent is to
allow code which may itself be in a trigger to make modifications without
setting up infinite recursion, or doing unnecessary work. Since the intent
was for these to be "internal" routines, they don't do extra work for the
caller (e.g. looking up column names, though that'd be easy enough to add).
This also makes them somewhat more efficient than the "regular" accessors
for simple operations, though speed isn't a major goal of CDBI.
- "regular" accessors retrieve or modify the relevant property of the
object as modelled by the CDBI class, with all of the class's side effects
(typically via triggers, though possibly via a custom get() or set()
function), including inflation/deflation, lazy loading, etc. This should
be the usual way to access object attributes, but for the reasons mentioned
above can cause problems when used in triggers. The before_create case is
special in another way: even if one can guarantee that a trigger won't
cause infinite recursion or a similar problem, there's no guarantee that
the object which is about to be created will be sufficiently assembled for
a "regular" accessor (or its side effects) to function properly. As a
consequence, before_create triggers should only use the low-level
accessors, and will need to account for any preprocessing needed to insure
that the value supplied by the caller is in the proper format to be written
to the database (modulo stringification, though I think that's more a
detail of the current implementation than a documented behavior).
This should become much cleaner when we have smarter attributes which can
handle interconversions on their own. Back to the tuit search . . .
> Further on in the triggered sub I sometimes have to
> create a new object in the database, and I'm currently
> unable to get this working. My best try is:
>
> if ($new_end && $new_start >=
> $old_start && (!$old_end || $new_end <= $old_end ) ) {
> # case: nnnn
> # ooooooooo(...)
> # solution: cut old in 2
> print STDERR " nnnn\n";
> print STDERR " ooooooooo(...)\n";
> my $old2 = $old->copy();
> $old2->_attribute_set("start_date", $new_end + 1 );
> $old2->update();
> $old->_attribute_set("end_date", $new_start - 1 );
> $old->update();
> }
>
> This get's stuck on line 51 in Trigger.pm again:
> Can't retrieve a reference at
> /usr/local/perl-5.6.0/lib/site_perl/5.6.0/Class/Trigger.pm
> line 51
Hmm. Do you happen to know whether the copy() or the update() triggers
this error?
--
Regards,
Charles Bailey < bailey _at_ newman _dot_ upenn _dot_ edu >
Newman Center at the University of Pennsylvania
|
(message missing)
|