[Dbix-class] Strange overwriting of values from db query

Byron Young Byron.Young at riverbed.com
Tue Jun 30 00:28:32 GMT 2009


kakimoto at tpg.com.au wrote on 2009-06-24:
> 
> hi guys,
> 
>  I have a very weird problem here.
>  I make 3 db search calls to a method, _get_entries_from_db and
> store each of the results in different hash slices of
> $lists{'active_list'}, $lists{'expired_list'} and
> $lists{'inactive_list'}.
> 
>  The weirdness occurs when I notice that the values in the hash
> slices
> change after each run of the method , _get_entries_from_db even if
> I did
> not write to them!
> 

The problem is that you're re-using the hashref you pass to _get_entries_from_db, which gets stored in the $user_subscriptions resultset that is returned.  Remember DBIC resultsets don't actually run the query until you ask for some data, so if you pass a hashref as the where clause and then subsequently modify that hash, your resultset will be modified.

Example:

package Test;

sub new {
  my $class = shift;
  my $hashref = shift;

  my $self = { data => $hashref };

  return bless $self, $class;
}
  
sub test {
  my $self = shift;

  print $self->{data}->{a} . "\n";
}

my $hashref = { a => 1 };
my $test_obj = Test->new($hashref);
$test_obj->test();
$hashref->{a} = 2;
$test_obj->test();


This will print 

1
2

because you changed the data that the test_obj was referencing.  Same thing is happening with your resultsets.

Just pass in some anonymous hashref to your _get_entries_from_db() call, like:

  $lists{'active_list'} = $self->_get_entries_from_db($c, { 'active_to' => { '>=', \'NOW()' } });

Byron

>  Here's the output
> ===============
> 
> [debug]  _get_entries_from_db - 7 entries pulled
> [debug]  _get_entries_from_db - 7 entries pulled
> [debug]  _get_entries_from_db - 68 entries pulled
> [debug]  _get_entries_from_db - 68 entries pulled
> [debug]  _get_entries_from_db - 4 entries pulled
> [debug]  _get_entries_from_db - 4 entries pulled
> [debug] R has 4
>  f has 4
> j has 4
> [debug] INACTIVE LIST -  inactive List has 4 entries
> [debug] INACTIVE LIST -  expired List has 4 entries
> [debug] INACTIVE LIST -  Active List has 4 entries
> [debug]  Outside, active_list has 4
> [debug]  Outside, inactive_list has 4
> [debug]  Outside, expired_list has 4
> [debug]  Retrieved current user's subscriptions.
> [debug] Rendering template "agents/subscriptions/manage.tt2"
> [info] Request took 0.259641s (3.851/s)
> 
> 
> 
> Here are the codes:
> =============
> 
> 
> sub _get_entries_from_db
> {
>     my ($self, $c, $user_subscriptions_filters) = @_;
>     
>     my $user_subscriptions =
> $c->model('gozilaDB::UserSubscriptions')->search(
>         $user_subscriptions_filters,
>         {
>             # join with the Subscriptions database table( identified via
>             # the accessor/relationship name, subscription. q{join}    
>             => q{subscription}, q{prefetch} => q{subscription},
>         },
>     );
>     
>     $c->log->debug(" _get_entries_from_db - " .
>     $user_subscriptions->count. " entries pulled" ); return
>     $user_subscriptions;
> }
> 
> 
> 
> 
> sub get_user_subscriptions
> {
>     my ( $self, $c, $args ) = @_;
>     
>     my %user_subscriptions_filter = (
>         q{user_id} =>
> gozila::Controller::Shared->get_current_active_user($c),
>     );
> 
>    my %extra_clause = (
>         q{join} => q{subscription},
>         # prefetch data from the subscriptions database table too
>     );
>     
>     if (defined($args->{'id'}))
>     {
>         $user_subscriptions_filter{'me.id'} = $args->{'id'};
>     }
>     
>     $c->log->debug( " _get_user_subscriptions -> Retrieving with
> args of "
>           . Data::Dumper->Dump( [\%user_subscriptions_filter] ) );
> 
>     my %lists = (); # get active entries
>     $user_subscriptions_filter{'active_to'} = { '>=', 'NOW()'};
>     $lists{'active_list'} = $self->_get_entries_from_db($c,
>     \%user_subscriptions_filter); my $r = $self->_get_entries_from_db($c,
> \%user_subscriptions_filter);
> 
>     # get expired entries $user_subscriptions_filter{'active_to'} = {
>     '<', 'NOW()'}; $lists{'expired_list'} =
>     $self->_get_entries_from_db($c, \%user_subscriptions_filter); my $f
>     =$self->_get_entries_from_db($c,
> \%user_subscriptions_filter);
> 
>     # get inactive entries - waiting for activation
>     $user_subscriptions_filter{'active_to'} = { '=', undef };
>     $lists{'inactive_list'} = $self->_get_entries_from_db($c,
>     \%user_subscriptions_filter); my $j =$self->_get_entries_from_db($c,
> \%user_subscriptions_filter);
> 
>     $c->log->debug("R has ". $r->count . "\n f has ".  $f->count
> ."\nj
> has ". $j->count );
>     $c->log->debug("INACTIVE LIST -  inactive List has " .
>     $lists{'inactive_list'}->count . " entries ");
>     $c->log->debug("INACTIVE LIST -  expired List has " .
>     $lists{'expired_list'}->count . " entries ");
>     $c->log->debug("INACTIVE LIST -  Active List has " .
> $lists{'active_list'}->count . " entries ");
> 
>     return \%lists;
> }
> 
> 
> 
> 
> thank you :)
> 
> K. akimoto
> 
> _______________________________________________
> List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
> IRC: irc.perl.org#dbix-class
> SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
> Searchable Archive: http://www.grokbase.com/group/dbix-
> class at lists.scsys.co.uk





More information about the DBIx-Class mailing list