perldbifetchall

Iterating the results returned from fetchall_arrayref


I have a sql wherein I am fetching few records, sorted by full name.

My requirement is to extract chunks of similar names and then do some operation on it.

Say, the sql returns some records containing names like [name1,name1,name2,name3,name3]

I need to split them to [name1,name1] , [name2] , [name3,name3]

I am able to do it, but I am not happy with my implementation as I have to call doSomethingWithNames()twice.

while (my $paRecs = $pStatementHandle->fetchall_arrayref({}, 3)){
   foreach my $phRec(@{$paRecs}){
       my $pCurrentName = $phRec->{'FULL_NAME'};
       if ((scalar(@aParentRecords) eq 0) or ($aParentRecords[-1] eq $pCurrentName)){
           push(@aParentRecords, $pCurrentName);
       } else {
           doSomethingWithNames(\@aParentRecords);
           @aParentRecords= ();
           push(@aParentRecords, $pCurrentName);
       }
   }
};
doSomethingWithNames(\@aParentRecords); # This should be inside while loop  

I believe am running into this issue because while doesn't go into the loop for the last iteration as fetch* returns undef.

Sounds basic PERL stuff, but tried many loop constructs with no luck. Any pointer will be a great help


Solution

  • The trick is to postpone existing the loop by converting it into an infinite loop. This requires checking the loop-terminating condition (!$rows) twice, though.

    my $rows = [];
    my $prev_name = '';
    my @group;
    while (1) {
       $rows = $sth->fetchall_arrayref({}, 3) if !@$rows;
    
       if (!$rows || $rows->[0]->{FULL_NAME} ne $prev_name)
          if (@group) {
             do_something(\@group);
             @group = ();
          }
    
          last if !$rows;
       }
    
       $prev_name = $rows->[0]->{FULL_NAME};
       push @group, shift(@$rows);
    }