Skip to content

Commit

Permalink
Microsoft.Data.Sqlite: Handle non-queries in SqliteDataReader
Browse files Browse the repository at this point in the history
Fixes #16044
  • Loading branch information
bricelam committed Jun 13, 2019
1 parent 507ef21 commit 46f4ede
Show file tree
Hide file tree
Showing 3 changed files with 277 additions and 29 deletions.
117 changes: 88 additions & 29 deletions src/Microsoft.Data.Sqlite.Core/SqliteDataReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public override int Depth
public override int FieldCount
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(FieldCount)))
: _record.FieldCount;
: (_record?.FieldCount ?? 0);

/// <summary>
/// Gets a handle to underlying prepared statement.
Expand Down Expand Up @@ -93,15 +93,19 @@ public override int RecordsAffected
/// <param name="name">The name of the column. The value is case-sensitive.</param>
/// <returns>The value.</returns>
public override object this[string name]
=> _record[name];
=> _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record[name];

/// <summary>
/// Gets the value of the specified column.
/// </summary>
/// <param name="ordinal">The zero-based column ordinal.</param>
/// <returns>The value.</returns>
public override object this[int ordinal]
=> _record[ordinal];
=> _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record[ordinal];

/// <summary>
/// Gets an enumerator that can be used to iterate through the rows in the data reader.
Expand All @@ -117,7 +121,7 @@ public override IEnumerator GetEnumerator()
public override bool Read()
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(Read)))
: _record.Read();
: (_record?.Read() ?? false);

/// <summary>
/// Advances to the next result set for batched statements.
Expand Down Expand Up @@ -267,7 +271,9 @@ protected override void Dispose(bool disposing)
public override string GetName(int ordinal)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetName)))
: _record.GetName(ordinal);
: _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record.GetName(ordinal);

/// <summary>
/// Gets the ordinal of the specified column.
Expand All @@ -277,7 +283,9 @@ public override string GetName(int ordinal)
public override int GetOrdinal(string name)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetOrdinal)))
: _record.GetOrdinal(name);
: _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record.GetOrdinal(name);

/// <summary>
/// Gets the declared data type name of the specified column. The storage class is returned for computed
Expand All @@ -290,7 +298,9 @@ public override int GetOrdinal(string name)
public override string GetDataTypeName(int ordinal)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetDataTypeName)))
: _record.GetDataTypeName(ordinal);
: _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record.GetDataTypeName(ordinal);

/// <summary>
/// Gets the data type of the specified column.
Expand All @@ -300,7 +310,9 @@ public override string GetDataTypeName(int ordinal)
public override Type GetFieldType(int ordinal)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetFieldType)))
: _record.GetFieldType(ordinal);
: _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record.GetFieldType(ordinal);

/// <summary>
/// Gets a value indicating whether the specified column is <see cref="DBNull" />.
Expand All @@ -310,7 +322,9 @@ public override Type GetFieldType(int ordinal)
public override bool IsDBNull(int ordinal)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(IsDBNull)))
: _record.IsDBNull(ordinal);
: _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record.IsDBNull(ordinal);

/// <summary>
/// Gets the value of the specified column as a <see cref="bool" />.
Expand All @@ -320,7 +334,9 @@ public override bool IsDBNull(int ordinal)
public override bool GetBoolean(int ordinal)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetBoolean)))
: _record.GetBoolean(ordinal);
: _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record.GetBoolean(ordinal);

/// <summary>
/// Gets the value of the specified column as a <see cref="byte" />.
Expand All @@ -330,7 +346,9 @@ public override bool GetBoolean(int ordinal)
public override byte GetByte(int ordinal)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetByte)))
: _record.GetByte(ordinal);
: _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record.GetByte(ordinal);

/// <summary>
/// Gets the value of the specified column as a <see cref="char" />.
Expand All @@ -340,7 +358,9 @@ public override byte GetByte(int ordinal)
public override char GetChar(int ordinal)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetChar)))
: _record.GetChar(ordinal);
: _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record.GetChar(ordinal);

/// <summary>
/// Gets the value of the specified column as a <see cref="DateTime" />.
Expand All @@ -350,7 +370,9 @@ public override char GetChar(int ordinal)
public override DateTime GetDateTime(int ordinal)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetDateTime)))
: _record.GetDateTime(ordinal);
: _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record.GetDateTime(ordinal);

/// <summary>
/// Gets the value of the specified column as a <see cref="DateTimeOffset" />.
Expand All @@ -360,7 +382,9 @@ public override DateTime GetDateTime(int ordinal)
public virtual DateTimeOffset GetDateTimeOffset(int ordinal)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetDateTimeOffset)))
: _record.GetDateTimeOffset(ordinal);
: _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record.GetDateTimeOffset(ordinal);

/// <summary>
/// Gets the value of the specified column as a <see cref="TimeSpan" />.
Expand All @@ -370,7 +394,9 @@ public virtual DateTimeOffset GetDateTimeOffset(int ordinal)
public virtual TimeSpan GetTimeSpan(int ordinal)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetTimeSpan)))
: _record.GetTimeSpan(ordinal);
: _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record.GetTimeSpan(ordinal);

/// <summary>
/// Gets the value of the specified column as a <see cref="decimal" />.
Expand All @@ -380,7 +406,9 @@ public virtual TimeSpan GetTimeSpan(int ordinal)
public override decimal GetDecimal(int ordinal)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetDecimal)))
: _record.GetDecimal(ordinal);
: _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record.GetDecimal(ordinal);

