Commit 847ebd02 authored by Daniel Rios's avatar Daniel Rios
Browse files

moved query constructors to BaseAdaptor module

parent 032fb3d4
......@@ -93,7 +93,6 @@ use strict;
use Bio::EnsEMBL::Root;
use Bio::EnsEMBL::Utils::Exception qw(throw);
@ISA = qw(Bio::EnsEMBL::Root);
......@@ -210,4 +209,335 @@ sub _list_dbIDs {
return \@out;
}
# _straight_join
# Arg [1] : (optional) boolean $new_val
# Example : $self->_straight_join(1);
# $self->generic_fetch($constraint);
# $self->_straight_join(0);
# Description: PROTECTED Getter/Setter that turns on/off the use of
# a straight join in queries.
# Returntype : boolean
# Exceptions : none
# Caller : general
sub _straight_join {
my $self = shift;
if(@_) {
$self->{'_straight_join'} = shift;
}
return $self->{'_straight_join'};
}
=head2 generic_fetch
Arg [1] : (optional) string $constraint
An SQL query constraint (i.e. part of the WHERE clause)
Arg [2] : (optional) Bio::EnsEMBL::AssemblyMapper $mapper
A mapper object used to remap features
as they are retrieved from the database
Arg [3] : (optional) Bio::EnsEMBL::Slice $slice
A slice that features should be remapped to
Example : $fts = $a->generic_fetch('contig_id in (1234, 1235)', 'Swall');
Description: Performs a database fetch and returns feature objects in
contig coordinates.
Returntype : listref of Bio::EnsEMBL::SeqFeature in contig coordinates
Exceptions : none
Caller : BaseFeatureAdaptor, ProxyDnaAlignFeatureAdaptor::generic_fetch
=cut
sub generic_fetch {
my ($self, $constraint, $mapper, $slice) = @_;
my @tabs = $self->_tables;
my $columns = join(', ', $self->_columns());
my $db = $self->db();
#
# Construct a left join statement if one was defined, and remove the
# left-joined table from the table list
#
my @left_join_list = $self->_left_join();
my $left_join = '';
my @tables;
if(@left_join_list) {
my %left_join_hash = map { $_->[0] => $_->[1] } @left_join_list;
while(my $t = shift @tabs) {
if( exists $left_join_hash{ $t->[0] } ) {
my $condition = $left_join_hash{ $t->[0] };
my $syn = $t->[1];
$left_join .= "LEFT JOIN\n ".$t->[0]." $syn ON $condition ";
} else {
push @tables, $t;
}
}
} else {
@tables = @tabs;
}
my $straight_join = '';
if($self->_straight_join()) {
$straight_join = "STRAIGHT_JOIN";
}
#construct a nice table string like 'table1 t1, table2 t2'
my $tablenames = join(', ', map({ join(' ', @$_) } @tables));
my $sql = "SELECT $straight_join $columns\n FROM $tablenames $left_join";
my $default_where = $self->_default_where_clause;
my $final_clause = $self->_final_clause;
#append a where clause if it was defined
if($constraint) {
$sql .= "\n WHERE $constraint ";
if($default_where) {
$sql .= " AND\n $default_where ";
}
} elsif($default_where) {
$sql .= "\n WHERE $default_where ";
}
#append additional clauses which may have been defined
$sql .= "\n$final_clause";
my $sth = $db->dbc->prepare($sql);
$sth->execute;
my $res = $self->_objs_from_sth($sth, $mapper, $slice);
return $res;
}
=head2 fetch_by_dbID
Arg [1] : int $id
The unique database identifier for the feature to be obtained
Example : $feat = $adaptor->fetch_by_dbID(1234));
$feat = $feat->transform('contig');
Description: Returns the feature created from the database defined by the
the id $id. The feature will be returned in its native
coordinate system. That is, the coordinate system in which it
is stored in the database. In order to convert it to a
particular coordinate system use the transfer() or transform()
method. If the feature is not found in the database then
undef is returned instead
Returntype : Bio::EnsEMBL::Feature or undef
Exceptions : thrown if $id arg is not provided
does not exist
Caller : general
=cut
sub fetch_by_dbID{
my ($self,$id) = @_;
throw("id argument is required") if(!defined $id);
#construct a constraint like 't1.table1_id = 123'
my @tabs = $self->_tables;
my ($name, $syn) = @{$tabs[0]};
my $constraint = "${syn}.${name}_id = $id";
#Should only be one
my ($feat) = @{$self->generic_fetch($constraint)};
return undef if(!$feat);
return $feat;
}
=head2 fetch_all_by_dbID_list
Arg [1] : listref of ints $id_list
The unique database identifiers for the features to be obtained
Example : @feats = @{$adaptor->fetch_by_dbID_list([1234, 2131, 982]))};
Description: Returns the features created from the database defined by the
the ids in contained in the id list $id_list. The features
will be returned in their native coordinate system. That is,
the coordinate system in which they are stored in the database.
In order to convert the features to a particular coordinate
system use the transfer() or transform() method. If none of the
features are found in the database a reference to an empty
list is returned.
Returntype : listref of Bio::EnsEMBL::Features
Exceptions : thrown if $id arg is not provided
does not exist
Caller : general
=cut
sub fetch_all_by_dbID_list {
my ($self,$id_list) = @_;
if(!defined($id_list) || ref($id_list) ne 'ARRAY') {
throw("id_list list reference argument is required");
}
return [] if(!@$id_list);
my @out;
#construct a constraint like 't1.table1_id = 123'
my @tabs = $self->_tables;
my ($name, $syn) = @{$tabs[0]};
# mysql is faster and we ensure that we do not exceed the max query size by
# splitting large queries into smaller queries of 200 ids
my $max_size = 200;
while(@$id_list) {
my @ids;
if(@$id_list > $max_size) {
@ids = splice(@$id_list, 0, $max_size);
} else {
@ids = splice(@$id_list, 0);
}
my $id_str;
if(@ids > 1) {
$id_str = " IN (" . join(',', @ids). ")";
} else {
$id_str = " = " . $ids[0];
}
my $constraint = "${syn}.${name}_id $id_str";
push @out, @{$self->generic_fetch($constraint)};
}
return \@out;
}
#_tables
#
# Args : none
# Example : $tablename = $self->_table_name()
# Description: ABSTRACT PROTECTED Subclasses are responsible for implementing
# this method. It should list of [tablename, alias] pairs.
# Additionally the primary table (with the dbID, analysis_id, and
# score) should be the first table in the list.
# e.g:
# ( ['repeat_feature', 'rf'],
# ['repeat_consensus', 'rc']);
# used to obtain features.
# Returntype : list of [tablename, alias] pairs
# Exceptions : thrown if not implemented by subclass
# Caller : BaseFeatureAdaptor::generic_fetch
#
sub _tables {
my $self = shift;
throw("abstract method _tables not defined by implementing" .
" subclass of BaseFeatureAdaptor");
return undef;
}
#_columns
#
# Args : none
# Example : $tablename = $self->_columns()
# Description: ABSTRACT PROTECTED Subclasses are responsible for implementing
# this method. It should return a list of columns to be used
# for feature creation
# Returntype : list of strings
# Exceptions : thrown if not implemented by subclass
# Caller : BaseFeatureAdaptor::generic_fetch
#
sub _columns {
my $self = shift;
throw("abstract method _columns not defined by implementing" .
" subclass of BaseFeatureAdaptor");
}
# _default_where_clause
#
# Arg [1] : none
# Example : none
# Description: May be overridden to provide an additional where constraint to
# the SQL query which is generated to fetch feature records.
# This constraint is always appended to the end of the generated
# where clause
# Returntype : string
# Exceptions : none
# Caller : generic_fetch
#
sub _default_where_clause {
my $self = shift;
return '';
}
# _left_join
# Arg [1] : none
# Example : none
# Description: Can be overridden by a subclass to specify any left joins
# which should occur. The table name specigfied in the join
# must still be present in the return values of
# Returntype : a {'tablename' => 'join condition'} pair
# Exceptions : none
# Caller : general
#
sub _left_join {
my $self = shift;
return ();
}
#_final_clause
# Arg [1] : none
# Example : none
# Description: May be overriden to provide an additional clause to the end
# of the SQL query used to fetch feature records.
# This is useful to add a required ORDER BY clause to the
# query for example.
# Returntype : string
# Exceptions : none
# Caller : generic_fetch
sub _final_clause {
my $self = shift;
return '';
}
#_objs_from_sth
# Arg [1] : DBI::row_hashref $hashref containing key-value pairs
# for each of the columns specified by the _columns method
# Example : my @feats = $self->_obj_from_hashref
# Description: ABSTRACT PROTECTED The subclass is responsible for implementing
# this method. It should take in a DBI row hash reference and
# return a list of created features in contig coordinates.
# Returntype : list of Bio::EnsEMBL::*Features in contig coordinates
# Exceptions : thrown if not implemented by subclass
# Caller : BaseFeatureAdaptor::generic_fetch
sub _objs_from_sth {
my $self = shift;
throw("abstract method _obj_from_sth not defined by implementing"
. " subclass of BaseFeatureAdaptor");
}
1;
......@@ -71,217 +71,6 @@ sub new {
}
# _straight_join
# Arg [1] : (optional) boolean $new_val
# Example : $self->_straight_join(1);
# $self->generic_fetch($constraint);
# $self->_straight_join(0);
# Description: PROTECTED Getter/Setter that turns on/off the use of
# a straight join in queries.
# Returntype : boolean
# Exceptions : none
# Caller : general
sub _straight_join {
my $self = shift;
if(@_) {
$self->{'_straight_join'} = shift;
}
return $self->{'_straight_join'};
}
=head2 generic_fetch
Arg [1] : (optional) string $constraint
An SQL query constraint (i.e. part of the WHERE clause)
Arg [2] : (optional) Bio::EnsEMBL::AssemblyMapper $mapper
A mapper object used to remap features
as they are retrieved from the database
Arg [3] : (optional) Bio::EnsEMBL::Slice $slice
A slice that features should be remapped to
Example : $fts = $a->generic_fetch('contig_id in (1234, 1235)', 'Swall');
Description: Performs a database fetch and returns feature objects in
contig coordinates.
Returntype : listref of Bio::EnsEMBL::SeqFeature in contig coordinates
Exceptions : none
Caller : BaseFeatureAdaptor, ProxyDnaAlignFeatureAdaptor::generic_fetch
=cut
sub generic_fetch {
my ($self, $constraint, $mapper, $slice) = @_;
my @tabs = $self->_tables;
my $columns = join(', ', $self->_columns());
my $db = $self->db();
#
# Construct a left join statement if one was defined, and remove the
# left-joined table from the table list
#
my @left_join_list = $self->_left_join();
my $left_join = '';
my @tables;
if(@left_join_list) {
my %left_join_hash = map { $_->[0] => $_->[1] } @left_join_list;
while(my $t = shift @tabs) {
if( exists $left_join_hash{ $t->[0] } ) {
my $condition = $left_join_hash{ $t->[0] };
my $syn = $t->[1];
$left_join .= "LEFT JOIN\n ".$t->[0]." $syn ON $condition ";
} else {
push @tables, $t;
}
}
} else {
@tables = @tabs;
}
my $straight_join = '';
if($self->_straight_join()) {
$straight_join = "STRAIGHT_JOIN";
}
#construct a nice table string like 'table1 t1, table2 t2'
my $tablenames = join(', ', map({ join(' ', @$_) } @tables));
my $sql = "SELECT $straight_join $columns\n FROM $tablenames $left_join";
my $default_where = $self->_default_where_clause;
my $final_clause = $self->_final_clause;
#append a where clause if it was defined
if($constraint) {
$sql .= "\n WHERE $constraint ";
if($default_where) {
$sql .= " AND\n $default_where ";
}
} elsif($default_where) {
$sql .= "\n WHERE $default_where ";
}
#append additional clauses which may have been defined
$sql .= "\n$final_clause";
my $sth = $db->dbc->prepare($sql);
$sth->execute;
my $res = $self->_objs_from_sth($sth, $mapper, $slice);
return $res;
}
=head2 fetch_by_dbID
Arg [1] : int $id
The unique database identifier for the feature to be obtained
Example : $feat = $adaptor->fetch_by_dbID(1234));
$feat = $feat->transform('contig');
Description: Returns the feature created from the database defined by the
the id $id. The feature will be returned in its native
coordinate system. That is, the coordinate system in which it
is stored in the database. In order to convert it to a
particular coordinate system use the transfer() or transform()
method. If the feature is not found in the database then
undef is returned instead
Returntype : Bio::EnsEMBL::Feature or undef
Exceptions : thrown if $id arg is not provided
does not exist
Caller : general
=cut
sub fetch_by_dbID{
my ($self,$id) = @_;
throw("id argument is required") if(!defined $id);
#construct a constraint like 't1.table1_id = 123'
my @tabs = $self->_tables;
my ($name, $syn) = @{$tabs[0]};
my $constraint = "${syn}.${name}_id = $id";
#Should only be one
my ($feat) = @{$self->generic_fetch($constraint)};
return undef if(!$feat);
return $feat;
}
=head2 fetch_all_by_dbID_list
Arg [1] : listref of ints $id_list
The unique database identifiers for the features to be obtained
Example : @feats = @{$adaptor->fetch_by_dbID_list([1234, 2131, 982]))};
Description: Returns the features created from the database defined by the
the ids in contained in the id list $id_list. The features
will be returned in their native coordinate system. That is,
the coordinate system in which they are stored in the database.
In order to convert the features to a particular coordinate
system use the transfer() or transform() method. If none of the
features are found in the database a reference to an empty
list is returned.
Returntype : listref of Bio::EnsEMBL::Features
Exceptions : thrown if $id arg is not provided
does not exist
Caller : general
=cut
sub fetch_all_by_dbID_list {
my ($self,$id_list) = @_;
if(!defined($id_list) || ref($id_list) ne 'ARRAY') {
throw("id_list list reference argument is required");
}
return [] if(!@$id_list);
my @out;
#construct a constraint like 't1.table1_id = 123'
my @tabs = $self->_tables;
my ($name, $syn) = @{$tabs[0]};
# mysql is faster and we ensure that we do not exceed the max query size by
# splitting large queries into smaller queries of 200 ids
my $max_size = 200;
while(@$id_list) {
my @ids;
if(@$id_list > $max_size) {
@ids = splice(@$id_list, 0, $max_size);
} else {
@ids = splice(@$id_list, 0);
}
my $id_str;
if(@ids > 1) {
$id_str = " IN (" . join(',', @ids). ")";
} else {
$id_str = " = " . $ids[0];
}
my $constraint = "${syn}.${name}_id $id_str";
push @out, @{$self->generic_fetch($constraint)};
}
return \@out;
}
=head2 fetch_all_by_Slice
Arg [1] : Bio::EnsEMBL::Slice $slice
......@@ -914,137 +703,6 @@ sub remove_by_Slice {
}
#_tables
#
# Args : none
# Example : $tablename = $self->_table_name()
# Description: ABSTRACT PROTECTED Subclasses are responsible for implementing
# this method. It should list of [tablename, alias] pairs.
# Additionally the primary table (with the dbID, analysis_id, and
# score) should be the first table in the list.
# e.g:
# ( ['repeat_feature', 'rf'],
# ['repeat_consensus', 'rc']);
# used to obtain features.
# Returntype : list of [tablename, alias] pairs
# Exceptions : thrown if not implemented by subclass
# Caller : BaseFeatureAdaptor::generic_fetch
#
sub _tables {
my $self = shift;
throw("abstract method _tables not defined by implementing" .
" subclass of BaseFeatureAdaptor");
return undef;
}
#_columns
#
# Args : none
# Example : $tablename = $self->_columns()
# Description: ABSTRACT PROTECTED Subclasses are responsible for implementing
# this method. It should return a list of columns to be used
# for feature creation
# Returntype : list of strings
# Exceptions : thrown if not implemented by subclass
# Caller : BaseFeatureAdaptor::generic_fetch
#
sub _columns {
my $self = shift;
throw("abstract method _columns not defined by implementing" .
" subclass of BaseFeatureAdaptor");
}