*** empty log message ***
[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::Context;
23
24 # FIXME - The user might be installing a new database, so can't rely
25 # on /etc/koha.conf anyway.
26
27 my $debug = 0;
28
29 my (
30     $sth, $sti,
31     $query,
32     %existingtables,    # tables already in database
33     %types,
34     $table,
35     $column,
36     $type, $null, $key, $default, $extra,
37     $prefitem,          # preference item in systempreferences table
38 );
39
40 my $dbh = C4::Context->dbh;
41 print "connected to your DB. Checking & modifying it\n";
42
43 #-------------------
44 # Defines
45
46 # Tables to add if they don't exist
47 my %requiretables = (
48     shelfcontents => "( shelfnumber int not null,
49                                                         itemnumber int not null,
50                                                         flags int)",
51     bookshelf => "( shelfnumber int auto_increment primary key,
52                                                 shelfname char(255))",
53     z3950queue => "( id int auto_increment primary key,
54                                                 term text,
55                                                 type char(10),
56                                                 startdate int,
57                                                 enddate int,
58                                                 done smallint,
59                                                 results longblob,
60                                                 numrecords int,
61                                                 servers text,
62                                                 identifier char(30))",
63     z3950results => "( id int auto_increment primary key,
64                                                 queryid int,
65                                                 server char(255),
66                                                 startdate int,
67                                                 enddate int,
68                                                 results longblob,
69                                                 numrecords int,
70                                                 numdownloaded int,
71                                                 highestseen int,
72                                                 active smallint)",
73     branchrelations => "( branchcode varchar(4),
74                                                         categorycode varchar(4))",
75     websites => "( websitenumber int(11) NOT NULL auto_increment,
76                                                 biblionumber int(11) NOT NULL default '0',
77                                                 title text,
78                                                 description text,
79                                                 url varchar(255),
80                                                 PRIMARY KEY (websitenumber) )",
81     marcrecorddone => "( isbn char(40),
82                                                                 issn char(40),
83                                                                 lccn char(40),
84                                                                 controlnumber char(40))",
85     uploadedmarc => "( id int(11) NOT NULL auto_increment PRIMARY KEY,
86                                                         marc longblob,
87                                                         hidden smallint(6) default NULL,
88                                                         name varchar(255) default NULL)",
89     ethnicity => "( code varchar(10) NOT NULL default '',
90                                         name varchar(255) default NULL,
91                                         PRIMARY KEY  (code)   )",
92     sessions => "( sessionID varchar(255) NOT NULL default '',
93                                                 userid varchar(255) default NULL,
94                                                 ip varchar(16) default NULL,
95                                                 lasttime int,
96                                                 PRIMARY KEY (sessionID)   )",
97     sessionqueries => "( sessionID varchar(255) NOT NULL default '',
98                                                                 userid char(100) NOT NULL default '',
99                                                                 ip char(18) NOT NULL default '',
100                                                                 url text NOT NULL default ''  )",
101     bibliothesaurus => "( id bigint(20) NOT NULL auto_increment,
102                                                         freelib char(255) NOT NULL default '',
103                                                         stdlib char(255) NOT NULL default '',
104                                                         category char(10) NOT NULL default '',
105                                                         level tinyint(4) NOT NULL default '1',
106                                                         hierarchy char(80) NOT NULL default '',
107                                                         father char(80) NOT NULL default '',
108                                                         PRIMARY KEY  (id),
109                                                         KEY freelib (freelib),
110                                                         KEY stdlib (stdlib),
111                                                         KEY category (category),
112                                                         KEY hierarchy (hierarchy)
113                                                         )",
114     marc_biblio => "(
115                                                 bibid bigint(20) unsigned NOT NULL auto_increment,
116                                                 biblionumber int(11) NOT NULL default '0',
117                                                 datecreated date NOT NULL default '0000-00-00',
118                                                 datemodified date default NULL,
119                                                 origincode char(20) default NULL,
120                                                 PRIMARY KEY  (bibid),
121                                                 KEY origincode (origincode),
122                                                 KEY biblionumber (biblionumber)
123                                                 ) ",
124     marc_blob_subfield => "(
125                                         blobidlink bigint(20) NOT NULL auto_increment,
126                                         subfieldvalue longtext NOT NULL,
127                                         PRIMARY KEY  (blobidlink)
128                                         ) ",
129     marc_subfield_structure => "(
130                                                 tagfield char(3) NOT NULL default '',
131                                                 tagsubfield char(1) NOT NULL default '',
132                                                 liblibrarian char(255) NOT NULL default '',
133                                                 libopac char(255) NOT NULL default '',
134                                                 repeatable tinyint(4) NOT NULL default '0',
135                                                 mandatory tinyint(4) NOT NULL default '0',
136                                                 kohafield char(40)  default NULL,
137                                                 tab tinyint(1) default NULL,
138                                                 authorised_value char(10) default NULL,
139                                                 thesaurus_category char(10) default NULL,
140                                                 value_builder char(80) default NULL,
141                                                 PRIMARY KEY  (tagfield,tagsubfield),
142                                                 KEY kohafield (kohafield),
143                                                 KEY tab (tab)
144                                                 )",
145     marc_subfield_table => "(
146                                                 subfieldid bigint(20) unsigned NOT NULL auto_increment,
147                                                 bibid bigint(20) unsigned NOT NULL default '0',
148                                                 tag char(3) NOT NULL default '',
149                                                 tagorder tinyint(4) NOT NULL default '1',
150                                                 tag_indicator char(2) NOT NULL default '',
151                                                 subfieldcode char(1) NOT NULL default '',
152                                                 subfieldorder tinyint(4) NOT NULL default '1',
153                                                 subfieldvalue varchar(255) default NULL,
154                                                 valuebloblink bigint(20) default NULL,
155                                                 PRIMARY KEY  (subfieldid),
156                                                 KEY bibid (bibid),
157                                                 KEY tag (tag),
158                                                 KEY tag_indicator (tag_indicator),
159                                                 KEY subfieldorder (subfieldorder),
160                                                 KEY subfieldcode (subfieldcode),
161                                                 KEY subfieldvalue (subfieldvalue),
162                                                 KEY tagorder (tagorder)
163                                         )",
164     marc_tag_structure => "(
165                                         tagfield char(3) NOT NULL default '',
166                                         liblibrarian char(255) NOT NULL default '',
167                                         libopac char(255) NOT NULL default '',
168                                         repeatable tinyint(4) NOT NULL default '0',
169                                         mandatory tinyint(4) NOT NULL default '0',
170                                         authorised_value char(10) default NULL,
171                                         PRIMARY KEY  (tagfield)
172                                         )",
173     marc_word => "(
174                                 bibid bigint(20) NOT NULL default '0',
175                                 tag char(3) NOT NULL default '',
176                                 tagorder tinyint(4) NOT NULL default '1',
177                                 subfieldid char(1) NOT NULL default '',
178                                 subfieldorder tinyint(4) NOT NULL default '1',
179                                 word varchar(255) NOT NULL default '',
180                                 sndx_word varchar(255) NOT NULL default '',
181                                 KEY bibid (bibid),
182                                 KEY tag (tag),
183                                 KEY tagorder (tagorder),
184                                 KEY subfieldid (subfieldid),
185                                 KEY subfieldorder (subfieldorder),
186                                 KEY word (word),
187                                 KEY sndx_word (sndx_word)
188                         )",
189     marc_breeding => "(  id bigint(20) NOT NULL auto_increment,
190                                 file varchar(80) NOT NULL default '',
191                                 isbn varchar(10) NOT NULL default '',
192                                 title varchar(128) default NULL,
193                                 author varchar(80) default NULL,
194                                 marc text NOT NULL,
195                                 encoding varchar(40) default NULL,
196                                 PRIMARY KEY  (id),
197                                 KEY title (title),
198                                 KEY isbn (isbn)
199                         )",
200     authorised_values => "(id int(11) NOT NULL auto_increment,
201                                 category char(10) NOT NULL default '',
202                                 authorised_value char(80) NOT NULL default '',
203                                 lib char(80) NULL,
204                                 PRIMARY KEY  (id),
205                                 KEY name (category)
206                         )",
207     userflags => "( bit int(11) NOT NULL default '0',
208                                 flag char(30), flagdesc char(255),
209                                 defaulton int(11)
210                         )",
211 );
212
213 my %requirefields = (
214     biblio        => { 'abstract' => 'text' },
215     deletedbiblio => { 'abstract' => 'text', 'marc' => 'blob' },
216     deleteditems => { 'marc' => 'blob', 'paidfor' => 'text' },
217     biblioitems   => {
218         'lccn' => 'char(25)',
219         'url'  => 'varchar(255)',
220         'marc' => 'text'
221     },
222     deletedbiblioitems => {
223         'lccn' => 'char(25)',
224         'url'  => 'varchar(255)',
225         'marc' => 'text'
226     },
227     branchtransfers => { 'datearrived'    => 'datetime' },
228     statistics      => { 'borrowernumber' => 'int(11)' },
229     aqbooksellers   => {
230         'invoicedisc' => 'float(6,4)',
231         'nocalc'      => 'int(11)'
232     },
233     borrowers => {
234         'userid'        => 'char(30)',
235         'password'      => 'char(30)',
236         'flags'         => 'int(11)',
237         'textmessaging' => 'varchar(30)',
238            'zipcode' => 'varchar(25)',
239                         'homezipcode' => 'varchar(25)',
240     },
241     aqorders => { 'budgetdate' => 'date' },
242     aqbudget => {'aqbudgetid' => 'tinyint(4) auto_increment primary key'},
243     items => {'paidfor' => 'text'},
244
245     #added so that reference items are not available for reserves...
246     itemtypes         => { 'notforloan'  => 'smallint(6)' },
247     systempreferences => { 'explanation' => 'char(80)',
248                            'type' => 'char(20)',
249                            'options' => 'text' },
250     z3950servers      => { 'syntax'      => 'char(80)' },
251         marc_tag_structure =>{
252                                                         'itemtype' => 'char(4) not NULL default \'\''},
253     marc_subfield_structure =>{'seealso'  => 'char(255)',
254                                                         'itemtype' => 'char(4) not NULL default \'\''},
255     bookshelf => {'owner' => 'char(80)',
256                                         'category' => 'char(1)',
257                                 },
258 );
259
260 my %dropable_table = (
261     classification => 'classification',
262     multipart      => 'multipart',
263     multivolume    => 'multivolume',
264     newitems       => 'newitems',
265     procedures     => 'procedures',
266     publisher      => 'publisher',
267     searchstats    => 'searchstats',
268     serialissues   => 'serialissues',
269 );
270
271 # the other hash contains other actions that can't be done elsewhere. they are done
272 # either BEFORE of AFTER everything else, depending on "when" entry (default => AFTER)
273
274 # The tabledata hash contains data that should be in the tables.
275 # The uniquefieldrequired hash entry is used to determine which (if any) fields
276 # must not exist in the table for this row to be inserted.  If the
277 # uniquefieldrequired entry is already in the table, the existing data is not
278 # modified, unless the forceupdate hash entry is also set.  Fields in the
279 # anonymous "forceupdate" hash will be forced to be updated to the default
280 # values given in the %tabledata hash.
281
282 my %tabledata = (
283     userflags => [
284         {
285             uniquefieldrequired => 'bit',
286             bit                 => 0,
287             flag                => 'superlibrarian',
288             flagdesc            => 'Access to all librarian functions',
289             defaulton           => 0
290         },
291         {
292             uniquefieldrequired => 'bit',
293             bit                 => 1,
294             flag                => 'circulate',
295             flagdesc            => 'Circulate books',
296             defaulton           => 0
297         },
298         {
299             uniquefieldrequired => 'bit',
300             bit                 => 2,
301             flag                => 'catalogue',
302             flagdesc            => 'View Catalogue (Librarian Interface)',
303             defaulton           => 0
304         },
305         {
306             uniquefieldrequired => 'bit',
307             bit                 => 3,
308             flag                => 'parameters',
309             flagdesc            => 'Set Koha system paramters',
310             defaulton           => 0
311         },
312         {
313             uniquefieldrequired => 'bit',
314             bit                 => 4,
315             flag                => 'borrowers',
316             flagdesc            => 'Add or modify borrowers',
317             defaulton           => 0
318         },
319         {
320             uniquefieldrequired => 'bit',
321             bit                 => 5,
322             flag                => 'permissions',
323             flagdesc            => 'Set user permissions',
324             defaulton           => 0
325         },
326         {
327             uniquefieldrequired => 'bit',
328             bit                 => 6,
329             flag                => 'reserveforothers',
330             flagdesc            => 'Reserve books for patrons',
331             defaulton           => 0
332         },
333         {
334             uniquefieldrequired => 'bit',
335             bit                 => 7,
336             flag                => 'borrow',
337             flagdesc            => 'Borrow books',
338             defaulton           => 1
339         },
340         {
341             uniquefieldrequired => 'bit',
342             bit                 => 8,
343             flag                => 'reserveforself',
344             flagdesc            => 'Reserve books for self',
345             defaulton           => 0
346         },
347         {
348             uniquefieldrequired => 'bit',
349             bit                 => 9,
350             flag                => 'editcatalogue',
351             flagdesc  => 'Edit Catalogue (Modify bibliographic/holdings data)',
352             defaulton => 0
353         },
354         {
355             uniquefieldrequired => 'bit',
356             bit                 => 10,
357             flag                => 'updatecharges',
358             flagdesc            => 'Update borrower charges',
359             defaulton           => 0
360         },
361     ],
362     systempreferences => [
363         {
364             uniquefieldrequired => 'variable',
365             forceupdate         => { 'explanation' => 1,
366                                      'type' => 1 },
367             variable            => 'LibraryName',
368             value               => '<i><b>Koha<br/>Free Software ILS<br/><br/></b>Koha : a gift, a contribution<br/> in Maori</i>',
369             explanation         => 'Library name as shown on main opac page',
370             type                => ''
371
372         },
373         {
374             uniquefieldrequired => 'variable',
375             forceupdate         => { 'explanation' => 1,
376                                      'type' => 1 },
377             variable            => 'autoMemberNum',
378             value               => '1',
379             explanation         => 'Member number is auto-calculated',
380             type                => 'YesNo'
381
382         },
383         {
384             uniquefieldrequired => 'variable',
385             forceupdate         => { 'explanation' => 1,
386                                      'type' => 1,
387                                      'options' => 1 },
388             variable            => 'acquisitions',
389             value               => 'normal',
390             explanation         =>
391 'Normal, budget-based acquisitions, or Simple bibliographic-data acquisitions',
392             type                => 'Choice',
393             options             => 'simple|normal'
394         },
395         {
396             uniquefieldrequired => 'variable',
397             forceupdate         => { 'explanation' => 1,
398                                      'type' => 1,
399                                      'options' => 1 },
400             variable            => 'dateformat',
401             value               => 'metric',
402             explanation         =>
403             'date format (us mm/dd/yyyy, metric dd/mm/yyy, ISO yyyy/mm/dd)',
404             type                => 'Choice',
405             options             => 'metric|us|iso'
406         },
407         {
408             uniquefieldrequired => 'variable',
409             variable            => 'template',
410             forceupdate         => { 'explanation' => 1,
411                                      'type' => 1 },
412             value               => 'default',
413             explanation         => 'Preference order for intranet interface templates',
414             type                => 'Themes'
415         },
416         {
417             uniquefieldrequired => 'variable',
418             variable            => 'autoBarcode',
419             forceupdate         => { 'explanation' => 1,
420                                      'type' => 1 },
421             value               => 'yes',
422             explanation         => 'Barcode is auto-calculated',
423             type                => 'YesNo'
424         },
425         {
426             uniquefieldrequired => 'variable',
427             variable            => 'insecure',
428             forceupdate         => { 'explanation' => 1,
429                                      'type' => 1 },
430             value               => 'no',
431             explanation         =>
432 'If YES, no auth at all is needed. Be careful if you set this to yes!',
433             type                => 'YesNo'
434         },
435         {
436             uniquefieldrequired => 'variable',
437             variable            => 'authoritysep',
438             forceupdate         => { 'explanation' => 1,
439                                      'type' => 1,
440                                      'options' => 1 },
441             value               => '--',
442             explanation         =>
443             'the separator used in authority/thesaurus. Usually --',
444             type                => 'free',
445             options             => '10'
446         },
447         {
448             uniquefieldrequired => 'variable',
449             variable            => 'opaclanguages',
450             forceupdate         => { 'explanation' => 1,
451                                      'type' => 1 },
452             value               => 'en',
453             explanation         => 'Set the preferred order for translations.  The top language will be tried first.',
454             type                => 'Languages'
455         },
456         {
457             uniquefieldrequired => 'variable',
458             variable            => 'opacthemes',
459             forceupdate         => { 'explanation' => 1,
460                                      'type' => 1 },
461             value               => 'css',
462             explanation         => 'Set the preferred order for themes.  The top theme will be tried first.',
463             type                => 'Themes'
464         },
465         {
466             uniquefieldrequired => 'variable',
467             variable            => 'timeout',
468             forceupdate         => { 'explanation' => 1,
469                                      'type' => 1 },
470             value               => '1200',
471             explanation         => 'Inactivity timeout for cookies authentication (in seconds)',
472             type                => 'Integer'
473         },
474         {
475             uniquefieldrequired => 'variable',
476             variable            => 'marc',
477             forceupdate         => { 'explanation' => 1,
478                                      'type' => 1 },
479             value               => 'yes',
480             explanation         => 'Turn on MARC support',
481             type                => 'YesNo'
482         },
483         {
484             uniquefieldrequired => 'variable',
485             variable            => 'marcflavour',
486             forceupdate         => { 'explanation' => 1,
487                                      'type' => 1,
488                                      'options' => 1},
489             value               => 'MARC21',
490             explanation         =>
491             'your MARC flavor (MARC21 or UNIMARC) used for character encoding',
492             type                => 'Choice',
493             options             => 'MARC21|UNIMARC'
494         },
495         {
496             uniquefieldrequired => 'variable',
497             variable            => 'checkdigit',
498             value               => 'none',
499             forceupdate         => { 'explanation' => 1,
500                                      'type' => 1,
501                                      'options' => 1},
502             explanation         => 'Validity checks on membership number: none or "Katipo" style checks',
503             type                => 'Choice',
504             options             => 'none|katipo'
505         },
506         {
507             uniquefieldrequired => 'variable',
508             variable            => 'maxoutstanding',
509             forceupdate         => { 'explanation' => 1,
510                                      'type' => 1 },
511             value               => '5',
512             explanation         =>
513             'maximum amount withstanding to be able make reserves ',
514             type                => 'Integer'
515         },
516         {
517             uniquefieldrequired => 'variable',
518             variable            => 'maxreserves',
519             forceupdate         => { 'explanation' => 1,
520                                      'type' => 1 },
521             value               => '5',
522             explanation         =>
523             'maximum number of reserves a member can make',
524             type                => 'Integer'
525
526         },
527         {
528             uniquefieldrequired => 'variable',
529             variable            => 'noissuescharge',
530             forceupdate         => { 'explanation' => 1,
531                                      'type' => 1 },
532             value               => '5',
533             explanation         =>
534             'maximum amount withstanding to be able to check out an item',
535             type                => 'Integer'
536
537         },
538         {
539             uniquefieldrequired => 'variable',
540             variable            => 'KohaAdminEmailAddress',
541             forceupdate         => { 'explanation' => 1,
542                                      'type' => 1 },
543             value               => 'your.mail@here',
544             explanation => 'the email address where borrowers modifs are sent',
545             type                => 'free'
546         },
547         {
548             uniquefieldrequired => 'variable',
549             variable            => 'gist',
550             forceupdate         => { 'explanation' => 1,
551                                      'type' => 1 },
552             value               => '0.125',
553             explanation => 'the gist rate. NOT in %, but in numeric form (0.12 for 12%)',
554             type                => 'free'
555         },
556         {
557             uniquefieldrequired => 'variable',
558             variable            => 'ldapserver',
559             forceupdate         => { 'explanation' => 1,
560                                      'type' => 1 },
561             value               => '',
562             explanation => 'your ldap server',
563             type                => 'free'
564         },
565         {
566             uniquefieldrequired => 'variable',
567             variable            => 'ldapinfos',
568             forceupdate         => { 'explanation' => 1,
569                                      'type' => 1 },
570             value               => '',
571             explanation => 'ldap info. The ldap will be used in dn : uid=xxx, <ldapinfos>',
572             type                => 'free'
573         },
574         {
575             uniquefieldrequired => 'variable',
576             variable            => 'printcirculationslips',
577             forceupdate         => { 'explanation' => 1,
578                                      'type' => 1 },
579             value               => '0',
580             explanation => 'if set to 1, print circulation slips. If set to 0, don\'t',
581             type                => 'free'
582         },
583     ],
584
585 );
586
587 my %fielddefinitions = (
588     printers => [
589         {
590             field   => 'printername',
591             type    => 'char(40)',
592             null    => '',
593             key     => 'PRI',
594             default => ''
595         },
596     ],
597     aqbookfund => [
598         {
599             field   => 'bookfundid',
600             type    => 'char(5)',
601             null    => '',
602             key     => 'PRI',
603             default => ''
604         },
605     ],
606     aqbudget => [
607         {
608             field   => 'aqbudgetid',
609             type    => 'tinyint(4)',
610             null    => '',
611             key     => 'PRI',
612                   default =>'',
613             extra => 'auto_increment'
614         },
615     ],
616     z3950servers => [
617         {
618             field   => 'id',
619             type    => 'int',
620             null    => '',
621             key     => 'PRI',
622             default => '',
623             extra   => 'auto_increment'
624         },
625     ],
626         marc_breeding => [
627         {
628             field   => 'z3950random',
629             type    => 'varchar(40)',
630             null    => 'NULL',
631             key     => '',
632             default => '',
633             extra   => ''
634         },
635         {
636             field   => 'encoding',
637             type    => 'varchar(40)',
638             null    => '',
639             key     => '',
640             default => '',
641             extra   => ''
642         },
643     ],
644 );
645
646 #-------------------
647 # Initialize
648
649 # Start checking
650
651 # Get version of MySQL database engine.
652 my $mysqlversion = `mysqld --version`;
653 $mysqlversion =~ /Ver (\S*) /;
654 $mysqlversion = $1;
655 if ( $mysqlversion ge '3.23' ) {
656     print "Could convert to MyISAM database tables...\n";
657 }
658
659 #---------------------------------
660 # Tables
661
662 # Collect all tables into a list
663 $sth = $dbh->prepare("show tables");
664 $sth->execute;
665 while ( my ($table) = $sth->fetchrow ) {
666     $existingtables{$table} = 1;
667 }
668
669
670 # Now add any missing tables
671 foreach $table ( keys %requiretables ) {
672     unless ( $existingtables{$table} ) {
673         print "Adding $table table...\n";
674         my $sth = $dbh->prepare("create table $table $requiretables{$table}");
675         $sth->execute;
676         if ( $sth->err ) {
677             print "Error : $sth->errstr \n";
678             $sth->finish;
679         }    # if error
680     }    # unless exists
681 }    # foreach
682
683 # now drop useless tables
684 foreach $table ( keys %dropable_table ) {
685         if ( $existingtables{$table} ) {
686                 print "Dropping unused table $table\n" if $debug;
687                 $dbh->do("drop table $table");
688                 if ( $dbh->err ) {
689                         print "Error : $dbh->errstr \n";
690                 }
691         }
692 }
693 unless ( $existingtables{'z3950servers'} ) {
694         #MJR: added syntax entries to close bug 624
695     print "Adding z3950servers table...\n";
696     my $sti = $dbh->prepare( "create table z3950servers (
697                                                                                 host char(255),
698                                                                                 port int,
699                                                                                 db char(255),
700                                                                                 userid char(255),
701                                                                                 password char(255),
702                                                                                 name text,
703                                                                                 id int,
704                                                                                 checked smallint,
705                                                                                 rank int,
706                                                                                 syntax char(80))"
707     );
708     $sti->execute;
709     $sti = $dbh->prepare( "insert into z3950servers
710                                                                 values ('z3950.loc.gov',
711                                                                 7090,
712                                                                 'voyager',
713                                                                 '', '',
714                                                                 'Library of Congress',
715                                                                 1, 1, 1, 'USMARC')"
716     );
717     $sti->execute;
718 }
719 unless ( $existingtables{'issuingrules'} ) {
720         $dbh->do("alter table categoryitem rename issuingrules");
721         print "renaming categoryitem\n";
722 }
723
724
725 #---------------------------------
726 # Columns
727
728 foreach $table ( keys %requirefields ) {
729     print "Check table $table\n" if $debug;
730     $sth = $dbh->prepare("show columns from $table");
731     $sth->execute();
732     undef %types;
733     while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
734     {
735         $types{$column} = $type;
736     }    # while
737     foreach $column ( keys %{ $requirefields{$table} } ) {
738         print "  Check column $column  [$types{$column}]\n" if $debug;
739         if ( !$types{$column} ) {
740
741             # column doesn't exist
742             print "Adding $column field to $table table...\n";
743             $query = "alter table $table
744                         add column $column " . $requirefields{$table}->{$column};
745             print "Execute: $query\n" if $debug;
746             my $sti = $dbh->prepare($query);
747             $sti->execute;
748             if ( $sti->err ) {
749                 print "**Error : $sti->errstr \n";
750                 $sti->finish;
751             }    # if error
752         }    # if column
753     }    # foreach column
754 }    # foreach table
755
756 foreach $table ( keys %fielddefinitions ) {
757         print "Check table $table\n" if $debug;
758         $sth = $dbh->prepare("show columns from $table");
759         $sth->execute();
760         my $definitions;
761         while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
762         {
763                 $definitions->{$column}->{type}    = $type;
764                 $definitions->{$column}->{null}    = $null;
765                 $definitions->{$column}->{key}     = $key;
766                 $definitions->{$column}->{default} = $default;
767                 $definitions->{$column}->{extra}   = $extra;
768         }    # while
769         my $fieldrow = $fielddefinitions{$table};
770         foreach my $row (@$fieldrow) {
771                 my $field   = $row->{field};
772                 my $type    = $row->{type};
773                 my $null    = $row->{null};
774                 my $key     = $row->{key};
775                 my $default = $row->{default};
776                 $default="''" unless $default;
777                 my $extra   = $row->{extra};
778                 my $def     = $definitions->{$field};
779                 unless ( $type eq $def->{type}
780                         && $null eq $def->{null}
781                         && $key eq $def->{key}
782                         && $default eq $def->{default}
783                         && $extra eq $def->{extra} )
784                 {
785
786                         if ( $null eq '' ) {
787                                 $null = 'NOT NULL';
788                         }
789                         if ( $key eq 'PRI' ) {
790                                 $key = 'PRIMARY KEY';
791                         }
792                         unless ( $extra eq 'auto_increment' ) {
793                                 $extra = '';
794                         }
795                         # if it's a new column use "add", if it's an old one, use "change".
796                         my $action;
797                         if ($definitions->{$field}->{type}) {
798                                 $action="change $field"
799                         } else {
800                                 $action="add";
801                         }
802 # if it's a primary key, drop the previous pk, before altering the table
803                         my $sth;
804                         if ($key ne 'PRIMARY KEY') {
805                                 $sth =$dbh->prepare("alter table $table $action $field $type $null $key $extra default ?");
806                         } else {
807                                 $sth =$dbh->prepare("alter table $table drop primary key, $action $field $type $null $key $extra default ?");
808                         }
809                         $sth->execute($default);
810                         print "  Alter $field in $table\n";
811                 }
812         }
813 }
814
815 # Get list of columns from borrowers table
816 my %itemtypes;
817 my %nullenabled;
818 $sth = $dbh->prepare("show columns from borrowers");
819 $sth->execute;
820 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
821 {
822     $itemtypes{$column} = $type;
823     $nullenabled{$column} = $null;
824 }
825
826 unless ( $itemtypes{'cardnumber'} eq 'varchar(20)' ) {
827     $itemtypes{'cardnumber'} =~ /varchar\((\d+)\)/;
828     my $oldlength = $1;
829     if ( $oldlength < 16 ) {
830         print "Setting maximum cardnumber length to 16 (was $oldlength) and marking unique.\n";
831         my $sti =
832           $dbh->prepare(
833             "alter table borrowers change cardnumber cardnumber varchar(16)");
834         $sti->execute;
835         $sti->finish;
836         $sti =
837           $dbh->prepare(
838             "alter table borrowers drop index cardnumber");
839         $sti->execute;
840         $sti->finish;
841         $sti =
842           $dbh->prepare(
843             "alter table borrowers add unique(cardnumber)");
844         $sti->execute;
845         $sti->finish;
846     }
847 }
848 #
849 # Get list of columns from items table
850 $sth = $dbh->prepare("show columns from items");
851 $sth->execute;
852 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
853 {
854     $itemtypes{$column} = $type;
855     $nullenabled{$column} = $null;
856 }
857
858 unless ( $itemtypes{'barcode'} eq 'varchar(20)' ) {
859     $itemtypes{'barcode'} =~ /varchar\((\d+)\)/;
860     my $oldlength = $1;
861     if ( $oldlength < 20 ) {
862         print "Setting maximum barcode length to 20 (was $oldlength).\n";
863         my $sti =
864           $dbh->prepare(
865             "alter table items change barcode barcode varchar(20)");
866         $sti->execute;
867     }
868 }
869 #
870 # dropping unique barcode index & setting barcode to null allowed.
871 #
872 $sth = $dbh->prepare("show index from items");
873 $sth->execute;
874 while ( my ( $table, $non_unique, $key_name, $Seq_in_index, $Column_name, $Collation, $cardinality, $sub_part, $Packed, $comment ) = $sth->fetchrow )
875 {
876         if ($key_name eq 'barcode' && $non_unique eq 0) {
877                 print "dropping BARCODE index to enable empty barcodes\n";
878                 $dbh->do("ALTER TABLE `items` DROP INDEX `barcode`");
879         }
880 }
881 $dbh->do("ALTER TABLE `items` CHANGE `barcode` `barcode` VARCHAR( 20 )") unless ($nullenabled{barcode} eq 'YES');
882
883 #
884 # creating fulltext index in bibliothesaurus if needed
885 #
886 $sth = $dbh->prepare("show index from bibliothesaurus");
887 $sth->execute;
888 my $exists=0;
889 while ( my ( $table, $non_unique, $key_name, $Seq_in_index, $Column_name, $Collation, $cardinality, $sub_part, $Packed, $comment ) = $sth->fetchrow )
890 {
891         if ($key_name eq 'category_2') {
892                 $exists=1;
893         }
894 }
895 print "Creating fulltext index on bibliothesaurus\n" unless $exists;
896 $dbh->do('create fulltext index category_2 on bibliothesaurus (category,freelib)') unless $exists;
897
898 #
899 # creating  index in z3950results if needed
900 #
901 $sth = $dbh->prepare("show index from z3950results");
902 $sth->execute;
903 my $exists=0;
904 while ( my ( $table, $non_unique, $key_name, $Seq_in_index, $Column_name, $Collation, $cardinality, $sub_part, $Packed, $comment ) = $sth->fetchrow )
905 {
906         if ($key_name eq 'query_server') {
907                 $exists=1;
908         }
909 }
910 print "Creating  index on z3950results\n" unless $exists;
911 $dbh->do('create unique index query_server on z3950results (queryid,server)') unless $exists;
912
913 # changing z3950daemon field to NULL in marc_breeding
914 $dbh->do("ALTER TABLE `marc_breeding` CHANGE `z3950random` `z3950random` VARCHAR( 40 )");
915
916 # making borrowernumber an auto_increment field
917 $dbh->do("ALTER TABLE `borrowers` CHANGE `borrowernumber` `borrowernumber` INTEGER auto_increment");
918
919 # extending the timestamp in branchtransfers...
920 my %branchtransfers;
921
922 $sth = $dbh->prepare("show columns from branchtransfers");
923 $sth->execute;
924 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
925 {
926     $branchtransfers{$column} = $type;
927 }
928
929 unless ( $branchtransfers{'datesent'} eq 'datetime' ) {
930     print "Setting type of datesent in branchtransfers to datetime.\n";
931     my $sti =
932       $dbh->prepare(
933         "alter table branchtransfers change datesent datesent datetime");
934     $sti->execute;
935 }
936
937 unless ( $branchtransfers{'datearrived'} eq 'datetime' ) {
938     print "Setting type of datearrived in branchtransfers to datetime.\n";
939     my $sti =
940       $dbh->prepare(
941         "alter table branchtransfers change datearrived datearrived datetime");
942     $sti->execute;
943 }
944
945 # changing the branchcategories table around...
946 my %branchcategories;
947
948 $sth = $dbh->prepare("show columns from branchcategories");
949 $sth->execute;
950 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
951 {
952     $branchcategories{$column} = $type;
953 }
954
955 unless ( $branchcategories{'categorycode'} eq 'varchar(4)' ) {
956     print
957 "Setting type of categorycode in branchcategories to varchar(4),\n and making the primary key.\n";
958     my $sti =
959       $dbh->prepare(
960 "alter table branchcategories change categorycode categorycode varchar(4) not null"
961     );
962     $sti->execute;
963     $sti =
964       $dbh->prepare(
965         "alter table branchcategories add primary key (categorycode)");
966     $sti->execute;
967 }
968
969 unless ( $branchcategories{'categoryname'} eq 'text' ) {
970     print "Changing branchcode in branchcategories to categoryname text.\n";
971     my $sth =
972       $dbh->prepare(
973         "alter table branchcategories change branchcode categoryname text");
974     $sth->execute;
975 }
976
977 unless ( $branchcategories{'codedescription'} eq 'text' ) {
978     print
979 "Replacing branchholding in branchcategories with codedescription text.\n";
980     my $sth =
981       $dbh->prepare(
982         "alter table branchcategories change branchholding codedescription text"
983     );
984     $sth->execute;
985 }
986
987 # changing the items table around...
988 my %items;
989
990 $sth = $dbh->prepare("show columns from items");
991 $sth->execute;
992 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
993 {
994     $items{$column} = $type;
995 }
996
997 if ($items{'bulk'} eq "varchar(30)") {
998     print "  Setting callnumber in items table\n";
999     my $sti =
1000       $dbh->prepare("ALTER TABLE `items` CHANGE `bulk` `itemcallnumber` VARCHAR( 30 ) DEFAULT NULL");
1001     $sti->execute;
1002     $sti = $dbh->prepare("update marc_subfield_structure set kohafield=\"items.itemcallnumber\" where kohafield=\"items.bulk\"");
1003     $sti->execute;
1004 }
1005
1006 #
1007 # creating  index in issuingrules if needed
1008 #
1009 $sth = $dbh->prepare("show index from issuingrules");
1010 $sth->execute;
1011 my $exists=0;
1012 while ( my ( $table, $non_unique, $key_name, $Seq_in_index, $Column_name, $Collation, $cardinality, $sub_part, $Packed, $comment ) = $sth->fetchrow )
1013 {
1014         if ($key_name eq 'PRIMARY') {
1015                 $exists=1;
1016         }
1017 }
1018 print "Creating  index on z3950results\n" unless $exists;
1019 $dbh->do('ALTER TABLE issuingrules ADD PRIMARY KEY ( branchcode, categorycode, itemtype )') unless $exists;
1020
1021 $dbh->do('ALTER TABLE marc_tag_structure drop primary key');
1022 $dbh->do('ALTER TABLE marc_tag_structure ADD PRIMARY KEY ( itemtype, tagfield )');
1023
1024 $dbh->do('ALTER TABLE marc_subfield_structure drop primary key');
1025 $dbh->do('ALTER TABLE marc_subfield_structure ADD PRIMARY KEY ( itemtype, tagfield, tagsubfield )');
1026
1027 # Populate tables with required data
1028
1029 foreach my $table ( keys %tabledata ) {
1030     print "Checking for data required in table $table...\n";
1031     my $tablerows = $tabledata{$table};
1032     foreach my $row (@$tablerows) {
1033         my $uniquefieldrequired = $row->{uniquefieldrequired};
1034         my $uniquevalue         = $row->{$uniquefieldrequired};
1035         my $forceupdate         = $row->{forceupdate};
1036         my $sth                 =
1037           $dbh->prepare(
1038 "select $uniquefieldrequired from $table where $uniquefieldrequired=?"
1039         );
1040         $sth->execute($uniquevalue);
1041         if ($sth->rows) {
1042             foreach my $field (keys %$forceupdate) {
1043                 if ($forceupdate->{$field}) {
1044                     my $sth=$dbh->prepare("update systempreferences set $field=? where $uniquefieldrequired=?");
1045                     $sth->execute($row->{$field}, $uniquevalue);
1046                 }
1047             }
1048         } else {
1049             print "Adding row to $table: ";
1050             my @values;
1051             my $fieldlist;
1052             my $placeholders;
1053             foreach my $field ( keys %$row ) {
1054                 next if $field eq 'uniquefieldrequired';
1055                 next if $field eq 'forceupdate';
1056                 my $value = $row->{$field};
1057                 push @values, $value;
1058                 print "  $field => $value";
1059                 $fieldlist .= "$field,";
1060                 $placeholders .= "?,";
1061             }
1062             print "\n";
1063             $fieldlist    =~ s/,$//;
1064             $placeholders =~ s/,$//;
1065             my $sth =
1066               $dbh->prepare(
1067                 "insert into $table ($fieldlist) values ($placeholders)");
1068             $sth->execute(@values);
1069         }
1070     }
1071 }
1072
1073 $sth->finish;
1074
1075 exit;
1076
1077 # $Log$
1078 # Revision 1.79  2004/05/18 09:50:07  tipaul
1079 # *** empty log message ***
1080 #
1081 # Revision 1.78  2004/05/10 09:29:33  tipaul
1082 # css is now the default theme for OPAC.
1083 # It will be the theme used for improvements and new things in OPAC.
1084 #
1085 # Revision 1.77  2004/05/06 14:56:51  tipaul
1086 # adding table issuingrules (previously called categoryitem
1087 #
1088 # Revision 1.76  2004/05/03 09:32:25  tipaul
1089 # adding printcirculationsplit parameter (already existed, but was not in systempref by defaul)
1090 #
1091 # Revision 1.75  2004/04/14 19:49:00  tipaul
1092 # seealso field set to 255 chars
1093 #
1094 # Revision 1.74  2004/03/11 16:10:16  tipaul
1095 # *** empty log message ***
1096 #
1097 # Revision 1.73  2004/03/06 20:26:13  tipaul
1098 # adding seealso feature in MARC searches
1099 #