Files
SourcetrailDB/core/src/DatabaseStorage.cpp
T
2021-01-25 20:31:45 +01:00

911 lines
25 KiB
C++

/*
* Copyright 2018 Coati Software KG
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "DatabaseStorage.h"
#include <vector>
#include "NodeKind.h"
#include "SourcetrailException.h"
#include "StorageFile.h"
#include "StorageNode.h"
#include "StorageSymbol.h"
#include "utility.h"
#include "version.h"
namespace sourcetrail
{
// --- Public Interface ---
int DatabaseStorage::getSupportedDatabaseVersion()
{
return DATABASE_VERSION;
}
std::unique_ptr<DatabaseStorage> DatabaseStorage::openDatabase(const std::string& dbFilePath)
{
try
{
std::unique_ptr<DatabaseStorage> storage = std::unique_ptr<DatabaseStorage>(new DatabaseStorage());
storage->m_database.open(dbFilePath.c_str());
storage->executeStatement("PRAGMA foreign_keys=ON;");
return std::move(storage);
}
catch (CppSQLite3Exception e)
{
throw SourcetrailException(e.errorMessage());
}
}
DatabaseStorage::~DatabaseStorage()
{
clearPrecompiledStatements();
m_database.close();
}
void DatabaseStorage::setupDatabase()
{
executeStatement("PRAGMA foreign_keys=ON;");
if (!isCompatible())
{
throw SourcetrailException("Unable to setup database tables because database is not compatible.");
}
setupTables();
setupIndices();
setupPrecompiledStatements();
insertOrUpdateMetaValue("storage_version", std::to_string(getSupportedDatabaseVersion()));
}
void DatabaseStorage::clearDatabase()
{
executeStatement("PRAGMA foreign_keys=OFF;");
clearPrecompiledStatements();
clearTables();
setupDatabase();
}
void DatabaseStorage::setProjectSettingsText(const std::string& text)
{
insertOrUpdateMetaValue("project_settings", text);
}
bool DatabaseStorage::isEmpty() const
{
const std::string tableName = "meta";
CppSQLite3Query q = executeQuery("SELECT name FROM sqlite_master WHERE type='table' AND name='" + tableName + "';");
if (!q.eof())
{
return q.getStringField(0, "") == tableName;
}
return true;
}
bool DatabaseStorage::isCompatible() const
{
if (isEmpty())
{
return true;
}
return getLoadedDatabaseVersion() == getSupportedDatabaseVersion();
}
int DatabaseStorage::getLoadedDatabaseVersion() const
{
if (isEmpty())
{
throw SourcetrailException("Unable to determine version of an empty database.");
}
CppSQLite3Query q = executeQuery("SELECT value FROM meta WHERE key = 'storage_version';");
if (!q.eof())
{
return std::stoi(q.getStringField(0, "0"));
}
return 0;
}
void DatabaseStorage::beginTransaction()
{
executeStatement("BEGIN TRANSACTION;");
}
void DatabaseStorage::commitTransaction()
{
executeStatement("COMMIT TRANSACTION;");
}
void DatabaseStorage::rollbackTransaction()
{
executeStatement("ROLLBACK TRANSACTION;");
}
void DatabaseStorage::optimizeDatabaseMemory()
{
executeStatement("VACUUM;");
}
int DatabaseStorage::addElementComponent(const StorageElementComponentData& storageElementComponentData)
{
m_insertElementComponentStatement.bind(1, storageElementComponentData.elementId);
m_insertElementComponentStatement.bind(2, storageElementComponentData.componentKind);
m_insertElementComponentStatement.bind(3, storageElementComponentData.data.c_str());
executeStatement(m_insertElementComponentStatement);
const int id = static_cast<int>(m_database.lastRowId());
m_insertElementComponentStatement.reset();
return id;
}
int DatabaseStorage::addNode(const StorageNodeData& storageNodeData)
{
int id = 0;
{
m_findNodeStatement.bind(1, storageNodeData.serializedName.c_str());
CppSQLite3Query q = executeQuery(m_findNodeStatement);
if (!q.eof())
{
id = q.getIntField(0, 0);
}
m_findNodeStatement.reset();
}
// FIXME: update node nodeKind here
if (id == 0)
{
id = insertElement();
m_insertNodeStatement.bind(1, id);
m_insertNodeStatement.bind(2, storageNodeData.nodeKind);
m_insertNodeStatement.bind(3, storageNodeData.serializedName.c_str());
executeStatement(m_insertNodeStatement);
m_insertNodeStatement.reset();
}
return id;
}
void DatabaseStorage::addSymbol(const StorageSymbol& storageSymbol)
{
m_insertSymbolStatement.bind(1, storageSymbol.id);
m_insertSymbolStatement.bind(2, storageSymbol.definitionKind);
executeStatement(m_insertSymbolStatement);
m_insertSymbolStatement.reset();
}
void DatabaseStorage::addFile(const StorageFile& storageFile)
{
{
m_findFileStatement.bind(1, storageFile.id);
CppSQLite3Query q = executeQuery(m_findFileStatement);
bool exists = !q.eof();
m_findFileStatement.reset();
if (exists)
{
return;
}
}
std::string content = "";
if (utility::getFileExists(storageFile.filePath))
{
content = utility::getFileContent(storageFile.filePath);
}
const int lineCount = utility::getLineCount(content);
{
m_insertFileStatement.bind(1, storageFile.id);
m_insertFileStatement.bind(2, storageFile.filePath.c_str());
m_insertFileStatement.bind(3, storageFile.languageIdentifier.c_str());
m_insertFileStatement.bind(4, storageFile.modificationTime.c_str());
m_insertFileStatement.bind(5, storageFile.indexed);
m_insertFileStatement.bind(6, storageFile.complete);
m_insertFileStatement.bind(7, lineCount);
executeStatement(m_insertFileStatement);
m_insertFileStatement.reset();
}
if (!content.empty())
{
m_insertFileContentStatement.bind(1, storageFile.id);
m_insertFileContentStatement.bind(2, content.c_str());
executeStatement(m_insertFileContentStatement);
m_insertFileContentStatement.reset();
}
}
int DatabaseStorage::addEdge(const StorageEdgeData& storageEdgeData)
{
int id = 0;
{
m_findEdgeStatement.bind(1, storageEdgeData.sourceNodeId);
m_findEdgeStatement.bind(2, storageEdgeData.targetNodeId);
m_findEdgeStatement.bind(3, storageEdgeData.edgeKind);
CppSQLite3Query q = executeQuery(m_findEdgeStatement);
if (!q.eof())
{
id = q.getIntField(0, 0);
}
m_findEdgeStatement.reset();
}
if (id == 0)
{
id = insertElement();
m_insertEdgeStatement.bind(1, id);
m_insertEdgeStatement.bind(2, storageEdgeData.edgeKind);
m_insertEdgeStatement.bind(3, storageEdgeData.sourceNodeId);
m_insertEdgeStatement.bind(4, storageEdgeData.targetNodeId);
executeStatement(m_insertEdgeStatement);
m_insertEdgeStatement.reset();
}
return id;
}
int DatabaseStorage::addLocalSymbol(const StorageLocalSymbolData& storageLocalSymbolData)
{
int id = 0;
{
m_findLocalSymbolStmt.bind(1, storageLocalSymbolData.name.c_str());
CppSQLite3Query q = executeQuery(m_findLocalSymbolStmt);
if (!q.eof())
{
id = q.getIntField(0, 0);
}
m_findLocalSymbolStmt.reset();
}
if (id == 0)
{
id = insertElement();
m_insertLocalSymbolStmt.bind(1, id);
m_insertLocalSymbolStmt.bind(2, storageLocalSymbolData.name.c_str());
executeStatement(m_insertLocalSymbolStmt);
m_insertLocalSymbolStmt.reset();
}
return id;
}
int DatabaseStorage::addSourceLocation(const StorageSourceLocationData& storageSourceLocationData)
{
int id = 0;
{
m_findSourceLocationStmt.bind(1, storageSourceLocationData.fileNodeId);
m_findSourceLocationStmt.bind(2, storageSourceLocationData.startLineNumber);
m_findSourceLocationStmt.bind(3, storageSourceLocationData.startColumnNumber);
m_findSourceLocationStmt.bind(4, storageSourceLocationData.endLineNumber);
m_findSourceLocationStmt.bind(5, storageSourceLocationData.endColumnNumber);
m_findSourceLocationStmt.bind(6, storageSourceLocationData.locationKind);
CppSQLite3Query q = executeQuery(m_findSourceLocationStmt);
if (!q.eof())
{
id = q.getIntField(0, 0);
}
m_findSourceLocationStmt.reset();
}
if (id == 0)
{
m_insertSourceLocationStmt.bind(1, storageSourceLocationData.fileNodeId);
m_insertSourceLocationStmt.bind(2, storageSourceLocationData.startLineNumber);
m_insertSourceLocationStmt.bind(3, storageSourceLocationData.startColumnNumber);
m_insertSourceLocationStmt.bind(4, storageSourceLocationData.endLineNumber);
m_insertSourceLocationStmt.bind(5, storageSourceLocationData.endColumnNumber);
m_insertSourceLocationStmt.bind(6, storageSourceLocationData.locationKind);
executeStatement(m_insertSourceLocationStmt);
id = static_cast<int>(m_database.lastRowId());
m_insertSourceLocationStmt.reset();
}
return id;
}
void DatabaseStorage::addOccurrence(const StorageOccurrence& storageOccurrence)
{
m_insertOccurenceStmt.bind(1, storageOccurrence.elementId);
m_insertOccurenceStmt.bind(2, storageOccurrence.sourceLocationId);
executeStatement(m_insertOccurenceStmt);
m_insertOccurenceStmt.reset();
}
int DatabaseStorage::addError(const StorageErrorData& storageErrorData)
{
int id = 0;
{
m_findErrorStatement.bind(1, storageErrorData.message.c_str());
m_findErrorStatement.bind(2, storageErrorData.fatal);
CppSQLite3Query q = executeQuery(m_findErrorStatement);
if (!q.eof() && q.numFields() > 0)
{
id = q.getIntField(0, -1);
}
m_findErrorStatement.reset();
}
if (id == 0)
{
id = insertElement();
m_insertErrorStatement.bind(1, id);
m_insertErrorStatement.bind(2, storageErrorData.message.c_str());
m_insertErrorStatement.bind(3, storageErrorData.fatal);
m_insertErrorStatement.bind(4, storageErrorData.indexed);
m_insertErrorStatement.bind(5, storageErrorData.translationUnit.c_str());
executeStatement(m_insertErrorStatement);
id = static_cast<int>(m_database.lastRowId());
m_insertErrorStatement.reset();
}
return id;
}
void DatabaseStorage::setNodeType(int nodeId, int nodeType)
{
m_setNodeTypeStmt.bind(1, nodeType);
m_setNodeTypeStmt.bind(2, nodeId);
executeStatement(m_setNodeTypeStmt);
m_setNodeTypeStmt.reset();
}
void DatabaseStorage::setFileLanguage(int fileId, const std::string& languageIdentifier)
{
m_setFileLanguageStmt.bind(1, languageIdentifier.c_str());
m_setFileLanguageStmt.bind(2, fileId);
executeStatement(m_setFileLanguageStmt);
m_setFileLanguageStmt.reset();
}
// --- Private Interface ---
void DatabaseStorage::setupTables()
{
executeStatement(
"CREATE TABLE IF NOT EXISTS meta("
" id INTEGER, "
" key TEXT, "
" value TEXT, "
" PRIMARY KEY(id)"
");");
executeStatement(
"CREATE TABLE IF NOT EXISTS element("
" id INTEGER, "
" PRIMARY KEY(id)"
");");
executeStatement(
"CREATE TABLE IF NOT EXISTS element_component("
" id INTEGER, "
" element_id INTEGER, "
" type INTEGER, "
" data TEXT, "
" PRIMARY KEY(id), "
" FOREIGN KEY(element_id) REFERENCES element(id) ON DELETE CASCADE"
");");
executeStatement(
"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"
");");
executeStatement(
"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"
");");
executeStatement(
"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"
");");
executeStatement(
"CREATE TABLE IF NOT EXISTS file("
" id INTEGER NOT NULL, "
" path TEXT, "
" language TEXT, "
" modification_time TEXT, "
" indexed INTEGER, "
" complete INTEGER, "
" line_count INTEGER, "
" PRIMARY KEY(id), "
" FOREIGN KEY(id) REFERENCES node(id) ON DELETE CASCADE"
");");
executeStatement(
"CREATE TABLE IF NOT EXISTS filecontent("
" id INTERGER, "
" content TEXT, "
" FOREIGN KEY(id) REFERENCES file(id)"
" ON DELETE CASCADE "
" ON UPDATE CASCADE"
");");
executeStatement(
"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"
");");
executeStatement(
"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"
");");
executeStatement(
"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"
");");
executeStatement(
"CREATE TABLE IF NOT EXISTS component_access("
" node_id INTEGER NOT NULL, "
" type INTEGER NOT NULL, "
" PRIMARY KEY(node_id), "
" FOREIGN KEY(node_id) REFERENCES node(id) ON DELETE CASCADE"
");");
executeStatement(
"CREATE TABLE IF NOT EXISTS error("
" id INTEGER NOT NULL, "
" message TEXT, "
" fatal INTEGER NOT NULL, "
" indexed INTEGER NOT NULL, "
" translation_unit TEXT, "
" PRIMARY KEY(id), "
" FOREIGN KEY(id) REFERENCES element(id) ON DELETE CASCADE"
");");
}
void DatabaseStorage::clearTables()
{
const std::vector<std::string> tableNames = {
"meta",
"error",
"component_access",
"occurrence",
"source_location",
"local_symbol",
"filecontent",
"file",
"symbol",
"node",
"edge",
"element_component"
"element"};
for (const std::string& tableName: tableNames)
{
executeStatement("DROP TABLE IF EXISTS main." + tableName + ";");
}
}
void DatabaseStorage::setupIndices()
{
executeStatement("CREATE INDEX IF NOT EXISTS node_serialized_name_index ON node(serialized_name);");
executeStatement("CREATE INDEX IF NOT EXISTS edge_source_target_type_index ON edge(source_node_id, target_node_id, type);");
executeStatement("CREATE INDEX IF NOT EXISTS local_symbol_name_index ON local_symbol(name);");
executeStatement(
"CREATE INDEX IF NOT EXISTS source_location_all_data_index "
"ON source_location(file_node_id, start_line, start_column, end_line, end_column, type);");
executeStatement("CREATE INDEX IF NOT EXISTS error_all_data_index ON error(message, fatal);");
}
void DatabaseStorage::setupPrecompiledStatements()
{
m_insertElementStatement = compileStatement("INSERT INTO element(id) VALUES(NULL);");
m_insertElementComponentStatement = compileStatement(
"INSERT INTO element_component(id, element_id, type, data) VALUES(NULL, ?, ?, ?);");
m_findNodeStatement = compileStatement("SELECT id FROM node WHERE serialized_name == ? LIMIT 1;");
m_insertNodeStatement = compileStatement("INSERT INTO node(id, type, serialized_name) VALUES(?, ?, ?);");
m_setNodeTypeStmt = compileStatement("UPDATE node SET type = ? WHERE id == ?;");
m_insertSymbolStatement = compileStatement("INSERT OR IGNORE INTO symbol(id, definition_kind) VALUES(?, ?);");
m_findFileStatement = compileStatement("SELECT id FROM file WHERE id == ?;");
m_insertFileStatement = compileStatement(
"INSERT OR IGNORE INTO file(id, path, language, modification_time, indexed, complete, line_count) VALUES(?, ?, ?, ?, ?, ?, ?);");
m_setFileLanguageStmt = compileStatement("UPDATE file SET language = ? WHERE id == ?;");
m_insertFileContentStatement = compileStatement("INSERT INTO filecontent(id, content) VALUES(?, ?);");
m_findEdgeStatement = compileStatement("SELECT id FROM edge WHERE source_node_id == ? AND target_node_id == ? AND type == ? LIMIT 1;");
m_insertEdgeStatement = compileStatement("INSERT INTO edge(id, type, source_node_id, target_node_id) VALUES(?, ?, ?, ?);");
m_findLocalSymbolStmt = compileStatement("SELECT id FROM local_symbol WHERE name == ? LIMIT 1;");
m_insertLocalSymbolStmt = compileStatement("INSERT INTO local_symbol(id, name) VALUES(?, ?);");
m_findSourceLocationStmt = compileStatement(
"SELECT id FROM source_location WHERE "
"file_node_id = ? AND "
"start_line = ? AND "
"start_column = ? AND "
"end_line = ? AND "
"end_column = ? AND "
"type = ? "
"LIMIT 1;");
m_insertSourceLocationStmt = compileStatement(
"INSERT INTO source_location("
"id, file_node_id, start_line, start_column, end_line, end_column, type) "
"VALUES(NULL, ?, ?, ?, ?, ?, ?);");
m_insertOccurenceStmt = compileStatement("INSERT OR IGNORE INTO occurrence(element_id, source_location_id) VALUES(?, ?);");
m_findErrorStatement = compileStatement(
"SELECT id FROM error WHERE "
"message = ? AND "
"fatal == ? "
"LIMIT 1;");
m_insertErrorStatement = compileStatement(
"INSERT INTO error(id, message, fatal, indexed, translation_unit) "
"VALUES(?, ?, ?, ?, ?);");
m_insertOrUpdateMetaValueStmt = compileStatement(
"INSERT OR REPLACE INTO meta(id, key, value) VALUES("
"(SELECT id FROM meta WHERE key = ?), ?, ?"
");");
}
void DatabaseStorage::clearPrecompiledStatements()
{
m_insertElementStatement.finalize();
m_insertElementComponentStatement.finalize();
m_findNodeStatement.finalize();
m_insertNodeStatement.finalize();
m_setNodeTypeStmt.finalize();
m_insertSymbolStatement.finalize();
m_findFileStatement.finalize();
m_insertFileStatement.finalize();
m_setFileLanguageStmt.finalize();
m_insertFileContentStatement.finalize();
m_findEdgeStatement.finalize();
m_insertEdgeStatement.finalize();
m_findLocalSymbolStmt.finalize();
m_insertLocalSymbolStmt.finalize();
m_findSourceLocationStmt.finalize();
m_insertSourceLocationStmt.finalize();
m_insertOccurenceStmt.finalize();
m_findErrorStatement.finalize();
m_insertErrorStatement.finalize();
m_insertOrUpdateMetaValueStmt.finalize();
}
int DatabaseStorage::insertElement()
{
executeStatement(m_insertElementStatement);
const int id = static_cast<int>(m_database.lastRowId());
m_insertElementStatement.reset();
return id;
}
void DatabaseStorage::insertOrUpdateMetaValue(const std::string& key, const std::string& value)
{
m_insertOrUpdateMetaValueStmt.bind(1, key.c_str());
m_insertOrUpdateMetaValueStmt.bind(2, key.c_str());
m_insertOrUpdateMetaValueStmt.bind(3, value.c_str());
executeStatement(m_insertOrUpdateMetaValueStmt);
m_insertOrUpdateMetaValueStmt.reset();
}
CppSQLite3Statement DatabaseStorage::compileStatement(const std::string& statement) const
{
try
{
return m_database.compileStatement(statement.c_str());
}
catch (CppSQLite3Exception e)
{
throw SourcetrailException("Failed to compile statement \"" + statement + "\" with message \"" + e.errorMessage() + "\".");
}
return CppSQLite3Statement();
}
void DatabaseStorage::executeStatement(const std::string& statement) const
{
try
{
m_database.execDML(statement.c_str());
}
catch (CppSQLite3Exception e)
{
throw SourcetrailException("Failed to execute statement \"" + statement + "\" with message \"" + e.errorMessage() + "\".");
}
}
void DatabaseStorage::executeStatement(CppSQLite3Statement& statement) const
{
try
{
statement.execDML();
}
catch (CppSQLite3Exception e)
{
throw SourcetrailException("Failed to execute statement with message \"" + std::string(e.errorMessage()) + "\".");
}
}
CppSQLite3Query DatabaseStorage::executeQuery(const std::string& query) const
{
try
{
return m_database.execQuery(query.c_str());
}
catch (CppSQLite3Exception e)
{
throw SourcetrailException("Failed to execute query \"" + query + "\" with message \"" + e.errorMessage() + "\".");
}
}
CppSQLite3Query DatabaseStorage::executeQuery(CppSQLite3Statement& statement) const
{
try
{
return statement.execQuery();
}
catch (CppSQLite3Exception e)
{
throw SourcetrailException("Failed to execute query with message \"" + std::string(e.errorMessage()) + "\".");
}
}
template <>
std::vector<StorageEdge> DatabaseStorage::doGetAll<StorageEdge>(const std::string& query) const
{
CppSQLite3Query q = executeQuery("SELECT id, type, source_node_id, target_node_id FROM edge " + query + ";");
std::vector<StorageEdge> edges;
while (!q.eof())
{
const int id = q.getIntField(0, 0);
const int edgeKind = q.getIntField(1, -1);
const int sourceId = q.getIntField(2, 0);
const int targetId = q.getIntField(3, 0);
if (id != 0 && edgeKind != -1)
{
edges.emplace_back(StorageEdge(id, sourceId, targetId, edgeKind));
}
q.nextRow();
}
return edges;
}
template <>
std::vector<StorageNode> DatabaseStorage::doGetAll<StorageNode>(const std::string& query) const
{
CppSQLite3Query q = executeQuery("SELECT id, type, serialized_name FROM node " + query + ";");
std::vector<StorageNode> nodes;
while (!q.eof())
{
const int 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.emplace_back(StorageNode(id, type, serializedName));
}
q.nextRow();
}
return nodes;
}
template <>
std::vector<StorageSymbol> DatabaseStorage::doGetAll<StorageSymbol>(const std::string& query) const
{
CppSQLite3Query q = executeQuery("SELECT id, definition_kind FROM symbol " + query + ";");
std::vector<StorageSymbol> symbols;
while (!q.eof())
{
const int id = q.getIntField(0, 0);
const int definitionKind = q.getIntField(1, 0);
if (id != 0)
{
symbols.emplace_back(StorageSymbol(id, definitionKind));
}
q.nextRow();
}
return symbols;
}
template <>
std::vector<StorageFile> DatabaseStorage::doGetAll<StorageFile>(const std::string& query) const
{
CppSQLite3Query q = executeQuery("SELECT id, path, language, modification_time, indexed, complete FROM file " + query + ";");
std::vector<StorageFile> files;
while (!q.eof())
{
const int id = q.getIntField(0, 0);
const std::string filePath = q.getStringField(1, "");
const std::string languageIdentifier = q.getStringField(2, "");
const std::string modificationTime = q.getStringField(3, "");
const bool indexed = q.getIntField(4, 0);
const bool complete = q.getIntField(5, 0);
if (id != 0)
{
files.emplace_back(StorageFile(id, filePath, languageIdentifier, modificationTime, indexed, complete));
}
q.nextRow();
}
return files;
}
template <>
std::vector<StorageLocalSymbol> DatabaseStorage::doGetAll<StorageLocalSymbol>(const std::string& query) const
{
CppSQLite3Query q = executeQuery("SELECT id, name FROM local_symbol " + query + ";");
std::vector<StorageLocalSymbol> localSymbols;
while (!q.eof())
{
const int id = q.getIntField(0, 0);
const std::string name = q.getStringField(1, "");
if (id != 0)
{
localSymbols.emplace_back(StorageLocalSymbol(id, name));
}
q.nextRow();
}
return localSymbols;
}
template <>
std::vector<StorageSourceLocation> DatabaseStorage::doGetAll<StorageSourceLocation>(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<StorageSourceLocation> sourceLocations;
while (!q.eof())
{
const int id = q.getIntField(0, 0);
const int 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 locationKind = q.getIntField(6, -1);
if (id != 0 && fileNodeId != 0 && startLineNumber != -1 && startColNumber != -1 && endLineNumber != -1 && endColNumber != -1 &&
locationKind != -1)
{
sourceLocations.emplace_back(
StorageSourceLocation(id, fileNodeId, startLineNumber, startColNumber, endLineNumber, endColNumber, locationKind));
}
q.nextRow();
}
return sourceLocations;
}
template <>
std::vector<StorageOccurrence> DatabaseStorage::doGetAll<StorageOccurrence>(const std::string& query) const
{
CppSQLite3Query q = executeQuery("SELECT element_id, source_location_id FROM occurrence " + query + ";");
std::vector<StorageOccurrence> occurrences;
while (!q.eof())
{
const int elementId = q.getIntField(0, 0);
const int sourceLocationId = q.getIntField(1, 0);
if (elementId != 0 && sourceLocationId != 0)
{
occurrences.emplace_back(StorageOccurrence(elementId, sourceLocationId));
}
q.nextRow();
}
return occurrences;
}
template <>
std::vector<StorageError> DatabaseStorage::doGetAll<StorageError>(const std::string& query) const
{
CppSQLite3Query q = executeQuery("SELECT id, message, fatal, indexed, translation_unit FROM error " + query + ";");
std::vector<StorageError> errors;
while (!q.eof())
{
const int id = q.getIntField(0, 0);
const std::string message = q.getStringField(1, "");
const bool fatal = q.getIntField(2, 0);
const bool indexed = q.getIntField(3, 0);
const std::string translationUnit = q.getStringField(4, "");
if (id != 0)
{
errors.emplace_back(StorageError(id, message, translationUnit, fatal, indexed));
}
q.nextRow();
}
return errors;
}
} // namespace sourcetrail