1 #include <creaImageIOSQLiteTreeHandler.h>
2 #include <creaImageIOSystem.h>
4 #include "CppSQLite3.h"
8 //#include <creaImageIOSQLiteTreeHandlerStructure.h>
10 //#include <creaImageIOUtilities.h>
12 //#include <icons/database.xpm>
18 #include <wx/filename.h>
21 //#include <icons/close.xpm>
24 #include <creaMessageManager.h>
27 #include <boost/filesystem.hpp>
28 #include <boost/algorithm/string/replace.hpp>
35 //=============================================================
36 SQLiteTreeHandler::SQLiteTreeHandler(const std::string& filename)
39 mDB = new CppSQLite3DB;
40 GimmickMessage(1,"SQLite version : "
41 <<std::string(mDB->SQLiteVersion())<< std::endl);
43 //=============================================================
45 //=============================================================
46 SQLiteTreeHandler::~SQLiteTreeHandler()
50 //=============================================================
53 //=============================================================
54 // void SQLiteTreeHandler::Print() const
57 std::cout << "-> '"<<GetName()<< "' - '"
58 << GetFileName()<<"'"<<std::endl;
59 ChildrenListType::const_iterator i;
60 for (i=GetChildrenList().begin(); i!=GetChildrenList().end(); i++)
66 //=============================================================
68 //=====================================================================
70 bool SQLiteTreeHandler::LocationIsValid()
76 //=====================================================================
79 //=====================================================================
80 bool SQLiteTreeHandler::Open(bool writable)
82 // std::cout << "***> SQLiteTreeHandler::Open('"<<GetFileName()<<"')"<<std::endl;
83 SetWritable(writable);
87 //=====================================================================
88 bool SQLiteTreeHandler::Create(bool writable)
90 // std::cout << "***> SQLiteTreeHandler::New('"<<GetFileName()<<"')"<<std::endl;
91 SetWritable(writable);
94 //=====================================================================
97 //=====================================================================
98 bool SQLiteTreeHandler::Close()
102 //=====================================================================
105 //=====================================================================
106 bool SQLiteTreeHandler::Destroy()
110 //=====================================================================
112 //=====================================================================
113 unsigned int SQLiteTreeHandler::GetNumberOfChildren(tree::Node* n)
117 //=====================================================================
119 //=====================================================================
120 int SQLiteTreeHandler::LoadChildren(tree::Node* parent, int maxlevel)
124 //=====================================================================
129 //=====================================================================
130 void SQLiteTreeHandler::UnLoad(tree::Node* n)
133 //=====================================================================
136 //=====================================================================
137 int SQLiteTreeHandler::AddBranch( const AttributeMapType& attr )
139 tree::Node* parent = DBGetParent(attr);
140 for (int level = parent->GetLevel()+1;
141 level < GetTree().GetNumberOfLevels();
145 parent = new tree::Node(parent,attr);
148 if (node->GetType()!=Node::Patient)
149 node->SetFieldValue("PARENT_ID",parent_id);
153 BuildSQLFieldsValues(node,val);
154 std::string insert("INSERT INTO ");
155 insert += std::string(SQLiteTreeHandlerStructure::Table(node->GetType()))
157 // std::cout << "** SQL = '"<<insert<<"'"<<std::endl;
159 // std::cout << "** SQL OK"<<std::endl;
161 // Store DB id of newly created node;
162 long lastrow = mDB->lastRowId();
163 std::stringstream ri;
164 ri << mDB->lastRowId();
166 // std::cout << "LastRowId='"<<mDB->lastRowId()<<"' vs '"<<created_id<<"'"<<std::endl;
168 node->SetFieldValue("ID",node_id);
170 // Insert in TypeId map
172 ti.type = node->GetType();
174 mTypeIdToNodeMap[ti] = node;
175 // std::cout << "== Insert TypeId ("<<ti.type<<","<<ti.id<<")"<<std::endl;
179 if (node->GetType()==Node::Patient) summary.added_patients++;
180 if (node->GetType()==Node::Study) summary.added_studies++;
181 if (node->GetType()==Node::Series) summary.added_series++;
182 if (node->GetType()==Node::Image) summary.added_images++;
187 //=====================================================================
190 //=====================================================================
191 bool SQLiteTreeHandler::Remove(tree::Node*)
195 //=====================================================================
211 //=====================================================================
212 // SQLite DB specific methods
213 //=====================================================================
218 //=====================================================================
219 char* format_sql(const std::string& s)
221 return sqlite3_mprintf("%q",s.c_str());
223 //=====================================================================
225 // sqlite3_exec(db, zSQL, 0, 0, 0);
226 // sqlite3_free(zSQL);
227 // char* CHAIN = format_sql(QUER); \
228 // sqlite3_free(CHAIN); \
230 //=====================================================================
231 #define QUERYDB(QUER,RES) \
234 GimmickMessage(2,"SQL: '"<<QUER<<"'"<<std::endl); \
235 RES = mDB->execQuery(QUER.c_str()); \
237 catch (CppSQLite3Exception& e) \
239 std::cout << "SQLite query '"<<QUER<<"' : " \
240 << e.errorCode() << ":" \
241 << e.errorMessage()<<std::endl; \
242 creaError("SQLite query '"<<QUER<<"' : " \
243 << e.errorCode() << ":" \
244 << e.errorMessage() ); \
247 //=====================================================================
249 //=====================================================================
250 #define UPDATEDB(UP) \
253 GimmickMessage(2,"SQL: '"<<UP<<"'"<<std::endl); \
254 mDB->execDML(UP.c_str()); \
256 catch (CppSQLite3Exception& e) \
258 std::cout << "SQLite update '"<<UP<<"' Error : " \
259 << e.errorCode() << ":" \
260 << e.errorMessage()<<std::endl; \
261 creaError("SQLite update '"<<UP<<"' Error : " \
262 << e.errorCode() << ":" \
263 << e.errorMessage() ); \
265 //=====================================================================
268 //=====================================================================
269 bool SQLiteTreeHandler::DBOpen()
271 GimmickMessage(1,"Opening SQLite database '"<<GetFileName()
272 <<"' ... "<<std::endl);
274 if (!boost::filesystem::exists(GetFileName()))
281 mDB->open(GetFileName().c_str());
283 catch (CppSQLite3Exception& e)
285 std::cerr << "Opening '"<<GetFileName()<<"' : "
286 << e.errorCode() << ":"
287 << e.errorMessage() << std::endl;
290 // IMPORT TREE DESCRIPTION (AND TEST DB VALIDITY)
291 if (!DBImportTreeDescription())
296 GimmickMessage(1,"Opening SQLite database '"<<GetFileName()
297 <<"' ... OK"<<std::endl);
300 //=====================================================================
302 //=====================================================================
303 bool SQLiteTreeHandler::DBCreate()
305 GimmickMessage(1,"Creating SQLite database '"<<GetFileName()
306 <<"' ... "<<std::endl);
308 if (boost::filesystem::exists(GetFileName()))
310 creaMessage("Gimmick!",1,
311 "[Gimmick!] !! ERROR '"<<GetFileName()<<"' : "
312 << "file already exists"<<std::endl);
319 mDB->open(GetFileName().c_str());
321 catch (CppSQLite3Exception& e)
323 creaMessage("Gimmick!",1,
324 "[Gimmick!] !! ERROR '"
325 << e.errorCode() << ":"
326 << e.errorMessage() <<std::endl);
334 // Create LEVELS table
335 command = "create table LEVELS\n";
336 command += "( Name text )\n";
339 // Iterate the Levels
340 for (int l=0; l<GetTree().GetNumberOfLevels(); ++l)
342 command = "INSERT INTO LEVELS (Name) VALUES ('";
343 command += GetTree().GetLevelDescriptor(l).GetName();
347 // Create table of level (for level>0, i.e. not Root)
350 command = "CREATE TABLE ";
351 command += GetTree().GetLevelDescriptor(l).GetName();
352 command += "\n(\nID INTEGER PRIMARY KEY";
355 command += ",\nPARENT_ID int not null";
357 AppendAttributesSQLDefinition(l,command);
360 command += ",\nconstraint FK_PARENT foreign key (PARENT_ID) references ";
361 command += GetTree().GetLevelDescriptor(l-1).GetName();
362 command += "(ID) on delete restrict on update restrict";
368 // Add Attribute 'ID' to Description
369 GetTree().GetAttributeDescriptorList(l).push_back
370 (AttributeDescriptor( "ID",
371 "Database Identifier",
373 AttributeDescriptor::PRIVATE
378 // Add Attribute 'PARENT_ID' to Description
379 GetTree().GetAttributeDescriptorList(l).push_back
380 (AttributeDescriptor( "PARENT_ID",
381 "Database Parent Identifier",
383 AttributeDescriptor::PRIVATE
389 // Create table *_ATTRIBUTES
391 command = "CREATE TABLE ";
392 command += GetTree().GetLevelDescriptor(l).GetName();
393 command += "_Attributes\n(\n";
394 command += "Key text,\n";
395 command += "Name text,\n";
396 command += "DicomGroup int,\n";
397 command += "DicomElement int,\n";
398 command += "Flags int\n";
403 // Fill the table *_ATTRIBUTES
404 LevelDescriptor::AttributeDescriptorListType::const_iterator i;
405 for (i = GetTree().GetAttributeDescriptorList(l).begin();
406 i != GetTree().GetAttributeDescriptorList(l).end();
410 std::stringstream insert;
411 insert << "INSERT INTO "
412 << GetTree().GetLevelDescriptor(l).GetName()
413 << "_Attributes (Key,Name,DicomGroup,DicomElement,Flags) "
415 << i->GetKey() << "','"
416 << i->GetName() << "',"
417 << i->GetGroup() << ","
418 << i->GetElement() << ","
419 << i->GetFlags() << ");";
421 UPDATEDB(insert.str());
425 catch (std::exception)
430 GetTree().SetChildrenLoaded(true);
431 GimmickMessage(1,"Creating SQLite database '"<<GetFileName()
432 <<"' ... OK"<<std::endl);
435 //=====================================================================
437 //=====================================================================
438 void SQLiteTreeHandler::AppendAttributesSQLDefinition(int level,
441 LevelDescriptor::AttributeDescriptorListType::const_iterator i;
442 for (i = GetTree().GetAttributeDescriptorList(level).begin();
443 i != GetTree().GetAttributeDescriptorList(level).end();
446 // if (i->second.flags==1) continue;
452 //=====================================================================
455 //=====================================================================
456 bool SQLiteTreeHandler::DBImportTreeDescription()
458 GimmickMessage(1,"Importing tree description from database ..."
461 // Test table 'LEVELS' existence
462 if ( ! mDB->tableExists("LEVELS") )
464 GimmickMessage(1,"!! ERROR : Table 'LEVELS' does not exist"
469 tree::Descriptor& desc = GetTree().GetDescriptor();
470 // clears the existing one
471 desc.GetLevelDescriptorList().clear();
474 std::string query = "SELECT * FROM LEVELS";
480 std::string name = q.getStringField(0);
481 GimmickMessage(2," * Importing level '"<<name<<"'"<<std::endl);
482 desc.GetLevelDescriptorList().push_back(LevelDescriptor(name));
487 for (int level = 0; level < nblevel; ++level )
489 std::string table = GetTree().GetLevelDescriptor(level).GetName();
490 table += "_Attributes";
491 // Test table 'LEVELS' existence
492 if ( ! mDB->tableExists(table.c_str()) )
494 GimmickMessage(1,"!! ERROR : Table '"<<table<<"' does not exist"
499 std::string query = "SELECT * FROM ";
504 GimmickMessage(2," * Level '"
505 <<GetTree().GetLevelDescriptor(level).GetName()
508 // Test that ID and PARENT_ID mandatory attributes exist
509 bool ID_found = false;
510 bool PARENT_ID_found = false;
511 if (level==0) ID_found = true;
512 if (level<=1) PARENT_ID_found = true;
516 std::string key(q.getStringField(0));
517 std::string name(q.getStringField(1));
518 GimmickMessage(2," - Importing attribute '"<<key<<"' '"<<name
520 desc.GetAttributeDescriptorList(level).push_back
521 (AttributeDescriptor( key, // Key
523 q.getIntField(2), // Group
524 q.getIntField(3), // Element
525 q.getIntField(4) // Flags
531 if ( key == "PARENT_ID" )
533 PARENT_ID_found = true;
538 if ( ! (ID_found || PARENT_ID_found ) )
540 GimmickMessage(1,"!! ERROR : Table '"<<table
541 <<"' does not contain mandatory attribute ID or PARENT_ID"
548 GimmickMessage(1,"Importing tree description from database ... OK"
552 //=====================================================================
568 //=====================================================================
569 tree::Node* SQLiteTreeHandler::DBGetParent( const AttributeMapType& attr)
571 Node* parent = GetTree().GetTree();
576 // Load the children of the current parent
577 DBLoadChildren(parent);
578 // Iterate the children
579 tree::Node::ChildrenListType::const_iterator i;
580 for (i = parent->GetChildrenList().begin();
581 i!= parent->GetChildrenList().end();
584 if ( (*i)->Matches( attr ) )
594 //=====================================================================
597 //=====================================================================
598 int SQLiteTreeHandler::DBLoadChildren(tree::Node* parent,
602 if (parent->GetChildrenLoaded()) return nbloaded;
605 int level = parent->GetLevel();
606 std::string query = "SELECT * FROM ";
607 query += GetTree().GetLevelDescriptor(level+1).GetName();
610 query += " WHERE PARENT_ID='" + parent->UnsafeGetAttribute("ID")
619 Node* n = new Node(parent);
620 for (int fld = 0; fld < q.numFields(); fld++)
622 n->UnsafeSetAttribute(q.fieldName(fld),q.getStringField(fld));
628 ti.id = n->GetFieldValue("ID");
629 mTypeIdToNodeMap[ti] = n;
632 if ( numberoflevels > 1 )
635 nbloaded += DBLoadChildren(n, numberoflevels-1);
642 parent->SetChildrenLoaded(true);
647 // std::cout << "SQLiteTreeHandler::DBLoadChildren("<<parent<<","<<maxlevel
648 // << ")"<<std::endl;
651 if (parent == GetTree()) { parent = 0; }
652 Node* xparent = parent;
653 if ( xparent==0 ) xparent = GetTree();
654 if ( xparent->ChildrenLoaded() )
656 // std::cout << "--> Children already loaded"<<std::endl;
659 if ( xparent->GetType() == Node::Image )
663 if ( xparent->GetType() >= maxlevel )
671 Node::Type type = xparent->GetType()+1;
675 std::string query = "SELECT * FROM ";
676 query += GetTree().GetDescriptor().GetLevelDescriptor(level).GetName();
677 //SQLiteTreeHandlerStructure::Table(type);
680 query += " WHERE PARENT_ID='" + parent->GetFieldValue("ID") + "'";
683 // std::cout << "** SQL = '"<<query<<"'"<<std::endl;
691 Node* n = new Node(type,
693 for (int fld = 0; fld < q.numFields(); fld++)
695 n->SetFieldValue(q.fieldName(fld),q.getStringField(fld));
700 ti.id = n->GetFieldValue("ID");
701 mTypeIdToNodeMap[ti] = n;
703 if ( type < maxlevel )
706 nbloaded += DBLoadChildren(n,maxlevel);
713 xparent->SetChildrenLoaded(true);
719 //=====================================================================
726 //=====================================================================
727 bool SQLiteTreeHandler::DBInsert(Node* alien_node,
728 UpdateSummary& summary)
730 // std::cout << "SQLiteTreeHandler::Insert('"<<alien_node->GetLabel()
731 // <<"')"<<std::endl;
733 // if (!ChildrenLoaded()) DBLoadChildren(this,Node::Database);
737 std::string parent_id;
738 parent = DBGetOrCreateParent(alien_node,parent_id,summary);
741 DBRecursiveGetOrCreateNode(alien_node,parent,parent_id,summary);
744 //=====================================================================
747 //=====================================================================
748 Node* SQLiteTreeHandler::DBGetOrCreateParent(Node* alien_node,
749 std::string& parent_id,
750 UpdateSummary& summary)
752 // std::cout << "DBGetOrCreateParent '" << alien_node->GetLabel()<<"'"
754 // Load the patients if not already done
755 DBLoadChildren(this,Node::Patient);
760 // The chain of ancestors
761 std::deque<Node*> chain;
762 Node* cur = alien_node->GetParent();
763 for (int type=Node::Patient;
764 type<alien_node->GetType();++type)
766 chain.push_front(cur);
767 cur = cur->GetParent();
770 // create the nodes if do not exist
771 std::deque<Node*>::iterator i;
772 for (i=chain.begin();i!=chain.end();++i)
774 // std::cout << " cur = '"<<(*i)->GetLabel()<<"'"<<std::endl;
775 // std::string cur_id = DBGetNodeId(*i,parent_id);
776 // if (cur_id.size()==0)
778 // Node does not exist : create it
780 parent = DBGetOrCreateNode(*i,
786 DBLoadChildren(parent,parent->GetType()+1);
792 //=====================================================================
796 //=====================================================================
797 void SQLiteTreeHandler::DBRecursiveGetOrCreateNode(Node* alien_node,
799 const std::string& parent_id,
800 UpdateSummary& summary)
802 // std::cout << "SQLiteTreeHandler::RecursiveGetOrCreateNode('"
803 // <<alien_node->GetLabel()
804 // <<"','"<<parent<<"','"<<parent_id<<"')"<<std::endl;
807 // std::cout << " -- Parent = '"<<parent->GetLabel()<<"'"<<std::endl;
810 Node* new_node = DBGetOrCreateNode(alien_node,
815 Node::ChildrenListType::iterator i;
816 for (i = alien_node->GetChildrenList().begin();
817 i != alien_node->GetChildrenList().end();
820 DBRecursiveGetOrCreateNode((*i),new_node,new_id,summary);
823 //=====================================================================
826 //=====================================================================
827 Node* SQLiteTreeHandler::DBGetOrCreateNode(Node* alien_node,
828 Node* internal_parent,
829 std::string parent_id,
830 std::string& node_id,
831 UpdateSummary& summary)
833 // std::cout << "DBGetOrCreateNode('"<<alien_node->GetLabel()<<"','"
834 // << internal_parent << "','"<< parent_id<<"')"<<std::endl;
835 if (internal_parent != 0)
837 // std::cout << " -- Parent = '"<<internal_parent->GetLabel()<<"'"<<std::endl;
839 // Node Exists ? return it
840 // First try among children of internal parent
841 Node* node = GetChildrenLike(internal_parent,alien_node);
844 node_id = node->UnsafeGetFieldValue("ID");
847 // Second : try in DB
849 // Does not exist : Create new one
850 node = new Node(alien_node->GetType(),this,internal_parent);
851 node->SetChildrenLoaded(true);
852 // Copy fields values from alien
853 Node::FieldValueMapType::iterator i,j;
854 for (i = node->GetFieldValueMap().begin();
855 i != node->GetFieldValueMap().end();
858 j = alien_node->GetFieldValueMap().find(i->first);
859 if (j != alien_node->GetFieldValueMap().end() )
861 i->second = j->second;
866 if (node->GetType()!=Node::Patient)
867 node->SetFieldValue("PARENT_ID",parent_id);
871 BuildSQLFieldsValues(node,val);
872 std::string insert("INSERT INTO ");
873 insert += std::string(SQLiteTreeHandlerStructure::Table(node->GetType()))
875 // std::cout << "** SQL = '"<<insert<<"'"<<std::endl;
877 // std::cout << "** SQL OK"<<std::endl;
879 // Store DB id of newly created node;
880 long lastrow = mDB->lastRowId();
881 std::stringstream ri;
882 ri << mDB->lastRowId();
884 // std::cout << "LastRowId='"<<mDB->lastRowId()<<"' vs '"<<created_id<<"'"<<std::endl;
886 node->SetFieldValue("ID",node_id);
887 // Insert in TypeId map
889 ti.type = node->GetType();
891 mTypeIdToNodeMap[ti] = node;
892 // std::cout << "== Insert TypeId ("<<ti.type<<","<<ti.id<<")"<<std::endl;
896 if (node->GetType()==Node::Patient) summary.added_patients++;
897 if (node->GetType()==Node::Study) summary.added_studies++;
898 if (node->GetType()==Node::Series) summary.added_series++;
899 if (node->GetType()==Node::Image) summary.added_images++;
903 //=====================================================================
905 //=====================================================================
906 Node* SQLiteTreeHandler::GetChildrenLike(Node* parent,
909 Node::ChildrenListType::iterator i;
910 for (i = parent->GetChildrenList().begin();
911 i != parent->GetChildrenList().end();
914 Node::Type type = alien_node->GetType();
917 j<SQLiteTreeHandlerStructure::NbQueryFields(type);
921 alien_node->GetFieldValue(SQLiteTreeHandlerStructure::
922 QueryField(type,j).key ) !=
923 (*i)->GetFieldValue(SQLiteTreeHandlerStructure::
924 QueryField(type,j).key ) )
937 //=====================================================================
939 //=====================================================================
940 std::string SQLiteTreeHandler::DBGetNodeId(Node* node,
941 const std::string& parent_id)
943 // std::cout << "SQLiteTreeHandler::DBGetNodeId('"<<node->GetLabel()
944 // <<"','"<<parent_id<<"')"
947 int type = node->GetType();
949 std::string table = SQLiteTreeHandlerStructure::Table(type);
950 std::string where = "WHERE ";
952 if (type!=Node::Patient)
954 where += "PARENT_ID='" + parent_id
955 //node->GetFieldValue("PARENT_ID")
959 for (int i=0;i<SQLiteTreeHandlerStructure::NbQueryFields(type);i++)
961 where += SQLiteTreeHandlerStructure::QueryField(type,i).key + "='"
962 + node->GetFieldValue(SQLiteTreeHandlerStructure::QueryField(type,i).key) + "' ";
963 if (i<SQLiteTreeHandlerStructure::NbQueryFields(type)-1)
967 std::string query = "SELECT ID FROM " + table + " " + where + ";";
968 // std::cout << "** SQL = '"<<query<<"'"<<std::endl;
975 // std::cout << " - Node exists " << std::endl;
976 std::string id = q.getStringField(0);
977 // std::cout << " id = '"<<id<<"'"<<std::endl;
984 //=====================================================================
988 //=====================================================================
989 Node* SQLiteTreeHandler::GetNodeFromTypeId(Node::Type type,
990 const std::string& id)
992 // std::cout << "GetNodeFromTypeId("<<type<<","<<id<<")"<<std::endl;
998 TypeIdToNodeMapType::iterator i = mTypeIdToNodeMap.find(ti);
999 if (i == mTypeIdToNodeMap.end())
1002 std::cout << "Internal error : mTypeIdToNodeMap does not contain key"
1004 creaError("Internal error : mTypeIdToNodeMap does not contain key");
1008 // std::cout << " ** Node = "<<i->second<<std::endl;
1011 //=====================================================================
1013 //=====================================================================
1014 bool SQLiteTreeHandler::Remove(Node* node)
1016 DBRecursiveRemoveNode(node);
1018 // std::cout << "DELETE"<<std::endl;
1019 if (node->GetParent())
1021 node->GetParent()->RemoveChildrenFromList(node);
1024 // std::cout << "DELETE OK"<<std::endl;
1027 //========================================================================
1029 //=====================================================================
1030 void SQLiteTreeHandler::DBRecursiveRemoveNode(Node* node)
1032 // std::cout << "SQLiteTreeHandler::DBRecursiveRemoveNode('"
1033 // <<node->GetLabel()<<"')"<<std::endl;
1035 std::string query = "DELETE FROM ";
1036 query += SQLiteTreeHandlerStructure::Table(node->GetType());
1037 query += " WHERE ID='"+ node->GetFieldValue("ID") + "';";
1041 Node::ChildrenListType::iterator i;
1042 for (i = node->GetChildrenList().begin();
1043 i != node->GetChildrenList().end();
1046 DBRecursiveRemoveNode((*i));
1049 //=====================================================================
1051 //=====================================================================
1052 int SQLiteTreeHandler::DBQueryNumberOfChildren(Node* node)
1054 std::string query = "SELECT COUNT (ID) FROM ";
1055 query += SQLiteTreeHandlerStructure::Table(node->GetType()+1);
1056 if (node->GetType() != Node::Database)
1058 query += " WHERE PARENT_ID='"+ node->GetFieldValue("ID")+"'";
1062 // std::cout << "**SQL = "<< query << std::endl;
1067 // std::cout << "**RES = "<< q.getIntField(0) <<std::endl;
1069 return q.getIntField(0);
1071 //=====================================================================
1073 //========================================================================
1074 std::string& format_sql2(std::string& str)
1076 // quote must be doubled
1077 // crea::Utils::Replace( str, "'", "''" );
1078 boost::algorithm::replace_all(str,"'","''");
1079 // Found strange strings which contained NULL char INSIDE string
1080 int i,size=str.size();
1081 for (i=0;i<size;++i)
1085 str = str.substr(0,i);
1089 // if (i<str.size())
1092 //========================================================================
1094 //=====================================================================
1095 void SQLiteTreeHandler::BuildSQLFieldsValues(Node* n,
1098 // std::cout << "BuildSQLFieldsValues('"<<n->GetLabel()<<"')"<<std::endl;
1100 std::string atts="";
1101 std::string values="";
1102 Node::FieldValueMapType::iterator i;
1103 for (i = n->GetFieldValueMap().begin();
1104 i != n->GetFieldValueMap().end();
1111 // std::cout << "("<<i->first<<","<<i->second<<")"<<std::endl;
1112 atts += "'" + i->first + "'";
1113 values += "'" + format_sql2(i->second) + "'";
1117 atts[atts.size()-1]=' ';
1118 values[values.size()-1]=' ';
1120 str = "("+atts+") VALUES ("+values+")";
1123 //=====================================================================
1128 } // namespace creaImageIO