Why not adopt me?
NAME
Data::Iterator::Hierarchical - Iterate hierarchically over tabular data
VERSION
Version 0.03
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 that is the result of naturally left joining several tables.
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. Input rows that consist entirely of undef()s are skipped.
So if the iterator returned by the hierarchical_iterator()
factory is called without arguments it behaves pretty much the same as the iterator that was supplied as the input except for the skipping of null rows. 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 in a 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.
If the interator returned in $inner_iterator
is not used (or even 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
In versions of Perl before 5.10 this module leaks closures as a consequnce of a bug in Perl's handling of reference counts. Consequnently the input iterator will not get released on these versions of Perl unless it is read to exhastion.
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:
RT: CPAN's request tracker
http://rt.cpan.org/NoAuth/Bugs.html?Dist=Data-Iterator::Hierarchical
AnnoCPAN: Annotated CPAN documentation
CPAN Ratings
Search CPAN
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.