adding printcirculationsplit parameter (already existed, but was not in systempref...
[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_subfield_structure =>{'seealso'  => 'char(255)'},
252     bookshelf => {'owner' => 'char(80)',
253                                         'category' => 'char(1)',
254                                 }
255 );
256
257 my %dropable_table = (
258     classification => 'classification',
259     multipart      => 'multipart',
260     multivolume    => 'multivolume',
261     newitems       => 'newitems',
262     procedures     => 'procedures',
263     publisher      => 'publisher',
264     searchstats    => 'searchstats',
265     serialissues   => 'serialissues',
266 );
267
268 # the other hash contains other actions that can't be done elsewhere. they are done
269 # either BEFORE of AFTER everything else, depending on "when" entry (default => AFTER)
270
271 # The tabledata hash contains data that should be in the tables.
272 # The uniquefieldrequired hash entry is used to determine which (if any) fields
273 # must not exist in the table for this row to be inserted.  If the
274 # uniquefieldrequired entry is already in the table, the existing data is not
275 # modified, unless the forceupdate hash entry is also set.  Fields in the
276 # anonymous "forceupdate" hash will be forced to be updated to the default
277 # values given in the %tabledata hash.
278
279 my %tabledata = (
280     userflags => [
281         {
282             uniquefieldrequired => 'bit',
283             bit                 => 0,
284             flag                => 'superlibrarian',
285             flagdesc            => 'Access to all librarian functions',
286             defaulton           => 0
287         },
288         {
289             uniquefieldrequired => 'bit',
290             bit                 => 1,
291             flag                => 'circulate',
292             flagdesc            => 'Circulate books',
293             defaulton           => 0
294         },
295         {
296             uniquefieldrequired => 'bit',
297             bit                 => 2,
298             flag                => 'catalogue',
299             flagdesc            => 'View Catalogue (Librarian Interface)',
300             defaulton           => 0
301         },
302         {
303             uniquefieldrequired => 'bit',
304             bit                 => 3,
305             flag                => 'parameters',
306             flagdesc            => 'Set Koha system paramters',
307             defaulton           => 0
308         },
309         {
310             uniquefieldrequired => 'bit',
311             bit                 => 4,
312             flag                => 'borrowers',
313             flagdesc            => 'Add or modify borrowers',
314             defaulton           => 0
315         },
316         {
317             uniquefieldrequired => 'bit',
318             bit                 => 5,
319             flag                => 'permissions',
320             flagdesc            => 'Set user permissions',
321             defaulton           => 0
322         },
323         {
324             uniquefieldrequired => 'bit',
325             bit                 => 6,
326             flag                => 'reserveforothers',
327             flagdesc            => 'Reserve books for patrons',
328             defaulton           => 0
329         },
330         {
331             uniquefieldrequired => 'bit',
332             bit                 => 7,
333             flag                => 'borrow',
334             flagdesc            => 'Borrow books',
335             defaulton           => 1
336         },
337         {
338             uniquefieldrequired => 'bit',
339             bit                 => 8,
340             flag                => 'reserveforself',
341             flagdesc            => 'Reserve books for self',
342             defaulton           => 0
343         },
344         {
345             uniquefieldrequired => 'bit',
346             bit                 => 9,
347             flag                => 'editcatalogue',
348             flagdesc  => 'Edit Catalogue (Modify bibliographic/holdings data)',
349             defaulton => 0
350         },
351         {
352             uniquefieldrequired => 'bit',
353             bit                 => 10,
354             flag                => 'updatecharges',
355             flagdesc            => 'Update borrower charges',
356             defaulton           => 0
357         },
358     ],
359     systempreferences => [
360         {
361             uniquefieldrequired => 'variable',
362             forceupdate         => { 'explanation' => 1,
363                                      'type' => 1 },
364             variable            => 'LibraryName',
365             value               => '<i><b>Koha<br/>Free Software ILS<br/><br/></b>Koha : a gift, a contribution<br/> in Maori</i>',
366             explanation         => 'Library name as shown on main opac page',
367             type                => ''
368
369         },
370         {
371             uniquefieldrequired => 'variable',
372             forceupdate         => { 'explanation' => 1,
373                                      'type' => 1 },
374             variable            => 'autoMemberNum',
375             value               => '1',
376             explanation         => 'Member number is auto-calculated',
377             type                => 'YesNo'
378
379         },
380         {
381             uniquefieldrequired => 'variable',
382             forceupdate         => { 'explanation' => 1,
383                                      'type' => 1,
384                                      'options' => 1 },
385             variable            => 'acquisitions',
386             value               => 'normal',
387             explanation         =>
388 'Normal, budget-based acquisitions, or Simple bibliographic-data acquisitions',
389             type                => 'Choice',
390             options             => 'simple|normal'
391         },
392         {
393             uniquefieldrequired => 'variable',
394             forceupdate         => { 'explanation' => 1,
395                                      'type' => 1,
396                                      'options' => 1 },
397             variable            => 'dateformat',
398             value               => 'metric',
399             explanation         =>
400             'date format (us mm/dd/yyyy, metric dd/mm/yyy, ISO yyyy/mm/dd)',
401             type                => 'Choice',
402             options             => 'metric|us|iso'
403         },
404         {
405             uniquefieldrequired => 'variable',
406             variable            => 'template',
407             forceupdate         => { 'explanation' => 1,
408                                      'type' => 1 },
409             value               => 'default',
410             explanation         => 'Preference order for intranet interface templates',
411             type                => 'Themes'
412         },
413         {
414             uniquefieldrequired => 'variable',
415             variable            => 'autoBarcode',
416             forceupdate         => { 'explanation' => 1,
417                                      'type' => 1 },
418             value               => 'yes',
419             explanation         => 'Barcode is auto-calculated',
420             type                => 'YesNo'
421         },
422         {
423             uniquefieldrequired => 'variable',
424             variable            => 'insecure',
425             forceupdate         => { 'explanation' => 1,
426                                      'type' => 1 },
427             value               => 'no',
428             explanation         =>
429 'If YES, no auth at all is needed. Be careful if you set this to yes!',
430             type                => 'YesNo'
431         },
432         {
433             uniquefieldrequired => 'variable',
434             variable            => 'authoritysep',
435             forceupdate         => { 'explanation' => 1,
436                                      'type' => 1,
437                                      'options' => 1 },
438             value               => '--',
439             explanation         =>
440             'the separator used in authority/thesaurus. Usually --',
441             type                => 'free',
442             options             => '10'
443         },
444         {
445             uniquefieldrequired => 'variable',
446             variable            => 'opaclanguages',
447             forceupdate         => { 'explanation' => 1,
448                                      'type' => 1 },
449             value               => 'en',
450             explanation         => 'Set the preferred order for translations.  The top language will be tried first.',
451             type                => 'Languages'
452         },
453         {
454             uniquefieldrequired => 'variable',
455             variable            => 'opacthemes',
456             forceupdate         => { 'explanation' => 1,
457                                      'type' => 1 },
458             value               => 'default',
459             explanation         => 'Set the preferred order for themes.  The top theme will be tried first.',
460             type                => 'Themes'
461         },
462         {
463             uniquefieldrequired => 'variable',
464             variable            => 'timeout',
465             forceupdate         => { 'explanation' => 1,
466                                      'type' => 1 },
467             value               => '1200',
468             explanation         => 'Inactivity timeout for cookies authentication (in seconds)',
469             type                => 'Integer'
470         },
471         {
472             uniquefieldrequired => 'variable',
473             variable            => 'marc',
474             forceupdate         => { 'explanation' => 1,
475                                      'type' => 1 },
476             value               => 'yes',
477             explanation         => 'Turn on MARC support',
478             type                => 'YesNo'
479         },
480         {
481             uniquefieldrequired => 'variable',
482             variable            => 'marcflavour',
483             forceupdate         => { 'explanation' => 1,
484                                      'type' => 1,
485                                      'options' => 1},
486             value               => 'MARC21',
487             explanation         =>
488             'your MARC flavor (MARC21 or UNIMARC) used for character encoding',
489             type                => 'Choice',
490             options             => 'MARC21|UNIMARC'
491         },
492         {
493             uniquefieldrequired => 'variable',
494             variable            => 'checkdigit',
495             value               => 'none',
496             forceupdate         => { 'explanation' => 1,
497                                      'type' => 1,
498                                      'options' => 1},
499             explanation         => 'Validity checks on membership number: none or "Katipo" style checks',
500             type                => 'Choice',
501             options             => 'none|katipo'
502         },
503         {
504             uniquefieldrequired => 'variable',
505             variable            => 'maxoutstanding',
506             forceupdate         => { 'explanation' => 1,
507                                      'type' => 1 },
508             value               => '5',
509             explanation         =>
510             'maximum amount withstanding to be able make reserves ',
511             type                => 'Integer'
512         },
513         {
514             uniquefieldrequired => 'variable',
515             variable            => 'maxreserves',
516             forceupdate         => { 'explanation' => 1,
517                                      'type' => 1 },
518             value               => '5',
519             explanation         =>
520             'maximum number of reserves a member can make',
521             type                => 'Integer'
522
523         },
524         {
525             uniquefieldrequired => 'variable',
526             variable            => 'noissuescharge',
527             forceupdate         => { 'explanation' => 1,
528                                      'type' => 1 },
529             value               => '5',
530             explanation         =>
531             'maximum amount withstanding to be able to check out an item',
532             type                => 'Integer'
533
534         },
535         {
536             uniquefieldrequired => 'variable',
537             variable            => 'KohaAdminEmailAddress',
538             forceupdate         => { 'explanation' => 1,
539                                      'type' => 1 },
540             value               => 'your.mail@here',
541             explanation => 'the email address where borrowers modifs are sent',
542             type                => 'free'
543         },
544         {
545             uniquefieldrequired => 'variable',
546             variable            => 'gist',
547             forceupdate         => { 'explanation' => 1,
548                                      'type' => 1 },
549             value               => '0.125',
550             explanation => 'the gist rate. NOT in %, but in numeric form (0.12 for 12%)',
551             type                => 'free'
552         },
553         {
554             uniquefieldrequired => 'variable',
555             variable            => 'ldapserver',
556             forceupdate         => { 'explanation' => 1,
557                                      'type' => 1 },
558             value               => '',
559             explanation => 'your ldap server',
560             type                => 'free'
561         },
562         {
563             uniquefieldrequired => 'variable',
564             variable            => 'ldapinfos',
565             forceupdate         => { 'explanation' => 1,
566                                      'type' => 1 },
567             value               => '',
568             explanation => 'ldap info. The ldap will be used in dn : uid=xxx, <ldapinfos>',
569             type                => 'free'
570         },
571         {
572             uniquefieldrequired => 'variable',
573             variable            => 'printcirculationslips',
574             forceupdate         => { 'explanation' => 1,
575                                      'type' => 1 },
576             value               => '0',
577             explanation => 'if set to 1, print circulation slips. If set to 0, don\'t',
578             type                => 'free'
579         },
580     ],
581
582 );
583
584 my %fielddefinitions = (
585     printers => [
586         {
587             field   => 'printername',
588             type    => 'char(40)',
589             null    => '',
590             key     => 'PRI',
591             default => ''
592         },
593     ],
594     aqbookfund => [
595         {
596             field   => 'bookfundid',
597             type    => 'char(5)',
598             null    => '',
599             key     => 'PRI',
600             default => ''
601         },
602     ],
603     aqbudget => [
604         {
605             field   => 'aqbudgetid',
606             type    => 'tinyint(4)',
607             null    => '',
608             key     => 'PRI',
609                   default =>'',
610             extra => 'auto_increment'
611         },
612     ],
613     z3950servers => [
614         {
615             field   => 'id',
616             type    => 'int',
617             null    => '',
618             key     => 'PRI',
619             default => '',
620             extra   => 'auto_increment'
621         },
622     ],
623         marc_breeding => [
624         {
625             field   => 'z3950random',
626             type    => 'varchar(40)',
627             null    => 'NULL',
628             key     => '',
629             default => '',
630             extra   => ''
631         },
632         {
633             field   => 'encoding',
634             type    => 'varchar(40)',
635             null    => '',
636             key     => '',
637             default => '',
638             extra   => ''
639         },
640     ],
641 );
642
643 #-------------------
644 # Initialize
645
646 # Start checking
647
648 # Get version of MySQL database engine.
649 my $mysqlversion = `mysqld --version`;
650 $mysqlversion =~ /Ver (\S*) /;
651 $mysqlversion = $1;
652 if ( $mysqlversion ge '3.23' ) {
653     print "Could convert to MyISAM database tables...\n";
654 }
655
656 #---------------------------------
657 # Tables
658
659 # Collect all tables into a list
660 $sth = $dbh->prepare("show tables");
661 $sth->execute;
662 while ( my ($table) = $sth->fetchrow ) {
663     $existingtables{$table} = 1;
664 }
665
666
667 # Now add any missing tables
668 foreach $table ( keys %requiretables ) {
669     unless ( $existingtables{$table} ) {
670         print "Adding $table table...\n";
671         my $sth = $dbh->prepare("create table $table $requiretables{$table}");
672         $sth->execute;
673         if ( $sth->err ) {
674             print "Error : $sth->errstr \n";
675             $sth->finish;
676         }    # if error
677     }    # unless exists
678 }    # foreach
679
680 # now drop useless tables
681 foreach $table ( keys %dropable_table ) {
682         if ( $existingtables{$table} ) {
683                 print "Dropping unused table $table\n" if $debug;
684                 $dbh->do("drop table $table");
685                 if ( $dbh->err ) {
686                         print "Error : $dbh->errstr \n";
687                 }
688         }
689 }
690 unless ( $existingtables{'z3950servers'} ) {
691         #MJR: added syntax entries to close bug 624
692     print "Adding z3950servers table...\n";
693     my $sti = $dbh->prepare( "create table z3950servers (
694                                                                                 host char(255),
695                                                                                 port int,
696                                                                                 db char(255),
697                                                                                 userid char(255),
698                                                                                 password char(255),
699                                                                                 name text,
700                                                                                 id int,
701                                                                                 checked smallint,
702                                                                                 rank int,
703                                                                                 syntax char(80))"
704     );
705     $sti->execute;
706     $sti = $dbh->prepare( "insert into z3950servers
707                                                                 values ('z3950.loc.gov',
708                                                                 7090,
709                                                                 'voyager',
710                                                                 '', '',
711                                                                 'Library of Congress',
712                                                                 1, 1, 1, 'USMARC')"
713     );
714     $sti->execute;
715 }
716
717 #---------------------------------
718 # Columns
719
720 foreach $table ( keys %requirefields ) {
721     print "Check table $table\n" if $debug;
722     $sth = $dbh->prepare("show columns from $table");
723     $sth->execute();
724     undef %types;
725     while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
726     {
727         $types{$column} = $type;
728     }    # while
729     foreach $column ( keys %{ $requirefields{$table} } ) {
730         print "  Check column $column  [$types{$column}]\n" if $debug;
731         if ( !$types{$column} ) {
732
733             # column doesn't exist
734             print "Adding $column field to $table table...\n";
735             $query = "alter table $table
736                         add column $column " . $requirefields{$table}->{$column};
737             print "Execute: $query\n" if $debug;
738             my $sti = $dbh->prepare($query);
739             $sti->execute;
740             if ( $sti->err ) {
741                 print "**Error : $sti->errstr \n";
742                 $sti->finish;
743             }    # if error
744         }    # if column
745     }    # foreach column
746 }    # foreach table
747
748 foreach $table ( keys %fielddefinitions ) {
749         print "Check table $table\n" if $debug;
750         $sth = $dbh->prepare("show columns from $table");
751         $sth->execute();
752         my $definitions;
753         while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
754         {
755                 $definitions->{$column}->{type}    = $type;
756                 $definitions->{$column}->{null}    = $null;
757                 $definitions->{$column}->{key}     = $key;
758                 $definitions->{$column}->{default} = $default;
759                 $definitions->{$column}->{extra}   = $extra;
760         }    # while
761         my $fieldrow = $fielddefinitions{$table};
762         foreach my $row (@$fieldrow) {
763                 my $field   = $row->{field};
764                 my $type    = $row->{type};
765                 my $null    = $row->{null};
766                 my $key     = $row->{key};
767                 my $default = $row->{default};
768                 $default="''" unless $default;
769                 my $extra   = $row->{extra};
770                 my $def     = $definitions->{$field};
771                 unless ( $type eq $def->{type}
772                         && $null eq $def->{null}
773                         && $key eq $def->{key}
774                         && $default eq $def->{default}
775                         && $extra eq $def->{extra} )
776                 {
777
778                         if ( $null eq '' ) {
779                                 $null = 'NOT NULL';
780                         }
781                         if ( $key eq 'PRI' ) {
782                                 $key = 'PRIMARY KEY';
783                         }
784                         unless ( $extra eq 'auto_increment' ) {
785                                 $extra = '';
786                         }
787                         # if it's a new column use "add", if it's an old one, use "change".
788                         my $action;
789                         if ($definitions->{$field}->{type}) {
790                                 $action="change $field"
791                         } else {
792                                 $action="add";
793                         }
794 # if it's a primary key, drop the previous pk, before altering the table
795                         my $sth;
796                         if ($key ne 'PRIMARY KEY') {
797                                 $sth =$dbh->prepare("alter table $table $action $field $type $null $key $extra default ?");
798                         } else {
799                                 $sth =$dbh->prepare("alter table $table drop primary key, $action $field $type $null $key $extra default ?");
800                         }
801                         $sth->execute($default);
802                         print "  Alter $field in $table\n";
803                 }
804         }
805 }
806
807 # Get list of columns from borrowers table
808 my %itemtypes;
809 my %nullenabled;
810 $sth = $dbh->prepare("show columns from borrowers");
811 $sth->execute;
812 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
813 {
814     $itemtypes{$column} = $type;
815     $nullenabled{$column} = $null;
816 }
817
818 unless ( $itemtypes{'cardnumber'} eq 'varchar(20)' ) {
819     $itemtypes{'cardnumber'} =~ /varchar\((\d+)\)/;
820     my $oldlength = $1;
821     if ( $oldlength < 16 ) {
822         print "Setting maximum cardnumber length to 16 (was $oldlength) and marking unique.\n";
823         my $sti =
824           $dbh->prepare(
825             "alter table borrowers change cardnumber cardnumber varchar(16)");
826         $sti->execute;
827         $sti->finish;
828         $sti =
829           $dbh->prepare(
830             "alter table borrowers drop index cardnumber");
831         $sti->execute;
832         $sti->finish;
833         $sti =
834           $dbh->prepare(
835             "alter table borrowers add unique(cardnumber)");
836         $sti->execute;
837         $sti->finish;
838     }
839 }
840 #
841 # Get list of columns from items table
842 $sth = $dbh->prepare("show columns from items");
843 $sth->execute;
844 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
845 {
846     $itemtypes{$column} = $type;
847     $nullenabled{$column} = $null;
848 }
849
850 unless ( $itemtypes{'barcode'} eq 'varchar(20)' ) {
851     $itemtypes{'barcode'} =~ /varchar\((\d+)\)/;
852     my $oldlength = $1;
853     if ( $oldlength < 20 ) {
854         print "Setting maximum barcode length to 20 (was $oldlength).\n";
855         my $sti =
856           $dbh->prepare(
857             "alter table items change barcode barcode varchar(20)");
858         $sti->execute;
859     }
860 }
861 #
862 # dropping unique barcode index & setting barcode to null allowed.
863 #
864 $sth = $dbh->prepare("show index from items");
865 $sth->execute;
866 while ( my ( $table, $non_unique, $key_name, $Seq_in_index, $Column_name, $Collation, $cardinality, $sub_part, $Packed, $comment ) = $sth->fetchrow )
867 {
868         if ($key_name eq 'barcode' && $non_unique eq 0) {
869                 print "dropping BARCODE index to enable empty barcodes\n";
870                 $dbh->do("ALTER TABLE `items` DROP INDEX `barcode`");
871         }
872 }
873 $dbh->do("ALTER TABLE `items` CHANGE `barcode` `barcode` VARCHAR( 20 )") unless ($nullenabled{barcode} eq 'YES');
874
875 #
876 # creating fulltext index in bibliothesaurus if needed
877 #
878 $sth = $dbh->prepare("show index from bibliothesaurus");
879 $sth->execute;
880 my $exists=0;
881 while ( my ( $table, $non_unique, $key_name, $Seq_in_index, $Column_name, $Collation, $cardinality, $sub_part, $Packed, $comment ) = $sth->fetchrow )
882 {
883         if ($key_name eq 'category_2') {
884                 $exists=1;
885         }
886 }
887 print "Creating fulltext index on bibliothesaurus\n" unless $exists;
888 $dbh->do('create fulltext index category_2 on bibliothesaurus (category,freelib)') unless $exists;
889
890 #
891 # creating  index in z3950results if needed
892 #
893 $sth = $dbh->prepare("show index from z3950results");
894 $sth->execute;
895 my $exists=0;
896 while ( my ( $table, $non_unique, $key_name, $Seq_in_index, $Column_name, $Collation, $cardinality, $sub_part, $Packed, $comment ) = $sth->fetchrow )
897 {
898         if ($key_name eq 'query_server') {
899                 $exists=1;
900         }
901 }
902 print "Creating  index on z3950results\n" unless $exists;
903 $dbh->do('create unique index query_server on z3950results (queryid,server)') unless $exists;
904
905 # changing z3950daemon field to NULL in marc_breeding
906 $dbh->do("ALTER TABLE `marc_breeding` CHANGE `z3950random` `z3950random` VARCHAR( 40 )");
907
908 # making borrowernumber an auto_increment field
909 $dbh->do("ALTER TABLE `borrowers` CHANGE `borrowernumber` `borrowernumber` INTEGER auto_increment");
910
911 # extending the timestamp in branchtransfers...
912 my %branchtransfers;
913
914 $sth = $dbh->prepare("show columns from branchtransfers");
915 $sth->execute;
916 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
917 {
918     $branchtransfers{$column} = $type;
919 }
920
921 unless ( $branchtransfers{'datesent'} eq 'datetime' ) {
922     print "Setting type of datesent in branchtransfers to datetime.\n";
923     my $sti =
924       $dbh->prepare(
925         "alter table branchtransfers change datesent datesent datetime");
926     $sti->execute;
927 }
928
929 unless ( $branchtransfers{'datearrived'} eq 'datetime' ) {
930     print "Setting type of datearrived in branchtransfers to datetime.\n";
931     my $sti =
932       $dbh->prepare(
933         "alter table branchtransfers change datearrived datearrived datetime");
934     $sti->execute;
935 }
936
937 # changing the branchcategories table around...
938 my %branchcategories;
939
940 $sth = $dbh->prepare("show columns from branchcategories");
941 $sth->execute;
942 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
943 {
944     $branchcategories{$column} = $type;
945 }
946
947 unless ( $branchcategories{'categorycode'} eq 'varchar(4)' ) {
948     print
949 "Setting type of categorycode in branchcategories to varchar(4),\n and making the primary key.\n";
950     my $sti =
951       $dbh->prepare(
952 "alter table branchcategories change categorycode categorycode varchar(4) not null"
953     );
954     $sti->execute;
955     $sti =
956       $dbh->prepare(
957         "alter table branchcategories add primary key (categorycode)");
958     $sti->execute;
959 }
960
961 unless ( $branchcategories{'categoryname'} eq 'text' ) {
962     print "Changing branchcode in branchcategories to categoryname text.\n";
963     my $sth =
964       $dbh->prepare(
965         "alter table branchcategories change branchcode categoryname text");
966     $sth->execute;
967 }
968
969 unless ( $branchcategories{'codedescription'} eq 'text' ) {
970     print
971 "Replacing branchholding in branchcategories with codedescription text.\n";
972     my $sth =
973       $dbh->prepare(
974         "alter table branchcategories change branchholding codedescription text"
975     );
976     $sth->execute;
977 }
978
979 # changing the items table around...
980 my %items;
981
982 $sth = $dbh->prepare("show columns from items");
983 $sth->execute;
984 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
985 {
986     $items{$column} = $type;
987 }
988
989 if ($items{'bulk'} eq "varchar(30)") {
990     print "  Setting callnumber in items table\n";
991     my $sti =
992       $dbh->prepare("ALTER TABLE `items` CHANGE `bulk` `itemcallnumber` VARCHAR( 30 ) DEFAULT NULL");
993     $sti->execute;
994     $sti = $dbh->prepare("update marc_subfield_structure set kohafield=\"items.itemcallnumber\" where kohafield=\"items.bulk\"");
995     $sti->execute;
996 }
997
998 # Populate tables with required data
999
1000 foreach my $table ( keys %tabledata ) {
1001     print "Checking for data required in table $table...\n";
1002     my $tablerows = $tabledata{$table};
1003     foreach my $row (@$tablerows) {
1004         my $uniquefieldrequired = $row->{uniquefieldrequired};
1005         my $uniquevalue         = $row->{$uniquefieldrequired};
1006         my $forceupdate         = $row->{forceupdate};
1007         my $sth                 =
1008           $dbh->prepare(
1009 "select $uniquefieldrequired from $table where $uniquefieldrequired=?"
1010         );
1011         $sth->execute($uniquevalue);
1012         if ($sth->rows) {
1013             foreach my $field (keys %$forceupdate) {
1014                 if ($forceupdate->{$field}) {
1015                     my $sth=$dbh->prepare("update systempreferences set $field=? where $uniquefieldrequired=?");
1016                     $sth->execute($row->{$field}, $uniquevalue);
1017                 }
1018             }
1019         } else {
1020             print "Adding row to $table: ";
1021             my @values;
1022             my $fieldlist;
1023             my $placeholders;
1024             foreach my $field ( keys %$row ) {
1025                 next if $field eq 'uniquefieldrequired';
1026                 next if $field eq 'forceupdate';
1027                 my $value = $row->{$field};
1028                 push @values, $value;
1029                 print "  $field => $value";
1030                 $fieldlist .= "$field,";
1031                 $placeholders .= "?,";
1032             }
1033             print "\n";
1034             $fieldlist    =~ s/,$//;
1035             $placeholders =~ s/,$//;
1036             my $sth =
1037               $dbh->prepare(
1038                 "insert into $table ($fieldlist) values ($placeholders)");
1039             $sth->execute(@values);
1040         }
1041     }
1042 }
1043
1044 $sth->finish;
1045
1046 exit;
1047
1048 # $Log$
1049 # Revision 1.76  2004/05/03 09:32:25  tipaul
1050 # adding printcirculationsplit parameter (already existed, but was not in systempref by defaul)
1051 #
1052 # Revision 1.75  2004/04/14 19:49:00  tipaul
1053 # seealso field set to 255 chars
1054 #
1055 # Revision 1.74  2004/03/11 16:10:16  tipaul
1056 # *** empty log message ***
1057 #
1058 # Revision 1.73  2004/03/06 20:26:13  tipaul
1059 # adding seealso feature in MARC searches
1060 #