[open-ils-commits] [GIT] Evergreen ILS branch master updated. 287a3e2052f5699daacddb7c536b6a15631fcf16

Evergreen Git git at git.evergreen-ils.org
Tue May 22 14:59:33 EDT 2012


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Evergreen ILS".

The branch, master has been updated
       via  287a3e2052f5699daacddb7c536b6a15631fcf16 (commit)
      from  b90330614c99c08f67b6e51cdf2aa035edfba66b (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 287a3e2052f5699daacddb7c536b6a15631fcf16
Author: Bill Erickson <berick at esilibrary.com>
Date:   Mon May 21 10:32:56 2012 -0400

    Query Parser merged copy / non-dynamic filters
    
    When more than one copy-level filter (e.g. locations()) is used in a
    query-parser query, all but the first are ignored.  The goal of this
    work is to compress multiple copy-level filters into a single filter
    that represents the full collection.  Wherever possible, boolean
    structures will be honored, to the extent possible for post-search
    copy-level filters.
    
    Examples:
    
    concerto locations(1,2) locations(3,4)
    
    ==> concerto locations(1,2,3,4)
    
    ( concerto locations(3,4,5) ) || (piano locations(3,5,7) )
    
    ==> ( concerto || piano ) locations(3,4,5,6,7)
    
    ( concerto locations(3,4,5) ) && ( piano locations(3,5,7) )
    
    ==> concerto piano locations(3,5)
    
    Note, in the last 2 examples, the final query does not exactly match the
    original.  This is because copy-level filters are applied after the
    initial search and cannot be executed as part of the  nested query.  The
    best we can do is create a representation of the final copy-level
    filter, based on the nesting, and apply it to the final result of the
    nested search.
    
    Signed-off-by: Bill Erickson <berick at esilibrary.com>
    Signed-off-by: Mike Rylander <mrylander at gmail.com>

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/QueryParser.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/QueryParser.pm
index d5e12a4..4cb51ed 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/QueryParser.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/QueryParser.pm
@@ -971,11 +971,80 @@ sub new_filter {
     return $node;
 }
 
+
+sub _merge_filters {
+    my $left_filter = shift;
+    my $right_filter = shift;
+    my $join = shift;
+
+    return undef unless $left_filter or $right_filter;
+    return $right_filter unless $left_filter;
+    return $left_filter unless $right_filter;
+
+    my $args = $left_filter->{args} || [];
+
+    if ($join eq '|') {
+        push(@$args, @{$right_filter->{args}});
+
+    } else {
+        # find the intersect values
+        my %new_vals;
+        map { $new_vals{$_} = 1 } @{$right_filter->{args} || []};
+        $args = [ grep { $new_vals{$_} } @$args ];
+    }
+
+    $left_filter->{args} = $args;
+    return $left_filter;
+}
+
+sub collapse_filters {
+    my $self = shift;
+    my $name = shift;
+
+    # start by merging any filters at this level.
+    # like-level filters are always ORed together
+
+    my $cur_filter;
+    my @cur_filters = grep {$_->name eq $name } @{ $self->filters };
+    if (@cur_filters) {
+        $cur_filter = shift @cur_filters;
+        my $args = $cur_filter->{args} || [];
+        $cur_filter = _merge_filters($cur_filter, $_, '|') for @cur_filters;
+    }
+
+    # next gather the collapsed filters from sub-plans and 
+    # merge them with our own
+
+    my @subquery = @{$self->{query}};
+
+    while (@subquery) {
+        my $blob = shift @subquery;
+        shift @subquery; # joiner
+        next unless $blob->isa('QueryParser::query_plan');
+        my $sub_filter = $blob->collapse_filters($name);
+        $cur_filter = _merge_filters($cur_filter, $sub_filter, $self->joiner);
+    }
+
+    if ($self->QueryParser->debug) {
+        my @args = ($cur_filter and $cur_filter->{args}) ? @{$cur_filter->{args}} : ();
+        warn "collapse_filters($name) => [@args]\n";
+    }
+
+    return $cur_filter;
+}
+
 sub find_filter {
     my $self = shift;
     my $needle = shift;;
     return undef unless ($needle);
-    return grep { $_->name eq $needle } @{ $self->filters };
+
+    my $filter = $self->collapse_filters($needle);
+
+    warn "find_filter($needle) => " . 
+        (($filter and $filter->{args}) ? "@{$filter->{args}}" : '[]') . "\n" 
+        if $self->QueryParser->debug;
+
+    return $filter ? ($filter) : ();
 }
 
 sub find_modifier {
@@ -1109,7 +1178,6 @@ sub add_filter {
     my $filter = shift;
 
     $self->{filters} ||= [];
-    $self->{filters} = [ grep {$_->name ne $filter->name} @{$self->{filters}} ];
 
     push(@{$self->{filters}}, $filter);
 

-----------------------------------------------------------------------

Summary of changes:
 .../lib/OpenILS/Application/Storage/QueryParser.pm |   72 +++++++++++++++++++-
 1 files changed, 70 insertions(+), 2 deletions(-)


hooks/post-receive
-- 
Evergreen ILS


More information about the open-ils-commits mailing list