0
|
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;
|