ensembl-hive  2.6
SqlHealthcheck.pm
Go to the documentation of this file.
1 =pod
2 
3 =head1 NAME
4 
6 
7 =head1 SYNOPSIS
8 
10  -db_conn mysql://ensro@compara1/mm14_compara_homology_71 \
11  -description 'We expect at least 20,000 human genes' \
12  -query 'SELECT * FROM member WHERE genome_db_id = 90 AND source_name = "ENSEMBLGENE"' \
13  -expected_size '>= 20000'
14 
15 =head1 DESCRIPTION
16 
17  This is a generic RunnableDB module for testing the size of the resultset of any SQL query.
18 
19  The query is passed by the parameter 'inputquery' (param substituted)
20  The expected size is passed by the parameter 'expected_size' as a string "CONDITION VALUE" (CONDITION defaults to equality, VALUE defaults to 0).
21  Currently, CONDITION is one of: = == < <= > >= <> !=
22 
23  TODO: implement a "expected_value" test
24 
25 =head1 LICENSE
26 
27  Copyright [1999-2015] Wellcome Trust Sanger Institute and the EMBL-European Bioinformatics Institute
28  Copyright [2016-2024] EMBL-European Bioinformatics Institute
29 
30  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
31  You may obtain a copy of the License at
32 
33  http://www.apache.org/licenses/LICENSE-2.0
34 
35  Unless required by applicable law or agreed to in writing, software distributed under the License
36  is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
37  See the License for the specific language governing permissions and limitations under the License.
38 
39 =head1 CONTACT
40 
41  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
42 
43 =cut
44 
45 
46 package Bio::EnsEMBL::Hive::RunnableDB::SqlHealthcheck;
47 
48 use strict;
49 use warnings;
50 
51 use base ('Bio::EnsEMBL::Hive::Process');
52 
53 
54 sub param_defaults {
55  return {
56  'description' => '/no description/',
57  'expected_size' => undef,
58  'inputquery' => undef,
59  }
60 }
61 
62 
63 
64 =head2 fetch_input
65 
66  Description : Implements fetch_input() interface method of Bio::EnsEMBL::Hive::Process that is used to read in parameters and load data.
67 
68 =cut
69 
70 sub fetch_input {
71  my $self = shift @_;
72 
73  $self->param('inputquery') && warn "'inputquery' is deprecated in SqlHealthcheck. Use 'query' instead\n";
74 
75  my $test = {
76  description => $self->param('description'),
77  query => $self->param('inputquery') || $self->param_required('query'),
78  expected_size => $self->param('expected_size'),
79  };
80 
81  $self->param('tests', [$test]);
82  $self->_validate_tests;
83 }
84 
85 
86 =head2 _validate_tests
87 
88  Description : Checks that the tests are properly defined, and parses the "expected_size"
89 
90 =cut
91 
92 sub _validate_tests {
93  my $self = shift @_;
94 
95  foreach my $test (@{$self->param('tests')}) {
96  die "The SQL query must be provided" unless $test->{query};
97  die "The description must be provided" unless $test->{description};
98  $test->{subst_query} = $self->param_substitute($test->{query});
99  my $expected_size = $self->param_substitute($test->{expected_size} || '');
100  unless ($expected_size =~ /^\s*(=|==|>|>=|<|<=|<>|!=|)\s*(\d*)\s*$/) {
101  die "Cannot interpret the 'expected_size' parameter: '$expected_size'";
102  }
103  $test->{logical_test} = $1 || '=';
104  $test->{reference_size} = $2 || '0';
105  }
106 }
107 
108 =head2 run
109 
110  Description : Implements run() interface method of Bio::EnsEMBL::Hive::Process
111  Iterate through the tests and run them all. Report the failed tests at the end
112 
113 =cut
114 
115 sub run {
116  my $self = shift @_;
117 
118  my @failures = ();
119  foreach my $test (@{$self->param('tests')}) {
120  push @failures, $test unless $self->_run_test($test);
121  }
122  if (@failures) {
123  # Transient errors like lost access to the database, etc, tend to
124  # make the job die in _run_test(). If we've passed this point, the
125  # test geneuinely failed, and it will fail again anyway
126  $self->input_job->transient_error(0);
127  die "The following tests have failed:\n".join('', map {sprintf(" - %s\n > %s\n", $_->{description}, $_->{subst_query})} @failures);
128  }
129 }
130 
131 
132 =head2 _run_test
133 
134  Description : Runs a single test, defined in a hash with the following keys:
135  description, query, reference_size, logical_test
136 
137 =cut
138 
139 sub _run_test {
140  my $self = shift @_;
141  my $test = shift @_;
142 
143  my $description = $test->{description};
144  my $query = $test->{subst_query};
145  my $reference_size = $test->{reference_size};
146  my $logical_test = $test->{logical_test};
147 
148  # Final semicolons are removed if present
149  if ($query =~ /(;\s*$)/) {
150  $query =~ s/$1//;
151  }
152 
153  $self->say_with_header( "Test description: $description" );
154  $self->say_with_header( "Checking whether the number of rows $logical_test $reference_size" );
155 
156  # This could benefit from 'switch' once we move to a more recent version of Perl
157  my $maxrow = $reference_size;
158  $maxrow++ if grep {$_ eq $logical_test} qw(= == > <= <> !=);
159 
160  $query .= " LIMIT $maxrow" unless $query =~ /LIMIT/i;
161  $self->say_with_header( "Query: $query" );
162 
163  my $sth = $self->data_dbc()->prepare( $query,
164  ($self->data_dbc->driver eq 'mysql') ? { 'mysql_use_result' => 1 } : undef );
165  $sth->execute();
166 
167  my $nrow = 0;
168  while (defined $sth->fetchrow_arrayref()) {
169  $nrow++;
170  }
171  $sth->finish;
172 
173  $self->say_with_header( "$nrow rows returned".($nrow == $maxrow ? " (test aborted, there could be more rows)" : "") );
174 
175  # This could benefit from 'switch' once we move to a more recent version of Perl
176  my $success = 0;
177  if ($logical_test eq '=' or $logical_test eq '==') {
178  $success = 1 if $nrow == $reference_size;
179 
180  } elsif ($logical_test eq '<' or $logical_test eq '<=') {
181  $success = 1 if $nrow < $maxrow;
182 
183  } elsif ($logical_test eq '>' or $logical_test eq '>=') {
184  $success = 1 if $nrow >= $maxrow;
185 
186  } elsif ($logical_test eq '<>' or $logical_test eq '!=') {
187  $success = 1 if $nrow != $reference_size;
188 
189  } else {
190  die "This should not happen. A logical test is not checked";
191  }
192  $self->say_with_header( $success ? "Success\n" : "Failure\n", 'important');
193  return $success;
194 }
195 
196 
197 1;
EnsEMBL
Definition: Filter.pm:1
map
public map()
Bio::EnsEMBL::Hive::Version
Definition: Version.pm:19
Bio::EnsEMBL::Hive::RunnableDB::SqlHealthcheck
Definition: SqlHealthcheck.pm:26
run
public run()
Bio::EnsEMBL::Hive
Definition: Hive.pm:38
Bio
Definition: AltAlleleGroup.pm:4