synch'ing 2.2 and head
[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 );
387
388 my %requirefields = (
389     biblio        => { 'abstract' => 'text' },
390     deletedbiblio => { 'abstract' => 'text', 'marc' => 'blob' },
391     deleteditems => { 'marc' => 'blob', 'paidfor' => 'text', 'location' => 'varchar(80)'},
392     biblioitems   => {
393         'lccn' => 'char(25)',
394         'url'  => 'varchar(255)',
395         'marc' => 'text'
396     },
397     deletedbiblioitems => {
398         'lccn' => 'char(25)',
399         'url'  => 'varchar(255)',
400         'marc' => 'text'
401     },
402     branchtransfers => { 'datearrived'    => 'datetime' },
403     statistics      => { 'borrowernumber' => 'int(11)' },
404     aqbooksellers   => {
405         'invoicedisc' => 'float(6,4)',
406         'nocalc'      => 'int(11)'
407     },
408     borrowers => {
409                 'userid'        => 'char(30)',
410                 'password'      => 'char(30)',
411                 'flags'         => 'int(11)',
412                 'textmessaging' => 'varchar(30)',
413                 'zipcode' => 'varchar(25)',
414                 'homezipcode' => 'varchar(25)',
415                 'sort1' => 'char(80)',
416                 'sort2' => 'char(80)',
417     },
418     aqorders => { 'budgetdate' => 'date',
419                                 'sort1' => 'char(80)',
420                                 'sort2' => 'char(80)', },
421     aqbudget => {'aqbudgetid' => 'tinyint(4) auto_increment primary key'},
422     items => {'paidfor' => 'text', 'location' => 'char(80)'},
423
424     #added so that reference items are not available for reserves...
425     itemtypes         => { 'notforloan'  => 'smallint(6)' },
426     systempreferences => { 'explanation' => 'char(80)',
427                            'type' => 'char(20)',
428                            'options' => 'text' },
429     z3950servers      => { 'syntax'      => 'char(80)' },
430         marc_tag_structure =>{
431                                                         'frameworkcode' => 'char(4) not NULL default \'\''},
432     marc_subfield_structure =>{'seealso'  => 'char(255)',
433                                                         'frameworkcode' => 'char(4) not NULL default \'\'',
434                                                         'hidden' => 'tinyint(1)',
435                                                         'isurl' => 'tinyint(1)',
436                                                         'link' => 'char(80)',
437                                                         },
438     bookshelf => {'owner' => 'char(80)',
439                                         'category' => 'char(1)',
440                                 },
441     marc_biblio        => { 'frameworkcode' => 'char(4) not NULL default \'\'' },
442 );
443
444 my %dropable_table = (
445     classification => 'classification',
446     multipart      => 'multipart',
447     multivolume    => 'multivolume',
448     newitems       => 'newitems',
449     procedures     => 'procedures',
450     publisher      => 'publisher',
451     searchstats    => 'searchstats',
452     serialissues   => 'serialissues',
453 );
454
455 my %uselessfields = (
456         aqorders => "requisitionedby,authorisedby,booksellerid,
457                         deliverydays,followupdays,
458                         numberfollowupsallowed,numberfollowupssent,
459                         dateprinted,sourced,quantityreceiveddamaged,
460                         subscriptionfrom,subscriptionto
461                         "
462         );
463 # the other hash contains other actions that can't be done elsewhere. they are done
464 # either BEFORE of AFTER everything else, depending on "when" entry (default => AFTER)
465
466 # The tabledata hash contains data that should be in the tables.
467 # The uniquefieldrequired hash entry is used to determine which (if any) fields
468 # must not exist in the table for this row to be inserted.  If the
469 # uniquefieldrequired entry is already in the table, the existing data is not
470 # modified, unless the forceupdate hash entry is also set.  Fields in the
471 # anonymous "forceupdate" hash will be forced to be updated to the default
472 # values given in the %tabledata hash.
473
474 my %tabledata = (
475     userflags => [
476         {
477             uniquefieldrequired => 'bit',
478             bit                 => 0,
479             flag                => 'superlibrarian',
480             flagdesc            => 'Access to all librarian functions',
481             defaulton           => 0
482         },
483         {
484             uniquefieldrequired => 'bit',
485             bit                 => 1,
486             flag                => 'circulate',
487             flagdesc            => 'Circulate books',
488             defaulton           => 0
489         },
490         {
491             uniquefieldrequired => 'bit',
492             bit                 => 2,
493             flag                => 'catalogue',
494             flagdesc            => 'View Catalogue (Librarian Interface)',
495             defaulton           => 0
496         },
497         {
498             uniquefieldrequired => 'bit',
499             bit                 => 3,
500             flag                => 'parameters',
501             flagdesc            => 'Set Koha system paramters',
502             defaulton           => 0
503         },
504         {
505             uniquefieldrequired => 'bit',
506             bit                 => 4,
507             flag                => 'borrowers',
508             flagdesc            => 'Add or modify borrowers',
509             defaulton           => 0
510         },
511         {
512             uniquefieldrequired => 'bit',
513             bit                 => 5,
514             flag                => 'permissions',
515             flagdesc            => 'Set user permissions',
516             defaulton           => 0
517         },
518         {
519             uniquefieldrequired => 'bit',
520             bit                 => 6,
521             flag                => 'reserveforothers',
522             flagdesc            => 'Reserve books for patrons',
523             defaulton           => 0
524         },
525         {
526             uniquefieldrequired => 'bit',
527             bit                 => 7,
528             flag                => 'borrow',
529             flagdesc            => 'Borrow books',
530             defaulton           => 1
531         },
532         {
533             uniquefieldrequired => 'bit',
534             bit                 => 8,
535             flag                => 'reserveforself',
536             flagdesc            => 'Reserve books for self',
537             defaulton           => 0
538         },
539         {
540             uniquefieldrequired => 'bit',
541             bit                 => 9,
542             flag                => 'editcatalogue',
543             flagdesc  => 'Edit Catalogue (Modify bibliographic/holdings data)',
544             defaulton => 0
545         },
546         {
547             uniquefieldrequired => 'bit',
548             bit                 => 10,
549             flag                => 'updatecharges',
550             flagdesc            => 'Update borrower charges',
551             defaulton           => 0
552         },
553         {
554             uniquefieldrequired => 'bit',
555             bit                 => 11,
556             flag                => 'acquisition',
557             flagdesc            => 'Acquisition and/or suggestion management',
558             defaulton           => 0
559         },
560         {
561             uniquefieldrequired => 'bit',
562             bit                 => 12,
563             flag                => 'management',
564             flagdesc            => 'Set library management parameters',
565             defaulton           => 0
566         },
567         {
568             uniquefieldrequired => 'bit',
569             bit                 => 13,
570             flag                => 'tools',
571             flagdesc            => 'Use tools (export, import, barcodes)',
572             defaulton           => 0
573         },        
574     ],
575     systempreferences => [
576         {
577             uniquefieldrequired => 'variable',
578             forceupdate         => { 'explanation' => 1,
579                                      'type' => 1 },
580             variable            => 'LibraryName',
581             value               => '<i><b>Koha<br/>Free Software ILS<br/><br/></b>Koha : a gift, a contribution<br/> in Maori</i>',
582             explanation         => 'Library name as shown on main opac page',
583             type                => ''
584
585         },
586         {
587             uniquefieldrequired => 'variable',
588             forceupdate         => { 'explanation' => 1,
589                                      'type' => 1 },
590             variable            => 'autoMemberNum',
591             value               => '1',
592             explanation         => 'Member number is auto-calculated',
593             type                => 'YesNo'
594
595         },
596         {
597             uniquefieldrequired => 'variable',
598             forceupdate         => { 'explanation' => 1,
599                                      'type' => 1,
600                                      'options' => 1 },
601             variable            => 'acquisitions',
602             value               => 'normal',
603             explanation         =>
604 'Normal, budget-based acquisitions, or Simple bibliographic-data acquisitions',
605             type                => 'Choice',
606             options             => 'simple|normal'
607         },
608         {
609             uniquefieldrequired => 'variable',
610             forceupdate         => { 'explanation' => 1,
611                                      'type' => 1,
612                                      'options' => 1 },
613             variable            => 'dateformat',
614             value               => 'metric',
615             explanation         =>
616             'date format (us mm/dd/yyyy, metric dd/mm/yyy, ISO yyyy/mm/dd)',
617             type                => 'Choice',
618             options             => 'metric|us|iso'
619         },
620         {
621             uniquefieldrequired => 'variable',
622             variable            => 'template',
623             forceupdate         => { 'explanation' => 1,
624                                      'type' => 1 },
625             value               => 'default',
626             explanation         => 'Preference order for intranet interface templates',
627             type                => 'Themes'
628         },
629         {
630             uniquefieldrequired => 'variable',
631             variable            => 'autoBarcode',
632             forceupdate         => { 'explanation' => 1,
633                                      'type' => 1 },
634             value               => 'yes',
635             explanation         => 'Barcode is auto-calculated',
636             type                => 'YesNo'
637         },
638         {
639             uniquefieldrequired => 'variable',
640             variable            => 'insecure',
641             forceupdate         => { 'explanation' => 1,
642                                      'type' => 1 },
643             value               => 'no',
644             explanation         =>
645 'If YES, no auth at all is needed. Be careful if you set this to yes!',
646             type                => 'YesNo'
647         },
648         {
649             uniquefieldrequired => 'variable',
650             variable            => 'authoritysep',
651             forceupdate         => { 'explanation' => 1,
652                                      'type' => 1,
653                                      'options' => 1 },
654             value               => '--',
655             explanation         =>
656             'the separator used in authority/thesaurus. Usually --',
657             type                => 'free',
658             options             => '10'
659         },
660         {
661             uniquefieldrequired => 'variable',
662             variable            => 'opaclanguages',
663             forceupdate         => { 'explanation' => 1,
664                                      'type' => 1 },
665             value               => 'en',
666             explanation         => 'Set the preferred order for translations.  The top language will be tried first.',
667             type                => 'Languages'
668         },
669         {
670             uniquefieldrequired => 'variable',
671             variable            => 'opacthemes',
672             forceupdate         => { 'explanation' => 1,
673                                      'type' => 1 },
674             value               => 'css',
675             explanation         => 'Set the preferred order for themes.  The top theme will be tried first.',
676             type                => 'Themes'
677         },
678         {
679             uniquefieldrequired => 'variable',
680             variable            => 'timeout',
681             forceupdate         => { 'explanation' => 1,
682                                      'type' => 1 },
683             value               => '1200',
684             explanation         => 'Inactivity timeout for cookies authentication (in seconds)',
685             type                => 'Integer'
686         },
687         {
688             uniquefieldrequired => 'variable',
689             variable            => 'marc',
690             forceupdate         => { 'explanation' => 1,
691                                      'type' => 1 },
692             value               => 'yes',
693             explanation         => 'Turn on MARC support',
694             type                => 'YesNo'
695         },
696         {
697             uniquefieldrequired => 'variable',
698             variable            => 'marcflavour',
699             forceupdate         => { 'explanation' => 1,
700                                      'type' => 1,
701                                      'options' => 1},
702             value               => 'MARC21',
703             explanation         =>
704             'your MARC flavor (MARC21 or UNIMARC) used for character encoding',
705             type                => 'Choice',
706             options             => 'MARC21|UNIMARC'
707         },
708         {
709             uniquefieldrequired => 'variable',
710             variable            => 'checkdigit',
711             value               => 'none',
712             forceupdate         => { 'explanation' => 1,
713                                      'type' => 1,
714                                      'options' => 1},
715             explanation         => 'Validity checks on membership number: none or "Katipo" style checks',
716             type                => 'Choice',
717             options             => 'none|katipo'
718         },
719         {
720             uniquefieldrequired => 'variable',
721             variable            => 'maxoutstanding',
722             forceupdate         => { 'explanation' => 1,
723                                      'type' => 1 },
724             value               => '5',
725             explanation         =>
726             'maximum amount withstanding to be able make reserves ',
727             type                => 'Integer'
728         },
729         {
730             uniquefieldrequired => 'variable',
731             variable            => 'maxreserves',
732             forceupdate         => { 'explanation' => 1,
733                                      'type' => 1 },
734             value               => '5',
735             explanation         =>
736             'maximum number of reserves a member can make',
737             type                => 'Integer'
738
739         },
740         {
741             uniquefieldrequired => 'variable',
742             variable            => 'noissuescharge',
743             forceupdate         => { 'explanation' => 1,
744                                      'type' => 1 },
745             value               => '5',
746             explanation         =>
747             'maximum amount withstanding to be able to check out an item',
748             type                => 'Integer'
749
750         },
751         {
752             uniquefieldrequired => 'variable',
753             variable            => 'KohaAdminEmailAddress',
754             forceupdate         => { 'explanation' => 1,
755                                      'type' => 1 },
756             value               => 'your.mail@here',
757             explanation => 'the email address where borrowers modifs are sent',
758             type                => 'free'
759         },
760         {
761             uniquefieldrequired => 'variable',
762             variable            => 'gist',
763             forceupdate         => { 'explanation' => 1,
764                                      'type' => 1 },
765             value               => '0.125',
766             explanation => 'the gist rate. NOT in %, but in numeric form (0.12 for 12%)',
767             type                => 'free'
768         },
769         {
770             uniquefieldrequired => 'variable',
771             variable            => 'printcirculationslips',
772             forceupdate         => { 'explanation' => 1,
773                                      'type' => 1 },
774             value               => '0',
775             explanation => 'if set to 1, print circulation slips. If set to 0, don\'t',
776             type                => 'free'
777         },
778         {
779             uniquefieldrequired => 'variable',
780             variable            => 'suggestion',
781             forceupdate         => { 'explanation' => 1,
782                                      'type' => 1 },
783             value               => '0',
784             explanation => 'if set to 1, suggestions are activated in OPAC',
785             type                => 'free'
786         },
787         {
788             uniquefieldrequired => 'variable',
789             variable            => 'ISBD',
790             forceupdate         => { 'explanation' => 1,
791                                      'type' => 1 },
792             value               => 'Fill with appropriate value...',
793             explanation => 'ISBD',
794             type                => 'free'
795         },
796         {
797             uniquefieldrequired => 'variable',
798             variable            => 'virtualshelves',
799             forceupdate         => { 'explanation' => 1,
800                                      'type' => 1 },
801             value               => '0',
802             explanation => 'Set virtual shelves management ON or OFF',
803             type                => 'YesNo'
804         },
805         {
806             uniquefieldrequired => 'variable',
807             variable            => 'itemcallnumber',
808             forceupdate         => { 'explanation' => 1,
809                                      'type' => 1 },
810             value               => '676a',
811             explanation => 'The MARC field/subfield that is used to calculate the itemcallnumber (in UNIMARC : 676a for Dewey, 680a for Loc)',
812             type                => 'free'
813         },
814         {
815             uniquefieldrequired => 'variable',
816             variable            => 'BiblioDefaultView',
817             value               => 'normal',
818             forceupdate         => { 'explanation' => 1,
819                                      'type' => 1,
820                                      'options' => 1},
821             explanation         => 'Define the default view of a biblio. Can be either normal, marc or isbd',
822             type                => 'Choice',
823             options             => 'normal|marc|isbd'
824         },
825         {
826             uniquefieldrequired => 'variable',
827             variable            => 'opacstylesheet',
828             value               => '',
829             forceupdate         => { 'explanation' => 1,
830                                      'type' => 1},
831             explanation         => 'Enter a complete URL to use an alternate stylesheet in OPAC',
832             type                => 'free',
833         },
834         {
835             uniquefieldrequired => 'variable',
836             variable            => 'opacsmallimage',
837             value               => '',
838             forceupdate         => { 'explanation' => 1,
839                                      'type' => 1},
840             explanation         => 'Enter a complete URL to an image, will be on top/left instead of the Koha logo',
841             type                => 'free',
842         },
843         {
844             uniquefieldrequired => 'variable',
845             variable            => 'opaclargeimage',
846             value               => '',
847             forceupdate         => { 'explanation' => 1,
848                                      'type' => 1},
849             explanation         => 'Enter a complete URL to an image, will be on the main page, instead of the Koha logo',
850             type                => 'free',
851         },
852         {
853             uniquefieldrequired => 'variable',
854             variable            => 'delimiter',
855             value               => ';',
856             forceupdate         => { 'explanation' => 1,
857                                      'type' => 1},
858             explanation         => 'separator for reports exported to spreadsheet',
859             type                => 'free',
860         },
861         {
862             uniquefieldrequired => 'variable',
863             variable            => 'MIME',
864             value               => 'OPENOFFICE.ORG',
865             forceupdate         => { 'explanation' => 1,
866                                      'type' => 1,
867                                      'options' => 1},
868             explanation         => 'Define the default application for report exportations into files',
869                 type            => 'Choice',
870                 options         => 'EXCEL|OPENOFFICE.ORG'
871         },
872         {
873             uniquefieldrequired => 'variable',
874             variable            => 'Delimiter',
875             value               => ';',
876                 forceupdate             => { 'explanation' => 1,
877                                      'type' => 1,
878                                      'options' => 1},
879             explanation         => 'Define the default separator character for report exportations into files',
880                 type            => 'Choice',
881                 options         => ';|tabulation|,|/|\|#'
882         },
883         {
884             uniquefieldrequired => 'variable',
885             variable            => 'SubscriptionHistory',
886             value               => ';',
887                 forceupdate             => { 'explanation' => 1,
888                                      'type' => 1,
889                                      'options' => 1},
890             explanation         => 'Define the information level for serials history in OPAC',
891                 type            => 'Choice',
892                 options         => 'simplified|full'
893         },
894         {
895             uniquefieldrequired => 'variable',
896             variable            => 'hidelostitems',
897             value               => 'No',
898             forceupdate         => { 'explanation' => 1,
899                                      'type' => 1},
900             explanation         => 'show or hide "lost" items in OPAC.',
901             type                => 'YesNo',
902         },
903     ],
904
905 );
906
907 my %fielddefinitions = (
908     printers => [
909         {
910             field   => 'printername',
911             type    => 'char(40)',
912             null    => '',
913             key     => 'PRI',
914             default => ''
915         },
916     ],
917     aqbookfund => [
918         {
919             field   => 'bookfundid',
920             type    => 'char(5)',
921             null    => '',
922             key     => 'PRI',
923             default => ''
924         },
925     ],
926     aqbudget => [
927         {
928             field   => 'aqbudgetid',
929             type    => 'tinyint(4)',
930             null    => '',
931             key     => 'PRI',
932                   default =>'',
933             extra => 'auto_increment'
934         },
935     ],
936     z3950servers => [
937         {
938             field   => 'id',
939             type    => 'int',
940             null    => '',
941             key     => 'PRI',
942             default => '',
943             extra   => 'auto_increment'
944         },
945     ],
946         marc_breeding => [
947         {
948             field   => 'z3950random',
949             type    => 'varchar(40)',
950             null    => 'NULL',
951             key     => '',
952             default => '',
953             extra   => ''
954         },
955         {
956             field   => 'encoding',
957             type    => 'varchar(40)',
958             null    => '',
959             key     => '',
960             default => '',
961             extra   => ''
962         },
963     ],
964 );
965
966 #-------------------
967 # Initialize
968
969 # Start checking
970
971 # Get version of MySQL database engine.
972 my $mysqlversion = `mysqld --version`;
973 $mysqlversion =~ /Ver (\S*) /;
974 $mysqlversion = $1;
975 if ( $mysqlversion ge '3.23' ) {
976     print "Could convert to MyISAM database tables...\n" unless $silent;
977 }
978
979 #---------------------------------
980 # Tables
981
982 # Collect all tables into a list
983 $sth = $dbh->prepare("show tables");
984 $sth->execute;
985 while ( my ($table) = $sth->fetchrow ) {
986     $existingtables{$table} = 1;
987 }
988
989
990 # Now add any missing tables
991 foreach $table ( keys %requiretables ) {
992     unless ( $existingtables{$table} ) {
993         print "Adding $table table...\n" unless $silent;
994         my $sth = $dbh->prepare("create table $table $requiretables{$table}");
995         $sth->execute;
996         if ( $sth->err ) {
997             print "Error : $sth->errstr \n";
998             $sth->finish;
999         }    # if error
1000     }    # unless exists
1001 }    # foreach
1002
1003 # now drop useless tables
1004 foreach $table ( keys %dropable_table ) {
1005         if ( $existingtables{$table} ) {
1006                 print "Dropping unused table $table\n" if $debug and not $silent;
1007                 $dbh->do("drop table $table");
1008                 if ( $dbh->err ) {
1009                         print "Error : $dbh->errstr \n";
1010                 }
1011         }
1012 }
1013 unless ( $existingtables{'z3950servers'} ) {
1014         #MJR: added syntax entries to close bug 624
1015     print "Adding z3950servers table...\n" unless $silent;
1016     my $sti = $dbh->prepare( "create table z3950servers (
1017                                                                                 host char(255),
1018                                                                                 port int,
1019                                                                                 db char(255),
1020                                                                                 userid char(255),
1021                                                                                 password char(255),
1022                                                                                 name text,
1023                                                                                 id int,
1024                                                                                 checked smallint,
1025                                                                                 rank int,
1026                                                                                 syntax char(80))"
1027     );
1028     $sti->execute;
1029     $sti = $dbh->prepare( "insert into z3950servers
1030                                                                 values ('z3950.loc.gov',
1031                                                                 7090,
1032                                                                 'voyager',
1033                                                                 '', '',
1034                                                                 'Library of Congress',
1035                                                                 1, 1, 1, 'USMARC')"
1036     );
1037     $sti->execute;
1038 }
1039 unless ( $existingtables{'issuingrules'} ) {
1040         $dbh->do("alter table categoryitem rename issuingrules");
1041         $dbh->do("ALTER TABLE issuingrules ADD maxissueqty int(4) default NULL");
1042         $dbh->do("ALTER TABLE issuingrules ADD issuelength int(4) default NULL");
1043         $dbh->do("ALTER TABLE issuingrules ADD branchcode varchar(4) NOT NULL default ''");
1044         print "renaming categoryitem\n" unless $silent;
1045 }
1046
1047
1048 #---------------------------------
1049 # Columns
1050
1051 foreach $table ( keys %requirefields ) {
1052     print "Check table $table\n" if $debug and not $silent;
1053     $sth = $dbh->prepare("show columns from $table");
1054     $sth->execute();
1055     undef %types;
1056     while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1057     {
1058         $types{$column} = $type;
1059     }    # while
1060     foreach $column ( keys %{ $requirefields{$table} } ) {
1061         print "  Check column $column  [$types{$column}]\n" if $debug and not $silent;
1062         if ( !$types{$column} ) {
1063
1064             # column doesn't exist
1065             print "Adding $column field to $table table...\n" unless $silent;
1066             $query = "alter table $table
1067                         add column $column " . $requirefields{$table}->{$column};
1068             print "Execute: $query\n" if $debug;
1069             my $sti = $dbh->prepare($query);
1070             $sti->execute;
1071             if ( $sti->err ) {
1072                 print "**Error : $sti->errstr \n";
1073                 $sti->finish;
1074             }    # if error
1075         }    # if column
1076     }    # foreach column
1077 }    # foreach table
1078
1079 foreach $table ( keys %fielddefinitions ) {
1080         print "Check table $table\n" if $debug;
1081         $sth = $dbh->prepare("show columns from $table");
1082         $sth->execute();
1083         my $definitions;
1084         while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1085         {
1086                 $definitions->{$column}->{type}    = $type;
1087                 $definitions->{$column}->{null}    = $null;
1088                 $definitions->{$column}->{key}     = $key;
1089                 $definitions->{$column}->{default} = $default;
1090                 $definitions->{$column}->{extra}   = $extra;
1091         }    # while
1092         my $fieldrow = $fielddefinitions{$table};
1093         foreach my $row (@$fieldrow) {
1094                 my $field   = $row->{field};
1095                 my $type    = $row->{type};
1096                 my $null    = $row->{null};
1097                 my $key     = $row->{key};
1098                 my $default = $row->{default};
1099                 $default="''" unless $default;
1100                 my $extra   = $row->{extra};
1101                 my $def     = $definitions->{$field};
1102                 unless ( $type eq $def->{type}
1103                         && $null eq $def->{null}
1104                         && $key eq $def->{key}
1105                         && $default eq $def->{default}
1106                         && $extra eq $def->{extra} )
1107                 {
1108
1109                         if ( $null eq '' ) {
1110                                 $null = 'NOT NULL';
1111                         }
1112                         if ( $key eq 'PRI' ) {
1113                                 $key = 'PRIMARY KEY';
1114                         }
1115                         unless ( $extra eq 'auto_increment' ) {
1116                                 $extra = '';
1117                         }
1118                         # if it's a new column use "add", if it's an old one, use "change".
1119                         my $action;
1120                         if ($definitions->{$field}->{type}) {
1121                                 $action="change $field"
1122                         } else {
1123                                 $action="add";
1124                         }
1125 # if it's a primary key, drop the previous pk, before altering the table
1126                         my $sth;
1127                         if ($key ne 'PRIMARY KEY') {
1128                                 $sth =$dbh->prepare("alter table $table $action $field $type $null $key $extra default ?");
1129                         } else {
1130                                 $sth =$dbh->prepare("alter table $table drop primary key, $action $field $type $null $key $extra default ?");
1131                         }
1132                         $sth->execute($default);
1133                         print "  Alter $field in $table\n" unless $silent;
1134                 }
1135         }
1136 }
1137
1138 # Get list of columns from borrowers table
1139 my %itemtypes;
1140 my %nullenabled;
1141 $sth = $dbh->prepare("show columns from borrowers");
1142 $sth->execute;
1143 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1144 {
1145     $itemtypes{$column} = $type;
1146     $nullenabled{$column} = $null;
1147 }
1148
1149 unless ( $itemtypes{'cardnumber'} eq 'varchar(20)' ) {
1150     $itemtypes{'cardnumber'} =~ /varchar\((\d+)\)/;
1151     my $oldlength = $1;
1152     if ( $oldlength < 16 ) {
1153         print "Setting maximum cardnumber length to 16 (was $oldlength) and marking unique.\n" unless $silent;
1154         my $sti =
1155           $dbh->prepare(
1156             "alter table borrowers change cardnumber cardnumber varchar(16)");
1157         $sti->execute;
1158         $sti->finish;
1159         $sti =
1160           $dbh->prepare(
1161             "alter table borrowers drop index cardnumber");
1162         $sti->execute;
1163         $sti->finish;
1164         $sti =
1165           $dbh->prepare(
1166             "alter table borrowers add unique(cardnumber)");
1167         $sti->execute;
1168         $sti->finish;
1169     }
1170 }
1171 #
1172 # Get list of columns from items table
1173 $sth = $dbh->prepare("show columns from items");
1174 $sth->execute;
1175 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1176 {
1177     $itemtypes{$column} = $type;
1178     $nullenabled{$column} = $null;
1179 }
1180
1181 unless ( $itemtypes{'barcode'} eq 'varchar(20)' ) {
1182     $itemtypes{'barcode'} =~ /varchar\((\d+)\)/;
1183     my $oldlength = $1;
1184     if ( $oldlength < 20 ) {
1185         print "Setting maximum barcode length to 20 (was $oldlength).\n" unless $silent;
1186         my $sti =
1187           $dbh->prepare(
1188             "alter table items change barcode barcode varchar(20)");
1189         $sti->execute;
1190     }
1191 }
1192 #
1193 # dropping unique barcode index & setting barcode to null allowed.
1194 #
1195 $sth = $dbh->prepare("show index from items");
1196 $sth->execute;
1197 while ( my ( $table, $non_unique, $key_name, $Seq_in_index, $Column_name, $Collation, $cardinality, $sub_part, $Packed, $comment ) = $sth->fetchrow )
1198 {
1199         if ($key_name eq 'barcode' && $non_unique eq 0) {
1200                 print "dropping BARCODE index to enable empty barcodes\n" unless $silent;
1201                 $dbh->do("ALTER TABLE `items` DROP INDEX `barcode`");
1202         }
1203 }
1204 $dbh->do("ALTER TABLE `items` CHANGE `barcode` `barcode` VARCHAR( 20 )") unless ($nullenabled{barcode} eq 'YES');
1205
1206 #
1207 # creating fulltext index in bibliothesaurus if needed
1208 #
1209 $sth = $dbh->prepare("show index from bibliothesaurus");
1210 $sth->execute;
1211 my $exists=0;
1212 while ( my ( $table, $non_unique, $key_name, $Seq_in_index, $Column_name, $Collation, $cardinality, $sub_part, $Packed, $comment ) = $sth->fetchrow )
1213 {
1214         if ($key_name eq 'category_2') {
1215                 $exists=1;
1216         }
1217 }
1218 print "Creating fulltext index on bibliothesaurus\n" unless $exists or $silent;
1219 $dbh->do('create fulltext index category_2 on bibliothesaurus (category,freelib)') unless $exists;
1220
1221 #
1222 # creating  index in z3950results if needed
1223 #
1224 $sth = $dbh->prepare("show index from z3950results");
1225 $sth->execute;
1226 my $exists=0;
1227 while ( my ( $table, $non_unique, $key_name, $Seq_in_index, $Column_name, $Collation, $cardinality, $sub_part, $Packed, $comment ) = $sth->fetchrow )
1228 {
1229         if ($key_name eq 'query_server') {
1230                 $exists=1;
1231         }
1232 }
1233 print "Creating  index on z3950results\n" unless $exists or $silent;
1234 $dbh->do('create unique index query_server on z3950results (queryid,server)') unless $exists;
1235
1236 # changing z3950daemon field to NULL in marc_breeding
1237 $dbh->do("ALTER TABLE `marc_breeding` CHANGE `z3950random` `z3950random` VARCHAR( 40 )");
1238
1239 # making borrowernumber an auto_increment field
1240 $dbh->do("ALTER TABLE `borrowers` CHANGE `borrowernumber` `borrowernumber` INTEGER auto_increment");
1241
1242 # changing indexes in marc_*_structure to use frameworkcode
1243 $dbh->do('alter table marc_subfield_structure drop index tab');
1244 $dbh->do('create index tab on marc_subfield_structure (frameworkcode,tab)');
1245 $dbh->do('alter table marc_subfield_structure drop index kohafield');
1246 $dbh->do('create index kohafield on marc_subfield_structure (frameworkcode,kohafield)');
1247
1248
1249 # extending the timestamp in branchtransfers...
1250 my %branchtransfers;
1251
1252 $sth = $dbh->prepare("show columns from branchtransfers");
1253 $sth->execute;
1254 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1255 {
1256     $branchtransfers{$column} = $type;
1257 }
1258
1259 unless ( $branchtransfers{'datesent'} eq 'datetime' ) {
1260     print "Setting type of datesent in branchtransfers to datetime.\n" unless $silent;
1261     my $sti =
1262       $dbh->prepare(
1263         "alter table branchtransfers change datesent datesent datetime");
1264     $sti->execute;
1265 }
1266
1267 unless ( $branchtransfers{'datearrived'} eq 'datetime' ) {
1268     print "Setting type of datearrived in branchtransfers to datetime.\n" unless $silent;
1269     my $sti =
1270       $dbh->prepare(
1271         "alter table branchtransfers change datearrived datearrived datetime");
1272     $sti->execute;
1273 }
1274
1275 # changing the branchcategories table around...
1276 my %branchcategories;
1277
1278 $sth = $dbh->prepare("show columns from branchcategories");
1279 $sth->execute;
1280 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1281 {
1282     $branchcategories{$column} = $type;
1283 }
1284
1285 unless ( $branchcategories{'categorycode'} eq 'varchar(4)' ) {
1286     print
1287 "Setting type of categorycode in branchcategories to varchar(4),\n and making the primary key.\n" unless $silent;
1288     my $sti =
1289       $dbh->prepare(
1290 "alter table branchcategories change categorycode categorycode varchar(4) not null"
1291     );
1292     $sti->execute;
1293     $sti =
1294       $dbh->prepare(
1295         "alter table branchcategories add primary key (categorycode)");
1296     $sti->execute;
1297 }
1298
1299 unless ( $branchcategories{'categoryname'} eq 'text' ) {
1300     print "Changing branchcode in branchcategories to categoryname text.\n" unless $silent;
1301     my $sth =
1302       $dbh->prepare(
1303         "alter table branchcategories change branchcode categoryname text");
1304     $sth->execute;
1305 }
1306
1307 unless ( $branchcategories{'codedescription'} eq 'text' ) {
1308     print
1309 "Replacing branchholding in branchcategories with codedescription text.\n" unless $silent;
1310     my $sth =
1311       $dbh->prepare(
1312         "alter table branchcategories change branchholding codedescription text"
1313     );
1314     $sth->execute;
1315 }
1316
1317 # changing the items table around...
1318 my %items;
1319
1320 $sth = $dbh->prepare("show columns from items");
1321 $sth->execute;
1322 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1323 {
1324     $items{$column} = $type;
1325 }
1326
1327 if ($items{'bulk'} eq "varchar(30)") {
1328     print "  Setting callnumber in items table\n" unless $silent;
1329     my $sti =
1330       $dbh->prepare("ALTER TABLE `items` CHANGE `bulk` `itemcallnumber` VARCHAR( 30 ) DEFAULT NULL");
1331     $sti->execute;
1332     $sti = $dbh->prepare("update marc_subfield_structure set kohafield=\"items.itemcallnumber\" where kohafield=\"items.bulk\"");
1333     $sti->execute;
1334 }
1335
1336 # changing the marc_subfield_structure table around...
1337 my %marc_subfield_structure;
1338
1339 $sth = $dbh->prepare("show columns from marc_subfield_structure");
1340 $sth->execute;
1341 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1342 {
1343     $marc_subfield_structure{$column} = $type;
1344 }
1345
1346 if ($marc_subfield_structure{thesaurus_category}) {
1347     print "  changing thesaurus_category in marc_subfield_structure table\n" unless $silent;
1348     my $sti =
1349       $dbh->prepare("ALTER TABLE marc_subfield_structure CHANGE `thesaurus_category` `authtypecode` VARCHAR(10 ) DEFAULT NULL");
1350     $sti->execute;
1351 }
1352
1353 #
1354 # creating  index in issuingrules if needed
1355 #
1356 $sth = $dbh->prepare("show index from issuingrules");
1357 $sth->execute;
1358 my $exists=0;
1359 while ( my ( $table, $non_unique, $key_name, $Seq_in_index, $Column_name, $Collation, $cardinality, $sub_part, $Packed, $comment ) = $sth->fetchrow )
1360 {
1361         if ($key_name eq 'PRIMARY') {
1362                 $exists=1;
1363         }
1364 }
1365 print "Creating  index on issuing rules\n" unless $exists or $silent;
1366 $dbh->do('ALTER TABLE issuingrules ADD PRIMARY KEY ( branchcode, categorycode, itemtype )') unless $exists;
1367
1368 $dbh->do('ALTER TABLE marc_tag_structure drop primary key');
1369 $dbh->do('ALTER TABLE marc_tag_structure ADD PRIMARY KEY ( frameworkcode, tagfield )');
1370
1371 $dbh->do('ALTER TABLE marc_subfield_structure drop primary key');
1372 $dbh->do('ALTER TABLE marc_subfield_structure ADD PRIMARY KEY ( frameworkcode, tagfield, tagsubfield )');
1373
1374 # Get list of columns from marc_word table
1375 my %marc_word;
1376 my %nullenabled;
1377 $sth = $dbh->prepare("show columns from marc_word");
1378 $sth->execute;
1379 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1380 {
1381     $marc_word{$column} = $type;
1382     $nullenabled{$column} = $null;
1383 }
1384 if ($marc_word{subfieldid}) {
1385         #create field tagsubfield, copy tag+subfieldid, then drop tag and subfieldid
1386         print "Modifying marc_word (concat on tag and subfield for better perfs)\n" unless $silent;
1387         $dbh->do("ALTER TABLE `marc_word` ADD `tagsubfield` CHAR( 4 ) NOT NULL AFTER `bibid`");
1388         $dbh->do("update marc_word set tagsubfield=concat(tag,subfieldid)");
1389         $dbh->do("alter table marc_word drop tag");
1390         $dbh->do("alter table marc_word drop subfieldid");
1391         $dbh->do("create index Search_Marc on marc_word (tagsubfield,word)");
1392 }
1393 # Populate tables with required data
1394
1395 # fill aqbasket if it's empty and aqorder is not
1396 # => it means it has just been created & must be filled
1397 $sth = $dbh->prepare("select count(*) from aqbasket");
1398 $sth->execute;
1399 if ($sth->fetchrow == 0) {
1400         $sth = $dbh->prepare("select count(*) from aqorders");
1401         $sth->execute;
1402         if ($sth->fetchrow >0) {
1403                 print "Populating new table aqbasket\n";
1404                 print "IMPORTANT NOTE: error message \"Duplicate entry 'X' for key 1\" may appear. it should not be a real trouble\n";
1405                 $sth=$dbh->prepare("select distinct basketno,booksellerid,authorisedby,entrydate,booksellerinvoicenumber from aqorders");
1406                 $sth->execute;
1407                 my ($basketno,$booksellerid,$authorisedby,$entrydate,$booksellerinvoicenumber);
1408                 my $sth2 = $dbh->prepare("insert into aqbasket (basketno,creationdate,booksellerid,authorisedby,booksellerinvoicenumber) values (?,?,?,?,?)");
1409                 while (($basketno,$booksellerid,$authorisedby,$entrydate,$booksellerinvoicenumber) = $sth->fetchrow) {
1410                         print "$basketno,$entrydate,$booksellerid,$authorisedby,$booksellerinvoicenumber\n";
1411                         $sth2->execute($basketno,$entrydate,$booksellerid,$authorisedby,$booksellerinvoicenumber);
1412                 }
1413         }
1414 }
1415 foreach my $table ( keys %tabledata ) {
1416     print "Checking for data required in table $table...\n" unless $silent;
1417     my $tablerows = $tabledata{$table};
1418     foreach my $row (@$tablerows) {
1419         my $uniquefieldrequired = $row->{uniquefieldrequired};
1420         my $uniquevalue         = $row->{$uniquefieldrequired};
1421         my $forceupdate         = $row->{forceupdate};
1422         my $sth                 =
1423           $dbh->prepare(
1424 "select $uniquefieldrequired from $table where $uniquefieldrequired=?"
1425         );
1426         $sth->execute($uniquevalue);
1427         if ($sth->rows) {
1428             foreach my $field (keys %$forceupdate) {
1429                 if ($forceupdate->{$field}) {
1430                     my $sth=$dbh->prepare("update systempreferences set $field=? where $uniquefieldrequired=?");
1431                     $sth->execute($row->{$field}, $uniquevalue);
1432                 }
1433             }
1434         } else {
1435             print "Adding row to $table: " unless $silent;
1436             my @values;
1437             my $fieldlist;
1438             my $placeholders;
1439             foreach my $field ( keys %$row ) {
1440                 next if $field eq 'uniquefieldrequired';
1441                 next if $field eq 'forceupdate';
1442                 my $value = $row->{$field};
1443                 push @values, $value;
1444                 print "  $field => $value" unless $silent;
1445                 $fieldlist .= "$field,";
1446                 $placeholders .= "?,";
1447             }
1448             print "\n" unless $silent;
1449             $fieldlist    =~ s/,$//;
1450             $placeholders =~ s/,$//;
1451             my $sth =
1452               $dbh->prepare(
1453                 "insert into $table ($fieldlist) values ($placeholders)");
1454             $sth->execute(@values);
1455         }
1456     }
1457 }
1458
1459 # at last, remove useless fields
1460 foreach $table ( keys %uselessfields ) {
1461         my @fields = split /,/,$uselessfields{$table};
1462         my $fields;
1463         my $exists;
1464         foreach my $fieldtodrop (@fields) {
1465                 $fieldtodrop =~ s/\t//g;
1466                 $fieldtodrop =~ s/\n//g;
1467                 $exists =0;
1468                 $sth = $dbh->prepare("show columns from $table");
1469                 $sth->execute;
1470                 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1471                 {
1472                         $exists =1 if ($column eq $fieldtodrop);
1473                 }
1474                 if ($exists) {
1475                         print "deleting $fieldtodrop field in $table...\n" unless $silent;
1476                         my $sth = $dbh->prepare("alter table $table drop $fieldtodrop");
1477                         $sth->execute;
1478                 }
1479         }
1480 }    # foreach
1481
1482
1483 $sth->finish;
1484
1485 exit;
1486
1487 # $Log$
1488 # Revision 1.105  2005/06/20 14:36:44  tipaul
1489 # synch'ing 2.2 and head
1490 #
1491 # Revision 1.100.2.5  2005/06/06 15:23:36  tipaul
1492 # 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 !
1493 #
1494 # Revision 1.100.2.4  2005/06/06 14:15:55  tipaul
1495 # adding 2 systemparameters to define an alternate image as logo in opac (the image on main page & on each top-left page)
1496 #
1497 # Revision 1.100.2.3  2005/06/02 21:05:34  hdl
1498 # adding variable SubscriptionHistory
1499 #
1500 # Revision 1.100.2.2  2005/03/29 15:41:43  tipaul
1501 # * new permissions : management & tools. You now have 2 new permissions :
1502 #       - management : means the user can manage library parameters, but NOT system parameters.
1503 #       - parameters : means the user can manage all parameters (including system parameters : marc structure, authorised values, system preferences. Was the only flag previously existing)
1504 #       - tools : means the user can import/export datas & edit barcodes.
1505 # note that for compatibility reasons, a user having "parameters" can access everything.
1506 # * 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.
1507 #
1508 # Revision 1.100.2.1  2005/03/17 17:15:18  tipaul
1509 # defaulting opacstylesheet to '' instead of 'normal' (that is stupid)
1510 #
1511 # Revision 1.100  2004/12/10 16:11:32  tipaul
1512 # 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
1513 #
1514 # Revision 1.99  2004/12/02 17:17:00  tipaul
1515 # adding acquisition permission
1516 #
1517 # Revision 1.98  2004/11/26 20:26:49  tipaul
1518 # bugfix for auth_header creation
1519 #
1520 # Revision 1.97  2004/11/23 09:11:08  tipaul
1521 # adding itemcallnumber entry
1522 #
1523 # Revision 1.96  2004/11/16 13:03:45  tipaul
1524 # removing ldap systempref, it's now in C4/Auth_with_ldap.pm separate package
1525 #
1526 # Revision 1.95  2004/11/08 19:57:32  tipaul
1527 # bugfix
1528 #
1529 # Revision 1.94  2004/09/06 10:00:29  tipaul
1530 # adding a "location" field to the library.
1531 # This field is useful when the callnumber contains no information on the room where the item is stored.
1532 # With this field, we now have 3 levels of informations to find a book :
1533 # * the branch.
1534 # * the location.
1535 # * the callnumber.
1536 #
1537 # This should be versatile enough to solve any storing method.
1538 # 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.
1539 #
1540 # Revision 1.93  2004/08/12 14:50:50  tipaul
1541 # bugfixes
1542 #
1543 # Revision 1.92  2004/08/06 16:38:42  tipaul
1544 # changing DB structure to calculate next issue number.
1545 # Seems to work fine.
1546 #
1547 # Still misses the date calculation & the test of end of subscription (maybe for monday ?)
1548 #
1549 # Revision 1.91  2004/07/15 09:52:28  tipaul
1550 # Acquisition & Suggestion :
1551 # * acquisition rewritte : create a aqbasket table to deal with "bookseller order header".
1552 # * add "close basket" feature : a closed basket can't be modified
1553 # * suggestion feature : manage suggestions in acquisition (after suggestion filled in OPAC)
1554 #
1555 # Revision 1.90  2004/07/06 08:24:18  tipaul
1556 # adding 2 free fields that can be used for sorting purposes
1557 #
1558 # Revision 1.89  2004/07/02 15:55:08  tipaul
1559 # Adding 2 new fields, called "sort1" and "sort2"
1560 # They can be used for sorting & statistics reasons by the library.
1561 #
1562 # Revision 1.88  2004/06/26 23:34:26  rangi
1563 # Fixing typo
1564 #
1565 # Revision 1.87  2004/06/23 13:03:09  tipaul
1566 # fixes in DB structure
1567 #
1568 # Revision 1.86  2004/06/22 11:30:57  tipaul
1569 # adding -s (silent) flag, to have a silent install.
1570 # only updater will be verbose
1571 #
1572 # Revision 1.85  2004/06/17 15:19:44  tipaul
1573 # missing Marc_Search index on marc_word
1574 #
1575 # Revision 1.84  2004/06/17 08:25:21  tipaul
1576 # DB modifs : merging tag & subfield in marc_word table
1577 #
1578 # Revision 1.83  2004/06/10 08:32:02  tipaul
1579 # MARC authority management (continued)
1580 #
1581 # Revision 1.82  2004/06/03 12:46:58  tipaul
1582 # * frameworks and itemtypes are independant
1583 #
1584 # 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.
1585 #
1586 # Revision 1.81  2004/05/28 09:56:21  tipaul
1587 # bugfix
1588 #
1589 # Revision 1.80  2004/05/28 08:32:00  tipaul
1590 # adding :
1591 # * MARC authority file
1592 # * seealso & hidden in MARC biblio structure.
1593 #
1594 # Revision 1.79  2004/05/18 09:50:07  tipaul
1595 # *** empty log message ***
1596 #
1597 # Revision 1.78  2004/05/10 09:29:33  tipaul
1598 # css is now the default theme for OPAC.
1599 # It will be the theme used for improvements and new things in OPAC.
1600 #
1601 # Revision 1.77  2004/05/06 14:56:51  tipaul
1602 # adding table issuingrules (previously called categoryitem
1603 #
1604 # Revision 1.76  2004/05/03 09:32:25  tipaul
1605 # adding printcirculationsplit parameter (already existed, but was not in systempref by defaul)
1606 #
1607 # Revision 1.75  2004/04/14 19:49:00  tipaul
1608 # seealso field set to 255 chars
1609 #
1610 # Revision 1.74  2004/03/11 16:10:16  tipaul
1611 # *** empty log message ***
1612 #
1613 # Revision 1.73  2004/03/06 20:26:13  tipaul
1614 # adding seealso feature in MARC searches
1615 #