home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / tsw / TSW_3.4.0.exe / Apache2 / perl / SQLMinus.pm < prev    next >
Encoding:
Perl POD Document  |  2002-12-13  |  36.1 KB  |  1,374 lines

  1. #!perl -w
  2. # vim:ts=4:sw=4:aw:ai:nowrapscan
  3. #
  4. #
  5.  
  6. package DBI::Shell::SQLMinus;
  7.  
  8. use strict;
  9. use Text::Abbrev ();
  10. use Text::ParseWords;
  11. use Text::Wrap;
  12. use IO::File;
  13. use IO::Tee;
  14. use Carp;
  15.  
  16. use vars qw(@ISA $show $set $VERSION);
  17.  
  18. $VERSION = sprintf( "%d.%02d", q$Revision: 11.91 $ =~ /(\d+)\.(\d+)/ );
  19.  
  20. sub init {
  21.     my ($class, $sh, @args) = @_;
  22.     $class = ref $class || $class;
  23.     my $sqlminus = {
  24.         archive    => {
  25.             log    => undef,
  26.         },
  27.         'breaks' => {
  28.             skip        => [ qw{text} ],
  29.             skip_page    => [ qw{text} ],
  30.             dup            => [ qw{text} ],
  31.             nodup        => [ qw{text} ],
  32.         },
  33.         break_current => {
  34.         },
  35.         'clear'    => {
  36.             break    => undef,
  37.             buffer    => undef,
  38.             columns    => undef,
  39.             computes    => undef,
  40.             screen    => undef,
  41.             sql        => undef,
  42.             timing    => undef,
  43.         },
  44.         db    => undef,
  45.         dbh => undef,
  46.         column => {
  47.             column_name    => [ qw{text} ],
  48.             alias        => [ qw{text} ],
  49.             clear        => [ qw{command} ],
  50.             fold_after    => [ qw{text} ],
  51.             fold_before    => [ qw{text} ],
  52.             format        => [ qw{text} ],
  53.             heading        => [ qw{text} ],
  54.             justify        => [ qw{c l r f} ],
  55.             like        => [ qw{text} ],
  56.             'length'    => [ qw{text} ],
  57.             newline        => [ qw{text} ],
  58.             new_value    => [ qw{text} ],
  59.             noprint        => [ qw{on off} ],
  60.             'print'        => [ qw{on off} ],
  61.             null        => [ qw{text} ],
  62.             on            => 1,
  63.             off            => 0,
  64.             truncated    => [ qw{on off} ],
  65.             type        => [ qw{text} ],
  66.             wordwrapped    => [ qw{on off} ],
  67.             wrapped        => [ qw{on off} ],
  68.             column_format    => undef,
  69.             format_function => undef,
  70.             precision    =>    undef,
  71.             scale        => undef,
  72.         },
  73.         # hash ref contains formats for code.
  74.         column_format => {
  75.         },
  76.         # Hash ref contains the formats for the column headers.
  77.         column_header_format => {
  78.         },
  79.         commands => {
  80.             '@'        => undef,
  81.             'accept'=> undef,
  82.             append    => undef,
  83.             attribute => undef,
  84.             break    => undef,
  85.             btitle    => undef,
  86.             change    => undef,
  87.             clear    => undef,
  88.             copy    => undef,
  89.             column    => undef,
  90.             compute    => undef,
  91.             define    => undef,
  92.             edit    => undef,
  93.             'exec'    => undef,
  94.             get        => undef,
  95.             pause    => undef,
  96.             prompt    => undef,
  97.             repheader=> undef,
  98.             repfooter=> undef,
  99.             run        => undef,
  100.             save    => undef,
  101.             set        => undef,
  102.             show    => undef,
  103.             start    => undef,
  104.             ttitle    => undef,
  105.             undefine=> undef,
  106.         },
  107.         set_current    => {
  108.             appinfo        => undef,
  109.             arraysize    => undef,
  110.             autocommit    => undef,
  111.             autoprint    => undef,
  112.             autorecovery=> undef,
  113.             autotrace    => undef,
  114.             blockterminator=> undef,
  115.             buffer        => undef,
  116.             closecursor    => undef,
  117.             cmdsep        => undef,
  118.             compatibility=> undef,
  119.             concat        => undef,
  120.             copycommit    => undef,
  121.             copytypecheck=> undef,
  122.             define        => undef,
  123.             document    => undef,
  124.             echo        => undef,
  125.             editfile    => undef,
  126.             embedded    => undef,
  127.             escape        => undef,
  128.             feedback    => undef,
  129.             flagger        => undef,
  130.             flush        => undef,
  131.             heading     => 1,
  132.             headsep     => ' ',
  133.             instance     => undef,
  134.             linesize    => 72,
  135.             limit        => undef,
  136.             loboffset    => undef,
  137.             logsource    => undef,
  138.             long        => undef,
  139.             longchunksize    => undef,
  140.             maxdata        => undef,
  141.             newpage        => undef,
  142.             null        => undef,
  143.             numwidth    => undef,
  144.             pagesize    => undef,
  145.             pause        => undef,
  146.             recsep         => 1,
  147.             recsepchar     => ' ',
  148.             scan        => qq{obsolete command: use 'set define' instead},
  149.             serveroutput=> undef,
  150.             shiftinout    => undef,
  151.             showmode    => undef,
  152.             space        => qq{obsolete command: use 'set define' instead},
  153.             sqlblanklines=> undef,
  154.             sqlcase        => undef,
  155.             sqlcontinue    => undef,
  156.             sqlnumber    => undef,
  157.             sqlprefix    => undef,
  158.             sqlprompt    => undef,
  159.             sqlterminator=> undef,
  160.             suffix        => undef,
  161.             tab            => undef,
  162.             termout        => undef,
  163.             'time'        => undef,
  164.             'timing'    => undef,
  165.             trimout        => undef,
  166.             trimspool    => undef,
  167.             'truncate'    => undef,
  168.             underline    => '-',
  169.             verify        => undef,
  170.             wrap        => undef,
  171.         },
  172.         # Each set command may call a custom function.  Included are
  173.         # currently defined sets.  For simple set/get, the value is
  174.         # stored set_current.
  175.         set_commands => {
  176.  
  177.             appinfo        => ['_unimp'],
  178.             arraysize    => ['_unimp'],
  179.             autocommit    => ['_unimp'],
  180.             autoprint    => ['_unimp'],
  181.             autorecovery    => ['_unimp'],
  182.             autotrace    => ['_unimp'],
  183.  
  184.             blockterminator    => ['_unimp'],
  185.             buffer        => ['_unimp'],
  186.  
  187.             closecursor    => ['_unimp'],
  188.             cmdsep        => ['_unimp'],
  189.             compatibility    => ['_unimp'],
  190.             concat        => ['_unimp'],
  191.             copycommit    => ['_unimp'],
  192.             copytypecheck    => ['_unimp'],
  193.  
  194.             define        => ['_unimp'],
  195.             document    => ['_unimp'],
  196.  
  197.             echo        => ['_set_get'],
  198.             editfile    => ['_unimp'],
  199.             embedded    => ['_unimp'],
  200.             escape        => ['_unimp'],
  201.  
  202.             feedback    => ['_unimp'],
  203.             flagger        => ['_unimp'],
  204.             flush        => ['_unimp'],
  205.  
  206.             heading     => ['_set_get'],
  207.             headsep     => ['_set_get'],
  208.  
  209.             instance     => ['_unimp'],
  210.  
  211.             linesize    => ['_set_get'],
  212.             limit        => ['_set_get'],
  213.             loboffset    => ['_unimp'],
  214.             logsource    => ['_unimp'],
  215.             long        => ['_unimp'],
  216.             longchunksize    => ['_unimp'],
  217.  
  218.             maxdata        => ['_unimp'],
  219.  
  220.             newpage        => ['_unimp'],
  221.             null        => ['_set_get'],
  222.             numwidth    => ['_unimp'],
  223.  
  224.             pagesize    => ['_set_get'],
  225.             pause        => ['_unimp'],
  226.  
  227.             recsep         => ['_set_get'],
  228.             recsepchar     => ['_set_get'],
  229.  
  230.             scan        => ['_print_buffer', 
  231.                 qq{obsolete command: use 'set define' instead}],
  232.             serveroutput    => ['_unimp'],
  233.             shiftinout    => ['_unimp'],
  234.             showmode    => ['_unimp'],
  235.             space        => ['_print_buffer', 
  236.                 qq{obsolete command: use 'set define' instead}],
  237.             sqlblanklines    => ['_unimp'],
  238.             sqlcase        => ['_unimp'],
  239.             sqlcontinue    => ['_unimp'],
  240.             sqlnumber    => ['_unimp'],
  241.             sqlprefix    => ['_unimp'],
  242.             sqlprompt    => ['_unimp'],
  243.             sqlterminator    => ['_unimp'],
  244.             suffix        => ['_unimp'],
  245.  
  246.             tab            => ['_unimp'],
  247.             termout        => ['_unimp'],
  248.             'time'        => ['_unimp'],
  249.             'timing'    => ['_unimp'],
  250.             trimout        => ['_unimp'],
  251.             trimspool    => ['_unimp'],
  252.             'truncate'    => ['_unimp'],
  253.  
  254.             underline    => ['_set_get'],
  255.  
  256.             verify        => ['_unimp'],
  257.  
  258.             wrap        => ['_unimp'],
  259.         },
  260.         show => {
  261.             all           => ['_all'],
  262.  
  263.             btitle        => ['_unimp'],
  264.  
  265.             catalogs      => ['_unimp'],
  266.             columns       => ['_unimp'],
  267.  
  268.             errors        => ['_unimp'],
  269.  
  270.             grants        => ['_unimp'],
  271.  
  272.             help          => ['_help'],
  273.             hints         => ['_hints'],
  274.  
  275.             lno           => ['_hints'],
  276.  
  277.             me            => ['_me'],
  278.  
  279.             objects       => ['_unimp'],
  280.  
  281.             packages      => ['_unimp'],
  282.             parameters    => ['_unimp'],
  283.             password      => ['_print_buffer', qq{I don\'t think so!}],
  284.             pno           => ['_unimp'],
  285.  
  286.             release       => ['_unimp'],
  287.             repfooter     => ['_unimp'],
  288.             repheader     => ['_unimp'],
  289.             roles         => ['_unimp'],
  290.  
  291.             schemas       => ['_schemas'],
  292.             sga           => ['_unimp'],
  293.             show          => ['_show_all_commands'],
  294.             spool         => ['_spool'],
  295.             sqlcode       => ['_sqlcode'],
  296.  
  297.             ttitle        => ['_unimp'],
  298.             tables        => ['_tables'],
  299.             types          => ['_types'],
  300.  
  301.             users         => ['_unimp'],
  302.  
  303.             views         => ['_views'],
  304.         },
  305.         sql => {
  306.             pno    => undef,
  307.             lno    => undef,
  308.             release    => undef,
  309.             user    => undef,
  310.         },
  311.     };
  312.  
  313.     my $pi = bless $sqlminus, $class;
  314.  
  315. # add the sqlminus object to the plugin list for reference later.
  316.     $sh->{plugin}->{sqlminus} = $pi;
  317.  
  318.     $pi->{dbh} = \$sh->{dbh};
  319.  
  320.     my $com_ref = $sh->{commands};
  321.  
  322.     foreach (sort keys %{$pi->{commands}}) {
  323.         $com_ref->{$_} = {
  324.             hint => "SQLMinus: $_",
  325.         };
  326.     }
  327.     return $pi;
  328. }
  329. #    'btittle' => {
  330. #        off => undef,
  331. #        on    => undef,
  332. #        col    => undef,
  333. #        skip    => undef,
  334. #        tab    => undef,
  335. #        left    => undef,
  336. #        center    => undef,
  337. #        right    => undef,
  338. #        bold    => undef,
  339. #        format    => undef,
  340. #        text    => undef,
  341. #        variable    => undef,
  342. #    },
  343. #
  344. # break.
  345. #
  346. # BRE[AK] [ON report_element [action [action]]] ...
  347. # where:
  348. # report_element
  349. # Requires the following syntax:
  350. # {column|expr|ROW|REPORT}
  351. # action
  352. # Requires the following syntax:
  353. # [SKI[P] n|[SKI[P]] PAGE][NODUP[LICATES]|DUP[LICATES]]
  354. sub do_break {
  355.     my ($self, $command, @args) = @_;
  356.  
  357.     # print "break command:\n";
  358.  
  359.     my $breaks = $self->{plugin}->{sqlminus}->{breaks};
  360.     my $cbreaks = $self->{plugin}->{sqlminus}->{break_current};
  361.  
  362.     unless( $command ) {
  363.         my $maxlen = 0;
  364.         foreach (keys %$cbreaks ) {
  365.             $maxlen = (length $_ > $maxlen? length $_ : $maxlen );
  366.         }
  367.         my $format = sprintf("%%-%ds", $maxlen );
  368.         foreach my $col_name (sort keys %$cbreaks) { 
  369.             $self->log( sprintf( $format, $col_name ));
  370.             foreach my $col (sort keys %$breaks) {
  371.                 next unless $cbreaks->{$col_name}->{$col};
  372.                 $self->print_buffer_nop(sprintf( "\t%-15s %s\n", $col, 
  373.                     ($cbreaks->{$col_name}->{$col}||'undef') ));
  374.             }
  375.         }
  376.         return;
  377.     }
  378.  
  379.     my @words = quotewords('\s+', 0, join( " ", @args));
  380.  
  381.     WORD:
  382.     while(@words) {
  383.         my $val = shift @words;
  384.  
  385.         if        ($val =~ m/row/i    ) {
  386.         } elsif    ($val =~ m/report/i    ) {
  387.         } elsif    ($val =~ m/on/i        ) { # Skip on
  388.             next WORD;
  389.         } else {
  390.             # Handle a column.
  391.             if (exists $cbreaks->{$val}) {
  392.                 delete $cbreaks->{$val};
  393.             }
  394.             $cbreaks->{$val} = {
  395.                   skip => undef
  396.                 , nodup => undef
  397.             }; # Create the column in the break group.
  398.  
  399.             ACTION:
  400.             while(@words) {
  401.                 my $action = shift @words;
  402.                 $self->print_buffer_nop( "actin $action" );
  403.                 last unless $action =~ m/\bskip|\bpage|\bnodup|\bdup/i;
  404.                 
  405. # These are the accepted action given to a break.
  406.                 if        ($action =~ m/\bskip/i    ) {
  407. # Skip consumes the next value, either page or a number.
  408.                     my $skip_val = shift @words if (@words);
  409.                     unless ($skip_val) {
  410.                         $self->print_buffer( 
  411.                             qq{break: action $action number lines|page} );
  412.                         last;
  413.                     }
  414.  
  415.                     $self->print_buffer_nop( "action $action $skip_val" );
  416.                     if ($skip_val =~ m/(\d+)/) {
  417.                         $cbreaks->{$val}->{skip} =  $skip_val;
  418.                         delete $cbreaks->{$val}->{skip_page} 
  419.                             if (exists $cbreaks->{$val}->{skip_page});
  420.                     } else {
  421.                         $cbreaks->{$val}->{skip_page} = 1;
  422.                         delete $cbreaks->{$val}->{skip} 
  423.                             if (exists $cbreaks->{$val}->{skip});
  424.                     }
  425. # Default value, if nodup/dup is not defined, add.
  426.                     unshift @words, 'nodup';
  427.                     unshift @words, 'nodup' unless (exists
  428.                         $cbreaks->{$val}->{dup} or exists
  429.                         $cbreaks->{$val}->{nodup});
  430.  
  431.                 } elsif ($action =~ m/\bnodup/i    ) {
  432.                     $cbreaks->{$val}->{nodup} =  1;
  433.                     delete $cbreaks->{$val}->{dup} 
  434.                             if (exists $cbreaks->{$val}->{dup});
  435.                 } elsif ($action =~ m/\bdup/i    ) {
  436.                     $cbreaks->{$val}->{dup} =  1;
  437.                     delete $cbreaks->{$val}->{nodup} 
  438.                             if (exists $cbreaks->{$val}->{nodup});
  439.                 } elsif ($action =~ m/\bpage/i    ) {
  440. # Put skip in front of the value and let the skip command handle it.
  441.                     unshift @words, 'skip', $action;
  442.                 } else {
  443.                     $self->print_buffer( 
  444.                         qq{break: action $action unknown, ambiguous, or not supported.} );
  445.                     last;
  446.                 }
  447.             }
  448.         }
  449.         return;
  450.     }
  451.  
  452.     return 
  453.     $self->print_buffer( 
  454.         qq{break: $command unknown, ambiguous, or not supported.} );
  455. }
  456.  
  457. #
  458. # set
  459. #
  460. sub do_set {
  461.     my ($self, $command, @args) = @_;
  462.  
  463.  
  464.     # print "set command:\n";
  465.  
  466.     my $set = $self->{plugin}->{sqlminus}->{set_current};
  467.  
  468.     unless( $command ) {
  469.         my $maxlen = 0;
  470.         foreach (keys %$set ) {
  471.             $maxlen = (length $_ > $maxlen? length $_ : $maxlen );
  472.         }
  473.         my $format = sprintf("%%-%ds %%s", $maxlen );
  474.         foreach (sort keys %$set) { 
  475.             $self->log( 
  476.                 sprintf( $format, $_, $set->{$_} || 'undef' )
  477.             );
  478.         }
  479.         return;
  480.     }
  481.  
  482.     my $options = Text::Abbrev::abbrev(keys %$set);
  483.  
  484.     my $ref = $self->{plugin}->{sqlminus};
  485.  
  486.     if (my $c = $options->{$command}) {
  487.         $self->log( "command: $command " . ref $c . "" );
  488.         if (my $c = $options->{$command}) {
  489.             my ($cmd, @cargs) = @{$ref->{set_commands}->{$c}};
  490.             push(@args, @cargs) if @cargs;
  491.             return $self->{plugin}->{sqlminus}->$cmd(\$self,$c,@args);
  492.         }
  493.     }
  494.     my %l;
  495.     foreach (keys %$options) { $l{$options->{$_}}++ if m/^$command/ }
  496.     my $sug = wrap( "\t(", "\t\t", sort keys %l );
  497.     $sug = "\n$sug)"    if defined $sug;
  498.     $sug = q{}            unless defined $sug;
  499. return 
  500.     $self->print_buffer( 
  501.         qq{set: $command unknown, ambiguous, or not supported.$sug} );
  502. }
  503.  
  504. # show
  505. sub do_show {
  506.     my ($self, $command, @args) = @_;
  507.  
  508.     return unless $command;
  509.  
  510.     my $show = $self->{plugin}->{sqlminus}->{show};
  511.     my $ref = $self->{plugin}->{sqlminus};
  512.  
  513.     my $options = Text::Abbrev::abbrev(keys %$show);
  514.     if (my $c = $options->{$command}) {
  515.         my ($cmd, @cargs) = @{$ref->{show}->{$c}};
  516.         push(@args, @cargs) if @cargs;
  517.         return $self->{plugin}->{sqlminus}->$cmd(\$self,@args);
  518.     }
  519.     my %l;
  520.     foreach (keys %$options) { $l{$options->{$_}}++ if m/^$command/ }
  521.     my $sug = wrap( "\t(", "\t\t", sort keys %l );
  522.     $sug = "\n$sug)"    if        defined $sug;
  523.     $sug = q{}            unless    defined $sug;  # rid warnings
  524. return 
  525.     $self->print_buffer( 
  526.         qq{show: $command unknown, ambiguous, or not supported.$sug} );
  527. }
  528.  
  529. #
  530. # Attempt to allow the user to define format string for query results.
  531. #
  532.  
  533.  
  534. sub do_column {
  535.     my ($self, $command, @args) = @_;
  536.  
  537.     # print "column command:\n" if $self->{debug};
  538.  
  539.     # my $set = $column_format;
  540.     my $ref                        = $self->{plugin}->{sqlminus};
  541.     my $column                    = $ref->{column};
  542.     my $column_format            = $ref->{column_format};
  543.     my $column_header_format    = $ref->{column_header_format};
  544.  
  545.     # If just the format command is issued, print all the current formatted
  546.     # columns.  Currently, only the column name is printed.
  547.     unless( $command ) {
  548.         my $maxlen = 0;
  549.         foreach (keys %$column_format ) {
  550.             $maxlen = (length $_ > $maxlen? length $_ : $maxlen );
  551.         }
  552.         my $format = sprintf("%%-%ds", $maxlen );
  553.         foreach my $col_name (sort keys %$column_format) { 
  554.             $self->log( sprintf( $format, $col_name ));
  555.             foreach my $col (sort keys %$column) {
  556.                 next unless $column_format->{$col_name}->{$col};
  557.                 $self->print_buffer_nop(sprintf( "\t%-15s %s\n", $col, 
  558.                     ($column_format->{$col_name}->{$col}||'undef') ));
  559.             }
  560.         }
  561.         return;
  562.     }
  563.  
  564.     if ( $command =~ m/clear/i ) {
  565.         # clear the format for either one or all columns.
  566.         if (@args) {
  567.             # Next argument column to clear.
  568.             my $f = shift @args;
  569.             # Format defined?
  570.             $self->_clear_format( \$column_format, $f );
  571.         } else {
  572.             # remove all column formats.
  573.  
  574.             foreach my $column (keys %$column_format) {
  575.                 # warn "Removing format for : $column :\n";
  576.                 $self->_clear_format( \$column_format, $column );
  577.             }
  578.  
  579.             # map { delete $column_format->{$_} } keys %$column_format 
  580.                 # if exists $ref->{column_format};
  581.             # map { delete $column_header_format->{$_} } 
  582.                 # keys %$column_header_format 
  583.                 # if exists $ref->{column_header_format};
  584.         }
  585.  
  586.     return $self->log( "format cleared" );
  587.     }
  588.  
  589.     #
  590.     # If column called with only a column name, display the current format.
  591.     #
  592.  
  593.     unless( @args ) {
  594.         return $self->log( "$command: no column format defined." ) 
  595.             unless exists $column_format->{$command};
  596.  
  597.         $self->log( "column $command format: " );
  598.         foreach my $col (sort keys %{$column_format->{$command}}) {
  599.             next unless $column_format->{$command}->{$col};
  600.             $self->print_buffer_nop(sprintf( "\t%-15s %s"
  601.                 , $col
  602.                 , ($column_format->{$command}->{$col}||'undef') ));
  603.         }
  604.         return;
  605.     }
  606.  
  607.     # print "column: $command ", join( " ", @args) , "\n" if $self->{debug};
  608.  
  609.     #
  610.     # column: column name.
  611.     #
  612.  
  613.     # Builds a structure of attributes supported in column formats.
  614.     my ($col, $col_head);
  615.     unless ( exists $column_format->{$command} ) {
  616.         my $struct = {};
  617.         foreach (keys %$column) {
  618.             $struct->{$_} = undef;
  619.         }
  620.         $column_format->{$command} = $struct;
  621.  
  622.         $col = $column_format->{$command};
  623.  
  624.         $col->{on} = 1;
  625.         $col->{off} = 0;
  626.     }
  627.  
  628.     $col = $column_format->{$command} unless $col;
  629.     $col_head = $column_header_format->{$command} unless $col_head;
  630.  
  631.  
  632.     my $options = Text::Abbrev::abbrev(keys %$column);
  633.  
  634.     # Handle quoted words or phrases.
  635.     my @words = quotewords('\s+', 0, join( " ", @args));
  636.  
  637.     print "column: $command ", join( " ", @words) , "\n" 
  638.         if $self->{debug};
  639.  
  640.     while(@words) {
  641.         my ( $text, $on, $off, $justify );
  642.         my $argv = shift @words;
  643.         my $c = exists $options->{$argv} ? $options->{$argv} : undef;
  644.         # determine if the current argument is part of the format
  645.         # string or a value.
  646.         if ($c) {
  647.             if    ( $c =~ m/alias/i ) {
  648.                 ########################################################
  649.                 # Alias
  650.                 ########################################################
  651.                 $col->{$c} = shift @words;
  652.                 $self->log( "setting alias ... $col->{$c} ..." ) 
  653.                     if $self->{debug};
  654.             } elsif ( $c =~ m/clear/i ) {
  655.                 ########################################################
  656.                 # Clear: syntax column column_name clear
  657.                 ########################################################
  658.                 $self->_clear_format( \$column_format, $command );
  659.                 return $self->log( "format cleared" );
  660.             } elsif ( $c =~ m/fold_after/i ) {
  661.                 ########################################################
  662.                 # Fold After
  663.                 ########################################################
  664.             } elsif ( $c =~ m/fold_before/i ) {
  665.                 ########################################################
  666.                 # Fold Before
  667.                 ########################################################
  668.             } elsif ( $c =~ m/format/i ) {
  669.                 ########################################################
  670.                 # Format
  671.                 ########################################################
  672.                 # Begin with format of A# strings, 9 numeric.
  673.                 my $f = shift @words;
  674.                 return $self->column_usage( {format => 'undef'} )
  675.                     unless $f;
  676.  
  677.                     $self->_determine_format( $f, \$col );
  678.  
  679.             } elsif ( $c =~ m/heading/i ) {
  680.                 ########################################################
  681.                 # Heading
  682.                 ########################################################
  683.                 $col->{$c} = shift @words;
  684.                 $self->log( "setting heading ... $col->{$c} ..." )
  685.                     if $self->{debug};
  686.             } elsif ( $c =~ m/justify/i ) {
  687.                 ########################################################
  688.                 # Justify
  689.                 ########################################################
  690.                 # unset current justification.
  691.                 my $f = shift @words;
  692.                 # Handle special conditions.
  693.                 if ($f =~ m/(?:of(?:f)?)/) {
  694.                     $col->{$c} = undef;
  695.                     $self->log( "justify cleared ... $f ..." ) if
  696.                         $self->{debug};
  697.                     next;
  698.                 }
  699.  
  700.                 $col->{$c} = undef;
  701.  
  702.                 foreach my $just (@{$column->{$c}}) {
  703.                     #$self->log( "\ttesting $f $just" ) if $self->{debug};
  704.                     if ($f =~ m/^($just)/i) {
  705.                         #$self->log( "\tmatch $f and $just" ) if $self->{debug};
  706.                         $col->{$c} = $1;
  707.                         last;
  708.                     }
  709.                 }
  710.                 return $self->log( "invalid justification $f" ) unless
  711.                     $col->{$c};
  712.                 $self->log( "setting justify ... $col->{$c}  $f ..." )
  713.                     if $self->{debug};
  714.             } elsif ( $c =~ m/like/i ) {
  715.                 ########################################################
  716.                 # Like
  717.                 ########################################################
  718.                 $col->{$c} = shift @words;
  719.             } elsif ( $c =~ m/newline/i ) {
  720.                 ########################################################
  721.                 # Newline
  722.                 ########################################################
  723.             } elsif ( $c =~ m/new_value/i ) {
  724.                 ########################################################
  725.                 # New Value
  726.                 ########################################################
  727.             } elsif ( $c =~ m/noprint/i ) {
  728.                 ########################################################
  729.                 # No Print
  730.                 ########################################################
  731.                 $col->{$c}        = 1;
  732.                 $col->{'print'}    = 0;
  733.                 $self->log( "setting noprint ... $col->{$c} ..." )
  734.                     if $self->{debug};
  735.             } elsif ( $c =~ m/print/i ) {
  736.                 ########################################################
  737.                 # Print
  738.                 ########################################################
  739.                 $col->{$c}            = 1;
  740.                 $col->{'noprint'}    = 0;
  741.                 $self->log( "setting print ... $col->{$c} ..." )
  742.                     if $self->{debug};
  743.             } elsif ( $c =~ m/null/i ) {
  744.                 ########################################################
  745.                 # Null
  746.                 ########################################################
  747.                 $col->{$c} = shift @words;
  748.                 $self->log( "setting null text ... $col->{$c} ..." )
  749.                     if $self->{debug};
  750.             } elsif ( $c =~ m/on/i ) {
  751.                 ########################################################
  752.                 # On
  753.                 ########################################################
  754.                 $col->{$c}            = 1;
  755.                 $col->{off}            = 0;
  756.                 $self->log( "setting format on ... $col->{$c} ..." )
  757.                     if $self->{debug};
  758.             } elsif ( $c =~ m/off/i ) {
  759.                 ########################################################
  760.                 # Off
  761.                 ########################################################
  762.                 $col->{$c}            = 1;
  763.                 $col->{on}            = 0;
  764.                 $self->log( "setting format off ... $col->{$c} ..." )
  765.                     if $self->{debug};
  766.             } elsif ( $c =~ m/truncated/i ) {
  767.                 ########################################################
  768.                 # Truncated
  769.                 ########################################################
  770.                 $col->{$c} = 1;
  771.                 $col->{'wrapped'} = 0;
  772.                 $self->log( "setting truncated ... $col->{$c} ..." )
  773.                     if $self->{debug};
  774.             } elsif ( $c =~ m/wordwrapped/i ) {
  775.                 ########################################################
  776.                 # Word Wrapped
  777.                 ########################################################
  778.                 $self->log( "setting wordwrapped ... $col->{$c} ..." )
  779.                     if $self->{debug};
  780.             } elsif ( $c =~ m/wrapped/i ) {
  781.                 ########################################################
  782.                 # Wrapped
  783.                 ########################################################
  784.                 $col->{$c} = 1;
  785.                 $col->{'truncated'} = 0;
  786.                 $self->log( "setting wrapped ... $col->{$c} ..." )
  787.                     if $self->{debug};
  788.             } else {
  789.                 ########################################################
  790.                 # Unknown
  791.                 ########################################################
  792.                 $self->log( "column unknown option: ... $c ..." )
  793.                     if $self->{debug};
  794.             }
  795.  
  796.         }
  797.     }
  798.     #
  799.     # At this point the format is defined for the current column, now build
  800.     # the format string.
  801.     #
  802.     {
  803.         # Default justify is left.
  804.         my $justify = '<';
  805.  
  806.         $self->log ("Truncated and Warpped both set for this column: $col->{name}" )
  807.             if (exists $col->{truncated}    and
  808.                 exists $col->{wrapped}        and
  809.                 $col->{truncated}            and 
  810.                 $col->{wrapped}
  811.             );
  812.  
  813.         $justify = '<' if defined $col->{truncated};
  814.         $justify = '[' if defined $col->{wrapped};
  815.  
  816.         if (defined $col->{'justify'}) {
  817.             if ($col->{'justify'} eq 'l') {
  818.                 $justify = 
  819.                     (defined $col->{wrapped} ? '[' : '<');
  820.             } elsif ( $col->{'justify'} eq 'r' ) {
  821.                 $justify =
  822.                     (defined $col->{wrapped} ? ']' : '>');
  823.             } elsif ( $col->{'justify'} eq 'c' ) {
  824.                 $justify = 
  825.                     (defined $col->{wrapped} ? '|' : '^');
  826.             } else {
  827.                 $self->log( "unknown justify $col->{'justify'}" )
  828.                     if $self->{debug};
  829.                 $justify = '<';
  830.             }
  831.         }
  832.  
  833.         # warn "build format for column: " . $command . "\n";
  834.  
  835.         unless (defined $col->{'length'}) {
  836.             $col->{'length'} = length $command;
  837.         }
  838.  
  839.         # Allow for head and column format differences.
  840.         $col_head->{'format'} = $justify x $col->{'length'};
  841.         $col->{'format'} = $justify x $col->{'length'};
  842.  
  843.         # foreach my $col (sort keys %{$column_format->{$command}}) {
  844.         #     next unless $column_format->{$command}->{$col};
  845.         #     printf( "\t%-15s %s\n", $col, ($column_format->{$command}->{$col}||'undef') );
  846.         # }
  847.  
  848.     }
  849.  
  850. return;
  851. }
  852.  
  853. sub column_usage {
  854.     my ($self, $error ) = @_;
  855.     return $self->print_buffer( 
  856.         join( " ",
  857.             qq{usage column:  },
  858.             (map { "$_ is $error->{$_}" } keys %$error ),
  859.         )
  860.     );
  861. }
  862.  
  863. sub _clear_format {
  864.     my ($self, $column_formats, $column) = @_;
  865.  
  866.     # warn "Removing format for : $column :\n";
  867.  
  868.     if (exists $$column_formats->{$column}) {
  869.         # Out of here!
  870.         delete $$column_formats->{$column};
  871.         # delete $$column_header_format->{$column};
  872.     } else {
  873.         # Can clear it, not defined.
  874.         $self->alert( "column clear $column: format not defined." );
  875.     }
  876.  
  877. }
  878.  
  879.  
  880. sub _determine_format {
  881.     my ($self, $format_requested, $mycol) = @_;
  882.  
  883.     my $col = ${$mycol};
  884.     my $numeric = ();
  885.  
  886.     # Determine what type of format?
  887.  
  888.     if ( $format_requested =~ m/a(\d+)/i ) {                # Character
  889.         $col->{'length'}    = $1;
  890.         $col->{'type'}        = 'char';
  891.         $col->{'format_function'} = undef;
  892.     } elsif ( $format_requested =~ m/^date$/ ) { # Date
  893.         $col->{'length'}    = 8;
  894.         $col->{'type'}        = 'date';
  895.         $col->{'format_function'} = undef;
  896.     } elsif ( $format_requested =~ m/(\d+)/ ) { # Numeric 9's
  897.         #       999.99 
  898.         # ^^^^^^^^^ ^^^^^
  899.         # PRECISION SCALE
  900.  
  901.         $col->{'format_function'} = undef;
  902.  
  903.         $col->{'type'}        = 'numeric';
  904.  
  905.         my $len = $format_requested        =~ tr /[0-9]/[0-9]/;
  906.         $len++ while($format_requested    =~ m/[BSVG\.\$]|MI/ig);
  907.         $len += $format_requested        =~ tr/,/,/;
  908.  
  909.         # Length is defined as total length of the formatted results.
  910.         $col->{'length'}    = $len;
  911.  
  912.         # Determine precision and scale:
  913.         my ($p,$s) = (0,0);
  914.         my ($p1,$s1) = split(/\./, $format_requested);
  915.         $p = $p1  =~ tr /[0-9]/[0-9]/ if $p1;
  916.         $s = $s1  =~ tr /[0-9]/[0-9]/ if $s1;
  917.  
  918.         # warn "$format_requested/precision($p)/scale($s)/length($len)\n";
  919.  
  920.         $col->{'precision'}    = $p;
  921.         $col->{'scale'}        = $s;
  922.  
  923.         # default the commify to NO.
  924.         $col->{'commify'} = 0;
  925.  
  926.         # $         $9999
  927.         if ($format_requested =~ m/\$/) {
  928.             # warn "adding function dollarsign\n";
  929.             $col->{'format_function'} = \&dollarsign;
  930.         }
  931.  
  932.         # B         B9999
  933.         $numeric->{B}++            if $format_requested =~ m/B/i;
  934.         # MI         9999MI
  935.         $numeric->{MI}++        if $format_requested =~ m/MI/i;
  936.         # S         S9999
  937.         $numeric->{S}++            if $format_requested =~ m/S/i;
  938.         # PR         9999PR
  939.         $numeric->{PR}++        if $format_requested =~ m/PR/i;
  940.         # D         99D99
  941.         $numeric->{D}++            if $format_requested =~ m/D/i;
  942.         # G            9G999
  943.         $numeric->{G}++            if $format_requested =~ m/G/i;
  944.         # C         C999
  945.         $numeric->{C}++            if $format_requested =~ m/C/i;
  946.         # L            L999
  947.         $numeric->{L}++            if $format_requested =~ m/L/i;
  948.         # . (period) 99.99
  949.         $numeric->{period}++    if $format_requested =~ m/\./;
  950.         # V         999V99
  951.         $numeric->{V}++            if $format_requested =~ m/V/i;
  952.         # EEEE         9.999EEEE
  953.         $numeric->{EEEE}++        if $format_requested =~ m/EEEE/i;
  954.  
  955.         # , (comma) 9,999
  956.         if ($format_requested =~ m/\,/) {
  957.                 $col->{'commify'} = 1;
  958.         }
  959.     } else {
  960.         return $self->column_usage( {format => "$format_requested invalid" });
  961.     }
  962.     # Save orignal format value.
  963.     $col->{'column_format'} = $format_requested;
  964.  
  965.     $self->log( "setting format ... $col->{'length'} $col->{'type'} ..." ) 
  966.         if $self->{debug};
  967.  
  968. return;
  969. }
  970.  
  971. # Document from Oracle 9i SQL*Plus reference.
  972. #
  973. # FOR[MAT] format
  974. # Specifies the display format of the column. The format specification
  975. # must be a text constant such as A10 or $9,999--not a variable.
  976. # Character Columns The default width of CHAR, NCHAR, VARCHAR2 (VARCHAR)
  977. # and NVARCHAR2 (NCHAR VARYING) columns is the width of the column in
  978. # the database. SQL*Plus formats these datatypes left-justified. If a
  979. # value does not fit within the column width, SQL*Plus wraps or
  980. # truncates the character string depending on the setting of SET WRAP.
  981. # A LONG, CLOB or NCLOB column's width defaults to the value of SET
  982. # LONGCHUNKSIZE or SET LONG, whichever one is smaller.
  983. # To change the width of a datatype to n, use FORMAT An. (A stands for
  984. # alphanumeric.) If you specify a width shorter than the column heading,
  985. # SQL*Plus truncates the heading. If you specify a width for a LONG,
  986. # CLOB, or NCLOB column, SQL*Plus uses the LONGCHUNKSIZE or the
  987. # specified width, whichever is smaller, as the column width.
  988. # DATE Columns The default width and format of unformatted DATE columns
  989. # in SQL*Plus is derived from the NLS parameters in effect. Otherwise,
  990. # the default width is A9. In Oracle9i, the NLS parameters may be set in
  991. # your database parameter file or may be environment variables or an
  992. # equivalent platform-specific mechanism. They may also be specified for
  993. # each session with the ALTER SESSION command. (See the documentation
  994. # for Oracle9i for a complete description of the NLS parameters).
  995. # You can change the format of any DATE column using the SQL function
  996. # TO_CHAR in your SQL SELECT statement. You may also wish to use an
  997. # explicit COLUMN FORMAT command to adjust the column width.
  998. # When you use SQL functions like TO_CHAR, Oracle automatically allows
  999. # for a very wide column.
  1000. # To change the width of a DATE column to n, use the COLUMN command with
  1001. # FORMAT An. If you specify a width shorter than the column heading, the
  1002. # heading is truncated.
  1003. # NUMBER Columns To change a NUMBER column's width, use FORMAT followed
  1004. # by an element as specified in Table 8-1.
  1005. # Table 8-1 Number Formats 
  1006. # Element  Examples  Description  
  1007. # 9            9999
  1008. #   Number of "9"s specifies number of significant digits returned.
  1009. #   Blanks are displayed for leading zeroes. A zero (0) is displayed for
  1010. #   a value of zero.
  1011. #  
  1012. # 0            0999 9990
  1013. #   Displays a leading zero or a value of zero in this position as 0. 
  1014. #  
  1015. # $         $9999
  1016. #   Prefixes value with dollar sign. 
  1017. #  
  1018. # B         B9999
  1019. #   Displays a zero value as blank, regardless of "0"s in the format model. 
  1020. #  
  1021. # MI         9999MI
  1022. #   Displays "-" after a negative value. For a positive value, a trailing space is displayed. 
  1023. #  
  1024. # S         S9999
  1025. #   Returns "+" for positive values and "-" for negative values in this position. 
  1026. #  
  1027. # PR         9999PR
  1028. #   Displays a negative value in <angle brackets>. For a positive value,
  1029. #   a leading and trailing space is displayed.
  1030. #  
  1031. # D         99D99
  1032. #   Displays the decimal character in this position, separating the
  1033. #   integral and fractional parts of a number.
  1034. #  
  1035. # G            9G999
  1036. #   Displays the group separator in this position.
  1037. #  
  1038. # C         C999
  1039. #   Displays the ISO currency symbol in this position. 
  1040. #  
  1041. # L            L999
  1042. #   Displays the local currency symbol in this position.
  1043. #  
  1044. # , (comma) 9,999
  1045. #   Displays a comma in this position. 
  1046. #  
  1047. # . (period) 99.99
  1048. #   Displays a period (decimal point) in this position, separating the
  1049. #   integral and fractional parts of a number.
  1050. #  
  1051. # V         999V99
  1052. #   Multiplies value by 10n, where n is number of "9"s after "V". 
  1053. #  
  1054. # EEEE         9.999EEEE
  1055. #   Displays value in scientific notation (format must contain exactly four "E"s). 
  1056. #  
  1057. # RN or rn     RN
  1058. #   Displays upper- or lowercase Roman numerals. Value can be an integer between 1 and 3999. 
  1059. #  
  1060. # DATE         DATE
  1061. #   Displays value as a date in MM/DD/YY format; used to format NUMBER
  1062. #   columns that represent Julian dates.
  1063. #  
  1064. #  
  1065. # The MI and PR format elements can only appear in the last position of
  1066. # a number format model. The S format element can only appear in the
  1067. # first or last position.
  1068. # If a number format model does not contain the MI, S or PR format
  1069. # elements, negative return values automatically contain a leading
  1070. # negative sign and positive values automatically contain a
  1071. # leading space.
  1072. # A number format model can contain only a single decimal character (D)
  1073. # or period (.), but it can contain multiple group separators (G) or
  1074. # commas (,). A group separator or comma cannot appear to the right of a
  1075. # decimal character or period in a number format model.
  1076. # SQL*Plus formats NUMBER data right-justified. A NUMBER column's width
  1077. # equals the width of the heading or the width of the FORMAT plus one
  1078. # space for the sign, whichever is greater. If you do not explicitly use
  1079. # FORMAT, then the column's width will always be at least the value of
  1080. # SET NUMWIDTH.
  1081. # SQL*Plus may round your NUMBER data to fit your format or field width.
  1082. # If a value cannot fit within the column width, SQL*Plus indicates
  1083. # overflow by displaying a pound sign (#) in place of each digit the
  1084. # width allows.
  1085. # If a positive value is extremely large and a numeric overflow occurs
  1086. # when rounding a number, then the infinity sign (~) replaces the value.
  1087. # Likewise, if a negative value is extremely small and a numeric
  1088. # overflow occurs when rounding a number, then the negative infinity
  1089. # sign replaces the value (-~).
  1090.  
  1091. # Commify used from the Perl CookBook
  1092. sub commify($) {
  1093.         my $num = reverse $_[0];
  1094.         $num =~ s/(\d\d\d)(?=\d)(?!\d*\.)/$1,/g;
  1095.         return scalar reverse $num;
  1096. }
  1097.  
  1098. sub dollarsign($$$$) {
  1099.         my ($num, $fmtnum, $dlen, $commify) = @_;
  1100.         my $formatted = sprintf "\$%${fmtnum}.${dlen}lf", $num;
  1101.         return ($commify ? commify($formatted) : $formatted);
  1102. }
  1103.  
  1104. sub zerofill($$$$) {
  1105.         my ($num, $fmtnum, $dlen, $commify) = @_;
  1106.         my $formatted = sprintf "%0${fmtnum}.${dlen}lf", $num;
  1107.         return ($commify ? commify($formatted) : $formatted);
  1108. }
  1109.  
  1110. sub signednum($$$$) {
  1111.         my ($num, $fmtnum, $dlen, $commify) = @_;
  1112.         my $formatted = sprintf "%+${fmtnum}.${dlen}lf", $num;
  1113.         return ($commify ? commify($formatted) : $formatted);
  1114. }
  1115.  
  1116. sub leadsign($$$$) {
  1117.         my ($num, $fmtnum, $dlen, $commify) = @_;
  1118.         my $formatted = sprintf "%+${fmtnum}.${dlen}lf", $num;
  1119.         return ($commify ? commify($formatted) : $formatted);
  1120. }
  1121.  
  1122. sub trailsign($$$$) {
  1123.         my ($num, $fmtnum, $dlen, $commify) = @_;
  1124.         $dlen--;
  1125.         my $formatted = sprintf "%${fmtnum}.${dlen}lf", abs($num);
  1126.         $formatted .= ($num > 0 ? '+' : '-');
  1127.         return ($commify ? commify($formatted) : $formatted);
  1128. }
  1129.  
  1130. sub ltgtsign($$$$) {
  1131.         my ($num, $fmtnum, $dlen, $commify) = @_;
  1132.         $dlen--;
  1133.         my $formatted = sprintf "%s%${fmtnum}.${dlen}lf%s" 
  1134.             ,($num > 0 ? '' : '<')
  1135.             ,abs($num),
  1136.             ,($num > 0 ? '' : '>');
  1137.         return ($commify ? commify($formatted) : $formatted);
  1138. }
  1139.  
  1140. #
  1141. # Private methods.
  1142. #
  1143.  
  1144. sub _me {
  1145.         my $pi   = shift;
  1146.         my $self = shift;
  1147.         return ${$self}->print_buffer("show me what???")
  1148.                 unless @_;
  1149.         return ${$self}->do_show(@_);
  1150. }
  1151.  
  1152. sub _all {
  1153.         my $pi = shift;
  1154.         my $self = shift;
  1155.         return ${$self}->print_buffer("show all of what???")
  1156.                 unless @_;
  1157.         return ${$self}->do_show(@_);
  1158. }
  1159.  
  1160. sub _show_all_commands {
  1161.         my $pi = shift;
  1162.         my $self = shift;
  1163. return
  1164.         ${$self}->print_buffer("Show supports the following commands:\n\t" .
  1165.                 join( "\n\t", keys %{$pi->{show}}));
  1166. }
  1167.  
  1168. sub _unimp {
  1169.         my $pi = shift;
  1170.         my $self = shift;
  1171.         return ${$self}->print_buffer("unimplemented");
  1172. }
  1173.  
  1174. sub _obsolete {
  1175.         my $pi = shift;
  1176.         my $self = shift;
  1177.         return ${$self}->print_buffer("obsolete: use " . join( " ", @_) );
  1178. }
  1179.  
  1180. sub _print_buffer {
  1181.         my $pi = shift;
  1182.         my $self = shift;
  1183.         return ${$self}->print_buffer(@_);
  1184. }
  1185.  
  1186. sub _set_get {
  1187.         my $pi = shift;
  1188.         my $self = shift;
  1189.         my $command = shift;
  1190.  
  1191.         carp "command undefined: " and return unless defined $command;
  1192.  
  1193. # Use the off to undefine/null a value.
  1194.         if (@_) {
  1195.                 my $val = shift;
  1196.                 if ($val =~ m/off/i) {
  1197.                     $pi->{set_current}->{$command} = undef;
  1198.                 } else {
  1199.                     $pi->{set_current}->{$command} = $val
  1200.                 }
  1201.  
  1202.         }
  1203.         ${$self}->print_buffer(
  1204.                         qq{$command: } .  ($pi->{set_current}->{$command}||
  1205.                         'null')
  1206.         );
  1207. return $pi->{set_current}->{$command};
  1208. }
  1209.  
  1210. #------------------------------------------------------------------
  1211. #
  1212. # Display a list of all schemas.
  1213. #
  1214. #------------------------------------------------------------------
  1215. sub _schemas {
  1216.         my ($pi, $sh, @args) = @_;
  1217.     #
  1218.     # Allow types to accept a list of types to display.
  1219.     #
  1220.     my $sth;
  1221.  
  1222.     my $dbh = ${$sh}->{dbh};
  1223.     $sth = $dbh->table_info('', '%', '', '');
  1224.  
  1225.     unless(ref $sth) {
  1226.         ${$sh}->log( "Advance table_info not supported\n");
  1227.         return;
  1228.     }
  1229.     return ${$sh}->sth_go($sth, 0, 0);
  1230. }
  1231.  
  1232. #------------------------------------------------------------------
  1233. #
  1234. # Display the last sql code, error, and error string.
  1235. #
  1236. #------------------------------------------------------------------
  1237. sub _sqlcode {
  1238.         my ($pi, $sh, @args) = @_;
  1239.  
  1240.     my $dbh = ${$sh}->{dbh};
  1241.  
  1242.     my $codes;
  1243.     
  1244.     $codes .= "last dbi error        : " . $dbh->err . "\n"        if $dbh->err;
  1245.     $codes .= "last dbi error string : " . $dbh->errstr . "\n"    if $dbh->err;
  1246.     $codes .= "last dbi error state  : " . $dbh->state    . "\n"    if $dbh->err;
  1247.  
  1248.     ${$sh}->print_buffer_nop( $codes ) if defined $codes;
  1249.  
  1250.     return $dbh->err||0;
  1251. }
  1252.  
  1253. #------------------------------------------------------------------
  1254. #
  1255. # Display a list of all tables.
  1256. #
  1257. #------------------------------------------------------------------
  1258. sub _tables {
  1259.         my ($pi, $sh, @args) = @_;
  1260.     return $pi->_sup_types( $sh, 'TABLE', @args );
  1261. }
  1262.  
  1263. #------------------------------------------------------------------
  1264. #
  1265. # Display a list of all types.
  1266. #
  1267. #------------------------------------------------------------------
  1268. sub _types {
  1269.         my ($pi, $sh, @args) = @_;
  1270.     #
  1271.     # Allow types to accept a list of types to display.
  1272.     #
  1273.     my $sth;
  1274.     if (@args) {
  1275.         return $pi->_sup_types( $sh, @args );
  1276.     } 
  1277.  
  1278.     my $dbh = ${$sh}->{dbh};
  1279.     $sth = $dbh->table_info('', '', '', '%');
  1280.  
  1281.     unless(ref $sth) {
  1282.         ${$sh}->log( "Advance table_info not supported\n" );
  1283.         return;
  1284.     }
  1285.     return ${$sh}->sth_go($sth, 0, 0);
  1286. }
  1287.  
  1288. #------------------------------------------------------------------
  1289. #
  1290. # Display a list of all views.
  1291. #
  1292. #------------------------------------------------------------------
  1293. sub _views {
  1294.         my ($pi, $sh, @args) = @_;
  1295.  
  1296.     return $pi->_sup_types( $sh, 'VIEW', @args );
  1297. }
  1298.  
  1299. #------------------------------------------------------------------
  1300. #
  1301. # Handle different types.
  1302. #
  1303. #------------------------------------------------------------------
  1304. sub _sup_types {
  1305.         my ($pi, $sh, $type, @args) = @_;
  1306.  
  1307.     $sh = ${$sh}; # Need to dereference the shell object.
  1308.  
  1309.     my $dbh = $sh->{dbh};
  1310.  
  1311.     return unless (defined $type);
  1312.  
  1313.     my $sth;
  1314.     if (@args) {
  1315.         my $tbl = join( ",", @args );
  1316.         $sth = $dbh->table_info(undef, undef, $tbl, $type);
  1317.     } else {
  1318.         $sth = $dbh->table_info(undef, undef, undef, $type);
  1319.     }
  1320.  
  1321.     unless (ref $sth) {
  1322.         ${$sh}->log( "Advance table_info not supported\n" );
  1323.         return;
  1324.     }
  1325.  
  1326.     return $sh->sth_go($sth, 0, 0);
  1327. }
  1328.  
  1329. 1;
  1330.  
  1331.  
  1332.