6 # This script checks for required updates to the database.
8 # Part of the Koha Library Software www.koha.org
9 # Licensed under the GPL.
12 # - Would also be a good idea to offer to do a backup at this time...
14 # NOTE: If you do something more than once in here, make it table driven.
23 # FIXME - The user might be installing a new database, so can't rely
24 # on /etc/koha.conf anyway.
31 %existingtables, # tables already in database
35 $type, $null, $key, $default, $extra,
36 $prefitem, # preference item in systempreferences table
43 my $dbh = C4::Context->dbh;
44 print "connected to your DB. Checking & modifying it\n" unless $silent;
49 # Tables to add if they don't exist
51 categorytable => "(categorycode char(5) NOT NULL default '',
52 description text default '',
53 itemtypecodes text default '',
54 PRIMARY KEY (categorycode)
56 subcategorytable => "(subcategorycode char(5) NOT NULL default '',
57 description text default '',
58 itemtypecodes text default '',
59 PRIMARY KEY (subcategorycode)
61 mediatypetable => "(mediatypecode char(5) NOT NULL default '',
62 description text default '',
63 itemtypecodes text default '',
64 PRIMARY KEY (mediatypecode)
67 `timestamp` TIMESTAMP NOT NULL ,
68 `user` INT( 11 ) NOT NULL ,
69 `module` TEXT default '',
70 `action` TEXT default '' ,
71 `object` INT(11) default '' ,
72 `info` TEXT default '' ,
73 PRIMARY KEY ( `timestamp` , `user` )
76 module varchar(20) NOT NULL default '',
77 code varchar(20) NOT NULL default '',
78 name varchar(100) NOT NULL default '',
79 title varchar(200) NOT NULL default '',
81 PRIMARY KEY (module,code)
84 alertid int(11) NOT NULL auto_increment,
85 borrowernumber int(11) NOT NULL default '0',
86 type varchar(10) NOT NULL default '',
87 externalid varchar(20) NOT NULL default '',
88 PRIMARY KEY (alertid),
89 KEY borrowernumber (borrowernumber),
90 KEY type (type,externalid)
96 subscription => { 'letter' => 'char(20) NULL'},
97 # tablename => { 'field' => 'fieldtype' },
100 my %dropable_table = (
101 # tablename => 'tablename',
104 my %uselessfields = (
105 # tablename => "field1,field2",
107 # the other hash contains other actions that can't be done elsewhere. they are done
108 # either BEFORE of AFTER everything else, depending on "when" entry (default => AFTER)
110 # The tabledata hash contains data that should be in the tables.
111 # The uniquefieldrequired hash entry is used to determine which (if any) fields
112 # must not exist in the table for this row to be inserted. If the
113 # uniquefieldrequired entry is already in the table, the existing data is not
114 # modified, unless the forceupdate hash entry is also set. Fields in the
115 # anonymous "forceupdate" hash will be forced to be updated to the default
116 # values given in the %tabledata hash.
120 # { uniquefielrequired => 'fieldname', # the primary key in the table
121 # fieldname => fieldvalue,
122 # fieldname2 => fieldvalue2,
125 systempreferences => [
127 uniquefieldrequired => 'variable',
128 variable => 'Activate_Log',
130 forceupdate => { 'explanation' => 1,
132 explanation => 'Turn Log Actions on DB On an Off',
136 uniquefieldrequired => 'variable',
137 variable => 'IndependantBranches',
139 forceupdate => { 'explanation' => 1,
141 explanation => 'Turn Branch independancy management On an Off',
145 uniquefieldrequired => 'variable',
146 variable => 'ReturnBeforeExpiry',
148 forceupdate => { 'explanation' => 1,
150 explanation => 'If Yes, Returndate on issuing can\'t be after borrower card expiry',
157 my %fielddefinitions = (
159 # { field => 'fieldname',
160 # type => 'fieldtype',
173 # Get version of MySQL database engine.
174 my $mysqlversion = `mysqld --version`;
175 $mysqlversion =~ /Ver (\S*) /;
177 if ( $mysqlversion ge '3.23' ) {
178 print "Could convert to MyISAM database tables...\n" unless $silent;
181 #---------------------------------
184 # Collect all tables into a list
185 $sth = $dbh->prepare("show tables");
187 while ( my ($table) = $sth->fetchrow ) {
188 $existingtables{$table} = 1;
192 # Now add any missing tables
193 foreach $table ( keys %requiretables ) {
194 unless ( $existingtables{$table} ) {
195 print "Adding $table table...\n" unless $silent;
196 my $sth = $dbh->prepare("create table $table $requiretables{$table}");
199 print "Error : $sth->errstr \n";
205 # now drop useless tables
206 foreach $table ( keys %dropable_table ) {
207 if ( $existingtables{$table} ) {
208 print "Dropping unused table $table\n" if $debug and not $silent;
209 $dbh->do("drop table $table");
211 print "Error : $dbh->errstr \n";
216 #---------------------------------
219 foreach $table ( keys %requirefields ) {
220 print "Check table $table\n" if $debug and not $silent;
221 $sth = $dbh->prepare("show columns from $table");
224 while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
226 $types{$column} = $type;
228 foreach $column ( keys %{ $requirefields{$table} } ) {
229 print " Check column $column [$types{$column}]\n" if $debug and not $silent;
230 if ( !$types{$column} ) {
232 # column doesn't exist
233 print "Adding $column field to $table table...\n" unless $silent;
234 $query = "alter table $table
235 add column $column " . $requirefields{$table}->{$column};
236 print "Execute: $query\n" if $debug;
237 my $sti = $dbh->prepare($query);
240 print "**Error : $sti->errstr \n";
247 foreach $table ( keys %fielddefinitions ) {
248 print "Check table $table\n" if $debug;
249 $sth = $dbh->prepare("show columns from $table");
252 while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
254 $definitions->{$column}->{type} = $type;
255 $definitions->{$column}->{null} = $null;
256 $definitions->{$column}->{key} = $key;
257 $definitions->{$column}->{default} = $default;
258 $definitions->{$column}->{extra} = $extra;
260 my $fieldrow = $fielddefinitions{$table};
261 foreach my $row (@$fieldrow) {
262 my $field = $row->{field};
263 my $type = $row->{type};
264 my $null = $row->{null};
265 my $key = $row->{key};
266 my $default = $row->{default};
267 $default="''" unless $default;
268 my $extra = $row->{extra};
269 my $def = $definitions->{$field};
270 unless ( $type eq $def->{type}
271 && $null eq $def->{null}
272 && $key eq $def->{key}
273 && $default eq $def->{default}
274 && $extra eq $def->{extra} )
280 if ( $key eq 'PRI' ) {
281 $key = 'PRIMARY KEY';
283 unless ( $extra eq 'auto_increment' ) {
286 # if it's a new column use "add", if it's an old one, use "change".
288 if ($definitions->{$field}->{type}) {
289 $action="change $field"
293 # if it's a primary key, drop the previous pk, before altering the table
295 if ($key ne 'PRIMARY KEY') {
296 $sth =$dbh->prepare("alter table $table $action $field $type $null $key $extra default ?");
298 $sth =$dbh->prepare("alter table $table drop primary key, $action $field $type $null $key $extra default ?");
300 $sth->execute($default);
301 print " Alter $field in $table\n" unless $silent;
307 # Populate tables with required data
308 foreach my $table ( keys %tabledata ) {
309 print "Checking for data required in table $table...\n" unless $silent;
310 my $tablerows = $tabledata{$table};
311 foreach my $row (@$tablerows) {
312 my $uniquefieldrequired = $row->{uniquefieldrequired};
313 my $uniquevalue = $row->{$uniquefieldrequired};
314 my $forceupdate = $row->{forceupdate};
317 "select $uniquefieldrequired from $table where $uniquefieldrequired=?"
319 $sth->execute($uniquevalue);
321 foreach my $field (keys %$forceupdate) {
322 if ($forceupdate->{$field}) {
323 my $sth=$dbh->prepare("update systempreferences set $field=? where $uniquefieldrequired=?");
324 $sth->execute($row->{$field}, $uniquevalue);
328 print "Adding row to $table: " unless $silent;
332 foreach my $field ( keys %$row ) {
333 next if $field eq 'uniquefieldrequired';
334 next if $field eq 'forceupdate';
335 my $value = $row->{$field};
336 push @values, $value;
337 print " $field => $value" unless $silent;
338 $fieldlist .= "$field,";
339 $placeholders .= "?,";
341 print "\n" unless $silent;
342 $fieldlist =~ s/,$//;
343 $placeholders =~ s/,$//;
346 "insert into $table ($fieldlist) values ($placeholders)");
347 $sth->execute(@values);
352 # at last, remove useless fields
353 foreach $table ( keys %uselessfields ) {
354 my @fields = split /,/,$uselessfields{$table};
357 foreach my $fieldtodrop (@fields) {
358 $fieldtodrop =~ s/\t//g;
359 $fieldtodrop =~ s/\n//g;
361 $sth = $dbh->prepare("show columns from $table");
363 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
365 $exists =1 if ($column eq $fieldtodrop);
368 print "deleting $fieldtodrop field in $table...\n" unless $silent;
369 my $sth = $dbh->prepare("alter table $table drop $fieldtodrop");
381 # Revision 1.119 2005/08/04 16:07:58 tipaul
382 # Synch really broke this script...
384 # Revision 1.118 2005/08/04 16:02:55 tipaul
385 # oops... error in synch between 2.2 and head
387 # Revision 1.117 2005/08/04 14:24:39 tipaul
388 # synch'ing 2.2 and head
390 # Revision 1.116 2005/08/04 08:55:54 tipaul
391 # Letters / alert system, continuing...
393 # * adding a package Letters.pm, that manages Letters & alerts.
394 # * adding feature : it's now possible to define a "letter" for any subscription created. If a letter is defined, users in OPAC can put an alert on the subscription. When an issue is marked "arrived", all users in the alert will recieve a mail (as defined in the "letter"). This last part (= send the mail) is not yet developped. (Should be done this week)
395 # * adding feature : it's now possible to "put to an alert" in OPAC, for any serial subscription. The alert is stored in a new table, called alert. An alert can be put only if the librarian has activated them in subscription (and they activate it just by choosing a "letter" to sent to borrowers on new issues)
396 # * adding feature : librarian can see in borrower detail which alerts they have put, and a user can see in opac-detail which alert they have put too.
398 # Note that the system should be generic enough to manage any type of alert.
399 # I plan to extend it soon to virtual shelves : a borrower will be able to put an alert on a virtual shelf, to be warned when something is changed in the virtual shelf (mail being sent once a day by cron, or manually by the shelf owner. Anyway, a mail won't be sent on every change, users would be spammed by Koha ;-) )
401 # Revision 1.115 2005/08/02 16:15:34 tipaul
402 # adding 2 fields to letter system :
403 # * module (acquisition, catalogue...) : it will be usefull to show the librarian only letters he may be interested by.
404 # * title, that will be used as mail subject.
406 # Revision 1.114 2005/07/28 15:10:13 tipaul
407 # Introducing new "Letters" system : Letters will be used everytime you want to sent something to someone (through mail or paper). For example, sending a mail for overdues use letter that you can put as parameters. Sending a mail to a borrower when a suggestion is validated uses a letter too.
408 # the letter table contains 3 fields :
409 # * code => the code of the letter
410 # * name => the complete name of the letter
411 # * content => the complete text. It's a TEXT field type, so has no limits.
413 # My next goal now is to work on point 2-I "serial issue alert"
414 # With this feature, in serials, a user can subscribe the "issue alert". For every issue arrived/missing, a mail is sent to all subscribers of this list. The mail warns the user that the issue is arrive or missing. Will be in head.
415 # (see mail on koha-devel, 2005/04/07)
417 # The "serial issue alert" will be the 1st to use this letter system that probably needs some tweaking ;-)
419 # Once it will be stabilised default letters (in any languages) could be added during installer to help the library begin with this new feature.
421 # Revision 1.113 2005/07/28 08:38:41 tipaul
422 # For instance, the return date does not rely on the borrower expiration date. A systempref will be added in Koha, to modify return date calculation schema :
423 # * ReturnBeforeExpiry = yes => return date can't be after expiry date
424 # * ReturnBeforeExpiry = no => return date can be after expiry date
426 # Revision 1.112 2005/07/26 08:19:47 hdl
427 # Adding IndependantBranches System preference variable in order to manage Branch independancy.
429 # Revision 1.111 2005/07/25 15:35:38 tipaul
430 # we have decided that moving to Koha 3.0 requires being already in Koha 2.2.x
431 # So, the updatedatabase script can highly be cleaned (90% removed).
432 # Let's play with the new Koha DB structure now ;-)