From: Lebbeous Fogle-Weekley Date: Wed, 21 Mar 2012 14:32:11 +0000 (-0400) Subject: prepare_filter() works as of early testing X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=4df91674fbc891d9e954496e135af1920ce680a0;p=evergreen%2Fequinox.git prepare_filter() works as of early testing Signed-off-by: Lebbeous Fogle-Weekley --- diff --git a/Open-ILS/scratch-recur2.pl b/Open-ILS/scratch-recur2.pl new file mode 100644 index 0000000000..a751afa7fb --- /dev/null +++ b/Open-ILS/scratch-recur2.pl @@ -0,0 +1,75 @@ +#!/usr/bin/perl -w + +use strict; + +use Data::Dumper; + +my $one = { + -and => [ + {foo => "bar"}, + {baz => {">=" => 3}} + ] +}; + +my $two = { + "xact_start" => {">" => "today"}, + "circ_lib" => "BR1" +}; + +my $three = { + -not => [ + {abc => {between => [1,32]}}, + {def => {">=" => 1}}, + {"ghi" => [1,2,3,4], "jkl" => 5} + ] +}; + +sub newkey { + my ($key) = @_; + + return ("+sometable", "XXX$key"); +} + +sub expand_key { + my ($o, $key) = @_; + + my ($table, $column) = newkey($key); + + $o->{$table} ||= {}; + + $o->{$table}{$column} = $o->{$key}; + delete $o->{$key}; + + return $o->{$table}{$column}; +} + +sub recursively_mark_column_names { + my ($o, $state) = @_; + + $state ||= {}; + + if (ref $o eq 'HASH') { + foreach my $key (keys %$o) { + if (not $state->{in_expr} and $key =~ /^[a-z]/) { + $state->{in_expr} = 1; + + print "attempting replacement of $key\n"; + my $deeper = expand_key($o, $key); + + recursively_mark_column_names($deeper, $state); + + $state->{in_expr} = 0; + } else { + recursively_mark_column_names($o->{$key}, $state); + } + } + } elsif (ref $o eq 'ARRAY') { + recursively_mark_column_names($_, $state) foreach @$o; + } # else scalar, nothing to do? +} + +recursively_mark_column_names($one); +recursively_mark_column_names($two); +recursively_mark_column_names($three); + +print Dumper($one, $two, $three), "\n"; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Fielder.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Fielder.pm index 2cfc979462..486ad78125 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Fielder.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Fielder.pm @@ -167,27 +167,29 @@ sub flattened_search { # filter. my $filter = OpenILS::Application::Flattener::prepare_filter($map, $where); - # Process the supplied sort/limit/offset clause and use it to finish the - # jffolo. - $jffolo = OpenILS::Application::Flattener::finish_jffolo( - $map, $jffolo, $slo - ); - - # Reach out and touch some service. - my $pcrud = create OpenSRF::AppSession("open-ils.pcrud"); - my $req = $pcrud->request( - "open-ils.pcrud.search.$hint", $auth, $filter, $jffolo - ); - - # Stream back flattened results. - while (my $resp = $req->recv(timeout => 60)) { - $conn->respond( - OpenILS::Application::Flattener::process_result($map, $resp) - ); - } - - # Clean up. - $pcrud->kill_me; + return [$filter, $jffolo]; +# # Process the supplied sort/limit/offset clause and use it to finish the +# # jffolo. +# $jffolo = OpenILS::Application::Flattener::finish_jffolo( +# $map, $jffolo, $slo +# ); + + # Reach out and touch pcrud (could be cstore, if we wanted to offer + # this as a private service). +# my $pcrud = create OpenSRF::AppSession("open-ils.pcrud"); +# my $req = $pcrud->request( +# "open-ils.pcrud.search.$hint", $auth, $filter, $jffolo +# ); +# +# # Stream back flattened results. +# while (my $resp = $req->recv(timeout => 60)) { +# $conn->respond( +# OpenILS::Application::Flattener::process_result($map, $resp) +# ); +# } +# +# # Clean up. +# $pcrud->kill_me; return; } diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Flattener.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Flattener.pm index c984ab4abf..4da71d170e 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Flattener.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Flattener.pm @@ -1,7 +1,7 @@ package OpenILS::Application::Flattener; # This package is not meant to be registered as a stand-alone OpenSRF -# application, but to be mixed into other services +# application, but to be used by high level methods in other services. use base qw/OpenILS::Application/; @@ -11,36 +11,19 @@ use warnings; use OpenSRF::EX qw/:try/; use OpenSRF::Utils::Logger qw/:logger/; use OpenILS::Utils::CStoreEditor q/:funcs/; - - -sub _fm_class_by_hint { - my ($hint) = @_; - - my ($class) = grep { - Fieldmapper->publish_fieldmapper->{$_}{hint} eq $hint - } keys %{ Fieldmapper->publish_fieldmapper }; - - return $class; - -} - -sub _fm_identity_from_class { - my ($class) = @_; - - return Fieldmapper->publish_fieldmapper->{$class}{identity}; -} +use OpenSRF::Utils::JSON; sub _fm_link_from_class { - my ($class, $piece) = @_; + my ($class, $field) = @_; - return Fieldmapper->publish_fieldmapper->{$class}{links}{$piece}; + return Fieldmapper->publish_fieldmapper->{$class}{links}{$field}; } sub _flattened_search_single_flesh_wad { my ($hint, $path) = @_; $path = [ @$path ]; # clone for processing here - my $class = _fm_class_by_hint($hint); + my $class = OpenSRF::Utils::JSON->lookup_class($hint); my $flesh_depth = 0; my $flesh_fields = {}; @@ -56,7 +39,7 @@ sub _flattened_search_single_flesh_wad { $flesh_fields->{$hint} ||= []; push @{ $flesh_fields->{$hint} }, $piece; $hint = $link->{class}; - $class = _fm_class_by_hint($hint); + $class = OpenSRF::Utils::JSON->lookup_class($hint); $flesh_depth++; } else { throw OpenSRF::EX::ERROR("no link $piece on $class"); @@ -74,8 +57,8 @@ sub _flattened_search_single_flesh_wad { sub _flattened_search_single_join_clause { my ($column_name, $hint, $path) = @_; - my $class = _fm_class_by_hint($hint); - my $last_ident = _fm_identity_from_class($class); + my $class = OpenSRF::Utils::JSON->lookup_class($hint); + my $last_ident = $class->Identity; $path = [ @$path ]; # clone for processing here @@ -92,7 +75,7 @@ sub _flattened_search_single_join_clause { my $link = _fm_link_from_class($class, $piece); if ($link) { $hint = $link->{class}; - $class = _fm_class_by_hint($hint); + $class = OpenSRF::Utils::JSON->lookup_class($hint); my $reltype = $link->{reltype}; my $field = $link->{key}; @@ -129,7 +112,7 @@ sub _flattened_search_single_join_clause { $core_join->{$alias} = $new_join; } - $last_ident = _fm_identity_from_class($class); + $last_ident = $class->Identity; $last_join = $new_join; } else { throw new OpenSRF::EX::ERROR("no link '$piece' on $class"); @@ -201,6 +184,62 @@ sub _flattened_search_merge_join_clause { %$old = ( %$old, %$new ); } +sub _flattened_search_expand_filter_column { + my ($o, $key, $map) = @_; + + if ($map->{$key}) { + my $table = $map->{$key}{last_join_alias}; + my $column = $map->{$key}{path}[-1]; + + if ($table) { + $o->{$table} ||= {}; + + $o->{$table}{$column} = $o->{$key}; + delete $o->{$key}; + + return $o->{$table}{$column}; + } else { # field must be on core class + $o->{$column} = $o->{$key}; + delete $o->{$key}; + return $o->{$column}; + } + } else { + return $o->{$key}; + } +} + +sub _flattened_search_recursively_apply_map_to_filter { + my ($o, $map, $state) = @_; + + $state ||= {}; + + if (ref $o eq 'HASH') { + foreach my $key (keys %$o) { + if (not $state->{in_expr} and $key =~ /^[a-z]/) { + $state->{in_expr} = 1; + + my $deeper = _flattened_search_expand_filter_column( + $o, $key, $map + ); + + _flattened_search_recursively_apply_map_to_filter( + $deeper, $map, $state + ); + + $state->{in_expr} = 0; + } else { + _flattened_search_recursively_apply_map_to_filter( + $o->{$key}, $map, $state + ); + } + } + } elsif (ref $o eq 'ARRAY') { + _flattened_search_recursively_apply_map_to_filter( + $_, $map, $state + ) foreach @$o; + } # else scalar, nothing to do? +} + # returns a normalized version of the map, and the jffolo (see below) sub process_map { my ($hint, $map) = @_; @@ -241,17 +280,11 @@ sub process_map { sub prepare_filter { my ($map, $where) = @_; - my $filter = {}; + my $filter = {%$where}; - # XXX find scratch-recur.pl and do something like that. -# foreach my $key (keys(%$where)) { -# next unless exists $map->{$key}; -# -# my $field = $map->{$key}{path}[-1]; -# my $last_join_alias = $map->{$key}{last_join_alias}; -# -# -# } + _flattened_search_recursively_apply_map_to_filter($filter, $map); + + return $filter; } 1;