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;
}