From a9c2f36da5e2d04e326da0accda1d941be97cee1 Mon Sep 17 00:00:00 2001 From: Christopher Jolly Date: Sun, 2 Jul 2023 15:46:17 +0800 Subject: [PATCH] Jet conversion functions like Cdbl/Csng/CLng don't accept or propogate null values. Normally we can just use an IIF to check if the expression is null or not. That does work fine but here we also check if the base expression is nullable. If the base expression will never return null we can simplify and just use the base expression rather than test for null --- .../Sql/Internal/JetQuerySqlGenerator.cs | 56 ++++++++++++++++++- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/src/EFCore.Jet/Query/Sql/Internal/JetQuerySqlGenerator.cs b/src/EFCore.Jet/Query/Sql/Internal/JetQuerySqlGenerator.cs index d85c132..8b6eb56 100644 --- a/src/EFCore.Jet/Query/Sql/Internal/JetQuerySqlGenerator.cs +++ b/src/EFCore.Jet/Query/Sql/Internal/JetQuerySqlGenerator.cs @@ -340,7 +340,7 @@ namespace EntityFrameworkCore.Jet.Query.Sql.Internal SqlExpression checksqlexp = convertExpression.Operand; SqlFunctionExpression notnullsqlexp = new SqlFunctionExpression(function, new SqlExpression[] { convertExpression.Operand }, - true, new[] { true }, typeMapping.ClrType, null); + false, new[] { false }, typeMapping.ClrType, null); SqlConstantExpression nullcons = new SqlConstantExpression(Expression.Constant(null), RelationalTypeMapping.NullMapping); SqlUnaryExpression isnullexp = new SqlUnaryExpression(ExpressionType.Equal, checksqlexp, typeof(bool), null); @@ -349,8 +349,58 @@ namespace EntityFrameworkCore.Jet.Query.Sql.Internal new CaseWhenClause(isnullexp, nullcons) }; CaseExpression caseexp = new CaseExpression(whenclause, notnullsqlexp); - //Visit(caseexp); - Visit(notnullsqlexp); + if (checksqlexp is ColumnExpression columnExpression) + { + if (columnExpression.IsNullable) + { + Visit(caseexp); + } + else + { + Visit(notnullsqlexp); + } + } + else if (checksqlexp is SqlFunctionExpression functionExpression) + { + if (functionExpression is { IsNullable: true, ArgumentsPropagateNullability: not null } && functionExpression.ArgumentsPropagateNullability.Any(d => d)) + { + Visit(caseexp); + } + else + { + Visit(notnullsqlexp); + } + } + else if (checksqlexp is SqlBinaryExpression binaryExpression) + { + bool leftnull = false, rightnull = false; + ColumnExpression? columnExpressionLeft = binaryExpression.Left as ColumnExpression; + SqlFunctionExpression? functionExpressionLeft = binaryExpression.Left as SqlFunctionExpression; + ColumnExpression? columnExpressionRight = binaryExpression.Right as ColumnExpression; + SqlFunctionExpression? functionExpressionRight = binaryExpression.Right as SqlFunctionExpression; + leftnull = columnExpressionLeft != null && columnExpressionLeft.IsNullable || + functionExpressionLeft != null && functionExpressionLeft.IsNullable; + rightnull = columnExpressionRight != null && columnExpressionRight.IsNullable || + functionExpressionRight != null && functionExpressionRight.IsNullable; + + if (leftnull || rightnull) + { + Visit(caseexp); + } + else + { + Visit(notnullsqlexp); + } + } + else if (checksqlexp is SqlUnaryExpression unaryExpression) + { + Visit(notnullsqlexp); + } + else + { + Visit(caseexp); + } + return notnullsqlexp; }