[Koha-patches] [PATCH] Bug Fixing merge_authority.pl
Galen Charlton
galen.charlton at liblime.com
Sat Aug 9 17:53:13 CEST 2008
From: Henri-Damien LAURENT <henridamien.laurent at biblibre.com>
merge works on the fly now.
But for an obscure reason, merge_authority.pl fails to update database when lanched on command line.
Adding one table to LOCK for noZebra UPDATE in Biblio.pm
You should remove C4::Search from merg_authority.pl
Signed-off-by: Galen Charlton <galen.charlton at liblime.com>
---
C4/AuthoritiesMarc.pm | 120 +++++++++++++++++-------------
C4/Biblio.pm | 5 +-
authorities/authorities.pl | 4 +-
misc/migration_tools/merge_authority.pl | 79 ++++++++------------
4 files changed, 103 insertions(+), 105 deletions(-)
diff --git a/C4/AuthoritiesMarc.pm b/C4/AuthoritiesMarc.pm
index 023cda0..011bcf1 100644
--- a/C4/AuthoritiesMarc.pm
+++ b/C4/AuthoritiesMarc.pm
@@ -538,8 +538,7 @@ sub AddAuthority {
,'a'=>$date."afrey50 ba0")
);
}
- }
-
+ }
my ($auth_type_tag, $auth_type_subfield) = get_auth_type_location($authtypecode);
if (!$authid and $format eq "MARC21") {
# only need to do this fix when modifying an existing authority
@@ -604,12 +603,8 @@ sub DelAuthority {
sub ModAuthority {
my ($authid,$record,$authtypecode,$merge)=@_;
my $dbh=C4::Context->dbh;
-# my ($oldrecord)=&GetAuthority($authid);
-# if ($oldrecord eq $record) {
-# return;
-# }
-# my $sth=$dbh->prepare("update auth_header set marc=?,marcxml=? where authid=?");
#Now rewrite the $record to table with an add
+ my $oldrecord=GetAuthority($authid);
$authid=AddAuthority($record,$authid,$authtypecode);
### If a library thinks that updating all biblios is a long process and wishes to leave that to a cron job to use merge_authotities.p
@@ -628,7 +623,7 @@ sub ModAuthority {
print AUTH $authid;
close AUTH;
} else {
-# &merge($authid,$record,$authid,$record);
+ &merge($authid,$oldrecord,$authid,$record);
}
return $authid;
}
@@ -1149,14 +1144,15 @@ Then we should add some new parameter : bibliotargettag, authtargettag
sub merge {
my ($mergefrom,$MARCfrom,$mergeto,$MARCto) = @_;
+ my ($counteditedbiblio,$countunmodifiedbiblio,$counterrors)=(0,0,0);
my $dbh=C4::Context->dbh;
my $authtypecodefrom = GetAuthTypeCode($mergefrom);
my $authtypecodeto = GetAuthTypeCode($mergeto);
# return if authority does not exist
my @X = $MARCfrom->fields();
- return if $#X == -1;
+ return "error MARCFROM not a marcrecord ".Data::Dumper::Dumper($MARCfrom) if $#X == -1;
@X = $MARCto->fields();
- return if $#X == -1;
+ return "error MARCTO not a marcrecord".Data::Dumper::Dumper($MARCto) if $#X == -1;
# search the tag to report
my $sth = $dbh->prepare("select auth_tag_to_report from auth_types where authtypecode=?");
$sth->execute($authtypecodefrom);
@@ -1167,62 +1163,82 @@ sub merge {
my @record_from;
@record_from = $MARCfrom->field($auth_tag_to_report)->subfields() if $MARCfrom->field($auth_tag_to_report);
+ my @reccache;
# search all biblio tags using this authority.
- $sth = $dbh->prepare("select distinct tagfield from marc_subfield_structure where authtypecode=?");
- $sth->execute($authtypecodefrom);
- my @tags_using_authtype;
- while (my ($tagfield) = $sth->fetchrow) {
- push @tags_using_authtype,$tagfield."9" ;
- }
-
+ #Getting marcbiblios impacted by the change.
if (C4::Context->preference('NoZebra')) {
- warn "MERGE TO DO";
+ #nozebra way
+ my $dbh=C4::Context->dbh;
+ my $rq=$dbh->prepare(qq(SELECT biblionumbers from nozebra where indexname="an" and server="biblioserver" and value="$mergefrom" ));
+ $rq->execute;
+ while (my $biblionumbers=$rq->fetchrow){
+ my @biblionumbers=split /;/,$biblionumbers;
+ map {
+ my $biblionumber=$1 if ($_=~/(\d+),.*/);
+ my $marc=GetMarcBiblio($biblionumber);
+ push @reccache,$marc;
+ } @biblionumbers;
+ }
} else {
- # now, find every biblio using this authority
- my $oConnection=C4::Context->Zconn("biblioserver");
+ #zebra connection
+ my $oConnection=C4::Context->Zconn("biblioserver",0);
my $query;
- $query= "an= ".$mergefrom;
+ $query= "an=".$mergefrom;
my $oResult = $oConnection->search(new ZOOM::Query::CCL2RPN( $query, $oConnection ));
my $count=$oResult->size() if ($oResult);
- my @reccache;
my $z=0;
while ( $z<$count ) {
- my $rec;
- $rec=$oResult->record($z);
+ my $rec;
+ $rec=$oResult->record($z);
my $marcdata = $rec->raw();
- push @reccache, $marcdata;
+ push @reccache, $marcdata;
$z++;
}
- $oResult->destroy();
- foreach my $marc(@reccache){
- my $update;
- my $marcrecord;
- $marcrecord = MARC::File::USMARC::decode($marc);
- foreach my $tagfield (@tags_using_authtype){
- $tagfield=substr($tagfield,0,3);
- my @tags = $marcrecord->field($tagfield);
- foreach my $tag (@tags){
- my $tagsubs=$tag->subfield("9");
- #warn "$tagfield:$tagsubs:$mergefrom";
- if ($tagsubs== $mergefrom) {
- $tag->update("9" =>$mergeto);
- foreach my $subfield (@record_to) {
- # warn "$subfield,$subfield->[0],$subfield->[1]";
- $tag->update($subfield->[0] =>$subfield->[1]);
- }#for $subfield
+ $oConnection->destroy();
+ }
+ warn scalar(@reccache)." biblios to update";
+ # Get All candidate Tags for the change
+ # (This will reduce the search scope in marc records).
+ $sth = $dbh->prepare("select distinct tagfield from marc_subfield_structure where authtypecode=?");
+ $sth->execute($authtypecodefrom);
+ my @tags_using_authtype;
+ while (my ($tagfield) = $sth->fetchrow) {
+ push @tags_using_authtype,$tagfield ;
+ }
+ my $tag_to=0;
+ if ($authtypecodeto ne $authtypecodefrom){
+ # If many tags, take the first
+ $sth->execute($authtypecodeto);
+ $tag_to=$sth->fetchrow;
+ warn $tag_to;
+ }
+ # BulkEdit marc records
+ # May be used as a template for a bulkedit field
+ foreach my $marcrecord(@reccache){
+ my $update;
+ $marcrecord= MARC::File::USMARC::decode($marcrecord) unless(C4::Context->preference('NoZebra'));
+ foreach my $tagfield (@tags_using_authtype){
+ foreach my $field ($marcrecord->field($tagfield)){
+ my $auth_number=$field->subfield("9");
+ my $tag=$field->tag();
+ if ($auth_number==$mergefrom) {
+ my $field_to=MARC::Field->new(($tag_to?$tag_to:$tag),$field->indicator(1),$field->indicator(2),"9"=>$mergeto);
+ foreach my $subfield (@record_to) {
+ $field_to->add_subfields($subfield->[0] =>$subfield->[1]);
+ }
+ $field->replace_with($field_to);
+ $update=1;
}
- $marcrecord->delete_field($tag);
- $marcrecord->add_fields($tag);
- $update=1;
}#for each tag
- }#foreach tagfield
- my $oldbiblio = TransformMarcToKoha($dbh,$marcrecord,"") ;
- if ($update==1){
+ }#foreach tagfield
+ my $oldbiblio = TransformMarcToKoha($dbh,$marcrecord,"") ;
+ if ($update==1){
&ModBiblio($marcrecord,$oldbiblio->{'biblionumber'},GetFrameworkCode($oldbiblio->{'biblionumber'})) ;
- }
-
- }#foreach $marc
- }
+ $counteditedbiblio++;
+ warn $counteditedbiblio if (($counteditedbiblio % 10) and $ENV{DEBUG});
+ }
+ }#foreach $marc
+ return $counteditedbiblio;
# now, find every other authority linked with this authority
# my $oConnection=C4::Context->Zconn("authorityserver");
# my $query;
diff --git a/C4/Biblio.pm b/C4/Biblio.pm
index a0406db..e4e2dc2 100755
--- a/C4/Biblio.pm
+++ b/C4/Biblio.pm
@@ -2140,8 +2140,8 @@ sub ModZebra {
# lock the nozebra table : we will read index lines, update them in Perl process
# and write everything in 1 transaction.
# lock the table to avoid someone else overwriting what we are doing
- $dbh->do('LOCK TABLES nozebra WRITE,biblio WRITE,biblioitems WRITE, systempreferences WRITE, auth_types WRITE, auth_header WRITE');
- my %result; # the result hash that will be builded by deletion / add, and written on mySQL at the end, to improve speed
+ $dbh->do('LOCK TABLES nozebra WRITE,biblio WRITE,biblioitems WRITE, systempreferences WRITE, auth_types WRITE, auth_header WRITE, auth_subfield_structure READ');
+ my %result; # the result hash that will be built by deletion / add, and written on mySQL at the end, to improve speed
if ($op eq 'specialUpdate') {
# OK, we have to add or update the record
# 1st delete (virtually, in indexes), if record actually exists
@@ -2163,7 +2163,6 @@ sub ModZebra {
}
}
$dbh->do('UNLOCK TABLES');
-
} else {
#
# we use zebra, just fill zebraqueue table
diff --git a/authorities/authorities.pl b/authorities/authorities.pl
index 26da895..a0ce203 100755
--- a/authorities/authorities.pl
+++ b/authorities/authorities.pl
@@ -580,7 +580,7 @@ if ($op eq "add") {
# it is not a duplicate (determined either by Koha itself or by user checking it's not a duplicate)
if (!$duplicateauthid or $confirm_not_duplicate) {
if ($is_a_modif ) {
- ModAuthority($authid,$record,$authtypecode,1);
+ ModAuthority($authid,$record,$authtypecode);
} else {
($authid) = AddAuthority($record,$authid,$authtypecode);
}
@@ -597,7 +597,7 @@ if ($op eq "add") {
}
} elsif ($op eq "delete") {
#------------------------------------------------------------------------------------------------------------------------------
- &AUTHdelauthority($authid);
+ &DelAuthority($authid);
if ($nonav){
print $input->redirect("auth_finder.pl");
}else{
diff --git a/misc/migration_tools/merge_authority.pl b/misc/migration_tools/merge_authority.pl
index 10d6aff..6345c9d 100755
--- a/misc/migration_tools/merge_authority.pl
+++ b/misc/migration_tools/merge_authority.pl
@@ -11,18 +11,20 @@ BEGIN {
# Koha modules used
use C4::Context;
+use C4::Search;
use C4::Biblio;
use C4::AuthoritiesMarc;
use Time::HiRes qw(gettimeofday);
use Getopt::Long;
-my ($version, $verbose, $mergefrom,$mergeto,$noconfirm);
+my ($version, $verbose, $mergefrom,$mergeto,$noconfirm,$batch);
GetOptions(
'h' => \$version,
'f:s' => \$mergefrom,
't:s' => \$mergeto,
'v' => \$verbose,
'n' => \$noconfirm,
+ 'b' => \$batch,
);
if ($version || ($mergefrom eq '')) {
@@ -34,6 +36,7 @@ parameters :
\tf : the authority number to merge (the one that can be deleted after the merge).
\tt : the authority number where to merge
\tn : don't ask for confirmation (useful for batch mergings, should not be used on command line)
+\tb : batch Merging
All biblios with the authority in -t will be modified to be "connected" to authority -f
SAMPLE :
@@ -49,11 +52,11 @@ my $dbh = C4::Context->dbh;
# my @subf = $subfields =~ /(##\d\d\d##.)/g;
$|=1; # flushes output
-my $authfrom = AUTHgetauthority($mergefrom);
-my $authto = AUTHgetauthority($mergeto);
+my $authfrom = GetAuthority($mergefrom);
+my $authto = GetAuthority($mergeto);
-my $authtypecodefrom = AUTHfind_authtypecode($mergefrom);
-my $authtypecodeto = AUTHfind_authtypecode($mergeto);
+my $authtypecodefrom = GetAuthTypeCode($mergefrom);
+my $authtypecodeto = GetAuthTypeCode($mergeto);
unless ($noconfirm) {
print "************\n";
@@ -71,49 +74,29 @@ unless ($noconfirm) {
}
my $starttime = gettimeofday;
print "Merging\n" unless $noconfirm;
-
-# search the tag to report
-my $sth = $dbh->prepare("select auth_tag_to_report from auth_types where authtypecode=?");
-$sth->execute($authtypecodefrom);
-my ($auth_tag_to_report) = $sth->fetchrow;
-# my $record_to_report = $authto->field($auth_tag_to_report);
-print "Reporting authority tag $auth_tag_to_report :\n" if $verbose;
-my @record_to = $authto->field($auth_tag_to_report)->subfields();
-my @record_from = $authfrom->field($auth_tag_to_report)->subfields();
-
-# search all biblio tags using this authority.
-$sth = $dbh->prepare("select distinct tagfield from marc_subfield_structure where authtypecode=?");
-$sth->execute($authtypecodefrom);
-my $tags_using_authtype;
-while (my ($tagfield) = $sth->fetchrow) {
- $tags_using_authtype.= "'".$tagfield."',";
-}
-chop $tags_using_authtype;
-# now, find every biblio using this authority
-my $query = "select bibid,tag,tag_indicator,tagorder,subfieldcode,subfieldorder from marc_subfield_table where tag in ($tags_using_authtype) and subfieldcode='9' and subfieldvalue='$mergefrom'";
-$sth = $dbh->prepare($query);
-$sth->execute;
-my $nbdone;
-# and delete entries before recreating them
-while (my ($bibid,$tag,$tag_indicator,$tagorder,$subfieldcode,$subfieldorder) = $sth->fetchrow) {
- my $biblio = GetMarcBiblio($bibid);
- print "BEFORE : ".$biblio->as_formatted."\n" if $verbose;
- # now, we know what uses the authority & where.
- # delete all subfields that are in the same tag/tagorder and that are in the authority (& that are not in tab ignore in the biblio)
- # then recreate them with the new authority.
- foreach my $subfield (@record_from) {
- &MARCdelsubfield($bibid,$tag,$tagorder,$subfield->[0]);
- }
- &MARCdelsubfield($dbh,$bibid,$tag,$tagorder,'9');
- foreach my $subfield (@record_to) {
- &MARCaddsubfield($bibid,$tag,$tag_indicator,$tagorder,$subfield->[0],$subfieldorder,$subfield->[1]);
+if ($batch) {
+ my @authlist;
+ my $cgidir = C4::Context->intranetdir ."/cgi-bin";
+ unless (opendir(DIR, "$cgidir/localfile/modified_authorities")) {
+ $cgidir = C4::Context->intranetdir;
+ opendir(DIR, "$cgidir/localfile/modified_authorities") || die "can't opendir $cgidir/localfile/modified_authorities: $!";
+ }
+ while (my $authid = readdir(DIR)) {
+ if ($authid =~ /\.authid$/) {
+ $authid =~ s/\.authid$//;
+ print "managing $authid\n" if $verbose;
+ my $MARCauth = GetAuthority($authid);
+ merge($authid,$MARCauth,$authid,$MARCauth) if ($MARCauth);
+ unlink $cgidir.'/localfile/modified_authorities/'.$authid.'.authid';
}
- &MARCaddsubfield($bibid,$tag,$tag_indicator,$tagorder,'9',$subfieldorder,$mergeto);
- $biblio = GetMarcBiblio($bibid);
- print "AFTER : ".$biblio->as_formatted."\n" if $verbose;
- $nbdone++;
-# &MARCdelsubfield($dbh,$bibid,$tag,$tagorder,$subfieldcode,$subfieldorder);
-
+ }
+ closedir DIR;
+} else {
+ my $MARCfrom = GetAuthority($mergefrom);
+ my $MARCto = GetAuthority($mergeto);
+ &merge($mergefrom,$MARCfrom,$mergeto,$MARCto);
+ #Could add mergefrom authority to mergeto rejected forms before deletion
+ DelAuthority($mergefrom);
}
my $timeneeded = gettimeofday - $starttime;
-print "$nbdone authorities done in $timeneeded seconds" unless $noconfirm;
+print "Done in $timeneeded seconds" unless $noconfirm;
--
1.5.5.GIT
More information about the Koha-patches
mailing list