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