Merge lp:~zorba-coders/zorba/pub_iter_imp into lp:zorba

Proposed by Paul J. Lucas
Status: Merged
Approved by: Paul J. Lucas
Approved revision: 11694
Merged at revision: 11689
Proposed branch: lp:~zorba-coders/zorba/pub_iter_imp
Merge into: lp:zorba
Diff against target: 610 lines (+290/-44)
11 files modified
include/zorba/function.h (+16/-25)
include/zorba/iterator.h (+23/-6)
modules/ftp-client/ftp-client.xq.src/ftp_functions.cpp (+38/-5)
src/api/CMakeLists.txt (+2/-0)
src/api/external_function.cpp (+30/-0)
src/api/iterator.cpp (+43/-0)
src/runtime/base/plan_iterator.cpp (+1/-1)
src/runtime/core/fncall_iterator.cpp (+90/-7)
src/runtime/core/fncall_iterator.h (+3/-0)
src/runtime/core/sequencetypes.cpp (+40/-0)
src/runtime/core/sequencetypes.h (+4/-0)
To merge this branch: bzr merge lp:~zorba-coders/zorba/pub_iter_imp
Reviewer Review Type Date Requested Status
Matthias Brantner Approve
Paul J. Lucas Approve
Review via email: mp+201708@code.launchpad.net

Commit message

Added count() & skip() to public Iterator API.

Description of the change

Added count() & skip() to public Iterator API.

To post a comment you must log in.
Revision history for this message
Paul J. Lucas (paul-lucas) :
review: Approve
Revision history for this message
Paul J. Lucas (paul-lucas) wrote :

So this looks right to me, but it doesn't work. ExtFunctionCallIterator::count() never gets called it seems. I did a test like:

let $conn := ftp:connect( "127.0.0.1", $options )
let $remote-path := "/"
return fn:count( ftp:list( $conn, $remote-path ) )

That should work, right?

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

The problem is that there is a TreatIterator put in place checking the return type of the function.

<FnCountIterator id="0x1926410">
  <TreatIterator type="[JSONXQType object]" quant="*" id="0x191d1e0">
    <ExtFunctionCallIterator id="0x193e380">
      <TreatIterator type="xs:anyURI" quant="" id="0x191cf20">
        <ExtFunctionCallIterator id="0x191e490">
          <SingletonIterator value="xs:string(127.0.0.1)" id="0x1927400"/>
          <JSONObjectIterator id="0x19264f0"/>
        </ExtFunctionCallIterator>
      </TreatIterator>
      <SingletonIterator value="xs:string(/)" id="0x19730c0"/>
    </ExtFunctionCallIterator>
  </TreatIterator>
</FnCountIterator>

The TreatIterator doesn't override count and, hence, the count call never gets executed on the ExtFunctionCallIterator. Could you please look at the implementation of the TreatIterator. I don't think this can easily be done but maybe you have an idea.

Revision history for this message
Paul J. Lucas (paul-lucas) wrote :

It depends on what the semantics of fn:count() are, i.e., is is supposed to do the type checks that TreatIterator::nextImpl() does? If the point of the count optimization is not to materialize the objects, then you (obviously) can't do type checks. But is that legal?

