Skip to content

Commit

Permalink
Used AppContext for backwards compatibility.
Browse files Browse the repository at this point in the history
  • Loading branch information
DavoudEshtehari committed Mar 22, 2020
1 parent 8fb43d6 commit 8442fe3
Show file tree
Hide file tree
Showing 16 changed files with 105 additions and 230 deletions.
5 changes: 5 additions & 0 deletions BUILDGUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,8 @@ Tests can be built and run with custom Target Frameworks. See the below examples
# Use above property to run Functional Tests with custom TargetFramework (.NET Core)
# Applicable values: netcoreapp2.1 | netcoreapp2.2 | netcoreapp3.0
```
## Set truncation on for scaled decimal parameters

Scaled decimal parameter truncation can be enabled by enabling below AppContext switch:

**"Microsoft.Data.SqlClient.TruncateScaledDecimal"**
Original file line number Diff line number Diff line change
Expand Up @@ -889,29 +889,5 @@ Unable to retrieve value for null key.
</remarks>
<exception cref="T:System.ArgumentNullException">To set the value to null, use <see cref="F:System.DBNull.Value" />.</exception>
</WorkstationID>
<TruncateScaledDecimal>
<summary>Gets or sets a Boolean value that indicates how the decimal scale conversion applies when using either the <see cref="P:Microsoft.Data.SqlClient.SqlParameter" /> type or <see cref="P:Microsoft.Data.SqlClient.SqlBulkCopy" /> type.</summary>
<value>The value of the <see cref="P:Microsoft.Data.SqlClient.SqlConnectionStringBuilder.TruncateScaledDecimal" /> property, or <see langword ="false" /> if none has been supplied.</value>
<remarks>
<format type="text/markdown"><![CDATA[
## Remarks
This property corresponds to the "Truncate Scaled Decimal" key within the connection string.
The value of this key must be `true`, `false`, `yes`, or `no`.
A value of `yes` is treated the same as a value of `true`.
A value of `no` is treated the same as a value of `false`.
If this property is set to **true**, the resulting value will be truncated by the number of <xref:Microsoft.Data.SqlClient.SqlParameter.Scale%2A>'s digits, or as defined in the target table in the <xref:Microsoft.Data.SqlClient.SqlBulkCopy.DestinationTableName%2A> property. Otherwise, the result will be rounded, as is done by Microsoft SQL Server.
> [!NOTE]
> This option is available for applications that need to maintain backwards compatibility with the previous behavior.
]]></format>
</remarks>
<altmember cref="P:Microsoft.Data.SqlClient.SqlConnectionStringBuilder.Keys" />
</TruncateScaledDecimal>
</members>
</docs>
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,6 @@ internal static partial class DbConnectionStringDefaults
internal const SqlConnectionColumnEncryptionSetting ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Disabled;
internal const string EnclaveAttestationUrl = "";
internal const SqlConnectionAttestationProtocol AttestationProtocol = SqlConnectionAttestationProtocol.NotSpecified;
internal const bool TruncateScaledDecimal = false;
}


Expand Down Expand Up @@ -705,7 +704,6 @@ internal static partial class DbConnectionStringKeywords
internal const string ColumnEncryptionSetting = "Column Encryption Setting";
internal const string EnclaveAttestationUrl = "Enclave Attestation Url";
internal const string AttestationProtocol = "Attestation Protocol";
internal const string TruncateScaledDecimal = "Truncate Scaled Decimal";

// common keywords (OleDb, OracleClient, SqlClient)
internal const string DataSource = "Data Source";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,6 @@ public SourceColumnMetadata(ValueMethod method, bool isSqlType, bool isDataFeed)
private int _currentRowLength;
private DataRowState _rowStateToSkip;
private IEnumerator _rowEnumerator;
private bool _truncateScaledDecimal;

private int RowNumber
{
Expand All @@ -231,17 +230,6 @@ private int RowNumber
}
}

private SqlConnection Connection
{
get { return _connection; }
set
{
var cnnStringBuilder = new SqlConnectionStringBuilder(value.ConnectionString);
_truncateScaledDecimal = cnnStringBuilder.TruncateScaledDecimal;
_connection = value;
}
}

private TdsParser _parser;
private TdsParserStateObject _stateObj;
private List<_ColumnMapping> _sortedColumnMappings;
Expand Down Expand Up @@ -279,7 +267,7 @@ public SqlBulkCopy(SqlConnection connection)
{
throw ADP.ArgumentNull(nameof(connection));
}
Connection = connection;
_connection = connection;
_columnMappings = new SqlBulkCopyColumnMappingCollection();
}

Expand All @@ -306,7 +294,7 @@ public SqlBulkCopy(string connectionString)
{
throw ADP.ArgumentNull(nameof(connectionString));
}
Connection = new SqlConnection(connectionString);
_connection = new SqlConnection(connectionString);
_columnMappings = new SqlBulkCopyColumnMappingCollection();
_ownConnection = true;
}
Expand Down Expand Up @@ -1511,8 +1499,7 @@ private object ConvertValue(object value, _SqlMetaData metadata, bool isNull, re

if (sqlValue.Scale != scale)
{
bool roundDecimal = !_truncateScaledDecimal;
sqlValue = TdsParser.AdjustSqlDecimalScale(sqlValue, scale, roundDecimal);
sqlValue = TdsParser.AdjustSqlDecimalScale(sqlValue, scale);
}

if (sqlValue.Precision > precision)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ internal static partial class DEFAULT
internal const SqlConnectionColumnEncryptionSetting ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Disabled;
internal const string EnclaveAttestationUrl = "";
internal static readonly SqlConnectionAttestationProtocol AttestationProtocol = SqlConnectionAttestationProtocol.NotSpecified;
internal const bool Truncate_Scaled_Decimal = false;
}

// SqlConnection ConnectionString Options
Expand Down Expand Up @@ -98,7 +97,6 @@ internal static class KEY
internal const string Connect_Retry_Count = "connectretrycount";
internal const string Connect_Retry_Interval = "connectretryinterval";
internal const string Authentication = "authentication";
internal const string Truncate_Scaled_Decimal = "truncate scaled decimal";
}

// Constant for the number of duplicate options in the connection string
Expand Down Expand Up @@ -224,8 +222,6 @@ internal static class TRANSACTIONBINDING

private readonly string _expandedAttachDBFilename; // expanded during construction so that CreatePermissionSet & Expand are consistent

private readonly bool _truncateScaledDecimal;

internal SqlConnectionString(string connectionString) : base(connectionString, GetParseSynonyms())
{
ThrowUnsupportedIfKeywordSet(KEY.AsynchronousProcessing);
Expand Down Expand Up @@ -281,7 +277,6 @@ internal SqlConnectionString(string connectionString) : base(connectionString, G
_userID = ConvertValueToString(KEY.User_ID, DEFAULT.User_ID);
_workstationId = ConvertValueToString(KEY.Workstation_Id, null);

_truncateScaledDecimal = ConvertValueToBoolean(KEY.Truncate_Scaled_Decimal, DEFAULT.Truncate_Scaled_Decimal);


if (_loadBalanceTimeout < 0)
Expand Down Expand Up @@ -506,7 +501,6 @@ internal SqlConnectionString(SqlConnectionString connectionOptions, string dataS
_columnEncryptionSetting = connectionOptions._columnEncryptionSetting;
_enclaveAttestationUrl = connectionOptions._enclaveAttestationUrl;
_attestationProtocol = connectionOptions._attestationProtocol;
_truncateScaledDecimal = connectionOptions._truncateScaledDecimal;

ValidateValueLength(_dataSource, TdsEnums.MAXLEN_SERVERNAME, KEY.Data_Source);
}
Expand All @@ -532,7 +526,6 @@ internal SqlConnectionString(SqlConnectionString connectionOptions, string dataS
internal bool Pooling { get { return _pooling; } }
internal bool Replication { get { return _replication; } }
internal bool UserInstance { get { return _userInstance; } }
internal bool TruncateScaledDecimal { get { return _truncateScaledDecimal; } }

internal int ConnectTimeout { get { return _connectTimeout; } }
internal int LoadBalanceTimeout { get { return _loadBalanceTimeout; } }
Expand Down Expand Up @@ -655,7 +648,6 @@ internal static Dictionary<string, string> GetParseSynonyms()
{ KEY.Connect_Retry_Count, KEY.Connect_Retry_Count },
{ KEY.Connect_Retry_Interval, KEY.Connect_Retry_Interval },
{ KEY.Authentication, KEY.Authentication },
{ KEY.Truncate_Scaled_Decimal, KEY.Truncate_Scaled_Decimal },

{ SYNONYM.APP, KEY.Application_Name },
{ SYNONYM.Async, KEY.AsynchronousProcessing },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ private enum Keywords
EnclaveAttestationUrl,
AttestationProtocol,

TruncateScaledDecimal,

// keep the count value last
KeywordsCount
}
Expand All @@ -94,7 +92,6 @@ private enum Keywords
private string _typeSystemVersion = DbConnectionStringDefaults.TypeSystemVersion;
private string _userID = DbConnectionStringDefaults.UserID;
private string _workstationID = DbConnectionStringDefaults.WorkstationID;
private bool _truncateScaledDecimal = DbConnectionStringDefaults.TruncateScaledDecimal;

private int _connectTimeout = DbConnectionStringDefaults.ConnectTimeout;
private int _loadBalanceTimeout = DbConnectionStringDefaults.LoadBalanceTimeout;
Expand Down Expand Up @@ -159,7 +156,6 @@ private static string[] CreateValidKeywords()
validKeywords[(int)Keywords.ColumnEncryptionSetting] = DbConnectionStringKeywords.ColumnEncryptionSetting;
validKeywords[(int)Keywords.EnclaveAttestationUrl] = DbConnectionStringKeywords.EnclaveAttestationUrl;
validKeywords[(int)Keywords.AttestationProtocol] = DbConnectionStringKeywords.AttestationProtocol;
validKeywords[(int)Keywords.TruncateScaledDecimal] = DbConnectionStringKeywords.TruncateScaledDecimal;
return validKeywords;
}

Expand Down Expand Up @@ -203,7 +199,6 @@ private static Dictionary<string, Keywords> CreateKeywordsDictionary()
hash.Add(DbConnectionStringKeywords.ColumnEncryptionSetting, Keywords.ColumnEncryptionSetting);
hash.Add(DbConnectionStringKeywords.EnclaveAttestationUrl, Keywords.EnclaveAttestationUrl);
hash.Add(DbConnectionStringKeywords.AttestationProtocol, Keywords.AttestationProtocol);
hash.Add(DbConnectionStringKeywords.TruncateScaledDecimal, Keywords.TruncateScaledDecimal);

hash.Add(DbConnectionStringSynonyms.APP, Keywords.ApplicationName);
hash.Add(DbConnectionStringSynonyms.EXTENDEDPROPERTIES, Keywords.AttachDBFilename);
Expand Down Expand Up @@ -361,9 +356,6 @@ public override object this[string keyword]
case Keywords.ConnectRetryInterval:
ConnectRetryInterval = ConvertToInt32(value);
break;
case Keywords.TruncateScaledDecimal:
TruncateScaledDecimal = ConvertToBoolean(value);
break;

default:
Debug.Fail("unexpected keyword");
Expand Down Expand Up @@ -829,17 +821,6 @@ public override ICollection Values
}
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml' path='docs/members[@name="SqlConnectionStringBuilder"]/TruncateScaledDecimal/*' />
public bool TruncateScaledDecimal
{
get { return _truncateScaledDecimal; }
set
{
SetValue(DbConnectionStringKeywords.TruncateScaledDecimal, value);
_truncateScaledDecimal = value;
}
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlConnectionStringBuilder.xml' path='docs/members[@name="SqlConnectionStringBuilder"]/Clear/*' />
public override void Clear()
{
Expand Down Expand Up @@ -976,8 +957,6 @@ private object GetAt(Keywords index)
return EnclaveAttestationUrl;
case Keywords.AttestationProtocol:
return AttestationProtocol;
case Keywords.TruncateScaledDecimal:
return TruncateScaledDecimal;

default:
Debug.Fail("unexpected keyword");
Expand Down Expand Up @@ -1123,9 +1102,6 @@ private void Reset(Keywords index)
case Keywords.AttestationProtocol:
_attestationProtocol = DbConnectionStringDefaults.AttestationProtocol;
break;
case Keywords.TruncateScaledDecimal:
_truncateScaledDecimal = DbConnectionStringDefaults.TruncateScaledDecimal;
break;
default:
Debug.Fail("unexpected keyword");
throw UnsupportedKeyword(s_validKeywords[(int)index]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ internal sealed partial class TdsParser
// Constants
private const int constBinBufferSize = 4096; // Size of the buffer used to read input parameter of type Stream
private const int constTextBufferSize = 4096; // Size of the buffer (in chars) user to read input parameter of type TextReader
private const string enableTruncateSwitch = "Microsoft.Data.SqlClient.TruncateScaledDecimal"; // for applications that need to maintain backwards compatibility with the previous behavior

// State variables
internal TdsParserState _state = TdsParserState.Closed; // status flag for connection
Expand Down Expand Up @@ -179,11 +180,13 @@ internal SqlInternalConnectionTds Connection
}
}

internal bool TruncateScaledDecimal
private static bool EnableTruncateSwitch
{
get
{
return _connHandler.ConnectionOptions.TruncateScaledDecimal;
bool value;
value = AppContext.TryGetSwitch(enableTruncateSwitch, out value) ? value : false;
return value;
}
}

Expand Down Expand Up @@ -6910,24 +6913,25 @@ private bool TryReadDecimalBits(int length, TdsParserStateObject stateObj, out i
return true;
}

internal static SqlDecimal AdjustSqlDecimalScale(SqlDecimal d, int newScale, bool round)
internal static SqlDecimal AdjustSqlDecimalScale(SqlDecimal d, int newScale)
{
if (d.Scale != newScale)
{
bool round = !EnableTruncateSwitch;
return SqlDecimal.AdjustScale(d, newScale - d.Scale, round);
}

return d;
}

internal static decimal AdjustDecimalScale(decimal value, int newScale, bool round)
internal static decimal AdjustDecimalScale(decimal value, int newScale)
{
int oldScale = (decimal.GetBits(value)[3] & 0x00ff0000) >> 0x10;

if (newScale != oldScale)
{
bool round = !EnableTruncateSwitch;
SqlDecimal num = new SqlDecimal(value);

num = SqlDecimal.AdjustScale(num, newScale - oldScale, round);
return num.Value;
}
Expand Down Expand Up @@ -8973,11 +8977,10 @@ private Task TDSExecuteRPCAddParameter(TdsParserStateObject stateObj, SqlParamet

// bug 49512, make sure the value matches the scale the user enters
if (!isNull)
{
bool roundDecimal = !TruncateScaledDecimal;
{
if (isSqlVal)
{
value = AdjustSqlDecimalScale((SqlDecimal)value, scale, roundDecimal);
value = AdjustSqlDecimalScale((SqlDecimal)value, scale);

// If Precision is specified, verify value precision vs param precision
if (precision != 0)
Expand All @@ -8990,7 +8993,7 @@ private Task TDSExecuteRPCAddParameter(TdsParserStateObject stateObj, SqlParamet
}
else
{
value = AdjustDecimalScale((Decimal)value, scale, roundDecimal);
value = AdjustDecimalScale((Decimal)value, scale);

SqlDecimal sqlValue = new SqlDecimal((Decimal)value);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1027,7 +1027,6 @@ internal static class DbConnectionStringDefaults
internal const SqlConnectionAttestationProtocol AttestationProtocol = SqlConnectionAttestationProtocol.NotSpecified;
internal const string Certificate = "";
internal const PoolBlockingPeriod PoolBlockingPeriod = SqlClient.PoolBlockingPeriod.Auto;
internal const bool TruncateScaledDecimal = false;
}

internal static class DbConnectionOptionKeywords
Expand Down Expand Up @@ -1100,7 +1099,6 @@ internal static class DbConnectionStringKeywords
internal const string EnclaveAttestationUrl = "Enclave Attestation Url";
internal const string AttestationProtocol = "Attestation Protocol";
internal const string PoolBlockingPeriod = "PoolBlockingPeriod";
internal const string TruncateScaledDecimal = "Truncate Scaled Decimal";

// common keywords (OleDb, OracleClient, SqlClient)
internal const string DataSource = "Data Source";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,6 @@ public SourceColumnMetadata(ValueMethod method, bool isSqlType, bool isDataFeed)
private int _currentRowLength;
private DataRowState _rowStateToSkip;
private IEnumerator _rowEnumerator;
private bool _truncateScaledDecimal;

private int RowNumber
{
Expand All @@ -291,17 +290,6 @@ private int RowNumber
}
}

private SqlConnection Connection
{
get { return _connection; }
set
{
var cnnStringBuilder = new SqlConnectionStringBuilder(value.ConnectionString);
_truncateScaledDecimal = cnnStringBuilder.TruncateScaledDecimal;
_connection = value;
}
}

private TdsParser _parser;
private TdsParserStateObject _stateObj;
private List<_ColumnMapping> _sortedColumnMappings;
Expand Down Expand Up @@ -345,7 +333,7 @@ public SqlBulkCopy(SqlConnection connection)
{
throw ADP.ArgumentNull("connection");
}
Connection = connection;
_connection = connection;
_columnMappings = new SqlBulkCopyColumnMappingCollection();
}

Expand Down Expand Up @@ -373,7 +361,7 @@ public SqlBulkCopy(string connectionString) : this(new SqlConnection(connectionS
{
throw ADP.ArgumentNull("connectionString");
}
Connection = new SqlConnection(connectionString);
_connection = new SqlConnection(connectionString);
_columnMappings = new SqlBulkCopyColumnMappingCollection();
_ownConnection = true;
}
Expand Down Expand Up @@ -1659,9 +1647,8 @@ private object ConvertValue(object value, _SqlMetaData metadata, bool isNull, re
}

if (sqlValue.Scale != scale)
{
bool roundDecimal = !_truncateScaledDecimal;
sqlValue = TdsParser.AdjustSqlDecimalScale(sqlValue, scale, roundDecimal);
{
sqlValue = TdsParser.AdjustSqlDecimalScale(sqlValue, scale);
}

if (sqlValue.Precision > precision)
Expand Down
Loading

0 comments on commit 8442fe3

Please sign in to comment.