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;