Improve handling of scalar subqueries in order by clause (#177)

* Add expression visitor to locate a scalar subquery. Handles finding deeper subqueries better than original code.
Also handle the case where the expression can be regarded as scalar (i.e. has a TOP 1 and projects only one field). In that case we rewrite the projections so that we take out any previously added projections as it is clear we are not needing it higher up in the SQL
pull/178/head
Christopher Jolly 2 years ago committed by GitHub
parent 9e9ef1bd2b
commit 1c29984574
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,14 +1,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;
using EntityFrameworkCore.Jet.Utilities;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Query.Internal;
using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
using Microsoft.EntityFrameworkCore.Storage;
@ -65,14 +59,15 @@ public class JetLiftOrderByPostprocessor : ExpressionVisitor
case SelectExpression selectExpression:
{
Dictionary<int, (int? indexcol, OrderingExpression? orderexp, bool ascend, bool rewrite, bool referstocurouter)> columnsToRewrite = new();
bool isscalarselect = selectExpression is { Limit: SqlConstantExpression { Value: 1 }, Projection.Count: 1 };
for (int i = 0; i < selectExpression.Orderings.Count; i++)
{
var sqlExpression = selectExpression.Orderings[i].Expression;
if (sqlExpression is not ColumnExpression)
{
bool containsscalar = sqlExpression is ScalarSubqueryExpression;
containsscalar = containsscalar || TryPeekFunction(sqlExpression as SqlFunctionExpression) || TryPeekCase(sqlExpression as CaseExpression) || TryPeekExists(sqlExpression as ExistsExpression);
var locate = new JetLocateScalarSubqueryVisitor(_typeMappingSource, _sqlExpressionFactory);
var locatedExpression = locate.Visit(sqlExpression);
bool containsscalar = locatedExpression is ScalarSubqueryExpression or ExistsExpression;
if (containsscalar)
{
int index = selectExpression.AddToProjection(sqlExpression);
@ -134,6 +129,25 @@ public class JetLiftOrderByPostprocessor : ExpressionVisitor
selectExpression.AppendOrdering(new OrderingExpression(newcolexp, ascending));
}
}
if (isscalarselect)
{
List<ProjectionExpression> newProjections = new List<ProjectionExpression>();
for (int j = 0; j < selectExpression.Projection.Count; j++)
{
var proj = selectExpression.Projection[j];
var item = columnsToRewrite.SingleOrDefault(c => c.Value.indexcol == j);
if (item.Value.indexcol == null)
{
newProjections.Add(proj);
}
}
selectExpression = selectExpression.Update(newProjections, selectExpression.Tables, selectExpression.Predicate,
selectExpression.GroupBy, selectExpression.Having, selectExpression.Orderings,
selectExpression.Limit, selectExpression.Offset);
}
var result = base.Visit(selectExpression);
return result;
}
@ -141,24 +155,4 @@ public class JetLiftOrderByPostprocessor : ExpressionVisitor
return base.Visit(expression);
}
private bool TryPeekExists(ExistsExpression? existsExpression)
{
return existsExpression is not null;
}
private bool TryPeekCase(CaseExpression? sqlExpression)
{
if (sqlExpression is null) return false;
if (sqlExpression.ElseResult is ScalarSubqueryExpression) return true;
if (sqlExpression.WhenClauses.Any(x => x.Result is ScalarSubqueryExpression)) return true;
if (sqlExpression.Operand is ScalarSubqueryExpression) return true;
return false;
}
private bool TryPeekFunction(SqlFunctionExpression? sqlExpression)
{
if (sqlExpression is null) return false;
return sqlExpression.Arguments != null && sqlExpression.Arguments.Any(x => x is ScalarSubqueryExpression);
}
}

