3 See the NOTICE file distributed with
this work
for additional information
4 regarding copyright ownership.
6 Licensed under the Apache License, Version 2.0 (the
"License");
7 you may not use
this file except in compliance with the License.
8 You may obtain a copy of the License at
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an
"AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License
for the specific language governing permissions and
16 limitations under the License.
23 Please email comments or questions to the
public Ensembl
24 developers list at <http:
26 Questions may also be sent to the Ensembl help desk at
40 -host =>
'ensembldb.ensembl.org',
47 my $analysis = $analysis_adaptor->fetch_by_logic_name(
'genscan');
51 Module to encapsulate all db access
for persistent
class Analysis.
52 There should be just one per application and database connection.
59 package Bio::EnsEMBL::DBSQL::AnalysisAdaptor;
76 internally loads and caches all the
Analysis objects from the
86 my ($class, $db) = @_;
88 my $self = $class->SUPER::new($db);
90 #load and cache all of the Analysis objects
100 Example : my @analysis = @{$analysis_adaptor->fetch_all()};
101 Description: fetches all of the
Analysis objects from the database and caches
105 Caller : AnalysisAdaptor::new
112 my ( $analysis, $dbID );
115 $self->{_cache} = {};
116 $self->{_logic_name_cache} = {};
118 my $sth = $self->prepare( q {
119 SELECT analysis.analysis_id, logic_name,
120 program, program_version, program_file,
121 db, db_version, db_file,
122 module, module_version,
123 gff_source, gff_feature,
124 created, parameters, description, display_label, displayable, web_data
126 LEFT JOIN analysis_description
127 ON analysis.analysis_id = analysis_description.analysis_id } );
130 while( $rowHashRef = $sth->fetchrow_hashref ) {
131 my $analysis = $self->_objFromHashref( $rowHashRef );
133 $self->{_cache}->{$analysis->dbID} = $analysis;
134 $self->{_logic_name_cache}->{lc($analysis->logic_name())} = $analysis;
137 my @ana = values %{$self->{_cache}};
143 =head2 fetch_all_by_feature_class
145 Arg [1] :
string $feature_cless - The name of the feature
class
146 Example : my @analyses = @{$analysis_adaptor->fetch_all_by_feature_class(
'Gene');
147 Description: Returns all analyses that correspond to a given
148 feature
class; see feature_classes method
for a list.
156 sub fetch_all_by_feature_class {
158 my $feat_class = shift ||
throw(
"Need a feature type, e.g. SimpleFeature" );
160 # Need a special case for density
161 # DensityFeature is the feature, but the analysis is linked to the DensityType
162 if ($feat_class =~ /Density/) {
163 $feat_class =
'DensityType';
166 my $adaptor = $self->db->get_adaptor($feat_class);
168 throw(
"$feat_class is not a know feature. No adaptor found");
171 # Check that feature has an analysis
172 my $has_analysis = 0;
173 my @columns = $adaptor->_columns;
174 foreach my $column (@columns) {
175 if ($column =~ /analysis/) {
180 if ($has_analysis == 0) {
181 throw(
"$feat_class does not have an analysis column");
184 # Retrieve the name of the table
185 my @tables = $adaptor->_tables();
186 my $table = $tables[0]->[0];
189 SELECT DISTINCT analysis_id FROM %s |;
191 my $sql = sprintf( $sql_t, $table );
192 my $sth = $self->prepare( $sql );
193 my $rv = $sth->execute();
194 my $res = $sth->fetchall_arrayref;
196 foreach my $r( @{$res} ){
197 my $analysis = $self->fetch_by_dbID($r->[0])
198 ||
throw(
"analysis_id $r->[0] from $table table "
199 .
"is not in the analysis table!" );
200 push @analyses, $analysis;
207 Arg [1] :
int $internal_analysis_id - the database
id of the analysis
209 Example : my $analysis = $analysis_adaptor->fetch_by_dbID(1);
210 Description: Retrieves an Analysis
object from the database via its
internal
223 if( defined $self->{_cache}->{$id} ) {
224 return $self->{_cache}->{$id};
228 SELECT analysis.analysis_id, logic_name,
229 program, program_version, program_file,
230 db, db_version, db_file,
231 module, module_version,
232 gff_source, gff_feature,
233 created, parameters, description, display_label, displayable, web_data
235 LEFT JOIN analysis_description
236 ON analysis.analysis_id = analysis_description.analysis_id
237 WHERE analysis.analysis_id = ? };
239 my $sth = $self->prepare($query);
240 $sth->bind_param(1,$id,SQL_INTEGER);
242 my $rowHashRef = $sth->fetchrow_hashref;
243 if( ! defined $rowHashRef ) {
247 my $anal = $self->_objFromHashref( $rowHashRef );
248 $self->{_cache}->{$anal->dbID} = $anal;
249 $self->{_logic_name_cache}->{lc($anal->logic_name())} = $anal;
254 =head2 fetch_by_logic_name
256 Arg [1] :
string $logic_name the logic name of the analysis to retrieve
257 Example : my $analysis = $a_adaptor->fetch_by_logic_name(
'Eponine');
258 Description: Retrieves an analysis
object from the database
using its unique
267 sub fetch_by_logic_name {
268 my ( $self, $logic_name ) = @_;
273 # Check the cache for the logic name
274 if ( defined( $self->{_logic_name_cache}{ lc($logic_name) } ) ) {
275 return $self->{_logic_name_cache}{ lc($logic_name) };
278 my $sth = $self->prepare(
280 SELECT analysis.analysis_id,
299 LEFT JOIN analysis_description
300 ON ( analysis.analysis_id = analysis_description.analysis_id )
301 WHERE LOWER(logic_name) = ?)
304 $sth->bind_param( 1, lc($logic_name), SQL_VARCHAR );
306 my $rowHashRef = $sth->fetchrow_hashref();
308 if ( !defined($rowHashRef) ) {
return }
310 $analysis = $self->_objFromHashref($rowHashRef);
312 # place the analysis in the caches, cross referenced by dbID and
314 $self->{_cache}->{ $analysis->dbID() } = $analysis;
315 $self->{_logic_name_cache}->{ lc($logic_name) } = $analysis;
318 } ## end sub fetch_by_logic_name
323 Arg [1] :
Bio:EnsEMBL::Analysis $analysis
324 Example : $analysis_adaptor->store($analysis);
325 Description: Stores $analysis in db. If the analysis is already stored in
326 the database its dbID and adaptor are updated, but the analysis
327 is not stored a second time.
328 Sets created date
if not already set. Sets dbID and adaptor
329 inside $analysis. Returns dbID.
330 Returntype :
int - dbID of stored analysis
331 Exceptions :
throw on incorrect argument
332 throw if analysis argument does not have a logic name
340 my $analysis = shift;
342 if(!ref($analysis) || !$analysis->isa(
'Bio::EnsEMBL::Analysis')) {
343 throw(
"Bio::EnsEMBL::Analysis argument expected.");
346 if($analysis->is_stored($self->db())) {
347 return $analysis->dbID();
350 if(!$analysis->logic_name()) {
351 throw(
"Analysis cannot be stored without a valid logic_name");
354 my $insert_ignore = $self->insert_ignore_clause();
356 my $rows_inserted = 0;
359 if ( $analysis->created() ) {
361 # We use insert IGNORE so that this method can be used in a
362 # multi-process environment. If another process has already written
363 # this record then there will not be a problem.
365 $sth = $self->prepare(
367 ${insert_ignore} INTO analysis
368 (created, logic_name, db, db_version, db_file, program, program_version, program_file, parameters, module, module_version, gff_source, gff_feature)
369 VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
372 $sth->bind_param( 1, $analysis->created(), SQL_DATETIME );
373 $sth->bind_param( 2, lc( $analysis->logic_name() ), SQL_VARCHAR );
374 $sth->bind_param( 3, $analysis->db(), SQL_VARCHAR );
375 $sth->bind_param( 4, $analysis->db_version(), SQL_VARCHAR );
376 $sth->bind_param( 5, $analysis->db_file(), SQL_VARCHAR );
377 $sth->bind_param( 6, $analysis->program(), SQL_VARCHAR );
378 $sth->bind_param( 7, $analysis->program_version(), SQL_VARCHAR );
379 $sth->bind_param( 8, $analysis->program_file(), SQL_VARCHAR );
380 $sth->bind_param( 9, $analysis->parameters(), SQL_VARCHAR );
381 $sth->bind_param( 10, $analysis->module(), SQL_VARCHAR );
382 $sth->bind_param( 11, $analysis->module_version(), SQL_VARCHAR );
383 $sth->bind_param( 12, $analysis->gff_source(), SQL_VARCHAR );
384 $sth->bind_param( 13, $analysis->gff_feature(), SQL_VARCHAR );
386 $rows_inserted = $sth->execute();
389 $sth = $self->prepare(
391 ${insert_ignore} INTO analysis
392 (created, logic_name, db, db_version, db_file, program, program_version, program_file, parameters, module, module_version, gff_source, gff_feature)
393 VALUES (CURRENT_TIMESTAMP, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
397 $sth->bind_param( 1, $analysis->logic_name, SQL_VARCHAR );
398 $sth->bind_param( 2, $analysis->db, SQL_VARCHAR );
399 $sth->bind_param( 3, $analysis->db_version, SQL_VARCHAR );
400 $sth->bind_param( 4, $analysis->db_file, SQL_VARCHAR );
401 $sth->bind_param( 5, $analysis->program, SQL_VARCHAR );
402 $sth->bind_param( 6, $analysis->program_version, SQL_VARCHAR );
403 $sth->bind_param( 7, $analysis->program_file, SQL_VARCHAR );
404 $sth->bind_param( 8, $analysis->parameters, SQL_VARCHAR );
405 $sth->bind_param( 9, $analysis->module, SQL_VARCHAR );
406 $sth->bind_param( 10, $analysis->module_version, SQL_VARCHAR );
407 $sth->bind_param( 11, $analysis->gff_source, SQL_VARCHAR );
408 $sth->bind_param( 12, $analysis->gff_feature, SQL_VARCHAR );
410 $rows_inserted = $sth->execute();
412 } ## end
else [
if ( $analysis->created...)]
415 # If we need to fetch the timestamp, or the insert failed due to
416 # existance of an existing entry, we need to retrieve the entry from
417 # the database. Note: $sth->execute() may return 0E0 on error which
418 # is zero, but true which is why the $rows_inserted clause was added.
419 if ( !$analysis->created() || !$rows_inserted || $rows_inserted == 0 )
422 $self->fetch_by_logic_name( $analysis->logic_name );
424 if ( !$new_analysis ) {
425 throw(
"Could not retrieve just stored analysis from database.\n"
426 .
"Possibly incorrect db permissions or missing analysis table\n"
430 $dbID = $new_analysis->dbID();
431 $analysis->created( $new_analysis->created() );
434 $dbID ||= $self->last_insert_id(
'analysis_id', undef,
'analysis');
437 # store description and display_label
438 if( defined( $analysis->description() ) || defined( $analysis->display_label() )|| defined( $analysis->web_data() )) {
439 $self->_store_description($analysis, $dbID);
443 $self->{_cache}->{$dbID} = $analysis;
444 $self->{_logic_name_cache}{lc($analysis->logic_name)} = $analysis;
446 $analysis->adaptor( $self );
447 $analysis->dbID( $dbID );
453 sub _store_description {
454 my ($self, $analysis, $dbID) = @_;
456 my $insert_ignore = $self->insert_ignore_clause();
457 my $sth = $self->prepare(
458 "${insert_ignore} INTO analysis_description (analysis_id, display_label, description, displayable, web_data) " .
462 my $display_label = $analysis->display_label();
463 $display_label =
'' unless defined $display_label; # SQLite doesn
't ignore NOT NULL errors
465 $sth->bind_param(1,$dbID,SQL_INTEGER);
466 $sth->bind_param(2,$display_label,SQL_VARCHAR);
467 $sth->bind_param(3,$analysis->description,SQL_LONGVARCHAR);
468 $sth->bind_param(4,$analysis->displayable,SQL_TINYINT);
469 $sth->bind_param(5,$analysis->web_data,SQL_LONGVARCHAR);
479 Arg [1] : Bio::EnsEMBL::Analysis $anal
480 Example : $adaptor->update($anal)
481 Description: Updates this analysis in the database
482 Returntype : int 1 if update is performed, undef if it is not
483 Exceptions : throw if arg is not an analysis object
494 throw("Expected Bio::EnsEMBL::Analysis argument.");
497 if(!$a->is_stored($self->db())) {
501 my $sth = $self->prepare
502 ("UPDATE analysis " .
503 "SET created = ?, logic_name = ?, db = ?, db_version = ?, db_file = ?, ".
504 " program = ?, program_version = ?, program_file = ?, ".
505 " parameters = ?, module = ?, module_version = ?, ".
506 " gff_source = ?, gff_feature = ? " .
507 "WHERE analysis_id = ?");
511 $sth->bind_param(1,$a->created,SQL_DATETIME);
512 $sth->bind_param(2,$a->logic_name,SQL_VARCHAR);
513 $sth->bind_param(3,$a->db,SQL_VARCHAR);
514 $sth->bind_param(4,$a->db_version,SQL_VARCHAR);
515 $sth->bind_param(5,$a->db_file,SQL_VARCHAR);
516 $sth->bind_param(6,$a->program,SQL_VARCHAR);
517 $sth->bind_param(7,$a->program_version,SQL_VARCHAR);
518 $sth->bind_param(8,$a->program_file,SQL_VARCHAR);
519 $sth->bind_param(9,$a->parameters,SQL_VARCHAR);
520 $sth->bind_param(10,$a->module,SQL_VARCHAR);
521 $sth->bind_param(11,$a->module_version,SQL_VARCHAR);
522 $sth->bind_param(12,$a->gff_source,SQL_VARCHAR);
523 $sth->bind_param(13,$a->gff_feature,SQL_VARCHAR);
524 $sth->bind_param(14,$a->dbID,SQL_INTEGER);
530 # also update description & display label - may need to create these if
532 $sth = $self->prepare("SELECT description FROM analysis_description WHERE analysis_id= ?");
533 $sth->execute($a->dbID);
534 if ($sth->fetchrow_hashref) { # update if exists
535 $sth = $self->prepare
536 ("UPDATE analysis_description SET description = ?, display_label = ?, displayable = ?, web_data = ? WHERE analysis_id = ?");
537 $sth->bind_param(1,$a->description,SQL_LONGVARCHAR);
538 $sth->bind_param(2,$a->display_label(),SQL_VARCHAR);
539 $sth->bind_param(3,$a->displayable,SQL_TINYINT);
540 $sth->bind_param(4,$a->web_data,SQL_LONGVARCHAR);
541 $sth->bind_param(5,$a->dbID,SQL_INTEGER);
544 } else { # create new entry
546 if( $a->description() || $a->display_label() || $a->web_data) {
547 $self->_store_description($a, $a->dbID);
555 # the logic_name cache needs to be re-updated now, since we may have just
556 # changed the logic_name
566 Arg [1] : Bio::EnsEMBL::Analysis $anal
567 Example : $adaptor->remove($anal)
568 Description: Removes this analysis from the database. This is not really
569 safe to execute in a multi process environment, so programs
570 should not remove analysis while out on the farm.
572 Exceptions : thrown if $anal arg is not an analysis object
579 my ($self, $analysis) = @_;
581 if (!defined $analysis || !ref $analysis) {
582 throw("called remove on AnalysisAdaptor with a [$analysis]");
585 if(!$analysis->is_stored($self->db())) {
589 my $sth = $self->prepare("DELETE FROM analysis WHERE analysis_id = ?");
590 $sth->bind_param(1,$analysis->dbID,SQL_INTEGER);
593 $sth = $self->prepare("DELETE FROM analysis_description WHERE analysis_id = ?");
594 $sth->execute($analysis->dbID());
596 # remove this analysis from the cache
597 delete $self->{'_cache
'}->{$analysis->dbID()};
598 delete $self->{'_logic_name_cache
'}->{lc($analysis->logic_name)};
601 # unset the adaptor and dbID
602 $analysis->dbID(undef);
603 $analysis->adaptor(undef);
612 Arg [1] : Bio::EnsEMBL::Analysis $anal
613 Example : if($adaptor->exists($anal)) #do something
614 Description: Tests whether this Analysis already exists in the database
615 by checking first if the adaptor and dbID are set and
616 secondly by whether it is in this adaptors internal cache.
617 Note that this will not actually check the database and will
618 not find and analysis which were recently added by other
619 processes. You are better off simply trying to store an
620 analysis which will reliably ensure that it is not stored twice
622 Returntype : int dbID if analysis is found, otherwise returns undef
623 Exceptions : thrown if $anal arg is not an analysis object
630 my ($self,$anal) = @_;
632 if(!ref($anal) || !$anal->isa("Bio::EnsEMBL::Analysis")) {
633 throw("Object is not a Bio::EnsEMBL::Analysis");
636 #if this analysis is stored in this db already return its dbID
637 if($anal->is_stored($self->db())) {
638 return $anal->dbID();
641 #this analysis object is not stored but one exactly like it may have been
642 foreach my $cacheId (keys %{$self->{_cache}}) {
643 if ($self->{_cache}->{$cacheId}->compare($anal) >= 0) {
644 # $anal->dbID( $cacheId );
645 # $anal->adaptor( $self );
650 #no analysis like this one exists in the database
655 =head2 _objFromHashref
657 Arg [1] : hashref $rowHash
658 Description: Private helper function generates an Analysis object from a
659 mysql row hash reference.
660 Returntype : Bio::EnsEMBL::Analysis
662 Caller : Bio::EnsEMBL::DBSQL::AnalsisAdaptor::fetch_* methods
667 sub _objFromHashref {
671 return Bio::EnsEMBL::Analysis->new_fast({
672 dbID => $h->{analysis_id},
675 _db_file => $h->{db_file},
676 _db_version => $h->{db_version},
677 _program => $h->{program},
678 _program_version => $h->{program_version},
679 _program_file => $h->{program_file},
680 _gff_source => $h->{gff_source},
681 _gff_feature => $h->{gff_feature},
682 _module => $h->{module},
683 _module_version => $h->{module_version},
684 _parameters => $h->{parameters},
685 _created => $h->{created},
686 _logic_name => $h->{logic_name},
687 _description => $h->{description},
688 _display_label => $h->{display_label},
689 _displayable => $h->{displayable},
690 _web_data => $h->{web_data},