For instance, the return date does not rely on the borrower expiration date. A system...
[koha.git] / updater / updatedatabase
1 #!/usr/bin/perl
2
3 # $Id$
4
5 # Database Updater
6 # This script checks for required updates to the database.
7
8 # Part of the Koha Library Software www.koha.org
9 # Licensed under the GPL.
10
11 # Bugs/ToDo:
12 # - Would also be a good idea to offer to do a backup at this time...
13
14 # NOTE:  If you do something more than once in here, make it table driven.
15 use strict;
16
17 # CPAN modules
18 use DBI;
19 use Getopt::Long;
20 # Koha modules
21 use C4::Context;
22
23 # FIXME - The user might be installing a new database, so can't rely
24 # on /etc/koha.conf anyway.
25
26 my $debug = 0;
27
28 my (
29     $sth, $sti,
30     $query,
31     %existingtables,    # tables already in database
32     %types,
33     $table,
34     $column,
35     $type, $null, $key, $default, $extra,
36     $prefitem,          # preference item in systempreferences table
37 );
38
39 my $silent;
40 GetOptions(
41         's' =>\$silent
42         );
43 my $dbh = C4::Context->dbh;
44 print "connected to your DB. Checking & modifying it\n" unless $silent;
45
46 #-------------------
47 # Defines
48
49 # Tables to add if they don't exist
50 my %requiretables = (
51     categorytable       => "(categorycode char(5) NOT NULL default '',
52                              description text default '',
53                              itemtypecodes text default '',
54                              PRIMARY KEY (categorycode)
55                             )",
56     subcategorytable       => "(subcategorycode char(5) NOT NULL default '',
57                              description text default '',
58                              itemtypecodes text default '',
59                              PRIMARY KEY (subcategorycode)
60                             )",
61     mediatypetable       => "(mediatypecode char(5) NOT NULL default '',
62                              description text default '',
63                              itemtypecodes text default '',
64                              PRIMARY KEY (mediatypecode)
65                             )",
66     action_logs         => "(
67                                     `timestamp` TIMESTAMP NOT NULL ,
68                                     `user` INT( 11 ) NOT NULL ,
69                                     `module` TEXT default '',
70                                     `action` TEXT default '' ,
71                                     `object` INT(11) default '' ,
72                                     `info` TEXT default '' ,
73                                     PRIMARY KEY ( `timestamp` , `user` )
74                             )",
75 );
76
77 my %requirefields = (
78 #    tablename        => { 'field' => 'fieldtype' },
79 );
80
81 my %dropable_table = (
82 # tablename => 'tablename',
83 );
84
85 my %uselessfields = (
86 # tablename => "field1,field2",
87         );
88 # the other hash contains other actions that can't be done elsewhere. they are done
89 # either BEFORE of AFTER everything else, depending on "when" entry (default => AFTER)
90
91 # The tabledata hash contains data that should be in the tables.
92 # The uniquefieldrequired hash entry is used to determine which (if any) fields
93 # must not exist in the table for this row to be inserted.  If the
94 # uniquefieldrequired entry is already in the table, the existing data is not
95 # modified, unless the forceupdate hash entry is also set.  Fields in the
96 # anonymous "forceupdate" hash will be forced to be updated to the default
97 # values given in the %tabledata hash.
98
99 my %tabledata = (
100 # tablename => [
101 #       {       uniquefielrequired => 'fieldname', # the primary key in the table
102 #               fieldname => fieldvalue,
103 #               fieldname2 => fieldvalue2,
104 #       },
105 # ],
106     systempreferences => [
107                 {
108             uniquefieldrequired => 'variable',
109             variable            => 'Activate_Log',
110             value               => 'On',
111             forceupdate         => { 'explanation' => 1,
112                                      'type' => 1},
113             explanation         => 'Turn Log Actions on DB On an Off',
114             type                => 'YesNo',
115         },
116                 {
117             uniquefieldrequired => 'variable',
118             variable            => 'ReturnBeforeExpiry',
119             value               => 'Off',
120             forceupdate         => { 'explanation' => 1,
121                                      'type' => 1},
122             explanation         => 'If Yes, Returndate on issuing can\'t be after borrower card expiry',
123             type                => 'YesNo',
124         },
125     ],
126
127 );
128
129 my %fielddefinitions = (
130 # fieldname => [
131 #       {                 field => 'fieldname',
132 #             type    => 'fieldtype',
133 #             null    => '',
134 #             key     => '',
135 #             default => ''
136 #         },
137 #     ],
138 );
139
140 #-------------------
141 # Initialize
142
143 # Start checking
144
145 # Get version of MySQL database engine.
146 my $mysqlversion = `mysqld --version`;
147 $mysqlversion =~ /Ver (\S*) /;
148 $mysqlversion = $1;
149 if ( $mysqlversion ge '3.23' ) {
150     print "Could convert to MyISAM database tables...\n" unless $silent;
151 }
152
153 #---------------------------------
154 # Tables
155
156 # Collect all tables into a list
157 $sth = $dbh->prepare("show tables");
158 $sth->execute;
159 while ( my ($table) = $sth->fetchrow ) {
160     $existingtables{$table} = 1;
161 }
162
163
164 # Now add any missing tables
165 foreach $table ( keys %requiretables ) {
166     unless ( $existingtables{$table} ) {
167         print "Adding $table table...\n" unless $silent;
168         my $sth = $dbh->prepare("create table $table $requiretables{$table}");
169         $sth->execute;
170         if ( $sth->err ) {
171             print "Error : $sth->errstr \n";
172             $sth->finish;
173         }    # if error
174     }    # unless exists
175 }    # foreach
176
177 # now drop useless tables
178 foreach $table ( keys %dropable_table ) {
179         if ( $existingtables{$table} ) {
180                 print "Dropping unused table $table\n" if $debug and not $silent;
181                 $dbh->do("drop table $table");
182                 if ( $dbh->err ) {
183                         print "Error : $dbh->errstr \n";
184                 }
185         }
186 }
187
188 #---------------------------------
189 # Columns
190
191 foreach $table ( keys %requirefields ) {
192     print "Check table $table\n" if $debug and not $silent;
193     $sth = $dbh->prepare("show columns from $table");
194     $sth->execute();
195     undef %types;
196     while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
197     {
198         $types{$column} = $type;
199     }    # while
200     foreach $column ( keys %{ $requirefields{$table} } ) {
201         print "  Check column $column  [$types{$column}]\n" if $debug and not $silent;
202         if ( !$types{$column} ) {
203
204             # column doesn't exist
205             print "Adding $column field to $table table...\n" unless $silent;
206             $query = "alter table $table
207                         add column $column " . $requirefields{$table}->{$column};
208             print "Execute: $query\n" if $debug;
209             my $sti = $dbh->prepare($query);
210             $sti->execute;
211             if ( $sti->err ) {
212                 print "**Error : $sti->errstr \n";
213                 $sti->finish;
214             }    # if error
215         }    # if column
216     }    # foreach column
217 }    # foreach table
218
219 foreach $table ( keys %fielddefinitions ) {
220         print "Check table $table\n" if $debug;
221         $sth = $dbh->prepare("show columns from $table");
222         $sth->execute();
223         my $definitions;
224         while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
225         {
226                 $definitions->{$column}->{type}    = $type;
227                 $definitions->{$column}->{null}    = $null;
228                 $definitions->{$column}->{key}     = $key;
229                 $definitions->{$column}->{default} = $default;
230                 $definitions->{$column}->{extra}   = $extra;
231         }    # while
232         my $fieldrow = $fielddefinitions{$table};
233         foreach my $row (@$fieldrow) {
234                 my $field   = $row->{field};
235                 my $type    = $row->{type};
236                 my $null    = $row->{null};
237                 my $key     = $row->{key};
238                 my $default = $row->{default};
239                 $default="''" unless $default;
240                 my $extra   = $row->{extra};
241                 my $def     = $definitions->{$field};
242                 unless ( $type eq $def->{type}
243                         && $null eq $def->{null}
244                         && $key eq $def->{key}
245                         && $default eq $def->{default}
246                         && $extra eq $def->{extra} )
247                 {
248
249                         if ( $null eq '' ) {
250                                 $null = 'NOT NULL';
251                         }
252                         if ( $key eq 'PRI' ) {
253                                 $key = 'PRIMARY KEY';
254                         }
255                         unless ( $extra eq 'auto_increment' ) {
256                                 $extra = '';
257                         }
258                         # if it's a new column use "add", if it's an old one, use "change".
259                         my $action;
260                         if ($definitions->{$field}->{type}) {
261                                 $action="change $field"
262                         } else {
263                                 $action="add";
264                         }
265 # if it's a primary key, drop the previous pk, before altering the table
266                         my $sth;
267                         if ($key ne 'PRIMARY KEY') {
268                                 $sth =$dbh->prepare("alter table $table $action $field $type $null $key $extra default ?");
269                         } else {
270                                 $sth =$dbh->prepare("alter table $table drop primary key, $action $field $type $null $key $extra default ?");
271                         }
272                         $sth->execute($default);
273                         print "  Alter $field in $table\n" unless $silent;
274                 }
275         }
276 }
277
278
279 # Populate tables with required data
280 foreach my $table ( keys %tabledata ) {
281     print "Checking for data required in table $table...\n" unless $silent;
282     my $tablerows = $tabledata{$table};
283     foreach my $row (@$tablerows) {
284         my $uniquefieldrequired = $row->{uniquefieldrequired};
285         my $uniquevalue         = $row->{$uniquefieldrequired};
286         my $forceupdate         = $row->{forceupdate};
287         my $sth                 =
288           $dbh->prepare(
289 "select $uniquefieldrequired from $table where $uniquefieldrequired=?"
290         );
291         $sth->execute($uniquevalue);
292         if ($sth->rows) {
293             foreach my $field (keys %$forceupdate) {
294                 if ($forceupdate->{$field}) {
295                     my $sth=$dbh->prepare("update systempreferences set $field=? where $uniquefieldrequired=?");
296                     $sth->execute($row->{$field}, $uniquevalue);
297                 }
298             }
299         } else {
300             print "Adding row to $table: " unless $silent;
301             my @values;
302             my $fieldlist;
303             my $placeholders;
304             foreach my $field ( keys %$row ) {
305                 next if $field eq 'uniquefieldrequired';
306                 next if $field eq 'forceupdate';
307                 my $value = $row->{$field};
308                 push @values, $value;
309                 print "  $field => $value" unless $silent;
310                 $fieldlist .= "$field,";
311                 $placeholders .= "?,";
312             }
313             print "\n" unless $silent;
314             $fieldlist    =~ s/,$//;
315             $placeholders =~ s/,$//;
316             my $sth =
317               $dbh->prepare(
318                 "insert into $table ($fieldlist) values ($placeholders)");
319             $sth->execute(@values);
320         }
321     }
322 }
323
324 # at last, remove useless fields
325 foreach $table ( keys %uselessfields ) {
326         my @fields = split /,/,$uselessfields{$table};
327         my $fields;
328         my $exists;
329         foreach my $fieldtodrop (@fields) {
330                 $fieldtodrop =~ s/\t//g;
331                 $fieldtodrop =~ s/\n//g;
332                 $exists =0;
333                 $sth = $dbh->prepare("show columns from $table");
334                 $sth->execute;
335                 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
336                 {
337                         $exists =1 if ($column eq $fieldtodrop);
338                 }
339                 if ($exists) {
340                         print "deleting $fieldtodrop field in $table...\n" unless $silent;
341                         my $sth = $dbh->prepare("alter table $table drop $fieldtodrop");
342                         $sth->execute;
343                 }
344         }
345 }    # foreach
346
347
348 $sth->finish;
349
350 exit;
351
352 # $Log$
353 # Revision 1.113  2005/07/28 08:38:41  tipaul
354 # For instance, the return date does not rely on the borrower expiration date. A systempref will be added in Koha, to modify return date calculation schema :
355 # * ReturnBeforeExpiry = yes => return date can't be after expiry date
356 # * ReturnBeforeExpiry = no  => return date can be after expiry date
357 #
358 # Revision 1.112  2005/07/26 08:19:47  hdl
359 # Adding IndependantBranches System preference variable in order to manage Branch independancy.
360 #
361 # Revision 1.111  2005/07/25 15:35:38  tipaul
362 # we have decided that moving to Koha 3.0 requires being already in Koha 2.2.x
363 # So, the updatedatabase script can highly be cleaned (90% removed).
364 # Let's play with the new Koha DB structure now ;-)
365 #
366 #!/usr/bin/perl
367
368 # $Id$
369
370 # Database Updater
371 # This script checks for required updates to the database.
372
373 # Part of the Koha Library Software www.koha.org
374 # Licensed under the GPL.
375
376 # Bugs/ToDo:
377 # - Would also be a good idea to offer to do a backup at this time...
378
379 # NOTE:  If you do something more than once in here, make it table driven.
380 use strict;
381
382 # CPAN modules
383 use DBI;
384 use Getopt::Long;
385 # Koha modules
386 use C4::Context;
387
388 # FIXME - The user might be installing a new database, so can't rely
389 # on /etc/koha.conf anyway.
390
391 my $debug = 0;
392
393 my (
394     $sth, $sti,
395     $query,
396     %existingtables,    # tables already in database
397     %types,
398     $table,
399     $column,
400     $type, $null, $key, $default, $extra,
401     $prefitem,          # preference item in systempreferences table
402 );
403
404 my $silent;
405 GetOptions(
406         's' =>\$silent
407         );
408 my $dbh = C4::Context->dbh;
409 print "connected to your DB. Checking & modifying it\n" unless $silent;
410
411 #-------------------
412 # Defines
413
414 # Tables to add if they don't exist
415 my %requiretables = (
416     categorytable       => "(categorycode char(5) NOT NULL default '',
417                              description text default '',
418                              itemtypecodes text default '',
419                              PRIMARY KEY (categorycode)
420                             )",
421     subcategorytable       => "(subcategorycode char(5) NOT NULL default '',
422                              description text default '',
423                              itemtypecodes text default '',
424                              PRIMARY KEY (subcategorycode)
425                             )",
426     mediatypetable       => "(mediatypecode char(5) NOT NULL default '',
427                              description text default '',
428                              itemtypecodes text default '',
429                              PRIMARY KEY (mediatypecode)
430                             )",
431     action_logs         => "(
432                                     `timestamp` TIMESTAMP NOT NULL ,
433                                     `user` INT( 11 ) NOT NULL ,
434                                     `module` TEXT default '',
435                                     `action` TEXT default '' ,
436                                     `object` INT(11) default '' ,
437                                     `info` TEXT default '' ,
438                                     PRIMARY KEY ( `timestamp` , `user` )
439                             )",
440 );
441
442 my %requirefields = (
443 #    tablename        => { 'field' => 'fieldtype' },
444 );
445
446 my %dropable_table = (
447 # tablename => 'tablename',
448 );
449
450 my %uselessfields = (
451 # tablename => "field1,field2",
452         );
453 # the other hash contains other actions that can't be done elsewhere. they are done
454 # either BEFORE of AFTER everything else, depending on "when" entry (default => AFTER)
455
456 # The tabledata hash contains data that should be in the tables.
457 # The uniquefieldrequired hash entry is used to determine which (if any) fields
458 # must not exist in the table for this row to be inserted.  If the
459 # uniquefieldrequired entry is already in the table, the existing data is not
460 # modified, unless the forceupdate hash entry is also set.  Fields in the
461 # anonymous "forceupdate" hash will be forced to be updated to the default
462 # values given in the %tabledata hash.
463
464 my %tabledata = (
465 # tablename => [
466 #       {       uniquefielrequired => 'fieldname', # the primary key in the table
467 #               fieldname => fieldvalue,
468 #               fieldname2 => fieldvalue2,
469 #       },
470 # ],
471     systempreferences => [
472                 {
473             uniquefieldrequired => 'variable',
474             variable            => 'Activate_Log',
475             value               => 'On',
476             forceupdate         => { 'explanation' => 1,
477                                      'type' => 1},
478             explanation         => 'Turn Log Actions on DB On an Off',
479             type                => 'YesNo',
480         },
481         {
482             uniquefieldrequired => 'variable',
483             variable            => 'IndependantBranches',
484             value               => 0,
485             forceupdate         => { 'explanation' => 1,
486                                      'type' => 1},
487             explanation         => 'Turn Branch independancy management On an Off',
488             type                => 'YesNo',
489         },
490
491     ],
492
493 );
494
495 my %fielddefinitions = (
496 # fieldname => [
497 #       {                 field => 'fieldname',
498 #             type    => 'fieldtype',
499 #             null    => '',
500 #             key     => '',
501 #             default => ''
502 #         },
503 #     ],
504 );
505
506 #-------------------
507 # Initialize
508
509 # Start checking
510
511 # Get version of MySQL database engine.
512 my $mysqlversion = `mysqld --version`;
513 $mysqlversion =~ /Ver (\S*) /;
514 $mysqlversion = $1;
515 if ( $mysqlversion ge '3.23' ) {
516     print "Could convert to MyISAM database tables...\n" unless $silent;
517 }
518
519 #---------------------------------
520 # Tables
521
522 # Collect all tables into a list
523 $sth = $dbh->prepare("show tables");
524 $sth->execute;
525 while ( my ($table) = $sth->fetchrow ) {
526     $existingtables{$table} = 1;
527 }
528
529
530 # Now add any missing tables
531 foreach $table ( keys %requiretables ) {
532     unless ( $existingtables{$table} ) {
533         print "Adding $table table...\n" unless $silent;
534         my $sth = $dbh->prepare("create table $table $requiretables{$table}");
535         $sth->execute;
536         if ( $sth->err ) {
537             print "Error : $sth->errstr \n";
538             $sth->finish;
539         }    # if error
540     }    # unless exists
541 }    # foreach
542
543 # now drop useless tables
544 foreach $table ( keys %dropable_table ) {
545         if ( $existingtables{$table} ) {
546                 print "Dropping unused table $table\n" if $debug and not $silent;
547                 $dbh->do("drop table $table");
548                 if ( $dbh->err ) {
549                         print "Error : $dbh->errstr \n";
550                 }
551         }
552 }
553
554 #---------------------------------
555 # Columns
556
557 foreach $table ( keys %requirefields ) {
558     print "Check table $table\n" if $debug and not $silent;
559     $sth = $dbh->prepare("show columns from $table");
560     $sth->execute();
561     undef %types;
562     while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
563     {
564         $types{$column} = $type;
565     }    # while
566     foreach $column ( keys %{ $requirefields{$table} } ) {
567         print "  Check column $column  [$types{$column}]\n" if $debug and not $silent;
568         if ( !$types{$column} ) {
569
570             # column doesn't exist
571             print "Adding $column field to $table table...\n" unless $silent;
572             $query = "alter table $table
573                         add column $column " . $requirefields{$table}->{$column};
574             print "Execute: $query\n" if $debug;
575             my $sti = $dbh->prepare($query);
576             $sti->execute;
577             if ( $sti->err ) {
578                 print "**Error : $sti->errstr \n";
579                 $sti->finish;
580             }    # if error
581         }    # if column
582     }    # foreach column
583 }    # foreach table
584
585 foreach $table ( keys %fielddefinitions ) {
586         print "Check table $table\n" if $debug;
587         $sth = $dbh->prepare("show columns from $table");
588         $sth->execute();
589         my $definitions;
590         while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
591         {
592                 $definitions->{$column}->{type}    = $type;
593                 $definitions->{$column}->{null}    = $null;
594                 $definitions->{$column}->{key}     = $key;
595                 $definitions->{$column}->{default} = $default;
596                 $definitions->{$column}->{extra}   = $extra;
597         }    # while
598         my $fieldrow = $fielddefinitions{$table};
599         foreach my $row (@$fieldrow) {
600                 my $field   = $row->{field};
601                 my $type    = $row->{type};
602                 my $null    = $row->{null};
603                 my $key     = $row->{key};
604                 my $default = $row->{default};
605                 $default="''" unless $default;
606                 my $extra   = $row->{extra};
607                 my $def     = $definitions->{$field};
608                 unless ( $type eq $def->{type}
609                         && $null eq $def->{null}
610                         && $key eq $def->{key}
611                         && $default eq $def->{default}
612                         && $extra eq $def->{extra} )
613                 {
614
615                         if ( $null eq '' ) {
616                                 $null = 'NOT NULL';
617                         }
618                         if ( $key eq 'PRI' ) {
619                                 $key = 'PRIMARY KEY';
620                         }
621                         unless ( $extra eq 'auto_increment' ) {
622                                 $extra = '';
623                         }
624                         # if it's a new column use "add", if it's an old one, use "change".
625                         my $action;
626                         if ($definitions->{$field}->{type}) {
627                                 $action="change $field"
628                         } else {
629                                 $action="add";
630                         }
631 # if it's a primary key, drop the previous pk, before altering the table
632                         my $sth;
633                         if ($key ne 'PRIMARY KEY') {
634                                 $sth =$dbh->prepare("alter table $table $action $field $type $null $key $extra default ?");
635                         } else {
636                                 $sth =$dbh->prepare("alter table $table drop primary key, $action $field $type $null $key $extra default ?");
637                         }
638                         $sth->execute($default);
639                         print "  Alter $field in $table\n" unless $silent;
640                 }
641         }
642 }
643
644
645 # Populate tables with required data
646 foreach my $table ( keys %tabledata ) {
647     print "Checking for data required in table $table...\n" unless $silent;
648     my $tablerows = $tabledata{$table};
649     foreach my $row (@$tablerows) {
650         my $uniquefieldrequired = $row->{uniquefieldrequired};
651         my $uniquevalue         = $row->{$uniquefieldrequired};
652         my $forceupdate         = $row->{forceupdate};
653         my $sth                 =
654           $dbh->prepare(
655 "select $uniquefieldrequired from $table where $uniquefieldrequired=?"
656         );
657         $sth->execute($uniquevalue);
658         if ($sth->rows) {
659             foreach my $field (keys %$forceupdate) {
660                 if ($forceupdate->{$field}) {
661                     my $sth=$dbh->prepare("update systempreferences set $field=? where $uniquefieldrequired=?");
662                     $sth->execute($row->{$field}, $uniquevalue);
663                 }
664             }
665         } else {
666             print "Adding row to $table: " unless $silent;
667             my @values;
668             my $fieldlist;
669             my $placeholders;
670             foreach my $field ( keys %$row ) {
671                 next if $field eq 'uniquefieldrequired';
672                 next if $field eq 'forceupdate';
673                 my $value = $row->{$field};
674                 push @values, $value;
675                 print "  $field => $value" unless $silent;
676                 $fieldlist .= "$field,";
677                 $placeholders .= "?,";
678             }
679             print "\n" unless $silent;
680             $fieldlist    =~ s/,$//;
681             $placeholders =~ s/,$//;
682             my $sth =
683               $dbh->prepare(
684                 "insert into $table ($fieldlist) values ($placeholders)");
685             $sth->execute(@values);
686         }
687     }
688 }
689
690 # at last, remove useless fields
691 foreach $table ( keys %uselessfields ) {
692         my @fields = split /,/,$uselessfields{$table};
693         my $fields;
694         my $exists;
695         foreach my $fieldtodrop (@fields) {
696                 $fieldtodrop =~ s/\t//g;
697                 $fieldtodrop =~ s/\n//g;
698                 $exists =0;
699                 $sth = $dbh->prepare("show columns from $table");
700                 $sth->execute;
701                 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
702                 {
703                         $exists =1 if ($column eq $fieldtodrop);
704                 }
705                 if ($exists) {
706                         print "deleting $fieldtodrop field in $table...\n" unless $silent;
707                         my $sth = $dbh->prepare("alter table $table drop $fieldtodrop");
708                         $sth->execute;
709                 }
710         }
711 }    # foreach
712
713
714 $sth->finish;
715
716 exit;
717
718 # $Log$
719 # Revision 1.113  2005/07/28 08:38:41  tipaul
720 # For instance, the return date does not rely on the borrower expiration date. A systempref will be added in Koha, to modify return date calculation schema :
721 # * ReturnBeforeExpiry = yes => return date can't be after expiry date
722 # * ReturnBeforeExpiry = no  => return date can be after expiry date
723 #
724 # Revision 1.112  2005/07/26 08:19:47  hdl
725 # Adding IndependantBranches System preference variable in order to manage Branch independancy.
726 #
727 # Revision 1.111  2005/07/25 15:35:38  tipaul
728 # we have decided that moving to Koha 3.0 requires being already in Koha 2.2.x
729 # So, the updatedatabase script can highly be cleaned (90% removed).
730 # Let's play with the new Koha DB structure now ;-)
731 #