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