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
pull/144/head
Christopher Jolly 2 years ago
parent cae7f8372b
commit 5b591b73fd

@ -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
@ -315,9 +317,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)
@ -411,8 +434,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 void GenerateIn(InExpression inExpression, bool negated)

Loading…
Cancel
Save