Skip to content

Commit c2440b8

Browse files
committed
Fix seek for ColumnStream (#5224)
Fixes #5223 (cherry picked from commit 820cfcd) # Conflicts: # src/Npgsql/Internal/NpgsqlReadBuffer.Stream.cs # test/Npgsql.Tests/ReaderTests.cs
1 parent 31bc401 commit c2440b8

File tree

2 files changed

+54
-9
lines changed

2 files changed

+54
-9
lines changed

src/Npgsql/NpgsqlReadBuffer.Stream.cs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public override long Position
6464
{
6565
if (value < 0)
6666
throw new ArgumentOutOfRangeException(nameof(value), "Non - negative number required.");
67-
Seek(_start + value, SeekOrigin.Begin);
67+
Seek(value, SeekOrigin.Begin);
6868
}
6969
}
7070

@@ -86,24 +86,25 @@ public override long Seek(long offset, SeekOrigin origin)
8686
var tempPosition = unchecked(_start + (int)offset);
8787
if (offset < 0 || tempPosition < _start)
8888
throw new IOException(seekBeforeBegin);
89-
_buf.ReadPosition = _start;
90-
return tempPosition;
89+
_buf.ReadPosition = tempPosition;
90+
_read = (int)offset;
91+
return _read;
9192
}
9293
case SeekOrigin.Current:
9394
{
9495
var tempPosition = unchecked(_buf.ReadPosition + (int)offset);
9596
if (unchecked(_buf.ReadPosition + offset) < _start || tempPosition < _start)
9697
throw new IOException(seekBeforeBegin);
97-
_buf.ReadPosition = tempPosition;
98-
return tempPosition;
98+
_read += (int)offset;
99+
return _read;
99100
}
100101
case SeekOrigin.End:
101102
{
102-
var tempPosition = unchecked(_len + (int)offset);
103-
if (unchecked(_len + offset) < _start || tempPosition < _start)
103+
var tempPosition = unchecked(_start + _len + (int)offset);
104+
if (unchecked(_start + _len + offset) < _start || tempPosition < _start)
104105
throw new IOException(seekBeforeBegin);
105-
_buf.ReadPosition = tempPosition;
106-
return tempPosition;
106+
_read = _len + (int)offset;
107+
return _read;
107108
}
108109
default:
109110
throw new ArgumentOutOfRangeException(nameof(origin), "Invalid seek origin.");

test/Npgsql.Tests/ReaderTests.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,6 +1508,50 @@ static Func<NpgsqlDataReader, int, Task<Stream>> BuildStreamGetter(bool isAsync)
15081508
? (Func<NpgsqlDataReader, int, Task<Stream>>)((r, index) => r.GetStreamAsync(index))
15091509
: (r, index) => Task.FromResult(r.GetStream(index));
15101510

1511+
[Test, IssueLink("https://github.com/npgsql/npgsql/issues/5223")]
1512+
public async Task GetStream_seek()
1513+
{
1514+
// Sequential doesn't allow to seek
1515+
if (IsSequential)
1516+
return;
1517+
1518+
await using var conn = await OpenConnectionAsync();
1519+
await using var cmd = conn.CreateCommand();
1520+
cmd.CommandText = "SELECT 'abcdefgh'";
1521+
await using var reader = await cmd.ExecuteReaderAsync();
1522+
await reader.ReadAsync();
1523+
1524+
var buffer = new byte[4];
1525+
1526+
await using var stream = reader.GetStream(0);
1527+
Assert.IsTrue(stream.CanSeek);
1528+
1529+
var seekPosition = stream.Seek(-1, SeekOrigin.End);
1530+
Assert.That(seekPosition, Is.EqualTo(stream.Length - 1));
1531+
var read = stream.Read(buffer);
1532+
Assert.That(read, Is.EqualTo(1));
1533+
Assert.That(Encoding.ASCII.GetString(buffer, 0, 1), Is.EqualTo("h"));
1534+
read = stream.Read(buffer);
1535+
Assert.That(read, Is.EqualTo(0));
1536+
1537+
seekPosition = stream.Seek(2, SeekOrigin.Begin);
1538+
Assert.That(seekPosition, Is.EqualTo(2));
1539+
read = stream.Read(buffer);
1540+
Assert.That(read, Is.EqualTo(buffer.Length));
1541+
Assert.That(Encoding.ASCII.GetString(buffer), Is.EqualTo("cdef"));
1542+
1543+
seekPosition = stream.Seek(-3, SeekOrigin.Current);
1544+
Assert.That(seekPosition, Is.EqualTo(3));
1545+
read = stream.Read(buffer);
1546+
Assert.That(read, Is.EqualTo(buffer.Length));
1547+
Assert.That(Encoding.ASCII.GetString(buffer), Is.EqualTo("defg"));
1548+
1549+
stream.Position = 1;
1550+
read = stream.Read(buffer);
1551+
Assert.That(read, Is.EqualTo(buffer.Length));
1552+
Assert.That(Encoding.ASCII.GetString(buffer), Is.EqualTo("bcde"));
1553+
}
1554+
15111555
#endregion GetBytes / GetStream
15121556

15131557
#region GetChars / GetTextReader

0 commit comments

Comments
 (0)