BaseMetaContainer.pm 10.8 KB
Newer Older
1
=head1 LICENSE
Daniel Rios's avatar
Daniel Rios committed
2

3
Copyright [1999-2013] Wellcome Trust Sanger Institute and the EMBL-European Bioinformatics Institute
4

5 6 7 8 9 10 11 12 13 14 15 16 17
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

=cut
18 19 20 21 22


=head1 CONTACT

  Please email comments or questions to the public Ensembl
Magali Ruffier's avatar
Magali Ruffier committed
23
  developers list at <http://lists.ensembl.org/mailman/listinfo/dev>.
24 25

  Questions may also be sent to the Ensembl help desk at
Magali Ruffier's avatar
Magali Ruffier committed
26
  <http://www.ensembl.org/Help/Contact>.
27 28

=cut
Daniel Rios's avatar
Daniel Rios committed
29 30 31

=head1 NAME

32 33
Bio::EnsEMBL::DBSQL::BaseMetaContainer - Encapsulates all generic access
to database meta information
Daniel Rios's avatar
Daniel Rios committed
34 35 36 37 38

=head1 SYNOPSIS

  my $meta_container = $db_adaptor->get_MetaContainer();

39 40
  my @mapping_info =
    @{ $meta_container->list_value_by_key('assembly.mapping') };
Daniel Rios's avatar
Daniel Rios committed
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

=head1 DESCRIPTION

  An object that encapsulates access to db meta data

=head1 METHODS

=cut

package Bio::EnsEMBL::DBSQL::BaseMetaContainer;

use vars qw(@ISA);
use strict;

use Bio::EnsEMBL::DBSQL::BaseAdaptor;
56
use Bio::EnsEMBL::Utils::Exception qw(throw deprecate warning);
Daniel Rios's avatar
Daniel Rios committed
57 58 59 60 61

@ISA = qw(Bio::EnsEMBL::DBSQL::BaseAdaptor);

# new() is inherited from Bio::EnsEMBL::DBSQL::BaseAdaptor

62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
=head2 get_schema_version

  Arg [1]    : none
  Example    : $schema_ver = $meta_container->get_schema_version();
  Description: Retrieves the schema version from the database meta table
  Returntype : int
  Exceptions : none
  Caller     : ?
  Status     : Medium risk

=cut

sub get_schema_version {
  my $self = shift;

77 78 79 80 81
  my $arrRef = $self->list_value_by_key('schema_version');

  if (@$arrRef) {
    my ($ver) = ( $arrRef->[0] =~ /^\s*(\d+)\s*$/ );
    if ( !defined($ver) ) {    # old style format
82 83
      return 0;
    }
84
    return $ver * 1; #multiply by 1 to get this into a number
85
  } else {
86 87 88 89 90
    warning(
      sprintf(
        "Please insert meta_key 'schema_version' "
          . "in meta table on core database '%s'\n",
        $self->dbc()->dbname() ) );
91
  }
92

93 94 95
  return 0;
}

Daniel Rios's avatar
Daniel Rios committed
96 97 98 99 100

=head2 list_value_by_key

  Arg [1]    : string $key
               the key to obtain values from the meta table with
101
  Example    : my @values = @{ $meta_container->list_value_by_key($key) };
Daniel Rios's avatar
Daniel Rios committed
102 103 104 105
  Description: gets a value for a key. Can be anything 
  Returntype : listref of strings 
  Exceptions : none
  Caller     : ?
106
  Status     : Stable
Daniel Rios's avatar
Daniel Rios committed
107 108 109 110

=cut

sub list_value_by_key {
111
  my ( $self, $key ) = @_;
Daniel Rios's avatar
Daniel Rios committed
112 113

  $self->{'cache'} ||= {};
114 115

  if ( exists $self->{'cache'}->{$key} ) {
Daniel Rios's avatar
Daniel Rios committed
116 117 118
    return $self->{'cache'}->{$key};
  }

119
  my $sth;
120

121
  if ( !$self->_species_specific_key($key) ) {
122
    $sth =
123 124 125 126 127
      $self->prepare( "SELECT meta_value "
        . "FROM meta "
        . "WHERE meta_key = ? "
        . "AND species_id IS NULL "
        . "ORDER BY meta_id" );
128 129
  } else {
    $sth =
130 131 132 133 134
      $self->prepare( "SELECT meta_value "
        . "FROM meta "
        . "WHERE meta_key = ? "
        . "AND species_id = ? "
        . "ORDER BY meta_id" );
135 136 137
    $sth->bind_param( 2, $self->species_id(), SQL_INTEGER );
  }

138 139 140
  $sth->bind_param( 1, $key, SQL_VARCHAR );
  $sth->execute();

141 142
  my @result;
  while ( my $arrRef = $sth->fetchrow_arrayref() ) {
Daniel Rios's avatar
Daniel Rios committed
143 144
    push( @result, $arrRef->[0] );
  }
145

Javier Herrero's avatar
Javier Herrero committed
146
  $sth->finish();
Daniel Rios's avatar
Daniel Rios committed
147 148 149
  $self->{'cache'}->{$key} = \@result;

  return \@result;
150
} ## end sub list_value_by_key
Daniel Rios's avatar
Daniel Rios committed
151

