From 8b37c3f19ef3e0fb0155fa43cda2a01d7a5e4e80 Mon Sep 17 00:00:00 2001 From: Sergei Pavlov Date: Thu, 26 Jun 2025 13:01:32 -0700 Subject: [PATCH] Optimize `TruncateToNetDecimal()`: use `Span` --- .../Sql.Drivers.SqlServer/InternalHelpers.cs | 8 ++++-- .../Sql.Drivers.SqlServer/v09/TypeMapper.cs | 28 +------------------ 2 files changed, 6 insertions(+), 30 deletions(-) diff --git a/Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/InternalHelpers.cs b/Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/InternalHelpers.cs index 6e2e5770e..57d8c718c 100644 --- a/Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/InternalHelpers.cs +++ b/Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/InternalHelpers.cs @@ -131,17 +131,19 @@ public static bool ShouldRetryOn(Exception ex) return ex is TimeoutException; } - private static UInt128 FromSqlDecimalData(int[] a) => - new((uint) a[2] | ((ulong) (uint) a[3] << 32), (uint) a[0] | ((ulong) (uint) a[1] << 32)); + private static UInt128 FromSqlDecimalData(ReadOnlySpan a) => + new(((ulong) a[3] << 32) | a[2], ((ulong) a[1] << 32) | a[0]); internal static decimal TruncateToNetDecimal(SqlDecimal sqlDecimal) { + Span data = stackalloc uint[4]; try { return sqlDecimal.Value; // throws an OverflowException if the value is out of the decimal range. } catch (OverflowException) { var scale = sqlDecimal.Scale; - var u128 = FromSqlDecimalData(sqlDecimal.Data); // sqlDecimal.Data allocates a new array + sqlDecimal.WriteTdsValue(data); + var u128 = FromSqlDecimalData(data); for (; scale > 0 && u128 > Max96bitValue; --scale) { u128 /= Ten; diff --git a/Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/v09/TypeMapper.cs b/Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/v09/TypeMapper.cs index 8530d9aaa..df0a0edd8 100644 --- a/Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/v09/TypeMapper.cs +++ b/Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/v09/TypeMapper.cs @@ -4,7 +4,6 @@ // Created by: Denis Krjuchkov // Created: 2009.07.02 -using System; using System.Data; using System.Data.Common; using Microsoft.Data.SqlClient; @@ -13,7 +12,7 @@ namespace Xtensive.Sql.Drivers.SqlServer.v09 { - internal class TypeMapper : Sql.TypeMapper + internal class TypeMapper(SqlDriver driver) : Sql.TypeMapper(driver) { private static readonly SqlValueType Decimal20Type = new(SqlType.Decimal, 20, 0); @@ -128,24 +127,6 @@ public override void Initialize() dateTimeRange = (ValueRange) Driver.ServerInfo.DataTypes.DateTime.ValueRange; } - private bool TryConvert(SqlDecimal sqlDecimal, out decimal result) - { - var data = sqlDecimal.Data; - if (data[3]==0 && sqlDecimal.Scale <= 28) { - result = new decimal(data[0], data[1], data[2], !sqlDecimal.IsPositive, sqlDecimal.Scale); - return true; - } - result = decimal.Zero; - return false; - } - - private SqlDecimal ReducePrecision(SqlDecimal d, int newPrecision) - { - var newScale = newPrecision - d.Precision + d.Scale; - var truncated = SqlDecimal.Truncate(d, newScale); - return SqlDecimal.ConvertToPrecScale(truncated, newPrecision, newScale); - } - private bool ShouldCompareValues(SqlDecimal valueFromDatabase) { var floorDigitCount = valueFromDatabase.Precision - valueFromDatabase.Scale; @@ -153,12 +134,5 @@ private bool ShouldCompareValues(SqlDecimal valueFromDatabase) return true; return false; } - - // Constructors - - public TypeMapper(SqlDriver driver) - : base(driver) - { - } } }