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