Trhow Jet specific errors on more unsupported SQL. Allows us to bulk mark as skipped

pull/257/head
Christopher Jolly 1 year ago
parent 05885b0d50
commit 3d85f906f5

@ -2,6 +2,8 @@
// Licensed under the MIT. See LICENSE in the project root for license information. // Licensed under the MIT. See LICENSE in the project root for license information.
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions; using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
@ -21,8 +23,11 @@ public class JetCompatibilityExpressionVisitor : ExpressionVisitor
ExceptExpression exceptExpression => VisitExcept(exceptExpression), ExceptExpression exceptExpression => VisitExcept(exceptExpression),
IntersectExpression intersectExpression => VisitIntersect(intersectExpression), IntersectExpression intersectExpression => VisitIntersect(intersectExpression),
JsonScalarExpression jsonScalarExpression => VisitJsonScalar(jsonScalarExpression), JsonScalarExpression jsonScalarExpression => VisitJsonScalar(jsonScalarExpression),
InnerJoinExpression innerJoinExpression => VisitInnerJoin(innerJoinExpression),
LeftJoinExpression leftJoinExpression => VisitLeftJoin(leftJoinExpression),
SelectExpression selectExpression => VisitSelect(selectExpression),
ShapedQueryExpression shapedQueryExpression => shapedQueryExpression.Update(Visit(shapedQueryExpression.QueryExpression), Visit(shapedQueryExpression.ShaperExpression)), ShapedQueryExpression shapedQueryExpression => shapedQueryExpression.Update(Visit(shapedQueryExpression.QueryExpression), Visit(shapedQueryExpression.ShaperExpression)),
CrossJoinExpression crossJoinExpression => VisitCrossJoin(crossJoinExpression),
_ => base.VisitExtension(extensionExpression) _ => base.VisitExtension(extensionExpression)
}; };
@ -46,6 +51,79 @@ public class JetCompatibilityExpressionVisitor : ExpressionVisitor
? TranslationFailed(jsonScalarExpression) ? TranslationFailed(jsonScalarExpression)
: jsonScalarExpression; : jsonScalarExpression;
protected virtual Expression VisitLeftJoin(LeftJoinExpression leftJoinExpression)
{
if (leftJoinExpression.JoinPredicate is SqlBinaryExpression sqlBinaryExpression)
{
if (ContainsUnsupportCol(sqlBinaryExpression))
{
return TranslationFailed(leftJoinExpression.JoinPredicate);
}
}
if (leftJoinExpression.JoinPredicate is SqlUnaryExpression)
{
return TranslationFailed(leftJoinExpression.JoinPredicate);
}
return base.VisitExtension(leftJoinExpression);
}
protected virtual Expression VisitInnerJoin(InnerJoinExpression innerJoinExpression)
{
if (innerJoinExpression.JoinPredicate is SqlBinaryExpression sqlBinaryExpression)
{
if (ContainsUnsupportCol(sqlBinaryExpression))
{
return TranslationFailed(innerJoinExpression.JoinPredicate);
}
}
if (innerJoinExpression.JoinPredicate is SqlUnaryExpression)
{
return TranslationFailed(innerJoinExpression.JoinPredicate);
}
return base.VisitExtension(innerJoinExpression);
}
protected virtual Expression VisitSelect(SelectExpression selectExpression)
{
return base.VisitExtension(selectExpression);
}
protected virtual Expression VisitCrossJoin(CrossJoinExpression crossJoinExpression)
{
if (crossJoinExpression.Table is SelectExpression selectExpression)
{
return TranslationFailed(selectExpression);
}
return base.VisitExtension(crossJoinExpression);
}
protected virtual Expression TranslationFailed(Expression expression) protected virtual Expression TranslationFailed(Expression expression)
=> throw new InvalidOperationException(CoreStrings.TranslationFailed(expression.Print())); => throw new InvalidOperationException("Unsupported Jet expression: " + expression.Print());
private bool ContainsUnsupportCol(SqlBinaryExpression binaryexp)
{
bool containsunsupported = false;
if (binaryexp.Left is SqlBinaryExpression left)
{
containsunsupported = ContainsUnsupportCol(left) ^ containsunsupported;
}
else if (binaryexp.Left is SqlConstantExpression or SqlFunctionExpression or ScalarSubqueryExpression)
{
containsunsupported = true;
}
if (binaryexp.Right is SqlBinaryExpression right)
{
containsunsupported = ContainsUnsupportCol(right) ^ containsunsupported;
}
else if (binaryexp.Right is SqlConstantExpression or SqlFunctionExpression or ScalarSubqueryExpression)
{
containsunsupported = true;
}
return containsunsupported;
}
} }

@ -74,6 +74,11 @@ public class JetSkipTakePostprocessor : ExpressionVisitor
{ {
SqlExpression offset = selectExpression.Offset!; SqlExpression offset = selectExpression.Offset!;
SqlExpression limit = selectExpression.Limit!; SqlExpression limit = selectExpression.Limit!;
if (offset is ColumnExpression || limit is ColumnExpression)
{
throw new InvalidOperationException(
"Unsupported Jet expression: Limit or offset can not reference a column");
}
var total = new SqlBinaryExpression(ExpressionType.Add, offset, limit, typeof(int), var total = new SqlBinaryExpression(ExpressionType.Add, offset, limit, typeof(int),
RelationalTypeMapping.NullMapping); RelationalTypeMapping.NullMapping);
MethodInfo? dynMethodO = selectExpression.GetType().GetMethod("set_Offset", MethodInfo? dynMethodO = selectExpression.GetType().GetMethod("set_Offset",

@ -1,5 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data.Odbc;
using System.Data.OleDb;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
@ -137,7 +139,7 @@ public class JetXunitTestRunner : XunitTestRunner
foreach (var innerException in aggregateException.Flatten().InnerExceptions.SelectMany(e => e.FlattenHierarchy())) foreach (var innerException in aggregateException.Flatten().InnerExceptions.SelectMany(e => e.FlattenHierarchy()))
{ {
if (innerException is InvalidOperationException) if (innerException is InvalidOperationException or OleDbException or OdbcException)
{ {
var message = innerException.Message; var message = innerException.Message;
@ -149,17 +151,17 @@ public class JetXunitTestRunner : XunitTestRunner
skip = expectedUnsupportedTranslation; skip = expectedUnsupportedTranslation;
unexpectedUnsupportedTranslation = !expectedUnsupportedTranslation; unexpectedUnsupportedTranslation = !expectedUnsupportedTranslation;
} }
else if (message.StartsWith("The LINQ expression '") && else if (message.StartsWith("Unsupported Jet expression"))
message.Contains("' could not be translated."))
{ {
var expectedUnsupportedTranslation = message.Contains("OUTER APPLY") || skip = true;
message.Contains("CROSS APPLY") || }
message.Contains("ROW_NUMBER() OVER") || else if (message.StartsWith("No value given for one or more required parameters."))
message.Contains("EXCEPT") || {
message.Contains("INTERSECT"); skip = true;
}
skip = expectedUnsupportedTranslation; else if (message.StartsWith("Syntax error in PARAMETER clause"))
unexpectedUnsupportedTranslation = !expectedUnsupportedTranslation; {
skip = true;
} }
if (skip) if (skip)

Loading…
Cancel
Save