Archive Ensembl HomeArchive Ensembl Home
BaseAdaptor.pm
Go to the documentation of this file.
00001 =head1 LICENSE
00002 
00003   Copyright (c) 1999-2012 The European Bioinformatics Institute and
00004   Genome Research Limited.  All rights reserved.
00005 
00006   This software is distributed under a modified Apache license.
00007   For license details, please see
00008 
00009     http://www.ensembl.org/info/about/code_licence.html
00010 
00011 =head1 CONTACT
00012 
00013   Please email comments or questions to the public Ensembl
00014   developers list at <dev@ensembl.org>.
00015 
00016   Questions may also be sent to the Ensembl help desk at
00017   <helpdesk@ensembl.org>.
00018 
00019 =cut
00020 
00021 =head1 NAME
00022 
00023 Bio::EnsEMBL::DBSQL::BaseAdaptor - Base Adaptor for DBSQL adaptors
00024 
00025 =head1 SYNOPSIS
00026 
00027   # base adaptor provides
00028 
00029   # SQL prepare function
00030   $adaptor->prepare("sql statement");
00031 
00032   # get of root DBAdaptor object
00033   $adaptor->db();
00034 
00035   # constructor, ok for inheritence
00036   $adaptor = Bio::EnsEMBL::DBSQL::SubClassOfBaseAdaptor->new($dbobj)
00037 
00038 =head1 DESCRIPTION
00039 
00040 This is a true base class for Adaptors in the Ensembl DBSQL
00041 system. Original idea from Arne
00042 
00043 Adaptors are expected to have the following functions
00044 
00045   $obj = $adaptor->fetch_by_dbID($internal_id);
00046 
00047 which builds the object from the primary key of the object. This
00048 function is crucial because it allows adaptors to collaborate relatively
00049 independently of each other - in other words, we can change the schema
00050 under one adaptor without too many knock on changes through the other
00051 adaptors.
00052 
00053 Most adaptors will also have
00054 
00055   $dbid = $adaptor->store($obj);
00056 
00057 which stores the object. Currently the storing of an object also causes
00058 the objects to set
00059 
00060   $obj->dbID();
00061 
00062 correctly and attach the adaptor.
00063 
00064 Other fetch functions go by the convention of
00065 
00066   @object_array = @{ $adaptor->fetch_all_by_XXXX($arguments_for_XXXX) };
00067 
00068 sometimes it returns an array ref denoted by the 'all' in the name of
00069 the method, sometimes an individual object. For example
00070 
00071   $gene = $gene_adaptor->fetch_by_stable_id($stable_id);
00072 
00073 or
00074 
00075   @fp = @{ $simple_feature_adaptor->fetch_all_by_Slice($slice) };
00076 
00077 Occassionally adaptors need to provide access to lists of ids. In this
00078 case the convention is to go list_XXXX, such as
00079 
00080   @gene_ids = @{ $gene_adaptor->list_geneIds() };
00081 
00082 (note: this method is poorly named)
00083 
00084 =head1 METHODS
00085 
00086 =cut
00087 
00088 package Bio::EnsEMBL::DBSQL::BaseAdaptor;
00089 require Exporter;
00090 use vars qw(@ISA @EXPORT);
00091 use strict;
00092 
00093 use Bio::EnsEMBL::Utils::Exception qw(throw);
00094 use DBI qw(:sql_types);
00095 use Data::Dumper;
00096 
00097 @ISA = qw(Exporter);
00098 @EXPORT = (@{$DBI::EXPORT_TAGS{'sql_types'}});
00099 
00100 =head2 new
00101 
00102   Arg [1]    : Bio::EnsEMBL::DBSQL::DBConnection $dbobj
00103   Example    : $adaptor = new AdaptorInheritedFromBaseAdaptor($dbobj);
00104   Description: Creates a new BaseAdaptor object.  The intent is that this
00105                constructor would be called by an inherited superclass either
00106                automatically or through $self->SUPER::new in an overridden 
00107                new method.
00108   Returntype : Bio::EnsEMBL::DBSQL::BaseAdaptor
00109   Exceptions : none
00110   Caller     : Bio::EnsEMBL::DBSQL::DBConnection
00111   Status     : Stable
00112 
00113 =cut
00114 
00115 sub new {
00116   my ( $class, $dbobj ) = @_;
00117 
00118   my $self = bless {}, $class;
00119 
00120   if ( !defined $dbobj || !ref $dbobj ) {
00121     throw("Don't have a db [$dbobj] for new adaptor");
00122   }
00123 
00124   if ( $dbobj->isa('Bio::EnsEMBL::DBSQL::DBAdaptor') ) {
00125     $self->db($dbobj);
00126     $self->dbc( $dbobj->dbc );
00127     $self->species_id( $dbobj->species_id() );
00128     $self->is_multispecies( $dbobj->is_multispecies() );
00129   } elsif ( ref($dbobj) =~ /DBAdaptor$/ ) {
00130     $self->db($dbobj);
00131     $self->dbc( $dbobj->dbc );
00132   } elsif ( ref($dbobj) =~ /DBConnection$/ ) {
00133     $self->dbc($dbobj);
00134   } else {
00135     throw("Don't have a DBAdaptor [$dbobj] for new adaptor");
00136   }
00137 
00138   return $self;
00139 }
00140 
00141 
00142 =head2 prepare
00143 
00144   Arg [1]    : string $string
00145                a SQL query to be prepared by this adaptors database
00146   Example    : $sth = $adaptor->prepare("select yadda from blabla")
00147   Description: provides a DBI statement handle from the adaptor. A convenience
00148                function so you dont have to write $adaptor->db->prepare all the
00149                time
00150   Returntype : DBI::StatementHandle
00151   Exceptions : none
00152   Caller     : Adaptors inherited from BaseAdaptor
00153   Status     : Stable
00154 
00155 =cut
00156 
00157 sub prepare {
00158   my ( $self, $string ) = @_;
00159 
00160   # Uncomment next line to cancel caching on the SQL side.
00161   # Needed for timing comparisons etc.
00162   #$string =~ s/SELECT/SELECT SQL_NO_CACHE/i;
00163 
00164   return $self->dbc->prepare($string);
00165 }
00166 
00167 
00168 =head2 db
00169 
00170   Arg [1]    : (optional) Bio::EnsEMBL::DBSQL::DBAdaptor $obj 
00171                the database this adaptor is using.
00172   Example    : $db = $adaptor->db();
00173   Description: Getter/Setter for the DatabaseConnection that this adaptor is 
00174                using.
00175   Returntype : Bio::EnsEMBL::DBSQL::DBAdaptor
00176   Exceptions : none
00177   Caller     : Adaptors inherited from BaseAdaptor
00178   Status     : Stable
00179 
00180 =cut
00181 
00182 sub db {
00183   my ( $self, $value ) = @_;
00184 
00185   if ( defined($value) ) {
00186     $self->{'db'} = $value;
00187   }
00188 
00189   return $self->{'db'};
00190 }
00191 
00192 =head2 dbc
00193 
00194   Arg [1]    : (optional) Bio::EnsEMBL::DBSQL::DBConnection $obj 
00195                the database this adaptor is using.
00196   Example    : $db = $adaptor->db();
00197   Description: Getter/Setter for the DatabaseConnection that this adaptor is 
00198                using.
00199   Returntype : Bio::EnsEMBL::DBSQL::DBConnection
00200   Exceptions : none
00201   Caller     : Adaptors inherited from BaseAdaptor
00202   Status     : Stable
00203 
00204 =cut
00205 
00206 sub dbc {
00207   my ( $self, $value ) = @_;
00208 
00209   if ( defined($value) ) {
00210     $self->{'dbc'} = $value;
00211   }
00212 
00213   return $self->{'dbc'};
00214 }
00215 
00216 =head2 is_multispecies
00217 
00218   Arg [1]    : (optional) boolean $arg
00219   Example    : if ($adaptor->is_multispecies()) { }
00220   Description: Getter/Setter for the is_multispecies boolean of
00221                to use for this adaptor.
00222   Returntype : boolean
00223   Exceptions : none
00224   Caller     : general
00225   Status     : Stable
00226 
00227 =cut
00228 
00229 sub is_multispecies {
00230   my ( $self, $arg ) = @_;
00231 
00232   if ( defined($arg) ) {
00233     $self->{_is_multispecies} = $arg;
00234   }
00235 
00236   return $self->{_is_multispecies};
00237 }
00238 
00239 =head2 species_id
00240 
00241   Arg [1]    : (optional) int $species_id
00242                The internal ID of the species in a multi-species database.
00243   Example    : $db = $adaptor->db();
00244   Description: Getter/Setter for the internal ID of the species in a
00245                multi-species database.  The default species ID is 1.
00246   Returntype : Integer
00247   Exceptions : none
00248   Caller     : Adaptors inherited from BaseAdaptor
00249   Status     : Stable
00250 
00251 =cut
00252 
00253 sub species_id {
00254   my ( $self, $value ) = @_;
00255 
00256   if ( defined($value) ) {
00257     $self->{'species_id'} = $value;
00258   }
00259 
00260   return $self->{'species_id'} || 1;
00261 }
00262 
00263 
00264 # list primary keys for a particular table
00265 # args are table name and primary key field
00266 # if primary key field is not supplied, tablename_id is assumed
00267 # returns listref of IDs
00268 sub _list_dbIDs {
00269   my ( $self, $table, $pk, $ordered ) = @_;
00270 
00271   if ( !defined($pk) ) { $pk = $table . "_id" }
00272 
00273   my $sql = sprintf( "SELECT %s FROM %s", $pk, $table );
00274 
00275   my $join_with_cs = 0;
00276   if (    $self->is_multispecies()
00277        && $self->isa('Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor')
00278        && !$self->isa('Bio::EnsEMBL::DBSQL::UnmappedObjectAdaptor') )
00279   {
00280     
00281     $sql .= q(
00282 JOIN seq_region USING (seq_region_id)
00283 JOIN coord_system cs USING (coord_system_id)
00284 WHERE cs.species_id = ?
00285 );
00286 
00287     $join_with_cs = 1;
00288   }
00289 
00290   if ( defined($ordered) && $ordered ) {
00291     $sql .= " ORDER BY seq_region_id, seq_region_start";
00292   }
00293 
00294   my $sth = $self->prepare($sql);
00295 
00296   if ($join_with_cs) {
00297     $sth->bind_param( 1, $self->species_id(), SQL_INTEGER );
00298   }
00299 
00300   eval { $sth->execute() };
00301   if ($@) {
00302     throw("Detected an error whilst executing SQL '${sql}': $@");
00303   }
00304 
00305   my $id;
00306   $sth->bind_col( 1, \$id );
00307 
00308   my @out;
00309   while ( $sth->fetch() ) {
00310     push( @out, $id );
00311   }
00312 
00313   return \@out;
00314 } ## end sub _list_dbIDs
00315 
00316 
00317 # _straight_join
00318 
00319 #   Arg [1]    : (optional) boolean $new_val
00320 #   Example    : $self->_straight_join(1);
00321 #                $self->generic_fetch($constraint);
00322 #                $self->_straight_join(0);
00323 #   Description: PROTECTED Getter/Setter that turns on/off the use of 
00324 #                a straight join in queries.
00325 #   Returntype : boolean
00326 #   Exceptions : none
00327 #   Caller     : general
00328 
00329 sub _straight_join {
00330   my $self = shift;
00331   if(@_) {
00332     $self->{'_straight_join'} = shift;
00333   }
00334 
00335   return $self->{'_straight_join'};
00336 }
00337 
00338 
00339 =head2 bind_param_generic_fetch
00340 
00341  Arg [1]   : (optional)  scalar $param
00342               This is the parameter to bind
00343  Arg [2]   : (optional) int $sql_type
00344               Type of the parameter (from DBI (:sql_types))
00345  Example   :  $adaptor->bind_param_generic_fetch($stable_id,SQL_VARCHAR);
00346               $adaptor->generic_fetch();
00347  Description:  When using parameters for the query, will call the bind_param to avoid
00348                some security issues. If there are no arguments, will return the bind_parameters
00349  ReturnType : listref
00350  Exceptions:  if called with one argument
00351 
00352 =cut
00353 
00354 sub bind_param_generic_fetch{
00355     my $self = shift;
00356     my $param = shift;
00357     my $sql_type = shift;
00358 
00359     if (defined $param && !defined $sql_type){
00360     throw("Need to specify sql_type for parameter $param\n");
00361     }
00362     elsif (defined $param && defined $sql_type){
00363     #check when there is a SQL_INTEGER type that the parameter is really a number
00364     if ($sql_type eq SQL_INTEGER){
00365         throw "Trying to assign a non numerical parameter to an integer value in the database" if ($param !~ /^\d+$/);
00366     }
00367     #both paramters have been entered, push it to the bind_param array
00368     push @{$self->{'_bind_param_generic_fetch'}},[$param,$sql_type];
00369     }
00370     elsif (!defined $param && !defined $sql_type){
00371     #when there are no arguments, return the array
00372     return $self->{'_bind_param_generic_fetch'};
00373     }
00374     
00375 }
00376 
00377 
00378 
00379 =head2 generic_fetch
00380 
00381   Arg [1]    : (optional) string $constraint
00382                An SQL query constraint (i.e. part of the WHERE clause)
00383   Arg [2]    : (optional) Bio::EnsEMBL::AssemblyMapper $mapper
00384                A mapper object used to remap features
00385                as they are retrieved from the database
00386   Arg [3]    : (optional) Bio::EnsEMBL::Slice $slice
00387                A slice that features should be remapped to
00388   Example    : $fts = $a->generic_fetch('contig_id in (1234, 1235)', 'Swall');
00389   Description: Performs a database fetch and returns feature objects in
00390                contig coordinates.
00391   Returntype : listref of Bio::EnsEMBL::SeqFeature in contig coordinates
00392   Exceptions : none
00393   Caller     : BaseFeatureAdaptor, ProxyDnaAlignFeatureAdaptor::generic_fetch
00394   Status     : Stable
00395 
00396 =cut
00397 
00398 sub generic_fetch {
00399   my ($self, $constraint, $mapper, $slice) = @_;
00400 
00401   my @tabs = $self->_tables();
00402 
00403   my $extra_default_where;
00404 
00405   # Hack for feature types that needs to be restricted to species_id (in
00406   # coord_system).
00407   if (    $self->is_multispecies()
00408        && $self->isa('Bio::EnsEMBL::DBSQL::BaseFeatureAdaptor')
00409        && !$self->isa('Bio::EnsEMBL::DBSQL::UnmappedObjectAdaptor') )
00410   {
00411     # We do a check to see if there is already seq_region
00412     # and coord_system defined to ensure we get the right
00413     # alias.  We then do the extra query irrespectively of
00414     # what has already been specified by the user.
00415     my %thash = map { $_->[0] => $_->[1] } @tabs;
00416 
00417     my $sr_alias =
00418       ( exists( $thash{seq_region} ) ? $thash{seq_region} : 'sr' );
00419     my $cs_alias =
00420       ( exists( $thash{coord_system} ) ? $thash{coord_system} : 'cs' );
00421 
00422     if ( !exists( $thash{seq_region} ) ) {
00423       push( @tabs, [ 'seq_region', $sr_alias ] );
00424     }
00425     if ( !exists( $thash{coord_system} ) ) {
00426       push( @tabs, [ 'coord_system', $cs_alias ] );
00427     }
00428 
00429     $extra_default_where = sprintf(
00430                       '%s.seq_region_id = %s.seq_region_id '
00431                         . 'AND %s.coord_system_id = %s.coord_system_id '
00432                         . 'AND %s.species_id = ?',
00433                       $tabs[0]->[1], $sr_alias, $sr_alias,
00434                       $cs_alias,     $cs_alias );
00435 
00436     $self->bind_param_generic_fetch( $self->species_id(), SQL_INTEGER );
00437   } ## end if ( $self->is_multispecies...)
00438 
00439   my $columns = join(', ', $self->_columns());
00440 
00441   my $db = $self->db();
00442 
00443   #
00444   # Construct a left join statement if one was defined, and remove the
00445   # left-joined table from the table list
00446   #
00447   my @left_join_list = $self->_left_join();
00448   my $left_join_prefix = '';
00449   my $left_join = '';
00450   my @tables;
00451   if(@left_join_list) {
00452     my %left_join_hash = map { $_->[0] => $_->[1] } @left_join_list;
00453     while(my $t = shift @tabs) {
00454         my $t_alias = $t->[0] . " " . $t->[1];
00455       if( exists $left_join_hash{ $t->[0] } || exists $left_join_hash{$t_alias}) {
00456         my $condition = $left_join_hash{ $t->[0] };
00457         $condition ||= $left_join_hash{$t_alias};
00458         my $syn = $t->[1];
00459         $left_join .=
00460           "\n  LEFT JOIN " . $t->[0] . " $syn ON $condition ) ";
00461         $left_join_prefix .= '(';
00462       } else {
00463         push @tables, $t;
00464       }
00465     }
00466   } else {
00467     @tables = @tabs;
00468   }
00469 
00470   my $straight_join = '';
00471 
00472   if($self->_straight_join()) {
00473     $straight_join = "STRAIGHT_JOIN";
00474   }
00475 
00476   #construct a nice table string like 'table1 t1, table2 t2'
00477   my $tablenames = join(', ', map({ join(' ', @$_) } @tables));
00478 
00479   my $sql =
00480       "SELECT $straight_join $columns\n"
00481     . "FROM $left_join_prefix ($tablenames) $left_join";
00482 
00483   my $default_where = $self->_default_where_clause();
00484   my $final_clause = $self->_final_clause;
00485 
00486   if ($extra_default_where) {
00487     if ($default_where) {
00488       $default_where .= "\n AND $extra_default_where";
00489     } else {
00490       $default_where = $extra_default_where;
00491     }
00492   }
00493 
00494   #append a where clause if it was defined
00495   if ($constraint) {
00496     $sql .= "\n WHERE $constraint ";
00497     if ($default_where) {
00498       $sql .= " AND\n       $default_where ";
00499     }
00500   } elsif ($default_where) {
00501     $sql .= "\n WHERE $default_where ";
00502   }
00503 
00504   #append additional clauses which may have been defined
00505   $sql .= "\n$final_clause";
00506 
00507 
00508   # FOR DEBUG:
00509   #printf(STDERR "SQL:\n%s\n", $sql);
00510   
00511   
00512   my $sth = $db->dbc->prepare($sql);
00513   my $bind_parameters = $self->bind_param_generic_fetch();
00514   if (defined $bind_parameters){
00515       #if we have bind the parameters, call the DBI to bind them
00516       my $i = 1;
00517       foreach my $param (@{$bind_parameters}){
00518         $sth->bind_param($i,$param->[0],$param->[1]);
00519         $i++;
00520       }
00521       #after binding parameters, undef for future queries
00522       $self->{'_bind_param_generic_fetch'} = ();
00523   }
00524   eval { $sth->execute() };
00525   if ($@) {
00526     throw("Detected an error whilst executing SQL '${sql}': $@");
00527   }
00528 
00529   my $res = $self->_objs_from_sth($sth, $mapper, $slice);
00530   $sth->finish();
00531   return $res;
00532 }
00533 
00534 
00535 =head2 fetch_by_dbID
00536 
00537   Arg [1]    : int $id
00538                The unique database identifier for the feature to be obtained
00539   Example    : $feat = $adaptor->fetch_by_dbID(1234));
00540                $feat = $feat->transform('contig');
00541   Description: Returns the feature created from the database defined by the
00542                the id $id.  The feature will be returned in its native
00543                coordinate system.  That is, the coordinate system in which it
00544                is stored in the database.  In order to convert it to a
00545                particular coordinate system use the transfer() or transform()
00546                method.  If the feature is not found in the database then
00547                undef is returned instead
00548   Returntype : Bio::EnsEMBL::Feature or undef
00549   Exceptions : thrown if $id arg is not provided
00550                does not exist
00551   Caller     : general
00552   Status     : Stable
00553 
00554 =cut
00555 
00556 sub fetch_by_dbID{
00557   my ($self,$id) = @_;
00558 
00559   throw("id argument is required") if(!defined $id);
00560 
00561   #construct a constraint like 't1.table1_id = 123'
00562   my @tabs = $self->_tables;
00563   my ($name, $syn) = @{$tabs[0]};
00564   $self->bind_param_generic_fetch($id,SQL_INTEGER);
00565   my $constraint = "${syn}.${name}_id = ?";
00566 
00567   #Should only be one
00568   my ($feat) = @{$self->generic_fetch($constraint)};
00569 
00570   return undef if(!$feat);
00571 
00572   return $feat;
00573 }
00574 
00575 
00576 =head2 fetch_all_by_dbID_list
00577 
00578   Arg [1]    : listref of integers $id_list
00579                The unique database identifiers for the features to
00580                be obtained.
00581   Arg [2]    : optional - Bio::EnsEMBL::Slice to map features onto.
00582   Example    : @feats = @{$adaptor->fetch_all_by_dbID_list([1234, 2131, 982]))};
00583   Description: Returns the features created from the database
00584                defined by the the IDs in contained in the provided
00585                ID list $id_list.  The features will be returned
00586                in their native coordinate system.  That is, the
00587                coordinate system in which they are stored in the
00588                database.  In order to convert the features to a
00589                particular coordinate system use the transfer() or
00590                transform() method.  If none of the features are
00591                found in the database a reference to an empty list is
00592                returned.
00593   Returntype : listref of Bio::EnsEMBL::Features
00594   Exceptions : thrown if $id arg is not provided
00595                does not exist
00596   Caller     : general
00597   Status     : Stable
00598 
00599 =cut
00600 
00601 sub fetch_all_by_dbID_list {
00602   my ( $self, $id_list_ref, $slice ) = @_;
00603 
00604   if ( !defined($id_list_ref) || ref($id_list_ref) ne 'ARRAY' ) {
00605     throw("id_list list reference argument is required");
00606   }
00607 
00608   if ( !@{$id_list_ref} ) { return [] }
00609 
00610   # Construct a constraint like 't1.table1_id = 123'
00611   my @tabs = $self->_tables();
00612   my ( $name, $syn ) = @{ $tabs[0] };
00613 
00614   # Ensure that we do not exceed MySQL's max_allowed_packet (defaults to
00615   # 1 MB) splitting large queries into smaller queries of at most 256 KB
00616   # (32768 8-bit characters).  Assuming a (generous) average dbID string
00617   # length of 16, this means 2048 dbIDs in each query.
00618   my $max_size = 2048;
00619 
00620 
00621   my %id_list;
00622   $id_list{$_}++ for @{$id_list_ref};
00623   my @id_list = keys %id_list;
00624 
00625   my @out;
00626 
00627   while (@id_list) {
00628     my @ids;
00629     my $id_str;
00630 
00631     if ( scalar(@id_list) > $max_size ) {
00632       @ids = splice( @id_list, 0, $max_size );
00633     } else {
00634       @ids     = @id_list;
00635       @id_list = ();
00636     }
00637 
00638     if ( scalar(@ids) > 1 ) {
00639       $id_str = " IN (" . join( ',', @ids ) . ")";
00640     } else {
00641       $id_str = " = " . $ids[0];
00642     }
00643 
00644     my $constraint = "${syn}.${name}_id $id_str";
00645 
00646     push @out, @{ $self->generic_fetch($constraint, undef, $slice) };
00647   }
00648 
00649   return \@out;
00650 } ## end sub fetch_all_by_dbID_list
00651 
00652 # might not be a good idea, but for convenience
00653 # shouldnt be called on the BIG tables though
00654 
00655 sub fetch_all {
00656   my $self = shift;
00657   return $self->generic_fetch();
00658 }
00659 
00660 =head2 last_insert_id
00661 
00662   Arg [1]     : (optional) $field the name of the field the inserted ID was pushed 
00663                 into
00664   Arg [2]     : (optional) HashRef used to pass extra attributes through to the 
00665                 DBD driver
00666   Description : Delegating method which uses DBI to extract the last inserted 
00667                 identifier. If using MySQL we just call the DBI method 
00668                 L<DBI::last_insert_id()> since MySQL ignores any extra
00669                 arguments. See L<DBI> for more information about this 
00670                 delegated method. 
00671   Example     : my $id = $self->last_insert_id('my_id'); my $other_id = $self->last_insert_id();
00672   Returntype  : Scalar or undef
00673   
00674 =cut
00675 
00676 sub last_insert_id {
00677   my ($self, $field, $attributes) = @_;
00678   my $dbc = $self->dbc();
00679   my $dbh = $dbc->db_handle();
00680   $attributes ||= {};
00681   my ($table) = $self->_tables();
00682   return $dbh->last_insert_id(undef, $dbc->dbname(), $table->[0], $field, $attributes);
00683 }
00684 
00685 
00686 #_tables
00687 #
00688 #  Args       : none
00689 #  Example    : $tablename = $self->_table_name()
00690 #  Description: ABSTRACT PROTECTED
00691 #               Subclasses are responsible for implementing this
00692 #               method.  It should list of [tablename, alias] pairs.
00693 #               Additionally the primary table (with the dbID,
00694 #               analysis_id, and score) should be the first table in
00695 #               the list. e.g:
00696 #               ( ['repeat_feature',   'rf'],
00697 #                 ['repeat_consensus', 'rc']);
00698 #               used to obtain features.  
00699 #  Returntype : list of [tablename, alias] pairs
00700 #  Exceptions : thrown if not implemented by subclass
00701 #  Caller     : BaseFeatureAdaptor::generic_fetch
00702 #
00703 
00704 sub _tables {
00705   throw(   "abstract method _tables not defined "
00706          . "by implementing subclass of BaseAdaptor" );
00707 }
00708 
00709 
00710 #_columns
00711 #
00712 #  Args       : none
00713 #  Example    : $tablename = $self->_columns()
00714 #  Description: ABSTRACT PROTECTED
00715 #               Subclasses are responsible for implementing this
00716 #               method.  It should return a list of columns to be
00717 #               used for feature creation.
00718 #  Returntype : list of strings
00719 #  Exceptions : thrown if not implemented by subclass
00720 #  Caller     : BaseFeatureAdaptor::generic_fetch
00721 #
00722 
00723 sub _columns {
00724   throw(   "abstract method _columns not defined "
00725          . "by implementing subclass of BaseAdaptor" );
00726 }
00727 
00728 
00729 # _default_where_clause
00730 #
00731 #  Arg [1]    : none
00732 #  Example    : none
00733 #  Description: May be overridden to provide an additional where
00734 #               constraint to the SQL query which is generated to
00735 #               fetch feature records.  This constraint is always
00736 #               appended to the end of the generated where clause
00737 #  Returntype : string
00738 #  Exceptions : none
00739 #  Caller     : generic_fetch
00740 #
00741 
00742 sub _default_where_clause { return '' }
00743 
00744 
00745 # _left_join
00746 
00747 #  Arg [1]    : none
00748 #  Example    : none
00749 #  Description: Can be overridden by a subclass to specify any left
00750 #               joins which should occur.  The table name specigfied
00751 #               in the join must still be present in the return
00752 #               values of.
00753 #  Returntype : a {'tablename' => 'join condition'} pair
00754 #  Exceptions : none
00755 #  Caller     : general
00756 #
00757 
00758 sub _left_join { return () }
00759 
00760 
00761 #_final_clause
00762 
00763 #  Arg [1]    : none
00764 #  Example    : none
00765 #  Description: May be overriden to provide an additional clause
00766 #               to the end of the SQL query used to fetch feature
00767 #               records.  This is useful to add a required ORDER BY
00768 #               clause to the query for example.
00769 #  Returntype : string
00770 #  Exceptions : none
00771 #  Caller     : generic_fetch
00772 
00773 sub _final_clause { return '' }
00774 
00775 
00776 #_objs_from_sth
00777 
00778 #  Arg [1]    : DBI::row_hashref $hashref containing key-value pairs 
00779 #               for each of the columns specified by the _columns method
00780 #  Example    : my @feats = $self->_obj_from_hashref
00781 #  Description: ABSTRACT PROTECTED
00782 #               The subclass is responsible for implementing this
00783 #               method.  It should take in a DBI row hash reference
00784 #               and return a list of created features in contig
00785 #               coordinates.
00786 #  Returntype : list of Bio::EnsEMBL::*Features in contig coordinates
00787 #  Exceptions : thrown if not implemented by subclass
00788 #  Caller     : BaseFeatureAdaptor::generic_fetch
00789 
00790 sub _objs_from_sth {
00791   throw(   "abstract method _objs_from_sth not defined "
00792          . "by implementing subclass of BaseAdaptor" );
00793 }
00794 
00795 sub dump_data {
00796   my $self = shift;
00797   my $data = shift;
00798 
00799   my $dumper = Data::Dumper->new([$data]);
00800   $dumper->Indent(0);
00801   $dumper->Terse(1);
00802    my $dump = $dumper->Dump();
00803 # $dump =~ s/'/\\'/g; 
00804  # $dump =~ s/^\$VAR1 = //;
00805   return $dump;
00806 }
00807 
00808 sub get_dumped_data {
00809     my $self = shift;
00810     my $data = shift;
00811 
00812     $data =~ s/\n|\r|\f|\\//g;
00813     return eval ($data);
00814 }
00815 
00816 
00817 1;