From 856e992c21ce0812d36248a502b2ebb0601ee215 Mon Sep 17 00:00:00 2001 From: Lebbeous Fogle-Weekley Date: Wed, 19 Sep 2012 15:27:03 -0400 Subject: [PATCH] Acq general search: improve searching for negative comparisons This aims to address Launchpad bug #1031535. I think the bug only really shows up when searches involve invoices either as the core type or with filter fields. If a search doesn't involve invoices, the problematic joins aren't present. Could use more testing though. Seems to make the problem go away, and other basic searches seem to work, but I certainly haven't tested everything. Signed-off-by: Lebbeous Fogle-Weekley Signed-off-by: Dan Wells --- .../lib/OpenILS/Application/Acq/Search.pm | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Search.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Search.pm index 094045fdd3..9c488b9136 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Search.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Search.pm @@ -234,6 +234,7 @@ sub prepare_terms { $outer_clause->{$conj} = [] unless $outer_clause->{$conj}; foreach my $unit (@{$terms->{$class}}) { + my $special_clause; my ($k, $v, $fuzzy, $between, $not, $castdate, $gte, $lte) = breakdown_term($unit); @@ -248,15 +249,29 @@ sub prepare_terms { } elsif ($gte or $lte) { my $op = $gte ? '>=' : '<='; $v = {$op => $v}; + } elsif (not ref $v and $not) { + # the old way, NOT (blah.id = $v) needs to be + # (blah.id <> $x OR blah.id IS NULL) + $not = 0; # avoid the regular negative transformation + $special_clause = { + "-or" => [ + {"+$class" => {$k => {"!=" => $v}}}, + {"+$class" => {$k => undef}} + ] + }; } $term_clause = {$k => $v}; } else { next; } - my $clause = {"+" . $class => $term_clause}; - $clause = {"-not" => $clause} if $not; - push @{$outer_clause->{$conj}}, $clause; + if ($special_clause) { + push @{$outer_clause->{$conj}}, $special_clause; + } else { + my $clause = {"+" . $class => $term_clause}; + $clause = {"-not" => $clause} if $not; + push @{$outer_clause->{$conj}}, $clause; + } } } @@ -340,7 +355,7 @@ sub build_from_clause_and_joins { } elsif ($class eq 'acqinv' or $core eq 'acqinv') { $graft_map{$class} = $query->{from}{$core}{acqmapinv}{join}{$class} ||= {}; - $graft_map{$class}{type} = $join_type; + $graft_map{$class}{type} = "left"; # $join_type } else { $graft_map{$class} = $query->{from}{$core}{$class} ||= {}; $graft_map{$class}{type} = $join_type; @@ -488,6 +503,11 @@ q/order_by clause must be of the long form, like: my $offset = add_au_joins($graft_map, $hint, prepare_au_terms($and_terms)); add_au_joins($graft_map, $hint, prepare_au_terms($or_terms, $offset)); + # The join to acqmapinv needs to be a left join when present. + if ($query->{from}{$hint}{acqmapinv}) { + $query->{from}{$hint}{acqmapinv}{type} = "left"; + } + if ($and_terms and $or_terms) { $query->{"where"} = { "-" . (lc $conj eq "or" ? "or" : "and") => [$and_terms, $or_terms] -- 2.43.2