sub parse_node()

in automation/tinc/main/ext/explain.pl [894:1023]


sub parse_node
{

    my ($ref_id, $parse_ctx, $depth, $plan_rows, $parent) = @_;

#    print "depth: $depth\n";
#    print "row: ",$plan_rows->[0],"\n"      if (scalar(@{$plan_rows}));

#    print "first: $first\n" if defined ($first);

    my $spclen = undef;
    my $node = undef;

    my $no_more_text = 0;

    while (scalar(@{$plan_rows}))
    {
        my $row = $plan_rows->[0];

        unless (defined($node))
        {
            $node = {};

            $node->{child} = [];

            $node->{txt} = "";
    
            $node->{parent} = $parent
                if (defined($parent));

            my $id = $$ref_id;
            $id++;
            $$ref_id= $id;
            $node->{id} = $id;
        }

        # XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX 
        # make initplan into a fake node so the graphs look nicer (eg
        # tpch query 15).  Prefix it with an arrow and add a fake cost.
        if ($row =~ m/\|(\s)*InitPlan(.*)slice/)
        {
            $row =~ s/InitPlan/\-\>  InitPlan/;
            if ($row !~ m/\(cost=/)
            {
                $row =~ s/\|$/\(cost=\?\)|/;
            }
        }

        if ($row !~ m/\|(\s)*\-\>/)
        {
            # add text to existing node

            if ($no_more_text)
            {
                print "error: no more text for ". $node->{id}, "\n";
            }

            $node->{txt} .= "\n" . $row;

#            print "txt: $node->{txt}\n";

            shift @{$plan_rows};
            next;
        }
        else
        {
            # new node
            unless ($no_more_text)
            {
                unless (length($node->{txt}))
                {
                    $node->{txt} .= $row;
                    shift @{$plan_rows};
                    next;
                }
            }

            # match the leading spaces before the '->', eg:
            # "|  ->  Sort  (cost=5990545.19..599..."

            my @spc = ($row =~ m/\|(\s*)\-\>/);

#            print "space match:", Data::Dumper->Dump(\@spc), "\n";

            $spclen = scalar(@spc) ?  length($spc[0]) : 0;

#            print "space len: $spclen, depth: $depth\n";

            if ($spclen > $depth)
            {
                # found a child
                push @{$node->{child}}, parse_node($ref_id, $parse_ctx,
                                                   $spclen, $plan_rows, 
                                                   $node->{id});
            }

        }

        if (defined($spclen))
        {
            if ($spclen <= $depth)
            { # found a sibling or parent
                # need to put the row back on the head of the list

                if (defined($node) && exists($node->{txt}))
                {
                    analyze_node($node, $parse_ctx);
                    
                    return $node;
                }
            }
        }
        else
        {
            die ("what the heck?");
        }

        $spclen = undef;
        $no_more_text = 1;

    } # end while
    
    if (defined($node))
    {
        analyze_node($node, $parse_ctx);
    }

    return $node;

}