improved sqlite performance with indices and compiled statements
This commit is contained in:
+465
-372
@@ -52,10 +52,30 @@ namespace sourcetrail
|
||||
|
||||
DatabaseStorage::~DatabaseStorage()
|
||||
{
|
||||
m_insertElementStatement.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();
|
||||
|
||||
m_database.close();
|
||||
}
|
||||
|
||||
void DatabaseStorage::setupTables()
|
||||
void DatabaseStorage::setupDatabase()
|
||||
{
|
||||
executeStatement("PRAGMA foreign_keys=ON;");
|
||||
|
||||
@@ -64,6 +84,328 @@ namespace sourcetrail
|
||||
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;");
|
||||
|
||||
const std::vector<std::string> tableNames = {
|
||||
"meta",
|
||||
"error",
|
||||
"component_access",
|
||||
"occurrence",
|
||||
"source_location",
|
||||
"local_symbol",
|
||||
"filecontent",
|
||||
"file",
|
||||
"symbol",
|
||||
"node",
|
||||
"edge",
|
||||
"element"
|
||||
};
|
||||
|
||||
for (const std::string& tableName : tableNames)
|
||||
{
|
||||
executeStatement("DROP TABLE IF EXISTS main." + tableName + ";");
|
||||
}
|
||||
|
||||
setupDatabase();
|
||||
}
|
||||
|
||||
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::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 = 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 = 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, "
|
||||
@@ -189,404 +531,155 @@ namespace sourcetrail
|
||||
" FOREIGN KEY(id) REFERENCES element(id) ON DELETE CASCADE"
|
||||
");"
|
||||
);
|
||||
|
||||
insertOrUpdateMetaValue("storage_version", std::to_string(getSupportedDatabaseVersion()));
|
||||
}
|
||||
|
||||
void DatabaseStorage::clearTables()
|
||||
void DatabaseStorage::setupIndices()
|
||||
{
|
||||
executeStatement("PRAGMA foreign_keys=OFF;");
|
||||
|
||||
const std::vector<std::string> tableNames = {
|
||||
"meta",
|
||||
"error",
|
||||
"component_access",
|
||||
"occurrence",
|
||||
"source_location",
|
||||
"local_symbol",
|
||||
"filecontent",
|
||||
"file",
|
||||
"symbol",
|
||||
"node",
|
||||
"edge",
|
||||
"element"
|
||||
};
|
||||
|
||||
for (const std::string& tableName : tableNames)
|
||||
{
|
||||
executeStatement("DROP TABLE IF EXISTS main." + tableName + ";");
|
||||
}
|
||||
|
||||
setupTables();
|
||||
}
|
||||
|
||||
bool DatabaseStorage::isEmpty() const
|
||||
{
|
||||
const std::string tableName = "meta";
|
||||
CppSQLite3Query q = executeQuery(
|
||||
"SELECT name FROM sqlite_master WHERE type='table' AND name='" + tableName + "';"
|
||||
executeStatement(
|
||||
"CREATE INDEX IF NOT EXISTS node_serialized_name_index ON node(serialized_name);"
|
||||
);
|
||||
|
||||
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::addNode(const StorageNodeData& storageNodeData)
|
||||
{
|
||||
int id = 0;
|
||||
|
||||
{
|
||||
CppSQLite3Statement stmt = m_database.compileStatement(
|
||||
"SELECT id FROM node WHERE serialized_name == ? LIMIT 1;"
|
||||
);
|
||||
stmt.bind(1, storageNodeData.serializedName.c_str());
|
||||
CppSQLite3Query q = executeQuery(stmt);
|
||||
if (!q.eof())
|
||||
{
|
||||
id = q.getIntField(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: update node nodeKind here
|
||||
|
||||
if (id == 0)
|
||||
{
|
||||
{
|
||||
CppSQLite3Statement stmt = m_database.compileStatement(
|
||||
"INSERT INTO element(id) VALUES(NULL);"
|
||||
);
|
||||
executeStatement(stmt);
|
||||
id = m_database.lastRowId();
|
||||
}
|
||||
{
|
||||
CppSQLite3Statement stmt = m_database.compileStatement(
|
||||
"INSERT INTO node(id, type, serialized_name) VALUES(?, ?, ?);"
|
||||
);
|
||||
stmt.bind(1, id);
|
||||
stmt.bind(2, storageNodeData.nodeKind);
|
||||
stmt.bind(3, storageNodeData.serializedName.c_str());
|
||||
executeStatement(stmt);
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
void DatabaseStorage::addSymbol(const StorageSymbol& storageSymbol)
|
||||
{
|
||||
CppSQLite3Statement stmt = m_database.compileStatement(
|
||||
"INSERT OR IGNORE INTO symbol(id, definition_kind) VALUES(?, ?);"
|
||||
executeStatement(
|
||||
"CREATE INDEX IF NOT EXISTS edge_source_target_type_index ON edge(source_node_id, target_node_id, type);"
|
||||
);
|
||||
stmt.bind(1, storageSymbol.id);
|
||||
stmt.bind(2, storageSymbol.definitionKind);
|
||||
executeStatement(stmt);
|
||||
}
|
||||
|
||||
void DatabaseStorage::addFile(const StorageFile& storageFile)
|
||||
{
|
||||
{
|
||||
CppSQLite3Statement stmt = m_database.compileStatement(
|
||||
"SELECT id FROM file WHERE id == ?;"
|
||||
);
|
||||
stmt.bind(1, storageFile.id);
|
||||
CppSQLite3Query q = executeQuery(stmt);
|
||||
if (!q.eof())
|
||||
{
|
||||
return; // early exit if the file already exists
|
||||
}
|
||||
}
|
||||
executeStatement(
|
||||
"CREATE INDEX IF NOT EXISTS local_symbol_name_index ON local_symbol(name);"
|
||||
);
|
||||
|
||||
std::string content = "";
|
||||
if (utility::getFileExists(storageFile.filePath))
|
||||
{
|
||||
content = utility::getFileContent(storageFile.filePath);
|
||||
}
|
||||
const int lineCount = utility::getLineCount(content);
|
||||
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);"
|
||||
);
|
||||
|
||||
{
|
||||
CppSQLite3Statement stmt = m_database.compileStatement(
|
||||
"INSERT OR IGNORE INTO file(id, path, language, modification_time, indexed, complete, line_count) VALUES(?, ?, ?, ?, ?, ?, ?);"
|
||||
);
|
||||
stmt.bind(1, storageFile.id);
|
||||
stmt.bind(2, storageFile.filePath.c_str());
|
||||
stmt.bind(3, storageFile.languageIdentifier.c_str());
|
||||
stmt.bind(4, storageFile.modificationTime.c_str());
|
||||
stmt.bind(5, storageFile.indexed);
|
||||
stmt.bind(6, storageFile.complete);
|
||||
stmt.bind(7, lineCount);
|
||||
executeStatement(stmt);
|
||||
}
|
||||
|
||||
if (!content.empty())
|
||||
{
|
||||
CppSQLite3Statement stmt = m_database.compileStatement(
|
||||
"INSERT INTO filecontent(id, content) VALUES(?, ?);"
|
||||
);
|
||||
stmt.bind(1, storageFile.id);
|
||||
stmt.bind(2, content.c_str());
|
||||
executeStatement(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
int DatabaseStorage::addEdge(const StorageEdgeData& storageEdgeData)
|
||||
{
|
||||
int id = 0;
|
||||
|
||||
{
|
||||
CppSQLite3Statement stmt = m_database.compileStatement(
|
||||
"SELECT id FROM edge WHERE source_node_id == ? AND target_node_id == ? AND type == ? LIMIT 1;"
|
||||
);
|
||||
stmt.bind(1, storageEdgeData.sourceNodeId);
|
||||
stmt.bind(2, storageEdgeData.targetNodeId);
|
||||
stmt.bind(3, storageEdgeData.edgeKind);
|
||||
CppSQLite3Query q = executeQuery(stmt);
|
||||
if (!q.eof())
|
||||
{
|
||||
id = q.getIntField(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (id == 0)
|
||||
{
|
||||
{
|
||||
CppSQLite3Statement stmt = m_database.compileStatement(
|
||||
"INSERT INTO element(id) VALUES(NULL);"
|
||||
);
|
||||
executeStatement(stmt);
|
||||
id = m_database.lastRowId();
|
||||
}
|
||||
{
|
||||
CppSQLite3Statement stmt = m_database.compileStatement(
|
||||
"INSERT INTO edge(id, type, source_node_id, target_node_id) VALUES(?, ?, ?, ?);"
|
||||
);
|
||||
stmt.bind(1, id);
|
||||
stmt.bind(2, storageEdgeData.edgeKind);
|
||||
stmt.bind(3, storageEdgeData.sourceNodeId);
|
||||
stmt.bind(4, storageEdgeData.targetNodeId);
|
||||
executeStatement(stmt);
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
int DatabaseStorage::addLocalSymbol(const StorageLocalSymbolData& storageLocalSymbolData)
|
||||
{
|
||||
int id = 0;
|
||||
|
||||
{
|
||||
CppSQLite3Statement stmt = m_database.compileStatement(
|
||||
"SELECT id FROM local_symbol WHERE name == ? LIMIT 1;"
|
||||
);
|
||||
stmt.bind(1, storageLocalSymbolData.name.c_str());
|
||||
CppSQLite3Query q = executeQuery(stmt);
|
||||
if (!q.eof())
|
||||
{
|
||||
id = q.getIntField(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (id == 0)
|
||||
{
|
||||
{
|
||||
CppSQLite3Statement stmt = m_database.compileStatement(
|
||||
"INSERT INTO element(id) VALUES(NULL);"
|
||||
);
|
||||
executeStatement(stmt);
|
||||
id = m_database.lastRowId();
|
||||
}
|
||||
{
|
||||
CppSQLite3Statement stmt = m_database.compileStatement(
|
||||
"INSERT INTO local_symbol(id, name) VALUES(?, ?);"
|
||||
);
|
||||
stmt.bind(1, id);
|
||||
stmt.bind(2, storageLocalSymbolData.name.c_str());
|
||||
executeStatement(stmt);
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
int DatabaseStorage::addSourceLocation(const StorageSourceLocationData& storageSourceLocationData)
|
||||
{
|
||||
int id = 0;
|
||||
|
||||
{
|
||||
CppSQLite3Statement stmt = m_database.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;"
|
||||
);
|
||||
stmt.bind(1, storageSourceLocationData.fileNodeId);
|
||||
stmt.bind(2, storageSourceLocationData.startLineNumber);
|
||||
stmt.bind(3, storageSourceLocationData.startColumnNumber);
|
||||
stmt.bind(4, storageSourceLocationData.endLineNumber);
|
||||
stmt.bind(5, storageSourceLocationData.endColumnNumber);
|
||||
stmt.bind(6, storageSourceLocationData.locationKind);
|
||||
CppSQLite3Query q = executeQuery(stmt);
|
||||
if (!q.eof())
|
||||
{
|
||||
id = q.getIntField(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (id == 0)
|
||||
{
|
||||
CppSQLite3Statement stmt = m_database.compileStatement(
|
||||
"INSERT INTO source_location(id, file_node_id, start_line, start_column, end_line, end_column, type) VALUES(NULL, ?, ?, ?, ?, ?, ?);"
|
||||
);
|
||||
stmt.bind(1, storageSourceLocationData.fileNodeId);
|
||||
stmt.bind(2, storageSourceLocationData.startLineNumber);
|
||||
stmt.bind(3, storageSourceLocationData.startColumnNumber);
|
||||
stmt.bind(4, storageSourceLocationData.endLineNumber);
|
||||
stmt.bind(5, storageSourceLocationData.endColumnNumber);
|
||||
stmt.bind(6, storageSourceLocationData.locationKind);
|
||||
executeStatement(stmt);
|
||||
id = m_database.lastRowId();
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
void DatabaseStorage::addOccurrence(const StorageOccurrence& storageOccurrence)
|
||||
{
|
||||
CppSQLite3Statement stmt = m_database.compileStatement(
|
||||
"INSERT OR IGNORE INTO occurrence(element_id, source_location_id) VALUES(?, ?);"
|
||||
executeStatement(
|
||||
"CREATE INDEX IF NOT EXISTS error_all_data_index ON error(message, fatal);"
|
||||
);
|
||||
stmt.bind(1, storageOccurrence.elementId);
|
||||
stmt.bind(2, storageOccurrence.sourceLocationId);
|
||||
executeStatement(stmt);
|
||||
}
|
||||
|
||||
int DatabaseStorage::addError(const StorageErrorData& storageErrorData)
|
||||
void DatabaseStorage::setupPrecompiledStatements()
|
||||
{
|
||||
int id = 0;
|
||||
{
|
||||
CppSQLite3Statement stmt = m_database.compileStatement(
|
||||
"SELECT id FROM error WHERE "
|
||||
"message = ? AND "
|
||||
"fatal == ? "
|
||||
"LIMIT 1;"
|
||||
);
|
||||
stmt.bind(1, storageErrorData.message.c_str());
|
||||
stmt.bind(2, storageErrorData.fatal);
|
||||
CppSQLite3Query q = executeQuery(stmt);
|
||||
if (!q.eof() && q.numFields() > 0)
|
||||
{
|
||||
id = q.getIntField(0, -1);
|
||||
}
|
||||
}
|
||||
m_insertElementStatement = compileStatement(
|
||||
"INSERT INTO element(id) VALUES(NULL);"
|
||||
);
|
||||
|
||||
if (id == 0)
|
||||
{
|
||||
{
|
||||
CppSQLite3Statement stmt = m_database.compileStatement(
|
||||
"INSERT INTO element(id) VALUES(NULL);"
|
||||
);
|
||||
executeStatement(stmt);
|
||||
id = m_database.lastRowId();
|
||||
}
|
||||
m_findNodeStatement = compileStatement(
|
||||
"SELECT id FROM node WHERE serialized_name == ? LIMIT 1;"
|
||||
);
|
||||
|
||||
CppSQLite3Statement stmt = m_database.compileStatement(
|
||||
"INSERT INTO error(id, message, fatal, indexed, translation_unit) "
|
||||
"VALUES(?, ?, ?, ?, ?);"
|
||||
);
|
||||
stmt.bind(1, id);
|
||||
stmt.bind(2, storageErrorData.message.c_str());
|
||||
stmt.bind(3, storageErrorData.fatal);
|
||||
stmt.bind(4, storageErrorData.indexed);
|
||||
stmt.bind(5, storageErrorData.translationUnit.c_str());
|
||||
executeStatement(stmt);
|
||||
id = m_database.lastRowId();
|
||||
}
|
||||
return id;
|
||||
}
|
||||
m_insertNodeStatement = compileStatement(
|
||||
"INSERT INTO node(id, type, serialized_name) VALUES(?, ?, ?);"
|
||||
);
|
||||
|
||||
void DatabaseStorage::setNodeType(int nodeId, int nodeType)
|
||||
{
|
||||
CppSQLite3Statement stmt = m_database.compileStatement(
|
||||
m_setNodeTypeStmt = compileStatement(
|
||||
"UPDATE node SET type = ? WHERE id == ?;"
|
||||
);
|
||||
stmt.bind(1, nodeType);
|
||||
stmt.bind(2, nodeId);
|
||||
executeStatement(stmt);
|
||||
}
|
||||
|
||||
void DatabaseStorage::setFileLanguage(int fileId, const std::string& languageIdentifier)
|
||||
{
|
||||
CppSQLite3Statement stmt = m_database.compileStatement(
|
||||
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 == ?;"
|
||||
);
|
||||
stmt.bind(1, languageIdentifier.c_str());
|
||||
stmt.bind(2, fileId);
|
||||
executeStatement(stmt);
|
||||
}
|
||||
|
||||
// --- Private Interface ---
|
||||
m_insertFileContentStatement = compileStatement(
|
||||
"INSERT INTO filecontent(id, content) VALUES(?, ?);"
|
||||
);
|
||||
|
||||
void DatabaseStorage::insertOrUpdateMetaValue(const std::string& key, const std::string& value)
|
||||
{
|
||||
CppSQLite3Statement stmt = m_database.compileStatement(std::string(
|
||||
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 = ?), ?, ?"
|
||||
");"
|
||||
).c_str());
|
||||
);
|
||||
}
|
||||
|
||||
stmt.bind(1, key.c_str());
|
||||
stmt.bind(2, key.c_str());
|
||||
stmt.bind(3, value.c_str());
|
||||
executeStatement(stmt);
|
||||
int DatabaseStorage::insertElement()
|
||||
{
|
||||
executeStatement(m_insertElementStatement);
|
||||
int id = 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
|
||||
|
||||
Reference in New Issue
Block a user