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

Fix to #15994 - Query: investigate suspicious SQL generated by query tests #18803

Merged
merged 1 commit into from
Nov 12, 2019
Merged
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 @@ -826,6 +826,30 @@ public virtual void Null_semantics_applied_when_comparing_function_with_nullable
useRelationalNulls: false);
}

[ConditionalFact(Skip = "Issue #18773")]
public virtual void Where_IndexOf_empty()
{
AssertQuery<NullSemanticsEntity1>(
es => es.Where(e => e.NullableStringA.IndexOf("") == e.NullableIntA),
es => es.Where(e => 0 == e.NullableIntA),
useRelationalNulls: false);
}

[ConditionalFact(Skip = "issue #18772")]
public virtual void Select_IndexOf()
{
using (var ctx = CreateContext())
{
var query = ctx.Entities1.OrderBy(e => e.Id).Select(e => e.NullableStringA.IndexOf("oo")).ToList();
Copy link
Contributor

Choose a reason for hiding this comment

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

Use AssertQuery syntax.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we don't have "real" assert infra for null semantics tests. Will add it at some point

Copy link
Contributor

Choose a reason for hiding this comment

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

Wouldn't MayBe pattern for client solve the purpose?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the AssertQuery we use in this suite is different than what we use everywhere else - it doesnt support custom projections (always assumes we return IQueryable<NullSemanticsEntityBase>) This was added because we need to pass useRelationalNulls flag to dbcontext, which the normal assert query doesnt provide. However, vast majority of tests uses the c# null semantics so we can just switch to the infra we already have, and places where we would pass useRelationalNulls: true, we can test using CreateContext directly. But I would prefer to do this in a different PR

var expected = _clientData._entities1.OrderBy(e => e.Id).Select(e => MaybeScalar<int>(e.NullableStringA, () => e.NullableStringA.IndexOf("oo"))).ToList();

for (var i = 0; i < query.Count; i++)
{
Assert.Equal(expected[i], query[i]);
}
}
}

