--- nfo/perl/libs/Data/Storage/Handler/Tangram.pm 2003/05/10 17:31:18 1.36 +++ nfo/perl/libs/Data/Storage/Handler/Tangram.pm 2003/06/25 22:57:54 1.40 @@ -1,13 +1,27 @@ ############################################ # -# $Id: Tangram.pm,v 1.36 2003/05/10 17:31:18 jonen Exp $ +# $Id: Tangram.pm,v 1.40 2003/06/25 22:57:54 joko Exp $ # # $Log: Tangram.pm,v $ +# Revision 1.40 2003/06/25 22:57:54 joko +# major rework of "sub sendQuery / sub getListFiltered": now should be capable of "sorting" +# +# Revision 1.39 2003/06/06 11:40:40 jonen +# fixed bug at 'getFilteredList' +# +# Revision 1.38 2003/05/13 16:38:38 joko +# problems with "tied" on 5.6.1/win32 +# +# Revision 1.37 2003/05/10 17:37:39 jonen +# corrected last commit +# # Revision 1.36 2003/05/10 17:31:18 jonen # + added new functions related to 'create' item # - createNode() # # creates non-persistent 'deep dummy filled' object -# - +# - insertChildNode() +# # inserts child node at given parent (child node haven't to exists, +# createNode will be injected transparently) # # Revision 1.35 2003/04/19 16:09:48 jonen # + added operator dispatching (currently for getting ref-type) at 'getListFiltered' @@ -488,61 +502,133 @@ # redirect to unfiltered mode #return $self->getListUnfiltered(@_); - my $nodename = shift; - my $filters = shift; + my $in = {}; + $in->{nodename} = shift; + $in->{filters} = shift; + $in->{sorting} = shift; + my @results; - $logger->debug( __PACKAGE__ . "->getListFiltered( nodename => '" . $nodename . "' )" ); + $logger->debug( __PACKAGE__ . "->getListFiltered( nodename => '" . $in->{nodename} . "' )" ); + + #print Dumper($filters); -#print Dumper($filters); + # 1. "Remote Object Handle" - get set of objects from odbms by object name + my $remote = $self->{_COREHANDLE}->remote($in->{nodename}); + # 2. Transfer $in to $orm_query + my $orm_query = {}; + + # 2.a. Filters my @tfilters; + my $orm_filter = undef; - foreach my $filter (@$filters) { + foreach my $filter (@{$in->{filters}}) { # get filter - TODO: for each filter #my $filter = $filters->[0]; - - # build filter + + # 1. The parts of a filter source entry my $lexpr = $filter->{key}; #my $op = $filter->{op}; my $op = '='; my $rexpr = $filter->{val}; my $tight = 100; + + # 2. Build filter target entry - # my $tfilter = Tangram::Filter->new( - # expr => "t1.$lexpr $op '$rexpr'", - # tight => $tight, - # objects => $objects, - # ); - + # Test 1 - didn't work out! + # my $tfilter = Tangram::Filter->new( + # expr => "t1.$lexpr $op '$rexpr'", + # tight => $tight, + # objects => $objects, + # ); + + my $orm_filter_tmp = undef; + # was: # TODO: is_op? # dispatch un-common operators if exists - if($filter->{op} eq "ref") { - push @tfilters, 'ref($remote->{' . $filter->{key} . '})' . " eq '$filter->{val}'"; + if ($filter->{op} eq "ref") { + # do nothing, results will be filtered later cause 'tangram-filter' doesn't support 'ref' query + #print "Filter->op eq 'ref'.\n"; + #push @tfilters, 'ref($remote->{' . $filter->{key} . '})' . " eq '$filter->{val}'"; } else { # HACK: build eval-string (sorry) to get filtered list - please give advice here - push @tfilters, '$remote->{' . $filter->{key} . '}' . " $filter->{op} '$filter->{val}'"; + #push @tfilters, '$remote->{' . $filter->{key} . '}' . " $filter->{op} '$filter->{val}'"; + # better: calculate expression right here! + #push @tfilters, '$remote->{' . $filter->{key} . '}' . " $filter->{op} '$filter->{val}'"; + + #print "key: ", $filter->{key}, "\n"; + + my $left = $remote->{$filter->{key}}; + #my $r = Tangram::Expr->new( 'string' => "'" . $filter->{val} . "'" ); + my $right = $filter->{val}; + my $op = $filter->{op}; + $orm_filter_tmp = $left->$op($right); + } + + if (not $orm_filter) { + $orm_filter = $orm_filter_tmp; + } else { + $orm_filter = $orm_filter->and($orm_filter_tmp); } } - my $tfilter = join(' & ', @tfilters); + $orm_query->{filter} = $orm_filter; - # get set of objects from odbms by object name - my $remote = $self->{_COREHANDLE}->remote($nodename); - # was: - #@results = $self->{COREHANDLE}->select($object_set, $tfilter); + + # 2.b. sorting [new as of 2003-06-17] + if ($in->{sorting}) { + my $sorting_rules = []; + my $sorting_order = 'ASC'; + foreach my $sorting_column (keys %{$in->{sorting}}) { + $sorting_order = $in->{sorting}->{$sorting_column} if $in->{sorting}->{$sorting_column}; + push @$sorting_rules, Tangram::Expr->new( 'string' => $sorting_column ); + } + $orm_query->{order} = $sorting_rules; + if ($sorting_order eq 'DESC') { + $orm_query->{desc} = 1; + } + } + + + # 3. build and issue query - return result as Tangram::Cursor + + # coerce hash into array (This is valid in Perl) + my @orm_query_args = %$orm_query; + # send query (arguments) to orm + @results = $self->{_COREHANDLE}->select($remote, @orm_query_args); + + #my $cursor = $self->{_COREHANDLE}->cursor($remote, @orm_query_args); + #return $cursor; + #print Dumper(@results); # is: # HACK: build eval-string (sorry) to get filtered list - please give advice here - my $evalstring = 'return $self->{_COREHANDLE}->select($remote, ' . $tfilter . ');'; - - #print "eval: $evalstring", "\n"; - - # get filtered list/set - @results = eval($evalstring); - die $@ if $@; + #my $evalstring = 'return $self->{_COREHANDLE}->select($remote, ' . $tfilter . $sorting . ');'; + #print "eval: $evalstring", "\n"; + # get filtered list/set + #@results = eval($evalstring); + #die $@ if $@; + +=pod + # filter results + if ($filters->[0]->{op} && ($filters->[0]->{op} eq "ref")) { + #print "Filter->op eq 'ref'.\n"; + my $att_name = $filters->[0]->{key}; + my $att_val = $filters->[0]->{val}; + my @filtered; + foreach(@results) { + if(ref($_->{$att_name}) eq $att_val) { + push @filtered, $_; + } + } + @results = @filtered; + } +=cut + + #print "results: " . Dumper(\@results); return \@results; } @@ -572,6 +658,13 @@ return $result; } +sub createResult { + my $self = shift; + my $rh = shift; + my $result = Data::Storage::Result::Tangram->new( RESULTHANDLE => $rh ); + return $result; +} + sub sendQuery { my $self = shift; my $query = shift; @@ -663,7 +756,10 @@ if ($crud eq 'RETRIEVE') { - my $list = $self->getListFiltered($query->{node}, $query->{criterias}); + my $list = $self->getListFiltered($query->{node}, $query->{criterias}, $query->{sorting}); + #return $list; + return $self->createResult($list); + #return $self->createSet($object); #return $self->createSet($list); return $self->createSet(@$list); @@ -955,32 +1051,42 @@ #print "Create child object [$nodename]: " . Dumper($child_entry); } - # get reference of tied node + # get reference of tied node (seems, only on Linux node's are tied!!) my $tied_node = tied $parent->{$nodename}; # insert/change child entry at parent #print "reference: " . ref($parent->{$nodename}) . "\n"; if(ref($parent->{$nodename}) eq 'ARRAY') { - # all tangram types are tied as 'SCALAR' with special 'FETCH', 'STORE' methods per type, - # so a 'PUSH' is not implemented (which could be then done transparently) - my $array = $tied_node->FETCH; - push @$array, $child_entry; - $tied_node->STORE($array); - # node will be normaly untied at 'STORE' - if(tied $parent->{$nodename}) { print "already tied !!\n"; } - else { undef $tied_node; } - } - elsif(ref($parent->{$nodename}) eq 'HASH') { - if(my $key = $query_args->{hash_key}) { - # same problem as with 'ARRAY': - # all tangram types are tied as 'SCALAR' with special 'FETCH', 'STORE' methods per type. - my $hash = $tied_node->FETCH; - $hash->{$key} = $child_entry; - $tied_node->STORE($hash); + # (seems, only on Linux node's are tied!!) + if($tied_node) { + # all tangram types are tied as 'SCALAR' with special 'FETCH', 'STORE' methods per type, + # so a 'PUSH' is not implemented (which could be then done transparently) + my $array = $tied_node->FETCH; + push @$array, $child_entry; + $tied_node->STORE($array); # node will be normaly untied at 'STORE' if(tied $parent->{$nodename}) { print "already tied !!\n"; } else { undef $tied_node; } } else { + push @{$parent->{$nodename}}, $child_entry; + } + } + elsif(ref($parent->{$nodename}) eq 'HASH') { + if(my $key = $query_args->{hash_key}) { + # (seems, only on Linux node's are tied!!) + if($tied_node) { + # same problem as with 'ARRAY': + # all tangram types are tied as 'SCALAR' with special 'FETCH', 'STORE' methods per type. + my $hash = $tied_node->FETCH; + $hash->{$key} = $child_entry; + $tied_node->STORE($hash); + # node will be normaly untied at 'STORE' + if(tied $parent->{$nodename}) { print "already tied !!\n"; } + else { undef $tied_node; } + } else { + $parent->{$nodename}->{$key} = $child_entry; + } + } else { print "ERROR: No HASH KEY given, so not able to insert hash entry!"; } }