Merge lp:~zorba-coders/zorba/pub_iter_imp into lp:zorba
- pub_iter_imp
- Merge into trunk
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 |
Related bugs: |
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.
Paul J. Lucas (paul-lucas) : | # |
Paul J. Lucas (paul-lucas) wrote : | # |
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">
<ExtFunctio
<
<
<
</ExtFuncti
</TreatIterator>
</FnCountIterator>
The TreatIterator doesn't override count and, hence, the count call never gets executed on the ExtFunctionCall
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:
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:
- 11691. By Paul J. Lucas
-
Intermedaite check-in.
- 11692. By Paul J. Lucas
-
Merge from trunk.
Paul J. Lucas (paul-lucas) wrote : | # |
I've implemented TreatIterator:
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.)
- 11693. By Paul J. Lucas
-
Added TreatIterator:
:count( ) and skip(). - 11694. By Paul J. Lucas
-
Merge from trunk.
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: {'Approve': 1, 'Pending': 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 : | # |
Why are there plain english error messages in there? For example, "sequence of more than one item".
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!
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
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 | }; |
So this looks right to me, but it doesn't work. ExtFunctionCall Iterator: :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?