diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.netcore.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.netcore.cs index 22e2fc437d..1abf0c0191 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.netcore.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParserStateObject.netcore.cs @@ -278,134 +278,6 @@ internal void StartSession(object cancellationOwner) _cancellationOwner.Target = cancellationOwner; } - /////////////////////////////////////// - // Buffer read methods - data values // - /////////////////////////////////////// - - // Reads the requested number of bytes from a plp data stream, or the entire data if - // requested length is -1 or larger than the actual length of data. First call to this method - // should be preceeded by a call to ReadPlpLength or ReadDataLength. - // Returns the actual bytes read. - // NOTE: This method must be retriable WITHOUT replaying a snapshot - // Every time you call this method increment the offset and decrease len by the value of totalBytesRead - internal bool TryReadPlpBytes(ref byte[] buff, int offset, int len, out int totalBytesRead) - { - int bytesRead; - int bytesLeft; - byte[] newbuf; - - if (_longlen == 0) - { - Debug.Assert(_longlenleft == 0); - if (buff == null) - { - buff = Array.Empty(); - } - - AssertValidState(); - totalBytesRead = 0; - return true; // No data - } - - Debug.Assert(_longlen != TdsEnums.SQL_PLP_NULL, "Out of sync plp read request"); - Debug.Assert((buff == null && offset == 0) || (buff.Length >= offset + len), "Invalid length sent to ReadPlpBytes()!"); - - bytesLeft = len; - - // If total length is known up front, allocate the whole buffer in one shot instead of realloc'ing and copying over each time - if (buff == null && _longlen != TdsEnums.SQL_PLP_UNKNOWNLEN) - { - if (_snapshot != null) - { - // if there is a snapshot and it contains a stored plp buffer take it - // and try to use it if it is the right length - buff = _snapshot._plpBuffer; - _snapshot._plpBuffer = null; - } - - if ((ulong)(buff?.Length ?? 0) != _longlen) - { - // if the buffer is null or the wrong length create one to use - buff = new byte[(Math.Min((int)_longlen, len))]; - } - } - - if (_longlenleft == 0) - { - if (!TryReadPlpLength(false, out _)) - { - totalBytesRead = 0; - return false; - } - if (_longlenleft == 0) - { // Data read complete - totalBytesRead = 0; - return true; - } - } - - if (buff == null) - { - buff = new byte[_longlenleft]; - } - - totalBytesRead = 0; - - while (bytesLeft > 0) - { - int bytesToRead = (int)Math.Min(_longlenleft, (ulong)bytesLeft); - if (buff.Length < (offset + bytesToRead)) - { - // Grow the array - newbuf = new byte[offset + bytesToRead]; - Buffer.BlockCopy(buff, 0, newbuf, 0, offset); - buff = newbuf; - } - - bool result = TryReadByteArray(buff.AsSpan(offset), bytesToRead, out bytesRead); - Debug.Assert(bytesRead <= bytesLeft, "Read more bytes than we needed"); - Debug.Assert((ulong)bytesRead <= _longlenleft, "Read more bytes than is available"); - - bytesLeft -= bytesRead; - offset += bytesRead; - totalBytesRead += bytesRead; - _longlenleft -= (ulong)bytesRead; - if (!result) - { - if (_snapshot != null) - { - // a partial read has happened so store the target buffer in the snapshot - // so it can be re-used when another packet arrives and we read again - _snapshot._plpBuffer = buff; - } - return false; - } - - if (_longlenleft == 0) - { - // Read the next chunk or cleanup state if hit the end - if (!TryReadPlpLength(false, out _)) - { - if (_snapshot != null) - { - // a partial read has happened so store the target buffer in the snapshot - // so it can be re-used when another packet arrives and we read again - _snapshot._plpBuffer = buff; - } - return false; - } - } - - AssertValidState(); - - // Catch the point where we read the entire plp data stream and clean up state - if (_longlenleft == 0) // Data read complete - break; - } - return true; - } - - ///////////////////////////////////////// // Value Skip Logic // ///////////////////////////////////////// diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.netfx.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.netfx.cs index 7d9829ab7e..8fa15e3a6b 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.netfx.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParserStateObject.netfx.cs @@ -372,134 +372,6 @@ internal void StartSession(int objectID) _allowObjectID = objectID; } - /////////////////////////////////////// - // Buffer read methods - data values // - /////////////////////////////////////// - - // Reads the requested number of bytes from a plp data stream, or the entire data if - // requested length is -1 or larger than the actual length of data. First call to this method - // should be preceeded by a call to ReadPlpLength or ReadDataLength. - // Returns the actual bytes read. - // NOTE: This method must be retriable WITHOUT replaying a snapshot - // Every time you call this method increment the offset and decrease len by the value of totalBytesRead - internal bool TryReadPlpBytes(ref byte[] buff, int offset, int len, out int totalBytesRead) - { - int bytesRead; - int bytesLeft; - byte[] newbuf; - - if (_longlen == 0) - { - Debug.Assert(_longlenleft == 0); - if (buff == null) - { - buff = Array.Empty(); - } - - AssertValidState(); - totalBytesRead = 0; - return true; // No data - } - - Debug.Assert(_longlen != TdsEnums.SQL_PLP_NULL, "Out of sync plp read request"); - Debug.Assert((buff == null && offset == 0) || (buff.Length >= offset + len), "Invalid length sent to ReadPlpBytes()!"); - - bytesLeft = len; - - // If total length is known up front, allocate the whole buffer in one shot instead of realloc'ing and copying over each time - if (buff == null && _longlen != TdsEnums.SQL_PLP_UNKNOWNLEN) - { - if (_snapshot != null) - { - // if there is a snapshot and it contains a stored plp buffer take it - // and try to use it if it is the right length - buff = _snapshot._plpBuffer; - _snapshot._plpBuffer = null; - } - - if ((ulong)(buff?.Length ?? 0) != _longlen) - { - // if the buffer is null or the wrong length create one to use - buff = new byte[(Math.Min((int)_longlen, len))]; - } - } - - if (_longlenleft == 0) - { - if (!TryReadPlpLength(false, out _)) - { - totalBytesRead = 0; - return false; - } - if (_longlenleft == 0) - { // Data read complete - totalBytesRead = 0; - return true; - } - } - - if (buff == null) - { - buff = new byte[_longlenleft]; - } - - totalBytesRead = 0; - - while (bytesLeft > 0) - { - int bytesToRead = (int)Math.Min(_longlenleft, (ulong)bytesLeft); - if (buff.Length < (offset + bytesToRead)) - { - // Grow the array - newbuf = new byte[offset + bytesToRead]; - Buffer.BlockCopy(buff, 0, newbuf, 0, offset); - buff = newbuf; - } - - bool result = TryReadByteArray(buff.AsSpan(offset), bytesToRead, out bytesRead); - Debug.Assert(bytesRead <= bytesLeft, "Read more bytes than we needed"); - Debug.Assert((ulong)bytesRead <= _longlenleft, "Read more bytes than is available"); - - bytesLeft -= bytesRead; - offset += bytesRead; - totalBytesRead += bytesRead; - _longlenleft -= (ulong)bytesRead; - if (!result) - { - if (_snapshot != null) - { - // a partial read has happened so store the target buffer in the snapshot - // so it can be re-used when another packet arrives and we read again - _snapshot._plpBuffer = buff; - } - return false; - } - - if (_longlenleft == 0) - { - // Read the next chunk or cleanup state if hit the end - if (!TryReadPlpLength(false, out _)) - { - if (_snapshot != null) - { - // a partial read has happened so store the target buffer in the snapshot - // so it can be re-used when another packet arrives and we read again - _snapshot._plpBuffer = buff; - } - return false; - } - } - - AssertValidState(); - - // Catch the point where we read the entire plp data stream and clean up state - if (_longlenleft == 0) // Data read complete - break; - } - return true; - } - - ///////////////////////////////////////// // Value Skip Logic // ///////////////////////////////////////// diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs index 0412a2eb6c..f2b084e7e4 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/TdsParserStateObject.cs @@ -1761,6 +1761,129 @@ internal int ReadPlpBytesChunk(byte[] buff, int offset, int len) return value; } + // Reads the requested number of bytes from a plp data stream, or the entire data if + // requested length is -1 or larger than the actual length of data. First call to this method + // should be preceeded by a call to ReadPlpLength or ReadDataLength. + // Returns the actual bytes read. + // NOTE: This method must be retriable WITHOUT replaying a snapshot + // Every time you call this method increment the offset and decrease len by the value of totalBytesRead + internal bool TryReadPlpBytes(ref byte[] buff, int offset, int len, out int totalBytesRead) + { + int bytesRead; + int bytesLeft; + byte[] newbuf; + + if (_longlen == 0) + { + Debug.Assert(_longlenleft == 0); + if (buff == null) + { + buff = Array.Empty(); + } + + AssertValidState(); + totalBytesRead = 0; + return true; // No data + } + + Debug.Assert(_longlen != TdsEnums.SQL_PLP_NULL, "Out of sync plp read request"); + Debug.Assert((buff == null && offset == 0) || (buff.Length >= offset + len), "Invalid length sent to ReadPlpBytes()!"); + + bytesLeft = len; + + // If total length is known up front, allocate the whole buffer in one shot instead of realloc'ing and copying over each time + if (buff == null && _longlen != TdsEnums.SQL_PLP_UNKNOWNLEN) + { + if (_snapshot != null) + { + // if there is a snapshot and it contains a stored plp buffer take it + // and try to use it if it is the right length + buff = _snapshot._plpBuffer; + _snapshot._plpBuffer = null; + } + + if ((ulong)(buff?.Length ?? 0) != _longlen) + { + // if the buffer is null or the wrong length create one to use + buff = new byte[(Math.Min((int)_longlen, len))]; + } + } + + if (_longlenleft == 0) + { + if (!TryReadPlpLength(false, out _)) + { + totalBytesRead = 0; + return false; + } + if (_longlenleft == 0) + { // Data read complete + totalBytesRead = 0; + return true; + } + } + + if (buff == null) + { + buff = new byte[_longlenleft]; + } + + totalBytesRead = 0; + + while (bytesLeft > 0) + { + int bytesToRead = (int)Math.Min(_longlenleft, (ulong)bytesLeft); + if (buff.Length < (offset + bytesToRead)) + { + // Grow the array + newbuf = new byte[offset + bytesToRead]; + Buffer.BlockCopy(buff, 0, newbuf, 0, offset); + buff = newbuf; + } + + bool result = TryReadByteArray(buff.AsSpan(offset), bytesToRead, out bytesRead); + Debug.Assert(bytesRead <= bytesLeft, "Read more bytes than we needed"); + Debug.Assert((ulong)bytesRead <= _longlenleft, "Read more bytes than is available"); + + bytesLeft -= bytesRead; + offset += bytesRead; + totalBytesRead += bytesRead; + _longlenleft -= (ulong)bytesRead; + if (!result) + { + if (_snapshot != null) + { + // a partial read has happened so store the target buffer in the snapshot + // so it can be re-used when another packet arrives and we read again + _snapshot._plpBuffer = buff; + } + return false; + } + + if (_longlenleft == 0) + { + // Read the next chunk or cleanup state if hit the end + if (!TryReadPlpLength(false, out _)) + { + if (_snapshot != null) + { + // a partial read has happened so store the target buffer in the snapshot + // so it can be re-used when another packet arrives and we read again + _snapshot._plpBuffer = buff; + } + return false; + } + } + + AssertValidState(); + + // Catch the point where we read the entire plp data stream and clean up state + if (_longlenleft == 0) // Data read complete + break; + } + return true; + } + /* // leave this in. comes handy if you have to do Console.WriteLine style debugging ;)