Sqlite: Improve constraint support

Now you can add more than one constraint. And we added some
new constraints too.

Change-Id: I849d2d2ef6e44c897a65ff2bdfe8d172a345c991
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2020-05-13 20:29:49 +02:00
committed by Tim Jenssen
parent a86fd58e40
commit c4bbc74e37
12 changed files with 497 additions and 242 deletions

View File

@@ -66,7 +66,7 @@ public:
Sqlite::Table table; Sqlite::Table table;
table.setUseIfNotExists(true); table.setUseIfNotExists(true);
table.setName("symbols"); table.setName("symbols");
table.addColumn("symbolId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey); table.addColumn("symbolId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}});
const Sqlite::Column &usrColumn = table.addColumn("usr", Sqlite::ColumnType::Text); const Sqlite::Column &usrColumn = table.addColumn("usr", Sqlite::ColumnType::Text);
const Sqlite::Column &symbolNameColumn = table.addColumn("symbolName", Sqlite::ColumnType::Text); const Sqlite::Column &symbolNameColumn = table.addColumn("symbolName", Sqlite::ColumnType::Text);
const Sqlite::Column &symbolKindColumn = table.addColumn("symbolKind", Sqlite::ColumnType::Integer); const Sqlite::Column &symbolKindColumn = table.addColumn("symbolKind", Sqlite::ColumnType::Integer);
@@ -100,7 +100,7 @@ public:
Sqlite::Table table; Sqlite::Table table;
table.setUseIfNotExists(true); table.setUseIfNotExists(true);
table.setName("sources"); table.setName("sources");
table.addColumn("sourceId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey); table.addColumn("sourceId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}});
const Sqlite::Column &directoryIdColumn = table.addColumn("directoryId", Sqlite::ColumnType::Integer); const Sqlite::Column &directoryIdColumn = table.addColumn("directoryId", Sqlite::ColumnType::Integer);
const Sqlite::Column &sourceNameColumn = table.addColumn("sourceName", Sqlite::ColumnType::Text); const Sqlite::Column &sourceNameColumn = table.addColumn("sourceName", Sqlite::ColumnType::Text);
table.addUniqueIndex({directoryIdColumn, sourceNameColumn}); table.addUniqueIndex({directoryIdColumn, sourceNameColumn});
@@ -113,7 +113,7 @@ public:
Sqlite::Table table; Sqlite::Table table;
table.setUseIfNotExists(true); table.setUseIfNotExists(true);
table.setName("directories"); table.setName("directories");
table.addColumn("directoryId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey); table.addColumn("directoryId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}});
const Sqlite::Column &directoryPathColumn = table.addColumn("directoryPath", Sqlite::ColumnType::Text); const Sqlite::Column &directoryPathColumn = table.addColumn("directoryPath", Sqlite::ColumnType::Text);
table.addUniqueIndex({directoryPathColumn}); table.addUniqueIndex({directoryPathColumn});
@@ -125,7 +125,7 @@ public:
Sqlite::Table table; Sqlite::Table table;
table.setUseIfNotExists(true); table.setUseIfNotExists(true);
table.setName("projectParts"); table.setName("projectParts");
table.addColumn("projectPartId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey); table.addColumn("projectPartId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}});
const Sqlite::Column &projectPartNameColumn = table.addColumn("projectPartName", Sqlite::ColumnType::Text); const Sqlite::Column &projectPartNameColumn = table.addColumn("projectPartName", Sqlite::ColumnType::Text);
table.addColumn("toolChainArguments", Sqlite::ColumnType::Text); table.addColumn("toolChainArguments", Sqlite::ColumnType::Text);
table.addColumn("compilerMacros", Sqlite::ColumnType::Text); table.addColumn("compilerMacros", Sqlite::ColumnType::Text);
@@ -160,7 +160,7 @@ public:
Sqlite::Table table; Sqlite::Table table;
table.setUseIfNotExists(true); table.setUseIfNotExists(true);
table.setName("usedMacros"); table.setName("usedMacros");
table.addColumn("usedMacroId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey); table.addColumn("usedMacroId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}});
const Sqlite::Column &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer); const Sqlite::Column &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer);
const Sqlite::Column &macroNameColumn = table.addColumn("macroName", Sqlite::ColumnType::Text); const Sqlite::Column &macroNameColumn = table.addColumn("macroName", Sqlite::ColumnType::Text);
table.addIndex({sourceIdColumn, macroNameColumn}); table.addIndex({sourceIdColumn, macroNameColumn});
@@ -174,9 +174,7 @@ public:
Sqlite::Table table; Sqlite::Table table;
table.setUseIfNotExists(true); table.setUseIfNotExists(true);
table.setName("fileStatuses"); table.setName("fileStatuses");
table.addColumn("sourceId", table.addColumn("sourceId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}});
Sqlite::ColumnType::Integer,
Sqlite::Contraint::PrimaryKey);
table.addColumn("size", Sqlite::ColumnType::Integer); table.addColumn("size", Sqlite::ColumnType::Integer);
table.addColumn("lastModified", Sqlite::ColumnType::Integer); table.addColumn("lastModified", Sqlite::ColumnType::Integer);
table.addColumn("indexingTimeStamp", Sqlite::ColumnType::Integer); table.addColumn("indexingTimeStamp", Sqlite::ColumnType::Integer);
@@ -201,7 +199,7 @@ public:
Sqlite::Table table; Sqlite::Table table;
table.setUseIfNotExists(true); table.setUseIfNotExists(true);
table.setName("precompiledHeaders"); table.setName("precompiledHeaders");
table.addColumn("projectPartId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey); table.addColumn("projectPartId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}});
table.addColumn("projectPchPath", Sqlite::ColumnType::Text); table.addColumn("projectPchPath", Sqlite::ColumnType::Text);
table.addColumn("projectPchBuildTime", Sqlite::ColumnType::Integer); table.addColumn("projectPchBuildTime", Sqlite::ColumnType::Integer);
table.addColumn("systemPchPath", Sqlite::ColumnType::Text); table.addColumn("systemPchPath", Sqlite::ColumnType::Text);

View File

