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

Basic arithmetics #20212

Merged
merged 20 commits into from
Jul 10, 2020
Merged

Basic arithmetics #20212

merged 20 commits into from
Jul 10, 2020

Conversation

lokalmatador
Copy link
Contributor

No description provided.

@lokalmatador
Copy link
Contributor Author

lokalmatador commented Mar 7, 2020

@bricelam draft for basic arithmetics and ef_negate

{
typeof(decimal),
typeof(TimeSpan),
typeof(ulong)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should file an issue to do the ulong ones too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it would make sense, yes. I'd be happy to work on this, when decimals are finished, if OK.

name: "ef_add",
(decimal? left, decimal? right) => left.HasValue && right.HasValue
? decimal.Add(left.Value, right.Value)
: default(decimal?),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this just be...

(decimal? left, decimal? right) => left / right,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean left + right? Yes, it can - and is now.

return decimal.Divide(dividend.Value, divisor.Value);
}

throw new DivideByZeroException();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't Divide just throw this?
Can all of this just be...

(decimal? dividend, decimal? divisor) => dividend / divisor,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, at least the tests passed this way. But it's anyway not needed here, as error checking happens down the path inside Decimal.Dec.Calc.cs which I (see below comment) unfortunately did not realize earlier.

Fixed it.

name: "ef_multiply",
(decimal? left, decimal? right) => left.HasValue && right.HasValue
? decimal.Multiply(left.Value, right.Value)
: default(decimal?),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto. left * right

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

name: "ef_negate",
(decimal? m) => m.HasValue
? decimal.Negate(m.Value)
: default(decimal?),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto. -m

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@lokalmatador
Copy link
Contributor Author

lokalmatador commented Mar 14, 2020

Didn't realize there were also operators...for whatever reason. Need to check more carefully next time. Thanks for the hints.

@lokalmatador
Copy link
Contributor Author

@bricelam sorry for the delay, been a little chaotic here recently. So I gave the error messages related to the above failures a look, but so far lack any idea how to approach this. Apparently, the failing test Microsoft.EntityFrameworkCore.ConfigurationPatternsTest.Can_register_multiple_context_types) also does not run locally and only gives this reason: LocalDb is not accessible on this platform. An external SQL Server must be configured. Any ideas how I could approach this? Thanks!

@smitpatel
Copy link
Member

@lokalmatador - That test has intermittent failure due to high load on SqlServer. I recently disabled that test from running. Can you rebase on latest master? The error should go away. It is not an issue in your PR.

@lokalmatador
Copy link
Contributor Author

@smitpatel Oh yeah, I can see it now. Thanks for the info.

@lokalmatador lokalmatador marked this pull request as ready for review March 29, 2020 12:09
@lokalmatador
Copy link
Contributor Author

Is there anything open on this PR?

Copy link
Member

@smitpatel smitpatel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need functional tests which performs decimal operations in query and assert generated SQL with it.

_ => visitedExpression
};

string ResolveFunctionNameFromExpressionType(ExpressionType expressionType)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@lokalmatador
Copy link
Contributor Author

We need functional tests which performs decimal operations in query and assert generated SQL with it.

@smitpatel Who will add those? Is it supposed to be me? If yes, maybe you can elaborate a little more on it?

@smitpatel
Copy link
Member

@maumar - Can you help with testing here?

@smitpatel
Copy link
Member

Ping @maumar

@bricelam bricelam assigned maumar and unassigned bricelam Jun 9, 2020
@maumar
Copy link
Contributor

maumar commented Jul 9, 2020

