long WAS the road to 1.3.0...
[koha.git] / updater / updatedatabase
1 #!/usr/bin/perl
2
3 # $Id$
4
5 # Database Updater
6 # This script checks for required updates to the database.  
7
8 # Part of the Koha Library Software www.koha.org
9 # Licensed under the GPL.
10
11 # Bugs/ToDo: 
12 # - Would also be a good idea to offer to do a backup at this time...
13
14 # NOTE:  If you do something more than once in here, make it table driven.
15
16 use strict;
17
18 # CPAN modules
19 use DBI;
20
21 # Koha modules
22 use C4::Database;
23
24 my $debug=0;
25
26 my (
27         $sth, $sti,
28         $query,
29         %existingtables,        # tables already in database
30         %types,
31         $table,
32         $column,
33         $type, $null, $key, $default, $extra,
34         $prefitem,              # preference item in systempreferences table
35 );
36
37 #-------------------
38 # Defines
39
40 # Tables to add if they don't exist
41 my %requiretables=(
42     shelfcontents=>"( shelfnumber int not null, 
43         itemnumber int not null, 
44         flags int)",
45     bookshelf=>"( shelfnumber int auto_increment primary key, 
46         shelfname char(255))",
47     z3950queue=>"( id int auto_increment primary key, 
48         term text, 
49         type char(10), 
50         startdate int, 
51         enddate int, 
52         done smallint, 
53         results longblob, 
54         numrecords int, 
55         servers text, 
56         identifier char(30))",
57     z3950results=>"( id int auto_increment primary key, 
58         queryid int, 
59         server char(255), 
60         startdate int, 
61         enddate int, 
62         results longblob, 
63         numrecords int, 
64         numdownloaded int, 
65         highestseen int, 
66         active smallint)",
67     branchrelations=>"( branchcode varchar(4), 
68         categorycode varchar(4))",
69     websites=>"( websitenumber int(11) NOT NULL auto_increment,
70         biblionumber int(11) NOT NULL default '0',
71         title text,
72         description text,
73         url varchar(255),
74         PRIMARY KEY (websitenumber) )",
75     marcrecorddone=>"( isbn char(40),
76                       issn char(40),
77                       lccn char(40),
78                       controlnumber char(40))",
79     uploadedmarc=>"( id int(11) NOT NULL auto_increment PRIMARY KEY,
80                     marc longblob,
81                     hidden smallint(6) default NULL,
82                     name varchar(255) default NULL)",
83     ethnicity=>"( code varchar(10) NOT NULL default '',
84                 name varchar(255) default NULL,
85                 PRIMARY KEY  (code)   )",
86     sessions=>"( sessionID varchar(255) NOT NULL default '',
87                 userid varchar(255) default NULL,
88                 ip varchar(16) default NULL,
89                 lasttime int,
90                 PRIMARY KEY (sessionID)   )",
91     sessionqueries=>"( sessionID varchar(255) NOT NULL default '',
92                        userid char(100) NOT NULL default '',
93                        ip char(18) NOT NULL default '',
94                        url text NOT NULL default ''  )",
95     bibliothesaurus=> "( code BIGINT not null AUTO_INCREMENT, 
96                          freelib CHAR (255) not null , 
97                          stdlib CHAR (255) not null , 
98                          type CHAR (80) not null , 
99                          PRIMARY KEY (code), 
100                          INDEX (freelib),index(stdlib),index(type) )",
101     marc_biblio => "(
102                          bibid bigint(20) unsigned NOT NULL auto_increment,
103                          biblionumber int(11) NOT NULL default '0',
104                          datecreated date NOT NULL default '0000-00-00',
105                          datemodified date default NULL,
106                          origincode char(20) default NULL,
107                          PRIMARY KEY  (bibid),
108                          KEY origincode (origincode),
109                          KEY biblionumber (biblionumber)
110                          ) ",
111      marc_blob_subfield => "(
112                              blobidlink bigint(20) NOT NULL auto_increment,
113                              subfieldvalue longtext NOT NULL,
114                              PRIMARY KEY  (blobidlink)
115                             ) ",
116      marc_subfield_structure => "(
117                                   tagfield char(3) NOT NULL default '',
118                                   tagsubfield char(1) NOT NULL default '',
119                                   liblibrarian char(255) NOT NULL default '',
120                                   libopac char(255) NOT NULL default '',
121                                   repeatable tinyint(4) NOT NULL default '0',
122                                   mandatory tinyint(4) NOT NULL default '0',
123                                   kohafield char(40) NOT NULL default '',
124                                   PRIMARY KEY  (tagfield,tagsubfield),
125                                   KEY kohafield (kohafield)
126                                  )",
127      marc_subfield_table => "(
128                               subfieldid bigint(20) unsigned NOT NULL auto_increment,
129                               bibid bigint(20) unsigned NOT NULL default '0',
130                               tag char(3) NOT NULL default '',
131                               tagorder tinyint(4) NOT NULL default '1',
132                               tag_indicator char(2) NOT NULL default '',
133                               subfieldcode char(1) NOT NULL default '',
134                               subfieldorder tinyint(4) NOT NULL default '1',
135                               subfieldvalue varchar(255) default NULL,
136                               valuebloblink bigint(20) default NULL,
137                               PRIMARY KEY  (subfieldid),
138                               KEY bibid (bibid),
139                               KEY tag (tag),
140                               KEY tag_indicator (tag_indicator),
141                               KEY subfieldorder (subfieldorder),
142                               KEY subfieldcode (subfieldcode),
143                               KEY subfieldvalue (subfieldvalue),
144                               KEY tagorder (tagorder)
145                             )",
146      marc_tag_structure => "(
147                              tagfield char(3) NOT NULL default '',
148                              liblibrarian char(255) NOT NULL default '',
149                              libopac char(255) NOT NULL default '',
150                              repeatable tinyint(4) NOT NULL default '0',
151                              mandatory tinyint(4) NOT NULL default '0',
152                              PRIMARY KEY  (tagfield)
153                             )",
154      marc_word => "(
155                     bibid bigint(20) NOT NULL default '0',
156                     tag char(3) NOT NULL default '',
157                     tagorder tinyint(4) NOT NULL default '1',
158                     subfieldid char(1) NOT NULL default '',
159                     subfieldorder tinyint(4) NOT NULL default '1',
160                     word varchar(255) NOT NULL default '',
161                     sndx_word varchar(255) NOT NULL default '',
162                     KEY bibid (bibid),
163                     KEY tag (tag),
164                     KEY tagorder (tagorder),
165                     KEY subfieldid (subfieldid),
166                     KEY subfieldorder (subfieldorder),
167                     KEY word (word),
168                     KEY sndx_word (sndx_word)
169                    )",
170 );
171
172
173 my %requirefields=(
174     biblio=>{ 'abstract' => 'text' },
175     deletedbiblio=>{ 'abstract' => 'text' },
176     biblioitems=>{ 'lccn' => 'char(25)',
177                 'url' => 'varchar(255)',
178                 'marc' => 'text' },
179     deletedbiblioitems=>{ 'lccn' => 'char(25)',
180                 'url' => 'varchar(255)',
181                 'marc' => 'text' },
182     branchtransfers=>{ 'datearrived' => 'datetime' },
183     statistics=>{'borrowernumber' =>'int(11)'},
184     aqbooksellers=>{'invoicedisc' =>'float(6,4)',
185                      'nocalc' => 'int(11)'},
186     borrowers=>{'userid' => 'char(30)',
187                 'password' => 'char(30)',},
188     aqorders=>{'budgetdate' => 'date'},
189 #added so that reference items are not available for reserves...
190     itemtypes=>{'notforloan' => 'smallint(6)'},
191     systempreferences =>{'explanation' => 'char(80)'},
192 );
193
194 my %dropable_table=(
195                     classification   =>'classification',
196                     multipart        =>'multipart',
197                     multivolume      =>'multivolume',
198                     newitems         =>'newitems',
199                     procedures       =>'procedures',
200                     publisher        =>'publisher',
201                     searchstats      =>'searchstats',
202                     serialissues     =>'serialissues',
203                     );
204
205 # Default system preferences
206 my %defaultprefs=(
207                   'autoMemberNum'=> ['1','1 or else. If 1, Barcode is auto-calculated'],
208                   'acquisitions'=> ['simple','normal or simple : will use acquisition system found in directory acqui.simple or acquisition'],
209                   'template' => ['default','template default name']
210                   );
211
212 #-------------------
213 # Initialize
214 my $dbh=C4Connect;
215
216 # Start checking
217
218 # Get version of MySQL database engine.
219 my $mysqlversion=`mysqld --version`;
220 $mysqlversion=~/Ver (\S*) /;
221 $mysqlversion=$1;
222 if ($mysqlversion ge '3.23') {
223     print "Could convert to MyISAM database tables...\n";
224 }
225
226 #---------------------------------
227 # Tables
228
229 # Collect all tables into a list
230 $sth=$dbh->prepare("show tables");
231 $sth->execute;
232 while (my ($table) = $sth->fetchrow) {
233     $existingtables{$table}=1;
234 }
235
236 # Now add any missing tables
237 foreach $table ( keys %requiretables ) {
238     print "Checking $table table...\n" if $debug;
239     unless ($existingtables{$table} ) {
240         print "Adding $table table...\n";
241         my $sth=$dbh->prepare(
242                 "create table $table $requiretables{$table}" );
243         $sth->execute;
244         if ($sth->err) {
245                 print "Error : $sth->errstr \n";
246                 $sth->finish;
247         } # if error
248     } # unless exists
249 } # foreach
250
251 # now drop useless tables
252 foreach $table ( keys %dropable_table) {
253     print "Dropping unused tables...\n" if $debug;
254     if ($existingtables{$table} ) {
255         $dbh->do("drop table $table");
256         if ($dbh->err) {
257             print "Error : $dbh->errstr \n";
258         }
259     }
260 }
261 unless ($existingtables{'z3950servers'}) {
262     print "Adding z3950servers table...\n";
263     my $sti=$dbh->prepare("create table z3950servers (
264         host char(255), 
265         port int, 
266         db char(255), 
267         userid char(255), 
268         password char(255), 
269         name text, 
270         id int, 
271         checked smallint, 
272         rank int)");
273     $sti->execute;
274     $sti=$dbh->prepare("insert into z3950servers 
275         values ('z3950.loc.gov', 
276         7090, 
277         'voyager', 
278         '', '', 
279         'Library of Congress', 
280         1, 1, 1)");
281     $sti->execute;
282 }
283
284 #---------------------------------
285 # Columns
286
287 foreach $table ( keys %requirefields ) {
288     print "Check table $table\n" if $debug;
289     $sth=$dbh->prepare("show columns from $table");
290     $sth->execute();
291     undef %types;
292     while ( ($column, $type, $null, $key, $default, $extra) 
293                 = $sth->fetchrow) {
294         $types{$column}=$type;
295     } # while 
296     foreach $column ( keys %{ $requirefields{$table} } )  {
297         print "  Check column $column\n" if $debug;
298         if ( ! $types{$column} ) {
299             # column doesn't exist
300             print "Adding $column field to $table table...\n";
301             $query="alter table $table
302                 add column $column " . $requirefields{$table}->{$column} ;
303             print "Execute: $query\n" if $debug;
304             my $sti=$dbh->prepare($query);
305             $sti->execute;
306             if ($sti->err) {
307                     print "**Error : $sti->errstr \n";
308                     $sti->finish;
309             } # if error
310         } # if column
311     } # foreach column
312 } # foreach table
313
314 # Get list of columns from items table
315 my %itemtypes;
316
317 my $sth=$dbh->prepare("show columns from items");
318 $sth->execute;
319 while (my ($column, $type, $null, $key, $default, $extra) = $sth->fetchrow) {
320     $itemtypes{$column}=$type;
321 }
322
323 unless ($itemtypes{'barcode'} eq 'varchar(20)') {
324     $itemtypes{'barcode'}=~/varchar\((\d+)\)/;
325     my $oldlength=$1;
326     if ($oldlength<20) {
327         print "Setting maximum barcode length to 20 (was $oldlength).\n";
328         my $sti=$dbh->prepare("alter table items change barcode barcode varchar(20) not null");
329         $sti->execute;
330     }
331 }
332
333 # extending the timestamp in branchtransfers...
334 my %branchtransfers;
335
336 my $sth=$dbh->prepare("show columns from branchtransfers");
337 $sth->execute;
338 while (my ($column, $type, $null, $key, $default, $extra) = $sth->fetchrow) {
339     $branchtransfers{$column}=$type;
340 }
341
342 unless ($branchtransfers{'datesent'} eq 'datetime') {
343     print "Setting type of datesent in branchtransfers to datetime.\n";
344     my $sti=$dbh->prepare("alter table branchtransfers change datesent datesent datetime");
345     $sti->execute;
346 }
347
348 unless ($branchtransfers{'datearrived'} eq 'datetime') {
349     print "Setting type of datearrived in branchtransfers to datetime.\n";
350     my $sti=$dbh->prepare("alter table branchtransfers change datearrived datearrived datetime");
351     $sti->execute;
352 }
353
354 # changing the branchcategories table around...
355 my %branchcategories;
356
357 my $sth=$dbh->prepare("show columns from branchcategories");
358 $sth->execute;
359 while (my ($column, $type, $null, $key, $default, $extra) = $sth->fetchrow) {
360     $branchcategories{$column}=$type;
361 }
362
363 unless ($branchcategories{'categorycode'} eq 'varchar(4)') {
364     print "Setting type of categorycode in branchcategories to varchar(4),\n and making the primary key.\n";
365     my $sti=$dbh->prepare("alter table branchcategories change categorycode categorycode varchar(4) not null");
366     $sti->execute;
367     $sti=$dbh->prepare("alter table branchcategories add primary key (categorycode)");
368     $sti->execute;
369 }
370
371 unless ($branchcategories{'categoryname'} eq 'text') {
372     print "Changing branchcode in branchcategories to categoryname text.\n";
373     my $sth=$dbh->prepare("alter table branchcategories change branchcode categoryname text");
374     $sth->execute;
375 }
376
377 unless ($branchcategories{'codedescription'} eq 'text') {
378     print "Replacing branchholding in branchcategories with codedescription text.\n";
379     my $sth=$dbh->prepare("alter table branchcategories change branchholding codedescription text");
380     $sth->execute;
381 }
382
383
384 # Populate systempreferences if it is empty
385
386 foreach $prefitem ( keys %defaultprefs ) {
387     $sth=$dbh->prepare("select value 
388         from systempreferences 
389         where variable=?");
390     $sth->execute($prefitem);
391     unless ($sth->rows) {
392         print "Adding system preference item $prefitem with value " .
393                 $defaultprefs{$prefitem}[0] ."\n";
394         $sti=$dbh->prepare("
395           insert into systempreferences (variable, value,explanation) 
396           values (?,?,?)");
397         $sti->execute($prefitem,$defaultprefs{$prefitem}[0],$defaultprefs{$prefitem}[1]);
398     } # unless
399 } # foreach
400
401
402 $sth->finish;
403 $dbh->disconnect;
404
405 exit;
406
407 # $Log$
408 # Revision 1.18  2002/09/24 13:50:55  tipaul
409 # long WAS the road to 1.3.0...
410 # coming VERY SOON NOW...
411 # modifying installer and buildrelease to update the DB
412 #
413 # Revision 1.17  2002/09/24 12:57:35  tipaul
414 # long WAS the road to 1.3.0...
415 # coming VERY SOON NOW...
416 # modifying installer and buildrelease to update the DB
417 #
418 # Revision 1.16  2002/07/31 02:34:27  finlayt
419 #
420 # added "notforloan" field to the itemtypes table.
421 #
422 # Revision 1.15  2002/07/20 22:30:06  rangi
423 # Making sure fix makes it into the main branch as well
424 # Fix for bug 69
425 #
426 # Revision 1.14  2002/07/08 16:20:26  tonnesen
427 # Added sessionqueries table and password/userid fields to borrowers table
428 #
429 # Revision 1.13  2002/07/04 18:05:36  tonnesen
430 # bug fix
431 #
432 # Revision 1.12  2002/07/04 16:41:06  tonnesen
433 # Merged changes from rel-1-2.  Abstracted table structure changes by alan.
434 #