152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
=head2 single_value_by_key

  Arg [1]    : string $key
               the key to obtain values from the meta table with
  Arg [2]    : boolean $warn
               If true will cause the code to warn the non-existence of a value
  Example    : my $value = $mc->single_value_by_key($key);
  Description: Gets a value for a key. Can be anything
  Returntype : Scalar
  Exceptions : Raised if more than 1 meta item is returned

=cut

sub single_value_by_key {
  my ($self, $key, $warn) = @_;
  my $results = $self->list_value_by_key($key);
  if(defined $results) {
    my $count = scalar(@{$results});
    if($count == 1) {
171 172
      my ($value) = @{$results};
      return $value;
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
    }
    elsif($count == 0) {
      if($warn) {
        my $group = $self->db()->group();
        my $msg = sprintf(qq{Please insert meta_key '%s' in meta table at %s db\n}, $key, $group);
        warning($msg);
      }
    }
    else {
      my $values = join(q{,}, @{$results});
      throw sprintf(q{Found the values [%s] for the key '%s'}, $values, $key);
    }
  }
  return;
} ## end sub single_value_by_key

Daniel Rios's avatar
Daniel Rios committed
189 190 191 192 193 194 195 196 197
=head2 store_key_value

  Arg [1]    : string $key
               a key under which $value should be stored
  Arg [2]    : string $value
               the value to store in the meta table
  Example    : $meta_container->store_key_value($key, $value);
  Description: stores a value in the meta container, accessable by a key
  Returntype : none
198
  Exceptions : Thrown if the key/value already exists.
Daniel Rios's avatar
Daniel Rios committed
199
  Caller     : ?
200
  Status     : Stable
Daniel Rios's avatar
Daniel Rios committed
201 202 203 204 205 206

=cut

sub store_key_value {
  my ( $self, $key, $value ) = @_;

207 208 209 210
  if ( $self->key_value_exists( $key, $value ) ) {
    warn(   "Key-value pair '$key'-'$value' "
          . "already exists in the meta table; "
          . "not storing duplicate" );
211 212 213
    return;
  }

214
  my $sth;
Daniel Rios's avatar
Daniel Rios committed
215

216
  if ( !$self->_species_specific_key($key) ) {
217
    $sth = $self->prepare(
218 219
          'INSERT INTO meta (meta_key, meta_value, species_id) '
        . 'VALUES(?, ?, \N)' );
220
  } else {
221
    $sth = $self->prepare(
222 223
          'INSERT INTO meta (meta_key, meta_value, species_id) '
        . 'VALUES (?, ?, ?)' );
224
    $sth->bind_param( 3, $self->species_id(), SQL_INTEGER );
225
  }
Daniel Rios's avatar
Daniel Rios committed
226

227 228 229 230
  $sth->bind_param( 1, $key,   SQL_VARCHAR );
  $sth->bind_param( 2, $value, SQL_VARCHAR );
  $sth->execute();

Daniel Rios's avatar
Daniel Rios committed
231 232 233
  $self->{'cache'} ||= {};

  delete $self->{'cache'}->{$key};
234
} ## end sub store_key_value
Daniel Rios's avatar
Daniel Rios committed
235 236 237 238 239 240 241 242 243 244 245 246

=head2 update_key_value

  Arg [1]    : string $key
               a key under which $value should be updated
  Arg [2]    : string $value
               the value to update in the meta table
  Example    : $meta_container->update_key_value($key, $value);
  Description: update a value in the meta container, accessable by a key
  Returntype : none
  Exceptions : none
  Caller     : ?
247
  Status     : Stable
Daniel Rios's avatar
Daniel Rios committed
248 249 250 251 252 253

=cut

sub update_key_value {
  my ( $self, $key, $value ) = @_;

254 255
  my $sth;

256
  if ( !$self->_species_specific_key($key) ) {
257
    $sth =
258 259 260
      $self->prepare( 'UPDATE meta SET meta_value = ? '
        . 'WHERE meta_key = ?'
        . 'AND species_id IS NULL' );
261
  } else {
262
    $sth =
263 264 265 266
      $self->prepare( 'UPDATE meta '
        . 'SET meta_value = ? '
        . 'WHERE meta_key = ? '
        . 'AND species_id = ?' );
267 268
    $sth->bind_param( 3, $self->species_id(), SQL_INTEGER );
  }
269 270 271 272 273

  $sth->bind_param( 1, $value, SQL_VARCHAR );
  $sth->bind_param( 2, $key,   SQL_VARCHAR );
  $sth->execute();

274
} ## end sub update_key_value
Daniel Rios's avatar
Daniel Rios committed
275 276 277 278 279 280 281 282 283 284 285 286


=head2 delete_key

  Arg [1]    : string $key
               The key which should be removed from the database.
  Example    : $meta_container->delete_key('sequence.compression');
  Description: Removes all rows from the meta table which have a meta_key
               equal to $key.
  Returntype : none
  Exceptions : none
  Caller     : dna_compress script, general
