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:
Marco Bubke
2020-06-02 22:16:06 +02:00
committed by Tim Jenssen
parent a61eff0079
commit cf441e8198
8 changed files with 139 additions and 7 deletions

View File

@@ -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;

View File

@@ -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();
}

View File

@@ -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;

View File

@@ -27,6 +27,7 @@ SOURCES += \
$$PWD/sqlitebasestatement.cpp
HEADERS += \
$$PWD/constraints.h \
$$PWD/tableconstraints.h \
$$PWD/createtablesqlstatementbuilder.h \
$$PWD/lastchangedrowid.h \
$$PWD/sqlitedatabasebackend.h \

View File

@@ -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;

View 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

View File

@@ -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

View File

@@ -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