Auto skip statements that are not supported by Jet. Track unsupported statements in log files. (#169)

pull/171/head
Laurents Meyer 2 years ago committed by GitHub
parent 79a0f1b679
commit a95017e38b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,51 @@
// Copyright (c) Pomelo Foundation. All rights reserved.
// Licensed under the MIT. See LICENSE in the project root for license information.
using System;
using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
namespace EntityFrameworkCore.Jet.Query.Internal;
public class JetCompatibilityExpressionVisitor : ExpressionVisitor
{
protected override Expression VisitExtension(Expression extensionExpression)
=> extensionExpression switch
{
RowNumberExpression rowNumberExpression => VisitRowNumber(rowNumberExpression),
CrossApplyExpression crossApplyExpression => VisitCrossApply(crossApplyExpression),
OuterApplyExpression outerApplyExpression => VisitOuterApply(outerApplyExpression),
ExceptExpression exceptExpression => VisitExcept(exceptExpression),
IntersectExpression intersectExpression => VisitIntersect(intersectExpression),
JsonScalarExpression jsonScalarExpression => VisitJsonScalar(jsonScalarExpression),
ShapedQueryExpression shapedQueryExpression => shapedQueryExpression.Update(Visit(shapedQueryExpression.QueryExpression), Visit(shapedQueryExpression.ShaperExpression)),
_ => base.VisitExtension(extensionExpression)
};
protected virtual Expression VisitRowNumber(RowNumberExpression rowNumberExpression)
=> TranslationFailed(rowNumberExpression);
protected virtual Expression VisitCrossApply(CrossApplyExpression crossApplyExpression)
=> TranslationFailed(crossApplyExpression);
protected virtual Expression VisitOuterApply(OuterApplyExpression outerApplyExpression)
=> TranslationFailed(outerApplyExpression);
protected virtual Expression VisitExcept(ExceptExpression exceptExpression)
=> TranslationFailed(exceptExpression);
protected virtual Expression VisitIntersect(IntersectExpression intersectExpression)
=> TranslationFailed(intersectExpression);
protected virtual Expression VisitJsonScalar(JsonScalarExpression jsonScalarExpression)
=> jsonScalarExpression.Path.Count > 0
? TranslationFailed(jsonScalarExpression)
: jsonScalarExpression;
protected virtual Expression TranslationFailed(Expression expression)
=> throw new InvalidOperationException(CoreStrings.TranslationFailed(expression.Print()));
}

@ -3,7 +3,6 @@
using System.Collections.Generic;
using System.Linq.Expressions;
using EntityFrameworkCore.Jet.Query.Internal;
using EntityFrameworkCore.Jet.Utilities;
using Microsoft.EntityFrameworkCore.Query;
@ -41,14 +40,19 @@ public class JetParameterBasedSqlProcessor : RelationalParameterBasedSqlProcesso
IReadOnlyDictionary<string, object?> parametersValues,
out bool canCache)
{
var optimizedQueryExpression = base.Optimize(queryExpression, parametersValues, out canCache);
queryExpression = base.Optimize(queryExpression, parametersValues, out canCache);
/*optimizedQueryExpression = new SkipTakeCollapsingExpressionVisitor(Dependencies.SqlExpressionFactory)
.Process(optimizedQueryExpression, parametersValues, out var canCache2);*/
//canCache &= canCache2;
return new SearchConditionConvertingExpressionVisitor(Dependencies.SqlExpressionFactory).Visit(optimizedQueryExpression);
queryExpression = new SearchConditionConvertingExpressionVisitor(Dependencies.SqlExpressionFactory).Visit(queryExpression);
// Run the compatibility checks as late in the query pipeline (before the actual SQL translation happens) as reasonable.
queryExpression = new JetCompatibilityExpressionVisitor().Visit(queryExpression);
return queryExpression;
}
/// <inheritdoc />

@ -19,8 +19,7 @@ public class JetParameterBasedSqlProcessorFactory : IRelationalParameterBasedSql
/// 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 JetParameterBasedSqlProcessorFactory(
RelationalParameterBasedSqlProcessorDependencies dependencies)
public JetParameterBasedSqlProcessorFactory(RelationalParameterBasedSqlProcessorDependencies dependencies)
{
Dependencies = dependencies;
}

@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using EntityFrameworkCore.Jet.Data;
using System.Linq;
@ -141,8 +142,7 @@ namespace EntityFrameworkCore.Jet.Query.Sql.Internal
if (isApplyExpression)
{
throw new InvalidOperationException(
"Jet does not support APPLY statements. Switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync() if needed.");
throw new UnreachableException();
}
if (index > 0)
@ -379,7 +379,8 @@ namespace EntityFrameworkCore.Jet.Query.Sql.Internal
Visit(jsonScalarExpression.Json);
return jsonScalarExpression;
}
return base.VisitJsonScalar(jsonScalarExpression);
throw new UnreachableException();
}
private bool IsNonComposedSetOperation(SelectExpression selectExpression)
@ -826,6 +827,6 @@ namespace EntityFrameworkCore.Jet.Query.Sql.Internal
}
protected override Expression VisitRowNumber(RowNumberExpression rowNumberExpression)
=> throw new InvalidOperationException(CoreStrings.TranslationFailed(rowNumberExpression));
=> throw new UnreachableException();
}
}

@ -152,7 +152,11 @@ public class JetXunitTestRunner : XunitTestRunner
else if (message.StartsWith("The LINQ expression '") &&
message.Contains("' could not be translated."))
{
var expectedUnsupportedTranslation = message.Contains("RowNumberExpression");
var expectedUnsupportedTranslation = message.Contains("OUTER APPLY") ||
message.Contains("CROSS APPLY") ||
message.Contains("ROW_NUMBER() OVER") ||
message.Contains("EXCEPT") ||
message.Contains("INTERSECT");
skip = expectedUnsupportedTranslation;
unexpectedUnsupportedTranslation = !expectedUnsupportedTranslation;
@ -160,22 +164,22 @@ public class JetXunitTestRunner : XunitTestRunner
if (skip)
{
// var sb = new StringBuilder();
// sb.AppendLine(message.ReplaceLineEndings(" "));
// sb.AppendLine("-----");
//
// File.AppendAllText("ExpectedUnsupportedTranslations.txt", sb.ToString());
var sb = new StringBuilder();
sb.AppendLine(message.ReplaceLineEndings(" "));
sb.AppendLine("-----");
File.AppendAllText("ExpectedUnsupportedTranslations.txt", sb.ToString());
break;
}
if (unexpectedUnsupportedTranslation)
{
// var sb = new StringBuilder();
// sb.AppendLine(message.ReplaceLineEndings(" "));
// sb.AppendLine("-----");
//
// File.AppendAllText("UnsupportedTranslations.txt", sb.ToString());
var sb = new StringBuilder();
sb.AppendLine(message.ReplaceLineEndings(" "));
sb.AppendLine("-----");
File.AppendAllText("UnexpectedUnsupportedTranslations.txt", sb.ToString());
}
}
}

Loading…
Cancel
Save