79599cdac44e725c9b5e4c3b8eee0e6e9dc9b29a
[koha.git] / misc / maintenance / fix_mysql_constraints.pl
1 #!/usr/bin/perl
2 #
3 # Copyright (C) 2012 Tamil s.a.r.l.
4 #
5 # This file is part of Koha.
6 #
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20 use Modern::Perl;
21
22 use Getopt::Long qw( GetOptions );
23 use Pod::Usage qw( pod2usage );
24 use Try::Tiny qw( catch try );
25 use Koha::Script;
26 use C4::Context;
27
28
29 my ($doit, $alterengine, $help);
30 my $result = GetOptions(
31     'doit'        => \$doit,
32     'alterengine' => \$alterengine,
33     'help|h'      => \$help,
34 );
35
36
37 sub usage {
38     pod2usage( -verbose => 2 );
39     exit;
40 }
41
42
43 sub fix_mysql_constraints {
44     my ($doit) = @_;
45
46     # Get all current DB constraints
47     my $dbh = C4::Context->dbh;
48     $dbh->{RaiseError} = 1;
49     $dbh->{ShowErrorStatement} = 1;
50     my $database = C4::Context->config('database');
51     my %db_constraint = map { $_->[0] => undef } @{$dbh->selectall_arrayref(
52         "SELECT CONSTRAINT_NAME
53            FROM information_schema.table_constraints
54           WHERE constraint_schema = '$database'
55             AND CONSTRAINT_TYPE != 'PRIMARY KEY' ")};
56
57     my $base_dir = C4::Context->config('intranetdir');
58     open my $fh, "<", "$base_dir/installer/data/mysql/kohastructure.sql"
59         or die "Unable to open kohastructure.sql file";
60
61     my $table_name;
62     my $engine_altered;
63     # FIXME: This hide problem. But if you run this script, it means that you
64     # have already identified issues with your Koha DB integrity, and will fix
65     # any necessary tables requiring records deleting.
66     $dbh->do("SET FOREIGN_KEY_CHECKS=0");
67     my $line = <$fh>;
68     while ( $line ) {
69         if ( $line =~ /CREATE TABLE (.*?) / ) {
70             $table_name = $1;
71             $table_name =~ s/\`//g;
72             $engine_altered = 0;
73             $line = <$fh>;
74             next;
75         }
76         unless ( $line =~ /CONSTRAINT /i ) {
77             $line = <$fh>;
78             next;
79         }
80         my $constraint = $line;
81         CONTRAINT_LOOP:
82         while ( $constraint !~ /,/ ) {
83             $line = <$fh>;
84             last CONTRAINT_LOOP if $line =~ /ENGINE/i;
85             $line =~ s/^ */ /;
86             $constraint .= $line;
87         }
88         $constraint =~ s/^ *//;
89         $constraint =~ s/\n//g;
90         $constraint =~ s/ *$//;
91         $constraint =~ s/,$//;
92         my ($name) = $constraint =~ /CONSTRAINT (.*?) /;
93         $name =~ s/\`//g;
94         unless ( exists($db_constraint{$name}) ) {
95             if ( $alterengine && !$engine_altered ) {
96                 my $sql = "ALTER TABLE $table_name ENGINE = 'InnoDB'";
97                 say $sql;
98                 if ( $doit ) {
99                     try {
100                         $dbh->do($sql) if $doit;
101                         $engine_altered = 1;
102                     } catch {
103                         say "Error: $_;";
104                     };
105                 }
106             }
107             my $sql = "ALTER TABLE $table_name ADD $constraint";
108             say $sql;
109             if ( $doit ) {
110                 try {
111                     $dbh->do($sql) if $doit;
112                 } catch {
113                     say "Error: $_";
114                 }
115             }
116         }
117         $line = <$fh> if $line =~ /CONSTRAINT/i;
118     }
119 }
120
121
122 usage() if $help;
123
124 fix_mysql_constraints($doit);
125
126 =head1 NAME
127
128 fix_mysql_constraints.pl
129
130 =head1 SYNOPSIS
131
132   fix_mysql_constraints.pl --help
133   fix_mysql_constraints.pl
134   fix_mysql_constraints.pl --doit
135
136 =head1 DESCRIPTION
137
138 See bug #8915
139
140 Alter tables to add missing constraints. Prior to altering tables, it may be
141 necessary to alter tables storage engine from MyISAM to InnoDB.
142
143 =over 8
144
145 =item B<--help>
146
147 Prints this help
148
149 =item B<--doit>
150
151 Alter tables effectively, otherwise just display the ALTER TABLE directives.
152
153 =item B<--alterengine>
154
155 Prior to add missing constraints, alter table engine to InnoDB.
156
157 =back
158
159 =cut