After trying to follow the output of SQLite's "explain" command, I waved Graph::Easy at it and produced reasonable graphs of the possible execution flow.

The script below is quite rudimentary but I'm interested in getting feedback early on.

I'd also like pointers to information on converting stack-based languages like vdbe and postscript into a conventional (applicative?) language, if it's possible.

$ sqlite3 db 'create table exampl (one, two)'; $ sqlite3 -separator $'\t' db 'explain select one from exampl'; | tee +ops |head -n 3 0 Goto 0 10 1 Integer 0 0 2 OpenRead 0 2 # Edited output in asc format $ ./vdbe_graph.pl -f asc ops [...] +------------------------+ | 2 OpenRead (0, 2) | +------------------------+ v +------------------------+ | 3 SetNumColumns (0, 1) | +------------------------+ v +------------------------+ | 4 Rewind (0, 8) | -+ +------------------------+ | v | +------------------------+ | +> | 5 Column (0, 0) | | | +------------------------+ | | v | | +------------------------+ | | | 6 Callback (1, 0) | | | +------------------------+ | | v | | +------------------------+ | +- | 7 Next (0, 5) | | +------------------------+ | v | +------------------------+ | | 8 Close (0, 0) | <+ +------------------------+ v [...]
The code for vdbe_graph.pl
#!/usr/bin/perl -w # vdbe_graph.pl use strict; use YAML; use Graph::Easy; use Getopt::Std; binmode STDOUT, ':utf8'; my %opt; getopts('o:f:', \%opt); my $g = Graph::Easy->new(); $g->set_attribute('flow', 'south'); my $prev; my @ops; while (<>) { chomp; my @fields = split /\t/, $_; next unless $fields[0] =~ /^\d+$/; my %curr; @curr{qw(n op p1 p2 p3)} = @fields; my $params = join(", ", @fields[2..$#fields]); my $n = $g->add_node($curr{n}); $n->set_attribute(label => "$curr{n} $curr{op} ($params)"); $n->set_attribute(align => 'left'); if ($prev) { $g->add_edge($prev->{n} => $curr{n}); } $prev = \%curr; push @ops, \%curr; } # If P2 is not zero and one or more of the entries are NULL, then jum +p to the address given by P2 # MakeRecord MoveGe MoveGt MoveLt MoveLe Rewind my %jumps = map { $_ => 1 } qw( Next Prev Gosub ForceInt MustBeInt Eq Ne Lt Le Gt Ge If IfNot IsNull NotNull MakeRecord MoveGe MoveGt MoveLt MoveLe Distinct Found NotFound IsUnique NotExists Last Rewind IdxGT IdxGE IdxLT FifoRead IfMemPos IfMemNeg IfMemZero VFilter VNe +xt); for my $n (grep { exists $jumps{$_->{op}} } @ops) { $g->add_edge($n->{n} => $n->{p2}); } for my $n (grep { $_->{op} eq 'Goto' } @ops) { $g->add_edge($n->{n} => $n->{p2}); if ($n->{n} != $n->{n}+1) { $g->del_edge($g->edge($n->{n} => $n->{n}+1)); } } for my $n (grep { $_->{op} eq 'Halt' } @ops) { next unless $g->node($n->{n}+1); $g->del_edge($g->edge($n->{n} => $n->{n}+1)); } my $ext = ($opt{o} && $opt{o} =~ /\.(...)$/) ? $1 : ''; my %ext_formats = ( asc => 'ascii', html=> 'html', txt => 'txt', box => 'boxart', viz => 'graphviz', png => 'graphviz', ); my $format = $ext_formats{ $opt{f} || ''} || $opt{f} || $ext_formats{ext} || 'ascii'; # Where does the output go if (defined $opt{o}) { if ($ext eq 'png') { open OUT, "| dot -Tpng -o $opt{o}"; } else { open OUT, "> $opt{o}"; } select OUT; } if ($format eq 'ascii') { print $g->as_ascii; } elsif ($format eq 'boxart') { print $g->as_boxart; } elsif ($format eq 'graphviz') { print $g->as_graphviz; } elsif ($format eq 'txt') { print $g->as_txt; } elsif ($format eq 'html') { print $g->as_html; } else { die; }

In reply to Graphing SQLite's VDBE by bsb

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.