]> Creatis software - creaImageIO.git/blob - src2/creaImageIOSQLiteTreeHandler.cpp
4d0d49eae165825a158b77f9788857c54d07a3a1
[creaImageIO.git] / src2 / creaImageIOSQLiteTreeHandler.cpp
1 #include <creaImageIOSQLiteTreeHandler.h>
2 #include <creaImageIOSystem.h>
3
4 #include "CppSQLite3.h"
5
6 #include <sys/stat.h>
7
8 //#include <creaImageIOSQLiteTreeHandlerStructure.h>
9
10 //#include <creaImageIOUtilities.h>
11
12 //#include <icons/database.xpm>
13
14 #include <deque>
15
16 #include "wx/wx.h"
17 #include <wx/dir.h>
18 #include <wx/filename.h>
19
20
21 //#include <icons/close.xpm>
22
23 #include <creaWx.h>
24 #include <creaMessageManager.h>
25 using namespace crea;
26
27 #include <boost/filesystem.hpp>
28 #include <boost/algorithm/string/replace.hpp>
29
30 namespace creaImageIO
31 {
32   using namespace tree;
33
34
35   //=============================================================
36   SQLiteTreeHandler::SQLiteTreeHandler(const std::string& filename)
37     : mFileName(filename)
38   {
39     mDB = new CppSQLite3DB;
40     GimmickMessage(1,"SQLite version : "
41                    <<std::string(mDB->SQLiteVersion())<< std::endl);
42   }
43   //=============================================================
44
45   //=============================================================
46   SQLiteTreeHandler::~SQLiteTreeHandler()
47   {
48     delete mDB;
49   }
50   //=============================================================
51   
52
53   //=============================================================
54   void SQLiteTreeHandler::BuildDefaultTreeDescription()
55   {
56     /*
57     for (int i = Node::Patient;
58          i <= Node::Image; 
59          ++i)
60       {
61         mNodeTypeDescription[i].BuildDefault(i);
62       }
63     */
64
65     // TODO : GetTree().GetDescription().LoadXML(FILE);
66   }
67   //=============================================================
68
69   //=============================================================
70   //  void SQLiteTreeHandler::Print() const 
71   //  {
72     /*
73     std::cout << "-> '"<<GetName()<< "' - '"
74               << GetFileName()<<"'"<<std::endl;
75     ChildrenListType::const_iterator i;
76     for (i=GetChildrenList().begin(); i!=GetChildrenList().end(); i++)
77       {
78         (*i)->Print();
79       }
80     */
81   //  }
82   //=============================================================
83   
84   //=====================================================================
85   /*
86   bool SQLiteTreeHandler::LocationIsValid()
87   {
88     // TO DO 
89     return true;
90   }
91   */
92   //=====================================================================
93
94   //=====================================================================
95   char* format_sql(const std::string& s)
96   { 
97     return sqlite3_mprintf("%q",s.c_str());
98   }
99   //=====================================================================
100
101   //  sqlite3_exec(db, zSQL, 0, 0, 0);
102   //  sqlite3_free(zSQL);
103   //    char* CHAIN = format_sql(QUER);         \
104 //  sqlite3_free(CHAIN);                                \
105
106   //=====================================================================
107 #define QUERYDB(QUER,RES)                                               \
108     try                                                                 \
109       {                                                                 \
110         GimmickMessage(2,"SQL: '"<<QUER<<"'"<<std::endl);               \
111         RES = mDB->execQuery(QUER.c_str());                             \
112       }                                                                 \
113     catch (CppSQLite3Exception& e)                                      \
114       {                                                                 \
115         std::cout << "SQLite query '"<<QUER<<"' : "                     \
116                   << e.errorCode() << ":"                               \
117                   << e.errorMessage()<<std::endl;                       \
118         creaError("SQLite query '"<<QUER<<"' : "                        \
119                   << e.errorCode() << ":"                               \
120                   << e.errorMessage() );                                \
121       }                                                                 \
122     
123   //=====================================================================
124   
125   //=====================================================================
126 #define UPDATEDB(UP)                                                    \
127   try                                                                   \
128     {                                                                   \
129       GimmickMessage(2,"SQL: '"<<UP<<"'"<<std::endl);                   \
130       mDB->execDML(UP.c_str());                                         \
131     }                                                                   \
132   catch (CppSQLite3Exception& e)                                        \
133     {                                                                   \
134       std::cout << "SQLite update '"<<UP<<"' Error : "                  \
135                 << e.errorCode() << ":"                                 \
136                 << e.errorMessage()<<std::endl;                         \
137       creaError("SQLite update '"<<UP<<"' Error : "                     \
138                 << e.errorCode() << ":"                                 \
139                 << e.errorMessage() );                                  \
140     }                                                                   
141   //=====================================================================
142
143   //=====================================================================
144   bool SQLiteTreeHandler::Open(bool writable)
145   {
146     //    std::cout << "***> SQLiteTreeHandler::Open('"<<GetFileName()<<"')"<<std::endl;
147     SetWritable(writable);
148     return DBOpen();
149   }
150
151   //=====================================================================
152   bool SQLiteTreeHandler::Create(bool writable)
153   {
154     //    std::cout << "***> SQLiteTreeHandler::New('"<<GetFileName()<<"')"<<std::endl;
155     SetWritable(writable);
156     return DBCreate();
157   }
158   //=====================================================================
159
160
161   //=====================================================================
162   bool SQLiteTreeHandler::Close()
163   {
164     return false;
165   }
166   //=====================================================================
167
168
169   //=====================================================================
170   bool SQLiteTreeHandler::Destroy()
171   {
172     return false;
173   }
174   //=====================================================================
175
176   //===================================================================== 
177   unsigned int SQLiteTreeHandler::GetNumberOfChildren(tree::Node* n) 
178   { 
179     return 0; 
180   }
181   //===================================================================== 
182
183   //===================================================================== 
184   int SQLiteTreeHandler::LoadChildren(tree::Node* parent, int maxlevel)
185   {
186     return 0;
187   }
188   //===================================================================== 
189
190
191
192
193   //===================================================================== 
194   void SQLiteTreeHandler::UnLoad(tree::Node* n)
195   {
196   }
197   //===================================================================== 
198
199
200   //===================================================================== 
201   int SQLiteTreeHandler::AddBranch( const std::map<std::string,std::string>& attr )
202   {
203     return -1;
204   }
205   //===================================================================== 
206  
207
208   //===================================================================== 
209    bool SQLiteTreeHandler::Remove(tree::Node*)
210    {
211      return false;
212    }
213   //===================================================================== 
214
215
216
217
218
219
220
221   //=====================================================================
222   bool SQLiteTreeHandler::DBOpen()
223   {
224     GimmickMessage(2,"Opening SQLite database '"<<GetFileName()<<std::endl);
225     // OPENING FILE
226     if (!boost::filesystem::exists(GetFileName())) 
227       {
228         return false;
229       }
230
231     try
232       {
233         mDB->open(GetFileName().c_str());
234       }
235     catch (CppSQLite3Exception& e)
236       {
237         std::cerr << "Opening '"<<GetFileName()<<"' : "
238                   << e.errorCode() << ":" 
239                   << e.errorMessage() << std::endl;
240         return false;
241       }
242     // TESTING STRUCTURE VALIDITY
243     if (!DBStructureIsValid())
244       {
245         std::cerr << "Opening '"<<GetFileName()<<"' : "
246                   << " invalid database structure" << std::endl;
247         return false;
248       }
249     // IMPORTING NODE TYPE DESCRIPTIONS
250     DBImportTreeDescription();
251     return true;
252   }
253   //=====================================================================
254
255   //=====================================================================
256   bool SQLiteTreeHandler::DBCreate()
257   {
258     //    std::cout << "### Creating SQLite database '"<<GetFileName()<<std::endl;
259
260     if (boost::filesystem::exists(GetFileName())) 
261       {
262         creaMessage("Gimmick!",1,
263                     "[Gimmick!] !! ERROR '"<<GetFileName()<<"' : "
264                     << "file already exists"<<std::endl);
265         return false;
266       }
267     
268     // OPENING
269     try
270       {
271         mDB->open(GetFileName().c_str());
272       }
273     catch (CppSQLite3Exception& e)
274       {
275         creaMessage("Gimmick!",1,
276                     "[Gimmick!] !! ERROR '"
277                     << e.errorCode() << ":" 
278                     << e.errorMessage() <<std::endl);
279         return false;
280       }
281     
282     // CREATING TABLES
283     try
284       {
285         std::string command;
286         // Create LEVELS table
287         command = "create table LEVELS\n";
288         command += "( Name text )\n";
289         UPDATEDB(command);
290
291         // Level 0
292         command = "INSERT INTO Levels (Name) VALUES ('";
293         command += GetTree().GetLevelDescriptor(0).GetName();
294         command += "')";
295         UPDATEDB(command);
296
297         command = "CREATE TABLE ";
298         command += GetTree().GetLevelDescriptor(0).GetName();
299         command += "\n(\nID INTEGER PRIMARY KEY";
300         AppendAttributesSQLDefinition(0,command);
301         command += "\n)";
302         UPDATEDB(command);
303         
304         // Iterate the other Levels
305         for (int l=1; l<GetTree().GetNumberOfLevels(); ++l)
306           {
307             command = "INSERT INTO LEVELS (Name) VALUES ('";
308             command += GetTree().GetLevelDescriptor(l).GetName();
309             command += "')";
310             UPDATEDB(command);
311             
312             command = "CREATE TABLE ";
313             command += GetTree().GetLevelDescriptor(l).GetName();
314             command += "\n(\nID INTEGER PRIMARY KEY,\nPARENT_ID int not null";  
315             AppendAttributesSQLDefinition(l,command);
316             command +=",\n";
317             command +="constraint FK_PARENT foreign key (PARENT_ID) references PATIENT(ID) on delete restrict on update restrict\n)";
318             UPDATEDB(command);
319           }
320         
321         // Create tables *_ATTRIBUTES
322         // and fill the tables *_ATTRIBUTES
323         DBExportTreeDescription();
324         
325       }
326     catch (std::exception)
327       {
328         return false;
329       }
330     // LG : TEST
331     if (DBStructureIsValid())
332       {
333         //      std::cout << "*** DONE ***"<<std::endl;
334         //      mDBLoaded = true;
335         GetTree().SetChildrenLoaded(true);
336         return true;
337         
338       }
339     else 
340       {
341         //      std::cout << "*** AAAARRRRGGG ***"<<std::endl;
342         
343         return false;
344       }
345   }
346   //=====================================================================
347   
348   //=====================================================================
349   void SQLiteTreeHandler::AppendAttributesSQLDefinition(int level,
350                                                         std::string& s)
351   {
352     LevelDescriptor::AttributeDescriptorListType::const_iterator i;
353     for (i  = GetTree().GetAttributeDescriptorList(level).begin();
354          i != GetTree().GetAttributeDescriptorList(level).end();
355          ++i)
356       {
357         //      if (i->second.flags==1) continue;
358         s += ",\n";
359         s += i->GetKey();
360         s += " text";
361       }
362   }
363   //=====================================================================
364   
365   //=====================================================================
366   void SQLiteTreeHandler::DBExportTreeDescription()
367   {
368     for (int level=0; level<GetTree().GetNumberOfLevels(); ++level)
369       {
370         std::string command;
371         command = "CREATE TABLE ";
372         command += GetTree().GetLevelDescriptor(level).GetName();
373         command += "_Attributes\n(\n";
374         command += "Key text,\n";
375         command += "Name text,\n";          
376         command += "DicomGroup int,\n";
377         command += "DicomElement int,\n";           
378         command += "Flags int\n";           
379         command += "\n)";
380         UPDATEDB(command);
381  
382         LevelDescriptor::AttributeDescriptorListType::const_iterator i;
383         for (i  = GetTree().GetAttributeDescriptorList(level).begin();
384              i != GetTree().GetAttributeDescriptorList(level).end();
385              ++i)
386           {
387             
388             std::stringstream insert;
389             insert << "INSERT INTO "
390                    << GetTree().GetLevelDescriptor(level).GetName()
391                    << "_Attributes (Key,Name,DicomGroup,DicomElement,Flags) "
392                    << "VALUES ('"
393                    << i->GetKey() << "','"
394                    << i->GetName() << "',"
395                    << i->GetGroup() << ","
396                    << i->GetElement() << ","
397                    << i->GetFlags() << ");";
398
399             UPDATEDB(insert.str());
400           }
401       }
402     
403   }
404   //=====================================================================
405   
406   //=====================================================================
407   void SQLiteTreeHandler::DBImportTreeDescription()
408   {
409     GimmickMessage(3,"ImportTreeDescription"<<std::endl);
410     
411     //    tree::Description& desc = GetTree().GetDescription();
412     /*
413
414     for (Node::Type type=Node::Patient; 
415          type<=Node::Image; 
416          type++)
417       {
418         std::string query = "SELECT * FROM ";
419         query += SQLiteTreeHandlerStructure::Table(type);
420         query += "_FIELDS";
421
422         //      std::cout << "** SQL = '"<<query<<"'"<<std::endl;
423         
424         CppSQLite3Query q;
425         QUERYDB(query,q);
426         
427
428         while (!q.eof())
429           {
430             Field::Description d(q.getStringField(0), // Key
431                                  q.getIntField(1), // Group
432                                  q.getIntField(2), // Element 
433                                  q.getStringField(3), // Name
434                                  q.getIntField(4) // Flags
435                                  );
436             GetNodeTypeDescription(type).GetFieldDescriptionMap()[d.key] = d;
437             //      std::cout << d << std::endl;
438             q.nextRow();
439           }
440       }
441     */
442   }
443   //=====================================================================
444
445
446     //=====================================================================
447   bool SQLiteTreeHandler::DBStructureIsValid()
448   {
449     bool success = true;
450
451     // TO DO : TABLE WHICH STORES THE LEVELS
452     /*
453     
454     for (int i = SQLiteTreeHandlerStructure::TableBegin();
455          i    != SQLiteTreeHandlerStructure::TableEnd();++i)
456       {
457         bool ok = mDB->tableExists(SQLiteTreeHandlerStructure::Table(i));
458         if (ok) 
459           {
460             //      std::cout << "** Table "<<SQLiteTreeHandlerStructure::Table(i)
461             //                <<" exists"<<std::endl;
462             // TO DO : TEST MANDATORY FIELDS EXIST
463           }
464         else 
465           {
466             //      std::cout << "** Table "<<SQLiteTreeHandlerStructure::Table(i)
467             //                <<" does *NOT* exist"<<std::endl;
468             success = false;
469           }
470       }
471     */
472     return success;
473   }  
474   //=====================================================================
475
476   /*
477   //=====================================================================
478   int SQLiteTreeHandler::DBLoadChildren(Node* parent, 
479                                         int maxlevel)
480   {
481
482     //    std::cout << "SQLiteTreeHandler::DBLoadChildren("<<parent<<","<<maxlevel
483     //        << ")"<<std::endl;
484     int nbloaded = 0;
485     if (parent == GetTree()) { parent = 0; }
486     Node* xparent = parent;
487     if ( xparent==0 ) xparent = GetTree();
488     if ( xparent->ChildrenLoaded() ) 
489       {
490         //      std::cout << "--> Children already loaded"<<std::endl;
491         return nbloaded;
492       }
493     if ( xparent->GetType() == Node::Image ) 
494       {
495         return nbloaded;
496       }
497     if ( xparent->GetType() >= maxlevel ) 
498       {
499         return nbloaded;
500       }
501    
502     //    msw[2].Pause();
503     //    msw[2].Resume();
504
505     Node::Type type = xparent->GetType()+1;
506
507     // Query DB
508
509     std::string query = "SELECT * FROM ";
510     query += GetTree().GetDescriptor().GetLevelDescriptor(level).GetName();
511       //SQLiteTreeHandlerStructure::Table(type);
512     if (parent!=0)
513       {
514         query += " WHERE PARENT_ID='" + parent->GetFieldValue("ID") + "'";
515       }
516
517     //    std::cout << "** SQL = '"<<query<<"'"<<std::endl;
518
519     CppSQLite3Query q;
520     QUERYDB(query,q);
521
522     while (!q.eof())
523       {
524         nbloaded++;
525         Node* n = new Node(type,
526                            this,xparent);
527         for (int fld = 0; fld < q.numFields(); fld++)
528           {
529             n->SetFieldValue(q.fieldName(fld),q.getStringField(fld));       
530           }
531         // Index 
532         TypeId ti;
533         ti.type = type;
534         ti.id = n->GetFieldValue("ID");    
535         mTypeIdToNodeMap[ti] = n;
536         // recurse 
537         if ( type < maxlevel ) 
538           {
539             msw[2].Pause();
540             nbloaded += DBLoadChildren(n,maxlevel);
541             msw[2].Resume();
542           }
543         // next entry in db
544         q.nextRow();
545       }
546
547     xparent->SetChildrenLoaded(true);
548     
549     //    msw[2].Pause();
550     return nbloaded;
551   }
552   //=====================================================================
553
554
555
556
557
558
559   //=====================================================================
560   bool SQLiteTreeHandler::DBInsert(Node* alien_node,
561                                    UpdateSummary& summary)
562   {
563     //    std::cout << "SQLiteTreeHandler::Insert('"<<alien_node->GetLabel()
564     //        <<"')"<<std::endl;
565     
566     //    if (!ChildrenLoaded()) DBLoadChildren(this,Node::Database);
567     
568     // Find parent
569     Node* parent;
570     std::string parent_id; 
571     parent = DBGetOrCreateParent(alien_node,parent_id,summary);
572     
573     // Insert 
574     DBRecursiveGetOrCreateNode(alien_node,parent,parent_id,summary);
575    return true;
576   }
577   //=====================================================================
578
579
580   //=====================================================================
581   Node* SQLiteTreeHandler::DBGetOrCreateParent(Node* alien_node,
582                                                 std::string& parent_id,
583                                                 UpdateSummary& summary)
584   {
585     //    std::cout << "DBGetOrCreateParent '" << alien_node->GetLabel()<<"'"
586     //        << std::endl;
587     // Load the patients if not already done
588     DBLoadChildren(this,Node::Patient);
589
590     parent_id = "";
591     Node* parent = this;
592
593     // The chain of ancestors
594     std::deque<Node*> chain;
595     Node* cur = alien_node->GetParent();
596     for (int type=Node::Patient; 
597          type<alien_node->GetType();++type)
598       {
599         chain.push_front(cur);
600         cur = cur->GetParent();
601       }
602
603     // create the nodes if do not exist
604     std::deque<Node*>::iterator i;
605     for (i=chain.begin();i!=chain.end();++i)
606       {
607         //      std::cout << " cur = '"<<(*i)->GetLabel()<<"'"<<std::endl;
608         //      std::string cur_id = DBGetNodeId(*i,parent_id);
609         //      if (cur_id.size()==0)
610         //        {
611         // Node does not exist : create it
612         std::string cur_id;
613         parent = DBGetOrCreateNode(*i, 
614                                         parent,
615                                         parent_id,
616                                         cur_id,
617                                         summary
618                                         );
619         DBLoadChildren(parent,parent->GetType()+1);
620
621         parent_id = cur_id;
622       }
623     return parent;
624   }
625   //=====================================================================
626
627
628
629   //=====================================================================
630   void SQLiteTreeHandler::DBRecursiveGetOrCreateNode(Node* alien_node, 
631                                                       Node* parent, 
632                                                       const std::string& parent_id,
633                                                       UpdateSummary& summary)
634   {
635     //    std::cout << "SQLiteTreeHandler::RecursiveGetOrCreateNode('"
636     //        <<alien_node->GetLabel()
637     //        <<"','"<<parent<<"','"<<parent_id<<"')"<<std::endl;
638     if (parent != 0) 
639       {
640         //      std::cout << " -- Parent = '"<<parent->GetLabel()<<"'"<<std::endl;
641       }   
642     std::string new_id;
643     Node* new_node = DBGetOrCreateNode(alien_node, 
644                                                  parent,
645                                                  parent_id,
646                                                  new_id,
647                                                  summary);
648     Node::ChildrenListType::iterator i;
649     for (i  = alien_node->GetChildrenList().begin();
650          i != alien_node->GetChildrenList().end();
651          i++)
652       {
653         DBRecursiveGetOrCreateNode((*i),new_node,new_id,summary);
654       }
655   }
656   //=====================================================================
657
658
659   //=====================================================================
660   Node* SQLiteTreeHandler::DBGetOrCreateNode(Node* alien_node, 
661                                                    Node* internal_parent,
662                                                    std::string parent_id,
663                                                    std::string& node_id,
664                                                    UpdateSummary& summary)
665   {
666     //   std::cout << "DBGetOrCreateNode('"<<alien_node->GetLabel()<<"','"
667     //        << internal_parent << "','"<< parent_id<<"')"<<std::endl;
668     if (internal_parent != 0) 
669       {
670         //      std::cout << " -- Parent = '"<<internal_parent->GetLabel()<<"'"<<std::endl;
671       }
672     // Node Exists ? return it 
673     // First try among children of internal parent 
674     Node* node = GetChildrenLike(internal_parent,alien_node);
675     if (node>0)
676       {
677         node_id = node->UnsafeGetFieldValue("ID");
678         return node;
679       }
680     // Second : try in DB 
681    
682     // Does not exist : Create new one
683     node = new Node(alien_node->GetType(),this,internal_parent);
684     node->SetChildrenLoaded(true);
685     // Copy fields values from alien
686     Node::FieldValueMapType::iterator i,j;
687     for (i =  node->GetFieldValueMap().begin();
688          i != node->GetFieldValueMap().end();
689          i++)
690       {
691         j = alien_node->GetFieldValueMap().find(i->first);
692         if (j != alien_node->GetFieldValueMap().end() )
693           {
694             i->second = j->second;
695           }
696       }
697
698     msw[2].Resume();
699     if (node->GetType()!=Node::Patient) 
700       node->SetFieldValue("PARENT_ID",parent_id);
701
702     // Insert in DB
703     std::string val;
704     BuildSQLFieldsValues(node,val);
705     std::string insert("INSERT INTO ");
706     insert += std::string(SQLiteTreeHandlerStructure::Table(node->GetType())) 
707       + " " + val + ";";
708     //    std::cout << "** SQL = '"<<insert<<"'"<<std::endl;
709     UPDATEDB(insert);
710     //    std::cout << "** SQL OK"<<std::endl;
711
712     // Store DB id of newly created node;
713     long lastrow = mDB->lastRowId();
714     std::stringstream ri;
715     ri << mDB->lastRowId();
716     node_id = ri.str();
717     //    std::cout << "LastRowId='"<<mDB->lastRowId()<<"' vs '"<<created_id<<"'"<<std::endl;
718
719     node->SetFieldValue("ID",node_id);
720     // Insert in TypeId map
721     TypeId ti;
722     ti.type = node->GetType();
723     ti.id = node_id;
724     mTypeIdToNodeMap[ti] = node;
725     //    std::cout << "== Insert TypeId ("<<ti.type<<","<<ti.id<<")"<<std::endl; 
726     // 
727     msw[2].Pause();
728
729     if (node->GetType()==Node::Patient) summary.added_patients++;
730     if (node->GetType()==Node::Study) summary.added_studies++;
731     if (node->GetType()==Node::Series) summary.added_series++;
732     if (node->GetType()==Node::Image) summary.added_images++;
733
734     return node;
735   }
736   //=====================================================================
737
738   //=====================================================================
739   Node* SQLiteTreeHandler::GetChildrenLike(Node* parent,
740                                             Node* alien_node)
741   {
742     Node::ChildrenListType::iterator i;
743     for (i  = parent->GetChildrenList().begin();
744          i != parent->GetChildrenList().end();
745          i++)
746       {
747         Node::Type type = alien_node->GetType();
748         bool ok = true;
749         for (int j=0;
750              j<SQLiteTreeHandlerStructure::NbQueryFields(type);
751              j++) 
752           {
753             if ( 
754                 alien_node->GetFieldValue(SQLiteTreeHandlerStructure::
755                                     QueryField(type,j).key )   !=
756                 (*i)->GetFieldValue(SQLiteTreeHandlerStructure::
757                                     QueryField(type,j).key ) )
758               {
759                 ok = false;
760                 break;
761               }
762           }
763         if (ok) 
764           {
765             return (*i);
766           }
767       }
768     return 0;    
769   }
770   //=====================================================================
771
772   //=====================================================================
773   std::string SQLiteTreeHandler::DBGetNodeId(Node* node, 
774                                               const std::string& parent_id)
775   {
776     //    std::cout << "SQLiteTreeHandler::DBGetNodeId('"<<node->GetLabel()
777     //        <<"','"<<parent_id<<"')"
778     //        <<std::endl;
779     msw[2].Resume();
780     int type = node->GetType();
781
782     std::string table = SQLiteTreeHandlerStructure::Table(type);
783     std::string where = "WHERE ";
784     
785     if (type!=Node::Patient)
786       {
787         where += "PARENT_ID='" + parent_id 
788           //node->GetFieldValue("PARENT_ID") 
789           + "' AND ";
790       }
791
792     for (int i=0;i<SQLiteTreeHandlerStructure::NbQueryFields(type);i++) 
793       {
794         where += SQLiteTreeHandlerStructure::QueryField(type,i).key + "='"
795           + node->GetFieldValue(SQLiteTreeHandlerStructure::QueryField(type,i).key) + "' ";
796         if (i<SQLiteTreeHandlerStructure::NbQueryFields(type)-1)
797           where += "AND ";
798     }
799
800     std::string query = "SELECT ID FROM " + table + " " + where + ";";                                                    
801     //    std::cout << "** SQL = '"<<query<<"'"<<std::endl;
802     CppSQLite3Query q;
803     QUERYDB(query,q);
804
805     if (!q.eof())
806       {
807         
808         //      std::cout << " - Node exists " << std::endl;
809         std::string id = q.getStringField(0);
810         //      std::cout << " id = '"<<id<<"'"<<std::endl;
811         msw[2].Pause();
812         return id;
813       }
814     msw[2].Pause();
815     return "";
816   }
817   //=====================================================================
818
819
820
821   //=====================================================================
822   Node* SQLiteTreeHandler::GetNodeFromTypeId(Node::Type type,
823                                        const std::string& id)
824   {
825     //    std::cout << "GetNodeFromTypeId("<<type<<","<<id<<")"<<std::endl;
826
827     TypeId ti;
828     ti.type = type;
829     ti.id = id;
830     
831     TypeIdToNodeMapType::iterator i = mTypeIdToNodeMap.find(ti);
832     if (i == mTypeIdToNodeMap.end())
833       {
834
835             std::cout << "Internal error : mTypeIdToNodeMap does not contain key"
836                       << std::endl;
837             creaError("Internal error : mTypeIdToNodeMap does not contain key");
838             // }
839       }
840
841     //    std::cout << " ** Node = "<<i->second<<std::endl;
842     return i->second;
843   }
844   //=====================================================================
845
846   //=====================================================================
847   bool SQLiteTreeHandler::Remove(Node* node)
848   {
849     DBRecursiveRemoveNode(node);
850  
851     //    std::cout << "DELETE"<<std::endl;
852     if (node->GetParent())
853       {
854         node->GetParent()->RemoveChildrenFromList(node);
855       }
856     delete node;
857     //    std::cout << "DELETE OK"<<std::endl;
858     return true;
859   }
860   //========================================================================
861
862   //=====================================================================
863   void SQLiteTreeHandler::DBRecursiveRemoveNode(Node* node)
864   {
865     //    std::cout << "SQLiteTreeHandler::DBRecursiveRemoveNode('"
866     //        <<node->GetLabel()<<"')"<<std::endl;
867
868     std::string query = "DELETE FROM ";
869     query += SQLiteTreeHandlerStructure::Table(node->GetType());
870     query += " WHERE ID='"+ node->GetFieldValue("ID") + "';";
871  
872     UPDATEDB(query);
873
874     Node::ChildrenListType::iterator i;
875     for (i  = node->GetChildrenList().begin();
876          i != node->GetChildrenList().end();
877          i++)
878       {
879         DBRecursiveRemoveNode((*i));
880       }
881   }
882   //=====================================================================
883   
884   //=====================================================================
885   int SQLiteTreeHandler::DBQueryNumberOfChildren(Node* node)
886   {
887     std::string query = "SELECT COUNT (ID) FROM ";
888     query += SQLiteTreeHandlerStructure::Table(node->GetType()+1);
889     if (node->GetType() != Node::Database) 
890       {
891         query += " WHERE PARENT_ID='"+ node->GetFieldValue("ID")+"'";
892       }
893     query  += ";";
894     
895     //   std::cout << "**SQL = "<< query << std::endl;
896     
897     CppSQLite3Query q;
898     QUERYDB(query,q);
899    
900      //    std::cout << "**RES = "<< q.getIntField(0) <<std::endl;
901
902     return q.getIntField(0);
903   }
904   //=====================================================================
905  
906   //========================================================================
907   std::string& format_sql2(std::string& str)
908   {
909     // quote must be doubled
910     //    crea::Utils::Replace( str, "'", "''" );
911     boost::algorithm::replace_all(str,"'","''");
912     // Found strange strings which contained NULL char INSIDE string 
913     int i,size=str.size();
914     for (i=0;i<size;++i) 
915       {
916         if (str[i]==0) 
917           {
918             str = str.substr(0,i);
919             break;
920           }
921       }
922     //    if (i<str.size())
923     return str;
924   }
925    //========================================================================
926
927   //=====================================================================
928   void SQLiteTreeHandler::BuildSQLFieldsValues(Node* n,
929                                         std::string& str)
930   {
931     //    std::cout << "BuildSQLFieldsValues('"<<n->GetLabel()<<"')"<<std::endl;
932
933     std::string atts="";
934     std::string values="";
935     Node::FieldValueMapType::iterator i;
936     for (i =  n->GetFieldValueMap().begin();
937          i != n->GetFieldValueMap().end();
938          i++)
939       {
940         if (i->first=="ID") 
941           {
942             continue;
943           }
944         //      std::cout << "("<<i->first<<","<<i->second<<")"<<std::endl;
945         atts += "'" + i->first + "'";
946         values += "'" + format_sql2(i->second) + "'"; 
947         atts += ",";
948         values += ",";
949       }
950     atts[atts.size()-1]=' ';
951     values[values.size()-1]=' ';
952
953     str = "("+atts+") VALUES ("+values+")";
954
955   }
956   //=====================================================================
957 */
958
959
960
961 } // namespace creaImageIO