zorba-coders team mailing list archive
-
zorba-coders team
-
Mailing list archive
-
Message #12136
[Merge] lp:~zorba-coders/zorba/index-maintenance into lp:zorba
Markos Zaharioudakis has proposed merging lp:~zorba-coders/zorba/index-maintenance into lp:zorba.
Requested reviews:
Markos Zaharioudakis (markos-za)
For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/index-maintenance/+merge/114682
Incremental maintenance for general indexes.
--
https://code.launchpad.net/~zorba-coders/zorba/index-maintenance/+merge/114682
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'ChangeLog'
--- ChangeLog 2012-07-12 15:34:50 +0000
+++ ChangeLog 2012-07-12 16:38:27 +0000
@@ -15,7 +15,8 @@
http://www.zorba-xquery.com/modules/store/data-structures/unordered-map module.
* Added support for fragments to fn:path
* Positional pagination support for collections
-
+ * Incremental maintenance for general indexes.
+
Optimizations:
* Small optimization of comparison operations.
* Improved hoist rule: tighter hoisting of expressions (also fixes bug #967428,
=== modified file 'src/compiler/xqddf/value_index.cpp'
--- src/compiler/xqddf/value_index.cpp 2012-07-11 04:46:41 +0000
+++ src/compiler/xqddf/value_index.cpp 2012-07-12 16:38:27 +0000
@@ -295,7 +295,7 @@
if (theIsGeneral && numKeys > 1)
{
RAISE_ERROR(zerr::ZDST0035_INDEX_GENERAL_MULTIKEY, theKeyExprs[1]->get_loc(),
- ERROR_PARAMS(theName->getStringValue()));
+ ERROR_PARAMS(theName->getStringValue()));
}
// Check constraints on the key exprs
@@ -579,7 +579,7 @@
if (theDocIndexerPlan != NULL)
{
- theDocIndexer = new DocIndexer(numKeys, theDocIndexerPlan, docVarName);
+ theDocIndexer = new DocIndexer(isGeneral(), numKeys, theDocIndexerPlan, docVarName);
return theDocIndexer.getp();
}
@@ -689,7 +689,7 @@
//
// Create theDocIndexer obj
//
- theDocIndexer = new DocIndexer(numKeys, theDocIndexerPlan, docVarName);
+ theDocIndexer = new DocIndexer(isGeneral(), numKeys, theDocIndexerPlan, docVarName);
return theDocIndexer.getp();
}
=== modified file 'src/functions/func_index_ddl.cpp'
--- src/functions/func_index_ddl.cpp 2012-07-11 04:46:41 +0000
+++ src/functions/func_index_ddl.cpp 2012-07-12 16:38:27 +0000
@@ -97,7 +97,8 @@
std::vector<PlanIter_t>& argv,
expr& ann) const
{
- return new GeneralIndexEntryBuilderIterator(sctx, loc, argv);
+ assert(argv.size() == 2);
+ return new GeneralIndexEntryBuilderIterator(sctx, loc, argv[0], argv[1]);
}
@@ -158,7 +159,7 @@
DECL(sctx, op_general_index_entry_builder,
(createQName(zorba_op_ns, "", "general-index-entry-builder"),
GENV_TYPESYSTEM.ANY_NODE_TYPE_ONE,
- true,
+ GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_STAR,
GENV_TYPESYSTEM.ITEM_TYPE_STAR));
DECL(sctx, op_create_internal_index,
=== modified file 'src/functions/func_index_ddl.h'
--- src/functions/func_index_ddl.h 2012-07-11 04:46:41 +0000
+++ src/functions/func_index_ddl.h 2012-07-12 16:38:27 +0000
@@ -121,7 +121,7 @@
/*******************************************************************************
- op:value-index-entry-builder($node as node(), .....)
+ op:value-index-entry-builder($node as node(), xs:anyAtomic?, ..., xs:anyAtomic?)
This is a variadic function. The 1st input is a domain node, and the rest of
the inputs are the key items that comprise the key tuple for that node
@@ -144,7 +144,7 @@
/*******************************************************************************
- op:general-index-entry-builder($node as node(), .....)
+ op:general-index-entry-builder($node as node(), xs:anyAtomic*)
********************************************************************************/
class op_general_index_entry_builder : public function
{
@@ -157,7 +157,7 @@
bool accessesDynCtx() const { return true; }
- bool mustCopyInputNodes(expr* fo, csize input) const { return false; }
+ bool mustCopyInputNodes(expr* fo, csize input) const { return false; }
CODEGEN_DECL();
};
=== modified file 'src/runtime/core/apply_updates.cpp'
--- src/runtime/core/apply_updates.cpp 2012-07-11 04:46:41 +0000
+++ src/runtime/core/apply_updates.cpp 2012-07-12 16:38:27 +0000
@@ -37,6 +37,8 @@
#include "common/shared_types.h"
+#include "diagnostics/util_macros.h"
+
namespace zorba
{
@@ -154,21 +156,18 @@
// maintained incrementally, and pass this info back to the pul.
pul->getIndicesToRefresh(indexes, truncate_indexes);
- ulong numIndices = (ulong)indexes.size();
+ csize numIndices = indexes.size();
std::vector<IndexDecl*> zorbaIndexes(numIndices);
- for (ulong i = 0; i < numIndices; ++i)
+ for (csize i = 0; i < numIndices; ++i)
{
IndexDecl* indexDecl = sctx->lookup_index(indexes[i]->getName());
if (indexDecl == NULL)
{
- throw XQUERY_EXCEPTION(
- zerr::ZDDY0021_INDEX_NOT_DECLARED,
- ERROR_PARAMS( indexes[i]->getName()->getStringValue() ),
- ERROR_LOC( loc )
- );
+ RAISE_ERROR(zerr::ZDDY0021_INDEX_NOT_DECLARED, loc,
+ ERROR_PARAMS(indexes[i]->getName()->getStringValue()));
}
if (indexDecl->getMaintenanceMode() == IndexDecl::DOC_MAP)
@@ -184,8 +183,8 @@
zorbaIndexes[i] = indexDecl;
}
- numIndices = (ulong)truncate_indexes.size();
- for (ulong i = 0; i < numIndices; ++i)
+ numIndices = truncate_indexes.size();
+ for (csize i = 0; i < numIndices; ++i)
{
IndexDecl* indexDecl = sctx->lookup_index(indexes[i]->getName());
@@ -233,17 +232,15 @@
}
catch (XQueryException& e)
{
- if ( e.has_source() &&
- ( e.diagnostic() == err::XUDY0021 ||
- e.diagnostic() == err::XUDY0015 ||
- e.diagnostic() == err::XUDY0016 ||
- e.diagnostic() == err::XUDY0017 ||
- e.diagnostic() == err::XUDY0014 ) )
+ if (e.has_source() &&
+ (e.diagnostic() == err::XUDY0021 ||
+ e.diagnostic() == err::XUDY0015 ||
+ e.diagnostic() == err::XUDY0016 ||
+ e.diagnostic() == err::XUDY0017 ||
+ e.diagnostic() == err::XUDY0014))
{
- XQueryException lNewE = XQUERY_EXCEPTION(
- err::XUDY0021,
- ERROR_PARAMS(ZED(XUDY0021_AppliedAt), loc)
- );
+ XQueryException lNewE =
+ XQUERY_EXCEPTION(err::XUDY0021, ERROR_PARAMS(ZED(XUDY0021_AppliedAt), loc));
QueryLoc lLoc;
lLoc.setFilename(e.source_uri());
=== modified file 'src/runtime/indexing/doc_indexer.cpp'
--- src/runtime/indexing/doc_indexer.cpp 2012-07-11 04:46:41 +0000
+++ src/runtime/indexing/doc_indexer.cpp 2012-07-12 16:38:27 +0000
@@ -33,8 +33,13 @@
/*******************************************************************************
********************************************************************************/
-DocIndexer::DocIndexer(csize numColumns, PlanIterator* plan, store::Item* varName)
+DocIndexer::DocIndexer(
+ bool general,
+ csize numColumns,
+ PlanIterator* plan,
+ store::Item* varName)
:
+ theIsGeneral(general),
theNumColumns(numColumns),
theIndexerPlan(plan),
theNodeVarName(varName),
@@ -81,41 +86,80 @@
store::Item_t tmp = docNode;
theDctx->set_variable(theNodeVarId, theNodeVarName, QueryLoc::null, tmp);
- csize numEntries = delta.size();
store::Item_t domainNode;
- store::IndexKey* key = NULL;
try
{
- while (thePlanWrapper->next(domainNode))
+ if (theIsGeneral)
{
- key = new store::IndexKey(theNumColumns);
-
- //std::cout << domainNode.getp() << " " << key << std::endl;
-
- for (csize i = 0; i < theNumColumns; ++i)
+ if (thePlanWrapper->next(domainNode))
{
- if (!thePlanWrapper->next((*key)[i]))
- throw ZORBA_EXCEPTION(zerr::ZXQP0003_INTERNAL_ERROR,
- ERROR_PARAMS(ZED(IncompleteKeyInIndexRefresh)));
+ store::Item_t key;
+ bool more = true;
+
+ while (more)
+ {
+ assert(domainNode->isNode());
+
+ while ((more = thePlanWrapper->next(key)))
+ {
+ if (key->isNode())
+ {
+ domainNode.transfer(key);
+ break;
+ }
+
+ store::Item_t node = domainNode;
+ delta.addGeneralPair(node, key);
+ }
+ }
}
+ }
+ else
+ {
+ store::IndexKey* key = NULL;
+
+ //std::cout << "Computing value index delta" << std::endl;
+
+ try
+ {
+ while (thePlanWrapper->next(domainNode))
+ {
+ key = new store::IndexKey(theNumColumns);
+
+ for (csize i = 0; i < theNumColumns; ++i)
+ {
+ if (!thePlanWrapper->next((*key)[i]))
+ {
+ throw ZORBA_EXCEPTION(zerr::ZXQP0003_INTERNAL_ERROR,
+ ERROR_PARAMS(ZED(IncompleteKeyInIndexRefresh)));
+ }
+ }
- delta.resize(numEntries + 1);
- delta[numEntries].first.transfer(domainNode);
- delta[numEntries].second = key;
- key = NULL;
- ++numEntries;
+ /*
+ std::cout << "[ node: " << domainNode.getp()
+ << " , key: " << key
+ << " , keyval: " << (*key)[0]->getStringValue()
+ << " ]" << std::endl;
+ */
+ delta.addValuePair(domainNode, key);
+ key = NULL;
+ }
+
+ //std::cout << std::endl;
+ }
+ catch(...)
+ {
+ if (key != NULL)
+ delete key;
+
+ throw;
+ }
}
}
catch(...)
{
- if (key != NULL)
- delete key;
-
- for (ulong i = 0; i < delta.size(); ++i)
- {
- delete delta[i].second;
- }
+ delta.clear();
theDctx->unset_variable(theNodeVarId, theNodeVarName, QueryLoc::null);
=== modified file 'src/runtime/indexing/doc_indexer.h'
--- src/runtime/indexing/doc_indexer.h 2012-07-11 04:46:41 +0000
+++ src/runtime/indexing/doc_indexer.h 2012-07-12 16:38:27 +0000
@@ -26,11 +26,13 @@
/*******************************************************************************
-
+ See IndexEntryCreator class in store/api/index.h
********************************************************************************/
class DocIndexer : public store::IndexEntryCreator
{
protected:
+ bool theIsGeneral;
+
csize theNumColumns;
PlanIter_t theIndexerPlan;
@@ -42,7 +44,11 @@
store::Iterator_t thePlanWrapper;
public:
- DocIndexer(csize numColumns, PlanIterator* plan, store::Item* varName);
+ DocIndexer(
+ bool general,
+ csize numColumns,
+ PlanIterator* plan,
+ store::Item* varName);
~DocIndexer();
=== modified file 'src/runtime/indexing/index_ddl.cpp'
--- src/runtime/indexing/index_ddl.cpp 2012-07-11 04:46:41 +0000
+++ src/runtime/indexing/index_ddl.cpp 2012-07-12 16:38:27 +0000
@@ -471,27 +471,15 @@
GeneralIndexEntryBuilderIterator
********************************************************************************/
-GeneralIndexEntryBuilderIteratorState::GeneralIndexEntryBuilderIteratorState()
-{
-}
-
-
-GeneralIndexEntryBuilderIteratorState::~GeneralIndexEntryBuilderIteratorState()
-{
-}
-
-
-void GeneralIndexEntryBuilderIteratorState::init(PlanState& planState)
-{
- PlanIteratorState::init(planState);
- theCurChild = 0;
-}
-
-
-void GeneralIndexEntryBuilderIteratorState::reset(PlanState& planState)
-{
- PlanIteratorState::reset(planState);
- theCurChild = 0;
+GeneralIndexEntryBuilderIterator::GeneralIndexEntryBuilderIterator(
+ static_context* sctx,
+ const QueryLoc& loc,
+ PlanIter_t& child0,
+ PlanIter_t& child1)
+ :
+ BinaryBaseIterator<GeneralIndexEntryBuilderIterator,
+ PlanIteratorState>(sctx, loc, child0, child1)
+{
}
@@ -500,38 +488,36 @@
}
+void GeneralIndexEntryBuilderIterator::serialize(::zorba::serialization::Archiver& ar)
+{
+ serialize_baseclass(ar,
+ (BinaryBaseIterator<GeneralIndexEntryBuilderIterator,
+ PlanIteratorState>*)this);
+}
+
+
bool GeneralIndexEntryBuilderIterator::nextImpl(
store::Item_t& result,
PlanState& planState) const
{
- GeneralIndexEntryBuilderIteratorState* state;
- DEFAULT_STACK_INIT(GeneralIndexEntryBuilderIteratorState, state, planState);
-
- for (; state->theCurChild < theChildren.size(); ++state->theCurChild)
+ PlanIteratorState* state;
+ DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
+
+ consumeNext(result, theChild0.getp(), planState);
+ ZORBA_ASSERT(result);
+
+ STACK_PUSH(true, state);
+
+ while (consumeNext(result, theChild1.getp(), planState))
{
- while (consumeNext(result, theChildren[state->theCurChild].getp(), planState))
- {
- STACK_PUSH(true, state);
- }
+ STACK_PUSH(true, state);
}
STACK_END(state);
}
-void GeneralIndexEntryBuilderIterator::accept(PlanIterVisitor& v) const
-{
- v.beginVisit(*this);
-
- std::vector<PlanIter_t>::const_iterator lIter = theChildren.begin();
- std::vector<PlanIter_t>::const_iterator lEnd = theChildren.end();
- for ( ; lIter != lEnd; ++lIter )
- {
- (*lIter)->accept(v);
- }
-
- v.endVisit(*this);
-}
+BINARY_ACCEPT(GeneralIndexEntryBuilderIterator)
/*******************************************************************************
=== modified file 'src/runtime/indexing/index_ddl.h'
--- src/runtime/indexing/index_ddl.h 2012-07-11 04:46:41 +0000
+++ src/runtime/indexing/index_ddl.h 2012-07-12 16:38:27 +0000
@@ -19,9 +19,9 @@
#include "common/shared_types.h"
+
#include "runtime/base/unarybase.h"
-
-
+#include "runtime/base/binarybase.h"
#include "runtime/base/narybase.h"
@@ -231,12 +231,12 @@
/******************************************************************************
-
+ zorba-op:value-index-entry-builder(node(), xs:anyAtomic)
*******************************************************************************/
class ValueIndexEntryBuilderIteratorState : public PlanIteratorState
{
public:
- uint32_t theCurChild;
+ csize theCurChild;
public:
ValueIndexEntryBuilderIteratorState();
@@ -283,50 +283,25 @@
/******************************************************************************
-
+ zorba-op:general-index-entry-builder(node(), xs:anyAtomic*)
*******************************************************************************/
-class GeneralIndexEntryBuilderIteratorState : public PlanIteratorState
-{
-public:
- uint32_t theCurChild;
-
-public:
- GeneralIndexEntryBuilderIteratorState();
-
- ~GeneralIndexEntryBuilderIteratorState();
-
- void init(PlanState&);
-
- void reset(PlanState&);
-};
-
-
class GeneralIndexEntryBuilderIterator :
-public NaryBaseIterator<GeneralIndexEntryBuilderIterator,
- GeneralIndexEntryBuilderIteratorState>
+public BinaryBaseIterator<GeneralIndexEntryBuilderIterator,
+ PlanIteratorState>
{
public:
SERIALIZABLE_CLASS(GeneralIndexEntryBuilderIterator);
-
SERIALIZABLE_CLASS_CONSTRUCTOR2T(GeneralIndexEntryBuilderIterator,
- NaryBaseIterator<GeneralIndexEntryBuilderIterator,
- GeneralIndexEntryBuilderIteratorState>);
-
- void serialize( ::zorba::serialization::Archiver& ar)
- {
- serialize_baseclass(ar,
- (NaryBaseIterator<GeneralIndexEntryBuilderIterator,
- GeneralIndexEntryBuilderIteratorState>*)this);
- }
-
+ BinaryBaseIterator<GeneralIndexEntryBuilderIterator,
+ PlanIteratorState>);
+ void serialize(::zorba::serialization::Archiver& ar);
+
+public:
GeneralIndexEntryBuilderIterator(
- static_context* sctx,
- const QueryLoc& loc,
- std::vector<PlanIter_t>& children)
- :
- NaryBaseIterator<GeneralIndexEntryBuilderIterator,
- GeneralIndexEntryBuilderIteratorState>(sctx, loc, children)
- {}
+ static_context* sctx,
+ const QueryLoc& loc,
+ PlanIter_t& child0,
+ PlanIter_t& child1);
virtual ~GeneralIndexEntryBuilderIterator();
=== modified file 'src/store/api/index.h'
--- src/store/api/index.h 2012-07-11 04:46:41 +0000
+++ src/store/api/index.h 2012-07-12 16:38:27 +0000
@@ -90,7 +90,7 @@
class IndexSpecification
{
public:
- ulong theNumKeyColumns;
+ csize theNumKeyColumns;
std::vector<store::Item_t> theKeyTypes;
std::vector<std::string> theCollations;
long theTimezone;
@@ -126,14 +126,14 @@
theIsGeneral = theIsUnique = theIsSorted = theIsTemp = theIsThreadSafe = false;
}
- void resize(ulong numColumns)
+ void resize(csize numColumns)
{
theNumKeyColumns = numColumns;
theKeyTypes.resize(numColumns);
theCollations.resize(numColumns);
}
- ulong getNumColumns() const { return theNumKeyColumns; }
+ csize getNumColumns() const { return theNumKeyColumns; }
long getTimezone() const { return theTimezone; }
};
@@ -145,14 +145,38 @@
class IndexKey : public ItemVector
{
public:
- IndexKey(ulong size = 0) : ItemVector(size) {}
+ IndexKey(csize size = 0) : ItemVector(size) {}
};
/**************************************************************************//**
- An index delta is a set of [domain-node, associated-key] pairs.
+ A index delta is a set of [domain-node, associated-key(s)] pairs.
*******************************************************************************/
-typedef std::vector<std::pair<store::Item_t, store::IndexKey*> > IndexDelta;
+class IndexDelta
+{
+public:
+ typedef std::pair<Item_t, IndexKey*> ValuePair;
+
+ typedef std::vector<ValuePair> ValueDelta;
+
+ typedef std::pair<Item_t, Item_t> GeneralPair;
+
+ typedef std::vector<GeneralPair> GeneralDelta;
+
+protected:
+ ValueDelta theValueDelta;
+ GeneralDelta theGeneralDelta;
+
+public:
+ void addValuePair(Item_t& node, IndexKey* key);
+
+ void addGeneralPair(Item_t& node, Item_t& key);
+
+ void clear();
+
+protected:
+ IndexDelta() {}
+};
/***************************************************************************//**
@@ -388,7 +412,7 @@
/**
* Return the number of columns in the jeys of this index.
*/
- virtual ulong getNumColumns() const = 0;
+ virtual csize getNumColumns() const = 0;
/**
* Return the timezone that is used when comparing date-time related items
@@ -399,7 +423,7 @@
* Return pointer to the collator used by this index when comparing items at
* its i-th column (return NULL if no collator is used for the i-th column).
*/
- virtual const XQPCollator* getCollator(ulong i) const = 0;
+ virtual const XQPCollator* getCollator(csize i) const = 0;
/**
* Create an index condition (see class IndexCondition below)
@@ -409,7 +433,7 @@
/**
* Returns the number of entries in the index
*/
- virtual ulong size() const = 0;
+ virtual csize size() const = 0;
/**
* Returns all keys stored in this index
@@ -423,23 +447,34 @@
* The index wil take the ownership of the key if it was not already in the
* index.
*
+ * NOTE: this method is needed here because it is invoked from the
+ * UDFunctionCallIterator to implement the function cache.
+ *
* @error ZDDY0035 if a key with more than one item is inserted into
* a general index
*/
virtual bool insert(store::IndexKey*& key, store::Item_t& item) = 0;
virtual bool remove(
- const store::IndexKey* key,
- const store::Item_t& item,
- bool all = false) = 0;
+ const store::IndexKey* key,
+ const store::Item_t& item,
+ bool all = false) = 0;
};
/*******************************************************************************
- An abstract class that provides a callback method for the store to call in order
- to perform index maintenance. The method computes [domain_item, associated-key]
- pairs for a given node that has some relationship to the domain expression.
+ An abstract class that provides a callback method for the store to call during
+ index maintenance. The method computes [domain_node, associated-key] pairs for
+ a given node that has some relationship to the domain expression.
+
+ Instances of IndexEntryCreator are created by the ApplyIterator for each
+ incrementally-maintenable index that needs maintenance. Such an instance is
+ stored inside the IndexDecl of the associated index, so that it can be
+ reused every time the index needs maintenance.
+
+ A concrete implementation of this class is provided in
+ runtime/index/doc_indexer.h
********************************************************************************/
class IndexEntryCreator : public SimpleRCObject
{
=== modified file 'src/store/naive/atomic_items.cpp'
--- src/store/naive/atomic_items.cpp 2012-07-11 04:46:41 +0000
+++ src/store/naive/atomic_items.cpp 2012-07-12 16:38:27 +0000
@@ -245,7 +245,21 @@
xs_long longValue = static_cast<xs_long>(doubleValue.getNumber());
+ /*
+ std::cout << "original long value = " << item->theValue << std::endl
+ << "double value = " << doubleValue << std::endl
+ << "new long value = " << longValue << std::endl << std::endl;
+
+ */
lossy = (longValue != item->theValue);
+
+ /*
+ std::cout << "original long value = " << item->theValue << std::endl
+ << "double value = " << doubleValue << std::endl
+ << "new long value = " << longValue << std::endl << std::endl;
+ */
+ std::cout << "lossy = " << lossy << std::endl << std::endl;
+
break;
}
=== modified file 'src/store/naive/item.cpp'
--- src/store/naive/item.cpp 2012-07-11 04:46:41 +0000
+++ src/store/naive/item.cpp 2012-07-12 16:38:27 +0000
@@ -19,6 +19,8 @@
#include <zorba/error.h>
#include "diagnostics/xquery_diagnostics.h"
+#include "diagnostics/assert.h"
+
#include "zorbatypes/datetime.h"
#include "store/api/item.h"
@@ -32,6 +34,9 @@
#include "runtime/function_item/function_item.h"
+# include <cstdlib>
+# include <execinfo.h>
+
namespace zorba
{
@@ -490,11 +495,50 @@
}
+static void print_stack_trace( std::ostream& o )
+{
+ int BUF_SIZE = 250;
+ void* buf[ BUF_SIZE ];
+
+ int const size = backtrace(buf, BUF_SIZE);
+
+ if (char** symbols = backtrace_symbols(buf, size))
+ {
+ for ( int i = 0; i < size; ++i )
+ o << symbols[i] << std::endl;
+
+ free( symbols );
+ }
+ else
+ {
+ o << "allocation of backtrace symbols failed" << std::endl;
+ }
+}
+
+
/**
* Accessor for xs:untypedAtomic and xs:string and its subtypes
*/
const zstring& Item::getString() const
{
+ if (isAtomic())
+ {
+ std::cerr << "Atomic item value: " << getStringValue() << std::endl;
+ }
+ else if (isNode())
+ {
+ std::cerr << "Node item: " << this << std::endl
+ << " node name: " << getNodeName()->getStringValue() << std::endl
+ << " node string value: " << getStringValue() << std::endl;
+ }
+ else
+ {
+ std::cerr << "???????" << std::endl;
+ }
+
+
+ print_stack_trace(std::cerr);
+
throw ZORBA_EXCEPTION(
zerr::ZSTR0040_TYPE_ERROR,
ERROR_PARAMS(
=== modified file 'src/store/naive/simple_index.cpp'
--- src/store/naive/simple_index.cpp 2012-07-11 04:46:41 +0000
+++ src/store/naive/simple_index.cpp 2012-07-12 16:38:27 +0000
@@ -594,7 +594,60 @@
}
-}
+} // namespace simplestore
+
+
+namespace store
+{
+
+/////////////////////////////////////////////////////////////////////////////////
+// //
+// IndexDelta //
+// //
+/////////////////////////////////////////////////////////////////////////////////
+
+/*******************************************************************************
+
+********************************************************************************/
+void IndexDelta::addValuePair(store::Item_t& node, store::IndexKey* key)
+{
+ theValueDelta.resize(theValueDelta.size() + 1);
+ theValueDelta.back().first.transfer(node);
+ theValueDelta.back().second = key;
+}
+
+
+/*******************************************************************************
+
+********************************************************************************/
+void IndexDelta::addGeneralPair(store::Item_t& node, store::Item_t& key)
+{
+ assert(node->isNode() && key->isAtomic());
+
+ theGeneralDelta.resize(theGeneralDelta.size() + 1);
+ theGeneralDelta.back().first.transfer(node);
+ theGeneralDelta.back().second.transfer(key);
+}
+
+
+/*******************************************************************************
+
+********************************************************************************/
+void IndexDelta::clear()
+{
+ for (csize i = 0; i < theValueDelta.size(); ++i)
+ {
+ delete theValueDelta[i].second;
+ }
+
+ theValueDelta.clear();
+ theGeneralDelta.clear();
+}
+
+
+} // namespace store
+
+
}
/* vim:set et sw=2 ts=2: */
=== modified file 'src/store/naive/simple_index.h'
--- src/store/naive/simple_index.h 2012-07-11 04:46:41 +0000
+++ src/store/naive/simple_index.h 2012-07-12 16:38:27 +0000
@@ -59,13 +59,13 @@
const store::IndexSpecification& getSpecification() const { return theSpec; }
- ulong getNumColumns() const { return theSpec.getNumColumns(); }
+ csize getNumColumns() const { return theSpec.getNumColumns(); }
long getTimezone() const { return theSpec.theTimezone; }
const std::vector<std::string>& getCollations() const { return theSpec.theCollations; }
- virtual ulong size() const = 0;
+ virtual csize size() const = 0;
virtual KeyIterator_t keys() const = 0;
@@ -298,7 +298,7 @@
{
}
- ulong numRanges() const { return theLowerBounds.size(); }
+ csize numRanges() const { return theLowerBounds.size(); }
void clear();
@@ -319,6 +319,33 @@
std::ostream& operator<<(std::ostream& os, const IndexBoxValueCondition& cond);
+/**************************************************************************//**
+ A index delta is a set of [domain-node, associated-key(s)] pairs.
+*******************************************************************************/
+class IndexDeltaImpl : public store::IndexDelta
+{
+public:
+ typedef std::vector<store::IndexDelta::ValuePair>::iterator
+ ValueIterator;
+
+ typedef std::vector<store::IndexDelta::ValuePair>::reverse_iterator
+ ReverseValueIterator;
+
+ typedef std::vector<store::IndexDelta::GeneralPair>::iterator
+ GeneralIterator;
+
+ typedef std::vector<store::IndexDelta::GeneralPair>::reverse_iterator
+ ReverseGeneralIterator;
+
+public:
+ IndexDeltaImpl() { }
+
+ ValueDelta& getValueDelta() { return theValueDelta; }
+
+ GeneralDelta& getGeneralDelta() { return theGeneralDelta; }
+};
+
+
}
}
=== modified file 'src/store/naive/simple_index_general.cpp'
--- src/store/naive/simple_index_general.cpp 2012-07-11 04:46:41 +0000
+++ src/store/naive/simple_index_general.cpp 2012-07-12 16:38:27 +0000
@@ -156,6 +156,27 @@
/******************************************************************************
*******************************************************************************/
+bool GeneralIndexValue::removeNode(const store::Item_t& node)
+{
+ GeneralIndexValue::iterator ite = theNodes.begin();
+ GeneralIndexValue::iterator end = theNodes.end();
+
+ for (; ite != end; ++ite)
+ {
+ if ((*ite).theNode == node)
+ {
+ theNodes.erase(ite);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+/******************************************************************************
+
+*******************************************************************************/
void GeneralIndexValue::addNode(store::Item_t& node, bool untyped)
{
csize numNodes = theNodes.size();
@@ -191,8 +212,8 @@
IndexImpl(qname, spec),
theKeyTypeCode(store::XS_LAST),
theCompFunction(spec.theTimezone, spec.theCollations[0]),
- theUntypedFlag(false),
- theMultiKeyFlag(false)
+ theNumUntypedEntries(0),
+ theNumMultiKeyNodes(0)
{
store::Item* typeName = spec.theKeyTypes[0].getp();
@@ -216,7 +237,7 @@
/******************************************************************************
*******************************************************************************/
-const XQPCollator* GeneralIndex::getCollator(ulong i) const
+const XQPCollator* GeneralIndex::getCollator(csize i) const
{
ZORBA_ASSERT(i == 0);
return theCompFunction.getCollator();
@@ -226,7 +247,7 @@
/******************************************************************************
*******************************************************************************/
-ulong GeneralIndex::size() const
+csize GeneralIndex::size() const
{
assert(false);
return 0;
@@ -348,6 +369,7 @@
{
// try lossless cast to xs:long
keyItem->castToLong(castItem);
+
if (castItem != NULL)
{
keyItem = static_cast<AtomicItem*>(castItem.getp());
@@ -363,7 +385,8 @@
if (lossy)
{
node2 = node;
- found = found || insertInMap(castItem, node2, store::XS_DECIMAL, false);
+ if (insertInMap(castItem, node2, store::XS_DECIMAL, false))
+ found = true;
}
return found;
@@ -389,10 +412,18 @@
if (lossy)
{
+ /*
+ std::cout << "Lossy LONG insertion in index" << getName()->getStringValue()
+ << std::endl
+ << "long value = " << longValue
+ << " double value = " << castItem->getDoubleValue()
+ << std::endl << std::endl;
+ */
node2 = node;
found = insertInMap(key, node2, store::XS_LONG, false);
- found = found || insertInMap(castItem, node, store::XS_DOUBLE, false);
+ if (insertInMap(castItem, node, store::XS_DOUBLE, false))
+ found = true;
}
else
{
@@ -440,7 +471,8 @@
xs_long longValue = longItem->getLongValue();
node2 = node;
- found = found || insertInMap(castItem, node2, store::XS_LONG, true);
+ if (insertInMap(castItem, node2, store::XS_LONG, true))
+ found = true;
if (longValue > theMaxLong || longValue < theMinLong)
{
@@ -458,7 +490,8 @@
if (lossy)
{
node2 = node;
- found = found || insertInMap(castItem, node2, store::XS_DOUBLE, true);
+ if (insertInMap(castItem, node2, store::XS_DOUBLE, true))
+ found = true;
}
}
@@ -468,19 +501,22 @@
if (untypedItem->castToGYear(castItem))
{
node2 = node;
- found = found || insertInMap(castItem, node2, store::XS_GYEAR, true);
+ if (insertInMap(castItem, node2, store::XS_GYEAR, true))
+ found = true;
}
if (untypedItem->castToHexBinary(castItem))
{
node2 = node;
- found = found || insertInMap(castItem, node2, store::XS_HEXBINARY, true);
+ if (insertInMap(castItem, node2, store::XS_HEXBINARY, true))
+ found = true;
}
if (untypedItem->castToBase64Binary(castItem))
{
node2 = node;
- found = found || insertInMap(castItem, node2, store::XS_BASE64BINARY, true);
+ if (insertInMap(castItem, node2, store::XS_BASE64BINARY, true))
+ found = true;
}
}
}
@@ -494,13 +530,15 @@
decimalItem->coerceToDouble(castItem, true, lossy);
node2 = node;
- found = found || insertInMap(castItem, node2, store::XS_DOUBLE, true);
+ if (insertInMap(castItem, node2, store::XS_DOUBLE, true))
+ found = true;
if (lossy)
{
castItem.transfer(decimalItem);
node2 = node;
- found = found || insertInMap(castItem, node2, store::XS_DECIMAL, true);
+ if (insertInMap(castItem, node2, store::XS_DECIMAL, true))
+ found = true;
}
// may also be hexBinary or base64Binary
@@ -509,13 +547,15 @@
if (untypedItem->castToHexBinary(castItem))
{
node2 = node;
- found = found || insertInMap(castItem, node2, store::XS_HEXBINARY, true);
+ if (insertInMap(castItem, node2, store::XS_HEXBINARY, true))
+ found = true;
}
if (untypedItem->castToBase64Binary(castItem))
{
node2 = node;
- found = found || insertInMap(castItem, node2, store::XS_BASE64BINARY, true);
+ if (insertInMap(castItem, node2, store::XS_BASE64BINARY, true))
+ found = true;
}
}
}
@@ -524,77 +564,88 @@
else if (untypedItem->castToDouble(castItem))
{
node2 = node;
- found = found || insertInMap(castItem, node2, store::XS_DOUBLE, true);
+ if (insertInMap(castItem, node2, store::XS_DOUBLE, true))
+ found = true;
}
// try casting to xs:datetime
else if (untypedItem->castToDateTime(castItem))
{
node2 = node;
- found = found || insertInMap(castItem, node2, store::XS_DATETIME, true);
+ if (insertInMap(castItem, node2, store::XS_DATETIME, true))
+ found = true;
}
// try casting to xs:date
else if (untypedItem->castToDate(castItem))
{
node2 = node;
- found = found || insertInMap(castItem, node2, store::XS_DATE, true);
+ if (insertInMap(castItem, node2, store::XS_DATE, true))
+ found = true;
}
// try casting to xs:time
else if (untypedItem->castToTime(castItem))
{
node2 = node;
- found = found || insertInMap(castItem, node2, store::XS_TIME, true);
+ if (insertInMap(castItem, node2, store::XS_TIME, true))
+ found = true;
}
// try casting to xs:gYearMonth
if (!sorted && untypedItem->castToGYearMonth(castItem))
{
node2 = node;
- found = found || insertInMap(castItem, node2, store::XS_GYEAR_MONTH, true);
+ if (insertInMap(castItem, node2, store::XS_GYEAR_MONTH, true))
+ found = true;
}
// try casting to xs:gMonthDay
else if (!sorted && untypedItem->castToGMonthDay(castItem))
{
node2 = node;
- found = found || insertInMap(castItem, node2, store::XS_GMONTH_DAY, true);
+ if (insertInMap(castItem, node2, store::XS_GMONTH_DAY, true))
+ found = true;
}
// try casting to xs:gDay
else if (!sorted && untypedItem->castToGDay(castItem))
{
node2 = node;
- found = found || insertInMap(castItem, node2, store::XS_GDAY, true);
+ if (insertInMap(castItem, node2, store::XS_GDAY, true))
+ found = true;
}
// try casting to xs:gMonth
else if (!sorted && untypedItem->castToGMonth(castItem))
{
node2 = node;
- found = found || insertInMap(castItem, node2, store::XS_GMONTH, true);
+ if (insertInMap(castItem, node2, store::XS_GMONTH, true))
+ found = true;
}
// try casting to xs:duration
else if (untypedItem->castToDuration(castItem))
{
node2 = node;
- found = found || insertInMap(castItem, node2, store::XS_DURATION, true);
+ if (insertInMap(castItem, node2, store::XS_DURATION, true))
+ found = true;
}
// try casting to xs:hexBinary
else if (!sorted && untypedItem->castToHexBinary(castItem))
{
node2 = node;
- found = found || insertInMap(castItem, node2, store::XS_HEXBINARY, true);
+ if (insertInMap(castItem, node2, store::XS_HEXBINARY, true))
+ found = true;
}
// try casting to xs:base64Binary
else if (!sorted && untypedItem->castToBase64Binary(castItem))
{
node2 = node;
- found = found || insertInMap(castItem, node2, store::XS_BASE64BINARY, true);
+ if (insertInMap(castItem, node2, store::XS_BASE64BINARY, true))
+ found = true;
}
return found;
@@ -620,17 +671,420 @@
bool untyped)
{
if (untyped)
- theUntypedFlag = true;
-
- if (isSorted())
- {
- GeneralTreeIndex* idx = static_cast<GeneralTreeIndex*>(this);
- return idx->insertInMap(key, node, idx->theMaps[targetMap], untyped);
- }
- else
- {
- GeneralHashIndex* idx = static_cast<GeneralHashIndex*>(this);
- return idx->insertInMap(key, node, idx->theMaps[targetMap], untyped);
+ ++theNumUntypedEntries;
+
+ if (isSorted())
+ {
+ GeneralTreeIndex* idx = static_cast<GeneralTreeIndex*>(this);
+ return idx->insertInMap(key, node, idx->theMaps[targetMap], untyped);
+ }
+ else
+ {
+ GeneralHashIndex* idx = static_cast<GeneralHashIndex*>(this);
+ return idx->insertInMap(key, node, idx->theMaps[targetMap], untyped);
+ }
+}
+
+
+/******************************************************************************
+
+*******************************************************************************/
+bool GeneralIndex::remove(const store::Item_t& key, const store::Item_t& node)
+{
+ bool lossy = false;
+ bool found = false;
+ store::Item_t castItem;
+
+ bool sorted = isSorted();
+
+ AtomicItem* keyItem = static_cast<AtomicItem*>(key.getp());
+
+ if (keyItem == NULL)
+ {
+ std::vector<store::Item_t>::iterator ite =
+ std::find(theEmptyKeyNodes.begin(), theEmptyKeyNodes.end(), node);
+
+ ZORBA_ASSERT(ite != theEmptyKeyNodes.end());
+
+ theEmptyKeyNodes.erase(ite);
+ return true;
+ }
+
+ if (keyItem->getBaseItem() != NULL)
+ {
+ keyItem = static_cast<AtomicItem*>(keyItem->getBaseItem());
+ }
+
+ if (isTyped())
+ {
+ return removeFromMap(key, node, theKeyTypeCode, false);
+ }
+
+ store::SchemaTypeCode keyType = keyItem->getTypeCode();
+
+ switch (keyType)
+ {
+ case store::XS_BASE64BINARY:
+ case store::XS_HEXBINARY:
+
+ case store::XS_QNAME:
+ case store::XS_NOTATION:
+
+ case store::XS_GYEAR_MONTH:
+ case store::XS_GYEAR:
+ case store::XS_GMONTH_DAY:
+ case store::XS_GDAY:
+ case store::XS_GMONTH:
+ {
+ assert(!sorted);
+ // falth through
+ }
+
+ case store::XS_ANY_URI:
+
+ case store::XS_BOOLEAN:
+
+ case store::XS_DATETIME:
+ case store::XS_DATE:
+ case store::XS_TIME:
+ {
+ return removeFromMap(key, node, keyType, false);
+ }
+
+ case store::XS_DURATION:
+ case store::XS_YM_DURATION:
+ case store::XS_DT_DURATION:
+ {
+ return removeFromMap(key, node, store::XS_DURATION, false);
+ }
+
+ case store::XS_STRING:
+ case store::XS_NORMALIZED_STRING:
+ case store::XS_TOKEN:
+ case store::XS_NMTOKEN:
+ case store::XS_LANGUAGE:
+ case store::XS_NAME:
+ case store::XS_NCNAME:
+ case store::XS_ID:
+ case store::XS_IDREF:
+ case store::XS_ENTITY:
+ {
+ return removeFromMap(key, node, store::XS_STRING, false);
+ }
+
+ case store::XS_DOUBLE:
+ case store::XS_FLOAT:
+ {
+ return removeFromMap(key, node, store::XS_DOUBLE, false);
+ }
+
+ case store::XS_DECIMAL:
+ case store::XS_INTEGER:
+ case store::XS_NON_POSITIVE_INTEGER:
+ case store::XS_NEGATIVE_INTEGER:
+ case store::XS_NON_NEGATIVE_INTEGER:
+ case store::XS_POSITIVE_INTEGER:
+ case store::XS_UNSIGNED_LONG:
+ {
+ // try lossless cast to xs:long
+ keyItem->castToLong(castItem);
+
+ if (castItem != NULL)
+ {
+ keyItem = static_cast<AtomicItem*>(castItem.getp());
+ goto longmap;
+ }
+
+ // Coerce to xs:double
+ keyItem->coerceToDouble(castItem, true, lossy);
+
+ found = removeFromMap(key, node, store::XS_DOUBLE, false);
+
+ if (lossy)
+ {
+ if (removeFromMap(castItem, node, store::XS_DECIMAL, false))
+ found = true;
+ }
+
+ return found;
+ }
+
+ case store::XS_LONG:
+ {
+ // NOTE: here we use KeyItem, instead of key, as arg to removeFromMap, because
+ // we can reach here from the store::XS_DECIMAL case.
+longmap:
+ xs_long longValue = static_cast<LongItem*>(keyItem)->getLongValue();
+
+ if (longValue > theMaxLong || longValue < theMinLong)
+ {
+ if (sorted)
+ {
+ lossy = true;
+ xs_double doubleValue(longValue);
+ GET_FACTORY().createDouble(castItem, doubleValue);
+ }
+ else
+ {
+ keyItem->coerceToDouble(castItem, false, lossy);
+ }
+
+ if (lossy)
+ {
+ /*
+ std::cout << "Lossy LONG insertion in index" << getName()->getStringValue()
+ << std::endl
+ << "long value = " << longValue
+ << " double value = " << castItem->getDoubleValue()
+ << std::endl << std::endl;
+ */
+ found = removeFromMap(keyItem, node, store::XS_LONG, false);
+
+ if (removeFromMap(castItem, node, store::XS_DOUBLE, false))
+ found = true;
+ }
+ else
+ {
+ found = removeFromMap(keyItem, node, store::XS_LONG, false);
+ }
+ }
+ else
+ {
+ found = removeFromMap(keyItem, node, store::XS_LONG, false);
+ }
+
+ return found;
+ }
+
+ case store::XS_INT:
+ case store::XS_SHORT:
+ case store::XS_BYTE:
+ case store::XS_UNSIGNED_INT:
+ case store::XS_UNSIGNED_SHORT:
+ case store::XS_UNSIGNED_BYTE:
+ {
+ return removeFromMap(key, node, store::XS_LONG, false);
+ }
+
+ case store::XS_UNTYPED_ATOMIC:
+ {
+ store::ItemHandle<UntypedAtomicItem> untypedItem =
+ static_cast<UntypedAtomicItem*>(key.getp());
+
+ // cast to xs:string
+ untypedItem->castToString(castItem);
+
+ found = removeFromMap(castItem, node, store::XS_STRING, false);
+
+ // try casting to xs:long
+ if (untypedItem->castToLong(castItem))
+ {
+ store::ItemHandle<LongItem> longItem = static_cast<LongItem*>(castItem.getp());
+
+ xs_long longValue = longItem->getLongValue();
+
+ if (removeFromMap(castItem, node, store::XS_LONG, true))
+ found = true;
+
+ if (longValue > theMaxLong || longValue < theMinLong)
+ {
+ if (sorted)
+ {
+ lossy = true;
+ xs_double doubleValue(longValue);
+ GET_FACTORY().createDouble(castItem, doubleValue);
+ }
+ else
+ {
+ longItem->coerceToDouble(castItem, false, lossy);
+ }
+
+ if (lossy)
+ {
+ if (removeFromMap(castItem, node, store::XS_DOUBLE, true))
+ found = true;
+ }
+ }
+
+ // may also be gYear, hexBinary, base64Binary, or boolean
+ if (!sorted)
+ {
+ if (untypedItem->castToGYear(castItem))
+ {
+ if (removeFromMap(castItem, node, store::XS_GYEAR, true))
+ found = true;
+ }
+
+ if (untypedItem->castToHexBinary(castItem))
+ {
+ if (removeFromMap(castItem, node, store::XS_HEXBINARY, true))
+ found = true;
+ }
+
+ if (untypedItem->castToBase64Binary(castItem))
+ {
+ if (removeFromMap(castItem, node, store::XS_BASE64BINARY, true))
+ found = true;
+ }
+ }
+ }
+
+ // try casting to xs:decimal
+ else if (untypedItem->castToDecimal(castItem))
+ {
+ store::ItemHandle<DecimalItem> decimalItem =
+ static_cast<DecimalItem*>(castItem.getp());
+
+ decimalItem->coerceToDouble(castItem, true, lossy);
+
+ if (removeFromMap(castItem, node, store::XS_DOUBLE, true))
+ found = true;
+
+ if (lossy)
+ {
+ castItem.transfer(decimalItem);
+ if (removeFromMap(castItem, node, store::XS_DECIMAL, true))
+ found = true;
+ }
+
+ // may also be hexBinary or base64Binary
+ if (sorted)
+ {
+ if (untypedItem->castToHexBinary(castItem))
+ {
+ if (removeFromMap(castItem, node, store::XS_HEXBINARY, true))
+ found = true;
+ }
+
+ if (untypedItem->castToBase64Binary(castItem))
+ {
+ if (removeFromMap(castItem, node, store::XS_BASE64BINARY, true))
+ found = true;
+ }
+ }
+ }
+
+ // try casting to xs:double
+ else if (untypedItem->castToDouble(castItem))
+ {
+ if (removeFromMap(castItem, node, store::XS_DOUBLE, true))
+ found = true;
+ }
+
+ // try casting to xs:datetime
+ else if (untypedItem->castToDateTime(castItem))
+ {
+ if (removeFromMap(castItem, node, store::XS_DATETIME, true))
+ found = true;
+ }
+
+ // try casting to xs:date
+ else if (untypedItem->castToDate(castItem))
+ {
+ if (removeFromMap(castItem, node, store::XS_DATE, true))
+ found = true;
+ }
+
+ // try casting to xs:time
+ else if (untypedItem->castToTime(castItem))
+ {
+ if (removeFromMap(castItem, node, store::XS_TIME, true))
+ found = true;
+ }
+
+ // try casting to xs:gYearMonth
+ if (!sorted && untypedItem->castToGYearMonth(castItem))
+ {
+ if (removeFromMap(castItem, node, store::XS_GYEAR_MONTH, true))
+ found = true;
+ }
+
+ // try casting to xs:gMonthDay
+ else if (!sorted && untypedItem->castToGMonthDay(castItem))
+ {
+ if (removeFromMap(castItem, node, store::XS_GMONTH_DAY, true))
+ found = true;
+ }
+
+ // try casting to xs:gDay
+ else if (!sorted && untypedItem->castToGDay(castItem))
+ {
+ if (removeFromMap(castItem, node, store::XS_GDAY, true))
+ found = true;
+ }
+
+ // try casting to xs:gMonth
+ else if (!sorted && untypedItem->castToGMonth(castItem))
+ {
+ if (removeFromMap(castItem, node, store::XS_GMONTH, true))
+ found = true;
+ }
+
+ // try casting to xs:duration
+ else if (untypedItem->castToDuration(castItem))
+ {
+ if (removeFromMap(castItem, node, store::XS_DURATION, true))
+ found = true;
+ }
+
+ // try casting to xs:hexBinary
+ else if (!sorted && untypedItem->castToHexBinary(castItem))
+ {
+ if (removeFromMap(castItem, node, store::XS_HEXBINARY, true))
+ found = true;
+ }
+
+ // try casting to xs:base64Binary
+ else if (!sorted && untypedItem->castToBase64Binary(castItem))
+ {
+ if (removeFromMap(castItem, node, store::XS_BASE64BINARY, true))
+ found = true;
+ }
+
+ return found;
+ }
+
+ default:
+ ZORBA_ASSERT(false);
+ }
+
+ return true;
+}
+
+
+/******************************************************************************
+
+*******************************************************************************/
+bool GeneralIndex::remove(
+ const store::IndexKey* key,
+ const store::Item_t& node,
+ bool all)
+{
+ ZORBA_ASSERT(false);
+}
+
+
+/******************************************************************************
+
+*******************************************************************************/
+bool GeneralIndex::removeFromMap(
+ const store::Item_t& key,
+ const store::Item_t& node,
+ store::SchemaTypeCode targetMap,
+ bool untyped)
+{
+ if (untyped)
+ --theNumUntypedEntries;
+
+ if (isSorted())
+ {
+ GeneralTreeIndex* idx = static_cast<GeneralTreeIndex*>(this);
+ return idx->removeFromMap(key, node, idx->theMaps[targetMap]);
+ }
+ else
+ {
+ GeneralHashIndex* idx = static_cast<GeneralHashIndex*>(this);
+ return idx->removeFromMap(key, node, idx->theMaps[targetMap]);
}
}
@@ -670,7 +1124,7 @@
*******************************************************************************/
GeneralHashIndex::~GeneralHashIndex()
{
- for (ulong i = 0; i < store::XS_LAST; ++i)
+ for (csize i = 0; i < store::XS_LAST; ++i)
{
if (theMaps[i] == NULL)
continue;
@@ -745,12 +1199,32 @@
/******************************************************************************
*******************************************************************************/
-bool GeneralHashIndex::remove(
+bool GeneralHashIndex::removeFromMap(
const store::Item_t& key,
- const store::Item_t& item,
- bool all)
+ const store::Item_t& node,
+ IndexMap* targetMap)
{
- assert(false);
+ assert(targetMap);
+ assert(key != NULL);
+
+ IndexMap::iterator pos = targetMap->find(key);
+
+ if (pos != targetMap->end())
+ {
+ GeneralIndexValue* valueSet = (*pos).second;
+
+ bool found = valueSet->removeNode(node);
+
+ if (valueSet->empty())
+ {
+ const_cast<store::Item*>((*pos).first)->removeReference();
+ delete valueSet;
+ targetMap->erase(pos);
+ }
+
+ return found;
+ }
+
return false;
}
@@ -760,7 +1234,7 @@
*******************************************************************************/
void GeneralHashIndex::clear()
{
- for (ulong i = 0; i < store::XS_LAST; ++i)
+ for (csize i = 0; i < store::XS_LAST; ++i)
{
if (theMaps[i] == NULL)
continue;
@@ -853,7 +1327,7 @@
*******************************************************************************/
GeneralTreeIndex::~GeneralTreeIndex()
{
- for (ulong i = 0; i < store::XS_LAST; ++i)
+ for (csize i = 0; i < store::XS_LAST; ++i)
{
if (theMaps[i] == NULL)
continue;
@@ -920,12 +1394,33 @@
/******************************************************************************
*******************************************************************************/
-bool GeneralTreeIndex::remove(
+bool GeneralTreeIndex::removeFromMap(
const store::Item_t& key,
- const store::Item_t& item,
- bool all)
+ const store::Item_t& node,
+ IndexMap* targetMap)
{
- return true;
+ assert(targetMap);
+ assert(key != NULL);
+
+ IndexMap::iterator pos = targetMap->find(key);
+
+ if (pos != targetMap->end())
+ {
+ GeneralIndexValue* valueSet = (*pos).second;
+
+ bool found = valueSet->removeNode(node);
+
+ if (valueSet->empty())
+ {
+ const_cast<store::Item*>((*pos).first)->removeReference();
+ delete valueSet;
+ targetMap->erase(pos);
+ }
+
+ return found;
+ }
+
+ return false;
}
@@ -934,7 +1429,7 @@
*******************************************************************************/
void GeneralTreeIndex::clear()
{
- for (ulong i = 0; i < store::XS_LAST; ++i)
+ for (csize i = 0; i < store::XS_LAST; ++i)
{
if (theMaps[i] == NULL)
continue;
@@ -1123,13 +1618,13 @@
if (theProbeKind == store::IndexCondition::POINT_VALUE ||
theProbeKind == store::IndexCondition::BOX_VALUE)
{
- if (theIndex->theMultiKeyFlag)
+ if (theIndex->theNumMultiKeyNodes > 0)
{
RAISE_ERROR_NO_LOC(err::XPTY0004,
ERROR_PARAMS(ZED(NoMultiKeyNodeValues_2), theIndex->getName()->getStringValue()));
}
- if (theIndex->theUntypedFlag)
+ if (theIndex->theNumUntypedEntries > 0)
{
checkStringKeyType(theCondition->theKey.getp());
checkStringKeyType(theCondition->theLowerBound.getp());
@@ -1871,7 +2366,7 @@
{
theIsFullProbe = true;
- for (ulong i = 0; i < store::XS_LAST; ++i)
+ for (csize i = 0; i < store::XS_LAST; ++i)
{
if (idx->theMaps[i] == NULL)
continue;
=== modified file 'src/store/naive/simple_index_general.h'
--- src/store/naive/simple_index_general.h 2012-07-11 04:46:41 +0000
+++ src/store/naive/simple_index_general.h 2012-07-12 16:38:27 +0000
@@ -77,19 +77,25 @@
typedef std::vector<NodeInfo>::const_iterator const_iterator;
+ typedef std::vector<NodeInfo>::iterator iterator;
+
protected:
std::vector<NodeInfo> theNodes;
public:
- GeneralIndexValue(ulong size = 0) : theNodes(size) {}
+ GeneralIndexValue(csize size = 0) : theNodes(size) {}
+
+ bool empty() const { return theNodes.empty(); }
void clear() { theNodes.clear(); }
- const_iterator begin() { return theNodes.begin(); }
+ const_iterator begin() const { return theNodes.begin(); }
- const_iterator end() { return theNodes.end(); }
+ const_iterator end() const { return theNodes.end(); }
void addNode(store::Item_t& node, bool untyped);
+
+ bool removeNode(const store::Item_t& node);
};
@@ -110,16 +116,17 @@
A vector storing all domain nodes for which the key expr returns the empty
sequence.
- theUntypedFlag:
- ---------------
- Set to true if there is at least one domain node for which the key expression
- returns an item with type xs:untypedAtomic and that item is sucessfully cast
- to an item with a type other than xs:string.
+ theNumUntypedEntries:
+ ---------------------
+ The number of [key, node] index entries where the key is the result of casting
+ an originally untyped key to a non-string atomic item. If > 0, then any value
+ probes with a key (or keys) whose type cannot be promoted to xs:string will
+ raise an error.
- theMultiKeyFlag:
- ----------------
- Set to true if there is at least one domain node for which the key expression
- returns more than one items.
+ theNumMultiKeyNodes:
+ --------------------
+ The number of domain nodes for which the key expression returns more than one
+ items. If > 0, then any value probes on the general index raise an error.
*******************************************************************************/
class GeneralIndex : public IndexImpl
{
@@ -144,9 +151,9 @@
std::vector<store::Item_t> theEmptyKeyNodes;
- bool theUntypedFlag;
+ csize theNumUntypedEntries;
- bool theMultiKeyFlag;
+ csize theNumMultiKeyNodes;
protected:
GeneralIndex(const store::Item_t& name, const store::IndexSpecification& spec);
@@ -161,27 +168,30 @@
store::SchemaTypeCode targetMap,
bool untyped);
- bool probeMap(
- const store::Item* key,
- store::SchemaTypeCode targetMap);
+ bool removeFromMap(
+ const store::Item_t& key,
+ const store::Item_t& node,
+ store::SchemaTypeCode targetMap,
+ bool untyped);
+
+ bool probeMap(const store::Item* key, store::SchemaTypeCode targetMap);
public:
- const XQPCollator* getCollator(ulong i) const;
-
- void setMultiKey() { theMultiKeyFlag = true; }
-
- ulong size() const;
+ const XQPCollator* getCollator(csize i) const;
+
+ void addMultiKey() { ++theNumMultiKeyNodes; }
+
+ void removeMultiKey() { assert(theNumMultiKeyNodes > 0); --theNumMultiKeyNodes; }
+
+ csize size() const;
bool insert(store::Item_t& key, store::Item_t& node);
- bool insert(store::IndexKey*& key, store::Item_t& value);
-
- virtual bool remove(const store::Item_t& key, const store::Item_t& item, bool all) = 0;
-
- virtual bool remove(
- const store::IndexKey* key,
- const store::Item_t& item,
- bool all = false) = 0;
+ bool insert(store::IndexKey*& key, store::Item_t& node);
+
+ bool remove(const store::IndexKey* key, const store::Item_t& node, bool all);
+
+ bool remove(const store::Item_t& key, const store::Item_t& node);
};
@@ -233,6 +243,11 @@
IndexMap*& targetMap,
bool untyped);
+ bool removeFromMap(
+ const store::Item_t& key,
+ const store::Item_t& node,
+ IndexMap* targetMap);
+
public:
GeneralHashIndex(
const store::Item_t& name,
@@ -242,17 +257,6 @@
Index::KeyIterator_t keys() const;
- bool remove(const store::Item_t& key, const store::Item_t& item, bool);
-
- bool remove(
- const store::IndexKey* key,
- const store::Item_t& item,
- bool all = false)
- {
- assert(key->size() == 1);
- return remove(((*key)[0]), item, all);
- }
-
void clear();
};
@@ -297,6 +301,11 @@
IndexMap*& targetMap,
bool untyped);
+ bool removeFromMap(
+ const store::Item_t& key,
+ const store::Item_t& item,
+ IndexMap* targetMap);
+
public:
GeneralTreeIndex(
const store::Item_t& qname,
@@ -306,17 +315,6 @@
Index::KeyIterator_t keys() const;
- bool remove(const store::Item_t& key, const store::Item_t& item, bool all);
-
- bool remove(
- const store::IndexKey* key,
- const store::Item_t& item,
- bool all = false)
- {
- assert(key->size() == 1);
- return remove(((*key)[0]), item, all);
- }
-
void clear();
};
=== modified file 'src/store/naive/simple_index_value.cpp'
--- src/store/naive/simple_index_value.cpp 2012-07-11 04:46:41 +0000
+++ src/store/naive/simple_index_value.cpp 2012-07-12 16:38:27 +0000
@@ -222,7 +222,7 @@
/******************************************************************************
********************************************************************************/
-const XQPCollator* ValueIndex::getCollator(ulong i) const
+const XQPCollator* ValueIndex::getCollator(csize i) const
{
return theCompFunction.getCollator(i);
}
@@ -345,7 +345,7 @@
/*******************************************************************************
********************************************************************************/
-ulong ValueHashIndex::size() const
+csize ValueHashIndex::size() const
{
return theMap.size();
}
@@ -429,9 +429,8 @@
const store::IndexKey* keyp = (*pos).first;
ValueIndexValue* valueSet = (*pos).second;
- ValueIndexValue::iterator valIte = std::find(valueSet->begin(),
- valueSet->end(),
- value);
+ ValueIndexValue::iterator valIte =
+ std::find(valueSet->begin(), valueSet->end(), value);
if (all)
{
@@ -642,10 +641,9 @@
/******************************************************************************
********************************************************************************/
-ulong ValueTreeIndex::size() const
+csize ValueTreeIndex::size() const
{
- assert(false);
- return 0;
+ return theMap.size();
}
@@ -736,9 +734,8 @@
const store::IndexKey* keyp = pos->first;
ValueIndexValue* valueSet = (*pos).second;
- ValueIndexValue::iterator valIte = std::find(valueSet->begin(),
- valueSet->end(),
- value);
+ ValueIndexValue::iterator valIte =
+ std::find(valueSet->begin(), valueSet->end(), value);
if (valIte != valueSet->end())
{
@@ -821,7 +818,7 @@
********************************************************************************/
void ProbeValueTreeIndexIterator::initBox()
{
- ulong numRanges = theBoxCond->numRanges();
+ csize numRanges = theBoxCond->numRanges();
assert(numRanges > 0 && numRanges <= theIndex->getNumColumns());
@@ -874,7 +871,7 @@
//
// Adjust the lower and/or upper bound index keys before probing the index.
//
- for (ulong i = 0; i < numRanges; i++)
+ for (csize i = 0; i < numRanges; i++)
{
const XQPCollator* collator = theIndex->getCollator(i);
=== modified file 'src/store/naive/simple_index_value.h'
--- src/store/naive/simple_index_value.h 2012-07-11 04:46:41 +0000
+++ src/store/naive/simple_index_value.h 2012-07-12 16:38:27 +0000
@@ -43,7 +43,7 @@
~ValueIndexCompareFunction();
- const XQPCollator* getCollator(ulong i) const { return theCollators[i]; }
+ const XQPCollator* getCollator(csize i) const { return theCollators[i]; }
uint32_t hash(const store::IndexKey* key) const;
@@ -64,7 +64,7 @@
class ValueIndexValue : public store::ItemVector
{
public:
- ValueIndexValue(ulong size = 0) : store::ItemVector(size) {}
+ ValueIndexValue(csize size = 0) : store::ItemVector(size) {}
};
@@ -86,16 +86,16 @@
virtual ~ValueIndex();
public:
- const XQPCollator* getCollator(ulong i) const;
+ const XQPCollator* getCollator(csize i) const;
virtual bool isTreeIndex() = 0;
virtual bool insert(store::IndexKey*& key, store::Item_t& item) = 0;
virtual bool remove(
- const store::IndexKey* key,
- const store::Item_t& item,
- bool all = false) = 0;
+ const store::IndexKey* key,
+ const store::Item_t& node,
+ bool all) = 0;
};
@@ -148,7 +148,7 @@
void clear();
- ulong size() const;
+ csize size() const;
Index::KeyIterator_t keys() const;
@@ -237,13 +237,13 @@
void clear();
- ulong size() const;
+ csize size() const;
Index::KeyIterator_t keys() const;
bool insert(store::IndexKey*& key, store::Item_t& item);
- bool remove(const store::IndexKey* key, const store::Item_t& item, bool all = false);
+ bool remove(const store::IndexKey* key, const store::Item_t& item, bool all);
};
=== modified file 'src/store/naive/simple_pul.cpp'
--- src/store/naive/simple_pul.cpp 2012-07-11 04:46:41 +0000
+++ src/store/naive/simple_pul.cpp 2012-07-12 16:38:27 +0000
@@ -24,6 +24,7 @@
#include "simple_store.h"
#include "collection.h"
#include "simple_index_value.h"
+#include "simple_index_general.h"
#include "simple_pul.h"
#include "pul_primitives.h"
#include "node_items.h"
@@ -2756,7 +2757,7 @@
modified by this pul, compute the index entries for I and D, and insert them
into the given deltas vector
********************************************************************************/
-void CollectionPul::computeIndexDeltas(std::vector<store::IndexDelta>& deltas)
+void CollectionPul::computeIndexDeltas(std::vector<IndexDeltaImpl>& deltas)
{
csize numIncrementalIndices = theIncrementalIndices.size();
@@ -2785,14 +2786,18 @@
for (csize idx = 0; idx < numIncrementalIndices; ++idx)
{
- store::IndexDelta::iterator ite;
- store::IndexDelta::iterator end;
- store::IndexDelta* delta;
- csize numApplied;
+ if (theIncrementalIndices[idx]->isGeneral())
+ {
+ ;
+ }
+ else
+ {
+ IndexDeltaImpl::ValueIterator ite;
+ IndexDeltaImpl::ValueIterator end;
+ store::IndexDelta::ValueDelta* delta;
+ csize numApplied;
- delta = &theInsertedDocsIndexDeltas[idx];
- if (delta)
- {
+ delta = &theInsertedDocsIndexDeltas[idx].getValueDelta();
numApplied = theNumInsertedDocsIndexDeltasApplied[idx];
ite = delta->begin() + numApplied;
end = delta->end();
@@ -2800,11 +2805,8 @@
{
delete (*ite).second;
}
- }
- delta = &theAfterIndexDeltas[idx];
- if (delta)
- {
+ delta = &theAfterIndexDeltas[idx].getValueDelta();
numApplied = theNumAfterIndexDeltasApplied[idx];
ite = delta->begin() + numApplied;
end = delta->end();
@@ -2812,33 +2814,15 @@
{
delete (*ite).second;
}
- }
-
- delta = &theDeletedDocsIndexDeltas[idx];
- if (delta)
- {
- ite = delta->begin();
- end = delta->end();
- for (; ite != end; ++ite)
- {
- delete (*ite).second;
- }
- }
-
- delta = &theBeforeIndexDeltas[idx];
- if (delta)
- {
- ite = delta->begin();
- end = delta->end();
- for (; ite != end; ++ite)
- {
- delete (*ite).second;
- }
+
+ theDeletedDocsIndexDeltas[idx].clear();
+
+ theBeforeIndexDeltas[idx].clear();
}
}
}
-
-
+
+
/*******************************************************************************
Refresh the incrementally maintained indexes.
********************************************************************************/
@@ -2846,91 +2830,278 @@
{
csize numIncrementalIndices = theIncrementalIndices.size();
- STORE_TRACE1("Refreshing indexes for collection "
- << (theCollection ?
- theCollection->getName()->getStringValue().c_str() :
- "NULL"));
-
- for (csize idx = 0; idx < numIncrementalIndices; ++idx)
- {
- ValueIndex* index = static_cast<ValueIndex*>(theIncrementalIndices[idx]);
-
- STORE_TRACE2("Index size before do = "
- << (!index->isTreeIndex() ? index->size() : 0));
-
- store::IndexDelta& beforeDelta = theBeforeIndexDeltas[idx];
- store::IndexDelta& afterDelta = theAfterIndexDeltas[idx];
- store::IndexDelta& deletedDelta = theDeletedDocsIndexDeltas[idx];
- store::IndexDelta& insertedDelta = theInsertedDocsIndexDeltas[idx];
-
- csize& numBeforeApplied = theNumBeforeIndexDeltasApplied[idx];
- csize& numAfterApplied = theNumAfterIndexDeltasApplied[idx];
- csize& numDeletedApplied = theNumDeletedDocsIndexDeltasApplied[idx];
- csize& numInsertedApplied = theNumInsertedDocsIndexDeltasApplied[idx];
-
- store::IndexKey* key;
- store::Item_t node;
-
- store::IndexDelta::iterator ite;
- store::IndexDelta::iterator end;
-
- ite = beforeDelta.begin();
- end = beforeDelta.end();
- for (; ite != end; ++ite, ++numBeforeApplied)
- {
- index->remove((*ite).second, (*ite).first);
- }
-
- ite = afterDelta.begin();
- end = afterDelta.end();
- for (; ite != end; ++ite, ++numAfterApplied)
- {
- node = (*ite).first;
- key = (*ite).second;
-
- // If the index had its own key obj already, delete the key obj that was
- // allocated during the delta creation.
- if (index->insert((*ite).second, node))
- {
- assert(key != (*ite).second);
- delete key;
- }
- }
-
- STORE_TRACE2("deleted-delta size = " << deletedDelta.size());
-
- ite = deletedDelta.begin();
- end = deletedDelta.end();
- for (; ite != end; ++ite, ++numDeletedApplied)
- {
- index->remove((*ite).second, (*ite).first);
- }
-
- STORE_TRACE2("inserted-delta size = " << insertedDelta.size());
-
- ite = insertedDelta.begin();
- end = insertedDelta.end();
- for (; ite != end; ++ite, ++numInsertedApplied)
- {
- node = (*ite).first;
- key = (*ite).second;
-
- if (index->insert((*ite).second, node))
- {
- assert(key != (*ite).second);
- delete key;
- }
- }
-
- STORE_TRACE2("Index size after do = "
- << (!index->isTreeIndex() ? index->size() : 0));
- }
-
- STORE_TRACE1("Refreshed indexes for collection "
- << (theCollection ?
- theCollection->getName()->getStringValue().c_str() :
- "NULL")
- << std::endl);
+ if (numIncrementalIndices > 0)
+ {
+ assert(theCollection);
+
+ STORE_TRACE1("Refreshing indexes for collection "
+ << theCollection->getName()->getStringValue().c_str());
+
+ for (csize idx = 0; idx < numIncrementalIndices; ++idx)
+ {
+ if (theIncrementalIndices[idx]->isGeneral())
+ refreshGeneralIndex(idx);
+ else
+ refreshValueIndex(idx);
+ }
+
+ STORE_TRACE1("Refreshed indexes for collection "
+ << theCollection->getName()->getStringValue().c_str()
+ << std::endl);
+ }
+}
+
+
+
+/*******************************************************************************
+
+********************************************************************************/
+void CollectionPul::refreshValueIndex(csize idx)
+{
+ ValueIndex* index = static_cast<ValueIndex*>(theIncrementalIndices[idx]);
+
+ STORE_TRACE2("Index size before do = " << index->size());
+
+ store::IndexDelta::ValueDelta&
+ beforeDelta = theBeforeIndexDeltas[idx].getValueDelta();
+ store::IndexDelta::ValueDelta&
+ afterDelta = theAfterIndexDeltas[idx].getValueDelta();
+ store::IndexDelta::ValueDelta&
+ deletedDelta = theDeletedDocsIndexDeltas[idx].getValueDelta();
+ store::IndexDelta::ValueDelta&
+ insertedDelta = theInsertedDocsIndexDeltas[idx].getValueDelta();
+
+ csize& numBeforeApplied = theNumBeforeIndexDeltasApplied[idx];
+ csize& numAfterApplied = theNumAfterIndexDeltasApplied[idx];
+ csize& numDeletedApplied = theNumDeletedDocsIndexDeltasApplied[idx];
+ csize& numInsertedApplied = theNumInsertedDocsIndexDeltasApplied[idx];
+
+ store::IndexKey* key;
+ store::Item_t node;
+
+ IndexDeltaImpl::ValueIterator ite;
+ IndexDeltaImpl::ValueIterator end;
+
+ ite = beforeDelta.begin();
+ end = beforeDelta.end();
+ for (; ite != end; ++ite, ++numBeforeApplied)
+ {
+ index->remove((*ite).second, (*ite).first, false);
+ }
+
+ ite = afterDelta.begin();
+ end = afterDelta.end();
+ for (; ite != end; ++ite, ++numAfterApplied)
+ {
+ node = (*ite).first;
+ key = (*ite).second;
+
+ // If the index had its own key obj already, delete the key obj that was
+ // allocated during the delta creation.
+ if (index->insert((*ite).second, node))
+ {
+ assert(key != (*ite).second);
+ delete key;
+ }
+ }
+
+ STORE_TRACE2("deleted-delta size = " << deletedDelta.size());
+
+ ite = deletedDelta.begin();
+ end = deletedDelta.end();
+ for (; ite != end; ++ite, ++numDeletedApplied)
+ {
+ index->remove((*ite).second, (*ite).first, false);
+ }
+
+ STORE_TRACE2("inserted-delta size = " << insertedDelta.size());
+
+ ite = insertedDelta.begin();
+ end = insertedDelta.end();
+ for (; ite != end; ++ite, ++numInsertedApplied)
+ {
+ node = (*ite).first;
+ key = (*ite).second;
+
+ if (index->insert((*ite).second, node))
+ {
+ assert(key != (*ite).second);
+ delete key;
+ }
+ }
+
+ STORE_TRACE2("Index size after do = " << index->size());
+}
+
+
+/*******************************************************************************
+
+********************************************************************************/
+void CollectionPul::refreshGeneralIndex(csize idx)
+{
+ GeneralIndex* index = static_cast<GeneralIndex*>(theIncrementalIndices[idx]);
+
+ store::IndexDelta::GeneralDelta&
+ beforeDelta = theBeforeIndexDeltas[idx].getGeneralDelta();
+ store::IndexDelta::GeneralDelta&
+ afterDelta = theAfterIndexDeltas[idx].getGeneralDelta();
+ store::IndexDelta::GeneralDelta&
+ deletedDelta = theDeletedDocsIndexDeltas[idx].getGeneralDelta();
+ store::IndexDelta::GeneralDelta&
+ insertedDelta = theInsertedDocsIndexDeltas[idx].getGeneralDelta();
+
+ csize& numBeforeApplied = theNumBeforeIndexDeltasApplied[idx];
+ csize& numAfterApplied = theNumAfterIndexDeltasApplied[idx];
+ csize& numDeletedApplied = theNumDeletedDocsIndexDeltasApplied[idx];
+ csize& numInsertedApplied = theNumInsertedDocsIndexDeltasApplied[idx];
+
+ store::Item_t key;
+ store::Item_t node;
+
+ IndexDeltaImpl::GeneralIterator ite;
+ IndexDeltaImpl::GeneralIterator end;
+ std::vector<store::Item_t>::iterator keyIte;
+ std::vector<store::Item_t>::iterator keyEnd;
+
+ STORE_TRACE2("before-delta size = " << deletedDelta.size());
+
+ ite = beforeDelta.begin();
+ end = beforeDelta.end();
+
+ while (ite != end)
+ {
+ store::Item* nodep = (*ite).first.getp();
+
+ index->remove((*ite).second, (*ite).first);
+ ++numBeforeApplied;
+ ++ite;
+
+ if (ite != end && (*ite).first.getp() == nodep)
+ {
+ index->remove((*ite).second, (*ite).first);
+ ++numDeletedApplied;
+ ++ite;
+
+ // Call removeMultiKey() after removing the 2nd key for the same node.
+ // We do this to make undo easier.
+ index->removeMultiKey();
+
+ while (ite != end && (*ite).first.getp() == nodep)
+ {
+ index->remove((*ite).second, (*ite).first);
+ ++numBeforeApplied;
+ ++ite;
+ }
+ }
+ }
+
+ STORE_TRACE2("after-delta size = " << deletedDelta.size());
+
+ ite = afterDelta.begin();
+ end = afterDelta.end();
+
+ while (ite != end)
+ {
+ node = (*ite).first;
+ key = (*ite).second;
+ store::Item* nodep = node.getp();
+
+ index->insert(key, node);
+ ++numAfterApplied;
+ ++ite;
+
+ if (ite != end && (*ite).first.getp() == nodep)
+ {
+ node = (*ite).first;
+ key = (*ite).second;
+
+ index->insert(key, node);
+ ++numAfterApplied;
+ ++ite;
+
+ index->addMultiKey();
+
+ while (ite != end && (*ite).first.getp() == nodep)
+ {
+ node = (*ite).first;
+ key = (*ite).second;
+
+ index->insert(key, node);
+ ++numAfterApplied;
+ ++ite;
+ }
+ }
+ }
+
+ STORE_TRACE2("deleted-delta size = " << deletedDelta.size());
+
+ ite = deletedDelta.begin();
+ end = deletedDelta.end();
+
+ while (ite != end)
+ {
+ store::Item* nodep = (*ite).first.getp();
+
+ index->remove((*ite).second, (*ite).first);
+ ++numDeletedApplied;
+ ++ite;
+
+ if (ite != end && (*ite).first.getp() == nodep)
+ {
+ index->remove((*ite).second, (*ite).first);
+ ++numDeletedApplied;
+ ++ite;
+
+ // Call removeMultiKey() after removing the 2nd key for the same node.
+ // We do this to make undo easier.
+ index->removeMultiKey();
+
+ while (ite != end && (*ite).first.getp() == nodep)
+ {
+ index->remove((*ite).second, (*ite).first);
+ ++numDeletedApplied;
+ ++ite;
+ }
+ }
+ }
+
+ STORE_TRACE2("inserted-delta size = " << insertedDelta.size());
+
+ ite = insertedDelta.begin();
+ end = insertedDelta.end();
+
+ while (ite != end)
+ {
+ node = (*ite).first;
+ key = (*ite).second;
+ store::Item* nodep = node.getp();
+
+ index->insert(key, node);
+ ++numInsertedApplied;
+ ++ite;
+
+ if (ite != end && (*ite).first.getp() == nodep)
+ {
+ node = (*ite).first;
+ key = (*ite).second;
+
+ index->insert(key, node);
+ ++numInsertedApplied;
+ ++ite;
+
+ index->addMultiKey();
+
+ while (ite != end && (*ite).first.getp() == nodep)
+ {
+ node = (*ite).first;
+ key = (*ite).second;
+
+ index->insert(key, node);
+ ++numInsertedApplied;
+ ++ite;
+ }
+ }
+ }
}
@@ -2949,70 +3120,10 @@
for (csize idx = 0; idx < numIncrementalIndices; ++idx)
{
- ValueIndex* index = static_cast<ValueIndex*>(theIncrementalIndices[idx]);
-
- STORE_TRACE2("Index size before undo = "
- << (!index->isTreeIndex() ? index->size() : 0));
-
- store::IndexDelta& beforeDelta = theBeforeIndexDeltas[idx];
- store::IndexDelta& afterDelta = theAfterIndexDeltas[idx];
- store::IndexDelta& insertedDelta = theInsertedDocsIndexDeltas[idx];
- store::IndexDelta& deletedDelta = theDeletedDocsIndexDeltas[idx];
-
- csize numBeforeApplied = theNumBeforeIndexDeltasApplied[idx];
- csize numAfterApplied = theNumAfterIndexDeltasApplied[idx];
- csize numDeletedApplied = theNumDeletedDocsIndexDeltasApplied[idx];
- csize numInsertedApplied = theNumInsertedDocsIndexDeltasApplied[idx];
-
- store::IndexDelta::reverse_iterator ite;
- store::IndexDelta::reverse_iterator end;
-
- ite = insertedDelta.rbegin() + (insertedDelta.size() - numInsertedApplied);
- end = insertedDelta.rend();
- for (; ite != end; ++ite)
- {
- index->remove((*ite).second, (*ite).first);
- }
-
- ite = deletedDelta.rbegin() + (deletedDelta.size() - numDeletedApplied);
- end = deletedDelta.rend();
- for (; ite != end; ++ite)
- {
- store::IndexKey* key = (*ite).second;
-
- // If the index takes ownership of the key obj, set the key ptr to null
- // so that the key obj will not be deleted during cleanIndexDeltas().
- if (!index->insert(key, (*ite).first))
- {
- assert(key == (*ite).second);
- (*ite).second = NULL;
- }
- }
-
- ite = afterDelta.rbegin() + (afterDelta.size() - numAfterApplied);
- end = afterDelta.rend();
- for (; ite != end; ++ite)
- {
- index->remove((*ite).second, (*ite).first);
- }
-
- ite = beforeDelta.rbegin() + (beforeDelta.size() - numBeforeApplied);
- end = beforeDelta.rend();
- for (; ite != end; ++ite)
- {
- store::IndexKey* key = (*ite).second;
-
- // If the index takes ownership of the key obj, set the key ptr to null
- // so that the key obj will not be deleted during cleanIndexDeltas().
- if (!index->insert(key, (*ite).first))
- {
- assert(key == (*ite).second);
- (*ite).second = NULL;
- }
- }
-
- STORE_TRACE2("Index size after undo = "
- << (!index->isTreeIndex() ? index->size() : 0));
+ if (theIncrementalIndices[idx]->isGeneral())
+ undoGeneralIndexRefresh(idx);
+ else
+ undoValueIndexRefresh(idx);
}
STORE_TRACE1("Reverted indexes for collection "
@@ -3024,6 +3135,208 @@
/*******************************************************************************
+
+********************************************************************************/
+void CollectionPul::undoValueIndexRefresh(csize idx)
+{
+ ValueIndex* index = static_cast<ValueIndex*>(theIncrementalIndices[idx]);
+
+ STORE_TRACE2("Index size before undo = " << index->size());
+
+ store::IndexDelta::ValueDelta&
+ beforeDelta = theBeforeIndexDeltas[idx].getValueDelta();
+ store::IndexDelta::ValueDelta&
+ afterDelta = theAfterIndexDeltas[idx].getValueDelta();
+ store::IndexDelta::ValueDelta&
+ insertedDelta = theInsertedDocsIndexDeltas[idx].getValueDelta();
+ store::IndexDelta::ValueDelta&
+ deletedDelta = theDeletedDocsIndexDeltas[idx].getValueDelta();
+
+ csize numBeforeApplied = theNumBeforeIndexDeltasApplied[idx];
+ csize numAfterApplied = theNumAfterIndexDeltasApplied[idx];
+ csize numDeletedApplied = theNumDeletedDocsIndexDeltasApplied[idx];
+ csize numInsertedApplied = theNumInsertedDocsIndexDeltasApplied[idx];
+
+ IndexDeltaImpl::ReverseValueIterator ite;
+ IndexDeltaImpl::ReverseValueIterator end;
+
+ ite = insertedDelta.rbegin() + (insertedDelta.size() - numInsertedApplied);
+ end = insertedDelta.rend();
+ for (; ite != end; ++ite)
+ {
+ index->remove((*ite).second, (*ite).first, false);
+ }
+
+ ite = deletedDelta.rbegin() + (deletedDelta.size() - numDeletedApplied);
+ end = deletedDelta.rend();
+ for (; ite != end; ++ite)
+ {
+ store::IndexKey* key = (*ite).second;
+
+ // If the index takes ownership of the key obj, set the key ptr to null
+ // so that the key obj will not be deleted during cleanIndexDeltas().
+ if (!index->insert(key, (*ite).first))
+ {
+ assert(key == (*ite).second);
+ (*ite).second = NULL;
+ }
+ }
+
+ ite = afterDelta.rbegin() + (afterDelta.size() - numAfterApplied);
+ end = afterDelta.rend();
+ for (; ite != end; ++ite)
+ {
+ index->remove((*ite).second, (*ite).first, false);
+ }
+
+ ite = beforeDelta.rbegin() + (beforeDelta.size() - numBeforeApplied);
+ end = beforeDelta.rend();
+ for (; ite != end; ++ite)
+ {
+ store::IndexKey* key = (*ite).second;
+
+ // If the index takes ownership of the key obj, set the key ptr to null
+ // so that the key obj will not be deleted during cleanIndexDeltas().
+ if (!index->insert(key, (*ite).first))
+ {
+ assert(key == (*ite).second);
+ (*ite).second = NULL;
+ }
+ }
+
+ STORE_TRACE2("Index size after undo = " << index->size());
+}
+
+
+/*******************************************************************************
+
+********************************************************************************/
+void CollectionPul::undoGeneralIndexRefresh(csize idx)
+{
+ GeneralIndex* index = static_cast<GeneralIndex*>(theIncrementalIndices[idx]);
+
+ store::IndexDelta::GeneralDelta&
+ beforeDelta = theBeforeIndexDeltas[idx].getGeneralDelta();
+ store::IndexDelta::GeneralDelta&
+ afterDelta = theAfterIndexDeltas[idx].getGeneralDelta();
+ store::IndexDelta::GeneralDelta&
+ insertedDelta = theInsertedDocsIndexDeltas[idx].getGeneralDelta();
+ store::IndexDelta::GeneralDelta&
+ deletedDelta = theDeletedDocsIndexDeltas[idx].getGeneralDelta();
+
+ csize numBeforeApplied = theNumBeforeIndexDeltasApplied[idx];
+ csize numAfterApplied = theNumAfterIndexDeltasApplied[idx];
+ csize numDeletedApplied = theNumDeletedDocsIndexDeltasApplied[idx];
+ csize numInsertedApplied = theNumInsertedDocsIndexDeltasApplied[idx];
+
+ IndexDeltaImpl::ReverseGeneralIterator ite;
+ IndexDeltaImpl::ReverseGeneralIterator end;
+ std::vector<store::Item_t>::reverse_iterator keyIte;
+ std::vector<store::Item_t>::reverse_iterator keyEnd;
+
+ // Inserted delta
+
+ ite = insertedDelta.rbegin() + (insertedDelta.size() - numInsertedApplied);
+ end = insertedDelta.rend();
+
+ while (ite != end)
+ {
+ store::Item* nodep = (*ite).first.getp();
+
+ index->remove((*ite).second, (*ite).first);
+ ++ite;
+
+ if (ite != end && (*ite).first.getp() == nodep)
+ {
+ index->removeMultiKey();
+
+ do
+ {
+ index->remove((*ite).second, (*ite).first);
+ ++ite;
+ }
+ while (ite != end && (*ite).first.getp() == nodep);
+ }
+ }
+
+ // Deleted delta
+
+ ite = deletedDelta.rbegin() + (deletedDelta.size() - numDeletedApplied);
+ end = deletedDelta.rend();
+
+ while (ite != end)
+ {
+ store::Item* nodep = (*ite).first.getp();
+
+ index->insert((*ite).second, (*ite).first);
+ ++ite;
+
+ if (ite != end && (*ite).first.getp() == nodep)
+ {
+ index->addMultiKey();
+
+ do
+ {
+ index->insert((*ite).second, (*ite).first);
+ ++ite;
+ }
+ while (ite != end && (*ite).first.getp() == nodep);
+ }
+ }
+
+ // After delta
+
+ ite = afterDelta.rbegin() + (afterDelta.size() - numAfterApplied);
+ end = afterDelta.rend();
+
+ while (ite != end)
+ {
+ store::Item* nodep = (*ite).first.getp();
+
+ index->remove((*ite).second, (*ite).first);
+ ++ite;
+
+ if (ite != end && (*ite).first.getp() == nodep)
+ {
+ index->removeMultiKey();
+
+ do
+ {
+ index->remove((*ite).second, (*ite).first);
+ ++ite;
+ }
+ while (ite != end && (*ite).first.getp() == nodep);
+ }
+ }
+
+ // Before delta
+
+ ite = beforeDelta.rbegin() + (beforeDelta.size() - numBeforeApplied);
+ end = beforeDelta.rend();
+
+ while (ite != end)
+ {
+ store::Item* nodep = (*ite).first.getp();
+
+ index->insert((*ite).second, (*ite).first);
+ ++ite;
+
+ if (ite != end && (*ite).first.getp() == nodep)
+ {
+ index->addMultiKey();
+
+ do
+ {
+ index->insert((*ite).second, (*ite).first);
+ ++ite;
+ }
+ while (ite != end && (*ite).first.getp() == nodep);
+ }
+ }
+}
+
+
+/*******************************************************************************
The method is called from CollectionPul::finalizeUpdates()
********************************************************************************/
void CollectionPul::truncateIndexes()
@@ -3173,10 +3486,10 @@
theMergeList.push_back(mergeInfo);
(void)GET_NODE_FACTORY().createTextNode(node->getTree(),
- node,
- false,
- i,
- newContent);
+ node,
+ false,
+ i,
+ newContent);
}
}
}
@@ -3215,16 +3528,12 @@
}
catch (const std::exception& e)
{
-#ifndef NDEBUG
- std::cerr << "Exception thrown during pul::applyUpdates: " << e.what() << std::endl;
-#endif
+ //std::cerr << "Exception thrown during pul::applyUpdates: " << e.what() << std::endl;
throw;
}
catch (...)
{
-#ifndef NDEBUG
- std::cerr << "Exception thrown during pul::applyUpdates " << std::endl;
-#endif
+ //std::cerr << "Exception thrown during pul::applyUpdates " << std::endl;
throw;
}
=== modified file 'src/store/naive/simple_pul.h'
--- src/store/naive/simple_pul.h 2012-07-11 04:46:41 +0000
+++ src/store/naive/simple_pul.h 2012-07-12 16:38:27 +0000
@@ -21,7 +21,7 @@
#include "shared_types.h"
#include "store/api/pul.h"
-#include "store/api/index.h"
+#include "store/naive/simple_index.h"
#include "zorbautils/hashfun.h"
#include "zorbautils/hashmap.h"
@@ -202,10 +202,10 @@
std::vector<IndexEntryCreator_t> theIndexEntryCreators;
- std::vector<store::IndexDelta> theBeforeIndexDeltas;
- std::vector<store::IndexDelta> theAfterIndexDeltas;
- std::vector<store::IndexDelta> theInsertedDocsIndexDeltas;
- std::vector<store::IndexDelta> theDeletedDocsIndexDeltas;
+ std::vector<IndexDeltaImpl> theBeforeIndexDeltas;
+ std::vector<IndexDeltaImpl> theAfterIndexDeltas;
+ std::vector<IndexDeltaImpl> theInsertedDocsIndexDeltas;
+ std::vector<IndexDeltaImpl> theDeletedDocsIndexDeltas;
#ifdef ZORBA_WITH_JSON
// jsoniq primitives
@@ -251,10 +251,18 @@
protected:
void switchPulInPrimitivesList(std::vector<UpdatePrimitive*>& list);
- void computeIndexDeltas(std::vector<store::IndexDelta>& deltas);
+ void computeIndexDeltas(std::vector<IndexDeltaImpl>& deltas);
void cleanIndexDeltas();
+ void refreshValueIndex(csize idx);
+
+ void refreshGeneralIndex(csize idx);
+
+ void undoValueIndexRefresh(csize idx);
+
+ void undoGeneralIndexRefresh(csize idx);
+
void truncateIndexes();
void undoRefreshIndexes();
=== modified file 'src/store/naive/store.cpp'
--- src/store/naive/store.cpp 2012-07-11 04:46:41 +0000
+++ src/store/naive/store.cpp 2012-07-12 16:38:27 +0000
@@ -672,7 +672,7 @@
// Current domain node has at least 2 keys. So insert them in the index.
// Note: we have to copy the domainNode rchandle because index->insert()
// will transfer the given node.
- index->setMultiKey();
+ index->addMultiKey();
store::Item_t node = domainNode;
index->insert(firstKeyItem, node);
@@ -724,10 +724,8 @@
if (!theIndices.get(non_const_items, index))
{
- throw ZORBA_EXCEPTION(
- zerr::ZSTR0002_INDEX_DOES_NOT_EXIST,
- ERROR_PARAMS( qname->getStringValue() )
- );
+ throw ZORBA_EXCEPTION(zerr::ZSTR0002_INDEX_DOES_NOT_EXIST,
+ ERROR_PARAMS(qname->getStringValue()));
}
deleteIndex(qname);
=== modified file 'src/store/util/item_vector.h'
--- src/store/util/item_vector.h 2012-07-11 04:46:41 +0000
+++ src/store/util/item_vector.h 2012-07-12 16:38:27 +0000
@@ -35,25 +35,25 @@
std::vector<Item_t> theItems;
public:
- ItemVector(ulong size = 0) : theItems(size) {}
+ ItemVector(csize size = 0) : theItems(size) {}
bool empty() const { return theItems.empty(); }
- ulong size() const { return (ulong)theItems.size(); }
+ csize size() const { return theItems.size(); }
- void resize(ulong newSize) { theItems.resize(newSize); }
+ void resize(csize newSize) { theItems.resize(newSize); }
void clear() { theItems.clear(); }
- const Item_t& operator[](ulong i) const { return theItems[i]; }
+ const Item_t& operator[](csize i) const { return theItems[i]; }
- Item_t& operator[](ulong i) { return theItems[i]; }
+ Item_t& operator[](csize i) { return theItems[i]; }
void push_back(const Item_t& item) { theItems.push_back(item); }
void transfer_back(Item_t& item)
{
- ulong size_ = size();
+ csize size_ = size();
theItems.resize(size_+1);
theItems[size_].transfer(item);
}
=== added file 'test/rbkt/ExpQueryResults/zorba/index/auctions2u.xml.res'
--- test/rbkt/ExpQueryResults/zorba/index/auctions2u.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/index/auctions2u.xml.res 2012-07-12 16:38:27 +0000
@@ -0,0 +1,306 @@
+
+TEST 1:
+
+<person id="person1"><watches>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction4"/>
+<watch open_auction="open_auction5"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction9"/>
+<watch open_auction="open_auction0"/>
+</watches></person><person id="person2"><watches>
+<watch open_auction="open_auction0"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction4"/>
+</watches></person><person id="person3"><watches>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction10"/>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction5"/>
+</watches></person><person id="person7"><watches>
+<watch open_auction="open_auction10"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction10"/>
+</watches></person><person id="person8"><watches>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction2"/>
+</watches></person><person id="person15"><watches>
+<watch open_auction="open_auction9"/>
+<watch open_auction="open_auction1"/>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction8"/>
+</watches></person><person id="person21"><watches>
+<watch open_auction="open_auction3"/>
+<watch open_auction="open_auction9"/>
+<watch open_auction="open_auction0"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction2"/>
+</watches></person><person id="person23"><watches>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction4"/>
+</watches></person>
+
+TEST 2:
+
+<person id="person1"><watches>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction4"/>
+<watch open_auction="open_auction5"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction9"/>
+<watch open_auction="open_auction0"/>
+</watches></person><person id="person2"><watches>
+<watch open_auction="open_auction0"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction4"/>
+</watches></person><person id="person3"><watches>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction10"/>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction5"/>
+</watches></person><person id="person7"><watches>
+<watch open_auction="open_auction10"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction10"/>
+</watches></person><person id="person8"><watches>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction2"/>
+</watches></person><person id="person15"><watches>
+<watch open_auction="open_auction9"/>
+<watch open_auction="open_auction1"/>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction8"/>
+</watches></person><person id="person21"><watches>
+<watch open_auction="open_auction3"/>
+<watch open_auction="open_auction9"/>
+<watch open_auction="open_auction0"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction2"/>
+</watches></person><person id="person23"><watches>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction4"/>
+</watches></person><person id="person203"><watches><watch open_auction="open_auction6"/><watch open_auction="open_auction2"/><watch open_auction="open_auction6"/><watch open_auction="open_auction5"/></watches></person>
+
+TEST 3:
+
+<person id="person1"><watches>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction4"/>
+<watch open_auction="open_auction5"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction9"/>
+<watch open_auction="open_auction0"/>
+</watches></person><person id="person2"><watches>
+<watch open_auction="open_auction0"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction4"/>
+</watches></person><person id="person3"><watches>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction10"/>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction5"/>
+</watches></person><person id="person7"><watches>
+<watch open_auction="open_auction10"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction10"/>
+</watches></person><person id="person8"><watches>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction2"/>
+</watches></person><person id="person15"><watches>
+<watch open_auction="open_auction9"/>
+<watch open_auction="open_auction1"/>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction8"/>
+</watches></person><person id="person21"><watches>
+<watch open_auction="open_auction3"/>
+<watch open_auction="open_auction9"/>
+<watch open_auction="open_auction0"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction2"/>
+</watches></person><person id="person23"><watches>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction4"/>
+</watches></person>
+
+TEST 4:
+
+<person id="person1"><watches>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction4"/>
+<watch open_auction="open_auction5"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction9"/>
+<watch open_auction="open_auction0"/>
+</watches></person><person id="person2"><watches>
+<watch open_auction="open_auction0"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction4"/>
+</watches></person><person id="person3"><watches>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction10"/>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction5"/>
+</watches></person><person id="person7"><watches>
+<watch open_auction="open_auction10"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction10"/>
+</watches></person><person id="person8"><watches>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction2"/>
+</watches></person><person id="person15"><watches>
+<watch open_auction="open_auction9"/>
+<watch open_auction="open_auction1"/>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction8"/>
+</watches></person><person id="person21"><watches>
+<watch open_auction="open_auction3"/>
+<watch open_auction="open_auction9"/>
+<watch open_auction="open_auction0"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction2"/>
+</watches></person><person id="person23"><watches>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction4"/>
+</watches></person><person id="person205"><watches><watch open_auction="open_auction6"/><watch open_auction="open_auction2"/><watch open_auction="open_auction6"/><watch open_auction="open_auction5"/></watches></person>
+
+TEST 5:
+
+<person id="person1"><watches>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction4"/>
+<watch open_auction="open_auction5"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction9"/>
+<watch open_auction="open_auction0"/>
+</watches></person><person id="person2"><watches>
+<watch open_auction="open_auction0"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction4"/>
+</watches></person><person id="person3"><watches>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction10"/>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction5"/>
+</watches></person><person id="person7"><watches>
+<watch open_auction="open_auction10"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction10"/>
+</watches></person><person id="person8"><watches>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction2"/>
+</watches></person><person id="person15"><watches>
+<watch open_auction="open_auction9"/>
+<watch open_auction="open_auction1"/>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction8"/>
+</watches></person><person id="person21"><watches>
+<watch open_auction="open_auction3"/>
+<watch open_auction="open_auction9"/>
+<watch open_auction="open_auction0"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction2"/>
+</watches></person><person id="person23"><watches>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction4"/>
+</watches></person><person id="person205"><watches><watch open_auction="open_auction6"/><watch open_auction="open_auction2"/><watch open_auction="open_auction6"/><watch open_auction="open_auction5"/><watch open_auction="open_auction8"/></watches></person><person id="person203"><watches><watch open_auction="open_auction6"/><watch open_auction="open_auction2"/><watch open_auction="open_auction6"/><watch open_auction="open_auction5"/></watches></person>
+
+TEST 6 (undo without do):
+
+<exception>err:XUDY0021 : updates violate constraint</exception><person id="person1"><watches>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction4"/>
+<watch open_auction="open_auction5"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction9"/>
+<watch open_auction="open_auction0"/>
+</watches></person><person id="person2"><watches>
+<watch open_auction="open_auction0"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction4"/>
+</watches></person><person id="person3"><watches>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction10"/>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction5"/>
+</watches></person><person id="person7"><watches>
+<watch open_auction="open_auction10"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction10"/>
+</watches></person><person id="person8"><watches>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction2"/>
+</watches></person><person id="person15"><watches>
+<watch open_auction="open_auction9"/>
+<watch open_auction="open_auction1"/>
+<watch open_auction="open_auction2"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction8"/>
+<watch open_auction="open_auction8"/>
+</watches></person><person id="person21"><watches>
+<watch open_auction="open_auction3"/>
+<watch open_auction="open_auction9"/>
+<watch open_auction="open_auction0"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction2"/>
+</watches></person><person id="person23"><watches>
+<watch open_auction="open_auction6"/>
+<watch open_auction="open_auction4"/>
+</watches></person><person id="person205"><watches><watch open_auction="open_auction6"/><watch open_auction="open_auction2"/><watch open_auction="open_auction6"/><watch open_auction="open_auction5"/><watch open_auction="open_auction8"/></watches></person><person id="person203"><watches><watch open_auction="open_auction6"/><watch open_auction="open_auction2"/><watch open_auction="open_auction6"/><watch open_auction="open_auction5"/></watches></person>
=== added file 'test/rbkt/ExpQueryResults/zorba/index/numbers2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/index/numbers2.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/index/numbers2.xml.res 2012-07-12 16:38:27 +0000
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+xs:long
+
+TEST 1:
+
+<exception>err:XPTY0004 : node with untyped key value found during probe on index "num:idx-g-h-untyped"</exception>
+
+TEST 2:
+
+
+ <s:integer xmlns:s="http://www.zorba-xquery.com/numbers.xsd";>2</s:integer>
+
+TEST 3:
+
+<s:integer xmlns:s="http://www.zorba-xquery.com/numbers.xsd";>2</s:integer><untyped>2</untyped>
+<s:integer xmlns:s="http://www.zorba-xquery.com/numbers.xsd";>2</s:integer><untyped>2</untyped>
+<s:integer xmlns:s="http://www.zorba-xquery.com/numbers.xsd";>2</s:integer><untyped>2</untyped>
+<s:integer xmlns:s="http://www.zorba-xquery.com/numbers.xsd";>2</s:integer><untyped>2</untyped>
+<untyped>2</untyped>
=== modified file 'test/rbkt/ExpQueryResults/zorba/index/undo2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/index/undo2.xml.res 2012-04-22 21:55:56 +0000
+++ test/rbkt/ExpQueryResults/zorba/index/undo2.xml.res 2012-07-12 16:38:27 +0000
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
-zerr:ZDDY0024<person id="1" key="5"/><person id="2" key="5"/><person id="1" key="5"/><person id="2" key="5"/>
+<exception>zerr:ZDDY0024 : "auctions:PersonId2": index uniqueness violation</exception><person id="1" key="5"/><person id="2" key="5"/><person id="1" key="5"/><person id="2" key="5"/>
=== added file 'test/rbkt/ExpQueryResults/zorba/index/undo4.xml.res'
--- test/rbkt/ExpQueryResults/zorba/index/undo4.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/index/undo4.xml.res 2012-07-12 16:38:27 +0000
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<person id="1"><car make="honda"/><car make="vw"/></person><person id="2"><car make="vw"/></person>
+
+TEST 0:
+
+<exception>err:XPTY0004 : node with more than one key value found during probe on index "f:PersonCars"</exception>
+
+TEST 1:
+
+<exception>zerr:ZDDY0024 : "f:PersonId": index uniqueness violation</exception>
+<person id="1"><car make="honda"/><car make="vw"/></person><person id="2"><car make="vw"/></person>
+
+TEST 2:
+
+<exception>zerr:ZDDY0024 : "f:PersonId": index uniqueness violation</exception>
+<person id="1"><car make="honda"/><car make="vw"/></person><person id="2"><car make="vw"/></person>
+
+TEST 3:
+
+<exception>zerr:ZDDY0024 : "f:PersonId": index uniqueness violation</exception>
+<person id="1"><car make="honda"/><car make="vw"/></person><person id="2"><car make="vw"/></person>
+
+TEST 4:
+
+<person id="1"><car make="vw"/></person><person id="2"><car make="vw"/></person>
=== modified file 'test/rbkt/Queries/zorba/index/auctions1u.xq'
--- test/rbkt/Queries/zorba/index/auctions1u.xq 2012-07-11 04:46:41 +0000
+++ test/rbkt/Queries/zorba/index/auctions1u.xq 2012-07-12 16:38:27 +0000
@@ -22,6 +22,8 @@
as first into
dml:collection($auctions:auctions)/site/people;
+ fn:trace("HELLO WORLD", "");
+
index_dml:refresh-index($emp-id);
(: don't refresh the emp-city index manually because it's done automatically :)
}
=== added file 'test/rbkt/Queries/zorba/index/auctions2u.xq'
--- test/rbkt/Queries/zorba/index/auctions2u.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/index/auctions2u.xq 2012-07-12 16:38:27 +0000
@@ -0,0 +1,175 @@
+import module namespace ddl = "http://www.zorba-xquery.com/modules/store/static/collections/ddl";;
+import module namespace dml = "http://www.zorba-xquery.com/modules/store/static/collections/dml";;
+import module namespace index_ddl = "http://www.zorba-xquery.com/modules/store/static/indexes/ddl";;
+import module namespace index_dml = "http://www.zorba-xquery.com/modules/store/static/indexes/dml";;
+
+import module namespace auctions = "http://www.w3.org/TestModules/auctions"; at
+ "auctions_module1.xqlib";
+
+declare namespace err = "http://www.w3.org/2005/xqt-errors";;
+
+
+variable $person :=
+ <doc>
+ <site>
+ <people>
+ <person id="person203">
+ <name>Ewing Andrade</name>
+ <emailaddress>mailto:Andrade@xxxxxxx</emailaddress>
+ <city>Portland</city>
+ <profile income="41889.41">
+ <interest category="category0"/>
+ <interest category="category0"/>
+ <business>Yes</business>
+ <age>18</age>
+ </profile>
+ <watches>
+ <watch open_auction="open_auction6"/>
+ <watch open_auction="open_auction2"/>
+ <watch open_auction="open_auction6"/>
+ <watch open_auction="open_auction5"/>
+ </watches>
+ </person>
+ </people>
+ </site>
+ </doc>;
+
+
+variable $person2 :=
+ <doc>
+ <site>
+ <people>
+ <person id="person205">
+ <name>Dr Who</name>
+ <emailaddress>mailto:boo@xxxxxxxx</emailaddress>
+ <city>Amsterdam</city>
+ <profile income="41000000000889.41">
+ <interest category="category0"/>
+ <interest category="category0"/>
+ <business>Yes</business>
+ <age>18000</age>
+ </profile>
+ <watches>
+ <watch open_auction="open_auction6"/>
+ <watch open_auction="open_auction2"/>
+ <watch open_auction="open_auction6"/>
+ <watch open_auction="open_auction5"/>
+ </watches>
+ </person>
+ </people>
+ </site>
+ </doc>;
+
+
+"
+TEST 1:
+
+"
+,
+{
+ auctions:create-db();
+
+ for $x in auctions:probe-point-watch($auctions:PersonWatches,
+ ("open_auction6", "open_auction2"))
+ return <person id = "{$x/@id}">{$x//watches}</person>
+}
+,
+"
+
+TEST 2:
+
+"
+,
+{
+ dml:insert-nodes($auctions:auctions, $person);
+
+ for $x in auctions:probe-point-watch($auctions:PersonWatches,
+ ("open_auction6", "open_auction2"))
+ return <person id = "{$x/@id}">{$x//watches}</person>
+}
+,
+"
+
+TEST 3:
+
+"
+,
+{
+ dml:delete-nodes(dml:collection($auctions:auctions)[2]);
+
+ for $x in auctions:probe-point-watch($auctions:PersonWatches,
+ ("open_auction6", "open_auction2"))
+ return <person id = "{$x/@id}">{$x//watches}</person>
+}
+,
+"
+
+TEST 4:
+
+"
+,
+{
+ dml:insert-nodes($auctions:auctions, $person);
+
+ (
+ dml:insert-nodes($auctions:auctions, $person2),
+
+ dml:delete-nodes(dml:collection($auctions:auctions)[2]),
+
+ insert node <watch open_auction="open_auction6"/> into
+ (dml:collection($auctions:auctions)[2])//watches
+ );
+
+ for $x in auctions:probe-point-watch($auctions:PersonWatches,
+ ("open_auction6", "open_auction2"))
+ return <person id = "{$x/@id}">{$x//watches}</person>
+}
+,
+"
+
+TEST 5:
+
+"
+,
+{
+ (
+ dml:insert-nodes($auctions:auctions, $person),
+
+ insert node <watch open_auction="open_auction8"/> into
+ (dml:collection($auctions:auctions)[2])//watches
+ );
+
+ for $x in auctions:probe-point-watch($auctions:PersonWatches,
+ ("open_auction6", "open_auction2"))
+ return <person id = "{$x/@id}">{$x//watches}</person>
+}
+,
+"
+
+TEST 6 (undo without do):
+
+"
+,
+{
+ try
+ {{
+ (
+ dml:insert-nodes($auctions:auctions, $person),
+
+ insert node (attribute id { 1 }) into $person//person
+ );
+ ()
+ }}
+ catch *
+ {
+ <exception>{$err:code} : {$err:description}</exception>
+ }
+ ,
+ for $x in auctions:probe-point-watch($auctions:PersonWatches,
+ ("open_auction6", "open_auction2"))
+ return <person id = "{$x/@id}">{$x//watches}</person>
+}
+,
+"
+"
+
=== modified file 'test/rbkt/Queries/zorba/index/auctions_module1.xqlib'
--- test/rbkt/Queries/zorba/index/auctions_module1.xqlib 2012-07-11 04:46:41 +0000
+++ test/rbkt/Queries/zorba/index/auctions_module1.xqlib 2012-07-12 16:38:27 +0000
@@ -44,7 +44,7 @@
auction. A person may watch multiple open auctions.
:)
-declare %ann:general-equality %ann:manual index auctions:PersonWatches
+declare %ann:general-equality %ann:automatic index auctions:PersonWatches
on nodes dml:collection(xs:QName("auctions:auctions"))/site/people/person
by (for $x in ./watches/watch/@open_auction return xs:string($x)) as xs:string*;
=== modified file 'test/rbkt/Queries/zorba/index/count.xqlib'
--- test/rbkt/Queries/zorba/index/count.xqlib 2012-05-11 20:30:16 +0000
+++ test/rbkt/Queries/zorba/index/count.xqlib 2012-07-12 16:38:27 +0000
@@ -11,18 +11,21 @@
declare collection def:user as node()*;
+
declare variable $def:user := xs:QName("def:user");
declare %ann:automatic %ann:unique %ann:value-equality index def:user-by-uid
on nodes dml:collection(xs:QName("def:user"))
by xs:string(@uid) as xs:string;
+
declare variable $def:user-by-uid := xs:QName("def:user-by-uid");
declare %ann:automatic %ann:value-range index def:user-by-uid-range
on nodes dml:collection(xs:QName("def:user"))
by xs:string(@uid) as xs:string;
+
declare variable $def:user-by-uid-range := xs:QName("def:user-by-uid-range");
declare %ann:manual %ann:general-range index def:user-by-uid-general-range
@@ -31,6 +34,7 @@
declare variable $def:user-by-uid-general-range := xs:QName("def:user-by-uid-general-range");
+
declare %ann:sequential function def:init()
{
ddl:create($def:user);
@@ -57,6 +61,7 @@
count(index_dml:probe-index-point-value(xs:QName("def:user-by-uid"), "1"))
};
+
declare function def:count-user-range()
{
count(
@@ -66,6 +71,7 @@
)
};
+
declare function def:count-user-general-range()
{
count(
=== modified file 'test/rbkt/Queries/zorba/index/numbers.xml'
--- test/rbkt/Queries/zorba/index/numbers.xml 2012-07-11 04:46:41 +0000
+++ test/rbkt/Queries/zorba/index/numbers.xml 2012-07-12 16:38:27 +0000
@@ -8,3 +8,38 @@
<xs_long num="9223372036854771200"/>
</numbers>
+
+<!--
+
+RELEASE:
+
+92 23 37 20 36 85 47 70 17 8
+92 23 37 20 36 85 47 70 70 0
+
+92 23 37 20 36 85 47 70 68 8
+92 23 37 20 36 85 47 70 70 0
+
+92 23 37 20 36 85 47 70 88 8
+92 23 37 20 36 85 47 70 70 0
+
+92 23 37 20 36 85 47 71 20 0
+92 23 37 20 36 85 47 71 70 0
+
+probe:
+92 23 37 20 36 85 47 70 68 8 E0
+
+
+DEBUG:
+
+92 23 37 20 36 85 47 70 17 8
+
+
+92 23 37 20 36 85 47 70 68 8
+
+
+92 23 37 20 36 85 47 70 88 8
+
+
+92 23 37 20 36 85 47 71 20 0
+
+-->
=== modified file 'test/rbkt/Queries/zorba/index/numbers.xqlib'
--- test/rbkt/Queries/zorba/index/numbers.xqlib 2012-07-11 04:46:41 +0000
+++ test/rbkt/Queries/zorba/index/numbers.xqlib 2012-07-12 16:38:27 +0000
@@ -10,14 +10,19 @@
declare variable $num:collname := xs:QName("num:numbers");
+declare variable $num:collname2 := xs:QName("num:numbers2");
declare variable $num:idx-g-h-long := xs:QName("num:idx-g-h-long");
declare variable $num:idx-g-t-long := xs:QName("num:idx-g-t-long");
+declare variable $num:idx-g-h-untyped := xs:QName("num:idx-g-h-untyped");
+
declare collection num:numbers as node()*;
-
-declare %ann:general-equality %ann:manual index num:idx-g-h-long
+declare collection num:numbers2 as node()*;
+
+
+declare %ann:general-equality %ann:automatic index num:idx-g-h-long
on nodes dml:collection(xs:QName("num:numbers"))//xs_long
by xs:long(.//@num);
@@ -26,3 +31,7 @@
on nodes dml:collection(xs:QName("num:numbers"))//xs_long
by xs:long(.//@num);
+
+declare %ann:general-equality %ann:automatic index num:idx-g-h-untyped
+on nodes dml:collection(xs:QName("num:numbers2"))/*
+by data(.);
=== added file 'test/rbkt/Queries/zorba/index/numbers.xsd'
--- test/rbkt/Queries/zorba/index/numbers.xsd 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/index/numbers.xsd 2012-07-12 16:38:27 +0000
@@ -0,0 +1,10 @@
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema";
+ targetNamespace="http://www.zorba-xquery.com/numbers.xsd";
+ xmlns="http://www.zorba-xquery.com/numbers.xsd";
+ elementFormDefault="qualified">
+
+
+<xs:element name="long" type="xs:long"/>
+<xs:element name="integer" type="xs:integer"/>
+
+</xs:schema>
=== added file 'test/rbkt/Queries/zorba/index/numbers2.xq'
--- test/rbkt/Queries/zorba/index/numbers2.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/index/numbers2.xq 2012-07-12 16:38:27 +0000
@@ -0,0 +1,92 @@
+import module namespace num = "http://www.w3.org/TestModules/numbers"; at "numbers.xqlib";
+
+import module namespace ddl = "http://www.zorba-xquery.com/modules/store/static/collections/ddl";;
+import module namespace dml = "http://www.zorba-xquery.com/modules/store/static/collections/dml";;
+import module namespace iddl = "http://www.zorba-xquery.com/modules/store/static/indexes/ddl";;
+import module namespace idml = "http://www.zorba-xquery.com/modules/store/static/indexes/dml";;
+
+declare namespace err = "http://www.w3.org/2005/xqt-errors";;
+
+import module namespace schema = "http://www.zorba-xquery.com/modules/schema";;
+
+import schema namespace s = "http://www.zorba-xquery.com/numbers.xsd"; at "numbers.xsd";
+
+declare variable $doc :=
+<numbers>
+<s:long>1</s:long>
+<s:integer>2</s:integer>
+<untyped>3</untyped>
+</numbers>
+;
+
+declare variable $vdoc := validate lax { $doc };
+
+
+ddl:create($num:collname2);
+
+iddl:create($num:idx-g-h-untyped);
+
+dml:insert-nodes($num:collname2, $vdoc);
+
+
+schema:schema-type(data(dml:collection($num:collname2)//s:long))
+,
+"
+
+TEST 1:
+
+"
+,
+try
+{
+ idml:probe-index-point-value($num:idx-g-h-untyped, 3)
+}
+catch *
+{
+ <exception>{$err:code} : {$err:description}</exception>
+}
+,
+"
+
+TEST 2:
+
+"
+,
+{
+ delete node dml:collection($num:collname2)/untyped;
+
+ idml:probe-index-point-general($num:idx-g-h-untyped, 3)
+ ,
+ "
+ "
+ ,
+ idml:probe-index-point-value($num:idx-g-h-untyped, 2)
+}
+,
+"
+
+TEST 3:
+
+"
+,
+{
+ insert node <untyped>2</untyped> as last into dml:collection($num:collname2)[1];
+
+ idml:probe-index-point-general($num:idx-g-h-untyped, 2),
+"
+",
+ idml:probe-index-point-general($num:idx-g-h-untyped, 2.0),
+"
+",
+ idml:probe-index-point-general($num:idx-g-h-untyped, xs:double(2.0)),
+"
+",
+ idml:probe-index-point-general($num:idx-g-h-untyped, xs:int(2)),
+"
+",
+ idml:probe-index-point-general($num:idx-g-h-untyped, "2")
+}
+,
+"
+"
+
=== modified file 'test/rbkt/Queries/zorba/index/undo2.xq'
--- test/rbkt/Queries/zorba/index/undo2.xq 2012-04-23 08:44:52 +0000
+++ test/rbkt/Queries/zorba/index/undo2.xq 2012-07-12 16:38:27 +0000
@@ -28,7 +28,7 @@
}}
catch *
{
- $err:code
+ <exception>{$err:code} : {$err:description}</exception>
}
,
=== modified file 'test/rbkt/Queries/zorba/index/undo2.xqlib'
--- test/rbkt/Queries/zorba/index/undo2.xqlib 2012-04-22 21:55:56 +0000
+++ test/rbkt/Queries/zorba/index/undo2.xqlib 2012-07-12 16:38:27 +0000
@@ -12,18 +12,21 @@
declare variable $auctions:auctions2 := xs:QName("auctions:auctions2");
declare variable $auctions:PersonId2 := xs:QName("auctions:PersonId2");
+
declare %an:ordered collection auctions:auctions1 as node()*;
declare %an:automatic %an:value-equality index auctions:PersonId1
on nodes dml:collection(xs:QName("auctions:auctions1"))
by xs:string(./@key) as xs:string;
+
declare %an:ordered collection auctions:auctions2 as node()*;
declare %an:unique %an:automatic %an:value-range index auctions:PersonId2
on nodes dml:collection(xs:QName("auctions:auctions2"))
by xs:string(./@id) as xs:string;
+
declare %an:sequential function auctions:create-db()
{
ddl:create($auctions:auctions1);
=== added file 'test/rbkt/Queries/zorba/index/undo4.xq'
--- test/rbkt/Queries/zorba/index/undo4.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/index/undo4.xq 2012-07-12 16:38:27 +0000
@@ -0,0 +1,145 @@
+
+import module namespace u = "http://www.zorba-xquery.com/unique-index"; at "undo4.xqlib";
+
+import module namespace dml = "http://www.zorba-xquery.com/modules/store/static/collections/dml";;
+import module namespace idml = "http://www.zorba-xquery.com/modules/store/static/indexes/dml";;
+
+declare namespace zerr = "http://www.zorba-xquery.com/errors";;
+declare namespace err = "http://www.w3.org/2005/xqt-errors";;
+
+u:create-db();
+
+
+dml:insert-nodes($u:c1,
+<person id="1">
+<car make="honda"/><car make="vw"/>
+</person>);
+
+dml:insert-nodes($u:c1,
+<person id="2">
+<car make="vw"/>
+</person>);
+
+
+dml:insert-nodes($u:c2,
+<person id="1">
+<car make="honda"/><car make="vw"/>
+</person>);
+
+
+idml:probe-index-point-general($u:PersonCars, "vw")
+,
+"
+
+TEST 0:
+
+"
+,
+try
+{
+ idml:probe-index-point-value($u:PersonCars, "vw")
+}
+catch *
+{
+ <exception>{$err:code} : {$err:description}</exception>
+}
+,
+"
+
+TEST 1:
+
+"
+,
+try
+{{
+ (
+ dml:insert-nodes($u:c1, <person id="3"><car make="vw"/></person>),
+
+ dml:insert-nodes($u:c2, <person id="1"/>)
+ );
+ ()
+}}
+catch *
+{
+ <exception>{$err:code} : {$err:description}</exception>
+}
+,
+"
+"
+,
+idml:probe-index-point-general($u:PersonCars, "vw")
+,
+"
+
+TEST 2:
+
+"
+,
+try
+{{
+ (
+ dml:insert-nodes($u:c1, <person id="3"><car make="vw"/></person>),
+
+ dml:delete-node-first($u:c1),
+
+ dml:insert-nodes($u:c2, <person id="1"/>)
+ );
+ ()
+}}
+catch *
+{
+ <exception>{$err:code} : {$err:description}</exception>
+}
+,
+"
+"
+,
+idml:probe-index-point-general($u:PersonCars, "vw")
+,
+"
+
+TEST 3:
+
+"
+,
+try
+{{
+ (
+ insert node <car make="BMW"/> into dml:collection($u:c1)[1],
+
+ dml:insert-nodes($u:c1, <person id="3"><car make="vw"/></person>),
+
+ dml:delete-node-first($u:c1),
+
+ delete nodes dml:collection($u:c1)[2]/car,
+
+ dml:insert-nodes($u:c2, <person id="1"/>)
+ );
+ ()
+}}
+catch *
+{
+ <exception>{$err:code} : {$err:description}</exception>
+}
+,
+"
+"
+,
+idml:probe-index-point-general($u:PersonCars, ("vw", "BMW"))
+,
+"
+
+TEST 4:
+
+"
+,
+{
+delete nodes dml:collection($u:c1)[1]/car[1];
+
+idml:probe-index-point-value($u:PersonCars, "vw")
+}
+,
+"
+"
+
+
=== added file 'test/rbkt/Queries/zorba/index/undo4.xqlib'
--- test/rbkt/Queries/zorba/index/undo4.xqlib 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/index/undo4.xqlib 2012-07-12 16:38:27 +0000
@@ -0,0 +1,43 @@
+module namespace f = "http://www.zorba-xquery.com/unique-index";;
+
+import module namespace ddl = "http://www.zorba-xquery.com/modules/store/static/collections/ddl";;
+import module namespace iddl = "http://www.zorba-xquery.com/modules/store/static/indexes/ddl";;
+import module namespace dml = "http://www.zorba-xquery.com/modules/store/static/collections/dml";;
+import module namespace idml = "http://www.zorba-xquery.com/modules/store/static/indexes/dml";;
+
+declare namespace an = "http://www.zorba-xquery.com/annotations";;
+
+
+
+declare variable $f:c1 := xs:QName("f:c1");
+declare variable $f:PersonCars := xs:QName("f:PersonCars");
+
+declare %an:ordered collection f:c1 as node()*;
+
+declare %an:automatic %an:general-equality index f:PersonCars
+on nodes dml:collection(xs:QName("f:c1"))
+by (for $x in ./car return xs:string($x/@make)) as xs:string*;
+
+
+
+declare variable $f:c2 := xs:QName("f:c2");
+declare variable $f:PersonId := xs:QName("f:PersonId");
+
+declare %an:ordered collection f:c2 as node()*;
+
+declare %an:unique %an:automatic %an:value-range index f:PersonId
+on nodes dml:collection(xs:QName("f:c2"))
+by xs:string(./@id) as xs:string;
+
+
+
+declare %an:sequential function f:create-db()
+{
+ ddl:create($f:c1);
+
+ ddl:create($f:c2);
+
+ iddl:create($f:PersonCars);
+
+ iddl:create($f:PersonId);
+};
Follow ups