287
  Status     : Stable
Daniel Rios's avatar
Daniel Rios committed
288 289 290 291

=cut

sub delete_key {
292
  my ( $self, $key ) = @_;
Daniel Rios's avatar
Daniel Rios committed
293

294 295
  my $sth;

296
  if ( !$self->_species_specific_key($key) ) {
297
    $sth =
298 299 300
      $self->prepare( 'DELETE FROM meta '
        . 'WHERE meta_key = ?'
        . 'AND species_id IS NULL' );
301
  } else {
302
    $sth =
303 304 305
      $self->prepare( 'DELETE FROM meta '
        . 'WHERE meta_key = ? '
        . 'AND species_id = ?' );
306
    $sth->bind_param( 2, $self->species_id(), SQL_INTEGER );
307
  }
Daniel Rios's avatar
Daniel Rios committed
308

309 310 311
  $sth->bind_param( 1, $key, SQL_VARCHAR );
  $sth->execute();

312
  delete $self->{'cache'}->{$key};
Daniel Rios's avatar
Daniel Rios committed
313
}
Daniel Rios's avatar
Daniel Rios committed
314

315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
=head2 delete_key_value

  Arg [1]    : string $key
               The key which should be removed from the database.
  Arg [2]    : string $value
               The value to be removed.
  Example    : $meta_container->delete_key('patch', 'patch_39_40_b.sql|xref_unique_constraint');
  Description: Removes all rows from the meta table which have a meta_key
               equal to $key, AND a meta_value equal to $value.
  Returntype : none
  Exceptions : none
  Caller     : general
  Status     : Stable

=cut

sub delete_key_value {
332
  my ( $self, $key, $value ) = @_;
333

334 335
  my $sth;

336
  if ( !$self->_species_specific_key($key) ) {
337
    $sth =
338 339 340 341
      $self->prepare( 'DELETE FROM meta '
        . 'WHERE meta_key = ? '
        . 'AND meta_value = ?'
        . 'AND species_id IS NULL' );
342
  } else {
343
    $sth =
344 345 346 347
      $self->prepare( 'DELETE FROM meta '
        . 'WHERE meta_key = ? '
        . 'AND meta_value = ? '
        . 'AND species_id = ?' );
348
    $sth->bind_param( 3, $self->species_id(), SQL_INTEGER );
349
  }
350

351 352 353 354
  $sth->bind_param( 1, $key,   SQL_VARCHAR );
  $sth->bind_param( 2, $value, SQL_VARCHAR );
  $sth->execute();

355 356
  delete $self->{'cache'}->{$key};
} ## end sub delete_key_value
357 358 359 360 361 362 363 364

=head2 key_value_exists

  Arg [1]    : string $key
               the key to check
  Arg [2]    : string $value
               the value to check
  Example    : if ($meta_container->key_value_exists($key, $value)) ...
365 366
  Description: Return true (1) if a particular key/value pair exists,
               false (0) otherwise.
367 368 369 370 371 372 373 374
  Returntype : boolean
  Exceptions : none
  Caller     : ?
  Status     : Stable

=cut

sub key_value_exists {
375
  my ( $self, $key, $value ) = @_;
376

377
  my $sth;
378

379
  if ( !$self->_species_specific_key($key) ) {
380
    $sth =
381 382 383 384 385
      $self->prepare( 'SELECT meta_value '
        . 'FROM meta '
        . 'WHERE meta_key = ? '
        . 'AND meta_value = ?'
        . 'AND species_id IS NULL' );
386 387
  } else {
    $sth =
388 389 390 391 392
      $self->prepare( 'SELECT meta_value '
        . 'FROM meta '
        . 'WHERE meta_key = ? '
        . 'AND meta_value = ? '
        . 'AND species_id = ?' );
393
    $sth->bind_param( 3, $self->species_id(), SQL_INTEGER );
394
  }
395

396 397 398 399
  $sth->bind_param( 1, $key,   SQL_VARCHAR );
  $sth->bind_param( 2, $value, SQL_VARCHAR );
  $sth->execute();

400 401
  while ( my $arrRef = $sth->fetchrow_arrayref() ) {
    if ( $arrRef->[0] eq $value ) {
402 403 404
      $sth->finish();
      return 1;
    }
405 406
  }

407 408 409 410 411 412 413
  return 0;
} ## end sub key_value_exists

# This utility method determines whether the key is a species-specific
# meta key or not.  If the key is either 'patch' or 'schema_version',
# then it is not species-specific.

414 415 416 417
# FIXME variation team messed up in release 65 and added the ploidy
# entry without species_id - this will be corrected for release 66,
# for now, I've added it to the list of allowed non-species specific

418 419
sub _species_specific_key {
  my ( $self, $key ) = @_;
420 421 422

  return (    $key ne 'patch'
           && $key ne 'schema_version'
423 424
           && $key ne 'schema_type'
           && $key ne 'ploidy');
425 426
}

Daniel Rios's avatar
Daniel Rios committed
427
1;