#include #include #include "CppSQLite3.h" #include //#include //#include //#include #include #include "wx/wx.h" #include #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; 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()+1; level < GetTree().GetNumberOfLevels(); level++) { // Create Node parent = new tree::Node(parent,attr); // Insert into DB 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 -1; } //===================================================================== //===================================================================== bool SQLiteTreeHandler::Remove(tree::Node*) { return false; } //===================================================================== //===================================================================== // SQLite DB specific methods //===================================================================== //===================================================================== 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 '"<open(GetFileName().c_str()); } catch (CppSQLite3Exception& e) { std::cerr << "Opening '"<open(GetFileName().c_str()); } catch (CppSQLite3Exception& e) { creaMessage("Gimmick!",1, "[Gimmick!] !! ERROR '" << 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"; } AppendAttributesSQLDefinition(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().GetAttributeDescriptorList(l).push_back (AttributeDescriptor( "ID", "Database Identifier", 0,0, AttributeDescriptor::PRIVATE )); if (l>1) { // Add Attribute 'PARENT_ID' to Description GetTree().GetAttributeDescriptorList(l).push_back (AttributeDescriptor( "PARENT_ID", "Database Parent Identifier", 0,0, AttributeDescriptor::PRIVATE )); } } // 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()); } } } catch (std::exception) { return false; } 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 '"<GetChildrenList().begin(); i!= parent->GetChildrenList().end(); ++i) { if ( (*i)->Matches( attr ) ) { go_down = true; parent = *i; } } } while (go_down); return parent; } //===================================================================== //===================================================================== int SQLiteTreeHandler::DBLoadChildren(tree::Node* parent, int numberoflevels) { int nbloaded = 0; if (parent->GetChildrenLoaded()) return nbloaded; // Query DB int level = parent->GetLevel(); std::string query = "SELECT * FROM "; query += GetTree().GetLevelDescriptor(level+1).GetName(); if (level>1) { query += " WHERE PARENT_ID='" + parent->UnsafeGetAttribute("ID") + "'"; } CppSQLite3Query q; QUERYDB(query,q); while (!q.eof()) { nbloaded++; Node* n = new Node(parent); for (int fld = 0; fld < q.numFields(); fld++) { n->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(); } parent->SetChildrenLoaded(true); // msw[2].Pause(); return nbloaded; // std::cout << "SQLiteTreeHandler::DBLoadChildren("<ChildrenLoaded() ) { // 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 ) { msw[2].Pause(); nbloaded += DBLoadChildren(n,maxlevel); msw[2].Resume(); } // next entry in db q.nextRow(); } xparent->SetChildrenLoaded(true); // msw[2].Pause(); return nbloaded; */ } //===================================================================== /* //===================================================================== 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) <GetLabel()<<"')"<GetFieldValueMap().begin(); i != n->GetFieldValueMap().end(); i++) { if (i->first=="ID") { continue; } // std::cout << "("<first<<","<second<<")"<first + "'"; values += "'" + format_sql2(i->second) + "'"; atts += ","; values += ","; } atts[atts.size()-1]=' '; values[values.size()-1]=' '; str = "("+atts+") VALUES ("+values+")"; } //===================================================================== */ } // namespace creaImageIO