Skip to content

Commit

Permalink
Merge pull request #425 from mk3008/421-experiment-typesafe-query-bui…
Browse files Browse the repository at this point in the history
…lder-unable-to-build-or-conditions-correctly

Fixed an issue where OR conditions were not grouped correctly.
  • Loading branch information
mk3008 authored May 27, 2024
2 parents 9181547 + 6c9875c commit 4dc7ffe
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 12 deletions.
8 changes: 5 additions & 3 deletions src/Carbunql.TypeSafe/Extensions/BinaryExpressionExtension.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Carbunql.Analysis.Parser;
using Carbunql.Extensions;
using System.Linq.Expressions;

namespace Carbunql.TypeSafe.Extensions;
Expand All @@ -24,11 +25,12 @@ private static string ToValue(ExpressionType nodeType, string left, string right
// Enclose expressions in parentheses based on operator precedence or specific conditions
if (nodeType == ExpressionType.OrElse)
{
if (leftValue.GetOperators().Any())
// If an AND condition exists, enclose the whole in parentheses.
if (leftValue.GetOperators().Where(x => x.IsEqualNoCase("and")).Any())
{
left = $"({left})";
}
if (rightValue.GetOperators().Any())
if (rightValue.GetOperators().Where(x => x.IsEqualNoCase("and")).Any())
{
right = $"({right})";
}
Expand Down Expand Up @@ -61,7 +63,7 @@ private static string ToValue(ExpressionType nodeType, string left, string right
ExpressionType.LessThan => $"{left} < {right}",
ExpressionType.LessThanOrEqual => $"{left} <= {right}",
ExpressionType.AndAlso => $"{left} and {right}",
ExpressionType.OrElse => $"{left} or {right}",
ExpressionType.OrElse => $"({left} or {right})",
_ => throw new NotSupportedException($"Unsupported expression type: {nodeType}")
};
}
Expand Down
10 changes: 2 additions & 8 deletions src/Carbunql.TypeSafe/FluentSelectQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,14 +120,8 @@ public FluentSelectQuery Where(Expression<Func<bool>> expression)

var value = ToValue(expression.Body, prmManager.AddParaemter);

if (expression.Body is BinaryExpression be && be.NodeType == ExpressionType.OrElse)
{
this.Where($"({value})");
}
else
{
this.Where(value);
}
this.Where(value);

return this;
}

Expand Down
29 changes: 28 additions & 1 deletion test/Carbunql.TypeSafe.Test/WhereTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,34 @@ public void OrTest()
FROM
sale AS a
WHERE
((a.quantity = 1) OR (a.unit_price = 2))";
(a.quantity = 1 OR a.unit_price = 2)";

Assert.Equal(expect, actual, true, true, true);
}

[Fact]
public void AndOrTest()
{
var a = Sql.DefineDataSet<sale>();

var query = Sql.From(() => a)
.Where(() =>
(a.quantity == 1 && a.unit_price == 1 || a.unit_price == 2)
&& (a.unit_price == 2 || a.quantity == 1 && a.unit_price == 1)
&& (a.unit_price == 1 || a.unit_price == 2)
);

var actual = query.ToText();
Output.WriteLine(query.ToText());

var expect = @"SELECT
*
FROM
sale AS a
WHERE
((a.quantity = 1 AND a.unit_price = 1) OR a.unit_price = 2)
AND (a.unit_price = 2 OR (a.quantity = 1 AND a.unit_price = 1))
AND (a.unit_price = 1 OR a.unit_price = 2)";

Assert.Equal(expect, actual, true, true, true);
}
Expand Down

0 comments on commit 4dc7ffe

Please sign in to comment.