diff --git a/Directory.Packages.props b/Directory.Packages.props index 662be990703..c04cc84129e 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -36,7 +36,7 @@ - + diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.InExpressionValuesExpandingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.InExpressionValuesExpandingExpressionVisitor.cs index e23cb211fe9..a3cdfa86608 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.InExpressionValuesExpandingExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.InExpressionValuesExpandingExpressionVisitor.cs @@ -10,7 +10,10 @@ namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal; public partial class CosmosShapedQueryCompilingExpressionVisitor { private static readonly bool UseOldBehavior35476 = - AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue35476", out var enabled35476) && enabled35476; + AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue35476", out var enabled35476) && enabled35476; + + private static readonly bool UseOldBehavior35983 = + AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue35983", out var enabled35983) && enabled35983; private sealed class ParameterInliner( ISqlExpressionFactory sqlExpressionFactory, @@ -85,7 +88,7 @@ protected override Expression VisitExtension(Expression expression) return base.VisitExtension(expression); } - // Inlines array parameter of full-text functions, transforming FullTextContainsAll(x, @keywordsArray) to FullTextContainsAll(x, keyword1, keyword2)) + // Inlines array parameter of full-text functions, transforming FullTextContainsAll(x, @keywordsArray) to FullTextContainsAll(x, keyword1, keyword2) case SqlFunctionExpression { Name: "FullTextContainsAny" or "FullTextContainsAll", @@ -106,14 +109,38 @@ protected override Expression VisitExtension(Expression expression) fullTextContainsAllAnyFunction.TypeMapping); } - // Inlines array parameter of full-text score, transforming FullTextScore(x, @keywordsArray) to FullTextScore(x, [keyword1, keyword2])) + // Inlines array parameter of full-text score, transforming FullTextScore(x, @keywordsArray) to FullTextScore(x, keyword1, keyword2) + case SqlFunctionExpression + { + Name: "FullTextScore", + IsScoringFunction: true, + Arguments: [var property, SqlParameterExpression { TypeMapping: { ElementTypeMapping: var elementTypeMapping }, Type: Type type } keywords] + } fullTextScoreFunction + when !UseOldBehavior35476 && !UseOldBehavior35983 && type == typeof(string[]): + { + var keywordValues = new List(); + foreach (var value in (IEnumerable)parametersValues[keywords.Name]) + { + keywordValues.Add(sqlExpressionFactory.Constant(value, typeof(string), elementTypeMapping)); + } + + return new SqlFunctionExpression( + fullTextScoreFunction.Name, + isScoringFunction: true, + [property, .. keywordValues], + fullTextScoreFunction.Type, + fullTextScoreFunction.TypeMapping); + } + + // Legacy path for #35983 + // Inlines array parameter of full-text score, transforming FullTextScore(x, @keywordsArray) to FullTextScore(x, [keyword1, keyword2]) case SqlFunctionExpression { Name: "FullTextScore", IsScoringFunction: true, Arguments: [var property, SqlParameterExpression { TypeMapping: { ElementTypeMapping: not null } typeMapping } keywords] } fullTextScoreFunction - when !UseOldBehavior35476: + when !UseOldBehavior35476 && UseOldBehavior35983: { var keywordValues = new List(); foreach (var value in (IEnumerable)parametersValues[keywords.Name]) diff --git a/src/EFCore.Cosmos/Query/Internal/Translators/CosmosFullTextSearchTranslator.cs b/src/EFCore.Cosmos/Query/Internal/Translators/CosmosFullTextSearchTranslator.cs index 11c4209100e..db9995c074e 100644 --- a/src/EFCore.Cosmos/Query/Internal/Translators/CosmosFullTextSearchTranslator.cs +++ b/src/EFCore.Cosmos/Query/Internal/Translators/CosmosFullTextSearchTranslator.cs @@ -15,7 +15,10 @@ public class CosmosFullTextSearchTranslator(ISqlExpressionFactory sqlExpressionF : IMethodCallTranslator { private static readonly bool UseOldBehavior35476 = - AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue35476", out var enabled35476) && enabled35476; + AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue35476", out var enabled35476) && enabled35476; + + private static readonly bool UseOldBehavior35983 = + AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue35983", out var enabled35983) && enabled35983; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -47,13 +50,36 @@ public class CosmosFullTextSearchTranslator(ISqlExpressionFactory sqlExpressionF typeMappingSource.FindMapping(typeof(bool))), nameof(CosmosDbFunctionsExtensions.FullTextScore) - when arguments is [_, var property, var keywords] => BuildScoringFunction( + when !UseOldBehavior35983 && arguments is [_, SqlExpression property, SqlConstantExpression { Type: var keywordClrType, Value: string[] values } keywords] + && keywordClrType == typeof(string[]) => BuildScoringFunction( + sqlExpressionFactory, + "FullTextScore", + [property, .. values.Select(x => sqlExpressionFactory.Constant(x))], + typeof(double), + typeMappingSource.FindMapping(typeof(double))), + + nameof(CosmosDbFunctionsExtensions.FullTextScore) + when !UseOldBehavior35983 && arguments is [_, SqlExpression property, SqlParameterExpression { Type: var keywordClrType } keywords] + && keywordClrType == typeof(string[]) => BuildScoringFunction( + sqlExpressionFactory, + "FullTextScore", + [property, keywords], + typeof(double), + typeMappingSource.FindMapping(typeof(double))), + + nameof(CosmosDbFunctionsExtensions.FullTextScore) + when !UseOldBehavior35983 && arguments is [_, SqlExpression property, ArrayConstantExpression keywords] => BuildScoringFunction( sqlExpressionFactory, "FullTextScore", - [ - property, - keywords, - ], + [property, .. keywords.Items], + typeof(double), + typeMappingSource.FindMapping(typeof(double))), + + nameof(CosmosDbFunctionsExtensions.FullTextScore) + when UseOldBehavior35983 && arguments is [_, var property, var keywords] => BuildScoringFunction( + sqlExpressionFactory, + "FullTextScore", + [property, keywords], typeof(double), typeMappingSource.FindMapping(typeof(double))),