//=============================================================
- //=============================================================
- 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
// {
*/
//=====================================================================
- //=====================================================================
- 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: '"<<QUER<<"'"<<std::endl); \
- RES = mDB->execQuery(QUER.c_str()); \
- } \
- catch (CppSQLite3Exception& e) \
- { \
- std::cout << "SQLite query '"<<QUER<<"' : " \
- << e.errorCode() << ":" \
- << e.errorMessage()<<std::endl; \
- creaError("SQLite query '"<<QUER<<"' : " \
- << e.errorCode() << ":" \
- << e.errorMessage() ); \
- } \
-
- //=====================================================================
-
- //=====================================================================
-#define UPDATEDB(UP) \
- try \
- { \
- GimmickMessage(2,"SQL: '"<<UP<<"'"<<std::endl); \
- mDB->execDML(UP.c_str()); \
- } \
- catch (CppSQLite3Exception& e) \
- { \
- std::cout << "SQLite update '"<<UP<<"' Error : " \
- << e.errorCode() << ":" \
- << e.errorMessage()<<std::endl; \
- creaError("SQLite update '"<<UP<<"' Error : " \
- << e.errorCode() << ":" \
- << e.errorMessage() ); \
- }
- //=====================================================================
//=====================================================================
bool SQLiteTreeHandler::Open(bool writable)
//=====================================================================
bool SQLiteTreeHandler::Close()
{
- return false;
+ return true;
}
//=====================================================================
//=====================================================================
- int SQLiteTreeHandler::AddBranch( const std::map<std::string,std::string>& attr )
+ int SQLiteTreeHandler::AddBranch( const AttributeMapType& attr )
{
+ tree::Node* parent = DBGetParent(attr);
+ for (int level = parent->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 = '"<<insert<<"'"<<std::endl;
+ UPDATEDB(insert);
+ // std::cout << "** SQL OK"<<std::endl;
+
+ // Store DB id of newly created node;
+ long lastrow = mDB->lastRowId();
+ std::stringstream ri;
+ ri << mDB->lastRowId();
+ node_id = ri.str();
+ // std::cout << "LastRowId='"<<mDB->lastRowId()<<"' vs '"<<created_id<<"'"<<std::endl;
+
+ node->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 ("<<ti.type<<","<<ti.id<<")"<<std::endl;
+ //
+ msw[2].Pause();
+
+ if (node->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;
}
//=====================================================================
+
+
+
+
+
+
+
+
+ //=====================================================================
+ // 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: '"<<QUER<<"'"<<std::endl); \
+ RES = mDB->execQuery(QUER.c_str()); \
+ } \
+ catch (CppSQLite3Exception& e) \
+ { \
+ std::cout << "SQLite query '"<<QUER<<"' : " \
+ << e.errorCode() << ":" \
+ << e.errorMessage()<<std::endl; \
+ creaError("SQLite query '"<<QUER<<"' : " \
+ << e.errorCode() << ":" \
+ << e.errorMessage() ); \
+ } \
+
+ //=====================================================================
+
+ //=====================================================================
+#define UPDATEDB(UP) \
+ try \
+ { \
+ GimmickMessage(2,"SQL: '"<<UP<<"'"<<std::endl); \
+ mDB->execDML(UP.c_str()); \
+ } \
+ catch (CppSQLite3Exception& e) \
+ { \
+ std::cout << "SQLite update '"<<UP<<"' Error : " \
+ << e.errorCode() << ":" \
+ << e.errorMessage()<<std::endl; \
+ creaError("SQLite update '"<<UP<<"' Error : " \
+ << e.errorCode() << ":" \
+ << e.errorMessage() ); \
+ }
+ //=====================================================================
+
+
//=====================================================================
bool SQLiteTreeHandler::DBOpen()
{
- GimmickMessage(2,"Opening SQLite database '"<<GetFileName()<<std::endl);
+ GimmickMessage(1,"Opening SQLite database '"<<GetFileName()
+ <<"' ... "<<std::endl);
// OPENING FILE
if (!boost::filesystem::exists(GetFileName()))
{
<< e.errorMessage() << std::endl;
return false;
}
- // TESTING STRUCTURE VALIDITY
- if (!DBStructureIsValid())
+ // IMPORT TREE DESCRIPTION (AND TEST DB VALIDITY)
+ if (!DBImportTreeDescription())
{
- std::cerr << "Opening '"<<GetFileName()<<"' : "
- << " invalid database structure" << std::endl;
return false;
}
- // IMPORTING NODE TYPE DESCRIPTIONS
- DBImportTreeDescription();
+
+ GimmickMessage(1,"Opening SQLite database '"<<GetFileName()
+ <<"' ... OK"<<std::endl);
return true;
}
//=====================================================================
//=====================================================================
bool SQLiteTreeHandler::DBCreate()
{
- // std::cout << "### Creating SQLite database '"<<GetFileName()<<std::endl;
+ GimmickMessage(1,"Creating SQLite database '"<<GetFileName()
+ <<"' ... "<<std::endl);
if (boost::filesystem::exists(GetFileName()))
{
command += "( Name text )\n";
UPDATEDB(command);
- // Level 0
- command = "INSERT INTO Levels (Name) VALUES ('";
- command += GetTree().GetLevelDescriptor(0).GetName();
- command += "')";
- UPDATEDB(command);
-
- command = "CREATE TABLE ";
- command += GetTree().GetLevelDescriptor(0).GetName();
- command += "\n(\nID INTEGER PRIMARY KEY";
- AppendAttributesSQLDefinition(0,command);
- command += "\n)";
- UPDATEDB(command);
-
- // Iterate the other Levels
- for (int l=1; l<GetTree().GetNumberOfLevels(); ++l)
+ // Iterate the Levels
+ for (int l=0; l<GetTree().GetNumberOfLevels(); ++l)
{
command = "INSERT INTO LEVELS (Name) VALUES ('";
command += GetTree().GetLevelDescriptor(l).GetName();
command += "')";
UPDATEDB(command);
+ // Create table of level (for level>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 += "\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 += "_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());
+ }
}
-
- // Create tables *_ATTRIBUTES
- // and fill the tables *_ATTRIBUTES
- DBExportTreeDescription();
-
}
catch (std::exception)
{
return false;
}
- // LG : TEST
- if (DBStructureIsValid())
- {
- // std::cout << "*** DONE ***"<<std::endl;
- // mDBLoaded = true;
- GetTree().SetChildrenLoaded(true);
- return true;
-
- }
- else
- {
- // std::cout << "*** AAAARRRRGGG ***"<<std::endl;
-
- return false;
- }
+
+ GetTree().SetChildrenLoaded(true);
+ GimmickMessage(1,"Creating SQLite database '"<<GetFileName()
+ <<"' ... OK"<<std::endl);
+ return true;
}
//=====================================================================
}
//=====================================================================
- //=====================================================================
- void SQLiteTreeHandler::DBExportTreeDescription()
- {
- for (int level=0; level<GetTree().GetNumberOfLevels(); ++level)
- {
- std::string command;
- command = "CREATE TABLE ";
- command += GetTree().GetLevelDescriptor(level).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);
-
- LevelDescriptor::AttributeDescriptorListType::const_iterator i;
- for (i = GetTree().GetAttributeDescriptorList(level).begin();
- i != GetTree().GetAttributeDescriptorList(level).end();
- ++i)
- {
-
- std::stringstream insert;
- insert << "INSERT INTO "
- << GetTree().GetLevelDescriptor(level).GetName()
- << "_Attributes (Key,Name,DicomGroup,DicomElement,Flags) "
- << "VALUES ('"
- << i->GetKey() << "','"
- << i->GetName() << "',"
- << i->GetGroup() << ","
- << i->GetElement() << ","
- << i->GetFlags() << ");";
-
- UPDATEDB(insert.str());
- }
- }
-
- }
- //=====================================================================
//=====================================================================
- void SQLiteTreeHandler::DBImportTreeDescription()
+ bool SQLiteTreeHandler::DBImportTreeDescription()
{
- GimmickMessage(3,"ImportTreeDescription"<<std::endl);
-
- // tree::Description& desc = GetTree().GetDescription();
- /*
+ GimmickMessage(1,"Importing tree description from database ..."
+ <<std::endl);
- for (Node::Type type=Node::Patient;
- type<=Node::Image;
- type++)
+ // Test table 'LEVELS' existence
+ if ( ! mDB->tableExists("LEVELS") )
{
- std::string query = "SELECT * FROM ";
- query += SQLiteTreeHandlerStructure::Table(type);
- query += "_FIELDS";
+ GimmickMessage(1,"!! ERROR : Table 'LEVELS' does not exist"
+ <<std::endl);
+ return false;
+ }
- // std::cout << "** SQL = '"<<query<<"'"<<std::endl;
+ tree::Descriptor& desc = GetTree().GetDescriptor();
+ // clears the existing one
+ desc.GetLevelDescriptorList().clear();
+
+ int nblevel = 0;
+ std::string query = "SELECT * FROM LEVELS";
+ CppSQLite3Query q;
+ QUERYDB(query,q);
+
+ while (!q.eof())
+ {
+ std::string name = q.getStringField(0);
+ GimmickMessage(2," * Importing level '"<<name<<"'"<<std::endl);
+ desc.GetLevelDescriptorList().push_back(LevelDescriptor(name));
+ nblevel++;
+ q.nextRow();
+ }
+
+ for (int level = 0; level < nblevel; ++level )
+ {
+ std::string table = GetTree().GetLevelDescriptor(level).GetName();
+ table += "_Attributes";
+ // Test table 'LEVELS' existence
+ if ( ! mDB->tableExists(table.c_str()) )
+ {
+ GimmickMessage(1,"!! ERROR : Table '"<<table<<"' does not exist"
+ <<std::endl);
+ return false;
+ }
+ std::string query = "SELECT * FROM ";
+ query += table;
CppSQLite3Query q;
QUERYDB(query,q);
+ GimmickMessage(2," * Level '"
+ <<GetTree().GetLevelDescriptor(level).GetName()
+ <<"'"<<std::endl);
+
+ // Test that ID and PARENT_ID mandatory attributes exist
+ bool ID_found = false;
+ bool PARENT_ID_found = false;
+ if (level==0) ID_found = true;
+ if (level<=1) PARENT_ID_found = true;
while (!q.eof())
{
- Field::Description d(q.getStringField(0), // Key
- q.getIntField(1), // Group
- q.getIntField(2), // Element
- q.getStringField(3), // Name
- q.getIntField(4) // Flags
- );
- GetNodeTypeDescription(type).GetFieldDescriptionMap()[d.key] = d;
- // std::cout << d << std::endl;
+ std::string key(q.getStringField(0));
+ std::string name(q.getStringField(1));
+ GimmickMessage(2," - Importing attribute '"<<key<<"' '"<<name
+ <<"'"<<std::endl);
+ desc.GetAttributeDescriptorList(level).push_back
+ (AttributeDescriptor( key, // Key
+ name, // Name
+ q.getIntField(2), // Group
+ q.getIntField(3), // Element
+ q.getIntField(4) // Flags
+ ));
+ if ( key == "ID" )
+ {
+ ID_found = true;
+ }
+ if ( key == "PARENT_ID" )
+ {
+ PARENT_ID_found = true;
+ }
q.nextRow();
}
+
+ if ( ! (ID_found || PARENT_ID_found ) )
+ {
+ GimmickMessage(1,"!! ERROR : Table '"<<table
+ <<"' does not contain mandatory attribute ID or PARENT_ID"
+ <<std::endl);
+ return false;
+
+ }
}
- */
+
+ GimmickMessage(1,"Importing tree description from database ... OK"
+ <<std::endl);
+ return true;
}
//=====================================================================
- //=====================================================================
- bool SQLiteTreeHandler::DBStructureIsValid()
+
+
+
+
+
+
+
+
+
+
+
+
+
+ //=====================================================================
+ tree::Node* SQLiteTreeHandler::DBGetParent( const AttributeMapType& attr)
{
- bool success = true;
+ 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;
+ }
+ }
+ }
+ while (go_down);
+ return parent;
+ }
+ //=====================================================================
- // TO DO : TABLE WHICH STORES THE LEVELS
- /*
-
- for (int i = SQLiteTreeHandlerStructure::TableBegin();
- i != SQLiteTreeHandlerStructure::TableEnd();++i)
+
+ //=====================================================================
+ 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)
{
- bool ok = mDB->tableExists(SQLiteTreeHandlerStructure::Table(i));
- if (ok)
+ 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++)
{
- // std::cout << "** Table "<<SQLiteTreeHandlerStructure::Table(i)
- // <<" exists"<<std::endl;
- // TO DO : TEST MANDATORY FIELDS EXIST
+ n->UnsafeSetAttribute(q.fieldName(fld),q.getStringField(fld));
}
- else
+ /*
+ // Index
+ TypeId ti;
+ ti.type = type;
+ ti.id = n->GetFieldValue("ID");
+ mTypeIdToNodeMap[ti] = n;
+ */
+ // recurse
+ if ( numberoflevels > 1 )
{
- // std::cout << "** Table "<<SQLiteTreeHandlerStructure::Table(i)
- // <<" does *NOT* exist"<<std::endl;
- success = false;
+ // msw[2].Pause();
+ nbloaded += DBLoadChildren(n, numberoflevels-1);
+ // msw[2].Resume();
}
+ // next entry in db
+ q.nextRow();
}
- */
- return success;
- }
- //=====================================================================
- /*
- //=====================================================================
- int SQLiteTreeHandler::DBLoadChildren(Node* parent,
- int maxlevel)
- {
+ parent->SetChildrenLoaded(true);
+
+ // msw[2].Pause();
+ return nbloaded;
// std::cout << "SQLiteTreeHandler::DBLoadChildren("<<parent<<","<<maxlevel
- // << ")"<<std::endl;
+ // << ")"<<std::endl;
+ /*
int nbloaded = 0;
if (parent == GetTree()) { parent = 0; }
Node* xparent = parent;
// msw[2].Pause();
return nbloaded;
+ */
}
//=====================================================================
-
+ /*
//=====================================================================
bool SQLiteTreeHandler::DBInsert(Node* alien_node,
UpdateSummary& summary)