Skip to content

Commit

Permalink
Support any expression type inside inline primitive collections (#31046)
Browse files Browse the repository at this point in the history
  • Loading branch information
roji authored Jun 13, 2023
1 parent e846c0c commit 7d3e715
Show file tree
Hide file tree
Showing 50 changed files with 1,724 additions and 776 deletions.
22 changes: 22 additions & 0 deletions src/EFCore.Cosmos/Properties/CosmosStrings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions src/EFCore.Cosmos/Properties/CosmosStrings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@
<data name="CanConnectNotSupported" xml:space="preserve">
<value>The Cosmos database does not support 'CanConnect' or 'CanConnectAsync'.</value>
</data>
<data name="CannotTranslateNonConstantNewArrayExpression" xml:space="preserve">
<value>The query contained a new array expression containing non-constant elements, which could not be translated: '{newArrayExpression}'.</value>
</data>
<data name="ConnectionStringConflictingConfiguration" xml:space="preserve">
<value>Both the connection string and CredentialToken, account key or account endpoint were specified. Specify only one set of connection details.</value>
</data>
Expand Down Expand Up @@ -226,6 +229,12 @@
<data name="OffsetRequiresLimit" xml:space="preserve">
<value>Cosmos SQL does not allow Offset without Limit. Consider specifying a 'Take' operation on the query.</value>
</data>
<data name="OneOfTwoValuesMustBeSet" xml:space="preserve">
<value>Exactly one of '{param1}' or '{param2}' must be set.</value>
</data>
<data name="OnlyConstantsAndParametersAllowedInContains" xml:space="preserve">
<value>Only constants or parameters are currently allowed in Contains.</value>
</data>
<data name="OrphanedNestedDocument" xml:space="preserve">
<value>The entity of type '{entityType}' is mapped as a part of the document mapped to '{missingEntityType}', but there is no tracked entity of this type with the corresponding key value. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the key values.</value>
</data>
Expand Down
59 changes: 0 additions & 59 deletions src/EFCore.Cosmos/Query/Internal/CosmosContainsTranslator.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ public CosmosMethodCallTranslatorProvider(
{
new CosmosEqualsTranslator(sqlExpressionFactory),
new CosmosStringMethodTranslator(sqlExpressionFactory),
new CosmosContainsTranslator(sqlExpressionFactory),
new CosmosRandomTranslator(sqlExpressionFactory),
new CosmosMathTranslator(sqlExpressionFactory),
new CosmosRegexTranslator(sqlExpressionFactory)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#nullable disable

using System.Collections;
using Microsoft.EntityFrameworkCore.Cosmos.Internal;

namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal;

Expand All @@ -26,51 +27,56 @@ public override Expression Visit(Expression expression)
{
if (expression is InExpression inExpression)
{
var inValues = new List<object>();
var inValues = new List<SqlExpression>();
var hasNullValue = false;
CoreTypeMapping typeMapping = null;

switch (inExpression.Values)
switch (inExpression)
{
case SqlConstantExpression sqlConstant:
case { ValuesParameter: SqlParameterExpression valuesParameter }:
{
typeMapping = sqlConstant.TypeMapping;
var values = (IEnumerable)sqlConstant.Value;
foreach (var value in values)
var typeMapping = valuesParameter.TypeMapping;

foreach (var value in (IEnumerable)_parametersValues[valuesParameter.Name])
{
if (value == null)
if (value is null)
{
hasNullValue = true;
continue;
}

inValues.Add(value);
inValues.Add(_sqlExpressionFactory.Constant(value, typeMapping));
}
}

break;
}

case SqlParameterExpression sqlParameter:
case { Values: IReadOnlyList<SqlExpression> values }:
{
typeMapping = sqlParameter.TypeMapping;
var values = (IEnumerable)_parametersValues[sqlParameter.Name];
foreach (var value in values)
{
if (value == null)
if (value is not (SqlConstantExpression or SqlParameterExpression))
{
throw new InvalidOperationException(CosmosStrings.OnlyConstantsAndParametersAllowedInContains);
}

if (IsNull(value))
{
hasNullValue = true;
continue;
}

inValues.Add(value);
}
}

break;
}

default:
throw new InvalidOperationException("IMPOSSIBLE");
}

var updatedInExpression = inValues.Count > 0
? _sqlExpressionFactory.In(
(SqlExpression)Visit(inExpression.Item),
_sqlExpressionFactory.Constant(inValues, typeMapping))
? _sqlExpressionFactory.In((SqlExpression)Visit(inExpression.Item), inValues)
: null;

var nullCheckExpression = hasNullValue
Expand All @@ -94,5 +100,9 @@ public override Expression Visit(Expression expression)

return base.Visit(expression);
}

private bool IsNull(SqlExpression expression)
=> expression is SqlConstantExpression { Value: null }
|| expression is SqlParameterExpression { Name: string parameterName } && _parametersValues[parameterName] is null;
}
}
Loading

0 comments on commit 7d3e715

Please sign in to comment.