6 # This script checks for required updates to the database.
8 # Part of the Koha Library Software www.koha.org
9 # Licensed under the GPL.
12 # - Would also be a good idea to offer to do a backup at this time...
14 # NOTE: If you do something more than once in here, make it table driven.
24 # FIXME - The user might be installing a new database, so can't rely
25 # on /etc/koha.conf anyway.
32 %existingtables, # tables already in database
36 $type, $null, $key, $default, $extra,
37 $prefitem, # preference item in systempreferences table
44 my $dbh = C4::Context->dbh;
45 print "connected to your DB. Checking & modifying it\n" unless $silent;
50 # Tables to add if they don't exist
52 shelfcontents => "( shelfnumber int not null,
53 itemnumber int not null,
55 bookshelf => "( shelfnumber int auto_increment primary key,
56 shelfname char(255))",
57 z3950queue => "( id int auto_increment primary key,
66 identifier char(30))",
67 z3950results => "( id int auto_increment primary key,
77 branchrelations => "( branchcode varchar(4),
78 categorycode varchar(4))",
79 websites => "( websitenumber int(11) NOT NULL auto_increment,
80 biblionumber int(11) NOT NULL default '0',
84 PRIMARY KEY (websitenumber) )",
85 marcrecorddone => "( isbn char(40),
88 controlnumber char(40))",
89 uploadedmarc => "( id int(11) NOT NULL auto_increment PRIMARY KEY,
91 hidden smallint(6) default NULL,
92 name varchar(255) default NULL)",
93 ethnicity => "( code varchar(10) NOT NULL default '',
94 name varchar(255) default NULL,
95 PRIMARY KEY (code) )",
96 sessions => "( sessionID varchar(255) NOT NULL default '',
97 userid varchar(255) default NULL,
98 ip varchar(16) default NULL,
100 PRIMARY KEY (sessionID) )",
101 sessionqueries => "( sessionID varchar(255) NOT NULL default '',
102 userid char(100) NOT NULL default '',
103 ip char(18) NOT NULL default '',
104 url text NOT NULL default '' )",
105 bibliothesaurus => "( id bigint(20) NOT NULL auto_increment,
106 freelib char(255) NOT NULL default '',
107 stdlib char(255) NOT NULL default '',
108 category char(10) NOT NULL default '',
109 level tinyint(4) NOT NULL default '1',
110 hierarchy char(80) NOT NULL default '',
111 father char(80) NOT NULL default '',
113 KEY freelib (freelib),
115 KEY category (category),
116 KEY hierarchy (hierarchy)
119 bibid bigint(20) unsigned NOT NULL auto_increment,
120 biblionumber int(11) NOT NULL default '0',
121 datecreated date NOT NULL default '0000-00-00',
122 datemodified date default NULL,
123 origincode char(20) default NULL,
125 KEY origincode (origincode),
126 KEY biblionumber (biblionumber)
128 marc_blob_subfield => "(
129 blobidlink bigint(20) NOT NULL auto_increment,
130 subfieldvalue longtext NOT NULL,
131 PRIMARY KEY (blobidlink)
133 marc_subfield_structure => "(
134 tagfield char(3) NOT NULL default '',
135 tagsubfield char(1) NOT NULL default '',
136 liblibrarian char(255) NOT NULL default '',
137 libopac char(255) NOT NULL default '',
138 repeatable tinyint(4) NOT NULL default '0',
139 mandatory tinyint(4) NOT NULL default '0',
140 kohafield char(40) default NULL,
141 tab tinyint(1) default NULL,
142 authorised_value char(10) default NULL,
143 thesaurus_category char(10) default NULL,
144 value_builder char(80) default NULL,
145 PRIMARY KEY (tagfield,tagsubfield),
146 KEY kohafield (kohafield),
149 marc_subfield_table => "(
150 subfieldid bigint(20) unsigned NOT NULL auto_increment,
151 bibid bigint(20) unsigned NOT NULL default '0',
152 tag char(3) NOT NULL default '',
153 tagorder tinyint(4) NOT NULL default '1',
154 tag_indicator char(2) NOT NULL default '',
155 subfieldcode char(1) NOT NULL default '',
156 subfieldorder tinyint(4) NOT NULL default '1',
157 subfieldvalue varchar(255) default NULL,
158 valuebloblink bigint(20) default NULL,
159 PRIMARY KEY (subfieldid),
162 KEY tag_indicator (tag_indicator),
163 KEY subfieldorder (subfieldorder),
164 KEY subfieldcode (subfieldcode),
165 KEY subfieldvalue (subfieldvalue),
166 KEY tagorder (tagorder)
168 marc_tag_structure => "(
169 tagfield char(3) NOT NULL default '',
170 liblibrarian char(255) NOT NULL default '',
171 libopac char(255) NOT NULL default '',
172 repeatable tinyint(4) NOT NULL default '0',
173 mandatory tinyint(4) NOT NULL default '0',
174 authorised_value char(10) default NULL,
175 PRIMARY KEY (tagfield)
178 bibid bigint(20) NOT NULL default '0',
179 tag char(3) NOT NULL default '',
180 tagorder tinyint(4) NOT NULL default '1',
181 subfieldid char(1) NOT NULL default '',
182 subfieldorder tinyint(4) NOT NULL default '1',
183 word varchar(255) NOT NULL default '',
184 sndx_word varchar(255) NOT NULL default '',
187 KEY tagorder (tagorder),
188 KEY subfieldid (subfieldid),
189 KEY subfieldorder (subfieldorder),
191 KEY sndx_word (sndx_word)
193 marc_breeding => "( id bigint(20) NOT NULL auto_increment,
194 file varchar(80) NOT NULL default '',
195 isbn varchar(10) NOT NULL default '',
196 title varchar(128) default NULL,
197 author varchar(80) default NULL,
199 encoding varchar(40) default NULL,
204 authorised_values => "(id int(11) NOT NULL auto_increment,
205 category char(10) NOT NULL default '',
206 authorised_value char(80) NOT NULL default '',
211 userflags => "( bit int(11) NOT NULL default '0',
212 flag char(30), flagdesc char(255),
216 authtypecode char(10) not NULL,
217 authtypetext char(255) not NULL,
218 auth_tag_to_report char(3) not NULL,
219 summary text not NULL,
220 PRIMARY KEY (authtypecode)
222 biblio_framework => "(
223 frameworkcode char(4) not NULL,
224 frameworktext char(255) not NULL,
225 PRIMARY KEY (frameworkcode)
227 auth_subfield_structure => "(
228 authtypecode char(10) NOT NULL default '',
229 tagfield char(3) NOT NULL default '',
230 tagsubfield char(1) NOT NULL default '',
231 liblibrarian char(255) NOT NULL default '',
232 libopac char(255) NOT NULL default '',
233 repeatable tinyint(4) NOT NULL default '0',
234 mandatory tinyint(4) NOT NULL default '0',
235 tab tinyint(1) default NULL,
236 authorised_value char(10) default NULL,
237 value_builder char(80) default NULL,
238 seealso char(255) default NULL,
239 PRIMARY KEY (authtypecode,tagfield,tagsubfield),
240 KEY tab (authtypecode,tab)
242 auth_tag_structure => "(
243 authtypecode char(10) NOT NULL default '',
244 tagfield char(3) NOT NULL default '',
245 liblibrarian char(255) NOT NULL default '',
246 libopac char(255) NOT NULL default '',
247 repeatable tinyint(4) NOT NULL default '0',
248 mandatory tinyint(4) NOT NULL default '0',
249 authorised_value char(10) default NULL,
250 PRIMARY KEY (authtypecode,tagfield)
253 authid bigint(20) unsigned NOT NULL auto_increment,
254 authtypecode char(10) NOT NULL default '',
255 datecreated date NOT NULL default '0000-00-00',
256 datemodified date default NULL,
257 origincode char(20) default NULL,
258 PRIMARY KEY (authid),
259 KEY origincode (origincode),
261 auth_subfield_table => "(
262 subfieldid bigint(20) unsigned NOT NULL auto_increment,
263 authid bigint(20) unsigned NOT NULL default '0',
264 tag char(3) NOT NULL default '',
265 tagorder tinyint(4) NOT NULL default '1',
266 tag_indicator char(2) NOT NULL default '',
267 subfieldcode char(1) NOT NULL default '',
268 subfieldorder tinyint(4) NOT NULL default '1',
269 subfieldvalue varchar(255) default NULL,
270 PRIMARY KEY (subfieldid),
273 KEY subfieldcode (subfieldcode),
274 KEY subfieldvalue (subfieldvalue)
277 authid bigint(20) NOT NULL default '0',
278 tagsubfield char(4) NOT NULL default '',
279 tagorder tinyint(4) NOT NULL default '1',
280 subfieldorder tinyint(4) NOT NULL default '1',
281 word varchar(255) NOT NULL default '',
282 sndx_word varchar(255) NOT NULL default '',
284 KEY marc_search (tagsubfield,word),
286 KEY sndx_word (sndx_word)
289 suggestionid int(8) NOT NULL auto_increment,
290 suggestedby int(11) NOT NULL default '0',
291 managedby int(11) default NULL,
292 status varchar(10) NOT NULL default '',
294 author varchar(80) default NULL,
295 title varchar(80) default NULL,
296 copyrightdate smallint(6) default NULL,
297 publishercode varchar(255) default NULL,
298 date timestamp(8) NOT NULL,
299 volumedesc char(255) default NULL,
300 publicationyear smallint(6) default NULL,
301 place char(255) default NULL,
302 isbn char(10) default NULL,
303 mailoverseeing smallint(1) default 0,
304 PRIMARY KEY (suggestionnumber),
305 KEY suggestedby (suggestedby),
306 KEY managedby (managedby)
308 aqbasket => "(basketno int(11) NOT NULL auto_increment,
311 booksellerid varchar(10),
312 authorisedby varchar(10),
313 booksellerinvoicenumber text,
314 PRIMARY KEY (basketno)
316 serial => "(serialid int(11) NOT NULL auto_increment,
317 biblionumber varchar(100) NOT NULL default '',
318 subscriptionid varchar(100) NOT NULL default '',
319 serialseq varchar(100) NOT NULL default '',
320 status tinyint(4) NOT NULL default '0',
321 planneddate date NOT NULL default '0000-00-00',
322 PRIMARY KEY (serialid)
324 subscription => "(biblionumber int(11) NOT NULL default '0',
325 subscriptionid int(11) NOT NULL auto_increment,
326 librarian varchar(100) default '',
327 startdate date default '0000-00-00',
328 aqbooksellerid int(11) default '0',
329 cost int(11) default '0',
330 aqbudgetid int(11) default '0',
331 weeklength tinyint(4) default '0',
332 monthlength tinyint(4) default '0',
333 numberlength tinyint(4) default '0',
334 periodicity tinyint(4) default '0',
335 dow varchar(100) default '',
336 numberingmethod varchar(100) default '',
338 arrivalplanified varchar(100) NOT NULL default '',
339 status varchar(100) NOT NULL default '',
340 add1 int(11) default 0,
341 every1 int(11) default 0,
342 whenmorethan1 int(11) default 0,
345 add2 int(11) default 0,
346 every2 int(11) default 0,
347 whenmorethan2 int(11) default 0,
350 add3 int(11) default 0,
351 every3 int(11) default 0,
352 innerloop1 int(11) default 0,
353 innerloop2 int(11) default 0,
354 innerloop3 int(11) default 0,
355 whenmorethan3 int(11) default 0,
358 PRIMARY KEY (subscriptionid)
360 # seqnum1 int(11) default '0',
361 # startseqnum1 int(11) default '0',
362 # seqtype1 int(11) default '0',
363 # freq1 int(11) default '0',
364 # step1 int(11) default '0',
365 # seqnum2 int(11) default '0',
366 # step2 int(11) default '0',
367 # startseqnum2 int(11) default '0',
368 # freq2 int(11) default '0',
369 # seqtype2 int(11) default '0',
370 # seqnum3 int(11) default '0',
371 # freq3 int(11) default '0',
372 # notes varchar(100) NOT NULL default '',
373 # step3 int(11) default '0',
374 # pos3 int(11) NOT NULL default '0',
375 # pos2 int(11) NOT NULL default '0',
376 # pos1 int(11) NOT NULL default '0',
377 # seqtype3 int(11) default '0',
379 subscriptionhistory => "(biblionumber int(11) NOT NULL default '0',
380 subscriptionid int(11) NOT NULL default '0',
381 startdate date NOT NULL default '0000-00-00',
382 enddate date default '0000-00-00',
383 missinglist longtext NOT NULL,
384 recievedlist longtext NOT NULL,
385 opacnote varchar(150) NOT NULL default '',
386 librariannote varchar(150) NOT NULL default '',
387 PRIMARY KEY (subscriptionid),
388 KEY biblionumber (biblionumber)
392 my %requirefields = (
393 biblio => { 'abstract' => 'text' },
394 deletedbiblio => { 'abstract' => 'text', 'marc' => 'blob' },
395 deleteditems => { 'marc' => 'blob', 'paidfor' => 'text' },
397 'lccn' => 'char(25)',
398 'url' => 'varchar(255)',
401 deletedbiblioitems => {
402 'lccn' => 'char(25)',
403 'url' => 'varchar(255)',
406 branchtransfers => { 'datearrived' => 'datetime' },
407 statistics => { 'borrowernumber' => 'int(11)' },
409 'invoicedisc' => 'float(6,4)',
410 'nocalc' => 'int(11)'
413 'userid' => 'char(30)',
414 'password' => 'char(30)',
415 'flags' => 'int(11)',
416 'textmessaging' => 'varchar(30)',
417 'zipcode' => 'varchar(25)',
418 'homezipcode' => 'varchar(25)',
419 'sort1' => 'char(80)',
420 'sort2' => 'char(80)',
422 aqorders => { 'budgetdate' => 'date',
423 'sort1' => 'char(80)',
424 'sort2' => 'char(80)', },
425 aqbudget => {'aqbudgetid' => 'tinyint(4) auto_increment primary key'},
426 items => {'paidfor' => 'text'},
428 #added so that reference items are not available for reserves...
429 itemtypes => { 'notforloan' => 'smallint(6)' },
430 systempreferences => { 'explanation' => 'char(80)',
431 'type' => 'char(20)',
432 'options' => 'text' },
433 z3950servers => { 'syntax' => 'char(80)' },
434 marc_tag_structure =>{
435 'frameworkcode' => 'char(4) not NULL default \'\''},
436 marc_subfield_structure =>{'seealso' => 'char(255)',
437 'frameworkcode' => 'char(4) not NULL default \'\'',
438 'hidden' => 'tinyint(1)',
439 'isurl' => 'tinyint(1)',
441 bookshelf => {'owner' => 'char(80)',
442 'category' => 'char(1)',
444 marc_biblio => { 'frameworkcode' => 'char(4) not NULL default \'\'' },
447 my %dropable_table = (
448 classification => 'classification',
449 multipart => 'multipart',
450 multivolume => 'multivolume',
451 newitems => 'newitems',
452 procedures => 'procedures',
453 publisher => 'publisher',
454 searchstats => 'searchstats',
455 serialissues => 'serialissues',
458 my %uselessfields = (
459 aqorders => "requisitionedby,authorisedby,booksellerid,
460 deliverydays,followupdays,
461 numberfollowupsallowed,numberfollowupssent,
462 dateprinted,sourced,quantityreceiveddamaged,
463 subscriptionfrom,subscriptionto
466 # the other hash contains other actions that can't be done elsewhere. they are done
467 # either BEFORE of AFTER everything else, depending on "when" entry (default => AFTER)
469 # The tabledata hash contains data that should be in the tables.
470 # The uniquefieldrequired hash entry is used to determine which (if any) fields
471 # must not exist in the table for this row to be inserted. If the
472 # uniquefieldrequired entry is already in the table, the existing data is not
473 # modified, unless the forceupdate hash entry is also set. Fields in the
474 # anonymous "forceupdate" hash will be forced to be updated to the default
475 # values given in the %tabledata hash.
480 uniquefieldrequired => 'bit',
482 flag => 'superlibrarian',
483 flagdesc => 'Access to all librarian functions',
487 uniquefieldrequired => 'bit',
490 flagdesc => 'Circulate books',
494 uniquefieldrequired => 'bit',
497 flagdesc => 'View Catalogue (Librarian Interface)',
501 uniquefieldrequired => 'bit',
503 flag => 'parameters',
504 flagdesc => 'Set Koha system paramters',
508 uniquefieldrequired => 'bit',
511 flagdesc => 'Add or modify borrowers',
515 uniquefieldrequired => 'bit',
517 flag => 'permissions',
518 flagdesc => 'Set user permissions',
522 uniquefieldrequired => 'bit',
524 flag => 'reserveforothers',
525 flagdesc => 'Reserve books for patrons',
529 uniquefieldrequired => 'bit',
532 flagdesc => 'Borrow books',
536 uniquefieldrequired => 'bit',
538 flag => 'reserveforself',
539 flagdesc => 'Reserve books for self',
543 uniquefieldrequired => 'bit',
545 flag => 'editcatalogue',
546 flagdesc => 'Edit Catalogue (Modify bibliographic/holdings data)',
550 uniquefieldrequired => 'bit',
552 flag => 'updatecharges',
553 flagdesc => 'Update borrower charges',
557 systempreferences => [
559 uniquefieldrequired => 'variable',
560 forceupdate => { 'explanation' => 1,
562 variable => 'LibraryName',
563 value => '<i><b>Koha<br/>Free Software ILS<br/><br/></b>Koha : a gift, a contribution<br/> in Maori</i>',
564 explanation => 'Library name as shown on main opac page',
569 uniquefieldrequired => 'variable',
570 forceupdate => { 'explanation' => 1,
572 variable => 'autoMemberNum',
574 explanation => 'Member number is auto-calculated',
579 uniquefieldrequired => 'variable',
580 forceupdate => { 'explanation' => 1,
583 variable => 'acquisitions',
586 'Normal, budget-based acquisitions, or Simple bibliographic-data acquisitions',
588 options => 'simple|normal'
591 uniquefieldrequired => 'variable',
592 forceupdate => { 'explanation' => 1,
595 variable => 'dateformat',
598 'date format (us mm/dd/yyyy, metric dd/mm/yyy, ISO yyyy/mm/dd)',
600 options => 'metric|us|iso'
603 uniquefieldrequired => 'variable',
604 variable => 'template',
605 forceupdate => { 'explanation' => 1,
608 explanation => 'Preference order for intranet interface templates',
612 uniquefieldrequired => 'variable',
613 variable => 'autoBarcode',
614 forceupdate => { 'explanation' => 1,
617 explanation => 'Barcode is auto-calculated',
621 uniquefieldrequired => 'variable',
622 variable => 'insecure',
623 forceupdate => { 'explanation' => 1,
627 'If YES, no auth at all is needed. Be careful if you set this to yes!',
631 uniquefieldrequired => 'variable',
632 variable => 'authoritysep',
633 forceupdate => { 'explanation' => 1,
638 'the separator used in authority/thesaurus. Usually --',
643 uniquefieldrequired => 'variable',
644 variable => 'opaclanguages',
645 forceupdate => { 'explanation' => 1,
648 explanation => 'Set the preferred order for translations. The top language will be tried first.',
652 uniquefieldrequired => 'variable',
653 variable => 'opacthemes',
654 forceupdate => { 'explanation' => 1,
657 explanation => 'Set the preferred order for themes. The top theme will be tried first.',
661 uniquefieldrequired => 'variable',
662 variable => 'timeout',
663 forceupdate => { 'explanation' => 1,
666 explanation => 'Inactivity timeout for cookies authentication (in seconds)',
670 uniquefieldrequired => 'variable',
672 forceupdate => { 'explanation' => 1,
675 explanation => 'Turn on MARC support',
679 uniquefieldrequired => 'variable',
680 variable => 'marcflavour',
681 forceupdate => { 'explanation' => 1,
686 'your MARC flavor (MARC21 or UNIMARC) used for character encoding',
688 options => 'MARC21|UNIMARC'
691 uniquefieldrequired => 'variable',
692 variable => 'checkdigit',
694 forceupdate => { 'explanation' => 1,
697 explanation => 'Validity checks on membership number: none or "Katipo" style checks',
699 options => 'none|katipo'
702 uniquefieldrequired => 'variable',
703 variable => 'maxoutstanding',
704 forceupdate => { 'explanation' => 1,
708 'maximum amount withstanding to be able make reserves ',
712 uniquefieldrequired => 'variable',
713 variable => 'maxreserves',
714 forceupdate => { 'explanation' => 1,
718 'maximum number of reserves a member can make',
723 uniquefieldrequired => 'variable',
724 variable => 'noissuescharge',
725 forceupdate => { 'explanation' => 1,
729 'maximum amount withstanding to be able to check out an item',
734 uniquefieldrequired => 'variable',
735 variable => 'KohaAdminEmailAddress',
736 forceupdate => { 'explanation' => 1,
738 value => 'your.mail@here',
739 explanation => 'the email address where borrowers modifs are sent',
743 uniquefieldrequired => 'variable',
745 forceupdate => { 'explanation' => 1,
748 explanation => 'the gist rate. NOT in %, but in numeric form (0.12 for 12%)',
752 uniquefieldrequired => 'variable',
753 variable => 'ldapserver',
754 forceupdate => { 'explanation' => 1,
757 explanation => 'your ldap server',
761 uniquefieldrequired => 'variable',
762 variable => 'ldapinfos',
763 forceupdate => { 'explanation' => 1,
766 explanation => 'ldap info. The ldap will be used in dn : uid=xxx, <ldapinfos>',
770 uniquefieldrequired => 'variable',
771 variable => 'printcirculationslips',
772 forceupdate => { 'explanation' => 1,
775 explanation => 'if set to 1, print circulation slips. If set to 0, don\'t',
779 uniquefieldrequired => 'variable',
780 variable => 'suggestion',
781 forceupdate => { 'explanation' => 1,
784 explanation => 'if set to 1, suggestions are activated in OPAC',
788 uniquefieldrequired => 'variable',
790 forceupdate => { 'explanation' => 1,
792 value => 'Fill with appropriate value...',
793 explanation => 'ISBD',
797 uniquefieldrequired => 'variable',
798 variable => 'virtualshelves',
799 forceupdate => { 'explanation' => 1,
802 explanation => 'Set virtual shelves management ON or OFF',
809 my %fielddefinitions = (
812 field => 'printername',
821 field => 'bookfundid',
830 field => 'aqbudgetid',
831 type => 'tinyint(4)',
835 extra => 'auto_increment'
845 extra => 'auto_increment'
850 field => 'z3950random',
851 type => 'varchar(40)',
859 type => 'varchar(40)',
873 # Get version of MySQL database engine.
874 my $mysqlversion = `mysqld --version`;
875 $mysqlversion =~ /Ver (\S*) /;
877 if ( $mysqlversion ge '3.23' ) {
878 print "Could convert to MyISAM database tables...\n" unless $silent;
881 #---------------------------------
884 # Collect all tables into a list
885 $sth = $dbh->prepare("show tables");
887 while ( my ($table) = $sth->fetchrow ) {
888 $existingtables{$table} = 1;
892 # Now add any missing tables
893 foreach $table ( keys %requiretables ) {
894 unless ( $existingtables{$table} ) {
895 print "Adding $table table...\n" unless $silent;
896 my $sth = $dbh->prepare("create table $table $requiretables{$table}");
899 print "Error : $sth->errstr \n";
905 # now drop useless tables
906 foreach $table ( keys %dropable_table ) {
907 if ( $existingtables{$table} ) {
908 print "Dropping unused table $table\n" if $debug and not $silent;
909 $dbh->do("drop table $table");
911 print "Error : $dbh->errstr \n";
915 unless ( $existingtables{'z3950servers'} ) {
916 #MJR: added syntax entries to close bug 624
917 print "Adding z3950servers table...\n" unless $silent;
918 my $sti = $dbh->prepare( "create table z3950servers (
931 $sti = $dbh->prepare( "insert into z3950servers
932 values ('z3950.loc.gov',
936 'Library of Congress',
941 unless ( $existingtables{'issuingrules'} ) {
942 $dbh->do("alter table categoryitem rename issuingrules");
943 $dbh->do("ALTER TABLE issuingrules ADD maxissueqty int(4) default NULL");
944 $dbh->do("ALTER TABLE issuingrules ADD issuelength int(4) default NULL");
945 $dbh->do("ALTER TABLE issuingrules ADD branchcode varchar(4) NOT NULL default ''");
946 print "renaming categoryitem\n" unless $silent;
950 #---------------------------------
953 foreach $table ( keys %requirefields ) {
954 print "Check table $table\n" if $debug and not $silent;
955 $sth = $dbh->prepare("show columns from $table");
958 while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
960 $types{$column} = $type;
962 foreach $column ( keys %{ $requirefields{$table} } ) {
963 print " Check column $column [$types{$column}]\n" if $debug and not $silent;
964 if ( !$types{$column} ) {
966 # column doesn't exist
967 print "Adding $column field to $table table...\n" unless $silent;
968 $query = "alter table $table
969 add column $column " . $requirefields{$table}->{$column};
970 print "Execute: $query\n" if $debug;
971 my $sti = $dbh->prepare($query);
974 print "**Error : $sti->errstr \n";
981 foreach $table ( keys %fielddefinitions ) {
982 print "Check table $table\n" if $debug;
983 $sth = $dbh->prepare("show columns from $table");
986 while ( ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
988 $definitions->{$column}->{type} = $type;
989 $definitions->{$column}->{null} = $null;
990 $definitions->{$column}->{key} = $key;
991 $definitions->{$column}->{default} = $default;
992 $definitions->{$column}->{extra} = $extra;
994 my $fieldrow = $fielddefinitions{$table};
995 foreach my $row (@$fieldrow) {
996 my $field = $row->{field};
997 my $type = $row->{type};
998 my $null = $row->{null};
999 my $key = $row->{key};
1000 my $default = $row->{default};
1001 $default="''" unless $default;
1002 my $extra = $row->{extra};
1003 my $def = $definitions->{$field};
1004 unless ( $type eq $def->{type}
1005 && $null eq $def->{null}
1006 && $key eq $def->{key}
1007 && $default eq $def->{default}
1008 && $extra eq $def->{extra} )
1011 if ( $null eq '' ) {
1014 if ( $key eq 'PRI' ) {
1015 $key = 'PRIMARY KEY';
1017 unless ( $extra eq 'auto_increment' ) {
1020 # if it's a new column use "add", if it's an old one, use "change".
1022 if ($definitions->{$field}->{type}) {
1023 $action="change $field"
1027 # if it's a primary key, drop the previous pk, before altering the table
1029 if ($key ne 'PRIMARY KEY') {
1030 $sth =$dbh->prepare("alter table $table $action $field $type $null $key $extra default ?");
1032 $sth =$dbh->prepare("alter table $table drop primary key, $action $field $type $null $key $extra default ?");
1034 $sth->execute($default);
1035 print " Alter $field in $table\n" unless $silent;
1040 # Get list of columns from borrowers table
1043 $sth = $dbh->prepare("show columns from borrowers");
1045 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1047 $itemtypes{$column} = $type;
1048 $nullenabled{$column} = $null;
1051 unless ( $itemtypes{'cardnumber'} eq 'varchar(20)' ) {
1052 $itemtypes{'cardnumber'} =~ /varchar\((\d+)\)/;
1054 if ( $oldlength < 16 ) {
1055 print "Setting maximum cardnumber length to 16 (was $oldlength) and marking unique.\n" unless $silent;
1058 "alter table borrowers change cardnumber cardnumber varchar(16)");
1063 "alter table borrowers drop index cardnumber");
1068 "alter table borrowers add unique(cardnumber)");
1074 # Get list of columns from items table
1075 $sth = $dbh->prepare("show columns from items");
1077 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1079 $itemtypes{$column} = $type;
1080 $nullenabled{$column} = $null;
1083 unless ( $itemtypes{'barcode'} eq 'varchar(20)' ) {
1084 $itemtypes{'barcode'} =~ /varchar\((\d+)\)/;
1086 if ( $oldlength < 20 ) {
1087 print "Setting maximum barcode length to 20 (was $oldlength).\n" unless $silent;
1090 "alter table items change barcode barcode varchar(20)");
1095 # dropping unique barcode index & setting barcode to null allowed.
1097 $sth = $dbh->prepare("show index from items");
1099 while ( my ( $table, $non_unique, $key_name, $Seq_in_index, $Column_name, $Collation, $cardinality, $sub_part, $Packed, $comment ) = $sth->fetchrow )
1101 if ($key_name eq 'barcode' && $non_unique eq 0) {
1102 print "dropping BARCODE index to enable empty barcodes\n" unless $silent;
1103 $dbh->do("ALTER TABLE `items` DROP INDEX `barcode`");
1106 $dbh->do("ALTER TABLE `items` CHANGE `barcode` `barcode` VARCHAR( 20 )") unless ($nullenabled{barcode} eq 'YES');
1109 # creating fulltext index in bibliothesaurus if needed
1111 $sth = $dbh->prepare("show index from bibliothesaurus");
1114 while ( my ( $table, $non_unique, $key_name, $Seq_in_index, $Column_name, $Collation, $cardinality, $sub_part, $Packed, $comment ) = $sth->fetchrow )
1116 if ($key_name eq 'category_2') {
1120 print "Creating fulltext index on bibliothesaurus\n" unless $exists or $silent;
1121 $dbh->do('create fulltext index category_2 on bibliothesaurus (category,freelib)') unless $exists;
1124 # creating index in z3950results if needed
1126 $sth = $dbh->prepare("show index from z3950results");
1129 while ( my ( $table, $non_unique, $key_name, $Seq_in_index, $Column_name, $Collation, $cardinality, $sub_part, $Packed, $comment ) = $sth->fetchrow )
1131 if ($key_name eq 'query_server') {
1135 print "Creating index on z3950results\n" unless $exists or $silent;
1136 $dbh->do('create unique index query_server on z3950results (queryid,server)') unless $exists;
1138 # changing z3950daemon field to NULL in marc_breeding
1139 $dbh->do("ALTER TABLE `marc_breeding` CHANGE `z3950random` `z3950random` VARCHAR( 40 )");
1141 # making borrowernumber an auto_increment field
1142 $dbh->do("ALTER TABLE `borrowers` CHANGE `borrowernumber` `borrowernumber` INTEGER auto_increment");
1144 # changing indexes in marc_*_structure to use frameworkcode
1145 $dbh->do('alter table marc_subfield_structure drop index tab');
1146 $dbh->do('create index tab on marc_subfield_structure (frameworkcode,tab)');
1147 $dbh->do('alter table marc_subfield_structure drop index kohafield');
1148 $dbh->do('create index kohafield on marc_subfield_structure (frameworkcode,kohafield)');
1151 # extending the timestamp in branchtransfers...
1152 my %branchtransfers;
1154 $sth = $dbh->prepare("show columns from branchtransfers");
1156 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1158 $branchtransfers{$column} = $type;
1161 unless ( $branchtransfers{'datesent'} eq 'datetime' ) {
1162 print "Setting type of datesent in branchtransfers to datetime.\n" unless $silent;
1165 "alter table branchtransfers change datesent datesent datetime");
1169 unless ( $branchtransfers{'datearrived'} eq 'datetime' ) {
1170 print "Setting type of datearrived in branchtransfers to datetime.\n" unless $silent;
1173 "alter table branchtransfers change datearrived datearrived datetime");
1177 # changing the branchcategories table around...
1178 my %branchcategories;
1180 $sth = $dbh->prepare("show columns from branchcategories");
1182 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1184 $branchcategories{$column} = $type;
1187 unless ( $branchcategories{'categorycode'} eq 'varchar(4)' ) {
1189 "Setting type of categorycode in branchcategories to varchar(4),\n and making the primary key.\n" unless $silent;
1192 "alter table branchcategories change categorycode categorycode varchar(4) not null"
1197 "alter table branchcategories add primary key (categorycode)");
1201 unless ( $branchcategories{'categoryname'} eq 'text' ) {
1202 print "Changing branchcode in branchcategories to categoryname text.\n" unless $silent;
1205 "alter table branchcategories change branchcode categoryname text");
1209 unless ( $branchcategories{'codedescription'} eq 'text' ) {
1211 "Replacing branchholding in branchcategories with codedescription text.\n" unless $silent;
1214 "alter table branchcategories change branchholding codedescription text"
1219 # changing the items table around...
1222 $sth = $dbh->prepare("show columns from items");
1224 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1226 $items{$column} = $type;
1229 if ($items{'bulk'} eq "varchar(30)") {
1230 print " Setting callnumber in items table\n" unless $silent;
1232 $dbh->prepare("ALTER TABLE `items` CHANGE `bulk` `itemcallnumber` VARCHAR( 30 ) DEFAULT NULL");
1234 $sti = $dbh->prepare("update marc_subfield_structure set kohafield=\"items.itemcallnumber\" where kohafield=\"items.bulk\"");
1238 # changing the marc_subfield_structure table around...
1239 my %marc_subfield_structure;
1241 $sth = $dbh->prepare("show columns from marc_subfield_structure");
1243 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1245 $marc_subfield_structure{$column} = $type;
1248 if ($marc_subfield_structure{thesaurus_category}) {
1249 print " changing thesaurus_category in marc_subfield_structure table\n" unless $silent;
1251 $dbh->prepare("ALTER TABLE marc_subfield_structure CHANGE `thesaurus_category` `authtypecode` VARCHAR(10 ) DEFAULT NULL");
1256 # creating index in issuingrules if needed
1258 $sth = $dbh->prepare("show index from issuingrules");
1261 while ( my ( $table, $non_unique, $key_name, $Seq_in_index, $Column_name, $Collation, $cardinality, $sub_part, $Packed, $comment ) = $sth->fetchrow )
1263 if ($key_name eq 'PRIMARY') {
1267 print "Creating index on issuing rules\n" unless $exists or $silent;
1268 $dbh->do('ALTER TABLE issuingrules ADD PRIMARY KEY ( branchcode, categorycode, itemtype )') unless $exists;
1270 $dbh->do('ALTER TABLE marc_tag_structure drop primary key');
1271 $dbh->do('ALTER TABLE marc_tag_structure ADD PRIMARY KEY ( frameworkcode, tagfield )');
1273 $dbh->do('ALTER TABLE marc_subfield_structure drop primary key');
1274 $dbh->do('ALTER TABLE marc_subfield_structure ADD PRIMARY KEY ( frameworkcode, tagfield, tagsubfield )');
1276 # Get list of columns from marc_word table
1279 $sth = $dbh->prepare("show columns from marc_word");
1281 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1283 $marc_word{$column} = $type;
1284 $nullenabled{$column} = $null;
1286 if ($marc_word{subfieldid}) {
1287 #create field tagsubfield, copy tag+subfieldid, then drop tag and subfieldid
1288 print "Modifying marc_word (concat on tag and subfield for better perfs)\n" unless $silent;
1289 $dbh->do("ALTER TABLE `marc_word` ADD `tagsubfield` CHAR( 4 ) NOT NULL AFTER `bibid`");
1290 $dbh->do("update marc_word set tagsubfield=concat(tag,subfieldid)");
1291 $dbh->do("alter table marc_word drop tag");
1292 $dbh->do("alter table marc_word drop subfieldid");
1293 $dbh->do("create index Search_Marc on marc_word (tagsubfield,word)");
1295 # Populate tables with required data
1297 # fill aqbasket if it's empty and aqorder is not
1298 # => it means it has just been created & must be filled
1299 $sth = $dbh->prepare("select count(*) from aqbasket");
1301 if ($sth->fetchrow == 0) {
1302 $sth = $dbh->prepare("select count(*) from aqorders");
1304 if ($sth->fetchrow >0) {
1305 print "Populating new table aqbasket\n";
1306 print "IMPORTANT NOTE: error message \"Duplicate entry 'X' for key 1\" may appear. it should not be a real trouble\n";
1307 $sth=$dbh->prepare("select distinct basketno,booksellerid,authorisedby,entrydate,booksellerinvoicenumber from aqorders");
1309 my ($basketno,$booksellerid,$authorisedby,$entrydate,$booksellerinvoicenumber);
1310 my $sth2 = $dbh->prepare("insert into aqbasket (basketno,creationdate,booksellerid,authorisedby,booksellerinvoicenumber) values (?,?,?,?,?)");
1311 while (($basketno,$booksellerid,$authorisedby,$entrydate,$booksellerinvoicenumber) = $sth->fetchrow) {
1312 print "$basketno,$entrydate,$booksellerid,$authorisedby,$booksellerinvoicenumber\n";
1313 $sth2->execute($basketno,$entrydate,$booksellerid,$authorisedby,$booksellerinvoicenumber);
1317 foreach my $table ( keys %tabledata ) {
1318 print "Checking for data required in table $table...\n" unless $silent;
1319 my $tablerows = $tabledata{$table};
1320 foreach my $row (@$tablerows) {
1321 my $uniquefieldrequired = $row->{uniquefieldrequired};
1322 my $uniquevalue = $row->{$uniquefieldrequired};
1323 my $forceupdate = $row->{forceupdate};
1326 "select $uniquefieldrequired from $table where $uniquefieldrequired=?"
1328 $sth->execute($uniquevalue);
1330 foreach my $field (keys %$forceupdate) {
1331 if ($forceupdate->{$field}) {
1332 my $sth=$dbh->prepare("update systempreferences set $field=? where $uniquefieldrequired=?");
1333 $sth->execute($row->{$field}, $uniquevalue);
1337 print "Adding row to $table: " unless $silent;
1341 foreach my $field ( keys %$row ) {
1342 next if $field eq 'uniquefieldrequired';
1343 next if $field eq 'forceupdate';
1344 my $value = $row->{$field};
1345 push @values, $value;
1346 print " $field => $value" unless $silent;
1347 $fieldlist .= "$field,";
1348 $placeholders .= "?,";
1350 print "\n" unless $silent;
1351 $fieldlist =~ s/,$//;
1352 $placeholders =~ s/,$//;
1355 "insert into $table ($fieldlist) values ($placeholders)");
1356 $sth->execute(@values);
1361 # at last, remove useless fields
1362 foreach $table ( keys %uselessfields ) {
1363 my @fields = split /,/,$uselessfields{$table};
1366 foreach my $fieldtodrop (@fields) {
1367 $fieldtodrop =~ s/\t//g;
1368 $fieldtodrop =~ s/\n//g;
1370 $sth = $dbh->prepare("show columns from $table");
1372 while ( my ( $column, $type, $null, $key, $default, $extra ) = $sth->fetchrow )
1374 $exists =1 if ($column eq $fieldtodrop);
1377 print "deleting $fieldtodrop field in $table...\n" unless $silent;
1378 my $sth = $dbh->prepare("alter table $table drop $fieldtodrop");
1390 # Revision 1.92 2004/08/06 16:38:42 tipaul
1391 # changing DB structure to calculate next issue number.
1392 # Seems to work fine.
1394 # Still misses the date calculation & the test of end of subscription (maybe for monday ?)
1396 # Revision 1.91 2004/07/15 09:52:28 tipaul
1397 # Acquisition & Suggestion :
1398 # * acquisition rewritte : create a aqbasket table to deal with "bookseller order header".
1399 # * add "close basket" feature : a closed basket can't be modified
1400 # * suggestion feature : manage suggestions in acquisition (after suggestion filled in OPAC)
1402 # Revision 1.90 2004/07/06 08:24:18 tipaul
1403 # adding 2 free fields that can be used for sorting purposes
1405 # Revision 1.89 2004/07/02 15:55:08 tipaul
1406 # Adding 2 new fields, called "sort1" and "sort2"
1407 # They can be used for sorting & statistics reasons by the library.
1409 # Revision 1.88 2004/06/26 23:34:26 rangi
1412 # Revision 1.87 2004/06/23 13:03:09 tipaul
1413 # fixes in DB structure
1415 # Revision 1.86 2004/06/22 11:30:57 tipaul
1416 # adding -s (silent) flag, to have a silent install.
1417 # only updater will be verbose
1419 # Revision 1.85 2004/06/17 15:19:44 tipaul
1420 # missing Marc_Search index on marc_word
1422 # Revision 1.84 2004/06/17 08:25:21 tipaul
1423 # DB modifs : merging tag & subfield in marc_word table
1425 # Revision 1.83 2004/06/10 08:32:02 tipaul
1426 # MARC authority management (continued)
1428 # Revision 1.82 2004/06/03 12:46:58 tipaul
1429 # * frameworks and itemtypes are independant
1431 # WARNING : will work only if applied to a 2.0 base. some modifs have been done since last commit that will NOT be applied if you run updatedatabase again.
1433 # Revision 1.81 2004/05/28 09:56:21 tipaul
1436 # Revision 1.80 2004/05/28 08:32:00 tipaul
1438 # * MARC authority file
1439 # * seealso & hidden in MARC biblio structure.
1441 # Revision 1.79 2004/05/18 09:50:07 tipaul
1442 # *** empty log message ***
1444 # Revision 1.78 2004/05/10 09:29:33 tipaul
1445 # css is now the default theme for OPAC.
1446 # It will be the theme used for improvements and new things in OPAC.
1448 # Revision 1.77 2004/05/06 14:56:51 tipaul
1449 # adding table issuingrules (previously called categoryitem
1451 # Revision 1.76 2004/05/03 09:32:25 tipaul
1452 # adding printcirculationsplit parameter (already existed, but was not in systempref by defaul)
1454 # Revision 1.75 2004/04/14 19:49:00 tipaul
1455 # seealso field set to 255 chars
1457 # Revision 1.74 2004/03/11 16:10:16 tipaul
1458 # *** empty log message ***
1460 # Revision 1.73 2004/03/06 20:26:13 tipaul
1461 # adding seealso feature in MARC searches