@@ -41,16 +41,11 @@ void CreateTableSqlStatementBuilder::setTableName(Utils::SmallString &&tableName
void CreateTableSqlStatementBuilder::addColumn(Utils::SmallStringView columnName, void CreateTableSqlStatementBuilder::addColumn(Utils::SmallStringView columnName,
ColumnType columnType, ColumnType columnType,
Contraint constraint, Constraints &&constraints)
ForeignKey &&foreignKey)
{ {
m_sqlStatementBuilder.clear(); m_sqlStatementBuilder.clear();
m_columns.emplace_back(Utils::SmallStringView{}, m_columns.emplace_back(Utils::SmallStringView{}, columnName, columnType, std::move(constraints));
columnName,
columnType,
constraint,
std::move(foreignKey));
} }
void CreateTableSqlStatementBuilder::setColumns(const SqliteColumns &columns) void CreateTableSqlStatementBuilder::setColumns(const SqliteColumns &columns)
@@ -121,8 +116,19 @@ Utils::SmallStringView actionToText(ForeignKeyAction action)
return ""; return "";
} }
void appendForeignKey(Utils::SmallString &columnDefinitionString, const ForeignKey &foreignKey) class ContraintsVisiter
{ {
public:
ContraintsVisiter(Utils::SmallString &columnDefinitionString)
: columnDefinitionString(columnDefinitionString)
{}
void operator()(const Unique &) { columnDefinitionString.append(" UNIQUE"); }
void operator()(const PrimaryKey &) { columnDefinitionString.append(" PRIMARY KEY"); }
void operator()(const ForeignKey &foreignKey)
{
columnDefinitionString.append(" REFERENCES "); columnDefinitionString.append(" REFERENCES ");
columnDefinitionString.append(foreignKey.table); columnDefinitionString.append(foreignKey.table);
@@ -144,7 +150,56 @@ void appendForeignKey(Utils::SmallString &columnDefinitionString, const ForeignK
if (foreignKey.enforcement == Enforment::Deferred) if (foreignKey.enforcement == Enforment::Deferred)
columnDefinitionString.append(" DEFERRABLE INITIALLY DEFERRED"); columnDefinitionString.append(" DEFERRABLE INITIALLY DEFERRED");
} }
void operator()(const NotNull &) { columnDefinitionString.append(" NOT NULL"); }
void operator()(const DefaultValue &defaultValue)
{
columnDefinitionString.append(" DEFAULT ");
switch (defaultValue.value.type()) {
case Sqlite::ValueType::Integer:
columnDefinitionString.append(
Utils::SmallString::number(defaultValue.value.toInteger()));
break;
case Sqlite::ValueType::Float:
columnDefinitionString.append(Utils::SmallString::number(defaultValue.value.toFloat()));
break;
case Sqlite::ValueType::String:
columnDefinitionString.append("\"");
columnDefinitionString.append(defaultValue.value.toStringView());
columnDefinitionString.append("\"");
break;
}
}
void operator()(const DefaultExpression &defaultexpression)
{
columnDefinitionString.append(" DEFAULT (");
columnDefinitionString.append(defaultexpression.expression);
columnDefinitionString.append(")");
}
void operator()(const Collate &collate)
{
columnDefinitionString.append(" COLLATE ");
columnDefinitionString.append(collate.collation);
}
void operator()(const GeneratedAlways &generatedAlways)
{
columnDefinitionString.append(" GENERATED ALWAYS AS (");
columnDefinitionString.append(generatedAlways.expression);
columnDefinitionString.append(")");
if (generatedAlways.storage == Sqlite::GeneratedAlwaysStorage::Virtual)
columnDefinitionString.append(" VIRTUAL");
else
columnDefinitionString.append(" STORED");
}
Utils::SmallString &columnDefinitionString;
};
} // namespace } // namespace
void CreateTableSqlStatementBuilder::bindColumnDefinitions() const void CreateTableSqlStatementBuilder::bindColumnDefinitions() const
{ {
@@ -154,19 +209,10 @@ void CreateTableSqlStatementBuilder::bindColumnDefinitions() const
for (const Column &column : m_columns) { for (const Column &column : m_columns) {
Utils::SmallString columnDefinitionString = {column.name, " ", column.typeString()}; Utils::SmallString columnDefinitionString = {column.name, " ", column.typeString()};
switch (column.constraint) { ContraintsVisiter visiter{columnDefinitionString};
case Contraint::PrimaryKey:
columnDefinitionString.append(" PRIMARY KEY"); for (const Constraint &constraint : column.constraints)
break; mpark::visit(visiter, constraint);
case Contraint::Unique:
columnDefinitionString.append(" UNIQUE");
break;
case Contraint::ForeignKey:
appendForeignKey(columnDefinitionString, column.foreignKey);
break;
case Contraint::NoConstraint:
break;
}
columnDefinitionStrings.push_back(columnDefinitionString); columnDefinitionStrings.push_back(columnDefinitionString);
} }

View File

@@ -36,10 +36,10 @@ public:
CreateTableSqlStatementBuilder(); CreateTableSqlStatementBuilder();
void setTableName(Utils::SmallString &&tableName); void setTableName(Utils::SmallString &&tableName);
void addColumn(Utils::SmallStringView columnName, void addColumn(Utils::SmallStringView columnName,
ColumnType columnType, ColumnType columnType,
Contraint constraint = Contraint::NoConstraint, Constraints &&constraints = {});
ForeignKey &&foreignKey = {});
void setColumns(const SqliteColumns &columns); void setColumns(const SqliteColumns &columns);
void setUseWithoutRowId(bool useWithoutRowId); void setUseWithoutRowId(bool useWithoutRowId);
void setUseIfNotExists(bool useIfNotExists); void setUseIfNotExists(bool useIfNotExists);

View File

@@ -27,56 +27,135 @@
#include "sqliteforeignkey.h" #include "sqliteforeignkey.h"
#include <sqlitevalue.h>
#include <utils/smallstring.h> #include <utils/smallstring.h>
#include <utils/variant.h>
#include <functional> #include <functional>
namespace Sqlite { namespace Sqlite {
class Unique
{
friend bool operator==(Unique, Unique) { return true; }
};
class PrimaryKey
{
friend bool operator==(PrimaryKey, PrimaryKey) { return true; }
};
class NotNull
{
friend bool operator==(NotNull, NotNull) { return true; }
};
class DefaultValue
{
public:
DefaultValue(long long value)
: value(value)
{}
DefaultValue(double value)
: value(value)
{}
DefaultValue(Utils::SmallStringView value)
: value(value)
{}
friend bool operator==(const DefaultValue &first, const DefaultValue &second)
{
return first.value == second.value;
}
public:
Sqlite::Value value;
};
class DefaultExpression
{
public:
DefaultExpression(Utils::SmallStringView expression)
: expression(expression)
{}
friend bool operator==(const DefaultExpression &first, const DefaultExpression &second)
{
return first.expression == second.expression;
}
public:
Utils::SmallString expression;
};
class Collate
{
public:
Collate(Utils::SmallStringView collation)
: collation(collation)
{}
friend bool operator==(const Collate &first, const Collate &second)
{
return first.collation == second.collation;
}
public:
Utils::SmallString collation;
};
enum class GeneratedAlwaysStorage { Stored, Virtual };
class GeneratedAlways
{
public:
GeneratedAlways(Utils::SmallStringView expression, GeneratedAlwaysStorage storage)
: expression(expression)
, storage(storage)
{}
friend bool operator==(const GeneratedAlways &first, const GeneratedAlways &second)
{
return first.expression == second.expression;
}
public:
Utils::SmallString expression;
GeneratedAlwaysStorage storage = {};
};
using Constraint = Utils::variant<Unique,
PrimaryKey,
ForeignKey,
NotNull,
DefaultValue,
DefaultExpression,
Collate,
GeneratedAlways>;
using Constraints = std::vector<Constraint>;
class Column class Column
{ {
public: public:
Column() = default; Column() = default;
Column(Utils::SmallStringView tableName,
Utils::SmallStringView name,
ColumnType type = ColumnType::Numeric,
Contraint constraint = Contraint::NoConstraint,
ForeignKey &&foreignKey = {})
: foreignKey(std::move(foreignKey))
, name(name)
, tableName(tableName)
, type(type)
, constraint(constraint)
{}
Column(Utils::SmallStringView tableName, Column(Utils::SmallStringView tableName,
Utils::SmallStringView name, Utils::SmallStringView name,
ColumnType type, ColumnType type,
Contraint constraint, Constraints &&constraints = {})
Utils::SmallStringView foreignKeyTable, : constraints(std::move(constraints))
Utils::SmallStringView foreignKeycolumn,
ForeignKeyAction foreignKeyUpdateAction,
ForeignKeyAction foreignKeyDeleteAction,
Enforment foreignKeyEnforcement)
: foreignKey(foreignKeyTable,
foreignKeycolumn,
foreignKeyUpdateAction,
foreignKeyDeleteAction,
foreignKeyEnforcement)
, name(name) , name(name)
, tableName(tableName) , tableName(tableName)
, type(type) , type(type)
, constraint(constraint)
{} {}
void clear() void clear()
{ {
name.clear(); name.clear();
type = ColumnType::Numeric; type = ColumnType::Numeric;
constraint = Contraint::NoConstraint; constraints = {};
foreignKey = {};
} }
Utils::SmallString typeString() const Utils::SmallString typeString() const
@@ -100,16 +179,14 @@ public:
friend bool operator==(const Column &first, const Column &second) friend bool operator==(const Column &first, const Column &second)
{ {
return first.name == second.name && first.type == second.type return first.name == second.name && first.type == second.type
&& first.constraint && first.constraints == second.constraints && first.tableName == second.tableName;
== second.constraint /* && first.foreignKey == second.foreignKey*/;
} }
public: public:
ForeignKey foreignKey; Constraints constraints;
Utils::SmallString name; Utils::SmallString name;
Utils::SmallString tableName; Utils::SmallString tableName;
ColumnType type = ColumnType::Numeric; ColumnType type = ColumnType::Numeric;
Contraint constraint = Contraint::NoConstraint;
}; // namespace Sqlite }; // namespace Sqlite
using SqliteColumns = std::vector<Column>; using SqliteColumns = std::vector<Column>;

View File

@@ -48,7 +48,7 @@ enum class ColumnType : char
None None
}; };
enum class Contraint : char { NoConstraint, PrimaryKey, Unique, ForeignKey }; enum class ConstraintType : char { NoConstraint, PrimaryKey, Unique, ForeignKey };
enum class ForeignKeyAction : char { NoAction, Restrict, SetNull, SetDefault, Cascade }; enum class ForeignKeyAction : char { NoAction, Restrict, SetNull, SetDefault, Cascade };

View File

@@ -73,9 +73,9 @@ public:
Column &addColumn(Utils::SmallStringView name, Column &addColumn(Utils::SmallStringView name,
ColumnType type = ColumnType::Numeric, ColumnType type = ColumnType::Numeric,
Contraint constraint = Contraint::NoConstraint) Constraints &&constraints = {})
{ {
m_sqliteColumns.emplace_back(m_tableName, name, type, constraint); m_sqliteColumns.emplace_back(m_tableName, name, type, std::move(constraints));
return m_sqliteColumns.back(); return m_sqliteColumns.back();
} }
@@ -85,17 +85,16 @@ public:
ForeignKeyAction foreignKeyupdateAction = {}, ForeignKeyAction foreignKeyupdateAction = {},
ForeignKeyAction foreignKeyDeleteAction = {}, ForeignKeyAction foreignKeyDeleteAction = {},
Enforment foreignKeyEnforcement = {}, Enforment foreignKeyEnforcement = {},
Constraints &&constraints = {},
ColumnType type = ColumnType::Integer) ColumnType type = ColumnType::Integer)
{ {
m_sqliteColumns.emplace_back(m_tableName, constraints.emplace_back(ForeignKey{referencedTable.name(),
name,
type,
Contraint::ForeignKey,
referencedTable.name(),
"", "",
foreignKeyupdateAction, foreignKeyupdateAction,
foreignKeyDeleteAction, foreignKeyDeleteAction,
foreignKeyEnforcement); foreignKeyEnforcement});
m_sqliteColumns.emplace_back(m_tableName, name, type, std::move(constraints));
return m_sqliteColumns.back(); return m_sqliteColumns.back();
} }
@@ -104,20 +103,22 @@ public:
const Column &referencedColumn, const Column &referencedColumn,
ForeignKeyAction foreignKeyupdateAction = {}, ForeignKeyAction foreignKeyupdateAction = {},
ForeignKeyAction foreignKeyDeleteAction = {}, ForeignKeyAction foreignKeyDeleteAction = {},
Enforment foreignKeyEnforcement = {}) Enforment foreignKeyEnforcement = {},
Constraints &&constraints = {})
{ {
if (referencedColumn.constraint != Contraint::Unique) if (!constainsUniqueIndex(referencedColumn.constraints))
throw ForeignKeyColumnIsNotUnique("Foreign column key must be unique!"); throw ForeignKeyColumnIsNotUnique("Foreign column key must be unique!");
constraints.emplace_back(ForeignKey{referencedColumn.tableName,
referencedColumn.name,
foreignKeyupdateAction,
foreignKeyDeleteAction,
foreignKeyEnforcement});
m_sqliteColumns.emplace_back(m_tableName, m_sqliteColumns.emplace_back(m_tableName,
name, name,
referencedColumn.type, referencedColumn.type,
Contraint::ForeignKey, std::move(constraints));
referencedColumn.tableName,
referencedColumn.name,
foreignKeyupdateAction,
foreignKeyDeleteAction,
foreignKeyEnforcement);
return m_sqliteColumns.back(); return m_sqliteColumns.back();
} }
@@ -181,6 +182,16 @@ public:
&& first.m_sqliteColumns == second.m_sqliteColumns; && first.m_sqliteColumns == second.m_sqliteColumns;
} }
static bool constainsUniqueIndex(const Constraints &constraints)
{
return std::find_if(constraints.begin(),
constraints.end(),
[](const Constraint &constraint) {
return Utils::holds_alternative<Unique>(constraint);
})
!= constraints.end();
}
private: private:
Utils::SmallStringVector sqliteColumnNames(const SqliteColumnConstReferences &columns) Utils::SmallStringVector sqliteColumnNames(const SqliteColumnConstReferences &columns)
{ {

View File

@@ -123,7 +123,7 @@ public:
Sqlite::Table table; Sqlite::Table table;
table.setName("newSymbols"); table.setName("newSymbols");
table.setUseTemporaryTable(true); table.setUseTemporaryTable(true);
table.addColumn("temporarySymbolId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey); table.addColumn("temporarySymbolId", Sqlite::ColumnType::Integer, {Sqlite::PrimaryKey{}});
const Sqlite::Column &symbolIdColumn = table.addColumn("symbolId", Sqlite::ColumnType::Integer); const Sqlite::Column &symbolIdColumn = table.addColumn("symbolId", Sqlite::ColumnType::Integer);
const Sqlite::Column &usrColumn = table.addColumn("usr", Sqlite::ColumnType::Text); const Sqlite::Column &usrColumn = table.addColumn("usr", Sqlite::ColumnType::Text);
const Sqlite::Column &symbolNameColumn = table.addColumn("symbolName", Sqlite::ColumnType::Text); const Sqlite::Column &symbolNameColumn = table.addColumn("symbolName", Sqlite::ColumnType::Text);

View File

@@ -32,19 +32,38 @@ namespace {
using Sqlite::Column; using Sqlite::Column;
using Sqlite::ColumnType; using Sqlite::ColumnType;
using Sqlite::Contraint; using Sqlite::ConstraintType;
using Sqlite::Enforment; using Sqlite::Enforment;
using Sqlite::ForeignKey;
using Sqlite::ForeignKeyAction; using Sqlite::ForeignKeyAction;
using Sqlite::JournalMode; using Sqlite::JournalMode;
using Sqlite::OpenMode; using Sqlite::OpenMode;
using Sqlite::PrimaryKey;
using Sqlite::SqliteColumns; using Sqlite::SqliteColumns;
using Sqlite::SqlStatementBuilderException; using Sqlite::SqlStatementBuilderException;
using Sqlite::Unique;
class CreateTableSqlStatementBuilder : public ::testing::Test class CreateTableSqlStatementBuilder : public ::testing::Test
{ {
protected: protected:
void bindValues(); void bindValues()
static SqliteColumns createColumns(); {
builder.clear();
builder.setTableName("test");
builder.addColumn("id", ColumnType::Integer, {PrimaryKey{}});
builder.addColumn("name", ColumnType::Text);
builder.addColumn("number", ColumnType::Numeric);
}
static SqliteColumns createColumns()
{
SqliteColumns columns;
columns.emplace_back("", "id", ColumnType::Integer, Sqlite::Constraints{PrimaryKey{}});
columns.emplace_back("", "name", ColumnType::Text);
columns.emplace_back("", "number", ColumnType::Numeric);
return columns;
}
protected: protected:
Sqlite::CreateTableSqlStatementBuilder builder; Sqlite::CreateTableSqlStatementBuilder builder;
@@ -158,7 +177,7 @@ TEST_F(CreateTableSqlStatementBuilder, UniqueContraint)
builder.clear(); builder.clear();
builder.setTableName("test"); builder.setTableName("test");
builder.addColumn("id", ColumnType::Integer, Contraint::Unique); builder.addColumn("id", ColumnType::Integer, {Unique{}});
ASSERT_THAT(builder.sqlStatement(), ASSERT_THAT(builder.sqlStatement(),
"CREATE TABLE test(id INTEGER UNIQUE)"); "CREATE TABLE test(id INTEGER UNIQUE)");
@@ -168,7 +187,7 @@ TEST_F(CreateTableSqlStatementBuilder, IfNotExitsModifier)
{ {
builder.clear(); builder.clear();
builder.setTableName("test"); builder.setTableName("test");
builder.addColumn("id", ColumnType::Integer, Contraint::NoConstraint); builder.addColumn("id", ColumnType::Integer, {});
builder.setUseIfNotExists(true); builder.setUseIfNotExists(true);
@@ -180,7 +199,7 @@ TEST_F(CreateTableSqlStatementBuilder, TemporaryTable)
{ {
builder.clear(); builder.clear();
builder.setTableName("test"); builder.setTableName("test");
builder.addColumn("id", ColumnType::Integer, Contraint::NoConstraint); builder.addColumn("id", ColumnType::Integer, {});
builder.setUseTemporaryTable(true); builder.setUseTemporaryTable(true);
@@ -188,31 +207,12 @@ TEST_F(CreateTableSqlStatementBuilder, TemporaryTable)
"CREATE TEMPORARY TABLE test(id INTEGER)"); "CREATE TEMPORARY TABLE test(id INTEGER)");
} }
void CreateTableSqlStatementBuilder::bindValues()
{
builder.clear();
builder.setTableName("test");
builder.addColumn("id", ColumnType::Integer, Contraint::PrimaryKey);
builder.addColumn("name", ColumnType::Text);
builder.addColumn("number",ColumnType:: Numeric);
}
SqliteColumns CreateTableSqlStatementBuilder::createColumns()
{
SqliteColumns columns;
columns.emplace_back("", "id", ColumnType::Integer, Contraint::PrimaryKey);
columns.emplace_back("", "name", ColumnType::Text);
columns.emplace_back("", "number", ColumnType::Numeric);
return columns;
}
TEST_F(CreateTableSqlStatementBuilder, ForeignKeyWithoutColumn) TEST_F(CreateTableSqlStatementBuilder, ForeignKeyWithoutColumn)
{ {
builder.clear(); builder.clear();
builder.setTableName("test"); builder.setTableName("test");
builder.addColumn("id", ColumnType::Integer, Contraint::ForeignKey, {"otherTable", ""}); builder.addColumn("id", ColumnType::Integer, {ForeignKey{"otherTable", ""}});
ASSERT_THAT(builder.sqlStatement(), "CREATE TABLE test(id INTEGER REFERENCES otherTable)"); ASSERT_THAT(builder.sqlStatement(), "CREATE TABLE test(id INTEGER REFERENCES otherTable)");
} }
@@ -222,7 +222,7 @@ TEST_F(CreateTableSqlStatementBuilder, ForeignKeyWithColumn)
builder.clear(); builder.clear();
builder.setTableName("test"); builder.setTableName("test");
builder.addColumn("id", ColumnType::Integer, Contraint::ForeignKey, {"otherTable", "otherColumn"}); builder.addColumn("id", ColumnType::Integer, {ForeignKey{"otherTable", "otherColumn"}});
ASSERT_THAT(builder.sqlStatement(), ASSERT_THAT(builder.sqlStatement(),
"CREATE TABLE test(id INTEGER REFERENCES otherTable(otherColumn))"); "CREATE TABLE test(id INTEGER REFERENCES otherTable(otherColumn))");
@@ -233,7 +233,7 @@ TEST_F(CreateTableSqlStatementBuilder, ForeignKeyUpdateNoAction)
builder.clear(); builder.clear();
builder.setTableName("test"); builder.setTableName("test");
builder.addColumn("id", ColumnType::Integer, Contraint::ForeignKey, {"otherTable", "otherColumn"}); builder.addColumn("id", ColumnType::Integer, {ForeignKey{"otherTable", "otherColumn"}});
ASSERT_THAT(builder.sqlStatement(), ASSERT_THAT(builder.sqlStatement(),
"CREATE TABLE test(id INTEGER REFERENCES otherTable(otherColumn))"); "CREATE TABLE test(id INTEGER REFERENCES otherTable(otherColumn))");
@@ -246,8 +246,7 @@ TEST_F(CreateTableSqlStatementBuilder, ForeignKeyUpdateRestrict)
builder.addColumn("id", builder.addColumn("id",
ColumnType::Integer, ColumnType::Integer,
Contraint::ForeignKey, {ForeignKey{"otherTable", "otherColumn", ForeignKeyAction::Restrict}});
{"otherTable", "otherColumn", ForeignKeyAction::Restrict});
ASSERT_THAT( ASSERT_THAT(
builder.sqlStatement(), builder.sqlStatement(),
@@ -261,8 +260,7 @@ TEST_F(CreateTableSqlStatementBuilder, ForeignKeyUpdateSetNull)
builder.addColumn("id", builder.addColumn("id",
ColumnType::Integer, ColumnType::Integer,
Contraint::ForeignKey, {ForeignKey{"otherTable", "otherColumn", ForeignKeyAction::SetNull}});
{"otherTable", "otherColumn", ForeignKeyAction::SetNull});
ASSERT_THAT( ASSERT_THAT(
builder.sqlStatement(), builder.sqlStatement(),
@@ -276,8 +274,7 @@ TEST_F(CreateTableSqlStatementBuilder, ForeignKeyUpdateSetDefault)
builder.addColumn("id", builder.addColumn("id",
ColumnType::Integer, ColumnType::Integer,
Contraint::ForeignKey, {ForeignKey{"otherTable", "otherColumn", ForeignKeyAction::SetDefault}});
{"otherTable", "otherColumn", ForeignKeyAction::SetDefault});
ASSERT_THAT( ASSERT_THAT(
builder.sqlStatement(), builder.sqlStatement(),
@@ -291,8 +288,7 @@ TEST_F(CreateTableSqlStatementBuilder, ForeignKeyUpdateCascade)
builder.addColumn("id", builder.addColumn("id",
ColumnType::Integer, ColumnType::Integer,
Contraint::ForeignKey, {ForeignKey{"otherTable", "otherColumn", ForeignKeyAction::Cascade}});
{"otherTable", "otherColumn", ForeignKeyAction::Cascade});
ASSERT_THAT( ASSERT_THAT(
builder.sqlStatement(), builder.sqlStatement(),
@@ -304,7 +300,7 @@ TEST_F(CreateTableSqlStatementBuilder, ForeignKeyDeleteNoAction)
builder.clear(); builder.clear();
builder.setTableName("test"); builder.setTableName("test");
builder.addColumn("id", ColumnType::Integer, Contraint::ForeignKey, {"otherTable", "otherColumn"}); builder.addColumn("id", ColumnType::Integer, {ForeignKey{"otherTable", "otherColumn"}});
ASSERT_THAT(builder.sqlStatement(), ASSERT_THAT(builder.sqlStatement(),
"CREATE TABLE test(id INTEGER REFERENCES otherTable(otherColumn))"); "CREATE TABLE test(id INTEGER REFERENCES otherTable(otherColumn))");
@@ -317,8 +313,7 @@ TEST_F(CreateTableSqlStatementBuilder, ForeignKeyDeleteRestrict)
builder.addColumn("id", builder.addColumn("id",
ColumnType::Integer, ColumnType::Integer,
Contraint::ForeignKey, {ForeignKey{"otherTable", "otherColumn", {}, ForeignKeyAction::Restrict}});
{"otherTable", "otherColumn", {}, ForeignKeyAction::Restrict});
ASSERT_THAT( ASSERT_THAT(
builder.sqlStatement(), builder.sqlStatement(),
@@ -332,8 +327,7 @@ TEST_F(CreateTableSqlStatementBuilder, ForeignKeyDeleteSetNull)
builder.addColumn("id", builder.addColumn("id",
ColumnType::Integer, ColumnType::Integer,
Contraint::ForeignKey, {ForeignKey{"otherTable", "otherColumn", {}, ForeignKeyAction::SetNull}});
{"otherTable", "otherColumn", {}, ForeignKeyAction::SetNull});
ASSERT_THAT( ASSERT_THAT(
builder.sqlStatement(), builder.sqlStatement(),
@@ -347,8 +341,7 @@ TEST_F(CreateTableSqlStatementBuilder, ForeignKeyDeleteSetDefault)
builder.addColumn("id", builder.addColumn("id",
ColumnType::Integer, ColumnType::Integer,
Contraint::ForeignKey, {ForeignKey{"otherTable", "otherColumn", {}, ForeignKeyAction::SetDefault}});
{"otherTable", "otherColumn", {}, ForeignKeyAction::SetDefault});
ASSERT_THAT( ASSERT_THAT(
builder.sqlStatement(), builder.sqlStatement(),
@@ -362,8 +355,7 @@ TEST_F(CreateTableSqlStatementBuilder, ForeignKeyDeleteCascade)
builder.addColumn("id", builder.addColumn("id",
ColumnType::Integer, ColumnType::Integer,
Contraint::ForeignKey, {ForeignKey{"otherTable", "otherColumn", {}, ForeignKeyAction::Cascade}});
{"otherTable", "otherColumn", {}, ForeignKeyAction::Cascade});
ASSERT_THAT( ASSERT_THAT(
builder.sqlStatement(), builder.sqlStatement(),
@@ -377,11 +369,10 @@ TEST_F(CreateTableSqlStatementBuilder, ForeignKeyDeleteAndUpdateAction)
builder.addColumn("id", builder.addColumn("id",
ColumnType::Integer, ColumnType::Integer,
Contraint::ForeignKey, {ForeignKey{"otherTable",
{"otherTable",
"otherColumn", "otherColumn",
ForeignKeyAction::SetDefault, ForeignKeyAction::SetDefault,
ForeignKeyAction::Cascade}); ForeignKeyAction::Cascade}});
ASSERT_THAT(builder.sqlStatement(), ASSERT_THAT(builder.sqlStatement(),
"CREATE TABLE test(id INTEGER REFERENCES otherTable(otherColumn) ON UPDATE SET " "CREATE TABLE test(id INTEGER REFERENCES otherTable(otherColumn) ON UPDATE SET "
@@ -395,15 +386,118 @@ TEST_F(CreateTableSqlStatementBuilder, ForeignKeyDeferred)
builder.addColumn("id", builder.addColumn("id",
ColumnType::Integer, ColumnType::Integer,
Contraint::ForeignKey, {ForeignKey{"otherTable",
{"otherTable",
"otherColumn", "otherColumn",
ForeignKeyAction::SetDefault, ForeignKeyAction::SetDefault,
ForeignKeyAction::Cascade, ForeignKeyAction::Cascade,
Enforment::Deferred}); Enforment::Deferred}});
ASSERT_THAT(builder.sqlStatement(), ASSERT_THAT(builder.sqlStatement(),
"CREATE TABLE test(id INTEGER REFERENCES otherTable(otherColumn) ON UPDATE SET " "CREATE TABLE test(id INTEGER REFERENCES otherTable(otherColumn) ON UPDATE SET "
"DEFAULT ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)"); "DEFAULT ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)");
} }
TEST_F(CreateTableSqlStatementBuilder, NotNullConstraint)
{
builder.clear();
builder.setTableName("test");
builder.addColumn("id", ColumnType::Integer, {Sqlite::NotNull{}});
ASSERT_THAT(builder.sqlStatement(), "CREATE TABLE test(id INTEGER NOT NULL)");
}
TEST_F(CreateTableSqlStatementBuilder, NotNullAndUniqueConstraint)
{
builder.clear();
builder.setTableName("test");
builder.addColumn("id", ColumnType::Integer, {Sqlite::Unique{}, Sqlite::NotNull{}});
ASSERT_THAT(builder.sqlStatement(), "CREATE TABLE test(id INTEGER UNIQUE NOT NULL)");
}
TEST_F(CreateTableSqlStatementBuilder, DefaultValueInt)
{
builder.clear();
builder.setTableName("test");
builder.addColumn("id", ColumnType::Integer, {Sqlite::DefaultValue{1LL}});
ASSERT_THAT(builder.sqlStatement(), "CREATE TABLE test(id INTEGER DEFAULT 1)");
}
TEST_F(CreateTableSqlStatementBuilder, DefaultValueFloat)
{
builder.clear();
builder.setTableName("test");
builder.addColumn("id", ColumnType::Real, {Sqlite::DefaultValue{1.1}});
ASSERT_THAT(builder.sqlStatement(), "CREATE TABLE test(id REAL DEFAULT 1.100000)");
}
TEST_F(CreateTableSqlStatementBuilder, DefaultValueString)
{
builder.clear();
builder.setTableName("test");
builder.addColumn("id", ColumnType::Text, {Sqlite::DefaultValue{"foo"}});
ASSERT_THAT(builder.sqlStatement(), "CREATE TABLE test(id TEXT DEFAULT \"foo\")");
}
TEST_F(CreateTableSqlStatementBuilder, DefaultExpression)
{
builder.clear();
builder.setTableName("test");
builder.addColumn("id",
ColumnType::Integer,
{Sqlite::DefaultExpression{"SELECT name FROM foo WHERE id=?"}});
ASSERT_THAT(builder.sqlStatement(),
"CREATE TABLE test(id INTEGER DEFAULT (SELECT name FROM foo WHERE id=?))");
}
TEST_F(CreateTableSqlStatementBuilder, Collation)
{
builder.clear();
builder.setTableName("test");
builder.addColumn("id", ColumnType::Text, {Sqlite::Collate{"unicode"}});
ASSERT_THAT(builder.sqlStatement(), "CREATE TABLE test(id TEXT COLLATE unicode)");
}
TEST_F(CreateTableSqlStatementBuilder, GeneratedAlwaysStored)
{
builder.clear();
builder.setTableName("test");
builder.addColumn("id",
ColumnType::Text,
{Sqlite::GeneratedAlways{"SELECT name FROM foo WHERE id=?",
Sqlite::GeneratedAlwaysStorage::Stored}});
ASSERT_THAT(
builder.sqlStatement(),
"CREATE TABLE test(id TEXT GENERATED ALWAYS AS (SELECT name FROM foo WHERE id=?) STORED)");
}
TEST_F(CreateTableSqlStatementBuilder, GeneratedAlwaysVirtual)
{
builder.clear();
builder.setTableName("test");
builder.addColumn("id",
ColumnType::Text,
{Sqlite::GeneratedAlways{"SELECT name FROM foo WHERE id=?",
Sqlite::GeneratedAlwaysStorage::Virtual}});
ASSERT_THAT(builder.sqlStatement(),
"CREATE TABLE test(id TEXT GENERATED ALWAYS AS (SELECT name FROM foo WHERE id=?) "
"VIRTUAL)");
}
} // namespace } // namespace

View File

@@ -37,21 +37,27 @@ using testing::AnyOf;
using testing::Assign; using testing::Assign;
using testing::ByMove; using testing::ByMove;
using testing::ByRef; using testing::ByRef;
using testing::Contains;
using testing::ContainerEq; using testing::ContainerEq;
using testing::Contains;
using testing::ElementsAre; using testing::ElementsAre;
using testing::Eq;
using testing::Field; using testing::Field;
using testing::Ge;
using testing::Gt;
using testing::HasSubstr; using testing::HasSubstr;
using testing::InSequence; using testing::InSequence;
using testing::Invoke; using testing::Invoke;
using testing::IsEmpty; using testing::IsEmpty;
using testing::IsNull; using testing::IsNull;
using testing::Le;
using testing::Lt;
using testing::Matcher; using testing::Matcher;
using testing::Mock; using testing::Mock;
using testing::MockFunction; using testing::MockFunction;
using testing::Ne;
using testing::NiceMock; using testing::NiceMock;
using testing::NotNull;
using testing::Not; using testing::Not;
using testing::NotNull;
using testing::Pair; using testing::Pair;
using testing::PrintToString; using testing::PrintToString;
using testing::Property; using testing::Property;
@@ -64,10 +70,4 @@ using testing::StrEq;
using testing::Throw; using testing::Throw;
using testing::TypedEq; using testing::TypedEq;
using testing::UnorderedElementsAre; using testing::UnorderedElementsAre;
using testing::VariantWith;
using testing::Eq;
using testing::Ge;
using testing::Gt;
using testing::Le;
using testing::Lt;
using testing::Ne;

View File

@@ -30,7 +30,7 @@
namespace { namespace {
using Sqlite::ColumnType; using Sqlite::ColumnType;
using Sqlite::Contraint; using Sqlite::ConstraintType;
using Sqlite::JournalMode; using Sqlite::JournalMode;
using Sqlite::OpenMode; using Sqlite::OpenMode;
using Column = Sqlite::Column; using Column = Sqlite::Column;
@@ -51,13 +51,7 @@ TEST_F(SqliteColumn, DefaultConstruct)
AllOf(Field(&Column::name, IsEmpty()), AllOf(Field(&Column::name, IsEmpty()),
Field(&Column::tableName, IsEmpty()), Field(&Column::tableName, IsEmpty()),
Field(&Column::type, ColumnType::Numeric), Field(&Column::type, ColumnType::Numeric),
Field(&Column::constraint, Contraint::NoConstraint), Field(&Column::constraints, IsEmpty())));
Field(&Column::foreignKey,
AllOf(Field(&ForeignKey::table, IsEmpty()),
Field(&ForeignKey::column, IsEmpty()),
Field(&ForeignKey::updateAction, ForeignKeyAction::NoAction),
Field(&ForeignKey::deleteAction, ForeignKeyAction::NoAction),
Field(&ForeignKey::enforcement, Enforment::Immediate)))));
} }
TEST_F(SqliteColumn, Clear) TEST_F(SqliteColumn, Clear)
@@ -65,11 +59,7 @@ TEST_F(SqliteColumn, Clear)
column.name = "foo"; column.name = "foo";
column.name = "foo"; column.name = "foo";
column.type = ColumnType::Text; column.type = ColumnType::Text;
column.constraint = Contraint::ForeignKey; column.constraints = {Sqlite::PrimaryKey{}};
column.foreignKey.table = "bar";
column.foreignKey.column = "hmm";
column.foreignKey.updateAction = ForeignKeyAction::Cascade;
column.foreignKey.deleteAction = ForeignKeyAction::SetNull;
column.clear(); column.clear();
@@ -77,13 +67,7 @@ TEST_F(SqliteColumn, Clear)
AllOf(Field(&Column::name, IsEmpty()), AllOf(Field(&Column::name, IsEmpty()),
Field(&Column::tableName, IsEmpty()), Field(&Column::tableName, IsEmpty()),
Field(&Column::type, ColumnType::Numeric), Field(&Column::type, ColumnType::Numeric),
Field(&Column::constraint, Contraint::NoConstraint), Field(&Column::constraints, IsEmpty())));
Field(&Column::foreignKey,
AllOf(Field(&ForeignKey::table, IsEmpty()),
Field(&ForeignKey::column, IsEmpty()),
Field(&ForeignKey::updateAction, ForeignKeyAction::NoAction),
Field(&ForeignKey::deleteAction, ForeignKeyAction::NoAction),
Field(&ForeignKey::enforcement, Enforment::Immediate)))));
} }
TEST_F(SqliteColumn, Constructor) TEST_F(SqliteColumn, Constructor)
@@ -91,24 +75,23 @@ TEST_F(SqliteColumn, Constructor)
column = Sqlite::Column{"table", column = Sqlite::Column{"table",
"column", "column",
ColumnType::Text, ColumnType::Text,
Contraint::ForeignKey, {ForeignKey{"referencedTable",
{"referencedTable",
"referencedColumn", "referencedColumn",
ForeignKeyAction::SetNull, ForeignKeyAction::SetNull,
ForeignKeyAction::Cascade, ForeignKeyAction::Cascade,
Enforment::Deferred}}; Enforment::Deferred}}};
ASSERT_THAT(column, ASSERT_THAT(column,
AllOf(Field(&Column::name, Eq("column")), AllOf(Field(&Column::name, Eq("column")),
Field(&Column::tableName, Eq("table")), Field(&Column::tableName, Eq("table")),
Field(&Column::type, ColumnType::Text), Field(&Column::type, ColumnType::Text),
Field(&Column::constraint, Contraint::ForeignKey), Field(&Column::constraints,
Field(&Column::foreignKey, ElementsAre(VariantWith<ForeignKey>(
AllOf(Field(&ForeignKey::table, Eq("referencedTable")), AllOf(Field(&ForeignKey::table, Eq("referencedTable")),
Field(&ForeignKey::column, Eq("referencedColumn")), Field(&ForeignKey::column, Eq("referencedColumn")),
Field(&ForeignKey::updateAction, ForeignKeyAction::SetNull), Field(&ForeignKey::updateAction, ForeignKeyAction::SetNull),
Field(&ForeignKey::deleteAction, ForeignKeyAction::Cascade), Field(&ForeignKey::deleteAction, ForeignKeyAction::Cascade),
Field(&ForeignKey::enforcement, Enforment::Deferred))))); Field(&ForeignKey::enforcement, Enforment::Deferred)))))));
} }
TEST_F(SqliteColumn, FlatConstructor) TEST_F(SqliteColumn, FlatConstructor)
@@ -116,24 +99,23 @@ TEST_F(SqliteColumn, FlatConstructor)
column = Sqlite::Column{"table", column = Sqlite::Column{"table",
"column", "column",
ColumnType::Text, ColumnType::Text,
Contraint::ForeignKey, {ForeignKey{"referencedTable",
"referencedTable",
"referencedColumn", "referencedColumn",
ForeignKeyAction::SetNull, ForeignKeyAction::SetNull,
ForeignKeyAction::Cascade, ForeignKeyAction::Cascade,
Enforment::Deferred}; Enforment::Deferred}}};
ASSERT_THAT(column, ASSERT_THAT(column,
AllOf(Field(&Column::name, Eq("column")), AllOf(Field(&Column::name, Eq("column")),
Field(&Column::tableName, Eq("table")), Field(&Column::tableName, Eq("table")),
Field(&Column::type, ColumnType::Text), Field(&Column::type, ColumnType::Text),
Field(&Column::constraint, Contraint::ForeignKey), Field(&Column::constraints,
Field(&Column::foreignKey, ElementsAre(VariantWith<ForeignKey>(
AllOf(Field(&ForeignKey::table, Eq("referencedTable")), AllOf(Field(&ForeignKey::table, Eq("referencedTable")),
Field(&ForeignKey::column, Eq("referencedColumn")), Field(&ForeignKey::column, Eq("referencedColumn")),
Field(&ForeignKey::updateAction, ForeignKeyAction::SetNull), Field(&ForeignKey::updateAction, ForeignKeyAction::SetNull),
Field(&ForeignKey::deleteAction, ForeignKeyAction::Cascade), Field(&ForeignKey::deleteAction, ForeignKeyAction::Cascade),
Field(&ForeignKey::enforcement, Enforment::Deferred))))); Field(&ForeignKey::enforcement, Enforment::Deferred)))))));
} }
} // namespace } // namespace

View File

@@ -39,7 +39,7 @@ namespace {
using Backend = Sqlite::DatabaseBackend; using Backend = Sqlite::DatabaseBackend;
using Sqlite::ColumnType; using Sqlite::ColumnType;
using Sqlite::Contraint; using Sqlite::ConstraintType;
using Sqlite::JournalMode; using Sqlite::JournalMode;
using Sqlite::OpenMode; using Sqlite::OpenMode;
using Sqlite::TextEncoding; using Sqlite::TextEncoding;

View File

@@ -34,7 +34,7 @@ namespace {
using Sqlite::Column; using Sqlite::Column;
using Sqlite::ColumnType; using Sqlite::ColumnType;
using Sqlite::Contraint; using Sqlite::ConstraintType;
using Sqlite::Database; using Sqlite::Database;
using Sqlite::Enforment; using Sqlite::Enforment;
using Sqlite::ForeignKey; using Sqlite::ForeignKey;
@@ -136,9 +136,7 @@ TEST_F(SqliteTable, AddForeignKeyColumnWithColumnCalls)
{ {
Sqlite::Table foreignTable; Sqlite::Table foreignTable;
foreignTable.setName("foreignTable"); foreignTable.setName("foreignTable");
auto &foreignColumn = foreignTable.addColumn("foreignColumn", auto &foreignColumn = foreignTable.addColumn("foreignColumn", ColumnType::Text, {Sqlite::Unique{}});
ColumnType::Text,
Sqlite::Contraint::Unique);
table.setName(tableName); table.setName(tableName);
table.addForeignKeyColumn("name", table.addForeignKeyColumn("name",
foreignColumn, foreignColumn,
@@ -159,19 +157,14 @@ TEST_F(SqliteTable, AddColumn)
{ {
table.setName(tableName); table.setName(tableName);
auto &column = table.addColumn("name", ColumnType::Text, Sqlite::Contraint::Unique); auto &column = table.addColumn("name", ColumnType::Text, {Sqlite::Unique{}});
ASSERT_THAT(column, ASSERT_THAT(column,
AllOf(Field(&Column::name, Eq("name")), AllOf(Field(&Column::name, Eq("name")),
Field(&Column::tableName, Eq(tableName)), Field(&Column::tableName, Eq(tableName)),
Field(&Column::type, ColumnType::Text), Field(&Column::type, ColumnType::Text),
Field(&Column::constraint, Contraint::Unique), Field(&Column::constraints,
Field(&Column::foreignKey, ElementsAre(VariantWith<Sqlite::Unique>(Eq(Sqlite::Unique{}))))));
AllOf(Field(&ForeignKey::table, IsEmpty()),
Field(&ForeignKey::column, IsEmpty()),
Field(&ForeignKey::updateAction, ForeignKeyAction::NoAction),
Field(&ForeignKey::deleteAction, ForeignKeyAction::NoAction),
Field(&ForeignKey::enforcement, Enforment::Immediate)))));
} }
TEST_F(SqliteTable, AddForeignKeyColumnWithTable) TEST_F(SqliteTable, AddForeignKeyColumnWithTable)
@@ -191,22 +184,20 @@ TEST_F(SqliteTable, AddForeignKeyColumnWithTable)
AllOf(Field(&Column::name, Eq("name")), AllOf(Field(&Column::name, Eq("name")),
Field(&Column::tableName, Eq(tableName)), Field(&Column::tableName, Eq(tableName)),
Field(&Column::type, ColumnType::Integer), Field(&Column::type, ColumnType::Integer),
Field(&Column::constraint, Contraint::ForeignKey), Field(&Column::constraints,
Field(&Column::foreignKey, ElementsAre(VariantWith<ForeignKey>(
AllOf(Field(&ForeignKey::table, Eq("foreignTable")), AllOf(Field(&ForeignKey::table, Eq("foreignTable")),
Field(&ForeignKey::column, IsEmpty()), Field(&ForeignKey::column, IsEmpty()),
Field(&ForeignKey::updateAction, ForeignKeyAction::SetNull), Field(&ForeignKey::updateAction, ForeignKeyAction::SetNull),
Field(&ForeignKey::deleteAction, ForeignKeyAction::Cascade), Field(&ForeignKey::deleteAction, ForeignKeyAction::Cascade),
Field(&ForeignKey::enforcement, Enforment::Deferred))))); Field(&ForeignKey::enforcement, Enforment::Deferred)))))));
} }
TEST_F(SqliteTable, AddForeignKeyColumnWithColumn) TEST_F(SqliteTable, AddForeignKeyColumnWithColumn)
{ {
Sqlite::Table foreignTable; Sqlite::Table foreignTable;
foreignTable.setName("foreignTable"); foreignTable.setName("foreignTable");
auto &foreignColumn = foreignTable.addColumn("foreignColumn", auto &foreignColumn = foreignTable.addColumn("foreignColumn", ColumnType::Text, {Sqlite::Unique{}});
ColumnType::Text,
Sqlite::Contraint::Unique);
table.setName(tableName); table.setName(tableName);
auto &column = table.addForeignKeyColumn("name", auto &column = table.addForeignKeyColumn("name",
@@ -219,22 +210,20 @@ TEST_F(SqliteTable, AddForeignKeyColumnWithColumn)
AllOf(Field(&Column::name, Eq("name")), AllOf(Field(&Column::name, Eq("name")),
Field(&Column::tableName, Eq(tableName)), Field(&Column::tableName, Eq(tableName)),
Field(&Column::type, ColumnType::Text), Field(&Column::type, ColumnType::Text),
Field(&Column::constraint, Contraint::ForeignKey), Field(&Column::constraints,
Field(&Column::foreignKey, ElementsAre(VariantWith<ForeignKey>(
AllOf(Field(&ForeignKey::table, Eq("foreignTable")), AllOf(Field(&ForeignKey::table, Eq("foreignTable")),
Field(&ForeignKey::column, Eq("foreignColumn")), Field(&ForeignKey::column, Eq("foreignColumn")),
Field(&ForeignKey::updateAction, ForeignKeyAction::SetNull), Field(&ForeignKey::updateAction, ForeignKeyAction::SetNull),
Field(&ForeignKey::deleteAction, ForeignKeyAction::Cascade), Field(&ForeignKey::deleteAction, ForeignKeyAction::Cascade),
Field(&ForeignKey::enforcement, Enforment::Deferred))))); Field(&ForeignKey::enforcement, Enforment::Deferred)))))));
} }
TEST_F(SqliteTable, AddForeignKeyWhichIsNotUniqueThrowsAnExceptions) TEST_F(SqliteTable, AddForeignKeyWhichIsNotUniqueThrowsAnExceptions)
{ {
Sqlite::Table foreignTable; Sqlite::Table foreignTable;
foreignTable.setName("foreignTable"); foreignTable.setName("foreignTable");
auto &foreignColumn = foreignTable.addColumn("foreignColumn", auto &foreignColumn = foreignTable.addColumn("foreignColumn", ColumnType::Text);
ColumnType::Text,
Sqlite::Contraint::NoConstraint);
table.setName(tableName); table.setName(tableName);
ASSERT_THROW(table.addForeignKeyColumn("name", ASSERT_THROW(table.addForeignKeyColumn("name",
@@ -245,4 +234,62 @@ TEST_F(SqliteTable, AddForeignKeyWhichIsNotUniqueThrowsAnExceptions)
Sqlite::ForeignKeyColumnIsNotUnique); Sqlite::ForeignKeyColumnIsNotUnique);
} }
TEST_F(SqliteTable, AddForeignKeyColumnWithTableAndNotNull)
{
Sqlite::Table foreignTable;
foreignTable.setName("foreignTable");
table.setName(tableName);
auto &column = table.addForeignKeyColumn("name",
foreignTable,
ForeignKeyAction::SetNull,
ForeignKeyAction::Cascade,
Enforment::Deferred,
{Sqlite::NotNull{}});
ASSERT_THAT(column,
AllOf(Field(&Column::name, Eq("name")),
Field(&Column::tableName, Eq(tableName)),
Field(&Column::type, ColumnType::Integer),
Field(&Column::constraints,
UnorderedElementsAre(
VariantWith<ForeignKey>(
AllOf(Field(&ForeignKey::table, Eq("foreignTable")),
Field(&ForeignKey::column, IsEmpty()),
Field(&ForeignKey::updateAction, ForeignKeyAction::SetNull),
Field(&ForeignKey::deleteAction, ForeignKeyAction::Cascade),
Field(&ForeignKey::enforcement, Enforment::Deferred))),
VariantWith<Sqlite::NotNull>(Eq(Sqlite::NotNull{}))))));
}
TEST_F(SqliteTable, AddForeignKeyColumnWithColumnAndNotNull)
{
Sqlite::Table foreignTable;
foreignTable.setName("foreignTable");
auto &foreignColumn = foreignTable.addColumn("foreignColumn", ColumnType::Text, {Sqlite::Unique{}});
table.setName(tableName);
auto &column = table.addForeignKeyColumn("name",
foreignColumn,
ForeignKeyAction::SetNull,
ForeignKeyAction::Cascade,
Enforment::Deferred,
{Sqlite::NotNull{}});
ASSERT_THAT(column,
AllOf(Field(&Column::name, Eq("name")),
Field(&Column::tableName, Eq(tableName)),
Field(&Column::type, ColumnType::Text),
Field(&Column::constraints,
UnorderedElementsAre(
VariantWith<ForeignKey>(
AllOf(Field(&ForeignKey::table, Eq("foreignTable")),
Field(&ForeignKey::column, Eq("foreignColumn")),
Field(&ForeignKey::updateAction, ForeignKeyAction::SetNull),
Field(&ForeignKey::deleteAction, ForeignKeyAction::Cascade),
Field(&ForeignKey::enforcement, Enforment::Deferred))),
VariantWith<Sqlite::NotNull>(Eq(Sqlite::NotNull{}))))));
}
} // namespace } // namespace