--- /dev/null
+#!/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";
# 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;
}
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/;
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 = {};
$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");
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
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};
$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");
%$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) = @_;
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;