| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | # | 
| 2 |  |  |  |  |  |  | # $Id: Entry.pm,v 1.9 2003/12/24 20:38:54 oratrc Exp $ | 
| 3 |  |  |  |  |  |  | # | 
| 4 |  |  |  |  |  |  | package Oracle::Trace::Entry; | 
| 5 |  |  |  |  |  |  |  | 
| 6 | 1 |  |  | 1 |  | 18 | use 5.008001; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 45 |  | 
| 7 | 1 |  |  | 1 |  | 6 | use strict; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 30 |  | 
| 8 | 1 |  |  | 1 |  | 5 | use warnings; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 25 |  | 
| 9 | 1 |  |  | 1 |  | 5 | use Data::Dumper; | 
|  | 1 |  |  |  |  | 9 |  | 
|  | 1 |  |  |  |  | 62 |  | 
| 10 | 1 |  |  | 1 |  | 548 | use Oracle::Trace::Chunk; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 1063 |  | 
| 11 |  |  |  |  |  |  |  | 
| 12 |  |  |  |  |  |  | our @ISA = qw(Oracle::Trace::Chunk); | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | our $VERSION = do { my @r = (q$Revision: 1.9 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; | 
| 15 |  |  |  |  |  |  |  | 
| 16 |  |  |  |  |  |  | my $DEBUG = $ENV{Oracle_Trace_DEBUG} || 0; | 
| 17 |  |  |  |  |  |  |  | 
| 18 |  |  |  |  |  |  | # Chunk | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | sub parse { | 
| 21 | 25 |  |  | 25 | 1 | 29 | my $self = shift; | 
| 22 | 25 |  |  |  |  | 25 | my $data = shift; | 
| 23 | 25 | 50 |  |  |  | 47 | $self->debug("incoming: ".Dumper($data)) if $DEBUG >= 4; | 
| 24 | 25 |  |  |  |  | 25 | my $i_line = 0; | 
| 25 | 25 | 50 |  |  |  | 53 | if ($data) { | 
| 26 |  |  |  |  |  |  | LINE: | 
| 27 | 25 |  |  |  |  | 168 | foreach my $line (split("\n", $data)) { | 
| 28 | 303 | 50 |  |  |  | 497 | $self->debug("line[".$i_line."] $line") if $DEBUG >= 5; | 
| 29 | 303 |  |  |  |  | 261 | $i_line++; | 
| 30 | 303 | 100 |  |  |  | 720 | next LINE if $line =~ /^(\*\*\*\s+\d+|END OF STMT)/; | 
| 31 | 274 | 100 |  |  |  | 511 | if ($line =~ /^(STAT|WAIT)\s+/) { | 
| 32 | 39 | 50 |  |  |  | 94 | next LINE unless $self->{_extended}; | 
| 33 |  |  |  |  |  |  | } | 
| 34 | 235 | 100 |  |  |  | 575 | if ($line =~ /dep=[1-9]+/) { | 
| 35 | 197 |  |  |  |  | 217 | $self->{_child}++; | 
| 36 | 197 | 50 |  |  |  | 414 | next LINE unless $self->{_recurse}; | 
| 37 |  |  |  |  |  |  | } | 
| 38 |  |  |  |  |  |  | # expecting uppercase words preceding data - misses binds | 
| 39 | 38 | 100 |  |  |  | 112 | if ($line =~ /^([A-Z]+(?:\s+[A-Z]+)*\s*(?:\#\d+)*):*(.*)$/) { | 
| 40 | 12 |  |  |  |  | 34 | my ($k, $v) = ($1, $2); | 
| 41 | 12 | 50 |  |  |  | 206 | if (my %data = ($v =~ /([a-z]+)=(\d+|'[^']*')/g)) { | 
| 42 | 12 |  |  |  |  | 13 | push @{$self->{_data}->{$k}}, \%data; | 
|  | 12 |  |  |  |  | 33 |  | 
| 43 | 12 | 100 | 66 |  |  | 56 | if ($k =~ /^PARSING IN CURSOR/ && defined($data{dep})) { | 
| 44 | 3 | 50 |  |  |  | 21 | $self->{_parent}++ if $data{dep} == 0; | 
| 45 |  |  |  |  |  |  | } | 
| 46 |  |  |  |  |  |  | } | 
| 47 |  |  |  |  |  |  | } else { | 
| 48 | 26 |  |  |  |  | 24 | push @{$self->{_data}{other}}, $line; | 
|  | 26 |  |  |  |  | 84 |  | 
| 49 |  |  |  |  |  |  | } | 
| 50 |  |  |  |  |  |  | } | 
| 51 |  |  |  |  |  |  | } | 
| 52 | 25 | 50 |  |  |  | 77 | $self->debug("_data: ".Dumper($self->{_data})) if $DEBUG >= 3; | 
| 53 | 25 | 50 |  |  |  | 46 | $self->debug("lines read: $i_line") if $DEBUG >= 2; | 
| 54 | 25 |  |  |  |  | 60 | return $self; | 
| 55 |  |  |  |  |  |  | } | 
| 56 |  |  |  |  |  |  |  | 
| 57 |  |  |  |  |  |  | =item values | 
| 58 |  |  |  |  |  |  |  | 
| 59 |  |  |  |  |  |  | Return the values from the hash referenced by the type and key given, with optional value or index. | 
| 60 |  |  |  |  |  |  |  | 
| 61 |  |  |  |  |  |  | @vals = $o_chk->values('type' => 'PARSE #\d+', 'key' => 'dep', 'value' => '0'); | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | =cut | 
| 64 |  |  |  |  |  |  |  | 
| 65 |  |  |  |  |  |  | sub values { | 
| 66 | 32 |  |  | 32 | 1 | 32 | my $self = shift; | 
| 67 | 32 |  |  |  |  | 101 | my %h = ( | 
| 68 |  |  |  |  |  |  | 'type'	=> 'PARSE .+', | 
| 69 |  |  |  |  |  |  | 'key'	=> '.+', | 
| 70 |  |  |  |  |  |  | 'value'	=> '.+', | 
| 71 |  |  |  |  |  |  | 'index'	=> '', | 
| 72 |  |  |  |  |  |  | @_); | 
| 73 | 32 |  |  |  |  | 37 | my @vals = (); | 
| 74 | 32 | 50 | 33 |  |  | 116 | unless (($h{type}) and ($h{key})) { | 
| 75 | 0 |  |  |  |  | 0 | $self->error("invalid type and key: ".Dumper(\%h)); | 
| 76 |  |  |  |  |  |  | } else { | 
| 77 | 32 |  |  |  |  | 80 | foreach my $k (grep(/$h{type}/, $self->keys)) { | 
| 78 | 23 |  |  |  |  | 26 | my $i_ind = 0; | 
| 79 | 23 | 50 |  |  |  | 39 | if ($h{index} =~ /\d+/) { | 
| 80 | 0 | 0 |  |  |  | 0 | if ($h{type} eq 'other') { | 
| 81 | 0 |  |  |  |  | 0 | @vals = grep(/$h{value}/, @{$self->{_data}{$k}[$h{index}]}); | 
|  | 0 |  |  |  |  | 0 |  | 
| 82 |  |  |  |  |  |  | } else { | 
| 83 | 0 | 0 | 0 |  |  | 0 | if (defined($self->{_data}{$k}[$h{index}]->{$h{key}}) && | 
| 84 |  |  |  |  |  |  | $self->{_data}{$k}[$h{index}]->{$h{key}} =~ /($h{value})/) { | 
| 85 | 0 |  |  |  |  | 0 | push(@vals, $1); | 
| 86 |  |  |  |  |  |  | } | 
| 87 |  |  |  |  |  |  | } | 
| 88 |  |  |  |  |  |  | } else { | 
| 89 | 23 | 100 |  |  |  | 36 | if ($h{type} eq 'other') { | 
| 90 | 12 |  |  |  |  | 13 | @vals = grep(/$h{value}/, @{$self->{_data}{$k}}); | 
|  | 12 |  |  |  |  | 78 |  | 
| 91 |  |  |  |  |  |  | } else { | 
| 92 | 11 |  |  |  |  | 11 | foreach my $h_d (@{$self->{_data}{$k}}) { | 
|  | 11 |  |  |  |  | 22 |  | 
| 93 | 12 | 100 | 66 |  |  | 125 | push(@vals, $1) if (defined($h_d->{$h{key}}) && $h_d->{$h{key}} =~ /($h{value})/); | 
| 94 |  |  |  |  |  |  | } | 
| 95 |  |  |  |  |  |  | } | 
| 96 |  |  |  |  |  |  | } | 
| 97 |  |  |  |  |  |  | } | 
| 98 |  |  |  |  |  |  | } | 
| 99 |  |  |  |  |  |  |  | 
| 100 | 32 |  |  |  |  | 136 | return @vals; | 
| 101 |  |  |  |  |  |  | } | 
| 102 |  |  |  |  |  |  |  | 
| 103 |  |  |  |  |  |  | =item elapsed | 
| 104 |  |  |  |  |  |  |  | 
| 105 |  |  |  |  |  |  | Return a total of the C times for this C. | 
| 106 |  |  |  |  |  |  |  | 
| 107 |  |  |  |  |  |  | my $elapsed = $o_ent->elapsed; | 
| 108 |  |  |  |  |  |  |  | 
| 109 |  |  |  |  |  |  | =cut | 
| 110 |  |  |  |  |  |  |  | 
| 111 |  |  |  |  |  |  | sub elapsed { | 
| 112 | 4 |  |  | 4 | 1 | 5 | my $self = shift; | 
| 113 | 4 |  |  |  |  | 5 | my $elapsed = 0; | 
| 114 |  |  |  |  |  |  |  | 
| 115 | 4 |  |  |  |  | 10 | my @parse = $self->values('type'=>'PARSE.+', 'key'=>'e'); | 
| 116 | 4 |  |  |  |  | 10 | my @exec  = $self->values('type'=>'EXEC.+', 'key'=>'e'); | 
| 117 | 4 |  |  |  |  | 10 | my @fetch = $self->values('type'=>'FETCH.+', 'key'=>'e'); | 
| 118 | 4 | 50 |  |  |  | 10 | $self->debug("p(@parse) e(@exec) f(@fetch)") if $DEBUG >= 3; | 
| 119 |  |  |  |  |  |  |  | 
| 120 | 4 |  |  |  |  | 6 | foreach my $x (@parse, @exec, @fetch) { | 
| 121 | 7 |  |  |  |  | 11 | $elapsed += $x; | 
| 122 |  |  |  |  |  |  | } | 
| 123 |  |  |  |  |  |  |  | 
| 124 | 4 |  |  |  |  | 17 | return $elapsed; | 
| 125 |  |  |  |  |  |  | } | 
| 126 |  |  |  |  |  |  |  | 
| 127 |  |  |  |  |  |  | =item stats | 
| 128 |  |  |  |  |  |  |  | 
| 129 |  |  |  |  |  |  | Synonmy for C | 
| 130 |  |  |  |  |  |  |  | 
| 131 |  |  |  |  |  |  | =cut | 
| 132 |  |  |  |  |  |  |  | 
| 133 | 0 |  |  | 0 | 0 |  | sub statistics { return $_[0]->stats; } | 
| 134 |  |  |  |  |  |  |  | 
| 135 |  |  |  |  |  |  | sub stats { | 
| 136 | 0 |  |  | 0 | 1 |  | my $self = shift; | 
| 137 | 0 |  |  |  |  |  | my @stats = (); | 
| 138 | 0 | 0 |  |  |  |  | unless ($self->{_extended}) { | 
| 139 | 0 |  |  |  |  |  | $self->fatal("extended statistics not enabled"); | 
| 140 |  |  |  |  |  |  | } else { | 
| 141 | 0 |  |  |  |  |  | @stats = $self->values('type'=>'STAT \#\d+','key'=>'op'); | 
| 142 |  |  |  |  |  |  | } | 
| 143 | 0 |  |  |  |  |  | return @stats; | 
| 144 |  |  |  |  |  |  | } | 
| 145 |  |  |  |  |  |  |  | 
| 146 |  |  |  |  |  |  | 1; | 
| 147 |  |  |  |  |  |  |  | 
| 148 |  |  |  |  |  |  | __END__ |