#!/usr/bin/env perl
#!/usr/local/bin/perl -w
# Albert Danial Jan 22 2005
use warnings;
use strict;
use File::Basename;
use DBI;
use DBD::SQLite 1.00;
use Data::Dumper;

# usage {{{1
my $script = basename $0;
my $usage  = "
Usage: $script  <partition db>

             Query the SQLite database containing a partitioned sofea
             model and its associated top-level database to get node
             indexing information.  Prints all ID's--original, canonical 
             within entire model, canonical within partition--for each 
             node, for each partition.  Identifies interior and boundary 
             nodes by
                 B - boundary node
                 I - interior node connected to other interior nodes
                 i - interior node that is not connected to any other
                     interior node
";
die $usage unless @ARGV;
# 1}}}

# open the two databases, load the boundary node table {{{1
my $partn_db_file = $ARGV[0];
$partn_db_file   .= ".db" unless -r $partn_db_file;
my $model_db_file = $partn_db_file;
$model_db_file    =~ s/_P\d+\.db$/.db/;
die "Cannot read corresponding model DB file '$model_db_file'\n"
    unless -r $model_db_file;

my $db     = DBI->connect("dbi:SQLite:dbname=$partn_db_file","","");
my $attach = "attach '$model_db_file' as MODEL_DB;";
my $st     = $db->do($attach);

# load the table which lists all the boundary nodes and the
# partitions they are in
my $query  = "select pid,nid from partition_bnode;";
my $raa    = $db->selectall_arrayref($query);
my %part_for_boundary_node = (); # pfbn{ seq_no } = [ list of partitions ]
my $nPartitions = 0;
foreach my $row (@{$raa}) {
    my $partition   = $row->[0]; # partitions numbered from 1..nPartitions
    my $node_seq_no = $row->[1];
    push @{$part_for_boundary_node{ $node_seq_no }}, $partition;
    $nPartitions = $partition if $partition > $nPartitions;
}
printf "Found %d partitions\n", $nPartitions;
# 1}}}
                                                                                
for (my $p = 1; $p <= $nPartitions; $p++) {

    # query to display all ID's for a each node  {{{1
    # MN.id     = node's user given ID (arbitrary alphanumeric)
    # MN.seq_no = node's 0-based canonical ID (for complete model)
    # CN.nid    = FK to MN.seq_no
    # CN.id     = node's 0-based canonical ID for this partition
    $query = sprintf "select MN.id, MN.seq_no, CN.nid, CN.id
                        from MODEL_DB.node MN, P%02d_canonical_nid CN
                        where MN.seq_no = CN.nid
                        order by CN.nid", $p, $p;
    my $raa   = $db->selectall_arrayref($query);
    # 1}}}

    # queries for nodes connected purely to interior, and to boundary nodes
    my %pure_interior_conn = (); # pic{ partn can. id of interior node } = 1
    my %boundary_conn      = (); # bc{  partn can. id of boundary node } = 1

    $query    = sprintf "select distinct(nid_a) from P%02d_node_node_i", $p;
    my $raaI  = $db->selectall_arrayref($query);
    if (@{$raaI}) { # interior could be null; test before trying to access it
        for (my $i = 0; $i < scalar @{$raaI}; $i++) {
            $pure_interior_conn{ $raaI->[$i][0] } = 1 };
    }

    $query    = sprintf "select distinct(nid_a) from P%02d_node_node_b", $p;
    my $raaB  = $db->selectall_arrayref($query);
    for (my $i = 0; $i < scalar @{$raaB}; $i++) {
        $boundary_conn{      $raaB->[$i][0] } = 1 };
                                                                                
    # print results {{{1
    printf "%2d: MODEL.node    P%02d_canonical_nid\n",
            $p, $p;
    print  "----------------  -----------------\n";
    print  "id        seq_no       nid       id\n";
    foreach my $row (@{$raa}) {
        printf "%-8s%8d  %8d %8d ", @{$row};
        my $node_seq_no = $row->[1];
        my $node_p_can  = $row->[3];
        # I - interior node
        # B - boundary node
        print "I" if $pure_interior_conn{ $node_p_can };
        print "B" if $part_for_boundary_node{$node_seq_no};
        printf "\n";
    }
    print "\n";
    # 1}}}
}
                                                                                
$st = $db->disconnect;
