You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by pt...@apache.org on 2023/01/25 08:21:33 UTC

[ignite-3] branch main updated: IGNITE-18627 .NET: Fix empty result set handling in IgniteDbDataReader (#1573)

This is an automated email from the ASF dual-hosted git repository.

ptupitsyn pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new 748c41b56c IGNITE-18627 .NET: Fix empty result set handling in IgniteDbDataReader (#1573)
748c41b56c is described below

commit 748c41b56c026e172e6218001d980ce20dc3a611
Author: Pavel Tupitsyn <pt...@apache.org>
AuthorDate: Wed Jan 25 10:21:27 2023 +0200

    IGNITE-18627 .NET: Fix empty result set handling in IgniteDbDataReader (#1573)
    
    * Fix `IndexOutOfRangeException` when reading empty result set
    * Fix `HasRows` to return false for empty result set
    * Fix `NextResult` to return false instead of throwing exception
---
 .../Sql/IgniteDbDataReaderTests.cs                 | 28 ++++++++++++++++++++--
 .../dotnet/Apache.Ignite/Internal/Sql/ResultSet.cs |  6 +++++
 .../dotnet/Apache.Ignite/Sql/IgniteDbDataReader.cs | 14 +++++------
 3 files changed, 39 insertions(+), 9 deletions(-)

diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/Sql/IgniteDbDataReaderTests.cs b/modules/platforms/dotnet/Apache.Ignite.Tests/Sql/IgniteDbDataReaderTests.cs
index a0adbae08a..937918196a 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/Sql/IgniteDbDataReaderTests.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/Sql/IgniteDbDataReaderTests.cs
@@ -555,12 +555,13 @@ public class IgniteDbDataReaderTests : IgniteTestsBase
     }
 
     [Test]
+    [SuppressMessage("Performance", "CA1849:Call async methods when in an async method", Justification = "Testing sync method.")]
     public async Task TestNextResult()
     {
         await using var reader = await ExecuteReader();
 
-        Assert.Throws<NotSupportedException>(() => reader.NextResult());
-        Assert.ThrowsAsync<NotSupportedException>(() => reader.NextResultAsync());
+        Assert.IsFalse(reader.NextResult());
+        Assert.IsFalse(await reader.NextResultAsync());
     }
 
     [Test]
@@ -631,6 +632,18 @@ public class IgniteDbDataReaderTests : IgniteTestsBase
         Assert.AreEqual(9, dt.Rows.Count);
     }
 
+    [Test]
+    public async Task TestDataTableLoadEmptyResultSet()
+    {
+        await using var reader = await Client.Sql.ExecuteReaderAsync(null, "SELECT * FROM TBL_ALL_COLUMNS_SQL WHERE KEY > 100");
+
+        var dt = new DataTable();
+        dt.Load(reader);
+
+        Assert.AreEqual(14, dt.Columns.Count);
+        Assert.AreEqual(0, dt.Rows.Count);
+    }
+
     [Test]
     public void TestExecuteReaderThrowsOnDmlQuery()
     {
@@ -640,6 +653,17 @@ public class IgniteDbDataReaderTests : IgniteTestsBase
         Assert.AreEqual("ExecuteReaderAsync does not support queries without row set (DDL, DML).", ex!.Message);
     }
 
+    [Test]
+    public async Task TestEmptyResultSet()
+    {
+        await using var reader = await Client.Sql.ExecuteReaderAsync(null, "SELECT * FROM TBL_ALL_COLUMNS_SQL WHERE KEY > 100");
+        bool readRes = await reader.ReadAsync();
+
+        Assert.IsFalse(readRes);
+        Assert.AreEqual(14, reader.FieldCount);
+        Assert.IsFalse(reader.HasRows);
+    }
+
     private async Task<IgniteDbDataReader> ExecuteReader()
     {
         var reader = await Client.Sql.ExecuteReaderAsync(null, AllColumnsQuery);
diff --git a/modules/platforms/dotnet/Apache.Ignite/Internal/Sql/ResultSet.cs b/modules/platforms/dotnet/Apache.Ignite/Internal/Sql/ResultSet.cs
index d4003f3e84..4ac7944c30 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Internal/Sql/ResultSet.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Internal/Sql/ResultSet.cs
@@ -78,6 +78,7 @@ namespace Apache.Ignite.Internal.Sql
             if (HasRowSet)
             {
                 _buffer = buf.Slice(reader.Consumed);
+                HasRows = reader.ReadArrayHeader() > 0;
             }
             else
             {
@@ -112,6 +113,11 @@ namespace Apache.Ignite.Internal.Sql
         /// </summary>
         internal bool IsDisposed => (_resourceId == null || _resourceClosed) && _bufferReleased > 0;
 
+        /// <summary>
+        /// Gets a value indicating whether this result set has any rows in it.
+        /// </summary>
+        internal bool HasRows { get; }
+
         /// <inheritdoc/>
         public async ValueTask<List<T>> ToListAsync() =>
             await CollectAsync(
diff --git a/modules/platforms/dotnet/Apache.Ignite/Sql/IgniteDbDataReader.cs b/modules/platforms/dotnet/Apache.Ignite/Sql/IgniteDbDataReader.cs
index f18312ef2a..64726ab664 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Sql/IgniteDbDataReader.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Sql/IgniteDbDataReader.cs
@@ -77,7 +77,7 @@ public sealed class IgniteDbDataReader : DbDataReader, IDbColumnSchemaGenerator
     public override int RecordsAffected => checked((int)_resultSet.AffectedRows);
 
     /// <inheritdoc/>
-    public override bool HasRows => _resultSet.HasRowSet;
+    public override bool HasRows => _resultSet.HasRows;
 
     /// <inheritdoc/>
     public override bool IsClosed => _resultSet.IsDisposed;
@@ -290,7 +290,7 @@ public sealed class IgniteDbDataReader : DbDataReader, IDbColumnSchemaGenerator
     public override bool IsDBNull(int ordinal) => GetReader().IsNull(ordinal);
 
     /// <inheritdoc/>
-    public override bool NextResult() => throw new NotSupportedException("Batched result sets are not supported.");
+    public override bool NextResult() => false;
 
     /// <inheritdoc/>
     public override bool Read() => ReadNextRowInCurrentPage() || FetchNextPage().GetAwaiter().GetResult();
@@ -520,18 +520,18 @@ public sealed class IgniteDbDataReader : DbDataReader, IDbColumnSchemaGenerator
             return false;
         }
 
-        ReadFirstRowInCurrentPage();
+        return ReadFirstRowInCurrentPage();
 
-        return true;
-
-        void ReadFirstRowInCurrentPage()
+        bool ReadFirstRowInCurrentPage()
         {
             var reader = _pageEnumerator.Current.GetReader();
 
             _pageRowCount = reader.ReadArrayHeader();
             _pageRowOffset = reader.Consumed;
-            _pageRowSize = reader.ReadBinaryHeader() + reader.Consumed - _pageRowOffset;
             _pageRowIndex = 0;
+            _pageRowSize = (_pageRowCount > 0 ? reader.ReadBinaryHeader() : 0) + reader.Consumed - _pageRowOffset;
+
+            return _pageRowCount > 0;
         }
     }
 }