Searches with NOT are now fully functionnal

Can create SQL request for any number of statements.
FIXED: splits entry if operator is "contains" and the value is like "foo bar boo"
This commit is contained in:
plugz 2003-07-08 11:59:08 +00:00
parent b72c761a02
commit d3ccb3148f

View file

@ -65,96 +65,139 @@ sub catalogsearch {
# where m1.bibid=m2.bibid and # where m1.bibid=m2.bibid and
# (m1.subfieldvalue like "Des%" and m2.subfieldvalue like "27%") # (m1.subfieldvalue like "Des%" and m2.subfieldvalue like "27%")
my $sql_tables; # will contain marc_subfield_table as m1,... # "Normal" statements
my $sql_where1; # will contain the "true" where my @normal_tags = ();
my $sql_where2; # will contain m1.bibid=m2.bibid my @normal_subfields = ();
my $nb_active=0; # will contain the number of "active" entries. and entry is active is a value is provided. my @normal_and_or = ();
my $nb_table=1; # will contain the number of table. ++ on each entry EXCEPT when an OR is provided. my @normal_operator = ();
my @normal_value = ();
for(my $i=0; $i<=@$value;$i++) { # Extracts the NOT statements from the list of statements
if (@$value[$i]) { my @not_tags = ();
$nb_active++; my @not_subfields = ();
if ($nb_active==1) { my @not_and_or = ();
if (@$operator[$i] eq "start") { my @not_operator = ();
$sql_tables .= "marc_subfield_table as m$nb_table,"; my @not_value = ();
$sql_where1 .= "@$excluding[$i](m1.subfieldvalue like '@$value[$i]%'"; my $any_not = 0;
if (@$tags[$i]) {
$sql_where1 .=" and m1.tag=@$tags[$i] and m1.subfieldcode='@$subfields[$i]'"; for(my $i = 0 ; $i <= $#{$value} ; $i++)
{
if(@$excluding[$i]) # NOT statements
{
$any_not = 1;
if(@$operator[$i] eq "contains")
{
foreach my $word (split(/ /, @$value[$i])) # if operator is contains, splits the words in separate requests
{
push @not_tags, @$tags[$i];
push @not_subfields, @$subfields[$i];
push @not_and_or, "or"; # as request is negated, finds "foo" or "bar" if final request is NOT "foo" and "bar"
push @not_operator, @$operator[$i];
push @not_value, $word;
} }
$sql_where1.=")";
} elsif (@$operator[$i] eq "contains") {
$sql_tables .= "marc_word as m$nb_table,";
$sql_where1 .= "@$excluding[$i](m1.word like '@$value[$i]%'";
if (@$tags[$i]) {
$sql_where1 .=" and m1.tag=@$tags[$i] and m1.subfieldid='@$subfields[$i]'";
} }
$sql_where1.=")"; else
} else { {
$sql_tables .= "marc_subfield_table as m$nb_table,"; push @not_tags, @$tags[$i];
$sql_where1 .= "@$excluding[$i](m1.subfieldvalue @$operator[$i] '@$value[$i]' "; push @not_subfields, @$subfields[$i];
if (@$tags[$i]) { push @not_and_or, "or"; # as request is negated, finds "foo" or "bar" if final request is NOT "foo" and "bar"
$sql_where1 .=" and m1.tag=@$tags[$i] and m1.subfieldcode='@$subfields[$i]'"; push @not_operator, @$operator[$i];
push @not_value, @$value[$i];
} }
$sql_where1.=")";
} }
} else { else # NORMAL statements
if (@$operator[$i] eq "start") { {
$nb_table++; if(@$operator[$i] eq "contains") # if operator is contains, splits the words in separate requests
$sql_tables .= "marc_subfield_table as m$nb_table,"; {
$sql_where1 .= "@$and_or[$i] @$excluding[$i](m$nb_table.subfieldvalue like '@$value[$i]%'"; foreach my $word (split(/ /, @$value[$i]))
if (@$tags[$i]) { {
$sql_where1 .=" and m$nb_table.tag=@$tags[$i] and m$nb_table.subfieldcode='@$subfields[$i])"; push @normal_tags, @$tags[$i];
push @normal_subfields, @$subfields[$i];
push @normal_and_or, "and"; # assumes "foo" and "bar" if "foo bar" is entered
push @normal_operator, @$operator[$i];
push @normal_value, $word;
} }
$sql_where1.=")";
$sql_where2 .= "m1.bibid=m$nb_table.bibid";
} elsif (@$operator[$i] eq "contains") {
if (@$and_or[$i] eq 'and') {
$nb_table++;
$sql_tables .= "marc_word as m$nb_table,";
$sql_where1 .= "@$and_or[$i] @$excluding[$i](m$nb_table.word like '@$value[$i]%'";
if (@$tags[$i]) {
$sql_where1 .=" and m$nb_table.tag=@$tags[$i] and m$nb_table.subfieldid='@$subfields[$i]'";
} }
$sql_where1.=")"; else
$sql_where2 .= "m1.bibid=m$nb_table.bibid"; {
} else { push @normal_tags, @$tags[$i];
$sql_where1 .= "@$and_or[$i] @$excluding[$i](m$nb_table.word like '@$value[$i]%'"; push @normal_subfields, @$subfields[$i];
if (@$tags[$i]) { push @normal_and_or, @$and_or[$i];
$sql_where1 .=" and m$nb_table.tag=@$tags[$i] and m$nb_table.subfieldid='@$subfields[$i]'"; push @normal_operator, @$operator[$i];
} push @normal_value, @$value[$i];
$sql_where1.=")";
$sql_where2 .= "m1.bibid=m$nb_table.bibid";
}
} else {
$nb_table++;
$sql_tables .= "marc_subfield_table as m$nb_table,";
$sql_where1 .= "@$and_or[$i] @$excluding[$i](m$nb_table.subfieldvalue @$operator[$i] '@$value[$i]'";
if (@$tags[$i]) {
$sql_where1 .=" and m$nb_table.tag=@$tags[$i] and m$nb_table.subfieldcode='@$subfields[$i]'";
}
$sql_where2 .= "m1.bibid=m$nb_table.bibid";
$sql_where1.=")";
} }
} }
} }
}
chop $sql_tables; # Finds the basic results without the NOT requests
my ($sql_tables, $sql_where1, $sql_where2) = create_request(\@normal_tags, \@normal_subfields, \@normal_and_or, \@normal_operator, \@normal_value);
my $sth; my $sth;
# warn "HERE (NORMAL)";
if ($sql_where2) { if ($sql_where2) {
$sth = $dbh->prepare("select distinct m1.bibid from $sql_tables where $sql_where2 and ($sql_where1)"); $sth = $dbh->prepare("select distinct m1.bibid from $sql_tables where $sql_where2 and ($sql_where1)");
# warn("-->select m1.bibid from $sql_tables where $sql_where2 and ($sql_where1)");
} else { } else {
$sth = $dbh->prepare("select distinct m1.bibid from $sql_tables where $sql_where1"); $sth = $dbh->prepare("select distinct m1.bibid from $sql_tables where $sql_where1");
# warn("==>select m1.bibid from $sql_tables where $sql_where1");
} }
$sth->execute;
my @result; $sth->execute();
my @result = ();
# Processes the NOT if any and there are results
my ($not_sql_tables, $not_sql_where1, $not_sql_where2);
if( ($sth->rows) && $any_not ) # some results to tune up and some NOT statements
{
($not_sql_tables, $not_sql_where1, $not_sql_where2) = create_request(\@not_tags, \@not_subfields, \@not_and_or, \@not_operator, \@not_value);
my @tmpresult;
while (my ($bibid) = $sth->fetchrow) {
push @tmpresult,$bibid;
}
my $sth_not;
# warn "HERE (NOT)";
if ($not_sql_where2) {
$sth_not = $dbh->prepare("select distinct m1.bibid from $not_sql_tables where $not_sql_where2 and ($not_sql_where1)");
# warn("-->select m1.bibid from $not_sql_tables where $not_sql_where2 and ($not_sql_where1)");
} else {
$sth_not = $dbh->prepare("select distinct m1.bibid from $not_sql_tables where $not_sql_where1");
# warn("==>select m1.bibid from $not_sql_tables where $not_sql_where1");
}
$sth_not->execute();
if($sth_not->rows)
{
my %not_bibids = ();
while(my $bibid = $sth_not->fetchrow()) {
$not_bibids{$bibid} = 1; # populates the hashtable with the bibids matching the NOT statement
}
foreach my $bibid (@tmpresult)
{
if(!$not_bibids{$bibid})
{
push @result, $bibid;
}
}
}
$sth_not->finish();
}
else # no NOT statements
{
while (my ($bibid) = $sth->fetchrow) { while (my ($bibid) = $sth->fetchrow) {
push @result,$bibid; push @result,$bibid;
} }
}
# we have bibid list. Now, loads title and author from [offset] to [offset]+[length] # we have bibid list. Now, loads title and author from [offset] to [offset]+[length]
my $counter = $offset; my $counter = $offset;
$sth = $dbh->prepare("select author,title from biblio,marc_biblio where biblio.biblionumber=marc_biblio.biblionumber and bibid=?"); $sth = $dbh->prepare("select author,title from biblio,marc_biblio where biblio.biblionumber=marc_biblio.biblionumber and bibid=?");
my @finalresult = (); my @finalresult = ();
while ($counter <= ($offset + $length)) { while (($counter <= $#result) && ($counter <= ($offset + $length))) {
$sth->execute($result[$counter]); $sth->execute($result[$counter]);
my ($author,$title) = $sth->fetchrow; my ($author,$title) = $sth->fetchrow;
my %line; my %line;
@ -164,9 +207,104 @@ sub catalogsearch {
push @finalresult, \%line; push @finalresult, \%line;
$counter++; $counter++;
} }
return @finalresult;
my $nbresults = $#result + 1;
return (\@finalresult, $nbresults);
} }
# Creates the SQL Request
sub create_request {
my ($tags, $subfields, $and_or, $operator, $value) = @_;
my $sql_tables; # will contain marc_subfield_table as m1,...
my $sql_where1; # will contain the "true" where
my $sql_where2 = "("; # will contain m1.bibid=m2.bibid
my $nb_active=0; # will contain the number of "active" entries. and entry is active is a value is provided.
my $nb_table=1; # will contain the number of table. ++ on each entry EXCEPT when an OR is provided.
for(my $i=0; $i<=@$value;$i++) {
if (@$value[$i]) {
$nb_active++;
if ($nb_active==1) {
if (@$operator[$i] eq "start") {
$sql_tables .= "marc_subfield_table as m$nb_table,";
$sql_where1 .= "(m1.subfieldvalue like '@$value[$i]%'";
if (@$tags[$i]) {
$sql_where1 .=" and m1.tag=@$tags[$i] and m1.subfieldcode='@$subfields[$i]'";
}
$sql_where1.=")";
} elsif (@$operator[$i] eq "contains") {
$sql_tables .= "marc_word as m$nb_table,";
$sql_where1 .= "(m1.word like '@$value[$i]%'";
if (@$tags[$i]) {
$sql_where1 .=" and m1.tag=@$tags[$i] and m1.subfieldid='@$subfields[$i]'";
}
$sql_where1.=")";
} else {
$sql_tables .= "marc_subfield_table as m$nb_table,";
$sql_where1 .= "(m1.subfieldvalue @$operator[$i] '@$value[$i]' ";
if (@$tags[$i]) {
$sql_where1 .=" and m1.tag=@$tags[$i] and m1.subfieldcode='@$subfields[$i]'";
}
$sql_where1.=")";
}
} else {
if (@$operator[$i] eq "start") {
$nb_table++;
$sql_tables .= "marc_subfield_table as m$nb_table,";
$sql_where1 .= "@$and_or[$i] (m$nb_table.subfieldvalue like '@$value[$i]%'";
if (@$tags[$i]) {
$sql_where1 .=" and m$nb_table.tag=@$tags[$i] and m$nb_table.subfieldcode='@$subfields[$i]'";
}
$sql_where1.=")";
$sql_where2 .= "m1.bibid=m$nb_table.bibid and ";
} elsif (@$operator[$i] eq "contains") {
if (@$and_or[$i] eq 'and') {
$nb_table++;
$sql_tables .= "marc_word as m$nb_table,";
$sql_where1 .= "@$and_or[$i] (m$nb_table.word like '@$value[$i]%'";
if (@$tags[$i]) {
$sql_where1 .=" and m$nb_table.tag=@$tags[$i] and m$nb_table.subfieldid='@$subfields[$i]'";
}
$sql_where1.=")";
$sql_where2 .= "m1.bibid=m$nb_table.bibid and ";
} else {
$sql_where1 .= "@$and_or[$i] (m$nb_table.word like '@$value[$i]%'";
if (@$tags[$i]) {
$sql_where1 .=" and m$nb_table.tag=@$tags[$i] and m$nb_table.subfieldid='@$subfields[$i]'";
}
$sql_where1.=")";
$sql_where2 .= "m1.bibid=m$nb_table.bibid and ";
}
} else {
$nb_table++;
$sql_tables .= "marc_subfield_table as m$nb_table,";
$sql_where1 .= "@$and_or[$i] (m$nb_table.subfieldvalue @$operator[$i] '@$value[$i]'";
if (@$tags[$i]) {
$sql_where1 .=" and m$nb_table.tag=@$tags[$i] and m$nb_table.subfieldcode='@$subfields[$i]'";
}
$sql_where2 .= "m1.bibid=m$nb_table.bibid and ";
$sql_where1.=")";
}
}
}
}
if($sql_where2 ne "(") # some datas added to sql_where2, processing
{
$sql_where2 = substr($sql_where2, 0, (length($sql_where2)-5)); # deletes the trailing ' and '
$sql_where2 .= ")";
}
else # no sql_where2 statement, deleting '('
{
$sql_where2 = "";
}
chop $sql_tables; # deletes the trailing ','
return ($sql_tables, $sql_where1, $sql_where2);
}
END { } # module clean-up code here (global destructor) END { } # module clean-up code here (global destructor)
1; 1;