Merge lp:~zorba-coders/zorba/skip-items into lp:zorba

Proposed by Nicolae Brinza
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
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

To post a comment you must log in.
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

Validation queue starting for the following merge proposals:
https://code.launchpad.net/~zorba-coders/zorba/skip-items/+merge/174723

Progress dashboard at http://jenkins.lambda.nu/view/ValidationQueue

Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

Validation queue result for https://code.launchpad.net/~zorba-coders/zorba/skip-items/+merge/174723

Stage "TestZorbaUbuntu" failed.
3 tests failed (8344 total tests run).

Check test results at http://jenkins.lambda.nu/job/TestZorbaUbuntu/81/testReport/ to view the results.

Revision history for this message
Nicolae Brinza (nbrinza) :
review: Approve
Revision history for this message
Matthias Brantner (matthias-brantner) wrote :

- Shouldn't skip take an unsigned integer?
- Why is the while loop in collections_impl.cpp:397 necessary if 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)
- state->theIteratorOpened == false => !state->theIteratorOpened
- could we implement and test skip for the EvalIterator as well?
- What about the index probe iterators (e.g. ProbeIndexPointValueIterator), they also skip

review: Needs Fixing
Revision history for this message
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_impl.cpp:397 necessary if
> 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/paging_1 to _5 use it.

> - state->theIteratorOpened == false => !state->theIteratorOpened

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. ProbeIndexPointValueIterator),
> they also skip

I was not aware they do. I'll write an optimization for them as well.

--

lp:~zorba-coders/zorba/skip-items updated
11551. By Nicolae Brinza

Fixed review issues.

11552. By Nicolae Brinza

Merged with Zorba trunk

Revision history for this message
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. ProbeValueTreeIndexIterator which handles the skip internally. So there is nothing to be done there.

I've pushed the pending fixes and the branch is ready for merging.

Revision history for this message
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(probe-*) will be executed efficiently. We can do this is a second step though. I'll create a follow up story for this.

- In ZorbaCollectionIterator::initCollection lines 307 and 326, you eventually add skipCount twice. Something smells spooky here.

review: Needs Information
lp:~zorba-coders/zorba/skip-items updated
11553. By Nicolae Brinza

Fixed the double addition of skipCount in ZorbaCollectionIterator::initCollection; added skip() to the EvalIterator.

Revision history for this message
Nicolae Brinza (nbrinza) wrote :

> - In ZorbaCollectionIterator::initCollection lines 307 and 326, you eventually
> 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.

--

Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

Validation queue starting for the following merge proposals:
https://code.launchpad.net/~zorba-coders/zorba/skip-items/+merge/174723

Progress dashboard at http://jenkins.lambda.nu/view/ValidationQueue

Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

Validation queue result for https://code.launchpad.net/~zorba-coders/zorba/skip-items/+merge/174723

Stage "TestZorbaUbuntu" failed.
1 tests failed (8415 total tests run).

Check test results at http://jenkins.lambda.nu/job/TestZorbaUbuntu/123/testReport/ to view the results.

lp:~zorba-coders/zorba/skip-items updated
11554. By Nicolae Brinza

Fixed a regression

Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

Validation queue starting for the following merge proposals:
https://code.launchpad.net/~zorba-coders/zorba/skip-items/+merge/174723

Progress dashboard at http://jenkins.lambda.nu/view/ValidationQueue

Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

Voting criteria failed for the following merge proposals:

https://code.launchpad.net/~zorba-coders/zorba/skip-items/+merge/174723 :
Votes: {'Needs Information': 1, 'Approve': 1}

Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

Validation queue result for https://code.launchpad.net/~zorba-coders/zorba/skip-items/+merge/174723

Stage "CommitZorba" failed.

Check console output at http://jenkins.lambda.nu/job/CommitZorba/56/console to view the results.

Revision history for this message
Matthias Brantner (matthias-brantner) wrote :

The following query crashes:

xquery version "3.0";

import module namespace ddl = "http://www.zorba-xquery.com/modules/store/dynamic/collections/ddl";
import module namespace dml = "http://www.zorba-xquery.com/modules/store/dynamic/collections/dml";
import module namespace e = "http://www.zorba-xquery.com/modules/reflection";

ddl:create(xs:QName("ddl:test2"),(<center1/>,<oldlast/>));

subsequence(e:eval("dml:collection(xs:QName('ddl:test2'))"), 2, 1)

review: Needs Fixing
lp:~zorba-coders/zorba/skip-items updated
11555. By Nicolae Brinza

