@@ -10,7 +10,7 @@ internal class Row : IDisposable
10
10
{
11
11
public Row ( ResultSet resultSet ) => ResultSet = resultSet ;
12
12
13
- public void SetData ( int [ ] dataLengths , int [ ] dataOffsets , byte [ ] payload )
13
+ public void SetData ( int [ ] dataLengths , int [ ] dataOffsets , ArraySegment < byte > payload )
14
14
{
15
15
m_dataLengths = dataLengths ;
16
16
m_dataOffsets = dataOffsets ;
@@ -21,36 +21,35 @@ public void BufferData()
21
21
{
22
22
// by default, m_payload, m_dataLengths, and m_dataOffsets are re-used to save allocations
23
23
// if the row is going to be buffered, we need to copy them
24
+ // since m_payload can span multiple rows, offests must recalculated to include only this row
24
25
25
- var bufferDataLengths = ArrayPool < int > . Shared . Rent ( m_dataLengths . Length ) ;
26
+ var bufferDataLengths = new int [ m_dataLengths . Length ] ;
26
27
Buffer . BlockCopy ( m_dataLengths , 0 , bufferDataLengths , 0 , m_dataLengths . Length * sizeof ( int ) ) ;
27
28
m_dataLengths = bufferDataLengths ;
28
29
29
- var bufferedDataOffsets = ArrayPool < int > . Shared . Rent ( m_dataOffsets . Length ) ;
30
- Buffer . BlockCopy ( m_dataOffsets , 0 , bufferedDataOffsets , 0 , m_dataOffsets . Length * sizeof ( int ) ) ;
31
- m_dataOffsets = bufferedDataOffsets ;
32
-
33
- var bufferedPayload = ArrayPool < byte > . Shared . Rent ( m_payload . Length ) ;
34
- Buffer . BlockCopy ( m_payload , 0 , bufferedPayload , 0 , m_payload . Length ) ;
35
- m_payload = bufferedPayload ;
30
+ var bufferDataOffsets = new int [ m_dataOffsets . Length ] ;
31
+ for ( var i = 0 ; i < m_dataOffsets . Length ; i ++ )
32
+ {
33
+ // a -1 offset denotes null, only adjust positive offsets
34
+ if ( m_dataOffsets [ i ] >= 0 )
35
+ bufferDataOffsets [ i ] = m_dataOffsets [ i ] - m_payload . Offset ;
36
+ else
37
+ bufferDataOffsets [ i ] = m_dataOffsets [ i ] ;
38
+ }
39
+ m_dataOffsets = bufferDataOffsets ;
36
40
37
- m_buffered = true ;
41
+ var bufferedPayload = new byte [ m_payload . Count ] ;
42
+ Buffer . BlockCopy ( m_payload . Array , m_payload . Offset , bufferedPayload , 0 , m_payload . Count ) ;
43
+ m_payload = new ArraySegment < byte > ( bufferedPayload ) ;
38
44
}
39
45
40
46
public void Dispose ( ) => ClearData ( ) ;
41
47
42
48
public void ClearData ( )
43
49
{
44
- if ( m_buffered )
45
- {
46
- ArrayPool < int > . Shared . Return ( m_dataLengths ) ;
47
- ArrayPool < int > . Shared . Return ( m_dataOffsets ) ;
48
- ArrayPool < byte > . Shared . Return ( m_payload ) ;
49
- m_buffered = false ;
50
- }
51
50
m_dataLengths = null ;
52
51
m_dataOffsets = null ;
53
- m_payload = null ;
52
+ m_payload = default ( ArraySegment < byte > ) ;
54
53
}
55
54
56
55
public bool GetBoolean ( int ordinal )
@@ -107,7 +106,7 @@ public long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffs
107
106
throw new ArgumentException ( "bufferOffset + length cannot exceed buffer.Length" , nameof ( length ) ) ;
108
107
109
108
int lengthToCopy = Math . Min ( m_dataLengths [ ordinal ] - ( int ) dataOffset , length ) ;
110
- Buffer . BlockCopy ( m_payload , checked ( ( int ) ( m_dataOffsets [ ordinal ] + dataOffset ) ) , buffer , bufferOffset , lengthToCopy ) ;
109
+ Buffer . BlockCopy ( m_payload . Array , checked ( ( int ) ( m_dataOffsets [ ordinal ] + dataOffset ) ) , buffer , bufferOffset , lengthToCopy ) ;
111
110
return lengthToCopy ;
112
111
}
113
112
@@ -255,7 +254,7 @@ public object GetValue(int ordinal)
255
254
if ( m_dataOffsets [ ordinal ] == - 1 )
256
255
return DBNull . Value ;
257
256
258
- var data = new ArraySegment < byte > ( m_payload , m_dataOffsets [ ordinal ] , m_dataLengths [ ordinal ] ) ;
257
+ var data = new ArraySegment < byte > ( m_payload . Array , m_dataOffsets [ ordinal ] , m_dataLengths [ ordinal ] ) ;
259
258
var columnDefinition = ResultSet . ColumnDefinitions [ ordinal ] ;
260
259
var isUnsigned = ( columnDefinition . ColumnFlags & ColumnFlags . Unsigned ) != 0 ;
261
260
switch ( columnDefinition . ColumnType )
@@ -279,7 +278,7 @@ public object GetValue(int ordinal)
279
278
// BIT column is transmitted as MSB byte array
280
279
ulong bitValue = 0 ;
281
280
for ( int i = 0 ; i < m_dataLengths [ ordinal ] ; i ++ )
282
- bitValue = bitValue * 256 + m_payload [ m_dataOffsets [ ordinal ] + i ] ;
281
+ bitValue = bitValue * 256 + m_payload . Array [ m_dataOffsets [ ordinal ] + i ] ;
283
282
return bitValue ;
284
283
285
284
case ColumnType . String :
@@ -296,7 +295,7 @@ public object GetValue(int ordinal)
296
295
if ( columnDefinition . CharacterSet == CharacterSet . Binary )
297
296
{
298
297
var result = new byte [ m_dataLengths [ ordinal ] ] ;
299
- Buffer . BlockCopy ( m_payload , m_dataOffsets [ ordinal ] , result , 0 , result . Length ) ;
298
+ Buffer . BlockCopy ( m_payload . Array , m_dataOffsets [ ordinal ] , result , 0 , result . Length ) ;
300
299
return Connection . OldGuids && columnDefinition . ColumnLength == 16 ? ( object ) new Guid ( result ) : result ;
301
300
}
302
301
return Encoding . UTF8 . GetString ( data ) ;
@@ -385,10 +384,8 @@ private static TimeSpan ParseTimeSpan(ArraySegment<byte> value)
385
384
public readonly ResultSet ResultSet ;
386
385
public MySqlConnection Connection => ResultSet . Connection ;
387
386
388
- byte [ ] m_payload ;
387
+ ArraySegment < byte > m_payload ;
389
388
int [ ] m_dataLengths ;
390
389
int [ ] m_dataOffsets ;
391
- bool m_buffered ;
392
-
393
390
}
394
391
}
0 commit comments