Skip to content

Commit b9cac12

Browse files
authored
Merge pull request #61 from dotnetprojects/Sqlite
Add NULL / NOT NULL explicitly
2 parents 64e7b95 + 3ea24a0 commit b9cac12

File tree

4 files changed

+161
-3
lines changed

4 files changed

+161
-3
lines changed

src/Migrator.Tests/Providers/SQLite/SQLiteTransformationProvider_AddTableTests.cs

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using System.Linq;
23
using DotNetProjects.Migrator.Framework;
34
using DotNetProjects.Migrator.Providers.Impl.SQLite;
@@ -12,7 +13,7 @@ namespace Migrator.Tests.Providers.SQLite;
1213
public class SQLiteTransformationProvider_AddTableTests : SQLiteTransformationProviderTestBase
1314
{
1415
[Test]
15-
public void AddForeignKey()
16+
public void AddTable_UniqueOnly_ContainsNull()
1617
{
1718
const string tableName = "MyTableName";
1819
const string columnName = "MyColumnName";
@@ -22,9 +23,96 @@ public void AddForeignKey()
2223

2324
// Assert
2425
var createScript = ((SQLiteTransformationProvider)Provider).GetSqlCreateTableScript(tableName);
25-
Assert.That("CREATE TABLE MyTableName (MyColumnName INTEGER UNIQUE)", Is.EqualTo(createScript));
26+
Assert.That("CREATE TABLE MyTableName (MyColumnName INTEGER NULL UNIQUE)", Is.EqualTo(createScript));
2627

2728
var sqliteInfo = ((SQLiteTransformationProvider)Provider).GetSQLiteTableInfo(tableName);
2829
Assert.That(sqliteInfo.Uniques.Single().KeyColumns.Single(), Is.EqualTo(columnName));
2930
}
31+
32+
[Test]
33+
public void AddTable_CompositePrimaryKey_ContainsNull()
34+
{
35+
const string tableName = "MyTableName";
36+
const string columnName1 = "Column1";
37+
const string columnName2 = "Column2";
38+
39+
// Arrange/Act
40+
Provider.AddTable(tableName,
41+
new Column(columnName1, System.Data.DbType.Int32, ColumnProperty.PrimaryKey),
42+
new Column(columnName2, System.Data.DbType.Int32, ColumnProperty.PrimaryKey | ColumnProperty.NotNull)
43+
);
44+
45+
Provider.ExecuteNonQuery($"INSERT INTO {tableName} ({columnName1}, {columnName2}) VALUES (1,1)");
46+
Assert.Throws<Exception>(() => Provider.ExecuteNonQuery($"INSERT INTO {tableName} ({columnName1}, {columnName2}) VALUES (1,1)"));
47+
48+
// Assert
49+
var createScript = ((SQLiteTransformationProvider)Provider).GetSqlCreateTableScript(tableName);
50+
Assert.That("CREATE TABLE MyTableName (Column1 INTEGER NOT NULL, Column2 INTEGER NOT NULL, PRIMARY KEY (Column1,Column2) )", Is.EqualTo(createScript));
51+
52+
var pragmaTableInfos = ((SQLiteTransformationProvider)Provider).GetPragmaTableInfoItems(tableName);
53+
Assert.That(pragmaTableInfos.All(x => x.NotNull), Is.True);
54+
55+
var sqliteInfo = ((SQLiteTransformationProvider)Provider).GetSQLiteTableInfo(tableName);
56+
Assert.That(sqliteInfo.Columns.First().Name, Is.EqualTo(columnName1));
57+
Assert.That(sqliteInfo.Columns[1].Name, Is.EqualTo(columnName2));
58+
}
59+
60+
[Test]
61+
public void AddTable_SinglePrimaryKey_ContainsNull()
62+
{
63+
const string tableName = "MyTableName";
64+
const string columnName1 = "Column1";
65+
const string columnName2 = "Column2";
66+
67+
// Arrange/Act
68+
Provider.AddTable(tableName,
69+
new Column(columnName1, System.Data.DbType.Int32, ColumnProperty.PrimaryKey),
70+
new Column(columnName2, System.Data.DbType.Int32, ColumnProperty.NotNull)
71+
);
72+
73+
Provider.ExecuteNonQuery($"INSERT INTO {tableName} ({columnName1}, {columnName2}) VALUES (1,1)");
74+
Assert.Throws<Exception>(() => Provider.ExecuteNonQuery($"INSERT INTO {tableName} ({columnName1}, {columnName2}) VALUES (1,2)"));
75+
76+
// Assert
77+
var createScript = ((SQLiteTransformationProvider)Provider).GetSqlCreateTableScript(tableName);
78+
Assert.That("CREATE TABLE MyTableName (Column1 INTEGER NOT NULL PRIMARY KEY, Column2 INTEGER NOT NULL)", Is.EqualTo(createScript));
79+
80+
var pragmaTableInfos = ((SQLiteTransformationProvider)Provider).GetPragmaTableInfoItems(tableName);
81+
Assert.That(pragmaTableInfos.All(x => x.NotNull), Is.True);
82+
83+
var sqliteInfo = ((SQLiteTransformationProvider)Provider).GetSQLiteTableInfo(tableName);
84+
Assert.That(sqliteInfo.Columns.First().Name, Is.EqualTo(columnName1));
85+
Assert.That(sqliteInfo.Columns[1].Name, Is.EqualTo(columnName2));
86+
}
87+
88+
[Test]
89+
public void AddTable_MiscellaneousColumns_Succeeds()
90+
{
91+
const string tableName = "MyTableName";
92+
const string columnName1 = "Column1";
93+
const string columnName2 = "Column2";
94+
95+
// Arrange/Act
96+
Provider.AddTable(tableName,
97+
new Column(columnName1, System.Data.DbType.Int32, ColumnProperty.NotNull | ColumnProperty.Identity | ColumnProperty.PrimaryKey),
98+
new Column(columnName2, System.Data.DbType.Int32, ColumnProperty.Null | ColumnProperty.Unique)
99+
);
100+
101+
Provider.ExecuteNonQuery($"INSERT INTO {tableName} ({columnName1}, {columnName2}) VALUES (1,1)");
102+
Assert.Throws<Exception>(() => Provider.ExecuteNonQuery($"INSERT INTO {tableName} ({columnName1}, {columnName2}) VALUES (1,1)"));
103+
104+
// Assert
105+
var createScript = ((SQLiteTransformationProvider)Provider).GetSqlCreateTableScript(tableName);
106+
Assert.That("CREATE TABLE MyTableName (Column1 INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, Column2 INTEGER NULL UNIQUE)", Is.EqualTo(createScript));
107+
108+
var pragmaTableInfos = ((SQLiteTransformationProvider)Provider).GetPragmaTableInfoItems(tableName);
109+
Assert.That(pragmaTableInfos.First().NotNull, Is.True);
110+
Assert.That(pragmaTableInfos[1].NotNull, Is.False);
111+
112+
var sqliteInfo = ((SQLiteTransformationProvider)Provider).GetSQLiteTableInfo(tableName);
113+
Assert.That(sqliteInfo.Columns.First().Name, Is.EqualTo(columnName1));
114+
Assert.That(sqliteInfo.Columns[1].Name, Is.EqualTo(columnName2));
115+
}
116+
117+
30118
}

