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.
24 Please email comments or questions to the
public Ensembl
25 developers list at <http:
27 Questions may also be sent to the Ensembl help desk at
38 # base adaptor provides
40 # SQL prepare function
41 $adaptor->
prepare(
"sql statement");
43 # get of root DBAdaptor object
46 # constructor, ok for inheritence
47 $adaptor = Bio::EnsEMBL::DBSQL::SubClassOfBaseAdaptor->new($dbobj);
51 This is a
true base
class for Adaptors in the Ensembl DBSQL
54 Adaptors are expected to have the following functions
56 $obj = $adaptor->fetch_by_dbID($internal_id);
58 which builds the
object from the primary key of the
object. This
59 function is crucial because it allows adaptors to collaborate relatively
60 independently of each other - in other words, we can change the schema
61 under one adaptor without too many knock on changes through the other
64 Most adaptors will also have
66 $dbid = $adaptor->store($obj);
68 which stores the
object. Currently the storing of an
object also causes
73 correctly and attach the adaptor.
75 Other fetch functions go by the convention of
77 @object_array = @{ $adaptor->fetch_all_by_XXXX($arguments_for_XXXX) };
79 sometimes it returns an array ref denoted by the
'all' in the name of
80 the method, sometimes an individual
object. For example
82 $gene = $gene_adaptor->fetch_by_stable_id($stable_id);
86 @fp = @{ $simple_feature_adaptor->fetch_all_by_Slice($slice) };
88 Occassionally adaptors need to provide access to lists of ids. In
this
89 case the convention is to go list_XXXX, such as
91 @gene_ids = @{ $gene_adaptor->list_geneIds() };
93 (note:
this method is poorly named)
100 use vars qw(@ISA @EXPORT);
105 use DBI qw(:sql_types);
107 use Scalar::Util qw/looks_like_number/;
110 @EXPORT = (@{$DBI::EXPORT_TAGS{
'sql_types'}});
115 Example : $adaptor =
new AdaptorInheritedFromBaseAdaptor($dbobj);
116 Description: Creates a
new BaseAdaptor
object. The intent is that
this
117 constructor would be called by an inherited superclass either
118 automatically or through $self->SUPER::new in an overridden
128 my ( $class, $dbobj ) = @_;
130 my $self = bless {}, $class;
132 if ( !defined $dbobj || !ref $dbobj ) {
133 throw(
"Don't have a db [$dbobj] for new adaptor");
136 if ( $dbobj->isa(
'Bio::EnsEMBL::DBSQL::DBAdaptor') ) {
138 $self->dbc( $dbobj->dbc );
139 $self->species_id( $dbobj->species_id() );
140 $self->is_multispecies( $dbobj->is_multispecies() );
141 } elsif ( ref($dbobj) =~ /DBAdaptor$/ ) {
143 $self->dbc( $dbobj->dbc );
144 } elsif ( ref($dbobj) =~ /DBConnection$/ ) {
147 throw(
"Don't have a DBAdaptor [$dbobj] for new adaptor");
156 Arg [1] :
string $string
157 a SQL query to be prepared by
this adaptors database
158 Example : $sth = $adaptor->
prepare(
"select yadda from blabla")
159 Description: provides a DBI statement handle from the adaptor. A convenience
160 function so you dont have to write $adaptor->db->prepare all the
162 Returntype : DBI::StatementHandle
164 Caller : Adaptors inherited from BaseAdaptor
170 my ( $self, $string ) = @_;
172 # Uncomment next line to cancel caching on the SQL side.
173 # Needed for timing comparisons etc.
174 #$string =~ s/SELECT/SELECT SQL_NO_CACHE/i;
176 return $self->dbc->prepare($string);
183 the database
this adaptor is
using.
184 Example : $db = $adaptor->db();
185 Description: Getter/Setter
for the DatabaseConnection that
this adaptor is
189 Caller : Adaptors inherited from BaseAdaptor
195 my ( $self, $value ) = @_;
197 if ( defined($value) ) {
198 $self->{
'db'} = $value;
201 return $self->{
'db'};
207 the database
this adaptor is
using.
208 Example : $db = $adaptor->db();
209 Description: Getter/Setter
for the DatabaseConnection that
this adaptor is
213 Caller : Adaptors inherited from BaseAdaptor
219 my ( $self, $value ) = @_;
221 if ( defined($value) ) {
222 $self->{
'dbc'} = $value;
225 return $self->{
'dbc'};
228 =head2 is_multispecies
230 Arg [1] : (optional)
boolean $arg
231 Example :
if ($adaptor->is_multispecies()) { }
232 Description: Getter/Setter
for the is_multispecies
boolean of
233 to use
for this adaptor.
241 sub is_multispecies {
242 my ( $self, $arg ) = @_;
244 if ( defined($arg) ) {
245 $self->{_is_multispecies} = $arg;
248 return $self->{_is_multispecies};
253 Arg [1] : (optional)
int $species_id
254 The
internal ID of the species in a multi-species database.
255 Example : $db = $adaptor->db();
256 Description: Getter/Setter
for the
internal ID of the species in a
257 multi-species database. The
default species ID is 1.
260 Caller : Adaptors inherited from BaseAdaptor
266 my ( $self, $value ) = @_;
268 if ( defined($value) ) {
269 $self->{
'species_id'} = $value;
272 return $self->{
'species_id'} || 1;
276 # list primary keys for a particular table
277 # args are table name and primary key field
278 # if primary key field is not supplied, tablename_id is assumed
279 # returns listref of IDs
281 my ( $self, $table, $pk, $ordered ) = @_;
283 if ( !defined($pk) ) { $pk = $table .
"_id" }
285 my $sql = sprintf(
"SELECT `%s` FROM `%s`", $pk, $table );
287 my $join_with_cs = 0;
288 if ( $self->is_multispecies()
289 && $self->isa(
'Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor')
290 && !$self->isa(
'Bio::EnsEMBL::DBSQL::UnmappedObjectAdaptor') )
294 JOIN seq_region USING (seq_region_id)
295 JOIN coord_system cs USING (coord_system_id)
296 WHERE cs.species_id = ?
302 if ( defined($ordered) && $ordered ) {
303 $sql .=
" ORDER BY seq_region_id, seq_region_start";
306 my $sth = $self->prepare($sql);
309 $sth->bind_param( 1, $self->species_id(), SQL_INTEGER );
312 eval { $sth->execute() };
314 throw(
"Detected an error whilst executing SQL '${sql}': $@");
318 $sth->bind_col( 1, \$id );
321 while ( $sth->fetch() ) {
326 } ## end sub _list_dbIDs
331 # Arg [1] : (optional) boolean $new_val
332 # Example : $self->_straight_join(1);
333 # $self->generic_fetch($constraint);
334 # $self->_straight_join(0);
335 # Description: PROTECTED Getter/Setter that turns on/off the use of
336 # a straight join in queries.
337 # Returntype : boolean
344 $self->{
'_straight_join'} = shift;
347 return $self->{
'_straight_join'};
350 sub _can_straight_join {
352 return $self->dbc->_driver_object->can_straight_join;
355 =head2 bind_param_generic_fetch
357 Arg [1] : (optional) scalar $param
358 This is the parameter to bind
359 Arg [2] : (optional)
int $sql_type
360 Type of the parameter (from DBI (:sql_types))
361 Example : $adaptor->bind_param_generic_fetch($stable_id,SQL_VARCHAR);
362 $adaptor->generic_fetch();
363 Description: When
using parameters
for the query, will call the bind_param to avoid
364 some security issues. If there are no arguments, will
return the bind_parameters
366 Exceptions:
if called with one argument
370 sub bind_param_generic_fetch{
373 my $sql_type = shift;
375 if (defined $param && !defined $sql_type){
376 throw(
"Need to specify sql_type for parameter $param\n");
378 elsif (defined $param && defined $sql_type){
379 #check when there is a SQL_INTEGER type that the parameter is really a number
380 if ($sql_type eq SQL_INTEGER){
381 throw "Trying to assign a non numerical parameter to an integer value in the database" if ($param !~ /^[+-]{0,1}\d+$/);
383 #both paramters have been entered, push it to the bind_param array
384 push @{$self->{
'_bind_param_generic_fetch'}},[$param,$sql_type];
386 elsif (!defined $param && !defined $sql_type){
387 #when there are no arguments, return the array
388 return $self->{
'_bind_param_generic_fetch'};
393 # Used to reset the params without circumventing scope
394 sub _bind_param_generic_fetch {
395 my ($self, $_bind_param_generic_fetch) = @_;
396 $self->{
'_bind_param_generic_fetch'} = $_bind_param_generic_fetch
if $_bind_param_generic_fetch;
397 return $self->{_bind_param_generic_fetch};
400 =head2 generate_in_constraint
402 Arg [1] : ArrayRef or Scalar $list
403 List or a single value of items to be pushed into an IN statement
404 Arg [2] : Scalar $column
405 Column
this IN statement is being applied to. Please fully resolve the
407 Arg [3] : Scalar $param_type
408 Data type which should be used when binding. Please use DBI data type symbols
409 Arg [4] : Scalar
boolean $inline_variables
410 Boolean to control
if variables are inlined in the constraint. If
411 false values are bound via bind_param_generic_fetch() (the
default behaviour).
413 Description : Used internally to generate a SQL constraint to restrict a query by an IN statement.
414 The code generates the complete IN statement.
416 Exceptions : If no list is supplied, the list of values is empty or no data type was given
421 sub generate_in_constraint {
422 my ($self, $list, $column, $param_type, $inline_variables) = @_;
423 throw(
"A list of values must be given")
if ! defined $list;
424 $list = wrap_array($list); # homogenise into an array
425 throw "We should be given at least one value to insert" if scalar(@{$list}) == 0;
426 throw "Please supply the DBI param type" if ! defined $param_type;
427 #Figure out if we need to quote our values if we are asked to inline the variables
428 my $quote_values = 1;
429 if($param_type == SQL_INTEGER || $param_type == SQL_TINYINT || $param_type == SQL_DOUBLE ) {
433 my $constraint = qq{${column} IN (};
434 if($inline_variables) {
436 $constraint .= join(q{,},
map { qq{
"${_}"} } @{$list});
439 $constraint .= join(q{,}, @{$list});
443 my @subs = (
'?') x scalar(@{$list});
444 $constraint .= join(q{,}, @subs);
445 $self->bind_param_generic_fetch($_, $param_type)
for @{$list};
453 Arg [1] : (optional)
string $constraint
454 An SQL query constraint (i.e. part of the WHERE clause)
456 A mapper
object used to remap features
457 as they are retrieved from the database
459 A slice that features should be remapped to
460 Example : $fts = $a->generic_fetch(
'contig_id in (1234, 1235)');
461 Description: Performs a database fetch and returns feature objects in
464 Exceptions : Thrown
if there is an issue with querying the data
465 Caller : BaseFeatureAdaptor, ProxyDnaAlignFeatureAdaptor::generic_fetch
471 my ($self, $constraint, $mapper, $slice) = @_;
472 my $sql = $self->_generate_sql($constraint);
473 my $params = $self->bind_param_generic_fetch();
475 $self->{_bind_param_generic_fetch} = undef;
476 my $sth = $self->db()->dbc()->prepare($sql);
478 foreach my $param (@{$params}){
479 $sth->bind_param($i,$param->[0],$param->[1]);
482 eval { $sth->execute() };
484 throw(
"Detected an error whilst executing SQL '${sql}': $@");
487 my $res = $self->_objs_from_sth($sth, $mapper, $slice);
494 Arg [1] : (optional)
string $constraint
495 An SQL query constraint (i.e. part of the WHERE clause)
496 Example : $number_feats = $a->generic_count(
'contig_id in (1234, 1235)');
497 Description: Performs a database fetch and returns a count of those features
498 found. This is analagous to C<generic_fetch()>
499 Returntype : Integer count of the elements.
500 Exceptions : Thrown
if there is an issue with querying the data
505 my ($self, $constraint) = @_;
506 my $sql = $self->_generate_sql($constraint,
'count(*)');
507 my $params = $self->bind_param_generic_fetch();
509 $self->{_bind_param_generic_fetch} = undef;
510 my $h = $self->db()->dbc()->sql_helper();
511 my $count = $h->execute_single_result(-SQL => $sql, -PARAMS => $params);
516 my ($self, $constraint, @input_columns) = @_;
518 my @tabs = $self->_tables();
520 my $extra_default_where;
522 # Hack for feature types that needs to be restricted to species_id (in
524 if ( $self->is_multispecies()
525 && $self->isa(
'Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor')
526 && !$self->isa(
'Bio::EnsEMBL::DBSQL::BaseAlignFeatureAdaptor')
527 && !$self->isa(
'Bio::EnsEMBL::DBSQL::UnmappedObjectAdaptor') )
529 # We do a check to see if there is already seq_region
530 # and coord_system defined to ensure we get the right
531 # alias. We then do the extra query irrespectively of
532 # what has already been specified by the user.
533 my %thash =
map { $_->[0] => $_->[1] } @tabs;
536 ( exists( $thash{seq_region} ) ? $thash{seq_region} :
'sr' );
538 ( exists( $thash{coord_system} ) ? $thash{coord_system} :
'cs' );
540 if ( !exists( $thash{seq_region} ) ) {
541 push( @tabs, [
'seq_region', $sr_alias ] );
543 if ( !exists( $thash{coord_system} ) ) {
544 push( @tabs, [
'coord_system', $cs_alias ] );
547 $extra_default_where = sprintf(
548 '%s.seq_region_id = %s.seq_region_id '
549 .
'AND %s.coord_system_id = %s.coord_system_id '
550 .
'AND %s.species_id = ?',
551 $tabs[0]->[1], $sr_alias, $sr_alias,
552 $cs_alias, $cs_alias );
554 $self->bind_param_generic_fetch( $self->species_id(), SQL_INTEGER );
555 } ## end
if ( $self->is_multispecies...)
557 @input_columns = $self->_columns()
if ! @input_columns;
558 my $columns = join(
', ', @input_columns);
561 # Construct a left join statement if one was defined, and remove the
562 # left-joined table from the table list
564 my @left_join_list = $self->_left_join();
565 my $left_join_prefix =
'';
568 if(@left_join_list) {
569 my %left_join_hash =
map { $_->[0] => $_->[1] } @left_join_list;
570 while(my $t = shift @tabs) {
571 my $t_alias = $t->[0] .
" " . $t->[1];
572 if( exists $left_join_hash{ $t->[0] } || exists $left_join_hash{$t_alias}) {
573 my $condition = $left_join_hash{ $t->[0] };
574 $condition ||= $left_join_hash{$t_alias};
577 "\n LEFT JOIN " . $t->[0] .
" $syn ON $condition ) ";
578 $left_join_prefix .=
'(';
587 my $straight_join =
'';
589 if($self->_straight_join() and $self->_can_straight_join) {
590 $straight_join =
"STRAIGHT_JOIN";
593 #construct a nice table string like 'table1 t1, table2 t2'
594 my $tablenames = join(
', ',
map({ join(
' ', @$_) } @tables));
597 "SELECT $straight_join $columns \n"
598 .
"FROM $left_join_prefix ($tablenames) $left_join";
600 my $default_where = $self->_default_where_clause();
601 my $final_clause = $self->_final_clause;
603 if ($extra_default_where) {
604 if ($default_where) {
605 $default_where .=
"\n AND $extra_default_where";
607 $default_where = $extra_default_where;
611 #append a where clause if it was defined
613 $sql .=
"\n WHERE $constraint ";
614 if ($default_where) {
615 $sql .=
" AND\n $default_where ";
617 } elsif ($default_where) {
618 $sql .=
"\n WHERE $default_where ";
621 #append additional clauses which may have been defined, don't append ORDER BY twice
622 if (index($final_clause,
"ORDER") == -1 || index($sql,
"ORDER") == -1) {
623 $sql .=
"\n$final_clause";
627 #printf(STDERR "SQL:\n%s\n", $sql);
636 The unique database identifier
for the feature to be obtained
637 Example : $feat = $adaptor->fetch_by_dbID(1234));
638 $feat = $feat->transform(
'contig');
639 Description: Returns the feature created from the database defined by the
640 the
id $id. The feature will be returned in its native
641 coordinate system. That is, the coordinate system in which it
642 is stored in the database. In order to convert it to a
643 particular coordinate system use the transfer() or transform()
644 method. If the feature is not found in the database then
645 undef is returned instead
647 Exceptions : thrown if $id arg is not provided
655 my ($self, $id) = @_;
656 if ($self->_no_id_cache()) {
657 return $self->_uncached_fetch_by_dbID($id);
659 return $self->_id_cache()->get($id);
662 # The actual implmenetation moved sideways to allow for uncached access
663 # otherwise we'd constantly loop
665 sub _uncached_fetch_by_dbID{
668 throw(
"id argument is required")
if(!defined $id);
670 #construct a constraint like 't1.table1_id = 123'
671 my @tabs = $self->_tables;
672 my ($name, $syn) = @{$tabs[0]};
673 $self->bind_param_generic_fetch($id,SQL_INTEGER);
674 my $constraint =
"${syn}.${name}_id = ?";
677 my ($feat) = @{$self->generic_fetch($constraint)};
685 =head2 fetch_all_by_dbID_list
687 Arg [1] : listref of integers $id_list
688 The unique database identifiers
for the features to
691 Example : @feats = @{$adaptor->fetch_all_by_dbID_list([1234, 2131, 982]))};
692 Description: Returns the features created from the database
693 defined by the the IDs in contained in the provided
694 ID list $id_list. The features will be returned
695 in their native coordinate system. That is, the
696 coordinate system in which they are stored in the
697 database. In order to convert the features to a
698 particular coordinate system use the transfer() or
699 transform() method. If none of the features are
700 found in the database a reference to an empty list is
702 Returntype : listref of
Bio::
EnsEMBL::Features
703 Exceptions : thrown if $id arg is not provided
710 sub fetch_all_by_dbID_list {
711 my ($self, $id_list_ref, $slice) = @_;
712 if ($self->_no_id_cache()) {
713 return $self->_uncached_fetch_all_by_dbID_list($id_list_ref, $slice);
715 return $self->_id_cache()->get_by_list($id_list_ref, $slice);
718 # The actual implmenetation moved sideways to allow for uncached access
719 # otherwise we'd constantly loop
720 sub _uncached_fetch_all_by_dbID_list {
721 my ( $self, $id_list_ref, $slice ) = @_;
722 return $self->_uncached_fetch_all_by_id_list($id_list_ref, $slice,
"dbID", 1);
723 } ## end sub fetch_all_by_dbID_list
725 =head2 _uncached_fetch_all_by_id_list
727 Arg [1] : listref of IDs
729 A slice that features should be remapped to
730 Arg [3] : String describing the ID type.
731 Valid values include dbID and stable_id. dbID is an alias
for
732 the primary key,
while other names
map directly to table columns
733 of the Feature
this adaptor manages.
734 Arg [4] : Boolean $numeric
735 Indicates
if the incoming data is to be processed as a numeric
736 or as a String. If arg [3] was set to dbID then we
default this to
737 be
true. If arg [3] was set to stable_id then we
default this to
739 When not
using a standard arg[3] the IDs are assumed to be Strings.
740 Arg [5] : Integer $max_size
741 Control the maximum number of IDs sent to a database in a single
742 query. Defaults to 2K
for Strings and 16K
for integers. Only
743 provide
if you know *exactly* why you need to edit it.
744 Example : $list_of_features = $adaptor->_uncached_fetch_all_by_id_list(
745 [qw(ENSG00000101321 ENSG00000101346 ENSG00000101367)],
747 "stable_id", 0); #
using strings
749 # Numeric set to true because we are using numerics
750 $list_of_features = $adaptor->_uncached_fetch_all_by_id_list(
755 # Numeric defaults to true because we are querying using dbID
756 $list_of_features = $adaptor->_uncached_fetch_all_by_id_list(
760 Description: This is a
generic method used to fetch lists of features by IDs.
761 It avoids caches, meaning it is best suited
for block fetching.
762 See fetch_all_by_dbID_list() for more
info.
763 Returntype : ArrayRef of
Bio::
EnsEMBL::Feature
764 Exceptions : Thrown if a list of IDs is not supplied.
765 Caller : BaseFeatureAdaptor, BaseAdaptor and derived classes.
769 sub _uncached_fetch_all_by_id_list {
770 my ( $self, $id_list_ref, $slice, $id_type, $numeric, $max_size ) = @_;
772 if ( !defined($id_list_ref) || ref($id_list_ref) ne
'ARRAY' ) {
773 throw(
"id_list list reference argument is required");
776 if ( !@{$id_list_ref} ) {
return [] }
778 # Construct a constraint like 't1.table1_id = 123'
779 my @tabs = $self->_tables();
780 my ( $name, $syn ) = @{ $tabs[0] };
782 # prepare column name for query. If the id_type was
783 # set to dbID then we assume the column must be
784 # tablename_id e.g. gene_id. Otherwise we assume the id_type
785 # is the field/column name
787 if($id_type eq
'dbID') {
788 $field_name = $name.
'_id';
789 # If numeric was not set default it to 1 since this is an int
790 $numeric = 1
if ! defined $numeric;
792 elsif($id_type eq
'stable_id') {
793 # If numeric was not set default it to 0 since this is a string
794 $numeric = 0
if ! defined $numeric;
795 $field_name = $id_type;
798 $field_name = $id_type;
803 # Ensuring we do not exceed MySQL's max_allowed_packet (defaults to 1MB)
804 # by splitting large queries into smaller queries of at most 256KB
805 # (262,144 8-bit characters)
806 # If we had a numeric then really we are talking about working with
807 # integers. Normal max ensembl id size is 12 plus 2 characters for
808 # commas in our IN statement comes to 14. Even bloating this to 16 gives
809 # a max number of 16,384 IDs (262114/16).
812 my $first_id = $id_list_ref->[0];
813 if(!looks_like_number($first_id)) {
814 throw "You specified that we are looking for numerics but $first_id is not a numeric";
816 $max_size = 16384
if ! defined $max_size;
817 $sql_data_type = SQL_INTEGER;
819 # However when dealing with Strings those can be very large (assuming
820 # 128 is the max length of a stable ID). 128 is 8x smaller than our
821 # previous max expected integer so we reduce the max ids by 8. This gives
824 $max_size = 2048
if ! defined $max_size;
825 $sql_data_type = SQL_VARCHAR;
828 # build up unique id list, also validate on the way by
830 for (@{$id_list_ref}) {
833 my @id_list = keys %id_list;
841 if ( scalar(@id_list) > $max_size ) {
842 @ids = splice( @id_list, 0, $max_size );
848 # Push off to our IN statement constructor for this work
849 my $constraint = $self->generate_in_constraint(\@ids,
"${syn}.${field_name}", $sql_data_type, $inline);
850 push @out, @{ $self->generic_fetch($constraint, undef, $slice) };
856 # might not be a good idea, but for convenience
857 # shouldnt be called on the BIG tables though
861 return $self->generic_fetch();
864 =head2 last_insert_id
866 Arg [1] : (optional) $field the name of the field the inserted ID was pushed
868 Arg [2] : (optional) HashRef used to pass extra attributes through to the
870 Arg [3] : (optional) $table the name of the table to use
if the adaptor
871 does not implement C<_tables()>
872 Description : Delegating method which uses DBI to extract the last inserted
873 identifier. If
using MySQL we just call the DBI method
874 L<DBI::last_insert_id()> since MySQL ignores any extra
875 arguments. See L<DBI>
for more information
about this
877 Example : my $id = $self->last_insert_id(
'my_id'); my $other_id = $self->last_insert_id();
878 Returntype : Scalar or undef
883 my ($self, $field, $attributes, $table) = @_;
884 my $dbc = $self->dbc();
885 my $dbh = $dbc->db_handle();
887 unless (@args = $dbc->_driver_object->last_insert_id_args($field, $table)) {
889 my ($table_entry) = $self->_tables(); # first table entry
890 $table = $table_entry->[0]; # table_entry is [ name, alias ]
892 @args = (undef, $dbc->dbname(), $table, $field);
895 return $dbh->last_insert_id(@args, $attributes);
898 =head2 insert_ignore_clause
901 sub insert_ignore_clause {
903 return $self->dbc->_driver_object->insert_ignore_clause;
908 Description : Used to
return an instance of a support BaseCache module
909 which can be used to speed up
object access. The method
910 also respects the DBAdaptor
's no_cache() flag and will
911 return undef in those situations
912 Example : my $cache = $self->_id_cache();
913 Returntype : Bio::EnsEMBL::DBSQL::Support::BaseCache
919 return if $self->db()->no_cache() && !$self->ignore_cache_override;
920 if(! exists $self->{_id_cache}) {
921 $self->{_id_cache} = $self->_build_id_cache();
923 return $self->{_id_cache};
928 Description : Flags if the ID based caching is active or not. This could be
929 due to the adaptor not wanting to cache or because of
930 a global no_cache() flag on the DBAdaptor instance
937 return 1 if ! $self->_id_cache();
941 =head2 ignore_cache_override
943 Description : Method to interfere with no_cache directive from Registry on
944 a per adaptor basis. This method should be called after new()
945 in order to trigger the _build_id_cache at first query.
946 Example : $adaptor->ignore_cache_override(1);
951 sub ignore_cache_override {
953 $self->{'_override
'} = shift if(@_);
954 unless (defined($self->{'_override
'})) {return}
955 return $self->{'_override
'};
958 =head2 schema_version
960 Description : Returns the schema version of the currently connected
961 DBAdaptor. The subroutine also caches this value so
962 repeated calls continue to be speedy.
963 Example : $adaptor->schema_version();
970 return $self->{_schema_version} if exists $self->{_schema_version};
971 my $mc = $self->db()->get_MetaContainer();
972 return $self->{_schema_version} = $mc->get_schema_version();
978 # Example : $tablename = $self->_table_name()
979 # Description: ABSTRACT PROTECTED
980 # Subclasses are responsible for implementing this
981 # method. It should list of [tablename, alias] pairs.
982 # Additionally the primary table (with the dbID,
983 # analysis_id, and score) should be the first table in
985 # ( ['repeat_feature
', 'rf
'],
986 # ['repeat_consensus
', 'rc
']);
987 # used to obtain features.
988 # Returntype : list of [tablename, alias] pairs
989 # Exceptions : thrown if not implemented by subclass
990 # Caller : BaseFeatureAdaptor::generic_fetch
994 throw( "abstract method _tables not defined "
995 . "by implementing subclass of BaseAdaptor" );
1002 # Example : $tablename = $self->_columns()
1003 # Description: ABSTRACT PROTECTED
1004 # Subclasses are responsible for implementing this
1005 # method. It should return a list of columns to be
1006 # used for feature creation.
1007 # Returntype : list of strings
1008 # Exceptions : thrown if not implemented by subclass
1009 # Caller : BaseFeatureAdaptor::generic_fetch
1013 throw( "abstract method _columns not defined "
1014 . "by implementing subclass of BaseAdaptor" );
1018 # _default_where_clause
1022 # Description: May be overridden to provide an additional where
1023 # constraint to the SQL query which is generated to
1024 # fetch feature records. This constraint is always
1025 # appended to the end of the generated where clause
1026 # Returntype : string
1028 # Caller : generic_fetch
1031 sub _default_where_clause { return '' }
1038 # Description: Can be overridden by a subclass to specify any left
1039 # joins which should occur. The table name specigfied
1040 # in the join must still be present in the return
1042 # Returntype : a {'tablename
' => 'join condition
'} pair
1047 sub _left_join { return () }
1054 # Description: May be overriden to provide an additional clause
1055 # to the end of the SQL query used to fetch feature
1056 # records. This is useful to add a required ORDER BY
1057 # clause to the query for example.
1058 # Returntype : string
1060 # Caller : generic_fetch
1062 sub _final_clause { return '' }
1067 # Arg [1] : DBI::row_hashref $hashref containing key-value pairs
1068 # for each of the columns specified by the _columns method
1069 # Example : my @feats = $self->_obj_from_hashref
1070 # Description: ABSTRACT PROTECTED
1071 # The subclass is responsible for implementing this
1072 # method. It should take in a DBI row hash reference
1073 # and return a list of created features in contig
1075 # Returntype : list of Bio::EnsEMBL::*Features in contig coordinates
1076 # Exceptions : thrown if not implemented by subclass
1077 # Caller : BaseFeatureAdaptor::generic_fetch
1079 sub _objs_from_sth {
1080 throw( "abstract method _objs_from_sth not defined "
1081 . "by implementing subclass of BaseAdaptor" );
1086 # Example : my $id_cache = $self->_build_id_cache
1087 # Description: ABSTRACT PROTECTED
1088 # The subclass is responsible for returning an instance
1089 # of the Bio::EnsEMBL::DBSQL::Support::BaseCache
1090 # which can be used to speed up ID based fetch operations
1091 # Returntype : Instance of Bio::EnsEMBL::DBSQL::Support::BaseCache
1092 # Exceptions : Could be thrown by the implementing sub-class
1093 # Caller : BaseAdaptor::_id_cache
1094 sub _build_id_cache {
1099 # Given a logic name and an existing constraint this will
1100 # add an analysis table constraint to the feature. Note that if no
1101 # analysis_id exists in the columns of the primary table then no
1102 # constraint is added at all
1104 sub _logic_name_to_constraint {
1106 my $constraint = shift;
1107 my $logic_name = shift;
1109 return $constraint if(!$logic_name);
1111 #make sure that an analysis_id exists in the primary table
1112 my ($prim_tab) = $self->_tables();
1113 my $prim_synonym = $prim_tab->[1];
1115 my $found_analysis=0;
1116 foreach my $col ($self->_columns) {
1117 my ($syn,$col_name) = split(/\./,$col);
1118 next if($syn ne $prim_synonym);
1119 if($col_name eq 'analysis_id
') {
1120 $found_analysis = 1;
1125 if(!$found_analysis) {
1126 warning("This feature is not associated with an analysis.\n" .
1127 "Ignoring logic_name argument = [$logic_name].\n");
1131 my $aa = $self->db->get_AnalysisAdaptor();
1132 my $an = $aa->fetch_by_logic_name($logic_name);
1134 if ( !defined($an) ) {
1138 my $an_id = $an->dbID();
1140 $constraint .= ' AND
' if($constraint);
1141 $constraint .= " ${prim_synonym}.analysis_id = $an_id";