Skip to content
Closed
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 @@ -133,7 +133,7 @@ public class YdbQueryableAggregateMethodTranslator(
[sumSqlExpression],
nullable: true,
argumentsPropagateNullability: ArrayUtil.FalseArrays[1],
typeof(decimal)),
typeof(long)),
sumInputType,
sumSqlExpression.TypeMapping);
}
Expand Down
32 changes: 32 additions & 0 deletions src/EFCore.Ydb/src/Query/Internal/YdbSqlExpressionFactory.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using System;
using System.Data;
using System.Diagnostics.CodeAnalysis;
using EntityFrameworkCore.Ydb.Storage.Internal.Mapping;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
using Microsoft.EntityFrameworkCore.Storage;
Expand All @@ -10,4 +13,33 @@ public class YdbSqlExpressionFactory(SqlExpressionFactoryDependencies dependenci
[return: NotNullIfNotNull("sqlExpression")]
public override SqlExpression? ApplyTypeMapping(SqlExpression? sqlExpression, RelationalTypeMapping? typeMapping) =>
base.ApplyTypeMapping(sqlExpression, typeMapping);

public override SqlExpression Coalesce(SqlExpression left, SqlExpression right,
RelationalTypeMapping? typeMapping = null)
{
// For .Sum(x => x.Decimal) EF generates coalesce(sum(x.Decimal), 0.0)) because SUM must have value

if (left is SqlFunctionExpression funcExpression
&&
right is SqlConstantExpression constExpression && constExpression.TypeMapping != null
&&
funcExpression.Name.Equals("SUM", StringComparison.OrdinalIgnoreCase)
&&
funcExpression.Arguments != null
&&
constExpression.TypeMapping.DbType == DbType.Decimal
&&
constExpression.Value != null)
{
// get column expression for SUM function expression
var columnExpression = funcExpression.Arguments[0] as ColumnExpression;

var correctRight = new SqlConstantExpression(constExpression.Value,
YdbDecimalTypeMapping.GetWithMaxPrecision(columnExpression?.TypeMapping?.Scale));

return base.Coalesce(left, correctRight, typeMapping);
}

return base.Coalesce(left, right, typeMapping);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,20 @@ public class YdbDecimalTypeMapping : DecimalTypeMapping
private const byte DefaultPrecision = 22;
private const byte DefaultScale = 9;

private const byte MaxPrecision = 35;

public new static YdbDecimalTypeMapping Default => new();

public static YdbDecimalTypeMapping GetWithMaxPrecision(int? scale) =>
new(new RelationalTypeMappingParameters(
new CoreTypeMappingParameters(
typeof(decimal)),
storeType: "Decimal",
dbType: System.Data.DbType.Decimal,
precision: MaxPrecision,
scale: scale ?? DefaultScale)
);

public YdbDecimalTypeMapping() : this(
new RelationalTypeMappingParameters(
new CoreTypeMappingParameters(typeof(decimal)),
Expand Down Expand Up @@ -41,4 +53,7 @@ protected override void ConfigureParameter(DbParameter parameter)
if (Scale is { } s)
parameter.Scale = (byte)s;
}

protected override string GenerateNonNullSqlLiteral(object value) =>
$"Decimal('{base.GenerateNonNullSqlLiteral(value)}', {Precision ?? DefaultPrecision}, {Scale ?? DefaultScale})";
}
Loading