Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Query : Adds string comparison alternative when converting LINQ to SQL #3668

Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c983055
string.Compare supported with LINQ to SQL
ernesto1596 Jan 27, 2023
9b944ac
Merge branch 'master' into ernestoc/stringCompareTo
ernesto1596 Feb 8, 2023
2d3d232
Merge branch 'master' into ernestoc/stringCompareTo
ernesto1596 Jun 13, 2023
8412d2a
Merge branch 'master' into ernestoc/stringCompareTo
ernesto1596 Jun 14, 2023
e25b814
Update tests
ernesto1596 Jun 14, 2023
3ae9b0e
Update test name
ernesto1596 Jun 14, 2023
8236ec2
Update tests
ernesto1596 Jun 14, 2023
1fd3fba
Add test
ernesto1596 Jun 14, 2023
8db7c5c
Merge branch 'master' into ernestoc/stringCompareTo
ernesto1596 Jun 14, 2023
2ec00e5
Create helper ReverseExpressionTypeForStrings
ernesto1596 Jun 14, 2023
fd56903
Merge branch 'master' into ernestoc/stringCompareTo
ernesto1596 Jun 15, 2023
890ac4e
Merge branch 'master' into ernestoc/stringCompareTo
ernesto1596 Jun 21, 2023
26988c7
Merge branch 'master' into ernestoc/stringCompareTo
ernesto1596 Jun 23, 2023
eca95b6
Merge branch 'master' into ernestoc/stringCompareTo
ernesto1596 Jul 6, 2023
c0d5805
Merge branch 'master' into ernestoc/stringCompareTo
adityasa Jul 7, 2023
60f933d
Merge branch 'master' into ernestoc/stringCompareTo
adityasa Jul 8, 2023
36a8f3d
PR feedback
ernesto1596 Jul 10, 2023
e155b8f
Merge branch 'master' into ernestoc/stringCompareTo
ernesto1596 Jul 10, 2023
ddd2498
Merge branch 'master' into ernestoc/stringCompareTo
ernesto1596 Jul 10, 2023
4b25820
Update tests
ernesto1596 Jul 10, 2023
b3e3620
Update base line
ernesto1596 Jul 10, 2023
6ef4f90
Merge branch 'master' into ernestoc/stringCompareTo
ealsur Jul 11, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions Microsoft.Azure.Cosmos/src/ClientResources.Designer.cs

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

6 changes: 6 additions & 0 deletions Microsoft.Azure.Cosmos/src/ClientResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -270,9 +270,15 @@
<data name="StringCompareToInvalidConstant" xml:space="preserve">
<value>The right hand side of string.CompareTo() comparison must be constant '0'</value>
</data>
<data name="StringCompareInvalidConstant" xml:space="preserve">
<value>The right hand side of string.Compare() comparison must be constant '0'</value>
ernesto1596 marked this conversation as resolved.
Show resolved Hide resolved
</data>
<data name="StringCompareToInvalidOperator" xml:space="preserve">
<value>Invalid operator for string.CompareTo(). Vaid operators are ('==', '&lt;', '&lt;=', '&gt;' or '&gt;=')</value>
</data>
<data name="StringCompareInvalidOperator" xml:space="preserve">
<value>Invalid operator for string.Compare(). Vaid operators are ('==', '&lt;', '&lt;=', '&gt;' or '&gt;=')</value>
</data>
<data name="TokenRefreshInProgress" xml:space="preserve">
<value>Token refresh in progress.</value>
</data>
Expand Down
86 changes: 74 additions & 12 deletions Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,10 @@ private static SqlScalarExpression VisitBinary(BinaryExpression inputExpression,
{
return ExpressionToSql.VisitStringCompareTo(methodCallExpression, constantExpression, inputExpression.NodeType, reverseNodeType, context);
}
if (TryMatchStringCompare(methodCallExpression, constantExpression, inputExpression.NodeType))
{
ernesto1596 marked this conversation as resolved.
Show resolved Hide resolved
return ExpressionToSql.VisitStringCompare(methodCallExpression, constantExpression, inputExpression.NodeType, reverseNodeType, context);
}
}

