forked from qt-creator/qt-creator
Sqlite: Add primary key table constraint to table builder
Change-Id: I60c158eb76db2217a2d045053bb8e47eef75ff7a Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
@@ -42,7 +42,10 @@ enum class AutoIncrement { No, Yes };
|
||||
|
||||
class PrimaryKey
|
||||
{
|
||||
friend bool operator==(PrimaryKey, PrimaryKey) { return true; }
|
||||
friend bool operator==(PrimaryKey first, PrimaryKey second)
|
||||
{
|
||||
return first.autoincrement == second.autoincrement;
|
||||
}
|
||||
|
||||
public:
|
||||
AutoIncrement autoincrement = AutoIncrement::No;
|
||||
|
@@ -48,7 +48,17 @@ void CreateTableSqlStatementBuilder::addColumn(Utils::SmallStringView columnName
|
||||
m_columns.emplace_back(Utils::SmallStringView{}, columnName, columnType, std::move(constraints));
|
||||
}
|
||||
|
||||
void CreateTableSqlStatementBuilder::setColumns(const SqliteColumns &columns)
|
||||
void CreateTableSqlStatementBuilder::addConstraint(TableConstraint &&constraint)
|
||||
{
|
||||
m_tableConstraints.push_back(std::move(constraint));
|
||||
}
|
||||
|
||||
void CreateTableSqlStatementBuilder::setConstraints(TableConstraints constraints)
|
||||
{
|
||||
m_tableConstraints = std::move(constraints);
|
||||
}
|
||||
|
||||
void CreateTableSqlStatementBuilder::setColumns(SqliteColumns columns)
|
||||
{
|
||||
m_sqlStatementBuilder.clear();
|
||||
|
||||
@@ -212,8 +222,25 @@ public:
|
||||
|
||||
Utils::SmallString &columnDefinitionString;
|
||||
};
|
||||
|
||||
class TableContraintsVisiter
|
||||
{
|
||||
public:
|
||||
TableContraintsVisiter(Utils::SmallString &columnDefinitionString)
|
||||
: columnDefinitionString(columnDefinitionString)
|
||||
{}
|
||||
|
||||
void operator()(const TablePrimaryKey &primaryKey)
|
||||
{
|
||||
columnDefinitionString.append("PRIMARY KEY(");
|
||||
columnDefinitionString.append(primaryKey.columns.join(", "));
|
||||
columnDefinitionString.append(")");
|
||||
}
|
||||
|
||||
Utils::SmallString &columnDefinitionString;
|
||||
};
|
||||
} // namespace
|
||||
void CreateTableSqlStatementBuilder::bindColumnDefinitions() const
|
||||
void CreateTableSqlStatementBuilder::bindColumnDefinitionsAndTableConstraints() const
|
||||
{
|
||||
Utils::SmallStringVector columnDefinitionStrings;
|
||||
columnDefinitionStrings.reserve(m_columns.size());
|
||||
@@ -226,7 +253,16 @@ void CreateTableSqlStatementBuilder::bindColumnDefinitions() const
|
||||
for (const Constraint &constraint : column.constraints)
|
||||
Utils::visit(visiter, constraint);
|
||||
|
||||
columnDefinitionStrings.push_back(columnDefinitionString);
|
||||
columnDefinitionStrings.push_back(std::move(columnDefinitionString));
|
||||
}
|
||||
|
||||
for (const TableConstraint &constraint : m_tableConstraints) {
|
||||
Utils::SmallString columnDefinitionString;
|
||||
|
||||
TableContraintsVisiter visiter{columnDefinitionString};
|
||||
Utils::visit(visiter, constraint);
|
||||
|
||||
columnDefinitionStrings.push_back(std::move(columnDefinitionString));
|
||||
}
|
||||
|
||||
m_sqlStatementBuilder.bind("$columnDefinitions", columnDefinitionStrings);
|
||||
@@ -238,7 +274,7 @@ void CreateTableSqlStatementBuilder::bindAll() const
|
||||
|
||||
bindTemporary();
|
||||
bindIfNotExists();
|
||||
bindColumnDefinitions();
|
||||
bindColumnDefinitionsAndTableConstraints();
|
||||
bindWithoutRowId();
|
||||
}
|
||||
|
||||
|
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "sqlitecolumn.h"
|
||||
#include "sqlstatementbuilder.h"
|
||||
#include "tableconstraints.h"
|
||||
|
||||
namespace Sqlite {
|
||||
|
||||
@@ -40,7 +41,9 @@ public:
|
||||
void addColumn(Utils::SmallStringView columnName,
|
||||
ColumnType columnType,
|
||||
Constraints &&constraints = {});
|
||||
void setColumns(const SqliteColumns &columns);
|
||||
void addConstraint(TableConstraint &&constraint);
|
||||
void setConstraints(TableConstraints constraints);
|
||||
void setColumns(SqliteColumns columns);
|
||||
void setUseWithoutRowId(bool useWithoutRowId);
|
||||
void setUseIfNotExists(bool useIfNotExists);
|
||||
void setUseTemporaryTable(bool useTemporaryTable);
|
||||
@@ -53,7 +56,7 @@ public:
|
||||
bool isValid() const;
|
||||
|
||||
protected:
|
||||
void bindColumnDefinitions() const;
|
||||
void bindColumnDefinitionsAndTableConstraints() const;
|
||||
void bindAll() const;
|
||||
void bindWithoutRowId() const;
|
||||
void bindIfNotExists() const;
|
||||
@@ -63,6 +66,7 @@ private:
|
||||
mutable SqlStatementBuilder m_sqlStatementBuilder;
|
||||
Utils::SmallString m_tableName;
|
||||
SqliteColumns m_columns;
|
||||
TableConstraints m_tableConstraints;
|
||||
bool m_useWithoutRowId = false;
|
||||
bool m_useIfNotExits = false;
|
||||
bool m_useTemporaryTable = false;
|
||||
|
@@ -27,6 +27,7 @@ SOURCES += \
|
||||
$$PWD/sqlitebasestatement.cpp
|
||||
HEADERS += \
|
||||
$$PWD/constraints.h \
|
||||
$$PWD/tableconstraints.h \
|
||||
$$PWD/createtablesqlstatementbuilder.h \
|
||||
$$PWD/lastchangedrowid.h \
|
||||
$$PWD/sqlitedatabasebackend.h \
|
||||
|
@@ -123,6 +123,17 @@ public:
|
||||
return m_sqliteColumns.back();
|
||||
}
|
||||
|
||||
void addPrimaryKeyContraint(const SqliteColumnConstReferences &columns)
|
||||
{
|
||||
Utils::SmallStringVector columnNames;
|
||||
columnNames.reserve(columns.size());
|
||||
|
||||
for (const auto &column : columns)
|
||||
columnNames.emplace_back(column.get().name);
|
||||
|
||||
m_tableConstraints.emplace_back(TablePrimaryKey{std::move(columnNames)});
|
||||
}
|
||||
|
||||
Index &addIndex(const SqliteColumnConstReferences &columns)
|
||||
{
|
||||
m_sqliteIndices.emplace_back(m_tableName.clone(), sqliteColumnNames(columns));
|
||||
@@ -159,6 +170,7 @@ public:
|
||||
builder.setUseIfNotExists(m_useIfNotExists);
|
||||
builder.setUseTemporaryTable(m_useTemporaryTable);
|
||||
builder.setColumns(m_sqliteColumns);
|
||||
builder.setConstraints(m_tableConstraints);
|
||||
|
||||
database.execute(builder.sqlStatement());
|
||||
|
||||
@@ -207,6 +219,7 @@ private:
|
||||
Utils::SmallString m_tableName;
|
||||
SqliteColumns m_sqliteColumns;
|
||||
SqliteIndices m_sqliteIndices;
|
||||
TableConstraints m_tableConstraints;
|
||||
bool m_withoutRowId = false;
|
||||
bool m_useIfNotExists = false;
|
||||
bool m_useTemporaryTable = false;
|
||||
|
49
src/libs/sqlite/tableconstraints.h
Normal file
49
src/libs/sqlite/tableconstraints.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 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 "sqliteglobal.h"
|
||||
|
||||
#include <sqlitevalue.h>
|
||||
#include <utils/smallstringvector.h>
|
||||
#include <utils/variant.h>
|
||||
|
||||
namespace Sqlite {
|
||||
class TablePrimaryKey
|
||||
{
|
||||
friend bool operator==(TablePrimaryKey first, TablePrimaryKey second)
|
||||
{
|
||||
return first.columns == second.columns;
|
||||
}
|
||||
|
||||
public:
|
||||
Utils::SmallStringVector columns;
|
||||
};
|
||||
|
||||
using TableConstraint = Utils::variant<TablePrimaryKey>;
|
||||
using TableConstraints = std::vector<TableConstraint>;
|
||||
|
||||
} // namespace Sqlite
|
@@ -530,4 +530,17 @@ TEST_F(CreateTableSqlStatementBuilder, BlobType)
|
||||
ASSERT_THAT(builder.sqlStatement(), "CREATE TABLE test(data BLOB)");
|
||||
}
|
||||
|
||||
TEST_F(CreateTableSqlStatementBuilder, TablePrimaryKeyConstaint)
|
||||
{
|
||||
builder.clear();
|
||||
builder.setTableName("test");
|
||||
builder.addColumn("id", ColumnType::Integer);
|
||||
builder.addColumn("text", ColumnType::Text);
|
||||
|
||||
builder.addConstraint(Sqlite::TablePrimaryKey{{"id, text"}});
|
||||
auto statement = builder.sqlStatement();
|
||||
|
||||
ASSERT_THAT(statement, "CREATE TABLE test(id INTEGER, text TEXT, PRIMARY KEY(id, text))");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@@ -292,4 +292,17 @@ TEST_F(SqliteTable, AddForeignKeyColumnWithColumnAndNotNull)
|
||||
VariantWith<Sqlite::NotNull>(Eq(Sqlite::NotNull{}))))));
|
||||
}
|
||||
|
||||
TEST_F(SqliteTable, AddPrimaryTableContraint)
|
||||
{
|
||||
table.setName(tableName.clone());
|
||||
const auto &idColumn = table.addColumn("id");
|
||||
const auto &nameColumn = table.addColumn("name");
|
||||
table.addPrimaryKeyContraint({idColumn, nameColumn});
|
||||
|
||||
EXPECT_CALL(mockDatabase,
|
||||
execute(
|
||||
Eq("CREATE TABLE testTable(id NUMERIC, name NUMERIC, PRIMARY KEY(id, name))")));
|
||||
|
||||
table.initialize(mockDatabase);
|
||||
}
|
||||
} // namespace
|
||||
|
Reference in New Issue
Block a user