Filename | /usr/local/src/github.com/foswiki/core/lib/Foswiki/Query/OP_where.pm |
Statements | Executed 14 statements in 741µs |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
3 | 1 | 1 | 61µs | 103µs | new | Foswiki::Query::OP_where::
1 | 1 | 1 | 24µs | 32µs | BEGIN@11 | Foswiki::Query::OP_where::
1 | 1 | 1 | 16µs | 34µs | BEGIN@12 | Foswiki::Query::OP_where::
1 | 1 | 1 | 9µs | 9µs | BEGIN@14 | Foswiki::Query::OP_where::
0 | 0 | 0 | 0s | 0s | _evaluate_for_RHS | Foswiki::Query::OP_where::
0 | 0 | 0 | 0s | 0s | evaluate | Foswiki::Query::OP_where::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # See bottom of file for license and copyright information | ||||
2 | |||||
3 | =begin TML | ||||
4 | |||||
5 | ---+ package Foswiki::Query::OP_where | ||||
6 | |||||
7 | =cut | ||||
8 | |||||
9 | package Foswiki::Query::OP_where; | ||||
10 | |||||
11 | 2 | 44µs | 2 | 39µs | # spent 32µs (24+7) within Foswiki::Query::OP_where::BEGIN@11 which was called:
# once (24µs+7µs) by Foswiki::Query::Parser::BEGIN@54 at line 11 # spent 32µs making 1 call to Foswiki::Query::OP_where::BEGIN@11
# spent 7µs making 1 call to strict::import |
12 | 2 | 43µs | 2 | 51µs | # spent 34µs (16+18) within Foswiki::Query::OP_where::BEGIN@12 which was called:
# once (16µs+18µs) by Foswiki::Query::Parser::BEGIN@54 at line 12 # spent 34µs making 1 call to Foswiki::Query::OP_where::BEGIN@12
# spent 18µs making 1 call to warnings::import |
13 | |||||
14 | 2 | 575µs | 1 | 9µs | # spent 9µs within Foswiki::Query::OP_where::BEGIN@14 which was called:
# once (9µs+0s) by Foswiki::Query::Parser::BEGIN@54 at line 14 # spent 9µs making 1 call to Foswiki::Query::OP_where::BEGIN@14 |
15 | 1 | 9µs | our @ISA = ('Foswiki::Query::OP'); | ||
16 | |||||
17 | # spent 103µs (61+42) within Foswiki::Query::OP_where::new which was called 3 times, avg 34µs/call:
# 3 times (61µs+42µs) by Foswiki::Query::Parser::new at line 105 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Query/Parser.pm, avg 34µs/call | ||||
18 | 6 | 64µs | my $class = shift; | ||
19 | 3 | 42µs | return $class->SUPER::new( # spent 42µs making 3 calls to Foswiki::Query::OP::new, avg 14µs/call | ||
20 | arity => 2, | ||||
21 | name => '[', | ||||
22 | close => ']', | ||||
23 | prec => 900 | ||||
24 | ); | ||||
25 | } | ||||
26 | |||||
27 | sub evaluate { | ||||
28 | my $this = shift; | ||||
29 | my $node = shift; | ||||
30 | my %domain = @_; | ||||
31 | |||||
32 | my $lhs_node = $node->{params}[0]; | ||||
33 | |||||
34 | # See Foswiki/Query/Node.pm for an explanation of restricted names | ||||
35 | my $lhs_values = $lhs_node->evaluate( restricted_name => 1, @_ ); | ||||
36 | $lhs_values = [$lhs_values] unless ( ref($lhs_values) eq 'ARRAY' ); | ||||
37 | |||||
38 | my $rhs_node = $node->{params}[1]; | ||||
39 | my @res; | ||||
40 | if ( ref( $rhs_node->{op} ) eq 'Foswiki::Query::OP_comma' ) { | ||||
41 | |||||
42 | # We have an array on the RHS. We apply the op to each item | ||||
43 | # on the RHS, passing in the complete LHS. This way, the operation | ||||
44 | # [a,b,c] WHERE [1,3] -> [a,c] | ||||
45 | # This process permits duplication of entries in the result. | ||||
46 | foreach my $rhs_item ( @{ $rhs_node->{params} } ) { | ||||
47 | $this->_evaluate_for_RHS( $lhs_values, $rhs_item, \%domain, \@res ); | ||||
48 | } | ||||
49 | } | ||||
50 | else { | ||||
51 | $this->_evaluate_for_RHS( $lhs_values, $rhs_node, \%domain, \@res ); | ||||
52 | } | ||||
53 | return unless scalar(@res); | ||||
54 | return \@res; | ||||
55 | } | ||||
56 | |||||
57 | # Give a set of values on the LHS of a where, and a single constraint | ||||
58 | # on the RHS, create a set of results. The results are selected from the | ||||
59 | # LHS, by index. For example, given [a,b,c] WHERE d then if d evaluates | ||||
60 | # to a constant integer, then it is taken as an index into [a,b,c]. Otherwise | ||||
61 | # it is evaluated and if it returns true, then the LHS entry at the | ||||
62 | # corresponding position is returned. So: | ||||
63 | # [a,b,c] WHERE 1 -> [b] | ||||
64 | # [a,b,c] WHERE name!='b' -> [a,c] | ||||
65 | sub _evaluate_for_RHS { | ||||
66 | my ( $this, $lhs_values, $rhs_node, $domain, $res ) = @_; | ||||
67 | |||||
68 | # See if we have an index on the RHS | ||||
69 | my $rhs_constant = -1; | ||||
70 | if ( $rhs_node->evaluatesToConstant(%$domain) ) { | ||||
71 | $rhs_constant = $rhs_node->evaluate(%$domain); | ||||
72 | if ( Foswiki::Query::OP::isNumber($rhs_constant) ) { | ||||
73 | |||||
74 | # Handle negative indices | ||||
75 | $rhs_constant += scalar(@$lhs_values) if ( $rhs_constant < 0 ); | ||||
76 | |||||
77 | # Trunc to integer | ||||
78 | $rhs_constant = int($rhs_constant); | ||||
79 | |||||
80 | # Don't bother if integer index is out of range | ||||
81 | return | ||||
82 | unless $rhs_constant >= 0 | ||||
83 | && $rhs_constant < scalar(@$lhs_values); | ||||
84 | } | ||||
85 | else { | ||||
86 | $rhs_constant = -1; # unmatchable | ||||
87 | } | ||||
88 | } | ||||
89 | |||||
90 | # For each item on the LHS | ||||
91 | my $i = 0; # LHS index | ||||
92 | foreach my $lhs_value (@$lhs_values) { | ||||
93 | if ( $rhs_constant < 0 | ||||
94 | && $rhs_node->evaluate( data => $lhs_value, tom => $domain->{tom} ) | ||||
95 | ) | ||||
96 | { | ||||
97 | push( @$res, $lhs_value ); | ||||
98 | } | ||||
99 | elsif ( $i == $rhs_constant ) { | ||||
100 | |||||
101 | # Special case; integer index responds with array el at that index | ||||
102 | push( @$res, $lhs_value ); | ||||
103 | } | ||||
104 | $i++; | ||||
105 | } | ||||
106 | } | ||||
107 | |||||
108 | 1 | 6µs | 1; | ||
109 | __END__ |