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