#include #include #include "CppSQLite3.h" #include //#include //#include //#include #include #include "wx/wx.h" #include #include //#include #include using namespace crea; #include #include namespace creaImageIO { using namespace tree; //============================================================= SQLiteTreeHandler::SQLiteTreeHandler(const std::string& filename) : mFileName(filename) { mDB = new CppSQLite3DB; mIsAdding=false; GimmickMessage(1,"SQLite version : " <SQLiteVersion())<< std::endl); } //============================================================= //============================================================= SQLiteTreeHandler::~SQLiteTreeHandler() { delete mDB; } //============================================================= //============================================================= // void SQLiteTreeHandler::Print() const // { /* std::cout << "-> '"<Print(); } */ // } //============================================================= //===================================================================== /* bool SQLiteTreeHandler::LocationIsValid() { // TO DO return true; } */ //===================================================================== //===================================================================== bool SQLiteTreeHandler::Open(bool writable) { // std::cout << "***> SQLiteTreeHandler::Open('"< SQLiteTreeHandler::New('"<GetLevel()<GetLevel()+1); } //===================================================================== //===================================================================== bool SQLiteTreeHandler::Remove(tree::Node* node) { DBRecursiveRemoveNode(node); // std::cout << "DELETE"<GetParent()) { node->GetParent()->RemoveChildrenFromList(node); } delete node; // std::cout << "DELETE OK"<execQuery(QUER.c_str()); \ } \ catch (CppSQLite3Exception& e) \ { \ GimmickError("SQLite query '"<execDML(UP.c_str()); \ } \ catch (CppSQLite3Exception& e) \ { \ GimmickError("SQLite update '"<open(GetFileName().c_str()); } catch (CppSQLite3Exception& e) { GimmickError("Opening '"<open(GetFileName().c_str()); } catch (CppSQLite3Exception& e) { GimmickError(e.errorCode() << ":" << e.errorMessage() <0, i.e. not Root) if (l>=0) { command = "CREATE TABLE "; command += GetTree().GetLevelDescriptor(l).GetName(); 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 table *_ATTRIBUTES command = "CREATE TABLE "; command += GetTree().GetLevelDescriptor(l).GetName(); command += "_Attributes\n(\n"; command += "Key text,\n"; command += "Name text,\n"; command += "DicomGroup int,\n"; command += "DicomElement int,\n"; command += "Flags int\n"; command += "\n)"; UPDATEDB(command); // Fill the table *_ATTRIBUTES LevelDescriptor::AttributeDescriptorListType::const_iterator i; for (i = GetTree().GetAttributeDescriptorList(l).begin(); i != GetTree().GetAttributeDescriptorList(l).end(); ++i) { std::stringstream insert; insert << "INSERT INTO " << GetTree().GetLevelDescriptor(l).GetName() << "_Attributes (Key,Name,DicomGroup,DicomElement,Flags) " << "VALUES ('" << i->GetKey() << "','" << i->GetName() << "'," << 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 from database ..." <tableExists("LEVELS") ) { GimmickMessage(1,"!! ERROR : Table 'LEVELS' does not exist" <tableExists(table.c_str()) ) { GimmickMessage(1,"!! ERROR : Table '"<GetKey()); if ( i != attr.end() ) { v = i->second; } */ GetTree().UnsafeSetAttribute( a->GetKey(), "" ); } // Reading Root attributes // Query DB query = "SELECT * FROM "; query += GetTree().GetLevelDescriptor(0).GetName(); QUERYDB(query,q); for (int fld = 0; fld < q.numFields(); fld++) { GetTree().UnsafeSetAttribute(q.fieldName(fld), q.getStringField(fld)); } GimmickMessage(1,"Importing tree description from database ... OK" <GetAttributeMap().begin(); i != n->GetAttributeMap().end(); i++) { if (i->first=="ID") { continue; } // std::cout << "("<first<<","<second<<")"<first + "'"; values += "'" + SQLformat(i->second) + "'"; atts += ","; values += ","; GimmickMessage(4,"'"<first<<"' = '"<second<<"'"<GetChildrenList().begin(); i!= parent->GetChildrenList().end(); ++i) { if ( (*i)->Matches( attr ) ) { go_down = true; parent = *i; break; } } } while (go_down); return parent; } //===================================================================== //===================================================================== int SQLiteTreeHandler::DBLoadChildren(tree::Node* node, int numberoflevels) { if (node->GetLevel()+1 >= node->GetTree()->GetNumberOfLevels() ) return 0; GimmickMessage(2,"Loading children of '"<GetLabel() <<"'"<GetChildrenLoaded()||mIsAdding) { // Iterate the children tree::Node::ChildrenListType::iterator i; for (i = node->GetChildrenList().begin(); i!= node->GetChildrenList().end(); ++i) { nbloaded += DBLoadChildren(*i,numberoflevels-1); } node->SetChildrenLoaded(true); return nbloaded; } 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) { query += " WHERE PARENT_ID='" + node->UnsafeGetAttribute("ID") + "'"; } CppSQLite3Query q; QUERYDB(query,q); int p=0; while (!q.eof()) { // std::cout << "DBLoadCh : creating node level "<UnsafeSetAttribute(q.fieldName(fld),q.getStringField(fld)); } /* // Index TypeId ti; ti.type = type; ti.id = n->GetFieldValue("ID"); mTypeIdToNodeMap[ti] = n; */ // recurse if ( numberoflevels != 1 ) { // msw[2].Pause(); nbloaded += DBLoadChildren(n, numberoflevels-1); // msw[2].Resume(); } // next entry in db q.nextRow(); } node->SetChildrenLoaded(true); // msw[2].Pause(); return nbloaded; } } //===================================================================== //====================================================================== void SQLiteTreeHandler::DBInsert(tree::Node* n) { GimmickMessage(2,"Inserting in DB '"<GetLabel() <<"'"<GetLevel()).GetName(); insert += " " + val + ";"; UPDATEDB(insert); // Store DB id of newly created node; long lastrow = mDB->lastRowId(); std::stringstream ri; ri << mDB->lastRowId(); n->SetAttribute("ID",ri.str()); } //====================================================================== //====================================================================== /// Graft the branch defined by the attributes to the parent void SQLiteTreeHandler::DBGraftToParent( tree::Node* parent, const AttributeMapType& attr) { // std::cout <<"Grafting to parent '"<GetLabel() // <<"'"<GetLevel()+1; level < GetTree().GetNumberOfLevels(); level++) { // Create Node tree::Node* child = new tree::Node(parent,attr); child->SetChildrenLoaded(true); // std::cout<<"Number of children "<GetNumberOfChildren()<GetLevel()>0 ) child->SetAttribute("PARENT_ID",parent->GetAttribute("ID")); // Insert in DB DBInsert(child); /* std::string val; SQLAppendAttributesValues(child,val); std::string insert("INSERT INTO "); insert += GetTree().GetLevelDescriptor(child->GetLevel()).GetName(); insert += " " + val + ";"; UPDATEDB(insert); // Store DB id of newly created node; long lastrow = mDB->lastRowId(); std::stringstream ri; ri << mDB->lastRowId(); child->SetAttribute("ID",ri.str()); */ // Down one level parent = child; /* // 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++; */ } } //====================================================================== //===================================================================== /// Sets an attribute of a Node bool SQLiteTreeHandler::DBSetAttribute(tree::Node* n, const std::string& key, const std::string& value) { GimmickMessage(3,"Setting Attribute of '"<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 += " LIMIT 1"; UPDATEDB(sql); } //===================================================================== //===================================================================== void SQLiteTreeHandler::DBRecursiveRemoveNode(Node* node) { std::string query = "DELETE FROM "; query += GetTree().GetLevelDescriptor(node->GetLevel()).GetName(); query += " WHERE ID='"+ node->GetAttribute("ID") + "';"; UPDATEDB(query); GimmickDebugMessage(2, " Deleting '" <GetLabel()<<"' with ID '" <GetAttribute("ID") <<"' in level "<< GetTree().GetLevelDescriptor(node->GetLevel()).GetName() <GetChildrenList().begin(); i != node->GetChildrenList().end(); i++) { DBRecursiveRemoveNode((*i)); } } //===================================================================== unsigned int SQLiteTreeHandler::GetNumberOfChildren(tree::Node* n) { // Query DB int nb=0; int level = n->GetLevel(); if(GetTree().GetNumberOfLevels()!=(level+1)) { std::string query = "SELECT * FROM "; query += GetTree().GetLevelDescriptor(level+1).GetName(); if (level>0) { query += " WHERE PARENT_ID='" + n->UnsafeGetAttribute("ID") + "'"; } CppSQLite3Query q; QUERYDB(query,q); while (!q.eof()) { nb++; q.nextRow(); } } return nb; } /* //===================================================================== bool SQLiteTreeHandler::DBInsert(Node* alien_node, UpdateSummary& summary) { // std::cout << "SQLiteTreeHandler::Insert('"<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; } return parent; } //===================================================================== //===================================================================== void SQLiteTreeHandler::DBRecursiveGetOrCreateNode(Node* alien_node, Node* parent, const std::string& parent_id, UpdateSummary& summary) { // std::cout << "SQLiteTreeHandler::RecursiveGetOrCreateNode('" // <GetLabel() // <<"','"<GetChildrenList().begin(); i != alien_node->GetChildrenList().end(); i++) { DBRecursiveGetOrCreateNode((*i),new_node,new_id,summary); } } //===================================================================== //===================================================================== Node* SQLiteTreeHandler::DBGetOrCreateNode(Node* alien_node, Node* internal_parent, std::string parent_id, std::string& node_id, UpdateSummary& summary) { // std::cout << "DBGetOrCreateNode('"<GetLabel()<<"','" // << internal_parent << "','"<< parent_id<<"')"<0) { node_id = node->UnsafeGetFieldValue("ID"); return node; } // 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++) { j = alien_node->GetFieldValueMap().find(i->first); if (j != alien_node->GetFieldValueMap().end() ) { i->second = j->second; } } msw[2].Resume(); if (node->GetType()!=Node::Patient) node->SetFieldValue("PARENT_ID",parent_id); // Insert in DB std::string val; BuildSQLFieldsValues(node,val); std::string insert("INSERT INTO "); insert += std::string(SQLiteTreeHandlerStructure::Table(node->GetType())) + " " + val + ";"; // std::cout << "** SQL = '"<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; } //===================================================================== //===================================================================== Node* SQLiteTreeHandler::GetChildrenLike(Node* parent, Node* alien_node) { Node::ChildrenListType::iterator i; for (i = parent->GetChildrenList().begin(); i != parent->GetChildrenList().end(); i++) { 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) { return (*i); } } return 0; } //===================================================================== //===================================================================== std::string SQLiteTreeHandler::DBGetNodeId(Node* node, const std::string& parent_id) { // std::cout << "SQLiteTreeHandler::DBGetNodeId('"<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;iGetParent()) { node->GetParent()->RemoveChildrenFromList(node); } delete node; // std::cout << "DELETE OK"<GetLabel()<<"')"<GetType()); query += " WHERE ID='"+ node->GetFieldValue("ID") + "';"; UPDATEDB(query); Node::ChildrenListType::iterator i; for (i = node->GetChildrenList().begin(); i != node->GetChildrenList().end(); i++) { DBRecursiveRemoveNode((*i)); } } //===================================================================== //===================================================================== int SQLiteTreeHandler::DBQueryNumberOfChildren(Node* node) { 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; CppSQLite3Query q; QUERYDB(query,q); // std::cout << "**RES = "<< q.getIntField(0) <