UNIONing projection with a numeric column to another projection that specifically projects NULL the the same name as a numeric field, the JOINING that to another table can leave that numeric field as another data type (NULL is not a numeric data type). Hence when using that supposedly numeric field in the join predicat against another numeric field we get a data type mismatch.

We try to detect this and when visiting the column (but only if we are within a binary expression and not a projection) we quickly wrap it in a convert function to make it properly numeric

The top/outer projection of this field can still be in a non numeric format, but JetDataReader is able to handle that. Would be better to produce the correctly converted data output anyway
7.0-servicing
Christopher Jolly 2 years ago
parent 574cdac15f
commit e04ee43a29

@ -46,6 +46,8 @@ namespace EntityFrameworkCore.Jet.Query.Sql.Internal
private readonly ISqlGenerationHelper _sqlGenerationHelper;
//private readonly JetSqlExpressionFactory _sqlExpressionFactory;
private List<string> _nullNumerics = new List<string>();
private Stack<Expression> parent = new Stack<Expression>();
private CoreTypeMapping? _boolTypeMapping;
/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
@ -319,9 +321,30 @@ namespace EntityFrameworkCore.Jet.Query.Sql.Internal
return result;
}
protected override Expression VisitInnerJoin(InnerJoinExpression innerJoinExpression)
protected override Expression VisitProjection(ProjectionExpression projectionExpression)
{
return base.VisitInnerJoin(innerJoinExpression);
if (projectionExpression.Expression is SqlConstantExpression { Value: null } constantExpression && (constantExpression.Type == typeof(int) || constantExpression.Type == typeof(double) || constantExpression.Type == typeof(float) || constantExpression.Type == typeof(decimal) || constantExpression.Type == typeof(short)))
{
_nullNumerics.Add(projectionExpression.Alias);
}
return base.VisitProjection(projectionExpression);
}
protected override Expression VisitColumn(ColumnExpression columnExpression)
{
if (columnExpression.IsNullable && _nullNumerics.Contains(columnExpression.Name) && _convertMappings.TryGetValue(columnExpression.Type.Name, out var function))
{
if (parent.TryPeek(out var exp) && exp is SqlBinaryExpression)
{
Sql.Append(function);
Sql.Append("(");
base.VisitColumn(columnExpression);
Sql.Append(")");
return columnExpression;
}
}
return base.VisitColumn(columnExpression);
}
private bool IsNonComposedSetOperation(SelectExpression selectExpression)
@ -415,8 +438,10 @@ namespace EntityFrameworkCore.Jet.Query.Sql.Internal
Visit(caseexp);
return sqlBinaryExpression;
}
return base.VisitSqlBinary(sqlBinaryExpression);
parent.Push(sqlBinaryExpression);
var res = base.VisitSqlBinary(sqlBinaryExpression);
parent.Pop();
return res;
}
protected override Expression VisitIn(InExpression inExpression)

Loading…
Cancel
Save