mysql compat: cgp_rule_condition s/condition/conditionname/
[freeside.git] / FS / bin / freeside-upgrade
1 #!/usr/bin/perl -w
2
3 use strict;
4 use vars qw($opt_d $opt_s $opt_q $opt_v $opt_r);
5 use vars qw($DEBUG $DRY_RUN);
6 use Getopt::Std;
7 use DBIx::DBSchema 0.31; #0.39
8 use FS::UID qw(adminsuidsetup checkeuid datasrc driver_name);  #getsecrets);
9 use FS::CurrentUser;
10 use FS::Schema qw( dbdef dbdef_dist reload_dbdef );
11 use FS::Misc::prune qw(prune_applications);
12 use FS::Conf;
13 use FS::Record qw(qsearch);
14 use FS::Upgrade qw(upgrade upgrade_sqlradius);
15
16 my $start = time;
17
18 die "Not running uid freeside!" unless checkeuid();
19
20 getopts("dqrs");
21
22 $DEBUG = !$opt_q;
23 #$DEBUG = $opt_v;
24
25 $DRY_RUN = $opt_d;
26
27 my $user = shift or die &usage;
28 $FS::CurrentUser::upgrade_hack = 1;
29 $FS::UID::callback_hack = 1;
30 my $dbh = adminsuidsetup($user);
31 $FS::UID::callback_hack = 0;
32
33 if ( driver_name =~ /^mysql/i ) { #until 0.39 is required above
34   eval "use DBIx::DBSchema 0.39;";
35   die $@ if $@;
36 }
37
38 #needs to match FS::Schema...
39 my $dbdef_file = "%%%FREESIDE_CONF%%%/dbdef.". datasrc;
40
41 dbdef_create($dbh, $dbdef_file);
42
43 delete $FS::Schema::dbdef_cache{$dbdef_file}; #force an actual reload
44 reload_dbdef($dbdef_file);
45
46 warn "Upgrade startup completed in ". (time-$start). " seconds\n"; # if $DEBUG;
47 $start = time;
48
49 #$DBIx::DBSchema::DEBUG = $DEBUG;
50 #$DBIx::DBSchema::Table::DEBUG = $DEBUG;
51 #$DBIx::DBSchema::Index::DEBUG = $DEBUG;
52
53 my @bugfix = ();
54
55 if (dbdef->table('cust_main')->column('agent_custid') && ! $opt_s) { 
56   push @bugfix,
57     "UPDATE cust_main SET agent_custid = NULL where agent_custid = ''";
58
59   push @bugfix,
60     "UPDATE h_cust_main SET agent_custid = NULL where agent_custid = ''"
61       if (dbdef->table('h_cust_main')); 
62 }
63
64 if ( dbdef->table('cgp_rule_condition') &&
65      dbdef->table('cgp_rule_condition')->column('condition') 
66    )
67 {
68   push @bugfix,
69    "ALTER TABLE ${_}cgp_rule_condition RENAME COLUMN condition TO conditionname"
70       for '', 'h_';
71
72 }
73
74 if ( $DRY_RUN ) {
75   print
76     join(";\n", @bugfix ). ";\n";
77 } elsif ( @bugfix ) {
78
79   foreach my $statement ( @bugfix ) {
80     warn "$statement\n";
81     $dbh->do( $statement )
82       or die "Error: ". $dbh->errstr. "\n executing: $statement";
83   }
84
85   dbdef_create($dbh, $dbdef_file);
86   delete $FS::Schema::dbdef_cache{$dbdef_file}; #force an actual reload
87   reload_dbdef($dbdef_file);
88
89 }
90
91 #you should have run fs-migrate-part_svc ages ago, when you upgraded
92 #from 1.3 to 1.4... if not, it needs to be hooked into -upgrade here or
93 #you'll lose all the part_svc settings it migrates to part_svc_column
94
95 my @statements = dbdef->sql_update_schema( dbdef_dist(datasrc),
96                                            $dbh,
97                                            { 'nullify_default' => 1, },
98                                          );
99
100 @statements = 
101   grep { $_ !~ /^CREATE +INDEX +h_queue/i } #useless, holds up queue insertion
102        @statements;
103
104 unless ( driver_name =~ /^mysql/i ) {
105   #not necessary under non-mysql, takes forever on big db
106   @statements =
107     grep { $_ !~ /^ *ALTER +TABLE +h_queue +ALTER +COLUMN +job +TYPE +varchar\(512\) *$/i }
108          @statements;
109 }
110
111 if ( $DRY_RUN ) {
112   print
113     join(";\n", @statements ). ";\n";
114   exit;
115 } else {
116   foreach my $statement ( @statements ) {
117     warn "$statement\n";
118     $dbh->do( $statement )
119       or die "Error: ". $dbh->errstr. "\n executing: $statement";
120   }
121
122 #  warn "Pre-schema change upgrades completed in ". (time-$start). " seconds\n"; # if $DEBUG;
123 #  $start = time;
124
125 #  dbdef->update_schema( dbdef_dist(datasrc), $dbh );
126 }
127
128 warn "Schema upgrade completed in ". (time-$start). " seconds\n"; # if $DEBUG;
129 $start = time;
130
131 my $hashref = {};
132 $hashref->{dry_run} = 1 if $DRY_RUN;
133 $hashref->{debug} = 1 if $DEBUG && $DRY_RUN;
134 prune_applications($hashref) unless $opt_s;
135
136 warn "Application pruning completed in ". (time-$start). " seconds\n"; # if $DEBUG;
137 $start = time;
138
139 print "\n" if $DRY_RUN;
140
141 if ( $dbh->{Driver}->{Name} =~ /^mysql/i && ! $opt_s ) {
142
143   foreach my $table (qw( svc_acct svc_phone )) {
144
145     my $sth = $dbh->prepare(
146       "SELECT COUNT(*) FROM duplicate_lock WHERE lockname = '$table'"
147     ) or die $dbh->errstr;
148
149     $sth->execute or die $sth->errstr;
150
151     unless ( $sth->fetchrow_arrayref->[0] ) {
152
153       $sth = $dbh->prepare(
154         "INSERT INTO duplicate_lock ( lockname ) VALUES ( '$table' )"
155       ) or die $dbh->errstr;
156
157       $sth->execute or die $sth->errstr;
158
159     }
160
161   }
162
163   warn "Duplication lock creation completed in ". (time-$start). " seconds\n"; # if $DEBUG;
164   $start = time;
165
166 }
167
168 $dbh->commit or die $dbh->errstr;
169
170 dbdef_create($dbh, $dbdef_file);
171
172 $dbh->disconnect or die $dbh->errstr;
173
174 delete $FS::Schema::dbdef_cache{$dbdef_file}; #force an actual reload
175 $FS::UID::AutoCommit = 0;
176 $FS::UID::callback_hack = 1;
177 $dbh = adminsuidsetup($user);
178 $FS::UID::callback_hack = 0;
179 unless ( $DRY_RUN || $opt_s ) {
180   my $dir = "%%%FREESIDE_CONF%%%/conf.". datasrc;
181   if (!scalar(qsearch('conf', {}))) {
182     my $error = FS::Conf::init_config($dir);
183     if ($error) {
184       warn "CONFIGURATION UPGRADE FAILED\n";
185       $dbh->rollback or die $dbh->errstr;
186       die $error;
187     }
188   }
189 }
190 $dbh->commit or die $dbh->errstr;
191 $dbh->disconnect or die $dbh->errstr;
192
193 $FS::UID::AutoCommit = 1;
194
195 $dbh = adminsuidsetup($user);
196
197 warn "Re-initialization with updated schema completed in ". (time-$start). " seconds\n"; # if $DEBUG;
198 $start = time;
199
200 upgrade()
201   unless $DRY_RUN || $opt_s;
202
203 $dbh->commit or die $dbh->errstr;
204
205 warn "Table updates completed in ". (time-$start). " seconds\n"; # if $DEBUG;
206 $start = time;
207
208 upgrade_sqlradius()
209   unless $DRY_RUN || $opt_s || $opt_r;
210
211 warn "SQL RADIUS updates completed in ". (time-$start). " seconds\n"; # if $DEBUG;
212 $start = time;
213
214 $dbh->commit or die $dbh->errstr;
215 $dbh->disconnect or die $dbh->errstr;
216
217 warn "Final commit and disconnection completed in ". (time-$start). " seconds; upgrade done!\n"; # if $DEBUG;
218
219 ###
220
221 sub dbdef_create { # reverse engineer the schema from the DB and save to file
222   my( $dbh, $file ) = @_;
223   my $dbdef = new_native DBIx::DBSchema $dbh;
224   $dbdef->save($file);
225 }
226
227 sub usage {
228   die "Usage:\n  freeside-upgrade [ -d ] [ -r ] [ -s ] [ -q | -v ] user\n"; 
229 }
230
231 =head1 NAME
232
233 freeside-upgrade - Upgrades database schema for new freeside verisons.
234
235 =head1 SYNOPSIS
236
237   freeside-upgrade [ -d ] [ -r ] [ -s ] [ -q | -v ]
238
239 =head1 DESCRIPTION
240
241 Reads your existing database schema and updates it to match the current schema,
242 adding any columns or tables necessary.
243
244 Also performs other upgrade functions:
245
246 =over 4
247
248 =item Calls FS:: Misc::prune::prune_applications (probably unnecessary every upgrade, but simply won't find any records to change)
249
250 =item If necessary, moves your configuration information from the filesystem in /usr/local/etc/freeside/conf.<datasrc> to the database.
251
252 =back
253
254   [ -d ]: Dry run; output SQL statements (to STDOUT) only, but do not execute
255           them.
256
257   [ -q ]: Run quietly.  This may become the default at some point.
258
259   [ -r ]: Skip sqlradius updates.  Useful for occassions where the sqlradius
260           databases may be inaccessible.
261
262   [ -v ]: Run verbosely, sending debugging information to STDERR.  This is the
263           current default.
264
265   [ -s ]: Schema changes only.  Useful for Pg/slony slaves where the data
266           changes will be replicated from the Pg/slony master.
267
268 =head1 SEE ALSO
269
270 =cut
271