/// <summary>
/// Gets the value of the specified column as a <see cref="double" />.
Expand All @@ -390,7 +418,9 @@ public override decimal GetDecimal(int ordinal)
public override double GetDouble(int ordinal)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetDouble)))
: _record.GetDouble(ordinal);
: _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record.GetDouble(ordinal);

/// <summary>
/// Gets the value of the specified column as a <see cref="float" />.
Expand All @@ -400,7 +430,9 @@ public override double GetDouble(int ordinal)
public override float GetFloat(int ordinal)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetFloat)))
: _record.GetFloat(ordinal);
: _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record.GetFloat(ordinal);

/// <summary>
/// Gets the value of the specified column as a <see cref="Guid" />.
Expand All @@ -410,7 +442,9 @@ public override float GetFloat(int ordinal)
public override Guid GetGuid(int ordinal)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetGuid)))
: _record.GetGuid(ordinal);
: _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record.GetGuid(ordinal);

/// <summary>
/// Gets the value of the specified column as a <see cref="short" />.
Expand All @@ -420,7 +454,9 @@ public override Guid GetGuid(int ordinal)
public override short GetInt16(int ordinal)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetInt16)))
: _record.GetInt16(ordinal);
: _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record.GetInt16(ordinal);

/// <summary>
/// Gets the value of the specified column as a <see cref="int" />.
Expand All @@ -430,7 +466,9 @@ public override short GetInt16(int ordinal)
public override int GetInt32(int ordinal)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetInt32)))
: _record.GetInt32(ordinal);
: _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record.GetInt32(ordinal);

/// <summary>
/// Gets the value of the specified column as a <see cref="long" />.
Expand All @@ -440,7 +478,9 @@ public override int GetInt32(int ordinal)
public override long GetInt64(int ordinal)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetInt64)))
: _record.GetInt64(ordinal);
: _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record.GetInt64(ordinal);

/// <summary>
/// Gets the value of the specified column as a <see cref="string" />.
Expand All @@ -450,7 +490,9 @@ public override long GetInt64(int ordinal)
public override string GetString(int ordinal)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetString)))
: _record.GetString(ordinal);
: _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record.GetString(ordinal);

/// <summary>
/// Reads a stream of bytes from the specified column. Not supported.
Expand All @@ -464,7 +506,9 @@ public override string GetString(int ordinal)
public override long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffset, int length)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetBytes)))
: _record.GetBytes(ordinal, dataOffset, buffer, bufferOffset, length);
: _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record.GetBytes(ordinal, dataOffset, buffer, bufferOffset, length);

/// <summary>
/// Reads a stream of characters from the specified column. Not supported.
Expand All @@ -478,7 +522,9 @@ public override long GetBytes(int ordinal, long dataOffset, byte[] buffer, int b
public override long GetChars(int ordinal, long dataOffset, char[] buffer, int bufferOffset, int length)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetChars)))
: _record.GetChars(ordinal, dataOffset, buffer, bufferOffset, length);
: _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record.GetChars(ordinal, dataOffset, buffer, bufferOffset, length);

/// <summary>
/// Retrieves data as a Stream. If the reader includes rowid (or any of its aliases), a
Expand All @@ -490,7 +536,9 @@ public override long GetChars(int ordinal, long dataOffset, char[] buffer, int b
public override Stream GetStream(int ordinal)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetStream)))
: _record.GetStream(ordinal);
: _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record.GetStream(ordinal);

/// <summary>
/// Gets the value of the specified column.
Expand All @@ -501,7 +549,9 @@ public override Stream GetStream(int ordinal)
public override T GetFieldValue<T>(int ordinal)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetFieldValue)))
: _record.GetFieldValue<T>(ordinal);
: _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record.GetFieldValue<T>(ordinal);

/// <summary>
/// Gets the value of the specified column.
Expand All @@ -511,7 +561,9 @@ public override T GetFieldValue<T>(int ordinal)
public override object GetValue(int ordinal)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetValue)))
: _record.GetValue(ordinal);
: _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record.GetValue(ordinal);

/// <summary>
/// Gets the column values of the current row.
Expand All @@ -521,7 +573,9 @@ public override object GetValue(int ordinal)
public override int GetValues(object[] values)
=> _closed
? throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetValues)))
: _record.GetValues(values);
: _record == null
? throw new InvalidOperationException(Resources.NoData)
: _record.GetValues(values);

/// <summary>
/// Returns a System.Data.DataTable that describes the column metadata of the System.Data.Common.DbDataReader.
Expand All @@ -534,6 +588,11 @@ public override DataTable GetSchemaTable()
throw new InvalidOperationException(Resources.DataReaderClosed(nameof(GetSchemaTable)));
}

if (_record == null)
{
throw new InvalidOperationException(Resources.NoData);
}

var schemaTable = new DataTable("SchemaTable");

var ColumnName = new DataColumn(SchemaTableColumn.ColumnName, typeof(string));
Expand Down
13 changes: 13 additions & 0 deletions test/Microsoft.Data.Sqlite.Tests/SqliteCommandTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,19 @@ public void ExecuteScalar_returns_null_when_empty()
}
}

[Fact]
public void ExecuteScalar_returns_null_when_non_query()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
var command = connection.CreateCommand();
command.CommandText = "CREATE TABLE Data (Value);";
connection.Open();

Assert.Null(command.ExecuteScalar());
}
}

[Fact]
public void ExecuteScalar_returns_long_when_integer()
{
Expand Down
Loading

0 comments on commit 46f4ede

Please sign in to comment.