Filename | /usr/local/src/github.com/foswiki/core/lib/Foswiki/Store/Interfaces/QueryAlgorithm.pm |
Statements | Executed 280 statements in 6.82ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 3.26ms | 3.53ms | BEGIN@17 | Foswiki::Store::Interfaces::QueryAlgorithm::
22 | 1 | 1 | 1.35ms | 1.64s | __ANON__[:187] | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 677µs | 811µs | BEGIN@20 | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 615µs | 1.30ms | BEGIN@9 | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 472µs | 648µs | BEGIN@8 | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 218µs | 1.65s | query | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 91µs | 262µs | getListOfWebs | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 79µs | 627µs | getWebIterator | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 55µs | 567µs | __ANON__[:228] | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 41µs | 1.65s | __ANON__[:109] | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 32µs | 75µs | addACLFilter | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 31µs | 129µs | BEGIN@342 | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 29µs | 107µs | BEGIN@6 | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 28µs | 35µs | BEGIN@4 | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 21µs | 38µs | BEGIN@5 | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 19µs | 19µs | new | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 16µs | 119µs | BEGIN@23 | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 11µs | 11µs | BEGIN@18 | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 11µs | 11µs | BEGIN@11 | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 10µs | 10µs | addPager | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 10µs | 10µs | BEGIN@10 | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 10µs | 10µs | BEGIN@21 | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 10µs | 10µs | BEGIN@19 | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 10µs | 10µs | BEGIN@15 | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 9µs | 9µs | BEGIN@13 | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 9µs | 9µs | BEGIN@14 | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 9µs | 9µs | BEGIN@16 | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 9µs | 9µs | BEGIN@12 | Foswiki::Store::Interfaces::QueryAlgorithm::
2 | 2 | 1 | 7µs | 7µs | CORE:match (opcode) | Foswiki::Store::Interfaces::QueryAlgorithm::
1 | 1 | 1 | 5µs | 5µs | CORE:sort (opcode) | Foswiki::Store::Interfaces::QueryAlgorithm::
2 | 2 | 1 | 4µs | 4µs | CORE:subst (opcode) | Foswiki::Store::Interfaces::QueryAlgorithm::
0 | 0 | 0 | 0s | 0s | getField | Foswiki::Store::Interfaces::QueryAlgorithm::
0 | 0 | 0 | 0s | 0s | getForm | Foswiki::Store::Interfaces::QueryAlgorithm::
0 | 0 | 0 | 0s | 0s | getRefTopic | Foswiki::Store::Interfaces::QueryAlgorithm::
0 | 0 | 0 | 0s | 0s | getRev1Info | Foswiki::Store::Interfaces::QueryAlgorithm::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # See bottom of file for license and copyright information | ||||
2 | package Foswiki::Store::Interfaces::QueryAlgorithm; | ||||
3 | |||||
4 | 2 | 48µs | 2 | 42µs | # spent 35µs (28+7) within Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@4 which was called:
# once (28µs+7µs) by Foswiki::Store::QueryAlgorithms::BruteForce::BEGIN@29 at line 4 # spent 35µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@4
# spent 7µs making 1 call to strict::import |
5 | 2 | 45µs | 2 | 56µs | # spent 38µs (21+17) within Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@5 which was called:
# once (21µs+17µs) by Foswiki::Store::QueryAlgorithms::BruteForce::BEGIN@29 at line 5 # spent 38µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@5
# spent 18µs making 1 call to warnings::import |
6 | 2 | 58µs | 2 | 184µs | # spent 107µs (29+77) within Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@6 which was called:
# once (29µs+77µs) by Foswiki::Store::QueryAlgorithms::BruteForce::BEGIN@29 at line 6 # spent 107µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@6
# spent 77µs making 1 call to Assert::import |
7 | |||||
8 | 2 | 157µs | 1 | 648µs | # spent 648µs (472+175) within Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@8 which was called:
# once (472µs+175µs) by Foswiki::Store::QueryAlgorithms::BruteForce::BEGIN@29 at line 8 # spent 648µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@8 |
9 | 2 | 159µs | 1 | 1.30ms | # spent 1.30ms (615µs+688µs) within Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@9 which was called:
# once (615µs+688µs) by Foswiki::Store::QueryAlgorithms::BruteForce::BEGIN@29 at line 9 # spent 1.30ms making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@9 |
10 | 2 | 43µs | 1 | 10µs | # spent 10µs within Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@10 which was called:
# once (10µs+0s) by Foswiki::Store::QueryAlgorithms::BruteForce::BEGIN@29 at line 10 # spent 10µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@10 |
11 | 2 | 44µs | 1 | 11µs | # spent 11µs within Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@11 which was called:
# once (11µs+0s) by Foswiki::Store::QueryAlgorithms::BruteForce::BEGIN@29 at line 11 # spent 11µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@11 |
12 | 2 | 41µs | 1 | 9µs | # spent 9µs within Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@12 which was called:
# once (9µs+0s) by Foswiki::Store::QueryAlgorithms::BruteForce::BEGIN@29 at line 12 # spent 9µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@12 |
13 | 2 | 41µs | 1 | 9µs | # spent 9µs within Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@13 which was called:
# once (9µs+0s) by Foswiki::Store::QueryAlgorithms::BruteForce::BEGIN@29 at line 13 # spent 9µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@13 |
14 | 2 | 41µs | 1 | 9µs | # spent 9µs within Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@14 which was called:
# once (9µs+0s) by Foswiki::Store::QueryAlgorithms::BruteForce::BEGIN@29 at line 14 # spent 9µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@14 |
15 | 2 | 41µs | 1 | 10µs | # spent 10µs within Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@15 which was called:
# once (10µs+0s) by Foswiki::Store::QueryAlgorithms::BruteForce::BEGIN@29 at line 15 # spent 10µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@15 |
16 | 2 | 41µs | 1 | 9µs | # spent 9µs within Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@16 which was called:
# once (9µs+0s) by Foswiki::Store::QueryAlgorithms::BruteForce::BEGIN@29 at line 16 # spent 9µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@16 |
17 | 2 | 201µs | 1 | 3.53ms | # spent 3.53ms (3.26+278µs) within Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@17 which was called:
# once (3.26ms+278µs) by Foswiki::Store::QueryAlgorithms::BruteForce::BEGIN@29 at line 17 # spent 3.53ms making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@17 |
18 | 2 | 42µs | 1 | 11µs | # spent 11µs within Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@18 which was called:
# once (11µs+0s) by Foswiki::Store::QueryAlgorithms::BruteForce::BEGIN@29 at line 18 # spent 11µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@18 |
19 | 2 | 41µs | 1 | 10µs | # spent 10µs within Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@19 which was called:
# once (10µs+0s) by Foswiki::Store::QueryAlgorithms::BruteForce::BEGIN@29 at line 19 # spent 10µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@19 |
20 | 2 | 157µs | 1 | 811µs | # spent 811µs (677+135) within Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@20 which was called:
# once (677µs+135µs) by Foswiki::Store::QueryAlgorithms::BruteForce::BEGIN@29 at line 20 # spent 811µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@20 |
21 | 2 | 48µs | 1 | 10µs | # spent 10µs within Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@21 which was called:
# once (10µs+0s) by Foswiki::Store::QueryAlgorithms::BruteForce::BEGIN@29 at line 21 # spent 10µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@21 |
22 | |||||
23 | 2 | 1.97ms | 2 | 221µs | # spent 119µs (16+102) within Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@23 which was called:
# once (16µs+102µs) by Foswiki::Store::QueryAlgorithms::BruteForce::BEGIN@29 at line 23 # spent 119µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@23
# spent 102µs making 1 call to constant::import |
24 | |||||
25 | =begin TML | ||||
26 | |||||
27 | ---+ package Foswiki::Store::Interfaces::QueryAlgorithm | ||||
28 | |||||
29 | Interface to query algorithms. | ||||
30 | Implementations of this interface are found in Foswiki/Store/*Algorithms. | ||||
31 | |||||
32 | The contract with query algorithms is specified by this interface description, | ||||
33 | plus the 'query' unit tests in Fn_SEARCH. | ||||
34 | The interface provides a default implementation of the 'getField' method, | ||||
35 | but all other methods are pure virtual and must be provided by subclasses. | ||||
36 | Note that if a subclass re-implements getField, then there is no direct | ||||
37 | need to inherit from this class (as long as all the methods are implemented). | ||||
38 | |||||
39 | =cut | ||||
40 | |||||
41 | =begin TML | ||||
42 | |||||
43 | ---++ ClassMethod new( $class, ) -> $cereal | ||||
44 | |||||
45 | =cut | ||||
46 | |||||
47 | # spent 19µs within Foswiki::Store::Interfaces::QueryAlgorithm::new which was called:
# once (19µs+0s) by Foswiki::Store::QueryAlgorithms::BruteForce::new at line 55 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Store/QueryAlgorithms/BruteForce.pm | ||||
48 | 1 | 2µs | my $class = shift; | ||
49 | 1 | 12µs | my $this = bless( {}, $class ); | ||
50 | 1 | 10µs | return $this; | ||
51 | } | ||||
52 | |||||
53 | =begin TML | ||||
54 | |||||
55 | ---++ ObjectMethod query( $query, $webs, $inputTopicSet, $session, $options ) -> $infoCache | ||||
56 | * =$query= - A Foswiki::Query::Node object | ||||
57 | * =$web= - name of the web being searched, or may be an array reference | ||||
58 | to a set of webs to search | ||||
59 | * =$inputTopicSet= - iterator over names of topics in that web to search | ||||
60 | * =$session= - reference to the store object | ||||
61 | * =$options= - hash of requested options | ||||
62 | This is the top-level interface to a query algorithm. A store module can call | ||||
63 | this method to start the 'hard work' query process. That process will call | ||||
64 | back to the =getField= method in this module to evaluate leaf data in the | ||||
65 | store. | ||||
66 | |||||
67 | To monitor the hoisting and evaluation processes, use the MONITOR_EVAL | ||||
68 | setting in Foswiki::Query::Node | ||||
69 | |||||
70 | this is a default implementation of the query() sub that uses the specific algorithms' _webQuery member function. | ||||
71 | |||||
72 | =cut | ||||
73 | |||||
74 | # spent 1.65s (218µs+1.65) within Foswiki::Store::Interfaces::QueryAlgorithm::query which was called:
# once (218µs+1.65s) by Foswiki::Store::VC::Store::query at line 575 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Store/VC/Store.pm | ||||
75 | 1 | 2µs | my ( $this, $query, $inputTopicSet, $session, $options ) = @_; | ||
76 | |||||
77 | 1 | 6µs | 1 | 4µs | if ( $query->isEmpty() ) # spent 4µs making 1 call to Foswiki::Query::Node::isEmpty |
78 | { #TODO: does this do anything in a type=query context? | ||||
79 | return Foswiki::Search::InfoCache->new( $session, '' ); | ||||
80 | } | ||||
81 | |||||
82 | 1 | 2µs | my $date = $options->{'date'} || ''; | ||
83 | |||||
84 | # Fold constants | ||||
85 | 1 | 8µs | 1 | 60µs | my $context = Foswiki::Meta->new( $session, $session->{webName} ); # spent 60µs making 1 call to Foswiki::Meta::new |
86 | print STDERR "--- before: " . $query->stringify() . "\n" if MONITOR; | ||||
87 | 1 | 9µs | 1 | 177µs | $query->simplify( tom => $context, data => $context ); # spent 177µs making 1 call to Foswiki::Query::Node::simplify |
88 | print STDERR "--- simplified: " . $query->stringify() . "\n" if MONITOR; | ||||
89 | |||||
90 | 1 | 9µs | 1 | 627µs | my $webItr = $this->getWebIterator( $session, $options ); # spent 627µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::getWebIterator |
91 | |||||
92 | #do the search | ||||
93 | my $queryItr = Foswiki::Iterator::ProcessIterator->new( | ||||
94 | $webItr, | ||||
95 | # spent 1.65s (41µs+1.65) within Foswiki::Store::Interfaces::QueryAlgorithm::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Store/Interfaces/QueryAlgorithm.pm:109] which was called:
# once (41µs+1.65s) by Foswiki::Iterator::ProcessIterator::next at line 51 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Iterator/ProcessIterator.pm | ||||
96 | 1 | 2µs | my $web = shift; | ||
97 | 1 | 1µs | my $params = shift; | ||
98 | |||||
99 | 1 | 7µs | 1 | 1.65s | my $infoCache = # spent 1.65s making 1 call to Foswiki::Store::QueryAlgorithms::BruteForce::_webQuery |
100 | $this->_webQuery( $params->{query}, $web, $params->{inputset}, | ||||
101 | $params->{session}, $params->{options} ); | ||||
102 | |||||
103 | 1 | 2µs | if ($date) { | ||
104 | $infoCache->filterByDate($date); | ||||
105 | } | ||||
106 | 1 | 12µs | 1 | 746µs | $infoCache->sortResults($options); # spent 746µs making 1 call to Foswiki::Search::InfoCache::sortResults |
107 | |||||
108 | 1 | 663µs | return $infoCache; | ||
109 | }, | ||||
110 | { | ||||
111 | 1 | 15µs | 1 | 51µs | query => $query, # spent 51µs making 1 call to Foswiki::Iterator::ProcessIterator::new |
112 | inputset => $inputTopicSet, | ||||
113 | session => $session, | ||||
114 | options => $options | ||||
115 | } | ||||
116 | ); | ||||
117 | |||||
118 | #sadly, the resultSet currently wants a real array, rather than an unevaluated iterator | ||||
119 | 1 | 9µs | 1 | 1.65s | my @resultCacheList = $queryItr->all(); # spent 1.65s making 1 call to Foswiki::Iterator::ProcessIterator::all |
120 | |||||
121 | #and thus if the ResultSet could be created using an unevaluated process itr, which would somehow rely on........ eeeeek | ||||
122 | 1 | 26µs | 2 | 56µs | my $resultset = # spent 47µs making 1 call to Foswiki::Search::ResultSet::new
# spent 8µs making 1 call to Foswiki::isTrue |
123 | new Foswiki::Search::ResultSet( \@resultCacheList, $options->{groupby}, | ||||
124 | $options->{order}, Foswiki::isTrue( $options->{reverse} ) ); | ||||
125 | |||||
126 | #consider if this is un-necessary - and that we can steal the web order sort from DBIStore and push up to the webItr | ||||
127 | 1 | 2µs | if ($date) { | ||
128 | $resultset->filterByDate($date); | ||||
129 | } | ||||
130 | 1 | 9µs | 1 | 34µs | $resultset->sortResults($options); # spent 34µs making 1 call to Foswiki::Search::ResultSet::sortResults |
131 | |||||
132 | #add permissions check | ||||
133 | 1 | 21µs | 1 | 75µs | $resultset = $this->addACLFilter( $resultset, $options ); # spent 75µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::addACLFilter |
134 | |||||
135 | #add paging if applicable. | ||||
136 | 1 | 61µs | 1 | 10µs | $this->addPager( $resultset, $options ); # spent 10µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::addPager |
137 | } | ||||
138 | |||||
139 | # spent 10µs within Foswiki::Store::Interfaces::QueryAlgorithm::addPager which was called:
# once (10µs+0s) by Foswiki::Store::Interfaces::QueryAlgorithm::query at line 136 | ||||
140 | 1 | 2µs | my $this = shift; | ||
141 | 1 | 1µs | my $resultset = shift; | ||
142 | 1 | 1µs | my $options = shift; | ||
143 | |||||
144 | 1 | 2µs | if ( $options->{paging_on} ) { | ||
145 | $resultset = | ||||
146 | new Foswiki::Iterator::PagerIterator( $resultset, | ||||
147 | $options->{pagesize}, $options->{showpage} ); | ||||
148 | } | ||||
149 | |||||
150 | 1 | 8µs | return $resultset; | ||
151 | } | ||||
152 | |||||
153 | # spent 75µs (32+43) within Foswiki::Store::Interfaces::QueryAlgorithm::addACLFilter which was called:
# once (32µs+43µs) by Foswiki::Store::Interfaces::QueryAlgorithm::query at line 133 | ||||
154 | 1 | 2µs | my $this = shift; | ||
155 | 1 | 1µs | my $resultset = shift; | ||
156 | 1 | 1µs | my $options = shift; | ||
157 | |||||
158 | #add filtering for ACL test - probably should make it a seperate filter | ||||
159 | $resultset = new Foswiki::Iterator::FilterIterator( | ||||
160 | $resultset, | ||||
161 | # spent 1.64s (1.35ms+1.64) within Foswiki::Store::Interfaces::QueryAlgorithm::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Store/Interfaces/QueryAlgorithm.pm:187] which was called 22 times, avg 74.7ms/call:
# 22 times (1.35ms+1.64s) by Foswiki::Iterator::FilterIterator::hasNext at line 66 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Iterator/FilterIterator.pm, avg 74.7ms/call | ||||
162 | 22 | 37µs | my $listItem = shift; | ||
163 | 22 | 28µs | my $params = shift; | ||
164 | |||||
165 | #ACL test | ||||
166 | 22 | 128µs | 22 | 1.71ms | my ( $web, $topic ) = # spent 1.71ms making 22 calls to Foswiki::Func::normalizeWebTopicName, avg 78µs/call |
167 | Foswiki::Func::normalizeWebTopicName( '', $listItem ); | ||||
168 | |||||
169 | 22 | 315µs | 66 | 1.63s | my $topicMeta = # spent 1.63s making 22 calls to Foswiki::MetaCache::addMeta, avg 74.2ms/call
# spent 179µs making 22 calls to Foswiki::Search::metacache, avg 8µs/call
# spent 166µs making 22 calls to Foswiki::search, avg 8µs/call |
170 | $Foswiki::Plugins::SESSION->search->metacache->addMeta( $web, | ||||
171 | $topic ); | ||||
172 | 22 | 30µs | if ( not defined($topicMeta) ) { | ||
173 | |||||
174 | #TODO: OMG! Search.pm relies on Meta::load (in the metacache) returning a meta object even when the topic does not exist. | ||||
175 | #lets change that | ||||
176 | $topicMeta = | ||||
177 | new Foswiki::Meta( $Foswiki::Plugins::SESSION, $web, $topic ); | ||||
178 | } | ||||
179 | 22 | 348µs | 66 | 7.86ms | my $info = # spent 7.51ms making 22 calls to Foswiki::MetaCache::get, avg 341µs/call
# spent 186µs making 22 calls to Foswiki::search, avg 8µs/call
# spent 166µs making 22 calls to Foswiki::Search::metacache, avg 8µs/call |
180 | $Foswiki::Plugins::SESSION->search->metacache->get( $web, $topic, | ||||
181 | $topicMeta ); | ||||
182 | ##ASSERT( defined( $info->{tom} ) ) if DEBUG; | ||||
183 | |||||
184 | # Check security (don't show topics the current user does not have permission to view) | ||||
185 | 22 | 34µs | return 0 unless ( $info->{allowView} ); | ||
186 | 22 | 152µs | return 1; | ||
187 | }, | ||||
188 | 1 | 28µs | 1 | 42µs | $options # spent 42µs making 1 call to Foswiki::Iterator::FilterIterator::new |
189 | ); | ||||
190 | } | ||||
191 | |||||
192 | # spent 627µs (79+548) within Foswiki::Store::Interfaces::QueryAlgorithm::getWebIterator which was called:
# once (79µs+548µs) by Foswiki::Store::Interfaces::QueryAlgorithm::query at line 90 | ||||
193 | 1 | 2µs | my $this = shift; | ||
194 | 1 | 1µs | my $session = shift; | ||
195 | 1 | 2µs | my $options = shift; | ||
196 | |||||
197 | 1 | 2µs | my $webNames = $options->{web} || ''; | ||
198 | 1 | 2µs | my $recurse = $options->{'recurse'} || ''; | ||
199 | 1 | 12µs | 1 | 175µs | my $isAdmin = $session->{users}->isAdmin( $session->{user} ); # spent 175µs making 1 call to Foswiki::Users::isAdmin |
200 | |||||
201 | #get a complete list of webs to search | ||||
202 | 1 | 17µs | 1 | 5µs | my $searchAllFlag = ( $webNames =~ /(^|[\,\s])(all|on)([\,\s]|$)/i ); # spent 5µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::CORE:match |
203 | 1 | 6µs | 1 | 262µs | my @webs = # spent 262µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::getListOfWebs |
204 | Foswiki::Store::Interfaces::QueryAlgorithm::getListOfWebs( $webNames, | ||||
205 | $recurse, $searchAllFlag ); | ||||
206 | 1 | 16µs | 1 | 45µs | my $rawWebIter = new Foswiki::ListIterator( \@webs ); # spent 45µs making 1 call to Foswiki::ListIterator::new |
207 | my $webItr = new Foswiki::Iterator::FilterIterator( | ||||
208 | $rawWebIter, | ||||
209 | # spent 567µs (55+512) within Foswiki::Store::Interfaces::QueryAlgorithm::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/Store/Interfaces/QueryAlgorithm.pm:228] which was called:
# once (55µs+512µs) by Foswiki::Iterator::FilterIterator::hasNext at line 66 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Iterator/FilterIterator.pm | ||||
210 | 1 | 2µs | my $web = shift; | ||
211 | 1 | 1µs | my $params = shift; | ||
212 | |||||
213 | # can't process what ain't thar | ||||
214 | 1 | 11µs | 1 | 198µs | return 0 unless $session->webExists($web); # spent 198µs making 1 call to Foswiki::webExists |
215 | |||||
216 | 1 | 6µs | 1 | 97µs | my $webObject = Foswiki::Meta->new( $session, $web ); # spent 97µs making 1 call to Foswiki::Meta::new |
217 | 1 | 17µs | 2 | 217µs | my $thisWebNoSearchAll = # spent 208µs making 1 call to Foswiki::Meta::getPreference
# spent 9µs making 1 call to Foswiki::isTrue |
218 | Foswiki::isTrue( $webObject->getPreference('NOSEARCHALL') ); | ||||
219 | |||||
220 | # make sure we can report this web on an 'all' search | ||||
221 | # DON'T filter out unless it's part of an 'all' search. | ||||
222 | 1 | 2µs | return 0 | ||
223 | if ( $searchAllFlag | ||||
224 | && !$isAdmin | ||||
225 | && ( $thisWebNoSearchAll || $web =~ /^[\.\_]/ ) | ||||
226 | && $web ne $session->{webName} ); | ||||
227 | 1 | 12µs | return 1; | ||
228 | }, | ||||
229 | {} | ||||
230 | 1 | 25µs | 1 | 62µs | ); # spent 62µs making 1 call to Foswiki::Iterator::FilterIterator::new |
231 | } | ||||
232 | |||||
233 | =begin TML | ||||
234 | |||||
235 | ---++ StaticMethod getField($class, $node, $data, $field ) -> $result | ||||
236 | * =$class= is this package | ||||
237 | * =$node= is the query node | ||||
238 | * =$data= is the indexed object | ||||
239 | * =$field= is the scalar being used to index the object | ||||
240 | =getField= is used by the query evaluation code in Foswiki::Query::Node to get | ||||
241 | information about a leaf node, or 'field'. A field can be a name, or a literal, | ||||
242 | and the information it refers to can be a scalar, a reference to a hash, or | ||||
243 | a reference to an array. The exact interpretation of fields is | ||||
244 | context-dependant, according to reasonably complex rules best documented by | ||||
245 | the Fn_SEARCH unit test and System.QuerySearch. | ||||
246 | |||||
247 | The function must map the query schema to whatever the underlying | ||||
248 | store uses to store a topic. See System.QuerySearch for more information | ||||
249 | on the query schema. | ||||
250 | |||||
251 | =cut | ||||
252 | |||||
253 | # Implements Foswiki::Store::Interfaces::QueryAlgorithm | ||||
254 | sub getField { | ||||
255 | |||||
256 | # The getField function allows for Store specific optimisations | ||||
257 | # such as direct database lookups. The default implementation | ||||
258 | # works with the Foswiki::Meta object. | ||||
259 | my ( $this, $node, $data, $field ) = @_; | ||||
260 | |||||
261 | my $result; | ||||
262 | ASSERT( UNIVERSAL::isa( $data, 'Foswiki::Meta' ) ) if DEBUG; | ||||
263 | |||||
264 | print STDERR "\n----- getField($field)\n" if MONITOR; | ||||
265 | |||||
266 | if ( $field eq 'META:VERSIONS' ) { | ||||
267 | |||||
268 | # Disallow reloading versions for an object loaded here | ||||
269 | # SMELL: violates Foswiki::Meta encapsulation | ||||
270 | return [] if $data->{_loadedByQueryAlgorithm}; | ||||
271 | |||||
272 | # Oooh, this is inefficient. | ||||
273 | my $it = $data->getRevisionHistory(); | ||||
274 | my @revs; | ||||
275 | while ( $it->hasNext() ) { | ||||
276 | my $n = $it->next(); | ||||
277 | my $t = | ||||
278 | $this->getRefTopic( $data, $data->web(), $data->topic(), $n ); | ||||
279 | $t->{_loadedByQueryAlgorithm} = 1; | ||||
280 | push( @revs, $t ); | ||||
281 | } | ||||
282 | return \@revs; | ||||
283 | } | ||||
284 | |||||
285 | if ( $field =~ s/^META:// ) { | ||||
286 | if ( $field eq 'TOPICINFO' ) { | ||||
287 | |||||
288 | # Ensure the revision info is populated from the store | ||||
289 | $data->getRevisionInfo(); | ||||
290 | } | ||||
291 | if ( $field eq 'CREATEINFO' ) { | ||||
292 | |||||
293 | # Ensure the revision info is populated from the store | ||||
294 | return $this->getRev1Info($data); | ||||
295 | } | ||||
296 | |||||
297 | if ( $Foswiki::Query::Node::isArrayType{$field} ) { | ||||
298 | |||||
299 | # Array type, have to use find | ||||
300 | my @e = $data->find($field); | ||||
301 | return \@e; | ||||
302 | } | ||||
303 | return $data->get($field); | ||||
304 | } | ||||
305 | |||||
306 | if ( $field eq 'name' ) { | ||||
307 | |||||
308 | # Special accessor to compensate for lack of a topic | ||||
309 | # name anywhere in the saved fields of meta | ||||
310 | return $data->topic(); | ||||
311 | } | ||||
312 | |||||
313 | if ( $field eq 'text' ) { | ||||
314 | |||||
315 | # Special accessor to compensate for lack of the topic text | ||||
316 | # name anywhere in the saved fields of meta | ||||
317 | return $data->text(); | ||||
318 | } | ||||
319 | |||||
320 | if ( $field eq 'web' ) { | ||||
321 | |||||
322 | # Special accessor to compensate for lack of a web | ||||
323 | # name anywhere in the saved fields of meta | ||||
324 | return $data->web(); | ||||
325 | } | ||||
326 | |||||
327 | if ( $field eq ':topic_meta:' ) { | ||||
328 | |||||
329 | #TODO: Sven expects this to be replaced with a fast call to | ||||
330 | # versions[0] - atm, thats needlessly slow | ||||
331 | # return the meta obj itself | ||||
332 | # actually should do this the way the versions feature is | ||||
333 | # supposed to return a particular one.. | ||||
334 | # SMELL: CDot can't work out what this is for.... | ||||
335 | return $data; | ||||
336 | } | ||||
337 | |||||
338 | return undef unless $data->topic(); | ||||
339 | |||||
340 | if (MONITOR) { | ||||
341 | print STDERR "----- getField(FIELD value $field)\n"; | ||||
342 | 2 | 1.36ms | 2 | 228µs | # spent 129µs (31+98) within Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@342 which was called:
# once (31µs+98µs) by Foswiki::Store::QueryAlgorithms::BruteForce::BEGIN@29 at line 342 # spent 129µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::BEGIN@342
# spent 98µs making 1 call to Exporter::import |
343 | print STDERR Dumper($data) . "\n"; | ||||
344 | } | ||||
345 | |||||
346 | # SHORTCUT; not a predefined name; assume it's a field | ||||
347 | # 'name' instead. | ||||
348 | $result = $data->get( 'FIELD', $field ); | ||||
349 | $result = $result->{value} if $result; | ||||
350 | return $result; | ||||
351 | } | ||||
352 | |||||
353 | =begin TML | ||||
354 | |||||
355 | ---++ StaticMethod getForm($class, $node, $data, $field ) -> $result | ||||
356 | * =$class= is this package | ||||
357 | * =$node= is the query node | ||||
358 | * =$data= is the indexed object (must be Foswiki::Meta) | ||||
359 | * =$formname= is the required form name | ||||
360 | |||||
361 | =cut | ||||
362 | |||||
363 | sub getForm { | ||||
364 | my ( $this, $node, $data, $formname ) = @_; | ||||
365 | return undef unless $data->topic(); | ||||
366 | |||||
367 | my $form = $data->get('FORM'); | ||||
368 | return undef unless $form && $formname eq $form->{name}; | ||||
369 | print STDERR "----- getForm($formname)\n" if MONITOR; | ||||
370 | |||||
371 | # TODO: This is where multiple form support needs to reside. | ||||
372 | # Return the array of FIELD for further indexing. | ||||
373 | my @e = $data->find('FIELD'); | ||||
374 | return \@e; | ||||
375 | } | ||||
376 | |||||
377 | =begin TML | ||||
378 | |||||
379 | ---++ StaticMethod getRefTopic($class, $relativeTo, $web, $topic, $rev) -> $topic | ||||
380 | * =$class= is this package | ||||
381 | * =$relativeTo= is a pointer into the data structure of this module where | ||||
382 | the ref is relative to; for example, in the expression | ||||
383 | "other/'Web.Topic'" then =$relativeTo= is =other=. | ||||
384 | * =$web= the web; =Web= in the above example | ||||
385 | * =$topic= the topic; =Topic= in the above example | ||||
386 | * =$rev= optional revision to load | ||||
387 | This method supports the =Foswiki::Query::OP_ref= and =Foswiki::Query::OP_at= | ||||
388 | operators by abstracting the loading of a topic referred to in a string. | ||||
389 | |||||
390 | =cut | ||||
391 | |||||
392 | # Default implements gets a new Foswiki::Meta | ||||
393 | sub getRefTopic { | ||||
394 | |||||
395 | # Get a referenced topic | ||||
396 | my ( $this, $relativeTo, $w, $t, $rev ) = @_; | ||||
397 | my $meta = Foswiki::Meta->load( $relativeTo->session, $w, $t, $rev ); | ||||
398 | print STDERR "----- getRefTopic($w, $t) -> " | ||||
399 | . ( $meta->getLoadedRev() ) . "\n" | ||||
400 | if MONITOR; | ||||
401 | return $meta; | ||||
402 | } | ||||
403 | |||||
404 | =begin TML | ||||
405 | |||||
406 | ---++ StaticMethod getRev1Info($meta) -> %info | ||||
407 | |||||
408 | Return revision info for the first revision in %info with at least: | ||||
409 | * ={date}= in epochSec | ||||
410 | * ={author}= canonical user ID | ||||
411 | * ={version}= the revision number | ||||
412 | |||||
413 | =cut | ||||
414 | |||||
415 | # Default implements gets a new Foswiki::Meta | ||||
416 | sub getRev1Info { | ||||
417 | my $this = shift; | ||||
418 | my $meta = shift; | ||||
419 | |||||
420 | my $wikiname = $meta->getRev1Info('createwikiname'); | ||||
421 | return $meta->{_getRev1Info}->{rev1info}; | ||||
422 | } | ||||
423 | |||||
424 | =begin TML | ||||
425 | |||||
426 | ---+ getListOfWebs($webnames, $recurse, $serachAllFlag) -> @webs | ||||
427 | |||||
428 | Convert a comma separated list of webs into the list we'll process | ||||
429 | TODO: this is part of the Store now, and so should not need to reference | ||||
430 | Meta - it rather uses the store. | ||||
431 | |||||
432 | =cut | ||||
433 | |||||
434 | # spent 262µs (91+171) within Foswiki::Store::Interfaces::QueryAlgorithm::getListOfWebs which was called:
# once (91µs+171µs) by Foswiki::Store::Interfaces::QueryAlgorithm::getWebIterator at line 203 | ||||
435 | 1 | 2µs | my ( $webName, $recurse, $searchAllFlag ) = @_; | ||
436 | 1 | 1µs | my $session = $Foswiki::Plugins::SESSION; | ||
437 | |||||
438 | 1 | 1µs | my %excludeWeb; | ||
439 | 1 | 1µs | my @tmpWebs; | ||
440 | |||||
441 | #$web = Foswiki::Sandbox::untaint( $web,\&Foswiki::Sandbox::validateWebName ); | ||||
442 | |||||
443 | 1 | 3µs | if ($webName) { | ||
444 | 1 | 6µs | foreach my $web ( split( /[\,\s]+/, $webName ) ) { | ||
445 | 1 | 11µs | 1 | 2µs | $web =~ s#\.#/#go; # spent 2µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::CORE:subst |
446 | |||||
447 | # the web processing loop filters for valid web names, | ||||
448 | # so don't do it here. | ||||
449 | 1 | 11µs | 1 | 2µs | if ( $web =~ s/^-// ) { # spent 2µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::CORE:subst |
450 | $excludeWeb{$web} = 1; | ||||
451 | } | ||||
452 | else { | ||||
453 | 1 | 16µs | 2 | 56µs | if ( $web =~ /^(all|on)$/i # spent 54µs making 1 call to Foswiki::isTrue
# spent 3µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::CORE:match |
454 | || $Foswiki::cfg{EnableHierarchicalWebs} | ||||
455 | && Foswiki::isTrue($recurse) ) | ||||
456 | { | ||||
457 | my $webObject; | ||||
458 | my $prefix = "$web/"; | ||||
459 | if ( $web =~ /^(all|on)$/i ) { | ||||
460 | $webObject = Foswiki::Meta->new($session); | ||||
461 | $prefix = ''; | ||||
462 | } | ||||
463 | else { | ||||
464 | $web = Foswiki::Sandbox::untaint( $web, | ||||
465 | \&Foswiki::Sandbox::validateWebName ); | ||||
466 | ASSERT($web) if DEBUG; | ||||
467 | push( @tmpWebs, $web ); | ||||
468 | $webObject = Foswiki::Meta->new( $session, $web ); | ||||
469 | } | ||||
470 | my $it = $webObject->eachWeb(1); | ||||
471 | while ( $it->hasNext() ) { | ||||
472 | my $w = $prefix . $it->next(); | ||||
473 | next | ||||
474 | unless $Foswiki::WebFilter::user_allowed->ok( | ||||
475 | $session, $w ); | ||||
476 | $w = Foswiki::Sandbox::untaint( $w, | ||||
477 | \&Foswiki::Sandbox::validateWebName ); | ||||
478 | ASSERT($web) if DEBUG; | ||||
479 | push( @tmpWebs, $w ); | ||||
480 | } | ||||
481 | } | ||||
482 | else { | ||||
483 | 1 | 7µs | 1 | 106µs | $web = Foswiki::Sandbox::untaint( $web, # spent 106µs making 1 call to Foswiki::Sandbox::untaint |
484 | \&Foswiki::Sandbox::validateWebName ); | ||||
485 | 1 | 2µs | push( @tmpWebs, $web ); | ||
486 | } | ||||
487 | } | ||||
488 | } | ||||
489 | |||||
490 | } | ||||
491 | else { | ||||
492 | |||||
493 | # default to current web | ||||
494 | my $web = | ||||
495 | Foswiki::Sandbox::untaint( $session->{webName}, | ||||
496 | \&Foswiki::Sandbox::validateWebName ); | ||||
497 | push( @tmpWebs, $web ); | ||||
498 | if ( Foswiki::isTrue($recurse) ) { | ||||
499 | require Foswiki::Meta; | ||||
500 | my $webObject = Foswiki::Meta->new( $session, $session->{webName} ); | ||||
501 | my $it = | ||||
502 | $webObject->eachWeb( $Foswiki::cfg{EnableHierarchicalWebs} ); | ||||
503 | while ( $it->hasNext() ) { | ||||
504 | my $w = $session->{webName} . '/' . $it->next(); | ||||
505 | next | ||||
506 | unless $Foswiki::WebFilter::user_allowed->ok( $session, $w ); | ||||
507 | $w = Foswiki::Sandbox::untaint( $w, | ||||
508 | \&Foswiki::Sandbox::validateWebName ); | ||||
509 | push( @tmpWebs, $w ); | ||||
510 | } | ||||
511 | } | ||||
512 | } | ||||
513 | |||||
514 | 1 | 1µs | my @webs; | ||
515 | 1 | 3µs | foreach my $web (@tmpWebs) { | ||
516 | 1 | 1µs | next unless defined $web; | ||
517 | 1 | 2µs | push( @webs, $web ) unless $excludeWeb{$web}; | ||
518 | 1 | 6µs | $excludeWeb{$web} = 1; # eliminate duplicates | ||
519 | } | ||||
520 | |||||
521 | # Default to alphanumeric sort order | ||||
522 | 1 | 23µs | 1 | 5µs | return sort @webs; # spent 5µs making 1 call to Foswiki::Store::Interfaces::QueryAlgorithm::CORE:sort |
523 | } | ||||
524 | |||||
525 | 1 | 5µs | 1; | ||
526 | __END__ | ||||
sub Foswiki::Store::Interfaces::QueryAlgorithm::CORE:match; # opcode | |||||
# spent 5µs within Foswiki::Store::Interfaces::QueryAlgorithm::CORE:sort which was called:
# once (5µs+0s) by Foswiki::Store::Interfaces::QueryAlgorithm::getListOfWebs at line 522 | |||||
sub Foswiki::Store::Interfaces::QueryAlgorithm::CORE:subst; # opcode |