Merged some features over from rel-1-2, including primary key checking.
[koha.git] / updater / updatedatabase
1 #!/usr/bin/perl
2
3 # $Id$
4
5 # Database Updater
6 # This script checks for required updates to the database.
7
8 # Part of the Koha Library Software www.koha.org
9 # Licensed under the GPL.
10
11 # Bugs/ToDo:
12 # - Would also be a good idea to offer to do a backup at this time...
13
14 # NOTE:  If you do something more than once in here, make it table driven.
15
16 use strict;
17
18 # CPAN modules
19 use DBI;
20
21 # Koha modules
22 use C4::Context;
23         # FIXME - /etc/koha.conf might not exist, so shouldn't use
24         # C4::Context.
25
26 # FIXME - The user might be installing a new database, so can't rely
27 # on /etc/koha.conf anyway.
28
29 my $debug=0;
30
31 my (
32         $sth, $sti,
33         $query,
34         %existingtables,        # tables already in database
35         %types,
36         $table,
37         $column,
38         $type, $null, $key, $default, $extra,
39         $prefitem,              # preference item in systempreferences table
40 );
41
42 my $dbh = C4::Context->dbh;
43
44 #-------------------
45 # Defines
46
47 # Tables to add if they don't exist
48 my %requiretables=(
49     shelfcontents=>"( shelfnumber int not null,
50                                                         itemnumber int not null,
51                                                         flags int)",
52     bookshelf=>"( shelfnumber int auto_increment primary key,
53                                                 shelfname char(255))",
54     z3950queue=>"( id int auto_increment primary key,
55                                                 term text,
56                                                 type char(10),
57                                                 startdate int,
58                                                 enddate int,
59                                                 done smallint,
60                                                 results longblob,
61                                                 numrecords int,
62                                                 servers text,
63                                                 identifier char(30))",
64         z3950results=>"( id int auto_increment primary key,
65                                                 queryid int,
66                                                 server char(255),
67                                                 startdate int,
68                                                 enddate int,
69                                                 results longblob,
70                                                 numrecords int,
71                                                 numdownloaded int,
72                                                 highestseen int,
73                                                 active smallint)",
74         branchrelations=>"( branchcode varchar(4),
75                                                         categorycode varchar(4))",
76         websites=>"( websitenumber int(11) NOT NULL auto_increment,
77                                                 biblionumber int(11) NOT NULL default '0',
78                                                 title text,
79                                                 description text,
80                                                 url varchar(255),
81                                                 PRIMARY KEY (websitenumber) )",
82         marcrecorddone=>"( isbn char(40),
83                                                                 issn char(40),
84                                                                 lccn char(40),
85                                                                 controlnumber char(40))",
86     uploadedmarc=>"( id int(11) NOT NULL auto_increment PRIMARY KEY,
87                                                         marc longblob,
88                                                         hidden smallint(6) default NULL,
89                                                         name varchar(255) default NULL)",
90         ethnicity=>"( code varchar(10) NOT NULL default '',
91                                         name varchar(255) default NULL,
92                                         PRIMARY KEY  (code)   )",
93         sessions=>"( sessionID varchar(255) NOT NULL default '',
94                                                 userid varchar(255) default NULL,
95                                                 ip varchar(16) default NULL,
96                                                 lasttime int,
97                                                 PRIMARY KEY (sessionID)   )",
98     sessionqueries=>"( sessionID varchar(255) NOT NULL default '',
99                                                                 userid char(100) NOT NULL default '',
100                                                                 ip char(18) NOT NULL default '',
101                                                                 url text NOT NULL default ''  )",
102         bibliothesaurus=> "( CREATE TABLE bibliothesaurus (
103                                                         id bigint(20) NOT NULL auto_increment,
104                                                         freelib char(255) NOT NULL default '',
105                                                         stdlib char(255) NOT NULL default '',
106                                                         category char(10) NOT NULL default '',
107                                                         level tinyint(4) NOT NULL default '1',
108                                                         hierarchy char(80) NOT NULL default '',
109                                                         PRIMARY KEY  (id),
110                                                         KEY freelib (freelib),
111                                                         KEY stdlib (stdlib),
112                                                         KEY category (category),
113                                                         KEY hierarchy (hierarchy)
114                                                         )",
115         marc_biblio => "(
116                                                 bibid bigint(20) unsigned NOT NULL auto_increment,
117                                                 biblionumber int(11) NOT NULL default '0',
118                                                 datecreated date NOT NULL default '0000-00-00',
119                                                 datemodified date default NULL,
120                                                 origincode char(20) default NULL,
121                                                 PRIMARY KEY  (bibid),
122                                                 KEY origincode (origincode),
123                                                 KEY biblionumber (biblionumber)
124                                                 ) ",
125         marc_blob_subfield => "(
126                                         blobidlink bigint(20) NOT NULL auto_increment,
127                                         subfieldvalue longtext NOT NULL,
128                                         PRIMARY KEY  (blobidlink)
129                                         ) ",
130         marc_subfield_structure => "(
131                                                 tagfield char(3) NOT NULL default '',
132                                                 tagsubfield char(1) NOT NULL default '',
133                                                 liblibrarian char(255) NOT NULL default '',
134                                                 libopac char(255) NOT NULL default '',
135                                                 repeatable tinyint(4) NOT NULL default '0',
136                                                 mandatory tinyint(4) NOT NULL default '0',
137                                                 kohafield char(40) NOT NULL default '',
138                                                 tab tinyint(1),
139                                                 authorised_value char(10) default NULL,
140                                                 thesaurus_category char(10) default NULL,
141                                                 value_builder char(80) NOT NULL default '',
142                                                 PRIMARY KEY  (tagfield,tagsubfield),
143                                                 KEY kohafield (kohafield),
144                                                 KEY tab (tab)
145                                                 )",
146         marc_subfield_table => "(
147                                                 subfieldid bigint(20) unsigned NOT NULL auto_increment,
148                                                 bibid bigint(20) unsigned NOT NULL default '0',
149                                                 tag char(3) NOT NULL default '',
150                                                 tagorder tinyint(4) NOT NULL default '1',
151                                                 tag_indicator char(2) NOT NULL default '',
152                                                 subfieldcode char(1) NOT NULL default '',
153                                                 subfieldorder tinyint(4) NOT NULL default '1',
154                                                 subfieldvalue varchar(255) default NULL,
155                                                 valuebloblink bigint(20) default NULL,
156                                                 PRIMARY KEY  (subfieldid),
157                                                 KEY bibid (bibid),
158                                                 KEY tag (tag),
159                                                 KEY tag_indicator (tag_indicator),
160                                                 KEY subfieldorder (subfieldorder),
161                                                 KEY subfieldcode (subfieldcode),
162                                                 KEY subfieldvalue (subfieldvalue),
163                                                 KEY tagorder (tagorder)
164                                         )",
165         marc_tag_structure => "(
166                                         tagfield char(3) NOT NULL default '',
167                                         liblibrarian char(255) NOT NULL default '',
168                                         libopac char(255) NOT NULL default '',
169                                         repeatable tinyint(4) NOT NULL default '0',
170                                         mandatory tinyint(4) NOT NULL default '0',
171                                         PRIMARY KEY  (tagfield)
172                                         )",
173         marc_word => "(
174                                 bibid bigint(20) NOT NULL default '0',
175                                 tag char(3) NOT NULL default '',
176                                 tagorder tinyint(4) NOT NULL default '1',
177                                 subfieldid char(1) NOT NULL default '',
178                                 subfieldorder tinyint(4) NOT NULL default '1',
179                                 word varchar(255) NOT NULL default '',
180                                 sndx_word varchar(255) NOT NULL default '',
181                                 KEY bibid (bibid),
182                                 KEY tag (tag),
183                                 KEY tagorder (tagorder),
184                                 KEY subfieldid (subfieldid),
185                                 KEY subfieldorder (subfieldorder),
186                                 KEY word (word),
187                                 KEY sndx_word (sndx_word)
188                         )",
189         marc_breeding =>"( file varchar(80) NOT NULL default '',
190                                                                 isbn varchar(10) NOT NULL default '',
191                                                                 marc text NOT NULL,
192                                                                 PRIMARY KEY  (isbn)
193                                                                 )",
194         authorised_values => "(id int(11) NOT NULL auto_increment,
195                                                                         category char(10) NOT NULL default '',
196                                                                         authorised_value char(80) NOT NULL default '',
197                                                                         PRIMARY KEY  (id),
198                                                                         KEY name (category)
199                                                                 )",
200         );
201
202
203 my %requirefields=(
204         biblio=>{ 'abstract' => 'text' },
205         deletedbiblio=>{ 'abstract' => 'text' },
206         biblioitems=>{ 'lccn' => 'char(25)',
207                                                 'url' => 'varchar(255)',
208                                                 'marc' => 'text' },
209         deletedbiblioitems=>{ 'lccn' => 'char(25)',
210                                                                 'url' => 'varchar(255)',
211                                                                 'marc' => 'text' },
212         branchtransfers=>{ 'datearrived' => 'datetime' },
213         statistics=>{'borrowernumber' =>'int(11)'},
214         aqbooksellers=>{'invoicedisc' =>'float(6,4)',
215                                                 'nocalc' => 'int(11)'},
216         borrowers=>{'userid' => 'char(30)',
217                                         'password' => 'char(30)',},
218         aqorders=>{'budgetdate' => 'date'},
219         #added so that reference items are not available for reserves...
220         itemtypes=>{'notforloan' => 'smallint(6)'},
221         systempreferences =>{'explanation' => 'char(80)'},
222 );
223
224 my %dropable_table=(
225                     classification   =>'classification',
226                     multipart        =>'multipart',
227                     multivolume      =>'multivolume',
228                     newitems         =>'newitems',
229                     procedures       =>'procedures',
230                     publisher        =>'publisher',
231                     searchstats      =>'searchstats',
232                     serialissues     =>'serialissues',
233                     );
234
235
236 # The tabledata hash contains data that should be in the tables.
237 # The uniquefieldrequired hash entry is used to determine which (if any) fields
238 # must not exist in the table for this row to be inserted.  If the
239 # uniquefieldrequired entry is already in the table, the existing data is not
240 # modified.
241
242 my %tabledata=(
243     userflags => [ 
244         { uniquefieldrequired => 'bit', bit => 0, flag => 'superlibrarian', flagdesc => 'Access to all librarian functions', defaulton => 0 },
245         { uniquefieldrequired => 'bit', bit => 1, flag => 'circulate', flagdesc => 'Circulate books', defaulton => 0 },
246         { uniquefieldrequired => 'bit', bit => 2, flag => 'catalogue', flagdesc => 'View Catalogue (Librarian Interface)', defaulton => 0 },
247         { uniquefieldrequired => 'bit', bit => 3, flag => 'parameters', flagdesc => 'Set Koha system paramters', defaulton => 0 },
248         { uniquefieldrequired => 'bit', bit => 4, flag => 'borrowers', flagdesc => 'Add or modify borrowers', defaulton => 0 },
249         { uniquefieldrequired => 'bit', bit => 5, flag => 'permissions', flagdesc => 'Set user permissions', defaulton => 0 },
250         { uniquefieldrequired => 'bit', bit => 6, flag => 'reserveforothers', flagdesc => 'Reserve books for patrons', defaulton => 0 },
251         { uniquefieldrequired => 'bit', bit => 7, flag => 'borrow', flagdesc => 'Borrow books', defaulton => 1 },
252         { uniquefieldrequired => 'bit', bit => 8, flag => 'reserveforself', flagdesc => 'Reserve books for self', defaulton => 0 },
253         { uniquefieldrequired => 'bit', bit => 9, flag => 'editcatalogue', flagdesc => 'Edit Catalogue (Modify bibliographic/holdings data)', defaulton => 0 },
254         { uniquefieldrequired => 'bit', bit => 10, flag => 'updatecharges', flagdesc => 'Update borrower charges', defaulton => 0 },
255     ],
256     systempreferences => [
257         { uniquefieldrequired => 'variable', variable => 'autoMemberNum', value => '1', explanation => '1 or else. If 1, Barcode is auto-calculated' },
258         { uniquefieldrequired => 'variable', variable => 'acquisitions', value => 'simple', explanation => 'normal or simple : will use acquisition system found in directory acqui.simple or acquisition' },
259         { uniquefieldrequired => 'variable', variable => 'dateformat', value => 'metric', explanation => 'metric or us' },
260         { uniquefieldrequired => 'variable', variable => 'template', value => 'metric', explanation => 'template default name' },
261         { uniquefieldrequired => 'variable', variable => 'autoBarcode', value => 'metric', explanation => '1 or else. If 1, Barcode is auto-calculated' },
262         { uniquefieldrequired => 'variable', variable => 'insecure', value => 'metric', explanation => 'if YES, no auth at all is needed. Be careful if you set this to yes !' },
263         { uniquefieldrequired => 'variable', variable => 'authoritysep', value => '--', explanation => 'the separator used in authority/thesaurus. Usually --' },
264     ],
265
266 );
267
268
269 my %fielddefinitions=(
270 printers => [
271         { field => 'printername', type => 'char(40)', null => '', key => 'PRI', default => '' },
272         ],
273 aqbookfund => [
274         { field => 'bookfundid', type => 'char(5)', null => '', key => 'PRI', default => '' },
275         ],
276 z3950servers => [
277         { field => 'id', type => 'int', null => '', key => 'PRI', default => '', extra => 'auto_increment' },
278         ],
279 );
280
281
282
283 #-------------------
284 # Initialize
285
286 # Start checking
287
288 # Get version of MySQL database engine.
289 my $mysqlversion=`mysqld --version`;
290 $mysqlversion=~/Ver (\S*) /;
291 $mysqlversion=$1;
292 if ($mysqlversion ge '3.23') {
293         print "Could convert to MyISAM database tables...\n";
294 }
295
296 #---------------------------------
297 # Tables
298
299 # Collect all tables into a list
300 $sth=$dbh->prepare("show tables");
301 $sth->execute;
302 while (my ($table) = $sth->fetchrow) {
303     $existingtables{$table}=1;
304 }
305
306 # Now add any missing tables
307 foreach $table ( keys %requiretables ) {
308         print "Checking $table table...\n" if $debug;
309         unless ($existingtables{$table} ) {
310                 print "Adding $table table...\n";
311                 my $sth=$dbh->prepare(
312                         "create table $table $requiretables{$table}" );
313                 $sth->execute;
314                 if ($sth->err) {
315                                 print "Error : $sth->errstr \n";
316                                 $sth->finish;
317                 } # if error
318         } # unless exists
319 } # foreach
320
321 # now drop useless tables
322 foreach $table ( keys %dropable_table) {
323         print "Dropping unused tables...\n" if $debug;
324         if ($existingtables{$table} ) {
325                 $dbh->do("drop table $table");
326                 if ($dbh->err) {
327                 print "Error : $dbh->errstr \n";
328                 }
329         }
330 }
331 unless ($existingtables{'z3950servers'}) {
332         print "Adding z3950servers table...\n";
333         my $sti=$dbh->prepare("create table z3950servers (
334                                                                                 host char(255),
335                                                                                 port int,
336                                                                                 db char(255),
337                                                                                 userid char(255),
338                                                                                 password char(255),
339                                                                                 name text,
340                                                                                 id int,
341                                                                                 checked smallint,
342                                                                                 rank int)");
343         $sti->execute;
344         $sti=$dbh->prepare("insert into z3950servers
345                                                                 values ('z3950.loc.gov',
346                                                                 7090,
347                                                                 'voyager',
348                                                                 '', '',
349                                                                 'Library of Congress',
350                                                                 1, 1, 1)");
351         $sti->execute;
352 }
353
354 #---------------------------------
355 # Columns
356
357 foreach $table ( keys %requirefields ) {
358         print "Check table $table\n" if $debug;
359         $sth=$dbh->prepare("show columns from $table");
360         $sth->execute();
361         undef %types;
362         while ( ($column, $type, $null, $key, $default, $extra)
363                         = $sth->fetchrow) {
364                 $types{$column}=$type;
365         } # while
366         foreach $column ( keys %{ $requirefields{$table} } )  {
367                 print "  Check column $column\n" if $debug;
368                 if ( ! $types{$column} ) {
369                 # column doesn't exist
370                 print "Adding $column field to $table table...\n";
371                 $query="alter table $table
372                         add column $column " . $requirefields{$table}->{$column} ;
373                 print "Execute: $query\n" if $debug;
374                 my $sti=$dbh->prepare($query);
375                 $sti->execute;
376                         if ($sti->err) {
377                                         print "**Error : $sti->errstr \n";
378                                         $sti->finish;
379                         } # if error
380                 } # if column
381         } # foreach column
382 } # foreach table
383
384 foreach $table ( keys %fielddefinitions ) {
385     print "Check table $table\n" if $debug;
386     $sth=$dbh->prepare("show columns from $table");
387     $sth->execute();
388     my $definitions;
389     while ( ($column, $type, $null, $key, $default, $extra) = $sth->fetchrow) {
390         $definitions->{$column}->{type}=$type;
391         $definitions->{$column}->{null}=$null;
392         $definitions->{$column}->{key}=$key;
393         $definitions->{$column}->{default}=$default;
394         $definitions->{$column}->{extra}=$extra;
395     } # while 
396     my $fieldrow=$fielddefinitions{$table};
397     foreach my $row ( @$fieldrow )  {
398         my $field = $row->{field};
399         my $type = $row->{type};
400         my $null = $row->{null};
401         my $key = $row->{key};
402         my $default = $row->{default};
403         my $extra = $row->{extra};
404         my $def=$definitions->{$field};
405         unless ($type eq $def->{type} && $null eq $def->{null} && $key eq $def->{key} && $default eq $def->{default} && $extra eq $def->{extra}) {
406             if ($null eq '') {
407                 $null='NOT NULL';
408             }
409             if ($key eq 'PRI') {
410                 $key ='PRIMARY KEY';
411             }
412             unless ($extra eq 'auto_increment') {
413                 $extra='';
414             }
415             my $sth=$dbh->prepare("alter table $table change $field $field $type $null $key $extra default ?");
416             $sth->execute($default);
417             print "  Alter $field in $table\n";
418         }
419     }
420 }
421
422 # Get list of columns from items table
423 my %itemtypes;
424
425 $sth=$dbh->prepare("show columns from items");
426 $sth->execute;
427 while (my ($column, $type, $null, $key, $default, $extra) = $sth->fetchrow) {
428         $itemtypes{$column}=$type;
429 }
430
431 unless ($itemtypes{'barcode'} eq 'varchar(20)') {
432         $itemtypes{'barcode'}=~/varchar\((\d+)\)/;
433         my $oldlength=$1;
434         if ($oldlength<20) {
435                 print "Setting maximum barcode length to 20 (was $oldlength).\n";
436                 my $sti=$dbh->prepare("alter table items change barcode barcode varchar(20) not null");
437                 $sti->execute;
438         }
439 }
440
441 # extending the timestamp in branchtransfers...
442 my %branchtransfers;
443
444 $sth=$dbh->prepare("show columns from branchtransfers");
445 $sth->execute;
446 while (my ($column, $type, $null, $key, $default, $extra) = $sth->fetchrow) {
447     $branchtransfers{$column}=$type;
448 }
449
450 unless ($branchtransfers{'datesent'} eq 'datetime') {
451     print "Setting type of datesent in branchtransfers to datetime.\n";
452     my $sti=$dbh->prepare("alter table branchtransfers change datesent datesent datetime");
453     $sti->execute;
454 }
455
456 unless ($branchtransfers{'datearrived'} eq 'datetime') {
457     print "Setting type of datearrived in branchtransfers to datetime.\n";
458     my $sti=$dbh->prepare("alter table branchtransfers change datearrived datearrived datetime");
459     $sti->execute;
460 }
461
462 # changing the branchcategories table around...
463 my %branchcategories;
464
465 $sth=$dbh->prepare("show columns from branchcategories");
466 $sth->execute;
467 while (my ($column, $type, $null, $key, $default, $extra) = $sth->fetchrow) {
468         $branchcategories{$column}=$type;
469 }
470
471 unless ($branchcategories{'categorycode'} eq 'varchar(4)') {
472         print "Setting type of categorycode in branchcategories to varchar(4),\n and making the primary key.\n";
473         my $sti=$dbh->prepare("alter table branchcategories change categorycode categorycode varchar(4) not null");
474         $sti->execute;
475         $sti=$dbh->prepare("alter table branchcategories add primary key (categorycode)");
476         $sti->execute;
477 }
478
479 unless ($branchcategories{'categoryname'} eq 'text') {
480         print "Changing branchcode in branchcategories to categoryname text.\n";
481         my $sth=$dbh->prepare("alter table branchcategories change branchcode categoryname text");
482         $sth->execute;
483 }
484
485 unless ($branchcategories{'codedescription'} eq 'text') {
486         print "Replacing branchholding in branchcategories with codedescription text.\n";
487         my $sth=$dbh->prepare("alter table branchcategories change branchholding codedescription text");
488         $sth->execute;
489 }
490
491
492 # Populate tables with required data
493  
494 foreach my $table (keys %tabledata) {
495     print "Checking for data required in table $table...\n";
496     my $tablerows=$tabledata{$table};
497     foreach my $row (@$tablerows) {
498         my $uniquefieldrequired=$row->{uniquefieldrequired};
499         my $uniquevalue=$row->{$uniquefieldrequired};
500         my $sth=$dbh->prepare("select $uniquefieldrequired from $table where $uniquefieldrequired=?");
501         $sth->execute($uniquevalue);
502         unless ($sth->rows) {
503             print "Adding row to $table: ";
504             my @values;
505             my $fieldlist;
506             my $placeholders;
507             foreach my $field (keys %$row) {
508                 (next) if ($field eq 'uniquefieldrequired');
509                 my $value=$row->{$field};
510                 push @values, $value;
511                 print "  $field => $value";
512                 $fieldlist.="$field,";
513                 $placeholders.="?,";
514             }
515             print "\n";
516             $fieldlist=~s/,$//;
517             $placeholders=~s/,$//;
518             my $sth=$dbh->prepare("insert into $table ($fieldlist) values ($placeholders)");
519             $sth->execute(@values);
520         }
521     }
522 }
523
524 $sth->finish;
525
526 exit;
527
528 # $Log$
529 # Revision 1.26  2002/11/12 17:42:40  tonnesen
530 # Merged some features over from rel-1-2, including primary key checking.
531 #
532 # Revision 1.25  2002/11/12 16:44:38  tipaul
533 # road to 1.3.2 :
534 # * many bugfixes
535 # * adding value_builder : you can map a subfield in the marc_subfield_structure to a sub stored in "value_builder" directory. In this directory you can create screen used to build values with any method. In this commit is a 1st draft of the builder for 100$a unimarc french subfield, which is composed of 35 digits, with 12 differents values (only the 4th first are provided for instance)
536 #
537 # Revision 1.24  2002/10/30 14:00:23  arensb
538 # (bug fix): Fixed typo.
539 #
540 # Revision 1.23  2002/10/25 10:55:46  tipaul
541 # Road to 1.3.2
542 # * bugfixes and improvements
543 # * manage mandatory MARC subfields
544 # * new table : authorised_values. this table contains categories and authorised values for the category. On MARC management, you can map a subfield to a authorised_values category. If you do this, the subfield can only be filled with a authorised_value of the selected category.
545 # this submit contains everything needed :
546 # * updatedatabase
547 # * admin screens
548 # * "links" management
549 # * creation of a html-list if a subfield is mapped to an authorised value.
550 #
551 # Note this is different from authorities support, which will come soon.
552 # The authorised_values is supposed to contains a "small" number of authorised values for a category (less than 50-100). If you enter more authorised values than this, it should be hard to find what you want in a BIG list...
553 #
554 # Revision 1.22  2002/10/15 10:08:19  tipaul
555 # fixme corrected, re-indent and adding the marc_breeding table (see commit of marcimport.pl for more explanations about breeding)
556 #
557 # Revision 1.21  2002/10/14 11:48:59  tipaul
558 # bugfix
559 #
560 # Revision 1.20  2002/10/10 04:49:41  arensb
561 # Added some FIXME comments.
562 #
563 # Revision 1.19  2002/10/05 10:17:17  arensb
564 # Merged with arensb-context branch: use C4::Context->dbh instead of
565 # &C4Connect, and generally prefer C4::Context over C4::Database.
566 #
567 # Revision 1.18.2.2  2002/10/05 06:18:43  arensb
568 # Added a whole mess of FIXME comments.
569 #
570 # Revision 1.18.2.1  2002/10/04 02:46:00  arensb
571 # Use C4::Connect instead of C4::Database, C4::Connect->dbh instead
572 # C4Connect.
573 #
574 # Revision 1.18  2002/09/24 13:50:55  tipaul
575 # long WAS the road to 1.3.0...
576 # coming VERY SOON NOW...
577 # modifying installer and buildrelease to update the DB
578 #
579 # Revision 1.17  2002/09/24 12:57:35  tipaul
580 # long WAS the road to 1.3.0...
581 # coming VERY SOON NOW...
582 # modifying installer and buildrelease to update the DB
583 #
584 # Revision 1.16  2002/07/31 02:34:27  finlayt
585 #
586 # added "notforloan" field to the itemtypes table.
587 #
588 # Revision 1.15  2002/07/20 22:30:06  rangi
589 # Making sure fix makes it into the main branch as well
590 # Fix for bug 69
591 #
592 # Revision 1.14  2002/07/08 16:20:26  tonnesen
593 # Added sessionqueries table and password/userid fields to borrowers table
594 #
595 # Revision 1.13  2002/07/04 18:05:36  tonnesen
596 # bug fix
597 #
598 # Revision 1.12  2002/07/04 16:41:06  tonnesen
599 # Merged changes from rel-1-2.  Abstracted table structure changes by alan.
600 #