Author: spadkins
Date: Sat Mar  7 11:08:54 2009
New Revision: 12576

Added:
   p5ee/trunk/App-Repository/bin/dash   (contents, props changed)

Log:
new

Added: p5ee/trunk/App-Repository/bin/dash
==============================================================================
--- (empty file)
+++ p5ee/trunk/App-Repository/bin/dash  Sat Mar  7 11:08:54 2009
@@ -0,0 +1,340 @@
+#!/usr/bin/perl -w
+
+use Date::Format;
+
+use App::Options (
+    options => [ qw(dbhost dbname dbuser dbpass repository table params 
columns headings compact decimals subtotal_columns totals
+                    distinct cache_skip cache_refresh silent) ],
+    option => {
+        repository => {
+            default => "default",
+            description => "Name of the repository to get the rows from",
+        },
+        table => {
+            description => "Table name (i.e. --table=customer)",
+        },
+        params => {
+            description => "List of params (var=value pairs) (i.e. 
--params=\"last_name=Jones|first_name=Mike\")",
+        },
+        columns => {
+            description => "List of columns (comma-separated list) (i.e. 
--columns=first_name,last_name)",
+        },
+        headings => {
+            description => "List of heading abbreviations (comma-separated) 
(i.e. --headings=first,last)",
+        },
+        compact => {
+            description => "Trim titles to make compact table",
+        },
+        decimals => {
+            description => "Number of decimal places to print on floats",
+            default => "2",
+        },
+        subtotal_columns => {
+            description => "Print sub-totals at the end",
+        },
+        totals => {
+            description => "Print totals at the end",
+        },
+        cache_skip => {
+            description => "Skip any cached values for the table",
+        },
+        cache_refresh => {
+            description => "Skip any cached values for the table but save the 
results in the cache",
+        },
+        distinct => {
+            description => "Select only distinct rows",
+        },
+        silent => {
+            default => 0,
+            description => "Do not emit prompts or other messages (useful 
during scripted use)",
+        },
+    },
+);
+
+use App;
+use strict;
+
+my $LOADED_TERM_READLINE = 0;
+my $term = undef;
+
+$| = 1;  # autoflush stdout
+
+{
+    my $context  = App->context();
+    my $options  = $context->{options};
+    &init($options);
+    my $silent   = $options->{silent};
+    my $done = 0;
+    my ($command, $command_entry);
+    my $prompt = "dash";
+    while (!$done) {
+        $command_entry = &get_command_entry($prompt, $options);
+        $command = &get_command_from_command_entry($command_entry);
+        if (!$command) {
+            #print "I didn't understand that.\n";
+            #print "Please try 'help' for help on the available commands and 
their use\n";
+        }
+        elsif ($command eq "help" || $command eq "?") {
+            &show_help($command_entry);
+        }
+        elsif ($command eq "repository") {
+            &set_repository($command_entry);
+        }
+        elsif ($command eq "select") {
+            &show_select($command_entry);
+        }
+        elsif ($command eq "exit") {
+            $done = 1;
+        }
+        else {
+            print "I don't know the '$command' command.\n";
+            print "Please try 'help' for help on the available commands and 
their use\n";
+        }
+    }
+    print "Goodbye\n" if (!$silent);
+}
+
+sub init {
+    my ($options) = @_;
+    eval { use Term::ReadLine; };
+    if ($@) {
+        $LOADED_TERM_READLINE = 0;
+    }
+    else {
+        $LOADED_TERM_READLINE = 1;
+        $term = Term::ReadLine->new($options->{app});
+    }
+}
+
+sub get_command_entry {
+    my ($prompt, $options) = @_;
+    my ($command_entry);
+    if ($LOADED_TERM_READLINE) {
+        $command_entry = &get_command_entry_readline($prompt, $options);
+    }
+    else {
+        $command_entry = &get_command_entry_std($prompt, $options);
+    }
+    return($command_entry);
+}
+
+sub get_command_entry_std {
+    my ($prompt, $options) = @_;
+    print "$prompt> " if (!$options->{silent});
+    my $command_entry = <STDIN>;
+    return($command_entry);
+}
+
+sub get_command_entry_readline {
+    my ($prompt, $options) = @_;
+    my $readline_prompt = $options->{silent} ? "" : "$prompt> ";
+    my $command_entry = $term->readline($readline_prompt);
+    return($command_entry);
+}
+
+sub get_command_from_command_entry {
+    my ($command_entry) = @_;
+    my ($command);
+    if ($command_entry =~ /^([a-zA-Z_\?]+)/) {
+        $command = $1;
+    }
+    return($command);
+}
+
+sub show_help {
+    my ($command_entry) = @_;
+    print "============================================================\n";
+    print "COMMANDS:\n";
+    print "============================================================\n";
+    print "help - [synonym: ?] show this list of commands\n";
+    print "exit - quit the program\n";
+}
+
+sub set_repository {
+    my ($command_entry) = @_;
+}
+
+sub show_select {
+    my ($command_entry) = @_;
+    my $context  = App->context();
+    my $db       = $context->repository($App::options{repository});
+    my $rows = $db->_do($command_entry);
+    foreach my $row (@$rows) {
+        print "ROW:[", join("|", @$row), "]\n";
+    }
+}
+
+sub foo {
+    my $context  = App->context();
+    my $db       = $context->repository($App::options{repository});
+    my $table    = $App::options{table};
+    my ($columns, $params, $headings, $get_options, $cache_rows);
+    if ($table && $App::options{hashkey}) {
+        my $hashkey = $App::options{hashkey};
+        my $table_def = $db->get_table_def($table);
+        my $cache_name = $table_def->{cache_name};
+        if ($cache_name) {
+            my $cache = $context->shared_datastore($cache_name);
+            my $ref = $cache->get_ref($hashkey);
+            if (!$ref) {
+                warn "Nothing in the [$cache_name] cache for table [$table] 
with hashkey [$hashkey]\n";
+            }
+            else {
+                ($table, $params, $columns, $cache_rows, $get_options) = @$ref;
+                $get_options->{cache_skip} = 1;
+                print $db->dump([$table, $params, $columns, $get_options]);
+            }
+        }
+        else {
+            warn "cache_name option is not set on table $table";
+        }
+    }
+    else {
+        if ($App::options{columns}) {
+            $columns  = [ split(/,/, $App::options{columns}) ];
+        }
+        else {
+            $columns  = $db->_get_default_columns($table);
+        }
+        die "Must supply the --params option\n" if (! defined 
$App::options{params});
+        $params   = { split(/[=>\|]+/, $App::options{params}) };
+        $headings = $App::options{headings} ? [ split(/,/, 
$App::options{headings}) ] : [];
+        $get_options = { extend_columns => 1 };
+    }
+    $get_options->{distinct} = 1 if ($App::options{distinct});
+    $get_options->{cache_skip} = 1 if ($App::options{cache_skip});
+    $get_options->{cache_refresh} = 1 if ($App::options{cache_refresh});
+    my $rows     = $db->get_rows($table, $params, $columns, $get_options);
+    my ($subtotal_rows, $total_rows);
+    if ($App::options{subtotal_columns}) {
+        my $subtotal_columns = [ split(/,/, $App::options{subtotal_columns}) ];
+        $subtotal_rows = $db->summarize_rows($table, $rows, $columns, 
$subtotal_columns);
+    }
+    if ($App::options{totals}) {
+        $total_rows = $db->summarize_rows($table, $rows, $columns);
+    }
+    if ($subtotal_rows) {
+        push(@$rows, @$subtotal_rows);
+    }
+    if ($total_rows) {
+        push(@$rows, @$total_rows);
+    }
+    my $formats  = [];
+    &print_table($rows, $columns, $formats, { compact => 
$App::options{compact}, headings => $headings });
+}
+
+sub print_table {
+    &App::sub_entry if ($App::trace);
+    my ($rows, $columns, $formats, $options) = @_;
+    my ($row, $r, $c, $elem, $format, $len, $f, $heading);
+    my (@autoformat);
+    my $headings = $options->{headings};
+
+    # compute the number of columns as the max columns of any row
+    my $max_columns = 0;
+    for ($r = 0; $r <= $#$rows; $r++) {
+        $row = $rows->[$r];
+        if ($max_columns < $#$row + 1) {
+            $max_columns = $#$row + 1;
+        }
+    }
+
+    # compute automatic sprintf formats
+    for ($c = 0; $c < $max_columns; $c++) {
+
+        if (! defined $autoformat[$c]) {
+            $autoformat[$c] = {
+                max_length => 0,
+                type => 2,        # 0=string, 1=float, 2=integer
+                min => undef,
+                max => undef,
+            };
+        }
+        $f = $autoformat[$c];
+
+        # set the length of the column by the length of its heading
+        $heading = ($headings && $headings->[$c]) ? $headings->[$c] : "";
+        if ($heading) { 
+            $len = length($heading);
+            if ($len > $f->{max_length}) {
+                $f->{max_length} = $len;
+            }
+        }
+        elsif (! $options->{compact}) { 
+            $len = length($columns->[$c]);
+            if ($len > $f->{max_length}) {
+                $f->{max_length} = $len;
+            }
+        }
+
+        for ($r = 0; $r <= $#$rows; $r++) {
+            $row = $rows->[$r];
+            if ($c <= $#$row && defined $row->[$c]) {
+                $elem = $row->[$c];
+                $len = length($elem);
+                if ($elem =~ /^-?[0-9]*\.[0-9]+$/) {  # float
+                    $len = length(sprintf("%.$App::options{decimals}f",$elem));
+                    $f->{type} = 1 if ($f->{type} > 1);
+                    if (!defined $f->{min} || $elem < $f->{min}) {
+                        $f->{min} = $elem;
+                    }
+                    if (!defined $f->{max} || $elem < $f->{max}) {
+                        $f->{max} = $elem;
+                    }
+                }
+                elsif ($elem =~ /^-?[0-9]+$/) { # integer
+                    if (!defined $f->{min} || $elem < $f->{min}) {
+                        $f->{min} = $elem;
+                    }
+                    if (!defined $f->{max} || $elem < $f->{max}) {
+                        $f->{max} = $elem;
+                    }
+                }
+                else {
+                    $f->{type} = 0;
+                }
+                $f->{max_length} = $len if ($len > $f->{max_length});
+            }
+        }
+        &determine_sprintf_fmt($f);
+    }
+    for ($c = 0; $c <= $#$columns; $c++) {
+        $format = $autoformat[$c]->{title_fmt} || "%s";
+        print " " if ($c > 0);
+        $heading = ($headings && $headings->[$c]) ? $headings->[$c] : 
$columns->[$c];
+        printf($format, $heading);
+    }
+    print "\n";
+    for ($r = 0; $r <= $#$rows; $r++) {
+        $row = $rows->[$r];
+        for ($c = 0; $c <= $#$row; $c++) {
+            $format = $autoformat[$c]->{fmt} || "%s";
+            print " " if ($c > 0);
+            printf($format, $row->[$c]);
+        }
+        print "\n";
+    }
+    &App::sub_exit() if ($App::trace);
+}
+
+sub determine_sprintf_fmt {
+    &App::sub_entry if ($App::trace);
+    my ($f) = @_;
+    my ($width, $int_len, $fract_len);
+    if ($f->{type} == 1) {     # float
+        $f->{title_fmt} = "%$f->{max_length}.$f->{max_length}s";
+        $f->{fmt} = "%$f->{max_length}.$App::options{decimals}f";
+    }
+    elsif ($f->{type} == 2) {  # integer
+        $f->{title_fmt} = "%$f->{max_length}.$f->{max_length}s";
+        $f->{fmt} = "%$f->{max_length}d";
+    }
+    else {                     # string
+        $f->{title_fmt} = "%-$f->{max_length}.$f->{max_length}s";
+        $f->{fmt} = "%-$f->{max_length}s";
+    }
+    &App::sub_exit($f->{fmt}) if ($App::trace);
+}
+
+exit (0);
+

Reply via email to