This commit was generated by cvs2svn to compensate for changes in r9232,
[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 #you should have run fs-migrate-part_svc ages ago, when you upgraded
65 #from 1.3 to 1.4... if not, it needs to be hooked into -upgrade here or
66 #you'll lose all the part_svc settings it migrates to part_svc_column
67
68 my @statements = dbdef->sql_update_schema( dbdef_dist(datasrc),
69                                            $dbh,
70                                            { 'nullify_default' => 1, },
71                                          );
72
73 @statements = 
74   grep { $_ !~ /^CREATE +INDEX +h_queue/i } #useless, holds up queue insertion
75        @statements;
76
77 unless ( driver_name =~ /^mysql/i ) {
78   #not necessary under non-mysql, takes forever on big db
79   @statements =
80     grep { $_ !~ /^ *ALTER +TABLE +h_queue +ALTER +COLUMN +job +TYPE +varchar\(512\) *$/i }
81          @statements;
82 }
83
84 if ( $DRY_RUN ) {
85   print
86     join(";\n", @bugfix, @statements ). ";\n";
87   exit;
88 } else {
89   foreach my $statement ( @bugfix, @statements ) {
90     warn "$statement\n";
91     $dbh->do( $statement )
92       or die "Error: ". $dbh->errstr. "\n executing: $statement";
93   }
94
95 #  warn "Pre-schema change upgrades completed in ". (time-$start). " seconds\n"; # if $DEBUG;
96 #  $start = time;
97
98 #  dbdef->update_schema( dbdef_dist(datasrc), $dbh );
99 }
100
101 warn "Schema upgrade completed in ". (time-$start). " seconds\n"; # if $DEBUG;
102 $start = time;
103
104 my $hashref = {};
105 $hashref->{dry_run} = 1 if $DRY_RUN;
106 $hashref->{debug} = 1 if $DEBUG && $DRY_RUN;
107 prune_applications($hashref) unless $opt_s;
108
109 warn "Application pruning completed in ". (time-$start). " seconds\n"; # if $DEBUG;
110 $start = time;
111
112 print "\n" if $DRY_RUN;
113
114 if ( $dbh->{Driver}->{Name} =~ /^mysql/i && ! $opt_s ) {
115
116   foreach my $table (qw( svc_acct svc_phone )) {
117
118     my $sth = $dbh->prepare(
119       "SELECT COUNT(*) FROM duplicate_lock WHERE lockname = '$table'"
120     ) or die $dbh->errstr;
121
122     $sth->execute or die $sth->errstr;
123
124     unless ( $sth->fetchrow_arrayref->[0] ) {
125
126       $sth = $dbh->prepare(
127         "INSERT INTO duplicate_lock ( lockname ) VALUES ( '$table' )"
128       ) or die $dbh->errstr;
129
130       $sth->execute or die $sth->errstr;
131
132     }
133
134   }
135
136   warn "Duplication lock creation completed in ". (time-$start). " seconds\n"; # if $DEBUG;
137   $start = time;
138
139 }
140
141 $dbh->commit or die $dbh->errstr;
142
143 dbdef_create($dbh, $dbdef_file);
144
145 $dbh->disconnect or die $dbh->errstr;
146
147 delete $FS::Schema::dbdef_cache{$dbdef_file}; #force an actual reload
148 $FS::UID::AutoCommit = 0;
149 $FS::UID::callback_hack = 1;
150 $dbh = adminsuidsetup($user);
151 $FS::UID::callback_hack = 0;
152 unless ( $DRY_RUN || $opt_s ) {
153   my $dir = "%%%FREESIDE_CONF%%%/conf.". datasrc;
154   if (!scalar(qsearch('conf', {}))) {
155     my $error = FS::Conf::init_config($dir);
156     if ($error) {
157       warn "CONFIGURATION UPGRADE FAILED\n";
158       $dbh->rollback or die $dbh->errstr;
159       die $error;
160     }
161   }
162 }
163 $dbh->commit or die $dbh->errstr;
164 $dbh->disconnect or die $dbh->errstr;
165
166 $dbh = adminsuidsetup($user);
167
168 warn "Re-initialization with updated schema completed in ". (time-$start). " seconds\n"; # if $DEBUG;
169 $start = time;
170
171 upgrade()
172   unless $DRY_RUN || $opt_s;
173
174 $dbh->commit or die $dbh->errstr;
175
176 warn "Table updates completed in ". (time-$start). " seconds\n"; # if $DEBUG;
177 $start = time;
178
179 upgrade_sqlradius()
180   unless $DRY_RUN || $opt_s || $opt_r;
181
182 warn "SQL RADIUS updates completed in ". (time-$start). " seconds\n"; # if $DEBUG;
183 $start = time;
184
185 $dbh->commit or die $dbh->errstr;
186 $dbh->disconnect or die $dbh->errstr;
187
188 warn "Final commit and disconnection completed in ". (time-$start). " seconds; upgrade done!\n"; # if $DEBUG;
189
190 ###
191
192 sub dbdef_create { # reverse engineer the schema from the DB and save to file
193   my( $dbh, $file ) = @_;
194   my $dbdef = new_native DBIx::DBSchema $dbh;
195   $dbdef->save($file);
196 }
197
198 sub usage {
199   die "Usage:\n  freeside-upgrade [ -d ] [ -r ] [ -s ] [ -q | -v ] user\n"; 
200 }
201
202 =head1 NAME
203
204 freeside-upgrade - Upgrades database schema for new freeside verisons.
205
206 =head1 SYNOPSIS
207
208   freeside-upgrade [ -d ] [ -r ] [ -s ] [ -q | -v ]
209
210 =head1 DESCRIPTION
211
212 Reads your existing database schema and updates it to match the current schema,
213 adding any columns or tables necessary.
214
215 Also performs other upgrade functions:
216
217 =over 4
218
219 =item Calls FS:: Misc::prune::prune_applications (probably unnecessary every upgrade, but simply won't find any records to change)
220
221 =item If necessary, moves your configuration information from the filesystem in /usr/local/etc/freeside/conf.<datasrc> to the database.
222
223 =back
224
225   [ -d ]: Dry run; output SQL statements (to STDOUT) only, but do not execute
226           them.
227
228   [ -q ]: Run quietly.  This may become the default at some point.
229
230   [ -r ]: Skip sqlradius updates.  Useful for occassions where the sqlradius
231           databases may be inaccessible.
232
233   [ -v ]: Run verbosely, sending debugging information to STDERR.  This is the
234           current default.
235
236   [ -s ]: Schema changes only.  Useful for Pg/slony slaves where the data
237           changes will be replicated from the Pg/slony master.
238
239 =head1 SEE ALSO
240
241 =cut
242