@lokalmatador sorry for the super late reply. For the test, please add the following snippet BuiltInDataTypesSqliteTest (around line 1508, just before AssertTranslationFailed helper method):

        [ConditionalFact]
        public virtual void Projecting_aritmetic_operations_on_decimals()
        {
            using var context = CreateContext();
            var expected = (from dt1 in context.Set<BuiltInDataTypes>().ToList()
                            from dt2 in context.Set<BuiltInDataTypes>().ToList()
                            orderby dt1.Id, dt2.Id
                            select new
                            {
                                add = dt1.TestDecimal + dt2.TestDecimal,
                                subtract = dt1.TestDecimal - dt2.TestDecimal,
                                multiply = dt1.TestDecimal * dt2.TestDecimal,
                                divide = dt1.TestDecimal / dt2.TestDecimal,
                                negate = -dt1.TestDecimal
                            }).ToList();

            Fixture.TestSqlLoggerFactory.Clear();

            var actual = (from dt1 in context.Set<BuiltInDataTypes>()
                          from dt2 in context.Set<BuiltInDataTypes>()
                          orderby dt1.Id, dt2.Id
                          select new
                          {
                              add = dt1.TestDecimal + dt2.TestDecimal,
                              subtract = dt1.TestDecimal - dt2.TestDecimal,
                              multiply = dt1.TestDecimal * dt2.TestDecimal,
                              divide = dt1.TestDecimal / dt2.TestDecimal,
                              negate = -dt1.TestDecimal
                          }).ToList();

            Assert.Equal(expected.Count, actual.Count);
            for (var i = 0; i < expected.Count; i++)
            {
                Assert.Equal(expected[i].add, actual[i].add);
                Assert.Equal(expected[i].subtract, actual[i].subtract);
                Assert.Equal(expected[i].multiply, actual[i].multiply);
                Assert.Equal(expected[i].divide, actual[i].divide);
                Assert.Equal(expected[i].negate, actual[i].negate);
            }

            AssertSql(
                @"SELECT ef_add(""b"".""TestDecimal"", ""b0"".""TestDecimal"") AS ""add"", ef_add(""b"".""TestDecimal"", ef_negate(""b0"".""TestDecimal"")) AS ""subtract"", ef_multiply(""b"".""TestDecimal"", ""b0"".""TestDecimal"") AS ""multiply"", ef_divide(""b"".""TestDecimal"", ""b0"".""TestDecimal"") AS ""divide"", ef_negate(""b"".""TestDecimal"") AS ""negate""
FROM ""BuiltInDataTypes"" AS ""b""
CROSS JOIN ""BuiltInDataTypes"" AS ""b0""
ORDER BY ""b"".""Id"", ""b0"".""Id""");
        }

Also, now some tests in NorthwindAggregateOperatorsQuerySqliteTest are failing with different exception (we used to throw translation error now we translate successfully but sqlite throws NSE. Please replace NorthwindAggregateOperatorsQuerySqliteTest listing the with the following:

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore.TestUtilities;
using Xunit;
using Xunit.Abstractions;

namespace Microsoft.EntityFrameworkCore.Query
{
    public class NorthwindAggregateOperatorsQuerySqliteTest : NorthwindAggregateOperatorsQueryRelationalTestBase<NorthwindQuerySqliteFixture<NoopModelCustomizer>>
    {
        public NorthwindAggregateOperatorsQuerySqliteTest(NorthwindQuerySqliteFixture<NoopModelCustomizer> fixture, ITestOutputHelper testOutputHelper)
            : base(fixture)
        {
            ClearLog();
            //Fixture.TestSqlLoggerFactory.SetTestOutputHelper(testOutputHelper);
        }

        public override Task Sum_with_division_on_decimal(bool async)
            => Assert.ThrowsAsync<NotSupportedException>(() => base.Sum_with_division_on_decimal(async));

        public override Task Sum_with_division_on_decimal_no_significant_digits(bool async)
            => Assert.ThrowsAsync<NotSupportedException>(() => base.Sum_with_division_on_decimal_no_significant_digits(async));

        public override Task Average_with_division_on_decimal(bool async)
            => Assert.ThrowsAsync<NotSupportedException>(() => base.Average_with_division_on_decimal(async));

        public override Task Average_with_division_on_decimal_no_significant_digits(bool async)
            => Assert.ThrowsAsync<NotSupportedException>(() => base.Average_with_division_on_decimal_no_significant_digits(async));
    }
}

and I will merge the PR

@smitpatel
Copy link
Member

Investigate NSE please

@lokalmatador
Copy link
Contributor Author

lokalmatador commented Jul 9, 2020

@maumar thanks for the code snippets, @smitpatel will do so!

@maumar
Copy link
Contributor

maumar commented Jul 9, 2020

in TranslateSum/TranslateAverage we check for the argument type to not be decimal. If it is, we throw the NSE that gets surfaced here. When I removed the check, test passes, but not sure if there are some more complicated cases that we are protecting against. @bricelam - thoughts?

@lokalmatador
Copy link
Contributor Author

Test are now passing. No exceptions.

@maumar maumar merged commit 30bb611 into dotnet:master Jul 10, 2020
@maumar
Copy link
Contributor

maumar commented Jul 10, 2020

@lokalmatador I have merged the PR. Thank you for the contribution!

@lokalmatador
Copy link
Contributor Author

You're welcome!

@bricelam
Copy link
Contributor

@maumar The rest of #19635 is about handling aggregates and OrderBy

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants