zorba-coders team mailing list archive
-
zorba-coders team
-
Mailing list archive
-
Message #24224
[Merge] lp:~zorba-coders/zorba/skip-items into lp:zorba
Nicolae Brinza has proposed merging lp:~zorba-coders/zorba/skip-items into lp:zorba.
Commit message:
Implemented the Skip-items facility
Requested reviews:
Nicolae Brinza (nbrinza)
For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/skip-items/+merge/174723
Implemented the Skip-items facility
--
https://code.launchpad.net/~zorba-coders/zorba/skip-items/+merge/174723
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'src/functions/func_sequences_impl.cpp'
--- src/functions/func_sequences_impl.cpp 2013-05-14 05:21:11 +0000
+++ src/functions/func_sequences_impl.cpp 2013-07-15 10:38:33 +0000
@@ -43,127 +43,6 @@
/*******************************************************************************
-
-********************************************************************************/
-bool rewriteSubsequenceCollection(
- static_context* aSctx,
- const QueryLoc& aLoc,
- std::vector<PlanIter_t>& aArgs,
- bool aIsIntSubsequence)
-{
- ZorbaCollectionIterator* collIter =
- dynamic_cast<ZorbaCollectionIterator*>(aArgs[0].getp());
- assert(collIter);
-
- std::vector<PlanIter_t>& lCollectionArgs = collIter->getChildren();
-
- SingletonIterator* lPosIter = dynamic_cast<SingletonIterator*>(aArgs[1].getp());
- if (lPosIter == NULL)
- {
- return false;
- }
-
- xs_long pos;
- const store::Item_t& lPosItem = lPosIter->getValue();
-
- try
- {
- if (aIsIntSubsequence)
- {
- pos = lPosItem->getLongValue();
- }
- else
- {
- xs_double dpos = lPosItem->getDoubleValue().round();
- xs_integer ipos(dpos.getNumber());
- pos = to_xs_long(ipos);
- }
- }
- catch (std::exception const&)
- {
- return false;
- }
-
- if (pos <= 1)
- {
- // if the start position is less than 1 we can't push this down into
- // the collection skip parameter because the result won't be equivalent.
- return false;
- }
-
- // prepare helper
- store::Item_t lItemOne;
- GENV_ITEMFACTORY->createInteger(lItemOne, Integer(1));
-
- int lNumCollArgs = lCollectionArgs.size();
- if (lNumCollArgs == 1)
- {
- // argument is of type collection(qname)
- // simply move the (pos-1) of subsequence into the skip of
- // collection function
- // subsequence(collection(qname), 10, 20)
- // -> subsequence(collection(qname, 10-1), 1, 20)
- PlanIter_t& lNewCollSkipIter = aArgs[1];
- PlanIter_t lOneIter = new SingletonIterator(aSctx, aLoc, lItemOne);
-
- lCollectionArgs.push_back(
- new NumArithIterator<zorba::SubtractOperation>(aSctx,
- collIter->getLocation(),
- lNewCollSkipIter,
- lOneIter)
- );
- }
- else if (lNumCollArgs <= 3 && lNumCollArgs != 0)
- {
- // argument is of type collection(qname,skip) or
- // collection(qname,start_uri,skip)
- int lSkipPosition = 1;
- if (lNumCollArgs == 3)
- {
- // collection function with start reference -> skip is the 3rd param
- lSkipPosition = 2;
- }
-
- // add position-1 of subsequence to collection skip
- // subsequence(collection(qname, 10), 10, 20)
- // -> subsequence(collection(qname, 10+10-1), 10, 20)
- PlanIter_t& lOldCollSkipIter = lCollectionArgs[lSkipPosition];
- PlanIter_t lOneIter = new SingletonIterator (aSctx, aLoc, lItemOne);
- PlanIter_t& lSubseqPosIter = aArgs[1];
-
- PlanIter_t lCollSkipAdditionIter =
- new NumArithIterator<zorba::SubtractOperation>(aSctx,
- collIter->getLocation(),
- lSubseqPosIter,
- lOneIter);
- lCollectionArgs[lSkipPosition] =
- new NumArithIterator<zorba::AddOperation>(aSctx,
- collIter->getLocation(),
- lOldCollSkipIter,
- lCollSkipAdditionIter);
- }
- else
- {
- // no collection function with 0 or >3 params
- assert(false);
- }
-
- aArgs[0] = new ZorbaCollectionIterator(aSctx,
- collIter->getLocation(),
- lCollectionArgs,
- collIter->isDynamic());
-
- // after pushing the position param down we need to rewrite the actual
- // position to 1:
- // subsequence(collection(qname, 10+10-1), 10, 20)
- // -> subsequence(collection(qname, 10+10-1), 1, 20)
- aArgs[1] = new SingletonIterator(aSctx, aLoc, lItemOne);
-
- return true;
-}
-
-
-/*******************************************************************************
********************************************************************************/
xqtref_t fn_unordered::getReturnType(const fo_expr* caller) const
{
@@ -573,8 +452,7 @@
const QueryLoc& aLoc,
std::vector<PlanIter_t>& aArgs,
expr& aAnn) const
-{
- const std::type_info& lFirstArgType = typeid(*aArgs[0]);
+{
fo_expr& subseqExpr = static_cast<fo_expr&>(aAnn);
const expr* inputExpr = subseqExpr.get_arg(0);
const expr* posExpr = subseqExpr.get_arg(1);
@@ -619,23 +497,8 @@
return aArgs[0];
}
}
- else if (typeid(ZorbaCollectionIterator) == lFirstArgType)
- {
- // push down position param into collection skip if possible
- if (rewriteSubsequenceCollection(aSctx, aLoc, aArgs, false /*no int*/))
- {
- // we have rewritten the subsequence to start at the beginning.
- // if there is no length param we can remove the entire
- // subsequence function
- // subsequence(collection(qname, 10), 1) -> collection(qname, 10)
- if (aArgs.size() == 2)
- {
- return aArgs[0];
- }
- }
- }
- done:
+done:
return new FnSubsequenceIterator(aSctx, aLoc, aArgs);
}
@@ -736,23 +599,8 @@
return aArgs[0];
}
}
- else if (typeid(ZorbaCollectionIterator) == lFirstArgType)
- {
- // push down position param into collection skip if possible
- if (rewriteSubsequenceCollection(aSctx, aLoc, aArgs, true /*flag int*/))
- {
- // we have rewritten the subsequence to start from the beginning.
- // if there is no length param we can remove the entire
- // subsequence function
- // subsequence(collection(qname, 10), 1) -> collection(qname, 10)
- if (aArgs.size() == 2)
- {
- return aArgs[0];
- }
- }
- }
- done:
+done:
return new SubsequenceIntIterator(aSctx, aLoc, aArgs);
}
=== modified file 'src/runtime/base/plan_iterator.cpp'
--- src/runtime/base/plan_iterator.cpp 2013-05-28 18:20:54 +0000
+++ src/runtime/base/plan_iterator.cpp 2013-07-15 10:38:33 +0000
@@ -31,6 +31,10 @@
#include "diagnostics/util_macros.h"
+#ifndef NDEBUG
+#include "system/properties.h"
+#endif
+
namespace zorba
{
@@ -180,6 +184,18 @@
}
+bool PlanIterator::skip(int64_t count, PlanState& planState) const
+{
+ bool have_more_items = true;
+ store::Item_t item;
+
+ while (count-- > 0 && (have_more_items = consumeNext(item, this, planState)))
+ ;
+
+ return have_more_items;
+}
+
+
#ifndef NDEBUG
bool PlanIterator::consumeNext(
store::Item_t& result,
@@ -196,7 +212,12 @@
if (planState.theCompilerCB->theConfig.print_item_flow)
{
- std::cout << "next (" << iter << " = " << typeid (*iter).name()
+ if (Properties::instance()->stableIteratorIds())
+ std::cout << "next (" << iter->getId();
+ else
+ std::cout << "next (" << iter;
+
+ std::cout << " = " << typeid (*iter).name()
<< ") -> "
<< "status: " << status << " -> "
<< ((status && result != NULL) ? result->show().c_str() : "null")
=== modified file 'src/runtime/base/plan_iterator.h'
--- src/runtime/base/plan_iterator.h 2013-05-28 18:20:54 +0000
+++ src/runtime/base/plan_iterator.h 2013-07-15 10:38:33 +0000
@@ -401,6 +401,19 @@
virtual bool count(store::Item_t& result, PlanState& planState) const;
/**
+ * Skip a number of items from the Plan's sequence. Classes can overwrite
+ * this functions to optimize the skipping by jumping directly to the
+ * desired position in the sequence.
+ *
+ * Returns true if the entire sequence has been consumed, false otherwise.
+ *
+ * @param count the number of items to be skipped
+ * @param planState the state plan
+ *
+ */
+ virtual bool skip(int64_t count, PlanState &planState) const;
+
+ /**
* Produce the next item and return it to the caller. Implicitly, the first
* call of 'producNext' initializes the iterator and allocates resources
* (main memory, file descriptors, etc.).
=== modified file 'src/runtime/collections/collections_impl.cpp'
--- src/runtime/collections/collections_impl.cpp 2013-05-02 18:34:27 +0000
+++ src/runtime/collections/collections_impl.cpp 2013-07-15 10:38:33 +0000
@@ -277,17 +277,13 @@
}
-bool ZorbaCollectionIterator::nextImpl(
- store::Item_t& result,
- PlanState& planState) const
+void ZorbaCollectionIterator::initCollection(PlanState& planState, int64_t skipCount) const
{
store::Item_t name;
+ xs_integer lSkip;
store::Collection_t collection;
- xs_integer lSkip;
- zstring lStart;
- ZorbaCollectionIteratorState* state;
- DEFAULT_STACK_INIT(ZorbaCollectionIteratorState, state, planState);
+ ZorbaCollectionIteratorState* state = StateTraitsImpl<ZorbaCollectionIteratorState>::getState(planState, theStateOffset);
consumeNext(name, theChildren[0].getp(), planState);
@@ -299,12 +295,13 @@
}
else
{
+ zstring lStart;
bool lRefPassed = theChildren.size() >= 3;
-
+
// read positional skip parameter
store::Item_t lSkipItem;
consumeNext(lSkipItem, theChildren[(lRefPassed ? 2 : 1)].getp(), planState);
- lSkip = lSkipItem->getIntegerValue();
+ lSkip = lSkipItem->getIntegerValue();
// negative skip is not allowed
if (lSkip.sign() < 0)
@@ -314,16 +311,16 @@
if (!lRefPassed)
{
- state->theIterator = collection->getIterator(lSkip);
+ state->theIterator = collection->getIterator(lSkip + skipCount);
}
else
{
store::Item_t lRefItem;
consumeNext(lRefItem, theChildren[1].getp(), planState);
- lStart = lRefItem->getString();
+ lStart = lRefItem->getString();
try
{
- state->theIterator = collection->getIterator(lSkip, lStart);
+ state->theIterator = collection->getIterator(lSkip + skipCount, lStart);
}
catch (ZorbaException& e)
{
@@ -346,6 +343,29 @@
}
state->theIteratorOpened = true;
+}
+
+
+bool ZorbaCollectionIterator::nextImpl(
+ store::Item_t& result,
+ PlanState& planState) const
+{
+ store::Item_t name;
+ xs_integer lSkip;
+ store::Collection_t collection;
+
+ ZorbaCollectionIteratorState* state;
+ DEFAULT_STACK_INIT(ZorbaCollectionIteratorState, state, planState);
+
+ if (state->theIterator.getp() != NULL && state->theIteratorOpened == false)
+ {
+ ZORBA_ASSERT (false && "nextImpl() called past iterator end");
+ return false;
+ }
+ else if (state->theIteratorOpened == false)
+ {
+ initCollection(planState, 0);
+ }
while (state->theIterator->next(result))
STACK_PUSH(true, state);
@@ -358,6 +378,36 @@
}
+bool ZorbaCollectionIterator::skip(int64_t count, PlanState& planState) const
+{
+ ZorbaCollectionIteratorState* state = StateTraitsImpl<ZorbaCollectionIteratorState>::getState(planState, theStateOffset);
+
+ if (state->theIterator.getp() != NULL && state->theIteratorOpened == false)
+ {
+ ZORBA_ASSERT (false && "nextImpl() called past iterator end");
+ return false;
+ }
+ else if (state->theIteratorOpened == false)
+ {
+ initCollection(planState, count);
+ }
+
+ store::Item_t result;
+ bool have_more_items = true;
+ while (count-- > 0 && (have_more_items = state->theIterator->next(result)))
+ ;
+
+ if ( ! have_more_items)
+ {
+ // close as early as possible
+ state->theIterator->close();
+ state->theIteratorOpened = false;
+ }
+
+ return have_more_items;
+}
+
+
bool ZorbaCollectionIterator::count(store::Item_t& result, PlanState& planState) const
{
if (!isCountOptimizable())
=== modified file 'src/runtime/collections/pregenerated/collections.h'
--- src/runtime/collections/pregenerated/collections.h 2013-03-24 20:40:03 +0000
+++ src/runtime/collections/pregenerated/collections.h 2013-07-15 10:38:33 +0000
@@ -291,6 +291,8 @@
public:
bool isCountOptimizable() const;
bool count(store::Item_t& result, PlanState& planState) const;
+ bool skip(int64_t count, PlanState& planState) const;
+ void initCollection(PlanState& planState, int64_t skipCount) const;
void accept(PlanIterVisitor& v) const;
bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;
=== modified file 'src/runtime/sequences/sequences_impl.cpp'
--- src/runtime/sequences/sequences_impl.cpp 2013-06-18 18:55:33 +0000
+++ src/runtime/sequences/sequences_impl.cpp 2013-07-15 10:38:33 +0000
@@ -533,11 +533,8 @@
goto done;
// Consume and skip all input items that are before the startPos
- for (; startPos > 1; --startPos)
- {
- if (!CONSUME(result, 0))
- goto done;
- }
+ if (!theChildren[0]->skip(startPos-1, planState))
+ goto done;
if (theChildren.size() < 3 || lengthDouble.isPosInf())
{
@@ -619,11 +616,8 @@
goto done;
// Consume and skip all input items that are before the startPos
- for (; startPos > 0; --startPos)
- {
- if (!CONSUME(result, 0))
- goto done;
- }
+ if (!theChildren[0]->skip(startPos, planState))
+ goto done;
if (theChildren.size() < 3)
{
@@ -694,11 +688,8 @@
--startPos;
// Consume and skip all input items that are before the startPos
- for (; startPos > 0; --startPos)
- {
- if (!CONSUME(result, 0))
- goto done;
- }
+ if (!theChildren[0]->skip(startPos, planState))
+ goto done;
if (CONSUME(result, 0))
{
=== modified file 'src/runtime/spec/collections/collections.xml'
--- src/runtime/spec/collections/collections.xml 2013-04-02 22:54:20 +0000
+++ src/runtime/spec/collections/collections.xml 2013-07-15 10:38:33 +0000
@@ -313,6 +313,16 @@
<zorba:param name="result" type="store::Item_t&"/>
<zorba:param name="planState" type="PlanState&"/>
</zorba:method>
+
+ <zorba:method name="skip" const="true" return="bool">
+ <zorba:param name="count" type="int64_t"/>
+ <zorba:param name="planState" type="PlanState&"/>
+ </zorba:method>
+
+ <zorba:method name="initCollection" const="true" return="void">
+ <zorba:param name="planState" type="PlanState&"/>
+ <zorba:param name="skipCount" type="int64_t"/>
+ </zorba:method>
<zorba:state generateInit="false" generateReset="false" generateDestructor="false">
<zorba:member type="store::Iterator_t" name="theIterator"/>
Follow ups
-
[Merge] lp:~zorba-coders/zorba/skip-items into lp:zorba
From: noreply, 2013-07-26
-
[Merge] lp:~zorba-coders/zorba/skip-items into lp:zorba
From: Zorba Build Bot, 2013-07-26
-
[Merge] lp:~zorba-coders/zorba/skip-items into lp:zorba
From: Zorba Build Bot, 2013-07-26
-
[Merge] lp:~zorba-coders/zorba/skip-items into lp:zorba
From: Zorba Build Bot, 2013-07-26
-
[Merge] lp:~zorba-coders/zorba/skip-items into lp:zorba
From: Zorba Build Bot, 2013-07-26
-
Re: [Merge] lp:~zorba-coders/zorba/skip-items into lp:zorba
From: Matthias Brantner, 2013-07-26
-
Re: [Merge] lp:~zorba-coders/zorba/skip-items into lp:zorba
From: Nicolae Brinza, 2013-07-26
-
Re: [Merge] lp:~zorba-coders/zorba/skip-items into lp:zorba
From: Matthias Brantner, 2013-07-25
-
[Merge] lp:~zorba-coders/zorba/skip-items into lp:zorba
From: Zorba Build Bot, 2013-07-25
-
[Merge] lp:~zorba-coders/zorba/skip-items into lp:zorba
From: Zorba Build Bot, 2013-07-25
-
[Merge] lp:~zorba-coders/zorba/skip-items into lp:zorba
From: Zorba Build Bot, 2013-07-25
-
[Merge] lp:~zorba-coders/zorba/skip-items into lp:zorba
From: Zorba Build Bot, 2013-07-25
-
[Merge] lp:~zorba-coders/zorba/skip-items into lp:zorba
From: Zorba Build Bot, 2013-07-25
-
Re: [Merge] lp:~zorba-coders/zorba/skip-items into lp:zorba
From: Matthias Brantner, 2013-07-23
-
Re: [Merge] lp:~zorba-coders/zorba/skip-items into lp:zorba
From: Nicolae Brinza, 2013-07-23
-
Re: [Merge] lp:~zorba-coders/zorba/skip-items into lp:zorba
From: Matthias Brantner, 2013-07-18
-
Re: [Merge] lp:~zorba-coders/zorba/skip-items into lp:zorba
From: Nicolae Brinza, 2013-07-17
-
[Merge] lp:~zorba-coders/zorba/skip-items into lp:zorba
From: Zorba Build Bot, 2013-07-15
-
[Merge] lp:~zorba-coders/zorba/skip-items into lp:zorba
From: Zorba Build Bot, 2013-07-15
-
[Merge] lp:~zorba-coders/zorba/skip-items into lp:zorba
From: Nicolae Brinza, 2013-07-15