Changeset 136

Show
Ignore:
Timestamp:
05/21/08 22:38:41 (8 months ago)
Author:
zork
Message:

xml sublist store partial implementation

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/dba/dba/ostream.cpp

    r115 r136  
    4545 
    4646bool 
     47OStream::putChild(Storeable* pObject, ColMemberEntry& pMember, CollectionFilterBase& pFilter, const char* pTableName) { 
     48  bool ret = false; 
     49  bool was_changed = false; 
     50  //ref data contains id - old fk_value pairs 
     51  id rel_id = pMember.getRelationId(); 
     52  std::vector<id> ids = loadRefData(pTableName, pMember.getFKeyName(), rel_id, pObject->getId()); 
     53  //if object is deleted forget about storing children and  
     54  //start deleting them 
     55  if (!pObject->isDeleted()) { 
     56    std::auto_ptr<CollectionFilterIterator> iterator(pFilter.createIterator()); 
     57    //bind foreign key to object table 
     58    id fk_value = pObject->getId(); 
     59    //iterate through collection and store all changed objects 
     60    //deleted objects are erased with their all children recursively 
     61    while(iterator->hasNext()) { 
     62      //this is current instance of storeable object from BIND_COL list 
     63      //we cast away const for update and update will alter 
     64      //Storeable member fields. Because of this collection order 
     65      //should not be determined by any of Storeable field. 
     66      Storeable& toStore = (Storeable&)(iterator->get()); 
     67      //if object is deleted we just ignore it 
     68      //its id is on ids list and this object will be deleted 
     69      //with rest of objects loaded from database and not on this list 
     70      if (!toStore.isDeleted()) { 
     71        //if object is not on list then it is new or 
     72        //was moved from another parent 
     73        std::vector<id>::iterator it = std::find(ids.begin(),ids.end(),toStore.getId()); 
     74        if (it == ids.end()) { 
     75          toStore.setChanged(); 
     76        } else { 
     77          //prevent erasing object and its children by eraseChildren(ids,...) below 
     78          ids.erase(it); 
     79        }; 
     80        bind(pTableName,pMember.getFKeyName(), new Int(fk_value), Database::INTEGER); 
     81        if (rel_id != Storeable::InvalidId) 
     82          bind(pTableName,"dba_coll_id", new Int(rel_id), Database::INTEGER); 
     83        open(pTableName); 
     84        if (toStore.isNew()) { 
     85          was_changed = store(&toStore); 
     86        } else if (toStore.isChanged()) { 
     87          was_changed = update(&toStore); 
     88        }; 
     89        if (was_changed) 
     90          makeOk(pObject); 
     91        unbind(pTableName,pMember.getFKeyName()); 
     92        if (rel_id != Storeable::InvalidId) 
     93          unbind(pTableName,"dba_coll_id"); 
     94        setRootTable(NULL); 
     95        was_changed = putChildren(&toStore); 
     96        if (!ret) ret = was_changed; 
     97      }; 
     98      iterator->moveForward(); 
     99    }; 
     100  }; 
     101  //there are unknown child objects loaded from database. 
     102  //synthesize instance for them and delete them with 
     103  //their children recursively. 
     104  if (!ids.empty()) { 
     105    Storeable& for_table = pFilter.create(); 
     106    was_changed = eraseChildren(ids,for_table,pTableName); 
     107    if (!ret) ret = was_changed; 
     108  }; 
     109  return ret; 
     110}; 
     111 
     112bool 
    47113OStream::putChildren(Storeable* pObject) { 
    48114  bool ret = false; 
    49   bool was_changed = false; 
    50115  const ColTable* table = getColTable(*pObject); 
    51116  while(table != NULL) { 
     
    60125      filter.updateRef((char*)pObject + member->getMemberOffset()); 
    61126      const char* obj_table = member->getTableName(); 
    62       //ref data contains id - old fk_value pairs 
    63       id rel_id = member->getRelationId(); 
    64       std::vector<id> ids = loadRefData(obj_table, member->getFKeyName(), rel_id, pObject->getId()); 
    65       //if object is deleted forget about storing children and  
    66       //start deleting them 
    67       if (!pObject->isDeleted()) { 
    68         std::auto_ptr<CollectionFilterIterator> iterator(filter.createIterator()); 
    69         //bind foreign key to object table 
    70         id fk_value = pObject->getId(); 
    71         //iterate through collection and store all changed objects 
    72         //deleted objects are erased with their all children recursively 
    73         while(iterator->hasNext()) { 
    74           //this is current instance of storeable object from BIND_COL list 
    75           //we cast away const for update and update will alter 
    76           //Storeable member fields. Because of this collection order 
    77           //should not be determined by any of Storeable field. 
    78           Storeable& toStore = (Storeable&)(iterator->get()); 
    79           //if object is deleted we just ignore it 
    80           //its id is on ids list and this object will be deleted 
    81           //with rest of objects loaded from database and not on this list 
    82           if (!toStore.isDeleted()) { 
    83             //if object is not on list then it is new or 
    84             //was moved from another parent 
    85             std::vector<id>::iterator it = std::find(ids.begin(),ids.end(),toStore.getId()); 
    86             if (it == ids.end()) { 
    87               toStore.setChanged(); 
    88             } else { 
    89               //prevent erasing object and its children by eraseChildren(ids,...) below 
    90               ids.erase(it); 
    91             }; 
    92             bind(obj_table,member->getFKeyName(), new Int(fk_value), Database::INTEGER); 
    93             if (rel_id != Storeable::InvalidId) 
    94               bind(obj_table,"dba_coll_id", new Int(rel_id), Database::INTEGER); 
    95             open(obj_table); 
    96             if (toStore.isNew()) { 
    97               was_changed = store(&toStore); 
    98             } else if (toStore.isChanged()) { 
    99               was_changed = update(&toStore); 
    100             }; 
    101             if (was_changed) 
    102               makeOk(pObject); 
    103             unbind(obj_table,member->getFKeyName()); 
    104             if (rel_id != Storeable::InvalidId) 
    105               unbind(obj_table,"dba_coll_id"); 
    106             setRootTable(NULL); 
    107             was_changed = putChildren(&toStore); 
    108             if (!ret) ret = was_changed; 
    109           }; 
    110           iterator->moveForward(); 
    111         }; 
    112       }; 
    113       //there are unknown child objects loaded from database. 
    114       //synthesize instance for them and delete them with 
    115       //their children recursively. 
    116       if (!ids.empty()) { 
    117         Storeable& for_table = filter.create(); 
    118         was_changed = eraseChildren(ids,for_table,obj_table); 
    119         if (!ret) ret = was_changed; 
    120       }; 
     127      //call archive specific store alghoritm 
     128      bool was_changed = putChild(pObject, *member, filter, obj_table); 
     129      if (!ret) ret = was_changed; 
    121130      //move forward in loop 
    122131      member = member->getNextMember(); 
  • trunk/dba/dba/ostream.h

    r115 r136  
    4949      @param pObject object to store 
    5050    */ 
    51     bool put(Storeable* pObject); 
     51    virtual bool put(Storeable* pObject); 
    5252    /** 
    5353      Prepare stream to put Storeable objects in it. If there is problem with object store then dba::DataException is thrown.  
     
    6767    */ 
    6868    virtual ~OStream() {}; 
     69  protected: 
     70    /** 
     71      Default implementation for BIND_COL store that works on data stored in relations and  
     72      linked using foreign keys. For data formats that are not layed out in this kind of structures 
     73      you should override this method providing different alghoritm 
     74      @param pObject pointer to root object 
     75      @param pMember member from collection table 
     76      @param pFilter filter that should be used to create instance of object 
     77      @param pTableName name of root relation 
     78      @return true if at least one subobject object was stored in archive, false otherwise 
     79    */ 
     80    virtual bool putChild(Storeable* pObject, ColMemberEntry& pMember, CollectionFilterBase& pFilter, const char* pTableName); 
     81    /** 
     82      Store all Storeable objects on sublists listed as BIND_COL in store table 
     83      @param pObject object that will be examined 
     84    */ 
     85    virtual bool putChildren(Storeable* pObject); 
     86    /** 
     87      Erase all objects that are related to Storeable pObj object using 
     88      BIND_COL entries in store table. 
     89      @param pRefData list of object identifiers 
     90      @param pObj instance of object that will be erased. Used for extractiin ColTable recursively 
     91      @param pRootTableName altered name of root store table of pObj or NULL if root table was not altered 
     92    */ 
     93    virtual bool eraseChildren(const std::vector<id>& pRefData, Storeable& pObj, const char* pRootTableName); 
    6994  private: 
    7095    /** 
     
    99124    */ 
    100125    virtual bool deleteRefData(const std::vector<id>& pIds, const char* pTableName); 
    101     /** 
    102       Store all Storeable objects on sublists listed as BIND_COL in store table 
    103       @param pObject object that will be examined 
    104     */ 
    105     bool putChildren(Storeable* pObject); 
    106     /** 
    107       Erase all objects that are related to Storeable pObj object using 
    108       BIND_COL entries in store table. 
    109       @param pRefData list of object identifiers 
    110       @param pObj instance of object that will be erased. Used for extractiin ColTable recursively 
    111       @param pRootTableName altered name of root store table of pObj or NULL if root table was not altered 
    112     */ 
    113     bool eraseChildren(const std::vector<id>& pRefData, Storeable& pObj, const char* pRootTableName); 
    114126}; 
    115127 
  • trunk/dba/dba/storeable.h

    r73 r136  
    2020namespace dba { 
    2121 
     22/** 
     23  Base class for store and collection table members 
     24*/ 
    2225class dbaDLLEXPORT MemberEntryBase { 
    2326  public: 
     27    /**@internal 
     28      Constructor - for internal use only 
     29      @param pMemberName name of relation field for member 
     30      @param pMemberOffset number of bytes from 'this' to first byte of member field in class 
     31    */ 
    2432    MemberEntryBase(const char* pMemberName, int pMemberOffset); 
     33    /**@internal 
     34      Get number of bytes from this to first byte of member field 
     35    */ 
    2536    int getMemberOffset() const; 
     37    /** 
     38      Get name of relation where class member is stored 
     39    */ 
    2640    const char* getMemberName() const; 
     41    /**@internal 
     42      set in BIND_* macros - for internal use only 
     43    */ 
    2744    void setMemberOffset(int pNewOffset); 
    2845  private:   
     
    5370class ColTable; 
    5471 
    55 /**@internal 
    56   single entry in store table 
     72/** 
     73  %Single entry in store table 
    5774*/ 
    5875class dbaDLLEXPORT StoreTableMember : public MemberEntryBase { 
    5976  public: 
     77    /**@internal 
     78      Constructor - used by BIND_* macros - for internal use only 
     79      @param pOwner store table that owns this member 
     80      @param pMemberName name of relation field for member 
     81      @param pMemberOffset number of bytes from 'this' to first byte of member field in class 
     82      @param pFilter instance of storeable filter for data conversion 
     83      @param pDatabaseType type of archive data (Database::StoreType enum value) 
     84    */ 
    6085    StoreTableMember(StoreTable* pOwner, const char* pMemberName, int pMemberOffset, StoreableFilterBase* pFilter, int pDatabaseType); 
     86    /**@internal 
     87      used by BIND_* macros - for internal use only 
     88      @param pFlag true if member owns passed pointer 
     89    */ 
    6190    void setFilterOwner(bool pFlag); 
     91    /**@internal 
     92      Add member to store table - for internal use only 
     93      @param pOwner store table where member should be added 
     94    */ 
    6295    void setTable(StoreTable* pOwner); 
    63      
     96    /** 
     97      Get pointer to filter assigned to member 
     98      @return pointer to filter instance 
     99    */ 
    64100    StoreableFilterBase* getFilter(); 
     101    /**@internal 
     102      Get archive data type 
     103      @return one of Database::StoreType enum values 
     104    */ 
    65105    int getDatabaseType(); 
     106    /**@internal 
     107      Get next member from store table member list 
     108      @return pointer to next member or NULL if not found 
     109    */ 
    66110    StoreTableMember* getNextMember() const; 
     111    /**@internal 
     112      Set next member - for internal use only 
     113      @param pMember new value of mNextMember field 
     114    */ 
    67115    void setNextMember(StoreTableMember* pMember);     
     116    /** 
     117      Deletes mFilter instance if mFilterOwner is true 
     118    */ 
    68119    ~StoreTableMember(); 
    69120  private: 
  • trunk/dba/dba/xmlostream.cpp

    r133 r136  
    1212#include "xmlostream.h" 
    1313#include "conversion.h" 
     14#include "collectionfilter.h" 
    1415 
    1516namespace dba { 
     
    99100  }; 
    100101  xmlAddChild(mParentNode, node); 
     102  //set new parent node for storing subobjects 
     103  mParentNode = node; 
    101104}; 
    102105 
    103106std::vector<id>  
    104107XMLOStream::loadRefData(const char* pTable, const char* pFkName, id pCollId, id pId) { 
    105   //TODO 
     108  //not used 
     109  return std::vector<id>(); 
    106110}; 
    107111 
    108112bool  
    109113XMLOStream::deleteRefData(const std::vector<id>& pIds, const char* pTableName) { 
    110   //TODO 
     114  //not used 
     115  return false; 
     116}; 
     117 
     118bool  
     119XMLOStream::putChildren(Storeable* pObject) { 
     120  bool ret = OStream::putChildren(pObject); 
     121  //parent node was set in store() to point to valid parent object 
     122  //in hierarchy. After storing all children we have to reset it back to 
     123  //parent of pObject node 
     124  mParentNode = mParentNode->parent; 
     125  if (mParentNode == NULL) 
     126    throw DatabaseException("Internal error: parent node is NULL"); 
     127}; 
     128 
     129bool  
     130XMLOStream::putChild(Storeable* pObject, ColMemberEntry& pMember, CollectionFilterBase& pFilter, const char* pTableName) { 
     131  bool was_changed = false; 
     132  bool ret = false; 
     133  if (!pObject->isDeleted()) { 
     134    std::auto_ptr<CollectionFilterIterator> iterator(pFilter.createIterator()); 
     135    while(iterator->hasNext()) { 
     136      Storeable& toStore = (Storeable&)(iterator->get()); 
     137      if (!toStore.isDeleted()) { 
     138        was_changed = store(&toStore); 
     139        if (!ret) ret = was_changed; 
     140      }; 
     141      iterator->moveForward(); 
     142    }; 
     143  }; 
     144  return ret; 
    111145}; 
    112146 
  • trunk/dba/dba/xmlostream.h

    r133 r136  
    3030    virtual void commit() { throw APIException("commit() not supported for XML format"); } 
    3131    virtual void rollback() { throw APIException("rollback() not supported for XML format"); } 
     32    virtual ~XMLOStream(); 
     33  protected: 
    3234    virtual void assignId(Storeable* pObject) throw (Exception); 
    3335    virtual bool erase(Storeable* pObject); 
     
    3537    virtual bool store(Storeable* pObject); 
    3638    virtual bool isCollectionFilterSupported() const { return true; }; 
     39    virtual bool putChild(Storeable* pObject, ColMemberEntry& pMember, CollectionFilterBase& pFilter, const char* pTableName); 
     40    virtual bool putChildren(Storeable* pObject); 
    3741    virtual std::vector<id> loadRefData(const char* pTable, const char* pFkName, id pCollId, id pId); 
    3842    virtual bool deleteRefData(const std::vector<id>& pIds, const char* pTableName); 
    39     virtual ~XMLOStream(); 
    4043  private: 
    4144    xmlNodePtr mParentNode; 
  • trunk/dba/docs/dba.doxyfile

    r97 r136  
    2222EXTRACT_LOCAL_CLASSES  = YES 
    2323EXTRACT_LOCAL_METHODS  = NO 
    24 HIDE_UNDOC_MEMBERS     = NO 
     24HIDE_UNDOC_MEMBERS     = YES 
    2525HIDE_UNDOC_CLASSES     = YES 
    2626HIDE_FRIEND_COMPOUNDS  = YES 
  • trunk/dba/test/main.cpp

    r133 r136  
    144144  CppUnit::BriefTestProgressListener listener; 
    145145  runner.eventManager().addListener(&listener); 
    146   //runner.addTest( CppUnit::TestFactoryRegistry::getRegistry().makeTest() ); 
     146  runner.addTest( CppUnit::TestFactoryRegistry::getRegistry().makeTest() ); 
    147147  //runner.addTest(new CppUnit::TestCaller<SQLite3SQLArchiveTestCase>("debug_test",&SQLite3SQLArchiveTestCase::sqlError)); 
    148148  //runner.addTest(new CppUnit::TestCaller<PostgresSQLArchiveTestCase>("debug_test",&PostgresSQLArchiveTestCase::sqlError)); 
     
    151151  //runner.addTest(new CppUnit::TestCaller<SQLite3SQLArchiveTestCase>("debug_test",&SQLite3SQLArchiveTestCase::transactions_rollback)); 
    152152  //runner.addTest(dba_tests::XMLTestCase::suite()); 
    153   runner.addTest(new CppUnit::TestCaller<dba_tests::XMLTestCase>("debug_test",&dba_tests::XMLTestCase::varLoad)); 
     153  //runner.addTest(new CppUnit::TestCaller<dba_tests::XMLTestCase>("debug_test",&dba_tests::XMLTestCase::sublist_one)); 
    154154  //runner.addTest(new CppUnit::TestCaller<OdbcPluginTestCase>("debug_test",&OdbcPluginTestCase::dbConnection)); 
    155155  //runner.addTest(new CppUnit::TestCaller<PostgresSQLArchiveTestCase>("debug_test",&PostgresSQLArchiveTestCase::sqlError)); 
  • trunk/dba/test/testobject.h

    r48 r136  
    245245    */ 
    246246    AgregatedObject(bool pVersion = false) 
    247       : mObject(7,7.7,"7",Utils::getNow()) 
     247      : mObject(7,7.7,"7",Utils::getDate(2008,1,1,0,0,0)) 
    248248    { 
    249249      if (pVersion) { 
    250250        mInt = 77; 
    251251      } else { 
    252         mObject = TestObject(3,3.3,"333",Utils::getNow(-33)); 
     252        mObject = TestObject(3,3.3,"333",Utils::getDate(2008,1,33,0,0,0)); 
    253253        mInt = 33; 
    254254      }; 
     
    310310    { 
    311311      for (int i=0; i < pChildrenCount; i++) { 
    312         mList.push_back(TestObject(i,i,"test_object",Utils::getNow(i))); 
     312        mList.push_back(TestObject(i,i,"test_object",Utils::getDate(2008,1,i+1,0,0,0))); 
    313313      }; 
    314314    }; 
     
    338338    { 
    339339      for (int i=0; i < pChildrenCount; i++) { 
    340         mList.insert(TestObject(i,i,"test_object",Utils::getNow(i))); 
     340        mList.insert(TestObject(i,i,"test_object",Utils::getDate(2008,1,i+1,0,0,0))); 
    341341      }; 
    342342    }; 
     
    366366    { 
    367367      for (int i=0; i < pChildrenCount; i++) { 
    368         mList.insert(TestObject(i,i,"test_object",Utils::getNow(i))); 
     368        mList.insert(TestObject(i,i,"test_object",Utils::getDate(2008,1,i+1,0,0,0))); 
    369369      }; 
    370370    }; 
     
    394394    { 
    395395      for (int i=0; i < pChildrenCount; i++) { 
    396         mList.push_back(TestObject(i,i,"test_object",Utils::getNow(i))); 
     396        mList.push_back(TestObject(i,i,"test_object",Utils::getDate(2008,1,i+1,0,0,0))); 
    397397      }; 
    398398    }; 
     
    422422    { 
    423423      for (int i=0; i < pChildrenCount; i++) { 
    424         mList.push_back(TestObject(i,i,"test_object",Utils::getNow(i))); 
     424        mList.push_back(TestObject(i,i,"test_object",Utils::getDate(2008,1,i+1,0,0,0))); 
    425425      }; 
    426426    }; 
     
    450450    { 
    451451      for (int i=0; i < pChildrenCount; i++) { 
    452         mList.push_back(InheritedObject(i,i,"ObjWithInheritedList child",Utils::getNow(i))); 
     452        mList.push_back(InheritedObject(i,i,"ObjWithInheritedList child",Utils::getDate(2008,1,i+1,0,0,0))); 
    453453      }; 
    454454    }; 
     
    508508    TreeObject() {}; 
    509509    TreeObject(int pInt, double pDouble, const std::string& pStr) 
    510       : TestObject(pInt, pDouble, pStr, Utils::getNow()) 
     510      : TestObject(pInt, pDouble, pStr, Utils::getDate(2008,1,1,0,0,0)) 
    511511    {}; 
    512512    bool operator==(const TreeObject& pObj) const { 
     
    533533    { 
    534534      for (int i=0; i < pChildrenCount; i++) { 
    535         mList.push_back(NullEmptyTestObject(i,i,"null_test_object",Utils::getNow(i))); 
     535        mList.push_back(NullEmptyTestObject(i,i,"null_test_object",Utils::getDate(2008,1,i+1,0,0,0))); 
    536536      }; 
    537537    }; 
     
    559559    TwoSubobjects(const char* pName)  
    560560      : mName(pName), 
    561         mObj1(TestObject(1,1,"1",Utils::getNow())), 
    562         mObj2(TestObject(2,2,"2",Utils::getNow(1))) 
     561        mObj1(TestObject(1,1,"1",Utils::getDate(2008,1,1,0,0,0))), 
     562        mObj2(TestObject(2,2,"2",Utils::getDate(2008,1,2,0,0,0))) 
    563563    {}; 
    564564    bool operator==(const TwoSubobjects& pObj) { 
  • trunk/dba/test/utils.cpp

    r79 r136  
    3434  ret.tm_sec = pSec; 
    3535  ret.tm_isdst = -1; 
     36  //normalize fields 
     37  mktime(&ret); 
    3638  return ret; 
    3739}; 
  • trunk/dba/test/xmltestcase.cpp

    r133 r136  
    179179}; 
    180180 
     181void  
     182XMLTestCase::sublist_one() { 
     183  const char* result =  
     184"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" 
     185"<dba>\n" 
     186"  <obj_with_list name=\"sub\">\n" 
     187"    <test_objects i_value=\"0\" f_value=\"0\" s_value=\"test_object\" d_value=\"2008-01-01Z00:00:00\"/>\n" 
     188"  </obj_with_list>\n" 
     189"</dba>\n"; 
     190  { 
     191    dba::XMLArchive ar; 
     192    unlink("sublist_one.xml"); 
     193    ar.open("sublist_one.xml"); 
     194    ObjWithList obj1("sub",1); 
     195    dba::XMLOStream stream(ar.getOStream()); 
     196    stream.open(); 
     197    stream.put(&obj1); 
     198  } 
     199  CPPUNIT_ASSERT(compareXML("sublist_one.xml",result)); 
     200}; 
     201 
     202 
    181203} //namespace 
  • trunk/dba/test/xmltestcase.h

    r133 r136  
    3333      CPPUNIT_TEST(simpleLoad); 
    3434      CPPUNIT_TEST(varLoad); 
     35      CPPUNIT_TEST(sublist_one); 
    3536    CPPUNIT_TEST_SUITE_END(); 
    3637  public: 
     
    4748    void simpleLoad(); 
    4849    void varLoad(); 
     50    void sublist_one(); 
    4951  private: 
    5052    bool compareXML(const char* pFilename, const char* pData);