Skip to content

Commit c568673

Browse files
committed
Fix to #35983 - Cosmos/FTS: update translation of FullTextScore to use multiple keywords rather than keyword array
Port of #35984 Fixes #35983 Description Reacting to Cosmos changing the signature of FullTextScore function. Customer impact TBD How found Partner team ask. Regression No Testing Extensively tested on EF 10, manual testing on EF9. End-to-end testing is not possible because we can't create containers programmatically (no support for it inside EF Core itself, and the Cosmos SDK which supports it is currently only available in beta, so we can't take dependency on it). Instead, we created containers and data using EF 10, ported all the query tests from EF 10 and ran them using the EF9 bits. Partner team will conduct additional testing on their end. Risk Low. Localized change to translation - method signature exposed by EF is already in place. New translation now resembles other FullText methods, so same techniques can be used for translation (essentially re-using code that has been in place for other methods and working). Full text search support is experimental on EF9. Added quirk just in case.
1 parent 1c96bce commit c568673

File tree

4 files changed

+66
-11
lines changed

4 files changed

+66
-11
lines changed

Directory.Packages.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
<PackageVersion Include="Microsoft.DotNet.Build.Tasks.Templating" Version="$(MicrosoftDotNetBuildTasksTemplatingVersion)" />
3737

3838
<!-- Azure SDK for .NET dependencies -->
39-
<PackageVersion Include="Microsoft.Azure.Cosmos" Version="3.45.2" />
39+
<PackageVersion Include="Microsoft.Azure.Cosmos" Version="3.49.0" />
4040

4141
<!-- SQL Server dependencies -->
4242
<PackageVersion Include="Microsoft.Data.SqlClient" Version="5.1.6" />

src/EFCore.Cosmos/EFCore.Cosmos.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@
5050

5151
<ItemGroup>
5252
<PackageReference Include="Microsoft.Azure.Cosmos" />
53+
<!-- Microsoft.Azure.Cosmos requires explicit reference to Newtonsoft.Json >= 10.0.2 -->
54+
<PackageReference Include="Newtonsoft.Json" />
5355
</ItemGroup>
5456

5557
<ItemGroup>

src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.InExpressionValuesExpandingExpressionVisitor.cs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal;
1010
public partial class CosmosShapedQueryCompilingExpressionVisitor
1111
{
1212
private static readonly bool UseOldBehavior35476 =
13-
AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue35476", out var enabled35476) && enabled35476;
13+
AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue35476", out var enabled35476) && enabled35476;
14+
15+
private static readonly bool UseOldBehavior35983 =
16+
AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue35983", out var enabled35983) && enabled35983;
1417

1518
private sealed class ParameterInliner(
1619
ISqlExpressionFactory sqlExpressionFactory,
@@ -85,7 +88,7 @@ protected override Expression VisitExtension(Expression expression)
8588
return base.VisitExtension(expression);
8689
}
8790

88-
// Inlines array parameter of full-text functions, transforming FullTextContainsAll(x, @keywordsArray) to FullTextContainsAll(x, keyword1, keyword2))
91+
// Inlines array parameter of full-text functions, transforming FullTextContainsAll(x, @keywordsArray) to FullTextContainsAll(x, keyword1, keyword2)
8992
case SqlFunctionExpression
9093
{
9194
Name: "FullTextContainsAny" or "FullTextContainsAll",
@@ -106,14 +109,38 @@ protected override Expression VisitExtension(Expression expression)
106109
fullTextContainsAllAnyFunction.TypeMapping);
107110
}
108111

