stonecolddevin has asked for the wisdom of the Perl Monks concerning the following question:

Hey all,
This is probably an ignorant question, but I'm having some trouble with Class::DBI retrieving all of the requested records from my database.
## index.cgi #!perl -w use strict; use PL; my $obj = PL->new; my @info = $obj->DBI->Entries->retrieve_from_sql(qq{ hidden = "n" ORDER BY date desc LIMIT 5 }); my %data; my @loop_data = (); ## NOT INCREMENTING PRIMARY KEY, THUS RETURNING THE FIRST ROW *TWICE* for (@info) { $data{author} = $_->author; $data{content} = $_->content; $data{title} = $_->title; $data{id} = $_->id; $data{date} = $_->date; push @loop_data, \%data; } my %content = ( title=>'Devin\'s Journal v.9', body=>\@loop_data, # CRITICAL: must + be arrayref containing hashref, # DBI should be $s +th->fetchrow_arrayref({}); search=>'search?q=', #to be defined in +Config.pm referer => $ENV{'REFERER'} ? $ENV{'REFERER'} : "none", IPAddy => $ENV{'REMOTE_ADDR'} ); $obj->Template->file ("tmpl/main.tmpl"); print $obj->Template->format ( \%content ); ## PL::DBI::Entries.pm package PL::DBI::Entries; use strict; use base 'PL::DBI'; sub new { my $class = shift; my $self = {}; bless $self, $class; return $self; } __PACKAGE__->columns( Primary => qw[id] ); __PACKAGE__->columns( All => qw [ id author title date content ip ] ); __PACKAGE__->table('entries'); 1;
It's retrieving two results, but it's the first record TWICE. What's going on here?
meh.

janitored by ybiC: Retitle from "Class::DBI" because one-word-node-titles hinder site search

Replies are listed 'Best First'.
Re: Duplicate rows with Class::DBI
by friedo (Prior) on Apr 25, 2005 at 23:09 UTC
    The problem lies here:

    my %data; my @loop_data = (); ## NOT INCREMENTING PRIMARY KEY, THUS RETURNING THE FIRST ROW *TWICE* for (@info) { $data{author} = $_->author; $data{content} = $_->content; $data{title} = $_->title; $data{id} = $_->id; $data{date} = $_->date; push @loop_data, \%data; }

    Your hash, %data, is defined outside the lexical block of the for-loop. At the end of the for-loop, you push a reference to %data onto @loop_data. The problem is that the next time through the loop, you modify the same %data, which is already being referenced by $loop_data[0], and push another reference to the same hash onto $loop_data[1]. Thus every element of @loop_data will be pointing to the same hash. You can fix this easily by declaring your %data hash inside the lexical block of your loop, so a new one gets created every time through the loop.

    my @loop_data; for (@info) { my %data; $data{author} = $_->author; $data{content} = $_->content; $data{title} = $_->title; $data{id} = $_->id; $data{date} = $_->date; push @loop_data, \%data; }

    Update: Formatting errors.

      Haha, friedo to the rescue yet again. I may have to write a perl meditation on that...;-)
      Worked like a charm, thanks very much :-)
      meh.

      Presuming that you want to push all the keys onto the array:

      push @loop_data, \%$_ for (@info);

        Why the \%$_? There's no need to copy $_'s referant, simply doing push @loop_data, $_ for @info would suffice. Of course, that's exactly the same as @loop_data = @info, so the whole thing is moot anyway. :)