logic: add storage transformation to merge anonymous types and the respective typedef

* moved storage related classes to data/storage folder
* implemented recording c++ unions as NODE_UNION instead of just using NODE_TYPE
* added transformation to merge anonymous classes/structs/enums/unions and typedef nodes
* added tests for this transformation
* added setting for enabling/disabling this transformation
This commit is contained in:
malte_langkabel
2017-07-18 15:14:43 +02:00
parent e536f20e36
commit cad595a32c
76 changed files with 524 additions and 96 deletions
@@ -0,0 +1,563 @@
#include "data/storage/IntermediateStorage.h"
#include <set>
IntermediateStorage::IntermediateStorage()
: m_nextId(1)
{
}
IntermediateStorage::~IntermediateStorage()
{
}
void IntermediateStorage::clear()
{
m_nodes.clear();
m_nodesIndex.clear();
m_files.clear();
m_symbols.clear();
m_edges.clear();
m_edgesIndex.clear();
m_localSymbols.clear();
m_sourceLocations.clear();
m_occurrences.clear();
m_componentAccesses.clear();
m_commentLocations.clear();
m_errors.clear();
m_nextId = 1;
}
size_t IntermediateStorage::getByteSize() const
{
unsigned int byteSize = 0;
for (const StorageFile& storageFile: getStorageFiles())
{
byteSize += sizeof(StorageFile);
byteSize += storageFile.filePath.size();
byteSize += storageFile.modificationTime.size();
}
for (const StorageError& storageError: getErrors())
{
byteSize += sizeof(StorageError);
byteSize += storageError.filePath.str().size();
byteSize += storageError.message.size();
}
for (const StorageNode& storageNode: getStorageNodes())
{
byteSize += sizeof(StorageNode);
byteSize += storageNode.serializedName.size();
}
for (const StorageLocalSymbol& storageLocalSymbol: getStorageLocalSymbols())
{
byteSize += sizeof(StorageLocalSymbol);
byteSize += storageLocalSymbol.name.size();
}
byteSize += sizeof(StorageEdge) * getStorageEdges().size();
byteSize += sizeof(StorageCommentLocation) * getCommentLocations().size();
byteSize += sizeof(StorageComponentAccess) * getComponentAccesses().size();
byteSize += sizeof(StorageOccurrence) * getStorageOccurrences().size();
byteSize += sizeof(StorageSymbol) * getStorageSymbols().size();
byteSize += sizeof(StorageSourceLocation) * getStorageSourceLocations().size();
return byteSize;
}
size_t IntermediateStorage::getSourceLocationCount() const
{
return m_sourceLocations.size();
}
void IntermediateStorage::setAllFilesIncomplete()
{
for (StorageFile& file : m_files)
{
file.complete = false;
}
}
void IntermediateStorage::setFilesWithErrorsIncomplete()
{
std::set<std::string> errorFileNames;
for (StorageError& error : m_errors)
{
errorFileNames.insert(error.filePath.str());
}
for (StorageFile& file : m_files)
{
if (errorFileNames.find(file.filePath) != errorFileNames.end())
{
file.complete = false;
}
}
}
Id IntermediateStorage::addNode(int type, const std::string& serializedName)
{
StorageNode node(0, type, serializedName);
const std::string serialized = serialize(node);
std::unordered_map<std::string, size_t>::iterator it = m_nodesIndex.find(serialized);
if (it != m_nodesIndex.end())
{
StorageNode& storedNode = m_nodes[it->second];
if (storedNode.type < type)
{
storedNode.type = type;
}
return storedNode.id;
}
const Id id = m_nextId++;
node.id = id;
m_nodes.push_back(node);
m_nodesIndex.emplace(serialized, m_nodes.size() - 1);
return id;
}
void IntermediateStorage::addFile(const Id id, const std::string& filePath, const std::string& modificationTime, bool complete)
{
const StorageFile file(id, filePath, modificationTime, complete);
const std::string serialized = serialize(file);
if (m_serializedFiles.find(serialized) == m_serializedFiles.end())
{
m_files.push_back(file);
m_serializedFiles.insert(serialized);
}
}
void IntermediateStorage::addSymbol(const Id id, int definitionKind)
{
m_symbols.push_back(StorageSymbol(id, definitionKind));
}
Id IntermediateStorage::addEdge(int type, Id sourceId, Id targetId)
{
StorageEdge edge = StorageEdge(0, type, sourceId, targetId);
const std::string serialized = serialize(edge);
std::unordered_map<std::string, size_t>::const_iterator it = m_edgesIndex.find(serialized);
if (it != m_edgesIndex.end())
{
return m_edges[it->second].id;
}
const Id id = m_nextId++;
edge.id = id;
m_edges.push_back(edge);
m_edgesIndex.emplace(serialized, m_edges.size() - 1);
return id;
}
Id IntermediateStorage::addLocalSymbol(const std::string& name)
{
StorageLocalSymbol localSymbol = StorageLocalSymbol(0, name);
const std::string serialized = serialize(localSymbol);
std::unordered_map<std::string, StorageLocalSymbol>::const_iterator it = m_localSymbols.find(serialized);
if (it != m_localSymbols.end())
{
return it->second.id;
}
const Id id = m_nextId++;
localSymbol.id = id;
m_localSymbols[serialized] = localSymbol;
return id;
}
Id IntermediateStorage::addSourceLocation(Id fileNodeId, uint startLine, uint startCol, uint endLine, uint endCol, int type)
{
StorageSourceLocation sourceLocation = StorageSourceLocation(
0,
fileNodeId,
startLine,
startCol,
endLine,
endCol,
type
);
const std::string serialized = serialize(sourceLocation);
std::unordered_map<std::string, StorageSourceLocation>::const_iterator it = m_sourceLocations.find(serialized);
if (it != m_sourceLocations.end())
{
return it->second.id;
}
const Id id = m_nextId++;
sourceLocation.id = id;
m_sourceLocations[serialized] = sourceLocation;
return id;
}
void IntermediateStorage::addOccurrence(Id elementId, Id sourceLocationId)
{
const StorageOccurrence occurrence(elementId, sourceLocationId);
const std::string serialized = serialize(occurrence);
if (m_serializedOccurrences.find(serialized) == m_serializedOccurrences.end())
{
m_occurrences.push_back(occurrence);
m_serializedOccurrences.insert(serialized);
}
}
void IntermediateStorage::addComponentAccess(Id nodeId, int type)
{
const StorageComponentAccess componentAccess(0, nodeId, type);
const std::string serialized = serialize(componentAccess);
if (m_serializedComponentAccesses.find(serialized) == m_serializedComponentAccesses.end())
{
m_componentAccesses.push_back(componentAccess);
m_serializedComponentAccesses.insert(serialized);
}
}
void IntermediateStorage::addCommentLocation(Id fileNodeId, uint startLine, uint startCol, uint endLine, uint endCol)
{
const StorageCommentLocation commentLocation(
0,
fileNodeId,
startLine,
startCol,
endLine,
endCol
);
const std::string serialized = serialize(commentLocation);
if (m_serializedCommentLocations.find(serialized) == m_serializedCommentLocations.end())
{
m_commentLocations.push_back(commentLocation);
m_serializedCommentLocations.insert(serialized);
}
}
void IntermediateStorage::addError(
const std::string& message, const FilePath& filePath, uint startLine, uint startCol, bool fatal, bool indexed)
{
const StorageError error(
0,
message,
filePath,
startLine,
startCol,
fatal,
indexed
);
const std::string serialized = serialize(error);
if (m_serializedErrors.find(serialized) == m_serializedErrors.end())
{
m_errors.push_back(error);
m_serializedErrors.insert(serialized);
}
}
void IntermediateStorage::forEachNode(std::function<void(const StorageNode& /*data*/)> callback) const
{
for (const StorageNode& node : m_nodes)
{
callback(node);
}
}
void IntermediateStorage::forEachFile(std::function<void(const StorageFile& /*data*/)> callback) const
{
for (std::vector<StorageFile>::const_iterator it = m_files.begin(); it != m_files.end(); it++)
{
callback(*it);
}
}
void IntermediateStorage::forEachSymbol(std::function<void(const StorageSymbol& /*data*/)> callback) const
{
for (std::vector<StorageSymbol>::const_iterator it = m_symbols.begin(); it != m_symbols.end(); it++)
{
callback(*it);
}
}
void IntermediateStorage::forEachEdge(std::function<void(const StorageEdge& /*data*/)> callback) const
{
for (const StorageEdge& edge : m_edges)
{
callback(edge);
}
}
void IntermediateStorage::forEachLocalSymbol(std::function<void(const StorageLocalSymbol& /*data*/)> callback) const
{
for (std::unordered_map<std::string, StorageLocalSymbol>::const_iterator it = m_localSymbols.begin();
it != m_localSymbols.end(); it++)
{
callback(it->second);
}
}
void IntermediateStorage::forEachSourceLocation(std::function<void(const StorageSourceLocation& /*data*/)> callback) const
{
for (std::unordered_map<std::string, StorageSourceLocation>::const_iterator it = m_sourceLocations.begin();
it != m_sourceLocations.end(); it++)
{
callback(it->second);
}
}
void IntermediateStorage::forEachOccurrence(std::function<void(const StorageOccurrence& /*data*/)> callback) const
{
for (std::vector<StorageOccurrence>::const_iterator it = m_occurrences.begin(); it != m_occurrences.end(); it++)
{
callback(*it);
}
}
void IntermediateStorage::forEachComponentAccess(std::function<void(const StorageComponentAccess& /*data*/)> callback) const
{
for (std::vector<StorageComponentAccess>::const_iterator it = m_componentAccesses.begin(); it != m_componentAccesses.end(); it++)
{
callback(*it);
}
}
void IntermediateStorage::forEachCommentLocation(std::function<void(const StorageCommentLocation& /*data*/)> callback) const
{
for (std::vector<StorageCommentLocation>::const_iterator it = m_commentLocations.begin(); it != m_commentLocations.end(); it++)
{
callback(*it);
}
}
void IntermediateStorage::forEachError(std::function<void(const StorageError& /*data*/)> callback) const
{
for (std::vector<StorageError>::const_iterator it = m_errors.begin(); it != m_errors.end(); it++)
{
callback(*it);
}
}
std::vector<StorageNode> IntermediateStorage::getStorageNodes() const
{
return m_nodes;
}
std::vector<StorageFile> IntermediateStorage::getStorageFiles() const
{
return m_files;
}
std::vector<StorageSymbol> IntermediateStorage::getStorageSymbols() const
{
return m_symbols;
}
std::vector<StorageEdge> IntermediateStorage::getStorageEdges() const
{
return m_edges;
}
std::vector<StorageLocalSymbol> IntermediateStorage::getStorageLocalSymbols() const
{
std::vector<StorageLocalSymbol> localSymbol;
localSymbol.reserve(m_localSymbols.size());
for (auto it: m_localSymbols)
{
localSymbol.push_back(it.second);
}
return localSymbol;
}
std::vector<StorageSourceLocation> IntermediateStorage::getStorageSourceLocations() const
{
std::vector<StorageSourceLocation> sourceLocations;
sourceLocations.reserve(m_sourceLocations.size());
for (auto it: m_sourceLocations)
{
sourceLocations.push_back(it.second);
}
return sourceLocations;
}
std::vector<StorageOccurrence> IntermediateStorage::getStorageOccurrences() const
{
return m_occurrences;
}
std::vector<StorageComponentAccess> IntermediateStorage::getComponentAccesses() const
{
return m_componentAccesses;
}
std::vector<StorageCommentLocation> IntermediateStorage::getCommentLocations() const
{
return m_commentLocations;
}
std::vector<StorageError> IntermediateStorage::getErrors() const
{
return m_errors;
}
void IntermediateStorage::setStorageNodes(const std::vector<StorageNode>& storageNodes)
{
m_nodes.clear();
m_nodesIndex.clear();
for (const StorageNode& storageNode: storageNodes)
{
m_nodes.push_back(storageNode);
m_nodesIndex.emplace(serialize(storageNode), m_nodes.size() - 1);
}
}
void IntermediateStorage::setStorageFiles(const std::vector<StorageFile>& storageFiles)
{
m_files = storageFiles;
}
void IntermediateStorage::setStorageSymbols(const std::vector<StorageSymbol>& storageSymbols)
{
m_symbols = storageSymbols;
}
void IntermediateStorage::setStorageEdges(const std::vector<StorageEdge>& storageEdges)
{
m_edges.clear();
m_edgesIndex.clear();
for (const StorageEdge& storageEdge: storageEdges)
{
m_edges.push_back(storageEdge);
m_edgesIndex.emplace(serialize(storageEdge), m_edges.size() - 1);
}
}
void IntermediateStorage::setStorageLocalSymbols(const std::vector<StorageLocalSymbol>& storageLocalSymbols)
{
m_localSymbols.clear();
for (const StorageLocalSymbol& storageLocalSymbol: storageLocalSymbols)
{
m_localSymbols[serialize(storageLocalSymbol)] = storageLocalSymbol;
}
}
void IntermediateStorage::setStorageSourceLocations(const std::vector<StorageSourceLocation>& storageSourceLocations)
{
m_sourceLocations.clear();
for (const StorageSourceLocation& storageSourceLocation: storageSourceLocations)
{
m_sourceLocations[serialize(storageSourceLocation)] = storageSourceLocation;
}
}
void IntermediateStorage::setStorageOccurrences(const std::vector<StorageOccurrence>& storageOccurrences)
{
m_occurrences = storageOccurrences;
}
void IntermediateStorage::setComponentAccesses(const std::vector<StorageComponentAccess>& componentAccesses)
{
m_componentAccesses = componentAccesses;
}
void IntermediateStorage::setCommentLocations(const std::vector<StorageCommentLocation>& commentLocations)
{
m_commentLocations = commentLocations;
}
void IntermediateStorage::setErrors(const std::vector<StorageError>& errors)
{
m_errors = errors;
}
Id IntermediateStorage::getNextId() const
{
return m_nextId;
}
void IntermediateStorage::setNextId(const Id nextId)
{
m_nextId = nextId;
}
std::string IntermediateStorage::serialize(const StorageNode& node) const
{
return node.serializedName;
}
std::string IntermediateStorage::serialize(const StorageFile& file) const
{
return file.filePath;
}
std::string IntermediateStorage::serialize(const StorageEdge& edge) const
{
return (
std::to_string(edge.type) + ";" +
std::to_string(edge.sourceNodeId) + ";" +
std::to_string(edge.targetNodeId)
);
}
std::string IntermediateStorage::serialize(const StorageLocalSymbol& localSymbol) const
{
return localSymbol.name;
}
std::string IntermediateStorage::serialize(const StorageSourceLocation& sourceLocation) const
{
return (
std::to_string(sourceLocation.fileNodeId) + ";" +
std::to_string(sourceLocation.startLine) + ";" +
std::to_string(sourceLocation.startCol) + ";" +
std::to_string(sourceLocation.endLine) + ";" +
std::to_string(sourceLocation.endCol) + ";" +
std::to_string(sourceLocation.type)
);
}
std::string IntermediateStorage::serialize(const StorageOccurrence& occurrence) const
{
return std::to_string(occurrence.elementId) + ";" + std::to_string(occurrence.sourceLocationId);
}
std::string IntermediateStorage::serialize(const StorageComponentAccess& componentAccess) const
{
return std::to_string(componentAccess.nodeId);
}
std::string IntermediateStorage::serialize(const StorageCommentLocation& commentLocation) const
{
return (
std::to_string(commentLocation.fileNodeId) + ";" +
std::to_string(commentLocation.startLine) + ";" +
std::to_string(commentLocation.startCol) + ";" +
std::to_string(commentLocation.endLine) + ";" +
std::to_string(commentLocation.endCol)
);
}
std::string IntermediateStorage::serialize(const StorageError& error) const
{
return (
error.message + ";" +
std::to_string(error.fatal) + ";" +
error.filePath.str() + ";" +
std::to_string(error.lineNumber) + ";" +
std::to_string(error.columnNumber)
);
}
+117
View File
@@ -0,0 +1,117 @@
#ifndef INTERMEDIATE_STORAGE_H
#define INTERMEDIATE_STORAGE_H
#include <memory>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include "data/storage/StorageTypes.h"
#include "data/storage/Storage.h"
class IntermediateStorage: public Storage
{
public:
IntermediateStorage();
virtual ~IntermediateStorage();
void clear();
size_t getByteSize() const;
size_t getSourceLocationCount() const;
void setAllFilesIncomplete();
void setFilesWithErrorsIncomplete();
virtual Id addNode(int type, const std::string& serializedName);
virtual void addFile(const Id id, const std::string& filePath, const std::string& modificationTime, bool complete);
virtual void addSymbol(const Id id, int definitionKind);
virtual Id addEdge(int type, Id sourceId, Id targetId);
virtual Id addLocalSymbol(const std::string& name);
virtual Id addSourceLocation(Id fileNodeId, uint startLine, uint startCol, uint endLine, uint endCol, int type);
virtual void addOccurrence(Id elementId, Id sourceLocationId);
virtual void addComponentAccess(Id nodeId , int type);
virtual void addCommentLocation(Id fileNodeId, uint startLine, uint startCol, uint endLine, uint endCol);
virtual void addError(const std::string& message, const FilePath& filePath, uint startLine, uint startCol, bool fatal, bool indexed);
virtual void forEachNode(std::function<void(const StorageNode& /*data*/)> callback) const;
virtual void forEachFile(std::function<void(const StorageFile& /*data*/)> callback) const;
virtual void forEachSymbol(std::function<void(const StorageSymbol& /*data*/)> callback) const;
virtual void forEachEdge(std::function<void(const StorageEdge& /*data*/)> callback) const;
virtual void forEachLocalSymbol(std::function<void(const StorageLocalSymbol& /*data*/)> callback) const;
virtual void forEachSourceLocation(std::function<void(const StorageSourceLocation& /*data*/)> callback) const;
virtual void forEachOccurrence(std::function<void(const StorageOccurrence& /*data*/)> callback) const;
virtual void forEachComponentAccess(std::function<void(const StorageComponentAccess& /*data*/)> callback) const;
virtual void forEachCommentLocation(std::function<void(const StorageCommentLocation& /*data*/)> callback) const;
virtual void forEachError(std::function<void(const StorageError& /*data*/)> callback) const;
// for conversion to and from 'SharedIntermediateStorage'
std::vector<StorageNode> getStorageNodes() const;
std::vector<StorageFile> getStorageFiles() const;
std::vector<StorageSymbol> getStorageSymbols() const;
std::vector<StorageEdge> getStorageEdges() const;
std::vector<StorageLocalSymbol> getStorageLocalSymbols() const;
std::vector<StorageSourceLocation> getStorageSourceLocations() const;
std::vector<StorageOccurrence> getStorageOccurrences() const;
std::vector<StorageComponentAccess> getComponentAccesses() const;
std::vector<StorageCommentLocation> getCommentLocations() const;
std::vector<StorageError> getErrors() const;
void setStorageNodes(const std::vector<StorageNode>& storageNodes);
void setStorageFiles(const std::vector<StorageFile>& storageFiles);
void setStorageSymbols(const std::vector<StorageSymbol>& storageSymbols);
void setStorageEdges(const std::vector<StorageEdge>& storageEdges);
void setStorageLocalSymbols(const std::vector<StorageLocalSymbol>& storageLocalSymbols);
void setStorageSourceLocations(const std::vector<StorageSourceLocation>& storageSourceLocations);
void setStorageOccurrences(const std::vector<StorageOccurrence>& storageOccurrences);
void setComponentAccesses(const std::vector<StorageComponentAccess>& componentAccesses);
void setCommentLocations(const std::vector<StorageCommentLocation>& commentLocations);
void setErrors(const std::vector<StorageError>& errors);
Id getNextId() const;
void setNextId(const Id nextId);
private:
std::string serialize(const StorageNode& node) const;
std::string serialize(const StorageFile& file) const;
std::string serialize(const StorageEdge& edge) const;
std::string serialize(const StorageLocalSymbol& localSymbol) const;
std::string serialize(const StorageSourceLocation& sourceLocation) const;
std::string serialize(const StorageOccurrence& occurrence) const;
std::string serialize(const StorageComponentAccess& componentAccess) const;
std::string serialize(const StorageCommentLocation& commentLocation) const;
std::string serialize(const StorageError& error) const;
std::unordered_map<std::string, size_t> m_nodesIndex;
std::vector<StorageNode> m_nodes;
std::unordered_set<std::string> m_serializedFiles; // this is used to prevent duplicates (unique)
std::vector<StorageFile> m_files;
std::vector<StorageSymbol> m_symbols;
std::unordered_map<std::string, size_t> m_edgesIndex;
std::vector<StorageEdge> m_edges;
std::unordered_map<std::string, StorageLocalSymbol> m_localSymbols;
std::unordered_map<std::string, StorageSourceLocation> m_sourceLocations;
std::unordered_set<std::string> m_serializedOccurrences; // this is used to prevent duplicates (unique)
std::vector<StorageOccurrence> m_occurrences;
std::unordered_set<std::string> m_serializedComponentAccesses; // this is used to prevent duplicates (unique)
std::vector<StorageComponentAccess> m_componentAccesses;
std::unordered_set<std::string> m_serializedCommentLocations; // this is used to prevent duplicates (unique)
std::vector<StorageCommentLocation> m_commentLocations;
std::unordered_set<std::string> m_serializedErrors; // this is used to prevent duplicates (unique)
std::vector<StorageError> m_errors;
Id m_nextId;
};
#endif // INTERMEDIATE_STORAGE_H
File diff suppressed because it is too large Load Diff
+195
View File
@@ -0,0 +1,195 @@
#ifndef PERSISTENT_STORAGE_H
#define PERSISTENT_STORAGE_H
#include <memory>
#include <vector>
#include "data/access/StorageAccess.h"
#include "data/fulltextsearch/FullTextSearchIndex.h"
#include "data/search/SearchIndex.h"
#include "data/HierarchyCache.h"
#include "data/storage/sqlite/SqliteIndexStorage.h"
#include "data/storage/sqlite/SqliteBookmarkStorage.h"
#include "data/storage/Storage.h"
class PersistentStorage
: public Storage
, public StorageAccess
{
public:
PersistentStorage(const FilePath& dbPath, const FilePath& bookmarkPath);
virtual ~PersistentStorage();
virtual Id addNode(int type, const std::string& serializedName);
virtual void addFile(const Id id, const std::string& filePath, const std::string& modificationTime, bool complete);
virtual void addSymbol(const Id id, int definitionKind);
virtual Id addEdge(int type, Id sourceId, Id targetId);
virtual Id addLocalSymbol(const std::string& name);
virtual Id addSourceLocation(Id fileNodeId, uint startLine, uint startCol, uint endLine, uint endCol, int type);
virtual void addOccurrence(Id elementId, Id sourceLocationId);
virtual void addComponentAccess(Id nodeId , int type);
virtual void addCommentLocation(Id fileNodeId, uint startLine, uint startCol, uint endLine, uint endCol);
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 std::string& categoryName);
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<NodeBookmark> getAllNodeBookmarks() const;
std::vector<EdgeBookmark> getAllEdgeBookmarks() const;
virtual std::vector<BookmarkCategory> getAllBookmarkCategories() const;
virtual void forEachNode(std::function<void(const StorageNode& /*data*/)> callback) const;
virtual void forEachFile(std::function<void(const StorageFile& /*data*/)> callback) const;
virtual void forEachSymbol(std::function<void(const StorageSymbol& /*data*/)> callback) const;
virtual void forEachEdge(std::function<void(const StorageEdge& /*data*/)> callback) const;
virtual void forEachLocalSymbol(std::function<void(const StorageLocalSymbol& /*data*/)> callback) const;
virtual void forEachSourceLocation(std::function<void(const StorageSourceLocation& /*data*/)> callback) const;
virtual void forEachOccurrence(std::function<void(const StorageOccurrence& /*data*/)> callback) const;
virtual void forEachComponentAccess(std::function<void(const StorageComponentAccess& /*data*/)> callback) const;
virtual void forEachCommentLocation(std::function<void(const StorageCommentLocation& /*data*/)> callback) const;
virtual void forEachError(std::function<void(const StorageError& /*data*/)> callback) const;
virtual void startInjection();
virtual void finishInjection();
void setMode(const SqliteIndexStorage::StorageModeType mode);
FilePath getDbFilePath() const;
bool isEmpty() const;
bool isIncompatible() const;
std::string getProjectSettingsText() const;
void setProjectSettingsText(std::string text);
void setup();
void clear();
void clearCaches();
std::set<FilePath> getReferenced(const std::set<FilePath>& filePaths);
std::set<FilePath> getReferencing(const std::set<FilePath>& filePaths);
void clearFileElements(const std::vector<FilePath>& filePaths, std::function<void(int)> updateStatusCallback);
std::vector<FileInfo> getInfoOnAllFiles() const;
void buildCaches();
void optimizeMemory();
// StorageAccess implementation
virtual Id getNodeIdForFileNode(const FilePath& filePath) const;
virtual Id getNodeIdForNameHierarchy(const NameHierarchy& nameHierarchy) const;
virtual std::vector<Id> getNodeIdsForNameHierarchies(const std::vector<NameHierarchy> nameHierarchies) const;
virtual NameHierarchy getNameHierarchyForNodeId(Id nodeId) const;
virtual std::vector<NameHierarchy> getNameHierarchiesForNodeIds(const std::vector<Id> nodeIds) const;
virtual Node::NodeType getNodeTypeForNodeWithId(Id nodeId) const;
virtual Id getIdForEdge(
Edge::EdgeType type, const NameHierarchy& fromNameHierarchy, const NameHierarchy& toNameHierarchy) const;
virtual StorageEdge getEdgeById(Id edgeId) const;
virtual std::shared_ptr<SourceLocationCollection> getFullTextSearchLocations(
const std::string& searchTerm, bool caseSensitive) const;
virtual std::vector<SearchMatch> getAutocompletionMatches(const std::string& query) const;
std::vector<SearchMatch> getAutocompletionSymbolMatches(const std::string& query, size_t maxResultsCount) const;
std::vector<SearchMatch> getAutocompletionFileMatches(const std::string& query, size_t maxResultsCount) const;
std::vector<SearchMatch> getAutocompletionCommandMatches(const std::string& query) const;
virtual std::vector<SearchMatch> getSearchMatchesForTokenIds(const std::vector<Id>& elementIds) const;
virtual std::shared_ptr<Graph> getGraphForAll() const;
virtual std::shared_ptr<Graph> getGraphForActiveTokenIds(
const std::vector<Id>& tokenIds, const std::vector<Id>& expandedNodeIds, bool* isActiveNamespace = nullptr) const;
virtual std::shared_ptr<Graph> getGraphForChildrenOfNodeId(Id nodeId) const;
virtual std::shared_ptr<Graph> getGraphForTrail(Id originId, Id targetId, Edge::EdgeTypeMask trailType, size_t depth) const;
virtual std::vector<Id> getActiveTokenIdsForId(Id tokenId, Id* declarationId) const;
virtual std::vector<Id> getNodeIdsForLocationIds(const std::vector<Id>& locationIds) const;
virtual std::shared_ptr<SourceLocationCollection> getSourceLocationsForTokenIds(const std::vector<Id>& tokenIds) const;
virtual std::shared_ptr<SourceLocationCollection> getSourceLocationsForLocationIds(const std::vector<Id>& locationIds) const;
virtual std::shared_ptr<SourceLocationFile> getSourceLocationsForFile(const FilePath& filePath) const;
virtual std::shared_ptr<SourceLocationFile> getSourceLocationsForLinesInFile(
const FilePath& filePath, uint firstLineNumber, uint lastLineNumber
) const;
virtual std::shared_ptr<SourceLocationFile> getCommentLocationsInFile(const FilePath& filePath) const;
virtual std::shared_ptr<TextAccess> getFileContent(const FilePath& filePath) const;
virtual FileInfo getFileInfoForFilePath(const FilePath& filePath) const;
virtual std::vector<FileInfo> getFileInfosForFilePaths(const std::vector<FilePath>& filePaths) const;
virtual StorageStats getStorageStats() const;
virtual ErrorCountInfo getErrorCount() const;
virtual ErrorCountInfo getErrorCount(const std::vector<ErrorInfo>& errors) const;
virtual std::vector<ErrorInfo> getErrors() const;
virtual std::vector<ErrorInfo> getErrorsLimited() const;
virtual std::shared_ptr<SourceLocationCollection> getErrorSourceLocationsLimited(std::vector<ErrorInfo>* errors) const;
private:
Id getFileNodeId(const FilePath& filePath) const;
std::vector<Id> getFileNodeIds(const std::vector<FilePath>& filePaths) const;
std::set<Id> getFileNodeIds(const std::set<FilePath>& filePaths) const;
FilePath getFileNodePath(Id fileId) const;
bool getFileNodeComplete(const FilePath& filePath) const;
std::unordered_map<Id, std::set<Id>> getFileIdToIncludingFileIdMap() const;
std::unordered_map<Id, std::set<Id>> getFileIdToImportingFileIdMap() const;
std::set<Id> getReferenced(const std::set<Id>& filePaths, std::unordered_map<Id, std::set<Id>> idToReferencingIdMap) const;
std::set<Id> getReferencing(const std::set<Id>& filePaths, std::unordered_map<Id, std::set<Id>> idToReferencingIdMap) const;
std::set<FilePath> getReferencedByIncludes(const std::set<FilePath>& filePaths);
std::set<FilePath> getReferencedByImports(const std::set<FilePath>& filePaths);
std::set<FilePath> getReferencingByIncludes(const std::set<FilePath>& filePaths);
std::set<FilePath> getReferencingByImports(const std::set<FilePath>& filePaths);
void addNodesToGraph(const std::vector<Id>& nodeIds, Graph* graph, bool addChildCount) const;
void addEdgesToGraph(const std::vector<Id>& edgeIds, Graph* graph) const;
void addNodesWithParentsAndEdgesToGraph(
const std::vector<Id>& nodeIds, const std::vector<Id>& edgeIds, Graph* graph) const;
void addAggregationEdgesToGraph(const Id nodeId, const std::vector<StorageEdge>& edgesToAggregate, Graph* graph) const;
void addComponentAccessToGraph(Graph* graph) const;
void addCompleteFlagsToSourceLocationCollection(SourceLocationCollection* collection) const;
void addInheritanceChainsToGraph(const std::vector<Id>& nodeIds, Graph* graph) const;
void buildFilePathMaps();
void buildSearchIndex();
void buildFullTextSearchIndex() const;
void buildHierarchyCache();
size_t m_preInjectionErrorCount;
SearchIndex m_commandIndex;
SearchIndex m_symbolIndex;
SearchIndex m_fileIndex;
mutable FullTextSearchIndex m_fullTextSearchIndex;
SqliteIndexStorage m_sqliteIndexStorage;
SqliteBookmarkStorage m_sqliteBookmarkStorage;
std::map<FilePath, Id> m_fileNodeIds;
std::map<Id, FilePath> m_fileNodePaths;
std::map<Id, bool> m_fileNodeComplete;
std::map<Id, DefinitionKind> m_symbolDefinitionKinds;
HierarchyCache m_hierarchyCache;
};
#endif // PERSISTENT_STORAGE_H
+213
View File
@@ -0,0 +1,213 @@
#include "data/storage/Storage.h"
#include <unordered_map>
#include "data/storage/StorageTypes.h"
#include "utility/tracing.h"
Storage::Storage()
{
}
Storage::~Storage()
{
}
void Storage::inject(Storage* injected)
{
std::lock_guard<std::mutex> lock(m_dataMutex);
TRACE();
startInjection();
std::unordered_map<Id, Id> injectedIdToOwnId;
injected->forEachNode(
[&](const StorageNode& injectedData)
{
const Id ownId = addNode(injectedData.type, injectedData.serializedName);
if (ownId != 0)
{
injectedIdToOwnId[injectedData.id] = ownId;
}
}
);
injected->forEachFile(
[&](const StorageFile& injectedData)
{
std::unordered_map<Id, Id>::const_iterator it;
it = injectedIdToOwnId.find(injectedData.id);
if (it == injectedIdToOwnId.end())
{
return;
}
const Id ownId = it->second;
addFile(ownId, injectedData.filePath, injectedData.modificationTime, injectedData.complete);
}
);
injected->forEachSymbol(
[&](const StorageSymbol& injectedData)
{
std::unordered_map<Id, Id>::const_iterator it;
it = injectedIdToOwnId.find(injectedData.id);
if (it == injectedIdToOwnId.end())
{
return;
}
const Id ownId = it->second;
addSymbol(ownId, injectedData.definitionKind);
}
);
injected->forEachEdge(
[&](const StorageEdge& injectedData)
{
std::unordered_map<Id, Id>::const_iterator it;
it = injectedIdToOwnId.find(injectedData.sourceNodeId);
if (it == injectedIdToOwnId.end())
{
return;
}
const Id ownSourceId = it->second;
it = injectedIdToOwnId.find(injectedData.targetNodeId);
if (it == injectedIdToOwnId.end())
{
return;
}
const Id ownTargetId = it->second;
const Id ownId = addEdge(injectedData.type, ownSourceId, ownTargetId);
if (ownId != 0)
{
injectedIdToOwnId[injectedData.id] = ownId;
}
}
);
injected->forEachLocalSymbol(
[&](const StorageLocalSymbol& injectedData)
{
const Id ownId = addLocalSymbol(injectedData.name);
if (ownId != 0)
{
injectedIdToOwnId[injectedData.id] = ownId;
}
}
);
injected->forEachSourceLocation(
[&](const StorageSourceLocation& injectedData)
{
std::unordered_map<Id, Id>::const_iterator it;
it = injectedIdToOwnId.find(injectedData.fileNodeId);
if (it == injectedIdToOwnId.end())
{
return;
}
const Id ownFileNodeId = it->second;
const Id ownId = addSourceLocation(
ownFileNodeId,
injectedData.startLine,
injectedData.startCol,
injectedData.endLine,
injectedData.endCol,
injectedData.type
);
if (ownId != 0)
{
injectedIdToOwnId[injectedData.id] = ownId;
}
}
);
injected->forEachOccurrence(
[&](const StorageOccurrence& injectedData)
{
std::unordered_map<Id, Id>::const_iterator it;
it = injectedIdToOwnId.find(injectedData.elementId);
if (it == injectedIdToOwnId.end())
{
return;
}
const Id ownElementId = it->second;
it = injectedIdToOwnId.find(injectedData.sourceLocationId);
if (it == injectedIdToOwnId.end())
{
return;
}
const Id ownSourceLocationId = it->second;
addOccurrence(ownElementId, ownSourceLocationId);
}
);
injected->forEachComponentAccess(
[&](const StorageComponentAccess& injectedData)
{
std::unordered_map<Id, Id>::const_iterator it;
it = injectedIdToOwnId.find(injectedData.nodeId);
if (it == injectedIdToOwnId.end())
{
return;
}
const Id ownNodeId = it->second;
addComponentAccess(ownNodeId, injectedData.type);
}
);
injected->forEachCommentLocation(
[&](const StorageCommentLocation& injectedData)
{
std::unordered_map<Id, Id>::const_iterator it;
it = injectedIdToOwnId.find(injectedData.fileNodeId);
if (it == injectedIdToOwnId.end())
{
return;
}
const Id ownFileNodeId = it->second;
addCommentLocation(
ownFileNodeId,
injectedData.startLine,
injectedData.startCol,
injectedData.endLine,
injectedData.endCol
);
}
);
injected->forEachError(
[&](const StorageError& injectedData)
{
addError(
injectedData.message,
injectedData.filePath,
injectedData.lineNumber,
injectedData.columnNumber,
injectedData.fatal,
injectedData.indexed
);
}
);
finishInjection();
}
void Storage::startInjection()
{
// may be implemented in derived
}
void Storage::finishInjection()
{
// may be implemented in derived
}
+48
View File
@@ -0,0 +1,48 @@
#ifndef STORAGE_H
#define STORAGE_H
#include <functional>
#include <mutex>
#include <string>
#include "data/storage/StorageTypes.h"
#include "utility/types.h"
class Storage
{
public:
Storage();
virtual ~Storage();
virtual Id addNode(int type, const std::string& serializedName) = 0;
virtual void addFile(const Id id, const std::string& filePath, const std::string& modificationTime, bool complete) = 0;
virtual void addSymbol(const Id id, int definitionKind) = 0;
virtual Id addEdge(int type, Id sourceId, Id targetId) = 0;
virtual Id addLocalSymbol(const std::string& name) = 0;
virtual Id addSourceLocation(Id fileNodeId, uint startLine, uint startCol, uint endLine, uint endCol, int type) = 0;
virtual void addOccurrence(Id elementId, Id sourceLocationId) = 0;
virtual void addComponentAccess(Id nodeId , int type) = 0;
virtual void addCommentLocation(Id fileNodeId, uint startLine, uint startCol, uint endLine, uint endCol) = 0;
virtual void addError(const std::string& message, const FilePath& filePath, uint startLine, uint startCol, bool fatal, bool indexed) = 0;
virtual void forEachNode(std::function<void(const StorageNode& /*data*/)> callback) const = 0;
virtual void forEachFile(std::function<void(const StorageFile& /*data*/)> callback) const = 0;
virtual void forEachSymbol(std::function<void(const StorageSymbol& /*data*/)> callback) const = 0;
virtual void forEachEdge(std::function<void(const StorageEdge& /*data*/)> callback) const = 0;
virtual void forEachLocalSymbol(std::function<void(const StorageLocalSymbol& /*data*/)> callback) const = 0;
virtual void forEachSourceLocation(std::function<void(const StorageSourceLocation& /*data*/)> callback) const = 0;
virtual void forEachOccurrence(std::function<void(const StorageOccurrence& /*data*/)> callback) const = 0;
virtual void forEachComponentAccess(std::function<void(const StorageComponentAccess& /*data*/)> callback) const = 0;
virtual void forEachCommentLocation(std::function<void(const StorageCommentLocation& /*data*/)> callback) const = 0;
virtual void forEachError(std::function<void(const StorageError& /*data*/)> callback) const = 0;
void inject(Storage* injected);
private:
virtual void startInjection();
virtual void finishInjection();
std::mutex m_dataMutex;
};
#endif // STORAGE_H
+28
View File
@@ -0,0 +1,28 @@
#include "data/storage/StorageCache.h"
void StorageCache::clear()
{
m_graphForAll.reset();
m_storageStats = StorageStats();
}
std::shared_ptr<Graph> StorageCache::getGraphForAll() const
{
if (!m_graphForAll)
{
m_graphForAll = StorageAccessProxy::getGraphForAll();
}
return m_graphForAll;
}
StorageStats StorageCache::getStorageStats() const
{
if (!m_storageStats.nodeCount)
{
m_storageStats = StorageAccessProxy::getStorageStats();
}
return m_storageStats;
}
+23
View File
@@ -0,0 +1,23 @@
#ifndef STORAGE_CACHE_H
#define STORAGE_CACHE_H
#include <map>
#include "data/access/StorageAccessProxy.h"
class StorageCache
: public StorageAccessProxy
{
public:
void clear();
virtual std::shared_ptr<Graph> getGraphForAll() const;
virtual StorageStats getStorageStats() const;
private:
mutable std::shared_ptr<Graph> m_graphForAll;
mutable StorageStats m_storageStats;
};
#endif // STORAGE_CACHE_H
+72
View File
@@ -0,0 +1,72 @@
#include "data/storage/StorageProvider.h"
#include "utility/logging/logging.h"
int StorageProvider::getStorageCount() const
{
std::lock_guard<std::mutex> lock(m_storagesMutex);
return m_storages.size();
}
void StorageProvider::insert(std::shared_ptr<IntermediateStorage> storage)
{
const std::size_t storageSize = storage->getSourceLocationCount();
std::list<std::shared_ptr<IntermediateStorage>>::iterator it;
std::lock_guard<std::mutex> lock(m_storagesMutex);
for (it = m_storages.begin(); it != m_storages.end(); it++)
{
if ((*it)->getSourceLocationCount() < storageSize)
{
break;
}
}
m_storages.insert(it, storage);
}
std::shared_ptr<IntermediateStorage> StorageProvider::consumeSecondLargestStorage()
{
std::shared_ptr<IntermediateStorage> ret;
{
std::lock_guard<std::mutex> lock(m_storagesMutex);
if (m_storages.size() > 1)
{
std::list<std::shared_ptr<IntermediateStorage>>::iterator it = m_storages.begin();
it++;
ret = *it;
m_storages.erase(it);
}
}
return ret;
}
std::shared_ptr<IntermediateStorage> StorageProvider::consumeLargestStorage()
{
std::shared_ptr<IntermediateStorage> ret;
{
std::lock_guard<std::mutex> lock(m_storagesMutex);
if (!m_storages.empty())
{
ret = m_storages.front();
m_storages.pop_front();
}
}
return ret;
}
void StorageProvider::logCurrentState() const
{
std::string logString = "Storages waiting for injection:";
{
std::lock_guard<std::mutex> lock(m_storagesMutex);
for (std::shared_ptr<IntermediateStorage> storage: m_storages)
{
logString += " " + std::to_string(storage->getSourceLocationCount()) + ";";
}
}
LOG_INFO(logString);
}
+29
View File
@@ -0,0 +1,29 @@
#ifndef STORAGE_PROVIDER_H
#define STORAGE_PROVIDER_H
#include <memory>
#include <mutex>
#include <list>
#include "data/storage/IntermediateStorage.h"
class StorageProvider
{
public:
int getStorageCount() const;
void insert(std::shared_ptr<IntermediateStorage> storage);
// returns empty shared_ptr if no storages available
std::shared_ptr<IntermediateStorage> consumeSecondLargestStorage();
// returns empty shared_ptr if no storages available
std::shared_ptr<IntermediateStorage> consumeLargestStorage();
void logCurrentState() const;
private:
std::list<std::shared_ptr<IntermediateStorage>> m_storages; // larger storages are in front
mutable std::mutex m_storagesMutex;
};
#endif // STORAGE_PROVIDER_H
+26
View File
@@ -0,0 +1,26 @@
#ifndef STORAGE_STATS_H
#define STORAGE_STATS_H
#include "utility/TimePoint.h"
struct StorageStats
{
StorageStats()
: nodeCount(0)
, edgeCount(0)
, fileCount(0)
, completedFileCount(0)
, fileLOCCount(0)
{}
size_t nodeCount;
size_t edgeCount;
size_t fileCount;
size_t completedFileCount;
size_t fileLOCCount;
TimePoint timestamp;
};
#endif // STORAGE_STATS_H
+349
View File
@@ -0,0 +1,349 @@
#ifndef STORAGE_TYPES_H
#define STORAGE_TYPES_H
#include <string>
#include "utility/file/FilePath.h"
#include "utility/types.h"
#include "data/DefinitionKind.h"
struct StorageEdge
{
StorageEdge()
: id(0)
, type(0)
, sourceNodeId(0)
, targetNodeId(0)
{}
StorageEdge(Id id, int type, Id sourceNodeId, Id targetNodeId)
: id(id)
, type(type)
, sourceNodeId(sourceNodeId)
, targetNodeId(targetNodeId)
{}
Id id;
int type;
Id sourceNodeId;
Id targetNodeId;
};
struct StorageNode
{
StorageNode()
: id(0)
, type(0)
, serializedName("")
{}
StorageNode(Id id, int type, const std::string& serializedName)
: id(id)
, type(type)
, serializedName(serializedName)
{}
Id id;
int type;
std::string serializedName;
};
struct StorageSymbol
{
StorageSymbol()
: id(0)
, definitionKind(definitionKindToInt(DEFINITION_NONE))
{}
StorageSymbol(Id id, int definitionKind)
: id(id)
, definitionKind(definitionKind)
{}
Id id;
int definitionKind;
};
struct StorageFile
{
StorageFile()
: id(0)
, filePath("")
, modificationTime("")
, complete(true)
{}
StorageFile(Id id, const std::string& filePath, const std::string& modificationTime, bool complete)
: id(id)
, filePath(filePath)
, modificationTime(modificationTime)
, complete(complete)
{}
Id id;
std::string filePath;
std::string modificationTime;
bool complete;
};
struct StorageLocalSymbol
{
StorageLocalSymbol()
: id(0)
, name("")
{}
StorageLocalSymbol(Id id, const std::string& name)
: id(id)
, name(name)
{}
Id id;
std::string name;
};
struct StorageSourceLocation
{
StorageSourceLocation()
: id(0)
, fileNodeId(0)
, startLine(-1)
, startCol(-1)
, endLine(-1)
, endCol(-1)
, type(0)
{}
StorageSourceLocation(Id id, Id fileNodeId, uint startLine, uint startCol, uint endLine, uint endCol, int type)
: id(id)
, fileNodeId(fileNodeId)
, startLine(startLine)
, startCol(startCol)
, endLine(endLine)
, endCol(endCol)
, type(type)
{}
Id id;
Id fileNodeId;
uint startLine;
uint startCol;
uint endLine;
uint endCol;
int type;
};
struct StorageOccurrence
{
StorageOccurrence()
: elementId(0)
, sourceLocationId(0)
{}
StorageOccurrence(Id elementId, Id sourceLocationId)
: elementId(elementId)
, sourceLocationId(sourceLocationId)
{}
Id elementId;
Id sourceLocationId;
};
struct StorageComponentAccess
{
StorageComponentAccess()
: id(0)
, nodeId(0)
, type(0)
{}
StorageComponentAccess(Id id, Id nodeId, int type)
: id(id)
, nodeId(nodeId)
, type(type)
{}
Id id;
Id nodeId;
int type;
};
struct StorageCommentLocation
{
StorageCommentLocation()
: id(0)
, fileNodeId(0)
, startLine(-1)
, startCol(-1)
, endLine(-1)
, endCol(-1)
{}
StorageCommentLocation(Id id, Id fileNodeId, uint startLine, uint startCol, uint endLine, uint endCol)
: id(id)
, fileNodeId(fileNodeId)
, startLine(startLine)
, startCol(startCol)
, endLine(endLine)
, endCol(endCol)
{}
Id id;
Id fileNodeId;
uint startLine;
uint startCol;
uint endLine;
uint endCol;
};
struct StorageError
{
StorageError()
: id(0)
, message("")
, lineNumber(-1)
, columnNumber(-1)
, fatal(0)
, indexed(0)
{}
StorageError(
Id id,
const std::string& message,
const FilePath& filePath,
uint lineNumber,
uint columnNumber,
bool fatal,
bool indexed
)
: id(id)
, message(message)
, filePath(filePath)
, lineNumber(lineNumber)
, columnNumber(columnNumber)
, fatal(fatal)
, indexed(indexed)
{}
Id id;
std::string message;
FilePath filePath;
uint lineNumber;
uint columnNumber;
bool fatal;
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
@@ -0,0 +1,10 @@
#include "data/storage/migration/SqliteStorageMigration.h"
SqliteStorageMigration::~SqliteStorageMigration()
{
}
bool SqliteStorageMigration::executeStatementInStorage(SqliteStorage* storage, const std::string& statement) const
{
return storage->executeStatement(statement);
}
@@ -0,0 +1,18 @@
#ifndef SQLITE_STORAGE_MIGRATION_H
#define SQLITE_STORAGE_MIGRATION_H
#include <string>
#include <vector>
#include "data/storage/sqlite/SqliteStorage.h"
#include "utility/migration/Migration.h"
class SqliteStorageMigration: public Migration<SqliteStorage>
{
public:
virtual ~SqliteStorageMigration();
bool executeStatementInStorage(SqliteStorage* storage, const std::string& statement) const;
};
#endif // SQLITE_STORAGE_MIGRATION_H
@@ -0,0 +1,16 @@
#include "data/storage/migration/SqliteStorageMigrationLambda.h"
SqliteStorageMigrationLambda::SqliteStorageMigrationLambda(std::function<void(const SqliteStorageMigration*, SqliteStorage*)> m_lambda)
: m_lambda(m_lambda)
{
}
SqliteStorageMigrationLambda::~SqliteStorageMigrationLambda()
{
}
void SqliteStorageMigrationLambda::apply(SqliteStorage* migratable) const
{
m_lambda(this, migratable);
}
@@ -0,0 +1,19 @@
#ifndef SQLITE_STORAGE_MIGRATION_LAMBDA_H
#define SQLITE_STORAGE_MIGRATION_LAMBDA_H
#include <functional>
#include "data/storage/migration/SqliteStorageMigration.h"
class SqliteStorageMigrationLambda: public SqliteStorageMigration
{
public:
SqliteStorageMigrationLambda(std::function<void(const SqliteStorageMigration*, SqliteStorage*)> m_lambda);
virtual ~SqliteStorageMigrationLambda();
virtual void apply(SqliteStorage* migratable) const;
private:
std::function<void(const SqliteStorageMigration*, SqliteStorage*)> m_lambda;
};
#endif // SQLITE_STORAGE_MIGRATION_LAMBDA_H
@@ -0,0 +1,10 @@
#ifndef SQLITE_STORAGE_MIGRATOR_H
#define SQLITE_STORAGE_MIGRATOR_H
#include "utility/migration/Migrator.h"
class SqliteStorage;
typedef Migrator<SqliteStorage> SqliteStorageMigrator;
#endif // SQLITE_STORAGE_MIGRATOR_H
@@ -0,0 +1,357 @@
#include "data/storage/sqlite/SqliteBookmarkStorage.h"
#include "data/storage/migration/SqliteStorageMigrationLambda.h"
#include "data/storage/migration/SqliteStorageMigrator.h"
#include "settings/ProjectSettings.h"
#include "utility/logging/logging.h"
#include "Application.h"
const size_t SqliteBookmarkStorage::s_storageVersion = 2;
SqliteBookmarkStorage::SqliteBookmarkStorage(const FilePath& dbFilePath)
: SqliteStorage(dbFilePath)
{
}
SqliteBookmarkStorage::~SqliteBookmarkStorage()
{
}
size_t SqliteBookmarkStorage::getStaticVersion() const
{
return s_storageVersion;
}
void SqliteBookmarkStorage::migrateIfNecessary()
{
SqliteStorageMigrator migrator;
migrator.addMigration(2, std::make_shared<SqliteStorageMigrationLambda>([](const SqliteStorageMigration* migration, SqliteStorage* storage){
std::string separator = "::";
if (std::shared_ptr<Project> currentProject = Application::getInstance()->getCurrentProject())
{
LanguageType currentLanguage = ProjectSettings::getLanguageOfProject(currentProject->getProjectSettingsFilePath());
if (currentLanguage == LANGUAGE_JAVA)
{
separator = ".";
}
}
migration->executeStatementInStorage(storage, "UPDATE bookmarked_node SET serialized_node_name = '" + separator + "\tm' || serialized_node_name");
migration->executeStatementInStorage(storage, "UPDATE bookmarked_edge SET serialized_source_node_name = '" + separator + "\tm' || serialized_source_node_name");
migration->executeStatementInStorage(storage, "UPDATE bookmarked_edge SET serialized_target_node_name = '" + separator + "\tm' || serialized_target_node_name");
}));
migrator.migrate(this, SqliteBookmarkStorage::s_storageVersion);
}
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<StorageBookmark> SqliteBookmarkStorage::getAllBookmarks() const
{
return doGetAll<StorageBookmark>("");
}
void SqliteBookmarkStorage::removeBookmark(const Id id)
{
executeStatement(
"DELETE FROM bookmark WHERE id = (" + std::to_string(id) + ");"
);
}
std::vector<StorageBookmarkedNode> SqliteBookmarkStorage::getAllBookmarkedNodes() const
{
return doGetAll<StorageBookmarkedNode>("");
}
std::vector<StorageBookmarkedEdge> SqliteBookmarkStorage::getAllBookmarkedEdges() const
{
return doGetAll<StorageBookmarkedEdge>("");
}
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<StorageBookmarkCategory> SqliteBookmarkStorage::getAllBookmarkCategories() const
{
return doGetAll<StorageBookmarkCategory>("");
}
StorageBookmarkCategory SqliteBookmarkStorage::getBookmarkCategoryByName(const std::string& name) const
{
return doGetFirst<StorageBookmarkCategory>("WHERE name == '" + name + "'");
}
void SqliteBookmarkStorage::removeBookmarkCategory(Id id)
{
executeStatement(
"DELETE FROM bookmark_category WHERE id = (" + std::to_string(id) + ");"
);
}
std::vector<std::pair<int, SqliteDatabaseIndex>> SqliteBookmarkStorage::getIndices() const
{
return std::vector<std::pair<int, SqliteDatabaseIndex>>();
}
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;
}
}
void SqliteBookmarkStorage::setupPrecompiledStatements()
{
}
template <>
std::vector<StorageBookmarkCategory> SqliteBookmarkStorage::doGetAll<StorageBookmarkCategory>(const std::string& query) const
{
CppSQLite3Query q = executeQuery(
"SELECT id, name FROM bookmark_category " + query + ";"
);
std::vector<StorageBookmarkCategory> 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<StorageBookmark> SqliteBookmarkStorage::doGetAll<StorageBookmark>(const std::string& query) const
{
CppSQLite3Query q = executeQuery(
"SELECT id, name, comment, timestamp, category_id FROM bookmark " + query + ";"
);
std::vector<StorageBookmark> 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<StorageBookmarkedNode> SqliteBookmarkStorage::doGetAll<StorageBookmarkedNode>(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<StorageBookmarkedNode> 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<StorageBookmarkedEdge> SqliteBookmarkStorage::doGetAll<StorageBookmarkedEdge>(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<StorageBookmarkedEdge> 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;
}
@@ -0,0 +1,70 @@
#ifndef SQLITE_BOOKMARK_STORAGE_H
#define SQLITE_BOOKMARK_STORAGE_H
#include "data/storage/sqlite/SqliteStorage.h"
#include "data/storage/StorageTypes.h"
#include "utility/types.h"
class SqliteBookmarkStorage
: public SqliteStorage
{
public:
SqliteBookmarkStorage(const FilePath& dbFilePath);
virtual ~SqliteBookmarkStorage();
virtual size_t getStaticVersion() const;
void migrateIfNecessary();
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<StorageBookmark> getAllBookmarks() const;
std::vector<StorageBookmarkedNode> getAllBookmarkedNodes() const;
std::vector<StorageBookmarkedEdge> getAllBookmarkedEdges() const;
void updateBookmark(const Id bookmarkId, const std::string& name, const std::string& comment, const Id categoryId);
std::vector<StorageBookmarkCategory> getAllBookmarkCategories() const;
StorageBookmarkCategory getBookmarkCategoryByName(const std::string& name) const;
private:
static const size_t s_storageVersion;
virtual std::vector<std::pair<int, SqliteDatabaseIndex>> getIndices() const;
virtual void clearTables();
virtual void setupTables();
virtual void setupPrecompiledStatements();
//void updateBookmarkMetaData(const BookmarkMetaData& metaData);
template <typename ResultType>
std::vector<ResultType> doGetAll(const std::string& query) const;
template <typename ResultType>
ResultType doGetFirst(const std::string& query) const
{
std::vector<ResultType> results = doGetAll<ResultType>(query + " LIMIT 1");
if (results.size() > 0)
{
return results[0];
}
return ResultType();
}
};
template <>
std::vector<StorageBookmarkCategory> SqliteBookmarkStorage::doGetAll<StorageBookmarkCategory>(const std::string& query) const;
template <>
std::vector<StorageBookmark> SqliteBookmarkStorage::doGetAll<StorageBookmark>(const std::string& query) const;
template <>
std::vector<StorageBookmarkedNode> SqliteBookmarkStorage::doGetAll<StorageBookmarkedNode>(const std::string& query) const;
template <>
std::vector<StorageBookmarkedEdge> SqliteBookmarkStorage::doGetAll<StorageBookmarkedEdge>(const std::string& query) const;
#endif // SQLITE_BOOKMARK_STORAGE_H
@@ -0,0 +1,43 @@
#include "data/storage/sqlite/SqliteDatabaseIndex.h"
#include "utility/logging/logging.h"
SqliteDatabaseIndex::SqliteDatabaseIndex(const std::string& indexName, const std::string& indexTarget)
: m_indexName(indexName)
, m_indexTarget(indexTarget)
{
}
SqliteDatabaseIndex::~SqliteDatabaseIndex()
{
}
void SqliteDatabaseIndex::createOnDatabase(CppSQLite3DB& database)
{
try
{
LOG_INFO_STREAM(<< "Creating database index \"" << m_indexName << "\"");
database.execDML((
"CREATE INDEX IF NOT EXISTS " + m_indexName + " ON " + m_indexTarget + ";"
).c_str());
}
catch (CppSQLite3Exception e)
{
LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage());
}
}
void SqliteDatabaseIndex::removeFromDatabase(CppSQLite3DB& database)
{
try
{
LOG_INFO_STREAM(<< "Removing database index \"" << m_indexName << "\"");
database.execDML((
"DROP INDEX IF EXISTS main." + m_indexName + ";"
).c_str());
}
catch (CppSQLite3Exception e)
{
LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage());
}
}
@@ -0,0 +1,21 @@
#ifndef SQLITE_DATABASE_INDEX_H
#define SQLITE_DATABASE_INDEX_H
#include <string>
#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
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,188 @@
#ifndef SQLITE_INDEX_STORAGE_H
#define SQLITE_INDEX_STORAGE_H
#include <memory>
#include <string>
#include <vector>
#include "data/location/SourceLocationFile.h"
#include "data/storage/sqlite/SqliteDatabaseIndex.h"
#include "data/storage/sqlite/SqliteStorage.h"
#include "data/storage/StorageTypes.h"
#include "utility/types.h"
#include "utility/utility.h"
#include "utility/utilityString.h"
class TextAccess;
class Version;
struct ParseLocation;
class SqliteIndexStorage
: public SqliteStorage
{
public:
SqliteIndexStorage(const FilePath& dbFilePath);
virtual ~SqliteIndexStorage();
virtual size_t getStaticVersion() const;
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<Id>& ids);
void removeElementsWithLocationInFiles(const std::vector<Id>& fileIds, std::function<void(int)> updateStatusCallback);
void removeErrorsInFiles(const std::vector<FilePath>& 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<StorageEdge> getEdgesBySourceId(Id sourceId) const;
std::vector<StorageEdge> getEdgesBySourceIds(const std::vector<Id>& sourceIds) const;
std::vector<StorageEdge> getEdgesByTargetId(Id targetId) const;
std::vector<StorageEdge> getEdgesByTargetIds(const std::vector<Id>& targetIds) const;
std::vector<StorageEdge> getEdgesBySourceOrTargetId(Id id) const;
std::vector<StorageEdge> getEdgesByType(int type) const;
std::vector<StorageEdge> getEdgesBySourceType(Id sourceId, int type) const;
std::vector<StorageEdge> getEdgesBySourcesType(const std::vector<Id>& sourceIds, int type) const;
std::vector<StorageEdge> getEdgesByTargetType(Id targetId, int type) const;
std::vector<StorageEdge> getEdgesByTargetsType(const std::vector<Id>& targetIds, int type) const;
StorageNode getNodeById(Id id) const;
StorageNode getNodeBySerializedName(const std::string& serializedName) const;
StorageLocalSymbol getLocalSymbolByName(const std::string& name) const;
StorageFile getFileByPath(const std::string& filePath) const;
std::vector<StorageFile> getFilesByPaths(const std::vector<FilePath>& filePaths) const;
std::shared_ptr<TextAccess> getFileContentByPath(const std::string& filePath) const;
std::shared_ptr<TextAccess> getFileContentById(Id fileId) const;
void setFileComplete(bool complete, Id fileId);
void setNodeType(int type, Id nodeId);
std::shared_ptr<SourceLocationFile> getSourceLocationsForFile(const FilePath& filePath) const;
std::vector<StorageOccurrence> getOccurrencesForLocationId(Id locationId) const;
std::vector<StorageOccurrence> getOccurrencesForLocationIds(const std::vector<Id>& locationIds) const;
std::vector<StorageOccurrence> getOccurrencesForElementIds(const std::vector<Id>& elementIds) const;
StorageComponentAccess getComponentAccessByNodeId(Id memberEdgeId) const;
std::vector<StorageComponentAccess> getComponentAccessesByNodeIds(const std::vector<Id>& memberEdgeIds) const;
std::vector<StorageCommentLocation> getCommentLocationsInFile(const FilePath& filePath) const;
template <typename ResultType>
std::vector<ResultType> getAll() const
{
return doGetAll<ResultType>("");
}
template <typename ResultType>
ResultType getFirstById(const Id id) const
{
if (id != 0)
{
return doGetFirst<ResultType>("WHERE id == " + std::to_string(id));
}
return ResultType();
}
template <typename ResultType>
std::vector<ResultType> getAllByIds(const std::vector<Id>& ids) const
{
if (ids.size())
{
return doGetAll<ResultType>("WHERE id IN (" + utility::join(utility::toStrings(ids), ',') + ")");
}
return std::vector<ResultType>();
}
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 std::vector<std::pair<int, SqliteDatabaseIndex>> getIndices() const;
virtual void clearTables();
virtual void setupTables();
virtual void setupPrecompiledStatements();
template <typename ResultType>
std::vector<ResultType> doGetAll(const std::string& query) const;
template <typename ResultType>
ResultType doGetFirst(const std::string& query) const
{
std::vector<ResultType> results = doGetAll<ResultType>(query + " LIMIT 1");
if (results.size() > 0)
{
return results[0];
}
return ResultType();
}
CppSQLite3Statement m_insertElementStmt;
CppSQLite3Statement m_insertEdgeStmt;
CppSQLite3Statement m_inserNodeStmt;
CppSQLite3Statement m_insertSymbolStmt;
CppSQLite3Statement m_insertFileStmt;
CppSQLite3Statement m_insertFileContentStmt;
CppSQLite3Statement m_inserLocalSymbolStmt;
CppSQLite3Statement m_checkSourceLocationExistsStmt;
CppSQLite3Statement m_insertSourceLocationStmt;
CppSQLite3Statement m_checkOccurrenceExistsStmt;
CppSQLite3Statement m_insertOccurrenceStmt;
CppSQLite3Statement m_insertComponentAccessStmt;
CppSQLite3Statement m_checkCommentLocationExistsStmt;
CppSQLite3Statement m_insertCommentLocationStmt;
CppSQLite3Statement m_checkErrorExistsStmt;
CppSQLite3Statement m_insertErrorStmt;
};
template <>
std::vector<StorageEdge> SqliteIndexStorage::doGetAll<StorageEdge>(const std::string& query) const;
template <>
std::vector<StorageNode> SqliteIndexStorage::doGetAll<StorageNode>(const std::string& query) const;
template <>
std::vector<StorageSymbol> SqliteIndexStorage::doGetAll<StorageSymbol>(const std::string& query) const;
template <>
std::vector<StorageFile> SqliteIndexStorage::doGetAll<StorageFile>(const std::string& query) const;
template <>
std::vector<StorageLocalSymbol> SqliteIndexStorage::doGetAll<StorageLocalSymbol>(const std::string& query) const;
template <>
std::vector<StorageSourceLocation> SqliteIndexStorage::doGetAll<StorageSourceLocation>(const std::string& query) const;
template <>
std::vector<StorageOccurrence> SqliteIndexStorage::doGetAll<StorageOccurrence>(const std::string& query) const;
template <>
std::vector<StorageComponentAccess> SqliteIndexStorage::doGetAll<StorageComponentAccess>(const std::string& query) const;
template <>
std::vector<StorageCommentLocation> SqliteIndexStorage::doGetAll<StorageCommentLocation>(const std::string& query) const;
template <>
std::vector<StorageError> SqliteIndexStorage::doGetAll<StorageError>(const std::string& query) const;
#endif // SQLITE_INDEX_STORAGE_H
@@ -0,0 +1,305 @@
#include "data/storage/sqlite/SqliteStorage.h"
#include "utility/logging/logging.h"
#include "utility/TimePoint.h"
SqliteStorage::SqliteStorage(const FilePath& dbFilePath)
: m_dbFilePath(dbFilePath.canonical())
{
m_database.open(m_dbFilePath.str().c_str());
executeStatement("PRAGMA foreign_keys=ON;");
m_mode = STORAGE_MODE_UNKNOWN;
}
SqliteStorage::~SqliteStorage()
{
try
{
m_database.close();
}
catch (CppSQLite3Exception e)
{
LOG_ERROR(e.errorMessage());
}
}
void SqliteStorage::setup()
{
m_indices = getIndices();
executeStatement("PRAGMA foreign_keys=ON;");
setupMetaTable();
setupTables();
setupPrecompiledStatements();
m_mode = STORAGE_MODE_UNKNOWN;
}
void SqliteStorage::clear()
{
executeStatement("PRAGMA foreign_keys=OFF;");
clearMetaTable();
clearTables();
setup();
}
size_t SqliteStorage::getVersion() const
{
std::string storageVersionStr = getMetaValue("storage_version");
if (storageVersionStr.size())
{
return std::stoi(storageVersionStr);
}
return 0;
}
void SqliteStorage::setVersion(size_t version)
{
insertOrUpdateMetaValue("storage_version", std::to_string(version));
}
void SqliteStorage::setMode(const StorageModeType mode)
{
if (mode == m_mode)
{
return;
}
for (size_t i = 0; i < m_indices.size(); i++)
{
if (m_indices[i].first & mode)
{
m_indices[i].second.createOnDatabase(m_database);
}
else
{
m_indices[i].second.removeFromDatabase(m_database);
}
}
m_mode = mode;
}
void SqliteStorage::beginTransaction()
{
executeStatement("BEGIN TRANSACTION;");
}
void SqliteStorage::commitTransaction()
{
executeStatement("COMMIT TRANSACTION;");
}
void SqliteStorage::rollbackTransaction()
{
executeStatement("ROLLBACK TRANSACTION;");
}
void SqliteStorage::optimizeMemory() const
{
executeStatement("VACUUM;");
}
FilePath SqliteStorage::getDbFilePath() const
{
return m_dbFilePath;
}
bool SqliteStorage::isEmpty() const
{
return getVersion() <= 0;
}
bool SqliteStorage::isIncompatible() const
{
size_t storageVersion = getVersion();
if (isEmpty() || storageVersion != getStaticVersion())
{
return true;
}
return false;
}
void SqliteStorage::setTime()
{
insertOrUpdateMetaValue("timestamp", TimePoint::now().toString());
}
TimePoint SqliteStorage::getTime() const
{
return TimePoint(getMetaValue("timestamp"));
}
void SqliteStorage::setupMetaTable()
{
try
{
m_database.execDML(
"CREATE TABLE IF NOT EXISTS meta("
"id INTEGER, "
"key TEXT, "
"value TEXT, "
"PRIMARY KEY(id)"
");"
);
}
catch (CppSQLite3Exception& e)
{
LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage());
throw(std::exception());
}
}
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());
}
}
bool SqliteStorage::executeStatement(const std::string& statement) const
{
try
{
m_database.execDML(statement.c_str());
}
catch (CppSQLite3Exception e)
{
LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage());
return false;
}
return true;
}
bool SqliteStorage::executeStatement(CppSQLite3Statement& statement) const
{
try
{
statement.execDML();
}
catch (CppSQLite3Exception e)
{
LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage());
return false;
}
return true;
}
int SqliteStorage::executeStatementScalar(const std::string& statement, const int nullValue) const
{
int ret = 0;
try
{
ret = m_database.execScalar(statement.c_str(), nullValue);
}
catch (CppSQLite3Exception e)
{
LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage());
}
return ret;
}
int SqliteStorage::executeStatementScalar(CppSQLite3Statement& statement, const int nullValue) const
{
int ret = 0;
try
{
CppSQLite3Query q = executeQuery(statement);
if (q.eof() || q.numFields() < 1)
{
throw CppSQLite3Exception(
CPPSQLITE_ERROR,
"Invalid scalar query",
false
);
}
ret = q.getIntField(0, nullValue);
}
catch (CppSQLite3Exception e)
{
LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage());
}
return ret;
}
CppSQLite3Query SqliteStorage::executeQuery(const std::string& statement) const
{
try
{
return m_database.execQuery(statement.c_str());
}
catch (CppSQLite3Exception e)
{
LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage());
}
return CppSQLite3Query();
}
CppSQLite3Query SqliteStorage::executeQuery(CppSQLite3Statement& statement) const
{
try
{
return statement.execQuery();
}
catch (CppSQLite3Exception e)
{
LOG_ERROR(std::to_string(e.errorCode()) + ": " + e.errorMessage());
}
return CppSQLite3Query();
}
bool SqliteStorage::hasTable(const std::string& tableName) const
{
CppSQLite3Query q = executeQuery(
"SELECT name FROM sqlite_master WHERE type='table' AND name='" + tableName + "';"
);
if (!q.eof())
{
return q.getStringField(0, "") == tableName;
}
return false;
}
std::string SqliteStorage::getMetaValue(const std::string& key) const
{
if (hasTable("meta"))
{
CppSQLite3Query q = executeQuery("SELECT value FROM meta WHERE key = '" + key + "';");
if (!q.eof())
{
return q.getStringField(0, "");
}
}
return "";
}
void SqliteStorage::insertOrUpdateMetaValue(const std::string& key, const std::string& value)
{
CppSQLite3Statement stmt = m_database.compileStatement(std::string(
"INSERT OR REPLACE INTO meta(id, key, value) VALUES("
"(SELECT id FROM meta WHERE key = ?), ?, ?"
");"
).c_str());
stmt.bind(1, key.c_str());
stmt.bind(2, key.c_str());
stmt.bind(3, value.c_str());
executeStatement(stmt);
}
@@ -0,0 +1,81 @@
#ifndef SQLITE_STORAGE_H
#define SQLITE_STORAGE_H
#include "sqlite/CppSQLite3.h"
#include "data/storage/sqlite/SqliteDatabaseIndex.h"
#include "utility/file/FilePath.h"
class SqliteStorageMigration;
class TimePoint;
class SqliteStorage
{
public:
enum StorageModeType
{
STORAGE_MODE_UNKNOWN = 0,
STORAGE_MODE_READ = 1,
STORAGE_MODE_WRITE = 2,
STORAGE_MODE_CLEAR = 4,
};
SqliteStorage(const FilePath& dbFilePath);
virtual ~SqliteStorage();
void setup();
void clear();
size_t getVersion() const;
void setVersion(size_t version);
void setMode(const StorageModeType mode);
void beginTransaction();
void commitTransaction();
void rollbackTransaction();
void optimizeMemory() const;
FilePath getDbFilePath() const;
bool isEmpty() const;
bool isIncompatible() const;
void setTime();
TimePoint getTime() const;
protected:
void setupMetaTable();
void clearMetaTable();
bool executeStatement(const std::string& statement) const;
bool executeStatement(CppSQLite3Statement& statement) const;
int executeStatementScalar(const std::string& statement, const int nullValue) const;
int executeStatementScalar(CppSQLite3Statement& statement, const int nullValue) const;
CppSQLite3Query executeQuery(const std::string& statement) const;
CppSQLite3Query executeQuery(CppSQLite3Statement& statement) const;
bool hasTable(const std::string& tableName) const;
std::string getMetaValue(const std::string& key) const;
void insertOrUpdateMetaValue(const std::string& key, const std::string& value);
mutable CppSQLite3DB m_database;
FilePath m_dbFilePath;
StorageModeType m_mode;
private:
virtual size_t getStaticVersion() const = 0;
virtual std::vector<std::pair<int, SqliteDatabaseIndex>> getIndices() const = 0;
virtual void clearTables() = 0;
virtual void setupTables() = 0;
virtual void setupPrecompiledStatements() = 0;
std::vector<std::pair<int, SqliteDatabaseIndex>> m_indices;
friend SqliteStorageMigration;
};
#endif // SQLITE_STORAGE_H