home *** CD-ROM | disk | FTP | other *** search
- #!perl -w
- # vim:ts=4:sw=4:aw:ai:nowrapscan
- #
- #
-
- package DBI::Shell::SQLMinus;
-
- use strict;
- use Text::Abbrev ();
- use Text::ParseWords;
- use Text::Wrap;
- use IO::File;
- use IO::Tee;
- use Carp;
-
- use vars qw(@ISA $show $set $VERSION);
-
- $VERSION = sprintf( "%d.%02d", q$Revision: 11.91 $ =~ /(\d+)\.(\d+)/ );
-
- sub init {
- my ($class, $sh, @args) = @_;
- $class = ref $class || $class;
- my $sqlminus = {
- archive => {
- log => undef,
- },
- 'breaks' => {
- skip => [ qw{text} ],
- skip_page => [ qw{text} ],
- dup => [ qw{text} ],
- nodup => [ qw{text} ],
- },
- break_current => {
- },
- 'clear' => {
- break => undef,
- buffer => undef,
- columns => undef,
- computes => undef,
- screen => undef,
- sql => undef,
- timing => undef,
- },
- db => undef,
- dbh => undef,
- column => {
- column_name => [ qw{text} ],
- alias => [ qw{text} ],
- clear => [ qw{command} ],
- fold_after => [ qw{text} ],
- fold_before => [ qw{text} ],
- format => [ qw{text} ],
- heading => [ qw{text} ],
- justify => [ qw{c l r f} ],
- like => [ qw{text} ],
- 'length' => [ qw{text} ],
- newline => [ qw{text} ],
- new_value => [ qw{text} ],
- noprint => [ qw{on off} ],
- 'print' => [ qw{on off} ],
- null => [ qw{text} ],
- on => 1,
- off => 0,
- truncated => [ qw{on off} ],
- type => [ qw{text} ],
- wordwrapped => [ qw{on off} ],
- wrapped => [ qw{on off} ],
- column_format => undef,
- format_function => undef,
- precision => undef,
- scale => undef,
- },
- # hash ref contains formats for code.
- column_format => {
- },
- # Hash ref contains the formats for the column headers.
- column_header_format => {
- },
- commands => {
- '@' => undef,
- 'accept'=> undef,
- append => undef,
- attribute => undef,
- break => undef,
- btitle => undef,
- change => undef,
- clear => undef,
- copy => undef,
- column => undef,
- compute => undef,
- define => undef,
- edit => undef,
- 'exec' => undef,
- get => undef,
- pause => undef,
- prompt => undef,
- repheader=> undef,
- repfooter=> undef,
- run => undef,
- save => undef,
- set => undef,
- show => undef,
- start => undef,
- ttitle => undef,
- undefine=> undef,
- },
- set_current => {
- appinfo => undef,
- arraysize => undef,
- autocommit => undef,
- autoprint => undef,
- autorecovery=> undef,
- autotrace => undef,
- blockterminator=> undef,
- buffer => undef,
- closecursor => undef,
- cmdsep => undef,
- compatibility=> undef,
- concat => undef,
- copycommit => undef,
- copytypecheck=> undef,
- define => undef,
- document => undef,
- echo => undef,
- editfile => undef,
- embedded => undef,
- escape => undef,
- feedback => undef,
- flagger => undef,
- flush => undef,
- heading => 1,
- headsep => ' ',
- instance => undef,
- linesize => 72,
- limit => undef,
- loboffset => undef,
- logsource => undef,
- long => undef,
- longchunksize => undef,
- maxdata => undef,
- newpage => undef,
- null => undef,
- numwidth => undef,
- pagesize => undef,
- pause => undef,
- recsep => 1,
- recsepchar => ' ',
- scan => qq{obsolete command: use 'set define' instead},
- serveroutput=> undef,
- shiftinout => undef,
- showmode => undef,
- space => qq{obsolete command: use 'set define' instead},
- sqlblanklines=> undef,
- sqlcase => undef,
- sqlcontinue => undef,
- sqlnumber => undef,
- sqlprefix => undef,
- sqlprompt => undef,
- sqlterminator=> undef,
- suffix => undef,
- tab => undef,
- termout => undef,
- 'time' => undef,
- 'timing' => undef,
- trimout => undef,
- trimspool => undef,
- 'truncate' => undef,
- underline => '-',
- verify => undef,
- wrap => undef,
- },
- # Each set command may call a custom function. Included are
- # currently defined sets. For simple set/get, the value is
- # stored set_current.
- set_commands => {
-
- appinfo => ['_unimp'],
- arraysize => ['_unimp'],
- autocommit => ['_unimp'],
- autoprint => ['_unimp'],
- autorecovery => ['_unimp'],
- autotrace => ['_unimp'],
-
- blockterminator => ['_unimp'],
- buffer => ['_unimp'],
-
- closecursor => ['_unimp'],
- cmdsep => ['_unimp'],
- compatibility => ['_unimp'],
- concat => ['_unimp'],
- copycommit => ['_unimp'],
- copytypecheck => ['_unimp'],
-
- define => ['_unimp'],
- document => ['_unimp'],
-
- echo => ['_set_get'],
- editfile => ['_unimp'],
- embedded => ['_unimp'],
- escape => ['_unimp'],
-
- feedback => ['_unimp'],
- flagger => ['_unimp'],
- flush => ['_unimp'],
-
- heading => ['_set_get'],
- headsep => ['_set_get'],
-
- instance => ['_unimp'],
-
- linesize => ['_set_get'],
- limit => ['_set_get'],
- loboffset => ['_unimp'],
- logsource => ['_unimp'],
- long => ['_unimp'],
- longchunksize => ['_unimp'],
-
- maxdata => ['_unimp'],
-
- newpage => ['_unimp'],
- null => ['_set_get'],
- numwidth => ['_unimp'],
-
- pagesize => ['_set_get'],
- pause => ['_unimp'],
-
- recsep => ['_set_get'],
- recsepchar => ['_set_get'],
-
- scan => ['_print_buffer',
- qq{obsolete command: use 'set define' instead}],
- serveroutput => ['_unimp'],
- shiftinout => ['_unimp'],
- showmode => ['_unimp'],
- space => ['_print_buffer',
- qq{obsolete command: use 'set define' instead}],
- sqlblanklines => ['_unimp'],
- sqlcase => ['_unimp'],
- sqlcontinue => ['_unimp'],
- sqlnumber => ['_unimp'],
- sqlprefix => ['_unimp'],
- sqlprompt => ['_unimp'],
- sqlterminator => ['_unimp'],
- suffix => ['_unimp'],
-
- tab => ['_unimp'],
- termout => ['_unimp'],
- 'time' => ['_unimp'],
- 'timing' => ['_unimp'],
- trimout => ['_unimp'],
- trimspool => ['_unimp'],
- 'truncate' => ['_unimp'],
-
- underline => ['_set_get'],
-
- verify => ['_unimp'],
-
- wrap => ['_unimp'],
- },
- show => {
- all => ['_all'],
-
- btitle => ['_unimp'],
-
- catalogs => ['_unimp'],
- columns => ['_unimp'],
-
- errors => ['_unimp'],
-
- grants => ['_unimp'],
-
- help => ['_help'],
- hints => ['_hints'],
-
- lno => ['_hints'],
-
- me => ['_me'],
-
- objects => ['_unimp'],
-
- packages => ['_unimp'],
- parameters => ['_unimp'],
- password => ['_print_buffer', qq{I don\'t think so!}],
- pno => ['_unimp'],
-
- release => ['_unimp'],
- repfooter => ['_unimp'],
- repheader => ['_unimp'],
- roles => ['_unimp'],
-
- schemas => ['_schemas'],
- sga => ['_unimp'],
- show => ['_show_all_commands'],
- spool => ['_spool'],
- sqlcode => ['_sqlcode'],
-
- ttitle => ['_unimp'],
- tables => ['_tables'],
- types => ['_types'],
-
- users => ['_unimp'],
-
- views => ['_views'],
- },
- sql => {
- pno => undef,
- lno => undef,
- release => undef,
- user => undef,
- },
- };
-
- my $pi = bless $sqlminus, $class;
-
- # add the sqlminus object to the plugin list for reference later.
- $sh->{plugin}->{sqlminus} = $pi;
-
- $pi->{dbh} = \$sh->{dbh};
-
- my $com_ref = $sh->{commands};
-
- foreach (sort keys %{$pi->{commands}}) {
- $com_ref->{$_} = {
- hint => "SQLMinus: $_",
- };
- }
- return $pi;
- }
- # 'btittle' => {
- # off => undef,
- # on => undef,
- # col => undef,
- # skip => undef,
- # tab => undef,
- # left => undef,
- # center => undef,
- # right => undef,
- # bold => undef,
- # format => undef,
- # text => undef,
- # variable => undef,
- # },
- #
- # break.
- #
- # BRE[AK] [ON report_element [action [action]]] ...
- #
- # where:
- #
- # report_element
- #
- # Requires the following syntax:
- #
- # {column|expr|ROW|REPORT}
- #
- # action
- #
- # Requires the following syntax:
- #
- # [SKI[P] n|[SKI[P]] PAGE][NODUP[LICATES]|DUP[LICATES]]
- #
- sub do_break {
- my ($self, $command, @args) = @_;
-
- # print "break command:\n";
-
- my $breaks = $self->{plugin}->{sqlminus}->{breaks};
- my $cbreaks = $self->{plugin}->{sqlminus}->{break_current};
-
- unless( $command ) {
- my $maxlen = 0;
- foreach (keys %$cbreaks ) {
- $maxlen = (length $_ > $maxlen? length $_ : $maxlen );
- }
- my $format = sprintf("%%-%ds", $maxlen );
- foreach my $col_name (sort keys %$cbreaks) {
- $self->log( sprintf( $format, $col_name ));
- foreach my $col (sort keys %$breaks) {
- next unless $cbreaks->{$col_name}->{$col};
- $self->print_buffer_nop(sprintf( "\t%-15s %s\n", $col,
- ($cbreaks->{$col_name}->{$col}||'undef') ));
- }
- }
- return;
- }
-
- my @words = quotewords('\s+', 0, join( " ", @args));
-
- WORD:
- while(@words) {
- my $val = shift @words;
-
- if ($val =~ m/row/i ) {
- } elsif ($val =~ m/report/i ) {
- } elsif ($val =~ m/on/i ) { # Skip on
- next WORD;
- } else {
- # Handle a column.
- if (exists $cbreaks->{$val}) {
- delete $cbreaks->{$val};
- }
- $cbreaks->{$val} = {
- skip => undef
- , nodup => undef
- }; # Create the column in the break group.
-
- ACTION:
- while(@words) {
- my $action = shift @words;
- $self->print_buffer_nop( "actin $action" );
- last unless $action =~ m/\bskip|\bpage|\bnodup|\bdup/i;
-
- # These are the accepted action given to a break.
- if ($action =~ m/\bskip/i ) {
- # Skip consumes the next value, either page or a number.
- my $skip_val = shift @words if (@words);
- unless ($skip_val) {
- $self->print_buffer(
- qq{break: action $action number lines|page} );
- last;
- }
-
- $self->print_buffer_nop( "action $action $skip_val" );
- if ($skip_val =~ m/(\d+)/) {
- $cbreaks->{$val}->{skip} = $skip_val;
- delete $cbreaks->{$val}->{skip_page}
- if (exists $cbreaks->{$val}->{skip_page});
- } else {
- $cbreaks->{$val}->{skip_page} = 1;
- delete $cbreaks->{$val}->{skip}
- if (exists $cbreaks->{$val}->{skip});
- }
- # Default value, if nodup/dup is not defined, add.
- unshift @words, 'nodup';
- unshift @words, 'nodup' unless (exists
- $cbreaks->{$val}->{dup} or exists
- $cbreaks->{$val}->{nodup});
-
- } elsif ($action =~ m/\bnodup/i ) {
- $cbreaks->{$val}->{nodup} = 1;
- delete $cbreaks->{$val}->{dup}
- if (exists $cbreaks->{$val}->{dup});
- } elsif ($action =~ m/\bdup/i ) {
- $cbreaks->{$val}->{dup} = 1;
- delete $cbreaks->{$val}->{nodup}
- if (exists $cbreaks->{$val}->{nodup});
- } elsif ($action =~ m/\bpage/i ) {
- # Put skip in front of the value and let the skip command handle it.
- unshift @words, 'skip', $action;
- } else {
- $self->print_buffer(
- qq{break: action $action unknown, ambiguous, or not supported.} );
- last;
- }
- }
- }
- return;
- }
-
- return
- $self->print_buffer(
- qq{break: $command unknown, ambiguous, or not supported.} );
- }
-
- #
- # set
- #
- sub do_set {
- my ($self, $command, @args) = @_;
-
-
- # print "set command:\n";
-
- my $set = $self->{plugin}->{sqlminus}->{set_current};
-
- unless( $command ) {
- my $maxlen = 0;
- foreach (keys %$set ) {
- $maxlen = (length $_ > $maxlen? length $_ : $maxlen );
- }
- my $format = sprintf("%%-%ds %%s", $maxlen );
- foreach (sort keys %$set) {
- $self->log(
- sprintf( $format, $_, $set->{$_} || 'undef' )
- );
- }
- return;
- }
-
- my $options = Text::Abbrev::abbrev(keys %$set);
-
- my $ref = $self->{plugin}->{sqlminus};
-
- if (my $c = $options->{$command}) {
- $self->log( "command: $command " . ref $c . "" );
- if (my $c = $options->{$command}) {
- my ($cmd, @cargs) = @{$ref->{set_commands}->{$c}};
- push(@args, @cargs) if @cargs;
- return $self->{plugin}->{sqlminus}->$cmd(\$self,$c,@args);
- }
- }
- my %l;
- foreach (keys %$options) { $l{$options->{$_}}++ if m/^$command/ }
- my $sug = wrap( "\t(", "\t\t", sort keys %l );
- $sug = "\n$sug)" if defined $sug;
- $sug = q{} unless defined $sug;
- return
- $self->print_buffer(
- qq{set: $command unknown, ambiguous, or not supported.$sug} );
- }
-
- # show
- sub do_show {
- my ($self, $command, @args) = @_;
-
- return unless $command;
-
- my $show = $self->{plugin}->{sqlminus}->{show};
- my $ref = $self->{plugin}->{sqlminus};
-
- my $options = Text::Abbrev::abbrev(keys %$show);
- if (my $c = $options->{$command}) {
- my ($cmd, @cargs) = @{$ref->{show}->{$c}};
- push(@args, @cargs) if @cargs;
- return $self->{plugin}->{sqlminus}->$cmd(\$self,@args);
- }
- my %l;
- foreach (keys %$options) { $l{$options->{$_}}++ if m/^$command/ }
- my $sug = wrap( "\t(", "\t\t", sort keys %l );
- $sug = "\n$sug)" if defined $sug;
- $sug = q{} unless defined $sug; # rid warnings
- return
- $self->print_buffer(
- qq{show: $command unknown, ambiguous, or not supported.$sug} );
- }
-
- #
- # Attempt to allow the user to define format string for query results.
- #
-
-
- sub do_column {
- my ($self, $command, @args) = @_;
-
- # print "column command:\n" if $self->{debug};
-
- # my $set = $column_format;
- my $ref = $self->{plugin}->{sqlminus};
- my $column = $ref->{column};
- my $column_format = $ref->{column_format};
- my $column_header_format = $ref->{column_header_format};
-
- # If just the format command is issued, print all the current formatted
- # columns. Currently, only the column name is printed.
- unless( $command ) {
- my $maxlen = 0;
- foreach (keys %$column_format ) {
- $maxlen = (length $_ > $maxlen? length $_ : $maxlen );
- }
- my $format = sprintf("%%-%ds", $maxlen );
- foreach my $col_name (sort keys %$column_format) {
- $self->log( sprintf( $format, $col_name ));
- foreach my $col (sort keys %$column) {
- next unless $column_format->{$col_name}->{$col};
- $self->print_buffer_nop(sprintf( "\t%-15s %s\n", $col,
- ($column_format->{$col_name}->{$col}||'undef') ));
- }
- }
- return;
- }
-
- if ( $command =~ m/clear/i ) {
- # clear the format for either one or all columns.
- if (@args) {
- # Next argument column to clear.
- my $f = shift @args;
- # Format defined?
- $self->_clear_format( \$column_format, $f );
- } else {
- # remove all column formats.
-
- foreach my $column (keys %$column_format) {
- # warn "Removing format for : $column :\n";
- $self->_clear_format( \$column_format, $column );
- }
-
- # map { delete $column_format->{$_} } keys %$column_format
- # if exists $ref->{column_format};
- # map { delete $column_header_format->{$_} }
- # keys %$column_header_format
- # if exists $ref->{column_header_format};
- }
-
- return $self->log( "format cleared" );
- }
-
- #
- # If column called with only a column name, display the current format.
- #
-
- unless( @args ) {
- return $self->log( "$command: no column format defined." )
- unless exists $column_format->{$command};
-
- $self->log( "column $command format: " );
- foreach my $col (sort keys %{$column_format->{$command}}) {
- next unless $column_format->{$command}->{$col};
- $self->print_buffer_nop(sprintf( "\t%-15s %s"
- , $col
- , ($column_format->{$command}->{$col}||'undef') ));
- }
- return;
- }
-
- # print "column: $command ", join( " ", @args) , "\n" if $self->{debug};
-
- #
- # column: column name.
- #
-
- # Builds a structure of attributes supported in column formats.
- my ($col, $col_head);
- unless ( exists $column_format->{$command} ) {
- my $struct = {};
- foreach (keys %$column) {
- $struct->{$_} = undef;
- }
- $column_format->{$command} = $struct;
-
- $col = $column_format->{$command};
-
- $col->{on} = 1;
- $col->{off} = 0;
- }
-
- $col = $column_format->{$command} unless $col;
- $col_head = $column_header_format->{$command} unless $col_head;
-
-
- my $options = Text::Abbrev::abbrev(keys %$column);
-
- # Handle quoted words or phrases.
- my @words = quotewords('\s+', 0, join( " ", @args));
-
- print "column: $command ", join( " ", @words) , "\n"
- if $self->{debug};
-
- while(@words) {
- my ( $text, $on, $off, $justify );
- my $argv = shift @words;
- my $c = exists $options->{$argv} ? $options->{$argv} : undef;
- # determine if the current argument is part of the format
- # string or a value.
- if ($c) {
- if ( $c =~ m/alias/i ) {
- ########################################################
- # Alias
- ########################################################
- $col->{$c} = shift @words;
- $self->log( "setting alias ... $col->{$c} ..." )
- if $self->{debug};
- } elsif ( $c =~ m/clear/i ) {
- ########################################################
- # Clear: syntax column column_name clear
- ########################################################
- $self->_clear_format( \$column_format, $command );
- return $self->log( "format cleared" );
- } elsif ( $c =~ m/fold_after/i ) {
- ########################################################
- # Fold After
- ########################################################
- } elsif ( $c =~ m/fold_before/i ) {
- ########################################################
- # Fold Before
- ########################################################
- } elsif ( $c =~ m/format/i ) {
- ########################################################
- # Format
- ########################################################
- # Begin with format of A# strings, 9 numeric.
- my $f = shift @words;
- return $self->column_usage( {format => 'undef'} )
- unless $f;
-
- $self->_determine_format( $f, \$col );
-
- } elsif ( $c =~ m/heading/i ) {
- ########################################################
- # Heading
- ########################################################
- $col->{$c} = shift @words;
- $self->log( "setting heading ... $col->{$c} ..." )
- if $self->{debug};
- } elsif ( $c =~ m/justify/i ) {
- ########################################################
- # Justify
- ########################################################
- # unset current justification.
- my $f = shift @words;
- # Handle special conditions.
- if ($f =~ m/(?:of(?:f)?)/) {
- $col->{$c} = undef;
- $self->log( "justify cleared ... $f ..." ) if
- $self->{debug};
- next;
- }
-
- $col->{$c} = undef;
-
- foreach my $just (@{$column->{$c}}) {
- #$self->log( "\ttesting $f $just" ) if $self->{debug};
- if ($f =~ m/^($just)/i) {
- #$self->log( "\tmatch $f and $just" ) if $self->{debug};
- $col->{$c} = $1;
- last;
- }
- }
- return $self->log( "invalid justification $f" ) unless
- $col->{$c};
- $self->log( "setting justify ... $col->{$c} $f ..." )
- if $self->{debug};
- } elsif ( $c =~ m/like/i ) {
- ########################################################
- # Like
- ########################################################
- $col->{$c} = shift @words;
- } elsif ( $c =~ m/newline/i ) {
- ########################################################
- # Newline
- ########################################################
- } elsif ( $c =~ m/new_value/i ) {
- ########################################################
- # New Value
- ########################################################
- } elsif ( $c =~ m/noprint/i ) {
- ########################################################
- # No Print
- ########################################################
- $col->{$c} = 1;
- $col->{'print'} = 0;
- $self->log( "setting noprint ... $col->{$c} ..." )
- if $self->{debug};
- } elsif ( $c =~ m/print/i ) {
- ########################################################
- # Print
- ########################################################
- $col->{$c} = 1;
- $col->{'noprint'} = 0;
- $self->log( "setting print ... $col->{$c} ..." )
- if $self->{debug};
- } elsif ( $c =~ m/null/i ) {
- ########################################################
- # Null
- ########################################################
- $col->{$c} = shift @words;
- $self->log( "setting null text ... $col->{$c} ..." )
- if $self->{debug};
- } elsif ( $c =~ m/on/i ) {
- ########################################################
- # On
- ########################################################
- $col->{$c} = 1;
- $col->{off} = 0;
- $self->log( "setting format on ... $col->{$c} ..." )
- if $self->{debug};
- } elsif ( $c =~ m/off/i ) {
- ########################################################
- # Off
- ########################################################
- $col->{$c} = 1;
- $col->{on} = 0;
- $self->log( "setting format off ... $col->{$c} ..." )
- if $self->{debug};
- } elsif ( $c =~ m/truncated/i ) {
- ########################################################
- # Truncated
- ########################################################
- $col->{$c} = 1;
- $col->{'wrapped'} = 0;
- $self->log( "setting truncated ... $col->{$c} ..." )
- if $self->{debug};
- } elsif ( $c =~ m/wordwrapped/i ) {
- ########################################################
- # Word Wrapped
- ########################################################
- $self->log( "setting wordwrapped ... $col->{$c} ..." )
- if $self->{debug};
- } elsif ( $c =~ m/wrapped/i ) {
- ########################################################
- # Wrapped
- ########################################################
- $col->{$c} = 1;
- $col->{'truncated'} = 0;
- $self->log( "setting wrapped ... $col->{$c} ..." )
- if $self->{debug};
- } else {
- ########################################################
- # Unknown
- ########################################################
- $self->log( "column unknown option: ... $c ..." )
- if $self->{debug};
- }
-
- }
- }
- #
- # At this point the format is defined for the current column, now build
- # the format string.
- #
- {
- # Default justify is left.
- my $justify = '<';
-
- $self->log ("Truncated and Warpped both set for this column: $col->{name}" )
- if (exists $col->{truncated} and
- exists $col->{wrapped} and
- $col->{truncated} and
- $col->{wrapped}
- );
-
- $justify = '<' if defined $col->{truncated};
- $justify = '[' if defined $col->{wrapped};
-
- if (defined $col->{'justify'}) {
- if ($col->{'justify'} eq 'l') {
- $justify =
- (defined $col->{wrapped} ? '[' : '<');
- } elsif ( $col->{'justify'} eq 'r' ) {
- $justify =
- (defined $col->{wrapped} ? ']' : '>');
- } elsif ( $col->{'justify'} eq 'c' ) {
- $justify =
- (defined $col->{wrapped} ? '|' : '^');
- } else {
- $self->log( "unknown justify $col->{'justify'}" )
- if $self->{debug};
- $justify = '<';
- }
- }
-
- # warn "build format for column: " . $command . "\n";
-
- unless (defined $col->{'length'}) {
- $col->{'length'} = length $command;
- }
-
- # Allow for head and column format differences.
- $col_head->{'format'} = $justify x $col->{'length'};
- $col->{'format'} = $justify x $col->{'length'};
-
- # foreach my $col (sort keys %{$column_format->{$command}}) {
- # next unless $column_format->{$command}->{$col};
- # printf( "\t%-15s %s\n", $col, ($column_format->{$command}->{$col}||'undef') );
- # }
-
- }
-
- return;
- }
-
- sub column_usage {
- my ($self, $error ) = @_;
- return $self->print_buffer(
- join( " ",
- qq{usage column: },
- (map { "$_ is $error->{$_}" } keys %$error ),
- )
- );
- }
-
- sub _clear_format {
- my ($self, $column_formats, $column) = @_;
-
- # warn "Removing format for : $column :\n";
-
- if (exists $$column_formats->{$column}) {
- # Out of here!
- delete $$column_formats->{$column};
- # delete $$column_header_format->{$column};
- } else {
- # Can clear it, not defined.
- $self->alert( "column clear $column: format not defined." );
- }
-
- }
-
-
- sub _determine_format {
- my ($self, $format_requested, $mycol) = @_;
-
- my $col = ${$mycol};
- my $numeric = ();
-
- # Determine what type of format?
-
- if ( $format_requested =~ m/a(\d+)/i ) { # Character
- $col->{'length'} = $1;
- $col->{'type'} = 'char';
- $col->{'format_function'} = undef;
- } elsif ( $format_requested =~ m/^date$/ ) { # Date
- $col->{'length'} = 8;
- $col->{'type'} = 'date';
- $col->{'format_function'} = undef;
- } elsif ( $format_requested =~ m/(\d+)/ ) { # Numeric 9's
- # 999.99
- # ^^^^^^^^^ ^^^^^
- # PRECISION SCALE
-
- $col->{'format_function'} = undef;
-
- $col->{'type'} = 'numeric';
-
- my $len = $format_requested =~ tr /[0-9]/[0-9]/;
- $len++ while($format_requested =~ m/[BSVG\.\$]|MI/ig);
- $len += $format_requested =~ tr/,/,/;
-
- # Length is defined as total length of the formatted results.
- $col->{'length'} = $len;
-
- # Determine precision and scale:
- my ($p,$s) = (0,0);
- my ($p1,$s1) = split(/\./, $format_requested);
- $p = $p1 =~ tr /[0-9]/[0-9]/ if $p1;
- $s = $s1 =~ tr /[0-9]/[0-9]/ if $s1;
-
- # warn "$format_requested/precision($p)/scale($s)/length($len)\n";
-
- $col->{'precision'} = $p;
- $col->{'scale'} = $s;
-
- # default the commify to NO.
- $col->{'commify'} = 0;
-
- # $ $9999
- if ($format_requested =~ m/\$/) {
- # warn "adding function dollarsign\n";
- $col->{'format_function'} = \&dollarsign;
- }
-
- # B B9999
- $numeric->{B}++ if $format_requested =~ m/B/i;
- # MI 9999MI
- $numeric->{MI}++ if $format_requested =~ m/MI/i;
- # S S9999
- $numeric->{S}++ if $format_requested =~ m/S/i;
- # PR 9999PR
- $numeric->{PR}++ if $format_requested =~ m/PR/i;
- # D 99D99
- $numeric->{D}++ if $format_requested =~ m/D/i;
- # G 9G999
- $numeric->{G}++ if $format_requested =~ m/G/i;
- # C C999
- $numeric->{C}++ if $format_requested =~ m/C/i;
- # L L999
- $numeric->{L}++ if $format_requested =~ m/L/i;
- # . (period) 99.99
- $numeric->{period}++ if $format_requested =~ m/\./;
- # V 999V99
- $numeric->{V}++ if $format_requested =~ m/V/i;
- # EEEE 9.999EEEE
- $numeric->{EEEE}++ if $format_requested =~ m/EEEE/i;
-
- # , (comma) 9,999
- if ($format_requested =~ m/\,/) {
- $col->{'commify'} = 1;
- }
- } else {
- return $self->column_usage( {format => "$format_requested invalid" });
- }
- # Save orignal format value.
- $col->{'column_format'} = $format_requested;
-
- $self->log( "setting format ... $col->{'length'} $col->{'type'} ..." )
- if $self->{debug};
-
- return;
- }
-
- # Document from Oracle 9i SQL*Plus reference.
- #
- # FOR[MAT] format
- #
- # Specifies the display format of the column. The format specification
- # must be a text constant such as A10 or $9,999--not a variable.
- #
- # Character Columns The default width of CHAR, NCHAR, VARCHAR2 (VARCHAR)
- # and NVARCHAR2 (NCHAR VARYING) columns is the width of the column in
- # the database. SQL*Plus formats these datatypes left-justified. If a
- # value does not fit within the column width, SQL*Plus wraps or
- # truncates the character string depending on the setting of SET WRAP.
- #
- # A LONG, CLOB or NCLOB column's width defaults to the value of SET
- # LONGCHUNKSIZE or SET LONG, whichever one is smaller.
- #
- # To change the width of a datatype to n, use FORMAT An. (A stands for
- # alphanumeric.) If you specify a width shorter than the column heading,
- # SQL*Plus truncates the heading. If you specify a width for a LONG,
- # CLOB, or NCLOB column, SQL*Plus uses the LONGCHUNKSIZE or the
- # specified width, whichever is smaller, as the column width.
- #
- # DATE Columns The default width and format of unformatted DATE columns
- # in SQL*Plus is derived from the NLS parameters in effect. Otherwise,
- # the default width is A9. In Oracle9i, the NLS parameters may be set in
- # your database parameter file or may be environment variables or an
- # equivalent platform-specific mechanism. They may also be specified for
- # each session with the ALTER SESSION command. (See the documentation
- # for Oracle9i for a complete description of the NLS parameters).
- #
- # You can change the format of any DATE column using the SQL function
- # TO_CHAR in your SQL SELECT statement. You may also wish to use an
- # explicit COLUMN FORMAT command to adjust the column width.
- #
- # When you use SQL functions like TO_CHAR, Oracle automatically allows
- # for a very wide column.
- #
- # To change the width of a DATE column to n, use the COLUMN command with
- # FORMAT An. If you specify a width shorter than the column heading, the
- # heading is truncated.
- #
- # NUMBER Columns To change a NUMBER column's width, use FORMAT followed
- # by an element as specified in Table 8-1.
- #
- # Table 8-1 Number Formats
- # Element Examples Description
- # 9 9999
- #
- # Number of "9"s specifies number of significant digits returned.
- # Blanks are displayed for leading zeroes. A zero (0) is displayed for
- # a value of zero.
- #
- # 0 0999 9990
- #
- # Displays a leading zero or a value of zero in this position as 0.
- #
- # $ $9999
- #
- # Prefixes value with dollar sign.
- #
- # B B9999
- #
- # Displays a zero value as blank, regardless of "0"s in the format model.
- #
- # MI 9999MI
- #
- # Displays "-" after a negative value. For a positive value, a trailing space is displayed.
- #
- # S S9999
- #
- # Returns "+" for positive values and "-" for negative values in this position.
- #
- # PR 9999PR
- #
- # Displays a negative value in <angle brackets>. For a positive value,
- # a leading and trailing space is displayed.
- #
- # D 99D99
- #
- # Displays the decimal character in this position, separating the
- # integral and fractional parts of a number.
- #
- # G 9G999
- #
- # Displays the group separator in this position.
- #
- # C C999
- #
- # Displays the ISO currency symbol in this position.
- #
- # L L999
- #
- # Displays the local currency symbol in this position.
- #
- # , (comma) 9,999
- #
- # Displays a comma in this position.
- #
- # . (period) 99.99
- #
- # Displays a period (decimal point) in this position, separating the
- # integral and fractional parts of a number.
- #
- # V 999V99
- #
- # Multiplies value by 10n, where n is number of "9"s after "V".
- #
- # EEEE 9.999EEEE
- #
- # Displays value in scientific notation (format must contain exactly four "E"s).
- #
- # RN or rn RN
- #
- # Displays upper- or lowercase Roman numerals. Value can be an integer between 1 and 3999.
- #
- # DATE DATE
- #
- # Displays value as a date in MM/DD/YY format; used to format NUMBER
- # columns that represent Julian dates.
- #
- #
- #
- # The MI and PR format elements can only appear in the last position of
- # a number format model. The S format element can only appear in the
- # first or last position.
- #
- # If a number format model does not contain the MI, S or PR format
- # elements, negative return values automatically contain a leading
- # negative sign and positive values automatically contain a
- # leading space.
- #
- # A number format model can contain only a single decimal character (D)
- # or period (.), but it can contain multiple group separators (G) or
- # commas (,). A group separator or comma cannot appear to the right of a
- # decimal character or period in a number format model.
- #
- # SQL*Plus formats NUMBER data right-justified. A NUMBER column's width
- # equals the width of the heading or the width of the FORMAT plus one
- # space for the sign, whichever is greater. If you do not explicitly use
- # FORMAT, then the column's width will always be at least the value of
- # SET NUMWIDTH.
- #
- # SQL*Plus may round your NUMBER data to fit your format or field width.
- #
- # If a value cannot fit within the column width, SQL*Plus indicates
- # overflow by displaying a pound sign (#) in place of each digit the
- # width allows.
- #
- # If a positive value is extremely large and a numeric overflow occurs
- # when rounding a number, then the infinity sign (~) replaces the value.
- # Likewise, if a negative value is extremely small and a numeric
- # overflow occurs when rounding a number, then the negative infinity
- # sign replaces the value (-~).
-
- # Commify used from the Perl CookBook
- sub commify($) {
- my $num = reverse $_[0];
- $num =~ s/(\d\d\d)(?=\d)(?!\d*\.)/$1,/g;
- return scalar reverse $num;
- }
-
- sub dollarsign($$$$) {
- my ($num, $fmtnum, $dlen, $commify) = @_;
- my $formatted = sprintf "\$%${fmtnum}.${dlen}lf", $num;
- return ($commify ? commify($formatted) : $formatted);
- }
-
- sub zerofill($$$$) {
- my ($num, $fmtnum, $dlen, $commify) = @_;
- my $formatted = sprintf "%0${fmtnum}.${dlen}lf", $num;
- return ($commify ? commify($formatted) : $formatted);
- }
-
- sub signednum($$$$) {
- my ($num, $fmtnum, $dlen, $commify) = @_;
- my $formatted = sprintf "%+${fmtnum}.${dlen}lf", $num;
- return ($commify ? commify($formatted) : $formatted);
- }
-
- sub leadsign($$$$) {
- my ($num, $fmtnum, $dlen, $commify) = @_;
- my $formatted = sprintf "%+${fmtnum}.${dlen}lf", $num;
- return ($commify ? commify($formatted) : $formatted);
- }
-
- sub trailsign($$$$) {
- my ($num, $fmtnum, $dlen, $commify) = @_;
- $dlen--;
- my $formatted = sprintf "%${fmtnum}.${dlen}lf", abs($num);
- $formatted .= ($num > 0 ? '+' : '-');
- return ($commify ? commify($formatted) : $formatted);
- }
-
- sub ltgtsign($$$$) {
- my ($num, $fmtnum, $dlen, $commify) = @_;
- $dlen--;
- my $formatted = sprintf "%s%${fmtnum}.${dlen}lf%s"
- ,($num > 0 ? '' : '<')
- ,abs($num),
- ,($num > 0 ? '' : '>');
- return ($commify ? commify($formatted) : $formatted);
- }
-
- #
- # Private methods.
- #
-
- sub _me {
- my $pi = shift;
- my $self = shift;
- return ${$self}->print_buffer("show me what???")
- unless @_;
- return ${$self}->do_show(@_);
- }
-
- sub _all {
- my $pi = shift;
- my $self = shift;
- return ${$self}->print_buffer("show all of what???")
- unless @_;
- return ${$self}->do_show(@_);
- }
-
- sub _show_all_commands {
- my $pi = shift;
- my $self = shift;
- return
- ${$self}->print_buffer("Show supports the following commands:\n\t" .
- join( "\n\t", keys %{$pi->{show}}));
- }
-
- sub _unimp {
- my $pi = shift;
- my $self = shift;
- return ${$self}->print_buffer("unimplemented");
- }
-
- sub _obsolete {
- my $pi = shift;
- my $self = shift;
- return ${$self}->print_buffer("obsolete: use " . join( " ", @_) );
- }
-
- sub _print_buffer {
- my $pi = shift;
- my $self = shift;
- return ${$self}->print_buffer(@_);
- }
-
- sub _set_get {
- my $pi = shift;
- my $self = shift;
- my $command = shift;
-
- carp "command undefined: " and return unless defined $command;
-
- # Use the off to undefine/null a value.
- if (@_) {
- my $val = shift;
- if ($val =~ m/off/i) {
- $pi->{set_current}->{$command} = undef;
- } else {
- $pi->{set_current}->{$command} = $val
- }
-
- }
- ${$self}->print_buffer(
- qq{$command: } . ($pi->{set_current}->{$command}||
- 'null')
- );
- return $pi->{set_current}->{$command};
- }
-
- #------------------------------------------------------------------
- #
- # Display a list of all schemas.
- #
- #------------------------------------------------------------------
- sub _schemas {
- my ($pi, $sh, @args) = @_;
- #
- # Allow types to accept a list of types to display.
- #
- my $sth;
-
- my $dbh = ${$sh}->{dbh};
- $sth = $dbh->table_info('', '%', '', '');
-
- unless(ref $sth) {
- ${$sh}->log( "Advance table_info not supported\n");
- return;
- }
- return ${$sh}->sth_go($sth, 0, 0);
- }
-
- #------------------------------------------------------------------
- #
- # Display the last sql code, error, and error string.
- #
- #------------------------------------------------------------------
- sub _sqlcode {
- my ($pi, $sh, @args) = @_;
-
- my $dbh = ${$sh}->{dbh};
-
- my $codes;
-
- $codes .= "last dbi error : " . $dbh->err . "\n" if $dbh->err;
- $codes .= "last dbi error string : " . $dbh->errstr . "\n" if $dbh->err;
- $codes .= "last dbi error state : " . $dbh->state . "\n" if $dbh->err;
-
- ${$sh}->print_buffer_nop( $codes ) if defined $codes;
-
- return $dbh->err||0;
- }
-
- #------------------------------------------------------------------
- #
- # Display a list of all tables.
- #
- #------------------------------------------------------------------
- sub _tables {
- my ($pi, $sh, @args) = @_;
- return $pi->_sup_types( $sh, 'TABLE', @args );
- }
-
- #------------------------------------------------------------------
- #
- # Display a list of all types.
- #
- #------------------------------------------------------------------
- sub _types {
- my ($pi, $sh, @args) = @_;
- #
- # Allow types to accept a list of types to display.
- #
- my $sth;
- if (@args) {
- return $pi->_sup_types( $sh, @args );
- }
-
- my $dbh = ${$sh}->{dbh};
- $sth = $dbh->table_info('', '', '', '%');
-
- unless(ref $sth) {
- ${$sh}->log( "Advance table_info not supported\n" );
- return;
- }
- return ${$sh}->sth_go($sth, 0, 0);
- }
-
- #------------------------------------------------------------------
- #
- # Display a list of all views.
- #
- #------------------------------------------------------------------
- sub _views {
- my ($pi, $sh, @args) = @_;
-
- return $pi->_sup_types( $sh, 'VIEW', @args );
- }
-
- #------------------------------------------------------------------
- #
- # Handle different types.
- #
- #------------------------------------------------------------------
- sub _sup_types {
- my ($pi, $sh, $type, @args) = @_;
-
- $sh = ${$sh}; # Need to dereference the shell object.
-
- my $dbh = $sh->{dbh};
-
- return unless (defined $type);
-
- my $sth;
- if (@args) {
- my $tbl = join( ",", @args );
- $sth = $dbh->table_info(undef, undef, $tbl, $type);
- } else {
- $sth = $dbh->table_info(undef, undef, undef, $type);
- }
-
- unless (ref $sth) {
- ${$sh}->log( "Advance table_info not supported\n" );
- return;
- }
-
- return $sh->sth_go($sth, 0, 0);
- }
-
- 1;
-
-
-