Skip to content

Commit 820cfcd

Browse files
authored
Fix seek for ColumnStream (#5224)
Fixes #5223
1 parent 9ce3ba0 commit 820cfcd

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
@@ -1468,6 +1468,50 @@ public async Task GetStream_in_middle_of_column_throws([Values] bool async)
14681468
Assert.That(() => reader.GetStream(0), Throws.Exception.TypeOf<InvalidOperationException>());
14691469
}
14701470

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

14731517
#region GetChars / GetTextReader

0 commit comments

Comments
 (0)