@ -0,0 +1,413 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;
using EntityFrameworkCore.Jet.Utilities;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Query.Internal;
using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
using Microsoft.EntityFrameworkCore.Storage;
namespace EntityFrameworkCore.Jet.Query.Internal;
/// <remarks>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </remarks>
public class JetLocateScalarSubqueryVisitor : SqlExpressionVisitor
{
private readonly IRelationalTypeMappingSource _typeMappingSource;
private readonly ISqlExpressionFactory _sqlExpressionFactory;
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public JetLocateScalarSubqueryVisitor(
IRelationalTypeMappingSource typeMappingSource,
ISqlExpressionFactory sqlExpressionFactory)
{
(_typeMappingSource, _sqlExpressionFactory) = (typeMappingSource, sqlExpressionFactory);
}
protected override Expression VisitAtTimeZone(AtTimeZoneExpression atTimeZoneExpression)
{
var operand = (SqlExpression)Visit(atTimeZoneExpression.Operand);
var timeZone = (SqlExpression)Visit(atTimeZoneExpression.TimeZone);
return atTimeZoneExpression.Update(operand, timeZone);
}
protected override Expression VisitCase(CaseExpression caseExpression)
{
var operand = (SqlExpression?)Visit(caseExpression.Operand);
var whenClauses = new List<CaseWhenClause>();
foreach (var whenClause in caseExpression.WhenClauses)
{
var test = (SqlExpression)Visit(whenClause.Test);
var result = (SqlExpression)Visit(whenClause.Result);
whenClauses.Add(new CaseWhenClause(test, result));
}
var elseResult = (SqlExpression?)Visit(caseExpression.ElseResult);
return caseExpression.Update(operand, whenClauses, elseResult);
}
protected override Expression VisitCollate(CollateExpression collateExpression)
{
var operand = (SqlExpression)Visit(collateExpression.Operand);
return collateExpression.Update(operand);
}
protected override Expression VisitColumn(ColumnExpression columnExpression)
{
return columnExpression;
}
protected override Expression VisitCrossApply(CrossApplyExpression crossApplyExpression)
{
var table = (TableExpressionBase)Visit(crossApplyExpression.Table);
return crossApplyExpression.Update(table);
}
protected override Expression VisitCrossJoin(CrossJoinExpression crossJoinExpression)
{
var table = (TableExpressionBase)Visit(crossJoinExpression.Table);
return crossJoinExpression.Update(table);
}
protected override Expression VisitDelete(DeleteExpression deleteExpression)
{
return deleteExpression.Update((SelectExpression)Visit(deleteExpression.SelectExpression));
}
protected override Expression VisitDistinct(DistinctExpression distinctExpression)
{
var operand = (SqlExpression)Visit(distinctExpression.Operand);
return distinctExpression.Update(operand);
}
protected override Expression VisitExcept(ExceptExpression exceptExpression)
{
var source1 = (SelectExpression)Visit(exceptExpression.Source1);
var source2 = (SelectExpression)Visit(exceptExpression.Source2);
return exceptExpression.Update(source1, source2);
}
protected override Expression VisitExists(ExistsExpression existsExpression)
{
var subquery = (SelectExpression)Visit(existsExpression.Subquery);
return existsExpression.Update(subquery);
}
protected override Expression VisitFromSql(FromSqlExpression fromSqlExpression)
{
return fromSqlExpression;
}
protected override Expression VisitIn(InExpression inExpression)
{
var item = (SqlExpression)Visit(inExpression.Item);
var subquery = (SelectExpression?)Visit(inExpression.Subquery);
var values = inExpression.Values;
SqlExpression[]? newValues = null;
if (values is not null)
{
for (var i = 0; i < values.Count; i++)
{
var value = values[i];
var newValue = (SqlExpression)Visit(value);
if (newValue != value && newValues is null)
{
newValues = new SqlExpression[values.Count];
for (var j = 0; j < i; j++)
{
newValues[j] = values[j];
}
}
if (newValues is not null)
{
newValues[i] = newValue;
}
}
}
var valuesParameter = (SqlParameterExpression?)Visit(inExpression.ValuesParameter);
return inExpression.Update(item, subquery, newValues ?? values, valuesParameter);
}
protected override Expression VisitIntersect(IntersectExpression intersectExpression)
{
var source1 = (SelectExpression)Visit(intersectExpression.Source1);
var source2 = (SelectExpression)Visit(intersectExpression.Source2);
return intersectExpression.Update(source1, source2);
}
protected override Expression VisitLike(LikeExpression likeExpression)
{
var match = (SqlExpression)Visit(likeExpression.Match);
var pattern = (SqlExpression)Visit(likeExpression.Pattern);
var escapeChar = (SqlExpression?)Visit(likeExpression.EscapeChar);
return likeExpression.Update(match, pattern, escapeChar);
}
protected override Expression VisitInnerJoin(InnerJoinExpression innerJoinExpression)
{
var table = (TableExpressionBase)Visit(innerJoinExpression.Table);
var joinPredicate = (SqlExpression)Visit(innerJoinExpression.JoinPredicate);
return innerJoinExpression.Update(table, joinPredicate);
}
protected override Expression VisitLeftJoin(LeftJoinExpression leftJoinExpression)
{
var table = (TableExpressionBase)Visit(leftJoinExpression.Table);
var joinPredicate = (SqlExpression)Visit(leftJoinExpression.JoinPredicate);
return leftJoinExpression.Update(table, joinPredicate);
}
protected override Expression VisitOrdering(OrderingExpression orderingExpression)
{
var expression = (SqlExpression)Visit(orderingExpression.Expression);
return orderingExpression.Update(expression);
}
protected override Expression VisitOuterApply(OuterApplyExpression outerApplyExpression)
{
var table = (TableExpressionBase)Visit(outerApplyExpression.Table);
return outerApplyExpression.Update(table);
}
protected override Expression VisitProjection(ProjectionExpression projectionExpression)
{
var expression = (SqlExpression)Visit(projectionExpression.Expression);
return projectionExpression.Update(expression);
}
protected override Expression VisitTableValuedFunction(TableValuedFunctionExpression tableValuedFunctionExpression)
{
var arguments = new SqlExpression[tableValuedFunctionExpression.Arguments.Count];
for (var i = 0; i < arguments.Length; i++)
{
arguments[i] = (SqlExpression)Visit(tableValuedFunctionExpression.Arguments[i]);
}
return tableValuedFunctionExpression.Update(arguments);
}
protected override Expression VisitRowNumber(RowNumberExpression rowNumberExpression)
{
var partitions = new List<SqlExpression>();
foreach (var partition in rowNumberExpression.Partitions)
{
var newPartition = (SqlExpression)Visit(partition);
partitions.Add(newPartition);
}
var orderings = new List<OrderingExpression>();
foreach (var ordering in rowNumberExpression.Orderings)
{
var newOrdering = (OrderingExpression)Visit(ordering);
orderings.Add(newOrdering);
}
return rowNumberExpression.Update(partitions, orderings);
}
protected override Expression VisitRowValue(RowValueExpression rowValueExpression)
{
var values = new SqlExpression[rowValueExpression.Values.Count];
for (var i = 0; i < values.Length; i++)
{
values[i] = (SqlExpression)Visit(rowValueExpression.Values[i]);
}
return rowValueExpression.Update(values);
}
protected override Expression VisitScalarSubquery(ScalarSubqueryExpression scalarSubqueryExpression)
{
return scalarSubqueryExpression;
}
protected override Expression VisitSelect(SelectExpression selectExpression)
{
var changed = false;
var projections = new List<ProjectionExpression>();
foreach (var item in selectExpression.Projection)
{
var updatedProjection = (ProjectionExpression)Visit(item);
projections.Add(updatedProjection);
changed |= updatedProjection != item;
}
var tables = new List<TableExpressionBase>();
foreach (var table in selectExpression.Tables)
{
var newTable = (TableExpressionBase)Visit(table);
changed |= newTable != table;
tables.Add(newTable);
}
var predicate = (SqlExpression?)Visit(selectExpression.Predicate);
changed |= predicate != selectExpression.Predicate;
var groupBy = new List<SqlExpression>();
foreach (var groupingKey in selectExpression.GroupBy)
{
var newGroupingKey = (SqlExpression)Visit(groupingKey);
changed |= newGroupingKey != groupingKey;
groupBy.Add(newGroupingKey);
}
var havingExpression = (SqlExpression?)Visit(selectExpression.Having);
changed |= havingExpression != selectExpression.Having;
var orderings = new List<OrderingExpression>();
foreach (var ordering in selectExpression.Orderings)
{
var orderingExpression = (SqlExpression)Visit(ordering.Expression);
changed |= orderingExpression != ordering.Expression;
orderings.Add(ordering.Update(orderingExpression));
}
var offset = (SqlExpression?)Visit(selectExpression.Offset);
changed |= offset != selectExpression.Offset;
var limit = (SqlExpression?)Visit(selectExpression.Limit);
changed |= limit != selectExpression.Limit;
return changed
? selectExpression.Update(
projections, tables, predicate, groupBy, havingExpression, orderings, limit, offset)
: selectExpression;
}
protected override Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpression)
{
var newLeft = (SqlExpression)Visit(sqlBinaryExpression.Left);
var newRight = (SqlExpression)Visit(sqlBinaryExpression.Right);
if (newLeft is ScalarSubqueryExpression)
{
return newLeft;
}
if (newRight is ScalarSubqueryExpression)
{
return newRight;
}
sqlBinaryExpression = sqlBinaryExpression.Update(newLeft, newRight);
return sqlBinaryExpression;
}
protected override Expression VisitSqlConstant(SqlConstantExpression sqlConstantExpression)
{
return sqlConstantExpression;
}
protected override Expression VisitSqlFragment(SqlFragmentExpression sqlFragmentExpression)
{
return sqlFragmentExpression;
}
protected override Expression VisitSqlFunction(SqlFunctionExpression sqlFunctionExpression)
{
var instance = (SqlExpression?)Visit(sqlFunctionExpression.Instance);
SqlExpression[]? arguments = default;
if (!sqlFunctionExpression.IsNiladic)
{
arguments = new SqlExpression[sqlFunctionExpression.Arguments.Count];
for (var i = 0; i < arguments.Length; i++)
{
arguments[i] = (SqlExpression)Visit(sqlFunctionExpression.Arguments[i]);
if (arguments[i] is ScalarSubqueryExpression)
{
return arguments[i];
}
}
}
var newFunction = sqlFunctionExpression.Update(instance, arguments);
return newFunction;
}
protected override Expression VisitSqlParameter(SqlParameterExpression sqlParameterExpression)
{
return sqlParameterExpression;
}
protected override Expression VisitSqlUnary(SqlUnaryExpression sqlUnaryExpression)
{
var operand = (SqlExpression)Visit(sqlUnaryExpression.Operand);
if (operand is ScalarSubqueryExpression)
{
return operand;
}
return sqlUnaryExpression.Update(operand);
}
protected override Expression VisitTable(TableExpression tableExpression)
{
return tableExpression;
}
protected override Expression VisitUnion(UnionExpression unionExpression)
{
var source1 = (SelectExpression)Visit(unionExpression.Source1);
var source2 = (SelectExpression)Visit(unionExpression.Source2);
return unionExpression.Update(source1, source2);
}
protected override Expression VisitUpdate(UpdateExpression updateExpression)
{
var selectExpression = (SelectExpression)Visit(updateExpression.SelectExpression);
List<ColumnValueSetter>? columnValueSetters = null;
for (var (i, n) = (0, updateExpression.ColumnValueSetters.Count); i < n; i++)
{
var columnValueSetter = updateExpression.ColumnValueSetters[i];
var newValue = (SqlExpression)Visit(columnValueSetter.Value);
if (columnValueSetters != null)
{
columnValueSetters.Add(new ColumnValueSetter(columnValueSetter.Column, newValue));
}
else if (!ReferenceEquals(newValue, columnValueSetter.Value))
{
columnValueSetters = new List<ColumnValueSetter>();
for (var j = 0; j < i; j++)
{
columnValueSetters.Add(updateExpression.ColumnValueSetters[j]);
}
columnValueSetters.Add(new ColumnValueSetter(columnValueSetter.Column, newValue));
}
}
return updateExpression.Update(selectExpression, columnValueSetters ?? updateExpression.ColumnValueSetters);
}
protected override Expression VisitJsonScalar(JsonScalarExpression jsonScalarExpression)
{
return jsonScalarExpression;
}
protected override Expression VisitValues(ValuesExpression valuesExpression)
{
var rowValues = new RowValueExpression[valuesExpression.RowValues.Count];
for (var i = 0; i < rowValues.Length; i++)
{
rowValues[i] = (RowValueExpression)Visit(valuesExpression.RowValues[i]);
}
return valuesExpression.Update(rowValues);
}
}

