ROSE  0.9.6a
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SqliteDatabaseGraph.h
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * ROSE Global Database Connection
4  *
5  * graph database storage class definition
6  *
7  *****************************************************************************/
8 
9 #ifndef SQLITE_DATABASEGRAPH_H
10 #define SQLITE_DATABASEGRAPH_H
11 
12 // for graph output as .dot file
13 #include <cstring>
14 #include <algorithm>
15 
16 // use the boost graph files
17 #include "boost/graph/adjacency_list.hpp"
18 #include "boost/graph/topological_sort.hpp"
19 #include "boost/graph/exception.hpp"
20 #include <boost/graph/graphviz.hpp>
21 
22 #include <rose.h>
23 #include "sqlite3x.h"
24 
26 #define GTYPE_CALLGRAPH 1
27 #define GTYPE_CLASSHIERARCHY 2
28 #define GTYPE_TESTGRAPH 3 // for database graph example
29 #define GTYPE_SIMPLECALLGRAPH 4 // for simple callgraph example
30 #define GTYPE_USERDEFINED 100 // user defined graphs should start with this id
31 
32 
33 //--------------------------------------------------------------------
34 // Schema Setup
35 //--------------------------------------------------------------------
36 #define PROJECTSTBL "projects"
37 #define GRAPHDATATBL "graphData"
38 #define GRAPHNODETBL "graphNode"
39 #define GRAPHEDGETBL "graphEdge"
40 
41 // VertexType
42 class dbTable
43 {
44  public:
45  dbTable(const char* table) { name = table; }
46 
47  std::string table() { return name; }
48  std::string field_list()
49  {
50  std::string list;
51  for( std::vector<std::string>::iterator it = columnNames.begin();
52  it != columnNames.end() ; it++ )
53  list += (*it) + ",";
54  return list.substr(0, list.size() - 2);
55  }
56 
57  std::vector<std::string> field_types() { return columnTypes; }
58 
59  std::vector<std::string> getColumnNames() { return columnNames; }
60 
61  std::string name;
62  std::vector<std::string> columnNames;
63  std::vector<std::string> columnTypes;
64 };
65 
66 // EdgetType
67 class dbRow : public dbTable
68 {
69  public:
70  dbRow(const char* table) : dbTable(table) {}
71 
72  void set_id(long id) { rowid = id; }
73  long get_id() const { return rowid; }
74 
75  virtual void load(sqlite3x::sqlite3_reader& r)=0;
76  virtual void insert(sqlite3x::sqlite3_connection* db)=0;
77 
78  long rowid;
79 };
80 
81 class projectsRow: public dbRow
82 {
83  public:
85  {
86  columnNames.push_back("id");
87  columnNames.push_back("name");
88  columnNames.push_back("CallgraphRootID");
89 
90  columnTypes.push_back("integer");
91  columnTypes.push_back("string");
92  columnTypes.push_back("integer");
93 
94  name = project;
95  }
96 
97  // Load from database
98  void load(sqlite3x::sqlite3_reader& r)
99  {
100  rowid = r.getint(0);
101  name = r.getstring(1);
102  rootid = r.getint(2);
103  }
104 
105  // Insert into database
106  // NOTE: does not check for duplicates
107  void insert(sqlite3x::sqlite3_connection* db)
108  {
109  sqlite3x::sqlite3_command selectcmd(*db,
110  "SELECT * FROM " + std::string(PROJECTSTBL) + " WHERE name=? AND CallgraphRootID=?;");
111  selectcmd.bind(1,name);
112  selectcmd.bind(2,rootid);
113 
114  sqlite3x::sqlite3_reader r = selectcmd.executereader();
115  if( r.read() ) {
116  rowid = r.getint(0);
117  return;
118  }
119 
120  sqlite3x::sqlite3_command insertcmd(*db,
121  "INSERT INTO " + std::string(PROJECTSTBL) + " (name,CallgraphRootID) VALUES (?,?);");
122  insertcmd.bind(1,name);
123  insertcmd.bind(2,rootid);
124  insertcmd.executenonquery();
125 
126  rowid = db->insertid();
127  }
128 
129  std::string name;
130  int rootid;
131 };
132 
133 class cgData : public dbRow
134 {
135  public:
136  cgData(int project, int type): dbRow(GRAPHDATATBL)
137  {
138  columnNames.push_back("id");
139  columnNames.push_back("projectid");
140  columnNames.push_back("graphType");
141 
142  columnTypes.push_back("integer");
143  columnTypes.push_back("integer");
144  columnTypes.push_back("integer");
145 
146  projectId = project;
147  graphType = type;
148  }
149  cgData(sqlite3x::sqlite3_reader& r): dbRow(GRAPHDATATBL) { load(r); }
150 
151  // Load from database
152  void load(sqlite3x::sqlite3_reader& r)
153  {
154  rowid = r.getint(0);
155  projectId = r.getint(1);
156  graphType = r.getint(2);
157  }
158 
159  // Insert into database
160  // NOTE: does not check for duplicates
161  void insert(sqlite3x::sqlite3_connection* db)
162  {
163  sqlite3x::sqlite3_command selectcmd(*db,
164  "SELECT * FROM " + std::string(GRAPHDATATBL) + " WHERE projectid=? AND graphType=?;");
165  selectcmd.bind(1,projectId);
166  selectcmd.bind(2,graphType);
167 
168  sqlite3x::sqlite3_reader r = selectcmd.executereader();
169  if( r.read() ) {
170  rowid = r.getint(0);
171  return;
172  }
173 
174  sqlite3x::sqlite3_command insertcmd(*db,
175  "INSERT INTO " + std::string(GRAPHDATATBL) + " (projectid,graphType) VALUES (?,?);");
176  insertcmd.bind(1,projectId);
177  insertcmd.bind(2,graphType);
178  insertcmd.executenonquery();
179 
180  rowid = db->insertid();
181  }
182 
183  void set_graphid(int id) { projectId = id; }
184  int get_graphid() { return projectId; }
185 
186  void set_projectid(int id) { projectId = id; }
187  int get_projectid() { return projectId; }
188 
189  void set_graphtype(int type) { graphType = type; }
190  int get_graphtype() { return graphType; }
191 
194 };
195 
196 class cgNode : public dbRow
197 {
198  public:
199  cgNode(int graphid, int node, std::string& name): dbRow(GRAPHNODETBL)
200  {
201  columnNames.push_back("id");
202  columnNames.push_back("graphId");
203  columnNames.push_back("nodeId");
204  columnNames.push_back("name");
205 
206  columnTypes.push_back("integer");
207  columnTypes.push_back("integer");
208  columnTypes.push_back("integer");
209  columnTypes.push_back("text");
210 
211  gid = graphid;
212  nodeId = node;
213  nodeName = name;
214  }
215  cgNode(sqlite3x::sqlite3_reader& r) : dbRow(GRAPHNODETBL) { load(r); }
216 
217  void load(sqlite3x::sqlite3_reader& r)
218  {
219  rowid = r.getint(0);
220  gid = r.getint(1);
221  nodeId = r.getint(2);
222  nodeName = r.getstring(3);
223  }
224 
225  void insert(sqlite3x::sqlite3_connection* db)
226  {
227  sqlite3x::sqlite3_command selectcmd(*db,
228  "SELECT * FROM " + std::string(GRAPHNODETBL) + " WHERE graphId=? AND nodeId=? AND name=?;");
229  selectcmd.bind(1,gid);
230  selectcmd.bind(2,nodeId);
231  selectcmd.bind(3,nodeName);
232 
233  sqlite3x::sqlite3_reader r = selectcmd.executereader();
234  if( r.read() ) {
235  rowid = r.getint(0);
236  return;
237  }
238 
239  sqlite3x::sqlite3_command insertcmd(*db,
240  "INSERT INTO " + std::string(GRAPHNODETBL) + " (graphId,nodeId,name) VALUES (?,?,?);");
241  insertcmd.bind(1,gid);
242  insertcmd.bind(2,nodeId);
243  insertcmd.bind(3,nodeName);
244  insertcmd.executenonquery();
245 
246  rowid = db->insertid();
247  }
248 
249  void set_graphid(int id) { gid = id; }
250  int get_graphid() { return gid; }
251 
252  void set_nodeid(int id) { nodeId = id; }
253  int get_nodeid() { return nodeId; }
254 
255  void set_nodename(std::string& name) { nodeName = name; }
256  std::string get_nodename() { return nodeName; }
257 
258  int gid;
259  int nodeId;
260  std::string nodeName;
261 };
262 
263 class cgEdge : public dbRow
264 {
265  public:
267 
268  cgEdge(int graphid, int edge, int source, int target): dbRow(GRAPHEDGETBL)
269  {
270  columnNames.push_back("id");
271  columnNames.push_back("graphId");
272  columnNames.push_back("edgeId");
273  columnNames.push_back("sourceId");
274  columnNames.push_back("targetId");
275 
276  columnTypes.push_back("integer");
277  columnTypes.push_back("integer");
278  columnTypes.push_back("integer");
279  columnTypes.push_back("integer");
280  columnTypes.push_back("integer");
281 
282  gid = graphid;
283  edgeId = edge;
284  sourceId = source;
285  targetId = target;
286  }
287  cgEdge(sqlite3x::sqlite3_reader& r): dbRow(GRAPHEDGETBL) { load(r); }
288 
289  void load(sqlite3x::sqlite3_reader& r)
290  {
291  rowid = r.getint(0);
292  gid = r.getint(1);
293  edgeId = r.getint(2);
294  sourceId = r.getint(3);
295  targetId = r.getint(4);
296  }
297 
298  void insert(sqlite3x::sqlite3_connection* db)
299  {
300  sqlite3x::sqlite3_command selectcmd(*db,
301  "SELECT * FROM " + std::string(GRAPHEDGETBL) + " WHERE graphId=? AND edgeId=? AND sourceId=? AND targetId=?;");
302  selectcmd.bind(1,gid);
303  selectcmd.bind(2,edgeId);
304  selectcmd.bind(3,sourceId);
305  selectcmd.bind(4,targetId);
306 
307  sqlite3x::sqlite3_reader r = selectcmd.executereader();
308  if( r.read() ) {
309  rowid = r.getint(0);
310  return;
311  }
312 
313  sqlite3x::sqlite3_command insertcmd(*db,
314  "INSERT INTO " + std::string(GRAPHEDGETBL) + " (graphId,edgeId,sourceId,targetId) VALUES (?,?,?,?);");
315  insertcmd.bind(1,gid);
316  insertcmd.bind(2,edgeId);
317  insertcmd.bind(3,sourceId);
318  insertcmd.bind(4,targetId);
319  insertcmd.executenonquery();
320 
321  rowid = db->insertid();
322  }
323 
324  void set_graphid(int id) { gid = id; }
325  int get_graphid() { return gid; }
326 
327  void set_edgeId(int id) { edgeId = id; }
328  int get_edgeId() { return edgeId; }
329 
330  void set_sourceId(int source) { sourceId = source; }
331  int get_sourceId() { return sourceId; }
332 
333  void set_targetId(int target) { targetId = target; }
334  int get_targetId() { return targetId; }
335 
336  int gid;
337  int edgeId;
338  int sourceId;
339  int targetId;
340 };
341 
342 bool
343 define_schema(sqlite3x::sqlite3_connection& gDB)
344 {
345  gDB.executenonquery("CREATE TABLE IF NOT EXISTS " + std::string(PROJECTSTBL) + " (id INTEGER PRIMARY KEY, name TEXT, callgraphRootId INTEGER)");
346  gDB.executenonquery("CREATE TABLE IF NOT EXISTS " + std::string(GRAPHDATATBL) + " (id INTEGER PRIMARY KEY, projectId INTEGER, graphType INTEGER)");
347  gDB.executenonquery("CREATE TABLE IF NOT EXISTS " + std::string(GRAPHNODETBL) + " (id INTEGER PRIMARY KEY, graphId INTEGER, nodeId INTEGER, name TEXT)");
348  gDB.executenonquery("CREATE TABLE IF NOT EXISTS " + std::string(GRAPHEDGETBL) + " (id INTEGER PRIMARY KEY, graphId INTEGER, edgeId INTEGER, sourceId INTEGER, targetID INTEGER)");
349 
350  return true;
351 }
352 
353 
354 // install boost database graph property map types
355 namespace boost {
357  BOOST_INSTALL_PROPERTY( vertex, dbg_data );
358 
360  BOOST_INSTALL_PROPERTY( edge, dbg_data );
361 
363  BOOST_INSTALL_PROPERTY( graph, dbg_data );
364 };
365 
366  //boost::GraphvizVertexProperty p;
367 
368 //-----------------------------------------------------------------------------
370 template<class VertexType, class EdgeType,
371  class BoostVertexList,
372  class BoostEdgeList,
373  class BoostDirection,
374  class BoostVertexProperty,
375  class BoostEdgeProperty,
376  class BoostGraphProperty>
378  public boost::adjacency_list<
379  BoostVertexList, BoostEdgeList, BoostDirection,
380  boost::property< boost::vertex_index1_t, std::size_t,
381  boost::property<boost::vertex_name_t, std::string,
382  boost::property<boost::vertex_color_t, boost::default_color_type,
383  boost::property<boost::vertex_dbg_data_t, VertexType,
384  BoostVertexProperty > > > >,
385  boost::property<boost::edge_dbg_data_t, EdgeType, BoostEdgeProperty>,
386  boost::property<boost::graph_dbg_data_t, int, BoostGraphProperty>
387  >
388 {
389 
390 public:
391 
393  typedef boost::adjacency_list<
394  //boost::vecS, boost::vecS, bidirectionalS,
395  BoostVertexList, BoostEdgeList, BoostDirection,
396  boost::property< boost::vertex_index1_t, std::size_t,
397  boost::property<boost::vertex_name_t, std::string,
398  boost::property<boost::vertex_color_t, boost::default_color_type,
399  boost::property<boost::vertex_dbg_data_t, VertexType,
400  BoostVertexProperty > > > >,
401  boost::property<boost::edge_dbg_data_t, EdgeType,
402  BoostEdgeProperty>,
403  boost::property<boost::graph_dbg_data_t, int, BoostGraphProperty>
405  typedef typename boost::graph_traits< dbgType >::vertex_descriptor dbgVertex;
407  typedef typename boost::graph_traits< dbgType >::edge_descriptor dbgEdge;
409  typedef typename std::pair<bool, dbgEdge> dbgEdgeReturn;
410 
412  DatabaseGraph( long pid, long type, sqlite3x::sqlite3_connection *gdb );
413 
415  ~DatabaseGraph( );
416 
418  dbgVertex insertVertex(VertexType& e1, std::string name);
420  dbgVertex insertVertex(VertexType& e, std::string name, int subgraphId, std::string subgraphName);
422  dbgEdgeReturn insertEdge(VertexType& e1, VertexType& e2, EdgeType& value);
424  dbgEdgeReturn insertEdge(VertexType& e1, VertexType& e2);
425 
427  bool searchEdge(EdgeType &edge, dbgEdge &edesc) const;
428 
429  // helper functions
430 
432  void setSubgraphInit(int refcol, dbRow *rowdata, int namecol);
433 
435  int clearSuccessors(VertexType& parent);
436 
438  int removeNode( VertexType& node );
439 
441  int nodeIsUsed(VertexType& node);
442 
444  int getGraphId();
445 
447  void setNodeNameColumn( int set ){ mNameColumn = set; }
448 
449 
450  // file functions
451 
453  int loadFromDatabase( void );
454 
456  int writeToDatabase( void );
457 
459  void writeToDOTFile(std::string filename);
460 
462  void writeAdjacencyMatrixToFileRaw(std::string filename) { };
463 
465  void writeAdjacencyMatrixToFileMcl(std::string filename) { };
466 
467 
468 private:
469 
471  bool searchVertex(VertexType &node, dbgVertex &vdesc) const;
472 
473 
474  // member variables
475 
478 
480  long mGraphId;
481 
483  long mType;
484 
486  short mNameColumn;
487 
489  sqlite3x::sqlite3_connection *mpGDB;
490 
493 
496 
499 
502 };
503 
504 
505 
506 // for shorter function definitions...
507 #define DBG_TEMPLATE_DEF template<class VertexType, class EdgeType,\
508  class BoostVertexList, class BoostEdgeList, class BoostDirection,\
509  class BoostVertexProperty, class BoostEdgeProperty, class BoostGraphProperty>
510 #define DBG_TEMPLATE_CLASSES VertexType, EdgeType, BoostVertexList, BoostEdgeList, BoostDirection, BoostVertexProperty, BoostEdgeProperty, BoostGraphProperty
511 
512 
513 //-----------------------------------------------------------------------------
514 // constructor
516 DatabaseGraph<DBG_TEMPLATE_CLASSES>::DatabaseGraph( long pid, long type, sqlite3x::sqlite3_connection *gdb )
517 {
518  mProjectId = pid;
519  mType = type;
520  mpGDB = gdb;
521  mNameColumn = -1;
522  mInitSubgraphs = false;
523  mGraphId = -1;
524 }
525 
529 {
530  dbgVertex vdesc;
531  if(searchVertex(e1, vdesc) ) {
532  // already there... , only set name etc.
533  } else {
534  vdesc = add_vertex( *this );
535  put( boost::vertex_dbg_data, *this, vdesc, e1 );
536  put( boost::vertex_index1, *this, vdesc, e1.get_id() );
537  }
538  put( boost::vertex_name, *this, vdesc, name );
539  // WARNING - dont use get( attr, G, vdesc)["label"] !!! , that's not for writing
540  get( boost::vertex_attribute, *this )[vdesc]["label"] = name;
541  //cerr << " added vertex || " << get(vertex_index1, *this, vdesc) << " " << name<< endl; // debug
542  //return e1.get_id();
543  return vdesc;
544 }
545 
548 DatabaseGraph<DBG_TEMPLATE_CLASSES>::insertVertex(VertexType& e1, std::string name, int subgraphId, std::string subgraphName)
549 {
550  // TODO init subgraphs
551  dbgVertex vdesc;
552  if(searchVertex(e1, vdesc) ) {
553  // already there... , only set name etc.
554  } else {
555  vdesc = add_vertex( *this );
556  put( boost::vertex_dbg_data, *this, vdesc, e1 );
557  put( boost::vertex_index1, *this, vdesc, e1.get_id() );
558  }
559  //vdesc = add_vertex( *this );
560  put( boost::vertex_name, *this, vdesc, name );
561  get( boost::vertex_attribute, *this )[vdesc]["label"] = name;
562  //cerr << " added vertex sg || " << get(vertex_index1, *this, vdesc) << " " << name<< endl; // debug
563  //return e1.get_id();
564  return vdesc;
565 }
566 
567 //-----------------------------------------------------------------------------
568 // insert an edge between e1 and e2
571 DatabaseGraph<DBG_TEMPLATE_CLASSES>::insertEdge(VertexType& e1, VertexType& e2, EdgeType& value)
572 {
573  dbgEdgeReturn ret;
574  ret.first = false;
575  dbgVertex vi1;
576  if(! searchVertex(e1, vi1) ) return ret;
577  dbgVertex vi2;
578  if(! searchVertex(e2, vi2) ) return ret;
579 
580  dbgEdge ei;
581  if ( ( !searchEdge(value, ei) ) ) {
582  std::pair<dbgEdge, bool> eres = add_edge( vi1, vi2, *this );
583  if(!eres.second) {
584  std::cerr << " add edge || failed!!! " << std::endl;
585  return ret;
586  }
587  put( boost::edge_dbg_data, *this, eres.first, value );
588  ei = eres.first;
589  //cerr << " added edge || " << get(vertex_index1, *this, boost::target(ei,*this))<<","<< get(vertex_index1, *this, boost::source(ei,*this)) << endl; // debug
590  //cerr << " for vertex |1 " << get(vertex_index1, *this, boost::target(ei,*this)) << " " << get(vertex_attribute, *this, boost::target(ei,*this))["label"] << endl; // debug
591  //cerr << " for vertex |2 " << get(vertex_index1, *this, boost::source(ei,*this)) << " " << get(vertex_attribute, *this, boost::source(ei,*this))["label"] << endl; // debug
592  }
593  ret.first = true;
594  ret.second = ei;
595  return ret;
596 }
597 
598 //-----------------------------------------------------------------------------
599 // destructor
601 {
602  // FIXME delete all nodes?
603 }
604 
605 
606 //-----------------------------------------------------------------------------
607 // set subgraph initialization information
609 {
610  mInitSubgraphs = true;
611  mSubgraphReferenceColumn = refcol;
612  mpSubgraphNameRowdata = rowdata;
613  mSubgraphNameColumn = namecol;
614 }
615 
616 
617 
618 
619 //-----------------------------------------------------------------------------
620 // remove all successor pointers from a node
622 {
623  dbgVertex srcVert;
624  if(!searchVertex( node, srcVert )) return false;
625  remove_out_edge_if( srcVert, always_true_pred(srcVert, *this), *this );
626  return true;
627 }
628 
630 template <typename Vertex, typename Graph>
632  always_true_predicate(Vertex u, const Graph& g) { }
633  template <class Edge>
634  bool operator()(const Edge& e) const {
635  return true;
636  }
637  };
638 template <typename Vertex, typename Graph>
640 always_true_pred(Vertex u, const Graph& g) {
642 }
643 
644 
645 
646 //-----------------------------------------------------------------------------
647 // write DOT graph to filename
649 {
650  std::ofstream fileout( filename.c_str() );
651 
652  dbgType *tG = dynamic_cast<dbgType *>( this );
653  write_graphviz( fileout, *this,
654  make_vertex_attributes_writer(*tG),
655  make_edge_attributes_writer(*tG),
656  make_graph_attributes_writer(*tG) );
657 
658  fileout.close();
659 }
660 
661 
662 //-----------------------------------------------------------------------------
663 // search for a specific node in the graph, using operator=, returns NULL if not found
664 
665 //template<class VertexType, class EdgeType>
667 {
669  tie(vi,vend) = vertices( *this );
670  for(; vi!=vend; vi++) {
671  if( get( boost::vertex_dbg_data, *this , *vi).get_id() == node.get_id() ) {
672  vdesc = *vi;
673  return true;
674  }
675  }
676  return false;
677 }
678 
679 
680 //-----------------------------------------------------------------------------
681 // search for a specific edge in the graph, using operator= on the id, returns NULL if not found
682 
683 //template<class VertexType, class EdgeType>
685 {
687  tie(ei,eend) = edges( *this );
688  // milki (06/23/2010) edge_iterators use preincrement
689  for(; ei!=eend; ++ei) {
690  if( get( boost::edge_dbg_data, *this , *ei).get_id() == edge.get_id() ) {
691  edesc = *ei;
692  return true;
693  }
694  }
695  return false;
696 }
697 
698 
699 
700 //-----------------------------------------------------------------------------
701 // check if there is an edge in the graph pointing to this node
702 //template<class VertexType, class EdgeType>
704 {
705  dbgVertex vi;
706  if(! searchVertex(node, vi) ) return false;
707 
709  tie(ii,iend) = in_edges(vi, *this );
710  if( ii == iend ) return false;
711  return true;
712 }
713 
714 
715 //-----------------------------------------------------------------------------
716 // check if there is an edge in the graph pointing to this node
717 //template<class VertexType, class EdgeType>
719 {
720  dbgVertex vi;
721  if(! searchVertex(node, vi) ) return false;
722 
723  //remove_edge_if( remove_node_pred(srcVert, *this), *this );
724  clear_vertex( vi, *this );
725  remove_vertex( vi, *this );
726  return true;
727 }
728 
730 /*template <typename Vertex, typename Graph>
731  struct remove_node_predicate {
732  remove_node_predicate(Vertex u, const Graph& g) : srcVert(u), G(g) { }
733  template <class Edge>
734  bool operator()(const Edge& e) const {
735  if( boost::source( e, G ) == srcVert ) return true;
736  if( boost::target( e, G ) == srcVert ) return true;
737  }
738  Vertex srcVert;
739  Graph G;
740  };
741 template <typename Vertex, typename Graph>
742 inline always_true_predicate<Vertex, Graph>
743 remove_nod_pred(Vertex u, const Graph& g) {
744  return always_true_predicate<Vertex, Graph>(u, g);
745 }*/
746 
747 
748 //-----------------------------------------------------------------------------
749 // get graph id (this function creates an graphdata entry, if the id is not retrieved by another function yet)
750 //template<class VertexType, class EdgeType>
752 {
753  if(mGraphId>0) return mGraphId;
754 
755  cgData dbg(mProjectId,mType);
756  dbg.insert(mpGDB);
757 
758  int gid = dbg.get_graphid();
759  assert( gid > 0);
760  mGraphId = gid;
761  return mGraphId;
762 }
763 
764 
765 //-----------------------------------------------------------------------------
766 // load graph from datbase
767 //template<class VertexType, class EdgeType>
769 {
770  int gid; // graph id for this graph
771  VertexType nodeinst; // an instance of the vertex type, this has to be a dbRow object
772  std::map<int,std::string> nodeNames; // get node names from graphnode table
773 
774  // we need a valid project id
775  if(!mProjectId) return 1;
776 
777  // get DB entry
778  gid = getGraphId();
779 
780  // get id's of referenced function entries
781  std::list<int> funcids;
782  bool showUncalledFunctions = true;
783 
784 
785  if(!showUncalledFunctions) {
786  // get only used functions
787  sqlite3x::sqlite3_command selectcmd(*mpGDB,
788  "SELECT DISTINCT sourceID FROM " + std::string(GRAPHEDGETBL) + " WHERE graphId = ? ORDER BY sourceID ASC;");
789  selectcmd.bind(1,gid);
790 
791  sqlite3x::sqlite3_reader r = selectcmd.executereader();
792 
793  while( r.read() )
794  funcids.push_back( r.getint(0) );
795 
796  sqlite3x::sqlite3_command selectcmd2(*mpGDB,
797  "SELECT DISTINCT targetId FROM " + std::string(GRAPHEDGETBL) + " WHERE graphId = ? ORDER BY targetId ASC;");
798  selectcmd2.bind(1,gid);
799 
800  sqlite3x::sqlite3_reader r2 = selectcmd2.executereader();
801 
802  int newid;
803  while( r.read() )
804  {
805  newid = r.getint(0);
806  std::list<int>::iterator fiditer =
807  std::find( funcids.begin(), funcids.end(), newid );
808  funcids.push_back( r.getint(0) );
809 
810  if(fiditer == funcids.end() )
811  funcids.push_back( newid );
812  }
813  // FIXME - get names?
814  assert( mNameColumn > 0 );
815  } else {
816 
817  // get all nodes in the graph
818  sqlite3x::sqlite3_command selectcmd(*mpGDB,
819  "SELECT DISTINCT nodeId,name FROM " + std::string(GRAPHNODETBL) + " WHERE graphId = ? ORDER BY nodeId ASC;");
820  selectcmd.bind(1,gid);
821 
822  sqlite3x::sqlite3_reader r = selectcmd.executereader();
823 
824  int newid;
825  while( r.read() )
826  {
827  newid = r.getint(0);
828  funcids.push_back( newid );
829  if(mNameColumn <= 0)
830  nodeNames[ newid ] = r.getstring(1);
831  }
832  }
833 
834  // init subgraphs if necessary
835  std::map<int, std::string> subgraphs;
836  if(mInitSubgraphs) {
837  assert( mpSubgraphNameRowdata );
838  assert( mSubgraphReferenceColumn >= 0 );
839  assert( mSubgraphNameColumn >= 0 );
840  assert( (int)mpSubgraphNameRowdata->getColumnNames().size() > mSubgraphNameColumn );
841  std::string fieldlist;
842  std::vector<std::string> fieldsSubgraphTable = mpSubgraphNameRowdata->getColumnNames();
843  std::vector<std::string> fieldsVertexTable = nodeinst.columnNames;
844  for(size_t i=0;i<fieldsSubgraphTable.size();i++) {
845  fieldlist += fieldsSubgraphTable[i];
846  if(i!=fieldsSubgraphTable.size()-1) fieldlist += ",";
847  }
848 
849  std::string recolname = fieldsVertexTable[ mSubgraphReferenceColumn ];
850 
851  sqlite3x::sqlite3_command selectcmd3(*mpGDB,
852  "SELECT DISTINCT " + recolname + " FROM " + nodeinst.name + ";");
853 
854  sqlite3x::sqlite3_reader r3 = selectcmd3.executereader();
855 
856  int sid;
857  int newid;
858 
859  sqlite3x::sqlite3_command selectcmd4(*mpGDB,
860  "SELECT " + fieldlist + " FROM " + nodeinst.name + " WHERE id=?;");
861  sqlite3x::sqlite3_reader r4;
862  while( r3.read() ) {
863  sid = r3.getint(0);
864  if( sid <= 0 )
865  continue;
866  selectcmd4.bind(1,sid);
867 
868  r4 = selectcmd4.executereader();
869  while( r4.read() ) {
870  newid = r4.getint(0);
871  funcids.push_back( newid );
872  if( mNameColumn <= 0 )
873  nodeNames[ newid ] = r4.getstring(1);
874  }
875  }
876  }
877 
878  // retrieve function entries, and add as nodes
879  for(std::list<int>::iterator i=funcids.begin();i!=funcids.end(); i++) {
880  //cout << " FIT " << (*i) << endl;
881  VertexType row;
882  int id = (*i);
883  sqlite3x::sqlite3_command selectcmd5(*mpGDB,
884  "SELECT " + row.field_list() + " FROM " + row.table() + " WHERE id=?;");
885  selectcmd5.bind(1,id);
886 
887  sqlite3x::sqlite3_reader r5 = selectcmd5.executereader();
888 
889  //assert( res->size() == 1);
890 
891  //cout << " X " << sqlrow[0] << " " << sqlrow[1] << " " << sqlrow[2] << endl;
892  std::string nodename;
893  if(mNameColumn>0) {
894  nodename = r5.getstring(mNameColumn); // get column with index mNameColumn from first sql row
895  } else {
896  nodename = nodeNames[ id ];
897  }
898 
899  // create boost vertex
900  typename boost::graph_traits< dbgType >::vertex_descriptor vdesc;
901  vdesc = add_vertex( *this );
902  put( boost::vertex_name, *this, vdesc, nodename );
903 
904  r5.read();
905  VertexType content(r5);
906  put( boost::vertex_dbg_data, *this, vdesc, content );
907  put( boost::vertex_index1, *this, vdesc, id );
908  get( boost::vertex_attribute, *this )[vdesc]["label"] = nodename;
909  if(mInitSubgraphs) {
910  // TODO
911  }
912  }
913 
914  sqlite3x::sqlite3_command selectcmd6(*mpGDB,
915  "SELECT * FROM " + std::string(GRAPHEDGETBL) + " WHERE graphId = ?;");
916  selectcmd6.bind(1,gid);
917 
918  sqlite3x::sqlite3_reader r6 = selectcmd6.executereader();
919 
920  cgEdge edge;
921  while( r6.read() ) {
922  edge.load(r6);
923  bool parFound = false, succFound = false;
925  tie(vi,vend) = vertices( *this );
926  typename boost::graph_traits< dbgType >::vertex_descriptor par=*vi, succ=*vi;
927 
928  for(; vi!=vend; vi++) {
929  //cout << " SRCH " << mNodes[j].value_list() << endl;
930  //if( C[j].first.get_id() == edges[i].get_sourceId() ) {
931  //gpar = C[j].first;
932  //}
933  if( get( boost::vertex_dbg_data, *this , *vi).get_id() == edge.get_sourceId() ) {
934  par = *vi;
935  parFound = true;
936  }
937  if( get( boost::vertex_dbg_data, *this , *vi).get_id() == edge.get_targetId() ) {
938  succ = *vi;
939  succFound = true;
940  }
941  //if( C[j].first.get_id() == edges[i].get_targetId() ) {
942  //succFound = true;
943  //}
944  }
945  if((!parFound)||(!succFound))
946  {
947  std::cout << " EDGE? from " << edge.get_sourceId() << " to "<< edge.get_targetId() << std::endl;
948  } // debug
949  assert( parFound );
950  assert( succFound );
951 
952  // store...
953  std::pair<dbgEdge, bool> eres = add_edge( par, succ, *this );
954  if(!eres.second) {
955  std::cerr << " add edge || failed!!! " << std::endl;
956  }
957  assert(eres.second);
958 
959  EdgeType row;
960  int id = edge.get_edgeId();
961  sqlite3x::sqlite3_command selectcmd7(*mpGDB,
962  "SELECT " + row.field_list() + " FROM " + row.table() +
963  " WHERE id=?;");
964  selectcmd7.bind(1,id);
965 
966  //assert( res->size() == 1);
967 
968  sqlite3x::sqlite3_reader r7 = selectcmd7.executereader();
969  r7.read();
970 
971  EdgeType content(r7);
972  put( boost::edge_dbg_data, *this, eres.first, content );
973  }
974  return 0;
975 }
976 
977 //-----------------------------------------------------------------------------
978 // store graph in datbase
979 //template<class VertexType, class EdgeType>
981 {
982  int gid; // graph id for this graph
983 
984  // we need a valid project id
985  if(!mProjectId) return 1;
986 
987  // get DB entry
988  gid = getGraphId();
989 
990  // clear all previous nodes
991  sqlite3x::sqlite3_command deletecmd(*mpGDB,
992  "DELETE FROM " + std::string(GRAPHNODETBL) + " WHERE graphId = ?;");
993  deletecmd.bind(1,gid);
994  deletecmd.executenonquery();
995 
996  // save node IDs
998  tie(vi,vend) = vertices( *this );
999  for(; vi!=vend; vi++) {
1000  cgNode node( gid,
1001  get( boost::vertex_dbg_data, *this, *vi).get_id(),
1002  get( boost::vertex_name, *this, *vi) );
1003  node.insert(mpGDB);
1004  }
1005 
1006 
1007  // clear all previous edges
1008  sqlite3x::sqlite3_command deletecmd2(*mpGDB,
1009  "DELETE FROM " + std::string(GRAPHEDGETBL) + " WHERE graphId = ?;");
1010  deletecmd2.bind(1,gid);
1011  deletecmd2.executenonquery();
1012 
1013  // save edges
1015  tie(ei,eend) = edges( *this );
1016  // milki (6/23/2010) edge_iterators use preincrement
1017  for(; ei!=eend; ++ei) {
1018  cgEdge edge(gid,
1019  get( boost::edge_dbg_data, *this, *ei ).get_id(),
1020  get( boost::vertex_dbg_data, *this, boost::source( *ei, *this ) ).get_id(),
1021  get( boost::vertex_dbg_data, *this, boost::target( *ei, *this ) ).get_id()
1022  );
1023  edge.insert(mpGDB);
1024  }
1025  return 0;
1026 }
1027 
1028 
1029 #endif