Federico Cavalieri has proposed merging lp:~zorba-coders/zorba/fix-fncall-iterator into lp:zorba.
Commit message: Fixed external functions skip iterator Requested reviews: Matthias Brantner (matthias-brantner) For more details, see: https://code.launchpad.net/~zorba-coders/zorba/fix-fncall-iterator/+merge/215934 Fixed external functions skip iterator -- https://code.launchpad.net/~zorba-coders/zorba/fix-fncall-iterator/+merge/215934 Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'src/runtime/core/fncall_iterator.cpp' --- src/runtime/core/fncall_iterator.cpp 2014-02-25 03:58:17 +0000 +++ src/runtime/core/fncall_iterator.cpp 2014-04-15 18:58:26 +0000 @@ -773,7 +773,8 @@ /******************************************************************************* ********************************************************************************/ -ExtFunctionCallIteratorState::ExtFunctionCallIteratorState() +ExtFunctionCallIteratorState::ExtFunctionCallIteratorState(): + theIsEvaluated(false) { } @@ -951,48 +952,40 @@ STACK_END( state ); } -bool ExtFunctionCallIterator::skip( int64_t count, - PlanState &planState ) const { +bool ExtFunctionCallIterator::skip(int64_t count, PlanState &planState) const +{ ItemSequence_t api_seq; bool more_items; - - ExtFunctionCallIteratorState *state; - DEFAULT_STACK_INIT( ExtFunctionCallIteratorState, state, planState ); - - try { - if ( theFunction->isContextual() ) { - ContextualExternalFunction const *const f = - dynamic_cast<ContextualExternalFunction const*>( theFunction ); - ZORBA_ASSERT( f ); - StaticContextImpl sctx( - theModuleSctx, - planState.theQuery ? - planState.theQuery->getRegisteredDiagnosticHandlerNoSync() : - nullptr - ); - DynamicContextImpl dctx( - nullptr, planState.theGlobalDynCtx, theModuleSctx - ); - api_seq = f->evaluate( state->m_extArgs, &sctx, &dctx ); - } else { - NonContextualExternalFunction const *const f = - dynamic_cast<NonContextualExternalFunction const*>( theFunction ); - ZORBA_ASSERT( f ); - api_seq = f->evaluate( state->m_extArgs ); - } - if ( !!api_seq ) { - Iterator_t api_iter( api_seq->getIterator() ); - api_iter->open(); - more_items = api_iter->skip( count ); - api_iter->close(); + ExtFunctionCallIteratorState *state = + StateTraitsImpl<ExtFunctionCallIteratorState>::getState(planState, this->theStateOffset); + + try + { + ZORBA_ASSERT(!state->theIsEvaluated); + evaluate(state, planState); + + if ( !state->theResult.isNull() ) + { + state->theResultIter = state->theResult->getIterator(); + state->theResultIter->open(); + more_items = state->theResultIter->skip( count ); + if (!more_items) + state->theResultIter->close(); } } - catch ( ZorbaException &e ) { + catch ( ZorbaException &e ) + { set_source( e, loc ); throw; } - STACK_PUSH( more_items, state ); - STACK_END( state ); + catch (std::exception const& e) + { + throw XQUERY_EXCEPTION( + zerr::ZXQP0001_DYNAMIC_RUNTIME_ERROR, + ERROR_PARAMS(e.what()), + ERROR_LOC(loc)); + } + return more_items; } bool ExtFunctionCallIterator::nextImpl( @@ -1000,102 +993,110 @@ PlanState& planState) const { Item lOutsideItem; - const NonContextualExternalFunction* lPureFct = 0; - const ContextualExternalFunction* lNonePureFct = 0; ExtFunctionCallIteratorState* state; DEFAULT_STACK_INIT(ExtFunctionCallIteratorState, state, planState); - try - { - if (!theFunction->isContextual()) - { - lPureFct = dynamic_cast<const NonContextualExternalFunction*>(theFunction); - ZORBA_ASSERT(lPureFct); - - state->theResult = lPureFct->evaluate(state->m_extArgs); - if(state->theResult.get() != NULL) - state->theResultIter = state->theResult->getIterator(); - } - else - { - lNonePureFct = dynamic_cast<const ContextualExternalFunction*>(theFunction); - ZORBA_ASSERT(lNonePureFct); - - // The planState.theQuery maybe null, e.g. in the case of constant-folding - // of global variable expressions - StaticContextImpl theSctxWrapper(theModuleSctx, - (planState.theQuery == NULL? - NULL : - planState.theQuery->getRegisteredDiagnosticHandlerNoSync())); - - DynamicContextImpl theDctxWrapper(NULL, - planState.theGlobalDynCtx, - theModuleSctx); - - state->theResult = lNonePureFct->evaluate(state->m_extArgs, - &theSctxWrapper, - &theDctxWrapper); - - if(state->theResult.get() != NULL) - state->theResultIter = state->theResult->getIterator(); - } // if (!theFunction->isContextual()) - } - catch (ZorbaException& e) - { - set_source( e, loc ); - throw; - } - catch (std::exception const& e) - { - throw XQUERY_EXCEPTION( - zerr::ZXQP0001_DYNAMIC_RUNTIME_ERROR, - ERROR_PARAMS(e.what()), - ERROR_LOC(loc)); - } - - - if(state->theResult.get() != NULL) - { - state->theResultIter->open(); - } - while (true) + if (!state->theIsEvaluated) { try { - if (state->theResult.get() == NULL) // This will happen if the user's external function returns a zorba::ItemSequence_t(NULL) - break; - - if (!state->theResultIter->next(lOutsideItem)) - { - state->theResultIter->close(); - break; - } - } - catch (XQueryException& e) - { - set_source( e, loc ); - throw; - } - - result = Unmarshaller::getInternalItem(lOutsideItem); - - if (theIsUpdating) - { - if (!result->isPul()) - throw XQUERY_EXCEPTION(err::XUDY0019, ERROR_LOC(loc)); - } - else - { - if (result->isPul()) - throw XQUERY_EXCEPTION(err::XUDY0018, ERROR_LOC(loc)); - } - STACK_PUSH(true, state); - } - + evaluate(state, planState); + + if (state->theResult.get() != NULL) + { + state->theResultIter = state->theResult->getIterator(); + state->theResultIter->open(); + } + } + catch (ZorbaException& e) + { + set_source( e, loc ); + throw; + } + catch (std::exception const& e) + { + throw XQUERY_EXCEPTION( + zerr::ZXQP0001_DYNAMIC_RUNTIME_ERROR, + ERROR_PARAMS(e.what()), + ERROR_LOC(loc)); + } + } + + if (!state->theResult.isNull() && //The external function returns zorba::ItemSequence_t(NULL) + state->theResultIter->isOpen()) //The iterator has not been skipped past its end + { + while (true) + { + try + { + if (!state->theResultIter->next(lOutsideItem)) + { + state->theResultIter->close(); + break; + } + } + catch (XQueryException& e) + { + set_source( e, loc ); + throw; + } + catch (std::exception const& e) + { + throw XQUERY_EXCEPTION( + zerr::ZXQP0001_DYNAMIC_RUNTIME_ERROR, + ERROR_PARAMS(e.what()), + ERROR_LOC(loc)); + } + + result = Unmarshaller::getInternalItem(lOutsideItem); + + if (theIsUpdating) + { + if (!result->isPul()) + throw XQUERY_EXCEPTION(err::XUDY0019, ERROR_LOC(loc)); + } + else + { + if (result->isPul()) + throw XQUERY_EXCEPTION(err::XUDY0018, ERROR_LOC(loc)); + } + STACK_PUSH(true, state); + } + } STACK_END (state); } +void ExtFunctionCallIterator::evaluate(ExtFunctionCallIteratorState* state, PlanState& planState) const +{ + if ( theFunction->isContextual() ) + { + ContextualExternalFunction const *const lFunction = + dynamic_cast<ContextualExternalFunction const*>( theFunction ); + ZORBA_ASSERT( lFunction ); + + StaticContextImpl lSctx(theModuleSctx, + planState.theQuery ? + planState.theQuery->getRegisteredDiagnosticHandlerNoSync(): + nullptr); + + DynamicContextImpl lDctx(nullptr, + planState.theGlobalDynCtx, + theModuleSctx); + + state->theResult = lFunction->evaluate( state->m_extArgs, &lSctx, &lDctx ); + } + else + { + NonContextualExternalFunction const *const lFunction = + dynamic_cast<NonContextualExternalFunction const*>( theFunction ); + ZORBA_ASSERT( lFunction ); + + state->theResult = lFunction->evaluate( state->m_extArgs ); + } + + state->theIsEvaluated = true; +} NARY_ACCEPT(ExtFunctionCallIterator); === modified file 'src/runtime/core/fncall_iterator.h' --- src/runtime/core/fncall_iterator.h 2014-02-12 02:25:45 +0000 +++ src/runtime/core/fncall_iterator.h 2014-04-15 18:58:26 +0000 @@ -215,6 +215,7 @@ std::vector<ItemSequence*> m_extArgs; ItemSequence_t theResult; Iterator_t theResultIter; + bool theIsEvaluated; ExtFunctionCallIteratorState(); @@ -265,7 +266,11 @@ bool nextImpl(store::Item_t& result, PlanState& planState) const; bool count(store::Item_t& result, PlanState& planState) const; + bool skip(int64_t count, PlanState &planState) const; + +private: + void evaluate(ExtFunctionCallIteratorState* state, PlanState& planState) const; }; } === added file 'test/rbkt/ExpQueryResults/zorba/file/file_read_text_lines-2.xml.res' --- test/rbkt/ExpQueryResults/zorba/file/file_read_text_lines-2.xml.res 1970-01-01 00:00:00 +0000 +++ test/rbkt/ExpQueryResults/zorba/file/file_read_text_lines-2.xml.res 2014-04-15 18:58:26 +0000 @@ -0,0 +1,1 @@ +<products> <product> \ No newline at end of file === added file 'test/rbkt/Queries/zorba/file/file_read_text_lines-2.xq' --- test/rbkt/Queries/zorba/file/file_read_text_lines-2.xq 1970-01-01 00:00:00 +0000 +++ test/rbkt/Queries/zorba/file/file_read_text_lines-2.xq 2014-04-15 18:58:26 +0000 @@ -0,0 +1,4 @@ +import module namespace file = "http://expath.org/ns/file"; + +file:read-text-lines(fn:resolve-uri("mydata.xml"))[1], +file:read-text-lines(fn:resolve-uri("mydata.xml"))[2]
-- Mailing list: https://launchpad.net/~zorba-coders Post to : zorba-coders@lists.launchpad.net Unsubscribe : https://launchpad.net/~zorba-coders More help : https://help.launchpad.net/ListHelp