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
40 # $db is a Bio::EnsEMBL::DBSQL::DBAdaptor object:
41 $attribute_adaptor = $db->get_AttributeAdaptor();
43 $attributes = $attribute_adaptor->fetch_all_by_MiscFeature($feature);
45 $attributes = $attribute_adaptor->fetch_all_by_Slice($slice);
47 $attribute_adaptor->store_on_Slice( $slice, \@attributes );
49 $attribute_adaptor->store_on_MiscFeature( $misc_feature,
58 package Bio::EnsEMBL::DBSQL::AttributeAdaptor;
77 Returntype : Bio::EnsEMBL::AttributeAdaptor
87 my $self = $class->SUPER::new(@_);
89 # cache creation could go here
99 sub store_batch_on_Object {
100 my ($self, $table, $attributes, $batch_size) = @_;
101 # $attributes is a hashref where the key is the object ID
102 # and the value is an array ref of Attribute objects
104 # maintain a hash of attrib type IDs by code so we don't have to keep looking them up...
105 my $attrib_type_ids = {};
107 # create an arrayref of the values to store
109 $batch_size ||= scalar(values(%$attributes));
111 while (my ($obj_id, $attribs) = each %{$attributes}) {
112 for my $attrib (@{$attribs}) {
114 my $attrib_type_id = $attrib_type_ids->{$attrib->code()};
115 if (!defined $attrib_type_id) {
116 $attrib_type_id = $self->_store_type($attrib);
117 $attrib_type_ids->{$attrib->code()} = $attrib_type_id;
120 push @$rows, sprintf(
'(%d, %d, %s)', $obj_id, $attrib_type_id, $self->dbc()->db_handle()->quote($attrib->value()));
122 if (scalar(@$rows) == $batch_size) {
123 $rows = $self->_store_batch_rows($table, $rows);
128 $rows = $self->_store_batch_rows($table, $rows);
133 sub _store_batch_rows {
134 my ($self, $table, $rows) = @_;
135 if (scalar(@$rows) > 0) {
136 $self->dbc()->sql_helper()->execute_update(-SQL =>
'INSERT INTO ' . $table .
'_attrib(' . $table .
'_id, attrib_type_id, value) VALUES ' . join(
',', @$rows));
142 sub store_batch_on_MiscAttrib {
143 my ($self, $attributes, $batch_size) = @_;
145 $self->store_batch_on_Object(
'misc_feature', $attributes, $batch_size);
150 sub store_batch_on_Slice {
151 my ($self, $attributes, $batch_size) = @_;
153 $self->store_batch_on_Object(
'seq_region', $attributes, $batch_size);
158 sub store_batch_on_Gene {
159 my ($self, $attributes, $batch_size) = @_;
161 $self->store_batch_on_Object(
'gene', $attributes, $batch_size);
166 sub store_batch_on_Transcript {
167 my ($self, $attributes, $batch_size) = @_;
169 $self->store_batch_on_Object(
'transcript', $attributes, $batch_size);
174 sub store_batch_on_Translation {
175 my ($self, $attributes, $batch_size) = @_;
177 $self->store_batch_on_Object(
'translation', $attributes, $batch_size);
182 sub store_batch_on_DnaDnaAlignFeature {
183 my ($self, $attributes, $batch_size) = @_;
185 $self->store_batch_on_Object(
'dna_align_feature', $attributes, $batch_size);
193 sub store_on_Object {
194 my ($self, $object_id, $attributes, $table, $type) = @_;
196 my $db = $self->db();
197 if (!defined $type) {
201 my $insert_ignore = $self->insert_ignore_clause();
202 my $sth = $self->prepare(
"${insert_ignore} INTO ${table}_attrib (${type}_id, attrib_type_id, value)" .
203 "VALUES (?, ?, ?)" );
205 for my $attrib ( @$attributes ) {
206 if(!ref($attrib) && $attrib->isa(
'Bio::EnsEMBL::Attribute')) {
207 throw(
"Reference to list of Bio::EnsEMBL::Attribute objects " .
208 "argument expected.");
211 my $atid = $self->_store_type( $attrib );
212 $sth->bind_param(1,$object_id,SQL_INTEGER);
213 $sth->bind_param(2,$atid,SQL_INTEGER);
214 $sth->bind_param(3,$attrib->value,SQL_VARCHAR);
222 sub store_on_MiscFeature {
223 my ($self, $object, $attributes) = @_;
225 assert_ref( $object,
'Bio::EnsEMBL::MiscFeature');
227 my $object_id = $object->dbID();
228 $self->store_on_Object($object_id, $attributes,
'misc',
'misc_feature');
234 my ($self, $object, $attributes) = @_;
236 assert_ref( $object,
'Bio::EnsEMBL::Slice');
238 my $object_id = $object->get_seq_region_id();
239 $self->store_on_Object($object_id, $attributes,
'seq_region');
241 my $undef_circular_cache = 0;
242 for my $attrib ( @$attributes ) {
243 if ((defined $attrib->code) and ($attrib->code eq
'circular_seq')) {
244 $undef_circular_cache = 1;
248 if ($undef_circular_cache) {
249 #the slice is circular
250 $object->{
'circular'} = 1;
251 my $slice_adaptor = $object->adaptor();
252 #undefine slice adaptor->is_circular and the circular slice cache
253 if (defined $slice_adaptor) {
254 $slice_adaptor->{
'is_circular'} = undef;
255 $slice_adaptor->{
'circular_sr_id_cache'} = {};
263 my ($self, $object, $attributes) = @_;
267 $object_id = $object;
270 $object_id = $object->dbID;
273 $self->store_on_Object($object_id, $attributes,
'gene');
278 sub store_on_Transcript {
279 my ($self, $object, $attributes) = @_;
283 $object_id = $object;
286 $object_id = $object->dbID;
289 $self->store_on_Object($object_id, $attributes,
'transcript');
294 sub store_on_RNAProduct {
295 my ($self, $object, $attributes) = @_;
299 $object_id = $object;
302 $object_id = $object->dbID();
305 $self->store_on_Object($object_id, $attributes,
'rnaproduct');
310 sub store_on_Translation {
311 my ($self, $object, $attributes) = @_;
315 $object_id = $object;
318 $object_id = $object->dbID;
321 $self->store_on_Object($object_id, $attributes,
'translation');
326 sub store_on_DnaDnaAlignFeature {
327 my ($self, $object, $attributes) = @_;
331 $object_id = $object;
334 $object_id = $object->dbID;
337 $self->store_on_Object($object_id, $attributes,
'dna_align_feature');
345 sub remove_from_Object {
346 my ($self, $object_id, $table, $code, $type) = @_;
348 my $db = $self->db();
350 if(!defined($object_id)) {
351 throw(
"$table must have dbID.");
353 if (!defined($type)) {
358 if (defined($code)) {
359 if ($db->dbc->driver() eq
'mysql') {
360 $sth = $self->prepare(
"DELETE a FROM " . $table .
"_attrib a, attrib_type at " .
361 "WHERE a.attrib_type_id = at.attrib_type_id AND ".
362 "a." . $type .
"_id = ? AND ".
365 $sth = $self->prepare(qq{DELETE FROM ${table}_attrib
366 WHERE ${type}_id = ? AND
368 (SELECT attrib_type_id
370 WHERE code LIKE ? ) });
372 $sth->bind_param(1,$object_id,SQL_INTEGER);
373 $sth->bind_param(2,$code,SQL_VARCHAR);
376 $sth = $self->prepare(
"DELETE FROM " . $table .
"_attrib " .
377 "WHERE " . $type .
"_id = ?");
378 $sth->bind_param(1,$object_id,SQL_INTEGER);
388 sub remove_from_MiscFeature {
389 my ($self, $object, $code) = @_;
391 assert_ref($object,
'Bio::EnsEMBL::MiscFeature');
393 my $object_id = $object->dbID();
394 $self->remove_from_Object($object_id,
'misc', $code,
'misc_feature');
400 sub remove_from_Slice {
401 my ($self, $object, $code) = @_;
403 assert_ref($object,
'Bio::EnsEMBL::Slice');
405 my $object_id = $object->get_seq_region_id();
406 $self->remove_from_Object($object_id,
'seq_region', $code);
412 sub remove_from_Gene {
413 my ($self, $object, $code) = @_;
415 assert_ref($object,
'Bio::EnsEMBL::Gene');
417 my $object_id = $object->dbID();
418 $self->remove_from_Object($object_id,
'gene', $code);
424 sub remove_from_Transcript {
425 my ($self, $object, $code) = @_;
427 assert_ref($object,
'Bio::EnsEMBL::Transcript');
429 my $object_id = $object->dbID();
430 $self->remove_from_Object($object_id,
'transcript', $code);
436 sub remove_from_RNAProduct {
437 my ($self, $object, $code) = @_;
439 assert_ref($object,
'Bio::EnsEMBL::RNAProduct');
441 my $object_id = $object->dbID();
442 $self->remove_from_Object($object_id,
'rnaproduct', $code);
448 sub remove_from_Translation {
449 my ($self, $object, $code) = @_;
451 assert_ref($object,
'Bio::EnsEMBL::Translation');
453 my $object_id = $object->dbID();
454 $self->remove_from_Object($object_id,
'translation', $code);
460 sub remove_from_DnaDnaAlignFeature {
461 my ($self, $object, $code) = @_;
463 assert_ref($object,
'Bio::EnsEMBL::DnaDnaAlignFeature');
465 my $object_id = $object->dbID();
466 $self->remove_from_Object($object_id,
'dna_align_feature', $code);
477 throw(
"Use of method fetch_all not supported for attributes");
481 my ($self, $code) = @_;
483 my $sql =
"SELECT attrib_type_id, code, name, description " .
485 WHERE code = '$code' ";
486 my $sth = $self->prepare($sql);
489 my ($attrib_type_id, $name, $desc);
490 $sth->bind_columns(\$attrib_type_id, \$code, \$name, \$desc);
492 my @results = $sth->fetchrow_array;
500 sub fetch_all_by_Object {
501 my ($self, $object_id, $table, $code, $type) = @_;
503 if (!defined $type) {
507 my $sql =
"SELECT at.code, at.name, at.description, a.value " .
508 "FROM " . $table .
"_attrib a, attrib_type at " .
509 "WHERE at.attrib_type_id = a.attrib_type_id ";
511 if (defined($code)) {
512 $sql .=
'AND at.code like "' . $code .
'" ';
514 if (defined($object_id)) {
515 $sql .=
"AND a." .$type .
"_id = " . $object_id;
518 my $sth = $self->prepare($sql);
520 my $results = $self->_obj_from_sth($sth);
527 sub fetch_all_by_MiscFeature {
528 my ($self, $object, $code) = @_;
532 if (defined($object)) {
533 assert_ref($object,
'Bio::EnsEMBL::MiscFeature');
534 $object_id = $object->dbID();
537 my $results = $self->fetch_all_by_Object($object_id,
'misc', $code,
'misc_feature');
543 sub fetch_all_by_Slice {
544 my ($self, $object, $code) = @_;
548 if (defined($object)) {
549 assert_ref($object,
'Bio::EnsEMBL::Slice');
550 $object_id = $object->get_seq_region_id();
553 my $results = $self->fetch_all_by_Object($object_id,
'seq_region', $code);
559 sub fetch_all_by_Gene {
560 my ($self, $object, $code) = @_;
564 if (defined($object)) {
565 assert_ref($object,
'Bio::EnsEMBL::Gene');
566 $object_id = $object->dbID();
569 my $results = $self->fetch_all_by_Object($object_id,
'gene', $code);
575 sub fetch_all_by_Transcript {
576 my ($self, $object, $code) = @_;
580 if (defined($object)) {
581 assert_ref($object,
'Bio::EnsEMBL::Transcript');
582 $object_id = $object->dbID();
585 my $results = $self->fetch_all_by_Object($object_id,
'transcript', $code);
591 sub fetch_all_by_Translation {
592 my ($self, $object, $code) = @_;
596 if (defined($object)) {
597 assert_ref($object,
'Bio::EnsEMBL::Translation');
598 $object_id = $object->dbID();
601 my $results = $self->fetch_all_by_Object($object_id,
'translation', $code);
607 sub fetch_all_by_RNAProduct {
608 my ($self, $object, $code) = @_;
612 if (defined($object)) {
613 assert_ref($object,
'Bio::EnsEMBL::RNAProduct');
614 $object_id = $object->dbID();
617 my $results = $self->fetch_all_by_Object($object_id,
'rnaproduct', $code);
623 sub fetch_all_by_DnaDnaAlignFeature {
624 my ($self, $object, $code) = @_;
628 if (defined($object)) {
629 assert_ref($object,
'Bio::EnsEMBL::DnaDnaAlignFeature');
630 $object_id = $object->dbID();
633 my $results = $self->fetch_all_by_Object($object_id,
'dna_align_feature', $code);
645 # backwards compatibility check:
646 # check if $ensID is an object; if so, return $obj->dbID
653 if ($ensID =~ /^\d+$/) {
656 } elsif ( ref($ensID) eq
'Bio::EnsEMBL::Gene'
657 or ref($ensID) eq
'Bio::EnsEMBL::Transcript'
658 or ref($ensID) eq
'Bio::EnsEMBL::Translation')
661 warning(
"You should pass a dbID rather than an ensembl object to store the attribute on");
666 throw(
"Ensembl object " . $ensID->display_id .
" doesn't have a dbID, can't store attribute");
670 throw(
"Invalid dbID");
673 } ## end sub _id_check
681 my $insert_ignore = $self->insert_ignore_clause();
682 my $sth1 = $self->prepare
683 (
"${insert_ignore} INTO attrib_type (code, name, description) values (?, ?, ?)" );
686 $sth1->bind_param(1, $attrib->code, SQL_VARCHAR);
687 $sth1->bind_param(2, $attrib->name, SQL_VARCHAR);
688 $sth1->bind_param(3, $attrib->description, SQL_LONGVARCHAR);
690 my $rows_inserted = $sth1->execute();
692 my $atid = $self->last_insert_id(
'attrib_type_id', undef,
'attrib_type');
694 if ($rows_inserted == 0) {
695 # the insert failed because the code is already stored
696 my $sth2 = $self->prepare(
"SELECT attrib_type_id FROM attrib_type " .
"WHERE code = ?");
697 $sth2->bind_param(1, $attrib->code, SQL_VARCHAR);
699 ($atid) = $sth2->fetchrow_array();
704 throw(
"Could not store or fetch attrib_type code [" . $attrib->code .
"]\n" .
"Wrong database user/permissions?");
711 } ## end sub _store_type
717 my ($code, $name, $desc, $value);
718 $sth->bind_columns(\$code, \$name, \$desc, \$value);
721 while ($sth->fetch()) {
725 'description' => $desc,