Strange overwriting of values from db query

2 messages Options
Embed this post
Permalink
kakimoto

Strange overwriting of values from db query

Reply Threaded More More options
Print post
Permalink

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!

 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@...
Byron Young

RE: Strange overwriting of values from db query

Reply Threaded More More options
Print post
Permalink
[hidden email] 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-
> [hidden email]



_______________________________________________
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@...