Merge lp:~zorba-coders/zorba/bug-966706 into lp:zorba

Proposed by Matthias Brantner
Status: Merged
Approved by: Markos Zaharioudakis
Approved revision: 10749
Merged at revision: 10817
Proposed branch: lp:~zorba-coders/zorba/bug-966706
Merge into: lp:zorba
Diff against target: 2245 lines (+925/-429)
23 files modified
ChangeLog (+1/-0)
src/runtime/core/apply_updates.cpp (+11/-5)
src/runtime/indexing/doc_indexer.cpp (+4/-6)
src/store/naive/node_items.cpp (+23/-23)
src/store/naive/node_items.h (+0/-22)
src/store/naive/pul_primitives.cpp (+33/-43)
src/store/naive/simple_index_value.cpp (+14/-13)
src/store/naive/simple_index_value.h (+9/-3)
src/store/naive/simple_pul.cpp (+476/-285)
src/store/naive/simple_pul.h (+24/-10)
src/store/naive/store.cpp (+18/-19)
src/store/naive/store_defs.h (+22/-0)
test/rbkt/ExpQueryResults/zorba/index/delete_from_collection_01.xml.res (+1/-0)
test/rbkt/ExpQueryResults/zorba/index/undo2.xml.res (+2/-0)
test/rbkt/ExpQueryResults/zorba/index/undo3.xml.res (+6/-0)
test/rbkt/ExpQueryResults/zorba/index/unique.xml.res (+1/-0)
test/rbkt/Queries/zorba/index/delete_from_collection_01.xq (+13/-0)
test/rbkt/Queries/zorba/index/delete_from_collection_01.xqlib (+42/-0)
test/rbkt/Queries/zorba/index/undo2.xq (+43/-0)
test/rbkt/Queries/zorba/index/undo2.xqlib (+36/-0)
test/rbkt/Queries/zorba/index/undo3.xq (+59/-0)
test/rbkt/Queries/zorba/index/unique.xq (+50/-0)
test/rbkt/Queries/zorba/index/unique.xqlib (+37/-0)
To merge this branch: bzr merge lp:~zorba-coders/zorba/bug-966706
Reviewer Review Type Date Requested Status
Markos Zaharioudakis Approve
Till Westmann Approve
Matthias Brantner Approve
Review via email: mp+103835@code.launchpad.net

This proposal supersedes a proposal from 2012-04-11.

Commit message

fixed bug #966706 (key uniqueness of value equality index not enforced)

Description of the change

fixed bug #966706 (key uniqueness of value equality index not enforced)

To post a comment you must log in.
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote : Posted in a previous version of this proposal

Attempt to merge into lp:zorba failed due to conflicts:

text conflict in ChangeLog

Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote : Posted in a previous version of this proposal
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote : Posted in a previous version of this proposal

Validation queue job bug-966706-2012-04-11T07-20-03.19Z is finished. The final status was:

All tests succeeded!

Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote : Posted in a previous version of this proposal

Voting does not meet specified criteria. Required: Approve > 1, Disapprove < 1, Needs Fixing < 1, Pending < 1. Got: 3 Pending.

Revision history for this message
Markos Zaharioudakis (markos-za) wrote : Posted in a previous version of this proposal

The problem is that now an index refresh must be undoable. I am looking at the code to think wat is the best way to do the undo.

review: Needs Fixing
Revision history for this message
Markos Zaharioudakis (markos-za) : Posted in a previous version of this proposal
review: Approve
Revision history for this message
Markos Zaharioudakis (markos-za) wrote : Posted in a previous version of this proposal

I have implemented undo for incrementally maintained indexes.

Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote : Posted in a previous version of this proposal

Attempt to merge into lp:zorba failed due to conflicts:

text conflict in ChangeLog

Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote : Posted in a previous version of this proposal
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote : Posted in a previous version of this proposal

The attempt to merge lp:~zorba-coders/zorba/bug-966706 into lp:zorba failed. Below is the output from the failed tests.

CMake Error at /home/ceej/zo/testing/zorbatest/tester/TarmacLander.cmake:274 (message):
  Validation queue job bug-966706-2012-04-23T12-28-50.058Z is finished. The
  final status was:

  1 tests did not succeed - changes not commited.

Error in read script: /home/ceej/zo/testing/zorbatest/tester/TarmacLander.cmake

Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote : Posted in a previous version of this proposal
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote : Posted in a previous version of this proposal

Validation queue job bug-966706-2012-04-23T13-08-37.923Z is finished. The final status was:

All tests succeeded!

Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote : Posted in a previous version of this proposal

Voting does not meet specified criteria. Required: Approve > 1, Disapprove < 1, Needs Fixing < 1, Pending < 1. Got: 2 Approve, 2 Pending.

Revision history for this message
Matthias Brantner (matthias-brantner) : Posted in a previous version of this proposal
review: Approve
Revision history for this message
Matthias Brantner (matthias-brantner) wrote : Posted in a previous version of this proposal

It seems that automatic indexes are not maintained if a node is deleted. The following example shows this:

library module:

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"));
};

main module:

import module namespace seq = "http://www.foo.com/default" at "default.xq";

seq:init();

variable $foo := seq:index();

seq:reset();

variable $bar := seq:index();

$foo, $bar

The expected result is '<foo uri="1"/><foo uri="1"/>' but should be '<foo uri="1"/>'.

review: Needs Fixing
Revision history for this message
Markos Zaharioudakis (markos-za) wrote : Posted in a previous version of this proposal

I have fixed your test, but now I have a problem with test index/undo3.xq. Its result is non-deterministic. Most of the time it returns the correct result, but sometimes not. And valgrind does not show any errors :(

Revision history for this message
Markos Zaharioudakis (markos-za) wrote : Posted in a previous version of this proposal

This is ready for review again.

Revision history for this message
Matthias Brantner (matthias-brantner) wrote :

Looks good. I have disabled some debug output in rev. 10748.

review: Approve
Revision history for this message
Till Westmann (tillw) wrote :

It would be nice to have 2 comments explaining
1) the modification of the parameter in simple_index_value.cpp:380 and 674 and
2) the role of key2 in Store::populateValueIndex.

It would also be nice to use the typedef here:

