/src/runtime/core/gflwor/window_iterator.cpp

https://github.com/cezarfx/zorba · C++ · 1108 lines · 676 code · 216 blank · 216 comment · 75 complexity · 78e8ea139857f45e5f9e995bb0b37cbb MD5 · raw file

  1. /*
  2. * Copyright 2006-2008 The FLWOR Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "stdafx.h"
  17. #include "system/globalenv.h"
  18. #include "runtime/core/gflwor/window_iterator.h"
  19. #include "runtime/core/gflwor/common.h"
  20. #include "runtime/core/var_iterators.h"
  21. #include "runtime/visitors/planiter_visitor.h"
  22. #include "store/api/store.h"
  23. #include "store/api/item_factory.h"
  24. namespace zorba
  25. {
  26. namespace flwor
  27. {
  28. SERIALIZABLE_CLASS_VERSIONS(StartClause)
  29. SERIALIZABLE_CLASS_VERSIONS(EndClause)
  30. SERIALIZABLE_CLASS_VERSIONS(WindowIterator)
  31. SERIALIZABLE_CLASS_VERSIONS(WindowVars)
  32. /////////////////////////////////////////////////////////////////////////////////
  33. // //
  34. // WindowVars //
  35. // //
  36. /////////////////////////////////////////////////////////////////////////////////
  37. /***************************************************************************//**
  38. ********************************************************************************/
  39. WindowVars::WindowVars()
  40. {
  41. }
  42. /***************************************************************************//**
  43. Constructor
  44. ********************************************************************************/
  45. WindowVars::WindowVars (
  46. const std::vector<PlanIter_t >& curVars,
  47. const std::vector<PlanIter_t >& prevVars,
  48. const std::vector<PlanIter_t >& nextVars,
  49. const std::vector<PlanIter_t >& posVars,
  50. const std::vector<PlanIter_t >& curOutVars,
  51. const std::vector<PlanIter_t >& prevOutVars,
  52. const std::vector<PlanIter_t >& nextOutVars,
  53. const std::vector<PlanIter_t >& posOutVars)
  54. :
  55. theCurVars(curVars),
  56. thePrevVars(prevVars),
  57. theNextVars(nextVars),
  58. thePosVars(posVars),
  59. theCurOuterVars(curOutVars),
  60. thePrevOuterVars(prevOutVars),
  61. theNextOuterVars(nextOutVars),
  62. thePosOuterVars(posOutVars)
  63. {
  64. }
  65. /***************************************************************************//**
  66. Destructor
  67. ********************************************************************************/
  68. WindowVars::~WindowVars()
  69. {
  70. }
  71. /***************************************************************************//**
  72. ********************************************************************************/
  73. void WindowVars::serialize(::zorba::serialization::Archiver& ar)
  74. {
  75. ar & theCurVars;
  76. ar & thePrevVars;
  77. ar & theNextVars;
  78. ar & thePosVars;
  79. ar & theCurOuterVars;
  80. ar & thePrevOuterVars;
  81. ar & theNextOuterVars;
  82. ar & thePosOuterVars;
  83. }
  84. /***************************************************************************//**
  85. ********************************************************************************/
  86. void WindowVars::accept(PlanIterVisitor& v, bool startClause) const
  87. {
  88. zstring varName;
  89. if (startClause)
  90. varName = "start-";
  91. else
  92. varName = "end-";
  93. if (!theCurVars.empty())
  94. {
  95. varName += "CurrentIn";
  96. v.beginVisitWinCondVariable(varName, theCurVars);
  97. v.endVisitWinCondVariable();
  98. }
  99. if (!thePrevVars.empty())
  100. {
  101. varName += "PrevIn";
  102. v.beginVisitWinCondVariable(varName, thePrevVars);
  103. v.endVisitWinCondVariable();
  104. }
  105. if (!theNextVars.empty())
  106. {
  107. varName += "NextIn";
  108. v.beginVisitWinCondVariable(varName, theNextVars);
  109. v.endVisitWinCondVariable();
  110. }
  111. if (!thePosVars.empty())
  112. {
  113. varName += "PosIn";
  114. v.beginVisitWinCondVariable(varName, thePosVars);
  115. v.endVisitWinCondVariable();
  116. }
  117. if (!theCurOuterVars.empty())
  118. {
  119. varName += "CurrentOut";
  120. v.beginVisitWinCondVariable(varName, theCurOuterVars);
  121. v.endVisitWinCondVariable();
  122. }
  123. if (!thePrevOuterVars.empty())
  124. {
  125. varName += "PrevOut";
  126. v.beginVisitWinCondVariable(varName, thePrevOuterVars);
  127. v.endVisitWinCondVariable();
  128. }
  129. if (!theNextOuterVars.empty())
  130. {
  131. varName += "NextOut";
  132. v.beginVisitWinCondVariable(varName, theNextOuterVars);
  133. v.endVisitWinCondVariable();
  134. }
  135. if (!thePosOuterVars.empty())
  136. {
  137. varName += "PosOut";
  138. v.beginVisitWinCondVariable(varName, thePosOuterVars);
  139. v.endVisitWinCondVariable();
  140. }
  141. }
  142. /*******************************************************************************
  143. Binds the variables inside the window clause.
  144. @param planState The PlanState
  145. @param aInputSeq The underlying input sequence
  146. @param aPosition The position of the current item within the input sequence
  147. (counting starts with 1).
  148. ********************************************************************************/
  149. void WindowVars::bindIntern(
  150. PlanState& planState,
  151. const store::TempSeq_t& inputSeq,
  152. const ulong pos) const
  153. {
  154. store::Item_t item;
  155. if (!theCurVars.empty())
  156. {
  157. inputSeq->getItem(xs_integer(pos), item);
  158. bindVariables(item, theCurVars, planState);
  159. }
  160. if (!thePrevVars.empty())
  161. {
  162. if (pos > 1)
  163. inputSeq->getItem(xs_integer(pos - 1), item);
  164. else
  165. item = NULL;
  166. bindVariables(item, thePrevVars, planState);
  167. }
  168. if (!theNextVars.empty())
  169. {
  170. inputSeq->getItem(xs_integer(pos + 1), item);
  171. bindVariables(item, theNextVars, planState);
  172. }
  173. if (!thePosVars.empty())
  174. {
  175. GENV_ITEMFACTORY->createInteger(item, xs_integer(pos));
  176. bindVariables(item, thePosVars, planState);
  177. }
  178. }
  179. /*******************************************************************************
  180. Binds the variables outside the window clause.
  181. @param planState The PlanState
  182. @param inputSeq The underlying input sequence
  183. @param pos The position of the current item within the input sequence
  184. (counting starts with 1).
  185. ********************************************************************************/
  186. void WindowVars::bindExtern(
  187. PlanState& planState,
  188. const store::TempSeq_t& inputSeq,
  189. const ulong pos) const
  190. {
  191. store::Item_t item;
  192. if (!theCurOuterVars.empty())
  193. {
  194. inputSeq->getItem(xs_integer(pos), item);
  195. bindVariables(item, theCurOuterVars, planState);
  196. }
  197. if (!thePrevOuterVars.empty())
  198. {
  199. if (pos > 1)
  200. inputSeq->getItem(xs_integer(pos - 1), item);
  201. else
  202. item = NULL;
  203. bindVariables(item, thePrevOuterVars, planState);
  204. }
  205. if (!theNextOuterVars.empty())
  206. {
  207. inputSeq->getItem(xs_integer(pos + 1), item);
  208. bindVariables(item, theNextOuterVars, planState);
  209. }
  210. if (!thePosOuterVars.empty())
  211. {
  212. GENV_ITEMFACTORY->createInteger(item, Integer(pos));
  213. bindVariables(item, thePosOuterVars, planState);
  214. }
  215. }
  216. /////////////////////////////////////////////////////////////////////////////////
  217. // //
  218. // StartClause //
  219. // //
  220. /////////////////////////////////////////////////////////////////////////////////
  221. /*******************************************************************************
  222. ********************************************************************************/
  223. StartClause::StartClause(
  224. PlanIter_t aStartClauseIter,
  225. WindowVars& aWindowVars)
  226. :
  227. theStartClauseIter(aStartClauseIter),
  228. theWindowVars(aWindowVars)
  229. {
  230. }
  231. /***************************************************************************//**
  232. ********************************************************************************/
  233. StartClause::~StartClause()
  234. {
  235. }
  236. void StartClause::serialize(::zorba::serialization::Archiver& ar)
  237. {
  238. ar & theStartClauseIter;
  239. ar & theWindowVars;
  240. }
  241. /***************************************************************************//**
  242. ********************************************************************************/
  243. uint32_t StartClause::getStateSizeOfSubtree() const
  244. {
  245. return theStartClauseIter->getStateSizeOfSubtree();
  246. }
  247. /***************************************************************************//**
  248. ********************************************************************************/
  249. void StartClause::accept(PlanIterVisitor& v) const
  250. {
  251. theWindowVars.accept(v, true);
  252. theStartClauseIter->accept(v);
  253. }
  254. /***************************************************************************//**
  255. ********************************************************************************/
  256. void StartClause::open(PlanState& planState, uint32_t& aOffset) const
  257. {
  258. theStartClauseIter->open(planState, aOffset);
  259. }
  260. /***************************************************************************//**
  261. ********************************************************************************/
  262. void StartClause::reset(PlanState& planState) const
  263. {
  264. theStartClauseIter->reset(planState);
  265. }
  266. /***************************************************************************//**
  267. ********************************************************************************/
  268. void StartClause::close(PlanState& planState) const
  269. {
  270. theStartClauseIter->close(planState);
  271. }
  272. /***************************************************************************//**
  273. Evaluate the start condition expr on the item that is pointed to by the given
  274. position within the temp sequence that materializes the result of the domain
  275. expr.
  276. ********************************************************************************/
  277. bool StartClause::evaluate(
  278. PlanState& planState,
  279. const store::TempSeq_t& inputSeq,
  280. const ulong pos) const
  281. {
  282. theWindowVars.bindIntern(planState, inputSeq, pos);
  283. return evalToBool(theStartClauseIter, planState);
  284. }
  285. /***************************************************************************//**
  286. Bind the references to the external start-condition variables to the values
  287. corresponding to the item that is pointed to by the given position within
  288. the temp sequence that materializes the result of the domain expr.
  289. ********************************************************************************/
  290. void StartClause::bindExtern(
  291. PlanState& planState,
  292. const store::TempSeq_t& inputSeq,
  293. const ulong pos) const
  294. {
  295. theWindowVars.bindExtern(planState, inputSeq, pos);
  296. }
  297. /***************************************************************************//**
  298. ********************************************************************************/
  299. void StartClause::bindIntern(
  300. PlanState& planState,
  301. const store::TempSeq_t& inputSeq,
  302. const ulong pos) const
  303. {
  304. theWindowVars.bindIntern(planState, inputSeq, pos);
  305. }
  306. /////////////////////////////////////////////////////////////////////////////////
  307. // //
  308. // EndClause //
  309. // //
  310. /////////////////////////////////////////////////////////////////////////////////
  311. /***************************************************************************//**
  312. If the EndClause is missing in the case of a tumbling window, this constructor
  313. should be used.
  314. ********************************************************************************/
  315. EndClause::EndClause()
  316. :
  317. theEndClauseIter(NULL),
  318. theOnlyEnd(false),
  319. theHasEndClause(false)
  320. {
  321. }
  322. /***************************************************************************//**
  323. ********************************************************************************/
  324. EndClause::EndClause(
  325. PlanIter_t aEndClauseIter,
  326. WindowVars& aWindowVars,
  327. bool aOnlyEnd)
  328. :
  329. theEndClauseIter(aEndClauseIter),
  330. theWindowVars(aWindowVars),
  331. theOnlyEnd(aOnlyEnd),
  332. theHasEndClause(true)
  333. {
  334. }
  335. /***************************************************************************//**
  336. ********************************************************************************/
  337. EndClause::~EndClause()
  338. {
  339. }
  340. /***************************************************************************//**
  341. ********************************************************************************/
  342. void EndClause::serialize(::zorba::serialization::Archiver& ar)
  343. {
  344. ar & theEndClauseIter;
  345. ar & theWindowVars;
  346. ar & theOnlyEnd;
  347. ar & theHasEndClause;
  348. }
  349. /***************************************************************************//**
  350. ********************************************************************************/
  351. uint32_t EndClause::getStateSizeOfSubtree() const
  352. {
  353. if (theHasEndClause)
  354. return theEndClauseIter->getStateSizeOfSubtree();
  355. else
  356. return 0;
  357. }
  358. /***************************************************************************//**
  359. ********************************************************************************/
  360. void EndClause::accept(PlanIterVisitor& v) const
  361. {
  362. //TODO more output
  363. if (theHasEndClause)
  364. {
  365. theWindowVars.accept(v, false);
  366. theEndClauseIter->accept(v);
  367. }
  368. }
  369. /***************************************************************************//**
  370. ********************************************************************************/
  371. void EndClause::open(PlanState& planState, uint32_t& aOffset) const
  372. {
  373. if (theHasEndClause)
  374. theEndClauseIter->open(planState, aOffset);
  375. }
  376. /***************************************************************************//**
  377. ********************************************************************************/
  378. void EndClause::reset(PlanState& planState) const
  379. {
  380. if (theHasEndClause)
  381. theEndClauseIter->reset(planState);
  382. }
  383. /***************************************************************************//**
  384. ********************************************************************************/
  385. void EndClause::close(PlanState& planState) const
  386. {
  387. if (theHasEndClause)
  388. theEndClauseIter->close(planState);
  389. }
  390. /***************************************************************************//**
  391. ********************************************************************************/
  392. bool EndClause::evaluate(
  393. PlanState& planState,
  394. const store::TempSeq_t& inputSeq,
  395. const ulong pos) const
  396. {
  397. theWindowVars.bindIntern(planState, inputSeq, pos);
  398. return evalToBool(theEndClauseIter, planState);
  399. }
  400. /***************************************************************************//**
  401. ********************************************************************************/
  402. void EndClause::bindIntern(
  403. PlanState& planState,
  404. const store::TempSeq_t& inputSeq,
  405. const ulong pos) const
  406. {
  407. theWindowVars.bindIntern(planState, inputSeq, pos);
  408. }
  409. /***************************************************************************//**
  410. ********************************************************************************/
  411. void EndClause::bindExtern(
  412. PlanState& planState,
  413. const store::TempSeq_t& inputSeq,
  414. const ulong pos) const
  415. {
  416. theWindowVars.bindExtern(planState, inputSeq, pos);
  417. }
  418. /////////////////////////////////////////////////////////////////////////////////
  419. // //
  420. // WindowDef //
  421. // //
  422. /////////////////////////////////////////////////////////////////////////////////
  423. WindowDef::~WindowDef()
  424. {
  425. }
  426. WindowDef::WindowDef(ulong aStartPos) : theStartPos(aStartPos), theEndPos(0)
  427. {
  428. }
  429. /////////////////////////////////////////////////////////////////////////////////
  430. // //
  431. // WindowState //
  432. // //
  433. /////////////////////////////////////////////////////////////////////////////////
  434. WindowState::WindowState() : theDomainSeq (NULL) , theCurInputPos(1)
  435. {
  436. }
  437. WindowState::~WindowState()
  438. {
  439. }
  440. void WindowState::init(PlanState& aState)
  441. {
  442. PlanIteratorState::init(aState);
  443. theCurInputPos = 1;
  444. theDomainSeq = NULL;
  445. }
  446. void WindowState::reset(PlanState& planState)
  447. {
  448. PlanIteratorState::reset(planState);
  449. theCurInputPos = 1;
  450. theDomainSeq = NULL;
  451. theOpenWindows.clear();
  452. }
  453. /////////////////////////////////////////////////////////////////////////////////
  454. // //
  455. // WindowIterator //
  456. // //
  457. /////////////////////////////////////////////////////////////////////////////////
  458. const ulong WindowIterator::MAX_HISTORY = 2147483647; //TODO should be set platform dependent, but somebody hat comment out everything in platform.h!
  459. /***************************************************************************//**
  460. ********************************************************************************/
  461. WindowIterator::WindowIterator(
  462. static_context* sctx,
  463. const QueryLoc& loc,
  464. WindowType windowType,
  465. PlanIter_t tupleIter,
  466. PlanIter_t domainIter,
  467. PlanIter_t treatIter,
  468. store::Item* varName,
  469. const std::vector<PlanIter_t>& varRefs,
  470. StartClause& startClause,
  471. EndClause& endClause,
  472. bool lazyEval,
  473. ulong maxNeededHistory)
  474. :
  475. PlanIterator(sctx, loc),
  476. theWindowType(windowType),
  477. theTupleIter(tupleIter),
  478. theInputIter(domainIter),
  479. theTreatIter(treatIter),
  480. theVarName(varName),
  481. theStartClause(startClause),
  482. theEndClause(endClause),
  483. theLazyEval(lazyEval),
  484. theMaxNeededHistory(maxNeededHistory)
  485. {
  486. castIterVector<LetVarIterator>(theVarRefs, varRefs);
  487. if (theWindowType == TUMBLING)
  488. theMaxNeededHistory = 1;
  489. }
  490. /***************************************************************************//**
  491. ********************************************************************************/
  492. WindowIterator::~WindowIterator()
  493. {
  494. }
  495. /***************************************************************************//**
  496. ********************************************************************************/
  497. void WindowIterator::serialize(::zorba::serialization::Archiver& ar)
  498. {
  499. serialize_baseclass(ar, (PlanIterator*)this);
  500. SERIALIZE_ENUM(WindowType, theWindowType);
  501. ar & theTupleIter;
  502. ar & theInputIter;
  503. ar & theTreatIter;
  504. ar & theVarName;
  505. ar & theVarRefs;
  506. ar & theStartClause;
  507. ar & theEndClause;
  508. ar & theLazyEval;
  509. ar & theMaxNeededHistory;
  510. }
  511. /***************************************************************************//**
  512. ********************************************************************************/
  513. zstring WindowIterator::getNameAsString() const {
  514. return "WindowIterator";
  515. }
  516. uint32_t WindowIterator::getStateSize() const
  517. {
  518. return StateTraitsImpl<WindowState>::getStateSize();
  519. }
  520. /***************************************************************************//**
  521. ********************************************************************************/
  522. uint32_t WindowIterator::getStateSizeOfSubtree() const
  523. {
  524. int32_t size = this->getStateSize();
  525. size += theTupleIter->getStateSizeOfSubtree();
  526. size += theInputIter->getStateSizeOfSubtree();
  527. size += theStartClause.getStateSizeOfSubtree();
  528. size += theEndClause.getStateSizeOfSubtree();
  529. if (theTreatIter)
  530. size += theTreatIter->getStateSizeOfSubtree();
  531. return size;
  532. }
  533. /***************************************************************************//**
  534. ********************************************************************************/
  535. void WindowIterator::accept(PlanIterVisitor& v) const
  536. {
  537. v.beginVisit(*this);
  538. v.beginVisitWindowVariable(theVarName->getStringValue().str(), theVarRefs);
  539. theInputIter->accept(v);
  540. v.endVisitWindowVariable();
  541. theStartClause.accept(v);
  542. theEndClause.accept(v);
  543. theTupleIter->accept(v);
  544. if (theTreatIter)
  545. theTreatIter->accept(v);
  546. v.endVisit(*this);
  547. }
  548. /***************************************************************************//**
  549. ********************************************************************************/
  550. void WindowIterator::openImpl(PlanState& planState, uint32_t& offset)
  551. {
  552. StateTraitsImpl<WindowState>::createState(planState, theStateOffset, offset);
  553. theTupleIter->open(planState, offset);
  554. theInputIter->open(planState, offset);
  555. if (theTreatIter)
  556. theTreatIter->open(planState, offset);
  557. theStartClause.open(planState, offset);
  558. theEndClause.open(planState, offset);
  559. }
  560. /***************************************************************************//**
  561. ********************************************************************************/
  562. void WindowIterator::resetImpl(PlanState& planState) const
  563. {
  564. WindowState* lState = StateTraitsImpl<WindowState>::getState(planState,
  565. theStateOffset);
  566. lState->reset(planState);
  567. theTupleIter->reset(planState);
  568. theInputIter->reset(planState);
  569. theStartClause.reset(planState);
  570. theEndClause.reset(planState);
  571. if (theTreatIter)
  572. theTreatIter->reset(planState);
  573. }
  574. /***************************************************************************//**
  575. ********************************************************************************/
  576. void WindowIterator::closeImpl(PlanState& planState)
  577. {
  578. theTupleIter->close(planState);
  579. theInputIter->close(planState);
  580. theStartClause.close(planState);
  581. theEndClause.close(planState);
  582. if (theTreatIter)
  583. theTreatIter->close(planState);
  584. StateTraitsImpl<WindowState>::destroyState(planState, theStateOffset);
  585. }
  586. /***************************************************************************//**
  587. Bind the window var to the items between the given starting and ending items
  588. of the domain sequence.
  589. ********************************************************************************/
  590. void WindowIterator::bindVariable(
  591. PlanState& planState,
  592. store::TempSeq_t& inputSeq,
  593. ulong startPos,
  594. ulong endPos) const
  595. {
  596. xs_integer const lStartPos(startPos);
  597. xs_integer const lEndPos(endPos);
  598. for (std::vector<LetVarIter_t>::const_iterator varIter = theVarRefs.begin();
  599. varIter != theVarRefs.end();
  600. ++varIter)
  601. {
  602. (*varIter)->bind(inputSeq, planState, lStartPos, lEndPos);
  603. }
  604. }
  605. /***************************************************************************//**
  606. The theMaxNeededHistory has to be determined by the compiler e.g. for
  607. $seq[$startPos - 4] cases
  608. ********************************************************************************/
  609. void WindowIterator::doGarbageCollection(WindowState* state) const
  610. {
  611. if (theMaxNeededHistory != MAX_HISTORY)
  612. {
  613. if (state->theOpenWindows.empty())
  614. {
  615. if (state->theCurInputPos > theMaxNeededHistory)
  616. state->theDomainSeq->
  617. purgeUpTo(xs_integer(state->theCurInputPos - theMaxNeededHistory));
  618. }
  619. else
  620. {
  621. int64_t purgeTo =
  622. state->theOpenWindows.front().theStartPos - theMaxNeededHistory;
  623. if (purgeTo > 0)
  624. state->theDomainSeq->purgeUpTo(xs_integer(purgeTo));
  625. }
  626. }
  627. }
  628. /***************************************************************************//**
  629. ********************************************************************************/
  630. bool WindowIterator::nextImpl(store::Item_t& aResult, PlanState& planState) const
  631. {
  632. store::Iterator_t iterator;
  633. WindowState* state;
  634. DEFAULT_STACK_INIT(WindowState, state, planState);
  635. // Pull the next tuple from the input stream
  636. while (consumeNext(aResult, theTupleIter, planState))
  637. {
  638. // Create the temp sequence where to materialize the result of the domain
  639. // expr (lazily if theLazyEval flag is true).
  640. iterator = new PlanIteratorWrapper(theInputIter, planState);
  641. state->theDomainSeq = GENV_STORE.createTempSeq(iterator, theLazyEval);
  642. // Its clever to switch quite early to avoid a lot of if-else statements
  643. if (theWindowType == WindowIterator::SLIDING)
  644. {
  645. // Get the next item from the domain sequence
  646. // TODO: can the xs_integer be hoisted?
  647. while (state->theDomainSeq->containsItem(xs_integer(state->theCurInputPos)))
  648. {
  649. // If the current item satisfies the start condition, create a candidate
  650. // window starting at the current domain item.
  651. if (theStartClause.evaluate(planState,
  652. state->theDomainSeq,
  653. state->theCurInputPos))
  654. {
  655. state->theOpenWindows.push_back(WindowDef(state->theCurInputPos));
  656. }
  657. // For each candidate window, check if the current domain item satisfies
  658. // the end condition. Notice that before evaluating the end condition
  659. // expr, we must rebind the internal vars of the start condition, because
  660. // those varaibles may be refrenced in the end cond expr.
  661. state->theCurWindow = state->theOpenWindows.begin();
  662. while ( state->theCurWindow != state->theOpenWindows.end() )
  663. {
  664. if (state->theCurWindow->theEndPos == 0)
  665. {
  666. theStartClause.bindIntern(planState,
  667. state->theDomainSeq,
  668. state->theCurWindow->theStartPos);
  669. ulong lCurPos = state->theCurInputPos;
  670. if ( theEndClause.evaluate(planState,
  671. state->theDomainSeq,
  672. lCurPos))
  673. {
  674. state->theCurWindow->theEndPos = lCurPos;
  675. }
  676. }
  677. ++state->theCurWindow;
  678. }
  679. // Try to return closed windows to the consumer iterator. Notice that
  680. // windows must be sorted according to the position of their starting
  681. // items in the domain sequence. So, we can return a closed window only
  682. // if it appears as the first window in state->theOpenWindows.
  683. state->theCurWindow = state->theOpenWindows.begin();
  684. while (!state->theOpenWindows.empty())
  685. {
  686. if (state->theCurWindow->theEndPos != 0)
  687. {
  688. // The current window is closed and its starting item is before the
  689. // stating items of all other windows (open or closed) in the domain
  690. // sequence. So, (a) bind the window var and the external vars of
  691. // the start and end conditions, (b) remove the window from the set
  692. // of candidate windows, (c) purge from the domain temp seq any item
  693. // that we know for sure they will not be needed in subsequent
  694. // evaluations of the start and/or end conditions, and (d) return to
  695. // the caller a new tuple that consists of the current input tuple
  696. // augmented with one column per variable that was bound in this step.
  697. theStartClause.bindExtern(planState,
  698. state->theDomainSeq,
  699. state->theCurWindow->theStartPos);
  700. theEndClause.bindExtern(planState,
  701. state->theDomainSeq,
  702. state->theCurWindow->theEndPos);
  703. bindVariable(planState,
  704. state->theDomainSeq,
  705. state->theCurWindow->theStartPos,
  706. state->theCurWindow->theEndPos);
  707. state->theCurWindow = state->theOpenWindows.erase(state->theCurWindow);
  708. //doGarbageCollection(state);
  709. if (theTreatIter)
  710. {
  711. store::Item_t tmp;
  712. while (consumeNext(tmp, theTreatIter, planState))
  713. {
  714. ;
  715. }
  716. theTreatIter->reset(planState);
  717. }
  718. STACK_PUSH(true, state);
  719. }
  720. else
  721. {
  722. break;
  723. }
  724. }
  725. ++state->theCurInputPos;
  726. }
  727. }
  728. else //Tumpling window
  729. {
  730. // Doing this switch now also avoids further overhad
  731. if (theEndClause.theHasEndClause)
  732. {
  733. while (state->theDomainSeq->containsItem(xs_integer(state->theCurInputPos)))
  734. {
  735. if (state->theOpenWindows.empty() &&
  736. theStartClause.evaluate(planState,
  737. state->theDomainSeq,
  738. state->theCurInputPos))
  739. {
  740. theStartClause.bindExtern(planState,
  741. state->theDomainSeq,
  742. state->theCurInputPos);
  743. state->theOpenWindows.push_back(state->theCurInputPos);
  744. }
  745. if ( !state->theOpenWindows.empty() &&
  746. theEndClause.evaluate(planState,
  747. state->theDomainSeq,
  748. state->theCurInputPos))
  749. {
  750. theEndClause.bindExtern(planState,
  751. state->theDomainSeq,
  752. state->theCurInputPos);
  753. bindVariable(planState,
  754. state->theDomainSeq,
  755. state->theOpenWindows[0].theStartPos,
  756. state->theCurInputPos);
  757. state->theOpenWindows.pop_back();
  758. assert(state->theOpenWindows.empty());
  759. if (theTreatIter)
  760. {
  761. store::Item_t tmp;
  762. while (consumeNext(tmp, theTreatIter, planState))
  763. {
  764. ;
  765. }
  766. theTreatIter->reset(planState);
  767. }
  768. STACK_PUSH(true, state);
  769. doGarbageCollection(state);
  770. }
  771. ++state->theCurInputPos;
  772. }
  773. }
  774. else
  775. {
  776. while (state->theDomainSeq->containsItem(xs_integer(state->theCurInputPos)))
  777. {
  778. if (theStartClause.evaluate(planState,
  779. state->theDomainSeq,
  780. state->theCurInputPos))
  781. {
  782. if (!state->theOpenWindows.empty())
  783. {
  784. //In no case there should be more than 1 position inside
  785. assert(state->theOpenWindows.size() == 1);
  786. theStartClause.bindExtern(planState,
  787. state->theDomainSeq,
  788. state->theOpenWindows[0].theStartPos);
  789. bindVariable(planState,
  790. state->theDomainSeq,
  791. state->theOpenWindows[0].theStartPos,
  792. state->theCurInputPos - 1);
  793. state->theOpenWindows.pop_back();
  794. assert(state->theOpenWindows.empty());
  795. if (theTreatIter)
  796. {
  797. store::Item_t tmp;
  798. while (consumeNext(tmp, theTreatIter, planState))
  799. {
  800. ;
  801. }
  802. theTreatIter->reset(planState);
  803. }
  804. STACK_PUSH(true, state);
  805. --state->theCurInputPos;
  806. doGarbageCollection(state);
  807. ++state->theCurInputPos;
  808. }
  809. state->theOpenWindows.push_back(state->theCurInputPos);
  810. }
  811. ++state->theCurInputPos;
  812. }
  813. }
  814. }
  815. // Check if we have open and/or closed windows
  816. state->theCurWindow = state->theOpenWindows.begin();
  817. while (state->theCurWindow != state->theOpenWindows.end())
  818. {
  819. if (!theEndClause.theOnlyEnd || state->theCurWindow->theEndPos != 0)
  820. {
  821. if (state->theCurWindow->theEndPos == 0)
  822. state->theCurWindow->theEndPos = state->theCurInputPos - 1;
  823. bindVariable(planState,
  824. state->theDomainSeq,
  825. state->theOpenWindows[0].theStartPos,
  826. state->theCurWindow->theEndPos);
  827. theStartClause.bindExtern(planState,
  828. state->theDomainSeq,
  829. state->theOpenWindows[0].theStartPos);
  830. theEndClause.bindExtern(planState,
  831. state->theDomainSeq,
  832. state->theCurWindow->theEndPos);
  833. state->theCurWindow = state->theOpenWindows.erase(state->theCurWindow);
  834. if (theTreatIter)
  835. {
  836. store::Item_t tmp;
  837. while (consumeNext(tmp, theTreatIter, planState))
  838. {
  839. ;
  840. }
  841. theTreatIter->reset(planState);
  842. }
  843. STACK_PUSH(true, state);
  844. }
  845. else
  846. {
  847. ++state->theCurWindow;
  848. }
  849. }
  850. theInputIter->reset(planState);
  851. state->reset(planState);
  852. }
  853. STACK_PUSH(false, state);
  854. STACK_END(state);
  855. }
  856. } //Namespace flwor
  857. }//Namespace zorba
  858. /* vim:set et sw=2 ts=2: */