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
15 changes: 3 additions & 12 deletions QueryKit.UnitTests/FilterParsingRegressionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,12 @@ public void decimal_value_uses_invariant_culture(string cultureName)
[Theory]
[InlineData("de-DE")]
[InlineData("fr-FR")]
public void decimal_value_with_culture_decimal_comma_is_read_as_before(string cultureName)
{
var input = """Rating > 4,5""";

var filterExpression = WithCulture(cultureName, () => FilterParser.ParseFilter<TestingPerson>(input));

filterExpression.ToDisplayString().Should().Be("x => (x.Rating > 45)");
}

[Fact]
public void decimal_value_with_decimal_comma_is_not_accepted_in_a_culture_with_decimal_point()
[InlineData("en-US")]
public void decimal_value_with_decimal_comma_is_not_accepted(string cultureName)
{
var input = """Rating > 4,5""";

var act = () => WithCulture("en-US", () => FilterParser.ParseFilter<TestingPerson>(input));
var act = () => WithCulture(cultureName, () => FilterParser.ParseFilter<TestingPerson>(input));

act.Should().Throw<QueryKitException>();
}
Expand Down
25 changes: 4 additions & 21 deletions QueryKit/FilterParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,24 +206,8 @@ from micros in DateTimeMicrosParser
from timeZone in DateTimeZoneParser
select dateFormat + timeFormat + micros + timeZone;

// A number with a '.' decimal point, or with the decimal separator of the current culture.
// The longer match wins, so '4.5' parses in every culture and '4,5' still parses in a culture that uses ','.
private static readonly Parser<string> UnsignedNumberParser = input =>
{
var invariant = Parse.DecimalInvariant(input);
var culture = Parse.Decimal(input);
return culture.WasSuccessful && (!invariant.WasSuccessful || culture.Remainder.Position > invariant.Remainder.Position)
? culture
: invariant;
};

// A number always uses the '.' decimal point, so a filter has the same meaning in every culture.
private static readonly Parser<string> NumberParser =
from sign in Parse.Char('-').Optional().Select(x => x.IsDefined ? "-" : "")
from number in UnsignedNumberParser
select sign + number;

// List items are separated by ',', so a list number always uses the '.' decimal point.
private static readonly Parser<string> ListNumberParser =
from sign in Parse.Char('-').Optional().Select(x => x.IsDefined ? "-" : "")
from number in Parse.DecimalInvariant
select sign + number;
Expand All @@ -247,7 +231,7 @@ from closingQuotes in Parse.Char('"').Repeat(count).Text()
.Or(GuidFormatParser)
.Or(DateTimeFormatParser)
.Or(TimeFormatParser)
.Or(ListNumberParser)
.Or(NumberParser)
.Or(RawStringLiteralParser.Or(DoubleQuoteParser))
.Or(Identifier)
.DelimitedBy(Parse.Char(',').Token());
Expand Down Expand Up @@ -472,7 +456,7 @@ private static Expression CreateRightExprFromType(Type leftExprType, string righ
var targetType = leftExprType;
if (isEnumerable)
{
if (op.IsCountOperator() && (int.TryParse(right, out var intVal) || int.TryParse(right, NumberStyles.Integer, CultureInfo.InvariantCulture, out intVal)))
if (op.IsCountOperator() && int.TryParse(right, NumberStyles.Integer, CultureInfo.InvariantCulture, out var intVal))
{
return FilterValue.Parameter(intVal, typeof(int));
}
Expand Down Expand Up @@ -1365,8 +1349,7 @@ private static bool IsPropertyPath(string value, Type entityType)
if (value == "null" ||
value.StartsWith("\"") ||
value.StartsWith("[") ||
value.Contains("-") && (DateTime.TryParse(value, out _) || DateTime.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out _)) ||
decimal.TryParse(value, out _) ||
value.Contains("-") && DateTime.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.None, out _) ||
decimal.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out _) ||
bool.TryParse(value, out _) ||
Guid.TryParse(value, out _))
Expand Down
Loading