diff --git a/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetStringMethodTranslator.cs b/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetStringMethodTranslator.cs index 0232255..e9d48e9 100644 --- a/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetStringMethodTranslator.cs +++ b/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetStringMethodTranslator.cs @@ -239,18 +239,29 @@ namespace EntityFrameworkCore.Jet.Query.ExpressionTranslators.Internal if (_lastOrDefaultMethodInfoWithoutArgs.Equals(method)) { var argument = arguments[0]; + var lenfunction = _sqlExpressionFactory.Function( + "LEN", + new[] { argument }, + nullable: true, + argumentsPropagateNullability: new[] { true }, + typeof(int)); + var casefunc = _sqlExpressionFactory.Case( + new[] + { + new CaseWhenClause( + _sqlExpressionFactory.Equal( + lenfunction, + _sqlExpressionFactory.Constant(0)), + _sqlExpressionFactory.Constant(1)) + }, + lenfunction); return _sqlExpressionFactory.Function( "MID", new[] { argument, _sqlExpressionFactory.Coalesce( - _sqlExpressionFactory.Function( - "LEN", - new[] { argument }, - nullable: true, - argumentsPropagateNullability: new[] { true }, - typeof(int)), + casefunc, _sqlExpressionFactory.Constant(0) ), _sqlExpressionFactory.Constant(1) diff --git a/src/EFCore.Jet/Query/Internal/JetSqlTranslatingExpressionVisitor.cs b/src/EFCore.Jet/Query/Internal/JetSqlTranslatingExpressionVisitor.cs index eb57aa0..e9d9636 100644 --- a/src/EFCore.Jet/Query/Internal/JetSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Jet/Query/Internal/JetSqlTranslatingExpressionVisitor.cs @@ -334,7 +334,7 @@ public class JetSqlTranslatingExpressionVisitor : RelationalSqlTranslatingExpres _sqlExpressionFactory.GreaterThan( _sqlExpressionFactory.Function( "INSTR", - new[] { _sqlExpressionFactory.Constant(1), translatedPattern, translatedInstance, _sqlExpressionFactory.Constant(1) }, + new[] { _sqlExpressionFactory.Constant(1), translatedInstance, translatedPattern, _sqlExpressionFactory.Constant(1) }, nullable: true, argumentsPropagateNullability: new[] { false, true, true, false }, typeof(int)), diff --git a/test/EFCore.Jet.FunctionalTests/GreenTests/ace_2010_odbc_x86.txt b/test/EFCore.Jet.FunctionalTests/GreenTests/ace_2010_odbc_x86.txt index f96382c..fa2c0b2 100644 --- a/test/EFCore.Jet.FunctionalTests/GreenTests/ace_2010_odbc_x86.txt +++ b/test/EFCore.Jet.FunctionalTests/GreenTests/ace_2010_odbc_x86.txt @@ -7973,6 +7973,10 @@ EntityFrameworkCore.Jet.FunctionalTests.Query.FromSqlSprocQueryJetTest.From_sql_ EntityFrameworkCore.Jet.FunctionalTests.Query.FromSqlSprocQueryJetTest.From_sql_queryable_with_multiple_stored_procedures_on_client(async: True) EntityFrameworkCore.Jet.FunctionalTests.Query.FromSqlSprocQueryJetTest.From_sql_queryable_with_multiple_stored_procedures(async: False) EntityFrameworkCore.Jet.FunctionalTests.Query.FromSqlSprocQueryJetTest.From_sql_queryable_with_multiple_stored_procedures(async: True) +EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_contains_on_argument_with_wildcard_column_negated(isAsync: False) +EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_contains_on_argument_with_wildcard_column_negated(isAsync: True) +EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_contains_on_argument_with_wildcard_column(isAsync: False) +EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_contains_on_argument_with_wildcard_column(isAsync: True) EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_contains_on_argument_with_wildcard_constant(isAsync: False) EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_contains_on_argument_with_wildcard_constant(isAsync: True) EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_ends_with_equals_nullable_column(isAsync: False) @@ -7989,6 +7993,8 @@ EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_ends_ EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_ends_with_on_argument_with_wildcard_column(isAsync: True) EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_ends_with_on_argument_with_wildcard_constant(isAsync: False) EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_ends_with_on_argument_with_wildcard_constant(isAsync: True) +EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_FirstOrDefault_and_LastOrDefault(async: False) +EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_FirstOrDefault_and_LastOrDefault(async: True) EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_starts_with_on_argument_with_wildcard_column_negated(isAsync: False) EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_starts_with_on_argument_with_wildcard_column_negated(isAsync: True) EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_starts_with_on_argument_with_wildcard_column(isAsync: False) diff --git a/test/EFCore.Jet.FunctionalTests/GreenTests/ace_2010_oledb_x86.txt b/test/EFCore.Jet.FunctionalTests/GreenTests/ace_2010_oledb_x86.txt index cdd00bd..55453cc 100644 --- a/test/EFCore.Jet.FunctionalTests/GreenTests/ace_2010_oledb_x86.txt +++ b/test/EFCore.Jet.FunctionalTests/GreenTests/ace_2010_oledb_x86.txt @@ -9412,6 +9412,10 @@ EntityFrameworkCore.Jet.FunctionalTests.Query.FromSqlSprocQueryJetTest.From_sql_ EntityFrameworkCore.Jet.FunctionalTests.Query.FromSqlSprocQueryJetTest.From_sql_queryable_with_multiple_stored_procedures_on_client(async: True) EntityFrameworkCore.Jet.FunctionalTests.Query.FromSqlSprocQueryJetTest.From_sql_queryable_with_multiple_stored_procedures(async: False) EntityFrameworkCore.Jet.FunctionalTests.Query.FromSqlSprocQueryJetTest.From_sql_queryable_with_multiple_stored_procedures(async: True) +EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_contains_on_argument_with_wildcard_column_negated(isAsync: False) +EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_contains_on_argument_with_wildcard_column_negated(isAsync: True) +EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_contains_on_argument_with_wildcard_column(isAsync: False) +EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_contains_on_argument_with_wildcard_column(isAsync: True) EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_contains_on_argument_with_wildcard_constant(isAsync: False) EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_contains_on_argument_with_wildcard_constant(isAsync: True) EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_contains_on_argument_with_wildcard_parameter(isAsync: False) @@ -9432,6 +9436,8 @@ EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_ends_ EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_ends_with_on_argument_with_wildcard_constant(isAsync: True) EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_ends_with_on_argument_with_wildcard_parameter(isAsync: False) EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_ends_with_on_argument_with_wildcard_parameter(isAsync: True) +EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_FirstOrDefault_and_LastOrDefault(async: False) +EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_FirstOrDefault_and_LastOrDefault(async: True) EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_starts_with_on_argument_with_bracket(isAsync: False) EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_starts_with_on_argument_with_bracket(isAsync: True) EntityFrameworkCore.Jet.FunctionalTests.Query.FunkyDataQueryJetTest.String_starts_with_on_argument_with_wildcard_column_negated(isAsync: False) diff --git a/test/EFCore.Jet.FunctionalTests/Query/FunkyDataQueryJetTest.cs b/test/EFCore.Jet.FunctionalTests/Query/FunkyDataQueryJetTest.cs index a24ac30..5bfe64d 100644 --- a/test/EFCore.Jet.FunctionalTests/Query/FunkyDataQueryJetTest.cs +++ b/test/EFCore.Jet.FunctionalTests/Query/FunkyDataQueryJetTest.cs @@ -140,10 +140,12 @@ FROM `FunkyCustomers` AS `f` await base.String_contains_on_argument_with_wildcard_column(isAsync); AssertSql( - $@"SELECT `f`.`FirstName` AS `fn`, `f0`.`LastName` AS `ln` + """ +SELECT `f`.`FirstName` AS `fn`, `f0`.`LastName` AS `ln` FROM `FunkyCustomers` AS `f`, `FunkyCustomers` AS `f0` -WHERE (`f0`.`LastName` LIKE '') OR INSTR(1, `f`.`FirstName`, `f0`.`LastName`, 1) > 0"); +WHERE `f`.`FirstName` IS NOT NULL AND `f0`.`LastName` IS NOT NULL AND (INSTR(1, `f`.`FirstName`, `f0`.`LastName`, 1) > 0 OR (`f0`.`LastName` LIKE '')) +"""); } public override async Task String_contains_on_argument_with_wildcard_column_negated(bool isAsync) @@ -151,10 +153,12 @@ WHERE (`f0`.`LastName` LIKE '') OR INSTR(1, `f`.`FirstName`, `f0`.`LastName`, 1) await base.String_contains_on_argument_with_wildcard_column_negated(isAsync); AssertSql( - $@"SELECT `f`.`FirstName` AS `fn`, `f0`.`LastName` AS `ln` + """ +SELECT `f`.`FirstName` AS `fn`, `f0`.`LastName` AS `ln` FROM `FunkyCustomers` AS `f`, `FunkyCustomers` AS `f0` -WHERE NOT ((`f0`.`LastName` LIKE '') OR INSTR(1, `f`.`FirstName`, `f0`.`LastName`, 1) > 0)"); +WHERE NOT (`f`.`FirstName` IS NOT NULL AND `f0`.`LastName` IS NOT NULL AND (INSTR(1, `f`.`FirstName`, `f0`.`LastName`, 1) > 0 OR (`f0`.`LastName` LIKE ''))) +"""); } public override async Task String_starts_with_on_argument_with_wildcard_constant(bool isAsync) diff --git a/test/EFCore.Jet.FunctionalTests/Query/NorthwindFunctionsQueryJetTest.Functions.cs b/test/EFCore.Jet.FunctionalTests/Query/NorthwindFunctionsQueryJetTest.Functions.cs index 04e2151..1007704 100644 --- a/test/EFCore.Jet.FunctionalTests/Query/NorthwindFunctionsQueryJetTest.Functions.cs +++ b/test/EFCore.Jet.FunctionalTests/Query/NorthwindFunctionsQueryJetTest.Functions.cs @@ -294,7 +294,7 @@ WHERE MID(`c`.`ContactName`, 1, 1) = 'A' """ SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region` FROM `Customers` AS `c` -WHERE MID(`c`.`ContactName`, IIF(LEN(`c`.`ContactName`) IS NULL, 0, LEN(`c`.`ContactName`)), 1) = 's' +WHERE MID(`c`.`ContactName`, IIF(IIF(LEN(`c`.`ContactName`) = 0, 1, LEN(`c`.`ContactName`)) IS NULL, 0, IIF(LEN(`c`.`ContactName`) = 0, 1, LEN(`c`.`ContactName`))), 1) = 's' """); } diff --git a/test/EFCore.Jet.FunctionalTests/Query/NullSemanticsQueryJetTest.cs b/test/EFCore.Jet.FunctionalTests/Query/NullSemanticsQueryJetTest.cs index 5aa2e34..e49c206 100644 --- a/test/EFCore.Jet.FunctionalTests/Query/NullSemanticsQueryJetTest.cs +++ b/test/EFCore.Jet.FunctionalTests/Query/NullSemanticsQueryJetTest.cs @@ -1031,7 +1031,7 @@ WHERE `e`.`NullableStringC` <> IIF(`e`.`NullableStringA` = `e`.`NullableStringB` """ SELECT `e`.`Id` FROM `Entities1` AS `e` -WHERE `e`.`NullableStringA` IS NOT NULL AND `e`.`NullableStringB` IS NOT NULL AND (INSTR(1, `e`.`NullableStringB`, `e`.`NullableStringA`, 1) > 0 OR (`e`.`NullableStringB` LIKE '')) AND `e`.`BoolA` = TRUE +WHERE `e`.`NullableStringA` IS NOT NULL AND `e`.`NullableStringB` IS NOT NULL AND (INSTR(1, `e`.`NullableStringA`, `e`.`NullableStringB`, 1) > 0 OR (`e`.`NullableStringB` LIKE '')) AND `e`.`BoolA` = TRUE """); } @@ -1808,10 +1808,10 @@ FROM `Entities1` AS `e` await base.Nullable_string_FirstOrDefault_compared_to_nullable_string_LastOrDefault(async); AssertSql( - """ + """ SELECT `e`.`Id`, `e`.`BoolA`, `e`.`BoolB`, `e`.`BoolC`, `e`.`IntA`, `e`.`IntB`, `e`.`IntC`, `e`.`NullableBoolA`, `e`.`NullableBoolB`, `e`.`NullableBoolC`, `e`.`NullableIntA`, `e`.`NullableIntB`, `e`.`NullableIntC`, `e`.`NullableStringA`, `e`.`NullableStringB`, `e`.`NullableStringC`, `e`.`StringA`, `e`.`StringB`, `e`.`StringC` FROM `Entities1` AS `e` -WHERE MID(`e`.`NullableStringA`, 1, 1) = MID(`e`.`NullableStringB`, IIF(LEN(`e`.`NullableStringB`) IS NULL, 0, LEN(`e`.`NullableStringB`)), 1) OR (`e`.`NullableStringA` IS NULL AND `e`.`NullableStringB` IS NULL) +WHERE MID(`e`.`NullableStringA`, 1, 1) = MID(`e`.`NullableStringB`, IIF(IIF(LEN(`e`.`NullableStringB`) = 0, 1, LEN(`e`.`NullableStringB`)) IS NULL, 0, IIF(LEN(`e`.`NullableStringB`) = 0, 1, LEN(`e`.`NullableStringB`))), 1) OR (`e`.`NullableStringA` IS NULL AND `e`.`NullableStringB` IS NULL) """); }