Skip to content

Commit 60eeb0b

Browse files
committed
Fix seek for ColumnStream (#5224)
Fixes #5223 (cherry picked from commit 820cfcd)
1 parent 4e76cbf commit 60eeb0b

File tree

2 files changed

+55
-8
lines changed

2 files changed

+55
-8
lines changed

src/Npgsql/Internal/NpgsqlReadBuffer.Stream.cs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public override long Position
6565
{
6666
if (value < 0)
6767
throw new ArgumentOutOfRangeException(nameof(value), "Non - negative number required.");
68-
Seek(_start + value, SeekOrigin.Begin);
68+
Seek(value, SeekOrigin.Begin);
6969
}
7070
}
7171

@@ -87,24 +87,27 @@ public override long Seek(long offset, SeekOrigin origin)
8787
var tempPosition = unchecked(_start + (int)offset);
8888
if (offset < 0 || tempPosition < _start)
8989
throw new IOException(seekBeforeBegin);
90-
_buf.ReadPosition = _start;
91-
return tempPosition;
90+
_buf.ReadPosition = tempPosition;
91+
_read = (int)offset;
92+
return _read;
9293
}
9394
case SeekOrigin.Current:
9495
{
9596
var tempPosition = unchecked(_buf.ReadPosition + (int)offset);
9697
if (unchecked(_buf.ReadPosition + offset) < _start || tempPosition < _start)
9798
throw new IOException(seekBeforeBegin);
9899
_buf.ReadPosition = tempPosition;
99-
return tempPosition;
100+
_read += (int)offset;
101+
return _read;
100102
}
101103
case SeekOrigin.End:
102104
{
103-
var tempPosition = unchecked(_len + (int)offset);
104-
if (unchecked(_len + offset) < _start || tempPosition < _start)
105+
var tempPosition = unchecked(_start + _len + (int)offset);
106+
if (unchecked(_start + _len + offset) < _start || tempPosition < _start)
105107
throw new IOException(seekBeforeBegin);
106108
_buf.ReadPosition = tempPosition;
107-
return tempPosition;
109+
_read = _len + (int)offset;
110+
return _read;
108111
}
109112
default:
110113
throw new ArgumentOutOfRangeException(nameof(origin), "Invalid seek origin.");
@@ -238,4 +241,4 @@ static void ValidateArguments(byte[] buffer, int offset, int count)
238241
if (buffer.Length - offset < count)
239242
throw new ArgumentException("Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.");
240243
}
241-
}
244+
}

test/Npgsql.Tests/ReaderTests.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1471,6 +1471,50 @@ public async Task GetStream_in_middle_of_column_throws([Values] bool async)
14711471
Assert.That(() => reader.GetStream(0), Throws.Exception.TypeOf<InvalidOperationException>());
14721472
}
14731473

1474+
[Test, IssueLink("https://github.com/npgsql/npgsql/issues/5223")]
1475+
public async Task GetStream_seek()
1476+
{
1477+
// Sequential doesn't allow to seek
1478+
if (IsSequential)
1479+
return;
1480+
1481+
await using var conn = await OpenConnectionAsync();
1482+
await using var cmd = conn.CreateCommand();
1483+
cmd.CommandText = "SELECT 'abcdefgh'";
1484+
await using var reader = await cmd.ExecuteReaderAsync();
1485+
await reader.ReadAsync();
1486+
1487+
var buffer = new byte[4];
1488+
1489+
await using var stream = reader.GetStream(0);
1490+
Assert.IsTrue(stream.CanSeek);
1491+
1492+
var seekPosition = stream.Seek(-1, SeekOrigin.End);
1493+
Assert.That(seekPosition, Is.EqualTo(stream.Length - 1));
1494+
var read = stream.Read(buffer);
1495+
Assert.That(read, Is.EqualTo(1));
1496+
Assert.That(Encoding.ASCII.GetString(buffer, 0, 1), Is.EqualTo("h"));
1497+
read = stream.Read(buffer);
1498+
Assert.That(read, Is.EqualTo(0));
1499+
1500+
seekPosition = stream.Seek(2, SeekOrigin.Begin);
1501+
Assert.That(seekPosition, Is.EqualTo(2));
1502+
read = stream.Read(buffer);
1503+
Assert.That(read, Is.EqualTo(buffer.Length));
1504+
Assert.That(Encoding.ASCII.GetString(buffer), Is.EqualTo("cdef"));
1505+
1506+
seekPosition = stream.Seek(-3, SeekOrigin.Current);
1507+
Assert.That(seekPosition, Is.EqualTo(3));
1508+
read = stream.Read(buffer);
1509+
Assert.That(read, Is.EqualTo(buffer.Length));
1510+
Assert.That(Encoding.ASCII.GetString(buffer), Is.EqualTo("defg"));
1511+
1512+
stream.Position = 1;
1513+
read = stream.Read(buffer);
1514+
Assert.That(read, Is.EqualTo(buffer.Length));
1515+
Assert.That(Encoding.ASCII.GetString(buffer), Is.EqualTo("bcde"));
1516+
}
1517+
14741518
#endregion GetBytes / GetStream
14751519

14761520
#region GetChars / GetTextReader

0 commit comments

Comments
 (0)