Skip to content

Commit

Permalink
Case insensitive SqliteDataReader
Browse files Browse the repository at this point in the history
Fixes #24011
  • Loading branch information
william-des authored and bricelam committed Apr 26, 2021
1 parent 90f8575 commit 9e17139
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 10 deletions.
3 changes: 2 additions & 1 deletion src/Microsoft.Data.Sqlite.Core/SqliteDataReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,9 @@ public override int RecordsAffected
/// <summary>
/// Gets the value of the specified column.
/// </summary>
/// <param name="name">The name of the column. The value is case-sensitive.</param>
/// <param name="name">The name of the column.</param>
/// <returns>The value.</returns>
/// <remarks>Performs a case-sensitive lookup first. If it fails, a second, case-insensitive search occurs.</remarks>
/// <seealso href="https://docs.microsoft.com/dotnet/standard/data/sqlite/types">Data Types</seealso>
public override object this[string name]
=> _record == null
Expand Down
7 changes: 7 additions & 0 deletions src/Microsoft.Data.Sqlite.Core/SqliteDataRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,13 @@ public virtual int GetOrdinal(string name)
return ordinal;
}

var insensitiveMatchingColumns = _columnNameOrdinalCache.Where(kv => kv.Key.Equals(name, StringComparison.OrdinalIgnoreCase));
if(insensitiveMatchingColumns.Count() == 1) {
ordinal = insensitiveMatchingColumns.First().Value;
_columnNameOrdinalCache.Add(name, ordinal);
return ordinal;
}

// NB: Message is provided by framework
throw new ArgumentOutOfRangeException(nameof(name), name, message: null);
}
Expand Down
23 changes: 14 additions & 9 deletions test/Microsoft.Data.Sqlite.Tests/SqliteDataReaderTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1276,19 +1276,21 @@ public void GetOrdinal_works()
}
}

[Fact]
public void GetOrdinal_throws_when_out_of_range()
[Theory]
[InlineData("SELECT 1;", "Name")]
[InlineData("SELECT 1 as Id, 2 as ID;", "id")]
public void GetOrdinal_throws_when_out_of_range(string query, string columnName)
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();

using (var reader = connection.ExecuteReader("SELECT 1;"))
using (var reader = connection.ExecuteReader(query))
{
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => reader.GetOrdinal("Name"));
var ex = Assert.Throws<ArgumentOutOfRangeException>(() => reader.GetOrdinal(columnName));
Assert.NotNull(ex.Message);
Assert.Equal("name", ex.ParamName);
Assert.Equal("Name", ex.ActualValue);
Assert.Equal(columnName, ex.ActualValue);
}
}
}
Expand Down Expand Up @@ -1583,19 +1585,22 @@ public void Item_by_ordinal_throws_when_non_query()
}
}

[Fact]
public void Item_by_name_works()
[Theory]
[InlineData("SELECT 1 as Id;", "Id", 1L)]
[InlineData("SELECT 1 as Id;", "id", 1L)]
[InlineData("SELECT 1 as Id, 2 as id;", "id", 2L)]
public void Item_by_name_works(string query, string column, long expected)
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
connection.Open();

using (var reader = connection.ExecuteReader("SELECT 1 AS Id;"))
using (var reader = connection.ExecuteReader(query))
{
var hasData = reader.Read();
Assert.True(hasData);

Assert.Equal(1L, reader["Id"]);
Assert.Equal(expected, reader[column]);
}
}
}
Expand Down

0 comments on commit 9e17139

Please sign in to comment.