Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Perf: Change SqlParameter bool fields to flags #1064

Merged
merged 2 commits into from
Jun 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,22 @@ private InstanceDescriptor ConvertToInstanceDescriptor(SqlParameter p)
}
}

[Flags]
private enum SqlParameterFlags : ushort
{
None = 0,
IsNull = 1,
IsNullable = 2,
IsSqlParameterSqlType = 4,
SourceColumnNullMapping = 8,
CoercedValueIsSqlType = 16,
CoercedValueIsDataFeed = 32,
HasReceivedMetadata = 64,
ForceColumnEncryption = 128,
IsDerivedParameterTypeName = 256,
HasScale = 512,
}

private MetaType _metaType;
private SqlCollation _collation;
private SqlMetaDataXmlSchemaCollection _xmlSchemaCollection;
Expand All @@ -217,14 +233,9 @@ private InstanceDescriptor ConvertToInstanceDescriptor(SqlParameter p)
private string _parameterName;
private byte _precision;
private byte _scale;
private bool _hasScale; // V1.0 compat, ignore _hasScale
private MetaType _internalMetaType;
private SqlBuffer _sqlBufferReturnValue;
private INullable _valueAsINullable;
private bool _isSqlParameterSqlType;
private bool _isNull;
private bool _coercedValueIsSqlType;
private bool _coercedValueIsDataFeed;
private int _actualSize;
private object _value;
private object _coercedValue;
Expand All @@ -234,13 +245,12 @@ private InstanceDescriptor ConvertToInstanceDescriptor(SqlParameter p)
private int _offset;
private string _sourceColumn;
private DataRowVersion _sourceVersion;
private bool _sourceColumnNullMapping;
private bool _isNullable;
private SqlParameterFlags _flags;

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlParameter.xml' path='docs/members[@name="SqlParameter"]/ctor2/*' />
public SqlParameter() : base()
{
_isNull = true;
_flags = SqlParameterFlags.IsNull;
_actualSize = -1;
_direction = ParameterDirection.Input;
}
Expand Down Expand Up @@ -360,7 +370,11 @@ private SqlParameter(SqlParameter source) : this()
/// For unencrypted parameters, the encryption metadata should still be sent (and will indicate
/// that no encryption is needed).
/// </summary>
internal bool HasReceivedMetadata { get; set; }
internal bool HasReceivedMetadata
{
get => HasFlag(SqlParameterFlags.HasReceivedMetadata);
set => SetFlag(SqlParameterFlags.HasReceivedMetadata, value);
}

/// <summary>
/// Returns the normalization rule version number as a byte
Expand Down Expand Up @@ -432,7 +446,11 @@ public string XmlSchemaCollectionName
DefaultValue(false),
ResCategory("Data")
]
public bool ForceColumnEncryption { get; set; }
public bool ForceColumnEncryption
{
get => HasFlag(SqlParameterFlags.ForceColumnEncryption);
set => SetFlag(SqlParameterFlags.ForceColumnEncryption, value);
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlParameter.xml' path='docs/members[@name="SqlParameter"]/DbType/*' />
public override DbType DbType
Expand Down Expand Up @@ -547,11 +565,11 @@ internal byte ScaleInternal
}
set
{
if (_scale != value || !_hasScale)
if (_scale != value || !HasFlag(SqlParameterFlags.HasScale))
{
PropertyChanging();
_scale = value;
_hasScale = true;
SetFlag(SqlParameterFlags.HasScale, true);
_actualSize = -1; // Invalidate actual size such that it is re-calculated
}
}
Expand Down Expand Up @@ -714,8 +732,8 @@ public override object Value
_sqlBufferReturnValue = null;
_coercedValue = null;
_valueAsINullable = _value as INullable;
_isSqlParameterSqlType = _valueAsINullable != null;
_isNull = (null == _value) || (_value == DBNull.Value) || (_isSqlParameterSqlType && _valueAsINullable.IsNull);
SetFlag(SqlParameterFlags.IsSqlParameterSqlType, _valueAsINullable != null);
SetFlag(SqlParameterFlags.IsNull, (null == _value) || (_value == DBNull.Value) || (HasFlag(SqlParameterFlags.IsSqlParameterSqlType) && _valueAsINullable.IsNull));
_udtLoadError = null;
_actualSize = -1;
}
Expand Down Expand Up @@ -752,8 +770,8 @@ public override ParameterDirection Direction
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlParameter.xml' path='docs/members[@name="SqlParameter"]/IsNullable/*' />
public override bool IsNullable
{
get => _isNullable;
set => _isNullable = value;
get => HasFlag(SqlParameterFlags.IsNullable);
set => SetFlag(SqlParameterFlags.IsNullable, value);
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlParameter.xml' path='docs/members[@name="SqlParameter"]/Offset/*' />
Expand Down Expand Up @@ -819,8 +837,8 @@ public override string SourceColumn
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlParameter.xml' path='docs/members[@name="SqlParameter"]/SourceColumnNullMapping/*' />
public override bool SourceColumnNullMapping
{
get => _sourceColumnNullMapping;
set => _sourceColumnNullMapping = value;
get => HasFlag(SqlParameterFlags.SourceColumnNullMapping);
set => SetFlag(SqlParameterFlags.SourceColumnNullMapping, value);
}

/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlParameter.xml' path='docs/members[@name="SqlParameter"]/ToString/*' />
Expand Down Expand Up @@ -869,7 +887,7 @@ internal bool CoercedValueIsDataFeed
GetCoercedValue();
}
AssertCachedPropertiesAreValid();
return _coercedValueIsDataFeed;
return HasFlag(SqlParameterFlags.CoercedValueIsDataFeed);
}
}

Expand All @@ -882,7 +900,7 @@ internal bool CoercedValueIsSqlType
GetCoercedValue();
}
AssertCachedPropertiesAreValid();
return _coercedValueIsSqlType;
return HasFlag(SqlParameterFlags.CoercedValueIsSqlType);
}
}

Expand All @@ -895,16 +913,21 @@ internal SqlCollation Collation
set => _collation = value;
}

private bool HasFlag(SqlParameterFlags flag)
{
return (_flags & flag) != 0;
}

internal bool IsNull
{
get
{
// NOTE: Udts can change their value any time
if (_internalMetaType.SqlDbType == SqlDbType.Udt)
{
_isNull = (_value == null) || (_value == DBNull.Value) || (_isSqlParameterSqlType && _valueAsINullable.IsNull);
SetFlag(SqlParameterFlags.IsNull, (_value == null) || (_value == DBNull.Value) || (HasFlag(SqlParameterFlags.IsSqlParameterSqlType) && _valueAsINullable.IsNull));
}
return _isNull;
return HasFlag(SqlParameterFlags.IsNull);
}
}

Expand Down Expand Up @@ -947,8 +970,8 @@ internal byte PrecisionInternal

internal bool ParameterIsSqlType
{
get => _isSqlParameterSqlType;
set => _isSqlParameterSqlType = value;
get => HasFlag(SqlParameterFlags.IsSqlParameterSqlType);
set => SetFlag(SqlParameterFlags.IsSqlParameterSqlType, value);
}

internal string ParameterNameFixed
Expand All @@ -967,7 +990,11 @@ internal string ParameterNameFixed

internal INullable ValueAsINullable => _valueAsINullable;

internal bool IsDerivedParameterTypeName { get; set; }
internal bool IsDerivedParameterTypeName
{
get => HasFlag(SqlParameterFlags.IsDerivedParameterTypeName);
set => SetFlag(SqlParameterFlags.IsDerivedParameterTypeName, value);
}

private void CloneHelper(SqlParameter destination)
{
Expand All @@ -978,9 +1005,17 @@ private void CloneHelper(SqlParameter destination)
destination._offset = _offset;
destination._sourceColumn = _sourceColumn;
destination._sourceVersion = _sourceVersion;
destination._sourceColumnNullMapping = _sourceColumnNullMapping;
destination._isNullable = _isNullable;

destination._flags = _flags & (
SqlParameterFlags.SourceColumnNullMapping |
SqlParameterFlags.IsNull |
SqlParameterFlags.IsNullable |
SqlParameterFlags.IsSqlParameterSqlType |
SqlParameterFlags.CoercedValueIsDataFeed |
SqlParameterFlags.CoercedValueIsSqlType |
SqlParameterFlags.ForceColumnEncryption |
SqlParameterFlags.IsDerivedParameterTypeName
// HasScale and HasReceivedMetadata deliberately omitted
);
destination._metaType = _metaType;
destination._collation = _collation;
if (_xmlSchemaCollection != null)
Expand All @@ -990,20 +1025,14 @@ private void CloneHelper(SqlParameter destination)
destination._udtTypeName = _udtTypeName;
destination._typeName = _typeName;
destination._udtLoadError = _udtLoadError;

destination._parameterName = _parameterName;
destination._precision = _precision;
destination._scale = _scale;
destination._sqlBufferReturnValue = _sqlBufferReturnValue;
destination._isSqlParameterSqlType = _isSqlParameterSqlType;
destination._internalMetaType = _internalMetaType;
destination.CoercedValue = CoercedValue; // copy cached value reference because of XmlReader problem
destination._valueAsINullable = _valueAsINullable;
destination._isNull = _isNull;
destination._coercedValueIsDataFeed = _coercedValueIsDataFeed;
destination._coercedValueIsSqlType = _coercedValueIsSqlType;
destination._actualSize = _actualSize;
destination.ForceColumnEncryption = ForceColumnEncryption;
}

internal void CopyTo(SqlParameter destination)
Expand Down Expand Up @@ -1035,12 +1064,12 @@ internal void FixStreamDataForNonPLP()
{
object value = GetCoercedValue();
AssertCachedPropertiesAreValid();
if (!_coercedValueIsDataFeed)
if (!HasFlag(SqlParameterFlags.CoercedValueIsDataFeed))
{
return;
}

_coercedValueIsDataFeed = false;
SetFlag(SqlParameterFlags.CoercedValueIsDataFeed, false);

if (value is TextDataFeed textFeed)
{
Expand Down Expand Up @@ -1466,7 +1495,7 @@ internal int GetActualSize()
case SqlDbType.NText:
case SqlDbType.Xml:
{
coercedSize = ((!_isNull) && (!_coercedValueIsDataFeed)) ? (StringSize(val, _coercedValueIsSqlType)) : 0;
coercedSize = ((!HasFlag(SqlParameterFlags.IsNull)) && (!HasFlag(SqlParameterFlags.CoercedValueIsDataFeed))) ? (StringSize(val, HasFlag(SqlParameterFlags.CoercedValueIsSqlType))) : 0;
_actualSize = (ShouldSerializeSize() ? Size : 0);
_actualSize = (ShouldSerializeSize() && (_actualSize <= coercedSize)) ? _actualSize : coercedSize;
if (_actualSize == -1)
Expand All @@ -1481,7 +1510,7 @@ internal int GetActualSize()
case SqlDbType.Text:
{
// for these types, ActualSize is the num of chars, not actual bytes - since non-unicode chars are not always uniform size
coercedSize = ((!_isNull) && (!_coercedValueIsDataFeed)) ? (StringSize(val, _coercedValueIsSqlType)) : 0;
coercedSize = ((!HasFlag(SqlParameterFlags.IsNull)) && (!HasFlag(SqlParameterFlags.CoercedValueIsDataFeed))) ? (StringSize(val, HasFlag(SqlParameterFlags.CoercedValueIsSqlType))) : 0;
_actualSize = (ShouldSerializeSize() ? Size : 0);
_actualSize = (ShouldSerializeSize() && (_actualSize <= coercedSize)) ? _actualSize : coercedSize;
if (_actualSize == -1)
Expand All @@ -1494,7 +1523,7 @@ internal int GetActualSize()
case SqlDbType.VarBinary:
case SqlDbType.Image:
case SqlDbType.Timestamp:
coercedSize = ((!_isNull) && (!_coercedValueIsDataFeed)) ? (BinarySize(val, _coercedValueIsSqlType)) : 0;
coercedSize = ((!HasFlag(SqlParameterFlags.IsNull)) && (!HasFlag(SqlParameterFlags.CoercedValueIsDataFeed))) ? (BinarySize(val, HasFlag(SqlParameterFlags.CoercedValueIsSqlType))) : 0;
_actualSize = (ShouldSerializeSize() ? Size : 0);
_actualSize = ((ShouldSerializeSize() && (_actualSize <= coercedSize)) ? _actualSize : coercedSize);
if (_actualSize == -1)
Expand Down Expand Up @@ -1553,14 +1582,15 @@ internal object GetCoercedValue()
{
// No coercion is done for DataFeeds and Nulls
_coercedValue = Value;
_coercedValueIsSqlType = _coercedValue != null && _isSqlParameterSqlType; // set to null for output parameters that keeps _isSqlParameterSqlType
_coercedValueIsDataFeed = isDataFeed;
SetFlag(SqlParameterFlags.CoercedValueIsSqlType, _coercedValue != null && HasFlag(SqlParameterFlags.IsSqlParameterSqlType)); // set to null for output parameters that keeps _isSqlParameterSqlType
SetFlag(SqlParameterFlags.CoercedValueIsDataFeed, isDataFeed);
_actualSize = IsNull ? 0 : -1;
}
else
{
_coercedValue = CoerceValue(Value, _internalMetaType, out _coercedValueIsDataFeed, out bool typeChanged);
_coercedValueIsSqlType = _isSqlParameterSqlType && (!typeChanged); // Type changed always results in a CLR type
_coercedValue = CoerceValue(Value, _internalMetaType, out bool coercedValueIsDataFeed, out bool typeChanged);
SetFlag(SqlParameterFlags.CoercedValueIsDataFeed, coercedValueIsDataFeed);
SetFlag(SqlParameterFlags.CoercedValueIsSqlType, HasFlag(SqlParameterFlags.IsSqlParameterSqlType) && (!typeChanged)); // Type changed always results in a CLR type
_actualSize = -1;
}
}
Expand Down Expand Up @@ -1758,7 +1788,7 @@ internal SmiParameterMetaData MetaDataForSmi(out ParameterPeekAheadValue peekAhe
[Conditional("DEBUG")]
internal void AssertCachedPropertiesAreValid()
{
AssertPropertiesAreValid(_coercedValue, _coercedValueIsSqlType, _coercedValueIsDataFeed, IsNull);
AssertPropertiesAreValid(_coercedValue, HasFlag(SqlParameterFlags.CoercedValueIsSqlType), HasFlag(SqlParameterFlags.CoercedValueIsDataFeed), IsNull);
}

[Conditional("DEBUG")]
Expand Down Expand Up @@ -1806,7 +1836,7 @@ private MetaType GetMetaTypeOnly()
}
else if (_sqlBufferReturnValue != null)
{ // value came back from the server
Type valueType = _sqlBufferReturnValue.GetTypeFromStorageType(_isSqlParameterSqlType);
Type valueType = _sqlBufferReturnValue.GetTypeFromStorageType(HasFlag(SqlParameterFlags.IsSqlParameterSqlType));
if (valueType != null)
{
return MetaType.GetMetaTypeFromType(valueType);
Expand Down Expand Up @@ -1849,13 +1879,18 @@ internal void SetSqlBuffer(SqlBuffer buff)
_sqlBufferReturnValue = buff;
_value = null;
_coercedValue = null;
_isNull = _sqlBufferReturnValue.IsNull;
_coercedValueIsDataFeed = false;
_coercedValueIsSqlType = false;
SetFlag(SqlParameterFlags.IsNull, _sqlBufferReturnValue.IsNull);
SetFlag(SqlParameterFlags.CoercedValueIsDataFeed, false);
SetFlag(SqlParameterFlags.CoercedValueIsSqlType, false);
_udtLoadError = null;
_actualSize = -1;
}

private void SetFlag(SqlParameterFlags flag, bool value)
{
_flags = value ? _flags | flag : _flags & ~flag;
}

internal void SetUdtLoadError(Exception e)
{
_udtLoadError = e;
Expand Down Expand Up @@ -1955,7 +1990,7 @@ internal MetaType ValidateTypeLengths()

if (
(maxSizeInBytes > TdsEnums.TYPE_SIZE_LIMIT) ||
_coercedValueIsDataFeed ||
HasFlag(SqlParameterFlags.CoercedValueIsDataFeed) ||
(sizeInCharacters == -1) ||
(actualSizeInBytes == -1)
)
Expand Down
Loading