@@ -24,6 +24,7 @@ public async Task<ResultSet> ReadResultSetHeaderAsync(IOBehavior ioBehavior)
24
24
LastInsertId = 0 ;
25
25
RecordsAffected = 0 ;
26
26
State = ResultSetState . None ;
27
+ m_columnDefinitionPayloadUsedBytes = 0 ;
27
28
m_dataLengths = null ;
28
29
m_dataOffsets = null ;
29
30
m_readBuffer . Clear ( ) ;
@@ -83,14 +84,25 @@ public async Task<ResultSet> ReadResultSetHeaderAsync(IOBehavior ioBehavior)
83
84
if ( reader . BytesRemaining != 0 )
84
85
throw new MySqlException ( "Unexpected data at end of column_count packet; see https://github.com/mysql-net/MySqlConnector/issues/324" ) ;
85
86
87
+ // reserve adequate space to hold a copy of all column definitions (but note that this can be resized below if we guess too small)
88
+ Array . Resize ( ref m_columnDefinitionPayloads , columnCount * 96 ) ;
89
+
86
90
ColumnDefinitions = new ColumnDefinitionPayload [ columnCount ] ;
87
91
m_dataOffsets = new int [ columnCount ] ;
88
92
m_dataLengths = new int [ columnCount ] ;
89
93
90
94
for ( var column = 0 ; column < ColumnDefinitions . Length ; column ++ )
91
95
{
92
96
payload = await Session . ReceiveReplyAsync ( ioBehavior , CancellationToken . None ) . ConfigureAwait ( false ) ;
93
- ColumnDefinitions [ column ] = ColumnDefinitionPayload . Create ( payload ) ;
97
+ var arraySegment = payload . ArraySegment ;
98
+
99
+ // 'Session.ReceiveReplyAsync' reuses a shared buffer; make a copy so that the column definitions can always be safely read at any future point
100
+ if ( m_columnDefinitionPayloadUsedBytes + arraySegment . Count > m_columnDefinitionPayloads . Length )
101
+ Array . Resize ( ref m_columnDefinitionPayloads , Math . Max ( m_columnDefinitionPayloadUsedBytes + arraySegment . Count , m_columnDefinitionPayloadUsedBytes * 2 ) ) ;
102
+ Buffer . BlockCopy ( arraySegment . Array , arraySegment . Offset , m_columnDefinitionPayloads , m_columnDefinitionPayloadUsedBytes , arraySegment . Count ) ;
103
+
104
+ ColumnDefinitions [ column ] = ColumnDefinitionPayload . Create ( new ArraySegment < byte > ( m_columnDefinitionPayloads , m_columnDefinitionPayloadUsedBytes , arraySegment . Count ) ) ;
105
+ m_columnDefinitionPayloadUsedBytes += arraySegment . Count ;
94
106
}
95
107
96
108
if ( ! Session . SupportsDeprecateEof )
@@ -421,6 +433,8 @@ public Row GetCurrentRow()
421
433
public int RecordsAffected { get ; private set ; }
422
434
public ResultSetState State { get ; private set ; }
423
435
436
+ byte [ ] m_columnDefinitionPayloads ;
437
+ int m_columnDefinitionPayloadUsedBytes ;
424
438
int [ ] m_dataLengths ;
425
439
int [ ] m_dataOffsets ;
426
440
readonly Queue < Row > m_readBuffer = new Queue < Row > ( ) ;
0 commit comments