Skip to content

Commit

Permalink
Use length facet for parameter size
Browse files Browse the repository at this point in the history
Issues:
#4608 Use column/property facets for parameter types in Query Pipeline
#4134 Use column/property facets for parameter types in Update Pipeline

If a property length is specified, then this is used to infer the length to use for parameters relating to that property, unless the length of the data is too long, in which case unbounded length is used. Because query has code that can infer the length to use for a parameter this still means that fragmentation will not happen without always using the 4000/8000 value.
  • Loading branch information
ajcvickers committed May 26, 2016
1 parent 14cba39 commit 921c48f
Show file tree
Hide file tree
Showing 12 changed files with 586 additions and 245 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -170,187 +170,188 @@ public void Log<TState>(
}
}

private static string FormatParameter(DbParameterLogData parameterData)
{
var builder = new StringBuilder();

var value = parameterData.Value;
var clrType = value?.GetType();

FormatParameterValue(builder, value);
public bool IsEnabled(LogLevel logLevel) => true;

if (parameterData.IsNullable
&& value != null
&& !IsNullableType(clrType))
{
builder.Append(" (Nullable = true)");
}
else
{
if (!parameterData.IsNullable
&& parameterData.HasValue
&& (value == null
|| IsNullableType(clrType)))
{
builder.Append(" (Nullable = false)");
}
}
public IDisposable BeginScope<TState>(TState state) => SqlLoggerData._log.Indent();

if (parameterData.Size != 0)
{
builder
.Append(" (Size = ")
.Append(parameterData.Size)
.Append(')');
}
// ReSharper disable once MemberCanBeMadeStatic.Local
public void ResetLoggerData() =>
#if NETSTANDARD1_3
_loggerData.Value = null;
#else
CallContext.LogicalSetData(ContextName, null);
#endif
}

if (parameterData.Precision != 0)
{
builder
.Append(" (Precision = ")
.Append(parameterData.Precision)
.Append(')');
}
public static string FormatParameter(DbParameterLogData parameterData)
{
var builder = new StringBuilder();

if (parameterData.Scale != 0)
{
builder
.Append(" (Scale = ")
.Append(parameterData.Scale)
.Append(')');
}
var value = parameterData.Value;
var clrType = value?.GetType();

if (parameterData.Direction != ParameterDirection.Input)
{
builder
.Append(" (Direction = ")
.Append(parameterData.Direction)
.Append(')');
}
FormatParameterValue(builder, value);

if (parameterData.HasValue
&& !IsNormalDbType(parameterData.DbType, clrType))
if (parameterData.IsNullable
&& value != null
&& !IsNullableType(clrType))
{
builder.Append(" (Nullable = true)");
}
else
{
if (!parameterData.IsNullable
&& parameterData.HasValue
&& (value == null
|| IsNullableType(clrType)))
{
builder
.Append(" (DbType = ")
.Append(parameterData.DbType)
.Append(')');
builder.Append(" (Nullable = false)");
}

return builder.ToString();
}

private static void FormatParameterValue(StringBuilder builder, object parameterValue)
if (parameterData.Size != 0)
{
if (parameterValue.GetType() != typeof(byte[]))
{
builder.Append(Convert.ToString(parameterValue, CultureInfo.InvariantCulture));
return;
}
builder
.Append(" (Size = ")
.Append(parameterData.Size)
.Append(')');
}

var buffer = (byte[])parameterValue;
builder.Append("0x");
if (parameterData.Precision != 0)
{
builder
.Append(" (Precision = ")
.Append(parameterData.Precision)
.Append(')');
}

for (var i = 0; i < buffer.Length; i++)
{
if (i > 31)
{
builder.Append("...");
break;
}
builder.Append(buffer[i].ToString("X2", CultureInfo.InvariantCulture));
}
if (parameterData.Scale != 0)
{
builder
.Append(" (Scale = ")
.Append(parameterData.Scale)
.Append(')');
}

private static bool IsNullableType(Type type)
if (parameterData.Direction != ParameterDirection.Input)
{
var typeInfo = type.GetTypeInfo();
builder
.Append(" (Direction = ")
.Append(parameterData.Direction)
.Append(')');
}

return !typeInfo.IsValueType
|| (typeInfo.IsGenericType
&& (typeInfo.GetGenericTypeDefinition() == typeof(Nullable<>)));
if (parameterData.HasValue
&& !IsNormalDbType(parameterData.DbType, clrType))
{
builder
.Append(" (DbType = ")
.Append(parameterData.DbType)
.Append(')');
}

private static bool IsNormalDbType(DbType dbType, Type clrType)
return builder.ToString();
}

