*** 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_subfield_structure =>{'seealso'  => 'char(80)'},
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
573 );
574
575 my %fielddefinitions = (
576     printers => [
577         {
578             field   => 'printername',
579             type    => 'char(40)',
580             null    => '',
581             key     => 'PRI',
582             default => ''
583         },
584     ],
585     aqbookfund => [
586         {
587             field   => 'bookfundid',
588             type    => 'char(5)',
589             null    => '',
590             key     => 'PRI',
591             default => ''
592         },
593     ],
594     aqbudget => [
595         {
596             field   => 'aqbudgetid',
597             type    => 'tinyint(4)',
598             null    => '',
599             key     => 'PRI',
600                   default =>'',
601             extra => 'auto_increment'
602         },
603     ],
604     z3950servers => [
605         {
606             field   => 'id',
607             type    => 'int',
608             null    => '',
609             key     => 'PRI',
610             default => '',
611             extra   => 'auto_increment'
612         },
613     ],
614         marc_breeding => [
615         {
616             field   => 'z3950random',
617             type    => 'varchar(40)',
618             null    => 'NULL',
619             key     => '',
620             default => '',
621             extra   => ''
622         },
623         {
624             field   => 'encoding',
625             type    => 'varchar(40)',
626             null    => '',
627             key     => '',
628             default => '',
629             extra   => ''
630         },
631     ],
632 );
633
634 #-------------------
635 # Initialize
636
637 # Start checking
638
639 # Get version of MySQL database engine.
640 my $mysqlversion = `mysqld --version`;
641 $mysqlversion =~ /Ver (\S*) /;
642 $mysqlversion = $1;
643 if ( $mysqlversion ge '3.23' ) {
644     print "Could convert to MyISAM database tables...\n";
645 }
646
647 #---------------------------------
648 # Tables
649
650 # Collect all tables into a list
651 $sth = $dbh->prepare("show tables");
652 $sth->execute;
653 while ( my ($table) = $sth->fetchrow ) {
654     $existingtables{$table} = 1;
655 }
656
657
658 # Now add any missing tables
659 foreach $table ( keys %requiretables ) {
660     unless ( $existingtables{$table} ) {
661         print "Adding $table table...\n";
662         my $sth = $dbh->prepare("create table $table $requiretables{$table}");
663         $sth->execute;
664         if ( $sth->err ) {
665             print "Error : $sth->errstr \n";
666             $sth->finish;
667         }    # if error
668     }    # unless exists
669 }    # foreach
670
671 # now drop useless tables
672 foreach $table ( keys %dropable_table ) {
673         if ( $existingtables{$table} ) {
674                 print "Dropping unused table $table\n" if $debug;
675                 $dbh->do("drop table $table");
676                 if ( $dbh->err ) {
677                         print "Error : $dbh->errstr \n";
678                 }
679         }
680 }
681 unless ( $existingtables{'z3950servers'} ) {
682         #MJR: added syntax entries to close bug 624
683     print "Adding z3950servers table...\n";
684     my $sti = $dbh->prepare( "create table z3950servers (
685                                                                                 host char(255),
686                                                                                 port int,
687                                                                                 db char(255),
688                                                                                 userid char(255),
689                                                                                 password char(255),
690                                                                                 name text,
691                                                                                 id int,
692                                                                                 checked smallint,
693                                                                                 rank int,
694                                                                                 syntax char(80))"
695     );
696     $sti->execute;
697     $sti = $dbh->prepare( "insert into z3950servers
698                                                                 values ('z3950.loc.gov',
699                                                                 7090,
700                                                                 'voyager',
701                                                                 '', '',
702                                                                 'Library of Congress',
703                                                                 1, 1, 1, 'USMARC')"
704     );
705     $sti->execute;
706 }
707
708 #---------------------------------
709 # Columns
710
711 foreach $table ( keys %requirefields ) {
712     print "Check table $table\n" if $debug;
713     $sth = $dbh->prepare("show columns from $table");
714     $sth->execute();
715     undef %types;
716     while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
717     {
718         $types{$column} = $type;
719     }    # while
720     foreach $column ( keys %{ $requirefields{$table} } ) {
721         print "  Check column $column  [$types{$column}]\n" if $debug;
722         if ( !$types{$column} ) {
723
724             # column doesn't exist
725             print "Adding $column field to $table table...\n";
726             $query = "alter table $table
727                         add column $column " . $requirefields{$table}->{$column};
728             print "Execute: $query\n" if $debug;
729             my $sti = $dbh->prepare($query);
730             $sti->execute;
731             if ( $sti->err ) {
732                 print "**Error : $sti->errstr \n";
733                 $sti->finish;
734             }    # if error
735         }    # if column
736     }    # foreach column
737 }    # foreach table
738
739 foreach $table ( keys %fielddefinitions ) {
740         print "Check table $table\n" if $debug;
741         $sth = $dbh->prepare("show columns from $table");
742         $sth->execute();
743         my $definitions;
744         while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
745         {
746                 $definitions->{$column}->{type}    = $type;
747                 $definitions->{$column}->{null}    = $null;
748                 $definitions->{$column}->{key}     = $key;
749                 $definitions->{$column}->{default} = $default;
750                 $definitions->{$column}->{extra}   = $extra;
751         }    # while
752         my $fieldrow = $fielddefinitions{$table};
753         foreach my $row (@$fieldrow) {
754                 my $field   = $row->{field};
755                 my $type    = $row->{type};
756                 my $null    = $row->{null};
757                 my $key     = $row->{key};
758                 my $default = $row->{default};
759                 $default="''" unless $default;
760                 my $extra   = $row->{extra};
761                 my $def     = $definitions->{$field};
762                 unless ( $type eq $def->{type}
763                         && $null eq $def->{null}
764                         && $key eq $def->{key}
765                         && $default eq $def->{default}
766                         && $extra eq $def->{extra} )
767                 {
768
769                         if ( $null eq '' ) {
770                                 $null = 'NOT NULL';
771                         }
772                         if ( $key eq 'PRI' ) {
773                                 $key = 'PRIMARY KEY';
774                         }
775                         unless ( $extra eq 'auto_increment' ) {
776                                 $extra = '';
777                         }
778                         # if it's a new column use "add", if it's an old one, use "change".
779                         my $action;
780                         if ($definitions->{$field}->{type}) {
781                                 $action="change $field"
782                         } else {
783                                 $action="add";
784                         }
785 # if it's a primary key, drop the previous pk, before altering the table
786                         my $sth;
787                         if ($key ne 'PRIMARY KEY') {
788                                 $sth =$dbh->prepare("alter table $table $action $field $type $null $key $extra default ?");
789                         } else {
790                                 $sth =$dbh->prepare("alter table $table drop primary key, $action $field $type $null $key $extra default ?");
791                         }
792                         $sth->execute($default);
793                         print "  Alter $field in $table\n";
794                 }
795         }
796 }
797
798 # Get list of columns from borrowers table
799 my %itemtypes;
800 my %nullenabled;
801 $sth = $dbh->prepare("show columns from borrowers");
802 $sth->execute;
803 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
804 {
805     $itemtypes{$column} = $type;
806     $nullenabled{$column} = $null;
807 }
808
809 unless ( $itemtypes{'cardnumber'} eq 'varchar(20)' ) {
810     $itemtypes{'cardnumber'} =~ /varchar\((\d+)\)/;
811     my $oldlength = $1;
812     if ( $oldlength < 16 ) {
813         print "Setting maximum cardnumber length to 16 (was $oldlength) and marking unique.\n";
814         my $sti =
815           $dbh->prepare(
816             "alter table borrowers change cardnumber cardnumber varchar(16)");
817         $sti->execute;
818         $sti->finish;
819         $sti =
820           $dbh->prepare(
821             "alter table borrowers drop index cardnumber");
822         $sti->execute;
823         $sti->finish;
824         $sti =
825           $dbh->prepare(
826             "alter table borrowers add unique(cardnumber)");
827         $sti->execute;
828         $sti->finish;
829     }
830 }
831 #
832 # Get list of columns from items table
833 $sth = $dbh->prepare("show columns from items");
834 $sth->execute;
835 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
836 {
837     $itemtypes{$column} = $type;
838     $nullenabled{$column} = $null;
839 }
840
841 unless ( $itemtypes{'barcode'} eq 'varchar(20)' ) {
842     $itemtypes{'barcode'} =~ /varchar\((\d+)\)/;
843     my $oldlength = $1;
844     if ( $oldlength < 20 ) {
845         print "Setting maximum barcode length to 20 (was $oldlength).\n";
846         my $sti =
847           $dbh->prepare(
848             "alter table items change barcode barcode varchar(20)");
849         $sti->execute;
850     }
851 }
852 #
853 # dropping unique barcode index & setting barcode to null allowed.
854 #
855 $sth = $dbh->prepare("show index from items");
856 $sth->execute;
857 while ( my ( $table, $non_unique, $key_name, $Seq_in_index, $Column_name, $Collation, $cardinality, $sub_part, $Packed, $comment ) = $sth->fetchrow )
858 {
859         if ($key_name eq 'barcode' && $non_unique eq 0) {
860                 print "dropping BARCODE index to enable empty barcodes\n";
861                 $dbh->do("ALTER TABLE `items` DROP INDEX `barcode`");
862         }
863 }
864 $dbh->do("ALTER TABLE `items` CHANGE `barcode` `barcode` VARCHAR( 20 )") unless ($nullenabled{barcode} eq 'YES');
865
866 #
867 # creating fulltext index in bibliothesaurus if needed
868 #
869 $sth = $dbh->prepare("show index from bibliothesaurus");
870 $sth->execute;
871 my $exists=0;
872 while ( my ( $table, $non_unique, $key_name, $Seq_in_index, $Column_name, $Collation, $cardinality, $sub_part, $Packed, $comment ) = $sth->fetchrow )
873 {
874         if ($key_name eq 'category_2') {
875                 $exists=1;
876         }
877 }
878 print "Creating fulltext index on bibliothesaurus\n" unless $exists;
879 $dbh->do('create fulltext index category_2 on bibliothesaurus (category,freelib)') unless $exists;
880
881 #
882 # creating  index in z3950results if needed
883 #
884 $sth = $dbh->prepare("show index from z3950results");
885 $sth->execute;
886 my $exists=0;
887 while ( my ( $table, $non_unique, $key_name, $Seq_in_index, $Column_name, $Collation, $cardinality, $sub_part, $Packed, $comment ) = $sth->fetchrow )
888 {
889         if ($key_name eq 'query_server') {
890                 $exists=1;
891         }
892 }
893 print "Creating  index on z3950results\n" unless $exists;
894 $dbh->do('create unique index query_server on z3950results (queryid,server)') unless $exists;
895
896 # changing z3950daemon field to NULL in marc_breeding
897 $dbh->do("ALTER TABLE `marc_breeding` CHANGE `z3950random` `z3950random` VARCHAR( 40 )");
898
899 # making borrowernumber an auto_increment field
900 $dbh->do("ALTER TABLE `borrowers` CHANGE `borrowernumber` `borrowernumber` INTEGER auto_increment");
901
902 # extending the timestamp in branchtransfers...
903 my %branchtransfers;
904
905 $sth = $dbh->prepare("show columns from branchtransfers");
906 $sth->execute;
907 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
908 {
909     $branchtransfers{$column} = $type;
910 }
911
912 unless ( $branchtransfers{'datesent'} eq 'datetime' ) {
913     print "Setting type of datesent in branchtransfers to datetime.\n";
914     my $sti =
915       $dbh->prepare(
916         "alter table branchtransfers change datesent datesent datetime");
917     $sti->execute;
918 }
919
920 unless ( $branchtransfers{'datearrived'} eq 'datetime' ) {
921     print "Setting type of datearrived in branchtransfers to datetime.\n";
922     my $sti =
923       $dbh->prepare(
924         "alter table branchtransfers change datearrived datearrived datetime");
925     $sti->execute;
926 }
927
928 # changing the branchcategories table around...
929 my %branchcategories;
930
931 $sth = $dbh->prepare("show columns from branchcategories");
932 $sth->execute;
933 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
934 {
935     $branchcategories{$column} = $type;
936 }
937
938 unless ( $branchcategories{'categorycode'} eq 'varchar(4)' ) {
939     print
940 "Setting type of categorycode in branchcategories to varchar(4),\n and making the primary key.\n";
941     my $sti =
942       $dbh->prepare(
943 "alter table branchcategories change categorycode categorycode varchar(4) not null"
944     );
945     $sti->execute;
946     $sti =
947       $dbh->prepare(
948         "alter table branchcategories add primary key (categorycode)");
949     $sti->execute;
950 }
951
952 unless ( $branchcategories{'categoryname'} eq 'text' ) {
953     print "Changing branchcode in branchcategories to categoryname text.\n";
954     my $sth =
955       $dbh->prepare(
956         "alter table branchcategories change branchcode categoryname text");
957     $sth->execute;
958 }
959
960 unless ( $branchcategories{'codedescription'} eq 'text' ) {
961     print
962 "Replacing branchholding in branchcategories with codedescription text.\n";
963     my $sth =
964       $dbh->prepare(
965         "alter table branchcategories change branchholding codedescription text"
966     );
967     $sth->execute;
968 }
969
970 # Populate tables with required data
971
972 foreach my $table ( keys %tabledata ) {
973     print "Checking for data required in table $table...\n";
974     my $tablerows = $tabledata{$table};
975     foreach my $row (@$tablerows) {
976         my $uniquefieldrequired = $row->{uniquefieldrequired};
977         my $uniquevalue         = $row->{$uniquefieldrequired};
978         my $forceupdate         = $row->{forceupdate};
979         my $sth                 =
980           $dbh->prepare(
981 "select $uniquefieldrequired from $table where $uniquefieldrequired=?"
982         );
983         $sth->execute($uniquevalue);
984         if ($sth->rows) {
985             foreach my $field (keys %$forceupdate) {
986                 if ($forceupdate->{$field}) {
987                     my $sth=$dbh->prepare("update systempreferences set $field=? where $uniquefieldrequired=?");
988                     $sth->execute($row->{$field}, $uniquevalue);
989                 }
990             }
991         } else {
992             print "Adding row to $table: ";
993             my @values;
994             my $fieldlist;
995             my $placeholders;
996             foreach my $field ( keys %$row ) {
997                 next if $field eq 'uniquefieldrequired';
998                 next if $field eq 'forceupdate';
999                 my $value = $row->{$field};
1000                 push @values, $value;
1001                 print "  $field => $value";
1002                 $fieldlist .= "$field,";
1003                 $placeholders .= "?,";
1004             }
1005             print "\n";
1006             $fieldlist    =~ s/,$//;
1007             $placeholders =~ s/,$//;
1008             my $sth =
1009               $dbh->prepare(
1010                 "insert into $table ($fieldlist) values ($placeholders)");
1011             $sth->execute(@values);
1012         }
1013     }
1014 }
1015
1016 $sth->finish;
1017
1018 exit;
1019
1020 # $Log$
1021 # Revision 1.74  2004/03/11 16:10:16  tipaul
1022 # *** empty log message ***
1023 #
1024 # Revision 1.73  2004/03/06 20:26:13  tipaul
1025 # adding seealso feature in MARC searches
1026 #