Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
13 changes: 7 additions & 6 deletions src/Microsoft.OData.Core/UriParser/Binders/InBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -274,9 +274,9 @@ private static int ProcessDoubleQuotedStringItem(int start, string input, String
// If prev and next are both double quotes, then it's an empty string.
if (input[k - 1] == '"')
{
// We append \"\" so as to return "\"\"" instead of "".
// This is to avoid passing an empty string to the ConstantNode.
sb.Append("\\\"\\\"");
// Here, we meet an empty string as "", we should do nothing here becase at the beginning appends a double quote, and at the end appends another double quote.
// So, don't do the following appending.
// sb.Append("\\\"\\\"");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you plan to remove this condition altogether

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I want to keep them intentionally for future awareness.

}
break;
}
Expand Down Expand Up @@ -334,9 +334,10 @@ private static int ProcessSingleQuotedStringItem(int start, string input, String
sb.Append('"');
return k;
}
// We append \"\" so as to return "\"\"" instead of "".
// This is to avoid passing an empty string to the ConstantNode.
sb.Append("\\\"\\\"");

// Here, we meet an empty string as '', we should do nothing here becase at the beginning appends a double quote, and at the end appends another double quote.
// So, don't do the following appending.
// sb.Append("\\\"\\\"");
}
// match with single quote ('), stop it.
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ namespace Microsoft.OData.UriParser

/// <summary>
/// Node representing a constant value, can either be primitive, complex, entity, or collection value.
/// Be noted:
/// If an 'in' clause, for example: $filter=name in ('abc', ''), since the InBinder converts the literal to ["abc", ""], in this case, the literal for second item is an empty string.
/// In all other cases, for example: $filter=name eq '', the literal for this node is "''", it's not an empty string.
/// </summary>
public sealed class ConstantNode : SingleValueNode
{
Expand All @@ -37,7 +40,8 @@ public sealed class ConstantNode : SingleValueNode
public ConstantNode(object constantValue, string literalText)
: this(constantValue)
{
ExceptionUtils.CheckArgumentStringNotNullOrEmpty(literalText, "literalText");
ExceptionUtils.CheckArgumentNotNull(literalText, "literalText");

this.LiteralText = literalText;
}

Expand All @@ -50,7 +54,7 @@ public ConstantNode(object constantValue, string literalText)
/// <exception cref="System.ArgumentNullException">Throws if the input literalText is null.</exception>
public ConstantNode(object constantValue, string literalText, IEdmTypeReference typeReference)
{
ExceptionUtils.CheckArgumentStringNotNullOrEmpty(literalText, "literalText");
ExceptionUtils.CheckArgumentNotNull(literalText, "literalText");

this.constantValue = constantValue;
this.LiteralText = literalText;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3114,7 +3114,11 @@ public void FilterWithInOperationWithEmptyString(string filterClause)
Assert.Equal(1, collectionNode.Collection.Count);

ConstantNode constantNode = collectionNode.Collection.First();
Assert.Equal("\"\"", constantNode.LiteralText);
Assert.Equal(string.Empty, constantNode.Value);

// Since in the 'in' clause, the item string is normalized as plain JSON (using [] instead of ()), and the string item has changed from '' to "".
// Thefore, the LiteralText is expected to be string.Empty.
Assert.Equal(string.Empty, constantNode.LiteralText);
}

[Theory]
Expand All @@ -3132,7 +3136,27 @@ public void FilterWithInOperationWithEmptyStringInSquareBrackets(string filterCl
Assert.Equal(1, collectionNode.Collection.Count);

ConstantNode constantNode = collectionNode.Collection.First();
Assert.Equal("\"\"", constantNode.LiteralText);
Assert.Equal(string.Empty, constantNode.Value);
Assert.Equal(string.Empty, constantNode.LiteralText);
}

[Theory]
[InlineData("SSN in ('abc', null, '')", 0)] // at the end
[InlineData("SSN in ('', 'abc', null)", 1)] // at the start
[InlineData("SSN in (null, '', 'abc')", 2)] // in the middle
public void FilterWithInOperationWithEmptyStringWithOthersShouldWork(string inLiteral, int index)
{
FilterClause filter = ParseFilter(inLiteral, HardCodedTestModel.TestModel, HardCodedTestModel.GetPersonType());

var inNode = Assert.IsType<InNode>(filter.Expression);
Assert.Equal("SSN", Assert.IsType<SingleValuePropertyAccessNode>(inNode.Left).Property.Name);

CollectionConstantNode collectionNode = Assert.IsType<CollectionConstantNode>(inNode.Right);
Assert.Equal(3, collectionNode.Collection.Count);

collectionNode.Collection.ElementAt((index + 0) % 3).ShouldBeConstantQueryNode("abc");
collectionNode.Collection.ElementAt((index + 1) % 3).ShouldBeConstantQueryNode<string>(null);
collectionNode.Collection.ElementAt((index + 2) % 3).ShouldBeConstantQueryNode("");
}

[Theory]
Expand Down