@ -10279,6 +10279,8 @@ EntityFrameworkCore.Jet.FunctionalTests.Query.NorthwindMiscellaneousQueryJetTest
EntityFrameworkCore.Jet.FunctionalTests.Query.NorthwindMiscellaneousQueryJetTest.OrderBy_conditional_operator(isAsync: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.NorthwindMiscellaneousQueryJetTest.OrderBy_correlated_subquery1(isAsync: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.NorthwindMiscellaneousQueryJetTest.OrderBy_correlated_subquery1(isAsync: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.NorthwindMiscellaneousQueryJetTest.OrderBy_correlated_subquery2(isAsync: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.NorthwindMiscellaneousQueryJetTest.OrderBy_correlated_subquery2(isAsync: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.NorthwindMiscellaneousQueryJetTest.OrderBy_Dto_projection_skip_take(isAsync: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.NorthwindMiscellaneousQueryJetTest.OrderBy_Dto_projection_skip_take(isAsync: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.NorthwindMiscellaneousQueryJetTest.OrderBy_empty_list_contains(isAsync: False)

@ -10513,8 +10513,12 @@ EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_subqu
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_subquery_boolean(isAsync: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_subquery_distinct_singleordefault_boolean2(isAsync: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_subquery_distinct_singleordefault_boolean2(isAsync: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_subquery_equality_to_null_with_composite_key_should_match_nulls(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_subquery_equality_to_null_with_composite_key_should_match_nulls(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_subquery_equality_to_null_with_composite_key(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_subquery_equality_to_null_with_composite_key(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_subquery_equality_to_null_without_composite_key_should_match_null(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_subquery_equality_to_null_without_composite_key_should_match_null(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_subquery_equality_to_null_without_composite_key(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_subquery_equality_to_null_without_composite_key(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.GearsOfWarQueryJetTest.Where_TimeOnly_Add_TimeSpan(async: False)
@ -13138,6 +13142,8 @@ EntityFrameworkCore.Jet.FunctionalTests.Query.NorthwindMiscellaneousQueryJetTest
EntityFrameworkCore.Jet.FunctionalTests.Query.NorthwindMiscellaneousQueryJetTest.OrderBy_conditional_operator(isAsync: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.NorthwindMiscellaneousQueryJetTest.OrderBy_correlated_subquery1(isAsync: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.NorthwindMiscellaneousQueryJetTest.OrderBy_correlated_subquery1(isAsync: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.NorthwindMiscellaneousQueryJetTest.OrderBy_correlated_subquery2(isAsync: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.NorthwindMiscellaneousQueryJetTest.OrderBy_correlated_subquery2(isAsync: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.NorthwindMiscellaneousQueryJetTest.OrderBy_Dto_projection_skip_take(isAsync: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.NorthwindMiscellaneousQueryJetTest.OrderBy_Dto_projection_skip_take(isAsync: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.NorthwindMiscellaneousQueryJetTest.OrderBy_empty_list_contains(isAsync: False)
@ -17115,8 +17121,12 @@ EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_su
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_subquery_boolean(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_subquery_distinct_singleordefault_boolean2(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_subquery_distinct_singleordefault_boolean2(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_subquery_equality_to_null_with_composite_key_should_match_nulls(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_subquery_equality_to_null_with_composite_key_should_match_nulls(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_subquery_equality_to_null_with_composite_key(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_subquery_equality_to_null_with_composite_key(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_subquery_equality_to_null_without_composite_key_should_match_null(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_subquery_equality_to_null_without_composite_key_should_match_null(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_subquery_equality_to_null_without_composite_key(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_subquery_equality_to_null_without_composite_key(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPCGearsOfWarQueryJetTest.Where_TimeOnly_Add_TimeSpan(async: False)
@ -18739,8 +18749,12 @@ EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_su
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_subquery_boolean(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_subquery_distinct_singleordefault_boolean2(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_subquery_distinct_singleordefault_boolean2(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_subquery_equality_to_null_with_composite_key_should_match_nulls(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_subquery_equality_to_null_with_composite_key_should_match_nulls(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_subquery_equality_to_null_with_composite_key(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_subquery_equality_to_null_with_composite_key(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_subquery_equality_to_null_without_composite_key_should_match_null(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_subquery_equality_to_null_without_composite_key_should_match_null(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_subquery_equality_to_null_without_composite_key(async: False)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_subquery_equality_to_null_without_composite_key(async: True)
EntityFrameworkCore.Jet.FunctionalTests.Query.TPTGearsOfWarQueryJetTest.Where_TimeOnly_Add_TimeSpan(async: False)

@ -9352,12 +9352,12 @@ WHERE NOT EXISTS (
AssertSql(
"""
SELECT [s].[Id], [s].[Banner], [s].[Banner5], [s].[InternalNumber], [s].[Name]
FROM [Squads] AS [s]
SELECT `s`.`Id`, `s`.`Banner`, `s`.`Banner5`, `s`.`InternalNumber`, `s`.`Name`
FROM `Squads` AS `s`
WHERE NOT EXISTS (
SELECT 1
FROM [Gears] AS [g]
WHERE [s].[Id] = [g].[SquadId] AND [g].[FullName] = N'Anthony Carmine')
FROM `Gears` AS `g`
WHERE `s`.`Id` = `g`.`SquadId` AND `g`.`FullName` = 'Anthony Carmine')
""");
}
@ -9382,12 +9382,12 @@ WHERE NOT EXISTS (
AssertSql(
"""
SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank]
FROM [Gears] AS [g]
SELECT `g`.`Nickname`, `g`.`SquadId`, `g`.`AssignedCityName`, `g`.`CityOfBirthName`, `g`.`Discriminator`, `g`.`FullName`, `g`.`HasSoulPatch`, `g`.`LeaderNickname`, `g`.`LeaderSquadId`, `g`.`Rank`
FROM `Gears` AS `g`
WHERE NOT EXISTS (
SELECT 1
FROM [Weapons] AS [w]
WHERE [g].[FullName] = [w].[OwnerFullName] AND [w].[Name] = N'Hammer of Dawn')
FROM `Weapons` AS `w`
WHERE `g`.`FullName` = `w`.`OwnerFullName` AND `w`.`Name` = 'Hammer of Dawn')
""");
}

@ -2283,27 +2283,29 @@ ORDER BY NOT (`t`.`c`), `t`.`CustomerID`
await base.OrderBy_correlated_subquery2(isAsync);
AssertSql(
$@"SELECT `o`.`OrderID`, `o`.`CustomerID`, `o`.`EmployeeID`, `o`.`OrderDate`
"""
SELECT `o`.`OrderID`, `o`.`CustomerID`, `o`.`EmployeeID`, `o`.`OrderDate`
FROM `Orders` AS `o`
WHERE (`o`.`OrderID` <= 10250) AND (((
SELECT TOP 1 `c`.`City`
FROM `Customers` AS `c`
ORDER BY CASE
WHEN EXISTS (
SELECT 1
FROM `Customers` AS `c0`
WHERE `c0`.`CustomerID` = 'ALFKI') THEN True
ELSE False
END) <> 'Nowhere') OR (
SELECT TOP 1 `c`.`City`
FROM `Customers` AS `c`
ORDER BY CASE
WHEN EXISTS (
SELECT 1
FROM `Customers` AS `c0`
WHERE `c0`.`CustomerID` = 'ALFKI') THEN True
ELSE False
END) IS NULL)");
WHERE `o`.`OrderID` <= 10250 AND ((
SELECT `t`.`City`
FROM (
SELECT TOP 1 `c`.`City`, IIF(EXISTS (
SELECT 1
FROM `Customers` AS `c1`
WHERE `c1`.`CustomerID` = 'ALFKI'), TRUE, FALSE) AS `c`, `c`.`CustomerID`
FROM `Customers` AS `c`
) AS `t`
ORDER BY NOT (`t`.`c`)) <> 'Nowhere' OR (
SELECT `t`.`City`
FROM (
SELECT TOP 1 `c`.`City`, IIF(EXISTS (
SELECT 1
FROM `Customers` AS `c1`
WHERE `c1`.`CustomerID` = 'ALFKI'), TRUE, FALSE) AS `c`, `c`.`CustomerID`
FROM `Customers` AS `c`
) AS `t`
ORDER BY NOT (`t`.`c`)) IS NULL)
""");
}
public override async Task Where_subquery_recursive_trivial(bool isAsync)

@ -12792,18 +12792,18 @@ WHERE NOT EXISTS (
AssertSql(
"""
SELECT [s].[Id], [s].[Banner], [s].[Banner5], [s].[InternalNumber], [s].[Name]
FROM [Squads] AS [s]
SELECT `s`.`Id`, `s`.`Banner`, `s`.`Banner5`, `s`.`InternalNumber`, `s`.`Name`
FROM `Squads` AS `s`
WHERE NOT EXISTS (
SELECT 1
FROM (
SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], N'Gear' AS [Discriminator]
FROM [Gears] AS [g]
SELECT `g`.`Nickname`, `g`.`SquadId`, `g`.`AssignedCityName`, `g`.`CityOfBirthName`, `g`.`FullName`, `g`.`HasSoulPatch`, `g`.`LeaderNickname`, `g`.`LeaderSquadId`, `g`.`Rank`, 'Gear' AS `Discriminator`
FROM `Gears` AS `g`
UNION ALL
SELECT [o].[Nickname], [o].[SquadId], [o].[AssignedCityName], [o].[CityOfBirthName], [o].[FullName], [o].[HasSoulPatch], [o].[LeaderNickname], [o].[LeaderSquadId], [o].[Rank], N'Officer' AS [Discriminator]
FROM [Officers] AS [o]
) AS [t]
WHERE [s].[Id] = [t].[SquadId] AND [t].[FullName] = N'Anthony Carmine')
SELECT `o`.`Nickname`, `o`.`SquadId`, `o`.`AssignedCityName`, `o`.`CityOfBirthName`, `o`.`FullName`, `o`.`HasSoulPatch`, `o`.`LeaderNickname`, `o`.`LeaderSquadId`, `o`.`Rank`, 'Officer' AS `Discriminator`
FROM `Officers` AS `o`
) AS `t`
WHERE `s`.`Id` = `t`.`SquadId` AND `t`.`FullName` = 'Anthony Carmine')
""");
}
@ -12834,18 +12834,18 @@ WHERE NOT EXISTS (
AssertSql(
"""
SELECT [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOfBirthName], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank], [t].[Discriminator]
SELECT `t`.`Nickname`, `t`.`SquadId`, `t`.`AssignedCityName`, `t`.`CityOfBirthName`, `t`.`FullName`, `t`.`HasSoulPatch`, `t`.`LeaderNickname`, `t`.`LeaderSquadId`, `t`.`Rank`, `t`.`Discriminator`
FROM (
SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], N'Gear' AS [Discriminator]
FROM [Gears] AS [g]
SELECT `g`.`Nickname`, `g`.`SquadId`, `g`.`AssignedCityName`, `g`.`CityOfBirthName`, `g`.`FullName`, `g`.`HasSoulPatch`, `g`.`LeaderNickname`, `g`.`LeaderSquadId`, `g`.`Rank`, 'Gear' AS `Discriminator`
FROM `Gears` AS `g`
UNION ALL
SELECT [o].[Nickname], [o].[SquadId], [o].[AssignedCityName], [o].[CityOfBirthName], [o].[FullName], [o].[HasSoulPatch], [o].[LeaderNickname], [o].[LeaderSquadId], [o].[Rank], N'Officer' AS [Discriminator]
FROM [Officers] AS [o]
) AS [t]
SELECT `o`.`Nickname`, `o`.`SquadId`, `o`.`AssignedCityName`, `o`.`CityOfBirthName`, `o`.`FullName`, `o`.`HasSoulPatch`, `o`.`LeaderNickname`, `o`.`LeaderSquadId`, `o`.`Rank`, 'Officer' AS `Discriminator`
FROM `Officers` AS `o`
) AS `t`
WHERE NOT EXISTS (
SELECT 1
FROM [Weapons] AS [w]
WHERE [t].[FullName] = [w].[OwnerFullName] AND [w].[Name] = N'Hammer of Dawn')
FROM `Weapons` AS `w`
WHERE `t`.`FullName` = `w`.`OwnerFullName` AND `w`.`Name` = 'Hammer of Dawn')
""");
}

@ -10403,13 +10403,13 @@ WHERE NOT EXISTS (
AssertSql(
"""
SELECT [s].[Id], [s].[Banner], [s].[Banner5], [s].[InternalNumber], [s].[Name]
FROM [Squads] AS [s]
SELECT `s`.`Id`, `s`.`Banner`, `s`.`Banner5`, `s`.`InternalNumber`, `s`.`Name`
FROM `Squads` AS `s`
WHERE NOT EXISTS (
SELECT 1
FROM [Gears] AS [g]
LEFT JOIN [Officers] AS [o] ON [g].[Nickname] = [o].[Nickname] AND [g].[SquadId] = [o].[SquadId]
WHERE [s].[Id] = [g].[SquadId] AND [g].[FullName] = N'Anthony Carmine')
FROM `Gears` AS `g`
LEFT JOIN `Officers` AS `o` ON `g`.`Nickname` = `o`.`Nickname` AND `g`.`SquadId` = `o`.`SquadId`
WHERE `s`.`Id` = `g`.`SquadId` AND `g`.`FullName` = 'Anthony Carmine')
""");
}
@ -10435,15 +10435,13 @@ WHERE NOT EXISTS (
AssertSql(
"""
SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], CASE
WHEN [o].[Nickname] IS NOT NULL THEN N'Officer'
END AS [Discriminator]
FROM [Gears] AS [g]
LEFT JOIN [Officers] AS [o] ON [g].[Nickname] = [o].[Nickname] AND [g].[SquadId] = [o].[SquadId]
SELECT `g`.`Nickname`, `g`.`SquadId`, `g`.`AssignedCityName`, `g`.`CityOfBirthName`, `g`.`FullName`, `g`.`HasSoulPatch`, `g`.`LeaderNickname`, `g`.`LeaderSquadId`, `g`.`Rank`, IIF(`o`.`Nickname` IS NOT NULL, 'Officer', NULL) AS `Discriminator`
FROM `Gears` AS `g`
LEFT JOIN `Officers` AS `o` ON `g`.`Nickname` = `o`.`Nickname` AND `g`.`SquadId` = `o`.`SquadId`
WHERE NOT EXISTS (
SELECT 1
FROM [Weapons] AS [w]
WHERE [g].[FullName] = [w].[OwnerFullName] AND [w].[Name] = N'Hammer of Dawn')
FROM `Weapons` AS `w`
WHERE `g`.`FullName` = `w`.`OwnerFullName` AND `w`.`Name` = 'Hammer of Dawn')
""");
}

Loading…
Cancel
Save