@@ -710,11 +710,23 @@ private Expression VisitAggregate(Expression source, MethodInfo method, LambdaEx
710710 MethodCallExpression expressionPart )
711711 {
712712 var aggregateType = ExtractAggregateType ( expressionPart ) ;
713+
713714 var origin = VisitAggregateSource ( source , argument , aggregateType , expressionPart ) ;
714715 var originProjection = origin . First ;
715716 var originColumnIndex = origin . Second ;
716- var aggregateDescriptor = new AggregateColumnDescriptor (
717- context . GetNextColumnAlias ( ) , originColumnIndex , aggregateType ) ;
717+
718+ // experiments
719+
720+ var headerColumns = originProjection . ItemProjector . DataSource . Header . Columns ;
721+ var aggregatedColumn = headerColumns [ originColumnIndex ] ;
722+
723+ // For decimal type we try to guess result precision and scale to avoid
724+ // usage of general values which can create some issues result reading
725+ ( int precision , int scale ) ? aggregateTypeHints = TryGuessDecimalPrecisionAndSclale ( aggregatedColumn , headerColumns , context . Model ) ;
726+
727+ var aggregateDescriptor = aggregateTypeHints . HasValue
728+ ? new AggregateColumnDescriptor ( context . GetNextColumnAlias ( ) , originColumnIndex , aggregateType , aggregateTypeHints . Value )
729+ : new AggregateColumnDescriptor ( context . GetNextColumnAlias ( ) , originColumnIndex , aggregateType ) ;
718730 var originDataSource = originProjection . ItemProjector . DataSource ;
719731 var resultDataSource = originDataSource . Aggregate ( null , aggregateDescriptor ) ;
720732
@@ -796,6 +808,68 @@ private Expression VisitAggregate(Expression source, MethodInfo method, LambdaEx
796808 return Expression . Convert ( result , resultType ) ;
797809 }
798810 return result ;
811+
812+
813+ static ( int , int ) ? TryGuessDecimalPrecisionAndSclale ( Column aggregatedColumn , Rse . ColumnCollection headerColumns , Orm . Model . DomainModel domainModel )
814+ {
815+ if ( aggregatedColumn . Type != WellKnownTypes . Decimal )
816+ return null ;
817+
818+ if ( aggregatedColumn is MappedColumn mColumn ) {
819+ var resolvedColumn = mColumn . ColumnInfoRef . Resolve ( domainModel ) ;
820+ if ( resolvedColumn . Precision . HasValue && resolvedColumn . Scale . HasValue )
821+ return ( resolvedColumn . Precision . Value , resolvedColumn . Scale . Value ) ;
822+ }
823+ else if ( aggregatedColumn is CalculatedColumn cColumn ) {
824+ var expression = cColumn . Expression ;
825+ var usedColumns = new Rse . Transformation . TupleAccessGatherer ( ) . Gather ( expression ) ;
826+
827+ var maxFloorDigits = 0 ;
828+ var maxScaleDigits = 0 ;
829+ foreach ( var cIndex in usedColumns ) {
830+ var usedColumn = headerColumns [ cIndex ] ;
831+ if ( usedColumn is MappedColumn mmColumn ) {
832+ var resolvedColumn = mmColumn . ColumnInfoRef . Resolve ( domainModel ) ;
833+ var precision = resolvedColumn . Precision ;
834+ var scale = resolvedColumn . Scale ;
835+ if ( resolvedColumn . ValueType != WellKnownTypes . Decimal ) {
836+ if ( ! precision . HasValue ) {
837+ precision = Type . GetTypeCode ( resolvedColumn . ValueType ) switch {
838+ TypeCode . Byte or TypeCode . SByte => 8 ,
839+ TypeCode . UInt16 or TypeCode . Int16 => 10 ,
840+ TypeCode . UInt32 => 18 ,
841+ TypeCode . UInt64 or TypeCode . Int64 => 28 ,
842+ TypeCode . Int32 => 19 ,
843+ _ => null
844+ } ;
845+ }
846+
847+ if ( ! scale . HasValue ) {
848+ scale = Type . GetTypeCode ( resolvedColumn . ValueType ) switch {
849+ TypeCode . Byte or TypeCode . SByte or TypeCode . UInt16 or TypeCode . Int16 => 5 ,
850+ TypeCode . UInt32 or TypeCode . Int32 or TypeCode . UInt64 or TypeCode . Int64 => 8 ,
851+ _ => null
852+ } ;
853+ }
854+ }
855+
856+ if ( precision . HasValue && scale . HasValue ) {
857+ if ( maxScaleDigits < scale . Value )
858+ maxScaleDigits = scale . Value ;
859+ var floorDigits = precision . Value - scale . Value ;
860+ if ( maxFloorDigits < floorDigits )
861+ maxFloorDigits = floorDigits ;
862+ }
863+ }
864+ }
865+ if ( maxFloorDigits == 0 && maxScaleDigits == 0 )
866+ return null ;
867+ if ( maxFloorDigits + maxScaleDigits <= 28 )
868+ return ( maxFloorDigits + maxScaleDigits , maxScaleDigits ) ;
869+ }
870+
871+ return null ;
872+ }
799873 }
800874
801875 private CompilableProvider ChooseSourceForAggregate ( CompilableProvider left , CompilableProvider right ,
0 commit comments