ensembl-hive  2.7.0
dump_mysql.pl
Go to the documentation of this file.
1 #!/usr/bin/env perl
2 # See the NOTICE file distributed with this work for additional information
3 # regarding copyright ownership.
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 
17 
18 package Script;
19 
20 use strict;
21 use warnings;
22 
23 use Carp;
24 use DBI;
25 use File::Spec;
26 use File::Path qw/mkpath/;
27 use Getopt::Long qw/:config no_ignore_case auto_version bundling_override/;
28 use IO::Compress::Gzip qw/gzip $GzipError/;
29 use Pod::Usage;
30 use Sys::Hostname;
31 
32 my $PIGZ_BINARY = 'pigz';
33 my $PIGZ_PROCESSORS = 2; #some machines only have 4 cores so do not go mad
34 my $MAX_FILE_SIZE = 1 * 1024 * 1024; #anything greater than 1MB farm out
35 
36 sub run {
37  my ($class) = @_;
38  my $self = bless({}, $class);
39  $self->args();
40  $self->logging();
41  $self->check();
42  $self->defaults();
43  $self->dry() if $self->opts()->{dry};
44  $self->process() if ! $self->opts()->{dry};
45 
46  if ($self->{oldfh}) {
47  select($self->{oldfh});
48  }
49  return;
50 }
51 
52 sub args {
53  my ($self) = @_;
54  my $opts = {};
55  GetOptions(
56  $opts, qw/
57  defaults=s
58  version|release=i
59  dry
60  host|hostname|h=s
61  port|P=i
62  username|user|u=s
63  password|pass|p=s
64  directory|dir=s
65  databases|database|db=s@
66  groups=s@
67  species=s@
68  tables|table=s@
69  pattern=s
70  sql
71  perlgzip
72  testcompatible
73  verbose|v
74  log=s
75  help
76  man
77  /
78  ) or pod2usage(-verbose => 1, -exitval => 1);
79  pod2usage(-verbose => 1, -exitval => 0) if $opts->{help};
80  pod2usage(-verbose => 2, -exitval => 0) if $opts->{man};
81  $self->{opts} = $opts;
82  return;
83 }
84 
85 sub logging {
86  my ($self) = @_;
87  my $o = $self->opts();
88  if ($o->{log}) {
89  $o->{verbose} = 1;
90  my $file = $o->{log};
91  open my $fh, '>', $file or die "Cannot open log file '${file}' for writing: $!";
92  my $oldfh = select($fh);
93  $self->{oldfh} = $oldfh;
94  }
95  return;
96 }
97 
98 sub check {
99  my ($self) = @_;
100  my $o = $self->opts();
101 
102  my @required_params;
103 
104  if (! $o->{defaults}) {
105  @required_params = qw/host username/;
106  pod2usage(
107  -message => '-pattern is not supported with -databases mode',
108  -verbose => 1,
109  -exitval => 1
110  ) if $o->{pattern} && $o->{databases};
111  }
112 
113  foreach my $r (@required_params) {
114  if (!$o->{$r}) {
115  pod2usage(
116  -message =>
117 "-${r} has not been given at the command line but is a required parameter",
118  -verbose => 1,
119  -exitval => 1
120  );
121  }
122  }
123 
124  #Check if gzip command is available
125  if($o->{perlgzip}) {
126  $self->{pigz_binary} = 0;
127  $self->v('Forcing Perl based GZip compression');
128  }
129  else {
130  `$PIGZ_BINARY --version >/dev/null 2>/dev/null`;
131  $self->{pigz_binary} = ($? == 0) ? 1 : 0;
132  my $feedback = ($self->{pigz_binary}) ? 'available' : 'not available';
133  $self->v(q{pigz binary '%s' is %s}, $PIGZ_BINARY, $feedback);
134  }
135 
136  return;
137 }
138 
139 sub defaults {
140  my ($self) = @_;
141  my $o = $self->opts();
142 
143  #Processing -opt 1 -opt 2,3 into opt => [1,2,3]
144  $self->_cmd_line_to_array('databases') if $o->{databases};
145  $self->_cmd_line_to_array('groups') if $o->{groups};
146  $self->_cmd_line_to_array('species') if $o->{species};
147 
148  my $original_databases_args = $o->{databases};
149 
150  #Tables
151  if ($o->{tables} && !$o->{sql}) {
152  $self->_cmd_line_to_array('tables');
153  $self->v(q{Will work with the tables [%s]}, join(q{,}, @{ $o->{tables} }));
154  }
155 
156  if ($o->{defaults}) {
157  $self->_set_opts_from_hostname();
158  } else {
159  $o->{port} = 3306 if !$o->{port};
160  if ($o->{pattern}) {
161  my $p = $o->{pattern};
162  $p = qr/$p/;
163  $o->{databases} = $self->_all_dbs($p);
164  }
165  $o->{directory} = File::Spec->rel2abs($o->{directory});
166  }
167 
168  if(! $o->{username}) {
169  pod2usage(
170  -msg => 'No -username given on the command line or in the configuration file',
171  -exitval => 1,
172  -verbose => 0
173  );
174  }
175 
176  $self->v(q{Using the database server %s@%s:%d},
177  map { $o->{$_} } qw/username host port/);
178 
179  #Filter for those on the specified server; sometimes redundant
180  my %dbs = map { $_ => 1 } @{ $self->_all_dbs() };
181  my @final_dbs;
182  foreach my $db (@{$o->{databases}}) {
183  if($dbs{$db}) {
184  push(@final_dbs, $db);
185  }
186  else {
187  $self->v('DB %s is not available from the specified server', $db);
188  }
189  }
190  $o->{databases} = \@final_dbs;
191 
192  #Filtering DBs based on groups & species
193  if ($o->{groups}) {
194  my %dbs;
195  foreach my $group (@{ $o->{groups} }) {
196  $self->v('Filtering for group %s', $group);
197  %dbs = map { $_ => 1 } grep { / _ $group _ /xms } @{ $o->{databases} };
198  }
199  $o->{databases} = [ keys %dbs ];
200  }
201  if ($o->{species}) {
202  my %dbs;
203  foreach my $species (@{ $o->{species} }) {
204  $self->v('Filtering for species %s', $species);
205  %dbs = map { $_ => 1 } grep { / $species _ /xms } @{ $o->{databases} };
206  }
207  $o->{databases} = [ keys %dbs ];
208  }
209 
210  #Do we have any DBs left to process?
211  my $db_count = scalar(@{ $o->{databases} });
212  if ($db_count == 0) {
213  my $msg = 'No databases found on the server ' . $o->{host};
214  if($original_databases_args && $o->{defaults}) {
215  my $version = $o->{version} || '-NONE';
216  $msg .= qq{. You specified the -database arg and -defaults. Are you on the correct server or did -version '$version' excluded this DB?};
217  }
218  pod2usage(-msg => $msg, -exitval => 1, -verbose => 0);
219  }
220  $self->v(q{Working %d database(s)}, $db_count);
221 
222  $o->{databases} = [ sort { $a cmp $b } @{ $o->{databases} } ];
223 
224  $o->{verbose} = 1 if $o->{dry};
225 
226  return;
227 }
228 
229 sub dry {
230  my ($self) = @_;
231  my $databases = $self->opts()->{databases};
232  my $list = join(q{,}, @{$databases});
233  $self->v(q{The following databases would have been dumped [%s]}, $list);
234  return;
235 }
236 
237 sub process {
238  my ($self) = @_;
239 
240 
241  my $test_case = $self->opts()->{testcompatible};
242 
243  $self->v('Producing test case compatible dumps') if $test_case;
244 
245  my $databases = $self->opts()->{databases};
246  foreach my $db (@{$databases}) {
247  $self->v('Working with database %s', $db);
248 
249  #Setup connection
250  $self->dbh($db);
251 
252  $self->_setup_dir($db);
253 
254  #Get all tables
255  my @tables = keys %{ $self->tables() };
256 
257  #Do data dumps if we didn't ask for just SQL
258  if (!$self->opts()->{sql}) {
259  my @tables_to_process;
260  if ($self->opts()->{tables}) {
261  my %lookup;
262  %lookup = map { $_ => 1 } @{ $self->opts()->{tables} };
263  @tables_to_process = grep { $lookup{$_} } @tables;
264  } else {
265  @tables_to_process = @tables;
266  }
267  foreach my $table (sort { $a cmp $b } @tables_to_process) {
268  next if $self->is_view($table);
269  $self->data($table, $db);
270  }
271  } else {
272  $self->v('-sql mode is on so no data dumping will occur');
273  }
274 
275  #Do SQL
276  my $sql_file;
277  my $fh;
278  if($test_case) {
279  $sql_file = $self->file('table.sql');
280  unlink $sql_file if -f $sql_file;
281  open $fh, '>', $sql_file or croak "Cannot open filehandle to $sql_file: $!";
282  }
283  else {
284  $sql_file = $self->file($db . '.sql.gz');
285  unlink $sql_file if -f $sql_file;
286  $fh = IO::Compress::Gzip->new($sql_file) or croak "Cannot create gzip stream to $sql_file: $GzipError";
287  }
288 
289  my $writer = sub {
290  my (@tabs) = @_;
291  foreach my $table (sort { $a cmp $b } @tabs) {
292  my $sql = $self->sql($table);
293  print $fh $sql, ';', "\n" x 2;
294  }
295  };
296  $writer->(grep { !$self->is_view($_) } @tables);
297  $writer->(grep { $self->is_view($_) } @tables);
298  $fh->close();
299  $self->permissions($sql_file);
300 
301  #Checksum the DB's files
302  $self->checksum() if ! $test_case;
303 
304  #Reset everything
305  $self->clear_dbh();
306  $self->clear_current_dir();
307  $self->clear_tables();
308 
309  $self->v('Finished with database %s', $db);
310  }
311  return;
312 }
313 
314 sub sql {
315  my ($self, $table) = @_;
316  my $q_table = $self->dbh()->quote_identifier($table);
317  my $array =
318  $self->dbh()
319  ->selectcol_arrayref(qq{SHOW CREATE TABLE $q_table}, { Columns => [2] });
320  my $sql = $array->[0];
321  return $self->modify_sql($sql, $table);
322 }
323 
324 sub modify_sql {
325  my ($self, $sql, $table) = @_;
326  if ($self->is_view($table)) {
327  $sql =~ s/DEFINER=.+ \s+ SQL/DEFINER=CURRENT_USER() SQL/xms;
328  $sql =~ s/SQL \s+ SECURITY \s+ DEFINER/SQL SECURITY INVOKER/xms;
329  }
330  if($self->opts()->{testcompatible}) {
331  $sql =~ s/DEFAULT\s+CHARSET=latin1//xms;
332  $sql =~ s/COLLATE=latin1_bin//xms;
333  $sql =~ s/AUTO_INCREMENT=\d+//xms;
334  $sql =~ s/CHARACTER SET latin1//g;
335  $sql =~ s/COLLATE latin1_bin//g;
336  }
337  return $sql;
338 }
339 
340 sub data {
341 
342  my ($self, $table, $db) = @_;
343  return if $self->is_view($table);
344  $self->v('Dumping table %s', $table);
345  my $q_table = $self->dbh()->quote_identifier($table);
346  my $file = $self->file($table . '.txt');
347 
348  my $dbc_params = $self->dbc_params($db);
349 
350  my $mysql_exe = 'mysql';
351 
352  my @cmd = (
353  $mysql_exe,
354  $dbc_params,
355  '--max_allowed_packet=1024M',
356  '--quick',
357  '--silent',
358  '--skip-column-names',
359  "-e 'SELECT * FROM ${db}.${table}'",
360  '|',
361  'sed -r ',
362  '-e \'s/(^|\t)NULL($|\t)/\1\\\\N\2/g\'',
363  '-e \'s/(^|\t)NULL($|\t)/\1\\\\N\2/g\'',
364  '>',
365  $file
366  );
367  my $cmd = join(' ', @cmd);
368  my $output = `$cmd 2>&1`;
369 
370  $self->compress($file) if ! $self->opts()->{testcompatible};
371  return;
372 }
373 
374 sub checksum {
375  my ($self) = @_;
376  my $dir = $self->current_dir();
377 
378  $self->v('Checksumming directory %s', $dir);
379 
380  opendir(my $dh, $dir) or die "Cannot open directory $dir";
381  my @files = sort { $a cmp $b } readdir($dh);
382  closedir($dh) or die "Cannot close directory $dir";
383 
384  my $checksum = $self->file('CHECKSUMS');
385  unlink $checksum if -f $checksum;
386 
387  open my $fh, '>', $checksum or croak "Cannot open filehandle to $checksum: $!";
388  foreach my $file (@files) {
389  next if $file =~ /^\./; #hidden file or up/current dir
390  next if $file =~ /^CHECKSUM/;
391  my $path = File::Spec->catfile($dir, $file);
392  my $sum = `sum $path`;
393  $sum =~ s/\s* $path//xms;
394  chomp($sum);
395  print $fh "${sum}\t${file}\n";
396  }
397  $fh->close();
398  $self->permissions($checksum);
399 
400  return;
401 }
402 
403 sub dbh {
404  my ($self, $database) = @_;
405  if (!exists $self->{'dbh'}) {
406  my $o = $self->opts();
407  my %args = (host => $o->{host}, port => $o->{port});
408  $args{database} = $database if defined $database;
409 
410  my $dsn =
411  'DBI:mysql:' . join(q{;}, map { $_ . '=' . $args{$_} } keys %args);
412  $self->v('DBI connection URI %s', $dsn);
413  my $dbh =
414  DBI->connect($dsn, $o->{username}, $o->{password}, { RaiseError => 1 });
415 
416  $self->{dbh} = $dbh;
417  }
418  return $self->{'dbh'};
419 }
420 
421 sub dbc_params {
422  my ($self, $database) = @_;
423  my $o = $self->opts();
424  my %args = (host => $o->{host}, port => $o->{port});
425  $args{database} = $database if defined $database;
426 
427  my $dbc_params = join(' ', (
428  '--host='.$o->{host},
429  '--port='.$o->{port},
430  '--user='.$o->{username},
431  '--password='.$o->{password}
432  )
433  );
434 
435  return $dbc_params;
436 }
437 
438 sub clear_dbh {
439  my ($self) = @_;
440  if (exists $self->{dbh}) {
441  $self->{dbh}->disconnect();
442  delete $self->{dbh};
443  }
444  return;
445 }
446 
447 sub is_view {
448  my ($self, $table) = @_;
449  return ($self->tables()->{$table} eq 'VIEW') ? 1 : 0;
450 }
451 
452 sub tables {
453  my ($self) = @_;
454  if (!exists $self->{tables}) {
455  my $array =
456  $self->dbh()->selectcol_arrayref(
457 'select TABLE_NAME, TABLE_TYPE from information_schema.TABLES where TABLE_SCHEMA = DATABASE()',
458  { Columns => [ 1, 2 ] }
459  );
460  my %hits = @{$array};
461  $self->{tables} = \%hits;
462  }
463  return $self->{tables};
464 }
465 
466 sub clear_tables {
467  my ($self) = @_;
468  delete $self->{tables};
469  return;
470 }
471 
472 sub file {
473  my ($self, $filename) = @_;
474  return File::Spec->catfile($self->current_dir(), $filename);
475 }
476 
477 sub current_dir {
478  my ($self, $current_dir) = @_;
479  $self->{'current_dir'} = $current_dir if defined $current_dir;
480  return $self->{'current_dir'};
481 }
482 
483 sub clear_current_dir {
484  my ($self) = @_;
485  delete $self->{current_dir};
486  return;
487 }
488 
489 sub opts {
490  my ($self) = @_;
491  return $self->{'opts'};
492 }
493 
494 sub compress {
495  my ($self, $file) = @_;
496  my $target_file = $file . '.gz';
497 
498  $self->v(q{Compressing '%s' to '%s'}, $file, $target_file);
499 
500  if (-f $target_file) {
501  unlink $target_file
502  or die "Cannot remove the existing gzip file $target_file: $!";
503  }
504 
505  my @stats = stat($file);
506  my $size = $stats[7];
507  if($self->{pigz_binary} && $size >= $MAX_FILE_SIZE) {
508  system ("$PIGZ_BINARY --processes $PIGZ_PROCESSORS -4 $file") and confess "Could not pigz $file using $PIGZ_BINARY";
509  }
510  else {
511  gzip $file => $target_file
512  or die "gzip failed from $file to $target_file : $GzipError\n";
513  }
514  if (-f $target_file && -f $file) {
515  unlink $file or die "Cannot remove the file $file: $!";
516  }
517  $self->permissions($target_file);
518  return $target_file;
519 }
520 
521 sub permissions {
522  my ($self, $file) = @_;
523  my $mode = 0666;
524  chmod($mode, $file) or die "Cannot perform the chmod to mode $mode for file $file";
525  return;
526 }
527 
528 sub v {
529  my ($self, $msg, @args) = @_;
530  return unless $self->opts()->{verbose};
531  my $s_msg = sprintf($msg, @args);
532  my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) =
533  localtime(time());
534  print sprintf("[%02d-%02d-%04d %02d:%02d:%02d] %s\n",
535  $mday, $mon, $year + 1900,
536  $hour, $min, $sec, $s_msg);
537  return;
538 }
539 
540 sub _setup_dir {
541  my ($self, $db) = @_;
542  my @path = ($self->opts()->{directory});
543  if($self->opts()->{testcompatible}) {
544  if( $db =~ /^(?:\w+_test_db_)?([a-zA-Z0-9_]+)_([a-z]+)_\d+/) {
545  push(@path, $1, $2);
546  }
547  else {
548  $self->v("Cannot decipher name and group from $db. Using the database name");
549  push(@path, $db);
550  }
551  }
552  else {
553  push(@path, $db);
554  }
555  my $dir = File::Spec->catdir(@path);
556  $self->current_dir($dir);
557  if (!-d $dir) {
558  mkpath($dir) or die "Cannot create directory $dir: $!";
559  chmod(0777, $dir)
560  or die "Cannot change permissions on dir for everyone to write: $!";
561  }
562  return $dir;
563 }
564 
565 sub _set_opts_from_hostname {
566  my ($self) = @_;
567  my $o = $self->opts();
568  my $defaults = $o->{defaults};
569  return unless $o->{defaults};
570  confess "The given location '$defaults' does not exist" if ! -f $defaults;
571 
572  my $host = $self->_host();
573  my $settings = $self->_hostname_opts_from_config()->{$host};
574  confess "Specified -defaults but $host is not known. Check your $defaults ini file"
575  if !$settings;
576 
577  #Setup default connection params
578  $o->{host} = $settings->{host} || $host; # use a configured host otherwise use hostname
579 
580  #only use if specified
581  $o->{port} = $settings->{port} if $settings->{port};
582  $o->{username} = $settings->{username} if $settings->{username};
583  $o->{password} = $settings->{password} if $settings->{password};
584  $o->{sql} = $settings->{sql} if $settings->{sql};
585 
586  if (!$o->{databases}) {
587  my $opts_pattern = $o->{pattern};
588  $opts_pattern = qr/$opts_pattern/ if $opts_pattern;
589  my $settings_pattern = $settings->{pattern};
590  my $pattern = (defined $opts_pattern) ? $opts_pattern : $settings_pattern;
591  $o->{databases} = $self->_all_dbs($pattern);
592  }
593 
594  #Set default dir
595  $o->{directory} = $settings->{dir};
596 
597  return;
598 }
599 
600 #Assume normal ini-file format
601 sub _hostname_opts_from_config {
602  my ($self) = @_;
603  my $hostname_opts = {};
604  my $target_dir;
605  if($self->opts()->{version}) {
606  $target_dir = 'release-' . $self->opts()->{version};
607  }
608  else {
609  $target_dir = 'dumps';
610  }
611 
612  my $defaults = $self->opts()->{defaults};
613  open my $fh, '<', $defaults or confess "Cannot open defaults file '$defaults' for reading: $!";
614 
615  my $current_section;
616  my $counter = 0;
617  while(my $line = <$fh>) {
618  $counter++;
619  next if $line =~ /^\s*(?:\#|\;|$)/; #next for comments & empty lines
620  $line =~ s/\s\;\s.+$//xmsg; #remove inline comments
621  #Section [sec]
622  if(my ($section) = $line =~ /^\s*\[\s*(.+?)\s*\]\s*$/xms) {
623  $current_section = $section;
624  $hostname_opts->{$current_section} = {};
625  next;
626  }
627  # key = value
628  if( my ($key, $value) = $line =~ /^\s*([^=]+?)\s*=\s*(.*?)\s*$/) {
629 
630  #Compile into a regex
631  if($key eq 'pattern') {
632  $value = qr/$value/;
633  }
634  #Change into the correct location
635  elsif($key eq 'dir') {
636  $value = File::Spec->catdir($value, $target_dir);
637  }
638  $hostname_opts->{$current_section}->{$key} = $value;
639  next;
640  }
641  confess "Error in ini file '$defaults' at line $counter: '$line'";
642  }
643  close $fh;
644  return $hostname_opts;
645 }
646 
647 sub _host {
648  my ($self) = @_;
649  my $host = hostname();
650  return $host;
651 }
652 
653 #Always filter by version if it was given
654 sub _all_dbs {
655  my ($self, $pattern) = @_;
656  my $like = '%';
657  if($self->opts()->{version}) {
658  $like = '%\\_'.$self->opts()->{version}.'%';
659  $self->v(q{Looking for databases with the pattern '%s' }, $like);
660  }
661  my $dbh = $self->dbh();
662  my $databases = $dbh->selectcol_arrayref('show databases like ?',
663  { Columns => [1] }, $like);
664  $self->clear_dbh();
665  return [ grep { $_ =~ $pattern } @{$databases}] if $pattern;
666  return $databases;
667 }
668 
669 sub _cmd_line_to_array {
670  my ($self, $key) = @_;
671  my $array = $self->opts()->{$key};
672  $array = (ref($array) && ref($array) eq 'ARRAY') ? $array : [$array];
673  my $string = join(q{,}, @{$array});
674  my @new_array = split(/,/, $string);
675  $self->opts()->{$key} = \@new_array;
676  return;
677 }
678 
679 Script->run();
680 
681 1;
682 __END__
683 
684 =pod
685 
686 =head1 NAME
687 
688 dump_mysql.pl
689 
690 =head1 SYNOPSIS
691 
692  #Basic
693  ./dump_mysql.pl (-version VER | -release VER) [-defaults] | [ -username USER -password PASS -host HOST [-port PORT] [-pattern 'REGEX' | -databases DB] [-tables TABLE] -directory DIR] [-verbose] [-help | -man]
694 
695  #Test Case compatbile dumps
696  ./dump_mysql.pl -username root -password pass -host 127.0.0.1 -testcompatible -verbose -directory /tmp/test-genome-DBs -database homo_sapiens_core_testdb
697 
698  #Using defaults ini file
699  ./dump_mysql.pl --defaults my.ini --username root --password p --version 64
700 
701  ./dump_mysql.pl --defaults my.ini --username root --password p --release 64 -dry
702 
703  ./dump_mysql.pl --defaults my.ini --username root --password p --version 64 --tables dna
704 
705  ./dump_mysql.pl --defaults my.ini --username root --password p --version 64 --tables meta,meta_coord --tables analysis --groups core,otherfeatures --groups vega
706 
707  ./dump_mysql.pl --defaults my.ini --username root --password p --version 64 --tables meta,meta_coord --tables analysis --groups core,otherfeatures --groups vega --sql
708 
709  #Using host
710  ./dump_mysql.pl --host srv --username root --password p --pattern '.+_64.+' --directory $PWD/dumps
711 
712  ./dump_mysql.pl --host srv --username root --password p --databases my_db --databases other_db --directory $PWD/dumps
713 
714  ./dump_mysql.pl --host srv --username root --password p --databases my_db,toto_db --databases other_db --directory $PWD/dumps
715 
716  ./dump_mysql.pl --host srv --username root --password p --databases my_db --tables dna,dnac --directory $PWD/dumps
717 
718  ./dump_mysql.pl --host srv --username root --password p --db my_db --tables dna --tables dnac --directory $PWD/dumps
719 
720 =head1 DESCRIPTION
721 
722 A script which is used to generate MySQL dumps which take into account issues
723 surrounding BLOB handling, VIEWS and other oddities of the Ensembl MySQL dump
724 process.
725 
726 You B<MUST> be on the database server the dumps are going to be generated
727 from. If not then all file manipulations will fail.
728 
729 As a pose to normal scripts this version is aware of webteam database setup
730 and therefore can automatically configure itself to a set of useful
731 parameters rather than having to manually configure the setup.
732 
733 =head1 OPTIONS
734 
735 =over 8
736 
737 =item B<--username | --user | -u>
738 
739 REQUIRED. Username of the connecting account. Must be able to perform
740 C<SELECT INTO OUTFILE> calls.
741 
742 =item B<--password | -pass | -p>
743 
744 REQUIRED. Password of the connecting user.
745 
746 =item B<--defaults>
747 
748 Uses the default mechanism which involves looking at the host the script
749 is executing on and setting a number of options for databases to look for
750 as well as port settings. C<-defaults> can be used in conjunction with
751 C<-groups>, C<-species> and C<-tables> but not with parameters like <--host>.
752 
753 The options set are specified by your custom ini-file.
754 
755 =item B<--version | --release>
756 
757 If you are using C<--defaults> then you must also specify the version
758 of the databases you are dumping. Once specified the program will only
759 consider databases with the version number in there (specifically the
760 occurance of C<%\_VERSION%>). C<--release> can also be used.
761 
762 =item B<--host | --hostname | -h>
763 
764 Host name of the database to connect to. Cannot be used with <--defaults>.
765 
766 =item B<--port | -P>
767 
768 Optional integer of the database port. Defaults to 3306. Cannot be used
769 with <--defaults>.
770 
771 =item B<--pattern>
772 
773 Allows the specification of a regular expression to select databases with.
774 Cannot be used in conjunction with the C<--databases> argument.
775 
776 =item B<--databases | --database | --db>
777 
778 Allows database name specification and can be used more than once. Cannot
779 be used in conjunction with C<--pattern>. Comma separated values are
780 supported.
781 
782 =item B<--tables | --table>
783 
784 Allows you to specify a table to perform the dumps for. This will be applied
785 to all databases matching the given pattern or the list of databases. Be
786 warned that this will cause a full SQL re-dump and checksum re-calculation.
787 
788 =item B<--directory | --dir>
789 
790 Target directory to place all dumps. A sub-directory will be created here;
791 one per database dump. Cannot be used with <--defaults>.
792 
793 =item B<--sql>
794 
795 Force a dump of the SQL for the database and nothing else.
796 
797 =item B<--testcompatible>
798 
799 If specified will create MySQL dumps compatible with the Ensembl test
800 framework. This creates 2 levels of directory based on the database
801 species and the group it belongs to e.g. homo_sapiens and otherfeatures. We
802 also avoid gzipping any file and produce a single table.sql file.
803 
804 =item B<--verbose>
805 
806 Makes the program give more information about what is going on. Otherwise
807 the program is silent.
808 
809 =item B<--log>
810 
811 If given the script will write all logs to output. Switches on C<--verbose>
812 
813 =item B<--perlgzip>
814 
815 Force the use of Perl's GZip libraries rather than using external zipping
816 like pigz.
817 
818 =item B<--dry>
819 
820 If specified the script will list all databases which have been found and
821 will be dumped but will not run any dumping process.
822 
823 =item B<--help>
824 
825 Help message
826 
827 =item B<--man>
828 
829 Man page
830 
831 =back
832 
833 =head1 DEFAULTS FILE FORMAT
834 
835 The defaults file format is an ini file which respects all basic rules about
836 comments (preceeded by a ;), section headers and key/value pairs. The basic
837 form of an entry is
838 
839  ; basic format
840  [server-name]
841  port = 3306 ; port of the DB
842  pattern = ^homo_sap\w+$ ; regular expression to filter DBs by
843  dir = /path/to/dump/dir ;
844 
845  ;more complex
846  [other-server-name]
847  port = 3306 ; port of the DB
848  pattern = ^web\w+$ ; regular expression to filter DBs by
849  dir = /path/to/dump/dir ;
850  sql = 1 ; dump just the SQL for these databases
851 
852  ;if your host isn't the same as the server you are running the script on
853  [mydumpserver]
854  host = my-real-server ; host you want the script to connect to
855  port = 3306 ; port of the DB
856  pattern = ^web\w+$ ; regular expression to filter DBs by
857  dir = /path/to/dump/dir ;
858  sql = 1 ; dump just the SQL for these databases
859 
860  ; and if you wanted everything in the config file so our cmd line becomes
861  ; ./dump_mysql.pl -defaults mydbcfg.ini
862  [myserver]
863  port = 5306
864  username = uberuser
865  password = uberpassword
866  pattern = ^homo_sap.+var.+$
867  dir = /path/to/dump/dir
868 
869 As an example of one which grabs all core dbs from a-m and puts it in /dumps
870 
871  [genome.mysql.server]
872  port = 3306
873  pattern = ^[a-m]\w*_core_\d+_\d+[a-z]?$
874  dir = /dumps
875 
876 The server name should be the same as what is emitted from
877 
878  perl -MSys::Hostname -e 'print hostname(), "\n"'
879 
880 Also using line bounded regular expressions i.e. C<^> and C<$> will improve
881 the accuracy of the databases you are looking for.
882 
883 =head1 REQUIREMENTS
884 
885 =over 8
886 
887 =item Perl 5.8+
888 
889 =item DBI
890 
891 =item DBD::mysql
892 
893 =item IO::Compress::Gzip
894 
895 =back
896 
897 =head1 MAKING IT FASTER
898 
899 =over 8
900 
901 =item pigz L<http://www.zlib.net/pigz/> a parallel GZip compressor
902 
903 =back
904 
905 =end
map
public map()
Script::run
public run()
Script::dry
public dry()
about
public about()
Script
Definition: dump_mysql.pl:9