Mercurial > repos > mahtabm > ensembl
comparison variant_effect_predictor/Bio/EnsEMBL/DBSQL/DBConnection.pm @ 0:1f6dce3d34e0
Uploaded
author | mahtabm |
---|---|
date | Thu, 11 Apr 2013 02:01:53 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1f6dce3d34e0 |
---|---|
1 =head1 LICENSE | |
2 | |
3 Copyright (c) 1999-2012 The European Bioinformatics Institute and | |
4 Genome Research Limited. All rights reserved. | |
5 | |
6 This software is distributed under a modified Apache license. | |
7 For license details, please see | |
8 | |
9 http://www.ensembl.org/info/about/code_licence.html | |
10 | |
11 =head1 CONTACT | |
12 | |
13 Please email comments or questions to the public Ensembl | |
14 developers list at <dev@ensembl.org>. | |
15 | |
16 Questions may also be sent to the Ensembl help desk at | |
17 <helpdesk@ensembl.org>. | |
18 | |
19 =cut | |
20 | |
21 =head1 NAME | |
22 | |
23 Bio::EnsEMBL::DBSQL::DBConnection | |
24 | |
25 =head1 SYNOPSIS | |
26 | |
27 $dbc = Bio::EnsEMBL::DBSQL::DBConnection->new( | |
28 -user => 'anonymous', | |
29 -dbname => 'homo_sapiens_core_20_34c', | |
30 -host => 'ensembldb.ensembl.org', | |
31 -driver => 'mysql', | |
32 ); | |
33 | |
34 # SQL statements should be created/executed through this modules | |
35 # prepare() and do() methods. | |
36 | |
37 $sth = $dbc->prepare("SELECT something FROM yourtable"); | |
38 | |
39 $sth->execute(); | |
40 | |
41 # do something with rows returned ... | |
42 | |
43 $sth->finish(); | |
44 | |
45 =head1 DESCRIPTION | |
46 | |
47 This class is a wrapper around DBIs datbase handle. It provides some | |
48 additional functionality such as the ability to automatically disconnect | |
49 when inactive and reconnect when needed. | |
50 | |
51 Generally this class will be used through one of the object adaptors or | |
52 the Bio::EnsEMBL::Registry and will not be instantiated directly. | |
53 | |
54 =head1 METHODS | |
55 | |
56 =cut | |
57 | |
58 | |
59 package Bio::EnsEMBL::DBSQL::DBConnection; | |
60 | |
61 use vars qw(@ISA); | |
62 use strict; | |
63 | |
64 use Bio::EnsEMBL::Root; | |
65 use DBI; | |
66 | |
67 use Bio::EnsEMBL::DBSQL::StatementHandle; | |
68 | |
69 use Bio::EnsEMBL::Utils::Exception qw/deprecate throw info warning/; | |
70 use Bio::EnsEMBL::Utils::Argument qw/rearrange/; | |
71 use Bio::EnsEMBL::Utils::Scalar qw/assert_ref wrap_array/; | |
72 use Bio::EnsEMBL::Utils::SqlHelper; | |
73 | |
74 @ISA = qw(Bio::EnsEMBL::Root); # for backwards compatibility | |
75 | |
76 =head2 new | |
77 | |
78 Arg [DBNAME] : (optional) string | |
79 The name of the database to connect to. | |
80 Arg [HOST] : (optional) string | |
81 The domain name of the database host to connect to. | |
82 'localhost' by default. | |
83 Arg [USER] : string | |
84 The name of the database user to connect with | |
85 Arg [PASS] : (optional) string | |
86 The password to be used to connect to the database | |
87 Arg [PORT] : (optional) int | |
88 The port to use when connecting to the database | |
89 3306 by default if the driver is mysql. | |
90 Arg [DRIVER] : (optional) string | |
91 The type of database driver to use to connect to the DB | |
92 mysql by default. | |
93 Arg [DBCONN] : (optional) | |
94 Open another handle to the same database as another connection | |
95 If this argument is specified, no other arguments should be | |
96 specified. | |
97 Arg [DISCONNECT_WHEN_INACTIVE]: (optional) boolean | |
98 If set to true, the database connection will be disconnected | |
99 everytime there are no active statement handles. This is | |
100 useful when running a lot of jobs on a compute farm | |
101 which would otherwise keep open a lot of connections to the | |
102 database. Database connections are automatically reopened | |
103 when required.Do not use this option together with RECONNECT_WHEN_CONNECTION_LOST. | |
104 Arg [WAIT_TIMEOUT]: (optional) integer | |
105 Time in seconds for the wait timeout to happen. Time after which | |
106 the connection is deleted if not used. By default this is 28800 (8 hours) | |
107 on most systems. | |
108 So set this to greater than this if your connection are getting deleted. | |
109 Only set this if you are having problems and know what you are doing. | |
110 Arg [RECONNECT_WHEN_CONNECTION_LOST]: (optional) boolean | |
111 In case you're reusing the same database connection, i.e. DISCONNECT_WHEN_INACTIVE is | |
112 set to false and running a job which takes a long time to process (over 8hrs), | |
113 which means that the db connection may be lost, set this option to true. | |
114 On each prepare or do statement the db handle will be pinged and the database | |
115 connection will be reconnected if it's lost. | |
116 | |
117 Example : $dbc = Bio::EnsEMBL::DBSQL::DBConnection->new | |
118 (-user => 'anonymous', | |
119 -dbname => 'homo_sapiens_core_20_34c', | |
120 -host => 'ensembldb.ensembl.org', | |
121 -driver => 'mysql'); | |
122 | |
123 Description: Constructor for a Database Connection. Any adaptors that require | |
124 database connectivity should inherit from this class. | |
125 Returntype : Bio::EnsEMBL::DBSQL::DBConnection | |
126 Exceptions : thrown if USER or DBNAME are not specified, or if the database | |
127 cannot be connected to. | |
128 Caller : Bio::EnsEMBL::Utils::ConfigRegistry ( for newer code using the registry) | |
129 Bio::EnsEMBL::DBSQL::DBAdaptor ( for old style code) | |
130 Status : Stable | |
131 | |
132 =cut | |
133 | |
134 sub new { | |
135 my $class = shift; | |
136 | |
137 my ( | |
138 $db, $host, $driver, | |
139 $user, $password, $port, | |
140 $inactive_disconnect, $dbconn, $wait_timeout, $reconnect | |
141 ) | |
142 = rearrange( [ | |
143 'DBNAME', 'HOST', 'DRIVER', 'USER', 'PASS', 'PORT', | |
144 'DISCONNECT_WHEN_INACTIVE', 'DBCONN', 'WAIT_TIMEOUT', 'RECONNECT_WHEN_CONNECTION_LOST' | |
145 ], | |
146 @_ | |
147 ); | |
148 | |
149 my $self = {}; | |
150 bless $self, $class; | |
151 | |
152 if($dbconn) { | |
153 if($db || $host || $driver || $password || $port || $inactive_disconnect || $reconnect) { | |
154 throw("Cannot specify other arguments when -DBCONN argument used."); | |
155 } | |
156 | |
157 $self->driver($dbconn->driver()); | |
158 $self->host($dbconn->host()); | |
159 $self->port($dbconn->port()); | |
160 $self->username($dbconn->username()); | |
161 $self->password($dbconn->password()); | |
162 $self->dbname($dbconn->dbname()); | |
163 | |
164 if($dbconn->disconnect_when_inactive()) { | |
165 $self->disconnect_when_inactive(1); | |
166 } | |
167 } else { | |
168 $driver ||= 'mysql'; | |
169 | |
170 if($driver eq 'mysql') { | |
171 $user || throw("-USER argument is required."); | |
172 $host ||= 'mysql'; | |
173 if(!defined($port)){ | |
174 $port = 3306; | |
175 if($host eq "ensembldb.ensembl.org"){ | |
176 if( $db =~ /\w+_\w+_\w+_(\d+)/){ | |
177 if($1 >= 48){ | |
178 $port = 5306; | |
179 } | |
180 } | |
181 } | |
182 } | |
183 } | |
184 | |
185 $wait_timeout ||= 0; | |
186 | |
187 $self->driver($driver); | |
188 $self->host( $host ); | |
189 $self->port($port); | |
190 $self->username( $user ); | |
191 $self->password( $password ); | |
192 $self->dbname( $db ); | |
193 $self->timeout($wait_timeout); | |
194 | |
195 if($inactive_disconnect) { | |
196 $self->disconnect_when_inactive($inactive_disconnect); | |
197 } | |
198 if($reconnect) { | |
199 $self->reconnect_when_lost($reconnect); | |
200 } | |
201 } | |
202 | |
203 # if(defined $dnadb) { | |
204 # $self->dnadb($dnadb); | |
205 # } | |
206 return $self; | |
207 } | |
208 | |
209 | |
210 =head2 connect | |
211 | |
212 Example : $dbcon->connect() | |
213 Description: Connects to the database using the connection attribute | |
214 information. | |
215 Returntype : none | |
216 Exceptions : none | |
217 Caller : new, db_handle | |
218 Status : Stable | |
219 | |
220 =cut | |
221 | |
222 sub connect { | |
223 my ($self) = @_; | |
224 | |
225 if ( $self->connected() ) { return } | |
226 | |
227 $self->connected(1); | |
228 | |
229 if ( defined( $self->db_handle() ) and $self->db_handle()->ping() ) { | |
230 warning( "unconnected db_handle is still pingable, " | |
231 . "reseting connected boolean\n" ); | |
232 } | |
233 | |
234 my ( $dsn, $dbh ); | |
235 my $dbname = $self->dbname(); | |
236 | |
237 if ( $self->driver() eq "Oracle" ) { | |
238 | |
239 $dsn = "DBI:Oracle:"; | |
240 | |
241 eval { | |
242 $dbh = DBI->connect( $dsn, | |
243 sprintf( "%s@%s", | |
244 $self->username(), $dbname ), | |
245 $self->password(), | |
246 { 'RaiseError' => 1, 'PrintError' => 0 } ); | |
247 }; | |
248 | |
249 } elsif ( $self->driver() eq "ODBC" ) { | |
250 | |
251 $dsn = sprintf( "DBI:ODBC:%s", $self->dbname() ); | |
252 | |
253 eval { | |
254 $dbh = DBI->connect( $dsn, | |
255 $self->username(), | |
256 $self->password(), { | |
257 'LongTruncOk' => 1, | |
258 'LongReadLen' => 2**16 - 8, | |
259 'RaiseError' => 1, | |
260 'PrintError' => 0, | |
261 'odbc_cursortype' => 2 } ); | |
262 }; | |
263 | |
264 } elsif ( $self->driver() eq "Sybase" ) { | |
265 my $dbparam = ($dbname) ? ";database=${dbname}" : q{}; | |
266 | |
267 $dsn = sprintf( "DBI:Sybase:server=%s%s;tdsLevel=CS_TDS_495", | |
268 $self->host(), $dbparam ); | |
269 | |
270 eval { | |
271 $dbh = DBI->connect( $dsn, | |
272 $self->username(), | |
273 $self->password(), { | |
274 'LongTruncOk' => 1, | |
275 'RaiseError' => 1, | |
276 'PrintError' => 0 } ); | |
277 }; | |
278 | |
279 } elsif ( lc( $self->driver() ) eq 'sqlite' ) { | |
280 | |
281 throw "We require a dbname to connect to a SQLite database" | |
282 if !$dbname; | |
283 | |
284 $dsn = sprintf( "DBI:SQLite:%s", $dbname ); | |
285 | |
286 eval { | |
287 $dbh = DBI->connect( $dsn, '', '', { 'RaiseError' => 1, } ); | |
288 }; | |
289 | |
290 } else { | |
291 | |
292 my $dbparam = ($dbname) ? "database=${dbname};" : q{}; | |
293 | |
294 $dsn = sprintf( "DBI:%s:%shost=%s;port=%s", | |
295 $self->driver(), $dbparam, | |
296 $self->host(), $self->port() ); | |
297 | |
298 if ( $self->{'disconnect_when_inactive'} ) { | |
299 $self->{'count'}++; | |
300 if ( $self->{'count'} > 1000 ) { | |
301 sleep 1; | |
302 $self->{'count'} = 0; | |
303 } | |
304 } | |
305 eval { | |
306 $dbh = DBI->connect( $dsn, $self->username(), $self->password(), | |
307 { 'RaiseError' => 1 } ); | |
308 }; | |
309 } | |
310 | |
311 if ( !$dbh || $@ || !$dbh->ping() ) { | |
312 warn( "Could not connect to database " | |
313 . $self->dbname() | |
314 . " as user " | |
315 . $self->username() | |
316 . " using [$dsn] as a locator:\n" | |
317 . $DBI::errstr ); | |
318 | |
319 $self->connected(0); | |
320 | |
321 throw( "Could not connect to database " | |
322 . $self->dbname() | |
323 . " as user " | |
324 . $self->username() | |
325 . " using [$dsn] as a locator:\n" | |
326 . $DBI::errstr ); | |
327 } | |
328 | |
329 $self->db_handle($dbh); | |
330 | |
331 if ( $self->timeout() ) { | |
332 $dbh->do( "SET SESSION wait_timeout=" . $self->timeout() ); | |
333 } | |
334 | |
335 #print("CONNECT\n"); | |
336 } ## end sub connect | |
337 | |
338 | |
339 =head2 connected | |
340 | |
341 Example : $dbcon->connected() | |
342 Description: Boolean which tells if DBConnection is connected or not. | |
343 State is set internally, and external processes should not alter state. | |
344 Returntype : undef or 1 | |
345 Exceptions : none | |
346 Caller : db_handle, connect, disconnect_if_idle, user processes | |
347 Status : Stable | |
348 | |
349 =cut | |
350 | |
351 sub connected { | |
352 my $self = shift; | |
353 | |
354 # Use the process id ($$) as part of the key for the connected flag. | |
355 # This forces the opening of another connection in a forked subprocess. | |
356 $self->{'connected'.$$} = shift if(@_); | |
357 return $self->{'connected'.$$}; | |
358 } | |
359 | |
360 sub disconnect_count { | |
361 my $self = shift; | |
362 return $self->{'disconnect_count'} = shift if(@_); | |
363 $self->{'disconnect_count'}=0 unless(defined($self->{'disconnect_count'})); | |
364 return $self->{'disconnect_count'}; | |
365 } | |
366 | |
367 sub timeout{ | |
368 my($self, $arg ) = @_; | |
369 | |
370 (defined $arg) && | |
371 ($self->{_timeout} = $arg ); | |
372 | |
373 return $self->{_timeout}; | |
374 | |
375 } | |
376 | |
377 sub query_count { | |
378 my $self = shift; | |
379 return $self->{'_query_count'} = shift if(@_); | |
380 $self->{'_query_count'}=0 unless(defined($self->{'_query_count'})); | |
381 return $self->{'_query_count'}; | |
382 } | |
383 | |
384 =head2 equals | |
385 | |
386 Example : warn 'Same!' if($dbc->equals($other_dbc)); | |
387 Description: Equality checker for DBConnection objects | |
388 Returntype : boolean | |
389 Exceptions : none | |
390 Caller : new | |
391 Status : Stable | |
392 | |
393 =cut | |
394 | |
395 | |
396 sub equals { | |
397 my ( $self, $dbc ) = @_; | |
398 return 0 if ! defined $dbc; | |
399 my $return = 0; | |
400 my $undef_str = q{!-undef-!}; | |
401 my $undef_num = -1; | |
402 | |
403 $return = 1 if ( | |
404 (($self->host() || $undef_str) eq ($dbc->host() || $undef_str)) && | |
405 (($self->dbname() || $undef_str) eq ($dbc->dbname() || $undef_str)) && | |
406 (($self->port() || $undef_num) == ($dbc->port() || $undef_num)) && | |
407 (($self->username() || $undef_str) eq ($dbc->username() || $undef_str)) && | |
408 ($self->driver() eq $dbc->driver()) | |
409 ); | |
410 | |
411 return $return; | |
412 } | |
413 | |
414 =head2 driver | |
415 | |
416 Arg [1] : (optional) string $arg | |
417 the name of the driver to use to connect to the database | |
418 Example : $driver = $db_connection->driver() | |
419 Description: Getter / Setter for the driver this connection uses. | |
420 Right now there is no point to setting this value after a | |
421 connection has already been established in the constructor. | |
422 Returntype : string | |
423 Exceptions : none | |
424 Caller : new | |
425 Status : Stable | |
426 | |
427 =cut | |
428 | |
429 sub driver { | |
430 my($self, $arg ) = @_; | |
431 | |
432 (defined $arg) && | |
433 ($self->{_driver} = $arg ); | |
434 return $self->{_driver}; | |
435 } | |
436 | |
437 | |
438 =head2 port | |
439 | |
440 Arg [1] : (optional) int $arg | |
441 the TCP or UDP port to use to connect to the database | |
442 Example : $port = $db_connection->port(); | |
443 Description: Getter / Setter for the port this connection uses to communicate | |
444 to the database daemon. There currently is no point in | |
445 setting this value after the connection has already been | |
446 established by the constructor. | |
447 Returntype : string | |
448 Exceptions : none | |
449 Caller : new | |
450 Status : Stable | |
451 | |
452 =cut | |
453 | |
454 sub port { | |
455 my ( $self, $value ) = @_; | |
456 | |
457 if ( defined($value) ) { | |
458 $self->{'_port'} = $value; | |
459 } | |
460 | |
461 return $self->{'_port'}; | |
462 } | |
463 | |
464 | |
465 =head2 dbname | |
466 | |
467 Arg [1] : (optional) string $arg | |
468 The new value of the database name used by this connection. | |
469 Example : $dbname = $db_connection->dbname() | |
470 Description: Getter/Setter for the name of the database used by this | |
471 connection. There is currently no point in setting this value | |
472 after the connection has already been established by the | |
473 constructor. | |
474 Returntype : string | |
475 Exceptions : none | |
476 Caller : new | |
477 Status : Stable | |
478 | |
479 =cut | |
480 | |
481 sub dbname { | |
482 my ($self, $arg ) = @_; | |
483 ( defined $arg ) && | |
484 ( $self->{_dbname} = $arg ); | |
485 $self->{_dbname}; | |
486 } | |
487 | |
488 | |
489 =head2 username | |
490 | |
491 Arg [1] : (optional) string $arg | |
492 The new value of the username used by this connection. | |
493 Example : $username = $db_connection->username() | |
494 Description: Getter/Setter for the username used by this | |
495 connection. There is currently no point in setting this value | |
496 after the connection has already been established by the | |
497 constructor. | |
498 Returntype : string | |
499 Exceptions : none | |
500 Caller : new | |
501 Status : Stable | |
502 | |
503 =cut | |
504 | |
505 sub username { | |
506 my ($self, $arg ) = @_; | |
507 ( defined $arg ) && | |
508 ( $self->{_username} = $arg ); | |
509 $self->{_username}; | |
510 } | |
511 | |
512 | |
513 =head2 host | |
514 | |
515 Arg [1] : (optional) string $arg | |
516 The new value of the host used by this connection. | |
517 Example : $host = $db_connection->host() | |
518 Description: Getter/Setter for the domain name of the database host use by | |
519 this connection. There is currently no point in setting | |
520 this value after the connection has already been established | |
521 by the constructor. | |
522 Returntype : string | |
523 Exceptions : none | |
524 Caller : new | |
525 Status : Stable | |
526 | |
527 =cut | |
528 | |
529 sub host { | |
530 my ($self, $arg ) = @_; | |
531 ( defined $arg ) && | |
532 ( $self->{_host} = $arg ); | |
533 $self->{_host}; | |
534 } | |
535 | |
536 | |
537 =head2 password | |
538 | |
539 Arg [1] : (optional) string $arg | |
540 The new value of the password used by this connection. | |
541 Example : $host = $db_connection->password() | |
542 Description: Getter/Setter for the password of to use for this | |
543 connection. There is currently no point in setting | |
544 this value after the connection has already been | |
545 established by the constructor. | |
546 Returntype : string | |
547 Exceptions : none | |
548 Caller : new | |
549 Status : Stable | |
550 | |
551 =cut | |
552 | |
553 sub password { | |
554 my ( $self, $arg ) = @_; | |
555 | |
556 if ( defined($arg) ) { | |
557 # Use an anonymous subroutine that will return the password when | |
558 # invoked. This will prevent the password from being accidentally | |
559 # displayed when using e.g. Data::Dumper on a structure containing | |
560 # one of these objects. | |
561 | |
562 $self->{_password} = sub { $arg }; | |
563 } | |
564 | |
565 return ( ref( $self->{_password} ) && &{ $self->{_password} } ) || ''; | |
566 } | |
567 | |
568 | |
569 | |
570 =head2 disconnect_when_inactive | |
571 | |
572 Arg [1] : (optional) boolean $newval | |
573 Example : $db->disconnect_when_inactive(1); | |
574 Description: Getter/Setter for the disconnect_when_inactive flag. If set | |
575 to true this DBConnection will continually disconnect itself | |
576 when there are no active statement handles and reconnect as | |
577 necessary. Useful for farm environments when there can be | |
578 many (often inactive) open connections to a database at once. | |
579 Returntype : boolean | |
580 Exceptions : none | |
581 Caller : Pipeline | |
582 Status : Stable | |
583 | |
584 =cut | |
585 | |
586 sub disconnect_when_inactive { | |
587 my ( $self, $value ) = @_; | |
588 | |
589 if ( defined($value) ) { | |
590 $self->{'disconnect_when_inactive'} = $value; | |
591 if ($value) { | |
592 $self->disconnect_if_idle(); | |
593 } | |
594 } | |
595 | |
596 return $self->{'disconnect_when_inactive'}; | |
597 } | |
598 | |
599 | |
600 =head2 reconnect_when_lost | |
601 | |
602 Arg [1] : (optional) boolean $newval | |
603 Example : $db->reconnect_when_lost(1); | |
604 Description: Getter/Setter for the reconnect_when_lost flag. If set | |
605 to true the db handle will be pinged on each prepare or do statement | |
606 and the connection will be reestablished in case it's lost. | |
607 Useful for long running jobs (over 8hrs), which means that the db | |
608 connection may be lost. | |
609 Returntype : boolean | |
610 Exceptions : none | |
611 Caller : Pipeline | |
612 Status : Stable | |
613 | |
614 =cut | |
615 | |
616 sub reconnect_when_lost { | |
617 my ( $self, $value ) = @_; | |
618 | |
619 if ( defined($value) ) { | |
620 $self->{'reconnect_when_lost'} = $value; | |
621 } | |
622 | |
623 return $self->{'reconnect_when_lost'}; | |
624 } | |
625 | |
626 | |
627 | |
628 =head2 locator | |
629 | |
630 Arg [1] : none | |
631 Example : $locator = $dbc->locator; | |
632 Description: Constructs a locator string for this database connection | |
633 that can, for example, be used by the DBLoader module | |
634 Returntype : string | |
635 Exceptions : none | |
636 Caller : general | |
637 Status : Stable | |
638 | |
639 =cut | |
640 | |
641 | |
642 sub locator { | |
643 my ($self) = @_; | |
644 | |
645 return sprintf( | |
646 "%s/host=%s;port=%s;dbname=%s;user=%s;pass=%s", | |
647 ref($self), $self->host(), $self->port(), | |
648 $self->dbname(), $self->username(), $self->password() ); | |
649 } | |
650 | |
651 | |
652 =head2 db_handle | |
653 | |
654 Arg [1] : DBI Database Handle $value | |
655 Example : $dbh = $db_connection->db_handle() | |
656 Description: Getter / Setter for the Database handle used by this | |
657 database connection. | |
658 Returntype : DBI Database Handle | |
659 Exceptions : none | |
660 Caller : new, DESTROY | |
661 Status : Stable | |
662 | |
663 =cut | |
664 | |
665 sub db_handle { | |
666 my $self = shift; | |
667 | |
668 # Use the process id ($$) as part of the key for the database handle | |
669 # this makes this object fork safe. fork() does not makes copies | |
670 # of the open socket which creates problems when one of the forked | |
671 # processes disconnects, | |
672 return $self->{'db_handle'.$$} = shift if(@_); | |
673 return $self->{'db_handle'.$$} if($self->connected); | |
674 | |
675 $self->connect(); | |
676 return $self->{'db_handle'.$$}; | |
677 } | |
678 | |
679 | |
680 =head2 prepare | |
681 | |
682 Arg [1] : string $string | |
683 the SQL statement to prepare | |
684 Example : $sth = $db_connection->prepare("SELECT column FROM table"); | |
685 Description: Prepares a SQL statement using the internal DBI database handle | |
686 and returns the DBI statement handle. | |
687 Returntype : DBI statement handle | |
688 Exceptions : thrown if the SQL statement is empty, or if the internal | |
689 database handle is not present | |
690 Caller : Adaptor modules | |
691 Status : Stable | |
692 | |
693 =cut | |
694 | |
695 sub prepare { | |
696 my ($self,@args) = @_; | |
697 | |
698 if( ! $args[0] ) { | |
699 throw("Attempting to prepare an empty SQL query."); | |
700 } | |
701 | |
702 #warn "SQL(".$self->dbname."):" . join(' ', @args) . "\n"; | |
703 if ( ($self->reconnect_when_lost()) and (!$self->db_handle()->ping()) ) { | |
704 $self->reconnect(); | |
705 } | |
706 my $sth = $self->db_handle->prepare(@args); | |
707 | |
708 # return an overridden statement handle that provides us with | |
709 # the means to disconnect inactive statement handles automatically | |
710 bless $sth, "Bio::EnsEMBL::DBSQL::StatementHandle"; | |
711 $sth->dbc($self); | |
712 $sth->sql($args[0]); | |
713 | |
714 $self->query_count($self->query_count()+1); | |
715 return $sth; | |
716 } | |
717 | |
718 =head2 reconnect | |
719 | |
720 Example : $dbcon->reconnect() | |
721 Description: Reconnects to the database using the connection attribute | |
722 information if db_handle no longer pingable. | |
723 Returntype : none | |
724 Exceptions : none | |
725 Caller : new, db_handle | |
726 Status : Stable | |
727 | |
728 =cut | |
729 | |
730 sub reconnect { | |
731 my ($self) = @_; | |
732 $self->connected(undef); | |
733 $self->db_handle(undef); | |
734 $self->connect(); | |
735 return; | |
736 } | |
737 | |
738 | |
739 =head2 do | |
740 | |
741 Arg [1] : string $string | |
742 the SQL statement to prepare | |
743 Example : $sth = $db_connection->do("SELECT column FROM table"); | |
744 Description: Executes a SQL statement using the internal DBI database handle. | |
745 Returntype : Result of DBI dbh do() method | |
746 Exceptions : thrown if the SQL statement is empty, or if the internal | |
747 database handle is not present. | |
748 Caller : Adaptor modules | |
749 Status : Stable | |
750 | |
751 =cut | |
752 | |
753 sub do { | |
754 my ($self,$string) = @_; | |
755 | |
756 if( ! $string ) { | |
757 throw("Attempting to do an empty SQL query."); | |
758 } | |
759 | |
760 # warn "SQL(".$self->dbname."): $string"; | |
761 my $error; | |
762 | |
763 my $do_result = $self->work_with_db_handle(sub { | |
764 my ($dbh) = @_; | |
765 my $result = eval { $dbh->do($string) }; | |
766 $error = $@ if $@; | |
767 return $result; | |
768 }); | |
769 | |
770 throw "Detected an error whilst executing statement '$string': $error" if $error; | |
771 | |
772 return $do_result; | |
773 } | |
774 | |
775 =head2 work_with_db_handle | |
776 | |
777 Arg [1] : CodeRef $callback | |
778 Example : my $q_t = $dbc->work_with_db_handle(sub { my ($dbh) = @_; return $dbh->quote_identifier('table'); }); | |
779 Description: Gives access to the DBI handle to execute methods not normally | |
780 provided by the DBConnection interface | |
781 Returntype : Any from callback | |
782 Exceptions : If the callback paramater is not a CodeRef; all other | |
783 errors are re-thrown after cleanup. | |
784 Caller : Adaptor modules | |
785 Status : Stable | |
786 | |
787 =cut | |
788 | |
789 sub work_with_db_handle { | |
790 my ($self, $callback) = @_; | |
791 my $wantarray = wantarray; | |
792 assert_ref($callback, 'CODE', 'callback'); | |
793 if( $self->reconnect_when_lost() && !$self->db_handle()->ping()) { | |
794 $self->reconnect(); | |
795 } | |
796 my @results; | |
797 eval { | |
798 if($wantarray) { | |
799 @results = $callback->($self->db_handle()) | |
800 } | |
801 elsif(defined $wantarray) { | |
802 $results[0] = $callback->($self->db_handle()); | |
803 } | |
804 else { | |
805 $callback->($self->db_handle()); | |
806 } | |
807 }; | |
808 my $original_error = $@; | |
809 | |
810 $self->query_count($self->query_count()+1); | |
811 eval { | |
812 if($self->disconnect_when_inactive()) { | |
813 $self->disconnect_if_idle(); | |
814 } | |
815 }; | |
816 if($@) { | |
817 warning "Detected an error whilst attempting to disconnect the DBI handle: $@"; | |
818 } | |
819 if($original_error) { | |
820 throw "Detected an error when running DBI wrapper callback:\n$original_error"; | |
821 } | |
822 | |
823 if(defined $wantarray) { | |
824 return ($wantarray) ? @results : $results[0]; | |
825 } | |
826 return; | |
827 } | |
828 | |
829 =head2 prevent_disconnect | |
830 | |
831 Arg[1] : CodeRef $callback | |
832 Example : $dbc->prevent_disconnect(sub { $dbc->do('do something'); $dbc->do('something else')}); | |
833 Description : A wrapper method which prevents database disconnection for the | |
834 duration of the callback. This is very useful if you need | |
835 to make multiple database calls avoiding excessive database | |
836 connection creation/destruction but still want the API | |
837 to disconnect after the body of work. | |
838 | |
839 The value of C<disconnect_when_inactive()> is set to 0 no | |
840 matter what the original value was & after $callback has | |
841 been executed. If C<disconnect_when_inactive()> was | |
842 already set to 0 then this method will be an effective no-op. | |
843 Returntype : None | |
844 Exceptions : Raised if there are issues with reverting the connection to its | |
845 default state. | |
846 Caller : DBConnection methods | |
847 Status : Beta | |
848 | |
849 =cut | |
850 | |
851 sub prevent_disconnect { | |
852 my ($self, $callback) = @_; | |
853 assert_ref($callback, 'CODE', 'callback'); | |
854 my $original_dwi = $self->disconnect_when_inactive(); | |
855 $self->disconnect_when_inactive(0); | |
856 eval { $callback->(); }; | |
857 my $original_error = $@; | |
858 eval { | |
859 $self->disconnect_when_inactive($original_dwi); | |
860 }; | |
861 if($@) { | |
862 warning "Detected an error whilst attempting to reset disconnect_when_idle: $@"; | |
863 } | |
864 if($original_error) { | |
865 throw "Detected an error when running DBI wrapper callback:\n$original_error"; | |
866 } | |
867 return; | |
868 } | |
869 | |
870 =head2 quote_identifier | |
871 | |
872 Arg [n] : scalar/ArrayRef | |
873 Example : $q = $dbc->quote_identifier('table', 'other'); | |
874 $q = $dbc->quote_identifier([undef, 'my_db', 'table'], [undef, 'my_db', 'other']); | |
875 Description: Executes the DBI C<quote_identifier> method which will quote | |
876 any given string using the database driver's quote character. | |
877 Returntype : ArrayRef | |
878 Exceptions : None | |
879 Caller : General | |
880 Status : Stable | |
881 | |
882 =cut | |
883 | |
884 sub quote_identifier { | |
885 my ($self, @identifiers) = @_; | |
886 return $self->work_with_db_handle(sub { | |
887 my ($dbh) = @_; | |
888 my @output; | |
889 foreach my $identifier_array (@identifiers) { | |
890 $identifier_array = wrap_array($identifier_array); | |
891 push(@output, $dbh->quote_identifier(@{$identifier_array})); | |
892 } | |
893 return \@output; | |
894 }); | |
895 } | |
896 | |
897 =head2 disconnect_if_idle | |
898 | |
899 Arg [1] : none | |
900 Example : $dbc->disconnect_if_idle(); | |
901 Description: Disconnects from the database if there are no currently active | |
902 statement handles. | |
903 It is called automatically by the DESTROY method of the | |
904 Bio::EnsEMBL::DBSQL::SQL::StatementHandle if the | |
905 disconect_when_inactive flag is set. | |
906 Users may call it whenever they want to disconnect. Connection will | |
907 reestablish on next access to db_handle() | |
908 Returntype : 1 or 0 | |
909 1=problem trying to disconnect while a statement handle was still active | |
910 Exceptions : none | |
911 Caller : Bio::EnsEMBL::DBSQL::SQL::StatementHandle::DESTROY | |
912 Bio::EnsEMBL::DBSQL::DBConnection::do | |
913 Status : Stable | |
914 | |
915 =cut | |
916 | |
917 sub disconnect_if_idle { | |
918 my $self = shift; | |
919 | |
920 return 0 if(!$self->connected()); | |
921 my $db_handle = $self->db_handle(); | |
922 return 0 unless(defined($db_handle)); | |
923 | |
924 #printf("disconnect_if_idle : kids=%d activekids=%d\n", | |
925 # $db_handle->{Kids}, $db_handle->{ActiveKids}); | |
926 | |
927 #If InactiveDestroy is set, don't disconnect. | |
928 #To comply with DBI specification | |
929 return 0 if($db_handle->{InactiveDestroy}); | |
930 | |
931 #If any statement handles are still active, don't allow disconnection | |
932 #In this case it is being called before a query has been fully processed | |
933 #either by not reading all rows of data returned, or not calling ->finish | |
934 #on the statement handle. Don't disconnect, send warning | |
935 if($db_handle->{ActiveKids} != 0) { | |
936 warn("Problem disconnect : kids=",$db_handle->{Kids}, | |
937 " activekids=",$db_handle->{ActiveKids},"\n"); | |
938 return 1; | |
939 } | |
940 | |
941 $db_handle->disconnect(); | |
942 $self->connected(undef); | |
943 $self->disconnect_count($self->disconnect_count()+1); | |
944 #print("DISCONNECT\n"); | |
945 $self->db_handle(undef); | |
946 return 0; | |
947 } | |
948 | |
949 | |
950 =head2 add_limit_clause | |
951 | |
952 Arg [1] : string $sql | |
953 Arg [2] : int $max_number | |
954 Example : my $new_sql = $dbc->add_limit_clause($sql,$max_number); | |
955 Description: Giving an SQL statement, it adds a limit clause, dependent on the database | |
956 (in MySQL, should add a LIMIT at the end, MSSQL uses a TOP clause) | |
957 Returntype : String containing the new valid SQL statement | |
958 Exceptions : none | |
959 Caller : general | |
960 Status : at risk | |
961 | |
962 =cut | |
963 | |
964 | |
965 sub add_limit_clause{ | |
966 my $self = shift; | |
967 my $sql = shift; | |
968 my $max_number = shift; | |
969 | |
970 my $new_sql = ''; | |
971 if ($self->driver eq 'mysql'){ | |
972 $new_sql = $sql . ' LIMIT ' . $max_number; | |
973 } | |
974 elsif ($self->driver eq 'odbc'){ | |
975 #need to get anything after the SELECT statement | |
976 $sql =~ /select(.*)/i; | |
977 $new_sql = 'SELECT TOP ' . $max_number . $1; | |
978 } | |
979 else{ | |
980 warning("Not possible to convert $sql to an unknow database driver: ", $self->driver, " no limit applied"); | |
981 $new_sql = $sql; | |
982 } | |
983 return $new_sql; | |
984 } | |
985 | |
986 | |
987 =head2 from_date_to_seconds | |
988 | |
989 Arg [1] : date $date | |
990 Example : my $string = $dbc->from_date_to_seconds($date); | |
991 Description: Giving a string representing a column of type date | |
992 applies the database function to convert to the number of seconds from 01-01-1970 | |
993 Returntype : string | |
994 Exceptions : none | |
995 Caller : general | |
996 Status : at risk | |
997 | |
998 =cut | |
999 | |
1000 sub from_date_to_seconds{ | |
1001 my $self= shift; | |
1002 my $column = shift; | |
1003 | |
1004 my $string; | |
1005 if ($self->driver eq 'mysql'){ | |
1006 $string = "UNIX_TIMESTAMP($column)"; | |
1007 } | |
1008 elsif ($self->driver eq 'odbc'){ | |
1009 $string = "DATEDIFF(second,'JAN 1 1970',$column)"; | |
1010 } | |
1011 else{ | |
1012 warning("Not possible to convert $column due to an unknown database driver: ", $self->driver); | |
1013 return ''; | |
1014 } | |
1015 return $string; | |
1016 } | |
1017 | |
1018 | |
1019 =head2 from_seconds_to_date | |
1020 | |
1021 Arg [1] : int $seconds | |
1022 Example : my $string = $dbc->from_seconds_to_date($seconds); | |
1023 Description: Giving an int representing number of seconds | |
1024 applies the database function to convert to a date | |
1025 Returntype : string | |
1026 Exceptions : none | |
1027 Caller : general | |
1028 Status : at risk | |
1029 | |
1030 =cut | |
1031 | |
1032 sub from_seconds_to_date{ | |
1033 my $self= shift; | |
1034 my $seconds = shift; | |
1035 | |
1036 my $string; | |
1037 if ($self->driver eq 'mysql'){ | |
1038 if ($seconds){ | |
1039 $string = "from_unixtime( ".$seconds.")"; | |
1040 } | |
1041 else{ | |
1042 $string = "\"0000-00-00 00:00:00\""; | |
1043 } | |
1044 } | |
1045 elsif ($self->driver eq 'odbc'){ | |
1046 if ($seconds){ | |
1047 $string = "DATEDIFF(date,'JAN 1 1970',$seconds)"; | |
1048 } | |
1049 else{ | |
1050 $string = "\"0000-00-00 00:00:00\""; | |
1051 } | |
1052 } | |
1053 else{ | |
1054 warning("Not possible to convert $seconds due to an unknown database driver: ", $self->driver); | |
1055 return ''; | |
1056 | |
1057 } | |
1058 return $string; | |
1059 } | |
1060 | |
1061 =head2 sql_helper | |
1062 | |
1063 Example : my $h = $dbc->sql_helper(); | |
1064 Description: Lazy generated instance of L<Bio::EnsEMBL::Utils::SqlHelper> | |
1065 which provides useful wrapper methods for interacting with a | |
1066 DBConnection instance. | |
1067 Returntype : Bio::EnsEMBL::Utils::SqlHelper | |
1068 Exceptions : none | |
1069 Caller : general | |
1070 Status : Stable | |
1071 | |
1072 =cut | |
1073 | |
1074 sub sql_helper { | |
1075 my ($self) = @_; | |
1076 if(! exists $self->{_sql_helper}) { | |
1077 my $helper = Bio::EnsEMBL::Utils::SqlHelper->new(-DB_CONNECTION => $self); | |
1078 $self->{_sql_helper} = $helper; | |
1079 } | |
1080 return $self->{_sql_helper}; | |
1081 } | |
1082 | |
1083 #### | |
1084 #deprecated functions | |
1085 #### | |
1086 | |
1087 =head2 group | |
1088 | |
1089 group is no longer available in DBConnection and should be accessed if needed | |
1090 from an adaptor. | |
1091 | |
1092 =cut | |
1093 | |
1094 sub group { | |
1095 my ($self, $arg ) = @_; | |
1096 ( defined $arg ) && | |
1097 ( $self->{_group} = $arg ); | |
1098 deprecate "group should not be called from DBConnection but from an adaptor\n"; | |
1099 return $self->{_group}; | |
1100 } | |
1101 | |
1102 =head2 species | |
1103 | |
1104 species is no longer available in DBConnection and should be accessed if needed | |
1105 from an adaptor. | |
1106 | |
1107 =cut | |
1108 | |
1109 sub species { | |
1110 my ($self, $arg ) = @_; | |
1111 ( defined $arg ) && | |
1112 ( $self->{_species} = $arg ); | |
1113 deprecate "species should not be called from DBConnection but from an adaptor\n"; | |
1114 return $self->{_species}; | |
1115 } | |
1116 | |
1117 1; |