From 2b24b88745772ee636485e9492ee96f44ca93a9c Mon Sep 17 00:00:00 2001 From: malte_langkabel Date: Mon, 17 Apr 2017 10:55:59 +0200 Subject: [PATCH] data: bookmark refactoring * implemented handling of aggregations in bookmarks * split index Storage and bookmark storage * each sqlite database has its own version now * added bookmark tests * fixed creating bookmark tables when project can be loaded but bookmark db does not exist * fixed font size for bookmarkview tooltips * using bookmark cache now * using default category name when none specified by the user * raising bookmark windows when they should be shown * clearing a bookmark or category in the editor will now update the star icon accordingly * non-persistent bookmarks use ids of nodes and edges now (instead of names) * git ignore .srctrlbm files --- .gitignore | 1 + .../data/gui/bookmark_view/bookmark_view.css | 5 - src/lib/Application.cpp | 9 +- src/lib/CMakeLists.txt | 10 +- src/lib/component/ComponentManager.cpp | 4 +- .../controller/BookmarkController.cpp | 596 ++---- .../component/controller/BookmarkController.h | 64 +- src/lib/component/view/BookmarkView.cpp | 6 +- src/lib/data/PersistentStorage.cpp | 444 ++-- src/lib/data/PersistentStorage.h | 31 +- src/lib/data/SqliteBookmarkStorage.cpp | 329 +++ src/lib/data/SqliteBookmarkStorage.h | 72 + src/lib/data/SqliteDatabaseIndex.cpp | 25 + src/lib/data/SqliteDatabaseIndex.h | 21 + src/lib/data/SqliteIndex.cpp | 25 - src/lib/data/SqliteIndex.h | 21 - src/lib/data/SqliteIndexStorage.cpp | 1169 +++++++++++ src/lib/data/SqliteIndexStorage.h | 176 ++ src/lib/data/SqliteStorage.cpp | 1815 +---------------- src/lib/data/SqliteStorage.h | 206 +- src/lib/data/StorageTypes.h | 112 + src/lib/data/TaskCleanStorage.cpp | 2 +- src/lib/data/TaskFinishParsing.cpp | 2 +- src/lib/data/access/StorageAccess.h | 22 +- src/lib/data/access/StorageAccessProxy.cpp | 118 +- src/lib/data/access/StorageAccessProxy.h | 18 +- src/lib/data/bookmark/Bookmark.cpp | 92 +- src/lib/data/bookmark/Bookmark.h | 35 +- src/lib/data/bookmark/BookmarkCategory.cpp | 8 +- src/lib/data/bookmark/BookmarkCategory.h | 3 +- src/lib/data/bookmark/EdgeBookmark.cpp | 44 +- src/lib/data/bookmark/EdgeBookmark.h | 29 +- src/lib/data/bookmark/NodeBookmark.cpp | 26 +- src/lib/data/bookmark/NodeBookmark.h | 10 +- src/lib/data/parser/TaskParseWrapper.cpp | 2 +- src/lib/project/Project.cpp | 7 +- .../messaging/type/MessageDeleteBookmark.h | 6 +- .../type/MessageDeleteBookmarkCategory.h | 28 + ...ssageDeleteBookmarkCategoryWithBookmarks.h | 28 - src/lib_gui/qt/element/QtBookmark.cpp | 47 +- src/lib_gui/qt/element/QtBookmarkBar.cpp | 7 +- src/lib_gui/qt/element/QtBookmarkCategory.cpp | 4 +- src/lib_gui/qt/window/QtBookmarkBrowser.cpp | 12 +- src/test/CMakeLists.txt | 3 +- src/test/SqliteBookmarkStorageTestSuite.h | 111 + ...tSuite.h => SqliteIndexStorageTestSuite.h} | 12 +- src/test/StorageTestSuite.h | 2 +- src/test/readme.txt | 18 + 48 files changed, 2856 insertions(+), 2981 deletions(-) create mode 100644 src/lib/data/SqliteBookmarkStorage.cpp create mode 100644 src/lib/data/SqliteBookmarkStorage.h create mode 100644 src/lib/data/SqliteDatabaseIndex.cpp create mode 100644 src/lib/data/SqliteDatabaseIndex.h delete mode 100644 src/lib/data/SqliteIndex.cpp delete mode 100644 src/lib/data/SqliteIndex.h create mode 100644 src/lib/data/SqliteIndexStorage.cpp create mode 100644 src/lib/data/SqliteIndexStorage.h create mode 100644 src/lib/utility/messaging/type/MessageDeleteBookmarkCategory.h delete mode 100644 src/lib/utility/messaging/type/MessageDeleteBookmarkCategoryWithBookmarks.h create mode 100644 src/test/SqliteBookmarkStorageTestSuite.h rename src/test/{SqliteStorageTestSuite.h => SqliteIndexStorageTestSuite.h} (87%) create mode 100644 src/test/readme.txt diff --git a/.gitignore b/.gitignore index a42f3ad9..f281f8c3 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ *.coatidb *.srctrldb +*.srctrlbm *.suo *.vcxproj.user *.sqlite diff --git a/bin/app/data/gui/bookmark_view/bookmark_view.css b/bin/app/data/gui/bookmark_view/bookmark_view.css index 6d26e285..d259784f 100644 --- a/bin/app/data/gui/bookmark_view/bookmark_view.css +++ b/bin/app/data/gui/bookmark_view/bookmark_view.css @@ -1,8 +1,3 @@ -/* General settings */ -* { - font-size: 16px; -} - /* Bookmark browser header */ #header_background { diff --git a/src/lib/Application.cpp b/src/lib/Application.cpp index fe020fbd..275eb598 100644 --- a/src/lib/Application.cpp +++ b/src/lib/Application.cpp @@ -169,10 +169,15 @@ void Application::createAndLoadProject(const FilePath& projectSettingsFilePath) MessageStatus("Failed to load project: " + projectSettingsFilePath.str(), true).dispatch(); } } + catch (std::exception& e) + { + LOG_ERROR_STREAM(<< "Failed to load project, exception thrown: " << e.what()); + MessageStatus("Failed to load project, exception was thrown: " + projectSettingsFilePath.str(), true).dispatch(); + } catch (...) { - LOG_ERROR_STREAM(<< "Failed to load project, exception thrown."); - MessageStatus("Failed to load project, exception was thrown: " + projectSettingsFilePath.str(), true).dispatch(); + LOG_ERROR_STREAM(<< "Failed to load project, unknown exception thrown."); + MessageStatus("Failed to load project, unknown exception was thrown: " + projectSettingsFilePath.str(), true).dispatch(); } if (m_hasGUI) diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index a7c3941e..4d3456c1 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -199,8 +199,12 @@ add_files( data/IntermediateStorage.h data/PersistentStorage.cpp data/PersistentStorage.h - data/SqliteIndex.cpp - data/SqliteIndex.h + data/SqliteBookmarkStorage.cpp + data/SqliteBookmarkStorage.h + data/SqliteDatabaseIndex.cpp + data/SqliteDatabaseIndex.h + data/SqliteIndexStorage.cpp + data/SqliteIndexStorage.h data/SqliteStorage.cpp data/SqliteStorage.h data/Storage.cpp @@ -335,7 +339,7 @@ add_files( utility/messaging/type/MessageCreateBookmarkCategory.h utility/messaging/type/MessageDeactivateEdge.h utility/messaging/type/MessageDeleteBookmark.h - utility/messaging/type/MessageDeleteBookmarkCategoryWithBookmarks.h + utility/messaging/type/MessageDeleteBookmarkCategory.h utility/messaging/type/MessageDeleteBookmarkForActiveTokens.h utility/messaging/type/MessageDispatchWhenLicenseValid.h utility/messaging/type/MessageDisplayBookmarkCreator.h diff --git a/src/lib/component/ComponentManager.cpp b/src/lib/component/ComponentManager.cpp index e53b9f82..aed46853 100644 --- a/src/lib/component/ComponentManager.cpp +++ b/src/lib/component/ComponentManager.cpp @@ -33,8 +33,8 @@ void ComponentManager::setup(ViewLayout* viewLayout) m_componentFactory->getViewFactory()->createCompositeView(viewLayout, CompositeView::DIRECTION_HORIZONTAL, "Search"); m_compositeViews.push_back(compositeView); - // std::shared_ptr bookmarkComponent = m_componentFactory->createBookmarkComponent(compositeView.get()); - // m_components.push_back(bookmarkComponent); + std::shared_ptr bookmarkComponent = m_componentFactory->createBookmarkComponent(compositeView.get()); + m_components.push_back(bookmarkComponent); std::shared_ptr undoRedoComponent = m_componentFactory->createUndoRedoComponent(compositeView.get()); m_components.push_back(undoRedoComponent); diff --git a/src/lib/component/controller/BookmarkController.cpp b/src/lib/component/controller/BookmarkController.cpp index 16d5ee1a..f0bf0c26 100644 --- a/src/lib/component/controller/BookmarkController.cpp +++ b/src/lib/component/controller/BookmarkController.cpp @@ -7,26 +7,22 @@ #include "utility/messaging/type/MessageActivateEdge.h" #include "utility/messaging/type/MessageActivateNodes.h" +#include "utility/Cache.h" #include "utility/logging/logging.h" #include "utility/utilityString.h" +#include "utility/utility.h" #include "data/bookmark/EdgeBookmark.h" #include "data/bookmark/NodeBookmark.h" -const std::string BookmarkController::m_edgeSeperatorToken = "=>"; +const std::string BookmarkController::s_edgeSeperatorToken = "=>"; +const std::string BookmarkController::s_defaultCategoryName = "Default Bookmark Category"; BookmarkController::BookmarkController(StorageAccess* storageAccess) : m_storageAccess(storageAccess) - , m_activeTokens() - , m_activeTokenNames() - , m_activeTokenDisplayNames() - , m_activeTokenTypes() - , m_activeEdges() - , m_activeEdgeNames() - , m_activeEdgeDisplayNames() - , m_activeEdgeTypes() - , m_activeTokenExists(false) + , m_bookmarkCache(storageAccess) + , m_hasBookmarkForActiveToken(false) { } @@ -38,89 +34,28 @@ void BookmarkController::clear() { } -std::vector> BookmarkController::getAllBookmarks() const -{ - LOG_INFO_STREAM(<< "Retrieving all bookmarks"); - - std::vector> bookmarks; - - std::vector nodeBookmarks = m_storageAccess->getAllNodeBookmarks(); - - for (unsigned int i = 0; i < nodeBookmarks.size(); i++) - { - bookmarks.push_back(std::make_shared(nodeBookmarks[i])); - } - - std::vector edgeBookmarks = m_storageAccess->getAllEdgeBookmarks(); - - for (unsigned int i = 0; i < edgeBookmarks.size(); i++) - { - bookmarks.push_back(std::make_shared(edgeBookmarks[i])); - } - - // std::vector bookmarks = m_storageAccess->getAllBookmarks(); - - // check whether bookmarks are still valid (so, no referenced tokens have been removed) - for (unsigned int i = 0; i < bookmarks.size(); i++) - { - for (unsigned int j = 0; j < bookmarks[i]->getTokenNames().size(); j++) - { - std::string name = bookmarks[i]->getTokenNames()[j]; - int type = bookmarks[i]->getTokenTypes()[j]; - - bool exists = false; - - if (dynamic_cast(bookmarks[i].get()) != NULL) - { - TempEdge tmpEdge = getEdge(name, type); - - exists = m_storageAccess->checkEdgeExists(tmpEdge.edgeId); - } - else - { - exists = m_storageAccess->checkNodeExistsByName(name); - } - - std::vector tokenIds = bookmarks[i]->getTokenIds(); - - bookmarks[i]->setValid(exists); - } - } - - - - return bookmarks; -} - std::vector> BookmarkController::getBookmarks(const MessageDisplayBookmarks::BookmarkFilter& filter, const MessageDisplayBookmarks::BookmarkOrder& order) const { - LOG_INFO_STREAM(<< "Retrieving bookmarks with filter '" << std::to_string(filter) << "' and order '" << std::to_string(order) << "'"); + LOG_INFO_STREAM(<< "Retrieving bookmarks with filter \"" << std::to_string(filter) << "\" and order \"" << std::to_string(order) << "\""); std::vector> bookmarks = getAllBookmarks(); - int bookmarkCount = bookmarks.size(); bookmarks = getFilteredBookmarks(bookmarks, filter); - bookmarkCount = bookmarks.size(); bookmarks = getOrderedBookmarks(bookmarks, order); return bookmarks; } -std::vector BookmarkController::getActiveTokenNames() const -{ - return m_activeTokenNames; -} - std::vector BookmarkController::getActiveTokenDisplayNames() const { - if (m_activeEdgeDisplayNames.size() > 0) + if (m_activeEdgeIds.size() > 0) { - return m_activeEdgeDisplayNames; + return getActiveEdgeDisplayNames(); } else { - return m_activeTokenDisplayNames; + return getActiveNodeDisplayNames(); } } @@ -129,82 +64,112 @@ std::vector BookmarkController::getAllBookmarkCategories() con return m_storageAccess->getAllBookmarkCategories(); } -bool BookmarkController::activeTokenExists() const +bool BookmarkController::hasBookmarkForActiveToken() const { - return m_activeTokenExists; + return m_hasBookmarkForActiveToken; } std::shared_ptr BookmarkController::getBookmarkForActiveToken() const { - if (m_activeEdgeNames.size() > 0) + if (!m_activeEdgeIds.empty()) { - std::vector bookmarks = m_storageAccess->getAllEdgeBookmarks(); - - for (unsigned int i = 0; i < bookmarks.size(); i++) + for (std::shared_ptr edgeBookmark: getAllEdgeBookmarks()) { - if (bookmarks[i].getTokenNames() == m_activeEdgeNames) + if (!m_activeNodeIds.empty() && edgeBookmark->getActiveNodeId() == m_activeNodeIds.front() && utility::isPermutation(edgeBookmark->getEdgeIds(), m_activeEdgeIds)) { - return std::make_shared(bookmarks[i]); + return std::make_shared(*(edgeBookmark.get())); } } } else { - std::vector bookmarks = m_storageAccess->getAllNodeBookmarks(); - - for (unsigned int i = 0; i < bookmarks.size(); i++) + for (std::shared_ptr nodeBookmark: getAllNodeBookmarks()) { - if (bookmarks[i].getTokenNames() == m_activeTokenNames) + if (utility::isPermutation(nodeBookmark->getNodeIds(), m_activeNodeIds)) { - return std::make_shared(bookmarks[i]); + return std::make_shared(*(nodeBookmark.get())); } } } - return NULL; + return std::shared_ptr(); +} + +BookmarkController::BookmarkCache::BookmarkCache(StorageAccess* storageAccess) + : m_storageAccess(storageAccess) +{ +} + +void BookmarkController::BookmarkCache::clear() +{ + m_nodeBookmarksValid = false; + m_edgeBookmarksValid = false; +} + +std::vector BookmarkController::BookmarkCache::getAllNodeBookmarks() +{ + if (!m_nodeBookmarksValid) + { + m_nodeBookmarks = m_storageAccess->getAllNodeBookmarks(); + m_nodeBookmarksValid = true; + } + return m_nodeBookmarks; +} + +std::vector BookmarkController::BookmarkCache::getAllEdgeBookmarks() +{ + if (!m_edgeBookmarksValid) + { + m_edgeBookmarks = m_storageAccess->getAllEdgeBookmarks(); + m_edgeBookmarksValid = true; + } + return m_edgeBookmarks; } void BookmarkController::handleMessage(MessageActivateBookmark* message) { LOG_INFO_STREAM(<< "Attempting to activate Bookmark"); - if (dynamic_cast(message->bookmark.get()) != NULL) + if (std::shared_ptr bookmark = std::dynamic_pointer_cast(message->bookmark)) { - EdgeBookmark* bookmark = dynamic_cast(message->bookmark.get()); - - NodeBookmark baseBookmark = bookmark->getBaseBookmark(); - MessageActivateNodes activateNodes; - - for (unsigned int i = 0; i < baseBookmark.getTokenNames().size(); i++) - { - NameHierarchy nh = NameHierarchy::deserialize(baseBookmark.getTokenNames()[i]); - activateNodes.addNode(0, nh); - } - + activateNodes.addNode(bookmark->getActiveNodeId(), NameHierarchy()); activateNodes.dispatch(); - NameHierarchy source; - NameHierarchy target; - for (unsigned int i = 0; i < bookmark->getTokenNames().size(); i++) + if (!bookmark->getEdgeIds().empty()) { - int tokenType = bookmark->getTokenTypes()[i]; - TempEdge tmpEdge = getEdge(bookmark->getTokenNames()[i], tokenType); + const Id firstEdgeId = bookmark->getEdgeIds().front(); + const StorageEdge storageEdge = m_storageAccess->getEdgeById(firstEdgeId); - MessageActivateEdge activateEdge(tmpEdge.edgeId, Edge::intToType(tokenType), tmpEdge.source, tmpEdge.target); - activateEdge.dispatch(); + const NameHierarchy sourceName = m_storageAccess->getNameHierarchyForNodeId(storageEdge.sourceNodeId); + const NameHierarchy targetName = m_storageAccess->getNameHierarchyForNodeId(storageEdge.targetNodeId); + + if (bookmark->getEdgeIds().size() == 1) + { + MessageActivateEdge(firstEdgeId, Edge::intToType(storageEdge.type), sourceName, targetName).dispatch(); + } + else + { + MessageActivateEdge activateEdge(0, Edge::EdgeType::EDGE_AGGREGATION, sourceName, targetName); + for (const Id aggregatedEdgeId: bookmark->getEdgeIds()) + { + activateEdge.aggregationIds.push_back(aggregatedEdgeId); + } + activateEdge.dispatch(); + } + } + else + { + LOG_ERROR_STREAM(<< "Failed to activate bookmark, did not find edges to activate"); } } - else + else if (std::shared_ptr bookmark = std::dynamic_pointer_cast(message->bookmark)) { - NodeBookmark* bookmark = dynamic_cast(message->bookmark.get()); - MessageActivateNodes activateNodes; - for (unsigned int i = 0; i < bookmark->getTokenNames().size(); i++) + for (Id nodeId: bookmark->getNodeIds()) { - NameHierarchy nh = NameHierarchy::deserialize(bookmark->getTokenNames()[i]); - activateNodes.addNode(0, nh); + activateNodes.addNode(nodeId, NameHierarchy()); } activateNodes.dispatch(); @@ -215,73 +180,37 @@ void BookmarkController::handleMessage(MessageActivateTokens* message) { LOG_INFO_STREAM(<< "Registering new active token"); - if (message->isEdge) + m_activeEdgeIds.clear(); + + if (message->isEdge || message->isAggregation) { - LOG_INFO_STREAM(<< "Registering new Edge"); + m_activeEdgeIds = message->tokenIds; - std::vector tokenNames; - std::vector tokenDisplayNames; - std::vector tokenTypes; - - for (unsigned int i = 0; i < message->tokenIds.size(); i++) + if (getBookmarkForActiveToken()) { - StorageEdge edge = m_storageAccess->getEdgeById(message->tokenIds[i]); - - int typeId = edge.type; - - tokenTypes.push_back(typeId); - - NameHierarchy sourceHierarchy = m_storageAccess->getNameHierarchyForNodeId(edge.sourceNodeId); - NameHierarchy targetHierarchy = m_storageAccess->getNameHierarchyForNodeId(edge.targetNodeId); - - std::string sourceNode = NameHierarchy::serialize(sourceHierarchy); - std::string targetNode = NameHierarchy::serialize(targetHierarchy); - - std::string tokenName = sourceNode + m_edgeSeperatorToken + targetNode; - - tokenNames.push_back(tokenName); - - tokenDisplayNames.push_back(sourceHierarchy.getRawName() + m_edgeSeperatorToken + targetHierarchy.getRawName()); - } - - m_activeEdges = message->tokenIds; - m_activeEdgeNames = tokenNames; - m_activeEdgeTypes = tokenTypes; - m_activeEdgeDisplayNames = tokenDisplayNames; - - if (m_storageAccess->checkEdgeBookmarkExistsByTokens(tokenNames)) - { - m_activeTokenExists = true; + m_hasBookmarkForActiveToken = true; getView()->setCreateButtonState(BookmarkView::CreateButtonState::ALREADY_CREATED); } else { - m_activeTokenExists = false; + m_hasBookmarkForActiveToken = false; getView()->setCreateButtonState(BookmarkView::CreateButtonState::CAN_CREATE); } } - else + else if(!message->isEdge) { LOG_INFO_STREAM(<< "Registering new Node"); - m_activeTokens = message->tokenIds; - m_activeTokenNames = getTokenNames(m_activeTokens); - m_activeTokenTypes = getTokenTypes(m_activeTokens); - m_activeTokenDisplayNames = getTokenDisplayNames(m_activeTokens); + m_activeNodeIds = message->tokenIds; - m_activeEdges.clear(); - m_activeEdgeNames.clear(); - m_activeEdgeTypes.clear(); - m_activeEdgeDisplayNames.clear(); - - if (m_storageAccess->checkNodeBookmarkExistsByTokens(m_activeTokenNames)) + if (getBookmarkForActiveToken()) { - m_activeTokenExists = true; + m_hasBookmarkForActiveToken = true; getView()->setCreateButtonState(BookmarkView::CreateButtonState::ALREADY_CREATED); } else { - m_activeTokenExists = false; + m_hasBookmarkForActiveToken = false; getView()->setCreateButtonState(BookmarkView::CreateButtonState::CAN_CREATE); } } @@ -291,157 +220,116 @@ void BookmarkController::handleMessage(MessageCreateBookmark* message) { LOG_INFO_STREAM(<< "Attempting to create new bookmark"); - if (m_activeTokens.size() > 0) + BookmarkCategory category(0, message->categoryName.empty() ? s_defaultCategoryName : message->categoryName); + + if (!m_activeEdgeIds.empty()) { - if (m_activeEdges.size() > 0) + LOG_INFO_STREAM(<< "Creating Edge Bookmark"); + + std::string displayName = message->displayName; + if (displayName.empty()) { - LOG_INFO_STREAM(<< "Creating Edge Bookmark"); - - std::string displayName = message->displayName; - if (displayName.size() <= 0) + std::vector activeEdgeDisplayNames = getActiveEdgeDisplayNames(); + if (!activeEdgeDisplayNames.empty()) { - displayName = getDisplayName(m_activeTokens[0]); + displayName = activeEdgeDisplayNames.front(); } + } - EdgeBookmark bookmark(displayName, m_activeTokens, m_activeTokenNames, message->comment, TimePoint::now()); + EdgeBookmark bookmark(0, displayName, message->comment, TimePoint::now(), category); + bookmark.setEdgeIds(m_activeEdgeIds); - bookmark.setDisplayName(message->displayName); - bookmark.setComment(message->comment); - bookmark.setTokenTypes(m_activeTokenTypes); - - BookmarkCategory category; - category.setName(message->categoryName); - - bookmark.setCategory(category); - - bookmark.setEdgeTokenIds(m_activeEdges); - bookmark.setEdgeTokenNames(m_activeEdgeNames); - bookmark.setEdgeTokenTypes(m_activeEdgeTypes); - - Id id = m_storageAccess->addEdgeBookmark(bookmark); - - bookmark.setId(id); - - m_activeTokenExists = true; - getView()->setCreateButtonState(BookmarkView::CreateButtonState::ALREADY_CREATED); - getView()->update(); + if (!m_activeNodeIds.empty()) + { + bookmark.setActiveNodeId(m_activeNodeIds.front()); } else { - LOG_INFO_STREAM(<< "Creating Node Bookmark"); - - std::string displayName = message->displayName; - if (displayName.size() <= 0) - { - displayName = getDisplayName(m_activeTokens[0]); - } - - NodeBookmark bookmark(displayName, m_activeTokens, m_activeTokenNames, message->comment, TimePoint::now()); - - bookmark.setTokenTypes(m_activeTokenTypes); - - BookmarkCategory category; - category.setName(message->categoryName); - - bookmark.setCategory(category); - - Id id = m_storageAccess->addNodeBookmark(bookmark); - - bookmark.setId(id); - - m_activeTokenExists = true; - getView()->setCreateButtonState(BookmarkView::CreateButtonState::ALREADY_CREATED); - getView()->update(); + LOG_ERROR("Cannot create bookmark for edge if no active node exists"); } + + const Id id = m_storageAccess->addEdgeBookmark(bookmark); + bookmark.setId(id); } + else + { + LOG_INFO_STREAM(<< "Creating Node Bookmark"); + + std::string displayName = message->displayName; + if (displayName.empty()) + { + std::vector activeNodeDisplayNames = getActiveNodeDisplayNames(); + if (!activeNodeDisplayNames.empty()) + { + displayName = activeNodeDisplayNames.front(); + } + } + + NodeBookmark bookmark(0, displayName, message->comment, TimePoint::now(), category); + bookmark.setNodeIds(m_activeNodeIds); + const Id id = m_storageAccess->addNodeBookmark(bookmark); + bookmark.setId(id); + } + + m_bookmarkCache.clear(); + + m_hasBookmarkForActiveToken = true; + getView()->setCreateButtonState(BookmarkView::CreateButtonState::ALREADY_CREATED); + getView()->update(); } void BookmarkController::handleMessage(MessageCreateBookmarkCategory* message) { - std::string categoryName = message->name; - LOG_INFO_STREAM(<< "Attempting to create new Bookmark category '" << categoryName << "'"); - - if (m_storageAccess->checkBookmarkCategoryExists(message->name) == false) - { - BookmarkCategory category; - category.setName(message->name); - - m_storageAccess->addBookmarkCategory(category); - } + const std::string& categoryName = message->name.empty() ? s_defaultCategoryName : message->name; + LOG_INFO_STREAM(<< "Attempting to create new Bookmark category \"" << categoryName << "\""); + m_storageAccess->addBookmarkCategory(categoryName); } void BookmarkController::handleMessage(MessageDeleteBookmark* message) { LOG_INFO_STREAM(<< "Attempting to delete Bookmark " << std::to_string(message->bookmarkId)); - if (message->isEdge) - { - m_storageAccess->removeEdgeBookmark(message->bookmarkId); - } - else - { - m_storageAccess->removeNodeBookmark(message->bookmarkId); - } + m_storageAccess->removeBookmark(message->bookmarkId); cleanBookmarkCategories(); + m_bookmarkCache.clear(); + + if (!getBookmarkForActiveToken()) + { + m_hasBookmarkForActiveToken = false; + getView()->setCreateButtonState(BookmarkView::CreateButtonState::CAN_CREATE); + } getView()->update(); } -void BookmarkController::handleMessage(MessageDeleteBookmarkCategoryWithBookmarks* message) +void BookmarkController::handleMessage(MessageDeleteBookmarkCategory* message) { - std::vector categories = m_storageAccess->getAllBookmarkCategories(); + m_storageAccess->removeBookmarkCategory(message->categoryId); - for (unsigned int i = 0; i < categories.size(); i++) + m_bookmarkCache.clear(); + + if (!getBookmarkForActiveToken()) { - if (categories[i].getId() == message->categoryId) - { - std::vector nodeBookmarks = m_storageAccess->getAllNodeBookmarks(); - for (unsigned int j = 0; j < nodeBookmarks.size(); j++) - { - if (nodeBookmarks[j].getCategory().getName() == categories[i].getName()) - { - m_storageAccess->removeNodeBookmark(nodeBookmarks[j].getId()); - } - } - - std::vector edgeBookmarks = m_storageAccess->getAllEdgeBookmarks(); - for (unsigned int j = 0; j < edgeBookmarks.size(); j++) - { - if (edgeBookmarks[j].getCategory().getName() == categories[i].getName()) - { - m_storageAccess->removeEdgeBookmark(edgeBookmarks[j].getId()); - } - } - - cleanBookmarkCategories(); - getView()->update(); - - return; - } + m_hasBookmarkForActiveToken = false; + getView()->setCreateButtonState(BookmarkView::CreateButtonState::CAN_CREATE); } + + getView()->update(); } void BookmarkController::handleMessage(MessageDeleteBookmarkForActiveTokens* message) { - std::shared_ptr bookmark = getBookmarkForActiveToken(); - - if (bookmark != NULL) + if (std::shared_ptr bookmark = getBookmarkForActiveToken()) { - LOG_INFO_STREAM(<< "Deleting bookmark " << bookmark->getDisplayName()); + LOG_INFO_STREAM(<< "Deleting bookmark " << bookmark->getName()); - if (dynamic_cast(bookmark.get()) != NULL) - { - m_storageAccess->removeEdgeBookmark(bookmark->getId()); - } - else if(dynamic_cast(bookmark.get()) != NULL) - { - m_storageAccess->removeNodeBookmark(bookmark->getId()); - } + m_storageAccess->removeBookmark(bookmark->getId()); cleanBookmarkCategories(); + m_bookmarkCache.clear(); - m_activeTokenExists = false; + m_hasBookmarkForActiveToken = false; getView()->setCreateButtonState(BookmarkView::CreateButtonState::CAN_CREATE); getView()->update(); } @@ -455,127 +343,88 @@ void BookmarkController::handleMessage(MessageEditBookmark* message) { LOG_INFO_STREAM(<< "Attempting to update Bookmark " << std::to_string(message->bookmarkId)); - if (message->isEdge) - { - EdgeBookmark bookmark = m_storageAccess->getEdgeBookmarkById(message->bookmarkId); + const std::string& categoryName = message->categoryName.empty() ? s_defaultCategoryName : message->categoryName; + m_storageAccess->updateBookmark(message->bookmarkId, message->displayName, message->comment, categoryName); - bookmark.setDisplayName(message->displayName); - bookmark.setComment(message->comment); - BookmarkCategory category; - category.setName(message->categoryName); - bookmark.setCategory(category); - - m_storageAccess->editEdgeBookmark(bookmark); - } - else - { - NodeBookmark bookmark = m_storageAccess->getNodeBookmarkById(message->bookmarkId); - - bookmark.setDisplayName(message->displayName); - bookmark.setComment(message->comment); - BookmarkCategory category; - category.setName(message->categoryName); - bookmark.setCategory(category); - - m_storageAccess->editNodeBookmark(bookmark); - } + cleanBookmarkCategories(); + m_bookmarkCache.clear(); getView()->update(); } void BookmarkController::handleMessage(MessageFinishedParsing* message) { + m_bookmarkCache.clear(); getView()->enableDisplayBookmarks(true); } -std::vector BookmarkController::getTokenNames(const std::vector& ids) const +std::vector> BookmarkController::getAllBookmarks() const { - std::vector names; + LOG_INFO_STREAM(<< "Retrieving all bookmarks"); - for (unsigned int i = 0; i < ids.size(); i++) + std::vector> bookmarks; + + for (std::shared_ptr nodeBookmark: getAllNodeBookmarks()) { - NameHierarchy nameHierarchy = m_storageAccess->getNameHierarchyForNodeId(ids[i]); - names.push_back(NameHierarchy::serialize(nameHierarchy)); + bookmarks.push_back(nodeBookmark); + } + for (std::shared_ptr edgeBookmark: getAllEdgeBookmarks()) + { + bookmarks.push_back(edgeBookmark); } - return names; + return bookmarks; } -std::vector BookmarkController::getTokenDisplayNames(const std::vector& ids) const +std::vector> BookmarkController::getAllNodeBookmarks() const +{ + std::vector> bookmarks; + for (const NodeBookmark& nodeBookmark: m_bookmarkCache.getAllNodeBookmarks()) + { + bookmarks.push_back(std::make_shared(nodeBookmark)); + } + return bookmarks; +} + +std::vector> BookmarkController::getAllEdgeBookmarks() const +{ + std::vector> bookmarks; + for (const EdgeBookmark& edgeBookmark: m_bookmarkCache.getAllEdgeBookmarks()) + { + bookmarks.push_back(std::make_shared(edgeBookmark)); + } + return bookmarks; +} + +std::vector BookmarkController::getActiveNodeDisplayNames() const { std::vector names; - - for (unsigned int i = 0; i < ids.size(); i++) + for (const NameHierarchy& nameHierarchy: m_storageAccess->getNameHierarchiesForNodeIds(m_activeNodeIds)) { - NameHierarchy nameHierarchy = m_storageAccess->getNameHierarchyForNodeId(ids[i]); names.push_back(nameHierarchy.getRawName()); } - return names; } -std::vector BookmarkController::getTokenTypes(const std::vector& ids) const +std::vector BookmarkController::getActiveEdgeDisplayNames() const { - std::vector types; - - for (unsigned int i = 0; i < ids.size(); i++) + std::vector activeEdgeDisplayNames; + for (Id activeEdgeId: m_activeEdgeIds) { - int type = m_storageAccess->getNodeTypeForNodeWithId(ids[i]); - types.push_back(type); + const StorageEdge activeEdge = m_storageAccess->getEdgeById(activeEdgeId); + const std::string sourceDisplayName = getNodeDisplayName(activeEdge.sourceNodeId); + const std::string targetDisplayName = getNodeDisplayName(activeEdge.targetNodeId); + activeEdgeDisplayNames.push_back(sourceDisplayName + s_edgeSeperatorToken + targetDisplayName); } - - return types; + return activeEdgeDisplayNames; } -std::string BookmarkController::getDisplayName(Id id) const +std::string BookmarkController::getNodeDisplayName(const Id nodeId) const { - NameHierarchy nameHierarchy = m_storageAccess->getNameHierarchyForNodeId(id); + NameHierarchy nameHierarchy = m_storageAccess->getNameHierarchyForNodeId(nodeId); return nameHierarchy.getRawName(); } -BookmarkController::TempEdge BookmarkController::getEdge(const std::string& tokenName, const int tokenType) const -{ - std::pair edgeTokens = seperateEdgeToken(tokenName); - - NameHierarchy source = NameHierarchy::deserialize(edgeTokens.first); - NameHierarchy target = NameHierarchy::deserialize(edgeTokens.second); - - Id edgeId = m_storageAccess->getIdForEdge(Edge::intToType(tokenType), source, target); - - TempEdge result; - - result.edgeId = edgeId; - result.source = source; - result.target = target; - result.type = tokenType; - - return result; -} - -std::pair BookmarkController::seperateEdgeToken(const std::string& token) const -{ - std::pair result; - - if (token.find(m_edgeSeperatorToken) != std::string::npos) - { - std::vector st = utility::splitToVector(token, m_edgeSeperatorToken); - - if (st.size() != 2) - { - LOG_ERROR_STREAM(<< "Invalid edge token found: " << token); - - return result; - } - else - { - result.first = st[0]; - result.second = st[1]; - } - } - - return result; -} - std::vector> BookmarkController::getFilteredBookmarks(const std::vector>& bookmarks, const MessageDisplayBookmarks::BookmarkFilter& filter) const { std::vector> result; @@ -586,27 +435,23 @@ std::vector> BookmarkController::getFilteredBookmarks( } else if (filter == MessageDisplayBookmarks::BookmarkFilter::NODES) { - for (unsigned int i = 0; i < bookmarks.size(); i++) + for (std::shared_ptr bookmark: bookmarks) { - if (dynamic_cast(bookmarks[i].get()) == NULL) + if (std::dynamic_pointer_cast(bookmark)) { - result.push_back(bookmarks[i]); + result.push_back(bookmark); } } - - return result; } else if (filter == MessageDisplayBookmarks::BookmarkFilter::EDGES) { - for (unsigned int i = 0; i < bookmarks.size(); i++) + for (std::shared_ptr bookmark: bookmarks) { - if (dynamic_cast(bookmarks[i].get()) != NULL) + if (std::dynamic_pointer_cast(bookmark)) { - result.push_back(bookmarks[i]); + result.push_back(bookmark); } } - - return result; } return result; @@ -668,11 +513,8 @@ void BookmarkController::cleanBookmarkCategories() { std::vector> bookmarks = getAllBookmarks(); - std::vector categories = getAllBookmarkCategories(); - - for (unsigned int i = 0; i < categories.size(); i++) + for (const BookmarkCategory& category: getAllBookmarkCategories()) { - BookmarkCategory category = categories[i]; bool used = false; for (unsigned int j = 0; j < bookmarks.size(); j++) @@ -698,8 +540,8 @@ bool BookmarkController::bookmarkDateCompare(const std::shared_ptr a, bool BookmarkController::bookmarkNameCompare(const std::shared_ptr a, const std::shared_ptr b) { - std::string aName = a->getDisplayName(); - std::string bName = b->getDisplayName(); + std::string aName = a->getName(); + std::string bName = b->getName(); aName = utility::toLowerCase(aName); bName = utility::toLowerCase(bName); @@ -720,4 +562,4 @@ bool BookmarkController::bookmarkNameCompare(const std::shared_ptr a, } return aName.length() < bName.length(); -} \ No newline at end of file +} diff --git a/src/lib/component/controller/BookmarkController.h b/src/lib/component/controller/BookmarkController.h index 0ec3aef0..c07c2758 100644 --- a/src/lib/component/controller/BookmarkController.h +++ b/src/lib/component/controller/BookmarkController.h @@ -2,15 +2,19 @@ #define BOOKMARK_CONTROLLER_H #include "data/bookmark/Bookmark.h" +#include "data/bookmark/NodeBookmark.h" +#include "data/bookmark/EdgeBookmark.h" #include "data/name/NameHierarchy.h" +#include "data/StorageTypes.h" #include "utility/messaging/MessageListener.h" #include "utility/messaging/type/MessageActivateBookmark.h" +#include "utility/messaging/type/MessageActivateEdge.h" #include "utility/messaging/type/MessageActivateTokens.h" #include "utility/messaging/type/MessageCreateBookmark.h" #include "utility/messaging/type/MessageCreateBookmarkCategory.h" #include "utility/messaging/type/MessageDeleteBookmark.h" -#include "utility/messaging/type/MessageDeleteBookmarkCategoryWithBookmarks.h" +#include "utility/messaging/type/MessageDeleteBookmarkCategory.h" #include "utility/messaging/type/MessageDeleteBookmarkForActiveTokens.h" #include "utility/messaging/type/MessageDisplayBookmarks.h" #include "utility/messaging/type/MessageEditBookmark.h" @@ -27,7 +31,7 @@ class BookmarkController , public MessageListener , public MessageListener , public MessageListener - , public MessageListener + , public MessageListener , public MessageListener , public MessageListener , public MessageListener @@ -38,23 +42,30 @@ public: virtual void clear(); - std::vector> getAllBookmarks() const; std::vector> getBookmarks(const MessageDisplayBookmarks::BookmarkFilter& filter, const MessageDisplayBookmarks::BookmarkOrder& order) const; - std::vector getActiveTokenNames() const; std::vector getActiveTokenDisplayNames() const; std::vector getAllBookmarkCategories() const; - bool activeTokenExists() const; - std::shared_ptr getBookmarkForActiveToken() const; // or null if no bookmark for that token exists + bool hasBookmarkForActiveToken() const; + std::shared_ptr getBookmarkForActiveToken() const; private: - struct TempEdge + class BookmarkCache { public: - Id edgeId; - NameHierarchy source; - NameHierarchy target; - int type; + BookmarkCache(StorageAccess* storageAccess); + + void clear(); + + std::vector getAllNodeBookmarks(); + std::vector getAllEdgeBookmarks(); + + private: + StorageAccess* m_storageAccess; + std::vector m_nodeBookmarks; + std::vector m_edgeBookmarks; + bool m_nodeBookmarksValid; + bool m_edgeBookmarksValid; }; virtual void handleMessage(MessageActivateBookmark* message); @@ -62,18 +73,18 @@ private: virtual void handleMessage(MessageCreateBookmark* message); virtual void handleMessage(MessageCreateBookmarkCategory* message); virtual void handleMessage(MessageDeleteBookmark* message); - virtual void handleMessage(MessageDeleteBookmarkCategoryWithBookmarks* message); + virtual void handleMessage(MessageDeleteBookmarkCategory* message); virtual void handleMessage(MessageDeleteBookmarkForActiveTokens* message); virtual void handleMessage(MessageEditBookmark* message); virtual void handleMessage(MessageFinishedParsing* message); - std::vector getTokenNames(const std::vector& ids) const; - std::vector getTokenDisplayNames(const std::vector& ids) const; - std::vector getTokenTypes(const std::vector& ids) const; - std::string getDisplayName(Id id) const; - TempEdge getEdge(const std::string& tokenName, const int tokenType) const; + std::vector> getAllBookmarks() const; + std::vector> getAllNodeBookmarks() const; + std::vector> getAllEdgeBookmarks() const; - std::pair seperateEdgeToken(const std::string& token) const; + std::vector getActiveNodeDisplayNames() const; + std::vector getActiveEdgeDisplayNames() const; + std::string getNodeDisplayName(const Id id) const; std::vector> getFilteredBookmarks(const std::vector>& bookmarks, const MessageDisplayBookmarks::BookmarkFilter& filter) const; std::vector> getOrderedBookmarks(const std::vector>& bookmarks, const MessageDisplayBookmarks::BookmarkOrder& order) const; @@ -85,20 +96,15 @@ private: static bool bookmarkDateCompare(const std::shared_ptr a, const std::shared_ptr b); static bool bookmarkNameCompare(const std::shared_ptr a, const std::shared_ptr b); - static const std::string m_edgeSeperatorToken; + static const std::string s_edgeSeperatorToken; + static const std::string s_defaultCategoryName; StorageAccess* m_storageAccess; - std::vector m_activeTokens; - std::vector m_activeTokenNames; - std::vector m_activeTokenDisplayNames; - std::vector m_activeTokenTypes; + mutable BookmarkCache m_bookmarkCache; - std::vector m_activeEdges; - std::vector m_activeEdgeNames; - std::vector m_activeEdgeDisplayNames; - std::vector m_activeEdgeTypes; - - bool m_activeTokenExists; + std::vector m_activeNodeIds; + std::vector m_activeEdgeIds; + bool m_hasBookmarkForActiveToken; }; #endif // BOOKMARK_CONTROLLER_H diff --git a/src/lib/component/view/BookmarkView.cpp b/src/lib/component/view/BookmarkView.cpp index 9bc99ace..35d049a6 100644 --- a/src/lib/component/view/BookmarkView.cpp +++ b/src/lib/component/view/BookmarkView.cpp @@ -48,7 +48,7 @@ void BookmarkView::handleMessage(MessageDisplayBookmarkCreator* message) { std::vector names = getController()->getActiveTokenDisplayNames(); - if (getController()->activeTokenExists()) + if (getController()->hasBookmarkForActiveToken()) { std::vector categories = getController()->getAllBookmarkCategories(); @@ -80,6 +80,6 @@ void BookmarkView::handleMessage(MessageDisplayBookmarkCreator* message) void BookmarkView::handleMessage(MessageDisplayBookmarkEditor* message) { std::vector categories = getController()->getAllBookmarkCategories(); - + displayBookmarkEditor(message->bookmark, categories); -} \ No newline at end of file +} diff --git a/src/lib/data/PersistentStorage.cpp b/src/lib/data/PersistentStorage.cpp index 04c981e4..c547bd0e 100644 --- a/src/lib/data/PersistentStorage.cpp +++ b/src/lib/data/PersistentStorage.cpp @@ -24,8 +24,9 @@ #include "data/location/SourceLocationFile.h" #include "data/parser/ParseLocation.h" -PersistentStorage::PersistentStorage(const FilePath& dbPath) - : m_sqliteStorage(dbPath) +PersistentStorage::PersistentStorage(const FilePath& dbPath, const FilePath& bookmarkPath) + : m_sqliteIndexStorage(dbPath) + , m_sqliteBookmarkStorage(bookmarkPath) { m_commandIndex.addNode(0, SearchMatch::getCommandName(SearchMatch::COMMAND_ALL)); m_commandIndex.addNode(0, SearchMatch::getCommandName(SearchMatch::COMMAND_ERROR)); @@ -39,18 +40,18 @@ PersistentStorage::~PersistentStorage() Id PersistentStorage::addNode(int type, const std::string& serializedName) { - const StorageNode storedNode = m_sqliteStorage.getNodeBySerializedName(serializedName); + const StorageNode storedNode = m_sqliteIndexStorage.getNodeBySerializedName(serializedName); Id id = storedNode.id; if (id == 0) { - id = m_sqliteStorage.addNode(type, serializedName); + id = m_sqliteIndexStorage.addNode(type, serializedName); } else { if (storedNode.type < type) { - m_sqliteStorage.setNodeType(type, id); + m_sqliteIndexStorage.setNodeType(type, id); } } @@ -59,41 +60,41 @@ Id PersistentStorage::addNode(int type, const std::string& serializedName) void PersistentStorage::addFile(const Id id, const std::string& filePath, const std::string& modificationTime, bool complete) { - StorageFile file = m_sqliteStorage.getFirstById(id); + StorageFile file = m_sqliteIndexStorage.getFirstById(id); if (file.id == 0) { - m_sqliteStorage.addFile(id, filePath, modificationTime, complete); + m_sqliteIndexStorage.addFile(id, filePath, modificationTime, complete); } else if (!file.complete && complete) { - m_sqliteStorage.setFileComplete(complete, id); + m_sqliteIndexStorage.setFileComplete(complete, id); } } void PersistentStorage::addSymbol(const Id id, int definitionKind) { - if (m_sqliteStorage.getFirstById(id).id == 0) + if (m_sqliteIndexStorage.getFirstById(id).id == 0) { - m_sqliteStorage.addSymbol(id, definitionKind); + m_sqliteIndexStorage.addSymbol(id, definitionKind); } } Id PersistentStorage::addEdge(int type, Id sourceId, Id targetId) { - Id edgeId = m_sqliteStorage.getEdgeBySourceTargetType(sourceId, targetId, type).id; + Id edgeId = m_sqliteIndexStorage.getEdgeBySourceTargetType(sourceId, targetId, type).id; if (edgeId == 0) { - edgeId = m_sqliteStorage.addEdge(type, sourceId, targetId); + edgeId = m_sqliteIndexStorage.addEdge(type, sourceId, targetId); } return edgeId; } Id PersistentStorage::addLocalSymbol(const std::string& name) { - Id localSymbolId = m_sqliteStorage.getLocalSymbolByName(name).id; + Id localSymbolId = m_sqliteIndexStorage.getLocalSymbolByName(name).id; if (localSymbolId == 0) { - localSymbolId = m_sqliteStorage.addLocalSymbol(name); + localSymbolId = m_sqliteIndexStorage.addLocalSymbol(name); } return localSymbolId; } @@ -101,10 +102,10 @@ Id PersistentStorage::addLocalSymbol(const std::string& name) Id PersistentStorage::addSourceLocation( Id fileNodeId, uint startLine, uint startCol, uint endLine, uint endCol, int type) { - Id sourceLocationId = m_sqliteStorage.getSourceLocationByAll(fileNodeId, startLine, startCol, endLine, endCol, type).id; + Id sourceLocationId = m_sqliteIndexStorage.getSourceLocationByAll(fileNodeId, startLine, startCol, endLine, endCol, type).id; if (sourceLocationId == 0) { - sourceLocationId = m_sqliteStorage.addSourceLocation( + sourceLocationId = m_sqliteIndexStorage.addSourceLocation( fileNodeId, startLine, startCol, @@ -118,20 +119,20 @@ Id PersistentStorage::addSourceLocation( void PersistentStorage::addOccurrence(Id elementId, Id sourceLocationId) { - m_sqliteStorage.addOccurrence(elementId, sourceLocationId); + m_sqliteIndexStorage.addOccurrence(elementId, sourceLocationId); } void PersistentStorage::addComponentAccess(Id nodeId , int type) { - if (m_sqliteStorage.getComponentAccessByNodeId(nodeId).nodeId == 0) + if (m_sqliteIndexStorage.getComponentAccessByNodeId(nodeId).nodeId == 0) { - m_sqliteStorage.addComponentAccess(nodeId, type); + m_sqliteIndexStorage.addComponentAccess(nodeId, type); } } void PersistentStorage::addCommentLocation(Id fileNodeId, uint startLine, uint startCol, uint endLine, uint endCol) { - m_sqliteStorage.addCommentLocation( + m_sqliteIndexStorage.addCommentLocation( fileNodeId, startLine, startCol, @@ -143,7 +144,7 @@ void PersistentStorage::addCommentLocation(Id fileNodeId, uint startLine, uint s void PersistentStorage::addError( const std::string& message, const FilePath& filePath, uint startLine, uint startCol, bool fatal, bool indexed) { - m_sqliteStorage.addError( + m_sqliteIndexStorage.addError( message, filePath, startLine, @@ -155,87 +156,172 @@ void PersistentStorage::addError( Id PersistentStorage::addNodeBookmark(const NodeBookmark& bookmark) { - return m_sqliteStorage.addNodeBookmark(bookmark); + const Id categoryId = addBookmarkCategory(bookmark.getCategory().getName()); + const Id id = m_sqliteBookmarkStorage.addBookmark(bookmark.getName(), bookmark.getComment(), bookmark.getTimeStamp().toString(), categoryId); + + for (const Id& nodeId: bookmark.getNodeIds()) + { + m_sqliteBookmarkStorage.addBookmarkedNode(id, m_sqliteIndexStorage.getNodeById(nodeId).serializedName); + } + + return id; } Id PersistentStorage::addEdgeBookmark(const EdgeBookmark& bookmark) { - return m_sqliteStorage.addEdgeBookmark(bookmark); + const Id categoryId = addBookmarkCategory(bookmark.getCategory().getName()); + const Id id = m_sqliteBookmarkStorage.addBookmark(bookmark.getName(), bookmark.getComment(), bookmark.getTimeStamp().toString(), categoryId); + for (const Id& edgeId: bookmark.getEdgeIds()) + { + const StorageEdge storageEdge = m_sqliteIndexStorage.getEdgeById(edgeId); + + bool sourceNodeActive = storageEdge.sourceNodeId == bookmark.getActiveNodeId(); + m_sqliteBookmarkStorage.addBookmarkedEdge( + id, + m_sqliteIndexStorage.getNodeById(storageEdge.sourceNodeId).serializedName, // todo: optimization for multiple edges in same bookmark: use a local cache here + m_sqliteIndexStorage.getNodeById(storageEdge.targetNodeId).serializedName, + storageEdge.type, + sourceNodeActive + ); + } + return id; } -Id PersistentStorage::addBookmarkCategory(const BookmarkCategory& category) +Id PersistentStorage::addBookmarkCategory(const std::string& name) { - return m_sqliteStorage.addBookmarkCategory(category.getName()); + if (name.empty()) + { + return 0; + } + + Id id = m_sqliteBookmarkStorage.getBookmarkCategoryByName(name).id; + if (id == 0) + { + id = m_sqliteBookmarkStorage.addBookmarkCategory(name); + } + return id; } -std::vector PersistentStorage::getAllNodeBookmarks() const +void PersistentStorage::updateBookmark(const Id bookmarkId, const std::string& name, const std::string& comment, const std::string& categoryName) { - return m_sqliteStorage.getAllNodeBookmarks(); + const Id categoryId = addBookmarkCategory(categoryName); // only creates category if id didn't exist before; + m_sqliteBookmarkStorage.updateBookmark(bookmarkId, name, comment, categoryId); } -NodeBookmark PersistentStorage::getNodeBookmarkById(const Id bookmarkId) const +void PersistentStorage::removeBookmark(const Id id) { - return m_sqliteStorage.getNodeBookmarkById(bookmarkId); -} - -bool PersistentStorage::checkNodeBookmarkExistsByTokens(const std::vector& tokenNames) const -{ - return m_sqliteStorage.checkNodeBookmarkExistsByNames(tokenNames); -} - -void PersistentStorage::removeNodeBookmark(Id id) -{ - m_sqliteStorage.removeNodeBookmark(id); -} - -void PersistentStorage::editNodeBookmark(const NodeBookmark& bookmark) -{ - m_sqliteStorage.editNodeBookmark(bookmark); -} - -std::vector PersistentStorage::getAllEdgeBookmarks() const -{ - return m_sqliteStorage.getAllEdgeBookmarks(); -} - -EdgeBookmark PersistentStorage::getEdgeBookmarkById(const Id bookmarkId) const -{ - return m_sqliteStorage.getEdgeBookmarkById(bookmarkId); -} - -bool PersistentStorage::checkEdgeBookmarkExistsByTokens(const std::vector& tokenNames) const -{ - return m_sqliteStorage.checkEdgeBookmarkExistsByNames(tokenNames); -} - -void PersistentStorage::removeEdgeBookmark(Id id) -{ - m_sqliteStorage.removeEdgeBookmark(id); -} - -void PersistentStorage::editEdgeBookmark(const EdgeBookmark& bookmark) -{ - m_sqliteStorage.editEdgeBookmark(bookmark); -} - -bool PersistentStorage::checkBookmarkCategoryExists(const std::string& name) const -{ - return m_sqliteStorage.checkBookmarkCategoryExists(name); -} - -std::vector PersistentStorage::getAllBookmarkCategories() const -{ - return m_sqliteStorage.getAllBookmarkCategories(); + m_sqliteBookmarkStorage.removeBookmark(id); } void PersistentStorage::removeBookmarkCategory(Id id) { - m_sqliteStorage.removeBookmarkCategory(id); + m_sqliteBookmarkStorage.removeBookmarkCategory(id); +} + +std::vector PersistentStorage::getAllNodeBookmarks() const +{ + std::unordered_map bookmarkCategories; + for (const StorageBookmarkCategory& bookmarkCategory: m_sqliteBookmarkStorage.getAllBookmarkCategories()) + { + bookmarkCategories[bookmarkCategory.id] = bookmarkCategory; + } + + std::unordered_map> bookmarkIdToBookmarkedNodeIds; + for (const StorageBookmarkedNode& bookmarkedNode: m_sqliteBookmarkStorage.getAllBookmarkedNodes()) + { + bookmarkIdToBookmarkedNodeIds[bookmarkedNode.bookmarkId].push_back(m_sqliteIndexStorage.getNodeBySerializedName(bookmarkedNode.serializedNodeName).id); + } + + std::vector nodeBookmarks; + + for (const StorageBookmark& storageBookmark: m_sqliteBookmarkStorage.getAllBookmarks()) + { + auto itCategories = bookmarkCategories.find(storageBookmark.categoryId); + auto itNodeIds = bookmarkIdToBookmarkedNodeIds.find(storageBookmark.id); + if (itCategories != bookmarkCategories.end() && itNodeIds != bookmarkIdToBookmarkedNodeIds.end()) + { + NodeBookmark bookmark( + storageBookmark.id, + storageBookmark.name, + storageBookmark.comment, + storageBookmark.timestamp, + BookmarkCategory(itCategories->second.id, itCategories->second.name) + ); + bookmark.setNodeIds(itNodeIds->second); + bookmark.setIsValid(); + nodeBookmarks.push_back(bookmark); + } + } + + return nodeBookmarks; +} + +std::vector PersistentStorage::getAllEdgeBookmarks() const +{ + std::unordered_map bookmarkCategories; + for (const StorageBookmarkCategory& bookmarkCategory: m_sqliteBookmarkStorage.getAllBookmarkCategories()) + { + bookmarkCategories[bookmarkCategory.id] = bookmarkCategory; + } + + std::unordered_map> bookmarkIdToBookmarkedEdges; + for (const StorageBookmarkedEdge& bookmarkedEdge: m_sqliteBookmarkStorage.getAllBookmarkedEdges()) + { + bookmarkIdToBookmarkedEdges[bookmarkedEdge.bookmarkId].push_back(bookmarkedEdge); + } + + std::vector edgeBookmarks; + + Cache nodeIdCache([&](std::string serializedNodeName){ return m_sqliteIndexStorage.getNodeBySerializedName(serializedNodeName).id; }); + for (const StorageBookmark& storageBookmark: m_sqliteBookmarkStorage.getAllBookmarks()) + { + auto itCategories = bookmarkCategories.find(storageBookmark.categoryId); + auto itBookmarkedEdges = bookmarkIdToBookmarkedEdges.find(storageBookmark.id); + if (itCategories != bookmarkCategories.end() && itBookmarkedEdges != bookmarkIdToBookmarkedEdges.end()) + { + EdgeBookmark bookmark( + storageBookmark.id, + storageBookmark.name, + storageBookmark.comment, + storageBookmark.timestamp, + BookmarkCategory(itCategories->second.id, itCategories->second.name) + ); + + Id activeNodeId = 0; + for (const StorageBookmarkedEdge& bookmarkedEdge: itBookmarkedEdges->second) + { + const Id sourceNodeId = nodeIdCache.getValue(bookmarkedEdge.serializedSourceNodeName); + const Id targetNodeId = nodeIdCache.getValue(bookmarkedEdge.serializedTargetNodeName); + const Id edgeId = m_sqliteIndexStorage.getEdgeBySourceTargetType(sourceNodeId, targetNodeId, bookmarkedEdge.edgeType).id; + bookmark.addEdgeId(edgeId); + + if (activeNodeId == 0) + { + activeNodeId = bookmarkedEdge.sourceNodeActive ? sourceNodeId : targetNodeId; + } + } + bookmark.setActiveNodeId(activeNodeId); + bookmark.setIsValid(); + edgeBookmarks.push_back(bookmark); + } + } + + return edgeBookmarks; +} + +std::vector PersistentStorage::getAllBookmarkCategories() const +{ + std::vector categories; + for (const StorageBookmarkCategory storageBookmarkCategoriy: m_sqliteBookmarkStorage.getAllBookmarkCategories()) + { + categories.push_back(BookmarkCategory(storageBookmarkCategoriy.id, storageBookmarkCategoriy.name)); + } + return categories; } void PersistentStorage::forEachNode(std::function callback) const { - for (StorageNode& node: m_sqliteStorage.getAll()) + for (StorageNode& node: m_sqliteIndexStorage.getAll()) { callback(node.id, node); } @@ -243,7 +329,7 @@ void PersistentStorage::forEachNode(std::function callback) const { - for (StorageFile& file: m_sqliteStorage.getAll()) + for (StorageFile& file: m_sqliteIndexStorage.getAll()) { callback(file); } @@ -251,7 +337,7 @@ void PersistentStorage::forEachFile(std::function callback) const { - for (StorageSymbol& symbol: m_sqliteStorage.getAll()) + for (StorageSymbol& symbol: m_sqliteIndexStorage.getAll()) { callback(symbol); } @@ -259,7 +345,7 @@ void PersistentStorage::forEachSymbol(std::function callback) const { - for (StorageEdge& edge: m_sqliteStorage.getAll()) + for (StorageEdge& edge: m_sqliteIndexStorage.getAll()) { callback(edge.id, edge); } @@ -268,7 +354,7 @@ void PersistentStorage::forEachEdge(std::function callback) const { - for (StorageLocalSymbol& localSymbol: m_sqliteStorage.getAll()) + for (StorageLocalSymbol& localSymbol: m_sqliteIndexStorage.getAll()) { callback(localSymbol.id, localSymbol); } @@ -276,7 +362,7 @@ void PersistentStorage::forEachLocalSymbol(std::function callback) const { - for (StorageSourceLocation& sourceLocation: m_sqliteStorage.getAll()) + for (StorageSourceLocation& sourceLocation: m_sqliteIndexStorage.getAll()) { callback(sourceLocation.id, sourceLocation); } @@ -284,7 +370,7 @@ void PersistentStorage::forEachSourceLocation(std::function callback) const { - for (StorageOccurrence& occurrence: m_sqliteStorage.getAll()) + for (StorageOccurrence& occurrence: m_sqliteIndexStorage.getAll()) { callback(occurrence); } @@ -292,7 +378,7 @@ void PersistentStorage::forEachOccurrence(std::function callback) const { - for (StorageComponentAccess& componentAccess: m_sqliteStorage.getAll()) + for (StorageComponentAccess& componentAccess: m_sqliteIndexStorage.getAll()) { callback(componentAccess); } @@ -300,7 +386,7 @@ void PersistentStorage::forEachComponentAccess(std::function callback) const { - for (StorageCommentLocation& commentLocation: m_sqliteStorage.getAll()) + for (StorageCommentLocation& commentLocation: m_sqliteIndexStorage.getAll()) { callback(commentLocation); } @@ -308,7 +394,7 @@ void PersistentStorage::forEachCommentLocation(std::function callback) const { - for (StorageError& error: m_sqliteStorage.getAll()) + for (StorageError& error: m_sqliteIndexStorage.getAll()) { callback(error); } @@ -318,12 +404,12 @@ void PersistentStorage::startInjection() { m_preInjectionErrorCount = getErrors().size(); - m_sqliteStorage.beginTransaction(); + m_sqliteIndexStorage.beginTransaction(); } void PersistentStorage::finishInjection() { - m_sqliteStorage.commitTransaction(); + m_sqliteIndexStorage.commitTransaction(); auto errors = getErrors(); @@ -333,44 +419,51 @@ void PersistentStorage::finishInjection() } } -void PersistentStorage::setMode(const SqliteStorage::StorageModeType mode) +void PersistentStorage::setMode(const SqliteIndexStorage::StorageModeType mode) { - m_sqliteStorage.setMode(mode); + m_sqliteIndexStorage.setMode(mode); } FilePath PersistentStorage::getDbFilePath() const { - return m_sqliteStorage.getDbFilePath(); + return m_sqliteIndexStorage.getDbFilePath(); } bool PersistentStorage::isEmpty() const { - return m_sqliteStorage.isEmpty(); + return m_sqliteIndexStorage.isEmpty(); } bool PersistentStorage::isIncompatible() const { - return m_sqliteStorage.isIncompatible(); + return m_sqliteIndexStorage.isIncompatible(); } std::string PersistentStorage::getProjectSettingsText() const { - return m_sqliteStorage.getProjectSettingsText(); + return m_sqliteIndexStorage.getProjectSettingsText(); } void PersistentStorage::setProjectSettingsText(std::string text) { - m_sqliteStorage.setProjectSettingsText(text); + m_sqliteIndexStorage.setProjectSettingsText(text); } void PersistentStorage::setup() { - m_sqliteStorage.setup(); + if (m_sqliteIndexStorage.isEmpty()) + { + m_sqliteIndexStorage.setup(); + } + if (m_sqliteBookmarkStorage.isEmpty()) + { + m_sqliteBookmarkStorage.setup(); + } } void PersistentStorage::clear() { - m_sqliteStorage.clear(); + m_sqliteIndexStorage.clear(); clearCaches(); } @@ -415,10 +508,10 @@ void PersistentStorage::clearFileElements(const std::vector& filePaths if (!fileNodeIds.empty()) { - m_sqliteStorage.removeElementsWithLocationInFiles(fileNodeIds, updateStatusCallback); - m_sqliteStorage.removeElements(fileNodeIds); + m_sqliteIndexStorage.removeElementsWithLocationInFiles(fileNodeIds, updateStatusCallback); + m_sqliteIndexStorage.removeElements(fileNodeIds); - m_sqliteStorage.removeErrorsInFiles(filePaths); + m_sqliteIndexStorage.removeErrorsInFiles(filePaths); } } @@ -428,7 +521,7 @@ std::vector PersistentStorage::getInfoOnAllFiles() const std::vector fileInfos; - std::vector storageFiles = m_sqliteStorage.getAll(); + std::vector storageFiles = m_sqliteIndexStorage.getAll(); for (size_t i = 0; i < storageFiles.size(); i++) { boost::posix_time::ptime modificationTime = boost::posix_time::not_a_date_time; @@ -460,18 +553,21 @@ void PersistentStorage::optimizeMemory() { TRACE(); - m_sqliteStorage.optimizeMemory(); - m_sqliteStorage.setVersion(); + m_sqliteIndexStorage.setVersion(); + m_sqliteIndexStorage.optimizeMemory(); + + m_sqliteBookmarkStorage.setVersion(); + m_sqliteBookmarkStorage.optimizeMemory(); } Id PersistentStorage::getNodeIdForFileNode(const FilePath& filePath) const { - return m_sqliteStorage.getFileByPath(filePath.str()).id; + return m_sqliteIndexStorage.getFileByPath(filePath.str()).id; } Id PersistentStorage::getNodeIdForNameHierarchy(const NameHierarchy& nameHierarchy) const { - return m_sqliteStorage.getNodeBySerializedName(NameHierarchy::serialize(nameHierarchy)).id; + return m_sqliteIndexStorage.getNodeBySerializedName(NameHierarchy::serialize(nameHierarchy)).id; } std::vector PersistentStorage::getNodeIdsForNameHierarchies(const std::vector nameHierarchies) const @@ -492,13 +588,13 @@ NameHierarchy PersistentStorage::getNameHierarchyForNodeId(Id nodeId) const { TRACE(); - return NameHierarchy::deserialize(m_sqliteStorage.getFirstById(nodeId).serializedName); + return NameHierarchy::deserialize(m_sqliteIndexStorage.getFirstById(nodeId).serializedName); } std::vector PersistentStorage::getNameHierarchiesForNodeIds(const std::vector nodeIds) const { std::vector nameHierarchies; - for (const StorageNode& storageNode : m_sqliteStorage.getAllByIds(nodeIds)) + for (const StorageNode& storageNode : m_sqliteIndexStorage.getAllByIds(nodeIds)) { nameHierarchies.push_back(NameHierarchy::deserialize(storageNode.serializedName)); } @@ -507,12 +603,12 @@ std::vector PersistentStorage::getNameHierarchiesForNodeIds(const Node::NodeType PersistentStorage::getNodeTypeForNodeWithId(Id nodeId) const { - return Node::intToType(m_sqliteStorage.getFirstById(nodeId).type); + return Node::intToType(m_sqliteIndexStorage.getFirstById(nodeId).type); } bool PersistentStorage::checkNodeExistsByName(const std::string& serializedName) const { - return m_sqliteStorage.checkNodeExistsByName(serializedName); + return m_sqliteIndexStorage.checkNodeExistsByName(serializedName); } Id PersistentStorage::getIdForEdge( @@ -521,17 +617,17 @@ Id PersistentStorage::getIdForEdge( { Id sourceId = getNodeIdForNameHierarchy(fromNameHierarchy); Id targetId = getNodeIdForNameHierarchy(toNameHierarchy); - return m_sqliteStorage.getEdgeBySourceTargetType(sourceId, targetId, type).id; + return m_sqliteIndexStorage.getEdgeBySourceTargetType(sourceId, targetId, type).id; } StorageEdge PersistentStorage::getEdgeById(Id edgeId) const { - return m_sqliteStorage.getEdgeById(edgeId); + return m_sqliteIndexStorage.getEdgeById(edgeId); } bool PersistentStorage::checkEdgeExists(Id edgeId) const { - return m_sqliteStorage.checkEdgeExists(edgeId); + return m_sqliteIndexStorage.checkEdgeExists(edgeId); } std::shared_ptr PersistentStorage::getFullTextSearchLocations( @@ -687,12 +783,12 @@ std::vector PersistentStorage::getAutocompletionSymbolMatches(const elementIds.insert(elementIds.end(), result.elementIds.begin(), result.elementIds.end()); } - for (StorageNode& node : m_sqliteStorage.getAllByIds(elementIds)) + for (StorageNode& node : m_sqliteIndexStorage.getAllByIds(elementIds)) { storageNodeMap[node.id] = node; } - for (StorageSymbol& symbol : m_sqliteStorage.getAllByIds(elementIds)) + for (StorageSymbol& symbol : m_sqliteIndexStorage.getAllByIds(elementIds)) { storageSymbolMap[symbol.id] = symbol; } @@ -813,7 +909,7 @@ std::vector PersistentStorage::getSearchMatchesForTokenIds(const st // fetch StorageNodes for node ids std::map storageNodeMap; - for (StorageNode& node : m_sqliteStorage.getAllByIds(elementIds)) + for (StorageNode& node : m_sqliteIndexStorage.getAllByIds(elementIds)) { storageNodeMap.emplace(node.id, node); } @@ -854,7 +950,7 @@ std::shared_ptr PersistentStorage::getGraphForAll() const std::shared_ptr graph = std::make_shared(); std::unordered_set explicitlyDefinedSymbolIds; - for (StorageSymbol symbol: m_sqliteStorage.getAll()) + for (StorageSymbol symbol: m_sqliteIndexStorage.getAll()) { if (intToDefinitionKind(symbol.definitionKind) == DEFINITION_EXPLICIT) { @@ -863,7 +959,7 @@ std::shared_ptr PersistentStorage::getGraphForAll() const } std::vector tokenIds; - for (StorageNode node: m_sqliteStorage.getAll()) + for (StorageNode node: m_sqliteIndexStorage.getAll()) { if (explicitlyDefinedSymbolIds.find(node.id) != explicitlyDefinedSymbolIds.end() && ( @@ -879,7 +975,7 @@ std::shared_ptr PersistentStorage::getGraphForAll() const } } - for (StorageFile file: m_sqliteStorage.getAll()) + for (StorageFile file: m_sqliteIndexStorage.getAll()) { tokenIds.push_back(file.id); } @@ -908,7 +1004,7 @@ std::shared_ptr PersistentStorage::getGraphForActiveTokenIds(const std::v if (tokenIds.size() == 1) { const Id elementId = tokenIds[0]; - StorageNode node = m_sqliteStorage.getFirstById(elementId); + StorageNode node = m_sqliteIndexStorage.getFirstById(elementId); if (node.id > 0) { @@ -924,7 +1020,7 @@ std::shared_ptr PersistentStorage::getGraphForActiveTokenIds(const std::v { nodeIds.push_back(elementId); - std::vector edges = m_sqliteStorage.getEdgesBySourceOrTargetId(elementId); + std::vector edges = m_sqliteIndexStorage.getEdgesBySourceOrTargetId(elementId); for (const StorageEdge& edge : edges) { Edge::EdgeType edgeType = Edge::intToType(edge.type); @@ -947,7 +1043,7 @@ std::shared_ptr PersistentStorage::getGraphForActiveTokenIds(const std::v addAggregations = true; } } - else if (m_sqliteStorage.isEdge(elementId)) + else if (m_sqliteIndexStorage.isEdge(elementId)) { edgeIds.push_back(elementId); } @@ -956,7 +1052,7 @@ std::shared_ptr PersistentStorage::getGraphForActiveTokenIds(const std::v if (ids.size() >= 1 || isNamespace) { std::set symbolIds; - for (const StorageSymbol& symbol : m_sqliteStorage.getAllByIds(ids)) + for (const StorageSymbol& symbol : m_sqliteIndexStorage.getAllByIds(ids)) { if (symbol.id > 0 && (!isNamespace || intToDefinitionKind(symbol.definitionKind) != DEFINITION_IMPLICIT)) { @@ -964,7 +1060,7 @@ std::shared_ptr PersistentStorage::getGraphForActiveTokenIds(const std::v } symbolIds.insert(symbol.id); } - for (const StorageNode& node : m_sqliteStorage.getAllByIds(ids)) + for (const StorageNode& node : m_sqliteIndexStorage.getAllByIds(ids)) { if (symbolIds.find(node.id) == symbolIds.end()) { @@ -976,7 +1072,7 @@ std::shared_ptr PersistentStorage::getGraphForActiveTokenIds(const std::v { if (nodeIds.size() != ids.size()) { - std::vector edges = m_sqliteStorage.getAllByIds(ids); + std::vector edges = m_sqliteIndexStorage.getAllByIds(ids); for (const StorageEdge& edge : edges) { if (edge.id > 0) @@ -1017,18 +1113,18 @@ std::vector PersistentStorage::getActiveTokenIdsForId(Id tokenId, Id* declar { std::vector activeTokenIds; - if (!(m_sqliteStorage.isEdge(tokenId) || m_sqliteStorage.isNode(tokenId))) + if (!(m_sqliteIndexStorage.isEdge(tokenId) || m_sqliteIndexStorage.isNode(tokenId))) { return activeTokenIds; } activeTokenIds.push_back(tokenId); - if (m_sqliteStorage.isNode(tokenId)) + if (m_sqliteIndexStorage.isNode(tokenId)) { *declarationId = tokenId; - std::vector incomingEdges = m_sqliteStorage.getEdgesByTargetId(tokenId); + std::vector incomingEdges = m_sqliteIndexStorage.getEdgesByTargetId(tokenId); for (size_t i = 0; i < incomingEdges.size(); i++) { activeTokenIds.push_back(incomingEdges[i].id); @@ -1046,18 +1142,18 @@ std::vector PersistentStorage::getNodeIdsForLocationIds(const std::vector nodeIds; std::set implicitNodeIds; - for (const StorageOccurrence& occurrence: m_sqliteStorage.getOccurrencesForLocationIds(locationIds)) + for (const StorageOccurrence& occurrence: m_sqliteIndexStorage.getOccurrencesForLocationIds(locationIds)) { const Id elementId = occurrence.elementId; - StorageEdge edge = m_sqliteStorage.getFirstById(elementId); + StorageEdge edge = m_sqliteIndexStorage.getFirstById(elementId); if (edge.id != 0) // here we test if location is an edge. { edgeIds.insert(edge.targetNodeId); } - else if(m_sqliteStorage.isNode(elementId)) + else if(m_sqliteIndexStorage.isNode(elementId)) { - StorageSymbol symbol = m_sqliteStorage.getFirstById(elementId); + StorageSymbol symbol = m_sqliteIndexStorage.getFirstById(elementId); if (symbol.id != 0) // here we test if location is a symbol { if (intToDefinitionKind(symbol.definitionKind) == DEFINITION_IMPLICIT) @@ -1111,22 +1207,22 @@ std::shared_ptr PersistentStorage::getSourceLocationsF std::shared_ptr collection = std::make_shared(); - for (const StorageFile& file : m_sqliteStorage.getAllByIds(fileIds)) + for (const StorageFile& file : m_sqliteIndexStorage.getAllByIds(fileIds)) { - collection->addSourceLocationFile(m_sqliteStorage.getSourceLocationsForFile(file.filePath)); + collection->addSourceLocationFile(m_sqliteIndexStorage.getSourceLocationsForFile(file.filePath)); } if (nonFileIds.size()) { std::vector locationIds; std::unordered_map locationIdToElementIdMap; - for (const StorageOccurrence& occurrence: m_sqliteStorage.getOccurrencesForElementIds(nonFileIds)) + for (const StorageOccurrence& occurrence: m_sqliteIndexStorage.getOccurrencesForElementIds(nonFileIds)) { locationIds.push_back(occurrence.sourceLocationId); locationIdToElementIdMap[occurrence.sourceLocationId] = occurrence.elementId; } - for (const StorageSourceLocation& sourceLocation: m_sqliteStorage.getAllByIds(locationIds)) + for (const StorageSourceLocation& sourceLocation: m_sqliteIndexStorage.getAllByIds(locationIds)) { auto it = locationIdToElementIdMap.find(sourceLocation.id); if (it != locationIdToElementIdMap.end()) @@ -1156,10 +1252,10 @@ std::shared_ptr PersistentStorage::getSourceLocationsF std::shared_ptr collection = std::make_shared(); - for (StorageSourceLocation location: m_sqliteStorage.getAllByIds(locationIds)) + for (StorageSourceLocation location: m_sqliteIndexStorage.getAllByIds(locationIds)) { std::vector elementIds; - for (const StorageOccurrence& occurrence: m_sqliteStorage.getOccurrencesForLocationId(location.id)) + for (const StorageOccurrence& occurrence: m_sqliteIndexStorage.getOccurrencesForLocationId(location.id)) { elementIds.push_back(occurrence.elementId); } @@ -1183,7 +1279,7 @@ std::shared_ptr PersistentStorage::getSourceLocationsForFile { TRACE(); - return m_sqliteStorage.getSourceLocationsForFile(filePath); + return m_sqliteIndexStorage.getSourceLocationsForFile(filePath); } std::shared_ptr PersistentStorage::getSourceLocationsForLinesInFile( @@ -1201,7 +1297,7 @@ std::shared_ptr PersistentStorage::getCommentLocationsInFile std::shared_ptr file = std::make_shared(filePath, false, false); - std::vector storageLocations = m_sqliteStorage.getCommentLocationsInFile(filePath); + std::vector storageLocations = m_sqliteIndexStorage.getCommentLocationsInFile(filePath); for (size_t i = 0; i < storageLocations.size(); i++) { file->addSourceLocation( @@ -1220,19 +1316,19 @@ std::shared_ptr PersistentStorage::getCommentLocationsInFile std::shared_ptr PersistentStorage::getFileContent(const FilePath& filePath) const { - return m_sqliteStorage.getFileContentByPath(filePath.str()); + return m_sqliteIndexStorage.getFileContentByPath(filePath.str()); } FileInfo PersistentStorage::getFileInfoForFilePath(const FilePath& filePath) const { - return FileInfo(filePath, m_sqliteStorage.getFileByPath(filePath.str()).modificationTime); + return FileInfo(filePath, m_sqliteIndexStorage.getFileByPath(filePath.str()).modificationTime); } std::vector PersistentStorage::getFileInfosForFilePaths(const std::vector& filePaths) const { std::vector fileInfos; - std::vector storageFiles = m_sqliteStorage.getFilesByPaths(filePaths); + std::vector storageFiles = m_sqliteIndexStorage.getFilesByPaths(filePaths); for (const StorageFile& file : storageFiles) { fileInfos.push_back(FileInfo(FilePath(file.filePath), file.modificationTime)); @@ -1247,12 +1343,12 @@ StorageStats PersistentStorage::getStorageStats() const StorageStats stats; - stats.nodeCount = m_sqliteStorage.getNodeCount(); - stats.edgeCount = m_sqliteStorage.getEdgeCount(); + stats.nodeCount = m_sqliteIndexStorage.getNodeCount(); + stats.edgeCount = m_sqliteIndexStorage.getEdgeCount(); - stats.fileCount = m_sqliteStorage.getFileCount(); - stats.completedFileCount = m_sqliteStorage.getCompletedFileCount(); - stats.fileLOCCount = m_sqliteStorage.getFileLineSum(); + stats.fileCount = m_sqliteIndexStorage.getFileCount(); + stats.completedFileCount = m_sqliteIndexStorage.getCompletedFileCount(); + stats.fileLOCCount = m_sqliteIndexStorage.getFileLineSum(); return stats; } @@ -1277,7 +1373,7 @@ ErrorCountInfo PersistentStorage::getErrorCount() const std::vector PersistentStorage::getErrors() const { - std::vector errors = m_sqliteStorage.getAll(); + std::vector errors = m_sqliteIndexStorage.getAll(); std::vector filteredErrors; for (const ErrorInfo& error : errors) @@ -1296,7 +1392,7 @@ std::shared_ptr PersistentStorage::getErrorSourceLocat TRACE(); std::shared_ptr errorCollection = std::make_shared(); - for (const ErrorInfo& error : m_sqliteStorage.getAll()) + for (const ErrorInfo& error : m_sqliteIndexStorage.getAll()) { if (m_errorFilter.filter(error)) { @@ -1380,7 +1476,7 @@ FilePath PersistentStorage::getFileNodePath(Id fileId) const std::unordered_map> PersistentStorage::getFileIdToIncludingFileIdMap() const { std::unordered_map> fileIdToIncludingFileIdMap; - for (const StorageEdge& includeEdge : m_sqliteStorage.getEdgesByType(Edge::typeToInt(Edge::EDGE_INCLUDE))) + for (const StorageEdge& includeEdge : m_sqliteIndexStorage.getEdgesByType(Edge::typeToInt(Edge::EDGE_INCLUDE))) { fileIdToIncludingFileIdMap[includeEdge.targetNodeId].insert(includeEdge.sourceNodeId); } @@ -1394,7 +1490,7 @@ std::unordered_map> PersistentStorage::getFileIdToImportingFile std::vector importedElementIds; std::map> elementIdToImportingFileIds; - for (const StorageEdge& importEdge : m_sqliteStorage.getEdgesByType(Edge::typeToInt(Edge::EDGE_IMPORT))) + for (const StorageEdge& importEdge : m_sqliteIndexStorage.getEdgesByType(Edge::typeToInt(Edge::EDGE_IMPORT))) { importedElementIds.push_back(importEdge.targetNodeId); elementIdToImportingFileIds[importEdge.targetNodeId].insert(importEdge.sourceNodeId); @@ -1404,13 +1500,13 @@ std::unordered_map> PersistentStorage::getFileIdToImportingFile { std::vector importedSourceLocationIds; std::unordered_map importedSourceLocationToElementIds; - for (const StorageOccurrence& occurrence: m_sqliteStorage.getOccurrencesForElementIds(importedElementIds)) + for (const StorageOccurrence& occurrence: m_sqliteIndexStorage.getOccurrencesForElementIds(importedElementIds)) { importedSourceLocationIds.push_back(occurrence.sourceLocationId); importedSourceLocationToElementIds[occurrence.sourceLocationId] = occurrence.elementId; } - for (const StorageSourceLocation& sourceLocation: m_sqliteStorage.getAllByIds(importedSourceLocationIds)) + for (const StorageSourceLocation& sourceLocation: m_sqliteIndexStorage.getAllByIds(importedSourceLocationIds)) { auto it = importedSourceLocationToElementIds.find(sourceLocation.id); if (it != importedSourceLocationToElementIds.end()) @@ -1553,18 +1649,18 @@ void PersistentStorage::addNodesToGraph(const std::vector& nodeIds, Graph* g } std::unordered_map symbolMap; - for (const StorageSymbol& symbol : m_sqliteStorage.getAllByIds(nodeIds)) + for (const StorageSymbol& symbol : m_sqliteIndexStorage.getAllByIds(nodeIds)) { symbolMap[symbol.id] = symbol; } std::unordered_map fileMap; - for (const StorageFile& file : m_sqliteStorage.getAllByIds(nodeIds)) + for (const StorageFile& file : m_sqliteIndexStorage.getAllByIds(nodeIds)) { fileMap[file.id] = file; } - for (const StorageNode& storageNode : m_sqliteStorage.getAllByIds(nodeIds)) + for (const StorageNode& storageNode : m_sqliteIndexStorage.getAllByIds(nodeIds)) { const Node::NodeType type = Node::intToType(storageNode.type); if (type == Node::NODE_FILE) @@ -1637,7 +1733,7 @@ void PersistentStorage::addEdgesToGraph(const std::vector& edgeIds, Graph* g return; } - for (const StorageEdge& storageEdge : m_sqliteStorage.getAllByIds(edgeIds)) + for (const StorageEdge& storageEdge : m_sqliteIndexStorage.getAllByIds(edgeIds)) { Node* sourceNode = graph->getNodeById(storageEdge.sourceNodeId); Node* targetNode = graph->getNodeById(storageEdge.targetNodeId); @@ -1662,7 +1758,7 @@ void PersistentStorage::addNodesWithChildrenAndEdgesToGraph( std::vector nodeIdsFull = nodeIds; if (edgeIds.size() > 0) { - for (const StorageEdge& storageEdge : m_sqliteStorage.getAllByIds(edgeIds)) + for (const StorageEdge& storageEdge : m_sqliteIndexStorage.getAllByIds(edgeIds)) { nodeIdsFull.push_back(storageEdge.sourceNodeId); nodeIdsFull.push_back(storageEdge.targetNodeId); @@ -1732,7 +1828,7 @@ void PersistentStorage::addAggregationEdgesToGraph( connectedNodeIds[isSource ? edge.targetNodeId : edge.sourceNodeId].push_back(edgeInfo); } - std::vector outgoingEdges = m_sqliteStorage.getEdgesBySourceIds(childNodeIds); + std::vector outgoingEdges = m_sqliteIndexStorage.getEdgesBySourceIds(childNodeIds); for (const StorageEdge& outEdge : outgoingEdges) { EdgeInfo edgeInfo; @@ -1741,7 +1837,7 @@ void PersistentStorage::addAggregationEdgesToGraph( connectedNodeIds[outEdge.targetNodeId].push_back(edgeInfo); } - std::vector incomingEdges = m_sqliteStorage.getEdgesByTargetIds(childNodeIds); + std::vector incomingEdges = m_sqliteIndexStorage.getEdgesByTargetIds(childNodeIds); for (const StorageEdge& inEdge : incomingEdges) { EdgeInfo edgeInfo; @@ -1814,7 +1910,7 @@ void PersistentStorage::addComponentAccessToGraph(Graph* graph) const } ); - std::vector accesses = m_sqliteStorage.getComponentAccessesByNodeIds(nodeIds); + std::vector accesses = m_sqliteIndexStorage.getComponentAccessesByNodeIds(nodeIds); for (const StorageComponentAccess& access : accesses) { if (access.nodeId != 0) @@ -1832,18 +1928,18 @@ void PersistentStorage::buildSearchIndex() FilePath dbPath = getDbFilePath(); std::unordered_map symbolMap; - for (StorageSymbol symbol : m_sqliteStorage.getAll()) + for (StorageSymbol symbol : m_sqliteIndexStorage.getAll()) { symbolMap[symbol.id] = symbol; } std::unordered_map fileMap; - for (StorageFile file : m_sqliteStorage.getAll()) + for (StorageFile file : m_sqliteIndexStorage.getAll()) { fileMap[file.id] = file; } - for (StorageNode node : m_sqliteStorage.getAll()) + for (StorageNode node : m_sqliteIndexStorage.getAll()) { if (Node::intToType(node.type) == Node::NODE_FILE) { @@ -1879,7 +1975,7 @@ void PersistentStorage::buildFilePathMaps() { TRACE(); - for (StorageFile file: m_sqliteStorage.getAll()) + for (StorageFile file: m_sqliteIndexStorage.getAll()) { m_fileNodeIds.emplace(file.filePath, file.id); m_fileNodePaths.emplace(file.id, file.filePath); @@ -1890,9 +1986,9 @@ void PersistentStorage::buildFullTextSearchIndex() const { TRACE(); - for (StorageFile file : m_sqliteStorage.getAll()) + for (StorageFile file : m_sqliteIndexStorage.getAll()) { - m_fullTextSearchIndex.addFile(file.id, m_sqliteStorage.getFileContentById(file.id)->getText()); + m_fullTextSearchIndex.addFile(file.id, m_sqliteIndexStorage.getFileContentById(file.id)->getText()); } } @@ -1900,14 +1996,14 @@ void PersistentStorage::buildHierarchyCache() { TRACE(); - std::vector memberEdges = m_sqliteStorage.getEdgesByType(Edge::typeToInt(Edge::EDGE_MEMBER)); + std::vector memberEdges = m_sqliteIndexStorage.getEdgesByType(Edge::typeToInt(Edge::EDGE_MEMBER)); Cache nodeTypeCache([this](Id id){ - return Node::intToType(m_sqliteStorage.getFirstById(id).type); + return Node::intToType(m_sqliteIndexStorage.getFirstById(id).type); }); Cache indexedNodeCache([this](Id id){ - StorageSymbol symbol = m_sqliteStorage.getFirstById(id); + StorageSymbol symbol = m_sqliteIndexStorage.getFirstById(id); if (symbol.id > 0) { return intToDefinitionKind(symbol.definitionKind) != DEFINITION_NONE; diff --git a/src/lib/data/PersistentStorage.h b/src/lib/data/PersistentStorage.h index 335a831c..96ffdce0 100644 --- a/src/lib/data/PersistentStorage.h +++ b/src/lib/data/PersistentStorage.h @@ -13,7 +13,8 @@ #include "data/parser/ParseLocation.h" #include "data/search/SearchIndex.h" #include "data/HierarchyCache.h" -#include "data/SqliteStorage.h" +#include "data/SqliteIndexStorage.h" +#include "data/SqliteBookmarkStorage.h" #include "data/Storage.h" #include "data/parser/ParserClientImpl.h" @@ -23,7 +24,7 @@ class PersistentStorage , public StorageAccess { public: - PersistentStorage(const FilePath& dbPath); + PersistentStorage(const FilePath& dbPath, const FilePath& bookmarkPath); virtual ~PersistentStorage(); virtual Id addNode(int type, const std::string& serializedName); @@ -38,23 +39,18 @@ public: virtual void addError(const std::string& message, const FilePath& filePath, uint startLine, uint startCol, bool fatal, bool indexed); virtual Id addNodeBookmark(const NodeBookmark& bookmark); virtual Id addEdgeBookmark(const EdgeBookmark& bookmark); - virtual Id addBookmarkCategory(const BookmarkCategory& category); + virtual Id addBookmarkCategory(const std::string& categoryName); - virtual std::vector getAllNodeBookmarks() const; - virtual NodeBookmark getNodeBookmarkById(const Id bookmarkId) const; - virtual bool checkNodeBookmarkExistsByTokens(const std::vector& tokenNames) const; - virtual void removeNodeBookmark(Id id); - virtual void editNodeBookmark(const NodeBookmark& bookmark); + void updateBookmark(const Id bookmarkId, const std::string& name, const std::string& comment, const std::string& categoryName); + + virtual void removeBookmark(const Id id); + virtual void removeBookmarkCategory(const Id id); + + std::vector getAllNodeBookmarks() const; + std::vector getAllEdgeBookmarks() const; - virtual std::vector getAllEdgeBookmarks() const; - virtual EdgeBookmark getEdgeBookmarkById(const Id bookmarkId) const; - virtual bool checkEdgeBookmarkExistsByTokens(const std::vector& tokenNames) const; - virtual void removeEdgeBookmark(Id id); - virtual void editEdgeBookmark(const EdgeBookmark& bookmark); - virtual bool checkBookmarkCategoryExists(const std::string& name) const; virtual std::vector getAllBookmarkCategories() const; - virtual void removeBookmarkCategory(Id id); virtual void forEachNode(std::function callback) const; virtual void forEachFile(std::function callback) const; @@ -70,7 +66,7 @@ public: virtual void startInjection(); virtual void finishInjection(); - void setMode(const SqliteStorage::StorageModeType mode); + void setMode(const SqliteIndexStorage::StorageModeType mode); FilePath getDbFilePath() const; @@ -188,7 +184,8 @@ private: mutable FullTextSearchIndex m_fullTextSearchIndex; - SqliteStorage m_sqliteStorage; + SqliteIndexStorage m_sqliteIndexStorage; + SqliteBookmarkStorage m_sqliteBookmarkStorage; mutable std::map m_fileNodeIds; mutable std::map m_fileNodePaths; diff --git a/src/lib/data/SqliteBookmarkStorage.cpp b/src/lib/data/SqliteBookmarkStorage.cpp new file mode 100644 index 00000000..6ee04545 --- /dev/null +++ b/src/lib/data/SqliteBookmarkStorage.cpp @@ -0,0 +1,329 @@ +#include "SqliteBookmarkStorage.h" + +#include "utility/logging/logging.h" +#include "utility/utility.h" +#include "utility/utilityString.h" + +const size_t SqliteBookmarkStorage::s_storageVersion = 1; + +SqliteBookmarkStorage::SqliteBookmarkStorage(const FilePath& dbFilePath) + : SqliteStorage(dbFilePath) +{ +} + +SqliteBookmarkStorage::~SqliteBookmarkStorage() +{ +} + +Id SqliteBookmarkStorage::addBookmarkCategory(const std::string& name) +{ + std::string statement = "INSERT INTO bookmark_category(id, name) " + "VALUES (NULL, ?);"; + + CppSQLite3Statement stmt = m_database.compileStatement(statement.c_str()); + stmt.bind(1, name.c_str()); + + executeStatement(stmt); + const Id id = m_database.lastRowId(); + + return id; +} + +Id SqliteBookmarkStorage::addBookmark(const std::string& name, const std::string& comment, const std::string& timestamp, const Id categoryId) +{ + std::string statement = "INSERT INTO bookmark(id, name, comment, timestamp, category_id) " + "VALUES (NULL, ?, ?, ?, " + std::to_string(categoryId) + ");"; + + + try + { + CppSQLite3Statement stmt = m_database.compileStatement(statement.c_str()); + stmt.bind(1, name.c_str()); + stmt.bind(2, comment.c_str()); + stmt.bind(3, timestamp.c_str()); + executeStatement(stmt); + + const Id id = m_database.lastRowId(); + return id; + } + catch (CppSQLite3Exception e) + { + LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage()); + } + return 0; +} + +Id SqliteBookmarkStorage::addBookmarkedNode(const Id bookmarkId, const std::string& nodeName) +{ + executeStatement("INSERT INTO bookmarked_element(id, bookmark_id) VALUES(NULL, " + std::to_string(bookmarkId) + ");"); + Id id = m_database.lastRowId(); + + std::string statement = "INSERT INTO bookmarked_node(id, serialized_node_name) " + "VALUES (" + std::to_string(id) + ", ?);"; + CppSQLite3Statement stmt = m_database.compileStatement(statement.c_str()); + stmt.bind(1, nodeName.c_str()); + executeStatement(stmt); + + return id; +} + +Id SqliteBookmarkStorage::addBookmarkedEdge(const Id bookmarkId, const std::string& sourceNodeName, const std::string& targetNodeName, const int edgeType, const bool sourceNodeActive) +{ + executeStatement("INSERT INTO bookmarked_element(id, bookmark_id) VALUES(NULL, " + std::to_string(bookmarkId) + ");"); + Id id = m_database.lastRowId(); + + std::string statement = "INSERT INTO bookmarked_edge(id, serialized_source_node_name, serialized_target_node_name, edge_type, source_node_active) " + "VALUES (" + std::to_string(id) + ", ?, ?, " + std::to_string(edgeType) + ", " + std::to_string(sourceNodeActive) + ");"; + CppSQLite3Statement stmt = m_database.compileStatement(statement.c_str()); + stmt.bind(1, sourceNodeName.c_str()); + stmt.bind(2, targetNodeName.c_str()); + executeStatement(stmt); + + return id; +} + +std::vector SqliteBookmarkStorage::getAllBookmarks() const +{ + return doGetAll(""); +} + +void SqliteBookmarkStorage::removeBookmark(const Id id) +{ + executeStatement( + "DELETE FROM bookmark WHERE id = (" + std::to_string(id) + ");" + ); +} + +std::vector SqliteBookmarkStorage::getAllBookmarkedNodes() const +{ + return doGetAll(""); +} + +std::vector SqliteBookmarkStorage::getAllBookmarkedEdges() const +{ + return doGetAll(""); +} + +void SqliteBookmarkStorage::updateBookmark(const Id bookmarkId, const std::string& name, const std::string& comment, const Id categoryId) +{ + executeStatement("UPDATE bookmark SET name = '" + name + "' WHERE id == " + std::to_string(bookmarkId) + ";"); + executeStatement("UPDATE bookmark SET comment = '" + comment + "' WHERE id == " + std::to_string(bookmarkId) + ";"); + executeStatement("UPDATE bookmark SET category_id = " + std::to_string(categoryId) + " WHERE id == " + std::to_string(bookmarkId) + ";"); +} + +std::vector SqliteBookmarkStorage::getAllBookmarkCategories() const +{ + return doGetAll(""); +} + +StorageBookmarkCategory SqliteBookmarkStorage::getBookmarkCategoryByName(const std::string& name) const +{ + return doGetFirst("WHERE name == '" + name + "'"); +} + +void SqliteBookmarkStorage::removeBookmarkCategory(Id id) +{ + executeStatement( + "DELETE FROM bookmark_category WHERE id = (" + std::to_string(id) + ");" + ); +} + +size_t SqliteBookmarkStorage::getStaticStorageVersion() const +{ + return s_storageVersion; +} + +std::vector> SqliteBookmarkStorage::getIndices() const +{ + return std::vector>(); +} + +void SqliteBookmarkStorage::clearTables() +{ + try + { + m_database.execDML("DROP TABLE IF EXISTS main.bookmarked_edge;"); + m_database.execDML("DROP TABLE IF EXISTS main.bookmarked_node;"); + m_database.execDML("DROP TABLE IF EXISTS main.bookmarked_element;"); + m_database.execDML("DROP TABLE IF EXISTS main.bookmark;"); + m_database.execDML("DROP TABLE IF EXISTS main.bookmark_category;"); + } + catch (CppSQLite3Exception& e) + { + LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage()); + } +} + +void SqliteBookmarkStorage::setupTables() +{ + try + { + m_database.execDML( + "CREATE TABLE IF NOT EXISTS bookmark_category(" + "id INTEGER NOT NULL, " + "name TEXT, " + "PRIMARY KEY(id)" + ");" + ); + + m_database.execDML( + "CREATE TABLE IF NOT EXISTS bookmark(" + "id INTEGER NOT NULL, " + "name TEXT, " + "comment TEXT, " + "timestamp TEXT, " + "category_id INTEGER, " + "FOREIGN KEY(category_id) REFERENCES bookmark_category(id) ON DELETE CASCADE, " + "PRIMARY KEY(id)" + ");" + ); + + m_database.execDML( + "CREATE TABLE IF NOT EXISTS bookmarked_element(" + "id INTEGER NOT NULL, " + "bookmark_id INTEGER NOT NULL, " + "FOREIGN KEY(bookmark_id) REFERENCES bookmark(id) ON DELETE CASCADE, " + "PRIMARY KEY(id)" + ");" + ); + + m_database.execDML( + "CREATE TABLE IF NOT EXISTS bookmarked_node(" + "id INTEGER NOT NULL, " + "serialized_node_name TEXT, " + "FOREIGN KEY(id) REFERENCES bookmarked_element(id) ON DELETE CASCADE, " + "PRIMARY KEY(id)" + ");" + ); + + m_database.execDML( + "CREATE TABLE IF NOT EXISTS bookmarked_edge(" + "id INTEGER NOT NULL, " + "serialized_source_node_name TEXT, " + "serialized_target_node_name TEXT, " + "edge_type INTEGER, " + "source_node_active INTEGER, " + "FOREIGN KEY(id) REFERENCES bookmarked_element(id) ON DELETE CASCADE, " + "PRIMARY KEY(id)" + ");" + ); + } + catch (CppSQLite3Exception& e) + { + LOG_ERROR_STREAM(<< "Failed to create tables: " << std::to_string(e.errorCode()) << ": " << e.errorMessage()); + throw e; + } + catch (std::exception& e) + { + LOG_ERROR_STREAM(<< "Failed to create tables: " << e.what()); + throw e; + } +} + +template <> +std::vector SqliteBookmarkStorage::doGetAll(const std::string& query) const +{ + CppSQLite3Query q = executeQuery( + "SELECT id, name FROM bookmark_category " + query + ";" + ); + + std::vector categories; + while (!q.eof()) + { + const Id id = q.getIntField(0, 0); + const std::string name = q.getStringField(1, ""); + + if (id != 0 && name != "") + { + categories.push_back(StorageBookmarkCategory(id, name)); + } + + q.nextRow(); + } + return categories; +} + +template <> +std::vector SqliteBookmarkStorage::doGetAll(const std::string& query) const +{ + CppSQLite3Query q = executeQuery( + "SELECT id, name, comment, timestamp, category_id FROM bookmark " + query + ";" + ); + + std::vector bookmarks; + while (!q.eof()) + { + const Id id = q.getIntField(0, 0); + const std::string name = q.getStringField(1, ""); + const std::string comment = q.getStringField(2, ""); + const std::string timestamp = q.getStringField(3, ""); + const Id categoryId = q.getIntField(4, 0); + + if (id != 0 && name != "" && timestamp != "") + { + bookmarks.push_back(StorageBookmark(id, name, comment, timestamp, categoryId)); + } + + q.nextRow(); + } + return bookmarks; +} + +template <> +std::vector SqliteBookmarkStorage::doGetAll(const std::string& query) const +{ + CppSQLite3Query q = executeQuery( + "SELECT " + "bookmarked_node.id, bookmarked_element.bookmark_id, bookmarked_node.serialized_node_name " + "FROM bookmarked_node " + "INNER JOIN " + "bookmarked_element ON bookmarked_node.id = bookmarked_element.id " + query + ";" + ); + + std::vector bookmarkedNodes; + while (!q.eof()) + { + const Id id = q.getIntField(0, 0); + const Id bookmarkId = q.getIntField(1, 0); + const std::string serializedNodeName = q.getStringField(2, ""); + + if (id != 0 && bookmarkId != 0 && serializedNodeName != "") + { + bookmarkedNodes.push_back(StorageBookmarkedNode(id, bookmarkId, serializedNodeName)); + } + + q.nextRow(); + } + return bookmarkedNodes; +} + +template <> +std::vector SqliteBookmarkStorage::doGetAll(const std::string& query) const +{ + CppSQLite3Query q = executeQuery( + "SELECT " + "bookmarked_edge.id, bookmarked_element.bookmark_id, bookmarked_edge.serialized_source_node_name, bookmarked_edge.serialized_target_node_name, bookmarked_edge.edge_type, bookmarked_edge.source_node_active " + "FROM bookmarked_edge " + "INNER JOIN " + "bookmarked_element ON bookmarked_edge.id = bookmarked_element.id " + query + ";" + ); + + std::vector bookmarkedEdges; + while (!q.eof()) + { + const Id id = q.getIntField(0, 0); + const Id bookmarkId = q.getIntField(1, 0); + const std::string serializedSourceNodeName = q.getStringField(2, ""); + const std::string serializedTargetNodeName = q.getStringField(3, ""); + const int edgeType = q.getIntField(4, -1); + const int sourceNodeActive = q.getIntField(5, -1); + + if (id != 0 && bookmarkId != 0 && serializedSourceNodeName != "" && serializedTargetNodeName != "" && edgeType != -1 && sourceNodeActive != -1) + { + bookmarkedEdges.push_back(StorageBookmarkedEdge(id, bookmarkId, serializedSourceNodeName, serializedTargetNodeName, edgeType, sourceNodeActive)); + } + + q.nextRow(); + } + return bookmarkedEdges; +} diff --git a/src/lib/data/SqliteBookmarkStorage.h b/src/lib/data/SqliteBookmarkStorage.h new file mode 100644 index 00000000..911b87dd --- /dev/null +++ b/src/lib/data/SqliteBookmarkStorage.h @@ -0,0 +1,72 @@ +#ifndef SQLITE_BOOKMARK_STORAGE_H +#define SQLITE_BOOKMARK_STORAGE_H + +#include "sqlite/CppSQLite3.h" + +#include "data/bookmark/BookmarkCategory.h" +#include "data/bookmark/EdgeBookmark.h" +#include "data/bookmark/NodeBookmark.h" +#include "data/SqliteStorage.h" +#include "data/StorageTypes.h" +#include "utility/file/FilePath.h" +#include "utility/types.h" + +class SqliteBookmarkStorage + : public SqliteStorage +{ +public: + SqliteBookmarkStorage(const FilePath& dbFilePath); + virtual ~SqliteBookmarkStorage(); + + Id addBookmarkCategory(const std::string& name); + Id addBookmark(const std::string& name, const std::string& comment, const std::string& timestamp, const Id categoryId); + Id addBookmarkedNode(const Id bookmarkId, const std::string& nodeName); + Id addBookmarkedEdge(const Id bookmarkId, const std::string& sourceNodeName, const std::string& targetNodeName, const int edgeType, const bool sourceNodeActive); + + void removeBookmarkCategory(Id id); + void removeBookmark(const Id id); + + std::vector getAllBookmarks() const; + std::vector getAllBookmarkedNodes() const; + std::vector getAllBookmarkedEdges() const; + + void updateBookmark(const Id bookmarkId, const std::string& name, const std::string& comment, const Id categoryId); + + std::vector getAllBookmarkCategories() const; + StorageBookmarkCategory getBookmarkCategoryByName(const std::string& name) const; + +private: + static const size_t s_storageVersion; + + virtual size_t getStaticStorageVersion() const; + virtual std::vector> getIndices() const; + virtual void clearTables(); + virtual void setupTables(); + + //void updateBookmarkMetaData(const BookmarkMetaData& metaData); + + template + std::vector doGetAll(const std::string& query) const; + + template + ResultType doGetFirst(const std::string& query) const + { + std::vector results = doGetAll(query + " LIMIT 1"); + if (results.size() > 0) + { + return results[0]; + } + return ResultType(); + } +}; + +template <> +std::vector SqliteBookmarkStorage::doGetAll(const std::string& query) const; +template <> +std::vector SqliteBookmarkStorage::doGetAll(const std::string& query) const; +template <> +std::vector SqliteBookmarkStorage::doGetAll(const std::string& query) const; +template <> +std::vector SqliteBookmarkStorage::doGetAll(const std::string& query) const; + +#endif // SQLITE_BOOKMARK_STORAGE_H diff --git a/src/lib/data/SqliteDatabaseIndex.cpp b/src/lib/data/SqliteDatabaseIndex.cpp new file mode 100644 index 00000000..cf274fef --- /dev/null +++ b/src/lib/data/SqliteDatabaseIndex.cpp @@ -0,0 +1,25 @@ +#include "data/SqliteDatabaseIndex.h" + +SqliteDatabaseIndex::SqliteDatabaseIndex(const std::string& indexName, const std::string& indexTarget) + : m_indexName(indexName) + , m_indexTarget(indexTarget) +{ +} + +SqliteDatabaseIndex::~SqliteDatabaseIndex() +{ +} + +void SqliteDatabaseIndex::createOnDatabase(CppSQLite3DB& database) +{ + database.execDML(( + "CREATE INDEX IF NOT EXISTS " + m_indexName + " ON " + m_indexTarget + ";" + ).c_str()); +} + +void SqliteDatabaseIndex::removeFromDatabase(CppSQLite3DB& database) +{ + database.execDML(( + "DROP INDEX IF EXISTS main." + m_indexName + ";" + ).c_str()); +} diff --git a/src/lib/data/SqliteDatabaseIndex.h b/src/lib/data/SqliteDatabaseIndex.h new file mode 100644 index 00000000..0ef19b56 --- /dev/null +++ b/src/lib/data/SqliteDatabaseIndex.h @@ -0,0 +1,21 @@ +#ifndef SQLITE_DATABASE_INDEX_H +#define SQLITE_DATABASE_INDEX_H + +#include +#include "sqlite/CppSQLite3.h" + +class SqliteDatabaseIndex +{ +public: + SqliteDatabaseIndex(const std::string& indexName, const std::string& indexTarget); + ~SqliteDatabaseIndex(); + + void createOnDatabase(CppSQLite3DB& database); + void removeFromDatabase(CppSQLite3DB& database); + +private: + std::string m_indexName; + std::string m_indexTarget; +}; + +#endif // SQLITE_DATABASE_INDEX_H diff --git a/src/lib/data/SqliteIndex.cpp b/src/lib/data/SqliteIndex.cpp deleted file mode 100644 index d95e3ef7..00000000 --- a/src/lib/data/SqliteIndex.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "data/SqliteIndex.h" - -SqliteIndex::SqliteIndex(const std::string& indexName, const std::string& indexTarget) - : m_indexName(indexName) - , m_indexTarget(indexTarget) -{ -} - -SqliteIndex::~SqliteIndex() -{ -} - -void SqliteIndex::createOnDatabase(CppSQLite3DB& database) -{ - database.execDML(( - "CREATE INDEX IF NOT EXISTS " + m_indexName + " ON " + m_indexTarget + ";" - ).c_str()); -} - -void SqliteIndex::removeFromDatabase(CppSQLite3DB& database) -{ - database.execDML(( - "DROP INDEX IF EXISTS main." + m_indexName + ";" - ).c_str()); -} diff --git a/src/lib/data/SqliteIndex.h b/src/lib/data/SqliteIndex.h deleted file mode 100644 index 68dac7c9..00000000 --- a/src/lib/data/SqliteIndex.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef SQLITE_INDEX_H -#define SQLITE_INDEX_H - -#include -#include "sqlite/CppSQLite3.h" - -class SqliteIndex -{ -public: - SqliteIndex(const std::string& indexName, const std::string& indexTarget); - ~SqliteIndex(); - - void createOnDatabase(CppSQLite3DB& database); - void removeFromDatabase(CppSQLite3DB& database); - -private: - std::string m_indexName; - std::string m_indexTarget; -}; - -#endif // SQLITE_INDEX_H diff --git a/src/lib/data/SqliteIndexStorage.cpp b/src/lib/data/SqliteIndexStorage.cpp new file mode 100644 index 00000000..9466d457 --- /dev/null +++ b/src/lib/data/SqliteIndexStorage.cpp @@ -0,0 +1,1169 @@ +#include "data/SqliteIndexStorage.h" + +#include + +#include "data/graph/Node.h" +#include "data/parser/ParseLocation.h" +#include "utility/logging/logging.h" +#include "utility/text/TextAccess.h" +#include "utility/Version.h" + +const size_t SqliteIndexStorage::s_storageVersion = 11; + +SqliteIndexStorage::SqliteIndexStorage(const FilePath& dbFilePath) + : SqliteStorage(dbFilePath.canonical()) +{ +} + +SqliteIndexStorage::~SqliteIndexStorage() +{ +} + +std::string SqliteIndexStorage::getProjectSettingsText() const +{ + return getMetaValue("project_settings"); +} + +void SqliteIndexStorage::setProjectSettingsText(std::string text) +{ + insertOrUpdateMetaValue("project_settings", text); +} + +Id SqliteIndexStorage::addEdge(int type, Id sourceNodeId, Id targetNodeId) +{ + executeStatement("INSERT INTO element(id) VALUES(NULL);"); + Id id = m_database.lastRowId(); + + executeStatement( + "INSERT INTO edge(id, type, source_node_id, target_node_id) VALUES(" + + std::to_string(id) + ", " + std::to_string(type) + ", " + + std::to_string(sourceNodeId) + ", " + std::to_string(targetNodeId) + ");" + ); + + return id; +} + +Id SqliteIndexStorage::addNode(const int type, const std::string& serializedName) +{ + executeStatement("INSERT INTO element(id) VALUES(NULL);"); + Id id = m_database.lastRowId(); + + CppSQLite3Statement stmt = m_database.compileStatement(( + "INSERT INTO node(id, type, serialized_name) VALUES(" + + std::to_string(id) + ", " + std::to_string(type) + ", ?);" + ).c_str()); + + stmt.bind(1, serializedName.c_str()); + executeStatement(stmt); + + return id; +} + +void SqliteIndexStorage::addSymbol(const int id, const int definitionKind) +{ + executeStatement( + "INSERT INTO symbol(id, definition_kind) VALUES(" + + std::to_string(id) + ", " + std::to_string(definitionKind) + ");" + ); +} + +void SqliteIndexStorage::addFile(const int id, const std::string& filePath, const std::string& modificationTime, bool complete) +{ + std::shared_ptr content = TextAccess::createFromFile(filePath); + unsigned int lineCount = content->getLineCount(); + + executeStatement( + "INSERT INTO file(id, path, modification_time, complete, line_count) VALUES(" + + std::to_string(id) + ", '" + filePath + "', '" + modificationTime + "', '" + std::to_string(complete) + "', " + std::to_string(lineCount) + ");" + ); + + CppSQLite3Statement stmt = m_database.compileStatement(( + "INSERT INTO filecontent(id, content) VALUES(" + + std::to_string(id) + ", ?);" + ).c_str()); + + stmt.bind(1, content->getText().c_str()); + executeStatement(stmt); + +} + +Id SqliteIndexStorage::addLocalSymbol(const std::string& name) +{ + executeStatement("INSERT INTO element(id) VALUES(NULL);"); + Id id = m_database.lastRowId(); + + CppSQLite3Statement stmt = m_database.compileStatement(( + "INSERT INTO local_symbol(id, name) VALUES(" + + std::to_string(id) + ", ?);" + ).c_str()); + + stmt.bind(1, name.c_str()); + executeStatement(stmt); + + return id; +} + +Id SqliteIndexStorage::addSourceLocation( + Id fileNodeId, uint startLine, uint startCol, uint endLine, uint endCol, int type) +{ + executeStatement( + "INSERT INTO source_location(id, file_node_id, start_line, start_column, end_line, end_column, type) " + "VALUES(NULL, " + std::to_string(fileNodeId) + ", " + + std::to_string(startLine) + ", " + std::to_string(startCol) + ", " + + std::to_string(endLine) + ", " + std::to_string(endCol) + ", " + std::to_string(type) + ");" + ); + + return m_database.lastRowId(); +} + +bool SqliteIndexStorage::addOccurrence(Id elementId, Id sourceLocationId) +{ + try + { + m_database.execDML(( + "INSERT INTO occurrence(element_id, source_location_id) " + "VALUES(" + std::to_string(elementId) + ", " + + std::to_string(sourceLocationId) + ");" + ).c_str()); + } + catch (CppSQLite3Exception& e) + { + return false; + } + return true; +} + +Id SqliteIndexStorage::addComponentAccess(Id nodeId, int type) +{ + executeStatement( + "INSERT INTO component_access(id, node_id, type) " + "VALUES (NULL, " + std::to_string(nodeId) + ", " + std::to_string(type) + ");" + ); + + return m_database.lastRowId(); +} + +Id SqliteIndexStorage::addCommentLocation(Id fileNodeId, uint startLine, uint startCol, uint endLine, uint endCol) +{ + executeStatement( + "INSERT INTO comment_location(id, file_node_id, start_line, start_column, end_line, end_column) " + "VALUES(NULL, " + std::to_string(fileNodeId) + ", " + + std::to_string(startLine) + ", " + std::to_string(startCol) + ", " + + std::to_string(endLine) + ", " + std::to_string(endCol) + ");" + ); + + return m_database.lastRowId(); +} + +Id SqliteIndexStorage::addError(const std::string& message, const FilePath& filePath, uint lineNumber, uint columnNumber, bool fatal, bool indexed) +{ + std::string sanitizedMessage = utility::replace(message, "'", "''"); + + // check for duplicate + CppSQLite3Statement stmt = m_database.compileStatement(( + "SELECT * FROM error WHERE " + "message == ? AND " + "fatal == " + std::to_string(fatal) + " AND " + "file_path == '" + filePath.str() + "' AND " + "line_number == " + std::to_string(lineNumber) + " AND " + "column_number == " + std::to_string(columnNumber) + ";" + ).c_str()); + + stmt.bind(1, sanitizedMessage.c_str()); + CppSQLite3Query q = executeQuery(stmt); + + if (!q.eof()) + { + return q.getIntField(0, -1); + } + + stmt.finalize(); + + stmt = m_database.compileStatement(( + "INSERT INTO error(message, fatal, indexed, file_path, line_number, column_number) " + "VALUES (?, " + std::to_string(fatal) + ", " + std::to_string(indexed) + ", '" + filePath.str() + + "', " + std::to_string(lineNumber) + ", " + std::to_string(columnNumber) + ");" + ).c_str()); + + stmt.bind(1, sanitizedMessage.c_str()); + executeStatement(stmt); + + return m_database.lastRowId(); +} + +void SqliteIndexStorage::removeElement(Id id) +{ + std::vector ids; + ids.push_back(id); + removeElements(ids); +} + +void SqliteIndexStorage::removeElements(const std::vector& ids) +{ + executeStatement( + "DELETE FROM element WHERE id IN (" + utility::join(utility::toStrings(ids), ',') + ");" + ); +} + +void SqliteIndexStorage::removeElementsWithLocationInFiles(const std::vector& fileIds, std::function updateStatusCallback) +{ + if (updateStatusCallback != nullptr) + { + updateStatusCallback(1); + } + + // preparing + executeStatement("DROP TABLE IF EXISTS main.element_id_to_clear;"); + + if (updateStatusCallback != nullptr) + { + updateStatusCallback(2); + } + + executeStatement( + "CREATE TABLE IF NOT EXISTS element_id_to_clear(" + "id INTEGER NOT NULL, " + "PRIMARY KEY(id));" + ); + + if (updateStatusCallback != nullptr) + { + updateStatusCallback(3); + } + + // store ids of all elements located in fileIds into element_id_to_clear + executeStatement( + "INSERT INTO element_id_to_clear " + " SELECT occurrence.element_id " + " FROM occurrence " + " INNER JOIN source_location ON (" + " occurrence.source_location_id = source_location.id" + " ) " + " WHERE source_location.file_node_id IN (" + utility::join(utility::toStrings(fileIds), ',') + ")" + " GROUP BY (occurrence.element_id)" + ); + + if (updateStatusCallback != nullptr) + { + updateStatusCallback(4); + } + + // delete all edges in element_id_to_clear + executeStatement( + "DELETE FROM element WHERE element.id IN (SELECT element_id_to_clear.id FROM element_id_to_clear INNER JOIN edge ON (element_id_to_clear.id = edge.id))" + ); + + if (updateStatusCallback != nullptr) + { + updateStatusCallback(22); + } + + // delete all edges originating from element_id_to_clear + executeStatement( + "DELETE FROM element WHERE element.id IN (SELECT id FROM edge WHERE source_node_id IN (SELECT id FROM element_id_to_clear))" + ); + + if (updateStatusCallback != nullptr) + { + updateStatusCallback(23); + } + + // remove all edges from element_id_to_clear (they have been cleared by now and we can disregard them) + executeStatement( + "DELETE FROM element_id_to_clear WHERE id IN (" + " SELECT id FROM edge" + ")" + ); + + if (updateStatusCallback != nullptr) + { + updateStatusCallback(24); + } + + // remove all files from element_id_to_clear (they will be cleared later) + executeStatement( + "DELETE FROM element_id_to_clear WHERE id IN (" + " SELECT id FROM file" + ")" + ); + + if (updateStatusCallback != nullptr) + { + updateStatusCallback(25); + } + + // delete source locations from fileIds (this also deletes the respective occurrences) + executeStatement( + "DELETE FROM source_location WHERE file_node_id IN (" + utility::join(utility::toStrings(fileIds), ',') + ");" + ); + + if (updateStatusCallback != nullptr) + { + updateStatusCallback(34); + } + + // remove all ids from element_id_to_clear that still have occurrences + executeStatement( + "DELETE FROM element_id_to_clear WHERE id IN (" + " SELECT element_id_to_clear.id FROM element_id_to_clear INNER JOIN occurrence ON element_id_to_clear.id = occurrence.element_id" + ")" + ); + + if (updateStatusCallback != nullptr) + { + updateStatusCallback(35); + } + + // remove all ids from element_id_to_clear that still have an edge pointing to them + executeStatement( + "DELETE FROM element_id_to_clear WHERE id IN (" + " SELECT target_node_id FROM edge" + ")" + ); + + if (updateStatusCallback != nullptr) + { + updateStatusCallback(44); + } + + // delete all elements that are still listed in element_id_to_clear + executeStatement( + "DELETE FROM element WHERE id IN (" + " SELECT id FROM element_id_to_clear" + ")" + ); + + if (updateStatusCallback != nullptr) + { + updateStatusCallback(80); + } + + // cleaning up + executeStatement("DROP TABLE IF EXISTS main.element_id_to_clear;"); + + if (updateStatusCallback != nullptr) + { + updateStatusCallback(89); + } +} + +void SqliteIndexStorage::removeErrorsInFiles(const std::vector& filePaths) +{ + executeStatement( + "DELETE FROM error WHERE file_path IN ('" + utility::join(utility::toStrings(filePaths), "', '") + "');" + ); +} + +bool SqliteIndexStorage::isEdge(Id elementId) const +{ + int count = executeStatementScalar("SELECT count(*) FROM edge WHERE id = " + std::to_string(elementId) + ";"); + return (count > 0); +} + +bool SqliteIndexStorage::isNode(Id elementId) const +{ + int count = executeStatementScalar("SELECT count(*) FROM node WHERE id = " + std::to_string(elementId) + ";"); + return (count > 0); +} + +bool SqliteIndexStorage::isFile(Id elementId) const +{ + int count = executeStatementScalar("SELECT count(*) FROM file WHERE id = " + std::to_string(elementId) + ";"); + return (count > 0); +} + +StorageEdge SqliteIndexStorage::getEdgeById(Id edgeId) const +{ + std::vector candidates = doGetAll("WHERE id = " + std::to_string(edgeId)); + + if (candidates.size() > 0) + { + return candidates[0]; + } + + return StorageEdge(); +} + +StorageEdge SqliteIndexStorage::getEdgeBySourceTargetType(Id sourceId, Id targetId, int type) const +{ + return doGetFirst("WHERE " + "source_node_id == " + std::to_string(sourceId) + " AND " + "target_node_id == " + std::to_string(targetId) + " AND " + "type == " + std::to_string(type) + ); +} + +std::vector SqliteIndexStorage::getEdgesBySourceId(Id sourceId) const +{ + return doGetAll("WHERE source_node_id == " + std::to_string(sourceId)); +} + +std::vector SqliteIndexStorage::getEdgesBySourceIds(const std::vector& sourceIds) const +{ + return doGetAll("WHERE source_node_id IN (" + utility::join(utility::toStrings(sourceIds), ',') + ")"); +} + +std::vector SqliteIndexStorage::getEdgesByTargetId(Id targetId) const +{ + return doGetAll("WHERE target_node_id == " + std::to_string(targetId)); +} + +std::vector SqliteIndexStorage::getEdgesByTargetIds(const std::vector& targetIds) const +{ + return doGetAll("WHERE target_node_id IN (" + utility::join(utility::toStrings(targetIds), ',') + ")"); +} + +std::vector SqliteIndexStorage::getEdgesBySourceOrTargetId(Id id) const +{ + return doGetAll("WHERE source_node_id == " + std::to_string(id) + " OR target_node_id == " + std::to_string(id)); +} + +std::vector SqliteIndexStorage::getEdgesByType(int type) const +{ + return doGetAll("WHERE type == " + std::to_string(type)); +} + +std::vector SqliteIndexStorage::getEdgesBySourceType(Id sourceId, int type) const +{ + return doGetAll("WHERE source_node_id == " + std::to_string(sourceId) + " AND type == " + std::to_string(type)); +} + +std::vector SqliteIndexStorage::getEdgesBySourcesType(const std::vector& sourceIds, int type) const +{ + return doGetAll("WHERE source_node_id IN (" + utility::join(utility::toStrings(sourceIds), ',') + ") AND type == " + std::to_string(type)); +} + +std::vector SqliteIndexStorage::getEdgesByTargetType(Id targetId, int type) const +{ + return doGetAll("WHERE target_node_id == " + std::to_string(targetId) + " AND type == " + std::to_string(type)); +} + +std::vector SqliteIndexStorage::getEdgesByTargetsType(const std::vector& targetIds, int type) const +{ + return doGetAll("WHERE target_node_id IN (" + utility::join(utility::toStrings(targetIds), ',') + ") AND type == " + std::to_string(type)); +} + +bool SqliteIndexStorage::checkEdgeExists(Id edgeId) const +{ + CppSQLite3Statement stmt = m_database.compileStatement( + ("SELECT type FROM edge WHERE id == " + std::to_string(edgeId) + ";").c_str() + ); + + CppSQLite3Query q = executeQuery(stmt); + + if (!q.eof()) + { + const int type = q.getIntField(0, -1); + + if (type != -1) + { + return true; + } + } + + return false; +} + +StorageNode SqliteIndexStorage::getNodeById(Id id) const +{ + std::vector candidates = doGetAll("WHERE id = " + std::to_string(id)); + + if (candidates.size() > 0) + { + return candidates[0]; + } + + return StorageNode(); +} + +StorageNode SqliteIndexStorage::getNodeBySerializedName(const std::string& serializedName) const +{ + CppSQLite3Statement stmt = m_database.compileStatement( + "SELECT id, type, serialized_name FROM node WHERE serialized_name == ? LIMIT 1;" + ); + + stmt.bind(1, serializedName.c_str()); + CppSQLite3Query q = executeQuery(stmt); + + if (!q.eof()) + { + const Id id = q.getIntField(0, 0); + const int type = q.getIntField(1, -1); + const std::string serializedName = q.getStringField(2, ""); + + if (id != 0 && type != -1) + { + return StorageNode(id, type, serializedName); + } + } + + return StorageNode(); +} + +bool SqliteIndexStorage::checkNodeExistsByName(const std::string& serializedName) const +{ + CppSQLite3Statement stmt = m_database.compileStatement( + "SELECT id FROM node WHERE serialized_name == ? LIMIT 1;" + ); + + stmt.bind(1, serializedName.c_str()); + CppSQLite3Query q = executeQuery(stmt); + + if (!q.eof()) + { + const Id id = q.getIntField(0, 0); + + if (id != -1) + { + return true; + } + } + + return false; +} + +StorageLocalSymbol SqliteIndexStorage::getLocalSymbolByName(const std::string& name) const +{ + return doGetFirst("WHERE name == '" + name + "'"); +} + +StorageFile SqliteIndexStorage::getFileByPath(const std::string& filePath) const +{ + return doGetFirst("WHERE file.path == '" + filePath + "'"); +} + +std::vector SqliteIndexStorage::getFilesByPaths(const std::vector& filePaths) const +{ + return doGetAll("WHERE file.path IN ('" + utility::join(utility::toStrings(filePaths), "', '") + "')"); +} + +std::shared_ptr SqliteIndexStorage::getFileContentById(Id fileId) const +{ + CppSQLite3Query q = executeQuery( + "SELECT content FROM filecontent WHERE id = '" + std::to_string(fileId) + "';" + ); + if (!q.eof()) + { + return TextAccess::createFromString(q.getStringField(0, "")); + } + + return TextAccess::createFromString(""); +} + +std::shared_ptr SqliteIndexStorage::getFileContentByPath(const std::string& filePath) const +{ + try + { + CppSQLite3Query q = executeQuery( + "SELECT filecontent.content " + "FROM filecontent " + "INNER JOIN file ON filecontent.id = file.id " + "WHERE file.path = '" + filePath + "';" + ); + + if (!q.eof()) + { + return TextAccess::createFromString(q.getStringField(0, "")); + } + } + catch (CppSQLite3Exception& e) + { + LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage()); + } + + return TextAccess::createFromFile(filePath); +} + +void SqliteIndexStorage::setFileComplete(bool complete, Id fileId) +{ + executeStatement( + "UPDATE file SET complete = " + std::to_string(complete) + " WHERE id == " + std::to_string(fileId) + ";" + ); +} + +void SqliteIndexStorage::setNodeType(int type, Id nodeId) +{ + executeStatement( + "UPDATE node SET type = " + std::to_string(type) + " WHERE id == " + std::to_string(nodeId) + ";" + ); +} + +StorageSourceLocation SqliteIndexStorage::getSourceLocationByAll(const Id fileNodeId, const uint startLine, const uint startCol, const uint endLine, const uint endCol, const int type) const +{ + return doGetFirst( + "WHERE file_node_id == " + std::to_string(fileNodeId) + + " AND start_line == " + std::to_string(startLine) + + " AND start_column == " + std::to_string(startCol) + + " AND end_line == " + std::to_string(endLine) + + " AND end_column == " + std::to_string(endCol) + + " AND type == " + std::to_string(type) + ";" + ); +} + +std::shared_ptr SqliteIndexStorage::getSourceLocationsForFile(const FilePath& filePath) const +{ + std::shared_ptr ret = std::make_shared(filePath, true, false); + + const StorageFile file = getFileByPath(filePath.str()); + if (file.id == 0) // early out + { + return ret; + } + + ret->setIsComplete(file.complete); + + std::vector sourceLocationIds; + std::unordered_map sourceLocationIdToData; + for (const StorageSourceLocation& storageLocation: + doGetAll("WHERE file_node_id == " + std::to_string(file.id))) + { + sourceLocationIds.push_back(storageLocation.id); + sourceLocationIdToData[storageLocation.id] = storageLocation; + } + + std::map> sourceLocationIdToElementIds; + for (const StorageOccurrence& occurrence: getOccurrencesForLocationIds(sourceLocationIds)) + { + sourceLocationIdToElementIds[occurrence.sourceLocationId].push_back(occurrence.elementId); + } + + for (const std::pair>& p : sourceLocationIdToElementIds) + { + auto it = sourceLocationIdToData.find(p.first); + if (it != sourceLocationIdToData.end()) + { + ret->addSourceLocation( + intToLocationType(it->second.type), + it->second.id, + p.second, + it->second.startLine, + it->second.startCol, + it->second.endLine, + it->second.endCol + ); + } + } + + return ret; +} + +std::vector SqliteIndexStorage::getOccurrencesForLocationId(Id locationId) const +{ + std::vector locationIds {locationId}; + return getOccurrencesForLocationIds(locationIds); +} + +std::vector SqliteIndexStorage::getOccurrencesForLocationIds(const std::vector& locationIds) const +{ + return doGetAll("WHERE source_location_id IN (" + utility::join(utility::toStrings(locationIds), ',') + ")"); +} + +std::vector SqliteIndexStorage::getOccurrencesForElementIds(const std::vector& elementIds) const +{ + return doGetAll("WHERE element_id IN (" + utility::join(utility::toStrings(elementIds), ',') + ")"); +} + +StorageComponentAccess SqliteIndexStorage::getComponentAccessByNodeId(Id nodeId) const +{ + return doGetFirst("WHERE node_id == " + std::to_string(nodeId)); +} + +std::vector SqliteIndexStorage::getComponentAccessesByNodeIds(const std::vector& nodeIds) const +{ + return doGetAll("WHERE node_id IN (" + utility::join(utility::toStrings(nodeIds), ',') + ")"); +} + +std::vector SqliteIndexStorage::getCommentLocationsInFile(const FilePath& filePath) const +{ + Id fileNodeId = getFileByPath(filePath.str()).id; + return doGetAll("WHERE file_node_id == " + std::to_string(fileNodeId)); +} + +int SqliteIndexStorage::getNodeCount() const +{ + return executeStatementScalar("SELECT COUNT(*) FROM node;"); +} + +int SqliteIndexStorage::getEdgeCount() const +{ + return executeStatementScalar("SELECT COUNT(*) FROM edge;"); +} + +int SqliteIndexStorage::getFileCount() const +{ + return executeStatementScalar("SELECT COUNT(*) FROM file;"); +} + +int SqliteIndexStorage::getCompletedFileCount() const +{ + return executeStatementScalar("SELECT COUNT(*) FROM file WHERE complete = 1;"); +} + +int SqliteIndexStorage::getFileLineSum() const +{ + return executeStatementScalar("SELECT SUM(line_count) FROM file;"); +} + +int SqliteIndexStorage::getSourceLocationCount() const +{ + return executeStatementScalar("SELECT COUNT(*) FROM source_location;"); +} + +std::vector> SqliteIndexStorage::getIndices() const +{ + std::vector> indices; + indices.push_back(std::make_pair( + STORAGE_MODE_WRITE, + SqliteDatabaseIndex("edge_multipart_index", "edge(type, source_node_id, target_node_id)") + )); + indices.push_back(std::make_pair( + STORAGE_MODE_WRITE | STORAGE_MODE_READ | STORAGE_MODE_CLEAR, + SqliteDatabaseIndex("node_serialized_name_index", "node(serialized_name)") + )); + indices.push_back(std::make_pair( + STORAGE_MODE_WRITE, + SqliteDatabaseIndex("local_symbol_name_index", "local_symbol(name)") + )); + indices.push_back(std::make_pair( + STORAGE_MODE_READ | STORAGE_MODE_CLEAR, + SqliteDatabaseIndex("source_location_file_node_id_index", "source_location(file_node_id)") + )); + indices.push_back(std::make_pair( + STORAGE_MODE_WRITE, + SqliteDatabaseIndex("source_location_all_data_index", "source_location(file_node_id, start_line, start_column, end_line, end_column, type)") + )); + indices.push_back(std::make_pair( + STORAGE_MODE_READ | STORAGE_MODE_CLEAR, + SqliteDatabaseIndex("occurrence_element_id_index", "occurrence(element_id)") + )); + indices.push_back(std::make_pair( + STORAGE_MODE_CLEAR, + SqliteDatabaseIndex("occurrence_source_location_id_index", "occurrence(source_location_id)") + )); + indices.push_back(std::make_pair( + STORAGE_MODE_WRITE | STORAGE_MODE_READ | STORAGE_MODE_CLEAR, + SqliteDatabaseIndex("component_access_node_id_index", "component_access(node_id)") + )); + return indices; +} + +void SqliteIndexStorage::clearTables() +{ + try + { + m_database.execDML("DROP TABLE IF EXISTS main.error;"); + m_database.execDML("DROP TABLE IF EXISTS main.comment_location;"); + m_database.execDML("DROP TABLE IF EXISTS main.component_access;"); + m_database.execDML("DROP TABLE IF EXISTS main.occurrence;"); + m_database.execDML("DROP TABLE IF EXISTS main.source_location;"); + m_database.execDML("DROP TABLE IF EXISTS main.local_symbol;"); + m_database.execDML("DROP TABLE IF EXISTS main.filecontent;"); + m_database.execDML("DROP TABLE IF EXISTS main.file;"); + m_database.execDML("DROP TABLE IF EXISTS main.symbol;"); + m_database.execDML("DROP TABLE IF EXISTS main.node;"); + m_database.execDML("DROP TABLE IF EXISTS main.edge;"); + m_database.execDML("DROP TABLE IF EXISTS main.element;"); + m_database.execDML("DROP TABLE IF EXISTS main.meta;"); + } + catch (CppSQLite3Exception& e) + { + LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage()); + } +} + +void SqliteIndexStorage::setupTables() +{ + try + { + m_database.execDML( + "CREATE TABLE IF NOT EXISTS element(" + "id INTEGER, " + "PRIMARY KEY(id));" + ); + + m_database.execDML( + "CREATE TABLE IF NOT EXISTS edge(" + "id INTEGER NOT NULL, " + "type INTEGER NOT NULL, " + "source_node_id INTEGER NOT NULL, " + "target_node_id INTEGER NOT NULL, " + "PRIMARY KEY(id), " + "FOREIGN KEY(id) REFERENCES element(id) ON DELETE CASCADE, " + "FOREIGN KEY(source_node_id) REFERENCES node(id) ON DELETE CASCADE, " + "FOREIGN KEY(target_node_id) REFERENCES node(id) ON DELETE CASCADE);" + ); + + m_database.execDML( + "CREATE TABLE IF NOT EXISTS node(" + "id INTEGER NOT NULL, " + "type INTEGER NOT NULL, " + "serialized_name TEXT, " + "PRIMARY KEY(id), " + "FOREIGN KEY(id) REFERENCES element(id) ON DELETE CASCADE);" + ); + + m_database.execDML( + "CREATE TABLE IF NOT EXISTS symbol(" + "id INTEGER NOT NULL, " + "definition_kind INTEGER NOT NULL, " + "PRIMARY KEY(id), " + "FOREIGN KEY(id) REFERENCES node(id) ON DELETE CASCADE);" + ); + + m_database.execDML( + "CREATE TABLE IF NOT EXISTS file(" + "id INTEGER NOT NULL, " + "path TEXT, " + "modification_time TEXT, " + "complete INTEGER, " + "line_count INTEGER, " + "PRIMARY KEY(id), " + "FOREIGN KEY(id) REFERENCES node(id) ON DELETE CASCADE);" + ); + + m_database.execDML( + "CREATE TABLE IF NOT EXISTS filecontent(" + "id INTERGER, " + "content TEXT, " + "FOREIGN KEY(id)" + "REFERENCES file(id)" + "ON DELETE CASCADE " + "ON UPDATE CASCADE);" + ); + + m_database.execDML( + "CREATE TABLE IF NOT EXISTS local_symbol(" + "id INTEGER NOT NULL, " + "name TEXT, " + "PRIMARY KEY(id), " + "FOREIGN KEY(id) REFERENCES element(id) ON DELETE CASCADE);" + ); + + m_database.execDML( + "CREATE TABLE IF NOT EXISTS source_location(" + "id INTEGER NOT NULL, " + "file_node_id INTEGER, " + "start_line INTEGER, " + "start_column INTEGER, " + "end_line INTEGER, " + "end_column INTEGER, " + "type INTEGER, " + "PRIMARY KEY(id), " + "FOREIGN KEY(file_node_id) REFERENCES node(id) ON DELETE CASCADE);" + ); + + m_database.execDML( + "CREATE TABLE IF NOT EXISTS occurrence(" + "element_id INTEGER NOT NULL, " + "source_location_id INTEGER NOT NULL, " + "PRIMARY KEY(element_id, source_location_id), " + "FOREIGN KEY(element_id) REFERENCES element(id) ON DELETE CASCADE, " + "FOREIGN KEY(source_location_id) REFERENCES source_location(id) ON DELETE CASCADE);" + ); + + m_database.execDML( + "CREATE TABLE IF NOT EXISTS component_access(" + "id INTEGER NOT NULL, " + "node_id INTEGER, " + "type INTEGER NOT NULL, " + "PRIMARY KEY(id), " + "FOREIGN KEY(node_id) REFERENCES node(id) ON DELETE CASCADE);" + ); + + m_database.execDML( + "CREATE TABLE IF NOT EXISTS comment_location(" + "id INTEGER NOT NULL, " + "file_node_id INTEGER, " + "start_line INTEGER, " + "start_column INTEGER, " + "end_line INTEGER, " + "end_column INTEGER, " + "PRIMARY KEY(id), " + "FOREIGN KEY(file_node_id) REFERENCES node(id) ON DELETE CASCADE);" + ); + + m_database.execDML( + "CREATE TABLE IF NOT EXISTS error(" + "id INTEGER NOT NULL, " + "message TEXT, " + "fatal INTEGER NOT NULL, " + "indexed INTEGER NOT NULL, " + "file_path TEXT, " + "line_number INTEGER, " + "column_number INTEGER, " + "PRIMARY KEY(id));" + ); + } + catch (CppSQLite3Exception& e) + { + LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage()); + + throw(std::exception()); + + // todo: cancel project creation and destroy created files, display message + } +} + +size_t SqliteIndexStorage::getStaticStorageVersion() const +{ + return s_storageVersion; +} + +template <> +std::vector SqliteIndexStorage::doGetAll(const std::string& query) const +{ + CppSQLite3Query q = executeQuery( + "SELECT id, type, source_node_id, target_node_id FROM edge " + query + ";" + ); + + 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; +} + +template <> +std::vector SqliteIndexStorage::doGetAll(const std::string& query) const +{ + CppSQLite3Query q = executeQuery( + "SELECT id, type, serialized_name FROM node " + query + ";" + ); + + std::vector nodes; + while (!q.eof()) + { + const Id id = q.getIntField(0, 0); + const int type = q.getIntField(1, -1); + const std::string serializedName = q.getStringField(2, ""); + + if (id != 0 && type != -1) + { + nodes.push_back(StorageNode(id, type, serializedName)); + } + + q.nextRow(); + } + return nodes; +} + +template <> +std::vector SqliteIndexStorage::doGetAll(const std::string& query) const +{ + CppSQLite3Query q = executeQuery( + "SELECT id, definition_kind FROM symbol " + query + ";" + ); + + std::vector symbols; + while (!q.eof()) + { + const Id id = q.getIntField(0, 0); + const int definitionKind = q.getIntField(1, 0); + + if (id != 0) + { + symbols.push_back(StorageSymbol(id, definitionKind)); + } + + q.nextRow(); + } + return symbols; +} + +template <> +std::vector SqliteIndexStorage::doGetAll(const std::string& query) const +{ + CppSQLite3Query q = executeQuery( + "SELECT id, path, modification_time, complete FROM file " + query + ";" + ); + + std::vector files; + while (!q.eof()) + { + const Id id = q.getIntField(0, 0); + const std::string filePath = q.getStringField(1, ""); + const std::string modificationTime = q.getStringField(2, ""); + const bool complete = q.getIntField(3, 0); + + if (id != 0) + { + files.push_back(StorageFile(id, filePath, modificationTime, complete)); + } + q.nextRow(); + } + + return files; +} + +template <> +std::vector SqliteIndexStorage::doGetAll(const std::string& query) const +{ + CppSQLite3Query q = executeQuery( + "SELECT id, name FROM local_symbol " + query + ";" + ); + + std::vector localSymbols; + + while (!q.eof()) + { + const Id id = q.getIntField(0, 0); + const std::string name = q.getStringField(1, ""); + + if (id != 0) + { + localSymbols.push_back(StorageLocalSymbol(id, name)); + } + + q.nextRow(); + } + return localSymbols; +} + +template <> +std::vector SqliteIndexStorage::doGetAll(const std::string& query) const +{ + CppSQLite3Query q = executeQuery( + "SELECT id, file_node_id, start_line, start_column, end_line, end_column, type FROM source_location " + query + ";" + ); + + std::vector sourceLocations; + + while (!q.eof()) + { + const Id id = q.getIntField(0, 0); + const Id fileNodeId = q.getIntField(1, 0); + const int startLineNumber = q.getIntField(2, -1); + const int startColNumber = q.getIntField(3, -1); + const int endLineNumber = q.getIntField(4, -1); + const int endColNumber = q.getIntField(5, -1); + const int type = q.getIntField(6, -1); + + if (id != 0 && fileNodeId != 0 && startLineNumber != -1 && startColNumber != -1 && endLineNumber != -1 && endColNumber != -1 && type != -1) + { + sourceLocations.push_back(StorageSourceLocation(id, fileNodeId, startLineNumber, startColNumber, endLineNumber, endColNumber, type)); + } + + q.nextRow(); + } + return sourceLocations; +} + +template <> +std::vector SqliteIndexStorage::doGetAll(const std::string& query) const +{ + CppSQLite3Query q = executeQuery( + "SELECT element_id, source_location_id FROM occurrence " + query + ";" + ); + + std::vector occurrences; + + while (!q.eof()) + { + const Id elementId = q.getIntField(0, 0); + const Id sourceLocationId = q.getIntField(1, 0); + + if (elementId != 0 && sourceLocationId != 0) + { + occurrences.push_back(StorageOccurrence(elementId, sourceLocationId)); + } + + q.nextRow(); + } + return occurrences; +} + +template <> +std::vector SqliteIndexStorage::doGetAll(const std::string& query) const +{ + CppSQLite3Query q = executeQuery( + "SELECT id, node_id, type FROM component_access " + query + ";" + ); + + std::vector componentAccesses; + + while (!q.eof()) + { + const Id id = q.getIntField(0, 0); + const Id nodeId = q.getIntField(1, 0); + const int type = q.getIntField(2, -1); + + if (id != 0 && nodeId != 0 && type != -1) + { + componentAccesses.push_back(StorageComponentAccess(nodeId, type)); + } + + q.nextRow(); + } + return componentAccesses; +} + +template <> +std::vector SqliteIndexStorage::doGetAll(const std::string& query) const +{ + CppSQLite3Query q = executeQuery( + "SELECT id, file_node_id, start_line, start_column, end_line, end_column FROM comment_location " + query + ";" + ); + + std::vector commentLocations; + + while (!q.eof()) + { + const Id id = q.getIntField(0, 0); + const Id fileNodeId = q.getIntField(1, 0); + const int startLineNumber = q.getIntField(2, -1); + const int startColNumber = q.getIntField(3, -1); + const int endLineNumber = q.getIntField(4, -1); + const int endColNumber = q.getIntField(5, -1); + + if (id != 0 && fileNodeId != 0 && startLineNumber != -1 && startColNumber != -1 && endLineNumber != -1 && endColNumber != -1) + { + commentLocations.push_back(StorageCommentLocation( + id, fileNodeId, startLineNumber, startColNumber, endLineNumber, endColNumber + )); + } + + q.nextRow(); + } + return commentLocations; +} + +template <> +std::vector SqliteIndexStorage::doGetAll(const std::string& query) const +{ + CppSQLite3Query q = executeQuery( + "SELECT message, fatal, indexed, file_path, line_number, column_number FROM error " + query + ";" + ); + + std::vector errors; + Id id = 1; + while (!q.eof()) + { + const std::string message = q.getStringField(0, ""); + const bool fatal = q.getIntField(1, 0); + const bool indexed = q.getIntField(2, 0); + const std::string filePath = q.getStringField(3, ""); + const int lineNumber = q.getIntField(4, -1); + const int columnNumber = q.getIntField(5, -1); + + if (lineNumber != -1 && columnNumber != -1) + { + errors.push_back(StorageError(id, message, filePath, lineNumber, columnNumber, fatal, indexed)); + id++; + } + + q.nextRow(); + } + + return errors; +} diff --git a/src/lib/data/SqliteIndexStorage.h b/src/lib/data/SqliteIndexStorage.h new file mode 100644 index 00000000..a6d5db9e --- /dev/null +++ b/src/lib/data/SqliteIndexStorage.h @@ -0,0 +1,176 @@ +#ifndef SQLITE_INDEX_STORAGE_H +#define SQLITE_INDEX_STORAGE_H + +#include +#include +#include + +#include "data/location/SourceLocationFile.h" +#include "data/name/NameHierarchy.h" +#include "data/StorageTypes.h" +#include "data/SqliteDatabaseIndex.h" +#include "utility/file/FilePath.h" +#include "utility/types.h" +#include "utility/utility.h" +#include "utility/utilityString.h" + +#include "data/SqliteStorage.h" + +class TextAccess; +class Version; +struct ParseLocation; + +class SqliteIndexStorage + : public SqliteStorage +{ +public: + SqliteIndexStorage(const FilePath& dbFilePath); + virtual ~SqliteIndexStorage(); + + std::string getProjectSettingsText() const; + void setProjectSettingsText(std::string text); + + Id addEdge(int type, Id sourceNodeId, Id targetNodeId); + + Id addNode(const int type, const std::string& serializedName); + void addSymbol(const int id, int definitionKind); + void addFile(const int id, const std::string& filePath, const std::string& modificationTime, bool complete); + Id addLocalSymbol(const std::string& name); + Id addSourceLocation(Id fileNodeId, uint startLine, uint startCol, uint endLine, uint endCol, int type); + bool addOccurrence(Id elementId, Id sourceLocationId); + Id addComponentAccess(Id nodeId, int type); + Id addCommentLocation(Id fileNodeId, uint startLine, uint startCol, uint endLine, uint endCol); + Id addError(const std::string& message, const FilePath& filePath, uint lineNumber, uint columnNumber, bool fatal, bool indexed); + + void removeElement(Id id); + void removeElements(const std::vector& ids); + void removeElementsWithLocationInFiles(const std::vector& fileIds, std::function updateStatusCallback); + + void removeErrorsInFiles(const std::vector& filePaths); + + bool isEdge(Id elementId) const; + bool isNode(Id elementId) const; + bool isFile(Id elementId) const; + + StorageEdge getEdgeById(Id edgeId) const; + 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 getEdgesByType(int type) const; + std::vector getEdgesBySourceType(Id sourceId, int type) const; + std::vector getEdgesBySourcesType(const std::vector& sourceIds, int type) const; + std::vector getEdgesByTargetType(Id targetId, int type) const; + std::vector getEdgesByTargetsType(const std::vector& targetIds, int type) const; + + bool checkEdgeExists(Id edgeId) const; + + StorageNode getNodeById(Id id) const; + StorageNode getNodeBySerializedName(const std::string& serializedName) const; + bool checkNodeExistsByName(const std::string& serializedName) const; + + StorageLocalSymbol getLocalSymbolByName(const std::string& name) const; + + StorageFile getFileByPath(const std::string& filePath) const; + + std::vector getFilesByPaths(const std::vector& filePaths) const; + std::shared_ptr getFileContentByPath(const std::string& filePath) const; + std::shared_ptr getFileContentById(Id fileId) const; + + void setFileComplete(bool complete, Id fileId); + void setNodeType(int type, Id nodeId); + + StorageSourceLocation getSourceLocationByAll(const Id fileNodeId, const uint startLine, const uint startCol, const uint endLine, const uint endCol, const int type) const; + std::shared_ptr getSourceLocationsForFile(const FilePath& filePath) const; + + std::vector getOccurrencesForLocationId(Id locationId) const; + std::vector getOccurrencesForLocationIds(const std::vector& locationIds) const; + std::vector getOccurrencesForElementIds(const std::vector& elementIds) const; + + StorageComponentAccess getComponentAccessByNodeId(Id memberEdgeId) const; + std::vector getComponentAccessesByNodeIds(const std::vector& memberEdgeIds) const; + + std::vector getCommentLocationsInFile(const FilePath& filePath) const; + + template + std::vector getAll() const + { + return doGetAll(""); + } + + template + ResultType getFirstById(const Id id) const + { + if (id != 0) + { + return doGetFirst("WHERE id == " + std::to_string(id)); + } + return ResultType(); + } + + template + std::vector getAllByIds(const std::vector& ids) const + { + if (ids.size()) + { + return doGetAll("WHERE id IN (" + utility::join(utility::toStrings(ids), ',') + ")"); + } + return std::vector(); + } + + int getNodeCount() const; + int getEdgeCount() const; + int getFileCount() const; + int getCompletedFileCount() const; + int getFileLineSum() const; + int getSourceLocationCount() const; + +private: + static const size_t s_storageVersion; + + virtual size_t getStaticStorageVersion() const; + virtual std::vector> getIndices() const; + virtual void clearTables(); + virtual void setupTables(); + + template + std::vector doGetAll(const std::string& query) const; + + template + ResultType doGetFirst(const std::string& query) const + { + std::vector results = doGetAll(query + " LIMIT 1"); + if (results.size() > 0) + { + return results[0]; + } + return ResultType(); + } +}; + +template <> +std::vector SqliteIndexStorage::doGetAll(const std::string& query) const; +template <> +std::vector SqliteIndexStorage::doGetAll(const std::string& query) const; +template <> +std::vector SqliteIndexStorage::doGetAll(const std::string& query) const; +template <> +std::vector SqliteIndexStorage::doGetAll(const std::string& query) const; +template <> +std::vector SqliteIndexStorage::doGetAll(const std::string& query) const; +template <> +std::vector SqliteIndexStorage::doGetAll(const std::string& query) const; +template <> +std::vector SqliteIndexStorage::doGetAll(const std::string& query) const; +template <> +std::vector SqliteIndexStorage::doGetAll(const std::string& query) const; +template <> +std::vector SqliteIndexStorage::doGetAll(const std::string& query) const; +template <> +std::vector SqliteIndexStorage::doGetAll(const std::string& query) const; + +#endif // SQLITE_INDEX_STORAGE_H diff --git a/src/lib/data/SqliteStorage.cpp b/src/lib/data/SqliteStorage.cpp index f0b5284a..a385db50 100644 --- a/src/lib/data/SqliteStorage.cpp +++ b/src/lib/data/SqliteStorage.cpp @@ -1,14 +1,6 @@ -#include "data/SqliteStorage.h" +#include "SqliteStorage.h" -#include - -#include "data/graph/Node.h" -#include "data/parser/ParseLocation.h" #include "utility/logging/logging.h" -#include "utility/text/TextAccess.h" -#include "utility/Version.h" - -const size_t SqliteStorage::STORAGE_VERSION = 11; SqliteStorage::SqliteStorage(const FilePath& dbFilePath) : m_dbFilePath(dbFilePath.canonical()) @@ -18,39 +10,6 @@ SqliteStorage::SqliteStorage(const FilePath& dbFilePath) executeStatement("PRAGMA foreign_keys=ON;"); m_mode = STORAGE_MODE_UNKNOWN; - - m_indices.push_back(std::make_pair( - STORAGE_MODE_WRITE, - SqliteIndex("edge_multipart_index", "edge(type, source_node_id, target_node_id)") - )); - m_indices.push_back(std::make_pair( - STORAGE_MODE_WRITE | STORAGE_MODE_READ | STORAGE_MODE_CLEAR, - SqliteIndex("node_serialized_name_index", "node(serialized_name)") - )); - m_indices.push_back(std::make_pair( - STORAGE_MODE_WRITE, - SqliteIndex("local_symbol_name_index", "local_symbol(name)") - )); - m_indices.push_back(std::make_pair( - STORAGE_MODE_READ | STORAGE_MODE_CLEAR, - SqliteIndex("source_location_file_node_id_index", "source_location(file_node_id)") - )); - m_indices.push_back(std::make_pair( - STORAGE_MODE_WRITE, - SqliteIndex("source_location_all_data_index", "source_location(file_node_id, start_line, start_column, end_line, end_column, type)") - )); - m_indices.push_back(std::make_pair( - STORAGE_MODE_READ | STORAGE_MODE_CLEAR, - SqliteIndex("occurrence_element_id_index", "occurrence(element_id)") - )); - m_indices.push_back(std::make_pair( - STORAGE_MODE_CLEAR, - SqliteIndex("occurrence_source_location_id_index", "occurrence(source_location_id)") - )); - m_indices.push_back(std::make_pair( - STORAGE_MODE_WRITE | STORAGE_MODE_READ | STORAGE_MODE_CLEAR, - SqliteIndex("component_access_node_id_index", "component_access(node_id)") - )); } SqliteStorage::~SqliteStorage() @@ -59,7 +18,7 @@ SqliteStorage::~SqliteStorage() { m_database.close(); } - catch(CppSQLite3Exception e) + catch (CppSQLite3Exception e) { LOG_ERROR(e.errorMessage()); } @@ -67,7 +26,10 @@ SqliteStorage::~SqliteStorage() void SqliteStorage::setup() { + m_indices = getIndices(); + executeStatement("PRAGMA foreign_keys=ON;"); + setupMetaTable(); setupTables(); m_mode = STORAGE_MODE_UNKNOWN; } @@ -75,6 +37,7 @@ void SqliteStorage::setup() void SqliteStorage::clear() { executeStatement("PRAGMA foreign_keys=OFF;"); + clearMetaTable(); clearTables(); setup(); @@ -142,7 +105,7 @@ bool SqliteStorage::isEmpty() const bool SqliteStorage::isIncompatible() const { size_t storageVersion = getStorageVersion(); - if (storageVersion == 0 || storageVersion != STORAGE_VERSION) + if (storageVersion == 0 || storageVersion != getStaticStorageVersion()) { return true; } @@ -150,1106 +113,13 @@ bool SqliteStorage::isIncompatible() const return false; } -std::string SqliteStorage::getProjectSettingsText() const -{ - return getMetaValue("project_settings"); -} - -void SqliteStorage::setProjectSettingsText(std::string text) -{ - insertOrUpdateMetaValue("project_settings", text); -} - void SqliteStorage::setVersion() { setStorageVersion(); setApplicationVersion(); } -Id SqliteStorage::addEdge(int type, Id sourceNodeId, Id targetNodeId) -{ - executeStatement("INSERT INTO element(id) VALUES(NULL);"); - Id id = m_database.lastRowId(); - - executeStatement( - "INSERT INTO edge(id, type, source_node_id, target_node_id) VALUES(" - + std::to_string(id) + ", " + std::to_string(type) + ", " - + std::to_string(sourceNodeId) + ", " + std::to_string(targetNodeId) + ");" - ); - - return id; -} - -Id SqliteStorage::addNode(const int type, const std::string& serializedName) -{ - executeStatement("INSERT INTO element(id) VALUES(NULL);"); - Id id = m_database.lastRowId(); - - CppSQLite3Statement stmt = m_database.compileStatement(( - "INSERT INTO node(id, type, serialized_name) VALUES(" - + std::to_string(id) + ", " + std::to_string(type) + ", ?);" - ).c_str()); - - stmt.bind(1, serializedName.c_str()); - executeStatement(stmt); - - return id; -} - -void SqliteStorage::addSymbol(const int id, const int definitionKind) -{ - executeStatement( - "INSERT INTO symbol(id, definition_kind) VALUES(" - + std::to_string(id) + ", " + std::to_string(definitionKind) + ");" - ); -} - -void SqliteStorage::addFile(const int id, const std::string& filePath, const std::string& modificationTime, bool complete) -{ - std::shared_ptr content = TextAccess::createFromFile(filePath); - unsigned int lineCount = content->getLineCount(); - - executeStatement( - "INSERT INTO file(id, path, modification_time, complete, line_count) VALUES(" - + std::to_string(id) + ", '" + filePath + "', '" + modificationTime + "', '" + std::to_string(complete) + "', " + std::to_string(lineCount) + ");" - ); - - CppSQLite3Statement stmt = m_database.compileStatement(( - "INSERT INTO filecontent(id, content) VALUES(" - + std::to_string(id) + ", ?);" - ).c_str()); - - stmt.bind(1, content->getText().c_str()); - executeStatement(stmt); -} - -Id SqliteStorage::addLocalSymbol(const std::string& name) -{ - executeStatement("INSERT INTO element(id) VALUES(NULL);"); - Id id = m_database.lastRowId(); - - CppSQLite3Statement stmt = m_database.compileStatement(( - "INSERT INTO local_symbol(id, name) VALUES(" - + std::to_string(id) + ", ?);" - ).c_str()); - - stmt.bind(1, name.c_str()); - executeStatement(stmt); - - return id; -} - -Id SqliteStorage::addSourceLocation( - Id fileNodeId, uint startLine, uint startCol, uint endLine, uint endCol, int type) -{ - executeStatement( - "INSERT INTO source_location(id, file_node_id, start_line, start_column, end_line, end_column, type) " - "VALUES(NULL, " + std::to_string(fileNodeId) + ", " - + std::to_string(startLine) + ", " + std::to_string(startCol) + ", " - + std::to_string(endLine) + ", " + std::to_string(endCol) + ", " + std::to_string(type) + ");" - ); - - return m_database.lastRowId(); -} - -bool SqliteStorage::addOccurrence(Id elementId, Id sourceLocationId) -{ - try - { - m_database.execDML(( - "INSERT INTO occurrence(element_id, source_location_id) " - "VALUES(" + std::to_string(elementId) + ", " - + std::to_string(sourceLocationId) + ");" - ).c_str()); - } - catch (CppSQLite3Exception& e) - { - return false; - } - return true; -} - -Id SqliteStorage::addComponentAccess(Id nodeId, int type) -{ - executeStatement( - "INSERT INTO component_access(id, node_id, type) " - "VALUES (NULL, " + std::to_string(nodeId) + ", " + std::to_string(type) + ");" - ); - - return m_database.lastRowId(); -} - -Id SqliteStorage::addCommentLocation(Id fileNodeId, uint startLine, uint startCol, uint endLine, uint endCol) -{ - executeStatement( - "INSERT INTO comment_location(id, file_node_id, start_line, start_column, end_line, end_column) " - "VALUES(NULL, " + std::to_string(fileNodeId) + ", " - + std::to_string(startLine) + ", " + std::to_string(startCol) + ", " - + std::to_string(endLine) + ", " + std::to_string(endCol) + ");" - ); - - return m_database.lastRowId(); -} - -Id SqliteStorage::addError(const std::string& message, const FilePath& filePath, uint lineNumber, uint columnNumber, bool fatal, bool indexed) -{ - std::string sanitizedMessage = utility::replace(message, "'", "''"); - - // check for duplicate - CppSQLite3Statement stmt = m_database.compileStatement(( - "SELECT * FROM error WHERE " - "message == ? AND " - "fatal == " + std::to_string(fatal) + " AND " - "file_path == '" + filePath.str() + "' AND " - "line_number == " + std::to_string(lineNumber) + " AND " - "column_number == " + std::to_string(columnNumber) + ";" - ).c_str()); - - stmt.bind(1, sanitizedMessage.c_str()); - CppSQLite3Query q = executeQuery(stmt); - - if (!q.eof()) - { - return q.getIntField(0, -1); - } - - stmt.finalize(); - - stmt = m_database.compileStatement(( - "INSERT INTO error(message, fatal, indexed, file_path, line_number, column_number) " - "VALUES (?, " + std::to_string(fatal) + ", " + std::to_string(indexed) + ", '" + filePath.str() + - "', " + std::to_string(lineNumber) + ", " + std::to_string(columnNumber) + ");" - ).c_str()); - - stmt.bind(1, sanitizedMessage.c_str()); - executeStatement(stmt); - - return m_database.lastRowId(); -} - -Id SqliteStorage::addNodeBookmark(const NodeBookmark& bookmark) -{ - std::string tokenName = bookmark.getDisplayName(); - std::string comment = bookmark.getComment(); - std::string timeStamp = bookmark.getTimeStamp().toString(); - - tokenName = utility::replace(tokenName, "'", "''"); - comment = utility::replace(comment, "'", "''"); - - /*tokenName = utility::replace(tokenName, "\\", "/"); - comment = utility::replace(comment, "\\", "/");*/ - - std::string statement = "INSERT INTO nodeBookmark(name, comment, timestamp, category) " - "VALUES (?, ?, ?, ?);"; - - int categoryId = getOrCreateBookmarkCategoryByName(bookmark.getCategory().getName()).getId(); - - CppSQLite3Statement stmt = m_database.compileStatement(statement.c_str()); - stmt.bind(1, tokenName.c_str()); - stmt.bind(2, comment.c_str()); - stmt.bind(3, timeStamp.c_str()); - stmt.bind(4, categoryId); - - stmt.execDML(); - - Id id = m_database.lastRowId(); - - for (unsigned int i = 0; i < bookmark.getTokenNames().size(); i++) - { - std::string name = bookmark.getTokenNames()[i]; - int type = bookmark.getTokenTypes()[i]; - - statement = "INSERT INTO nodeBookmarkToken(bookmarkId, name, type) " - "VALUES (" + std::to_string(id) + ", ?, " + std::to_string(type) + ");"; - - stmt = m_database.compileStatement(statement.c_str()); - stmt.bind(1, name.c_str()); - - stmt.execDML(); - } - - return id; -} - -Id SqliteStorage::addEdgeBookmark(const EdgeBookmark& bookmark) -{ - std::string tokenName = bookmark.getDisplayName(); - std::string comment = bookmark.getComment(); - std::string timeStamp = bookmark.getTimeStamp().toString(); - - tokenName = utility::replace(tokenName, "'", "''"); - comment = utility::replace(comment, "'", "''"); - - std::string statement = "INSERT INTO edgeBookmark(name, comment, timestamp, category) " - "VALUES (?, ?, ?, ?);"; - - int categoryId = getOrCreateBookmarkCategoryByName(bookmark.getCategory().getName()).getId(); - - CppSQLite3Statement stmt = m_database.compileStatement(statement.c_str()); - stmt.bind(1, tokenName.c_str()); - stmt.bind(2, comment.c_str()); - stmt.bind(3, timeStamp.c_str()); - stmt.bind(4, categoryId); - - stmt.execDML(); - - Id id = m_database.lastRowId(); - - for (unsigned int i = 0; i < bookmark.getEdgeTokenNames().size(); i++) - { - std::string name = bookmark.getEdgeTokenNames()[i]; - int type = bookmark.getEdgeTokenTypes()[i]; - - statement = "INSERT INTO edgeBookmarkToken(bookmarkId, name, type) " - "VALUES (" + std::to_string(id) + ", ?, " + std::to_string(type) + ");"; - - stmt = m_database.compileStatement(statement.c_str()); - stmt.bind(1, name.c_str()); - - stmt.execDML(); - } - - statement = "INSERT INTO edgeBaseBookmark(edgeId) " - "VALUES (" + std::to_string(id) + ");"; - stmt = m_database.compileStatement(statement.c_str()); - stmt.execDML(); - Id baseId = m_database.lastRowId(); - - for (unsigned int i = 0; i < bookmark.getTokenNames().size(); i++) - { - statement = "INSERT INTO edgeBaseBookmarkToken(bookmarkId, name, type) " - "VALUES (" + std::to_string(baseId) + ", ?, " + std::to_string(bookmark.getTokenTypes()[i]) + ");"; - - stmt = m_database.compileStatement(statement.c_str()); - stmt.bind(1, bookmark.getTokenNames()[i].c_str()); - - stmt.execDML(); - } - - return id; -} - -Id SqliteStorage::addBookmarkCategory(const std::string& name) -{ - std::string statement = "INSERT INTO bookmarkCategory(name) " - "VALUES (?);"; - - CppSQLite3Statement stmt = m_database.compileStatement(statement.c_str()); - stmt.bind(1, name.c_str()); - - stmt.execDML(); - - Id id = m_database.lastRowId(); - - return id; -} - -void SqliteStorage::removeElement(Id id) -{ - std::vector ids; - ids.push_back(id); - removeElements(ids); -} - -void SqliteStorage::removeElements(const std::vector& ids) -{ - executeStatement( - "DELETE FROM element WHERE id IN (" + utility::join(utility::toStrings(ids), ',') + ");" - ); -} - -void SqliteStorage::removeElementsWithLocationInFiles(const std::vector& fileIds, std::function updateStatusCallback) -{ - if (updateStatusCallback != nullptr) - { - updateStatusCallback(1); - } - - // preparing - executeStatement("DROP TABLE IF EXISTS main.element_id_to_clear;"); - - if (updateStatusCallback != nullptr) - { - updateStatusCallback(2); - } - - executeStatement( - "CREATE TABLE IF NOT EXISTS element_id_to_clear(" - "id INTEGER NOT NULL, " - "PRIMARY KEY(id));" - ); - - if (updateStatusCallback != nullptr) - { - updateStatusCallback(3); - } - - // store ids of all elements located in fileIds into element_id_to_clear - executeStatement( - "INSERT INTO element_id_to_clear " - " SELECT occurrence.element_id " - " FROM occurrence " - " INNER JOIN source_location ON (" - " occurrence.source_location_id = source_location.id" - " ) " - " WHERE source_location.file_node_id IN (" + utility::join(utility::toStrings(fileIds), ',') + ")" - " GROUP BY (occurrence.element_id)" - ); - - if (updateStatusCallback != nullptr) - { - updateStatusCallback(4); - } - - // delete all edges in element_id_to_clear - executeStatement( - "DELETE FROM element WHERE element.id IN (SELECT element_id_to_clear.id FROM element_id_to_clear INNER JOIN edge ON (element_id_to_clear.id = edge.id))" - ); - - if (updateStatusCallback != nullptr) - { - updateStatusCallback(22); - } - - // delete all edges originating from element_id_to_clear - executeStatement( - "DELETE FROM element WHERE element.id IN (SELECT id FROM edge WHERE source_node_id IN (SELECT id FROM element_id_to_clear))" - ); - - if (updateStatusCallback != nullptr) - { - updateStatusCallback(23); - } - - // remove all edges from element_id_to_clear (they have been cleared by now and we can disregard them) - executeStatement( - "DELETE FROM element_id_to_clear WHERE id IN (" - " SELECT id FROM edge" - ")" - ); - - if (updateStatusCallback != nullptr) - { - updateStatusCallback(24); - } - - // remove all files from element_id_to_clear (they will be cleared later) - executeStatement( - "DELETE FROM element_id_to_clear WHERE id IN (" - " SELECT id FROM file" - ")" - ); - - if (updateStatusCallback != nullptr) - { - updateStatusCallback(25); - } - - // delete source locations from fileIds (this also deletes the respective occurrences) - executeStatement( - "DELETE FROM source_location WHERE file_node_id IN (" + utility::join(utility::toStrings(fileIds), ',') + ");" - ); - - if (updateStatusCallback != nullptr) - { - updateStatusCallback(34); - } - - // remove all ids from element_id_to_clear that still have occurrences - executeStatement( - "DELETE FROM element_id_to_clear WHERE id IN (" - " SELECT element_id_to_clear.id FROM element_id_to_clear INNER JOIN occurrence ON element_id_to_clear.id = occurrence.element_id" - ")" - ); - - if (updateStatusCallback != nullptr) - { - updateStatusCallback(35); - } - - // remove all ids from element_id_to_clear that still have an edge pointing to them - executeStatement( - "DELETE FROM element_id_to_clear WHERE id IN (" - " SELECT target_node_id FROM edge" - ")" - ); - - if (updateStatusCallback != nullptr) - { - updateStatusCallback(44); - } - - // delete all elements that are still listed in element_id_to_clear - executeStatement( - "DELETE FROM element WHERE id IN (" - " SELECT id FROM element_id_to_clear" - ")" - ); - - if (updateStatusCallback != nullptr) - { - updateStatusCallback(80); - } - - // cleaning up - executeStatement("DROP TABLE IF EXISTS main.element_id_to_clear;"); - - if (updateStatusCallback != nullptr) - { - updateStatusCallback(89); - } -} - -void SqliteStorage::removeErrorsInFiles(const std::vector& filePaths) -{ - executeStatement( - "DELETE FROM error WHERE file_path IN ('" + utility::join(utility::toStrings(filePaths), "', '") + "');" - ); -} - -bool SqliteStorage::isEdge(Id elementId) const -{ - int count = executeScalar("SELECT count(*) FROM edge WHERE id = " + std::to_string(elementId) + ";"); - return (count > 0); -} - -bool SqliteStorage::isNode(Id elementId) const -{ - int count = executeScalar("SELECT count(*) FROM node WHERE id = " + std::to_string(elementId) + ";"); - return (count > 0); -} - -bool SqliteStorage::isFile(Id elementId) const -{ - int count = executeScalar("SELECT count(*) FROM file WHERE id = " + std::to_string(elementId) + ";"); - return (count > 0); -} - -StorageEdge SqliteStorage::getEdgeById(Id edgeId) const -{ - std::vector candidates = doGetAll("WHERE id = " + std::to_string(edgeId)); - - if (candidates.size() > 0) - { - return candidates[0]; - } - - return StorageEdge(); -} - -StorageEdge SqliteStorage::getEdgeBySourceTargetType(Id sourceId, Id targetId, int type) const -{ - return doGetFirst("WHERE " - "source_node_id == " + std::to_string(sourceId) + " AND " - "target_node_id == " + std::to_string(targetId) + " AND " - "type == " + std::to_string(type) - ); -} - -std::vector SqliteStorage::getEdgesBySourceId(Id sourceId) const -{ - return doGetAll("WHERE source_node_id == " + std::to_string(sourceId)); -} - -std::vector SqliteStorage::getEdgesBySourceIds(const std::vector& sourceIds) const -{ - return doGetAll("WHERE source_node_id IN (" + utility::join(utility::toStrings(sourceIds), ',') + ")"); -} - -std::vector SqliteStorage::getEdgesByTargetId(Id targetId) const -{ - return doGetAll("WHERE target_node_id == " + std::to_string(targetId)); -} - -std::vector SqliteStorage::getEdgesByTargetIds(const std::vector& targetIds) const -{ - return doGetAll("WHERE target_node_id IN (" + utility::join(utility::toStrings(targetIds), ',') + ")"); -} - -std::vector SqliteStorage::getEdgesBySourceOrTargetId(Id id) const -{ - return doGetAll("WHERE source_node_id == " + std::to_string(id) + " OR target_node_id == " + std::to_string(id)); -} - -std::vector SqliteStorage::getEdgesByType(int type) const -{ - return doGetAll("WHERE type == " + std::to_string(type)); -} - -std::vector SqliteStorage::getEdgesBySourceType(Id sourceId, int type) const -{ - return doGetAll("WHERE source_node_id == " + std::to_string(sourceId) + " AND type == " + std::to_string(type)); -} - -std::vector SqliteStorage::getEdgesBySourcesType(const std::vector& sourceIds, int type) const -{ - return doGetAll("WHERE source_node_id IN (" + utility::join(utility::toStrings(sourceIds), ',') + ") AND type == " + std::to_string(type)); -} - -std::vector SqliteStorage::getEdgesByTargetType(Id targetId, int type) const -{ - return doGetAll("WHERE target_node_id == " + std::to_string(targetId) + " AND type == " + std::to_string(type)); -} - -std::vector SqliteStorage::getEdgesByTargetsType(const std::vector& targetIds, int type) const -{ - return doGetAll("WHERE target_node_id IN (" + utility::join(utility::toStrings(targetIds), ',') + ") AND type == " + std::to_string(type)); -} - -bool SqliteStorage::checkEdgeExists(Id edgeId) const -{ - CppSQLite3Statement stmt = m_database.compileStatement( - ("SELECT type FROM edge WHERE id == " + std::to_string(edgeId) + ";").c_str() - ); - - CppSQLite3Query q = executeQuery(stmt); - - if (!q.eof()) - { - const int type = q.getIntField(0, -1); - - if (type != -1) - { - return true; - } - } - - return false; -} - -StorageNode SqliteStorage::getNodeById(Id id) const -{ - std::vector candidates = doGetAll("WHERE id = " + std::to_string(id)); - - if (candidates.size() > 0) - { - return candidates[0]; - } - - return StorageNode(); -} - -StorageNode SqliteStorage::getNodeBySerializedName(const std::string& serializedName) const -{ - CppSQLite3Statement stmt = m_database.compileStatement( - "SELECT id, type, serialized_name FROM node WHERE serialized_name == ? LIMIT 1;" - ); - - stmt.bind(1, serializedName.c_str()); - CppSQLite3Query q = executeQuery(stmt); - - if (!q.eof()) - { - const Id id = q.getIntField(0, 0); - const int type = q.getIntField(1, -1); - const std::string serializedName = q.getStringField(2, ""); - - if (id != 0 && type != -1) - { - return StorageNode(id, type, serializedName); - } - } - - return StorageNode(); -} - -bool SqliteStorage::checkNodeExistsByName(const std::string& serializedName) const -{ - CppSQLite3Statement stmt = m_database.compileStatement( - "SELECT id FROM node WHERE serialized_name == ? LIMIT 1;" - ); - - stmt.bind(1, serializedName.c_str()); - CppSQLite3Query q = executeQuery(stmt); - - if (!q.eof()) - { - const Id id = q.getIntField(0, 0); - - if (id != (Id)-1) - { - return true; - } - } - - return false; -} - -StorageLocalSymbol SqliteStorage::getLocalSymbolByName(const std::string& name) const -{ - return doGetFirst("WHERE name == '" + name + "'"); -} - -StorageFile SqliteStorage::getFileByPath(const std::string& filePath) const -{ - return doGetFirst("WHERE file.path == '" + filePath + "'"); -} - -std::vector SqliteStorage::getFilesByPaths(const std::vector& filePaths) const -{ - return doGetAll("WHERE file.path IN ('" + utility::join(utility::toStrings(filePaths), "', '") + "')"); -} - -std::shared_ptr SqliteStorage::getFileContentById(Id fileId) const -{ - CppSQLite3Query q = executeQuery( - "SELECT content FROM filecontent WHERE id = '" + std::to_string(fileId) + "';" - ); - if (!q.eof()) - { - return TextAccess::createFromString(q.getStringField(0, "")); - } - - return TextAccess::createFromString(""); -} - -std::shared_ptr SqliteStorage::getFileContentByPath(const std::string& filePath) const -{ - try - { - CppSQLite3Query q = executeQuery( - "SELECT filecontent.content " - "FROM filecontent " - "INNER JOIN file ON filecontent.id = file.id " - "WHERE file.path = '" + filePath + "';" - ); - - if (!q.eof()) - { - return TextAccess::createFromString(q.getStringField(0, "")); - } - } - catch (CppSQLite3Exception& e) - { - LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage()); - } - - return TextAccess::createFromFile(filePath); -} - -void SqliteStorage::setFileComplete(bool complete, Id fileId) -{ - executeStatement( - "UPDATE file SET complete = " + std::to_string(complete) + " WHERE id == " + std::to_string(fileId) + ";" - ); -} - -void SqliteStorage::setNodeType(int type, Id nodeId) -{ - executeStatement( - "UPDATE node SET type = " + std::to_string(type) + " WHERE id == " + std::to_string(nodeId) + ";" - ); -} - -StorageSourceLocation SqliteStorage::getSourceLocationByAll(const Id fileNodeId, const uint startLine, const uint startCol, const uint endLine, const uint endCol, const int type) const -{ - return doGetFirst( - "WHERE file_node_id == " + std::to_string(fileNodeId) + - " AND start_line == " + std::to_string(startLine) + - " AND start_column == " + std::to_string(startCol) + - " AND end_line == " + std::to_string(endLine) + - " AND end_column == " + std::to_string(endCol) + - " AND type == " + std::to_string(type) + ";" - ); -} - -std::shared_ptr SqliteStorage::getSourceLocationsForFile(const FilePath& filePath) const -{ - std::shared_ptr ret = std::make_shared(filePath, true, false); - - const StorageFile file = getFileByPath(filePath.str()); - if (file.id == 0) // early out - { - return ret; - } - - ret->setIsComplete(file.complete); - - std::vector sourceLocationIds; - std::unordered_map sourceLocationIdToData; - for (const StorageSourceLocation& storageLocation: - doGetAll("WHERE file_node_id == " + std::to_string(file.id))) - { - sourceLocationIds.push_back(storageLocation.id); - sourceLocationIdToData[storageLocation.id] = storageLocation; - } - - std::map> sourceLocationIdToElementIds; - for (const StorageOccurrence& occurrence: getOccurrencesForLocationIds(sourceLocationIds)) - { - sourceLocationIdToElementIds[occurrence.sourceLocationId].push_back(occurrence.elementId); - } - - for (const std::pair>& p : sourceLocationIdToElementIds) - { - auto it = sourceLocationIdToData.find(p.first); - if (it != sourceLocationIdToData.end()) - { - ret->addSourceLocation( - intToLocationType(it->second.type), - it->second.id, - p.second, - it->second.startLine, - it->second.startCol, - it->second.endLine, - it->second.endCol - ); - } - } - - return ret; -} - -std::vector SqliteStorage::getOccurrencesForLocationId(Id locationId) const -{ - std::vector locationIds {locationId}; - return getOccurrencesForLocationIds(locationIds); -} - -std::vector SqliteStorage::getOccurrencesForLocationIds(const std::vector& locationIds) const -{ - return doGetAll("WHERE source_location_id IN (" + utility::join(utility::toStrings(locationIds), ',') + ")"); -} - -std::vector SqliteStorage::getOccurrencesForElementIds(const std::vector& elementIds) const -{ - return doGetAll("WHERE element_id IN (" + utility::join(utility::toStrings(elementIds), ',') + ")"); -} - -StorageComponentAccess SqliteStorage::getComponentAccessByNodeId(Id nodeId) const -{ - return doGetFirst("WHERE node_id == " + std::to_string(nodeId)); -} - -std::vector SqliteStorage::getComponentAccessesByNodeIds(const std::vector& nodeIds) const -{ - return doGetAll("WHERE node_id IN (" + utility::join(utility::toStrings(nodeIds), ',') + ")"); -} - -std::vector SqliteStorage::getCommentLocationsInFile(const FilePath& filePath) const -{ - Id fileNodeId = getFileByPath(filePath.str()).id; - return doGetAll("WHERE file_node_id == " + std::to_string(fileNodeId)); -} - -std::vector SqliteStorage::getAllNodeBookmarks() const -{ - return doGetAll(""); -} - -NodeBookmark SqliteStorage::getNodeBookmarkById(const Id bookmarkId) const -{ - std::vector candidates = doGetAll("WHERE id = " + std::to_string(bookmarkId)); - - if (candidates.size() > 0) - { - return candidates[0]; - } - - return NodeBookmark(); -} - -bool SqliteStorage::checkNodeBookmarkExistsByNames(const std::vector& names) const -{ - // bookmarks can only be uniquly identified by their token names. - // therefore, a bookmark exists if there is an exactly matching set of 'bookmarkToken's with a common foreign key - - if (names.size() <= 0) - { - return false; - } - - std::set bookmarkIds; - bool insert = true; - - for (unsigned int i = 0; i < names.size(); i++) - { - CppSQLite3Query q = m_database.execQuery(( - "SELECT bookmarkId FROM nodeBookmarkToken WHERE name = '" + names[i] +"';" - ).c_str()); - - bool contains = false; - - while (!q.eof()) - { - int id = q.getIntField(0, -1); - - if (insert) - { - bookmarkIds.insert(id); - } - else - { - if (bookmarkIds.find(id) != bookmarkIds.end()) - { - contains = true; - } - } - - q.nextRow(); - } - - if ((contains == false && insert == false) - || bookmarkIds.size() <= 0) - { - return false; - } - - insert = false; - } - - return true; -} - -void SqliteStorage::removeNodeBookmark(Id id) -{ - executeStatement( - "DELETE FROM nodeBookmark WHERE id = (" + std::to_string(id) + ");" - ); -} - -void SqliteStorage::editNodeBookmark(const NodeBookmark& bookmark) -{ - std::string statement = "UPDATE nodeBookmark SET name=?, comment=?, category=? WHERE id=" + std::to_string(bookmark.getId()) + ";"; - - BookmarkCategory category = getBookmarkCategoryByName(bookmark.getCategory().getName()); - if (category.getId() == (Id)-1) - { - category.setId(addBookmarkCategory(bookmark.getCategory().getName())); - category.setName(bookmark.getCategory().getName()); - } - - CppSQLite3Statement stmt = m_database.compileStatement(statement.c_str()); - stmt.bind(1, bookmark.getDisplayName().c_str()); - stmt.bind(2, bookmark.getComment().c_str()); - stmt.bind(3, (int)category.getId()); - - stmt.execDML(); -} - -std::vector SqliteStorage::getAllEdgeBookmarks() const -{ - return doGetAll(""); -} - -EdgeBookmark SqliteStorage::getEdgeBookmarkById(const Id bookmarkId) const -{ - std::vector candidates = doGetAll("WHERE id = " + std::to_string(bookmarkId)); - - if (candidates.size() > 0) - { - return candidates[0]; - } - - return EdgeBookmark(); -} - -bool SqliteStorage::checkEdgeBookmarkExistsByNames(const std::vector& names) const -{ - if (names.size() <= 0) - { - return false; - } - - std::set bookmarkIds; - bool insert = true; - - for (unsigned int i = 0; i < names.size(); i++) - { - CppSQLite3Query q = m_database.execQuery(( - "SELECT bookmarkId FROM edgeBookmarkToken WHERE name = '" + names[i] + "';" - ).c_str()); - - bool contains = false; - - while (!q.eof()) - { - int id = q.getIntField(0, -1); - - if (insert) - { - bookmarkIds.insert(id); - } - else - { - if (bookmarkIds.find(id) != bookmarkIds.end()) - { - contains = true; - } - } - - q.nextRow(); - } - - if ((contains == false && insert == false) - || bookmarkIds.size() <= 0) - { - return false; - } - - insert = false; - } - - return true; -} - -void SqliteStorage::removeEdgeBookmark(Id id) -{ - executeStatement( - "DELETE FROM edgeBookmark WHERE id = (" + std::to_string(id) + ");" - ); -} - -void SqliteStorage::editEdgeBookmark(const EdgeBookmark& bookmark) -{ - std::string statement = "UPDATE edgeBookmark SET name=?, comment=?, category=? WHERE id=" + std::to_string(bookmark.getId()) + ";"; - - BookmarkCategory category = getBookmarkCategoryByName(bookmark.getCategory().getName()); - if (category.getId() == (Id)-1) - { - category.setId(addBookmarkCategory(bookmark.getCategory().getName())); - category.setName(bookmark.getCategory().getName()); - } - - CppSQLite3Statement stmt = m_database.compileStatement(statement.c_str()); - stmt.bind(1, bookmark.getDisplayName().c_str()); - stmt.bind(2, bookmark.getComment().c_str()); - stmt.bind(3, (int)category.getId()); - - stmt.execDML(); -} - -std::vector SqliteStorage::getAllBookmarkCategories() const -{ - return doGetAll(""); -} - -BookmarkCategory SqliteStorage::getBookmarkCategoryByName(const std::string& name) const -{ - BookmarkCategory category; - category.setName(""); - category.setId(-1); - - CppSQLite3Query q = m_database.execQuery(( - "SELECT id FROM bookmarkCategory WHERE name = '" + name + "';" - ).c_str()); - - while (!q.eof()) - { - int id = q.getIntField(0, -1); - - if (id > -1) - { - category.setName(name); - category.setId(id); - } - - q.nextRow(); - } - - return category; -} - -BookmarkCategory SqliteStorage::getOrCreateBookmarkCategoryByName(const std::string& name) -{ - if (checkBookmarkCategoryExists(name)) - { - return getBookmarkCategoryByName(name); - } - else - { - Id id = addBookmarkCategory(name); - BookmarkCategory result; - result.setName(name); - result.setId(id); - - return result; - } -} - -bool SqliteStorage::checkBookmarkCategoryExists(const std::string& name) const -{ - CppSQLite3Query q = m_database.execQuery(( - "SELECT id FROM bookmarkCategory WHERE name = '" + name + "';" - ).c_str()); - - while (!q.eof()) - { - int id = q.getIntField(0, -1); - - if (id > -1) - { - return true; - } - - q.nextRow(); - } - - return false; -} - -void SqliteStorage::removeBookmarkCategory(Id id) -{ - executeStatement( - "DELETE FROM bookmarkCategory WHERE id = (" + std::to_string(id) + ");" - ); -} - -int SqliteStorage::getNodeCount() const -{ - return executeScalar("SELECT COUNT(*) FROM node;"); -} - -int SqliteStorage::getEdgeCount() const -{ - return executeScalar("SELECT COUNT(*) FROM edge;"); -} - -int SqliteStorage::getFileCount() const -{ - return executeScalar("SELECT COUNT(*) FROM file;"); -} - -int SqliteStorage::getCompletedFileCount() const -{ - return executeScalar("SELECT COUNT(*) FROM file WHERE complete = 1;"); -} - -int SqliteStorage::getFileLineSum() const -{ - return executeScalar("SELECT SUM(line_count) FROM file;"); -} - -int SqliteStorage::getSourceLocationCount() const -{ - return executeScalar("SELECT COUNT(*) FROM source_location;"); -} - -void SqliteStorage::clearTables() -{ - try - { - m_database.execDML("DROP TABLE IF EXISTS main.error;"); - m_database.execDML("DROP TABLE IF EXISTS main.comment_location;"); - m_database.execDML("DROP TABLE IF EXISTS main.component_access;"); - m_database.execDML("DROP TABLE IF EXISTS main.occurrence;"); - m_database.execDML("DROP TABLE IF EXISTS main.source_location;"); - m_database.execDML("DROP TABLE IF EXISTS main.local_symbol;"); - m_database.execDML("DROP TABLE IF EXISTS main.filecontent;"); - m_database.execDML("DROP TABLE IF EXISTS main.file;"); - m_database.execDML("DROP TABLE IF EXISTS main.symbol;"); - m_database.execDML("DROP TABLE IF EXISTS main.node;"); - m_database.execDML("DROP TABLE IF EXISTS main.edge;"); - m_database.execDML("DROP TABLE IF EXISTS main.element;"); - m_database.execDML("DROP TABLE IF EXISTS main.meta;"); - } - catch (CppSQLite3Exception& e) - { - LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage()); - } -} - -void SqliteStorage::setupTables() +void SqliteStorage::setupMetaTable() { try { @@ -1258,206 +128,27 @@ void SqliteStorage::setupTables() "id INTEGER, " "key TEXT, " "value TEXT, " - "PRIMARY KEY(id));" + "PRIMARY KEY(id)" + ");" ); - - m_database.execDML( - "CREATE TABLE IF NOT EXISTS element(" - "id INTEGER, " - "PRIMARY KEY(id));" - ); - - m_database.execDML( - "CREATE TABLE IF NOT EXISTS edge(" - "id INTEGER NOT NULL, " - "type INTEGER NOT NULL, " - "source_node_id INTEGER NOT NULL, " - "target_node_id INTEGER NOT NULL, " - "PRIMARY KEY(id), " - "FOREIGN KEY(id) REFERENCES element(id) ON DELETE CASCADE, " - "FOREIGN KEY(source_node_id) REFERENCES node(id) ON DELETE CASCADE, " - "FOREIGN KEY(target_node_id) REFERENCES node(id) ON DELETE CASCADE);" - ); - - m_database.execDML( - "CREATE TABLE IF NOT EXISTS node(" - "id INTEGER NOT NULL, " - "type INTEGER NOT NULL, " - "serialized_name TEXT, " - "PRIMARY KEY(id), " - "FOREIGN KEY(id) REFERENCES element(id) ON DELETE CASCADE);" - ); - - m_database.execDML( - "CREATE TABLE IF NOT EXISTS symbol(" - "id INTEGER NOT NULL, " - "definition_kind INTEGER NOT NULL, " - "PRIMARY KEY(id), " - "FOREIGN KEY(id) REFERENCES node(id) ON DELETE CASCADE);" - ); - - m_database.execDML( - "CREATE TABLE IF NOT EXISTS file(" - "id INTEGER NOT NULL, " - "path TEXT, " - "modification_time TEXT, " - "complete INTEGER, " - "line_count INTEGER, " - "UNIQUE(path) ON CONFLICT REPLACE," - "PRIMARY KEY(id), " - "FOREIGN KEY(id) REFERENCES node(id) ON DELETE CASCADE);" - ); - - m_database.execDML( - "CREATE TABLE IF NOT EXISTS filecontent(" - "id INTERGER, " - "content TEXT, " - "FOREIGN KEY(id)" - "REFERENCES file(id)" - "ON DELETE CASCADE " - "ON UPDATE CASCADE);" - ); - - m_database.execDML( - "CREATE TABLE IF NOT EXISTS local_symbol(" - "id INTEGER NOT NULL, " - "name TEXT, " - "PRIMARY KEY(id), " - "FOREIGN KEY(id) REFERENCES element(id) ON DELETE CASCADE);" - ); - - m_database.execDML( - "CREATE TABLE IF NOT EXISTS source_location(" - "id INTEGER NOT NULL, " - "file_node_id INTEGER, " - "start_line INTEGER, " - "start_column INTEGER, " - "end_line INTEGER, " - "end_column INTEGER, " - "type INTEGER, " - "PRIMARY KEY(id), " - "FOREIGN KEY(file_node_id) REFERENCES node(id) ON DELETE CASCADE);" - ); - - m_database.execDML( - "CREATE TABLE IF NOT EXISTS occurrence(" - "element_id INTEGER NOT NULL, " - "source_location_id INTEGER NOT NULL, " - "PRIMARY KEY(element_id, source_location_id), " - "FOREIGN KEY(element_id) REFERENCES element(id) ON DELETE CASCADE, " - "FOREIGN KEY(source_location_id) REFERENCES source_location(id) ON DELETE CASCADE);" - ); - - m_database.execDML( - "CREATE TABLE IF NOT EXISTS component_access(" - "id INTEGER NOT NULL, " - "node_id INTEGER, " - "type INTEGER NOT NULL, " - "UNIQUE(node_id) ON CONFLICT REPLACE," - "PRIMARY KEY(id), " - "FOREIGN KEY(node_id) REFERENCES node(id) ON DELETE CASCADE);" - ); - - m_database.execDML( - "CREATE TABLE IF NOT EXISTS comment_location(" - "id INTEGER NOT NULL, " - "file_node_id INTEGER, " - "start_line INTEGER, " - "start_column INTEGER, " - "end_line INTEGER, " - "end_column INTEGER, " - "UNIQUE(file_node_id, start_line, start_column, end_line, end_column) ON CONFLICT REPLACE," - "PRIMARY KEY(id), " - "FOREIGN KEY(file_node_id) REFERENCES node(id) ON DELETE CASCADE);" - ); - - m_database.execDML( - "CREATE TABLE IF NOT EXISTS error(" - "id INTEGER NOT NULL, " - "message TEXT, " - "fatal INTEGER NOT NULL, " - "indexed INTEGER NOT NULL, " - "file_path TEXT, " - "line_number INTEGER, " - "column_number INTEGER, " - "UNIQUE(message, fatal, file_path, line_number, column_number) ON CONFLICT REPLACE," - "PRIMARY KEY(id));" - ); - - // m_database.execDML( - // "CREATE TABLE IF NOT EXISTS bookmarkCategory(" - // "id INTEGER NOT NULL, " - // "name TEXT, " - // "PRIMARY KEY(id));" - // ); - - // m_database.execDML( - // "CREATE TABLE IF NOT EXISTS nodeBookmark(" - // "id INTEGER NOT NULL, " - // "name TEXT, " - // "comment TEXT, " - // "timestamp TEXT, " - // "category INTEGER, " - // "PRIMARY KEY(id), " - // "FOREIGN KEY(category) REFERENCES bookmarkCategory(id));" - // ); - - // m_database.execDML( - // "CREATE TABLE IF NOT EXISTS edgeBookmark(" - // "id INTEGER NOT NULL, " - // "name TEXT, " - // "comment TEXT, " - // "timestamp TEXT, " - // "category INTEGER, " - // "PRIMARY KEY(id), " - // "FOREIGN KEY(category) REFERENCES bookmarkCategory(id));" - // ); - - // m_database.execDML( - // "CREATE TABLE IF NOT EXISTS nodeBookmarkToken(" - // "id INTEGER NOT NULL, " - // "bookmarkId INTEGER NOT NULL, " - // "name TEXT, " - // "type INTEGER, " - // "PRIMARY KEY(id), " - // "FOREIGN KEY(bookmarkId) REFERENCES nodeBookmark(id) ON DELETE CASCADE);" - // ); - - // m_database.execDML( - // "CREATE TABLE IF NOT EXISTS edgeBookmarkToken(" - // "id INTEGER NOT NULL, " - // "bookmarkId INTEGER NOT NULL, " - // "name TEXT, " - // "type INTEGER, " - // "PRIMARY KEY(id), " - // "FOREIGN KEY(bookmarkId) REFERENCES edgeBookmark(id) ON DELETE CASCADE);" - // ); - - // m_database.execDML( - // "CREATE TABLE IF NOT EXISTS edgeBaseBookmark(" - // "id INTEGER NOT NULL, " - // "edgeId INTEGER, " - // "PRIMARY KEY(id), " - // "FOREIGN KEY(edgeId) REFERENCES edgeBookmark(id) ON DELETE CASCADE);" - // ); - - // m_database.execDML( - // "CREATE TABLE IF NOT EXISTS edgeBaseBookmarkToken(" - // "id INTEGER NOT NULL, " - // "bookmarkId INTEGER NOT NULL, " - // "name TEXT, " - // "type INTEGER, " - // "PRIMARY KEY(id), " - // "FOREIGN KEY(bookmarkId) REFERENCES edgeBaseBookmark(id) ON DELETE CASCADE);" - // ); } catch (CppSQLite3Exception& e) { LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage()); throw(std::exception()); + } +} - // todo: cancel project creation and destroy created files, display message +void SqliteStorage::clearMetaTable() +{ + try + { + m_database.execDML("DROP TABLE IF EXISTS main.meta;"); + } + catch (CppSQLite3Exception& e) + { + LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage()); } } @@ -1467,7 +158,7 @@ void SqliteStorage::executeStatement(const std::string& statement) const { m_database.execDML(statement.c_str()); } - catch(CppSQLite3Exception e) + catch (CppSQLite3Exception e) { LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage()); } @@ -1479,33 +170,33 @@ void SqliteStorage::executeStatement(CppSQLite3Statement& statement) const { statement.execDML(); } - catch(CppSQLite3Exception e) + catch (CppSQLite3Exception e) { LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage()); } } -int SqliteStorage::executeScalar(const std::string& statement) const +int SqliteStorage::executeStatementScalar(const std::string& statement) const { int ret = 0; try { ret = m_database.execScalar(statement.c_str()); } - catch(CppSQLite3Exception e) + catch (CppSQLite3Exception e) { LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage()); } return ret; } -CppSQLite3Query SqliteStorage::executeQuery(const std::string& query) const +CppSQLite3Query SqliteStorage::executeQuery(const std::string& statement) const { try { - return m_database.execQuery(query.c_str()); + return m_database.execQuery(statement.c_str()); } - catch(CppSQLite3Exception e) + catch (CppSQLite3Exception e) { LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage()); } @@ -1518,7 +209,7 @@ CppSQLite3Query SqliteStorage::executeQuery(CppSQLite3Statement& statement) cons { return statement.execQuery(); } - catch(CppSQLite3Exception e) + catch (CppSQLite3Exception e) { LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage()); } @@ -1582,12 +273,12 @@ size_t SqliteStorage::getStorageVersion() const void SqliteStorage::setStorageVersion() { - insertOrUpdateMetaValue("storage_version", std::to_string(STORAGE_VERSION)); + insertOrUpdateMetaValue("storage_version", std::to_string(getStaticStorageVersion())); } Version SqliteStorage::getApplicationVersion() const { - std::string versionStr = getMetaValue("version"); + std::string versionStr = getMetaValue("application_version"); if (versionStr.size()) { @@ -1599,447 +290,5 @@ Version SqliteStorage::getApplicationVersion() const void SqliteStorage::setApplicationVersion() { - insertOrUpdateMetaValue("version", Version::getApplicationVersion().toString()); -} - -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const -{ - CppSQLite3Query q = executeQuery( - "SELECT id, type, source_node_id, target_node_id FROM edge " + query + ";" - ); - - 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; -} - -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const -{ - CppSQLite3Query q = executeQuery( - "SELECT id, type, serialized_name FROM node " + query + ";" - ); - - std::vector nodes; - while (!q.eof()) - { - const Id id = q.getIntField(0, 0); - const int type = q.getIntField(1, -1); - const std::string serializedName = q.getStringField(2, ""); - - if (id != 0 && type != -1) - { - nodes.push_back(StorageNode(id, type, serializedName)); - } - - q.nextRow(); - } - return nodes; -} - -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const -{ - CppSQLite3Query q = executeQuery( - "SELECT id, definition_kind FROM symbol " + query + ";" - ); - - std::vector symbols; - while (!q.eof()) - { - const Id id = q.getIntField(0, 0); - const int definitionKind = q.getIntField(1, 0); - - if (id != 0) - { - symbols.push_back(StorageSymbol(id, definitionKind)); - } - - q.nextRow(); - } - return symbols; -} - -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const -{ - CppSQLite3Query q = executeQuery( - "SELECT id, path, modification_time, complete FROM file " + query + ";" - ); - - std::vector files; - while (!q.eof()) - { - const Id id = q.getIntField(0, 0); - const std::string filePath = q.getStringField(1, ""); - const std::string modificationTime = q.getStringField(2, ""); - const bool complete = q.getIntField(3, 0); - - if (id != 0) - { - files.push_back(StorageFile(id, filePath, modificationTime, complete)); - } - q.nextRow(); - } - - return files; -} - -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const -{ - CppSQLite3Query q = executeQuery( - "SELECT id, name FROM local_symbol " + query + ";" - ); - - std::vector localSymbols; - - while (!q.eof()) - { - const Id id = q.getIntField(0, 0); - const std::string name = q.getStringField(1, ""); - - if (id != 0) - { - localSymbols.push_back(StorageLocalSymbol(id, name)); - } - - q.nextRow(); - } - return localSymbols; -} - -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const -{ - CppSQLite3Query q = executeQuery( - "SELECT id, file_node_id, start_line, start_column, end_line, end_column, type FROM source_location " + query + ";" - ); - - std::vector sourceLocations; - - while (!q.eof()) - { - const Id id = q.getIntField(0, 0); - const Id fileNodeId = q.getIntField(1, 0); - const int startLineNumber = q.getIntField(2, -1); - const int startColNumber = q.getIntField(3, -1); - const int endLineNumber = q.getIntField(4, -1); - const int endColNumber = q.getIntField(5, -1); - const int type = q.getIntField(6, -1); - - if (id != 0 && fileNodeId != 0 && startLineNumber != -1 && startColNumber != -1 && endLineNumber != -1 && endColNumber != -1 && type != -1) - { - sourceLocations.push_back(StorageSourceLocation(id, fileNodeId, startLineNumber, startColNumber, endLineNumber, endColNumber, type)); - } - - q.nextRow(); - } - return sourceLocations; -} - -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const -{ - CppSQLite3Query q = executeQuery( - "SELECT element_id, source_location_id FROM occurrence " + query + ";" - ); - - std::vector occurrences; - - while (!q.eof()) - { - const Id elementId = q.getIntField(0, 0); - const Id sourceLocationId = q.getIntField(1, 0); - - if (elementId != 0 && sourceLocationId != 0) - { - occurrences.push_back(StorageOccurrence(elementId, sourceLocationId)); - } - - q.nextRow(); - } - return occurrences; -} - -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const -{ - CppSQLite3Query q = executeQuery( - "SELECT id, node_id, type FROM component_access " + query + ";" - ); - - std::vector componentAccesses; - - while (!q.eof()) - { - const Id id = q.getIntField(0, 0); - const Id nodeId = q.getIntField(1, 0); - const int type = q.getIntField(2, -1); - - if (id != 0 && nodeId != 0 && type != -1) - { - componentAccesses.push_back(StorageComponentAccess(nodeId, type)); - } - - q.nextRow(); - } - return componentAccesses; -} - -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const -{ - CppSQLite3Query q = executeQuery( - "SELECT id, file_node_id, start_line, start_column, end_line, end_column FROM comment_location " + query + ";" - ); - - std::vector commentLocations; - - while (!q.eof()) - { - const Id id = q.getIntField(0, 0); - const Id fileNodeId = q.getIntField(1, 0); - const int startLineNumber = q.getIntField(2, -1); - const int startColNumber = q.getIntField(3, -1); - const int endLineNumber = q.getIntField(4, -1); - const int endColNumber = q.getIntField(5, -1); - - if (id != 0 && fileNodeId != 0 && startLineNumber != -1 && startColNumber != -1 && endLineNumber != -1 && endColNumber != -1) - { - commentLocations.push_back(StorageCommentLocation( - id, fileNodeId, startLineNumber, startColNumber, endLineNumber, endColNumber - )); - } - - q.nextRow(); - } - return commentLocations; -} - -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const -{ - CppSQLite3Query q = executeQuery( - "SELECT message, fatal, indexed, file_path, line_number, column_number FROM error " + query + ";" - ); - - std::vector errors; - Id id = 1; - while (!q.eof()) - { - const std::string message = q.getStringField(0, ""); - const bool fatal = q.getIntField(1, 0); - const bool indexed = q.getIntField(2, 0); - const std::string filePath = q.getStringField(3, ""); - const int lineNumber = q.getIntField(4, -1); - const int columnNumber = q.getIntField(5, -1); - - if (lineNumber != -1 && columnNumber != -1) - { - errors.push_back(StorageError(id, message, filePath, lineNumber, columnNumber, fatal, indexed)); - id++; - } - - q.nextRow(); - } - - return errors; -} - -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const -{ - CppSQLite3Query q = m_database.execQuery(( - "SELECT id, name, comment, timestamp, category FROM nodeBookmark " + query + ";" - ).c_str()); - - std::vector bookmarks; - bookmarks.clear(); - - while (!q.eof()) - { - const int id = q.getIntField(0, -1); - const std::string name = q.getStringField(1, ""); - const std::string comment = q.getStringField(2, ""); - const std::string timeStamp = q.getStringField(3, ""); - const int categoryId = q.getIntField(4, -1); - - CppSQLite3Query qSub = m_database.execQuery(( - "SELECT name, type FROM nodeBookmarkToken WHERE bookmarkId = " + std::to_string(id) + ";" - ).c_str()); - - std::vector tokenNames; - std::vector tokenTypes; - - while (!qSub.eof()) - { - const std::string tokenName = qSub.getStringField(0, ""); - const int tokenType = qSub.getIntField(1, -1); - tokenNames.push_back(tokenName); - tokenTypes.push_back(tokenType); - qSub.nextRow(); - } - - NodeBookmark bookmark(name, std::vector(), tokenNames, comment, TimePoint(timeStamp)); - bookmark.setId(id); - bookmark.setTokenTypes(tokenTypes); - - qSub = m_database.execQuery(( - "SELECT id, name FROM bookmarkCategory WHERE id = " + std::to_string(categoryId) + ";" - ).c_str()); - - while (!qSub.eof()) - { - const int categoryId = qSub.getIntField(0, -1); - const std::string name = qSub.getStringField(1, ""); - BookmarkCategory category; - category.setId(categoryId); - category.setName(name); - bookmark.setCategory(category); - - qSub.nextRow(); - } - - bookmarks.push_back(bookmark); - - q.nextRow(); - } - - return bookmarks; -} - -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const -{ - CppSQLite3Query q = m_database.execQuery(( - "SELECT id, name, comment, timestamp, category FROM edgeBookmark " + query + ";" - ).c_str()); - - std::vector bookmarks; - bookmarks.clear(); - - while (!q.eof()) - { - const int id = q.getIntField(0, -1); - const std::string name = q.getStringField(1, ""); - const std::string comment = q.getStringField(2, ""); - const std::string timeStamp = q.getStringField(3, ""); - const int categoryId = q.getIntField(4, -1); - - CppSQLite3Query qSub = m_database.execQuery(( - "SELECT name, type FROM edgeBookmarkToken WHERE bookmarkId = " + std::to_string(id) + ";" - ).c_str()); - - - std::vector tokenNames; - std::vector tokenTypes; - while (!qSub.eof()) - { - const std::string tokenName = qSub.getStringField(0, ""); - const int tokenType = qSub.getIntField(1, -1); - tokenNames.push_back(tokenName); - tokenTypes.push_back(tokenType); - qSub.nextRow(); - } - - qSub = m_database.execQuery(( - "SELECT id FROM edgeBaseBookmark WHERE edgeId = " + std::to_string(id) + ";" - ).c_str()); - - NodeBookmark baseBookmark; // there should only be one base bookmark, if there are more use the last one - while (!qSub.eof()) - { - const int baseId = qSub.getIntField(0, -1); - - baseBookmark.setId(baseId); - - CppSQLite3Query qSubSub = m_database.execQuery(( - "SELECT id, name, type FROM edgeBaseBookmarkToken WHERE bookmarkId = " + std::to_string(baseId) + ";" - ).c_str()); - - std::vector baseTokenNames; - std::vector baseTokenTypes; - while (!qSubSub.eof()) - { - const std::string baseTokenName = qSubSub.getStringField(1, ""); - const int baseTokenType = qSubSub.getIntField(2, -1); - baseTokenNames.push_back(baseTokenName); - baseTokenTypes.push_back(baseTokenType); - qSubSub.nextRow(); - } - - baseBookmark.setTokenNames(baseTokenNames); - baseBookmark.setTokenTypes(baseTokenTypes); - - qSub.nextRow(); - } - - EdgeBookmark bookmark(name, std::vector(), tokenNames, comment, TimePoint(timeStamp)); - bookmark.setTokenTypes(tokenTypes); - bookmark.setBaseBookmark(baseBookmark); - bookmark.setId(id); - - qSub = m_database.execQuery(( - "SELECT id, name FROM bookmarkCategory WHERE id = " + std::to_string(categoryId) + ";" - ).c_str()); - - while (!qSub.eof()) - { - const int categoryId = qSub.getIntField(0, -1); - const std::string name = qSub.getStringField(1, ""); - BookmarkCategory category; - category.setId(categoryId); - category.setName(name); - bookmark.setCategory(category); - - qSub.nextRow(); - } - - bookmarks.push_back(bookmark); - - q.nextRow(); - } - - return bookmarks; -} - -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const -{ - std::vector categories; - - CppSQLite3Query q = m_database.execQuery(( - "SELECT id, name FROM bookmarkCategory " + query + ";" - ).c_str()); - - while (!q.eof()) - { - const int id = q.getIntField(0, -1); - const std::string name = q.getStringField(1, ""); - - BookmarkCategory category; - category.setId(id); - category.setName(name); - - categories.push_back(category); - - q.nextRow(); - } - - return categories; + insertOrUpdateMetaValue("application_version", Version::getApplicationVersion().toString()); } diff --git a/src/lib/data/SqliteStorage.h b/src/lib/data/SqliteStorage.h index bf5fe8a9..f578d8c0 100644 --- a/src/lib/data/SqliteStorage.h +++ b/src/lib/data/SqliteStorage.h @@ -1,27 +1,11 @@ #ifndef SQLITE_STORAGE_H #define SQLITE_STORAGE_H -#include -#include -#include - #include "sqlite/CppSQLite3.h" -#include "data/bookmark/BookmarkCategory.h" -#include "data/bookmark/EdgeBookmark.h" -#include "data/bookmark/NodeBookmark.h" -#include "data/location/SourceLocationFile.h" -#include "data/name/NameHierarchy.h" -#include "data/StorageTypes.h" -#include "data/SqliteIndex.h" +#include "data/SqliteDatabaseIndex.h" #include "utility/file/FilePath.h" -#include "utility/types.h" -#include "utility/utility.h" -#include "utility/utilityString.h" - -class TextAccess; -class Version; -struct ParseLocation; +#include "utility/Version.h" class SqliteStorage { @@ -35,7 +19,7 @@ public: }; SqliteStorage(const FilePath& dbFilePath); - ~SqliteStorage(); + virtual ~SqliteStorage(); void setup(); void clear(); @@ -52,140 +36,16 @@ public: bool isEmpty() const; bool isIncompatible() const; - std::string getProjectSettingsText() const; - void setProjectSettingsText(std::string text); void setVersion(); - Id addEdge(int type, Id sourceNodeId, Id targetNodeId); - - Id addNode(const int type, const std::string& serializedName); - void addSymbol(const int id, int definitionKind); - void addFile(const int id, const std::string& filePath, const std::string& modificationTime, bool complete); - Id addLocalSymbol(const std::string& name); - Id addSourceLocation(Id fileNodeId, uint startLine, uint startCol, uint endLine, uint endCol, int type); - bool addOccurrence(Id elementId, Id sourceLocationId); - Id addComponentAccess(Id nodeId, int type); - Id addCommentLocation(Id fileNodeId, uint startLine, uint startCol, uint endLine, uint endCol); - Id addError(const std::string& message, const FilePath& filePath, uint lineNumber, uint columnNumber, bool fatal, bool indexed); - Id addNodeBookmark(const NodeBookmark& bookmark); - Id addEdgeBookmark(const EdgeBookmark& bookmark); - Id addBookmarkCategory(const std::string& name); - - void removeElement(Id id); - void removeElements(const std::vector& ids); - void removeElementsWithLocationInFiles(const std::vector& fileIds, std::function updateStatusCallback); - - void removeErrorsInFiles(const std::vector& filePaths); - - bool isEdge(Id elementId) const; - bool isNode(Id elementId) const; - bool isFile(Id elementId) const; - - StorageEdge getEdgeById(Id edgeId) const; - 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 getEdgesByType(int type) const; - std::vector getEdgesBySourceType(Id sourceId, int type) const; - std::vector getEdgesBySourcesType(const std::vector& sourceIds, int type) const; - std::vector getEdgesByTargetType(Id targetId, int type) const; - std::vector getEdgesByTargetsType(const std::vector& targetIds, int type) const; - - bool checkEdgeExists(Id edgeId) const; - - StorageNode getNodeById(Id id) const; - StorageNode getNodeBySerializedName(const std::string& serializedName) const; - bool checkNodeExistsByName(const std::string& serializedName) const; - - StorageLocalSymbol getLocalSymbolByName(const std::string& name) const; - - StorageFile getFileByPath(const std::string& filePath) const; - - std::vector getFilesByPaths(const std::vector& filePaths) const; - std::shared_ptr getFileContentByPath(const std::string& filePath) const; - std::shared_ptr getFileContentById(Id fileId) const; - - void setFileComplete(bool complete, Id fileId); - void setNodeType(int type, Id nodeId); - - StorageSourceLocation getSourceLocationByAll(const Id fileNodeId, const uint startLine, const uint startCol, const uint endLine, const uint endCol, const int type) const; - std::shared_ptr getSourceLocationsForFile(const FilePath& filePath) const; - - std::vector getOccurrencesForLocationId(Id locationId) const; - std::vector getOccurrencesForLocationIds(const std::vector& locationIds) const; - std::vector getOccurrencesForElementIds(const std::vector& elementIds) const; - - StorageComponentAccess getComponentAccessByNodeId(Id memberEdgeId) const; - std::vector getComponentAccessesByNodeIds(const std::vector& memberEdgeIds) const; - - std::vector getCommentLocationsInFile(const FilePath& filePath) const; - - template - std::vector getAll() const - { - return doGetAll(""); - } - - std::vector getAllNodeBookmarks() const; - NodeBookmark getNodeBookmarkById(const Id bookmarkId) const; - bool checkNodeBookmarkExistsByNames(const std::vector& names) const; - void removeNodeBookmark(Id id); - void editNodeBookmark(const NodeBookmark& bookmark); - - std::vector getAllEdgeBookmarks() const; - EdgeBookmark getEdgeBookmarkById(const Id bookmarkId) const; - bool checkEdgeBookmarkExistsByNames(const std::vector& names) const; - void removeEdgeBookmark(Id id); - void editEdgeBookmark(const EdgeBookmark& bookmark); - - std::vector getAllBookmarkCategories() const; - BookmarkCategory getBookmarkCategoryByName(const std::string& name) const; - BookmarkCategory getOrCreateBookmarkCategoryByName(const std::string& name); - bool checkBookmarkCategoryExists(const std::string& name) const; - void removeBookmarkCategory(Id id); - - template - ResultType getFirstById(const Id id) const - { - if (id != 0) - { - return doGetFirst("WHERE id == " + std::to_string(id)); - } - return ResultType(); - } - - template - std::vector getAllByIds(const std::vector& ids) const - { - if (ids.size()) - { - return doGetAll("WHERE id IN (" + utility::join(utility::toStrings(ids), ',') + ")"); - } - return std::vector(); - } - - int getNodeCount() const; - int getEdgeCount() const; - int getFileCount() const; - int getCompletedFileCount() const; - int getFileLineSum() const; - int getSourceLocationCount() const; - -private: - static const size_t STORAGE_VERSION; - - void clearTables(); - void setupTables(); +protected: + void setupMetaTable(); + void clearMetaTable(); void executeStatement(const std::string& statement) const; void executeStatement(CppSQLite3Statement& statement) const; - int executeScalar(const std::string& statement) const; + int executeStatementScalar(const std::string& statement) const; CppSQLite3Query executeQuery(const std::string& statement) const; CppSQLite3Query executeQuery(CppSQLite3Statement& statement) const; @@ -200,54 +60,18 @@ private: Version getApplicationVersion() const; void setApplicationVersion(); - template - std::vector doGetAll(const std::string& query) const; - - template - ResultType doGetFirst(const std::string& query) const - { - std::vector results = doGetAll(query + " LIMIT 1"); - if (results.size() > 0) - { - return results[0]; - } - return ResultType(); - } - mutable CppSQLite3DB m_database; FilePath m_dbFilePath; StorageModeType m_mode; - std::vector> m_indices; + +private: + virtual size_t getStaticStorageVersion() const = 0; + virtual std::vector> getIndices() const = 0; + virtual void clearTables() = 0; + virtual void setupTables() = 0; + + std::vector> m_indices; }; -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const; -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const; -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const; -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const; -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const; -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const; -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const; -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const; -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const; -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const; -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const; -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const; -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const; -template <> -std::vector SqliteStorage::doGetAll(const std::string& query) const; - #endif // SQLITE_STORAGE_H diff --git a/src/lib/data/StorageTypes.h b/src/lib/data/StorageTypes.h index bf63090e..810fbbb7 100644 --- a/src/lib/data/StorageTypes.h +++ b/src/lib/data/StorageTypes.h @@ -234,4 +234,116 @@ struct StorageError bool indexed; }; + + + + +struct StorageBookmarkCategory +{ + StorageBookmarkCategory() + : id(0) + , name("") + {} + + StorageBookmarkCategory( + Id id, + const std::string& name + ) + : id(id) + , name(name) + {} + + Id id; + std::string name; +}; + +struct StorageBookmark +{ + StorageBookmark() + : id(0) + , name("") + , comment("") + , timestamp("") + , categoryId(0) + {} + + StorageBookmark( + Id id, + const std::string& name, + const std::string& comment, + const std::string& timestamp, + const Id categoryId + ) + : id(id) + , name(name) + , comment(comment) + , timestamp(timestamp) + , categoryId(categoryId) + {} + + Id id; + std::string name; + std::string comment; + std::string timestamp; + Id categoryId; +}; + +struct StorageBookmarkedNode +{ + StorageBookmarkedNode() + : id(0) + , bookmarkId(0) + , serializedNodeName("") + {} + + StorageBookmarkedNode( + Id id, + Id bookmarkId, + const std::string& serializedNodeName + ) + : id(id) + , bookmarkId(bookmarkId) + , serializedNodeName(serializedNodeName) + {} + + Id id; + Id bookmarkId; + std::string serializedNodeName; +}; + +struct StorageBookmarkedEdge +{ + StorageBookmarkedEdge() + : id(0) + , bookmarkId(0) + , serializedSourceNodeName("") + , serializedTargetNodeName("") + , edgeType(0) + , sourceNodeActive(false) + {} + + StorageBookmarkedEdge( + Id id, + Id bookmarkId, + const std::string& serializedSourceNodeName, + const std::string& serializedTargetNodeName, + int edgeType, + bool sourceNodeActive + ) + : id(id) + , bookmarkId(bookmarkId) + , serializedSourceNodeName(serializedSourceNodeName) + , serializedTargetNodeName(serializedTargetNodeName) + , edgeType(edgeType) + , sourceNodeActive(sourceNodeActive) + {} + + Id id; + Id bookmarkId; + std::string serializedSourceNodeName; + std::string serializedTargetNodeName; + int edgeType; + bool sourceNodeActive; +}; + #endif // STORAGE_TYPES_H diff --git a/src/lib/data/TaskCleanStorage.cpp b/src/lib/data/TaskCleanStorage.cpp index 1ea9df2c..d4f7b001 100644 --- a/src/lib/data/TaskCleanStorage.cpp +++ b/src/lib/data/TaskCleanStorage.cpp @@ -25,7 +25,7 @@ void TaskCleanStorage::doEnter(std::shared_ptr blackboard) if (!m_filePaths.empty()) { - m_storage->setMode(SqliteStorage::STORAGE_MODE_CLEAR); + m_storage->setMode(SqliteIndexStorage::STORAGE_MODE_CLEAR); } } diff --git a/src/lib/data/TaskFinishParsing.cpp b/src/lib/data/TaskFinishParsing.cpp index 138f2ca6..1a8b0e9f 100644 --- a/src/lib/data/TaskFinishParsing.cpp +++ b/src/lib/data/TaskFinishParsing.cpp @@ -23,7 +23,7 @@ TaskFinishParsing::~TaskFinishParsing() void TaskFinishParsing::doEnter(std::shared_ptr blackboard) { - m_storage->setMode(SqliteStorage::STORAGE_MODE_READ); + m_storage->setMode(SqliteIndexStorage::STORAGE_MODE_READ); } Task::TaskState TaskFinishParsing::doUpdate(std::shared_ptr blackboard) diff --git a/src/lib/data/access/StorageAccess.h b/src/lib/data/access/StorageAccess.h index 46503df4..e20dd5ec 100644 --- a/src/lib/data/access/StorageAccess.h +++ b/src/lib/data/access/StorageAccess.h @@ -80,25 +80,19 @@ public: virtual void setErrorFilter(const ErrorFilter& filter); - virtual Id addNodeBookmark(const NodeBookmark& bookmark) = 0; - virtual Id addEdgeBookmark(const EdgeBookmark& bookmark) = 0; - virtual Id addBookmarkCategory(const BookmarkCategory& category) = 0; + virtual Id addNodeBookmark(const NodeBookmark& bookmark) = 0; // todo: remove these from storage access + virtual Id addEdgeBookmark(const EdgeBookmark& bookmark) = 0; // todo: remove these from storage access + virtual Id addBookmarkCategory(const std::string& categoryName) = 0; // todo: remove these from storage access + + virtual void updateBookmark(const Id bookmarkId, const std::string& name, const std::string& comment, const std::string& categoryName) = 0; // todo: remove these from storage access + + virtual void removeBookmark(const Id id) = 0; // todo: remove these from storage access + virtual void removeBookmarkCategory(const Id id) = 0; // todo: remove these from storage access virtual std::vector getAllNodeBookmarks() const = 0; - virtual NodeBookmark getNodeBookmarkById(const Id bookmarkId) const = 0; - virtual bool checkNodeBookmarkExistsByTokens(const std::vector& tokenNames) const = 0; - virtual void removeNodeBookmark(Id id) = 0; - virtual void editNodeBookmark(const NodeBookmark& bookmark) = 0; - virtual std::vector getAllEdgeBookmarks() const = 0; - virtual EdgeBookmark getEdgeBookmarkById(const Id bookmarkId) const = 0; - virtual bool checkEdgeBookmarkExistsByTokens(const std::vector& tokenNames) const = 0; - virtual void removeEdgeBookmark(Id id) = 0; - virtual void editEdgeBookmark(const EdgeBookmark& bookmark) = 0; virtual std::vector getAllBookmarkCategories() const = 0; - virtual bool checkBookmarkCategoryExists(const std::string& name) const = 0; - virtual void removeBookmarkCategory(Id id) = 0; protected: ErrorFilter m_errorFilter; diff --git a/src/lib/data/access/StorageAccessProxy.cpp b/src/lib/data/access/StorageAccessProxy.cpp index ed57c0fc..5f41b0b8 100644 --- a/src/lib/data/access/StorageAccessProxy.cpp +++ b/src/lib/data/access/StorageAccessProxy.cpp @@ -349,16 +349,40 @@ Id StorageAccessProxy::addEdgeBookmark(const EdgeBookmark& bookmark) return -1; } -Id StorageAccessProxy::addBookmarkCategory(const BookmarkCategory& category) +Id StorageAccessProxy::addBookmarkCategory(const std::string& categoryName) { if (hasSubject()) { - return m_subject->addBookmarkCategory(category); + return m_subject->addBookmarkCategory(categoryName); } return -1; } +void StorageAccessProxy::updateBookmark(const Id bookmarkId, const std::string& name, const std::string& comment, const std::string& categoryName) +{ + if (hasSubject()) + { + m_subject->updateBookmark(bookmarkId, name, comment, categoryName); + } +} + +void StorageAccessProxy::removeBookmark(const Id id) +{ + if (hasSubject()) + { + m_subject->removeBookmark(id); + } +} + +void StorageAccessProxy::removeBookmarkCategory(const Id id) +{ + if (hasSubject()) + { + m_subject->removeBookmarkCategory(id); + } +} + std::vector StorageAccessProxy::getAllNodeBookmarks() const { if (hasSubject()) @@ -369,42 +393,6 @@ std::vector StorageAccessProxy::getAllNodeBookmarks() const return std::vector(); } -NodeBookmark StorageAccessProxy::getNodeBookmarkById(const Id bookmarkId) const -{ - if (hasSubject()) - { - return m_subject->getNodeBookmarkById(bookmarkId); - } - - return NodeBookmark(); -} - -bool StorageAccessProxy::checkNodeBookmarkExistsByTokens(const std::vector& tokenNames) const -{ - if (hasSubject()) - { - return m_subject->checkNodeBookmarkExistsByTokens(tokenNames); - } - - return false; -} - -void StorageAccessProxy::removeNodeBookmark(Id id) -{ - if (hasSubject()) - { - m_subject->removeNodeBookmark(id); - } -} - -void StorageAccessProxy::editNodeBookmark(const NodeBookmark& bookmark) -{ - if (hasSubject()) - { - m_subject->editNodeBookmark(bookmark); - } -} - std::vector StorageAccessProxy::getAllEdgeBookmarks() const { if (hasSubject()) @@ -415,42 +403,6 @@ std::vector StorageAccessProxy::getAllEdgeBookmarks() const return std::vector(); } -EdgeBookmark StorageAccessProxy::getEdgeBookmarkById(const Id bookmarkId) const -{ - if (hasSubject()) - { - return m_subject->getEdgeBookmarkById(bookmarkId); - } - - return EdgeBookmark(); -} - -bool StorageAccessProxy::checkEdgeBookmarkExistsByTokens(const std::vector& tokenNames) const -{ - if (hasSubject()) - { - return m_subject->checkEdgeBookmarkExistsByTokens(tokenNames); - } - - return false; -} - -void StorageAccessProxy::removeEdgeBookmark(Id id) -{ - if (hasSubject()) - { - m_subject->removeEdgeBookmark(id); - } -} - -void StorageAccessProxy::editEdgeBookmark(const EdgeBookmark& bookmark) -{ - if (hasSubject()) - { - m_subject->editEdgeBookmark(bookmark); - } -} - std::vector StorageAccessProxy::getAllBookmarkCategories() const { if (hasSubject()) @@ -461,24 +413,6 @@ std::vector StorageAccessProxy::getAllBookmarkCategories() con return std::vector(); } -bool StorageAccessProxy::checkBookmarkCategoryExists(const std::string& name) const -{ - if (hasSubject()) - { - return m_subject->checkBookmarkCategoryExists(name); - } - - return false; -} - -void StorageAccessProxy::removeBookmarkCategory(Id id) -{ - if (hasSubject()) - { - m_subject->removeBookmarkCategory(id); - } -} - void StorageAccessProxy::setErrorFilter(const ErrorFilter& filter) { StorageAccess::setErrorFilter(filter); diff --git a/src/lib/data/access/StorageAccessProxy.h b/src/lib/data/access/StorageAccessProxy.h index bac5a99b..45169246 100644 --- a/src/lib/data/access/StorageAccessProxy.h +++ b/src/lib/data/access/StorageAccessProxy.h @@ -71,23 +71,17 @@ public: virtual Id addNodeBookmark(const NodeBookmark& bookmark); virtual Id addEdgeBookmark(const EdgeBookmark& bookmark); - virtual Id addBookmarkCategory(const BookmarkCategory& category); + virtual Id addBookmarkCategory(const std::string& categoryName); + + virtual void updateBookmark(const Id bookmarkId, const std::string& name, const std::string& comment, const std::string& categoryName); + + virtual void removeBookmark(const Id id); + virtual void removeBookmarkCategory(const Id id); virtual std::vector getAllNodeBookmarks() const; - virtual NodeBookmark getNodeBookmarkById(const Id bookmarkId) const; - virtual bool checkNodeBookmarkExistsByTokens(const std::vector& tokenNames) const; - virtual void removeNodeBookmark(Id id); - virtual void editNodeBookmark(const NodeBookmark& bookmark); - virtual std::vector getAllEdgeBookmarks() const; - virtual EdgeBookmark getEdgeBookmarkById(const Id bookmarkId) const; - virtual bool checkEdgeBookmarkExistsByTokens(const std::vector& tokenNames) const; - virtual void removeEdgeBookmark(Id id); - virtual void editEdgeBookmark(const EdgeBookmark& bookmark); virtual std::vector getAllBookmarkCategories() const; - virtual bool checkBookmarkCategoryExists(const std::string& name) const; - virtual void removeBookmarkCategory(Id id); protected: virtual void setErrorFilter(const ErrorFilter& filter); diff --git a/src/lib/data/bookmark/Bookmark.cpp b/src/lib/data/bookmark/Bookmark.cpp index b3309e30..22ada1ee 100644 --- a/src/lib/data/bookmark/Bookmark.cpp +++ b/src/lib/data/bookmark/Bookmark.cpp @@ -1,28 +1,12 @@ #include "Bookmark.h" -Bookmark::Bookmark() - : m_id(-1) - , m_tokenTypes() - , m_tokenIds() - , m_tokenNames() - , m_comment("") - , m_displayName("") - , m_valid(false) - , m_timeStamp() - , m_category() -{ -} - -Bookmark::Bookmark(const std::string& displayName, const std::vector& tokens, const std::vector& tokenNames, const std::string& comment, const TimePoint& timeStamp) - : m_id(-1) - , m_tokenTypes() - , m_tokenIds(tokens) - , m_tokenNames(tokenNames) +Bookmark::Bookmark(const Id id, const std::string& name, const std::string& comment, const TimePoint& timeStamp, const BookmarkCategory& category) + : m_id(id) + , m_name(name) , m_comment(comment) - , m_displayName(displayName) - , m_valid(false) , m_timeStamp(timeStamp) - , m_category() + , m_category(category) + , m_isValid(false) { } @@ -40,34 +24,14 @@ void Bookmark::setId(const Id id) m_id = id; } -std::vector Bookmark::getTokenTypes() const +std::string Bookmark::getName() const { - return m_tokenTypes; + return m_name; } -void Bookmark::setTokenTypes(const std::vector& types) +void Bookmark::setName(const std::string& name) { - m_tokenTypes = types; -} - -std::vector Bookmark::getTokenIds() const -{ - return m_tokenIds; -} - -void Bookmark::setTokenIds(const std::vector& ids) -{ - m_tokenIds = ids; -} - -std::vector Bookmark::getTokenNames() const -{ - return m_tokenNames; -} - -void Bookmark::setTokenNames(const std::vector& names) -{ - m_tokenNames = names; + m_name = name; } std::string Bookmark::getComment() const @@ -80,31 +44,16 @@ void Bookmark::setComment(const std::string& comment) m_comment = comment; } -std::string Bookmark::getDisplayName() const -{ - return m_displayName; -} - -void Bookmark::setDisplayName(const std::string& name) -{ - m_displayName = name; -} - -bool Bookmark::isValid() const -{ - return m_valid; -} - -void Bookmark::setValid(const bool valid) -{ - m_valid = valid; -} - TimePoint Bookmark::getTimeStamp() const { return m_timeStamp; } +void Bookmark::setTimeStamp(const TimePoint& timeStamp) +{ + m_timeStamp = timeStamp; +} + BookmarkCategory Bookmark::getCategory() const { return m_category; @@ -113,4 +62,15 @@ BookmarkCategory Bookmark::getCategory() const void Bookmark::setCategory(const BookmarkCategory& category) { m_category = category; -} \ No newline at end of file +} + +bool Bookmark::isValid() const +{ + return m_isValid; +} + +void Bookmark::setIsValid(const bool isValid) +{ + m_isValid = isValid; +} + diff --git a/src/lib/data/bookmark/Bookmark.h b/src/lib/data/bookmark/Bookmark.h index 210d4d41..901c557d 100644 --- a/src/lib/data/bookmark/Bookmark.h +++ b/src/lib/data/bookmark/Bookmark.h @@ -12,49 +12,34 @@ class Bookmark { public: - Bookmark(); - Bookmark(const std::string& displayName, const std::vector& tokens, const std::vector& tokenNames, const std::string& comment, const TimePoint& timeStamp); + Bookmark(const Id id, const std::string& name, const std::string& comment, const TimePoint& timeStamp, const BookmarkCategory& category); virtual ~Bookmark(); Id getId() const; void setId(const Id id); - std::vector getTokenTypes() const; - void setTokenTypes(const std::vector& types); - - std::vector getTokenIds() const; - void setTokenIds(const std::vector& ids); - - std::vector getTokenNames() const; - void setTokenNames(const std::vector& names); + std::string getName() const; + void setName(const std::string& name); std::string getComment() const; void setComment(const std::string& comment); - std::string getDisplayName() const; - void setDisplayName(const std::string& name); - - bool isValid() const; - void setValid(const bool valid); - TimePoint getTimeStamp() const; + void setTimeStamp(const TimePoint& timeStamp); BookmarkCategory getCategory() const; void setCategory(const BookmarkCategory& category); + bool isValid() const; + void setIsValid(const bool isValid = true); + private: Id m_id; - std::vector m_tokenTypes; - std::vector m_tokenIds; - std::vector m_tokenNames; + std::string m_name; std::string m_comment; - std::string m_displayName; - - bool m_valid; - TimePoint m_timeStamp; - BookmarkCategory m_category; + bool m_isValid; }; -#endif // BOOKMARK_H \ No newline at end of file +#endif // BOOKMARK_H diff --git a/src/lib/data/bookmark/BookmarkCategory.cpp b/src/lib/data/bookmark/BookmarkCategory.cpp index 88fa7d54..cd0ee1b3 100644 --- a/src/lib/data/bookmark/BookmarkCategory.cpp +++ b/src/lib/data/bookmark/BookmarkCategory.cpp @@ -6,6 +6,12 @@ BookmarkCategory::BookmarkCategory() { } +BookmarkCategory::BookmarkCategory(const Id id, const std::string& name) + : m_id(id) + , m_name(name) +{ +} + BookmarkCategory::~BookmarkCategory() { } @@ -28,4 +34,4 @@ std::string BookmarkCategory::getName() const void BookmarkCategory::setName(const std::string& name) { m_name = name; -} \ No newline at end of file +} diff --git a/src/lib/data/bookmark/BookmarkCategory.h b/src/lib/data/bookmark/BookmarkCategory.h index 65bbf52b..207f7c4d 100644 --- a/src/lib/data/bookmark/BookmarkCategory.h +++ b/src/lib/data/bookmark/BookmarkCategory.h @@ -9,6 +9,7 @@ class BookmarkCategory { public: BookmarkCategory(); + BookmarkCategory(const Id id, const std::string& name); ~BookmarkCategory(); Id getId() const; @@ -22,4 +23,4 @@ private: std::string m_name; }; -#endif // BOOKMARK_CATEGORY_H \ No newline at end of file +#endif // BOOKMARK_CATEGORY_H diff --git a/src/lib/data/bookmark/EdgeBookmark.cpp b/src/lib/data/bookmark/EdgeBookmark.cpp index 253e2bd5..42d55e86 100644 --- a/src/lib/data/bookmark/EdgeBookmark.cpp +++ b/src/lib/data/bookmark/EdgeBookmark.cpp @@ -1,12 +1,7 @@ #include "EdgeBookmark.h" -EdgeBookmark::EdgeBookmark() - : Bookmark() -{ -} - -EdgeBookmark::EdgeBookmark(const std::string& displayName, const std::vector& tokens, const std::vector& tokenNames, const std::string& comment, const TimePoint& timeStamp) - : Bookmark(displayName, tokens, tokenNames, comment, timeStamp) +EdgeBookmark::EdgeBookmark(const Id id, const std::string& name, const std::string& comment, const TimePoint& timeStamp, const BookmarkCategory& category) + : Bookmark(id, name, comment, timeStamp, category) { } @@ -14,42 +9,27 @@ EdgeBookmark::~EdgeBookmark() { } -std::vector EdgeBookmark::getEdgeTokenTypes() const +void EdgeBookmark::addEdgeId(const Id edgeId) { - return m_edgeTokenTypes; + m_edgeIds.push_back(edgeId); } -void EdgeBookmark::setEdgeTokenTypes(const std::vector& tokenTypes) +void EdgeBookmark::setEdgeIds(const std::vector& edgesIds) { - m_edgeTokenTypes = tokenTypes; + m_edgeIds = edgesIds; } -std::vector EdgeBookmark::getEdgeTokenIds() const +std::vector EdgeBookmark::getEdgeIds() const { - return m_edgeTokenIds; + return m_edgeIds; } -void EdgeBookmark::setEdgeTokenIds(const std::vector& tokenIds) +void EdgeBookmark::setActiveNodeId(const Id activeNodeId) { - m_edgeTokenIds = tokenIds; + m_activeNodeId = activeNodeId; } -std::vector EdgeBookmark::getEdgeTokenNames() const +Id EdgeBookmark::getActiveNodeId() const { - return m_edgeTokenNames; + return m_activeNodeId; } - -void EdgeBookmark::setEdgeTokenNames(const std::vector& tokenNames) -{ - m_edgeTokenNames = tokenNames; -} - -NodeBookmark EdgeBookmark::getBaseBookmark() const -{ - return m_baseBookmark; -} - -void EdgeBookmark::setBaseBookmark(const NodeBookmark& baseBookmark) -{ - m_baseBookmark = baseBookmark; -} \ No newline at end of file diff --git a/src/lib/data/bookmark/EdgeBookmark.h b/src/lib/data/bookmark/EdgeBookmark.h index 3ec29535..b98c96f6 100644 --- a/src/lib/data/bookmark/EdgeBookmark.h +++ b/src/lib/data/bookmark/EdgeBookmark.h @@ -2,34 +2,25 @@ #define EDGE_BOOKMARK_H #include "Bookmark.h" -#include "NodeBookmark.h" +#include "data/graph/Edge.h" class EdgeBookmark : public Bookmark { public: - EdgeBookmark(); - EdgeBookmark(const std::string& displayName, const std::vector& tokens, const std::vector& tokenNames, const std::string& comment, const TimePoint& timeStamp); + EdgeBookmark(const Id id, const std::string& name, const std::string& comment, const TimePoint& timeStamp, const BookmarkCategory& category); virtual ~EdgeBookmark(); - std::vector getEdgeTokenTypes() const; - void setEdgeTokenTypes(const std::vector& tokenTypes); + void addEdgeId(const Id edgeId); + void setEdgeIds(const std::vector& edgesIds); + std::vector getEdgeIds() const; - std::vector getEdgeTokenIds() const; - void setEdgeTokenIds(const std::vector& tokenIds); - - std::vector getEdgeTokenNames() const; - void setEdgeTokenNames(const std::vector& tokenNames); - - NodeBookmark getBaseBookmark() const; - void setBaseBookmark(const NodeBookmark& baseBookmark); + void setActiveNodeId(const Id activeNodeId); + Id getActiveNodeId() const; private: - std::vector m_edgeTokenTypes; - std::vector m_edgeTokenIds; - std::vector m_edgeTokenNames; - - NodeBookmark m_baseBookmark; + std::vector m_edgeIds; + Id m_activeNodeId; }; -#endif // EDGE_BOOKMARK_H \ No newline at end of file +#endif // EDGE_BOOKMARK_H diff --git a/src/lib/data/bookmark/NodeBookmark.cpp b/src/lib/data/bookmark/NodeBookmark.cpp index 3691efd0..5bb0dd20 100644 --- a/src/lib/data/bookmark/NodeBookmark.cpp +++ b/src/lib/data/bookmark/NodeBookmark.cpp @@ -1,15 +1,25 @@ #include "NodeBookmark.h" -NodeBookmark::NodeBookmark() - : Bookmark() -{ -} - -NodeBookmark::NodeBookmark(const std::string& displayName, const std::vector& tokens, const std::vector& tokenNames, const std::string& comment, const TimePoint& timeStamp) - : Bookmark(displayName, tokens, tokenNames, comment, timeStamp) +NodeBookmark::NodeBookmark(const Id id, const std::string& name, const std::string& comment, const TimePoint& timeStamp, const BookmarkCategory& category) + : Bookmark(id, name, comment, timeStamp, category) { } NodeBookmark::~NodeBookmark() { -} \ No newline at end of file +} + +void NodeBookmark::addNodeId(const Id nodeId) +{ + m_nodeIds.push_back(nodeId); +} + +void NodeBookmark::setNodeIds(const std::vector& nodeIds) +{ + m_nodeIds = nodeIds; +} + +std::vector NodeBookmark::getNodeIds() const +{ + return m_nodeIds; +} diff --git a/src/lib/data/bookmark/NodeBookmark.h b/src/lib/data/bookmark/NodeBookmark.h index 793eb0d6..31b19d16 100644 --- a/src/lib/data/bookmark/NodeBookmark.h +++ b/src/lib/data/bookmark/NodeBookmark.h @@ -7,9 +7,15 @@ class NodeBookmark : public Bookmark { public: - NodeBookmark(); - NodeBookmark(const std::string& displayName, const std::vector& tokens, const std::vector& tokenNames, const std::string& comment, const TimePoint& timeStamp); + NodeBookmark(const Id id, const std::string& name, const std::string& comment, const TimePoint& timeStamp, const BookmarkCategory& category); virtual ~NodeBookmark(); + + void addNodeId(const Id nodeId); + void setNodeIds(const std::vector& nodeIds); + std::vector getNodeIds() const; + +private: + std::vector m_nodeIds; }; #endif // NODE_BOOKMARK_H diff --git a/src/lib/data/parser/TaskParseWrapper.cpp b/src/lib/data/parser/TaskParseWrapper.cpp index e8cbdb59..b79a6a67 100644 --- a/src/lib/data/parser/TaskParseWrapper.cpp +++ b/src/lib/data/parser/TaskParseWrapper.cpp @@ -36,7 +36,7 @@ void TaskParseWrapper::doEnter(std::shared_ptr blackboard) if (sourceFileCount > 0) { - m_storage->setMode(SqliteStorage::STORAGE_MODE_WRITE); + m_storage->setMode(SqliteIndexStorage::STORAGE_MODE_WRITE); } } diff --git a/src/lib/project/Project.cpp b/src/lib/project/Project.cpp index fd1d2c30..90e4f7a3 100644 --- a/src/lib/project/Project.cpp +++ b/src/lib/project/Project.cpp @@ -193,10 +193,12 @@ void Project::load() } const FilePath projectSettingsPath = m_settings->getFilePath(); + const std::string dbExtension = (projectSettingsPath.extension() == ".coatiproject" ? "coatidb" : "srctrldb"); const FilePath dbPath = FilePath(projectSettingsPath).replaceExtension(dbExtension); + const FilePath bookmarkPath = FilePath(projectSettingsPath).replaceExtension("srctrlbm"); - m_storage = std::make_shared(dbPath); + m_storage = std::make_shared(dbPath, bookmarkPath); bool canLoad = false; @@ -212,7 +214,6 @@ void Project::load() else if (m_storage->isEmpty()) { m_state = PROJECT_STATE_EMPTY; - m_storage->setup(); } else if (m_storage->isIncompatible()) { @@ -230,6 +231,8 @@ void Project::load() canLoad = true; } + m_storage->setup(); + m_sourceGroups = SourceGroupFactory::getInstance()->createSourceGroups(m_settings->getAllSourceGroupSettings()); if (!m_sourceGroups.empty()) { diff --git a/src/lib/utility/messaging/type/MessageDeleteBookmark.h b/src/lib/utility/messaging/type/MessageDeleteBookmark.h index 13cc65e9..0d4aa1c8 100644 --- a/src/lib/utility/messaging/type/MessageDeleteBookmark.h +++ b/src/lib/utility/messaging/type/MessageDeleteBookmark.h @@ -8,9 +8,8 @@ class MessageDeleteBookmark : public Message { public: - MessageDeleteBookmark(const Id bookmarkId, const bool isEdge) + MessageDeleteBookmark(const Id bookmarkId) : bookmarkId(bookmarkId) - , isEdge(isEdge) { } @@ -24,7 +23,6 @@ public: } const Id bookmarkId; - const bool isEdge; }; -#endif // MESSAGE_DELETE_BOOKMARK_H \ No newline at end of file +#endif // MESSAGE_DELETE_BOOKMARK_H diff --git a/src/lib/utility/messaging/type/MessageDeleteBookmarkCategory.h b/src/lib/utility/messaging/type/MessageDeleteBookmarkCategory.h new file mode 100644 index 00000000..6e8a7013 --- /dev/null +++ b/src/lib/utility/messaging/type/MessageDeleteBookmarkCategory.h @@ -0,0 +1,28 @@ +#ifndef MESSAGE_DELETE_BOOKMARK_CATEGORY_H +#define MESSAGE_DELETE_BOOKMARK_CATEGORY_H + +#include "utility/messaging/Message.h" +#include "utility/types.h" + +class MessageDeleteBookmarkCategory + : public Message +{ +public: + MessageDeleteBookmarkCategory(const Id id) + : categoryId(id) + { + } + + ~MessageDeleteBookmarkCategory() + { + } + + static const std::string getStaticType() + { + return "MessageDeleteBookmarkCategory"; + } + + const Id categoryId; +}; + +#endif // MESSAGE_DELETE_BOOKMARK_CATEGORY_H diff --git a/src/lib/utility/messaging/type/MessageDeleteBookmarkCategoryWithBookmarks.h b/src/lib/utility/messaging/type/MessageDeleteBookmarkCategoryWithBookmarks.h deleted file mode 100644 index 57eddcac..00000000 --- a/src/lib/utility/messaging/type/MessageDeleteBookmarkCategoryWithBookmarks.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef MESSAGE_DELETE_BOOKMARK_CATEGORY_WITH_BOOKMARKS_H -#define MESSAGE_DELETE_BOOKMARK_CATEGORY_WITH_BOOKMARKS_H - -#include "utility/messaging/Message.h" -#include "utility/types.h" - -class MessageDeleteBookmarkCategoryWithBookmarks - : public Message -{ -public: - MessageDeleteBookmarkCategoryWithBookmarks(const Id id) - : categoryId(id) - { - } - - ~MessageDeleteBookmarkCategoryWithBookmarks() - { - } - - static const std::string getStaticType() - { - return "MessageDeleteBookmarkCategoryWithBookmarks"; - } - - const Id categoryId; -}; - -#endif // MESSAGE_DELETE_BOOKMARK_CATEGORY_WITH_BOOKMARKS_H \ No newline at end of file diff --git a/src/lib_gui/qt/element/QtBookmark.cpp b/src/lib_gui/qt/element/QtBookmark.cpp index 7f884dd3..68a6b128 100644 --- a/src/lib_gui/qt/element/QtBookmark.cpp +++ b/src/lib_gui/qt/element/QtBookmark.cpp @@ -92,27 +92,30 @@ QtBookmark::~QtBookmark() void QtBookmark::setBookmark(const std::shared_ptr bookmark) { - m_bookmark = bookmark; - - m_activateButton->setText(bookmark->getDisplayName().c_str()); - - if (m_bookmark->isValid() == false) + if (bookmark) { - m_activateButton->setEnabled(false); - m_editButton->setEnabled(false); - } + m_bookmark = bookmark; - if (m_bookmark->getComment().length() > 0) - { - m_comment->setText(m_bookmark->getComment().c_str()); - m_toggleCommentButton->show(); - } - else - { - m_toggleCommentButton->hide(); - } + m_activateButton->setText(m_bookmark->getName().c_str()); - m_dateLabel->setText(getDateString().c_str()); + if (m_bookmark->isValid() == false) + { + m_activateButton->setEnabled(false); + m_editButton->setEnabled(false); + } + + if (m_bookmark->getComment().length() > 0) + { + m_comment->setText(m_bookmark->getComment().c_str()); + m_toggleCommentButton->show(); + } + else + { + m_toggleCommentButton->hide(); + } + + m_dateLabel->setText(getDateString().c_str()); + } } Id QtBookmark::getBookmarkId() const @@ -169,7 +172,7 @@ void QtBookmark::resizeEvent(QResizeEvent* event) return; } - m_activateButton->setText(m_bookmark->getDisplayName().c_str()); + m_activateButton->setText(m_bookmark->getName().c_str()); QTimer::singleShot(10, this, SLOT(elideButtonText())); } @@ -218,21 +221,21 @@ void QtBookmark::deleteClicked() if (ret == 0) // QMessageBox::Yes) { - MessageDeleteBookmark(m_bookmark->getId(), (dynamic_cast(m_bookmark.get()) != NULL)).dispatch(); + MessageDeleteBookmark(m_bookmark->getId()).dispatch(); } } void QtBookmark::elideButtonText() { m_activateButton->setText(m_activateButton->fontMetrics().elidedText( - m_bookmark->getDisplayName().c_str(), Qt::ElideMiddle, m_activateButton->width() - 16)); + m_bookmark->getName().c_str(), Qt::ElideMiddle, m_activateButton->width() - 16)); } void QtBookmark::handleMessage(MessageEditBookmark* message) { if (m_bookmark->getId() == message->bookmarkId) { - m_bookmark->setDisplayName(message->displayName); + m_bookmark->setName(message->displayName); m_bookmark->setComment(message->comment); m_activateButton->setText(message->displayName.c_str()); diff --git a/src/lib_gui/qt/element/QtBookmarkBar.cpp b/src/lib_gui/qt/element/QtBookmarkBar.cpp index 5f3cae75..8fd9daf2 100644 --- a/src/lib_gui/qt/element/QtBookmarkBar.cpp +++ b/src/lib_gui/qt/element/QtBookmarkBar.cpp @@ -186,19 +186,21 @@ void QtBookmarkBar::doDisplayBookmarkCreator(const std::vector& nam bookmarkCreator->setDisplayName(displayName); bookmarkCreator->setBookmarkCategories(categories); bookmarkCreator->show(); + bookmarkCreator->raise(); } void QtBookmarkBar::doDisplayBookmarkEditor(std::shared_ptr bookmark, const std::vector& categories) { QtBookmarkCreator* bookmarkCreator = new QtBookmarkCreator(NULL, true, bookmark->getId()); bookmarkCreator->setupBookmarkCreator(); - bookmarkCreator->setDisplayName(bookmark->getDisplayName()); + bookmarkCreator->setDisplayName(bookmark->getName()); bookmarkCreator->setComment(bookmark->getComment()); bookmarkCreator->setBookmarkCategories(categories); bookmarkCreator->setCurrentBookmarkCategory(bookmark->getCategory()); bookmarkCreator->setIsEdge((dynamic_cast(bookmark.get()) != NULL)); bookmarkCreator->show(); + bookmarkCreator->raise(); } void QtBookmarkBar::doDisplayBookmarks(const std::vector>& bookmarks) @@ -211,6 +213,7 @@ void QtBookmarkBar::doDisplayBookmarks(const std::vectorsetBookmarks(bookmarks); m_bookmarkBrowser->show(); + m_bookmarkBrowser->raise(); } void QtBookmarkBar::doSetCreateButtonState(const BookmarkView::CreateButtonState& state) @@ -248,4 +251,4 @@ void QtBookmarkBar::doSetCreateButtonState(const BookmarkView::CreateButtonState void QtBookmarkBar::doEnableDisplayButton(bool enable) { m_showBookmarksButton->setEnabled(enable); -} \ No newline at end of file +} diff --git a/src/lib_gui/qt/element/QtBookmarkCategory.cpp b/src/lib_gui/qt/element/QtBookmarkCategory.cpp index bd8982f4..4481ffc0 100644 --- a/src/lib_gui/qt/element/QtBookmarkCategory.cpp +++ b/src/lib_gui/qt/element/QtBookmarkCategory.cpp @@ -3,7 +3,7 @@ #include #include -#include "utility/messaging/type/MessageDeleteBookmarkCategoryWithBookmarks.h" +#include "utility/messaging/type/MessageDeleteBookmarkCategory.h" #include "utility/ResourcePaths.h" #include "qt/utility/utilityQt.h" @@ -142,6 +142,6 @@ void QtBookmarkCategory::deleteClicked() if (ret == 0) // QMessageBox::Yes { - MessageDeleteBookmarkCategoryWithBookmarks(m_id).dispatch(); + MessageDeleteBookmarkCategory(m_id).dispatch(); } } diff --git a/src/lib_gui/qt/window/QtBookmarkBrowser.cpp b/src/lib_gui/qt/window/QtBookmarkBrowser.cpp index 62bcaea9..7758d7a3 100644 --- a/src/lib_gui/qt/window/QtBookmarkBrowser.cpp +++ b/src/lib_gui/qt/window/QtBookmarkBrowser.cpp @@ -126,17 +126,17 @@ void QtBookmarkBrowser::setBookmarks(const std::vector { m_bookmarkTree->clear(); - for (unsigned int i = 0; i < bookmarks.size(); i++) + for (std::shared_ptr bookmark: bookmarks) { - QtBookmark* bookmark = new QtBookmark(); - bookmark->setBookmark(bookmarks[i]); + QtBookmark* qtBookmark = new QtBookmark(); + qtBookmark->setBookmark(bookmark); - QTreeWidgetItem* top = findOrCreateTreeCategory(bookmarks[i]->getCategory()); + QTreeWidgetItem* top = findOrCreateTreeCategory(bookmark->getCategory()); QTreeWidgetItem* treeWidgetItem = new QTreeWidgetItem(top); - m_bookmarkTree->setItemWidget(treeWidgetItem, 0, bookmark); + m_bookmarkTree->setItemWidget(treeWidgetItem, 0, qtBookmark); top->addChild(treeWidgetItem); - bookmark->setTreeWidgetItem(top); + qtBookmark->setTreeWidgetItem(top); top->setExpanded(true); } diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index b0024211..b97e0694 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -24,7 +24,8 @@ add_files( SettingsMigratorTestSuite.h SearchIndexTestSuite.h SourceLocationCollectionTestSuite.h - SqliteStorageTestSuite.h + SqliteBookmarkStorageTestSuite.h + SqliteIndexStorageTestSuite.h StorageTestSuite.h TaskSchedulerTestSuite.h TextAccessTestSuite.h diff --git a/src/test/SqliteBookmarkStorageTestSuite.h b/src/test/SqliteBookmarkStorageTestSuite.h new file mode 100644 index 00000000..8a881642 --- /dev/null +++ b/src/test/SqliteBookmarkStorageTestSuite.h @@ -0,0 +1,111 @@ +#include "cxxtest/TestSuite.h" + +#include "boost/filesystem.hpp" + +#include "data/bookmark/EdgeBookmark.h" +#include "data/bookmark/NodeBookmark.h" +#include "data/SqliteBookmarkStorage.h" + +class SqliteBookmarkStorageTestSuite: public CxxTest::TestSuite +{ +public: + void test_add_bookmarks() + { + std::string databasePath = "data/SQLiteTestSuite/bookmarkTest.sqlite"; + int bookmarkCount = 4; + int result = -1; + { + boost::filesystem::remove(databasePath); + SqliteBookmarkStorage storage(databasePath); + storage.setup(); + + for (unsigned int i = 0; i < bookmarkCount; i++) + { + const Id categoryId = storage.addBookmarkCategory("test category"); + storage.addBookmark("test bookmark", "test comment", TimePoint::now().toString(), categoryId); + } + + result = storage.getAllBookmarks().size(); + } + + boost::filesystem::remove(databasePath); + + TS_ASSERT_EQUALS(result, bookmarkCount); + } + + void test_add_bookmarked_node() + { + std::string databasePath = "data/SQLiteTestSuite/bookmarkTest.sqlite"; + int bookmarkCount = 4; + int result = -1; + { + boost::filesystem::remove(databasePath); + SqliteBookmarkStorage storage(databasePath); + storage.setup(); + + const Id categoryId = storage.addBookmarkCategory("test category"); + const Id bookmarkId = storage.addBookmark("test bookmark", "test comment", TimePoint::now().toString(), categoryId); + + for (unsigned int i = 0; i < bookmarkCount; i++) + { + storage.addBookmarkedNode(bookmarkId, "test name"); + } + + result = storage.getAllBookmarkedNodes().size(); + } + + boost::filesystem::remove(databasePath); + + TS_ASSERT_EQUALS(result, bookmarkCount); + } + + void test_remove_bookmark_also_removes_bookmarked_node() + { + std::string databasePath = "data/SQLiteTestSuite/bookmarkTest.sqlite"; + int bookmarkCount = 4; + int result = -1; + { + boost::filesystem::remove(databasePath); + SqliteBookmarkStorage storage(databasePath); + storage.setup(); + + const Id categoryId = storage.addBookmarkCategory("test category"); + const Id bookmarkId = storage.addBookmark("test bookmark", "test comment", TimePoint::now().toString(), categoryId); + const Id bookmarkedNodeId = storage.addBookmarkedNode(bookmarkId, "test name"); + + storage.removeBookmark(bookmarkId); + + result = storage.getAllBookmarkedNodes().size(); + } + + boost::filesystem::remove(databasePath); + + TS_ASSERT_EQUALS(result, 0); + } + + void test_edit_nodeBookmark() + { + std::string databasePath = "data/SQLiteTestSuite/bookmarkTest.sqlite"; + + const std::string updatedName = "updated name"; + const std::string updatedComment = "updated comment"; + + StorageBookmark storageBookmark; + { + boost::filesystem::remove(databasePath); + SqliteBookmarkStorage storage(databasePath); + storage.setup(); + + const Id categoryId = storage.addBookmarkCategory("test category"); + const Id bookmarkId = storage.addBookmark("test bookmark", "test comment", TimePoint::now().toString(), categoryId); + const Id bookmarkedNodeId = storage.addBookmarkedNode(bookmarkId, "test name"); + + storage.updateBookmark(bookmarkId, updatedName, updatedComment, categoryId); + + storageBookmark = storage.getAllBookmarks().front(); + } + + TS_ASSERT_EQUALS(updatedName, storageBookmark.name); + TS_ASSERT_EQUALS(updatedComment, storageBookmark.comment); + } +}; diff --git a/src/test/SqliteStorageTestSuite.h b/src/test/SqliteIndexStorageTestSuite.h similarity index 87% rename from src/test/SqliteStorageTestSuite.h rename to src/test/SqliteIndexStorageTestSuite.h index 4d341efe..db37b165 100644 --- a/src/test/SqliteStorageTestSuite.h +++ b/src/test/SqliteIndexStorageTestSuite.h @@ -3,9 +3,9 @@ #include "boost/filesystem.hpp" #include "sqlite/CppSQLite3.h" -#include "data/SqliteStorage.h" +#include "data/SqliteIndexStorage.h" -class SqliteStorageTestSuite: public CxxTest::TestSuite +class SqliteIndexStorageTestSuite: public CxxTest::TestSuite { public: void test_storage_adds_node_successfully() @@ -13,7 +13,7 @@ public: std::string databasePath = "data/SQLiteTestSuite/test.sqlite"; int nodeCount = -1; { - SqliteStorage storage(databasePath); + SqliteIndexStorage storage(databasePath); storage.setup(); storage.beginTransaction(); storage.addNode(0, "a"); @@ -30,7 +30,7 @@ public: std::string databasePath = "data/SQLiteTestSuite/test.sqlite"; int nodeCount = -1; { - SqliteStorage storage(databasePath); + SqliteIndexStorage storage(databasePath); storage.setup(); storage.beginTransaction(); int nodeId = storage.addNode(0, "a"); @@ -48,7 +48,7 @@ public: std::string databasePath = "data/SQLiteTestSuite/test.sqlite"; int edgeCount = -1; { - SqliteStorage storage(databasePath); + SqliteIndexStorage storage(databasePath); storage.setup(); storage.beginTransaction(); int sourceNodeId = storage.addNode(0, "a"); @@ -67,7 +67,7 @@ public: std::string databasePath = "data/SQLiteTestSuite/test.sqlite"; int edgeCount = -1; { - SqliteStorage storage(databasePath); + SqliteIndexStorage storage(databasePath); storage.setup(); storage.beginTransaction(); int sourceNodeId = storage.addNode(0, "a"); diff --git a/src/test/StorageTestSuite.h b/src/test/StorageTestSuite.h index 44e87fa8..1063e9b3 100644 --- a/src/test/StorageTestSuite.h +++ b/src/test/StorageTestSuite.h @@ -232,7 +232,7 @@ private: { public: TestStorage() - : PersistentStorage("data/test.sqlite") + : PersistentStorage("data/test.sqlite", "data/testBookmarks.sqlite") { clear(); } diff --git a/src/test/readme.txt b/src/test/readme.txt new file mode 100644 index 00000000..54dced1c --- /dev/null +++ b/src/test/readme.txt @@ -0,0 +1,18 @@ +--------- +Debugging +--------- +To debug unit tests remove the post-build event, set the execution directory for 'Coati_test' to '.../Coati/bin/test' and run 'Coati_test' as startup project + + +Post build event (if you manage to delete it without saving it somewhere): + +setlocal +cd $(ProjectDir)../../bin/test/ +$(OutDir)$(TargetName)$(TargetExt) +if %errorlevel% neq 0 goto :cmEnd +:cmEnd +endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone +:cmErrorLevel +exit /b %1 +:cmDone +if %errorlevel% neq 0 goto :VCEnd \ No newline at end of file