109-
// Inlines array parameter of full-text score, transforming FullTextScore(x, @keywordsArray) to FullTextScore(x, [keyword1, keyword2]))
112+
// Inlines array parameter of full-text score, transforming FullTextScore(x, @keywordsArray) to FullTextScore(x, keyword1, keyword2)
113+
case SqlFunctionExpression
114+
{
115+
Name: "FullTextScore",
116+
IsScoringFunction: true,
117+
Arguments: [var property, SqlParameterExpression { TypeMapping: { ElementTypeMapping: var elementTypeMapping }, Type: Type type } keywords]
118+
} fullTextScoreFunction
119+
when !UseOldBehavior35476 && !UseOldBehavior35983 && type == typeof(string[]):
120+
{
121+
var keywordValues = new List<SqlExpression>();
122+
foreach (var value in (IEnumerable)parametersValues[keywords.Name])
123+
{
124+
keywordValues.Add(sqlExpressionFactory.Constant(value, typeof(string), elementTypeMapping));
125+
}
126+
127+
return new SqlFunctionExpression(
128+
fullTextScoreFunction.Name,
129+
isScoringFunction: true,
130+
[property, .. keywordValues],
131+
fullTextScoreFunction.Type,
132+
fullTextScoreFunction.TypeMapping);
133+
}
134+
135+
// Legacy path for #35983
136+
// Inlines array parameter of full-text score, transforming FullTextScore(x, @keywordsArray) to FullTextScore(x, [keyword1, keyword2])
110137
case SqlFunctionExpression
111138
{
112139
Name: "FullTextScore",
113140
IsScoringFunction: true,
114141
Arguments: [var property, SqlParameterExpression { TypeMapping: { ElementTypeMapping: not null } typeMapping } keywords]
115142
} fullTextScoreFunction
116-
when !UseOldBehavior35476:
143+
when !UseOldBehavior35476 && UseOldBehavior35983:
117144
{
118145
var keywordValues = new List<string>();
119146
foreach (var value in (IEnumerable)parametersValues[keywords.Name])

src/EFCore.Cosmos/Query/Internal/Translators/CosmosFullTextSearchTranslator.cs

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ public class CosmosFullTextSearchTranslator(ISqlExpressionFactory sqlExpressionF
1515
: IMethodCallTranslator
1616
{
1717
private static readonly bool UseOldBehavior35476 =
18-
AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue35476", out var enabled35476) && enabled35476;
18+
AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue35476", out var enabled35476) && enabled35476;
19+
20+
private static readonly bool UseOldBehavior35983 =
21+
AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue35983", out var enabled35983) && enabled35983;
1922

2023
/// <summary>
2124
/// 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
4750
typeMappingSource.FindMapping(typeof(bool))),
4851

4952
nameof(CosmosDbFunctionsExtensions.FullTextScore)
50-
when arguments is [_, var property, var keywords] => BuildScoringFunction(
53+
when !UseOldBehavior35983 && arguments is [_, SqlExpression property, SqlConstantExpression { Type: var keywordClrType, Value: string[] values } keywords]
54+
&& keywordClrType == typeof(string[]) => BuildScoringFunction(
55+
sqlExpressionFactory,
56+
"FullTextScore",
57+
[property, .. values.Select(x => sqlExpressionFactory.Constant(x))],
58+
typeof(double),
59+
typeMappingSource.FindMapping(typeof(double))),
60+
61+
nameof(CosmosDbFunctionsExtensions.FullTextScore)
62+
when !UseOldBehavior35983 && arguments is [_, SqlExpression property, SqlParameterExpression { Type: var keywordClrType } keywords]
63+
&& keywordClrType == typeof(string[]) => BuildScoringFunction(
64+
sqlExpressionFactory,
65+
"FullTextScore",
66+
[property, keywords],
67+
typeof(double),
68+
typeMappingSource.FindMapping(typeof(double))),
69+
70+
nameof(CosmosDbFunctionsExtensions.FullTextScore)
71+
when !UseOldBehavior35983 && arguments is [_, SqlExpression property, ArrayConstantExpression keywords] => BuildScoringFunction(
5172
sqlExpressionFactory,
5273
"FullTextScore",
53-
[
54-
property,
55-
keywords,
56-
],
74+
[property, .. keywords.Items],
75+
typeof(double),
76+
typeMappingSource.FindMapping(typeof(double))),
77+
78+
nameof(CosmosDbFunctionsExtensions.FullTextScore)
79+
when UseOldBehavior35983 && arguments is [_, var property, var keywords] => BuildScoringFunction(
80+
sqlExpressionFactory,
81+
"FullTextScore",
82+
[property, keywords],
5783
typeof(double),
5884
typeMappingSource.FindMapping(typeof(double))),
5985

0 commit comments

Comments
 (0)