Merge lp:~zorba-coders/zorba/markos-scratch into lp:zorba

Proposed by Markos Zaharioudakis
Status: Merged
Approved by: Markos Zaharioudakis
Approved revision: 11149
Merged at revision: 11516
Proposed branch: lp:~zorba-coders/zorba/markos-scratch
Merge into: lp:zorba
Diff against target: 725 lines (+334/-143)
10 files modified
ChangeLog (+2/-0)
src/functions/udf.cpp (+7/-26)
src/runtime/core/fncall_iterator.cpp (+172/-102)
src/runtime/core/fncall_iterator.h (+17/-10)
src/runtime/util/item_iterator.cpp (+1/-1)
src/runtime/util/item_iterator.h (+6/-4)
src/runtime/util/single_item_iterator.h (+80/-0)
test/rbkt/ExpQueryResults/zorba/udf/cache01.xml.res (+6/-0)
test/rbkt/ExpQueryResults/zorba/udf/cache_01.xml.res (+6/-0)
test/rbkt/Queries/zorba/udf/cache_01.xq (+37/-0)
To merge this branch: bzr merge lp:~zorba-coders/zorba/markos-scratch
Reviewer Review Type Date Requested Status
Markos Zaharioudakis Approve
Review via email: mp+169606@code.launchpad.net

Commit message

Optimized implementation of function caching and removed the restriction on the return type.

Description of the change

Optimized implementation of function caching and removed the restriction on the return type.

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

The attempt to merge lp:~zorba-coders/zorba/markos-scratch into lp:zorba failed. Below is the output from the failed tests.

CMake Error at /home/ceej/zo/testing/zorbatest/tester/TarmacLander.cmake:281 (message):
  Validation queue job markos-scratch-2013-06-15T23-03-13.979Z is finished.
  The final status was:

  No tests were run - build or configure step must have failed.

  Not commiting changes.

Error in read script: /home/ceej/zo/testing/zorbatest/tester/TarmacLander.cmake

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

The attempt to merge lp:~zorba-coders/zorba/markos-scratch into lp:zorba failed. Below is the output from the failed tests.

CMake Error at /home/ceej/zo/testing/zorbatest/tester/TarmacLander.cmake:281 (message):
  Validation queue job markos-scratch-2013-06-15T23-34-46.252Z is finished.
  The final status was:

  No tests were run - build or configure step must have failed.

  Not commiting changes.

Error in read script: /home/ceej/zo/testing/zorbatest/tester/TarmacLander.cmake

11149. By Markos Zaharioudakis

added missing file

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

Validation queue job markos-scratch-2013-06-16T06-55-56.112Z is finished. The final status was:

