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

Translate x.parse #28337

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open

Translate x.parse #28337

wants to merge 12 commits into from

Conversation

MaRK0960
Copy link

@MaRK0960 MaRK0960 commented Jun 28, 2022

Fixes #28287

  • I've read the guidelines for contributing and seen the walkthrough
  • I've posted a comment on an issue with a detailed description of how I am planning to contribute and got approval from a member of the team
  • The code builds and tests pass locally (also verified by our automated build checks)
  • Commit messages follow this format:
        Summary of the changes
        - Detail 1
        - Detail 2

        Fixes #bugnumber
  • Tests for the changes have been added (for bug fixes / features)
  • Code follows the same patterns and style as existing code in this repo

@dnfadmin
Copy link

dnfadmin commented Jun 28, 2022

CLA assistant check
All CLA requirements met.

@smitpatel
Copy link
Member

Can we also get tests which converts from actual string values. Also some negative tests where the string is not exactly parse-able and we verify database behavior.

MaRK0960 added 2 commits June 29, 2022 21:43
Added tests against overflow.
Added tests against bad format.
Copy link
Member

@roji roji left a comment

Choose a reason for hiding this comment

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

Thanks for the changes. This looks almost ready, see below for some nits and test cleanup.

{
await AssertQuery(
async,
ss => ss.Set<Order>().Where(o => o.CustomerID == "ALFKI")
Copy link
Member

Choose a reason for hiding this comment

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

Merge the two Where clauses (here and below). Also consider removing the check for CustomerID - is there any reason to restrict to those rows only?

Copy link
Author

Choose a reason for hiding this comment

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

Some rows are not parse-able, making them not suitable for this test.

.Where(o => byte.Parse(Convert.ToString(o.OrderID % 1)) >= 0),
entryCount: 6);

await AssertQuery(
Copy link
Member

Choose a reason for hiding this comment

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

Any reason for the 2nd test query? I can see this below as well - the point here generally isn't to check that the database operation works (we don't test the database, only EF), so I'm not sure what this one checks beyond the above.

Unless the extra queries add coverage for EF specifically, I think it's better to just do one query per test.

MaRK0960 added 2 commits July 11, 2022 13:05
nameof instead of string.
Merge the Where clauses.
@MaRK0960 MaRK0960 requested a review from roji July 19, 2022 17:32
@MaRK0960
Copy link
Author

MaRK0960 commented Aug 3, 2022

@roji Is there anything else?

@tmricardo7
Copy link

any updates on this @roji ?

@roji
Copy link
Member

roji commented Nov 17, 2022

@MaRK0960 sorry for not giving this any attention - the 7.0 release (and resulting bugfixes) are have taken up most of my time. I'll do my best to look at this again in the next couple of weeks.

Copy link
Member

@roji roji left a comment

Choose a reason for hiding this comment

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

@MaRK0960 apologies for letting this sit for so long without reviewing. Aside from one important note (the one about type inference), I think this is more or less ready; I'm happy to also take over this (as we haven't responded for so long), let me know what you want to do.

async,
ss => ss.Set<Customer>()
.Where(c => c.CustomerID == "ALFKI")
.Select(c => byte.Parse(c.CustomerID)));
Copy link
Member

Choose a reason for hiding this comment

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

It's never a good idea to put the tested invocation in the top-most select, because providers that don't have a translation for it will go into client evaluation. Ideally, these tests would simply have Parse in the Where clause instead.

@@ -14,4 +14,56 @@ public class NorthwindFunctionsQueryInMemoryTest : NorthwindFunctionsQueryTestBa
{
//TestLoggerFactory.TestOutputHelper = testOutputHelper;
}

public override Task Byte_Parse_Non_Numeric_Bad_Format(bool async)
Copy link
Member

Choose a reason for hiding this comment

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

It's not great to force all providers to override and catch an exception... But on the other hand it's true that the exception type itself varies from provider to provider. It may be enough to simply verify that an exception is caught in the base implementation without asserting which kind it is.

Copy link
Author

Choose a reason for hiding this comment

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

There is a test in SqlServer that checks if all tests are overridden:

[ConditionalFact]
public virtual void Check_all_tests_overridden()
=> TestHelpers.AssertAllMethodsOverridden(GetType());

And if the assertion is done in the base class, we can't override it.

IDiagnosticsLogger<DbLoggerCategory.Query> logger)
=> SupportedMethods.Contains(method)
? _sqlExpressionFactory.Function(
"CONVERT",
Copy link
Member

Choose a reason for hiding this comment

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

There's a subtle problem here, where the type mapping coming out of the conversion is fixed and depends only on the CLR type; this doesn't allow for type inference to apply a type mapping from the other side of e.g. a comarison.

For example, let's assume you do int.Parse(decimalParam) == b.SomeDecimalColumn, where SomeColumn has a type mapping of decimal(5,2). Your translation of int.Parse would convert decimalParam to decimal(18,2), because that's the fixed value in the table above; but it should allow the column type mapping to be inferred from the other side instead.

The right way to do this would be to simply use _sqlExpressionFactory.Convert(), specifying only the CLR type and not the type mapping. This produces CAST(x AS y) instead of CONVERT, and since the type mapping is null, it can be inferred from the other side.

@MaRK0960
Copy link
Author

No problem, I will continue working on it.

@roji
Copy link
Member

roji commented Apr 25, 2023

@MaRK0960 ok great, let me know if you run out of time or something, otherwise you can ask for another review after you've made changes etc.

@MaRK0960 MaRK0960 requested a review from roji May 4, 2023 19:25
@Saibamen
Copy link

@roji: ping

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.

Translate int.Parse and similar
7 participants