private static void FormatParameterValue(StringBuilder builder, object parameterValue)
{
if (parameterValue.GetType() != typeof(byte[]))
{
if (clrType == null)
{
return false;
}
builder.Append(Convert.ToString(parameterValue, CultureInfo.InvariantCulture));
return;
}

clrType = UnwrapEnumType(UnwrapNullableType(clrType));
var buffer = (byte[])parameterValue;
builder.Append("0x");

switch (dbType)
for (var i = 0; i < buffer.Length; i++)
{
if (i > 31)
{
case DbType.AnsiString: // Zero
return clrType != typeof(string);
case DbType.Binary:
return clrType == typeof(byte[]);
case DbType.Byte:
return clrType == typeof(byte);
case DbType.Boolean:
return clrType == typeof(bool);
case DbType.Decimal:
return clrType == typeof(decimal);
case DbType.Double:
return clrType == typeof(double);
case DbType.Guid:
return clrType == typeof(Guid);
case DbType.Int16:
return clrType == typeof(short);
case DbType.Int32:
return clrType == typeof(int);
case DbType.Int64:
return clrType == typeof(long);
case DbType.Object:
return clrType == typeof(object);
case DbType.SByte:
return clrType == typeof(sbyte);
case DbType.Single:
return clrType == typeof(float);
case DbType.String:
return clrType == typeof(string);
case DbType.Time:
return clrType == typeof(TimeSpan);
case DbType.UInt16:
return clrType == typeof(ushort);
case DbType.UInt32:
return clrType == typeof(uint);
case DbType.UInt64:
return clrType == typeof(ulong);
case DbType.DateTime2:
return clrType == typeof(DateTime);
case DbType.DateTimeOffset:
return clrType == typeof(DateTimeOffset);
//case DbType.VarNumeric:
//case DbType.AnsiStringFixedLength:
//case DbType.StringFixedLength:
//case DbType.Xml:
//case DbType.Currency:
//case DbType.Date:
//case DbType.DateTime:
default:
return false;
builder.Append("...");
break;
}
builder.Append(buffer[i].ToString("X2", CultureInfo.InvariantCulture));
}
}

private static Type UnwrapNullableType(Type type)
=> Nullable.GetUnderlyingType(type) ?? type;
private static bool IsNullableType(Type type)
{
var typeInfo = type.GetTypeInfo();

private static Type UnwrapEnumType(Type type)
=> !type.GetTypeInfo().IsEnum ? type : Enum.GetUnderlyingType(type);
return !typeInfo.IsValueType
|| (typeInfo.IsGenericType
&& (typeInfo.GetGenericTypeDefinition() == typeof(Nullable<>)));
}

public bool IsEnabled(LogLevel logLevel) => true;
private static bool IsNormalDbType(DbType dbType, Type clrType)
{
if (clrType == null)
{
return false;
}

public IDisposable BeginScope<TState>(TState state) => SqlLoggerData._log.Indent();
clrType = UnwrapEnumType(UnwrapNullableType(clrType));

// ReSharper disable once MemberCanBeMadeStatic.Local
public void ResetLoggerData() =>
#if NETSTANDARD1_3
_loggerData.Value = null;
#else
CallContext.LogicalSetData(ContextName, null);
#endif
switch (dbType)
{
case DbType.AnsiString: // Zero
return clrType != typeof(string);
case DbType.Binary:
return clrType == typeof(byte[]);
case DbType.Byte:
return clrType == typeof(byte);
case DbType.Boolean:
return clrType == typeof(bool);
case DbType.Decimal:
return clrType == typeof(decimal);
case DbType.Double:
return clrType == typeof(double);
case DbType.Guid:
return clrType == typeof(Guid);
case DbType.Int16:
return clrType == typeof(short);
case DbType.Int32:
return clrType == typeof(int);
case DbType.Int64:
return clrType == typeof(long);
case DbType.Object:
return clrType == typeof(object);
case DbType.SByte:
return clrType == typeof(sbyte);
case DbType.Single:
return clrType == typeof(float);
case DbType.String:
return clrType == typeof(string);
case DbType.Time:
return clrType == typeof(TimeSpan);
case DbType.UInt16:
return clrType == typeof(ushort);
case DbType.UInt32:
return clrType == typeof(uint);
case DbType.UInt64:
return clrType == typeof(ulong);
case DbType.DateTime2:
return clrType == typeof(DateTime);
case DbType.DateTimeOffset:
return clrType == typeof(DateTimeOffset);
//case DbType.VarNumeric:
//case DbType.AnsiStringFixedLength:
//case DbType.StringFixedLength:
//case DbType.Xml:
//case DbType.Currency:
//case DbType.Date:
//case DbType.DateTime:
default:
return false;
}
}

private static Type UnwrapNullableType(Type type)
=> Nullable.GetUnderlyingType(type) ?? type;

private static Type UnwrapEnumType(Type type)
=> !type.GetTypeInfo().IsEnum ? type : Enum.GetUnderlyingType(type);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,17 @@ protected virtual RelationalTypeMapping CreateMappingFromStoreType([NotNull] str
return null;
}

var closeParen = storeType.IndexOf(")", openParen + 1, StringComparison.Ordinal);
int size;
if (closeParen > openParen
&& int.TryParse(storeType.Substring(openParen + 1, closeParen - openParen - 1), out size)
&& mapping.Size != size)
if (mapping.ClrType == typeof(string)
|| mapping.ClrType == typeof(byte[]))
{
return mapping.CreateCopy(storeType, size);
var closeParen = storeType.IndexOf(")", openParen + 1, StringComparison.Ordinal);
int size;
if (closeParen > openParen
&& int.TryParse(storeType.Substring(openParen + 1, closeParen - openParen - 1), out size)
&& mapping.Size != size)
{
return mapping.CreateCopy(storeType, size);
}
}
}

Expand Down
Loading

0 comments on commit 921c48f

Please sign in to comment.