fix(etl): address Codex MCP review findings for Phase 2
- Filter MERGE SQL columns to only include columns that exist in destination (allColumns and updateColumns were using unfiltered source columns) - Fix schema-qualified table names to use proper [schema].[table] format instead of wrapping entire name in single brackets - Add empty column mapping validation to throw early if no columns intersect - Add JdeDateTransformer output column collision detection in OnInitialize - Add TODO comment for WithCommandTimeout (stored but not yet passed to destinations) - Add tests for FormatQualifiedTableName and output column collision
This commit is contained in:
@@ -98,4 +98,20 @@ public class CommonScriptsTests
|
||||
Assert.Equal("TimeoutScript", runner.ScriptName);
|
||||
Assert.NotNull(runner);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("WorkOrder", "[dbo].[WorkOrder]")]
|
||||
[InlineData("dbo.WorkOrder", "[dbo].[WorkOrder]")]
|
||||
[InlineData("[dbo].[WorkOrder]", "[dbo].[WorkOrder]")]
|
||||
[InlineData("Config.Settings", "[Config].[Settings]")]
|
||||
[InlineData("[Config].[Settings]", "[Config].[Settings]")]
|
||||
[InlineData("myschema.MyTable", "[myschema].[MyTable]")]
|
||||
public void FormatQualifiedTableName_VariousFormats_FormatsCorrectly(string input, string expected)
|
||||
{
|
||||
// Act
|
||||
var result = CommonScripts.FormatQualifiedTableName(input);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,6 +240,46 @@ public class JdeDateTransformerTests
|
||||
Assert.Equal(sentinel, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OutputColumnConflictsWithExistingColumn_ThrowsInvalidOperationException()
|
||||
{
|
||||
// Arrange - "Name" column exists and we try to use it as output
|
||||
var source = CreateMockReader(new[] { "Id", "UPMJ", "TDAY", "Name" }, new object[] { 1, 124001m, 120000m, "Test" });
|
||||
var transformer = new JdeDateTransformer("UPMJ", "TDAY", "Name"); // "Name" conflicts
|
||||
|
||||
// Act & Assert
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => transformer.Transform(source));
|
||||
Assert.Contains("conflicts with existing column", ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OutputColumnMatchesDateColumn_Succeeds()
|
||||
{
|
||||
// Arrange - output column can match the date column name (it replaces it)
|
||||
var source = CreateMockReader(new[] { "Id", "UPMJ", "TDAY", "Name" }, new object[] { 1, 124001m, 120000m, "Test" });
|
||||
var transformer = new JdeDateTransformer("UPMJ", "TDAY", "UPMJ"); // Same as date column
|
||||
|
||||
// Act - should not throw
|
||||
var reader = transformer.Transform(source);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("UPMJ", reader.GetName(1)); // Still named UPMJ
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OutputColumnMatchesTimeColumn_Succeeds()
|
||||
{
|
||||
// Arrange - output column can match the time column name (it's removed anyway)
|
||||
var source = CreateMockReader(new[] { "Id", "UPMJ", "TDAY", "Name" }, new object[] { 1, 124001m, 120000m, "Test" });
|
||||
var transformer = new JdeDateTransformer("UPMJ", "TDAY", "TDAY"); // Same as time column
|
||||
|
||||
// Act - should not throw
|
||||
var reader = transformer.Transform(source);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(3, reader.FieldCount); // One column removed
|
||||
}
|
||||
|
||||
private static IDataReader CreateMockReader(string[] columns, object[] values)
|
||||
{
|
||||
var reader = Substitute.For<IDataReader>();
|
||||
|
||||
Reference in New Issue
Block a user