Skip to content

Commit 6c49dc0

Browse files
committed
Detect simple column mapping errors.
1 parent 321ef4d commit 6c49dc0

File tree

3 files changed

+97
-6
lines changed

3 files changed

+97
-6
lines changed

src/MySqlConnector/MySql.Data.MySqlClient/MySqlBulkCopy.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ private async ValueTask WriteToServerAsync(IOBehavior ioBehavior, CancellationTo
159159
using (var reader = (MySqlDataReader) await cmd.ExecuteReaderAsync(CommandBehavior.SchemaOnly, ioBehavior, cancellationToken).ConfigureAwait(false))
160160
{
161161
var schema = reader.GetColumnSchema();
162-
for (var i = 0; i < schema.Count; i++)
162+
for (var i = 0; i < Math.Min(m_valuesEnumerator!.FieldCount, schema.Count); i++)
163163
{
164164
var destinationColumn = reader.GetName(i);
165165
if (schema[i].DataTypeName == "BIT")
@@ -188,7 +188,7 @@ private async ValueTask WriteToServerAsync(IOBehavior ioBehavior, CancellationTo
188188
}
189189

190190
// set columns and expressions from the column mappings
191-
for (var i = 0; i < m_valuesEnumerator!.FieldCount; i++)
191+
for (var i = 0; i < m_valuesEnumerator.FieldCount; i++)
192192
{
193193
var columnMapping = columnMappings.FirstOrDefault(x => x.SourceOrdinal == i);
194194
if (columnMapping is null)
@@ -199,7 +199,7 @@ private async ValueTask WriteToServerAsync(IOBehavior ioBehavior, CancellationTo
199199
else
200200
{
201201
if (columnMapping.DestinationColumn.Length == 0)
202-
throw new InvalidOperationException("MySqlBulkCopyColumnMapping.DestinationName is not set.");
202+
throw new InvalidOperationException("MySqlBulkCopyColumnMapping.DestinationName is not set for SourceOrdinal {0}".FormatInvariant(columnMapping.SourceOrdinal));
203203
if (columnMapping.DestinationColumn[0] == '@')
204204
bulkLoader.Columns.Add(columnMapping.DestinationColumn);
205205
else
@@ -209,6 +209,12 @@ private async ValueTask WriteToServerAsync(IOBehavior ioBehavior, CancellationTo
209209
}
210210
}
211211

212+
foreach (var columnMapping in columnMappings)
213+
{
214+
if (columnMapping.SourceOrdinal < 0 || columnMapping.SourceOrdinal >= m_valuesEnumerator.FieldCount)
215+
throw new InvalidOperationException("SourceOrdinal {0} is an invalid value".FormatInvariant(columnMapping.SourceOrdinal));
216+
}
217+
212218
await bulkLoader.LoadAsync(ioBehavior, cancellationToken).ConfigureAwait(false);
213219

214220
if (closeConnection)

tests/SideBySide/BulkLoaderAsync.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,8 +499,19 @@ public async Task BulkLoadDataTableWithTooLongData()
499499
var bulkCopy = new MySqlBulkCopy(connection)
500500
{
501501
DestinationTableName = "bulk_load_data_table",
502+
ColumnMappings =
503+
{
504+
new MySqlBulkCopyColumnMapping(0, "b"),
505+
}
502506
};
503-
await Assert.ThrowsAsync<MySqlException>(async () => await bulkCopy.WriteToServerAsync(dataTable));
507+
try
508+
{
509+
await bulkCopy.WriteToServerAsync(dataTable);
510+
Assert.True(false, "Expected exception wasn't thrown");
511+
}
512+
catch (MySqlException ex) when (ex.InnerException?.InnerException is NotSupportedException)
513+
{
514+
}
504515
}
505516

506517
[Theory]

tests/SideBySide/BulkLoaderSync.cs

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -822,8 +822,8 @@ public void BulkCopyColumnMappings()
822822
Rows =
823823
{
824824
new object[] { 1, 100, "a", "A", new byte[] { 0x33, 0x30 } },
825-
new object[] { 2, 200, "bb", "BB", new byte[] { 0x33, 0x31 } },
826-
new object[] { 3, 300, "ccc", "CCC", new byte[] { 0x33, 0x32 } },
825+
new object[] { 2, 200, "bb", "BB", new byte[] { 0x33, 0x31 } },
826+
new object[] { 3, 300, "ccc", "CCC", new byte[] { 0x33, 0x32 } },
827827
}
828828
};
829829

@@ -844,6 +844,80 @@ public void BulkCopyColumnMappings()
844844
Assert.Equal(new byte[] { 0x33, 0x32 }, reader.GetValue(2));
845845
Assert.False(reader.Read());
846846
}
847+
848+
[Fact]
849+
public void BulkCopyColumnMappingsInvalidSourceOrdinal()
850+
{
851+
using var connection = new MySqlConnection(GetLocalConnectionString());
852+
connection.Open();
853+
using (var cmd = new MySqlCommand(@"drop table if exists bulk_copy_column_mapping;
854+
create table bulk_copy_column_mapping(intvalue int, `text` text, data blob);", connection))
855+
{
856+
cmd.ExecuteNonQuery();
857+
}
858+
859+
var bulkCopy = new MySqlBulkCopy(connection)
860+
{
861+
DestinationTableName = "bulk_copy_column_mapping",
862+
ColumnMappings =
863+
{
864+
new MySqlBulkCopyColumnMapping(6, "@val", "intvalue = @val + 1"),
865+
},
866+
};
867+
868+
var dataTable = new DataTable()
869+
{
870+
Columns =
871+
{
872+
new DataColumn("c1", typeof(int)),
873+
},
874+
Rows =
875+
{
876+
new object[] { 1 },
877+
new object[] { 2 },
878+
new object[] { 3 },
879+
}
880+
};
881+
882+
Assert.Throws<InvalidOperationException>(() => bulkCopy.WriteToServer(dataTable));
883+
}
884+
885+
[Fact]
886+
public void BulkCopyColumnMappingsInvalidDestinationColumn()
887+
{
888+
using var connection = new MySqlConnection(GetLocalConnectionString());
889+
connection.Open();
890+
using (var cmd = new MySqlCommand(@"drop table if exists bulk_copy_column_mapping;
891+
create table bulk_copy_column_mapping(intvalue int, `text` text, data blob);", connection))
892+
{
893+
cmd.ExecuteNonQuery();
894+
}
895+
896+
var bulkCopy = new MySqlBulkCopy(connection)
897+
{
898+
DestinationTableName = "bulk_copy_column_mapping",
899+
ColumnMappings =
900+
{
901+
new MySqlBulkCopyColumnMapping { SourceOrdinal = 0 },
902+
},
903+
};
904+
905+
var dataTable = new DataTable()
906+
{
907+
Columns =
908+
{
909+
new DataColumn("c1", typeof(int)),
910+
},
911+
Rows =
912+
{
913+
new object[] { 1 },
914+
new object[] { 2 },
915+
new object[] { 3 },
916+
}
917+
};
918+
919+
Assert.Throws<InvalidOperationException>(() => bulkCopy.WriteToServer(dataTable));
920+
}
847921
#endif
848922

849923
[Fact]

0 commit comments

Comments
 (0)