Merge lp:~zorba-coders/zorba/skip-items into lp:zorba
- skip-items
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Nicolae Brinza |
Approved revision: | 11550 |
Merged at revision: | 11568 |
Proposed branch: | lp:~zorba-coders/zorba/skip-items |
Merge into: | lp:zorba |
Diff against target: |
720 lines (+233/-238) 13 files modified
src/functions/func_sequences_impl.cpp (+3/-155) src/runtime/api/plan_wrapper.cpp (+11/-0) src/runtime/api/plan_wrapper.h (+2/-0) src/runtime/base/plan_iterator.cpp (+22/-1) src/runtime/base/plan_iterator.h (+13/-0) src/runtime/collections/collections_impl.cpp (+53/-11) src/runtime/collections/pregenerated/collections.h (+2/-0) src/runtime/eval/eval.cpp (+94/-56) src/runtime/eval/eval.h (+6/-0) src/runtime/sequences/sequences_impl.cpp (+6/-15) src/runtime/spec/collections/collections.xml (+10/-0) test/rbkt/ExpQueryResults/zorba/eval/eval16.xml.res (+2/-0) test/rbkt/Queries/zorba/eval/eval16.xq (+9/-0) |
To merge this branch: | bzr merge lp:~zorba-coders/zorba/skip-items |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Matthias Brantner | Approve | ||
Nicolae Brinza | Approve | ||
Review via email: mp+174723@code.launchpad.net |
Commit message
Implemented the Skip-items facility
Description of the change
Implemented the Skip-items facility
Zorba Build Bot (zorba-buildbot) wrote : | # |
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue result for https:/
Stage "TestZorbaUbuntu" failed.
3 tests failed (8344 total tests run).
Check test results at http://
Nicolae Brinza (nbrinza) : | # |
Matthias Brantner (matthias-brantner) wrote : | # |
- Shouldn't skip take an unsigned integer?
- Why is the while loop in collections_
- state->
- could we implement and test skip for the EvalIterator as well?
- What about the index probe iterators (e.g. ProbeIndexPoint
Nicolae Brinza (nbrinza) wrote : | # |
> - Shouldn't skip take an unsigned integer?
The parameters to fn:subsequence and co are all signed. E.g. you can pass a negative skip.
> - Why is the while loop in collections_
> initCollection is called before? I think there might be a bug in
> initCollection. Specifically, the else block in line 298 is never called
> because the CollectionIterator is not rewritten anymore (i.e.
> theChildren.size() will always return one)
You're very right. It was not really a bug, but the skip optimization didn't really happen because it was the while() that was doing the skipping instead of the getIterator(skip). I've fixed that. But the else block at line 298 cannot be deleted as the 3-parameter function was not only used by the rewriter, e.g. the collections/
> - state->
Fixed.
> - could we implement and test skip for the EvalIterator as well?
All iterators have the default implementation of skip in plan_iterator.cpp. How can we improve that implementation for EvalIterator?
> - What about the index probe iterators (e.g. ProbeIndexPoint
> they also skip
I was not aware they do. I'll write an optimization for them as well.
--
- 11551. By Nicolae Brinza
-
Fixed review issues.
- 11552. By Nicolae Brinza
-
Merged with Zorba trunk
Nicolae Brinza (nbrinza) wrote : | # |
I've looked into the index probe iterators but they already optimize any skipping. They take a Skip parameter and then they push it into an underlying iterator e.g. ProbeValueTreeI
I've pushed the pending fixes and the branch is ready for merging.
Matthias Brantner (matthias-brantner) wrote : | # |
Looks good to me. Only two issues.
- The thing with the probe iterators is that there are additional functions called probe-*-skip that allow
you to skip explicitly. However, subsequence is not rewritten into these functions. We will need to override the skip function in all the probe iterators (similar to count) such that subsequence(
- In ZorbaCollection
- 11553. By Nicolae Brinza
-
Fixed the double addition of skipCount in ZorbaCollection
Iterator: :initCollection ; added skip() to the EvalIterator.
Nicolae Brinza (nbrinza) wrote : | # |
> - In ZorbaCollection
> add skipCount twice. Something smells spooky here.
Yes, it seems it was added twice. I've fixed it.
I've also added the skip() function to the EvalIterator.
--
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue starting for the following merge proposals:
https:/
Progress dashboard at http://
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue result for https:/
Stage "TestZorbaUbuntu" failed.
1 tests failed (8415 total tests run).
Check test results at http://
- 11554. By Nicolae Brinza
-
Fixed a regression
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue starting for the following merge proposals:
https:/
Progress dashboard at http://
Zorba Build Bot (zorba-buildbot) wrote : | # |
Voting criteria failed for the following merge proposals:
https:/
Votes: {'Needs Information': 1, 'Approve': 1}
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue result for https:/
Stage "CommitZorba" failed.
Check console output at http://
Matthias Brantner (matthias-brantner) wrote : | # |
The following query crashes:
xquery version "3.0";
import module namespace ddl = "http://
import module namespace dml = "http://
import module namespace e = "http://
ddl:create(
subsequence(
- 11555. By Nicolae Brinza
-
Fixed a bug with eval() and the new skip() functionality.
- 11556. By Nicolae Brinza
-
Cleanup
Nicolae Brinza (nbrinza) wrote : | # |
I've fixed the crash and added the query as zorba/eval/
--
Matthias Brantner (matthias-brantner) : | # |
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue starting for the following merge proposals:
https:/
Progress dashboard at http://
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue result for https:/
Stage "AddTestSuitesU
Check console output at http://
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue starting for the following merge proposals:
https:/
Progress dashboard at http://
Zorba Build Bot (zorba-buildbot) wrote : | # |
Validation queue succeeded - proposal merged!
Preview Diff
1 | === modified file 'src/functions/func_sequences_impl.cpp' |
2 | --- src/functions/func_sequences_impl.cpp 2013-05-14 05:21:11 +0000 |
3 | +++ src/functions/func_sequences_impl.cpp 2013-07-26 12:54:41 +0000 |
4 | @@ -43,127 +43,6 @@ |
5 | |
6 | |
7 | /******************************************************************************* |
8 | - |
9 | -********************************************************************************/ |
10 | -bool rewriteSubsequenceCollection( |
11 | - static_context* aSctx, |
12 | - const QueryLoc& aLoc, |
13 | - std::vector<PlanIter_t>& aArgs, |
14 | - bool aIsIntSubsequence) |
15 | -{ |
16 | - ZorbaCollectionIterator* collIter = |
17 | - dynamic_cast<ZorbaCollectionIterator*>(aArgs[0].getp()); |
18 | - assert(collIter); |
19 | - |
20 | - std::vector<PlanIter_t>& lCollectionArgs = collIter->getChildren(); |
21 | - |
22 | - SingletonIterator* lPosIter = dynamic_cast<SingletonIterator*>(aArgs[1].getp()); |
23 | - if (lPosIter == NULL) |
24 | - { |
25 | - return false; |
26 | - } |
27 | - |
28 | - xs_long pos; |
29 | - const store::Item_t& lPosItem = lPosIter->getValue(); |
30 | - |
31 | - try |
32 | - { |
33 | - if (aIsIntSubsequence) |
34 | - { |
35 | - pos = lPosItem->getLongValue(); |
36 | - } |
37 | - else |
38 | - { |
39 | - xs_double dpos = lPosItem->getDoubleValue().round(); |
40 | - xs_integer ipos(dpos.getNumber()); |
41 | - pos = to_xs_long(ipos); |
42 | - } |
43 | - } |
44 | - catch (std::exception const&) |
45 | - { |
46 | - return false; |
47 | - } |
48 | - |
49 | - if (pos <= 1) |
50 | - { |
51 | - // if the start position is less than 1 we can't push this down into |
52 | - // the collection skip parameter because the result won't be equivalent. |
53 | - return false; |
54 | - } |
55 | - |
56 | - // prepare helper |
57 | - store::Item_t lItemOne; |
58 | - GENV_ITEMFACTORY->createInteger(lItemOne, Integer(1)); |
59 | - |
60 | - int lNumCollArgs = lCollectionArgs.size(); |
61 | - if (lNumCollArgs == 1) |
62 | - { |
63 | - // argument is of type collection(qname) |
64 | - // simply move the (pos-1) of subsequence into the skip of |
65 | - // collection function |
66 | - // subsequence(collection(qname), 10, 20) |
67 | - // -> subsequence(collection(qname, 10-1), 1, 20) |
68 | - PlanIter_t& lNewCollSkipIter = aArgs[1]; |
69 | - PlanIter_t lOneIter = new SingletonIterator(aSctx, aLoc, lItemOne); |
70 | - |
71 | - lCollectionArgs.push_back( |
72 | - new NumArithIterator<zorba::SubtractOperation>(aSctx, |
73 | - collIter->getLocation(), |
74 | - lNewCollSkipIter, |
75 | - lOneIter) |
76 | - ); |
77 | - } |
78 | - else if (lNumCollArgs <= 3 && lNumCollArgs != 0) |
79 | - { |
80 | - // argument is of type collection(qname,skip) or |
81 | - // collection(qname,start_uri,skip) |
82 | - int lSkipPosition = 1; |
83 | - if (lNumCollArgs == 3) |
84 | - { |
85 | - // collection function with start reference -> skip is the 3rd param |
86 | - lSkipPosition = 2; |
87 | - } |
88 | - |
89 | - // add position-1 of subsequence to collection skip |
90 | - // subsequence(collection(qname, 10), 10, 20) |
91 | - // -> subsequence(collection(qname, 10+10-1), 10, 20) |
92 | - PlanIter_t& lOldCollSkipIter = lCollectionArgs[lSkipPosition]; |
93 | - PlanIter_t lOneIter = new SingletonIterator (aSctx, aLoc, lItemOne); |
94 | - PlanIter_t& lSubseqPosIter = aArgs[1]; |
95 | - |
96 | - PlanIter_t lCollSkipAdditionIter = |
97 | - new NumArithIterator<zorba::SubtractOperation>(aSctx, |
98 | - collIter->getLocation(), |
99 | - lSubseqPosIter, |
100 | - lOneIter); |
101 | - lCollectionArgs[lSkipPosition] = |
102 | - new NumArithIterator<zorba::AddOperation>(aSctx, |
103 | - collIter->getLocation(), |
104 | - lOldCollSkipIter, |
105 | - lCollSkipAdditionIter); |
106 | - } |
107 | - else |
108 | - { |
109 | - // no collection function with 0 or >3 params |
110 | - assert(false); |
111 | - } |
112 | - |
113 | - aArgs[0] = new ZorbaCollectionIterator(aSctx, |
114 | - collIter->getLocation(), |
115 | - lCollectionArgs, |
116 | - collIter->isDynamic()); |
117 | - |
118 | - // after pushing the position param down we need to rewrite the actual |
119 | - // position to 1: |
120 | - // subsequence(collection(qname, 10+10-1), 10, 20) |
121 | - // -> subsequence(collection(qname, 10+10-1), 1, 20) |
122 | - aArgs[1] = new SingletonIterator(aSctx, aLoc, lItemOne); |
123 | - |
124 | - return true; |
125 | -} |
126 | - |
127 | - |
128 | -/******************************************************************************* |
129 | ********************************************************************************/ |
130 | xqtref_t fn_unordered::getReturnType(const fo_expr* caller) const |
131 | { |
132 | @@ -573,8 +452,7 @@ |
133 | const QueryLoc& aLoc, |
134 | std::vector<PlanIter_t>& aArgs, |
135 | expr& aAnn) const |
136 | -{ |
137 | - const std::type_info& lFirstArgType = typeid(*aArgs[0]); |
138 | +{ |
139 | fo_expr& subseqExpr = static_cast<fo_expr&>(aAnn); |
140 | const expr* inputExpr = subseqExpr.get_arg(0); |
141 | const expr* posExpr = subseqExpr.get_arg(1); |
142 | @@ -619,23 +497,8 @@ |
143 | return aArgs[0]; |
144 | } |
145 | } |
146 | - else if (typeid(ZorbaCollectionIterator) == lFirstArgType) |
147 | - { |
148 | - // push down position param into collection skip if possible |
149 | - if (rewriteSubsequenceCollection(aSctx, aLoc, aArgs, false /*no int*/)) |
150 | - { |
151 | - // we have rewritten the subsequence to start at the beginning. |
152 | - // if there is no length param we can remove the entire |
153 | - // subsequence function |
154 | - // subsequence(collection(qname, 10), 1) -> collection(qname, 10) |
155 | - if (aArgs.size() == 2) |
156 | - { |
157 | - return aArgs[0]; |
158 | - } |
159 | - } |
160 | - } |
161 | |
162 | - done: |
163 | +done: |
164 | return new FnSubsequenceIterator(aSctx, aLoc, aArgs); |
165 | } |
166 | |
167 | @@ -736,23 +599,8 @@ |
168 | return aArgs[0]; |
169 | } |
170 | } |
171 | - else if (typeid(ZorbaCollectionIterator) == lFirstArgType) |
172 | - { |
173 | - // push down position param into collection skip if possible |
174 | - if (rewriteSubsequenceCollection(aSctx, aLoc, aArgs, true /*flag int*/)) |
175 | - { |
176 | - // we have rewritten the subsequence to start from the beginning. |
177 | - // if there is no length param we can remove the entire |
178 | - // subsequence function |
179 | - // subsequence(collection(qname, 10), 1) -> collection(qname, 10) |
180 | - if (aArgs.size() == 2) |
181 | - { |
182 | - return aArgs[0]; |
183 | - } |
184 | - } |
185 | - } |
186 | |
187 | - done: |
188 | +done: |
189 | return new SubsequenceIntIterator(aSctx, aLoc, aArgs); |
190 | } |
191 | |
192 | |
193 | === modified file 'src/runtime/api/plan_wrapper.cpp' |
194 | --- src/runtime/api/plan_wrapper.cpp 2013-03-17 13:55:28 +0000 |
195 | +++ src/runtime/api/plan_wrapper.cpp 2013-07-26 12:54:41 +0000 |
196 | @@ -162,6 +162,17 @@ |
197 | /******************************************************************************* |
198 | |
199 | ********************************************************************************/ |
200 | +bool PlanWrapper::skip(int64_t count) |
201 | +{ |
202 | + ZORBA_ASSERT(theIsOpen); |
203 | + |
204 | + return theIterator->skip(count, *thePlanState); |
205 | +} |
206 | + |
207 | + |
208 | +/******************************************************************************* |
209 | + |
210 | +********************************************************************************/ |
211 | void PlanWrapper::reset() |
212 | { |
213 | ZORBA_ASSERT(theIsOpen); |
214 | |
215 | === modified file 'src/runtime/api/plan_wrapper.h' |
216 | --- src/runtime/api/plan_wrapper.h 2013-03-04 21:00:58 +0000 |
217 | +++ src/runtime/api/plan_wrapper.h 2013-07-26 12:54:41 +0000 |
218 | @@ -97,6 +97,8 @@ |
219 | |
220 | bool next(store::Item_t& item); |
221 | |
222 | + bool skip(int64_t count); |
223 | + |
224 | void reset(); |
225 | |
226 | void close(); |
227 | |
228 | === modified file 'src/runtime/base/plan_iterator.cpp' |
229 | --- src/runtime/base/plan_iterator.cpp 2013-05-28 18:20:54 +0000 |
230 | +++ src/runtime/base/plan_iterator.cpp 2013-07-26 12:54:41 +0000 |
231 | @@ -31,6 +31,10 @@ |
232 | |
233 | #include "diagnostics/util_macros.h" |
234 | |
235 | +#ifndef NDEBUG |
236 | +#include "system/properties.h" |
237 | +#endif |
238 | + |
239 | namespace zorba |
240 | { |
241 | |
242 | @@ -180,6 +184,18 @@ |
243 | } |
244 | |
245 | |
246 | +bool PlanIterator::skip(int64_t count, PlanState& planState) const |
247 | +{ |
248 | + bool have_more_items = true; |
249 | + store::Item_t item; |
250 | + |
251 | + while (count-- > 0 && (have_more_items = consumeNext(item, this, planState))) |
252 | + ; |
253 | + |
254 | + return have_more_items; |
255 | +} |
256 | + |
257 | + |
258 | #ifndef NDEBUG |
259 | bool PlanIterator::consumeNext( |
260 | store::Item_t& result, |
261 | @@ -196,7 +212,12 @@ |
262 | |
263 | if (planState.theCompilerCB->theConfig.print_item_flow) |
264 | { |
265 | - std::cout << "next (" << iter << " = " << typeid (*iter).name() |
266 | + if (Properties::instance()->stableIteratorIds()) |
267 | + std::cout << "next (" << iter->getId(); |
268 | + else |
269 | + std::cout << "next (" << iter; |
270 | + |
271 | + std::cout << " = " << typeid (*iter).name() |
272 | << ") -> " |
273 | << "status: " << status << " -> " |
274 | << ((status && result != NULL) ? result->show().c_str() : "null") |
275 | |
276 | === modified file 'src/runtime/base/plan_iterator.h' |
277 | --- src/runtime/base/plan_iterator.h 2013-05-28 18:20:54 +0000 |
278 | +++ src/runtime/base/plan_iterator.h 2013-07-26 12:54:41 +0000 |
279 | @@ -401,6 +401,19 @@ |
280 | virtual bool count(store::Item_t& result, PlanState& planState) const; |
281 | |
282 | /** |
283 | + * Skip a number of items from the Plan's sequence. Classes can overwrite |
284 | + * this functions to optimize the skipping by jumping directly to the |
285 | + * desired position in the sequence. |
286 | + * |
287 | + * Returns true if the entire sequence has been consumed, false otherwise. |
288 | + * |
289 | + * @param count the number of items to be skipped |
290 | + * @param planState the state plan |
291 | + * |
292 | + */ |
293 | + virtual bool skip(int64_t count, PlanState &planState) const; |
294 | + |
295 | + /** |
296 | * Produce the next item and return it to the caller. Implicitly, the first |
297 | * call of 'producNext' initializes the iterator and allocates resources |
298 | * (main memory, file descriptors, etc.). |
299 | |
300 | === modified file 'src/runtime/collections/collections_impl.cpp' |
301 | --- src/runtime/collections/collections_impl.cpp 2013-05-02 18:34:27 +0000 |
302 | +++ src/runtime/collections/collections_impl.cpp 2013-07-26 12:54:41 +0000 |
303 | @@ -277,17 +277,13 @@ |
304 | } |
305 | |
306 | |
307 | -bool ZorbaCollectionIterator::nextImpl( |
308 | - store::Item_t& result, |
309 | - PlanState& planState) const |
310 | +void ZorbaCollectionIterator::initCollection(PlanState& planState, int64_t skipCount) const |
311 | { |
312 | store::Item_t name; |
313 | + xs_integer lSkip; |
314 | store::Collection_t collection; |
315 | - xs_integer lSkip; |
316 | - zstring lStart; |
317 | |
318 | - ZorbaCollectionIteratorState* state; |
319 | - DEFAULT_STACK_INIT(ZorbaCollectionIteratorState, state, planState); |
320 | + ZorbaCollectionIteratorState* state = StateTraitsImpl<ZorbaCollectionIteratorState>::getState(planState, theStateOffset); |
321 | |
322 | consumeNext(name, theChildren[0].getp(), planState); |
323 | |
324 | @@ -295,16 +291,20 @@ |
325 | |
326 | if (theChildren.size() == 1) |
327 | { |
328 | - state->theIterator = collection->getIterator(); |
329 | + if (skipCount < 0) |
330 | + skipCount = 0; |
331 | + lSkip = skipCount; |
332 | + state->theIterator = collection->getIterator(lSkip); |
333 | } |
334 | else |
335 | { |
336 | + zstring lStart; |
337 | bool lRefPassed = theChildren.size() >= 3; |
338 | - |
339 | + |
340 | // read positional skip parameter |
341 | store::Item_t lSkipItem; |
342 | consumeNext(lSkipItem, theChildren[(lRefPassed ? 2 : 1)].getp(), planState); |
343 | - lSkip = lSkipItem->getIntegerValue(); |
344 | + lSkip = lSkipItem->getIntegerValue() + skipCount; |
345 | |
346 | // negative skip is not allowed |
347 | if (lSkip.sign() < 0) |
348 | @@ -320,7 +320,7 @@ |
349 | { |
350 | store::Item_t lRefItem; |
351 | consumeNext(lRefItem, theChildren[1].getp(), planState); |
352 | - lStart = lRefItem->getString(); |
353 | + lStart = lRefItem->getString(); |
354 | try |
355 | { |
356 | state->theIterator = collection->getIterator(lSkip, lStart); |
357 | @@ -346,6 +346,29 @@ |
358 | } |
359 | |
360 | state->theIteratorOpened = true; |
361 | +} |
362 | + |
363 | + |
364 | +bool ZorbaCollectionIterator::nextImpl( |
365 | + store::Item_t& result, |
366 | + PlanState& planState) const |
367 | +{ |
368 | + store::Item_t name; |
369 | + xs_integer lSkip; |
370 | + store::Collection_t collection; |
371 | + |
372 | + ZorbaCollectionIteratorState* state; |
373 | + DEFAULT_STACK_INIT(ZorbaCollectionIteratorState, state, planState); |
374 | + |
375 | + if (state->theIterator.getp() != NULL && state->theIteratorOpened == false) |
376 | + { |
377 | + ZORBA_ASSERT (false && "nextImpl() called past iterator end"); |
378 | + return false; |
379 | + } |
380 | + else if ( ! state->theIteratorOpened) |
381 | + { |
382 | + initCollection(planState, 0); |
383 | + } |
384 | |
385 | while (state->theIterator->next(result)) |
386 | STACK_PUSH(true, state); |
387 | @@ -358,6 +381,25 @@ |
388 | } |
389 | |
390 | |
391 | +bool ZorbaCollectionIterator::skip(int64_t count, PlanState& planState) const |
392 | +{ |
393 | + ZorbaCollectionIteratorState* state = StateTraitsImpl<ZorbaCollectionIteratorState>::getState(planState, theStateOffset); |
394 | + |
395 | + if (state->theIterator.getp() != NULL && state->theIteratorOpened == false) |
396 | + { |
397 | + ZORBA_ASSERT (false && "nextImpl() called past iterator end"); |
398 | + return false; |
399 | + } |
400 | + else if ( ! state->theIteratorOpened) |
401 | + { |
402 | + initCollection(planState, count); |
403 | + return true; |
404 | + } |
405 | + else |
406 | + return false; |
407 | +} |
408 | + |
409 | + |
410 | bool ZorbaCollectionIterator::count(store::Item_t& result, PlanState& planState) const |
411 | { |
412 | if (!isCountOptimizable()) |
413 | |
414 | === modified file 'src/runtime/collections/pregenerated/collections.h' |
415 | --- src/runtime/collections/pregenerated/collections.h 2013-03-24 20:40:03 +0000 |
416 | +++ src/runtime/collections/pregenerated/collections.h 2013-07-26 12:54:41 +0000 |
417 | @@ -291,6 +291,8 @@ |
418 | public: |
419 | bool isCountOptimizable() const; |
420 | bool count(store::Item_t& result, PlanState& planState) const; |
421 | + bool skip(int64_t count, PlanState& planState) const; |
422 | + void initCollection(PlanState& planState, int64_t skipCount) const; |
423 | void accept(PlanIterVisitor& v) const; |
424 | |
425 | bool nextImpl(store::Item_t& result, PlanState& aPlanState) const; |
426 | |
427 | === modified file 'src/runtime/eval/eval.cpp' |
428 | --- src/runtime/eval/eval.cpp 2013-03-24 20:40:03 +0000 |
429 | +++ src/runtime/eval/eval.cpp 2013-07-26 12:54:41 +0000 |
430 | @@ -71,6 +71,17 @@ |
431 | /****************************************************************************//** |
432 | |
433 | ********************************************************************************/ |
434 | +void EvalIteratorState::reset(PlanState& planState) |
435 | +{ |
436 | + PlanIteratorState::reset(planState); |
437 | + |
438 | + thePlanWrapper = NULL; |
439 | +} |
440 | + |
441 | + |
442 | +/****************************************************************************//** |
443 | + |
444 | +********************************************************************************/ |
445 | EvalIterator::EvalIterator( |
446 | static_context* sctx, |
447 | const QueryLoc& loc, |
448 | @@ -126,6 +137,73 @@ |
449 | /****************************************************************************//** |
450 | |
451 | ********************************************************************************/ |
452 | +void EvalIterator::init( |
453 | + bool doCount, |
454 | + PlanState& planState) const |
455 | +{ |
456 | + store::Item_t item; |
457 | + EvalIteratorState* state = StateTraitsImpl<EvalIteratorState>::getState(planState, theStateOffset); |
458 | + |
459 | + CONSUME(item, 0); |
460 | + |
461 | + // Create the "import" sctx. The importOuterEnv() method (called below) will |
462 | + // register into the importSctx (a) the outer vars of the eval query and (b) |
463 | + // the expression-level ns bindings of the outer query at the place where |
464 | + // the eval call appears at. |
465 | + static_context* importSctx = theSctx->create_child_context(); |
466 | + |
467 | + // Create the root sctx for the eval query |
468 | + static_context* evalSctx = importSctx->create_child_context(); |
469 | + |
470 | + // Create the ccb for the eval query |
471 | + CompilerCB* evalCCB = new CompilerCB(*planState.theCompilerCB); |
472 | + evalCCB->theIsEval = true; |
473 | + evalCCB->theRootSctx = evalSctx; |
474 | + evalCCB->theConfig.for_serialization_only = !theDoNodeCopy; |
475 | + (evalCCB->theSctxMap)[1] = evalSctx; |
476 | + |
477 | + state->ccb.reset(evalCCB); |
478 | + |
479 | + // Create the dynamic context for the eval query |
480 | + dynamic_context* evalDctx = new dynamic_context(planState.theGlobalDynCtx); |
481 | + state->dctx.reset(evalDctx); |
482 | + |
483 | + // Import the outer environment. |
484 | + ulong maxOuterVarId; |
485 | + importOuterEnv(planState, evalCCB, importSctx, evalDctx, maxOuterVarId); |
486 | + |
487 | + // If we are here after a reset, we must set state->thePlanWrapper to NULL |
488 | + // before reseting the state->thePlan. Otherwise, the current state->thePlan |
489 | + // will be destroyed first, and then we will attempt to close it when |
490 | + // state->thePlanWrapper is reset later. |
491 | + state->thePlanWrapper = NULL; |
492 | + |
493 | + // Compile |
494 | + state->thePlan = compile(evalCCB, item->getStringValue(), maxOuterVarId, doCount); |
495 | + |
496 | + planState.theCompilerCB->theNextVisitId = evalCCB->theNextVisitId + 1; |
497 | + |
498 | + // Set the values for the (explicit) external vars of the eval query |
499 | + setExternalVariables(evalCCB, importSctx, evalSctx, evalDctx); |
500 | + |
501 | + // Execute |
502 | + state->thePlanWrapper = new PlanWrapper(state->thePlan, |
503 | + evalCCB, |
504 | + evalDctx, |
505 | + planState.theQuery, |
506 | + planState.theStackDepth + 1, |
507 | + state->ccb->theHaveTimeout, |
508 | + state->ccb->theTimeout); |
509 | + |
510 | + state->thePlanWrapper->checkDepth(loc); |
511 | + |
512 | + state->thePlanWrapper->open(); |
513 | +} |
514 | + |
515 | + |
516 | +/****************************************************************************//** |
517 | + |
518 | +********************************************************************************/ |
519 | bool EvalIterator::nextORcount( |
520 | bool doCount, |
521 | store::Item_t& result, |
522 | @@ -136,62 +214,8 @@ |
523 | |
524 | DEFAULT_STACK_INIT(EvalIteratorState, state, planState); |
525 | |
526 | - CONSUME(item, 0); |
527 | - |
528 | - { |
529 | - // Create the "import" sctx. The importOuterEnv() method (called below) will |
530 | - // register into the importSctx (a) the outer vars of the eval query and (b) |
531 | - // the expression-level ns bindings of the outer query at the place where |
532 | - // the eval call appears at. |
533 | - static_context* importSctx = theSctx->create_child_context(); |
534 | - |
535 | - // Create the root sctx for the eval query |
536 | - static_context* evalSctx = importSctx->create_child_context(); |
537 | - |
538 | - // Create the ccb for the eval query |
539 | - CompilerCB* evalCCB = new CompilerCB(*planState.theCompilerCB); |
540 | - evalCCB->theIsEval = true; |
541 | - evalCCB->theRootSctx = evalSctx; |
542 | - evalCCB->theConfig.for_serialization_only = !theDoNodeCopy; |
543 | - (evalCCB->theSctxMap)[1] = evalSctx; |
544 | - |
545 | - state->ccb.reset(evalCCB); |
546 | - |
547 | - // Create the dynamic context for the eval query |
548 | - dynamic_context* evalDctx = new dynamic_context(planState.theGlobalDynCtx); |
549 | - state->dctx.reset(evalDctx); |
550 | - |
551 | - // Import the outer environment. |
552 | - ulong maxOuterVarId; |
553 | - importOuterEnv(planState, evalCCB, importSctx, evalDctx, maxOuterVarId); |
554 | - |
555 | - // If we are here after a reset, we must set state->thePlanWrapper to NULL |
556 | - // before reseting the state->thePlan. Otherwise, the current state->thePlan |
557 | - // will be destroyed first, and then we will attempt to close it when |
558 | - // state->thePlanWrapper is reset later. |
559 | - state->thePlanWrapper = NULL; |
560 | - |
561 | - // Compile |
562 | - state->thePlan = compile(evalCCB, item->getStringValue(), maxOuterVarId, doCount); |
563 | - |
564 | - planState.theCompilerCB->theNextVisitId = evalCCB->theNextVisitId + 1; |
565 | - |
566 | - // Set the values for the (explicit) external vars of the eval query |
567 | - setExternalVariables(evalCCB, importSctx, evalSctx, evalDctx); |
568 | - |
569 | - // Execute |
570 | - state->thePlanWrapper = new PlanWrapper(state->thePlan, |
571 | - evalCCB, |
572 | - evalDctx, |
573 | - planState.theQuery, |
574 | - planState.theStackDepth + 1, |
575 | - state->ccb->theHaveTimeout, |
576 | - state->ccb->theTimeout); |
577 | - |
578 | - state->thePlanWrapper->checkDepth(loc); |
579 | - |
580 | - state->thePlanWrapper->open(); |
581 | - } |
582 | + if (state->thePlanWrapper.getp() == NULL) |
583 | + init(doCount, planState); |
584 | |
585 | while (state->thePlanWrapper->next(result)) |
586 | { |
587 | @@ -205,6 +229,20 @@ |
588 | |
589 | |
590 | /****************************************************************************//** |
591 | + |
592 | +********************************************************************************/ |
593 | +bool EvalIterator::skip(int64_t count, PlanState &planState) const |
594 | +{ |
595 | + EvalIteratorState* state = StateTraitsImpl<EvalIteratorState>::getState(planState, theStateOffset); |
596 | + |
597 | + if (state->thePlanWrapper.getp() == NULL) |
598 | + init(false, planState); |
599 | + |
600 | + return state->thePlanWrapper->skip(count); |
601 | +} |
602 | + |
603 | + |
604 | +/****************************************************************************//** |
605 | This method imports a static and dynamic environment from the quter query into |
606 | the eval query. In particular: |
607 | |
608 | |
609 | === modified file 'src/runtime/eval/eval.h' |
610 | --- src/runtime/eval/eval.h 2013-03-24 20:40:03 +0000 |
611 | +++ src/runtime/eval/eval.h 2013-07-26 12:54:41 +0000 |
612 | @@ -38,6 +38,8 @@ |
613 | EvalIteratorState(); |
614 | |
615 | ~EvalIteratorState(); |
616 | + |
617 | + void reset(PlanState& planState); |
618 | }; |
619 | |
620 | |
621 | @@ -130,7 +132,11 @@ |
622 | return nextORcount(true, result, planState); |
623 | } |
624 | |
625 | + bool skip(int64_t count, PlanState &planState) const; |
626 | + |
627 | private: |
628 | + void init(bool doCount, PlanState& planState) const; |
629 | + |
630 | void importOuterEnv( |
631 | PlanState& planState, |
632 | CompilerCB* evalCCB, |
633 | |
634 | === modified file 'src/runtime/sequences/sequences_impl.cpp' |
635 | --- src/runtime/sequences/sequences_impl.cpp 2013-06-18 18:55:33 +0000 |
636 | +++ src/runtime/sequences/sequences_impl.cpp 2013-07-26 12:54:41 +0000 |
637 | @@ -533,11 +533,8 @@ |
638 | goto done; |
639 | |
640 | // Consume and skip all input items that are before the startPos |
641 | - for (; startPos > 1; --startPos) |
642 | - { |
643 | - if (!CONSUME(result, 0)) |
644 | - goto done; |
645 | - } |
646 | + if (!theChildren[0]->skip(startPos-1, planState)) |
647 | + goto done; |
648 | |
649 | if (theChildren.size() < 3 || lengthDouble.isPosInf()) |
650 | { |
651 | @@ -619,11 +616,8 @@ |
652 | goto done; |
653 | |
654 | // Consume and skip all input items that are before the startPos |
655 | - for (; startPos > 0; --startPos) |
656 | - { |
657 | - if (!CONSUME(result, 0)) |
658 | - goto done; |
659 | - } |
660 | + if (!theChildren[0]->skip(startPos, planState)) |
661 | + goto done; |
662 | |
663 | if (theChildren.size() < 3) |
664 | { |
665 | @@ -694,11 +688,8 @@ |
666 | --startPos; |
667 | |
668 | // Consume and skip all input items that are before the startPos |
669 | - for (; startPos > 0; --startPos) |
670 | - { |
671 | - if (!CONSUME(result, 0)) |
672 | - goto done; |
673 | - } |
674 | + if (!theChildren[0]->skip(startPos, planState)) |
675 | + goto done; |
676 | |
677 | if (CONSUME(result, 0)) |
678 | { |
679 | |
680 | === modified file 'src/runtime/spec/collections/collections.xml' |
681 | --- src/runtime/spec/collections/collections.xml 2013-04-02 22:54:20 +0000 |
682 | +++ src/runtime/spec/collections/collections.xml 2013-07-26 12:54:41 +0000 |
683 | @@ -313,6 +313,16 @@ |
684 | <zorba:param name="result" type="store::Item_t&"/> |
685 | <zorba:param name="planState" type="PlanState&"/> |
686 | </zorba:method> |
687 | + |
688 | + <zorba:method name="skip" const="true" return="bool"> |
689 | + <zorba:param name="count" type="int64_t"/> |
690 | + <zorba:param name="planState" type="PlanState&"/> |
691 | + </zorba:method> |
692 | + |
693 | + <zorba:method name="initCollection" const="true" return="void"> |
694 | + <zorba:param name="planState" type="PlanState&"/> |
695 | + <zorba:param name="skipCount" type="int64_t"/> |
696 | + </zorba:method> |
697 | |
698 | <zorba:state generateInit="false" generateReset="false" generateDestructor="false"> |
699 | <zorba:member type="store::Iterator_t" name="theIterator"/> |
700 | |
701 | === added file 'test/rbkt/ExpQueryResults/zorba/eval/eval16.xml.res' |
702 | --- test/rbkt/ExpQueryResults/zorba/eval/eval16.xml.res 1970-01-01 00:00:00 +0000 |
703 | +++ test/rbkt/ExpQueryResults/zorba/eval/eval16.xml.res 2013-07-26 12:54:41 +0000 |
704 | @@ -0,0 +1,2 @@ |
705 | +<?xml version="1.0" encoding="UTF-8"?> |
706 | +<oldlast/> |
707 | |
708 | === added file 'test/rbkt/Queries/zorba/eval/eval16.xq' |
709 | --- test/rbkt/Queries/zorba/eval/eval16.xq 1970-01-01 00:00:00 +0000 |
710 | +++ test/rbkt/Queries/zorba/eval/eval16.xq 2013-07-26 12:54:41 +0000 |
711 | @@ -0,0 +1,9 @@ |
712 | +xquery version "3.0"; |
713 | + |
714 | +import module namespace ddl = "http://www.zorba-xquery.com/modules/store/dynamic/collections/ddl"; |
715 | +import module namespace dml = "http://www.zorba-xquery.com/modules/store/dynamic/collections/dml"; |
716 | +import module namespace e = "http://www.zorba-xquery.com/modules/reflection"; |
717 | + |
718 | +ddl:create(xs:QName("ddl:test2"),(<center1/>,<oldlast/>)); |
719 | + |
720 | +subsequence(e:eval("dml:collection(xs:QName('ddl:test2'))"), 2, 1) |
Validation queue starting for the following merge proposals: /code.launchpad .net/~zorba- coders/ zorba/skip- items/+ merge/174723
https:/
Progress dashboard at http:// jenkins. lambda. nu/view/ ValidationQueue