0
|
1 =head1 LICENSE
|
|
2
|
|
3 Copyright (c) 1999-2012 The European Bioinformatics Institute and
|
|
4 Genome Research Limited. All rights reserved.
|
|
5
|
|
6 This software is distributed under a modified Apache license.
|
|
7 For license details, please see
|
|
8
|
|
9 http://www.ensembl.org/info/about/code_licence.html
|
|
10
|
|
11 =head1 CONTACT
|
|
12
|
|
13 Please email comments or questions to the public Ensembl
|
|
14 developers list at <dev@ensembl.org>.
|
|
15
|
|
16 Questions may also be sent to the Ensembl help desk at
|
|
17 <helpdesk@ensembl.org>.
|
|
18
|
|
19 =cut
|
|
20
|
|
21 =head1 NAME
|
|
22
|
|
23 Bio::EnsEMBL::DBSQL::AttributeAdaptor - Provides database interaction for
|
|
24 Bio::EnsEMBL::Attribute objects.
|
|
25
|
|
26
|
|
27 =head1 SYNOPSIS
|
|
28
|
|
29 # $db is a Bio::EnsEMBL::DBSQL::DBAdaptor object:
|
|
30 $attribute_adaptor = $db->get_AttributeAdaptor();
|
|
31
|
|
32 $attributes = $attribute_adaptor->fetch_all_by_MiscFeature($feature);
|
|
33
|
|
34 $attributes = $attribute_adaptor->fetch_all_by_Slice($slice);
|
|
35
|
|
36 $attribute_adaptor->store_on_Slice( $slice, \@attributes );
|
|
37
|
|
38 $attribute_adaptor->store_on_MiscFeature( $misc_feature,
|
|
39 \@attributes )
|
|
40
|
|
41 =head1 DESCRIPTION
|
|
42
|
|
43 =head1 METHODS
|
|
44
|
|
45 =cut
|
|
46
|
|
47 package Bio::EnsEMBL::DBSQL::AttributeAdaptor;
|
|
48
|
|
49 use strict;
|
|
50 use warnings;
|
|
51
|
|
52 use Bio::EnsEMBL::DBSQL::BaseAdaptor;
|
|
53 use Bio::EnsEMBL::Attribute;
|
|
54
|
|
55 use Bio::EnsEMBL::Utils::Exception qw(throw warning);
|
|
56
|
|
57 use vars qw(@ISA);
|
|
58
|
|
59 @ISA = qw(Bio::EnsEMBL::DBSQL::BaseAdaptor);
|
|
60
|
|
61
|
|
62 =head2 new
|
|
63
|
|
64 Arg [...] : Superclass args. See Bio::EnsEMBL::DBSQL::BaseAdaptor
|
|
65 Description: Instantiates a Bio::EnsEMBL::DBSQL::AttributeAdaptor
|
|
66 Returntype : Bio::EnsEMBL::AttributeAdaptor
|
|
67 Exceptions : none
|
|
68 Caller : DBAdaptor
|
|
69 Status : Stable
|
|
70
|
|
71 =cut
|
|
72
|
|
73
|
|
74 sub new {
|
|
75 my $class = shift;
|
|
76
|
|
77 my $self = $class->SUPER::new(@_);
|
|
78
|
|
79
|
|
80 # cache creation could go here
|
|
81 return $self;
|
|
82 }
|
|
83
|
|
84 use vars '$AUTOLOAD';
|
|
85
|
|
86 sub AUTOLOAD {
|
|
87 my ($self,@args) = @_;
|
|
88 my @array_return=();
|
|
89 my $ref_return = undef;
|
|
90 $AUTOLOAD =~ /^.*::(\w+_)+(\w+)$/ ;
|
|
91
|
|
92 my $sub = $1;
|
|
93 my $type = $2;
|
|
94
|
|
95
|
|
96
|
|
97 # print STDERR "AUTO".$AUTOLOAD."\n";
|
|
98
|
|
99 # print STDERR "AUTOLOAD reached with call to $sub of type $type\n";
|
|
100 if($self->can($sub)){
|
|
101 return $self->$sub($type,@args);
|
|
102 }
|
|
103 else{
|
|
104 warn("In AttribAdaptor cannot call sub $sub$type\n");
|
|
105 }
|
|
106 return undef;
|
|
107 }
|
|
108
|
|
109
|
|
110
|
|
111 sub store_on_ {
|
|
112 my $self = shift;
|
|
113 my $type = shift;
|
|
114 my $object = shift;
|
|
115 my $attributes = shift;
|
|
116 my $table;
|
|
117
|
|
118
|
|
119 my $object_id;
|
|
120 if($type =~ /[GT][er][na][en]/){
|
|
121 if (!ref($object)){
|
|
122 $object_id = $object;
|
|
123 }
|
|
124 else {
|
|
125 $object_id = $object->dbID;
|
|
126 }
|
|
127 $table = lc($type);
|
|
128 # $type = lc($type);
|
|
129 }
|
|
130 else{
|
|
131 if(!ref($object) || !$object->isa('Bio::EnsEMBL::'.$type)) {
|
|
132 throw("$type argument is required. but you passed $object");
|
|
133 }
|
|
134 if($type eq "Slice"){
|
|
135 $object_id = $object->get_seq_region_id();
|
|
136 $table = "seq_region";
|
|
137 $type = "seq_region";
|
|
138 }
|
|
139 else{
|
|
140 if($type eq "MiscFeature"){
|
|
141 $type = "misc_feature";
|
|
142 $table = "misc";
|
|
143 }
|
|
144 else{
|
|
145 $table = lc($type);
|
|
146 }
|
|
147
|
|
148 $object_id = $object->dbID();
|
|
149 my $db = $self->db();
|
|
150
|
|
151 if(!$object->is_stored($db)) {
|
|
152 throw("$type is not stored in this database.");
|
|
153 }
|
|
154
|
|
155 }
|
|
156 }
|
|
157 my $sth = $self->prepare( "INSERT into ".$table."_attrib ".
|
|
158 "SET ".$type."_id = ?, attrib_type_id = ?, ".
|
|
159 "value = ? " );
|
|
160
|
|
161 my $undef_circular_cache = 0;
|
|
162 for my $attrib ( @$attributes ) {
|
|
163 if(!ref($attrib) && $attrib->isa('Bio::EnsEMBL::Attribute')) {
|
|
164 throw("Reference to list of Bio::EnsEMBL::Attribute objects " .
|
|
165 "argument expected.");
|
|
166 }
|
|
167 my $atid = $self->_store_type( $attrib );
|
|
168 if ((defined $attrib->code) and ($attrib->code eq 'circular_seq')) {
|
|
169 $undef_circular_cache = 1;
|
|
170 }
|
|
171 $sth->bind_param(1,$object_id,SQL_INTEGER);
|
|
172 $sth->bind_param(2,$atid,SQL_INTEGER);
|
|
173 $sth->bind_param(3,$attrib->value,SQL_VARCHAR);
|
|
174 $sth->execute();
|
|
175 }
|
|
176
|
|
177 if($table eq "seq_region") {
|
|
178 if ($undef_circular_cache) {
|
|
179 #the slice is circular
|
|
180 $object->{'circular'} = 1;
|
|
181 my $slice_adaptor = $object->adaptor();
|
|
182 #undefine slice adaptor->is_circular and the circular slice cache
|
|
183 if (defined $slice_adaptor) {
|
|
184 $slice_adaptor->{'is_circular'} = undef;
|
|
185 $slice_adaptor->{'circular_sr_id_cache'} = {};
|
|
186 }
|
|
187 }
|
|
188 }
|
|
189
|
|
190 return;
|
|
191 }
|
|
192
|
|
193
|
|
194 sub remove_from_{
|
|
195 my $self = shift;
|
|
196 my $type = shift;
|
|
197 my $object = shift;
|
|
198 my $code = shift;
|
|
199 my $table;
|
|
200
|
|
201 if(!ref($object) || !$object->isa('Bio::EnsEMBL::'.$type)) {
|
|
202 throw("$type argument is required or a attrib code. but you passed $object");
|
|
203 }
|
|
204
|
|
205 my $object_id;
|
|
206 if($type eq "Slice"){
|
|
207 $object_id = $object->get_seq_region_id();
|
|
208 $table = "seq_region";
|
|
209 $type = "seq_region";
|
|
210 if ((defined $code) and ($code eq 'circular_seq')) {
|
|
211 #undefine slice->is_circular, slice adaptor->is_circular and the circular slice cache
|
|
212 $object->{'circular'} = undef;
|
|
213 my $slice_adaptor = $object->adaptor();
|
|
214 if (defined $slice_adaptor) {
|
|
215 $slice_adaptor->{'is_circular'} = undef;
|
|
216 $slice_adaptor->{'circular_sr_id_cache'} = {};
|
|
217 }
|
|
218 }
|
|
219 }
|
|
220 else{
|
|
221 if($type eq "MiscFeature"){
|
|
222 $type = "misc_feature";
|
|
223 $table = "misc";
|
|
224 }
|
|
225 else{
|
|
226 $table = lc($type);
|
|
227 }
|
|
228
|
|
229 $object_id = $object->dbID();
|
|
230 my $db = $self->db();
|
|
231
|
|
232 if(!$object->is_stored($db)) {
|
|
233 throw("$type is not stored in this database.");
|
|
234 }
|
|
235
|
|
236 }
|
|
237
|
|
238 if(!defined($object_id)) {
|
|
239 throw("$type must have dbID.");
|
|
240 }
|
|
241
|
|
242 my $sth;
|
|
243 if(defined($code)){
|
|
244 $sth = $self->prepare("DELETE a FROM ".$table."_attrib a ,attrib_type at " .
|
|
245 "WHERE a.attrib_type_id = at.attrib_type_id AND ".
|
|
246 "a.".$type."_id = ? AND ".
|
|
247 "at.code like ?");
|
|
248 $sth->bind_param(1,$object_id,SQL_INTEGER);
|
|
249 $sth->bind_param(2,$code,SQL_VARCHAR);
|
|
250 }
|
|
251 else{
|
|
252 $sth = $self->prepare("DELETE FROM ".$table."_attrib " .
|
|
253 "WHERE ".$type."_id = ?");
|
|
254 $sth->bind_param(1,$object_id,SQL_INTEGER);
|
|
255 }
|
|
256 $sth->execute();
|
|
257
|
|
258 $sth->finish();
|
|
259
|
|
260 return;
|
|
261 }
|
|
262
|
|
263
|
|
264
|
|
265 sub fetch_all_by_{
|
|
266 my $self = shift;
|
|
267 my $type = shift;
|
|
268 my $object = shift;
|
|
269 my $code = shift;
|
|
270 my $table =undef;
|
|
271
|
|
272 if(!ref($object) || !$object->isa('Bio::EnsEMBL::'.$type)) {
|
|
273 throw("$type argument is required. but you passed $object");
|
|
274 }
|
|
275
|
|
276 my $object_id;
|
|
277 if($type eq "Slice"){
|
|
278 $object_id = $object->get_seq_region_id();
|
|
279 $table = "seq_region";
|
|
280 $type = "seq_region";
|
|
281 }
|
|
282 else{
|
|
283 if($type eq "MiscFeature"){
|
|
284 $type = "misc_feature";
|
|
285 $table = "misc";
|
|
286 }
|
|
287 else{
|
|
288 $table = lc($type);
|
|
289 }
|
|
290
|
|
291 $object_id = $object->dbID();
|
|
292 }
|
|
293
|
|
294 if(!defined($object_id)) {
|
|
295 throw("$type must have dbID.");
|
|
296 }
|
|
297
|
|
298
|
|
299 my $sql = "SELECT at.code, at.name, at.description, t.value " .
|
|
300 "FROM ".($table||$type)."_attrib t, attrib_type at ".
|
|
301 "WHERE t.".$type."_id = ? " .
|
|
302 "AND at.attrib_type_id = t.attrib_type_id ";
|
|
303
|
|
304 if(defined($code)){
|
|
305 $sql .= 'AND at.code like "'.$code.'" ';
|
|
306 }
|
|
307
|
|
308 my $sth = $self->prepare($sql);
|
|
309
|
|
310 $sth->bind_param(1,$object_id,SQL_INTEGER);
|
|
311 $sth->execute();
|
|
312
|
|
313 my $results = $self->_obj_from_sth($sth);
|
|
314
|
|
315 $sth->finish();
|
|
316
|
|
317 return $results;
|
|
318
|
|
319 }
|
|
320
|
|
321
|
|
322 sub DESTROY{
|
|
323 }
|
|
324
|
|
325
|
|
326 #
|
|
327 # _id_check
|
|
328 #
|
|
329 # backwards compatibility check:
|
|
330 # check if $ensID is an object; if so, return $obj->dbID
|
|
331 #
|
|
332
|
|
333 sub _id_check {
|
|
334 my $self = shift;
|
|
335 my $ensID = shift;
|
|
336
|
|
337 if ($ensID =~ /^\d+$/) {
|
|
338 return $ensID;
|
|
339
|
|
340 } elsif (ref($ensID) eq 'Bio::EnsEMBL::Gene' or
|
|
341 ref($ensID) eq 'Bio::EnsEMBL::Transcript' or
|
|
342 ref($ensID) eq 'Bio::EnsEMBL::Translation') {
|
|
343
|
|
344 warning("You should pass a dbID rather than an ensembl object to store the attribute on");
|
|
345
|
|
346 if ($ensID->dbID) {
|
|
347 return $ensID->dbID;
|
|
348 } else {
|
|
349 throw("Ensembl object ".$ensID->display_id." doesn't have a dbID, can't store attribute");
|
|
350 }
|
|
351
|
|
352 } else {
|
|
353 throw("Invalid dbID");
|
|
354 }
|
|
355
|
|
356 }
|
|
357
|
|
358
|
|
359 # _store_type
|
|
360
|
|
361 sub _store_type {
|
|
362 my $self = shift;
|
|
363 my $attrib = shift;
|
|
364
|
|
365 my $sth1 = $self->prepare
|
|
366 ("INSERT IGNORE INTO attrib_type set code = ?, name = ?, ".
|
|
367 "description = ?" );
|
|
368
|
|
369
|
|
370 $sth1->bind_param(1,$attrib->code,SQL_VARCHAR);
|
|
371 $sth1->bind_param(2,$attrib->name,SQL_VARCHAR);
|
|
372 $sth1->bind_param(3,$attrib->description,SQL_LONGVARCHAR);
|
|
373
|
|
374 my $rows_inserted = $sth1->execute();
|
|
375
|
|
376 my $atid = $sth1->{'mysql_insertid'};
|
|
377
|
|
378 if($rows_inserted == 0) {
|
|
379 # the insert failed because the code is already stored
|
|
380 my $sth2 = $self->prepare
|
|
381 ("SELECT attrib_type_id FROM attrib_type " .
|
|
382 "WHERE code = ?");
|
|
383 $sth2->bind_param(1,$attrib->code,SQL_VARCHAR);
|
|
384 $sth2->execute();
|
|
385 ($atid) = $sth2->fetchrow_array();
|
|
386
|
|
387 $sth2->finish();
|
|
388
|
|
389 if(!$atid) {
|
|
390 throw("Could not store or fetch attrib_type code [".$attrib->code."]\n" .
|
|
391 "Wrong database user/permissions?");
|
|
392 }
|
|
393 }
|
|
394
|
|
395 $sth1->finish();
|
|
396
|
|
397 return $atid;
|
|
398 }
|
|
399
|
|
400
|
|
401 sub _obj_from_sth {
|
|
402 my $self = shift;
|
|
403 my $sth = shift;
|
|
404
|
|
405 my ($code, $name, $desc, $value);
|
|
406 $sth->bind_columns(\$code, \$name, \$desc, \$value);
|
|
407
|
|
408 my @results;
|
|
409 while($sth->fetch()) {
|
|
410 push @results, Bio::EnsEMBL::Attribute->new_fast
|
|
411 ( {'code' => $code,
|
|
412 'name' => $name,
|
|
413 'description' => $desc,
|
|
414 'value' => $value} );
|
|
415 }
|
|
416
|
|
417 return \@results;
|
|
418 }
|
|
419
|
|
420
|
|
421
|
|
422
|
|
423 1;
|
|
424
|