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