diff --git a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerByteArrayMethodTranslator.cs b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerByteArrayMethodTranslator.cs index c317e54eb08..e39444e3fd5 100644 --- a/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerByteArrayMethodTranslator.cs +++ b/src/EFCore.SqlServer/Query/Internal/Translators/SqlServerByteArrayMethodTranslator.cs @@ -16,21 +16,6 @@ public class SqlServerByteArrayMethodTranslator : IMethodCallTranslator { private readonly ISqlExpressionFactory _sqlExpressionFactory; - // NOTE: Might want to move these to a shared file, similar to EnumerableMethods - private static readonly MethodInfo IndexOfMethodInfo - = typeof(Array) - .GetGenericMethod(nameof(Array.IndexOf), 1, BindingFlags.Public | BindingFlags.Static, (_, t) => - { - return [t[0].MakeArrayType(), t[0]]; - })!; - - private static readonly MethodInfo IndexOfWithStartingPositionMethodInfo - = typeof(Array) - .GetGenericMethod(nameof(Array.IndexOf), 1, BindingFlags.Public | BindingFlags.Static, (_, t) => - { - return [t[0].MakeArrayType(), t[0], typeof(int)]; - })!; - /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in @@ -61,7 +46,6 @@ public SqlServerByteArrayMethodTranslator(ISqlExpressionFactory sqlExpressionFac var methodDefinition = method.GetGenericMethodDefinition(); if (methodDefinition.Equals(EnumerableMethods.Contains)) { - // NOTE: Should this be refactored to use the TranslateIndexOf method?? Everything is same expect one check var source = arguments[0]; var sourceTypeMapping = source.TypeMapping; @@ -91,12 +75,12 @@ public SqlServerByteArrayMethodTranslator(ISqlExpressionFactory sqlExpressionFac method.ReturnType); } - if (methodDefinition.Equals(IndexOfMethodInfo)) + if (methodDefinition.Equals(ArrayMethods.IndexOf)) { return TranslateIndexOf(method, arguments[0], arguments[1], null); } - if (methodDefinition.Equals(IndexOfWithStartingPositionMethodInfo)) + if (methodDefinition.Equals(ArrayMethods.IndexOfWithStartingPosition)) { return TranslateIndexOf(method, arguments[0], arguments[1], arguments[2]); } diff --git a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteByteArrayMethodTranslator.cs b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteByteArrayMethodTranslator.cs index d4e67d23a7c..5a7215a2b8d 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteByteArrayMethodTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/Translators/SqliteByteArrayMethodTranslator.cs @@ -40,28 +40,30 @@ public SqliteByteArrayMethodTranslator(ISqlExpressionFactory sqlExpressionFactor IDiagnosticsLogger logger) { if (method.IsGenericMethod - && method.GetGenericMethodDefinition().Equals(EnumerableMethods.Contains) + && arguments.Count >= 1 && arguments[0].Type == typeof(byte[])) { - var source = arguments[0]; + var genericMethodDefinition = method.GetGenericMethodDefinition(); + if (genericMethodDefinition.Equals(EnumerableMethods.Contains)) + { + return _sqlExpressionFactory.GreaterThan( + GetInStrSqlFunctionExpression(arguments[0], arguments[1]), + _sqlExpressionFactory.Constant(0)); - var value = arguments[1] is SqlConstantExpression constantValue - ? (SqlExpression)_sqlExpressionFactory.Constant(new[] { (byte)constantValue.Value! }, source.TypeMapping) - : _sqlExpressionFactory.Function( - "char", - new[] { arguments[1] }, - nullable: false, - argumentsPropagateNullability: new[] { false }, - typeof(string)); + } - return _sqlExpressionFactory.GreaterThan( - _sqlExpressionFactory.Function( - "instr", - new[] { source, value }, - nullable: true, - argumentsPropagateNullability: new[] { true, true }, - typeof(int)), - _sqlExpressionFactory.Constant(0)); + if (genericMethodDefinition.Equals(ArrayMethods.IndexOf)) + { + return _sqlExpressionFactory.Subtract( + GetInStrSqlFunctionExpression(arguments[0], arguments[1]), + _sqlExpressionFactory.Constant(1)); + } + + if (genericMethodDefinition.Equals(ArrayMethods.IndexOfWithStartingPosition)) + { + // NOTE: IndexOf Method with a starting position is not supported by SQLite + return null; + } } // See issue#16428 @@ -92,4 +94,23 @@ public SqliteByteArrayMethodTranslator(ISqlExpressionFactory sqlExpressionFactor return null; } + + private SqlExpression GetInStrSqlFunctionExpression(SqlExpression source, SqlExpression valueToSearch) + { + var value = valueToSearch is SqlConstantExpression { Value: byte constantValue } + ? _sqlExpressionFactory.Constant(new byte[] { constantValue }, source.TypeMapping) + : _sqlExpressionFactory.Function( + "char", + [valueToSearch], + nullable: false, + argumentsPropagateNullability: [false], + typeof(string)); + + return _sqlExpressionFactory.Function( + "instr", + [source, value], + nullable: true, + argumentsPropagateNullability: [true, true], + typeof(int)); + } } diff --git a/src/Shared/ArrayMethods.cs b/src/Shared/ArrayMethods.cs new file mode 100644 index 00000000000..220481c7679 --- /dev/null +++ b/src/Shared/ArrayMethods.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.EntityFrameworkCore; + +internal static class ArrayMethods +{ + public static MethodInfo IndexOf { get; } + + public static MethodInfo IndexOfWithStartingPosition { get; } + + static ArrayMethods() + { + var arrayGenericMethods = typeof(Array) + .GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly) + .Where(m => m.IsGenericMethod) + .GroupBy(m => m.Name) + .ToDictionary(m => m.Key, l => l.ToList()); + + IndexOf = GetMethod(nameof(Array.IndexOf), 1, (t) => + { + return [t[0].MakeArrayType(), t[0]]; + }); + + IndexOfWithStartingPosition = GetMethod(nameof(Array.IndexOf), 1, (t) => + { + return [t[0].MakeArrayType(), t[0], typeof(int)]; + }); + + MethodInfo GetMethod(string name, int genericParameterCount, Func parameterGenerator) + => arrayGenericMethods[name].Single( + mi => mi.IsGenericMethod && mi.GetGenericArguments().Length == genericParameterCount + && mi.GetParameters().Select(e => e.ParameterType).SequenceEqual( + parameterGenerator(mi.IsGenericMethod ? mi.GetGenericArguments() : []))); + } +} diff --git a/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs index c0304cffe59..45d1eaf997e 100644 --- a/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs @@ -6263,18 +6263,16 @@ public virtual Task Byte_array_filter_by_length_parameter(bool async) [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual Task Byte_array_of_type_varbinary_max_filter_by_index_of_literal_casts_to_int(bool async) - { - return AssertQuery( + public virtual Task Byte_array_with_max_possible_length_filter_by_index_of_literal(bool async) + => AssertQuery( async, ss => ss.Set().Where(w => Array.IndexOf(w.Banner, (byte)1) == 1), ss => ss.Set().Where(w => w.Banner != null && Array.IndexOf(w.Banner, (byte)1) == 1) ); - } [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual Task Byte_array_of_type_varbinary_max_filter_by_index_of_parameter_casts_to_int(bool async) + public virtual Task Byte_array_with_max_possible_length_filter_by_index_of_parameter(bool async) { byte b = 0; return AssertQuery( @@ -6286,18 +6284,16 @@ public virtual Task Byte_array_of_type_varbinary_max_filter_by_index_of_paramete [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual Task Byte_array_of_type_varbinary_n_filter_by_index_of_literal_does_not_cast(bool async) - { - return AssertQuery( + public virtual Task Byte_array_with_length_n_filter_by_index_of_literal(bool async) + => AssertQuery( async, ss => ss.Set().Where(w => Array.IndexOf(w.Banner5, (byte)5) == 1), ss => ss.Set().Where(w => w.Banner != null && Array.IndexOf(w.Banner5, (byte)5) == 1) ); - } [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual Task Byte_array_of_type_varbinary_n_filter_by_index_of_parameter_does_not_cast(bool async) + public virtual Task Byte_array_with_lenght_n_filter_by_index_of_parameter(bool async) { byte b = 4; return AssertQuery( @@ -6309,21 +6305,19 @@ public virtual Task Byte_array_of_type_varbinary_n_filter_by_index_of_parameter_ [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual Task Byte_array_of_type_varbinary_max_filter_by_index_of_with_starting_position_literal_casts_to_int(bool async) - { - return AssertQuery( + public virtual Task Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position(bool async) + => AssertQuery( async, ss => ss.Set().Where(w => Array.IndexOf(w.Banner, (byte)1, 1) == 1), ss => ss.Set().Where(w => w.Banner != null && Array.IndexOf(w.Banner, (byte)1, 1) == 1) ); - } [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual Task Byte_array_of_type_varbinary_max_filter_by_index_of_with_starting_position_parameter_casts_to_int(bool async) + public virtual Task Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position_parameter(bool async) { byte b = 0; - int startPos = 0; + var startPos = 0; return AssertQuery( async, ss => ss.Set().Where(w => Array.IndexOf(w.Banner, b, startPos) == 0), @@ -6333,21 +6327,19 @@ public virtual Task Byte_array_of_type_varbinary_max_filter_by_index_of_with_sta [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual Task Byte_array_of_type_varbinary_n_filter_by_index_of_with_starting_position_literal_does_not_cast(bool async) - { - return AssertQuery( + public virtual Task Byte_array_with_length_n_filter_by_index_of_with_starting_position_literal(bool async) + => AssertQuery( async, ss => ss.Set().Where(w => Array.IndexOf(w.Banner5, (byte)5, 1) == 1), ss => ss.Set().Where(w => w.Banner != null && Array.IndexOf(w.Banner5, (byte)5, 1) == 1) ); - } [ConditionalTheory] [MemberData(nameof(IsAsyncData))] - public virtual Task Byte_array_of_type_varbinary_n_filter_by_index_of_with_starting_position_parameter_does_not_cast(bool async) + public virtual Task Byte_array_with_length_n_filter_by_index_of_with_starting_position_parameter(bool async) { byte b = 4; - int startPos = 0; + var startPos = 0; return AssertQuery( async, ss => ss.Set().Where(w => Array.IndexOf(w.Banner5, b, startPos) == 0), diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs index f7370739a85..f490b9a2adc 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs @@ -7678,9 +7678,9 @@ WHERE DATALENGTH([s].[Banner5]) = 5 #region Byte Array IndexOf Translation - public override async Task Byte_array_of_type_varbinary_max_filter_by_index_of_literal_casts_to_int(bool async) + public override async Task Byte_array_with_max_possible_length_filter_by_index_of_literal(bool async) { - await base.Byte_array_of_type_varbinary_max_filter_by_index_of_literal_casts_to_int(async); + await base.Byte_array_with_max_possible_length_filter_by_index_of_literal(async); AssertSql( """ @@ -7690,9 +7690,9 @@ WHERE CAST(CHARINDEX(0x01, [s].[Banner]) AS int) - 1 = 1 """); } - public override async Task Byte_array_of_type_varbinary_max_filter_by_index_of_parameter_casts_to_int(bool async) + public override async Task Byte_array_with_max_possible_length_filter_by_index_of_parameter(bool async) { - await base.Byte_array_of_type_varbinary_max_filter_by_index_of_parameter_casts_to_int(async); + await base.Byte_array_with_max_possible_length_filter_by_index_of_parameter(async); AssertSql( """ @@ -7704,9 +7704,9 @@ WHERE CAST(CHARINDEX(CAST(@__b_0 AS varbinary(max)), [s].[Banner]) AS int) - 1 = """); } - public override async Task Byte_array_of_type_varbinary_n_filter_by_index_of_literal_does_not_cast(bool async) + public override async Task Byte_array_with_length_n_filter_by_index_of_literal(bool async) { - await base.Byte_array_of_type_varbinary_n_filter_by_index_of_literal_does_not_cast(async); + await base.Byte_array_with_length_n_filter_by_index_of_literal(async); AssertSql( """ @@ -7716,9 +7716,9 @@ WHERE CHARINDEX(0x05, [s].[Banner5]) - 1 = 1 """); } - public override async Task Byte_array_of_type_varbinary_n_filter_by_index_of_parameter_does_not_cast(bool async) + public override async Task Byte_array_with_lenght_n_filter_by_index_of_parameter(bool async) { - await base.Byte_array_of_type_varbinary_n_filter_by_index_of_parameter_does_not_cast(async); + await base.Byte_array_with_lenght_n_filter_by_index_of_parameter(async); AssertSql( """ @@ -7730,9 +7730,9 @@ WHERE CHARINDEX(CAST(@__b_0 AS varbinary(5)), [s].[Banner5]) - 1 = 0 """); } - public override async Task Byte_array_of_type_varbinary_max_filter_by_index_of_with_starting_position_literal_casts_to_int(bool async) + public override async Task Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position(bool async) { - await base.Byte_array_of_type_varbinary_max_filter_by_index_of_with_starting_position_literal_casts_to_int(async); + await base.Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position(async); AssertSql( """ @@ -7742,9 +7742,9 @@ WHERE CAST(CHARINDEX(0x01, [s].[Banner], 2) AS int) - 1 = 1 """); } - public override async Task Byte_array_of_type_varbinary_max_filter_by_index_of_with_starting_position_parameter_casts_to_int(bool async) + public override async Task Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position_parameter(bool async) { - await base.Byte_array_of_type_varbinary_max_filter_by_index_of_with_starting_position_parameter_casts_to_int(async); + await base.Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position_parameter(async); AssertSql( """ @@ -7757,9 +7757,9 @@ WHERE CAST(CHARINDEX(CAST(@__b_0 AS varbinary(max)), [s].[Banner], @__startPos_1 """); } - public override async Task Byte_array_of_type_varbinary_n_filter_by_index_of_with_starting_position_literal_does_not_cast(bool async) + public override async Task Byte_array_with_length_n_filter_by_index_of_with_starting_position_literal(bool async) { - await base.Byte_array_of_type_varbinary_n_filter_by_index_of_with_starting_position_literal_does_not_cast(async); + await base.Byte_array_with_length_n_filter_by_index_of_with_starting_position_literal(async); AssertSql( """ @@ -7769,9 +7769,9 @@ WHERE CHARINDEX(0x05, [s].[Banner5], 2) - 1 = 1 """); } - public override async Task Byte_array_of_type_varbinary_n_filter_by_index_of_with_starting_position_parameter_does_not_cast(bool async) + public override async Task Byte_array_with_length_n_filter_by_index_of_with_starting_position_parameter(bool async) { - await base.Byte_array_of_type_varbinary_n_filter_by_index_of_with_starting_position_parameter_does_not_cast(async); + await base.Byte_array_with_length_n_filter_by_index_of_with_starting_position_parameter(async); AssertSql( """ diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TPCGearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TPCGearsOfWarQuerySqlServerTest.cs index 8f12ed4fa79..bfc654dd4d2 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TPCGearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TPCGearsOfWarQuerySqlServerTest.cs @@ -10222,9 +10222,9 @@ WHERE DATALENGTH([s].[Banner5]) = 5 #region Byte Array IndexOf Translation - public override async Task Byte_array_of_type_varbinary_max_filter_by_index_of_literal_casts_to_int(bool async) + public override async Task Byte_array_with_max_possible_length_filter_by_index_of_literal(bool async) { - await base.Byte_array_of_type_varbinary_max_filter_by_index_of_literal_casts_to_int(async); + await base.Byte_array_with_max_possible_length_filter_by_index_of_literal(async); AssertSql( """ @@ -10234,9 +10234,9 @@ WHERE CAST(CHARINDEX(0x01, [s].[Banner]) AS int) - 1 = 1 """); } - public override async Task Byte_array_of_type_varbinary_max_filter_by_index_of_parameter_casts_to_int(bool async) + public override async Task Byte_array_with_max_possible_length_filter_by_index_of_parameter(bool async) { - await base.Byte_array_of_type_varbinary_max_filter_by_index_of_parameter_casts_to_int(async); + await base.Byte_array_with_max_possible_length_filter_by_index_of_parameter(async); AssertSql( """ @@ -10248,9 +10248,9 @@ WHERE CAST(CHARINDEX(CAST(@__b_0 AS varbinary(max)), [s].[Banner]) AS int) - 1 = """); } - public override async Task Byte_array_of_type_varbinary_n_filter_by_index_of_literal_does_not_cast(bool async) + public override async Task Byte_array_with_length_n_filter_by_index_of_literal(bool async) { - await base.Byte_array_of_type_varbinary_n_filter_by_index_of_literal_does_not_cast(async); + await base.Byte_array_with_length_n_filter_by_index_of_literal(async); AssertSql( """ @@ -10260,9 +10260,9 @@ WHERE CHARINDEX(0x05, [s].[Banner5]) - 1 = 1 """); } - public override async Task Byte_array_of_type_varbinary_n_filter_by_index_of_parameter_does_not_cast(bool async) + public override async Task Byte_array_with_lenght_n_filter_by_index_of_parameter(bool async) { - await base.Byte_array_of_type_varbinary_n_filter_by_index_of_parameter_does_not_cast(async); + await base.Byte_array_with_lenght_n_filter_by_index_of_parameter(async); AssertSql( """ @@ -10274,9 +10274,9 @@ WHERE CHARINDEX(CAST(@__b_0 AS varbinary(5)), [s].[Banner5]) - 1 = 0 """); } - public override async Task Byte_array_of_type_varbinary_max_filter_by_index_of_with_starting_position_literal_casts_to_int(bool async) + public override async Task Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position(bool async) { - await base.Byte_array_of_type_varbinary_max_filter_by_index_of_with_starting_position_literal_casts_to_int(async); + await base.Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position(async); AssertSql( """ @@ -10286,9 +10286,9 @@ WHERE CAST(CHARINDEX(0x01, [s].[Banner], 2) AS int) - 1 = 1 """); } - public override async Task Byte_array_of_type_varbinary_max_filter_by_index_of_with_starting_position_parameter_casts_to_int(bool async) + public override async Task Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position_parameter(bool async) { - await base.Byte_array_of_type_varbinary_max_filter_by_index_of_with_starting_position_parameter_casts_to_int(async); + await base.Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position_parameter(async); AssertSql( """ @@ -10301,9 +10301,9 @@ WHERE CAST(CHARINDEX(CAST(@__b_0 AS varbinary(max)), [s].[Banner], @__startPos_1 """); } - public override async Task Byte_array_of_type_varbinary_n_filter_by_index_of_with_starting_position_literal_does_not_cast(bool async) + public override async Task Byte_array_with_length_n_filter_by_index_of_with_starting_position_literal(bool async) { - await base.Byte_array_of_type_varbinary_n_filter_by_index_of_with_starting_position_literal_does_not_cast(async); + await base.Byte_array_with_length_n_filter_by_index_of_with_starting_position_literal(async); AssertSql( """ @@ -10313,9 +10313,9 @@ WHERE CHARINDEX(0x05, [s].[Banner5], 2) - 1 = 1 """); } - public override async Task Byte_array_of_type_varbinary_n_filter_by_index_of_with_starting_position_parameter_does_not_cast(bool async) + public override async Task Byte_array_with_length_n_filter_by_index_of_with_starting_position_parameter(bool async) { - await base.Byte_array_of_type_varbinary_n_filter_by_index_of_with_starting_position_parameter_does_not_cast(async); + await base.Byte_array_with_length_n_filter_by_index_of_with_starting_position_parameter(async); AssertSql( """ diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs index e898569764e..59fe339674c 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs @@ -8688,9 +8688,9 @@ WHERE DATALENGTH([s].[Banner5]) = 5 #region Byte Array IndexOf Translation - public override async Task Byte_array_of_type_varbinary_max_filter_by_index_of_literal_casts_to_int(bool async) + public override async Task Byte_array_with_max_possible_length_filter_by_index_of_literal(bool async) { - await base.Byte_array_of_type_varbinary_max_filter_by_index_of_literal_casts_to_int(async); + await base.Byte_array_with_max_possible_length_filter_by_index_of_literal(async); AssertSql( """ @@ -8700,9 +8700,9 @@ WHERE CAST(CHARINDEX(0x01, [s].[Banner]) AS int) - 1 = 1 """); } - public override async Task Byte_array_of_type_varbinary_max_filter_by_index_of_parameter_casts_to_int(bool async) + public override async Task Byte_array_with_max_possible_length_filter_by_index_of_parameter(bool async) { - await base.Byte_array_of_type_varbinary_max_filter_by_index_of_parameter_casts_to_int(async); + await base.Byte_array_with_max_possible_length_filter_by_index_of_parameter(async); AssertSql( """ @@ -8714,9 +8714,9 @@ WHERE CAST(CHARINDEX(CAST(@__b_0 AS varbinary(max)), [s].[Banner]) AS int) - 1 = """); } - public override async Task Byte_array_of_type_varbinary_n_filter_by_index_of_literal_does_not_cast(bool async) + public override async Task Byte_array_with_length_n_filter_by_index_of_literal(bool async) { - await base.Byte_array_of_type_varbinary_n_filter_by_index_of_literal_does_not_cast(async); + await base.Byte_array_with_length_n_filter_by_index_of_literal(async); AssertSql( """ @@ -8726,9 +8726,9 @@ WHERE CHARINDEX(0x05, [s].[Banner5]) - 1 = 1 """); } - public override async Task Byte_array_of_type_varbinary_n_filter_by_index_of_parameter_does_not_cast(bool async) + public override async Task Byte_array_with_lenght_n_filter_by_index_of_parameter(bool async) { - await base.Byte_array_of_type_varbinary_n_filter_by_index_of_parameter_does_not_cast(async); + await base.Byte_array_with_lenght_n_filter_by_index_of_parameter(async); AssertSql( """ @@ -8740,9 +8740,9 @@ WHERE CHARINDEX(CAST(@__b_0 AS varbinary(5)), [s].[Banner5]) - 1 = 0 """); } - public override async Task Byte_array_of_type_varbinary_max_filter_by_index_of_with_starting_position_literal_casts_to_int(bool async) + public override async Task Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position(bool async) { - await base.Byte_array_of_type_varbinary_max_filter_by_index_of_with_starting_position_literal_casts_to_int(async); + await base.Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position(async); AssertSql( """ @@ -8752,9 +8752,9 @@ WHERE CAST(CHARINDEX(0x01, [s].[Banner], 2) AS int) - 1 = 1 """); } - public override async Task Byte_array_of_type_varbinary_max_filter_by_index_of_with_starting_position_parameter_casts_to_int(bool async) + public override async Task Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position_parameter(bool async) { - await base.Byte_array_of_type_varbinary_max_filter_by_index_of_with_starting_position_parameter_casts_to_int(async); + await base.Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position_parameter(async); AssertSql( """ @@ -8767,9 +8767,9 @@ WHERE CAST(CHARINDEX(CAST(@__b_0 AS varbinary(max)), [s].[Banner], @__startPos_1 """); } - public override async Task Byte_array_of_type_varbinary_n_filter_by_index_of_with_starting_position_literal_does_not_cast(bool async) + public override async Task Byte_array_with_length_n_filter_by_index_of_with_starting_position_literal(bool async) { - await base.Byte_array_of_type_varbinary_n_filter_by_index_of_with_starting_position_literal_does_not_cast(async); + await base.Byte_array_with_length_n_filter_by_index_of_with_starting_position_literal(async); AssertSql( """ @@ -8779,9 +8779,9 @@ WHERE CHARINDEX(0x05, [s].[Banner5], 2) - 1 = 1 """); } - public override async Task Byte_array_of_type_varbinary_n_filter_by_index_of_with_starting_position_parameter_does_not_cast(bool async) + public override async Task Byte_array_with_length_n_filter_by_index_of_with_starting_position_parameter(bool async) { - await base.Byte_array_of_type_varbinary_n_filter_by_index_of_with_starting_position_parameter_does_not_cast(async); + await base.Byte_array_with_length_n_filter_by_index_of_with_starting_position_parameter(async); AssertSql( """ diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TemporalGearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TemporalGearsOfWarQuerySqlServerTest.cs index 45441c6807b..7f7d8789fc8 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TemporalGearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TemporalGearsOfWarQuerySqlServerTest.cs @@ -3264,9 +3264,9 @@ WHEN [t].[GearNickName] IS NOT NULL THEN [g].[Nickname] #region Byte Array IndexOf Translation - public override async Task Byte_array_of_type_varbinary_max_filter_by_index_of_literal_casts_to_int(bool async) + public override async Task Byte_array_with_max_possible_length_filter_by_index_of_literal(bool async) { - await base.Byte_array_of_type_varbinary_max_filter_by_index_of_literal_casts_to_int(async); + await base.Byte_array_with_max_possible_length_filter_by_index_of_literal(async); AssertSql( """ @@ -3276,9 +3276,9 @@ WHERE CAST(CHARINDEX(0x01, [s].[Banner]) AS int) - 1 = 1 """); } - public override async Task Byte_array_of_type_varbinary_max_filter_by_index_of_parameter_casts_to_int(bool async) + public override async Task Byte_array_with_max_possible_length_filter_by_index_of_parameter(bool async) { - await base.Byte_array_of_type_varbinary_max_filter_by_index_of_parameter_casts_to_int(async); + await base.Byte_array_with_max_possible_length_filter_by_index_of_parameter(async); AssertSql( """ @@ -3290,9 +3290,9 @@ WHERE CAST(CHARINDEX(CAST(@__b_0 AS varbinary(max)), [s].[Banner]) AS int) - 1 = """); } - public override async Task Byte_array_of_type_varbinary_n_filter_by_index_of_literal_does_not_cast(bool async) + public override async Task Byte_array_with_length_n_filter_by_index_of_literal(bool async) { - await base.Byte_array_of_type_varbinary_n_filter_by_index_of_literal_does_not_cast(async); + await base.Byte_array_with_length_n_filter_by_index_of_literal(async); AssertSql( """ @@ -3302,9 +3302,9 @@ WHERE CHARINDEX(0x05, [s].[Banner5]) - 1 = 1 """); } - public override async Task Byte_array_of_type_varbinary_n_filter_by_index_of_parameter_does_not_cast(bool async) + public override async Task Byte_array_with_lenght_n_filter_by_index_of_parameter(bool async) { - await base.Byte_array_of_type_varbinary_n_filter_by_index_of_parameter_does_not_cast(async); + await base.Byte_array_with_lenght_n_filter_by_index_of_parameter(async); AssertSql( """ @@ -3316,9 +3316,9 @@ WHERE CHARINDEX(CAST(@__b_0 AS varbinary(5)), [s].[Banner5]) - 1 = 0 """); } - public override async Task Byte_array_of_type_varbinary_max_filter_by_index_of_with_starting_position_literal_casts_to_int(bool async) + public override async Task Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position(bool async) { - await base.Byte_array_of_type_varbinary_max_filter_by_index_of_with_starting_position_literal_casts_to_int(async); + await base.Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position(async); AssertSql( """ @@ -3328,9 +3328,9 @@ WHERE CAST(CHARINDEX(0x01, [s].[Banner], 2) AS int) - 1 = 1 """); } - public override async Task Byte_array_of_type_varbinary_max_filter_by_index_of_with_starting_position_parameter_casts_to_int(bool async) + public override async Task Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position_parameter(bool async) { - await base.Byte_array_of_type_varbinary_max_filter_by_index_of_with_starting_position_parameter_casts_to_int(async); + await base.Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position_parameter(async); AssertSql( """ @@ -3343,9 +3343,9 @@ WHERE CAST(CHARINDEX(CAST(@__b_0 AS varbinary(max)), [s].[Banner], @__startPos_1 """); } - public override async Task Byte_array_of_type_varbinary_n_filter_by_index_of_with_starting_position_literal_does_not_cast(bool async) + public override async Task Byte_array_with_length_n_filter_by_index_of_with_starting_position_literal(bool async) { - await base.Byte_array_of_type_varbinary_n_filter_by_index_of_with_starting_position_literal_does_not_cast(async); + await base.Byte_array_with_length_n_filter_by_index_of_with_starting_position_literal(async); AssertSql( """ @@ -3355,9 +3355,9 @@ WHERE CHARINDEX(0x05, [s].[Banner5], 2) - 1 = 1 """); } - public override async Task Byte_array_of_type_varbinary_n_filter_by_index_of_with_starting_position_parameter_does_not_cast(bool async) + public override async Task Byte_array_with_length_n_filter_by_index_of_with_starting_position_parameter(bool async) { - await base.Byte_array_of_type_varbinary_n_filter_by_index_of_with_starting_position_parameter_does_not_cast(async); + await base.Byte_array_with_length_n_filter_by_index_of_with_starting_position_parameter(async); AssertSql( """ diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/GearsOfWarQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/GearsOfWarQuerySqliteTest.cs index b6a8aef4253..a2422a2dfeb 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/GearsOfWarQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/GearsOfWarQuerySqliteTest.cs @@ -438,48 +438,70 @@ WHERE length("s"."Banner") = length(@__byteArrayParam) #region Byte Array IndexOf Translation - // TODO: These tests need to be updated when the translation for IndexOf has been added - - public override Task Byte_array_of_type_varbinary_max_filter_by_index_of_literal_casts_to_int(bool async) + public override async Task Byte_array_with_max_possible_length_filter_by_index_of_literal(bool async) { - return Task.CompletedTask; - } + await base.Byte_array_with_max_possible_length_filter_by_index_of_literal(async); - public override Task Byte_array_of_type_varbinary_max_filter_by_index_of_parameter_casts_to_int(bool async) - { - return Task.CompletedTask; + AssertSql( + """ +SELECT "s"."Id", "s"."Banner", "s"."Banner5", "s"."InternalNumber", "s"."Name" +FROM "Squads" AS "s" +WHERE instr("s"."Banner", X'01') - 1 = 1 +"""); } - public override Task Byte_array_of_type_varbinary_n_filter_by_index_of_literal_does_not_cast(bool async) + public override async Task Byte_array_with_max_possible_length_filter_by_index_of_parameter(bool async) { - return Task.CompletedTask; - } + await base.Byte_array_with_max_possible_length_filter_by_index_of_parameter(async); - public override Task Byte_array_of_type_varbinary_n_filter_by_index_of_parameter_does_not_cast(bool async) - { - return Task.CompletedTask; - } + AssertSql( + """ +@__b_0='0' - public override Task Byte_array_of_type_varbinary_max_filter_by_index_of_with_starting_position_literal_casts_to_int(bool async) - { - return Task.CompletedTask; +SELECT "s"."Id", "s"."Banner", "s"."Banner5", "s"."InternalNumber", "s"."Name" +FROM "Squads" AS "s" +WHERE instr("s"."Banner", char(@__b_0)) - 1 = 0 +"""); } - public override Task Byte_array_of_type_varbinary_max_filter_by_index_of_with_starting_position_parameter_casts_to_int(bool async) + public override async Task Byte_array_with_length_n_filter_by_index_of_literal(bool async) { - return Task.CompletedTask; - } + await base.Byte_array_with_length_n_filter_by_index_of_literal(async); - public override Task Byte_array_of_type_varbinary_n_filter_by_index_of_with_starting_position_literal_does_not_cast(bool async) - { - return Task.CompletedTask; + AssertSql( + """ +SELECT "s"."Id", "s"."Banner", "s"."Banner5", "s"."InternalNumber", "s"."Name" +FROM "Squads" AS "s" +WHERE instr("s"."Banner5", X'05') - 1 = 1 +"""); } - public override Task Byte_array_of_type_varbinary_n_filter_by_index_of_with_starting_position_parameter_does_not_cast(bool async) + public override async Task Byte_array_with_lenght_n_filter_by_index_of_parameter(bool async) { - return Task.CompletedTask; + await base.Byte_array_with_lenght_n_filter_by_index_of_parameter(async); + + AssertSql( + """ +@__b_0='4' + +SELECT "s"."Id", "s"."Banner", "s"."Banner5", "s"."InternalNumber", "s"."Name" +FROM "Squads" AS "s" +WHERE instr("s"."Banner5", char(@__b_0)) - 1 = 0 +"""); } + public override Task Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position(bool async) + => AssertTranslationFailed(() => base.Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position(async)); + + public override Task Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position_parameter(bool async) + => AssertTranslationFailed(() => base.Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position_parameter(async)); + + public override Task Byte_array_with_length_n_filter_by_index_of_with_starting_position_literal(bool async) + => AssertTranslationFailed(() => base.Byte_array_with_length_n_filter_by_index_of_with_starting_position_literal(async)); + + public override Task Byte_array_with_length_n_filter_by_index_of_with_starting_position_parameter(bool async) + => AssertTranslationFailed(() => base.Byte_array_with_length_n_filter_by_index_of_with_starting_position_parameter(async)); + #endregion public override async Task Byte_array_filter_by_SequenceEqual(bool async) diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/TPCGearsOfWarQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/TPCGearsOfWarQuerySqliteTest.cs index b536c518efd..75200b370b4 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/TPCGearsOfWarQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/TPCGearsOfWarQuerySqliteTest.cs @@ -303,48 +303,70 @@ public override async Task Byte_array_filter_by_SequenceEqual(bool async) #region Byte Array IndexOf Translation - // TODO: These tests need to be updated when the translation for IndexOf has been added - - public override Task Byte_array_of_type_varbinary_max_filter_by_index_of_literal_casts_to_int(bool async) + public override async Task Byte_array_with_max_possible_length_filter_by_index_of_literal(bool async) { - return Task.CompletedTask; - } + await base.Byte_array_with_max_possible_length_filter_by_index_of_literal(async); - public override Task Byte_array_of_type_varbinary_max_filter_by_index_of_parameter_casts_to_int(bool async) - { - return Task.CompletedTask; + AssertSql( + """ +SELECT "s"."Id", "s"."Banner", "s"."Banner5", "s"."InternalNumber", "s"."Name" +FROM "Squads" AS "s" +WHERE instr("s"."Banner", X'01') - 1 = 1 +"""); } - public override Task Byte_array_of_type_varbinary_n_filter_by_index_of_literal_does_not_cast(bool async) + public override async Task Byte_array_with_max_possible_length_filter_by_index_of_parameter(bool async) { - return Task.CompletedTask; - } + await base.Byte_array_with_max_possible_length_filter_by_index_of_parameter(async); - public override Task Byte_array_of_type_varbinary_n_filter_by_index_of_parameter_does_not_cast(bool async) - { - return Task.CompletedTask; - } + AssertSql( + """ +@__b_0='0' - public override Task Byte_array_of_type_varbinary_max_filter_by_index_of_with_starting_position_literal_casts_to_int(bool async) - { - return Task.CompletedTask; +SELECT "s"."Id", "s"."Banner", "s"."Banner5", "s"."InternalNumber", "s"."Name" +FROM "Squads" AS "s" +WHERE instr("s"."Banner", char(@__b_0)) - 1 = 0 +"""); } - public override Task Byte_array_of_type_varbinary_max_filter_by_index_of_with_starting_position_parameter_casts_to_int(bool async) + public override async Task Byte_array_with_length_n_filter_by_index_of_literal(bool async) { - return Task.CompletedTask; - } + await base.Byte_array_with_length_n_filter_by_index_of_literal(async); - public override Task Byte_array_of_type_varbinary_n_filter_by_index_of_with_starting_position_literal_does_not_cast(bool async) - { - return Task.CompletedTask; + AssertSql( + """ +SELECT "s"."Id", "s"."Banner", "s"."Banner5", "s"."InternalNumber", "s"."Name" +FROM "Squads" AS "s" +WHERE instr("s"."Banner5", X'05') - 1 = 1 +"""); } - public override Task Byte_array_of_type_varbinary_n_filter_by_index_of_with_starting_position_parameter_does_not_cast(bool async) + public override async Task Byte_array_with_lenght_n_filter_by_index_of_parameter(bool async) { - return Task.CompletedTask; + await base.Byte_array_with_lenght_n_filter_by_index_of_parameter(async); + + AssertSql( + """ +@__b_0='4' + +SELECT "s"."Id", "s"."Banner", "s"."Banner5", "s"."InternalNumber", "s"."Name" +FROM "Squads" AS "s" +WHERE instr("s"."Banner5", char(@__b_0)) - 1 = 0 +"""); } + public override Task Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position(bool async) + => AssertTranslationFailed(() => base.Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position(async)); + + public override Task Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position_parameter(bool async) + => AssertTranslationFailed(() => base.Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position_parameter(async)); + + public override Task Byte_array_with_length_n_filter_by_index_of_with_starting_position_literal(bool async) + => AssertTranslationFailed(() => base.Byte_array_with_length_n_filter_by_index_of_with_starting_position_literal(async)); + + public override Task Byte_array_with_length_n_filter_by_index_of_with_starting_position_parameter(bool async) + => AssertTranslationFailed(() => base.Byte_array_with_length_n_filter_by_index_of_with_starting_position_parameter(async)); + #endregion public override Task Where_TimeSpan_Hours(bool async) diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/TPTGearsOfWarQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/TPTGearsOfWarQuerySqliteTest.cs index c4bac47a2a2..641aee7f7db 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/TPTGearsOfWarQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/TPTGearsOfWarQuerySqliteTest.cs @@ -303,48 +303,70 @@ public override async Task Byte_array_filter_by_SequenceEqual(bool async) #region Byte Array IndexOf Translation - // TODO: These tests need to be updated when the translation for IndexOf has been added - - public override Task Byte_array_of_type_varbinary_max_filter_by_index_of_literal_casts_to_int(bool async) + public override async Task Byte_array_with_max_possible_length_filter_by_index_of_literal(bool async) { - return Task.CompletedTask; - } + await base.Byte_array_with_max_possible_length_filter_by_index_of_literal(async); - public override Task Byte_array_of_type_varbinary_max_filter_by_index_of_parameter_casts_to_int(bool async) - { - return Task.CompletedTask; + AssertSql( + """ +SELECT "s"."Id", "s"."Banner", "s"."Banner5", "s"."InternalNumber", "s"."Name" +FROM "Squads" AS "s" +WHERE instr("s"."Banner", X'01') - 1 = 1 +"""); } - public override Task Byte_array_of_type_varbinary_n_filter_by_index_of_literal_does_not_cast(bool async) + public override async Task Byte_array_with_max_possible_length_filter_by_index_of_parameter(bool async) { - return Task.CompletedTask; - } + await base.Byte_array_with_max_possible_length_filter_by_index_of_parameter(async); - public override Task Byte_array_of_type_varbinary_n_filter_by_index_of_parameter_does_not_cast(bool async) - { - return Task.CompletedTask; - } + AssertSql( + """ +@__b_0='0' - public override Task Byte_array_of_type_varbinary_max_filter_by_index_of_with_starting_position_literal_casts_to_int(bool async) - { - return Task.CompletedTask; +SELECT "s"."Id", "s"."Banner", "s"."Banner5", "s"."InternalNumber", "s"."Name" +FROM "Squads" AS "s" +WHERE instr("s"."Banner", char(@__b_0)) - 1 = 0 +"""); } - public override Task Byte_array_of_type_varbinary_max_filter_by_index_of_with_starting_position_parameter_casts_to_int(bool async) + public override async Task Byte_array_with_length_n_filter_by_index_of_literal(bool async) { - return Task.CompletedTask; - } + await base.Byte_array_with_length_n_filter_by_index_of_literal(async); - public override Task Byte_array_of_type_varbinary_n_filter_by_index_of_with_starting_position_literal_does_not_cast(bool async) - { - return Task.CompletedTask; + AssertSql( + """ +SELECT "s"."Id", "s"."Banner", "s"."Banner5", "s"."InternalNumber", "s"."Name" +FROM "Squads" AS "s" +WHERE instr("s"."Banner5", X'05') - 1 = 1 +"""); } - public override Task Byte_array_of_type_varbinary_n_filter_by_index_of_with_starting_position_parameter_does_not_cast(bool async) + public override async Task Byte_array_with_lenght_n_filter_by_index_of_parameter(bool async) { - return Task.CompletedTask; + await base.Byte_array_with_lenght_n_filter_by_index_of_parameter(async); + + AssertSql( + """ +@__b_0='4' + +SELECT "s"."Id", "s"."Banner", "s"."Banner5", "s"."InternalNumber", "s"."Name" +FROM "Squads" AS "s" +WHERE instr("s"."Banner5", char(@__b_0)) - 1 = 0 +"""); } + public override Task Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position(bool async) + => AssertTranslationFailed(() => base.Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position(async)); + + public override Task Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position_parameter(bool async) + => AssertTranslationFailed(() => base.Byte_array_with_max_possible_length_filter_by_index_of_with_starting_position_parameter(async)); + + public override Task Byte_array_with_length_n_filter_by_index_of_with_starting_position_literal(bool async) + => AssertTranslationFailed(() => base.Byte_array_with_length_n_filter_by_index_of_with_starting_position_literal(async)); + + public override Task Byte_array_with_length_n_filter_by_index_of_with_starting_position_parameter(bool async) + => AssertTranslationFailed(() => base.Byte_array_with_length_n_filter_by_index_of_with_starting_position_parameter(async)); + #endregion public override Task Where_TimeSpan_Hours(bool async)