/* # --------------------------------------------------------------------- # # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image # pour la Santé) # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton # Previous Authors : Laurent Guigues, Jean-Pierre Roux # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil # # This software is governed by the CeCILL-B license under French law and # abiding by the rules of distribution of free software. You can use, # modify and/ or redistribute the software under the terms of the CeCILL-B # license as circulated by CEA, CNRS and INRIA at the following URL # http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html # or in the file LICENSE.txt. # # As a counterpart to the access to the source code and rights to copy, # modify and redistribute granted by the license, users are provided only # with a limited warranty and the software's author, the holder of the # economic rights, and the successive licensors have only limited # liability. # # The fact that you are presently reading this means that you have had # knowledge of the CeCILL-B license and that you accept its terms. # ------------------------------------------------------------------------ */ #include #include #include #include "CppSQLite3.h" #include #include #include #include using namespace crea; 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; } //============================================================= //===================================================================== //===================================================================== bool SQLiteTreeHandler::Open(bool writable) { //sqlite3_exec(mDB, "PRAGMA synchronous=OFF ", NULL, 0, &errMsg); SetWritable(writable); return DBOpen(); } //===================================================================== bool SQLiteTreeHandler::Create(bool writable) { // std::cout << "***> SQLiteTreeHandler::New('"<execDML("PRAGMA synchronous=ON "); if (parent==0) parent = GetTree().GetTree(); return DBLoadChildren(parent,maxlevel); } //===================================================================== //===================================================================== void SQLiteTreeHandler::UnLoad(tree::Node* n) { } //===================================================================== //===================================================================== int SQLiteTreeHandler::AddBranch( const AttributeMapType& attr ) { tree::Node* parent = DBGetParent(attr); DBGraftToParent(parent,attr); return (parent->GetLevel()+1); } //===================================================================== //===================================================================== bool SQLiteTreeHandler::Remove(tree::Node* node) { 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 '"<open(GetFileName().c_str()); mDB->execDML("pragma synchronous=off;"); } catch (CppSQLite3Exception& e) { GimmickError("Opening '"<open(GetFileName().c_str()); } catch (CppSQLite3Exception& e) { GimmickError(e.errorCode() << ":" << e.errorMessage() <execDML("pragma synchronous=off;"); // CREATING TABLES std::string command; // Create LEVELS table command = "create table LEVELS\n"; command += "( Name text )\n"; UPDATEDB(command); int l; // Iterate the Levels for (l=0; l0, 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); GetTree().CopyAttributeDescriptorList(l); // 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 for database ..." <tableExists("LEVELS") ) { GimmickMessage(1,"!! ERROR : Table 'LEVELS' does not exist" <tableExists(table.c_str()) ) { GimmickMessage(1,"!! ERROR : Table '"<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; } atts += "'" + i->first + "'"; SQLformat(i->second, out); values += "'" + out + "'"; 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()) { // 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->GetAttribute("ID") + "'"; } GimmickDebugMessage(1, "query : '" <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(); } 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); if (level>1) { int nc = GetNumberOfChildren(parent)+1; // std::cout<<"Number of children "<GetNumberOfChildren()<GetLevel()>0 ) child->SetAttribute("PARENT_ID",parent->GetAttribute("ID")); // Insert in DB DBInsert(child); // Down one level parent = child; } } //====================================================================== //===================================================================== /// 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 += convert(value); sql += "' WHERE ID = '"; sql += n->GetAttribute("ID"); sql +="'"; // sql += " LIMIT 1"; UPDATEDB(sql); return true; } //===================================================================== /// 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) { std::string sql = "UPDATE "; sql += levelDescriptor; sql += " SET "; sql += key; sql += " = '"; sql += value; sql += "' WHERE "; sql += searchParam; sql += " = '"; sql += searchVal; sql += "'"; std::cout<GetLevel()).GetName(); query += " WHERE ID='"+ node->GetAttribute("ID") + "';"; UPDATEDB(query); if(node->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")); } } //===================================================================== void SQLiteTreeHandler::DBRecursiveRemoveNode(int level, std::string parentId) { std::stringstream out; std::stringstream result; out<<"SELECT ID FROM "<GetLevel(); if(level0) { std::string query = "SELECT NumberOfChildren FROM "; query += GetTree().GetLevelDescriptor(level).GetName(); if (level>0) { 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(nb==0) { nb=1; } */ return nb; } //===================================================================== // get all attributes from database for a given file void SQLiteTreeHandler::getAllAttributes(std::string i_filename, std::map &i_results) { int level=GetTree().GetNumberOfLevels()-1; std::string search = i_filename; std::string param = "FullFileName"; std::string name; std::string id; std::set pid; std::vector attr; std::vector::iterator it_attr; std::vector values; std::vector::iterator it_val; while(level>=1) { attr = GetTree().GetAttributeDescriptorList(level,1); name = GetTree().GetLevelDescriptor(level).GetName(); std::vector values; //EED 2018-04-13 GetUpLevelNodeId(level, param,search,id); if (level>1) { GetUpLevelNodeId(level, param,search,id); } GetAttributes(name, param,search,attr, values); for(it_attr = attr.begin(), it_val = values.begin(); it_attr != attr.end(); it_attr++, it_val++) { i_results[(*it_attr).GetKey()] = (*it_val).c_str(); } // for search = id; param = "ID"; level --; } // while level } //===================================================================== // get selected attributes from database for a given file void SQLiteTreeHandler::GetAttributes(std::string name, std::string i_id, std::string i_value, tree::LevelDescriptor::AttributeDescriptorListType i_attr, std::vector &i_results) { //SELECT t1.ArtistName,CDs.Title FROM Artists t1, CDs WHERE t1.ArtistID=CDs.ArtistID std::stringstream out; std::stringstream results; out<<"SELECT "; tree::LevelDescriptor::AttributeDescriptorListType::iterator it = i_attr.begin(); std::string query =""; for(; it != i_attr.end(); it++) { query += (*it).GetKey(); query +=" ,"; } query = query.substr(0, query.size()-1); out << query; out << "FROM "<1) { GetUpLevelNodeId(level, sp, sv, parent_id); level--; sp = "ID"; sv = parent_id; } ///* // std::stringstream out; // std::stringstream results; // out<<"SELECT PARENT_ID FROM "<