Commit 2df9a99c authored by Marco Bubke's avatar Marco Bubke Committed by Tim Jenssen

Clang: Add RefactoringDatabaseInitializer

We moved the creation of the tables and indices to an extra class which can
be called from other places. So you can be sure that a database is
initialized.

Change-Id: Ief5b30ced7b9011ca94367aa2578098423dcecd9
Reviewed-by: Tim Jenssen's avatarTim Jenssen <tim.jenssen@qt.io>
parent 62313559
......@@ -175,6 +175,7 @@ HEADERS += \
$$PWD/requestsourcerangesforquerymessage.h \
$$PWD/stringcachefwd.h \
$$PWD/stringcachealgorithms.h \
$$PWD/projectmanagementserverinterface.h
$$PWD/projectmanagementserverinterface.h \
$$PWD/refactoringdatabaseinitializer.h
contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <createtablesqlstatementbuilder.h>
#include <sqlitetransaction.h>
#include <sqlitetable.h>
namespace ClangBackEnd {
template<typename DatabaseType>
class RefactoringDatabaseInitializer
{
public:
RefactoringDatabaseInitializer(DatabaseType &database)
: database(database)
{
Sqlite::ImmediateTransaction<DatabaseType> transaction{database};
createSymbolsTable();
createLocationsTable();
createSourcesTable();
transaction.commit();
}
void createSymbolsTable()
{
Sqlite::Table table;
table.setUseIfNotExists(true);
table.setName("symbols");
table.addColumn("symbolId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey);
const Sqlite::Column &usrColumn = table.addColumn("usr", Sqlite::ColumnType::Text);
table.addColumn("symbolName", Sqlite::ColumnType::Text);
table.addIndex({usrColumn});
table.initialize(database);
}
void createLocationsTable()
{
Sqlite::Table table;
table.setUseIfNotExists(true);
table.setName("locations");
table.addColumn("symbolId", Sqlite::ColumnType::Integer);
table.addColumn("line", Sqlite::ColumnType::Integer);
table.addColumn("column", Sqlite::ColumnType::Integer);
const Sqlite::Column &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer);
table.addIndex({sourceIdColumn});
table.initialize(database);
}
void createSourcesTable()
{
Sqlite::Table table;
table.setUseIfNotExists(true);
table.setName("sources");
table.addColumn("sourceId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey);
table.addColumn("sourcePath", Sqlite::ColumnType::Text);
table.initialize(database);
}
public:
DatabaseType &database;
};
} // namespace ClangBackEnd
......@@ -47,56 +47,6 @@ public:
{
}
Sqlite::Table createSymbolsTable()
{
Sqlite::Table table;
table.setUseIfNotExists(true);
table.setName("symbols");
table.addColumn("symbolId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey);
const Sqlite::Column &usrColumn = table.addColumn("usr", Sqlite::ColumnType::Text);
table.addColumn("symbolName", Sqlite::ColumnType::Text);
table.addIndex({usrColumn});
Sqlite::ImmediateTransaction<DatabaseType> transaction(database);
table.initialize(database);
transaction.commit();
return table;
}
Sqlite::Table createLocationsTable()
{
Sqlite::Table table;
table.setUseIfNotExists(true);
table.setName("locations");
table.addColumn("symbolId", Sqlite::ColumnType::Integer);
table.addColumn("line", Sqlite::ColumnType::Integer);
table.addColumn("column", Sqlite::ColumnType::Integer);
const Sqlite::Column &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer);
table.addIndex({sourceIdColumn});
Sqlite::ImmediateTransaction<DatabaseType> transaction(database);
table.initialize(database);
transaction.commit();
return table;
}
Sqlite::Table createSourcesTable()
{
Sqlite::Table table;
table.setUseIfNotExists(true);
table.setName("sources");
table.addColumn("sourceId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey);
table.addColumn("sourcePath", Sqlite::ColumnType::Text);
Sqlite::ImmediateTransaction<DatabaseType> transaction(database);
table.initialize(database);
transaction.commit();
return table;
}
Sqlite::Table createNewSymbolsTable() const
{
Sqlite::Table table;
......@@ -137,9 +87,6 @@ public:
public:
Database &database;
Sqlite::Table symbolsTable{createSymbolsTable()};
Sqlite::Table locationsTable{createLocationsTable()};
Sqlite::Table sourcesTable{createSourcesTable()};
Sqlite::Table newSymbolsTablet{createNewSymbolsTable()};
Sqlite::Table newLocationsTable{createNewLocationsTable()};
WriteStatement insertSymbolsToNewSymbolsStatement{
......
......@@ -32,6 +32,7 @@
#include "symbolscollector.h"
#include "symbolstorage.h"
#include <refactoringdatabaseinitializer.h>
#include <stringcache.h>
#include <sqlitedatabase.h>
......@@ -47,12 +48,13 @@ public:
Sqlite::ReadStatement,
Sqlite::WriteStatement>;
using Storage = ClangBackEnd::SymbolStorage<StatementFactory>;
using DatabaseInitializer = RefactoringDatabaseInitializer<Sqlite::Database>;
SymbolIndexing(FilePathCache<std::mutex> &filePathCache,
Utils::PathString &&databaseFilePath)
: m_filePathCache(filePathCache),
m_database(std::move(databaseFilePath))
m_database(std::move(databaseFilePath)),
m_databaseInitializer(m_database)
{
}
......@@ -75,6 +77,7 @@ public:
private:
FilePathCache<std::mutex> &m_filePathCache;
Sqlite::Database m_database;
DatabaseInitializer m_databaseInitializer;
SymbolsCollector m_collector{m_filePathCache};
StatementFactory m_statementFactory{m_database};
Storage m_symbolStorage{m_statementFactory, m_filePathCache};
......
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "googletest.h"
#include <mocksqlitedatabase.h>
#include <refactoringdatabaseinitializer.h>
namespace {
using Initializer = ClangBackEnd::RefactoringDatabaseInitializer<NiceMock<MockSqliteDatabase>>;
using Sqlite::Table;
class RefactoringDatabaseInitializer : public testing::Test
{
protected:
NiceMock<MockMutex> mockMutex;
NiceMock<MockSqliteDatabase> mockDatabase{mockMutex};
Initializer initializer{mockDatabase};
};
TEST_F(RefactoringDatabaseInitializer, AddSymbolsTable)
{
InSequence s;
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS symbols(symbolId INTEGER PRIMARY KEY, usr TEXT, symbolName TEXT)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_usr ON symbols(usr)")));
initializer.createSymbolsTable();
}
TEST_F(RefactoringDatabaseInitializer, AddLocationsTable)
{
InSequence s;
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS locations(symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_locations_sourceId ON locations(sourceId)")));
initializer.createLocationsTable();
}
TEST_F(RefactoringDatabaseInitializer, AddSourcesTable)
{
InSequence s;
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sources(sourceId INTEGER PRIMARY KEY, sourcePath TEXT)")));
initializer.createSourcesTable();
}
TEST_F(RefactoringDatabaseInitializer, CreateInTheContructor)
{
InSequence s;
EXPECT_CALL(mockMutex, lock());
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS symbols(symbolId INTEGER PRIMARY KEY, usr TEXT, symbolName TEXT)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_usr ON symbols(usr)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS locations(symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_locations_sourceId ON locations(sourceId)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sources(sourceId INTEGER PRIMARY KEY, sourcePath TEXT)")));
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
EXPECT_CALL(mockMutex, unlock());
Initializer initializer{mockDatabase};
}
}
......@@ -47,47 +47,6 @@ protected:
StatementFactory factory{mockDatabase};
};
TEST_F(StorageSqliteStatementFactory, AddSymbolsTable)
{
InSequence s;
EXPECT_CALL(mockMutex, lock());
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS symbols(symbolId INTEGER PRIMARY KEY, usr TEXT, symbolName TEXT)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_usr ON symbols(usr)")));
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
EXPECT_CALL(mockMutex, unlock());
factory.createSymbolsTable();
}
TEST_F(StorageSqliteStatementFactory, AddLocationsTable)
{
InSequence s;
EXPECT_CALL(mockMutex, lock());
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS locations(symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_locations_sourceId ON locations(sourceId)")));
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
EXPECT_CALL(mockMutex, unlock());
factory.createLocationsTable();
}
TEST_F(StorageSqliteStatementFactory, AddSourcesTable)
{
InSequence s;
EXPECT_CALL(mockMutex, lock());
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sources(sourceId INTEGER PRIMARY KEY, sourcePath TEXT)")));
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT")));
EXPECT_CALL(mockMutex, unlock());
factory.createSourcesTable();
}
TEST_F(StorageSqliteStatementFactory, AddNewSymbolsTable)
{
InSequence s;
......@@ -120,16 +79,11 @@ TEST_F(StorageSqliteStatementFactory, AddNewLocationsTable)
TEST_F(StorageSqliteStatementFactory, AddTablesInConstructor)
{
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))).Times(5);
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))).Times(5);
EXPECT_CALL(mockMutex, lock()).Times(5);
EXPECT_CALL(mockMutex, unlock()).Times(5);
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS symbols(symbolId INTEGER PRIMARY KEY, usr TEXT, symbolName TEXT)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_symbols_usr ON symbols(usr)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS locations(symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_locations_sourceId ON locations(sourceId)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS sources(sourceId INTEGER PRIMARY KEY, sourcePath TEXT)")));
EXPECT_CALL(mockDatabase, execute(Eq("BEGIN IMMEDIATE"))).Times(2);
EXPECT_CALL(mockDatabase, execute(Eq("COMMIT"))).Times(2);
EXPECT_CALL(mockMutex, lock()).Times(2);
EXPECT_CALL(mockMutex, unlock()).Times(2);
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TEMPORARY TABLE newSymbols(temporarySymbolId INTEGER PRIMARY KEY, symbolId INTEGER, usr TEXT, symbolName TEXT)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_newSymbols_usr_symbolName ON newSymbols(usr, symbolName)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_newSymbols_symbolId ON newSymbols(symbolId)")));
......
......@@ -75,7 +75,8 @@ SOURCES += \
storagesqlitestatementfactory-test.cpp \
querysqlitestatementfactory-test.cpp \
sqliteindex-test.cpp \
sqlitetransaction-test.cpp
sqlitetransaction-test.cpp \
refactoringdatabaseinitializer-test.cpp
!isEmpty(LIBCLANG_LIBS) {
SOURCES += \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment