Archive Ensembl HomeArchive Ensembl Home
BaseMetaContainer.pm
Go to the documentation of this file.
00001 =head1 LICENSE
00002 
00003   Copyright (c) 1999-2012 The European Bioinformatics Institute and
00004   Genome Research Limited.  All rights reserved.
00005 
00006   This software is distributed under a modified Apache license.
00007   For license details, please see
00008 
00009     http://www.ensembl.org/info/about/code_licence.html
00010 
00011 =head1 CONTACT
00012 
00013   Please email comments or questions to the public Ensembl
00014   developers list at <dev@ensembl.org>.
00015 
00016   Questions may also be sent to the Ensembl help desk at
00017   <helpdesk@ensembl.org>.
00018 
00019 =cut
00020 
00021 =head1 NAME
00022 
00023 Bio::EnsEMBL::DBSQL::BaseMetaContainer - Encapsulates all generic access
00024 to database meta information
00025 
00026 =head1 SYNOPSIS
00027 
00028   my $meta_container = $db_adaptor->get_MetaContainer();
00029 
00030   my @mapping_info =
00031     @{ $meta_container->list_value_by_key('assembly.mapping') };
00032 
00033 =head1 DESCRIPTION
00034 
00035   An object that encapsulates access to db meta data
00036 
00037 =head1 METHODS
00038 
00039 =cut
00040 
00041 package Bio::EnsEMBL::DBSQL::BaseMetaContainer;
00042 
00043 use vars qw(@ISA);
00044 use strict;
00045 
00046 use Bio::EnsEMBL::DBSQL::BaseAdaptor;
00047 use Bio::EnsEMBL::Utils::Exception qw(throw deprecate warning);
00048 
00049 @ISA = qw(Bio::EnsEMBL::DBSQL::BaseAdaptor);
00050 
00051 # new() is inherited from Bio::EnsEMBL::DBSQL::BaseAdaptor
00052 
00053 =head2 get_schema_version
00054 
00055   Arg [1]    : none
00056   Example    : $schema_ver = $meta_container->get_schema_version();
00057   Description: Retrieves the schema version from the database meta table
00058   Returntype : int
00059   Exceptions : none
00060   Caller     : ?
00061   Status     : Medium risk
00062 
00063 =cut
00064 
00065 sub get_schema_version {
00066   my $self = shift;
00067 
00068   my $arrRef = $self->list_value_by_key('schema_version');
00069 
00070   if (@$arrRef) {
00071     my ($ver) = ( $arrRef->[0] =~ /^\s*(\d+)\s*$/ );
00072     if ( !defined($ver) ) {    # old style format
00073       return 0;
00074     }
00075     return $ver;
00076   } else {
00077     warning(
00078       sprintf(
00079         "Please insert meta_key 'schema_version' "
00080           . "in meta table on core database '%s'\n",
00081         $self->dbc()->dbname() ) );
00082   }
00083 
00084   return 0;
00085 }
00086 
00087 
00088 =head2 list_value_by_key
00089 
00090   Arg [1]    : string $key
00091                the key to obtain values from the meta table with
00092   Example    : my @values = @{ $meta_container->list_value_by_key($key) };
00093   Description: gets a value for a key. Can be anything 
00094   Returntype : listref of strings 
00095   Exceptions : none
00096   Caller     : ?
00097   Status     : Stable
00098 
00099 =cut
00100 
00101 sub list_value_by_key {
00102   my ( $self, $key ) = @_;
00103 
00104   $self->{'cache'} ||= {};
00105 
00106   if ( exists $self->{'cache'}->{$key} ) {
00107     return $self->{'cache'}->{$key};
00108   }
00109 
00110   my $sth;
00111 
00112   if ( !$self->_species_specific_key($key) ) {
00113     $sth =
00114       $self->prepare( "SELECT meta_value "
00115         . "FROM meta "
00116         . "WHERE meta_key = ? "
00117         . "AND species_id IS NULL "
00118         . "ORDER BY meta_id" );
00119   } else {
00120     $sth =
00121       $self->prepare( "SELECT meta_value "
00122         . "FROM meta "
00123         . "WHERE meta_key = ? "
00124         . "AND species_id = ? "
00125         . "ORDER BY meta_id" );
00126     $sth->bind_param( 2, $self->species_id(), SQL_INTEGER );
00127   }
00128 
00129   $sth->bind_param( 1, $key, SQL_VARCHAR );
00130   $sth->execute();
00131 
00132   my @result;
00133   while ( my $arrRef = $sth->fetchrow_arrayref() ) {
00134     push( @result, $arrRef->[0] );
00135   }
00136 
00137   $sth->finish();
00138   $self->{'cache'}->{$key} = \@result;
00139 
00140   return \@result;
00141 } ## end sub list_value_by_key
00142 
00143 =head2 single_value_by_key
00144 
00145   Arg [1]    : string $key
00146                the key to obtain values from the meta table with
00147   Arg [2]    : boolean $warn
00148                If true will cause the code to warn the non-existence of a value
00149   Example    : my $value = $mc->single_value_by_key($key);
00150   Description: Gets a value for a key. Can be anything
00151   Returntype : Scalar
00152   Exceptions : Raised if more than 1 meta item is returned
00153 
00154 =cut
00155 
00156 sub single_value_by_key {
00157   my ($self, $key, $warn) = @_;
00158   my $results = $self->list_value_by_key($key);
00159   if(defined $results) {
00160     my $count = scalar(@{$results});
00161     if($count == 1) {
00162       my ($value) = @{$results};
00163       return $value;
00164     }
00165     elsif($count == 0) {
00166       if($warn) {
00167         my $group = $self->db()->group();
00168         my $msg = sprintf(qq{Please insert meta_key '%s' in meta table at %s db\n}, $key, $group);
00169         warning($msg);
00170       }
00171     }
00172     else {
00173       my $values = join(q{,}, @{$results});
00174       throw sprintf(q{Found the values [%s] for the key '%s'}, $values, $key);
00175     }
00176   }
00177   return;
00178 } ## end sub single_value_by_key
00179 
00180 =head2 store_key_value
00181 
00182   Arg [1]    : string $key
00183                a key under which $value should be stored
00184   Arg [2]    : string $value
00185                the value to store in the meta table
00186   Example    : $meta_container->store_key_value($key, $value);
00187   Description: stores a value in the meta container, accessable by a key
00188   Returntype : none
00189   Exceptions : Thrown if the key/value already exists.
00190   Caller     : ?
00191   Status     : Stable
00192 
00193 =cut
00194 
00195 sub store_key_value {
00196   my ( $self, $key, $value ) = @_;
00197 
00198   if ( $self->key_value_exists( $key, $value ) ) {
00199     warn(   "Key-value pair '$key'-'$value' "
00200           . "already exists in the meta table; "
00201           . "not storing duplicate" );
00202     return;
00203   }
00204 
00205   my $sth;
00206 
00207   if ( !$self->_species_specific_key($key) ) {
00208     $sth = $self->prepare(
00209           'INSERT INTO meta (meta_key, meta_value, species_id) '
00210         . 'VALUES(?, ?, \N)' );
00211   } else {
00212     $sth = $self->prepare(
00213           'INSERT INTO meta (meta_key, meta_value, species_id) '
00214         . 'VALUES (?, ?, ?)' );
00215     $sth->bind_param( 3, $self->species_id(), SQL_INTEGER );
00216   }
00217 
00218   $sth->bind_param( 1, $key,   SQL_VARCHAR );
00219   $sth->bind_param( 2, $value, SQL_VARCHAR );
00220   $sth->execute();
00221 
00222   $self->{'cache'} ||= {};
00223 
00224   delete $self->{'cache'}->{$key};
00225 } ## end sub store_key_value
00226 
00227 =head2 update_key_value
00228 
00229   Arg [1]    : string $key
00230                a key under which $value should be updated
00231   Arg [2]    : string $value
00232                the value to update in the meta table
00233   Example    : $meta_container->update_key_value($key, $value);
00234   Description: update a value in the meta container, accessable by a key
00235   Returntype : none
00236   Exceptions : none
00237   Caller     : ?
00238   Status     : Stable
00239 
00240 =cut
00241 
00242 sub update_key_value {
00243   my ( $self, $key, $value ) = @_;
00244 
00245   my $sth;
00246 
00247   if ( !$self->_species_specific_key($key) ) {
00248     $sth =
00249       $self->prepare( 'UPDATE meta SET meta_value = ? '
00250         . 'WHERE meta_key = ?'
00251         . 'AND species_id IS NULL' );
00252   } else {
00253     $sth =
00254       $self->prepare( 'UPDATE meta '
00255         . 'SET meta_value = ? '
00256         . 'WHERE meta_key = ? '
00257         . 'AND species_id = ?' );
00258     $sth->bind_param( 3, $self->species_id(), SQL_INTEGER );
00259   }
00260 
00261   $sth->bind_param( 1, $value, SQL_VARCHAR );
00262   $sth->bind_param( 2, $key,   SQL_VARCHAR );
00263   $sth->execute();
00264 
00265 } ## end sub update_key_value
00266 
00267 
00268 =head2 delete_key
00269 
00270   Arg [1]    : string $key
00271                The key which should be removed from the database.
00272   Example    : $meta_container->delete_key('sequence.compression');
00273   Description: Removes all rows from the meta table which have a meta_key
00274                equal to $key.
00275   Returntype : none
00276   Exceptions : none
00277   Caller     : dna_compress script, general
00278   Status     : Stable
00279 
00280 =cut
00281 
00282 sub delete_key {
00283   my ( $self, $key ) = @_;
00284 
00285   my $sth;
00286 
00287   if ( !$self->_species_specific_key($key) ) {
00288     $sth =
00289       $self->prepare( 'DELETE FROM meta '
00290         . 'WHERE meta_key = ?'
00291         . 'AND species_id IS NULL' );
00292   } else {
00293     $sth =
00294       $self->prepare( 'DELETE FROM meta '
00295         . 'WHERE meta_key = ? '
00296         . 'AND species_id = ?' );
00297     $sth->bind_param( 2, $self->species_id(), SQL_INTEGER );
00298   }
00299 
00300   $sth->bind_param( 1, $key, SQL_VARCHAR );
00301   $sth->execute();
00302 
00303   delete $self->{'cache'}->{$key};
00304 }
00305 
00306 =head2 delete_key_value
00307 
00308   Arg [1]    : string $key
00309                The key which should be removed from the database.
00310   Arg [2]    : string $value
00311                The value to be removed.
00312   Example    : $meta_container->delete_key('patch', 'patch_39_40_b.sql|xref_unique_constraint');
00313   Description: Removes all rows from the meta table which have a meta_key
00314                equal to $key, AND a meta_value equal to $value.
00315   Returntype : none
00316   Exceptions : none
00317   Caller     : general
00318   Status     : Stable
00319 
00320 =cut
00321 
00322 sub delete_key_value {
00323   my ( $self, $key, $value ) = @_;
00324 
00325   my $sth;
00326 
00327   if ( !$self->_species_specific_key($key) ) {
00328     $sth =
00329       $self->prepare( 'DELETE FROM meta '
00330         . 'WHERE meta_key = ? '
00331         . 'AND meta_value = ?'
00332         . 'AND species_id IS NULL' );
00333   } else {
00334     $sth =
00335       $self->prepare( 'DELETE FROM meta '
00336         . 'WHERE meta_key = ? '
00337         . 'AND meta_value = ? '
00338         . 'AND species_id = ?' );
00339     $sth->bind_param( 3, $self->species_id(), SQL_INTEGER );
00340   }
00341 
00342   $sth->bind_param( 1, $key,   SQL_VARCHAR );
00343   $sth->bind_param( 2, $value, SQL_VARCHAR );
00344   $sth->execute();
00345 
00346   delete $self->{'cache'}->{$key};
00347 } ## end sub delete_key_value
00348 
00349 =head2 key_value_exists
00350 
00351   Arg [1]    : string $key
00352                the key to check
00353   Arg [2]    : string $value
00354                the value to check
00355   Example    : if ($meta_container->key_value_exists($key, $value)) ...
00356   Description: Return true (1) if a particular key/value pair exists,
00357                false (0) otherwise.
00358   Returntype : boolean
00359   Exceptions : none
00360   Caller     : ?
00361   Status     : Stable
00362 
00363 =cut
00364 
00365 sub key_value_exists {
00366   my ( $self, $key, $value ) = @_;
00367 
00368   my $sth;
00369 
00370   if ( !$self->_species_specific_key($key) ) {
00371     $sth =
00372       $self->prepare( 'SELECT meta_value '
00373         . 'FROM meta '
00374         . 'WHERE meta_key = ? '
00375         . 'AND meta_value = ?'
00376         . 'AND species_id IS NULL' );
00377   } else {
00378     $sth =
00379       $self->prepare( 'SELECT meta_value '
00380         . 'FROM meta '
00381         . 'WHERE meta_key = ? '
00382         . 'AND meta_value = ? '
00383         . 'AND species_id = ?' );
00384     $sth->bind_param( 3, $self->species_id(), SQL_INTEGER );
00385   }
00386 
00387   $sth->bind_param( 1, $key,   SQL_VARCHAR );
00388   $sth->bind_param( 2, $value, SQL_VARCHAR );
00389   $sth->execute();
00390 
00391   while ( my $arrRef = $sth->fetchrow_arrayref() ) {
00392     if ( $arrRef->[0] eq $value ) {
00393       $sth->finish();
00394       return 1;
00395     }
00396   }
00397 
00398   return 0;
00399 } ## end sub key_value_exists
00400 
00401 # This utility method determines whether the key is a species-specific
00402 # meta key or not.  If the key is either 'patch' or 'schema_version',
00403 # then it is not species-specific.
00404 
00405 # FIXME variation team messed up in release 65 and added the ploidy
00406 # entry without species_id - this will be corrected for release 66,
00407 # for now, I've added it to the list of allowed non-species specific
00408 
00409 sub _species_specific_key {
00410   my ( $self, $key ) = @_;
00411 
00412   return (    $key ne 'patch'
00413            && $key ne 'schema_version'
00414            && $key ne 'schema_type'
00415            && $key ne 'ploidy');
00416 }
00417 
00418 1;