diff --git a/src/lib/data/SqliteStorage.cpp b/src/lib/data/SqliteStorage.cpp index 7a31ce97..78a05f49 100644 --- a/src/lib/data/SqliteStorage.cpp +++ b/src/lib/data/SqliteStorage.cpp @@ -3,6 +3,8 @@ #include "data/graph/Node.h" #include "data/location/TokenLocation.h" #include "utility/logging/logging.h" +#include "utility/utility.h" +#include "utility/utilityString.h" SqliteStorage::SqliteStorage(const std::string& dbFilePath) { @@ -240,52 +242,27 @@ StorageEdge SqliteStorage::getEdgeBySourceTargetType(Id sourceId, Id targetId, i std::vector SqliteStorage::getEdgesBySourceId(Id sourceId) const { - std::vector edges; + return getAllEdges("WHERE source_node_id == " + std::to_string(sourceId)); +} - CppSQLite3Query q = m_database.execQuery(( - "SELECT id, type, target_node_id FROM edge WHERE " - "source_node_id == " + std::to_string(sourceId) + ";" - ).c_str()); - - while (!q.eof()) - { - const Id id = q.getIntField(0, 0); - const int type = q.getIntField(1, -1); - const Id targetId = q.getIntField(2, 0); - - if (id != 0 && type != -1 && targetId != 0) - { - edges.push_back(StorageEdge(id, type, sourceId, targetId)); - } - - q.nextRow(); - } - return edges; +std::vector SqliteStorage::getEdgesBySourceIds(const std::vector& sourceIds) const +{ + return getAllEdges("WHERE source_node_id IN (" + utility::join(utility::toStrings(sourceIds), ',') + ")"); } std::vector SqliteStorage::getEdgesByTargetId(Id targetId) const { - std::vector edges; + return getAllEdges("WHERE target_node_id == " + std::to_string(targetId)); +} - CppSQLite3Query q = m_database.execQuery(( - "SELECT id, type, source_node_id FROM edge WHERE " - "target_node_id == " + std::to_string(targetId) + ";" - ).c_str()); +std::vector SqliteStorage::getEdgesByTargetIds(const std::vector& targetIds) const +{ + return getAllEdges("WHERE target_node_id IN (" + utility::join(utility::toStrings(targetIds), ',') + ")"); +} - while (!q.eof()) - { - const Id id = q.getIntField(0, 0); - const int type = q.getIntField(1, -1); - const Id sourceId = q.getIntField(2, 0); - - if (id != 0 && type != -1 && targetId != 0) - { - edges.push_back(StorageEdge(id, type, sourceId, targetId)); - } - - q.nextRow(); - } - return edges; +std::vector SqliteStorage::getEdgesBySourceOrTargetId(Id id) const +{ + return getAllEdges("WHERE source_node_id == " + std::to_string(id) + " OR target_node_id == " + std::to_string(id)); } std::vector SqliteStorage::getEdgesBySourceType(Id sourceId, int type) const @@ -626,13 +603,31 @@ StorageComponentAccess SqliteStorage::getComponentAccessByMemberEdgeId(Id member while (!q.eof()) { return StorageComponentAccess( - q.getIntField(0, 0), q.getIntField(1, 0), q.getIntField(2, 0) ); } - return StorageComponentAccess(0, 0, 0); + return StorageComponentAccess(0, 0); +} + +std::vector SqliteStorage::getComponentAccessByMemberEdgeIds(const std::vector& memberEdgeIds) const +{ + CppSQLite3Query q = m_database.execQuery(( + "SELECT id, edge_id, type FROM component_access WHERE edge_id IN (" + utility::join(utility::toStrings(memberEdgeIds), ',') + ");" + ).c_str()); + + std::vector accesses; + while (!q.eof()) + { + accesses.push_back(StorageComponentAccess( + q.getIntField(1, 0), + q.getIntField(2, 0) + )); + + q.nextRow(); + } + return accesses; } Id SqliteStorage::getNodeIdBySignature(const std::string& signature) const @@ -854,3 +849,27 @@ std::vector SqliteStorage::getAllSourceLocations(const st return sourceLocations; } + +std::vector SqliteStorage::getAllEdges(const std::string& query) const +{ + CppSQLite3Query q = m_database.execQuery(( + "SELECT id, type, source_node_id, target_node_id FROM edge " + query + ";" + ).c_str()); + + std::vector edges; + while (!q.eof()) + { + const Id id = q.getIntField(0, 0); + const int type = q.getIntField(1, -1); + const Id sourceId = q.getIntField(2, 0); + const Id targetId = q.getIntField(3, 0); + + if (id != 0 && type != -1) + { + edges.push_back(StorageEdge(id, type, sourceId, targetId)); + } + + q.nextRow(); + } + return edges; +} diff --git a/src/lib/data/SqliteStorage.h b/src/lib/data/SqliteStorage.h index 034be2e6..8ed8df99 100644 --- a/src/lib/data/SqliteStorage.h +++ b/src/lib/data/SqliteStorage.h @@ -50,7 +50,10 @@ public: StorageEdge getEdgeBySourceTargetType(Id sourceId, Id targetId, int type) const; std::vector getEdgesBySourceId(Id sourceId) const; + std::vector getEdgesBySourceIds(const std::vector& sourceIds) const; std::vector getEdgesByTargetId(Id targetId) const; + std::vector getEdgesByTargetIds(const std::vector& targetIds) const; + std::vector getEdgesBySourceOrTargetId(Id id) const; std::vector getEdgesBySourceType(Id sourceId, int type) const; std::vector getEdgesByTargetType(Id targetId, int type) const; StorageEdge getEdgeById(Id edgeId) const; @@ -81,6 +84,7 @@ public: Id getElementIdByLocationId(Id locationId) const; StorageComponentAccess getComponentAccessByMemberEdgeId(Id memberEdgeId) const; + std::vector getComponentAccessByMemberEdgeIds(const std::vector& memberEdgeIds) const; Id getNodeIdBySignature(const std::string& signature) const; int getNodeCount() const; @@ -96,6 +100,8 @@ private: StorageSourceLocation getFirstSourceLocation(const std::string& query) const; std::vector getAllSourceLocations(const std::string& query) const; + std::vector getAllEdges(const std::string& query) const; + template ResultType getFirstResult(const std::string& query) const; diff --git a/src/lib/data/Storage.cpp b/src/lib/data/Storage.cpp index b517b2c2..c9210143 100644 --- a/src/lib/data/Storage.cpp +++ b/src/lib/data/Storage.cpp @@ -722,8 +722,7 @@ std::shared_ptr Storage::getGraphForActiveTokenIds(const std::vector& ); std::cout << "add node and children " << a << std::endl; - std::vector edges = m_sqliteStorage.getEdgesBySourceId(node.id); - utility::append(edges, m_sqliteStorage.getEdgesByTargetId(node.id)); + std::vector edges = m_sqliteStorage.getEdgesBySourceOrTargetId(node.id); float b = utility::duration( [&]() @@ -771,21 +770,7 @@ std::shared_ptr Storage::getGraphForActiveTokenIds(const std::vector& } } - graph->forEachEdge( - [this](Edge* edge) - { - if (!edge->isType(Edge::EDGE_MEMBER)) - { - return; - } - - StorageComponentAccess access = m_sqliteStorage.getComponentAccessByMemberEdgeId(edge->getId()); - if (access.id && access.type) - { - edge->addComponentAccess(std::make_shared(TokenComponentAccess::intToType(access.type))); - } - } - ); + addComponentAccessToGraph(graph); return g; } @@ -1355,39 +1340,30 @@ void Storage::addAggregationEdgesToGraph(const Id nodeId, Graph* graph) const // build aggregation edges: // get all children of the active node - // get all edges of the children - // get all nodes connected by these edges - // remove all nodes that are in active node's children - // get all parents of these nodes (up to last level except namespace/undefined) - // add hierarchies for these parents - // create aggregation edges between parents and active node - std::vector childNodeIds = getAllChildNodeIds(nodeId, graph); + // get all edges of the children std::map> connectedNodeIds; - for (size_t i = 0; i < childNodeIds.size(); i++) + + std::vector outgoingEdges = m_sqliteStorage.getEdgesBySourceIds(childNodeIds); + for (size_t j = 0; j < outgoingEdges.size(); j++) { - const Id nodeId = childNodeIds[i]; - - std::vector outgoingEdges = m_sqliteStorage.getEdgesBySourceId(nodeId); - for (size_t j = 0; j < outgoingEdges.size(); j++) - { - EdgeInfo edgeInfo; - edgeInfo.edgeId = outgoingEdges[j].id; - edgeInfo.forward = true; - connectedNodeIds[outgoingEdges[j].targetNodeId].push_back(edgeInfo); - } - - std::vector incomingEdges = m_sqliteStorage.getEdgesByTargetId(nodeId); - for (size_t j = 0; j < incomingEdges.size(); j++) - { - EdgeInfo edgeInfo; - edgeInfo.edgeId = incomingEdges[j].id; - edgeInfo.forward = false; - connectedNodeIds[incomingEdges[j].sourceNodeId].push_back(edgeInfo); - } + EdgeInfo edgeInfo; + edgeInfo.edgeId = outgoingEdges[j].id; + edgeInfo.forward = true; + connectedNodeIds[outgoingEdges[j].targetNodeId].push_back(edgeInfo); } + std::vector incomingEdges = m_sqliteStorage.getEdgesByTargetIds(childNodeIds); + for (size_t j = 0; j < incomingEdges.size(); j++) + { + EdgeInfo edgeInfo; + edgeInfo.edgeId = incomingEdges[j].id; + edgeInfo.forward = false; + connectedNodeIds[incomingEdges[j].sourceNodeId].push_back(edgeInfo); + } + + // get all parent nodes of all connected nodes (up to last level except namespace/undefined) Id nodeParentNodeId = getLastVisibleParentNodeId(nodeId); std::map> connectedParentNodeIds; @@ -1401,6 +1377,7 @@ void Storage::addAggregationEdgesToGraph(const Id nodeId, Graph* graph) const } } + // add hierarchies for these parents and create aggregation edges between parents and active node Node* sourceNode = graph->getNodeById(nodeId); for (const std::pair> p : connectedParentNodeIds) @@ -1410,7 +1387,7 @@ void Storage::addAggregationEdgesToGraph(const Id nodeId, Graph* graph) const Node* targetNode = graph->getNodeById(aggregationTargetNodeId); if (!targetNode) { - targetNode = addNodeAndAllChildrenToGraph(getLastVisibleParentNodeId(aggregationTargetNodeId), graph); + targetNode = addNodeAndAllChildrenToGraph(aggregationTargetNodeId, graph); } std::shared_ptr componentAggregation = std::make_shared(); @@ -1479,3 +1456,30 @@ void Storage::addAccess(const Id nodeId, ParserClient::AccessType access) m_sqliteStorage.addComponentAccess(memberEdges[0].id, convertAccessType(access)); } + +void Storage::addComponentAccessToGraph(Graph* graph) const +{ + std::vector memberEdgeIds; + + graph->forEachEdge( + [&memberEdgeIds](Edge* edge) + { + if (!edge->isType(Edge::EDGE_MEMBER)) + { + return; + } + + memberEdgeIds.push_back(edge->getId()); + } + ); + + std::vector accesses = m_sqliteStorage.getComponentAccessByMemberEdgeIds(memberEdgeIds); + for (const StorageComponentAccess& access : accesses) + { + if (access.memberEdgeId && access.type) + { + graph->getEdgeById(access.memberEdgeId)->addComponentAccess( + std::make_shared(TokenComponentAccess::intToType(access.type))); + } + } +} diff --git a/src/lib/data/Storage.h b/src/lib/data/Storage.h index 6d6248f1..8aa1f6a2 100644 --- a/src/lib/data/Storage.h +++ b/src/lib/data/Storage.h @@ -174,6 +174,8 @@ private: TokenComponentAccess::AccessType convertAccessType(ParserClient::AccessType access) const; void addAccess(const Id nodeId, ParserClient::AccessType access); + void addComponentAccessToGraph(Graph* graph) const; + SearchIndex m_tokenIndex; SqliteStorage m_sqliteStorage; diff --git a/src/lib/data/StorageTypes.h b/src/lib/data/StorageTypes.h index af9fede0..afcc6a75 100644 --- a/src/lib/data/StorageTypes.h +++ b/src/lib/data/StorageTypes.h @@ -70,13 +70,11 @@ struct StorageSourceLocation struct StorageComponentAccess { - StorageComponentAccess(Id id, Id memberEdgeId, int type) - : id(id) - , memberEdgeId(memberEdgeId) + StorageComponentAccess(Id memberEdgeId, int type) + : memberEdgeId(memberEdgeId) , type(type) {} - Id id; Id memberEdgeId; int type; }; diff --git a/src/lib/utility/utility.h b/src/lib/utility/utility.h index a5b9fa28..117bc02e 100644 --- a/src/lib/utility/utility.h +++ b/src/lib/utility/utility.h @@ -33,6 +33,9 @@ namespace utility template std::vector toVector(const std::deque& d); + template + std::vector toStrings(const std::vector& d); + bool intersectionPoint(Vec2f a1, Vec2f b1, Vec2f a2, Vec2f b2, Vec2f* i); size_t digits(size_t n); @@ -67,4 +70,15 @@ std::vector utility::toVector(const std::deque& d) return v; } +template +std::vector utility::toStrings(const std::vector& d) +{ + std::vector v; + for (const T& t : d) + { + v.push_back(std::to_string(t)); + } + return v; +} + #endif // UTILITY_H