s/holded by/maintained/
[koha.git] / installer / data / mysql / update22to30.pl
1 #!/usr/bin/perl
2
3
4 # Database Updater
5 # This script checks for required updates to the database.
6
7 # Part of the Koha Library Software www.koha.org
8 # Licensed under the GPL.
9
10 # Bugs/ToDo:
11 # - Would also be a good idea to offer to do a backup at this time...
12
13 # NOTE:  If you do something more than once in here, make it table driven.
14 use strict;
15
16 # CPAN modules
17 use DBI;
18 use Getopt::Long;
19 # Koha modules
20 use C4::Context;
21
22 use MARC::Record;
23 use MARC::File::XML ( BinaryEncoding => 'utf8' );
24  
25 # FIXME - The user might be installing a new database, so can't rely
26 # on /etc/koha.conf anyway.
27
28 my $debug = 0;
29
30 my (
31     $sth, $sti,
32     $query,
33     %existingtables,    # tables already in database
34     %types,
35     $table,
36     $column,
37     $type, $null, $key, $default, $extra,
38     $prefitem,          # preference item in systempreferences table
39 );
40
41 my $silent;
42 GetOptions(
43     's' =>\$silent
44     );
45 my $dbh = C4::Context->dbh;
46 $|=1; # flushes output
47
48 my $DBversion = "3.00.00.000";
49 # if we are upgrading from Koha 2.2, then we need to run the complete & long updatedatabase
50     # Tables to add if they don't exist
51     my %requiretables = (
52         action_logs     => "(
53                         `timestamp` TIMESTAMP NOT NULL ,
54                         `user` INT( 11 ) NOT NULL default '0' ,
55                         `module` TEXT default '',
56                         `action` TEXT default '' ,
57                         `object` INT(11) NULL ,
58                         `info` TEXT default '' ,
59                         PRIMARY KEY ( `timestamp` , `user` )
60                     )",
61         letter        => "(
62                         module varchar(20) NOT NULL default '',
63                         code varchar(20) NOT NULL default '',
64                         name varchar(100) NOT NULL default '',
65                         title varchar(200) NOT NULL default '',
66                         content text,
67                         PRIMARY KEY  (module,code)
68                     )",
69         alert        =>"(
70                         alertid int(11) NOT NULL auto_increment,
71                         borrowernumber int(11) NOT NULL default '0',
72                         type varchar(10) NOT NULL default '',
73                         externalid varchar(20) NOT NULL default '',
74                         PRIMARY KEY  (alertid),
75                         KEY borrowernumber (borrowernumber),
76                         KEY type (type,externalid)
77                     )",
78         opac_news => "(
79                     `idnew` int(10) unsigned NOT NULL auto_increment,
80                     `title` varchar(250) NOT NULL default '',
81                     `new` text NOT NULL,
82                     `lang` varchar(4) NOT NULL default '',
83                     `timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP,
84                     PRIMARY KEY  (`idnew`)
85                     )",
86         repeatable_holidays => "(
87                     `id` int(11) NOT NULL auto_increment,
88                     `branchcode` varchar(4) NOT NULL default '',
89                     `weekday` smallint(6) default NULL,
90                     `day` smallint(6) default NULL,
91                     `month` smallint(6) default NULL,
92                     `title` varchar(50) NOT NULL default '',
93                     `description` text NOT NULL,
94                     PRIMARY KEY  (`id`)
95                     )",
96         special_holidays => "(
97                     `id` int(11) NOT NULL auto_increment,
98                     `branchcode` varchar(4) NOT NULL default '',
99                     `day` smallint(6) NOT NULL default '0',
100                     `month` smallint(6) NOT NULL default '0',
101                     `year` smallint(6) NOT NULL default '0',
102                     `isexception` smallint(1) NOT NULL default '1',
103                     `title` varchar(50) NOT NULL default '',
104                     `description` text NOT NULL,
105                     PRIMARY KEY  (`id`)
106                     )",
107         overduerules    =>"(`branchcode` varchar(255) NOT NULL default '',
108                         `categorycode` char(2) NOT NULL default '',
109                         `delay1` int(4) default '0',
110                         `letter1` varchar(20) default NULL,
111                         `debarred1` char(1) default '0',
112                         `delay2` int(4) default '0',
113                         `debarred2` char(1) default '0',
114                         `letter2` varchar(20) default NULL,
115                         `delay3` int(4) default '0',
116                         `letter3` varchar(20) default NULL,
117                         `debarred3` int(1) default '0',
118                         PRIMARY KEY  (`branchcode`,`categorycode`)
119                         )",
120         cities            => "(`cityid` int auto_increment,
121                             `city_name` char(100) NOT NULL,
122                             `city_zipcode` char(20),
123                             PRIMARY KEY (`cityid`)
124                         )",
125         roadtype            => "(`roadtypeid` int auto_increment,
126                             `road_type` char(100) NOT NULL,
127                             PRIMARY KEY (`roadtypeid`)
128                         )",
129     
130         labels                     => "(
131                     labelid int(11) NOT NULL auto_increment,
132                                 itemnumber varchar(100) NOT NULL default '',
133                                 timestamp timestamp(14) NOT NULL,
134                                 PRIMARY KEY  (labelid)
135                                 )",
136     
137         labels_conf                => "(
138                     id int(4) NOT NULL auto_increment,
139                                 barcodetype char(100) default '',
140                                 title tinyint(1) default '0',
141                                 isbn tinyint(1) default '0',
142                                 itemtype tinyint(1) default '0',
143                                 barcode tinyint(1) default '0',
144                                 dewey tinyint(1) default '0',
145                                 class tinyint(1) default '0',
146                                 author tinyint(1) default '0',
147                                 papertype char(100) default '',
148                                 startrow int(2) default NULL,
149                                 PRIMARY KEY  (id)
150                                 )",
151         reviews                  => "(
152                                 reviewid integer NOT NULL auto_increment,
153                                 borrowernumber integer,
154                                 biblionumber integer,
155                                 review text,
156                                 approved tinyint,
157                                 datereviewed datetime,
158                                 PRIMARY KEY (reviewid)
159                                 )",
160         subscriptionroutinglist=>"(
161                                 routingid integer NOT NULL auto_increment,
162                                 borrowernumber integer,
163                                 ranking integer,
164                                 subscriptionid integer,
165                                 PRIMARY KEY (routingid)
166                                 )",
167     
168         notifys    => "(
169                 notify_id int(11) NOT NULL default '0',
170                     `borrowernumber` int(11) NOT NULL default '0',
171                 `itemnumber` int(11) NOT NULL default '0',
172                 `notify_date` date NOT NULL default '0000-00-00',
173                         `notify_send_date` date default NULL,
174                         `notify_level` int(1) NOT NULL default '0',
175                         `method` varchar(20) NOT NULL default ''
176                 )",
177     
178     charges    => "(
179                 `charge_id` varchar(5) NOT NULL default '',
180                     `description` text NOT NULL,
181                     `amount` decimal(28,6) NOT NULL default '0.000000',
182                             `min` int(4) NOT NULL default '0',
183                     `max` int(4) NOT NULL default '0',
184                             `level` int(1) NOT NULL default '0',
185                             PRIMARY KEY  (`charge_id`)
186                 )",
187         tags => "(
188             `entry` varchar(255) NOT NULL default '',
189             `weight` bigint(20) NOT NULL default '0',
190             PRIMARY KEY  (`entry`)
191         )
192         ",
193     zebraqueue    => "(
194                     `id` int NOT NULL auto_increment,
195                     `biblio_auth_number` int NOT NULL,
196                     `operation` char(20) NOT NULL,
197                     `server` char(20) NOT NULL ,
198                     PRIMARY KEY  (`id`)
199                 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci AUTO_INCREMENT=1",
200     
201     );
202     
203     my %requirefields = (
204         subscription => { 'letter' => 'char(20) NULL', 'distributedto' => 'text NULL', 'firstacquidate'=>'date NOT NULL','irregularity'=>'TEXT NULL default \'\'','numberpattern'=>'TINYINT(3) NULL default 0', 'callnumber'=>'text NULL', 'hemisphere' =>'TINYINT(3) NULL default 0', 'issuesatonce'=>'TINYINT(3) NOT NULL default 1',  'branchcode' =>'varchar(12) NOT NULL default \'\'', 'manualhistory'=>'TINYINT(1) NOT NULL default 0','internalnotes'=>'LONGTEXT NULL default \'\''},
205         itemtypes => { 'imageurl' => 'char(200) NULL'},
206         aqbookfund => { 'branchcode' => 'varchar(4) NULL'},
207         aqbudget => { 'branchcode' => 'varchar(4) NULL'},
208         auth_header => { 'marc' => 'BLOB NOT NULL', 'linkid' => 'BIGINT(20) NULL'},
209         auth_subfield_structure =>{ 'hidden' => 'TINYINT(3) NOT NULL default 0', 'kohafield' => 'VARCHAR(45) NULL', 'linkid' =>  'TINYINT(1) NOT NULL default 0', 'isurl' => 'TINYINT(1)', 'frameworkcode'=>'VARCHAR(8) NOT  NULL'},
210         marc_breeding => { 'isbn' => 'varchar(13) NOT NULL'},
211         serial =>{ 'publisheddate' => 'date', 'claimdate' => 'date', 'itemnumber'=>'text NULL','routingnotes'=>'text NULL',},
212         statistics => { 'associatedborrower' => 'integer'},
213         z3950servers =>{  "name" =>"text",  "description" => "text NOT NULL",
214                         "position" =>"enum('primary','secondary','') NOT NULL default 'primary'",  "icon" =>"text",
215                         "type" =>"enum('zed','opensearch') NOT NULL default 'zed'",
216                         },
217         issues =>{ 'issuedate'=>"date NOT NULL default '0000-00-00'", },
218     
219     #    tablename        => { 'field' => 'fieldtype' },
220     );
221     
222     # Enter here the table to delete.
223     my @TableToDelete = qw(
224         additionalauthors
225         bibliosubject
226         bibliosubtitle
227         bibliothesaurus
228     );
229     
230     my %uselessfields = (
231     # tablename => "field1,field2",
232         borrowers => "suburb,altstreetaddress,altsuburb,altcity,studentnumber,school,area,preferredcont,altcp",
233         deletedborrowers=> "suburb,altstreetaddress,altsuburb,altcity,studentnumber,school,area,preferredcont,altcp",
234         );
235     # the other hash contains other actions that can't be done elsewhere. they are done
236     # either BEFORE of AFTER everything else, depending on "when" entry (default => AFTER)
237     
238     # The tabledata hash contains data that should be in the tables.
239     # The uniquefieldrequired hash entry is used to determine which (if any) fields
240     # must not exist in the table for this row to be inserted.  If the
241     # uniquefieldrequired entry is already in the table, the existing data is not
242     # modified, unless the forceupdate hash entry is also set.  Fields in the
243     # anonymous "forceupdate" hash will be forced to be updated to the default
244     # values given in the %tabledata hash.
245     
246     my %tabledata = (
247     # tablename => [
248     #    {    uniquefielrequired => 'fieldname', # the primary key in the table
249     #        fieldname => fieldvalue,
250     #        fieldname2 => fieldvalue2,
251     #    },
252     # ],
253         systempreferences => [
254             {
255                 uniquefieldrequired => 'variable',
256                 variable            => 'useDaysMode',
257                 value               => 'Calendar',
258                 forceupdate         => { 'explanation' => 1,
259                                         'type' => 1},
260                 explanation            => 'How to calculate return dates : Calendar means holidays will be controled, Days means the return date don\'t depend on holidays',
261                 type        => 'Choice',
262                 options        => 'Calendar|Days'
263             },
264             {
265                 uniquefieldrequired => 'variable',
266                 variable            => 'DebugLevel',
267                 value               => '0',
268                 forceupdate         => { 'explanation' => 1,
269                                         'type' => 1},
270                 explanation            => 'Set the level of error info sent to the browser. 0=none, 1=some, 2=most',
271                 type                => 'Choice',
272                 options             => '0|1|2'
273             },
274             {
275                 uniquefieldrequired => 'variable',
276                 variable            => 'BorrowersTitles',
277                 value               => 'Mr|Mrs|Miss|Ms',
278                 forceupdate         => { 'explanation' => 1,
279                                         'type' => 1},
280                 explanation         => 'List all Titles for borrowers',
281                 type                => 'free',
282             },
283             {
284                 uniquefieldrequired => 'variable',
285                 variable            => 'BorrowerMandatoryField',
286                 value               => 'cardnumber|surname|address',
287                 forceupdate         => { 'explanation' => 1,
288                                         'type' => 1},
289                 explanation         => 'List all mandatory fields for borrowers',
290                 type                => 'free',
291             },
292             {
293                 uniquefieldrequired => 'variable',
294                 variable            => 'borrowerRelationship',
295                 value               => 'father|mother,grand-mother',
296                 forceupdate         => { 'explanation' => 1,
297                                         'type' => 1},
298                 explanation         => 'The relationships between a guarantor & a guarantee (separated by | or ,)',
299                 type                => 'free',
300             },
301             {
302                 uniquefieldrequired => 'variable',
303                 variable            => 'ReservesMaxPickUpDelay',
304                 value               => '10',
305                 forceupdate         => { 'explanation' => 1,
306                                         'type' => 1},
307                 explanation         => 'Maximum delay to pick up a reserved document',
308                 type                => 'free',
309             },
310             {
311                 uniquefieldrequired => 'variable',
312                 variable            => 'TransfersMaxDaysWarning',
313                 value               => '3',
314                 forceupdate         => { 'explanation' => 1,
315                                         'type' => 1},
316                 explanation         => 'Max delay before considering the transfer has potentialy a problem',
317                 type                => 'free',
318             },
319             {
320                 uniquefieldrequired => 'variable',
321                 variable            => 'memberofinstitution',
322                 value               => '0',
323                 forceupdate         => { 'explanation' => 1,
324                                         'type' => 1},
325                 explanation         => 'Are your patrons members of institutions',
326                 type                => 'YesNo',
327             },
328         {
329                 uniquefieldrequired => 'variable',
330                 variable            => 'ReadingHistory',
331                 value               => '0',
332                 forceupdate         => { 'explanation' => 1,
333                                         'type' => 1},
334                 explanation         => 'Allow reading record info retrievable from issues and oldissues tables',
335                 type                => 'YesNo',
336             },
337         {
338                 uniquefieldrequired => 'variable',
339                 variable            => 'IssuingInProcess',
340                 value               => '0',
341                 forceupdate         => { 'explanation' => 1,
342                                         'type' => 1},
343                 explanation         => 'Allow no debt alert if the patron is issuing item that accumulate debt',
344                 type                => 'YesNo',
345             },
346         {
347                 uniquefieldrequired => 'variable',
348                 variable            => 'AutomaticItemReturn',
349                 value               => '1',
350                 forceupdate         => { 'explanation' => 1,
351                                         'type' => 1},
352                 explanation         => 'This Variable allow or not to return automaticly to his homebranch',
353                 type                => 'YesNo',
354             },
355         {
356                 uniquefieldrequired => 'variable',
357                 variable            => 'reviewson',
358                 value               => '0',
359                 forceupdate         => { 'explanation' => 1,
360                                         'type' => 1},
361                 explanation         => 'Allows patrons to submit reviews from the opac',
362                 type                => 'YesNo',
363             },
364         {
365                 uniquefieldrequired => 'variable',
366                 variable            => 'intranet_includes',
367                 value               => 'includes',
368                 forceupdate         => { 'explanation' => 1,
369                                         'type' => 1},
370                 explanation         => 'The includes directory you want for specific look of Koha (includes or includes_npl for example)',
371                 type                => 'Free',
372             },
373             {
374                 uniquefieldrequired => 'variable',
375                 variable            => 'AutoLocation',
376                 value               => '0',
377                 forceupdate         => { 'explanation' => 1,
378                                         'type' => 1},
379                 explanation         => 'switch to activate or not Autolocation, if Yes, the Librarian can\'t change his location, it\'s defined by branchip',
380                 type                => 'YesNo',
381             },
382             {
383                 uniquefieldrequired => 'variable',
384                 variable            => 'serialsadditems',
385                 value               => '0',
386                 forceupdate         => {
387                     'explanation' => 1,
388                     'type' => 1
389                 },
390                 explanation => 'If set, a new item will be automatically added when receiving an issue',
391                 type => 'YesNo',
392             },
393             {
394                 uniquefieldrequired => 'variable',
395                 variable            => 'expandedSearchOption',
396                 value               => '0',
397                 forceupdate         => {
398                     'explanation' => 1,
399                     'type' => 1
400                 },
401                 explanation => 'search among marc field',
402                 type => 'YesNo',
403             },
404         {
405                 uniquefieldrequired => 'variable',
406                 variable            => 'RequestOnOpac',
407                 value               => '1',
408                 forceupdate         => { 'explanation' => 1,
409                                         'type' => 1},
410                 explanation         => 'option to allow reserves on opac',
411                 type                => 'YesNo',
412             },
413         {
414                 uniquefieldrequired => 'variable',
415                 variable            => 'OpacCloud',
416                 value               => '1',
417                 forceupdate         => { 'explanation' => 1,
418                                         'type' => 1},
419                 explanation         => 'Enable / Disable cloud link on OPAC (Require to run misc/cronjobs/build_browser_and_cloud.pl on the server)',
420                 type                => 'YesNo',
421             },
422         {
423                 uniquefieldrequired => 'variable',
424                 variable            => 'OpacBrowser',
425                 value               => '1',
426                 forceupdate         => { 'explanation' => 1,
427                                         'type' => 1},
428                 explanation         => 'Enable/Disable browser link on OPAC (Require to run misc/cronjobs/build_browser_and_cloud.pl on the server)',
429                 type                => 'YesNo',
430             },
431         {
432                 uniquefieldrequired => 'variable',
433                 variable            => 'OpacTopissue',
434                 value               => '1',
435                 forceupdate         => { 'explanation' => 1,
436                                         'type' => 1},
437                 explanation         => 'Enable / Disable the top issue link on OPAC',
438                 type                => 'YesNo',
439             },
440         {
441                 uniquefieldrequired => 'variable',
442                 variable            => 'OpacAuthorities',
443                 value               => '1',
444                 forceupdate         => { 'explanation' => 1,
445                                         'type' => 1},
446                 explanation         => 'Enable / Disable the search authority link on OPAC',
447                 type                => 'YesNo',
448             },
449             {
450                 uniquefieldrequired => 'variable',
451                 variable            => 'CataloguingLog',
452                 value               => '0',
453                 forceupdate         => {'explanation' => 1, 'type' => 1},
454                 explanation         => 'Active this if you want to log cataloguing action.',
455                 type                => 'YesNo',
456             },
457             {
458                 uniquefieldrequired => 'variable',
459                 variable            => 'BorrowersLog',
460                 value               => '0',
461                 forceupdate         => {'explanation' => 1, 'type' => 1},
462                 explanation         => 'Active this if you want to log borrowers edition/creation/deletion...',
463                 type                => 'YesNo',
464             },
465             {
466                 uniquefieldrequired => 'variable',
467                 variable            => 'SubscriptionLog',
468                 value               => '0',
469                 forceupdate         => {'explanation' => 1, 'type' => 1},
470                 explanation         => 'Active this if you want to log Subscription action',
471                 type                => 'YesNo',
472             },
473             {
474                 uniquefieldrequired => 'variable',
475                 variable            => 'IssueLog',
476                 value               => '0',
477                 forceupdate         => {'explanation' => 1, 'type' => 1},
478                 explanation         => 'Active this if you want to log issue.',
479                 type                => 'YesNo',
480             },
481             {
482                 uniquefieldrequired => 'variable',
483                 variable            => 'ReturnLog',
484                 value               => '0',
485                 forceupdate         => {'explanation' => 1, 'type' => 1},
486                 explanation         => 'Active this if you want to log the circulation return',
487                 type                => 'YesNo',
488             },
489             {
490                 uniquefieldrequired => 'variable',
491                 variable            => 'Version',
492                 value               => '3.0',
493                 forceupdate         => {'explanation' => 1, 'type' => 1},
494                 explanation         => 'Koha Version',
495                 type                => 'Free',
496             },
497             {   
498                 uniquefieldrequired => 'variable',
499                 variable            => 'LetterLog',
500                 value               => '0',
501                 forceupdate         => {'explanation' => 1, 'type' => 1},
502                 explanation         => 'Active this if you want to log all the letter sent',
503                 type                => 'YesNo',
504             },
505             {
506                 uniquefieldrequired => 'variable',
507                 variable            => 'FinesLog',
508                 value               => '0',
509                 forceupdate         => {'explanation' => 1, 'type' => 1},
510                 explanation         => 'Active this if you want to log fines',
511                 type                => 'YesNo',
512             },
513             {
514                 uniquefieldrequired => 'variable',
515                 variable            => 'NoZebra',
516                 value               => '0',
517                 forceupdate         => {'explanation' => 1, 'type' => 1},
518                 explanation         => 'Active this if you want NOT to use zebra (large libraries should avoid this parameters)',
519                 type                => 'YesNo',
520             },
521             {
522                 uniquefieldrequired => 'variable',
523                 variable            => 'NoZebraIndexes',
524                 value               => '0',
525                 forceupdate         => {'explanation' => 1, 'type' => 1},
526                 explanation         => "Enter a specific hash for NoZebra indexes. Enter : 'indexname' => '100a,245a,500*','index2' => '...'",
527                 type                => 'Free',
528             },
529             {
530                 uniquefieldrequired => 'variable',
531                 variable            => 'uppercasesurnames',
532                 value               => '0',
533                 forceupdate         => {'explanation' => 1, 'type' => 1},
534                 explanation         => "Force Surnames to be uppercase",
535                 type                => 'YesNo',
536             },
537         ],
538         userflags => [
539             {
540                 uniquefieldrequired => 'bit',
541                 bit                 => '14',
542                 flag                => 'editauthorities',
543                 flagdesc            => 'allow to edit authorities',
544                 defaulton           => '0',
545             },
546             {
547                 uniquefieldrequired => 'bit',
548                 bit                 => '15',
549                 flag                 => 'serials',
550                 flagdesc            => 'allow to manage serials subscriptions',
551                 defaulton           => '0',
552             },
553             {
554                 uniquefieldrequired => 'bit',
555                 bit                 => '16',
556                 flag                 => 'reports',
557                 flagdesc            => 'allow to access to the reports module',
558                 defaulton           => '0',
559             },
560         ],
561         authorised_values => [
562             {
563                 uniquefieldrequired => 'id',
564                 category            => 'SUGGEST',
565                 authorised_value    => 'Not enough budget',
566                 lib                 => 'This book it too much expensive',
567             }
568         ],
569     );
570     
571     my %fielddefinitions = (
572     # fieldname => [
573     #    {          field => 'fieldname',
574     #             type    => 'fieldtype',
575     #             null    => '',
576     #             key     => '',
577     #             default => ''
578     #         },
579     #     ],
580         aqbasket =>  [
581             {
582                 field    => 'booksellerid',
583                 type    => 'int(11)',
584                 null    => 'NOT NULL',
585                 key        => '',
586                 default    => '1',
587                 extra    => '',
588             },
589         ],
590                 aqbookfund => [
591                         {
592                                 field  => 'bookfundid',
593                                 type   => 'varchar(5)',
594                                 null   => 'NOT NULL',
595                                 key    => 'PRI',
596                                 default => '',
597                                 extra  => '',
598                         },
599                 ],
600   
601         aqbooksellers =>  [
602             {
603                 field    => 'id',
604                 type    => 'int(11)',
605                 null    => 'NOT NULL',
606                 key        => 'PRI',
607                 default    => '',
608                 extra    => 'auto_increment',
609             },
610             {
611                 field    => 'listprice',
612                 type    => 'varchar(10)',
613                 null    => 'NULL',
614                 key        => '',
615                 default    => '',
616                 extra    => '',
617             },
618             {
619                 field    => 'invoiceprice',
620                 type    => 'varchar(10)',
621                 null    => 'NULL',
622                 key        => '',
623                 default    => '',
624                 extra    => '',
625             },
626                         {
627                                 field   => 'invoicedisc',
628                                 type    => 'float(6,4)',
629                                 null    => 'NULL',
630                                 key     => '',
631                                 default => 'NULL',
632                                 extra   => '',
633                         },
634                                 
635         ],
636         
637                 aqbudget     =>  [
638                         {
639                                 field    => 'bookfundid',
640                                 type     => 'varchar(5)',
641                                 null     => 'NOT NULL',
642                                 key      => '',
643                                 default  => '',
644                                 exra     => '',
645                          },
646                 ],
647                 
648         accountlines =>  [
649             {
650                 field    => 'notify_id',
651                 type    => 'int(11)',
652                 null    => 'NOT NULL',
653                 key        => '',
654                 default    => '0',
655                 extra    => '',
656             },
657             {
658                 field    => 'notify_level',
659                 type    => 'int(2)',
660                 null    => 'NOT NULL',
661                 key        => '',
662                 default    => '0',
663                 extra    => '',
664             },
665                         {
666                                 field   => 'accountno',
667                                 type    => 'smallint(6)',
668                                 null    => 'NOT NULL',
669                                 key     => '',
670                                 default => '0',
671                                 extra   => '',
672                         },
673                         {
674                                 field   => 'description',
675                                 type    => 'mediumtext',
676                                 null    => 'NULL',
677                         },
678                         {
679                                 field   => 'dispute',
680                                 type    => 'mediumtext',
681                                 null    => 'NULL',
682                     },
683         
684         ],
685         
686         borrowers => [
687             {    field => 'firstname',
688                 type => 'text',
689                 null => 'NULL',
690             },
691             {    field => 'initials',
692                 type => 'text',
693                 null => 'NULL',
694             },
695             {    field => 'B_email',
696                 type => 'text',
697                 null => 'NULL',
698                 after => 'B_zipcode',
699             },
700             {
701                 field => 'streetnumber', # street number (hidden if streettable table is empty)
702                 type => 'char(10)',
703                 null => 'NULL',
704                 after => 'initials',
705             },
706             {
707                 field => 'streettype', # street table, list builded from a system table
708                 type => 'char(50)',
709                 null => 'NULL',
710                 after => 'streetnumber',
711             },
712             {    field => 'phone',
713                 type => 'text',
714                 null => 'NULL',
715             },
716             {
717                 field => 'B_streetnumber', # street number (hidden if streettable table is empty)
718                 type => 'char(10)',
719                 null => 'NULL',
720                 after => 'fax',
721             },
722             {
723                 field => 'B_streettype', # street table, list builded from a system table
724                 type => 'char(50)',
725                 null => 'NULL',
726                 after => 'B_streetnumber',
727             },
728             {
729                 field => 'phonepro',
730                 type => 'text',
731                 null => 'NULL',
732                 after => 'fax',
733             },
734             {
735                 field => 'address2', # complement address
736                 type => 'text',
737                 null => 'NULL',
738                 after => 'address',
739             },
740             {
741                 field => 'emailpro',
742                 type => 'text',
743                 null => 'NULL',
744                 after => 'fax',
745             },
746             {
747                 field => 'contactfirstname', # contact's firstname
748                 type => 'text',
749                 null => 'NULL',
750                 after => 'contactname',
751             },
752             {
753                 field => 'contacttitle', # contact's title
754                 type => 'text',
755                 null => 'NULL',
756                 after => 'contactfirstname',
757             },
758             {
759                 field => 'branchcode',
760                 type  => 'varchar(10)',
761                 null  => 'NOT NULL',
762                 default    => '',
763                 extra => '',
764             },
765             {
766                 field => 'categorycode',
767                 type  => 'varchar(10)',
768                 null  => 'NOT NULL',
769                 default    => '',
770                 extra => '',
771             }
772         ],
773         
774         biblioitems =>  [
775             {
776                 field    => 'itemtype',
777                 type    => 'varchar(10)',
778                 null    => 'NOT NULL',
779                 key        => '',
780                 default    => '',
781                 extra    => '',
782             },
783             {
784                 field    => 'lcsort',
785                 type    => 'varchar(25)',
786                 null    => 'NULL',
787                 key        => '',
788                 default    => '',
789                 extra    => '',
790             },
791             {
792                 field    => 'ccode',
793                 type    => 'varchar(4)',
794                 null    => 'NULL',
795                 key        => '',
796                 default    => '',
797                 extra    => '',
798             },
799             {
800                 field   => 'dewey',
801                 type    => 'varchar(30)',
802                 null    => 'null',
803                 default => '',
804                 extra   => '',
805             },
806             {
807                 field   => 'publicationyear',
808                 type    => 'text',
809                 null    => 'null',
810                 default => '',
811                 extra   => '',
812             },
813             {
814                 field   => 'collectiontitle',
815                 type    => 'mediumtext',
816                 null    => 'null',
817                 default => '',
818                 extra   => '',
819             },
820             {
821                 field   => 'collectionissn',
822                 type    => 'mediumtext',
823                 null    => 'null',
824                 default => '',
825                 extra   => '',
826             },
827             {
828                 field   => 'collectionvolume',
829                 type    => 'mediumtext',
830                 null    => 'null',
831                 default => '',
832                 extra   => '',
833             },
834             {
835                 field   => 'editionstatement',
836                 type    => 'text',
837                 null    => 'null',
838                 default => '',
839                 extra   => '',
840             },
841             {
842                 field   => 'editionresponsibility',
843                 type    => 'text',
844                 null    => 'null',
845                 default => '',
846                 extra   => '',
847             },
848                 
849         ],
850         deletedbiblioitems => [
851             {
852                 field   => 'itemtype',
853                 type    => 'varchar(10)',
854                 null    => 'NOT NULL',
855                 default => '',
856                 extra   => '',
857             },
858             {
859                 field   => 'dewey',
860                 type    => 'varchar(30)',
861                 null    => 'null',
862                 default => '',
863                 extra   => '',
864             },
865         ],
866         branches =>  [
867             {
868                 field    => 'branchip',
869                 type    => 'varchar(15)',
870                 null    => 'NULL',
871                 key        => '',
872                 default    => '',
873                 extra    => '',
874             },
875             {
876                 field    => 'branchprinter',
877                 type    => 'varchar(100)',
878                 null    => 'NULL',
879                 key        => '',
880                 default    => '',
881                 extra    => '',
882             },
883             {
884                 field   => 'branchcode',
885                 type    => 'varchar(10)',
886                 null    => 'NOT NULL',
887                 default => '',
888                 extra   => '',
889             }
890         ],
891         branchtransfers =>[
892             {
893                 field   => 'frombranch',
894                 type    => 'VARCHAR(10)',
895                 null    => 'NOT NULL',
896                 key     => '',
897                 default => '',
898                 extra   => '',
899             },
900             {
901                 field   => 'tobranch',
902                 type    => 'VARCHAR(10)',
903                 null    => 'NOT NULL',
904                 key     => '',
905                 default => '',
906             }
907         ],
908         
909         categories =>  [
910             {
911                 field    => 'category_type',
912                 type    => 'char(1)',
913                 null    => 'NOT NULL',
914                 key        => '',
915                 default    => 'A',
916                 extra    => '',
917             },
918             {
919                 field   => 'categorycode',
920                 type    => 'varchar(10)',
921                 null    => 'NOT NULL',
922                 key     => 'PRI',
923                 default => '',
924                 extra   => '',
925             },
926         ],
927         
928         deletedborrowers => [
929             {    field => 'firstname',
930                 type => 'text',
931                 null => 'NULL',
932             },
933             {    field => 'initials',
934                 type => 'text',
935                 null => 'NULL',
936             },
937             {    field => 'B_email',
938                 type => 'text',
939                 null => 'NULL',
940                 after => 'B_zipcode',
941             },
942             {
943                 field => 'streetnumber', # street number (hidden if streettable table is empty)
944                 type => 'char(10)',
945                 null => 'NULL',
946                 after => 'initials',
947             },
948             {
949                 field => 'streettype', # street table, list builded from a system table
950                 type => 'char(50)',
951                 null => 'NULL',
952                 after => 'streetnumber',
953             },
954             {    field => 'phone',
955                 type => 'text',
956                 null => 'NULL',
957             },
958             {
959                 field => 'B_streetnumber', # street number (hidden if streettable table is empty)
960                 type => 'char(10)',
961                 null => 'NULL',
962                 after => 'fax',
963             },
964             {
965                 field => 'B_streettype', # street table, list builded from a system table
966                 type => 'char(50)',
967                 null => 'NULL',
968                 after => 'B_streetnumber',
969             },
970             {
971                 field => 'phonepro',
972                 type => 'text',
973                 null => 'NULL',
974                 after => 'fax',
975             },
976             {
977                 field => 'address2', # complement address
978                 type => 'text',
979                 null => 'NULL',
980                 after => 'address',
981             },
982             {
983                 field => 'emailpro',
984                 type => 'text',
985                 null => 'NULL',
986                 after => 'fax',
987             },
988             {
989                 field => 'contactfirstname', # contact's firstname
990                 type => 'text',
991                 null => 'NULL',
992                 after => 'contactname',
993             },
994             {
995                 field => 'contacttitle', # contact's title
996                 type => 'text',
997                 null => 'NULL',
998                 after => 'contactfirstname',
999             },
1000         ],
1001         
1002         issues =>  [
1003             {
1004                 field    => 'borrowernumber',
1005                 type    => 'int(11)',
1006                 null    => 'NULL', # can be null when a borrower is deleted and the foreign key rule executed
1007                 key        => '',
1008                 default    => '',
1009                 extra    => '',
1010             },
1011             {
1012                 field    => 'itemnumber',
1013                 type    => 'int(11)',
1014                 null    => 'NULL', # can be null when a borrower is deleted and the foreign key rule executed
1015                 key        => '',
1016                 default    => '',
1017                 extra    => '',
1018             },
1019             {
1020                 field   => 'branchcode',
1021                 type    => 'varchar(10)',
1022                 null    => 'NULL',
1023                 key     => '',
1024                 default => '',
1025                 extra   => '',
1026             },
1027             {
1028                 field   => 'issuedate',
1029                 type    => 'date',
1030                 null    => '',
1031                 key     => '',
1032                 default => '0000-00-00',
1033                 extra   => '',
1034             },
1035         ],
1036         issuingrules => [
1037             {
1038                 field   => 'categorycode',
1039                 type    => 'varchar(10)',
1040                 null    => 'NOT NULL',
1041                 default => '',
1042                 extra   => '',
1043             },
1044             {
1045                 field   => 'branchcode',
1046                 type    => 'varchar(10)',
1047                 null    => 'NOT NULL',
1048                 default => '',
1049                 extra   => '',
1050             },
1051             {
1052                 field   => 'itemtype',
1053                 type    => 'varchar(10)',
1054                 null    => 'NOT NULL',
1055                 default => '',
1056                 extra   => '',
1057             },
1058         ],
1059
1060         items => [
1061             {
1062                 field    => 'onloan',
1063                 type    => 'date',
1064                 null    => 'NULL',
1065                 key        => '',
1066                 default    => '0000-00-00',
1067                 extra    => '',
1068             },
1069             {
1070                 field    => 'cutterextra',
1071                 type    => 'varchar(45)',
1072                 null    => 'NULL',
1073                 key        => '',
1074                 default    => '',
1075                 extra    => '',
1076             },
1077             {
1078                 field    => 'homebranch',
1079                 type    => 'varchar(10)',
1080                 null    => 'NULL',
1081                 key        => '',
1082                 default    => '',
1083                 extra    => '',
1084             },
1085             {
1086                 field    => 'holdingbranch',
1087                 type    => 'varchar(10)',
1088                 null    => 'NULL',
1089                 key        => '',
1090                 default    => '',
1091                 extra    => '',
1092             },
1093             {
1094                 field    => 'itype',
1095                 type    => 'varchar(10)',
1096                 null    => 'NULL',
1097                 key        => '',
1098                 default    => '',
1099                 extra    => '',
1100             },
1101         ],
1102         itemtypes => [
1103             {
1104                 field  => 'itemtype',
1105                 type   => 'varchar(10)',
1106                 default    => '',
1107                 null   => 'NOT NULL',
1108                 key    => 'PRI',
1109                 extra  => 'UNIQUE',
1110             },
1111             {
1112                 field  => 'summary',
1113                 type   => 'TEXT',
1114                 null   => 'NULL',
1115                 key    => '',
1116                 extra  => '',
1117             },
1118         ],
1119         marc_breeding => [
1120             {
1121                 field => 'marc',
1122                 type  => 'LONGBLOB',
1123                 null  => 'NULL',
1124                 key    => '',
1125                 extra  => '',
1126             }
1127         ],
1128         marc_subfield_structure => [
1129             {
1130                 field => 'defaultvalue',
1131                 type  => 'TEXT',
1132                 null  => 'NULL',
1133                 key    => '',
1134                 extra  => '',
1135             }
1136         ],
1137         opac_news => [
1138             {
1139                 field  => 'expirationdate',
1140                 type   => 'date',
1141                 null   => 'null',
1142                 key    => '',
1143                 extra  => '',
1144             },
1145             {
1146                 field   => 'number',
1147                 type    => 'int(11)',
1148                 null    => 'NULL',
1149                 key     => '',
1150                 default => '0',
1151                 extra   => '',
1152             },
1153         ],
1154         reserves =>  [
1155             {
1156                 field    => 'waitingdate',
1157                 type    => 'date',
1158                 null    => 'NULL',
1159                 key        => '',
1160                 default    => '',
1161                 extra    => '',
1162             },
1163         ],
1164         serial => [
1165             {
1166                 field   => 'notes',
1167                 type    => 'TEXT',
1168                 null    => 'NULL',
1169                 key     => '',
1170                 default => '',
1171                 extra   => ''
1172             },
1173         ],
1174         shelfcontents => [
1175             {
1176                 field => 'dateadded',
1177                 type => 'timestamp',
1178                 null    => 'NULL',
1179             },
1180         ],
1181         statistics => [
1182             {
1183                 field => 'branch',
1184                 type => 'varchar(10)',
1185                 null    => 'NOT NULL',
1186             },
1187             {
1188                 field => 'itemtype',
1189                 type => 'varchar(10)',
1190                 null    => 'NOT NULL',
1191             },
1192         ],
1193         systempreferences =>  [
1194             {
1195                 field    => 'value',
1196                 type    => 'text',
1197                 null    => 'NULL',
1198                 key        => '',
1199                 default    => '',
1200                 extra    => '',
1201             },
1202             {
1203                 field    => 'explanation',
1204                 type    => 'text',
1205                 null    => 'NULL',
1206                 key        => '',
1207                 default    => '',
1208                 extra    => '',
1209             },
1210         ],
1211         suggestions => [
1212             {
1213                 field   => 'reason',
1214                 type    => 'text',
1215                 null    => 'NULL',
1216                 key     => ''  ,
1217                 default => '',
1218                 extra   =>    '',
1219             }
1220         ],
1221     );
1222     
1223     my %indexes = (
1224     #    table => [
1225     #         {    indexname => 'index detail'
1226     #         }
1227     #    ],
1228         aqbooksellers => [
1229             {    indexname => 'PRIMARY',
1230                 content => 'id',
1231                 type => 'PRI',
1232             }
1233         ],
1234         aqbasket => [
1235             {    indexname => 'booksellerid',
1236                 content => 'booksellerid',
1237             },
1238         ],
1239         aqorders => [
1240             {    indexname => 'basketno',
1241                 content => 'basketno',
1242             },
1243         ],
1244         aqorderbreakdown => [
1245             {    indexname => 'ordernumber',
1246                 content => 'ordernumber',
1247             },
1248             {    indexname => 'bookfundid',
1249                 content => 'bookfundid',
1250             },
1251         ],
1252         biblioitems => [
1253             {    indexname => 'isbn',
1254                 content => 'isbn',
1255             },
1256             {    indexname => 'publishercode',
1257                 content => 'publishercode',
1258             },
1259         ],
1260         branches => [
1261             {
1262                 indexname => 'branchcode',
1263                 content   => 'branchcode',
1264                 type => 'PRI',
1265             }
1266         ],
1267         branchrelations => [
1268             {
1269                 indexname => 'PRIMARY',
1270                 content => 'categorycode',
1271                 type => 'PRI',
1272             }
1273         ],
1274         branchrelations => [
1275             {    indexname => 'PRIMARY',
1276                 content => 'branchcode,categorycode',
1277                 type => 'PRI',
1278             },
1279             {    indexname => 'branchcode',
1280                 content => 'branchcode',
1281             },
1282             {    indexname => 'categorycode',
1283                 content => 'categorycode',
1284             }
1285         ],
1286         currency => [
1287             {    indexname => 'PRIMARY',
1288                 content => 'currency',
1289                 type => 'PRI',
1290             }
1291         ],
1292         categories => [
1293             {
1294                 indexname => 'categorycode',
1295                 content   => 'categorycode',
1296             }
1297         ],
1298         items => [
1299             {    indexname => 'homebranch',
1300                 content => 'homebranch',
1301             },
1302             {    indexname => 'holdingbranch',
1303                 content => 'holdingbranch',
1304             }
1305         ],
1306         itemtypes => [
1307             {
1308                 indexname => 'itemtype',
1309                 content   => 'itemtype',
1310             }
1311         ],
1312         shelfcontents => [
1313             {    indexname => 'shelfnumber',
1314                 content => 'shelfnumber',
1315             },
1316             {    indexname => 'itemnumber',
1317                 content => 'itemnumber',
1318             }
1319         ],
1320             userflags => [
1321                     {   indexname => 'PRIMARY',
1322                             content => 'bit',
1323                             type => 'PRI',
1324                     }
1325             ]
1326     );
1327     
1328     my %foreign_keys = (
1329     #    table => [
1330     #         {    key => 'the key in table' (must be indexed)
1331     #            foreigntable => 'the foreigntable name', # (the parent)
1332     #            foreignkey => 'the foreign key column(s)' # (in the parent)
1333     #            onUpdate => 'CASCADE|SET NULL|NO ACTION| RESTRICT',
1334     #            onDelete => 'CASCADE|SET NULL|NO ACTION| RESTRICT',
1335     #         }
1336     #    ],
1337         branchrelations => [
1338             {    key => 'branchcode',
1339                 foreigntable => 'branches',
1340                 foreignkey => 'branchcode',
1341                 onUpdate => 'CASCADE',
1342                 onDelete => 'CASCADE',
1343             },
1344             {    key => 'categorycode',
1345                 foreigntable => 'branchcategories',
1346                 foreignkey => 'categorycode',
1347                 onUpdate => 'CASCADE',
1348                 onDelete => 'CASCADE',
1349             },
1350         ],
1351         shelfcontents => [
1352             {    key => 'shelfnumber',
1353                 foreigntable => 'virtualshelf',
1354                 foreignkey => 'shelfnumber',
1355                 onUpdate => 'CASCADE',
1356                 onDelete => 'CASCADE',
1357             },
1358             {    key => 'itemnumber',
1359                 foreigntable => 'items',
1360                 foreignkey => 'itemnumber',
1361                 onUpdate => 'CASCADE',
1362                 onDelete => 'CASCADE',
1363             },
1364         ],
1365         # onDelete is RESTRICT on reference tables (branches, itemtype) as we don't want items to be
1366         # easily deleted, but branches/itemtype not too easy to empty...
1367         biblioitems => [
1368             {    key => 'biblionumber',
1369                 foreigntable => 'biblio',
1370                 foreignkey => 'biblionumber',
1371                 onUpdate => 'CASCADE',
1372                 onDelete => 'CASCADE',
1373             },
1374             {    key => 'itemtype',
1375                 foreigntable => 'itemtypes',
1376                 foreignkey => 'itemtype',
1377                 onUpdate => 'CASCADE',
1378                 onDelete => 'RESTRICT',
1379             },
1380         ],
1381         items => [
1382             {    key => 'biblioitemnumber',
1383                 foreigntable => 'biblioitems',
1384                 foreignkey => 'biblioitemnumber',
1385                 onUpdate => 'CASCADE',
1386                 onDelete => 'CASCADE',
1387             },
1388             {    key => 'homebranch',
1389                 foreigntable => 'branches',
1390                 foreignkey => 'branchcode',
1391                 onUpdate => 'CASCADE',
1392                 onDelete => 'RESTRICT',
1393             },
1394             {    key => 'holdingbranch',
1395                 foreigntable => 'branches',
1396                 foreignkey => 'branchcode',
1397                 onUpdate => 'CASCADE',
1398                 onDelete => 'RESTRICT',
1399             },
1400         ],
1401         aqbasket => [
1402             {    key => 'booksellerid',
1403                 foreigntable => 'aqbooksellers',
1404                 foreignkey => 'id',
1405                 onUpdate => 'CASCADE',
1406                 onDelete => 'RESTRICT',
1407             },
1408         ],
1409         aqorders => [
1410             {    key => 'basketno',
1411                 foreigntable => 'aqbasket',
1412                 foreignkey => 'basketno',
1413                 onUpdate => 'CASCADE',
1414                 onDelete => 'CASCADE',
1415             },
1416             {    key => 'biblionumber',
1417                 foreigntable => 'biblio',
1418                 foreignkey => 'biblionumber',
1419                 onUpdate => 'SET NULL',
1420                 onDelete => 'SET NULL',
1421             },
1422         ],
1423         aqbooksellers => [
1424             {    key => 'listprice',
1425                 foreigntable => 'currency',
1426                 foreignkey => 'currency',
1427                 onUpdate => 'CASCADE',
1428                 onDelete => 'CASCADE',
1429             },
1430             {    key => 'invoiceprice',
1431                 foreigntable => 'currency',
1432                 foreignkey => 'currency',
1433                 onUpdate => 'CASCADE',
1434                 onDelete => 'CASCADE',
1435             },
1436         ],
1437         aqorderbreakdown => [
1438             {    key => 'ordernumber',
1439                 foreigntable => 'aqorders',
1440                 foreignkey => 'ordernumber',
1441                 onUpdate => 'CASCADE',
1442                 onDelete => 'CASCADE',
1443             },
1444             {    key => 'bookfundid',
1445                 foreigntable => 'aqbookfund',
1446                 foreignkey => 'bookfundid',
1447                 onUpdate => 'CASCADE',
1448                 onDelete => 'CASCADE',
1449             },
1450         ],
1451         branchtransfers => [
1452             {    key => 'frombranch',
1453                 foreigntable => 'branches',
1454                 foreignkey => 'branchcode',
1455                 onUpdate => 'CASCADE',
1456                 onDelete => 'CASCADE',
1457             },
1458             {    key => 'tobranch',
1459                 foreigntable => 'branches',
1460                 foreignkey => 'branchcode',
1461                 onUpdate => 'CASCADE',
1462                 onDelete => 'CASCADE',
1463             },
1464             {    key => 'itemnumber',
1465                 foreigntable => 'items',
1466                 foreignkey => 'itemnumber',
1467                 onUpdate => 'CASCADE',
1468                 onDelete => 'CASCADE',
1469             },
1470         ],
1471         issues => [    # constraint is SET NULL : when a borrower or an item is deleted, we keep the issuing record
1472         # for stat purposes
1473             {    key => 'borrowernumber',
1474                 foreigntable => 'borrowers',
1475                 foreignkey => 'borrowernumber',
1476                 onUpdate => 'SET NULL',
1477                 onDelete => 'SET NULL',
1478             },
1479             {    key => 'itemnumber',
1480                 foreigntable => 'items',
1481                 foreignkey => 'itemnumber',
1482                 onUpdate => 'SET NULL',
1483                 onDelete => 'SET NULL',
1484             },
1485         ],
1486         reserves => [
1487             {    key => 'borrowernumber',
1488                 foreigntable => 'borrowers',
1489                 foreignkey => 'borrowernumber',
1490                 onUpdate => 'CASCADE',
1491                 onDelete => 'CASCADE',
1492             },
1493             {    key => 'biblionumber',
1494                 foreigntable => 'biblio',
1495                 foreignkey => 'biblionumber',
1496                 onUpdate => 'CASCADE',
1497                 onDelete => 'CASCADE',
1498             },
1499             {    key => 'itemnumber',
1500                 foreigntable => 'items',
1501                 foreignkey => 'itemnumber',
1502                 onUpdate => 'CASCADE',
1503                 onDelete => 'CASCADE',
1504             },
1505             {    key => 'branchcode',
1506                 foreigntable => 'branches',
1507                 foreignkey => 'branchcode',
1508                 onUpdate => 'CASCADE',
1509                 onDelete => 'CASCADE',
1510             },
1511         ],
1512         borrowers => [ # foreign keys are RESTRICT as we don't want to delete borrowers when a branch is deleted
1513         # but prevent deleting a branch as soon as it has 1 borrower !
1514             {    key => 'categorycode',
1515                 foreigntable => 'categories',
1516                 foreignkey => 'categorycode',
1517                 onUpdate => 'RESTRICT',
1518                 onDelete => 'RESTRICT',
1519             },
1520             {    key => 'branchcode',
1521                 foreigntable => 'branches',
1522                 foreignkey => 'branchcode',
1523                 onUpdate => 'RESTRICT',
1524                 onDelete => 'RESTRICT',
1525             },
1526         ],
1527         deletedborrowers => [ # foreign keys are RESTRICT as we don't want to delete borrowers when a branch is deleted
1528         # but prevent deleting a branch as soon as it has 1 borrower !
1529             {    key => 'categorycode',
1530                 foreigntable => 'categories',
1531                 foreignkey => 'categorycode',
1532                 onUpdate => 'RESTRICT',
1533                 onDelete => 'RESTRICT',
1534             },
1535             {    key => 'branchcode',
1536                 foreigntable => 'branches',
1537                 foreignkey => 'branchcode',
1538                 onUpdate => 'RESTRICT',
1539                 onDelete => 'RESTRICT',
1540             },
1541         ],
1542         accountlines => [
1543             {    key => 'borrowernumber',
1544                 foreigntable => 'borrowers',
1545                 foreignkey => 'borrowernumber',
1546                 onUpdate => 'CASCADE',
1547                 onDelete => 'CASCADE',
1548             },
1549             {    key => 'itemnumber',
1550                 foreigntable => 'items',
1551                 foreignkey => 'itemnumber',
1552                 onUpdate => 'SET NULL',
1553                 onDelete => 'SET NULL',
1554             },
1555         ],
1556         auth_tag_structure => [
1557             {    key => 'authtypecode',
1558                 foreigntable => 'auth_types',
1559                 foreignkey => 'authtypecode',
1560                 onUpdate => 'CASCADE',
1561                 onDelete => 'CASCADE',
1562             },
1563         ],
1564         # FIXME : don't constraint auth_*_table and auth_word, as they may be replaced by zebra
1565     );
1566     
1567     
1568     # column changes
1569     my %column_change = (
1570         # table
1571         borrowers => [
1572                     {
1573                         from => 'emailaddress',
1574                         to => 'email',
1575                         after => 'city',
1576                     },
1577                     {
1578                         from => 'streetaddress',
1579                         to => 'address',
1580                         after => 'initials',
1581                     },
1582                     {
1583                         from => 'faxnumber',
1584                         to => 'fax',
1585                         after => 'phone',
1586                     },
1587                     {
1588                         from => 'textmessaging',
1589                         to => 'opacnote',
1590                         after => 'userid',
1591                     },
1592                     {
1593                         from => 'altnotes',
1594                         to => 'contactnote',
1595                         after => 'opacnote',
1596                     },
1597                     {
1598                         from => 'physstreet',
1599                         to => 'B_address',
1600                         after => 'fax',
1601                     },
1602                     {
1603                         from => 'streetcity',
1604                         to => 'B_city',
1605                         after => 'B_address',
1606                     },
1607                     {
1608                         from => 'phoneday',
1609                         to => 'mobile',
1610                         after => 'phone',
1611                     },
1612                     {
1613                         from => 'zipcode',
1614                         to => 'zipcode',
1615                         after => 'city',
1616                     },
1617                     {
1618                         from => 'homezipcode',
1619                         to => 'B_zipcode',
1620                         after => 'B_city',
1621                     },
1622                     {
1623                         from => 'altphone',
1624                         to => 'B_phone',
1625                         after => 'B_zipcode',
1626                     },
1627                     {
1628                         from => 'expiry',
1629                         to => 'dateexpiry',
1630                         after => 'dateenrolled',
1631                     },
1632                     {
1633                         from => 'guarantor',
1634                         to => 'guarantorid',
1635                         after => 'contactname',
1636                     },
1637                     {
1638                         from => 'altrelationship',
1639                         to => 'relationship',
1640                         after => 'borrowernotes',
1641                     },
1642                 ],
1643     
1644         deletedborrowers => [
1645                     {
1646                         from => 'emailaddress',
1647                         to => 'email',
1648                         after => 'city',
1649                     },
1650                     {
1651                         from => 'streetaddress',
1652                         to => 'address',
1653                         after => 'initials',
1654                     },
1655                     {
1656                         from => 'faxnumber',
1657                         to => 'fax',
1658                         after => 'phone',
1659                     },
1660                     {
1661                         from => 'textmessaging',
1662                         to => 'opacnote',
1663                         after => 'userid',
1664                     },
1665                     {
1666                         from => 'altnotes',
1667                         to => 'contactnote',
1668                         after => 'opacnote',
1669                     },
1670                     {
1671                         from => 'physstreet',
1672                         to => 'B_address',
1673                         after => 'fax',
1674                     },
1675                     {
1676                         from => 'streetcity',
1677                         to => 'B_city',
1678                         after => 'B_address',
1679                     },
1680                     {
1681                         from => 'phoneday',
1682                         to => 'mobile',
1683                         after => 'phone',
1684                     },
1685                     {
1686                         from => 'zipcode',
1687                         to => 'zipcode',
1688                         after => 'city',
1689                     },
1690                     {
1691                         from => 'homezipcode',
1692                         to => 'B_zipcode',
1693                         after => 'B_city',
1694                     },
1695                     {
1696                         from => 'altphone',
1697                         to => 'B_phone',
1698                         after => 'B_zipcode',
1699                     },
1700                     {
1701                         from => 'expiry',
1702                         to => 'dateexpiry',
1703                         after => 'dateenrolled',
1704                     },
1705                     {
1706                         from => 'guarantor',
1707                         to => 'guarantorid',
1708                         after => 'contactname',
1709                     },
1710                     {
1711                         from => 'altrelationship',
1712                         to => 'relationship',
1713                         after => 'borrowernotes',
1714                     },
1715                 ],
1716             );
1717         
1718     
1719     # MOVE all tables TO UTF-8 and innoDB
1720     $sth = $dbh->prepare("show table status");
1721     $sth->execute;
1722     while ( my $table = $sth->fetchrow_hashref ) {
1723         next if $table->{Name} eq 'marc_word';
1724         next if $table->{Name} eq 'marc_subfield_table';
1725         next if $table->{Name} eq 'auth_word';
1726         next if $table->{Name} eq 'auth_subfield_table';
1727         if ($table->{Engine} ne 'InnoDB') {
1728             print "moving $table->{Name} to InnoDB\n";
1729             $dbh->do("ALTER TABLE $table->{Name} TYPE = innodb");
1730         }
1731         unless ($table->{Collation} =~ /^utf8/) {
1732             print "moving $table->{Name} to utf8\n";
1733             $dbh->do("ALTER TABLE $table->{Name} CONVERT TO CHARACTER SET utf8");
1734             $dbh->do("ALTER TABLE $table->{Name} DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci");
1735             # 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 !
1736         } else {
1737         }
1738     }
1739     
1740     
1741     foreach my $table (keys %column_change) {
1742         $sth = $dbh->prepare("show columns from $table");
1743         $sth->execute();
1744         undef %types;
1745         while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1746         {
1747             $types{$column}->{type} ="$type";
1748             $types{$column}->{null} = "$null";
1749             $types{$column}->{key} = "$key";
1750             $types{$column}->{default} = "$default";
1751             $types{$column}->{extra} = "$extra";
1752         }    # while
1753         my $tablerows = $column_change{$table};
1754         foreach my $row ( @$tablerows ) {
1755             if ($types{$row->{from}}->{type}) {
1756                 print "altering $table $row->{from} to $row->{to}\n";
1757                 # ALTER TABLE `borrowers` CHANGE `faxnumber` `fax` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
1758     #             alter table `borrowers` change `faxnumber` `fax` type text  null after phone
1759                 my $sql =
1760                     "alter table `$table` change `$row->{from}` `$row->{to}` $types{$row->{from}}->{type} ".
1761                     ($types{$row->{from}}->{null} eq 'YES'?" NULL":" NOT NULL").
1762                     ($types{$row->{from}}->{default}?" default ".$types{$row->{from}}->{default}:"").
1763                     "$types{$row->{from}}->{extra} after $row->{after} ";
1764     #             print "$sql";
1765                 $dbh->do($sql);
1766             }
1767         }
1768     }
1769     
1770     # Enter here the field you want to delete from DB.
1771     # FIXME :: there is a %uselessfield before which seems doing the same things.
1772     my %fieldtodelete = (
1773         # tablename => [fieldname1,fieldname2,...]
1774     
1775     ); # %fielddelete
1776     
1777     print "removing some unused fields...\n";
1778     foreach my $table ( keys %fieldtodelete ) {
1779         foreach my $field ( @{$fieldtodelete{$table}} ){
1780             print "removing ".$field." from ".$table;
1781             my $sth = $dbh->prepare("ALTER TABLE $table DROP $field");
1782             $sth->execute;
1783             if ( $sth->err ) {
1784                 print "Error : $sth->errstr \n";
1785             }
1786         }
1787     }
1788     
1789     # Enter here the line you want to remove from DB.
1790     my %linetodelete = (
1791         # table name => where clause.
1792         userflags => "bit = 8", # delete the 'reserveforself' flags
1793         
1794     ); # %linetodelete
1795     
1796     #-------------------
1797     # Initialize
1798     
1799     # Start checking
1800     
1801     # Get version of MySQL database engine.
1802     my $mysqlversion = `mysqld --version`;
1803     $mysqlversion =~ /Ver (\S*) /;
1804     $mysqlversion = $1;
1805     if ( $mysqlversion ge '3.23' ) {
1806         print "Could convert to MyISAM database tables...\n" unless $silent;
1807     }
1808     
1809     #---------------------------------
1810     # Tables
1811     
1812     # Collect all tables into a list
1813     $sth = $dbh->prepare("show tables");
1814     $sth->execute;
1815     while ( my ($table) = $sth->fetchrow ) {
1816         $existingtables{$table} = 1;
1817     }
1818     
1819     
1820     # Now add any missing tables
1821     foreach $table ( keys %requiretables ) {
1822         unless ( $existingtables{$table} ) {
1823         print "Adding $table table...\n" unless $silent;
1824             my $sth = $dbh->prepare("create table $table $requiretables{$table} ENGINE=InnoDB DEFAULT CHARSET=utf8");
1825             $sth->execute;
1826             if ( $sth->err ) {
1827                 print "Error : $sth->errstr \n";
1828                 $sth->finish;
1829             }    # if error
1830         }    # unless exists
1831     }    # foreach
1832     
1833     #---------------------------------
1834     # Columns
1835     
1836     foreach $table ( keys %requirefields ) {
1837         print "Check table $table\n" if $debug and not $silent;
1838         $sth = $dbh->prepare("show columns from $table");
1839         $sth->execute();
1840         undef %types;
1841         while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1842         {
1843             $types{$column} = $type;
1844         }    # while
1845         foreach $column ( keys %{ $requirefields{$table} } ) {
1846             print "  Check column $column  [$types{$column}]\n" if $debug and not $silent;
1847             if ( !$types{$column} ) {
1848     
1849                 # column doesn't exist
1850                 print "Adding $column field to $table table...\n" unless $silent;
1851                 $query = "alter table $table
1852                 add column $column " . $requirefields{$table}->{$column};
1853                 print "Execute: $query\n" if $debug;
1854                 my $sti = $dbh->prepare($query);
1855                 $sti->execute;
1856                 if ( $sti->err ) {
1857                     print "**Error : $sti->errstr \n";
1858                     $sti->finish;
1859                 }    # if error
1860             }    # if column
1861         }    # foreach column
1862     }    # foreach table
1863     
1864     foreach $table ( keys %fielddefinitions ) {
1865         print "Check table $table\n" if $debug;
1866         $sth = $dbh->prepare("show columns from $table");
1867         $sth->execute();
1868         my $definitions;
1869         while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1870         {
1871             $definitions->{$column}->{type}    = $type;
1872             $definitions->{$column}->{null}    = $null;
1873             $definitions->{$column}->{null}    = 'NULL' if $null eq 'YES';
1874             $definitions->{$column}->{key}     = $key;
1875             $definitions->{$column}->{default} = $default;
1876             $definitions->{$column}->{extra}   = $extra;
1877         }    # while
1878         my $fieldrow = $fielddefinitions{$table};
1879         foreach my $row (@$fieldrow) {
1880             my $field   = $row->{field};
1881             my $type    = $row->{type};
1882             my $null    = $row->{null};
1883     #         $null    = 'YES' if $row->{null} eq 'NULL';
1884             my $key     = $row->{key};
1885             my $default = $row->{default};
1886     #         $default="''" unless $default;
1887             my $extra   = $row->{extra};
1888             my $def     = $definitions->{$field};
1889             my $after    = ($row->{after}?" after ".$row->{after}:"");
1890     
1891             unless ( $type eq $def->{type}
1892                 && $null eq $def->{null}
1893                 && $key eq $def->{key}
1894                 && $extra eq $def->{extra} )
1895             {
1896                 if ( $null eq '' ) {
1897                     $null = 'NOT NULL';
1898                 }
1899                 if ( $key eq 'PRI' ) {
1900                     $key = 'PRIMARY KEY';
1901                 }
1902                 unless ( $extra eq 'auto_increment' ) {
1903                     $extra = '';
1904                 }
1905         
1906                 # if it's a new column use "add", if it's an old one, use "change".
1907                 my $action;
1908                 if ($definitions->{$field}->{type}) {
1909                     $action="change $field"
1910                 } else {
1911                     $action="add";
1912                 }
1913     # if it's a primary key, drop the previous pk, before altering the table
1914                 print "  alter or create $field in $table\n" unless $silent;
1915                 my $query;
1916                 if ($key ne 'PRIMARY KEY') {
1917     #                 warn "alter table $table $action $field $type $null $key $extra default $default $after";
1918                     $query = "alter table $table $action $field $type $null $key $extra ".($default?"default ".$dbh->quote($default):"")." $after";
1919                 } else {
1920     #             warn "alter table $table drop primary key, $action $field $type $null $key $extra default $default $after";
1921                     # something strange : for indexes UNIQUE, they are reported as primary key here.
1922                     # but if you try to run with drop primary key, it fails.
1923                     # thus, we run the query twice, one will fail, one will succeed.
1924                     # strange...
1925                     $query="alter table $table drop primary key, $action $field $type $null $key $extra ".($default?"default ".$dbh->quote($default):"")." $after";
1926                     $query="alter table $table $action $field $type $null $key $extra ".($default?"default ".$dbh->quote($default):"")." $after";
1927                 }
1928                 $dbh->do($query);
1929             }
1930         }
1931     }
1932     
1933     print "removing some unused data...\n";
1934     foreach my $table ( keys %linetodelete ) {
1935         foreach my $where ( @{linetodelete{$table}} ){
1936             print "DELETE FROM ".$table." where ".$where;
1937             print "\n";
1938             my $sth = $dbh->prepare("DELETE FROM $table where $where");
1939             $sth->execute;
1940             if ( $sth->err ) {
1941                 print "Error : $sth->errstr \n";
1942             }
1943         }
1944     }
1945     
1946     # Populate tables with required data
1947     
1948     # synch table and deletedtable.
1949     foreach my $table (('borrowers','items','biblio','biblioitems')) {
1950         my %deletedborrowers;
1951         print "synch'ing $table and deleted$table\n";
1952         $sth = $dbh->prepare("show columns from deleted$table");
1953         $sth->execute;
1954         while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow ) {
1955             $deletedborrowers{$column}=1;
1956         }
1957         $sth = $dbh->prepare("show columns from $table");
1958         $sth->execute;
1959         my $previous;
1960         while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow ) {
1961             unless ($deletedborrowers{$column}) {
1962                 my $newcol="alter table deleted$table add $column $type";
1963                 if ($null eq 'YES') {
1964                     $newcol .= " NULL ";
1965                 } else {
1966                     $newcol .= " NOT NULL ";
1967                 }
1968                 $newcol .= "default ".$dbh->quote($default) if $default;
1969                 $newcol .= " after $previous" if $previous;
1970                 $previous=$column;
1971                 print "creating column $column\n";
1972                 $dbh->do($newcol);
1973             }
1974         }
1975     }
1976     #
1977     # update publisheddate 
1978     #
1979     $sth = $dbh->prepare("select count(*) from serial where publisheddate is NULL");
1980     $sth->execute;
1981     my ($emptypublished) = $sth->fetchrow;
1982     if ($emptypublished) {
1983         print "Updating publisheddate\n";
1984         $dbh->do("update serial set publisheddate=planneddate where publisheddate is NULL");
1985     }
1986     foreach my $table ( keys %tabledata ) {
1987         print "Checking for data required in table $table...\n" unless $silent;
1988         my $tablerows = $tabledata{$table};
1989         foreach my $row (@$tablerows) {
1990             my $uniquefieldrequired = $row->{uniquefieldrequired};
1991             my $uniquevalue         = $row->{$uniquefieldrequired};
1992             my $forceupdate         = $row->{forceupdate};
1993             my $sth                 =
1994             $dbh->prepare(
1995     "select $uniquefieldrequired from $table where $uniquefieldrequired=?"
1996             );
1997             $sth->execute($uniquevalue);
1998             if ($sth->rows) {
1999                 foreach my $field (keys %$forceupdate) {
2000                     if ($forceupdate->{$field}) {
2001                         my $sth=$dbh->prepare("update systempreferences set $field=? where $uniquefieldrequired=?");
2002                         $sth->execute($row->{$field}, $uniquevalue);
2003                     }
2004                 }
2005             } else {
2006                 print "Adding row to $table: " unless $silent;
2007                 my @values;
2008                 my $fieldlist;
2009                 my $placeholders;
2010                 foreach my $field ( keys %$row ) {
2011                     next if $field eq 'uniquefieldrequired';
2012                     next if $field eq 'forceupdate';
2013                     my $value = $row->{$field};
2014                     push @values, $value;
2015                     print "  $field => $value" unless $silent;
2016                     $fieldlist .= "$field,";
2017                     $placeholders .= "?,";
2018                 }
2019                 print "\n" unless $silent;
2020                 $fieldlist    =~ s/,$//;
2021                 $placeholders =~ s/,$//;
2022                 print "insert into $table ($fieldlist) values ($placeholders)";
2023                 my $sth =
2024                 $dbh->prepare(
2025                     "insert into $table ($fieldlist) values ($placeholders)");
2026                 $sth->execute(@values);
2027             }
2028         }
2029     }
2030     
2031     #
2032     # check indexes and create them when needed
2033     #
2034     print "Checking for index required...\n" unless $silent;
2035     foreach my $table ( keys %indexes ) {
2036         #
2037         # read all indexes from $table
2038         #
2039         $sth = $dbh->prepare("show index from $table");
2040         $sth->execute;
2041         my %existingindexes;
2042         while ( my ( $table, $non_unique, $key_name, $Seq_in_index, $Column_name, $Collation, $cardinality, $sub_part, $Packed, $comment ) = $sth->fetchrow ) {
2043             $existingindexes{$key_name} = 1;
2044         }
2045         # read indexes to check
2046         my $tablerows = $indexes{$table};
2047         foreach my $row (@$tablerows) {
2048             my $key_name=$row->{indexname};
2049             if ($existingindexes{$key_name} eq 1) {
2050     #             print "$key_name existing";
2051             } else {
2052                 print "\tCreating index $key_name in $table\n";
2053                 my $sql;
2054                 if ($row->{indexname} eq 'PRIMARY') {
2055                     $sql = "alter table $table ADD PRIMARY KEY ($row->{content})";
2056                 } else {
2057                     $sql = "alter table $table ADD INDEX $key_name ($row->{content}) $row->{type}";
2058                 }
2059                 $dbh->do($sql);
2060                 print "Error $sql : $dbh->err \n" if $dbh->err;
2061             }
2062         }
2063     }
2064     
2065     #
2066     # check foreign keys and create them when needed
2067     #
2068     print "Checking for foreign keys required...\n" unless $silent;
2069     foreach my $table ( keys %foreign_keys ) {
2070         #
2071         # read all indexes from $table
2072         #
2073         $sth = $dbh->prepare("show table status like '$table'");
2074         $sth->execute;
2075         my $stat = $sth->fetchrow_hashref;
2076         # read indexes to check
2077         my $tablerows = $foreign_keys{$table};
2078         foreach my $row (@$tablerows) {
2079             my $foreign_table=$row->{foreigntable};
2080             if ($stat->{'Comment'} =~/$foreign_table/) {
2081     #             print "$foreign_table existing\n";
2082             } else {
2083                 print "\tCreating foreign key $foreign_table in $table\n";
2084                 # first, drop any orphan value in child table
2085                 if ($row->{onDelete} ne "RESTRICT") {
2086                     my $sql = "delete from $table where $row->{key} not in (select $row->{foreignkey} from $row->{foreigntable})";
2087                     $dbh->do($sql);
2088                     print "SQL ERROR: $sql : $dbh->err \n" if $dbh->err;
2089                 }
2090                 my $sql="alter table $table ADD FOREIGN KEY $row->{key} ($row->{key}) REFERENCES $row->{foreigntable} ($row->{foreignkey})";
2091                 $sql .= " on update ".$row->{onUpdate} if $row->{onUpdate};
2092                 $sql .= " on delete ".$row->{onDelete} if $row->{onDelete};
2093                 $dbh->do($sql);
2094                 if ($dbh->err) {
2095                     print "====================
2096     An error occured during :
2097     \t$sql
2098     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).
2099     You can find those values with select
2100     \t$table.* from $table where $row->{key} not in (select $row->{foreignkey} from $row->{foreigntable})
2101     ====================\n
2102     ";
2103                 }
2104             }
2105         }
2106     }
2107     # now drop useless tables
2108     foreach $table ( @TableToDelete ) {
2109         if ( $existingtables{$table} ) {
2110             print "Dropping unused table $table\n" if $debug and not $silent;
2111             $dbh->do("drop table $table");
2112             if ( $dbh->err ) {
2113                 print "Error : $dbh->errstr \n";
2114             }
2115         }
2116     }
2117     
2118     #
2119     # SPECIFIC STUFF
2120     #
2121     #
2122     # create frameworkcode row in biblio table & fill it with marc_biblio.frameworkcode.
2123     #
2124     
2125     # 1st, get how many biblio we will have to do...
2126     $sth = $dbh->prepare('select count(*) from marc_biblio');
2127     $sth->execute;
2128     my ($totaltodo) = $sth->fetchrow;
2129     
2130     $sth = $dbh->prepare("show columns from biblio");
2131     $sth->execute();
2132     my $definitions;
2133     my $bibliofwexist=0;
2134     while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow ){
2135         $bibliofwexist=1 if $column eq 'frameworkcode';
2136     }
2137     unless ($bibliofwexist) {
2138         print "moving biblioframework to biblio table\n";
2139         $dbh->do('ALTER TABLE `biblio` ADD `frameworkcode` VARCHAR( 4 ) NOT NULL AFTER `biblionumber`');
2140         $sth = $dbh->prepare('select biblionumber,frameworkcode from marc_biblio');
2141         $sth->execute;
2142         my $sth_update = $dbh->prepare('update biblio set frameworkcode=? where biblionumber=?');
2143         my $totaldone=0;
2144         while (my ($biblionumber,$frameworkcode) = $sth->fetchrow) {
2145             $sth_update->execute($frameworkcode,$biblionumber);
2146             $totaldone++;
2147             print "\r$totaldone / $totaltodo" unless ($totaldone % 100);
2148         }
2149         print "\rdone\n";
2150     }
2151     
2152     # at last, remove useless fields
2153     foreach $table ( keys %uselessfields ) {
2154         my @fields = split /,/,$uselessfields{$table};
2155         my $fields;
2156         my $exists;
2157         foreach my $fieldtodrop (@fields) {
2158             $fieldtodrop =~ s/\t//g;
2159             $fieldtodrop =~ s/\n//g;
2160             $exists =0;
2161             $sth = $dbh->prepare("show columns from $table");
2162             $sth->execute;
2163             while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
2164             {
2165                 $exists =1 if ($column eq $fieldtodrop);
2166             }
2167             if ($exists) {
2168                 print "deleting $fieldtodrop field in $table...\n" unless $silent;
2169                 my $sth = $dbh->prepare("alter table $table drop $fieldtodrop");
2170                 $sth->execute;
2171             }
2172         }
2173     }    # foreach
2174     
2175     #
2176     # Changing aqbookfund's primary key 
2177     #
2178     $sth=$dbh->prepare("ALTER TABLE `aqbookfund` DROP PRIMARY KEY , ADD PRIMARY KEY ( `bookfundid` , `branchcode` ) ;");
2179     $sth->execute;
2180     
2181     $sth->finish;
2182     print "upgrade to Koha 3.0 done\n";
2183     SetVersion ($DBversion);
2184
2185
2186 =item TransformToNum
2187
2188   Transform the Koha version from a 4 parts string
2189   to a number, with just 1 .
2190   
2191 =cut
2192
2193 sub TransformToNum {
2194     my $version = shift;
2195     # remove the 3 last . to have a Perl number
2196     $version =~ s/(.*\..*)\.(.*)\.(.*)/$1$2$3/;
2197     return $version;
2198 }
2199
2200 =item SetVersion
2201     set the DBversion in the systempreferences
2202 =cut
2203
2204 sub SetVersion {
2205     my $kohaversion = TransformToNum(shift);
2206     if (C4::Context->preference('Version')) {
2207       my $finish=$dbh->prepare("UPDATE systempreferences SET value=? WHERE variable='Version'");
2208       $finish->execute($kohaversion);
2209     } else {
2210       my $finish=$dbh->prepare("INSERT into systempreferences (variable,value,explanation) values ('Version',?,'The Koha database version. WARNING: Don\'t change this value manually, it\'s maintained by the webinstaller')");
2211       $finish->execute($kohaversion);
2212     }
2213 }
2214 exit;
2215
2216 # Revision 1.172  2007/07/19 10:21:22  hdl