ensembl-hive  2.6
DBAdaptor.pm
Go to the documentation of this file.
1 =pod
2 
3 =head1 NAME
4 
6 
7 =head1 SYNOPSIS
8 
9  my $db = Bio::EnsEMBL::Hive::DBSQL::DBAdaptor->new( -url => 'mysql://my_username:my_password@my_hostname:3306/my_hive_database' );
10 
11 =head1 DESCRIPTION
12 
13  This object represents the handle for a Hive system enabled database
14 
15 =head1 LICENSE
16 
17  Copyright [1999-2015] Wellcome Trust Sanger Institute and the EMBL-European Bioinformatics Institute
18  Copyright [2016-2024] EMBL-European Bioinformatics Institute
19 
20  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
21  You may obtain a copy of the License at
22 
23  http://www.apache.org/licenses/LICENSE-2.0
24 
25  Unless required by applicable law or agreed to in writing, software distributed under the License
26  is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
27  See the License for the specific language governing permissions and limitations under the License.
28 
29 =head1 CONTACT
30 
31  Please subscribe to the Hive mailing list: http://listserver.ebi.ac.uk/mailman/listinfo/ehive-users to discuss Hive-related questions or to be notified of our updates
32 
33 =cut
34 
35 
36 package Bio::EnsEMBL::Hive::DBSQL::DBAdaptor;
37 
38 use strict;
39 use warnings;
40 
41 use Scalar::Util qw(weaken);
42 
47 use Bio::EnsEMBL::Hive::Utils ('throw');
48 
58 
59 my $default_reg_type = 'hive';
60 
61 sub new {
62  my $class = shift @_;
63  my %flags = @_;
64 
65  my ($dbc, $url, $reg_conf, $reg_type, $reg_alias, $species, $no_sql_schema_version_check)
66  = delete @flags{qw(-dbconn -url -reg_conf -reg_type -reg_alias -species -no_sql_schema_version_check)};
67 
68  if ($url && $no_sql_schema_version_check) {
69  #check to see if the url has been quoted. If so, move the quote
70  #after the no_sql_schema_version_check
71  $url =~ s/([\'\"]?)$/;no_sql_schema_version_check=1$1/;
72  }
73 
74  if($reg_conf or $reg_alias) { # need to initialize Registry even if $reg_conf is not really given
75  require Bio::EnsEMBL::Registry;
76  # if undefined, default reg_conf will be used. If missing, will throw
77  Bio::EnsEMBL::Registry->load_all($reg_conf, undef, undef, undef, 'throw_if_missing');
78  }
79 
80  my $self;
81 
82  if($url) {
83  $dbc = Bio::EnsEMBL::Hive::DBSQL::DBConnection->new(-url => $url, %flags)
84  or die "Unable to create a DBC using url='$url'";
85 
86  } elsif($reg_alias) {
87 
88  if($reg_alias=~/^(\w+):(\w+)$/) {
89  ($reg_type, $reg_alias) = ($1, $2);
90  }
91 
92  unless($reg_type) { # if no $reg_type explicitly given, try to guess:
93  my $dbas = Bio::EnsEMBL::Registry->get_all_DBAdaptors(-species => $reg_alias);
94 
95  if( scalar(@$dbas) == 1 ) {
96  $self = $dbas->[0];
97  } elsif( @$dbas ) {
98  warn "The registry contains multiple entries for '$reg_alias', please prepend the reg_alias with the desired type\n";
99  }
100  }
101 
102  unless($self) { # otherwise (or if not found) try a specific $reg_type
103  $reg_type ||= $default_reg_type;
104  $self = Bio::EnsEMBL::Registry->get_DBAdaptor($reg_alias, $reg_type)
105  or die "Unable to connect to DBA using reg_conf='$reg_conf', reg_type='$reg_type', reg_alias='$reg_alias'\n";
106  }
107 
108  if( $self and !$self->isa($class) ) { # if we found a non-Hive Registry entry, detach the $dbc and build a Hive dba around it:
109  $dbc = $self->dbc;
110  $self = undef;
111  }
112  }
113 
114  if($dbc && !$self) {
115  $self = bless {}, $class;
116  $self->dbc( $dbc );
117  }
118 
119  unless($no_sql_schema_version_check) {
120 
121  my $dbc = $self->dbc();
122 
123  # Make a safe URL without affecting EHIVE_PASS, which could have been set by the user
124  my $safe_url = $dbc->url('EHIVE_TMP_PASSWORD');
125  $safe_url =~ s/EHIVE_TMP_PASSWORD/EHIVE_PASS/;
126 
127  my $code_sql_schema_version = Bio::EnsEMBL::Hive::DBSQL::SqlSchemaAdaptor->get_code_sql_schema_version()
128  || die "DB($safe_url) Could not establish code_sql_schema_version, please check that 'EHIVE_ROOT_DIR' environment variable is set correctly";
129 
130  my $db_sql_schema_version = eval { $self->get_MetaAdaptor->fetch_by_meta_key( 'hive_sql_schema_version' )->{'meta_value'}; };
131 
132  if($@) {
133  if($@ =~ /hive_meta.*doesn't exist/) {
134 
135  die "\nDB($safe_url) The 'hive_meta' table does not seem to exist in the database yet.\nPlease patch the database up to sql_schema_version '$code_sql_schema_version' and try again.\n";
136 
137  } else {
138 
139  die "DB($safe_url) $@";
140  }
141 
142  } elsif(!$db_sql_schema_version) {
143 
144  die "\nDB($safe_url) The 'hive_meta' table does not contain 'hive_sql_schema_version' entry.\nPlease investigate.\n";
145 
146  } elsif($db_sql_schema_version < $code_sql_schema_version) {
147 
148  my $new_patches = Bio::EnsEMBL::Hive::DBSQL::SqlSchemaAdaptor->get_sql_schema_patches( $db_sql_schema_version, $dbc->driver )
149  || die "DB($safe_url) sql_schema_version mismatch: the database's version is '$db_sql_schema_version' but the code is already '$code_sql_schema_version'.\n"
150  ."Unfortunately we cannot patch the database; you may have to create a new database or agree to run older code\n";
151 
152  my $sql_patcher_command = "$ENV{'EHIVE_ROOT_DIR'}/scripts/db_cmd.pl -url $safe_url";
153 
154  die "DB($safe_url) sql_schema_version mismatch: the database's version is '$db_sql_schema_version' but the code is already '$code_sql_schema_version'.\n"
155  ."Please upgrade the database by applying the following patches:\n\n"
156  .join("\n", map { ($_=~/\.\w*sql\w*$/) ? "\t$sql_patcher_command < $_" : "$_ -url $safe_url" } @$new_patches)
157  ."\n\nand try again.\n";
158 
159  } elsif($code_sql_schema_version < $db_sql_schema_version) {
160 
161  die "DB($safe_url) sql_schema_version mismatch: the database's version is '$db_sql_schema_version', but your code is still '$code_sql_schema_version'.\n"
162  ."Please update the code and try again.\n";
163  }
164  }
165 
166  if($species) { # [compatibility with core code] store the DBAdaptor in Registry:
167  require Bio::EnsEMBL::Registry;
168  $self->{'_species'} = $species;
169  Bio::EnsEMBL::Registry->add_DBAdaptor( $species, $default_reg_type, $self );
170  }
171 
172  return $self;
173 }
174 
175 
176 sub species { # a stub to please Registry code
177  my $self = shift;
178  return $self->{'_species'} // "$self";
179 }
180 
181 sub group { # a stub to please Registry code
182  return $default_reg_type;
183 }
184 
185 
186 sub dbc {
187  my $self = shift;
188 
189  $self->{'_dbc'} = bless shift, 'Bio::EnsEMBL::Hive::DBSQL::DBConnection' if(@_);
190 
191  return $self->{'_dbc'};
192 }
193 
194 
195 sub hive_pipeline {
196  my $self = shift @_;
197  if (@_) {
198  $self->{'_hive_pipeline'} = shift @_;
199  }
200  unless ($self->{'_hive_pipeline'}) {
201  $self->{'_hive_pipeline'} = Bio::EnsEMBL::Hive::HivePipeline->new( -dba => $self ); # ToDo: this lazy-loaded object is not registered in TheApiary (yet)
202  }
203  return $self->{'_hive_pipeline'};
204 }
205 
206 
207 our %adaptor_type_2_package_name = (
208  'Accumulator' => 'Bio::EnsEMBL::Hive::DBSQL::AccumulatorAdaptor',
209  'Analysis' => 'Bio::EnsEMBL::Hive::DBSQL::AnalysisAdaptor',
210  'AnalysisCtrlRule' => 'Bio::EnsEMBL::Hive::DBSQL::AnalysisCtrlRuleAdaptor',
211  'AnalysisData' => 'Bio::EnsEMBL::Hive::DBSQL::AnalysisDataAdaptor',
212  'AnalysisJob' => 'Bio::EnsEMBL::Hive::DBSQL::AnalysisJobAdaptor',
213  'AnalysisStats' => 'Bio::EnsEMBL::Hive::DBSQL::AnalysisStatsAdaptor',
214  'Beekeeper' => 'Bio::EnsEMBL::Hive::DBSQL::BeekeeperAdaptor',
215  'DataflowRule' => 'Bio::EnsEMBL::Hive::DBSQL::DataflowRuleAdaptor',
216  'DataflowTarget' => 'Bio::EnsEMBL::Hive::DBSQL::DataflowTargetAdaptor',
217  'LogMessage' => 'Bio::EnsEMBL::Hive::DBSQL::LogMessageAdaptor',
218  'Meta' => 'Bio::EnsEMBL::Hive::DBSQL::MetaAdaptor',
219  'PipelineWideParameters'=> 'Bio::EnsEMBL::Hive::DBSQL::PipelineWideParametersAdaptor',
220  'NakedTable' => 'Bio::EnsEMBL::Hive::DBSQL::NakedTableAdaptor',
221  'ResourceClass' => 'Bio::EnsEMBL::Hive::DBSQL::ResourceClassAdaptor',
222  'ResourceDescription' => 'Bio::EnsEMBL::Hive::DBSQL::ResourceDescriptionAdaptor',
223  'Role' => 'Bio::EnsEMBL::Hive::DBSQL::RoleAdaptor',
224  'Semaphore' => 'Bio::EnsEMBL::Hive::DBSQL::SemaphoreAdaptor',
225  'Queen' => 'Bio::EnsEMBL::Hive::Queen',
226 
227  # aliases:
228  'Job' => 'Bio::EnsEMBL::Hive::DBSQL::AnalysisJobAdaptor',
229  'Worker' => 'Bio::EnsEMBL::Hive::Queen',
230  'MetaParameters' => 'Bio::EnsEMBL::Hive::DBSQL::MetaAdaptor',
231 );
232 
233 
234 sub get_available_adaptors {
235 
236  return \%adaptor_type_2_package_name;
237 }
238 
239 
240 sub parse_underscored_id_name {
241  my ($self, $underscored_id_name) = @_;
242 
243  my ($is_an_id, $foo_id_method_name, $foo_obj_method_name);
244 
245  my @syll = split(/_/, $underscored_id_name);
246  if($syll[scalar(@syll)-1] eq 'id') {
247  pop @syll;
248  ($is_an_id, $foo_id_method_name, $foo_obj_method_name) = ( 1, $underscored_id_name, join('_', @syll) );
249  } else {
250  ($is_an_id, $foo_id_method_name, $foo_obj_method_name) = ( 0, $underscored_id_name .'_id' , $underscored_id_name );
251  }
252 
253  my $AdaptorType = ''; # will be growing from right to left
254  while(@syll) {
255  $AdaptorType = ucfirst(pop @syll) . $AdaptorType;
256  if(exists( $self->get_available_adaptors->{ $AdaptorType })) {
257  return ($AdaptorType, $is_an_id, $foo_id_method_name, $foo_obj_method_name);
258  }
259  }
260  return; # could not parse
261 }
262 
263 
264 sub get_adaptor {
265  my $self = shift;
266  my $AdaptorType = shift;
267 
268  my $adaptor_package_name = $self->get_available_adaptors()->{$AdaptorType}
269  or throw("Could not find a module corresponding to '$AdaptorType'");
270 
271  my $signature = join(':', $adaptor_package_name, @_);
272 
273  unless( $self->{'_cached_adaptor'}{$signature} ) {
274 
275  eval "require $adaptor_package_name"
276  or throw("Could not load or compile module '$adaptor_package_name' because $@");
277 
278  $self->{'_cached_adaptor'}{$signature} = $adaptor_package_name->new( $self, @_ );
279  }
280 
281  return $self->{'_cached_adaptor'}{$signature};
282 }
283 
284 
285 sub DESTROY { } # to simplify AUTOLOAD
286 
287 sub AUTOLOAD {
288  our $AUTOLOAD;
289 
290  my $type;
291  if ( $AUTOLOAD =~ /^.*::get_(\w+)Adaptor$/ ) {
292  $type = $1;
293  } elsif ( $AUTOLOAD =~ /^.*::get_(\w+)$/ ) {
294  $type = $1;
295  } else {
296  throw( "DBAdaptor::AUTOLOAD: Could not interpret the method: $AUTOLOAD" );
297  }
298 
299  my $self = shift;
300 
301  return $self->get_adaptor($type, @_);
302 }
303 
304 
305 1;
Bio::EnsEMBL::Hive::Utils
Definition: Collection.pm:4
Bio::EnsEMBL::Hive::DBSQL::DBAdaptor::new
public new()
Bio::EnsEMBL::Hive::ResourceDescription
Definition: ResourceDescription.pm:9
map
public map()
Bio::EnsEMBL::Hive::ResourceClass
Definition: ResourceClass.pm:9
Bio::EnsEMBL::Hive::PipelineWideParameters
Definition: PipelineWideParameters.pm:9
Bio::EnsEMBL::Hive::HivePipeline::new
public new()
Bio::EnsEMBL::Hive::DBSQL::DBConnection
Definition: DBConnection.pm:20
Bio::EnsEMBL::Hive::MetaParameters
Definition: MetaParameters.pm:9
Bio::EnsEMBL::Registry
Definition: Registry.pm:113
Bio::EnsEMBL::Hive::AnalysisStats
Definition: AnalysisStats.pm:12
Bio::EnsEMBL::Hive::DataflowRule
Definition: DataflowRule.pm:20
Bio::EnsEMBL::Hive::HivePipeline
Definition: HivePipeline.pm:13
Bio::EnsEMBL::Hive
Definition: DockerSwarm.pm:5
Bio::EnsEMBL::Hive::DBSQL::SqlSchemaAdaptor
Definition: SqlSchemaAdaptor.pm:17
Bio::EnsEMBL::Hive::AnalysisCtrlRule
Definition: AnalysisCtrlRule.pm:17
Bio::EnsEMBL::Hive::DataflowTarget
Definition: DataflowTarget.pm:6
Bio::EnsEMBL::Hive::DBSQL::SqlSchemaAdaptor::get_sql_schema_patches
public get_sql_schema_patches()
Bio::EnsEMBL::Hive::DBSQL::DBAdaptor
Definition: DBAdaptor.pm:31
Bio::EnsEMBL::Registry::add_DBAdaptor
public void add_DBAdaptor()
Bio::EnsEMBL::Hive
Definition: Hive.pm:38
get_adaptor
public get_adaptor()
Bio::EnsEMBL::Hive::Analysis
Definition: Analysis.pm:18