zorba-coders team mailing list archive
-
zorba-coders team
-
Mailing list archive
-
Message #08748
[Merge] lp:~zorba-coders/zorba/bug-966706 into lp:zorba
Matthias Brantner has proposed merging lp:~zorba-coders/zorba/bug-966706 into lp:zorba.
Requested reviews:
Matthias Brantner (matthias-brantner)
Till Westmann (tillw)
Markos Zaharioudakis (markos-za)
Related bugs:
Bug #966706 in Zorba: "key uniqueness of value equality index not enforced"
https://bugs.launchpad.net/zorba/+bug/966706
For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/bug-966706/+merge/103835
fixed bug #966706 (key uniqueness of value equality index not enforced)
--
https://code.launchpad.net/~zorba-coders/zorba/bug-966706/+merge/103835
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'ChangeLog'
--- ChangeLog 2012-04-25 17:16:48 +0000
+++ ChangeLog 2012-04-27 09:11:24 +0000
@@ -29,6 +29,7 @@
* Fixed bug #967428 (do not hoist index creation outside a try-catch)
* Fixed performance problem with the findNodeSources function of the no-copy rule
* Fixed bug #872234 (prevent a rewritting to take place in case of sequential expr)
+ * Fixed bug #966706 (key uniqueness of index not enforced during incremental refresh)
* Fixed bug #906494 (default compile with D_FILE_OFFSET_BITS=64)
* Fixed bug #988412 (date:current-dateTime daylight saving)
* Fixed bug #912586, #912593 and #912722 (assertion failures with lax validation)
=== modified file 'src/runtime/core/apply_updates.cpp'
--- src/runtime/core/apply_updates.cpp 2012-04-24 12:39:38 +0000
+++ src/runtime/core/apply_updates.cpp 2012-04-27 09:11:24 +0000
@@ -92,19 +92,24 @@
store::Item_t item;
ulong numItems = 0;
- std::auto_ptr<store::PUL> pul;
+ store::PUL_t pul;
ApplyIteratorState* state;
DEFAULT_STACK_INIT(ApplyIteratorState, state, planState);
- pul.reset(GENV_ITEMFACTORY->createPendingUpdateList());
-
// Note: updating expr might not return a pul because of vacuous exprs
while (consumeNext(item, theChild, planState))
{
if (item->isPul())
{
- pul->mergeUpdates(item);
+ if (pul)
+ {
+ pul->mergeUpdates(item);
+ }
+ else
+ {
+ pul.transfer(item);
+ }
}
else if (!theDiscardXDM)
{
@@ -113,7 +118,8 @@
}
}
- apply_updates(ccb, gdctx, theSctx, pul.get(), loc);
+ if(pul)
+ apply_updates(ccb, gdctx, theSctx, pul, loc);
state->theXDMIte = state->theXDMItems.begin();
state->theXDMEnd = state->theXDMItems.end();
=== modified file 'src/runtime/indexing/doc_indexer.cpp'
--- src/runtime/indexing/doc_indexer.cpp 2012-04-24 12:39:38 +0000
+++ src/runtime/indexing/doc_indexer.cpp 2012-04-27 09:11:24 +0000
@@ -84,7 +84,7 @@
QueryLoc::null,
tmp);
- ulong numEntries = delta.size();
+ csize numEntries = delta.size();
store::Item_t domainNode;
store::IndexKey* key = NULL;
@@ -96,13 +96,11 @@
//std::cout << domainNode.getp() << " " << key << std::endl;
- for (ulong i = 0; i < theNumColumns; ++i)
+ for (csize i = 0; i < theNumColumns; ++i)
{
if (!thePlanWrapper->next((*key)[i]))
- throw ZORBA_EXCEPTION(
- zerr::ZXQP0003_INTERNAL_ERROR,
- ERROR_PARAMS( ZED( IncompleteKeyInIndexRefresh ) )
- );
+ throw ZORBA_EXCEPTION(zerr::ZXQP0003_INTERNAL_ERROR,
+ ERROR_PARAMS(ZED(IncompleteKeyInIndexRefresh)));
}
delta.resize(numEntries + 1);
=== modified file 'src/store/naive/node_items.cpp'
--- src/store/naive/node_items.cpp 2012-04-24 12:39:38 +0000
+++ src/store/naive/node_items.cpp 2012-04-27 09:11:24 +0000
@@ -456,7 +456,7 @@
#ifndef NDEBUG
XmlNode::~XmlNode()
{
- NODE_TRACE1("Deleted " << store::StoreConsts::toString(getNodeKind()) << this);
+ STORE_TRACE1("Deleted " << store::StoreConsts::toString(getNodeKind()) << this);
}
#endif
@@ -1650,7 +1650,7 @@
:
InternalNode(store::StoreConsts::documentNode)
{
- NODE_TRACE1("Loaded doc node " << this);
+ STORE_TRACE1("Loaded doc node " << this);
}
@@ -1666,7 +1666,7 @@
theBaseUri(baseUri),
theDocUri(docUri)
{
- NODE_TRACE1("{\nConstructing doc node " << this << " tree = "
+ STORE_TRACE1("{\nConstructing doc node " << this << " tree = "
<< getTree()->getId() << ":" << getTree()
<< " doc uri = " << docUri);
}
@@ -1721,8 +1721,8 @@
throw;
}
- NODE_TRACE1("}");
- NODE_TRACE1("Copied doc node " << this << " to node " << copyNode);
+ STORE_TRACE1("}");
+ STORE_TRACE1("Copied doc node " << this << " to node " << copyNode);
return copyNode;
}
@@ -1891,7 +1891,7 @@
theNodes.resize(numAttributes);
}
- NODE_TRACE1("Loaded elem node " << this << " name = " << theName->show()
+ STORE_TRACE1("Loaded elem node " << this << " name = " << theName->show()
<< " num bindings = " << numBindings << " num attributes = "
<< numAttributes << std::endl);
}
@@ -2017,7 +2017,7 @@
throw;
}
- NODE_TRACE1("Constructed element node " << this << " parent = "
+ STORE_TRACE1("Constructed element node " << this << " parent = "
<< std::hex << (parent ? (ulong)parent : 0) << " pos = " << pos
<< " tree = " << getTree()->getId() << ":" << getTree()
<< " ordpath = " << theOrdPath.show()
@@ -2358,7 +2358,7 @@
throw;
}
- NODE_TRACE1("Copied elem node " << this << " to node " << copyNode
+ STORE_TRACE1("Copied elem node " << this << " to node " << copyNode
<< " name = " << theName->getStringValue() << " parent = "
<< (parent ? parent : 0x0)
<< " pos = " << pos << " copy mode = " << copymode.toString());
@@ -3326,7 +3326,7 @@
if (qn->isBaseUri())
theFlags |= IsBaseUri;
- NODE_TRACE1("Loaded attr node " << this << " name = " << theName->getStringValue());
+ STORE_TRACE1("Loaded attr node " << this << " name = " << theName->getStringValue());
}
@@ -3449,7 +3449,7 @@
throw;
}
- NODE_TRACE1("Constructed attribute node " << this << " parent = "
+ STORE_TRACE1("Constructed attribute node " << this << " parent = "
<< std::hex << (parent ? (ulong)parent : 0) << " pos = " << pos
<< " tree = " << getTree()->getId() << ":" << getTree()
<< " ordpath = " << theOrdPath.show()
@@ -3532,7 +3532,7 @@
throw;
}
- NODE_TRACE1("Copied attribute node " << this << " to node " << copyNode
+ STORE_TRACE1("Copied attribute node " << this << " to node " << copyNode
<< " name = " << theName->show() << " parent = "
<< std::hex << (parent ? (ulong)parent : 0) << " pos = " << pos
<< " copy mode = " << copymode.toString());
@@ -3788,7 +3788,7 @@
{
setText(content);
- NODE_TRACE1("Loaded text node " << this << " content = " << getText());
+ STORE_TRACE1("Loaded text node " << this << " content = " << getText());
}
@@ -3833,13 +3833,13 @@
}
#ifdef TEXT_ORDPATH
- NODE_TRACE1("Constructed text node " << this << " parent = "
+ STORE_TRACE1("Constructed text node " << this << " parent = "
<< std::hex << (parent ? (ulong)parent : 0) << " pos = " << pos
<< " tree = " << getTree()->getId() << ":" << getTree()
<< " ordpath = " << theOrdPath.show()
<< " content = " << getText());
#else
- NODE_TRACE1("Constructed text node " << this << " parent = "
+ STORE_TRACE1("Constructed text node " << this << " parent = "
<< std::hex << (parent ? (ulong)parent : 0) << " pos = " << pos
<< " tree = " << getTree()->getId() << ":" << getTree()
<< " content = " << getText());
@@ -3894,12 +3894,12 @@
p->insertChild(this, p->numChildren());
#ifdef TEXT_ORDPATH
- NODE_TRACE1("Constructed text node " << this << " parent = "
+ STORE_TRACE1("Constructed text node " << this << " parent = "
<< std::hex << (parent ? (ulong)parent : 0)
<< " ordpath = " << theOrdPath.show()
<< " content = " << getValue()->getStringValue());
#else
- NODE_TRACE1("Constructed text node " << this << " parent = "
+ STORE_TRACE1("Constructed text node " << this << " parent = "
<< std::hex << (parent ? (ulong)parent : 0)
<< " content = " << getValue()->getStringValue());
#endif
@@ -4011,7 +4011,7 @@
throw;
}
- NODE_TRACE1("Copied text node " << this << " to node " << copyNode
+ STORE_TRACE1("Copied text node " << this << " to node " << copyNode
<< " parent = " << std::hex << (parent ? (ulong)parent : 0)
<< " pos = " << pos);
@@ -4496,7 +4496,7 @@
theName = qnpool.insert(zstring(), zstring(), theTarget);
- NODE_TRACE1("Loaded pi node " << this << " target = " << theTarget
+ STORE_TRACE1("Loaded pi node " << this << " target = " << theTarget
<< std::endl);
}
@@ -4529,7 +4529,7 @@
parent->insertChild(this, pos);
}
- NODE_TRACE1("Constructed pi node " << this << " parent = "
+ STORE_TRACE1("Constructed pi node " << this << " parent = "
<< std::hex << (parent ? (ulong)parent : 0) << " pos = " << pos
<< " tree = " << getTree()->getId() << ":" << getTree()
<< " ordpath = " << theOrdPath.show() << " target = " << theTarget);
@@ -4578,7 +4578,7 @@
throw;
}
- NODE_TRACE1("Copied pi node " << this << " to node " << copyNode
+ STORE_TRACE1("Copied pi node " << this << " to node " << copyNode
<< " parent = " << std::hex << (parent ? (ulong)parent : 0)
<< " pos = " << pos);
@@ -4636,7 +4636,7 @@
{
theContent.take(content);
- NODE_TRACE1("Loaded comment node " << this << " content = " << theContent);
+ STORE_TRACE1("Loaded comment node " << this << " content = " << theContent);
}
@@ -4662,7 +4662,7 @@
parent->insertChild(this, pos);
}
- NODE_TRACE1("Constructed comment node " << this << " parent = "
+ STORE_TRACE1("Constructed comment node " << this << " parent = "
<< std::hex << (parent ? (ulong)parent : 0) << " pos = " << pos
<< " tree = " << getTree()->getId() << ":" << getTree()
<< " ordpath = " << theOrdPath.show() << " content = "
@@ -4709,7 +4709,7 @@
throw;
}
- NODE_TRACE1("Copied coment node " << this << " to node " << copyNode
+ STORE_TRACE1("Copied coment node " << this << " to node " << copyNode
<< " parent = " << std::hex << (parent ? (ulong)parent : 0)
<< " pos = " << pos);
=== modified file 'src/store/naive/node_items.h'
--- src/store/naive/node_items.h 2012-04-24 12:39:38 +0000
+++ src/store/naive/node_items.h 2012-04-27 09:11:24 +0000
@@ -107,28 +107,6 @@
<< store::StoreConsts::toString(getNodeKind()))
-#ifndef NDEBUG
-
-#define NODE_TRACE(level, msg) \
-{ \
- if (level <= GET_STORE().getTraceLevel()) \
- std::cout << msg << std::endl; \
-}
-
-#define NODE_TRACE1(msg) NODE_TRACE(1, msg);
-#define NODE_TRACE2(msg) NODE_TRACE(2, msg);
-#define NODE_TRACE3(msg) NODE_TRACE(3, msg);
-
-#else
-
-#define NODE_TRACE(msg)
-#define NODE_TRACE1(msg)
-#define NODE_TRACE2(msg)
-#define NODE_TRACE3(msg)
-
-#endif
-
-
/*******************************************************************************
theRefCount : It is the sum of theRefCounts of all the nodes belonging to
=== modified file 'src/store/naive/pul_primitives.cpp'
--- src/store/naive/pul_primitives.cpp 2012-04-24 12:39:38 +0000
+++ src/store/naive/pul_primitives.cpp 2012-04-27 09:11:24 +0000
@@ -35,6 +35,7 @@
#include "store/api/validator.h"
#include "diagnostics/xquery_diagnostics.h"
+#include "diagnostics/util_macros.h"
namespace zorba {
@@ -946,42 +947,36 @@
void UpdDeleteCollection::apply()
{
theCollection = GET_STORE().getCollection(theName, theDynamicCollection);
+
if (theCollection == NULL)
return;//If two delete collection are issued in the same snapshot is a noop
+
Collection* collection = static_cast<Collection*>(theCollection.getp());
std::vector<store::Index*> indexes;
collection->getIndexes(indexes);
if (!indexes.empty())
- throw XQUERY_EXCEPTION(
- zerr::ZDDY0013_COLLECTION_BAD_DESTROY_INDEXES,
- ERROR_PARAMS( collection->getName()->getStringValue() ),
- ERROR_LOC( theLoc )
- );
+ RAISE_ERROR(zerr::ZDDY0013_COLLECTION_BAD_DESTROY_INDEXES, theLoc,
+ ERROR_PARAMS(collection->getName()->getStringValue()));
std::vector<store::IC*> activeICs;
collection->getActiveICs(activeICs);
if (!activeICs.empty())
- throw XQUERY_EXCEPTION(
- zerr::ZDDY0014_COLLECTION_BAD_DESTROY_ICS,
- ERROR_PARAMS( collection->getName()->getStringValue() ),
- ERROR_LOC( theLoc )
- );
+ RAISE_ERROR(zerr::ZDDY0014_COLLECTION_BAD_DESTROY_ICS, theLoc,
+ ERROR_PARAMS(collection->getName()->getStringValue()));
uint64_t size;
- try {
+ try
+ {
size = to_xs_unsignedLong(collection->size());
- } catch (std::range_error& e)
+ }
+ catch (std::range_error& e)
{
- throw ZORBA_EXCEPTION(
- zerr::ZSTR0060_RANGE_EXCEPTION,
- ERROR_PARAMS(
- BUILD_STRING("collection too big ("
- << e.what() << "; " << theName << ")")
- )
- );
+ throw ZORBA_EXCEPTION(zerr::ZSTR0060_RANGE_EXCEPTION,
+ ERROR_PARAMS(BUILD_STRING("collection too big ("
+ << e.what() << "; " << theName << ")")));
}
for (uint64_t i = 0; i < size; ++i)
@@ -989,11 +984,10 @@
XmlNode* root = static_cast<XmlNode*>(collection->nodeAt(xs_integer(i)).getp());
XmlTree* tree = root->getTree();
if (tree->getRefCount() > 1)
- throw XQUERY_EXCEPTION(
- zerr::ZDDY0015_COLLECTION_BAD_DESTROY_NODES,
- ERROR_PARAMS( collection->getName()->getStringValue() ),
- ERROR_LOC( theLoc )
- );
+ {
+ RAISE_ERROR(zerr::ZDDY0015_COLLECTION_BAD_DESTROY_NODES, theLoc,
+ ERROR_PARAMS(collection->getName()->getStringValue()));
+ }
}
GET_STORE().deleteCollection(theName, theDynamicCollection);
@@ -1013,13 +1007,13 @@
void UpdInsertIntoCollection::apply()
{
Collection* lColl = static_cast<Collection*>
- (GET_STORE().getCollection(theName, theDynamicCollection).getp());
+ (GET_STORE().getCollection(theName, theDynamicCollection).getp());
assert(lColl);
theIsApplied = true;
- std::size_t numNodes = theNodes.size();
- for (std::size_t i = 0; i < numNodes; ++i)
+ csize numNodes = theNodes.size();
+ for (csize i = 0; i < numNodes; ++i)
{
lColl->addNode(theNodes[i], xs_integer(-1));
++theNumApplied;
@@ -1030,7 +1024,7 @@
void UpdInsertIntoCollection::undo()
{
Collection* lColl = static_cast<Collection*>
- (GET_STORE().getCollection(theName, theDynamicCollection).getp());
+ (GET_STORE().getCollection(theName, theDynamicCollection).getp());
assert(lColl);
uint64_t lastPos;
@@ -1040,13 +1034,9 @@
}
catch (std::range_error& e)
{
- throw ZORBA_EXCEPTION(
- zerr::ZSTR0060_RANGE_EXCEPTION,
- ERROR_PARAMS(
- BUILD_STRING("collection too big ("
- << e.what() << "; " << theName << ")")
- )
- );
+ throw ZORBA_EXCEPTION(zerr::ZSTR0060_RANGE_EXCEPTION,
+ ERROR_PARAMS(BUILD_STRING("collection too big ("
+ << e.what() << "; " << theName << ")")));
}
for (long i = theNumApplied-1; i >= 0; --i)
@@ -1154,7 +1144,7 @@
void UpdInsertBeforeIntoCollection::apply()
{
Collection* lColl = static_cast<Collection*>
- (GET_STORE().getCollection(theName, theDynamicCollection).getp());
+ (GET_STORE().getCollection(theName, theDynamicCollection).getp());
assert(lColl);
if (!theNodes.empty())
@@ -1170,7 +1160,7 @@
void UpdInsertBeforeIntoCollection::undo()
{
Collection* lColl = static_cast<Collection*>
- (GET_STORE().getCollection(theName, theDynamicCollection).getp());
+ (GET_STORE().getCollection(theName, theDynamicCollection).getp());
assert(lColl);
ZORBA_ASSERT(theFirstNode == lColl->nodeAt(theFirstPos));
@@ -1184,7 +1174,7 @@
void UpdInsertAfterIntoCollection::apply()
{
Collection* lColl = static_cast<Collection*>
- (GET_STORE().getCollection(theName, theDynamicCollection).getp());
+ (GET_STORE().getCollection(theName, theDynamicCollection).getp());
assert(lColl);
if (!theNodes.empty())
@@ -1201,7 +1191,7 @@
void UpdInsertAfterIntoCollection::undo()
{
Collection* lColl = static_cast<Collection*>
- (GET_STORE().getCollection(theName, theDynamicCollection).getp());
+ (GET_STORE().getCollection(theName, theDynamicCollection).getp());
assert(lColl);
ZORBA_ASSERT(theFirstNode == lColl->nodeAt(theFirstPos));
@@ -1236,13 +1226,13 @@
);
}
- std::size_t numNodes = theNodes.size();
+ csize numNodes = theNodes.size();
bool isLast = theIsLast;
if (theIsLast)
{
- for (std::size_t i = numNodes; i > 0; --i)
+ for (csize i = numNodes; i > 0; --i)
{
if (theNodes[i-1] != lColl->nodeAt(xs_integer(size - i)))
{
@@ -1270,7 +1260,7 @@
void UpdDeleteNodesFromCollection::undo()
{
Collection* lColl = static_cast<Collection*>
- (GET_STORE().getCollection(theName, theDynamicCollection).getp());
+ (GET_STORE().getCollection(theName, theDynamicCollection).getp());
assert(lColl);
for (std::size_t i = 0; i < theNumApplied; ++i)
@@ -1289,7 +1279,7 @@
void UpdTruncateCollection::apply()
{
Collection* lColl = static_cast<Collection*>
- (GET_STORE().getCollection(theName, theDynamicCollection).getp());
+ (GET_STORE().getCollection(theName, theDynamicCollection).getp());
assert(lColl);
lColl->removeAll();
=== modified file 'src/store/naive/simple_index_value.cpp'
--- src/store/naive/simple_index_value.cpp 2012-04-24 12:39:38 +0000
+++ src/store/naive/simple_index_value.cpp 2012-04-27 09:11:24 +0000
@@ -366,9 +366,9 @@
ERROR_PARAMS(key->toString(), theQname->getStringValue()));
}
- ValueIndexValue* valueSet = NULL;
+ IndexMap::iterator pos = theMap.find(key);
- if (theMap.get(key, valueSet))
+ if (pos != theMap.end())
{
if (isUnique())
{
@@ -376,21 +376,20 @@
ERROR_PARAMS(theQname->getStringValue()));
}
- valueSet->resize(valueSet->size() + 1);
- (*valueSet)[valueSet->size()-1].transfer(value);
-
+ (*pos).second->transfer_back(value);
+ key = const_cast<store::IndexKey*>((*pos).first);
+
return true;
}
- valueSet = new ValueIndexValue(1);
+ ValueIndexValue* valueSet = new ValueIndexValue(1);
(*valueSet)[0].transfer(value);
//std::cout << "Index Entry Insert [" << key << ","
// << valueSet << "]" << std::endl;
- const store::IndexKey* key2 = key;
- theMap.insert(key2, valueSet);
- key = NULL; // ownership of the key obj passes to the index.
+ // Note: ownership of the key obj passes to the index.
+ theMap.insert(key, valueSet);
return false;
}
@@ -407,7 +406,7 @@
********************************************************************************/
bool ValueHashIndex::remove(
const store::IndexKey* key,
- store::Item_t& value,
+ const store::Item_t& value,
bool all)
{
if (key->size() != getNumColumns())
@@ -649,7 +648,7 @@
#if 0
std::cout << "inserting entry : [(";
- for (ulong i = 0; i < getNumColumns(); i++)
+ for (csize i = 0; i < getNumColumns(); i++)
{
if (key[i] != NULL)
std::cout << key[i]->getStringValue() << ", ";
@@ -672,14 +671,16 @@
}
pos->second->transfer_back(value);
+ key = const_cast<store::IndexKey*>(pos->first);
+
return true;
}
ValueIndexValue* valueSet = new ValueIndexValue(1);
(*valueSet)[0].transfer(value);
+ // Note: ownership of the key obj passes to the index.
theMap.insert(IndexMapPair(key, valueSet));
- key = NULL; // ownership of the key obj passes to the index.
return false;
}
@@ -690,7 +691,7 @@
********************************************************************************/
bool ValueTreeIndex::remove(
const store::IndexKey* key,
- store::Item_t& value,
+ const store::Item_t& value,
bool all)
{
if (key->size() != getNumColumns())
=== modified file 'src/store/naive/simple_index_value.h'
--- src/store/naive/simple_index_value.h 2012-04-24 12:39:38 +0000
+++ src/store/naive/simple_index_value.h 2012-04-27 09:11:24 +0000
@@ -88,11 +88,13 @@
public:
const XQPCollator* getCollator(ulong i) const;
+ virtual bool isTreeIndex() = 0;
+
virtual bool insert(store::IndexKey*& key, store::Item_t& item) = 0;
virtual bool remove(
const store::IndexKey* key,
- store::Item_t& item,
+ const store::Item_t& item,
bool all = false) = 0;
};
@@ -142,6 +144,8 @@
~ValueHashIndex();
public:
+ bool isTreeIndex() { return false; }
+
void clear();
ulong size() const;
@@ -150,7 +154,7 @@
bool insert(store::IndexKey*& key, store::Item_t& item);
- bool remove(const store::IndexKey* key, store::Item_t& item, bool all);
+ bool remove(const store::IndexKey* key, const store::Item_t& item, bool all);
};
@@ -227,6 +231,8 @@
~ValueTreeIndex();
public:
+ bool isTreeIndex() { return true; }
+
void clear();
ulong size() const;
@@ -235,7 +241,7 @@
bool insert(store::IndexKey*& key, store::Item_t& item);
- bool remove(const store::IndexKey* key, store::Item_t& item, bool all = false);
+ bool remove(const store::IndexKey* key, const store::Item_t& item, bool all = false);
};
=== modified file 'src/store/naive/simple_pul.cpp'
--- src/store/naive/simple_pul.cpp 2012-04-24 12:39:38 +0000
+++ src/store/naive/simple_pul.cpp 2012-04-27 09:11:24 +0000
@@ -58,28 +58,6 @@
/*******************************************************************************
********************************************************************************/
-void cleanIndexDeltas(std::vector<store::IndexDelta>& deltas)
-{
- std::vector<store::IndexDelta>::iterator ite = deltas.begin();
- std::vector<store::IndexDelta>::iterator end = deltas.end();
-
- for (; ite != end; ++ite)
- {
- store::IndexDelta::iterator ite2 = (*ite).begin();
- store::IndexDelta::iterator end2 = (*ite).end();
-
- for (; ite2 != end2; ++ite2)
- {
- if ((*ite2).second)
- delete (*ite2).second;
- }
- }
-}
-
-
-/*******************************************************************************
-
-********************************************************************************/
void applyList(std::vector<UpdatePrimitive*>& aVector)
{
std::vector<UpdatePrimitive*>::iterator iter = aVector.begin();
@@ -97,9 +75,9 @@
********************************************************************************/
void undoList(std::vector<UpdatePrimitive*>& list)
{
- ulong size = (ulong)list.size();
+ csize size = list.size();
- for (ulong i = size; i > 0; --i)
+ for (csize i = size; i > 0; --i)
{
if (list[i-1]->isApplied())
list[i-1]->undo();
@@ -150,14 +128,14 @@
cleanList(theValidationList);
- CollectionPulMap::iterator ite = theCollectionPuls.begin();
- CollectionPulMap::iterator end = theCollectionPuls.end();
+ CollectionPuls::iterator ite = theCollectionPuls.begin();
+ CollectionPuls::iterator end = theCollectionPuls.end();
for (; ite != end; ++ite)
{
- if ((*ite).second != NULL)
- delete (*ite).second;
+ delete (*ite);
}
+
cleanList(theICActivationList);
cleanList(theCreateDocumentList);
cleanList(theDeleteDocumentList);
@@ -197,49 +175,53 @@
if (collName == theLastCollection)
return theLastPul;
- return getCollectionPulByName(collName,collection->isDynamic());
+
+ return getCollectionPulByName(collName, collection->isDynamic());
}
else if (theNoCollectionPul != NULL)
{
return theNoCollectionPul;
}
- else if (theCollectionPuls[NULL] != NULL)
- {
- theNoCollectionPul = theCollectionPuls[NULL];
- return theNoCollectionPul;
- }
else
{
theNoCollectionPul = new CollectionPul(this, NULL);
- theCollectionPuls[NULL] = theNoCollectionPul;
+ theCollectionPuls.push_back(theNoCollectionPul);
+ theCollectionPulsMap[NULL] = theCollectionPuls.size() - 1;
return theNoCollectionPul;
}
}
-CollectionPul* PULImpl::getCollectionPulByName(const store::Item* name, bool dynamicCollection)
+
+CollectionPul* PULImpl::getCollectionPulByName(
+ const store::Item* name,
+ bool isDynamic)
{
const QNameItem* collName = static_cast<const QNameItem*>(name)->getNormalized();
- assert(!name->isNode());
+ assert(name->isAtomic());
// "name" is the name of a collection.
if (name == theLastCollection)
return theLastPul;
- CollectionPulMap::iterator ite = theCollectionPuls.find(collName);
+ CollectionPulMap::iterator ite = theCollectionPulsMap.find(collName);
theLastCollection = collName;
- if (ite != theCollectionPuls.end())
+ if (ite != theCollectionPulsMap.end())
{
- theLastPul = ite->second;
+ theLastPul = theCollectionPuls[ite->second];
}
else
{
Collection* collection = static_cast<Collection*>
- (GET_STORE().getCollection(collName,dynamicCollection).getp());
+ (GET_STORE().getCollection(collName, isDynamic).getp());
+
theLastPul = new CollectionPul(this, collection);
- theCollectionPuls[collName] = theLastPul;
+
+ theCollectionPuls.push_back(theLastPul);
+
+ theCollectionPulsMap[collName] = theCollectionPuls.size() - 1;
}
return theLastPul;
@@ -1107,17 +1089,17 @@
PULImpl* otherp = reinterpret_cast<PULImpl*>(other);
// Merge collection-specific primitives
- CollectionPulMap::iterator thisIte = theCollectionPuls.begin();
- CollectionPulMap::iterator thisEnd = theCollectionPuls.end();
- CollectionPulMap::iterator otherIte = otherp->theCollectionPuls.begin();
- CollectionPulMap::iterator otherEnd = otherp->theCollectionPuls.end();
+ CollectionPulMap::iterator thisIte = theCollectionPulsMap.begin();
+ CollectionPulMap::iterator thisEnd = theCollectionPulsMap.end();
+ CollectionPulMap::iterator otherIte = otherp->theCollectionPulsMap.begin();
+ CollectionPulMap::iterator otherEnd = otherp->theCollectionPulsMap.end();
while (thisIte != thisEnd && otherIte != otherEnd)
{
if (thisIte->first == otherIte->first)
{
- CollectionPul* thisPul = thisIte->second;
- CollectionPul* otherPul = otherIte->second;
+ CollectionPul* thisPul = theCollectionPuls[thisIte->second];
+ CollectionPul* otherPul = otherp->theCollectionPuls[otherIte->second];
// Merge XQUF primitives
mergeUpdateList(thisPul,
@@ -1186,18 +1168,27 @@
}
else
{
- theCollectionPuls[otherIte->first] = otherIte->second;
- otherIte->second->thePul = this;
- otherIte->second = NULL;
+ CollectionPul* otherPul = otherp->theCollectionPuls[otherIte->second];
+ otherp->theCollectionPuls[otherIte->second] = NULL;
+
+ theCollectionPuls.push_back(otherPul);
+ theCollectionPulsMap[otherIte->first] = theCollectionPuls.size() - 1;
+
+ otherPul->switchPul(this);
++otherIte;
}
}
while (otherIte != otherEnd)
{
- theCollectionPuls[otherIte->first] = otherIte->second;
- otherIte->second->switchPul(this);
- otherIte->second = NULL;
+ CollectionPul* otherPul = otherp->theCollectionPuls[otherIte->second];
+ otherp->theCollectionPuls[otherIte->second] = NULL;
+
+ theCollectionPuls.push_back(otherPul);
+ theCollectionPulsMap[otherIte->first] = theCollectionPuls.size() - 1;
+
+ otherPul->switchPul(this);
+
++otherIte;
}
@@ -1470,14 +1461,14 @@
********************************************************************************/
void PULImpl::checkTransformUpdates(const std::vector<store::Item*>& rootNodes) const
{
- ulong numRoots = (ulong)rootNodes.size();
+ csize numRoots = rootNodes.size();
- CollectionPulMap::const_iterator collIte = theCollectionPuls.begin();
- CollectionPulMap::const_iterator collEnd = theCollectionPuls.end();
+ std::vector<CollectionPul*>::const_iterator collIte = theCollectionPuls.begin();
+ std::vector<CollectionPul*>::const_iterator collEnd = theCollectionPuls.end();
for (; collIte != collEnd; ++collIte)
{
- CollectionPul* pul = collIte->second;
+ CollectionPul* pul = *collIte;
NodeToUpdatesMap::iterator it = pul->theNodeToUpdatesMap.begin();
NodeToUpdatesMap::iterator end = pul->theNodeToUpdatesMap.end();
@@ -1488,7 +1479,7 @@
bool found = false;
- for (ulong i = 0; i < numRoots; i++)
+ for (csize i = 0; i < numRoots; i++)
{
XmlNode* rootNode = reinterpret_cast<XmlNode*>(rootNodes[i]);
@@ -1533,12 +1524,12 @@
std::set<store::Collection*> collections;
std::set<store::Collection*> truncated_collections;
- CollectionPulMap::iterator collIte = theCollectionPuls.begin();
- CollectionPulMap::iterator collEnd = theCollectionPuls.end();
+ CollectionPuls::iterator collIte = theCollectionPuls.begin();
+ CollectionPuls::iterator collEnd = theCollectionPuls.end();
for (; collIte != collEnd; ++collIte)
{
- store::Collection* collection = store->getCollection(collIte->first);
+ store::Collection* collection = (*collIte)->theCollection;
// The collection may not be created yet.
if (collection == NULL)
@@ -1546,7 +1537,7 @@
collections.insert(collection);
- CollectionPul* pul = collIte->second;
+ CollectionPul* pul = *collIte;
if (pul->theTruncateCollectionList.size() > 0)
{
@@ -1570,6 +1561,7 @@
(pul->theInsertIntoCollectionList[i]);
csize numDocs = upd->numNodes();
+
for (csize j = 0; j < numDocs; ++j)
pul->theInsertedDocs.push_back(static_cast<XmlNode*>(upd->getNode(j)));
}
@@ -1582,6 +1574,7 @@
(pul->theDeleteFromCollectionList[i]);
csize numDocs = upd->numNodes();
+
for (csize j = 0; j < numDocs; ++j)
pul->theDeletedDocs.push_back(static_cast<XmlNode*>(upd->getNode(j)));
}
@@ -1689,8 +1682,8 @@
********************************************************************************/
void PULImpl::applyUpdates(bool inheritNSBindings)
{
- CollectionPulMap::iterator collIte = theCollectionPuls.begin();
- CollectionPulMap::iterator collEnd = theCollectionPuls.end();
+ CollectionPuls::iterator collIte = theCollectionPuls.begin();
+ CollectionPuls::iterator collEnd = theCollectionPuls.end();
theInheritNSBindings = inheritNSBindings;
@@ -1701,7 +1694,7 @@
// maintained incrementally w.r.t. updates in C.
for (; collIte != collEnd; ++collIte)
{
- CollectionPul* pul = collIte->second;
+ CollectionPul* pul = *collIte;
pul->applyUpdates();
}
@@ -1726,7 +1719,7 @@
// check integrity constraints for involved collections
for (collIte = theCollectionPuls.begin(); collIte != collEnd; ++collIte)
{
- CollectionPul* pul = collIte->second;
+ CollectionPul* pul = *collIte;
if (pul->theCollection != NULL)
{
@@ -1743,9 +1736,18 @@
// Apply delete-collection primitives
for (collIte = theCollectionPuls.begin(); collIte != collEnd; ++collIte)
{
- CollectionPul* pul = collIte->second;
+ CollectionPul* pul = *collIte;
applyList(pul->theDeleteCollectionList);
}
+
+ // Refresh each incrementally maintained index. We need to do this here
+ // because refreshIndices can raise an error (e.g. if the unique constraint
+ // of an index is violated).
+ for (collIte = theCollectionPuls.begin(); collIte != collEnd; ++collIte)
+ {
+ CollectionPul* pul = *collIte;
+ pul->refreshIndexes();
+ }
}
catch (...)
{
@@ -1753,10 +1755,10 @@
throw;
}
- //
+ // Perform actions that are not expected to raise any errors
for (collIte = theCollectionPuls.begin(); collIte != collEnd; ++collIte)
{
- CollectionPul* pul = collIte->second;
+ CollectionPul* pul = *collIte;
pul->finalizeUpdates();
}
@@ -1790,12 +1792,12 @@
{
undoList(theValidationList);
- CollectionPulMap::iterator collIte = theCollectionPuls.begin();
- CollectionPulMap::iterator collEnd = theCollectionPuls.end();
+ CollectionPuls::iterator collIte = theCollectionPuls.begin();
+ CollectionPuls::iterator collEnd = theCollectionPuls.end();
for (; collIte != collEnd; ++collIte)
{
- CollectionPul* pul = collIte->second;
+ CollectionPul* pul = *collIte;
undoList(pul->theDeleteCollectionList);
}
@@ -1807,7 +1809,7 @@
for (collIte = theCollectionPuls.begin(); collIte != collEnd; ++collIte)
{
- CollectionPul* pul = collIte->second;
+ CollectionPul* pul = *collIte;
pul->undoUpdates();
}
@@ -1851,10 +1853,7 @@
cleanList(theTruncateCollectionList);
cleanList(theDeleteCollectionList);
- cleanIndexDeltas(theBeforeIndexDeltas);
- cleanIndexDeltas(theAfterIndexDeltas);
- cleanIndexDeltas(theInsertedDocsIndexDeltas);
- cleanIndexDeltas(theDeletedDocsIndexDeltas);
+ cleanIndexDeltas();
}
@@ -1890,22 +1889,44 @@
}
}
-/*******************************************************************************
- The comparison function for sorting the entries of an IndexDelta by the doc node
-********************************************************************************/
-static bool cmp(const std::pair<store::Item_t, store::IndexKey*>& e1,
- const std::pair<store::Item_t, store::IndexKey*>& e2)
-{
- return e1.first.getp() < e2.first.getp();
-}
-
-
-/*******************************************************************************
- Compute the index contents on the modified docs, before any modifications
- are actually applied.
+
+/*******************************************************************************
+ For each incrementally-maintained index associated with this collection,
+ compute the index contents on the modified and deleted docs, before any
+ modifications are actually applied.
+
+ Note 1: If any docs are deleted, we have to remove from the before and after
+ deltas any entries for nodes belonging to the deleted docs. This is required
+ for the undo to work properly. For example, let E = [N, K] be an after-delta
+ entry, and let N be a node in a doc D that is going to be removed from the
+ collection. Then, during undo, the key pointer in E may be a dangling pointer.
+
+ Note 2: Given note 1, we actually have to compute the delete-docs deltas
+ *before* any modification are actually applied.
********************************************************************************/
void CollectionPul::computeIndexBeforeDeltas()
{
+ csize numIncrementalIndices = theIncrementalIndices.size();
+
+ if (numIncrementalIndices == 0)
+ return;
+
+ std::vector<XmlNode*>::const_iterator docIte = theDeletedDocs.begin();
+ std::vector<XmlNode*>::const_iterator docEnd = theDeletedDocs.end();
+
+ for (; docIte != docEnd; ++docIte)
+ {
+ theModifiedDocs.erase(*docIte);
+
+ for (csize i = 0; i < numIncrementalIndices; ++i)
+ {
+ store::IndexEntryCreator* docIndexer = theIndexEntryCreators[i].getp();
+ store::IndexDelta& indexDelta = theDeletedDocsIndexDeltas[i];
+
+ docIndexer->createIndexEntries((*docIte), indexDelta);
+ }
+ }
+
computeIndexDeltas(theBeforeIndexDeltas);
}
@@ -1917,21 +1938,19 @@
********************************************************************************/
void CollectionPul::computeIndexAfterDeltas()
{
+ csize numIncrementalIndices = theIncrementalIndices.size();
+
+ if (numIncrementalIndices == 0)
+ return;
+
computeIndexDeltas(theAfterIndexDeltas);
- csize numIncrementalIndices = theIncrementalIndices.size();
-
- if (numIncrementalIndices == 0)
- return;
-
- theInsertedDocsIndexDeltas.resize(numIncrementalIndices);
-
std::vector<XmlNode*>::const_iterator docIte = theInsertedDocs.begin();
std::vector<XmlNode*>::const_iterator docEnd = theInsertedDocs.end();
for (; docIte != docEnd; ++docIte)
{
- for (ulong i = 0; i < numIncrementalIndices; ++i)
+ for (csize i = 0; i < numIncrementalIndices; ++i)
{
store::IndexEntryCreator* docIndexer = theIndexEntryCreators[i].getp();
store::IndexDelta& indexDelta = theInsertedDocsIndexDeltas[i];
@@ -1939,22 +1958,6 @@
docIndexer->createIndexEntries((*docIte), indexDelta);
}
}
-
- theDeletedDocsIndexDeltas.resize(numIncrementalIndices);
-
- docIte = theDeletedDocs.begin();
- docEnd = theDeletedDocs.end();
-
- for (; docIte != docEnd; ++docIte)
- {
- for (ulong i = 0; i < numIncrementalIndices; ++i)
- {
- store::IndexEntryCreator* docIndexer = theIndexEntryCreators[i].getp();
- store::IndexDelta& indexDelta = theDeletedDocsIndexDeltas[i];
-
- docIndexer->createIndexEntries((*docIte), indexDelta);
- }
- }
}
@@ -1965,19 +1968,14 @@
********************************************************************************/
void CollectionPul::computeIndexDeltas(std::vector<store::IndexDelta>& deltas)
{
- ulong numIncrementalIndices = (ulong)theIncrementalIndices.size();
-
- if (numIncrementalIndices == 0)
- return;
-
- deltas.resize(numIncrementalIndices);
+ csize numIncrementalIndices = theIncrementalIndices.size();
std::set<XmlNode*>::const_iterator docIte = theModifiedDocs.begin();
std::set<XmlNode*>::const_iterator docEnd = theModifiedDocs.end();
for (; docIte != docEnd; ++docIte)
{
- for (ulong i = 0; i < numIncrementalIndices; ++i)
+ for (csize i = 0; i < numIncrementalIndices; ++i)
{
store::IndexEntryCreator* docIndexer = theIndexEntryCreators[i].getp();
store::IndexDelta& indexDelta = deltas[i];
@@ -1985,113 +1983,268 @@
docIndexer->createIndexEntries((*docIte), indexDelta);
}
}
-
- for (ulong i = 0; i < numIncrementalIndices; ++i)
- {
- store::IndexDelta& indexDelta = deltas[i];
-
- std::sort(indexDelta.begin(), indexDelta.end(), cmp);
- }
-}
-
-
-/*******************************************************************************
-
-********************************************************************************/
-void CollectionPul::refreshIndices()
-{
- csize numIncrementalIndices = theTruncatedIndices.size();
- for (csize idx = 0; idx < numIncrementalIndices; ++idx)
+}
+
+
+/*******************************************************************************
+
+********************************************************************************/
+void CollectionPul::cleanIndexDeltas()
+{
+ csize numIncrementalIndices = theIncrementalIndices.size();
+
+ for (csize idx = 0; idx < numIncrementalIndices; ++idx)
+ {
+ store::IndexDelta::iterator ite;
+ store::IndexDelta::iterator end;
+ store::IndexDelta* delta;
+ csize numApplied;
+
+ delta = &theInsertedDocsIndexDeltas[idx];
+ if (delta)
+ {
+ numApplied = theNumInsertedDocsIndexDeltasApplied[idx];
+ ite = delta->begin() + numApplied;
+ end = delta->end();
+ for (; ite != end; ++ite)
+ {
+ delete (*ite).second;
+ }
+ }
+
+ delta = &theAfterIndexDeltas[idx];
+ if (delta)
+ {
+ numApplied = theNumAfterIndexDeltasApplied[idx];
+ ite = delta->begin() + numApplied;
+ end = delta->end();
+ for (; ite != end; ++ite)
+ {
+ 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;
+ }
+ }
+ }
+}
+
+
+/*******************************************************************************
+ Refresh the incrementally maintained indexes.
+********************************************************************************/
+void CollectionPul::refreshIndexes()
+{
+ 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);
+}
+
+
+/*******************************************************************************
+
+********************************************************************************/
+void CollectionPul::undoRefreshIndexes()
+{
+ csize numIncrementalIndices = theIncrementalIndices.size();
+
+ STORE_TRACE1("Reverting indexes for collection "
+ << (theCollection ?
+ theCollection->getName()->getStringValue().c_str() :
+ "NULL")
+ << std::endl);
+
+ 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));
+ }
+
+ STORE_TRACE1("Reverted indexes for collection "
+ << (theCollection ?
+ theCollection->getName()->getStringValue().c_str() :
+ "NULL")
+ << std::endl);
+}
+
+
+/*******************************************************************************
+ The method is called from CollectionPul::finalizeUpdates()
+********************************************************************************/
+void CollectionPul::truncateIndexes()
+{
+ csize numTruncatedIndices = theTruncatedIndices.size();
+
+ for (csize idx = 0; idx < numTruncatedIndices; ++idx)
{
ValueIndex* index = static_cast<ValueIndex*>(theTruncatedIndices[idx]);
index->clear();
}
-
- numIncrementalIndices = theIncrementalIndices.size();
-
- for (csize idx = 0; idx < numIncrementalIndices; ++idx)
- {
- ValueIndex* index = static_cast<ValueIndex*>(theIncrementalIndices[idx]);
-
- //
- // Referesh the index w.r.t. modified docs.
- //
- ValueIndexCompareFunction keyCmp(index->getNumColumns(),
- index->getTimezone(),
- index->getCollations());
-
- store::IndexDelta& beforeDelta = theBeforeIndexDeltas[idx];
- store::IndexDelta& afterDelta = theAfterIndexDeltas[idx];
- store::IndexDelta& insertedDelta = theInsertedDocsIndexDeltas[idx];
- store::IndexDelta& deletedDelta = theDeletedDocsIndexDeltas[idx];
-
- store::IndexDelta::iterator beforeIte = beforeDelta.begin();
- store::IndexDelta::iterator beforeEnd = beforeDelta.end();
- store::IndexDelta::iterator afterIte = afterDelta.begin();
- store::IndexDelta::iterator afterEnd = afterDelta.end();
- store::IndexDelta::iterator insertedIte = insertedDelta.begin();
- store::IndexDelta::iterator insertedEnd = insertedDelta.end();
- store::IndexDelta::iterator deletedIte = deletedDelta.begin();
- store::IndexDelta::iterator deletedEnd = deletedDelta.end();
-
- while (beforeIte != beforeEnd && afterIte != afterEnd)
- {
- store::Item_t& beforeNode = (*beforeIte).first;
- store::Item_t& afterNode = (*afterIte).first;
- store::IndexKey* beforeKey = (*beforeIte).second;
- store::IndexKey*& afterKey = (*afterIte).second;
-
- if (beforeNode == afterNode)
- {
- if (!keyCmp.equal(beforeKey, afterKey))
- {
- index->remove(beforeKey, beforeNode);
- index->insert(afterKey, afterNode);
- }
-
- ++beforeIte;
- ++afterIte;
- }
- else if (beforeNode < afterNode)
- {
- index->remove(beforeKey, beforeNode);
- ++beforeIte;
- }
- else
- {
- index->insert(afterKey, afterNode);
- ++afterIte;
- }
- }
-
- while (beforeIte != beforeEnd)
- {
- index->remove((*beforeIte).second, (*beforeIte).first);
- ++beforeIte;
- }
-
- while (afterIte != afterEnd)
- {
- index->insert((*afterIte).second, (*afterIte).first);
- ++afterIte;
- }
-
- //
- // Referesh the index w.r.t. newly inserted docs.
- //
- for (; insertedIte != insertedEnd; ++insertedIte)
- {
- index->insert((*insertedIte).second, (*insertedIte).first);
- }
-
- //
- // Referesh the index w.r.t. deleted docs,
- //
- for (; deletedIte != deletedEnd; ++deletedIte)
- {
- index->remove((*deletedIte).second, (*deletedIte).first);
- }
- }
}
@@ -2100,6 +2253,37 @@
********************************************************************************/
void CollectionPul::applyUpdates()
{
+ csize numIncrementalIndices = theIncrementalIndices.size();
+
+#if 0
+ if (theCollection != NULL)
+ {
+ std::cout << "applying PUL for collection "
+ << theCollection->getName()->getStringValue() << std::endl;
+ }
+#endif
+
+ if (numIncrementalIndices > 0)
+ {
+ theBeforeIndexDeltas.resize(numIncrementalIndices);
+ theAfterIndexDeltas.resize(numIncrementalIndices);
+ theDeletedDocsIndexDeltas.resize(numIncrementalIndices);
+ theInsertedDocsIndexDeltas.resize(numIncrementalIndices);
+
+ theNumBeforeIndexDeltasApplied.resize(numIncrementalIndices);
+ theNumAfterIndexDeltasApplied.resize(numIncrementalIndices);
+ theNumInsertedDocsIndexDeltasApplied.resize(numIncrementalIndices);
+ theNumDeletedDocsIndexDeltasApplied.resize(numIncrementalIndices);
+
+ for (csize idx = 0; idx < numIncrementalIndices; ++idx)
+ {
+ theNumBeforeIndexDeltasApplied[idx] = 0;
+ theNumAfterIndexDeltasApplied[idx] = 0;
+ theNumInsertedDocsIndexDeltasApplied[idx] = 0;
+ theNumDeletedDocsIndexDeltasApplied[idx] = 0;
+ }
+ }
+
// Don't apply anything if the collection is going to be deleted.
if (!theDeleteCollectionList.empty())
return;
@@ -2214,6 +2398,71 @@
#endif
throw;
}
+
+#if 0
+ if (theCollection != NULL)
+ {
+ std::cout << "applied PUL for collection "
+ << theCollection->getName()->getStringValue() << std::endl << std::endl;
+ }
+#endif
+}
+
+
+/*******************************************************************************
+
+********************************************************************************/
+void CollectionPul::undoUpdates()
+{
+ if (!theIsApplied)
+ return;
+
+ try
+ {
+ undoList(theTruncateCollectionList);
+ undoList(theDeleteFromCollectionList);
+ undoList(theInsertIntoCollectionList);
+ undoList(theCreateCollectionList);
+
+#ifndef ZORBA_NO_XMLSCHEMA
+ // Undo validate-in-place validation
+ undoList(theRevalidateList);
+
+ // Undo apply-updates caused validation
+ if (theValidationPul)
+ {
+ undoList(static_cast<PULImpl *>(theValidationPul.getp())->theValidationList);
+ }
+#endif
+
+ // Undo text node merging
+ std::vector<TextNodeMerge>::reverse_iterator rit = theMergeList.rbegin();
+ std::vector<TextNodeMerge>::reverse_iterator rend = theMergeList.rend();
+ for (; rit != rend; ++rit)
+ {
+ TextNodeMerge merge = (*rit);
+ XmlNode* newTextNode = merge.theParent->getChild(merge.thePos);
+ ZORBA_ASSERT(newTextNode->getNodeKind()== store::StoreConsts::textNode);
+
+ newTextNode->detach();
+
+ for (csize j = 0; j < merge.theMergedNodes.size(); ++j)
+ merge.theMergedNodes[j]->connect(merge.theParent, merge.thePos + j);
+ }
+ theMergeList.clear();
+
+ undoList(theDeleteList);
+ undoList(theReplaceContentList);
+ undoList(theReplaceNodeList);
+ undoList(theInsertList);
+ undoList(theDoFirstList);
+
+ undoRefreshIndexes();
+ }
+ catch (...)
+ {
+ ZORBA_FATAL(0, "Unexpected error during pul undo");
+ }
}
@@ -2228,9 +2477,7 @@
{
try
{
- // Refresh each incrementally maintained index using its before and after
- // deltas.
- refreshIndices();
+ truncateIndexes();
// If necessary, adjust the position of trees inside this collection.
if (theAdjustTreePositions)
@@ -2241,9 +2488,8 @@
// Detach nodes that were deleted from their trees due to replace-node,
// replace-content, or delete-node XQUF primitives.
- csize numUpdates;
+ csize numUpdates = theReplaceNodeList.size();
- numUpdates = theReplaceNodeList.size();
for (csize i = 0; i < numUpdates; ++i)
{
UpdatePrimitive* upd = theReplaceNodeList[i];
@@ -2318,61 +2564,6 @@
}
-/*******************************************************************************
-
-********************************************************************************/
-void CollectionPul::undoUpdates()
-{
- if (!theIsApplied)
- return;
-
- try
- {
- undoList(theTruncateCollectionList);
- undoList(theDeleteFromCollectionList);
- undoList(theInsertIntoCollectionList);
- undoList(theCreateCollectionList);
-
-#ifndef ZORBA_NO_XMLSCHEMA
- // Undo validate-in-place validation
- undoList(theRevalidateList);
-
- // Undo apply-updates caused validation
- if (theValidationPul)
- {
- undoList(static_cast<PULImpl *>(theValidationPul.getp())->theValidationList);
- }
-#endif
-
- // Undo text node merging
- std::vector<TextNodeMerge>::reverse_iterator rit = theMergeList.rbegin();
- std::vector<TextNodeMerge>::reverse_iterator rend = theMergeList.rend();
- for (; rit != rend; ++rit)
- {
- TextNodeMerge merge = (*rit);
- XmlNode* newTextNode = merge.theParent->getChild(merge.thePos);
- ZORBA_ASSERT(newTextNode->getNodeKind()== store::StoreConsts::textNode);
-
- newTextNode->detach();
-
- for (csize j = 0; j < merge.theMergedNodes.size(); ++j)
- merge.theMergedNodes[j]->connect(merge.theParent, merge.thePos + j);
- }
- theMergeList.clear();
-
- undoList(theDeleteList);
- undoList(theReplaceContentList);
- undoList(theReplaceNodeList);
- undoList(theInsertList);
- undoList(theDoFirstList);
- }
- catch (...)
- {
- ZORBA_FATAL(0, "Unexpected error during pul undo");
- }
-}
-
-
} // namespace simplestore
} // namespace zorba
/* vim:set et sw=2 ts=2: */
=== modified file 'src/store/naive/simple_pul.h'
--- src/store/naive/simple_pul.h 2012-04-24 12:39:38 +0000
+++ src/store/naive/simple_pul.h 2012-04-27 09:11:24 +0000
@@ -204,6 +204,11 @@
std::vector<store::IndexDelta> theInsertedDocsIndexDeltas;
std::vector<store::IndexDelta> theDeletedDocsIndexDeltas;
+ std::vector<csize> theNumBeforeIndexDeltasApplied;
+ std::vector<csize> theNumAfterIndexDeltasApplied;
+ std::vector<csize> theNumInsertedDocsIndexDeltasApplied;
+ std::vector<csize> theNumDeletedDocsIndexDeltasApplied;
+
public:
CollectionPul(PULImpl* pul, Collection* collection);
@@ -211,18 +216,18 @@
void switchPul(PULImpl* pul);
+ void computeIndexBeforeDeltas();
+
+ void computeIndexAfterDeltas();
+
+ void refreshIndexes();
+
void applyUpdates();
+ void undoUpdates();
+
void finalizeUpdates();
- void undoUpdates();
-
- void computeIndexBeforeDeltas();
-
- void computeIndexAfterDeltas();
-
- void refreshIndices();
-
void setAdjustTreePositions() { theAdjustTreePositions = true; }
void addToCheckForMerge(InternalNode* parent) { theMergeToCheckSet.insert(parent); }
@@ -231,6 +236,12 @@
void switchPulInPrimitivesList(std::vector<UpdatePrimitive*>& list);
void computeIndexDeltas(std::vector<store::IndexDelta>& deltas);
+
+ void cleanIndexDeltas();
+
+ void truncateIndexes();
+
+ void undoRefreshIndexes();
};
@@ -273,11 +284,14 @@
UP_LIST_CREATE_INDEX
};
- typedef std::map<const QNameItem*, CollectionPul*> CollectionPulMap;
+ typedef std::vector<CollectionPul*> CollectionPuls;
+
+ typedef std::map<const QNameItem*, csize> CollectionPulMap;
protected:
// XQUF and collection primitives, grouped by the collection that is being updated.
- CollectionPulMap theCollectionPuls;
+ CollectionPuls theCollectionPuls;
+ CollectionPulMap theCollectionPulsMap;
CollectionPul * theNoCollectionPul;
CollectionPul * theLastPul;
const QNameItem * theLastCollection;
=== modified file 'src/store/naive/store.cpp'
--- src/store/naive/store.cpp 2012-04-18 11:16:33 +0000
+++ src/store/naive/store.cpp 2012-04-27 09:11:24 +0000
@@ -523,23 +523,24 @@
********************************************************************************/
void Store::populateValueIndex(
- const store::Index_t& aIndex,
- store::Iterator* aSourceIter,
- ulong aNumColumns)
+ const store::Index_t& idx,
+ store::Iterator* sourceIter,
+ ulong numColumns)
{
- if (!aSourceIter)
+ if (!sourceIter)
return;
store::Item_t domainItem;
store::IndexKey* key = NULL;
-
- ValueIndex* index = static_cast<ValueIndex*>(aIndex.getp());
-
- aSourceIter->open();
+ store::IndexKey* key2 = NULL;
+
+ ValueIndex* index = static_cast<ValueIndex*>(idx.getp());
+
+ sourceIter->open();
try
{
- while (aSourceIter->next(domainItem))
+ while (sourceIter->next(domainItem))
{
if (domainItem->isNode() &&
domainItem->getCollection() == NULL &&
@@ -549,12 +550,12 @@
ERROR_PARAMS(index->getName()->getStringValue()));
}
- if (key == NULL)
- key = new store::IndexKey(aNumColumns);
+ if (key2 == key)
+ key = new store::IndexKey(numColumns);
- for (ulong i = 0; i < aNumColumns; ++i)
+ for (ulong i = 0; i < numColumns; ++i)
{
- if (!aSourceIter->next((*key)[i]))
+ if (!sourceIter->next((*key)[i]))
{
// The source iter is a ValueIndexEntryBuilderIterator, whose next()
// method is guaranteed to return true exactly once. The result from
@@ -564,7 +565,8 @@
}
}
- index->insert(key, domainItem);
+ key2 = key;
+ index->insert(key2, domainItem);
}
}
catch(...)
@@ -572,14 +574,11 @@
if (key != NULL)
delete key;
- aSourceIter->close();
+ sourceIter->close();
throw;
}
- if (key != NULL)
- delete key;
-
- aSourceIter->close();
+ sourceIter->close();
}
=== modified file 'src/store/naive/store_defs.h'
--- src/store/naive/store_defs.h 2012-04-24 12:39:38 +0000
+++ src/store/naive/store_defs.h 2012-04-27 09:11:24 +0000
@@ -55,6 +55,28 @@
#define COMMENT_NODE(item) (reinterpret_cast<CommentNode*>((item).getp()))
+
+#ifndef NDEBUG
+
+#define STORE_TRACE(level, msg) \
+{ \
+ if (level <= GET_STORE().getTraceLevel()) \
+ std::cout << msg << std::endl; \
+}
+
+#define STORE_TRACE1(msg) STORE_TRACE(1, msg);
+#define STORE_TRACE2(msg) STORE_TRACE(2, msg);
+#define STORE_TRACE3(msg) STORE_TRACE(3, msg);
+
+#else
+
+#define STORE_TRACE(msg)
+#define STORE_TRACE1(msg)
+#define STORE_TRACE2(msg)
+#define STORE_TRACE3(msg)
+
+#endif
+
}
}
#endif
=== added file 'test/rbkt/ExpQueryResults/zorba/index/delete_from_collection_01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/index/delete_from_collection_01.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/index/delete_from_collection_01.xml.res 2012-04-27 09:11:24 +0000
@@ -0,0 +1,1 @@
+<foo uri="1"/>
=== added file 'test/rbkt/ExpQueryResults/zorba/index/undo2.xml.res'
--- test/rbkt/ExpQueryResults/zorba/index/undo2.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/index/undo2.xml.res 2012-04-27 09:11:24 +0000
@@ -0,0 +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"/>
=== added file 'test/rbkt/ExpQueryResults/zorba/index/undo3.xml.res'
--- test/rbkt/ExpQueryResults/zorba/index/undo3.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/index/undo3.xml.res 2012-04-27 09:11:24 +0000
@@ -0,0 +1,6 @@
+<?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"/>
=== added file 'test/rbkt/ExpQueryResults/zorba/index/unique.xml.res'
--- test/rbkt/ExpQueryResults/zorba/index/unique.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/index/unique.xml.res 2012-04-27 09:11:24 +0000
@@ -0,0 +1,1 @@
+zerr:ZDDY0024 zerr:ZDDY0024<person id="5"/><person id="5"/>
=== added file 'test/rbkt/Queries/zorba/index/delete_from_collection_01.xq'
--- test/rbkt/Queries/zorba/index/delete_from_collection_01.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/index/delete_from_collection_01.xq 2012-04-27 09:11:24 +0000
@@ -0,0 +1,13 @@
+
+import module namespace seq = "http://www.foo.com/default" at "delete_from_collection_01.xqlib";
+
+seq:init();
+
+variable $foo := seq:index();
+
+seq:reset();
+
+variable $bar := seq:index();
+
+
+$foo, $bar
=== added file 'test/rbkt/Queries/zorba/index/delete_from_collection_01.xqlib'
--- test/rbkt/Queries/zorba/index/delete_from_collection_01.xqlib 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/index/delete_from_collection_01.xqlib 2012-04-27 09:11:24 +0000
@@ -0,0 +1,42 @@
+module namespace seq = "http://www.foo.com/default";
+
+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 an = "http://www.zorba-xquery.com/annotations";
+
+
+declare collection seq:counters as node()*;
+
+
+declare %an:automatic %an:unique %an:value-equality index seq:counters-by-uri
+ on nodes dml:collection(xs:QName("seq:counters"))
+ by xs:string(./@uri) as xs:string;
+
+
+declare %an:sequential function seq:init()
+{
+ ddl:create(xs:QName("seq:counters"));
+ iddl:create(xs:QName("seq:counters-by-uri"));
+ dml:insert-nodes(xs:QName("seq:counters"), <foo uri="1"/>);
+};
+
+
+declare function seq:index ()
+{
+ idml:probe-index-point-value(xs:QName("seq:counters-by-uri"), "1")
+};
+
+
+declare %an:sequential function seq:reset ()
+{
+ dml:delete-nodes(idml:probe-index-point-value(xs:QName("seq:counters-by-uri"), "1"));
+};
+
+
+
=== added file 'test/rbkt/Queries/zorba/index/undo2.xq'
--- test/rbkt/Queries/zorba/index/undo2.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/index/undo2.xq 2012-04-27 09:11:24 +0000
@@ -0,0 +1,43 @@
+import module namespace u = "http://www.zorba-xquery.com/unique-index" at "undo2.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:auctions1, <person id="1" key="5"/>);
+dml:insert-nodes($u:auctions1, <person id="2" key="5"/>);
+
+try
+{{
+ (
+ dml:insert-nodes($u:auctions1, <person id="3" key="1"/>),
+
+ insert node <foo/> into dml:collection($u:auctions1)[1],
+
+ dml:insert-nodes($u:auctions1, <person id="4" key="5"/>),
+
+ replace value of node dml:collection($u:auctions1)[1]/@key with "1",
+
+ dml:insert-nodes($u:auctions2, <person id="1"/>),
+ dml:insert-nodes($u:auctions2, <person id="1"/>));
+ ()
+}}
+catch *
+{
+ $err:code
+}
+,
+
+dml:collection($u:auctions1)
+,
+idml:probe-index-point-value($u:PersonId1, "1")
+,
+idml:probe-index-point-value($u:PersonId1, "3")
+,
+idml:probe-index-point-value($u:PersonId1, "5")
+,
+dml:collection($u:auctions2)
=== added file 'test/rbkt/Queries/zorba/index/undo2.xqlib'
--- test/rbkt/Queries/zorba/index/undo2.xqlib 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/index/undo2.xqlib 2012-04-27 09:11:24 +0000
@@ -0,0 +1,36 @@
+module namespace auctions = "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 $auctions:auctions1 := xs:QName("auctions:auctions1");
+declare variable $auctions:PersonId1 := xs:QName("auctions:PersonId1");
+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);
+
+ ddl:create($auctions:auctions2);
+
+ iddl:create($auctions:PersonId1);
+
+ iddl:create($auctions:PersonId2);
+};
=== added file 'test/rbkt/Queries/zorba/index/undo3.xq'
--- test/rbkt/Queries/zorba/index/undo3.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/index/undo3.xq 2012-04-27 09:11:24 +0000
@@ -0,0 +1,59 @@
+import module namespace u = "http://www.zorba-xquery.com/unique-index" at "undo2.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:auctions1, <person id="1" key="5"/>);
+dml:insert-nodes($u:auctions1, <person id="2" key="5"/>);
+
+try
+{{
+ (
+ dml:insert-nodes($u:auctions1, <person id="3" key="1"/>),
+
+ insert node <foo/> into dml:collection($u:auctions1)[1],
+
+ dml:insert-nodes($u:auctions1, <person id="4" key="5"/>),
+
+ replace value of node dml:collection($u:auctions1)[1]/@key with "1",
+
+ dml:delete-nodes-first($u:auctions1, 1),
+
+ dml:insert-nodes($u:auctions2, <person id="1"/>),
+ dml:insert-nodes($u:auctions2, <person id="1"/>));
+ ()
+}}
+catch *
+{
+ $err:code
+}
+,
+"
+"
+,
+dml:collection($u:auctions1)
+,
+"
+"
+,
+idml:probe-index-point-value($u:PersonId1, "1")
+,
+"
+"
+,
+idml:probe-index-point-value($u:PersonId1, "3")
+,
+"
+"
+,
+idml:probe-index-point-value($u:PersonId1, "5")
+,
+"
+"
+,
+dml:collection($u:auctions2)
=== added file 'test/rbkt/Queries/zorba/index/unique.xq'
--- test/rbkt/Queries/zorba/index/unique.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/index/unique.xq 2012-04-27 09:11:24 +0000
@@ -0,0 +1,50 @@
+import module namespace u = "http://www.zorba-xquery.com/unique-index" at "unique.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:auctions1, <person id="5"/>);
+
+try
+{{
+ (dml:insert-nodes($u:auctions1, <person id="1"/>),
+ dml:insert-nodes($u:auctions1, <person id="1"/>));
+ ()
+}}
+catch *
+{
+ $err:code
+}
+,
+
+try
+{{
+ (
+ dml:insert-nodes($u:auctions1, <person id="1"/>),
+ dml:insert-nodes($u:auctions1, <person id="3"/>),
+ dml:delete-nodes-first($u:auctions1, 1),
+
+ dml:insert-nodes($u:auctions2, <person id="1"/>),
+ dml:insert-nodes($u:auctions2, <person id="1"/>));
+ ()
+}}
+catch *
+{
+ $err:code
+}
+,
+
+dml:collection($u:auctions1)
+,
+idml:probe-index-point-value($u:PersonId1, "1")
+,
+idml:probe-index-point-value($u:PersonId1, "3")
+,
+idml:probe-index-point-value($u:PersonId1, "5")
+,
+dml:collection($u:auctions2)
=== added file 'test/rbkt/Queries/zorba/index/unique.xqlib'
--- test/rbkt/Queries/zorba/index/unique.xqlib 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/index/unique.xqlib 2012-04-27 09:11:24 +0000
@@ -0,0 +1,37 @@
+module namespace auctions = "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 $auctions:auctions1 := xs:QName("auctions:auctions1");
+declare variable $auctions:PersonId1 := xs:QName("auctions:PersonId1");
+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:unique %an:automatic %an:value-equality index auctions:PersonId1
+on nodes dml:collection(xs:QName("auctions:auctions1"))
+by xs:string(./@id) 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);
+
+ ddl:create($auctions:auctions2);
+
+ iddl:create($auctions:PersonId1);
+
+ iddl:create($auctions:PersonId2);
+};
Follow ups
-
[Merge] lp:~zorba-coders/zorba/bug-966706 into lp:zorba
From: noreply, 2012-05-03
-
[Merge] lp:~zorba-coders/zorba/bug-966706 into lp:zorba
From: Zorba Build Bot, 2012-05-03
-
[Merge] lp:~zorba-coders/zorba/bug-966706 into lp:zorba
From: Zorba Build Bot, 2012-05-03
-
[Merge] lp:~zorba-coders/zorba/bug-966706 into lp:zorba
From: Markos Zaharioudakis, 2012-05-03
-
[Merge] lp:~zorba-coders/zorba/bug-966706 into lp:zorba
From: Zorba Build Bot, 2012-05-03
-
Re: [Merge] lp:~zorba-coders/zorba/bug-966706 into lp:zorba
From: Zorba Build Bot, 2012-05-03
-
[Merge] lp:~zorba-coders/zorba/bug-966706 into lp:zorba
From: Markos Zaharioudakis, 2012-05-03
-
[Merge] lp:~zorba-coders/zorba/bug-966706 into lp:zorba
From: Zorba Build Bot, 2012-05-03
-
Re: [Merge] lp:~zorba-coders/zorba/bug-966706 into lp:zorba
From: Zorba Build Bot, 2012-05-03
-
[Merge] lp:~zorba-coders/zorba/bug-966706 into lp:zorba
From: Markos Zaharioudakis, 2012-05-03
-
Re: [Merge] lp:~zorba-coders/zorba/bug-966706 into lp:zorba
From: Markos Zaharioudakis, 2012-05-03
-
Re: [Merge] lp:~zorba-coders/zorba/bug-966706 into lp:zorba
From: Till Westmann, 2012-04-27
-
Re: [Merge] lp:~zorba-coders/zorba/bug-966706 into lp:zorba
From: Matthias Brantner, 2012-04-27
-
[Merge] lp:~zorba-coders/zorba/bug-966706 into lp:zorba
From: Matthias Brantner, 2012-04-27