diff --git a/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetStringMethodTranslator.cs b/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetStringMethodTranslator.cs index ee04731..38978ec 100644 --- a/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetStringMethodTranslator.cs +++ b/src/EFCore.Jet/Query/ExpressionTranslators/Internal/JetStringMethodTranslator.cs @@ -20,44 +20,68 @@ namespace EntityFrameworkCore.Jet.Query.ExpressionTranslators.Internal { private readonly JetSqlExpressionFactory _sqlExpressionFactory; - // TODO: Translation. - [NotNull] private static readonly MethodInfo _concat = typeof(string).GetRuntimeMethod(nameof(string.Concat), new[] {typeof(string), typeof(string)}); + private static readonly MethodInfo _indexOfMethodInfo + = typeof(string).GetRequiredRuntimeMethod(nameof(string.IndexOf), typeof(string)); - [NotNull] private static readonly MethodInfo _contains = typeof(string).GetRuntimeMethod(nameof(string.Contains), new[] {typeof(string)}); + private static readonly MethodInfo _replaceMethodInfo + = typeof(string).GetRequiredRuntimeMethod(nameof(string.Replace), typeof(string), typeof(string)); - [NotNull] private static readonly MethodInfo _startsWith = typeof(string).GetRuntimeMethod(nameof(string.StartsWith), new[] {typeof(string)}); - [NotNull] private static readonly MethodInfo _endsWith = typeof(string).GetRuntimeMethod(nameof(string.EndsWith), new[] {typeof(string)}); + private static readonly MethodInfo _toLowerMethodInfo + = typeof(string).GetRequiredRuntimeMethod(nameof(string.ToLower), Array.Empty()); - [NotNull] private static readonly MethodInfo _trimWithNoParam = typeof(string).GetRuntimeMethod(nameof(string.Trim), new Type[0]); - [NotNull] private static readonly MethodInfo _trimWithChars = typeof(string).GetRuntimeMethod(nameof(string.Trim), new[] {typeof(char[])}); - // [NotNull] private static readonly MethodInfo _trimWithSingleChar = typeof(string).GetRuntimeMethod(nameof(string.Trim), new[] {typeof(char)}); // Jet TRIM does not take arguments + private static readonly MethodInfo _toUpperMethodInfo + = typeof(string).GetRequiredRuntimeMethod(nameof(string.ToUpper), Array.Empty()); - [NotNull] private static readonly MethodInfo _trimStartWithNoParam = typeof(string).GetRuntimeMethod(nameof(string.TrimStart), new Type[0]); - [NotNull] private static readonly MethodInfo _trimStartWithChars = typeof(string).GetRuntimeMethod(nameof(string.TrimStart), new[] {typeof(char[])}); - // [NotNull] private static readonly MethodInfo _trimStartWithSingleChar = typeof(string).GetRuntimeMethod(nameof(string.TrimStart), new[] {typeof(char)}); // Jet LTRIM does not take arguments + private static readonly MethodInfo _substringMethodInfoWithOneArg + = typeof(string).GetRequiredRuntimeMethod(nameof(string.Substring), typeof(int)); - [NotNull] private static readonly MethodInfo _trimEndWithNoParam = typeof(string).GetRuntimeMethod(nameof(string.TrimEnd), new Type[0]); - [NotNull] private static readonly MethodInfo _trimEndWithChars = typeof(string).GetRuntimeMethod(nameof(string.TrimEnd), new[] {typeof(char[])}); - // [NotNull] private static readonly MethodInfo _trimEndWithSingleChar = typeof(string).GetRuntimeMethod(nameof(string.TrimEnd), new[] {typeof(char)}); // Jet LTRIM does not take arguments + private static readonly MethodInfo _substringMethodInfoWithTwoArgs + = typeof(string).GetRequiredRuntimeMethod(nameof(string.Substring), typeof(int), typeof(int)); - [NotNull] private static readonly MethodInfo _substring = typeof(string).GetTypeInfo() - .GetDeclaredMethods(nameof(string.Substring)) - .Single( - m => m.GetParameters() - .Length == 1); + private static readonly MethodInfo _isNullOrEmptyMethodInfo + = typeof(string).GetRequiredRuntimeMethod(nameof(string.IsNullOrEmpty), typeof(string)); - [NotNull] private static readonly MethodInfo _substringWithLength = typeof(string).GetTypeInfo() - .GetDeclaredMethods(nameof(string.Substring)) - .Single( - m => m.GetParameters() - .Length == 2); + private static readonly MethodInfo _isNullOrWhiteSpaceMethodInfo + = typeof(string).GetRequiredRuntimeMethod(nameof(string.IsNullOrWhiteSpace), typeof(string)); - [NotNull] private static readonly MethodInfo _toLower = typeof(string).GetRuntimeMethod(nameof(string.ToLower), Array.Empty()); - [NotNull] private static readonly MethodInfo _toUpper = typeof(string).GetRuntimeMethod(nameof(string.ToUpper), Array.Empty()); + // Method defined in netcoreapp2.0 only + private static readonly MethodInfo _trimStartMethodInfoWithoutArgs + = typeof(string).GetRequiredRuntimeMethod(nameof(string.TrimStart), Array.Empty()); - [NotNull] private static readonly MethodInfo _replace = typeof(string).GetRuntimeMethod(nameof(string.Replace), new[] {typeof(string), typeof(string)}); + private static readonly MethodInfo _trimEndMethodInfoWithoutArgs + = typeof(string).GetRequiredRuntimeMethod(nameof(string.TrimEnd), Array.Empty()); - private static readonly MethodInfo _isNullOrWhiteSpace = typeof(string).GetRuntimeMethod(nameof(string.IsNullOrWhiteSpace), new[] {typeof(string)}); + private static readonly MethodInfo _trimMethodInfoWithoutArgs + = typeof(string).GetRequiredRuntimeMethod(nameof(string.Trim), Array.Empty()); + + // Method defined in netstandard2.0 + private static readonly MethodInfo _trimStartMethodInfoWithCharArrayArg + = typeof(string).GetRequiredRuntimeMethod(nameof(string.TrimStart), typeof(char[])); + + private static readonly MethodInfo _trimEndMethodInfoWithCharArrayArg + = typeof(string).GetRequiredRuntimeMethod(nameof(string.TrimEnd), typeof(char[])); + + private static readonly MethodInfo _trimMethodInfoWithCharArrayArg + = typeof(string).GetRequiredRuntimeMethod(nameof(string.Trim), typeof(char[])); + + private static readonly MethodInfo _startsWithMethodInfo + = typeof(string).GetRequiredRuntimeMethod(nameof(string.StartsWith), typeof(string)); + + private static readonly MethodInfo _containsMethodInfo + = typeof(string).GetRequiredRuntimeMethod(nameof(string.Contains), typeof(string)); + + private static readonly MethodInfo _endsWithMethodInfo + = typeof(string).GetRequiredRuntimeMethod(nameof(string.EndsWith), typeof(string)); + + private static readonly MethodInfo _firstOrDefaultMethodInfoWithoutArgs + = typeof(Enumerable).GetRuntimeMethods().Single( + m => m.Name == nameof(Enumerable.FirstOrDefault) + && m.GetParameters().Length == 1).MakeGenericMethod(typeof(char)); + + private static readonly MethodInfo _lastOrDefaultMethodInfoWithoutArgs + = typeof(Enumerable).GetRuntimeMethods().Single( + m => m.Name == nameof(Enumerable.LastOrDefault) + && m.GetParameters().Length == 1).MakeGenericMethod(typeof(char)); public JetStringMethodTranslator(ISqlExpressionFactory sqlExpressionFactory) @@ -65,7 +89,41 @@ namespace EntityFrameworkCore.Jet.Query.ExpressionTranslators.Internal public SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList arguments, IDiagnosticsLogger logger) { - if (Equals(method, _contains)) + if (_indexOfMethodInfo.Equals(method)) + { + var argument = arguments[0]; + var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, argument)!; + argument = _sqlExpressionFactory.ApplyTypeMapping(argument, stringTypeMapping); + + SqlExpression charIndexExpression; + var storeType = stringTypeMapping.StoreType; + if (string.Equals(storeType, "nvarchar(max)", StringComparison.OrdinalIgnoreCase) + || string.Equals(storeType, "varchar(max)", StringComparison.OrdinalIgnoreCase)) + { + charIndexExpression = _sqlExpressionFactory.Function( + "INSTR", + new[] { _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping), argument }, + nullable: true, + argumentsPropagateNullability: new[] { true, true }, + typeof(long)); + + charIndexExpression = _sqlExpressionFactory.Convert(charIndexExpression, typeof(int)); + } + else + { + charIndexExpression = _sqlExpressionFactory.Function( + "INSTR", + new[] { _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping), argument }, + nullable: true, + argumentsPropagateNullability: new[] { true, true }, + method.ReturnType); + } + + charIndexExpression = _sqlExpressionFactory.Subtract(charIndexExpression, _sqlExpressionFactory.Constant(1)); + return charIndexExpression; + } + + if (Equals(method, _containsMethodInfo)) { var patternExpression = arguments[0]; var patternConstantExpression = patternExpression as SqlConstantExpression; @@ -96,7 +154,7 @@ namespace EntityFrameworkCore.Jet.Query.ExpressionTranslators.Internal _sqlExpressionFactory.Equal(patternExpression, _sqlExpressionFactory.Constant(string.Empty))); } - if (Equals(method, _startsWith)) + if (Equals(method, _startsWithMethodInfo)) { return _sqlExpressionFactory.Like( // ReSharper disable once AssignNullToNotNullAttribute @@ -105,7 +163,7 @@ namespace EntityFrameworkCore.Jet.Query.ExpressionTranslators.Internal ); } - if (Equals(method, _endsWith)) + if (Equals(method, _endsWithMethodInfo)) { return _sqlExpressionFactory.Like( instance, @@ -114,43 +172,45 @@ namespace EntityFrameworkCore.Jet.Query.ExpressionTranslators.Internal // Jet TRIM does not take arguments. // _trimWithNoParam is only available since .NET Core 2.0 (or .NET Standard 2.1). - if (Equals(method, _trimWithNoParam) || - Equals(method, _trimWithChars) && ((arguments[0] as SqlConstantExpression)?.Value == null || + if (Equals(method, _trimMethodInfoWithoutArgs) || + Equals(method, _trimMethodInfoWithCharArrayArg) && ((arguments[0] as SqlConstantExpression)?.Value == null || ((arguments[0] as SqlConstantExpression)?.Value as Array)?.Length == 0)) { - return _sqlExpressionFactory.Function("TRIM", new[] {instance}, false, new[] {false}, method.ReturnType); + return _sqlExpressionFactory.Function("TRIM", new[] {instance}, false, new[] {false}, method.ReturnType, instance.TypeMapping); } // Jet LTRIM does not take arguments // _trimStartWithNoParam is only available since .NET Core 2.0 (or .NET Standard 2.1). - if (Equals(method, _trimStartWithNoParam) || - Equals(method, _trimStartWithChars) && ((arguments[0] as SqlConstantExpression)?.Value == null || + if (Equals(method, _trimStartMethodInfoWithoutArgs) || + Equals(method, _trimStartMethodInfoWithCharArrayArg) && ((arguments[0] as SqlConstantExpression)?.Value == null || ((arguments[0] as SqlConstantExpression)?.Value as Array)?.Length == 0)) { - return _sqlExpressionFactory.Function("LTRIM", new[] {instance}, false, new[] {false}, method.ReturnType); + return _sqlExpressionFactory.Function("LTRIM", new[] {instance}, false, new[] {false}, method.ReturnType, instance.TypeMapping); } // Jet RTRIM does not take arguments // _trimEndWithNoParam is only available since .NET Core 2.0 (or .NET Standard 2.1). - if (Equals(method, _trimEndWithNoParam) || - Equals(method, _trimEndWithChars) && ((arguments[0] as SqlConstantExpression)?.Value == null || + if (Equals(method, _trimEndMethodInfoWithoutArgs) || + Equals(method, _trimEndMethodInfoWithCharArrayArg) && ((arguments[0] as SqlConstantExpression)?.Value == null || ((arguments[0] as SqlConstantExpression)?.Value as Array)?.Length == 0)) { - return _sqlExpressionFactory.Function("RTRIM", new[] {instance}, false, new[] {false}, method.ReturnType); + return _sqlExpressionFactory.Function("RTRIM", new[] {instance}, false, new[] {false}, method.ReturnType, instance.TypeMapping); } - if (Equals(method, _toLower)) + if (_toLowerMethodInfo.Equals(method) + || _toUpperMethodInfo.Equals(method)) { - return _sqlExpressionFactory.Function("LCASE", new[] {instance}, false, new[] {false}, method.ReturnType); - } - - if (Equals(method, _toUpper)) - { - return _sqlExpressionFactory.Function("UCASE", new[] {instance}, false, new[] {false}, method.ReturnType); + return _sqlExpressionFactory.Function( + _toLowerMethodInfo.Equals(method) ? "LCASE" : "UCASE", + new[] { instance }, + nullable: true, + argumentsPropagateNullability: new[] { true }, + method.ReturnType, + instance.TypeMapping); } - if (Equals(_substring, _trimEndWithNoParam) || - Equals(_substringWithLength, _trimEndWithChars)) + if (_substringMethodInfoWithOneArg.Equals(method) || + _substringMethodInfoWithTwoArgs.Equals(method)) { var parameters = new List( new[] @@ -161,31 +221,40 @@ namespace EntityFrameworkCore.Jet.Query.ExpressionTranslators.Internal ? (SqlExpression) _sqlExpressionFactory.Constant((int) constantExpression.Value + 1) : _sqlExpressionFactory.Add( arguments[0], - _sqlExpressionFactory.Constant(1)), - arguments[1] + _sqlExpressionFactory.Constant(1)) }); - - // MID can be called with an optional `length` parameter. if (arguments.Count >= 2) + { parameters.Add(arguments[1]); + } return _sqlExpressionFactory.Function( "MID", parameters, false, new[] {false}, - method.ReturnType); + method.ReturnType,instance.TypeMapping); } - if (Equals(method, _replace)) + if (_replaceMethodInfo.Equals(method)) { + var firstArgument = arguments[0]; + var secondArgument = arguments[1]; + var stringTypeMapping = ExpressionExtensions.InferTypeMapping(instance, firstArgument, secondArgument); + + instance = _sqlExpressionFactory.ApplyTypeMapping(instance, stringTypeMapping); + firstArgument = _sqlExpressionFactory.ApplyTypeMapping(firstArgument, stringTypeMapping); + secondArgument = _sqlExpressionFactory.ApplyTypeMapping(secondArgument, stringTypeMapping); + return _sqlExpressionFactory.Function( "REPLACE", - new[] {instance}.Concat(arguments), - false, new[] {false}, - method.ReturnType); + new[] { instance, firstArgument, secondArgument }, + nullable: true, + argumentsPropagateNullability: new[] { true, true, true }, + method.ReturnType, + stringTypeMapping); } - if (Equals(method, _isNullOrWhiteSpace)) + if (Equals(method, _isNullOrWhiteSpaceMethodInfo)) { return _sqlExpressionFactory.OrElse( _sqlExpressionFactory.IsNull(arguments[0]), @@ -198,6 +267,38 @@ namespace EntityFrameworkCore.Jet.Query.ExpressionTranslators.Internal _sqlExpressionFactory.Constant(string.Empty))); } + if (_firstOrDefaultMethodInfoWithoutArgs.Equals(method)) + { + var argument = arguments[0]; + return _sqlExpressionFactory.Function( + "MID", + new[] { argument, _sqlExpressionFactory.Constant(1), _sqlExpressionFactory.Constant(1) }, + nullable: true, + argumentsPropagateNullability: new[] { true, true, true }, + method.ReturnType); + } + + if (_lastOrDefaultMethodInfoWithoutArgs.Equals(method)) + { + var argument = arguments[0]; + return _sqlExpressionFactory.Function( + "MID", + new[] + { + argument, + _sqlExpressionFactory.Function( + "LEN", + new[] { argument }, + nullable: true, + argumentsPropagateNullability: new[] { true }, + typeof(int)), + _sqlExpressionFactory.Constant(1) + }, + nullable: true, + argumentsPropagateNullability: new[] { true, true, true }, + method.ReturnType); + } + return null; } } diff --git a/test/EFCore.Jet.FunctionalTests/LoadJetTest.cs b/test/EFCore.Jet.FunctionalTests/LoadJetTest.cs index 1684930..b7f762b 100644 --- a/test/EFCore.Jet.FunctionalTests/LoadJetTest.cs +++ b/test/EFCore.Jet.FunctionalTests/LoadJetTest.cs @@ -201,7 +201,7 @@ WHERE `s`.`ParentId` = {AssertSqlHelper.Parameter("@__p_0")}"); base.Lazy_load_many_to_one_reference_to_principal_alternate_key(state); AssertSql( - $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 450)")} + $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 255)")} SELECT `p`.`Id`, `p`.`AlternateId` FROM `Parent` AS `p` @@ -213,7 +213,7 @@ WHERE `p`.`AlternateId` = {AssertSqlHelper.Parameter("@__p_0")}"); base.Lazy_load_one_to_one_reference_to_principal_alternate_key(state); AssertSql( - $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 450)")} + $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 255)")} SELECT `p`.`Id`, `p`.`AlternateId` FROM `Parent` AS `p` @@ -225,7 +225,7 @@ WHERE `p`.`AlternateId` = {AssertSqlHelper.Parameter("@__p_0")}"); base.Lazy_load_one_to_one_reference_to_dependent_alternate_key(state); AssertSql( - $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 450)")} + $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 255)")} SELECT `s`.`Id`, `s`.`ParentId` FROM `SingleAk` AS `s` @@ -313,8 +313,7 @@ WHERE `s`.`ParentId` = {AssertSqlHelper.Parameter("@__p_0")}"); base.Lazy_load_collection_composite_key(state); AssertSql( - $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 450)")} - + $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 255)")} {AssertSqlHelper.Declaration("@__p_1='707' (Nullable = true)")} SELECT `c`.`Id`, `c`.`ParentAlternateId`, `c`.`ParentId` @@ -327,8 +326,7 @@ WHERE (`c`.`ParentAlternateId` = {AssertSqlHelper.Parameter("@__p_0")}) AND (`c` base.Lazy_load_many_to_one_reference_to_principal_composite_key(state); AssertSql( - $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 450)")} - + $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 255)")} {AssertSqlHelper.Declaration("@__p_1='707'")} SELECT `p`.`Id`, `p`.`AlternateId` @@ -341,8 +339,7 @@ WHERE (`p`.`AlternateId` = {AssertSqlHelper.Parameter("@__p_0")}) AND (`p`.`Id` base.Lazy_load_one_to_one_reference_to_principal_composite_key(state); AssertSql( - $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 450)")} - + $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 255)")} {AssertSqlHelper.Declaration("@__p_1='707'")} SELECT `p`.`Id`, `p`.`AlternateId` @@ -355,8 +352,7 @@ WHERE (`p`.`AlternateId` = {AssertSqlHelper.Parameter("@__p_0")}) AND (`p`.`Id` base.Lazy_load_one_to_one_reference_to_dependent_composite_key(state); AssertSql( - $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 450)")} - + $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 255)")} {AssertSqlHelper.Declaration("@__p_1='707' (Nullable = true)")} SELECT `s`.`Id`, `s`.`ParentAlternateId`, `s`.`ParentId` @@ -543,7 +539,7 @@ WHERE `s`.`Id` = {AssertSqlHelper.Parameter("@__p_0")}"); AssertSql( $@"SELECT TOP 2 `p`.`Id`, `p`.`AlternateId` FROM `Parent` AS `p` -WHERE False = True"); +WHERE 0 = 1"); } public override async Task Load_one_to_one_reference_to_principal_using_Query_null_FK(EntityState state, bool async) @@ -553,7 +549,7 @@ WHERE False = True"); AssertSql( $@"SELECT TOP 2 `p`.`Id`, `p`.`AlternateId` FROM `Parent` AS `p` -WHERE False = True"); +WHERE 0 = 1"); } public override async Task Load_collection_not_found(EntityState state, bool async) @@ -1046,7 +1042,7 @@ WHERE `s`.`ParentId` = {AssertSqlHelper.Parameter("@__p_0")}"); await base.Load_collection_alternate_key(state, async); AssertSql( - $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 450)")} + $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 255)")} SELECT `c`.`Id`, `c`.`ParentId` FROM `ChildAk` AS `c` @@ -1058,7 +1054,7 @@ WHERE `c`.`ParentId` = {AssertSqlHelper.Parameter("@__p_0")}"); await base.Load_many_to_one_reference_to_principal_alternate_key(state, async); AssertSql( - $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 450)")} + $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 255)")} SELECT `p`.`Id`, `p`.`AlternateId` FROM `Parent` AS `p` @@ -1070,7 +1066,7 @@ WHERE `p`.`AlternateId` = {AssertSqlHelper.Parameter("@__p_0")}"); await base.Load_one_to_one_reference_to_principal_alternate_key(state, async); AssertSql( - $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 450)")} + $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 255)")} SELECT `p`.`Id`, `p`.`AlternateId` FROM `Parent` AS `p` @@ -1082,7 +1078,7 @@ WHERE `p`.`AlternateId` = {AssertSqlHelper.Parameter("@__p_0")}"); await base.Load_one_to_one_reference_to_dependent_alternate_key(state, async); AssertSql( - $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 450)")} + $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 255)")} SELECT `s`.`Id`, `s`.`ParentId` FROM `SingleAk` AS `s` @@ -1094,7 +1090,7 @@ WHERE `s`.`ParentId` = {AssertSqlHelper.Parameter("@__p_0")}"); await base.Load_collection_using_Query_alternate_key(state, async); AssertSql( - $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 450)")} + $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 255)")} SELECT `c`.`Id`, `c`.`ParentId` FROM `ChildAk` AS `c` @@ -1106,7 +1102,7 @@ WHERE `c`.`ParentId` = {AssertSqlHelper.Parameter("@__p_0")}"); await base.Load_many_to_one_reference_to_principal_using_Query_alternate_key(state, async); AssertSql( - $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 450)")} + $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 255)")} SELECT TOP 2 `p`.`Id`, `p`.`AlternateId` FROM `Parent` AS `p` @@ -1118,7 +1114,7 @@ WHERE `p`.`AlternateId` = {AssertSqlHelper.Parameter("@__p_0")}"); await base.Load_one_to_one_reference_to_principal_using_Query_alternate_key(state, async); AssertSql( - $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 450)")} + $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 255)")} SELECT TOP 2 `p`.`Id`, `p`.`AlternateId` FROM `Parent` AS `p` @@ -1130,7 +1126,7 @@ WHERE `p`.`AlternateId` = {AssertSqlHelper.Parameter("@__p_0")}"); await base.Load_one_to_one_reference_to_dependent_using_Query_alternate_key(state, async); AssertSql( - $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 450)")} + $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 255)")} SELECT TOP 2 `s`.`Id`, `s`.`ParentId` FROM `SingleAk` AS `s` @@ -1158,7 +1154,7 @@ WHERE `s`.`ParentId` = {AssertSqlHelper.Parameter("@__p_0")}"); AssertSql( $@"SELECT TOP 2 `p`.`Id`, `p`.`AlternateId` FROM `Parent` AS `p` -WHERE False = True"); +WHERE 0 = 1"); } public override async Task Load_one_to_one_reference_to_principal_using_Query_null_FK_alternate_key(EntityState state, bool async) @@ -1168,7 +1164,7 @@ WHERE False = True"); AssertSql( $@"SELECT TOP 2 `p`.`Id`, `p`.`AlternateId` FROM `Parent` AS `p` -WHERE False = True"); +WHERE 0 = 1"); } public override async Task Load_collection_shadow_fk(EntityState state, bool async) @@ -1288,7 +1284,7 @@ WHERE `s`.`ParentId` = {AssertSqlHelper.Parameter("@__p_0")}"); AssertSql( $@"SELECT TOP 2 `p`.`Id`, `p`.`AlternateId` FROM `Parent` AS `p` -WHERE False = True"); +WHERE 0 = 1"); } public override async Task Load_one_to_one_reference_to_principal_using_Query_null_FK_shadow_fk(EntityState state, bool async) @@ -1298,7 +1294,7 @@ WHERE False = True"); AssertSql( $@"SELECT TOP 2 `p`.`Id`, `p`.`AlternateId` FROM `Parent` AS `p` -WHERE False = True"); +WHERE 0 = 1"); } public override async Task Load_collection_composite_key(EntityState state, bool async) @@ -1306,8 +1302,7 @@ WHERE False = True"); await base.Load_collection_composite_key(state, async); AssertSql( - $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 450)")} - + $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 255)")} {AssertSqlHelper.Declaration("@__p_1='707' (Nullable = true)")} SELECT `c`.`Id`, `c`.`ParentAlternateId`, `c`.`ParentId` @@ -1320,8 +1315,7 @@ WHERE (`c`.`ParentAlternateId` = {AssertSqlHelper.Parameter("@__p_0")}) AND (`c` await base.Load_many_to_one_reference_to_principal_composite_key(state, async); AssertSql( - $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 450)")} - + $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 255)")} {AssertSqlHelper.Declaration("@__p_1='707'")} SELECT `p`.`Id`, `p`.`AlternateId` @@ -1334,8 +1328,7 @@ WHERE (`p`.`AlternateId` = {AssertSqlHelper.Parameter("@__p_0")}) AND (`p`.`Id` await base.Load_one_to_one_reference_to_principal_composite_key(state, async); AssertSql( - $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 450)")} - + $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 255)")} {AssertSqlHelper.Declaration("@__p_1='707'")} SELECT `p`.`Id`, `p`.`AlternateId` @@ -1348,8 +1341,7 @@ WHERE (`p`.`AlternateId` = {AssertSqlHelper.Parameter("@__p_0")}) AND (`p`.`Id` await base.Load_one_to_one_reference_to_dependent_composite_key(state, async); AssertSql( - $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 450)")} - + $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 255)")} {AssertSqlHelper.Declaration("@__p_1='707' (Nullable = true)")} SELECT `s`.`Id`, `s`.`ParentAlternateId`, `s`.`ParentId` @@ -1362,8 +1354,7 @@ WHERE (`s`.`ParentAlternateId` = {AssertSqlHelper.Parameter("@__p_0")}) AND (`s` await base.Load_collection_using_Query_composite_key(state, async); AssertSql( - $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 450)")} - + $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 255)")} {AssertSqlHelper.Declaration("@__p_1='707' (Nullable = true)")} SELECT `c`.`Id`, `c`.`ParentAlternateId`, `c`.`ParentId` @@ -1376,8 +1367,7 @@ WHERE (`c`.`ParentAlternateId` = {AssertSqlHelper.Parameter("@__p_0")}) AND (`c` await base.Load_many_to_one_reference_to_principal_using_Query_composite_key(state, async); AssertSql( - $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 450)")} - + $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 255)")} {AssertSqlHelper.Declaration("@__p_1='707'")} SELECT TOP 2 `p`.`Id`, `p`.`AlternateId` @@ -1390,8 +1380,7 @@ WHERE (`p`.`AlternateId` = {AssertSqlHelper.Parameter("@__p_0")}) AND (`p`.`Id` await base.Load_one_to_one_reference_to_principal_using_Query_composite_key(state, async); AssertSql( - $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 450)")} - + $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 255)")} {AssertSqlHelper.Declaration("@__p_1='707'")} SELECT TOP 2 `p`.`Id`, `p`.`AlternateId` @@ -1404,8 +1393,7 @@ WHERE (`p`.`AlternateId` = {AssertSqlHelper.Parameter("@__p_0")}) AND (`p`.`Id` await base.Load_one_to_one_reference_to_dependent_using_Query_composite_key(state, async); AssertSql( - $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 450)")} - + $@"{AssertSqlHelper.Declaration("@__p_0='Root' (Size = 255)")} {AssertSqlHelper.Declaration("@__p_1='707' (Nullable = true)")} SELECT TOP 2 `s`.`Id`, `s`.`ParentAlternateId`, `s`.`ParentId` @@ -1434,7 +1422,7 @@ WHERE (`s`.`ParentAlternateId` = {AssertSqlHelper.Parameter("@__p_0")}) AND (`s` AssertSql( $@"SELECT TOP 2 `p`.`Id`, `p`.`AlternateId` FROM `Parent` AS `p` -WHERE False = True"); +WHERE 0 = 1"); } public override async Task Load_one_to_one_reference_to_principal_using_Query_null_FK_composite_key(EntityState state, bool async) @@ -1444,7 +1432,7 @@ WHERE False = True"); AssertSql( $@"SELECT TOP 2 `p`.`Id`, `p`.`AlternateId` FROM `Parent` AS `p` -WHERE False = True"); +WHERE 0 = 1"); } protected override void ClearLog() => Fixture.TestSqlLoggerFactory.Clear(); diff --git a/test/EFCore.Jet.FunctionalTests/Query/NorthwindNavigationsQueryJetTest.cs b/test/EFCore.Jet.FunctionalTests/Query/NorthwindNavigationsQueryJetTest.cs index 5bf9336..6ea2eba 100644 --- a/test/EFCore.Jet.FunctionalTests/Query/NorthwindNavigationsQueryJetTest.cs +++ b/test/EFCore.Jet.FunctionalTests/Query/NorthwindNavigationsQueryJetTest.cs @@ -260,7 +260,7 @@ LEFT JOIN `Customers` AS `c` ON `o`.`CustomerID` = `c`.`CustomerID`"); $@"SELECT `o`.`OrderID`, `o`.`CustomerID`, `o`.`EmployeeID`, `o`.`OrderDate` FROM `Orders` AS `o` LEFT JOIN `Customers` AS `c` ON `o`.`CustomerID` = `c`.`CustomerID` -WHERE (`c`.`City` = 'Seattle') AND ((`c`.`Phone` <> '555 555 5555') OR `c`.`Phone` IS NULL)"); +WHERE (`c`.`City` = 'Seattle') AND ((`c`.`Phone` <> '555 555 5555') OR (`c`.`Phone` IS NULL))"); } public override async Task Select_Navigations_Where_Navigations(bool isAsync) @@ -271,7 +271,7 @@ WHERE (`c`.`City` = 'Seattle') AND ((`c`.`Phone` <> '555 555 5555') OR `c`.`Phon $@"SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region` FROM `Orders` AS `o` LEFT JOIN `Customers` AS `c` ON `o`.`CustomerID` = `c`.`CustomerID` -WHERE (`c`.`City` = 'Seattle') AND ((`c`.`Phone` <> '555 555 5555') OR `c`.`Phone` IS NULL)"); +WHERE (`c`.`City` = 'Seattle') AND ((`c`.`Phone` <> '555 555 5555') OR (`c`.`Phone` IS NULL))"); } public override async Task Select_Singleton_Navigation_With_Member_Access(bool isAsync) @@ -282,7 +282,7 @@ WHERE (`c`.`City` = 'Seattle') AND ((`c`.`Phone` <> '555 555 5555') OR `c`.`Phon $@"SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region` FROM `Orders` AS `o` LEFT JOIN `Customers` AS `c` ON `o`.`CustomerID` = `c`.`CustomerID` -WHERE (`c`.`City` = 'Seattle') AND ((`c`.`Phone` <> '555 555 5555') OR `c`.`Phone` IS NULL)"); +WHERE (`c`.`City` = 'Seattle') AND ((`c`.`Phone` <> '555 555 5555') OR (`c`.`Phone` IS NULL))"); } public override async Task Select_count_plus_sum(bool isAsync) @@ -308,7 +308,7 @@ FROM `Orders` AS `o1`"); $@"SELECT `c`.`City` AS `B` FROM `Orders` AS `o` LEFT JOIN `Customers` AS `c` ON `o`.`CustomerID` = `c`.`CustomerID` -WHERE (`c`.`City` = 'Seattle') AND ((`c`.`Phone` <> '555 555 5555') OR `c`.`Phone` IS NULL)"); +WHERE (`c`.`City` = 'Seattle') AND ((`c`.`Phone` <> '555 555 5555') OR (`c`.`Phone` IS NULL))"); } public override async Task Select_Where_Navigation_Scalar_Equals_Navigation_Scalar_Projected(bool isAsync) @@ -358,8 +358,8 @@ WHERE `e0`.`EmployeeID` IS NULL"); AssertSql( $@"SELECT `e`.`EmployeeID`, `e`.`City`, `e`.`Country`, `e`.`FirstName`, `e`.`ReportsTo`, `e`.`Title` -FROM `Employees` AS `e` -LEFT JOIN `Employees` AS `e0` ON `e`.`ReportsTo` = `e0`.`EmployeeID` +FROM (`Employees` AS `e` +LEFT JOIN `Employees` AS `e0` ON `e`.`ReportsTo` = `e0`.`EmployeeID`) LEFT JOIN `Employees` AS `e1` ON `e0`.`ReportsTo` = `e1`.`EmployeeID` WHERE `e1`.`EmployeeID` IS NULL"); } diff --git a/test/EFCore.Jet.FunctionalTests/Query/NorthwindSelectQueryJetTest.cs b/test/EFCore.Jet.FunctionalTests/Query/NorthwindSelectQueryJetTest.cs index f30c62b..5272634 100644 --- a/test/EFCore.Jet.FunctionalTests/Query/NorthwindSelectQueryJetTest.cs +++ b/test/EFCore.Jet.FunctionalTests/Query/NorthwindSelectQueryJetTest.cs @@ -868,10 +868,7 @@ FROM `Orders` AS `o`"); await base.Select_byte_constant(isAsync); AssertSql( - $@"SELECT CASE - WHEN `c`.`CustomerID` = 'ALFKI' THEN 1 - ELSE 2 -END + $@"SELECT IIF(`c`.`CustomerID` = 'ALFKI', 1, 2) FROM `Customers` AS `c`"); } @@ -880,10 +877,7 @@ FROM `Customers` AS `c`"); await base.Select_short_constant(isAsync); AssertSql( - $@"SELECT CASE - WHEN `c`.`CustomerID` = 'ALFKI' THEN 1 - ELSE 2 -END + $@"SELECT IIF(`c`.`CustomerID` = 'ALFKI', 1, 2) FROM `Customers` AS `c`"); } @@ -892,7 +886,7 @@ FROM `Customers` AS `c`"); await base.Select_bool_constant(isAsync); AssertSql( - $@"SELECT IIF(`c`.`CustomerID` = 'ALFKI', 1, 0) + $@"SELECT IIF(`c`.`CustomerID` = 'ALFKI', TRUE, FALSE) FROM `Customers` AS `c`"); } @@ -940,7 +934,7 @@ FROM `Orders` AS `o`"); await base.Select_GetValueOrDefault_on_DateTime_with_null_values(isAsync); AssertSql( - $@"SELECT IIf(`o`.`OrderDate` IS NULL, '01/01/1753 00:00:00', `o`.`OrderDate`) + $@"SELECT IIF(`o`.`OrderDate` IS NULL, '01/01/1753 00:00:00', `o`.`OrderDate`) FROM `Customers` AS `c` LEFT JOIN `Orders` AS `o` ON `c`.`CustomerID` = `o`.`CustomerID`"); } @@ -950,7 +944,7 @@ LEFT JOIN `Orders` AS `o` ON `c`.`CustomerID` = `o`.`CustomerID`"); await base.Cast_on_top_level_projection_brings_explicit_Cast(isAsync); AssertSql( - $@"SELECT IIf(`o`.`OrderID` IS NULL, NULL, CDBL(`o`.`OrderID`)) + $@"SELECT IIF(`o`.`OrderID` IS NULL, NULL, CDBL(`o`.`OrderID`)) FROM `Orders` AS `o`"); } @@ -969,10 +963,10 @@ FROM `Orders` AS `o`"); AssertSql( $@"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` -INNER JOIN `Orders` AS `o` ON `c`.`CustomerID` = `o`.`CustomerID` +FROM (`Customers` AS `c` +INNER JOIN `Orders` AS `o` ON `c`.`CustomerID` = `o`.`CustomerID`) INNER JOIN `Order Details` AS `o0` ON `o`.`OrderID` = `o0`.`OrderID` -WHERE IIf(`o0`.`Discount` IS NULL, NULL, CDBL(`o0`.`Discount`)) >= 0.25E0"); +WHERE IIF(`o0`.`Discount` IS NULL, NULL, CDBL(`o0`.`Discount`)) >= 0.25"); } public override async Task SelectMany_without_result_selector_naked_collection_navigation(bool isAsync) diff --git a/test/EFCore.Jet.FunctionalTests/Query/NorthwindWhereQueryJetTest.cs b/test/EFCore.Jet.FunctionalTests/Query/NorthwindWhereQueryJetTest.cs index 37631ce..4c3f427 100644 --- a/test/EFCore.Jet.FunctionalTests/Query/NorthwindWhereQueryJetTest.cs +++ b/test/EFCore.Jet.FunctionalTests/Query/NorthwindWhereQueryJetTest.cs @@ -411,7 +411,7 @@ WHERE EXISTS ( AssertSql( $@"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 (IIF(`c`.`CustomerID` = 'ALFKI', 1, 0) BOR IIF(`c`.`CustomerID` = 'ANATR', 1, 0)) = True"); +WHERE IIF(`c`.`CustomerID` = 'ALFKI', TRUE, FALSE) BOR IIF(`c`.`CustomerID` = 'ANATR', TRUE, FALSE)"); } public override async Task Where_bitwise_and(bool isAsync) @@ -421,7 +421,7 @@ WHERE (IIF(`c`.`CustomerID` = 'ALFKI', 1, 0) BOR IIF(`c`.`CustomerID` = 'ANATR', AssertSql( $@"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 (IIF(`c`.`CustomerID` = 'ALFKI', 1, 0) BAND IIF(`c`.`CustomerID` = 'ANATR', 1, 0)) = True"); +WHERE IIF(`c`.`CustomerID` = 'ALFKI', TRUE, FALSE) BAND IIF(`c`.`CustomerID` = 'ANATR', TRUE, FALSE)"); } public override async Task Where_bitwise_xor(bool isAsync) @@ -457,15 +457,16 @@ WHERE `e`.`Title` = 'Sales Representative'"); { await base.Where_shadow_subquery_FirstOrDefault(isAsync); - // issue #15994 -// AssertSql( -// $@"SELECT `e`.`EmployeeID`, `e`.`City`, `e`.`Country`, `e`.`FirstName`, `e`.`ReportsTo`, `e`.`Title` -//FROM `Employees` AS `e` -//WHERE `e`.`Title` = ( -// SELECT TOP 1 `e2`.`Title` -// FROM `Employees` AS `e2` -// ORDER BY `e2`.`Title` -//)"); + AssertSql( + @"SELECT `e`.`EmployeeID`, `e`.`City`, `e`.`Country`, `e`.`FirstName`, `e`.`ReportsTo`, `e`.`Title` +FROM `Employees` AS `e` +WHERE (`e`.`Title` = ( + SELECT TOP 1 `e0`.`Title` + FROM `Employees` AS `e0` + ORDER BY `e0`.`Title`)) OR ((`e`.`Title` IS NULL) AND (( + SELECT TOP 1 `e0`.`Title` + FROM `Employees` AS `e0` + ORDER BY `e0`.`Title`) IS NULL))"); } public override async Task Where_subquery_correlated(bool isAsync) @@ -663,13 +664,7 @@ WHERE CAST(LEN(`c`.`City`) AS int) = 6"); AssertSql( $@"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 (CASE - WHEN 'Sea' = '' THEN 0 - ELSE CHARINDEX('Sea', `c`.`City`) - 1 -END <> -1) OR CASE - WHEN 'Sea' = '' THEN 0 - ELSE CHARINDEX('Sea', `c`.`City`) - 1 -END IS NULL"); +WHERE ((INSTR(`c`.`City`, 'Sea') - 1) <> -1) OR (`c`.`City` IS NULL)"); } public override async Task Where_string_replace(bool isAsync) @@ -689,33 +684,31 @@ WHERE REPLACE(`c`.`City`, 'Sea', 'Rea') = 'Reattle'"); AssertSql( $@"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 SUBSTRING(`c`.`City`, 1 + 1, 2) = 'ea'"); +WHERE MID(`c`.`City`, 2, 2) = 'ea'"); } public override async Task Where_datetime_now(bool isAsync) { await base.Where_datetime_now(isAsync); - // issue #15994 -// AssertSql( -// $@"{AssertSqlHelper.Declaration("@__myDatetime_0='2015-04-10T00:00:00'")} + AssertSql( + $@"{AssertSqlHelper.Declaration("@__myDatetime_0='2015-04-10T00:00:00'")} -//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 GETDATE() <> @__myDatetime_0"); +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 GETDATE() <> @__myDatetime_0"); } public override async Task Where_datetime_utcnow(bool isAsync) { await base.Where_datetime_utcnow(isAsync); - // issue #15994 -// AssertSql( -// $@"{AssertSqlHelper.Declaration("@__myDatetime_0='2015-04-10T00:00:00'")} + AssertSql( + $@"{AssertSqlHelper.Declaration("@__myDatetime_0='2015-04-10T00:00:00'")} -//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 GETUTCDATE() <> @__myDatetime_0"); +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 GETUTCDATE() <> @__myDatetime_0"); } public override async Task Where_datetime_today(bool isAsync) @@ -834,22 +827,20 @@ WHERE DATEPART(millisecond, `o`.`OrderDate`) = 88"); { await base.Where_datetimeoffset_now_component(isAsync); - // issue #15994 -// AssertSql( -// $@"SELECT `o`.`OrderID`, `o`.`CustomerID`, `o`.`EmployeeID`, `o`.`OrderDate` -//FROM `Orders` AS `o` -//WHERE `o`.`OrderDate` = SYSDATETIMEOFFSET()"); + AssertSql( + $@"SELECT `o`.`OrderID`, `o`.`CustomerID`, `o`.`EmployeeID`, `o`.`OrderDate` +FROM `Orders` AS `o` +WHERE `o`.`OrderDate` = SYSDATETIMEOFFSET()"); } public override async Task Where_datetimeoffset_utcnow_component(bool isAsync) { await base.Where_datetimeoffset_utcnow_component(isAsync); - // issue #15994 -// AssertSql( -// $@"SELECT `o`.`OrderID`, `o`.`CustomerID`, `o`.`EmployeeID`, `o`.`OrderDate` -//FROM `Orders` AS `o` -//WHERE `o`.`OrderDate` = CAST(SYSUTCDATETIME() AS datetimeoffset)"); + AssertSql( + $@"SELECT `o`.`OrderID`, `o`.`CustomerID`, `o`.`EmployeeID`, `o`.`OrderDate` +FROM `Orders` AS `o` +WHERE `o`.`OrderDate` = CAST(SYSUTCDATETIME() AS datetimeoffset)"); } public override async Task Where_simple_reversed(bool isAsync) @@ -885,7 +876,7 @@ FROM `Customers` AS `c`"); { await base.Where_constant_is_null(isAsync); - AssertSql( + AssertSql( $@"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 0 = 1"); @@ -927,7 +918,7 @@ FROM `Customers` AS `c`"); AssertSql( $@"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 (`c`.`City` = `c`.`City`) OR `c`.`City` IS NULL"); +WHERE (`c`.`City` = `c`.`City`) OR (`c`.`City` IS NULL)"); } public override async Task Where_in_optimization_multiple(bool isAsync) @@ -938,7 +929,7 @@ WHERE (`c`.`City` = `c`.`City`) OR `c`.`City` IS NULL"); $@"SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region`, `e`.`EmployeeID`, `e`.`City`, `e`.`Country`, `e`.`FirstName`, `e`.`ReportsTo`, `e`.`Title` FROM `Customers` AS `c`, `Employees` AS `e` -WHERE (((`c`.`City` = 'London') OR (`c`.`City` = 'Berlin')) OR (`c`.`CustomerID` = 'ALFKI')) OR (`c`.`CustomerID` = 'ABCDE')"); +WHERE (`c`.`City` IN ('London', 'Berlin') OR (`c`.`CustomerID` = 'ALFKI')) OR (`c`.`CustomerID` = 'ABCDE')"); } public override async Task Where_not_in_optimization1(bool isAsync) @@ -949,7 +940,7 @@ WHERE (((`c`.`City` = 'London') OR (`c`.`City` = 'Berlin')) OR (`c`.`CustomerID` $@"SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region`, `e`.`EmployeeID`, `e`.`City`, `e`.`Country`, `e`.`FirstName`, `e`.`ReportsTo`, `e`.`Title` FROM `Customers` AS `c`, `Employees` AS `e` -WHERE ((`c`.`City` <> 'London') OR `c`.`City` IS NULL) AND ((`e`.`City` <> 'London') OR `e`.`City` IS NULL)"); +WHERE ((`c`.`City` <> 'London') OR (`c`.`City` IS NULL)) AND ((`e`.`City` <> 'London') OR (`e`.`City` IS NULL))"); } public override async Task Where_not_in_optimization2(bool isAsync) @@ -960,7 +951,7 @@ WHERE ((`c`.`City` <> 'London') OR `c`.`City` IS NULL) AND ((`e`.`City` <> 'Lond $@"SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region`, `e`.`EmployeeID`, `e`.`City`, `e`.`Country`, `e`.`FirstName`, `e`.`ReportsTo`, `e`.`Title` FROM `Customers` AS `c`, `Employees` AS `e` -WHERE ((`c`.`City` <> 'London') OR `c`.`City` IS NULL) AND ((`c`.`City` <> 'Berlin') OR `c`.`City` IS NULL)"); +WHERE `c`.`City` NOT IN ('London', 'Berlin') OR (`c`.`City` IS NULL)"); } public override async Task Where_not_in_optimization3(bool isAsync) @@ -971,7 +962,7 @@ WHERE ((`c`.`City` <> 'London') OR `c`.`City` IS NULL) AND ((`c`.`City` <> 'Berl $@"SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region`, `e`.`EmployeeID`, `e`.`City`, `e`.`Country`, `e`.`FirstName`, `e`.`ReportsTo`, `e`.`Title` FROM `Customers` AS `c`, `Employees` AS `e` -WHERE (((`c`.`City` <> 'London') OR `c`.`City` IS NULL) AND ((`c`.`City` <> 'Berlin') OR `c`.`City` IS NULL)) AND ((`c`.`City` <> 'Seattle') OR `c`.`City` IS NULL)"); +WHERE `c`.`City` NOT IN ('London', 'Berlin', 'Seattle') OR (`c`.`City` IS NULL)"); } public override async Task Where_not_in_optimization4(bool isAsync) @@ -982,7 +973,7 @@ WHERE (((`c`.`City` <> 'London') OR `c`.`City` IS NULL) AND ((`c`.`City` <> 'Ber $@"SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region`, `e`.`EmployeeID`, `e`.`City`, `e`.`Country`, `e`.`FirstName`, `e`.`ReportsTo`, `e`.`Title` FROM `Customers` AS `c`, `Employees` AS `e` -WHERE ((((`c`.`City` <> 'London') OR `c`.`City` IS NULL) AND ((`c`.`City` <> 'Berlin') OR `c`.`City` IS NULL)) AND ((`c`.`City` <> 'Seattle') OR `c`.`City` IS NULL)) AND ((`c`.`City` <> 'Lisboa') OR `c`.`City` IS NULL)"); +WHERE `c`.`City` NOT IN ('London', 'Berlin', 'Seattle', 'Lisboa') OR (`c`.`City` IS NULL)"); } public override async Task Where_select_many_and(bool isAsync) @@ -1018,30 +1009,19 @@ WHERE `t`.`EmployeeID` = 5"); AssertSql( $@"SELECT `p`.`ProductID`, `p`.`Discontinued`, `p`.`ProductName`, `p`.`SupplierID`, `p`.`UnitPrice`, `p`.`UnitsInStock` FROM `Products` AS `p` -WHERE `p`.`Discontinued` = True"); +WHERE `p`.`Discontinued`"); } public override async Task Where_bool_member_false(bool isAsync) { await base.Where_bool_member_false(isAsync); - // issue #15994 -// AssertSql( -// $@"SELECT `p`.`ProductID`, `p`.`Discontinued`, `p`.`ProductName`, `p`.`SupplierID`, `p`.`UnitPrice`, `p`.`UnitsInStock` -//FROM `Products` AS `p` -//WHERE `p`.`Discontinued` = False"); + AssertSql( + $@"SELECT `p`.`ProductID`, `p`.`Discontinued`, `p`.`ProductName`, `p`.`SupplierID`, `p`.`UnitPrice`, `p`.`UnitsInStock` +FROM `Products` AS `p` +WHERE NOT (`p`.`Discontinued`)"); } - // public override async Task Where_bool_client_side_negated(bool isAsync) - // { - // await base.Where_bool_client_side_negated(isAsync); - - // AssertSql( - // $@"SELECT `p`.`ProductID`, `p`.`Discontinued`, `p`.`ProductName`, `p`.`SupplierID`, `p`.`UnitPrice`, `p`.`UnitsInStock` - //FROM `Products` AS `p` - //WHERE `p`.`Discontinued` = 1"); - // } - public override async Task Where_bool_member_negated_twice(bool isAsync) { await base.Where_bool_member_negated_twice(isAsync); @@ -1049,7 +1029,7 @@ WHERE `p`.`Discontinued` = True"); AssertSql( $@"SELECT `p`.`ProductID`, `p`.`Discontinued`, `p`.`ProductName`, `p`.`SupplierID`, `p`.`UnitPrice`, `p`.`UnitsInStock` FROM `Products` AS `p` -WHERE `p`.`Discontinued` = True"); +WHERE `p`.`Discontinued`"); } public override async Task Where_bool_member_shadow(bool isAsync) @@ -1059,7 +1039,7 @@ WHERE `p`.`Discontinued` = True"); AssertSql( $@"SELECT `p`.`ProductID`, `p`.`Discontinued`, `p`.`ProductName`, `p`.`SupplierID`, `p`.`UnitPrice`, `p`.`UnitsInStock` FROM `Products` AS `p` -WHERE `p`.`Discontinued` = True"); +WHERE `p`.`Discontinued`"); } public override async Task Where_bool_member_false_shadow(bool isAsync) @@ -1069,7 +1049,7 @@ WHERE `p`.`Discontinued` = True"); AssertSql( $@"SELECT `p`.`ProductID`, `p`.`Discontinued`, `p`.`ProductName`, `p`.`SupplierID`, `p`.`UnitPrice`, `p`.`UnitsInStock` FROM `Products` AS `p` -WHERE `p`.`Discontinued` <> True"); +WHERE NOT (`p`.`Discontinued`)"); } public override async Task Where_bool_member_equals_constant(bool isAsync) @@ -1079,7 +1059,7 @@ WHERE `p`.`Discontinued` <> True"); AssertSql( $@"SELECT `p`.`ProductID`, `p`.`Discontinued`, `p`.`ProductName`, `p`.`SupplierID`, `p`.`UnitPrice`, `p`.`UnitsInStock` FROM `Products` AS `p` -WHERE `p`.`Discontinued` = True"); +WHERE `p`.`Discontinued`"); } public override async Task Where_bool_member_in_complex_predicate(bool isAsync) @@ -1089,7 +1069,7 @@ WHERE `p`.`Discontinued` = True"); AssertSql( $@"SELECT `p`.`ProductID`, `p`.`Discontinued`, `p`.`ProductName`, `p`.`SupplierID`, `p`.`UnitPrice`, `p`.`UnitsInStock` FROM `Products` AS `p` -WHERE ((`p`.`ProductID` > 100) AND (`p`.`Discontinued` = True)) OR (`p`.`Discontinued` = True)"); +WHERE ((`p`.`ProductID` > 100) AND `p`.`Discontinued`) OR `p`.`Discontinued`"); } public override async Task Where_bool_member_compared_to_binary_expression(bool isAsync) @@ -1099,7 +1079,7 @@ WHERE ((`p`.`ProductID` > 100) AND (`p`.`Discontinued` = True)) OR (`p`.`Discont AssertSql( $@"SELECT `p`.`ProductID`, `p`.`Discontinued`, `p`.`ProductName`, `p`.`SupplierID`, `p`.`UnitPrice`, `p`.`UnitsInStock` FROM `Products` AS `p` -WHERE `p`.`Discontinued` = IIF(`p`.`ProductID` > 50, 1, 0)"); +WHERE `p`.`Discontinued` = IIF(`p`.`ProductID` > 50, TRUE, FALSE)"); } public override async Task Where_not_bool_member_compared_to_not_bool_member(bool isAsync) @@ -1177,7 +1157,7 @@ END"); AssertSql( $@"SELECT `p`.`ProductID`, `p`.`Discontinued`, `p`.`ProductName`, `p`.`SupplierID`, `p`.`UnitPrice`, `p`.`UnitsInStock` FROM `Products` AS `p` -WHERE (`p`.`Discontinued` <> True) AND (`p`.`ProductID` >= 20)"); +WHERE NOT (`p`.`Discontinued`) AND (`p`.`ProductID` >= 20)"); } public override async Task Where_de_morgan_and_optimized(bool isAsync) @@ -1187,7 +1167,7 @@ WHERE (`p`.`Discontinued` <> True) AND (`p`.`ProductID` >= 20)"); AssertSql( $@"SELECT `p`.`ProductID`, `p`.`Discontinued`, `p`.`ProductName`, `p`.`SupplierID`, `p`.`UnitPrice`, `p`.`UnitsInStock` FROM `Products` AS `p` -WHERE (`p`.`Discontinued` <> True) OR (`p`.`ProductID` >= 20)"); +WHERE NOT (`p`.`Discontinued`) OR (`p`.`ProductID` >= 20)"); } public override async Task Where_complex_negated_expression_optimized(bool isAsync) @@ -1197,7 +1177,7 @@ WHERE (`p`.`Discontinued` <> True) OR (`p`.`ProductID` >= 20)"); AssertSql( $@"SELECT `p`.`ProductID`, `p`.`Discontinued`, `p`.`ProductName`, `p`.`SupplierID`, `p`.`UnitPrice`, `p`.`UnitsInStock` FROM `Products` AS `p` -WHERE ((`p`.`Discontinued` <> True) AND (`p`.`ProductID` < 60)) AND (`p`.`ProductID` > 30)"); +WHERE (NOT (`p`.`Discontinued`) AND (`p`.`ProductID` < 60)) AND (`p`.`ProductID` > 30)"); } public override async Task Where_short_member_comparison(bool isAsync) @@ -1356,54 +1336,44 @@ WHERE `p`.`UnitsInStock` >= 20"); { await base.Where_ternary_boolean_condition_false(isAsync); - // issue #15994 -// AssertSql( -// $@"{AssertSqlHelper.Declaration("@__flag_0='False'")} - -//SELECT `p`.`ProductID`, `p`.`Discontinued`, `p`.`ProductName`, `p`.`SupplierID`, `p`.`UnitPrice`, `p`.`UnitsInStock` -//FROM `Products` AS `p` -//WHERE ((@__flag_0 = True) AND (`p`.`UnitsInStock` >= 20)) OR ((@__flag_0 <> True) AND (`p`.`UnitsInStock` < 20))"); + AssertSql( + $@"SELECT `p`.`ProductID`, `p`.`Discontinued`, `p`.`ProductName`, `p`.`SupplierID`, `p`.`UnitPrice`, `p`.`UnitsInStock` +FROM `Products` AS `p` +WHERE `p`.`UnitsInStock` < 20"); } public override async Task Where_ternary_boolean_condition_with_another_condition(bool isAsync) { await base.Where_ternary_boolean_condition_with_another_condition(isAsync); - // issue #15994 -// AssertSql( -// $@"{AssertSqlHelper.Declaration("@__productId_0='15'")} + AssertSql( + $@"{AssertSqlHelper.Declaration("@__productId_0='15'")} -//@__flag_1='True' +@__flag_1='True' -//SELECT `p`.`ProductID`, `p`.`Discontinued`, `p`.`ProductName`, `p`.`SupplierID`, `p`.`UnitPrice`, `p`.`UnitsInStock` -//FROM `Products` AS `p` -//WHERE (`p`.`ProductID` < @__productId_0) AND (((@__flag_1 = True) AND (`p`.`UnitsInStock` >= 20)) OR ((@__flag_1 <> True) AND (`p`.`UnitsInStock` < 20)))"); +SELECT `p`.`ProductID`, `p`.`Discontinued`, `p`.`ProductName`, `p`.`SupplierID`, `p`.`UnitPrice`, `p`.`UnitsInStock` +FROM `Products` AS `p` +WHERE (`p`.`ProductID` < @__productId_0) AND (((@__flag_1 = True) AND (`p`.`UnitsInStock` >= 20)) OR ((@__flag_1 <> True) AND (`p`.`UnitsInStock` < 20)))"); } public override async Task Where_ternary_boolean_condition_with_false_as_result_true(bool isAsync) { await base.Where_ternary_boolean_condition_with_false_as_result_true(isAsync); - // issue #15994 -// AssertSql( -// $@"{AssertSqlHelper.Declaration("@__flag_0='True'")} - -//SELECT `p`.`ProductID`, `p`.`Discontinued`, `p`.`ProductName`, `p`.`SupplierID`, `p`.`UnitPrice`, `p`.`UnitsInStock` -//FROM `Products` AS `p` -//WHERE (@__flag_0 = True) AND (`p`.`UnitsInStock` >= 20)"); + AssertSql( + $@"SELECT `p`.`ProductID`, `p`.`Discontinued`, `p`.`ProductName`, `p`.`SupplierID`, `p`.`UnitPrice`, `p`.`UnitsInStock` +FROM `Products` AS `p` +WHERE `p`.`UnitsInStock` >= 20"); } public override async Task Where_ternary_boolean_condition_with_false_as_result_false(bool isAsync) { await base.Where_ternary_boolean_condition_with_false_as_result_false(isAsync); - // issue #15994 -// AssertSql( -// $@"{AssertSqlHelper.Declaration("@__flag_0='False'")} - -//SELECT `p`.`ProductID`, `p`.`Discontinued`, `p`.`ProductName`, `p`.`SupplierID`, `p`.`UnitPrice`, `p`.`UnitsInStock` -//FROM `Products` AS `p` -//WHERE (@__flag_0 = True) AND (`p`.`UnitsInStock` >= 20)"); + AssertSql( + @"SELECT `p`.`ProductID`, `p`.`Discontinued`, `p`.`ProductName`, `p`.`SupplierID`, `p`.`UnitPrice`, `p`.`UnitsInStock` +FROM `Products` AS `p` +WHERE 0 = 1"); } public override async Task Where_compare_constructed_equal(bool isAsync) @@ -1494,7 +1464,7 @@ FROM `Customers` AS `c`"); AssertSql( $@"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 `c`.`City` IS NULL AND (`c`.`Country` = 'UK')"); +WHERE (`c`.`City` IS NULL) AND (`c`.`Country` = 'UK')"); } public override async Task Where_Is_on_same_type(bool isAsync) @@ -1528,7 +1498,7 @@ FROM ( WHERE `c`.`CustomerID` = 'ALFKI' ) AS `t` LEFT JOIN `Orders` AS `o` ON `t`.`CustomerID` = `o`.`CustomerID` -ORDER BY `t`.`CustomerID`, `o`.`OrderID`", +ORDER BY `t`.`CustomerID`", // $@"SELECT `o`.`OrderID`, `o`.`ProductID`, `o`.`Discount`, `o`.`Quantity`, `o`.`UnitPrice` FROM `Order Details` AS `o` @@ -1552,19 +1522,24 @@ WHERE `c`.`CustomerID` = {AssertSqlHelper.Parameter("@__p_0")}"); { await base.Where_multiple_contains_in_subquery_with_or(isAsync); - // issue #15994 -// AssertSql( -// $@"SELECT `od`.`OrderID`, `od`.`ProductID`, `od`.`Discount`, `od`.`Quantity`, `od`.`UnitPrice` -//FROM `Order Details` AS `od` -//WHERE `od`.`ProductID` IN ( -// SELECT TOP 1 `p`.`ProductID` -// FROM `Products` AS `p` -// ORDER BY `p`.`ProductID` -//) OR `od`.`OrderID` IN ( -// SELECT TOP 1 `o`.`OrderID` -// FROM `Orders` AS `o` -// ORDER BY `o`.`OrderID` -//)"); + AssertSql( + @"SELECT `o`.`OrderID`, `o`.`ProductID`, `o`.`Discount`, `o`.`Quantity`, `o`.`UnitPrice` +FROM `Order Details` AS `o` +WHERE EXISTS ( + SELECT 1 + FROM ( + SELECT TOP 1 `p`.`ProductID` + FROM `Products` AS `p` + ORDER BY `p`.`ProductID` + ) AS `t` + WHERE `t`.`ProductID` = `o`.`ProductID`) OR EXISTS ( + SELECT 1 + FROM ( + SELECT TOP 1 `o0`.`OrderID` + FROM `Orders` AS `o0` + ORDER BY `o0`.`OrderID` + ) AS `t0` + WHERE `t0`.`OrderID` = `o`.`OrderID`)"); } public override async Task Where_multiple_contains_in_subquery_with_and(bool isAsync) @@ -1574,16 +1549,21 @@ WHERE `c`.`CustomerID` = {AssertSqlHelper.Parameter("@__p_0")}"); AssertSql( $@"SELECT `o`.`OrderID`, `o`.`ProductID`, `o`.`Discount`, `o`.`Quantity`, `o`.`UnitPrice` FROM `Order Details` AS `o` -WHERE `o`.`ProductID` IN ( - SELECT TOP 20 `p`.`ProductID` - FROM `Products` AS `p` - ORDER BY `p`.`ProductID` -) - AND `o`.`OrderID` IN ( - SELECT TOP 10 `o0`.`OrderID` - FROM `Orders` AS `o0` - ORDER BY `o0`.`OrderID` -)"); +WHERE EXISTS ( + SELECT 1 + FROM ( + SELECT TOP 20 `p`.`ProductID` + FROM `Products` AS `p` + ORDER BY `p`.`ProductID` + ) AS `t` + WHERE `t`.`ProductID` = `o`.`ProductID`) AND EXISTS ( + SELECT 1 + FROM ( + SELECT TOP 10 `o0`.`OrderID` + FROM `Orders` AS `o0` + ORDER BY `o0`.`OrderID` + ) AS `t0` + WHERE `t0`.`OrderID` = `o`.`OrderID`)"); } public override async Task Where_contains_on_navigation(bool isAsync) @@ -1609,13 +1589,12 @@ WHERE EXISTS ( await base.Where_subquery_FirstOrDefault_is_null(isAsync); AssertSql( - $@"SELECT `c`.`CustomerID`, `c`.`Address`, `c`.`City`, `c`.`CompanyName`, `c`.`ContactName`, `c`.`ContactTitle`, `c`.`Country`, `c`.`Fax`, `c`.`Phone`, `c`.`PostalCode`, `c`.`Region` + @"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 ( - SELECT TOP 1 `o`.`OrderID` +WHERE NOT (EXISTS ( + SELECT 1 FROM `Orders` AS `o` - WHERE `c`.`CustomerID` = `o`.`CustomerID` - ORDER BY `o`.`OrderID`) IS NULL"); + WHERE `c`.`CustomerID` = `o`.`CustomerID`))"); } public override async Task Where_subquery_FirstOrDefault_compared_to_entity(bool isAsync) @@ -1660,10 +1639,7 @@ WHERE {AssertSqlHelper.Parameter("@__p_0")} = True"); AssertSql( $@"SELECT `p`.`ProductID`, `p`.`Discontinued`, `p`.`ProductName`, `p`.`SupplierID`, `p`.`UnitPrice`, `p`.`UnitsInStock` FROM `Products` AS `p` -WHERE CASE - WHEN True = True THEN False - ELSE True -END = True"); +WHERE FALSE"); } public override async Task Enclosing_class_settable_member_generates_parameter(bool isAsync) @@ -1713,7 +1689,7 @@ WHERE `o`.`OrderID` = 1"); AssertSql( $@"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 `c`.`City` IN ('Seattle')"); +WHERE `c`.`City` = 'Seattle'"); } public override async Task Filter_non_nullable_value_after_FirstOrDefault_on_empty_collection(bool isAsync) @@ -1749,6 +1725,644 @@ FROM `Orders` AS `o` WHERE CAST(`o`.`OrderID` AS nvarchar(max)) LIKE '%20%'"); } + public override async Task Using_same_parameter_twice_in_query_generates_one_sql_parameter(bool async) + { + await base.Using_same_parameter_twice_in_query_generates_one_sql_parameter(async); + + AssertSql( + @"@__i_0='10' +SELECT `c`.`CustomerID` +FROM `Customers` AS `c` +WHERE ((CAST(@__i_0 AS nchar(5)) + `c`.`CustomerID`) + CAST(@__i_0 AS nchar(5))) = `c`.`CompanyName`"); + } + + public override async Task Where_Queryable_ToList_Count(bool async) + { + await base.Where_Queryable_ToList_Count(async); + + AssertSql( + @"SELECT `c`.`CustomerID`, `o0`.`OrderID`, `o0`.`CustomerID`, `o0`.`EmployeeID`, `o0`.`OrderDate` +FROM `Customers` AS `c` +LEFT JOIN `Orders` AS `o0` ON `c`.`CustomerID` = `o0`.`CustomerID` +WHERE ( + SELECT COUNT(*) + FROM `Orders` AS `o` + WHERE `o`.`CustomerID` = `c`.`CustomerID`) = 0 +ORDER BY `c`.`CustomerID`"); + } + + public override async Task Where_Queryable_ToList_Contains(bool async) + { + await base.Where_Queryable_ToList_Contains(async); + + AssertSql( + @"SELECT `c`.`CustomerID`, `o0`.`CustomerID`, `o0`.`OrderID` +FROM `Customers` AS `c` +LEFT JOIN `Orders` AS `o0` ON `c`.`CustomerID` = `o0`.`CustomerID` +WHERE EXISTS ( + SELECT 1 + FROM `Orders` AS `o` + WHERE (`o`.`CustomerID` = `c`.`CustomerID`) AND (`o`.`CustomerID` = 'ALFKI')) +ORDER BY `c`.`CustomerID`"); + } + + public override async Task Where_Queryable_ToArray_Count(bool async) + { + await base.Where_Queryable_ToArray_Count(async); + + AssertSql( + @"SELECT `c`.`CustomerID`, `o0`.`OrderID`, `o0`.`CustomerID`, `o0`.`EmployeeID`, `o0`.`OrderDate` +FROM `Customers` AS `c` +LEFT JOIN `Orders` AS `o0` ON `c`.`CustomerID` = `o0`.`CustomerID` +WHERE ( + SELECT COUNT(*) + FROM `Orders` AS `o` + WHERE `o`.`CustomerID` = `c`.`CustomerID`) = 0 +ORDER BY `c`.`CustomerID`"); + } + + public override async Task Where_Queryable_ToArray_Contains(bool async) + { + await base.Where_Queryable_ToArray_Contains(async); + + AssertSql( + @"SELECT `c`.`CustomerID`, `o0`.`CustomerID`, `o0`.`OrderID` +FROM `Customers` AS `c` +LEFT JOIN `Orders` AS `o0` ON `c`.`CustomerID` = `o0`.`CustomerID` +WHERE EXISTS ( + SELECT 1 + FROM `Orders` AS `o` + WHERE (`o`.`CustomerID` = `c`.`CustomerID`) AND (`o`.`CustomerID` = 'ALFKI')) +ORDER BY `c`.`CustomerID`"); + } + + public override async Task Where_Queryable_AsEnumerable_Count(bool async) + { + await base.Where_Queryable_AsEnumerable_Count(async); + + AssertSql( + @"SELECT `c`.`CustomerID`, `o0`.`OrderID`, `o0`.`CustomerID`, `o0`.`EmployeeID`, `o0`.`OrderDate` +FROM `Customers` AS `c` +LEFT JOIN `Orders` AS `o0` ON `c`.`CustomerID` = `o0`.`CustomerID` +WHERE ( + SELECT COUNT(*) + FROM `Orders` AS `o` + WHERE `o`.`CustomerID` = `c`.`CustomerID`) = 0 +ORDER BY `c`.`CustomerID`"); + } + + public override async Task Where_Queryable_AsEnumerable_Contains(bool async) + { + await base.Where_Queryable_AsEnumerable_Contains(async); + + AssertSql( + @"SELECT `c`.`CustomerID`, `o0`.`CustomerID`, `o0`.`OrderID` +FROM `Customers` AS `c` +LEFT JOIN `Orders` AS `o0` ON `c`.`CustomerID` = `o0`.`CustomerID` +WHERE EXISTS ( + SELECT 1 + FROM `Orders` AS `o` + WHERE (`o`.`CustomerID` = `c`.`CustomerID`) AND (`o`.`CustomerID` = 'ALFKI')) +ORDER BY `c`.`CustomerID`"); + } + + public override async Task Where_Queryable_AsEnumerable_Contains_negated(bool async) + { + await base.Where_Queryable_AsEnumerable_Contains_negated(async); + + AssertSql( + @"SELECT `c`.`CustomerID`, `o0`.`CustomerID`, `o0`.`OrderID` +FROM `Customers` AS `c` +LEFT JOIN `Orders` AS `o0` ON `c`.`CustomerID` = `o0`.`CustomerID` +WHERE NOT (EXISTS ( + SELECT 1 + FROM `Orders` AS `o` + WHERE (`o`.`CustomerID` = `c`.`CustomerID`) AND (`o`.`CustomerID` = 'ALFKI'))) +ORDER BY `c`.`CustomerID`"); + } + + public override async Task Where_Queryable_ToList_Count_member(bool async) + { + await base.Where_Queryable_ToList_Count_member(async); + + AssertSql( + @"SELECT `c`.`CustomerID`, `o0`.`OrderID`, `o0`.`CustomerID`, `o0`.`EmployeeID`, `o0`.`OrderDate` +FROM `Customers` AS `c` +LEFT JOIN `Orders` AS `o0` ON `c`.`CustomerID` = `o0`.`CustomerID` +WHERE ( + SELECT COUNT(*) + FROM `Orders` AS `o` + WHERE `o`.`CustomerID` = `c`.`CustomerID`) = 0 +ORDER BY `c`.`CustomerID`"); + } + + public override async Task Where_Queryable_ToArray_Length_member(bool async) + { + await base.Where_Queryable_ToArray_Length_member(async); + + AssertSql( + @"SELECT `c`.`CustomerID`, `o0`.`OrderID`, `o0`.`CustomerID`, `o0`.`EmployeeID`, `o0`.`OrderDate` +FROM `Customers` AS `c` +LEFT JOIN `Orders` AS `o0` ON `c`.`CustomerID` = `o0`.`CustomerID` +WHERE ( + SELECT COUNT(*) + FROM `Orders` AS `o` + WHERE `o`.`CustomerID` = `c`.`CustomerID`) = 0 +ORDER BY `c`.`CustomerID`"); + } + + public override async Task Where_collection_navigation_ToList_Count(bool async) + { + await base.Where_collection_navigation_ToList_Count(async); + + AssertSql( + @"SELECT `o`.`OrderID`, `o1`.`OrderID`, `o1`.`ProductID`, `o1`.`Discount`, `o1`.`Quantity`, `o1`.`UnitPrice` +FROM `Orders` AS `o` +LEFT JOIN `Order Details` AS `o1` ON `o`.`OrderID` = `o1`.`OrderID` +WHERE (`o`.`OrderID` < 10300) AND (( + SELECT COUNT(*) + FROM `Order Details` AS `o0` + WHERE `o`.`OrderID` = `o0`.`OrderID`) = 0) +ORDER BY `o`.`OrderID`, `o1`.`OrderID`"); + } + + public override async Task Where_collection_navigation_ToList_Contains(bool async) + { + await base.Where_collection_navigation_ToList_Contains(async); + + AssertSql( + @"@__entity_equality_order_0_OrderID='10248' (Nullable = true) +SELECT `c`.`CustomerID`, `t`.`OrderID`, `t`.`CustomerID`, `t`.`EmployeeID`, `t`.`OrderDate` +FROM `Customers` AS `c` +LEFT JOIN ( + SELECT `o0`.`OrderID`, `o0`.`CustomerID`, `o0`.`EmployeeID`, `o0`.`OrderDate` + FROM `Orders` AS `o0` +) AS `t` ON `c`.`CustomerID` = `t`.`CustomerID` +WHERE EXISTS ( + SELECT 1 + FROM `Orders` AS `o` + WHERE (`c`.`CustomerID` = `o`.`CustomerID`) AND (`o`.`OrderID` = @__entity_equality_order_0_OrderID)) +ORDER BY `c`.`CustomerID`, `t`.`OrderID`"); + } + + public override async Task Where_collection_navigation_ToArray_Count(bool async) + { + await base.Where_collection_navigation_ToArray_Count(async); + + AssertSql( + @"SELECT `o`.`OrderID`, `o1`.`OrderID`, `o1`.`ProductID`, `o1`.`Discount`, `o1`.`Quantity`, `o1`.`UnitPrice` +FROM `Orders` AS `o` +LEFT JOIN `Order Details` AS `o1` ON `o`.`OrderID` = `o1`.`OrderID` +WHERE (`o`.`OrderID` < 10300) AND (( + SELECT COUNT(*) + FROM `Order Details` AS `o0` + WHERE `o`.`OrderID` = `o0`.`OrderID`) = 0) +ORDER BY `o`.`OrderID`, `o1`.`OrderID`"); + } + + public override async Task Where_collection_navigation_ToArray_Contains(bool async) + { + await base.Where_collection_navigation_ToArray_Contains(async); + + AssertSql( + @"@__entity_equality_order_0_OrderID='10248' (Nullable = true) +SELECT `c`.`CustomerID`, `t`.`OrderID`, `t`.`CustomerID`, `t`.`EmployeeID`, `t`.`OrderDate` +FROM `Customers` AS `c` +LEFT JOIN ( + SELECT `o0`.`OrderID`, `o0`.`CustomerID`, `o0`.`EmployeeID`, `o0`.`OrderDate` + FROM `Orders` AS `o0` +) AS `t` ON `c`.`CustomerID` = `t`.`CustomerID` +WHERE EXISTS ( + SELECT 1 + FROM `Orders` AS `o` + WHERE (`c`.`CustomerID` = `o`.`CustomerID`) AND (`o`.`OrderID` = @__entity_equality_order_0_OrderID)) +ORDER BY `c`.`CustomerID`, `t`.`OrderID`"); + } + + public override async Task Where_collection_navigation_AsEnumerable_Count(bool async) + { + await base.Where_collection_navigation_AsEnumerable_Count(async); + + AssertSql( + @"SELECT `o`.`OrderID`, `o1`.`OrderID`, `o1`.`ProductID`, `o1`.`Discount`, `o1`.`Quantity`, `o1`.`UnitPrice` +FROM `Orders` AS `o` +LEFT JOIN `Order Details` AS `o1` ON `o`.`OrderID` = `o1`.`OrderID` +WHERE (`o`.`OrderID` < 10300) AND (( + SELECT COUNT(*) + FROM `Order Details` AS `o0` + WHERE `o`.`OrderID` = `o0`.`OrderID`) = 0) +ORDER BY `o`.`OrderID`, `o1`.`OrderID`"); + } + + public override async Task Where_collection_navigation_AsEnumerable_Contains(bool async) + { + await base.Where_collection_navigation_AsEnumerable_Contains(async); + + AssertSql( + @"@__entity_equality_order_0_OrderID='10248' (Nullable = true) +SELECT `c`.`CustomerID`, `t`.`OrderID`, `t`.`CustomerID`, `t`.`EmployeeID`, `t`.`OrderDate` +FROM `Customers` AS `c` +LEFT JOIN ( + SELECT `o0`.`OrderID`, `o0`.`CustomerID`, `o0`.`EmployeeID`, `o0`.`OrderDate` + FROM `Orders` AS `o0` +) AS `t` ON `c`.`CustomerID` = `t`.`CustomerID` +WHERE EXISTS ( + SELECT 1 + FROM `Orders` AS `o` + WHERE (`c`.`CustomerID` = `o`.`CustomerID`) AND (`o`.`OrderID` = @__entity_equality_order_0_OrderID)) +ORDER BY `c`.`CustomerID`, `t`.`OrderID`"); + } + + public override async Task Where_collection_navigation_ToList_Count_member(bool async) + { + await base.Where_collection_navigation_ToList_Count_member(async); + + AssertSql( + @"SELECT `o`.`OrderID`, `o1`.`OrderID`, `o1`.`ProductID`, `o1`.`Discount`, `o1`.`Quantity`, `o1`.`UnitPrice` +FROM `Orders` AS `o` +LEFT JOIN `Order Details` AS `o1` ON `o`.`OrderID` = `o1`.`OrderID` +WHERE (`o`.`OrderID` < 10300) AND (( + SELECT COUNT(*) + FROM `Order Details` AS `o0` + WHERE `o`.`OrderID` = `o0`.`OrderID`) = 0) +ORDER BY `o`.`OrderID`, `o1`.`OrderID`"); + } + + public override async Task Where_collection_navigation_ToArray_Length_member(bool async) + { + await base.Where_collection_navigation_ToArray_Length_member(async); + + AssertSql( + @"SELECT `o`.`OrderID`, `o1`.`OrderID`, `o1`.`ProductID`, `o1`.`Discount`, `o1`.`Quantity`, `o1`.`UnitPrice` +FROM `Orders` AS `o` +LEFT JOIN `Order Details` AS `o1` ON `o`.`OrderID` = `o1`.`OrderID` +WHERE (`o`.`OrderID` < 10300) AND (( + SELECT COUNT(*) + FROM `Order Details` AS `o0` + WHERE `o`.`OrderID` = `o0`.`OrderID`) = 0) +ORDER BY `o`.`OrderID`, `o1`.`OrderID`"); + } + + public override async Task Where_list_object_contains_over_value_type(bool async) + { + await base.Where_list_object_contains_over_value_type(async); + + AssertSql( + @"SELECT `o`.`OrderID`, `o`.`CustomerID`, `o`.`EmployeeID`, `o`.`OrderDate` +FROM `Orders` AS `o` +WHERE `o`.`OrderID` IN (10248, 10249)"); + } + + public override async Task Where_array_of_object_contains_over_value_type(bool async) + { + await base.Where_array_of_object_contains_over_value_type(async); + + AssertSql( + @"SELECT `o`.`OrderID`, `o`.`CustomerID`, `o`.`EmployeeID`, `o`.`OrderDate` +FROM `Orders` AS `o` +WHERE `o`.`OrderID` IN (10248, 10249)"); + } + + public override async Task Multiple_OrElse_on_same_column_converted_to_in_with_overlap(bool async) + { + await base.Multiple_OrElse_on_same_column_converted_to_in_with_overlap(async); + + AssertSql( + @"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 `c`.`CustomerID` IN ('ALFKI', 'ANATR', 'ANTON')"); + } + + public override async Task Multiple_OrElse_on_same_column_with_null_constant_comparison_converted_to_in(bool async) + { + await base.Multiple_OrElse_on_same_column_with_null_constant_comparison_converted_to_in(async); + + AssertSql( + @"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 `c`.`Region` IN ('WA', 'OR', 'BC') OR (`c`.`Region` IS NULL)"); + } + + public override async Task Constant_array_Contains_OrElse_comparison_with_constant_gets_combined_to_one_in(bool async) + { + await base.Constant_array_Contains_OrElse_comparison_with_constant_gets_combined_to_one_in(async); + + AssertSql( + @"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 `c`.`CustomerID` IN ('ALFKI', 'ANATR', 'ANTON')"); + } + + public override async Task Constant_array_Contains_OrElse_comparison_with_constant_gets_combined_to_one_in_with_overlap(bool async) + { + await base.Constant_array_Contains_OrElse_comparison_with_constant_gets_combined_to_one_in_with_overlap(async); + + AssertSql( + @"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 `c`.`CustomerID` IN ('ALFKI', 'ANATR', 'ANTON')"); + } + + public override async Task Constant_array_Contains_OrElse_another_Contains_gets_combined_to_one_in_with_overlap(bool async) + { + await base.Constant_array_Contains_OrElse_another_Contains_gets_combined_to_one_in_with_overlap(async); + + AssertSql( + @"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 `c`.`CustomerID` IN ('ALFKI', 'ANATR', 'ANTON')"); + } + + public override async Task Constant_array_Contains_AndAlso_another_Contains_gets_combined_to_one_in_with_overlap(bool async) + { + await base.Constant_array_Contains_AndAlso_another_Contains_gets_combined_to_one_in_with_overlap(async); + + AssertSql( + @"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 `c`.`CustomerID` NOT IN ('ALFKI', 'ANATR', 'ANTON')"); + } + + public override async Task Multiple_AndAlso_on_same_column_converted_to_in_using_parameters(bool async) + { + await base.Multiple_AndAlso_on_same_column_converted_to_in_using_parameters(async); + + // issue #21462 + AssertSql( + @"@__prm1_0='ALFKI' (Size = 5) (DbType = StringFixedLength) +@__prm2_1='ANATR' (Size = 5) (DbType = StringFixedLength) +@__prm3_2='ANTON' (Size = 5) (DbType = StringFixedLength) +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 ((`c`.`CustomerID` <> @__prm1_0) AND (`c`.`CustomerID` <> @__prm2_1)) AND (`c`.`CustomerID` <> @__prm3_2)"); + } + + public override async Task Array_of_parameters_Contains_OrElse_comparison_with_constant_gets_combined_to_one_in(bool async) + { + await base.Array_of_parameters_Contains_OrElse_comparison_with_constant_gets_combined_to_one_in(async); + + // issue #21462 + AssertSql( + @"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 `c`.`CustomerID` IN ('ALFKI', 'ANATR') OR (`c`.`CustomerID` = 'ANTON')"); + } + + public override async Task Multiple_OrElse_on_same_column_with_null_parameter_comparison_converted_to_in(bool async) + { + await base.Multiple_OrElse_on_same_column_with_null_parameter_comparison_converted_to_in(async); + + // issue #21462 + AssertSql( + @"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 (`c`.`Region` IN ('WA', 'OR') OR (`c`.`Region` IS NULL)) OR (`c`.`Region` = 'BC')"); + } + + public override async Task Parameter_array_Contains_OrElse_comparison_with_constant(bool async) + { + await base.Parameter_array_Contains_OrElse_comparison_with_constant(async); + + AssertSql( + @"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 `c`.`CustomerID` IN ('ALFKI', 'ANATR') OR (`c`.`CustomerID` = 'ANTON')"); + } + + public override async Task Parameter_array_Contains_OrElse_comparison_with_parameter_with_overlap(bool async) + { + await base.Parameter_array_Contains_OrElse_comparison_with_parameter_with_overlap(async); + + AssertSql( + @"@__prm1_0='ANTON' (Size = 5) (DbType = StringFixedLength) +@__prm2_2='ALFKI' (Size = 5) (DbType = StringFixedLength) +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 ((`c`.`CustomerID` = @__prm1_0) OR `c`.`CustomerID` IN (N'ALFKI', N'ANATR')) OR (`c`.`CustomerID` = @__prm2_2)"); + } + + public override async Task Two_sets_of_comparison_combine_correctly(bool async) + { + await base.Two_sets_of_comparison_combine_correctly(async); + + AssertSql( + @"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 `c`.`CustomerID` = 'ANATR'"); + } + + public override async Task Two_sets_of_comparison_combine_correctly2(bool async) + { + await base.Two_sets_of_comparison_combine_correctly2(async); + + AssertSql( + @"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 (`c`.`Region` <> 'WA') AND (`c`.`Region` IS NOT NULL)"); + } + + public override async Task Filter_with_EF_Property_using_closure_for_property_name(bool async) + { + await base.Filter_with_EF_Property_using_closure_for_property_name(async); + + AssertSql( + @"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 `c`.`CustomerID` = 'ALFKI'"); + } + + public override async Task Filter_with_EF_Property_using_function_for_property_name(bool async) + { + await base.Filter_with_EF_Property_using_function_for_property_name(async); + + AssertSql( + @"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 `c`.`CustomerID` = 'ALFKI'"); + } + + public override async Task FirstOrDefault_over_scalar_projection_compared_to_null(bool async) + { + await base.FirstOrDefault_over_scalar_projection_compared_to_null(async); + + AssertSql( + @"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 ( + SELECT TOP 1 `o`.`OrderID` + FROM `Orders` AS `o` + WHERE `c`.`CustomerID` = `o`.`CustomerID`) IS NULL"); + } + + public override async Task FirstOrDefault_over_scalar_projection_compared_to_not_null(bool async) + { + await base.FirstOrDefault_over_scalar_projection_compared_to_not_null(async); + + AssertSql( + @"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 ( + SELECT TOP 1 `o`.`OrderID` + FROM `Orders` AS `o` + WHERE `c`.`CustomerID` = `o`.`CustomerID`) IS NOT NULL"); + } + + public override async Task FirstOrDefault_over_custom_projection_compared_to_null(bool async) + { + await base.FirstOrDefault_over_custom_projection_compared_to_null(async); + + AssertSql( + @"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 NOT (EXISTS ( + SELECT 1 + FROM `Orders` AS `o` + WHERE `c`.`CustomerID` = `o`.`CustomerID`))"); + } + + public override async Task FirstOrDefault_over_custom_projection_compared_to_not_null(bool async) + { + await base.FirstOrDefault_over_custom_projection_compared_to_not_null(async); + + AssertSql( + @"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 EXISTS ( + SELECT 1 + FROM `Orders` AS `o` + WHERE `c`.`CustomerID` = `o`.`CustomerID`)"); + } + + public override async Task SingleOrDefault_over_custom_projection_compared_to_null(bool async) + { + await base.SingleOrDefault_over_custom_projection_compared_to_null(async); + + AssertSql( + @"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 NOT (EXISTS ( + SELECT 1 + FROM `Orders` AS `o` + WHERE `c`.`CustomerID` = `o`.`CustomerID`))"); + } + + public override async Task SingleOrDefault_over_custom_projection_compared_to_not_null(bool async) + { + await base.SingleOrDefault_over_custom_projection_compared_to_not_null(async); + + AssertSql( + @"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 EXISTS ( + SELECT 1 + FROM `Orders` AS `o` + WHERE `c`.`CustomerID` = `o`.`CustomerID`)"); + } + + public override async Task LastOrDefault_over_custom_projection_compared_to_null(bool async) + { + await base.LastOrDefault_over_custom_projection_compared_to_null(async); + + AssertSql( + @"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 NOT (EXISTS ( + SELECT 1 + FROM `Orders` AS `o` + WHERE `c`.`CustomerID` = `o`.`CustomerID`))"); + } + + public override async Task LastOrDefault_over_custom_projection_compared_to_not_null(bool async) + { + await base.LastOrDefault_over_custom_projection_compared_to_not_null(async); + + AssertSql( + @"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 EXISTS ( + SELECT 1 + FROM `Orders` AS `o` + WHERE `c`.`CustomerID` = `o`.`CustomerID`)"); + } + + public override async Task First_over_custom_projection_compared_to_null(bool async) + { + await base.First_over_custom_projection_compared_to_null(async); + + AssertSql( + @"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 NOT (EXISTS ( + SELECT 1 + FROM `Orders` AS `o` + WHERE `c`.`CustomerID` = `o`.`CustomerID`))"); + } + + public override async Task First_over_custom_projection_compared_to_not_null(bool async) + { + await base.First_over_custom_projection_compared_to_not_null(async); + + AssertSql( + @"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 EXISTS ( + SELECT 1 + FROM `Orders` AS `o` + WHERE `c`.`CustomerID` = `o`.`CustomerID`)"); + } + + public override async Task Single_over_custom_projection_compared_to_null(bool async) + { + await base.Single_over_custom_projection_compared_to_null(async); + + AssertSql( + @"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 NOT (EXISTS ( + SELECT 1 + FROM `Orders` AS `o` + WHERE `c`.`CustomerID` = `o`.`CustomerID`))"); + } + + public override async Task Single_over_custom_projection_compared_to_not_null(bool async) + { + await base.Single_over_custom_projection_compared_to_not_null(async); + + AssertSql( + @"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 EXISTS ( + SELECT 1 + FROM `Orders` AS `o` + WHERE `c`.`CustomerID` = `o`.`CustomerID`)"); + } + + public override async Task Last_over_custom_projection_compared_to_null(bool async) + { + await base.Last_over_custom_projection_compared_to_null(async); + + AssertSql( + @"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 NOT (EXISTS ( + SELECT 1 + FROM `Orders` AS `o` + WHERE `c`.`CustomerID` = `o`.`CustomerID`))"); + } + + public override async Task Last_over_custom_projection_compared_to_not_null(bool async) + { + await base.Last_over_custom_projection_compared_to_not_null(async); + + AssertSql( + @"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 EXISTS ( + SELECT 1 + FROM `Orders` AS `o` + WHERE `c`.`CustomerID` = `o`.`CustomerID`)"); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); diff --git a/test/EFCore.Jet.FunctionalTests/Query/NullSemanticsQueryJetTest.cs b/test/EFCore.Jet.FunctionalTests/Query/NullSemanticsQueryJetTest.cs index c1975ce..92a59b3 100644 --- a/test/EFCore.Jet.FunctionalTests/Query/NullSemanticsQueryJetTest.cs +++ b/test/EFCore.Jet.FunctionalTests/Query/NullSemanticsQueryJetTest.cs @@ -207,11 +207,11 @@ WHERE `e`.`BoolA` <> `e`.`BoolB`", // $@"SELECT `e`.`Id` FROM `Entities1` AS `e` -WHERE (`e`.`BoolA` <> `e`.`NullableBoolB`) OR `e`.`NullableBoolB` IS NULL", +WHERE (`e`.`BoolA` <> `e`.`NullableBoolB`) OR (`e`.`NullableBoolB` IS NULL)", // $@"SELECT `e`.`Id` FROM `Entities1` AS `e` -WHERE (`e`.`NullableBoolA` <> `e`.`BoolB`) OR `e`.`NullableBoolA` IS NULL", +WHERE (`e`.`NullableBoolA` <> `e`.`BoolB`) OR (`e`.`NullableBoolA` IS NULL)", // $@"SELECT `e`.`Id` FROM `Entities1` AS `e` @@ -673,7 +673,7 @@ WHERE (`e`.`NullableStringA` = 'Foo') OR `e`.`NullableStringA` IS NULL"); await base.Where_multiple_ands_with_nullable_parameter_and_constant(async); AssertSql( - $@"{AssertSqlHelper.Declaration("@__prm3_2='Blah' (Size = 4000)")} + $@"{AssertSqlHelper.Declaration("@__prm3_2='Blah' (Size = 255)")} SELECT `e`.`Id` FROM `Entities1` AS `e` @@ -685,7 +685,7 @@ WHERE ((((`e`.`NullableStringA` <> 'Foo') OR `e`.`NullableStringA` IS NULL) AND await base.Where_multiple_ands_with_nullable_parameter_and_constant_not_optimized(async); AssertSql( - $@"{AssertSqlHelper.Declaration("@__prm3_2='Blah' (Size = 4000)")} + $@"{AssertSqlHelper.Declaration("@__prm3_2='Blah' (Size = 255)")} SELECT `e`.`Id` FROM `Entities1` AS `e` @@ -896,7 +896,7 @@ WHERE `e`.`NullableBoolA` = `e`.`NullableBoolB`"); AssertSql( $@"SELECT `e`.`Id` FROM `Entities1` AS `e` -WHERE `e`.`NullableBoolA` = True"); +WHERE `e`.`NullableBoolA` = TRUE"); } public override async Task Where_nullable_bool_equal_with_constant(bool async) @@ -906,7 +906,7 @@ WHERE `e`.`NullableBoolA` = True"); AssertSql( $@"SELECT `e`.`Id` FROM `Entities1` AS `e` -WHERE `e`.`NullableBoolA` = True"); +WHERE `e`.`NullableBoolA` = TRUE"); } public override async Task Where_nullable_bool_with_null_check(bool async) @@ -1082,7 +1082,7 @@ WHERE `e`.`StringA` = `e`.`StringB`"); await base.Projecting_nullable_bool_with_coalesce(async); AssertSql( - $@"SELECT `e`.`Id`, IIf(`e`.`NullableBoolA` IS NULL, NULL, `e`.`NullableBoolA`) AS `Coalesce` + $@"SELECT `e`.`Id`, IIF(`e`.`NullableBoolA` IS NULL, NULL, `e`.`NullableBoolA`) AS `Coalesce` FROM `Entities1` AS `e`"); } @@ -1091,7 +1091,7 @@ FROM `Entities1` AS `e`"); await base.Projecting_nullable_bool_with_coalesce_nested(async); AssertSql( - $@"SELECT `e`.`Id`, IIf(`e`.`NullableBoolA` IS NULL, NULL, `e`.`NullableBoolA`)) AS `Coalesce` + $@"SELECT `e`.`Id`, IIF(`e`.`NullableBoolA` IS NULL, NULL, `e`.`NullableBoolA`)) AS `Coalesce` FROM `Entities1` AS `e`"); } diff --git a/test/EFCore.Jet.FunctionalTests/Query/SqlExecutorJetTest.cs b/test/EFCore.Jet.FunctionalTests/Query/SqlExecutorJetTest.cs index 18e207e..7bbf7fa 100644 --- a/test/EFCore.Jet.FunctionalTests/Query/SqlExecutorJetTest.cs +++ b/test/EFCore.Jet.FunctionalTests/Query/SqlExecutorJetTest.cs @@ -1,6 +1,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System.Data.Common; +using System.Data.Odbc; using System.Threading.Tasks; using EntityFrameworkCore.Jet.Data; using System.Data.OleDb; @@ -53,9 +54,8 @@ namespace EntityFrameworkCore.Jet.FunctionalTests.Query base.Query_with_parameters(); AssertSql( - $@"{AssertSqlHelper.Declaration("@p0='London' (Size = 4000)")} - -{AssertSqlHelper.Declaration("@p1='Sales Representative' (Size = 4000)")} + $@"{AssertSqlHelper.Declaration("@p0='London' (Size = 255)")} +{AssertSqlHelper.Declaration("@p1='Sales Representative' (Size = 255)")} SELECT COUNT(*) FROM ""Customers"" WHERE ""City"" = {AssertSqlHelper.Parameter("@p0")} AND ""ContactTitle"" = {AssertSqlHelper.Parameter("@p1")}"); } @@ -95,15 +95,13 @@ SELECT COUNT(*) FROM ""Customers"" WHERE ""City"" = {AssertSqlHelper.Parameter(" base.Query_with_dbParameters_mixed(); AssertSql( - $@"{AssertSqlHelper.Declaration("@p0='London' (Size = 4000)")} - + $@"{AssertSqlHelper.Declaration("@p0='London' (Size = 255)")} {AssertSqlHelper.Declaration("@contactTitle='Sales Representative' (Nullable = false) (Size = 20)")} SELECT COUNT(*) FROM ""Customers"" WHERE ""City"" = {AssertSqlHelper.Parameter("@p0")} AND ""ContactTitle"" = {AssertSqlHelper.Parameter("@contactTitle")}", // $@"{AssertSqlHelper.Declaration("@city='London' (Nullable = false) (Size = 6)")} - -{AssertSqlHelper.Declaration("@p0='Sales Representative' (Size = 4000)")} +{AssertSqlHelper.Declaration("@p0='Sales Representative' (Size = 255)")} SELECT COUNT(*) FROM ""Customers"" WHERE ""City"" = {AssertSqlHelper.Parameter("@city")} AND ""ContactTitle"" = {AssertSqlHelper.Parameter("@p0")}"); } @@ -113,9 +111,8 @@ SELECT COUNT(*) FROM ""Customers"" WHERE ""City"" = {AssertSqlHelper.Parameter(" base.Query_with_parameters_interpolated(); AssertSql( - $@"{AssertSqlHelper.Declaration("@p0='London' (Size = 4000)")} - -{AssertSqlHelper.Declaration("@p1='Sales Representative' (Size = 4000)")} + $@"{AssertSqlHelper.Declaration("@p0='London' (Size = 255)")} +{AssertSqlHelper.Declaration("@p1='Sales Representative' (Size = 255)")} SELECT COUNT(*) FROM ""Customers"" WHERE ""City"" = {AssertSqlHelper.Parameter("@p0")} AND ""ContactTitle"" = {AssertSqlHelper.Parameter("@p1")}"); } @@ -125,9 +122,8 @@ SELECT COUNT(*) FROM ""Customers"" WHERE ""City"" = {AssertSqlHelper.Parameter(" await base.Query_with_parameters_async(); AssertSql( - $@"{AssertSqlHelper.Declaration("@p0='London' (Size = 4000)")} - -{AssertSqlHelper.Declaration("@p1='Sales Representative' (Size = 4000)")} + $@"{AssertSqlHelper.Declaration("@p0='London' (Size = 255)")} +{AssertSqlHelper.Declaration("@p1='Sales Representative' (Size = 255)")} SELECT COUNT(*) FROM ""Customers"" WHERE ""City"" = {AssertSqlHelper.Parameter("@p0")} AND ""ContactTitle"" = {AssertSqlHelper.Parameter("@p1")}"); } @@ -137,15 +133,14 @@ SELECT COUNT(*) FROM ""Customers"" WHERE ""City"" = {AssertSqlHelper.Parameter(" await base.Query_with_parameters_interpolated_async(); AssertSql( - $@"{AssertSqlHelper.Declaration("@p0='London' (Size = 4000)")} - -{AssertSqlHelper.Declaration("@p1='Sales Representative' (Size = 4000)")} + $@"{AssertSqlHelper.Declaration("@p0='London' (Size = 255)")} +{AssertSqlHelper.Declaration("@p1='Sales Representative' (Size = 255)")} SELECT COUNT(*) FROM ""Customers"" WHERE ""City"" = {AssertSqlHelper.Parameter("@p0")} AND ""ContactTitle"" = {AssertSqlHelper.Parameter("@p1")}"); } protected override DbParameter CreateDbParameter(string name, object value) - => new OleDbParameter { ParameterName = name, Value = value }; + => new OdbcParameter { ParameterName = name, Value = value }; protected override string TenMostExpensiveProductsSproc => "`Ten Most Expensive Products`"; protected override string CustomerOrderHistorySproc => "`CustOrderHist` @CustomerID"; diff --git a/test/EFCore.Jet.FunctionalTests/Scaffolding/JetDatabaseModelFactoryTest.cs b/test/EFCore.Jet.FunctionalTests/Scaffolding/JetDatabaseModelFactoryTest.cs index f83adcc..3b1af10 100644 --- a/test/EFCore.Jet.FunctionalTests/Scaffolding/JetDatabaseModelFactoryTest.cs +++ b/test/EFCore.Jet.FunctionalTests/Scaffolding/JetDatabaseModelFactoryTest.cs @@ -124,6 +124,7 @@ DROP TABLE `JustTableName`;"); #region Table + //Note - No table or column comments in Jet [ConditionalFact] public void Create_columns() { @@ -145,15 +146,15 @@ CREATE TABLE `Blogs` ( { Assert.Null(c.Table.Schema); Assert.Equal("Blogs", c.Table.Name); - Assert.Equal( + /*Assert.Equal( @"Blog table comment. -On multiple lines.", c.Table.Comment); +On multiple lines.", c.Table.Comment);*/ }); Assert.Single(table.Columns.Where(c => c.Name == "Id")); Assert.Single(table.Columns.Where(c => c.Name == "Name")); - Assert.Single(table.Columns.Where(c => c.Comment == "Blog.Id column comment.")); - Assert.Single(table.Columns.Where(c => c.Comment != null)); + //Assert.Single(table.Columns.Where(c => c.Comment == "Blog.Id column comment.")); + //Assert.Single(table.Columns.Where(c => c.Comment != null)); }, "DROP TABLE `Blogs`"); } @@ -332,7 +333,7 @@ DROP TABLE PrincipalTable;"); #region ColumnFacets - [ConditionalFact] + [ConditionalFact(Skip = "Jet does not support type aliases")] public void Column_with_type_alias_assigns_underlying_store_type() { Fixture.TestStore.ExecuteNonQuery( @@ -813,7 +814,7 @@ DROP TABLE NoFacetTypes; DROP TABLE RowversionType;"); } - [ConditionalFact] + [ConditionalFact(Skip = "Jet does not support storing computed values")] public void Default_and_computed_values_are_stored() { Test(