Skip to content

Commit

Permalink
Translate 'case when X is null...' to 'coalesce(X,...)'.
Browse files Browse the repository at this point in the history
  • Loading branch information
bgurmendi authored and rwasef1830 committed Jun 1, 2018
1 parent c1cf255 commit 11f1cbd
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 0 deletions.
17 changes: 17 additions & 0 deletions src/EntityFramework6.Npgsql/SqlGenerators/SqlBaseGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,23 @@ protected string GetDbType(EdmType edmType)

public override VisitedExpression Visit([NotNull] DbCaseExpression expression)
{
// Check for COALESCE like CASE
if (expression.When.Count == 1 &&
expression.When[0].ExpressionKind == DbExpressionKind.IsNull)
{
var isNullExpression = (DbIsNullExpression)expression.When[0];
if (isNullExpression.Argument.Equals(expression.Else))
{
var coalesceExpression = new LiteralExpression("COALESCE(");
coalesceExpression.Append(expression.Else.Accept(this));
coalesceExpression.Append(",");
coalesceExpression.Append(expression.Then[0].Accept(this));
coalesceExpression.Append(")");
return coalesceExpression;
}
}

// General CASE
var caseExpression = new LiteralExpression(" CASE ");
for (var i = 0; i < expression.When.Count && i < expression.Then.Count; ++i)
{
Expand Down
75 changes: 75 additions & 0 deletions test/EntityFramework6.Npgsql.Tests/EntityFrameworkBasicTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
using System.Data.Entity.Core.Metadata.Edm;
using System.Data.Entity.Core.Objects;
using System.Data.Entity.Infrastructure;
using System.Diagnostics.CodeAnalysis;
using NpgsqlTypes;

namespace EntityFramework6.Npgsql.Tests
Expand Down Expand Up @@ -772,5 +773,79 @@ public void TestTableValuedStoredFunctions()
Assert.AreEqual(1, list2[0].Something);
}
}

[Test]
public void Test_string_type_inference_in_coalesce_statements()
{
using (var context = new BloggingContext(ConnectionString))
{
context.Database.Log = Console.Out.WriteLine;

context.Blogs.Add(new Blog { Name = "Hello" });
context.SaveChanges();

string stringValue = "string_value";
var query = context.Blogs.Select(b => stringValue + "_postfix");
var blogTitle = query.First();
Assert.That(blogTitle, Is.EqualTo("string_value_postfix"));
Console.WriteLine(query.ToString());
StringAssert.AreEqualIgnoringCase(
"SELECT COALESCE(@p__linq__0,E'') || E'_postfix' AS \"C1\" FROM \"dbo\".\"Blogs\" AS \"Extent1\"",
query.ToString());
}
}

[Test]
[SuppressMessage("ReSharper", "ConstantNullCoalescingCondition")]
public void Test_string_null_propagation()
{
using (var context = new BloggingContext(ConnectionString))
{
context.Database.Log = Console.Out.WriteLine;

context.Blogs.Add(new Blog { Name = "Hello" });
context.SaveChanges();

string stringValue = "string_value";
var query = context.Blogs.Select(b => (stringValue ?? "default_value") + "_postfix");
var blog_title = query.First();
Assert.That(blog_title, Is.EqualTo("string_value_postfix"));

Console.WriteLine(query.ToString());
StringAssert.AreEqualIgnoringCase(
"SELECT CASE WHEN (COALESCE(@p__linq__0,E'default_value') IS NULL) THEN (E'')"
+ " WHEN (@p__linq__0 IS NULL) THEN (E'default_value') ELSE (@p__linq__0) END ||"
+ " E'_postfix' AS \"C1\" FROM \"dbo\".\"Blogs\" AS \"Extent1\"",
query.ToString());
}
}

[Test]
[SuppressMessage("ReSharper", "ConstantNullCoalescingCondition")]
public void Test_string_multiple_null_propagation()
{
using (var context = new BloggingContext(ConnectionString))
{
context.Database.Log = Console.Out.WriteLine;

context.Blogs.Add(new Blog { Name = "Hello" });
context.SaveChanges();

string stringValue1 = "string_value1";
string stringValue2 = "string_value2";
string stringValue3 = "string_value3";

var query = context.Blogs.Select(b => (stringValue1 ?? stringValue2 ?? stringValue3) + "_postfix");
var blog_title = query.First();
Assert.That(blog_title, Is.EqualTo("string_value1_postfix"));

Console.WriteLine(query.ToString());
StringAssert.AreEqualIgnoringCase(
"SELECT CASE WHEN (COALESCE(@p__linq__0,COALESCE(@p__linq__1,@p__linq__2)) IS NULL)"
+ " THEN (E'') WHEN (@p__linq__0 IS NULL) THEN (COALESCE(@p__linq__1,@p__linq__2)) ELSE"
+ " (@p__linq__0) END || E'_postfix' AS \"C1\" FROM \"dbo\".\"Blogs\" AS \"Extent1\"",
query.ToString());
}
}
}
}

0 comments on commit 11f1cbd

Please sign in to comment.