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)
99 use vars qw(@ISA @EXPORT);
104 use DBI qw(:sql_types);
106 use Scalar::Util qw/looks_like_number/;
109 @EXPORT = (@{$DBI::EXPORT_TAGS{
'sql_types'}});
114 Example : $adaptor =
new AdaptorInheritedFromBaseAdaptor($dbobj);
115 Description: Creates a
new BaseAdaptor
object. The intent is that
this
116 constructor would be called by an inherited superclass either
117 automatically or through $self->SUPER::new in an overridden
127 my ( $class, $dbobj ) = @_;
129 my $self = bless {}, $class;
131 if ( !defined $dbobj || !ref $dbobj ) {
132 throw(
"Don't have a db [$dbobj] for new adaptor");
135 if ( $dbobj->isa(
'Bio::EnsEMBL::DBSQL::DBAdaptor') ) {
137 $self->dbc( $dbobj->dbc );
138 $self->species_id( $dbobj->species_id() );
139 $self->is_multispecies( $dbobj->is_multispecies() );
140 } elsif ( ref($dbobj) =~ /DBAdaptor$/ ) {
142 $self->dbc( $dbobj->dbc );
143 } elsif ( ref($dbobj) =~ /DBConnection$/ ) {
146 throw(
"Don't have a DBAdaptor [$dbobj] for new adaptor");
155 Arg [1] :
string $string
156 a SQL query to be prepared by
this adaptors database
157 Example : $sth = $adaptor->
prepare(
"select yadda from blabla")
158 Description: provides a DBI statement handle from the adaptor. A convenience
159 function so you dont have to write $adaptor->db->prepare all the
161 Returntype : DBI::StatementHandle
163 Caller : Adaptors inherited from BaseAdaptor
169 my ( $self, $string ) = @_;
171 # Uncomment next line to cancel caching on the SQL side.
172 # Needed for timing comparisons etc.
173 #$string =~ s/SELECT/SELECT SQL_NO_CACHE/i;
175 return $self->dbc->prepare($string);
182 the database
this adaptor is
using.
183 Example : $db = $adaptor->db();
184 Description: Getter/Setter
for the DatabaseConnection that
this adaptor is
188 Caller : Adaptors inherited from BaseAdaptor
194 my ( $self, $value ) = @_;
196 if ( defined($value) ) {
197 $self->{
'db'} = $value;
200 return $self->{
'db'};
206 the database
this adaptor is
using.
207 Example : $db = $adaptor->db();
208 Description: Getter/Setter
for the DatabaseConnection that
this adaptor is
212 Caller : Adaptors inherited from BaseAdaptor
218 my ( $self, $value ) = @_;
220 if ( defined($value) ) {
221 $self->{
'dbc'} = $value;
224 return $self->{
'dbc'};
227 =head2 is_multispecies
229 Arg [1] : (optional)
boolean $arg
230 Example :
if ($adaptor->is_multispecies()) { }
231 Description: Getter/Setter
for the is_multispecies
boolean of
232 to use
for this adaptor.
240 sub is_multispecies {
241 my ( $self, $arg ) = @_;
243 if ( defined($arg) ) {
244 $self->{_is_multispecies} = $arg;
247 return $self->{_is_multispecies};
252 Arg [1] : (optional)
int $species_id
253 The
internal ID of the species in a multi-species database.
254 Example : $db = $adaptor->db();
255 Description: Getter/Setter
for the
internal ID of the species in a
256 multi-species database. The
default species ID is 1.
259 Caller : Adaptors inherited from BaseAdaptor
265 my ( $self, $value ) = @_;
267 if ( defined($value) ) {
268 $self->{
'species_id'} = $value;
271 return $self->{
'species_id'} || 1;
275 # list primary keys for a particular table
276 # args are table name and primary key field
277 # if primary key field is not supplied, tablename_id is assumed
278 # returns listref of IDs
280 my ( $self, $table, $pk, $ordered ) = @_;
282 if ( !defined($pk) ) { $pk = $table .
"_id" }
284 my $sql = sprintf(
"SELECT `%s` FROM `%s`", $pk, $table );
286 my $join_with_cs = 0;
287 if ( $self->is_multispecies()
288 && $self->isa(
'Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor')
289 && !$self->isa(
'Bio::EnsEMBL::DBSQL::UnmappedObjectAdaptor') )
293 JOIN seq_region USING (seq_region_id)
294 JOIN coord_system cs USING (coord_system_id)
295 WHERE cs.species_id = ?
301 if ( defined($ordered) && $ordered ) {
302 $sql .=
" ORDER BY seq_region_id, seq_region_start";
305 my $sth = $self->prepare($sql);
308 $sth->bind_param( 1, $self->species_id(), SQL_INTEGER );
311 eval { $sth->execute() };
313 throw(
"Detected an error whilst executing SQL '${sql}': $@");
317 $sth->bind_col( 1, \$id );
320 while ( $sth->fetch() ) {
325 } ## end sub _list_dbIDs
330 # Arg [1] : (optional) boolean $new_val
331 # Example : $self->_straight_join(1);
332 # $self->generic_fetch($constraint);
333 # $self->_straight_join(0);
334 # Description: PROTECTED Getter/Setter that turns on/off the use of
335 # a straight join in queries.
336 # Returntype : boolean
343 $self->{
'_straight_join'} = shift;
346 return $self->{
'_straight_join'};
349 sub _can_straight_join {
351 return $self->dbc->_driver_object->can_straight_join;
354 =head2 bind_param_generic_fetch
356 Arg [1] : (optional) scalar $param
357 This is the parameter to bind
358 Arg [2] : (optional)
int $sql_type
359 Type of the parameter (from DBI (:sql_types))
360 Example : $adaptor->bind_param_generic_fetch($stable_id,SQL_VARCHAR);
361 $adaptor->generic_fetch();
362 Description: When
using parameters
for the query, will call the bind_param to avoid
363 some security issues. If there are no arguments, will
return the bind_parameters
365 Exceptions:
if called with one argument
369 sub bind_param_generic_fetch{
372 my $sql_type = shift;
374 if (defined $param && !defined $sql_type){
375 throw(
"Need to specify sql_type for parameter $param\n");
377 elsif (defined $param && defined $sql_type){
378 #check when there is a SQL_INTEGER type that the parameter is really a number
379 if ($sql_type eq SQL_INTEGER){
380 throw "Trying to assign a non numerical parameter to an integer value in the database" if ($param !~ /^[+-]{0,1}\d+$/);
382 #both paramters have been entered, push it to the bind_param array
383 push @{$self->{
'_bind_param_generic_fetch'}},[$param,$sql_type];
385 elsif (!defined $param && !defined $sql_type){
386 #when there are no arguments, return the array
387 return $self->{
'_bind_param_generic_fetch'};
392 # Used to reset the params without circumventing scope
393 sub _bind_param_generic_fetch {
394 my ($self, $_bind_param_generic_fetch) = @_;
395 $self->{
'_bind_param_generic_fetch'} = $_bind_param_generic_fetch
if $_bind_param_generic_fetch;
396 return $self->{_bind_param_generic_fetch};
399 =head2 generate_in_constraint
401 Arg [1] : ArrayRef or Scalar $list
402 List or a single value of items to be pushed into an IN statement
403 Arg [2] : Scalar $column
404 Column
this IN statement is being applied to. Please fully resolve the
406 Arg [3] : Scalar $param_type
407 Data type which should be used when binding. Please use DBI data type symbols
408 Arg [4] : Scalar
boolean $inline_variables
409 Boolean to control
if variables are inlined in the constraint. If
410 false values are bound via bind_param_generic_fetch() (the
default behaviour).
412 Description : Used internally to generate a SQL constraint to restrict a query by an IN statement.
413 The code generates the complete IN statement.
415 Exceptions : If no list is supplied, the list of values is empty or no data type was given
420 sub generate_in_constraint {
421 my ($self, $list, $column, $param_type, $inline_variables) = @_;
422 throw(
"A list of values must be given")
if ! defined $list;
423 $list = wrap_array($list); # homogenise into an array
424 throw "We should be given at least one value to insert" if scalar(@{$list}) == 0;
425 throw "Please supply the DBI param type" if ! defined $param_type;
426 #Figure out if we need to quote our values if we are asked to inline the variables
427 my $quote_values = 1;
428 if($param_type == SQL_INTEGER || $param_type == SQL_TINYINT || $param_type == SQL_DOUBLE ) {
432 my $constraint = qq{${column} IN (};
433 if($inline_variables) {
435 $constraint .= join(q{,},
map { qq{
"${_}"} } @{$list});
438 $constraint .= join(q{,}, @{$list});
442 my @subs = (
'?') x scalar(@{$list});
443 $constraint .= join(q{,}, @subs);
444 $self->bind_param_generic_fetch($_, $param_type)
for @{$list};
452 Arg [1] : (optional)
string $constraint
453 An SQL query constraint (i.e. part of the WHERE clause)
455 A mapper
object used to remap features
456 as they are retrieved from the database
458 A slice that features should be remapped to
459 Example : $fts = $a->generic_fetch(
'contig_id in (1234, 1235)');
460 Description: Performs a database fetch and returns feature objects in
463 Exceptions : Thrown
if there is an issue with querying the data
464 Caller : BaseFeatureAdaptor, ProxyDnaAlignFeatureAdaptor::generic_fetch
470 my ($self, $constraint, $mapper, $slice) = @_;
471 my $sql = $self->_generate_sql($constraint);
472 my $params = $self->bind_param_generic_fetch();
474 $self->{_bind_param_generic_fetch} = undef;
475 my $sth = $self->db()->dbc()->prepare($sql);
477 foreach my $param (@{$params}){
478 $sth->bind_param($i,$param->[0],$param->[1]);
481 eval { $sth->execute() };
483 throw(
"Detected an error whilst executing SQL '${sql}': $@");
486 my $res = $self->_objs_from_sth($sth, $mapper, $slice);
493 Arg [1] : (optional)
string $constraint
494 An SQL query constraint (i.e. part of the WHERE clause)
495 Example : $number_feats = $a->generic_count(
'contig_id in (1234, 1235)');
496 Description: Performs a database fetch and returns a count of those features
497 found. This is analagous to C<generic_fetch()>
498 Returntype : Integer count of the elements.
499 Exceptions : Thrown
if there is an issue with querying the data
504 my ($self, $constraint) = @_;
505 my $sql = $self->_generate_sql($constraint,
'count(*)');
506 my $params = $self->bind_param_generic_fetch();
508 $self->{_bind_param_generic_fetch} = undef;
509 my $h = $self->db()->dbc()->sql_helper();
510 my $count = $h->execute_single_result(-SQL => $sql, -PARAMS => $params);
515 my ($self, $constraint, @input_columns) = @_;
517 my @tabs = $self->_tables();
519 my $extra_default_where;
521 # Hack for feature types that needs to be restricted to species_id (in
523 if ( $self->is_multispecies()
524 && $self->isa(
'Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor')
525 && !$self->isa(
'Bio::EnsEMBL::DBSQL::BaseAlignFeatureAdaptor')
526 && !$self->isa(
'Bio::EnsEMBL::DBSQL::UnmappedObjectAdaptor') )
528 # We do a check to see if there is already seq_region
529 # and coord_system defined to ensure we get the right
530 # alias. We then do the extra query irrespectively of
531 # what has already been specified by the user.
532 my %thash =
map { $_->[0] => $_->[1] } @tabs;
535 ( exists( $thash{seq_region} ) ? $thash{seq_region} :
'sr' );
537 ( exists( $thash{coord_system} ) ? $thash{coord_system} :
'cs' );
539 if ( !exists( $thash{seq_region} ) ) {
540 push( @tabs, [
'seq_region', $sr_alias ] );
542 if ( !exists( $thash{coord_system} ) ) {
543 push( @tabs, [
'coord_system', $cs_alias ] );
546 $extra_default_where = sprintf(
547 '%s.seq_region_id = %s.seq_region_id '
548 .
'AND %s.coord_system_id = %s.coord_system_id '
549 .
'AND %s.species_id = ?',
550 $tabs[0]->[1], $sr_alias, $sr_alias,
551 $cs_alias, $cs_alias );
553 $self->bind_param_generic_fetch( $self->species_id(), SQL_INTEGER );
554 } ## end
if ( $self->is_multispecies...)
556 @input_columns = $self->_columns()
if ! @input_columns;
557 my $columns = join(
', ', @input_columns);
560 # Construct a left join statement if one was defined, and remove the
561 # left-joined table from the table list
563 my @left_join_list = $self->_left_join();
564 my $left_join_prefix =
'';
567 if(@left_join_list) {
568 my %left_join_hash =
map { $_->[0] => $_->[1] } @left_join_list;
569 while(my $t = shift @tabs) {
570 my $t_alias = $t->[0] .
" " . $t->[1];
571 if( exists $left_join_hash{ $t->[0] } || exists $left_join_hash{$t_alias}) {
572 my $condition = $left_join_hash{ $t->[0] };
573 $condition ||= $left_join_hash{$t_alias};
576 "\n LEFT JOIN " . $t->[0] .
" $syn ON $condition ) ";
577 $left_join_prefix .=
'(';
586 my $straight_join =
'';
588 if($self->_straight_join() and $self->_can_straight_join) {
589 $straight_join =
"STRAIGHT_JOIN";
592 #construct a nice table string like 'table1 t1, table2 t2'
593 my $tablenames = join(
', ',
map({ join(
' ', @$_) } @tables));
596 "SELECT $straight_join $columns \n"
597 .
"FROM $left_join_prefix ($tablenames) $left_join";
599 my $default_where = $self->_default_where_clause();
600 my $final_clause = $self->_final_clause;
602 if ($extra_default_where) {
603 if ($default_where) {
604 $default_where .=
"\n AND $extra_default_where";
606 $default_where = $extra_default_where;
610 #append a where clause if it was defined
612 $sql .=
"\n WHERE $constraint ";
613 if ($default_where) {
614 $sql .=
" AND\n $default_where ";
616 } elsif ($default_where) {
617 $sql .=
"\n WHERE $default_where ";
620 #append additional clauses which may have been defined, don't append ORDER BY twice
621 if (index($final_clause,
"ORDER") == -1 || index($sql,
"ORDER") == -1) {
622 $sql .=
"\n$final_clause";
626 #printf(STDERR "SQL:\n%s\n", $sql);
635 The unique database identifier
for the feature to be obtained
636 Example : $feat = $adaptor->fetch_by_dbID(1234));
637 $feat = $feat->transform(
'contig');
638 Description: Returns the feature created from the database defined by the
639 the
id $id. The feature will be returned in its native
640 coordinate system. That is, the coordinate system in which it
641 is stored in the database. In order to convert it to a
642 particular coordinate system use the transfer() or transform()
643 method. If the feature is not found in the database then
644 undef is returned instead
646 Exceptions : thrown if $id arg is not provided
654 my ($self, $id) = @_;
655 if ($self->_no_id_cache()) {
656 return $self->_uncached_fetch_by_dbID($id);
658 return $self->_id_cache()->get($id);
661 # The actual implmenetation moved sideways to allow for uncached access
662 # otherwise we'd constantly loop
664 sub _uncached_fetch_by_dbID{
667 throw(
"id argument is required")
if(!defined $id);
669 #construct a constraint like 't1.table1_id = 123'
670 my @tabs = $self->_tables;
671 my ($name, $syn) = @{$tabs[0]};
672 $self->bind_param_generic_fetch($id,SQL_INTEGER);
673 my $constraint =
"${syn}.${name}_id = ?";
676 my ($feat) = @{$self->generic_fetch($constraint)};
684 =head2 fetch_all_by_dbID_list
686 Arg [1] : listref of integers $id_list
687 The unique database identifiers
for the features to
690 Example : @feats = @{$adaptor->fetch_all_by_dbID_list([1234, 2131, 982]))};
691 Description: Returns the features created from the database
692 defined by the the IDs in contained in the provided
693 ID list $id_list. The features will be returned
694 in their native coordinate system. That is, the
695 coordinate system in which they are stored in the
696 database. In order to convert the features to a
697 particular coordinate system use the transfer() or
698 transform() method. If none of the features are
699 found in the database a reference to an empty list is
701 Returntype : listref of
Bio::
EnsEMBL::Features
702 Exceptions : thrown if $id arg is not provided
709 sub fetch_all_by_dbID_list {
710 my ($self, $id_list_ref, $slice) = @_;
711 if ($self->_no_id_cache()) {
712 return $self->_uncached_fetch_all_by_dbID_list($id_list_ref, $slice);
714 return $self->_id_cache()->get_by_list($id_list_ref, $slice);
717 # The actual implmenetation moved sideways to allow for uncached access
718 # otherwise we'd constantly loop
719 sub _uncached_fetch_all_by_dbID_list {
720 my ( $self, $id_list_ref, $slice ) = @_;
721 return $self->_uncached_fetch_all_by_id_list($id_list_ref, $slice,
"dbID", 1);
722 } ## end sub fetch_all_by_dbID_list
724 =head2 _uncached_fetch_all_by_id_list
726 Arg [1] : listref of IDs
728 A slice that features should be remapped to
729 Arg [3] : String describing the ID type.
730 Valid values include dbID and stable_id. dbID is an alias
for
731 the primary key,
while other names
map directly to table columns
732 of the Feature
this adaptor manages.
733 Arg [4] : Boolean $numeric
734 Indicates
if the incoming data is to be processed as a numeric
735 or as a String. If arg [3] was set to dbID then we
default this to
736 be
true. If arg [3] was set to stable_id then we
default this to
738 When not
using a standard arg[3] the IDs are assumed to be Strings.
739 Arg [5] : Integer $max_size
740 Control the maximum number of IDs sent to a database in a single
741 query. Defaults to 2K
for Strings and 16K
for integers. Only
742 provide
if you know *exactly* why you need to edit it.
743 Example : $list_of_features = $adaptor->_uncached_fetch_all_by_id_list(
744 [qw(ENSG00000101321 ENSG00000101346 ENSG00000101367)],
746 "stable_id", 0); #
using strings
748 # Numeric set to true because we are using numerics
749 $list_of_features = $adaptor->_uncached_fetch_all_by_id_list(
754 # Numeric defaults to true because we are querying using dbID
755 $list_of_features = $adaptor->_uncached_fetch_all_by_id_list(
759 Description: This is a
generic method used to fetch lists of features by IDs.
760 It avoids caches, meaning it is best suited
for block fetching.
761 See fetch_all_by_dbID_list() for more
info.
762 Returntype : ArrayRef of
Bio::
EnsEMBL::Feature
763 Exceptions : Thrown if a list of IDs is not supplied.
764 Caller : BaseFeatureAdaptor, BaseAdaptor and derived classes.
768 sub _uncached_fetch_all_by_id_list {
769 my ( $self, $id_list_ref, $slice, $id_type, $numeric, $max_size ) = @_;
771 if ( !defined($id_list_ref) || ref($id_list_ref) ne
'ARRAY' ) {
772 throw(
"id_list list reference argument is required");
775 if ( !@{$id_list_ref} ) {
return [] }
777 # Construct a constraint like 't1.table1_id = 123'
778 my @tabs = $self->_tables();
779 my ( $name, $syn ) = @{ $tabs[0] };
781 # prepare column name for query. If the id_type was
782 # set to dbID then we assume the column must be
783 # tablename_id e.g. gene_id. Otherwise we assume the id_type
784 # is the field/column name
786 if($id_type eq
'dbID') {
787 $field_name = $name.
'_id';
788 # If numeric was not set default it to 1 since this is an int
789 $numeric = 1
if ! defined $numeric;
791 elsif($id_type eq
'stable_id') {
792 # If numeric was not set default it to 0 since this is a string
793 $numeric = 0
if ! defined $numeric;
794 $field_name = $id_type;
797 $field_name = $id_type;
802 # Ensuring we do not exceed MySQL's max_allowed_packet (defaults to 1MB)
803 # by splitting large queries into smaller queries of at most 256KB
804 # (262,144 8-bit characters)
805 # If we had a numeric then really we are talking about working with
806 # integers. Normal max ensembl id size is 12 plus 2 characters for
807 # commas in our IN statement comes to 14. Even bloating this to 16 gives
808 # a max number of 16,384 IDs (262114/16).
811 my $first_id = $id_list_ref->[0];
812 if(!looks_like_number($first_id)) {
813 throw "You specified that we are looking for numerics but $first_id is not a numeric";
815 $max_size = 16384
if ! defined $max_size;
816 $sql_data_type = SQL_INTEGER;
818 # However when dealing with Strings those can be very large (assuming
819 # 128 is the max length of a stable ID). 128 is 8x smaller than our
820 # previous max expected integer so we reduce the max ids by 8. This gives
823 $max_size = 2048
if ! defined $max_size;
824 $sql_data_type = SQL_VARCHAR;
827 # build up unique id list, also validate on the way by
829 for (@{$id_list_ref}) {
832 my @id_list = keys %id_list;
840 if ( scalar(@id_list) > $max_size ) {
841 @ids = splice( @id_list, 0, $max_size );
847 # Push off to our IN statement constructor for this work
848 my $constraint = $self->generate_in_constraint(\@ids,
"${syn}.${field_name}", $sql_data_type, $inline);
849 push @out, @{ $self->generic_fetch($constraint, undef, $slice) };
855 # might not be a good idea, but for convenience
856 # shouldnt be called on the BIG tables though
860 return $self->generic_fetch();
863 =head2 last_insert_id
865 Arg [1] : (optional) $field the name of the field the inserted ID was pushed
867 Arg [2] : (optional) HashRef used to pass extra attributes through to the
869 Arg [3] : (optional) $table the name of the table to use
if the adaptor
870 does not implement C<_tables()>
871 Description : Delegating method which uses DBI to extract the last inserted
872 identifier. If
using MySQL we just call the DBI method
873 L<DBI::last_insert_id()> since MySQL ignores any extra
874 arguments. See L<DBI>
for more information
about this
876 Example : my $id = $self->last_insert_id(
'my_id'); my $other_id = $self->last_insert_id();
877 Returntype : Scalar or undef
882 my ($self, $field, $attributes, $table) = @_;
883 my $dbc = $self->dbc();
884 my $dbh = $dbc->db_handle();
886 unless (@args = $dbc->_driver_object->last_insert_id_args($field, $table)) {
888 my ($table_entry) = $self->_tables(); # first table entry
889 $table = $table_entry->[0]; # table_entry is [ name, alias ]
891 @args = (undef, $dbc->dbname(), $table, $field);
894 return $dbh->last_insert_id(@args, $attributes);
897 =head2 insert_ignore_clause
900 sub insert_ignore_clause {
902 return $self->dbc->_driver_object->insert_ignore_clause;
907 Description : Used to
return an instance of a support BaseCache module
908 which can be used to speed up
object access. The method
909 also respects the DBAdaptor
's no_cache() flag and will
910 return undef in those situations
911 Example : my $cache = $self->_id_cache();
912 Returntype : Bio::EnsEMBL::DBSQL::Support::BaseCache
918 return if $self->db()->no_cache() && !$self->ignore_cache_override;
919 if(! exists $self->{_id_cache}) {
920 $self->{_id_cache} = $self->_build_id_cache();
922 return $self->{_id_cache};
927 Description : Flags if the ID based caching is active or not. This could be
928 due to the adaptor not wanting to cache or because of
929 a global no_cache() flag on the DBAdaptor instance
936 return 1 if ! $self->_id_cache();
940 =head2 ignore_cache_override
942 Description : Method to interfere with no_cache directive from Registry on
943 a per adaptor basis. This method should be called after new()
944 in order to trigger the _build_id_cache at first query.
945 Example : $adaptor->ignore_cache_override(1);
950 sub ignore_cache_override {
952 $self->{'_override
'} = shift if(@_);
953 unless (defined($self->{'_override
'})) {return}
954 return $self->{'_override
'};
957 =head2 schema_version
959 Description : Returns the schema version of the currently connected
960 DBAdaptor. The subroutine also caches this value so
961 repeated calls continue to be speedy.
962 Example : $adaptor->schema_version();
969 return $self->{_schema_version} if exists $self->{_schema_version};
970 my $mc = $self->db()->get_MetaContainer();
971 return $self->{_schema_version} = $mc->get_schema_version();
977 # Example : $tablename = $self->_table_name()
978 # Description: ABSTRACT PROTECTED
979 # Subclasses are responsible for implementing this
980 # method. It should list of [tablename, alias] pairs.
981 # Additionally the primary table (with the dbID,
982 # analysis_id, and score) should be the first table in
984 # ( ['repeat_feature
', 'rf
'],
985 # ['repeat_consensus
', 'rc
']);
986 # used to obtain features.
987 # Returntype : list of [tablename, alias] pairs
988 # Exceptions : thrown if not implemented by subclass
989 # Caller : BaseFeatureAdaptor::generic_fetch
993 throw( "abstract method _tables not defined "
994 . "by implementing subclass of BaseAdaptor" );
1001 # Example : $tablename = $self->_columns()
1002 # Description: ABSTRACT PROTECTED
1003 # Subclasses are responsible for implementing this
1004 # method. It should return a list of columns to be
1005 # used for feature creation.
1006 # Returntype : list of strings
1007 # Exceptions : thrown if not implemented by subclass
1008 # Caller : BaseFeatureAdaptor::generic_fetch
1012 throw( "abstract method _columns not defined "
1013 . "by implementing subclass of BaseAdaptor" );
1017 # _default_where_clause
1021 # Description: May be overridden to provide an additional where
1022 # constraint to the SQL query which is generated to
1023 # fetch feature records. This constraint is always
1024 # appended to the end of the generated where clause
1025 # Returntype : string
1027 # Caller : generic_fetch
1030 sub _default_where_clause { return '' }
1037 # Description: Can be overridden by a subclass to specify any left
1038 # joins which should occur. The table name specigfied
1039 # in the join must still be present in the return
1041 # Returntype : a {'tablename
' => 'join condition
'} pair
1046 sub _left_join { return () }
1053 # Description: May be overriden to provide an additional clause
1054 # to the end of the SQL query used to fetch feature
1055 # records. This is useful to add a required ORDER BY
1056 # clause to the query for example.
1057 # Returntype : string
1059 # Caller : generic_fetch
1061 sub _final_clause { return '' }
1066 # Arg [1] : DBI::row_hashref $hashref containing key-value pairs
1067 # for each of the columns specified by the _columns method
1068 # Example : my @feats = $self->_obj_from_hashref
1069 # Description: ABSTRACT PROTECTED
1070 # The subclass is responsible for implementing this
1071 # method. It should take in a DBI row hash reference
1072 # and return a list of created features in contig
1074 # Returntype : list of Bio::EnsEMBL::*Features in contig coordinates
1075 # Exceptions : thrown if not implemented by subclass
1076 # Caller : BaseFeatureAdaptor::generic_fetch
1078 sub _objs_from_sth {
1079 throw( "abstract method _objs_from_sth not defined "
1080 . "by implementing subclass of BaseAdaptor" );
1085 # Example : my $id_cache = $self->_build_id_cache
1086 # Description: ABSTRACT PROTECTED
1087 # The subclass is responsible for returning an instance
1088 # of the Bio::EnsEMBL::DBSQL::Support::BaseCache
1089 # which can be used to speed up ID based fetch operations
1090 # Returntype : Instance of Bio::EnsEMBL::DBSQL::Support::BaseCache
1091 # Exceptions : Could be thrown by the implementing sub-class
1092 # Caller : BaseAdaptor::_id_cache
1093 sub _build_id_cache {
1098 # Given a logic name and an existing constraint this will
1099 # add an analysis table constraint to the feature. Note that if no
1100 # analysis_id exists in the columns of the primary table then no
1101 # constraint is added at all
1103 sub _logic_name_to_constraint {
1105 my $constraint = shift;
1106 my $logic_name = shift;
1108 return $constraint if(!$logic_name);
1110 #make sure that an analysis_id exists in the primary table
1111 my ($prim_tab) = $self->_tables();
1112 my $prim_synonym = $prim_tab->[1];
1114 my $found_analysis=0;
1115 foreach my $col ($self->_columns) {
1116 my ($syn,$col_name) = split(/\./,$col);
1117 next if($syn ne $prim_synonym);
1118 if($col_name eq 'analysis_id
') {
1119 $found_analysis = 1;
1124 if(!$found_analysis) {
1125 warning("This feature is not associated with an analysis.\n" .
1126 "Ignoring logic_name argument = [$logic_name].\n");
1130 my $aa = $self->db->get_AnalysisAdaptor();
1131 my $an = $aa->fetch_by_logic_name($logic_name);
1133 if ( !defined($an) ) {
1137 my $an_id = $an->dbID();
1139 $constraint .= ' AND
' if($constraint);
1140 $constraint .= " ${prim_synonym}.analysis_id = $an_id";