Head & rel_2_2 merged
[koha.git] / updater / updatedatabase
1 #!/usr/bin/perl
2
3 <<<<<<< updatedatabase
4 # $Id$
5 =======
6 # $Id$
7 >>>>>>> 1.100.2.46
8
9 # Database Updater
10 # This script checks for required updates to the database.
11
12 # Part of the Koha Library Software www.koha.org
13 # Licensed under the GPL.
14
15 # Bugs/ToDo:
16 # - Would also be a good idea to offer to do a backup at this time...
17
18 # NOTE:  If you do something more than once in here, make it table driven.
19 use strict;
20
21 # CPAN modules
22 use DBI;
23 use Getopt::Long;
24
25 # Koha modules
26 use C4::Context;
27
28 use MARC::Record;
29 use MARC::File::XML ( BinaryEncoding => 'utf8' );
30  
31 # FIXME - The user might be installing a new database, so can't rely
32 # on /etc/koha.conf anyway.
33
34 my $debug = 0;
35
36 my (
37     $sth, $sti,
38     $query,
39     %existingtables,    # tables already in database
40     %types,
41     $table,
42     $column,
43     $type, $null, $key, $default, $extra,
44     $prefitem,          # preference item in systempreferences table
45 );
46
47 my $silent;
48 GetOptions( 's' => \$silent );
49 my $dbh = C4::Context->dbh;
50 print "connected to your DB. Checking & modifying it\n" unless $silent;
51 $|=1; # flushes output
52
53 #-------------------
54 # Defines
55
56 # Tables to add if they don't exist
57 my %requiretables = (
58     categorytable       => "(categorycode char(5) NOT NULL default '',
59                              description text default '',
60                              itemtypecodes text default '',
61                              PRIMARY KEY (categorycode)
62                             )",
63     subcategorytable       => "(subcategorycode char(5) NOT NULL default '',
64                              description text default '',
65                              itemtypecodes text default '',
66                              PRIMARY KEY (subcategorycode)
67                             )",
68     mediatypetable       => "(mediatypecode char(5) NOT NULL default '',
69                              description text default '',
70                              itemtypecodes text default '',
71                              PRIMARY KEY (mediatypecode)
72                             )",
73     action_logs         => "(
74                                     `timestamp` TIMESTAMP NOT NULL ,
75                                     `user` INT( 11 ) NOT NULL ,
76                                     `module` TEXT default '',
77                                     `action` TEXT default '' ,
78                                     `object` INT(11) default '' ,
79                                     `info` TEXT default '' ,
80                                     PRIMARY KEY ( `timestamp` , `user` )
81                             )",
82         letter          => "(
83                                         module varchar(20) NOT NULL default '',
84                                         code varchar(20) NOT NULL default '',
85                                         name varchar(100) NOT NULL default '',
86                                         title varchar(200) NOT NULL default '',
87                                         content text,
88                                         PRIMARY KEY  (module,code)
89                                 )",
90         alert           =>"(
91                                         alertid int(11) NOT NULL auto_increment,
92                                         borrowernumber int(11) NOT NULL default '0',
93                                         type varchar(10) NOT NULL default '',
94                                         externalid varchar(20) NOT NULL default '',
95                                         PRIMARY KEY  (alertid),
96                                         KEY borrowernumber (borrowernumber),
97                                         KEY type (type,externalid)
98                                 )",
99         opac_news => "(
100                                 `idnew` int(10) unsigned NOT NULL auto_increment,
101                                 `title` varchar(250) NOT NULL default '',
102                                 `new` text NOT NULL,
103                                 `lang` varchar(4) NOT NULL default '',
104                                 `timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP,
105                                 PRIMARY KEY  (`idnew`)
106                                 )",
107         repeatable_holidays => "(
108                                 `id` int(11) NOT NULL auto_increment,
109                                 `branchcode` varchar(4) NOT NULL default '',
110                                 `weekday` smallint(6) default NULL,
111                                 `day` smallint(6) default NULL,
112                                 `month` smallint(6) default NULL,
113                                 `title` varchar(50) NOT NULL default '',
114                                 `description` text NOT NULL,
115                                 PRIMARY KEY  (`id`)
116                                 )",
117         special_holidays => "(
118                                 `id` int(11) NOT NULL auto_increment,
119                                 `branchcode` varchar(4) NOT NULL default '',
120                                 `day` smallint(6) NOT NULL default '0',
121                                 `month` smallint(6) NOT NULL default '0',
122                                 `year` smallint(6) NOT NULL default '0',
123                                 `isexception` smallint(1) NOT NULL default '1',
124                                 `title` varchar(50) NOT NULL default '',
125                                 `description` text NOT NULL,
126                                 PRIMARY KEY  (`id`)
127                                 )",
128         overduerules    =>"(`branchcode` varchar(255) NOT NULL default '',
129                                         `categorycode` char(2) NOT NULL default '',
130                                         `delay1` int(4) default '0',
131                                         `letter1` varchar(20) default NULL,
132                                         `debarred1` char(1) default '0',
133                                         `delay2` int(4) default '0',
134                                         `debarred2` char(1) default '0',
135                                         `letter2` varchar(20) default NULL,
136                                         `delay3` int(4) default '0',
137                                         `letter3` varchar(20) default NULL,
138                                         `debarred3` int(1) default '0',
139                                         PRIMARY KEY  (`branchcode`,`categorycode`)
140                                         )",
141         cities                  => "(`cityid` int auto_increment,
142                                                 `city_name` char(100) NOT NULL,
143                                                 `city_zipcode` char(20),
144                                                 PRIMARY KEY (`cityid`)
145                                         )",
146 <<<<<<< updatedatabase
147         roadtype                        => "(`roadtypeid` int auto_increment,
148                                                 `road_type` char(100) NOT NULL,
149                                                 PRIMARY KEY (`roadtypeid`)
150 =======
151     marc_word => "(
152                                 bibid bigint(20) NOT NULL default '0',
153                                 tag char(3) NOT NULL default '',
154                                 tagorder tinyint(4) NOT NULL default '1',
155                                 subfieldid char(1) NOT NULL default '',
156                                 subfieldorder tinyint(4) NOT NULL default '1',
157                                 word varchar(255) NOT NULL default '',
158                                 sndx_word varchar(255) NOT NULL default '',
159                                 KEY bibid (bibid),
160                                 KEY tag (tag),
161                                 KEY tagorder (tagorder),
162                                 KEY subfieldid (subfieldid),
163                                 KEY subfieldorder (subfieldorder),
164                                 KEY word (word),
165                                 KEY sndx_word (sndx_word)
166                         )",
167     marc_breeding => "(  id bigint(20) NOT NULL auto_increment,
168                                 file varchar(80) NOT NULL default '',
169                                 isbn varchar(10) NOT NULL default '',
170                                 title varchar(128) default NULL,
171                                 author varchar(80) default NULL,
172                                 marc text NOT NULL,
173                                 encoding varchar(40) default NULL,
174                                 PRIMARY KEY  (id),
175                                 KEY title (title),
176                                 KEY isbn (isbn)
177                         )",
178     authorised_values => "(id int(11) NOT NULL auto_increment,
179                                 category char(10) NOT NULL default '',
180                                 authorised_value char(80) NOT NULL default '',
181                                 lib char(80) NULL,
182                                 PRIMARY KEY  (id),
183                                 KEY name (category)
184                         )",
185     userflags => "( bit int(11) NOT NULL default '0',
186                                 flag char(30), flagdesc char(255),
187                                 defaulton int(11)
188                         )",
189     auth_types => "(
190                                         authtypecode char(10) not NULL,
191                                         authtypetext char(255) not NULL,
192                                         auth_tag_to_report char(3) not NULL,
193                                         summary text not NULL,
194                                         PRIMARY KEY (authtypecode)
195                         )",
196     biblio_framework => "(
197                                         frameworkcode char(4) not NULL,
198                                         frameworktext char(255) not NULL,
199                                         PRIMARY KEY (frameworkcode)
200                         )",
201     auth_subfield_structure => "(
202                                         authtypecode char(10) NOT NULL default '',
203                                         tagfield char(3) NOT NULL default '',
204                                         tagsubfield char(1) NOT NULL default '',
205                                         liblibrarian char(255) NOT NULL default '',
206                                         libopac char(255) NOT NULL default '',
207                                         repeatable tinyint(4) NOT NULL default '0',
208                                         mandatory tinyint(4) NOT NULL default '0',
209                                         tab tinyint(1) default NULL,
210                                         authorised_value char(10) default NULL,
211                                         value_builder char(80) default NULL,
212                                         seealso char(255) default NULL,
213                                         PRIMARY KEY  (authtypecode,tagfield,tagsubfield),
214                                         KEY tab (authtypecode,tab)
215 >>>>>>> 1.100.2.46
216                                         )",
217 <<<<<<< updatedatabase
218
219         labels                     => "(
220                                 labelid int(11) NOT NULL auto_increment,
221                                 itemnumber varchar(100) NOT NULL default '',
222                                 timestamp timestamp(14) NOT NULL,
223                                 PRIMARY KEY  (labelid)
224                                 )",
225
226         labels_conf                => "(
227                                 id int(4) NOT NULL auto_increment,
228                                 barcodetype char(100) default '',
229                                 title tinyint(1) default '0',
230                                 isbn tinyint(1) default '0',
231                                 itemtype tinyint(1) default '0',
232                                 barcode tinyint(1) default '0',
233                                 dewey tinyint(1) default '0',
234                                 class tinyint(1) default '0',
235                                 author tinyint(1) default '0',
236                                 papertype char(100) default '',
237                                 startrow int(2) default NULL,
238                                 PRIMARY KEY  (id)
239                                 )",
240        reviews                  => "(
241                                 reviewid integer NOT NULL auto_increment,
242                                 borrowernumber integer,
243                                 biblionumber integer,
244                                 review text,
245                                 approved tinyint,
246                                 datereviewed datetime,
247                                 PRIMARY KEY (reviewid)
248                                 )",
249        borrowers_to_borrowers  => "(
250                                 borrower1 integer,
251                                 borrower2 integer
252                                 )",
253
254 =======
255     auth_tag_structure => "(
256                                         authtypecode char(10) NOT NULL default '',
257                                         tagfield char(3) NOT NULL default '',
258                                         liblibrarian char(255) NOT NULL default '',
259                                         libopac char(255) NOT NULL default '',
260                                         repeatable tinyint(4) NOT NULL default '0',
261                                         mandatory tinyint(4) NOT NULL default '0',
262                                         authorised_value char(10) default NULL,
263                                         PRIMARY KEY  (authtypecode,tagfield)
264                                         )",
265     auth_header => "(
266                                                 authid bigint(20) unsigned NOT NULL auto_increment,
267                                                 authtypecode char(10) NOT NULL default '',
268                                                 datecreated date NOT NULL default '0000-00-00',
269                                                 datemodified date default NULL,
270                                                 origincode char(20) default NULL,
271                                                 PRIMARY KEY  (authid),
272                                                 KEY origincode (origincode)
273                                                 ) ",
274     auth_subfield_table => "(
275                                                 subfieldid bigint(20) unsigned NOT NULL auto_increment,
276                                                 authid bigint(20) unsigned NOT NULL default '0',
277                                                 tag char(3) NOT NULL default '',
278                                                 tagorder tinyint(4) NOT NULL default '1',
279                                                 tag_indicator char(2) NOT NULL default '',
280                                                 subfieldcode char(1) NOT NULL default '',
281                                                 subfieldorder tinyint(4) NOT NULL default '1',
282                                                 subfieldvalue varchar(255) default NULL,
283                                                 PRIMARY KEY  (subfieldid),
284                                                 KEY authid (authid),
285                                                 KEY tag (tag),
286                                                 KEY subfieldcode (subfieldcode),
287                                                 KEY subfieldvalue (subfieldvalue)
288                                         )",
289     auth_word => "(
290                                 authid bigint(20) NOT NULL default '0',
291                                 tagsubfield char(4) NOT NULL default '',
292                                 tagorder tinyint(4) NOT NULL default '1',
293                                 subfieldorder tinyint(4) NOT NULL default '1',
294                                 word varchar(255) NOT NULL default '',
295                                 sndx_word varchar(255) NOT NULL default '',
296                                 KEY authid (authid),
297                                 KEY marc_search (tagsubfield,word),
298                                 KEY word (word),
299                                 KEY sndx_word (sndx_word)
300                         )",
301     suggestions => "(
302                                 suggestionid int(8) NOT NULL auto_increment,
303                                 suggestedby int(11) NOT NULL default '0',
304                                 managedby int(11) default NULL ,
305                                 STATUS varchar(10) NOT NULL default '',
306                                 note text,
307                                 author varchar(80) default NULL ,
308                                 title varchar(80) default NULL ,
309                                 copyrightdate smallint(6) default NULL ,
310                                 publishercode varchar(255) default NULL ,
311                                 date timestamp(8) NOT NULL ,
312                                 volumedesc varchar(255) default NULL ,
313                                 publicationyear smallint(6) default '0',
314                                 place varchar(255) default NULL ,
315                                 isbn varchar(10) default NULL ,
316                                 mailoverseeing smallint(1) default '0',
317                                 biblionumber int(11) default NULL ,
318                                 PRIMARY KEY (suggestionid) ,
319                                 KEY suggestedby(suggestedby) ,
320                                 KEY managedby(managedby)
321                         )",
322     aqbasket => "(basketno int(11) NOT NULL auto_increment,
323                                 creationdate date,
324                                 closedate date,
325                                 booksellerid varchar(10),
326                                 authorisedby varchar(10),
327                                 booksellerinvoicenumber text,
328                                 PRIMARY KEY (basketno)
329                                 )",
330     serial => "(serialid int(11) NOT NULL auto_increment,
331                                 biblionumber varchar(100) NOT NULL default '',
332                                 subscriptionid varchar(100) NOT NULL default '',
333                                 serialseq varchar(100) NOT NULL default '',
334                                 status tinyint(4) NOT NULL default '0',
335                                 planneddate date NOT NULL default '0000-00-00',
336                                 publishedddate date NOT NULL default '0000-00-00',
337                                 PRIMARY KEY  (serialid)
338                                 )",
339     subscription => "(biblionumber int(11) NOT NULL default '0',
340                                                 subscriptionid int(11) NOT NULL auto_increment,
341                                                 librarian varchar(100) default '',
342                                                 startdate date default '0000-00-00',
343                                                 aqbooksellerid int(11) default '0',
344                                                 cost int(11) default '0',
345                                                 aqbudgetid int(11) default '0',
346                                                 weeklength tinyint(4) default '0',
347                                                 monthlength tinyint(4) default '0',
348                                                 numberlength tinyint(4) default '0',
349                                                 periodicity tinyint(4) default '0',
350                                                 dow varchar(100) default '',
351                                                 numberingmethod varchar(100) default '',
352                                                 notes text,
353                                                 status varchar(100) NOT NULL default '',
354                                                 add1 int(11) default 0,
355                                                 every1 int(11) default 0,
356                                                 whenmorethan1 int(11) default 0,
357                                                 setto1 int(11),
358                                                 lastvalue1 int(11),
359                                                 add2 int(11) default 0,
360                                                 every2 int(11) default 0,
361                                                 whenmorethan2 int(11) default 0,
362                                                 setto2 int(11),
363                                                 lastvalue2 int(11),
364                                                 add3 int(11) default 0,
365                                                 every3 int(11) default 0,
366                                                 innerloop1 int(11) default 0,
367                                                 innerloop2 int(11) default 0,
368                                                 innerloop3 int(11) default 0,
369                                                 whenmorethan3 int(11) default 0,
370                                                 setto3 int(11),
371                                                 lastvalue3 int(11),
372                                                 PRIMARY KEY  (subscriptionid)
373                                                 )",
374     subscriptionhistory => "(biblionumber int(11) NOT NULL default '0',
375                                                         subscriptionid int(11) NOT NULL default '0',
376                                                         histstartdate date NOT NULL default '0000-00-00',
377                                                         enddate date default '0000-00-00',
378                                                         missinglist longtext NOT NULL,
379                                                         recievedlist longtext NOT NULL,
380                                                         opacnote varchar(150) NOT NULL default '',
381                                                         librariannote varchar(150) NOT NULL default '',
382                                                         PRIMARY KEY  (subscriptionid),
383                                                         KEY biblionumber (biblionumber)
384                                 )",
385     labels => "(labelid int(11) NOT NULL auto_increment,
386                             itemnumber varchar(100) NOT NULL default '',
387                             timestamp timestamp(14) NOT NULL,
388                             PRIMARY KEY  (labelid)
389                             )",
390     labels_conf => "(id int(4) NOT NULL auto_increment,
391                            barcodetype char(100) default '',
392                            title tinyint(1) default '0',
393                            isbn tinyint(1) default '0',
394                            itemtype tinyint(1) default '0',
395                            barcode tinyint(1) default '0',
396                            dewey tinyint(1) default '0',
397                            class tinyint(1) default '0',
398                            author tinyint(1) default '0',
399                            papertype char(100) default '',
400                            startrow int(2) default NULL,
401                            PRIMARY KEY  (id)
402                            )",
403 >>>>>>> 1.100.2.46
404 );
405
406 my %requirefields = (
407 <<<<<<< updatedatabase
408         subscription => { 'letter' => 'char(20) NULL', 'distributedto' => 'text NULL'},
409         itemtypes => { 'imageurl' => 'char(200) NULL'},
410         aqbookfund => { 'branchcode' => 'varchar(4) NULL'},
411         aqbudget => { 'branchcode' => 'varchar(4) NULL'},
412         auth_header => { 'marc' => 'BLOB NOT NULL', 'linkid' => 'BIGINT(20) NULL'},
413         auth_subfield_structure =>{ 'hidden' => 'TINYINT(3) NOT NULL UNSIGNED ZEROFILL', 'kohafield' => 'VARCHAR(45) NOT NULL', 'linkid' =>  'TINYINT(1) NOT NULL UNSIGNED', 'isurl' => 'TINYINT(1) UNSIGNED'},
414         statistics => { 'associatedborrower' => 'integer'},
415 #    tablename        => { 'field' => 'fieldtype' },
416 =======
417     biblio        => { 'abstract' => 'text' },
418     deletedbiblio => { 'abstract' => 'text', 'marc' => 'blob' },
419     deleteditems =>
420       { 'marc' => 'blob', 'paidfor' => 'text', 'location' => 'varchar(80)' },
421     biblioitems => {
422         'lccn' => 'char(25)',
423         'url'  => 'varchar(255)',
424         'marc' => 'text'
425     },
426     deletedbiblioitems => {
427         'lccn' => 'char(25)',
428         'url'  => 'varchar(255)',
429         'marc' => 'text'
430     },
431     branchtransfers => { 'datearrived'    => 'datetime' },
432     statistics      => { 'borrowernumber' => 'int(11)' },
433     aqbooksellers   => {
434         'invoicedisc' => 'float(6,4)',
435         'nocalc'      => 'int(11)'
436     },
437     borrowers => {
438         'userid'        => 'char(30)',
439         'password'      => 'char(30)',
440         'flags'         => 'int(11)',
441         'textmessaging' => 'varchar(30)',
442         'zipcode'       => 'varchar(25)',
443         'homezipcode'   => 'varchar(25)',
444         'sort1'         => 'char(80)',
445         'sort2'         => 'char(80)',
446     },
447     aqorders => {
448         'budgetdate' => 'date',
449         'sort1'      => 'char(80)',
450         'sort2'      => 'char(80)',
451     },
452     aqbudget => {
453         'aqbudgetid' => 'tinyint(4) auto_increment primary key',
454         'branchcode' => 'varchar(4)',
455     },
456     aqbookfund => { 'branchcode' => 'varchar(4)', },
457     items      => { 'paidfor'    => 'text', 'location' => 'char(80)' },
458
459     #added so that reference items are not available for reserves...
460     itemtypes         => { 'notforloan' => 'smallint(6)' },
461     systempreferences => {
462         'explanation' => 'char(80)',
463         'type'        => 'char(20)',
464         'options'     => 'text'
465     },
466     z3950servers       => { 'syntax' => 'char(80)' },
467     marc_tag_structure =>
468       { 'frameworkcode' => 'char(4) not NULL default \'\'' },
469     marc_subfield_structure => {
470         'seealso'       => 'char(255)',
471         'frameworkcode' => 'char(4) not NULL default \'\'',
472         'hidden'        => 'tinyint(1)',
473         'isurl'         => 'tinyint(1)',
474         'link'          => 'char(80)',
475     },
476     bookshelf => {
477         'owner'    => 'char(80)',
478         'category' => 'char(1)',
479     },
480     marc_biblio => { 'frameworkcode' => 'char(4) not NULL default \'\'' },
481 >>>>>>> 1.100.2.46
482 );
483
484 my %dropable_table = (
485         sessionqueries  => 'sessionqueries',
486         marcrecorddone  => 'marcrecorddone',
487         users                   => 'users',
488         itemsprices             => 'itemsprices',
489         biblioanalysis  => 'biblioanalysis',
490         borexp                  => 'borexp',
491 # tablename => 'tablename',
492 );
493
494 my %uselessfields = (
495 <<<<<<< updatedatabase
496 # tablename => "field1,field2",
497         borrowers => "suburb,altstreetaddress,altsuburb,altcity,studentnumber,school,area,preferredcont,altcp",
498         deletedborrowers=> "suburb,altstreetaddress,altsuburb,altcity,studentnumber,school,area,preferredcont,altcp",
499         );
500 =======
501     aqorders => "requisitionedby,authorisedby,booksellerid,
502                         deliverydays,followupdays,
503                         numberfollowupsallowed,numberfollowupssent,
504                         dateprinted,sourced,quantityreceiveddamaged,
505                         subscriptionfrom,subscriptionto
506                         "
507 );
508
509 >>>>>>> 1.100.2.46
510 # the other hash contains other actions that can't be done elsewhere. they are done
511 # either BEFORE of AFTER everything else, depending on "when" entry (default => AFTER)
512
513 # The tabledata hash contains data that should be in the tables.
514 # The uniquefieldrequired hash entry is used to determine which (if any) fields
515 # must not exist in the table for this row to be inserted.  If the
516 # uniquefieldrequired entry is already in the table, the existing data is not
517 # modified, unless the forceupdate hash entry is also set.  Fields in the
518 # anonymous "forceupdate" hash will be forced to be updated to the default
519 # values given in the %tabledata hash.
520
521 my %tabledata = (
522 <<<<<<< updatedatabase
523 # tablename => [
524 #       {       uniquefielrequired => 'fieldname', # the primary key in the table
525 #               fieldname => fieldvalue,
526 #               fieldname2 => fieldvalue2,
527 #       },
528 # ],
529 =======
530     userflags => [
531         {
532             uniquefieldrequired => 'bit',
533             bit                 => 0,
534             flag                => 'superlibrarian',
535             flagdesc            => 'Access to all librarian functions',
536             defaulton           => 0
537         },
538         {
539             uniquefieldrequired => 'bit',
540             bit                 => 1,
541             flag                => 'circulate',
542             flagdesc            => 'Circulate books',
543             defaulton           => 0
544         },
545         {
546             uniquefieldrequired => 'bit',
547             bit                 => 2,
548             flag                => 'catalogue',
549             flagdesc            => 'View Catalogue (Librarian Interface)',
550             defaulton           => 0
551         },
552         {
553             uniquefieldrequired => 'bit',
554             bit                 => 3,
555             flag                => 'parameters',
556             flagdesc            => 'Set Koha system paramters',
557             defaulton           => 0
558         },
559         {
560             uniquefieldrequired => 'bit',
561             bit                 => 4,
562             flag                => 'borrowers',
563             flagdesc            => 'Add or modify borrowers',
564             defaulton           => 0
565         },
566         {
567             uniquefieldrequired => 'bit',
568             bit                 => 5,
569             flag                => 'permissions',
570             flagdesc            => 'Set user permissions',
571             defaulton           => 0
572         },
573         {
574             uniquefieldrequired => 'bit',
575             bit                 => 6,
576             flag                => 'reserveforothers',
577             flagdesc            => 'Reserve books for patrons',
578             defaulton           => 0
579         },
580         {
581             uniquefieldrequired => 'bit',
582             bit                 => 7,
583             flag                => 'borrow',
584             flagdesc            => 'Borrow books',
585             defaulton           => 1
586         },
587         {
588             uniquefieldrequired => 'bit',
589             bit                 => 8,
590             flag                => 'reserveforself',
591             flagdesc            => 'Reserve books for self',
592             defaulton           => 0
593         },
594         {
595             uniquefieldrequired => 'bit',
596             bit                 => 9,
597             flag                => 'editcatalogue',
598             flagdesc  => 'Edit Catalogue (Modify bibliographic/holdings data)',
599             defaulton => 0
600         },
601         {
602             uniquefieldrequired => 'bit',
603             bit                 => 10,
604             flag                => 'updatecharges',
605             flagdesc            => 'Update borrower charges',
606             defaulton           => 0
607         },
608         {
609             uniquefieldrequired => 'bit',
610             bit                 => 11,
611             flag                => 'acquisition',
612             flagdesc            => 'Acquisition and/or suggestion management',
613             defaulton           => 0
614         },
615         {
616             uniquefieldrequired => 'bit',
617             bit                 => 12,
618             flag                => 'management',
619             flagdesc            => 'Set library management parameters',
620             defaulton           => 0
621         },
622         {
623             uniquefieldrequired => 'bit',
624             bit                 => 13,
625             flag                => 'tools',
626             flagdesc            => 'Use tools (export, import, barcodes)',
627             defaulton           => 0
628         },
629     ],
630 >>>>>>> 1.100.2.46
631     systempreferences => [
632                 {
633             uniquefieldrequired => 'variable',
634 <<<<<<< updatedatabase
635             variable            => 'Activate_Log',
636             value               => 'On',
637             forceupdate         => { 'explanation' => 1,
638                                      'type' => 1},
639             explanation         => 'Turn Log Actions on DB On an Off',
640             type                => 'YesNo',
641 =======
642             forceupdate         => {
643                 'explanation' => 1,
644                 'type'        => 1
645             },
646             variable => 'LibraryName',
647             value    =>
648 '<i><b>Koha<br/>Free Software ILS<br/><br/></b>Koha : a gift, a contribution<br/> in Maori</i>',
649             explanation => 'Library name as shown on main opac page',
650             type        => ''
651
652 >>>>>>> 1.100.2.46
653         },
654         {
655             uniquefieldrequired => 'variable',
656 <<<<<<< updatedatabase
657             variable            => 'IndependantBranches',
658             value               => 0,
659             forceupdate         => { 'explanation' => 1,
660                                      'type' => 1},
661             explanation         => 'Turn Branch independancy management On an Off',
662             type                => 'YesNo',
663 =======
664             forceupdate         => {
665                 'explanation' => 1,
666                 'type'        => 1
667             },
668             variable    => 'autoMemberNum',
669             value       => '1',
670             explanation => 'Member number is auto-calculated',
671             type        => 'YesNo'
672
673 >>>>>>> 1.100.2.46
674         },
675                 {
676             uniquefieldrequired => 'variable',
677 <<<<<<< updatedatabase
678             variable            => 'ReturnBeforeExpiry',
679             value               => 'Off',
680             forceupdate         => { 'explanation' => 1,
681                                      'type' => 1},
682             explanation         => 'If Yes, Returndate on issuing can\'t be after borrower card expiry',
683             type                => 'YesNo',
684 =======
685             forceupdate         => {
686                 'explanation' => 1,
687                 'type'        => 1,
688                 'options'     => 1
689             },
690             variable    => 'acquisitions',
691             value       => 'normal',
692             explanation =>
693 'Normal, budget-based acquisitions, or Simple bibliographic-data acquisitions',
694             type    => 'Choice',
695             options => 'simple|normal'
696         },
697         {
698             uniquefieldrequired => 'variable',
699             forceupdate         => {
700                 'explanation' => 1,
701                 'type'        => 1,
702                 'options'     => 1
703             },
704             variable    => 'dateformat',
705             value       => 'metric',
706             explanation =>
707               'date format (us mm/dd/yyyy, metric dd/mm/yyy, ISO yyyy/mm/dd)',
708             type    => 'Choice',
709             options => 'metric|us|iso'
710         },
711         {
712             uniquefieldrequired => 'variable',
713             variable            => 'template',
714             forceupdate         => {
715                 'explanation' => 1,
716                 'type'        => 1
717             },
718             value       => 'default',
719             explanation => 'Preference order for intranet interface templates',
720             type        => 'Themes'
721         },
722         {
723             uniquefieldrequired => 'variable',
724             variable            => 'autoBarcode',
725             forceupdate         => {
726                 'explanation' => 1,
727                 'type'        => 1
728             },
729             value       => 'yes',
730             explanation => 'Barcode is auto-calculated',
731             type        => 'YesNo'
732         },
733         {
734             uniquefieldrequired => 'variable',
735             variable            => 'insecure',
736             forceupdate         => {
737                 'explanation' => 1,
738                 'type'        => 1
739             },
740             value       => 'no',
741             explanation =>
742 'If YES, no auth at all is needed. Be careful if you set this to yes!',
743             type => 'YesNo'
744         },
745         {
746             uniquefieldrequired => 'variable',
747             variable            => 'authoritysep',
748             forceupdate         => {
749                 'explanation' => 1,
750                 'type'        => 1,
751                 'options'     => 1
752             },
753             value       => '--',
754             explanation =>
755               'the separator used in authority/thesaurus. Usually --',
756             type    => 'free',
757             options => '10'
758         },
759         {
760             uniquefieldrequired => 'variable',
761             variable            => 'opaclanguages',
762             forceupdate         => {
763                 'explanation' => 1,
764                 'type'        => 1
765             },
766             value       => 'en',
767             explanation =>
768 'Set the preferred order for translations.  The top language will be tried first.',
769             type => 'Languages'
770         },
771         {
772             uniquefieldrequired => 'variable',
773             variable            => 'opacthemes',
774             forceupdate         => {
775                 'explanation' => 1,
776                 'type'        => 1
777             },
778             value       => 'css',
779             explanation =>
780 'Set the preferred order for themes.  The top theme will be tried first.',
781             type => 'Themes'
782         },
783         {
784             uniquefieldrequired => 'variable',
785             variable            => 'timeout',
786             forceupdate         => {
787                 'explanation' => 1,
788                 'type'        => 1
789             },
790             value       => '1200',
791             explanation =>
792               'Inactivity timeout for cookies authentication (in seconds)',
793             type => 'Integer'
794         },
795         {
796             uniquefieldrequired => 'variable',
797             variable            => 'marc',
798             forceupdate         => {
799                 'explanation' => 1,
800                 'type'        => 1
801             },
802             value       => 'yes',
803             explanation => 'Turn on MARC support',
804             type        => 'YesNo'
805         },
806         {
807             uniquefieldrequired => 'variable',
808             variable            => 'sortbynonfiling',
809             forceupdate         => {
810                 'explanation' => 1,
811                 'type'        => 1
812             },
813             value       => 'no',
814             explanation => 'Sort search results by MARC nonfiling characters',
815             type        => 'YesNo'
816         },
817         {
818             uniquefieldrequired => 'variable',
819             variable            => 'marcflavour',
820             forceupdate         => {
821                 'explanation' => 1,
822                 'type'        => 1,
823                 'options'     => 1
824             },
825             value       => 'MARC21',
826             explanation =>
827 'your MARC flavor (MARC21 or UNIMARC) used for character encoding',
828             type    => 'Choice',
829             options => 'MARC21|UNIMARC'
830         },
831         {
832             uniquefieldrequired => 'variable',
833             variable            => 'checkdigit',
834             value               => 'none',
835             forceupdate         => {
836                 'explanation' => 1,
837                 'type'        => 1,
838                 'options'     => 1
839             },
840             explanation =>
841 'Validity checks on membership number: none or "Katipo" style checks',
842             type    => 'Choice',
843             options => 'none|katipo'
844         },
845         {
846             uniquefieldrequired => 'variable',
847             variable            => 'maxoutstanding',
848             forceupdate         => {
849                 'explanation' => 1,
850                 'type'        => 1
851             },
852             value       => '5',
853             explanation =>
854               'maximum amount withstanding to be able make reserves ',
855             type => 'Integer'
856         },
857         {
858             uniquefieldrequired => 'variable',
859             variable            => 'maxreserves',
860             forceupdate         => {
861                 'explanation' => 1,
862                 'type'        => 1
863             },
864             value       => '5',
865             explanation => 'maximum number of reserves a member can make',
866             type        => 'Integer'
867
868         },
869         {
870             uniquefieldrequired => 'variable',
871             variable            => 'noissuescharge',
872             forceupdate         => {
873                 'explanation' => 1,
874                 'type'        => 1
875             },
876             value       => '5',
877             explanation =>
878               'maximum amount withstanding to be able to check out an item',
879             type => 'Integer'
880
881         },
882         {
883             uniquefieldrequired => 'variable',
884             variable            => 'KohaAdminEmailAddress',
885             forceupdate         => {
886                 'explanation' => 1,
887                 'type'        => 1
888             },
889             value       => 'your.mail@here',
890             explanation => 'the email address where borrowers modifs are sent',
891             type        => 'free'
892         },
893         {
894             uniquefieldrequired => 'variable',
895             variable            => 'gist',
896             forceupdate         => {
897                 'explanation' => 1,
898                 'type'        => 1
899             },
900             value       => '0.125',
901             explanation =>
902               'the gist rate. NOT in %, but in numeric form (0.12 for 12%)',
903             type => 'free'
904         },
905         {
906             uniquefieldrequired => 'variable',
907             variable            => 'printcirculationslips',
908             forceupdate         => {
909                 'explanation' => 1,
910                 'type'        => 1
911             },
912             value       => '0',
913             explanation =>
914               'if set to 1, print circulation slips. If set to 0, don\'t',
915             type => 'free'
916         },
917         {
918             uniquefieldrequired => 'variable',
919             variable            => 'suggestion',
920             forceupdate         => {
921                 'explanation' => 1,
922                 'type'        => 1
923             },
924             value       => '0',
925             explanation => 'if set to 1, suggestions are activated in OPAC',
926             type        => 'free'
927         },
928         {
929             uniquefieldrequired => 'variable',
930             variable            => 'ISBD',
931             forceupdate         => {
932                 'explanation' => 1,
933                 'type'        => 1
934             },
935             value       => 'Fill with appropriate value...',
936             explanation => 'ISBD',
937             type        => 'free'
938         },
939         {
940             uniquefieldrequired => 'variable',
941             variable            => 'virtualshelves',
942             forceupdate         => {
943                 'explanation' => 1,
944                 'type'        => 1
945             },
946             value       => '0',
947             explanation => 'Set virtual shelves management ON or OFF',
948             type        => 'YesNo'
949         },
950         {
951             uniquefieldrequired => 'variable',
952             variable            => 'itemcallnumber',
953             forceupdate         => {
954                 'explanation' => 1,
955                 'type'        => 1
956             },
957             value       => '676a',
958             explanation =>
959 'The MARC field/subfield that is used to calculate the itemcallnumber (in UNIMARC : 676a for Dewey, 680a for Loc)',
960             type => 'free'
961         },
962         {
963             uniquefieldrequired => 'variable',
964             variable            => 'BiblioDefaultView',
965             value               => 'normal',
966             forceupdate         => {
967                 'explanation' => 1,
968                 'type'        => 1,
969                 'options'     => 1
970             },
971             explanation =>
972 'Define the default view of a biblio. Can be either normal, marc or isbd',
973             type    => 'Choice',
974             options => 'normal|marc|isbd'
975         },
976
977         {
978             uniquefieldrequired => 'variable',
979             variable            => 'LabelMARCView',
980             value               => 'standard',
981             forceupdate         => {
982                 'explanation' => 1,
983                 'type'        => 1,
984                 'options'     => 1
985             },
986             explanation => 'Define how a MARC record will display',
987             type        => 'Choice',
988             options     => 'standard|economical'
989 >>>>>>> 1.100.2.46
990         },
991
992         {
993             uniquefieldrequired => 'variable',
994             variable            => 'opacstylesheet',
995             value               => '',
996             forceupdate         => {
997                 'explanation' => 1,
998                 'type'        => 1
999             },
1000             explanation =>
1001 'Enter a complete URL to use an alternate layout stylesheet in OPAC',
1002             type => 'free',
1003         },
1004         {
1005             uniquefieldrequired => 'variable',
1006             variable            => 'opaccolorstylesheet',
1007             value               => '',
1008             forceupdate         => {
1009                 'explanation' => 1,
1010                 'type'        => 1
1011             },
1012             explanation =>
1013               'Enter the name of the color stylesheet to use in the OPAC',
1014             type => 'free',
1015         },
1016         {
1017             uniquefieldrequired => 'variable',
1018             variable            => 'opaclayoutstylesheet',
1019             value               => '',
1020             forceupdate         => {
1021                 'explanation' => 1,
1022                 'type'        => 1
1023             },
1024             explanation =>
1025               'Enter the name of the layout stylesheet to use in the OPAC',
1026             type => 'free',
1027         },
1028
1029         {
1030             uniquefieldrequired => 'variable',
1031             variable            => 'opacreadinghistory',
1032             value               => '1',
1033             forceupdate         => {
1034                 'explanation' => 1,
1035                 'type'        => 1
1036             },
1037             explanation =>
1038               'Turn on/off display of Patron Reading History in OPAC',
1039             type => 'YesNo',
1040         },
1041         {
1042             uniquefieldrequired => 'variable',
1043             variable            => 'opaclanguagesdisplay',
1044             value               => '1',
1045             forceupdate         => {
1046                 'explanation' => 1,
1047                 'type'        => 1
1048             },
1049             explanation =>
1050               'Turn on/off display of Change Language feature on OPAC',
1051             type => 'YesNo',
1052         },
1053         {
1054             uniquefieldrequired => 'variable',
1055             variable            => 'patronimages',
1056             value               => '0',
1057             forceupdate         => {
1058                 'explanation' => 1,
1059                 'type'        => 1
1060             },
1061             explanation =>
1062 'Turn on/off display of patron images in Intranet and specify a file extension for images',
1063             type => 'free',
1064         },
1065         {
1066             uniquefieldrequired => 'variable',
1067             variable            => 'intranetstylesheet',
1068             value               => '',
1069             forceupdate         => {
1070                 'explanation' => 1,
1071                 'type'        => 1
1072             },
1073             explanation =>
1074 'Enter a complete URL to use an alternate layout stylesheet in Intranet',
1075             type => 'free',
1076         },
1077         {
1078             uniquefieldrequired => 'variable',
1079             variable            => 'intranetcolorstylesheet',
1080             value               => '',
1081             forceupdate         => {
1082                 'explanation' => 1,
1083                 'type'        => 1
1084             },
1085             explanation =>
1086               'Enter the name of the color stylesheet to use in Intranet',
1087             type => 'free',
1088         },
1089         {
1090             uniquefieldrequired => 'variable',
1091             variable            => 'opacsmallimage',
1092             value               => '',
1093             forceupdate         => {
1094                 'explanation' => 1,
1095                 'type'        => 1
1096             },
1097             explanation =>
1098 'Enter a complete URL to an image, will be on top/left instead of the Koha logo',
1099             type => 'free',
1100         },
1101         {
1102             uniquefieldrequired => 'variable',
1103             variable            => 'opaclargeimage',
1104             value               => '',
1105             forceupdate         => {
1106                 'explanation' => 1,
1107                 'type'        => 1
1108             },
1109             explanation =>
1110 'Enter a complete URL to an image, will be on the main page, instead of the Koha logo',
1111             type => 'free',
1112         },
1113         {
1114             uniquefieldrequired => 'variable',
1115             variable            => 'delimiter',
1116             value               => ';',
1117             forceupdate         => {
1118                 'explanation' => 1,
1119                 'type'        => 1
1120             },
1121             explanation => 'separator for reports exported to spreadsheet',
1122             type        => 'free',
1123         },
1124         {
1125             uniquefieldrequired => 'variable',
1126             variable            => 'MIME',
1127             value               => 'OPENOFFICE.ORG',
1128             forceupdate         => {
1129                 'explanation' => 1,
1130                 'type'        => 1,
1131                 'options'     => 1
1132             },
1133             explanation =>
1134 'Define the default application for report exportations into files',
1135             type    => 'Choice',
1136             options => 'EXCEL|OPENOFFICE.ORG'
1137         },
1138         {
1139             uniquefieldrequired => 'variable',
1140             variable            => 'Delimiter',
1141             value               => ';',
1142             forceupdate         => {
1143                 'explanation' => 1,
1144                 'type'        => 1,
1145                 'options'     => 1
1146             },
1147             explanation =>
1148 'Define the default separator character for report exportations into files',
1149             type    => 'Choice',
1150             options => ';|tabulation|,|/|\|#'
1151         },
1152         {
1153             uniquefieldrequired => 'variable',
1154             variable            => 'SubscriptionHistory',
1155             value               => ';',
1156             forceupdate         => {
1157                 'explanation' => 1,
1158                 'type'        => 1,
1159                 'options'     => 1
1160             },
1161             explanation =>
1162               'Define the information level for serials history in OPAC',
1163             type    => 'Choice',
1164             options => 'simplified|full'
1165         },
1166         {
1167             uniquefieldrequired => 'variable',
1168             variable            => 'hidelostitems',
1169             value               => 'No',
1170             forceupdate         => {
1171                 'explanation' => 1,
1172                 'type'        => 1
1173             },
1174             explanation => 'show or hide "lost" items in OPAC.',
1175             type        => 'YesNo',
1176         },
1177         {
1178             uniquefieldrequired => 'variable',
1179             variable            => 'IndependantBranches',
1180             value               => '0',
1181             forceupdate         => {
1182                 'explanation' => 1,
1183                 'type'        => 1
1184             },
1185             explanation => 'Turn Branch independency management On and Off',
1186             type        => 'YesNo',
1187         },
1188         {
1189             uniquefieldrequired => 'variable',
1190             variable            => 'ReturnBeforeExpiry',
1191             value               => '0',
1192             forceupdate         => {
1193                 'explanation' => 1,
1194                 'type'        => 1
1195             },
1196             explanation =>
1197 'If Yes, Returndate on issuing can\'t be after borrower card expiry',
1198             type => 'YesNo',
1199         },
1200         {
1201             uniquefieldrequired => 'variable',
1202             variable            => 'Disable_Dictionary',
1203             value               => '0',
1204             forceupdate         => {
1205                 'explanation' => 1,
1206                 'type'        => 1
1207             },
1208             explanation => 'Disables Dictionary buttons if set to yes',
1209             type        => 'YesNo',
1210         },
1211         {
1212             uniquefieldrequired => 'variable',
1213             variable            => 'hide_marc',
1214             value               => '0',
1215             forceupdate         => {
1216                 'explanation' => 1,
1217                 'type'        => 1
1218             },
1219             explanation =>
1220 'hide marc specific datas like subfield code & indicators to library',
1221             type => 'YesNo',
1222         },
1223         {
1224             uniquefieldrequired => 'variable',
1225             variable            => 'NotifyBorrowerDeparture',
1226             value               => '0',
1227             forceupdate         => {
1228                 'explanation' => 1,
1229                 'type'        => 1
1230             },
1231             explanation =>
1232               'Delay before expiry where a notice is sent when issuing',
1233             type => 'Integer',
1234         },
1235         {
1236             uniquefieldrequired => 'variable',
1237             variable            => 'OpacPasswordChange',
1238             value               => '1',
1239             forceupdate         => {
1240                 'explanation' => 1,
1241                 'type'        => 1
1242             },
1243             explanation =>
1244 'Enable/Disable password change in OPAC (disable it when using LDAP auth)',
1245             type => 'YesNo',
1246         },
1247         {
1248             uniquefieldrequired => 'variable',
1249             variable            => 'OpacNav',
1250             value               => '',
1251             forceupdate         => {
1252                 'explanation' => 1,
1253                 'type'        => 1
1254             },
1255             explanation =>
1256 'Use HTML tabs to add navigational links to the left-hand navigational bar in OPAC',
1257             type    => 'Textarea',
1258             options => '70|10'
1259         },
1260         {
1261             uniquefieldrequired => 'variable',
1262             variable            => 'IntranetNav',
1263             value               => '',
1264             forceupdate         => {
1265                 'explanation' => 1,
1266                 'type'        => 1
1267             },
1268             explanation =>
1269 'Use HTML tabs to add navigational links to the left-hand navigational bar in Intranet',
1270             type    => 'Textarea',
1271             options => '70|10'
1272         },
1273
1274         {
1275             uniquefieldrequired => 'variable',
1276             variable            => 'AnonSuggestions',
1277             value               => '0',
1278             forceupdate         => {
1279                 'explanation' => 1,
1280                 '
1281                                         type' => 1
1282             },
1283             explanation =>
1284               'Set to anonymous borrowernumber to enable Anonymous suggestions',
1285             type => 'free',
1286         },
1287         {
1288             uniquefieldrequired => 'variable',
1289             variable            => 'MARCOrgCode',
1290             value               => '0',
1291             forceupdate         => {
1292                 'explanation' => 1,
1293                 '
1294                         type' => 1
1295             },
1296             explanation =>
1297 'Your MARC Organization Code - http://www.loc.gov/marc/organizations/orgshome.html',
1298             type => 'free',
1299         },
1300         {
1301             uniquefieldrequired => 'variable',
1302             variable            => 'AmazonContent',
1303             value               => '0',
1304             forceupdate         => {
1305                 'explanation' => 1,
1306                 '
1307                                         type' => 1
1308             },
1309             explanation =>
1310 'Turn On Amazon Content - You MUST set AmazonDevKey and AmazonAssocTag if enabled',
1311             type => 'YesNo',
1312         },
1313         {
1314             uniquefieldrequired => 'variable',
1315             variable            => 'AmazonDevKey',
1316             value               => '',
1317             forceupdate         => {
1318                 'explanation' => 1,
1319                 '
1320                                         type' => 1
1321             },
1322             explanation =>
1323 'see: aws-portal.amazon.com/gp/aws/developer/registration/index.html',
1324             type => 'free',
1325         },
1326         {
1327             uniquefieldrequired => 'variable',
1328             variable            => 'AmazonAssocTag',
1329             value               => '',
1330             forceupdate         => {
1331                 'explanation' => 1,
1332                 '
1333                                         type' => 1
1334             },
1335             explanation =>
1336               'see: associates.amazon.com/gp/flex/associates/apply-login.html',
1337             type => 'free',
1338         },
1339         {
1340             uniquefieldrequired => 'variable',
1341             forceupdate         => {
1342                 'explanation' => 1,
1343                 'type'        => 1,
1344                 'options'     => 1
1345             },
1346             variable    => 'TemplateEncoding',
1347             value       => 'iso-8859-1',
1348             explanation => 'Specify the encoding to use in Templates',
1349             type        => 'Choice',
1350             options     => 'iso-8859-1|utf-8'
1351         },
1352
1353         {
1354             uniquefieldrequired => 'variable',
1355             variable            => 'opaccredits',
1356             value               => '',
1357             forceupdate         => {
1358                 'explanation' => 1,
1359                 '
1360                                         type' => 1
1361             },
1362             explanation =>
1363               'Put any HTML Credits at the bottom of the OPAC page',
1364             type    => 'Textarea',
1365             options => '70|10'
1366         },
1367                 
1368 {
1369             uniquefieldrequired => 'variable',
1370             variable            => 'opacheader',
1371             value               => '',
1372             forceupdate         => { 'explanation' => 1,                                                                        
1373                                                         'type' => 1},
1374             explanation         => 'Enter HTML to be included as a custom header in the OPAC',
1375             type                => 'Textarea',
1376                         options                         => '30|10'
1377         },
1378
1379                 {
1380             uniquefieldrequired => 'variable',
1381             variable            => 'IntranetBiblioDefaultView',
1382             value               => 'marc',
1383             forceupdate         => { 'explanation' => 1,                                                             
1384                                                                 'type' => 1},
1385             explanation         => 'Define the default view of a biblio in the intranet. Can be either normal, marc, or ISBD',
1386             type                => 'Choice',
1387                         options                         => 'normal|marc|isbd'
1388         },
1389                 
1390                                 {
1391             uniquefieldrequired => 'variable',
1392             variable            => 'opacbookbag',
1393             value               => '1',
1394             forceupdate         => { 'explanation' => 1,                                                             
1395                                                                 'type' => 1},
1396             explanation         => 'Enable or disable display of biblio basket (book bag)',
1397             type                => 'YesNo'
1398         },
1399                 
1400                                 {
1401             uniquefieldrequired => 'variable',
1402             variable            => 'opacuserlogin',
1403             value               => '1',
1404             forceupdate         => { 'explanation' => 1,                                                             
1405                                                                 'type' => 1},
1406             explanation         => 'Enable or disable display of user login features',
1407             type                => 'YesNo'
1408         },
1409                 
1410         {
1411             uniquefieldrequired => 'variable',
1412             variable            => 'serialsadditems',
1413             value               => '0',
1414             forceupdate         => {
1415                 'explanation' => 1,
1416                 '
1417                                         type' => 1
1418             },
1419             explanation =>
1420 'If set, a new item will be automatically added when receiving an issue',
1421             type => 'YesNo',
1422         },
1423         {
1424             uniquefieldrequired => 'variable',
1425             variable            => 'advancedMARCeditor',
1426             value               => '0',
1427             forceupdate         => {
1428                 'explanation' => 1,
1429                 '
1430                                         type' => 1
1431             },
1432             explanation =>
1433 "If set, the MARC editor won't show you tag/subfields description",
1434             type => 'YesNo',
1435         },
1436         {
1437             uniquefieldrequired => 'variable',
1438             variable            => 'z3950NormalizeAuthor',
1439             value               => '0',
1440             forceupdate         => {
1441                 'explanation' => 1,
1442                 '
1443                                         type' => 1
1444             },
1445             explanation =>
1446 "If set, Personnal Authorities will replace authors in biblio.author",
1447             type => 'YesNo',
1448         },
1449         {
1450             uniquefieldrequired => 'variable',
1451             variable            => 'z3950AuthorAuthFields',
1452             value               => '701,702,700',
1453             forceupdate         => {
1454                 'explanation' => 1,
1455                 '
1456                                         type' => 1
1457             },
1458             explanation =>
1459 "contains the MARC biblio tags of person authorities to fill biblio.author with when importing biblio",
1460             type => 'free',
1461         },
1462         {
1463             uniquefieldrequired => 'variable',
1464             variable            => 'useDaysMode',
1465             value               => 'Calendar',
1466             forceupdate         => { 'explanation' => 1,
1467                                      'type' => 1},
1468             explanation                 => 'How to calculate return dates : Calendar means holidays will be controled, Days means the return date don\'t depend on holidays',
1469                 type            => 'Choice',
1470                 options         => 'Calendar|Days'
1471         },
1472         {
1473             uniquefieldrequired => 'variable',
1474             variable            => 'borrowerMandatoryField',
1475             value               => 'zipcode|surname',
1476             forceupdate         => { 'explanation' => 1,
1477                                      'type' => 1},
1478             explanation         => 'List all mandatory fields for borrowers',
1479             type                => 'free',
1480         },
1481         {
1482 <<<<<<< updatedatabase
1483             uniquefieldrequired => 'variable',
1484             variable            => 'borrowerRelationship',
1485             value               => 'father|mother,grand-mother',
1486             forceupdate         => { 'explanation' => 1,
1487                                      'type' => 1},
1488             explanation         => 'The relationships between a guarantor & a guarantee (separated by | or ,)',
1489             type                => 'free',
1490 =======
1491             field   => 'aqbudgetid',
1492             type    => 'tinyint(4)',
1493             null    => '',
1494             key     => 'PRI',
1495             default => '',
1496             extra   => 'auto_increment'
1497 >>>>>>> 1.100.2.46
1498         },
1499         {
1500             uniquefieldrequired => 'variable',
1501             variable            => 'ReservesMaxPickUpDelay',
1502             value               => '10',
1503             forceupdate         => { 'explanation' => 1,
1504                                      'type' => 1},
1505             explanation         => 'Maximum delay to pick up a reserved document',
1506             type                => 'free',
1507         },
1508 <<<<<<< updatedatabase
1509 =======
1510     ],
1511     marc_breeding => [
1512 >>>>>>> 1.100.2.46
1513         {
1514             uniquefieldrequired => 'variable',
1515             variable            => 'TransfersMaxDaysWarning',
1516             value               => '3',
1517             forceupdate         => { 'explanation' => 1,
1518                                      'type' => 1},
1519             explanation         => 'Max delay before considering the transfer has potentialy a problem',
1520             type                => 'free',
1521         },
1522         {
1523             uniquefieldrequired => 'variable',
1524             variable            => 'memberofinstitution',
1525             value               => '0',
1526             forceupdate         => { 'explanation' => 1,
1527                                      'type' => 1},
1528             explanation         => 'Are your patrons members of institutions',
1529             type                => 'YesNo',
1530         },
1531         {
1532             uniquefieldrequired => 'variable',
1533             variable            => 'ReadingHistory',
1534             value               => '0',
1535             forceupdate         => { 'explanation' => 1,
1536                                      'type' => 1},
1537             explanation         => 'Allow reading record info retrievable from issues and oldissues tables',
1538             type                => 'YesNo',
1539         },
1540         {
1541             uniquefieldrequired => 'variable',
1542             variable            => 'IssuingInProcess',
1543             value               => '0',
1544             forceupdate         => { 'explanation' => 1,
1545                                      'type' => 1},
1546             explanation         => 'Allow no debt alert if the patron is issuing item that accumulate debt',
1547             type                => 'YesNo',
1548         },
1549         {
1550             uniquefieldrequired => 'variable',
1551             variable            => 'AutomaticItemReturn',
1552             value               => '1',
1553             forceupdate         => { 'explanation' => 1,
1554                                      'type' => 1},
1555             explanation         => 'This Variable allow or not to return automaticly to his homebranch',
1556             type                => 'YesNo',
1557         },
1558         {
1559             uniquefieldrequired => 'variable',
1560             variable            => 'reviewson',
1561             value               => '0',
1562             forceupdate         => { 'explanation' => 1,
1563                                      'type' => 1},
1564             explanation         => 'Allows patrons to submit reviews from the opac',
1565             type                => 'YesNo',
1566         },
1567     ],
1568 <<<<<<< updatedatabase
1569
1570 );
1571
1572 my %fielddefinitions = (
1573 # fieldname => [
1574 #       {                 field => 'fieldname',
1575 #             type    => 'fieldtype',
1576 #             null    => '',
1577 #             key     => '',
1578 #             default => ''
1579 #         },
1580 #     ],
1581         serial => [
1582 =======
1583     serial => [
1584 >>>>>>> 1.100.2.46
1585         {
1586             field   => 'notes',
1587             type    => 'TEXT',
1588             null    => 'NULL',
1589             key     => '',
1590             default => '',
1591             extra   => ''
1592         },
1593     ],
1594 <<<<<<< updatedatabase
1595         aqbasket =>  [
1596                 {
1597                         field   => 'booksellerid',
1598                         type    => 'int(11)',
1599                         null    => 'NOT NULL',
1600                         key             => '',
1601                         default => '1',
1602                         extra   => '',
1603                 },
1604         ],
1605         aqbooksellers =>  [
1606                 {
1607                         field   => 'listprice',
1608                         type    => 'varchar(10)',
1609                         null    => 'NULL',
1610                         key             => '',
1611                         default => '',
1612                         extra   => '',
1613                 },
1614                 {
1615                         field   => 'invoiceprice',
1616                         type    => 'varchar(10)',
1617                         null    => 'NULL',
1618                         key             => '',
1619                         default => '',
1620                         extra   => '',
1621                 },
1622         ],
1623         issues =>  [
1624                 {
1625                         field   => 'borrowernumber',
1626                         type    => 'int(11)',
1627                         null    => 'NULL', # can be null when a borrower is deleted and the foreign key rule executed
1628                         key             => '',
1629                         default => '',
1630                         extra   => '',
1631                 },
1632                 {
1633                         field   => 'itemnumber',
1634                         type    => 'int(11)',
1635                         null    => 'NULL', # can be null when a borrower is deleted and the foreign key rule executed
1636                         key             => '',
1637                         default => '',
1638                         extra   => '',
1639                 },
1640         ],
1641         borrowers => [
1642                 {       field => 'firstname',
1643                         type => 'text',
1644                         null => 'NULL',
1645                  },
1646                 {       field => 'initials',
1647                         type => 'text',
1648                         null => 'NULL',
1649                  },
1650                 {       field => 'B_email',
1651                         type => 'text',
1652                         null => 'NULL',
1653                         after => 'B_zipcode',
1654                  },
1655                  {
1656                         field => 'streetnumber', # street number (hidden if streettable table is empty)
1657                         type => 'char(10)',
1658                         null => 'NULL',
1659                         after => 'initials',
1660                 },
1661                 {
1662                         field => 'streettype', # street table, list builded from a system table
1663                         type => 'char(50)',
1664                         null => 'NULL',
1665                         after => 'streetnumber',
1666                 },
1667                 {       field => 'phone',
1668                         type => 'text',
1669                         null => 'NULL',
1670                  },                             
1671                 {
1672                         field => 'B_streetnumber', # street number (hidden if streettable table is empty)
1673                         type => 'char(10)',
1674                         null => 'NULL',
1675                         after => 'fax',
1676                 },
1677                 {
1678                         field => 'B_streettype', # street table, list builded from a system table
1679                         type => 'char(50)',
1680                         null => 'NULL',
1681                         after => 'B_streetnumber',
1682                 },
1683                 {
1684                         field => 'phonepro',
1685                         type => 'text',
1686                         null => 'NULL',
1687                         after => 'fax',
1688                 },
1689                 {
1690                         field => 'address2', # complement address
1691                         type => 'text',
1692                         null => 'NULL',
1693                         after => 'address',
1694                 },
1695                 {
1696                         field => 'emailpro',
1697                         type => 'text',
1698                         null => 'NULL',
1699                         after => 'fax',
1700                 },
1701                 {
1702                         field => 'contactfirstname', # contact's firstname
1703                         type => 'text',
1704                         null => 'NULL',
1705                         after => 'contactname',
1706                 },
1707                 {
1708                         field => 'contacttitle', # contact's title
1709                         type => 'text',
1710                         null => 'NULL',
1711                         after => 'contactfirstname',
1712                 },
1713         ],
1714         
1715         deletedborrowers => [
1716                 {       field => 'firstname',
1717                         type => 'text',
1718                         null => 'NULL',
1719                  },
1720                 {       field => 'initials',
1721                         type => 'text',
1722                         null => 'NULL',
1723                  },
1724                 {       field => 'B_email',
1725                         type => 'text',
1726                         null => 'NULL',
1727                         after => 'B_zipcode',
1728                  },
1729                  {
1730                         field => 'streetnumber', # street number (hidden if streettable table is empty)
1731                         type => 'char(10)',
1732                         null => 'NULL',
1733                         after => 'initials',
1734                 },
1735                 {
1736                         field => 'streettype', # street table, list builded from a system table
1737                         type => 'char(50)',
1738                         null => 'NULL',
1739                         after => 'streetnumber',
1740                 },
1741                 {       field => 'phone',
1742                         type => 'text',
1743                         null => 'NULL',
1744                  },             
1745                  {
1746                         field => 'B_streetnumber', # street number (hidden if streettable table is empty)
1747                         type => 'char(10)',
1748                         null => 'NULL',
1749                         after => 'fax',
1750                 },
1751                 {
1752                         field => 'B_streettype', # street table, list builded from a system table
1753                         type => 'char(50)',
1754                         null => 'NULL',
1755                         after => 'B_streetnumber',
1756                 },
1757                 {
1758                         field => 'phonepro',
1759                         type => 'text',
1760                         null => 'NULL',
1761                         after => 'fax',
1762                 },
1763                 {
1764                         field => 'address2', # complement address
1765                         type => 'text',
1766                         null => 'NULL',
1767                         after => 'address',
1768                 },
1769                 {
1770                         field => 'emailpro',
1771                         type => 'text',
1772                         null => 'NULL',
1773                         after => 'fax',
1774                 },
1775                 {
1776                         field => 'contactfirstname', # contact's firstname
1777                         type => 'text',
1778                         null => 'NULL',
1779                         after => 'contactname',
1780                 },
1781                 {
1782                         field => 'contacttitle', # contact's title
1783                         type => 'text',
1784                         null => 'NULL',
1785                         after => 'contactfirstname',
1786                 },
1787         ],
1788         
1789         branches =>  [
1790                 {
1791                         field   => 'branchip',
1792                         type    => 'varchar(15)',
1793                         null    => 'NULL',
1794                         key             => '',
1795                         default => '',
1796                         extra   => '',
1797                 },
1798                 {
1799                         field   => 'branchprinter',
1800                         type    => 'varchar(100)',
1801                         null    => 'NULL',
1802                         key             => '',
1803                         default => '',
1804                         extra   => '',
1805                 },
1806         ],
1807         categories =>  [
1808                 {
1809                         field   => 'category_type',
1810                         type    => 'char(1)',
1811                         null    => 'NOT NULL',
1812                         key             => '',
1813                         default => 'A',
1814                         extra   => '',
1815                 },
1816         ],
1817         reserves =>  [
1818                 {
1819                         field   => 'waitingdate',
1820                         type    => 'date',
1821                         null    => 'NULL',
1822                         key             => '',
1823                         default => '',
1824                         extra   => '',
1825                 },
1826         ],
1827 );
1828
1829 my %indexes = (
1830 #       table => [
1831 #               {       indexname => 'index detail'
1832 #               }
1833 #       ],
1834         shelfcontents => [
1835                 {       indexname => 'shelfnumber',
1836                         content => 'shelfnumber',
1837                 },
1838                 {       indexname => 'itemnumber',
1839                         content => 'itemnumber',
1840                 }
1841         ],
1842         bibliosubject => [
1843                 {       indexname => 'biblionumber',
1844                         content => 'biblionumber',
1845                 }
1846         ],
1847         items => [
1848                 {       indexname => 'homebranch',
1849                         content => 'homebranch',
1850                 },
1851                 {       indexname => 'holdingbranch',
1852                         content => 'holdingbranch',
1853                 }
1854         ],
1855         aqbooksellers => [
1856                 {       indexname => 'PRIMARY',
1857                         content => 'id',
1858                         type => 'PRIMARY',
1859                 }
1860         ],
1861         aqbasket => [
1862                 {       indexname => 'booksellerid',
1863                         content => 'booksellerid',
1864                 },
1865         ],
1866         aqorders => [
1867                 {       indexname => 'basketno',
1868                         content => 'basketno',
1869                 },
1870         ],
1871         aqorderbreakdown => [
1872                 {       indexname => 'ordernumber',
1873                         content => 'ordernumber',
1874                 },
1875                 {       indexname => 'bookfundid',
1876                         content => 'bookfundid',
1877                 },
1878         ],
1879         currency => [
1880                 {       indexname => 'PRIMARY',
1881                         content => 'currency',
1882                         type => 'PRIMARY',
1883                 }
1884         ],
1885 =======
1886     biblioitems => [
1887         {
1888             field   => 'dewey',
1889             type    => 'varchar(30)',
1890             null    => 'NULL',
1891             key     => '',
1892             default => '',
1893             extra   => ''
1894         },
1895     ],
1896 >>>>>>> 1.100.2.46
1897 );
1898
1899 my %foreign_keys = (
1900 #       table => [
1901 #               {       key => 'the key in table' (must be indexed)
1902 #                       foreigntable => 'the foreigntable name', # (the parent)
1903 #                       foreignkey => 'the foreign key column(s)' # (in the parent)
1904 #                       onUpdate => 'CASCADE|SET NULL|NO ACTION| RESTRICT',
1905 #                       onDelete => 'CASCADE|SET NULL|NO ACTION| RESTRICT',
1906 #               }
1907 #       ],
1908         shelfcontents => [
1909                 {       key => 'shelfnumber',
1910                         foreigntable => 'bookshelf',
1911                         foreignkey => 'shelfnumber',
1912                         onUpdate => 'CASCADE',
1913                         onDelete => 'CASCADE',
1914                 },
1915                 {       key => 'itemnumber',
1916                         foreigntable => 'items',
1917                         foreignkey => 'itemnumber',
1918                         onUpdate => 'CASCADE',
1919                         onDelete => 'CASCADE',
1920                 },
1921         ],
1922         # onDelete is RESTRICT on reference tables (branches, itemtype) as we don't want items to be 
1923         # easily deleted, but branches/itemtype not too easy to empty...
1924         biblioitems => [
1925                 {       key => 'biblionumber',
1926                         foreigntable => 'biblio',
1927                         foreignkey => 'biblionumber',
1928                         onUpdate => 'CASCADE',
1929                         onDelete => 'CASCADE',
1930                 },
1931                 {       key => 'itemtype',
1932                         foreigntable => 'itemtypes',
1933                         foreignkey => 'itemtype',
1934                         onUpdate => 'CASCADE',
1935                         onDelete => 'RESTRICT',
1936                 },
1937         ],
1938         items => [
1939                 {       key => 'biblioitemnumber',
1940                         foreigntable => 'biblioitems',
1941                         foreignkey => 'biblioitemnumber',
1942                         onUpdate => 'CASCADE',
1943                         onDelete => 'CASCADE',
1944                 },
1945                 {       key => 'homebranch',
1946                         foreigntable => 'branches',
1947                         foreignkey => 'branchcode',
1948                         onUpdate => 'CASCADE',
1949                         onDelete => 'RESTRICT',
1950                 },
1951                 {       key => 'holdingbranch',
1952                         foreigntable => 'branches',
1953                         foreignkey => 'branchcode',
1954                         onUpdate => 'CASCADE',
1955                         onDelete => 'RESTRICT',
1956                 },
1957         ],
1958         additionalauthors => [
1959                 {       key => 'biblionumber',
1960                         foreigntable => 'biblio',
1961                         foreignkey => 'biblionumber',
1962                         onUpdate => 'CASCADE',
1963                         onDelete => 'CASCADE',
1964                 },
1965         ],
1966         bibliosubject => [
1967                 {       key => 'biblionumber',
1968                         foreigntable => 'biblio',
1969                         foreignkey => 'biblionumber',
1970                         onUpdate => 'CASCADE',
1971                         onDelete => 'CASCADE',
1972                 },
1973         ],
1974         aqbasket => [
1975                 {       key => 'booksellerid',
1976                         foreigntable => 'aqbooksellers',
1977                         foreignkey => 'id',
1978                         onUpdate => 'CASCADE',
1979                         onDelete => 'RESTRICT',
1980                 },
1981         ],
1982         aqorders => [
1983                 {       key => 'basketno',
1984                         foreigntable => 'aqbasket',
1985                         foreignkey => 'basketno',
1986                         onUpdate => 'CASCADE',
1987                         onDelete => 'CASCADE',
1988                 },
1989                 {       key => 'biblionumber',
1990                         foreigntable => 'biblio',
1991                         foreignkey => 'biblionumber',
1992                         onUpdate => 'SET NULL',
1993                         onDelete => 'SET NULL',
1994                 },
1995         ],
1996         aqbooksellers => [
1997                 {       key => 'listprice',
1998                         foreigntable => 'currency',
1999                         foreignkey => 'currency',
2000                         onUpdate => 'CASCADE',
2001                         onDelete => 'CASCADE',
2002                 },
2003                 {       key => 'invoiceprice',
2004                         foreigntable => 'currency',
2005                         foreignkey => 'currency',
2006                         onUpdate => 'CASCADE',
2007                         onDelete => 'CASCADE',
2008                 },
2009         ],
2010         aqorderbreakdown => [
2011                 {       key => 'ordernumber',
2012                         foreigntable => 'aqorders',
2013                         foreignkey => 'ordernumber',
2014                         onUpdate => 'CASCADE',
2015                         onDelete => 'CASCADE',
2016                 },
2017                 {       key => 'bookfundid',
2018                         foreigntable => 'aqbookfund',
2019                         foreignkey => 'bookfundid',
2020                         onUpdate => 'CASCADE',
2021                         onDelete => 'CASCADE',
2022                 },
2023         ],
2024         branchtransfers => [
2025                 {       key => 'frombranch',
2026                         foreigntable => 'branches',
2027                         foreignkey => 'branchcode',
2028                         onUpdate => 'CASCADE',
2029                         onDelete => 'CASCADE',
2030                 },
2031                 {       key => 'tobranch',
2032                         foreigntable => 'branches',
2033                         foreignkey => 'branchcode',
2034                         onUpdate => 'CASCADE',
2035                         onDelete => 'CASCADE',
2036                 },
2037                 {       key => 'itemnumber',
2038                         foreigntable => 'items',
2039                         foreignkey => 'itemnumber',
2040                         onUpdate => 'CASCADE',
2041                         onDelete => 'CASCADE',
2042                 },
2043         ],
2044         issuingrules => [
2045                 {       key => 'categorycode',
2046                         foreigntable => 'categories',
2047                         foreignkey => 'categorycode',
2048                         onUpdate => 'CASCADE',
2049                         onDelete => 'CASCADE',
2050                 },
2051                 {       key => 'itemtype',
2052                         foreigntable => 'itemtypes',
2053                         foreignkey => 'itemtype',
2054                         onUpdate => 'CASCADE',
2055                         onDelete => 'CASCADE',
2056                 },
2057         ],
2058         issues => [     # constraint is SET NULL : when a borrower or an item is deleted, we keep the issuing record
2059         # for stat purposes
2060                 {       key => 'borrowernumber',
2061                         foreigntable => 'borrowers',
2062                         foreignkey => 'borrowernumber',
2063                         onUpdate => 'SET NULL',
2064                         onDelete => 'SET NULL',
2065                 },
2066                 {       key => 'itemnumber',
2067                         foreigntable => 'items',
2068                         foreignkey => 'itemnumber',
2069                         onUpdate => 'SET NULL',
2070                         onDelete => 'SET NULL',
2071                 },
2072         ],
2073         reserves => [
2074                 {       key => 'borrowernumber',
2075                         foreigntable => 'borrowers',
2076                         foreignkey => 'borrowernumber',
2077                         onUpdate => 'CASCADE',
2078                         onDelete => 'CASCADE',
2079                 },
2080                 {       key => 'biblionumber',
2081                         foreigntable => 'biblio',
2082                         foreignkey => 'biblionumber',
2083                         onUpdate => 'CASCADE',
2084                         onDelete => 'CASCADE',
2085                 },
2086                 {       key => 'itemnumber',
2087                         foreigntable => 'items',
2088                         foreignkey => 'itemnumber',
2089                         onUpdate => 'CASCADE',
2090                         onDelete => 'CASCADE',
2091                 },
2092                 {       key => 'branchcode',
2093                         foreigntable => 'branches',
2094                         foreignkey => 'branchcode',
2095                         onUpdate => 'CASCADE',
2096                         onDelete => 'CASCADE',
2097                 },
2098         ],
2099         borrowers => [ # foreign keys are RESTRICT as we don't want to delete borrowers when a branch is deleted
2100         # but prevent deleting a branch as soon as it has 1 borrower !
2101                 {       key => 'categorycode',
2102                         foreigntable => 'categories',
2103                         foreignkey => 'categorycode',
2104                         onUpdate => 'RESTRICT',
2105                         onDelete => 'RESTRICT',
2106                 },
2107                 {       key => 'branchcode',
2108                         foreigntable => 'branches',
2109                         foreignkey => 'branchcode',
2110                         onUpdate => 'RESTRICT',
2111                         onDelete => 'RESTRICT',
2112                 },
2113         ],
2114         deletedborrowers => [ # foreign keys are RESTRICT as we don't want to delete borrowers when a branch is deleted
2115         # but prevent deleting a branch as soon as it has 1 borrower !
2116                 {       key => 'categorycode',
2117                         foreigntable => 'categories',
2118                         foreignkey => 'categorycode',
2119                         onUpdate => 'RESTRICT',
2120                         onDelete => 'RESTRICT',
2121                 },
2122                 {       key => 'branchcode',
2123                         foreigntable => 'branches',
2124                         foreignkey => 'branchcode',
2125                         onUpdate => 'RESTRICT',
2126                         onDelete => 'RESTRICT',
2127                 },
2128         ],
2129         accountlines => [
2130                 {       key => 'borrowernumber',
2131                         foreigntable => 'borrowers',
2132                         foreignkey => 'borrowernumber',
2133                         onUpdate => 'CASCADE',
2134                         onDelete => 'CASCADE',
2135                 },
2136                 {       key => 'itemnumber',
2137                         foreigntable => 'items',
2138                         foreignkey => 'itemnumber',
2139                         onUpdate => 'SET NULL',
2140                         onDelete => 'SET NULL',
2141                 },
2142         ],
2143         auth_tag_structure => [
2144                 {       key => 'authtypecode',
2145                         foreigntable => 'auth_types',
2146                         foreignkey => 'authtypecode',
2147                         onUpdate => 'CASCADE',
2148                         onDelete => 'CASCADE',
2149                 },
2150         ],
2151         # FIXME : don't constraint auth_*_table and auth_word, as they may be replaced by zebra
2152 );
2153
2154
2155 # column changes
2156 my %column_change = (
2157         # table
2158         borrowers => [
2159                                 {
2160                                         from => 'emailaddress',
2161                                         to => 'email',
2162                                         after => 'city',
2163                                 },
2164                                 {
2165                                         from => 'streetaddress',
2166                                         to => 'address',
2167                                         after => 'initials',
2168                                 },
2169                                 {
2170                                         from => 'faxnumber',
2171                                         to => 'fax',
2172                                         after => 'phone',
2173                                 },
2174                                 {
2175                                         from => 'textmessaging',
2176                                         to => 'opacnote',
2177                                         after => 'userid',
2178                                 },
2179                                 {
2180                                         from => 'altnotes',
2181                                         to => 'contactnote',
2182                                         after => 'opacnote',
2183                                 },
2184                                 {
2185                                         from => 'physstreet',
2186                                         to => 'B_address',
2187                                         after => 'fax',
2188                                 },
2189                                 {
2190                                         from => 'streetcity',
2191                                         to => 'B_city',
2192                                         after => 'B_address',
2193                                 },
2194                                 {
2195                                         from => 'phoneday',
2196                                         to => 'mobile',
2197                                         after => 'phone',
2198                                 },
2199                                 {
2200                                         from => 'zipcode',
2201                                         to => 'zipcode',
2202                                         after => 'city',
2203                                 },
2204                                 {
2205                                         from => 'homezipcode',
2206                                         to => 'B_zipcode',
2207                                         after => 'B_city',
2208                                 },
2209                                 {
2210                                         from => 'altphone',
2211                                         to => 'B_phone',
2212                                         after => 'B_zipcode',
2213                                 },
2214                                 {
2215                                         from => 'expiry',
2216                                         to => 'dateexpiry',
2217                                         after => 'dateenrolled',
2218                                 },
2219                                 {
2220                                         from => 'guarantor',
2221                                         to => 'guarantorid',
2222                                         after => 'contactname',
2223                                 },
2224                                 {
2225                                         from => 'textmessaging',
2226                                         to => 'opacnotes',
2227                                         after => 'flags',
2228                                 },
2229                                 {
2230                                         from => 'altnotes',
2231                                         to => 'contactnotes',
2232                                         after => 'opacnotes',
2233                                 },
2234                                 {
2235                                         from => 'altrelationship',
2236                                         to => 'relationship',
2237                                         after => 'borrowernotes',
2238                                 },
2239                         ],
2240
2241         deletedborrowers => [
2242                                 {
2243                                         from => 'emailaddress',
2244                                         to => 'email',
2245                                         after => 'city',
2246                                 },
2247                                 {
2248                                         from => 'streetaddress',
2249                                         to => 'address',
2250                                         after => 'initials',
2251                                 },
2252                                 {
2253                                         from => 'faxnumber',
2254                                         to => 'fax',
2255                                         after => 'phone',
2256                                 },
2257                                 {
2258                                         from => 'textmessaging',
2259                                         to => 'opacnote',
2260                                         after => 'userid',
2261                                 },
2262                                 {
2263                                         from => 'altnotes',
2264                                         to => 'contactnote',
2265                                         after => 'opacnote',
2266                                 },
2267                                 {
2268                                         from => 'physstreet',
2269                                         to => 'B_address',
2270                                         after => 'fax',
2271                                 },
2272                                 {
2273                                         from => 'streetcity',
2274                                         to => 'B_city',
2275                                         after => 'B_address',
2276                                 },
2277                                 {
2278                                         from => 'phoneday',
2279                                         to => 'mobile',
2280                                         after => 'phone',
2281                                 },
2282                                 {
2283                                         from => 'zipcode',
2284                                         to => 'zipcode',
2285                                         after => 'city',
2286                                 },
2287                                 {
2288                                         from => 'homezipcode',
2289                                         to => 'B_zipcode',
2290                                         after => 'B_city',
2291                                 },
2292                                 {
2293                                         from => 'altphone',
2294                                         to => 'B_phone',
2295                                         after => 'B_zipcode',
2296                                 },
2297                                 {
2298                                         from => 'expiry',
2299                                         to => 'dateexpiry',
2300                                         after => 'dateenrolled',
2301                                 },
2302                                 {
2303                                         from => 'guarantor',
2304                                         to => 'guarantorid',
2305                                         after => 'contactname',
2306                                 },
2307                                 {
2308                                         from => 'textmessaging',
2309                                         to => 'opacnotes',
2310                                         after => 'flags',
2311                                 },
2312                                 {
2313                                         from => 'altnotes',
2314                                         to => 'contactnotes',
2315                                         after => 'opacnotes',
2316                                 },
2317                                 {
2318                                         from => 'altrelationship',
2319                                         to => 'relationship',
2320                                         after => 'borrowernotes',
2321                                 },
2322                         ],
2323
2324                 );
2325                 
2326 foreach my $table (keys %column_change) {
2327         $sth = $dbh->prepare("show columns from $table");
2328         $sth->execute();
2329         undef %types;
2330         while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
2331         {
2332                 $types{$column}->{type} ="$type";
2333                 $types{$column}->{null} = "$null";
2334                 $types{$column}->{key} = "$key";
2335                 $types{$column}->{default} = "$default";
2336                 $types{$column}->{extra} = "$extra";
2337         }    # while
2338         my $tablerows = $column_change{$table};
2339         foreach my $row ( @$tablerows ) {
2340                 if ($types{$row->{from}}->{type}) {
2341                         print "altering $table $row->{from} to $row->{to}\n";
2342                         # ALTER TABLE `borrowers` CHANGE `faxnumber` `fax` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL 
2343 #                       alter table `borrowers` change `faxnumber` `fax` type text  null after phone
2344                         my $sql = 
2345                                 "alter table `$table` change `$row->{from}` `$row->{to}` $types{$row->{from}}->{type} ".
2346                                 ($types{$row->{from}}->{null} eq 'YES'?" NULL":" NOT NULL").
2347                                 ($types{$row->{from}}->{default}?" default ".$types{$row->{from}}->{default}:"").
2348                                 "$types{$row->{from}}->{extra} after $row->{after} ";
2349 #                       print "$sql";
2350                         $dbh->do($sql);
2351                 }
2352         }
2353 }
2354
2355 #-------------------
2356 # Initialize
2357
2358 # Start checking
2359
2360 # Get version of MySQL database engine.
2361 my $mysqlversion = `mysqld --version`;
2362 $mysqlversion =~ /Ver (\S*) /;
2363 $mysqlversion = $1;
2364 if ( $mysqlversion ge '3.23' ) {
2365     print "Could convert to MyISAM database tables...\n" unless $silent;
2366 }
2367
2368 #---------------------------------
2369 # Tables
2370
2371 # Collect all tables into a list
2372 $sth = $dbh->prepare("show tables");
2373 $sth->execute;
2374 while ( my ($table) = $sth->fetchrow ) {
2375     $existingtables{$table} = 1;
2376 }
2377
2378 # Now add any missing tables
2379 foreach $table ( keys %requiretables ) {
2380     unless ( $existingtables{$table} ) {
2381         print "Adding $table table...\n" unless $silent;
2382         my $sth = $dbh->prepare("create table $table $requiretables{$table}");
2383         $sth->execute;
2384         if ( $sth->err ) {
2385             print "Error : $sth->errstr \n";
2386             $sth->finish;
2387         }    # if error
2388     }    # unless exists
2389 }    # foreach
2390
2391 # now drop useless tables
2392 foreach $table ( keys %dropable_table ) {
2393     if ( $existingtables{$table} ) {
2394         print "Dropping unused table $table\n" if $debug and not $silent;
2395         $dbh->do("drop table $table");
2396         if ( $dbh->err ) {
2397             print "Error : $dbh->errstr \n";
2398         }
2399     }
2400 }
2401 <<<<<<< updatedatabase
2402
2403 =======
2404 unless ( $existingtables{'z3950servers'} ) {
2405
2406     #MJR: added syntax entries to close bug 624
2407     print "Adding z3950servers table...\n" unless $silent;
2408     my $sti = $dbh->prepare(
2409         "create table z3950servers (
2410                                                                                 host char(255),
2411                                                                                 port int,
2412                                                                                 db char(255),
2413                                                                                 userid char(255),
2414                                                                                 password char(255),
2415                                                                                 name text,
2416                                                                                 id int,
2417                                                                                 checked smallint,
2418                                                                                 rank int,
2419                                                                                 syntax char(80))"
2420     );
2421     $sti->execute;
2422     $sti = $dbh->prepare(
2423         "insert into z3950servers
2424                                                                 values ('z3950.loc.gov',
2425                                                                 7090,
2426                                                                 'voyager',
2427                                                                 '', '',
2428                                                                 'Library of Congress',
2429                                                                 1, 1, 1, 'USMARC')"
2430     );
2431     $sti->execute;
2432 }
2433 unless ( $existingtables{'issuingrules'} ) {
2434     $dbh->do("alter table categoryitem rename issuingrules");
2435     $dbh->do("ALTER TABLE issuingrules ADD maxissueqty int(4) default NULL");
2436     $dbh->do("ALTER TABLE issuingrules ADD issuelength int(4) default NULL");
2437     $dbh->do(
2438         "ALTER TABLE issuingrules ADD branchcode varchar(4) NOT NULL default ''"
2439     );
2440     print "renaming categoryitem\n" unless $silent;
2441 }
2442
2443 >>>>>>> 1.100.2.46
2444 #---------------------------------
2445 # Columns
2446
2447 foreach $table ( keys %requirefields ) {
2448     print "Check table $table\n" if $debug and not $silent;
2449     $sth = $dbh->prepare("show columns from $table");
2450     $sth->execute();
2451     undef %types;
2452     while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
2453     {
2454         $types{$column} = $type;
2455     }    # while
2456     foreach $column ( keys %{ $requirefields{$table} } ) {
2457         print "  Check column $column  [$types{$column}]\n"
2458           if $debug and not $silent;
2459         if ( !$types{$column} ) {
2460
2461             # column doesn't exist
2462             print "Adding $column field to $table table...\n" unless $silent;
2463             $query = "alter table $table
2464                         add column $column " . $requirefields{$table}->{$column};
2465             print "Execute: $query\n" if $debug;
2466             my $sti = $dbh->prepare($query);
2467             $sti->execute;
2468             if ( $sti->err ) {
2469                 print "**Error : $sti->errstr \n";
2470                 $sti->finish;
2471             }    # if error
2472         }    # if column
2473     }    # foreach column
2474 }    # foreach table
2475
2476 foreach $table ( keys %fielddefinitions ) {
2477 <<<<<<< updatedatabase
2478         print "Check table $table\n" if $debug;
2479         $sth = $dbh->prepare("show columns from $table");
2480         $sth->execute();
2481         my $definitions;
2482         while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
2483         {
2484                 $definitions->{$column}->{type}    = $type;
2485                 $definitions->{$column}->{null}    = $null;
2486                 $definitions->{$column}->{null}    = 'NULL' if $null eq 'YES';
2487                 $definitions->{$column}->{key}     = $key;
2488                 $definitions->{$column}->{default} = $default;
2489                 $definitions->{$column}->{extra}   = $extra;
2490         }    # while
2491         my $fieldrow = $fielddefinitions{$table};
2492         foreach my $row (@$fieldrow) {
2493                 my $field   = $row->{field};
2494                 my $type    = $row->{type};
2495                 my $null    = $row->{null};
2496 #               $null    = 'YES' if $row->{null} eq 'NULL';
2497                 my $key     = $row->{key};
2498                 my $default = $row->{default};
2499                 my $null    = $row->{null};
2500 #               $default="''" unless $default;
2501                 my $extra   = $row->{extra};
2502                 my $def     = $definitions->{$field};
2503                 my $after       = ($row->{after}?" after ".$row->{after}:"");
2504
2505                 unless ( $type eq $def->{type}
2506                         && $null eq $def->{null}
2507                         && $key eq $def->{key}
2508                         && $extra eq $def->{extra} )
2509                 {
2510                         if ( $null eq '' ) {
2511                                 $null = 'NOT NULL';
2512                         }
2513                         if ( $key eq 'PRI' ) {
2514                                 $key = 'PRIMARY KEY';
2515                         }
2516                         unless ( $extra eq 'auto_increment' ) {
2517                                 $extra = '';
2518                         }
2519
2520                         # if it's a new column use "add", if it's an old one, use "change".
2521                         my $action;
2522                         if ($definitions->{$field}->{type}) {
2523                                 $action="change $field"
2524                         } else {
2525                                 $action="add";
2526                         }
2527 # if it's a primary key, drop the previous pk, before altering the table
2528                         my $sth;
2529                         if ($key ne 'PRIMARY KEY') {
2530                                 $sth =$dbh->prepare("alter table $table $action $field $type $null $key $extra default ? $after");
2531                         } else {
2532                                 $sth =$dbh->prepare("alter table $table drop primary key, $action $field $type $null $key $extra default ? $after");
2533                         }
2534                         $sth->execute($default);
2535                         print "  alter or create $field in $table\n" unless $silent;
2536                 }
2537         }
2538 =======
2539     print "Check table $table\n" if $debug;
2540     $sth = $dbh->prepare("show columns from $table");
2541     $sth->execute();
2542     my $definitions;
2543     while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
2544     {
2545         $definitions->{$column}->{type}    = $type;
2546         $definitions->{$column}->{null}    = $null;
2547         $definitions->{$column}->{null}    = 'NULL' if $null eq 'YES';
2548         $definitions->{$column}->{key}     = $key;
2549         $definitions->{$column}->{default} = $default;
2550         $definitions->{$column}->{extra}   = $extra;
2551     }    # while
2552     my $fieldrow = $fielddefinitions{$table};
2553     foreach my $row (@$fieldrow) {
2554         my $field   = $row->{field};
2555         my $type    = $row->{type};
2556         my $key     = $row->{key};
2557         my $default = $row->{default};
2558         my $null    = $row->{null};
2559
2560         #               $default="''" unless $default;
2561         my $extra = $row->{extra};
2562         my $def   = $definitions->{$field};
2563
2564         unless ( $type eq $def->{type}
2565             && $null  eq $def->{null}
2566             && $key   eq $def->{key}
2567             && $extra eq $def->{extra} )
2568         {
2569             if ( $null eq '' ) {
2570                 $null = 'NOT NULL';
2571             }
2572             if ( $key eq 'PRI' ) {
2573                 $key = 'PRIMARY KEY';
2574             }
2575             unless ( $extra eq 'auto_increment' ) {
2576                 $extra = '';
2577             }
2578
2579             # if it's a new column use "add", if it's an old one, use "change".
2580             my $action;
2581             if ( $definitions->{$field}->{type} ) {
2582                 $action = "change $field";
2583             }
2584             else {
2585                 $action = "add";
2586             }
2587
2588         # if it's a primary key, drop the previous pk, before altering the table
2589             my $sth;
2590             if ( $key ne 'PRIMARY KEY' ) {
2591                 $sth =
2592                   $dbh->prepare(
2593 "alter table $table $action $field $type $null $key $extra default ?"
2594                   );
2595             }
2596             else {
2597                 $sth =
2598                   $dbh->prepare(
2599 "alter table $table drop primary key, $action $field $type $null $key $extra default ?"
2600                   );
2601             }
2602             $sth->execute($default);
2603             print "  Alter $field in $table\n" unless $silent;
2604         }
2605     }
2606 >>>>>>> 1.100.2.46
2607 }
2608
2609 <<<<<<< updatedatabase
2610 =======
2611 # Get list of columns from borrowers table
2612 my %itemtypes;
2613 my %nullenabled;
2614 $sth = $dbh->prepare("show columns from borrowers");
2615 $sth->execute;
2616 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
2617 {
2618     $itemtypes{$column}   = $type;
2619     $nullenabled{$column} = $null;
2620 }
2621
2622 unless ( $itemtypes{'cardnumber'} eq 'varchar(20)' ) {
2623     $itemtypes{'cardnumber'} =~ /varchar\((\d+)\)/;
2624     my $oldlength = $1;
2625     if ( $oldlength < 16 ) {
2626         print
2627 "Setting maximum cardnumber length to 16 (was $oldlength) and marking unique.\n"
2628           unless $silent;
2629         my $sti =
2630           $dbh->prepare(
2631             "alter table borrowers change cardnumber cardnumber varchar(16)");
2632         $sti->execute;
2633         $sti->finish;
2634         $sti = $dbh->prepare("alter table borrowers drop index cardnumber");
2635         $sti->execute;
2636         $sti->finish;
2637         $sti = $dbh->prepare("alter table borrowers add unique(cardnumber)");
2638         $sti->execute;
2639         $sti->finish;
2640     }
2641 }
2642
2643 #
2644 # Get list of columns from items table
2645 $sth = $dbh->prepare("show columns from items");
2646 $sth->execute;
2647 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
2648 {
2649     $itemtypes{$column}   = $type;
2650     $nullenabled{$column} = $null;
2651 }
2652
2653 unless ( $itemtypes{'barcode'} eq 'varchar(20)' ) {
2654     $itemtypes{'barcode'} =~ /varchar\((\d+)\)/;
2655     my $oldlength = $1;
2656     if ( $oldlength < 20 ) {
2657         print "Setting maximum barcode length to 20 (was $oldlength).\n"
2658           unless $silent;
2659         my $sti =
2660           $dbh->prepare("alter table items change barcode barcode varchar(20)");
2661         $sti->execute;
2662     }
2663 }
2664
2665 #
2666 # dropping unique barcode index & setting barcode to null allowed.
2667 #
2668 $sth = $dbh->prepare("show index from items");
2669 $sth->execute;
2670 while (
2671     my (
2672         $table,       $non_unique, $key_name,    $Seq_in_index,
2673         $Column_name, $Collation,  $cardinality, $sub_part,
2674         $Packed,      $comment
2675     )
2676     = $sth->fetchrow
2677   )
2678 {
2679     if ( $key_name eq 'barcode' && $non_unique eq 0 ) {
2680         print "dropping BARCODE index to enable empty barcodes\n"
2681           unless $silent;
2682         $dbh->do("ALTER TABLE `items` DROP INDEX `barcode`");
2683     }
2684 }
2685 $dbh->do("ALTER TABLE `items` CHANGE `barcode` `barcode` VARCHAR( 20 )")
2686   unless ( $nullenabled{barcode} eq 'YES' );
2687
2688 #
2689 # creating fulltext index in bibliothesaurus if needed
2690 #
2691 $sth = $dbh->prepare("show index from bibliothesaurus");
2692 $sth->execute;
2693 my $exists = 0;
2694 while (
2695     my (
2696         $table,       $non_unique, $key_name,    $Seq_in_index,
2697         $Column_name, $Collation,  $cardinality, $sub_part,
2698         $Packed,      $comment
2699     )
2700     = $sth->fetchrow
2701   )
2702 {
2703     if ( $key_name eq 'category_2' ) {
2704         $exists = 1;
2705     }
2706 }
2707 print "Creating fulltext index on bibliothesaurus\n" unless $exists or $silent;
2708 $dbh->do(
2709     'create fulltext index category_2 on bibliothesaurus (category,freelib)')
2710   unless $exists;
2711
2712 #
2713 # creating  index in z3950results if needed
2714 #
2715 $sth = $dbh->prepare("show index from z3950results");
2716 $sth->execute;
2717 my $exists = 0;
2718 while (
2719     my (
2720         $table,       $non_unique, $key_name,    $Seq_in_index,
2721         $Column_name, $Collation,  $cardinality, $sub_part,
2722         $Packed,      $comment
2723     )
2724     = $sth->fetchrow
2725   )
2726 {
2727     if ( $key_name eq 'query_server' ) {
2728         $exists = 1;
2729     }
2730 }
2731 print "Creating  index on z3950results\n" unless $exists or $silent;
2732 $dbh->do('create unique index query_server on z3950results (queryid,server)')
2733   unless $exists;
2734
2735 # changing z3950daemon field to NULL in marc_breeding
2736 $dbh->do(
2737 "ALTER TABLE `marc_breeding` CHANGE `z3950random` `z3950random` VARCHAR( 40 )"
2738 );
2739
2740 # making borrowernumber an auto_increment field
2741 $dbh->do(
2742 "ALTER TABLE `borrowers` CHANGE `borrowernumber` `borrowernumber` INTEGER auto_increment"
2743 );
2744
2745 # changing indexes in marc_*_structure to use frameworkcode
2746 $dbh->do('alter table marc_subfield_structure drop index tab');
2747 $dbh->do('create index tab on marc_subfield_structure (frameworkcode,tab)');
2748 $dbh->do('alter table marc_subfield_structure drop index kohafield');
2749 $dbh->do(
2750 'create index kohafield on marc_subfield_structure (frameworkcode,kohafield)'
2751 );
2752
2753 # extending the timestamp in branchtransfers...
2754 my %branchtransfers;
2755
2756 $sth = $dbh->prepare("show columns from branchtransfers");
2757 $sth->execute;
2758 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
2759 {
2760     $branchtransfers{$column} = $type;
2761 }
2762
2763 unless ( $branchtransfers{'datesent'} eq 'datetime' ) {
2764     print "Setting type of datesent in branchtransfers to datetime.\n"
2765       unless $silent;
2766     my $sti =
2767       $dbh->prepare(
2768         "alter table branchtransfers change datesent datesent datetime");
2769     $sti->execute;
2770 }
2771
2772 unless ( $branchtransfers{'datearrived'} eq 'datetime' ) {
2773     print "Setting type of datearrived in branchtransfers to datetime.\n"
2774       unless $silent;
2775     my $sti =
2776       $dbh->prepare(
2777         "alter table branchtransfers change datearrived datearrived datetime");
2778     $sti->execute;
2779 }
2780
2781 # changing the branchcategories table around...
2782 my %branchcategories;
2783
2784 $sth = $dbh->prepare("show columns from branchcategories");
2785 $sth->execute;
2786 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
2787 {
2788     $branchcategories{$column} = $type;
2789 }
2790
2791 unless ( $branchcategories{'categorycode'} eq 'varchar(4)' ) {
2792     print
2793 "Setting type of categorycode in branchcategories to varchar(4),\n and making the primary key.\n"
2794       unless $silent;
2795     my $sti =
2796       $dbh->prepare(
2797 "alter table branchcategories change categorycode categorycode varchar(4) not null"
2798       );
2799     $sti->execute;
2800     $sti =
2801       $dbh->prepare(
2802         "alter table branchcategories add primary key (categorycode)");
2803     $sti->execute;
2804 }
2805
2806 unless ( $branchcategories{'categoryname'} eq 'text' ) {
2807     print "Changing branchcode in branchcategories to categoryname text.\n"
2808       unless $silent;
2809     my $sth =
2810       $dbh->prepare(
2811         "alter table branchcategories change branchcode categoryname text");
2812     $sth->execute;
2813 }
2814
2815 unless ( $branchcategories{'codedescription'} eq 'text' ) {
2816     print
2817       "Replacing branchholding in branchcategories with codedescription text.\n"
2818       unless $silent;
2819     my $sth =
2820       $dbh->prepare(
2821         "alter table branchcategories change branchholding codedescription text"
2822       );
2823     $sth->execute;
2824 }
2825
2826 # changing the items table around...
2827 my %items;
2828
2829 $sth = $dbh->prepare("show columns from items");
2830 $sth->execute;
2831 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
2832 {
2833     $items{$column} = $type;
2834 }
2835
2836 if ( $items{'bulk'} eq "varchar(30)" ) {
2837     print "  Setting callnumber in items table\n" unless $silent;
2838     my $sti =
2839       $dbh->prepare(
2840 "ALTER TABLE `items` CHANGE `bulk` `itemcallnumber` VARCHAR( 30 ) DEFAULT NULL"
2841       );
2842     $sti->execute;
2843     $sti =
2844       $dbh->prepare(
2845 "update marc_subfield_structure set kohafield=\"items.itemcallnumber\" where kohafield=\"items.bulk\""
2846       );
2847     $sti->execute;
2848 }
2849
2850 # changing the marc_subfield_structure table around...
2851 my %marc_subfield_structure;
2852
2853 $sth = $dbh->prepare("show columns from marc_subfield_structure");
2854 $sth->execute;
2855 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
2856 {
2857     $marc_subfield_structure{$column} = $type;
2858 }
2859
2860 if ( $marc_subfield_structure{thesaurus_category} ) {
2861     print "  changing thesaurus_category in marc_subfield_structure table\n"
2862       unless $silent;
2863     my $sti =
2864       $dbh->prepare(
2865 "ALTER TABLE marc_subfield_structure CHANGE `thesaurus_category` `authtypecode` VARCHAR(10 ) DEFAULT NULL"
2866       );
2867     $sti->execute;
2868 }
2869
2870 #
2871 # creating  index in issuingrules if needed
2872 #
2873 $sth = $dbh->prepare("show index from issuingrules");
2874 $sth->execute;
2875 my $exists = 0;
2876 while (
2877     my (
2878         $table,       $non_unique, $key_name,    $Seq_in_index,
2879         $Column_name, $Collation,  $cardinality, $sub_part,
2880         $Packed,      $comment
2881     )
2882     = $sth->fetchrow
2883   )
2884 {
2885     if ( $key_name eq 'PRIMARY' ) {
2886         $exists = 1;
2887     }
2888 }
2889 print "Creating  index on issuing rules\n" unless $exists or $silent;
2890 $dbh->do(
2891 'ALTER TABLE issuingrules ADD PRIMARY KEY ( branchcode, categorycode, itemtype )'
2892   )
2893   unless $exists;
2894
2895 $dbh->do('ALTER TABLE marc_tag_structure drop primary key');
2896 $dbh->do(
2897     'ALTER TABLE marc_tag_structure ADD PRIMARY KEY ( frameworkcode, tagfield )'
2898 );
2899
2900 $dbh->do('ALTER TABLE marc_subfield_structure drop primary key');
2901 $dbh->do(
2902 'ALTER TABLE marc_subfield_structure ADD PRIMARY KEY ( frameworkcode, tagfield, tagsubfield )'
2903 );
2904
2905 $dbh->do(
2906 "alter table marc_subfield_table change tagorder tagorder int not null default '1'"
2907 );
2908
2909 # Get list of columns from marc_word table
2910 my %marc_word;
2911 my %nullenabled;
2912 $sth = $dbh->prepare("show columns from marc_word");
2913 $sth->execute;
2914 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
2915 {
2916     $marc_word{$column}   = $type;
2917     $nullenabled{$column} = $null;
2918 }
2919 if ( $marc_word{subfieldid} ) {
2920
2921     #create field tagsubfield, copy tag+subfieldid, then drop tag and subfieldid
2922     print "Modifying marc_word (concat on tag and subfield for better perfs)\n"
2923       unless $silent;
2924     $dbh->do(
2925 "ALTER TABLE `marc_word` ADD `tagsubfield` CHAR( 4 ) NOT NULL AFTER `bibid`"
2926     );
2927     $dbh->do("update marc_word set tagsubfield=concat(tag,subfieldid)");
2928     $dbh->do("alter table marc_word drop tag");
2929     $dbh->do("alter table marc_word drop subfieldid");
2930     $dbh->do("create index Search_Marc on marc_word (tagsubfield,word)");
2931 }
2932
2933 >>>>>>> 1.100.2.46
2934 # Populate tables with required data
2935
2936 # synch table and deletedtable.
2937 foreach my $table ( ( 'borrowers', 'items', 'biblio', 'biblioitems' ) ) {
2938     my %deletedborrowers;
2939     print "synch'ing $table\n";
2940     $sth = $dbh->prepare("show columns from deleted$table");
2941     $sth->execute;
2942     while ( my ( $column, $type, $null, $key, $default, $extra ) =
2943         $sth->fetchrow )
2944     {
2945         $deletedborrowers{$column} = 1;
2946     }
2947     $sth = $dbh->prepare("show columns from $table");
2948     $sth->execute;
2949     my $previous;
2950     while ( my ( $column, $type, $null, $key, $default, $extra ) =
2951         $sth->fetchrow )
2952     {
2953         unless ( $deletedborrowers{$column} ) {
2954             my $newcol = "alter table deleted$table add $column $type";
2955             if ( $null eq 'YES' ) {
2956                 $newcol .= " NULL ";
2957             }
2958             else {
2959                 $newcol .= " NOT NULL ";
2960             }
2961             $newcol .= "default $default" if $default;
2962             $newcol .= " after $previous" if $previous;
2963             $previous = $column;
2964             print "creating column $column\n";
2965             $dbh->do($newcol);
2966         }
2967     }
2968 }
2969
2970 <<<<<<< updatedatabase
2971 =======
2972 # fill aqbasket if it's empty and aqorder is not
2973 # => it means it has just been created & must be filled
2974 $sth = $dbh->prepare("select count(*) from aqbasket");
2975 $sth->execute;
2976 if ( $sth->fetchrow == 0 ) {
2977     $sth = $dbh->prepare("select count(*) from aqorders");
2978     $sth->execute;
2979     if ( $sth->fetchrow > 0 ) {
2980         print "Populating new table aqbasket\n";
2981         print
2982 "IMPORTANT NOTE: error message \"Duplicate entry 'X' for key 1\" may appear. it should not be a real trouble\n";
2983         $sth =
2984           $dbh->prepare(
2985 "select distinct basketno,booksellerid,authorisedby,entrydate,booksellerinvoicenumber from aqorders"
2986           );
2987         $sth->execute;
2988         my ( $basketno, $booksellerid, $authorisedby, $entrydate,
2989             $booksellerinvoicenumber );
2990         my $sth2 =
2991           $dbh->prepare(
2992 "insert into aqbasket (basketno,creationdate,booksellerid,authorisedby,booksellerinvoicenumber) values (?,?,?,?,?)"
2993           );
2994         while (
2995             (
2996                 $basketno,     $booksellerid,
2997                 $authorisedby, $entrydate,
2998                 $booksellerinvoicenumber
2999             )
3000             = $sth->fetchrow
3001           )
3002         {
3003             print
3004 "$basketno,$entrydate,$booksellerid,$authorisedby,$booksellerinvoicenumber\n";
3005             $sth2->execute( $basketno, $entrydate, $booksellerid, $authorisedby,
3006                 $booksellerinvoicenumber );
3007         }
3008     }
3009 }
3010 >>>>>>> 1.100.2.46
3011 foreach my $table ( keys %tabledata ) {
3012     print "Checking for data required in table $table...\n" unless $silent;
3013     my $tablerows = $tabledata{$table};
3014     foreach my $row (@$tablerows) {
3015         my $uniquefieldrequired = $row->{uniquefieldrequired};
3016         my $uniquevalue         = $row->{$uniquefieldrequired};
3017         my $forceupdate         = $row->{forceupdate};
3018         my $sth                 =
3019           $dbh->prepare(
3020 "select $uniquefieldrequired from $table where $uniquefieldrequired=?"
3021           );
3022         $sth->execute($uniquevalue);
3023 <<<<<<< updatedatabase
3024                 if ($sth->rows) {
3025                         foreach my $field (keys %$forceupdate) {
3026                                 if ($forceupdate->{$field}) {
3027                                         my $sth=$dbh->prepare("update systempreferences set $field=? where $uniquefieldrequired=?");
3028                                         $sth->execute($row->{$field}, $uniquevalue);
3029                                 }
3030                 }
3031                 } else {
3032                         print "Adding row to $table: " unless $silent;
3033                         my @values;
3034                         my $fieldlist;
3035                         my $placeholders;
3036                         foreach my $field ( keys %$row ) {
3037                                 next if $field eq 'uniquefieldrequired';
3038                                 next if $field eq 'forceupdate';
3039                                 my $value = $row->{$field};
3040                                 push @values, $value;
3041                                 print "  $field => $value" unless $silent;
3042                                 $fieldlist .= "$field,";
3043                                 $placeholders .= "?,";
3044                         }
3045                         print "\n" unless $silent;
3046                         $fieldlist    =~ s/,$//;
3047                         $placeholders =~ s/,$//;
3048                         my $sth =
3049                         $dbh->prepare(
3050                                 "insert into $table ($fieldlist) values ($placeholders)");
3051                         $sth->execute(@values);
3052                 }
3053         }
3054 }
3055
3056 #
3057 # check indexes and create them when needed
3058 #
3059 print "Checking for index required...\n" unless $silent;
3060 foreach my $table ( keys %indexes ) {
3061         #
3062         # read all indexes from $table
3063         #
3064         $sth = $dbh->prepare("show index from $table");
3065         $sth->execute;
3066         my %existingindexes;
3067         while ( my ( $table, $non_unique, $key_name, $Seq_in_index, $Column_name, $Collation, $cardinality, $sub_part, $Packed, $comment ) = $sth->fetchrow ) {
3068                 $existingindexes{$key_name} = 1;
3069         }
3070         # read indexes to check
3071         my $tablerows = $indexes{$table};
3072         foreach my $row (@$tablerows) {
3073                 my $key_name=$row->{indexname};
3074                 if ($existingindexes{$key_name} eq 1) {
3075 #                       print "$key_name existing";
3076                 } else {
3077                         print "\tCreating index $key_name in $table\n";
3078                         my $sql;
3079                         if ($row->{indexname} eq 'PRIMARY') {
3080                                 $sql = "alter table $table ADD PRIMARY KEY ($row->{content})";
3081                         } else {
3082                                 $sql = "alter table $table ADD INDEX $key_name ($row->{content}) $row->{type}";
3083                         }
3084                         $dbh->do($sql);
3085             print "Error $sql : $dbh->err \n" if $dbh->err;
3086                 }
3087         }
3088 }
3089
3090 #
3091 # check foreign keys and create them when needed
3092 #
3093 print "Checking for foreign keys required...\n" unless $silent;
3094 foreach my $table ( keys %foreign_keys ) {
3095         #
3096         # read all indexes from $table
3097         #
3098         $sth = $dbh->prepare("show table status like '$table'");
3099         $sth->execute;
3100         my $stat = $sth->fetchrow_hashref;
3101         # read indexes to check
3102         my $tablerows = $foreign_keys{$table};
3103         foreach my $row (@$tablerows) {
3104                 my $foreign_table=$row->{foreigntable};
3105                 if ($stat->{'Comment'} =~/$foreign_table/) {
3106 #                       print "$foreign_table existing\n";
3107                 } else {
3108                         print "\tCreating foreign key $foreign_table in $table\n";
3109                         # first, drop any orphan value in child table
3110                         if ($row->{onDelete} ne "RESTRICT") {
3111                                 my $sql = "delete from $table where $row->{key} not in (select $row->{foreignkey} from $row->{foreigntable})";
3112                                 $dbh->do($sql);
3113                                 print "SQL ERROR: $sql : $dbh->err \n" if $dbh->err;
3114                         }
3115                         my $sql="alter table $table ADD FOREIGN KEY $row->{key} ($row->{key}) REFERENCES $row->{foreigntable} ($row->{foreignkey})";
3116                         $sql .= " on update ".$row->{onUpdate} if $row->{onUpdate};
3117                         $sql .= " on delete ".$row->{onDelete} if $row->{onDelete};
3118                         $dbh->do($sql);
3119                         if ($dbh->err) {
3120                                 print "====================
3121 An error occured during :
3122 \t$sql
3123 It probably means there is something wrong in your DB : a row ($table.$row->{key}) refers to a value in $row->{foreigntable}.$row->{foreignkey} that does not exist. solve the problem and run updater again (or just the previous SQL statement).
3124 You can find those values with select
3125 \t$table.* from $table where $row->{key} not in (select $row->{foreignkey} from $row->{foreigntable})
3126 ====================\n
3127 ";
3128                         }
3129                 }
3130         }
3131 }
3132
3133 #
3134 # SPECIFIC STUFF
3135 #
3136 #
3137 # create frameworkcode row in biblio table & fill it with marc_biblio.frameworkcode.
3138 #
3139
3140 # 1st, get how many biblio we will have to do...
3141 $sth = $dbh->prepare('select count(*) from marc_biblio');
3142 $sth->execute;
3143 my ($totaltodo) = $sth->fetchrow;
3144
3145 $sth = $dbh->prepare("show columns from biblio");
3146 $sth->execute();
3147 my $definitions;
3148 my $bibliofwexist=0;
3149 while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow ){
3150         $bibliofwexist=1 if $column eq 'frameworkcode';
3151 }
3152 unless ($bibliofwexist) {
3153         print "moving biblioframework to biblio table\n";
3154         $dbh->do('ALTER TABLE `biblio` ADD `frameworkcode` VARCHAR( 4 ) NOT NULL AFTER `biblionumber`');
3155         $sth = $dbh->prepare('select biblionumber,frameworkcode from marc_biblio');
3156         $sth->execute;
3157         my $sth_update = $dbh->prepare('update biblio set frameworkcode=? where biblionumber=?');
3158         my $totaldone=0;
3159         while (my ($biblionumber,$frameworkcode) = $sth->fetchrow) {
3160                 $sth_update->execute($frameworkcode,$biblionumber);
3161                 $totaldone++;
3162                 print "\r$totaldone / $totaltodo" unless ($totaldone % 100);
3163         }
3164         print "\rdone\n";
3165 }
3166
3167 #
3168 # moving MARC data from marc_subfield_table to biblioitems.marc
3169 #
3170 $sth = $dbh->prepare("show columns from biblioitems");
3171 $sth->execute();
3172 my $definitions;
3173 my $marcdone=0;
3174 while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow ){
3175         $marcdone=1 if ($type eq 'blob' && $column eq 'marc') ;
3176 }
3177 unless ($marcdone) {
3178         print "moving MARC record to biblioitems table\n";
3179         # changing marc field type
3180         $dbh->do('ALTER TABLE `biblioitems` CHANGE `marc` `marc` BLOB NULL DEFAULT NULL ');
3181         # adding marc xml, just for convenience
3182         $dbh->do('ALTER TABLE `biblioitems` ADD `marcxml` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ');
3183         # moving data from marc_subfield_value to biblio
3184         $sth = $dbh->prepare('select bibid,biblionumber from marc_biblio');
3185         $sth->execute;
3186         my $sth_update = $dbh->prepare('update biblioitems set marc=?, marcxml=? where biblionumber=?');
3187         my $totaldone=0;
3188         while (my ($bibid,$biblionumber) = $sth->fetchrow) {
3189                 my $record = MARCgetbiblio($dbh,$bibid);
3190         #Force UTF-8 in record leader
3191                 $record->encoding('UTF-8');
3192                 print $record->as_formatted if ($biblionumber==3902);
3193                 $sth_update->execute($record->as_usmarc(),$record->as_xml_record(),$biblionumber);
3194                 $totaldone++;
3195                 print "\r$totaldone / $totaltodo" unless ($totaldone % 100);
3196         }
3197         print "\rdone\n";
3198 =======
3199         if ( $sth->rows ) {
3200             foreach my $field ( keys %$forceupdate ) {
3201                 if ( $forceupdate->{$field} ) {
3202                     my $sth =
3203                       $dbh->prepare(
3204 "update systempreferences set $field=? where $uniquefieldrequired=?"
3205                       );
3206                     $sth->execute( $row->{$field}, $uniquevalue );
3207                 }
3208             }
3209         }
3210         else {
3211             print "Adding row to $table: " unless $silent;
3212             my @values;
3213             my $fieldlist;
3214             my $placeholders;
3215             foreach my $field ( keys %$row ) {
3216                 next if $field eq 'uniquefieldrequired';
3217                 next if $field eq 'forceupdate';
3218                 my $value = $row->{$field};
3219                 push @values, $value;
3220                 print "  $field => $value" unless $silent;
3221                 $fieldlist    .= "$field,";
3222                 $placeholders .= "?,";
3223             }
3224             print "\n" unless $silent;
3225             $fieldlist    =~ s/,$//;
3226             $placeholders =~ s/,$//;
3227             my $sth =
3228               $dbh->prepare(
3229                 "insert into $table ($fieldlist) values ($placeholders)");
3230             $sth->execute(@values);
3231         }
3232     }
3233 >>>>>>> 1.100.2.46
3234 }
3235
3236
3237 # at last, remove useless fields
3238 foreach $table ( keys %uselessfields ) {
3239     my @fields = split /,/, $uselessfields{$table};
3240     my $fields;
3241     my $exists;
3242     foreach my $fieldtodrop (@fields) {
3243         $fieldtodrop =~ s/\t//g;
3244         $fieldtodrop =~ s/\n//g;
3245         $exists = 0;
3246         $sth    = $dbh->prepare("show columns from $table");
3247         $sth->execute;
3248         while ( my ( $column, $type, $null, $key, $default, $extra ) =
3249             $sth->fetchrow )
3250         {
3251             $exists = 1 if ( $column eq $fieldtodrop );
3252         }
3253         if ($exists) {
3254             print "deleting $fieldtodrop field in $table...\n" unless $silent;
3255             my $sth = $dbh->prepare("alter table $table drop $fieldtodrop");
3256             $sth->execute;
3257         }
3258     }
3259 }    # foreach
3260
3261 <<<<<<< updatedatabase
3262
3263 # MOVE all tables TO UTF-8 and innoDB
3264 $sth = $dbh->prepare("show table status");
3265 $sth->execute;
3266 while ( my $table = $sth->fetchrow_hashref ) {
3267 #       if ($table->{Engine} ne 'InnoDB') {
3268 #               $dbh->do("ALTER TABLE $table->{Name} TYPE = innodb");
3269 #               print "moving $table->{Name} to InnoDB\n";
3270 #       }
3271         unless ($table->{Collation} =~ /^utf8/) {
3272                 $dbh->do("ALTER TABLE $table->{Name} CONVERT TO CHARACTER SET utf8");
3273                 $dbh->do("ALTER TABLE $table->{Name} DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci");
3274                 # FIXME : maybe a ALTER TABLE tbl_name CONVERT TO CHARACTER SET utf8 would be better, def char set seems to work fine. If any problem encountered, let's try with convert !
3275                 print "moving $table->{Name} to utf8\n";
3276         } else {
3277         }
3278 }
3279
3280 =======
3281 >>>>>>> 1.100.2.46
3282 $sth->finish;
3283
3284 #
3285 # those 2 subs are a copy of Biblio.pm, version 2.2.4
3286 # they are useful only once, for moving from 2.2 to 3.0
3287 # the MARCgetbiblio & MARCgetitem subs in Biblio.pm
3288 # are still here, but uses other tables
3289 # (the ones that are filled by updatedatabase !)
3290 #
3291
3292 sub MARCgetbiblio {
3293
3294     # Returns MARC::Record of the biblio passed in parameter.
3295     my ( $dbh, $bibid ) = @_;
3296     my $record = MARC::Record->new();
3297 #       warn "". $bidid;
3298
3299     my $sth =
3300       $dbh->prepare(
3301 "select bibid,subfieldid,tag,tagorder,tag_indicator,subfieldcode,subfieldorder,subfieldvalue,valuebloblink
3302                                  from marc_subfield_table
3303                                  where bibid=? order by tag,tagorder,subfieldorder
3304                          "
3305     );
3306     my $sth2 =
3307       $dbh->prepare(
3308         "select subfieldvalue from marc_blob_subfield where blobidlink=?");
3309     $sth->execute($bibid);
3310     my $prevtagorder = 1;
3311     my $prevtag      = 'XXX';
3312     my $previndicator;
3313     my $field;        # for >=10 tags
3314     my $prevvalue;    # for <10 tags
3315     while ( my $row = $sth->fetchrow_hashref ) {
3316
3317         if ( $row->{'valuebloblink'} ) {    #---- search blob if there is one
3318             $sth2->execute( $row->{'valuebloblink'} );
3319             my $row2 = $sth2->fetchrow_hashref;
3320             $sth2->finish;
3321             $row->{'subfieldvalue'} = $row2->{'subfieldvalue'};
3322         }
3323         if ( $row->{tagorder} ne $prevtagorder || $row->{tag} ne $prevtag ) {
3324             $previndicator .= "  ";
3325             if ( $prevtag < 10 ) {
3326                                 if ($prevtag ne '000') {
3327                         $record->add_fields( ( sprintf "%03s", $prevtag ), $prevvalue ) unless $prevtag eq "XXX";    # ignore the 1st loop
3328                                 } else {
3329                                         $record->leader(sprintf("%24s",$prevvalue));
3330                                 }
3331             }
3332             else {
3333                 $record->add_fields($field) unless $prevtag eq "XXX";
3334             }
3335             undef $field;
3336             $prevtagorder  = $row->{tagorder};
3337             $prevtag       = $row->{tag};
3338             $previndicator = $row->{tag_indicator};
3339             if ( $row->{tag} < 10 ) {
3340                 $prevvalue = $row->{subfieldvalue};
3341             }
3342             else {
3343                 $field = MARC::Field->new(
3344                     ( sprintf "%03s", $prevtag ),
3345                     substr( $row->{tag_indicator} . '  ', 0, 1 ),
3346                     substr( $row->{tag_indicator} . '  ', 1, 1 ),
3347                     $row->{'subfieldcode'},
3348                     $row->{'subfieldvalue'}
3349                 );
3350             }
3351         }
3352         else {
3353             if ( $row->{tag} < 10 ) {
3354                 $record->add_fields( ( sprintf "%03s", $row->{tag} ),
3355                     $row->{'subfieldvalue'} );
3356             }
3357             else {
3358                 $field->add_subfields( $row->{'subfieldcode'},
3359                     $row->{'subfieldvalue'} );
3360             }
3361             $prevtag       = $row->{tag};
3362             $previndicator = $row->{tag_indicator};
3363         }
3364     }
3365
3366     # the last has not been included inside the loop... do it now !
3367     if ( $prevtag ne "XXX" )
3368     { # check that we have found something. Otherwise, prevtag is still XXX and we
3369          # must return an empty record, not make MARC::Record fail beca