9 #ifndef SQLITE_DATABASEGRAPH_H
10 #define SQLITE_DATABASEGRAPH_H
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>
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
36 #define PROJECTSTBL "projects"
37 #define GRAPHDATATBL "graphData"
38 #define GRAPHNODETBL "graphNode"
39 #define GRAPHEDGETBL "graphEdge"
51 for( std::vector<std::string>::iterator it =
columnNames.begin();
54 return list.substr(0, list.size() - 2);
75 virtual void load(sqlite3x::sqlite3_reader& r)=0;
76 virtual void insert(sqlite3x::sqlite3_connection* db)=0;
98 void load(sqlite3x::sqlite3_reader& r)
101 name = r.getstring(1);
107 void insert(sqlite3x::sqlite3_connection* db)
109 sqlite3x::sqlite3_command selectcmd(*db,
110 "SELECT * FROM " + std::string(
PROJECTSTBL) +
" WHERE name=? AND CallgraphRootID=?;");
111 selectcmd.bind(1,
name);
114 sqlite3x::sqlite3_reader r = selectcmd.executereader();
120 sqlite3x::sqlite3_command insertcmd(*db,
121 "INSERT INTO " + std::string(
PROJECTSTBL) +
" (name,CallgraphRootID) VALUES (?,?);");
122 insertcmd.bind(1,
name);
124 insertcmd.executenonquery();
126 rowid = db->insertid();
152 void load(sqlite3x::sqlite3_reader& r)
161 void insert(sqlite3x::sqlite3_connection* db)
163 sqlite3x::sqlite3_command selectcmd(*db,
164 "SELECT * FROM " + std::string(
GRAPHDATATBL) +
" WHERE projectid=? AND graphType=?;");
168 sqlite3x::sqlite3_reader r = selectcmd.executereader();
174 sqlite3x::sqlite3_command insertcmd(*db,
175 "INSERT INTO " + std::string(
GRAPHDATATBL) +
" (projectid,graphType) VALUES (?,?);");
178 insertcmd.executenonquery();
180 rowid = db->insertid();
217 void load(sqlite3x::sqlite3_reader& r)
225 void insert(sqlite3x::sqlite3_connection* db)
227 sqlite3x::sqlite3_command selectcmd(*db,
228 "SELECT * FROM " + std::string(
GRAPHNODETBL) +
" WHERE graphId=? AND nodeId=? AND name=?;");
229 selectcmd.bind(1,
gid);
233 sqlite3x::sqlite3_reader r = selectcmd.executereader();
239 sqlite3x::sqlite3_command insertcmd(*db,
240 "INSERT INTO " + std::string(
GRAPHNODETBL) +
" (graphId,nodeId,name) VALUES (?,?,?);");
241 insertcmd.bind(1,
gid);
244 insertcmd.executenonquery();
246 rowid = db->insertid();
289 void load(sqlite3x::sqlite3_reader& r)
298 void insert(sqlite3x::sqlite3_connection* db)
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);
307 sqlite3x::sqlite3_reader r = selectcmd.executereader();
313 sqlite3x::sqlite3_command insertcmd(*db,
314 "INSERT INTO " + std::string(
GRAPHEDGETBL) +
" (graphId,edgeId,sourceId,targetId) VALUES (?,?,?,?);");
315 insertcmd.bind(1,
gid);
319 insertcmd.executenonquery();
321 rowid = db->insertid();
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)");
370 template<
class VertexType,
class EdgeType,
371 class BoostVertexList,
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>
393 typedef boost::adjacency_list<
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,
400 BoostVertexProperty > > > >,
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;
412 DatabaseGraph(
long pid,
long type, sqlite3x::sqlite3_connection *gdb );
489 sqlite3x::sqlite3_connection *
mpGDB;
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
522 mInitSubgraphs =
false;
531 if(searchVertex(e1, vdesc) ) {
534 vdesc = add_vertex( *
this );
536 put( boost::vertex_index1, *
this, vdesc, e1.get_id() );
538 put( boost::vertex_name, *
this, vdesc, name );
540 get( boost::vertex_attribute, *this )[vdesc][
"label"] = name;
552 if(searchVertex(e1, vdesc) ) {
555 vdesc = add_vertex( *
this );
557 put( boost::vertex_index1, *
this, vdesc, e1.get_id() );
560 put( boost::vertex_name, *
this, vdesc, name );
561 get( boost::vertex_attribute, *this )[vdesc][
"label"] = name;
576 if(! searchVertex(e1, vi1) )
return ret;
578 if(! searchVertex(e2, vi2) )
return ret;
581 if ( ( !searchEdge(value, ei) ) ) {
582 std::pair<dbgEdge, bool> eres = add_edge( vi1, vi2, *
this );
584 std::cerr <<
" add edge || failed!!! " << std::endl;
610 mInitSubgraphs =
true;
611 mSubgraphReferenceColumn = refcol;
612 mpSubgraphNameRowdata = rowdata;
613 mSubgraphNameColumn = namecol;
624 if(!searchVertex( node, srcVert ))
return false;
630 template <
typename Vertex,
typename Graph>
633 template <
class Edge>
638 template <
typename Vertex,
typename Graph>
650 std::ofstream fileout( filename.c_str() );
653 write_graphviz( fileout, *
this,
654 make_vertex_attributes_writer(*tG),
655 make_edge_attributes_writer(*tG),
656 make_graph_attributes_writer(*tG) );
669 tie(vi,vend) = vertices( *
this );
670 for(; vi!=vend; vi++) {
687 tie(ei,eend) = edges( *
this );
689 for(; ei!=eend; ++ei) {
706 if(! searchVertex(node, vi) )
return false;
709 tie(ii,iend) = in_edges(vi, *
this );
710 if( ii == iend )
return false;
721 if(! searchVertex(node, vi) )
return false;
724 clear_vertex( vi, *
this );
725 remove_vertex( vi, *
this );
753 if(mGraphId>0)
return mGraphId;
772 std::map<int,std::string> nodeNames;
775 if(!mProjectId)
return 1;
781 std::list<int> funcids;
782 bool showUncalledFunctions =
true;
785 if(!showUncalledFunctions) {
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);
791 sqlite3x::sqlite3_reader r = selectcmd.executereader();
794 funcids.push_back( r.getint(0) );
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);
800 sqlite3x::sqlite3_reader r2 = selectcmd2.executereader();
806 std::list<int>::iterator fiditer =
807 std::find( funcids.begin(), funcids.end(), newid );
808 funcids.push_back( r.getint(0) );
810 if(fiditer == funcids.end() )
811 funcids.push_back( newid );
814 assert( mNameColumn > 0 );
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);
822 sqlite3x::sqlite3_reader r = selectcmd.executereader();
828 funcids.push_back( newid );
830 nodeNames[ newid ] = r.getstring(1);
835 std::map<int, std::string> subgraphs;
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 +=
",";
849 std::string recolname = fieldsVertexTable[ mSubgraphReferenceColumn ];
851 sqlite3x::sqlite3_command selectcmd3(*mpGDB,
852 "SELECT DISTINCT " + recolname +
" FROM " + nodeinst.name +
";");
854 sqlite3x::sqlite3_reader r3 = selectcmd3.executereader();
859 sqlite3x::sqlite3_command selectcmd4(*mpGDB,
860 "SELECT " + fieldlist +
" FROM " + nodeinst.name +
" WHERE id=?;");
861 sqlite3x::sqlite3_reader r4;
866 selectcmd4.bind(1,sid);
868 r4 = selectcmd4.executereader();
870 newid = r4.getint(0);
871 funcids.push_back( newid );
872 if( mNameColumn <= 0 )
873 nodeNames[ newid ] = r4.getstring(1);
879 for(std::list<int>::iterator i=funcids.begin();i!=funcids.end(); i++) {
883 sqlite3x::sqlite3_command selectcmd5(*mpGDB,
884 "SELECT " + row.field_list() +
" FROM " + row.table() +
" WHERE id=?;");
885 selectcmd5.bind(1,
id);
887 sqlite3x::sqlite3_reader r5 = selectcmd5.executereader();
892 std::string nodename;
894 nodename = r5.getstring(mNameColumn);
896 nodename = nodeNames[ id ];
900 typename boost::graph_traits< dbgType >::vertex_descriptor vdesc;
901 vdesc = add_vertex( *
this );
902 put( boost::vertex_name, *
this, vdesc, nodename );
905 VertexType content(r5);
907 put( boost::vertex_index1, *
this, vdesc,
id );
908 get( boost::vertex_attribute, *this )[vdesc][
"label"] = nodename;
914 sqlite3x::sqlite3_command selectcmd6(*mpGDB,
915 "SELECT * FROM " + std::string(
GRAPHEDGETBL) +
" WHERE graphId = ?;");
916 selectcmd6.bind(1,gid);
918 sqlite3x::sqlite3_reader r6 = selectcmd6.executereader();
923 bool parFound =
false, succFound =
false;
925 tie(vi,vend) = vertices( *
this );
926 typename boost::graph_traits< dbgType >::vertex_descriptor par=*vi, succ=*vi;
928 for(; vi!=vend; vi++) {
945 if((!parFound)||(!succFound))
953 std::pair<dbgEdge, bool> eres = add_edge( par, succ, *
this );
955 std::cerr <<
" add edge || failed!!! " << std::endl;
961 sqlite3x::sqlite3_command selectcmd7(*mpGDB,
962 "SELECT " + row.field_list() +
" FROM " + row.table() +
964 selectcmd7.bind(1,
id);
968 sqlite3x::sqlite3_reader r7 = selectcmd7.executereader();
971 EdgeType content(r7);
985 if(!mProjectId)
return 1;
991 sqlite3x::sqlite3_command deletecmd(*mpGDB,
992 "DELETE FROM " + std::string(
GRAPHNODETBL) +
" WHERE graphId = ?;");
993 deletecmd.bind(1,gid);
994 deletecmd.executenonquery();
998 tie(vi,vend) = vertices( *
this );
999 for(; vi!=vend; vi++) {
1002 get( boost::vertex_name, *
this, *vi) );
1008 sqlite3x::sqlite3_command deletecmd2(*mpGDB,
1009 "DELETE FROM " + std::string(
GRAPHEDGETBL) +
" WHERE graphId = ?;");
1010 deletecmd2.bind(1,gid);
1011 deletecmd2.executenonquery();
1015 tie(ei,eend) = edges( *
this );
1017 for(; ei!=eend; ++ei) {