ensembl-hive  2.7.0
StatementHandle.pm
Go to the documentation of this file.
1 =head1 LICENSE
2 
3 See the NOTICE file distributed with this work for additional information
4 regarding copyright ownership.
5 
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9 
10  http://www.apache.org/licenses/LICENSE-2.0
11 
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17 
18 =cut
19 
20 
21 =head1 CONTACT
22 
23  Please email comments or questions to the public Ensembl
24  developers list at <http://lists.ensembl.org/mailman/listinfo/dev>.
25 
26  Questions may also be sent to the Ensembl help desk at
27  <http://www.ensembl.org/Help/Contact>.
28 
29 =cut
30 
31 =head1 NAME
32 
34 
35 =head1 SYNOPSIS
36 
37 Do not use this class directly. It will automatically be used by the
39 
40 =head1 DESCRIPTION
41 
42 This class extends DBD::mysql::st so that the DESTROY method may be
43 overridden. If the DBConnection::disconnect_when_inactive flag is set
44 this statement handle will cause the database connection to be closed
45 when it goes out of scope and there are no other open statement handles.
46 
47 =head1 METHODS
48 
49 =cut
50 
52 
53 use vars qw(@ISA);
54 use strict;
55 
56 use Bio::EnsEMBL::Utils::Exception qw(warning throw);
57 
58 use DBI;
59 
60 #use Time::HiRes qw(time);
61 
62 @ISA = qw(DBI::st);
63 
64 
65 # As DBD::mysql::st is a tied hash can't store things in it,
66 # so have to have parallel hash
67 my %dbchash;
68 my %dbc_sql_hash;
69 
70 
71 sub dbc {
72  my $self = shift;
73 
74  if (@_) {
75  my $dbc = shift;
76  if(!defined($dbc)) {
77  # without delete key space would grow indefinitely causing mem-leak
78  delete($dbchash{$self});
79  } else {
80  $dbchash{$self} = $dbc;
81  }
82  }
83 
84  return $dbchash{$self};
85 }
86 
87 sub sql {
88  my $self = shift;
89 
90  if (@_) {
91  my $sql = shift;
92  if(!defined($sql)) {
93  # without delete key space would grow indefinitely causing mem-leak
94  delete($dbc_sql_hash{$self});
95  } else {
96  $dbc_sql_hash{$self} = $sql;
97  }
98  }
99 
100  return $dbc_sql_hash{$self};
101 }
102 
103 sub DESTROY {
104  my ($self) = @_;
105 
106  my $dbc = $self->dbc;
107  $self->dbc(undef);
108  my $sql = $self->sql;
109  $self->sql(undef);
110 
111  # Re-bless into DBI::st so that superclass destroy method is called if
112  # it exists (it does not exist in all DBI versions).
113  bless( $self, 'DBI::st' );
114 
115  # The count for the number of kids is decremented only after this
116  # function is complete. Disconnect if there is 1 kid (this one)
117  # remaining.
118  if ( $dbc
119  && $dbc->disconnect_when_inactive()
120  && $dbc->connected
121  && ( $dbc->db_handle->{Kids} == 1 ) )
122  {
123  if ( $dbc->disconnect_if_idle() ) {
124  warn("Problem disconnect $self around sql = $sql\n");
125  }
126  }
127 } ## end sub DESTROY
128 
129 1;
130 
131 # Comment out this "__END__" for printing out handy debug information
132 # (every query if you want).
133 
134 __END__
135 
136 # To stop caching messing up your timings, try doing the following on
137 # any adapter:
138 #
139 # $slice_adaptor->dbc()->db_handle()
140 # ->do("SET SESSION query_cache_type = OFF");
141 #
142 # To start logging:
143 # Bio::EnsEMBL::DBSQL::StatementHandle->sql_timing_start();
144 #
145 # To display the results:
146 # Bio::EnsEMBL::DBSQL::StatementHandle->sql_timing_print(1);
147 #
148 # To pause logging:
149 # Bio::EnsEMBL::DBSQL::StatementHandle->sql_timimg_pause();
150 #
151 # To resume logging after pause:
152 # Bio::EnsEMBL::DBSQL::StatementHandle->sql_timimg_resume();
153 
154 use Time::HiRes qw(time);
155 
156 my @bind_args = ();
157 my $dump = 0;
158 my %total_time;
159 my %min_time;
160 my %max_time;
161 my %number_of_times;
162 my %first_time;
163 my $grand_total;
164 
165 sub sql_timing_start {
166  %total_time = ();
167  %number_of_times = ();
168  %min_time = ();
169  %max_time = ();
170  %first_time = ();
171  $dump = 1;
172 }
173 
174 sub sql_timing_pause { $dump = 0 }
175 sub sql_timing_resume { $dump = 1 }
176 
177 sub sql_timing_print {
178  my ( $self, $level, $fh ) = @_;
179 
180  my $grand_total = 0;
181 
182  if ( !defined($fh) ) {
183  $fh = \*STDERR;
184  }
185 
186  print( ref($fh), "\n" );
187 
188  foreach my $key ( keys %total_time ) {
189  $grand_total += $total_time{$key};
190 
191  if ( !( defined($level) and $level ) ) { next }
192 
193  print( $fh $key, "\n" );
194 
195  print( $fh
196  "total\t \tnum\tfirst \t\tavg\t \t[min ,max ]\n" );
197 
198  printf( $fh "%6f\t%d\t%6f\t%6f\t[%6f, %6f]\n\n",
199  $total_time{$key}, $number_of_times{$key},
200  $first_time{$key}, ( $total_time{$key}/$number_of_times{$key} ),
201  $min_time{$key}, $max_time{$key} );
202  }
203 
204  printf( $fh "\ntotal time %6f\n\n", $grand_total );
205 
206 } ## end sub sql_timing_print
207 
208 sub bind_param {
209  my ( $self, @args ) = @_;
210 
211  $bind_args[ $args[0] - 1 ] = $args[1];
212  $self->SUPER::bind_param(@args);
213 }
214 
215 sub execute {
216  my ( $self, @args ) = @_;
217 
218  my $retval;
219  # Skip dumping if !$dump
220  if ( !$dump ) {
221  local $self->{RaiseError};
222  $retval = $self->SUPER::execute(@args);
223  if ( !defined($retval) ) {
224  throw("Failed to execute SQL statement");
225  }
226  return $retval;
227  }
228 
229  my $sql = $self->sql();
230  my @chrs = split( //, $sql );
231 
232  my $j = 0;
233 
234  for ( my $i = 0; $i < @chrs; $i++ ) {
235  if ( $chrs[$i] eq '?' && defined( $bind_args[$j] ) ) {
236  $chrs[$i] = $bind_args[ $j++ ];
237  }
238  }
239 
240  my $str = join( '', @chrs );
241 
242  # Uncomment this line if you want to see sql in order.
243  # print( STDERR "\n\nSQL:\n$str\n\n" );
244 
245  my $time = time();
246  {
247  local $self->{RaiseError};
248  $retval = $self->SUPER::execute(@args);
249  if ( !defined($retval) ) {
250  throw("Failed to execute SQL statement");
251  }
252  }
253  # my $res = $self->SUPER::execute(@args);
254  $time = time() - $time;
255 
256  if ( defined( $total_time{$sql} ) ) {
257  $total_time{$sql} += $time;
258  $number_of_times{$sql}++;
259 
260  if ( $min_time{$sql} > $time ) { $min_time{$sql} = $time }
261  if ( $max_time{$sql} < $time ) { $max_time{$sql} = $time }
262 
263  } else {
264  $first_time{$sql} = $time;
265  $max_time{$sql} = $time;
266  $min_time{$sql} = $time;
267  $total_time{$sql} = $time;
268  $number_of_times{$sql} = 1;
269  }
270 
271  return $retval;
272 } ## end sub execute
273 
274 1;
Bio::EnsEMBL::DBSQL::StatementHandle
Definition: StatementHandle.pm:21
Bio::EnsEMBL::DBSQL::DBConnection
Definition: DBConnection.pm:42
Bio
Definition: AltAlleleGroup.pm:4
Bio::EnsEMBL::Utils::Exception
Definition: Exception.pm:68