All tests succeeded!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ChangeLog'
2--- ChangeLog 2013-06-14 05:20:13 +0000
3+++ ChangeLog 2013-06-16 06:47:28 +0000
4@@ -16,6 +16,8 @@
5 if the FOR clause is followed by an orderby or groupby clause.
6 * Replaced use of create_value_type() in runtime with getTypeCode().
7 * Optimized switch expression
8+ * Optimized implementation of function caching and removed the restriction
9+ on the return type.
10
11 Bug Fixes/Other Changes:
12 * Fixed bug #1117952 (Improve XML error output format)
13
14=== modified file 'src/functions/udf.cpp'
15--- src/functions/udf.cpp 2013-05-08 20:14:47 +0000
16+++ src/functions/udf.cpp 2013-06-16 06:47:28 +0000
17@@ -651,14 +651,14 @@
18 }
19
20 // was the %ann:cache annotation given explicitly by the user
21- bool lExplicitCacheRequest =
22+ bool explicitCacheRequest =
23 (theAnnotationList ?
24 theAnnotationList->contains(AnnotationInternal::zann_cache) :
25 false);
26
27 if (isVariadic())
28 {
29- if (lExplicitCacheRequest)
30+ if (explicitCacheRequest)
31 {
32 diag->add_warning(
33 NEW_XQUERY_WARNING(zwarn::ZWST0005_CACHING_NOT_POSSIBLE,
34@@ -668,27 +668,9 @@
35 return;
36 }
37
38- // parameter and return types are subtype of xs:anyAtomicType?
39- const xqtref_t& lRes = theSignature.returnType();
40 TypeManager* tm = theBodyExpr->get_sctx()->get_typemanager();
41
42- if (!TypeOps::is_subtype(tm,
43- *lRes,
44- *GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_ONE,
45- theLoc))
46- {
47- if (lExplicitCacheRequest)
48- {
49- diag->add_warning(
50- NEW_XQUERY_WARNING(zwarn::ZWST0005_CACHING_NOT_POSSIBLE,
51- WARN_PARAMS(getName()->getStringValue(),
52- ZED(ZWST0005_RETURN_TYPE),
53- lRes->toString()),
54- WARN_LOC(theLoc)));
55- }
56- return;
57- }
58-
59+ // parameter and return types are subtype of xs:anyAtomicType
60 csize lArity = theSignature.paramCount();
61 for (csize i = 0; i < lArity; ++i)
62 {
63@@ -698,7 +680,7 @@
64 *GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_ONE,
65 theLoc))
66 {
67- if (lExplicitCacheRequest)
68+ if (explicitCacheRequest)
69 {
70 diag->add_warning(
71 NEW_XQUERY_WARNING(zwarn::ZWST0005_CACHING_NOT_POSSIBLE,
72@@ -715,7 +697,7 @@
73 // function updating?
74 if (isUpdating())
75 {
76- if (lExplicitCacheRequest)
77+ if (explicitCacheRequest)
78 {
79 diag->add_warning(
80 NEW_XQUERY_WARNING(zwarn::ZWST0005_CACHING_NOT_POSSIBLE,
81@@ -727,7 +709,7 @@
82
83 if (isSequential() || !isDeterministic())
84 {
85- if (lExplicitCacheRequest)
86+ if (explicitCacheRequest)
87 {
88 diag->add_warning(
89 NEW_XQUERY_WARNING(zwarn::ZWST0006_CACHING_MIGHT_NOT_BE_INTENDED,
90@@ -740,9 +722,8 @@
91 return;
92 }
93
94-
95 // optimization is prerequisite before invoking isRecursive
96- if (!lExplicitCacheRequest && isOptimized() && !isRecursive())
97+ if (!explicitCacheRequest && isOptimized() && !isRecursive())
98 {
99 return;
100 }
101
102=== modified file 'src/runtime/core/fncall_iterator.cpp'
103--- src/runtime/core/fncall_iterator.cpp 2013-04-24 01:35:58 +0000
104+++ src/runtime/core/fncall_iterator.cpp 2013-06-16 06:47:28 +0000
105@@ -55,6 +55,7 @@
106
107
108 #ifdef ZORBA_WITH_DEBUGGER
109+
110 #include "debugger/debugger_commons.h"
111
112 #define DEBUGGER_COMMONS state->thePlanState->theDebuggerCommons
113@@ -78,6 +79,12 @@
114 if (DEBUGGER_COMMONS) { \
115 DEBUGGER_COMMONS->popStackFrame(); \
116 }
117+
118+#else
119+
120+#define DEBUGGER_PUSH_FRAME
121+#define DEBUGGER_POP_FRAME
122+
123 #endif
124
125 namespace zorba {
126@@ -179,8 +186,6 @@
127 {
128 thePlan->reset(*thePlanState);
129 }
130-
131- theArgValues.clear();
132 }
133
134
135@@ -244,34 +249,45 @@
136 PlanState& planState,
137 UDFunctionCallIteratorState* state)
138 {
139- store::Index_t lIndex = theUDF->getCache();
140-
141- if (!lIndex && theUDF->cacheResults())
142+ if (theUDF->cacheResults())
143 {
144- const signature& sig = theUDF->getSignature();
145+ store::Index_t index = theUDF->getCache();
146
147 csize numArgs = theChildren.size();
148
149- store::IndexSpecification lSpec;
150- lSpec.theNumKeyColumns = numArgs;
151- lSpec.theKeyTypes.resize(numArgs);
152- lSpec.theCollations.resize(numArgs);
153- lSpec.theIsTemp = true;
154- lSpec.theIsUnique = true;
155+ if (!index)
156+ {
157+ const signature& sig = theUDF->getSignature();
158+
159+ store::IndexSpecification lSpec;
160+ lSpec.theNumKeyColumns = numArgs;
161+ lSpec.theKeyTypes.resize(numArgs);
162+ lSpec.theCollations.resize(numArgs);
163+ lSpec.theIsTemp = true;
164+ lSpec.theIsUnique = false;
165+
166+ for (csize i = 0; i < numArgs; ++i)
167+ {
168+ lSpec.theKeyTypes[i] = sig[i]->getBaseBuiltinType()->getQName().getp();
169+ }
170+
171+ index = GENV_STORE.createIndex(theUDF->getName(), lSpec, 0);
172+
173+ theUDF->setCache(index.getp()); // cache the cache in the function itself
174+
175+ state->theArgValues.reserve(numArgs);
176+ }
177+
178+ state->theCache = index.getp();
179+ state->theCacheCond = index->createCondition(store::IndexCondition::POINT_VALUE);
180+ state->theCacheProbeIte = GENV_ITERATOR_FACTORY->createIndexProbeIterator(index);
181+ state->theArgValues.resize(numArgs);
182
183 for (csize i = 0; i < numArgs; ++i)
184 {
185- lSpec.theKeyTypes[i] = sig[i]->getBaseBuiltinType()->getQName().getp();
186+ state->theArgValues[i] = new SingleItemIterator();
187 }
188-
189- lIndex = GENV_STORE.createIndex(theUDF->getName(), lSpec, 0);
190-
191- theUDF->setCache(lIndex.getp()); // cache the cache in the function itself
192-
193- state->theArgValues.reserve(numArgs);
194 }
195-
196- state->theCache = lIndex.getp();
197 }
198
199
200@@ -284,11 +300,9 @@
201 store::Item_t& result,
202 std::vector<store::Item_t>& argValues) const
203 {
204- if (!state->theCache)
205- return false;
206+ assert(state->theCache);
207
208- store::IndexCondition_t cond =
209- state->theCache->createCondition(store::IndexCondition::POINT_VALUE);
210+ state->theCacheCond->clear();
211
212 std::vector<store::Iterator_t>::iterator ite = state->theArgWrappers.begin();
213
214@@ -296,21 +310,21 @@
215 {
216 store::Iterator_t& argWrapper = (*ite);
217 store::Item_t argValue;
218+
219 if (argWrapper) // might be 0 if argument is not used
220 {
221 argWrapper->next(argValue); // guaranteed to have exactly one result
222 }
223+
224 argValues.push_back(argValue);
225- cond->pushItem(argValue);
226+
227+ state->theCacheCond->pushItem(argValue);
228 }
229
230- store::IndexProbeIterator_t probeIte =
231- GENV_STORE.getIteratorFactory()->createIndexProbeIterator(state->theCache);
232-
233- probeIte->init(cond);
234- probeIte->open();
235-
236- return probeIte->next(result);
237+ state->theCacheProbeIte->init(state->theCacheCond);
238+ state->theCacheProbeIte->open();
239+
240+ return state->theCacheProbeIte->next(result);
241 }
242
243
244@@ -320,18 +334,22 @@
245 void UDFunctionCallIterator::insertCacheEntry(
246 UDFunctionCallIteratorState* state,
247 std::vector<store::Item_t>& argValues,
248- store::Item_t& udfValue) const
249+ const store::Item_t& udfResult) const
250 {
251- if (state->theCache)
252- {
253- std::auto_ptr<store::IndexKey> k(new store::IndexKey());
254- store::IndexKey* k2 = k.get();
255- k->theItems = argValues;
256- store::Item_t lTmp = udfValue; // insert will eventually transfer the Item_t
257- if (!state->theCache->insert(k2, lTmp))
258- {
259- k.release();
260- }
261+ assert(state->theCache);
262+
263+ state->theCacheKey = new store::IndexKey();
264+ state->theCacheKey->theItems.swap(argValues);
265+ store::Item_t tmp = udfResult;
266+
267+ try
268+ {
269+ ZORBA_ASSERT(!state->theCache->insert(state->theCacheKey, tmp));
270+ }
271+ catch (...)
272+ {
273+ delete state->theCacheKey;
274+ throw;
275 }
276 }
277
278@@ -449,8 +467,9 @@
279 {
280 try
281 {
282- std::vector<store::Item_t> lKey;
283- bool lCacheHit;
284+ std::vector<store::Item_t> argValues;
285+ bool cacheHit;
286+ store::Item_t tmp;
287
288 UDFunctionCallIteratorState* state;
289 DEFAULT_STACK_INIT(UDFunctionCallIteratorState, state, planState);
290@@ -465,82 +484,133 @@
291 state->thePlanOpen = true;
292 }
293
294- // check if there is a cache and the result is already in the cache
295- lCacheHit = probeCache(planState, state, result, lKey);
296-
297- // if not in the cache, we bind the arguments to the function
298- if (!lCacheHit)
299- {
300- const std::vector<ArgVarRefs>& argsRefs = theUDF->getArgVarsRefs();
301- const std::vector<store::Iterator_t>& argWraps = state->theArgWrappers;
302-
303- for (size_t i = 0; i < argsRefs.size(); ++i)
304- {
305- if (argWraps[i] != NULL)
306- {
307- const ArgVarRefs& argVarRefs = argsRefs[i];
308- store::Iterator_t argWrapper;
309- if (state->theCache)
310- {
311- std::vector<store::Item_t> lParam(1, lKey[i]);
312- state->theArgValues.push_back(GENV_STORE.createTempSeq(lParam));
313- argWrapper = state->theArgValues.back()->getIterator();
314- argWrapper->open();
315- }
316- else
317- {
318+ if (state->theCache)
319+ {
320+ // check if the result is already in the cache
321+ cacheHit = probeCache(planState, state, result, argValues);
322+
323+ // if not in the cache, we bind the arguments to the function
324+ if (!cacheHit)
325+ {
326+ const std::vector<ArgVarRefs>& argsRefs = theUDF->getArgVarsRefs();
327+ const std::vector<store::Iterator_t>& argWraps = state->theArgWrappers;
328+
329+ for (csize i = 0; i < argsRefs.size(); ++i)
330+ {
331+ if (argWraps[i] != NULL)
332+ {
333+ const ArgVarRefs& argVarRefs = argsRefs[i];
334+ store::Iterator_t argWrapper;
335+
336+ store::Item_t argValue = argValues[i];
337+ state->theArgValues[i]->init(argValue);
338+ argWrapper = state->theArgValues[i];
339+
340+ ArgVarRefs::const_iterator argVarRefsIte = argVarRefs.begin();
341+ ArgVarRefs::const_iterator argVarRefsEnd = argVarRefs.end();
342+
343+ for (; argVarRefsIte != argVarRefsEnd; ++argVarRefsIte)
344+ {
345+ const LetVarIter_t& argRef = (*argVarRefsIte);
346+ assert(argRef != NULL);
347+
348+ if (argRef != NULL)
349+ {
350+ argRef->bind(argWrapper, *state->thePlanState);
351+ }
352+ }
353+ }
354+ }
355+ }
356+
357+ if (!cacheHit)
358+ {
359+ DEBUGGER_PUSH_FRAME;
360+
361+ if (consumeNext(result, state->thePlan, *state->thePlanState))
362+ {
363+ insertCacheEntry(state, argValues, result);
364+
365+ DEBUGGER_POP_FRAME;
366+ STACK_PUSH(true, state);
367+ DEBUGGER_PUSH_FRAME;
368+
369+ while (consumeNext(result, state->thePlan, *state->thePlanState))
370+ {
371+ tmp = result;
372+ ZORBA_ASSERT(state->theCache->insert(state->theCacheKey, tmp));
373+
374+ DEBUGGER_POP_FRAME;
375+ STACK_PUSH(true, state);
376+ DEBUGGER_PUSH_FRAME;
377+ }
378+ }
379+ else
380+ {
381+ insertCacheEntry(state, argValues, NULL);
382+ }
383+
384+ DEBUGGER_POP_FRAME;
385+ }
386+ else // cache hit
387+ {
388+ if (result != NULL)
389+ {
390+ STACK_PUSH(true, state);
391+
392+ while (state->theCacheProbeIte->next(result))
393+ {
394+ STACK_PUSH(true, state);
395+ }
396+ }
397+ }
398+ }
399+ else // no cache
400+ {
401+ {
402+ const std::vector<ArgVarRefs>& argsRefs = theUDF->getArgVarsRefs();
403+ const std::vector<store::Iterator_t>& argWraps = state->theArgWrappers;
404+
405+ for (csize i = 0; i < argsRefs.size(); ++i)
406+ {
407+ if (argWraps[i] != NULL)
408+ {
409+ const ArgVarRefs& argVarRefs = argsRefs[i];
410+ store::Iterator_t argWrapper;
411+
412 if (i < argWraps.size())
413 argWrapper = argWraps[i];
414- }
415-
416- ArgVarRefs::const_iterator argVarRefsIte = argVarRefs.begin();
417- ArgVarRefs::const_iterator argVarRefsEnd = argVarRefs.end();
418-
419- for (; argVarRefsIte != argVarRefsEnd; ++argVarRefsIte)
420- {
421- const LetVarIter_t& argRef = (*argVarRefsIte);
422- assert(argRef != NULL);
423-
424- if (argRef != NULL)
425+
426+ ArgVarRefs::const_iterator argVarRefsIte = argVarRefs.begin();
427+ ArgVarRefs::const_iterator argVarRefsEnd = argVarRefs.end();
428+
429+ for (; argVarRefsIte != argVarRefsEnd; ++argVarRefsIte)
430 {
431- argRef->bind(argWrapper, *state->thePlanState);
432+ const LetVarIter_t& argRef = (*argVarRefsIte);
433+ assert(argRef != NULL);
434+
435+ if (argRef != NULL)
436+ {
437+ argRef->bind(argWrapper, *state->thePlanState);
438+ }
439 }
440 }
441 }
442 }
443- }
444
445- if (lCacheHit)
446- {
447- STACK_PUSH(true, state);
448- }
449- else
450- {
451-#ifdef ZORBA_WITH_DEBUGGER
452 DEBUGGER_PUSH_FRAME;
453-#endif
454+
455 while (consumeNext(result, state->thePlan, *state->thePlanState))
456 {
457-#ifdef ZORBA_WITH_DEBUGGER
458 DEBUGGER_POP_FRAME;
459-#endif
460-
461- insertCacheEntry(state, lKey, result);
462 STACK_PUSH(true, state);
463-
464-#ifdef ZORBA_WITH_DEBUGGER
465 DEBUGGER_PUSH_FRAME;
466-#endif
467 }
468
469-#ifdef ZORBA_WITH_DEBUGGER
470 DEBUGGER_POP_FRAME;
471-#endif
472-
473 }
474
475 STACK_END(state);
476-
477 }
478 catch (ZorbaException& err)
479 {
480
481=== modified file 'src/runtime/core/fncall_iterator.h'
482--- src/runtime/core/fncall_iterator.h 2013-05-25 14:36:27 +0000
483+++ src/runtime/core/fncall_iterator.h 2013-06-16 06:47:28 +0000
484@@ -23,6 +23,7 @@
485 #include "common/shared_types.h"
486
487 #include "runtime/hof/function_item.h"
488+#include "runtime/util/single_item_iterator.h"
489
490 #include "context/static_context.h"
491
492@@ -93,15 +94,21 @@
493 class UDFunctionCallIteratorState : public PlanIteratorState
494 {
495 public:
496- dynamic_context * theLocalDCtx;
497- bool theIsLocalDCtxOwner;
498- PlanIter_t thePlan;
499- PlanState * thePlanState;
500- bool thePlanOpen;
501- uint32_t thePlanStateSize;
502- std::vector<store::Iterator_t> theArgWrappers;
503- store::Index * theCache;
504- std::vector<store::TempSeq_t> theArgValues;
505+ dynamic_context * theLocalDCtx;
506+ bool theIsLocalDCtxOwner;
507+
508+ PlanIter_t thePlan;
509+ PlanState * thePlanState;
510+ bool thePlanOpen;
511+ uint32_t thePlanStateSize;
512+
513+ std::vector<store::Iterator_t> theArgWrappers;
514+
515+ store::Index * theCache;
516+ store::IndexKey * theCacheKey;
517+ store::IndexCondition_t theCacheCond;
518+ store::IndexProbeIterator_t theCacheProbeIte;
519+ std::vector<SingleItemIterator_t> theArgValues;
520
521 UDFunctionCallIteratorState();
522
523@@ -194,7 +201,7 @@
524 void insertCacheEntry(
525 UDFunctionCallIteratorState* state,
526 std::vector<store::Item_t>& argValues,
527- store::Item_t& udfValue) const;
528+ const store::Item_t& udfResult) const;
529 };
530
531
532
533=== modified file 'src/runtime/util/item_iterator.cpp'
534--- src/runtime/util/item_iterator.cpp 2013-03-04 21:00:58 +0000
535+++ src/runtime/util/item_iterator.cpp 2013-06-16 06:47:28 +0000
536@@ -20,7 +20,7 @@
537
538 namespace zorba {
539
540-ItemIterator::ItemIterator(std::vector<store::Item_t> const &aItems)
541+ItemIterator::ItemIterator(const std::vector<store::Item_t>& aItems)
542 :
543 theItems(aItems)
544 {
545
546=== modified file 'src/runtime/util/item_iterator.h'
547--- src/runtime/util/item_iterator.h 2013-03-05 00:45:43 +0000
548+++ src/runtime/util/item_iterator.h 2013-06-16 06:47:28 +0000
549@@ -13,8 +13,8 @@
550 * See the License for the specific language governing permissions and
551 * limitations under the License.
552 */
553-#ifndef ZORBA_RUNTIME_ITEM_ITERATOR_H2
554-#define ZORBA_RUNTIME_ITEM_ITERATOR_H2
555+#ifndef ZORBA_RUNTIME_UTIL_ITEM_ITERATOR
556+#define ZORBA_RUNTIME_UTIL_ITEM_ITERATOR
557
558 #include <vector>
559 #include "store/api/iterator.h"
560@@ -25,12 +25,14 @@
561 class ItemIterator : public store::Iterator
562 {
563 private:
564- std::vector<store::Item_t> theItems;
565+ std::vector<store::Item_t> theItems;
566 std::vector<store::Item_t>::iterator theIterator;
567
568 public:
569- ItemIterator(std::vector<store::Item_t> const &aItems);
570+ ItemIterator(const std::vector<store::Item_t>& aItems);
571+
572 ItemIterator(store::Item_t aItem);
573+
574 ItemIterator(); // construct the empty sequence
575
576 virtual ~ItemIterator(){}
577
578=== added file 'src/runtime/util/single_item_iterator.h'
579--- src/runtime/util/single_item_iterator.h 1970-01-01 00:00:00 +0000
580+++ src/runtime/util/single_item_iterator.h 2013-06-16 06:47:28 +0000
581@@ -0,0 +1,80 @@
582+/*
583+ * Copyright 2006-2008 The FLWOR Foundation.
584+ *
585+ * Licensed under the Apache License, Version 2.0 (the "License");
586+ * you may not use this file except in compliance with the License.
587+ * You may obtain a copy of the License at
588+ *
589+ * http://www.apache.org/licenses/LICENSE-2.0
590+ *
591+ * Unless required by applicable law or agreed to in writing, software
592+ * distributed under the License is distributed on an "AS IS" BASIS,
593+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
594+ * See the License for the specific language governing permissions and
595+ * limitations under the License.
596+ */
597+#ifndef ZORBA_RUNTIME_UTIL_SINGLE_ITEM_ITERATOR
598+#define ZORBA_RUNTIME_UTIL_SINGLE_ITEM_ITERATOR
599+
600+#include <vector>
601+
602+#include "store/api/iterator.h"
603+
604+#include "common/shared_types.h"
605+
606+namespace zorba
607+{
608+
609+class SingleItemIterator : public store::Iterator
610+{
611+private:
612+ store::Item_t theItem;
613+ bool theIsDone;
614+
615+public:
616+ SingleItemIterator() : theIsDone(true) {}
617+
618+ SingleItemIterator(store::Item_t& item)
619+ {
620+ theIsDone = false;
621+ theItem.transfer(item);
622+ }
623+
624+ virtual ~SingleItemIterator() {}
625+
626+ void init(store::Item_t& item)
627+ {
628+ theIsDone = false;
629+ theItem.transfer(item);
630+ }
631+
632+ void open() {}
633+
634+ bool next(store::Item_t& res)
635+ {
636+ if (theIsDone)
637+ return false;
638+
639+ res = theItem;
640+ theIsDone = true;
641+ return true;
642+ }
643+
644+ void reset() { theIsDone = (theItem == NULL); }
645+
646+ void close() { theItem = NULL; theIsDone = true; }
647+
648+#ifndef NDEBUG
649+ // toString() debugging method.
650+ virtual std::string toString() const { return ""; };
651+#endif
652+};
653+
654+
655+typedef rchandle<SingleItemIterator> SingleItemIterator_t;
656+
657+
658+} // namespace zorba
659+
660+#endif
661+/* vim:set et sw=2 ts=2: */
662
663=== added file 'test/rbkt/ExpQueryResults/zorba/udf/cache01.xml.res'
664--- test/rbkt/ExpQueryResults/zorba/udf/cache01.xml.res 1970-01-01 00:00:00 +0000
665+++ test/rbkt/ExpQueryResults/zorba/udf/cache01.xml.res 2013-06-16 06:47:28 +0000
666@@ -0,0 +1,6 @@
667+4
668+
669+ 4
670+
671+ 22 == 484
672+ 22 == 484
673
674=== added file 'test/rbkt/ExpQueryResults/zorba/udf/cache_01.xml.res'
675--- test/rbkt/ExpQueryResults/zorba/udf/cache_01.xml.res 1970-01-01 00:00:00 +0000
676+++ test/rbkt/ExpQueryResults/zorba/udf/cache_01.xml.res 2013-06-16 06:47:28 +0000
677@@ -0,0 +1,6 @@
678+4
679+
680+ 4
681+
682+ 22 == 484
683+ 22 == 484
684
685=== added file 'test/rbkt/Queries/zorba/udf/cache_01.xq'
686--- test/rbkt/Queries/zorba/udf/cache_01.xq 1970-01-01 00:00:00 +0000
687+++ test/rbkt/Queries/zorba/udf/cache_01.xq 2013-06-16 06:47:28 +0000
688@@ -0,0 +1,37 @@
689+
690+declare namespace ann = "http://www.zorba-xquery.com/annotations";
691+
692+declare function local:dummy()
693+{
694+ ()
695+};
696+
697+
698+declare %ann:cache function local:foo($x as xs:integer)
699+{
700+ if ($x < 10)
701+ then $x * $x
702+ else if ($x < 20)
703+ then local:dummy()
704+ else ($x, " == ", $x * $x)
705+};
706+
707+
708+local:foo(2),
709+"
710+",
711+local:foo(12),
712+"
713+",
714+local:foo(2),
715+"
716+",
717+local:foo(12),
718+"
719+",
720+local:foo(22),
721+"
722+",
723+local:foo(22),
724+"
725+"

Subscribers

People subscribed via source and target branches