1 /*
2  * Copyright 2006-2008 The FLWOR Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #ifndef ZORBA_SIMPLE_STORE_PUL
17 #define ZORBA_SIMPLE_STORE_PUL
18 
19 #include <vector>
20 
21 #include "shared_types.h"
22 
23 #include "store/api/pul.h"
24 #include "simple_index.h"
25 
26 #include "zorbautils/hashfun.h"
27 #include "zorbautils/hashmap.h"
28 
29 
30 namespace zorba
31 {
32 
33 namespace store
34 {
35   class SchemaValidator;
36 }
37 
38 
39 namespace simplestore
40 {
41 
42 class UpdatePrimitive;
43 class IndexKey;
44 class PULImpl;
45 class QNameItem;
46 class Collection;
47 class InternalNode;
48 class TextNode;
49 
50 
51 typedef std::vector<UpdatePrimitive*> NodeUpdates;
52 
53 
54 /*******************************************************************************
55   A map that maps each target node N to the update primitives having N as their
56   target. This map is a data member of each PUL. The map contains target nodes
57   that appear in the following kinds of primitives:
58 
59   UpdDelete,
60   UpdRenameElem, UpdRenameAttr, UpdRenamePi,
61   UpdInsertChildren, UpdInsertAttributes, UpdReplaceChild,
62   UpdReplaceAttribute, UpdReplaceElemContent,
63   UpdReplaceAttrValue, UpdReplacePiValue, UpdReplaceTextValue, UpdReplaceCommentValue,
64 
65   It is used to check that, for certain kinds of updates, there are no duplicate
66   updates of that kind on the same target node. In particular, there can be no
67   duplicate rename, replaveValue, replaceContent, or replaceNode updates.
68 ********************************************************************************/
69 class NodeToUpdatesMap
70 {
71 public:
72 
73   class CompareFunction
74   {
75   public:
equal(const store::Item * n1,const store::Item * n2)76     static bool equal(const store::Item* n1, const store::Item* n2)
77     {
78       return n1 == n2;
79     }
80 
hash(const store::Item * n)81     static uint32_t hash(const store::Item* n)
82     {
83       return hashfun::h32((void*)(&n), sizeof(void*), FNV_32_INIT);
84     }
85   };
86 
87   typedef HashMap<store::Item*, NodeUpdates*, CompareFunction> Map;
88 
89   typedef Map::iterator iterator;
90 
91 private:
92 
93   Map    theMap;
94   csize  theNumDeletes;
95 
96 public:
NodeToUpdatesMap()97   NodeToUpdatesMap() : theMap(8, false), theNumDeletes(0)
98   {
99   }
100 
101   ~NodeToUpdatesMap();
102 
begin()103   iterator begin() const { return theMap.begin(); }
104 
end()105   iterator end() const { return theMap.end(); }
106 
empty()107   bool empty() const { return theMap.empty(); }
108 
get(store::Item * key,NodeUpdates * & value)109   bool get(store::Item* key, NodeUpdates*& value) { return theMap.get(key, value); }
110 
insert(store::Item * key,NodeUpdates * value)111   bool insert(store::Item* key, NodeUpdates* value) { return theMap.insert(key, value); }
112 
remove(store::Item * key)113   bool remove(store::Item* key) { return theMap.erase(key); }
114 
clear()115   void clear() { theMap.clear(); }
116 };
117 
118 
119 /*******************************************************************************
120   Class storing all update primitives involving a single collection, or no
121   collection at all.
122 
123   theDoFirstList:
124   ---------------
125   insertInto, insertAttributes, replaceValue, rename
126 
127   theInsertList:
128   --------------
129   insertBefore, insertAfter, insertIntoFirst, insertIntoLast
130 
131   theMergeToCheckSet:
132   -------------------
133   Nodes whose children might need to be merged
134 
135 ********************************************************************************/
136 class CollectionPul
137 {
138   friend class PULImpl;
139   friend class UpdatePrimitive;
140   friend class ElementNode;
141   friend class AttributeNode;
142 
143   struct TextNodeMerge
144   {
145     InternalNode         * theParent;
146     ulong                  thePos;
147     std::vector<XmlNode_t> theMergedNodes;
148 
TextNodeMergeTextNodeMerge149     TextNodeMerge(InternalNode* aParent, ulong aPos)
150       :
151       theParent(aParent),
152       thePos(aPos)
153     {
154     }
155   };
156 
157 protected:
158   // Bookeeping
159   Collection                       * theCollection;
160 
161   PULImpl                          * thePul;
162 
163   NodeToUpdatesMap                   theNodeToUpdatesMap;
164 
165   std::set<InternalNode*>            theMergeToCheckSet;
166   std::vector<TextNodeMerge>         theMergeList;
167 
168   std::vector<UpdatePrimitive*>      thePrimitivesToRecheck;
169 
170   std::set<store::Item*>             theValidationNodes;
171 
172   store::PUL_t                       theValidationPul;
173 
174   bool                               theAdjustTreePositions;
175 
176   bool                               theIsApplied;
177 
178   // XQUF update primitives
179   std::vector<UpdatePrimitive*>      theDoFirstList;
180   std::vector<UpdatePrimitive*>      theInsertList;
181   std::vector<UpdatePrimitive*>      theReplaceNodeList;
182   std::vector<UpdatePrimitive*>      theReplaceContentList;
183   std::vector<UpdatePrimitive*>      theDeleteList;
184 
185   // Update primitives for collection functions
186   std::vector<UpdatePrimitive*>      theCreateCollectionList;
187   std::vector<UpdatePrimitive*>      theInsertIntoCollectionList;
188   std::vector<UpdatePrimitive*>      theDeleteFromCollectionList;
189   std::vector<UpdatePrimitive*>      theTruncateCollectionList;
190   std::vector<UpdatePrimitive*>      theDeleteCollectionList;
191 
192   // Validate in place primitives
193   std::vector<UpdatePrimitive*>      theRevalidateList;
194 
195   // Index Maintenance
196   std::set<store::Item*>             theModifiedDocs;
197   std::vector<store::Item*>          theInsertedDocs;
198   std::vector<store::Item*>          theDeletedDocs;
199 
200   std::vector<IndexImpl*>            theIncrementalIndices;
201   std::vector<IndexImpl*>            theTruncatedIndices;
202 
203   std::vector<IndexEntryCreator_t>   theIndexEntryCreators;
204 
205   std::vector<IndexDeltaImpl>        theBeforeIndexDeltas;
206   std::vector<IndexDeltaImpl>        theAfterIndexDeltas;
207   std::vector<IndexDeltaImpl>        theInsertedDocsIndexDeltas;
208   std::vector<IndexDeltaImpl>        theDeletedDocsIndexDeltas;
209 
210 #ifdef ZORBA_WITH_JSON
211   // jsoniq primitives
212   std::vector<UpdatePrimitive*>      theJSONObjectInsertList;
213   std::vector<UpdatePrimitive*>      theJSONObjectDeleteList;
214   std::vector<UpdatePrimitive*>      theJSONObjectReplaceValueList;
215   std::vector<UpdatePrimitive*>      theJSONObjectRenameList;
216 
217   std::vector<UpdatePrimitive*>      theJSONArrayInsertList;
218   std::vector<UpdatePrimitive*>      theJSONArrayAppendList;
219   std::vector<UpdatePrimitive*>      theJSONArrayDeleteList;
220   std::vector<UpdatePrimitive*>      theJSONArrayReplaceValueList;
221 #endif
222 
223   std::vector<csize>                 theNumBeforeIndexDeltasApplied;
224   std::vector<csize>                 theNumAfterIndexDeltasApplied;
225   std::vector<csize>                 theNumInsertedDocsIndexDeltasApplied;
226   std::vector<csize>                 theNumDeletedDocsIndexDeltasApplied;
227 
228 public:
229   CollectionPul(PULImpl* pul, Collection* collection);
230 
231   ~CollectionPul();
232 
233   void switchPul(PULImpl* pul);
234 
235   void computeIndexBeforeDeltas();
236 
237   void computeIndexAfterDeltas();
238 
239   void refreshIndexes();
240 
241   void applyUpdates();
242 
243   void undoUpdates();
244 
245   void finalizeUpdates();
246 
setAdjustTreePositions()247   void setAdjustTreePositions() { theAdjustTreePositions = true; }
248 
addToCheckForMerge(InternalNode * parent)249   void addToCheckForMerge(InternalNode* parent) { theMergeToCheckSet.insert(parent); }
250 
251 protected:
252   void switchPulInPrimitivesList(std::vector<UpdatePrimitive*>& list);
253 
254   void computeIndexDeltas(std::vector<IndexDeltaImpl>& deltas);
255 
256   void cleanIndexDeltas();
257 
258   void refreshValueIndex(csize idx);
259 
260   void refreshGeneralIndex(csize idx);
261 
262   void undoValueIndexRefresh(csize idx);
263 
264   void undoGeneralIndexRefresh(csize idx);
265 
266   void truncateIndexes();
267 
268   void undoRefreshIndexes();
269 };
270 
271 
272 /*******************************************************************************
273   theCollectionPuls  :
274   theNoCollectionPul : Pointer to the CollectionPul that contains the XQUF
275                        primitives for the trees that do not belong to any
276                        collection. Note: theCollectionPuls contains a pointer
277                        to this CollectionPul as well, with NULL as the associated
278                        QName item.
279   theLastPul         :
280   theLastCollection  :
281 
282   thePutList         :
283   theCreateIndexList :
284   theDeleteIndexList :
285   theRefreshIndexList:
286 
287   theValidator       :
288   theValidationList  : If this list is non-empty, then all the other lists are
289                        empty and vice-versa.
290 
291   theICChecker       : The object that invokes the check Iterator
292 ********************************************************************************/
293 class PULImpl : public store::PUL
294 {
295   friend class CollectionPul;
296   friend class UpdRevalidate;
297 
298 public:
299   enum UpdListKind
300   {
301     UP_LIST_NONE,
302     UP_LIST_DO_FIRST,
303     UP_LIST_REPLACE_NODE,
304     UP_LIST_REPLACE_CONTENT,
305     UP_LIST_DELETE,
306     UP_LIST_PUT,
307     UP_LIST_CREATE_COLLECTION,
308     UP_LIST_CREATE_INDEX
309   };
310 
311   typedef std::vector<CollectionPul*> CollectionPuls;
312 
313   typedef std::map<const QNameItem*, csize> CollectionPulMap;
314 
315 protected:
316   // XQUF and collection primitives, grouped by the collection that is being updated.
317   CollectionPuls                     theCollectionPuls;
318   CollectionPulMap                   theCollectionPulsMap;
319   CollectionPul                    * theNoCollectionPul;
320   CollectionPul                    * theLastPul;
321   const QNameItem                  * theLastCollection;
322 
323   // fn:put primitives
324   std::vector<UpdatePrimitive*>      thePutList;
325 
326   // Index primitives
327   std::vector<UpdatePrimitive*>      theCreateIndexList;
328   std::vector<UpdatePrimitive*>      theDeleteIndexList;
329   std::vector<UpdatePrimitive*>      theRefreshIndexList;
330 
331   // Integrity constrint
332   std::vector<UpdatePrimitive*>      theICActivationList;
333   store::ICChecker                 * theICChecker;
334 
335   // Document primitives
336   std::vector<UpdatePrimitive*>      theCreateDocumentList;
337   std::vector<UpdatePrimitive*>      theDeleteDocumentList;
338 
339   // Hashmap primitives
340   // ddl
341   std::vector<UpdatePrimitive*>      theCreateHashMapList;
342   std::vector<UpdatePrimitive*>      theDestroyHashMapList;
343   // dml
344   std::vector<UpdatePrimitive*>      theInsertIntoHashMapList;
345   std::vector<UpdatePrimitive*>      theRemoveFromHashMapList;
346 
347   // Revalidation
348   store::SchemaValidator           * theValidator;
349 
350   std::vector<UpdatePrimitive*>      theValidationList;
351 
352   bool                               theInheritNSBindings;
353 
354 public:
355   PULImpl();
356 
357   ~PULImpl();
358 
359   // XQUF primitives
360   void addDelete(
361       const QueryLoc* aQueryLoc,
362       store::Item_t& n);
363 
364   void addInsertInto(
365         const QueryLoc* aQueryLoc,
366         store::Item_t& target,
367         std::vector<store::Item_t>& children);
368 
369   void addInsertFirst(
370         const QueryLoc* aQueryLoc,
371         store::Item_t& target,
372         std::vector<store::Item_t>& children);
373 
374   void addInsertLast(
375         const QueryLoc* aQueryLoc,
376         store::Item_t& target,
377         std::vector<store::Item_t>& children);
378 
379   void addInsertBefore(
380         const QueryLoc* aQueryLoc,
381         store::Item_t& target,
382         std::vector<store::Item_t>& siblings);
383 
384   void addInsertAfter(
385         const QueryLoc* aQueryLoc,
386         store::Item_t& target,
387         std::vector<store::Item_t>& siblings);
388 
389   void addInsertAttributes(
390         const QueryLoc* aQueryLoc,
391         store::Item_t& target,
392         std::vector<store::Item_t>& attrs);
393 
394   void addReplaceNode(
395         const QueryLoc* aQueryLoc,
396         store::Item_t& target,
397         std::vector<store::Item_t>& replacementNodes);
398 
399   void addReplaceContent(
400         const QueryLoc* aQueryLoc,
401         store::Item_t& target,
402         store::Item_t& newTextChild);
403 
404   void addReplaceValue(
405         const QueryLoc* aQueryLoc,
406         store::Item_t& target,
407         zstring& newValue);
408 
409   void addRename(
410         const QueryLoc* aQueryLoc,
411         store::Item_t& target,
412         store::Item_t& newName);
413 
414   void addPut(
415         const QueryLoc* aQueryLoc,
416         store::Item_t& node,
417         store::Item_t& uri);
418 
419   // Revalidation primitives
420   void addSetElementType(
421         const QueryLoc* aQueryLoc,
422         store::Item_t& target,
423         store::Item_t& typeName,
424         store::Item_t& value,
425         bool haveValue,
426         bool haveEmptyValue,
427         bool haveTypedValue,
428         bool isInSubstitutionGroup);
429 
430   void addSetElementType(
431         const QueryLoc* aQueryLoc,
432         store::Item_t&               target,
433         store::Item_t&               typeName,
434         std::vector<store::Item_t>&  value,
435         bool                         haveValue,
436         bool                         haveEmptyValue,
437         bool                         haveTypedValue,
438         bool                         isInSubstitutionGroup);
439 
440   void addSetAttributeType(
441         const QueryLoc* aQueryLoc,
442         store::Item_t&               target,
443         store::Item_t&               typeName,
444         store::Item_t&               typedValue);
445 
446   void addSetAttributeType(
447         const QueryLoc* aQueryLoc,
448         store::Item_t&              target,
449         store::Item_t&              typeName,
450         std::vector<store::Item_t>& typedValue);
451 
452   void addRevalidate(
453           const QueryLoc* aQueryLoc,
454           store::Item_t&              target);
455 
456   // Collection primitives
457   void addCreateCollection(
458         const QueryLoc* aQueryLoc,
459         store::Item_t& name,
460         const std::vector<store::Annotation_t>& annotations,
461         const store::Item_t& nodeType,
462         bool isDynamic);
463 
464   void addDeleteCollection(
465         const QueryLoc* aQueryLoc,
466         store::Item_t& name,
467         bool isDynamic);
468 
469   void addInsertIntoCollection(
470         const QueryLoc* aQueryLoc,
471         store::Item_t& name,
472         std::vector<store::Item_t>& nodes,
473         bool isDynamic);
474 
475   void addInsertFirstIntoCollection(
476         const QueryLoc* aQueryLoc,
477         store::Item_t& name,
478         std::vector<store::Item_t>& nodes,
479         bool isDynamic);
480 
481   void addInsertLastIntoCollection(
482         const QueryLoc* aQueryLoc,
483         store::Item_t& name,
484         std::vector<store::Item_t>& nodes,
485         bool isDynamic);
486 
487   void addInsertBeforeIntoCollection(
488         const QueryLoc* aQueryLoc,
489         store::Item_t& name,
490         store::Item_t& target,
491         std::vector<store::Item_t>& nodes,
492         bool isDynamic);
493 
494   void addInsertAfterIntoCollection(
495         const QueryLoc* aQueryLoc,
496         store::Item_t& name,
497         store::Item_t& target,
498         std::vector<store::Item_t>& nodes,
499         bool isDynamic);
500 
501   void addDeleteFromCollection(
502         const QueryLoc* aQueryLoc,
503         store::Item_t& name,
504         std::vector<store::Item_t>& nodes,
505         bool isLast,
506         bool isDynamic);
507 
508   void addTruncateCollection(
509         const QueryLoc* aQueryLoc,
510         store::Item_t& name,
511         bool isDynamic);
512 
513   // Index primitives
514   void addCreateIndex(
515         const QueryLoc* aQueryLoc,
516         const store::Item_t& qname,
517         const store::IndexSpecification& spec,
518         store::Iterator* sourceIter);
519 
520   void addDeleteIndex(
521         const QueryLoc* aQueryLoc,
522         const store::Item_t& qname);
523 
524   void addRefreshIndex(
525         const QueryLoc* aQueryLoc,
526         const store::Item_t& qname,
527         store::Iterator* sourceIter);
528 
529   virtual void addActivateIC(
530         const QueryLoc* aQueryLoc,
531         const store::Item_t& qname,
532         const store::Item_t& aCollectionName);
533 
534   virtual void addActivateForeignKeyIC(
535         const QueryLoc* aQueryLoc,
536         const store::Item_t& qname,
537         const store::Item_t& aFromCollectionName,
538         const store::Item_t& aToCollectionName);
539 
540   virtual void addDeActivateIC(
541         const QueryLoc* aQueryLoc,
542         const store::Item_t& qname);
543 
544   // document primitives
545   virtual void addCreateDocument(
546         const QueryLoc* aQueryLoc,
547         const store::Item_t& uri,
548         store::Item_t& doc);
549 
550   virtual void addDeleteDocument(
551         const QueryLoc* aQueryLoc,
552         const store::Item_t& uri);
553 
554   // hash map primitives
555 
556   virtual void addCreateHashMap(
557         const QueryLoc* aQueryLoc,
558         const store::Item_t& aQName,
559         const std::vector<store::Item_t>& aKeyTypes,
560         const std::vector<zstring>& aCollations,
561         long  aTimezone);
562 
563   virtual void addDestroyHashMap(
564         const QueryLoc* aQueryLoc,
565         const store::Item_t& aQName);
566 
567   virtual void addInsertIntoHashMap(
568       const QueryLoc* aQueryLoc,
569       const store::Item_t& aQName,
570       const std::vector<store::Item_t>& aKey,
571       const store::Iterator_t& aValue);
572 
573   virtual void addRemoveFromHashMap(
574       const QueryLoc* aQueryLoc,
575       const store::Item_t& aQName,
576       const std::vector<store::Item_t>& aKey);
577 
578 #ifdef ZORBA_WITH_JSON
579   // jsoniq primitives
580 
581   virtual void addJSONObjectInsert(
582       const QueryLoc* aQueryLoc,
583       store::Item_t& target,
584       std::vector<store::Item_t>& names,
585       std::vector<store::Item_t>& values);
586 
587   virtual void addJSONObjectInsert(
588       const QueryLoc* aQueryLoc,
589       store::Item_t& target,
590       store::Item_t& content);
591 
592   virtual void addJSONObjectDelete(
593       const QueryLoc* aQueryLoc,
594       store::Item_t& target,
595       store::Item_t& name);
596 
597   virtual void addJSONObjectReplaceValue(
598       const QueryLoc* aQueryLoc,
599       store::Item_t& target,
600       store::Item_t& name,
601       store::Item_t& newValue);
602 
603   virtual void addJSONObjectRename(
604       const QueryLoc* aQueryLoc,
605       store::Item_t& target,
606       store::Item_t& name,
607       store::Item_t& newName);
608 
609   virtual void addJSONArrayInsert(
610       const QueryLoc* aQueryLoc,
611       store::Item_t& target,
612       store::Item_t& pos,
613       std::vector<store::Item_t>& members);
614 
615   virtual void addJSONArrayAppend(
616       const QueryLoc* aQueryLoc,
617       store::Item_t& target,
618       std::vector<store::Item_t>& members);
619 
620   virtual void addJSONArrayDelete(
621       const QueryLoc* aQueryLoc,
622       store::Item_t& target,
623       store::Item_t& pos);
624 
625   virtual void addJSONArrayReplaceValue(
626       const QueryLoc* aQueryLoc,
627       store::Item_t& target,
628       store::Item_t& pos,
629       store::Item_t& newValue);
630 #endif
631 
632   // merge
633   void mergeUpdates(store::Item* other);
634 
635   // apply
636   void applyUpdates(bool inheritNSBindings);
637 
638   // utils
639   void checkTransformUpdates(const std::vector<store::Item*>& rootNodes) const;
640 
641   void getIndicesToRefresh(
642       std::vector<store::Index*>& indices,
643       std::vector<store::Index*>& truncate_indices);
644 
645   void addIndexEntryCreator(
646         const store::Item* collectionName,
647         store::Index* idx,
648         store::IndexEntryCreator* creator);
649 
650   void addIndexTruncator(
651       const store::Item* collectionName,
652       store::Index* idx);
653 
654   void setValidator(store::SchemaValidator* validator);
655 
getValidator()656   store::SchemaValidator* getValidator() const { return theValidator; }
657 
inheritNSBindings()658   bool inheritNSBindings() const { return theInheritNSBindings; }
659 
660   // integrity constraints related
661   void setICChecker(store::ICChecker* icChecker);
662 
663   void checkIC(const store::Item* collName);
664 
665 
666 protected:
667   void mergeTargetedUpdateLists(
668       CollectionPul* myPul,
669       std::vector<UpdatePrimitive*>& myList,
670       std::vector<UpdatePrimitive*>& otherList);
671 
672   void mergeCollectionUpdateLists(
673       CollectionPul* myPul,
674       std::vector<UpdatePrimitive*>& myList,
675       std::vector<UpdatePrimitive*>& otherList);
676 
677   void mergeSimpleUpdateLists(
678       std::vector<UpdatePrimitive*>& myList,
679       std::vector<UpdatePrimitive*>& otherList);
680 
681   void addInsertChildren(
682         const QueryLoc* loc,
683         store::UpdateConsts::UpdPrimKind kind,
684         store::Item_t& target,
685         store::Item_t& sibling,
686         std::vector<store::Item_t>& children);
687 
688   CollectionPul* getCollectionPul(const store::Item* target);
689 
690   CollectionPul* getCollectionPulByName(const store::Item* name, bool isDynamic);
691 
692   void undoUpdates();
693 };
694 
695 
696 
697 
698 }
699 }
700 
701 #endif
702 
703 /*
704  * Local variables:
705  * mode: c++
706  * End:
707  */
708 /* vim:set et sw=2 ts=2: */
709