From c2debcf509cd2cf5fb4fd20cf240c694a7f1c3ea Mon Sep 17 00:00:00 2001 From: rangi Date: Mon, 13 Feb 2006 21:03:21 +0000 Subject: [PATCH] Start of the complete rewrite of Search.pm It just does a simple cql search at the moment, takes a hashref of keyed by variable. I have introduced 2 new variables to koha.conf zebraserver and zebraport Ill add to the installer to get these set. Very very very much a work in progress still. Thanks to paul for getting things up to this point. --- C4/Search.pm | 979 ++------------------------------------------------- 1 file changed, 35 insertions(+), 944 deletions(-) diff --git a/C4/Search.pm b/C4/Search.pm index b3224937e6..6cb3e72721 100755 --- a/C4/Search.pm +++ b/C4/Search.pm @@ -1,6 +1,6 @@ package C4::Search; -# Copyright 2000-2002 Katipo Communications +# Copyright 2000-2006 Katipo Communications # # This file is part of Koha. # @@ -18,14 +18,11 @@ package C4::Search; # Suite 330, Boston, MA 02111-1307 USA use strict; -require Exporter; -use DBI; +use ZOOM; +use Smart::Comments; use C4::Context; -use C4::Reserves2; - # FIXME - C4::Search uses C4::Reserves2, which uses C4::Search. - # So Perl complains that all of the functions here get redefined. -use C4::Date; -use C4::Biblio; + +require Exporter; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); @@ -41,16 +38,11 @@ C4::Search - Functions for searching the Koha catalog and other databases use C4::Search; - my ($count, @results) = catalogsearch($env, $type, $search, $num, $offset); - =head1 DESCRIPTION This module provides the searching facilities for the Koha catalog and other databases. -C<&catalogsearch> is a front end to all the other searches. Depending -on what is passed to it, it calls the appropriate search function. - =head1 FUNCTIONS =over 2 @@ -58,942 +50,41 @@ on what is passed to it, it calls the appropriate search function. =cut @ISA = qw(Exporter); -@EXPORT = qw( - &catalogsearch &KeywordSearch &CatSearch &subsearch -); +@EXPORT = qw(search); # make all your functions, whether exported or not; -=item catalogsearch - - ($count, @results) = &catalogsearch($env, $type, $search, $num, $offset); - -This is primarily a front-end to other, more specialized catalog -search functions: if C<$search-E{itemnumber}> or -C<$search-E{isbn}> is given, C<&catalogsearch> uses a precise -C<&CatSearch>. If $search->{subject} is given, it runs a subject -C<&CatSearch>. If C<$search-E{keyword}> is given, it runs a -C<&KeywordSearch>. Otherwise, it runs a loose C<&CatSearch>. - -If C<$env-E{itemcount}> is 1, then C<&catalogsearch> also counts -the items for each result, and adds several keys: - -=over 4 - -=item C - -The total number of copies of this book. - -=item C - -This is a reference-to-hash; the keys are the names of branches where -this book may be found, and the values are the number of copies at -that branch. - -=item C - -A descriptive string saying where the book is located, and how many -copies there are, if greater than 1. - -=item C - -The book's subject, with spaces replaced with C<%20>, presumably for -HTML. - -=back - -=cut -#' -sub catalogsearch { - my ($env,$type,$search,$num,$offset)=@_; - my $dbh = C4::Context->dbh; - # foreach my $key (%$search){ - # $search->{$key}=$dbh->quote($search->{$key}); - # } - my ($count,@results); - if ($search->{'itemnumber'} ne '' || $search->{'isbn'} ne ''){ - print STDERR "Doing a precise search\n"; - ($count,@results)=CatSearch($env,'precise',$search,$num,$offset); - } elsif ($search->{'subject'} ne ''){ - ($count,@results)=CatSearch($env,'subject',$search,$num,$offset); - } elsif ($search->{'keyword'} ne ''){ - ($count,@results)=&KeywordSearch($env,'keyword',$search,$num,$offset); - } else { - ($count,@results)=CatSearch($env,'loose',$search,$num,$offset); - - } - if ($env->{itemcount} eq '1') { - foreach my $data (@results){ - my ($counts) = itemcount2($env, $data->{'biblionumber'}, 'intra'); - my $subject2=$data->{'subject'}; - $subject2=~ s/ /%20/g; - $data->{'itemcount'}=$counts->{'total'}; - my $totalitemcounts=0; - foreach my $key (keys %$counts){ - if ($key ne 'total'){ # FIXME - Should ignore 'order', too. - #$data->{'location'}.="$key $counts->{$key} "; - $totalitemcounts+=$counts->{$key}; - $data->{'locationhash'}->{$key}=$counts->{$key}; - } - } - my $locationtext=''; - my $locationtextonly=''; - my $notavailabletext=''; - foreach (sort keys %{$data->{'locationhash'}}) { - if ($_ eq 'notavailable') { - $notavailabletext="Not available"; - my $c=$data->{'locationhash'}->{$_}; - $data->{'not-available-p'}=$totalitemcounts; - if ($totalitemcounts>1) { - $notavailabletext.=" ($c)"; - $data->{'not-available-plural-p'}=1; - } - } else { - $locationtext.="$_"; - my $c=$data->{'locationhash'}->{$_}; - if ($_ eq 'Item Lost') { - $data->{'lost-p'}=$totalitemcounts; - $data->{'lost-plural-p'}=1 - if $totalitemcounts > 1; - } elsif ($_ eq 'Withdrawn') { - $data->{'withdrawn-p'}=$totalitemcounts; - $data->{'withdrawn-plural-p'}=1 - if $totalitemcounts > 1; - } elsif ($_ eq 'On Loan') { - $data->{'on-loan-p'}=$totalitemcounts; - $data->{'on-loan-plural-p'}=1 - if $totalitemcounts > 1; - } else { - $locationtextonly.=$_; - $locationtextonly.=" ($c), " - if $totalitemcounts>1; - } - if ($totalitemcounts>1) { - $locationtext.=" ($c), "; - } - } - } - if ($notavailabletext) { - $locationtext.=$notavailabletext; - } else { - $locationtext=~s/, $//; - } - $data->{'location'}=$locationtext; - $data->{'location-only'}=$locationtextonly; - $data->{'subject2'}=$subject2; - $data->{'use-location-flags-p'}=1; # XXX - } - } - return ($count,@results); -} - -=item KeywordSearch - - $search = { "keyword" => "One or more keywords", - "class" => "VID|CD", # Limit search to fiction and CDs - "dewey" => "813", - }; - ($count, @results) = &KeywordSearch($env, $type, $search, $num, $offset); - -C<&KeywordSearch> searches the catalog by keyword: given a string -(C<$search-E{"keyword"}> consisting of a space-separated list of -keywords, it looks for books that contain any of those keywords in any -of a number of places. - -C<&KeywordSearch> looks for keywords in the book title (and subtitle), -series name, notes (both C and C), -and subjects. - -C<$search-E{"class"}> can be set to a C<|> (pipe)-separated list of -item class codes (e.g., "F" for fiction, "JNF" for junior nonfiction, -etc.). In this case, the search will be restricted to just those -classes. - -If C<$search-E{"class"}> is not specified, you may specify -C<$search-E{"dewey"}>. This will restrict the search to that -particular Dewey Decimal Classification category. Setting -C<$search-E{"dewey"}> to "513" will return books about arithmetic, -whereas setting it to "5" will return all books with Dewey code 5I -(Science and Mathematics). - -C<$env> and C<$type> are ignored. - -C<$offset> and C<$num> specify the subset of results to return. -C<$num> specifies the number of results to return, and C<$offset> is -the number of the first result. Thus, setting C<$offset> to 100 and -C<$num> to 5 will return results 100 through 104 inclusive. - -=cut -#' -sub KeywordSearch { - my ($env,$type,$search,$num,$offset)=@_; - my $dbh = C4::Context->dbh; - $search->{'keyword'}=~ s/ +$//; - my @key=split(' ',$search->{'keyword'}); - # FIXME - Naive users might enter comma-separated - # words, e.g., "training, animal". Ought to cope with - # this. - my $count=@key; - my $i=1; - my %biblionumbers; # Set of biblionumbers returned by the - # various searches. - - # FIXME - Ought to filter the stopwords out of the list of keywords. - # @key = map { !defined($stopwords{$_}) } @key; - - # FIXME - The way this code is currently set up, it looks for all of - # the keywords first in (title, notes, seriestitle), then in the - # subtitle, then in the subject. Thus, if you look for keywords - # "science fiction", this search won't find a book with - # title = "How to write fiction" - # subtitle = "A science-based approach" - # Is this the desired effect? If not, then the first SQL query - # should look in the biblio, subtitle, and subject tables all at - # once. The way the first query is built can accomodate this easily. - - # Look for keywords in table 'biblio'. - - # Build an SQL query that finds each of the keywords in any of the - # title, biblio.notes, or seriestitle. To do this, we'll build up an - # array of clauses, one for each keyword. - my $query; # The SQL query - my @clauses = (); # The search clauses - my @bind = (); # The term bindings - - $query = <bind_columns() ? Documented as the most - # efficient way to fetch data. - my $sth=$dbh->prepare($query); - $sth->execute(@bind); - while (my @res = $sth->fetchrow_array) { - for (@res) - { - $biblionumbers{$_} = 1; # Add these results to the set - } - } - $sth->finish; - - # Now look for keywords in the 'bibliosubtitle' table. - - # Again, we build a list of clauses from the keywords. - @clauses = (); - @bind = (); - $query = "SELECT biblionumber FROM bibliosubtitle WHERE "; - foreach my $keyword (@key) - { - push @clauses, - "subtitle LIKE ? OR subtitle like ?"; - push(@bind,"\Q$keyword\E%","% \Q$keyword\E%"); - } - $query .= "(" . join(") AND (", @clauses) . ")"; - - $sth=$dbh->prepare($query); - $sth->execute(@bind); - while (my @res = $sth->fetchrow_array) { - for (@res) - { - $biblionumbers{$_} = 1; # Add these results to the set - } - } - $sth->finish; - - # Look for the keywords in the notes for individual items - # ('biblioitems.notes') - - # Again, we build a list of clauses from the keywords. - @clauses = (); - @bind = (); - $query = "SELECT biblionumber FROM biblioitems WHERE "; - foreach my $keyword (@key) - { - push @clauses, - "notes LIKE ? OR notes like ?"; - push(@bind,"\Q$keyword\E%","% \Q$keyword\E%"); - } - $query .= "(" . join(") AND (", @clauses) . ")"; - - $sth=$dbh->prepare($query); - $sth->execute(@bind); - while (my @res = $sth->fetchrow_array) { - for (@res) - { - $biblionumbers{$_} = 1; # Add these results to the set - } - } - $sth->finish; - - # Look for keywords in the 'bibliosubject' table. - - # FIXME - The other queries look for words in the desired field that - # begin with the individual keywords the user entered. This one - # searches for the literal string the user entered. Is this the - # desired effect? - # Note in particular that spaces are retained: if the user typed - # science fiction - # (with two spaces), this won't find the subject "science fiction" - # (one space). Likewise, a search for "%" will return absolutely - # everything. - # If this isn't the desired effect, see the previous searches for - # how to do it. - - $sth=$dbh->prepare("Select biblionumber from bibliosubject where subject - like ? group by biblionumber"); - $sth->execute("%$search->{'keyword'}%"); - - while (my @res = $sth->fetchrow_array) { - for (@res) - { - $biblionumbers{$_} = 1; # Add these results to the set +sub search { + my ($search,$type)=@_; + my $q; + my $host=C4::Context->config("zebraserver"); + my $port=C4::Context->config("zebraport"); + my $intranetdir=C4::Context->config("intranetdir"); + my $Zconn; + eval { + $Zconn = new ZOOM::Connection($host,$port); + }; + if ($@) { + warn "Error ", $@->code(), ": ", $@->message(), "\n"; } - } - $sth->finish; - - my $i2=0; - my $i3=0; - my $i4=0; - - my @res2; - my @res = keys %biblionumbers; - $count=@res; - - $i=0; -# print "count $count"; - if ($search->{'class'} ne ''){ - while ($i2 <$count){ - my $query="select * from biblio,biblioitems where - biblio.biblionumber=? and - biblio.biblionumber=biblioitems.biblionumber "; - my @bind = ($res[$i2]); - if ($search->{'class'} ne ''){ # FIXME - Redundant - my @temp=split(/\|/,$search->{'class'}); - my $count=@temp; - $query.= "and ( itemtype=?"; - push(@bind,$temp[0]); - for (my $i=1;$i<$count;$i++){ - $query.=" or itemtype=?"; - push(@bind,$temp[$i]); - } - $query.=")"; - } - my $sth=$dbh->prepare($query); - # print $query; - $sth->execute(@bind); - if (my $data2=$sth->fetchrow_hashref){ - my $dewey= $data2->{'dewey'}; - my $subclass=$data2->{'subclass'}; - # FIXME - This next bit is bogus, because it assumes that the - # Dewey code is a floating-point number. It isn't. It's - # actually a string that mainly consists of numbers. In - # particular, "4" is not a valid Dewey code, although "004" - # is ("Data processing; Computer science"). Likewise, zeros - # after the decimal are significant ("575" is not the same as - # "575.0"; the latter is more specific). And "000" is a - # perfectly good Dewey code ("General works; computer - # science") and should not be interpreted to mean "this - # database entry does not have a Dewey code". That's what - # NULL is for. - $dewey=~s/\.*0*$//; - ($dewey == 0) && ($dewey=''); - ($dewey) && ($dewey.=" $subclass") ; - $sth->finish; - my $end=$offset +$num; - if ($i4 <= $offset){ - $i4++; - } -# print $i4; - if ($i4 <=$end && $i4 > $offset){ - $data2->{'dewey'}=$dewey; - $res2[$i3]=$data2; - -# $res2[$i3]="$data2->{'author'}\t$data2->{'title'}\t$data2->{'biblionumber'}\t$data2->{'copyrightdate'}\t$dewey"; - $i3++; - $i4++; -# print "in here $i3
"; - } else { -# print $end; - } - $i++; - } - $i2++; - } - $count=$i; - - } else { - # $search->{'class'} was not specified - - # FIXME - This is bogus: it makes a separate query for each - # biblioitem, and returns results in apparently random order. It'd - # be much better to combine all of the previous queries into one big - # one (building it up a little at a time, of course), and have that - # big query select all of the desired fields, instead of just - # 'biblionumber'. - - while ($i2 < $num && $i2 < $count){ - my $query="select * from biblio,biblioitems where - biblio.biblionumber=? and - biblio.biblionumber=biblioitems.biblionumber "; - my @bind=($res[$i2+$offset]); - - if ($search->{'dewey'} ne ''){ - $query.= "and (dewey like ?)"; - push(@bind,"$search->{'dewey'}%"); - } - - my $sth=$dbh->prepare($query); -# print $query; - $sth->execute(@bind); - if (my $data2=$sth->fetchrow_hashref){ - my $dewey= $data2->{'dewey'}; - my $subclass=$data2->{'subclass'}; - $dewey=~s/\.*0*$//; - ($dewey == 0) && ($dewey=''); - ($dewey) && ($dewey.=" $subclass") ; - $sth->finish; - $data2->{'dewey'}=$dewey; - - $res2[$i]=$data2; -# $res2[$i]="$data2->{'author'}\t$data2->{'title'}\t$data2->{'biblionumber'}\t$data2->{'copyrightdate'}\t$dewey"; - $i++; - } - $i2++; - - } - } - - #$count=$i; - return($count,@res2); -} - -=item CatSearch - - ($count, @results) = &CatSearch($env, $type, $search, $num, $offset); - -C<&CatSearch> searches the Koha catalog. It returns a list whose first -element is the number of returned results, and whose subsequent -elements are the results themselves. - -Each returned element is a reference-to-hash. Most of the keys are -simply the fields from the C table in the Koha database, but -the following keys may also be present: - -=over 4 - -=item C - -The book's illustrator. - -=item C - -The publisher. - -=back - -C<$env> is ignored. - -C<$type> may be C, C, or C. This controls the -high-level behavior of C<&CatSearch>, as described below. - -In many cases, the description below says that a certain field in the -database must match the search string. In these cases, it means that -the beginning of some word in the field must match the search string. -Thus, an author search for "sm" will return books whose author is -"John Smith" or "Mike Smalls", but not "Paul Grossman", since the "sm" -does not occur at the beginning of a word. - -Note that within each search mode, the criteria are and-ed together. -That is, if you perform a loose search on the author "Jerome" and the -title "Boat", the search will only return books by Jerome containing -"Boat" in the title. - -It is not possible to cross modes, e.g., set the author to "Asimov" -and the subject to "Math" in hopes of finding books on math by Asimov. - -=head2 Loose search - -If C<$type> is set to C, the following search criteria may be -used: - -=over 4 - -=item C<$search-E{author}> - -The search string is a space-separated list of words. Each word must -match either the C or C field. - -=item C<$search-E{title}> - -Each word in the search string must match the book title. If no author -is specified, the book subtitle will also be searched. - -=item C<$search-E{abstract}> - -Searches for the given search string in the book's abstract. - -=item C<$search-E{'date-before'}> - -Searches for books whose copyright date matches the search string. -That is, setting C<$search-E{'date-before'}> to "1985" will find -books written in 1985, and setting it to "198" will find books written -between 1980 and 1989. - -=item C<$search-E{title}> - -Searches by title are also affected by the value of -C<$search-E{"ttype"}>; if it is set to C, then the book -title, (one of) the series titleZ<>(s), or (one of) the unititleZ<>(s) must -match the search string exactly (the subtitle is not searched). - -If C<$search-E{"ttype"}> is set to anything other than C, -each word in the search string must match the title, subtitle, -unititle, or series title. - -=item C<$search-E{class}> - -Restricts the search to certain item classes. The value of -C<$search-E{"class"}> is a | (pipe)-separated list of item types. -Thus, setting it to "F" restricts the search to fiction, and setting -it to "CD|CAS" will only look in compact disks and cassettes. - -=item C<$search-E{dewey}> - -Searches for books whose Dewey Decimal Classification code matches the -search string. That is, setting C<$search-E{"dewey"}> to "5" will -search for all books in 5I (Science and mathematics), setting it -to "54" will search for all books in 54I (Chemistry), and setting -it to "546" will search for books on inorganic chemistry. - -=item C<$search-E{publisher}> - -Searches for books whose publisher contains the search string (unlike -other search criteria, C<$search-E{publisher}> is a string, not a -set of words. - -=back - -=head2 Subject search - -If C<$type> is set to C, the following search criterion may -be used: - -=over 4 - -=item C<$search-E{subject}> - -The search string is a space-separated list of words, each of which -must match the book's subject. - -Special case: if C<$search-E{subject}> is set to C, -C<&CatSearch> will search for books whose subject is "New Zealand". -However, setting C<$search-E{subject}> to C<"nz football"> will -search for books on "nz" and "football", not books on "New Zealand" -and "football". - -=back - -=head2 Precise search - -If C<$type> is set to C, the following search criteria may be -used: - -=over 4 - -=item C<$search-E{item}> - -Searches for books whose barcode exactly matches the search string. - -=item C<$search-E{isbn}> - -Searches for books whose ISBN exactly matches the search string. - -=back - -For a loose search, if an author was specified, the results are -ordered by author and title. If no author was specified, the results -are ordered by title. - -For other (non-loose) searches, if a subject was specified, the -results are ordered alphabetically by subject. - -In all other cases (e.g., loose search by keyword), the results are -not ordered. - -=cut -#' -sub CatSearch { - my ($env,$type,$search,$num,$offset)=@_; - my $dbh = C4::Context->dbh; - my $query = ''; - my @bind = (); - my @results; - - my $title = lc($search->{'title'}); - - if ($type eq 'loose') { - if ($search->{'author'} ne ''){ - my @key=split(' ',$search->{'author'}); - my $count=@key; - my $i=1; - $query="select *,biblio.author,biblio.biblionumber from - biblio - left join additionalauthors - on additionalauthors.biblionumber =biblio.biblionumber - where - ((biblio.author like ? or biblio.author like ? or - additionalauthors.author like ? or additionalauthors.author - like ? - )"; - @bind=("$key[0]%","% $key[0]%","$key[0]%","% $key[0]%"); - while ($i < $count){ - $query .= " and ( - biblio.author like ? or biblio.author like ? or - additionalauthors.author like ? or additionalauthors.author like ? - )"; - push(@bind,"$key[$i]%","% $key[$i]%","$key[$i]%","% $key[$i]%"); - $i++; - } - $query .= ")"; - if ($search->{'title'} ne ''){ - my @key=split(' ',$search->{'title'}); - my $count=@key; - my $i=0; - $query.= " and (((title like ? or title like ?)"; - push(@bind,"$key[0]%","% $key[0]%"); - while ($i<$count){ - $query .= " and (title like ? or title like ?)"; - push(@bind,"$key[$i]%","% $key[$i]%"); - $i++; - } - $query.=") or ((seriestitle like ? or seriestitle like ?)"; - push(@bind,"$key[0]%","% $key[0]%"); - for ($i=1;$i<$count;$i++){ - $query.=" and (seriestitle like ? or seriestitle like ?)"; - push(@bind,"$key[$i]%","% $key[$i]%"); - } - $query.=") or ((unititle like ? or unititle like ?)"; - push(@bind,"$key[0]%","% $key[0]%"); - for ($i=1;$i<$count;$i++){ - $query.=" and (unititle like ? or unititle like ?)"; - push(@bind,"$key[$i]%","% $key[$i]%"); - } - $query .= "))"; - } - if ($search->{'abstract'} ne ''){ - $query.= " and (abstract like ?)"; - push(@bind,"%$search->{'abstract'}%"); - } - if ($search->{'date-before'} ne ''){ - $query.= " and (copyrightdate like ?)"; - push(@bind,"%$search->{'date-before'}%"); - } - $query.=" group by biblio.biblionumber"; - } else { - if ($search->{'title'} ne '') { - if ($search->{'ttype'} eq 'exact'){ - $query="select * from biblio - where - (biblio.title=? or (biblio.unititle = ? - or biblio.unititle like ? or - biblio.unititle like ? or - biblio.unititle like ?) or - (biblio.seriestitle = ? or - biblio.seriestitle like ? or - biblio.seriestitle like ? or - biblio.seriestitle like ?) - )"; - @bind=($search->{'title'},$search->{'title'},"$search->{'title'} |%","%| $search->{'title'} |%","%| $search->{'title'}",$search->{'title'},"$search->{'title'} |%","%| $search->{'title'} |%","%| $search->{'title'}"); - } else { - my @key=split(' ',$search->{'title'}); - my $count=@key; - my $i=1; - $query="select biblio.biblionumber,author,title,unititle,notes,abstract,serial,seriestitle,copyrightdate,timestamp,subtitle from biblio - left join bibliosubtitle on - biblio.biblionumber=bibliosubtitle.biblionumber - where - (((title like ? or title like ?)"; - @bind=("$key[0]%","% $key[0]%"); - while ($i<$count){ - $query .= " and (title like ? or title like ?)"; - push(@bind,"$key[$i]%","% $key[$i]%"); - $i++; - } - $query.=") or ((subtitle like ? or subtitle like ?)"; - push(@bind,"$key[0]%","% $key[0]%"); - for ($i=1;$i<$count;$i++){ - $query.=" and (subtitle like ? or subtitle like ?)"; - push(@bind,"$key[$i]%","% $key[$i]%"); - } - $query.=") or ((seriestitle like ? or seriestitle like ?)"; - push(@bind,"$key[0]%","% $key[0]%"); - for ($i=1;$i<$count;$i++){ - $query.=" and (seriestitle like ? or seriestitle like ?)"; - push(@bind,"$key[$i]%","% $key[$i]%"); - } - $query.=") or ((unititle like ? or unititle like ?)"; - push(@bind,"$key[0]%","% $key[0]%"); - for ($i=1;$i<$count;$i++){ - $query.=" and (unititle like ? or unititle like ?)"; - push(@bind,"$key[$i]%","% $key[$i]%"); - } - $query .= "))"; - } - if ($search->{'abstract'} ne ''){ - $query.= " and (abstract like ?)"; - push(@bind,"%$search->{'abstract'}%"); - } - if ($search->{'date-before'} ne ''){ - $query.= " and (copyrightdate like ?)"; - push(@bind,"%$search->{'date-before'}%"); - } - } elsif ($search->{'class'} ne ''){ - $query="select * from biblioitems,biblio where biblio.biblionumber=biblioitems.biblionumber"; - my @temp=split(/\|/,$search->{'class'}); - my $count=@temp; - $query.= " and ( itemtype= ?)"; - @bind=($temp[0]); - for (my $i=1;$i<$count;$i++){ - $query.=" or itemtype=?"; - push(@bind,$temp[$i]); - } - $query.=")"; - if ($search->{'illustrator'} ne ''){ - $query.=" and illus like ?"; - push(@bind,"%".$search->{'illustrator'}."%"); - } - if ($search->{'dewey'} ne ''){ - $query.=" and biblioitems.dewey like ?"; - push(@bind,"$search->{'dewey'}%"); - } - } elsif ($search->{'dewey'} ne ''){ - $query="select * from biblioitems,biblio - where biblio.biblionumber=biblioitems.biblionumber - and biblioitems.dewey like ?"; - @bind=("$search->{'dewey'}%"); - } elsif ($search->{'illustrator'} ne '') { - $query="select * from biblioitems,biblio - where biblio.biblionumber=biblioitems.biblionumber - and biblioitems.illus like ?"; - @bind=("%".$search->{'illustrator'}."%"); - } elsif ($search->{'publisher'} ne ''){ - $query = "Select * from biblio,biblioitems where biblio.biblionumber - =biblioitems.biblionumber and (publishercode like ?)"; - @bind=("%$search->{'publisher'}%"); - } elsif ($search->{'abstract'} ne ''){ - $query = "Select * from biblio where abstract like ?"; - @bind=("%$search->{'abstract'}%"); - } elsif ($search->{'date-before'} ne ''){ - $query = "Select * from biblio where copyrightdate like ?"; - @bind=("%$search->{'date-before'}%"); - } - $query .=" group by biblio.biblionumber"; - } - } - if ($type eq 'subject'){ - my @key=split(' ',$search->{'subject'}); - my $count=@key; - my $i=1; - $query="select * from bibliosubject, biblioitems where -(bibliosubject.biblionumber = biblioitems.biblionumber) and ( subject like ? or subject like ? or subject like ?)"; - @bind=("$key[0]%","% $key[0]%","%($key[0])%"); - while ($i<$count){ - $query.=" and (subject like ? or subject like ? or subject like ?)"; - push(@bind,"$key[$i]%","% $key[$i]%","%($key[$i])%"); - $i++; - } - - # FIXME - Wouldn't it be better to fix the database so that if a - # book has a subject "NZ", then it also gets added the subject - # "New Zealand"? - # This can also be generalized by adding a table of subject - # synonyms to the database: just declare "NZ" to be a synonym for - # "New Zealand", "SF" a synonym for both "Science fiction" and - # "Fantastic fiction", etc. - - if (lc($search->{'subject'}) eq 'nz'){ - $query.= " or (subject like 'NEW ZEALAND %' or subject like '% NEW ZEALAND %' - or subject like '% NEW ZEALAND' or subject like '%(NEW ZEALAND)%' ) "; - } elsif ( $search->{'subject'} =~ /^nz /i || $search->{'subject'} =~ / nz /i || $search->{'subject'} =~ / nz$/i){ - $query=~ s/ nz/ NEW ZEALAND/ig; - $query=~ s/nz /NEW ZEALAND /ig; - $query=~ s/\(nz\)/\(NEW ZEALAND\)/gi; - } + + if ($type eq 'CQL'){ + my $string; + foreach my $var (keys %$search) { + $string.="$var=\"$search->{$var}\" "; + } + $Zconn->option(cqlfile => "$intranetdir/zebra/pqf.properties"); + $Zconn->option(preferredRecordSyntax => "xml"); + $q = new ZOOM::Query::CQL2RPN( $string, $Zconn); } - if ($type eq 'precise'){ - if ($search->{'itemnumber'} ne ''){ - $query="select * from items,biblio "; - my $search2=uc $search->{'itemnumber'}; - $query=$query." where - items.biblionumber=biblio.biblionumber - and barcode=?"; - @bind=($search2); - # FIXME - .= <{'isbn'} ne ''){ - my $search2=uc $search->{'isbn'}; - my $sth1=$dbh->prepare("select * from biblioitems where isbn=?"); - $sth1->execute($search2); - my $i2=0; - while (my $data=$sth1->fetchrow_hashref) { - my $sth=$dbh->prepare("select * from biblioitems,biblio where - biblio.biblionumber = ? - and biblioitems.biblionumber = biblio.biblionumber"); - $sth->execute($data->{'biblionumber'}); - # FIXME - There's already a $data in this scope. - my $data=$sth->fetchrow_hashref; - my ($dewey, $subclass) = ($data->{'dewey'}, $data->{'subclass'}); - # FIXME - The following assumes that the Dewey code is a - # floating-point number. It isn't: it's a string. - $dewey=~s/\.*0*$//; - ($dewey == 0) && ($dewey=''); - ($dewey) && ($dewey.=" $subclass"); - $data->{'dewey'}=$dewey; - $results[$i2]=$data; - # $results[$i2]="$data->{'author'}\t$data->{'title'}\t$data->{'biblionumber'}\t$data->{'copyrightdate'}\t$dewey\t$data->{'isbn'}\t$data->{'itemtype'}"; - $i2++; - $sth->finish; - } - $sth1->finish; - } - } - if ($type ne 'precise' && $type ne 'subject'){ - if ($search->{'author'} ne ''){ - $query .= " order by biblio.author,title"; - } else { - $query .= " order by title"; - } - } else { - if ($type eq 'subject'){ - $query .= " group by subject "; - } - } - my $sth=$dbh->prepare($query); - $sth->execute(@bind); - my $count=1; - my $i=0; - my $limit= $num+$offset; - while (my $data=$sth->fetchrow_hashref){ - my $query="select classification,dewey,subclass,publishercode from biblioitems where biblionumber=?"; - my @bind=($data->{'biblionumber'}); - if ($search->{'class'} ne ''){ - my @temp=split(/\|/,$search->{'class'}); - my $count=@temp; - $query.= " and ( itemtype= ?"; - push(@bind,$temp[0]); - for (my $i=1;$i<$count;$i++){ - $query.=" or itemtype=?"; - push(@bind,$temp[$i]); - } - $query.=")"; - } - if ($search->{'dewey'} ne ''){ - $query.=" and dewey=? "; - push(@bind,$search->{'dewey'}); - } - if ($search->{'illustrator'} ne ''){ - $query.=" and illus like ?"; - push(@bind,"%$search->{'illustrator'}%"); - } - if ($search->{'publisher'} ne ''){ - $query.= " and (publishercode like ?)"; - push(@bind,"%$search->{'publisher'}%"); - } - my $sti=$dbh->prepare($query); - $sti->execute(@bind); - my $classification; - my $dewey; - my $subclass; - my $true=0; - my $publishercode; - my $bibitemdata; - if ($bibitemdata = $sti->fetchrow_hashref()){ - $true=1; - $classification=$bibitemdata->{'classification'}; - $dewey=$bibitemdata->{'dewey'}; - $subclass=$bibitemdata->{'subclass'}; - $publishercode=$bibitemdata->{'publishercode'}; - } - # print STDERR "$dewey $subclass $publishercode\n"; - # FIXME - The Dewey code is a string, not a number. - $dewey=~s/\.*0*$//; - ($dewey == 0) && ($dewey=''); - ($dewey) && ($dewey.=" $subclass"); - $data->{'classification'}=$classification; - $data->{'dewey'}=$dewey; - $data->{'publishercode'}=$publishercode; - $sti->finish; - if ($true == 1){ - if ($count > $offset && $count <= $limit){ - $results[$i]=$data; - $i++; - } - $count++; - } - } - $sth->finish; - $count--; - return($count,@results); -} - -=item subsearch - - @results = &subsearch($env, $subject); - -Searches for books that have a subject that exactly matches -C<$subject>. - -C<&subsearch> returns an array of results. Each element of this array -is a string, containing the book's title, author, and biblionumber, -separated by tabs. - -C<$env> is ignored. - -=cut -#' -sub subsearch { - my ($env,$subject)=@_; - my $dbh = C4::Context->dbh; - my $sth=$dbh->prepare("Select * from biblio,bibliosubject where - biblio.biblionumber=bibliosubject.biblionumber and - bibliosubject.subject=? group by biblio.biblionumber - order by biblio.title"); - $sth->execute($subject); - my $i=0; - my @results; - while (my $data=$sth->fetchrow_hashref){ - push @results, $data; - $i++; - } - $sth->finish; - return(@results); + eval { + my $rs = $Zconn->search($q); + my $n = $rs->size(); + ###$rs->record(0)->render(); + }; + if ($@) { + print "Error ", $@->code(), ": ", $@->message(), "\n"; + } } - -END { } # module clean-up code here (global destructor) - 1; __END__ -- 2.39.5