Fixed a bug with eval() and the new skip() functionality.

11556. By Nicolae Brinza

Cleanup

Revision history for this message
Nicolae Brinza (nbrinza) wrote :

I've fixed the crash and added the query as zorba/eval/eval16.xq.

--

Revision history for this message
Matthias Brantner (matthias-brantner) :
review: Approve
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

Validation queue starting for the following merge proposals:
https://code.launchpad.net/~zorba-coders/zorba/skip-items/+merge/174723

Progress dashboard at http://jenkins.lambda.nu/view/ValidationQueue

Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

Validation queue result for https://code.launchpad.net/~zorba-coders/zorba/skip-items/+merge/174723

Stage "AddTestSuitesUbuntu" failed.

Check console output at http://jenkins.lambda.nu/job/AddTestSuitesUbuntu/125/console to view the results.

Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

Validation queue starting for the following merge proposals:
https://code.launchpad.net/~zorba-coders/zorba/skip-items/+merge/174723

Progress dashboard at http://jenkins.lambda.nu/view/ValidationQueue

Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

Validation queue succeeded - proposal merged!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/functions/func_sequences_impl.cpp'
--- src/functions/func_sequences_impl.cpp 2013-05-14 05:21:11 +0000
+++ src/functions/func_sequences_impl.cpp 2013-07-26 12:54:41 +0000
@@ -43,127 +43,6 @@
4343
4444
45/*******************************************************************************45/*******************************************************************************
46
47********************************************************************************/
48bool rewriteSubsequenceCollection(
49 static_context* aSctx,
50 const QueryLoc& aLoc,
51 std::vector<PlanIter_t>& aArgs,
52 bool aIsIntSubsequence)
53{
54 ZorbaCollectionIterator* collIter =
55 dynamic_cast<ZorbaCollectionIterator*>(aArgs[0].getp());
56 assert(collIter);
57
58 std::vector<PlanIter_t>& lCollectionArgs = collIter->getChildren();
59
60 SingletonIterator* lPosIter = dynamic_cast<SingletonIterator*>(aArgs[1].getp());
61 if (lPosIter == NULL)
62 {
63 return false;
64 }
65
66 xs_long pos;
67 const store::Item_t& lPosItem = lPosIter->getValue();
68
69 try
70 {
71 if (aIsIntSubsequence)
72 {
73 pos = lPosItem->getLongValue();
74 }
75 else
76 {
77 xs_double dpos = lPosItem->getDoubleValue().round();
78 xs_integer ipos(dpos.getNumber());
79 pos = to_xs_long(ipos);
80 }
81 }
82 catch (std::exception const&)
83 {
84 return false;
85 }
86
87 if (pos <= 1)
88 {
89 // if the start position is less than 1 we can't push this down into
90 // the collection skip parameter because the result won't be equivalent.
91 return false;
92 }
93
94 // prepare helper
95 store::Item_t lItemOne;
96 GENV_ITEMFACTORY->createInteger(lItemOne, Integer(1));
97
98 int lNumCollArgs = lCollectionArgs.size();
99 if (lNumCollArgs == 1)
100 {
101 // argument is of type collection(qname)
102 // simply move the (pos-1) of subsequence into the skip of
103 // collection function
104 // subsequence(collection(qname), 10, 20)
105 // -> subsequence(collection(qname, 10-1), 1, 20)
106 PlanIter_t& lNewCollSkipIter = aArgs[1];
107 PlanIter_t lOneIter = new SingletonIterator(aSctx, aLoc, lItemOne);
108
109 lCollectionArgs.push_back(
110 new NumArithIterator<zorba::SubtractOperation>(aSctx,
111 collIter->getLocation(),
112 lNewCollSkipIter,
113 lOneIter)
114 );
115 }
116 else if (lNumCollArgs <= 3 && lNumCollArgs != 0)
117 {
118 // argument is of type collection(qname,skip) or
119 // collection(qname,start_uri,skip)
120 int lSkipPosition = 1;
121 if (lNumCollArgs == 3)
122 {
123 // collection function with start reference -> skip is the 3rd param
124 lSkipPosition = 2;
125 }
126
127 // add position-1 of subsequence to collection skip
128 // subsequence(collection(qname, 10), 10, 20)
129 // -> subsequence(collection(qname, 10+10-1), 10, 20)
130 PlanIter_t& lOldCollSkipIter = lCollectionArgs[lSkipPosition];
131 PlanIter_t lOneIter = new SingletonIterator (aSctx, aLoc, lItemOne);
132 PlanIter_t& lSubseqPosIter = aArgs[1];
133
134 PlanIter_t lCollSkipAdditionIter =
135 new NumArithIterator<zorba::SubtractOperation>(aSctx,
136 collIter->getLocation(),
137 lSubseqPosIter,
138 lOneIter);
139 lCollectionArgs[lSkipPosition] =
140 new NumArithIterator<zorba::AddOperation>(aSctx,
141 collIter->getLocation(),
142 lOldCollSkipIter,
143 lCollSkipAdditionIter);
144 }
145 else
146 {
147 // no collection function with 0 or >3 params
148 assert(false);
149 }
150
151 aArgs[0] = new ZorbaCollectionIterator(aSctx,
152 collIter->getLocation(),
153 lCollectionArgs,
154 collIter->isDynamic());
155
156 // after pushing the position param down we need to rewrite the actual
157 // position to 1:
158 // subsequence(collection(qname, 10+10-1), 10, 20)
159 // -> subsequence(collection(qname, 10+10-1), 1, 20)
160 aArgs[1] = new SingletonIterator(aSctx, aLoc, lItemOne);
161
162 return true;
163}
164
165
166/*******************************************************************************
167********************************************************************************/46********************************************************************************/
168xqtref_t fn_unordered::getReturnType(const fo_expr* caller) const47xqtref_t fn_unordered::getReturnType(const fo_expr* caller) const
169{48{
@@ -573,8 +452,7 @@
573 const QueryLoc& aLoc,452 const QueryLoc& aLoc,
574 std::vector<PlanIter_t>& aArgs,453 std::vector<PlanIter_t>& aArgs,
575 expr& aAnn) const454 expr& aAnn) const
576{455{
577 const std::type_info& lFirstArgType = typeid(*aArgs[0]);
578 fo_expr& subseqExpr = static_cast<fo_expr&>(aAnn);456 fo_expr& subseqExpr = static_cast<fo_expr&>(aAnn);
579 const expr* inputExpr = subseqExpr.get_arg(0);457 const expr* inputExpr = subseqExpr.get_arg(0);
580 const expr* posExpr = subseqExpr.get_arg(1);458 const expr* posExpr = subseqExpr.get_arg(1);
@@ -619,23 +497,8 @@
619 return aArgs[0];497 return aArgs[0];
620 }498 }
621 }499 }
622 else if (typeid(ZorbaCollectionIterator) == lFirstArgType)
623 {
624 // push down position param into collection skip if possible
625 if (rewriteSubsequenceCollection(aSctx, aLoc, aArgs, false /*no int*/))
626 {
627 // we have rewritten the subsequence to start at the beginning.
628 // if there is no length param we can remove the entire
629 // subsequence function
630 // subsequence(collection(qname, 10), 1) -> collection(qname, 10)
631 if (aArgs.size() == 2)
632 {
633 return aArgs[0];
634 }
635 }
636 }
637500
638 done:501done:
639 return new FnSubsequenceIterator(aSctx, aLoc, aArgs);502 return new FnSubsequenceIterator(aSctx, aLoc, aArgs);
640}503}
641504
@@ -736,23 +599,8 @@
736 return aArgs[0];599 return aArgs[0];
737 }600 }
738 }601 }
739 else if (typeid(ZorbaCollectionIterator) == lFirstArgType)
740 {
741 // push down position param into collection skip if possible
742 if (rewriteSubsequenceCollection(aSctx, aLoc, aArgs, true /*flag int*/))
743 {
744 // we have rewritten the subsequence to start from the beginning.
745 // if there is no length param we can remove the entire
746 // subsequence function
747 // subsequence(collection(qname, 10), 1) -> collection(qname, 10)
748 if (aArgs.size() == 2)
749 {
750 return aArgs[0];
751 }
752 }
753 }
754602
755 done:603done:
756 return new SubsequenceIntIterator(aSctx, aLoc, aArgs);604 return new SubsequenceIntIterator(aSctx, aLoc, aArgs);
757}605}
758606
759607
=== modified file 'src/runtime/api/plan_wrapper.cpp'
--- src/runtime/api/plan_wrapper.cpp 2013-03-17 13:55:28 +0000
+++ src/runtime/api/plan_wrapper.cpp 2013-07-26 12:54:41 +0000
@@ -162,6 +162,17 @@
162/*******************************************************************************162/*******************************************************************************
163163
164********************************************************************************/164********************************************************************************/
165bool PlanWrapper::skip(int64_t count)
166{
167 ZORBA_ASSERT(theIsOpen);
168
169 return theIterator->skip(count, *thePlanState);
170}
171
172
173/*******************************************************************************
174
175********************************************************************************/
165void PlanWrapper::reset()176void PlanWrapper::reset()
166{177{
167 ZORBA_ASSERT(theIsOpen);178 ZORBA_ASSERT(theIsOpen);
168179
=== modified file 'src/runtime/api/plan_wrapper.h'
--- src/runtime/api/plan_wrapper.h 2013-03-04 21:00:58 +0000
+++ src/runtime/api/plan_wrapper.h 2013-07-26 12:54:41 +0000
@@ -97,6 +97,8 @@
9797
98 bool next(store::Item_t& item);98 bool next(store::Item_t& item);
9999
100 bool skip(int64_t count);
101
100 void reset();102 void reset();
101103
102 void close();104 void close();
103105
=== modified file 'src/runtime/base/plan_iterator.cpp'
--- src/runtime/base/plan_iterator.cpp 2013-05-28 18:20:54 +0000
+++ src/runtime/base/plan_iterator.cpp 2013-07-26 12:54:41 +0000
@@ -31,6 +31,10 @@
3131
32#include "diagnostics/util_macros.h"32#include "diagnostics/util_macros.h"
3333
34#ifndef NDEBUG
35#include "system/properties.h"
36#endif
37
34namespace zorba38namespace zorba
35{39{
3640
@@ -180,6 +184,18 @@
180}184}
181185
182186
187bool PlanIterator::skip(int64_t count, PlanState& planState) const
188{
189 bool have_more_items = true;
190 store::Item_t item;
191
192 while (count-- > 0 && (have_more_items = consumeNext(item, this, planState)))
193 ;
194
195 return have_more_items;
196}
197
198
183#ifndef NDEBUG199#ifndef NDEBUG
184bool PlanIterator::consumeNext(200bool PlanIterator::consumeNext(
185 store::Item_t& result,201 store::Item_t& result,
@@ -196,7 +212,12 @@
196212
197 if (planState.theCompilerCB->theConfig.print_item_flow)213 if (planState.theCompilerCB->theConfig.print_item_flow)
198 {214 {
199 std::cout << "next (" << iter << " = " << typeid (*iter).name()215 if (Properties::instance()->stableIteratorIds())
216 std::cout << "next (" << iter->getId();
217 else
218 std::cout << "next (" << iter;
219
220 std::cout << " = " << typeid (*iter).name()
200 << ") -> "221 << ") -> "
201 << "status: " << status << " -> "222 << "status: " << status << " -> "
202 << ((status && result != NULL) ? result->show().c_str() : "null")223 << ((status && result != NULL) ? result->show().c_str() : "null")
203224
=== modified file 'src/runtime/base/plan_iterator.h'
--- src/runtime/base/plan_iterator.h 2013-05-28 18:20:54 +0000
+++ src/runtime/base/plan_iterator.h 2013-07-26 12:54:41 +0000
@@ -401,6 +401,19 @@
401 virtual bool count(store::Item_t& result, PlanState& planState) const;401 virtual bool count(store::Item_t& result, PlanState& planState) const;
402402
403 /**403 /**
404 * Skip a number of items from the Plan's sequence. Classes can overwrite
405 * this functions to optimize the skipping by jumping directly to the
406 * desired position in the sequence.
407 *
408 * Returns true if the entire sequence has been consumed, false otherwise.
409 *
410 * @param count the number of items to be skipped
411 * @param planState the state plan
412 *
413 */
414 virtual bool skip(int64_t count, PlanState &planState) const;
415
416 /**
404 * Produce the next item and return it to the caller. Implicitly, the first417 * Produce the next item and return it to the caller. Implicitly, the first
405 * call of 'producNext' initializes the iterator and allocates resources418 * call of 'producNext' initializes the iterator and allocates resources
406 * (main memory, file descriptors, etc.).419 * (main memory, file descriptors, etc.).
407420
=== modified file 'src/runtime/collections/collections_impl.cpp'
--- src/runtime/collections/collections_impl.cpp 2013-05-02 18:34:27 +0000
+++ src/runtime/collections/collections_impl.cpp 2013-07-26 12:54:41 +0000
@@ -277,17 +277,13 @@
277}277}
278278
279279
280bool ZorbaCollectionIterator::nextImpl(280void ZorbaCollectionIterator::initCollection(PlanState& planState, int64_t skipCount) const
281 store::Item_t& result,
282 PlanState& planState) const
283{281{
284 store::Item_t name;282 store::Item_t name;
283 xs_integer lSkip;
285 store::Collection_t collection;284 store::Collection_t collection;
286 xs_integer lSkip;
287 zstring lStart;
288285
289 ZorbaCollectionIteratorState* state;286 ZorbaCollectionIteratorState* state = StateTraitsImpl<ZorbaCollectionIteratorState>::getState(planState, theStateOffset);
290 DEFAULT_STACK_INIT(ZorbaCollectionIteratorState, state, planState);
291287
292 consumeNext(name, theChildren[0].getp(), planState);288 consumeNext(name, theChildren[0].getp(), planState);
293289
@@ -295,16 +291,20 @@
295291
296 if (theChildren.size() == 1)292 if (theChildren.size() == 1)
297 {293 {
298 state->theIterator = collection->getIterator();294 if (skipCount < 0)
295 skipCount = 0;
296 lSkip = skipCount;
297 state->theIterator = collection->getIterator(lSkip);
299 }298 }
300 else299 else
301 {300 {
301 zstring lStart;
302 bool lRefPassed = theChildren.size() >= 3;302 bool lRefPassed = theChildren.size() >= 3;
303 303
304 // read positional skip parameter304 // read positional skip parameter
305 store::Item_t lSkipItem;305 store::Item_t lSkipItem;
306 consumeNext(lSkipItem, theChildren[(lRefPassed ? 2 : 1)].getp(), planState);306 consumeNext(lSkipItem, theChildren[(lRefPassed ? 2 : 1)].getp(), planState);
307 lSkip = lSkipItem->getIntegerValue(); 307 lSkip = lSkipItem->getIntegerValue() + skipCount;
308308
309 // negative skip is not allowed309 // negative skip is not allowed
310 if (lSkip.sign() < 0)310 if (lSkip.sign() < 0)
@@ -320,7 +320,7 @@
320 {320 {
321 store::Item_t lRefItem;321 store::Item_t lRefItem;
322 consumeNext(lRefItem, theChildren[1].getp(), planState);322 consumeNext(lRefItem, theChildren[1].getp(), planState);
323 lStart = lRefItem->getString(); 323 lStart = lRefItem->getString();
324 try324 try
325 {325 {
326 state->theIterator = collection->getIterator(lSkip, lStart);326 state->theIterator = collection->getIterator(lSkip, lStart);
@@ -346,6 +346,29 @@
346 }346 }
347347
348 state->theIteratorOpened = true;348 state->theIteratorOpened = true;
349}
350
351
352bool ZorbaCollectionIterator::nextImpl(
353 store::Item_t& result,
354 PlanState& planState) const
355{
356 store::Item_t name;
357 xs_integer lSkip;
358 store::Collection_t collection;
359
360 ZorbaCollectionIteratorState* state;
361 DEFAULT_STACK_INIT(ZorbaCollectionIteratorState, state, planState);
362
363 if (state->theIterator.getp() != NULL && state->theIteratorOpened == false)
364 {
365 ZORBA_ASSERT (false && "nextImpl() called past iterator end");
366 return false;
367 }
368 else if ( ! state->theIteratorOpened)
369 {
370 initCollection(planState, 0);
371 }
349372
350 while (state->theIterator->next(result))373 while (state->theIterator->next(result))
351 STACK_PUSH(true, state);374 STACK_PUSH(true, state);
@@ -358,6 +381,25 @@
358}381}
359382
360383
384bool ZorbaCollectionIterator::skip(int64_t count, PlanState& planState) const
385{
386 ZorbaCollectionIteratorState* state = StateTraitsImpl<ZorbaCollectionIteratorState>::getState(planState, theStateOffset);
387
388 if (state->theIterator.getp() != NULL && state->theIteratorOpened == false)
389 {
390 ZORBA_ASSERT (false && "nextImpl() called past iterator end");
391 return false;
392 }
393 else if ( ! state->theIteratorOpened)
394 {
395 initCollection(planState, count);
396 return true;
397 }
398 else
399 return false;
400}
401
402
361bool ZorbaCollectionIterator::count(store::Item_t& result, PlanState& planState) const403bool ZorbaCollectionIterator::count(store::Item_t& result, PlanState& planState) const
362{404{
363 if (!isCountOptimizable())405 if (!isCountOptimizable())
364406
=== modified file 'src/runtime/collections/pregenerated/collections.h'
--- src/runtime/collections/pregenerated/collections.h 2013-03-24 20:40:03 +0000
+++ src/runtime/collections/pregenerated/collections.h 2013-07-26 12:54:41 +0000
@@ -291,6 +291,8 @@
291public:291public:
292 bool isCountOptimizable() const;292 bool isCountOptimizable() const;
293 bool count(store::Item_t& result, PlanState& planState) const;293 bool count(store::Item_t& result, PlanState& planState) const;
294 bool skip(int64_t count, PlanState& planState) const;
295 void initCollection(PlanState& planState, int64_t skipCount) const;
294 void accept(PlanIterVisitor& v) const;296 void accept(PlanIterVisitor& v) const;
295297
296 bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;298 bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;
297299
=== modified file 'src/runtime/eval/eval.cpp'
--- src/runtime/eval/eval.cpp 2013-03-24 20:40:03 +0000
+++ src/runtime/eval/eval.cpp 2013-07-26 12:54:41 +0000
@@ -71,6 +71,17 @@
71/****************************************************************************//**71/****************************************************************************//**
7272
73********************************************************************************/73********************************************************************************/
74void EvalIteratorState::reset(PlanState& planState)
75{
76 PlanIteratorState::reset(planState);
77
78 thePlanWrapper = NULL;
79}
80
81
82/****************************************************************************//**
83
84********************************************************************************/
74EvalIterator::EvalIterator(85EvalIterator::EvalIterator(
75 static_context* sctx,86 static_context* sctx,
76 const QueryLoc& loc,87 const QueryLoc& loc,
@@ -126,6 +137,73 @@
126/****************************************************************************//**137/****************************************************************************//**
127138
128********************************************************************************/139********************************************************************************/
140void EvalIterator::init(
141 bool doCount,
142 PlanState& planState) const
143{
144 store::Item_t item;
145 EvalIteratorState* state = StateTraitsImpl<EvalIteratorState>::getState(planState, theStateOffset);
146
147 CONSUME(item, 0);
148
149 // Create the "import" sctx. The importOuterEnv() method (called below) will
150 // register into the importSctx (a) the outer vars of the eval query and (b)
151 // the expression-level ns bindings of the outer query at the place where
152 // the eval call appears at.
153 static_context* importSctx = theSctx->create_child_context();
154
155 // Create the root sctx for the eval query
156 static_context* evalSctx = importSctx->create_child_context();
157
158 // Create the ccb for the eval query
159 CompilerCB* evalCCB = new CompilerCB(*planState.theCompilerCB);
160 evalCCB->theIsEval = true;
161 evalCCB->theRootSctx = evalSctx;
162 evalCCB->theConfig.for_serialization_only = !theDoNodeCopy;
163 (evalCCB->theSctxMap)[1] = evalSctx;
164
165 state->ccb.reset(evalCCB);
166
167 // Create the dynamic context for the eval query
168 dynamic_context* evalDctx = new dynamic_context(planState.theGlobalDynCtx);
169 state->dctx.reset(evalDctx);
170
171 // Import the outer environment.
172 ulong maxOuterVarId;
173 importOuterEnv(planState, evalCCB, importSctx, evalDctx, maxOuterVarId);
174
175 // If we are here after a reset, we must set state->thePlanWrapper to NULL
176 // before reseting the state->thePlan. Otherwise, the current state->thePlan
177 // will be destroyed first, and then we will attempt to close it when
178 // state->thePlanWrapper is reset later.
179 state->thePlanWrapper = NULL;
180
181 // Compile
182 state->thePlan = compile(evalCCB, item->getStringValue(), maxOuterVarId, doCount);
183
184 planState.theCompilerCB->theNextVisitId = evalCCB->theNextVisitId + 1;
185
186 // Set the values for the (explicit) external vars of the eval query
187 setExternalVariables(evalCCB, importSctx, evalSctx, evalDctx);
188
189 // Execute
190 state->thePlanWrapper = new PlanWrapper(state->thePlan,
191 evalCCB,
192 evalDctx,
193 planState.theQuery,
194 planState.theStackDepth + 1,
195 state->ccb->theHaveTimeout,
196 state->ccb->theTimeout);
197
198 state->thePlanWrapper->checkDepth(loc);
199
200 state->thePlanWrapper->open();
201}
202
203
204/****************************************************************************//**
205
206********************************************************************************/
129bool EvalIterator::nextORcount(207bool EvalIterator::nextORcount(
130 bool doCount,208 bool doCount,
131 store::Item_t& result,209 store::Item_t& result,
@@ -136,62 +214,8 @@
136214
137 DEFAULT_STACK_INIT(EvalIteratorState, state, planState);215 DEFAULT_STACK_INIT(EvalIteratorState, state, planState);
138216
139 CONSUME(item, 0);217 if (state->thePlanWrapper.getp() == NULL)
140218 init(doCount, planState);
141 {
142 // Create the "import" sctx. The importOuterEnv() method (called below) will
143 // register into the importSctx (a) the outer vars of the eval query and (b)
144 // the expression-level ns bindings of the outer query at the place where
145 // the eval call appears at.
146 static_context* importSctx = theSctx->create_child_context();
147
148 // Create the root sctx for the eval query
149 static_context* evalSctx = importSctx->create_child_context();
150
151 // Create the ccb for the eval query
152 CompilerCB* evalCCB = new CompilerCB(*planState.theCompilerCB);
153 evalCCB->theIsEval = true;
154 evalCCB->theRootSctx = evalSctx;
155 evalCCB->theConfig.for_serialization_only = !theDoNodeCopy;
156 (evalCCB->theSctxMap)[1] = evalSctx;
157
158 state->ccb.reset(evalCCB);
159
160 // Create the dynamic context for the eval query
161 dynamic_context* evalDctx = new dynamic_context(planState.theGlobalDynCtx);
162 state->dctx.reset(evalDctx);
163
164 // Import the outer environment.
165 ulong maxOuterVarId;
166 importOuterEnv(planState, evalCCB, importSctx, evalDctx, maxOuterVarId);
167
168 // If we are here after a reset, we must set state->thePlanWrapper to NULL
169 // before reseting the state->thePlan. Otherwise, the current state->thePlan
170 // will be destroyed first, and then we will attempt to close it when
171 // state->thePlanWrapper is reset later.
172 state->thePlanWrapper = NULL;
173
174 // Compile
175 state->thePlan = compile(evalCCB, item->getStringValue(), maxOuterVarId, doCount);
176
177 planState.theCompilerCB->theNextVisitId = evalCCB->theNextVisitId + 1;
178
179 // Set the values for the (explicit) external vars of the eval query
180 setExternalVariables(evalCCB, importSctx, evalSctx, evalDctx);
181
182 // Execute
183 state->thePlanWrapper = new PlanWrapper(state->thePlan,
184 evalCCB,
185 evalDctx,
186 planState.theQuery,
187 planState.theStackDepth + 1,
188 state->ccb->theHaveTimeout,
189 state->ccb->theTimeout);
190
191 state->thePlanWrapper->checkDepth(loc);
192
193 state->thePlanWrapper->open();
194 }
195219
196 while (state->thePlanWrapper->next(result))220 while (state->thePlanWrapper->next(result))
197 {221 {
@@ -205,6 +229,20 @@
205229
206230
207/****************************************************************************//**231/****************************************************************************//**
232
233********************************************************************************/
234bool EvalIterator::skip(int64_t count, PlanState &planState) const
235{
236 EvalIteratorState* state = StateTraitsImpl<EvalIteratorState>::getState(planState, theStateOffset);
237
238 if (state->thePlanWrapper.getp() == NULL)
239 init(false, planState);
240
241 return state->thePlanWrapper->skip(count);
242}
243
244
245/****************************************************************************//**
208 This method imports a static and dynamic environment from the quter query into246 This method imports a static and dynamic environment from the quter query into
209 the eval query. In particular:247 the eval query. In particular:
210248
211249
=== modified file 'src/runtime/eval/eval.h'
--- src/runtime/eval/eval.h 2013-03-24 20:40:03 +0000
+++ src/runtime/eval/eval.h 2013-07-26 12:54:41 +0000
@@ -38,6 +38,8 @@
38 EvalIteratorState();38 EvalIteratorState();
3939
40 ~EvalIteratorState();40 ~EvalIteratorState();
41
42 void reset(PlanState& planState);
41};43};
4244
4345
@@ -130,7 +132,11 @@
130 return nextORcount(true, result, planState);132 return nextORcount(true, result, planState);
131 }133 }
132134
135 bool skip(int64_t count, PlanState &planState) const;
136
133private:137private:
138 void init(bool doCount, PlanState& planState) const;
139
134 void importOuterEnv(140 void importOuterEnv(
135 PlanState& planState,141 PlanState& planState,
136 CompilerCB* evalCCB,142 CompilerCB* evalCCB,
137143
=== modified file 'src/runtime/sequences/sequences_impl.cpp'
--- src/runtime/sequences/sequences_impl.cpp 2013-06-18 18:55:33 +0000
+++ src/runtime/sequences/sequences_impl.cpp 2013-07-26 12:54:41 +0000
@@ -533,11 +533,8 @@
533 goto done;533 goto done;
534534
535 // Consume and skip all input items that are before the startPos535 // Consume and skip all input items that are before the startPos
536 for (; startPos > 1; --startPos)536 if (!theChildren[0]->skip(startPos-1, planState))
537 {537 goto done;
538 if (!CONSUME(result, 0))
539 goto done;
540 }
541538
542 if (theChildren.size() < 3 || lengthDouble.isPosInf())539 if (theChildren.size() < 3 || lengthDouble.isPosInf())
543 {540 {
@@ -619,11 +616,8 @@
619 goto done;616 goto done;
620617
621 // Consume and skip all input items that are before the startPos618 // Consume and skip all input items that are before the startPos
622 for (; startPos > 0; --startPos)619 if (!theChildren[0]->skip(startPos, planState))
623 {620 goto done;
624 if (!CONSUME(result, 0))
625 goto done;
626 }
627621
628 if (theChildren.size() < 3)622 if (theChildren.size() < 3)
629 {623 {
@@ -694,11 +688,8 @@
694 --startPos;688 --startPos;
695689
696 // Consume and skip all input items that are before the startPos690 // Consume and skip all input items that are before the startPos
697 for (; startPos > 0; --startPos)691 if (!theChildren[0]->skip(startPos, planState))
698 {692 goto done;
699 if (!CONSUME(result, 0))
700 goto done;
701 }
702693
703 if (CONSUME(result, 0))694 if (CONSUME(result, 0))
704 {695 {
705696
=== modified file 'src/runtime/spec/collections/collections.xml'
--- src/runtime/spec/collections/collections.xml 2013-04-02 22:54:20 +0000
+++ src/runtime/spec/collections/collections.xml 2013-07-26 12:54:41 +0000
@@ -313,6 +313,16 @@
313 <zorba:param name="result" type="store::Item_t&amp;"/>313 <zorba:param name="result" type="store::Item_t&amp;"/>
314 <zorba:param name="planState" type="PlanState&amp;"/>314 <zorba:param name="planState" type="PlanState&amp;"/>
315 </zorba:method>315 </zorba:method>
316
317 <zorba:method name="skip" const="true" return="bool">
318 <zorba:param name="count" type="int64_t"/>
319 <zorba:param name="planState" type="PlanState&amp;"/>
320 </zorba:method>
321
322 <zorba:method name="initCollection" const="true" return="void">
323 <zorba:param name="planState" type="PlanState&amp;"/>
324 <zorba:param name="skipCount" type="int64_t"/>
325 </zorba:method>
316326
317 <zorba:state generateInit="false" generateReset="false" generateDestructor="false">327 <zorba:state generateInit="false" generateReset="false" generateDestructor="false">
318 <zorba:member type="store::Iterator_t" name="theIterator"/>328 <zorba:member type="store::Iterator_t" name="theIterator"/>
319329
=== added file 'test/rbkt/ExpQueryResults/zorba/eval/eval16.xml.res'
--- test/rbkt/ExpQueryResults/zorba/eval/eval16.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/eval/eval16.xml.res 2013-07-26 12:54:41 +0000
@@ -0,0 +1,2 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<oldlast/>
03
=== added file 'test/rbkt/Queries/zorba/eval/eval16.xq'
--- test/rbkt/Queries/zorba/eval/eval16.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/eval/eval16.xq 2013-07-26 12:54:41 +0000
@@ -0,0 +1,9 @@
1xquery version "3.0";
2
3import module namespace ddl = "http://www.zorba-xquery.com/modules/store/dynamic/collections/ddl";
4import module namespace dml = "http://www.zorba-xquery.com/modules/store/dynamic/collections/dml";
5import module namespace e = "http://www.zorba-xquery.com/modules/reflection";
6
7ddl:create(xs:QName("ddl:test2"),(<center1/>,<oldlast/>));
8
9subsequence(e:eval("dml:collection(xs:QName('ddl:test2'))"), 2, 1)

Subscribers

People subscribed via source and target branches