feat(etl): add binary method overrides to DataTransformerBase
Add virtual methods to DataTransformerBase for GetBytes, GetChars, GetData, and GetDataTypeName that properly handle computed columns by throwing NotSupportedException when MapOrdinal returns -1. Update TransformingDataReader to delegate these methods to the transformer instead of directly to the source reader.
This commit is contained in:
@@ -225,8 +225,162 @@ public class TransformingDataReaderTests
|
||||
Assert.Equal("PassThrough", transformer.TransformerName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetBytes_ComputedColumn_ThrowsNotSupportedException()
|
||||
{
|
||||
// Arrange - transformer that returns -1 for ordinal 0 (computed)
|
||||
var source = Substitute.For<IDataReader>();
|
||||
source.FieldCount.Returns(2);
|
||||
source.GetName(0).Returns("Computed");
|
||||
source.GetName(1).Returns("B");
|
||||
var transformer = new ComputedColumnTransformer();
|
||||
var reader = transformer.Transform(source);
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<NotSupportedException>(() =>
|
||||
reader.GetBytes(0, 0, null, 0, 0));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetChars_ComputedColumn_ThrowsNotSupportedException()
|
||||
{
|
||||
// Arrange - transformer that returns -1 for ordinal 0 (computed)
|
||||
var source = Substitute.For<IDataReader>();
|
||||
source.FieldCount.Returns(2);
|
||||
source.GetName(0).Returns("Computed");
|
||||
source.GetName(1).Returns("B");
|
||||
var transformer = new ComputedColumnTransformer();
|
||||
var reader = transformer.Transform(source);
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<NotSupportedException>(() =>
|
||||
reader.GetChars(0, 0, null, 0, 0));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetData_ComputedColumn_ThrowsNotSupportedException()
|
||||
{
|
||||
// Arrange - transformer that returns -1 for ordinal 0 (computed)
|
||||
var source = Substitute.For<IDataReader>();
|
||||
source.FieldCount.Returns(2);
|
||||
source.GetName(0).Returns("Computed");
|
||||
source.GetName(1).Returns("B");
|
||||
var transformer = new ComputedColumnTransformer();
|
||||
var reader = transformer.Transform(source);
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<NotSupportedException>(() =>
|
||||
reader.GetData(0));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDataTypeName_ComputedColumn_ThrowsNotSupportedException()
|
||||
{
|
||||
// Arrange - transformer that returns -1 for ordinal 0 (computed)
|
||||
var source = Substitute.For<IDataReader>();
|
||||
source.FieldCount.Returns(2);
|
||||
source.GetName(0).Returns("Computed");
|
||||
source.GetName(1).Returns("B");
|
||||
var transformer = new ComputedColumnTransformer();
|
||||
var reader = transformer.Transform(source);
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<NotSupportedException>(() =>
|
||||
reader.GetDataTypeName(0));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetBytes_NonComputedColumn_DelegatesToSource()
|
||||
{
|
||||
// Arrange
|
||||
var source = Substitute.For<IDataReader>();
|
||||
source.FieldCount.Returns(2);
|
||||
source.GetName(0).Returns("A");
|
||||
source.GetName(1).Returns("B");
|
||||
var expectedBytes = new byte[] { 1, 2, 3 };
|
||||
source.GetBytes(1, 0, Arg.Any<byte[]?>(), 0, 3).Returns(3L);
|
||||
var transformer = new PassThroughTransformer();
|
||||
var reader = transformer.Transform(source);
|
||||
|
||||
// Act
|
||||
var buffer = new byte[3];
|
||||
var result = reader.GetBytes(1, 0, buffer, 0, 3);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(3L, result);
|
||||
source.Received(1).GetBytes(1, 0, buffer, 0, 3);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetChars_NonComputedColumn_DelegatesToSource()
|
||||
{
|
||||
// Arrange
|
||||
var source = Substitute.For<IDataReader>();
|
||||
source.FieldCount.Returns(2);
|
||||
source.GetName(0).Returns("A");
|
||||
source.GetName(1).Returns("B");
|
||||
source.GetChars(1, 0, Arg.Any<char[]?>(), 0, 3).Returns(3L);
|
||||
var transformer = new PassThroughTransformer();
|
||||
var reader = transformer.Transform(source);
|
||||
|
||||
// Act
|
||||
var buffer = new char[3];
|
||||
var result = reader.GetChars(1, 0, buffer, 0, 3);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(3L, result);
|
||||
source.Received(1).GetChars(1, 0, buffer, 0, 3);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetData_NonComputedColumn_DelegatesToSource()
|
||||
{
|
||||
// Arrange
|
||||
var source = Substitute.For<IDataReader>();
|
||||
source.FieldCount.Returns(2);
|
||||
source.GetName(0).Returns("A");
|
||||
source.GetName(1).Returns("B");
|
||||
var nestedReader = Substitute.For<IDataReader>();
|
||||
source.GetData(1).Returns(nestedReader);
|
||||
var transformer = new PassThroughTransformer();
|
||||
var reader = transformer.Transform(source);
|
||||
|
||||
// Act
|
||||
var result = reader.GetData(1);
|
||||
|
||||
// Assert
|
||||
Assert.Same(nestedReader, result);
|
||||
source.Received(1).GetData(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDataTypeName_NonComputedColumn_DelegatesToSource()
|
||||
{
|
||||
// Arrange
|
||||
var source = Substitute.For<IDataReader>();
|
||||
source.FieldCount.Returns(2);
|
||||
source.GetName(0).Returns("A");
|
||||
source.GetName(1).Returns("B");
|
||||
source.GetDataTypeName(1).Returns("nvarchar");
|
||||
var transformer = new PassThroughTransformer();
|
||||
var reader = transformer.Transform(source);
|
||||
|
||||
// Act
|
||||
var result = reader.GetDataTypeName(1);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("nvarchar", result);
|
||||
source.Received(1).GetDataTypeName(1);
|
||||
}
|
||||
|
||||
private class PassThroughTransformer : DataTransformerBase
|
||||
{
|
||||
public override string TransformerName => "PassThrough";
|
||||
}
|
||||
|
||||
private class ComputedColumnTransformer : DataTransformerBase
|
||||
{
|
||||
public override string TransformerName => "Computed";
|
||||
public override int MapOrdinal(int ordinal, IDataReader source) => ordinal == 0 ? -1 : ordinal;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user