From 0a7d82ef6cb6939db0b5d6f89f372fa5820da072 Mon Sep 17 00:00:00 2001 From: Lawrence LCI Date: Thu, 23 Sep 2021 14:13:03 -0700 Subject: [PATCH 1/7] Move the netcore version of SqlCachedBuffer to src and update reference in netfx csproj --- .../src/Microsoft.Data.SqlClient.csproj | 4 +- .../netfx/src/Microsoft.Data.SqlClient.csproj | 6 +- .../Data/SqlClient/SqlCachedBuffer.cs | 169 ------------------ .../Data/SqlClient/SqlCachedBuffer.cs | 0 4 files changed, 7 insertions(+), 172 deletions(-) delete mode 100644 src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs rename src/Microsoft.Data.SqlClient/{netcore => }/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs (100%) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj index d918134b15..f26669dd2f 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -196,6 +196,9 @@ Microsoft\Data\SqlClient\SqlBulkCopyColumnOrderHintCollection.cs + + Microsoft\Data\SqlClient\SqlCachedBuffer.cs + Microsoft\Data\SqlClient\SqlClientEncryptionAlgorithm.cs @@ -474,7 +477,6 @@ - diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj index f54e7630c6..6e3252690e 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -267,6 +267,9 @@ Microsoft\Data\SqlClient\SqlBulkCopyColumnOrderHintCollection.cs + + Microsoft\Data\SqlClient\SqlCachedBuffer.cs + Microsoft\Data\SqlClient\SqlClientEncryptionAlgorithm.cs @@ -430,12 +433,11 @@ - + - diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs deleted file mode 100644 index 62f4d85591..0000000000 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs +++ /dev/null @@ -1,169 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; -using System.Data.SqlTypes; -using System.Diagnostics; -using System.IO; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Xml; - -namespace Microsoft.Data.SqlClient -{ - // Caches the bytes returned from partial length prefixed datatypes, like XML - sealed internal class SqlCachedBuffer : System.Data.SqlTypes.INullable - { - public static readonly SqlCachedBuffer Null = new SqlCachedBuffer(); - private const int _maxChunkSize = 2048; // Arbitrary value for chunk size. Revisit this later for better perf - - private List _cachedBytes; - - private SqlCachedBuffer() - { - // For constructing Null - } - - private SqlCachedBuffer(List cachedBytes) - { - _cachedBytes = cachedBytes; - } - - internal List CachedBytes - { - get { return _cachedBytes; } - } - - // Reads off from the network buffer and caches bytes. Only reads one column value in the current row. - static internal bool TryCreate(SqlMetaDataPriv metadata, TdsParser parser, TdsParserStateObject stateObj, out SqlCachedBuffer buffer) - { - int cb = 0; - ulong plplength; - byte[] byteArr; - - List cachedBytes = new List(); - buffer = null; - - // the very first length is already read. - if (!parser.TryPlpBytesLeft(stateObj, out plplength)) - { - return false; - } - // For now we only handle Plp data from the parser directly. - Debug.Assert(metadata.metaType.IsPlp, "SqlCachedBuffer call on a non-plp data"); - do - { - if (plplength == 0) - break; - do - { - cb = (plplength > (ulong)_maxChunkSize) ? _maxChunkSize : (int)plplength; - byteArr = new byte[cb]; - if (!stateObj.TryReadPlpBytes(ref byteArr, 0, cb, out cb)) - { - return false; - } - Debug.Assert(cb == byteArr.Length); - if (cachedBytes.Count == 0) - { - // Add the Byte order mark if needed if we read the first array - AddByteOrderMark(byteArr, cachedBytes); - } - cachedBytes.Add(byteArr); - plplength -= (ulong)cb; - } while (plplength > 0); - if (!parser.TryPlpBytesLeft(stateObj, out plplength)) - { - return false; - } - } while (plplength > 0); - Debug.Assert(stateObj._longlen == 0 && stateObj._longlenleft == 0); - - buffer = new SqlCachedBuffer(cachedBytes); - return true; - } - - private static void AddByteOrderMark(byte[] byteArr, List cachedBytes) - { - // Need to find out if we should add byte order mark or not. - // We need to add this if we are getting ntext xml, not if we are getting binary xml - // Binary Xml always begins with the bytes 0xDF and 0xFF - // If we aren't getting these, then we are getting unicode xml - if ((byteArr.Length < 2) || (byteArr[0] != 0xDF) || (byteArr[1] != 0xFF)) - { - Debug.Assert(cachedBytes.Count == 0); - cachedBytes.Add(TdsEnums.XMLUNICODEBOMBYTES); - } - } - - internal Stream ToStream() - { - return new SqlCachedStream(this); - } - - override public string ToString() - { - if (IsNull) - throw new SqlNullValueException(); - - if (_cachedBytes.Count == 0) - { - return String.Empty; - } - SqlXml sxml = new SqlXml(ToStream()); - return sxml.Value; - } - - internal SqlString ToSqlString() - { - if (IsNull) - return SqlString.Null; - string str = ToString(); - return new SqlString(str); - } - - internal SqlXml ToSqlXml() - { - SqlXml sx = new SqlXml(ToStream()); - return sx; - } - - // Prevent inlining so that reflection calls are not moved to caller that may be in a different assembly that may have a different grant set. - [MethodImpl(MethodImplOptions.NoInlining)] - internal XmlReader ToXmlReader() - { - //XmlTextReader xr = new XmlTextReader(fragment, XmlNodeType.Element, null); - XmlReaderSettings readerSettings = new XmlReaderSettings(); - readerSettings.ConformanceLevel = ConformanceLevel.Fragment; - - // Call internal XmlReader.CreateSqlReader from System.Xml. - // Signature: internal static XmlReader CreateSqlReader(Stream input, XmlReaderSettings settings, XmlParserContext inputContext); - MethodInfo createSqlReaderMethodInfo = typeof(System.Xml.XmlReader).GetMethod("CreateSqlReader", BindingFlags.Static | BindingFlags.NonPublic); - object[] args = new object[3] { ToStream(), readerSettings, null }; - XmlReader xr; - - new System.Security.Permissions.ReflectionPermission(System.Security.Permissions.ReflectionPermissionFlag.MemberAccess).Assert(); - try - { - xr = (XmlReader)createSqlReaderMethodInfo.Invoke(null, args); - } - finally - { - System.Security.Permissions.ReflectionPermission.RevertAssert(); - } - return xr; - } - - public bool IsNull - { - get - { - return (_cachedBytes == null) ? true : false; - } - } - - } - -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs similarity index 100% rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs From a183f01f3a41fbb4f97e50cf1fdf31b614de76ba Mon Sep 17 00:00:00 2001 From: Lawrence LCI Date: Thu, 23 Sep 2021 14:22:08 -0700 Subject: [PATCH 2/7] Update the code to conform with the coding style --- .../Data/SqlClient/SqlCachedBuffer.cs | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs index 04aeaa552e..7fe3d12d27 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs @@ -15,10 +15,10 @@ namespace Microsoft.Data.SqlClient // Caches the bytes returned from partial length prefixed datatypes, like XML sealed internal class SqlCachedBuffer : System.Data.SqlTypes.INullable { - public static readonly SqlCachedBuffer Null = new SqlCachedBuffer(); - private const int _maxChunkSize = 2048; // Arbitrary value for chunk size. Revisit this later for better perf + public static readonly SqlCachedBuffer Null = new(); + private const int MaxChunkSize = 2048; // Arbitrary value for chunk size. Revisit this later for better perf - private List _cachedBytes; + private readonly List _cachedBytes; private SqlCachedBuffer() { @@ -38,15 +38,13 @@ internal List CachedBytes // Reads off from the network buffer and caches bytes. Only reads one column value in the current row. internal static bool TryCreate(SqlMetaDataPriv metadata, TdsParser parser, TdsParserStateObject stateObj, out SqlCachedBuffer buffer) { - int cb = 0; - ulong plplength; byte[] byteArr; - List cachedBytes = new List(); + List cachedBytes = new(); buffer = null; // the very first length is already read. - if (!parser.TryPlpBytesLeft(stateObj, out plplength)) + if (!parser.TryPlpBytesLeft(stateObj, out ulong plplength)) { return false; } @@ -58,7 +56,7 @@ internal static bool TryCreate(SqlMetaDataPriv metadata, TdsParser parser, TdsPa break; do { - cb = (plplength > (ulong)_maxChunkSize) ? _maxChunkSize : (int)plplength; + int cb = (plplength > (ulong)MaxChunkSize) ? MaxChunkSize : (int)plplength; byteArr = new byte[cb]; if (!stateObj.TryReadPlpBytes(ref byteArr, 0, cb, out cb)) { @@ -111,7 +109,7 @@ override public string ToString() { return string.Empty; } - SqlXml sxml = new SqlXml(ToStream()); + SqlXml sxml = new(ToStream()); return sxml.Value; } @@ -125,7 +123,7 @@ internal SqlString ToSqlString() internal SqlXml ToSqlXml() { - SqlXml sx = new SqlXml(ToStream()); + SqlXml sx = new(ToStream()); return sx; } @@ -140,7 +138,7 @@ public bool IsNull { get { - return (_cachedBytes == null) ? true : false; + return (_cachedBytes == null); } } From 752033196b05e825471625bcae375c331600dee7 Mon Sep 17 00:00:00 2001 From: Lawrence LCI Date: Thu, 23 Sep 2021 16:26:49 -0700 Subject: [PATCH 3/7] Update the get accessor to expression body definition --- .../src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs index 7fe3d12d27..38129e2bf0 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs @@ -32,7 +32,7 @@ private SqlCachedBuffer(List cachedBytes) internal List CachedBytes { - get { return _cachedBytes; } + get => _cachedBytes; } // Reads off from the network buffer and caches bytes. Only reads one column value in the current row. @@ -136,10 +136,7 @@ internal XmlReader ToXmlReader() public bool IsNull { - get - { - return (_cachedBytes == null); - } + get => _cachedBytes == null; } From 986fe1c2989dcafdd6c4a86f0c8351f090097b43 Mon Sep 17 00:00:00 2001 From: Lawrence LCI Date: Thu, 23 Sep 2021 16:31:26 -0700 Subject: [PATCH 4/7] Remove ToXmlReader because it's not referenced anywhere on both netfx and netcore and it's internal --- .../src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs index 38129e2bf0..d1f0fe1233 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs @@ -127,13 +127,6 @@ internal SqlXml ToSqlXml() return sx; } - // Prevent inlining so that reflection calls are not moved to caller that may be in a different assembly that may have a different grant set. - [MethodImpl(MethodImplOptions.NoInlining)] - internal XmlReader ToXmlReader() - { - return SqlTypeWorkarounds.SqlXmlCreateSqlXmlReader(ToStream(), closeInput: false); - } - public bool IsNull { get => _cachedBytes == null; From fac9f003da5bf4fbce931147580c78eaa0d0e1cc Mon Sep 17 00:00:00 2001 From: Lawrence LCI <31262254+lcheunglci@users.noreply.github.com> Date: Tue, 5 Oct 2021 13:41:18 -0700 Subject: [PATCH 5/7] Apply suggestions from code review Co-authored-by: DavoudEshtehari <61173489+DavoudEshtehari@users.noreply.github.com> --- .../src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs index d1f0fe1233..71d8364d49 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs @@ -13,7 +13,7 @@ namespace Microsoft.Data.SqlClient { // Caches the bytes returned from partial length prefixed datatypes, like XML - sealed internal class SqlCachedBuffer : System.Data.SqlTypes.INullable + internal sealed class SqlCachedBuffer : INullable { public static readonly SqlCachedBuffer Null = new(); private const int MaxChunkSize = 2048; // Arbitrary value for chunk size. Revisit this later for better perf @@ -35,7 +35,9 @@ internal List CachedBytes get => _cachedBytes; } - // Reads off from the network buffer and caches bytes. Only reads one column value in the current row. + /// + /// Reads off from the network buffer and caches bytes. Only reads one column value in the current row. + /// internal static bool TryCreate(SqlMetaDataPriv metadata, TdsParser parser, TdsParserStateObject stateObj, out SqlCachedBuffer buffer) { byte[] byteArr; @@ -53,7 +55,9 @@ internal static bool TryCreate(SqlMetaDataPriv metadata, TdsParser parser, TdsPa do { if (plplength == 0) + { break; + } do { int cb = (plplength > (ulong)MaxChunkSize) ? MaxChunkSize : (int)plplength; From 65f648802804d551ae726a875a7b83d2d2609817 Mon Sep 17 00:00:00 2001 From: Lawrence LCI Date: Tue, 5 Oct 2021 13:48:45 -0700 Subject: [PATCH 6/7] Revised the expression bodied getter and spacing based on the comments --- .../Microsoft/Data/SqlClient/SqlCachedBuffer.cs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs index 71d8364d49..7b3961f4b0 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs @@ -30,10 +30,7 @@ private SqlCachedBuffer(List cachedBytes) _cachedBytes = cachedBytes; } - internal List CachedBytes - { - get => _cachedBytes; - } + internal List CachedBytes =>_cachedBytes; /// /// Reads off from the network buffer and caches bytes. Only reads one column value in the current row. @@ -107,7 +104,9 @@ internal Stream ToStream() override public string ToString() { if (IsNull) + { throw new SqlNullValueException(); + } if (_cachedBytes.Count == 0) { @@ -120,7 +119,10 @@ override public string ToString() internal SqlString ToSqlString() { if (IsNull) + { return SqlString.Null; + } + string str = ToString(); return new SqlString(str); } @@ -131,11 +133,6 @@ internal SqlXml ToSqlXml() return sx; } - public bool IsNull - { - get => _cachedBytes == null; - } - - + public bool IsNull => _cachedBytes == null; } } From ee8f9f23fbff593c54f826d9dbad7a3afe3a8058 Mon Sep 17 00:00:00 2001 From: Lawrence LCI Date: Wed, 6 Oct 2021 15:16:41 -0700 Subject: [PATCH 7/7] Fix compiler error due to redefinition of IsNull --- .../src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs index a5959189ee..5a4de1e191 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCachedBuffer.cs @@ -140,14 +140,6 @@ internal XmlReader ToXmlReader() return SqlTypeWorkarounds.SqlXmlCreateSqlXmlReader(ToStream(), closeInput: false, async: false); } - public bool IsNull - { - get - { - return (_cachedBytes == null) ? true : false; - } - } - public bool IsNull => _cachedBytes == null; } }