diff --git a/.github/workflows/sql/oracle.sql b/.github/workflows/sql/oracle.sql
index 5dc26fc6..6423ae4c 100644
--- a/.github/workflows/sql/oracle.sql
+++ b/.github/workflows/sql/oracle.sql
@@ -14,6 +14,7 @@ grant resource to k with admin option;
grant connect to k with admin option;
grant unlimited tablespace to k with admin option;
grant select on v_$session to k with grant option;
+grant select on sys.gv_$session to k with grant option;
grant alter system to k;
exit;
\ No newline at end of file
diff --git a/src/Migrator.Tests/Database/DatabaseName/DatabaseNameService.cs b/src/Migrator.Tests/Database/DatabaseName/DatabaseNameService.cs
index 8d8e7d2f..505e396c 100644
--- a/src/Migrator.Tests/Database/DatabaseName/DatabaseNameService.cs
+++ b/src/Migrator.Tests/Database/DatabaseName/DatabaseNameService.cs
@@ -1,16 +1,15 @@
using System;
using System.Globalization;
using System.IO;
-using System.Linq;
+using System.Security.Cryptography;
using System.Text.RegularExpressions;
using Migrator.Tests.Database.DatabaseName.Interfaces;
-using Migrator.Tests.Database.GuidServices.Interfaces;
namespace Migrator.Test.Shared.Database;
-public partial class DatabaseNameService(TimeProvider timeProvider, IGuidService guidService) : IDatabaseNameService
+public partial class DatabaseNameService(TimeProvider timeProvider) : IDatabaseNameService
{
- private const string TestDatabaseString = "Test";
+ private const string TestDatabaseString = "T";
private const string TimeStampPattern = "yyyyMMddHHmmssfff";
public DateTime? ReadTimeStampFromString(string name)
@@ -33,14 +32,25 @@ public string CreateDatabaseName()
var dateTimePattern = timeProvider.GetUtcNow()
.ToString(TimeStampPattern);
- var randomString = string.Concat(guidService.NewGuid()
- .ToString("N")
- .Reverse()
- .Take(9));
+ var randomString = CreateRandomChars(7);
return $"{dateTimePattern}{TestDatabaseString}{randomString}";
}
- [GeneratedRegex(@"^(\d+)(?=Test.{9}$)")]
+ private string CreateRandomChars(int length)
+ {
+ var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+ var stringChars = new char[length];
+
+ for (var i = 0; i < length; i++)
+ {
+ var index = RandomNumberGenerator.GetInt32(chars.Length);
+ stringChars[i] = chars[index];
+ }
+
+ return new string(stringChars);
+ }
+
+ [GeneratedRegex(@"^([\d]+)(?=T.{7}$)")]
private static partial Regex DateTimeRegex();
-}
\ No newline at end of file
+}
diff --git a/src/Migrator.Tests/Database/DerivedDatabaseIntegrationTestServices/OracleDatabaseIntegrationTestService.cs b/src/Migrator.Tests/Database/DerivedDatabaseIntegrationTestServices/OracleDatabaseIntegrationTestService.cs
index 9b5d1fee..6d41ace4 100644
--- a/src/Migrator.Tests/Database/DerivedDatabaseIntegrationTestServices/OracleDatabaseIntegrationTestService.cs
+++ b/src/Migrator.Tests/Database/DerivedDatabaseIntegrationTestServices/OracleDatabaseIntegrationTestService.cs
@@ -1,7 +1,6 @@
using System;
-using System.Collections.Generic;
using System.Linq;
-using System.Text.RegularExpressions;
+using System.Text;
using System.Threading;
using System.Threading.Tasks;
using DotNetProjects.Migrator.Framework.Data.Common;
@@ -19,17 +18,21 @@
namespace Migrator.Tests.Database.DerivedDatabaseIntegrationTestServices;
+
+///
+/// We use the tablespace users since the server container is recreated before the test runs (once per github workflow run)
+///
+///
+///
public class OracleDatabaseIntegrationTestService(
TimeProvider timeProvider,
IDatabaseNameService databaseNameService)
: DatabaseIntegrationTestServiceBase(databaseNameService), IDatabaseIntegrationTestService
{
- private const string TableSpacePrefix = "TS_";
private const string UserStringKey = "User Id";
private const string PasswordStringKey = "Password";
private const string ReplaceString = "RandomStringThatIsNotQuotedByTheBuilderDoNotChange";
private readonly MappingSchema _mappingSchema = new MappingSchemaFactory().CreateOracleMappingSchema();
- private Regex _tablespaceRegex = new("^TS_TESTS_");
///
/// Creates an oracle database for test purposes.
@@ -61,8 +64,6 @@ public class OracleDatabaseIntegrationTestService(
///
public override async Task CreateTestDatabaseAsync(DatabaseConnectionConfig databaseConnectionConfig, CancellationToken cancellationToken)
{
- DataConnection context;
-
var tempDatabaseConnectionConfig = databaseConnectionConfig.Adapt();
var connectionStringBuilder = new OracleConnectionStringBuilder()
@@ -82,15 +83,12 @@ public override async Task CreateTestDatabaseAsync(DatabaseConnect
var tempUserName = DatabaseNameService.CreateDatabaseName();
- List userNames;
-
var dataOptions = new DataOptions().UseOracle(databaseConnectionConfig.ConnectionString)
.UseMappingSchema(_mappingSchema);
- using (context = new DataConnection(dataOptions))
- {
- userNames = await context.QueryToListAsync("SELECT username FROM all_users", cancellationToken);
- }
+ using var context = new DataConnection(dataOptions);
+
+ var userNames = await context.GetTable().Select(x => x.UserName).ToListAsync(cancellationToken);
var toBeDeletedUsers = userNames.Where(x =>
{
@@ -112,49 +110,33 @@ await Parallel.ForEachAsync(
};
await DropDatabaseAsync(databaseInfoToBeDeleted, cancellationTokenInner);
-
});
- using (context = new DataConnection(dataOptions))
- {
- // To be on the safe side we check for table spaces used in tests that have not been deleted for any reason (possible connection issues/concurrent deletion attempts - there is
- // no transaction for DDL in Oracle etc.).
- var tableSpaceNames = await context.GetTable()
- .Select(x => x.TablespaceName)
- .ToListAsync(cancellationToken);
-
- var toBeDeletedTableSpaces = tableSpaceNames
- .Where(x =>
- {
- var replacedTablespaceString = _tablespaceRegex.Replace(x, "");
- var creationDate = DatabaseNameService.ReadTimeStampFromString(replacedTablespaceString);
- return creationDate.HasValue && creationDate.Value < timeProvider.GetUtcNow().Subtract(_MinTimeSpanBeforeDatabaseDeletion);
- });
+ var stringBuilder = new StringBuilder();
+ stringBuilder.Append($"CREATE USER \"{tempUserName}\" IDENTIFIED BY \"{tempUserName}\"");
+ stringBuilder.AppendLine($"DEFAULT TABLESPACE users");
+ stringBuilder.AppendLine($"TEMPORARY TABLESPACE TEMP");
+ stringBuilder.AppendLine($"QUOTA UNLIMITED ON users");
- foreach (var toBeDeletedTableSpace in toBeDeletedTableSpaces)
- {
- await context.ExecuteAsync($"DROP TABLESPACE {toBeDeletedTableSpace} INCLUDING CONTENTS AND DATAFILES", cancellationToken);
- }
+ await context.ExecuteAsync(stringBuilder.ToString(), cancellationToken);
- await context.ExecuteAsync($"CREATE USER \"{tempUserName}\" IDENTIFIED BY \"{tempUserName}\"", cancellationToken);
+ var privileges = new[]
+ {
+ "CONNECT",
+ "CREATE SESSION",
+ "RESOURCE",
+ "UNLIMITED TABLESPACE"
+ };
- var privileges = new[]
- {
- "CONNECT",
- "CREATE SESSION",
- "RESOURCE",
- "UNLIMITED TABLESPACE"
- };
-
- await context.ExecuteAsync($"GRANT {string.Join(", ", privileges)} TO \"{tempUserName}\"", cancellationToken);
- await context.ExecuteAsync($"GRANT SELECT ON SYS.V_$SESSION TO \"{tempUserName}\"", cancellationToken);
- }
+ await context.ExecuteAsync($"GRANT {string.Join(", ", privileges)} TO \"{tempUserName}\"", cancellationToken);
+ await context.ExecuteAsync($"GRANT SELECT ON SYS.GV_$SESSION TO \"{tempUserName}\"", cancellationToken);
connectionStringBuilder.Add(UserStringKey, ReplaceString);
connectionStringBuilder.Add(PasswordStringKey, ReplaceString);
tempDatabaseConnectionConfig.ConnectionString = connectionStringBuilder.ConnectionString;
tempDatabaseConnectionConfig.ConnectionString = tempDatabaseConnectionConfig.ConnectionString.Replace(ReplaceString, $"\"{tempUserName}\"");
+ tempDatabaseConnectionConfig.Schema = tempUserName;
var databaseInfo = new DatabaseInfo
{
@@ -168,16 +150,18 @@ await Parallel.ForEachAsync(
public override async Task DropDatabaseAsync(DatabaseInfo databaseInfo, CancellationToken cancellationToken)
{
+ ArgumentNullException.ThrowIfNull(databaseInfo);
+
var creationDate = ReadTimeStampFromDatabaseName(databaseInfo.SchemaName);
var dataOptions = new DataOptions().UseOracle(databaseInfo.DatabaseConnectionConfigMaster.ConnectionString)
.UseMappingSchema(_mappingSchema);
+ using var context = new DataConnection(dataOptions);
+
var maxAttempts = 4;
var delayBetweenAttempts = TimeSpan.FromSeconds(1);
- using var context = new DataConnection(dataOptions);
-
for (var i = 0; i < maxAttempts; i++)
{
try
@@ -192,6 +176,13 @@ public override async Task DropDatabaseAsync(DatabaseInfo databaseInfo, Cancella
await context.ExecuteAsync(killStatement, cancellationToken);
}
+ var userExists = context.GetTable().Any(x => x.UserName == databaseInfo.SchemaName);
+
+ if (!userExists)
+ {
+ break;
+ }
+
await context.ExecuteAsync($"DROP USER \"{databaseInfo.SchemaName}\" CASCADE", cancellationToken);
}
catch
@@ -207,19 +198,13 @@ public override async Task DropDatabaseAsync(DatabaseInfo databaseInfo, Cancella
{
break;
}
- }
- await Task.Delay(delayBetweenAttempts, cancellationToken);
+ await Task.Delay(delayBetweenAttempts, cancellationToken);
- delayBetweenAttempts = delayBetweenAttempts.Add(TimeSpan.FromSeconds(1));
+ delayBetweenAttempts = delayBetweenAttempts.Add(TimeSpan.FromSeconds(1));
+ }
}
- var tablespaceName = $"{TableSpacePrefix}{databaseInfo.SchemaName}";
-
- var tablespaces = await context.GetTable().ToListAsync(cancellationToken);
-
- await context.ExecuteAsync($"DROP TABLESPACE {tablespaceName} INCLUDING CONTENTS AND DATAFILES", cancellationToken);
-
await context.ExecuteAsync($"PURGE RECYCLEBIN", cancellationToken);
}
-}
\ No newline at end of file
+}
diff --git a/src/Migrator.Tests/Providers/Base/TransformationProviderBase.cs b/src/Migrator.Tests/Providers/Base/TransformationProviderBase.cs
index dfd236c2..f12b7f27 100644
--- a/src/Migrator.Tests/Providers/Base/TransformationProviderBase.cs
+++ b/src/Migrator.Tests/Providers/Base/TransformationProviderBase.cs
@@ -64,10 +64,9 @@ protected void DropTestTables()
}
}
-
protected async Task BeginOracleTransactionAsync()
{
- using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
+ using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(1));
var configReader = new ConfigurationReader();
var databaseConnectionConfig = configReader.GetDatabaseConnectionConfigById(DatabaseConnectionConfigIds.OracleId);
diff --git a/src/Migrator.Tests/Providers/Generic/Generic_AddTableTestsBase.cs b/src/Migrator.Tests/Providers/Generic/Generic_AddTableTestsBase.cs
index 97c315f9..0c78c68b 100644
--- a/src/Migrator.Tests/Providers/Generic/Generic_AddTableTestsBase.cs
+++ b/src/Migrator.Tests/Providers/Generic/Generic_AddTableTestsBase.cs
@@ -1,4 +1,6 @@
+using System.Collections.Generic;
using System.Data;
+using System.Linq;
using DotNetProjects.Migrator.Framework;
using Migrator.Tests.Providers.Base;
using NUnit.Framework;
@@ -30,6 +32,86 @@ public void AddTable_PrimaryKeyWithIdentity_Success()
Assert.That(column2.ColumnProperty.HasFlag(ColumnProperty.NotNull), Is.True);
}
+ [Test]
+ public void AddTable_PrimaryKeyAndIdentity_Success()
+ {
+ // Arrange
+ var tableName = "TableName";
+ var column1Name = "Column1";
+ var column2Name = "Column2";
+
+ // Act
+ Provider.AddTable(tableName,
+ new Column(column1Name, DbType.Int32, ColumnProperty.NotNull | ColumnProperty.PrimaryKey | ColumnProperty.Identity),
+ new Column(column2Name, DbType.Int32, ColumnProperty.NotNull)
+ );
+
+ // Assert
+ var column1 = Provider.GetColumnByName(tableName, column1Name);
+ var column2 = Provider.GetColumnByName(tableName, column2Name);
+
+ Assert.That(column1.ColumnProperty.HasFlag(ColumnProperty.PrimaryKeyWithIdentity), Is.True);
+ Assert.That(column2.ColumnProperty.HasFlag(ColumnProperty.NotNull), Is.True);
+ }
+
+ [Test]
+ public void AddTable_PrimaryKeyAndIdentityWithInsertNull_Success()
+ {
+ // Arrange
+ var tableName = "TableName";
+ var column1Name = "Column1";
+ var column2Name = "Column2";
+
+ // Act
+ Provider.AddTable(tableName,
+ new Column(column1Name, DbType.Int32, ColumnProperty.NotNull | ColumnProperty.PrimaryKey | ColumnProperty.Identity),
+ new Column(column2Name, DbType.Int32, ColumnProperty.NotNull)
+ );
+
+ Provider.Insert(table: tableName, [column2Name], [999]);
+
+ // Assert
+ var column1 = Provider.GetColumnByName(tableName, column1Name);
+ var column2 = Provider.GetColumnByName(tableName, column2Name);
+
+ using var cmd = Provider.CreateCommand();
+ using var reader = Provider.Select(cmd: cmd, table: tableName, columns: [column1Name, column2Name]);
+
+ List<(int, int)> records = [];
+
+ while (reader.Read())
+ {
+ records.Add((reader.GetInt32(0), reader.GetInt32(1)));
+ }
+
+ Assert.That(records.Single().Item1, Is.EqualTo(1));
+
+ Assert.That(column1.ColumnProperty.HasFlag(ColumnProperty.PrimaryKeyWithIdentity), Is.True);
+ Assert.That(column2.ColumnProperty.HasFlag(ColumnProperty.NotNull), Is.True);
+ }
+
+ [Test]
+ public void AddTable_PrimaryKeyAndIdentityWithoutNotNull_Success()
+ {
+ // Arrange
+ var tableName = "TableName";
+ var column1Name = "Column1";
+ var column2Name = "Column2";
+
+ // Act
+ Provider.AddTable(tableName,
+ new Column(column1Name, DbType.Int32, ColumnProperty.PrimaryKey | ColumnProperty.Identity),
+ new Column(column2Name, DbType.Int32, ColumnProperty.NotNull)
+ );
+
+ // Assert
+ var column1 = Provider.GetColumnByName(tableName, column1Name);
+ var column2 = Provider.GetColumnByName(tableName, column2Name);
+
+ Assert.That(column1.ColumnProperty.HasFlag(ColumnProperty.PrimaryKeyWithIdentity), Is.True);
+ Assert.That(column2.ColumnProperty.HasFlag(ColumnProperty.NotNull), Is.True);
+ }
+
[Test]
public void AddTable_NotNull_Success()
{
diff --git a/src/Migrator.Tests/Providers/Generic/Generic_DefaultValueTestsBase.cs b/src/Migrator.Tests/Providers/Generic/Generic_DefaultValueTestsBase.cs
new file mode 100644
index 00000000..58d525bb
--- /dev/null
+++ b/src/Migrator.Tests/Providers/Generic/Generic_DefaultValueTestsBase.cs
@@ -0,0 +1,50 @@
+using System.Data;
+using DotNetProjects.Migrator.Framework;
+using Migrator.Tests.Providers.Base;
+using NUnit.Framework;
+
+namespace Migrator.Tests.Providers.Generic;
+
+public abstract class Generic_DefaultValueTestsBase : TransformationProviderBase
+{
+ [Test]
+ public void DefaultValue_Null_Success()
+ {
+ const string tableNameSource = "SourceTable";
+ const string columnName1Target = "TargetColumn1";
+
+ Provider.AddTable(tableNameSource,
+ new Column(columnName1Target, DbType.Int32, ColumnProperty.Null, null)
+ );
+
+ Provider.ChangeColumn(tableNameSource, new Column(columnName1Target, DbType.Int32, ColumnProperty.NotNull));
+ }
+
+ [Test]
+ public void DefaultValue_ConvertStringToNotNull_DoesNotThrow()
+ {
+ const string tableNameSource = "SourceTable";
+ const string columnName1Target = "TargetColumn1";
+
+ Provider.AddTable(tableNameSource,
+ new Column(columnName1Target, DbType.String, 32, ColumnProperty.NotNull)
+ );
+
+ Provider.ChangeColumn(tableNameSource, new Column(columnName1Target, DbType.String, ColumnProperty.Null));
+ }
+
+ [Test]
+ public void RemoveColumnDefaultValue_DoesNotThrow()
+ {
+ const string tableNameSource = "TableName";
+ const string columnName1 = "ColumnName1";
+
+ Provider.AddTable(tableNameSource,
+ new Column(columnName1, DbType.Int32, ColumnProperty.NotNull, 10)
+ );
+
+ Provider.RemoveColumnDefaultValue(tableNameSource, columnName1);
+
+ Provider.ChangeColumn(tableNameSource, new Column(columnName1, DbType.Int32, ColumnProperty.Null));
+ }
+}
\ No newline at end of file
diff --git a/src/Migrator.Tests/Providers/OracleProvider/OracleTransformationProvider_DefaultValueTests.cs b/src/Migrator.Tests/Providers/OracleProvider/OracleTransformationProvider_DefaultValueTests.cs
new file mode 100644
index 00000000..28097140
--- /dev/null
+++ b/src/Migrator.Tests/Providers/OracleProvider/OracleTransformationProvider_DefaultValueTests.cs
@@ -0,0 +1,16 @@
+using System.Threading.Tasks;
+using Migrator.Tests.Providers.Generic;
+using NUnit.Framework;
+
+namespace Migrator.Tests.Providers.OracleProvider;
+
+[TestFixture]
+[Category("Oracle")]
+public class OracleTransformationProvider_DefaultValueTests : Generic_DefaultValueTestsBase
+{
+ [SetUp]
+ public async Task SetUpAsync()
+ {
+ await BeginOracleTransactionAsync();
+ }
+}
\ No newline at end of file
diff --git a/src/Migrator.Tests/Providers/PostgreSQL/PostgresSQLTransformationProvider_AddPrimaryKeyTests.cs b/src/Migrator.Tests/Providers/PostgreSQL/PostgreSQLTransformationProvider_AddPrimaryKeyTests.cs
similarity index 100%
rename from src/Migrator.Tests/Providers/PostgreSQL/PostgresSQLTransformationProvider_AddPrimaryKeyTests.cs
rename to src/Migrator.Tests/Providers/PostgreSQL/PostgreSQLTransformationProvider_AddPrimaryKeyTests.cs
diff --git a/src/Migrator.Tests/Providers/PostgreSQL/PostgresSQLTransformationProvider_ChangeColumnTests.cs b/src/Migrator.Tests/Providers/PostgreSQL/PostgreSQLTransformationProvider_ChangeColumnTests.cs
similarity index 83%
rename from src/Migrator.Tests/Providers/PostgreSQL/PostgresSQLTransformationProvider_ChangeColumnTests.cs
rename to src/Migrator.Tests/Providers/PostgreSQL/PostgreSQLTransformationProvider_ChangeColumnTests.cs
index 746ba161..cb91de8e 100644
--- a/src/Migrator.Tests/Providers/PostgreSQL/PostgresSQLTransformationProvider_ChangeColumnTests.cs
+++ b/src/Migrator.Tests/Providers/PostgreSQL/PostgreSQLTransformationProvider_ChangeColumnTests.cs
@@ -1,4 +1,6 @@
+using System.Data;
using System.Threading.Tasks;
+using DotNetProjects.Migrator.Framework;
using Migrator.Tests.Providers.Generic;
using NUnit.Framework;
diff --git a/src/Migrator.Tests/Providers/PostgreSQL/PostgreSQLTransformationProvider_DefaultValueTests.cs b/src/Migrator.Tests/Providers/PostgreSQL/PostgreSQLTransformationProvider_DefaultValueTests.cs
new file mode 100644
index 00000000..a985d3ab
--- /dev/null
+++ b/src/Migrator.Tests/Providers/PostgreSQL/PostgreSQLTransformationProvider_DefaultValueTests.cs
@@ -0,0 +1,16 @@
+using System.Threading.Tasks;
+using Migrator.Tests.Providers.Generic;
+using NUnit.Framework;
+
+namespace Migrator.Tests.Providers.PostgreSQL;
+
+[TestFixture]
+[Category("Postgre")]
+public class PostgreSQLTransformationProvider_DefaultValueTests : Generic_DefaultValueTestsBase
+{
+ [SetUp]
+ public async Task SetUpAsync()
+ {
+ await BeginPostgreSQLTransactionAsync();
+ }
+}
\ No newline at end of file
diff --git a/src/Migrator.Tests/Providers/SQLServer/SQLServerTransformationProvider_DefaultValueTests.cs b/src/Migrator.Tests/Providers/SQLServer/SQLServerTransformationProvider_DefaultValueTests.cs
new file mode 100644
index 00000000..73caec5d
--- /dev/null
+++ b/src/Migrator.Tests/Providers/SQLServer/SQLServerTransformationProvider_DefaultValueTests.cs
@@ -0,0 +1,16 @@
+using System.Threading.Tasks;
+using Migrator.Tests.Providers.Generic;
+using NUnit.Framework;
+
+namespace Migrator.Tests.Providers.SQLServer;
+
+[TestFixture]
+[Category("SqlServer")]
+public class SQLServerTransformationProvider_DefaultValueTests : Generic_DefaultValueTestsBase
+{
+ [SetUp]
+ public async Task SetUpAsync()
+ {
+ await BeginSQLServerTransactionAsync();
+ }
+}
\ No newline at end of file
diff --git a/src/Migrator.Tests/Providers/SQLite/SQLiteTransformationProvider_DefaultValueTests.cs b/src/Migrator.Tests/Providers/SQLite/SQLiteTransformationProvider_DefaultValueTests.cs
new file mode 100644
index 00000000..e6bac437
--- /dev/null
+++ b/src/Migrator.Tests/Providers/SQLite/SQLiteTransformationProvider_DefaultValueTests.cs
@@ -0,0 +1,16 @@
+using System.Threading.Tasks;
+using Migrator.Tests.Providers.Generic;
+using NUnit.Framework;
+
+namespace Migrator.Tests.Providers.SQLite;
+
+[TestFixture]
+[Category("SQLite")]
+public class SQLiteTransformationProvider_DefaultValueTests : Generic_AddIndexTestsBase
+{
+ [SetUp]
+ public async Task SetUpAsync()
+ {
+ await BeginSQLiteTransactionAsync();
+ }
+}
diff --git a/src/Migrator.Tests/Settings/Models/DatabaseConnectionConfig.cs b/src/Migrator.Tests/Settings/Models/DatabaseConnectionConfig.cs
index e7d96884..e41c7ea8 100644
--- a/src/Migrator.Tests/Settings/Models/DatabaseConnectionConfig.cs
+++ b/src/Migrator.Tests/Settings/Models/DatabaseConnectionConfig.cs
@@ -2,10 +2,18 @@ namespace Migrator.Tests.Settings.Models;
public class DatabaseConnectionConfig
{
+ ///
+ /// Gets or sets the connection string.
+ ///
public string ConnectionString { get; set; }
///
/// Gets or sets the connection identifier.
///
public string Id { get; set; }
+
+ ///
+ /// Gets or sets the schema name.
+ ///
+ public string Schema { get; set; }
}
\ No newline at end of file
diff --git a/src/Migrator/Providers/Impl/Oracle/OracleTransformationProvider.cs b/src/Migrator/Providers/Impl/Oracle/OracleTransformationProvider.cs
index 4c48d311..6a5a35ed 100644
--- a/src/Migrator/Providers/Impl/Oracle/OracleTransformationProvider.cs
+++ b/src/Migrator/Providers/Impl/Oracle/OracleTransformationProvider.cs
@@ -635,7 +635,11 @@ public override Column[] GetColumns(string table)
}
// dataDefaultString contains ISEQ$$ if the column is an identity column
- if (!string.IsNullOrWhiteSpace(dataDefaultString) && !dataDefaultString.Contains("ISEQ$$") && !dataDefaultString.Contains(".nextval"))
+ if (
+ !string.IsNullOrWhiteSpace(dataDefaultString) &&
+ (column.Type == DbType.String || !dataDefaultString.Equals("null", StringComparison.OrdinalIgnoreCase)) &&
+ !dataDefaultString.Contains("ISEQ$$") &&
+ !dataDefaultString.Contains(".nextval"))
{
// This is only necessary because older versions of this migrator added single quotes for numerics.
var singleQuoteStrippedString = dataDefaultString.Replace("'", "");