src/Migrator/Providers/ColumnPropertiesMapper.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,10 @@ protected virtual void AddNull(Column column, List<string> vals)
186186
{
187187
if (!PropertySelected(column.ColumnProperty, ColumnProperty.PrimaryKey))
188188
{
189-
if (dialect.NeedsNullForNullableWhenAlteringTable) AddValueIfSelected(column, ColumnProperty.Null, vals);
189+
if (dialect.NeedsNullForNullableWhenAlteringTable)
190+
{
191+
AddValueIfSelected(column, ColumnProperty.Null, vals);
192+
}
190193
}
191194
}
192195

@@ -223,7 +226,9 @@ protected virtual void AddName(List<string> vals)
223226
protected virtual void AddValueIfSelected(Column column, ColumnProperty property, ICollection<string> vals)
224227
{
225228
if (PropertySelected(column.ColumnProperty, property))
229+
{
226230
vals.Add(dialect.SqlForProperty(property, column));
231+
}
227232
}
228233

229234
public static bool PropertySelected(ColumnProperty source, ColumnProperty comparison)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Migrator.Framework;
4+
using Migrator.Providers;
5+
6+
namespace DotNetProjects.Migrator.Providers.Impl.SQLite;
7+
8+
public class SQLiteColumnPropertiesMapper : ColumnPropertiesMapper
9+
{
10+
public SQLiteColumnPropertiesMapper(Dialect dialect, string type) : base(dialect, type)
11+
{
12+
}
13+
14+
protected override void AddNull(Column column, List<string> vals)
15+
{
16+
var isPrimaryKeySelected = PropertySelected(column.ColumnProperty, ColumnProperty.PrimaryKey);
17+
var isNullSelected = PropertySelected(column.ColumnProperty, ColumnProperty.Null);
18+
var isNotNullSelected = PropertySelected(column.ColumnProperty, ColumnProperty.NotNull);
19+
20+
if (isNullSelected || (!isNotNullSelected && !isPrimaryKeySelected))
21+
{
22+
AddValueIfSelected(column, ColumnProperty.Null, vals);
23+
}
24+
}
25+
26+
protected override void AddNotNull(Column column, List<string> vals)
27+
{
28+
var isPrimaryKeySelected = PropertySelected(column.ColumnProperty, ColumnProperty.PrimaryKey);
29+
var isNullSelected = PropertySelected(column.ColumnProperty, ColumnProperty.Null);
30+
var isNotNullSelected = PropertySelected(column.ColumnProperty, ColumnProperty.NotNull);
31+
32+
if (isNullSelected && isPrimaryKeySelected)
33+
{
34+
throw new Exception("This is currently not supported by the migrator see issue #44");
35+
}
36+
37+
if (isNotNullSelected || isPrimaryKeySelected)
38+
{
39+
AddValueIfSelected(column, ColumnProperty.NotNull, vals);
40+
}
41+
}
42+
43+
protected virtual void AddValueIfSelected(Column column, ColumnProperty property, ICollection<string> vals)
44+
{
45+
vals.Add(dialect.SqlForProperty(property, column));
46+
}
47+
}

src/Migrator/Providers/Impl/SQLite/SQLiteDialect.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,5 +83,23 @@ public override ITransformationProvider GetTransformationProvider(Dialect dialec
8383
{
8484
return new SQLiteTransformationProvider(dialect, connection, scope, providerName);
8585
}
86+
87+
public override ColumnPropertiesMapper GetColumnMapper(Column column)
88+
{
89+
// Copied from base
90+
var type = column.Size > 0 ? GetTypeName(column.Type, column.Size) : GetTypeName(column.Type);
91+
92+
if (column.Precision.HasValue || column.Scale.HasValue)
93+
{
94+
type = GetTypeNameParametrized(column.Type, column.Size, column.Precision ?? 0, column.Scale ?? 0);
95+
}
96+
97+
if (!IdentityNeedsType && column.IsIdentity)
98+
{
99+
type = String.Empty;
100+
}
101+
102+
return new SQLiteColumnPropertiesMapper(this, type);
103+
}
86104
}
87105
}

0 commit comments

Comments
 (0)