Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using System.Collections.Generic;
using System.Data;
using DotNetProjects.Migrator.Framework;
using Migrator.Tests.Providers.Base;
using Migrator.Tests.Providers.Generic.Models;
using NUnit.Framework;

namespace Migrator.Tests.Providers.Generic;

public abstract class Generic_CopyDataFromTableToTableBase : TransformationProviderBase
{
[Test]
public void CopyDataFromTableToTable_Success()
{
// Arrange
const string tableNameSource = "SourceTable";
const string columnName1Source = "SourceColumn1";
const string columnName2Source = "SourceColumn2";
const string columnName3Source = "SourceColumn3";

const string tableNameTarget = "TargetTable";
const string columnName1Target = "TargetColumn1";
const string columnName2Target = "TargetColumn2";
const string columnName3Target = "TargetColumn3";

Provider.AddTable(tableNameSource,
new Column(columnName1Source, DbType.Int32),
new Column(columnName2Source, DbType.String),
new Column(columnName3Source, DbType.Int32)
);

Provider.AddTable(tableNameTarget,
new Column(columnName1Target, DbType.Int32),
new Column(columnName2Target, DbType.String),
new Column(columnName3Target, DbType.Int32)
);

Provider.Insert(tableNameSource, [columnName1Source, columnName2Source, columnName3Source], [2, "Hello2", 22]);
Provider.Insert(tableNameSource, [columnName1Source, columnName2Source, columnName3Source], [1, "Hello1", 11]);

// Act
Provider.CopyDataFromTableToTable(
tableNameSource,
[columnName1Source, columnName2Source, columnName3Source],
tableNameTarget,
[columnName1Target, columnName2Target, columnName3Target],
[columnName1Source]);

// Assert
List<CopyDataFromTableToTableModel> targetRows = [];
using (var cmd = Provider.CreateCommand())
using (var reader = Provider.Select(cmd, tableNameTarget, [columnName1Target, columnName2Target, columnName3Target]))
{
while (reader.Read())
{
targetRows.Add(new CopyDataFromTableToTableModel
{
Column1 = reader.GetInt32(0),
Column2 = reader.GetString(1),
Column3 = reader.GetInt32(2),
});
}
}

List<CopyDataFromTableToTableModel> expectedTargetRows = [
new CopyDataFromTableToTableModel{ Column1 = 1, Column2 = "Hello1", Column3 = 11 },
new CopyDataFromTableToTableModel{ Column1 = 2, Column2 = "Hello2", Column3 = 22 },
];

Assert.That(targetRows, Is.EquivalentTo(expectedTargetRows).Using<CopyDataFromTableToTableModel>((x, y) =>
x.Column1 == y.Column1 &&
x.Column2 == y.Column2 &&
x.Column3 == y.Column3));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Migrator.Tests.Providers.Generic.Models;

public class CopyDataFromTableToTableModel
{
public int Column1 { get; set; }
public string Column2 { get; set; }
public int Column3 { get; set; }
}
Original file line number Diff line number Diff line change
@@ -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_CopyDataFromTableToTableTests : Generic_CopyDataFromTableToTableBase
{
[SetUp]
public async Task SetUpAsync()
{
await BeginOracleTransactionAsync();
}
}
Original file line number Diff line number Diff line change
@@ -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_CopyDataFromTableToTableTests : Generic_CopyDataFromTableToTableBase
{
[SetUp]
public async Task SetUpAsync()
{
await BeginPostgreSQLTransactionAsync();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,22 @@ public void ChangeColumn_DateTimeToDateTime2_Success()
Assert.That(columnBefore.Type == DbType.DateTime);
Assert.That(columnAfter.Type == DbType.DateTime2);
}

[Test, Ignore("This issue is not yet fixed. See https://github.com/dotnetprojects/Migrator.NET/issues/132")]
public void ChangeColumn_WithUniqueThenReChangeToNonUnique_UniqueConstraintShouldBeRemoved()
{
// Arrange
const string tableName = "TestTable";
const string columnName = "TestColumn";

Provider.AddTable(tableName, new Column(columnName, DbType.Int32, ColumnProperty.NotNull));

// Act
Provider.ChangeColumn(tableName, new Column(columnName, DbType.Int32, ColumnProperty.NotNull | ColumnProperty.Unique));
Provider.ChangeColumn(tableName, new Column(columnName, DbType.Int32, ColumnProperty.NotNull));

// Assert
var indexes = Provider.GetIndexes(tableName);
Assert.That(indexes, Is.Empty);
}
}
Original file line number Diff line number Diff line change
@@ -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_CopyDataFromTableToTableTests : Generic_CopyDataFromTableToTableBase
{
[SetUp]
public async Task SetUpAsync()
{
await BeginSQLServerTransactionAsync();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ public void ChangeColumn_HavingColumnPropertyUniqueAndIndex_RebuildSucceeds()
Provider.ExecuteNonQuery($"INSERT INTO {testTableName} ({propertyName1}, {propertyName2}) VALUES (2, 3)");

// Assert
var createScriptAfter = ((SQLiteTransformationProvider)Provider).GetSqlCreateTableScript(testTableName);
Assert.That(createScriptAfter, Does.Contain("Color2 TEXT NULL UNIQUE"));

using var command = Provider.GetCommand();
using var reader = Provider.ExecuteQuery(command, $"SELECT COUNT(*) as Count from {testTableName}");
reader.Read();
Expand All @@ -65,4 +68,26 @@ public void ChangeColumn_HavingColumnPropertyUniqueAndIndex_RebuildSucceeds()
Assert.That(indexAfter.Name, Is.EqualTo(indexName));
CollectionAssert.AreEquivalent(indexAfter.KeyColumns, new string[] { propertyName1, propertyName2 });
}

[Test]
public void ChangeColumn_StringFromNullToNotNull_StillNotNull()
{
// Arrange
const string testTableName = "MyDefaultTestTable";
const string propertyName1 = "Color1";
const string propertyName2 = "Color2";

Provider.AddTable(testTableName,
new Column(propertyName1, DbType.Int32, ColumnProperty.PrimaryKey),
new Column(propertyName2, DbType.String, 100, ColumnProperty.Null)
);

// Act
Provider.ChangeColumn(table: testTableName, new Column(propertyName2, DbType.String, ColumnProperty.NotNull));


// Assert
var createScriptAfter = ((SQLiteTransformationProvider)Provider).GetSqlCreateTableScript(testTableName);
Assert.That(createScriptAfter, Does.Contain("Color2 TEXT NOT NULL"));
}
}
Original file line number Diff line number Diff line change
@@ -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_CopyDataFromTableToTableTests : Generic_CopyDataFromTableToTableBase
{
[SetUp]
public async Task SetUpAsync()
{
await BeginSQLiteTransactionAsync();
}
}
10 changes: 10 additions & 0 deletions src/Migrator/Framework/ITransformationProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,16 @@ public interface ITransformationProvider : IDisposable
/// <returns></returns>
bool ConstraintExists(string table, string name);

/// <summary>
/// Copies data from source table to target table using INSERT INTO...SELECT..FROM
/// </summary>
/// <param name="sourceTableName"></param>
/// <param name="sourceColumnNames"></param>
/// <param name="targetTableName"></param>
/// <param name="targetColumnNames"></param>
/// <param name="orderBySourceColumns">Sort source by these columns. <paramref name="sourceColumnNames"/> must contain the <paramref name="orderBySourceColumns"/>.
void CopyDataFromTableToTable(string sourceTableName, List<string> sourceColumnNames, string targetTableName, List<string> targetColumnNames, List<string> orderBySourceColumns);

/// <summary>
/// Check to see if a primary key constraint exists on the table
/// </summary>
Expand Down
53 changes: 53 additions & 0 deletions src/Migrator/Providers/Impl/Oracle/OracleTransformationProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,59 @@ protected override void ConfigureParameterWithValue(IDbDataParameter parameter,
}
}

public override void CopyDataFromTableToTable(string sourceTableName, List<string> sourceColumnNames, string targetTableName, List<string> targetColumnNames, List<string> orderBySourceColumns)
{
orderBySourceColumns ??= [];

if (!TableExists(sourceTableName))
{
throw new Exception($"Source table '{QuoteTableNameIfRequired(sourceTableName)}' does not exist");
}

if (!TableExists(targetTableName))
{
throw new Exception($"Target table '{QuoteTableNameIfRequired(targetTableName)}' does not exist");
}

var sourceColumnsConcatenated = sourceColumnNames.Concat(orderBySourceColumns);

foreach (var column in sourceColumnsConcatenated)
{
if (!ColumnExists(sourceTableName, column))
{
throw new Exception($"Column {column} in source table does not exist.");
}
}

foreach (var column in targetColumnNames)
{
if (!ColumnExists(targetTableName, column))
{
throw new Exception($"Column {column} in target table does not exist.");
}
}

if (!orderBySourceColumns.All(x => sourceColumnNames.Contains(x)))
{
throw new Exception($"All columns in {nameof(orderBySourceColumns)} must be in {nameof(sourceColumnNames)}");
}

var sourceTableNameQuoted = QuoteTableNameIfRequired(sourceTableName);
var targetTableNameQuoted = QuoteTableNameIfRequired(targetTableName);

var sourceColumnNamesQuoted = sourceColumnNames.Select(QuoteColumnNameIfRequired).ToList();
var targetColumnNamesQuoted = targetColumnNames.Select(QuoteColumnNameIfRequired).ToList();
var orderBySourceColumnsQuoted = orderBySourceColumns.Select(QuoteColumnNameIfRequired).ToList();

var sourceColumnsJoined = string.Join(", ", sourceColumnNamesQuoted);
var targetColumnsJoined = string.Join(", ", targetColumnNamesQuoted);
var orderBySourceColumnsJoined = string.Join(", ", orderBySourceColumnsQuoted);


var sql = $"INSERT INTO {targetTableNameQuoted} ({targetColumnsJoined}) SELECT {sourceColumnsJoined} FROM {sourceTableNameQuoted} ORDER BY {orderBySourceColumnsJoined}";
ExecuteNonQuery(sql);
}

public override void RemoveColumnDefaultValue(string table, string column)
{
var sql = string.Format("ALTER TABLE {0} MODIFY {1} DEFAULT NULL", table, column);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,59 @@ public override void UpdateTargetFromSource(string tableSourceNotQuoted, string
ExecuteNonQuery(sql);
}

public override void CopyDataFromTableToTable(string sourceTableName, List<string> sourceColumnNames, string targetTableName, List<string> targetColumnNames, List<string> orderBySourceColumns)
{
orderBySourceColumns ??= [];

if (!TableExists(sourceTableName))
{
throw new Exception($"Source table '{QuoteTableNameIfRequired(sourceTableName)}' does not exist");
}

if (!TableExists(targetTableName))
{
throw new Exception($"Target table '{QuoteTableNameIfRequired(targetTableName)}' does not exist");
}

var sourceColumnsConcatenated = sourceColumnNames.Concat(orderBySourceColumns);

foreach (var column in sourceColumnsConcatenated)
{
if (!ColumnExists(sourceTableName, column))
{
throw new Exception($"Column {column} in source table does not exist.");
}
}

foreach (var column in targetColumnNames)
{
if (!ColumnExists(targetTableName, column))
{
throw new Exception($"Column {column} in target table does not exist.");
}
}

if (!orderBySourceColumns.All(x => sourceColumnNames.Contains(x)))
{
throw new Exception($"All columns in {nameof(orderBySourceColumns)} must be in {nameof(sourceColumnNames)}");
}

var sourceTableNameQuoted = QuoteTableNameIfRequired(sourceTableName);
var targetTableNameQuoted = QuoteTableNameIfRequired(targetTableName);

var sourceColumnNamesQuoted = sourceColumnNames.Select(QuoteColumnNameIfRequired).ToList();
var targetColumnNamesQuoted = targetColumnNames.Select(QuoteColumnNameIfRequired).ToList();
var orderBySourceColumnsQuoted = orderBySourceColumns.Select(QuoteColumnNameIfRequired).ToList();

var sourceColumnsJoined = string.Join(", ", sourceColumnNamesQuoted);
var targetColumnsJoined = string.Join(", ", targetColumnNamesQuoted);
var orderBySourceColumnsJoined = string.Join(", ", orderBySourceColumnsQuoted);


var sql = $"INSERT INTO {targetTableNameQuoted} ({targetColumnsJoined}) SELECT {sourceColumnsJoined} FROM {sourceTableNameQuoted} ORDER BY {orderBySourceColumnsJoined}";
ExecuteNonQuery(sql);
}

protected override void ConfigureParameterWithValue(IDbDataParameter parameter, int index, object value)
{
if (value is ushort)
Expand All @@ -879,4 +932,5 @@ protected override void ConfigureParameterWithValue(IDbDataParameter parameter,
base.ConfigureParameterWithValue(parameter, index, value);
}
}

}
Loading
Loading