However, I think (correct me if I'm wrong) that the presence of fn:count() wrapped around an expression changes what the expected type is (to xs:integer) and it also makes the quantization checks irrelevant since fn:count() works on any length sequence.

If that's true, then TreatIterator::count() would simply call its child's count without any other checks. I think the same would be true for skip().

lp:~zorba-coders/zorba/pub_iter_imp updated
11691. By Paul J. Lucas

Intermedaite check-in.

11692. By Paul J. Lucas

Merge from trunk.

Revision history for this message
Paul J. Lucas (paul-lucas) wrote :

I've implemented TreatIterator::count(), but it's not clear what skip() should do, exactly. Should it just call its' child's skip()? Should it do some other checks? If so, what?

The problem is that skip() only reports whether there are *more* left, not how many are left.

What if the sequence has 5 elements, you tell it to skip 4, and the quantifier is 1? Is that invalid (because there were originally 5) or valid (because there is now exactly 1 left)?

(You can construct similar "what if" questions for the other quantifiers as well.)

lp:~zorba-coders/zorba/pub_iter_imp updated
11693. By Paul J. Lucas

Added TreatIterator::count() and skip().

11694. By Paul J. Lucas

Merge from trunk.

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/pub_iter_imp/+merge/201708

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/pub_iter_imp/+merge/201708 :
Votes: {'Approve': 1, 'Pending': 1}

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

Validation queue result for https://code.launchpad.net/~zorba-coders/zorba/pub_iter_imp/+merge/201708

Stage "CommitZorba" failed.

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

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

Why are there plain english error messages in there? For example, "sequence of more than one item".

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/pub_iter_imp/+merge/201708

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!

Revision history for this message
Paul J. Lucas (paul-lucas) wrote :

> Why are there plain english error messages in there? For example, "sequence of
> more than one item".

Because the original code had them. The raiseError() function is non-trivial and I didn't feel like figuring it out at this point. It should be fixed, I agree.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/zorba/function.h'
2--- include/zorba/function.h 2013-08-23 11:15:04 +0000
3+++ include/zorba/function.h 2014-01-17 20:08:57 +0000
4@@ -4,7 +4,7 @@
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8- *
9+ *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13@@ -30,10 +30,10 @@
14
15 /**************************************************************************//**
16 The Function class represents a function that is callable from XQuery code,
17- and it gives access to the various properties that are specified in the
18+ and it gives access to the various properties that are specified in the
19 declaration of the function within a Prolog.
20
21- Instances of Function are returned by the StaticContext::findFunctions()
22+ Instances of Function are returned by the StaticContext::findFunctions()
23 method. To be mopre precise, StaticContext::findFunctions() returns smart
24 pointers to Function objects. These smart pointers must be destroyed before
25 the StaticContext object they were obtained from is destroyed.
26@@ -45,31 +45,27 @@
27 class ZORBA_DLL_PUBLIC Function : public SmartObject
28 {
29 public:
30- /** \brief Destructor
31- */
32- virtual ~Function() {}
33-
34 /**
35 * @return True if the function is sequential; false otherwise.
36- */
37+ */
38 virtual bool
39 isSequential() const = 0;
40
41 /**
42 * @return True if the function is updating; false otherwise.
43- */
44+ */
45 virtual bool
46 isUpdating() const = 0;
47
48 /**
49 * @return True if the function is private; false otherwise.
50- */
51+ */
52 virtual bool
53 isPrivate() const = 0;
54
55 /**
56 * @return True if the function is deterministic; false otherwise.
57- */
58+ */
59 virtual bool
60 isDeterministic() const = 0;
61
62@@ -99,7 +95,7 @@
63
64 /**
65 * @return The arity of the function. If the function is variadic (which is
66- * possible only for builtin functions), the result of this method
67+ * possible only for builtin functions), the result of this method
68 * is non-deterministic.
69 */
70 virtual size_t
71@@ -119,7 +115,7 @@
72
73 /**
74 * @return True if the function implementation is written in XQuery (or
75- * equivalently, it is a non-external function with a Prolog
76+ * equivalently, it is a non-external function with a Prolog
77 * declaration); false otherwise
78 */
79 virtual bool
80@@ -138,10 +134,10 @@
81 The ExternalFunction class serves as the base of subclasses that represent
82 the implementation/body of external functions.
83
84- Instances of ExternalFunction must provide an evaluate method that serves
85- as the implementation of the function. During its evaluation, an external
86- function may or may not need to access the static and/or dynamic context of
87- the invoking XQuery module. If the function implementation does need to
88+ Instances of ExternalFunction must provide an evaluate method that serves
89+ as the implementation of the function. During its evaluation, an external
90+ function may or may not need to access the static and/or dynamic context of
91+ the invoking XQuery module. If the function implementation does need to
92 access either context, the function is referred to as "contextual"; otherwise,
93 it is "non-contextual".
94 *******************************************************************************/
95@@ -150,8 +146,7 @@
96 public:
97 typedef std::vector<ItemSequence*> Arguments_t;
98
99- public:
100- virtual ~ExternalFunction() {}
101+ virtual ~ExternalFunction();
102
103 /**
104 * @return The namespace URI of the function QName
105@@ -189,8 +184,6 @@
106 class ZORBA_DLL_PUBLIC NonContextualExternalFunction : public ExternalFunction
107 {
108 public:
109- virtual ~NonContextualExternalFunction() {}
110-
111 virtual ItemSequence_t
112 evaluate(const Arguments_t&) const = 0;
113
114@@ -201,7 +194,7 @@
115
116 /**************************************************************************//**
117 The ContextualExternalFunction class serves as the base of subclasses that
118- represent the implementation of contextual external functions.
119+ represent the implementation of contextual external functions.
120
121 For each external function, an application must provide a concrete subclass
122 of this class and "store" an instance of the subclass inside an ExternalModule
123@@ -211,14 +204,12 @@
124 class ZORBA_DLL_PUBLIC ContextualExternalFunction : public ExternalFunction
125 {
126 public:
127- virtual ~ContextualExternalFunction() {}
128-
129 virtual ItemSequence_t
130 evaluate(
131 const Arguments_t&,
132 const StaticContext*,
133 const DynamicContext*) const = 0;
134-
135+
136 bool
137 isContextual() const { return true; }
138 };
139
140=== modified file 'include/zorba/iterator.h'
141--- include/zorba/iterator.h 2013-08-01 09:52:25 +0000
142+++ include/zorba/iterator.h 2014-01-17 20:08:57 +0000
143@@ -34,13 +34,10 @@
144 class ZORBA_DLL_PUBLIC Iterator : virtual public SmartObject
145 {
146 public:
147- /** \brief Destructor
148- */
149- virtual ~Iterator() {}
150-
151 /** \brief Start iterating.
152 *
153- * This function needs to be called before calling next() or close().
154+ * This function needs to be called before calling next(), count(), skip() or
155+ * close().
156 * Its purpose is to create and initialize any resources that may be
157 * needed during the iteration. It should not be called again until
158 * after close() has been called.
159@@ -73,10 +70,30 @@
160 close() = 0;
161
162 /**
163- * brief Check whether the iterator is open or not
164+ * \brief Check whether the iterator is open or not
165 */
166 virtual bool
167 isOpen() const = 0;
168+
169+ /**
170+ * Counts the number of items this iterator would have returned.
171+ *
172+ * @throw ZorbaException if an error occurs or the iterator has not been
173+ * opened.
174+ */
175+ virtual int64_t
176+ count();
177+
178+ /**
179+ * Skips a number of items.
180+ *
181+ * @param count The number of items to skip.
182+ * @return \c true only if there are more items.
183+ * @throw ZorbaException if an error occurs or the iterator has not been
184+ * opened.
185+ */
186+ virtual bool
187+ skip(int64_t count);
188 };
189
190
191
192=== modified file 'modules/ftp-client/ftp-client.xq.src/ftp_functions.cpp'
193--- modules/ftp-client/ftp-client.xq.src/ftp_functions.cpp 2014-01-11 01:27:47 +0000
194+++ modules/ftp-client/ftp-client.xq.src/ftp_functions.cpp 2014-01-17 20:08:57 +0000
195@@ -612,14 +612,18 @@
196
197 // inherited from Iterator
198 void close();
199+ int64_t count();
200 bool isOpen() const;
201 bool next( Item& );
202 void open();
203+ bool skip( int64_t );
204
205 private:
206 ItemFactory *const factory_;
207 istream is_;
208 bool open_;
209+
210+ bool get_line( string* );
211 };
212
213 list_iterator::list_iterator( curl::streambuf *cbuf, ItemFactory *factory ) :
214@@ -633,10 +637,32 @@
215 open_ = false;
216 }
217
218+int64_t list_iterator::count() {
219+ int64_t count = 0;
220+ string line;
221+ while ( get_line( &line ) ) {
222+ struct ftpparse ftp_file;
223+ if ( ftpparse( &ftp_file, line.data(), line.size() ) )
224+ ++count;
225+ } // while
226+ return count;
227+}
228+
229 Iterator_t list_iterator::getIterator() {
230 return this;
231 }
232
233+bool list_iterator::get_line( string *line ) {
234+ while ( getline( is_, *line ) ) {
235+ if ( !line->empty() ) {
236+ if ( (*line)[ line->size() - 1 ] == '\r' )
237+ line->erase( line->size() - 1 );
238+ return true;
239+ }
240+ } // while
241+ return false;
242+}
243+
244 bool list_iterator::isOpen() const {
245 return open_;
246 }
247@@ -647,11 +673,7 @@
248 static Item const size_key( factory_->createString( "size" ) );
249
250 string line;
251- while ( getline( is_, line ) ) {
252- if ( line.empty() )
253- continue;
254- if ( line[ line.size() - 1 ] == '\r' )
255- line.erase( line.size() - 1 );
256+ while ( get_line( &line ) ) {
257 struct ftpparse ftp_file;
258 if ( ftpparse( &ftp_file, line.data(), line.size() ) ) {
259 vector<pair<Item,Item> > kv;
260@@ -709,6 +731,17 @@
261 open_ = true;
262 }
263
264+bool list_iterator::skip( int64_t count ) {
265+ string line;
266+ bool more_items = true;
267+ while ( count > 0 && (more_items = get_line( &line )) ) {
268+ struct ftpparse ftp_file;
269+ if ( ftpparse( &ftp_file, line.data(), line.size() ) )
270+ --count;
271+ } // while
272+ return more_items;
273+}
274+
275 list_function::list_function( module const *m ) :
276 function( m, "list" )
277 {
278
279=== modified file 'src/api/CMakeLists.txt'
280--- src/api/CMakeLists.txt 2014-01-03 17:31:44 +0000
281+++ src/api/CMakeLists.txt 2014-01-17 20:08:57 +0000
282@@ -16,8 +16,10 @@
283
284 SET(API_SRCS
285 base64_util.cpp
286+ external_function.cpp
287 smart_ptr.cpp
288 diagnostic_handler.cpp
289+ iterator.cpp
290 zorba.cpp
291 zorbaimpl.cpp
292 xqueryimpl.cpp
293
294=== added file 'src/api/external_function.cpp'
295--- src/api/external_function.cpp 1970-01-01 00:00:00 +0000
296+++ src/api/external_function.cpp 2014-01-17 20:08:57 +0000
297@@ -0,0 +1,30 @@
298+/*
299+ * Copyright 2006-2013 The FLWOR Foundation.
300+ *
301+ * Licensed under the Apache License, Version 2.0 (the "License");
302+ * you may not use this file except in compliance with the License.
303+ * You may obtain a copy of the License at
304+ *
305+ * http://www.apache.org/licenses/LICENSE-2.0
306+ *
307+ * Unless required by applicable law or agreed to in writing, software
308+ * distributed under the License is distributed on an "AS IS" BASIS,
309+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
310+ * See the License for the specific language governing permissions and
311+ * limitations under the License.
312+ */
313+
314+#include <zorba/function.h>
315+
316+namespace zorba {
317+
318+///////////////////////////////////////////////////////////////////////////////
319+
320+ExternalFunction::~ExternalFunction() {
321+ // out-of-line since it's virtual
322+}
323+
324+///////////////////////////////////////////////////////////////////////////////
325+
326+} // namespace zorba
327+/* vim:set et sw=2 ts=2: */
328
329=== added file 'src/api/iterator.cpp'
330--- src/api/iterator.cpp 1970-01-01 00:00:00 +0000
331+++ src/api/iterator.cpp 2014-01-17 20:08:57 +0000
332@@ -0,0 +1,43 @@
333+/*
334+ * Copyright 2006-2013 The FLWOR Foundation.
335+ *
336+ * Licensed under the Apache License, Version 2.0 (the "License");
337+ * you may not use this file except in compliance with the License.
338+ * You may obtain a copy of the License at
339+ *
340+ * http://www.apache.org/licenses/LICENSE-2.0
341+ *
342+ * Unless required by applicable law or agreed to in writing, software
343+ * distributed under the License is distributed on an "AS IS" BASIS,
344+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
345+ * See the License for the specific language governing permissions and
346+ * limitations under the License.
347+ */
348+
349+#include <zorba/item.h>
350+#include <zorba/iterator.h>
351+
352+namespace zorba {
353+
354+///////////////////////////////////////////////////////////////////////////////
355+
356+int64_t Iterator::count() {
357+ int64_t count = 0;
358+ Item item;
359+ while ( next( item ) )
360+ ++count;
361+ return count;
362+}
363+
364+bool Iterator::skip( int64_t count ) {
365+ Item item;
366+ bool more_items = true;
367+ while ( count > 0 && (more_items = next( item )) )
368+ --count;
369+ return more_items;
370+}
371+
372+///////////////////////////////////////////////////////////////////////////////
373+
374+} // namespace zorba
375+/* vim:set et sw=2 ts=2: */
376
377=== modified file 'src/runtime/base/plan_iterator.cpp'
378--- src/runtime/base/plan_iterator.cpp 2013-08-05 11:54:06 +0000
379+++ src/runtime/base/plan_iterator.cpp 2014-01-17 20:08:57 +0000
380@@ -186,7 +186,7 @@
381 ++count;
382 }
383
384- STACK_PUSH(GENV_ITEMFACTORY->createInteger(result, Integer(count)), state);
385+ STACK_PUSH(GENV_ITEMFACTORY->createInteger(result, xs_integer(count)), state);
386 STACK_END(state);
387 }
388
389
390=== modified file 'src/runtime/core/fncall_iterator.cpp'
391--- src/runtime/core/fncall_iterator.cpp 2014-01-10 22:33:46 +0000
392+++ src/runtime/core/fncall_iterator.cpp 2014-01-17 20:08:57 +0000
393@@ -49,8 +49,9 @@
394 #include "util/string_util.h"
395
396 #include "store/api/index.h"
397+#include "store/api/item_factory.h"
398+#include "store/api/iterator_factory.h"
399 #include "store/api/store.h"
400-#include "store/api/iterator_factory.h"
401 #include "store/api/temp_seq.h"
402
403
404@@ -859,6 +860,93 @@
405 }
406 }
407
408+bool ExtFunctionCallIterator::count( store::Item_t &result,
409+ PlanState &planState ) const {
410+ ItemSequence_t api_seq;
411+
412+ ExtFunctionCallIteratorState *state;
413+ DEFAULT_STACK_INIT( ExtFunctionCallIteratorState, state, planState );
414+
415+ try {
416+ if ( theFunction->isContextual() ) {
417+ ContextualExternalFunction const *const f =
418+ dynamic_cast<ContextualExternalFunction const*>( theFunction );
419+ ZORBA_ASSERT( f );
420+ StaticContextImpl sctx(
421+ theModuleSctx,
422+ planState.theQuery ?
423+ planState.theQuery->getRegisteredDiagnosticHandlerNoSync() :
424+ nullptr
425+ );
426+ DynamicContextImpl dctx(
427+ nullptr, planState.theGlobalDynCtx, theModuleSctx
428+ );
429+ api_seq = f->evaluate( state->m_extArgs, &sctx, &dctx );
430+ } else {
431+ NonContextualExternalFunction const *const f =
432+ dynamic_cast<NonContextualExternalFunction const*>( theFunction );
433+ ZORBA_ASSERT( f );
434+ api_seq = f->evaluate( state->m_extArgs );
435+ }
436+ if ( !!api_seq ) {
437+ Iterator_t api_iter( api_seq->getIterator() );
438+ api_iter->open();
439+ int64_t const count = api_iter->count();
440+ api_iter->close();
441+ GENV_ITEMFACTORY->createInteger( result, xs_integer( count ) );
442+ }
443+ }
444+ catch ( ZorbaException &e ) {
445+ set_source( e, loc );
446+ throw;
447+ }
448+ STACK_PUSH( true, state );
449+ STACK_END( state );
450+}
451+
452+bool ExtFunctionCallIterator::skip( int64_t count,
453+ PlanState &planState ) const {
454+ ItemSequence_t api_seq;
455+ bool more_items;
456+
457+ ExtFunctionCallIteratorState *state;
458+ DEFAULT_STACK_INIT( ExtFunctionCallIteratorState, state, planState );
459+
460+ try {
461+ if ( theFunction->isContextual() ) {
462+ ContextualExternalFunction const *const f =
463+ dynamic_cast<ContextualExternalFunction const*>( theFunction );
464+ ZORBA_ASSERT( f );
465+ StaticContextImpl sctx(
466+ theModuleSctx,
467+ planState.theQuery ?
468+ planState.theQuery->getRegisteredDiagnosticHandlerNoSync() :
469+ nullptr
470+ );
471+ DynamicContextImpl dctx(
472+ nullptr, planState.theGlobalDynCtx, theModuleSctx
473+ );
474+ api_seq = f->evaluate( state->m_extArgs, &sctx, &dctx );
475+ } else {
476+ NonContextualExternalFunction const *const f =
477+ dynamic_cast<NonContextualExternalFunction const*>( theFunction );
478+ ZORBA_ASSERT( f );
479+ api_seq = f->evaluate( state->m_extArgs );
480+ }
481+ if ( !!api_seq ) {
482+ Iterator_t api_iter( api_seq->getIterator() );
483+ api_iter->open();
484+ more_items = api_iter->skip( count );
485+ api_iter->close();
486+ }
487+ }
488+ catch ( ZorbaException &e ) {
489+ set_source( e, loc );
490+ throw;
491+ }
492+ STACK_PUSH( more_items, state );
493+ STACK_END( state );
494+}
495
496 bool ExtFunctionCallIterator::nextImpl(
497 store::Item_t& result,
498@@ -906,17 +994,12 @@
499 state->theResultIter = state->theResult->getIterator();
500 } // if (!theFunction->isContextual())
501 }
502- catch (XQueryException& e)
503- {
504- set_source( e, loc );
505- throw;
506- }
507 catch (ZorbaException& e)
508 {
509 set_source( e, loc );
510 throw;
511 }
512- catch (std::exception& e)
513+ catch (std::exception const& e)
514 {
515 throw XQUERY_EXCEPTION(
516 zerr::ZXQP0001_DYNAMIC_RUNTIME_ERROR,
517
518=== modified file 'src/runtime/core/fncall_iterator.h'
519--- src/runtime/core/fncall_iterator.h 2013-09-26 09:37:30 +0000
520+++ src/runtime/core/fncall_iterator.h 2014-01-17 20:08:57 +0000
521@@ -259,6 +259,9 @@
522 void openImpl(PlanState& planState, uint32_t& offset);
523
524 bool nextImpl(store::Item_t& result, PlanState& planState) const;
525+
526+ bool count(store::Item_t& result, PlanState& planState) const;
527+ bool skip(int64_t count, PlanState &planState) const;
528 };
529
530 }
531
532=== modified file 'src/runtime/core/sequencetypes.cpp'
533--- src/runtime/core/sequencetypes.cpp 2013-09-16 09:08:27 +0000
534+++ src/runtime/core/sequencetypes.cpp 2014-01-17 20:08:57 +0000
535@@ -32,6 +32,8 @@
536
537 #include "store/api/item_factory.h"
538
539+#include "zorbatypes/integer.h"
540+#include "zorbatypes/numeric_types.h"
541
542 namespace zorba
543 {
544@@ -587,6 +589,44 @@
545 ar & theQName;
546 }
547
548+bool TreatIterator::count( store::Item_t &result, PlanState &planState) const {
549+ bool const ret_val = theChild->count( result, planState );
550+ xs_integer const count( result->getIntegerValue() );
551+
552+ switch ( theQuantifier ) {
553+ case SequenceType::QUANT_QUESTION:
554+ if ( count <= numeric_consts<xs_integer>::one() )
555+ break;
556+ // no break;
557+ case SequenceType::QUANT_ONE:
558+ if ( count > numeric_consts<xs_integer>::one() )
559+ raiseError("sequence of more than one item");
560+ // no break;
561+ case SequenceType::QUANT_PLUS:
562+ if ( count == numeric_consts<xs_integer>::zero() )
563+ raiseError("empty-sequence()");
564+ break;
565+ default:
566+ // do nothing
567+ break;
568+ }
569+ return ret_val;
570+}
571+
572+bool TreatIterator::skip( int64_t count, PlanState &planState ) const {
573+ switch ( theQuantifier ) {
574+ //
575+ // Given that the skip() signature is not as good as it could be (it should
576+ // return a pair<int64_t,bool> indicating how many were skipped and whether
577+ // there are more), it's not possible to optimize this for any quantifier
578+ // other than '*' (since any number of elements is valid for '*').
579+ //
580+ case SequenceType::QUANT_STAR:
581+ return theChild->skip( count, planState );
582+ default:
583+ return base_type::skip( count, planState );
584+ }
585+}
586
587 bool TreatIterator::nextImpl(store::Item_t& result, PlanState& planState) const
588 {
589
590=== modified file 'src/runtime/core/sequencetypes.h'
591--- src/runtime/core/sequencetypes.h 2013-06-13 14:54:50 +0000
592+++ src/runtime/core/sequencetypes.h 2014-01-17 20:08:57 +0000
593@@ -213,6 +213,7 @@
594 PlanIteratorState>
595 {
596 friend class PrinterVisitor;
597+ typedef UnaryBaseIterator<TreatIterator,PlanIteratorState> base_type;
598
599 private:
600 xqtref_t theTreatType;
601@@ -242,6 +243,9 @@
602
603 bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;
604
605+ bool count(store::Item_t& result, PlanState& planState) const;
606+ bool skip(int64_t count, PlanState &planState) const;
607+
608 protected:
609 void raiseError(const zstring& valueType) const;
610 };

Subscribers

People subscribed via source and target branches