=== modified file 'src/store/naive/simple_pul.cpp'
--- src/store/naive/simple_pul.cpp 2012-04-27 19:58:40 +0000
+++ src/store/naive/simple_pul.cpp 2012-04-27 20:03:20 +0000
@@ -1463,8 +1463,8 @@
 {
   csize numRoots = rootNodes.size();

- std::vector<CollectionPul*>::const_iterator collIte = theCollectionPuls.begin();
- std::vector<CollectionPul*>::const_iterator collEnd = theCollectionPuls.end();
+ CollectionPuls::const_iterator collIte = theCollectionPuls.begin();
+ CollectionPuls::const_iterator collEnd = theCollectionPuls.end();

   for (; collIte != collEnd; ++collIte)
   {

review: Approve
Revision history for this message
Markos Zaharioudakis (markos-za) :
review: Approve
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

Attempt to merge into lp:zorba failed due to conflicts:

text conflict in src/store/naive/simple_pul.cpp

Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

Attempt to merge into lp:zorba failed due to conflicts:

text conflict in src/store/naive/simple_pul.cpp

lp:~zorba-coders/zorba/bug-966706 updated
10749. By Markos Zaharioudakis

merge from trunk

Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :
Revision history for this message
Zorba Build Bot (zorba-buildbot) wrote :

Validation queue job bug-966706-2012-05-03T10-09-44.874Z is finished. The final status was:

All tests succeeded!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ChangeLog'
2--- ChangeLog 2012-05-03 09:13:18 +0000
3+++ ChangeLog 2012-05-03 10:05:25 +0000
4@@ -36,6 +36,7 @@
5 * Fixed bug #967428 (do not hoist index creation outside a try-catch)
6 * Fixed performance problem with the findNodeSources function of the no-copy rule
7 * Fixed bug #872234 (prevent a rewritting to take place in case of sequential expr)
8+ * Fixed bug #966706 (key uniqueness of index not enforced during incremental refresh)
9 * Fixed bug #906494 (default compile with D_FILE_OFFSET_BITS=64)
10 * Fixed bug #988412 (date:current-dateTime daylight saving)
11 * Fixed bug #912586, #912593 and #912722 (assertion failures with lax validation)
12
13=== modified file 'src/runtime/core/apply_updates.cpp'
14--- src/runtime/core/apply_updates.cpp 2012-04-24 12:39:38 +0000
15+++ src/runtime/core/apply_updates.cpp 2012-05-03 10:05:25 +0000
16@@ -92,19 +92,24 @@
17
18 store::Item_t item;
19 ulong numItems = 0;
20- std::auto_ptr<store::PUL> pul;
21+ store::PUL_t pul;
22
23 ApplyIteratorState* state;
24 DEFAULT_STACK_INIT(ApplyIteratorState, state, planState);
25
26- pul.reset(GENV_ITEMFACTORY->createPendingUpdateList());
27-
28 // Note: updating expr might not return a pul because of vacuous exprs
29 while (consumeNext(item, theChild, planState))
30 {
31 if (item->isPul())
32 {
33- pul->mergeUpdates(item);
34+ if (pul)
35+ {
36+ pul->mergeUpdates(item);
37+ }
38+ else
39+ {
40+ pul.transfer(item);
41+ }
42 }
43 else if (!theDiscardXDM)
44 {
45@@ -113,7 +118,8 @@
46 }
47 }
48
49- apply_updates(ccb, gdctx, theSctx, pul.get(), loc);
50+ if(pul)
51+ apply_updates(ccb, gdctx, theSctx, pul, loc);
52
53 state->theXDMIte = state->theXDMItems.begin();
54 state->theXDMEnd = state->theXDMItems.end();
55
56=== modified file 'src/runtime/indexing/doc_indexer.cpp'
57--- src/runtime/indexing/doc_indexer.cpp 2012-04-24 12:39:38 +0000
58+++ src/runtime/indexing/doc_indexer.cpp 2012-05-03 10:05:25 +0000
59@@ -84,7 +84,7 @@
60 QueryLoc::null,
61 tmp);
62
63- ulong numEntries = delta.size();
64+ csize numEntries = delta.size();
65 store::Item_t domainNode;
66 store::IndexKey* key = NULL;
67
68@@ -96,13 +96,11 @@
69
70 //std::cout << domainNode.getp() << " " << key << std::endl;
71
72- for (ulong i = 0; i < theNumColumns; ++i)
73+ for (csize i = 0; i < theNumColumns; ++i)
74 {
75 if (!thePlanWrapper->next((*key)[i]))
76- throw ZORBA_EXCEPTION(
77- zerr::ZXQP0003_INTERNAL_ERROR,
78- ERROR_PARAMS( ZED( IncompleteKeyInIndexRefresh ) )
79- );
80+ throw ZORBA_EXCEPTION(zerr::ZXQP0003_INTERNAL_ERROR,
81+ ERROR_PARAMS(ZED(IncompleteKeyInIndexRefresh)));
82 }
83
84 delta.resize(numEntries + 1);
85
86=== modified file 'src/store/naive/node_items.cpp'
87--- src/store/naive/node_items.cpp 2012-05-03 09:09:01 +0000
88+++ src/store/naive/node_items.cpp 2012-05-03 10:05:25 +0000
89@@ -457,7 +457,7 @@
90 #ifndef NDEBUG
91 XmlNode::~XmlNode()
92 {
93- NODE_TRACE1("Deleted " << store::StoreConsts::toString(getNodeKind()) << this);
94+ STORE_TRACE1("Deleted " << store::StoreConsts::toString(getNodeKind()) << this);
95 }
96 #endif
97
98@@ -1651,7 +1651,7 @@
99 :
100 InternalNode(store::StoreConsts::documentNode)
101 {
102- NODE_TRACE1("Loaded doc node " << this);
103+ STORE_TRACE1("Loaded doc node " << this);
104 }
105
106
107@@ -1667,7 +1667,7 @@
108 theBaseUri(baseUri),
109 theDocUri(docUri)
110 {
111- NODE_TRACE1("{\nConstructing doc node " << this << " tree = "
112+ STORE_TRACE1("{\nConstructing doc node " << this << " tree = "
113 << getTree()->getId() << ":" << getTree()
114 << " doc uri = " << docUri);
115 }
116@@ -1722,8 +1722,8 @@
117 throw;
118 }
119
120- NODE_TRACE1("}");
121- NODE_TRACE1("Copied doc node " << this << " to node " << copyNode);
122+ STORE_TRACE1("}");
123+ STORE_TRACE1("Copied doc node " << this << " to node " << copyNode);
124
125 return copyNode;
126 }
127@@ -1892,7 +1892,7 @@
128 theNodes.resize(numAttributes);
129 }
130
131- NODE_TRACE1("Loaded elem node " << this << " name = " << theName->show()
132+ STORE_TRACE1("Loaded elem node " << this << " name = " << theName->show()
133 << " num bindings = " << numBindings << " num attributes = "
134 << numAttributes << std::endl);
135 }
136@@ -2018,7 +2018,7 @@
137 throw;
138 }
139
140- NODE_TRACE1("Constructed element node " << this << " parent = "
141+ STORE_TRACE1("Constructed element node " << this << " parent = "
142 << std::hex << (parent ? (ulong)parent : 0) << " pos = " << pos
143 << " tree = " << getTree()->getId() << ":" << getTree()
144 << " ordpath = " << theOrdPath.show()
145@@ -2359,7 +2359,7 @@
146 throw;
147 }
148
149- NODE_TRACE1("Copied elem node " << this << " to node " << copyNode
150+ STORE_TRACE1("Copied elem node " << this << " to node " << copyNode
151 << " name = " << theName->getStringValue() << " parent = "
152 << (parent ? parent : 0x0)
153 << " pos = " << pos << " copy mode = " << copymode.toString());
154@@ -3327,7 +3327,7 @@
155 if (qn->isBaseUri())
156 theFlags |= IsBaseUri;
157
158- NODE_TRACE1("Loaded attr node " << this << " name = " << theName->getStringValue());
159+ STORE_TRACE1("Loaded attr node " << this << " name = " << theName->getStringValue());
160 }
161
162
163@@ -3450,7 +3450,7 @@
164 throw;
165 }
166
167- NODE_TRACE1("Constructed attribute node " << this << " parent = "
168+ STORE_TRACE1("Constructed attribute node " << this << " parent = "
169 << std::hex << (parent ? (ulong)parent : 0) << " pos = " << pos
170 << " tree = " << getTree()->getId() << ":" << getTree()
171 << " ordpath = " << theOrdPath.show()
172@@ -3533,7 +3533,7 @@
173 throw;
174 }
175
176- NODE_TRACE1("Copied attribute node " << this << " to node " << copyNode
177+ STORE_TRACE1("Copied attribute node " << this << " to node " << copyNode
178 << " name = " << theName->show() << " parent = "
179 << std::hex << (parent ? (ulong)parent : 0) << " pos = " << pos
180 << " copy mode = " << copymode.toString());
181@@ -3789,7 +3789,7 @@
182 {
183 setText(content);
184
185- NODE_TRACE1("Loaded text node " << this << " content = " << getText());
186+ STORE_TRACE1("Loaded text node " << this << " content = " << getText());
187 }
188
189
190@@ -3834,13 +3834,13 @@
191 }
192
193 #ifdef TEXT_ORDPATH
194- NODE_TRACE1("Constructed text node " << this << " parent = "
195+ STORE_TRACE1("Constructed text node " << this << " parent = "
196 << std::hex << (parent ? (ulong)parent : 0) << " pos = " << pos
197 << " tree = " << getTree()->getId() << ":" << getTree()
198 << " ordpath = " << theOrdPath.show()
199 << " content = " << getText());
200 #else
201- NODE_TRACE1("Constructed text node " << this << " parent = "
202+ STORE_TRACE1("Constructed text node " << this << " parent = "
203 << std::hex << (parent ? (ulong)parent : 0) << " pos = " << pos
204 << " tree = " << getTree()->getId() << ":" << getTree()
205 << " content = " << getText());
206@@ -3895,12 +3895,12 @@
207 p->insertChild(this, p->numChildren());
208
209 #ifdef TEXT_ORDPATH
210- NODE_TRACE1("Constructed text node " << this << " parent = "
211+ STORE_TRACE1("Constructed text node " << this << " parent = "
212 << std::hex << (parent ? (ulong)parent : 0)
213 << " ordpath = " << theOrdPath.show()
214 << " content = " << getValue()->getStringValue());
215 #else
216- NODE_TRACE1("Constructed text node " << this << " parent = "
217+ STORE_TRACE1("Constructed text node " << this << " parent = "
218 << std::hex << (parent ? (ulong)parent : 0)
219 << " content = " << getValue()->getStringValue());
220 #endif
221@@ -4012,7 +4012,7 @@
222 throw;
223 }
224
225- NODE_TRACE1("Copied text node " << this << " to node " << copyNode
226+ STORE_TRACE1("Copied text node " << this << " to node " << copyNode
227 << " parent = " << std::hex << (parent ? (ulong)parent : 0)
228 << " pos = " << pos);
229
230@@ -4497,7 +4497,7 @@
231
232 theName = qnpool.insert(zstring(), zstring(), theTarget);
233
234- NODE_TRACE1("Loaded pi node " << this << " target = " << theTarget
235+ STORE_TRACE1("Loaded pi node " << this << " target = " << theTarget
236 << std::endl);
237 }
238
239@@ -4530,7 +4530,7 @@
240 parent->insertChild(this, pos);
241 }
242
243- NODE_TRACE1("Constructed pi node " << this << " parent = "
244+ STORE_TRACE1("Constructed pi node " << this << " parent = "
245 << std::hex << (parent ? (ulong)parent : 0) << " pos = " << pos
246 << " tree = " << getTree()->getId() << ":" << getTree()
247 << " ordpath = " << theOrdPath.show() << " target = " << theTarget);
248@@ -4579,7 +4579,7 @@
249 throw;
250 }
251
252- NODE_TRACE1("Copied pi node " << this << " to node " << copyNode
253+ STORE_TRACE1("Copied pi node " << this << " to node " << copyNode
254 << " parent = " << std::hex << (parent ? (ulong)parent : 0)
255 << " pos = " << pos);
256
257@@ -4637,7 +4637,7 @@
258 {
259 theContent.take(content);
260
261- NODE_TRACE1("Loaded comment node " << this << " content = " << theContent);
262+ STORE_TRACE1("Loaded comment node " << this << " content = " << theContent);
263 }
264
265
266@@ -4663,7 +4663,7 @@
267 parent->insertChild(this, pos);
268 }
269
270- NODE_TRACE1("Constructed comment node " << this << " parent = "
271+ STORE_TRACE1("Constructed comment node " << this << " parent = "
272 << std::hex << (parent ? (ulong)parent : 0) << " pos = " << pos
273 << " tree = " << getTree()->getId() << ":" << getTree()
274 << " ordpath = " << theOrdPath.show() << " content = "
275@@ -4710,7 +4710,7 @@
276 throw;
277 }
278
279- NODE_TRACE1("Copied coment node " << this << " to node " << copyNode
280+ STORE_TRACE1("Copied coment node " << this << " to node " << copyNode
281 << " parent = " << std::hex << (parent ? (ulong)parent : 0)
282 << " pos = " << pos);
283
284
285=== modified file 'src/store/naive/node_items.h'
286--- src/store/naive/node_items.h 2012-05-03 09:09:01 +0000
287+++ src/store/naive/node_items.h 2012-05-03 10:05:25 +0000
288@@ -107,28 +107,6 @@
289 << store::StoreConsts::toString(getNodeKind()))
290
291
292-#ifndef NDEBUG
293-
294-#define NODE_TRACE(level, msg) \
295-{ \
296- if (level <= GET_STORE().getTraceLevel()) \
297- std::cout << msg << std::endl; \
298-}
299-
300-#define NODE_TRACE1(msg) NODE_TRACE(1, msg);
301-#define NODE_TRACE2(msg) NODE_TRACE(2, msg);
302-#define NODE_TRACE3(msg) NODE_TRACE(3, msg);
303-
304-#else
305-
306-#define NODE_TRACE(msg)
307-#define NODE_TRACE1(msg)
308-#define NODE_TRACE2(msg)
309-#define NODE_TRACE3(msg)
310-
311-#endif
312-
313-
314 /*******************************************************************************
315
316 theRefCount : It is the sum of theRefCounts of all the nodes belonging to
317
318=== modified file 'src/store/naive/pul_primitives.cpp'
319--- src/store/naive/pul_primitives.cpp 2012-04-24 12:39:38 +0000
320+++ src/store/naive/pul_primitives.cpp 2012-05-03 10:05:25 +0000
321@@ -35,6 +35,7 @@
322 #include "store/api/validator.h"
323
324 #include "diagnostics/xquery_diagnostics.h"
325+#include "diagnostics/util_macros.h"
326
327
328 namespace zorba {
329@@ -946,42 +947,36 @@
330 void UpdDeleteCollection::apply()
331 {
332 theCollection = GET_STORE().getCollection(theName, theDynamicCollection);
333+
334 if (theCollection == NULL)
335 return;//If two delete collection are issued in the same snapshot is a noop
336+
337 Collection* collection = static_cast<Collection*>(theCollection.getp());
338
339 std::vector<store::Index*> indexes;
340 collection->getIndexes(indexes);
341
342 if (!indexes.empty())
343- throw XQUERY_EXCEPTION(
344- zerr::ZDDY0013_COLLECTION_BAD_DESTROY_INDEXES,
345- ERROR_PARAMS( collection->getName()->getStringValue() ),
346- ERROR_LOC( theLoc )
347- );
348+ RAISE_ERROR(zerr::ZDDY0013_COLLECTION_BAD_DESTROY_INDEXES, theLoc,
349+ ERROR_PARAMS(collection->getName()->getStringValue()));
350
351 std::vector<store::IC*> activeICs;
352 collection->getActiveICs(activeICs);
353
354 if (!activeICs.empty())
355- throw XQUERY_EXCEPTION(
356- zerr::ZDDY0014_COLLECTION_BAD_DESTROY_ICS,
357- ERROR_PARAMS( collection->getName()->getStringValue() ),
358- ERROR_LOC( theLoc )
359- );
360+ RAISE_ERROR(zerr::ZDDY0014_COLLECTION_BAD_DESTROY_ICS, theLoc,
361+ ERROR_PARAMS(collection->getName()->getStringValue()));
362
363 uint64_t size;
364- try {
365+ try
366+ {
367 size = to_xs_unsignedLong(collection->size());
368- } catch (std::range_error& e)
369+ }
370+ catch (std::range_error& e)
371 {
372- throw ZORBA_EXCEPTION(
373- zerr::ZSTR0060_RANGE_EXCEPTION,
374- ERROR_PARAMS(
375- BUILD_STRING("collection too big ("
376- << e.what() << "; " << theName << ")")
377- )
378- );
379+ throw ZORBA_EXCEPTION(zerr::ZSTR0060_RANGE_EXCEPTION,
380+ ERROR_PARAMS(BUILD_STRING("collection too big ("
381+ << e.what() << "; " << theName << ")")));
382 }
383
384 for (uint64_t i = 0; i < size; ++i)
385@@ -989,11 +984,10 @@
386 XmlNode* root = static_cast<XmlNode*>(collection->nodeAt(xs_integer(i)).getp());
387 XmlTree* tree = root->getTree();
388 if (tree->getRefCount() > 1)
389- throw XQUERY_EXCEPTION(
390- zerr::ZDDY0015_COLLECTION_BAD_DESTROY_NODES,
391- ERROR_PARAMS( collection->getName()->getStringValue() ),
392- ERROR_LOC( theLoc )
393- );
394+ {
395+ RAISE_ERROR(zerr::ZDDY0015_COLLECTION_BAD_DESTROY_NODES, theLoc,
396+ ERROR_PARAMS(collection->getName()->getStringValue()));
397+ }
398 }
399
400 GET_STORE().deleteCollection(theName, theDynamicCollection);
401@@ -1013,13 +1007,13 @@
402 void UpdInsertIntoCollection::apply()
403 {
404 Collection* lColl = static_cast<Collection*>
405- (GET_STORE().getCollection(theName, theDynamicCollection).getp());
406+ (GET_STORE().getCollection(theName, theDynamicCollection).getp());
407 assert(lColl);
408
409 theIsApplied = true;
410
411- std::size_t numNodes = theNodes.size();
412- for (std::size_t i = 0; i < numNodes; ++i)
413+ csize numNodes = theNodes.size();
414+ for (csize i = 0; i < numNodes; ++i)
415 {
416 lColl->addNode(theNodes[i], xs_integer(-1));
417 ++theNumApplied;
418@@ -1030,7 +1024,7 @@
419 void UpdInsertIntoCollection::undo()
420 {
421 Collection* lColl = static_cast<Collection*>
422- (GET_STORE().getCollection(theName, theDynamicCollection).getp());
423+ (GET_STORE().getCollection(theName, theDynamicCollection).getp());
424 assert(lColl);
425
426 uint64_t lastPos;
427@@ -1040,13 +1034,9 @@
428 }
429 catch (std::range_error& e)
430 {
431- throw ZORBA_EXCEPTION(
432- zerr::ZSTR0060_RANGE_EXCEPTION,
433- ERROR_PARAMS(
434- BUILD_STRING("collection too big ("
435- << e.what() << "; " << theName << ")")
436- )
437- );
438+ throw ZORBA_EXCEPTION(zerr::ZSTR0060_RANGE_EXCEPTION,
439+ ERROR_PARAMS(BUILD_STRING("collection too big ("
440+ << e.what() << "; " << theName << ")")));
441 }
442
443 for (long i = theNumApplied-1; i >= 0; --i)
444@@ -1154,7 +1144,7 @@
445 void UpdInsertBeforeIntoCollection::apply()
446 {
447 Collection* lColl = static_cast<Collection*>
448- (GET_STORE().getCollection(theName, theDynamicCollection).getp());
449+ (GET_STORE().getCollection(theName, theDynamicCollection).getp());
450 assert(lColl);
451
452 if (!theNodes.empty())
453@@ -1170,7 +1160,7 @@
454 void UpdInsertBeforeIntoCollection::undo()
455 {
456 Collection* lColl = static_cast<Collection*>
457- (GET_STORE().getCollection(theName, theDynamicCollection).getp());
458+ (GET_STORE().getCollection(theName, theDynamicCollection).getp());
459 assert(lColl);
460 ZORBA_ASSERT(theFirstNode == lColl->nodeAt(theFirstPos));
461
462@@ -1184,7 +1174,7 @@
463 void UpdInsertAfterIntoCollection::apply()
464 {
465 Collection* lColl = static_cast<Collection*>
466- (GET_STORE().getCollection(theName, theDynamicCollection).getp());
467+ (GET_STORE().getCollection(theName, theDynamicCollection).getp());
468 assert(lColl);
469
470 if (!theNodes.empty())
471@@ -1201,7 +1191,7 @@
472 void UpdInsertAfterIntoCollection::undo()
473 {
474 Collection* lColl = static_cast<Collection*>
475- (GET_STORE().getCollection(theName, theDynamicCollection).getp());
476+ (GET_STORE().getCollection(theName, theDynamicCollection).getp());
477 assert(lColl);
478 ZORBA_ASSERT(theFirstNode == lColl->nodeAt(theFirstPos));
479
480@@ -1236,13 +1226,13 @@
481 );
482 }
483
484- std::size_t numNodes = theNodes.size();
485+ csize numNodes = theNodes.size();
486
487 bool isLast = theIsLast;
488
489 if (theIsLast)
490 {
491- for (std::size_t i = numNodes; i > 0; --i)
492+ for (csize i = numNodes; i > 0; --i)
493 {
494 if (theNodes[i-1] != lColl->nodeAt(xs_integer(size - i)))
495 {
496@@ -1270,7 +1260,7 @@
497 void UpdDeleteNodesFromCollection::undo()
498 {
499 Collection* lColl = static_cast<Collection*>
500- (GET_STORE().getCollection(theName, theDynamicCollection).getp());
501+ (GET_STORE().getCollection(theName, theDynamicCollection).getp());
502 assert(lColl);
503
504 for (std::size_t i = 0; i < theNumApplied; ++i)
505@@ -1289,7 +1279,7 @@
506 void UpdTruncateCollection::apply()
507 {
508 Collection* lColl = static_cast<Collection*>
509- (GET_STORE().getCollection(theName, theDynamicCollection).getp());
510+ (GET_STORE().getCollection(theName, theDynamicCollection).getp());
511 assert(lColl);
512
513 lColl->removeAll();
514
515=== modified file 'src/store/naive/simple_index_value.cpp'
516--- src/store/naive/simple_index_value.cpp 2012-05-02 23:15:16 +0000
517+++ src/store/naive/simple_index_value.cpp 2012-05-03 10:05:25 +0000
518@@ -368,9 +368,9 @@
519 ERROR_PARAMS(key->toString(), theQname->getStringValue()));
520 }
521
522- ValueIndexValue* valueSet = NULL;
523+ IndexMap::iterator pos = theMap.find(key);
524
525- if (theMap.get(key, valueSet))
526+ if (pos != theMap.end())
527 {
528 if (isUnique())
529 {
530@@ -378,21 +378,20 @@
531 ERROR_PARAMS(theQname->getStringValue()));
532 }
533
534- valueSet->resize(valueSet->size() + 1);
535- (*valueSet)[valueSet->size()-1].transfer(value);
536-
537+ (*pos).second->transfer_back(value);
538+ key = const_cast<store::IndexKey*>((*pos).first);
539+
540 return true;
541 }
542
543- valueSet = new ValueIndexValue(1);
544+ ValueIndexValue* valueSet = new ValueIndexValue(1);
545 (*valueSet)[0].transfer(value);
546
547 //std::cout << "Index Entry Insert [" << key << ","
548 // << valueSet << "]" << std::endl;
549
550- const store::IndexKey* key2 = key;
551- theMap.insert(key2, valueSet);
552- key = NULL; // ownership of the key obj passes to the index.
553+ // Note: ownership of the key obj passes to the index.
554+ theMap.insert(key, valueSet);
555
556 return false;
557 }
558@@ -409,7 +408,7 @@
559 ********************************************************************************/
560 bool ValueHashIndex::remove(
561 const store::IndexKey* key,
562- store::Item_t& value,
563+ const store::Item_t& value,
564 bool all)
565 {
566 if (key->size() != getNumColumns())
567@@ -653,7 +652,7 @@
568 #if 0
569 std::cout << "inserting entry : [(";
570
571- for (ulong i = 0; i < getNumColumns(); i++)
572+ for (csize i = 0; i < getNumColumns(); i++)
573 {
574 if (key[i] != NULL)
575 std::cout << key[i]->getStringValue() << ", ";
576@@ -676,14 +675,16 @@
577 }
578
579 pos->second->transfer_back(value);
580+ key = const_cast<store::IndexKey*>(pos->first);
581+
582 return true;
583 }
584
585 ValueIndexValue* valueSet = new ValueIndexValue(1);
586 (*valueSet)[0].transfer(value);
587
588+ // Note: ownership of the key obj passes to the index.
589 theMap.insert(IndexMapPair(key, valueSet));
590- key = NULL; // ownership of the key obj passes to the index.
591
592 return false;
593 }
594@@ -694,7 +695,7 @@
595 ********************************************************************************/
596 bool ValueTreeIndex::remove(
597 const store::IndexKey* key,
598- store::Item_t& value,
599+ const store::Item_t& value,
600 bool all)
601 {
602 if (key->size() != getNumColumns())
603
604=== modified file 'src/store/naive/simple_index_value.h'
605--- src/store/naive/simple_index_value.h 2012-04-24 12:39:38 +0000
606+++ src/store/naive/simple_index_value.h 2012-05-03 10:05:25 +0000
607@@ -88,11 +88,13 @@
608 public:
609 const XQPCollator* getCollator(ulong i) const;
610
611+ virtual bool isTreeIndex() = 0;
612+
613 virtual bool insert(store::IndexKey*& key, store::Item_t& item) = 0;
614
615 virtual bool remove(
616 const store::IndexKey* key,
617- store::Item_t& item,
618+ const store::Item_t& item,
619 bool all = false) = 0;
620 };
621
622@@ -142,6 +144,8 @@
623 ~ValueHashIndex();
624
625 public:
626+ bool isTreeIndex() { return false; }
627+
628 void clear();
629
630 ulong size() const;
631@@ -150,7 +154,7 @@
632
633 bool insert(store::IndexKey*& key, store::Item_t& item);
634
635- bool remove(const store::IndexKey* key, store::Item_t& item, bool all);
636+ bool remove(const store::IndexKey* key, const store::Item_t& item, bool all);
637 };
638
639
640@@ -227,6 +231,8 @@
641 ~ValueTreeIndex();
642
643 public:
644+ bool isTreeIndex() { return true; }
645+
646 void clear();
647
648 ulong size() const;
649@@ -235,7 +241,7 @@
650
651 bool insert(store::IndexKey*& key, store::Item_t& item);
652
653- bool remove(const store::IndexKey* key, store::Item_t& item, bool all = false);
654+ bool remove(const store::IndexKey* key, const store::Item_t& item, bool all = false);
655 };
656
657
658
659=== modified file 'src/store/naive/simple_pul.cpp'
660--- src/store/naive/simple_pul.cpp 2012-05-02 22:59:31 +0000
661+++ src/store/naive/simple_pul.cpp 2012-05-03 10:05:25 +0000
662@@ -58,28 +58,6 @@
663 /*******************************************************************************
664
665 ********************************************************************************/
666-void cleanIndexDeltas(std::vector<store::IndexDelta>& deltas)
667-{
668- std::vector<store::IndexDelta>::iterator ite = deltas.begin();
669- std::vector<store::IndexDelta>::iterator end = deltas.end();
670-
671- for (; ite != end; ++ite)
672- {
673- store::IndexDelta::iterator ite2 = (*ite).begin();
674- store::IndexDelta::iterator end2 = (*ite).end();
675-
676- for (; ite2 != end2; ++ite2)
677- {
678- if ((*ite2).second)
679- delete (*ite2).second;
680- }
681- }
682-}
683-
684-
685-/*******************************************************************************
686-
687-********************************************************************************/
688 void applyList(std::vector<UpdatePrimitive*>& aVector)
689 {
690 std::vector<UpdatePrimitive*>::iterator iter = aVector.begin();
691@@ -97,9 +75,9 @@
692 ********************************************************************************/
693 void undoList(std::vector<UpdatePrimitive*>& list)
694 {
695- ulong size = (ulong)list.size();
696+ csize size = list.size();
697
698- for (ulong i = size; i > 0; --i)
699+ for (csize i = size; i > 0; --i)
700 {
701 if (list[i-1]->isApplied())
702 list[i-1]->undo();
703@@ -150,14 +128,14 @@
704
705 cleanList(theValidationList);
706
707- CollectionPulMap::iterator ite = theCollectionPuls.begin();
708- CollectionPulMap::iterator end = theCollectionPuls.end();
709+ CollectionPuls::iterator ite = theCollectionPuls.begin();
710+ CollectionPuls::iterator end = theCollectionPuls.end();
711
712 for (; ite != end; ++ite)
713 {
714- if ((*ite).second != NULL)
715- delete (*ite).second;
716+ delete (*ite);
717 }
718+
719 cleanList(theICActivationList);
720 cleanList(theCreateDocumentList);
721 cleanList(theDeleteDocumentList);
722@@ -197,49 +175,53 @@
723
724 if (collName == theLastCollection)
725 return theLastPul;
726- return getCollectionPulByName(collName,collection->isDynamic());
727+
728+ return getCollectionPulByName(collName, collection->isDynamic());
729 }
730 else if (theNoCollectionPul != NULL)
731 {
732 return theNoCollectionPul;
733 }
734- else if (theCollectionPuls[NULL] != NULL)
735- {
736- theNoCollectionPul = theCollectionPuls[NULL];
737- return theNoCollectionPul;
738- }
739 else
740 {
741 theNoCollectionPul = new CollectionPul(this, NULL);
742- theCollectionPuls[NULL] = theNoCollectionPul;
743+ theCollectionPuls.push_back(theNoCollectionPul);
744+ theCollectionPulsMap[NULL] = theCollectionPuls.size() - 1;
745 return theNoCollectionPul;
746 }
747 }
748
749-CollectionPul* PULImpl::getCollectionPulByName(const store::Item* name, bool dynamicCollection)
750+
751+CollectionPul* PULImpl::getCollectionPulByName(
752+ const store::Item* name,
753+ bool isDynamic)
754 {
755 const QNameItem* collName = static_cast<const QNameItem*>(name)->getNormalized();
756
757- assert(!name->isNode());
758+ assert(name->isAtomic());
759
760 // "name" is the name of a collection.
761 if (name == theLastCollection)
762 return theLastPul;
763
764- CollectionPulMap::iterator ite = theCollectionPuls.find(collName);
765+ CollectionPulMap::iterator ite = theCollectionPulsMap.find(collName);
766
767 theLastCollection = collName;
768
769- if (ite != theCollectionPuls.end())
770+ if (ite != theCollectionPulsMap.end())
771 {
772- theLastPul = ite->second;
773+ theLastPul = theCollectionPuls[ite->second];
774 }
775 else
776 {
777 Collection* collection = static_cast<Collection*>
778- (GET_STORE().getCollection(collName,dynamicCollection).getp());
779+ (GET_STORE().getCollection(collName, isDynamic).getp());
780+
781 theLastPul = new CollectionPul(this, collection);
782- theCollectionPuls[collName] = theLastPul;
783+
784+ theCollectionPuls.push_back(theLastPul);
785+
786+ theCollectionPulsMap[collName] = theCollectionPuls.size() - 1;
787 }
788
789 return theLastPul;
790@@ -1107,17 +1089,17 @@
791 PULImpl* otherp = reinterpret_cast<PULImpl*>(other);
792
793 // Merge collection-specific primitives
794- CollectionPulMap::iterator thisIte = theCollectionPuls.begin();
795- CollectionPulMap::iterator thisEnd = theCollectionPuls.end();
796- CollectionPulMap::iterator otherIte = otherp->theCollectionPuls.begin();
797- CollectionPulMap::iterator otherEnd = otherp->theCollectionPuls.end();
798+ CollectionPulMap::iterator thisIte = theCollectionPulsMap.begin();
799+ CollectionPulMap::iterator thisEnd = theCollectionPulsMap.end();
800+ CollectionPulMap::iterator otherIte = otherp->theCollectionPulsMap.begin();
801+ CollectionPulMap::iterator otherEnd = otherp->theCollectionPulsMap.end();
802
803 while (thisIte != thisEnd && otherIte != otherEnd)
804 {
805 if (thisIte->first == otherIte->first)
806 {
807- CollectionPul* thisPul = thisIte->second;
808- CollectionPul* otherPul = otherIte->second;
809+ CollectionPul* thisPul = theCollectionPuls[thisIte->second];
810+ CollectionPul* otherPul = otherp->theCollectionPuls[otherIte->second];
811
812 // Merge XQUF primitives
813 mergeUpdateList(thisPul,
814@@ -1186,18 +1168,27 @@
815 }
816 else
817 {
818- theCollectionPuls[otherIte->first] = otherIte->second;
819- otherIte->second->switchPul(this);
820- otherIte->second = NULL;
821+ CollectionPul* otherPul = otherp->theCollectionPuls[otherIte->second];
822+ otherp->theCollectionPuls[otherIte->second] = NULL;
823+
824+ theCollectionPuls.push_back(otherPul);
825+ theCollectionPulsMap[otherIte->first] = theCollectionPuls.size() - 1;
826+
827+ otherPul->switchPul(this);
828 ++otherIte;
829 }
830 }
831
832 while (otherIte != otherEnd)
833 {
834- theCollectionPuls[otherIte->first] = otherIte->second;
835- otherIte->second->switchPul(this);
836- otherIte->second = NULL;
837+ CollectionPul* otherPul = otherp->theCollectionPuls[otherIte->second];
838+ otherp->theCollectionPuls[otherIte->second] = NULL;
839+
840+ theCollectionPuls.push_back(otherPul);
841+ theCollectionPulsMap[otherIte->first] = theCollectionPuls.size() - 1;
842+
843+ otherPul->switchPul(this);
844+
845 ++otherIte;
846 }
847
848@@ -1470,14 +1461,14 @@
849 ********************************************************************************/
850 void PULImpl::checkTransformUpdates(const std::vector<store::Item*>& rootNodes) const
851 {
852- ulong numRoots = (ulong)rootNodes.size();
853+ csize numRoots = rootNodes.size();
854
855- CollectionPulMap::const_iterator collIte = theCollectionPuls.begin();
856- CollectionPulMap::const_iterator collEnd = theCollectionPuls.end();
857+ std::vector<CollectionPul*>::const_iterator collIte = theCollectionPuls.begin();
858+ std::vector<CollectionPul*>::const_iterator collEnd = theCollectionPuls.end();
859
860 for (; collIte != collEnd; ++collIte)
861 {
862- CollectionPul* pul = collIte->second;
863+ CollectionPul* pul = *collIte;
864
865 NodeToUpdatesMap::iterator it = pul->theNodeToUpdatesMap.begin();
866 NodeToUpdatesMap::iterator end = pul->theNodeToUpdatesMap.end();
867@@ -1488,7 +1479,7 @@
868
869 bool found = false;
870
871- for (ulong i = 0; i < numRoots; i++)
872+ for (csize i = 0; i < numRoots; i++)
873 {
874 XmlNode* rootNode = reinterpret_cast<XmlNode*>(rootNodes[i]);
875
876@@ -1533,12 +1524,12 @@
877 std::set<store::Collection*> collections;
878 std::set<store::Collection*> truncated_collections;
879
880- CollectionPulMap::iterator collIte = theCollectionPuls.begin();
881- CollectionPulMap::iterator collEnd = theCollectionPuls.end();
882+ CollectionPuls::iterator collIte = theCollectionPuls.begin();
883+ CollectionPuls::iterator collEnd = theCollectionPuls.end();
884
885 for (; collIte != collEnd; ++collIte)
886 {
887- store::Collection* collection = store->getCollection(collIte->first);
888+ store::Collection* collection = (*collIte)->theCollection;
889
890 // The collection may not be created yet.
891 if (collection == NULL)
892@@ -1546,7 +1537,7 @@
893
894 collections.insert(collection);
895
896- CollectionPul* pul = collIte->second;
897+ CollectionPul* pul = *collIte;
898
899 if (pul->theTruncateCollectionList.size() > 0)
900 {
901@@ -1570,6 +1561,7 @@
902 (pul->theInsertIntoCollectionList[i]);
903
904 csize numDocs = upd->numNodes();
905+
906 for (csize j = 0; j < numDocs; ++j)
907 pul->theInsertedDocs.push_back(static_cast<XmlNode*>(upd->getNode(j)));
908 }
909@@ -1582,6 +1574,7 @@
910 (pul->theDeleteFromCollectionList[i]);
911
912 csize numDocs = upd->numNodes();
913+
914 for (csize j = 0; j < numDocs; ++j)
915 pul->theDeletedDocs.push_back(static_cast<XmlNode*>(upd->getNode(j)));
916 }
917@@ -1689,8 +1682,8 @@
918 ********************************************************************************/
919 void PULImpl::applyUpdates(bool inheritNSBindings)
920 {
921- CollectionPulMap::iterator collIte = theCollectionPuls.begin();
922- CollectionPulMap::iterator collEnd = theCollectionPuls.end();
923+ CollectionPuls::iterator collIte = theCollectionPuls.begin();
924+ CollectionPuls::iterator collEnd = theCollectionPuls.end();
925
926 theInheritNSBindings = inheritNSBindings;
927
928@@ -1701,7 +1694,7 @@
929 // maintained incrementally w.r.t. updates in C.
930 for (; collIte != collEnd; ++collIte)
931 {
932- CollectionPul* pul = collIte->second;
933+ CollectionPul* pul = *collIte;
934 pul->applyUpdates();
935 }
936
937@@ -1726,7 +1719,7 @@
938 // check integrity constraints for involved collections
939 for (collIte = theCollectionPuls.begin(); collIte != collEnd; ++collIte)
940 {
941- CollectionPul* pul = collIte->second;
942+ CollectionPul* pul = *collIte;
943
944 if (pul->theCollection != NULL)
945 {
946@@ -1743,9 +1736,18 @@
947 // Apply delete-collection primitives
948 for (collIte = theCollectionPuls.begin(); collIte != collEnd; ++collIte)
949 {
950- CollectionPul* pul = collIte->second;
951+ CollectionPul* pul = *collIte;
952 applyList(pul->theDeleteCollectionList);
953 }
954+
955+ // Refresh each incrementally maintained index. We need to do this here
956+ // because refreshIndices can raise an error (e.g. if the unique constraint
957+ // of an index is violated).
958+ for (collIte = theCollectionPuls.begin(); collIte != collEnd; ++collIte)
959+ {
960+ CollectionPul* pul = *collIte;
961+ pul->refreshIndexes();
962+ }
963 }
964 catch (...)
965 {
966@@ -1753,10 +1755,10 @@
967 throw;
968 }
969
970- //
971+ // Perform actions that are not expected to raise any errors
972 for (collIte = theCollectionPuls.begin(); collIte != collEnd; ++collIte)
973 {
974- CollectionPul* pul = collIte->second;
975+ CollectionPul* pul = *collIte;
976 pul->finalizeUpdates();
977 }
978
979@@ -1790,12 +1792,12 @@
980 {
981 undoList(theValidationList);
982
983- CollectionPulMap::iterator collIte = theCollectionPuls.begin();
984- CollectionPulMap::iterator collEnd = theCollectionPuls.end();
985+ CollectionPuls::iterator collIte = theCollectionPuls.begin();
986+ CollectionPuls::iterator collEnd = theCollectionPuls.end();
987
988 for (; collIte != collEnd; ++collIte)
989 {
990- CollectionPul* pul = collIte->second;
991+ CollectionPul* pul = *collIte;
992 undoList(pul->theDeleteCollectionList);
993 }
994
995@@ -1807,7 +1809,7 @@
996
997 for (collIte = theCollectionPuls.begin(); collIte != collEnd; ++collIte)
998 {
999- CollectionPul* pul = collIte->second;
1000+ CollectionPul* pul = *collIte;
1001 pul->undoUpdates();
1002 }
1003
1004@@ -1851,10 +1853,7 @@
1005 cleanList(theTruncateCollectionList);
1006 cleanList(theDeleteCollectionList);
1007
1008- cleanIndexDeltas(theBeforeIndexDeltas);
1009- cleanIndexDeltas(theAfterIndexDeltas);
1010- cleanIndexDeltas(theInsertedDocsIndexDeltas);
1011- cleanIndexDeltas(theDeletedDocsIndexDeltas);
1012+ cleanIndexDeltas();
1013 }
1014
1015
1016@@ -1890,22 +1889,44 @@
1017 }
1018 }
1019
1020-/*******************************************************************************
1021- The comparison function for sorting the entries of an IndexDelta by the doc node
1022-********************************************************************************/
1023-static bool cmp(const std::pair<store::Item_t, store::IndexKey*>& e1,
1024- const std::pair<store::Item_t, store::IndexKey*>& e2)
1025-{
1026- return e1.first.getp() < e2.first.getp();
1027-}
1028-
1029-
1030-/*******************************************************************************
1031- Compute the index contents on the modified docs, before any modifications
1032- are actually applied.
1033+
1034+/*******************************************************************************
1035+ For each incrementally-maintained index associated with this collection,
1036+ compute the index contents on the modified and deleted docs, before any
1037+ modifications are actually applied.
1038+
1039+ Note 1: If any docs are deleted, we have to remove from the before and after
1040+ deltas any entries for nodes belonging to the deleted docs. This is required
1041+ for the undo to work properly. For example, let E = [N, K] be an after-delta
1042+ entry, and let N be a node in a doc D that is going to be removed from the
1043+ collection. Then, during undo, the key pointer in E may be a dangling pointer.
1044+
1045+ Note 2: Given note 1, we actually have to compute the delete-docs deltas
1046+ *before* any modification are actually applied.
1047 ********************************************************************************/
1048 void CollectionPul::computeIndexBeforeDeltas()
1049 {
1050+ csize numIncrementalIndices = theIncrementalIndices.size();
1051+
1052+ if (numIncrementalIndices == 0)
1053+ return;
1054+
1055+ std::vector<XmlNode*>::const_iterator docIte = theDeletedDocs.begin();
1056+ std::vector<XmlNode*>::const_iterator docEnd = theDeletedDocs.end();
1057+
1058+ for (; docIte != docEnd; ++docIte)
1059+ {
1060+ theModifiedDocs.erase(*docIte);
1061+
1062+ for (csize i = 0; i < numIncrementalIndices; ++i)
1063+ {
1064+ store::IndexEntryCreator* docIndexer = theIndexEntryCreators[i].getp();
1065+ store::IndexDelta& indexDelta = theDeletedDocsIndexDeltas[i];
1066+
1067+ docIndexer->createIndexEntries((*docIte), indexDelta);
1068+ }
1069+ }
1070+
1071 computeIndexDeltas(theBeforeIndexDeltas);
1072 }
1073
1074@@ -1917,21 +1938,19 @@
1075 ********************************************************************************/
1076 void CollectionPul::computeIndexAfterDeltas()
1077 {
1078+ csize numIncrementalIndices = theIncrementalIndices.size();
1079+
1080+ if (numIncrementalIndices == 0)
1081+ return;
1082+
1083 computeIndexDeltas(theAfterIndexDeltas);
1084
1085- csize numIncrementalIndices = theIncrementalIndices.size();
1086-
1087- if (numIncrementalIndices == 0)
1088- return;
1089-
1090- theInsertedDocsIndexDeltas.resize(numIncrementalIndices);
1091-
1092 std::vector<XmlNode*>::const_iterator docIte = theInsertedDocs.begin();
1093 std::vector<XmlNode*>::const_iterator docEnd = theInsertedDocs.end();
1094
1095 for (; docIte != docEnd; ++docIte)
1096 {
1097- for (ulong i = 0; i < numIncrementalIndices; ++i)
1098+ for (csize i = 0; i < numIncrementalIndices; ++i)
1099 {
1100 store::IndexEntryCreator* docIndexer = theIndexEntryCreators[i].getp();
1101 store::IndexDelta& indexDelta = theInsertedDocsIndexDeltas[i];
1102@@ -1939,22 +1958,6 @@
1103 docIndexer->createIndexEntries((*docIte), indexDelta);
1104 }
1105 }
1106-
1107- theDeletedDocsIndexDeltas.resize(numIncrementalIndices);
1108-
1109- docIte = theDeletedDocs.begin();
1110- docEnd = theDeletedDocs.end();
1111-
1112- for (; docIte != docEnd; ++docIte)
1113- {
1114- for (ulong i = 0; i < numIncrementalIndices; ++i)
1115- {
1116- store::IndexEntryCreator* docIndexer = theIndexEntryCreators[i].getp();
1117- store::IndexDelta& indexDelta = theDeletedDocsIndexDeltas[i];
1118-
1119- docIndexer->createIndexEntries((*docIte), indexDelta);
1120- }
1121- }
1122 }
1123
1124
1125@@ -1965,19 +1968,14 @@
1126 ********************************************************************************/
1127 void CollectionPul::computeIndexDeltas(std::vector<store::IndexDelta>& deltas)
1128 {
1129- ulong numIncrementalIndices = (ulong)theIncrementalIndices.size();
1130-
1131- if (numIncrementalIndices == 0)
1132- return;
1133-
1134- deltas.resize(numIncrementalIndices);
1135+ csize numIncrementalIndices = theIncrementalIndices.size();
1136
1137 std::set<XmlNode*>::const_iterator docIte = theModifiedDocs.begin();
1138 std::set<XmlNode*>::const_iterator docEnd = theModifiedDocs.end();
1139
1140 for (; docIte != docEnd; ++docIte)
1141 {
1142- for (ulong i = 0; i < numIncrementalIndices; ++i)
1143+ for (csize i = 0; i < numIncrementalIndices; ++i)
1144 {
1145 store::IndexEntryCreator* docIndexer = theIndexEntryCreators[i].getp();
1146 store::IndexDelta& indexDelta = deltas[i];
1147@@ -1985,113 +1983,268 @@
1148 docIndexer->createIndexEntries((*docIte), indexDelta);
1149 }
1150 }
1151-
1152- for (ulong i = 0; i < numIncrementalIndices; ++i)
1153- {
1154- store::IndexDelta& indexDelta = deltas[i];
1155-
1156- std::sort(indexDelta.begin(), indexDelta.end(), cmp);
1157- }
1158-}
1159-
1160-
1161-/*******************************************************************************
1162-
1163-********************************************************************************/
1164-void CollectionPul::refreshIndices()
1165-{
1166- csize numIncrementalIndices = theTruncatedIndices.size();
1167- for (csize idx = 0; idx < numIncrementalIndices; ++idx)
1168+}
1169+
1170+
1171+/*******************************************************************************
1172+
1173+********************************************************************************/
1174+void CollectionPul::cleanIndexDeltas()
1175+{
1176+ csize numIncrementalIndices = theIncrementalIndices.size();
1177+
1178+ for (csize idx = 0; idx < numIncrementalIndices; ++idx)
1179+ {
1180+ store::IndexDelta::iterator ite;
1181+ store::IndexDelta::iterator end;
1182+ store::IndexDelta* delta;
1183+ csize numApplied;
1184+
1185+ delta = &theInsertedDocsIndexDeltas[idx];
1186+ if (delta)
1187+ {
1188+ numApplied = theNumInsertedDocsIndexDeltasApplied[idx];
1189+ ite = delta->begin() + numApplied;
1190+ end = delta->end();
1191+ for (; ite != end; ++ite)
1192+ {
1193+ delete (*ite).second;
1194+ }
1195+ }
1196+
1197+ delta = &theAfterIndexDeltas[idx];
1198+ if (delta)
1199+ {
1200+ numApplied = theNumAfterIndexDeltasApplied[idx];
1201+ ite = delta->begin() + numApplied;
1202+ end = delta->end();
1203+ for (; ite != end; ++ite)
1204+ {
1205+ delete (*ite).second;
1206+ }
1207+ }
1208+
1209+ delta = &theDeletedDocsIndexDeltas[idx];
1210+ if (delta)
1211+ {
1212+ ite = delta->begin();
1213+ end = delta->end();
1214+ for (; ite != end; ++ite)
1215+ {
1216+ delete (*ite).second;
1217+ }
1218+ }
1219+
1220+ delta = &theBeforeIndexDeltas[idx];
1221+ if (delta)
1222+ {
1223+ ite = delta->begin();
1224+ end = delta->end();
1225+ for (; ite != end; ++ite)
1226+ {
1227+ delete (*ite).second;
1228+ }
1229+ }
1230+ }
1231+}
1232+
1233+
1234+/*******************************************************************************
1235+ Refresh the incrementally maintained indexes.
1236+********************************************************************************/
1237+void CollectionPul::refreshIndexes()
1238+{
1239+ csize numIncrementalIndices = theIncrementalIndices.size();
1240+
1241+ STORE_TRACE1("Refreshing indexes for collection "
1242+ << (theCollection ?
1243+ theCollection->getName()->getStringValue().c_str() :
1244+ "NULL"));
1245+
1246+ for (csize idx = 0; idx < numIncrementalIndices; ++idx)
1247+ {
1248+ ValueIndex* index = static_cast<ValueIndex*>(theIncrementalIndices[idx]);
1249+
1250+ STORE_TRACE2("Index size before do = "
1251+ << (!index->isTreeIndex() ? index->size() : 0));
1252+
1253+ store::IndexDelta& beforeDelta = theBeforeIndexDeltas[idx];
1254+ store::IndexDelta& afterDelta = theAfterIndexDeltas[idx];
1255+ store::IndexDelta& deletedDelta = theDeletedDocsIndexDeltas[idx];
1256+ store::IndexDelta& insertedDelta = theInsertedDocsIndexDeltas[idx];
1257+
1258+ csize& numBeforeApplied = theNumBeforeIndexDeltasApplied[idx];
1259+ csize& numAfterApplied = theNumAfterIndexDeltasApplied[idx];
1260+ csize& numDeletedApplied = theNumDeletedDocsIndexDeltasApplied[idx];
1261+ csize& numInsertedApplied = theNumInsertedDocsIndexDeltasApplied[idx];
1262+
1263+ store::IndexKey* key;
1264+ store::Item_t node;
1265+
1266+ store::IndexDelta::iterator ite;
1267+ store::IndexDelta::iterator end;
1268+
1269+ ite = beforeDelta.begin();
1270+ end = beforeDelta.end();
1271+ for (; ite != end; ++ite, ++numBeforeApplied)
1272+ {
1273+ index->remove((*ite).second, (*ite).first);
1274+ }
1275+
1276+ ite = afterDelta.begin();
1277+ end = afterDelta.end();
1278+ for (; ite != end; ++ite, ++numAfterApplied)
1279+ {
1280+ node = (*ite).first;
1281+ key = (*ite).second;
1282+
1283+ // If the index had its own key obj already, delete the key obj that was
1284+ // allocated during the delta creation.
1285+ if (index->insert((*ite).second, node))
1286+ {
1287+ assert(key != (*ite).second);
1288+ delete key;
1289+ }
1290+ }
1291+
1292+ STORE_TRACE2("deleted-delta size = " << deletedDelta.size());
1293+
1294+ ite = deletedDelta.begin();
1295+ end = deletedDelta.end();
1296+ for (; ite != end; ++ite, ++numDeletedApplied)
1297+ {
1298+ index->remove((*ite).second, (*ite).first);
1299+ }
1300+
1301+ STORE_TRACE2("inserted-delta size = " << insertedDelta.size());
1302+
1303+ ite = insertedDelta.begin();
1304+ end = insertedDelta.end();
1305+ for (; ite != end; ++ite, ++numInsertedApplied)
1306+ {
1307+ node = (*ite).first;
1308+ key = (*ite).second;
1309+
1310+ if (index->insert((*ite).second, node))
1311+ {
1312+ assert(key != (*ite).second);
1313+ delete key;
1314+ }
1315+ }
1316+
1317+ STORE_TRACE2("Index size after do = "
1318+ << (!index->isTreeIndex() ? index->size() : 0));
1319+ }
1320+
1321+ STORE_TRACE1("Refreshed indexes for collection "
1322+ << (theCollection ?
1323+ theCollection->getName()->getStringValue().c_str() :
1324+ "NULL")
1325+ << std::endl);
1326+}
1327+
1328+
1329+/*******************************************************************************
1330+
1331+********************************************************************************/
1332+void CollectionPul::undoRefreshIndexes()
1333+{
1334+ csize numIncrementalIndices = theIncrementalIndices.size();
1335+
1336+ STORE_TRACE1("Reverting indexes for collection "
1337+ << (theCollection ?
1338+ theCollection->getName()->getStringValue().c_str() :
1339+ "NULL")
1340+ << std::endl);
1341+
1342+ for (csize idx = 0; idx < numIncrementalIndices; ++idx)
1343+ {
1344+ ValueIndex* index = static_cast<ValueIndex*>(theIncrementalIndices[idx]);
1345+
1346+ STORE_TRACE2("Index size before undo = "
1347+ << (!index->isTreeIndex() ? index->size() : 0));
1348+
1349+ store::IndexDelta& beforeDelta = theBeforeIndexDeltas[idx];
1350+ store::IndexDelta& afterDelta = theAfterIndexDeltas[idx];
1351+ store::IndexDelta& insertedDelta = theInsertedDocsIndexDeltas[idx];
1352+ store::IndexDelta& deletedDelta = theDeletedDocsIndexDeltas[idx];
1353+
1354+ csize numBeforeApplied = theNumBeforeIndexDeltasApplied[idx];
1355+ csize numAfterApplied = theNumAfterIndexDeltasApplied[idx];
1356+ csize numDeletedApplied = theNumDeletedDocsIndexDeltasApplied[idx];
1357+ csize numInsertedApplied = theNumInsertedDocsIndexDeltasApplied[idx];
1358+
1359+ store::IndexDelta::reverse_iterator ite;
1360+ store::IndexDelta::reverse_iterator end;
1361+
1362+ ite = insertedDelta.rbegin() + (insertedDelta.size() - numInsertedApplied);
1363+ end = insertedDelta.rend();
1364+ for (; ite != end; ++ite)
1365+ {
1366+ index->remove((*ite).second, (*ite).first);
1367+ }
1368+
1369+ ite = deletedDelta.rbegin() + (deletedDelta.size() - numDeletedApplied);
1370+ end = deletedDelta.rend();
1371+ for (; ite != end; ++ite)
1372+ {
1373+ store::IndexKey* key = (*ite).second;
1374+
1375+ // If the index takes ownership of the key obj, set the key ptr to null
1376+ // so that the key obj will not be deleted during cleanIndexDeltas().
1377+ if (!index->insert(key, (*ite).first))
1378+ {
1379+ assert(key == (*ite).second);
1380+ (*ite).second = NULL;
1381+ }
1382+ }
1383+
1384+ ite = afterDelta.rbegin() + (afterDelta.size() - numAfterApplied);
1385+ end = afterDelta.rend();
1386+ for (; ite != end; ++ite)
1387+ {
1388+ index->remove((*ite).second, (*ite).first);
1389+ }
1390+
1391+ ite = beforeDelta.rbegin() + (beforeDelta.size() - numBeforeApplied);
1392+ end = beforeDelta.rend();
1393+ for (; ite != end; ++ite)
1394+ {
1395+ store::IndexKey* key = (*ite).second;
1396+
1397+ // If the index takes ownership of the key obj, set the key ptr to null
1398+ // so that the key obj will not be deleted during cleanIndexDeltas().
1399+ if (!index->insert(key, (*ite).first))
1400+ {
1401+ assert(key == (*ite).second);
1402+ (*ite).second = NULL;
1403+ }
1404+ }
1405+
1406+ STORE_TRACE2("Index size after undo = "
1407+ << (!index->isTreeIndex() ? index->size() : 0));
1408+ }
1409+
1410+ STORE_TRACE1("Reverted indexes for collection "
1411+ << (theCollection ?
1412+ theCollection->getName()->getStringValue().c_str() :
1413+ "NULL")
1414+ << std::endl);
1415+}
1416+
1417+
1418+/*******************************************************************************
1419+ The method is called from CollectionPul::finalizeUpdates()
1420+********************************************************************************/
1421+void CollectionPul::truncateIndexes()
1422+{
1423+ csize numTruncatedIndices = theTruncatedIndices.size();
1424+
1425+ for (csize idx = 0; idx < numTruncatedIndices; ++idx)
1426 {
1427 ValueIndex* index = static_cast<ValueIndex*>(theTruncatedIndices[idx]);
1428 index->clear();
1429 }
1430-
1431- numIncrementalIndices = theIncrementalIndices.size();
1432-
1433- for (csize idx = 0; idx < numIncrementalIndices; ++idx)
1434- {
1435- ValueIndex* index = static_cast<ValueIndex*>(theIncrementalIndices[idx]);
1436-
1437- //
1438- // Referesh the index w.r.t. modified docs.
1439- //
1440- ValueIndexCompareFunction keyCmp(index->getNumColumns(),
1441- index->getTimezone(),
1442- index->getCollations());
1443-
1444- store::IndexDelta& beforeDelta = theBeforeIndexDeltas[idx];
1445- store::IndexDelta& afterDelta = theAfterIndexDeltas[idx];
1446- store::IndexDelta& insertedDelta = theInsertedDocsIndexDeltas[idx];
1447- store::IndexDelta& deletedDelta = theDeletedDocsIndexDeltas[idx];
1448-
1449- store::IndexDelta::iterator beforeIte = beforeDelta.begin();
1450- store::IndexDelta::iterator beforeEnd = beforeDelta.end();
1451- store::IndexDelta::iterator afterIte = afterDelta.begin();
1452- store::IndexDelta::iterator afterEnd = afterDelta.end();
1453- store::IndexDelta::iterator insertedIte = insertedDelta.begin();
1454- store::IndexDelta::iterator insertedEnd = insertedDelta.end();
1455- store::IndexDelta::iterator deletedIte = deletedDelta.begin();
1456- store::IndexDelta::iterator deletedEnd = deletedDelta.end();
1457-
1458- while (beforeIte != beforeEnd && afterIte != afterEnd)
1459- {
1460- store::Item_t& beforeNode = (*beforeIte).first;
1461- store::Item_t& afterNode = (*afterIte).first;
1462- store::IndexKey* beforeKey = (*beforeIte).second;
1463- store::IndexKey*& afterKey = (*afterIte).second;
1464-
1465- if (beforeNode == afterNode)
1466- {
1467- if (!keyCmp.equal(beforeKey, afterKey))
1468- {
1469- index->remove(beforeKey, beforeNode);
1470- index->insert(afterKey, afterNode);
1471- }
1472-
1473- ++beforeIte;
1474- ++afterIte;
1475- }
1476- else if (beforeNode < afterNode)
1477- {
1478- index->remove(beforeKey, beforeNode);
1479- ++beforeIte;
1480- }
1481- else
1482- {
1483- index->insert(afterKey, afterNode);
1484- ++afterIte;
1485- }
1486- }
1487-
1488- while (beforeIte != beforeEnd)
1489- {
1490- index->remove((*beforeIte).second, (*beforeIte).first);
1491- ++beforeIte;
1492- }
1493-
1494- while (afterIte != afterEnd)
1495- {
1496- index->insert((*afterIte).second, (*afterIte).first);
1497- ++afterIte;
1498- }
1499-
1500- //
1501- // Referesh the index w.r.t. newly inserted docs.
1502- //
1503- for (; insertedIte != insertedEnd; ++insertedIte)
1504- {
1505- index->insert((*insertedIte).second, (*insertedIte).first);
1506- }
1507-
1508- //
1509- // Referesh the index w.r.t. deleted docs,
1510- //
1511- for (; deletedIte != deletedEnd; ++deletedIte)
1512- {
1513- index->remove((*deletedIte).second, (*deletedIte).first);
1514- }
1515- }
1516 }
1517
1518
1519@@ -2100,6 +2253,37 @@
1520 ********************************************************************************/
1521 void CollectionPul::applyUpdates()
1522 {
1523+ csize numIncrementalIndices = theIncrementalIndices.size();
1524+
1525+#if 0
1526+ if (theCollection != NULL)
1527+ {
1528+ std::cout << "applying PUL for collection "
1529+ << theCollection->getName()->getStringValue() << std::endl;
1530+ }
1531+#endif
1532+
1533+ if (numIncrementalIndices > 0)
1534+ {
1535+ theBeforeIndexDeltas.resize(numIncrementalIndices);
1536+ theAfterIndexDeltas.resize(numIncrementalIndices);
1537+ theDeletedDocsIndexDeltas.resize(numIncrementalIndices);
1538+ theInsertedDocsIndexDeltas.resize(numIncrementalIndices);
1539+
1540+ theNumBeforeIndexDeltasApplied.resize(numIncrementalIndices);
1541+ theNumAfterIndexDeltasApplied.resize(numIncrementalIndices);
1542+ theNumInsertedDocsIndexDeltasApplied.resize(numIncrementalIndices);
1543+ theNumDeletedDocsIndexDeltasApplied.resize(numIncrementalIndices);
1544+
1545+ for (csize idx = 0; idx < numIncrementalIndices; ++idx)
1546+ {
1547+ theNumBeforeIndexDeltasApplied[idx] = 0;
1548+ theNumAfterIndexDeltasApplied[idx] = 0;
1549+ theNumInsertedDocsIndexDeltasApplied[idx] = 0;
1550+ theNumDeletedDocsIndexDeltasApplied[idx] = 0;
1551+ }
1552+ }
1553+
1554 // Don't apply anything if the collection is going to be deleted.
1555 if (!theDeleteCollectionList.empty())
1556 return;
1557@@ -2214,6 +2398,71 @@
1558 #endif
1559 throw;
1560 }
1561+
1562+#if 0
1563+ if (theCollection != NULL)
1564+ {
1565+ std::cout << "applied PUL for collection "
1566+ << theCollection->getName()->getStringValue() << std::endl << std::endl;
1567+ }
1568+#endif
1569+}
1570+
1571+
1572+/*******************************************************************************
1573+
1574+********************************************************************************/
1575+void CollectionPul::undoUpdates()
1576+{
1577+ if (!theIsApplied)
1578+ return;
1579+
1580+ try
1581+ {
1582+ undoList(theTruncateCollectionList);
1583+ undoList(theDeleteFromCollectionList);
1584+ undoList(theInsertIntoCollectionList);
1585+ undoList(theCreateCollectionList);
1586+
1587+#ifndef ZORBA_NO_XMLSCHEMA
1588+ // Undo validate-in-place validation
1589+ undoList(theRevalidateList);
1590+
1591+ // Undo apply-updates caused validation
1592+ if (theValidationPul)
1593+ {
1594+ undoList(static_cast<PULImpl *>(theValidationPul.getp())->theValidationList);
1595+ }
1596+#endif
1597+
1598+ // Undo text node merging
1599+ std::vector<TextNodeMerge>::reverse_iterator rit = theMergeList.rbegin();
1600+ std::vector<TextNodeMerge>::reverse_iterator rend = theMergeList.rend();
1601+ for (; rit != rend; ++rit)
1602+ {
1603+ TextNodeMerge merge = (*rit);
1604+ XmlNode* newTextNode = merge.theParent->getChild(merge.thePos);
1605+ ZORBA_ASSERT(newTextNode->getNodeKind()== store::StoreConsts::textNode);
1606+
1607+ newTextNode->detach();
1608+
1609+ for (csize j = 0; j < merge.theMergedNodes.size(); ++j)
1610+ merge.theMergedNodes[j]->connect(merge.theParent, merge.thePos + j);
1611+ }
1612+ theMergeList.clear();
1613+
1614+ undoList(theDeleteList);
1615+ undoList(theReplaceContentList);
1616+ undoList(theReplaceNodeList);
1617+ undoList(theInsertList);
1618+ undoList(theDoFirstList);
1619+
1620+ undoRefreshIndexes();
1621+ }
1622+ catch (...)
1623+ {
1624+ ZORBA_FATAL(0, "Unexpected error during pul undo");
1625+ }
1626 }
1627
1628
1629@@ -2228,9 +2477,7 @@
1630 {
1631 try
1632 {
1633- // Refresh each incrementally maintained index using its before and after
1634- // deltas.
1635- refreshIndices();
1636+ truncateIndexes();
1637
1638 // If necessary, adjust the position of trees inside this collection.
1639 if (theAdjustTreePositions)
1640@@ -2241,9 +2488,8 @@
1641
1642 // Detach nodes that were deleted from their trees due to replace-node,
1643 // replace-content, or delete-node XQUF primitives.
1644- csize numUpdates;
1645+ csize numUpdates = theReplaceNodeList.size();
1646
1647- numUpdates = theReplaceNodeList.size();
1648 for (csize i = 0; i < numUpdates; ++i)
1649 {
1650 UpdatePrimitive* upd = theReplaceNodeList[i];
1651@@ -2318,61 +2564,6 @@
1652 }
1653
1654
1655-/*******************************************************************************
1656-
1657-********************************************************************************/
1658-void CollectionPul::undoUpdates()
1659-{
1660- if (!theIsApplied)
1661- return;
1662-
1663- try
1664- {
1665- undoList(theTruncateCollectionList);
1666- undoList(theDeleteFromCollectionList);
1667- undoList(theInsertIntoCollectionList);
1668- undoList(theCreateCollectionList);
1669-
1670-#ifndef ZORBA_NO_XMLSCHEMA
1671- // Undo validate-in-place validation
1672- undoList(theRevalidateList);
1673-
1674- // Undo apply-updates caused validation
1675- if (theValidationPul)
1676- {
1677- undoList(static_cast<PULImpl *>(theValidationPul.getp())->theValidationList);
1678- }
1679-#endif
1680-
1681- // Undo text node merging
1682- std::vector<TextNodeMerge>::reverse_iterator rit = theMergeList.rbegin();
1683- std::vector<TextNodeMerge>::reverse_iterator rend = theMergeList.rend();
1684- for (; rit != rend; ++rit)
1685- {
1686- TextNodeMerge merge = (*rit);
1687- XmlNode* newTextNode = merge.theParent->getChild(merge.thePos);
1688- ZORBA_ASSERT(newTextNode->getNodeKind()== store::StoreConsts::textNode);
1689-
1690- newTextNode->detach();
1691-
1692- for (csize j = 0; j < merge.theMergedNodes.size(); ++j)
1693- merge.theMergedNodes[j]->connect(merge.theParent, merge.thePos + j);
1694- }
1695- theMergeList.clear();
1696-
1697- undoList(theDeleteList);
1698- undoList(theReplaceContentList);
1699- undoList(theReplaceNodeList);
1700- undoList(theInsertList);
1701- undoList(theDoFirstList);
1702- }
1703- catch (...)
1704- {
1705- ZORBA_FATAL(0, "Unexpected error during pul undo");
1706- }
1707-}
1708-
1709-
1710 } // namespace simplestore
1711 } // namespace zorba
1712 /* vim:set et sw=2 ts=2: */
1713
1714=== modified file 'src/store/naive/simple_pul.h'
1715--- src/store/naive/simple_pul.h 2012-04-24 12:39:38 +0000
1716+++ src/store/naive/simple_pul.h 2012-05-03 10:05:25 +0000
1717@@ -204,6 +204,11 @@
1718 std::vector<store::IndexDelta> theInsertedDocsIndexDeltas;
1719 std::vector<store::IndexDelta> theDeletedDocsIndexDeltas;
1720
1721+ std::vector<csize> theNumBeforeIndexDeltasApplied;
1722+ std::vector<csize> theNumAfterIndexDeltasApplied;
1723+ std::vector<csize> theNumInsertedDocsIndexDeltasApplied;
1724+ std::vector<csize> theNumDeletedDocsIndexDeltasApplied;
1725+
1726 public:
1727 CollectionPul(PULImpl* pul, Collection* collection);
1728
1729@@ -211,18 +216,18 @@
1730
1731 void switchPul(PULImpl* pul);
1732
1733+ void computeIndexBeforeDeltas();
1734+
1735+ void computeIndexAfterDeltas();
1736+
1737+ void refreshIndexes();
1738+
1739 void applyUpdates();
1740
1741+ void undoUpdates();
1742+
1743 void finalizeUpdates();
1744
1745- void undoUpdates();
1746-
1747- void computeIndexBeforeDeltas();
1748-
1749- void computeIndexAfterDeltas();
1750-
1751- void refreshIndices();
1752-
1753 void setAdjustTreePositions() { theAdjustTreePositions = true; }
1754
1755 void addToCheckForMerge(InternalNode* parent) { theMergeToCheckSet.insert(parent); }
1756@@ -231,6 +236,12 @@
1757 void switchPulInPrimitivesList(std::vector<UpdatePrimitive*>& list);
1758
1759 void computeIndexDeltas(std::vector<store::IndexDelta>& deltas);
1760+
1761+ void cleanIndexDeltas();
1762+
1763+ void truncateIndexes();
1764+
1765+ void undoRefreshIndexes();
1766 };
1767
1768
1769@@ -273,11 +284,14 @@
1770 UP_LIST_CREATE_INDEX
1771 };
1772
1773- typedef std::map<const QNameItem*, CollectionPul*> CollectionPulMap;
1774+ typedef std::vector<CollectionPul*> CollectionPuls;
1775+
1776+ typedef std::map<const QNameItem*, csize> CollectionPulMap;
1777
1778 protected:
1779 // XQUF and collection primitives, grouped by the collection that is being updated.
1780- CollectionPulMap theCollectionPuls;
1781+ CollectionPuls theCollectionPuls;
1782+ CollectionPulMap theCollectionPulsMap;
1783 CollectionPul * theNoCollectionPul;
1784 CollectionPul * theLastPul;
1785 const QNameItem * theLastCollection;
1786
1787=== modified file 'src/store/naive/store.cpp'
1788--- src/store/naive/store.cpp 2012-05-03 09:09:01 +0000
1789+++ src/store/naive/store.cpp 2012-05-03 10:05:25 +0000
1790@@ -523,23 +523,24 @@
1791
1792 ********************************************************************************/
1793 void Store::populateValueIndex(
1794- const store::Index_t& aIndex,
1795- store::Iterator* aSourceIter,
1796- ulong aNumColumns)
1797+ const store::Index_t& idx,
1798+ store::Iterator* sourceIter,
1799+ ulong numColumns)
1800 {
1801- if (!aSourceIter)
1802+ if (!sourceIter)
1803 return;
1804
1805 store::Item_t domainItem;
1806 store::IndexKey* key = NULL;
1807-
1808- ValueIndex* index = static_cast<ValueIndex*>(aIndex.getp());
1809-
1810- aSourceIter->open();
1811+ store::IndexKey* key2 = NULL;
1812+
1813+ ValueIndex* index = static_cast<ValueIndex*>(idx.getp());
1814+
1815+ sourceIter->open();
1816
1817 try
1818 {
1819- while (aSourceIter->next(domainItem))
1820+ while (sourceIter->next(domainItem))
1821 {
1822 if (domainItem->isNode() &&
1823 domainItem->getCollection() == NULL &&
1824@@ -549,12 +550,12 @@
1825 ERROR_PARAMS(index->getName()->getStringValue()));
1826 }
1827
1828- if (key == NULL)
1829- key = new store::IndexKey(aNumColumns);
1830+ if (key2 == key)
1831+ key = new store::IndexKey(numColumns);
1832
1833- for (ulong i = 0; i < aNumColumns; ++i)
1834+ for (ulong i = 0; i < numColumns; ++i)
1835 {
1836- if (!aSourceIter->next((*key)[i]))
1837+ if (!sourceIter->next((*key)[i]))
1838 {
1839 // The source iter is a ValueIndexEntryBuilderIterator, whose next()
1840 // method is guaranteed to return true exactly once. The result from
1841@@ -564,7 +565,8 @@
1842 }
1843 }
1844
1845- index->insert(key, domainItem);
1846+ key2 = key;
1847+ index->insert(key2, domainItem);
1848 }
1849 }
1850 catch(...)
1851@@ -572,14 +574,11 @@
1852 if (key != NULL)
1853 delete key;
1854
1855- aSourceIter->close();
1856+ sourceIter->close();
1857 throw;
1858 }
1859
1860- if (key != NULL)
1861- delete key;
1862-
1863- aSourceIter->close();
1864+ sourceIter->close();
1865 }
1866
1867
1868
1869=== modified file 'src/store/naive/store_defs.h'
1870--- src/store/naive/store_defs.h 2012-04-24 12:39:38 +0000
1871+++ src/store/naive/store_defs.h 2012-05-03 10:05:25 +0000
1872@@ -55,6 +55,28 @@
1873
1874 #define COMMENT_NODE(item) (reinterpret_cast<CommentNode*>((item).getp()))
1875
1876+
1877+#ifndef NDEBUG
1878+
1879+#define STORE_TRACE(level, msg) \
1880+{ \
1881+ if (level <= GET_STORE().getTraceLevel()) \
1882+ std::cout << msg << std::endl; \
1883+}
1884+
1885+#define STORE_TRACE1(msg) STORE_TRACE(1, msg);
1886+#define STORE_TRACE2(msg) STORE_TRACE(2, msg);
1887+#define STORE_TRACE3(msg) STORE_TRACE(3, msg);
1888+
1889+#else
1890+
1891+#define STORE_TRACE(msg)
1892+#define STORE_TRACE1(msg)
1893+#define STORE_TRACE2(msg)
1894+#define STORE_TRACE3(msg)
1895+
1896+#endif
1897+
1898 }
1899 }
1900 #endif
1901
1902=== added file 'test/rbkt/ExpQueryResults/zorba/index/delete_from_collection_01.xml.res'
1903--- test/rbkt/ExpQueryResults/zorba/index/delete_from_collection_01.xml.res 1970-01-01 00:00:00 +0000
1904+++ test/rbkt/ExpQueryResults/zorba/index/delete_from_collection_01.xml.res 2012-05-03 10:05:25 +0000
1905@@ -0,0 +1,1 @@
1906+<foo uri="1"/>
1907
1908=== added file 'test/rbkt/ExpQueryResults/zorba/index/undo2.xml.res'
1909--- test/rbkt/ExpQueryResults/zorba/index/undo2.xml.res 1970-01-01 00:00:00 +0000
1910+++ test/rbkt/ExpQueryResults/zorba/index/undo2.xml.res 2012-05-03 10:05:25 +0000
1911@@ -0,0 +1,2 @@
1912+<?xml version="1.0" encoding="UTF-8"?>
1913+zerr:ZDDY0024<person id="1" key="5"/><person id="2" key="5"/><person id="1" key="5"/><person id="2" key="5"/>
1914
1915=== added file 'test/rbkt/ExpQueryResults/zorba/index/undo3.xml.res'
1916--- test/rbkt/ExpQueryResults/zorba/index/undo3.xml.res 1970-01-01 00:00:00 +0000
1917+++ test/rbkt/ExpQueryResults/zorba/index/undo3.xml.res 2012-05-03 10:05:25 +0000
1918@@ -0,0 +1,6 @@
1919+<?xml version="1.0" encoding="UTF-8"?>
1920+zerr:ZDDY0024
1921+<person id="1" key="5"/><person id="2" key="5"/>
1922+
1923+
1924+<person id="1" key="5"/><person id="2" key="5"/>
1925
1926=== added file 'test/rbkt/ExpQueryResults/zorba/index/unique.xml.res'
1927--- test/rbkt/ExpQueryResults/zorba/index/unique.xml.res 1970-01-01 00:00:00 +0000
1928+++ test/rbkt/ExpQueryResults/zorba/index/unique.xml.res 2012-05-03 10:05:25 +0000
1929@@ -0,0 +1,1 @@
1930+zerr:ZDDY0024 zerr:ZDDY0024<person id="5"/><person id="5"/>
1931
1932=== added file 'test/rbkt/Queries/zorba/index/delete_from_collection_01.xq'
1933--- test/rbkt/Queries/zorba/index/delete_from_collection_01.xq 1970-01-01 00:00:00 +0000
1934+++ test/rbkt/Queries/zorba/index/delete_from_collection_01.xq 2012-05-03 10:05:25 +0000
1935@@ -0,0 +1,13 @@
1936+
1937+import module namespace seq = "http://www.foo.com/default" at "delete_from_collection_01.xqlib";
1938+
1939+seq:init();
1940+
1941+variable $foo := seq:index();
1942+
1943+seq:reset();
1944+
1945+variable $bar := seq:index();
1946+
1947+
1948+$foo, $bar
1949
1950=== added file 'test/rbkt/Queries/zorba/index/delete_from_collection_01.xqlib'
1951--- test/rbkt/Queries/zorba/index/delete_from_collection_01.xqlib 1970-01-01 00:00:00 +0000
1952+++ test/rbkt/Queries/zorba/index/delete_from_collection_01.xqlib 2012-05-03 10:05:25 +0000
1953@@ -0,0 +1,42 @@
1954+module namespace seq = "http://www.foo.com/default";
1955+
1956+import module namespace ddl = "http://www.zorba-xquery.com/modules/store/static/collections/ddl";
1957+
1958+import module namespace dml = "http://www.zorba-xquery.com/modules/store/static/collections/dml";
1959+
1960+import module namespace iddl = "http://www.zorba-xquery.com/modules/store/static/indexes/ddl";
1961+
1962+import module namespace idml = "http://www.zorba-xquery.com/modules/store/static/indexes/dml";
1963+
1964+declare namespace an = "http://www.zorba-xquery.com/annotations";
1965+
1966+
1967+declare collection seq:counters as node()*;
1968+
1969+
1970+declare %an:automatic %an:unique %an:value-equality index seq:counters-by-uri
1971+ on nodes dml:collection(xs:QName("seq:counters"))
1972+ by xs:string(./@uri) as xs:string;
1973+
1974+
1975+declare %an:sequential function seq:init()
1976+{
1977+ ddl:create(xs:QName("seq:counters"));
1978+ iddl:create(xs:QName("seq:counters-by-uri"));
1979+ dml:insert-nodes(xs:QName("seq:counters"), <foo uri="1"/>);
1980+};
1981+
1982+
1983+declare function seq:index ()
1984+{
1985+ idml:probe-index-point-value(xs:QName("seq:counters-by-uri"), "1")
1986+};
1987+
1988+
1989+declare %an:sequential function seq:reset ()
1990+{
1991+ dml:delete-nodes(idml:probe-index-point-value(xs:QName("seq:counters-by-uri"), "1"));
1992+};
1993+
1994+
1995+
1996
1997=== added file 'test/rbkt/Queries/zorba/index/undo2.xq'
1998--- test/rbkt/Queries/zorba/index/undo2.xq 1970-01-01 00:00:00 +0000
1999+++ test/rbkt/Queries/zorba/index/undo2.xq 2012-05-03 10:05:25 +0000
2000@@ -0,0 +1,43 @@
2001+import module namespace u = "http://www.zorba-xquery.com/unique-index" at "undo2.xqlib";
2002+
2003+import module namespace dml = "http://www.zorba-xquery.com/modules/store/static/collections/dml";
2004+import module namespace idml = "http://www.zorba-xquery.com/modules/store/static/indexes/dml";
2005+
2006+declare namespace zerr = "http://www.zorba-xquery.com/errors";
2007+declare namespace err = "http://www.w3.org/2005/xqt-errors";
2008+
2009+u:create-db();
2010+
2011+dml:insert-nodes($u:auctions1, <person id="1" key="5"/>);
2012+dml:insert-nodes($u:auctions1, <person id="2" key="5"/>);
2013+
2014+try
2015+{{
2016+ (
2017+ dml:insert-nodes($u:auctions1, <person id="3" key="1"/>),
2018+
2019+ insert node <foo/> into dml:collection($u:auctions1)[1],
2020+
2021+ dml:insert-nodes($u:auctions1, <person id="4" key="5"/>),
2022+
2023+ replace value of node dml:collection($u:auctions1)[1]/@key with "1",
2024+
2025+ dml:insert-nodes($u:auctions2, <person id="1"/>),
2026+ dml:insert-nodes($u:auctions2, <person id="1"/>));
2027+ ()
2028+}}
2029+catch *
2030+{
2031+ $err:code
2032+}
2033+,
2034+
2035+dml:collection($u:auctions1)
2036+,
2037+idml:probe-index-point-value($u:PersonId1, "1")
2038+,
2039+idml:probe-index-point-value($u:PersonId1, "3")
2040+,
2041+idml:probe-index-point-value($u:PersonId1, "5")
2042+,
2043+dml:collection($u:auctions2)
2044
2045=== added file 'test/rbkt/Queries/zorba/index/undo2.xqlib'
2046--- test/rbkt/Queries/zorba/index/undo2.xqlib 1970-01-01 00:00:00 +0000
2047+++ test/rbkt/Queries/zorba/index/undo2.xqlib 2012-05-03 10:05:25 +0000
2048@@ -0,0 +1,36 @@
2049+module namespace auctions = "http://www.zorba-xquery.com/unique-index";
2050+
2051+import module namespace ddl = "http://www.zorba-xquery.com/modules/store/static/collections/ddl";
2052+import module namespace iddl = "http://www.zorba-xquery.com/modules/store/static/indexes/ddl";
2053+import module namespace dml = "http://www.zorba-xquery.com/modules/store/static/collections/dml";
2054+import module namespace idml = "http://www.zorba-xquery.com/modules/store/static/indexes/dml";
2055+
2056+declare namespace an = "http://www.zorba-xquery.com/annotations";
2057+
2058+declare variable $auctions:auctions1 := xs:QName("auctions:auctions1");
2059+declare variable $auctions:PersonId1 := xs:QName("auctions:PersonId1");
2060+declare variable $auctions:auctions2 := xs:QName("auctions:auctions2");
2061+declare variable $auctions:PersonId2 := xs:QName("auctions:PersonId2");
2062+
2063+declare %an:ordered collection auctions:auctions1 as node()*;
2064+
2065+declare %an:automatic %an:value-equality index auctions:PersonId1
2066+on nodes dml:collection(xs:QName("auctions:auctions1"))
2067+by xs:string(./@key) as xs:string;
2068+
2069+declare %an:ordered collection auctions:auctions2 as node()*;
2070+
2071+declare %an:unique %an:automatic %an:value-range index auctions:PersonId2
2072+on nodes dml:collection(xs:QName("auctions:auctions2"))
2073+by xs:string(./@id) as xs:string;
2074+
2075+declare %an:sequential function auctions:create-db()
2076+{
2077+ ddl:create($auctions:auctions1);
2078+
2079+ ddl:create($auctions:auctions2);
2080+
2081+ iddl:create($auctions:PersonId1);
2082+
2083+ iddl:create($auctions:PersonId2);
2084+};
2085
2086=== added file 'test/rbkt/Queries/zorba/index/undo3.xq'
2087--- test/rbkt/Queries/zorba/index/undo3.xq 1970-01-01 00:00:00 +0000
2088+++ test/rbkt/Queries/zorba/index/undo3.xq 2012-05-03 10:05:25 +0000
2089@@ -0,0 +1,59 @@
2090+import module namespace u = "http://www.zorba-xquery.com/unique-index" at "undo2.xqlib";
2091+
2092+import module namespace dml = "http://www.zorba-xquery.com/modules/store/static/collections/dml";
2093+import module namespace idml = "http://www.zorba-xquery.com/modules/store/static/indexes/dml";
2094+
2095+declare namespace zerr = "http://www.zorba-xquery.com/errors";
2096+declare namespace err = "http://www.w3.org/2005/xqt-errors";
2097+
2098+u:create-db();
2099+
2100+dml:insert-nodes($u:auctions1, <person id="1" key="5"/>);
2101+dml:insert-nodes($u:auctions1, <person id="2" key="5"/>);
2102+
2103+try
2104+{{
2105+ (
2106+ dml:insert-nodes($u:auctions1, <person id="3" key="1"/>),
2107+
2108+ insert node <foo/> into dml:collection($u:auctions1)[1],
2109+
2110+ dml:insert-nodes($u:auctions1, <person id="4" key="5"/>),
2111+
2112+ replace value of node dml:collection($u:auctions1)[1]/@key with "1",
2113+
2114+ dml:delete-nodes-first($u:auctions1, 1),
2115+
2116+ dml:insert-nodes($u:auctions2, <person id="1"/>),
2117+ dml:insert-nodes($u:auctions2, <person id="1"/>));
2118+ ()
2119+}}
2120+catch *
2121+{
2122+ $err:code
2123+}
2124+,
2125+"
2126+"
2127+,
2128+dml:collection($u:auctions1)
2129+,
2130+"
2131+"
2132+,
2133+idml:probe-index-point-value($u:PersonId1, "1")
2134+,
2135+"
2136+"
2137+,
2138+idml:probe-index-point-value($u:PersonId1, "3")
2139+,
2140+"
2141+"
2142+,
2143+idml:probe-index-point-value($u:PersonId1, "5")
2144+,
2145+"
2146+"
2147+,
2148+dml:collection($u:auctions2)
2149
2150=== added file 'test/rbkt/Queries/zorba/index/unique.xq'
2151--- test/rbkt/Queries/zorba/index/unique.xq 1970-01-01 00:00:00 +0000
2152+++ test/rbkt/Queries/zorba/index/unique.xq 2012-05-03 10:05:25 +0000
2153@@ -0,0 +1,50 @@
2154+import module namespace u = "http://www.zorba-xquery.com/unique-index" at "unique.xqlib";
2155+
2156+import module namespace dml = "http://www.zorba-xquery.com/modules/store/static/collections/dml";
2157+import module namespace idml = "http://www.zorba-xquery.com/modules/store/static/indexes/dml";
2158+
2159+declare namespace zerr = "http://www.zorba-xquery.com/errors";
2160+declare namespace err = "http://www.w3.org/2005/xqt-errors";
2161+
2162+u:create-db();
2163+
2164+dml:insert-nodes($u:auctions1, <person id="5"/>);
2165+
2166+try
2167+{{
2168+ (dml:insert-nodes($u:auctions1, <person id="1"/>),
2169+ dml:insert-nodes($u:auctions1, <person id="1"/>));
2170+ ()
2171+}}
2172+catch *
2173+{
2174+ $err:code
2175+}
2176+,
2177+
2178+try
2179+{{
2180+ (
2181+ dml:insert-nodes($u:auctions1, <person id="1"/>),
2182+ dml:insert-nodes($u:auctions1, <person id="3"/>),
2183+ dml:delete-nodes-first($u:auctions1, 1),
2184+
2185+ dml:insert-nodes($u:auctions2, <person id="1"/>),
2186+ dml:insert-nodes($u:auctions2, <person id="1"/>));
2187+ ()
2188+}}
2189+catch *
2190+{
2191+ $err:code
2192+}
2193+,
2194+
2195+dml:collection($u:auctions1)
2196+,
2197+idml:probe-index-point-value($u:PersonId1, "1")
2198+,
2199+idml:probe-index-point-value($u:PersonId1, "3")
2200+,
2201+idml:probe-index-point-value($u:PersonId1, "5")
2202+,
2203+dml:collection($u:auctions2)
2204
2205=== added file 'test/rbkt/Queries/zorba/index/unique.xqlib'
2206--- test/rbkt/Queries/zorba/index/unique.xqlib 1970-01-01 00:00:00 +0000
2207+++ test/rbkt/Queries/zorba/index/unique.xqlib 2012-05-03 10:05:25 +0000
2208@@ -0,0 +1,37 @@
2209+module namespace auctions = "http://www.zorba-xquery.com/unique-index";
2210+
2211+import module namespace ddl = "http://www.zorba-xquery.com/modules/store/static/collections/ddl";
2212+import module namespace iddl = "http://www.zorba-xquery.com/modules/store/static/indexes/ddl";
2213+import module namespace dml = "http://www.zorba-xquery.com/modules/store/static/collections/dml";
2214+import module namespace idml = "http://www.zorba-xquery.com/modules/store/static/indexes/dml";
2215+
2216+declare namespace an = "http://www.zorba-xquery.com/annotations";
2217+
2218+declare variable $auctions:auctions1 := xs:QName("auctions:auctions1");
2219+declare variable $auctions:PersonId1 := xs:QName("auctions:PersonId1");
2220+declare variable $auctions:auctions2 := xs:QName("auctions:auctions2");
2221+declare variable $auctions:PersonId2 := xs:QName("auctions:PersonId2");
2222+
2223+declare %an:ordered collection auctions:auctions1 as node()*;
2224+
2225+declare %an:unique %an:automatic %an:value-equality index auctions:PersonId1
2226+on nodes dml:collection(xs:QName("auctions:auctions1"))
2227+by xs:string(./@id) as xs:string;
2228+
2229+
2230+declare %an:ordered collection auctions:auctions2 as node()*;
2231+
2232+declare %an:unique %an:automatic %an:value-range index auctions:PersonId2
2233+on nodes dml:collection(xs:QName("auctions:auctions2"))
2234+by xs:string(./@id) as xs:string;
2235+
2236+declare %an:sequential function auctions:create-db()
2237+{
2238+ ddl:create($auctions:auctions1);
2239+
2240+ ddl:create($auctions:auctions2);
2241+
2242+ iddl:create($auctions:PersonId1);
2243+
2244+ iddl:create($auctions:PersonId2);
2245+};

Subscribers

People subscribed via source and target branches