← Index
NYTProf Performance Profile   « line view »
For ./view
  Run on Fri Jul 31 18:42:36 2015
Reported on Fri Jul 31 18:48:15 2015

Filename/var/www/foswikidev/core/lib/Foswiki/Query/Node.pm
StatementsExecuted 286714 statements in 681ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
2643898543ms1.21sFoswiki::Query::Node::::evaluateFoswiki::Query::Node::evaluate (recurses: max depth 2, inclusive time 761ms)
876011132ms299msFoswiki::Query::Node::::_getFieldFoswiki::Query::Node::_getField
240338.90ms12.5msFoswiki::Query::Node::::simplifyFoswiki::Query::Node::simplify (recurses: max depth 1, inclusive time 9.91ms)
320322.59ms2.90msFoswiki::Query::Node::::toStringFoswiki::Query::Node::toString (recurses: max depth 4, inclusive time 5.99ms)
147211.76ms3.30msFoswiki::Query::Node::::newLeafFoswiki::Query::Node::newLeaf
400331.05ms1.75msFoswiki::Query::Node::::evaluatesToConstantFoswiki::Query::Node::evaluatesToConstant (recurses: max depth 1, inclusive time 280µs)
8011756µs1.34msFoswiki::Query::Node::::_freezeFoswiki::Query::Node::_freeze
111445µs983µsFoswiki::Query::Node::::BEGIN@75Foswiki::Query::Node::BEGIN@75
4011139µs139µsFoswiki::Query::Node::::isEmptyFoswiki::Query::Node::isEmpty
11114µs26µsFoswiki::Query::Node::::BEGIN@29Foswiki::Query::Node::BEGIN@29
11110µs21µsFoswiki::Query::Node::::BEGIN@93Foswiki::Query::Node::BEGIN@93
1119µs14µsFoswiki::Query::Node::::BEGIN@30Foswiki::Query::Node::BEGIN@30
1119µs24µsFoswiki::Query::Node::::BEGIN@109Foswiki::Query::Node::BEGIN@109
1119µs35µsFoswiki::Query::Node::::BEGIN@34Foswiki::Query::Node::BEGIN@34
1119µs102µsFoswiki::Query::Node::::BEGIN@35Foswiki::Query::Node::BEGIN@35
1118µs36µsFoswiki::Query::Node::::BEGIN@41Foswiki::Query::Node::BEGIN@41
1118µs32µsFoswiki::Query::Node::::BEGIN@42Foswiki::Query::Node::BEGIN@42
1115µs5µsFoswiki::Query::Node::::BEGIN@31Foswiki::Query::Node::BEGIN@31
1114µs4µsFoswiki::Query::Node::::BEGIN@37Foswiki::Query::Node::BEGIN@37
0000s0sFoswiki::Query::Node::::_makeArrayFoswiki::Query::Node::_makeArray
0000s0sFoswiki::Query::Node::::emptyExpressionFoswiki::Query::Node::emptyExpression
0000s0sFoswiki::Query::Node::::tokensFoswiki::Query::Node::tokens
Call graph for these subroutines as a Graphviz dot language file.
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::Node
6
7A Node object is a single node in a query (either a tree node or a leaf node).
8A tree of node objects represents a query over the Foswiki database.
9
10Fields are given by name, and values by strings or numbers.
11
12A query object implements the =evaluate= method as its general
13contract with the rest of the world. This method is a "reference implementation" -
14it does a brute force evaluation of the expression represented by the node in a given
15data domain. It is expected that smarter store implementations will analyse the parse tree
16and derive as many optimisations as possible, minimising fallback to this brute force
17evaluation.
18
19The reference implementation of evaluation uses the =getField= method in the
20{Store}{QueryAlgorithm} to get data from the store. This further decouples the query
21object from the detail of the store implementation.
22
23See Foswiki::Store::QueryAlgorithms for a full spec of the interface to
24query algorithms.
25
26=cut
27
28package Foswiki::Query::Node;
29227µs239µs
# spent 26µs (14+13) within Foswiki::Query::Node::BEGIN@29 which was called: # once (14µs+13µs) by Foswiki::Infix::Node::BEGIN@131 at line 29
use strict;
# spent 26µs making 1 call to Foswiki::Query::Node::BEGIN@29 # spent 13µs making 1 call to strict::import
30227µs218µs
# spent 14µs (9+4) within Foswiki::Query::Node::BEGIN@30 which was called: # once (9µs+4µs) by Foswiki::Infix::Node::BEGIN@131 at line 30
use warnings;
# spent 14µs making 1 call to Foswiki::Query::Node::BEGIN@30 # spent 4µs making 1 call to warnings::import
31233µs15µs
# spent 5µs within Foswiki::Query::Node::BEGIN@31 which was called: # once (5µs+0s) by Foswiki::Infix::Node::BEGIN@131 at line 31
use Foswiki::Infix::Node ();
# spent 5µs making 1 call to Foswiki::Query::Node::BEGIN@31
3218µsour @ISA = ('Foswiki::Infix::Node');
33
34228µs261µs
# spent 35µs (9+26) within Foswiki::Query::Node::BEGIN@34 which was called: # once (9µs+26µs) by Foswiki::Infix::Node::BEGIN@131 at line 34
use Assert;
# spent 35µs making 1 call to Foswiki::Query::Node::BEGIN@34 # spent 26µs making 1 call to Exporter::import
35229µs2194µs
# spent 102µs (9+93) within Foswiki::Query::Node::BEGIN@35 which was called: # once (9µs+93µs) by Foswiki::Infix::Node::BEGIN@131 at line 35
use Error qw( :try );
# spent 102µs making 1 call to Foswiki::Query::Node::BEGIN@35 # spent 93µs making 1 call to Error::import
36
37224µs14µs
# spent 4µs within Foswiki::Query::Node::BEGIN@37 which was called: # once (4µs+0s) by Foswiki::Infix::Node::BEGIN@131 at line 37
use Foswiki::Meta ();
# spent 4µs making 1 call to Foswiki::Query::Node::BEGIN@37
38
39# <DEBUG SUPPORT>
40
41230µs263µs
# spent 36µs (8+28) within Foswiki::Query::Node::BEGIN@41 which was called: # once (8µs+28µs) by Foswiki::Infix::Node::BEGIN@131 at line 41
use constant MONITOR_EVAL => 0;
# spent 36µs making 1 call to Foswiki::Query::Node::BEGIN@41 # spent 28µs making 1 call to constant::import
422112µs257µs
# spent 32µs (8+24) within Foswiki::Query::Node::BEGIN@42 which was called: # once (8µs+24µs) by Foswiki::Infix::Node::BEGIN@131 at line 42
use constant MONITOR_FOLD => 0;
# spent 32µs making 1 call to Foswiki::Query::Node::BEGIN@42 # spent 24µs making 1 call to constant::import
43
44# Cache of the names of $Foswiki::cfg items that are accessible
451100nsour $isAccessibleCfg;
46
47=begin TML
48
49---++ PUBLIC %aliases
50A hash mapping short aliases for META: entry names. For example, this hash
51maps 'form' to 'META:FORM'. Published because extensions (search
52implementations) have made use of it in the past, though not part of the
53offical API.
54
55This hash is maintained by Foswiki::Meta and is *strictly read-only*
56
57---++ PUBLIC %isArrayType
58Maps META: entry type names to true if the type is an array type (such as
59FIELD, ATTACHMENT or PREFERENCE). Published because extensions (search
60implementations) have made use of it in the past, though not part of the
61offical API. The type name should be given without the leading 'META:'
62
63This hash is maintained by Foswiki::Meta and is *strictly read-only*
64
65=cut
66
67# These used to be declared here, but have been refactored back into
68# Foswiki::Meta
6911µs*aliases = \%Foswiki::Meta::aliases;
701300ns*isArrayType = \%Foswiki::Meta::isArrayType;
71
721100nsour $emptyExprOp;
731100nsour $commaOp;
74
75
# spent 983µs (445+538) within Foswiki::Query::Node::BEGIN@75 which was called: # once (445µs+538µs) by Foswiki::Infix::Node::BEGIN@131 at line 80
BEGIN {
76162µs require Foswiki::Query::OP_empty;
7713µs130µs $emptyExprOp = Foswiki::Query::OP_empty->new();
# spent 30µs making 1 call to Foswiki::Query::OP_empty::new
78168µs require Foswiki::Query::OP_comma;
7916µs129µs $commaOp = Foswiki::Query::OP_comma->new();
# spent 29µs making 1 call to Foswiki::Query::OP_comma::new
80163µs1983µs}
# spent 983µs making 1 call to Foswiki::Query::Node::BEGIN@75
81
82sub emptyExpression {
83 my $this = shift;
84 return $this->newNode($emptyExprOp);
85}
86
87
# spent 2.90ms (2.59+308µs) within Foswiki::Query::Node::toString which was called 320 times, avg 9µs/call: # 160 times (960µs+-960µs) by Foswiki::Query::Node::toString at line 102, avg 0s/call # 120 times (1.11ms+-1.11ms) by Foswiki::Query::Node::toString at line 94, avg 0s/call # 40 times (521µs+2.37ms) by Foswiki::Store::QueryAlgorithms::BruteForce::_webQuery at line 158 of /var/www/foswikidev/core/lib/Foswiki/Store/QueryAlgorithms/BruteForce.pm, avg 72µs/call
sub toString {
8832085µs my $a = shift;
8932049µs return 'undef' unless defined($a);
90
91 # Suppress the recursion check; the tree can easily be more than
92 # 100 levels deep.
932118µs232µs
# spent 21µs (10+11) within Foswiki::Query::Node::BEGIN@93 which was called: # once (10µs+11µs) by Foswiki::Infix::Node::BEGIN@131 at line 93
no warnings 'recursion';
# spent 21µs making 1 call to Foswiki::Query::Node::BEGIN@93 # spent 11µs making 1 call to warnings::unimport
943201.42ms440243µs if ( UNIVERSAL::isa( $a, 'Foswiki::Query::Node' ) ) {
# spent 243µs making 320 calls to UNIVERSAL::isa, avg 761ns/call # spent 3.57ms making 120 calls to Foswiki::Query::Node::toString, avg 30µs/call, recursion: max depth 3, sum of overlapping time 3.57ms
95 return
96 '{ op => '
97 . $a->{op}
98 . ', params => '
99 . toString( $a->{params} ) . ' }';
100 }
101200106µs if ( ref($a) eq 'ARRAY' ) {
102280712µs1600s return '[' . join( ',', map { toString($_) } @$a ) . ']';
# spent 2.42ms making 160 calls to Foswiki::Query::Node::toString, avg 15µs/call, recursion: max depth 4, sum of overlapping time 2.42ms
103 }
1048028µs if ( ref($a) eq 'HASH' ) {
105 return
106 '{'
107 . join( ',', map { "$_=>" . toString( $a->{$_} ) } keys %$a ) . '}';
108 }
10921.27ms240µs
# spent 24µs (9+15) within Foswiki::Query::Node::BEGIN@109 which was called: # once (9µs+15µs) by Foswiki::Infix::Node::BEGIN@131 at line 109
use warnings 'recursion';
# spent 24µs making 1 call to Foswiki::Query::Node::BEGIN@109 # spent 15µs making 1 call to warnings::import
11080204µs8064µs if ( UNIVERSAL::isa( $a, 'Foswiki::Meta' ) ) {
# spent 64µs making 80 calls to UNIVERSAL::isa, avg 805ns/call
111 return $a->stringify();
112 }
11380227µs return $a;
114}
115
1161300nsmy $ind = 0;
117
118# </DEBUG SUPPORT>
119
120# STATIC overrides Foswiki::Infix::Node
121# We expand config vars to constant strings during the parse, because
122# otherwise we'd have to export the knowledge of config vars out to other
123# engines that may evaluate queries instead of the default evaluator.
124
# spent 3.30ms (1.76+1.54) within Foswiki::Query::Node::newLeaf which was called 147 times, avg 22µs/call: # 87 times (1.30ms+1.10ms) by Foswiki::Infix::Parser::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Infix/Parser.pm:306] at line 276 of /var/www/foswikidev/core/lib/Foswiki/Infix/Parser.pm, avg 28µs/call # 60 times (457µs+434µs) by Foswiki::Infix::Parser::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Infix/Parser.pm:306] at line 260 of /var/www/foswikidev/core/lib/Foswiki/Infix/Parser.pm, avg 15µs/call
sub newLeaf {
125147139µs my ( $class, $val, $type ) = @_;
126
127147207µs if ( $type == Foswiki::Infix::Node::NAME
128 && $val =~ m/^({[A-Z][A-Z0-9_]*})+$/i )
129 {
130
131 # config var name, make sure it's accessible.
13236µs unless ( defined $isAccessibleCfg ) {
133 $isAccessibleCfg =
134156µs { map { $_ => 1 } @{ $Foswiki::cfg{AccessibleCFG} } };
135 }
136 $val =
137389µs ( $isAccessibleCfg->{$val} ) ? eval( '$Foswiki::cfg' . $val ) : '';
# spent 4µs executing statements in string eval # spent 3µs executing statements in string eval # spent 3µs executing statements in string eval
138327µs331µs return $class->SUPER::newLeaf( $val, Foswiki::Infix::Node::STRING );
# spent 31µs making 3 calls to Foswiki::Infix::Node::newLeaf, avg 10µs/call
139 }
140 else {
1411441.32ms1441.51ms return $class->SUPER::newLeaf( $val, $type );
# spent 1.51ms making 144 calls to Foswiki::Infix::Node::newLeaf, avg 10µs/call
142 }
143}
144
145=begin TML
146
147---++ ObjectMethod evaluate(...) -> $result
148
149Evaluate this node by invoking the =evaluate= method of the attached operator.
150The return result is either an array ref (for many results) or a scalar (for a
151single result)
152
153This is the reference evaluator for queries. However it may not be the only
154engine that evaluates them; external engines, such as SQL, might be delegated
155the responsibility of evaluating queries in a search context.
156
157Name resolution depends on the context in which the name is used. A name
158on the LHS of the dot and where operators may only be a form name, or a META:
159name, referred to as a "restricted name". A name anywhere else can be
160a META: name, a field name, or one of the shortcuts (such as "web", "name"
161etc). Fields and forms are looked up by calling the =getField= and
162=getForm= methods in the query engine respectively.
163
164=cut
165
166
# spent 1.21s (543ms+664ms) within Foswiki::Query::Node::evaluate which was called 26438 times, avg 46µs/call: # 8769 times (406ms+-406ms) by Foswiki::Query::ConditionalOP::evalTest at line 69 of /var/www/foswikidev/core/lib/Foswiki/Query/ConditionalOP.pm, avg 0s/call # 8769 times (36.9ms+-36.9ms) by Foswiki::Query::ConditionalOP::evalTest at line 70 of /var/www/foswikidev/core/lib/Foswiki/Query/ConditionalOP.pm, avg 0s/call # 8760 times (98.7ms+1.10s) by Foswiki::Store::QueryAlgorithms::BruteForce::_webQuery at line 214 of /var/www/foswikidev/core/lib/Foswiki/Store/QueryAlgorithms/BruteForce.pm, avg 137µs/call # 80 times (546µs+0s) by Foswiki::Query::Node::simplify at line 348, avg 7µs/call # 43 times (392µs+6.93ms) by Foswiki::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Macros/IF.pm:50] at line 42 of /var/www/foswikidev/core/lib/Foswiki/Macros/IF.pm, avg 170µs/call # 12 times (82µs+-82µs) by Foswiki::Query::OP_and::evaluate at line 35 of /var/www/foswikidev/core/lib/Foswiki/Query/OP_and.pm, avg 0s/call # 3 times (22µs+-22µs) by Foswiki::Query::OP_or::evaluate at line 35 of /var/www/foswikidev/core/lib/Foswiki/Query/OP_or.pm, avg 0s/call # once (8µs+0s) by Foswiki::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Macros/QUERY.pm:68] at line 66 of /var/www/foswikidev/core/lib/Foswiki/Macros/QUERY.pm # once (4µs+-4µs) by Foswiki::If::OP_allows::evaluate at line 45 of /var/www/foswikidev/core/lib/Foswiki/If/OP_allows.pm
sub evaluate {
167264385.31ms my $this = shift;
168 ASSERT( scalar(@_) % 2 == 0 ) if DEBUG;
169264382.88ms my $result;
170
171 print STDERR ( ' ' x $ind ) . $this->stringify() if MONITOR_EVAL;
172
1732643818.8ms if ( !ref( $this->{op} ) ) {
1741761415.4ms my %domain = @_;
1751761417.8ms if ( $this->{op} == Foswiki::Infix::Node::NAME
176 && defined $domain{data} )
177 {
178 print STDERR ' NAME' if MONITOR_EVAL;
179876012.2ms if ( lc( $this->{params}[0] ) eq 'now' ) {
180 $result = time();
181 }
182 elsif ( lc( $this->{params}[0] ) eq 'undefined' ) {
183 $result = undef;
184 }
185 else {
186
187 # a name; either the form name or a field name.
188 # Look it up in $domain{data}
1898760241ms eval "require $Foswiki::cfg{Store}{QueryAlgorithm}";
# spent 22.7ms executing statements in 8760 string evals (merged)
19087601.83ms if ($@) {
191 print STDERR ' BOOM ' if MONITOR_EVAL;
192 die $@;
193 }
19487607.12ms my $name = $this->{params}[0];
19587606.26ms my $realname = $Foswiki::Meta::aliases{$name} || $name;
19687606.42ms if ( $domain{restricted_name} && $realname !~ /^META:/ ) {
197
198 # Only a form name and META: expressions are
199 # legal on the LHS of a dot or where expression
200 print STDERR " form $name" if MONITOR_EVAL;
201 $result =
202 $Foswiki::cfg{Store}{QueryAlgorithm}
203 ->getForm( $this, $domain{data}, $name );
204 }
205 else {
206 print STDERR " field $name" if MONITOR_EVAL;
207876061.8ms876014.3ms $name = $realname
# spent 14.3ms making 8760 calls to UNIVERSAL::isa, avg 2µs/call
208 if UNIVERSAL::isa( $domain{data}, 'Foswiki::Meta' );
209876017.0ms8760299ms $result = $this->_getField( $domain{data}, $name );
# spent 299ms making 8760 calls to Foswiki::Query::Node::_getField, avg 34µs/call
210 }
211 }
212 }
213 else {
214 print STDERR ' constant' if MONITOR_EVAL;
21588545.16ms $result = $this->{params}[0];
216 }
217 }
218 else {
219 print STDERR " {\n" if MONITOR_EVAL;
2208824621µs $ind++ if MONITOR_EVAL;
221882413.0ms my %params = @_;
22288243.59ms delete $params{no_fields}; # kill semaphore
223882437.4ms88241.11s $result = $this->{op}->evaluate( $this, %params );
# spent 1.10s making 8763 calls to Foswiki::Query::OP_eq::evaluate, avg 126µs/call # spent 4.37ms making 16 calls to Foswiki::If::OP_dollar::evaluate, avg 273µs/call # spent 1.85ms making 8 calls to Foswiki::Query::OP_and::evaluate, avg 231µs/call # spent 1.26ms making 6 calls to Foswiki::Query::OP_ne::evaluate, avg 210µs/call # spent 1.18ms making 13 calls to Foswiki::If::OP_defined::evaluate, avg 91µs/call # spent 515µs making 1 call to Foswiki::Query::OP_or::evaluate # spent 433µs making 4 calls to Foswiki::If::OP_istopic::evaluate, avg 108µs/call # spent 208µs making 12 calls to Foswiki::If::OP_context::evaluate, avg 17µs/call # spent 180µs making 1 call to Foswiki::If::OP_allows::evaluate
224 $ind-- if MONITOR_EVAL;
22588246.07ms print STDERR ( ' ' x $ind ) . '}' . $this->{op}->{name}
226 if MONITOR_EVAL;
227 }
228 if (MONITOR_EVAL) {
229 print STDERR ' -> ' . toString($result);
230 my %domain = @_;
231 print STDERR " IN " . $domain{tom}->getPath() . "\n"
232 if ref( $domain{tom} ) && !$ind;
233 print STDERR "\n";
234 }
2352643887.1ms return $result;
236}
237
238# Private method to fetch field values
239
# spent 299ms (132+167) within Foswiki::Query::Node::_getField which was called 8760 times, avg 34µs/call: # 8760 times (132ms+167ms) by Foswiki::Query::Node::evaluate at line 209, avg 34µs/call
sub _getField {
24087606.23ms my ( $this, $data, $name ) = @_;
241
242876090.2ms17520167ms if ( UNIVERSAL::isa( $data, 'Foswiki::Meta' ) ) {
# spent 162ms making 8760 calls to Foswiki::Store::Interfaces::QueryAlgorithm::getField, avg 18µs/call # spent 4.79ms making 8760 calls to UNIVERSAL::isa, avg 547ns/call
243
244 # If the data is a Foswiki::Meta, pass on to the query algorithm
245 return $Foswiki::cfg{Store}{QueryAlgorithm}
246 ->getField( $this, $data, $name );
247 }
248
249 if ( ref($data) eq 'ARRAY' ) {
250
251 # Array objects are returned during evaluation, e.g. when
252 # a subset of an array is matched for further processing.
253
254 # Indexing an array object. The index will be one of:
255 # 1. An integer, which is an implicit index='x' query
256 # 2. A name, which is an implicit name='x' query
257 if ( $name =~ m/^\d+$/ ) {
258
259 # Integer index
260 return $data->[$name];
261 }
262
263 # String index
264 my @res;
265
266 # Get all array entries that match the field
267 foreach my $f (@$data) {
268 my $val = $this->_getField( $f, $name );
269 push( @res, $val ) if defined($val);
270 }
271 return \@res if ( scalar(@res) );
272
273 # The field name wasn't explicitly seen in any of the records.
274 # Try again, this time matching 'name' and returning 'value'
275 foreach my $f (@$data) {
276 next unless ref($f) eq 'HASH';
277 if ( $f->{name}
278 && $f->{name} eq $name
279 && defined $f->{value} )
280 {
281 push( @res, $f->{value} );
282 }
283 }
284 return \@res if ( scalar(@res) );
285 return undef;
286 }
287
288 if ( ref($data) eq 'HASH' ) {
289
290 # A hash object may be returned when a sub-object of a Foswiki::Meta
291 # object has been matched.
292 return $data->{ $this->{params}[0] };
293 }
294
295 # Last ditch - treat it as a constant
296 return $this->{params}[0];
297}
298
299=begin TML
300
301---++ ObjectMethod evaluatesToConstant(%opts)
302
303Support for expression optimisation/hoisting.
304
305Determine if this node evaluates to a constant or not. "Constant" is defined
306as "anything that doesn't involve actually looking in searched topics".
307This function takes the same parameters (%domain) as evaluate(). Note that
308no reference to the tom or data web or topic will be made, so you can
309simply pass an arbitrary Foswiki::Meta.
310
311=cut
312
313
# spent 1.75ms (1.05+701µs) within Foswiki::Query::Node::evaluatesToConstant which was called 400 times, avg 4µs/call: # 240 times (633µs+773µs) by Foswiki::Query::Node::simplify at line 347, avg 6µs/call # 120 times (280µs+-280µs) by Foswiki::Query::OP::evaluatesToConstant at line 66 of /var/www/foswikidev/core/lib/Foswiki/Query/OP.pm, avg 0s/call # 40 times (141µs+208µs) by Foswiki::Store::QueryAlgorithms::BruteForce::_webQuery at line 81 of /var/www/foswikidev/core/lib/Foswiki/Store/QueryAlgorithms/BruteForce.pm, avg 9µs/call
sub evaluatesToConstant {
31440071µs my $this = shift;
31540063µs my $c = 0;
316400511µs120981µs if ( ref( $this->{op} ) ) {
# spent 981µs making 120 calls to Foswiki::Query::OP::evaluatesToConstant, avg 8µs/call
317 $c = $this->{op}->evaluatesToConstant( $this, @_ );
318 }
319 elsif ( $this->{op} == Foswiki::Infix::Node::NUMBER ) {
320 $c = 1;
321 }
322 elsif ( $this->{op} == Foswiki::Infix::Node::STRING ) {
323 $c = 1;
324 }
325 print STDERR $this->stringify() . " is "
326 . ( $c ? '' : 'not ' )
327 . "constant\n"
328 if MONITOR_FOLD;
3294007.28ms return $c;
330}
331
332=begin TML
333
334---++ ObjectMethod simplify(%opts)
335
336Simplify the query by spotting constant expressions and evaluating them,
337replacing the constant expression with an atomic value in the expression tree.
338This function takes the same parameters (%domain) as evaluate(). Note that
339no reference to the tom or data web or topic will be made, so you can
340simply pass an arbitrary Foswiki::Meta.
341
342=cut
343
344
# spent 12.5ms (8.90+3.58) within Foswiki::Query::Node::simplify which was called 240 times, avg 52µs/call: # 160 times (7.70ms+-7.70ms) by Foswiki::Query::Node::simplify at line 354, avg 0s/call # 40 times (471µs+8.32ms) by Foswiki::Store::QueryAlgorithms::BruteForce::_webQuery at line 79 of /var/www/foswikidev/core/lib/Foswiki/Store/QueryAlgorithms/BruteForce.pm, avg 220µs/call # 40 times (728µs+2.96ms) by Foswiki::Store::Interfaces::QueryAlgorithm::query at line 98 of /var/www/foswikidev/core/lib/Foswiki/Store/Interfaces/QueryAlgorithm.pm, avg 92µs/call
sub simplify {
34524057µs my $this = shift;
346
347240725µs2401.41ms if ( $this->evaluatesToConstant(@_) ) {
# spent 1.41ms making 240 calls to Foswiki::Query::Node::evaluatesToConstant, avg 6µs/call
34880172µs80546µs my $c = $this->evaluate(@_);
# spent 546µs making 80 calls to Foswiki::Query::Node::evaluate, avg 7µs/call
3498023µs $c = 0 unless defined $c;
35080179µs801.34ms $this->_freeze($c);
# spent 1.34ms making 80 calls to Foswiki::Query::Node::_freeze, avg 17µs/call
351 }
352 else {
353160149µs for my $f ( @{ $this->{params} } ) {
3542401.08ms400290µs if ( UNIVERSAL::can( $f, 'simplify' ) ) {
# spent 290µs making 240 calls to UNIVERSAL::can, avg 1µs/call # spent 9.91ms making 160 calls to Foswiki::Query::Node::simplify, avg 62µs/call, recursion: max depth 1, sum of overlapping time 9.91ms
355 $f->simplify(@_);
356 }
357 }
358 }
359}
360
361
# spent 1.34ms (756µs+583µs) within Foswiki::Query::Node::_freeze which was called 80 times, avg 17µs/call: # 80 times (756µs+583µs) by Foswiki::Query::Node::simplify at line 350, avg 17µs/call
sub _freeze {
3628075µs my ( $this, $c ) = @_;
363
36480320µs80301µs if ( ref($c) eq 'ARRAY' ) {
# spent 301µs making 80 calls to Foswiki::Query::OP::isNumber, avg 4µs/call
365 $this->_makeArray($c);
366 }
367 elsif ( ref($c) eq 'HASH' ) {
368 $this->convertToLeaf( Foswiki::Infix::Node::HASH, $c );
369 }
370 elsif ( ref($c) eq 'Foswiki::Meta' ) {
371 $this->convertToLeaf( Foswiki::Infix::Node::META, $c );
372 }
373 elsif ( Foswiki::Query::OP::isNumber($c) ) {
374 $this->convertToLeaf( Foswiki::Infix::Node::NUMBER, $c );
375 }
376 else {
377
378 #Item10703: can't convert a non-scalar to a STRING without further processing.
37980208µs80282µs if ( ref($c) eq '' ) {
# spent 282µs making 80 calls to Foswiki::Infix::Node::convertToLeaf, avg 4µs/call
380 $this->convertToLeaf( Foswiki::Infix::Node::STRING, $c );
381 }
382 else {
383 print STDERR "_freeze" . ref($c) . "\n" if MONITOR_FOLD;
384 }
385 }
386}
387
388sub _makeArray {
389 my ( $this, $array ) = @_;
390 if ( scalar(@$array) == 0 ) {
391 $this->{op} = $emptyExprOp;
392 }
393 elsif ( scalar(@$array) == 1 ) {
394 die unless defined $array->[0];
395 $this->_freeze( $array->[0] );
396 }
397 else {
398 $this->{op} = $commaOp;
399 $this->{params}[0] = Foswiki::Query::Node->newNode($commaOp);
400 $this->{params}[0]->_freeze( shift(@$array) );
401 $this->{params}[1] = Foswiki::Query::Node->newNode($commaOp);
402 $this->{params}[1]->_freeze($array);
403 }
404}
405
406=begin TML
407
408---++ ObjectMethod tokens() -> []
409Provided for compatibility with Foswiki::Search::Node
410
411=cut
412
413sub tokens {
414 return [];
415}
416
417=begin TML
418
419---++ ObjectMethod isEmpty() -> $boolean
420Provided for compatibility with Foswiki::Search::Node
421
422=cut
423
424
# spent 139µs within Foswiki::Query::Node::isEmpty which was called 40 times, avg 3µs/call: # 40 times (139µs+0s) by Foswiki::Store::Interfaces::QueryAlgorithm::query at line 84 of /var/www/foswikidev/core/lib/Foswiki/Store/Interfaces/QueryAlgorithm.pm, avg 3µs/call
sub isEmpty {
42540133µs return 0;
426}
427
42815µs1;
429__END__