diff options
-rw-r--r-- | src/libs/sqlite/constraints.h | 5 | ||||
-rw-r--r-- | src/libs/sqlite/createtablesqlstatementbuilder.cpp | 44 | ||||
-rw-r--r-- | src/libs/sqlite/createtablesqlstatementbuilder.h | 8 | ||||
-rw-r--r-- | src/libs/sqlite/sqlite-lib.pri | 1 | ||||
-rw-r--r-- | src/libs/sqlite/sqlitetable.h | 13 | ||||
-rw-r--r-- | src/libs/sqlite/tableconstraints.h | 49 | ||||
-rw-r--r-- | tests/unit/unittest/createtablesqlstatementbuilder-test.cpp | 13 | ||||
-rw-r--r-- | tests/unit/unittest/sqlitetable-test.cpp | 13 |
8 files changed, 139 insertions, 7 deletions
diff --git a/src/libs/sqlite/constraints.h b/src/libs/sqlite/constraints.h index d60a767a28..c8e1ecf7d7 100644 --- a/src/libs/sqlite/constraints.h +++ b/src/libs/sqlite/constraints.h @@ -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; diff --git a/src/libs/sqlite/createtablesqlstatementbuilder.cpp b/src/libs/sqlite/createtablesqlstatementbuilder.cpp index 2a14fe9ca5..2ea93d2bcd 100644 --- a/src/libs/sqlite/createtablesqlstatementbuilder.cpp +++ b/src/libs/sqlite/createtablesqlstatementbuilder.cpp @@ -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(); } diff --git a/src/libs/sqlite/createtablesqlstatementbuilder.h b/src/libs/sqlite/createtablesqlstatementbuilder.h index 786753fdfa..3e3743e9da 100644 --- a/src/libs/sqlite/createtablesqlstatementbuilder.h +++ b/src/libs/sqlite/createtablesqlstatementbuilder.h @@ -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; diff --git a/src/libs/sqlite/sqlite-lib.pri b/src/libs/sqlite/sqlite-lib.pri index 4c0b3a18e7..1ab7631387 100644 --- a/src/libs/sqlite/sqlite-lib.pri +++ b/src/libs/sqlite/sqlite-lib.pri @@ -27,6 +27,7 @@ SOURCES += \ $$PWD/sqlitebasestatement.cpp HEADERS += \ $$PWD/constraints.h \ + $$PWD/tableconstraints.h \ $$PWD/createtablesqlstatementbuilder.h \ $$PWD/lastchangedrowid.h \ $$PWD/sqlitedatabasebackend.h \ diff --git a/src/libs/sqlite/sqlitetable.h b/src/libs/sqlite/sqlitetable.h index a7b524cd3b..9883415a9f 100644 --- a/src/libs/sqlite/sqlitetable.h +++ b/src/libs/sqlite/sqlitetable.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; diff --git a/src/libs/sqlite/tableconstraints.h b/src/libs/sqlite/tableconstraints.h new file mode 100644 index 0000000000..b2dee2c928 --- /dev/null +++ b/src/libs/sqlite/tableconstraints.h @@ -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 diff --git a/tests/unit/unittest/createtablesqlstatementbuilder-test.cpp b/tests/unit/unittest/createtablesqlstatementbuilder-test.cpp index 49099081a0..0e92b06897 100644 --- a/tests/unit/unittest/createtablesqlstatementbuilder-test.cpp +++ b/tests/unit/unittest/createtablesqlstatementbuilder-test.cpp @@ -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 diff --git a/tests/unit/unittest/sqlitetable-test.cpp b/tests/unit/unittest/sqlitetable-test.cpp index 05d3e73462..f96b451785 100644 --- a/tests/unit/unittest/sqlitetable-test.cpp +++ b/tests/unit/unittest/sqlitetable-test.cpp @@ -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 |