style sheet to hide styles from Netscape 4.7
[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 = 1;
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
42 #-------------------
43 # Defines
44
45 # Tables to add if they don't exist
46 my %requiretables = (
47     shelfcontents => "( shelfnumber int not null,
48                                                         itemnumber int not null,
49                                                         flags int)",
50     bookshelf => "( shelfnumber int auto_increment primary key,
51                                                 shelfname char(255))",
52     z3950queue => "( id int auto_increment primary key,
53                                                 term text,
54                                                 type char(10),
55                                                 startdate int,
56                                                 enddate int,
57                                                 done smallint,
58                                                 results longblob,
59                                                 numrecords int,
60                                                 servers text,
61                                                 identifier char(30))",
62     z3950results => "( id int auto_increment primary key,
63                                                 queryid int,
64                                                 server char(255),
65                                                 startdate int,
66                                                 enddate int,
67                                                 results longblob,
68                                                 numrecords int,
69                                                 numdownloaded int,
70                                                 highestseen int,
71                                                 active smallint)",
72     branchrelations => "( branchcode varchar(4),
73                                                         categorycode varchar(4))",
74     websites => "( websitenumber int(11) NOT NULL auto_increment,
75                                                 biblionumber int(11) NOT NULL default '0',
76                                                 title text,
77                                                 description text,
78                                                 url varchar(255),
79                                                 PRIMARY KEY (websitenumber) )",
80     marcrecorddone => "( isbn char(40),
81                                                                 issn char(40),
82                                                                 lccn char(40),
83                                                                 controlnumber char(40))",
84     uploadedmarc => "( id int(11) NOT NULL auto_increment PRIMARY KEY,
85                                                         marc longblob,
86                                                         hidden smallint(6) default NULL,
87                                                         name varchar(255) default NULL)",
88     ethnicity => "( code varchar(10) NOT NULL default '',
89                                         name varchar(255) default NULL,
90                                         PRIMARY KEY  (code)   )",
91     sessions => "( sessionID varchar(255) NOT NULL default '',
92                                                 userid varchar(255) default NULL,
93                                                 ip varchar(16) default NULL,
94                                                 lasttime int,
95                                                 PRIMARY KEY (sessionID)   )",
96     sessionqueries => "( sessionID varchar(255) NOT NULL default '',
97                                                                 userid char(100) NOT NULL default '',
98                                                                 ip char(18) NOT NULL default '',
99                                                                 url text NOT NULL default ''  )",
100     bibliothesaurus => "( id bigint(20) NOT NULL auto_increment,
101                                                         freelib char(255) NOT NULL default '',
102                                                         stdlib char(255) NOT NULL default '',
103                                                         category char(10) NOT NULL default '',
104                                                         level tinyint(4) NOT NULL default '1',
105                                                         hierarchy char(80) NOT NULL default '',
106                                                         father bigint(20) NOT NULL default '',
107                                                         PRIMARY KEY  (id),
108                                                         KEY freelib (freelib),
109                                                         KEY stdlib (stdlib),
110                                                         KEY category (category),
111                                                         KEY hierarchy (hierarchy)
112                                                         )",
113     marc_biblio => "(
114                                                 bibid bigint(20) unsigned NOT NULL auto_increment,
115                                                 biblionumber int(11) NOT NULL default '0',
116                                                 datecreated date NOT NULL default '0000-00-00',
117                                                 datemodified date default NULL,
118                                                 origincode char(20) default NULL,
119                                                 PRIMARY KEY  (bibid),
120                                                 KEY origincode (origincode),
121                                                 KEY biblionumber (biblionumber)
122                                                 ) ",
123     marc_blob_subfield => "(
124                                         blobidlink bigint(20) NOT NULL auto_increment,
125                                         subfieldvalue longtext NOT NULL,
126                                         PRIMARY KEY  (blobidlink)
127                                         ) ",
128     marc_subfield_structure => "(
129                                                 tagfield char(3) NOT NULL default '',
130                                                 tagsubfield char(1) NOT NULL default '',
131                                                 liblibrarian char(255) NOT NULL default '',
132                                                 libopac char(255) NOT NULL default '',
133                                                 repeatable tinyint(4) NOT NULL default '0',
134                                                 mandatory tinyint(4) NOT NULL default '0',
135                                                 kohafield char(40)  default NULL,
136                                                 tab tinyint(1) default NULL,
137                                                 authorised_value char(10) default NULL,
138                                                 thesaurus_category char(10) default NULL,
139                                                 value_builder char(80) default NULL,
140                                                 PRIMARY KEY  (tagfield,tagsubfield),
141                                                 KEY kohafield (kohafield),
142                                                 KEY tab (tab)
143                                                 )",
144     marc_subfield_table => "(
145                                                 subfieldid bigint(20) unsigned NOT NULL auto_increment,
146                                                 bibid bigint(20) unsigned NOT NULL default '0',
147                                                 tag char(3) NOT NULL default '',
148                                                 tagorder tinyint(4) NOT NULL default '1',
149                                                 tag_indicator char(2) NOT NULL default '',
150                                                 subfieldcode char(1) NOT NULL default '',
151                                                 subfieldorder tinyint(4) NOT NULL default '1',
152                                                 subfieldvalue varchar(255) default NULL,
153                                                 valuebloblink bigint(20) default NULL,
154                                                 PRIMARY KEY  (subfieldid),
155                                                 KEY bibid (bibid),
156                                                 KEY tag (tag),
157                                                 KEY tag_indicator (tag_indicator),
158                                                 KEY subfieldorder (subfieldorder),
159                                                 KEY subfieldcode (subfieldcode),
160                                                 KEY subfieldvalue (subfieldvalue),
161                                                 KEY tagorder (tagorder)
162                                         )",
163     marc_tag_structure => "(
164                                         tagfield char(3) NOT NULL default '',
165                                         liblibrarian char(255) NOT NULL default '',
166                                         libopac char(255) NOT NULL default '',
167                                         repeatable tinyint(4) NOT NULL default '0',
168                                         mandatory tinyint(4) NOT NULL default '0',
169                                         authorised_value char(10) default NULL,
170                                         PRIMARY KEY  (tagfield)
171                                         )",
172     marc_word => "(
173                                 bibid bigint(20) NOT NULL default '0',
174                                 tag char(3) NOT NULL default '',
175                                 tagorder tinyint(4) NOT NULL default '1',
176                                 subfieldid char(1) NOT NULL default '',
177                                 subfieldorder tinyint(4) NOT NULL default '1',
178                                 word varchar(255) NOT NULL default '',
179                                 sndx_word varchar(255) NOT NULL default '',
180                                 KEY bibid (bibid),
181                                 KEY tag (tag),
182                                 KEY tagorder (tagorder),
183                                 KEY subfieldid (subfieldid),
184                                 KEY subfieldorder (subfieldorder),
185                                 KEY word (word),
186                                 KEY sndx_word (sndx_word)
187                         )",
188     marc_breeding => "(  id bigint(20) NOT NULL auto_increment,
189                                 file varchar(80) NOT NULL default '',
190                                 isbn varchar(10) NOT NULL default '',
191                                 title varchar(128) default NULL,
192                                 author varchar(80) default NULL,
193                                 marc text NOT NULL,
194                                 encoding varchar(40) default NULL,
195                                 PRIMARY KEY  (id),
196                                 KEY title (title),
197                                 KEY isbn (isbn)
198                         )",
199     authorised_values => "(id int(11) NOT NULL auto_increment,
200                                 category char(10) NOT NULL default '',
201                                 authorised_value char(80) NOT NULL default '',
202                                 lib char(80) NULL,
203                                 PRIMARY KEY  (id),
204                                 KEY name (category)
205                         )",
206     userflags => "( bit int(11) NOT NULL default '0',
207                                 flag char(30), flagdesc char(255),
208                                 defaulton int(11)
209                         )",
210 );
211
212 my %requirefields = (
213     biblio        => { 'abstract' => 'text' },
214     deletedbiblio => { 'abstract' => 'text' },
215     biblioitems   => {
216         'lccn' => 'char(25)',
217         'url'  => 'varchar(255)',
218         'marc' => 'text'
219     },
220     deletedbiblioitems => {
221         'lccn' => 'char(25)',
222         'url'  => 'varchar(255)',
223         'marc' => 'text'
224     },
225     branchtransfers => { 'datearrived'    => 'datetime' },
226     statistics      => { 'borrowernumber' => 'int(11)' },
227     aqbooksellers   => {
228         'invoicedisc' => 'float(6,4)',
229         'nocalc'      => 'int(11)'
230     },
231     borrowers => {
232         'userid'        => 'char(30)',
233         'password'      => 'char(30)',
234         'flags'         => 'int(11)',
235         'textmessaging' => 'varchar(30)',
236            'zipcode' => 'varchar(25)',
237                         'homezipcode' => 'varchar(25)',
238     },
239     aqorders => { 'budgetdate' => 'date' },
240
241     #added so that reference items are not available for reserves...
242     itemtypes         => { 'notforloan'  => 'smallint(6)' },
243     systempreferences => { 'explanation' => 'char(80)',
244                            'type' => 'char(20)',
245                            'options' => 'text' },
246     z3950servers      => { 'syntax'      => 'char(80)' },
247 );
248
249 my %dropable_table = (
250     classification => 'classification',
251     multipart      => 'multipart',
252     multivolume    => 'multivolume',
253     newitems       => 'newitems',
254     procedures     => 'procedures',
255     publisher      => 'publisher',
256     searchstats    => 'searchstats',
257     serialissues   => 'serialissues',
258 );
259
260 # The tabledata hash contains data that should be in the tables.
261 # The uniquefieldrequired hash entry is used to determine which (if any) fields
262 # must not exist in the table for this row to be inserted.  If the
263 # uniquefieldrequired entry is already in the table, the existing data is not
264 # modified, unless the forceupdate hash entry is also set.  Fields in the
265 # anonymous "forceupdate" hash will be forced to be updated to the default
266 # values given in the %tabledata hash.
267
268 my %tabledata = (
269     userflags => [
270         {
271             uniquefieldrequired => 'bit',
272             bit                 => 0,
273             flag                => 'superlibrarian',
274             flagdesc            => 'Access to all librarian functions',
275             defaulton           => 0
276         },
277         {
278             uniquefieldrequired => 'bit',
279             bit                 => 1,
280             flag                => 'circulate',
281             flagdesc            => 'Circulate books',
282             defaulton           => 0
283         },
284         {
285             uniquefieldrequired => 'bit',
286             bit                 => 2,
287             flag                => 'catalogue',
288             flagdesc            => 'View Catalogue (Librarian Interface)',
289             defaulton           => 0
290         },
291         {
292             uniquefieldrequired => 'bit',
293             bit                 => 3,
294             flag                => 'parameters',
295             flagdesc            => 'Set Koha system paramters',
296             defaulton           => 0
297         },
298         {
299             uniquefieldrequired => 'bit',
300             bit                 => 4,
301             flag                => 'borrowers',
302             flagdesc            => 'Add or modify borrowers',
303             defaulton           => 0
304         },
305         {
306             uniquefieldrequired => 'bit',
307             bit                 => 5,
308             flag                => 'permissions',
309             flagdesc            => 'Set user permissions',
310             defaulton           => 0
311         },
312         {
313             uniquefieldrequired => 'bit',
314             bit                 => 6,
315             flag                => 'reserveforothers',
316             flagdesc            => 'Reserve books for patrons',
317             defaulton           => 0
318         },
319         {
320             uniquefieldrequired => 'bit',
321             bit                 => 7,
322             flag                => 'borrow',
323             flagdesc            => 'Borrow books',
324             defaulton           => 1
325         },
326         {
327             uniquefieldrequired => 'bit',
328             bit                 => 8,
329             flag                => 'reserveforself',
330             flagdesc            => 'Reserve books for self',
331             defaulton           => 0
332         },
333         {
334             uniquefieldrequired => 'bit',
335             bit                 => 9,
336             flag                => 'editcatalogue',
337             flagdesc  => 'Edit Catalogue (Modify bibliographic/holdings data)',
338             defaulton => 0
339         },
340         {
341             uniquefieldrequired => 'bit',
342             bit                 => 10,
343             flag                => 'updatecharges',
344             flagdesc            => 'Update borrower charges',
345             defaulton           => 0
346         },
347     ],
348     systempreferences => [
349         {
350             uniquefieldrequired => 'variable',
351             forceupdate         => { 'explanation' => 1,
352                                      'type' => 1 },
353             variable            => 'autoMemberNum',
354             value               => '1',
355             explanation         => 'Member number is auto-calculated',
356             type                => 'YesNo'
357
358         },
359         {
360             uniquefieldrequired => 'variable',
361             forceupdate         => { 'explanation' => 1,
362                                      'type' => 1,
363                                      'options' => 1 },
364             variable            => 'acquisitions',
365             value               => 'simple',
366             explanation         =>
367 'Normal, budget-based acquisitions, or Simple bibliographic-data acquisitions',
368             type                => 'Choice',
369             options             => 'simple|normal'
370         },
371         {
372             uniquefieldrequired => 'variable',
373             forceupdate         => { 'explanation' => 1,
374                                      'type' => 1,
375                                      'options' => 1 },
376             variable            => 'dateformat',
377             value               => 'metric',
378             explanation         =>
379             'date format (US mm/dd/yyyy, metric dd/mm/yyy, ISO yyyy/mm/dd)',
380             type                => 'Choice',
381             options             => 'metric|us|iso'
382         },
383         {
384             uniquefieldrequired => 'variable',
385             variable            => 'template',
386             forceupdate         => { 'explanation' => 1,
387                                      'type' => 1 },
388             value               => 'default',
389             explanation         => 'Preference order for intranet interface templates',
390             type                => 'Themes'
391         },
392         {
393             uniquefieldrequired => 'variable',
394             variable            => 'autoBarcode',
395             forceupdate         => { 'explanation' => 1,
396                                      'type' => 1 },
397             value               => 'yes',
398             explanation         => 'Barcode is auto-calculated',
399             type                => 'YesNo'
400         },
401         {
402             uniquefieldrequired => 'variable',
403             variable            => 'insecure',
404             forceupdate         => { 'explanation' => 1,
405                                      'type' => 1 },
406             value               => 'no',
407             explanation         =>
408 'If YES, no auth at all is needed. Be careful if you set this to yes!',
409             type                => 'YesNo'
410         },
411         {
412             uniquefieldrequired => 'variable',
413             variable            => 'authoritysep',
414             forceupdate         => { 'explanation' => 1,
415                                      'type' => 1,
416                                      'options' => 1 },
417             value               => '--',
418             explanation         =>
419             'the separator used in authority/thesaurus. Usually --',
420             type                => 'free',
421             options             => '10'
422         },
423         {
424             uniquefieldrequired => 'variable',
425             variable            => 'opaclanguages',
426             forceupdate         => { 'explanation' => 1,
427                                      'type' => 1 },
428             value               => 'en',
429             explanation         => 'Set the preferred order for translations.  The top language will be tried first.',
430             type                => 'Languages'
431         },
432         {
433             uniquefieldrequired => 'variable',
434             variable            => 'opacthemes',
435             forceupdate         => { 'explanation' => 1,
436                                      'type' => 1 },
437             value               => 'default',
438             explanation         => 'Set the preferred order for themes.  The top theme will be tried first.',
439             type                => 'Themes'
440         },
441         {
442             uniquefieldrequired => 'variable',
443             variable            => 'timeout',
444             forceupdate         => { 'explanation' => 1,
445                                      'type' => 1 },
446             value               => '1200',
447             explanation         => 'Inactivity timeout for cookies authentication (in seconds)',
448             type                => 'Integer'
449         },
450         {
451             uniquefieldrequired => 'variable',
452             variable            => 'marc',
453             forceupdate         => { 'explanation' => 1,
454                                      'type' => 1 },
455             value               => 'yes',
456             explanation         => 'Turn on MARC support',
457             type                => 'YesNo'
458         },
459         {
460             uniquefieldrequired => 'variable',
461             variable            => 'marcflavour',
462             forceupdate         => { 'explanation' => 1,
463                                      'type' => 1,
464                                      'options' => 1},
465             value               => 'MARC21',
466             explanation         =>
467             'your MARC flavor (MARC21 or UNIMARC) used for character encoding',
468             type                => 'Choice',
469             options             => 'MARC21|UNIMARC'
470         },
471         {
472             uniquefieldrequired => 'variable',
473             variable            => 'checkdigit',
474             value               => 'none',
475             forceupdate         => { 'explanation' => 1,
476                                      'type' => 1,
477                                      'options' => 1},
478             explanation         => 'Validity checks on membership number: none or "Katipo" style checks',
479             type                => 'Choice',
480             options             => 'none|katipo'
481         },
482         {
483             uniquefieldrequired => 'variable',
484             variable            => 'maxoutstanding',
485             forceupdate         => { 'explanation' => 1,
486                                      'type' => 1 },
487             value               => '5',
488             explanation         =>
489             'maximum amount withstanding to be able make reserves ',
490             type                => 'Integer'
491         },
492         {
493             uniquefieldrequired => 'variable',
494             variable            => 'maxreserves',
495             forceupdate         => { 'explanation' => 1,
496                                      'type' => 1 },
497             value               => '5',
498             explanation         =>
499             'maximum number of reserves a member can make',
500             type                => 'Integer'
501
502         },
503         {
504             uniquefieldrequired => 'variable',
505             variable            => 'noissuescharge',
506             forceupdate         => { 'explanation' => 1,
507                                      'type' => 1 },
508             value               => '5',
509             explanation         =>
510             'maximum amount withstanding to be able to check out an item',
511             type                => 'Integer'
512
513         },
514         {
515             uniquefieldrequired => 'variable',
516             variable            => 'KohaAdminEmailAddress',
517             forceupdate         => { 'explanation' => 1,
518                                      'type' => 1 },
519             value               => 'your.mail@here',
520             explanation => 'the email adress where borrowers modifs are sent',
521             type                => 'free'
522         },
523     ],
524
525 );
526
527 my %fielddefinitions = (
528     printers => [
529         {
530             field   => 'printername',
531             type    => 'char(40)',
532             null    => '',
533             key     => 'PRI',
534             default => ''
535         },
536     ],
537     aqbookfund => [
538         {
539             field   => 'bookfundid',
540             type    => 'char(5)',
541             null    => '',
542             key     => 'PRI',
543             default => ''
544         },
545     ],
546     z3950servers => [
547         {
548             field   => 'id',
549             type    => 'int',
550             null    => '',
551             key     => 'PRI',
552             default => '',
553             extra   => 'auto_increment'
554         },
555     ],
556 );
557
558 #-------------------
559 # Initialize
560
561 # Start checking
562
563 # Get version of MySQL database engine.
564 my $mysqlversion = `mysqld --version`;
565 $mysqlversion =~ /Ver (\S*) /;
566 $mysqlversion = $1;
567 if ( $mysqlversion ge '3.23' ) {
568     print "Could convert to MyISAM database tables...\n";
569 }
570
571 #---------------------------------
572 # Tables
573
574 # Collect all tables into a list
575 $sth = $dbh->prepare("show tables");
576 $sth->execute;
577 while ( my ($table) = $sth->fetchrow ) {
578     $existingtables{$table} = 1;
579 }
580
581 # Now add any missing tables
582 foreach $table ( keys %requiretables ) {
583     print "Checking $table table...\n" if $debug;
584     unless ( $existingtables{$table} ) {
585         print "Adding $table table...\n";
586         my $sth = $dbh->prepare("create table $table $requiretables{$table}");
587         $sth->execute;
588         if ( $sth->err ) {
589             print "Error : $sth->errstr \n";
590             $sth->finish;
591         }    # if error
592     }    # unless exists
593 }    # foreach
594
595 # now drop useless tables
596 foreach $table ( keys %dropable_table ) {
597     print "Dropping unused tables...\n" if $debug;
598     if ( $existingtables{$table} ) {
599         $dbh->do("drop table $table");
600         if ( $dbh->err ) {
601             print "Error : $dbh->errstr \n";
602         }
603     }
604 }
605 unless ( $existingtables{'z3950servers'} ) {
606     print "Adding z3950servers table...\n";
607     my $sti = $dbh->prepare( "create table z3950servers (
608                                                                                 host char(255),
609                                                                                 port int,
610                                                                                 db char(255),
611                                                                                 userid char(255),
612                                                                                 password char(255),
613                                                                                 name text,
614                                                                                 id int,
615                                                                                 checked smallint,
616                                                                                 rank int)"
617     );
618     $sti->execute;
619     $sti = $dbh->prepare( "insert into z3950servers
620                                                                 values ('z3950.loc.gov',
621                                                                 7090,
622                                                                 'voyager',
623                                                                 '', '',
624                                                                 'Library of Congress',
625                                                                 1, 1, 1)"
626     );
627     $sti->execute;
628 }
629
630 #---------------------------------
631 # Columns
632
633 foreach $table ( keys %requirefields ) {
634     print "Check table $table\n" if $debug;
635     $sth = $dbh->prepare("show columns from $table");
636     $sth->execute();
637     undef %types;
638     while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
639     {
640         $types{$column} = $type;
641     }    # while
642     foreach $column ( keys %{ $requirefields{$table} } ) {
643         print "  Check column $column  [$types{$column}]\n" if $debug;
644         if ( !$types{$column} ) {
645
646             # column doesn't exist
647             print "Adding $column field to $table table...\n";
648             $query = "alter table $table
649                         add column $column " . $requirefields{$table}->{$column};
650             print "Execute: $query\n" if $debug;
651             my $sti = $dbh->prepare($query);
652             $sti->execute;
653             if ( $sti->err ) {
654                 print "**Error : $sti->errstr \n";
655                 $sti->finish;
656             }    # if error
657         }    # if column
658     }    # foreach column
659 }    # foreach table
660
661 foreach $table ( keys %fielddefinitions ) {
662     print "Check table $table\n" if $debug;
663     $sth = $dbh->prepare("show columns from $table");
664     $sth->execute();
665     my $definitions;
666     while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
667     {
668         $definitions->{$column}->{type}    = $type;
669         $definitions->{$column}->{null}    = $null;
670         $definitions->{$column}->{key}     = $key;
671         $definitions->{$column}->{default} = $default;
672         $definitions->{$column}->{extra}   = $extra;
673     }    # while
674     my $fieldrow = $fielddefinitions{$table};
675     foreach my $row (@$fieldrow) {
676         my $field   = $row->{field};
677         my $type    = $row->{type};
678         my $null    = $row->{null};
679         my $key     = $row->{key};
680         my $default = $row->{default};
681         my $extra   = $row->{extra};
682         my $def     = $definitions->{$field};
683         unless ( $type eq $def->{type}
684             && $null eq $def->{null}
685             && $key eq $def->{key}
686             && $default eq $def->{default}
687             && $extra eq $def->{extra} )
688         {
689
690             if ( $null eq '' ) {
691                 $null = 'NOT NULL';
692             }
693             if ( $key eq 'PRI' ) {
694                 $key = 'PRIMARY KEY';
695             }
696             unless ( $extra eq 'auto_increment' ) {
697                 $extra = '';
698             }
699             my $sth =
700               $dbh->prepare(
701 "alter table $table change $field $field $type $null $key $extra default ?"
702             );
703             $sth->execute($default);
704             print "  Alter $field in $table\n";
705         }
706     }
707 }
708
709 # Get list of columns from items table
710 my %itemtypes;
711
712 $sth = $dbh->prepare("show columns from items");
713 $sth->execute;
714 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
715 {
716     $itemtypes{$column} = $type;
717 }
718
719 unless ( $itemtypes{'barcode'} eq 'varchar(20)' ) {
720     $itemtypes{'barcode'} =~ /varchar\((\d+)\)/;
721     my $oldlength = $1;
722     if ( $oldlength < 20 ) {
723         print "Setting maximum barcode length to 20 (was $oldlength).\n";
724         my $sti =
725           $dbh->prepare(
726             "alter table items change barcode barcode varchar(20) not null");
727         $sti->execute;
728     }
729 }
730
731 # extending the timestamp in branchtransfers...
732 my %branchtransfers;
733
734 $sth = $dbh->prepare("show columns from branchtransfers");
735 $sth->execute;
736 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
737 {
738     $branchtransfers{$column} = $type;
739 }
740
741 unless ( $branchtransfers{'datesent'} eq 'datetime' ) {
742     print "Setting type of datesent in branchtransfers to datetime.\n";
743     my $sti =
744       $dbh->prepare(
745         "alter table branchtransfers change datesent datesent datetime");
746     $sti->execute;
747 }
748
749 unless ( $branchtransfers{'datearrived'} eq 'datetime' ) {
750     print "Setting type of datearrived in branchtransfers to datetime.\n";
751     my $sti =
752       $dbh->prepare(
753         "alter table branchtransfers change datearrived datearrived datetime");
754     $sti->execute;
755 }
756
757 # changing the branchcategories table around...
758 my %branchcategories;
759
760 $sth = $dbh->prepare("show columns from branchcategories");
761 $sth->execute;
762 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
763 {
764     $branchcategories{$column} = $type;
765 }
766
767 unless ( $branchcategories{'categorycode'} eq 'varchar(4)' ) {
768     print
769 "Setting type of categorycode in branchcategories to varchar(4),\n and making the primary key.\n";
770     my $sti =
771       $dbh->prepare(
772 "alter table branchcategories change categorycode categorycode varchar(4) not null"
773     );
774     $sti->execute;
775     $sti =
776       $dbh->prepare(
777         "alter table branchcategories add primary key (categorycode)");
778     $sti->execute;
779 }
780
781 unless ( $branchcategories{'categoryname'} eq 'text' ) {
782     print "Changing branchcode in branchcategories to categoryname text.\n";
783     my $sth =
784       $dbh->prepare(
785         "alter table branchcategories change branchcode categoryname text");
786     $sth->execute;
787 }
788
789 unless ( $branchcategories{'codedescription'} eq 'text' ) {
790     print
791 "Replacing branchholding in branchcategories with codedescription text.\n";
792     my $sth =
793       $dbh->prepare(
794         "alter table branchcategories change branchholding codedescription text"
795     );
796     $sth->execute;
797 }
798
799 # Populate tables with required data
800
801 foreach my $table ( keys %tabledata ) {
802     print "Checking for data required in table $table...\n";
803     my $tablerows = $tabledata{$table};
804     foreach my $row (@$tablerows) {
805         my $uniquefieldrequired = $row->{uniquefieldrequired};
806         my $uniquevalue         = $row->{$uniquefieldrequired};
807         my $forceupdate         = $row->{forceupdate};
808         my $sth                 =
809           $dbh->prepare(
810 "select $uniquefieldrequired from $table where $uniquefieldrequired=?"
811         );
812         $sth->execute($uniquevalue);
813         if ($sth->rows) {
814             foreach my $field (keys %$forceupdate) {
815                 if ($forceupdate->{$field}) {
816                     my $sth=$dbh->prepare("update systempreferences set $field=? where $uniquefieldrequired=?");
817                     $sth->execute($row->{$field}, $uniquevalue);
818                 }
819             }
820         } else {
821             print "Adding row to $table: ";
822             my @values;
823             my $fieldlist;
824             my $placeholders;
825             foreach my $field ( keys %$row ) {
826                 next if $field eq 'uniquefieldrequired';
827                 next if $field eq 'forceupdate';
828                 my $value = $row->{$field};
829                 push @values, $value;
830                 print "  $field => $value";
831                 $fieldlist .= "$field,";
832                 $placeholders .= "?,";
833             }
834             print "\n";
835             $fieldlist    =~ s/,$//;
836             $placeholders =~ s/,$//;
837             my $sth =
838               $dbh->prepare(
839                 "insert into $table ($fieldlist) values ($placeholders)");
840             $sth->execute(@values);
841         }
842     }
843 }
844
845 $sth->finish;
846
847 exit;
848
849 # $Log$
850 # Revision 1.50  2003/06/11 21:28:22  tonnesen
851 # Added modifications required to the systempreferences table by the new
852 # systempreferences.pl script.  The systempreferences.pl script will not work
853 # properly until this table is updated.
854 #
855 # Revision 1.49  2003/05/26 10:41:53  tipaul
856 # bugfix : borrowers modifs overwritten by stupid hash entry existing twice.
857 #
858 # Revision 1.48  2003/05/20 19:50:45  slef
859 # Initial fix to bug 456: hardwired paths
860 #
861 # Revision 1.47  2003/05/15 12:23:33  tipaul
862 # adding zipcode and homezipcode into borrowers table (bug #246
863 #
864 # Revision 1.46  2003/05/08 12:48:24  wolfpac444
865 # Added "noissuescharge" parameter
866 #
867 # Revision 1.45  2003/05/08 12:26:16  wolfpac444
868 # Bug fixes
869 #
870 # Revision 1.44  2003/05/03 05:39:57  rangi
871 # Fixing bug 429
872 # (Wording changes in the explanation fields in system preferences)
873 #
874 # Revision 1.43  2003/05/02 23:01:09  rangi
875 # Adding the textmessaging column to the borrowers table.
876 # insertdata.pl is expecting this to exist, and hence modifying/adding
877 # borrowers was broken.
878 #
879 # Also ran they script thru perltidy
880 #
881 # Revision 1.42  2003/04/29 16:53:25  tipaul
882 # really proud of this commit :-)
883 # z3950 search and import seems to works fine.
884 # Let me explain how :
885 # * a "search z3950" button is added in the addbiblio template.
886 # * when clicked, a popup appears and z3950/search.pl is called
887 # * z3950/search.pl calls addz3950search in the DB
888 # * the z3950 daemon retrieve the records and stores them in z3950results AND in marc_breeding table.
889 # * as long as there as searches pending, the popup auto refresh every 2 seconds, and says how many searches are pending.
890 # * when the user clicks on a z3950 result => the parent popup is called with the requested biblio, and auto-filled
891 #
892 # Note :
893 # * character encoding support : (It's a nightmare...) In the z3950servers table, a "encoding" column has been added. You can put "UNIMARC" or "USMARC" in this column. Depending on this, the char_decode in C4::Biblio.pm replaces marc-char-encode by an iso 8859-1 encoding. Note that in the breeding import this value has been added too, for a better support.
894 # * the marc_breeding and z3950* tables have been modified : they have an encoding column and the random z3950 number is stored too for convenience => it's the key I use to list only requested biblios in the popup.
895 #
896 # Revision 1.41  2003/04/29 08:09:44  tipaul
897 # z3950 support is coming...
898 # * adding a syntax column in z3950 table = this column will say wether the z3950 must be called with PerferedRecordsyntax => USMARC or PerferedRecordsyntax => UNIMARC. I tried some french UNIMARC z3950 servers, and some only send USMARC, some only UNIMARC, some can answer with both.
899 # Note this is a 1st draft. More to follow (today ? I hope).
900 #
901 # Revision 1.40  2003/04/22 10:48:27  wolfpac444
902 # Added "father" column to bibliothesaurus table
903 #
904 # Revision 1.39  2003/04/04 08:45:00  tipaul
905 # last commits before 1.9.1
906 #
907 # Revision 1.38  2003/03/18 10:58:19  tipaul
908 # adding checkdigit parameter that choose how to check the members cardnumber.
909 # At the moment :
910 # * none = no checking
911 # * katipo = checked as before
912 #
913 # Revision 1.37  2003/01/30 01:47:48  acli
914 # Corrected syntax error reported by Benedict
915 #
916 # Made the indentation somewhat easier to read; the messiness probably caused
917 # the original syntax error.
918 #
919 # Revision 1.36  2003/01/28 15:13:30  tipaul
920 # userflag table now created in upgrade script (bugfix #171)
921 #
922 # Revision 1.35  2003/01/27 03:12:49  acli
923 # Reworded the description for "acquisitions" to make it fit on the screen
924 #
925 # Added "iso" to dateformat, since dateformat is not yet being used anyway
926 #
927 # Revision 1.34  2003/01/23 12:30:02  tipaul
928 # introducint marcflavour in systempref file : used for character decoding
929 #
930 # Revision 1.33  2003/01/21 09:03:27  tipaul
931 # bugfix (NOTE : this bugs makes installation of the 1.3.3 a little fuzzy. Please fix your DB if you installed 1.3.3)
932 #
933 # Revision 1.32  2003/01/16 10:29:45  tipaul
934 # adding a MARC parameter in systempref ( which is ON or OFF)
935 # the search will be a marc search if MARC=ON
936 # and a standard (v1.2) search if MARC=OFF
937 #
938 # Revision 1.31  2003/01/06 13:32:43  tipaul
939 # *** empty log message ***
940 #
941 # Revision 1.29  2003/01/06 11:14:11  tipaul
942 # last bugfixes before 1.3.3 : systempref table correctly filled
943 #
944 # Revision 1.28  2002/12/10 13:27:47  tipaul
945 # bugfixes (davide mails in koha-dev)
946 #
947 # Revision 1.27  2002/11/26 15:04:54  tipaul
948 # road to 1.3.2. Updating db structure during installation
949 #
950 # Revision 1.26  2002/11/12 17:42:40  tonnesen
951 # Merged some features over from rel-1-2, including primary key checking.
952 #
953 # Revision 1.25  2002/11/12 16:44:38  tipaul
954 # road to 1.3.2 :
955 # * many bugfixes
956 # * adding value_builder : you can map a subfield in the marc_subfield_structure to a sub stored in "value_builder" directory. In this directory you can create screen used to build values with any method. In this commit is a 1st draft of the builder for 100$a unimarc french subfield, which is composed of 35 digits, with 12 differents values (only the 4th first are provided for instance)
957 #
958 # Revision 1.24  2002/10/30 14:00:23  arensb
959 # (bug fix): Fixed typo.
960 #
961 # Revision 1.23  2002/10/25 10:55:46  tipaul
962 # Road to 1.3.2
963 # * bugfixes and improvements
964 # * manage mandatory MARC subfields
965 # * new table : authorised_values. this table contains categories and authorised values for the category. On MARC management, you can map a subfield to a authorised_values category. If you do this, the subfield can only be filled with a authorised_value of the selected category.
966 # this submit contains everything needed :
967 # * updatedatabase
968 # * admin screens
969 # * "links" management
970 # * creation of a html-list if a subfield is mapped to an authorised value.
971 #
972 # Note this is different from authorities support, which will come soon.
973 # The authorised_values is supposed to contains a "small" number of authorised values for a category (less than 50-100). If you enter more authorised values than this, it should be hard to find what you want in a BIG list...
974 #
975 # Revision 1.22  2002/10/15 10:08:19  tipaul
976 # fixme corrected, re-indent and adding the marc_breeding table (see commit of marcimport.pl for more explanations about breeding)
977 #
978 # Revision 1.21  2002/10/14 11:48:59  tipaul
979 # bugfix
980 #
981 # Revision 1.20  2002/10/10 04:49:41  arensb
982 # Added some FIXME comments.
983 #
984 # Revision 1.19  2002/10/05 10:17:17  arensb
985 # Merged with arensb-context branch: use C4::Context->dbh instead of
986 # &C4Connect, and generally prefer C4::Context over C4::Database.
987 #
988 # Revision 1.18.2.2  2002/10/05 06:18:43  arensb
989 # Added a whole mess of FIXME comments.
990 #
991 # Revision 1.18.2.1  2002/10/04 02:46:00  arensb
992 # Use C4::Connect instead of C4::Database, C4::Connect->dbh instead
993 # C4Connect.
994 #
995 # Revision 1.18  2002/09/24 13:50:55  tipaul
996 # long WAS the road to 1.3.0...
997 # coming VERY SOON NOW...
998 # modifying installer and buildrelease to update the DB
999 #
1000 # Revision 1.17  2002/09/24 12:57:35  tipaul
1001 # long WAS the road to 1.3.0...
1002 # coming VERY SOON NOW...
1003 # modifying installer and buildrelease to update the DB
1004 #
1005 # Revision 1.16  2002/07/31 02:34:27  finlayt
1006 #
1007 # added "notforloan" field to the itemtypes table.
1008 #
1009 # Revision 1.15  2002/07/20 22:30:06  rangi
1010 # Making sure fix makes it into the main branch as well
1011 # Fix for bug 69
1012 #
1013 # Revision 1.14  2002/07/08 16:20:26  tonnesen
1014 # Added sessionqueries table and password/userid fields to borrowers table
1015 #
1016 # Revision 1.13  2002/07/04 18:05:36  tonnesen
1017 # bug fix
1018 #
1019 # Revision 1.12  2002/07/04 16:41:06  tonnesen
1020 # Merged changes from rel-1-2.  Abstracted table structure changes by alan.
1021 #