File Coverage

blib/lib/MySQL/Backup.pm
Criterion Covered Total %
statement 6 311 1.9
branch 0 144 0.0
condition 0 29 0.0
subroutine 2 13 15.3
pod 0 11 0.0
total 8 508 1.5


line stmt bran cond sub pod time code
1             package MySQL::Backup;
2            
3 1     1   34473 use strict;
  1         2  
  1         43  
4            
5 1     1   2327 use DBI;
  1         37750  
  1         9735  
6             our $VERSION = '0.04';
7            
8             sub new{ #standart constructor
9 0     0 0   my ($pkg, $dbname, $dbhost, $dbuser, $dbpass, $param) = @_;
10            
11 0           my $self = {};
12 0           my $dbh = DBI->connect("DBI:mysql:$dbname:$dbhost", $dbuser, $dbpass, {RaiseError=>1});
13 0           $self->{'DBH_OBJ'} = $dbh;
14 0           $self->{'param'} = {};
15            
16 0           foreach my $key(keys %{$param}){
  0            
17 0           $self->{'param'}->{$key} = $param->{$key};
18             }
19            
20 0           bless($self, $pkg);
21 0           return $self;
22             }
23            
24             sub new_from_DBH{ #if you have already DBI connection, you can use this
25 0     0 0   my ($pkg, $dbh, $param) = @_;
26            
27 0           my $self = {};
28 0           $self->{'DBH_OBJ'} = $dbh;
29 0           $self->{'param'} = {};
30            
31 0           foreach my $key(keys %{$param}){
  0            
32 0           $self->{'param'}->{$key} = $param->{$key};
33             }
34            
35 0           bless($self, $pkg);
36 0           return $self;
37             }
38            
39             sub run_sql{
40 0     0 0   my ($self, $sql) = @_;
41 0           my $dbh = $self->{'DBH_OBJ'};
42             #die $dbh->prepare($sql);
43            
44 0   0       my $sth = $dbh->prepare($sql) || die $self->caller();
45            
46 0 0         if (not $sth){
47 0           die $DBI::errstr;
48             }
49            
50 0           my $res = $sth->execute;
51 0 0         if (not $res){
52 0           return undef;
53             }
54 0           return $sth;
55             }
56            
57             sub arr_hash{
58 0     0 0   my ($self, $sql) = @_;
59 0           my @res;
60 0 0         if (my $sth = $self->run_sql($sql)){
61 0           while (my $ref = $sth->fetchrow_hashref){
62 0           push @res, $ref;
63             }
64             }
65 0           return @res;
66             }
67            
68             sub param{
69 0     0 0   my ($self, $ref) = @_;
70 0 0         if(ref $ref eq 'HASH'){
    0          
71 0           foreach my $key(keys %{$ref}){
  0            
72 0           $self->{'param'}->{$key} = $ref->{$key};
73             }
74             }
75             elsif(ref $ref eq 'SCALAR'){
76 0 0         if(defined $self->{'param'}->{$ref}){
77 0           return $self->{'param'}->{$ref};
78             }
79             else{
80 0           $self->{'error'} = 'can\'t return this param: please check if name of it is right. Also, this param can be undefined';
81 0           return undef;
82             }
83             }
84             }
85            
86             sub table_desc{ #creates a structure of the inputed table
87            
88 0     0 0   my ($self, $table) = @_;
89 0           my @temp = $self->arr_hash("SHOW COLUMNS FROM $table");
90 0           my @temp2;
91            
92 0           foreach my $ref(@temp){
93 0 0         my $null = 'NOT NULL' if ($ref->{'Null'} !~ m/YES/i);
94 0           my $default;
95 0 0         if($ref->{'default'}){
96 0           $default .= $null.' default '."'".$ref->{'Default'}."'";
97             }
98             else{
99 0 0 0       if (($ref->{'Null'} =~ m/YES/i)and(!($ref->{'Type'} =~ m/timestamp/i))){
100 0           $default .= 'default '.'NULL';
101             }
102             else{
103 0           $default .= $null;
104             }
105             }
106 0           chomp $default;
107 0 0         push @temp2, join(' ', '`'.$ref->{'Field'}.'`', $ref->{'Type'}, $default.($ref->{'Extra'}?' '.$ref->{'Extra'}:''));
108             }
109            
110 0           my $columns = join(', ', @temp2);
111            
112 0           @temp = $self->arr_hash("SHOW KEYS FROM $table");
113 0           foreach my $ref(@temp){
114 0 0         if ($ref->{'Key_name'} =~ m/PRIMARY/i){
    0          
    0          
115 0           $columns .= ", PRIMARY KEY (`".$ref->{'Column_name'}."`)";
116             }
117             elsif ($ref->{'Non_unique'} =~ m/0/i){
118 0           $columns .= ", UNIQUE INDEX (`".$ref->{'Column_name'}."`)";
119             }
120             elsif ($ref->{'Index_type'} =~ m/FULLTEXT/i){
121 0           $columns .= ", FULLTEXT INDEX (`".$ref->{'Column_name'}."`)";
122             }
123             else{
124 0           $columns .= ", INDEX (`".$ref->{'Column_name'}."`)";
125             }
126             }
127 0           my $sql = "CREATE TABLE `$table` ($columns);";
128            
129 0           return $sql;
130             }
131            
132             sub create_structure{ #creates a structure of the current DB
133 0     0 0   my $self = shift;
134 0           my @arr;
135             my $sql;
136            
137 0 0         unless($self->{'param'}->{'tables'}){
138 0           my $sth = $self->run_sql("SHOW TABLES");
139 0           while(my @temp = $sth->fetchrow_array()){
140 0           push @arr, $temp[0];
141             }
142            
143 0           foreach my $temp(@arr){
144 0           $sql .= $self->table_desc($temp)."\n";
145             }
146             }
147             else{
148 0           @arr = @{$self->{'param'}->{'tables'}};
  0            
149 0           foreach my $temp(@arr){
150 0           $sql .= $self->table_desc($temp)."\n";
151             }
152             }
153            
154 0           return $sql;
155             }
156            
157             sub get_table_data{
158            
159 0     0 0   my ($self, $table) = @_;
160 0           my $data;
161 0           my @temp = $self->arr_hash("SELECT * FROM $table WHERE 1");
162            
163 0           foreach my $ref (@temp){
164 0           my @keys = keys %$ref;
165 0           my $key_list = '`'.join('`, `', @keys).'`';
166 0           my @values;
167 0           for(my $i=0; $i<=$#keys; $i++){
168 0           push @values, $self->{'DBH_OBJ'}->quote($ref->{$keys[$i]});
169             }
170 0           my $value_list = join(', ', @values);
171 0 0         if($self->{'param'}->{'USE_REPLACE'}){
172 0           $data .= "REPLACE INTO `$table` ($key_list) VALUES ($value_list);\n";
173             }
174             else{
175 0           $data .= "INSERT INTO `$table` ($key_list) VALUES ($value_list);\n";
176             }
177             }
178            
179 0           return $data;
180             }
181            
182             sub data_backup{ #get all data from current database
183            
184 0     0 0   my $self = shift;
185             #my $sth = $self->run_sql("SHOW TABLES");
186             #my (@tables, @tables_for_lock);
187             #while(my $temp = $sth->fetchrow_array()){
188             # push @tables, "$temp";
189             # push @tables_for_lock, "$temp WRITE";
190             #}
191             #$self->run_sql("LOCK TABLES ".join(', ', @tables_for_lock));
192 0           my @arr;
193 0           my $sql = '';
194             #foreach my $temp(@tables){
195             # $sql .= $self->get_table_data($temp);
196             #}
197            
198 0 0         unless($self->{'param'}->{'tables'}){
199 0           my $sth = $self->run_sql("SHOW TABLES");
200 0           while(my @temp = $sth->fetchrow_array()){
201 0           push @arr, $temp[0];
202             }
203            
204 0           foreach my $temp(@arr){
205 0           my $table_data = $self->get_table_data($temp);
206 0 0 0       $sql .= "/* $temp */\n" if (($self->{'param'}->{'SHOW_TABLE_NAMES'})and($table_data));
207 0 0         $sql .= $table_data if $table_data;
208             }
209             }
210             else{
211 0           foreach my $temp(@{$self->{'param'}->{'tables'}}){
  0            
212 0           my $table_data = $self->get_table_data($temp);
213 0 0 0       $sql .= "/* $temp */\n" if (($self->{'param'}->{'SHOW_TABLE_NAMES'})and($table_data));
214 0 0         $sql .= $table_data if $table_data;
215             }
216             }
217            
218             #$self->run_sql("UNLOCK TABLES");
219 0           return $sql;
220             }
221            
222             sub run_restore_script{
223 0     0 0   my ($self, $file) = @_;
224 0           my $sth = $self->run_sql("SHOW TABLES");
225 0           my $dbh = $self->{'DBH_OBJ'};
226 0           my (@tables, @tables_for_lock);
227 0           while(my $temp = $sth->fetchrow_array()){
228 0           push @tables, "$temp";
229 0           push @tables_for_lock, "$temp WRITE";
230             }
231             #$self->run_sql("LOCK TABLES ".join(', ', @tables_for_lock));
232             #$sth = run_sql("FLUSH TABLES");
233 0           foreach my $temp(@tables){
234 0           $dbh->do("DROP TABLE IF EXISTS `$temp`");
235             }
236            
237 0           open(FILE, $file);
238 0           my $fline = readline(FILE);
239 0 0         if ($fline =~ m/\r\n/){
    0          
    0          
240 0           $/ = ";\r\n";
241             }
242             elsif($fline =~ m/\n\r/){
243 0           $/ = ";\n\r";
244             }
245             elsif($fline =~ m/\r/){
246 0           $/ = ";\r";
247             }
248             else{
249 0           $/ = ";\n";
250             }
251 0           my @sql = ;
252 0           unshift @sql, $fline;
253 0           $/= "\n";
254 0           close(FILE);
255            
256 0           foreach my $sql(@sql){
257 0           chomp $sql;
258 0           $self->run_sql($sql);
259             }
260            
261             #$dbh->do("RESET MASTER");
262             #$self->run_sql("UNLOCK TABLES");
263 0           return \@sql;
264             }
265            
266             sub run_upgrade_script{
267 0     0 0   my $self =shift;
268 0           my $file = shift;
269 0           my $db_vers;
270 0           my $dbh = $self->{'DBH_OBJ'};
271 0           my $sth = $self->run_sql("SHOW TABLES");
272 0           my (@tables, @tables_for_lock, $table_list);
273 0           while(my $temp = $sth->fetchrow_array()){
274 0           push @tables, "`$temp`";
275 0           push @tables_for_lock, "`$temp` WRITE";
276             }
277             #run_sql("LOCK TABLES ".join(', ', @tables_for_lock));
278             #$sth = run_sql("FLUSH TABLES");
279            
280 0           open(FILE, $file);
281 0           my $fline = readline(FILE);
282 0 0         if ($fline =~ m/\r\n/){
    0          
283 0           $/ = ";\r\n";
284             }
285             elsif($fline =~ m/\n\r/){
286 0           $/ = ";\n\r";
287             }
288             else{
289 0           $/ = ";\n";
290             }
291            
292 0           my @sql = ;
293 0           unshift @sql, $fline;
294 0           $/= "\n";
295 0           close(FILE);
296            
297 0           foreach my $sql(@sql){
298 0           chomp $sql;
299 0 0 0       if($sql =~ /^CREATE TABLE ([`\w]+) \((.*)\)/i){
    0          
    0          
300 0           for(my $i=0; $i<=$#tables; $i++){
301             #die "lc($tables[$i]) eq lc($1)";
302 0 0 0       if(($tables[$i] eq $1)or(lc($tables[$i]) eq lc($1))){
303 0           my $temp_2_1 = $2;
304 0           my @columns_desc = split /, /, $temp_2_1;
305 0           my $real_table = $self->table_desc($tables[$i]);
306             #die $real_table
307             #die $real_table."
".$sql if $tables[$i] eq 'perldesk_kb_ratings';
308 0           $real_table =~ /^CREATE TABLE ([`\w]+) \((.*)\)/i;
309 0           my $temp_2_2 = $2;
310 0           my @real_columns_desc = split /, /, $temp_2_2;
311            
312            
313            
314 0           my (@columns, @real_columns);
315 0           $#columns = $#columns_desc;
316 0           $#real_columns = $#real_columns_desc;
317 0           for(my $j=0; $j<=$#columns_desc; $j++){
318 0           $columns_desc[$j] =~ s/^\s*(.*?)\s*$/$1/gi;
319 0 0         if($columns_desc[$j] =~ m/^([`\w]+) /){
320 0           $columns[$j] = $1;
321             }
322             }
323            
324 0           for(my $j=0; $j<=$#real_columns_desc; $j++){
325 0           $real_columns_desc[$j] =~ s/^\s*(.*?)\s*$/$1/gi;
326 0 0         if($real_columns_desc[$j] =~ m/^([`\w]+) /){
327 0           $real_columns[$j] = $1;
328             }
329             }
330            
331 0           my $bool = 0;
332 0           for(my $j=0; $j<=$#columns; $j++){ #checking for existing of columns
333 0           for(my $k=0; $k<=$#real_columns; $k++){
334 0           $bool = 0;
335 0 0         if ($columns_desc[$j] =~ /^PRIMARY KEY \(([`\w]+)\)/){ #checking if it's Primary key
    0          
    0          
    0          
    0          
    0          
336 0           my $column_name = $1;
337             #die $tables[$i];
338 0           $sth = $self->run_sql("SHOW KEYS FROM $tables[$i]");
339            
340 0           while(my $temp = $sth->fetchrow_hashref()){
341             # die $temp->{'Column_name'}.' '.$column_name;
342 0 0 0       if((($temp->{'Key_name'} eq 'PRIMARY')or($temp->{'Key_name'} eq 'primary'))and(('`'.$temp->{'Column_name'}.'`' eq $column_name)or('`'.lc($temp->{'Column_name'}).'`' eq lc($column_name)))){
      0        
      0        
343 0           $bool= 1;
344             #die $bool;
345 0           last;
346             }
347             }
348             }
349            
350            
351             elsif ($columns_desc[$j] =~ /^KEY(.*)\(([`\w]+)\)/){ #checking if it's key
352             #for(my $l=0; $l<$#real_columns; $l++){
353 0 0         if($columns_desc[$j] eq $real_columns_desc[$k]){
354            
355 0           $bool = 1;
356 0           last;
357             }
358             #}
359 0 0         if($bool){last;}
  0            
360             }
361             # elsif ($columns_desc[$j] =~ /^INDEX/){
362            
363             # }
364             elsif ($columns_desc[$j] =~ /^INDEX(.*)\(([`\w]+)\)/){ #checking if it's key
365             #for(my $l=0; $l<$#real_columns; $l++){
366 0 0         if($columns_desc[$j] eq $real_columns_desc[$k]){
367             #die $real_columns_desc[$k];
368 0           $bool = 1;
369             #die $columns_desc[$j]." ".$real_columns_desc[$k];
370             #die $bool;
371 0           last;
372             }
373             #}
374 0 0         if($bool){last;}
  0            
375             }
376             elsif ($columns_desc[$j] =~ /^UNIQUE INDEX(.*)\(([`\w]+)\)/){ #checking if it's key UNIQUE
377            
378             #for(my $l=0; $l<$#real_columns; $l++){
379 0 0         if($columns_desc[$j] eq $real_columns_desc[$k]){
380 0           $bool = 1;
381             #die $columns_desc[$j];
382 0           last;
383             }
384             #}
385 0 0         if($bool){last;}
  0            
386             }
387            
388             elsif ($columns_desc[$j] =~ /^FULLTEXT INDEX(.*)\(([`\w]+)\)/){ #checking if it's key FULLTEXT
389             #die $columns_desc[$j];
390             #for(my $l=0; $l<$#real_columns; $l++){
391 0 0         if($columns_desc[$j] eq $real_columns_desc[$k]){
392 0           $bool = 1;
393 0           last;
394             }
395             #}
396 0 0         if($bool){last;}
  0            
397             }
398            
399             elsif(lc($columns[$j]) eq lc($real_columns[$k])){ #checking for existence of column
400 0 0         if(lc($columns_desc[$j]) eq lc($real_columns_desc[$k])){
401 0           $bool = 1;
402 0           last;
403             }
404             else{
405             #die "lc($columns[$j]) eq lc($real_columns[$k])";
406             # die "$columns_desc[$j] eq $real_columns_desc[$k]";
407 0           $bool = 2;
408 0           last;
409             }
410             }
411             }
412 0           my $key;
413 0 0         unless($bool){ #the column or Key doesn't exist
    0          
414             #chomp $columns_desc[$j];
415            
416 0 0         if($columns_desc[$j] =~ /^PRIMARY KEY \(([`\w]+)\)/){
417            
418 0           my $column_name = $1; #die $column_name;
419 0           $key = "PRIMARY KEY ($column_name)";
420             #killimg duplicates
421 0           my $sth = $self->run_sql("SELECT * FROM $tables[$i] WHERE 1");
422 0           while(my $temp = $sth->fetchrow_hashref()){
423 0           my $th = $self->run_sql("SELECT * FROM $tables[$i] WHERE $column_name = ".$dbh->quote($temp->{$column_name}));
424 0           my $rows = $th->rows;
425 0 0         if($rows > 1){
426 0           $self->run_sql("DELETE FROM $tables[$i] WHERE $column_name = ".$dbh->quote($temp->{$column_name})." LIMIT 1");
427 0           $table_list.="DELETE FROM $tables[$i] WHERE $column_name = ".$dbh->quote($temp->{$column_name})." LIMIT 1\n";
428             }
429             }
430             }
431 0           my $key_name;
432 0 0         unless ($key){
433 0 0         if($columns_desc[$j] =~ /^KEY (.*) \((.*)\)/){
    0          
    0          
    0          
    0          
    0          
    0          
    0          
434 0           $key = "INDEX $1 ($2)";
435 0           $key_name = $1;
436             }
437             elsif($columns_desc[$j] =~ /^KEY(.*)\((.*)\)/){
438 0           $key = "INDEX ($2)";
439 0           $key_name = $2;
440             }
441             elsif($columns_desc[$j] =~ /^INDEX (.*) \((.*)\)/){
442 0           $key = "INDEX $1 ($2)";
443 0           $key_name = $1;
444             }
445             elsif($columns_desc[$j] =~ /^INDEX(.*)\((.*)\)/){
446 0           $key = "INDEX ($2)";
447 0           $key_name = $2;
448             }
449             elsif($columns_desc[$j] =~ /^UNIQUE INDEX (.*) \((.*)\)/){
450 0           $key = "UNIQUE INDEX $1 ($2)";
451 0           $key_name = $1;
452             }
453             elsif($columns_desc[$j] =~ /^UNIQUE INDEX(.*)\((.*)\)/){
454 0           $key = "UNIQUE INDEX ($2)";
455 0           $key_name = $2;
456             }
457             elsif($columns_desc[$j] =~ /^FULLTEXT INDEX (.*) \((.*)\)/){
458 0           $key = "FULLTEXT INDEX $1 ($2)";
459 0           $key_name = $1;
460             }
461             elsif($columns_desc[$j] =~ /^FULLTEXT INDEX(.*)\((.*)\)/){
462 0           $key = "FULLTEXT INDEX ($2)";
463 0           $key_name = $2;
464             }
465            
466             }
467            
468 0 0         unless($key){
469 0           my $add;
470 0 0         if($columns_desc[$j] =~ m/auto_increment/i){$add=' PRIMARY KEY';}
  0            
471 0           my $sql2 = "ALTER TABLE $tables[$i] ADD COLUMN ".$columns_desc[$j].$add;
472 0 0         eval{$dbh->do($sql2)} or die $self->errstr("Couldn't execute statement: $sql2 $DBI::errstr: stopped");
  0            
473 0           $table_list .= $sql2."\n";
474             }
475             else{
476            
477 0           my $sql2 = "SHOW KEYS FROM $tables[$i]";
478             #die $sql2;
479 0           my $sth = $self->run_sql($sql2);
480 0           $table_list .= $sql2."\n";
481 0           my $key_exists;
482 0           while(my $ref = $sth->fetchrow_hashref()){
483 0           die $ref->{'Key_name'}.' ? '.$key_name;
484 0 0         if('`'.$ref->{'Key_name'}.'`' eq $key_name){
485 0           $key_exists = 1;
486 0           last;
487             }
488             }
489 0 0         unless($key_exists){
490 0           $sql2 = "ALTER TABLE $tables[$i] ADD $key";
491 0           die $sql2;
492 0           $self->run_sql($sql2);
493 0           $table_list .= $sql2."\n";
494             }
495             }
496            
497             #$bool =1;
498             }
499             elsif($bool == 2){
500 0           my $add;
501             #if($columns_desc[$j] =~ m/auto_increment/i){$add=' PRIMARY KEY';}
502 0           my $sql2 = "ALTER TABLE $tables[$i] MODIFY COLUMN ".$columns_desc[$j].$add;
503 0 0         eval{$dbh->do($sql2)} or die $self->errstr("Couldn't execute statement: $sql2 $DBI::errstr: stopped");
  0            
504 0           $table_list .= $sql2."\n";
505             }
506             }
507            
508 0           $table_list .= "Log: ".$tables[$i]." ".$2."\n";
509 0           last;
510             }
511 0 0         if($i == $#tables){ #table doesn't exist
512 0           $dbh->do($sql);
513 0           $table_list .= $sql."\n";
514             }
515             }
516             }
517             elsif($sql =~ /^ALTER TABLE (.*) DROP INDEX (.*);/i){
518 0           $sth = $self->run_sql("SHOW KEYS FROM $1");
519 0           my $bool = 0;
520 0           while(my $temp = $sth->fetchrow_hashref()){
521 0 0         if(lc($temp->{'Key_name'}) eq lc($2)){
522 0           $bool= 1;
523 0           last;
524             }
525             }
526 0 0         if ($bool){
527 0           $table_list .= $sql."\n";
528 0           $dbh->do($sql);
529             }
530             }
531             elsif(($sql =~ /^INSERT/i)or($sql =~ /^REPLACE/i)){
532 0           $sql =~ s/^INSERT/REPLACE/i;
533 0           $sql =~ m/INTO (\w+)/i;
534 0           my $table = $1;
535 0 0 0       if(($table eq 'perlDesk_settings')and($sql !~ /^ALTER/i)){
536 0 0         if($sql =~ m/\(value, setting\) VALUES \('(.*)', 'db_version'\);$/i){
537 0           $db_vers = $1;
538 0           $table_list .= $sql."\n";
539 0           $self->run_sql($sql);
540             }
541             else{
542 0           $sql =~ m/\(value, setting\) VALUES \('(.*)', '(.*)'\);$/i;
543 0           my ($value, $setting) = ($1, $2);
544 0           my $sth = $self->run_sql("SELECT * FROM perlDesk_settings WHERE setting=".$dbh->quote($setting));
545 0 0         unless($sth->rows){
546 0           $table_list .= $sql."\n";
547 0           $self->run_sql($sql);
548             }
549             }
550             }
551             else{
552 0           $table_list .= $sql."\n";
553 0           my $rt = $dbh->prepare($sql);
554 0           $rt->execute;
555             }
556             }
557             else{
558 0           $table_list .= $sql."\n";
559 0           my $rt = $dbh->prepare($sql);
560 0           $rt->execute;
561             }
562             }
563            
564            
565            
566            
567 0           $self->run_sql("UNLOCK TABLES");
568 0           return $db_vers;
569             }
570            
571             1;
572            
573             __END__