Skip to content

Commit db7f451

Browse files
[Hotfix 2.1.5] | Remove union overlay design and use reflection in SqlTypeWorkarounds (#1647) (#1729)
1 parent 5807592 commit db7f451

File tree

5 files changed

+502
-138
lines changed

5 files changed

+502
-138
lines changed

src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,7 @@
458458
<Compile Include="Microsoft\Data\SqlClient\SqlColumnEncryptionEnclaveProvider.cs" />
459459
<Compile Include="Microsoft\Data\SqlClient\SqlEnclaveAttestationParameters.cs" />
460460
<Compile Include="Microsoft\Data\SqlClient\EnclaveDelegate.cs" />
461+
<Compile Include="Microsoft\Data\SqlTypes\SqlTypeWorkarounds.netcore.cs" />
461462
</ItemGroup>
462463
<!-- Windows only -->
463464
<ItemGroup Condition="'$(TargetsWindows)' == 'true'">
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Data.SqlTypes;
6+
using System.Runtime.InteropServices;
7+
8+
namespace Microsoft.Data.SqlTypes
9+
{
10+
/// <summary>
11+
/// This type provides workarounds for the separation between System.Data.Common
12+
/// and Microsoft.Data.SqlClient. The latter wants to access internal members of the former, and
13+
/// this class provides ways to do that. We must review and update this implementation any time the
14+
/// implementation of the corresponding types in System.Data.Common change.
15+
/// </summary>
16+
internal static partial class SqlTypeWorkarounds
17+
{
18+
#region Work around inability to access SqlMoney.ctor(long, int) and SqlMoney.ToSqlInternalRepresentation
19+
/// <summary>
20+
/// Constructs a SqlMoney from a long value without scaling. The ignored parameter exists
21+
/// only to distinguish this constructor from the constructor that takes a long.
22+
/// Used only internally.
23+
/// </summary>
24+
internal static SqlMoney SqlMoneyCtor(long value, int ignored)
25+
{
26+
var c = default(SqlMoneyCaster);
27+
28+
// Same behavior as the internal SqlMoney.ctor(long, bool) overload
29+
c.Fake._fNotNull = true;
30+
c.Fake._value = value;
31+
32+
return c.Real;
33+
}
34+
35+
internal static long SqlMoneyToSqlInternalRepresentation(SqlMoney money)
36+
{
37+
var c = default(SqlMoneyCaster);
38+
c.Real = money;
39+
40+
// Same implementation as the internal SqlMoney.ToSqlInternalRepresentation implementation
41+
if (money.IsNull)
42+
{
43+
throw new SqlNullValueException();
44+
}
45+
return c.Fake._value;
46+
}
47+
48+
[StructLayout(LayoutKind.Sequential)]
49+
private struct SqlMoneyLookalike // exact same shape as SqlMoney, but with accessible fields
50+
{
51+
internal bool _fNotNull;
52+
internal long _value;
53+
}
54+
55+
[StructLayout(LayoutKind.Explicit)]
56+
private struct SqlMoneyCaster
57+
{
58+
[FieldOffset(0)]
59+
internal SqlMoney Real;
60+
[FieldOffset(0)]
61+
internal SqlMoneyLookalike Fake;
62+
}
63+
#endregion
64+
65+
#region Work around inability to access SqlDecimal._data1/2/3/4
66+
internal static void SqlDecimalExtractData(SqlDecimal d, out uint data1, out uint data2, out uint data3, out uint data4)
67+
{
68+
// Extract the four data elements from SqlDecimal.
69+
var c = default(SqlDecimalCaster);
70+
c.Real = d;
71+
data1 = c.Fake._data1;
72+
data2 = c.Fake._data2;
73+
data3 = c.Fake._data3;
74+
data4 = c.Fake._data4;
75+
}
76+
77+
[StructLayout(LayoutKind.Sequential)]
78+
private struct SqlDecimalLookalike // exact same shape as SqlDecimal, but with accessible fields
79+
{
80+
internal byte _bStatus;
81+
internal byte _bLen;
82+
internal byte _bPrec;
83+
internal byte _bScale;
84+
internal uint _data1;
85+
internal uint _data2;
86+
internal uint _data3;
87+
internal uint _data4;
88+
}
89+
90+
[StructLayout(LayoutKind.Explicit)]
91+
private struct SqlDecimalCaster
92+
{
93+
[FieldOffset(0)]
94+
internal SqlDecimal Real;
95+
[FieldOffset(0)]
96+
internal SqlDecimalLookalike Fake;
97+
}
98+
#endregion
99+
100+
#region Work around inability to access SqlBinary.ctor(byte[], bool)
101+
internal static SqlBinary SqlBinaryCtor(byte[] value, bool ignored)
102+
{
103+
// Construct a SqlBinary without allocating/copying the byte[]. This provides
104+
// the same behavior as SqlBinary.ctor(byte[], bool).
105+
var c = default(SqlBinaryCaster);
106+
c.Fake._value = value;
107+
return c.Real;
108+
}
109+
110+
[StructLayout(LayoutKind.Sequential)]
111+
private struct SqlBinaryLookalike
112+
{
113+
internal byte[] _value;
114+
}
115+
116+
[StructLayout(LayoutKind.Explicit)]
117+
private struct SqlBinaryCaster
118+
{
119+
[FieldOffset(0)]
120+
internal SqlBinary Real;
121+
[FieldOffset(0)]
122+
internal SqlBinaryLookalike Fake;
123+
}
124+
#endregion
125+
126+
#region Work around inability to access SqlGuid.ctor(byte[], bool)
127+
internal static SqlGuid SqlGuidCtor(byte[] value, bool ignored)
128+
{
129+
// Construct a SqlGuid without allocating/copying the byte[]. This provides
130+
// the same behavior as SqlGuid.ctor(byte[], bool).
131+
var c = default(SqlGuidCaster);
132+
c.Fake._value = value;
133+
return c.Real;
134+
}
135+
136+
[StructLayout(LayoutKind.Sequential)]
137+
private struct SqlGuidLookalike
138+
{
139+
internal byte[] _value;
140+
}
141+
142+
[StructLayout(LayoutKind.Explicit)]
143+
private struct SqlGuidCaster
144+
{
145+
[FieldOffset(0)]
146+
internal SqlGuid Real;
147+
[FieldOffset(0)]
148+
internal SqlGuidLookalike Fake;
149+
}
150+
#endregion
151+
}
152+
}

src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,7 @@
409409
<Compile Include="Microsoft\Data\SqlClient\TdsParserStaticMethods.cs" />
410410
<Compile Include="Microsoft\Data\SqlClient\SqlClientWrapperSmiStreamChars.cs" />
411411
<Compile Include="Microsoft\Data\SqlTypes\SqlStreamChars.cs" />
412+
<Compile Include="Microsoft\Data\SqlTypes\SqlTypeWorkarounds.netfx.cs" />
412413
<Compile Include="Microsoft\Data\Common\NativeMethods.cs" />
413414
<Compile Include="Microsoft\Data\Common\GreenMethods.cs" />
414415
<Compile Include="Microsoft\Data\Common\SQLResource.cs" />

0 commit comments

Comments
 (0)