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