X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=src2%2FcreaImageIOSQLiteTreeHandler.cpp;h=f29a8ce7ef4b7ced02410167684d1b1405cfef16;hb=96ca5a0d7b7ccd6b4291160c19afd48e3207db2a;hp=4d0d49eae165825a158b77f9788857c54d07a3a1;hpb=f4bdead5143dc3d816f1c2f2bd9786a21c843760;p=creaImageIO.git diff --git a/src2/creaImageIOSQLiteTreeHandler.cpp b/src2/creaImageIOSQLiteTreeHandler.cpp index 4d0d49e..f29a8ce 100644 --- a/src2/creaImageIOSQLiteTreeHandler.cpp +++ b/src2/creaImageIOSQLiteTreeHandler.cpp @@ -13,15 +13,9 @@ #include -#include "wx/wx.h" -#include -#include - - //#include #include -#include using namespace crea; #include @@ -37,6 +31,7 @@ namespace creaImageIO : mFileName(filename) { mDB = new CppSQLite3DB; + mIsAdding=false; GimmickMessage(1,"SQLite version : " <SQLiteVersion())<< std::endl); } @@ -50,95 +45,8 @@ namespace creaImageIO //============================================================= - //============================================================= - void SQLiteTreeHandler::BuildDefaultTreeDescription() - { - /* - for (int i = Node::Patient; - i <= Node::Image; - ++i) - { - mNodeTypeDescription[i].BuildDefault(i); - } - */ - - // TODO : GetTree().GetDescription().LoadXML(FILE); - } - //============================================================= - - //============================================================= - // void SQLiteTreeHandler::Print() const - // { - /* - std::cout << "-> '"<Print(); - } - */ - // } - //============================================================= - - //===================================================================== - /* - bool SQLiteTreeHandler::LocationIsValid() - { - // TO DO - return true; - } - */ - //===================================================================== - - //===================================================================== - char* format_sql(const std::string& s) - { - return sqlite3_mprintf("%q",s.c_str()); - } //===================================================================== - // sqlite3_exec(db, zSQL, 0, 0, 0); - // sqlite3_free(zSQL); - // char* CHAIN = format_sql(QUER); \ -// sqlite3_free(CHAIN); \ - - //===================================================================== -#define QUERYDB(QUER,RES) \ - try \ - { \ - GimmickMessage(2,"SQL: '"<execQuery(QUER.c_str()); \ - } \ - catch (CppSQLite3Exception& e) \ - { \ - std::cout << "SQLite query '"<execDML(UP.c_str()); \ - } \ - catch (CppSQLite3Exception& e) \ - { \ - std::cout << "SQLite update '"<& attr ) + int SQLiteTreeHandler::AddBranch( const AttributeMapType& attr ) { - return -1; + tree::Node* parent = DBGetParent(attr); + DBGraftToParent(parent,attr); + return (parent->GetLevel()+1); + } //===================================================================== //===================================================================== - bool SQLiteTreeHandler::Remove(tree::Node*) + bool SQLiteTreeHandler::Remove(tree::Node* node) { - return false; + DBRecursiveRemoveNode(node); + + // std::cout << "DELETE"<GetParent(); + if (parent) + { + int nC = parent->RemoveChildrenFromList(node); + if(nC>0 && parent->GetLevel()>0) + { + std::stringstream out; + out <GetLevel()>0) + { + Remove(parent); + } + // std::cout << "DELETE OK"<execQuery(QUER.c_str()); \ + } \ + catch (CppSQLite3Exception& e) \ + { \ + GimmickError("SQLite query '"<execDML(UP.c_str()); \ + } \ + catch (CppSQLite3Exception& e) \ + { \ + GimmickError("SQLite update '"<0, i.e. not Root) + if (l>=0) { - command = "INSERT INTO LEVELS (Name) VALUES ('"; - command += GetTree().GetLevelDescriptor(l).GetName(); - command += "')"; - UPDATEDB(command); - command = "CREATE TABLE "; command += GetTree().GetLevelDescriptor(l).GetName(); - command += "\n(\nID INTEGER PRIMARY KEY,\nPARENT_ID int not null"; - AppendAttributesSQLDefinition(l,command); - command +=",\n"; - command +="constraint FK_PARENT foreign key (PARENT_ID) references PATIENT(ID) on delete restrict on update restrict\n)"; + command += "\n(\nID INTEGER PRIMARY KEY"; + if (l>1) + { + command += ",\nPARENT_ID int not null"; + } + SQLAppendAttributesDefinition(l,command); + if (l>1) + { + command += ",\nconstraint FK_PARENT foreign key (PARENT_ID) references "; + command += GetTree().GetLevelDescriptor(l-1).GetName(); + command += "(ID) on delete restrict on update restrict"; + } + command += "\n)"; UPDATEDB(command); + + + // Add Attribute 'ID' to Description + GetTree().GetDescriptor().Add + (AttributeDescriptor( "ID", + "Database Identifier", + 0,0, + AttributeDescriptor::PRIVATE + ),l); + + if (l>1) + { + // Add Attribute 'PARENT_ID' to Description + GetTree().GetDescriptor().Add + (AttributeDescriptor( "PARENT_ID", + "Database Parent Identifier", + 0,0, + AttributeDescriptor::PRIVATE + ),l); + } + } - // Create tables *_ATTRIBUTES - // and fill the tables *_ATTRIBUTES - DBExportTreeDescription(); - - } - catch (std::exception) - { - return false; - } - // LG : TEST - if (DBStructureIsValid()) - { - // std::cout << "*** DONE ***"<second.flags==1) continue; - s += ",\n"; - s += i->GetKey(); - s += " text"; - } - } - //===================================================================== - - //===================================================================== - void SQLiteTreeHandler::DBExportTreeDescription() - { - for (int level=0; levelGetKey() << "','" @@ -395,567 +381,641 @@ namespace creaImageIO << i->GetGroup() << "," << i->GetElement() << "," << i->GetFlags() << ");"; - UPDATEDB(insert.str()); } - } + + } // For l=0... + + // Initialize the root attributes + GetTree().InitializeAttributeMap(); + // Insert the root in the level 0 table + DBInsert(GetTree().GetTree()); + + GetTree().SetChildrenLoaded(true); + GimmickMessage(1,"Creating SQLite database '"<second.flags==1) continue; + s += ",\n"; + s += i->GetKey(); + s += " text"; + } + } + //===================================================================== + + + //===================================================================== + bool SQLiteTreeHandler::DBImportTreeDescription() + { + GimmickMessage(1,"Importing tree description for database ..." + <tableExists("LEVELS") ) { - std::string query = "SELECT * FROM "; - query += SQLiteTreeHandlerStructure::Table(type); - query += "_FIELDS"; + GimmickMessage(1,"!! ERROR : Table 'LEVELS' does not exist" + <tableExists(table.c_str()) ) + { + GimmickMessage(1,"!! ERROR : Table '"<tableExists(SQLiteTreeHandlerStructure::Table(i)); - if (ok) - { - // std::cout << "** Table "<GetKey(), "" ); } - */ - return success; - } - //===================================================================== - /* - //===================================================================== - int SQLiteTreeHandler::DBLoadChildren(Node* parent, - int maxlevel) - { + // Reading Root attributes + // Query DB + query = "SELECT * FROM "; + query += GetTree().GetLevelDescriptor(0).GetName(); + QUERYDB(query,q); - // std::cout << "SQLiteTreeHandler::DBLoadChildren("<ChildrenLoaded() ) + for (int fld = 0; fld < q.numFields(); fld++) { - // std::cout << "--> Children already loaded"<GetType() == Node::Image ) - { - return nbloaded; - } - if ( xparent->GetType() >= maxlevel ) - { - return nbloaded; - } - - // msw[2].Pause(); - // msw[2].Resume(); - - Node::Type type = xparent->GetType()+1; - // Query DB - - std::string query = "SELECT * FROM "; - query += GetTree().GetDescriptor().GetLevelDescriptor(level).GetName(); - //SQLiteTreeHandlerStructure::Table(type); - if (parent!=0) - { - query += " WHERE PARENT_ID='" + parent->GetFieldValue("ID") + "'"; - } - - // std::cout << "** SQL = '"<SetFieldValue(q.fieldName(fld),q.getStringField(fld)); - } - // Index - TypeId ti; - ti.type = type; - ti.id = n->GetFieldValue("ID"); - mTypeIdToNodeMap[ti] = n; - // recurse - if ( type < maxlevel ) + if (str[i]==0) { - msw[2].Pause(); - nbloaded += DBLoadChildren(n,maxlevel); - msw[2].Resume(); + str = str.substr(0,i); + break; } - // next entry in db - q.nextRow(); } - - xparent->SetChildrenLoaded(true); - - // msw[2].Pause(); - return nbloaded; + // if (iGetAttributeMap().begin(); + i != n->GetAttributeMap().end(); + i++) + { + if (i->first=="ID") + { + continue; + } + atts += "'" + i->first + "'"; + values += "'" + SQLformat(i->second) + "'"; + atts += ","; + values += ","; + GimmickMessage(4,"'"<first<<"' = '"<second<<"'"<GetLabel() - // <<"')"<GetLabel()<<"'" - // << std::endl; - // Load the patients if not already done - DBLoadChildren(this,Node::Patient); - - parent_id = ""; - Node* parent = this; - - // The chain of ancestors - std::deque chain; - Node* cur = alien_node->GetParent(); - for (int type=Node::Patient; - typeGetType();++type) - { - chain.push_front(cur); - cur = cur->GetParent(); - } - - // create the nodes if do not exist - std::deque::iterator i; - for (i=chain.begin();i!=chain.end();++i) - { - // std::cout << " cur = '"<<(*i)->GetLabel()<<"'"<GetType()+1); - - parent_id = cur_id; + Node* parent = GetTree().GetTree(); + bool go_down; + do + { + go_down = false; + // Load the children of the current parent + DBLoadChildren(parent); + // Iterate the children + tree::Node::ChildrenListType::const_iterator i; + for (i = parent->GetChildrenList().begin(); + i!= parent->GetChildrenList().end(); + ++i) + { + if ( (*i)->Matches( attr ) ) + { + go_down = true; + parent = *i; + break; + } + } } + while (go_down); return parent; } //===================================================================== - - //===================================================================== - void SQLiteTreeHandler::DBRecursiveGetOrCreateNode(Node* alien_node, - Node* parent, - const std::string& parent_id, - UpdateSummary& summary) + int SQLiteTreeHandler::DBLoadChildren(tree::Node* node, + int numberoflevels) { - // std::cout << "SQLiteTreeHandler::RecursiveGetOrCreateNode('" - // <GetLabel() - // <<"','"<GetChildrenList().begin(); - i != alien_node->GetChildrenList().end(); - i++) - { - DBRecursiveGetOrCreateNode((*i),new_node,new_id,summary); - } - } - //===================================================================== + if (node->GetLevel()+1 >= node->GetTree()->GetNumberOfLevels() ) + return 0; + GimmickMessage(2,"Loading children of '"<GetLabel() + <<"'"<GetLabel()<<"','" - // << internal_parent << "','"<< parent_id<<"')"<GetChildrenLoaded()) { - // std::cout << " -- Parent = '"<GetLabel()<<"'"<GetChildrenList().begin(); + i!= node->GetChildrenList().end(); + ++i) + { + nbloaded += DBLoadChildren(*i,numberoflevels-1); + } + node->SetChildrenLoaded(true); + return nbloaded; + } - // Node Exists ? return it - // First try among children of internal parent - Node* node = GetChildrenLike(internal_parent,alien_node); - if (node>0) + else + { + /// If children not loaded : do it and recurse + + // Query DB + int level = node->GetLevel(); + std::string query = "SELECT * FROM "; + + query += GetTree().GetLevelDescriptor(level+1).GetName(); + if (level>0) { - node_id = node->UnsafeGetFieldValue("ID"); - return node; + query += " WHERE PARENT_ID='" + node->GetAttribute("ID") + + "'"; } - // Second : try in DB - - // Does not exist : Create new one - node = new Node(alien_node->GetType(),this,internal_parent); - node->SetChildrenLoaded(true); - // Copy fields values from alien - Node::FieldValueMapType::iterator i,j; - for (i = node->GetFieldValueMap().begin(); - i != node->GetFieldValueMap().end(); - i++) + CppSQLite3Query q; + QUERYDB(query,q); + + int p=0; + while (!q.eof()) { - j = alien_node->GetFieldValueMap().find(i->first); - if (j != alien_node->GetFieldValueMap().end() ) + + // std::cout << "DBLoadCh : creating node level "<second = j->second; + n->UnsafeSetAttribute(q.fieldName(fld),q.getStringField(fld)); } + + // recurse + if ( numberoflevels != 1 ) + { + // msw[2].Pause(); + nbloaded += DBLoadChildren(n, numberoflevels-1); + // msw[2].Resume(); + } + // next entry in db + q.nextRow(); } - msw[2].Resume(); - if (node->GetType()!=Node::Patient) - node->SetFieldValue("PARENT_ID",parent_id); + node->SetChildrenLoaded(true); + + + // msw[2].Pause(); + return nbloaded; + } + } + //===================================================================== - // Insert in DB + //====================================================================== + void SQLiteTreeHandler::DBInsert(tree::Node* n) + { + GimmickMessage(2,"Inserting in DB '"<GetLabel() + <<"'"<GetType())) - + " " + val + ";"; - // std::cout << "** SQL = '"<GetLevel()).GetName(); + insert += " " + val + ";"; + UPDATEDB(insert); + // Store DB id of newly created node; long lastrow = mDB->lastRowId(); std::stringstream ri; ri << mDB->lastRowId(); - node_id = ri.str(); - // std::cout << "LastRowId='"<lastRowId()<<"' vs '"<SetFieldValue("ID",node_id); - // Insert in TypeId map - TypeId ti; - ti.type = node->GetType(); - ti.id = node_id; - mTypeIdToNodeMap[ti] = node; - // std::cout << "== Insert TypeId ("<GetType()==Node::Patient) summary.added_patients++; - if (node->GetType()==Node::Study) summary.added_studies++; - if (node->GetType()==Node::Series) summary.added_series++; - if (node->GetType()==Node::Image) summary.added_images++; - - return node; + n->SetAttribute("ID",ri.str()); } - //===================================================================== + //====================================================================== - //===================================================================== - Node* SQLiteTreeHandler::GetChildrenLike(Node* parent, - Node* alien_node) + //====================================================================== + /// Graft the branch defined by the attributes to the parent + void SQLiteTreeHandler::DBGraftToParent( tree::Node* parent, + const AttributeMapType& attr) { - Node::ChildrenListType::iterator i; - for (i = parent->GetChildrenList().begin(); - i != parent->GetChildrenList().end(); - i++) + // std::cout <<"Grafting to parent '"<GetLabel() + // <<"'"<GetLevel()+1; + level < GetTree().GetNumberOfLevels(); + level++) { - Node::Type type = alien_node->GetType(); - bool ok = true; - for (int j=0; - jGetFieldValue(SQLiteTreeHandlerStructure:: - QueryField(type,j).key ) != - (*i)->GetFieldValue(SQLiteTreeHandlerStructure:: - QueryField(type,j).key ) ) - { - ok = false; - break; - } - } - if (ok) + // Create Node + tree::Node* child = new tree::Node(parent,attr); + child->SetChildrenLoaded(true); + if (level>1) { - return (*i); + int nc = GetNumberOfChildren(parent)+1; + + // std::cout<<"Number of children "<GetNumberOfChildren()<GetLabel() - // <<"','"<GetType(); - - std::string table = SQLiteTreeHandlerStructure::Table(type); - std::string where = "WHERE "; - - if (type!=Node::Patient) - { - where += "PARENT_ID='" + parent_id - //node->GetFieldValue("PARENT_ID") - + "' AND "; - } - for (int i=0;iGetLevel()>0 ) + child->SetAttribute("PARENT_ID",parent->GetAttribute("ID")); - // std::cout << " - Node exists " << std::endl; - std::string id = q.getStringField(0); - // std::cout << " id = '"<GetLabel()<< + "' "<SetAttribute(key,value); + std::string sql = "UPDATE "; + sql += GetTree().GetLevelDescriptor(n->GetLevel()).GetName(); + sql += " SET "; + sql += key; + sql += " = '"; + sql += value; + sql += "' WHERE ID = '"; + sql += n->GetAttribute("ID"); + sql +="'"; + // sql += " LIMIT 1"; + UPDATEDB(sql); + return true; } - //===================================================================== - //===================================================================== - bool SQLiteTreeHandler::Remove(Node* node) + //===================================================================== + /// Sets an attribute of a Node + void SQLiteTreeHandler::DBSetAttribute(const std::string& levelDescriptor, + const std::string& key, + const std::string& value, + const std::string& searchParam, + const std::string& searchVal) { - DBRecursiveRemoveNode(node); - - // std::cout << "DELETE"<GetParent()) - { - node->GetParent()->RemoveChildrenFromList(node); - } - delete node; - // std::cout << "DELETE OK"<GetLabel()<<"')"<GetType()); - query += " WHERE ID='"+ node->GetFieldValue("ID") + "';"; + + query += GetTree().GetLevelDescriptor(node->GetLevel()).GetName(); + query += " WHERE ID='"+ node->GetAttribute("ID") + "';"; UPDATEDB(query); - - Node::ChildrenListType::iterator i; - for (i = node->GetChildrenList().begin(); - i != node->GetChildrenList().end(); - i++) - { - DBRecursiveRemoveNode((*i)); - } + GimmickDebugMessage(2, + " Deleting '" + <GetLabel()<<"' with ID '" + <GetAttribute("ID") + <<"' in level "<< GetTree().GetLevelDescriptor(node->GetLevel()).GetName() + <GetNumberOfChildren()!=0) + { + Node::ChildrenListType::iterator i; + for (i = node->GetChildrenList().begin(); + i != node->GetChildrenList().end(); + i++) + { + DBRecursiveRemoveNode((*i)); + } + } + else if(node->GetLevel()GetLevel()+1,node->GetAttribute("ID")); + } } + //===================================================================== - - //===================================================================== - int SQLiteTreeHandler::DBQueryNumberOfChildren(Node* node) + void SQLiteTreeHandler::DBRecursiveRemoveNode(int level, std::string parentId) { - std::string query = "SELECT COUNT (ID) FROM "; - query += SQLiteTreeHandlerStructure::Table(node->GetType()+1); - if (node->GetType() != Node::Database) - { - query += " WHERE PARENT_ID='"+ node->GetFieldValue("ID")+"'"; - } - query += ";"; - - // std::cout << "**SQL = "<< query << std::endl; + std::stringstream out; + std::stringstream result; + out<<"SELECT ID FROM "<GetLevel(); + + if(level0) { - if (str[i]==0) + std::string query = "SELECT NumberOfChildren FROM "; + query += GetTree().GetLevelDescriptor(level).GetName(); + if (level>0) { - str = str.substr(0,i); - break; + query += " WHERE ID='" + n->GetAttribute("ID") + + "'"; + } + CppSQLite3Query q; + QUERYDB(query,q); + + + while (!q.eof()) + { + for (int fld = 0; fld < q.numFields(); fld++) + { + nb=q.getIntField(fld); + } + q.nextRow(); } } - // if (iGetLabel()<<"')"<GetFieldValueMap().begin(); - i != n->GetFieldValueMap().end(); - i++) - { - if (i->first=="ID") + while(level>1) { - continue; + std::stringstream out; + std::stringstream results; + out<<"SELECT PARENT_ID FROM "<first<<","<second<<")"<first + "'"; - values += "'" + format_sql2(i->second) + "'"; - atts += ","; - values += ","; - } - atts[atts.size()-1]=' '; - values[values.size()-1]=' '; - - str = "("+atts+") VALUES ("+values+")"; + parent_id=sv; } - //===================================================================== -*/ - + //===================================================================== + void SQLiteTreeHandler::RemoveEntries(const std::string i_table, + const std::string i_attribute, + const std::string i_operand, + const std::string i_val) + { + std::stringstream query; + query<<"DELETE FROM "<