[ConditionalFact]
public virtual void Null_semantics_applied_when_comparing_two_functions_with_nullable_arguments()
{
Expand Down Expand Up @@ -933,8 +957,8 @@ join e2 in ctx.Entities2

var result = query.ToList();

var expected = (from e1 in ctx.Entities1.ToList()
join e2 in ctx.Entities2.ToList()
var expected = (from e1 in _clientData._entities1
join e2 in _clientData._entities2
on new
{
one = e1.NullableStringA,
Expand All @@ -950,6 +974,13 @@ join e2 in ctx.Entities2.ToList()
select new { e1, e2 }).ToList();

Assert.Equal(result.Count, expected.Count);
var orderedResult = result.OrderBy(x => x.e1.Id).ThenBy(x => x.e2.Id).ToList();
var orderedExpected = expected.OrderBy(x => x.e1.Id).ThenBy(x => x.e2.Id).ToList();
for (var i = 0; i < orderedExpected.Count; i++)
{
Assert.Equal(orderedExpected[i].e1.Id, orderedResult[i].e1.Id);
Assert.Equal(orderedExpected[i].e2.Id, orderedResult[i].e2.Id);
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ public virtual void Shaper_command_caching_when_parameter_names_different()
.Where(e2 => InMemoryCheck.Check(differentVariableName, e2.CustomerID) || true).Count();
}

[ConditionalFact] // See issue #12771
[ConditionalFact]
public virtual void Can_convert_manually_build_expression_with_default()
{
using var context = CreateContext();
Expand All @@ -252,7 +252,7 @@ public virtual void Can_convert_manually_build_expression_with_default()
Expression.NotEqual(
Expression.Property(
parameter,
"CustomerID"),
"City"),
Expression.Default(typeof(string))),
parameter);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -871,17 +871,16 @@ public override void Where_equal_with_conditional()
{
base.Where_equal_with_conditional();

// issue #15994
// AssertSql(
// @"SELECT [e].[Id]
//FROM [Entities1] AS [e]
//WHERE (CASE
// WHEN ([e].[NullableStringA] = [e].[NullableStringB]) OR ([e].[NullableStringA] IS NULL AND [e].[NullableStringB] IS NULL)
// THEN [e].[NullableStringA] ELSE [e].[NullableStringB]
//END = [e].[NullableStringC]) OR (CASE
// WHEN ([e].[NullableStringA] = [e].[NullableStringB]) OR ([e].[NullableStringA] IS NULL AND [e].[NullableStringB] IS NULL)
// THEN [e].[NullableStringA] ELSE [e].[NullableStringB]
//END IS NULL AND [e].[NullableStringC] IS NULL)");
AssertSql(
@"SELECT [e].[Id]
FROM [Entities1] AS [e]
WHERE (CASE
WHEN ([e].[NullableStringA] = [e].[NullableStringB]) OR ([e].[NullableStringA] IS NULL AND [e].[NullableStringB] IS NULL) THEN [e].[NullableStringA]
ELSE [e].[NullableStringB]
END = [e].[NullableStringC]) OR (CASE
WHEN ([e].[NullableStringA] = [e].[NullableStringB]) OR ([e].[NullableStringA] IS NULL AND [e].[NullableStringB] IS NULL) THEN [e].[NullableStringA]
ELSE [e].[NullableStringB]
END IS NULL AND [e].[NullableStringC] IS NULL)");
}

public override void Where_not_equal_with_conditional()
Expand Down Expand Up @@ -1213,38 +1212,139 @@ public override void Null_semantics_applied_when_comparing_function_with_nullabl
{
base.Null_semantics_applied_when_comparing_function_with_nullable_argument_to_a_nullable_column();

// issue #15994
// AssertSql(
// @"SELECT [e].[Id]
//FROM [Entities1] AS [e]
//WHERE ((CHARINDEX(N'oo', [e].[NullableStringA]) - 1) = [e].[NullableIntA]) OR ([e].[NullableStringA] IS NULL AND [e].[NullableIntA] IS NULL)",
// //
// @"SELECT [e].[Id]
//FROM [Entities1] AS [e]
//WHERE ((CHARINDEX(N'ar', [e].[NullableStringA]) - 1) = [e].[NullableIntA]) OR ([e].[NullableStringA] IS NULL AND [e].[NullableIntA] IS NULL)",
// //
// @"SELECT [e].[Id]
//FROM [Entities1] AS [e]
//WHERE (((CHARINDEX(N'oo', [e].[NullableStringA]) - 1) <> [e].[NullableIntB]) OR ([e].[NullableStringA] IS NULL OR [e].[NullableIntB] IS NULL)) AND ([e].[NullableStringA] IS NOT NULL OR [e].[NullableIntB] IS NOT NULL)");
AssertSql(
@"SELECT [e].[Id]
FROM [Entities1] AS [e]
WHERE (CASE
WHEN N'oo' = N'' THEN 0
ELSE CHARINDEX(N'oo', [e].[NullableStringA]) - 1
END = [e].[NullableIntA]) OR (CASE
WHEN N'oo' = N'' THEN 0
ELSE CHARINDEX(N'oo', [e].[NullableStringA]) - 1
END IS NULL AND [e].[NullableIntA] IS NULL)",
//
@"SELECT [e].[Id]
FROM [Entities1] AS [e]
WHERE (CASE
WHEN N'ar' = N'' THEN 0
ELSE CHARINDEX(N'ar', [e].[NullableStringA]) - 1
END = [e].[NullableIntA]) OR (CASE
WHEN N'ar' = N'' THEN 0
ELSE CHARINDEX(N'ar', [e].[NullableStringA]) - 1
END IS NULL AND [e].[NullableIntA] IS NULL)",
//
@"SELECT [e].[Id]
FROM [Entities1] AS [e]
WHERE ((CASE
WHEN N'oo' = N'' THEN 0
ELSE CHARINDEX(N'oo', [e].[NullableStringA]) - 1
END <> [e].[NullableIntB]) OR (CASE
WHEN N'oo' = N'' THEN 0
ELSE CHARINDEX(N'oo', [e].[NullableStringA]) - 1
END IS NULL OR [e].[NullableIntB] IS NULL)) AND (CASE
WHEN N'oo' = N'' THEN 0
ELSE CHARINDEX(N'oo', [e].[NullableStringA]) - 1
END IS NOT NULL OR [e].[NullableIntB] IS NOT NULL)");
// issue #18773
// AssertSql(
// @"SELECT [e].[Id]
//FROM [Entities1] AS [e]
//WHERE ((CHARINDEX(N'oo', [e].[NullableStringA]) - 1) = [e].[NullableIntA]) OR ([e].[NullableStringA] IS NULL AND [e].[NullableIntA] IS NULL)",
// //
// @"SELECT [e].[Id]
//FROM [Entities1] AS [e]
//WHERE ((CHARINDEX(N'ar', [e].[NullableStringA]) - 1) = [e].[NullableIntA]) OR ([e].[NullableStringA] IS NULL AND [e].[NullableIntA] IS NULL)",
// //
// @"SELECT [e].[Id]
//FROM [Entities1] AS [e]
//WHERE (((CHARINDEX(N'oo', [e].[NullableStringA]) - 1) <> [e].[NullableIntB]) OR ([e].[NullableStringA] IS NULL OR [e].[NullableIntB] IS NULL)) AND ([e].[NullableStringA] IS NOT NULL OR [e].[NullableIntB] IS NOT NULL)");
}

public override void Where_IndexOf_empty()
{
base.Where_IndexOf_empty();

AssertSql(
@"");
}

public override void Null_semantics_applied_when_comparing_two_functions_with_nullable_arguments()
{
base.Null_semantics_applied_when_comparing_two_functions_with_nullable_arguments();

// issue #15994
// AssertSql(
// @"SELECT [e].[Id]
//FROM [Entities1] AS [e]
//WHERE ((CHARINDEX(N'oo', [e].[NullableStringA]) - 1) = (CHARINDEX(N'ar', [e].[NullableStringB]) - 1)) OR ([e].[NullableStringA] IS NULL AND [e].[NullableStringB] IS NULL)",
// //
// @"SELECT [e].[Id]
//FROM [Entities1] AS [e]
//WHERE (((CHARINDEX(N'oo', [e].[NullableStringA]) - 1) <> (CHARINDEX(N'ar', [e].[NullableStringB]) - 1)) OR ([e].[NullableStringA] IS NULL OR [e].[NullableStringB] IS NULL)) AND ([e].[NullableStringA] IS NOT NULL OR [e].[NullableStringB] IS NOT NULL)",
// //
// @"SELECT [e].[Id]
//FROM [Entities1] AS [e]
//WHERE (((CHARINDEX(N'oo', [e].[NullableStringA]) - 1) <> (CHARINDEX(N'ar', [e].[NullableStringA]) - 1)) OR [e].[NullableStringA] IS NULL) AND [e].[NullableStringA] IS NOT NULL");
AssertSql(
@"SELECT [e].[Id]
FROM [Entities1] AS [e]
WHERE (CASE
WHEN N'oo' = N'' THEN 0
ELSE CHARINDEX(N'oo', [e].[NullableStringA]) - 1
END = CASE
WHEN N'ar' = N'' THEN 0
ELSE CHARINDEX(N'ar', [e].[NullableStringB]) - 1
END) OR (CASE
WHEN N'oo' = N'' THEN 0
ELSE CHARINDEX(N'oo', [e].[NullableStringA]) - 1
END IS NULL AND CASE
WHEN N'ar' = N'' THEN 0
ELSE CHARINDEX(N'ar', [e].[NullableStringB]) - 1
END IS NULL)",
//
@"SELECT [e].[Id]
FROM [Entities1] AS [e]
WHERE ((CASE
WHEN N'oo' = N'' THEN 0
ELSE CHARINDEX(N'oo', [e].[NullableStringA]) - 1
END <> CASE
WHEN N'ar' = N'' THEN 0
ELSE CHARINDEX(N'ar', [e].[NullableStringB]) - 1
END) OR (CASE
WHEN N'oo' = N'' THEN 0
ELSE CHARINDEX(N'oo', [e].[NullableStringA]) - 1
END IS NULL OR CASE
WHEN N'ar' = N'' THEN 0
ELSE CHARINDEX(N'ar', [e].[NullableStringB]) - 1
END IS NULL)) AND (CASE
WHEN N'oo' = N'' THEN 0
ELSE CHARINDEX(N'oo', [e].[NullableStringA]) - 1
END IS NOT NULL OR CASE
WHEN N'ar' = N'' THEN 0
ELSE CHARINDEX(N'ar', [e].[NullableStringB]) - 1
END IS NOT NULL)",
//
@"SELECT [e].[Id]
FROM [Entities1] AS [e]
WHERE ((CASE
WHEN N'oo' = N'' THEN 0
ELSE CHARINDEX(N'oo', [e].[NullableStringA]) - 1
END <> CASE
WHEN N'ar' = N'' THEN 0
ELSE CHARINDEX(N'ar', [e].[NullableStringA]) - 1
END) OR (CASE
WHEN N'oo' = N'' THEN 0
ELSE CHARINDEX(N'oo', [e].[NullableStringA]) - 1
END IS NULL OR CASE
WHEN N'ar' = N'' THEN 0
ELSE CHARINDEX(N'ar', [e].[NullableStringA]) - 1
END IS NULL)) AND (CASE
WHEN N'oo' = N'' THEN 0
ELSE CHARINDEX(N'oo', [e].[NullableStringA]) - 1
END IS NOT NULL OR CASE
WHEN N'ar' = N'' THEN 0
ELSE CHARINDEX(N'ar', [e].[NullableStringA]) - 1
END IS NOT NULL)");
// issue #18773
// AssertSql(
// @"SELECT [e].[Id]
//FROM [Entities1] AS [e]
//WHERE ((CHARINDEX(N'oo', [e].[NullableStringA]) - 1) = (CHARINDEX(N'ar', [e].[NullableStringB]) - 1)) OR ([e].[NullableStringA] IS NULL AND [e].[NullableStringB] IS NULL)",
// //
// @"SELECT [e].[Id]
//FROM [Entities1] AS [e]
//WHERE (((CHARINDEX(N'oo', [e].[NullableStringA]) - 1) <> (CHARINDEX(N'ar', [e].[NullableStringB]) - 1)) OR ([e].[NullableStringA] IS NULL OR [e].[NullableStringB] IS NULL)) AND ([e].[NullableStringA] IS NOT NULL OR [e].[NullableStringB] IS NOT NULL)",
// //
// @"SELECT [e].[Id]
//FROM [Entities1] AS [e]
//WHERE (((CHARINDEX(N'oo', [e].[NullableStringA]) - 1) <> (CHARINDEX(N'ar', [e].[NullableStringA]) - 1)) OR [e].[NullableStringA] IS NULL) AND [e].[NullableStringA] IS NOT NULL");
}

public override void Null_semantics_applied_when_comparing_two_functions_with_multiple_nullable_arguments()
Expand Down Expand Up @@ -1333,9 +1433,13 @@ public override void Null_semantics_join_with_composite_key()
{
base.Null_semantics_join_with_composite_key();

// issue #15994
//AssertSql(
// @"");
AssertSql(
@"SELECT [e].[Id], [e].[BoolA], [e].[BoolB], [e].[BoolC], [e].[IntA], [e].[IntB], [e].[IntC], [e].[NullableBoolA], [e].[NullableBoolB], [e].[NullableBoolC], [e].[NullableIntA], [e].[NullableIntB], [e].[NullableIntC], [e].[NullableStringA], [e].[NullableStringB], [e].[NullableStringC], [e].[StringA], [e].[StringB], [e].[StringC], [e0].[Id], [e0].[BoolA], [e0].[BoolB], [e0].[BoolC], [e0].[IntA], [e0].[IntB], [e0].[IntC], [e0].[NullableBoolA], [e0].[NullableBoolB], [e0].[NullableBoolC], [e0].[NullableIntA], [e0].[NullableIntB], [e0].[NullableIntC], [e0].[NullableStringA], [e0].[NullableStringB], [e0].[NullableStringC], [e0].[StringA], [e0].[StringB], [e0].[StringC]
FROM [Entities1] AS [e]
INNER JOIN [Entities2] AS [e0] ON ((([e].[NullableStringA] = [e0].[NullableStringB]) OR ([e].[NullableStringA] IS NULL AND [e0].[NullableStringB] IS NULL)) AND (CASE
WHEN (([e].[NullableStringB] <> [e].[NullableStringC]) OR ([e].[NullableStringB] IS NULL OR [e].[NullableStringC] IS NULL)) AND ([e].[NullableStringB] IS NOT NULL OR [e].[NullableStringC] IS NOT NULL) THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END = COALESCE([e0].[NullableBoolA], [e0].[BoolC]))) AND (CAST(1 AS bit) = CAST(1 AS bit))");
}

public override void Null_semantics_contains()
Expand Down
Loading