The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Data::Iterator::Hierarchical - Iterate hierarchically over data

VERSION

Version 0.01

SYNOPSIS

      my $sth = $db->prepare(<<SQL);
        SELECT agent, co, co_name, sound
        FROM some_view_containing_left_joins 
        ORDER BY agent, co, sound
      SQL

      $sth->execute;

      my $it = hierarchical_iterator($sth);

      while( my($agent) = $it->(my $it_co, 1)) {
        print "agent=$agent\n";
        while( my ($co,$co_name) = $it_co->(my $it_sound, 2) ) {
          print "  co=$co, co_name=$co_name\n";
          while( my($sound) = $it_sound->() ) {
            print "    sound=$sound\n";   
          }
        }
      }

DESCRIPTION

This module allows nested loops to iterate in the natural way over a sorted rowset as would typically be returned from an SQL database query.

In the example from the synopsis we want an interator that loops over agent. Within that we want another interator to loop over country (code and name). Finally within that we want to loop over sound.

And mostly that's all there is to say the iterator should just "Do What I Mean" (DWIM).

input

     agent   |  co     | co_name  | sound
    =========|=========|==========|========
      X      |  B      | Belgum   | fizz
      X      |  D      | Germany  | bang
      X      |  D      | Germany  | pow
      X      |  D      | Germany  | zap
      Y      |  NULL   | NULL     | NULL
      Z      |  B      | Belgum   | NULL
      Z      |  E      | Spain    | bar 
      Z      |  E      | Spain    | bar 
      Z      |  I      | Italy    | foo

output

    agent=X
      co=B, co_name=Belgum
        sound=fizz
      co=D, co_name=Germany
        sound=bang
        sound=pow
        sound=zap
    agent=Y
    agent=Z
      co=B, co_name=Belgum
      co=E, co_name=Spain
        sound=bar
        sound=bar
      co=I, co_name=Italy
        sound=foo

EXPORT

hierarchical_iterator

FUNCTIONS

hierarchical_iterator($rowset_source)

A factory for iterator functions. Takes a rowset source as an argument and returns an interator function.

The input rowset is cannonically presented as iterator function that is to be called with no arguments in a list context and is expected to return the next row from the set as a list. When the input is exhasted the iterator is expected to return an empty list.

For convienience the data source can also be specified simply as \@array in which case the interator sub { shift @array } is assumed. Finally, if the data source is specified as anything other than an ARRAY or CODE reference then it is assumed to be an object that provides a fetchrow_array() method (such as a DBI handle).

$iterator->($inner_iterator,$want)

The ineresting function from this module is, of course, the iterator function returned by the iterator factory. This iterator when called in a list context without arguments simply returns the next a row of data, or an empty list to denote exhaustion. It is an error to call the iterator in a non-LIST context. As an artifact, rows that consist entirely of undef()s are skipped.

So, when called without arguments, the iterator returned by hierarchical_iterator() is pretty much the same as the iterator that was supplied as the input! The interesting stuff starts happening when you pass arguments to the iterator function.

The second argument instructs the interator to return only a limited number of leading columns to from each row. The first argument is used to return an inner Data::Iterator::Hierarchical iterator that will iterate over only the successive rows of the input until the leading colums change and return only the remaining columns.

    my ($col1,$col2) = $iterator->(my $inner_iterator,2);

The two arguments are specified this seemingly illogical order because the second argument becomes optional if the Want module is installed and the iterator is used in a simple list assignment (as above). In this case the number of columns can be inferred from the left hand side of the assignment.

In the above example, if $inner_iterator is not used to exhastion, then the next invocation of $iterator will discard all input rows until there is a different pair of values in the first two columns.

BUGS AND CAVEATS

Note that

To do: (need stuff in here about nulls, non-rectangular input, repeated rows, changing the number of columns half way etc.)

AUTHOR

Brian McCauley, <nobull at cpan.org>

BUGS

Please report any bugs or feature requests to bug-data-iterator-hierarchical at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Data-Iterator::Hierarchical. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Data::Iterator::Hierarchical

You can also look for information at:

ACKNOWLEDGEMENTS

COPYRIGHT & LICENSE

Copyright 2008 Brian McCauley, all rights reserved.

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.