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

Hello folks, Can one of you Monkish gentlemen help me with this? I am stuck with a recursion issue here. Basically i am trying to print out a spreadsheet of parents and children of this structure:

A1

A1 B1

A1 B1 C1

A1 B1 C1 D1

A1 B1 C2

A1 B1 C3

A1 B1 C4 D2

A1 B2

A1 B2 C5 D3

Here B1 is child of A1 and C1 is child of B1. B1 has many children C1,C2,C3 C4. My program succeeds till line 4. The moment the last child doesn't have a grand child under it, it stops. How could I make it go back and keep on printing out till the end? Here is my actual code snippet: $top calls the first asset A1 which is parent of B1,B2 etc.
my @line; foreach (my $top = $top_sth->fetchrow_hashref) { $line[0]= $top->{guid}; push @line,$top->{title}; $exchange->stdxls_write($exchange->stdxls_row(), \@line); print STDERR "Level1 ".$top->{title}."\n"; child_levels($top->{asset_id},@line); } $workbook->close(); sub child_levels { my ($asset_id,@line) = @_; my $child_sth = $dbh->prepare(' SELECT asset_id ,title ,seq ,guid ,parent_id FROM asset WHERE parent_id = ? ORDER BY seq ') or die $dbh->errstr; $child_sth->execute($asset_id) or die $child_sth->errstr; foreach (my $child = $child_sth->fetchrow_hashref) { $line[0]= $child->{guid}; push @line,$child->{title}; $exchange->stdxls_write($exchange->stdxls_row(), \@line); child_levels($child->{asset_id},@line); }

Replies are listed 'Best First'.
Re: Recursive program
by roboticus (Chancellor) on Aug 22, 2014 at 18:06 UTC

    newtoperl101:

    I think the part that's biting you is the fact that you're trying to use the database recursively. Many (most?) database interfaces let you have only one active statement at a time, so once you go down a level, you're effectively destroying the resultset of the caller. I'd suggest one of two ways to work around it:

    • Instead of processing the results as you read them from the database, read the entire set of results into an array. Then loop over the array to further process it.
      The disadvantage is that your memory size can increase dramatically, but unless you have wide and deep hierarchies, that's not likely to be an issue.
    • Alternatively, you could use multiple database connections--specifically create a new database handle inside child_levels. This way, each statement will use its own database handle, and won't be killed by the routine. The disadvantage is that it consumes multiple database connections.

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

Re: Recursive program
by remiah (Hermit) on Aug 24, 2014 at 02:43 UTC

    hello newtoperl101

    I wonder how it will be if you change this line

    $exchange->stdxls_write($exchange->stdxls_row(), \@line);
    to
    print join('', @line) . "\n";
    I mean I would like to separate excel things from recursive call problems.
    regards.