SqlScalarExpression left = ExpressionToSql.VisitScalarExpression(inputExpression.Left, context);
Expand Down Expand Up @@ -615,32 +619,90 @@ private static SqlScalarExpression VisitStringCompareTo(
{
if (reverseNodeType)
{
compareOperator = ReverseExpressionTypeForStrings(compareOperator, ClientResources.StringCompareToInvalidOperator);
}

SqlBinaryScalarOperatorKind op = GetBinaryOperatorKind(compareOperator, null);

SqlScalarExpression leftExpression = ExpressionToSql.VisitNonSubqueryScalarExpression(left.Object, context);
SqlScalarExpression rightExpression = ExpressionToSql.VisitNonSubqueryScalarExpression(left.Arguments[0], context);

return SqlBinaryScalarExpression.Create(op, leftExpression, rightExpression);
}

private static ExpressionType ReverseExpressionTypeForStrings(ExpressionType compareOperator, string errorMessage)
{
switch (compareOperator)
{
case ExpressionType.Equal:
// do nothing
break;
case ExpressionType.GreaterThan:
compareOperator = ExpressionType.LessThan;
break;
case ExpressionType.GreaterThanOrEqual:
compareOperator = ExpressionType.LessThanOrEqual;
break;
case ExpressionType.LessThan:
compareOperator = ExpressionType.GreaterThan;
break;
case ExpressionType.LessThanOrEqual:
compareOperator = ExpressionType.GreaterThanOrEqual;
break;
default:
throw new DocumentQueryException(string.Format(CultureInfo.CurrentCulture, errorMessage));
}

return compareOperator;
}

private static bool TryMatchStringCompare(MethodCallExpression left, ConstantExpression right, ExpressionType compareOperator)
{
if (left.Method.Equals(typeof(string).GetMethod("Compare", new Type[] { typeof(string), typeof(string) })) && left.Arguments.Count == 2)
{
// operator can only be =, >, >=, <, <=
switch (compareOperator)
{
case ExpressionType.Equal:
// do nothing
break;
case ExpressionType.GreaterThan:
compareOperator = ExpressionType.LessThan;
break;
case ExpressionType.GreaterThanOrEqual:
compareOperator = ExpressionType.LessThanOrEqual;
break;
case ExpressionType.LessThan:
compareOperator = ExpressionType.GreaterThan;
break;
case ExpressionType.LessThanOrEqual:
compareOperator = ExpressionType.GreaterThanOrEqual;
break;
default:
throw new DocumentQueryException(string.Format(CultureInfo.CurrentCulture, ClientResources.StringCompareToInvalidOperator));
throw new DocumentQueryException(string.Format(CultureInfo.CurrentCulture, ClientResources.StringCompareInvalidOperator));
}

// the constant value should be zero, otherwise we can't determine how to translate the expression
// it could be either integer or nullable integer
if (!(right.Type == typeof(int) && (int)right.Value == 0) &&
!(right.Type == typeof(int?) && ((int?)right.Value).HasValue && ((int?)right.Value).Value == 0))
{
ernesto1596 marked this conversation as resolved.
Show resolved Hide resolved
throw new DocumentQueryException(string.Format(CultureInfo.CurrentCulture, ClientResources.StringCompareInvalidConstant));
}

return true;
}

return false;
}

private static SqlScalarExpression VisitStringCompare(
MethodCallExpression left,
ConstantExpression right,
ExpressionType compareOperator,
bool reverseNodeType,
TranslationContext context)
{
if (reverseNodeType)
{
compareOperator = ReverseExpressionTypeForStrings(compareOperator, ClientResources.StringCompareInvalidOperator);
}

SqlBinaryScalarOperatorKind op = GetBinaryOperatorKind(compareOperator, null);

SqlScalarExpression leftExpression = ExpressionToSql.VisitNonSubqueryScalarExpression(left.Object, context);
SqlScalarExpression rightExpression = ExpressionToSql.VisitNonSubqueryScalarExpression(left.Arguments[0], context);
SqlScalarExpression leftExpression = ExpressionToSql.VisitNonSubqueryScalarExpression(left.Arguments[0], context);
SqlScalarExpression rightExpression = ExpressionToSql.VisitNonSubqueryScalarExpression(left.Arguments[1], context);

return SqlBinaryScalarExpression.Create(op, leftExpression, rightExpression);
}
Expand Down
Loading