Adding a log facility for actions watching.
[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 use lib "/usr/koha200pre2/modules";
16 use strict;
17
18 # CPAN modules
19 use DBI;
20 use Getopt::Long;
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 $silent;
41 GetOptions(
42         's' =>\$silent
43         );
44 my $dbh = C4::Context->dbh;
45 print "connected to your DB. Checking & modifying it\n" unless $silent;
46
47 #-------------------
48 # Defines
49
50 # Tables to add if they don't exist
51 my %requiretables = (
52     shelfcontents => "( shelfnumber int not null,
53                                                         itemnumber int not null,
54                                                         flags int)",
55     bookshelf => "( shelfnumber int auto_increment primary key,
56                                                 shelfname char(255))",
57     z3950queue => "( id int auto_increment primary key,
58                                                 term text,
59                                                 type char(10),
60                                                 startdate int,
61                                                 enddate int,
62                                                 done smallint,
63                                                 results longblob,
64                                                 numrecords int,
65                                                 servers text,
66                                                 identifier char(30))",
67     z3950results => "( id int auto_increment primary key,
68                                                 queryid int,
69                                                 server char(255),
70                                                 startdate int,
71                                                 enddate int,
72                                                 results longblob,
73                                                 numrecords int,
74                                                 numdownloaded int,
75                                                 highestseen int,
76                                                 active smallint)",
77     branchrelations => "( branchcode varchar(4),
78                                                         categorycode varchar(4))",
79     websites => "( websitenumber int(11) NOT NULL auto_increment,
80                                                 biblionumber int(11) NOT NULL default '0',
81                                                 title text,
82                                                 description text,
83                                                 url varchar(255),
84                                                 PRIMARY KEY (websitenumber) )",
85     marcrecorddone => "( isbn char(40),
86                                                                 issn char(40),
87                                                                 lccn char(40),
88                                                                 controlnumber char(40))",
89     uploadedmarc => "( id int(11) NOT NULL auto_increment PRIMARY KEY,
90                                                         marc longblob,
91                                                         hidden smallint(6) default NULL,
92                                                         name varchar(255) default NULL)",
93     ethnicity => "( code varchar(10) NOT NULL default '',
94                                         name varchar(255) default NULL,
95                                         PRIMARY KEY  (code)   )",
96     sessions => "( sessionID varchar(255) NOT NULL default '',
97                                                 userid varchar(255) default NULL,
98                                                 ip varchar(16) default NULL,
99                                                 lasttime int,
100                                                 PRIMARY KEY (sessionID)   )",
101     sessionqueries => "( sessionID varchar(255) NOT NULL default '',
102                                                                 userid char(100) NOT NULL default '',
103                                                                 ip char(18) NOT NULL default '',
104                                                                 url text NOT NULL default ''  )",
105     bibliothesaurus => "( id bigint(20) NOT NULL auto_increment,
106                                                         freelib char(255) NOT NULL default '',
107                                                         stdlib char(255) NOT NULL default '',
108                                                         category char(10) NOT NULL default '',
109                                                         level tinyint(4) NOT NULL default '1',
110                                                         hierarchy char(80) NOT NULL default '',
111                                                         father char(80) NOT NULL default '',
112                                                         PRIMARY KEY  (id),
113                                                         KEY freelib (freelib),
114                                                         KEY stdlib (stdlib),
115                                                         KEY category (category),
116                                                         KEY hierarchy (hierarchy)
117                                                         )",
118     marc_biblio => "(
119                                                 bibid bigint(20) unsigned NOT NULL auto_increment,
120                                                 biblionumber int(11) NOT NULL default '0',
121                                                 datecreated date NOT NULL default '0000-00-00',
122                                                 datemodified date default NULL,
123                                                 origincode char(20) default NULL,
124                                                 PRIMARY KEY  (bibid),
125                                                 KEY origincode (origincode),
126                                                 KEY biblionumber (biblionumber)
127                                                 ) ",
128     marc_blob_subfield => "(
129                                         blobidlink bigint(20) NOT NULL auto_increment,
130                                         subfieldvalue longtext NOT NULL,
131                                         PRIMARY KEY  (blobidlink)
132                                         ) ",
133     marc_subfield_structure => "(
134                                                 tagfield char(3) NOT NULL default '',
135                                                 tagsubfield char(1) NOT NULL default '',
136                                                 liblibrarian char(255) NOT NULL default '',
137                                                 libopac char(255) NOT NULL default '',
138                                                 repeatable tinyint(4) NOT NULL default '0',
139                                                 mandatory tinyint(4) NOT NULL default '0',
140                                                 kohafield char(40)  default NULL,
141                                                 tab tinyint(1) default NULL,
142                                                 authorised_value char(10) default NULL,
143                                                 thesaurus_category char(10) default NULL,
144                                                 value_builder char(80) default NULL,
145                                                 PRIMARY KEY  (tagfield,tagsubfield),
146                                                 KEY kohafield (kohafield),
147                                                 KEY tab (tab)
148                                                 )",
149     marc_subfield_table => "(
150                                                 subfieldid bigint(20) unsigned NOT NULL auto_increment,
151                                                 bibid bigint(20) unsigned NOT NULL default '0',
152                                                 tag char(3) NOT NULL default '',
153                                                 tagorder tinyint(4) NOT NULL default '1',
154                                                 tag_indicator char(2) NOT NULL default '',
155                                                 subfieldcode char(1) NOT NULL default '',
156                                                 subfieldorder tinyint(4) NOT NULL default '1',
157                                                 subfieldvalue varchar(255) default NULL,
158                                                 valuebloblink bigint(20) default NULL,
159                                                 PRIMARY KEY  (subfieldid),
160                                                 KEY bibid (bibid),
161                                                 KEY tag (tag),
162                                                 KEY tag_indicator (tag_indicator),
163                                                 KEY subfieldorder (subfieldorder),
164                                                 KEY subfieldcode (subfieldcode),
165                                                 KEY subfieldvalue (subfieldvalue),
166                                                 KEY tagorder (tagorder)
167                                         )",
168     marc_tag_structure => "(
169                                         tagfield char(3) NOT NULL default '',
170                                         liblibrarian char(255) NOT NULL default '',
171                                         libopac char(255) NOT NULL default '',
172                                         repeatable tinyint(4) NOT NULL default '0',
173                                         mandatory tinyint(4) NOT NULL default '0',
174                                         authorised_value char(10) default NULL,
175                                         PRIMARY KEY  (tagfield)
176                                         )",
177     marc_word => "(
178                                 bibid bigint(20) NOT NULL default '0',
179                                 tag char(3) NOT NULL default '',
180                                 tagorder tinyint(4) NOT NULL default '1',
181                                 subfieldid char(1) NOT NULL default '',
182                                 subfieldorder tinyint(4) NOT NULL default '1',
183                                 word varchar(255) NOT NULL default '',
184                                 sndx_word varchar(255) NOT NULL default '',
185                                 KEY bibid (bibid),
186                                 KEY tag (tag),
187                                 KEY tagorder (tagorder),
188                                 KEY subfieldid (subfieldid),
189                                 KEY subfieldorder (subfieldorder),
190                                 KEY word (word),
191                                 KEY sndx_word (sndx_word)
192                         )",
193     marc_breeding => "(  id bigint(20) NOT NULL auto_increment,
194                                 file varchar(80) NOT NULL default '',
195                                 isbn varchar(10) NOT NULL default '',
196                                 title varchar(128) default NULL,
197                                 author varchar(80) default NULL,
198                                 marc text NOT NULL,
199                                 encoding varchar(40) default NULL,
200                                 PRIMARY KEY  (id),
201                                 KEY title (title),
202                                 KEY isbn (isbn)
203                         )",
204     authorised_values => "(id int(11) NOT NULL auto_increment,
205                                 category char(10) NOT NULL default '',
206                                 authorised_value char(80) NOT NULL default '',
207                                 lib char(80) NULL,
208                                 PRIMARY KEY  (id),
209                                 KEY name (category)
210                         )",
211     userflags => "( bit int(11) NOT NULL default '0',
212                                 flag char(30), flagdesc char(255),
213                                 defaulton int(11)
214                         )",
215         auth_types => "(
216                                         authtypecode char(10) not NULL,
217                                         authtypetext char(255) not NULL,
218                                         auth_tag_to_report char(3) not NULL,
219                                         summary text not NULL,
220                                         PRIMARY KEY (authtypecode)
221                         )",
222         biblio_framework => "(
223                                         frameworkcode char(4) not NULL,
224                                         frameworktext char(255) not NULL,
225                                         PRIMARY KEY (frameworkcode)
226                         )",
227     auth_subfield_structure => "(
228                                         authtypecode char(10) NOT NULL default '',
229                                         tagfield char(3) NOT NULL default '',
230                                         tagsubfield char(1) NOT NULL default '',
231                                         liblibrarian char(255) NOT NULL default '',
232                                         libopac char(255) NOT NULL default '',
233                                         repeatable tinyint(4) NOT NULL default '0',
234                                         mandatory tinyint(4) NOT NULL default '0',
235                                         tab tinyint(1) default NULL,
236                                         authorised_value char(10) default NULL,
237                                         value_builder char(80) default NULL,
238                                         seealso char(255) default NULL,
239                                         PRIMARY KEY  (authtypecode,tagfield,tagsubfield),
240                                         KEY tab (authtypecode,tab)
241                                         )",
242     auth_tag_structure => "(
243                                         authtypecode char(10) NOT NULL default '',
244                                         tagfield char(3) NOT NULL default '',
245                                         liblibrarian char(255) NOT NULL default '',
246                                         libopac char(255) NOT NULL default '',
247                                         repeatable tinyint(4) NOT NULL default '0',
248                                         mandatory tinyint(4) NOT NULL default '0',
249                                         authorised_value char(10) default NULL,
250                                         PRIMARY KEY  (authtypecode,tagfield)
251                                         )",
252     auth_header => "(
253                                                 authid bigint(20) unsigned NOT NULL auto_increment,
254                                                 authtypecode char(10) NOT NULL default '',
255                                                 datecreated date NOT NULL default '0000-00-00',
256                                                 datemodified date default NULL,
257                                                 origincode char(20) default NULL,
258                                                 PRIMARY KEY  (authid),
259                                                 KEY origincode (origincode)
260                                                 ) ",
261     auth_subfield_table => "(
262                                                 subfieldid bigint(20) unsigned NOT NULL auto_increment,
263                                                 authid bigint(20) unsigned NOT NULL default '0',
264                                                 tag char(3) NOT NULL default '',
265                                                 tagorder tinyint(4) NOT NULL default '1',
266                                                 tag_indicator char(2) NOT NULL default '',
267                                                 subfieldcode char(1) NOT NULL default '',
268                                                 subfieldorder tinyint(4) NOT NULL default '1',
269                                                 subfieldvalue varchar(255) default NULL,
270                                                 PRIMARY KEY  (subfieldid),
271                                                 KEY authid (authid),
272                                                 KEY tag (tag),
273                                                 KEY subfieldcode (subfieldcode),
274                                                 KEY subfieldvalue (subfieldvalue)
275                                         )",
276     auth_word => "(
277                                 authid bigint(20) NOT NULL default '0',
278                                 tagsubfield char(4) NOT NULL default '',
279                                 tagorder tinyint(4) NOT NULL default '1',
280                                 subfieldorder tinyint(4) NOT NULL default '1',
281                                 word varchar(255) NOT NULL default '',
282                                 sndx_word varchar(255) NOT NULL default '',
283                                 KEY authid (authid),
284                                 KEY marc_search (tagsubfield,word),
285                                 KEY word (word),
286                                 KEY sndx_word (sndx_word)
287                         )",
288         suggestions => "(
289                                 suggestionid int(8) NOT NULL auto_increment,
290                                 suggestedby int(11) NOT NULL default '0',
291                                 managedby int(11) default NULL ,
292                                 STATUS varchar(10) NOT NULL default '',
293                                 note text,
294                                 author varchar(80) default NULL ,
295                                 title varchar(80) default NULL ,
296                                 copyrightdate smallint(6) default NULL ,
297                                 publishercode varchar(255) default NULL ,
298                                 date timestamp(8) NOT NULL ,
299                                 volumedesc varchar(255) default NULL ,
300                                 publicationyear smallint(6) default '0',
301                                 place varchar(255) default NULL ,
302                                 isbn varchar(10) default NULL ,
303                                 mailoverseeing smallint(1) default '0',
304                                 biblionumber int(11) default NULL ,
305                                 PRIMARY KEY (suggestionid) ,
306                                 KEY suggestedby(suggestedby) ,
307                                 KEY managedby(managedby)
308                         )",
309         aqbasket => "(basketno int(11) NOT NULL auto_increment,
310                                 creationdate date,
311                                 closedate date,
312                                 booksellerid varchar(10),
313                                 authorisedby varchar(10),
314                                 booksellerinvoicenumber text,
315                                 PRIMARY KEY (basketno)
316                                 )",
317         serial => "(serialid int(11) NOT NULL auto_increment,
318                                 biblionumber varchar(100) NOT NULL default '',
319                                 subscriptionid varchar(100) NOT NULL default '',
320                                 serialseq varchar(100) NOT NULL default '',
321                                 status tinyint(4) NOT NULL default '0',
322                                 planneddate date NOT NULL default '0000-00-00',
323                                 PRIMARY KEY  (serialid)
324                                 )",
325         subscription => "(biblionumber int(11) NOT NULL default '0',
326                                                 subscriptionid int(11) NOT NULL auto_increment,
327                                                 librarian varchar(100) default '',
328                                                 startdate date default '0000-00-00',
329                                                 aqbooksellerid int(11) default '0',
330                                                 cost int(11) default '0',
331                                                 aqbudgetid int(11) default '0',
332                                                 weeklength tinyint(4) default '0',
333                                                 monthlength tinyint(4) default '0',
334                                                 numberlength tinyint(4) default '0',
335                                                 periodicity tinyint(4) default '0',
336                                                 dow varchar(100) default '',
337                                                 numberingmethod varchar(100) default '',
338                                                 notes text,
339                                                 status varchar(100) NOT NULL default '',
340                                                 add1 int(11) default 0,
341                                                 every1 int(11) default 0,
342                                                 whenmorethan1 int(11) default 0,
343                                                 setto1 int(11),
344                                                 lastvalue1 int(11),
345                                                 add2 int(11) default 0,
346                                                 every2 int(11) default 0,
347                                                 whenmorethan2 int(11) default 0,
348                                                 setto2 int(11),
349                                                 lastvalue2 int(11),
350                                                 add3 int(11) default 0,
351                                                 every3 int(11) default 0,
352                                                 innerloop1 int(11) default 0,
353                                                 innerloop2 int(11) default 0,
354                                                 innerloop3 int(11) default 0,
355                                                 whenmorethan3 int(11) default 0,
356                                                 setto3 int(11),
357                                                 lastvalue3 int(11),
358                                                 PRIMARY KEY  (subscriptionid)
359                                                 )",
360         subscriptionhistory => "(biblionumber int(11) NOT NULL default '0',
361                                                         subscriptionid int(11) NOT NULL default '0',
362                                                         histstartdate date NOT NULL default '0000-00-00',
363                                                         enddate date default '0000-00-00',
364                                                         missinglist longtext NOT NULL,
365                                                         recievedlist longtext NOT NULL,
366                                                         opacnote varchar(150) NOT NULL default '',
367                                                         librariannote varchar(150) NOT NULL default '',
368                                                         PRIMARY KEY  (subscriptionid),
369                                                         KEY biblionumber (biblionumber)
370                                                 )",
371     categorytable       => "(categorycode char(5) NOT NULL default '',
372                              description text default '',
373                              itemtypecodes text default '',
374                              PRIMARY KEY (categorycode)
375                             )",
376     subcategorytable       => "(subcategorycode char(5) NOT NULL default '',
377                              description text default '',
378                              itemtypecodes text default '',
379                              PRIMARY KEY (subcategorycode)
380                             )",
381     mediatypetable       => "(mediatypecode char(5) NOT NULL default '',
382                              description text default '',
383                              itemtypecodes text default '',
384                              PRIMARY KEY (mediatypecode)
385                             )",
386     `action_logs`       => "(
387                                     `timestamp` TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL ,
388                                     `user` INT( 11 ) NOT NULL ,
389                                     `module` TEXT default '',
390                                     `action` TEXT default '' ,
391                                     `info` TEXT default '' ,
392                                     PRIMARY KEY ( `timestamp` , `user` )
393                             )",
394 );
395
396 my %requirefields = (
397     biblio        => { 'abstract' => 'text' },
398     deletedbiblio => { 'abstract' => 'text', 'marc' => 'blob' },
399     deleteditems => { 'marc' => 'blob', 'paidfor' => 'text', 'location' => 'varchar(80)'},
400     biblioitems   => {
401         'lccn' => 'char(25)',
402         'url'  => 'varchar(255)',
403         'marc' => 'text'
404     },
405     deletedbiblioitems => {
406         'lccn' => 'char(25)',
407         'url'  => 'varchar(255)',
408         'marc' => 'text'
409     },
410     branchtransfers => { 'datearrived'    => 'datetime' },
411     statistics      => { 'borrowernumber' => 'int(11)' },
412     aqbooksellers   => {
413         'invoicedisc' => 'float(6,4)',
414         'nocalc'      => 'int(11)'
415     },
416     borrowers => {
417                 'userid'        => 'char(30)',
418                 'password'      => 'char(30)',
419                 'flags'         => 'int(11)',
420                 'textmessaging' => 'varchar(30)',
421                 'zipcode' => 'varchar(25)',
422                 'homezipcode' => 'varchar(25)',
423                 'sort1' => 'char(80)',
424                 'sort2' => 'char(80)',
425     },
426     aqorders => { 'budgetdate' => 'date',
427                                 'sort1' => 'char(80)',
428                                 'sort2' => 'char(80)', },
429     aqbookfund =>{'branchcode'=> 'varchar(4) NULL'},
430     aqbudget => {'aqbudgetid' => 'tinyint(4) auto_increment primary key', 'branchcode'=> 'varchar(4) NULL'},
431     items => {'paidfor' => 'text', 'location' => 'char(80)'},
432
433     #added so that reference items are not available for reserves...
434     itemtypes         => { 'notforloan'  => 'smallint(6)' },
435     systempreferences => { 'explanation' => 'char(80)',
436                            'type' => 'char(20)',
437                            'options' => 'text' },
438     z3950servers      => { 'syntax'      => 'char(80)' },
439         marc_tag_structure =>{
440                                                         'frameworkcode' => 'char(4) not NULL default \'\''},
441     marc_subfield_structure =>{'seealso'  => 'char(255)',
442                                                         'frameworkcode' => 'char(4) not NULL default \'\'',
443                                                         'hidden' => 'tinyint(1)',
444                                                         'isurl' => 'tinyint(1)',
445                                                         'link' => 'char(80)',
446                                                         },
447     bookshelf => {'owner' => 'char(80)',
448                                         'category' => 'char(1)',
449                                 },
450     marc_biblio        => { 'frameworkcode' => 'char(4) not NULL default \'\'' },
451 );
452
453 my %dropable_table = (
454     classification => 'classification',
455     multipart      => 'multipart',
456     multivolume    => 'multivolume',
457     newitems       => 'newitems',
458     procedures     => 'procedures',
459     publisher      => 'publisher',
460     searchstats    => 'searchstats',
461     serialissues   => 'serialissues',
462 );
463
464 my %uselessfields = (
465         aqorders => "requisitionedby,authorisedby,booksellerid,
466                         deliverydays,followupdays,
467                         numberfollowupsallowed,numberfollowupssent,
468                         dateprinted,sourced,quantityreceiveddamaged,
469                         subscriptionfrom,subscriptionto
470                         "
471         );
472 # the other hash contains other actions that can't be done elsewhere. they are done
473 # either BEFORE of AFTER everything else, depending on "when" entry (default => AFTER)
474
475 # The tabledata hash contains data that should be in the tables.
476 # The uniquefieldrequired hash entry is used to determine which (if any) fields
477 # must not exist in the table for this row to be inserted.  If the
478 # uniquefieldrequired entry is already in the table, the existing data is not
479 # modified, unless the forceupdate hash entry is also set.  Fields in the
480 # anonymous "forceupdate" hash will be forced to be updated to the default
481 # values given in the %tabledata hash.
482
483 my %tabledata = (
484     userflags => [
485         {
486             uniquefieldrequired => 'bit',
487             bit                 => 0,
488             flag                => 'superlibrarian',
489             flagdesc            => 'Access to all librarian functions',
490             defaulton           => 0
491         },
492         {
493             uniquefieldrequired => 'bit',
494             bit                 => 1,
495             flag                => 'circulate',
496             flagdesc            => 'Circulate books',
497             defaulton           => 0
498         },
499         {
500             uniquefieldrequired => 'bit',
501             bit                 => 2,
502             flag                => 'catalogue',
503             flagdesc            => 'View Catalogue (Librarian Interface)',
504             defaulton           => 0
505         },
506         {
507             uniquefieldrequired => 'bit',
508             bit                 => 3,
509             flag                => 'parameters',
510             flagdesc            => 'Set Koha system paramters',
511             defaulton           => 0
512         },
513         {
514             uniquefieldrequired => 'bit',
515             bit                 => 4,
516             flag                => 'borrowers',
517             flagdesc            => 'Add or modify borrowers',
518             defaulton           => 0
519         },
520         {
521             uniquefieldrequired => 'bit',
522             bit                 => 5,
523             flag                => 'permissions',
524             flagdesc            => 'Set user permissions',
525             defaulton           => 0
526         },
527         {
528             uniquefieldrequired => 'bit',
529             bit                 => 6,
530             flag                => 'reserveforothers',
531             flagdesc            => 'Reserve books for patrons',
532             defaulton           => 0
533         },
534         {
535             uniquefieldrequired => 'bit',
536             bit                 => 7,
537             flag                => 'borrow',
538             flagdesc            => 'Borrow books',
539             defaulton           => 1
540         },
541         {
542             uniquefieldrequired => 'bit',
543             bit                 => 8,
544             flag                => 'reserveforself',
545             flagdesc            => 'Reserve books for self',
546             defaulton           => 0
547         },
548         {
549             uniquefieldrequired => 'bit',
550             bit                 => 9,
551             flag                => 'editcatalogue',
552             flagdesc  => 'Edit Catalogue (Modify bibliographic/holdings data)',
553             defaulton => 0
554         },
555         {
556             uniquefieldrequired => 'bit',
557             bit                 => 10,
558             flag                => 'updatecharges',
559             flagdesc            => 'Update borrower charges',
560             defaulton           => 0
561         },
562         {
563             uniquefieldrequired => 'bit',
564             bit                 => 11,
565             flag                => 'acquisition',
566             flagdesc            => 'Acquisition and/or suggestion management',
567             defaulton           => 0
568         },
569         {
570             uniquefieldrequired => 'bit',
571             bit                 => 12,
572             flag                => 'management',
573             flagdesc            => 'Set library management parameters',
574             defaulton           => 0
575         },
576         {
577             uniquefieldrequired => 'bit',
578             bit                 => 13,
579             flag                => 'tools',
580             flagdesc            => 'Use tools (export, import, barcodes)',
581             defaulton           => 0
582         },        
583     ],
584     systempreferences => [
585         {
586             uniquefieldrequired => 'variable',
587             forceupdate         => { 'explanation' => 1,
588                                      'type' => 1 },
589             variable            => 'LibraryName',
590             value               => '<i><b>Koha<br/>Free Software ILS<br/><br/></b>Koha : a gift, a contribution<br/> in Maori</i>',
591             explanation         => 'Library name as shown on main opac page',
592             type                => ''
593
594         },
595         {
596             uniquefieldrequired => 'variable',
597             forceupdate         => { 'explanation' => 1,
598                                      'type' => 1 },
599             variable            => 'autoMemberNum',
600             value               => '1',
601             explanation         => 'Member number is auto-calculated',
602             type                => 'YesNo'
603
604         },
605         {
606             uniquefieldrequired => 'variable',
607             forceupdate         => { 'explanation' => 1,
608                                      'type' => 1,
609                                      'options' => 1 },
610             variable            => 'acquisitions',
611             value               => 'normal',
612             explanation         =>
613 'Normal, budget-based acquisitions, or Simple bibliographic-data acquisitions',
614             type                => 'Choice',
615             options             => 'simple|normal'
616         },
617         {
618             uniquefieldrequired => 'variable',
619             forceupdate         => { 'explanation' => 1,
620                                      'type' => 1,
621                                      'options' => 1 },
622             variable            => 'dateformat',
623             value               => 'metric',
624             explanation         =>
625             'date format (us mm/dd/yyyy, metric dd/mm/yyy, ISO yyyy/mm/dd)',
626             type                => 'Choice',
627             options             => 'metric|us|iso'
628         },
629         {
630             uniquefieldrequired => 'variable',
631             variable            => 'template',
632             forceupdate         => { 'explanation' => 1,
633                                      'type' => 1 },
634             value               => 'default',
635             explanation         => 'Preference order for intranet interface templates',
636             type                => 'Themes'
637         },
638         {
639             uniquefieldrequired => 'variable',
640             variable            => 'autoBarcode',
641             forceupdate         => { 'explanation' => 1,
642                                      'type' => 1 },
643             value               => 'yes',
644             explanation         => 'Barcode is auto-calculated',
645             type                => 'YesNo'
646         },
647         {
648             uniquefieldrequired => 'variable',
649             variable            => 'insecure',
650             forceupdate         => { 'explanation' => 1,
651                                      'type' => 1 },
652             value               => 'no',
653             explanation         =>
654 'If YES, no auth at all is needed. Be careful if you set this to yes!',
655             type                => 'YesNo'
656         },
657         {
658             uniquefieldrequired => 'variable',
659             variable            => 'authoritysep',
660             forceupdate         => { 'explanation' => 1,
661                                      'type' => 1,
662                                      'options' => 1 },
663             value               => '--',
664             explanation         =>
665             'the separator used in authority/thesaurus. Usually --',
666             type                => 'free',
667             options             => '10'
668         },
669         {
670             uniquefieldrequired => 'variable',
671             variable            => 'opaclanguages',
672             forceupdate         => { 'explanation' => 1,
673                                      'type' => 1 },
674             value               => 'en',
675             explanation         => 'Set the preferred order for translations.  The top language will be tried first.',
676             type                => 'Languages'
677         },
678         {
679             uniquefieldrequired => 'variable',
680             variable            => 'opacthemes',
681             forceupdate         => { 'explanation' => 1,
682                                      'type' => 1 },
683             value               => 'css',
684             explanation         => 'Set the preferred order for themes.  The top theme will be tried first.',
685             type                => 'Themes'
686         },
687         {
688             uniquefieldrequired => 'variable',
689             variable            => 'timeout',
690             forceupdate         => { 'explanation' => 1,
691                                      'type' => 1 },
692             value               => '1200',
693             explanation         => 'Inactivity timeout for cookies authentication (in seconds)',
694             type                => 'Integer'
695         },
696         {
697             uniquefieldrequired => 'variable',
698             variable            => 'marc',
699             forceupdate         => { 'explanation' => 1,
700                                      'type' => 1 },
701             value               => 'yes',
702             explanation         => 'Turn on MARC support',
703             type                => 'YesNo'
704         },
705         {
706             uniquefieldrequired => 'variable',
707             variable            => 'marcflavour',
708             forceupdate         => { 'explanation' => 1,
709                                      'type' => 1,
710                                      'options' => 1},
711             value               => 'MARC21',
712             explanation         =>
713             'your MARC flavor (MARC21 or UNIMARC) used for character encoding',
714             type                => 'Choice',
715             options             => 'MARC21|UNIMARC'
716         },
717         {
718             uniquefieldrequired => 'variable',
719             variable            => 'checkdigit',
720             value               => 'none',
721             forceupdate         => { 'explanation' => 1,
722                                      'type' => 1,
723                                      'options' => 1},
724             explanation         => 'Validity checks on membership number: none or "Katipo" style checks',
725             type                => 'Choice',
726             options             => 'none|katipo'
727         },
728         {
729             uniquefieldrequired => 'variable',
730             variable            => 'maxoutstanding',
731             forceupdate         => { 'explanation' => 1,
732                                      'type' => 1 },
733             value               => '5',
734             explanation         =>
735             'maximum amount withstanding to be able make reserves ',
736             type                => 'Integer'
737         },
738         {
739             uniquefieldrequired => 'variable',
740             variable            => 'maxreserves',
741             forceupdate         => { 'explanation' => 1,
742                                      'type' => 1 },
743             value               => '5',
744             explanation         =>
745             'maximum number of reserves a member can make',
746             type                => 'Integer'
747
748         },
749         {
750             uniquefieldrequired => 'variable',
751             variable            => 'noissuescharge',
752             forceupdate         => { 'explanation' => 1,
753                                      'type' => 1 },
754             value               => '5',
755             explanation         =>
756             'maximum amount withstanding to be able to check out an item',
757             type                => 'Integer'
758
759         },
760         {
761             uniquefieldrequired => 'variable',
762             variable            => 'KohaAdminEmailAddress',
763             forceupdate         => { 'explanation' => 1,
764                                      'type' => 1 },
765             value               => 'your.mail@here',
766             explanation => 'the email address where borrowers modifs are sent',
767             type                => 'free'
768         },
769         {
770             uniquefieldrequired => 'variable',
771             variable            => 'gist',
772             forceupdate         => { 'explanation' => 1,
773                                      'type' => 1 },
774             value               => '0.125',
775             explanation => 'the gist rate. NOT in %, but in numeric form (0.12 for 12%)',
776             type                => 'free'
777         },
778         {
779             uniquefieldrequired => 'variable',
780             variable            => 'printcirculationslips',
781             forceupdate         => { 'explanation' => 1,
782                                      'type' => 1 },
783             value               => '0',
784             explanation => 'if set to 1, print circulation slips. If set to 0, don\'t',
785             type                => 'free'
786         },
787         {
788             uniquefieldrequired => 'variable',
789             variable            => 'suggestion',
790             forceupdate         => { 'explanation' => 1,
791                                      'type' => 1 },
792             value               => '0',
793             explanation => 'if set to 1, suggestions are activated in OPAC',
794             type                => 'free'
795         },
796         {
797             uniquefieldrequired => 'variable',
798             variable            => 'ISBD',
799             forceupdate         => { 'explanation' => 1,
800                                      'type' => 1 },
801             value               => 'Fill with appropriate value...',
802             explanation => 'ISBD',
803             type                => 'free'
804         },
805         {
806             uniquefieldrequired => 'variable',
807             variable            => 'virtualshelves',
808             forceupdate         => { 'explanation' => 1,
809                                      'type' => 1 },
810             value               => '0',
811             explanation => 'Set virtual shelves management ON or OFF',
812             type                => 'YesNo'
813         },
814         {
815             uniquefieldrequired => 'variable',
816             variable            => 'itemcallnumber',
817             forceupdate         => { 'explanation' => 1,
818                                      'type' => 1 },
819             value               => '676a',
820             explanation => 'The MARC field/subfield that is used to calculate the itemcallnumber (in UNIMARC : 676a for Dewey, 680a for Loc)',
821             type                => 'free'
822         },
823         {
824             uniquefieldrequired => 'variable',
825             variable            => 'BiblioDefaultView',
826             value               => 'normal',
827             forceupdate         => { 'explanation' => 1,
828                                      'type' => 1,
829                                      'options' => 1},
830             explanation         => 'Define the default view of a biblio. Can be either normal, marc or isbd',
831             type                => 'Choice',
832             options             => 'normal|marc|isbd'
833         },
834         {
835             uniquefieldrequired => 'variable',
836             variable            => 'opacstylesheet',
837             value               => '',
838             forceupdate         => { 'explanation' => 1,
839                                      'type' => 1},
840             explanation         => 'Enter a complete URL to use an alternate stylesheet in OPAC',
841             type                => 'free',
842         },
843         {
844             uniquefieldrequired => 'variable',
845             variable            => 'opacsmallimage',
846             value               => '',
847             forceupdate         => { 'explanation' => 1,
848                                      'type' => 1},
849             explanation         => 'Enter a complete URL to an image, will be on top/left instead of the Koha logo',
850             type                => 'free',
851         },
852         {
853             uniquefieldrequired => 'variable',
854             variable            => 'opaclargeimage',
855             value               => '',
856             forceupdate         => { 'explanation' => 1,
857                                      'type' => 1},
858             explanation         => 'Enter a complete URL to an image, will be on the main page, instead of the Koha logo',
859             type                => 'free',
860         },
861         {
862             uniquefieldrequired => 'variable',
863             variable            => 'delimiter',
864             value               => ';',
865             forceupdate         => { 'explanation' => 1,
866                                      'type' => 1},
867             explanation         => 'separator for reports exported to spreadsheet',
868             type                => 'free',
869         },
870         {
871             uniquefieldrequired => 'variable',
872             variable            => 'MIME',
873             value               => 'OPENOFFICE.ORG',
874             forceupdate         => { 'explanation' => 1,
875                                      'type' => 1,
876                                      'options' => 1},
877             explanation         => 'Define the default application for report exportations into files',
878                 type            => 'Choice',
879                 options         => 'EXCEL|OPENOFFICE.ORG'
880         },
881         {
882             uniquefieldrequired => 'variable',
883             variable            => 'Delimiter',
884             value               => ';',
885                 forceupdate             => { 'explanation' => 1,
886                                      'type' => 1,
887                                      'options' => 1},
888             explanation         => 'Define the default separator character for report exportations into files',
889                 type            => 'Choice',
890                 options         => ';|tabulation|,|/|\|#'
891         },
892         {
893             uniquefieldrequired => 'variable',
894             variable            => 'SubscriptionHistory',
895             value               => ';',
896                 forceupdate             => { 'explanation' => 1,
897                                      'type' => 1,
898                                      'options' => 1},
899             explanation         => 'Define the information level for serials history in OPAC',
900                 type            => 'Choice',
901                 options         => 'simplified|full'
902         },
903         {
904             uniquefieldrequired => 'variable',
905             variable            => 'hidelostitems',
906             value               => 'No',
907             forceupdate         => { 'explanation' => 1,
908                                      'type' => 1},
909             explanation         => 'show or hide "lost" items in OPAC.',
910             type                => 'YesNo',
911         },
912     ],
913
914 );
915
916 my %fielddefinitions = (
917     printers => [
918         {
919             field   => 'printername',
920             type    => 'char(40)',
921             null    => '',
922             key     => 'PRI',
923             default => ''
924         },
925     ],
926     aqbookfund => [
927         {
928             field   => 'bookfundid',
929             type    => 'char(5)',
930             null    => '',
931             key     => 'PRI',
932             default => ''
933         },
934         {
935             field   => 'branchcode',
936             type    => 'varchar(4)',
937             null    => 'NULL',
938             key     => '',
939             default =>'',
940             extra => ''
941         },
942     ],
943     aqbudget => [
944         {
945             field   => 'aqbudgetid',
946             type    => 'tinyint(4)',
947             null    => '',
948             key     => 'PRI',
949                   default =>'',
950             extra => 'auto_increment'
951         },
952         {
953             field   => 'branchcode',
954             type    => 'varchar(4)',
955             null    => 'NULL',
956             key     => '',
957             default =>'',
958             extra => ''
959         },
960     ],
961     z3950servers => [
962         {
963             field   => 'id',
964             type    => 'int',
965             null    => '',
966             key     => 'PRI',
967             default => '',
968             extra   => 'auto_increment'
969         },
970     ],
971         marc_breeding => [
972         {
973             field   => 'z3950random',
974             type    => 'varchar(40)',
975             null    => 'NULL',
976             key     => '',
977             default => '',
978             extra   => ''
979         },
980         {
981             field   => 'encoding',
982             type    => 'varchar(40)',
983             null    => '',
984             key     => '',
985             default => '',
986             extra   => ''
987         },
988     ],
989 );
990
991 #-------------------
992 # Initialize
993
994 # Start checking
995
996 # Get version of MySQL database engine.
997 my $mysqlversion = `mysqld --version`;
998 $mysqlversion =~ /Ver (\S*) /;
999 $mysqlversion = $1;
1000 if ( $mysqlversion ge '3.23' ) {
1001     print "Could convert to MyISAM database tables...\n" unless $silent;
1002 }
1003
1004 #---------------------------------
1005 # Tables
1006
1007 # Collect all tables into a list
1008 $sth = $dbh->prepare("show tables");
1009 $sth->execute;
1010 while ( my ($table) = $sth->fetchrow ) {
1011     $existingtables{$table} = 1;
1012 }
1013
1014
1015 # Now add any missing tables
1016 foreach $table ( keys %requiretables ) {
1017     unless ( $existingtables{$table} ) {
1018         print "Adding $table table...\n" unless $silent;
1019         my $sth = $dbh->prepare("create table $table $requiretables{$table}");
1020         $sth->execute;
1021         if ( $sth->err ) {
1022             print "Error : $sth->errstr \n";
1023             $sth->finish;
1024         }    # if error
1025     }    # unless exists
1026 }    # foreach
1027
1028 # now drop useless tables
1029 foreach $table ( keys %dropable_table ) {
1030         if ( $existingtables{$table} ) {
1031                 print "Dropping unused table $table\n" if $debug and not $silent;
1032                 $dbh->do("drop table $table");
1033                 if ( $dbh->err ) {
1034                         print "Error : $dbh->errstr \n";
1035                 }
1036         }
1037 }
1038 unless ( $existingtables{'z3950servers'} ) {
1039         #MJR: added syntax entries to close bug 624
1040     print "Adding z3950servers table...\n" unless $silent;
1041     my $sti = $dbh->prepare( "create table z3950servers (
1042                                                                                 host char(255),
1043                                                                                 port int,
1044                                                                                 db char(255),
1045                                                                                 userid char(255),
1046                                                                                 password char(255),
1047                                                                                 name text,
1048                                                                                 id int,
1049                                                                                 checked smallint,
1050                                                                                 rank int,
1051                                                                                 syntax char(80))"
1052     );
1053     $sti->execute;
1054     $sti = $dbh->prepare( "insert into z3950servers
1055                                                                 values ('z3950.loc.gov',
1056                                                                 7090,
1057                                                                 'voyager',
1058                                                                 '', '',
1059                                                                 'Library of Congress',
1060                                                                 1, 1, 1, 'USMARC')"
1061     );
1062     $sti->execute;
1063 }
1064 unless ( $existingtables{'issuingrules'} ) {
1065         $dbh->do("alter table categoryitem rename issuingrules");
1066         $dbh->do("ALTER TABLE issuingrules ADD maxissueqty int(4) default NULL");
1067         $dbh->do("ALTER TABLE issuingrules ADD issuelength int(4) default NULL");
1068         $dbh->do("ALTER TABLE issuingrules ADD branchcode varchar(4) NOT NULL default ''");
1069         print "renaming categoryitem\n" unless $silent;
1070 }
1071
1072
1073 #---------------------------------
1074 # Columns
1075
1076 foreach $table ( keys %requirefields ) {
1077     print "Check table $table\n" if $debug and not $silent;
1078     $sth = $dbh->prepare("show columns from $table");
1079     $sth->execute();
1080     undef %types;
1081     while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1082     {
1083         $types{$column} = $type;
1084     }    # while
1085     foreach $column ( keys %{ $requirefields{$table} } ) {
1086         print "  Check column $column  [$types{$column}]\n" if $debug and not $silent;
1087         if ( !$types{$column} ) {
1088
1089             # column doesn't exist
1090             print "Adding $column field to $table table...\n" unless $silent;
1091             $query = "alter table $table
1092                         add column $column " . $requirefields{$table}->{$column};
1093             print "Execute: $query\n" if $debug;
1094             my $sti = $dbh->prepare($query);
1095             $sti->execute;
1096             if ( $sti->err ) {
1097                 print "**Error : $sti->errstr \n";
1098                 $sti->finish;
1099             }    # if error
1100         }    # if column
1101     }    # foreach column
1102 }    # foreach table
1103
1104 foreach $table ( keys %fielddefinitions ) {
1105         print "Check table $table\n" if $debug;
1106         $sth = $dbh->prepare("show columns from $table");
1107         $sth->execute();
1108         my $definitions;
1109         while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1110         {
1111                 $definitions->{$column}->{type}    = $type;
1112                 $definitions->{$column}->{null}    = $null;
1113                 $definitions->{$column}->{key}     = $key;
1114                 $definitions->{$column}->{default} = $default;
1115                 $definitions->{$column}->{extra}   = $extra;
1116         }    # while
1117         my $fieldrow = $fielddefinitions{$table};
1118         foreach my $row (@$fieldrow) {
1119                 my $field   = $row->{field};
1120                 my $type    = $row->{type};
1121                 my $null    = $row->{null};
1122                 my $key     = $row->{key};
1123                 my $default = $row->{default};
1124                 $default="''" unless $default;
1125                 my $extra   = $row->{extra};
1126                 my $def     = $definitions->{$field};
1127                 unless ( $type eq $def->{type}
1128                         && $null eq $def->{null}
1129                         && $key eq $def->{key}
1130                         && $default eq $def->{default}
1131                         && $extra eq $def->{extra} )
1132                 {
1133
1134                         if ( $null eq '' ) {
1135                                 $null = 'NOT NULL';
1136                         }
1137                         if ( $key eq 'PRI' ) {
1138                                 $key = 'PRIMARY KEY';
1139                         }
1140                         unless ( $extra eq 'auto_increment' ) {
1141                                 $extra = '';
1142                         }
1143                         # if it's a new column use "add", if it's an old one, use "change".
1144                         my $action;
1145                         if ($definitions->{$field}->{type}) {
1146                                 $action="change $field"
1147                         } else {
1148                                 $action="add";
1149                         }
1150 # if it's a primary key, drop the previous pk, before altering the table
1151                         my $sth;
1152                         if ($key ne 'PRIMARY KEY') {
1153                                 $sth =$dbh->prepare("alter table $table $action $field $type $null $key $extra default ?");
1154                         } else {
1155                                 $sth =$dbh->prepare("alter table $table drop primary key, $action $field $type $null $key $extra default ?");
1156                         }
1157                         $sth->execute($default);
1158                         print "  Alter $field in $table\n" unless $silent;
1159                 }
1160         }
1161 }
1162
1163 # Get list of columns from borrowers table
1164 my %itemtypes;
1165 my %nullenabled;
1166 $sth = $dbh->prepare("show columns from borrowers");
1167 $sth->execute;
1168 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1169 {
1170     $itemtypes{$column} = $type;
1171     $nullenabled{$column} = $null;
1172 }
1173
1174 unless ( $itemtypes{'cardnumber'} eq 'varchar(20)' ) {
1175     $itemtypes{'cardnumber'} =~ /varchar\((\d+)\)/;
1176     my $oldlength = $1;
1177     if ( $oldlength < 16 ) {
1178         print "Setting maximum cardnumber length to 16 (was $oldlength) and marking unique.\n" unless $silent;
1179         my $sti =
1180           $dbh->prepare(
1181             "alter table borrowers change cardnumber cardnumber varchar(16)");
1182         $sti->execute;
1183         $sti->finish;
1184         $sti =
1185           $dbh->prepare(
1186             "alter table borrowers drop index cardnumber");
1187         $sti->execute;
1188         $sti->finish;
1189         $sti =
1190           $dbh->prepare(
1191             "alter table borrowers add unique(cardnumber)");
1192         $sti->execute;
1193         $sti->finish;
1194     }
1195 }
1196 #
1197 # Get list of columns from items table
1198 $sth = $dbh->prepare("show columns from items");
1199 $sth->execute;
1200 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1201 {
1202     $itemtypes{$column} = $type;
1203     $nullenabled{$column} = $null;
1204 }
1205
1206 unless ( $itemtypes{'barcode'} eq 'varchar(20)' ) {
1207     $itemtypes{'barcode'} =~ /varchar\((\d+)\)/;
1208     my $oldlength = $1;
1209     if ( $oldlength < 20 ) {
1210         print "Setting maximum barcode length to 20 (was $oldlength).\n" unless $silent;
1211         my $sti =
1212           $dbh->prepare(
1213             "alter table items change barcode barcode varchar(20)");
1214         $sti->execute;
1215     }
1216 }
1217 #
1218 # dropping unique barcode index & setting barcode to null allowed.
1219 #
1220 $sth = $dbh->prepare("show index from items");
1221 $sth->execute;
1222 while ( my ( $table, $non_unique, $key_name, $Seq_in_index, $Column_name, $Collation, $cardinality, $sub_part, $Packed, $comment ) = $sth->fetchrow )
1223 {
1224         if ($key_name eq 'barcode' && $non_unique eq 0) {
1225                 print "dropping BARCODE index to enable empty barcodes\n" unless $silent;
1226                 $dbh->do("ALTER TABLE `items` DROP INDEX `barcode`");
1227         }
1228 }
1229 $dbh->do("ALTER TABLE `items` CHANGE `barcode` `barcode` VARCHAR( 20 )") unless ($nullenabled{barcode} eq 'YES');
1230
1231 #
1232 # creating fulltext index in bibliothesaurus if needed
1233 #
1234 $sth = $dbh->prepare("show index from bibliothesaurus");
1235 $sth->execute;
1236 my $exists=0;
1237 while ( my ( $table, $non_unique, $key_name, $Seq_in_index, $Column_name, $Collation, $cardinality, $sub_part, $Packed, $comment ) = $sth->fetchrow )
1238 {
1239         if ($key_name eq 'category_2') {
1240                 $exists=1;
1241         }
1242 }
1243 print "Creating fulltext index on bibliothesaurus\n" unless $exists or $silent;
1244 $dbh->do('create fulltext index category_2 on bibliothesaurus (category,freelib)') unless $exists;
1245
1246 #
1247 # creating  index in z3950results if needed
1248 #
1249 $sth = $dbh->prepare("show index from z3950results");
1250 $sth->execute;
1251 my $exists=0;
1252 while ( my ( $table, $non_unique, $key_name, $Seq_in_index, $Column_name, $Collation, $cardinality, $sub_part, $Packed, $comment ) = $sth->fetchrow )
1253 {
1254         if ($key_name eq 'query_server') {
1255                 $exists=1;
1256         }
1257 }
1258 print "Creating  index on z3950results\n" unless $exists or $silent;
1259 $dbh->do('create unique index query_server on z3950results (queryid,server)') unless $exists;
1260
1261 # changing z3950daemon field to NULL in marc_breeding
1262 $dbh->do("ALTER TABLE `marc_breeding` CHANGE `z3950random` `z3950random` VARCHAR( 40 )");
1263
1264 # making borrowernumber an auto_increment field
1265 $dbh->do("ALTER TABLE `borrowers` CHANGE `borrowernumber` `borrowernumber` INTEGER auto_increment");
1266
1267 # changing indexes in marc_*_structure to use frameworkcode
1268 $dbh->do('alter table marc_subfield_structure drop index tab');
1269 $dbh->do('create index tab on marc_subfield_structure (frameworkcode,tab)');
1270 $dbh->do('alter table marc_subfield_structure drop index kohafield');
1271 $dbh->do('create index kohafield on marc_subfield_structure (frameworkcode,kohafield)');
1272
1273
1274 # extending the timestamp in branchtransfers...
1275 my %branchtransfers;
1276
1277 $sth = $dbh->prepare("show columns from branchtransfers");
1278 $sth->execute;
1279 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1280 {
1281     $branchtransfers{$column} = $type;
1282 }
1283
1284 unless ( $branchtransfers{'datesent'} eq 'datetime' ) {
1285     print "Setting type of datesent in branchtransfers to datetime.\n" unless $silent;
1286     my $sti =
1287       $dbh->prepare(
1288         "alter table branchtransfers change datesent datesent datetime");
1289     $sti->execute;
1290 }
1291
1292 unless ( $branchtransfers{'datearrived'} eq 'datetime' ) {
1293     print "Setting type of datearrived in branchtransfers to datetime.\n" unless $silent;
1294     my $sti =
1295       $dbh->prepare(
1296         "alter table branchtransfers change datearrived datearrived datetime");
1297     $sti->execute;
1298 }
1299
1300 # changing the branchcategories table around...
1301 my %branchcategories;
1302
1303 $sth = $dbh->prepare("show columns from branchcategories");
1304 $sth->execute;
1305 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1306 {
1307     $branchcategories{$column} = $type;
1308 }
1309
1310 unless ( $branchcategories{'categorycode'} eq 'varchar(4)' ) {
1311     print
1312 "Setting type of categorycode in branchcategories to varchar(4),\n and making the primary key.\n" unless $silent;
1313     my $sti =
1314       $dbh->prepare(
1315 "alter table branchcategories change categorycode categorycode varchar(4) not null"
1316     );
1317     $sti->execute;
1318     $sti =
1319       $dbh->prepare(
1320         "alter table branchcategories add primary key (categorycode)");
1321     $sti->execute;
1322 }
1323
1324 unless ( $branchcategories{'categoryname'} eq 'text' ) {
1325     print "Changing branchcode in branchcategories to categoryname text.\n" unless $silent;
1326     my $sth =
1327       $dbh->prepare(
1328         "alter table branchcategories change branchcode categoryname text");
1329     $sth->execute;
1330 }
1331
1332 unless ( $branchcategories{'codedescription'} eq 'text' ) {
1333     print
1334 "Replacing branchholding in branchcategories with codedescription text.\n" unless $silent;
1335     my $sth =
1336       $dbh->prepare(
1337         "alter table branchcategories change branchholding codedescription text"
1338     );
1339     $sth->execute;
1340 }
1341
1342 # changing the items table around...
1343 my %items;
1344
1345 $sth = $dbh->prepare("show columns from items");
1346 $sth->execute;
1347 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1348 {
1349     $items{$column} = $type;
1350 }
1351
1352 if ($items{'bulk'} eq "varchar(30)") {
1353     print "  Setting callnumber in items table\n" unless $silent;
1354     my $sti =
1355       $dbh->prepare("ALTER TABLE `items` CHANGE `bulk` `itemcallnumber` VARCHAR( 30 ) DEFAULT NULL");
1356     $sti->execute;
1357     $sti = $dbh->prepare("update marc_subfield_structure set kohafield=\"items.itemcallnumber\" where kohafield=\"items.bulk\"");
1358     $sti->execute;
1359 }
1360
1361 # changing the marc_subfield_structure table around...
1362 my %marc_subfield_structure;
1363
1364 $sth = $dbh->prepare("show columns from marc_subfield_structure");
1365 $sth->execute;
1366 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1367 {
1368     $marc_subfield_structure{$column} = $type;
1369 }
1370
1371 if ($marc_subfield_structure{thesaurus_category}) {
1372     print "  changing thesaurus_category in marc_subfield_structure table\n" unless $silent;
1373     my $sti =
1374       $dbh->prepare("ALTER TABLE marc_subfield_structure CHANGE `thesaurus_category` `authtypecode` VARCHAR(10 ) DEFAULT NULL");
1375     $sti->execute;
1376 }
1377
1378 #
1379 # creating  index in issuingrules if needed
1380 #
1381 $sth = $dbh->prepare("show index from issuingrules");
1382 $sth->execute;
1383 my $exists=0;
1384 while ( my ( $table, $non_unique, $key_name, $Seq_in_index, $Column_name, $Collation, $cardinality, $sub_part, $Packed, $comment ) = $sth->fetchrow )
1385 {
1386         if ($key_name eq 'PRIMARY') {
1387                 $exists=1;
1388         }
1389 }
1390 print "Creating  index on issuing rules\n" unless $exists or $silent;
1391 $dbh->do('ALTER TABLE issuingrules ADD PRIMARY KEY ( branchcode, categorycode, itemtype )') unless $exists;
1392
1393 $dbh->do('ALTER TABLE marc_tag_structure drop primary key');
1394 $dbh->do('ALTER TABLE marc_tag_structure ADD PRIMARY KEY ( frameworkcode, tagfield )');
1395
1396 $dbh->do('ALTER TABLE marc_subfield_structure drop primary key');
1397 $dbh->do('ALTER TABLE marc_subfield_structure ADD PRIMARY KEY ( frameworkcode, tagfield, tagsubfield )');
1398
1399 # Get list of columns from marc_word table
1400 my %marc_word;
1401 my %nullenabled;
1402 $sth = $dbh->prepare("show columns from marc_word");
1403 $sth->execute;
1404 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1405 {
1406     $marc_word{$column} = $type;
1407     $nullenabled{$column} = $null;
1408 }
1409 if ($marc_word{subfieldid}) {
1410         #create field tagsubfield, copy tag+subfieldid, then drop tag and subfieldid
1411         print "Modifying marc_word (concat on tag and subfield for better perfs)\n" unless $silent;
1412         $dbh->do("ALTER TABLE `marc_word` ADD `tagsubfield` CHAR( 4 ) NOT NULL AFTER `bibid`");
1413         $dbh->do("update marc_word set tagsubfield=concat(tag,subfieldid)");
1414         $dbh->do("alter table marc_word drop tag");
1415         $dbh->do("alter table marc_word drop subfieldid");
1416         $dbh->do("create index Search_Marc on marc_word (tagsubfield,word)");
1417 }
1418 # Populate tables with required data
1419
1420 # fill aqbasket if it's empty and aqorder is not
1421 # => it means it has just been created & must be filled
1422 $sth = $dbh->prepare("select count(*) from aqbasket");
1423 $sth->execute;
1424 if ($sth->fetchrow == 0) {
1425         $sth = $dbh->prepare("select count(*) from aqorders");
1426         $sth->execute;
1427         if ($sth->fetchrow >0) {
1428                 print "Populating new table aqbasket\n";
1429                 print "IMPORTANT NOTE: error message \"Duplicate entry 'X' for key 1\" may appear. it should not be a real trouble\n";
1430                 $sth=$dbh->prepare("select distinct basketno,booksellerid,authorisedby,entrydate,booksellerinvoicenumber from aqorders");
1431                 $sth->execute;
1432                 my ($basketno,$booksellerid,$authorisedby,$entrydate,$booksellerinvoicenumber);
1433                 my $sth2 = $dbh->prepare("insert into aqbasket (basketno,creationdate,booksellerid,authorisedby,booksellerinvoicenumber) values (?,?,?,?,?)");
1434                 while (($basketno,$booksellerid,$authorisedby,$entrydate,$booksellerinvoicenumber) = $sth->fetchrow) {
1435                         print "$basketno,$entrydate,$booksellerid,$authorisedby,$booksellerinvoicenumber\n";
1436                         $sth2->execute($basketno,$entrydate,$booksellerid,$authorisedby,$booksellerinvoicenumber);
1437                 }
1438         }
1439 }
1440 foreach my $table ( keys %tabledata ) {
1441     print "Checking for data required in table $table...\n" unless $silent;
1442     my $tablerows = $tabledata{$table};
1443     foreach my $row (@$tablerows) {
1444         my $uniquefieldrequired = $row->{uniquefieldrequired};
1445         my $uniquevalue         = $row->{$uniquefieldrequired};
1446         my $forceupdate         = $row->{forceupdate};
1447         my $sth                 =
1448           $dbh->prepare(
1449 "select $uniquefieldrequired from $table where $uniquefieldrequired=?"
1450         );
1451         $sth->execute($uniquevalue);
1452         if ($sth->rows) {
1453             foreach my $field (keys %$forceupdate) {
1454                 if ($forceupdate->{$field}) {
1455                     my $sth=$dbh->prepare("update systempreferences set $field=? where $uniquefieldrequired=?");
1456                     $sth->execute($row->{$field}, $uniquevalue);
1457                 }
1458             }
1459         } else {
1460             print "Adding row to $table: " unless $silent;
1461             my @values;
1462             my $fieldlist;
1463             my $placeholders;
1464             foreach my $field ( keys %$row ) {
1465                 next if $field eq 'uniquefieldrequired';
1466                 next if $field eq 'forceupdate';
1467                 my $value = $row->{$field};
1468                 push @values, $value;
1469                 print "  $field => $value" unless $silent;
1470                 $fieldlist .= "$field,";
1471                 $placeholders .= "?,";
1472             }
1473             print "\n" unless $silent;
1474             $fieldlist    =~ s/,$//;
1475             $placeholders =~ s/,$//;
1476             my $sth =
1477               $dbh->prepare(
1478                 "insert into $table ($fieldlist) values ($placeholders)");
1479             $sth->execute(@values);
1480         }
1481     }
1482 }
1483
1484 # at last, remove useless fields
1485 foreach $table ( keys %uselessfields ) {
1486         my @fields = split /,/,$uselessfields{$table};
1487         my $fields;
1488         my $exists;
1489         foreach my $fieldtodrop (@fields) {
1490                 $fieldtodrop =~ s/\t//g;
1491                 $fieldtodrop =~ s/\n//g;
1492                 $exists =0;
1493                 $sth = $dbh->prepare("show columns from $table");
1494                 $sth->execute;
1495                 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1496                 {
1497                         $exists =1 if ($column eq $fieldtodrop);
1498                 }
1499                 if ($exists) {
1500                         print "deleting $fieldtodrop field in $table...\n" unless $silent;
1501                         my $sth = $dbh->prepare("alter table $table drop $fieldtodrop");
1502                         $sth->execute;
1503                 }
1504         }
1505 }    # foreach
1506
1507
1508 $sth->finish;
1509
1510 exit;
1511
1512 # $Log$
1513 # Revision 1.107  2005/07/14 09:53:10  hdl
1514 # Adding a log facility for actions watching.
1515 # Code to be widely used in order to report data modifications.
1516 #
1517 # Revision 1.106  2005/07/06 17:47:22  hdl
1518 # Add branch selection and filter for budgets and funds.
1519 # May be too much... Funds could be enough....
1520 #
1521 # It works provided you update your base adding branchcode both in aqbookfund AND aqbudget.
1522 # If selection in budget is not needed, I shall remove.
1523 #
1524 # Revision 1.105  2005/06/20 14:36:44  tipaul
1525 # synch'ing 2.2 and head
1526 #
1527 # Revision 1.100.2.5  2005/06/06 15:23:36  tipaul
1528 # adding a systempref to choose either to show or hide "lost" items. Note that "lost items" can be related to an authorised value list, so does not necessary mean "item definetly lost". Even here, some libraries want to see lost items, and some don't want. This parameter will make everybody happy !
1529 #
1530 # Revision 1.100.2.4  2005/06/06 14:15:55  tipaul
1531 # adding 2 systemparameters to define an alternate image as logo in opac (the image on main page & on each top-left page)
1532 #
1533 # Revision 1.100.2.3  2005/06/02 21:05:34  hdl
1534 # adding variable SubscriptionHistory
1535 #
1536 # Revision 1.100.2.2  2005/03/29 15:41:43  tipaul
1537 # * new permissions : management & tools. You now have 2 new permissions :
1538 #       - management : means the user can manage library parameters, but NOT system parameters.
1539 #       - parameters : means the user can manage all parameters (including system parameters : marc structure, authorised values, system preferences. Was the only flag previously existing)
1540 #       - tools : means the user can import/export datas & edit barcodes.
1541 # note that for compatibility reasons, a user having "parameters" can access everything.
1542 # * new permission scheme. In every template new variables are available. They are written CAN_user_permission, with permission being one of the permission flag. templates can now show or hidde menu entries depending on user permissions. For example, a user with just circ permissions should have only the "circulation" button on home page. Templates are NOT updated in this version (except for system parameters, as proof of concept), they will be in the next ones. But the scheme is ready.
1543 #
1544 # Revision 1.100.2.1  2005/03/17 17:15:18  tipaul
1545 # defaulting opacstylesheet to '' instead of 'normal' (that is stupid)
1546 #
1547 # Revision 1.100  2004/12/10 16:11:32  tipaul
1548 # Improvement : adding a systempref to define default view in OPAC (either normal, MARC or ISBD). Created automatically during install or update. Check that you have a Koha >> parameters >> systempreferences >> BiblioDefaultView, Variable type : Choice, Variable options : normal|marc|isbd
1549 #
1550 # Revision 1.99  2004/12/02 17:17:00  tipaul
1551 # adding acquisition permission
1552 #
1553 # Revision 1.98  2004/11/26 20:26:49  tipaul
1554 # bugfix for auth_header creation
1555 #
1556 # Revision 1.97  2004/11/23 09:11:08  tipaul
1557 # adding itemcallnumber entry
1558 #
1559 # Revision 1.96  2004/11/16 13:03:45  tipaul
1560 # removing ldap systempref, it's now in C4/Auth_with_ldap.pm separate package
1561 #
1562 # Revision 1.95  2004/11/08 19:57:32  tipaul
1563 # bugfix
1564 #
1565 # Revision 1.94  2004/09/06 10:00:29  tipaul
1566 # adding a "location" field to the library.
1567 # This field is useful when the callnumber contains no information on the room where the item is stored.
1568 # With this field, we now have 3 levels of informations to find a book :
1569 # * the branch.
1570 # * the location.
1571 # * the callnumber.
1572 #
1573 # This should be versatile enough to solve any storing method.
1574 # This hack is quite simple, due to the nice Biblio.pm API. The MARC => koha db link is automatically managed. Just add the link in the parameters section.
1575 #
1576 # Revision 1.93  2004/08/12 14:50:50  tipaul
1577 # bugfixes
1578 #
1579 # Revision 1.92  2004/08/06 16:38:42  tipaul
1580 # changing DB structure to calculate next issue number.
1581 # Seems to work fine.
1582 #
1583 # Still misses the date calculation & the test of end of subscription (maybe for monday ?)
1584 #
1585 # Revision 1.91  2004/07/15 09:52:28  tipaul
1586 # Acquisition & Suggestion :
1587 # * acquisition rewritte : create a aqbasket table to deal with "bookseller order header".
1588 # * add "close basket" feature : a closed basket can't be modified
1589 # * suggestion feature : manage suggestions in acquisition (after suggestion filled in OPAC)
1590 #
1591 # Revision 1.90  2004/07/06 08:24:18  tipaul
1592 # adding 2 free fields that can be used for sorting purposes
1593 #
1594 # Revision 1.89  2004/07/02 15:55:08  tipaul
1595 # Adding 2 new fields, called "sort1" and "sort2"
1596 # They can be used for sorting & statistics reasons by the library.
1597 #
1598 # Revision 1.88  2004/06/26 23:34:26  rangi
1599 # Fixing typo
1600 #
1601 # Revision 1.87  2004/06/23 13:03:09  tipaul
1602 # fixes in DB structure
1603 #
1604 # Revision 1.86  2004/06/22 11:30:57  tipaul
1605 # adding -s (silent) flag, to have a silent install.
1606 # only updater will be verbose
1607 #
1608 # Revision 1.85  2004/06/17 15:19:44  tipaul
1609 # missing Marc_Search index on marc_word
1610 #
1611 # Revision 1.84  2004/06/17 08:25:21  tipaul
1612 # DB modifs : merging tag & subfield in marc_word table
1613 #
1614 # Revision 1.83  2004/06/10 08:32:02  tipaul
1615 # MARC authority management (continued)
1616 #
1617 # Revision 1.82  2004/06/03 12:46:58  tipaul
1618 # * frameworks and itemtypes are independant
1619 #
1620 # WARNING : will work only if applied to a 2.0 base. some modifs have been done since last commit that will NOT be applied if you run updatedatabase again.
1621 #
1622 # Revision 1.81  2004/05/28 09:56:21  tipaul
1623 # bugfix
1624 #
1625 # Revision 1.80  2004/05/28 08:32:00  tipaul
1626 # adding :
1627 # * MARC authority file
1628 # * seealso & hidden in MARC biblio structure.
1629 #
1630 # Revision 1.79  2004/05/18 09:50:07  tipaul
1631 # *** empty log message ***
1632 #
1633 # Revision 1.78  2004/05/10 09:29:33  tipaul
1634 # css is now the default theme for OPAC.
1635 # It will be the theme used for improvements and new things in OPAC.
1636 #
1637 # Revision 1.77  2004/05/06 14:56:51  tipaul
1638 # adding table issuingrules (previously called categoryitem
1639 #
1640 # Revision 1.76  2004/05/03 09:32:25  tipaul
1641 # adding printcirculationsplit parameter (already existed, but was not in systempref by defaul)
1642 #
1643 # Revision 1.75  2004/04/14 19:49:00  tipaul
1644 # seealso field set to 255 chars
1645 #
1646 # Revision 1.74  2004/03/11 16:10:16  tipaul
1647 # *** empty log message ***
1648 #
1649 # Revision 1.73  2004/03/06 20:26:13  tipaul
1650 # adding seealso feature in MARC searches
1651 #